2 * Copyright (C) 1993-2001 by Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
6 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
7 * Use is subject to license terms.
9 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
13 # ifndef __FreeBSD_cc_version
14 # include <osreldate.h>
16 # if __FreeBSD_cc_version < 430000
17 # include <osreldate.h>
23 #include <sys/ioctl.h>
24 #include "netinet/ipl.h"
27 static const char sccsid
[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-2000 Darren Reed";
28 static const char rcsid
[] = "@(#)$Id: ipf.c,v 1.35.2.3 2004/12/15 18:27:17 darrenr Exp $";
30 #if !defined(__SVR4) && defined(__GNUC__)
31 extern char *index
__P((const char *, int));
36 extern frentry_t
*frtop
;
39 void ipf_frsync
__P((void));
40 void zerostats
__P((void));
41 int main
__P((int, char *[]));
47 static void procfile
__P((char *, char *)), flushfilter
__P((char *));
48 static void set_state
__P((u_int
)), showstats
__P((friostat_t
*));
49 static void packetlogon
__P((char *)), swapactive
__P((void));
50 static int opendevice
__P((char *, int));
51 static void closedevice
__P((void));
52 static char *ipfname
= IPL_NAME
;
53 static void usage
__P((void));
54 static int showversion
__P((void));
55 static int get_flags
__P((void));
56 static void ipf_interceptadd
__P((int, ioctlfunc_t
, void *));
59 static ioctlfunc_t iocfunctions
[IPL_LOGSIZE
] = { ioctl
, ioctl
, ioctl
,
66 fprintf(stderr
, "usage: ipf [-6AdDEGInoPrRsvVyzZ] %s %s %s",
67 "[-l block|pass|nomatch|state|nat]", "[-cc] [-F i|o|a|s|S|u]",
68 "[-f filename] [-T <tuneopts>] [zonename]\n");
78 const char *optstr
= "6Ac:dDEf:F:GIl:noPrRsT:vVyzZ";
84 * We need to set the zone name before calling the functions
85 * in the switch statement below. Note that ipf.c differs from the other
86 * tools in the ipfilter suite: the zone name is specified as the
87 * last argument, while the other tools use the -z option. ipf
88 * already has a -z option, so the last argument is used instead.
90 getzonearg(argc
, argv
, optstr
);
92 while ((c
= getopt(argc
, argv
, optstr
)) != -1) {
104 opts
&= ~OPT_INACTIVE
;
107 if (strcmp(optarg
, "c") == 0)
120 procfile(argv
[0], optarg
);
126 /* Already handled by getzonearg() above */
129 opts
^= OPT_INACTIVE
;
135 opts
^= OPT_DONOTHING
;
140 ipfname
= IPAUTH_NAME
;
143 opts
^= OPT_NORESOLVE
;
152 if (opendevice(ipfname
, 1) >= 0)
153 ipf_dotuning(fd
, optarg
, ioctl
);
166 opts
^= OPT_ZERORULEST
;
185 static int opendevice(ipfdev
, check
)
189 if (opts
& OPT_DONOTHING
)
192 if (check
&& checkrev(ipfname
) == -1) {
193 fprintf(stderr
, "User/kernel version check failed\n");
201 if ((fd
= open(ipfdev
, O_RDWR
)) == -1)
202 if ((fd
= open(ipfdev
, O_RDONLY
)) == -1)
203 perror("open device");
205 if (setzone(fd
) != 0) {
214 static void closedevice()
221 static int get_flags()
225 if ((opendevice(ipfname
, 1) != -2) &&
226 (ioctl(fd
, SIOCGETFF
, &i
) == -1)) {
234 static void set_state(enable
)
237 if (opendevice(ipfname
, 0) != -2)
238 if (ioctl(fd
, SIOCFRENB
, &enable
) == -1) {
241 "IP FIlter: already initialized\n");
249 static void procfile(name
, file
)
252 (void) opendevice(ipfname
, 1);
256 ipf_parsefile(fd
, ipf_interceptadd
, iocfunctions
, file
);
261 emit(-1, -1, NULL
, NULL
);
266 static void ipf_interceptadd(fd
, ioctlfunc
, ptr
)
268 ioctlfunc_t ioctlfunc
;
274 ipf_addrule(fd
, ioctlfunc
, ptr
);
278 static void packetlogon(opt
)
281 int flag
, xfd
, logopt
, change
= 0;
285 if ((opts
& (OPT_DONOTHING
|OPT_VERBOSE
)) == OPT_VERBOSE
)
286 printf("log flag is currently %#x\n", flag
);
289 flag
&= ~(FF_LOGPASS
|FF_LOGNOMATCH
|FF_LOGBLOCK
);
291 if (strstr(opt
, "pass")) {
293 if (opts
& OPT_VERBOSE
)
294 printf("set log flag: pass\n");
297 if (strstr(opt
, "nomatch")) {
298 flag
|= FF_LOGNOMATCH
;
299 if (opts
& OPT_VERBOSE
)
300 printf("set log flag: nomatch\n");
303 if (strstr(opt
, "block") || index(opt
, 'd')) {
305 if (opts
& OPT_VERBOSE
)
306 printf("set log flag: block\n");
309 if (strstr(opt
, "none")) {
310 if (opts
& OPT_VERBOSE
)
311 printf("disable all log flags\n");
316 if (opendevice(ipfname
, 1) != -2 &&
317 (ioctl(fd
, SIOCSETFF
, &flag
) != 0))
318 perror("ioctl(SIOCSETFF)");
321 if ((opts
& (OPT_DONOTHING
|OPT_VERBOSE
)) == OPT_VERBOSE
) {
323 printf("log flags are now %#x\n", flag
);
326 if (strstr(opt
, "state")) {
327 if (opts
& OPT_VERBOSE
)
328 printf("set state log flag\n");
329 xfd
= open(IPSTATE_NAME
, O_RDWR
);
330 if (xfd
>= 0 && setzone(xfd
) != 0) {
337 if (ioctl(xfd
, SIOCGETLG
, &logopt
))
338 perror("ioctl(SIOCGETLG)");
341 if (ioctl(xfd
, SIOCSETLG
, &logopt
))
342 perror("ioctl(SIOCSETLG)");
348 if (strstr(opt
, "nat")) {
349 if (opts
& OPT_VERBOSE
)
350 printf("set nat log flag\n");
351 xfd
= open(IPNAT_NAME
, O_RDWR
);
352 if (xfd
>= 0 && setzone(xfd
) != 0) {
359 if (ioctl(xfd
, SIOCGETLG
, &logopt
))
360 perror("ioctl(SIOCGETLG)");
363 if (ioctl(xfd
, SIOCSETLG
, &logopt
))
364 perror("ioctl(SIOCSETLG)");
372 static void flushfilter(arg
)
379 if (!strcmp(arg
, "s") || !strcmp(arg
, "S")) {
381 fl
= FLUSH_TABLE_ALL
;
383 fl
= FLUSH_TABLE_CLOSING
;
387 if (opendevice(IPSTATE_NAME
, 1) == -2)
390 if (!(opts
& OPT_DONOTHING
)) {
392 if (ioctl(fd
, SIOCIPFL6
, &fl
) == -1) {
393 perror("ioctl(SIOCIPFL6)");
397 if (ioctl(fd
, SIOCIPFFL
, &fl
) == -1) {
398 perror("ioctl(SIOCIPFFL)");
403 if ((opts
& (OPT_DONOTHING
|OPT_VERBOSE
)) == OPT_VERBOSE
) {
404 printf("remove flags %s (%d)\n", arg
, rem
);
405 printf("removed %d filter rules\n", fl
);
412 if (!strcmp(arg
, "u")) {
415 * Flush auth rules and packets
417 if (opendevice(IPL_AUTH
, 1) == -1)
418 perror("open(IPL_AUTH)");
420 if (ioctl(fd
, SIOCIPFFA
, &fl
) == -1)
421 perror("ioctl(SIOCIPFFA)");
428 if (strchr(arg
, 'i') || strchr(arg
, 'I'))
430 if (strchr(arg
, 'o') || strchr(arg
, 'O'))
432 if (strchr(arg
, 'a') || strchr(arg
, 'A'))
433 fl
= FR_OUTQUE
|FR_INQUE
;
434 if (opts
& OPT_INACTIVE
)
438 if (opendevice(ipfname
, 1) == -2)
441 if (!(opts
& OPT_DONOTHING
)) {
443 if (ioctl(fd
, SIOCIPFL6
, &fl
) == -1) {
444 perror("ioctl(SIOCIPFL6)");
448 if (ioctl(fd
, SIOCIPFFL
, &fl
) == -1) {
449 perror("ioctl(SIOCIPFFL)");
455 if ((opts
& (OPT_DONOTHING
|OPT_VERBOSE
)) == OPT_VERBOSE
) {
456 printf("remove flags %s%s (%d)\n", (rem
& FR_INQUE
) ? "I" : "",
457 (rem
& FR_OUTQUE
) ? "O" : "", rem
);
458 printf("removed %d filter rules\n", fl
);
464 static void swapactive()
468 if (opendevice(ipfname
, 1) != -2 && ioctl(fd
, SIOCSWAPA
, &in
) == -1)
469 perror("ioctl(SIOCSWAPA)");
471 printf("Set %d now inactive\n", in
);
479 if (opendevice(ipfname
, 1) != -2 && ioctl(fd
, SIOCFRSYN
, &frsyn
) == -1)
482 printf("filter sync'd\n");
489 friostat_t
*fiop
= &fio
;
491 if (opendevice(ipfname
, 1) != -2) {
492 if (ioctl(fd
, SIOCFRZST
, &fiop
) == -1) {
493 perror("ioctl(SIOCFRZST)");
503 * read the kernel stats for packets blocked and passed
505 static void showstats(fp
)
508 printf("bad packets:\t\tin %lu\tout %lu\n",
509 fp
->f_st
[0].fr_bad
, fp
->f_st
[1].fr_bad
);
510 printf(" input packets:\t\tblocked %lu passed %lu nomatch %lu",
511 fp
->f_st
[0].fr_block
, fp
->f_st
[0].fr_pass
,
513 printf(" counted %lu\n", fp
->f_st
[0].fr_acct
);
514 printf("output packets:\t\tblocked %lu passed %lu nomatch %lu",
515 fp
->f_st
[1].fr_block
, fp
->f_st
[1].fr_pass
,
517 printf(" counted %lu\n", fp
->f_st
[0].fr_acct
);
518 printf(" input packets logged:\tblocked %lu passed %lu\n",
519 fp
->f_st
[0].fr_bpkl
, fp
->f_st
[0].fr_ppkl
);
520 printf("output packets logged:\tblocked %lu passed %lu\n",
521 fp
->f_st
[1].fr_bpkl
, fp
->f_st
[1].fr_ppkl
);
522 printf(" packets logged:\tinput %lu-%lu output %lu-%lu\n",
523 fp
->f_st
[0].fr_pkl
, fp
->f_st
[0].fr_skip
,
524 fp
->f_st
[1].fr_pkl
, fp
->f_st
[1].fr_skip
);
528 static int showversion()
536 bzero((caddr_t
)&ipfo
, sizeof(ipfo
));
537 ipfo
.ipfo_rev
= IPFILTER_VERSION
;
538 ipfo
.ipfo_size
= sizeof(fio
);
539 ipfo
.ipfo_ptr
= (void *)&fio
;
540 ipfo
.ipfo_type
= IPFOBJ_IPFSTAT
;
542 printf("ipf: %s (%d)\n", IPL_VERSION
, (int)sizeof(frentry_t
));
544 if ((vfd
= open(ipfname
, O_RDONLY
)) == -1) {
545 perror("open device");
549 if (setzone(vfd
) != 0) {
554 if (ioctl(vfd
, SIOCGETFS
, &ipfo
)) {
555 perror("ioctl(SIOCGETFS)");
562 printf("Kernel: %-*.*s\n", (int)sizeof(fio
.f_version
),
563 (int)sizeof(fio
.f_version
), fio
.f_version
);
564 printf("Running: %s\n", (fio
.f_running
> 0) ? "yes" : "no");
565 printf("Log Flags: %#x = ", flags
);
567 if (flags
& FF_LOGPASS
) {
571 if (flags
& FF_LOGBLOCK
) {
572 printf("%sblock", s
);
575 if (flags
& FF_LOGNOMATCH
) {
576 printf("%snomatch", s
);
579 if (flags
& FF_BLOCKNONIP
) {
580 printf("%snonip", s
);
588 if (FR_ISPASS(fio
.f_defpass
))
590 else if (FR_ISBLOCK(fio
.f_defpass
))
593 s
= "nomatch -> block";
594 printf("%s all, Logging: %savailable\n", s
, fio
.f_logging
? "" : "un");
595 printf("Active list: %d\n", fio
.f_active
);
596 printf("Feature mask: %#x\n", fio
.f_features
);