2 * Copyright (c) 2002 Luigi Rizzo
3 * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
4 * Copyright (c) 1994 Ugen J.S.Antsilevich
6 * Idea and grammar partially left from:
7 * Copyright (c) 1993 Daniel Boulet
9 * Redistribution and use in source forms, with and without modification,
10 * are permitted provided that this entire comment appears intact.
12 * Redistribution in binary form may occur without any restrictions.
13 * Obviously, it would be nice if you gave credit where credit is due
14 * but requiring it would be too onerous.
16 * This software is provided ``AS IS'' without any warranties of any kind.
18 * NEW command line interface for IP firewall facility
20 * $FreeBSD: src/sbin/ipfw/ipfw2.c,v 1.4.2.13 2003/05/27 22:21:11 gshapiro Exp $
23 #include <sys/param.h>
25 #include <sys/socket.h>
26 #include <sys/sockio.h>
27 #include <sys/sysctl.h>
31 #include <arpa/inet.h>
49 #include <netinet/in.h>
50 #include <netinet/in_systm.h>
51 #include <netinet/ip.h>
52 #include <netinet/ip_icmp.h>
53 #include <netinet/tcp.h>
55 #include <net/if_dl.h>
56 #include <net/route.h>
57 #include <net/ethernet.h>
60 #include "../../sys/net/ipfw3/ip_fw3.h"
61 #include "../../sys/net/dummynet3/ip_dummynet3.h"
62 #include "../../sys/net/libalias/alias.h"
63 #include "../../sys/net/ipfw3_basic/ip_fw3_basic.h"
64 #include "../../sys/net/ipfw3_nat/ip_fw3_nat.h"
68 #define KEYWORD_SIZE 256
69 #define MAPPING_SIZE 256
71 #define MAX_KEYWORD_LEN 20
73 #define WHITESP " \t\f\v\n\r"
74 #define IPFW_LIB_PATH "/usr/lib/libipfw3%s.so"
75 #define IP_MASK_ALL 0xffffffff
76 #define NAT_BUF_LEN 1024
78 * we use IPPROTO_ETHERTYPE as a fake protocol id to call the print routines
79 * This is only used in this code.
81 #define IPPROTO_ETHERTYPE 0x1000
84 * This macro returns the size of a struct sockaddr when passed
85 * through a routing socket. Basically we round up sa_len to
86 * a multiple of sizeof(long), with a minimum of sizeof(long).
87 * The check for a NULL pointer is just a convenience, probably never used.
88 * The case sa_len == 0 should only apply to empty structures.
91 ( (!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? \
93 1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) )
96 * show_rules() prints the body of an ipfw rule.
97 * Because the standard rule has at least proto src_ip dst_ip, we use
98 * a helper function to produce these entries if not provided explicitly.
99 * The first argument is the list of fields we have, the second is
100 * the list of fields we want to be printed.
102 * Special cases if we have provided a MAC header:
103 * + if the rule does not contain IP addresses/ports, do not print them;
104 * + if the rule does not contain an IP proto, print "all" instead of "ip";
107 #define HAVE_PROTO 0x0001
108 #define HAVE_SRCIP 0x0002
109 #define HAVE_DSTIP 0x0004
110 #define HAVE_MAC 0x0008
111 #define HAVE_MACTYPE 0x0010
112 #define HAVE_OPTIONS 0x8000
114 #define HAVE_IP (HAVE_PROTO | HAVE_SRCIP | HAVE_DSTIP)
117 * Definition of a port range, and macros to deal with values.
118 * FORMAT: HI 16-bits == first port in range, 0 == all ports.
119 * LO 16-bits == number of ports in range
120 * NOTES: - Port values are not stored in network byte order.
123 #define port_range u_long
125 #define GETLOPORT(x) ((x) >> 0x10)
126 #define GETNUMPORTS(x) ((x) & 0x0000ffff)
127 #define GETHIPORT(x) (GETLOPORT((x)) + GETNUMPORTS((x)))
129 /* Set y to be the low-port value in port_range variable x. */
130 #define SETLOPORT(x, y) ((x) = ((x) & 0x0000ffff) | ((y) << 0x10))
132 /* Set y to be the number of ports in port_range variable x. */
133 #define SETNUMPORTS(x, y) ((x) = ((x) & 0xffff0000) | (y))
135 #define INC_ARGCV() do { \
143 int ipfw_socket = -1; /* main RAW socket */
144 int do_resolv, /* Would try to resolve all */
145 do_acct, /* Show packet/byte count */
146 do_time, /* Show time stamps */
147 do_quiet = 1, /* Be quiet , default is quiet*/
148 do_force, /* Don't ask for confirmation */
149 do_pipe, /* this cmd refers to a pipe */
150 do_nat, /* Nat configuration. */
151 do_sort, /* field to sort results (0 = no) */
152 do_dynamic, /* display dynamic rules */
153 do_expired, /* display expired dynamic rules */
154 do_compact, /* show rules in compact mode */
155 show_sets, /* display rule sets */
194 struct char_int_map dummynet_params[] = {
196 { "noerror", TOK_NOERROR },
197 { "buckets", TOK_BUCKETS },
198 { "dst-ip", TOK_DSTIP },
199 { "src-ip", TOK_SRCIP },
200 { "dst-port", TOK_DSTPORT },
201 { "src-port", TOK_SRCPORT },
202 { "proto", TOK_PROTO },
203 { "weight", TOK_WEIGHT },
205 { "mask", TOK_MASK },
206 { "droptail", TOK_DROPTAIL },
208 { "gred", TOK_GRED },
210 { "bandwidth", TOK_BW },
211 { "delay", TOK_DELAY },
212 { "pipe", TOK_PIPE },
213 { "queue", TOK_QUEUE },
214 { "dummynet-params", TOK_NULL },
218 struct char_int_map nat_params[] = {
222 { "deny_in", TOK_DENY_INC },
223 { "same_ports", TOK_SAME_PORTS },
224 { "unreg_only", TOK_UNREG_ONLY },
225 { "reset", TOK_RESET_ADDR },
226 { "reverse", TOK_ALIAS_REV },
227 { "proxy_only", TOK_PROXY_ONLY },
228 { "redirect_addr", TOK_REDIR_ADDR },
229 { "redirect_port", TOK_REDIR_PORT },
230 { "redirect_proto", TOK_REDIR_PROTO },
234 struct ipfw_keyword {
236 char word[MAX_KEYWORD_LEN];
241 struct ipfw_mapping {
249 struct ipfw_keyword keywords[KEYWORD_SIZE];
250 struct ipfw_mapping mappings[MAPPING_SIZE];
253 match_token(struct char_int_map *table, char *string)
256 if (strcmp(table->key, string) == 0) {
265 get_modules(char *modules_str, int len)
267 if (do_get_x(IP_FW_MODULE, modules_str, &len) < 0)
268 errx(EX_USAGE, "ipfw3 not loaded.");
272 list_modules(int ac, char *av[])
274 void *module_str = NULL;
276 if ((module_str = realloc(module_str, len)) == NULL)
277 err(EX_OSERR, "realloc");
279 get_modules(module_str, len);
280 printf("%s", (char *)module_str);
283 parse_accept(ipfw_insn **cmd, int *ac, char **av[])
285 (*cmd)->opcode = O_BASIC_ACCEPT;
286 (*cmd)->module = MODULE_BASIC_ID;
287 (*cmd)->len = (*cmd)->len|LEN_OF_IPFWINSN;
292 parse_deny(ipfw_insn **cmd, int *ac, char **av[])
294 (*cmd)->opcode = O_BASIC_DENY;
295 (*cmd)->module = MODULE_BASIC_ID;
296 (*cmd)->len = (*cmd)->len|LEN_OF_IPFWINSN;
301 show_accept(ipfw_insn *cmd, int show_or)
307 show_deny(ipfw_insn *cmd, int show_or)
316 init_module mod_init_func;
318 char module_lib_file[50];
319 void *module_str = NULL;
322 if ((module_str = realloc(module_str, len)) == NULL)
323 err(EX_OSERR, "realloc");
325 get_modules(module_str, len);
327 const char s[2] = ",";
329 token = strtok(module_str, s);
330 while (token != NULL) {
331 sprintf(module_lib_file, IPFW_LIB_PATH, token);
332 token = strtok(NULL, s);
333 module_lib = dlopen(module_lib_file, RTLD_LAZY);
335 fprintf(stderr, "Couldn't open %s: %s\n",
336 module_lib_file, dlerror());
339 mod_init_func = dlsym(module_lib, "load_module");
340 if ((error = dlerror()))
342 fprintf(stderr, "Couldn't find init function: %s\n", error);
345 (*mod_init_func)((register_func)register_ipfw_func,
346 (register_keyword)register_ipfw_keyword);
351 prepare_default_funcs(void)
354 register_ipfw_keyword(MODULE_BASIC_ID, O_BASIC_ACCEPT,
355 "allow", IPFW_KEYWORD_TYPE_ACTION);
356 register_ipfw_keyword(MODULE_BASIC_ID, O_BASIC_ACCEPT,
357 "accept", IPFW_KEYWORD_TYPE_ACTION);
358 register_ipfw_func(MODULE_BASIC_ID, O_BASIC_ACCEPT,
359 (parser_func)parse_accept, (shower_func)show_accept);
361 register_ipfw_keyword(MODULE_BASIC_ID, O_BASIC_DENY, "deny",
362 IPFW_KEYWORD_TYPE_ACTION);
363 register_ipfw_keyword(MODULE_BASIC_ID, O_BASIC_DENY, "reject",
364 IPFW_KEYWORD_TYPE_ACTION);
365 register_ipfw_func(MODULE_BASIC_ID, O_BASIC_DENY,
366 (parser_func)parse_deny, (shower_func)show_deny);
370 register_ipfw_keyword(int module, int opcode, char *word, int type)
372 struct ipfw_keyword *tmp;
376 if (tmp->type == IPFW_KEYWORD_TYPE_NONE) {
377 strcpy(tmp->word, word);
378 tmp->module = module;
379 tmp->opcode = opcode;
383 if (strcmp(tmp->word, word) == 0)
384 errx(EX_USAGE, "keyword `%s' exists", word);
392 register_ipfw_func(int module, int opcode, parser_func parser, shower_func shower)
394 struct ipfw_mapping *tmp;
398 if (tmp->type == IPFW_MAPPING_TYPE_NONE) {
399 tmp->module = module;
400 tmp->opcode = opcode;
401 tmp->parser = parser;
402 tmp->shower = shower;
403 tmp->type = IPFW_MAPPING_TYPE_IN_USE;
406 if (tmp->opcode == opcode && tmp->module == module) {
407 errx(EX_USAGE, "func `%d' of module `%d' exists",
418 * check whether 'or' need to be printed,
420 * first filter with 'or', print name without 'or'
421 * same as previous, then print or and no filter name
422 * not first but different from previous, print name without 'or'
423 * show_or = 1: show or and ignore filter name
424 * show_or = 0: show filter name ignore or
426 void prev_show_chk(ipfw_insn *cmd, uint8_t *prev_module, uint8_t *prev_opcode,
429 if (cmd->len & F_OR) {
430 if (*prev_module == 0 && *prev_opcode == 0) {
433 *prev_module = cmd->module;
434 *prev_opcode = cmd->opcode;
435 } else if (cmd->module == *prev_module && cmd->opcode ==
437 /* if same as previous */
442 *prev_module = cmd->module;
443 *prev_opcode = cmd->opcode;
453 * word can be: proto from to other
457 * other show all other filters
459 int show_filter(ipfw_insn *cmd, char *word, int type)
461 struct ipfw_keyword *k;
462 struct ipfw_mapping *m;
465 int need_check, show_or;
466 uint8_t prev_module, prev_opcode;
470 for (i = 1; i< KEYWORD_SIZE; i++, k++) {
471 if (strcmp(word, "proto") == 0 ||
472 strcmp(word, "from") == 0 ||
473 strcmp(word, "to") == 0) {
474 need_check = strcmp(k->word, word) == 0;
476 need_check = strcmp(k->word, "proto") != 0 &&
477 strcmp(k->word, "from")!=0 &&
478 strcmp(k->word, "to")!=0;
480 if (k->type == type && need_check) {
481 if (k->module == cmd->module &&
482 k->opcode == cmd->opcode) {
483 for (j = 1; j< MAPPING_SIZE; j++, m++) {
485 IPFW_MAPPING_TYPE_IN_USE &&
486 k->module == m->module &&
487 k->opcode == m->opcode) {
488 prev_show_chk(cmd, &prev_module,
489 &prev_opcode, &show_or);
490 if (cmd->len & F_NOT)
505 show_rules(struct ipfw_ioc_rule *rule, int pcwidth, int bcwidth)
507 static int twidth = 0;
511 u_int32_t set_disable = rule->set_disable;
513 if (set_disable & (1 << rule->set)) { /* disabled */
517 printf("# DISABLED ");
519 printf("%05u ", rule->rulenum);
522 printf("%*ju %*ju ", pcwidth, (uintmax_t)rule->pcnt, bcwidth,
523 (uintmax_t)rule->bcnt);
529 strcpy(timestr, ctime((time_t *)&twidth));
530 *strchr(timestr, '\n') = '\0';
531 twidth = strlen(timestr);
533 if (rule->timestamp) {
534 time_t t = _long_to_time(rule->timestamp);
536 strcpy(timestr, ctime(&t));
537 *strchr(timestr, '\n') = '\0';
538 printf("%s ", timestr);
540 printf("%*s ", twidth, " ");
542 } else if (do_time == 2) {
543 printf( "%10u ", rule->timestamp);
547 printf("set %d ", rule->set);
550 struct ipfw_keyword *k;
551 struct ipfw_mapping *m;
552 shower_func fn, comment_fn = NULL;
553 ipfw_insn *comment_cmd;
557 * show others and actions
559 for (l = rule->cmd_len - rule->act_ofs, cmd = ACTION_PTR(rule);
560 l > 0; l -= F_LEN(cmd),
561 cmd = (ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) {
564 for (i = 1; i< KEYWORD_SIZE; i++, k++) {
565 if ( k->module == cmd->module && k->opcode == cmd->opcode ) {
566 for (j = 1; j< MAPPING_SIZE; j++, m++) {
567 if (m->type == IPFW_MAPPING_TYPE_IN_USE &&
568 m->module == cmd->module &&
569 m->opcode == cmd->opcode) {
570 if (cmd->module == MODULE_BASIC_ID &&
571 cmd->opcode == O_BASIC_COMMENT) {
572 comment_fn = m->shower;
578 if (cmd->module == MODULE_BASIC_ID &&
580 O_BASIC_CHECK_STATE) {
595 for (l = rule->act_ofs, cmd = rule->cmd; l > 0; l -= F_LEN(cmd),
596 cmd = (ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) {
597 changed = show_filter(cmd, "proto", IPFW_KEYWORD_TYPE_FILTER);
599 if (!changed && !do_quiet)
606 for (l = rule->act_ofs, cmd = rule->cmd; l > 0; l -= F_LEN(cmd),
607 cmd = (ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) {
608 changed = show_filter(cmd, "from", IPFW_KEYWORD_TYPE_FILTER);
610 if (!changed && !do_quiet)
617 for (l = rule->act_ofs, cmd = rule->cmd; l > 0; l -= F_LEN(cmd),
618 cmd = (ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) {
619 changed = show_filter(cmd, "to", IPFW_KEYWORD_TYPE_FILTER);
621 if (!changed && !do_quiet)
627 for (l = rule->act_ofs, cmd = rule->cmd, m = mappings;
628 l > 0; l -= F_LEN(cmd),
629 cmd=(ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) {
630 show_filter(cmd, "other", IPFW_KEYWORD_TYPE_FILTER);
633 /* show the comment in the end */
634 if (comment_fn != NULL) {
635 (*comment_fn)(comment_cmd, 0);
642 show_states(struct ipfw_ioc_state *d, int pcwidth, int bcwidth)
647 printf("%05u ", d->rulenum);
649 printf("%*ju %*ju ", pcwidth, (uintmax_t)d->pcnt,
650 bcwidth, (uintmax_t)d->bcnt);
654 /* state->timestamp */
656 time_t t = _long_to_time(d->timestamp);
657 strcpy(timestr, ctime(&t));
658 *strchr(timestr, '\n') = '\0';
659 printf(" (%s", timestr);
661 /* state->lifetime */
662 printf(" %ds", d->lifetime);
666 t = _long_to_time(d->expiry);
667 strcpy(timestr, ctime(&t));
668 *strchr(timestr, '\n') = '\0';
669 printf(" %s)", timestr);
674 } else if (do_time == 2) {
675 printf("(%u %ds %u) ", d->timestamp, d->lifetime, d->expiry);
678 if ((pe = getprotobynumber(d->flow_id.proto)) != NULL)
679 printf(" %s", pe->p_name);
681 printf(" proto %u", d->flow_id.proto);
683 a.s_addr = htonl(d->flow_id.src_ip);
684 printf(" %s %d", inet_ntoa(a), d->flow_id.src_port);
686 a.s_addr = htonl(d->flow_id.dst_ip);
687 printf(" <-> %s %d", inet_ntoa(a), d->flow_id.dst_port);
688 printf(" CPU %d", d->cpuid);
693 sort_q(const void *pa, const void *pb)
695 int rev = (do_sort < 0);
696 int field = rev ? -do_sort : do_sort;
698 const struct dn_ioc_flowqueue *a = pa;
699 const struct dn_ioc_flowqueue *b = pb;
703 res = a->len - b->len;
706 res = a->len_bytes - b->len_bytes;
709 case 3: /* tot pkts */
710 res = a->tot_pkts - b->tot_pkts;
713 case 4: /* tot bytes */
714 res = a->tot_bytes - b->tot_bytes;
721 return (int)(rev ? res : -res);
725 show_queues(struct dn_ioc_flowset *fs, struct dn_ioc_flowqueue *q)
729 printf("mask: 0x%02x 0x%08x/0x%04x -> 0x%08x/0x%04x\n",
730 fs->flow_mask.u.ip.proto,
731 fs->flow_mask.u.ip.src_ip, fs->flow_mask.u.ip.src_port,
732 fs->flow_mask.u.ip.dst_ip, fs->flow_mask.u.ip.dst_port);
733 if (fs->rq_elements == 0)
736 printf("BKT Prot ___Source IP/port____ "
737 "____Dest. IP/port____ Tot_pkt/bytes Pkt/Byte Drp\n");
739 heapsort(q, fs->rq_elements, sizeof(*q), sort_q);
740 for (l = 0; l < fs->rq_elements; l++) {
744 ina.s_addr = htonl(q[l].id.u.ip.src_ip);
745 printf("%3d ", q[l].hash_slot);
746 pe = getprotobynumber(q[l].id.u.ip.proto);
748 printf("%-4s ", pe->p_name);
750 printf("%4u ", q[l].id.u.ip.proto);
752 inet_ntoa(ina), q[l].id.u.ip.src_port);
753 ina.s_addr = htonl(q[l].id.u.ip.dst_ip);
755 inet_ntoa(ina), q[l].id.u.ip.dst_port);
756 printf("%4ju %8ju %2u %4u %3u\n",
757 (uintmax_t)q[l].tot_pkts, (uintmax_t)q[l].tot_bytes,
758 q[l].len, q[l].len_bytes, q[l].drops);
760 printf(" S %20ju F %20ju\n",
761 (uintmax_t)q[l].S, (uintmax_t)q[l].F);
766 show_flowset_parms(struct dn_ioc_flowset *fs, char *prefix)
770 char red[90]; /* Display RED parameters */
774 if (fs->flags_fs & DN_QSIZE_IS_BYTES) {
776 sprintf(qs, "%d KB", l / 1024);
778 sprintf(qs, "%d B", l);
780 sprintf(qs, "%3d sl.", l);
782 sprintf(plr, "plr %f", 1.0 * fs->plr / (double)(0x7fffffff));
785 if (fs->flags_fs & DN_IS_RED) /* RED parameters */
787 "\n\t %cRED w_q %f min_th %d max_th %d max_p %f",
788 (fs->flags_fs & DN_IS_GENTLE_RED) ? 'G' : ' ',
789 1.0 * fs->w_q / (double)(1 << SCALE_RED),
790 SCALE_VAL(fs->min_th),
791 SCALE_VAL(fs->max_th),
792 1.0 * fs->max_p / (double)(1 << SCALE_RED));
794 sprintf(red, "droptail");
796 printf("%s %s%s %d queues (%d buckets) %s\n",
797 prefix, qs, plr, fs->rq_elements, fs->rq_size, red);
801 show_pipes(void *data, int nbytes, int ac, char *av[])
805 struct dn_ioc_pipe *p = (struct dn_ioc_pipe *)data;
806 struct dn_ioc_flowset *fs;
807 struct dn_ioc_flowqueue *q;
811 rulenum = strtoul(*av++, NULL, 10);
814 for (; nbytes >= sizeof(*p); p = (struct dn_ioc_pipe *)next) {
815 double b = p->bandwidth;
819 if (p->fs.fs_type != DN_IS_PIPE)
820 break; /* done with pipes, now queues */
823 * compute length, as pipe have variable size
825 l = sizeof(*p) + p->fs.rq_elements * sizeof(*q);
826 next = (void *)p + l;
829 if (rulenum != 0 && rulenum != p->pipe_nr)
836 sprintf(buf, "unlimited");
837 else if (b >= 1000000)
838 sprintf(buf, "%7.3f Mbit/s", b/1000000);
840 sprintf(buf, "%7.3f Kbit/s", b/1000);
842 sprintf(buf, "%7.3f bit/s ", b);
844 sprintf(prefix, "%05d: %s %4d ms ",
845 p->pipe_nr, buf, p->delay);
846 show_flowset_parms(&p->fs, prefix);
848 printf(" V %20ju\n", (uintmax_t)p->V >> MY_M);
850 q = (struct dn_ioc_flowqueue *)(p+1);
851 show_queues(&p->fs, q);
854 for (fs = next; nbytes >= sizeof(*fs); fs = next) {
857 if (fs->fs_type != DN_IS_QUEUE)
859 l = sizeof(*fs) + fs->rq_elements * sizeof(*q);
860 next = (void *)fs + l;
862 q = (struct dn_ioc_flowqueue *)(fs+1);
863 sprintf(prefix, "q%05d: weight %d pipe %d ",
864 fs->fs_nr, fs->weight, fs->parent_nr);
865 show_flowset_parms(fs, prefix);
871 * This one handles all set-related commands
872 * ipfw set { show | enable | disable }
874 * ipfw set move X to Y
875 * ipfw set move rule X to Y
878 sets_handler(int ac, char *av[])
880 u_int32_t set_disable, masks[2];
882 u_int8_t cmd, new_set;
887 errx(EX_USAGE, "set needs command");
888 if (!strncmp(*av, "show", strlen(*av)) ) {
894 while (nbytes >= nalloc) {
895 nalloc = nalloc * 2+321;
898 if ((data = malloc(nbytes)) == NULL) {
899 err(EX_OSERR, "malloc");
901 } else if ((data = realloc(data, nbytes)) == NULL) {
902 err(EX_OSERR, "realloc");
904 if (do_get_x(IP_FW_GET, data, &nbytes) < 0) {
905 err(EX_OSERR, "getsockopt(IP_FW_GET)");
908 set_disable = ((struct ipfw_ioc_rule *)data)->set_disable;
909 for (i = 0, msg = "disable" ; i < 31; i++)
910 if ( (set_disable & (1<<i))) {
911 printf("%s %d", msg, i);
914 msg = (set_disable) ? " enable" : "enable";
915 for (i = 0; i < 31; i++)
916 if ( !(set_disable & (1<<i))) {
917 printf("%s %d", msg, i);
921 } else if (!strncmp(*av, "swap", strlen(*av))) {
924 errx(EX_USAGE, "set swap needs 2 set numbers\n");
925 rulenum = atoi(av[0]);
926 new_set = atoi(av[1]);
927 if (!isdigit(*(av[0])) || rulenum > 30)
928 errx(EX_DATAERR, "invalid set number %s\n", av[0]);
929 if (!isdigit(*(av[1])) || new_set > 30)
930 errx(EX_DATAERR, "invalid set number %s\n", av[1]);
931 masks[0] = (4 << 24) | (new_set << 16) | (rulenum);
932 i = do_set_x(IP_FW_DEL, masks, sizeof(u_int32_t));
933 } else if (!strncmp(*av, "move", strlen(*av))) {
935 if (ac && !strncmp(*av, "rule", strlen(*av))) {
940 if (ac != 3 || strncmp(av[1], "to", strlen(*av)))
941 errx(EX_USAGE, "syntax: set move [rule] X to Y\n");
942 rulenum = atoi(av[0]);
943 new_set = atoi(av[2]);
944 if (!isdigit(*(av[0])) || (cmd == 3 && rulenum > 30) ||
945 (cmd == 2 && rulenum == 65535) )
946 errx(EX_DATAERR, "invalid source number %s\n", av[0]);
947 if (!isdigit(*(av[2])) || new_set > 30)
948 errx(EX_DATAERR, "invalid dest. set %s\n", av[1]);
949 masks[0] = (cmd << 24) | (new_set << 16) | (rulenum);
950 i = do_set_x(IP_FW_DEL, masks, sizeof(u_int32_t));
951 } else if (!strncmp(*av, "disable", strlen(*av)) ||
952 !strncmp(*av, "enable", strlen(*av)) ) {
953 int which = !strncmp(*av, "enable", strlen(*av)) ? 1 : 0;
956 masks[0] = masks[1] = 0;
962 errx(EX_DATAERR, "invalid set number %d\n", i);
963 masks[which] |= (1<<i);
964 } else if (!strncmp(*av, "disable", strlen(*av)))
966 else if (!strncmp(*av, "enable", strlen(*av)))
969 errx(EX_DATAERR, "invalid set command %s\n", *av);
972 if ( (masks[0] & masks[1]) != 0 )
973 errx(EX_DATAERR, "cannot enable and disable the same set\n");
974 i = do_set_x(IP_FW_DEL, masks, sizeof(masks));
976 warn("set enable/disable: setsockopt(IP_FW_DEL)");
978 errx(EX_USAGE, "invalid set command %s\n", *av);
982 add_state(int ac, char *av[])
984 struct ipfw_ioc_state ioc_state;
985 ioc_state.expiry = 0;
986 ioc_state.lifetime = 0;
988 if (strcmp(*av, "rulenum") == 0) {
990 ioc_state.rulenum = atoi(*av);
992 errx(EX_USAGE, "ipfw state add rule");
996 pe = getprotobyname(*av);
997 ioc_state.flow_id.proto = pe->p_proto;
1000 ioc_state.flow_id.src_ip = inet_addr(*av);
1003 ioc_state.flow_id.src_port = atoi(*av);
1006 ioc_state.flow_id.dst_ip = inet_addr(*av);
1009 ioc_state.flow_id.dst_port = atoi(*av);
1012 if (strcmp(*av, "live") == 0) {
1014 ioc_state.lifetime = atoi(*av);
1018 if (strcmp(*av, "expiry") == 0) {
1020 ioc_state.expiry = strtoul(*av, NULL, 10);
1021 printf("ioc_state.expiry=%d\n", ioc_state.expiry);
1024 if (do_set_x(IP_FW_STATE_ADD, &ioc_state, sizeof(struct ipfw_ioc_state)) < 0 ) {
1025 err(EX_UNAVAILABLE, "do_set_x(IP_FW_STATE_ADD)");
1028 printf("Flushed all states.\n");
1033 delete_state(int ac, char *av[])
1037 if (ac == 1 && isdigit(**av))
1038 rulenum = atoi(*av);
1039 if (do_set_x(IP_FW_STATE_DEL, &rulenum, sizeof(int)) < 0 )
1040 err(EX_UNAVAILABLE, "do_set_x(IP_FW_STATE_DEL)");
1042 printf("Flushed all states.\n");
1046 flush_state(int ac, char *av[])
1051 printf("Are you sure? [yn] ");
1054 c = toupper(getc(stdin));
1055 while (c != '\n' && getc(stdin) != '\n')
1057 return; /* and do not flush */
1058 } while (c != 'Y' && c != 'N');
1059 if (c == 'N') /* user said no */
1062 if (do_set_x(IP_FW_STATE_FLUSH, NULL, 0) < 0 )
1063 err(EX_UNAVAILABLE, "do_set_x(IP_FW_STATE_FLUSH)");
1065 printf("Flushed all states.\n");
1069 list(int ac, char *av[])
1071 struct ipfw_ioc_state *dynrules, *d;
1072 struct ipfw_ioc_rule *r;
1076 int bcwidth, n, nbytes, nstat, ndyn, pcwidth, width;
1077 int exitval = EX_OK, lac;
1078 char **lav, *endptr;
1084 /* get rules or pipes from kernel, resizing array as necessary */
1087 while (nbytes >= nalloc) {
1088 nalloc = nalloc * 2 ;
1090 if ((data = realloc(data, nbytes)) == NULL)
1091 err(EX_OSERR, "realloc");
1092 if (do_get_x(IP_FW_GET, data, &nbytes) < 0)
1093 err(EX_OSERR, "do_get_x(IP_FW_GET)");
1097 * Count static rules.
1100 nstat = r->static_count;
1103 * Count dynamic rules. This is easier as they have
1106 dynrules = (struct ipfw_ioc_state *)((void *)r + r->static_len);
1107 ndyn = (nbytes - r->static_len) / sizeof(*dynrules);
1109 /* if showing stats, figure out column widths ahead of time */
1110 bcwidth = pcwidth = 0;
1112 for (n = 0, r = data; n < nstat;
1113 n++, r = (void *)r + IOC_RULESIZE(r)) {
1114 /* packet counter */
1115 width = snprintf(NULL, 0, "%ju", (uintmax_t)r->pcnt);
1116 if (width > pcwidth)
1120 width = snprintf(NULL, 0, "%ju", (uintmax_t)r->bcnt);
1121 if (width > bcwidth)
1125 if (do_dynamic && ndyn) {
1126 for (n = 0, d = dynrules; n < ndyn; n++, d++) {
1127 width = snprintf(NULL, 0, "%ju", (uintmax_t)d->pcnt);
1128 if (width > pcwidth)
1131 width = snprintf(NULL, 0, "%ju", (uintmax_t)d->bcnt);
1132 if (width > bcwidth)
1137 /* if no rule numbers were specified, list all rules */
1139 if (do_dynamic != 2) {
1140 for (n = 0, r = data; n < nstat; n++,
1141 r = (void *)r + IOC_RULESIZE(r)) {
1142 show_rules(r, pcwidth, bcwidth);
1145 if (do_dynamic && ndyn) {
1146 if (do_dynamic != 2) {
1147 printf("## States (%d):\n", ndyn);
1149 for (n = 0, d = dynrules; n < ndyn; n++, d++)
1150 show_states(d, pcwidth, bcwidth);
1155 /* display specific rules requested on command line */
1157 if (do_dynamic != 2) {
1158 for (lac = ac, lav = av; lac != 0; lac--) {
1159 /* convert command line rule # */
1160 rnum = strtoul(*lav++, &endptr, 10);
1163 warnx("invalid rule number: %s", *(lav - 1));
1166 for (n = seen = 0, r = data; n < nstat;
1167 n++, r = (void *)r + IOC_RULESIZE(r) ) {
1168 if (r->rulenum > rnum)
1170 if (r->rulenum == rnum) {
1171 show_rules(r, pcwidth, bcwidth);
1176 /* give precedence to other error(s) */
1177 if (exitval == EX_OK)
1178 exitval = EX_UNAVAILABLE;
1179 warnx("rule %lu does not exist", rnum);
1184 if (do_dynamic && ndyn) {
1185 if (do_dynamic != 2) {
1186 printf("## States (%d):\n", ndyn);
1188 for (lac = ac, lav = av; lac != 0; lac--) {
1189 rnum = strtoul(*lav++, &endptr, 10);
1191 /* already warned */
1193 for (n = 0, d = dynrules; n < ndyn; n++, d++) {
1194 if (d->rulenum > rnum)
1196 if (d->rulenum == rnum)
1197 show_states(d, pcwidth, bcwidth);
1207 if (exitval != EX_OK)
1212 show_dummynet(int ac, char *av[])
1216 int nalloc = 1024; /* start somewhere... */
1221 while (nbytes >= nalloc) {
1222 nalloc = nalloc * 2 + 200;
1224 if ((data = realloc(data, nbytes)) == NULL)
1225 err(EX_OSERR, "realloc");
1226 if (do_get_x(IP_DUMMYNET_GET, data, &nbytes) < 0) {
1227 err(EX_OSERR, "do_get_x(IP_%s_GET)",
1228 do_pipe ? "DUMMYNET" : "FW");
1232 show_pipes(data, nbytes, ac, av);
1239 fprintf(stderr, "usage: ipfw [options]\n"
1240 " ipfw add [rulenum] [set id] action filters\n"
1241 " ipfw delete [rulenum]\n"
1243 " ipfw list [rulenum]\n"
1244 " ipfw show [rulenum]\n"
1245 " ipfw zero [rulenum]\n"
1246 " ipfw set [show|enable|disable]\n"
1248 " ipfw [enable|disable]\n"
1249 " ipfw log [reset|off|on]\n"
1250 " ipfw nat [config|show|delete]\n"
1251 " ipfw pipe [config|show|delete]\n"
1252 " ipfw state [add|delete|list|show]"
1253 "\nsee ipfw manpage for details\n");
1258 delete_nat_config(int ac, char *av[])
1265 if (do_set_x(IP_FW_NAT_DEL, &i, sizeof(i)) == -1)
1266 errx(EX_USAGE, "NAT %d in use or not exists", i);
1270 delete_rules(int ac, char *av[])
1272 struct dn_ioc_pipe pipe;
1274 int exitval = EX_OK;
1278 memset(&pipe, 0, sizeof pipe);
1281 if (ac > 0 && !strncmp(*av, "set", strlen(*av))) {
1282 do_set = 1; /* delete set */
1287 while (ac && isdigit(**av)) {
1296 i = do_set_x(IP_DUMMYNET_DEL, &pipe, sizeof pipe);
1299 warn("rule %u: setsockopt(IP_DUMMYNET_DEL)",
1300 do_pipe == 1 ? pipe.pipe_nr : pipe.fs.fs_nr);
1303 rulenum = (i & 0xffff) | (do_set << 24);
1304 i = do_set_x(IP_FW_DEL, &rulenum, sizeof rulenum);
1306 exitval = EX_UNAVAILABLE;
1307 warn("rule %u: setsockopt(IP_FW_DEL)",
1312 if (exitval != EX_OK)
1317 static unsigned long
1318 getbw(const char *str, u_short *flags, int kb)
1324 val = strtoul(str, &end, 0);
1325 if (*end == 'k' || *end == 'K') {
1328 } else if (*end == 'm' || *end == 'M') {
1334 * Deal with bits or bytes or b(bits) or B(bytes). If there is no
1335 * trailer assume bits.
1337 if (strncasecmp(end, "bit", 3) == 0) {
1339 } else if (strncasecmp(end, "byte", 4) == 0) {
1341 } else if (*end == 'b') {
1343 } else if (*end == 'B') {
1348 * Return in bits if flags is NULL, else flag bits
1349 * or bytes in flags and return the unconverted value.
1351 if (inbytes && flags)
1352 *flags |= DN_QSIZE_IS_BYTES;
1353 else if (inbytes && flags == NULL)
1360 * config dummynet pipe/queue
1363 config_dummynet(int ac, char **av)
1365 struct dn_ioc_pipe pipe;
1372 memset(&pipe, 0, sizeof pipe);
1374 if (ac && isdigit(**av)) {
1386 int tok = match_token(dummynet_params, *av);
1391 pipe.fs.flags_fs |= DN_NOERROR;
1395 NEED1("plr needs argument 0..1\n");
1396 d = strtod(av[0], NULL);
1401 pipe.fs.plr = (int)(d*0x7fffffff);
1406 NEED1("queue needs queue size\n");
1408 pipe.fs.qsize = getbw(av[0], &pipe.fs.flags_fs, 1024);
1413 NEED1("buckets needs argument\n");
1414 pipe.fs.rq_size = strtoul(av[0], NULL, 0);
1419 NEED1("mask needs mask specifier\n");
1421 * per-flow queue, mask is dst_ip, dst_port,
1422 * src_ip, src_port, proto measured in bits
1426 pipe.fs.flow_mask.type = ETHERTYPE_IP;
1427 pipe.fs.flow_mask.u.ip.dst_ip = 0;
1428 pipe.fs.flow_mask.u.ip.src_ip = 0;
1429 pipe.fs.flow_mask.u.ip.dst_port = 0;
1430 pipe.fs.flow_mask.u.ip.src_port = 0;
1431 pipe.fs.flow_mask.u.ip.proto = 0;
1435 u_int32_t *p32 = NULL;
1436 u_int16_t *p16 = NULL;
1438 tok = match_token(dummynet_params, *av);
1443 * special case, all bits significant
1445 pipe.fs.flow_mask.u.ip.dst_ip = ~0;
1446 pipe.fs.flow_mask.u.ip.src_ip = ~0;
1447 pipe.fs.flow_mask.u.ip.dst_port = ~0;
1448 pipe.fs.flow_mask.u.ip.src_port = ~0;
1449 pipe.fs.flow_mask.u.ip.proto = ~0;
1450 pipe.fs.flags_fs |= DN_HAVE_FLOW_MASK;
1454 p32 = &pipe.fs.flow_mask.u.ip.dst_ip;
1458 p32 = &pipe.fs.flow_mask.u.ip.src_ip;
1462 p16 = &pipe.fs.flow_mask.u.ip.dst_port;
1466 p16 = &pipe.fs.flow_mask.u.ip.src_port;
1477 errx(EX_USAGE, "mask: value missing");
1478 if (*av[0] == '/') {
1479 a = strtoul(av[0]+1, &end, 0);
1480 a = (a == 32) ? ~0 : (1 << a) - 1;
1482 a = strtoul(av[0], &end, 0);
1485 else if (p16 != NULL) {
1488 "mask: must be 16 bit");
1489 *p16 = (u_int16_t)a;
1493 "mask: must be 8 bit");
1494 pipe.fs.flow_mask.u.ip.proto = (uint8_t)a;
1497 pipe.fs.flags_fs |= DN_HAVE_FLOW_MASK;
1499 } /* end while, config masks */
1506 NEED1("red/gred needs w_q/min_th/max_th/max_p\n");
1507 pipe.fs.flags_fs |= DN_IS_RED;
1508 if (tok == TOK_GRED)
1509 pipe.fs.flags_fs |= DN_IS_GENTLE_RED;
1511 * the format for parameters is w_q/min_th/max_th/max_p
1513 if ((end = strsep(&av[0], "/"))) {
1514 double w_q = strtod(end, NULL);
1515 if (w_q > 1 || w_q <= 0)
1516 errx(EX_DATAERR, "0 < w_q <= 1");
1517 pipe.fs.w_q = (int) (w_q * (1 << SCALE_RED));
1519 if ((end = strsep(&av[0], "/"))) {
1520 pipe.fs.min_th = strtoul(end, &end, 0);
1521 if (*end == 'K' || *end == 'k')
1522 pipe.fs.min_th *= 1024;
1524 if ((end = strsep(&av[0], "/"))) {
1525 pipe.fs.max_th = strtoul(end, &end, 0);
1526 if (*end == 'K' || *end == 'k')
1527 pipe.fs.max_th *= 1024;
1529 if ((end = strsep(&av[0], "/"))) {
1530 double max_p = strtod(end, NULL);
1531 if (max_p > 1 || max_p <= 0)
1532 errx(EX_DATAERR, "0 < max_p <= 1");
1533 pipe.fs.max_p = (int)(max_p * (1 << SCALE_RED));
1539 pipe.fs.flags_fs &= ~(DN_IS_RED|DN_IS_GENTLE_RED);
1543 NEED1("bw needs bandwidth\n");
1545 errx(EX_DATAERR, "bandwidth only valid for pipes");
1547 * set bandwidth value
1549 pipe.bandwidth = getbw(av[0], NULL, 1000);
1550 if (pipe.bandwidth < 0)
1551 errx(EX_DATAERR, "bandwidth too large");
1557 errx(EX_DATAERR, "delay only valid for pipes");
1558 NEED1("delay needs argument 0..10000ms\n");
1559 pipe.delay = strtoul(av[0], NULL, 0);
1565 errx(EX_DATAERR, "weight only valid for queues");
1566 NEED1("weight needs argument 0..100\n");
1567 pipe.fs.weight = strtoul(av[0], &end, 0);
1573 errx(EX_DATAERR, "pipe only valid for queues");
1574 NEED1("pipe needs pipe_number\n");
1575 pipe.fs.parent_nr = strtoul(av[0], &end, 0);
1580 errx(EX_DATAERR, "unrecognised option ``%s''", *av);
1584 if (pipe.pipe_nr == 0)
1585 errx(EX_DATAERR, "pipe_nr must be > 0");
1586 if (pipe.delay > 10000)
1587 errx(EX_DATAERR, "delay must be < 10000");
1588 } else { /* do_pipe == 2, queue */
1589 if (pipe.fs.parent_nr == 0)
1590 errx(EX_DATAERR, "pipe must be > 0");
1591 if (pipe.fs.weight >100)
1592 errx(EX_DATAERR, "weight must be <= 100");
1594 if (pipe.fs.flags_fs & DN_QSIZE_IS_BYTES) {
1595 if (pipe.fs.qsize > 1024*1024)
1596 errx(EX_DATAERR, "queue size must be < 1MB");
1598 if (pipe.fs.qsize > 100)
1599 errx(EX_DATAERR, "2 <= queue size <= 100");
1601 if (pipe.fs.flags_fs & DN_IS_RED) {
1603 int lookup_depth, avg_pkt_size;
1604 double s, idle, weight, w_q;
1608 if (pipe.fs.min_th >= pipe.fs.max_th)
1609 errx(EX_DATAERR, "min_th %d must be < than max_th %d",
1610 pipe.fs.min_th, pipe.fs.max_th);
1611 if (pipe.fs.max_th == 0)
1612 errx(EX_DATAERR, "max_th must be > 0");
1615 if (sysctlbyname("net.inet.ip.dummynet.red_lookup_depth",
1616 &lookup_depth, &len, NULL, 0) == -1)
1618 errx(1, "sysctlbyname(\"%s\")",
1619 "net.inet.ip.dummynet.red_lookup_depth");
1620 if (lookup_depth == 0)
1621 errx(EX_DATAERR, "net.inet.ip.dummynet.red_lookup_depth"
1622 " must be greater than zero");
1625 if (sysctlbyname("net.inet.ip.dummynet.red_avg_pkt_size",
1626 &avg_pkt_size, &len, NULL, 0) == -1)
1628 errx(1, "sysctlbyname(\"%s\")",
1629 "net.inet.ip.dummynet.red_avg_pkt_size");
1630 if (avg_pkt_size == 0)
1632 "net.inet.ip.dummynet.red_avg_pkt_size must"
1633 " be greater than zero");
1635 len = sizeof(clock_hz);
1636 if (sysctlbyname("net.inet.ip.dummynet.hz", &clock_hz, &len,
1638 errx(1, "sysctlbyname(\"%s\")",
1639 "net.inet.ip.dummynet.hz");
1643 * Ticks needed for sending a medium-sized packet.
1644 * Unfortunately, when we are configuring a WF2Q+ queue, we
1645 * do not have bandwidth information, because that is stored
1646 * in the parent pipe, and also we have multiple queues
1647 * competing for it. So we set s=0, which is not very
1648 * correct. But on the other hand, why do we want RED with
1651 if (pipe.bandwidth == 0) /* this is a WF2Q+ queue */
1654 s = clock_hz * avg_pkt_size * 8 / pipe.bandwidth;
1657 * max idle time (in ticks) before avg queue size becomes 0.
1658 * NOTA: (3/w_q) is approx the value x so that
1659 * (1-w_q)^x < 10^-3.
1661 w_q = ((double)pipe.fs.w_q) / (1 << SCALE_RED);
1662 idle = s * 3. / w_q;
1663 pipe.fs.lookup_step = (int)idle / lookup_depth;
1664 if (!pipe.fs.lookup_step)
1665 pipe.fs.lookup_step = 1;
1667 for (t = pipe.fs.lookup_step; t > 0; --t)
1669 pipe.fs.lookup_weight = (int)(weight * (1 << SCALE_RED));
1671 i = do_set_x(IP_DUMMYNET_CONFIGURE, &pipe, sizeof pipe);
1673 err(1, "do_set_x(%s)", "IP_DUMMYNET_CONFIGURE");
1677 * helper function, updates the pointer to cmd with the length
1678 * of the current command, and also cleans up the first word of
1679 * the new command in case it has been clobbered before.
1682 next_cmd(ipfw_insn *cmd)
1685 bzero(cmd, sizeof(*cmd));
1690 * Parse arguments and assemble the microinstructions which make up a rule.
1691 * Rules are added into the 'rulebuf' and then copied in the correct order
1692 * into the actual rule.
1697 add(int ac, char *av[])
1700 * rules are added into the 'rulebuf' and then copied in
1701 * the correct order into the actual rule.
1702 * Some things that need to go out of order (prob, action etc.)
1705 static uint32_t rulebuf[IPFW_RULE_SIZE_MAX];
1706 static uint32_t actbuf[IPFW_RULE_SIZE_MAX];
1707 static uint32_t othbuf[IPFW_RULE_SIZE_MAX];
1708 static uint32_t cmdbuf[IPFW_RULE_SIZE_MAX];
1710 ipfw_insn *src, *dst, *cmd, *action, *other;
1713 ipfw_insn *the_comment = NULL;
1714 struct ipfw_ioc_rule *rule;
1715 struct ipfw_keyword *key;
1716 struct ipfw_mapping *map;
1720 bzero(actbuf, sizeof(actbuf)); /* actions go here */
1721 bzero(othbuf, sizeof(actbuf)); /* others */
1722 bzero(cmdbuf, sizeof(cmdbuf)); /* filters */
1723 bzero(rulebuf, sizeof(rulebuf));
1725 rule = (struct ipfw_ioc_rule *)rulebuf;
1726 cmd = (ipfw_insn *)cmdbuf;
1727 action = (ipfw_insn *)actbuf;
1728 other = (ipfw_insn *)othbuf;
1730 NEED2("need more parameters");
1733 /* [rule N] -- Rule number optional */
1734 if (ac && isdigit(**av)) {
1735 rule->rulenum = atoi(*av);
1739 /* [set N] -- set number (0..30), optional */
1740 if (ac > 1 && !strncmp(*av, "set", strlen(*av))) {
1741 int set = strtoul(av[1], NULL, 10);
1742 if (set < 0 || set > 30)
1743 errx(EX_DATAERR, "illegal set %s", av[1]);
1752 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) {
1753 if (key->type == IPFW_KEYWORD_TYPE_OTHERS &&
1754 strcmp(key->word, *av) == 0) {
1755 for (j = 0, map = mappings;
1756 j < MAPPING_SIZE; j++, map++) {
1757 if (map->type == IPFW_MAPPING_TYPE_IN_USE &&
1758 map->module == key->module &&
1759 map->opcode == key->opcode ) {
1761 (*fn)(&other, &ac, &av);
1768 if (i >= KEYWORD_SIZE) {
1770 } else if (F_LEN(other) > 0) {
1771 if (other->module == MODULE_BASIC_ID &&
1772 other->opcode == O_BASIC_CHECK_STATE) {
1773 other = next_cmd(other);
1776 other = next_cmd(other);
1783 * only accept 1 action
1785 NEED1("missing action");
1786 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) {
1787 if (ac > 0 && key->type == IPFW_KEYWORD_TYPE_ACTION &&
1788 strcmp(key->word, *av) == 0) {
1789 for (j = 0, map = mappings; j<MAPPING_SIZE; j++, map++) {
1790 if (map->type == IPFW_MAPPING_TYPE_IN_USE &&
1791 map->module == key->module &&
1792 map->opcode == key->opcode) {
1794 (*fn)(&action, &ac, &av);
1801 if (F_LEN(action) > 0)
1802 action = next_cmd(action);
1807 if (strcmp(*av, "proto") == 0){
1811 NEED1("missing protocol");
1812 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) {
1813 if (key->type == IPFW_KEYWORD_TYPE_FILTER &&
1814 strcmp(key->word, "proto") == 0) {
1815 for (j = 0, map = mappings; j<MAPPING_SIZE; j++, map++) {
1816 if (map->type == IPFW_MAPPING_TYPE_IN_USE &&
1817 map->module == key->module &&
1818 map->opcode == key->opcode ) {
1820 (*fn)(&cmd, &ac, &av);
1828 cmd = next_cmd(cmd);
1834 char *s, *cur; /* current filter */
1835 ipfw_insn_u32 *cmd32; /* alias for cmd */
1838 cmd32 = (ipfw_insn_u32 *)cmd;
1839 if (strcmp(*av, "or") == 0) {
1841 errx(EX_USAGE, "'or' should"
1842 "between two filters\n");
1847 if (strcmp(*av, "not") == 0) {
1848 if (cmd->len & F_NOT)
1849 errx(EX_USAGE, "double \"not\" not allowed\n");
1855 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) {
1856 if (key->type == IPFW_KEYWORD_TYPE_FILTER &&
1857 strcmp(key->word, cur) == 0) {
1858 for (j = 0, map = mappings;
1859 j< MAPPING_SIZE; j++, map++) {
1860 if (map->type == IPFW_MAPPING_TYPE_IN_USE &&
1861 map->module == key->module &&
1862 map->opcode == key->opcode ) {
1864 (*fn)(&cmd, &ac, &av);
1869 } else if (i == KEYWORD_SIZE-1) {
1870 errx(EX_USAGE, "bad command `%s'", cur);
1873 if (i >= KEYWORD_SIZE) {
1875 } else if (F_LEN(cmd) > 0) {
1878 cmd = next_cmd(cmd);
1884 errx(EX_USAGE, "bad command `%s'", *av);
1887 * Now copy stuff into the rule.
1888 * [filters][others][action][comment]
1890 dst = (ipfw_insn *)rule->cmd;
1892 * copy all filters, except comment
1894 src = (ipfw_insn *)cmdbuf;
1895 for (src = (ipfw_insn *)cmdbuf; src != cmd; src += i) {
1896 /* pick comment out */
1898 if (src->module == MODULE_BASIC_ID && src->opcode == O_BASIC_COMMENT) {
1901 bcopy(src, dst, i * sizeof(u_int32_t));
1902 dst = (ipfw_insn *)((uint32_t *)dst + i);
1907 * start action section, it begin with others
1909 rule->act_ofs = (uint32_t *)dst - (uint32_t *)(rule->cmd);
1912 * copy all other others
1914 for (src = (ipfw_insn *)othbuf; src != other; src += i) {
1916 bcopy(src, dst, i * sizeof(u_int32_t));
1917 dst = (ipfw_insn *)((uint32_t *)dst + i);
1920 /* copy the action to the end of rule */
1921 src = (ipfw_insn *)actbuf;
1923 bcopy(src, dst, i * sizeof(u_int32_t));
1924 dst = (ipfw_insn *)((uint32_t *)dst + i);
1927 * comment place behind the action
1929 if (the_comment != NULL) {
1930 i = F_LEN(the_comment);
1931 bcopy(the_comment, dst, i * sizeof(u_int32_t));
1932 dst = (ipfw_insn *)((uint32_t *)dst + i);
1935 rule->cmd_len = (u_int32_t *)dst - (u_int32_t *)(rule->cmd);
1936 i = (void *)dst - (void *)rule;
1937 if (do_set_x(IP_FW_ADD, (void *)rule, i) == -1) {
1938 err(EX_UNAVAILABLE, "getsockopt(%s)", "IP_FW_ADD");
1941 show_rules(rule, 10, 10);
1945 zero(int ac, char *av[])
1953 /* clear all entries */
1954 if (do_set_x(IP_FW_ZERO, NULL, 0) < 0)
1955 err(EX_UNAVAILABLE, "do_set_x(IP_FW_ZERO)");
1957 printf("Accounting cleared.\n");
1963 if (isdigit(**av)) {
1964 rulenum = atoi(*av);
1966 if (do_set_x(IP_FW_ZERO, &rulenum, sizeof rulenum)) {
1967 warn("rule %u: do_set_x(IP_FW_ZERO)", rulenum);
1968 failed = EX_UNAVAILABLE;
1969 } else if (!do_quiet)
1970 printf("Entry %d cleared\n", rulenum);
1972 errx(EX_USAGE, "invalid rule number ``%s''", *av);
1975 if (failed != EX_OK)
1980 resetlog(int ac, char *av[])
1988 /* clear all entries */
1989 if (setsockopt(ipfw_socket, IPPROTO_IP, IP_FW_RESETLOG, NULL, 0) < 0)
1990 err(EX_UNAVAILABLE, "setsockopt(IP_FW_RESETLOG)");
1992 printf("Logging counts reset.\n");
1999 if (isdigit(**av)) {
2000 rulenum = atoi(*av);
2002 if (setsockopt(ipfw_socket, IPPROTO_IP,
2003 IP_FW_RESETLOG, &rulenum, sizeof rulenum)) {
2004 warn("rule %u: setsockopt(IP_FW_RESETLOG)", rulenum);
2005 failed = EX_UNAVAILABLE;
2006 } else if (!do_quiet)
2007 printf("Entry %d logging count reset\n", rulenum);
2009 errx(EX_DATAERR, "invalid rule number ``%s''", *av);
2012 if (failed != EX_OK)
2019 int cmd = IP_FW_FLUSH;
2021 cmd = IP_DUMMYNET_FLUSH;
2022 } else if (do_nat) {
2023 cmd = IP_FW_NAT_FLUSH;
2028 printf("Are you sure? [yn] ");
2031 c = toupper(getc(stdin));
2032 while (c != '\n' && getc(stdin) != '\n')
2034 return; /* and do not flush */
2035 } while (c != 'Y' && c != 'N');
2036 if (c == 'N') /* user said no */
2039 if (do_set_x(cmd, NULL, 0) < 0 ) {
2041 errx(EX_USAGE, "pipe/queue in use");
2043 errx(EX_USAGE, "NAT configuration in use");
2045 errx(EX_USAGE, "do_set_x(IP_FWFLUSH) failed");
2048 printf("Flushed all %s.\n", do_pipe ? "pipes":
2049 (do_nat?"nat configurations":"rules"));
2054 str2addr(const char* str, struct in_addr* addr)
2058 if (inet_aton (str, addr))
2061 hp = gethostbyname (str);
2063 errx (1, "unknown host %s", str);
2065 memcpy (addr, hp->h_addr, sizeof (struct in_addr));
2069 str2portrange(const char* str, const char* proto, port_range *portRange)
2074 u_short loPort, hiPort;
2076 /* First see if this is a service, return corresponding port if so. */
2077 sp = getservbyname (str, proto);
2079 SETLOPORT(*portRange, ntohs(sp->s_port));
2080 SETNUMPORTS(*portRange, 1);
2084 /* Not a service, see if it's a single port or port range. */
2085 sep = strchr (str, '-');
2087 SETLOPORT(*portRange, strtol(str, &end, 10));
2090 SETNUMPORTS(*portRange, 1);
2094 /* Error in port range field. */
2095 errx (EX_DATAERR, "%s/%s: unknown service", str, proto);
2098 /* Port range, get the values and sanity check. */
2099 sscanf (str, "%hu-%hu", &loPort, &hiPort);
2100 SETLOPORT(*portRange, loPort);
2101 SETNUMPORTS(*portRange, 0); /* Error by default */
2102 if (loPort <= hiPort)
2103 SETNUMPORTS(*portRange, hiPort - loPort + 1);
2105 if (GETNUMPORTS(*portRange) == 0)
2106 errx (EX_DATAERR, "invalid port range %s", str);
2112 str2proto(const char* str)
2114 if (!strcmp (str, "tcp"))
2116 if (!strcmp (str, "udp"))
2118 errx (EX_DATAERR, "unknown protocol %s. Expected tcp or udp", str);
2122 str2addr_portrange (const char* str, struct in_addr* addr,
2123 char* proto, port_range *portRange)
2127 ptr = strchr (str, ':');
2129 errx (EX_DATAERR, "%s is missing port number", str);
2134 str2addr (str, addr);
2135 return str2portrange (ptr, proto, portRange);
2139 * Search for interface with name "ifn", and fill n accordingly:
2141 * n->ip ip address of interface "ifn"
2142 * n->if_name copy of interface name "ifn"
2145 set_addr_dynamic(const char *ifn, struct cfg_nat *n)
2147 struct if_msghdr *ifm;
2148 struct ifa_msghdr *ifam;
2149 struct sockaddr_dl *sdl;
2150 struct sockaddr_in *sin;
2151 char *buf, *lim, *next;
2160 mib[4] = NET_RT_IFLIST;
2164 * Get interface data.
2166 if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1)
2167 err(1, "iflist-sysctl-estimate");
2168 if ((buf = malloc(needed)) == NULL)
2169 errx(1, "malloc failed");
2170 if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1)
2171 err(1, "iflist-sysctl-get");
2174 * Loop through interfaces until one with
2175 * given name is found. This is done to
2176 * find correct interface index for routing
2177 * message processing.
2181 while (next < lim) {
2182 ifm = (struct if_msghdr *)next;
2183 next += ifm->ifm_msglen;
2184 if (ifm->ifm_version != RTM_VERSION) {
2186 warnx("routing message version %d "
2187 "not understood", ifm->ifm_version);
2190 if (ifm->ifm_type == RTM_IFINFO) {
2191 sdl = (struct sockaddr_dl *)(ifm + 1);
2192 if (strlen(ifn) == sdl->sdl_nlen &&
2193 strncmp(ifn, sdl->sdl_data, sdl->sdl_nlen) == 0) {
2194 ifIndex = ifm->ifm_index;
2195 ifMTU = ifm->ifm_data.ifi_mtu;
2201 errx(1, "unknown interface name %s", ifn);
2203 * Get interface address.
2206 while (next < lim) {
2207 ifam = (struct ifa_msghdr *)next;
2208 next += ifam->ifam_msglen;
2209 if (ifam->ifam_version != RTM_VERSION) {
2211 warnx("routing message version %d "
2212 "not understood", ifam->ifam_version);
2215 if (ifam->ifam_type != RTM_NEWADDR)
2217 if (ifam->ifam_addrs & RTA_IFA) {
2219 char *cp = (char *)(ifam + 1);
2221 for (i = 1; i < RTA_IFA; i <<= 1) {
2222 if (ifam->ifam_addrs & i)
2223 cp += SA_SIZE((struct sockaddr *)cp);
2225 if (((struct sockaddr *)cp)->sa_family == AF_INET) {
2226 sin = (struct sockaddr_in *)cp;
2232 errx(1, "%s: cannot get interface address", ifn);
2234 n->ip = sin->sin_addr;
2235 strncpy(n->if_name, ifn, IF_NAMESIZE);
2241 setup_redir_addr(char *spool_buf, int len, int *_ac, char ***_av)
2243 struct cfg_redir *r;
2244 struct cfg_spool *tmp;
2246 char tmp_spool_buf[NAT_BUF_LEN];
2247 int ac, i, space, lsnat;
2254 if (len >= SOF_REDIR) {
2255 r = (struct cfg_redir *)spool_buf;
2256 /* Skip cfg_redir at beginning of buf. */
2257 spool_buf = &spool_buf[SOF_REDIR];
2264 r->mode = REDIR_ADDR;
2265 /* Extract local address. */
2267 errx(EX_DATAERR, "redirect_addr: missing local address");
2269 sep = strchr(*av, ',');
2270 if (sep) { /* LSNAT redirection syntax. */
2271 r->laddr.s_addr = INADDR_NONE;
2272 /* Preserve av, copy spool servers to tmp_spool_buf. */
2273 strncpy(tmp_spool_buf, *av, strlen(*av)+1);
2276 str2addr(*av, &r->laddr);
2280 /* Extract public address. */
2282 errx(EX_DATAERR, "redirect_addr: missing public address");
2284 str2addr(*av, &r->paddr);
2287 /* Setup LSNAT server pool. */
2289 sep = strtok(tmp_spool_buf, ", ");
2290 while (sep != NULL) {
2291 tmp = (struct cfg_spool *)spool_buf;
2292 if (len < SOF_SPOOL)
2297 str2addr(sep, &tmp->addr);
2300 /* Point to the next possible cfg_spool. */
2301 spool_buf = &spool_buf[SOF_SPOOL];
2302 sep = strtok(NULL, ", ");
2308 errx(EX_DATAERR, "redirect_addr: buf is too small\n");
2312 setup_redir_port(char *spool_buf, int len, int *_ac, char ***_av)
2314 char **av, *sep, *protoName;
2315 char tmp_spool_buf[NAT_BUF_LEN];
2316 int ac, space, lsnat;
2317 struct cfg_redir *r;
2318 struct cfg_spool *tmp;
2319 u_short numLocalPorts;
2320 port_range portRange;
2328 if (len >= SOF_REDIR) {
2329 r = (struct cfg_redir *)spool_buf;
2330 /* Skip cfg_redir at beginning of buf. */
2331 spool_buf = &spool_buf[SOF_REDIR];
2338 r->mode = REDIR_PORT;
2343 errx (EX_DATAERR, "redirect_port: missing protocol");
2345 r->proto = str2proto(*av);
2350 * Extract local address.
2353 errx (EX_DATAERR, "redirect_port: missing local address");
2355 sep = strchr(*av, ',');
2356 /* LSNAT redirection syntax. */
2358 r->laddr.s_addr = INADDR_NONE;
2361 /* Preserve av, copy spool servers to tmp_spool_buf. */
2362 strncpy(tmp_spool_buf, *av, strlen(*av)+1);
2365 if (str2addr_portrange (*av, &r->laddr, protoName, &portRange) != 0)
2366 errx(EX_DATAERR, "redirect_port:"
2367 "invalid local port range");
2369 r->lport = GETLOPORT(portRange);
2370 numLocalPorts = GETNUMPORTS(portRange);
2375 * Extract public port and optionally address.
2378 errx (EX_DATAERR, "redirect_port: missing public port");
2380 sep = strchr (*av, ':');
2382 if (str2addr_portrange (*av, &r->paddr, protoName, &portRange) != 0)
2383 errx(EX_DATAERR, "redirect_port:"
2384 "invalid public port range");
2386 r->paddr.s_addr = INADDR_ANY;
2387 if (str2portrange(*av, protoName, &portRange) != 0)
2388 errx(EX_DATAERR, "redirect_port:"
2389 "invalid public port range");
2392 r->pport = GETLOPORT(portRange);
2393 r->pport_cnt = GETNUMPORTS(portRange);
2397 * Extract remote address and optionally port.
2400 * NB: isalpha(**av) => we've to check that next parameter is really an
2401 * option for this redirect entry, else stop here processing arg[cv].
2403 if (ac != 0 && !isalpha(**av)) {
2404 sep = strchr (*av, ':');
2406 if (str2addr_portrange (*av, &r->raddr,
2407 protoName, &portRange) != 0)
2408 errx(EX_DATAERR, "redirect_port:"
2409 "invalid remote port range");
2411 SETLOPORT(portRange, 0);
2412 SETNUMPORTS(portRange, 1);
2413 str2addr (*av, &r->raddr);
2417 SETLOPORT(portRange, 0);
2418 SETNUMPORTS(portRange, 1);
2419 r->raddr.s_addr = INADDR_ANY;
2421 r->rport = GETLOPORT(portRange);
2422 r->rport_cnt = GETNUMPORTS(portRange);
2425 * Make sure port ranges match up, then add the redirect ports.
2427 if (numLocalPorts != r->pport_cnt)
2428 errx(EX_DATAERR, "redirect_port:"
2429 "port ranges must be equal in size");
2431 /* Remote port range is allowed to be '0' which means all ports. */
2432 if (r->rport_cnt != numLocalPorts &&
2433 (r->rport_cnt != 1 || r->rport != 0))
2434 errx(EX_DATAERR, "redirect_port: remote port must"
2435 "be 0 or equal to local port range in size");
2438 * Setup LSNAT server pool.
2441 sep = strtok(tmp_spool_buf, ", ");
2442 while (sep != NULL) {
2443 tmp = (struct cfg_spool *)spool_buf;
2444 if (len < SOF_SPOOL)
2449 if (str2addr_portrange(sep,
2450 &tmp->addr, protoName, &portRange) != 0)
2451 errx(EX_DATAERR, "redirect_port:"
2452 "invalid local port range");
2453 if (GETNUMPORTS(portRange) != 1)
2454 errx(EX_DATAERR, "redirect_port: local port"
2455 "must be single in this context");
2456 tmp->port = GETLOPORT(portRange);
2458 /* Point to the next possible cfg_spool. */
2459 spool_buf = &spool_buf[SOF_SPOOL];
2460 sep = strtok(NULL, ", ");
2466 errx(EX_DATAERR, "redirect_port: buf is too small\n");
2470 setup_redir_proto(char *spool_buf, int len, int *_ac, char ***_av)
2472 struct protoent *protoent;
2473 struct cfg_redir *r;
2480 if (len >= SOF_REDIR) {
2481 r = (struct cfg_redir *)spool_buf;
2482 /* Skip cfg_redir at beginning of buf. */
2483 spool_buf = &spool_buf[SOF_REDIR];
2489 r->mode = REDIR_PROTO;
2494 errx(EX_DATAERR, "redirect_proto: missing protocol");
2496 protoent = getprotobyname(*av);
2497 if (protoent == NULL)
2498 errx(EX_DATAERR, "redirect_proto: unknown protocol %s", *av);
2500 r->proto = protoent->p_proto;
2505 * Extract local address.
2508 errx(EX_DATAERR, "redirect_proto: missing local address");
2510 str2addr(*av, &r->laddr);
2514 * Extract optional public address.
2517 r->paddr.s_addr = INADDR_ANY;
2518 r->raddr.s_addr = INADDR_ANY;
2520 /* see above in setup_redir_port() */
2521 if (!isalpha(**av)) {
2522 str2addr(*av, &r->paddr);
2526 * Extract optional remote address.
2528 /* see above in setup_redir_port() */
2529 if (ac != 0 && !isalpha(**av)) {
2530 str2addr(*av, &r->raddr);
2538 errx(EX_DATAERR, "redirect_proto: buf is too small\n");
2542 show_nat_config(char *buf) {
2544 struct cfg_redir *t;
2545 struct cfg_spool *s;
2547 int i, cnt, flag, off;
2549 n = (struct cfg_nat *)buf;
2552 printf("ipfw nat %u config", n->id);
2553 if (strlen(n->if_name) != 0)
2554 printf(" if %s", n->if_name);
2555 else if (n->ip.s_addr != 0)
2556 printf(" ip %s", inet_ntoa(n->ip));
2557 while (n->mode != 0) {
2558 if (n->mode & PKT_ALIAS_LOG) {
2560 n->mode &= ~PKT_ALIAS_LOG;
2561 } else if (n->mode & PKT_ALIAS_DENY_INCOMING) {
2563 n->mode &= ~PKT_ALIAS_DENY_INCOMING;
2564 } else if (n->mode & PKT_ALIAS_SAME_PORTS) {
2565 printf(" same_ports");
2566 n->mode &= ~PKT_ALIAS_SAME_PORTS;
2567 } else if (n->mode & PKT_ALIAS_UNREGISTERED_ONLY) {
2568 printf(" unreg_only");
2569 n->mode &= ~PKT_ALIAS_UNREGISTERED_ONLY;
2570 } else if (n->mode & PKT_ALIAS_RESET_ON_ADDR_CHANGE) {
2572 n->mode &= ~PKT_ALIAS_RESET_ON_ADDR_CHANGE;
2573 } else if (n->mode & PKT_ALIAS_REVERSE) {
2575 n->mode &= ~PKT_ALIAS_REVERSE;
2576 } else if (n->mode & PKT_ALIAS_PROXY_ONLY) {
2577 printf(" proxy_only");
2578 n->mode &= ~PKT_ALIAS_PROXY_ONLY;
2581 /* Print all the redirect's data configuration. */
2582 for (cnt = 0; cnt < n->redir_cnt; cnt++) {
2583 t = (struct cfg_redir *)&buf[off];
2587 printf(" redirect_addr");
2588 if (t->spool_cnt == 0)
2589 printf(" %s", inet_ntoa(t->laddr));
2591 for (i = 0; i < t->spool_cnt; i++) {
2592 s = (struct cfg_spool *)&buf[off];
2597 printf("%s", inet_ntoa(s->addr));
2600 printf(" %s", inet_ntoa(t->paddr));
2603 p = getprotobynumber(t->proto);
2604 printf(" redirect_port %s ", p->p_name);
2605 if (!t->spool_cnt) {
2606 printf("%s:%u", inet_ntoa(t->laddr), t->lport);
2607 if (t->pport_cnt > 1)
2608 printf("-%u", t->lport + t->pport_cnt - 1);
2610 for (i=0; i < t->spool_cnt; i++) {
2611 s = (struct cfg_spool *)&buf[off];
2614 printf("%s:%u", inet_ntoa(s->addr), s->port);
2619 if (t->paddr.s_addr)
2620 printf("%s:", inet_ntoa(t->paddr));
2621 printf("%u", t->pport);
2622 if (!t->spool_cnt && t->pport_cnt > 1)
2623 printf("-%u", t->pport + t->pport_cnt - 1);
2625 if (t->raddr.s_addr) {
2626 printf(" %s", inet_ntoa(t->raddr));
2628 printf(":%u", t->rport);
2629 if (!t->spool_cnt && t->rport_cnt > 1)
2630 printf("-%u", t->rport +
2636 p = getprotobynumber(t->proto);
2637 printf(" redirect_proto %s %s", p->p_name,
2638 inet_ntoa(t->laddr));
2639 if (t->paddr.s_addr != 0) {
2640 printf(" %s", inet_ntoa(t->paddr));
2641 if (t->raddr.s_addr)
2642 printf(" %s", inet_ntoa(t->raddr));
2646 errx(EX_DATAERR, "unknown redir mode");
2655 show_nat(int ac, char **av) {
2657 struct cfg_redir *e;
2658 int i, nbytes, nalloc, size;
2659 int nat_cnt, redir_cnt, nat_id;
2671 nat_id = strtoul(*av, NULL, 10);
2674 while (nbytes >= nalloc) {
2675 nalloc = nalloc * 2;
2677 if ((data = realloc(data, nbytes)) == NULL) {
2678 err(EX_OSERR, "realloc");
2680 if (do_get_x(IP_FW_NAT_GET, data, &nbytes) < 0) {
2681 err(EX_OSERR, "do_get_x(IP_FW_NAT_GET)");
2689 nat_cnt = *((int *)data);
2690 for (i = sizeof(nat_cnt); nat_cnt; nat_cnt--) {
2691 n = (struct cfg_nat *)&data[i];
2692 if (n->id >= 0 && n->id <= IPFW_DEFAULT_RULE) {
2693 if (nat_id == 0 || n->id == nat_id)
2694 show_nat_config(&data[i]);
2696 i += sizeof(struct cfg_nat);
2697 for (redir_cnt = 0; redir_cnt < n->redir_cnt; redir_cnt++) {
2698 e = (struct cfg_redir *)&data[i];
2699 i += sizeof(struct cfg_redir) +
2700 e->spool_cnt * sizeof(struct cfg_spool);
2706 get_kern_boottime(void)
2708 struct timeval boottime;
2712 mib[1] = KERN_BOOTTIME;
2713 size = sizeof(boottime);
2714 if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 &&
2715 boottime.tv_sec != 0) {
2716 return boottime.tv_sec;
2722 show_nat_state(int ac, char **av)
2735 nat_id = strtoul(*av, NULL, 10);
2738 while (nbytes >= nalloc) {
2739 nalloc = nalloc * 2;
2741 if ((data = realloc(data, nbytes)) == NULL) {
2742 err(EX_OSERR, "realloc");
2744 memcpy(data, &nat_id, sizeof(int));
2745 if (do_get_x(IP_FW_NAT_LOG, data, &nbytes) < 0) {
2746 err(EX_OSERR, "do_get_x(IP_FW_NAT_GET_STATE)");
2751 struct ipfw_ioc_nat_state *nat_state;
2752 nat_state =(struct ipfw_ioc_nat_state *)data;
2753 int count = nbytes / sizeof( struct ipfw_ioc_nat_state);
2755 uptime_sec = get_kern_boottime();
2756 for (i = 0; i < count; i ++) {
2757 struct protoent *pe = getprotobynumber(nat_state->link_type);
2758 printf("%s ", pe->p_name);
2759 printf("%s:%hu => ",inet_ntoa(nat_state->src_addr),
2760 htons(nat_state->src_port));
2761 printf("%s:%hu",inet_ntoa(nat_state->alias_addr),
2762 htons(nat_state->alias_port));
2763 printf(" -> %s:%hu ",inet_ntoa(nat_state->dst_addr),
2764 htons(nat_state->dst_port));
2767 time_t t = _long_to_time(uptime_sec + nat_state->timestamp);
2768 strcpy(timestr, ctime(&t));
2769 *strchr(timestr, '\n') = '\0';
2770 printf("%s ", timestr);
2771 } else if (do_time == 2) {
2772 printf( "%10u ", uptime_sec + nat_state->timestamp);
2780 * do_set_x - extended version og do_set
2781 * insert a x_header in the beginning of the rule buf
2782 * and call setsockopt() with IP_FW_X.
2785 do_set_x(int optname, void *rule, int optlen)
2789 ip_fw_x_header *x_header;
2790 if (ipfw_socket < 0)
2791 err(EX_UNAVAILABLE, "socket not avaialble");
2792 len = optlen + sizeof(ip_fw_x_header);
2793 newbuf = malloc(len);
2795 err(EX_OSERR, "malloc newbuf in do_set_x");
2797 x_header = (ip_fw_x_header *)newbuf;
2798 x_header->opcode = optname;
2799 /* copy the rule into the newbuf, just after the x_header*/
2800 bcopy(rule, ++x_header, optlen);
2801 return setsockopt(ipfw_socket, IPPROTO_IP, IP_FW_X, newbuf, len);
2808 do_get_x(int optname, void *rule, int *optlen)
2810 int len, *newbuf, retval;
2812 ip_fw_x_header *x_header;
2813 if (ipfw_socket < 0)
2814 err(EX_UNAVAILABLE, "socket not avaialble");
2815 len = *optlen + sizeof(ip_fw_x_header);
2816 newbuf = malloc(len);
2818 err(EX_OSERR, "malloc newbuf in do_get_x");
2820 x_header = (ip_fw_x_header *)newbuf;
2821 x_header->opcode = optname;
2822 /* copy the rule into the newbuf, just after the x_header*/
2823 bcopy(rule, ++x_header, *optlen);
2824 retval = getsockopt(ipfw_socket, IPPROTO_IP, IP_FW_X, newbuf, &len);
2825 bcopy(newbuf, rule, len);
2831 config_nat(int ac, char **av)
2833 struct cfg_nat *n; /* Nat instance configuration. */
2834 int i, len, off, tok;
2835 char *id, buf[NAT_BUF_LEN]; /* Buffer for serialized data. */
2838 /* Offset in buf: save space for n at the beginning. */
2839 off = sizeof(struct cfg_nat);
2840 memset(buf, 0, sizeof(buf));
2841 n = (struct cfg_nat *)buf;
2845 if (ac && isdigit(**av)) {
2851 errx(EX_DATAERR, "missing nat id");
2853 errx(EX_DATAERR, "missing option");
2856 tok = match_token(nat_params, *av);
2861 errx(EX_DATAERR, "missing option");
2862 if (!inet_aton(av[0], &(n->ip)))
2863 errx(EX_DATAERR, "bad ip address ``%s''",
2869 errx(EX_DATAERR, "missing option");
2870 set_addr_dynamic(av[0], n);
2874 n->mode |= PKT_ALIAS_LOG;
2877 n->mode |= PKT_ALIAS_DENY_INCOMING;
2879 case TOK_SAME_PORTS:
2880 n->mode |= PKT_ALIAS_SAME_PORTS;
2882 case TOK_UNREG_ONLY:
2883 n->mode |= PKT_ALIAS_UNREGISTERED_ONLY;
2885 case TOK_RESET_ADDR:
2886 n->mode |= PKT_ALIAS_RESET_ON_ADDR_CHANGE;
2889 n->mode |= PKT_ALIAS_REVERSE;
2891 case TOK_PROXY_ONLY:
2892 n->mode |= PKT_ALIAS_PROXY_ONLY;
2895 * All the setup_redir_* functions work directly in the final
2896 * buffer, see above for details.
2898 case TOK_REDIR_ADDR:
2899 case TOK_REDIR_PORT:
2900 case TOK_REDIR_PROTO:
2902 case TOK_REDIR_ADDR:
2903 i = setup_redir_addr(&buf[off], len, &ac, &av);
2905 case TOK_REDIR_PORT:
2906 i = setup_redir_port(&buf[off], len, &ac, &av);
2908 case TOK_REDIR_PROTO:
2909 i = setup_redir_proto(&buf[off], len, &ac, &av);
2917 errx(EX_DATAERR, "unrecognised option ``%s''", av[-1]);
2920 i = do_set_x(IP_FW_NAT_CFG, buf, off);
2922 err(1, "do_set_x(%s)", "IP_FW_NAT_CFG");
2924 /* After every modification, we show the resultant rule. */
2926 char *_av[] = {"config", id};
2932 ipfw_main(int ac, char **av)
2939 /* Set the force flag for non-interactive processes */
2940 do_force = !isatty(STDIN_FILENO);
2942 optind = optreset = 1;
2943 while ((ch = getopt(ac, av, "hs:acdDefNStTv")) != -1)
2945 case 'h': /* help */
2947 break; /* NOTREACHED */
2949 case 's': /* sort */
2950 do_sort = atoi(optarg);
2992 NEED1("bad arguments, for usage summary ``ipfw''");
2995 * optional: pipe or queue or nat
2999 if (!strncmp(*av, "nat", strlen(*av)))
3001 else if (!strncmp(*av, "pipe", strlen(*av))) {
3003 } else if (!strncmp(*av, "queue", strlen(*av))) {
3006 NEED1("missing command");
3009 * for pipes and queues and nat we normally say 'pipe NN config'
3010 * but the code is easier to parse as 'pipe config NN'
3011 * so we swap the two arguments.
3013 if ((do_pipe || do_nat) && ac > 2 && isdigit(*(av[1]))) {
3019 if (!strncmp(*av, "add", strlen(*av))) {
3022 } else if (!strncmp(*av, "delete", strlen(*av))) {
3023 delete_rules(ac, av);
3024 } else if (!strncmp(*av, "flush", strlen(*av))) {
3026 } else if (!strncmp(*av, "list", strlen(*av))) {
3029 } else if (!strncmp(*av, "show", strlen(*av))) {
3033 } else if (!strncmp(*av, "zero", strlen(*av))) {
3035 } else if (!strncmp(*av, "set", strlen(*av))) {
3036 sets_handler(ac, av);
3037 } else if (!strncmp(*av, "module", strlen(*av))) {
3039 if (!strncmp(*av, "show", strlen(*av)) ||
3040 !strncmp(*av, "show", strlen(*av))) {
3041 list_modules(ac, av);
3043 errx(EX_USAGE, "bad ipfw module command `%s'", *av);
3045 } else if (!strncmp(*av, "resetlog", strlen(*av))) {
3047 } else if (!strncmp(*av, "log", strlen(*av))) {
3049 if (!strncmp(*av, "reset", strlen(*av))) {
3051 } else if (!strncmp(*av, "off", strlen(*av))) {
3053 } else if (!strncmp(*av, "on", strlen(*av))) {
3056 errx(EX_USAGE, "bad command `%s'", *av);
3058 } else if (!strncmp(*av, "nat", strlen(*av))) {
3060 if (!strncmp(*av, "config", strlen(*av))) {
3062 } else if (!strncmp(*av, "flush", strlen(*av))) {
3064 } else if (!strncmp(*av, "show", strlen(*av)) ||
3065 !strncmp(*av, "list", strlen(*av))) {
3066 if (ac > 2 && isdigit(*(av[1]))) {
3072 if (!strncmp(*av, "config", strlen(*av))) {
3074 } else if (!strncmp(*av, "state", strlen(*av))) {
3075 show_nat_state(ac,av);
3078 "bad nat show command `%s'", *av);
3080 } else if (!strncmp(*av, "delete", strlen(*av))) {
3081 delete_nat_config(ac, av);
3083 errx(EX_USAGE, "bad ipfw nat command `%s'", *av);
3085 } else if (!strncmp(*av, "pipe", strlen(*av)) ||
3086 !strncmp(*av, "queue", strlen(*av))) {
3088 if (!strncmp(*av, "config", strlen(*av))) {
3089 config_dummynet(ac, av);
3090 } else if (!strncmp(*av, "flush", strlen(*av))) {
3092 } else if (!strncmp(*av, "show", strlen(*av))) {
3093 show_dummynet(ac, av);
3095 errx(EX_USAGE, "bad ipfw pipe command `%s'", *av);
3097 } else if (!strncmp(*av, "state", strlen(*av))) {
3099 if (!strncmp(*av, "add", strlen(*av))) {
3101 } else if (!strncmp(*av, "delete", strlen(*av))) {
3102 delete_state(ac, av);
3103 } else if (!strncmp(*av, "flush", strlen(*av))) {
3104 flush_state(ac, av);
3105 } else if (!strncmp(*av, "list", strlen(*av))) {
3108 } else if (!strncmp(*av, "show", strlen(*av))) {
3113 errx(EX_USAGE, "bad ipfw state command `%s'", *av);
3116 errx(EX_USAGE, "bad ipfw command `%s'", *av);
3122 ipfw_readfile(int ac, char *av[])
3125 char *a, *p, *args[MAX_ARGS], *cmd = NULL;
3127 int i=0, lineno=0, qflag=0, pflag=0, status;
3132 while ((c = getopt(ac, av, "D:U:p:q")) != -1) {
3136 errx(EX_USAGE, "-D requires -p");
3137 if (i > MAX_ARGS - 2)
3138 errx(EX_USAGE, "too many -D or -U options");
3145 errx(EX_USAGE, "-U requires -p");
3146 if (i > MAX_ARGS - 2)
3147 errx(EX_USAGE, "too many -D or -U options");
3164 errx(EX_USAGE, "bad arguments, for usage"
3165 " summary ``ipfw''");
3172 errx(EX_USAGE, "extraneous filename arguments");
3174 if ((f = fopen(av[0], "r")) == NULL)
3175 err(EX_UNAVAILABLE, "fopen: %s", av[0]);
3178 /* pipe through preprocessor (cpp or m4) */
3183 if (pipe(pipedes) == -1)
3184 err(EX_OSERR, "cannot create pipe");
3186 switch ((preproc = fork())) {
3188 err(EX_OSERR, "cannot fork");
3192 if (dup2(fileno(f), 0) == -1 ||
3193 dup2(pipedes[1], 1) == -1) {
3194 err(EX_OSERR, "dup2()");
3200 err(EX_OSERR, "execvp(%s) failed", cmd);
3206 if ((f = fdopen(pipedes[0], "r")) == NULL) {
3207 int savederrno = errno;
3209 kill(preproc, SIGTERM);
3211 err(EX_OSERR, "fdopen()");
3216 while (fgets(buf, BUFSIZ, f)) {
3218 sprintf(linename, "Line %d", lineno);
3223 if ((p = strchr(buf, '#')) != NULL)
3228 for (a = strtok(buf, WHITESP); a && i < MAX_ARGS;
3229 a = strtok(NULL, WHITESP), i++) {
3233 if (i == (qflag? 2: 1))
3236 errx(EX_USAGE, "%s: too many arguments", linename);
3243 if (waitpid(preproc, &status, 0) == -1)
3244 errx(EX_OSERR, "waitpid()");
3245 if (WIFEXITED(status) && WEXITSTATUS(status) != EX_OK)
3246 errx(EX_UNAVAILABLE, "preprocessor exited with status %d",
3247 WEXITSTATUS(status));
3248 else if (WIFSIGNALED(status))
3249 errx(EX_UNAVAILABLE, "preprocessor exited with signal %d",
3255 main(int ac, char *av[])
3257 ipfw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
3258 if (ipfw_socket < 0)
3259 err(EX_UNAVAILABLE, "socket");
3261 memset(keywords, 0, sizeof(struct ipfw_keyword) * KEYWORD_SIZE);
3262 memset(mappings, 0, sizeof(struct ipfw_mapping) * MAPPING_SIZE);
3264 prepare_default_funcs();
3266 if (ac > 1 && av[ac - 1][0] == '/' && access(av[ac - 1], R_OK) == 0)
3267 ipfw_readfile(ac, av);