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/ipfw3/ip_fw3_table.h"
62 #include "../../sys/net/dummynet3/ip_dummynet3.h"
63 #include "../../sys/net/libalias/alias.h"
64 #include "../../sys/net/ipfw3_basic/ip_fw3_basic.h"
65 #include "../../sys/net/ipfw3_nat/ip_fw3_nat.h"
69 #define KEYWORD_SIZE 256
70 #define MAPPING_SIZE 256
72 #define MAX_KEYWORD_LEN 20
74 #define WHITESP " \t\f\v\n\r"
75 #define IPFW_LIB_PATH "/usr/lib/libipfw3%s.so"
76 #define IP_MASK_ALL 0xffffffff
77 #define NAT_BUF_LEN 1024
79 * we use IPPROTO_ETHERTYPE as a fake protocol id to call the print routines
80 * This is only used in this code.
82 #define IPPROTO_ETHERTYPE 0x1000
85 * This macro returns the size of a struct sockaddr when passed
86 * through a routing socket. Basically we round up sa_len to
87 * a multiple of sizeof(long), with a minimum of sizeof(long).
88 * The check for a NULL pointer is just a convenience, probably never used.
89 * The case sa_len == 0 should only apply to empty structures.
92 ( (!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? \
94 1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) )
97 * show_rules() prints the body of an ipfw rule.
98 * Because the standard rule has at least proto src_ip dst_ip, we use
99 * a helper function to produce these entries if not provided explicitly.
100 * The first argument is the list of fields we have, the second is
101 * the list of fields we want to be printed.
103 * Special cases if we have provided a MAC header:
104 * + if the rule does not contain IP addresses/ports, do not print them;
105 * + if the rule does not contain an IP proto, print "all" instead of "ip";
108 #define HAVE_PROTO 0x0001
109 #define HAVE_SRCIP 0x0002
110 #define HAVE_DSTIP 0x0004
111 #define HAVE_MAC 0x0008
112 #define HAVE_MACTYPE 0x0010
113 #define HAVE_OPTIONS 0x8000
115 #define HAVE_IP (HAVE_PROTO | HAVE_SRCIP | HAVE_DSTIP)
118 * Definition of a port range, and macros to deal with values.
119 * FORMAT: HI 16-bits == first port in range, 0 == all ports.
120 * LO 16-bits == number of ports in range
121 * NOTES: - Port values are not stored in network byte order.
124 #define port_range u_long
126 #define GETLOPORT(x) ((x) >> 0x10)
127 #define GETNUMPORTS(x) ((x) & 0x0000ffff)
128 #define GETHIPORT(x) (GETLOPORT((x)) + GETNUMPORTS((x)))
130 /* Set y to be the low-port value in port_range variable x. */
131 #define SETLOPORT(x, y) ((x) = ((x) & 0x0000ffff) | ((y) << 0x10))
133 /* Set y to be the number of ports in port_range variable x. */
134 #define SETNUMPORTS(x, y) ((x) = ((x) & 0xffff0000) | (y))
136 #define INC_ARGCV() do { \
144 int ipfw_socket = -1; /* main RAW socket */
145 int do_resolv, /* Would try to resolve all */
146 do_acct, /* Show packet/byte count */
147 do_time, /* Show time stamps */
148 do_quiet = 1, /* Be quiet , default is quiet*/
149 do_force, /* Don't ask for confirmation */
150 do_pipe, /* this cmd refers to a pipe */
151 do_nat, /* Nat configuration. */
152 do_sort, /* field to sort results (0 = no) */
153 do_dynamic, /* display dynamic rules */
154 do_expired, /* display expired dynamic rules */
155 do_compact, /* show rules in compact mode */
156 show_sets, /* display rule sets */
195 struct char_int_map dummynet_params[] = {
197 { "noerror", TOK_NOERROR },
198 { "buckets", TOK_BUCKETS },
199 { "dst-ip", TOK_DSTIP },
200 { "src-ip", TOK_SRCIP },
201 { "dst-port", TOK_DSTPORT },
202 { "src-port", TOK_SRCPORT },
203 { "proto", TOK_PROTO },
204 { "weight", TOK_WEIGHT },
206 { "mask", TOK_MASK },
207 { "droptail", TOK_DROPTAIL },
209 { "gred", TOK_GRED },
211 { "bandwidth", TOK_BW },
212 { "delay", TOK_DELAY },
213 { "pipe", TOK_PIPE },
214 { "queue", TOK_QUEUE },
215 { "dummynet-params", TOK_NULL },
219 struct char_int_map nat_params[] = {
223 { "deny_in", TOK_DENY_INC },
224 { "same_ports", TOK_SAME_PORTS },
225 { "unreg_only", TOK_UNREG_ONLY },
226 { "reset", TOK_RESET_ADDR },
227 { "reverse", TOK_ALIAS_REV },
228 { "proxy_only", TOK_PROXY_ONLY },
229 { "redirect_addr", TOK_REDIR_ADDR },
230 { "redirect_port", TOK_REDIR_PORT },
231 { "redirect_proto", TOK_REDIR_PROTO },
235 struct ipfw_keyword {
237 char word[MAX_KEYWORD_LEN];
242 struct ipfw_mapping {
250 struct ipfw_keyword keywords[KEYWORD_SIZE];
251 struct ipfw_mapping mappings[MAPPING_SIZE];
254 match_token(struct char_int_map *table, char *string)
257 if (strcmp(table->key, string) == 0) {
266 get_modules(char *modules_str, int len)
268 if (do_get_x(IP_FW_MODULE, modules_str, &len) < 0)
269 errx(EX_USAGE, "ipfw3 not loaded.");
273 list_modules(int ac, char *av[])
275 void *module_str = NULL;
277 if ((module_str = realloc(module_str, len)) == NULL)
278 err(EX_OSERR, "realloc");
280 get_modules(module_str, len);
281 printf("%s", (char *)module_str);
284 parse_accept(ipfw_insn **cmd, int *ac, char **av[])
286 (*cmd)->opcode = O_BASIC_ACCEPT;
287 (*cmd)->module = MODULE_BASIC_ID;
288 (*cmd)->len = (*cmd)->len|LEN_OF_IPFWINSN;
290 if (!strncmp(**av, "log", strlen(**av))) {
293 if (isdigit(***av)) {
294 (*cmd)->arg1 = strtoul(**av, NULL, 10);
301 parse_deny(ipfw_insn **cmd, int *ac, char **av[])
303 (*cmd)->opcode = O_BASIC_DENY;
304 (*cmd)->module = MODULE_BASIC_ID;
305 (*cmd)->len = (*cmd)->len|LEN_OF_IPFWINSN;
307 if (!strncmp(**av, "log", strlen(**av))) {
310 if (isdigit(***av)) {
311 (*cmd)->arg1 = strtoul(**av, NULL, 10);
318 show_accept(ipfw_insn *cmd, int show_or)
322 printf(" log %d", cmd->arg1);
327 show_deny(ipfw_insn *cmd, int show_or)
331 printf(" log %d", cmd->arg1);
339 init_module mod_init_func;
341 char module_lib_file[50];
342 void *module_str = NULL;
345 if ((module_str = realloc(module_str, len)) == NULL)
346 err(EX_OSERR, "realloc");
348 get_modules(module_str, len);
350 const char s[2] = ",";
352 token = strtok(module_str, s);
353 while (token != NULL) {
354 sprintf(module_lib_file, IPFW_LIB_PATH, token);
355 token = strtok(NULL, s);
356 module_lib = dlopen(module_lib_file, RTLD_LAZY);
358 fprintf(stderr, "Couldn't open %s: %s\n",
359 module_lib_file, dlerror());
362 mod_init_func = dlsym(module_lib, "load_module");
363 if ((error = dlerror()))
365 fprintf(stderr, "Couldn't find init function: %s\n", error);
368 (*mod_init_func)((register_func)register_ipfw_func,
369 (register_keyword)register_ipfw_keyword);
374 prepare_default_funcs(void)
377 register_ipfw_keyword(MODULE_BASIC_ID, O_BASIC_ACCEPT, "allow", ACTION);
378 register_ipfw_keyword(MODULE_BASIC_ID, O_BASIC_ACCEPT, "accept", ACTION);
379 register_ipfw_func(MODULE_BASIC_ID, O_BASIC_ACCEPT,
380 (parser_func)parse_accept, (shower_func)show_accept);
382 register_ipfw_keyword(MODULE_BASIC_ID, O_BASIC_DENY, "deny", ACTION);
383 register_ipfw_keyword(MODULE_BASIC_ID, O_BASIC_DENY, "reject", ACTION);
384 register_ipfw_func(MODULE_BASIC_ID, O_BASIC_DENY,
385 (parser_func)parse_deny, (shower_func)show_deny);
389 register_ipfw_keyword(int module, int opcode, char *word, int type)
391 struct ipfw_keyword *tmp;
395 if (tmp->type == NONE) {
396 strcpy(tmp->word, word);
397 tmp->module = module;
398 tmp->opcode = opcode;
402 if (strcmp(tmp->word, word) == 0)
403 errx(EX_USAGE, "keyword `%s' exists", word);
411 register_ipfw_func(int module, int opcode, parser_func parser, shower_func shower)
413 struct ipfw_mapping *tmp;
417 if (tmp->type == NONE) {
418 tmp->module = module;
419 tmp->opcode = opcode;
420 tmp->parser = parser;
421 tmp->shower = shower;
425 if (tmp->opcode == opcode && tmp->module == module) {
426 errx(EX_USAGE, "func `%d' of module `%d' exists",
437 * this func need to check whether 'or' need to be printed,
438 * when the filter is the first filter with 'or' when dont print
439 * when not first and same as previous, then print or and no filter name
440 * when not first but different from previous, print name without 'or'
441 * show_or = 1: show or and ignore filter name
442 * show_or = 0: show filter name ignore or
444 void prev_show_chk(ipfw_insn *cmd, uint8_t *prev_module, uint8_t *prev_opcode,
447 if (cmd->len & F_OR) {
448 if (*prev_module == 0 && *prev_opcode == 0) {
449 /* first cmd with 'or' flag */
451 *prev_module = cmd->module;
452 *prev_opcode = cmd->opcode;
453 } else if (cmd->module == *prev_module &&
454 cmd->opcode == *prev_opcode) {
455 /* cmd same as previous, same module and opcode */
458 /* cmd different from prev*/
460 *prev_module = cmd->module;
461 *prev_opcode = cmd->opcode;
472 * word can be: proto from to other
476 * other show all other filters
478 int show_filter(ipfw_insn *cmd, char *word, int type)
480 struct ipfw_keyword *k;
481 struct ipfw_mapping *m;
484 uint8_t prev_module, prev_opcode;
488 for (i = 1; i < KEYWORD_SIZE; i++, k++) {
489 if (k->type == type) {
490 if (k->module == cmd->module &&
491 k->opcode == cmd->opcode) {
492 for (j = 1; j < MAPPING_SIZE; j++, m++) {
493 if (m->type == IN_USE &&
494 k->module == m->module &&
495 k->opcode == m->opcode) {
496 prev_show_chk(cmd, &prev_module,
497 &prev_opcode, &show_or);
498 if (cmd->len & F_NOT)
513 show_rules(struct ipfw_ioc_rule *rule, int pcwidth, int bcwidth)
515 static int twidth = 0;
519 u_int32_t set_disable = rule->set_disable;
521 if (set_disable & (1 << rule->set)) { /* disabled */
525 printf("# DISABLED ");
527 printf("%05u ", rule->rulenum);
530 printf("%*ju %*ju ", pcwidth, (uintmax_t)rule->pcnt, bcwidth,
531 (uintmax_t)rule->bcnt);
537 strcpy(timestr, ctime((time_t *)&twidth));
538 *strchr(timestr, '\n') = '\0';
539 twidth = strlen(timestr);
541 if (rule->timestamp) {
542 time_t t = _long_to_time(rule->timestamp);
544 strcpy(timestr, ctime(&t));
545 *strchr(timestr, '\n') = '\0';
546 printf("%s ", timestr);
548 printf("%*s ", twidth, " ");
550 } else if (do_time == 2) {
551 printf( "%10u ", rule->timestamp);
555 printf("set %d ", rule->set);
558 struct ipfw_keyword *k;
559 struct ipfw_mapping *m;
560 shower_func fn, comment_fn = NULL;
561 ipfw_insn *comment_cmd;
565 * show others and actions
567 for (l = rule->cmd_len - rule->act_ofs, cmd = ACTION_PTR(rule);
568 l > 0; l -= F_LEN(cmd),
569 cmd = (ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) {
572 for (i = 1; i< KEYWORD_SIZE; i++, k++) {
573 if ( k->module == cmd->module && k->opcode == cmd->opcode ) {
574 for (j = 1; j< MAPPING_SIZE; j++, m++) {
575 if (m->type == IN_USE &&
576 m->module == cmd->module &&
577 m->opcode == cmd->opcode) {
578 if (cmd->module == MODULE_BASIC_ID &&
579 cmd->opcode == O_BASIC_COMMENT) {
580 comment_fn = m->shower;
586 if (cmd->module == MODULE_BASIC_ID &&
588 O_BASIC_CHECK_STATE) {
603 for (l = rule->act_ofs, cmd = rule->cmd; l > 0; l -= F_LEN(cmd),
604 cmd = (ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) {
605 changed = show_filter(cmd, "proto", PROTO);
607 if (!changed && !do_quiet)
614 for (l = rule->act_ofs, cmd = rule->cmd; l > 0; l -= F_LEN(cmd),
615 cmd = (ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) {
616 changed = show_filter(cmd, "from", FROM);
618 if (!changed && !do_quiet)
625 for (l = rule->act_ofs, cmd = rule->cmd; l > 0; l -= F_LEN(cmd),
626 cmd = (ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) {
627 changed = show_filter(cmd, "to", TO);
629 if (!changed && !do_quiet)
635 for (l = rule->act_ofs, cmd = rule->cmd, m = mappings;
636 l > 0; l -= F_LEN(cmd),
637 cmd=(ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) {
638 show_filter(cmd, "other", FILTER);
641 /* show the comment in the end */
642 if (comment_fn != NULL) {
643 (*comment_fn)(comment_cmd, 0);
650 show_states(struct ipfw_ioc_state *d, int pcwidth, int bcwidth)
655 printf("%05u ", d->rulenum);
657 printf("%*ju %*ju ", pcwidth, (uintmax_t)d->pcnt,
658 bcwidth, (uintmax_t)d->bcnt);
662 /* state->timestamp */
664 time_t t = _long_to_time(d->timestamp);
665 strcpy(timestr, ctime(&t));
666 *strchr(timestr, '\n') = '\0';
667 printf(" (%s", timestr);
669 /* state->lifetime */
670 printf(" %ds", d->lifetime);
674 t = _long_to_time(d->expiry);
675 strcpy(timestr, ctime(&t));
676 *strchr(timestr, '\n') = '\0';
677 printf(" %s)", timestr);
682 } else if (do_time == 2) {
683 printf("(%u %ds %u) ", d->timestamp, d->lifetime, d->expiry);
686 if ((pe = getprotobynumber(d->flow_id.proto)) != NULL)
687 printf(" %s", pe->p_name);
689 printf(" proto %u", d->flow_id.proto);
691 a.s_addr = htonl(d->flow_id.src_ip);
692 printf(" %s %d", inet_ntoa(a), d->flow_id.src_port);
694 a.s_addr = htonl(d->flow_id.dst_ip);
695 printf(" <-> %s %d", inet_ntoa(a), d->flow_id.dst_port);
696 printf(" CPU %d", d->cpuid);
701 sort_q(const void *pa, const void *pb)
703 int rev = (do_sort < 0);
704 int field = rev ? -do_sort : do_sort;
706 const struct dn_ioc_flowqueue *a = pa;
707 const struct dn_ioc_flowqueue *b = pb;
711 res = a->len - b->len;
714 res = a->len_bytes - b->len_bytes;
717 case 3: /* tot pkts */
718 res = a->tot_pkts - b->tot_pkts;
721 case 4: /* tot bytes */
722 res = a->tot_bytes - b->tot_bytes;
729 return (int)(rev ? res : -res);
733 show_queues(struct dn_ioc_flowset *fs, struct dn_ioc_flowqueue *q)
737 printf("mask: 0x%02x 0x%08x/0x%04x -> 0x%08x/0x%04x\n",
738 fs->flow_mask.u.ip.proto,
739 fs->flow_mask.u.ip.src_ip, fs->flow_mask.u.ip.src_port,
740 fs->flow_mask.u.ip.dst_ip, fs->flow_mask.u.ip.dst_port);
741 if (fs->rq_elements == 0)
744 printf("BKT Prot ___Source IP/port____ "
745 "____Dest. IP/port____ Tot_pkt/bytes Pkt/Byte Drp\n");
747 heapsort(q, fs->rq_elements, sizeof(*q), sort_q);
748 for (l = 0; l < fs->rq_elements; l++) {
752 ina.s_addr = htonl(q[l].id.u.ip.src_ip);
753 printf("%3d ", q[l].hash_slot);
754 pe = getprotobynumber(q[l].id.u.ip.proto);
756 printf("%-4s ", pe->p_name);
758 printf("%4u ", q[l].id.u.ip.proto);
760 inet_ntoa(ina), q[l].id.u.ip.src_port);
761 ina.s_addr = htonl(q[l].id.u.ip.dst_ip);
763 inet_ntoa(ina), q[l].id.u.ip.dst_port);
764 printf("%4ju %8ju %2u %4u %3u\n",
765 (uintmax_t)q[l].tot_pkts, (uintmax_t)q[l].tot_bytes,
766 q[l].len, q[l].len_bytes, q[l].drops);
768 printf(" S %20ju F %20ju\n",
769 (uintmax_t)q[l].S, (uintmax_t)q[l].F);
774 show_flowset_parms(struct dn_ioc_flowset *fs, char *prefix)
778 char red[90]; /* Display RED parameters */
782 if (fs->flags_fs & DN_QSIZE_IS_BYTES) {
784 sprintf(qs, "%d KB", l / 1024);
786 sprintf(qs, "%d B", l);
788 sprintf(qs, "%3d sl.", l);
790 sprintf(plr, "plr %f", 1.0 * fs->plr / (double)(0x7fffffff));
793 if (fs->flags_fs & DN_IS_RED) /* RED parameters */
795 "\n\t %cRED w_q %f min_th %d max_th %d max_p %f",
796 (fs->flags_fs & DN_IS_GENTLE_RED) ? 'G' : ' ',
797 1.0 * fs->w_q / (double)(1 << SCALE_RED),
798 SCALE_VAL(fs->min_th),
799 SCALE_VAL(fs->max_th),
800 1.0 * fs->max_p / (double)(1 << SCALE_RED));
802 sprintf(red, "droptail");
804 printf("%s %s%s %d queues (%d buckets) %s\n",
805 prefix, qs, plr, fs->rq_elements, fs->rq_size, red);
809 show_pipes(void *data, int nbytes, int ac, char *av[])
813 struct dn_ioc_pipe *p = (struct dn_ioc_pipe *)data;
814 struct dn_ioc_flowset *fs;
815 struct dn_ioc_flowqueue *q;
819 rulenum = strtoul(*av++, NULL, 10);
822 for (; nbytes >= sizeof(*p); p = (struct dn_ioc_pipe *)next) {
823 double b = p->bandwidth;
827 if (p->fs.fs_type != DN_IS_PIPE)
828 break; /* done with pipes, now queues */
831 * compute length, as pipe have variable size
833 l = sizeof(*p) + p->fs.rq_elements * sizeof(*q);
834 next = (void *)p + l;
837 if (rulenum != 0 && rulenum != p->pipe_nr)
844 sprintf(buf, "unlimited");
845 else if (b >= 1000000)
846 sprintf(buf, "%7.3f Mbit/s", b/1000000);
848 sprintf(buf, "%7.3f Kbit/s", b/1000);
850 sprintf(buf, "%7.3f bit/s ", b);
852 sprintf(prefix, "%05d: %s %4d ms ",
853 p->pipe_nr, buf, p->delay);
854 show_flowset_parms(&p->fs, prefix);
856 printf(" V %20ju\n", (uintmax_t)p->V >> MY_M);
858 q = (struct dn_ioc_flowqueue *)(p+1);
859 show_queues(&p->fs, q);
862 for (fs = next; nbytes >= sizeof(*fs); fs = next) {
865 if (fs->fs_type != DN_IS_QUEUE)
867 l = sizeof(*fs) + fs->rq_elements * sizeof(*q);
868 next = (void *)fs + l;
870 q = (struct dn_ioc_flowqueue *)(fs+1);
871 sprintf(prefix, "q%05d: weight %d pipe %d ",
872 fs->fs_nr, fs->weight, fs->parent_nr);
873 show_flowset_parms(fs, prefix);
879 * This one handles all set-related commands
880 * ipfw set { show | enable | disable }
882 * ipfw set move X to Y
883 * ipfw set move rule X to Y
886 sets_handler(int ac, char *av[])
888 u_int32_t set_disable, masks[2];
890 u_int8_t cmd, new_set;
895 errx(EX_USAGE, "set needs command");
896 if (!strncmp(*av, "show", strlen(*av)) ) {
902 while (nbytes >= nalloc) {
903 nalloc = nalloc * 2+321;
906 if ((data = malloc(nbytes)) == NULL) {
907 err(EX_OSERR, "malloc");
909 } else if ((data = realloc(data, nbytes)) == NULL) {
910 err(EX_OSERR, "realloc");
912 if (do_get_x(IP_FW_GET, data, &nbytes) < 0) {
913 err(EX_OSERR, "getsockopt(IP_FW_GET)");
916 set_disable = ((struct ipfw_ioc_rule *)data)->set_disable;
917 for (i = 0, msg = "disable" ; i < 31; i++)
918 if ( (set_disable & (1<<i))) {
919 printf("%s %d", msg, i);
922 msg = (set_disable) ? " enable" : "enable";
923 for (i = 0; i < 31; i++)
924 if ( !(set_disable & (1<<i))) {
925 printf("%s %d", msg, i);
929 } else if (!strncmp(*av, "swap", strlen(*av))) {
932 errx(EX_USAGE, "set swap needs 2 set numbers\n");
933 rulenum = atoi(av[0]);
934 new_set = atoi(av[1]);
935 if (!isdigit(*(av[0])) || rulenum > 30)
936 errx(EX_DATAERR, "invalid set number %s\n", av[0]);
937 if (!isdigit(*(av[1])) || new_set > 30)
938 errx(EX_DATAERR, "invalid set number %s\n", av[1]);
939 masks[0] = (4 << 24) | (new_set << 16) | (rulenum);
940 i = do_set_x(IP_FW_DEL, masks, sizeof(u_int32_t));
941 } else if (!strncmp(*av, "move", strlen(*av))) {
943 if (ac && !strncmp(*av, "rule", strlen(*av))) {
948 if (ac != 3 || strncmp(av[1], "to", strlen(*av)))
949 errx(EX_USAGE, "syntax: set move [rule] X to Y\n");
950 rulenum = atoi(av[0]);
951 new_set = atoi(av[2]);
952 if (!isdigit(*(av[0])) || (cmd == 3 && rulenum > 30) ||
953 (cmd == 2 && rulenum == 65535) )
954 errx(EX_DATAERR, "invalid source number %s\n", av[0]);
955 if (!isdigit(*(av[2])) || new_set > 30)
956 errx(EX_DATAERR, "invalid dest. set %s\n", av[1]);
957 masks[0] = (cmd << 24) | (new_set << 16) | (rulenum);
958 i = do_set_x(IP_FW_DEL, masks, sizeof(u_int32_t));
959 } else if (!strncmp(*av, "disable", strlen(*av)) ||
960 !strncmp(*av, "enable", strlen(*av)) ) {
961 int which = !strncmp(*av, "enable", strlen(*av)) ? 1 : 0;
964 masks[0] = masks[1] = 0;
970 errx(EX_DATAERR, "invalid set number %d\n", i);
971 masks[which] |= (1<<i);
972 } else if (!strncmp(*av, "disable", strlen(*av)))
974 else if (!strncmp(*av, "enable", strlen(*av)))
977 errx(EX_DATAERR, "invalid set command %s\n", *av);
980 if ( (masks[0] & masks[1]) != 0 )
981 errx(EX_DATAERR, "cannot enable and disable the same set\n");
982 i = do_set_x(IP_FW_DEL, masks, sizeof(masks));
984 warn("set enable/disable: setsockopt(IP_FW_DEL)");
986 errx(EX_USAGE, "invalid set command %s\n", *av);
990 add_state(int ac, char *av[])
992 struct ipfw_ioc_state ioc_state;
993 ioc_state.expiry = 0;
994 ioc_state.lifetime = 0;
996 if (strcmp(*av, "rulenum") == 0) {
998 ioc_state.rulenum = atoi(*av);
1000 errx(EX_USAGE, "ipfw state add rule");
1003 struct protoent *pe;
1004 pe = getprotobyname(*av);
1005 ioc_state.flow_id.proto = pe->p_proto;
1008 ioc_state.flow_id.src_ip = inet_addr(*av);
1011 ioc_state.flow_id.src_port = atoi(*av);
1014 ioc_state.flow_id.dst_ip = inet_addr(*av);
1017 ioc_state.flow_id.dst_port = atoi(*av);
1020 if (strcmp(*av, "live") == 0) {
1022 ioc_state.lifetime = atoi(*av);
1026 if (strcmp(*av, "expiry") == 0) {
1028 ioc_state.expiry = strtoul(*av, NULL, 10);
1029 printf("ioc_state.expiry=%d\n", ioc_state.expiry);
1032 if (do_set_x(IP_FW_STATE_ADD, &ioc_state, sizeof(struct ipfw_ioc_state)) < 0 ) {
1033 err(EX_UNAVAILABLE, "do_set_x(IP_FW_STATE_ADD)");
1036 printf("Flushed all states.\n");
1041 delete_state(int ac, char *av[])
1045 if (ac == 1 && isdigit(**av))
1046 rulenum = atoi(*av);
1047 if (do_set_x(IP_FW_STATE_DEL, &rulenum, sizeof(int)) < 0 )
1048 err(EX_UNAVAILABLE, "do_set_x(IP_FW_STATE_DEL)");
1050 printf("Flushed all states.\n");
1054 flush_state(int ac, char *av[])
1059 printf("Are you sure? [yn] ");
1062 c = toupper(getc(stdin));
1063 while (c != '\n' && getc(stdin) != '\n')
1065 return; /* and do not flush */
1066 } while (c != 'Y' && c != 'N');
1067 if (c == 'N') /* user said no */
1070 if (do_set_x(IP_FW_STATE_FLUSH, NULL, 0) < 0 )
1071 err(EX_UNAVAILABLE, "do_set_x(IP_FW_STATE_FLUSH)");
1073 printf("Flushed all states.\n");
1077 lookup_host (char *host, struct in_addr *ipaddr)
1081 if (!inet_aton(host, ipaddr)) {
1082 if ((he = gethostbyname(host)) == NULL)
1084 *ipaddr = *(struct in_addr *)he->h_addr_list[0];
1090 table_append(int ac, char *av[])
1092 struct ipfw_ioc_table tbl;
1100 errx(EX_USAGE, "table id `%s' invalid", *av);
1102 if (tbl.id < 0 || tbl.id > IPFW_TABLES_MAX - 1)
1103 errx(EX_USAGE, "table id `%d' invalid", tbl.id);
1106 if (strcmp(*av, "ip") == 0)
1108 else if (strcmp(*av, "mac") == 0)
1111 errx(EX_USAGE, "table type `%s' not supported", *av);
1114 if (tbl.type == 1) { /* table type ipv4 */
1115 struct ipfw_ioc_table_ip_entry ip_ent;
1117 errx(EX_USAGE, "IP address required");
1119 p = strchr(*av, '/');
1122 ip_ent.masklen = atoi(p);
1123 if (ip_ent.masklen > 32)
1124 errx(EX_DATAERR, "bad width ``%s''", p);
1126 ip_ent.masklen = 32;
1129 if (lookup_host(*av, (struct in_addr *)&ip_ent.addr) != 0)
1130 errx(EX_NOHOST, "hostname ``%s'' unknown", *av);
1132 tbl.ip_ent[0] = ip_ent;
1133 size = sizeof(tbl) + sizeof(ip_ent);
1134 } else if (tbl.type == 2) { /* table type mac */
1135 struct ipfw_ioc_table_mac_entry mac_ent;
1137 errx(EX_USAGE, "MAC address required");
1139 mac_ent.addr = *ether_aton(*av);
1140 tbl.mac_ent[0] = mac_ent;
1141 size = sizeof(tbl) + sizeof(mac_ent);
1143 if (do_set_x(IP_FW_TABLE_APPEND, &tbl, size) < 0 )
1144 errx(EX_USAGE, "do_set_x(IP_FW_TABLE_APPEND) "
1145 "table `%d' append `%s' failed", tbl.id, *av);
1149 table_remove(int ac, char *av[])
1151 struct ipfw_ioc_table tbl;
1152 struct ipfw_ioc_table_ip_entry ip_ent;
1160 errx(EX_USAGE, "table id `%s' invalid", *av);
1162 if (tbl.id < 0 || tbl.id > IPFW_TABLES_MAX - 1)
1163 errx(EX_USAGE, "table id `%d' invalid", tbl.id);
1166 if (strcmp(*av, "ip") == 0)
1168 else if (strcmp(*av, "mac") == 0)
1171 errx(EX_USAGE, "table type `%s' not supported", *av);
1175 errx(EX_USAGE, "IP address required");
1176 p = strchr(*av, '/');
1179 ip_ent.masklen = atoi(p);
1180 if (ip_ent.masklen > 32)
1181 errx(EX_DATAERR, "bad width ``%s''", p);
1183 ip_ent.masklen = 32;
1186 if (lookup_host(*av, (struct in_addr *)&ip_ent.addr) != 0)
1187 errx(EX_NOHOST, "hostname ``%s'' unknown", *av);
1189 tbl.ip_ent[0] = ip_ent;
1190 size = sizeof(tbl) + sizeof(ip_ent);
1191 if (do_set_x(IP_FW_TABLE_REMOVE, &tbl, size) < 0 ) {
1192 errx(EX_USAGE, "do_set_x(IP_FW_TABLE_REMOVE) "
1193 "table `%d' append `%s' failed", tbl.id, *av);
1198 table_flush(int ac, char *av[])
1200 struct ipfw_ioc_table ioc_table;
1201 struct ipfw_ioc_table *t = &ioc_table;
1204 if (isdigit(**av)) {
1206 if (t->id < 0 || t->id > IPFW_TABLES_MAX - 1)
1207 errx(EX_USAGE, "table id `%d' invalid", t->id);
1209 errx(EX_USAGE, "table id `%s' invalid", *av);
1211 if (do_set_x(IP_FW_TABLE_FLUSH, t, sizeof(struct ipfw_ioc_table)) < 0 )
1212 errx(EX_USAGE, "do_set_x(IP_FW_TABLE_FLUSH) "
1213 "table `%s' flush failed", *av);
1217 table_list(int ac, char *av[])
1219 struct ipfw_ioc_table *ioc_table;
1220 int i, count, nbytes, nalloc = 1024;
1223 if (strcmp(*av, "list") == 0) {
1225 while (nbytes >= nalloc) {
1226 nalloc = nalloc * 2 ;
1228 if ((data = realloc(data, nbytes)) == NULL)
1229 err(EX_OSERR, "realloc");
1230 if (do_get_x(IP_FW_TABLE_LIST, data, &nbytes) < 0)
1231 err(EX_OSERR, "do_get_x(IP_FW_TABLE_LIST)");
1233 ioc_table = (struct ipfw_ioc_table *)data;
1234 count = nbytes / sizeof(struct ipfw_ioc_table);
1235 for (i = 0; i < count; i++, ioc_table++) {
1236 if (ioc_table->type > 0) {
1237 printf("table %d",ioc_table->id);
1238 if (ioc_table->type == 1)
1240 else if (ioc_table->type == 2)
1241 printf(" type mac");
1242 printf(" count %d",ioc_table->count);
1243 if (strlen(ioc_table->name) > 0)
1244 printf(" name %s",ioc_table->name);
1250 errx(EX_USAGE, "ipfw3 table `%s' delete invalid", *av);
1255 print_table(struct ipfw_ioc_table * tbl)
1259 errx(EX_USAGE, "table %d is not in use", tbl->id);
1261 printf("table %d", tbl->id);
1264 else if (tbl->type == 2)
1265 printf(" type mac");
1267 printf(" count %d", tbl->count);
1268 if (strlen(tbl->name) > 0)
1269 printf(" name %s", tbl->name);
1273 if (tbl->type == 1) {
1274 struct ipfw_ioc_table_ip_entry *ip_ent;
1275 ip_ent = tbl->ip_ent;
1276 for (i = 0; i < tbl->count; i++) {
1277 printf("%s", inet_ntoa(*(struct in_addr *)&ip_ent->addr));
1278 printf("/%d ", ip_ent->masklen);
1282 } else if (tbl->type == 2) {
1283 struct ipfw_ioc_table_mac_entry *mac_ent;
1284 mac_ent = tbl->mac_ent;
1285 for (i = 0; i < tbl->count; i++) {
1286 printf("%s", ether_ntoa(&mac_ent->addr));
1294 table_show(int ac, char *av[])
1296 int nbytes, nalloc = 1024;
1299 if (isdigit(**av)) {
1301 while (nbytes >= nalloc) {
1302 nalloc = nalloc * 2 + 256;
1305 if ((data = malloc(nbytes)) == NULL) {
1306 err(EX_OSERR, "malloc");
1308 } else if ((data = realloc(data, nbytes)) == NULL) {
1309 err(EX_OSERR, "realloc");
1311 /* store table id in the header of data */
1312 int *head = (int *)data;
1314 if (*head < 0 || *head > IPFW_TABLES_MAX - 1)
1315 errx(EX_USAGE, "table id `%d' invalid", *head);
1316 if (do_get_x(IP_FW_TABLE_SHOW, data, &nbytes) < 0)
1317 err(EX_OSERR, "do_get_x(IP_FW_TABLE_LIST)");
1318 struct ipfw_ioc_table *tbl;
1319 tbl = (struct ipfw_ioc_table *)data;
1323 errx(EX_USAGE, "ipfw3 table `%s' show invalid", *av);
1328 table_create(int ac, char *av[])
1330 struct ipfw_ioc_table ioc_table;
1331 struct ipfw_ioc_table *t = &ioc_table;
1335 errx(EX_USAGE, "table parameters invalid");
1336 if (isdigit(**av)) {
1338 if (t->id < 0 || t->id > IPFW_TABLES_MAX - 1)
1339 errx(EX_USAGE, "table id `%d' invalid", t->id);
1341 errx(EX_USAGE, "table id `%s' invalid", *av);
1344 if (strcmp(*av, "ip") == 0)
1346 else if (strcmp(*av, "mac") == 0)
1349 errx(EX_USAGE, "table type `%s' not supported", *av);
1352 memset(t->name, 0, IPFW_TABLE_NAME_LEN);
1353 if (ac == 2 && strcmp(*av, "name") == 0) {
1355 if (strlen(*av) < IPFW_TABLE_NAME_LEN) {
1356 strncpy(t->name, *av, strlen(*av));
1358 errx(EX_USAGE, "table name `%s' too long", *av);
1360 } else if (ac == 1) {
1361 errx(EX_USAGE, "table `%s' invalid", *av);
1364 if (do_set_x(IP_FW_TABLE_CREATE, t, sizeof(struct ipfw_ioc_table)) < 0)
1365 errx(EX_USAGE, "do_set_x(IP_FW_TABLE_CREATE) "
1366 "table `%d' in use", t->id);
1370 table_delete(int ac, char *av[])
1372 struct ipfw_ioc_table ioc_table;
1373 struct ipfw_ioc_table *t = &ioc_table;
1376 if (isdigit(**av)) {
1378 if (t->id < 0 || t->id > IPFW_TABLES_MAX - 1)
1379 errx(EX_USAGE, "table id `%d' invalid", t->id);
1381 errx(EX_USAGE, "table id `%s' invalid", *av);
1383 if (t->id < 0 || t->id > IPFW_TABLES_MAX - 1)
1384 errx(EX_USAGE, "table id `%d' invalid", t->id);
1386 if (do_set_x(IP_FW_TABLE_DELETE, t, sizeof(struct ipfw_ioc_table)) < 0)
1387 errx(EX_USAGE, "do_set_x(IP_FW_TABLE_DELETE) "
1388 "table `%s' delete failed", *av);
1392 table_test(int ac, char *av[])
1394 struct ipfw_ioc_table tbl;
1401 errx(EX_USAGE, "table id `%s' invalid", *av);
1403 if (tbl.id < 0 || tbl.id > IPFW_TABLES_MAX - 1)
1404 errx(EX_USAGE, "table id `%d' invalid", tbl.id);
1407 if (strcmp(*av, "ip") == 0)
1409 else if (strcmp(*av, "mac") == 0)
1412 errx(EX_USAGE, "table type `%s' not supported", *av);
1415 if (tbl.type == 1) { /* table type ipv4 */
1416 struct ipfw_ioc_table_ip_entry ip_ent;
1417 if (lookup_host(*av, (struct in_addr *)&ip_ent.addr) != 0)
1418 errx(EX_NOHOST, "hostname ``%s'' unknown", *av);
1420 tbl.ip_ent[0] = ip_ent;
1421 size = sizeof(tbl) + sizeof(ip_ent);
1422 } else if (tbl.type == 2) { /* table type mac */
1423 struct ipfw_ioc_table_mac_entry mac_ent;
1425 errx(EX_USAGE, "MAC address required");
1427 mac_ent.addr = *ether_aton(*av);
1428 tbl.mac_ent[0] = mac_ent;
1429 size = sizeof(tbl) + sizeof(mac_ent);
1431 if (do_set_x(IP_FW_TABLE_TEST, &tbl, size) < 0 ) {
1432 printf("NO, %s not exists in table %d\n", *av, tbl.id);
1434 printf("YES, %s exists in table %d\n", *av, tbl.id);
1439 table_rename(int ac, char *av[])
1441 struct ipfw_ioc_table tbl;
1444 bzero(&tbl, sizeof(tbl));
1449 errx(EX_USAGE, "table id `%s' invalid", *av);
1451 if (tbl.id < 0 || tbl.id > IPFW_TABLES_MAX - 1)
1452 errx(EX_USAGE, "table id `%d' invalid", tbl.id);
1455 strlcpy(tbl.name, *av, IPFW_TABLE_NAME_LEN);
1457 if (do_set_x(IP_FW_TABLE_RENAME, &tbl, size) < 0 )
1458 errx(EX_USAGE, "do_set_x(IP_FW_TABLE_RENAME) "
1459 "table `%d' not in use", tbl.id);
1463 list(int ac, char *av[])
1465 struct ipfw_ioc_state *dynrules, *d;
1466 struct ipfw_ioc_rule *r;
1470 int bcwidth, n, nbytes, nstat, ndyn, pcwidth, width;
1471 int exitval = EX_OK, lac;
1472 char **lav, *endptr;
1478 /* get rules or pipes from kernel, resizing array as necessary */
1481 while (nbytes >= nalloc) {
1482 nalloc = nalloc * 2 ;
1484 if ((data = realloc(data, nbytes)) == NULL)
1485 err(EX_OSERR, "realloc");
1486 if (do_get_x(IP_FW_GET, data, &nbytes) < 0)
1487 err(EX_OSERR, "do_get_x(IP_FW_GET)");
1491 * Count static rules.
1494 nstat = r->static_count;
1497 * Count dynamic rules. This is easier as they have
1500 dynrules = (struct ipfw_ioc_state *)((void *)r + r->static_len);
1501 ndyn = (nbytes - r->static_len) / sizeof(*dynrules);
1503 /* if showing stats, figure out column widths ahead of time */
1504 bcwidth = pcwidth = 0;
1506 for (n = 0, r = data; n < nstat;
1507 n++, r = (void *)r + IOC_RULESIZE(r)) {
1508 /* packet counter */
1509 width = snprintf(NULL, 0, "%ju", (uintmax_t)r->pcnt);
1510 if (width > pcwidth)
1514 width = snprintf(NULL, 0, "%ju", (uintmax_t)r->bcnt);
1515 if (width > bcwidth)
1519 if (do_dynamic && ndyn) {
1520 for (n = 0, d = dynrules; n < ndyn; n++, d++) {
1521 width = snprintf(NULL, 0, "%ju", (uintmax_t)d->pcnt);
1522 if (width > pcwidth)
1525 width = snprintf(NULL, 0, "%ju", (uintmax_t)d->bcnt);
1526 if (width > bcwidth)
1531 /* if no rule numbers were specified, list all rules */
1533 if (do_dynamic != 2) {
1534 for (n = 0, r = data; n < nstat; n++,
1535 r = (void *)r + IOC_RULESIZE(r)) {
1536 show_rules(r, pcwidth, bcwidth);
1539 if (do_dynamic && ndyn) {
1540 if (do_dynamic != 2) {
1541 printf("## States (%d):\n", ndyn);
1543 for (n = 0, d = dynrules; n < ndyn; n++, d++)
1544 show_states(d, pcwidth, bcwidth);
1549 /* display specific rules requested on command line */
1551 if (do_dynamic != 2) {
1552 for (lac = ac, lav = av; lac != 0; lac--) {
1553 /* convert command line rule # */
1554 rnum = strtoul(*lav++, &endptr, 10);
1557 warnx("invalid rule number: %s", *(lav - 1));
1560 for (n = seen = 0, r = data; n < nstat;
1561 n++, r = (void *)r + IOC_RULESIZE(r) ) {
1562 if (r->rulenum > rnum)
1564 if (r->rulenum == rnum) {
1565 show_rules(r, pcwidth, bcwidth);
1570 /* give precedence to other error(s) */
1571 if (exitval == EX_OK)
1572 exitval = EX_UNAVAILABLE;
1573 warnx("rule %lu does not exist", rnum);
1578 if (do_dynamic && ndyn) {
1579 if (do_dynamic != 2) {
1580 printf("## States (%d):\n", ndyn);
1582 for (lac = ac, lav = av; lac != 0; lac--) {
1583 rnum = strtoul(*lav++, &endptr, 10);
1585 /* already warned */
1587 for (n = 0, d = dynrules; n < ndyn; n++, d++) {
1588 if (d->rulenum > rnum)
1590 if (d->rulenum == rnum)
1591 show_states(d, pcwidth, bcwidth);
1601 if (exitval != EX_OK)
1606 show_dummynet(int ac, char *av[])
1610 int nalloc = 1024; /* start somewhere... */
1615 while (nbytes >= nalloc) {
1616 nalloc = nalloc * 2 + 200;
1618 if ((data = realloc(data, nbytes)) == NULL)
1619 err(EX_OSERR, "realloc");
1620 if (do_get_x(IP_DUMMYNET_GET, data, &nbytes) < 0) {
1621 err(EX_OSERR, "do_get_x(IP_%s_GET)",
1622 do_pipe ? "DUMMYNET" : "FW");
1626 show_pipes(data, nbytes, ac, av);
1633 fprintf(stderr, "usage: ipfw [options]\n"
1634 " ipfw add [rulenum] [set id] action filters\n"
1635 " ipfw delete [rulenum]\n"
1637 " ipfw list [rulenum]\n"
1638 " ipfw show [rulenum]\n"
1639 " ipfw zero [rulenum]\n"
1640 " ipfw set [show|enable|disable]\n"
1642 " ipfw [enable|disable]\n"
1643 " ipfw log [reset|off|on]\n"
1644 " ipfw nat [config|show|delete]\n"
1645 " ipfw pipe [config|show|delete]\n"
1646 " ipfw state [add|delete|list|show]"
1647 "\nsee ipfw manpage for details\n");
1652 delete_nat_config(int ac, char *av[])
1659 if (do_set_x(IP_FW_NAT_DEL, &i, sizeof(i)) == -1)
1660 errx(EX_USAGE, "NAT %d in use or not exists", i);
1664 delete_rules(int ac, char *av[])
1666 struct dn_ioc_pipe pipe;
1668 int exitval = EX_OK;
1672 memset(&pipe, 0, sizeof pipe);
1675 if (ac > 0 && !strncmp(*av, "set", strlen(*av))) {
1676 do_set = 1; /* delete set */
1681 while (ac && isdigit(**av)) {
1690 i = do_set_x(IP_DUMMYNET_DEL, &pipe, sizeof pipe);
1693 warn("rule %u: setsockopt(IP_DUMMYNET_DEL)",
1694 do_pipe == 1 ? pipe.pipe_nr : pipe.fs.fs_nr);
1697 rulenum = (i & 0xffff) | (do_set << 24);
1698 i = do_set_x(IP_FW_DEL, &rulenum, sizeof rulenum);
1700 exitval = EX_UNAVAILABLE;
1701 warn("rule %u: setsockopt(IP_FW_DEL)",
1706 if (exitval != EX_OK)
1711 static unsigned long
1712 getbw(const char *str, u_short *flags, int kb)
1718 val = strtoul(str, &end, 0);
1719 if (*end == 'k' || *end == 'K') {
1722 } else if (*end == 'm' || *end == 'M') {
1728 * Deal with bits or bytes or b(bits) or B(bytes). If there is no
1729 * trailer assume bits.
1731 if (strncasecmp(end, "bit", 3) == 0) {
1733 } else if (strncasecmp(end, "byte", 4) == 0) {
1735 } else if (*end == 'b') {
1737 } else if (*end == 'B') {
1742 * Return in bits if flags is NULL, else flag bits
1743 * or bytes in flags and return the unconverted value.
1745 if (inbytes && flags)
1746 *flags |= DN_QSIZE_IS_BYTES;
1747 else if (inbytes && flags == NULL)
1754 * config dummynet pipe/queue
1757 config_dummynet(int ac, char **av)
1759 struct dn_ioc_pipe pipe;
1766 memset(&pipe, 0, sizeof pipe);
1768 if (ac && isdigit(**av)) {
1780 int tok = match_token(dummynet_params, *av);
1785 pipe.fs.flags_fs |= DN_NOERROR;
1789 NEED1("plr needs argument 0..1\n");
1790 d = strtod(av[0], NULL);
1795 pipe.fs.plr = (int)(d*0x7fffffff);
1800 NEED1("queue needs queue size\n");
1802 pipe.fs.qsize = getbw(av[0], &pipe.fs.flags_fs, 1024);
1807 NEED1("buckets needs argument\n");
1808 pipe.fs.rq_size = strtoul(av[0], NULL, 0);
1813 NEED1("mask needs mask specifier\n");
1815 * per-flow queue, mask is dst_ip, dst_port,
1816 * src_ip, src_port, proto measured in bits
1820 pipe.fs.flow_mask.type = ETHERTYPE_IP;
1821 pipe.fs.flow_mask.u.ip.dst_ip = 0;
1822 pipe.fs.flow_mask.u.ip.src_ip = 0;
1823 pipe.fs.flow_mask.u.ip.dst_port = 0;
1824 pipe.fs.flow_mask.u.ip.src_port = 0;
1825 pipe.fs.flow_mask.u.ip.proto = 0;
1829 u_int32_t *p32 = NULL;
1830 u_int16_t *p16 = NULL;
1832 tok = match_token(dummynet_params, *av);
1837 * special case, all bits significant
1839 pipe.fs.flow_mask.u.ip.dst_ip = ~0;
1840 pipe.fs.flow_mask.u.ip.src_ip = ~0;
1841 pipe.fs.flow_mask.u.ip.dst_port = ~0;
1842 pipe.fs.flow_mask.u.ip.src_port = ~0;
1843 pipe.fs.flow_mask.u.ip.proto = ~0;
1844 pipe.fs.flags_fs |= DN_HAVE_FLOW_MASK;
1848 p32 = &pipe.fs.flow_mask.u.ip.dst_ip;
1852 p32 = &pipe.fs.flow_mask.u.ip.src_ip;
1856 p16 = &pipe.fs.flow_mask.u.ip.dst_port;
1860 p16 = &pipe.fs.flow_mask.u.ip.src_port;
1871 errx(EX_USAGE, "mask: value missing");
1872 if (*av[0] == '/') {
1873 a = strtoul(av[0]+1, &end, 0);
1874 a = (a == 32) ? ~0 : (1 << a) - 1;
1876 a = strtoul(av[0], &end, 0);
1879 else if (p16 != NULL) {
1882 "mask: must be 16 bit");
1883 *p16 = (u_int16_t)a;
1887 "mask: must be 8 bit");
1888 pipe.fs.flow_mask.u.ip.proto = (uint8_t)a;
1891 pipe.fs.flags_fs |= DN_HAVE_FLOW_MASK;
1893 } /* end while, config masks */
1900 NEED1("red/gred needs w_q/min_th/max_th/max_p\n");
1901 pipe.fs.flags_fs |= DN_IS_RED;
1902 if (tok == TOK_GRED)
1903 pipe.fs.flags_fs |= DN_IS_GENTLE_RED;
1905 * the format for parameters is w_q/min_th/max_th/max_p
1907 if ((end = strsep(&av[0], "/"))) {
1908 double w_q = strtod(end, NULL);
1909 if (w_q > 1 || w_q <= 0)
1910 errx(EX_DATAERR, "0 < w_q <= 1");
1911 pipe.fs.w_q = (int) (w_q * (1 << SCALE_RED));
1913 if ((end = strsep(&av[0], "/"))) {
1914 pipe.fs.min_th = strtoul(end, &end, 0);
1915 if (*end == 'K' || *end == 'k')
1916 pipe.fs.min_th *= 1024;
1918 if ((end = strsep(&av[0], "/"))) {
1919 pipe.fs.max_th = strtoul(end, &end, 0);
1920 if (*end == 'K' || *end == 'k')
1921 pipe.fs.max_th *= 1024;
1923 if ((end = strsep(&av[0], "/"))) {
1924 double max_p = strtod(end, NULL);
1925 if (max_p > 1 || max_p <= 0)
1926 errx(EX_DATAERR, "0 < max_p <= 1");
1927 pipe.fs.max_p = (int)(max_p * (1 << SCALE_RED));
1933 pipe.fs.flags_fs &= ~(DN_IS_RED|DN_IS_GENTLE_RED);
1937 NEED1("bw needs bandwidth\n");
1939 errx(EX_DATAERR, "bandwidth only valid for pipes");
1941 * set bandwidth value
1943 pipe.bandwidth = getbw(av[0], NULL, 1000);
1944 if (pipe.bandwidth < 0)
1945 errx(EX_DATAERR, "bandwidth too large");
1951 errx(EX_DATAERR, "delay only valid for pipes");
1952 NEED1("delay needs argument 0..10000ms\n");
1953 pipe.delay = strtoul(av[0], NULL, 0);
1959 errx(EX_DATAERR, "weight only valid for queues");
1960 NEED1("weight needs argument 0..100\n");
1961 pipe.fs.weight = strtoul(av[0], &end, 0);
1967 errx(EX_DATAERR, "pipe only valid for queues");
1968 NEED1("pipe needs pipe_number\n");
1969 pipe.fs.parent_nr = strtoul(av[0], &end, 0);
1974 errx(EX_DATAERR, "unrecognised option ``%s''", *av);
1978 if (pipe.pipe_nr == 0)
1979 errx(EX_DATAERR, "pipe_nr must be > 0");
1980 if (pipe.delay > 10000)
1981 errx(EX_DATAERR, "delay must be < 10000");
1982 } else { /* do_pipe == 2, queue */
1983 if (pipe.fs.parent_nr == 0)
1984 errx(EX_DATAERR, "pipe must be > 0");
1985 if (pipe.fs.weight >100)
1986 errx(EX_DATAERR, "weight must be <= 100");
1988 if (pipe.fs.flags_fs & DN_QSIZE_IS_BYTES) {
1989 if (pipe.fs.qsize > 1024*1024)
1990 errx(EX_DATAERR, "queue size must be < 1MB");
1992 if (pipe.fs.qsize > 100)
1993 errx(EX_DATAERR, "2 <= queue size <= 100");
1995 if (pipe.fs.flags_fs & DN_IS_RED) {
1997 int lookup_depth, avg_pkt_size;
1998 double s, idle, weight, w_q;
2002 if (pipe.fs.min_th >= pipe.fs.max_th)
2003 errx(EX_DATAERR, "min_th %d must be < than max_th %d",
2004 pipe.fs.min_th, pipe.fs.max_th);
2005 if (pipe.fs.max_th == 0)
2006 errx(EX_DATAERR, "max_th must be > 0");
2009 if (sysctlbyname("net.inet.ip.dummynet.red_lookup_depth",
2010 &lookup_depth, &len, NULL, 0) == -1)
2012 errx(1, "sysctlbyname(\"%s\")",
2013 "net.inet.ip.dummynet.red_lookup_depth");
2014 if (lookup_depth == 0)
2015 errx(EX_DATAERR, "net.inet.ip.dummynet.red_lookup_depth"
2016 " must be greater than zero");
2019 if (sysctlbyname("net.inet.ip.dummynet.red_avg_pkt_size",
2020 &avg_pkt_size, &len, NULL, 0) == -1)
2022 errx(1, "sysctlbyname(\"%s\")",
2023 "net.inet.ip.dummynet.red_avg_pkt_size");
2024 if (avg_pkt_size == 0)
2026 "net.inet.ip.dummynet.red_avg_pkt_size must"
2027 " be greater than zero");
2029 len = sizeof(clock_hz);
2030 if (sysctlbyname("net.inet.ip.dummynet.hz", &clock_hz, &len,
2032 errx(1, "sysctlbyname(\"%s\")",
2033 "net.inet.ip.dummynet.hz");
2037 * Ticks needed for sending a medium-sized packet.
2038 * Unfortunately, when we are configuring a WF2Q+ queue, we
2039 * do not have bandwidth information, because that is stored
2040 * in the parent pipe, and also we have multiple queues
2041 * competing for it. So we set s=0, which is not very
2042 * correct. But on the other hand, why do we want RED with
2045 if (pipe.bandwidth == 0) /* this is a WF2Q+ queue */
2048 s = clock_hz * avg_pkt_size * 8 / pipe.bandwidth;
2051 * max idle time (in ticks) before avg queue size becomes 0.
2052 * NOTA: (3/w_q) is approx the value x so that
2053 * (1-w_q)^x < 10^-3.
2055 w_q = ((double)pipe.fs.w_q) / (1 << SCALE_RED);
2056 idle = s * 3. / w_q;
2057 pipe.fs.lookup_step = (int)idle / lookup_depth;
2058 if (!pipe.fs.lookup_step)
2059 pipe.fs.lookup_step = 1;
2061 for (t = pipe.fs.lookup_step; t > 0; --t)
2063 pipe.fs.lookup_weight = (int)(weight * (1 << SCALE_RED));
2065 i = do_set_x(IP_DUMMYNET_CONFIGURE, &pipe, sizeof pipe);
2067 err(1, "do_set_x(%s)", "IP_DUMMYNET_CONFIGURE");
2071 * helper function, updates the pointer to cmd with the length
2072 * of the current command, and also cleans up the first word of
2073 * the new command in case it has been clobbered before.
2076 next_cmd(ipfw_insn *cmd)
2079 bzero(cmd, sizeof(*cmd));
2084 * Parse arguments and assemble the microinstructions which make up a rule.
2085 * Rules are added into the 'rulebuf' and then copied in the correct order
2086 * into the actual rule.
2091 add(int ac, char *av[])
2094 * rules are added into the 'rulebuf' and then copied in
2095 * the correct order into the actual rule.
2096 * Some things that need to go out of order (prob, action etc.)
2099 static uint32_t rulebuf[IPFW_RULE_SIZE_MAX];
2100 static uint32_t actbuf[IPFW_RULE_SIZE_MAX];
2101 static uint32_t othbuf[IPFW_RULE_SIZE_MAX];
2102 static uint32_t cmdbuf[IPFW_RULE_SIZE_MAX];
2104 ipfw_insn *src, *dst, *cmd, *action, *other;
2107 ipfw_insn *the_comment = NULL;
2108 struct ipfw_ioc_rule *rule;
2109 struct ipfw_keyword *key;
2110 struct ipfw_mapping *map;
2114 bzero(actbuf, sizeof(actbuf)); /* actions go here */
2115 bzero(othbuf, sizeof(actbuf)); /* others */
2116 bzero(cmdbuf, sizeof(cmdbuf)); /* filters */
2117 bzero(rulebuf, sizeof(rulebuf));
2119 rule = (struct ipfw_ioc_rule *)rulebuf;
2120 cmd = (ipfw_insn *)cmdbuf;
2121 action = (ipfw_insn *)actbuf;
2122 other = (ipfw_insn *)othbuf;
2124 NEED2("need more parameters");
2127 /* [rule N] -- Rule number optional */
2128 if (ac && isdigit(**av)) {
2129 rule->rulenum = atoi(*av);
2133 /* [set N] -- set number (0..30), optional */
2134 if (ac > 1 && !strncmp(*av, "set", strlen(*av))) {
2135 int set = strtoul(av[1], NULL, 10);
2136 if (set < 0 || set > 30)
2137 errx(EX_DATAERR, "illegal set %s", av[1]);
2146 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) {
2147 if (key->type == BEFORE &&
2148 strcmp(key->word, *av) == 0) {
2149 for (j = 0, map = mappings;
2150 j < MAPPING_SIZE; j++, map++) {
2151 if (map->type == IN_USE &&
2152 map->module == key->module &&
2153 map->opcode == key->opcode ) {
2155 (*fn)(&other, &ac, &av);
2162 if (i >= KEYWORD_SIZE) {
2164 } else if (F_LEN(other) > 0) {
2165 if (other->module == MODULE_BASIC_ID &&
2166 other->opcode == O_BASIC_CHECK_STATE) {
2167 other = next_cmd(other);
2170 other = next_cmd(other);
2177 * only accept 1 action
2179 NEED1("missing action");
2180 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) {
2181 if (ac > 0 && key->type == ACTION &&
2182 strcmp(key->word, *av) == 0) {
2183 for (j = 0, map = mappings; j<MAPPING_SIZE; j++, map++) {
2184 if (map->type == IN_USE &&
2185 map->module == key->module &&
2186 map->opcode == key->opcode) {
2188 (*fn)(&action, &ac, &av);
2195 if (F_LEN(action) > 0)
2196 action = next_cmd(action);
2201 if (strcmp(*av, "proto") == 0){
2205 NEED1("missing protocol");
2206 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) {
2207 if (key->type == PROTO &&
2208 strcmp(key->word, "proto") == 0) {
2209 for (j = 0, map = mappings; j<MAPPING_SIZE; j++, map++) {
2210 if (map->type == IN_USE &&
2211 map->module == key->module &&
2212 map->opcode == key->opcode ) {
2214 (*fn)(&cmd, &ac, &av);
2222 cmd = next_cmd(cmd);
2228 char *s, *cur; /* current filter */
2229 ipfw_insn_u32 *cmd32; /* alias for cmd */
2232 cmd32 = (ipfw_insn_u32 *)cmd;
2233 if (strcmp(*av, "or") == 0) {
2235 errx(EX_USAGE, "'or' should"
2236 "between two filters\n");
2241 if (strcmp(*av, "not") == 0) {
2242 if (cmd->len & F_NOT)
2243 errx(EX_USAGE, "double \"not\" not allowed\n");
2249 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) {
2250 if ((key->type == FILTER ||
2251 key->type == AFTER ||
2252 key->type == FROM ||
2254 strcmp(key->word, cur) == 0) {
2255 for (j = 0, map = mappings;
2256 j< MAPPING_SIZE; j++, map++) {
2257 if (map->type == IN_USE &&
2258 map->module == key->module &&
2259 map->opcode == key->opcode ) {
2261 (*fn)(&cmd, &ac, &av);
2266 } else if (i == KEYWORD_SIZE - 1) {
2267 errx(EX_USAGE, "bad command `%s'", cur);
2270 if (i >= KEYWORD_SIZE) {
2272 } else if (F_LEN(cmd) > 0) {
2275 cmd = next_cmd(cmd);
2281 errx(EX_USAGE, "bad command `%s'", *av);
2284 * Now copy stuff into the rule.
2285 * [filters][others][action][comment]
2287 dst = (ipfw_insn *)rule->cmd;
2289 * copy all filters, except comment
2291 src = (ipfw_insn *)cmdbuf;
2292 for (src = (ipfw_insn *)cmdbuf; src != cmd; src += i) {
2293 /* pick comment out */
2295 if (src->module == MODULE_BASIC_ID && src->opcode == O_BASIC_COMMENT) {
2298 bcopy(src, dst, i * sizeof(u_int32_t));
2299 dst = (ipfw_insn *)((uint32_t *)dst + i);
2304 * start action section, it begin with others
2306 rule->act_ofs = (uint32_t *)dst - (uint32_t *)(rule->cmd);
2309 * copy all other others
2311 for (src = (ipfw_insn *)othbuf; src != other; src += i) {
2313 bcopy(src, dst, i * sizeof(u_int32_t));
2314 dst = (ipfw_insn *)((uint32_t *)dst + i);
2317 /* copy the action to the end of rule */
2318 src = (ipfw_insn *)actbuf;
2320 bcopy(src, dst, i * sizeof(u_int32_t));
2321 dst = (ipfw_insn *)((uint32_t *)dst + i);
2324 * comment place behind the action
2326 if (the_comment != NULL) {
2327 i = F_LEN(the_comment);
2328 bcopy(the_comment, dst, i * sizeof(u_int32_t));
2329 dst = (ipfw_insn *)((uint32_t *)dst + i);
2332 rule->cmd_len = (u_int32_t *)dst - (u_int32_t *)(rule->cmd);
2333 i = (void *)dst - (void *)rule;
2334 if (do_set_x(IP_FW_ADD, (void *)rule, i) == -1) {
2335 err(EX_UNAVAILABLE, "getsockopt(%s)", "IP_FW_ADD");
2338 show_rules(rule, 10, 10);
2342 zero(int ac, char *av[])
2350 /* clear all entries */
2351 if (do_set_x(IP_FW_ZERO, NULL, 0) < 0)
2352 err(EX_UNAVAILABLE, "do_set_x(IP_FW_ZERO)");
2354 printf("Accounting cleared.\n");
2360 if (isdigit(**av)) {
2361 rulenum = atoi(*av);
2363 if (do_set_x(IP_FW_ZERO, &rulenum, sizeof rulenum)) {
2364 warn("rule %u: do_set_x(IP_FW_ZERO)", rulenum);
2365 failed = EX_UNAVAILABLE;
2366 } else if (!do_quiet)
2367 printf("Entry %d cleared\n", rulenum);
2369 errx(EX_USAGE, "invalid rule number ``%s''", *av);
2372 if (failed != EX_OK)
2377 resetlog(int ac, char *av[])
2385 /* clear all entries */
2386 if (setsockopt(ipfw_socket, IPPROTO_IP, IP_FW_RESETLOG, NULL, 0) < 0)
2387 err(EX_UNAVAILABLE, "setsockopt(IP_FW_RESETLOG)");
2389 printf("Logging counts reset.\n");
2396 if (isdigit(**av)) {
2397 rulenum = atoi(*av);
2399 if (setsockopt(ipfw_socket, IPPROTO_IP,
2400 IP_FW_RESETLOG, &rulenum, sizeof rulenum)) {
2401 warn("rule %u: setsockopt(IP_FW_RESETLOG)", rulenum);
2402 failed = EX_UNAVAILABLE;
2403 } else if (!do_quiet)
2404 printf("Entry %d logging count reset\n", rulenum);
2406 errx(EX_DATAERR, "invalid rule number ``%s''", *av);
2409 if (failed != EX_OK)
2416 int cmd = IP_FW_FLUSH;
2418 cmd = IP_DUMMYNET_FLUSH;
2419 } else if (do_nat) {
2420 cmd = IP_FW_NAT_FLUSH;
2425 printf("Are you sure? [yn] ");
2428 c = toupper(getc(stdin));
2429 while (c != '\n' && getc(stdin) != '\n')
2431 return; /* and do not flush */
2432 } while (c != 'Y' && c != 'N');
2433 if (c == 'N') /* user said no */
2436 if (do_set_x(cmd, NULL, 0) < 0 ) {
2438 errx(EX_USAGE, "pipe/queue in use");
2440 errx(EX_USAGE, "NAT configuration in use");
2442 errx(EX_USAGE, "do_set_x(IP_FWFLUSH) failed");
2445 printf("Flushed all %s.\n", do_pipe ? "pipes":
2446 (do_nat?"nat configurations":"rules"));
2451 str2addr(const char* str, struct in_addr* addr)
2455 if (inet_aton (str, addr))
2458 hp = gethostbyname (str);
2460 errx (1, "unknown host %s", str);
2462 memcpy (addr, hp->h_addr, sizeof (struct in_addr));
2466 str2portrange(const char* str, const char* proto, port_range *portRange)
2471 u_short loPort, hiPort;
2473 /* First see if this is a service, return corresponding port if so. */
2474 sp = getservbyname (str, proto);
2476 SETLOPORT(*portRange, ntohs(sp->s_port));
2477 SETNUMPORTS(*portRange, 1);
2481 /* Not a service, see if it's a single port or port range. */
2482 sep = strchr (str, '-');
2484 SETLOPORT(*portRange, strtol(str, &end, 10));
2487 SETNUMPORTS(*portRange, 1);
2491 /* Error in port range field. */
2492 errx (EX_DATAERR, "%s/%s: unknown service", str, proto);
2495 /* Port range, get the values and sanity check. */
2496 sscanf (str, "%hu-%hu", &loPort, &hiPort);
2497 SETLOPORT(*portRange, loPort);
2498 SETNUMPORTS(*portRange, 0); /* Error by default */
2499 if (loPort <= hiPort)
2500 SETNUMPORTS(*portRange, hiPort - loPort + 1);
2502 if (GETNUMPORTS(*portRange) == 0)
2503 errx (EX_DATAERR, "invalid port range %s", str);
2509 str2proto(const char* str)
2511 if (!strcmp (str, "tcp"))
2513 if (!strcmp (str, "udp"))
2515 errx (EX_DATAERR, "unknown protocol %s. Expected tcp or udp", str);
2519 str2addr_portrange (const char* str, struct in_addr* addr,
2520 char* proto, port_range *portRange)
2524 ptr = strchr (str, ':');
2526 errx (EX_DATAERR, "%s is missing port number", str);
2531 str2addr (str, addr);
2532 return str2portrange (ptr, proto, portRange);
2536 * Search for interface with name "ifn", and fill n accordingly:
2538 * n->ip ip address of interface "ifn"
2539 * n->if_name copy of interface name "ifn"
2542 set_addr_dynamic(const char *ifn, struct cfg_nat *n)
2544 struct if_msghdr *ifm;
2545 struct ifa_msghdr *ifam;
2546 struct sockaddr_dl *sdl;
2547 struct sockaddr_in *sin;
2548 char *buf, *lim, *next;
2557 mib[4] = NET_RT_IFLIST;
2561 * Get interface data.
2563 if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1)
2564 err(1, "iflist-sysctl-estimate");
2565 if ((buf = malloc(needed)) == NULL)
2566 errx(1, "malloc failed");
2567 if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1)
2568 err(1, "iflist-sysctl-get");
2571 * Loop through interfaces until one with
2572 * given name is found. This is done to
2573 * find correct interface index for routing
2574 * message processing.
2578 while (next < lim) {
2579 ifm = (struct if_msghdr *)next;
2580 next += ifm->ifm_msglen;
2581 if (ifm->ifm_version != RTM_VERSION) {
2583 warnx("routing message version %d "
2584 "not understood", ifm->ifm_version);
2587 if (ifm->ifm_type == RTM_IFINFO) {
2588 sdl = (struct sockaddr_dl *)(ifm + 1);
2589 if (strlen(ifn) == sdl->sdl_nlen &&
2590 strncmp(ifn, sdl->sdl_data, sdl->sdl_nlen) == 0) {
2591 ifIndex = ifm->ifm_index;
2592 ifMTU = ifm->ifm_data.ifi_mtu;
2598 errx(1, "unknown interface name %s", ifn);
2600 * Get interface address.
2603 while (next < lim) {
2604 ifam = (struct ifa_msghdr *)next;
2605 next += ifam->ifam_msglen;
2606 if (ifam->ifam_version != RTM_VERSION) {
2608 warnx("routing message version %d "
2609 "not understood", ifam->ifam_version);
2612 if (ifam->ifam_type != RTM_NEWADDR)
2614 if (ifam->ifam_addrs & RTA_IFA) {
2616 char *cp = (char *)(ifam + 1);
2618 for (i = 1; i < RTA_IFA; i <<= 1) {
2619 if (ifam->ifam_addrs & i)
2620 cp += SA_SIZE((struct sockaddr *)cp);
2622 if (((struct sockaddr *)cp)->sa_family == AF_INET) {
2623 sin = (struct sockaddr_in *)cp;
2629 errx(1, "%s: cannot get interface address", ifn);
2631 n->ip = sin->sin_addr;
2632 strncpy(n->if_name, ifn, IF_NAMESIZE);
2638 setup_redir_addr(char *spool_buf, int len, int *_ac, char ***_av)
2640 struct cfg_redir *r;
2641 struct cfg_spool *tmp;
2643 char tmp_spool_buf[NAT_BUF_LEN];
2644 int ac, i, space, lsnat;
2651 if (len >= SOF_REDIR) {
2652 r = (struct cfg_redir *)spool_buf;
2653 /* Skip cfg_redir at beginning of buf. */
2654 spool_buf = &spool_buf[SOF_REDIR];
2661 r->mode = REDIR_ADDR;
2662 /* Extract local address. */
2664 errx(EX_DATAERR, "redirect_addr: missing local address");
2666 sep = strchr(*av, ',');
2667 if (sep) { /* LSNAT redirection syntax. */
2668 r->laddr.s_addr = INADDR_NONE;
2669 /* Preserve av, copy spool servers to tmp_spool_buf. */
2670 strncpy(tmp_spool_buf, *av, strlen(*av)+1);
2673 str2addr(*av, &r->laddr);
2677 /* Extract public address. */
2679 errx(EX_DATAERR, "redirect_addr: missing public address");
2681 str2addr(*av, &r->paddr);
2684 /* Setup LSNAT server pool. */
2686 sep = strtok(tmp_spool_buf, ", ");
2687 while (sep != NULL) {
2688 tmp = (struct cfg_spool *)spool_buf;
2689 if (len < SOF_SPOOL)
2694 str2addr(sep, &tmp->addr);
2697 /* Point to the next possible cfg_spool. */
2698 spool_buf = &spool_buf[SOF_SPOOL];
2699 sep = strtok(NULL, ", ");
2705 errx(EX_DATAERR, "redirect_addr: buf is too small\n");
2709 setup_redir_port(char *spool_buf, int len, int *_ac, char ***_av)
2711 char **av, *sep, *protoName;
2712 char tmp_spool_buf[NAT_BUF_LEN];
2713 int ac, space, lsnat;
2714 struct cfg_redir *r;
2715 struct cfg_spool *tmp;
2716 u_short numLocalPorts;
2717 port_range portRange;
2725 if (len >= SOF_REDIR) {
2726 r = (struct cfg_redir *)spool_buf;
2727 /* Skip cfg_redir at beginning of buf. */
2728 spool_buf = &spool_buf[SOF_REDIR];
2735 r->mode = REDIR_PORT;
2740 errx (EX_DATAERR, "redirect_port: missing protocol");
2742 r->proto = str2proto(*av);
2747 * Extract local address.
2750 errx (EX_DATAERR, "redirect_port: missing local address");
2752 sep = strchr(*av, ',');
2753 /* LSNAT redirection syntax. */
2755 r->laddr.s_addr = INADDR_NONE;
2758 /* Preserve av, copy spool servers to tmp_spool_buf. */
2759 strncpy(tmp_spool_buf, *av, strlen(*av)+1);
2762 if (str2addr_portrange (*av, &r->laddr, protoName, &portRange) != 0)
2763 errx(EX_DATAERR, "redirect_port:"
2764 "invalid local port range");
2766 r->lport = GETLOPORT(portRange);
2767 numLocalPorts = GETNUMPORTS(portRange);
2772 * Extract public port and optionally address.
2775 errx (EX_DATAERR, "redirect_port: missing public port");
2777 sep = strchr (*av, ':');
2779 if (str2addr_portrange (*av, &r->paddr, protoName, &portRange) != 0)
2780 errx(EX_DATAERR, "redirect_port:"
2781 "invalid public port range");
2783 r->paddr.s_addr = INADDR_ANY;
2784 if (str2portrange(*av, protoName, &portRange) != 0)
2785 errx(EX_DATAERR, "redirect_port:"
2786 "invalid public port range");
2789 r->pport = GETLOPORT(portRange);
2790 r->pport_cnt = GETNUMPORTS(portRange);
2794 * Extract remote address and optionally port.
2797 * NB: isalpha(**av) => we've to check that next parameter is really an
2798 * option for this redirect entry, else stop here processing arg[cv].
2800 if (ac != 0 && !isalpha(**av)) {
2801 sep = strchr (*av, ':');
2803 if (str2addr_portrange (*av, &r->raddr,
2804 protoName, &portRange) != 0)
2805 errx(EX_DATAERR, "redirect_port:"
2806 "invalid remote port range");
2808 SETLOPORT(portRange, 0);
2809 SETNUMPORTS(portRange, 1);
2810 str2addr (*av, &r->raddr);
2814 SETLOPORT(portRange, 0);
2815 SETNUMPORTS(portRange, 1);
2816 r->raddr.s_addr = INADDR_ANY;
2818 r->rport = GETLOPORT(portRange);
2819 r->rport_cnt = GETNUMPORTS(portRange);
2822 * Make sure port ranges match up, then add the redirect ports.
2824 if (numLocalPorts != r->pport_cnt)
2825 errx(EX_DATAERR, "redirect_port:"
2826 "port ranges must be equal in size");
2828 /* Remote port range is allowed to be '0' which means all ports. */
2829 if (r->rport_cnt != numLocalPorts &&
2830 (r->rport_cnt != 1 || r->rport != 0))
2831 errx(EX_DATAERR, "redirect_port: remote port must"
2832 "be 0 or equal to local port range in size");
2835 * Setup LSNAT server pool.
2838 sep = strtok(tmp_spool_buf, ", ");
2839 while (sep != NULL) {
2840 tmp = (struct cfg_spool *)spool_buf;
2841 if (len < SOF_SPOOL)
2846 if (str2addr_portrange(sep,
2847 &tmp->addr, protoName, &portRange) != 0)
2848 errx(EX_DATAERR, "redirect_port:"
2849 "invalid local port range");
2850 if (GETNUMPORTS(portRange) != 1)
2851 errx(EX_DATAERR, "redirect_port: local port"
2852 "must be single in this context");
2853 tmp->port = GETLOPORT(portRange);
2855 /* Point to the next possible cfg_spool. */
2856 spool_buf = &spool_buf[SOF_SPOOL];
2857 sep = strtok(NULL, ", ");
2863 errx(EX_DATAERR, "redirect_port: buf is too small\n");
2867 setup_redir_proto(char *spool_buf, int len, int *_ac, char ***_av)
2869 struct protoent *protoent;
2870 struct cfg_redir *r;
2877 if (len >= SOF_REDIR) {
2878 r = (struct cfg_redir *)spool_buf;
2879 /* Skip cfg_redir at beginning of buf. */
2880 spool_buf = &spool_buf[SOF_REDIR];
2886 r->mode = REDIR_PROTO;
2891 errx(EX_DATAERR, "redirect_proto: missing protocol");
2893 protoent = getprotobyname(*av);
2894 if (protoent == NULL)
2895 errx(EX_DATAERR, "redirect_proto: unknown protocol %s", *av);
2897 r->proto = protoent->p_proto;
2902 * Extract local address.
2905 errx(EX_DATAERR, "redirect_proto: missing local address");
2907 str2addr(*av, &r->laddr);
2911 * Extract optional public address.
2914 r->paddr.s_addr = INADDR_ANY;
2915 r->raddr.s_addr = INADDR_ANY;
2917 /* see above in setup_redir_port() */
2918 if (!isalpha(**av)) {
2919 str2addr(*av, &r->paddr);
2923 * Extract optional remote address.
2925 /* see above in setup_redir_port() */
2926 if (ac != 0 && !isalpha(**av)) {
2927 str2addr(*av, &r->raddr);
2935 errx(EX_DATAERR, "redirect_proto: buf is too small\n");
2939 show_nat_config(char *buf) {
2941 struct cfg_redir *t;
2942 struct cfg_spool *s;
2944 int i, cnt, flag, off;
2946 n = (struct cfg_nat *)buf;
2949 printf("ipfw nat %u config", n->id);
2950 if (strlen(n->if_name) != 0)
2951 printf(" if %s", n->if_name);
2952 else if (n->ip.s_addr != 0)
2953 printf(" ip %s", inet_ntoa(n->ip));
2954 while (n->mode != 0) {
2955 if (n->mode & PKT_ALIAS_LOG) {
2957 n->mode &= ~PKT_ALIAS_LOG;
2958 } else if (n->mode & PKT_ALIAS_DENY_INCOMING) {
2960 n->mode &= ~PKT_ALIAS_DENY_INCOMING;
2961 } else if (n->mode & PKT_ALIAS_SAME_PORTS) {
2962 printf(" same_ports");
2963 n->mode &= ~PKT_ALIAS_SAME_PORTS;
2964 } else if (n->mode & PKT_ALIAS_UNREGISTERED_ONLY) {
2965 printf(" unreg_only");
2966 n->mode &= ~PKT_ALIAS_UNREGISTERED_ONLY;
2967 } else if (n->mode & PKT_ALIAS_RESET_ON_ADDR_CHANGE) {
2969 n->mode &= ~PKT_ALIAS_RESET_ON_ADDR_CHANGE;
2970 } else if (n->mode & PKT_ALIAS_REVERSE) {
2972 n->mode &= ~PKT_ALIAS_REVERSE;
2973 } else if (n->mode & PKT_ALIAS_PROXY_ONLY) {
2974 printf(" proxy_only");
2975 n->mode &= ~PKT_ALIAS_PROXY_ONLY;
2978 /* Print all the redirect's data configuration. */
2979 for (cnt = 0; cnt < n->redir_cnt; cnt++) {
2980 t = (struct cfg_redir *)&buf[off];
2984 printf(" redirect_addr");
2985 if (t->spool_cnt == 0)
2986 printf(" %s", inet_ntoa(t->laddr));
2988 for (i = 0; i < t->spool_cnt; i++) {
2989 s = (struct cfg_spool *)&buf[off];
2994 printf("%s", inet_ntoa(s->addr));
2997 printf(" %s", inet_ntoa(t->paddr));
3000 p = getprotobynumber(t->proto);
3001 printf(" redirect_port %s ", p->p_name);
3002 if (!t->spool_cnt) {
3003 printf("%s:%u", inet_ntoa(t->laddr), t->lport);
3004 if (t->pport_cnt > 1)
3005 printf("-%u", t->lport + t->pport_cnt - 1);
3007 for (i=0; i < t->spool_cnt; i++) {
3008 s = (struct cfg_spool *)&buf[off];
3011 printf("%s:%u", inet_ntoa(s->addr), s->port);
3016 if (t->paddr.s_addr)
3017 printf("%s:", inet_ntoa(t->paddr));
3018 printf("%u", t->pport);
3019 if (!t->spool_cnt && t->pport_cnt > 1)
3020 printf("-%u", t->pport + t->pport_cnt - 1);
3022 if (t->raddr.s_addr) {
3023 printf(" %s", inet_ntoa(t->raddr));
3025 printf(":%u", t->rport);
3026 if (!t->spool_cnt && t->rport_cnt > 1)
3027 printf("-%u", t->rport +
3033 p = getprotobynumber(t->proto);
3034 printf(" redirect_proto %s %s", p->p_name,
3035 inet_ntoa(t->laddr));
3036 if (t->paddr.s_addr != 0) {
3037 printf(" %s", inet_ntoa(t->paddr));
3038 if (t->raddr.s_addr)
3039 printf(" %s", inet_ntoa(t->raddr));
3043 errx(EX_DATAERR, "unknown redir mode");
3052 show_nat(int ac, char **av) {
3054 struct cfg_redir *e;
3055 int i, nbytes, nalloc, size;
3056 int nat_cnt, redir_cnt, nat_id;
3068 nat_id = strtoul(*av, NULL, 10);
3071 while (nbytes >= nalloc) {
3072 nalloc = nalloc * 2;
3074 if ((data = realloc(data, nbytes)) == NULL) {
3075 err(EX_OSERR, "realloc");
3077 if (do_get_x(IP_FW_NAT_GET, data, &nbytes) < 0) {
3078 err(EX_OSERR, "do_get_x(IP_FW_NAT_GET)");
3086 nat_cnt = *((int *)data);
3087 for (i = sizeof(nat_cnt); nat_cnt; nat_cnt--) {
3088 n = (struct cfg_nat *)&data[i];
3089 if (n->id >= 0 && n->id <= IPFW_DEFAULT_RULE) {
3090 if (nat_id == 0 || n->id == nat_id)
3091 show_nat_config(&data[i]);
3093 i += sizeof(struct cfg_nat);
3094 for (redir_cnt = 0; redir_cnt < n->redir_cnt; redir_cnt++) {
3095 e = (struct cfg_redir *)&data[i];
3096 i += sizeof(struct cfg_redir) +
3097 e->spool_cnt * sizeof(struct cfg_spool);
3103 get_kern_boottime(void)
3105 struct timeval boottime;
3109 mib[1] = KERN_BOOTTIME;
3110 size = sizeof(boottime);
3111 if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 &&
3112 boottime.tv_sec != 0) {
3113 return boottime.tv_sec;
3119 show_nat_state(int ac, char **av)
3132 nat_id = strtoul(*av, NULL, 10);
3135 while (nbytes >= nalloc) {
3136 nalloc = nalloc * 2;
3138 if ((data = realloc(data, nbytes)) == NULL) {
3139 err(EX_OSERR, "realloc");
3141 memcpy(data, &nat_id, sizeof(int));
3142 if (do_get_x(IP_FW_NAT_LOG, data, &nbytes) < 0) {
3143 err(EX_OSERR, "do_get_x(IP_FW_NAT_GET_STATE)");
3148 struct ipfw_ioc_nat_state *nat_state;
3149 nat_state =(struct ipfw_ioc_nat_state *)data;
3150 int count = nbytes / sizeof( struct ipfw_ioc_nat_state);
3152 uptime_sec = get_kern_boottime();
3153 for (i = 0; i < count; i ++) {
3154 struct protoent *pe = getprotobynumber(nat_state->link_type);
3155 printf("%s ", pe->p_name);
3156 printf("%s:%hu => ",inet_ntoa(nat_state->src_addr),
3157 htons(nat_state->src_port));
3158 printf("%s:%hu",inet_ntoa(nat_state->alias_addr),
3159 htons(nat_state->alias_port));
3160 printf(" -> %s:%hu ",inet_ntoa(nat_state->dst_addr),
3161 htons(nat_state->dst_port));
3164 time_t t = _long_to_time(uptime_sec + nat_state->timestamp);
3165 strcpy(timestr, ctime(&t));
3166 *strchr(timestr, '\n') = '\0';
3167 printf("%s ", timestr);
3168 } else if (do_time == 2) {
3169 printf( "%10u ", uptime_sec + nat_state->timestamp);
3177 * do_set_x - extended version og do_set
3178 * insert a x_header in the beginning of the rule buf
3179 * and call setsockopt() with IP_FW_X.
3182 do_set_x(int optname, void *rule, int optlen)
3186 ip_fw_x_header *x_header;
3187 if (ipfw_socket < 0)
3188 err(EX_UNAVAILABLE, "socket not avaialble");
3189 len = optlen + sizeof(ip_fw_x_header);
3190 newbuf = malloc(len);
3192 err(EX_OSERR, "malloc newbuf in do_set_x");
3194 x_header = (ip_fw_x_header *)newbuf;
3195 x_header->opcode = optname;
3196 /* copy the rule into the newbuf, just after the x_header*/
3197 bcopy(rule, ++x_header, optlen);
3198 return setsockopt(ipfw_socket, IPPROTO_IP, IP_FW_X, newbuf, len);
3205 do_get_x(int optname, void *rule, int *optlen)
3207 int len, *newbuf, retval;
3209 ip_fw_x_header *x_header;
3210 if (ipfw_socket < 0)
3211 err(EX_UNAVAILABLE, "socket not avaialble");
3212 len = *optlen + sizeof(ip_fw_x_header);
3213 newbuf = malloc(len);
3215 err(EX_OSERR, "malloc newbuf in do_get_x");
3217 x_header = (ip_fw_x_header *)newbuf;
3218 x_header->opcode = optname;
3219 /* copy the rule into the newbuf, just after the x_header*/
3220 bcopy(rule, ++x_header, *optlen);
3221 retval = getsockopt(ipfw_socket, IPPROTO_IP, IP_FW_X, newbuf, &len);
3222 bcopy(newbuf, rule, len);
3228 config_nat(int ac, char **av)
3230 struct cfg_nat *n; /* Nat instance configuration. */
3231 int i, len, off, tok;
3232 char *id, buf[NAT_BUF_LEN]; /* Buffer for serialized data. */
3235 /* Offset in buf: save space for n at the beginning. */
3236 off = sizeof(struct cfg_nat);
3237 memset(buf, 0, sizeof(buf));
3238 n = (struct cfg_nat *)buf;
3242 if (ac && isdigit(**av)) {
3248 errx(EX_DATAERR, "missing nat id");
3250 errx(EX_DATAERR, "missing option");
3253 tok = match_token(nat_params, *av);
3258 errx(EX_DATAERR, "missing option");
3259 if (!inet_aton(av[0], &(n->ip)))
3260 errx(EX_DATAERR, "bad ip address ``%s''",
3266 errx(EX_DATAERR, "missing option");
3267 set_addr_dynamic(av[0], n);
3271 n->mode |= PKT_ALIAS_LOG;
3274 n->mode |= PKT_ALIAS_DENY_INCOMING;
3276 case TOK_SAME_PORTS:
3277 n->mode |= PKT_ALIAS_SAME_PORTS;
3279 case TOK_UNREG_ONLY:
3280 n->mode |= PKT_ALIAS_UNREGISTERED_ONLY;
3282 case TOK_RESET_ADDR:
3283 n->mode |= PKT_ALIAS_RESET_ON_ADDR_CHANGE;
3286 n->mode |= PKT_ALIAS_REVERSE;
3288 case TOK_PROXY_ONLY:
3289 n->mode |= PKT_ALIAS_PROXY_ONLY;
3292 * All the setup_redir_* functions work directly in the final
3293 * buffer, see above for details.
3295 case TOK_REDIR_ADDR:
3296 case TOK_REDIR_PORT:
3297 case TOK_REDIR_PROTO:
3299 case TOK_REDIR_ADDR:
3300 i = setup_redir_addr(&buf[off], len, &ac, &av);
3302 case TOK_REDIR_PORT:
3303 i = setup_redir_port(&buf[off], len, &ac, &av);
3305 case TOK_REDIR_PROTO:
3306 i = setup_redir_proto(&buf[off], len, &ac, &av);
3314 errx(EX_DATAERR, "unrecognised option ``%s''", av[-1]);
3317 i = do_set_x(IP_FW_NAT_CFG, buf, off);
3319 err(1, "do_set_x(%s)", "IP_FW_NAT_CFG");
3321 /* After every modification, we show the resultant rule. */
3323 char *_av[] = {"config", id};
3329 ipfw_main(int ac, char **av)
3336 /* Set the force flag for non-interactive processes */
3337 do_force = !isatty(STDIN_FILENO);
3339 optind = optreset = 1;
3340 while ((ch = getopt(ac, av, "hs:acdDefNStTv")) != -1)
3342 case 'h': /* help */
3344 break; /* NOTREACHED */
3346 case 's': /* sort */
3347 do_sort = atoi(optarg);
3389 NEED1("bad arguments, for usage summary ``ipfw''");
3392 * optional: pipe or queue or nat
3396 if (!strncmp(*av, "nat", strlen(*av)))
3398 else if (!strncmp(*av, "pipe", strlen(*av))) {
3400 } else if (!strncmp(*av, "queue", strlen(*av))) {
3403 NEED1("missing command");
3406 * for pipes and queues and nat we normally say 'pipe NN config'
3407 * but the code is easier to parse as 'pipe config NN'
3408 * so we swap the two arguments.
3410 if ((do_pipe || do_nat) && ac > 2 && isdigit(*(av[1]))) {
3416 if (!strncmp(*av, "add", strlen(*av))) {
3419 } else if (!strncmp(*av, "delete", strlen(*av))) {
3420 delete_rules(ac, av);
3421 } else if (!strncmp(*av, "flush", strlen(*av))) {
3423 } else if (!strncmp(*av, "list", strlen(*av))) {
3426 } else if (!strncmp(*av, "show", strlen(*av))) {
3430 } else if (!strncmp(*av, "zero", strlen(*av))) {
3432 } else if (!strncmp(*av, "set", strlen(*av))) {
3433 sets_handler(ac, av);
3434 } else if (!strncmp(*av, "module", strlen(*av))) {
3436 if (!strncmp(*av, "show", strlen(*av)) ||
3437 !strncmp(*av, "show", strlen(*av))) {
3438 list_modules(ac, av);
3440 errx(EX_USAGE, "bad ipfw module command `%s'", *av);
3442 } else if (!strncmp(*av, "resetlog", strlen(*av))) {
3444 } else if (!strncmp(*av, "log", strlen(*av))) {
3446 if (!strncmp(*av, "reset", strlen(*av))) {
3448 } else if (!strncmp(*av, "off", strlen(*av))) {
3450 } else if (!strncmp(*av, "on", strlen(*av))) {
3453 errx(EX_USAGE, "bad command `%s'", *av);
3455 } else if (!strncmp(*av, "nat", strlen(*av))) {
3457 if (!strncmp(*av, "config", strlen(*av))) {
3459 } else if (!strncmp(*av, "flush", strlen(*av))) {
3461 } else if (!strncmp(*av, "show", strlen(*av)) ||
3462 !strncmp(*av, "list", strlen(*av))) {
3463 if (ac > 2 && isdigit(*(av[1]))) {
3469 if (!strncmp(*av, "config", strlen(*av))) {
3471 } else if (!strncmp(*av, "state", strlen(*av))) {
3472 show_nat_state(ac,av);
3475 "bad nat show command `%s'", *av);
3477 } else if (!strncmp(*av, "delete", strlen(*av))) {
3478 delete_nat_config(ac, av);
3480 errx(EX_USAGE, "bad ipfw nat command `%s'", *av);
3482 } else if (!strncmp(*av, "pipe", strlen(*av)) ||
3483 !strncmp(*av, "queue", strlen(*av))) {
3485 if (!strncmp(*av, "config", strlen(*av))) {
3486 config_dummynet(ac, av);
3487 } else if (!strncmp(*av, "flush", strlen(*av))) {
3489 } else if (!strncmp(*av, "show", strlen(*av))) {
3490 show_dummynet(ac, av);
3492 errx(EX_USAGE, "bad ipfw pipe command `%s'", *av);
3494 } else if (!strncmp(*av, "state", strlen(*av))) {
3496 if (!strncmp(*av, "add", strlen(*av))) {
3498 } else if (!strncmp(*av, "delete", strlen(*av))) {
3499 delete_state(ac, av);
3500 } else if (!strncmp(*av, "flush", strlen(*av))) {
3501 flush_state(ac, av);
3502 } else if (!strncmp(*av, "list", strlen(*av))) {
3505 } else if (!strncmp(*av, "show", strlen(*av))) {
3510 errx(EX_USAGE, "bad ipfw state command `%s'", *av);
3512 } else if (!strncmp(*av, "table", strlen(*av))) {
3513 if (ac > 2 && isdigit(*(av[1]))) {
3519 if (!strncmp(*av, "append", strlen(*av))) {
3520 table_append(ac, av);
3521 } else if (!strncmp(*av, "remove", strlen(*av))) {
3522 table_remove(ac, av);
3523 } else if (!strncmp(*av, "flush", strlen(*av))) {
3524 table_flush(ac, av);
3525 } else if (!strncmp(*av, "list", strlen(*av))) {
3527 } else if (!strncmp(*av, "show", strlen(*av))) {
3529 } else if (!strncmp(*av, "type", strlen(*av))) {
3530 table_create(ac, av);
3531 } else if (!strncmp(*av, "delete", strlen(*av))) {
3532 table_delete(ac, av);
3533 } else if (!strncmp(*av, "test", strlen(*av))) {
3535 } else if (!strncmp(*av, "name", strlen(*av))) {
3536 table_rename(ac, av);
3538 errx(EX_USAGE, "bad ipfw table command `%s'", *av);
3542 errx(EX_USAGE, "bad ipfw command `%s'", *av);
3548 ipfw_readfile(int ac, char *av[])
3551 char *a, *p, *args[MAX_ARGS], *cmd = NULL;
3553 int i=0, lineno=0, qflag=0, pflag=0, status;
3558 while ((c = getopt(ac, av, "D:U:p:q")) != -1) {
3562 errx(EX_USAGE, "-D requires -p");
3563 if (i > MAX_ARGS - 2)
3564 errx(EX_USAGE, "too many -D or -U options");
3571 errx(EX_USAGE, "-U requires -p");
3572 if (i > MAX_ARGS - 2)
3573 errx(EX_USAGE, "too many -D or -U options");
3590 errx(EX_USAGE, "bad arguments, for usage"
3591 " summary ``ipfw''");
3598 errx(EX_USAGE, "extraneous filename arguments");
3600 if ((f = fopen(av[0], "r")) == NULL)
3601 err(EX_UNAVAILABLE, "fopen: %s", av[0]);
3604 /* pipe through preprocessor (cpp or m4) */
3609 if (pipe(pipedes) == -1)
3610 err(EX_OSERR, "cannot create pipe");
3612 switch ((preproc = fork())) {
3614 err(EX_OSERR, "cannot fork");
3618 if (dup2(fileno(f), 0) == -1 ||
3619 dup2(pipedes[1], 1) == -1) {
3620 err(EX_OSERR, "dup2()");
3626 err(EX_OSERR, "execvp(%s) failed", cmd);
3632 if ((f = fdopen(pipedes[0], "r")) == NULL) {
3633 int savederrno = errno;
3635 kill(preproc, SIGTERM);
3637 err(EX_OSERR, "fdopen()");
3642 while (fgets(buf, BUFSIZ, f)) {
3644 sprintf(linename, "Line %d", lineno);
3649 if ((p = strchr(buf, '#')) != NULL)
3654 for (a = strtok(buf, WHITESP); a && i < MAX_ARGS;
3655 a = strtok(NULL, WHITESP), i++) {
3659 if (i == (qflag? 2: 1))
3662 errx(EX_USAGE, "%s: too many arguments", linename);
3669 if (waitpid(preproc, &status, 0) == -1)
3670 errx(EX_OSERR, "waitpid()");
3671 if (WIFEXITED(status) && WEXITSTATUS(status) != EX_OK)
3672 errx(EX_UNAVAILABLE, "preprocessor exited with status %d",
3673 WEXITSTATUS(status));
3674 else if (WIFSIGNALED(status))
3675 errx(EX_UNAVAILABLE, "preprocessor exited with signal %d",
3681 main(int ac, char *av[])
3683 ipfw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
3684 if (ipfw_socket < 0)
3685 err(EX_UNAVAILABLE, "socket");
3687 memset(keywords, 0, sizeof(struct ipfw_keyword) * KEYWORD_SIZE);
3688 memset(mappings, 0, sizeof(struct ipfw_mapping) * MAPPING_SIZE);
3690 prepare_default_funcs();
3692 if (ac > 1 && av[ac - 1][0] == '/' && access(av[ac - 1], R_OK) == 0)
3693 ipfw_readfile(ac, av);