ipf.c revision 1.1.1.1.2.2 1 /* $NetBSD: ipf.c,v 1.1.1.1.2.2 2012/04/17 00:03:26 yamt Exp $ */
2
3 /*
4 * Copyright (C) 2009 by Darren Reed.
5 *
6 * See the IPFILTER.LICENCE file for details on licencing.
7 */
8 #ifdef __FreeBSD__
9 # ifndef __FreeBSD_cc_version
10 # include <osreldate.h>
11 # else
12 # if __FreeBSD_cc_version < 430000
13 # include <osreldate.h>
14 # endif
15 # endif
16 #endif
17 #include "ipf.h"
18 #include <fcntl.h>
19 #include <ctype.h>
20 #include <sys/ioctl.h>
21 #include "netinet/ipl.h"
22
23 #if !defined(lint)
24 static const char sccsid[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-2000 Darren Reed";
25 static const char rcsid[] = "@(#)Id";
26 #endif
27
28 #if !defined(__SVR4) && defined(__GNUC__)
29 extern char *index __P((const char *, int));
30 #endif
31
32 extern char *optarg;
33 extern int optind;
34 extern frentry_t *frtop;
35
36
37 void ipf_frsync __P((void));
38 void zerostats __P((void));
39 int main __P((int, char *[]));
40
41 int opts = 0;
42 int outputc = 0;
43 int use_inet6 = 0;
44
45 static void procfile __P((char *, char *));
46 static void flushfilter __P((char *, int *));
47 static void set_state __P((u_int));
48 static void showstats __P((friostat_t *));
49 static void packetlogon __P((char *));
50 static void swapactive __P((void));
51 static int opendevice __P((char *, int));
52 static void closedevice __P((void));
53 static char *ipfname = IPL_NAME;
54 static void usage __P((void));
55 static int showversion __P((void));
56 static int get_flags __P((void));
57 static void ipf_interceptadd __P((int, ioctlfunc_t, void *));
58
59 static int fd = -1;
60 static ioctlfunc_t iocfunctions[IPL_LOGSIZE] = { ioctl, ioctl, ioctl,
61 ioctl, ioctl, ioctl,
62 ioctl, ioctl };
63
64
65 static void usage()
66 {
67 fprintf(stderr, "usage: ipf [-6AdDEInoPrRsvVyzZ] %s %s %s\n",
68 "[-l block|pass|nomatch|state|nat]", "[-cc] [-F i|o|a|s|S|u]",
69 "[-f filename] [-T <tuneopts>]");
70 exit(1);
71 }
72
73
74 int main(argc,argv)
75 int argc;
76 char *argv[];
77 {
78 int c, *filter = NULL;
79
80 if (argc < 2)
81 usage();
82
83 assigndefined(getenv("IPF_PREDEFINED"));
84
85 while ((c = getopt(argc, argv, "46Ac:dDEf:F:Il:m:noPrRsT:vVyzZ")) != -1) {
86 switch (c)
87 {
88 case '?' :
89 usage();
90 break;
91 case '4' :
92 use_inet6 = -1;
93 break;
94 case '6' :
95 use_inet6 = 1;
96 break;
97 case 'A' :
98 opts &= ~OPT_INACTIVE;
99 break;
100 case 'c' :
101 if (strcmp(optarg, "c") == 0)
102 outputc = 1;
103 break;
104 case 'E' :
105 set_state((u_int)1);
106 break;
107 case 'D' :
108 set_state((u_int)0);
109 break;
110 case 'd' :
111 opts ^= OPT_DEBUG;
112 break;
113 case 'f' :
114 procfile(argv[0], optarg);
115 break;
116 case 'F' :
117 flushfilter(optarg, filter);
118 break;
119 case 'I' :
120 opts ^= OPT_INACTIVE;
121 break;
122 case 'l' :
123 packetlogon(optarg);
124 break;
125 case 'm' :
126 filter = parseipfexpr(optarg, NULL);
127 break;
128 case 'n' :
129 opts ^= OPT_DONOTHING|OPT_DONTOPEN;
130 break;
131 case 'o' :
132 break;
133 case 'P' :
134 ipfname = IPAUTH_NAME;
135 break;
136 case 'R' :
137 opts ^= OPT_NORESOLVE;
138 break;
139 case 'r' :
140 opts ^= OPT_REMOVE;
141 break;
142 case 's' :
143 swapactive();
144 break;
145 case 'T' :
146 if (opendevice(ipfname, 1) >= 0)
147 ipf_dotuning(fd, optarg, ioctl);
148 break;
149 case 'v' :
150 opts += OPT_VERBOSE;
151 break;
152 case 'V' :
153 if (showversion())
154 exit(1);
155 break;
156 case 'y' :
157 ipf_frsync();
158 break;
159 case 'z' :
160 opts ^= OPT_ZERORULEST;
161 break;
162 case 'Z' :
163 zerostats();
164 break;
165 }
166 }
167
168 if (optind < 2)
169 usage();
170
171 if (fd != -1)
172 (void) close(fd);
173
174 return(0);
175 /* NOTREACHED */
176 }
177
178
179 static int opendevice(ipfdev, check)
180 char *ipfdev;
181 int check;
182 {
183 if (opts & OPT_DONOTHING)
184 return -2;
185
186 if (check && checkrev(ipfname) == -1) {
187 fprintf(stderr, "User/kernel version check failed\n");
188 return -2;
189 }
190
191 if (!ipfdev)
192 ipfdev = ipfname;
193
194 if (fd == -1)
195 if ((fd = open(ipfdev, O_RDWR)) == -1)
196 if ((fd = open(ipfdev, O_RDONLY)) == -1)
197 ipferror(fd, "open device");
198 return fd;
199 }
200
201
202 static void closedevice()
203 {
204 close(fd);
205 fd = -1;
206 }
207
208
209 static int get_flags()
210 {
211 int i = 0;
212
213 if ((opendevice(ipfname, 1) != -2) &&
214 (ioctl(fd, SIOCGETFF, &i) == -1)) {
215 ipferror(fd, "SIOCGETFF");
216 return 0;
217 }
218 return i;
219 }
220
221
222 static void set_state(enable)
223 u_int enable;
224 {
225 if (opendevice(ipfname, 0) != -2) {
226 if (ioctl(fd, SIOCFRENB, &enable) == -1) {
227 if (errno == EBUSY) {
228 fprintf(stderr,
229 "IP FIlter: already initialized\n");
230 } else {
231 ipferror(fd, "SIOCFRENB");
232 }
233 }
234 }
235 return;
236 }
237
238
239 static void procfile(name, file)
240 char *name, *file;
241 {
242 (void) opendevice(ipfname, 1);
243
244 initparse();
245
246 ipf_parsefile(fd, ipf_interceptadd, iocfunctions, file);
247
248 if (outputc) {
249 printC(0);
250 printC(1);
251 emit(-1, -1, NULL, NULL);
252 }
253 }
254
255
256 static void ipf_interceptadd(fd, ioctlfunc, ptr)
257 int fd;
258 ioctlfunc_t ioctlfunc;
259 void *ptr;
260 {
261 if (outputc)
262 printc(ptr);
263
264 ipf_addrule(fd, ioctlfunc, ptr);
265 }
266
267
268 static void packetlogon(opt)
269 char *opt;
270 {
271 int flag, xfd, logopt, change = 0;
272
273 flag = get_flags();
274 if (flag != 0) {
275 if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE)
276 printf("log flag is currently %#x\n", flag);
277 }
278
279 flag &= ~(FF_LOGPASS|FF_LOGNOMATCH|FF_LOGBLOCK);
280
281 if (strstr(opt, "pass")) {
282 flag |= FF_LOGPASS;
283 if (opts & OPT_VERBOSE)
284 printf("set log flag: pass\n");
285 change = 1;
286 }
287 if (strstr(opt, "nomatch")) {
288 flag |= FF_LOGNOMATCH;
289 if (opts & OPT_VERBOSE)
290 printf("set log flag: nomatch\n");
291 change = 1;
292 }
293 if (strstr(opt, "block") || index(opt, 'd')) {
294 flag |= FF_LOGBLOCK;
295 if (opts & OPT_VERBOSE)
296 printf("set log flag: block\n");
297 change = 1;
298 }
299 if (strstr(opt, "none")) {
300 if (opts & OPT_VERBOSE)
301 printf("disable all log flags\n");
302 change = 1;
303 }
304
305 if (change == 1) {
306 if (opendevice(ipfname, 1) != -2 &&
307 (ioctl(fd, SIOCSETFF, &flag) != 0))
308 ipferror(fd, "ioctl(SIOCSETFF)");
309 }
310
311 if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
312 flag = get_flags();
313 printf("log flags are now %#x\n", flag);
314 }
315
316 if (strstr(opt, "state")) {
317 if (opts & OPT_VERBOSE)
318 printf("set state log flag\n");
319 xfd = open(IPSTATE_NAME, O_RDWR);
320 if (xfd >= 0) {
321 logopt = 0;
322 if (ioctl(xfd, SIOCGETLG, &logopt))
323 ipferror(fd, "ioctl(SIOCGETLG)");
324 else {
325 logopt = 1 - logopt;
326 if (ioctl(xfd, SIOCSETLG, &logopt))
327 ipferror(xfd, "ioctl(SIOCSETLG)");
328 }
329 close(xfd);
330 }
331 }
332
333 if (strstr(opt, "nat")) {
334 if (opts & OPT_VERBOSE)
335 printf("set nat log flag\n");
336 xfd = open(IPNAT_NAME, O_RDWR);
337 if (xfd >= 0) {
338 logopt = 0;
339 if (ioctl(xfd, SIOCGETLG, &logopt))
340 ipferror(xfd, "ioctl(SIOCGETLG)");
341 else {
342 logopt = 1 - logopt;
343 if (ioctl(xfd, SIOCSETLG, &logopt))
344 ipferror(xfd, "ioctl(SIOCSETLG)");
345 }
346 close(xfd);
347 }
348 }
349 }
350
351
352 static void flushfilter(arg, filter)
353 char *arg;
354 int *filter;
355 {
356 int fl = 0, rem;
357
358 if (!arg || !*arg)
359 return;
360 if (!strcmp(arg, "s") || !strcmp(arg, "S") || ISDIGIT(*arg)) {
361 if (*arg == 'S')
362 fl = 0;
363 else if (*arg == 's')
364 fl = 1;
365 else
366 fl = atoi(arg);
367 rem = fl;
368
369 closedevice();
370 if (opendevice(IPSTATE_NAME, 1) == -2)
371 exit(1);
372
373 if (!(opts & OPT_DONOTHING)) {
374 if (use_inet6) {
375 fprintf(stderr,
376 "IPv6 rules are no longer seperate\n");
377 } else if (filter != NULL) {
378 ipfobj_t obj;
379
380 obj.ipfo_rev = IPFILTER_VERSION;
381 obj.ipfo_size = filter[0] * sizeof(int);
382 obj.ipfo_type = IPFOBJ_IPFEXPR;
383 obj.ipfo_ptr = filter;
384 if (ioctl(fd, SIOCMATCHFLUSH, &obj) == -1) {
385 ipferror(fd, "ioctl(SIOCMATCHFLUSH)");
386 fl = -1;
387 } else {
388 fl = obj.ipfo_retval;
389 }
390 } else {
391 if (ioctl(fd, SIOCIPFFL, &fl) == -1) {
392 ipferror(fd, "ioctl(SIOCIPFFL)");
393 exit(1);
394 }
395 }
396 }
397 if ((opts & (OPT_DONOTHING|OPT_DEBUG)) == OPT_DEBUG) {
398 printf("remove flags %s (%d)\n", arg, rem);
399 }
400 if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
401 printf("%d state entries removed\n", fl);
402 }
403 closedevice();
404 return;
405 }
406
407 #ifdef SIOCIPFFA
408 if (!strcmp(arg, "u")) {
409 closedevice();
410 /*
411 * Flush auth rules and packets
412 */
413 if (opendevice(IPL_AUTH, 1) == -1)
414 perror("open(IPL_AUTH)");
415 else {
416 if (ioctl(fd, SIOCIPFFA, &fl) == -1)
417 ipferror(fd, "ioctl(SIOCIPFFA)");
418 }
419 closedevice();
420 return;
421 }
422 #endif
423
424 if (strchr(arg, 'i') || strchr(arg, 'I'))
425 fl = FR_INQUE;
426 if (strchr(arg, 'o') || strchr(arg, 'O'))
427 fl = FR_OUTQUE;
428 if (strchr(arg, 'a') || strchr(arg, 'A'))
429 fl = FR_OUTQUE|FR_INQUE;
430 if (opts & OPT_INACTIVE)
431 fl |= FR_INACTIVE;
432 rem = fl;
433
434 if (opendevice(ipfname, 1) == -2)
435 exit(1);
436
437 if (!(opts & OPT_DONOTHING)) {
438 if (use_inet6) {
439 if (ioctl(fd, SIOCIPFL6, &fl) == -1) {
440 ipferror(fd, "ioctl(SIOCIPFL6)");
441 exit(1);
442 }
443 } else {
444 if (ioctl(fd, SIOCIPFFL, &fl) == -1) {
445 ipferror(fd, "ioctl(SIOCIPFFL)");
446 exit(1);
447 }
448 }
449 }
450
451 if ((opts & (OPT_DONOTHING|OPT_DEBUG)) == OPT_DEBUG) {
452 printf("remove flags %s%s (%d)\n", (rem & FR_INQUE) ? "I" : "",
453 (rem & FR_OUTQUE) ? "O" : "", rem);
454 }
455 if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
456 printf("%d filter rules removed\n", fl);
457 }
458 return;
459 }
460
461
462 static void swapactive()
463 {
464 int in = 2;
465
466 if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCSWAPA, &in) == -1)
467 ipferror(fd, "ioctl(SIOCSWAPA)");
468 else
469 printf("Set %d now inactive\n", in);
470 }
471
472
473 void ipf_frsync()
474 {
475 int frsyn = 0;
476
477 if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCFRSYN, &frsyn) == -1)
478 ipferror(fd, "SIOCFRSYN");
479 else
480 printf("filter sync'd\n");
481 }
482
483
484 void zerostats()
485 {
486 ipfobj_t obj;
487 friostat_t fio;
488
489 obj.ipfo_rev = IPFILTER_VERSION;
490 obj.ipfo_type = IPFOBJ_IPFSTAT;
491 obj.ipfo_size = sizeof(fio);
492 obj.ipfo_ptr = &fio;
493 obj.ipfo_offset = 0;
494
495 if (opendevice(ipfname, 1) != -2) {
496 if (ioctl(fd, SIOCFRZST, &obj) == -1) {
497 ipferror(fd, "ioctl(SIOCFRZST)");
498 exit(-1);
499 }
500 showstats(&fio);
501 }
502
503 }
504
505
506 /*
507 * read the kernel stats for packets blocked and passed
508 */
509 static void showstats(fp)
510 friostat_t *fp;
511 {
512 printf("bad packets:\t\tin %lu\tout %lu\n",
513 fp->f_st[0].fr_bad, fp->f_st[1].fr_bad);
514 printf(" input packets:\t\tblocked %lu passed %lu nomatch %lu",
515 fp->f_st[0].fr_block, fp->f_st[0].fr_pass,
516 fp->f_st[0].fr_nom);
517 printf(" counted %lu\n", fp->f_st[0].fr_acct);
518 printf("output packets:\t\tblocked %lu passed %lu nomatch %lu",
519 fp->f_st[1].fr_block, fp->f_st[1].fr_pass,
520 fp->f_st[1].fr_nom);
521 printf(" counted %lu\n", fp->f_st[0].fr_acct);
522 printf(" input packets logged:\tblocked %lu passed %lu\n",
523 fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl);
524 printf("output packets logged:\tblocked %lu passed %lu\n",
525 fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl);
526 }
527
528
529 static int showversion()
530 {
531 struct friostat fio;
532 ipfobj_t ipfo;
533 u_32_t flags;
534 char *s;
535 int vfd;
536
537 bzero((caddr_t)&ipfo, sizeof(ipfo));
538 ipfo.ipfo_rev = IPFILTER_VERSION;
539 ipfo.ipfo_size = sizeof(fio);
540 ipfo.ipfo_ptr = (void *)&fio;
541 ipfo.ipfo_type = IPFOBJ_IPFSTAT;
542
543 printf("ipf: %s (%d)\n", IPL_VERSION, (int)sizeof(frentry_t));
544
545 if ((vfd = open(ipfname, O_RDONLY)) == -1) {
546 perror("open device");
547 return 1;
548 }
549
550 if (ioctl(vfd, SIOCGETFS, &ipfo)) {
551 ipferror(vfd, "ioctl(SIOCGETFS)");
552 close(vfd);
553 return 1;
554 }
555 close(vfd);
556 flags = get_flags();
557
558 printf("Kernel: %-*.*s\n", (int)sizeof(fio.f_version),
559 (int)sizeof(fio.f_version), fio.f_version);
560 printf("Running: %s\n", (fio.f_running > 0) ? "yes" : "no");
561 printf("Log Flags: %#x = ", flags);
562 s = "";
563 if (flags & FF_LOGPASS) {
564 printf("pass");
565 s = ", ";
566 }
567 if (flags & FF_LOGBLOCK) {
568 printf("%sblock", s);
569 s = ", ";
570 }
571 if (flags & FF_LOGNOMATCH) {
572 printf("%snomatch", s);
573 s = ", ";
574 }
575 if (flags & FF_BLOCKNONIP) {
576 printf("%snonip", s);
577 s = ", ";
578 }
579 if (!*s)
580 printf("none set");
581 putchar('\n');
582
583 printf("Default: ");
584 if (FR_ISPASS(fio.f_defpass))
585 s = "pass";
586 else if (FR_ISBLOCK(fio.f_defpass))
587 s = "block";
588 else
589 s = "nomatch -> block";
590 printf("%s all, Logging: %savailable\n", s, fio.f_logging ? "" : "un");
591 printf("Active list: %d\n", fio.f_active);
592 printf("Feature mask: %#x\n", fio.f_features);
593
594 return 0;
595 }
596