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/ipfw2/ip_fw2.h"
61 #include "../../sys/net/dummynet2/ip_dummynet2.h"
62 #include "../../sys/net/libalias/alias.h"
63 #include "../../sys/net/ipfw2_basic/ip_fw2_basic.h"
64 #include "../../sys/net/ipfw2_nat/ip_fw2_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/libipfw2%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, "ipfw2 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 sysctl_handler(int ac, char *av[], int which)
1002 warnx("missing keyword to enable/disable\n");
1003 } else if (strncmp(*av, "firewall", strlen(*av)) == 0) {
1004 sysctlbyname("net.inet.ip.fw.enable", NULL, 0,
1005 &which, sizeof(which));
1006 } else if (strncmp(*av, "one_pass", strlen(*av)) == 0) {
1007 sysctlbyname("net.inet.ip.fw.one_pass", NULL, 0,
1008 &which, sizeof(which));
1009 } else if (strncmp(*av, "debug", strlen(*av)) == 0) {
1010 sysctlbyname("net.inet.ip.fw.debug", NULL, 0,
1011 &which, sizeof(which));
1012 } else if (strncmp(*av, "verbose", strlen(*av)) == 0) {
1013 sysctlbyname("net.inet.ip.fw.verbose", NULL, 0,
1014 &which, sizeof(which));
1015 } else if (strncmp(*av, "dyn_keepalive", strlen(*av)) == 0) {
1016 sysctlbyname("net.inet.ip.fw.dyn_keepalive", NULL, 0,
1017 &which, sizeof(which));
1019 warnx("unrecognize enable/disable keyword: %s\n", *av);
1025 add_state(int ac, char *av[])
1027 struct ipfw_ioc_state ioc_state;
1028 ioc_state.expiry = 0;
1029 ioc_state.lifetime = 0;
1031 if (strcmp(*av, "rulenum") == 0) {
1033 ioc_state.rulenum = atoi(*av);
1035 errx(EX_USAGE, "ipfw state add rule");
1038 struct protoent *pe;
1039 pe = getprotobyname(*av);
1040 ioc_state.flow_id.proto = pe->p_proto;
1043 ioc_state.flow_id.src_ip = inet_addr(*av);
1046 ioc_state.flow_id.src_port = atoi(*av);
1049 ioc_state.flow_id.dst_ip = inet_addr(*av);
1052 ioc_state.flow_id.dst_port = atoi(*av);
1055 if (strcmp(*av, "live") == 0) {
1057 ioc_state.lifetime = atoi(*av);
1061 if (strcmp(*av, "expiry") == 0) {
1063 ioc_state.expiry = strtoul(*av, NULL, 10);
1064 printf("ioc_state.expiry=%d\n", ioc_state.expiry);
1067 if (do_set_x(IP_FW_STATE_ADD, &ioc_state, sizeof(struct ipfw_ioc_state)) < 0 ) {
1068 err(EX_UNAVAILABLE, "do_set_x(IP_FW_STATE_ADD)");
1071 printf("Flushed all states.\n");
1076 delete_state(int ac, char *av[])
1080 if (ac == 1 && isdigit(**av))
1081 rulenum = atoi(*av);
1082 if (do_set_x(IP_FW_STATE_DEL, &rulenum, sizeof(int)) < 0 )
1083 err(EX_UNAVAILABLE, "do_set_x(IP_FW_STATE_DEL)");
1085 printf("Flushed all states.\n");
1089 flush_state(int ac, char *av[])
1094 printf("Are you sure? [yn] ");
1097 c = toupper(getc(stdin));
1098 while (c != '\n' && getc(stdin) != '\n')
1100 return; /* and do not flush */
1101 } while (c != 'Y' && c != 'N');
1102 if (c == 'N') /* user said no */
1105 if (do_set_x(IP_FW_STATE_FLUSH, NULL, 0) < 0 )
1106 err(EX_UNAVAILABLE, "do_set_x(IP_FW_STATE_FLUSH)");
1108 printf("Flushed all states.\n");
1112 list(int ac, char *av[])
1114 struct ipfw_ioc_state *dynrules, *d;
1115 struct ipfw_ioc_rule *r;
1119 int bcwidth, n, nbytes, nstat, ndyn, pcwidth, width;
1120 int exitval = EX_OK, lac;
1121 char **lav, *endptr;
1127 /* get rules or pipes from kernel, resizing array as necessary */
1130 while (nbytes >= nalloc) {
1131 nalloc = nalloc * 2 ;
1133 if ((data = realloc(data, nbytes)) == NULL)
1134 err(EX_OSERR, "realloc");
1135 if (do_get_x(IP_FW_GET, data, &nbytes) < 0)
1136 err(EX_OSERR, "do_get_x(IP_FW_GET)");
1140 * Count static rules.
1143 nstat = r->static_count;
1146 * Count dynamic rules. This is easier as they have
1149 dynrules = (struct ipfw_ioc_state *)((void *)r + r->static_len);
1150 ndyn = (nbytes - r->static_len) / sizeof(*dynrules);
1152 /* if showing stats, figure out column widths ahead of time */
1153 bcwidth = pcwidth = 0;
1155 for (n = 0, r = data; n < nstat;
1156 n++, r = (void *)r + IOC_RULESIZE(r)) {
1157 /* packet counter */
1158 width = snprintf(NULL, 0, "%ju", (uintmax_t)r->pcnt);
1159 if (width > pcwidth)
1163 width = snprintf(NULL, 0, "%ju", (uintmax_t)r->bcnt);
1164 if (width > bcwidth)
1168 if (do_dynamic && ndyn) {
1169 for (n = 0, d = dynrules; n < ndyn; n++, d++) {
1170 width = snprintf(NULL, 0, "%ju", (uintmax_t)d->pcnt);
1171 if (width > pcwidth)
1174 width = snprintf(NULL, 0, "%ju", (uintmax_t)d->bcnt);
1175 if (width > bcwidth)
1180 /* if no rule numbers were specified, list all rules */
1182 if (do_dynamic != 2) {
1183 for (n = 0, r = data; n < nstat; n++,
1184 r = (void *)r + IOC_RULESIZE(r)) {
1185 show_rules(r, pcwidth, bcwidth);
1188 if (do_dynamic && ndyn) {
1189 if (do_dynamic != 2) {
1190 printf("## States (%d):\n", ndyn);
1192 for (n = 0, d = dynrules; n < ndyn; n++, d++)
1193 show_states(d, pcwidth, bcwidth);
1198 /* display specific rules requested on command line */
1200 if (do_dynamic != 2) {
1201 for (lac = ac, lav = av; lac != 0; lac--) {
1202 /* convert command line rule # */
1203 rnum = strtoul(*lav++, &endptr, 10);
1206 warnx("invalid rule number: %s", *(lav - 1));
1209 for (n = seen = 0, r = data; n < nstat;
1210 n++, r = (void *)r + IOC_RULESIZE(r) ) {
1211 if (r->rulenum > rnum)
1213 if (r->rulenum == rnum) {
1214 show_rules(r, pcwidth, bcwidth);
1219 /* give precedence to other error(s) */
1220 if (exitval == EX_OK)
1221 exitval = EX_UNAVAILABLE;
1222 warnx("rule %lu does not exist", rnum);
1227 if (do_dynamic && ndyn) {
1228 if (do_dynamic != 2) {
1229 printf("## States (%d):\n", ndyn);
1231 for (lac = ac, lav = av; lac != 0; lac--) {
1232 rnum = strtoul(*lav++, &endptr, 10);
1234 /* already warned */
1236 for (n = 0, d = dynrules; n < ndyn; n++, d++) {
1237 if (d->rulenum > rnum)
1239 if (d->rulenum == rnum)
1240 show_states(d, pcwidth, bcwidth);
1250 if (exitval != EX_OK)
1255 show_dummynet(int ac, char *av[])
1259 int nalloc = 1024; /* start somewhere... */
1264 while (nbytes >= nalloc) {
1265 nalloc = nalloc * 2 + 200;
1267 if ((data = realloc(data, nbytes)) == NULL)
1268 err(EX_OSERR, "realloc");
1269 if (do_get_x(IP_DUMMYNET_GET, data, &nbytes) < 0) {
1270 err(EX_OSERR, "do_get_x(IP_%s_GET)",
1271 do_pipe ? "DUMMYNET" : "FW");
1275 show_pipes(data, nbytes, ac, av);
1282 fprintf(stderr, "usage: ipfw [options]\n"
1283 " ipfw add [rulenum] [set id] action filters\n"
1284 " ipfw delete [rulenum]\n"
1286 " ipfw list [rulenum]\n"
1287 " ipfw show [rulenum]\n"
1288 " ipfw zero [rulenum]\n"
1289 " ipfw set [show|enable|disable]\n"
1291 " ipfw [enable|disable]\n"
1292 " ipfw log [reset|off|on]\n"
1293 " ipfw nat [config|show|delete]\n"
1294 " ipfw pipe [config|show|delete]\n"
1295 " ipfw state [add|delete|list|show]"
1296 "\nsee ipfw manpage for details\n");
1301 delete_nat_config(int ac, char *av[])
1308 if (do_set_x(IP_FW_NAT_DEL, &i, sizeof(i)) == -1)
1309 err(EX_UNAVAILABLE, "getsockopt(%s)", "IP_FW_NAT_DEL");
1313 delete_rules(int ac, char *av[])
1315 struct dn_ioc_pipe pipe;
1317 int exitval = EX_OK;
1321 memset(&pipe, 0, sizeof pipe);
1324 if (ac > 0 && !strncmp(*av, "set", strlen(*av))) {
1325 do_set = 1; /* delete set */
1330 while (ac && isdigit(**av)) {
1339 i = do_set_x(IP_DUMMYNET_DEL, &pipe, sizeof pipe);
1342 warn("rule %u: setsockopt(IP_DUMMYNET_DEL)",
1343 do_pipe == 1 ? pipe.pipe_nr : pipe.fs.fs_nr);
1346 rulenum = (i & 0xffff) | (do_set << 24);
1347 i = do_set_x(IP_FW_DEL, &rulenum, sizeof rulenum);
1349 exitval = EX_UNAVAILABLE;
1350 warn("rule %u: setsockopt(IP_FW_DEL)",
1355 if (exitval != EX_OK)
1360 static unsigned long
1361 getbw(const char *str, u_short *flags, int kb)
1367 val = strtoul(str, &end, 0);
1368 if (*end == 'k' || *end == 'K') {
1371 } else if (*end == 'm' || *end == 'M') {
1377 * Deal with bits or bytes or b(bits) or B(bytes). If there is no
1378 * trailer assume bits.
1380 if (strncasecmp(end, "bit", 3) == 0) {
1382 } else if (strncasecmp(end, "byte", 4) == 0) {
1384 } else if (*end == 'b') {
1386 } else if (*end == 'B') {
1391 * Return in bits if flags is NULL, else flag bits
1392 * or bytes in flags and return the unconverted value.
1394 if (inbytes && flags)
1395 *flags |= DN_QSIZE_IS_BYTES;
1396 else if (inbytes && flags == NULL)
1403 * config dummynet pipe/queue
1406 config_dummynet(int ac, char **av)
1408 struct dn_ioc_pipe pipe;
1415 memset(&pipe, 0, sizeof pipe);
1417 if (ac && isdigit(**av)) {
1429 int tok = match_token(dummynet_params, *av);
1434 pipe.fs.flags_fs |= DN_NOERROR;
1438 NEED1("plr needs argument 0..1\n");
1439 d = strtod(av[0], NULL);
1444 pipe.fs.plr = (int)(d*0x7fffffff);
1449 NEED1("queue needs queue size\n");
1451 pipe.fs.qsize = getbw(av[0], &pipe.fs.flags_fs, 1024);
1456 NEED1("buckets needs argument\n");
1457 pipe.fs.rq_size = strtoul(av[0], NULL, 0);
1462 NEED1("mask needs mask specifier\n");
1464 * per-flow queue, mask is dst_ip, dst_port,
1465 * src_ip, src_port, proto measured in bits
1469 pipe.fs.flow_mask.type = ETHERTYPE_IP;
1470 pipe.fs.flow_mask.u.ip.dst_ip = 0;
1471 pipe.fs.flow_mask.u.ip.src_ip = 0;
1472 pipe.fs.flow_mask.u.ip.dst_port = 0;
1473 pipe.fs.flow_mask.u.ip.src_port = 0;
1474 pipe.fs.flow_mask.u.ip.proto = 0;
1478 u_int32_t *p32 = NULL;
1479 u_int16_t *p16 = NULL;
1481 tok = match_token(dummynet_params, *av);
1486 * special case, all bits significant
1488 pipe.fs.flow_mask.u.ip.dst_ip = ~0;
1489 pipe.fs.flow_mask.u.ip.src_ip = ~0;
1490 pipe.fs.flow_mask.u.ip.dst_port = ~0;
1491 pipe.fs.flow_mask.u.ip.src_port = ~0;
1492 pipe.fs.flow_mask.u.ip.proto = ~0;
1493 pipe.fs.flags_fs |= DN_HAVE_FLOW_MASK;
1497 p32 = &pipe.fs.flow_mask.u.ip.dst_ip;
1501 p32 = &pipe.fs.flow_mask.u.ip.src_ip;
1505 p16 = &pipe.fs.flow_mask.u.ip.dst_port;
1509 p16 = &pipe.fs.flow_mask.u.ip.src_port;
1520 errx(EX_USAGE, "mask: value missing");
1521 if (*av[0] == '/') {
1522 a = strtoul(av[0]+1, &end, 0);
1523 a = (a == 32) ? ~0 : (1 << a) - 1;
1525 a = strtoul(av[0], &end, 0);
1528 else if (p16 != NULL) {
1531 "mask: must be 16 bit");
1532 *p16 = (u_int16_t)a;
1536 "mask: must be 8 bit");
1537 pipe.fs.flow_mask.u.ip.proto = (uint8_t)a;
1540 pipe.fs.flags_fs |= DN_HAVE_FLOW_MASK;
1542 } /* end while, config masks */
1549 NEED1("red/gred needs w_q/min_th/max_th/max_p\n");
1550 pipe.fs.flags_fs |= DN_IS_RED;
1551 if (tok == TOK_GRED)
1552 pipe.fs.flags_fs |= DN_IS_GENTLE_RED;
1554 * the format for parameters is w_q/min_th/max_th/max_p
1556 if ((end = strsep(&av[0], "/"))) {
1557 double w_q = strtod(end, NULL);
1558 if (w_q > 1 || w_q <= 0)
1559 errx(EX_DATAERR, "0 < w_q <= 1");
1560 pipe.fs.w_q = (int) (w_q * (1 << SCALE_RED));
1562 if ((end = strsep(&av[0], "/"))) {
1563 pipe.fs.min_th = strtoul(end, &end, 0);
1564 if (*end == 'K' || *end == 'k')
1565 pipe.fs.min_th *= 1024;
1567 if ((end = strsep(&av[0], "/"))) {
1568 pipe.fs.max_th = strtoul(end, &end, 0);
1569 if (*end == 'K' || *end == 'k')
1570 pipe.fs.max_th *= 1024;
1572 if ((end = strsep(&av[0], "/"))) {
1573 double max_p = strtod(end, NULL);
1574 if (max_p > 1 || max_p <= 0)
1575 errx(EX_DATAERR, "0 < max_p <= 1");
1576 pipe.fs.max_p = (int)(max_p * (1 << SCALE_RED));
1582 pipe.fs.flags_fs &= ~(DN_IS_RED|DN_IS_GENTLE_RED);
1586 NEED1("bw needs bandwidth\n");
1588 errx(EX_DATAERR, "bandwidth only valid for pipes");
1590 * set bandwidth value
1592 pipe.bandwidth = getbw(av[0], NULL, 1000);
1593 if (pipe.bandwidth < 0)
1594 errx(EX_DATAERR, "bandwidth too large");
1600 errx(EX_DATAERR, "delay only valid for pipes");
1601 NEED1("delay needs argument 0..10000ms\n");
1602 pipe.delay = strtoul(av[0], NULL, 0);
1608 errx(EX_DATAERR, "weight only valid for queues");
1609 NEED1("weight needs argument 0..100\n");
1610 pipe.fs.weight = strtoul(av[0], &end, 0);
1616 errx(EX_DATAERR, "pipe only valid for queues");
1617 NEED1("pipe needs pipe_number\n");
1618 pipe.fs.parent_nr = strtoul(av[0], &end, 0);
1623 errx(EX_DATAERR, "unrecognised option ``%s''", *av);
1627 if (pipe.pipe_nr == 0)
1628 errx(EX_DATAERR, "pipe_nr must be > 0");
1629 if (pipe.delay > 10000)
1630 errx(EX_DATAERR, "delay must be < 10000");
1631 } else { /* do_pipe == 2, queue */
1632 if (pipe.fs.parent_nr == 0)
1633 errx(EX_DATAERR, "pipe must be > 0");
1634 if (pipe.fs.weight >100)
1635 errx(EX_DATAERR, "weight must be <= 100");
1637 if (pipe.fs.flags_fs & DN_QSIZE_IS_BYTES) {
1638 if (pipe.fs.qsize > 1024*1024)
1639 errx(EX_DATAERR, "queue size must be < 1MB");
1641 if (pipe.fs.qsize > 100)
1642 errx(EX_DATAERR, "2 <= queue size <= 100");
1644 if (pipe.fs.flags_fs & DN_IS_RED) {
1646 int lookup_depth, avg_pkt_size;
1647 double s, idle, weight, w_q;
1651 if (pipe.fs.min_th >= pipe.fs.max_th)
1652 errx(EX_DATAERR, "min_th %d must be < than max_th %d",
1653 pipe.fs.min_th, pipe.fs.max_th);
1654 if (pipe.fs.max_th == 0)
1655 errx(EX_DATAERR, "max_th must be > 0");
1658 if (sysctlbyname("net.inet.ip.dummynet.red_lookup_depth",
1659 &lookup_depth, &len, NULL, 0) == -1)
1661 errx(1, "sysctlbyname(\"%s\")",
1662 "net.inet.ip.dummynet.red_lookup_depth");
1663 if (lookup_depth == 0)
1664 errx(EX_DATAERR, "net.inet.ip.dummynet.red_lookup_depth"
1665 " must be greater than zero");
1668 if (sysctlbyname("net.inet.ip.dummynet.red_avg_pkt_size",
1669 &avg_pkt_size, &len, NULL, 0) == -1)
1671 errx(1, "sysctlbyname(\"%s\")",
1672 "net.inet.ip.dummynet.red_avg_pkt_size");
1673 if (avg_pkt_size == 0)
1675 "net.inet.ip.dummynet.red_avg_pkt_size must"
1676 " be greater than zero");
1678 len = sizeof(clock_hz);
1679 if (sysctlbyname("net.inet.ip.dummynet.hz", &clock_hz, &len,
1681 errx(1, "sysctlbyname(\"%s\")",
1682 "net.inet.ip.dummynet.hz");
1686 * Ticks needed for sending a medium-sized packet.
1687 * Unfortunately, when we are configuring a WF2Q+ queue, we
1688 * do not have bandwidth information, because that is stored
1689 * in the parent pipe, and also we have multiple queues
1690 * competing for it. So we set s=0, which is not very
1691 * correct. But on the other hand, why do we want RED with
1694 if (pipe.bandwidth == 0) /* this is a WF2Q+ queue */
1697 s = clock_hz * avg_pkt_size * 8 / pipe.bandwidth;
1700 * max idle time (in ticks) before avg queue size becomes 0.
1701 * NOTA: (3/w_q) is approx the value x so that
1702 * (1-w_q)^x < 10^-3.
1704 w_q = ((double)pipe.fs.w_q) / (1 << SCALE_RED);
1705 idle = s * 3. / w_q;
1706 pipe.fs.lookup_step = (int)idle / lookup_depth;
1707 if (!pipe.fs.lookup_step)
1708 pipe.fs.lookup_step = 1;
1710 for (t = pipe.fs.lookup_step; t > 0; --t)
1712 pipe.fs.lookup_weight = (int)(weight * (1 << SCALE_RED));
1714 i = do_set_x(IP_DUMMYNET_CONFIGURE, &pipe, sizeof pipe);
1716 err(1, "do_set_x(%s)", "IP_DUMMYNET_CONFIGURE");
1720 * helper function, updates the pointer to cmd with the length
1721 * of the current command, and also cleans up the first word of
1722 * the new command in case it has been clobbered before.
1725 next_cmd(ipfw_insn *cmd)
1728 bzero(cmd, sizeof(*cmd));
1733 * Parse arguments and assemble the microinstructions which make up a rule.
1734 * Rules are added into the 'rulebuf' and then copied in the correct order
1735 * into the actual rule.
1740 add(int ac, char *av[])
1743 * rules are added into the 'rulebuf' and then copied in
1744 * the correct order into the actual rule.
1745 * Some things that need to go out of order (prob, action etc.)
1748 static uint32_t rulebuf[IPFW_RULE_SIZE_MAX];
1749 static uint32_t actbuf[IPFW_RULE_SIZE_MAX];
1750 static uint32_t othbuf[IPFW_RULE_SIZE_MAX];
1751 static uint32_t cmdbuf[IPFW_RULE_SIZE_MAX];
1753 ipfw_insn *src, *dst, *cmd, *action, *other;
1754 ipfw_insn *the_comment = NULL;
1755 struct ipfw_ioc_rule *rule;
1756 struct ipfw_keyword *key;
1757 struct ipfw_mapping *map;
1761 bzero(actbuf, sizeof(actbuf)); /* actions go here */
1762 bzero(othbuf, sizeof(actbuf)); /* others */
1763 bzero(cmdbuf, sizeof(cmdbuf)); /* filters */
1764 bzero(rulebuf, sizeof(rulebuf));
1766 rule = (struct ipfw_ioc_rule *)rulebuf;
1767 cmd = (ipfw_insn *)cmdbuf;
1768 action = (ipfw_insn *)actbuf;
1769 other = (ipfw_insn *)othbuf;
1771 NEED2("need more parameters");
1774 /* [rule N] -- Rule number optional */
1775 if (ac && isdigit(**av)) {
1776 rule->rulenum = atoi(*av);
1780 /* [set N] -- set number (0..30), optional */
1781 if (ac > 1 && !strncmp(*av, "set", strlen(*av))) {
1782 int set = strtoul(av[1], NULL, 10);
1783 if (set < 0 || set > 30)
1784 errx(EX_DATAERR, "illegal set %s", av[1]);
1793 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) {
1794 if (key->type == IPFW_KEYWORD_TYPE_OTHERS &&
1795 strcmp(key->word, *av) == 0) {
1796 for (j = 0, map = mappings;
1797 j < MAPPING_SIZE; j++, map++) {
1798 if (map->type == IPFW_MAPPING_TYPE_IN_USE &&
1799 map->module == key->module &&
1800 map->opcode == key->opcode ) {
1802 (*fn)(&other, &ac, &av);
1809 if (i >= KEYWORD_SIZE) {
1811 } else if (F_LEN(other) > 0) {
1812 if (other->module == MODULE_BASIC_ID &&
1813 other->opcode == O_BASIC_CHECK_STATE) {
1814 other = next_cmd(other);
1817 other = next_cmd(other);
1824 * only accept 1 action
1826 NEED1("missing action");
1827 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) {
1828 if (ac > 0 && key->type == IPFW_KEYWORD_TYPE_ACTION &&
1829 strcmp(key->word, *av) == 0) {
1830 for (j = 0, map = mappings; j<MAPPING_SIZE; j++, map++) {
1831 if (map->type == IPFW_MAPPING_TYPE_IN_USE &&
1832 map->module == key->module &&
1833 map->opcode == key->opcode) {
1835 (*fn)(&action, &ac, &av);
1842 if (F_LEN(action) > 0)
1843 action = next_cmd(action);
1848 if (strcmp(*av, "proto") == 0){
1852 NEED1("missing protocol");
1853 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) {
1854 if (key->type == IPFW_KEYWORD_TYPE_FILTER &&
1855 strcmp(key->word, "proto") == 0) {
1856 for (j = 0, map = mappings; j<MAPPING_SIZE; j++, map++) {
1857 if (map->type == IPFW_MAPPING_TYPE_IN_USE &&
1858 map->module == key->module &&
1859 map->opcode == key->opcode ) {
1861 (*fn)(&cmd, &ac, &av);
1869 cmd = next_cmd(cmd);
1876 ipfw_insn_u32 *cmd32; /* alias for cmd */
1879 cmd32 = (ipfw_insn_u32 *)cmd;
1880 if (strcmp(*av, "not") == 0) {
1881 if (cmd->len & F_NOT)
1882 errx(EX_USAGE, "double \"not\" not allowed\n");
1887 if (*s == '!') { /* alternate syntax for NOT */
1888 if (cmd->len & F_NOT)
1889 errx(EX_USAGE, "double \"not\" not allowed");
1893 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) {
1894 if (key->type == IPFW_KEYWORD_TYPE_FILTER &&
1895 strcmp(key->word, s) == 0) {
1896 for (j = 0, map = mappings;
1897 j< MAPPING_SIZE; j++, map++) {
1898 if (map->type == IPFW_MAPPING_TYPE_IN_USE &&
1899 map->module == key->module &&
1900 map->opcode == key->opcode ) {
1902 (*fn)(&cmd, &ac, &av);
1907 } else if (i == KEYWORD_SIZE-1) {
1908 errx(EX_USAGE, "bad command `%s'", s);
1911 if (i >= KEYWORD_SIZE) {
1913 } else if (F_LEN(cmd) > 0) {
1914 cmd = next_cmd(cmd);
1920 errx(EX_USAGE, "bad command `%s'", *av);
1923 * Now copy stuff into the rule.
1924 * [filters][others][action][comment]
1926 dst = (ipfw_insn *)rule->cmd;
1928 * copy all filters, except comment
1930 src = (ipfw_insn *)cmdbuf;
1931 for (src = (ipfw_insn *)cmdbuf; src != cmd; src += i) {
1932 /* pick comment out */
1934 if (src->module == MODULE_BASIC_ID && src->opcode == O_BASIC_COMMENT) {
1937 bcopy(src, dst, i * sizeof(u_int32_t));
1938 dst = (ipfw_insn *)((uint32_t *)dst + i);
1943 * start action section, it begin with others
1945 rule->act_ofs = (uint32_t *)dst - (uint32_t *)(rule->cmd);
1948 * copy all other others
1950 for (src = (ipfw_insn *)othbuf; src != other; src += i) {
1952 bcopy(src, dst, i * sizeof(u_int32_t));
1953 dst = (ipfw_insn *)((uint32_t *)dst + i);
1956 /* copy the action to the end of rule */
1957 src = (ipfw_insn *)actbuf;
1959 bcopy(src, dst, i * sizeof(u_int32_t));
1960 dst = (ipfw_insn *)((uint32_t *)dst + i);
1963 * comment place behind the action
1965 if (the_comment != NULL) {
1966 i = F_LEN(the_comment);
1967 bcopy(the_comment, dst, i * sizeof(u_int32_t));
1968 dst = (ipfw_insn *)((uint32_t *)dst + i);
1971 rule->cmd_len = (u_int32_t *)dst - (u_int32_t *)(rule->cmd);
1972 i = (void *)dst - (void *)rule;
1973 if (do_set_x(IP_FW_ADD, (void *)rule, i) == -1) {
1974 err(EX_UNAVAILABLE, "getsockopt(%s)", "IP_FW_ADD");
1977 show_rules(rule, 10, 10);
1981 zero(int ac, char *av[])
1989 /* clear all entries */
1990 if (do_set_x(IP_FW_ZERO, NULL, 0) < 0)
1991 err(EX_UNAVAILABLE, "do_set_x(IP_FW_ZERO)");
1993 printf("Accounting cleared.\n");
1999 if (isdigit(**av)) {
2000 rulenum = atoi(*av);
2002 if (do_set_x(IP_FW_ZERO, &rulenum, sizeof rulenum)) {
2003 warn("rule %u: do_set_x(IP_FW_ZERO)", rulenum);
2004 failed = EX_UNAVAILABLE;
2005 } else if (!do_quiet)
2006 printf("Entry %d cleared\n", rulenum);
2008 errx(EX_USAGE, "invalid rule number ``%s''", *av);
2011 if (failed != EX_OK)
2016 resetlog(int ac, char *av[])
2024 /* clear all entries */
2025 if (setsockopt(ipfw_socket, IPPROTO_IP, IP_FW_RESETLOG, NULL, 0) < 0)
2026 err(EX_UNAVAILABLE, "setsockopt(IP_FW_RESETLOG)");
2028 printf("Logging counts reset.\n");
2035 if (isdigit(**av)) {
2036 rulenum = atoi(*av);
2038 if (setsockopt(ipfw_socket, IPPROTO_IP,
2039 IP_FW_RESETLOG, &rulenum, sizeof rulenum)) {
2040 warn("rule %u: setsockopt(IP_FW_RESETLOG)", rulenum);
2041 failed = EX_UNAVAILABLE;
2042 } else if (!do_quiet)
2043 printf("Entry %d logging count reset\n", rulenum);
2045 errx(EX_DATAERR, "invalid rule number ``%s''", *av);
2048 if (failed != EX_OK)
2055 int cmd = IP_FW_FLUSH;
2057 cmd = IP_DUMMYNET_FLUSH;
2058 } else if (do_nat) {
2059 cmd = IP_FW_NAT_FLUSH;
2064 printf("Are you sure? [yn] ");
2067 c = toupper(getc(stdin));
2068 while (c != '\n' && getc(stdin) != '\n')
2070 return; /* and do not flush */
2071 } while (c != 'Y' && c != 'N');
2072 if (c == 'N') /* user said no */
2075 if (do_set_x(cmd, NULL, 0) < 0 ) {
2076 err(EX_UNAVAILABLE, "do_set_x(%s)",
2077 do_pipe? "IP_DUMMYNET_FLUSH":
2078 (do_nat? "IP_FW_NAT_FLUSH": "IP_FW_FLUSH"));
2081 printf("Flushed all %s.\n", do_pipe ? "pipes":
2082 (do_nat?"nat configurations":"rules"));
2087 str2addr(const char* str, struct in_addr* addr)
2091 if (inet_aton (str, addr))
2094 hp = gethostbyname (str);
2096 errx (1, "unknown host %s", str);
2098 memcpy (addr, hp->h_addr, sizeof (struct in_addr));
2102 str2portrange(const char* str, const char* proto, port_range *portRange)
2107 u_short loPort, hiPort;
2109 /* First see if this is a service, return corresponding port if so. */
2110 sp = getservbyname (str, proto);
2112 SETLOPORT(*portRange, ntohs(sp->s_port));
2113 SETNUMPORTS(*portRange, 1);
2117 /* Not a service, see if it's a single port or port range. */
2118 sep = strchr (str, '-');
2120 SETLOPORT(*portRange, strtol(str, &end, 10));
2123 SETNUMPORTS(*portRange, 1);
2127 /* Error in port range field. */
2128 errx (EX_DATAERR, "%s/%s: unknown service", str, proto);
2131 /* Port range, get the values and sanity check. */
2132 sscanf (str, "%hu-%hu", &loPort, &hiPort);
2133 SETLOPORT(*portRange, loPort);
2134 SETNUMPORTS(*portRange, 0); /* Error by default */
2135 if (loPort <= hiPort)
2136 SETNUMPORTS(*portRange, hiPort - loPort + 1);
2138 if (GETNUMPORTS(*portRange) == 0)
2139 errx (EX_DATAERR, "invalid port range %s", str);
2145 str2proto(const char* str)
2147 if (!strcmp (str, "tcp"))
2149 if (!strcmp (str, "udp"))
2151 errx (EX_DATAERR, "unknown protocol %s. Expected tcp or udp", str);
2155 str2addr_portrange (const char* str, struct in_addr* addr,
2156 char* proto, port_range *portRange)
2160 ptr = strchr (str, ':');
2162 errx (EX_DATAERR, "%s is missing port number", str);
2167 str2addr (str, addr);
2168 return str2portrange (ptr, proto, portRange);
2172 * Search for interface with name "ifn", and fill n accordingly:
2174 * n->ip ip address of interface "ifn"
2175 * n->if_name copy of interface name "ifn"
2178 set_addr_dynamic(const char *ifn, struct cfg_nat *n)
2180 struct if_msghdr *ifm;
2181 struct ifa_msghdr *ifam;
2182 struct sockaddr_dl *sdl;
2183 struct sockaddr_in *sin;
2184 char *buf, *lim, *next;
2193 mib[4] = NET_RT_IFLIST;
2197 * Get interface data.
2199 if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1)
2200 err(1, "iflist-sysctl-estimate");
2201 if ((buf = malloc(needed)) == NULL)
2202 errx(1, "malloc failed");
2203 if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1)
2204 err(1, "iflist-sysctl-get");
2207 * Loop through interfaces until one with
2208 * given name is found. This is done to
2209 * find correct interface index for routing
2210 * message processing.
2214 while (next < lim) {
2215 ifm = (struct if_msghdr *)next;
2216 next += ifm->ifm_msglen;
2217 if (ifm->ifm_version != RTM_VERSION) {
2219 warnx("routing message version %d "
2220 "not understood", ifm->ifm_version);
2223 if (ifm->ifm_type == RTM_IFINFO) {
2224 sdl = (struct sockaddr_dl *)(ifm + 1);
2225 if (strlen(ifn) == sdl->sdl_nlen &&
2226 strncmp(ifn, sdl->sdl_data, sdl->sdl_nlen) == 0) {
2227 ifIndex = ifm->ifm_index;
2228 ifMTU = ifm->ifm_data.ifi_mtu;
2234 errx(1, "unknown interface name %s", ifn);
2236 * Get interface address.
2239 while (next < lim) {
2240 ifam = (struct ifa_msghdr *)next;
2241 next += ifam->ifam_msglen;
2242 if (ifam->ifam_version != RTM_VERSION) {
2244 warnx("routing message version %d "
2245 "not understood", ifam->ifam_version);
2248 if (ifam->ifam_type != RTM_NEWADDR)
2250 if (ifam->ifam_addrs & RTA_IFA) {
2252 char *cp = (char *)(ifam + 1);
2254 for (i = 1; i < RTA_IFA; i <<= 1) {
2255 if (ifam->ifam_addrs & i)
2256 cp += SA_SIZE((struct sockaddr *)cp);
2258 if (((struct sockaddr *)cp)->sa_family == AF_INET) {
2259 sin = (struct sockaddr_in *)cp;
2265 errx(1, "%s: cannot get interface address", ifn);
2267 n->ip = sin->sin_addr;
2268 strncpy(n->if_name, ifn, IF_NAMESIZE);
2274 setup_redir_addr(char *spool_buf, int len, int *_ac, char ***_av)
2276 struct cfg_redir *r;
2277 struct cfg_spool *tmp;
2279 char tmp_spool_buf[NAT_BUF_LEN];
2280 int ac, i, space, lsnat;
2287 if (len >= SOF_REDIR) {
2288 r = (struct cfg_redir *)spool_buf;
2289 /* Skip cfg_redir at beginning of buf. */
2290 spool_buf = &spool_buf[SOF_REDIR];
2297 r->mode = REDIR_ADDR;
2298 /* Extract local address. */
2300 errx(EX_DATAERR, "redirect_addr: missing local address");
2302 sep = strchr(*av, ',');
2303 if (sep) { /* LSNAT redirection syntax. */
2304 r->laddr.s_addr = INADDR_NONE;
2305 /* Preserve av, copy spool servers to tmp_spool_buf. */
2306 strncpy(tmp_spool_buf, *av, strlen(*av)+1);
2309 str2addr(*av, &r->laddr);
2313 /* Extract public address. */
2315 errx(EX_DATAERR, "redirect_addr: missing public address");
2317 str2addr(*av, &r->paddr);
2320 /* Setup LSNAT server pool. */
2322 sep = strtok(tmp_spool_buf, ", ");
2323 while (sep != NULL) {
2324 tmp = (struct cfg_spool *)spool_buf;
2325 if (len < SOF_SPOOL)
2330 str2addr(sep, &tmp->addr);
2333 /* Point to the next possible cfg_spool. */
2334 spool_buf = &spool_buf[SOF_SPOOL];
2335 sep = strtok(NULL, ", ");
2341 errx(EX_DATAERR, "redirect_addr: buf is too small\n");
2345 setup_redir_port(char *spool_buf, int len, int *_ac, char ***_av)
2347 char **av, *sep, *protoName;
2348 char tmp_spool_buf[NAT_BUF_LEN];
2349 int ac, space, lsnat;
2350 struct cfg_redir *r;
2351 struct cfg_spool *tmp;
2352 u_short numLocalPorts;
2353 port_range portRange;
2361 if (len >= SOF_REDIR) {
2362 r = (struct cfg_redir *)spool_buf;
2363 /* Skip cfg_redir at beginning of buf. */
2364 spool_buf = &spool_buf[SOF_REDIR];
2371 r->mode = REDIR_PORT;
2376 errx (EX_DATAERR, "redirect_port: missing protocol");
2378 r->proto = str2proto(*av);
2383 * Extract local address.
2386 errx (EX_DATAERR, "redirect_port: missing local address");
2388 sep = strchr(*av, ',');
2389 /* LSNAT redirection syntax. */
2391 r->laddr.s_addr = INADDR_NONE;
2394 /* Preserve av, copy spool servers to tmp_spool_buf. */
2395 strncpy(tmp_spool_buf, *av, strlen(*av)+1);
2398 if (str2addr_portrange (*av, &r->laddr, protoName, &portRange) != 0)
2399 errx(EX_DATAERR, "redirect_port:"
2400 "invalid local port range");
2402 r->lport = GETLOPORT(portRange);
2403 numLocalPorts = GETNUMPORTS(portRange);
2408 * Extract public port and optionally address.
2411 errx (EX_DATAERR, "redirect_port: missing public port");
2413 sep = strchr (*av, ':');
2415 if (str2addr_portrange (*av, &r->paddr, protoName, &portRange) != 0)
2416 errx(EX_DATAERR, "redirect_port:"
2417 "invalid public port range");
2419 r->paddr.s_addr = INADDR_ANY;
2420 if (str2portrange(*av, protoName, &portRange) != 0)
2421 errx(EX_DATAERR, "redirect_port:"
2422 "invalid public port range");
2425 r->pport = GETLOPORT(portRange);
2426 r->pport_cnt = GETNUMPORTS(portRange);
2430 * Extract remote address and optionally port.
2433 * NB: isalpha(**av) => we've to check that next parameter is really an
2434 * option for this redirect entry, else stop here processing arg[cv].
2436 if (ac != 0 && !isalpha(**av)) {
2437 sep = strchr (*av, ':');
2439 if (str2addr_portrange (*av, &r->raddr,
2440 protoName, &portRange) != 0)
2441 errx(EX_DATAERR, "redirect_port:"
2442 "invalid remote port range");
2444 SETLOPORT(portRange, 0);
2445 SETNUMPORTS(portRange, 1);
2446 str2addr (*av, &r->raddr);
2450 SETLOPORT(portRange, 0);
2451 SETNUMPORTS(portRange, 1);
2452 r->raddr.s_addr = INADDR_ANY;
2454 r->rport = GETLOPORT(portRange);
2455 r->rport_cnt = GETNUMPORTS(portRange);
2458 * Make sure port ranges match up, then add the redirect ports.
2460 if (numLocalPorts != r->pport_cnt)
2461 errx(EX_DATAERR, "redirect_port:"
2462 "port ranges must be equal in size");
2464 /* Remote port range is allowed to be '0' which means all ports. */
2465 if (r->rport_cnt != numLocalPorts &&
2466 (r->rport_cnt != 1 || r->rport != 0))
2467 errx(EX_DATAERR, "redirect_port: remote port must"
2468 "be 0 or equal to local port range in size");
2471 * Setup LSNAT server pool.
2474 sep = strtok(tmp_spool_buf, ", ");
2475 while (sep != NULL) {
2476 tmp = (struct cfg_spool *)spool_buf;
2477 if (len < SOF_SPOOL)
2482 if (str2addr_portrange(sep,
2483 &tmp->addr, protoName, &portRange) != 0)
2484 errx(EX_DATAERR, "redirect_port:"
2485 "invalid local port range");
2486 if (GETNUMPORTS(portRange) != 1)
2487 errx(EX_DATAERR, "redirect_port: local port"
2488 "must be single in this context");
2489 tmp->port = GETLOPORT(portRange);
2491 /* Point to the next possible cfg_spool. */
2492 spool_buf = &spool_buf[SOF_SPOOL];
2493 sep = strtok(NULL, ", ");
2499 errx(EX_DATAERR, "redirect_port: buf is too small\n");
2503 setup_redir_proto(char *spool_buf, int len, int *_ac, char ***_av)
2505 struct protoent *protoent;
2506 struct cfg_redir *r;
2513 if (len >= SOF_REDIR) {
2514 r = (struct cfg_redir *)spool_buf;
2515 /* Skip cfg_redir at beginning of buf. */
2516 spool_buf = &spool_buf[SOF_REDIR];
2522 r->mode = REDIR_PROTO;
2527 errx(EX_DATAERR, "redirect_proto: missing protocol");
2529 protoent = getprotobyname(*av);
2530 if (protoent == NULL)
2531 errx(EX_DATAERR, "redirect_proto: unknown protocol %s", *av);
2533 r->proto = protoent->p_proto;
2538 * Extract local address.
2541 errx(EX_DATAERR, "redirect_proto: missing local address");
2543 str2addr(*av, &r->laddr);
2547 * Extract optional public address.
2550 r->paddr.s_addr = INADDR_ANY;
2551 r->raddr.s_addr = INADDR_ANY;
2553 /* see above in setup_redir_port() */
2554 if (!isalpha(**av)) {
2555 str2addr(*av, &r->paddr);
2559 * Extract optional remote address.
2561 /* see above in setup_redir_port() */
2562 if (ac != 0 && !isalpha(**av)) {
2563 str2addr(*av, &r->raddr);
2571 errx(EX_DATAERR, "redirect_proto: buf is too small\n");
2575 show_nat_config(char *buf) {
2577 struct cfg_redir *t;
2578 struct cfg_spool *s;
2580 int i, cnt, flag, off;
2582 n = (struct cfg_nat *)buf;
2585 printf("ipfw nat %u config", n->id);
2586 if (strlen(n->if_name) != 0)
2587 printf(" if %s", n->if_name);
2588 else if (n->ip.s_addr != 0)
2589 printf(" ip %s", inet_ntoa(n->ip));
2590 while (n->mode != 0) {
2591 if (n->mode & PKT_ALIAS_LOG) {
2593 n->mode &= ~PKT_ALIAS_LOG;
2594 } else if (n->mode & PKT_ALIAS_DENY_INCOMING) {
2596 n->mode &= ~PKT_ALIAS_DENY_INCOMING;
2597 } else if (n->mode & PKT_ALIAS_SAME_PORTS) {
2598 printf(" same_ports");
2599 n->mode &= ~PKT_ALIAS_SAME_PORTS;
2600 } else if (n->mode & PKT_ALIAS_UNREGISTERED_ONLY) {
2601 printf(" unreg_only");
2602 n->mode &= ~PKT_ALIAS_UNREGISTERED_ONLY;
2603 } else if (n->mode & PKT_ALIAS_RESET_ON_ADDR_CHANGE) {
2605 n->mode &= ~PKT_ALIAS_RESET_ON_ADDR_CHANGE;
2606 } else if (n->mode & PKT_ALIAS_REVERSE) {
2608 n->mode &= ~PKT_ALIAS_REVERSE;
2609 } else if (n->mode & PKT_ALIAS_PROXY_ONLY) {
2610 printf(" proxy_only");
2611 n->mode &= ~PKT_ALIAS_PROXY_ONLY;
2614 /* Print all the redirect's data configuration. */
2615 for (cnt = 0; cnt < n->redir_cnt; cnt++) {
2616 t = (struct cfg_redir *)&buf[off];
2620 printf(" redirect_addr");
2621 if (t->spool_cnt == 0)
2622 printf(" %s", inet_ntoa(t->laddr));
2624 for (i = 0; i < t->spool_cnt; i++) {
2625 s = (struct cfg_spool *)&buf[off];
2630 printf("%s", inet_ntoa(s->addr));
2633 printf(" %s", inet_ntoa(t->paddr));
2636 p = getprotobynumber(t->proto);
2637 printf(" redirect_port %s ", p->p_name);
2638 if (!t->spool_cnt) {
2639 printf("%s:%u", inet_ntoa(t->laddr), t->lport);
2640 if (t->pport_cnt > 1)
2641 printf("-%u", t->lport + t->pport_cnt - 1);
2643 for (i=0; i < t->spool_cnt; i++) {
2644 s = (struct cfg_spool *)&buf[off];
2647 printf("%s:%u", inet_ntoa(s->addr), s->port);
2652 if (t->paddr.s_addr)
2653 printf("%s:", inet_ntoa(t->paddr));
2654 printf("%u", t->pport);
2655 if (!t->spool_cnt && t->pport_cnt > 1)
2656 printf("-%u", t->pport + t->pport_cnt - 1);
2658 if (t->raddr.s_addr) {
2659 printf(" %s", inet_ntoa(t->raddr));
2661 printf(":%u", t->rport);
2662 if (!t->spool_cnt && t->rport_cnt > 1)
2663 printf("-%u", t->rport +
2669 p = getprotobynumber(t->proto);
2670 printf(" redirect_proto %s %s", p->p_name,
2671 inet_ntoa(t->laddr));
2672 if (t->paddr.s_addr != 0) {
2673 printf(" %s", inet_ntoa(t->paddr));
2674 if (t->raddr.s_addr)
2675 printf(" %s", inet_ntoa(t->raddr));
2679 errx(EX_DATAERR, "unknown redir mode");
2688 show_nat(int ac, char **av) {
2690 struct cfg_redir *e;
2691 int i, nbytes, nalloc, size;
2692 int nat_cnt, redir_cnt, nat_id;
2704 nat_id = strtoul(*av, NULL, 10);
2707 while (nbytes >= nalloc) {
2708 nalloc = nalloc * 2;
2710 if ((data = realloc(data, nbytes)) == NULL) {
2711 err(EX_OSERR, "realloc");
2713 if (do_get_x(IP_FW_NAT_GET, data, &nbytes) < 0) {
2714 err(EX_OSERR, "do_get_x(IP_FW_NAT_GET)");
2722 nat_cnt = *((int *)data);
2723 for (i = sizeof(nat_cnt); nat_cnt; nat_cnt--) {
2724 n = (struct cfg_nat *)&data[i];
2725 if (n->id >= 0 && n->id <= IPFW_DEFAULT_RULE) {
2726 if (nat_id == 0 || n->id == nat_id)
2727 show_nat_config(&data[i]);
2729 i += sizeof(struct cfg_nat);
2730 for (redir_cnt = 0; redir_cnt < n->redir_cnt; redir_cnt++) {
2731 e = (struct cfg_redir *)&data[i];
2732 i += sizeof(struct cfg_redir) +
2733 e->spool_cnt * sizeof(struct cfg_spool);
2739 * do_set_x - extended version og do_set
2740 * insert a x_header in the beginning of the rule buf
2741 * and call setsockopt() with IP_FW_X.
2744 do_set_x(int optname, void *rule, int optlen)
2748 ip_fw_x_header *x_header;
2749 if (ipfw_socket < 0) {
2750 err(EX_UNAVAILABLE, "socket");
2752 bzero(new_rule_buf, IPFW_RULE_SIZE_MAX);
2753 x_header = (ip_fw_x_header *)new_rule_buf;
2754 x_header->opcode = optname;
2755 /* copy the rule into the newbuf, just after the x_header*/
2756 bcopy(rule, ++x_header, optlen);
2757 len = optlen + sizeof(ip_fw_x_header);
2758 return setsockopt(ipfw_socket, IPPROTO_IP, IP_FW_X, new_rule_buf, len);
2765 do_get_x(int optname, void *rule, int *optlen)
2769 ip_fw_x_header *x_header;
2770 if (ipfw_socket < 0) {
2771 err(EX_UNAVAILABLE, "socket");
2773 bzero(new_rule_buf, IPFW_RULE_SIZE_MAX);
2774 x_header = (ip_fw_x_header *)new_rule_buf;
2775 x_header->opcode = optname;
2776 /* copy the rule into the newbuf, just after the x_header*/
2777 bcopy(rule, ++x_header, *optlen);
2778 len = *optlen + sizeof(ip_fw_x_header);
2779 retval = getsockopt(ipfw_socket, IPPROTO_IP, IP_FW_X, new_rule_buf, &len);
2780 bcopy(new_rule_buf, rule, len);
2786 config_nat(int ac, char **av)
2788 struct cfg_nat *n; /* Nat instance configuration. */
2789 int i, len, off, tok;
2790 char *id, buf[NAT_BUF_LEN]; /* Buffer for serialized data. */
2793 /* Offset in buf: save space for n at the beginning. */
2794 off = sizeof(struct cfg_nat);
2795 memset(buf, 0, sizeof(buf));
2796 n = (struct cfg_nat *)buf;
2800 if (ac && isdigit(**av)) {
2806 errx(EX_DATAERR, "missing nat id");
2808 errx(EX_DATAERR, "missing option");
2811 tok = match_token(nat_params, *av);
2816 errx(EX_DATAERR, "missing option");
2817 if (!inet_aton(av[0], &(n->ip)))
2818 errx(EX_DATAERR, "bad ip address ``%s''",
2824 errx(EX_DATAERR, "missing option");
2825 set_addr_dynamic(av[0], n);
2829 n->mode |= PKT_ALIAS_LOG;
2832 n->mode |= PKT_ALIAS_DENY_INCOMING;
2834 case TOK_SAME_PORTS:
2835 n->mode |= PKT_ALIAS_SAME_PORTS;
2837 case TOK_UNREG_ONLY:
2838 n->mode |= PKT_ALIAS_UNREGISTERED_ONLY;
2840 case TOK_RESET_ADDR:
2841 n->mode |= PKT_ALIAS_RESET_ON_ADDR_CHANGE;
2844 n->mode |= PKT_ALIAS_REVERSE;
2846 case TOK_PROXY_ONLY:
2847 n->mode |= PKT_ALIAS_PROXY_ONLY;
2850 * All the setup_redir_* functions work directly in the final
2851 * buffer, see above for details.
2853 case TOK_REDIR_ADDR:
2854 case TOK_REDIR_PORT:
2855 case TOK_REDIR_PROTO:
2857 case TOK_REDIR_ADDR:
2858 i = setup_redir_addr(&buf[off], len, &ac, &av);
2860 case TOK_REDIR_PORT:
2861 i = setup_redir_port(&buf[off], len, &ac, &av);
2863 case TOK_REDIR_PROTO:
2864 i = setup_redir_proto(&buf[off], len, &ac, &av);
2872 errx(EX_DATAERR, "unrecognised option ``%s''", av[-1]);
2875 i = do_set_x(IP_FW_NAT_CFG, buf, off);
2877 err(1, "do_set_x(%s)", "IP_FW_NAT_CFG");
2879 /* After every modification, we show the resultant rule. */
2881 char *_av[] = {"config", id};
2887 ipfw_main(int ac, char **av)
2894 /* Set the force flag for non-interactive processes */
2895 do_force = !isatty(STDIN_FILENO);
2897 optind = optreset = 1;
2898 while ((ch = getopt(ac, av, "hs:acdDefNStTv")) != -1)
2900 case 'h': /* help */
2902 break; /* NOTREACHED */
2904 case 's': /* sort */
2905 do_sort = atoi(optarg);
2947 NEED1("bad arguments, for usage summary ``ipfw''");
2950 * optional: pipe or queue or nat
2954 if (!strncmp(*av, "nat", strlen(*av)))
2956 else if (!strncmp(*av, "pipe", strlen(*av))) {
2958 } else if (!strncmp(*av, "queue", strlen(*av))) {
2961 NEED1("missing command");
2964 * for pipes and queues and nat we normally say 'pipe NN config'
2965 * but the code is easier to parse as 'pipe config NN'
2966 * so we swap the two arguments.
2968 if ((do_pipe || do_nat) && ac > 2 && isdigit(*(av[1]))) {
2974 if (!strncmp(*av, "add", strlen(*av))) {
2977 } else if (!strncmp(*av, "delete", strlen(*av))) {
2978 delete_rules(ac, av);
2979 } else if (!strncmp(*av, "flush", strlen(*av))) {
2981 } else if (!strncmp(*av, "list", strlen(*av))) {
2984 } else if (!strncmp(*av, "show", strlen(*av))) {
2988 } else if (!strncmp(*av, "zero", strlen(*av))) {
2990 } else if (!strncmp(*av, "set", strlen(*av))) {
2991 sets_handler(ac, av);
2992 } else if (!strncmp(*av, "module", strlen(*av))) {
2994 if (!strncmp(*av, "show", strlen(*av)) ||
2995 !strncmp(*av, "show", strlen(*av))) {
2996 list_modules(ac, av);
2998 errx(EX_USAGE, "bad ipfw module command `%s'", *av);
3000 } else if (!strncmp(*av, "enable", strlen(*av))) {
3001 sysctl_handler(ac, av, 1);
3002 } else if (!strncmp(*av, "disable", strlen(*av))) {
3003 sysctl_handler(ac, av, 0);
3004 } else if (!strncmp(*av, "resetlog", strlen(*av))) {
3006 } else if (!strncmp(*av, "log", strlen(*av))) {
3008 if (!strncmp(*av, "reset", strlen(*av))) {
3010 } else if (!strncmp(*av, "off", strlen(*av))) {
3012 } else if (!strncmp(*av, "on", strlen(*av))) {
3015 errx(EX_USAGE, "bad command `%s'", *av);
3017 } else if (!strncmp(*av, "nat", strlen(*av))) {
3019 if (!strncmp(*av, "config", strlen(*av))) {
3021 } else if (!strncmp(*av, "flush", strlen(*av))) {
3023 } else if (!strncmp(*av, "show", strlen(*av)) ||
3024 !strncmp(*av, "list", strlen(*av))) {
3026 } else if (!strncmp(*av, "delete", strlen(*av))) {
3027 delete_nat_config(ac, av);
3029 errx(EX_USAGE, "bad ipfw nat command `%s'", *av);
3031 } else if (!strncmp(*av, "pipe", strlen(*av)) ||
3032 !strncmp(*av, "queue", strlen(*av))) {
3034 if (!strncmp(*av, "config", strlen(*av))) {
3035 config_dummynet(ac, av);
3036 } else if (!strncmp(*av, "flush", strlen(*av))) {
3038 } else if (!strncmp(*av, "show", strlen(*av))) {
3039 show_dummynet(ac, av);
3041 errx(EX_USAGE, "bad ipfw pipe command `%s'", *av);
3043 } else if (!strncmp(*av, "state", strlen(*av))) {
3045 if (!strncmp(*av, "add", strlen(*av))) {
3047 } else if (!strncmp(*av, "delete", strlen(*av))) {
3048 delete_state(ac, av);
3049 } else if (!strncmp(*av, "flush", strlen(*av))) {
3050 flush_state(ac, av);
3051 } else if (!strncmp(*av, "list", strlen(*av))) {
3054 } else if (!strncmp(*av, "show", strlen(*av))) {
3059 errx(EX_USAGE, "bad ipfw state command `%s'", *av);
3062 errx(EX_USAGE, "bad ipfw command `%s'", *av);
3068 ipfw_readfile(int ac, char *av[])
3071 char *a, *p, *args[MAX_ARGS], *cmd = NULL;
3073 int i=0, lineno=0, qflag=0, pflag=0, status;
3078 while ((c = getopt(ac, av, "D:U:p:q")) != -1)
3082 errx(EX_USAGE, "-D requires -p");
3083 if (i > MAX_ARGS - 2)
3085 "too many -D or -U options");
3092 errx(EX_USAGE, "-U requires -p");
3093 if (i > MAX_ARGS - 2)
3095 "too many -D or -U options");
3112 errx(EX_USAGE, "bad arguments, for usage"
3113 " summary ``ipfw''");
3119 errx(EX_USAGE, "extraneous filename arguments");
3121 if ((f = fopen(av[0], "r")) == NULL)
3122 err(EX_UNAVAILABLE, "fopen: %s", av[0]);
3125 /* pipe through preprocessor (cpp or m4) */
3130 if (pipe(pipedes) == -1)
3131 err(EX_OSERR, "cannot create pipe");
3133 switch ((preproc = fork())) {
3135 err(EX_OSERR, "cannot fork");
3139 if (dup2(fileno(f), 0) == -1 ||
3140 dup2(pipedes[1], 1) == -1) {
3141 err(EX_OSERR, "dup2()");
3147 err(EX_OSERR, "execvp(%s) failed", cmd);
3153 if ((f = fdopen(pipedes[0], "r")) == NULL) {
3154 int savederrno = errno;
3156 kill(preproc, SIGTERM);
3158 err(EX_OSERR, "fdopen()");
3163 while (fgets(buf, BUFSIZ, f)) {
3165 sprintf(linename, "Line %d", lineno);
3170 if ((p = strchr(buf, '#')) != NULL)
3175 for (a = strtok(buf, WHITESP); a && i < MAX_ARGS;
3176 a = strtok(NULL, WHITESP), i++) {
3180 if (i == (qflag? 2: 1))
3183 errx(EX_USAGE, "%s: too many arguments", linename);
3190 if (waitpid(preproc, &status, 0) == -1)
3191 errx(EX_OSERR, "waitpid()");
3192 if (WIFEXITED(status) && WEXITSTATUS(status) != EX_OK)
3193 errx(EX_UNAVAILABLE, "preprocessor exited with status %d",
3194 WEXITSTATUS(status));
3195 else if (WIFSIGNALED(status))
3196 errx(EX_UNAVAILABLE, "preprocessor exited with signal %d",
3202 main(int ac, char *av[])
3204 ipfw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
3205 if (ipfw_socket < 0)
3206 err(EX_UNAVAILABLE, "socket");
3208 memset(keywords, 0, sizeof(struct ipfw_keyword) * KEYWORD_SIZE);
3209 memset(mappings, 0, sizeof(struct ipfw_mapping) * MAPPING_SIZE);
3211 prepare_default_funcs();
3213 if (ac > 1 && av[ac - 1][0] == '/' && access(av[ac - 1], R_OK) == 0)
3214 ipfw_readfile(ac, av);