2 * Copyright (c) 2002 Luigi Rizzo
3 * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
4 * Copyright (c) 1994 Ugen J.S.Antsilevich
6 * Idea and grammar partially left from:
7 * Copyright (c) 1993 Daniel Boulet
9 * Redistribution and use in source forms, with and without modification,
10 * are permitted provided that this entire comment appears intact.
12 * Redistribution in binary form may occur without any restrictions.
13 * Obviously, it would be nice if you gave credit where credit is due
14 * but requiring it would be too onerous.
16 * This software is provided ``AS IS'' without any warranties of any kind.
18 * NEW command line interface for IP firewall facility
20 * $FreeBSD: src/sbin/ipfw/ipfw2.c,v 1.4.2.13 2003/05/27 22:21:11 gshapiro Exp $
23 #include <sys/param.h>
25 #include <sys/socket.h>
26 #include <sys/sockio.h>
27 #include <sys/sysctl.h>
31 #include <arpa/inet.h>
49 #include <netinet/in.h>
50 #include <netinet/in_systm.h>
51 #include <netinet/ip.h>
52 #include <netinet/ip_icmp.h>
53 #include <netinet/tcp.h>
55 #include <net/if_dl.h>
56 #include <net/route.h>
57 #include <net/ethernet.h>
60 #include "../../sys/net/ipfw3/ip_fw3.h"
61 #include "../../sys/net/dummynet3/ip_dummynet3.h"
62 #include "../../sys/net/libalias/alias.h"
63 #include "../../sys/net/ipfw3_basic/ip_fw3_basic.h"
64 #include "../../sys/net/ipfw3_nat/ip_fw3_nat.h"
68 #define KEYWORD_SIZE 256
69 #define MAPPING_SIZE 256
71 #define MAX_KEYWORD_LEN 20
73 #define WHITESP " \t\f\v\n\r"
74 #define IPFW_LIB_PATH "/usr/lib/libipfw3%s.so"
75 #define IP_MASK_ALL 0xffffffff
76 #define NAT_BUF_LEN 1024
78 * we use IPPROTO_ETHERTYPE as a fake protocol id to call the print routines
79 * This is only used in this code.
81 #define IPPROTO_ETHERTYPE 0x1000
84 * This macro returns the size of a struct sockaddr when passed
85 * through a routing socket. Basically we round up sa_len to
86 * a multiple of sizeof(long), with a minimum of sizeof(long).
87 * The check for a NULL pointer is just a convenience, probably never used.
88 * The case sa_len == 0 should only apply to empty structures.
91 ( (!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? \
93 1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) )
96 * show_rules() prints the body of an ipfw rule.
97 * Because the standard rule has at least proto src_ip dst_ip, we use
98 * a helper function to produce these entries if not provided explicitly.
99 * The first argument is the list of fields we have, the second is
100 * the list of fields we want to be printed.
102 * Special cases if we have provided a MAC header:
103 * + if the rule does not contain IP addresses/ports, do not print them;
104 * + if the rule does not contain an IP proto, print "all" instead of "ip";
107 #define HAVE_PROTO 0x0001
108 #define HAVE_SRCIP 0x0002
109 #define HAVE_DSTIP 0x0004
110 #define HAVE_MAC 0x0008
111 #define HAVE_MACTYPE 0x0010
112 #define HAVE_OPTIONS 0x8000
114 #define HAVE_IP (HAVE_PROTO | HAVE_SRCIP | HAVE_DSTIP)
117 * Definition of a port range, and macros to deal with values.
118 * FORMAT: HI 16-bits == first port in range, 0 == all ports.
119 * LO 16-bits == number of ports in range
120 * NOTES: - Port values are not stored in network byte order.
123 #define port_range u_long
125 #define GETLOPORT(x) ((x) >> 0x10)
126 #define GETNUMPORTS(x) ((x) & 0x0000ffff)
127 #define GETHIPORT(x) (GETLOPORT((x)) + GETNUMPORTS((x)))
129 /* Set y to be the low-port value in port_range variable x. */
130 #define SETLOPORT(x, y) ((x) = ((x) & 0x0000ffff) | ((y) << 0x10))
132 /* Set y to be the number of ports in port_range variable x. */
133 #define SETNUMPORTS(x, y) ((x) = ((x) & 0xffff0000) | (y))
135 #define INC_ARGCV() do { \
143 int ipfw_socket = -1; /* main RAW socket */
144 int do_resolv, /* Would try to resolve all */
145 do_acct, /* Show packet/byte count */
146 do_time, /* Show time stamps */
147 do_quiet = 1, /* Be quiet , default is quiet*/
148 do_force, /* Don't ask for confirmation */
149 do_pipe, /* this cmd refers to a pipe */
150 do_nat, /* Nat configuration. */
151 do_sort, /* field to sort results (0 = no) */
152 do_dynamic, /* display dynamic rules */
153 do_expired, /* display expired dynamic rules */
154 do_compact, /* show rules in compact mode */
155 show_sets, /* display rule sets */
194 struct char_int_map dummynet_params[] = {
196 { "noerror", TOK_NOERROR },
197 { "buckets", TOK_BUCKETS },
198 { "dst-ip", TOK_DSTIP },
199 { "src-ip", TOK_SRCIP },
200 { "dst-port", TOK_DSTPORT },
201 { "src-port", TOK_SRCPORT },
202 { "proto", TOK_PROTO },
203 { "weight", TOK_WEIGHT },
205 { "mask", TOK_MASK },
206 { "droptail", TOK_DROPTAIL },
208 { "gred", TOK_GRED },
210 { "bandwidth", TOK_BW },
211 { "delay", TOK_DELAY },
212 { "pipe", TOK_PIPE },
213 { "queue", TOK_QUEUE },
214 { "dummynet-params", TOK_NULL },
218 struct char_int_map nat_params[] = {
222 { "deny_in", TOK_DENY_INC },
223 { "same_ports", TOK_SAME_PORTS },
224 { "unreg_only", TOK_UNREG_ONLY },
225 { "reset", TOK_RESET_ADDR },
226 { "reverse", TOK_ALIAS_REV },
227 { "proxy_only", TOK_PROXY_ONLY },
228 { "redirect_addr", TOK_REDIR_ADDR },
229 { "redirect_port", TOK_REDIR_PORT },
230 { "redirect_proto", TOK_REDIR_PROTO },
234 struct ipfw_keyword {
236 char word[MAX_KEYWORD_LEN];
241 struct ipfw_mapping {
249 struct ipfw_keyword keywords[KEYWORD_SIZE];
250 struct ipfw_mapping mappings[MAPPING_SIZE];
253 match_token(struct char_int_map *table, char *string)
256 if (strcmp(table->key, string) == 0) {
265 get_modules(char *modules_str, int len)
267 if (do_get_x(IP_FW_MODULE, modules_str, &len) < 0)
268 errx(EX_USAGE, "ipfw3 not loaded.");
272 list_modules(int ac, char *av[])
274 void *module_str = NULL;
276 if ((module_str = realloc(module_str, len)) == NULL)
277 err(EX_OSERR, "realloc");
279 get_modules(module_str, len);
280 printf("%s", (char *)module_str);
283 parse_accept(ipfw_insn **cmd, int *ac, char **av[])
285 (*cmd)->opcode = O_BASIC_ACCEPT;
286 (*cmd)->module = MODULE_BASIC_ID;
287 (*cmd)->len = (*cmd)->len|LEN_OF_IPFWINSN;
292 parse_deny(ipfw_insn **cmd, int *ac, char **av[])
294 (*cmd)->opcode = O_BASIC_DENY;
295 (*cmd)->module = MODULE_BASIC_ID;
296 (*cmd)->len = (*cmd)->len|LEN_OF_IPFWINSN;
301 show_accept(ipfw_insn *cmd)
307 show_deny(ipfw_insn *cmd)
316 init_module mod_init_func;
318 char module_lib_file[50];
319 void *module_str = NULL;
322 if ((module_str = realloc(module_str, len)) == NULL)
323 err(EX_OSERR, "realloc");
325 get_modules(module_str, len);
327 const char s[2] = ",";
329 token = strtok(module_str, s);
330 while (token != NULL) {
331 sprintf(module_lib_file, IPFW_LIB_PATH, token);
332 token = strtok(NULL, s);
333 module_lib = dlopen(module_lib_file, RTLD_LAZY);
335 fprintf(stderr, "Couldn't open %s: %s\n",
336 module_lib_file, dlerror());
339 mod_init_func = dlsym(module_lib, "load_module");
340 if ((error = dlerror()))
342 fprintf(stderr, "Couldn't find init function: %s\n", error);
345 (*mod_init_func)((register_func)register_ipfw_func,
346 (register_keyword)register_ipfw_keyword);
351 prepare_default_funcs()
354 register_ipfw_keyword(MODULE_BASIC_ID, O_BASIC_ACCEPT,
355 "allow", IPFW_KEYWORD_TYPE_ACTION);
356 register_ipfw_keyword(MODULE_BASIC_ID, O_BASIC_ACCEPT,
357 "accept", IPFW_KEYWORD_TYPE_ACTION);
358 register_ipfw_func(MODULE_BASIC_ID, O_BASIC_ACCEPT,
359 (parser_func)parse_accept, (shower_func)show_accept);
361 register_ipfw_keyword(MODULE_BASIC_ID, O_BASIC_DENY, "deny",
362 IPFW_KEYWORD_TYPE_ACTION);
363 register_ipfw_keyword(MODULE_BASIC_ID, O_BASIC_DENY, "reject",
364 IPFW_KEYWORD_TYPE_ACTION);
365 register_ipfw_func(MODULE_BASIC_ID, O_BASIC_DENY,
366 (parser_func)parse_deny, (shower_func)show_deny);
370 register_ipfw_keyword(int module, int opcode, char *word, int type)
372 struct ipfw_keyword *tmp;
376 if (tmp->type == IPFW_KEYWORD_TYPE_NONE) {
377 strcpy(tmp->word, word);
378 tmp->module = module;
379 tmp->opcode = opcode;
383 if (strcmp(tmp->word, word) == 0)
384 errx(EX_USAGE, "keyword `%s' exists", word);
392 register_ipfw_func(int module, int opcode, parser_func parser, shower_func shower)
394 struct ipfw_mapping *tmp;
398 if (tmp->type == IPFW_MAPPING_TYPE_NONE) {
399 tmp->module = module;
400 tmp->opcode = opcode;
401 tmp->parser = parser;
402 tmp->shower = shower;
403 tmp->type = IPFW_MAPPING_TYPE_IN_USE;
406 if (tmp->opcode == opcode && tmp->module == module) {
407 errx(EX_USAGE, "func `%d' of module `%d' exists",
418 show_rules(struct ipfw_ioc_rule *rule, int pcwidth, int bcwidth)
420 static int twidth = 0;
422 int l, or_block = 0; /* we are in an or block */
424 u_int32_t set_disable = rule->set_disable;
426 if (set_disable & (1 << rule->set)) { /* disabled */
430 printf("# DISABLED ");
432 printf("%05u ", rule->rulenum);
435 printf("%*ju %*ju ", pcwidth, (uintmax_t)rule->pcnt, bcwidth,
436 (uintmax_t)rule->bcnt);
442 strcpy(timestr, ctime((time_t *)&twidth));
443 *strchr(timestr, '\n') = '\0';
444 twidth = strlen(timestr);
446 if (rule->timestamp) {
447 time_t t = _long_to_time(rule->timestamp);
449 strcpy(timestr, ctime(&t));
450 *strchr(timestr, '\n') = '\0';
451 printf("%s ", timestr);
453 printf("%*s ", twidth, " ");
455 } else if (do_time == 2) {
456 printf( "%10u ", rule->timestamp);
460 printf("set %d ", rule->set);
463 struct ipfw_keyword *k;
464 struct ipfw_mapping *m;
465 shower_func fn, comment_fn = NULL;
466 ipfw_insn *comment_cmd;
470 * show others and actions
472 for (l = rule->cmd_len - rule->act_ofs, cmd = ACTION_PTR(rule);
473 l > 0; l -= F_LEN(cmd),
474 cmd = (ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) {
477 for (i = 1; i< KEYWORD_SIZE; i++, k++) {
478 if ( k->module == cmd->module && k->opcode == cmd->opcode ) {
479 for (j = 1; j< MAPPING_SIZE; j++, m++) {
480 if (m->type == IPFW_MAPPING_TYPE_IN_USE &&
481 m->module == cmd->module &&
482 m->opcode == cmd->opcode) {
483 if (cmd->module == MODULE_BASIC_ID &&
484 cmd->opcode == O_BASIC_COMMENT) {
485 comment_fn = m->shower;
491 if (cmd->module == MODULE_BASIC_ID &&
493 O_BASIC_CHECK_STATE) {
508 for (l = rule->act_ofs, cmd = rule->cmd;
509 l > 0;l -= F_LEN(cmd) ,
510 cmd = (ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) {
513 for (i = 1; i< KEYWORD_SIZE; i++, k++) {
514 if (k->type == IPFW_KEYWORD_TYPE_FILTER &&
515 strcmp(k->word, "proto") == 0) {
516 if (k->module == cmd->module &&
517 k->opcode == cmd->opcode) {
518 for (j = 1; j< MAPPING_SIZE; j++, m++) {
519 if (m->type == IPFW_MAPPING_TYPE_IN_USE &&
520 k->module == m->module &&
521 k->opcode == m->opcode) {
522 if (cmd->len & F_NOT) {
535 if (!changed && !do_quiet)
543 for (l = rule->act_ofs, cmd = rule->cmd;
544 l > 0; l -= F_LEN(cmd),
545 cmd = (ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) {
548 for (i = 1; i< KEYWORD_SIZE; i++, k++) {
549 if (k->type == IPFW_KEYWORD_TYPE_FILTER &&
550 strcmp(k->word, "from") == 0) {
551 if (k->module == cmd->module &&
552 k->opcode == cmd->opcode) {
553 for (j = 1; j< MAPPING_SIZE; j++, m++) {
554 if (m->type == IPFW_MAPPING_TYPE_IN_USE &&
555 k->module == m->module &&
556 k->opcode == m->opcode) {
557 if (cmd->len & F_NOT)
570 if (!changed && !do_quiet)
578 for (l = rule->act_ofs, cmd = rule->cmd;
579 l > 0; l -= F_LEN(cmd),
580 cmd = (ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) {
583 for (i = 1; i< KEYWORD_SIZE; i++, k++) {
584 if (k->type == IPFW_KEYWORD_TYPE_FILTER &&
585 strcmp(k->word, "to") == 0) {
586 if (k->module == cmd->module &&
587 k->opcode == cmd->opcode) {
588 for (j = 1; j < MAPPING_SIZE; j++, m++) {
589 if (m->type == IPFW_MAPPING_TYPE_IN_USE &&
590 k->module == m->module &&
591 k->opcode == m->opcode ) {
592 if (cmd->len & F_NOT)
605 if (!changed && !do_quiet)
612 for (l = rule->act_ofs, cmd = rule->cmd, m = mappings;
613 l > 0; l -= F_LEN(cmd),
614 cmd=(ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) {
617 for (i = 1; i< KEYWORD_SIZE; i++, k++) {
618 if (k->module == cmd->module && k->opcode == cmd->opcode) {
619 if (strcmp(k->word, "proto") != 0 &&
620 strcmp(k->word, "from") !=0 &&
621 strcmp(k->word, "to") !=0) {
622 for (j = 1; j < MAPPING_SIZE; j++, m++) {
623 if (m->module == cmd->module &&
624 m->opcode == cmd->opcode) {
625 if (cmd->len & F_NOT)
638 if (cmd->len & F_OR) {
641 } else if (or_block) {
646 /* show the comment in the end */
647 if (comment_fn != NULL) {
648 (*comment_fn)(comment_cmd);
655 show_states(struct ipfw_ioc_state *d, int pcwidth, int bcwidth)
660 printf("%05u ", d->rulenum);
662 printf("%*ju %*ju ", pcwidth, (uintmax_t)d->pcnt,
663 bcwidth, (uintmax_t)d->bcnt);
667 /* state->timestamp */
669 time_t t = _long_to_time(d->timestamp);
670 strcpy(timestr, ctime(&t));
671 *strchr(timestr, '\n') = '\0';
672 printf(" (%s", timestr);
674 /* state->lifetime */
675 printf(" %ds", d->lifetime);
679 t = _long_to_time(d->expiry);
680 strcpy(timestr, ctime(&t));
681 *strchr(timestr, '\n') = '\0';
682 printf(" %s)", timestr);
687 } else if (do_time == 2) {
688 printf("(%u %ds %u) ", d->timestamp, d->lifetime, d->expiry);
691 if ((pe = getprotobynumber(d->flow_id.proto)) != NULL)
692 printf(" %s", pe->p_name);
694 printf(" proto %u", d->flow_id.proto);
696 a.s_addr = htonl(d->flow_id.src_ip);
697 printf(" %s %d", inet_ntoa(a), d->flow_id.src_port);
699 a.s_addr = htonl(d->flow_id.dst_ip);
700 printf(" <-> %s %d", inet_ntoa(a), d->flow_id.dst_port);
701 printf(" CPU %d", d->cpuid);
706 sort_q(const void *pa, const void *pb)
708 int rev = (do_sort < 0);
709 int field = rev ? -do_sort : do_sort;
711 const struct dn_ioc_flowqueue *a = pa;
712 const struct dn_ioc_flowqueue *b = pb;
716 res = a->len - b->len;
719 res = a->len_bytes - b->len_bytes;
722 case 3: /* tot pkts */
723 res = a->tot_pkts - b->tot_pkts;
726 case 4: /* tot bytes */
727 res = a->tot_bytes - b->tot_bytes;
734 return (int)(rev ? res : -res);
738 show_queues(struct dn_ioc_flowset *fs, struct dn_ioc_flowqueue *q)
742 printf("mask: 0x%02x 0x%08x/0x%04x -> 0x%08x/0x%04x\n",
743 fs->flow_mask.u.ip.proto,
744 fs->flow_mask.u.ip.src_ip, fs->flow_mask.u.ip.src_port,
745 fs->flow_mask.u.ip.dst_ip, fs->flow_mask.u.ip.dst_port);
746 if (fs->rq_elements == 0)
749 printf("BKT Prot ___Source IP/port____ "
750 "____Dest. IP/port____ Tot_pkt/bytes Pkt/Byte Drp\n");
752 heapsort(q, fs->rq_elements, sizeof(*q), sort_q);
753 for (l = 0; l < fs->rq_elements; l++) {
757 ina.s_addr = htonl(q[l].id.u.ip.src_ip);
758 printf("%3d ", q[l].hash_slot);
759 pe = getprotobynumber(q[l].id.u.ip.proto);
761 printf("%-4s ", pe->p_name);
763 printf("%4u ", q[l].id.u.ip.proto);
765 inet_ntoa(ina), q[l].id.u.ip.src_port);
766 ina.s_addr = htonl(q[l].id.u.ip.dst_ip);
768 inet_ntoa(ina), q[l].id.u.ip.dst_port);
769 printf("%4ju %8ju %2u %4u %3u\n",
770 (uintmax_t)q[l].tot_pkts, (uintmax_t)q[l].tot_bytes,
771 q[l].len, q[l].len_bytes, q[l].drops);
773 printf(" S %20ju F %20ju\n",
774 (uintmax_t)q[l].S, (uintmax_t)q[l].F);
779 show_flowset_parms(struct dn_ioc_flowset *fs, char *prefix)
783 char red[90]; /* Display RED parameters */
787 if (fs->flags_fs & DN_QSIZE_IS_BYTES) {
789 sprintf(qs, "%d KB", l / 1024);
791 sprintf(qs, "%d B", l);
793 sprintf(qs, "%3d sl.", l);
795 sprintf(plr, "plr %f", 1.0 * fs->plr / (double)(0x7fffffff));
798 if (fs->flags_fs & DN_IS_RED) /* RED parameters */
800 "\n\t %cRED w_q %f min_th %d max_th %d max_p %f",
801 (fs->flags_fs & DN_IS_GENTLE_RED) ? 'G' : ' ',
802 1.0 * fs->w_q / (double)(1 << SCALE_RED),
803 SCALE_VAL(fs->min_th),
804 SCALE_VAL(fs->max_th),
805 1.0 * fs->max_p / (double)(1 << SCALE_RED));
807 sprintf(red, "droptail");
809 printf("%s %s%s %d queues (%d buckets) %s\n",
810 prefix, qs, plr, fs->rq_elements, fs->rq_size, red);
814 show_pipes(void *data, int nbytes, int ac, char *av[])
818 struct dn_ioc_pipe *p = (struct dn_ioc_pipe *)data;
819 struct dn_ioc_flowset *fs;
820 struct dn_ioc_flowqueue *q;
824 rulenum = strtoul(*av++, NULL, 10);
827 for (; nbytes >= sizeof(*p); p = (struct dn_ioc_pipe *)next) {
828 double b = p->bandwidth;
832 if (p->fs.fs_type != DN_IS_PIPE)
833 break; /* done with pipes, now queues */
836 * compute length, as pipe have variable size
838 l = sizeof(*p) + p->fs.rq_elements * sizeof(*q);
839 next = (void *)p + l;
842 if (rulenum != 0 && rulenum != p->pipe_nr)
849 sprintf(buf, "unlimited");
850 else if (b >= 1000000)
851 sprintf(buf, "%7.3f Mbit/s", b/1000000);
853 sprintf(buf, "%7.3f Kbit/s", b/1000);
855 sprintf(buf, "%7.3f bit/s ", b);
857 sprintf(prefix, "%05d: %s %4d ms ",
858 p->pipe_nr, buf, p->delay);
859 show_flowset_parms(&p->fs, prefix);
861 printf(" V %20ju\n", (uintmax_t)p->V >> MY_M);
863 q = (struct dn_ioc_flowqueue *)(p+1);
864 show_queues(&p->fs, q);
867 for (fs = next; nbytes >= sizeof(*fs); fs = next) {
870 if (fs->fs_type != DN_IS_QUEUE)
872 l = sizeof(*fs) + fs->rq_elements * sizeof(*q);
873 next = (void *)fs + l;
875 q = (struct dn_ioc_flowqueue *)(fs+1);
876 sprintf(prefix, "q%05d: weight %d pipe %d ",
877 fs->fs_nr, fs->weight, fs->parent_nr);
878 show_flowset_parms(fs, prefix);
884 * This one handles all set-related commands
885 * ipfw set { show | enable | disable }
887 * ipfw set move X to Y
888 * ipfw set move rule X to Y
891 sets_handler(int ac, char *av[])
893 u_int32_t set_disable, masks[2];
895 u_int8_t cmd, new_set;
900 errx(EX_USAGE, "set needs command");
901 if (!strncmp(*av, "show", strlen(*av)) ) {
907 while (nbytes >= nalloc) {
908 nalloc = nalloc * 2+321;
911 if ((data = malloc(nbytes)) == NULL) {
912 err(EX_OSERR, "malloc");
914 } else if ((data = realloc(data, nbytes)) == NULL) {
915 err(EX_OSERR, "realloc");
917 if (do_get_x(IP_FW_GET, data, &nbytes) < 0) {
918 err(EX_OSERR, "getsockopt(IP_FW_GET)");
921 set_disable = ((struct ipfw_ioc_rule *)data)->set_disable;
922 for (i = 0, msg = "disable" ; i < 31; i++)
923 if ( (set_disable & (1<<i))) {
924 printf("%s %d", msg, i);
927 msg = (set_disable) ? " enable" : "enable";
928 for (i = 0; i < 31; i++)
929 if ( !(set_disable & (1<<i))) {
930 printf("%s %d", msg, i);
934 } else if (!strncmp(*av, "swap", strlen(*av))) {
937 errx(EX_USAGE, "set swap needs 2 set numbers\n");
938 rulenum = atoi(av[0]);
939 new_set = atoi(av[1]);
940 if (!isdigit(*(av[0])) || rulenum > 30)
941 errx(EX_DATAERR, "invalid set number %s\n", av[0]);
942 if (!isdigit(*(av[1])) || new_set > 30)
943 errx(EX_DATAERR, "invalid set number %s\n", av[1]);
944 masks[0] = (4 << 24) | (new_set << 16) | (rulenum);
945 i = do_set_x(IP_FW_DEL, masks, sizeof(u_int32_t));
946 } else if (!strncmp(*av, "move", strlen(*av))) {
948 if (ac && !strncmp(*av, "rule", strlen(*av))) {
953 if (ac != 3 || strncmp(av[1], "to", strlen(*av)))
954 errx(EX_USAGE, "syntax: set move [rule] X to Y\n");
955 rulenum = atoi(av[0]);
956 new_set = atoi(av[2]);
957 if (!isdigit(*(av[0])) || (cmd == 3 && rulenum > 30) ||
958 (cmd == 2 && rulenum == 65535) )
959 errx(EX_DATAERR, "invalid source number %s\n", av[0]);
960 if (!isdigit(*(av[2])) || new_set > 30)
961 errx(EX_DATAERR, "invalid dest. set %s\n", av[1]);
962 masks[0] = (cmd << 24) | (new_set << 16) | (rulenum);
963 i = do_set_x(IP_FW_DEL, masks, sizeof(u_int32_t));
964 } else if (!strncmp(*av, "disable", strlen(*av)) ||
965 !strncmp(*av, "enable", strlen(*av)) ) {
966 int which = !strncmp(*av, "enable", strlen(*av)) ? 1 : 0;
969 masks[0] = masks[1] = 0;
975 errx(EX_DATAERR, "invalid set number %d\n", i);
976 masks[which] |= (1<<i);
977 } else if (!strncmp(*av, "disable", strlen(*av)))
979 else if (!strncmp(*av, "enable", strlen(*av)))
982 errx(EX_DATAERR, "invalid set command %s\n", *av);
985 if ( (masks[0] & masks[1]) != 0 )
986 errx(EX_DATAERR, "cannot enable and disable the same set\n");
987 i = do_set_x(IP_FW_DEL, masks, sizeof(masks));
989 warn("set enable/disable: setsockopt(IP_FW_DEL)");
991 errx(EX_USAGE, "invalid set command %s\n", *av);
995 add_state(int ac, char *av[])
997 struct ipfw_ioc_state ioc_state;
998 ioc_state.expiry = 0;
999 ioc_state.lifetime = 0;
1001 if (strcmp(*av, "rulenum") == 0) {
1003 ioc_state.rulenum = atoi(*av);
1005 errx(EX_USAGE, "ipfw state add rule");
1008 struct protoent *pe;
1009 pe = getprotobyname(*av);
1010 ioc_state.flow_id.proto = pe->p_proto;
1013 ioc_state.flow_id.src_ip = inet_addr(*av);
1016 ioc_state.flow_id.src_port = atoi(*av);
1019 ioc_state.flow_id.dst_ip = inet_addr(*av);
1022 ioc_state.flow_id.dst_port = atoi(*av);
1025 if (strcmp(*av, "live") == 0) {
1027 ioc_state.lifetime = atoi(*av);
1031 if (strcmp(*av, "expiry") == 0) {
1033 ioc_state.expiry = strtoul(*av, NULL, 10);
1034 printf("ioc_state.expiry=%d\n", ioc_state.expiry);
1037 if (do_set_x(IP_FW_STATE_ADD, &ioc_state, sizeof(struct ipfw_ioc_state)) < 0 ) {
1038 err(EX_UNAVAILABLE, "do_set_x(IP_FW_STATE_ADD)");
1041 printf("Flushed all states.\n");
1046 delete_state(int ac, char *av[])
1050 if (ac == 1 && isdigit(**av))
1051 rulenum = atoi(*av);
1052 if (do_set_x(IP_FW_STATE_DEL, &rulenum, sizeof(int)) < 0 )
1053 err(EX_UNAVAILABLE, "do_set_x(IP_FW_STATE_DEL)");
1055 printf("Flushed all states.\n");
1059 flush_state(int ac, char *av[])
1064 printf("Are you sure? [yn] ");
1067 c = toupper(getc(stdin));
1068 while (c != '\n' && getc(stdin) != '\n')
1070 return; /* and do not flush */
1071 } while (c != 'Y' && c != 'N');
1072 if (c == 'N') /* user said no */
1075 if (do_set_x(IP_FW_STATE_FLUSH, NULL, 0) < 0 )
1076 err(EX_UNAVAILABLE, "do_set_x(IP_FW_STATE_FLUSH)");
1078 printf("Flushed all states.\n");
1082 list(int ac, char *av[])
1084 struct ipfw_ioc_state *dynrules, *d;
1085 struct ipfw_ioc_rule *r;
1089 int bcwidth, n, nbytes, nstat, ndyn, pcwidth, width;
1090 int exitval = EX_OK, lac;
1091 char **lav, *endptr;
1097 /* get rules or pipes from kernel, resizing array as necessary */
1100 while (nbytes >= nalloc) {
1101 nalloc = nalloc * 2 ;
1103 if ((data = realloc(data, nbytes)) == NULL)
1104 err(EX_OSERR, "realloc");
1105 if (do_get_x(IP_FW_GET, data, &nbytes) < 0)
1106 err(EX_OSERR, "do_get_x(IP_FW_GET)");
1110 * Count static rules.
1113 nstat = r->static_count;
1116 * Count dynamic rules. This is easier as they have
1119 dynrules = (struct ipfw_ioc_state *)((void *)r + r->static_len);
1120 ndyn = (nbytes - r->static_len) / sizeof(*dynrules);
1122 /* if showing stats, figure out column widths ahead of time */
1123 bcwidth = pcwidth = 0;
1125 for (n = 0, r = data; n < nstat;
1126 n++, r = (void *)r + IOC_RULESIZE(r)) {
1127 /* packet counter */
1128 width = snprintf(NULL, 0, "%ju", (uintmax_t)r->pcnt);
1129 if (width > pcwidth)
1133 width = snprintf(NULL, 0, "%ju", (uintmax_t)r->bcnt);
1134 if (width > bcwidth)
1138 if (do_dynamic && ndyn) {
1139 for (n = 0, d = dynrules; n < ndyn; n++, d++) {
1140 width = snprintf(NULL, 0, "%ju", (uintmax_t)d->pcnt);
1141 if (width > pcwidth)
1144 width = snprintf(NULL, 0, "%ju", (uintmax_t)d->bcnt);
1145 if (width > bcwidth)
1150 /* if no rule numbers were specified, list all rules */
1152 if (do_dynamic != 2) {
1153 for (n = 0, r = data; n < nstat; n++,
1154 r = (void *)r + IOC_RULESIZE(r)) {
1155 show_rules(r, pcwidth, bcwidth);
1158 if (do_dynamic && ndyn) {
1159 if (do_dynamic != 2) {
1160 printf("## States (%d):\n", ndyn);
1162 for (n = 0, d = dynrules; n < ndyn; n++, d++)
1163 show_states(d, pcwidth, bcwidth);
1168 /* display specific rules requested on command line */
1170 if (do_dynamic != 2) {
1171 for (lac = ac, lav = av; lac != 0; lac--) {
1172 /* convert command line rule # */
1173 rnum = strtoul(*lav++, &endptr, 10);
1176 warnx("invalid rule number: %s", *(lav - 1));
1179 for (n = seen = 0, r = data; n < nstat;
1180 n++, r = (void *)r + IOC_RULESIZE(r) ) {
1181 if (r->rulenum > rnum)
1183 if (r->rulenum == rnum) {
1184 show_rules(r, pcwidth, bcwidth);
1189 /* give precedence to other error(s) */
1190 if (exitval == EX_OK)
1191 exitval = EX_UNAVAILABLE;
1192 warnx("rule %lu does not exist", rnum);
1197 if (do_dynamic && ndyn) {
1198 if (do_dynamic != 2) {
1199 printf("## States (%d):\n", ndyn);
1201 for (lac = ac, lav = av; lac != 0; lac--) {
1202 rnum = strtoul(*lav++, &endptr, 10);
1204 /* already warned */
1206 for (n = 0, d = dynrules; n < ndyn; n++, d++) {
1207 if (d->rulenum > rnum)
1209 if (d->rulenum == rnum)
1210 show_states(d, pcwidth, bcwidth);
1220 if (exitval != EX_OK)
1225 show_dummynet(int ac, char *av[])
1229 int nalloc = 1024; /* start somewhere... */
1234 while (nbytes >= nalloc) {
1235 nalloc = nalloc * 2 + 200;
1237 if ((data = realloc(data, nbytes)) == NULL)
1238 err(EX_OSERR, "realloc");
1239 if (do_get_x(IP_DUMMYNET_GET, data, &nbytes) < 0) {
1240 err(EX_OSERR, "do_get_x(IP_%s_GET)",
1241 do_pipe ? "DUMMYNET" : "FW");
1245 show_pipes(data, nbytes, ac, av);
1252 fprintf(stderr, "usage: ipfw [options]\n"
1253 " ipfw add [rulenum] [set id] action filters\n"
1254 " ipfw delete [rulenum]\n"
1256 " ipfw list [rulenum]\n"
1257 " ipfw show [rulenum]\n"
1258 " ipfw zero [rulenum]\n"
1259 " ipfw set [show|enable|disable]\n"
1261 " ipfw [enable|disable]\n"
1262 " ipfw log [reset|off|on]\n"
1263 " ipfw nat [config|show|delete]\n"
1264 " ipfw pipe [config|show|delete]\n"
1265 " ipfw state [add|delete|list|show]"
1266 "\nsee ipfw manpage for details\n");
1271 delete_nat_config(int ac, char *av[])
1278 if (do_set_x(IP_FW_NAT_DEL, &i, sizeof(i)) == -1)
1279 err(EX_UNAVAILABLE, "getsockopt(%s)", "IP_FW_NAT_DEL");
1283 delete_rules(int ac, char *av[])
1285 struct dn_ioc_pipe pipe;
1287 int exitval = EX_OK;
1291 memset(&pipe, 0, sizeof pipe);
1294 if (ac > 0 && !strncmp(*av, "set", strlen(*av))) {
1295 do_set = 1; /* delete set */
1300 while (ac && isdigit(**av)) {
1309 i = do_set_x(IP_DUMMYNET_DEL, &pipe, sizeof pipe);
1312 warn("rule %u: setsockopt(IP_DUMMYNET_DEL)",
1313 do_pipe == 1 ? pipe.pipe_nr : pipe.fs.fs_nr);
1316 rulenum = (i & 0xffff) | (do_set << 24);
1317 i = do_set_x(IP_FW_DEL, &rulenum, sizeof rulenum);
1319 exitval = EX_UNAVAILABLE;
1320 warn("rule %u: setsockopt(IP_FW_DEL)",
1325 if (exitval != EX_OK)
1330 static unsigned long
1331 getbw(const char *str, u_short *flags, int kb)
1337 val = strtoul(str, &end, 0);
1338 if (*end == 'k' || *end == 'K') {
1341 } else if (*end == 'm' || *end == 'M') {
1347 * Deal with bits or bytes or b(bits) or B(bytes). If there is no
1348 * trailer assume bits.
1350 if (strncasecmp(end, "bit", 3) == 0) {
1352 } else if (strncasecmp(end, "byte", 4) == 0) {
1354 } else if (*end == 'b') {
1356 } else if (*end == 'B') {
1361 * Return in bits if flags is NULL, else flag bits
1362 * or bytes in flags and return the unconverted value.
1364 if (inbytes && flags)
1365 *flags |= DN_QSIZE_IS_BYTES;
1366 else if (inbytes && flags == NULL)
1373 * config dummynet pipe/queue
1376 config_dummynet(int ac, char **av)
1378 struct dn_ioc_pipe pipe;
1385 memset(&pipe, 0, sizeof pipe);
1387 if (ac && isdigit(**av)) {
1399 int tok = match_token(dummynet_params, *av);
1404 pipe.fs.flags_fs |= DN_NOERROR;
1408 NEED1("plr needs argument 0..1\n");
1409 d = strtod(av[0], NULL);
1414 pipe.fs.plr = (int)(d*0x7fffffff);
1419 NEED1("queue needs queue size\n");
1421 pipe.fs.qsize = getbw(av[0], &pipe.fs.flags_fs, 1024);
1426 NEED1("buckets needs argument\n");
1427 pipe.fs.rq_size = strtoul(av[0], NULL, 0);
1432 NEED1("mask needs mask specifier\n");
1434 * per-flow queue, mask is dst_ip, dst_port,
1435 * src_ip, src_port, proto measured in bits
1439 pipe.fs.flow_mask.type = ETHERTYPE_IP;
1440 pipe.fs.flow_mask.u.ip.dst_ip = 0;
1441 pipe.fs.flow_mask.u.ip.src_ip = 0;
1442 pipe.fs.flow_mask.u.ip.dst_port = 0;
1443 pipe.fs.flow_mask.u.ip.src_port = 0;
1444 pipe.fs.flow_mask.u.ip.proto = 0;
1448 u_int32_t *p32 = NULL;
1449 u_int16_t *p16 = NULL;
1451 tok = match_token(dummynet_params, *av);
1456 * special case, all bits significant
1458 pipe.fs.flow_mask.u.ip.dst_ip = ~0;
1459 pipe.fs.flow_mask.u.ip.src_ip = ~0;
1460 pipe.fs.flow_mask.u.ip.dst_port = ~0;
1461 pipe.fs.flow_mask.u.ip.src_port = ~0;
1462 pipe.fs.flow_mask.u.ip.proto = ~0;
1463 pipe.fs.flags_fs |= DN_HAVE_FLOW_MASK;
1467 p32 = &pipe.fs.flow_mask.u.ip.dst_ip;
1471 p32 = &pipe.fs.flow_mask.u.ip.src_ip;
1475 p16 = &pipe.fs.flow_mask.u.ip.dst_port;
1479 p16 = &pipe.fs.flow_mask.u.ip.src_port;
1490 errx(EX_USAGE, "mask: value missing");
1491 if (*av[0] == '/') {
1492 a = strtoul(av[0]+1, &end, 0);
1493 a = (a == 32) ? ~0 : (1 << a) - 1;
1495 a = strtoul(av[0], &end, 0);
1498 else if (p16 != NULL) {
1501 "mask: must be 16 bit");
1502 *p16 = (u_int16_t)a;
1506 "mask: must be 8 bit");
1507 pipe.fs.flow_mask.u.ip.proto = (uint8_t)a;
1510 pipe.fs.flags_fs |= DN_HAVE_FLOW_MASK;
1512 } /* end while, config masks */
1519 NEED1("red/gred needs w_q/min_th/max_th/max_p\n");
1520 pipe.fs.flags_fs |= DN_IS_RED;
1521 if (tok == TOK_GRED)
1522 pipe.fs.flags_fs |= DN_IS_GENTLE_RED;
1524 * the format for parameters is w_q/min_th/max_th/max_p
1526 if ((end = strsep(&av[0], "/"))) {
1527 double w_q = strtod(end, NULL);
1528 if (w_q > 1 || w_q <= 0)
1529 errx(EX_DATAERR, "0 < w_q <= 1");
1530 pipe.fs.w_q = (int) (w_q * (1 << SCALE_RED));
1532 if ((end = strsep(&av[0], "/"))) {
1533 pipe.fs.min_th = strtoul(end, &end, 0);
1534 if (*end == 'K' || *end == 'k')
1535 pipe.fs.min_th *= 1024;
1537 if ((end = strsep(&av[0], "/"))) {
1538 pipe.fs.max_th = strtoul(end, &end, 0);
1539 if (*end == 'K' || *end == 'k')
1540 pipe.fs.max_th *= 1024;
1542 if ((end = strsep(&av[0], "/"))) {
1543 double max_p = strtod(end, NULL);
1544 if (max_p > 1 || max_p <= 0)
1545 errx(EX_DATAERR, "0 < max_p <= 1");
1546 pipe.fs.max_p = (int)(max_p * (1 << SCALE_RED));
1552 pipe.fs.flags_fs &= ~(DN_IS_RED|DN_IS_GENTLE_RED);
1556 NEED1("bw needs bandwidth\n");
1558 errx(EX_DATAERR, "bandwidth only valid for pipes");
1560 * set bandwidth value
1562 pipe.bandwidth = getbw(av[0], NULL, 1000);
1563 if (pipe.bandwidth < 0)
1564 errx(EX_DATAERR, "bandwidth too large");
1570 errx(EX_DATAERR, "delay only valid for pipes");
1571 NEED1("delay needs argument 0..10000ms\n");
1572 pipe.delay = strtoul(av[0], NULL, 0);
1578 errx(EX_DATAERR, "weight only valid for queues");
1579 NEED1("weight needs argument 0..100\n");
1580 pipe.fs.weight = strtoul(av[0], &end, 0);
1586 errx(EX_DATAERR, "pipe only valid for queues");
1587 NEED1("pipe needs pipe_number\n");
1588 pipe.fs.parent_nr = strtoul(av[0], &end, 0);
1593 errx(EX_DATAERR, "unrecognised option ``%s''", *av);
1597 if (pipe.pipe_nr == 0)
1598 errx(EX_DATAERR, "pipe_nr must be > 0");
1599 if (pipe.delay > 10000)
1600 errx(EX_DATAERR, "delay must be < 10000");
1601 } else { /* do_pipe == 2, queue */
1602 if (pipe.fs.parent_nr == 0)
1603 errx(EX_DATAERR, "pipe must be > 0");
1604 if (pipe.fs.weight >100)
1605 errx(EX_DATAERR, "weight must be <= 100");
1607 if (pipe.fs.flags_fs & DN_QSIZE_IS_BYTES) {
1608 if (pipe.fs.qsize > 1024*1024)
1609 errx(EX_DATAERR, "queue size must be < 1MB");
1611 if (pipe.fs.qsize > 100)
1612 errx(EX_DATAERR, "2 <= queue size <= 100");
1614 if (pipe.fs.flags_fs & DN_IS_RED) {
1616 int lookup_depth, avg_pkt_size;
1617 double s, idle, weight, w_q;
1621 if (pipe.fs.min_th >= pipe.fs.max_th)
1622 errx(EX_DATAERR, "min_th %d must be < than max_th %d",
1623 pipe.fs.min_th, pipe.fs.max_th);
1624 if (pipe.fs.max_th == 0)
1625 errx(EX_DATAERR, "max_th must be > 0");
1628 if (sysctlbyname("net.inet.ip.dummynet.red_lookup_depth",
1629 &lookup_depth, &len, NULL, 0) == -1)
1631 errx(1, "sysctlbyname(\"%s\")",
1632 "net.inet.ip.dummynet.red_lookup_depth");
1633 if (lookup_depth == 0)
1634 errx(EX_DATAERR, "net.inet.ip.dummynet.red_lookup_depth"
1635 " must be greater than zero");
1638 if (sysctlbyname("net.inet.ip.dummynet.red_avg_pkt_size",
1639 &avg_pkt_size, &len, NULL, 0) == -1)
1641 errx(1, "sysctlbyname(\"%s\")",
1642 "net.inet.ip.dummynet.red_avg_pkt_size");
1643 if (avg_pkt_size == 0)
1645 "net.inet.ip.dummynet.red_avg_pkt_size must"
1646 " be greater than zero");
1648 len = sizeof(clock_hz);
1649 if (sysctlbyname("net.inet.ip.dummynet.hz", &clock_hz, &len,
1651 errx(1, "sysctlbyname(\"%s\")",
1652 "net.inet.ip.dummynet.hz");
1656 * Ticks needed for sending a medium-sized packet.
1657 * Unfortunately, when we are configuring a WF2Q+ queue, we
1658 * do not have bandwidth information, because that is stored
1659 * in the parent pipe, and also we have multiple queues
1660 * competing for it. So we set s=0, which is not very
1661 * correct. But on the other hand, why do we want RED with
1664 if (pipe.bandwidth == 0) /* this is a WF2Q+ queue */
1667 s = clock_hz * avg_pkt_size * 8 / pipe.bandwidth;
1670 * max idle time (in ticks) before avg queue size becomes 0.
1671 * NOTA: (3/w_q) is approx the value x so that
1672 * (1-w_q)^x < 10^-3.
1674 w_q = ((double)pipe.fs.w_q) / (1 << SCALE_RED);
1675 idle = s * 3. / w_q;
1676 pipe.fs.lookup_step = (int)idle / lookup_depth;
1677 if (!pipe.fs.lookup_step)
1678 pipe.fs.lookup_step = 1;
1680 for (t = pipe.fs.lookup_step; t > 0; --t)
1682 pipe.fs.lookup_weight = (int)(weight * (1 << SCALE_RED));
1684 i = do_set_x(IP_DUMMYNET_CONFIGURE, &pipe, sizeof pipe);
1686 err(1, "do_set_x(%s)", "IP_DUMMYNET_CONFIGURE");
1690 * helper function, updates the pointer to cmd with the length
1691 * of the current command, and also cleans up the first word of
1692 * the new command in case it has been clobbered before.
1695 next_cmd(ipfw_insn *cmd)
1698 bzero(cmd, sizeof(*cmd));
1703 * Parse arguments and assemble the microinstructions which make up a rule.
1704 * Rules are added into the 'rulebuf' and then copied in the correct order
1705 * into the actual rule.
1710 add(int ac, char *av[])
1713 * rules are added into the 'rulebuf' and then copied in
1714 * the correct order into the actual rule.
1715 * Some things that need to go out of order (prob, action etc.)
1718 static uint32_t rulebuf[IPFW_RULE_SIZE_MAX];
1719 static uint32_t actbuf[IPFW_RULE_SIZE_MAX];
1720 static uint32_t othbuf[IPFW_RULE_SIZE_MAX];
1721 static uint32_t cmdbuf[IPFW_RULE_SIZE_MAX];
1723 ipfw_insn *src, *dst, *cmd, *action, *other;
1724 ipfw_insn *the_comment = NULL;
1725 struct ipfw_ioc_rule *rule;
1726 struct ipfw_keyword *key;
1727 struct ipfw_mapping *map;
1731 bzero(actbuf, sizeof(actbuf)); /* actions go here */
1732 bzero(othbuf, sizeof(actbuf)); /* others */
1733 bzero(cmdbuf, sizeof(cmdbuf)); /* filters */
1734 bzero(rulebuf, sizeof(rulebuf));
1736 rule = (struct ipfw_ioc_rule *)rulebuf;
1737 cmd = (ipfw_insn *)cmdbuf;
1738 action = (ipfw_insn *)actbuf;
1739 other = (ipfw_insn *)othbuf;
1741 NEED2("need more parameters");
1744 /* [rule N] -- Rule number optional */
1745 if (ac && isdigit(**av)) {
1746 rule->rulenum = atoi(*av);
1750 /* [set N] -- set number (0..30), optional */
1751 if (ac > 1 && !strncmp(*av, "set", strlen(*av))) {
1752 int set = strtoul(av[1], NULL, 10);
1753 if (set < 0 || set > 30)
1754 errx(EX_DATAERR, "illegal set %s", av[1]);
1763 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) {
1764 if (key->type == IPFW_KEYWORD_TYPE_OTHERS &&
1765 strcmp(key->word, *av) == 0) {
1766 for (j = 0, map = mappings;
1767 j < MAPPING_SIZE; j++, map++) {
1768 if (map->type == IPFW_MAPPING_TYPE_IN_USE &&
1769 map->module == key->module &&
1770 map->opcode == key->opcode ) {
1772 (*fn)(&other, &ac, &av);
1779 if (i >= KEYWORD_SIZE) {
1781 } else if (F_LEN(other) > 0) {
1782 if (other->module == MODULE_BASIC_ID &&
1783 other->opcode == O_BASIC_CHECK_STATE) {
1784 other = next_cmd(other);
1787 other = next_cmd(other);
1794 * only accept 1 action
1796 NEED1("missing action");
1797 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) {
1798 if (ac > 0 && key->type == IPFW_KEYWORD_TYPE_ACTION &&
1799 strcmp(key->word, *av) == 0) {
1800 for (j = 0, map = mappings; j<MAPPING_SIZE; j++, map++) {
1801 if (map->type == IPFW_MAPPING_TYPE_IN_USE &&
1802 map->module == key->module &&
1803 map->opcode == key->opcode) {
1805 (*fn)(&action, &ac, &av);
1812 if (F_LEN(action) > 0)
1813 action = next_cmd(action);
1818 if (strcmp(*av, "proto") == 0){
1822 NEED1("missing protocol");
1823 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) {
1824 if (key->type == IPFW_KEYWORD_TYPE_FILTER &&
1825 strcmp(key->word, "proto") == 0) {
1826 for (j = 0, map = mappings; j<MAPPING_SIZE; j++, map++) {
1827 if (map->type == IPFW_MAPPING_TYPE_IN_USE &&
1828 map->module == key->module &&
1829 map->opcode == key->opcode ) {
1831 (*fn)(&cmd, &ac, &av);
1839 cmd = next_cmd(cmd);
1846 ipfw_insn_u32 *cmd32; /* alias for cmd */
1849 cmd32 = (ipfw_insn_u32 *)cmd;
1850 if (strcmp(*av, "not") == 0) {
1851 if (cmd->len & F_NOT)
1852 errx(EX_USAGE, "double \"not\" not allowed\n");
1857 if (*s == '!') { /* alternate syntax for NOT */
1858 if (cmd->len & F_NOT)
1859 errx(EX_USAGE, "double \"not\" not allowed");
1863 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) {
1864 if (key->type == IPFW_KEYWORD_TYPE_FILTER &&
1865 strcmp(key->word, s) == 0) {
1866 for (j = 0, map = mappings;
1867 j< MAPPING_SIZE; j++, map++) {
1868 if (map->type == IPFW_MAPPING_TYPE_IN_USE &&
1869 map->module == key->module &&
1870 map->opcode == key->opcode ) {
1872 (*fn)(&cmd, &ac, &av);
1877 } else if (i == KEYWORD_SIZE-1) {
1878 errx(EX_USAGE, "bad command `%s'", s);
1881 if (i >= KEYWORD_SIZE) {
1883 } else if (F_LEN(cmd) > 0) {
1884 cmd = next_cmd(cmd);
1890 errx(EX_USAGE, "bad command `%s'", *av);
1893 * Now copy stuff into the rule.
1894 * [filters][others][action][comment]
1896 dst = (ipfw_insn *)rule->cmd;
1898 * copy all filters, except comment
1900 src = (ipfw_insn *)cmdbuf;
1901 for (src = (ipfw_insn *)cmdbuf; src != cmd; src += i) {
1902 /* pick comment out */
1904 if (src->module == MODULE_BASIC_ID && src->opcode == O_BASIC_COMMENT) {
1907 bcopy(src, dst, i * sizeof(u_int32_t));
1908 dst = (ipfw_insn *)((uint32_t *)dst + i);
1913 * start action section, it begin with others
1915 rule->act_ofs = (uint32_t *)dst - (uint32_t *)(rule->cmd);
1918 * copy all other others
1920 for (src = (ipfw_insn *)othbuf; src != other; src += i) {
1922 bcopy(src, dst, i * sizeof(u_int32_t));
1923 dst = (ipfw_insn *)((uint32_t *)dst + i);
1926 /* copy the action to the end of rule */
1927 src = (ipfw_insn *)actbuf;
1929 bcopy(src, dst, i * sizeof(u_int32_t));
1930 dst = (ipfw_insn *)((uint32_t *)dst + i);
1933 * comment place behind the action
1935 if (the_comment != NULL) {
1936 i = F_LEN(the_comment);
1937 bcopy(the_comment, dst, i * sizeof(u_int32_t));
1938 dst = (ipfw_insn *)((uint32_t *)dst + i);
1941 rule->cmd_len = (u_int32_t *)dst - (u_int32_t *)(rule->cmd);
1942 i = (void *)dst - (void *)rule;
1943 if (do_set_x(IP_FW_ADD, (void *)rule, i) == -1) {
1944 err(EX_UNAVAILABLE, "getsockopt(%s)", "IP_FW_ADD");
1947 show_rules(rule, 10, 10);
1951 zero(int ac, char *av[])
1959 /* clear all entries */
1960 if (do_set_x(IP_FW_ZERO, NULL, 0) < 0)
1961 err(EX_UNAVAILABLE, "do_set_x(IP_FW_ZERO)");
1963 printf("Accounting cleared.\n");
1969 if (isdigit(**av)) {
1970 rulenum = atoi(*av);
1972 if (do_set_x(IP_FW_ZERO, &rulenum, sizeof rulenum)) {
1973 warn("rule %u: do_set_x(IP_FW_ZERO)", rulenum);
1974 failed = EX_UNAVAILABLE;
1975 } else if (!do_quiet)
1976 printf("Entry %d cleared\n", rulenum);
1978 errx(EX_USAGE, "invalid rule number ``%s''", *av);
1981 if (failed != EX_OK)
1986 resetlog(int ac, char *av[])
1994 /* clear all entries */
1995 if (setsockopt(ipfw_socket, IPPROTO_IP, IP_FW_RESETLOG, NULL, 0) < 0)
1996 err(EX_UNAVAILABLE, "setsockopt(IP_FW_RESETLOG)");
1998 printf("Logging counts reset.\n");
2005 if (isdigit(**av)) {
2006 rulenum = atoi(*av);
2008 if (setsockopt(ipfw_socket, IPPROTO_IP,
2009 IP_FW_RESETLOG, &rulenum, sizeof rulenum)) {
2010 warn("rule %u: setsockopt(IP_FW_RESETLOG)", rulenum);
2011 failed = EX_UNAVAILABLE;
2012 } else if (!do_quiet)
2013 printf("Entry %d logging count reset\n", rulenum);
2015 errx(EX_DATAERR, "invalid rule number ``%s''", *av);
2018 if (failed != EX_OK)
2025 int cmd = IP_FW_FLUSH;
2027 cmd = IP_DUMMYNET_FLUSH;
2028 } else if (do_nat) {
2029 cmd = IP_FW_NAT_FLUSH;
2034 printf("Are you sure? [yn] ");
2037 c = toupper(getc(stdin));
2038 while (c != '\n' && getc(stdin) != '\n')
2040 return; /* and do not flush */
2041 } while (c != 'Y' && c != 'N');
2042 if (c == 'N') /* user said no */
2045 if (do_set_x(cmd, NULL, 0) < 0 ) {
2046 err(EX_UNAVAILABLE, "do_set_x(%s)",
2047 do_pipe? "IP_DUMMYNET_FLUSH":
2048 (do_nat? "IP_FW_NAT_FLUSH": "IP_FW_FLUSH"));
2051 printf("Flushed all %s.\n", do_pipe ? "pipes":
2052 (do_nat?"nat configurations":"rules"));
2057 str2addr(const char* str, struct in_addr* addr)
2061 if (inet_aton (str, addr))
2064 hp = gethostbyname (str);
2066 errx (1, "unknown host %s", str);
2068 memcpy (addr, hp->h_addr, sizeof (struct in_addr));
2072 str2portrange(const char* str, const char* proto, port_range *portRange)
2077 u_short loPort, hiPort;
2079 /* First see if this is a service, return corresponding port if so. */
2080 sp = getservbyname (str, proto);
2082 SETLOPORT(*portRange, ntohs(sp->s_port));
2083 SETNUMPORTS(*portRange, 1);
2087 /* Not a service, see if it's a single port or port range. */
2088 sep = strchr (str, '-');
2090 SETLOPORT(*portRange, strtol(str, &end, 10));
2093 SETNUMPORTS(*portRange, 1);
2097 /* Error in port range field. */
2098 errx (EX_DATAERR, "%s/%s: unknown service", str, proto);
2101 /* Port range, get the values and sanity check. */
2102 sscanf (str, "%hu-%hu", &loPort, &hiPort);
2103 SETLOPORT(*portRange, loPort);
2104 SETNUMPORTS(*portRange, 0); /* Error by default */
2105 if (loPort <= hiPort)
2106 SETNUMPORTS(*portRange, hiPort - loPort + 1);
2108 if (GETNUMPORTS(*portRange) == 0)
2109 errx (EX_DATAERR, "invalid port range %s", str);
2115 str2proto(const char* str)
2117 if (!strcmp (str, "tcp"))
2119 if (!strcmp (str, "udp"))
2121 errx (EX_DATAERR, "unknown protocol %s. Expected tcp or udp", str);
2125 str2addr_portrange (const char* str, struct in_addr* addr,
2126 char* proto, port_range *portRange)
2130 ptr = strchr (str, ':');
2132 errx (EX_DATAERR, "%s is missing port number", str);
2137 str2addr (str, addr);
2138 return str2portrange (ptr, proto, portRange);
2142 * Search for interface with name "ifn", and fill n accordingly:
2144 * n->ip ip address of interface "ifn"
2145 * n->if_name copy of interface name "ifn"
2148 set_addr_dynamic(const char *ifn, struct cfg_nat *n)
2150 struct if_msghdr *ifm;
2151 struct ifa_msghdr *ifam;
2152 struct sockaddr_dl *sdl;
2153 struct sockaddr_in *sin;
2154 char *buf, *lim, *next;
2163 mib[4] = NET_RT_IFLIST;
2167 * Get interface data.
2169 if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1)
2170 err(1, "iflist-sysctl-estimate");
2171 if ((buf = malloc(needed)) == NULL)
2172 errx(1, "malloc failed");
2173 if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1)
2174 err(1, "iflist-sysctl-get");
2177 * Loop through interfaces until one with
2178 * given name is found. This is done to
2179 * find correct interface index for routing
2180 * message processing.
2184 while (next < lim) {
2185 ifm = (struct if_msghdr *)next;
2186 next += ifm->ifm_msglen;
2187 if (ifm->ifm_version != RTM_VERSION) {
2189 warnx("routing message version %d "
2190 "not understood", ifm->ifm_version);
2193 if (ifm->ifm_type == RTM_IFINFO) {
2194 sdl = (struct sockaddr_dl *)(ifm + 1);
2195 if (strlen(ifn) == sdl->sdl_nlen &&
2196 strncmp(ifn, sdl->sdl_data, sdl->sdl_nlen) == 0) {
2197 ifIndex = ifm->ifm_index;
2198 ifMTU = ifm->ifm_data.ifi_mtu;
2204 errx(1, "unknown interface name %s", ifn);
2206 * Get interface address.
2209 while (next < lim) {
2210 ifam = (struct ifa_msghdr *)next;
2211 next += ifam->ifam_msglen;
2212 if (ifam->ifam_version != RTM_VERSION) {
2214 warnx("routing message version %d "
2215 "not understood", ifam->ifam_version);
2218 if (ifam->ifam_type != RTM_NEWADDR)
2220 if (ifam->ifam_addrs & RTA_IFA) {
2222 char *cp = (char *)(ifam + 1);
2224 for (i = 1; i < RTA_IFA; i <<= 1) {
2225 if (ifam->ifam_addrs & i)
2226 cp += SA_SIZE((struct sockaddr *)cp);
2228 if (((struct sockaddr *)cp)->sa_family == AF_INET) {
2229 sin = (struct sockaddr_in *)cp;
2235 errx(1, "%s: cannot get interface address", ifn);
2237 n->ip = sin->sin_addr;
2238 strncpy(n->if_name, ifn, IF_NAMESIZE);
2244 setup_redir_addr(char *spool_buf, int len, int *_ac, char ***_av)
2246 struct cfg_redir *r;
2247 struct cfg_spool *tmp;
2249 char tmp_spool_buf[NAT_BUF_LEN];
2250 int ac, i, space, lsnat;
2257 if (len >= SOF_REDIR) {
2258 r = (struct cfg_redir *)spool_buf;
2259 /* Skip cfg_redir at beginning of buf. */
2260 spool_buf = &spool_buf[SOF_REDIR];
2267 r->mode = REDIR_ADDR;
2268 /* Extract local address. */
2270 errx(EX_DATAERR, "redirect_addr: missing local address");
2272 sep = strchr(*av, ',');
2273 if (sep) { /* LSNAT redirection syntax. */
2274 r->laddr.s_addr = INADDR_NONE;
2275 /* Preserve av, copy spool servers to tmp_spool_buf. */
2276 strncpy(tmp_spool_buf, *av, strlen(*av)+1);
2279 str2addr(*av, &r->laddr);
2283 /* Extract public address. */
2285 errx(EX_DATAERR, "redirect_addr: missing public address");
2287 str2addr(*av, &r->paddr);
2290 /* Setup LSNAT server pool. */
2292 sep = strtok(tmp_spool_buf, ", ");
2293 while (sep != NULL) {
2294 tmp = (struct cfg_spool *)spool_buf;
2295 if (len < SOF_SPOOL)
2300 str2addr(sep, &tmp->addr);
2303 /* Point to the next possible cfg_spool. */
2304 spool_buf = &spool_buf[SOF_SPOOL];
2305 sep = strtok(NULL, ", ");
2311 errx(EX_DATAERR, "redirect_addr: buf is too small\n");
2315 setup_redir_port(char *spool_buf, int len, int *_ac, char ***_av)
2317 char **av, *sep, *protoName;
2318 char tmp_spool_buf[NAT_BUF_LEN];
2319 int ac, space, lsnat;
2320 struct cfg_redir *r;
2321 struct cfg_spool *tmp;
2322 u_short numLocalPorts;
2323 port_range portRange;
2331 if (len >= SOF_REDIR) {
2332 r = (struct cfg_redir *)spool_buf;
2333 /* Skip cfg_redir at beginning of buf. */
2334 spool_buf = &spool_buf[SOF_REDIR];
2341 r->mode = REDIR_PORT;
2346 errx (EX_DATAERR, "redirect_port: missing protocol");
2348 r->proto = str2proto(*av);
2353 * Extract local address.
2356 errx (EX_DATAERR, "redirect_port: missing local address");
2358 sep = strchr(*av, ',');
2359 /* LSNAT redirection syntax. */
2361 r->laddr.s_addr = INADDR_NONE;
2364 /* Preserve av, copy spool servers to tmp_spool_buf. */
2365 strncpy(tmp_spool_buf, *av, strlen(*av)+1);
2368 if (str2addr_portrange (*av, &r->laddr, protoName, &portRange) != 0)
2369 errx(EX_DATAERR, "redirect_port:"
2370 "invalid local port range");
2372 r->lport = GETLOPORT(portRange);
2373 numLocalPorts = GETNUMPORTS(portRange);
2378 * Extract public port and optionally address.
2381 errx (EX_DATAERR, "redirect_port: missing public port");
2383 sep = strchr (*av, ':');
2385 if (str2addr_portrange (*av, &r->paddr, protoName, &portRange) != 0)
2386 errx(EX_DATAERR, "redirect_port:"
2387 "invalid public port range");
2389 r->paddr.s_addr = INADDR_ANY;
2390 if (str2portrange(*av, protoName, &portRange) != 0)
2391 errx(EX_DATAERR, "redirect_port:"
2392 "invalid public port range");
2395 r->pport = GETLOPORT(portRange);
2396 r->pport_cnt = GETNUMPORTS(portRange);
2400 * Extract remote address and optionally port.
2403 * NB: isalpha(**av) => we've to check that next parameter is really an
2404 * option for this redirect entry, else stop here processing arg[cv].
2406 if (ac != 0 && !isalpha(**av)) {
2407 sep = strchr (*av, ':');
2409 if (str2addr_portrange (*av, &r->raddr,
2410 protoName, &portRange) != 0)
2411 errx(EX_DATAERR, "redirect_port:"
2412 "invalid remote port range");
2414 SETLOPORT(portRange, 0);
2415 SETNUMPORTS(portRange, 1);
2416 str2addr (*av, &r->raddr);
2420 SETLOPORT(portRange, 0);
2421 SETNUMPORTS(portRange, 1);
2422 r->raddr.s_addr = INADDR_ANY;
2424 r->rport = GETLOPORT(portRange);
2425 r->rport_cnt = GETNUMPORTS(portRange);
2428 * Make sure port ranges match up, then add the redirect ports.
2430 if (numLocalPorts != r->pport_cnt)
2431 errx(EX_DATAERR, "redirect_port:"
2432 "port ranges must be equal in size");
2434 /* Remote port range is allowed to be '0' which means all ports. */
2435 if (r->rport_cnt != numLocalPorts &&
2436 (r->rport_cnt != 1 || r->rport != 0))
2437 errx(EX_DATAERR, "redirect_port: remote port must"
2438 "be 0 or equal to local port range in size");
2441 * Setup LSNAT server pool.
2444 sep = strtok(tmp_spool_buf, ", ");
2445 while (sep != NULL) {
2446 tmp = (struct cfg_spool *)spool_buf;
2447 if (len < SOF_SPOOL)
2452 if (str2addr_portrange(sep,
2453 &tmp->addr, protoName, &portRange) != 0)
2454 errx(EX_DATAERR, "redirect_port:"
2455 "invalid local port range");
2456 if (GETNUMPORTS(portRange) != 1)
2457 errx(EX_DATAERR, "redirect_port: local port"
2458 "must be single in this context");
2459 tmp->port = GETLOPORT(portRange);
2461 /* Point to the next possible cfg_spool. */
2462 spool_buf = &spool_buf[SOF_SPOOL];
2463 sep = strtok(NULL, ", ");
2469 errx(EX_DATAERR, "redirect_port: buf is too small\n");
2473 setup_redir_proto(char *spool_buf, int len, int *_ac, char ***_av)
2475 struct protoent *protoent;
2476 struct cfg_redir *r;
2483 if (len >= SOF_REDIR) {
2484 r = (struct cfg_redir *)spool_buf;
2485 /* Skip cfg_redir at beginning of buf. */
2486 spool_buf = &spool_buf[SOF_REDIR];
2492 r->mode = REDIR_PROTO;
2497 errx(EX_DATAERR, "redirect_proto: missing protocol");
2499 protoent = getprotobyname(*av);
2500 if (protoent == NULL)
2501 errx(EX_DATAERR, "redirect_proto: unknown protocol %s", *av);
2503 r->proto = protoent->p_proto;
2508 * Extract local address.
2511 errx(EX_DATAERR, "redirect_proto: missing local address");
2513 str2addr(*av, &r->laddr);
2517 * Extract optional public address.
2520 r->paddr.s_addr = INADDR_ANY;
2521 r->raddr.s_addr = INADDR_ANY;
2523 /* see above in setup_redir_port() */
2524 if (!isalpha(**av)) {
2525 str2addr(*av, &r->paddr);
2529 * Extract optional remote address.
2531 /* see above in setup_redir_port() */
2532 if (ac != 0 && !isalpha(**av)) {
2533 str2addr(*av, &r->raddr);
2541 errx(EX_DATAERR, "redirect_proto: buf is too small\n");
2545 show_nat_config(char *buf) {
2547 struct cfg_redir *t;
2548 struct cfg_spool *s;
2550 int i, cnt, flag, off;
2552 n = (struct cfg_nat *)buf;
2555 printf("ipfw nat %u config", n->id);
2556 if (strlen(n->if_name) != 0)
2557 printf(" if %s", n->if_name);
2558 else if (n->ip.s_addr != 0)
2559 printf(" ip %s", inet_ntoa(n->ip));
2560 while (n->mode != 0) {
2561 if (n->mode & PKT_ALIAS_LOG) {
2563 n->mode &= ~PKT_ALIAS_LOG;
2564 } else if (n->mode & PKT_ALIAS_DENY_INCOMING) {
2566 n->mode &= ~PKT_ALIAS_DENY_INCOMING;
2567 } else if (n->mode & PKT_ALIAS_SAME_PORTS) {
2568 printf(" same_ports");
2569 n->mode &= ~PKT_ALIAS_SAME_PORTS;
2570 } else if (n->mode & PKT_ALIAS_UNREGISTERED_ONLY) {
2571 printf(" unreg_only");
2572 n->mode &= ~PKT_ALIAS_UNREGISTERED_ONLY;
2573 } else if (n->mode & PKT_ALIAS_RESET_ON_ADDR_CHANGE) {
2575 n->mode &= ~PKT_ALIAS_RESET_ON_ADDR_CHANGE;
2576 } else if (n->mode & PKT_ALIAS_REVERSE) {
2578 n->mode &= ~PKT_ALIAS_REVERSE;
2579 } else if (n->mode & PKT_ALIAS_PROXY_ONLY) {
2580 printf(" proxy_only");
2581 n->mode &= ~PKT_ALIAS_PROXY_ONLY;
2584 /* Print all the redirect's data configuration. */
2585 for (cnt = 0; cnt < n->redir_cnt; cnt++) {
2586 t = (struct cfg_redir *)&buf[off];
2590 printf(" redirect_addr");
2591 if (t->spool_cnt == 0)
2592 printf(" %s", inet_ntoa(t->laddr));
2594 for (i = 0; i < t->spool_cnt; i++) {
2595 s = (struct cfg_spool *)&buf[off];
2600 printf("%s", inet_ntoa(s->addr));
2603 printf(" %s", inet_ntoa(t->paddr));
2606 p = getprotobynumber(t->proto);
2607 printf(" redirect_port %s ", p->p_name);
2608 if (!t->spool_cnt) {
2609 printf("%s:%u", inet_ntoa(t->laddr), t->lport);
2610 if (t->pport_cnt > 1)
2611 printf("-%u", t->lport + t->pport_cnt - 1);
2613 for (i=0; i < t->spool_cnt; i++) {
2614 s = (struct cfg_spool *)&buf[off];
2617 printf("%s:%u", inet_ntoa(s->addr), s->port);
2622 if (t->paddr.s_addr)
2623 printf("%s:", inet_ntoa(t->paddr));
2624 printf("%u", t->pport);
2625 if (!t->spool_cnt && t->pport_cnt > 1)
2626 printf("-%u", t->pport + t->pport_cnt - 1);
2628 if (t->raddr.s_addr) {
2629 printf(" %s", inet_ntoa(t->raddr));
2631 printf(":%u", t->rport);
2632 if (!t->spool_cnt && t->rport_cnt > 1)
2633 printf("-%u", t->rport +
2639 p = getprotobynumber(t->proto);
2640 printf(" redirect_proto %s %s", p->p_name,
2641 inet_ntoa(t->laddr));
2642 if (t->paddr.s_addr != 0) {
2643 printf(" %s", inet_ntoa(t->paddr));
2644 if (t->raddr.s_addr)
2645 printf(" %s", inet_ntoa(t->raddr));
2649 errx(EX_DATAERR, "unknown redir mode");
2658 show_nat(int ac, char **av) {
2660 struct cfg_redir *e;
2661 int i, nbytes, nalloc, size;
2662 int nat_cnt, redir_cnt, nat_id;
2674 nat_id = strtoul(*av, NULL, 10);
2677 while (nbytes >= nalloc) {
2678 nalloc = nalloc * 2;
2680 if ((data = realloc(data, nbytes)) == NULL) {
2681 err(EX_OSERR, "realloc");
2683 if (do_get_x(IP_FW_NAT_GET, data, &nbytes) < 0) {
2684 err(EX_OSERR, "do_get_x(IP_FW_NAT_GET)");
2692 nat_cnt = *((int *)data);
2693 for (i = sizeof(nat_cnt); nat_cnt; nat_cnt--) {
2694 n = (struct cfg_nat *)&data[i];
2695 if (n->id >= 0 && n->id <= IPFW_DEFAULT_RULE) {
2696 if (nat_id == 0 || n->id == nat_id)
2697 show_nat_config(&data[i]);
2699 i += sizeof(struct cfg_nat);
2700 for (redir_cnt = 0; redir_cnt < n->redir_cnt; redir_cnt++) {
2701 e = (struct cfg_redir *)&data[i];
2702 i += sizeof(struct cfg_redir) +
2703 e->spool_cnt * sizeof(struct cfg_spool);
2709 * do_set_x - extended version og do_set
2710 * insert a x_header in the beginning of the rule buf
2711 * and call setsockopt() with IP_FW_X.
2714 do_set_x(int optname, void *rule, int optlen)
2718 ip_fw_x_header *x_header;
2719 if (ipfw_socket < 0)
2720 err(EX_UNAVAILABLE, "socket not avaialble");
2721 len = optlen + sizeof(ip_fw_x_header);
2722 newbuf = malloc(len);
2724 err(EX_OSERR, "malloc newbuf in do_set_x");
2726 x_header = (ip_fw_x_header *)newbuf;
2727 x_header->opcode = optname;
2728 /* copy the rule into the newbuf, just after the x_header*/
2729 bcopy(rule, ++x_header, optlen);
2730 return setsockopt(ipfw_socket, IPPROTO_IP, IP_FW_X, newbuf, len);
2737 do_get_x(int optname, void *rule, int *optlen)
2739 int len, *newbuf, retval;
2741 ip_fw_x_header *x_header;
2742 if (ipfw_socket < 0)
2743 err(EX_UNAVAILABLE, "socket not avaialble");
2744 len = *optlen + sizeof(ip_fw_x_header);
2745 newbuf = malloc(len);
2747 err(EX_OSERR, "malloc newbuf in do_get_x");
2749 x_header = (ip_fw_x_header *)newbuf;
2750 x_header->opcode = optname;
2751 /* copy the rule into the newbuf, just after the x_header*/
2752 bcopy(rule, ++x_header, *optlen);
2753 retval = getsockopt(ipfw_socket, IPPROTO_IP, IP_FW_X, newbuf, &len);
2754 bcopy(newbuf, rule, len);
2760 config_nat(int ac, char **av)
2762 struct cfg_nat *n; /* Nat instance configuration. */
2763 int i, len, off, tok;
2764 char *id, buf[NAT_BUF_LEN]; /* Buffer for serialized data. */
2767 /* Offset in buf: save space for n at the beginning. */
2768 off = sizeof(struct cfg_nat);
2769 memset(buf, 0, sizeof(buf));
2770 n = (struct cfg_nat *)buf;
2774 if (ac && isdigit(**av)) {
2780 errx(EX_DATAERR, "missing nat id");
2782 errx(EX_DATAERR, "missing option");
2785 tok = match_token(nat_params, *av);
2790 errx(EX_DATAERR, "missing option");
2791 if (!inet_aton(av[0], &(n->ip)))
2792 errx(EX_DATAERR, "bad ip address ``%s''",
2798 errx(EX_DATAERR, "missing option");
2799 set_addr_dynamic(av[0], n);
2803 n->mode |= PKT_ALIAS_LOG;
2806 n->mode |= PKT_ALIAS_DENY_INCOMING;
2808 case TOK_SAME_PORTS:
2809 n->mode |= PKT_ALIAS_SAME_PORTS;
2811 case TOK_UNREG_ONLY:
2812 n->mode |= PKT_ALIAS_UNREGISTERED_ONLY;
2814 case TOK_RESET_ADDR:
2815 n->mode |= PKT_ALIAS_RESET_ON_ADDR_CHANGE;
2818 n->mode |= PKT_ALIAS_REVERSE;
2820 case TOK_PROXY_ONLY:
2821 n->mode |= PKT_ALIAS_PROXY_ONLY;
2824 * All the setup_redir_* functions work directly in the final
2825 * buffer, see above for details.
2827 case TOK_REDIR_ADDR:
2828 case TOK_REDIR_PORT:
2829 case TOK_REDIR_PROTO:
2831 case TOK_REDIR_ADDR:
2832 i = setup_redir_addr(&buf[off], len, &ac, &av);
2834 case TOK_REDIR_PORT:
2835 i = setup_redir_port(&buf[off], len, &ac, &av);
2837 case TOK_REDIR_PROTO:
2838 i = setup_redir_proto(&buf[off], len, &ac, &av);
2846 errx(EX_DATAERR, "unrecognised option ``%s''", av[-1]);
2849 i = do_set_x(IP_FW_NAT_CFG, buf, off);
2851 err(1, "do_set_x(%s)", "IP_FW_NAT_CFG");
2853 /* After every modification, we show the resultant rule. */
2855 char *_av[] = {"config", id};
2861 ipfw_main(int ac, char **av)
2868 /* Set the force flag for non-interactive processes */
2869 do_force = !isatty(STDIN_FILENO);
2871 optind = optreset = 1;
2872 while ((ch = getopt(ac, av, "hs:acdDefNStTv")) != -1)
2874 case 'h': /* help */
2876 break; /* NOTREACHED */
2878 case 's': /* sort */
2879 do_sort = atoi(optarg);
2921 NEED1("bad arguments, for usage summary ``ipfw''");
2924 * optional: pipe or queue or nat
2928 if (!strncmp(*av, "nat", strlen(*av)))
2930 else if (!strncmp(*av, "pipe", strlen(*av))) {
2932 } else if (!strncmp(*av, "queue", strlen(*av))) {
2935 NEED1("missing command");
2938 * for pipes and queues and nat we normally say 'pipe NN config'
2939 * but the code is easier to parse as 'pipe config NN'
2940 * so we swap the two arguments.
2942 if ((do_pipe || do_nat) && ac > 2 && isdigit(*(av[1]))) {
2948 if (!strncmp(*av, "add", strlen(*av))) {
2951 } else if (!strncmp(*av, "delete", strlen(*av))) {
2952 delete_rules(ac, av);
2953 } else if (!strncmp(*av, "flush", strlen(*av))) {
2955 } else if (!strncmp(*av, "list", strlen(*av))) {
2958 } else if (!strncmp(*av, "show", strlen(*av))) {
2962 } else if (!strncmp(*av, "zero", strlen(*av))) {
2964 } else if (!strncmp(*av, "set", strlen(*av))) {
2965 sets_handler(ac, av);
2966 } else if (!strncmp(*av, "module", strlen(*av))) {
2968 if (!strncmp(*av, "show", strlen(*av)) ||
2969 !strncmp(*av, "show", strlen(*av))) {
2970 list_modules(ac, av);
2972 errx(EX_USAGE, "bad ipfw module command `%s'", *av);
2974 } else if (!strncmp(*av, "resetlog", strlen(*av))) {
2976 } else if (!strncmp(*av, "log", strlen(*av))) {
2978 if (!strncmp(*av, "reset", strlen(*av))) {
2980 } else if (!strncmp(*av, "off", strlen(*av))) {
2982 } else if (!strncmp(*av, "on", strlen(*av))) {
2985 errx(EX_USAGE, "bad command `%s'", *av);
2987 } else if (!strncmp(*av, "nat", strlen(*av))) {
2989 if (!strncmp(*av, "config", strlen(*av))) {
2991 } else if (!strncmp(*av, "flush", strlen(*av))) {
2993 } else if (!strncmp(*av, "show", strlen(*av)) ||
2994 !strncmp(*av, "list", strlen(*av))) {
2996 } else if (!strncmp(*av, "delete", strlen(*av))) {
2997 delete_nat_config(ac, av);
2999 errx(EX_USAGE, "bad ipfw nat command `%s'", *av);
3001 } else if (!strncmp(*av, "pipe", strlen(*av)) ||
3002 !strncmp(*av, "queue", strlen(*av))) {
3004 if (!strncmp(*av, "config", strlen(*av))) {
3005 config_dummynet(ac, av);
3006 } else if (!strncmp(*av, "flush", strlen(*av))) {
3008 } else if (!strncmp(*av, "show", strlen(*av))) {
3009 show_dummynet(ac, av);
3011 errx(EX_USAGE, "bad ipfw pipe command `%s'", *av);
3013 } else if (!strncmp(*av, "state", strlen(*av))) {
3015 if (!strncmp(*av, "add", strlen(*av))) {
3017 } else if (!strncmp(*av, "delete", strlen(*av))) {
3018 delete_state(ac, av);
3019 } else if (!strncmp(*av, "flush", strlen(*av))) {
3020 flush_state(ac, av);
3021 } else if (!strncmp(*av, "list", strlen(*av))) {
3024 } else if (!strncmp(*av, "show", strlen(*av))) {
3029 errx(EX_USAGE, "bad ipfw state command `%s'", *av);
3032 errx(EX_USAGE, "bad ipfw command `%s'", *av);
3038 ipfw_readfile(int ac, char *av[])
3041 char *a, *p, *args[MAX_ARGS], *cmd = NULL;
3043 int i=0, lineno=0, qflag=0, pflag=0, status;
3048 while ((c = getopt(ac, av, "D:U:p:q")) != -1) {
3052 errx(EX_USAGE, "-D requires -p");
3053 if (i > MAX_ARGS - 2)
3054 errx(EX_USAGE, "too many -D or -U options");
3061 errx(EX_USAGE, "-U requires -p");
3062 if (i > MAX_ARGS - 2)
3063 errx(EX_USAGE, "too many -D or -U options");
3080 errx(EX_USAGE, "bad arguments, for usage"
3081 " summary ``ipfw''");
3088 errx(EX_USAGE, "extraneous filename arguments");
3090 if ((f = fopen(av[0], "r")) == NULL)
3091 err(EX_UNAVAILABLE, "fopen: %s", av[0]);
3094 /* pipe through preprocessor (cpp or m4) */
3099 if (pipe(pipedes) == -1)
3100 err(EX_OSERR, "cannot create pipe");
3102 switch ((preproc = fork())) {
3104 err(EX_OSERR, "cannot fork");
3108 if (dup2(fileno(f), 0) == -1 ||
3109 dup2(pipedes[1], 1) == -1) {
3110 err(EX_OSERR, "dup2()");
3116 err(EX_OSERR, "execvp(%s) failed", cmd);
3122 if ((f = fdopen(pipedes[0], "r")) == NULL) {
3123 int savederrno = errno;
3125 kill(preproc, SIGTERM);
3127 err(EX_OSERR, "fdopen()");
3132 while (fgets(buf, BUFSIZ, f)) {
3134 sprintf(linename, "Line %d", lineno);
3139 if ((p = strchr(buf, '#')) != NULL)
3144 for (a = strtok(buf, WHITESP); a && i < MAX_ARGS;
3145 a = strtok(NULL, WHITESP), i++) {
3149 if (i == (qflag? 2: 1))
3152 errx(EX_USAGE, "%s: too many arguments", linename);
3159 if (waitpid(preproc, &status, 0) == -1)
3160 errx(EX_OSERR, "waitpid()");
3161 if (WIFEXITED(status) && WEXITSTATUS(status) != EX_OK)
3162 errx(EX_UNAVAILABLE, "preprocessor exited with status %d",
3163 WEXITSTATUS(status));
3164 else if (WIFSIGNALED(status))
3165 errx(EX_UNAVAILABLE, "preprocessor exited with signal %d",
3171 main(int ac, char *av[])
3173 ipfw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
3174 if (ipfw_socket < 0)
3175 err(EX_UNAVAILABLE, "socket");
3177 memset(keywords, 0, sizeof(struct ipfw_keyword) * KEYWORD_SIZE);
3178 memset(mappings, 0, sizeof(struct ipfw_mapping) * MAPPING_SIZE);
3180 prepare_default_funcs();
3182 if (ac > 1 && av[ac - 1][0] == '/' && access(av[ac - 1], R_OK) == 0)
3183 ipfw_readfile(ac, av);