--- sbin/ipfw/ipfw.8 Thu Sep 29 08:44:59 2005 +++ sbin/ipfw/ipfw.8 Thu Oct 6 16:14:34 2005 @@ -9,61 +9,108 @@ .Nd IP firewall and traffic shaper control program .Sh SYNOPSIS .Nm -.Op Fl cq +.Op Fl cCq +.Op Fl D Ar device +.Op Fl I Ar device .Cm add .Ar rule .Nm -.Op Fl acdefnNStT +.Op Fl acCdefnNStT +.Op Fl D Ar device +.Op Fl I Ar device .Brq Cm list | show .Op Ar rule | first-last ... .Nm .Op Fl f | q +.Op Fl C +.Op Fl D Ar device +.Op Fl I Ar device .Cm flush .Nm -.Op Fl q +.Op Fl qC +.Op Fl D Ar device +.Op Fl I Ar device .Brq Cm delete | zero | resetlog .Op Cm set .Op Ar number ... .Nm +.Op Fl C +.Op Fl D Ar device +.Op Fl I Ar device .Cm enable .Brq Cm firewall | altq | one_pass | debug | verbose | dyn_keepalive .Nm +.Op Fl C +.Op Fl D Ar device +.Op Fl I Ar device .Cm disable .Brq Cm firewall | altq | one_pass | debug | verbose | dyn_keepalive .Pp .Nm +.Op Fl C +.Op Fl D Ar device +.Op Fl I Ar device .Cm set Oo Cm disable Ar number ... Oc Op Cm enable Ar number ... .Nm +.Op Fl C +.Op Fl D Ar device +.Op Fl I Ar device .Cm set move .Op Cm rule .Ar number Cm to Ar number .Nm +.Op Fl C +.Op Fl D Ar device +.Op Fl I Ar device .Cm set swap Ar number number .Nm +.Op Fl C +.Op Fl D Ar device +.Op Fl I Ar device .Cm set show .Pp .Nm +.Op Fl C +.Op Fl D Ar device +.Op Fl I Ar device .Cm table Ar number Cm add Ar addr Ns Oo / Ns Ar masklen Oc Op Ar value .Nm +.Op Fl C +.Op Fl D Ar device +.Op Fl I Ar device .Cm table Ar number Cm delete Ar addr Ns Op / Ns Ar masklen .Nm +.Op Fl C +.Op Fl D Ar device +.Op Fl I Ar device .Cm table Ar number Cm flush .Nm +.Op Fl C +.Op Fl D Ar device +.Op Fl I Ar device .Cm table Ar number Cm list .Pp .Nm +.Op Fl C +.Op Fl D Ar device +.Op Fl I Ar device .Brq Cm pipe | queue .Ar number .Cm config .Ar config-options .Nm +.Op Fl C +.Op Fl D Ar device +.Op Fl I Ar device .Op Fl s Op Ar field .Brq Cm pipe | queue .Brq Cm delete | list | show .Op Ar number ... .Pp .Nm -.Op Fl cfnNqS +.Op Fl cCfnNqS +.Op Fl D Ar device +.Op Fl I Ar device .Oo .Fl p Ar preproc .Oo @@ -199,8 +246,16 @@ When entering or showing rules, print them in compact form, i.e., without the optional "ip from any to any" string when this does not carry any additional information. +.It Fl C +Use the device file /dev/ipfwctl or specified through +.Cm Fl I +option instead of using a RAW socket control interface. .It Fl d While listing, show dynamic rules in addition to static ones. +.It Fl D Ar device +Use the device file +.Cm device +for dummynet instead of the default /dev/dnctl. .It Fl e While listing, if the .Fl d @@ -215,6 +270,10 @@ them to the kernel. .It Fl N Try to resolve addresses and service names in output. +.It Fl I Ar device +Use the device file +.Cm device +instead of the default /dev/ipfwctl. .It Fl q While .Cm add Ns ing , --- sbin/ipfw/ipfw2.c Thu Sep 29 08:44:59 2005 +++ sbin/ipfw/ipfw2.c Fri Oct 7 09:25:26 2005 @@ -57,10 +57,13 @@ #include #include #include +#include +#include #include #include int + do_ioctl, /* Use ioctl instead sockopt */ do_resolv, /* Would try to resolve all */ do_time, /* Show time stamps */ do_quiet, /* Be quiet in add and flush */ @@ -75,6 +78,12 @@ comment_only, /* only print action and comment */ verbose; +char *ipfw_ioctl_dev = "/dev/ipfwctl"; +char *dummynet_ioctl_dev = "/dev/dnctl"; + +#define IOCTLSCMD do_ioctl ? "ioctl(SCMD)/":"setsockopt" +#define IOCTLGCMD do_ioctl ? "ioctl(GCMD)/":"getsockopt" + #define IP_MASK_ALL 0xffffffff /* * the following macro returns an error message if we run out of @@ -428,6 +437,65 @@ return ret; } +static int +do_ctl(int optname, void* optval, uintptr_t optlen) +{ + static int fw_dev = -1; /* ipfw control device */ + static int dn_dev = -1; /* dummynet control device */ + struct ip_fw_ctl fw_ctl; + struct ip_dummynet_ctl dn_ctl; + int i; + + if (fw_dev == -1) { + for(i = O_RDWR; i >= O_RDONLY; i--) { + fw_dev = open(ipfw_ioctl_dev, i); + if (fw_dev != -1) + break; + if (errno != EACCES) + err(1, "%s", ipfw_ioctl_dev); + } + } + if (dn_dev == -1 && + ( optname == IP_DUMMYNET_GET || optname == IP_DUMMYNET_DEL || + optname == IP_DUMMYNET_FLUSH || optname == IP_DUMMYNET_CONFIGURE)) + { + for(i = O_RDWR; i >= O_RDONLY; i--) { + dn_dev = open(dummynet_ioctl_dev, i); + if (dn_dev != -1) + break; + if (errno != EACCES) + err(1, "%s", dummynet_ioctl_dev); + } + if (dn_dev < 0) + err(1,"%s", dummynet_ioctl_dev); + + dn_ctl.opcode = optname; + dn_ctl.value = optval; + dn_ctl.valsize = optlen; + + if (optname == IP_DUMMYNET_GET) + return ioctl(dn_dev, IPDNIOCGCMD, &dn_ctl); + else + return ioctl(dn_dev, IPDNIOCSCMD, &dn_ctl); + } + + if (fw_dev < 0) + err(1,"%s", ipfw_ioctl_dev); + + fw_ctl.opcode = optname; + fw_ctl.value = optval; + fw_ctl.valsize = optlen; + + if (optname == IP_FW_GET || optname == IP_FW_ADD || + optname == IP_FW_TABLE_LIST || optname == IP_FW_TABLE_GETSIZE) + { + i = ioctl(fw_dev, IPFWIOCGCMD, &fw_ctl); + } else { + i = ioctl(fw_dev, IPFWIOCSCMD, &fw_ctl); + } + + return i; +} /* * conditionally runs the command. */ @@ -440,6 +508,9 @@ if (test_only) return 0; + if (do_ioctl) + return do_ctl(optname, optval, optlen); + if (s == -1) s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (s < 0) @@ -2249,7 +2320,7 @@ if ((data = calloc(1, nbytes)) == NULL) err(EX_OSERR, "calloc"); if (do_cmd(IP_FW_GET, data, (uintptr_t)&nbytes) < 0) - err(EX_OSERR, "getsockopt(IP_FW_GET)"); + err(EX_OSERR, "%s(IP_FW_GET)", IOCTLGCMD); bcopy(&((struct ip_fw *)data)->next_rule, &set_disable, sizeof(set_disable)); @@ -2324,7 +2395,7 @@ i = do_cmd(IP_FW_DEL, masks, sizeof(masks)); if (i) - warn("set enable/disable: setsockopt(IP_FW_DEL)"); + warn("set enable/disable: %s(IP_FW_DEL)",IOCTLSCMD); } else errx(EX_USAGE, "invalid set command %s\n", *av); } @@ -2398,7 +2469,7 @@ if ((data = realloc(data, nbytes)) == NULL) err(EX_OSERR, "realloc"); if (do_cmd(ocmd, data, (uintptr_t)&nbytes) < 0) - err(EX_OSERR, "getsockopt(IP_%s_GET)", + err(EX_OSERR, "%s(IP_%s_GET)",IOCTLGCMD, do_pipe ? "DUMMYNET" : "FW"); } @@ -2541,7 +2612,7 @@ { fprintf(stderr, "ipfw syntax summary (but please do read the ipfw(8) manpage):\n" -"ipfw [-abcdefhnNqStTv] where is one of:\n" +"ipfw [-abcCdDefhInNpqStTv] where is one of:\n" "add [num] [set N] [prob x] RULE-BODY\n" "{pipe|queue} N config PIPE-BODY\n" "[pipe|queue] {zero|delete|show} [N{,N}]\n" @@ -3068,16 +3139,17 @@ i = do_cmd(IP_DUMMYNET_DEL, &p, sizeof p); if (i) { exitval = 1; - warn("rule %u: setsockopt(IP_DUMMYNET_DEL)", - do_pipe == 1 ? p.pipe_nr : p.fs.fs_nr); + warn("rule %u: %s(IP_DUMMYNET_DEL)", + do_pipe == 1 ? p.pipe_nr : p.fs.fs_nr, + IOCTLSCMD); } } else { rulenum = (i & 0xffff) | (do_set << 24); i = do_cmd(IP_FW_DEL, &rulenum, sizeof rulenum); if (i) { exitval = EX_UNAVAILABLE; - warn("rule %u: setsockopt(IP_FW_DEL)", - rulenum); + warn("rule %u: %s(IP_FW_DEL)", + rulenum, IOCTLSCMD); } } } @@ -3464,7 +3536,7 @@ } i = do_cmd(IP_DUMMYNET_CONFIGURE, &p, sizeof p); if (i) - err(1, "setsockopt(%s)", "IP_DUMMYNET_CONFIGURE"); + err(1, "%s(%s)", IOCTLSCMD,"IP_DUMMYNET_CONFIGURE"); } static void @@ -4653,7 +4725,7 @@ rule->cmd_len = (uint32_t *)dst - (uint32_t *)(rule->cmd); i = (char *)dst - (char *)rule; if (do_cmd(IP_FW_ADD, rule, (uintptr_t)&i) == -1) - err(EX_UNAVAILABLE, "getsockopt(%s)", "IP_FW_ADD"); + err(EX_UNAVAILABLE, "%s(%s)", IOCTLGCMD, "IP_FW_ADD"); if (!do_quiet) show_ipfw(rule, 0, 0); } @@ -4670,7 +4742,7 @@ if (!ac) { /* clear all entries */ if (do_cmd(optname, NULL, 0) < 0) - err(EX_UNAVAILABLE, "setsockopt(IP_FW_%s)", name); + err(EX_UNAVAILABLE, "%s(IP_FW_%s)", IOCTLSCMD, name); if (!do_quiet) printf("%s.\n", optname == IP_FW_ZERO ? "Accounting cleared":"Logging counts reset"); @@ -4685,8 +4757,8 @@ av++; ac--; if (do_cmd(optname, &rulenum, sizeof rulenum)) { - warn("rule %u: setsockopt(IP_FW_%s)", - rulenum, name); + warn("rule %u: %s(IP_FW_%s)", + rulenum, IOCTLSCMD, name); failed = EX_UNAVAILABLE; } else if (!do_quiet) printf("Entry %d %s.\n", rulenum, @@ -4721,7 +4793,7 @@ return; } if (do_cmd(cmd, NULL, 0) < 0) - err(EX_UNAVAILABLE, "setsockopt(IP_%s_FLUSH)", + err(EX_UNAVAILABLE, "%s(IP_%s_FLUSH)", IOCTLSCMD, do_pipe ? "DUMMYNET" : "FW"); if (!do_quiet) printf("Flushed all %s.\n", do_pipe ? "pipes" : "rules"); @@ -4787,23 +4859,23 @@ ent.value = 0; if (do_cmd(do_add ? IP_FW_TABLE_ADD : IP_FW_TABLE_DEL, &ent, sizeof(ent)) < 0) - err(EX_OSERR, "setsockopt(IP_FW_TABLE_%s)", + err(EX_OSERR, "%s(IP_FW_TABLE_%s)", IOCTLSCMD, do_add ? "ADD" : "DEL"); } else if (_substrcmp(*av, "flush") == 0) { if (do_cmd(IP_FW_TABLE_FLUSH, &ent.tbl, sizeof(ent.tbl)) < 0) - err(EX_OSERR, "setsockopt(IP_FW_TABLE_FLUSH)"); + err(EX_OSERR, "%s(IP_FW_TABLE_FLUSH)", IOCTLSCMD); } else if (_substrcmp(*av, "list") == 0) { a = ent.tbl; l = sizeof(a); if (do_cmd(IP_FW_TABLE_GETSIZE, &a, (uintptr_t)&l) < 0) - err(EX_OSERR, "getsockopt(IP_FW_TABLE_GETSIZE)"); + err(EX_OSERR, "%s(IP_FW_TABLE_GETSIZE)", IOCTLGCMD); l = sizeof(*tbl) + a * sizeof(ipfw_table_entry); tbl = malloc(l); if (tbl == NULL) err(EX_OSERR, "malloc"); tbl->tbl = ent.tbl; if (do_cmd(IP_FW_TABLE_LIST, tbl, (uintptr_t)&l) < 0) - err(EX_OSERR, "getsockopt(IP_FW_TABLE_LIST)"); + err(EX_OSERR, "%s(IP_FW_TABLE_LIST)", IOCTLGCMD); for (a = 0; a < tbl->cnt; a++) { printf("%s/%u %u\n", inet_ntoa(*(struct in_addr *)&tbl->ent[a].addr), @@ -4915,7 +4987,7 @@ save_av = av; optind = optreset = 0; - while ((ch = getopt(ac, av, "abcdefhnNqs:STtv")) != -1) + while ((ch = getopt(ac, av, "abcCdDefhInNqs:STtv")) != -1) switch (ch) { case 'a': do_acct = 1; @@ -4930,10 +5002,20 @@ do_compact = 1; break; + case 'C': /* use ioctl instead sockopt */ + do_ioctl = 1; + break; + case 'd': do_dynamic = 1; break; + case 'D': + do_ioctl = 1; + dummynet_ioctl_dev = optarg; /* dummynet ioctl device name */ + ac--; av++; + break; + case 'e': do_expired = 1; break; @@ -4947,6 +5029,12 @@ help(); break; /* NOTREACHED */ + case 'I': + do_ioctl = 1; + ipfw_ioctl_dev = optarg; /* ipfw ioctl device name */ + ac--; av++; + break; + case 'n': test_only = 1; break; @@ -5072,14 +5160,30 @@ filename = av[ac-1]; - while ((c = getopt(ac, av, "cfNnp:qS")) != -1) { + while ((c = getopt(ac, av, "cCDfINnp:qS")) != -1) { switch(c) { case 'c': do_compact = 1; break; + case 'C': + do_ioctl = 1; + break; + + case 'D': + do_ioctl = 1; + dummynet_ioctl_dev = optarg; /* dummynet ioctl device name */ + ac--; av++; + break; + case 'f': do_force = 1; + break; + + case 'I': + do_ioctl = 1; + ipfw_ioctl_dev = optarg; /* ipfw ioctl device name */ + ac--; av++; break; case 'N':