xref: /aosp_15_r20/external/iptables/utils/nfnl_osf.c (revision a71a954618bbadd4a345637e5edcf36eec826889)
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