1*a71a9546SAutomerger Merge Worker /*
2*a71a9546SAutomerger Merge Worker * Copyright (c) 2005 Evgeniy Polyakov <[email protected]>
3*a71a9546SAutomerger Merge Worker *
4*a71a9546SAutomerger Merge Worker *
5*a71a9546SAutomerger Merge Worker * This program is free software; you can redistribute it and/or modify
6*a71a9546SAutomerger Merge Worker * it under the terms of the GNU General Public License as published by
7*a71a9546SAutomerger Merge Worker * the Free Software Foundation; either version 2 of the License, or
8*a71a9546SAutomerger Merge Worker * (at your option) any later version.
9*a71a9546SAutomerger Merge Worker *
10*a71a9546SAutomerger Merge Worker * This program is distributed in the hope that it will be useful,
11*a71a9546SAutomerger Merge Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*a71a9546SAutomerger Merge Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*a71a9546SAutomerger Merge Worker * GNU General Public License for more details.
14*a71a9546SAutomerger Merge Worker *
15*a71a9546SAutomerger Merge Worker * You should have received a copy of the GNU General Public License
16*a71a9546SAutomerger Merge Worker * along with this program; if not, write to the Free Software
17*a71a9546SAutomerger Merge Worker * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18*a71a9546SAutomerger Merge Worker */
19*a71a9546SAutomerger Merge Worker
20*a71a9546SAutomerger Merge Worker #include <sys/types.h>
21*a71a9546SAutomerger Merge Worker #include <sys/socket.h>
22*a71a9546SAutomerger Merge Worker #include <sys/poll.h>
23*a71a9546SAutomerger Merge Worker #include <sys/time.h>
24*a71a9546SAutomerger Merge Worker
25*a71a9546SAutomerger Merge Worker #include <arpa/inet.h>
26*a71a9546SAutomerger Merge Worker
27*a71a9546SAutomerger Merge Worker #include <ctype.h>
28*a71a9546SAutomerger Merge Worker #include <errno.h>
29*a71a9546SAutomerger Merge Worker #include <stdio.h>
30*a71a9546SAutomerger Merge Worker #include <stdlib.h>
31*a71a9546SAutomerger Merge Worker #include <string.h>
32*a71a9546SAutomerger Merge Worker #include <stdarg.h>
33*a71a9546SAutomerger Merge Worker #include <time.h>
34*a71a9546SAutomerger Merge Worker #include <unistd.h>
35*a71a9546SAutomerger Merge Worker
36*a71a9546SAutomerger Merge Worker #include <netinet/ip.h>
37*a71a9546SAutomerger Merge Worker #include <netinet/tcp.h>
38*a71a9546SAutomerger Merge Worker
39*a71a9546SAutomerger Merge Worker #include <linux/connector.h>
40*a71a9546SAutomerger Merge Worker #include <linux/types.h>
41*a71a9546SAutomerger Merge Worker #include <linux/netlink.h>
42*a71a9546SAutomerger Merge Worker #include <linux/rtnetlink.h>
43*a71a9546SAutomerger Merge Worker #include <linux/unistd.h>
44*a71a9546SAutomerger Merge Worker
45*a71a9546SAutomerger Merge Worker #include <libnfnetlink/libnfnetlink.h>
46*a71a9546SAutomerger Merge Worker
47*a71a9546SAutomerger Merge Worker #include <linux/netfilter/nfnetlink.h>
48*a71a9546SAutomerger Merge Worker #include <linux/netfilter/xt_osf.h>
49*a71a9546SAutomerger Merge Worker
50*a71a9546SAutomerger Merge Worker #define OPTDEL ','
51*a71a9546SAutomerger Merge Worker #define OSFPDEL ':'
52*a71a9546SAutomerger Merge Worker #define MAXOPTSTRLEN 128
53*a71a9546SAutomerger Merge Worker
54*a71a9546SAutomerger Merge Worker #ifndef NIPQUAD
55*a71a9546SAutomerger Merge Worker #define NIPQUAD(addr) \
56*a71a9546SAutomerger Merge Worker ((unsigned char *)&addr)[0], \
57*a71a9546SAutomerger Merge Worker ((unsigned char *)&addr)[1], \
58*a71a9546SAutomerger Merge Worker ((unsigned char *)&addr)[2], \
59*a71a9546SAutomerger Merge Worker ((unsigned char *)&addr)[3]
60*a71a9546SAutomerger Merge Worker #endif
61*a71a9546SAutomerger Merge Worker
62*a71a9546SAutomerger Merge Worker static struct nfnl_handle *nfnlh;
63*a71a9546SAutomerger Merge Worker static struct nfnl_subsys_handle *nfnlssh;
64*a71a9546SAutomerger Merge Worker
65*a71a9546SAutomerger Merge Worker static struct xt_osf_opt IANA_opts[] = {
66*a71a9546SAutomerger Merge Worker { .kind = 0, .length = 1,},
67*a71a9546SAutomerger Merge Worker { .kind=1, .length=1,},
68*a71a9546SAutomerger Merge Worker { .kind=2, .length=4,},
69*a71a9546SAutomerger Merge Worker { .kind=3, .length=3,},
70*a71a9546SAutomerger Merge Worker { .kind=4, .length=2,},
71*a71a9546SAutomerger Merge Worker { .kind=5, .length=1,}, /* SACK length is not defined */
72*a71a9546SAutomerger Merge Worker { .kind=6, .length=6,},
73*a71a9546SAutomerger Merge Worker { .kind=7, .length=6,},
74*a71a9546SAutomerger Merge Worker { .kind=8, .length=10,},
75*a71a9546SAutomerger Merge Worker { .kind=9, .length=2,},
76*a71a9546SAutomerger Merge Worker { .kind=10, .length=3,},
77*a71a9546SAutomerger Merge Worker { .kind=11, .length=1,}, /* CC: Suppose 1 */
78*a71a9546SAutomerger Merge Worker { .kind=12, .length=1,}, /* the same */
79*a71a9546SAutomerger Merge Worker { .kind=13, .length=1,}, /* and here too */
80*a71a9546SAutomerger Merge Worker { .kind=14, .length=3,},
81*a71a9546SAutomerger Merge Worker { .kind=15, .length=1,}, /* TCP Alternate Checksum Data. Length is not defined */
82*a71a9546SAutomerger Merge Worker { .kind=16, .length=1,},
83*a71a9546SAutomerger Merge Worker { .kind=17, .length=1,},
84*a71a9546SAutomerger Merge Worker { .kind=18, .length=3,},
85*a71a9546SAutomerger Merge Worker { .kind=19, .length=18,},
86*a71a9546SAutomerger Merge Worker { .kind=20, .length=1,},
87*a71a9546SAutomerger Merge Worker { .kind=21, .length=1,},
88*a71a9546SAutomerger Merge Worker { .kind=22, .length=1,},
89*a71a9546SAutomerger Merge Worker { .kind=23, .length=1,},
90*a71a9546SAutomerger Merge Worker { .kind=24, .length=1,},
91*a71a9546SAutomerger Merge Worker { .kind=25, .length=1,},
92*a71a9546SAutomerger Merge Worker { .kind=26, .length=1,},
93*a71a9546SAutomerger Merge Worker };
94*a71a9546SAutomerger Merge Worker
95*a71a9546SAutomerger Merge Worker static FILE *osf_log_stream;
96*a71a9546SAutomerger Merge Worker
uloga(const char * f,...)97*a71a9546SAutomerger Merge Worker static void uloga(const char *f, ...)
98*a71a9546SAutomerger Merge Worker {
99*a71a9546SAutomerger Merge Worker va_list ap;
100*a71a9546SAutomerger Merge Worker
101*a71a9546SAutomerger Merge Worker if (!osf_log_stream)
102*a71a9546SAutomerger Merge Worker osf_log_stream = stdout;
103*a71a9546SAutomerger Merge Worker
104*a71a9546SAutomerger Merge Worker va_start(ap, f);
105*a71a9546SAutomerger Merge Worker vfprintf(osf_log_stream, f, ap);
106*a71a9546SAutomerger Merge Worker va_end(ap);
107*a71a9546SAutomerger Merge Worker
108*a71a9546SAutomerger Merge Worker fflush(osf_log_stream);
109*a71a9546SAutomerger Merge Worker }
110*a71a9546SAutomerger Merge Worker
ulog(const char * f,...)111*a71a9546SAutomerger Merge Worker static void ulog(const char *f, ...)
112*a71a9546SAutomerger Merge Worker {
113*a71a9546SAutomerger Merge Worker char str[64];
114*a71a9546SAutomerger Merge Worker struct tm tm;
115*a71a9546SAutomerger Merge Worker struct timeval tv;
116*a71a9546SAutomerger Merge Worker va_list ap;
117*a71a9546SAutomerger Merge Worker
118*a71a9546SAutomerger Merge Worker if (!osf_log_stream)
119*a71a9546SAutomerger Merge Worker osf_log_stream = stdout;
120*a71a9546SAutomerger Merge Worker
121*a71a9546SAutomerger Merge Worker gettimeofday(&tv, NULL);
122*a71a9546SAutomerger Merge Worker localtime_r((time_t *)&tv.tv_sec, &tm);
123*a71a9546SAutomerger Merge Worker strftime(str, sizeof(str), "%F %R:%S", &tm);
124*a71a9546SAutomerger Merge Worker
125*a71a9546SAutomerger Merge Worker fprintf(osf_log_stream, "%s.%lu %ld ", str, tv.tv_usec, syscall(__NR_gettid));
126*a71a9546SAutomerger Merge Worker
127*a71a9546SAutomerger Merge Worker va_start(ap, f);
128*a71a9546SAutomerger Merge Worker vfprintf(osf_log_stream, f, ap);
129*a71a9546SAutomerger Merge Worker va_end(ap);
130*a71a9546SAutomerger Merge Worker
131*a71a9546SAutomerger Merge Worker fflush(osf_log_stream);
132*a71a9546SAutomerger Merge Worker }
133*a71a9546SAutomerger Merge Worker
134*a71a9546SAutomerger Merge Worker #define ulog_err(f, a...) uloga(f ": %s [%d].\n", ##a, strerror(errno), errno)
135*a71a9546SAutomerger Merge Worker
xt_osf_strchr(char * ptr,char c)136*a71a9546SAutomerger Merge Worker static char *xt_osf_strchr(char *ptr, char c)
137*a71a9546SAutomerger Merge Worker {
138*a71a9546SAutomerger Merge Worker char *tmp;
139*a71a9546SAutomerger Merge Worker
140*a71a9546SAutomerger Merge Worker tmp = strchr(ptr, c);
141*a71a9546SAutomerger Merge Worker if (tmp)
142*a71a9546SAutomerger Merge Worker *tmp = '\0';
143*a71a9546SAutomerger Merge Worker
144*a71a9546SAutomerger Merge Worker while (tmp && isspace(*(tmp + 1)))
145*a71a9546SAutomerger Merge Worker tmp++;
146*a71a9546SAutomerger Merge Worker
147*a71a9546SAutomerger Merge Worker return tmp;
148*a71a9546SAutomerger Merge Worker }
149*a71a9546SAutomerger Merge Worker
xt_osf_parse_opt(struct xt_osf_opt * opt,__u16 * optnum,char * obuf,int olen)150*a71a9546SAutomerger Merge Worker static void xt_osf_parse_opt(struct xt_osf_opt *opt, __u16 *optnum, char *obuf, int olen)
151*a71a9546SAutomerger Merge Worker {
152*a71a9546SAutomerger Merge Worker int i, op;
153*a71a9546SAutomerger Merge Worker char *ptr, wc;
154*a71a9546SAutomerger Merge Worker unsigned long val;
155*a71a9546SAutomerger Merge Worker
156*a71a9546SAutomerger Merge Worker ptr = &obuf[0];
157*a71a9546SAutomerger Merge Worker i = 0;
158*a71a9546SAutomerger Merge Worker while (ptr != NULL && i < olen && *ptr != 0) {
159*a71a9546SAutomerger Merge Worker val = 0;
160*a71a9546SAutomerger Merge Worker wc = OSF_WSS_PLAIN;
161*a71a9546SAutomerger Merge Worker switch (obuf[i]) {
162*a71a9546SAutomerger Merge Worker case 'N':
163*a71a9546SAutomerger Merge Worker op = OSFOPT_NOP;
164*a71a9546SAutomerger Merge Worker ptr = xt_osf_strchr(&obuf[i], OPTDEL);
165*a71a9546SAutomerger Merge Worker if (ptr) {
166*a71a9546SAutomerger Merge Worker *ptr = '\0';
167*a71a9546SAutomerger Merge Worker ptr++;
168*a71a9546SAutomerger Merge Worker i += (int)(ptr - &obuf[i]);
169*a71a9546SAutomerger Merge Worker } else
170*a71a9546SAutomerger Merge Worker i++;
171*a71a9546SAutomerger Merge Worker break;
172*a71a9546SAutomerger Merge Worker case 'S':
173*a71a9546SAutomerger Merge Worker op = OSFOPT_SACKP;
174*a71a9546SAutomerger Merge Worker ptr = xt_osf_strchr(&obuf[i], OPTDEL);
175*a71a9546SAutomerger Merge Worker if (ptr) {
176*a71a9546SAutomerger Merge Worker *ptr = '\0';
177*a71a9546SAutomerger Merge Worker ptr++;
178*a71a9546SAutomerger Merge Worker i += (int)(ptr - &obuf[i]);
179*a71a9546SAutomerger Merge Worker } else
180*a71a9546SAutomerger Merge Worker i++;
181*a71a9546SAutomerger Merge Worker break;
182*a71a9546SAutomerger Merge Worker case 'T':
183*a71a9546SAutomerger Merge Worker op = OSFOPT_TS;
184*a71a9546SAutomerger Merge Worker ptr = xt_osf_strchr(&obuf[i], OPTDEL);
185*a71a9546SAutomerger Merge Worker if (ptr) {
186*a71a9546SAutomerger Merge Worker *ptr = '\0';
187*a71a9546SAutomerger Merge Worker ptr++;
188*a71a9546SAutomerger Merge Worker i += (int)(ptr - &obuf[i]);
189*a71a9546SAutomerger Merge Worker } else
190*a71a9546SAutomerger Merge Worker i++;
191*a71a9546SAutomerger Merge Worker break;
192*a71a9546SAutomerger Merge Worker case 'W':
193*a71a9546SAutomerger Merge Worker op = OSFOPT_WSO;
194*a71a9546SAutomerger Merge Worker ptr = xt_osf_strchr(&obuf[i], OPTDEL);
195*a71a9546SAutomerger Merge Worker if (ptr) {
196*a71a9546SAutomerger Merge Worker switch (obuf[i + 1]) {
197*a71a9546SAutomerger Merge Worker case '%':
198*a71a9546SAutomerger Merge Worker wc = OSF_WSS_MODULO;
199*a71a9546SAutomerger Merge Worker break;
200*a71a9546SAutomerger Merge Worker case 'S':
201*a71a9546SAutomerger Merge Worker wc = OSF_WSS_MSS;
202*a71a9546SAutomerger Merge Worker break;
203*a71a9546SAutomerger Merge Worker case 'T':
204*a71a9546SAutomerger Merge Worker wc = OSF_WSS_MTU;
205*a71a9546SAutomerger Merge Worker break;
206*a71a9546SAutomerger Merge Worker default:
207*a71a9546SAutomerger Merge Worker wc = OSF_WSS_PLAIN;
208*a71a9546SAutomerger Merge Worker break;
209*a71a9546SAutomerger Merge Worker }
210*a71a9546SAutomerger Merge Worker
211*a71a9546SAutomerger Merge Worker *ptr = '\0';
212*a71a9546SAutomerger Merge Worker ptr++;
213*a71a9546SAutomerger Merge Worker if (wc)
214*a71a9546SAutomerger Merge Worker val = strtoul(&obuf[i + 2], NULL, 10);
215*a71a9546SAutomerger Merge Worker else
216*a71a9546SAutomerger Merge Worker val = strtoul(&obuf[i + 1], NULL, 10);
217*a71a9546SAutomerger Merge Worker i += (int)(ptr - &obuf[i]);
218*a71a9546SAutomerger Merge Worker
219*a71a9546SAutomerger Merge Worker } else
220*a71a9546SAutomerger Merge Worker i++;
221*a71a9546SAutomerger Merge Worker break;
222*a71a9546SAutomerger Merge Worker case 'M':
223*a71a9546SAutomerger Merge Worker op = OSFOPT_MSS;
224*a71a9546SAutomerger Merge Worker ptr = xt_osf_strchr(&obuf[i], OPTDEL);
225*a71a9546SAutomerger Merge Worker if (ptr) {
226*a71a9546SAutomerger Merge Worker if (obuf[i + 1] == '%')
227*a71a9546SAutomerger Merge Worker wc = OSF_WSS_MODULO;
228*a71a9546SAutomerger Merge Worker *ptr = '\0';
229*a71a9546SAutomerger Merge Worker ptr++;
230*a71a9546SAutomerger Merge Worker if (wc)
231*a71a9546SAutomerger Merge Worker val = strtoul(&obuf[i + 2], NULL, 10);
232*a71a9546SAutomerger Merge Worker else
233*a71a9546SAutomerger Merge Worker val = strtoul(&obuf[i + 1], NULL, 10);
234*a71a9546SAutomerger Merge Worker i += (int)(ptr - &obuf[i]);
235*a71a9546SAutomerger Merge Worker } else
236*a71a9546SAutomerger Merge Worker i++;
237*a71a9546SAutomerger Merge Worker break;
238*a71a9546SAutomerger Merge Worker case 'E':
239*a71a9546SAutomerger Merge Worker op = OSFOPT_EOL;
240*a71a9546SAutomerger Merge Worker ptr = xt_osf_strchr(&obuf[i], OPTDEL);
241*a71a9546SAutomerger Merge Worker if (ptr) {
242*a71a9546SAutomerger Merge Worker *ptr = '\0';
243*a71a9546SAutomerger Merge Worker ptr++;
244*a71a9546SAutomerger Merge Worker i += (int)(ptr - &obuf[i]);
245*a71a9546SAutomerger Merge Worker } else
246*a71a9546SAutomerger Merge Worker i++;
247*a71a9546SAutomerger Merge Worker break;
248*a71a9546SAutomerger Merge Worker default:
249*a71a9546SAutomerger Merge Worker op = OSFOPT_EMPTY;
250*a71a9546SAutomerger Merge Worker ptr = xt_osf_strchr(&obuf[i], OPTDEL);
251*a71a9546SAutomerger Merge Worker if (ptr) {
252*a71a9546SAutomerger Merge Worker ptr++;
253*a71a9546SAutomerger Merge Worker i += (int)(ptr - &obuf[i]);
254*a71a9546SAutomerger Merge Worker } else
255*a71a9546SAutomerger Merge Worker i++;
256*a71a9546SAutomerger Merge Worker break;
257*a71a9546SAutomerger Merge Worker }
258*a71a9546SAutomerger Merge Worker
259*a71a9546SAutomerger Merge Worker if (op != OSFOPT_EMPTY) {
260*a71a9546SAutomerger Merge Worker opt[*optnum].kind = IANA_opts[op].kind;
261*a71a9546SAutomerger Merge Worker opt[*optnum].length = IANA_opts[op].length;
262*a71a9546SAutomerger Merge Worker opt[*optnum].wc.wc = wc;
263*a71a9546SAutomerger Merge Worker opt[*optnum].wc.val = val;
264*a71a9546SAutomerger Merge Worker (*optnum)++;
265*a71a9546SAutomerger Merge Worker }
266*a71a9546SAutomerger Merge Worker }
267*a71a9546SAutomerger Merge Worker }
268*a71a9546SAutomerger Merge Worker
osf_load_line(char * buffer,int len,int del)269*a71a9546SAutomerger Merge Worker static int osf_load_line(char *buffer, int len, int del)
270*a71a9546SAutomerger Merge Worker {
271*a71a9546SAutomerger Merge Worker int i, cnt = 0;
272*a71a9546SAutomerger Merge Worker char obuf[MAXOPTSTRLEN];
273*a71a9546SAutomerger Merge Worker struct xt_osf_user_finger f;
274*a71a9546SAutomerger Merge Worker char *pbeg, *pend;
275*a71a9546SAutomerger Merge Worker char buf[NFNL_HEADER_LEN + NFA_LENGTH(sizeof(struct xt_osf_user_finger))];
276*a71a9546SAutomerger Merge Worker struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
277*a71a9546SAutomerger Merge Worker
278*a71a9546SAutomerger Merge Worker memset(&f, 0, sizeof(struct xt_osf_user_finger));
279*a71a9546SAutomerger Merge Worker
280*a71a9546SAutomerger Merge Worker ulog("Loading '%s'.\n", buffer);
281*a71a9546SAutomerger Merge Worker
282*a71a9546SAutomerger Merge Worker for (i = 0; i < len && buffer[i] != '\0'; ++i) {
283*a71a9546SAutomerger Merge Worker if (buffer[i] == ':')
284*a71a9546SAutomerger Merge Worker cnt++;
285*a71a9546SAutomerger Merge Worker }
286*a71a9546SAutomerger Merge Worker
287*a71a9546SAutomerger Merge Worker if (cnt != 8) {
288*a71a9546SAutomerger Merge Worker ulog("Wrong input line '%s': cnt: %d, must be 8, i: %d, must be %d.\n", buffer, cnt, i, len);
289*a71a9546SAutomerger Merge Worker return -EINVAL;
290*a71a9546SAutomerger Merge Worker }
291*a71a9546SAutomerger Merge Worker
292*a71a9546SAutomerger Merge Worker memset(obuf, 0, sizeof(obuf));
293*a71a9546SAutomerger Merge Worker
294*a71a9546SAutomerger Merge Worker pbeg = buffer;
295*a71a9546SAutomerger Merge Worker pend = xt_osf_strchr(pbeg, OSFPDEL);
296*a71a9546SAutomerger Merge Worker if (pend) {
297*a71a9546SAutomerger Merge Worker *pend = '\0';
298*a71a9546SAutomerger Merge Worker if (pbeg[0] == 'S') {
299*a71a9546SAutomerger Merge Worker f.wss.wc = OSF_WSS_MSS;
300*a71a9546SAutomerger Merge Worker if (pbeg[1] == '%')
301*a71a9546SAutomerger Merge Worker f.wss.val = strtoul(&pbeg[2], NULL, 10);
302*a71a9546SAutomerger Merge Worker else if (pbeg[1] == '*')
303*a71a9546SAutomerger Merge Worker f.wss.val = 0;
304*a71a9546SAutomerger Merge Worker else
305*a71a9546SAutomerger Merge Worker f.wss.val = strtoul(&pbeg[1], NULL, 10);
306*a71a9546SAutomerger Merge Worker } else if (pbeg[0] == 'T') {
307*a71a9546SAutomerger Merge Worker f.wss.wc = OSF_WSS_MTU;
308*a71a9546SAutomerger Merge Worker if (pbeg[1] == '%')
309*a71a9546SAutomerger Merge Worker f.wss.val = strtoul(&pbeg[2], NULL, 10);
310*a71a9546SAutomerger Merge Worker else if (pbeg[1] == '*')
311*a71a9546SAutomerger Merge Worker f.wss.val = 0;
312*a71a9546SAutomerger Merge Worker else
313*a71a9546SAutomerger Merge Worker f.wss.val = strtoul(&pbeg[1], NULL, 10);
314*a71a9546SAutomerger Merge Worker } else if (pbeg[0] == '%') {
315*a71a9546SAutomerger Merge Worker f.wss.wc = OSF_WSS_MODULO;
316*a71a9546SAutomerger Merge Worker f.wss.val = strtoul(&pbeg[1], NULL, 10);
317*a71a9546SAutomerger Merge Worker } else if (isdigit(pbeg[0])) {
318*a71a9546SAutomerger Merge Worker f.wss.wc = OSF_WSS_PLAIN;
319*a71a9546SAutomerger Merge Worker f.wss.val = strtoul(&pbeg[0], NULL, 10);
320*a71a9546SAutomerger Merge Worker }
321*a71a9546SAutomerger Merge Worker
322*a71a9546SAutomerger Merge Worker pbeg = pend + 1;
323*a71a9546SAutomerger Merge Worker }
324*a71a9546SAutomerger Merge Worker pend = xt_osf_strchr(pbeg, OSFPDEL);
325*a71a9546SAutomerger Merge Worker if (pend) {
326*a71a9546SAutomerger Merge Worker *pend = '\0';
327*a71a9546SAutomerger Merge Worker f.ttl = strtoul(pbeg, NULL, 10);
328*a71a9546SAutomerger Merge Worker pbeg = pend + 1;
329*a71a9546SAutomerger Merge Worker }
330*a71a9546SAutomerger Merge Worker pend = xt_osf_strchr(pbeg, OSFPDEL);
331*a71a9546SAutomerger Merge Worker if (pend) {
332*a71a9546SAutomerger Merge Worker *pend = '\0';
333*a71a9546SAutomerger Merge Worker f.df = strtoul(pbeg, NULL, 10);
334*a71a9546SAutomerger Merge Worker pbeg = pend + 1;
335*a71a9546SAutomerger Merge Worker }
336*a71a9546SAutomerger Merge Worker pend = xt_osf_strchr(pbeg, OSFPDEL);
337*a71a9546SAutomerger Merge Worker if (pend) {
338*a71a9546SAutomerger Merge Worker *pend = '\0';
339*a71a9546SAutomerger Merge Worker f.ss = strtoul(pbeg, NULL, 10);
340*a71a9546SAutomerger Merge Worker pbeg = pend + 1;
341*a71a9546SAutomerger Merge Worker }
342*a71a9546SAutomerger Merge Worker
343*a71a9546SAutomerger Merge Worker pend = xt_osf_strchr(pbeg, OSFPDEL);
344*a71a9546SAutomerger Merge Worker if (pend) {
345*a71a9546SAutomerger Merge Worker *pend = '\0';
346*a71a9546SAutomerger Merge Worker i = sizeof(obuf);
347*a71a9546SAutomerger Merge Worker snprintf(obuf, i, "%.*s,", i - 2, pbeg);
348*a71a9546SAutomerger Merge Worker pbeg = pend + 1;
349*a71a9546SAutomerger Merge Worker }
350*a71a9546SAutomerger Merge Worker
351*a71a9546SAutomerger Merge Worker pend = xt_osf_strchr(pbeg, OSFPDEL);
352*a71a9546SAutomerger Merge Worker if (pend) {
353*a71a9546SAutomerger Merge Worker *pend = '\0';
354*a71a9546SAutomerger Merge Worker i = sizeof(f.genre);
355*a71a9546SAutomerger Merge Worker if (pbeg[0] == '@' || pbeg[0] == '*')
356*a71a9546SAutomerger Merge Worker pbeg++;
357*a71a9546SAutomerger Merge Worker snprintf(f.genre, i, "%.*s", i - 1, pbeg);
358*a71a9546SAutomerger Merge Worker pbeg = pend + 1;
359*a71a9546SAutomerger Merge Worker }
360*a71a9546SAutomerger Merge Worker
361*a71a9546SAutomerger Merge Worker pend = xt_osf_strchr(pbeg, OSFPDEL);
362*a71a9546SAutomerger Merge Worker if (pend) {
363*a71a9546SAutomerger Merge Worker *pend = '\0';
364*a71a9546SAutomerger Merge Worker i = sizeof(f.version);
365*a71a9546SAutomerger Merge Worker snprintf(f.version, i, "%.*s", i - 1, pbeg);
366*a71a9546SAutomerger Merge Worker pbeg = pend + 1;
367*a71a9546SAutomerger Merge Worker }
368*a71a9546SAutomerger Merge Worker
369*a71a9546SAutomerger Merge Worker pend = xt_osf_strchr(pbeg, OSFPDEL);
370*a71a9546SAutomerger Merge Worker if (pend) {
371*a71a9546SAutomerger Merge Worker *pend = '\0';
372*a71a9546SAutomerger Merge Worker i = sizeof(f.subtype);
373*a71a9546SAutomerger Merge Worker snprintf(f.subtype, i, "%.*s", i - 1, pbeg);
374*a71a9546SAutomerger Merge Worker }
375*a71a9546SAutomerger Merge Worker
376*a71a9546SAutomerger Merge Worker xt_osf_parse_opt(f.opt, &f.opt_num, obuf, sizeof(obuf));
377*a71a9546SAutomerger Merge Worker
378*a71a9546SAutomerger Merge Worker memset(buf, 0, sizeof(buf));
379*a71a9546SAutomerger Merge Worker
380*a71a9546SAutomerger Merge Worker if (del)
381*a71a9546SAutomerger Merge Worker nfnl_fill_hdr(nfnlssh, nmh, 0, AF_UNSPEC, 0, OSF_MSG_REMOVE,
382*a71a9546SAutomerger Merge Worker NLM_F_ACK | NLM_F_REQUEST);
383*a71a9546SAutomerger Merge Worker else
384*a71a9546SAutomerger Merge Worker nfnl_fill_hdr(nfnlssh, nmh, 0, AF_UNSPEC, 0, OSF_MSG_ADD,
385*a71a9546SAutomerger Merge Worker NLM_F_ACK | NLM_F_REQUEST | NLM_F_CREATE);
386*a71a9546SAutomerger Merge Worker
387*a71a9546SAutomerger Merge Worker nfnl_addattr_l(nmh, sizeof(buf), OSF_ATTR_FINGER, &f, sizeof(struct xt_osf_user_finger));
388*a71a9546SAutomerger Merge Worker
389*a71a9546SAutomerger Merge Worker return nfnl_query(nfnlh, nmh);
390*a71a9546SAutomerger Merge Worker }
391*a71a9546SAutomerger Merge Worker
osf_load_entries(char * path,int del)392*a71a9546SAutomerger Merge Worker static int osf_load_entries(char *path, int del)
393*a71a9546SAutomerger Merge Worker {
394*a71a9546SAutomerger Merge Worker FILE *inf;
395*a71a9546SAutomerger Merge Worker int err = 0, lineno = 0;
396*a71a9546SAutomerger Merge Worker char buf[1024];
397*a71a9546SAutomerger Merge Worker
398*a71a9546SAutomerger Merge Worker inf = fopen(path, "r");
399*a71a9546SAutomerger Merge Worker if (!inf) {
400*a71a9546SAutomerger Merge Worker ulog_err("Failed to open file '%s'", path);
401*a71a9546SAutomerger Merge Worker return -1;
402*a71a9546SAutomerger Merge Worker }
403*a71a9546SAutomerger Merge Worker
404*a71a9546SAutomerger Merge Worker while(fgets(buf, sizeof(buf), inf)) {
405*a71a9546SAutomerger Merge Worker int len, rc;
406*a71a9546SAutomerger Merge Worker
407*a71a9546SAutomerger Merge Worker lineno++;
408*a71a9546SAutomerger Merge Worker
409*a71a9546SAutomerger Merge Worker if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r')
410*a71a9546SAutomerger Merge Worker continue;
411*a71a9546SAutomerger Merge Worker
412*a71a9546SAutomerger Merge Worker len = strlen(buf) - 1;
413*a71a9546SAutomerger Merge Worker
414*a71a9546SAutomerger Merge Worker if (len <= 0)
415*a71a9546SAutomerger Merge Worker continue;
416*a71a9546SAutomerger Merge Worker
417*a71a9546SAutomerger Merge Worker buf[len] = '\0';
418*a71a9546SAutomerger Merge Worker
419*a71a9546SAutomerger Merge Worker rc = osf_load_line(buf, len, del);
420*a71a9546SAutomerger Merge Worker if (rc && (!del || errno != ENOENT)) {
421*a71a9546SAutomerger Merge Worker ulog_err("Failed to load line %d", lineno);
422*a71a9546SAutomerger Merge Worker err = rc;
423*a71a9546SAutomerger Merge Worker }
424*a71a9546SAutomerger Merge Worker
425*a71a9546SAutomerger Merge Worker memset(buf, 0, sizeof(buf));
426*a71a9546SAutomerger Merge Worker }
427*a71a9546SAutomerger Merge Worker
428*a71a9546SAutomerger Merge Worker fclose(inf);
429*a71a9546SAutomerger Merge Worker return err;
430*a71a9546SAutomerger Merge Worker }
431*a71a9546SAutomerger Merge Worker
main(int argc,char * argv[])432*a71a9546SAutomerger Merge Worker int main(int argc, char *argv[])
433*a71a9546SAutomerger Merge Worker {
434*a71a9546SAutomerger Merge Worker int ch, del = 0, err;
435*a71a9546SAutomerger Merge Worker char *fingerprints = NULL;
436*a71a9546SAutomerger Merge Worker
437*a71a9546SAutomerger Merge Worker while ((ch = getopt(argc, argv, "f:dh")) != -1) {
438*a71a9546SAutomerger Merge Worker switch (ch) {
439*a71a9546SAutomerger Merge Worker case 'f':
440*a71a9546SAutomerger Merge Worker fingerprints = optarg;
441*a71a9546SAutomerger Merge Worker break;
442*a71a9546SAutomerger Merge Worker case 'd':
443*a71a9546SAutomerger Merge Worker del = 1;
444*a71a9546SAutomerger Merge Worker break;
445*a71a9546SAutomerger Merge Worker default:
446*a71a9546SAutomerger Merge Worker fprintf(stderr,
447*a71a9546SAutomerger Merge Worker "Usage: %s -f fingerprints [-d]\n",
448*a71a9546SAutomerger Merge Worker argv[0]);
449*a71a9546SAutomerger Merge Worker return -1;
450*a71a9546SAutomerger Merge Worker }
451*a71a9546SAutomerger Merge Worker }
452*a71a9546SAutomerger Merge Worker
453*a71a9546SAutomerger Merge Worker if (!fingerprints) {
454*a71a9546SAutomerger Merge Worker err = -ENOENT;
455*a71a9546SAutomerger Merge Worker ulog("Missing fingerprints file argument.\n");
456*a71a9546SAutomerger Merge Worker goto err_out_exit;
457*a71a9546SAutomerger Merge Worker }
458*a71a9546SAutomerger Merge Worker
459*a71a9546SAutomerger Merge Worker nfnlh = nfnl_open();
460*a71a9546SAutomerger Merge Worker if (!nfnlh) {
461*a71a9546SAutomerger Merge Worker err = -EINVAL;
462*a71a9546SAutomerger Merge Worker ulog_err("Failed to create nfnl handler");
463*a71a9546SAutomerger Merge Worker goto err_out_exit;
464*a71a9546SAutomerger Merge Worker }
465*a71a9546SAutomerger Merge Worker
466*a71a9546SAutomerger Merge Worker #ifndef NFNL_SUBSYS_OSF
467*a71a9546SAutomerger Merge Worker #define NFNL_SUBSYS_OSF 5
468*a71a9546SAutomerger Merge Worker #endif
469*a71a9546SAutomerger Merge Worker
470*a71a9546SAutomerger Merge Worker nfnlssh = nfnl_subsys_open(nfnlh, NFNL_SUBSYS_OSF, OSF_MSG_MAX, 0);
471*a71a9546SAutomerger Merge Worker if (!nfnlssh) {
472*a71a9546SAutomerger Merge Worker err = -EINVAL;
473*a71a9546SAutomerger Merge Worker ulog_err("Faied to create nfnl subsystem");
474*a71a9546SAutomerger Merge Worker goto err_out_close;
475*a71a9546SAutomerger Merge Worker }
476*a71a9546SAutomerger Merge Worker
477*a71a9546SAutomerger Merge Worker err = osf_load_entries(fingerprints, del);
478*a71a9546SAutomerger Merge Worker if (err)
479*a71a9546SAutomerger Merge Worker goto err_out_close_subsys;
480*a71a9546SAutomerger Merge Worker
481*a71a9546SAutomerger Merge Worker nfnl_subsys_close(nfnlssh);
482*a71a9546SAutomerger Merge Worker nfnl_close(nfnlh);
483*a71a9546SAutomerger Merge Worker
484*a71a9546SAutomerger Merge Worker return 0;
485*a71a9546SAutomerger Merge Worker
486*a71a9546SAutomerger Merge Worker err_out_close_subsys:
487*a71a9546SAutomerger Merge Worker nfnl_subsys_close(nfnlssh);
488*a71a9546SAutomerger Merge Worker err_out_close:
489*a71a9546SAutomerger Merge Worker nfnl_close(nfnlh);
490*a71a9546SAutomerger Merge Worker err_out_exit:
491*a71a9546SAutomerger Merge Worker return err;
492*a71a9546SAutomerger Merge Worker }
493