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 static uint32_t new_rule_buf[IPFW_RULE_SIZE_MAX]; /* buf use in do_get/set_x */
251 struct ipfw_keyword keywords[KEYWORD_SIZE];
252 struct ipfw_mapping mappings[MAPPING_SIZE];
255 match_token(struct char_int_map *table, char *string)
258 if (strcmp(table->key, string) == 0) {
267 get_modules(char *modules_str, int len)
269 if (do_get_x(IP_FW_MODULE, modules_str, &len) < 0)
270 errx(EX_USAGE, "ipfw3 not loaded.");
274 list_modules(int ac, char *av[])
276 void *module_str = NULL;
278 if ((module_str = realloc(module_str, len)) == NULL)
279 err(EX_OSERR, "realloc");
281 get_modules(module_str, len);
282 printf("%s", (char *)module_str);
285 parse_accept(ipfw_insn **cmd, int *ac, char **av[])
287 (*cmd)->opcode = O_BASIC_ACCEPT;
288 (*cmd)->module = MODULE_BASIC_ID;
289 (*cmd)->len = (*cmd)->len|LEN_OF_IPFWINSN;
294 parse_deny(ipfw_insn **cmd, int *ac, char **av[])
296 (*cmd)->opcode = O_BASIC_DENY;
297 (*cmd)->module = MODULE_BASIC_ID;
298 (*cmd)->len = (*cmd)->len|LEN_OF_IPFWINSN;
303 show_accept(ipfw_insn *cmd)
309 show_deny(ipfw_insn *cmd)
318 init_module mod_init_func;
320 char module_lib_file[50];
321 void *module_str = NULL;
324 if ((module_str = realloc(module_str, len)) == NULL)
325 err(EX_OSERR, "realloc");
327 get_modules(module_str, len);
329 const char s[2] = ",";
331 token = strtok(module_str, s);
332 while (token != NULL) {
333 sprintf(module_lib_file, IPFW_LIB_PATH, token);
334 token = strtok(NULL, s);
335 module_lib = dlopen(module_lib_file, RTLD_LAZY);
337 fprintf(stderr, "Couldn't open %s: %s\n",
338 module_lib_file, dlerror());
341 mod_init_func = dlsym(module_lib, "load_module");
342 if ((error = dlerror()))
344 fprintf(stderr, "Couldn't find init function: %s\n", error);
347 (*mod_init_func)((register_func)register_ipfw_func,
348 (register_keyword)register_ipfw_keyword);
353 prepare_default_funcs()
356 register_ipfw_keyword(MODULE_BASIC_ID, O_BASIC_ACCEPT,
357 "allow", IPFW_KEYWORD_TYPE_ACTION);
358 register_ipfw_keyword(MODULE_BASIC_ID, O_BASIC_ACCEPT,
359 "accept", IPFW_KEYWORD_TYPE_ACTION);
360 register_ipfw_func(MODULE_BASIC_ID, O_BASIC_ACCEPT,
361 (parser_func)parse_accept, (shower_func)show_accept);
363 register_ipfw_keyword(MODULE_BASIC_ID, O_BASIC_DENY, "deny",
364 IPFW_KEYWORD_TYPE_ACTION);
365 register_ipfw_keyword(MODULE_BASIC_ID, O_BASIC_DENY, "reject",
366 IPFW_KEYWORD_TYPE_ACTION);
367 register_ipfw_func(MODULE_BASIC_ID, O_BASIC_DENY,
368 (parser_func)parse_deny, (shower_func)show_deny);
372 register_ipfw_keyword(int module, int opcode, char *word, int type)
374 struct ipfw_keyword *tmp;
378 if (tmp->type == IPFW_KEYWORD_TYPE_NONE) {
379 strcpy(tmp->word, word);
380 tmp->module = module;
381 tmp->opcode = opcode;
385 if (strcmp(tmp->word, word) == 0)
386 errx(EX_USAGE, "keyword `%s' exists", word);
394 register_ipfw_func(int module, int opcode, parser_func parser, shower_func shower)
396 struct ipfw_mapping *tmp;
400 if (tmp->type == IPFW_MAPPING_TYPE_NONE) {
401 tmp->module = module;
402 tmp->opcode = opcode;
403 tmp->parser = parser;
404 tmp->shower = shower;
405 tmp->type = IPFW_MAPPING_TYPE_IN_USE;
408 if (tmp->opcode == opcode && tmp->module == module) {
409 errx(EX_USAGE, "func `%d' of module `%d' exists",
420 show_rules(struct ipfw_ioc_rule *rule, int pcwidth, int bcwidth)
422 static int twidth = 0;
424 int l, or_block = 0; /* we are in an or block */
426 u_int32_t set_disable = rule->set_disable;
428 if (set_disable & (1 << rule->set)) { /* disabled */
432 printf("# DISABLED ");
434 printf("%05u ", rule->rulenum);
437 printf("%*ju %*ju ", pcwidth, (uintmax_t)rule->pcnt, bcwidth,
438 (uintmax_t)rule->bcnt);
444 strcpy(timestr, ctime((time_t *)&twidth));
445 *strchr(timestr, '\n') = '\0';
446 twidth = strlen(timestr);
448 if (rule->timestamp) {
449 time_t t = _long_to_time(rule->timestamp);
451 strcpy(timestr, ctime(&t));
452 *strchr(timestr, '\n') = '\0';
453 printf("%s ", timestr);
455 printf("%*s ", twidth, " ");
457 } else if (do_time == 2) {
458 printf( "%10u ", rule->timestamp);
462 printf("set %d ", rule->set);
465 struct ipfw_keyword *k;
466 struct ipfw_mapping *m;
467 shower_func fn, comment_fn = NULL;
468 ipfw_insn *comment_cmd;
472 * show others and actions
474 for (l = rule->cmd_len - rule->act_ofs, cmd = ACTION_PTR(rule);
475 l > 0; l -= F_LEN(cmd),
476 cmd = (ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) {
479 for (i = 1; i< KEYWORD_SIZE; i++, k++) {
480 if ( k->module == cmd->module && k->opcode == cmd->opcode ) {
481 for (j = 1; j< MAPPING_SIZE; j++, m++) {
482 if (m->type == IPFW_MAPPING_TYPE_IN_USE &&
483 m->module == cmd->module &&
484 m->opcode == cmd->opcode) {
485 if (cmd->module == MODULE_BASIC_ID &&
486 cmd->opcode == O_BASIC_COMMENT) {
487 comment_fn = m->shower;
493 if (cmd->module == MODULE_BASIC_ID &&
495 O_BASIC_CHECK_STATE) {
510 for (l = rule->act_ofs, cmd = rule->cmd;
511 l > 0;l -= F_LEN(cmd) ,
512 cmd = (ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) {
515 for (i = 1; i< KEYWORD_SIZE; i++, k++) {
516 if (k->type == IPFW_KEYWORD_TYPE_FILTER &&
517 strcmp(k->word, "proto") == 0) {
518 if (k->module == cmd->module &&
519 k->opcode == cmd->opcode) {
520 for (j = 1; j< MAPPING_SIZE; j++, m++) {
521 if (m->type == IPFW_MAPPING_TYPE_IN_USE &&
522 k->module == m->module &&
523 k->opcode == m->opcode) {
524 if (cmd->len & F_NOT) {
537 if (!changed && !do_quiet)
545 for (l = rule->act_ofs, cmd = rule->cmd;
546 l > 0; l -= F_LEN(cmd),
547 cmd = (ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) {
550 for (i = 1; i< KEYWORD_SIZE; i++, k++) {
551 if (k->type == IPFW_KEYWORD_TYPE_FILTER &&
552 strcmp(k->word, "from") == 0) {
553 if (k->module == cmd->module &&
554 k->opcode == cmd->opcode) {
555 for (j = 1; j< MAPPING_SIZE; j++, m++) {
556 if (m->type == IPFW_MAPPING_TYPE_IN_USE &&
557 k->module == m->module &&
558 k->opcode == m->opcode) {
559 if (cmd->len & F_NOT)
572 if (!changed && !do_quiet)
580 for (l = rule->act_ofs, cmd = rule->cmd;
581 l > 0; l -= F_LEN(cmd),
582 cmd = (ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) {
585 for (i = 1; i< KEYWORD_SIZE; i++, k++) {
586 if (k->type == IPFW_KEYWORD_TYPE_FILTER &&
587 strcmp(k->word, "to") == 0) {
588 if (k->module == cmd->module &&
589 k->opcode == cmd->opcode) {
590 for (j = 1; j < MAPPING_SIZE; j++, m++) {
591 if (m->type == IPFW_MAPPING_TYPE_IN_USE &&
592 k->module == m->module &&
593 k->opcode == m->opcode ) {
594 if (cmd->len & F_NOT)
607 if (!changed && !do_quiet)
614 for (l = rule->act_ofs, cmd = rule->cmd, m = mappings;
615 l > 0; l -= F_LEN(cmd),
616 cmd=(ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) {
619 for (i = 1; i< KEYWORD_SIZE; i++, k++) {
620 if (k->module == cmd->module && k->opcode == cmd->opcode) {
621 if (strcmp(k->word, "proto") != 0 &&
622 strcmp(k->word, "from") !=0 &&
623 strcmp(k->word, "to") !=0) {
624 for (j = 1; j < MAPPING_SIZE; j++, m++) {
625 if (m->module == cmd->module &&
626 m->opcode == cmd->opcode) {
627 if (cmd->len & F_NOT)
640 if (cmd->len & F_OR) {
643 } else if (or_block) {
648 /* show the comment in the end */
649 if (comment_fn != NULL) {
650 (*comment_fn)(comment_cmd);
657 show_states(struct ipfw_ioc_state *d, int pcwidth, int bcwidth)
662 printf("%05u ", d->rulenum);
664 printf("%*ju %*ju ", pcwidth, (uintmax_t)d->pcnt,
665 bcwidth, (uintmax_t)d->bcnt);
669 /* state->timestamp */
671 time_t t = _long_to_time(d->timestamp);
672 strcpy(timestr, ctime(&t));
673 *strchr(timestr, '\n') = '\0';
674 printf(" (%s", timestr);
676 /* state->lifetime */
677 printf(" %ds", d->lifetime);
681 t = _long_to_time(d->expiry);
682 strcpy(timestr, ctime(&t));
683 *strchr(timestr, '\n') = '\0';
684 printf(" %s)", timestr);
689 } else if (do_time == 2) {
690 printf("(%u %ds %u) ", d->timestamp, d->lifetime, d->expiry);
693 if ((pe = getprotobynumber(d->flow_id.proto)) != NULL)
694 printf(" %s", pe->p_name);
696 printf(" proto %u", d->flow_id.proto);
698 a.s_addr = htonl(d->flow_id.src_ip);
699 printf(" %s %d", inet_ntoa(a), d->flow_id.src_port);
701 a.s_addr = htonl(d->flow_id.dst_ip);
702 printf(" <-> %s %d", inet_ntoa(a), d->flow_id.dst_port);
703 printf(" CPU %d", d->cpuid);
708 sort_q(const void *pa, const void *pb)
710 int rev = (do_sort < 0);
711 int field = rev ? -do_sort : do_sort;
713 const struct dn_ioc_flowqueue *a = pa;
714 const struct dn_ioc_flowqueue *b = pb;
718 res = a->len - b->len;
721 res = a->len_bytes - b->len_bytes;
724 case 3: /* tot pkts */
725 res = a->tot_pkts - b->tot_pkts;
728 case 4: /* tot bytes */
729 res = a->tot_bytes - b->tot_bytes;
736 return (int)(rev ? res : -res);
740 show_queues(struct dn_ioc_flowset *fs, struct dn_ioc_flowqueue *q)
744 printf("mask: 0x%02x 0x%08x/0x%04x -> 0x%08x/0x%04x\n",
745 fs->flow_mask.u.ip.proto,
746 fs->flow_mask.u.ip.src_ip, fs->flow_mask.u.ip.src_port,
747 fs->flow_mask.u.ip.dst_ip, fs->flow_mask.u.ip.dst_port);
748 if (fs->rq_elements == 0)
751 printf("BKT Prot ___Source IP/port____ "
752 "____Dest. IP/port____ Tot_pkt/bytes Pkt/Byte Drp\n");
754 heapsort(q, fs->rq_elements, sizeof(*q), sort_q);
755 for (l = 0; l < fs->rq_elements; l++) {
759 ina.s_addr = htonl(q[l].id.u.ip.src_ip);
760 printf("%3d ", q[l].hash_slot);
761 pe = getprotobynumber(q[l].id.u.ip.proto);
763 printf("%-4s ", pe->p_name);
765 printf("%4u ", q[l].id.u.ip.proto);
767 inet_ntoa(ina), q[l].id.u.ip.src_port);
768 ina.s_addr = htonl(q[l].id.u.ip.dst_ip);
770 inet_ntoa(ina), q[l].id.u.ip.dst_port);
771 printf("%4ju %8ju %2u %4u %3u\n",
772 (uintmax_t)q[l].tot_pkts, (uintmax_t)q[l].tot_bytes,
773 q[l].len, q[l].len_bytes, q[l].drops);
775 printf(" S %20ju F %20ju\n",
776 (uintmax_t)q[l].S, (uintmax_t)q[l].F);
781 show_flowset_parms(struct dn_ioc_flowset *fs, char *prefix)
785 char red[90]; /* Display RED parameters */
789 if (fs->flags_fs & DN_QSIZE_IS_BYTES) {
791 sprintf(qs, "%d KB", l / 1024);
793 sprintf(qs, "%d B", l);
795 sprintf(qs, "%3d sl.", l);
797 sprintf(plr, "plr %f", 1.0 * fs->plr / (double)(0x7fffffff));
800 if (fs->flags_fs & DN_IS_RED) /* RED parameters */
802 "\n\t %cRED w_q %f min_th %d max_th %d max_p %f",
803 (fs->flags_fs & DN_IS_GENTLE_RED) ? 'G' : ' ',
804 1.0 * fs->w_q / (double)(1 << SCALE_RED),
805 SCALE_VAL(fs->min_th),
806 SCALE_VAL(fs->max_th),
807 1.0 * fs->max_p / (double)(1 << SCALE_RED));
809 sprintf(red, "droptail");
811 printf("%s %s%s %d queues (%d buckets) %s\n",
812 prefix, qs, plr, fs->rq_elements, fs->rq_size, red);
816 show_pipes(void *data, int nbytes, int ac, char *av[])
820 struct dn_ioc_pipe *p = (struct dn_ioc_pipe *)data;
821 struct dn_ioc_flowset *fs;
822 struct dn_ioc_flowqueue *q;
826 rulenum = strtoul(*av++, NULL, 10);
829 for (; nbytes >= sizeof(*p); p = (struct dn_ioc_pipe *)next) {
830 double b = p->bandwidth;
834 if (p->fs.fs_type != DN_IS_PIPE)
835 break; /* done with pipes, now queues */
838 * compute length, as pipe have variable size
840 l = sizeof(*p) + p->fs.rq_elements * sizeof(*q);
841 next = (void *)p + l;
844 if (rulenum != 0 && rulenum != p->pipe_nr)
851 sprintf(buf, "unlimited");
852 else if (b >= 1000000)
853 sprintf(buf, "%7.3f Mbit/s", b/1000000);
855 sprintf(buf, "%7.3f Kbit/s", b/1000);
857 sprintf(buf, "%7.3f bit/s ", b);
859 sprintf(prefix, "%05d: %s %4d ms ",
860 p->pipe_nr, buf, p->delay);
861 show_flowset_parms(&p->fs, prefix);
863 printf(" V %20ju\n", (uintmax_t)p->V >> MY_M);
865 q = (struct dn_ioc_flowqueue *)(p+1);
866 show_queues(&p->fs, q);
869 for (fs = next; nbytes >= sizeof(*fs); fs = next) {
872 if (fs->fs_type != DN_IS_QUEUE)
874 l = sizeof(*fs) + fs->rq_elements * sizeof(*q);
875 next = (void *)fs + l;
877 q = (struct dn_ioc_flowqueue *)(fs+1);
878 sprintf(prefix, "q%05d: weight %d pipe %d ",
879 fs->fs_nr, fs->weight, fs->parent_nr);
880 show_flowset_parms(fs, prefix);
886 * This one handles all set-related commands
887 * ipfw set { show | enable | disable }
889 * ipfw set move X to Y
890 * ipfw set move rule X to Y
893 sets_handler(int ac, char *av[])
895 u_int32_t set_disable, masks[2];
897 u_int8_t cmd, new_set;
902 errx(EX_USAGE, "set needs command");
903 if (!strncmp(*av, "show", strlen(*av)) ) {
909 while (nbytes >= nalloc) {
910 nalloc = nalloc * 2+321;
913 if ((data = malloc(nbytes)) == NULL) {
914 err(EX_OSERR, "malloc");
916 } else if ((data = realloc(data, nbytes)) == NULL) {
917 err(EX_OSERR, "realloc");
919 if (do_get_x(IP_FW_GET, data, &nbytes) < 0) {
920 err(EX_OSERR, "getsockopt(IP_FW_GET)");
923 set_disable = ((struct ipfw_ioc_rule *)data)->set_disable;
924 for (i = 0, msg = "disable" ; i < 31; i++)
925 if ( (set_disable & (1<<i))) {
926 printf("%s %d", msg, i);
929 msg = (set_disable) ? " enable" : "enable";
930 for (i = 0; i < 31; i++)
931 if ( !(set_disable & (1<<i))) {
932 printf("%s %d", msg, i);
936 } else if (!strncmp(*av, "swap", strlen(*av))) {
939 errx(EX_USAGE, "set swap needs 2 set numbers\n");
940 rulenum = atoi(av[0]);
941 new_set = atoi(av[1]);
942 if (!isdigit(*(av[0])) || rulenum > 30)
943 errx(EX_DATAERR, "invalid set number %s\n", av[0]);
944 if (!isdigit(*(av[1])) || new_set > 30)
945 errx(EX_DATAERR, "invalid set number %s\n", av[1]);
946 masks[0] = (4 << 24) | (new_set << 16) | (rulenum);
947 i = do_set_x(IP_FW_DEL, masks, sizeof(u_int32_t));
948 } else if (!strncmp(*av, "move", strlen(*av))) {
950 if (ac && !strncmp(*av, "rule", strlen(*av))) {
955 if (ac != 3 || strncmp(av[1], "to", strlen(*av)))
956 errx(EX_USAGE, "syntax: set move [rule] X to Y\n");
957 rulenum = atoi(av[0]);
958 new_set = atoi(av[2]);
959 if (!isdigit(*(av[0])) || (cmd == 3 && rulenum > 30) ||
960 (cmd == 2 && rulenum == 65535) )
961 errx(EX_DATAERR, "invalid source number %s\n", av[0]);
962 if (!isdigit(*(av[2])) || new_set > 30)
963 errx(EX_DATAERR, "invalid dest. set %s\n", av[1]);
964 masks[0] = (cmd << 24) | (new_set << 16) | (rulenum);
965 i = do_set_x(IP_FW_DEL, masks, sizeof(u_int32_t));
966 } else if (!strncmp(*av, "disable", strlen(*av)) ||
967 !strncmp(*av, "enable", strlen(*av)) ) {
968 int which = !strncmp(*av, "enable", strlen(*av)) ? 1 : 0;
971 masks[0] = masks[1] = 0;
977 errx(EX_DATAERR, "invalid set number %d\n", i);
978 masks[which] |= (1<<i);
979 } else if (!strncmp(*av, "disable", strlen(*av)))
981 else if (!strncmp(*av, "enable", strlen(*av)))
984 errx(EX_DATAERR, "invalid set command %s\n", *av);
987 if ( (masks[0] & masks[1]) != 0 )
988 errx(EX_DATAERR, "cannot enable and disable the same set\n");
989 i = do_set_x(IP_FW_DEL, masks, sizeof(masks));
991 warn("set enable/disable: setsockopt(IP_FW_DEL)");
993 errx(EX_USAGE, "invalid set command %s\n", *av);
997 add_state(int ac, char *av[])
999 struct ipfw_ioc_state ioc_state;
1000 ioc_state.expiry = 0;
1001 ioc_state.lifetime = 0;
1003 if (strcmp(*av, "rulenum") == 0) {
1005 ioc_state.rulenum = atoi(*av);
1007 errx(EX_USAGE, "ipfw state add rule");
1010 struct protoent *pe;
1011 pe = getprotobyname(*av);
1012 ioc_state.flow_id.proto = pe->p_proto;
1015 ioc_state.flow_id.src_ip = inet_addr(*av);
1018 ioc_state.flow_id.src_port = atoi(*av);
1021 ioc_state.flow_id.dst_ip = inet_addr(*av);
1024 ioc_state.flow_id.dst_port = atoi(*av);
1027 if (strcmp(*av, "live") == 0) {
1029 ioc_state.lifetime = atoi(*av);
1033 if (strcmp(*av, "expiry") == 0) {
1035 ioc_state.expiry = strtoul(*av, NULL, 10);
1036 printf("ioc_state.expiry=%d\n", ioc_state.expiry);
1039 if (do_set_x(IP_FW_STATE_ADD, &ioc_state, sizeof(struct ipfw_ioc_state)) < 0 ) {
1040 err(EX_UNAVAILABLE, "do_set_x(IP_FW_STATE_ADD)");
1043 printf("Flushed all states.\n");
1048 delete_state(int ac, char *av[])
1052 if (ac == 1 && isdigit(**av))
1053 rulenum = atoi(*av);
1054 if (do_set_x(IP_FW_STATE_DEL, &rulenum, sizeof(int)) < 0 )
1055 err(EX_UNAVAILABLE, "do_set_x(IP_FW_STATE_DEL)");
1057 printf("Flushed all states.\n");
1061 flush_state(int ac, char *av[])
1066 printf("Are you sure? [yn] ");
1069 c = toupper(getc(stdin));
1070 while (c != '\n' && getc(stdin) != '\n')
1072 return; /* and do not flush */
1073 } while (c != 'Y' && c != 'N');
1074 if (c == 'N') /* user said no */
1077 if (do_set_x(IP_FW_STATE_FLUSH, NULL, 0) < 0 )
1078 err(EX_UNAVAILABLE, "do_set_x(IP_FW_STATE_FLUSH)");
1080 printf("Flushed all states.\n");
1084 list(int ac, char *av[])
1086 struct ipfw_ioc_state *dynrules, *d;
1087 struct ipfw_ioc_rule *r;
1091 int bcwidth, n, nbytes, nstat, ndyn, pcwidth, width;
1092 int exitval = EX_OK, lac;
1093 char **lav, *endptr;
1099 /* get rules or pipes from kernel, resizing array as necessary */
1102 while (nbytes >= nalloc) {
1103 nalloc = nalloc * 2 ;
1105 if ((data = realloc(data, nbytes)) == NULL)
1106 err(EX_OSERR, "realloc");
1107 if (do_get_x(IP_FW_GET, data, &nbytes) < 0)
1108 err(EX_OSERR, "do_get_x(IP_FW_GET)");
1112 * Count static rules.
1115 nstat = r->static_count;
1118 * Count dynamic rules. This is easier as they have
1121 dynrules = (struct ipfw_ioc_state *)((void *)r + r->static_len);
1122 ndyn = (nbytes - r->static_len) / sizeof(*dynrules);
1124 /* if showing stats, figure out column widths ahead of time */
1125 bcwidth = pcwidth = 0;
1127 for (n = 0, r = data; n < nstat;
1128 n++, r = (void *)r + IOC_RULESIZE(r)) {
1129 /* packet counter */
1130 width = snprintf(NULL, 0, "%ju", (uintmax_t)r->pcnt);
1131 if (width > pcwidth)
1135 width = snprintf(NULL, 0, "%ju", (uintmax_t)r->bcnt);
1136 if (width > bcwidth)
1140 if (do_dynamic && ndyn) {
1141 for (n = 0, d = dynrules; n < ndyn; n++, d++) {
1142 width = snprintf(NULL, 0, "%ju", (uintmax_t)d->pcnt);
1143 if (width > pcwidth)
1146 width = snprintf(NULL, 0, "%ju", (uintmax_t)d->bcnt);
1147 if (width > bcwidth)
1152 /* if no rule numbers were specified, list all rules */
1154 if (do_dynamic != 2) {
1155 for (n = 0, r = data; n < nstat; n++,
1156 r = (void *)r + IOC_RULESIZE(r)) {
1157 show_rules(r, pcwidth, bcwidth);
1160 if (do_dynamic && ndyn) {
1161 if (do_dynamic != 2) {
1162 printf("## States (%d):\n", ndyn);
1164 for (n = 0, d = dynrules; n < ndyn; n++, d++)
1165 show_states(d, pcwidth, bcwidth);
1170 /* display specific rules requested on command line */
1172 if (do_dynamic != 2) {
1173 for (lac = ac, lav = av; lac != 0; lac--) {
1174 /* convert command line rule # */
1175 rnum = strtoul(*lav++, &endptr, 10);
1178 warnx("invalid rule number: %s", *(lav - 1));
1181 for (n = seen = 0, r = data; n < nstat;
1182 n++, r = (void *)r + IOC_RULESIZE(r) ) {
1183 if (r->rulenum > rnum)
1185 if (r->rulenum == rnum) {
1186 show_rules(r, pcwidth, bcwidth);
1191 /* give precedence to other error(s) */
1192 if (exitval == EX_OK)
1193 exitval = EX_UNAVAILABLE;
1194 warnx("rule %lu does not exist", rnum);
1199 if (do_dynamic && ndyn) {
1200 if (do_dynamic != 2) {
1201 printf("## States (%d):\n", ndyn);
1203 for (lac = ac, lav = av; lac != 0; lac--) {
1204 rnum = strtoul(*lav++, &endptr, 10);
1206 /* already warned */
1208 for (n = 0, d = dynrules; n < ndyn; n++, d++) {
1209 if (d->rulenum > rnum)
1211 if (d->rulenum == rnum)
1212 show_states(d, pcwidth, bcwidth);
1222 if (exitval != EX_OK)
1227 show_dummynet(int ac, char *av[])
1231 int nalloc = 1024; /* start somewhere... */
1236 while (nbytes >= nalloc) {
1237 nalloc = nalloc * 2 + 200;
1239 if ((data = realloc(data, nbytes)) == NULL)
1240 err(EX_OSERR, "realloc");
1241 if (do_get_x(IP_DUMMYNET_GET, data, &nbytes) < 0) {
1242 err(EX_OSERR, "do_get_x(IP_%s_GET)",
1243 do_pipe ? "DUMMYNET" : "FW");
1247 show_pipes(data, nbytes, ac, av);
1254 fprintf(stderr, "usage: ipfw [options]\n"
1255 " ipfw add [rulenum] [set id] action filters\n"
1256 " ipfw delete [rulenum]\n"
1258 " ipfw list [rulenum]\n"
1259 " ipfw show [rulenum]\n"
1260 " ipfw zero [rulenum]\n"
1261 " ipfw set [show|enable|disable]\n"
1263 " ipfw [enable|disable]\n"
1264 " ipfw log [reset|off|on]\n"
1265 " ipfw nat [config|show|delete]\n"
1266 " ipfw pipe [config|show|delete]\n"
1267 " ipfw state [add|delete|list|show]"
1268 "\nsee ipfw manpage for details\n");
1273 delete_nat_config(int ac, char *av[])
1280 if (do_set_x(IP_FW_NAT_DEL, &i, sizeof(i)) == -1)
1281 err(EX_UNAVAILABLE, "getsockopt(%s)", "IP_FW_NAT_DEL");
1285 delete_rules(int ac, char *av[])
1287 struct dn_ioc_pipe pipe;
1289 int exitval = EX_OK;
1293 memset(&pipe, 0, sizeof pipe);
1296 if (ac > 0 && !strncmp(*av, "set", strlen(*av))) {
1297 do_set = 1; /* delete set */
1302 while (ac && isdigit(**av)) {
1311 i = do_set_x(IP_DUMMYNET_DEL, &pipe, sizeof pipe);
1314 warn("rule %u: setsockopt(IP_DUMMYNET_DEL)",
1315 do_pipe == 1 ? pipe.pipe_nr : pipe.fs.fs_nr);
1318 rulenum = (i & 0xffff) | (do_set << 24);
1319 i = do_set_x(IP_FW_DEL, &rulenum, sizeof rulenum);
1321 exitval = EX_UNAVAILABLE;
1322 warn("rule %u: setsockopt(IP_FW_DEL)",
1327 if (exitval != EX_OK)
1332 static unsigned long
1333 getbw(const char *str, u_short *flags, int kb)
1339 val = strtoul(str, &end, 0);
1340 if (*end == 'k' || *end == 'K') {
1343 } else if (*end == 'm' || *end == 'M') {
1349 * Deal with bits or bytes or b(bits) or B(bytes). If there is no
1350 * trailer assume bits.
1352 if (strncasecmp(end, "bit", 3) == 0) {
1354 } else if (strncasecmp(end, "byte", 4) == 0) {
1356 } else if (*end == 'b') {
1358 } else if (*end == 'B') {
1363 * Return in bits if flags is NULL, else flag bits
1364 * or bytes in flags and return the unconverted value.
1366 if (inbytes && flags)
1367 *flags |= DN_QSIZE_IS_BYTES;
1368 else if (inbytes && flags == NULL)
1375 * config dummynet pipe/queue
1378 config_dummynet(int ac, char **av)
1380 struct dn_ioc_pipe pipe;
1387 memset(&pipe, 0, sizeof pipe);
1389 if (ac && isdigit(**av)) {
1401 int tok = match_token(dummynet_params, *av);
1406 pipe.fs.flags_fs |= DN_NOERROR;
1410 NEED1("plr needs argument 0..1\n");
1411 d = strtod(av[0], NULL);
1416 pipe.fs.plr = (int)(d*0x7fffffff);
1421 NEED1("queue needs queue size\n");
1423 pipe.fs.qsize = getbw(av[0], &pipe.fs.flags_fs, 1024);
1428 NEED1("buckets needs argument\n");
1429 pipe.fs.rq_size = strtoul(av[0], NULL, 0);
1434 NEED1("mask needs mask specifier\n");
1436 * per-flow queue, mask is dst_ip, dst_port,
1437 * src_ip, src_port, proto measured in bits
1441 pipe.fs.flow_mask.type = ETHERTYPE_IP;
1442 pipe.fs.flow_mask.u.ip.dst_ip = 0;
1443 pipe.fs.flow_mask.u.ip.src_ip = 0;
1444 pipe.fs.flow_mask.u.ip.dst_port = 0;
1445 pipe.fs.flow_mask.u.ip.src_port = 0;
1446 pipe.fs.flow_mask.u.ip.proto = 0;
1450 u_int32_t *p32 = NULL;
1451 u_int16_t *p16 = NULL;
1453 tok = match_token(dummynet_params, *av);
1458 * special case, all bits significant
1460 pipe.fs.flow_mask.u.ip.dst_ip = ~0;
1461 pipe.fs.flow_mask.u.ip.src_ip = ~0;
1462 pipe.fs.flow_mask.u.ip.dst_port = ~0;
1463 pipe.fs.flow_mask.u.ip.src_port = ~0;
1464 pipe.fs.flow_mask.u.ip.proto = ~0;
1465 pipe.fs.flags_fs |= DN_HAVE_FLOW_MASK;
1469 p32 = &pipe.fs.flow_mask.u.ip.dst_ip;
1473 p32 = &pipe.fs.flow_mask.u.ip.src_ip;
1477 p16 = &pipe.fs.flow_mask.u.ip.dst_port;
1481 p16 = &pipe.fs.flow_mask.u.ip.src_port;
1492 errx(EX_USAGE, "mask: value missing");
1493 if (*av[0] == '/') {
1494 a = strtoul(av[0]+1, &end, 0);
1495 a = (a == 32) ? ~0 : (1 << a) - 1;
1497 a = strtoul(av[0], &end, 0);
1500 else if (p16 != NULL) {
1503 "mask: must be 16 bit");
1504 *p16 = (u_int16_t)a;
1508 "mask: must be 8 bit");
1509 pipe.fs.flow_mask.u.ip.proto = (uint8_t)a;
1512 pipe.fs.flags_fs |= DN_HAVE_FLOW_MASK;
1514 } /* end while, config masks */
1521 NEED1("red/gred needs w_q/min_th/max_th/max_p\n");
1522 pipe.fs.flags_fs |= DN_IS_RED;
1523 if (tok == TOK_GRED)
1524 pipe.fs.flags_fs |= DN_IS_GENTLE_RED;
1526 * the format for parameters is w_q/min_th/max_th/max_p
1528 if ((end = strsep(&av[0], "/"))) {
1529 double w_q = strtod(end, NULL);
1530 if (w_q > 1 || w_q <= 0)
1531 errx(EX_DATAERR, "0 < w_q <= 1");
1532 pipe.fs.w_q = (int) (w_q * (1 << SCALE_RED));
1534 if ((end = strsep(&av[0], "/"))) {
1535 pipe.fs.min_th = strtoul(end, &end, 0);
1536 if (*end == 'K' || *end == 'k')
1537 pipe.fs.min_th *= 1024;
1539 if ((end = strsep(&av[0], "/"))) {
1540 pipe.fs.max_th = strtoul(end, &end, 0);
1541 if (*end == 'K' || *end == 'k')
1542 pipe.fs.max_th *= 1024;
1544 if ((end = strsep(&av[0], "/"))) {
1545 double max_p = strtod(end, NULL);
1546 if (max_p > 1 || max_p <= 0)
1547 errx(EX_DATAERR, "0 < max_p <= 1");
1548 pipe.fs.max_p = (int)(max_p * (1 << SCALE_RED));
1554 pipe.fs.flags_fs &= ~(DN_IS_RED|DN_IS_GENTLE_RED);
1558 NEED1("bw needs bandwidth\n");
1560 errx(EX_DATAERR, "bandwidth only valid for pipes");
1562 * set bandwidth value
1564 pipe.bandwidth = getbw(av[0], NULL, 1000);
1565 if (pipe.bandwidth < 0)
1566 errx(EX_DATAERR, "bandwidth too large");
1572 errx(EX_DATAERR, "delay only valid for pipes");
1573 NEED1("delay needs argument 0..10000ms\n");
1574 pipe.delay = strtoul(av[0], NULL, 0);
1580 errx(EX_DATAERR, "weight only valid for queues");
1581 NEED1("weight needs argument 0..100\n");
1582 pipe.fs.weight = strtoul(av[0], &end, 0);
1588 errx(EX_DATAERR, "pipe only valid for queues");
1589 NEED1("pipe needs pipe_number\n");
1590 pipe.fs.parent_nr = strtoul(av[0], &end, 0);
1595 errx(EX_DATAERR, "unrecognised option ``%s''", *av);
1599 if (pipe.pipe_nr == 0)
1600 errx(EX_DATAERR, "pipe_nr must be > 0");
1601 if (pipe.delay > 10000)
1602 errx(EX_DATAERR, "delay must be < 10000");
1603 } else { /* do_pipe == 2, queue */
1604 if (pipe.fs.parent_nr == 0)
1605 errx(EX_DATAERR, "pipe must be > 0");
1606 if (pipe.fs.weight >100)
1607 errx(EX_DATAERR, "weight must be <= 100");
1609 if (pipe.fs.flags_fs & DN_QSIZE_IS_BYTES) {
1610 if (pipe.fs.qsize > 1024*1024)
1611 errx(EX_DATAERR, "queue size must be < 1MB");
1613 if (pipe.fs.qsize > 100)
1614 errx(EX_DATAERR, "2 <= queue size <= 100");
1616 if (pipe.fs.flags_fs & DN_IS_RED) {
1618 int lookup_depth, avg_pkt_size;
1619 double s, idle, weight, w_q;
1623 if (pipe.fs.min_th >= pipe.fs.max_th)
1624 errx(EX_DATAERR, "min_th %d must be < than max_th %d",
1625 pipe.fs.min_th, pipe.fs.max_th);
1626 if (pipe.fs.max_th == 0)
1627 errx(EX_DATAERR, "max_th must be > 0");
1630 if (sysctlbyname("net.inet.ip.dummynet.red_lookup_depth",
1631 &lookup_depth, &len, NULL, 0) == -1)
1633 errx(1, "sysctlbyname(\"%s\")",
1634 "net.inet.ip.dummynet.red_lookup_depth");
1635 if (lookup_depth == 0)
1636 errx(EX_DATAERR, "net.inet.ip.dummynet.red_lookup_depth"
1637 " must be greater than zero");
1640 if (sysctlbyname("net.inet.ip.dummynet.red_avg_pkt_size",
1641 &avg_pkt_size, &len, NULL, 0) == -1)
1643 errx(1, "sysctlbyname(\"%s\")",
1644 "net.inet.ip.dummynet.red_avg_pkt_size");
1645 if (avg_pkt_size == 0)
1647 "net.inet.ip.dummynet.red_avg_pkt_size must"
1648 " be greater than zero");
1650 len = sizeof(clock_hz);
1651 if (sysctlbyname("net.inet.ip.dummynet.hz", &clock_hz, &len,
1653 errx(1, "sysctlbyname(\"%s\")",
1654 "net.inet.ip.dummynet.hz");
1658 * Ticks needed for sending a medium-sized packet.
1659 * Unfortunately, when we are configuring a WF2Q+ queue, we
1660 * do not have bandwidth information, because that is stored
1661 * in the parent pipe, and also we have multiple queues
1662 * competing for it. So we set s=0, which is not very
1663 * correct. But on the other hand, why do we want RED with
1666 if (pipe.bandwidth == 0) /* this is a WF2Q+ queue */
1669 s = clock_hz * avg_pkt_size * 8 / pipe.bandwidth;
1672 * max idle time (in ticks) before avg queue size becomes 0.
1673 * NOTA: (3/w_q) is approx the value x so that
1674 * (1-w_q)^x < 10^-3.
1676 w_q = ((double)pipe.fs.w_q) / (1 << SCALE_RED);
1677 idle = s * 3. / w_q;
1678 pipe.fs.lookup_step = (int)idle / lookup_depth;
1679 if (!pipe.fs.lookup_step)
1680 pipe.fs.lookup_step = 1;
1682 for (t = pipe.fs.lookup_step; t > 0; --t)
1684 pipe.fs.lookup_weight = (int)(weight * (1 << SCALE_RED));
1686 i = do_set_x(IP_DUMMYNET_CONFIGURE, &pipe, sizeof pipe);
1688 err(1, "do_set_x(%s)", "IP_DUMMYNET_CONFIGURE");
1692 * helper function, updates the pointer to cmd with the length
1693 * of the current command, and also cleans up the first word of
1694 * the new command in case it has been clobbered before.
1697 next_cmd(ipfw_insn *cmd)
1700 bzero(cmd, sizeof(*cmd));
1705 * Parse arguments and assemble the microinstructions which make up a rule.
1706 * Rules are added into the 'rulebuf' and then copied in the correct order
1707 * into the actual rule.
1712 add(int ac, char *av[])
1715 * rules are added into the 'rulebuf' and then copied in
1716 * the correct order into the actual rule.
1717 * Some things that need to go out of order (prob, action etc.)
1720 static uint32_t rulebuf[IPFW_RULE_SIZE_MAX];
1721 static uint32_t actbuf[IPFW_RULE_SIZE_MAX];
1722 static uint32_t othbuf[IPFW_RULE_SIZE_MAX];
1723 static uint32_t cmdbuf[IPFW_RULE_SIZE_MAX];
1725 ipfw_insn *src, *dst, *cmd, *action, *other;
1726 ipfw_insn *the_comment = NULL;
1727 struct ipfw_ioc_rule *rule;
1728 struct ipfw_keyword *key;
1729 struct ipfw_mapping *map;
1733 bzero(actbuf, sizeof(actbuf)); /* actions go here */
1734 bzero(othbuf, sizeof(actbuf)); /* others */
1735 bzero(cmdbuf, sizeof(cmdbuf)); /* filters */
1736 bzero(rulebuf, sizeof(rulebuf));
1738 rule = (struct ipfw_ioc_rule *)rulebuf;
1739 cmd = (ipfw_insn *)cmdbuf;
1740 action = (ipfw_insn *)actbuf;
1741 other = (ipfw_insn *)othbuf;
1743 NEED2("need more parameters");
1746 /* [rule N] -- Rule number optional */
1747 if (ac && isdigit(**av)) {
1748 rule->rulenum = atoi(*av);
1752 /* [set N] -- set number (0..30), optional */
1753 if (ac > 1 && !strncmp(*av, "set", strlen(*av))) {
1754 int set = strtoul(av[1], NULL, 10);
1755 if (set < 0 || set > 30)
1756 errx(EX_DATAERR, "illegal set %s", av[1]);
1765 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) {
1766 if (key->type == IPFW_KEYWORD_TYPE_OTHERS &&
1767 strcmp(key->word, *av) == 0) {
1768 for (j = 0, map = mappings;
1769 j < MAPPING_SIZE; j++, map++) {
1770 if (map->type == IPFW_MAPPING_TYPE_IN_USE &&
1771 map->module == key->module &&
1772 map->opcode == key->opcode ) {
1774 (*fn)(&other, &ac, &av);
1781 if (i >= KEYWORD_SIZE) {
1783 } else if (F_LEN(other) > 0) {
1784 if (other->module == MODULE_BASIC_ID &&
1785 other->opcode == O_BASIC_CHECK_STATE) {
1786 other = next_cmd(other);
1789 other = next_cmd(other);
1796 * only accept 1 action
1798 NEED1("missing action");
1799 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) {
1800 if (ac > 0 && key->type == IPFW_KEYWORD_TYPE_ACTION &&
1801 strcmp(key->word, *av) == 0) {
1802 for (j = 0, map = mappings; j<MAPPING_SIZE; j++, map++) {
1803 if (map->type == IPFW_MAPPING_TYPE_IN_USE &&
1804 map->module == key->module &&
1805 map->opcode == key->opcode) {
1807 (*fn)(&action, &ac, &av);
1814 if (F_LEN(action) > 0)
1815 action = next_cmd(action);
1820 if (strcmp(*av, "proto") == 0){
1824 NEED1("missing protocol");
1825 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) {
1826 if (key->type == IPFW_KEYWORD_TYPE_FILTER &&
1827 strcmp(key->word, "proto") == 0) {
1828 for (j = 0, map = mappings; j<MAPPING_SIZE; j++, map++) {
1829 if (map->type == IPFW_MAPPING_TYPE_IN_USE &&
1830 map->module == key->module &&
1831 map->opcode == key->opcode ) {
1833 (*fn)(&cmd, &ac, &av);
1841 cmd = next_cmd(cmd);
1848 ipfw_insn_u32 *cmd32; /* alias for cmd */
1851 cmd32 = (ipfw_insn_u32 *)cmd;
1852 if (strcmp(*av, "not") == 0) {
1853 if (cmd->len & F_NOT)
1854 errx(EX_USAGE, "double \"not\" not allowed\n");
1859 if (*s == '!') { /* alternate syntax for NOT */
1860 if (cmd->len & F_NOT)
1861 errx(EX_USAGE, "double \"not\" not allowed");
1865 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) {
1866 if (key->type == IPFW_KEYWORD_TYPE_FILTER &&
1867 strcmp(key->word, s) == 0) {
1868 for (j = 0, map = mappings;
1869 j< MAPPING_SIZE; j++, map++) {
1870 if (map->type == IPFW_MAPPING_TYPE_IN_USE &&
1871 map->module == key->module &&
1872 map->opcode == key->opcode ) {
1874 (*fn)(&cmd, &ac, &av);
1879 } else if (i == KEYWORD_SIZE-1) {
1880 errx(EX_USAGE, "bad command `%s'", s);
1883 if (i >= KEYWORD_SIZE) {
1885 } else if (F_LEN(cmd) > 0) {
1886 cmd = next_cmd(cmd);
1892 errx(EX_USAGE, "bad command `%s'", *av);
1895 * Now copy stuff into the rule.
1896 * [filters][others][action][comment]
1898 dst = (ipfw_insn *)rule->cmd;
1900 * copy all filters, except comment
1902 src = (ipfw_insn *)cmdbuf;
1903 for (src = (ipfw_insn *)cmdbuf; src != cmd; src += i) {
1904 /* pick comment out */
1906 if (src->module == MODULE_BASIC_ID && src->opcode == O_BASIC_COMMENT) {
1909 bcopy(src, dst, i * sizeof(u_int32_t));
1910 dst = (ipfw_insn *)((uint32_t *)dst + i);
1915 * start action section, it begin with others
1917 rule->act_ofs = (uint32_t *)dst - (uint32_t *)(rule->cmd);
1920 * copy all other others
1922 for (src = (ipfw_insn *)othbuf; src != other; src += i) {
1924 bcopy(src, dst, i * sizeof(u_int32_t));
1925 dst = (ipfw_insn *)((uint32_t *)dst + i);
1928 /* copy the action to the end of rule */
1929 src = (ipfw_insn *)actbuf;
1931 bcopy(src, dst, i * sizeof(u_int32_t));
1932 dst = (ipfw_insn *)((uint32_t *)dst + i);
1935 * comment place behind the action
1937 if (the_comment != NULL) {
1938 i = F_LEN(the_comment);
1939 bcopy(the_comment, dst, i * sizeof(u_int32_t));
1940 dst = (ipfw_insn *)((uint32_t *)dst + i);
1943 rule->cmd_len = (u_int32_t *)dst - (u_int32_t *)(rule->cmd);
1944 i = (void *)dst - (void *)rule;
1945 if (do_set_x(IP_FW_ADD, (void *)rule, i) == -1) {
1946 err(EX_UNAVAILABLE, "getsockopt(%s)", "IP_FW_ADD");
1949 show_rules(rule, 10, 10);
1953 zero(int ac, char *av[])
1961 /* clear all entries */
1962 if (do_set_x(IP_FW_ZERO, NULL, 0) < 0)
1963 err(EX_UNAVAILABLE, "do_set_x(IP_FW_ZERO)");
1965 printf("Accounting cleared.\n");
1971 if (isdigit(**av)) {
1972 rulenum = atoi(*av);
1974 if (do_set_x(IP_FW_ZERO, &rulenum, sizeof rulenum)) {
1975 warn("rule %u: do_set_x(IP_FW_ZERO)", rulenum);
1976 failed = EX_UNAVAILABLE;
1977 } else if (!do_quiet)
1978 printf("Entry %d cleared\n", rulenum);
1980 errx(EX_USAGE, "invalid rule number ``%s''", *av);
1983 if (failed != EX_OK)
1988 resetlog(int ac, char *av[])
1996 /* clear all entries */
1997 if (setsockopt(ipfw_socket, IPPROTO_IP, IP_FW_RESETLOG, NULL, 0) < 0)
1998 err(EX_UNAVAILABLE, "setsockopt(IP_FW_RESETLOG)");
2000 printf("Logging counts reset.\n");
2007 if (isdigit(**av)) {
2008 rulenum = atoi(*av);
2010 if (setsockopt(ipfw_socket, IPPROTO_IP,
2011 IP_FW_RESETLOG, &rulenum, sizeof rulenum)) {
2012 warn("rule %u: setsockopt(IP_FW_RESETLOG)", rulenum);
2013 failed = EX_UNAVAILABLE;
2014 } else if (!do_quiet)
2015 printf("Entry %d logging count reset\n", rulenum);
2017 errx(EX_DATAERR, "invalid rule number ``%s''", *av);
2020 if (failed != EX_OK)
2027 int cmd = IP_FW_FLUSH;
2029 cmd = IP_DUMMYNET_FLUSH;
2030 } else if (do_nat) {
2031 cmd = IP_FW_NAT_FLUSH;
2036 printf("Are you sure? [yn] ");
2039 c = toupper(getc(stdin));
2040 while (c != '\n' && getc(stdin) != '\n')
2042 return; /* and do not flush */
2043 } while (c != 'Y' && c != 'N');
2044 if (c == 'N') /* user said no */
2047 if (do_set_x(cmd, NULL, 0) < 0 ) {
2048 err(EX_UNAVAILABLE, "do_set_x(%s)",
2049 do_pipe? "IP_DUMMYNET_FLUSH":
2050 (do_nat? "IP_FW_NAT_FLUSH": "IP_FW_FLUSH"));
2053 printf("Flushed all %s.\n", do_pipe ? "pipes":
2054 (do_nat?"nat configurations":"rules"));
2059 str2addr(const char* str, struct in_addr* addr)
2063 if (inet_aton (str, addr))
2066 hp = gethostbyname (str);
2068 errx (1, "unknown host %s", str);
2070 memcpy (addr, hp->h_addr, sizeof (struct in_addr));
2074 str2portrange(const char* str, const char* proto, port_range *portRange)
2079 u_short loPort, hiPort;
2081 /* First see if this is a service, return corresponding port if so. */
2082 sp = getservbyname (str, proto);
2084 SETLOPORT(*portRange, ntohs(sp->s_port));
2085 SETNUMPORTS(*portRange, 1);
2089 /* Not a service, see if it's a single port or port range. */
2090 sep = strchr (str, '-');
2092 SETLOPORT(*portRange, strtol(str, &end, 10));
2095 SETNUMPORTS(*portRange, 1);
2099 /* Error in port range field. */
2100 errx (EX_DATAERR, "%s/%s: unknown service", str, proto);
2103 /* Port range, get the values and sanity check. */
2104 sscanf (str, "%hu-%hu", &loPort, &hiPort);
2105 SETLOPORT(*portRange, loPort);
2106 SETNUMPORTS(*portRange, 0); /* Error by default */
2107 if (loPort <= hiPort)
2108 SETNUMPORTS(*portRange, hiPort - loPort + 1);
2110 if (GETNUMPORTS(*portRange) == 0)
2111 errx (EX_DATAERR, "invalid port range %s", str);
2117 str2proto(const char* str)
2119 if (!strcmp (str, "tcp"))
2121 if (!strcmp (str, "udp"))
2123 errx (EX_DATAERR, "unknown protocol %s. Expected tcp or udp", str);
2127 str2addr_portrange (const char* str, struct in_addr* addr,
2128 char* proto, port_range *portRange)
2132 ptr = strchr (str, ':');
2134 errx (EX_DATAERR, "%s is missing port number", str);
2139 str2addr (str, addr);
2140 return str2portrange (ptr, proto, portRange);
2144 * Search for interface with name "ifn", and fill n accordingly:
2146 * n->ip ip address of interface "ifn"
2147 * n->if_name copy of interface name "ifn"
2150 set_addr_dynamic(const char *ifn, struct cfg_nat *n)
2152 struct if_msghdr *ifm;
2153 struct ifa_msghdr *ifam;
2154 struct sockaddr_dl *sdl;
2155 struct sockaddr_in *sin;
2156 char *buf, *lim, *next;
2165 mib[4] = NET_RT_IFLIST;
2169 * Get interface data.
2171 if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1)
2172 err(1, "iflist-sysctl-estimate");
2173 if ((buf = malloc(needed)) == NULL)
2174 errx(1, "malloc failed");
2175 if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1)
2176 err(1, "iflist-sysctl-get");
2179 * Loop through interfaces until one with
2180 * given name is found. This is done to
2181 * find correct interface index for routing
2182 * message processing.
2186 while (next < lim) {
2187 ifm = (struct if_msghdr *)next;
2188 next += ifm->ifm_msglen;
2189 if (ifm->ifm_version != RTM_VERSION) {
2191 warnx("routing message version %d "
2192 "not understood", ifm->ifm_version);
2195 if (ifm->ifm_type == RTM_IFINFO) {
2196 sdl = (struct sockaddr_dl *)(ifm + 1);
2197 if (strlen(ifn) == sdl->sdl_nlen &&
2198 strncmp(ifn, sdl->sdl_data, sdl->sdl_nlen) == 0) {
2199 ifIndex = ifm->ifm_index;
2200 ifMTU = ifm->ifm_data.ifi_mtu;
2206 errx(1, "unknown interface name %s", ifn);
2208 * Get interface address.
2211 while (next < lim) {
2212 ifam = (struct ifa_msghdr *)next;
2213 next += ifam->ifam_msglen;
2214 if (ifam->ifam_version != RTM_VERSION) {
2216 warnx("routing message version %d "
2217 "not understood", ifam->ifam_version);
2220 if (ifam->ifam_type != RTM_NEWADDR)
2222 if (ifam->ifam_addrs & RTA_IFA) {
2224 char *cp = (char *)(ifam + 1);
2226 for (i = 1; i < RTA_IFA; i <<= 1) {
2227 if (ifam->ifam_addrs & i)
2228 cp += SA_SIZE((struct sockaddr *)cp);
2230 if (((struct sockaddr *)cp)->sa_family == AF_INET) {
2231 sin = (struct sockaddr_in *)cp;
2237 errx(1, "%s: cannot get interface address", ifn);
2239 n->ip = sin->sin_addr;
2240 strncpy(n->if_name, ifn, IF_NAMESIZE);
2246 setup_redir_addr(char *spool_buf, int len, int *_ac, char ***_av)
2248 struct cfg_redir *r;
2249 struct cfg_spool *tmp;
2251 char tmp_spool_buf[NAT_BUF_LEN];
2252 int ac, i, space, lsnat;
2259 if (len >= SOF_REDIR) {
2260 r = (struct cfg_redir *)spool_buf;
2261 /* Skip cfg_redir at beginning of buf. */
2262 spool_buf = &spool_buf[SOF_REDIR];
2269 r->mode = REDIR_ADDR;
2270 /* Extract local address. */
2272 errx(EX_DATAERR, "redirect_addr: missing local address");
2274 sep = strchr(*av, ',');
2275 if (sep) { /* LSNAT redirection syntax. */
2276 r->laddr.s_addr = INADDR_NONE;
2277 /* Preserve av, copy spool servers to tmp_spool_buf. */
2278 strncpy(tmp_spool_buf, *av, strlen(*av)+1);
2281 str2addr(*av, &r->laddr);
2285 /* Extract public address. */
2287 errx(EX_DATAERR, "redirect_addr: missing public address");
2289 str2addr(*av, &r->paddr);
2292 /* Setup LSNAT server pool. */
2294 sep = strtok(tmp_spool_buf, ", ");
2295 while (sep != NULL) {
2296 tmp = (struct cfg_spool *)spool_buf;
2297 if (len < SOF_SPOOL)
2302 str2addr(sep, &tmp->addr);
2305 /* Point to the next possible cfg_spool. */
2306 spool_buf = &spool_buf[SOF_SPOOL];
2307 sep = strtok(NULL, ", ");
2313 errx(EX_DATAERR, "redirect_addr: buf is too small\n");
2317 setup_redir_port(char *spool_buf, int len, int *_ac, char ***_av)
2319 char **av, *sep, *protoName;
2320 char tmp_spool_buf[NAT_BUF_LEN];
2321 int ac, space, lsnat;
2322 struct cfg_redir *r;
2323 struct cfg_spool *tmp;
2324 u_short numLocalPorts;
2325 port_range portRange;
2333 if (len >= SOF_REDIR) {
2334 r = (struct cfg_redir *)spool_buf;
2335 /* Skip cfg_redir at beginning of buf. */
2336 spool_buf = &spool_buf[SOF_REDIR];
2343 r->mode = REDIR_PORT;
2348 errx (EX_DATAERR, "redirect_port: missing protocol");
2350 r->proto = str2proto(*av);
2355 * Extract local address.
2358 errx (EX_DATAERR, "redirect_port: missing local address");
2360 sep = strchr(*av, ',');
2361 /* LSNAT redirection syntax. */
2363 r->laddr.s_addr = INADDR_NONE;
2366 /* Preserve av, copy spool servers to tmp_spool_buf. */
2367 strncpy(tmp_spool_buf, *av, strlen(*av)+1);
2370 if (str2addr_portrange (*av, &r->laddr, protoName, &portRange) != 0)
2371 errx(EX_DATAERR, "redirect_port:"
2372 "invalid local port range");
2374 r->lport = GETLOPORT(portRange);
2375 numLocalPorts = GETNUMPORTS(portRange);
2380 * Extract public port and optionally address.
2383 errx (EX_DATAERR, "redirect_port: missing public port");
2385 sep = strchr (*av, ':');
2387 if (str2addr_portrange (*av, &r->paddr, protoName, &portRange) != 0)
2388 errx(EX_DATAERR, "redirect_port:"
2389 "invalid public port range");
2391 r->paddr.s_addr = INADDR_ANY;
2392 if (str2portrange(*av, protoName, &portRange) != 0)
2393 errx(EX_DATAERR, "redirect_port:"
2394 "invalid public port range");
2397 r->pport = GETLOPORT(portRange);
2398 r->pport_cnt = GETNUMPORTS(portRange);
2402 * Extract remote address and optionally port.
2405 * NB: isalpha(**av) => we've to check that next parameter is really an
2406 * option for this redirect entry, else stop here processing arg[cv].
2408 if (ac != 0 && !isalpha(**av)) {
2409 sep = strchr (*av, ':');
2411 if (str2addr_portrange (*av, &r->raddr,
2412 protoName, &portRange) != 0)
2413 errx(EX_DATAERR, "redirect_port:"
2414 "invalid remote port range");
2416 SETLOPORT(portRange, 0);
2417 SETNUMPORTS(portRange, 1);
2418 str2addr (*av, &r->raddr);
2422 SETLOPORT(portRange, 0);
2423 SETNUMPORTS(portRange, 1);
2424 r->raddr.s_addr = INADDR_ANY;
2426 r->rport = GETLOPORT(portRange);
2427 r->rport_cnt = GETNUMPORTS(portRange);
2430 * Make sure port ranges match up, then add the redirect ports.
2432 if (numLocalPorts != r->pport_cnt)
2433 errx(EX_DATAERR, "redirect_port:"
2434 "port ranges must be equal in size");
2436 /* Remote port range is allowed to be '0' which means all ports. */
2437 if (r->rport_cnt != numLocalPorts &&
2438 (r->rport_cnt != 1 || r->rport != 0))
2439 errx(EX_DATAERR, "redirect_port: remote port must"
2440 "be 0 or equal to local port range in size");
2443 * Setup LSNAT server pool.
2446 sep = strtok(tmp_spool_buf, ", ");
2447 while (sep != NULL) {
2448 tmp = (struct cfg_spool *)spool_buf;
2449 if (len < SOF_SPOOL)
2454 if (str2addr_portrange(sep,
2455 &tmp->addr, protoName, &portRange) != 0)
2456 errx(EX_DATAERR, "redirect_port:"
2457 "invalid local port range");
2458 if (GETNUMPORTS(portRange) != 1)
2459 errx(EX_DATAERR, "redirect_port: local port"
2460 "must be single in this context");
2461 tmp->port = GETLOPORT(portRange);
2463 /* Point to the next possible cfg_spool. */
2464 spool_buf = &spool_buf[SOF_SPOOL];
2465 sep = strtok(NULL, ", ");
2471 errx(EX_DATAERR, "redirect_port: buf is too small\n");
2475 setup_redir_proto(char *spool_buf, int len, int *_ac, char ***_av)
2477 struct protoent *protoent;
2478 struct cfg_redir *r;
2485 if (len >= SOF_REDIR) {
2486 r = (struct cfg_redir *)spool_buf;
2487 /* Skip cfg_redir at beginning of buf. */
2488 spool_buf = &spool_buf[SOF_REDIR];
2494 r->mode = REDIR_PROTO;
2499 errx(EX_DATAERR, "redirect_proto: missing protocol");
2501 protoent = getprotobyname(*av);
2502 if (protoent == NULL)
2503 errx(EX_DATAERR, "redirect_proto: unknown protocol %s", *av);
2505 r->proto = protoent->p_proto;
2510 * Extract local address.
2513 errx(EX_DATAERR, "redirect_proto: missing local address");
2515 str2addr(*av, &r->laddr);
2519 * Extract optional public address.
2522 r->paddr.s_addr = INADDR_ANY;
2523 r->raddr.s_addr = INADDR_ANY;
2525 /* see above in setup_redir_port() */
2526 if (!isalpha(**av)) {
2527 str2addr(*av, &r->paddr);
2531 * Extract optional remote address.
2533 /* see above in setup_redir_port() */
2534 if (ac != 0 && !isalpha(**av)) {
2535 str2addr(*av, &r->raddr);
2543 errx(EX_DATAERR, "redirect_proto: buf is too small\n");
2547 show_nat_config(char *buf) {
2549 struct cfg_redir *t;
2550 struct cfg_spool *s;
2552 int i, cnt, flag, off;
2554 n = (struct cfg_nat *)buf;
2557 printf("ipfw nat %u config", n->id);
2558 if (strlen(n->if_name) != 0)
2559 printf(" if %s", n->if_name);
2560 else if (n->ip.s_addr != 0)
2561 printf(" ip %s", inet_ntoa(n->ip));
2562 while (n->mode != 0) {
2563 if (n->mode & PKT_ALIAS_LOG) {
2565 n->mode &= ~PKT_ALIAS_LOG;
2566 } else if (n->mode & PKT_ALIAS_DENY_INCOMING) {
2568 n->mode &= ~PKT_ALIAS_DENY_INCOMING;
2569 } else if (n->mode & PKT_ALIAS_SAME_PORTS) {
2570 printf(" same_ports");
2571 n->mode &= ~PKT_ALIAS_SAME_PORTS;
2572 } else if (n->mode & PKT_ALIAS_UNREGISTERED_ONLY) {
2573 printf(" unreg_only");
2574 n->mode &= ~PKT_ALIAS_UNREGISTERED_ONLY;
2575 } else if (n->mode & PKT_ALIAS_RESET_ON_ADDR_CHANGE) {
2577 n->mode &= ~PKT_ALIAS_RESET_ON_ADDR_CHANGE;
2578 } else if (n->mode & PKT_ALIAS_REVERSE) {
2580 n->mode &= ~PKT_ALIAS_REVERSE;
2581 } else if (n->mode & PKT_ALIAS_PROXY_ONLY) {
2582 printf(" proxy_only");
2583 n->mode &= ~PKT_ALIAS_PROXY_ONLY;
2586 /* Print all the redirect's data configuration. */
2587 for (cnt = 0; cnt < n->redir_cnt; cnt++) {
2588 t = (struct cfg_redir *)&buf[off];
2592 printf(" redirect_addr");
2593 if (t->spool_cnt == 0)
2594 printf(" %s", inet_ntoa(t->laddr));
2596 for (i = 0; i < t->spool_cnt; i++) {
2597 s = (struct cfg_spool *)&buf[off];
2602 printf("%s", inet_ntoa(s->addr));
2605 printf(" %s", inet_ntoa(t->paddr));
2608 p = getprotobynumber(t->proto);
2609 printf(" redirect_port %s ", p->p_name);
2610 if (!t->spool_cnt) {
2611 printf("%s:%u", inet_ntoa(t->laddr), t->lport);
2612 if (t->pport_cnt > 1)
2613 printf("-%u", t->lport + t->pport_cnt - 1);
2615 for (i=0; i < t->spool_cnt; i++) {
2616 s = (struct cfg_spool *)&buf[off];
2619 printf("%s:%u", inet_ntoa(s->addr), s->port);
2624 if (t->paddr.s_addr)
2625 printf("%s:", inet_ntoa(t->paddr));
2626 printf("%u", t->pport);
2627 if (!t->spool_cnt && t->pport_cnt > 1)
2628 printf("-%u", t->pport + t->pport_cnt - 1);
2630 if (t->raddr.s_addr) {
2631 printf(" %s", inet_ntoa(t->raddr));
2633 printf(":%u", t->rport);
2634 if (!t->spool_cnt && t->rport_cnt > 1)
2635 printf("-%u", t->rport +
2641 p = getprotobynumber(t->proto);
2642 printf(" redirect_proto %s %s", p->p_name,
2643 inet_ntoa(t->laddr));
2644 if (t->paddr.s_addr != 0) {
2645 printf(" %s", inet_ntoa(t->paddr));
2646 if (t->raddr.s_addr)
2647 printf(" %s", inet_ntoa(t->raddr));
2651 errx(EX_DATAERR, "unknown redir mode");
2660 show_nat(int ac, char **av) {
2662 struct cfg_redir *e;
2663 int i, nbytes, nalloc, size;
2664 int nat_cnt, redir_cnt, nat_id;
2676 nat_id = strtoul(*av, NULL, 10);
2679 while (nbytes >= nalloc) {
2680 nalloc = nalloc * 2;
2682 if ((data = realloc(data, nbytes)) == NULL) {
2683 err(EX_OSERR, "realloc");
2685 if (do_get_x(IP_FW_NAT_GET, data, &nbytes) < 0) {
2686 err(EX_OSERR, "do_get_x(IP_FW_NAT_GET)");
2694 nat_cnt = *((int *)data);
2695 for (i = sizeof(nat_cnt); nat_cnt; nat_cnt--) {
2696 n = (struct cfg_nat *)&data[i];
2697 if (n->id >= 0 && n->id <= IPFW_DEFAULT_RULE) {
2698 if (nat_id == 0 || n->id == nat_id)
2699 show_nat_config(&data[i]);
2701 i += sizeof(struct cfg_nat);
2702 for (redir_cnt = 0; redir_cnt < n->redir_cnt; redir_cnt++) {
2703 e = (struct cfg_redir *)&data[i];
2704 i += sizeof(struct cfg_redir) +
2705 e->spool_cnt * sizeof(struct cfg_spool);
2711 * do_set_x - extended version og do_set
2712 * insert a x_header in the beginning of the rule buf
2713 * and call setsockopt() with IP_FW_X.
2716 do_set_x(int optname, void *rule, int optlen)
2720 ip_fw_x_header *x_header;
2721 if (ipfw_socket < 0) {
2722 err(EX_UNAVAILABLE, "socket");
2724 bzero(new_rule_buf, IPFW_RULE_SIZE_MAX);
2725 x_header = (ip_fw_x_header *)new_rule_buf;
2726 x_header->opcode = optname;
2727 /* copy the rule into the newbuf, just after the x_header*/
2728 bcopy(rule, ++x_header, optlen);
2729 len = optlen + sizeof(ip_fw_x_header);
2730 return setsockopt(ipfw_socket, IPPROTO_IP, IP_FW_X, new_rule_buf, len);
2737 do_get_x(int optname, void *rule, int *optlen)
2741 ip_fw_x_header *x_header;
2742 if (ipfw_socket < 0) {
2743 err(EX_UNAVAILABLE, "socket");
2745 bzero(new_rule_buf, IPFW_RULE_SIZE_MAX);
2746 x_header = (ip_fw_x_header *)new_rule_buf;
2747 x_header->opcode = optname;
2748 /* copy the rule into the newbuf, just after the x_header*/
2749 bcopy(rule, ++x_header, *optlen);
2750 len = *optlen + sizeof(ip_fw_x_header);
2751 retval = getsockopt(ipfw_socket, IPPROTO_IP, IP_FW_X, new_rule_buf, &len);
2752 bcopy(new_rule_buf, rule, len);
2758 config_nat(int ac, char **av)
2760 struct cfg_nat *n; /* Nat instance configuration. */
2761 int i, len, off, tok;
2762 char *id, buf[NAT_BUF_LEN]; /* Buffer for serialized data. */
2765 /* Offset in buf: save space for n at the beginning. */
2766 off = sizeof(struct cfg_nat);
2767 memset(buf, 0, sizeof(buf));
2768 n = (struct cfg_nat *)buf;
2772 if (ac && isdigit(**av)) {
2778 errx(EX_DATAERR, "missing nat id");
2780 errx(EX_DATAERR, "missing option");
2783 tok = match_token(nat_params, *av);
2788 errx(EX_DATAERR, "missing option");
2789 if (!inet_aton(av[0], &(n->ip)))
2790 errx(EX_DATAERR, "bad ip address ``%s''",
2796 errx(EX_DATAERR, "missing option");
2797 set_addr_dynamic(av[0], n);
2801 n->mode |= PKT_ALIAS_LOG;
2804 n->mode |= PKT_ALIAS_DENY_INCOMING;
2806 case TOK_SAME_PORTS:
2807 n->mode |= PKT_ALIAS_SAME_PORTS;
2809 case TOK_UNREG_ONLY:
2810 n->mode |= PKT_ALIAS_UNREGISTERED_ONLY;
2812 case TOK_RESET_ADDR:
2813 n->mode |= PKT_ALIAS_RESET_ON_ADDR_CHANGE;
2816 n->mode |= PKT_ALIAS_REVERSE;
2818 case TOK_PROXY_ONLY:
2819 n->mode |= PKT_ALIAS_PROXY_ONLY;
2822 * All the setup_redir_* functions work directly in the final
2823 * buffer, see above for details.
2825 case TOK_REDIR_ADDR:
2826 case TOK_REDIR_PORT:
2827 case TOK_REDIR_PROTO:
2829 case TOK_REDIR_ADDR:
2830 i = setup_redir_addr(&buf[off], len, &ac, &av);
2832 case TOK_REDIR_PORT:
2833 i = setup_redir_port(&buf[off], len, &ac, &av);
2835 case TOK_REDIR_PROTO:
2836 i = setup_redir_proto(&buf[off], len, &ac, &av);
2844 errx(EX_DATAERR, "unrecognised option ``%s''", av[-1]);
2847 i = do_set_x(IP_FW_NAT_CFG, buf, off);
2849 err(1, "do_set_x(%s)", "IP_FW_NAT_CFG");
2851 /* After every modification, we show the resultant rule. */
2853 char *_av[] = {"config", id};
2859 ipfw_main(int ac, char **av)
2866 /* Set the force flag for non-interactive processes */
2867 do_force = !isatty(STDIN_FILENO);
2869 optind = optreset = 1;
2870 while ((ch = getopt(ac, av, "hs:acdDefNStTv")) != -1)
2872 case 'h': /* help */
2874 break; /* NOTREACHED */
2876 case 's': /* sort */
2877 do_sort = atoi(optarg);
2919 NEED1("bad arguments, for usage summary ``ipfw''");
2922 * optional: pipe or queue or nat
2926 if (!strncmp(*av, "nat", strlen(*av)))
2928 else if (!strncmp(*av, "pipe", strlen(*av))) {
2930 } else if (!strncmp(*av, "queue", strlen(*av))) {
2933 NEED1("missing command");
2936 * for pipes and queues and nat we normally say 'pipe NN config'
2937 * but the code is easier to parse as 'pipe config NN'
2938 * so we swap the two arguments.
2940 if ((do_pipe || do_nat) && ac > 2 && isdigit(*(av[1]))) {
2946 if (!strncmp(*av, "add", strlen(*av))) {
2949 } else if (!strncmp(*av, "delete", strlen(*av))) {
2950 delete_rules(ac, av);
2951 } else if (!strncmp(*av, "flush", strlen(*av))) {
2953 } else if (!strncmp(*av, "list", strlen(*av))) {
2956 } else if (!strncmp(*av, "show", strlen(*av))) {
2960 } else if (!strncmp(*av, "zero", strlen(*av))) {
2962 } else if (!strncmp(*av, "set", strlen(*av))) {
2963 sets_handler(ac, av);
2964 } else if (!strncmp(*av, "module", strlen(*av))) {
2966 if (!strncmp(*av, "show", strlen(*av)) ||
2967 !strncmp(*av, "show", strlen(*av))) {
2968 list_modules(ac, av);
2970 errx(EX_USAGE, "bad ipfw module command `%s'", *av);
2972 } else if (!strncmp(*av, "resetlog", strlen(*av))) {
2974 } else if (!strncmp(*av, "log", strlen(*av))) {
2976 if (!strncmp(*av, "reset", strlen(*av))) {
2978 } else if (!strncmp(*av, "off", strlen(*av))) {
2980 } else if (!strncmp(*av, "on", strlen(*av))) {
2983 errx(EX_USAGE, "bad command `%s'", *av);
2985 } else if (!strncmp(*av, "nat", strlen(*av))) {
2987 if (!strncmp(*av, "config", strlen(*av))) {
2989 } else if (!strncmp(*av, "flush", strlen(*av))) {
2991 } else if (!strncmp(*av, "show", strlen(*av)) ||
2992 !strncmp(*av, "list", strlen(*av))) {
2994 } else if (!strncmp(*av, "delete", strlen(*av))) {
2995 delete_nat_config(ac, av);
2997 errx(EX_USAGE, "bad ipfw nat command `%s'", *av);
2999 } else if (!strncmp(*av, "pipe", strlen(*av)) ||
3000 !strncmp(*av, "queue", strlen(*av))) {
3002 if (!strncmp(*av, "config", strlen(*av))) {
3003 config_dummynet(ac, av);
3004 } else if (!strncmp(*av, "flush", strlen(*av))) {
3006 } else if (!strncmp(*av, "show", strlen(*av))) {
3007 show_dummynet(ac, av);
3009 errx(EX_USAGE, "bad ipfw pipe command `%s'", *av);
3011 } else if (!strncmp(*av, "state", strlen(*av))) {
3013 if (!strncmp(*av, "add", strlen(*av))) {
3015 } else if (!strncmp(*av, "delete", strlen(*av))) {
3016 delete_state(ac, av);
3017 } else if (!strncmp(*av, "flush", strlen(*av))) {
3018 flush_state(ac, av);
3019 } else if (!strncmp(*av, "list", strlen(*av))) {
3022 } else if (!strncmp(*av, "show", strlen(*av))) {
3027 errx(EX_USAGE, "bad ipfw state command `%s'", *av);
3030 errx(EX_USAGE, "bad ipfw command `%s'", *av);
3036 ipfw_readfile(int ac, char *av[])
3039 char *a, *p, *args[MAX_ARGS], *cmd = NULL;
3041 int i=0, lineno=0, qflag=0, pflag=0, status;
3046 while ((c = getopt(ac, av, "D:U:p:q")) != -1)
3050 errx(EX_USAGE, "-D requires -p");
3051 if (i > MAX_ARGS - 2)
3053 "too many -D or -U options");
3060 errx(EX_USAGE, "-U requires -p");
3061 if (i > MAX_ARGS - 2)
3063 "too many -D or -U options");
3080 errx(EX_USAGE, "bad arguments, for usage"
3081 " summary ``ipfw''");
3087 errx(EX_USAGE, "extraneous filename arguments");
3089 if ((f = fopen(av[0], "r")) == NULL)
3090 err(EX_UNAVAILABLE, "fopen: %s", av[0]);
3093 /* pipe through preprocessor (cpp or m4) */
3098 if (pipe(pipedes) == -1)
3099 err(EX_OSERR, "cannot create pipe");
3101 switch ((preproc = fork())) {
3103 err(EX_OSERR, "cannot fork");
3107 if (dup2(fileno(f), 0) == -1 ||
3108 dup2(pipedes[1], 1) == -1) {
3109 err(EX_OSERR, "dup2()");
3115 err(EX_OSERR, "execvp(%s) failed", cmd);
3121 if ((f = fdopen(pipedes[0], "r")) == NULL) {
3122 int savederrno = errno;
3124 kill(preproc, SIGTERM);
3126 err(EX_OSERR, "fdopen()");
3131 while (fgets(buf, BUFSIZ, f)) {
3133 sprintf(linename, "Line %d", lineno);
3138 if ((p = strchr(buf, '#')) != NULL)
3143 for (a = strtok(buf, WHITESP); a && i < MAX_ARGS;
3144 a = strtok(NULL, WHITESP), i++) {
3148 if (i == (qflag? 2: 1))
3151 errx(EX_USAGE, "%s: too many arguments", linename);
3158 if (waitpid(preproc, &status, 0) == -1)
3159 errx(EX_OSERR, "waitpid()");
3160 if (WIFEXITED(status) && WEXITSTATUS(status) != EX_OK)
3161 errx(EX_UNAVAILABLE, "preprocessor exited with status %d",
3162 WEXITSTATUS(status));
3163 else if (WIFSIGNALED(status))
3164 errx(EX_UNAVAILABLE, "preprocessor exited with signal %d",
3170 main(int ac, char *av[])
3172 ipfw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
3173 if (ipfw_socket < 0)
3174 err(EX_UNAVAILABLE, "socket");
3176 memset(keywords, 0, sizeof(struct ipfw_keyword) * KEYWORD_SIZE);
3177 memset(mappings, 0, sizeof(struct ipfw_mapping) * MAPPING_SIZE);
3179 prepare_default_funcs();
3181 if (ac > 1 && av[ac - 1][0] == '/' && access(av[ac - 1], R_OK) == 0)
3182 ipfw_readfile(ac, av);