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
;
293 parse_deny(ipfw_insn
**cmd
, int *ac
, char **av
[])
295 (*cmd
)->opcode
= O_BASIC_DENY
;
296 (*cmd
)->module
= MODULE_BASIC_ID
;
297 (*cmd
)->len
= (*cmd
)->len
|LEN_OF_IPFWINSN
;
302 show_accept(ipfw_insn
*cmd
, int show_or
)
308 show_deny(ipfw_insn
*cmd
, int show_or
)
317 init_module mod_init_func
;
319 char module_lib_file
[50];
320 void *module_str
= NULL
;
323 if ((module_str
= realloc(module_str
, len
)) == NULL
)
324 err(EX_OSERR
, "realloc");
326 get_modules(module_str
, len
);
328 const char s
[2] = ",";
330 token
= strtok(module_str
, s
);
331 while (token
!= NULL
) {
332 sprintf(module_lib_file
, IPFW_LIB_PATH
, token
);
333 token
= strtok(NULL
, s
);
334 module_lib
= dlopen(module_lib_file
, RTLD_LAZY
);
336 fprintf(stderr
, "Couldn't open %s: %s\n",
337 module_lib_file
, dlerror());
340 mod_init_func
= dlsym(module_lib
, "load_module");
341 if ((error
= dlerror()))
343 fprintf(stderr
, "Couldn't find init function: %s\n", error
);
346 (*mod_init_func
)((register_func
)register_ipfw_func
,
347 (register_keyword
)register_ipfw_keyword
);
352 prepare_default_funcs(void)
355 register_ipfw_keyword(MODULE_BASIC_ID
, O_BASIC_ACCEPT
, "allow", ACTION
);
356 register_ipfw_keyword(MODULE_BASIC_ID
, O_BASIC_ACCEPT
, "accept", ACTION
);
357 register_ipfw_func(MODULE_BASIC_ID
, O_BASIC_ACCEPT
,
358 (parser_func
)parse_accept
, (shower_func
)show_accept
);
360 register_ipfw_keyword(MODULE_BASIC_ID
, O_BASIC_DENY
, "deny", ACTION
);
361 register_ipfw_keyword(MODULE_BASIC_ID
, O_BASIC_DENY
, "reject", ACTION
);
362 register_ipfw_func(MODULE_BASIC_ID
, O_BASIC_DENY
,
363 (parser_func
)parse_deny
, (shower_func
)show_deny
);
367 register_ipfw_keyword(int module
, int opcode
, char *word
, int type
)
369 struct ipfw_keyword
*tmp
;
373 if (tmp
->type
== NONE
) {
374 strcpy(tmp
->word
, word
);
375 tmp
->module
= module
;
376 tmp
->opcode
= opcode
;
380 if (strcmp(tmp
->word
, word
) == 0)
381 errx(EX_USAGE
, "keyword `%s' exists", word
);
389 register_ipfw_func(int module
, int opcode
, parser_func parser
, shower_func shower
)
391 struct ipfw_mapping
*tmp
;
395 if (tmp
->type
== NONE
) {
396 tmp
->module
= module
;
397 tmp
->opcode
= opcode
;
398 tmp
->parser
= parser
;
399 tmp
->shower
= shower
;
403 if (tmp
->opcode
== opcode
&& tmp
->module
== module
) {
404 errx(EX_USAGE
, "func `%d' of module `%d' exists",
415 * this func need to check whether 'or' need to be printed,
416 * when the filter is the first filter with 'or' when dont print
417 * when not first and same as previous, then print or and no filter name
418 * when not first but different from previous, print name without 'or'
419 * show_or = 1: show or and ignore filter name
420 * show_or = 0: show filter name ignore or
422 void prev_show_chk(ipfw_insn
*cmd
, uint8_t *prev_module
, uint8_t *prev_opcode
,
425 if (cmd
->len
& F_OR
) {
426 if (*prev_module
== 0 && *prev_opcode
== 0) {
427 /* first cmd with 'or' flag */
429 *prev_module
= cmd
->module
;
430 *prev_opcode
= cmd
->opcode
;
431 } else if (cmd
->module
== *prev_module
&&
432 cmd
->opcode
== *prev_opcode
) {
433 /* cmd same as previous, same module and opcode */
436 /* cmd different from prev*/
438 *prev_module
= cmd
->module
;
439 *prev_opcode
= cmd
->opcode
;
450 * word can be: proto from to other
454 * other show all other filters
456 int show_filter(ipfw_insn
*cmd
, char *word
, int type
)
458 struct ipfw_keyword
*k
;
459 struct ipfw_mapping
*m
;
462 uint8_t prev_module
, prev_opcode
;
466 for (i
= 1; i
< KEYWORD_SIZE
; i
++, k
++) {
467 if (k
->type
== type
) {
468 if (k
->module
== cmd
->module
&&
469 k
->opcode
== cmd
->opcode
) {
470 for (j
= 1; j
< MAPPING_SIZE
; j
++, m
++) {
471 if (m
->type
== IN_USE
&&
472 k
->module
== m
->module
&&
473 k
->opcode
== m
->opcode
) {
474 prev_show_chk(cmd
, &prev_module
,
475 &prev_opcode
, &show_or
);
476 if (cmd
->len
& F_NOT
)
491 show_rules(struct ipfw_ioc_rule
*rule
, int pcwidth
, int bcwidth
)
493 static int twidth
= 0;
497 u_int32_t set_disable
= rule
->set_disable
;
499 if (set_disable
& (1 << rule
->set
)) { /* disabled */
503 printf("# DISABLED ");
505 printf("%05u ", rule
->rulenum
);
508 printf("%*ju %*ju ", pcwidth
, (uintmax_t)rule
->pcnt
, bcwidth
,
509 (uintmax_t)rule
->bcnt
);
515 strcpy(timestr
, ctime((time_t *)&twidth
));
516 *strchr(timestr
, '\n') = '\0';
517 twidth
= strlen(timestr
);
519 if (rule
->timestamp
) {
520 time_t t
= _long_to_time(rule
->timestamp
);
522 strcpy(timestr
, ctime(&t
));
523 *strchr(timestr
, '\n') = '\0';
524 printf("%s ", timestr
);
526 printf("%*s ", twidth
, " ");
528 } else if (do_time
== 2) {
529 printf( "%10u ", rule
->timestamp
);
533 printf("set %d ", rule
->set
);
536 struct ipfw_keyword
*k
;
537 struct ipfw_mapping
*m
;
538 shower_func fn
, comment_fn
= NULL
;
539 ipfw_insn
*comment_cmd
;
543 * show others and actions
545 for (l
= rule
->cmd_len
- rule
->act_ofs
, cmd
= ACTION_PTR(rule
);
546 l
> 0; l
-= F_LEN(cmd
),
547 cmd
= (ipfw_insn
*)((uint32_t *)cmd
+ F_LEN(cmd
))) {
550 for (i
= 1; i
< KEYWORD_SIZE
; i
++, k
++) {
551 if ( k
->module
== cmd
->module
&& k
->opcode
== cmd
->opcode
) {
552 for (j
= 1; j
< MAPPING_SIZE
; j
++, m
++) {
553 if (m
->type
== IN_USE
&&
554 m
->module
== cmd
->module
&&
555 m
->opcode
== cmd
->opcode
) {
556 if (cmd
->module
== MODULE_BASIC_ID
&&
557 cmd
->opcode
== O_BASIC_COMMENT
) {
558 comment_fn
= m
->shower
;
564 if (cmd
->module
== MODULE_BASIC_ID
&&
566 O_BASIC_CHECK_STATE
) {
581 for (l
= rule
->act_ofs
, cmd
= rule
->cmd
; l
> 0; l
-= F_LEN(cmd
),
582 cmd
= (ipfw_insn
*)((uint32_t *)cmd
+ F_LEN(cmd
))) {
583 changed
= show_filter(cmd
, "proto", PROTO
);
585 if (!changed
&& !do_quiet
)
592 for (l
= rule
->act_ofs
, cmd
= rule
->cmd
; l
> 0; l
-= F_LEN(cmd
),
593 cmd
= (ipfw_insn
*)((uint32_t *)cmd
+ F_LEN(cmd
))) {
594 changed
= show_filter(cmd
, "from", FROM
);
596 if (!changed
&& !do_quiet
)
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
, "to", TO
);
607 if (!changed
&& !do_quiet
)
613 for (l
= rule
->act_ofs
, cmd
= rule
->cmd
, m
= mappings
;
614 l
> 0; l
-= F_LEN(cmd
),
615 cmd
=(ipfw_insn
*)((uint32_t *)cmd
+ F_LEN(cmd
))) {
616 show_filter(cmd
, "other", FILTER
);
619 /* show the comment in the end */
620 if (comment_fn
!= NULL
) {
621 (*comment_fn
)(comment_cmd
, 0);
628 show_states(struct ipfw_ioc_state
*d
, int pcwidth
, int bcwidth
)
633 printf("%05u ", d
->rulenum
);
635 printf("%*ju %*ju ", pcwidth
, (uintmax_t)d
->pcnt
,
636 bcwidth
, (uintmax_t)d
->bcnt
);
640 /* state->timestamp */
642 time_t t
= _long_to_time(d
->timestamp
);
643 strcpy(timestr
, ctime(&t
));
644 *strchr(timestr
, '\n') = '\0';
645 printf(" (%s", timestr
);
647 /* state->lifetime */
648 printf(" %ds", d
->lifetime
);
652 t
= _long_to_time(d
->expiry
);
653 strcpy(timestr
, ctime(&t
));
654 *strchr(timestr
, '\n') = '\0';
655 printf(" %s)", timestr
);
660 } else if (do_time
== 2) {
661 printf("(%u %ds %u) ", d
->timestamp
, d
->lifetime
, d
->expiry
);
664 if ((pe
= getprotobynumber(d
->flow_id
.proto
)) != NULL
)
665 printf(" %s", pe
->p_name
);
667 printf(" proto %u", d
->flow_id
.proto
);
669 a
.s_addr
= htonl(d
->flow_id
.src_ip
);
670 printf(" %s %d", inet_ntoa(a
), d
->flow_id
.src_port
);
672 a
.s_addr
= htonl(d
->flow_id
.dst_ip
);
673 printf(" <-> %s %d", inet_ntoa(a
), d
->flow_id
.dst_port
);
674 printf(" CPU %d", d
->cpuid
);
679 sort_q(const void *pa
, const void *pb
)
681 int rev
= (do_sort
< 0);
682 int field
= rev
? -do_sort
: do_sort
;
684 const struct dn_ioc_flowqueue
*a
= pa
;
685 const struct dn_ioc_flowqueue
*b
= pb
;
689 res
= a
->len
- b
->len
;
692 res
= a
->len_bytes
- b
->len_bytes
;
695 case 3: /* tot pkts */
696 res
= a
->tot_pkts
- b
->tot_pkts
;
699 case 4: /* tot bytes */
700 res
= a
->tot_bytes
- b
->tot_bytes
;
707 return (int)(rev
? res
: -res
);
711 show_queues(struct dn_ioc_flowset
*fs
, struct dn_ioc_flowqueue
*q
)
715 printf("mask: 0x%02x 0x%08x/0x%04x -> 0x%08x/0x%04x\n",
716 fs
->flow_mask
.u
.ip
.proto
,
717 fs
->flow_mask
.u
.ip
.src_ip
, fs
->flow_mask
.u
.ip
.src_port
,
718 fs
->flow_mask
.u
.ip
.dst_ip
, fs
->flow_mask
.u
.ip
.dst_port
);
719 if (fs
->rq_elements
== 0)
722 printf("BKT Prot ___Source IP/port____ "
723 "____Dest. IP/port____ Tot_pkt/bytes Pkt/Byte Drp\n");
725 heapsort(q
, fs
->rq_elements
, sizeof(*q
), sort_q
);
726 for (l
= 0; l
< fs
->rq_elements
; l
++) {
730 ina
.s_addr
= htonl(q
[l
].id
.u
.ip
.src_ip
);
731 printf("%3d ", q
[l
].hash_slot
);
732 pe
= getprotobynumber(q
[l
].id
.u
.ip
.proto
);
734 printf("%-4s ", pe
->p_name
);
736 printf("%4u ", q
[l
].id
.u
.ip
.proto
);
738 inet_ntoa(ina
), q
[l
].id
.u
.ip
.src_port
);
739 ina
.s_addr
= htonl(q
[l
].id
.u
.ip
.dst_ip
);
741 inet_ntoa(ina
), q
[l
].id
.u
.ip
.dst_port
);
742 printf("%4ju %8ju %2u %4u %3u\n",
743 (uintmax_t)q
[l
].tot_pkts
, (uintmax_t)q
[l
].tot_bytes
,
744 q
[l
].len
, q
[l
].len_bytes
, q
[l
].drops
);
746 printf(" S %20ju F %20ju\n",
747 (uintmax_t)q
[l
].S
, (uintmax_t)q
[l
].F
);
752 show_flowset_parms(struct dn_ioc_flowset
*fs
, char *prefix
)
756 char red
[90]; /* Display RED parameters */
760 if (fs
->flags_fs
& DN_QSIZE_IS_BYTES
) {
762 sprintf(qs
, "%d KB", l
/ 1024);
764 sprintf(qs
, "%d B", l
);
766 sprintf(qs
, "%3d sl.", l
);
768 sprintf(plr
, "plr %f", 1.0 * fs
->plr
/ (double)(0x7fffffff));
771 if (fs
->flags_fs
& DN_IS_RED
) /* RED parameters */
773 "\n\t %cRED w_q %f min_th %d max_th %d max_p %f",
774 (fs
->flags_fs
& DN_IS_GENTLE_RED
) ? 'G' : ' ',
775 1.0 * fs
->w_q
/ (double)(1 << SCALE_RED
),
776 SCALE_VAL(fs
->min_th
),
777 SCALE_VAL(fs
->max_th
),
778 1.0 * fs
->max_p
/ (double)(1 << SCALE_RED
));
780 sprintf(red
, "droptail");
782 printf("%s %s%s %d queues (%d buckets) %s\n",
783 prefix
, qs
, plr
, fs
->rq_elements
, fs
->rq_size
, red
);
787 show_pipes(void *data
, int nbytes
, int ac
, char *av
[])
791 struct dn_ioc_pipe
*p
= (struct dn_ioc_pipe
*)data
;
792 struct dn_ioc_flowset
*fs
;
793 struct dn_ioc_flowqueue
*q
;
797 rulenum
= strtoul(*av
++, NULL
, 10);
800 for (; nbytes
>= sizeof(*p
); p
= (struct dn_ioc_pipe
*)next
) {
801 double b
= p
->bandwidth
;
805 if (p
->fs
.fs_type
!= DN_IS_PIPE
)
806 break; /* done with pipes, now queues */
809 * compute length, as pipe have variable size
811 l
= sizeof(*p
) + p
->fs
.rq_elements
* sizeof(*q
);
812 next
= (void *)p
+ l
;
815 if (rulenum
!= 0 && rulenum
!= p
->pipe_nr
)
822 sprintf(buf
, "unlimited");
823 else if (b
>= 1000000)
824 sprintf(buf
, "%7.3f Mbit/s", b
/1000000);
826 sprintf(buf
, "%7.3f Kbit/s", b
/1000);
828 sprintf(buf
, "%7.3f bit/s ", b
);
830 sprintf(prefix
, "%05d: %s %4d ms ",
831 p
->pipe_nr
, buf
, p
->delay
);
832 show_flowset_parms(&p
->fs
, prefix
);
834 printf(" V %20ju\n", (uintmax_t)p
->V
>> MY_M
);
836 q
= (struct dn_ioc_flowqueue
*)(p
+1);
837 show_queues(&p
->fs
, q
);
840 for (fs
= next
; nbytes
>= sizeof(*fs
); fs
= next
) {
843 if (fs
->fs_type
!= DN_IS_QUEUE
)
845 l
= sizeof(*fs
) + fs
->rq_elements
* sizeof(*q
);
846 next
= (void *)fs
+ l
;
848 q
= (struct dn_ioc_flowqueue
*)(fs
+1);
849 sprintf(prefix
, "q%05d: weight %d pipe %d ",
850 fs
->fs_nr
, fs
->weight
, fs
->parent_nr
);
851 show_flowset_parms(fs
, prefix
);
857 * This one handles all set-related commands
858 * ipfw set { show | enable | disable }
860 * ipfw set move X to Y
861 * ipfw set move rule X to Y
864 sets_handler(int ac
, char *av
[])
866 u_int32_t set_disable
, masks
[2];
868 u_int8_t cmd
, new_set
;
873 errx(EX_USAGE
, "set needs command");
874 if (!strncmp(*av
, "show", strlen(*av
)) ) {
880 while (nbytes
>= nalloc
) {
881 nalloc
= nalloc
* 2+321;
884 if ((data
= malloc(nbytes
)) == NULL
) {
885 err(EX_OSERR
, "malloc");
887 } else if ((data
= realloc(data
, nbytes
)) == NULL
) {
888 err(EX_OSERR
, "realloc");
890 if (do_get_x(IP_FW_GET
, data
, &nbytes
) < 0) {
891 err(EX_OSERR
, "getsockopt(IP_FW_GET)");
894 set_disable
= ((struct ipfw_ioc_rule
*)data
)->set_disable
;
895 for (i
= 0, msg
= "disable" ; i
< 31; i
++)
896 if ( (set_disable
& (1<<i
))) {
897 printf("%s %d", msg
, i
);
900 msg
= (set_disable
) ? " enable" : "enable";
901 for (i
= 0; i
< 31; i
++)
902 if ( !(set_disable
& (1<<i
))) {
903 printf("%s %d", msg
, i
);
907 } else if (!strncmp(*av
, "swap", strlen(*av
))) {
910 errx(EX_USAGE
, "set swap needs 2 set numbers\n");
911 rulenum
= atoi(av
[0]);
912 new_set
= atoi(av
[1]);
913 if (!isdigit(*(av
[0])) || rulenum
> 30)
914 errx(EX_DATAERR
, "invalid set number %s\n", av
[0]);
915 if (!isdigit(*(av
[1])) || new_set
> 30)
916 errx(EX_DATAERR
, "invalid set number %s\n", av
[1]);
917 masks
[0] = (4 << 24) | (new_set
<< 16) | (rulenum
);
918 i
= do_set_x(IP_FW_DEL
, masks
, sizeof(u_int32_t
));
919 } else if (!strncmp(*av
, "move", strlen(*av
))) {
921 if (ac
&& !strncmp(*av
, "rule", strlen(*av
))) {
926 if (ac
!= 3 || strncmp(av
[1], "to", strlen(*av
)))
927 errx(EX_USAGE
, "syntax: set move [rule] X to Y\n");
928 rulenum
= atoi(av
[0]);
929 new_set
= atoi(av
[2]);
930 if (!isdigit(*(av
[0])) || (cmd
== 3 && rulenum
> 30) ||
931 (cmd
== 2 && rulenum
== 65535) )
932 errx(EX_DATAERR
, "invalid source number %s\n", av
[0]);
933 if (!isdigit(*(av
[2])) || new_set
> 30)
934 errx(EX_DATAERR
, "invalid dest. set %s\n", av
[1]);
935 masks
[0] = (cmd
<< 24) | (new_set
<< 16) | (rulenum
);
936 i
= do_set_x(IP_FW_DEL
, masks
, sizeof(u_int32_t
));
937 } else if (!strncmp(*av
, "disable", strlen(*av
)) ||
938 !strncmp(*av
, "enable", strlen(*av
)) ) {
939 int which
= !strncmp(*av
, "enable", strlen(*av
)) ? 1 : 0;
942 masks
[0] = masks
[1] = 0;
948 errx(EX_DATAERR
, "invalid set number %d\n", i
);
949 masks
[which
] |= (1<<i
);
950 } else if (!strncmp(*av
, "disable", strlen(*av
)))
952 else if (!strncmp(*av
, "enable", strlen(*av
)))
955 errx(EX_DATAERR
, "invalid set command %s\n", *av
);
958 if ( (masks
[0] & masks
[1]) != 0 )
959 errx(EX_DATAERR
, "cannot enable and disable the same set\n");
960 i
= do_set_x(IP_FW_DEL
, masks
, sizeof(masks
));
962 warn("set enable/disable: setsockopt(IP_FW_DEL)");
964 errx(EX_USAGE
, "invalid set command %s\n", *av
);
968 add_state(int ac
, char *av
[])
970 struct ipfw_ioc_state ioc_state
;
971 ioc_state
.expiry
= 0;
972 ioc_state
.lifetime
= 0;
974 if (strcmp(*av
, "rulenum") == 0) {
976 ioc_state
.rulenum
= atoi(*av
);
978 errx(EX_USAGE
, "ipfw state add rule");
982 pe
= getprotobyname(*av
);
983 ioc_state
.flow_id
.proto
= pe
->p_proto
;
986 ioc_state
.flow_id
.src_ip
= inet_addr(*av
);
989 ioc_state
.flow_id
.src_port
= atoi(*av
);
992 ioc_state
.flow_id
.dst_ip
= inet_addr(*av
);
995 ioc_state
.flow_id
.dst_port
= atoi(*av
);
998 if (strcmp(*av
, "live") == 0) {
1000 ioc_state
.lifetime
= atoi(*av
);
1004 if (strcmp(*av
, "expiry") == 0) {
1006 ioc_state
.expiry
= strtoul(*av
, NULL
, 10);
1007 printf("ioc_state.expiry=%d\n", ioc_state
.expiry
);
1010 if (do_set_x(IP_FW_STATE_ADD
, &ioc_state
, sizeof(struct ipfw_ioc_state
)) < 0 ) {
1011 err(EX_UNAVAILABLE
, "do_set_x(IP_FW_STATE_ADD)");
1014 printf("Flushed all states.\n");
1019 delete_state(int ac
, char *av
[])
1023 if (ac
== 1 && isdigit(**av
))
1024 rulenum
= atoi(*av
);
1025 if (do_set_x(IP_FW_STATE_DEL
, &rulenum
, sizeof(int)) < 0 )
1026 err(EX_UNAVAILABLE
, "do_set_x(IP_FW_STATE_DEL)");
1028 printf("Flushed all states.\n");
1032 flush_state(int ac
, char *av
[])
1037 printf("Are you sure? [yn] ");
1040 c
= toupper(getc(stdin
));
1041 while (c
!= '\n' && getc(stdin
) != '\n')
1043 return; /* and do not flush */
1044 } while (c
!= 'Y' && c
!= 'N');
1045 if (c
== 'N') /* user said no */
1048 if (do_set_x(IP_FW_STATE_FLUSH
, NULL
, 0) < 0 )
1049 err(EX_UNAVAILABLE
, "do_set_x(IP_FW_STATE_FLUSH)");
1051 printf("Flushed all states.\n");
1055 lookup_host (char *host
, struct in_addr
*ipaddr
)
1059 if (!inet_aton(host
, ipaddr
)) {
1060 if ((he
= gethostbyname(host
)) == NULL
)
1062 *ipaddr
= *(struct in_addr
*)he
->h_addr_list
[0];
1068 table_append(int ac
, char *av
[])
1070 struct ipfw_ioc_table tbl
;
1078 errx(EX_USAGE
, "table id `%s' invalid", *av
);
1080 if (tbl
.id
< 0 || tbl
.id
> IPFW_TABLES_MAX
- 1)
1081 errx(EX_USAGE
, "table id `%d' invalid", tbl
.id
);
1084 if (strcmp(*av
, "ip") == 0)
1086 else if (strcmp(*av
, "mac") == 0)
1089 errx(EX_USAGE
, "table type `%s' not supported", *av
);
1092 if (tbl
.type
== 1) { /* table type ipv4 */
1093 struct ipfw_ioc_table_ip_entry ip_ent
;
1095 errx(EX_USAGE
, "IP address required");
1097 p
= strchr(*av
, '/');
1100 ip_ent
.masklen
= atoi(p
);
1101 if (ip_ent
.masklen
> 32)
1102 errx(EX_DATAERR
, "bad width ``%s''", p
);
1104 ip_ent
.masklen
= 32;
1107 if (lookup_host(*av
, (struct in_addr
*)&ip_ent
.addr
) != 0)
1108 errx(EX_NOHOST
, "hostname ``%s'' unknown", *av
);
1110 tbl
.ip_ent
[0] = ip_ent
;
1111 size
= sizeof(tbl
) + sizeof(ip_ent
);
1112 } else if (tbl
.type
== 2) { /* table type mac */
1113 struct ipfw_ioc_table_mac_entry mac_ent
;
1115 errx(EX_USAGE
, "MAC address required");
1117 mac_ent
.addr
= *ether_aton(*av
);
1118 tbl
.mac_ent
[0] = mac_ent
;
1119 size
= sizeof(tbl
) + sizeof(mac_ent
);
1121 if (do_set_x(IP_FW_TABLE_APPEND
, &tbl
, size
) < 0 )
1122 errx(EX_USAGE
, "do_set_x(IP_FW_TABLE_APPEND) "
1123 "table `%d' append `%s' failed", tbl
.id
, *av
);
1127 table_remove(int ac
, char *av
[])
1129 struct ipfw_ioc_table tbl
;
1130 struct ipfw_ioc_table_ip_entry ip_ent
;
1138 errx(EX_USAGE
, "table id `%s' invalid", *av
);
1140 if (tbl
.id
< 0 || tbl
.id
> IPFW_TABLES_MAX
- 1)
1141 errx(EX_USAGE
, "table id `%d' invalid", tbl
.id
);
1144 if (strcmp(*av
, "ip") == 0)
1146 else if (strcmp(*av
, "mac") == 0)
1149 errx(EX_USAGE
, "table type `%s' not supported", *av
);
1153 errx(EX_USAGE
, "IP address required");
1154 p
= strchr(*av
, '/');
1157 ip_ent
.masklen
= atoi(p
);
1158 if (ip_ent
.masklen
> 32)
1159 errx(EX_DATAERR
, "bad width ``%s''", p
);
1161 ip_ent
.masklen
= 32;
1164 if (lookup_host(*av
, (struct in_addr
*)&ip_ent
.addr
) != 0)
1165 errx(EX_NOHOST
, "hostname ``%s'' unknown", *av
);
1167 tbl
.ip_ent
[0] = ip_ent
;
1168 size
= sizeof(tbl
) + sizeof(ip_ent
);
1169 if (do_set_x(IP_FW_TABLE_REMOVE
, &tbl
, size
) < 0 ) {
1170 errx(EX_USAGE
, "do_set_x(IP_FW_TABLE_REMOVE) "
1171 "table `%d' append `%s' failed", tbl
.id
, *av
);
1176 table_flush(int ac
, char *av
[])
1178 struct ipfw_ioc_table ioc_table
;
1179 struct ipfw_ioc_table
*t
= &ioc_table
;
1182 if (isdigit(**av
)) {
1184 if (t
->id
< 0 || t
->id
> IPFW_TABLES_MAX
- 1)
1185 errx(EX_USAGE
, "table id `%d' invalid", t
->id
);
1187 errx(EX_USAGE
, "table id `%s' invalid", *av
);
1189 if (do_set_x(IP_FW_TABLE_FLUSH
, t
, sizeof(struct ipfw_ioc_table
)) < 0 )
1190 errx(EX_USAGE
, "do_set_x(IP_FW_TABLE_FLUSH) "
1191 "table `%s' flush failed", *av
);
1195 table_list(int ac
, char *av
[])
1197 struct ipfw_ioc_table
*ioc_table
;
1198 int i
, count
, nbytes
, nalloc
= 1024;
1201 if (strcmp(*av
, "list") == 0) {
1203 while (nbytes
>= nalloc
) {
1204 nalloc
= nalloc
* 2 ;
1206 if ((data
= realloc(data
, nbytes
)) == NULL
)
1207 err(EX_OSERR
, "realloc");
1208 if (do_get_x(IP_FW_TABLE_LIST
, data
, &nbytes
) < 0)
1209 err(EX_OSERR
, "do_get_x(IP_FW_TABLE_LIST)");
1211 ioc_table
= (struct ipfw_ioc_table
*)data
;
1212 count
= nbytes
/ sizeof(struct ipfw_ioc_table
);
1213 for (i
= 0; i
< count
; i
++, ioc_table
++) {
1214 if (ioc_table
->type
> 0) {
1215 printf("table %d",ioc_table
->id
);
1216 if (ioc_table
->type
== 1)
1218 else if (ioc_table
->type
== 2)
1219 printf(" type mac");
1220 printf(" count %d",ioc_table
->count
);
1221 if (strlen(ioc_table
->name
) > 0)
1222 printf(" name %s",ioc_table
->name
);
1228 errx(EX_USAGE
, "ipfw3 table `%s' delete invalid", *av
);
1233 print_table(struct ipfw_ioc_table
* tbl
)
1237 errx(EX_USAGE
, "table %d is not in use", tbl
->id
);
1239 printf("table %d", tbl
->id
);
1242 else if (tbl
->type
== 2)
1243 printf(" type mac");
1245 printf(" count %d", tbl
->count
);
1246 if (strlen(tbl
->name
) > 0)
1247 printf(" name %s", tbl
->name
);
1251 if (tbl
->type
== 1) {
1252 struct ipfw_ioc_table_ip_entry
*ip_ent
;
1253 ip_ent
= tbl
->ip_ent
;
1254 for (i
= 0; i
< tbl
->count
; i
++) {
1255 printf("%s", inet_ntoa(*(struct in_addr
*)&ip_ent
->addr
));
1256 printf("/%d ", ip_ent
->masklen
);
1260 } else if (tbl
->type
== 2) {
1261 struct ipfw_ioc_table_mac_entry
*mac_ent
;
1262 mac_ent
= tbl
->mac_ent
;
1263 for (i
= 0; i
< tbl
->count
; i
++) {
1264 printf("%s", ether_ntoa(&mac_ent
->addr
));
1272 table_show(int ac
, char *av
[])
1274 int nbytes
, nalloc
= 1024;
1277 if (isdigit(**av
)) {
1279 while (nbytes
>= nalloc
) {
1280 nalloc
= nalloc
* 2 + 256;
1283 if ((data
= malloc(nbytes
)) == NULL
) {
1284 err(EX_OSERR
, "malloc");
1286 } else if ((data
= realloc(data
, nbytes
)) == NULL
) {
1287 err(EX_OSERR
, "realloc");
1289 /* store table id in the header of data */
1290 int *head
= (int *)data
;
1292 if (*head
< 0 || *head
> IPFW_TABLES_MAX
- 1)
1293 errx(EX_USAGE
, "table id `%d' invalid", *head
);
1294 if (do_get_x(IP_FW_TABLE_SHOW
, data
, &nbytes
) < 0)
1295 err(EX_OSERR
, "do_get_x(IP_FW_TABLE_LIST)");
1296 struct ipfw_ioc_table
*tbl
;
1297 tbl
= (struct ipfw_ioc_table
*)data
;
1301 errx(EX_USAGE
, "ipfw3 table `%s' show invalid", *av
);
1306 table_create(int ac
, char *av
[])
1308 struct ipfw_ioc_table ioc_table
;
1309 struct ipfw_ioc_table
*t
= &ioc_table
;
1313 errx(EX_USAGE
, "table parameters invalid");
1314 if (isdigit(**av
)) {
1316 if (t
->id
< 0 || t
->id
> IPFW_TABLES_MAX
- 1)
1317 errx(EX_USAGE
, "table id `%d' invalid", t
->id
);
1319 errx(EX_USAGE
, "table id `%s' invalid", *av
);
1322 if (strcmp(*av
, "ip") == 0)
1324 else if (strcmp(*av
, "mac") == 0)
1327 errx(EX_USAGE
, "table type `%s' not supported", *av
);
1330 memset(t
->name
, 0, IPFW_TABLE_NAME_LEN
);
1331 if (ac
== 2 && strcmp(*av
, "name") == 0) {
1333 if (strlen(*av
) < IPFW_TABLE_NAME_LEN
) {
1334 strncpy(t
->name
, *av
, strlen(*av
));
1336 errx(EX_USAGE
, "table name `%s' too long", *av
);
1338 } else if (ac
== 1) {
1339 errx(EX_USAGE
, "table `%s' invalid", *av
);
1342 if (do_set_x(IP_FW_TABLE_CREATE
, t
, sizeof(struct ipfw_ioc_table
)) < 0)
1343 errx(EX_USAGE
, "do_set_x(IP_FW_TABLE_CREATE) "
1344 "table `%d' in use", t
->id
);
1348 table_delete(int ac
, char *av
[])
1350 struct ipfw_ioc_table ioc_table
;
1351 struct ipfw_ioc_table
*t
= &ioc_table
;
1354 if (isdigit(**av
)) {
1356 if (t
->id
< 0 || t
->id
> IPFW_TABLES_MAX
- 1)
1357 errx(EX_USAGE
, "table id `%d' invalid", t
->id
);
1359 errx(EX_USAGE
, "table id `%s' invalid", *av
);
1361 if (t
->id
< 0 || t
->id
> IPFW_TABLES_MAX
- 1)
1362 errx(EX_USAGE
, "table id `%d' invalid", t
->id
);
1364 if (do_set_x(IP_FW_TABLE_DELETE
, t
, sizeof(struct ipfw_ioc_table
)) < 0)
1365 errx(EX_USAGE
, "do_set_x(IP_FW_TABLE_DELETE) "
1366 "table `%s' delete failed", *av
);
1370 table_test(int ac
, char *av
[])
1372 struct ipfw_ioc_table tbl
;
1379 errx(EX_USAGE
, "table id `%s' invalid", *av
);
1381 if (tbl
.id
< 0 || tbl
.id
> IPFW_TABLES_MAX
- 1)
1382 errx(EX_USAGE
, "table id `%d' invalid", tbl
.id
);
1385 if (strcmp(*av
, "ip") == 0)
1387 else if (strcmp(*av
, "mac") == 0)
1390 errx(EX_USAGE
, "table type `%s' not supported", *av
);
1393 if (tbl
.type
== 1) { /* table type ipv4 */
1394 struct ipfw_ioc_table_ip_entry ip_ent
;
1395 if (lookup_host(*av
, (struct in_addr
*)&ip_ent
.addr
) != 0)
1396 errx(EX_NOHOST
, "hostname ``%s'' unknown", *av
);
1398 tbl
.ip_ent
[0] = ip_ent
;
1399 size
= sizeof(tbl
) + sizeof(ip_ent
);
1400 } else if (tbl
.type
== 2) { /* table type mac */
1401 struct ipfw_ioc_table_mac_entry mac_ent
;
1403 errx(EX_USAGE
, "MAC address required");
1405 mac_ent
.addr
= *ether_aton(*av
);
1406 tbl
.mac_ent
[0] = mac_ent
;
1407 size
= sizeof(tbl
) + sizeof(mac_ent
);
1409 if (do_set_x(IP_FW_TABLE_TEST
, &tbl
, size
) < 0 ) {
1410 printf("NO, %s not exists in table %d\n", *av
, tbl
.id
);
1412 printf("YES, %s exists in table %d\n", *av
, tbl
.id
);
1417 table_rename(int ac
, char *av
[])
1419 struct ipfw_ioc_table tbl
;
1422 bzero(&tbl
, sizeof(tbl
));
1427 errx(EX_USAGE
, "table id `%s' invalid", *av
);
1429 if (tbl
.id
< 0 || tbl
.id
> IPFW_TABLES_MAX
- 1)
1430 errx(EX_USAGE
, "table id `%d' invalid", tbl
.id
);
1433 strlcpy(tbl
.name
, *av
, IPFW_TABLE_NAME_LEN
);
1435 if (do_set_x(IP_FW_TABLE_RENAME
, &tbl
, size
) < 0 )
1436 errx(EX_USAGE
, "do_set_x(IP_FW_TABLE_RENAME) "
1437 "table `%d' not in use", tbl
.id
);
1441 list(int ac
, char *av
[])
1443 struct ipfw_ioc_state
*dynrules
, *d
;
1444 struct ipfw_ioc_rule
*r
;
1448 int bcwidth
, n
, nbytes
, nstat
, ndyn
, pcwidth
, width
;
1449 int exitval
= EX_OK
, lac
;
1450 char **lav
, *endptr
;
1456 /* get rules or pipes from kernel, resizing array as necessary */
1459 while (nbytes
>= nalloc
) {
1460 nalloc
= nalloc
* 2 ;
1462 if ((data
= realloc(data
, nbytes
)) == NULL
)
1463 err(EX_OSERR
, "realloc");
1464 if (do_get_x(IP_FW_GET
, data
, &nbytes
) < 0)
1465 err(EX_OSERR
, "do_get_x(IP_FW_GET)");
1469 * Count static rules.
1472 nstat
= r
->static_count
;
1475 * Count dynamic rules. This is easier as they have
1478 dynrules
= (struct ipfw_ioc_state
*)((void *)r
+ r
->static_len
);
1479 ndyn
= (nbytes
- r
->static_len
) / sizeof(*dynrules
);
1481 /* if showing stats, figure out column widths ahead of time */
1482 bcwidth
= pcwidth
= 0;
1484 for (n
= 0, r
= data
; n
< nstat
;
1485 n
++, r
= (void *)r
+ IOC_RULESIZE(r
)) {
1486 /* packet counter */
1487 width
= snprintf(NULL
, 0, "%ju", (uintmax_t)r
->pcnt
);
1488 if (width
> pcwidth
)
1492 width
= snprintf(NULL
, 0, "%ju", (uintmax_t)r
->bcnt
);
1493 if (width
> bcwidth
)
1497 if (do_dynamic
&& ndyn
) {
1498 for (n
= 0, d
= dynrules
; n
< ndyn
; n
++, d
++) {
1499 width
= snprintf(NULL
, 0, "%ju", (uintmax_t)d
->pcnt
);
1500 if (width
> pcwidth
)
1503 width
= snprintf(NULL
, 0, "%ju", (uintmax_t)d
->bcnt
);
1504 if (width
> bcwidth
)
1509 /* if no rule numbers were specified, list all rules */
1511 if (do_dynamic
!= 2) {
1512 for (n
= 0, r
= data
; n
< nstat
; n
++,
1513 r
= (void *)r
+ IOC_RULESIZE(r
)) {
1514 show_rules(r
, pcwidth
, bcwidth
);
1517 if (do_dynamic
&& ndyn
) {
1518 if (do_dynamic
!= 2) {
1519 printf("## States (%d):\n", ndyn
);
1521 for (n
= 0, d
= dynrules
; n
< ndyn
; n
++, d
++)
1522 show_states(d
, pcwidth
, bcwidth
);
1527 /* display specific rules requested on command line */
1529 if (do_dynamic
!= 2) {
1530 for (lac
= ac
, lav
= av
; lac
!= 0; lac
--) {
1531 /* convert command line rule # */
1532 rnum
= strtoul(*lav
++, &endptr
, 10);
1535 warnx("invalid rule number: %s", *(lav
- 1));
1538 for (n
= seen
= 0, r
= data
; n
< nstat
;
1539 n
++, r
= (void *)r
+ IOC_RULESIZE(r
) ) {
1540 if (r
->rulenum
> rnum
)
1542 if (r
->rulenum
== rnum
) {
1543 show_rules(r
, pcwidth
, bcwidth
);
1548 /* give precedence to other error(s) */
1549 if (exitval
== EX_OK
)
1550 exitval
= EX_UNAVAILABLE
;
1551 warnx("rule %lu does not exist", rnum
);
1556 if (do_dynamic
&& ndyn
) {
1557 if (do_dynamic
!= 2) {
1558 printf("## States (%d):\n", ndyn
);
1560 for (lac
= ac
, lav
= av
; lac
!= 0; lac
--) {
1561 rnum
= strtoul(*lav
++, &endptr
, 10);
1563 /* already warned */
1565 for (n
= 0, d
= dynrules
; n
< ndyn
; n
++, d
++) {
1566 if (d
->rulenum
> rnum
)
1568 if (d
->rulenum
== rnum
)
1569 show_states(d
, pcwidth
, bcwidth
);
1579 if (exitval
!= EX_OK
)
1584 show_dummynet(int ac
, char *av
[])
1588 int nalloc
= 1024; /* start somewhere... */
1593 while (nbytes
>= nalloc
) {
1594 nalloc
= nalloc
* 2 + 200;
1596 if ((data
= realloc(data
, nbytes
)) == NULL
)
1597 err(EX_OSERR
, "realloc");
1598 if (do_get_x(IP_DUMMYNET_GET
, data
, &nbytes
) < 0) {
1599 err(EX_OSERR
, "do_get_x(IP_%s_GET)",
1600 do_pipe
? "DUMMYNET" : "FW");
1604 show_pipes(data
, nbytes
, ac
, av
);
1611 fprintf(stderr
, "usage: ipfw [options]\n"
1612 " ipfw add [rulenum] [set id] action filters\n"
1613 " ipfw delete [rulenum]\n"
1615 " ipfw list [rulenum]\n"
1616 " ipfw show [rulenum]\n"
1617 " ipfw zero [rulenum]\n"
1618 " ipfw set [show|enable|disable]\n"
1620 " ipfw [enable|disable]\n"
1621 " ipfw log [reset|off|on]\n"
1622 " ipfw nat [config|show|delete]\n"
1623 " ipfw pipe [config|show|delete]\n"
1624 " ipfw state [add|delete|list|show]"
1625 "\nsee ipfw manpage for details\n");
1630 delete_nat_config(int ac
, char *av
[])
1637 if (do_set_x(IP_FW_NAT_DEL
, &i
, sizeof(i
)) == -1)
1638 errx(EX_USAGE
, "NAT %d in use or not exists", i
);
1642 delete_rules(int ac
, char *av
[])
1644 struct dn_ioc_pipe pipe
;
1646 int exitval
= EX_OK
;
1650 memset(&pipe
, 0, sizeof pipe
);
1653 if (ac
> 0 && !strncmp(*av
, "set", strlen(*av
))) {
1654 do_set
= 1; /* delete set */
1659 while (ac
&& isdigit(**av
)) {
1668 i
= do_set_x(IP_DUMMYNET_DEL
, &pipe
, sizeof pipe
);
1671 warn("rule %u: setsockopt(IP_DUMMYNET_DEL)",
1672 do_pipe
== 1 ? pipe
.pipe_nr
: pipe
.fs
.fs_nr
);
1675 rulenum
= (i
& 0xffff) | (do_set
<< 24);
1676 i
= do_set_x(IP_FW_DEL
, &rulenum
, sizeof rulenum
);
1678 exitval
= EX_UNAVAILABLE
;
1679 warn("rule %u: setsockopt(IP_FW_DEL)",
1684 if (exitval
!= EX_OK
)
1689 static unsigned long
1690 getbw(const char *str
, u_short
*flags
, int kb
)
1696 val
= strtoul(str
, &end
, 0);
1697 if (*end
== 'k' || *end
== 'K') {
1700 } else if (*end
== 'm' || *end
== 'M') {
1706 * Deal with bits or bytes or b(bits) or B(bytes). If there is no
1707 * trailer assume bits.
1709 if (strncasecmp(end
, "bit", 3) == 0) {
1711 } else if (strncasecmp(end
, "byte", 4) == 0) {
1713 } else if (*end
== 'b') {
1715 } else if (*end
== 'B') {
1720 * Return in bits if flags is NULL, else flag bits
1721 * or bytes in flags and return the unconverted value.
1723 if (inbytes
&& flags
)
1724 *flags
|= DN_QSIZE_IS_BYTES
;
1725 else if (inbytes
&& flags
== NULL
)
1732 * config dummynet pipe/queue
1735 config_dummynet(int ac
, char **av
)
1737 struct dn_ioc_pipe pipe
;
1744 memset(&pipe
, 0, sizeof pipe
);
1746 if (ac
&& isdigit(**av
)) {
1758 int tok
= match_token(dummynet_params
, *av
);
1763 pipe
.fs
.flags_fs
|= DN_NOERROR
;
1767 NEED1("plr needs argument 0..1\n");
1768 d
= strtod(av
[0], NULL
);
1773 pipe
.fs
.plr
= (int)(d
*0x7fffffff);
1778 NEED1("queue needs queue size\n");
1780 pipe
.fs
.qsize
= getbw(av
[0], &pipe
.fs
.flags_fs
, 1024);
1785 NEED1("buckets needs argument\n");
1786 pipe
.fs
.rq_size
= strtoul(av
[0], NULL
, 0);
1791 NEED1("mask needs mask specifier\n");
1793 * per-flow queue, mask is dst_ip, dst_port,
1794 * src_ip, src_port, proto measured in bits
1798 pipe
.fs
.flow_mask
.type
= ETHERTYPE_IP
;
1799 pipe
.fs
.flow_mask
.u
.ip
.dst_ip
= 0;
1800 pipe
.fs
.flow_mask
.u
.ip
.src_ip
= 0;
1801 pipe
.fs
.flow_mask
.u
.ip
.dst_port
= 0;
1802 pipe
.fs
.flow_mask
.u
.ip
.src_port
= 0;
1803 pipe
.fs
.flow_mask
.u
.ip
.proto
= 0;
1807 u_int32_t
*p32
= NULL
;
1808 u_int16_t
*p16
= NULL
;
1810 tok
= match_token(dummynet_params
, *av
);
1815 * special case, all bits significant
1817 pipe
.fs
.flow_mask
.u
.ip
.dst_ip
= ~0;
1818 pipe
.fs
.flow_mask
.u
.ip
.src_ip
= ~0;
1819 pipe
.fs
.flow_mask
.u
.ip
.dst_port
= ~0;
1820 pipe
.fs
.flow_mask
.u
.ip
.src_port
= ~0;
1821 pipe
.fs
.flow_mask
.u
.ip
.proto
= ~0;
1822 pipe
.fs
.flags_fs
|= DN_HAVE_FLOW_MASK
;
1826 p32
= &pipe
.fs
.flow_mask
.u
.ip
.dst_ip
;
1830 p32
= &pipe
.fs
.flow_mask
.u
.ip
.src_ip
;
1834 p16
= &pipe
.fs
.flow_mask
.u
.ip
.dst_port
;
1838 p16
= &pipe
.fs
.flow_mask
.u
.ip
.src_port
;
1849 errx(EX_USAGE
, "mask: value missing");
1850 if (*av
[0] == '/') {
1851 a
= strtoul(av
[0]+1, &end
, 0);
1852 a
= (a
== 32) ? ~0 : (1 << a
) - 1;
1854 a
= strtoul(av
[0], &end
, 0);
1857 else if (p16
!= NULL
) {
1860 "mask: must be 16 bit");
1861 *p16
= (u_int16_t
)a
;
1865 "mask: must be 8 bit");
1866 pipe
.fs
.flow_mask
.u
.ip
.proto
= (uint8_t)a
;
1869 pipe
.fs
.flags_fs
|= DN_HAVE_FLOW_MASK
;
1871 } /* end while, config masks */
1878 NEED1("red/gred needs w_q/min_th/max_th/max_p\n");
1879 pipe
.fs
.flags_fs
|= DN_IS_RED
;
1880 if (tok
== TOK_GRED
)
1881 pipe
.fs
.flags_fs
|= DN_IS_GENTLE_RED
;
1883 * the format for parameters is w_q/min_th/max_th/max_p
1885 if ((end
= strsep(&av
[0], "/"))) {
1886 double w_q
= strtod(end
, NULL
);
1887 if (w_q
> 1 || w_q
<= 0)
1888 errx(EX_DATAERR
, "0 < w_q <= 1");
1889 pipe
.fs
.w_q
= (int) (w_q
* (1 << SCALE_RED
));
1891 if ((end
= strsep(&av
[0], "/"))) {
1892 pipe
.fs
.min_th
= strtoul(end
, &end
, 0);
1893 if (*end
== 'K' || *end
== 'k')
1894 pipe
.fs
.min_th
*= 1024;
1896 if ((end
= strsep(&av
[0], "/"))) {
1897 pipe
.fs
.max_th
= strtoul(end
, &end
, 0);
1898 if (*end
== 'K' || *end
== 'k')
1899 pipe
.fs
.max_th
*= 1024;
1901 if ((end
= strsep(&av
[0], "/"))) {
1902 double max_p
= strtod(end
, NULL
);
1903 if (max_p
> 1 || max_p
<= 0)
1904 errx(EX_DATAERR
, "0 < max_p <= 1");
1905 pipe
.fs
.max_p
= (int)(max_p
* (1 << SCALE_RED
));
1911 pipe
.fs
.flags_fs
&= ~(DN_IS_RED
|DN_IS_GENTLE_RED
);
1915 NEED1("bw needs bandwidth\n");
1917 errx(EX_DATAERR
, "bandwidth only valid for pipes");
1919 * set bandwidth value
1921 pipe
.bandwidth
= getbw(av
[0], NULL
, 1000);
1922 if (pipe
.bandwidth
< 0)
1923 errx(EX_DATAERR
, "bandwidth too large");
1929 errx(EX_DATAERR
, "delay only valid for pipes");
1930 NEED1("delay needs argument 0..10000ms\n");
1931 pipe
.delay
= strtoul(av
[0], NULL
, 0);
1937 errx(EX_DATAERR
, "weight only valid for queues");
1938 NEED1("weight needs argument 0..100\n");
1939 pipe
.fs
.weight
= strtoul(av
[0], &end
, 0);
1945 errx(EX_DATAERR
, "pipe only valid for queues");
1946 NEED1("pipe needs pipe_number\n");
1947 pipe
.fs
.parent_nr
= strtoul(av
[0], &end
, 0);
1952 errx(EX_DATAERR
, "unrecognised option ``%s''", *av
);
1956 if (pipe
.pipe_nr
== 0)
1957 errx(EX_DATAERR
, "pipe_nr must be > 0");
1958 if (pipe
.delay
> 10000)
1959 errx(EX_DATAERR
, "delay must be < 10000");
1960 } else { /* do_pipe == 2, queue */
1961 if (pipe
.fs
.parent_nr
== 0)
1962 errx(EX_DATAERR
, "pipe must be > 0");
1963 if (pipe
.fs
.weight
>100)
1964 errx(EX_DATAERR
, "weight must be <= 100");
1966 if (pipe
.fs
.flags_fs
& DN_QSIZE_IS_BYTES
) {
1967 if (pipe
.fs
.qsize
> 1024*1024)
1968 errx(EX_DATAERR
, "queue size must be < 1MB");
1970 if (pipe
.fs
.qsize
> 100)
1971 errx(EX_DATAERR
, "2 <= queue size <= 100");
1973 if (pipe
.fs
.flags_fs
& DN_IS_RED
) {
1975 int lookup_depth
, avg_pkt_size
;
1976 double s
, idle
, weight
, w_q
;
1980 if (pipe
.fs
.min_th
>= pipe
.fs
.max_th
)
1981 errx(EX_DATAERR
, "min_th %d must be < than max_th %d",
1982 pipe
.fs
.min_th
, pipe
.fs
.max_th
);
1983 if (pipe
.fs
.max_th
== 0)
1984 errx(EX_DATAERR
, "max_th must be > 0");
1987 if (sysctlbyname("net.inet.ip.dummynet.red_lookup_depth",
1988 &lookup_depth
, &len
, NULL
, 0) == -1)
1990 errx(1, "sysctlbyname(\"%s\")",
1991 "net.inet.ip.dummynet.red_lookup_depth");
1992 if (lookup_depth
== 0)
1993 errx(EX_DATAERR
, "net.inet.ip.dummynet.red_lookup_depth"
1994 " must be greater than zero");
1997 if (sysctlbyname("net.inet.ip.dummynet.red_avg_pkt_size",
1998 &avg_pkt_size
, &len
, NULL
, 0) == -1)
2000 errx(1, "sysctlbyname(\"%s\")",
2001 "net.inet.ip.dummynet.red_avg_pkt_size");
2002 if (avg_pkt_size
== 0)
2004 "net.inet.ip.dummynet.red_avg_pkt_size must"
2005 " be greater than zero");
2007 len
= sizeof(clock_hz
);
2008 if (sysctlbyname("net.inet.ip.dummynet.hz", &clock_hz
, &len
,
2010 errx(1, "sysctlbyname(\"%s\")",
2011 "net.inet.ip.dummynet.hz");
2015 * Ticks needed for sending a medium-sized packet.
2016 * Unfortunately, when we are configuring a WF2Q+ queue, we
2017 * do not have bandwidth information, because that is stored
2018 * in the parent pipe, and also we have multiple queues
2019 * competing for it. So we set s=0, which is not very
2020 * correct. But on the other hand, why do we want RED with
2023 if (pipe
.bandwidth
== 0) /* this is a WF2Q+ queue */
2026 s
= clock_hz
* avg_pkt_size
* 8 / pipe
.bandwidth
;
2029 * max idle time (in ticks) before avg queue size becomes 0.
2030 * NOTA: (3/w_q) is approx the value x so that
2031 * (1-w_q)^x < 10^-3.
2033 w_q
= ((double)pipe
.fs
.w_q
) / (1 << SCALE_RED
);
2034 idle
= s
* 3. / w_q
;
2035 pipe
.fs
.lookup_step
= (int)idle
/ lookup_depth
;
2036 if (!pipe
.fs
.lookup_step
)
2037 pipe
.fs
.lookup_step
= 1;
2039 for (t
= pipe
.fs
.lookup_step
; t
> 0; --t
)
2041 pipe
.fs
.lookup_weight
= (int)(weight
* (1 << SCALE_RED
));
2043 i
= do_set_x(IP_DUMMYNET_CONFIGURE
, &pipe
, sizeof pipe
);
2045 err(1, "do_set_x(%s)", "IP_DUMMYNET_CONFIGURE");
2049 * helper function, updates the pointer to cmd with the length
2050 * of the current command, and also cleans up the first word of
2051 * the new command in case it has been clobbered before.
2054 next_cmd(ipfw_insn
*cmd
)
2057 bzero(cmd
, sizeof(*cmd
));
2062 * Parse arguments and assemble the microinstructions which make up a rule.
2063 * Rules are added into the 'rulebuf' and then copied in the correct order
2064 * into the actual rule.
2069 add(int ac
, char *av
[])
2072 * rules are added into the 'rulebuf' and then copied in
2073 * the correct order into the actual rule.
2074 * Some things that need to go out of order (prob, action etc.)
2077 static uint32_t rulebuf
[IPFW_RULE_SIZE_MAX
];
2078 static uint32_t actbuf
[IPFW_RULE_SIZE_MAX
];
2079 static uint32_t othbuf
[IPFW_RULE_SIZE_MAX
];
2080 static uint32_t cmdbuf
[IPFW_RULE_SIZE_MAX
];
2082 ipfw_insn
*src
, *dst
, *cmd
, *action
, *other
;
2085 ipfw_insn
*the_comment
= NULL
;
2086 struct ipfw_ioc_rule
*rule
;
2087 struct ipfw_keyword
*key
;
2088 struct ipfw_mapping
*map
;
2092 bzero(actbuf
, sizeof(actbuf
)); /* actions go here */
2093 bzero(othbuf
, sizeof(actbuf
)); /* others */
2094 bzero(cmdbuf
, sizeof(cmdbuf
)); /* filters */
2095 bzero(rulebuf
, sizeof(rulebuf
));
2097 rule
= (struct ipfw_ioc_rule
*)rulebuf
;
2098 cmd
= (ipfw_insn
*)cmdbuf
;
2099 action
= (ipfw_insn
*)actbuf
;
2100 other
= (ipfw_insn
*)othbuf
;
2102 NEED2("need more parameters");
2105 /* [rule N] -- Rule number optional */
2106 if (ac
&& isdigit(**av
)) {
2107 rule
->rulenum
= atoi(*av
);
2111 /* [set N] -- set number (0..30), optional */
2112 if (ac
> 1 && !strncmp(*av
, "set", strlen(*av
))) {
2113 int set
= strtoul(av
[1], NULL
, 10);
2114 if (set
< 0 || set
> 30)
2115 errx(EX_DATAERR
, "illegal set %s", av
[1]);
2124 for (i
= 0, key
= keywords
; i
< KEYWORD_SIZE
; i
++, key
++) {
2125 if (key
->type
== BEFORE
&&
2126 strcmp(key
->word
, *av
) == 0) {
2127 for (j
= 0, map
= mappings
;
2128 j
< MAPPING_SIZE
; j
++, map
++) {
2129 if (map
->type
== IN_USE
&&
2130 map
->module
== key
->module
&&
2131 map
->opcode
== key
->opcode
) {
2133 (*fn
)(&other
, &ac
, &av
);
2140 if (i
>= KEYWORD_SIZE
) {
2142 } else if (F_LEN(other
) > 0) {
2143 if (other
->module
== MODULE_BASIC_ID
&&
2144 other
->opcode
== O_BASIC_CHECK_STATE
) {
2145 other
= next_cmd(other
);
2148 other
= next_cmd(other
);
2155 * only accept 1 action
2157 NEED1("missing action");
2158 for (i
= 0, key
= keywords
; i
< KEYWORD_SIZE
; i
++, key
++) {
2159 if (ac
> 0 && key
->type
== ACTION
&&
2160 strcmp(key
->word
, *av
) == 0) {
2161 for (j
= 0, map
= mappings
; j
<MAPPING_SIZE
; j
++, map
++) {
2162 if (map
->type
== IN_USE
&&
2163 map
->module
== key
->module
&&
2164 map
->opcode
== key
->opcode
) {
2166 (*fn
)(&action
, &ac
, &av
);
2173 if (F_LEN(action
) > 0)
2174 action
= next_cmd(action
);
2179 if (strcmp(*av
, "proto") == 0){
2183 NEED1("missing protocol");
2184 for (i
= 0, key
= keywords
; i
< KEYWORD_SIZE
; i
++, key
++) {
2185 if (key
->type
== PROTO
&&
2186 strcmp(key
->word
, "proto") == 0) {
2187 for (j
= 0, map
= mappings
; j
<MAPPING_SIZE
; j
++, map
++) {
2188 if (map
->type
== IN_USE
&&
2189 map
->module
== key
->module
&&
2190 map
->opcode
== key
->opcode
) {
2192 (*fn
)(&cmd
, &ac
, &av
);
2200 cmd
= next_cmd(cmd
);
2206 char *s
, *cur
; /* current filter */
2207 ipfw_insn_u32
*cmd32
; /* alias for cmd */
2210 cmd32
= (ipfw_insn_u32
*)cmd
;
2211 if (strcmp(*av
, "or") == 0) {
2213 errx(EX_USAGE
, "'or' should"
2214 "between two filters\n");
2219 if (strcmp(*av
, "not") == 0) {
2220 if (cmd
->len
& F_NOT
)
2221 errx(EX_USAGE
, "double \"not\" not allowed\n");
2227 for (i
= 0, key
= keywords
; i
< KEYWORD_SIZE
; i
++, key
++) {
2228 if ((key
->type
== FILTER
||
2229 key
->type
== AFTER
||
2230 key
->type
== FROM
||
2232 strcmp(key
->word
, cur
) == 0) {
2233 for (j
= 0, map
= mappings
;
2234 j
< MAPPING_SIZE
; j
++, map
++) {
2235 if (map
->type
== IN_USE
&&
2236 map
->module
== key
->module
&&
2237 map
->opcode
== key
->opcode
) {
2239 (*fn
)(&cmd
, &ac
, &av
);
2244 } else if (i
== KEYWORD_SIZE
- 1) {
2245 errx(EX_USAGE
, "bad command `%s'", cur
);
2248 if (i
>= KEYWORD_SIZE
) {
2250 } else if (F_LEN(cmd
) > 0) {
2253 cmd
= next_cmd(cmd
);
2259 errx(EX_USAGE
, "bad command `%s'", *av
);
2262 * Now copy stuff into the rule.
2263 * [filters][others][action][comment]
2265 dst
= (ipfw_insn
*)rule
->cmd
;
2267 * copy all filters, except comment
2269 src
= (ipfw_insn
*)cmdbuf
;
2270 for (src
= (ipfw_insn
*)cmdbuf
; src
!= cmd
; src
+= i
) {
2271 /* pick comment out */
2273 if (src
->module
== MODULE_BASIC_ID
&& src
->opcode
== O_BASIC_COMMENT
) {
2276 bcopy(src
, dst
, i
* sizeof(u_int32_t
));
2277 dst
= (ipfw_insn
*)((uint32_t *)dst
+ i
);
2282 * start action section, it begin with others
2284 rule
->act_ofs
= (uint32_t *)dst
- (uint32_t *)(rule
->cmd
);
2287 * copy all other others
2289 for (src
= (ipfw_insn
*)othbuf
; src
!= other
; src
+= i
) {
2291 bcopy(src
, dst
, i
* sizeof(u_int32_t
));
2292 dst
= (ipfw_insn
*)((uint32_t *)dst
+ i
);
2295 /* copy the action to the end of rule */
2296 src
= (ipfw_insn
*)actbuf
;
2298 bcopy(src
, dst
, i
* sizeof(u_int32_t
));
2299 dst
= (ipfw_insn
*)((uint32_t *)dst
+ i
);
2302 * comment place behind the action
2304 if (the_comment
!= NULL
) {
2305 i
= F_LEN(the_comment
);
2306 bcopy(the_comment
, dst
, i
* sizeof(u_int32_t
));
2307 dst
= (ipfw_insn
*)((uint32_t *)dst
+ i
);
2310 rule
->cmd_len
= (u_int32_t
*)dst
- (u_int32_t
*)(rule
->cmd
);
2311 i
= (void *)dst
- (void *)rule
;
2312 if (do_set_x(IP_FW_ADD
, (void *)rule
, i
) == -1) {
2313 err(EX_UNAVAILABLE
, "getsockopt(%s)", "IP_FW_ADD");
2316 show_rules(rule
, 10, 10);
2320 zero(int ac
, char *av
[])
2328 /* clear all entries */
2329 if (do_set_x(IP_FW_ZERO
, NULL
, 0) < 0)
2330 err(EX_UNAVAILABLE
, "do_set_x(IP_FW_ZERO)");
2332 printf("Accounting cleared.\n");
2338 if (isdigit(**av
)) {
2339 rulenum
= atoi(*av
);
2341 if (do_set_x(IP_FW_ZERO
, &rulenum
, sizeof rulenum
)) {
2342 warn("rule %u: do_set_x(IP_FW_ZERO)", rulenum
);
2343 failed
= EX_UNAVAILABLE
;
2344 } else if (!do_quiet
)
2345 printf("Entry %d cleared\n", rulenum
);
2347 errx(EX_USAGE
, "invalid rule number ``%s''", *av
);
2350 if (failed
!= EX_OK
)
2355 resetlog(int ac
, char *av
[])
2363 /* clear all entries */
2364 if (setsockopt(ipfw_socket
, IPPROTO_IP
, IP_FW_RESETLOG
, NULL
, 0) < 0)
2365 err(EX_UNAVAILABLE
, "setsockopt(IP_FW_RESETLOG)");
2367 printf("Logging counts reset.\n");
2374 if (isdigit(**av
)) {
2375 rulenum
= atoi(*av
);
2377 if (setsockopt(ipfw_socket
, IPPROTO_IP
,
2378 IP_FW_RESETLOG
, &rulenum
, sizeof rulenum
)) {
2379 warn("rule %u: setsockopt(IP_FW_RESETLOG)", rulenum
);
2380 failed
= EX_UNAVAILABLE
;
2381 } else if (!do_quiet
)
2382 printf("Entry %d logging count reset\n", rulenum
);
2384 errx(EX_DATAERR
, "invalid rule number ``%s''", *av
);
2387 if (failed
!= EX_OK
)
2394 int cmd
= IP_FW_FLUSH
;
2396 cmd
= IP_DUMMYNET_FLUSH
;
2397 } else if (do_nat
) {
2398 cmd
= IP_FW_NAT_FLUSH
;
2403 printf("Are you sure? [yn] ");
2406 c
= toupper(getc(stdin
));
2407 while (c
!= '\n' && getc(stdin
) != '\n')
2409 return; /* and do not flush */
2410 } while (c
!= 'Y' && c
!= 'N');
2411 if (c
== 'N') /* user said no */
2414 if (do_set_x(cmd
, NULL
, 0) < 0 ) {
2416 errx(EX_USAGE
, "pipe/queue in use");
2418 errx(EX_USAGE
, "NAT configuration in use");
2420 errx(EX_USAGE
, "do_set_x(IP_FWFLUSH) failed");
2423 printf("Flushed all %s.\n", do_pipe
? "pipes":
2424 (do_nat
?"nat configurations":"rules"));
2429 str2addr(const char* str
, struct in_addr
* addr
)
2433 if (inet_aton (str
, addr
))
2436 hp
= gethostbyname (str
);
2438 errx (1, "unknown host %s", str
);
2440 memcpy (addr
, hp
->h_addr
, sizeof (struct in_addr
));
2444 str2portrange(const char* str
, const char* proto
, port_range
*portRange
)
2449 u_short loPort
, hiPort
;
2451 /* First see if this is a service, return corresponding port if so. */
2452 sp
= getservbyname (str
, proto
);
2454 SETLOPORT(*portRange
, ntohs(sp
->s_port
));
2455 SETNUMPORTS(*portRange
, 1);
2459 /* Not a service, see if it's a single port or port range. */
2460 sep
= strchr (str
, '-');
2462 SETLOPORT(*portRange
, strtol(str
, &end
, 10));
2465 SETNUMPORTS(*portRange
, 1);
2469 /* Error in port range field. */
2470 errx (EX_DATAERR
, "%s/%s: unknown service", str
, proto
);
2473 /* Port range, get the values and sanity check. */
2474 sscanf (str
, "%hu-%hu", &loPort
, &hiPort
);
2475 SETLOPORT(*portRange
, loPort
);
2476 SETNUMPORTS(*portRange
, 0); /* Error by default */
2477 if (loPort
<= hiPort
)
2478 SETNUMPORTS(*portRange
, hiPort
- loPort
+ 1);
2480 if (GETNUMPORTS(*portRange
) == 0)
2481 errx (EX_DATAERR
, "invalid port range %s", str
);
2487 str2proto(const char* str
)
2489 if (!strcmp (str
, "tcp"))
2491 if (!strcmp (str
, "udp"))
2493 errx (EX_DATAERR
, "unknown protocol %s. Expected tcp or udp", str
);
2497 str2addr_portrange (const char* str
, struct in_addr
* addr
,
2498 char* proto
, port_range
*portRange
)
2502 ptr
= strchr (str
, ':');
2504 errx (EX_DATAERR
, "%s is missing port number", str
);
2509 str2addr (str
, addr
);
2510 return str2portrange (ptr
, proto
, portRange
);
2514 * Search for interface with name "ifn", and fill n accordingly:
2516 * n->ip ip address of interface "ifn"
2517 * n->if_name copy of interface name "ifn"
2520 set_addr_dynamic(const char *ifn
, struct cfg_nat
*n
)
2522 struct if_msghdr
*ifm
;
2523 struct ifa_msghdr
*ifam
;
2524 struct sockaddr_dl
*sdl
;
2525 struct sockaddr_in
*sin
;
2526 char *buf
, *lim
, *next
;
2535 mib
[4] = NET_RT_IFLIST
;
2539 * Get interface data.
2541 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) == -1)
2542 err(1, "iflist-sysctl-estimate");
2543 if ((buf
= malloc(needed
)) == NULL
)
2544 errx(1, "malloc failed");
2545 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) == -1)
2546 err(1, "iflist-sysctl-get");
2549 * Loop through interfaces until one with
2550 * given name is found. This is done to
2551 * find correct interface index for routing
2552 * message processing.
2556 while (next
< lim
) {
2557 ifm
= (struct if_msghdr
*)next
;
2558 next
+= ifm
->ifm_msglen
;
2559 if (ifm
->ifm_version
!= RTM_VERSION
) {
2561 warnx("routing message version %d "
2562 "not understood", ifm
->ifm_version
);
2565 if (ifm
->ifm_type
== RTM_IFINFO
) {
2566 sdl
= (struct sockaddr_dl
*)(ifm
+ 1);
2567 if (strlen(ifn
) == sdl
->sdl_nlen
&&
2568 strncmp(ifn
, sdl
->sdl_data
, sdl
->sdl_nlen
) == 0) {
2569 ifIndex
= ifm
->ifm_index
;
2570 ifMTU
= ifm
->ifm_data
.ifi_mtu
;
2576 errx(1, "unknown interface name %s", ifn
);
2578 * Get interface address.
2581 while (next
< lim
) {
2582 ifam
= (struct ifa_msghdr
*)next
;
2583 next
+= ifam
->ifam_msglen
;
2584 if (ifam
->ifam_version
!= RTM_VERSION
) {
2586 warnx("routing message version %d "
2587 "not understood", ifam
->ifam_version
);
2590 if (ifam
->ifam_type
!= RTM_NEWADDR
)
2592 if (ifam
->ifam_addrs
& RTA_IFA
) {
2594 char *cp
= (char *)(ifam
+ 1);
2596 for (i
= 1; i
< RTA_IFA
; i
<<= 1) {
2597 if (ifam
->ifam_addrs
& i
)
2598 cp
+= SA_SIZE((struct sockaddr
*)cp
);
2600 if (((struct sockaddr
*)cp
)->sa_family
== AF_INET
) {
2601 sin
= (struct sockaddr_in
*)cp
;
2607 errx(1, "%s: cannot get interface address", ifn
);
2609 n
->ip
= sin
->sin_addr
;
2610 strncpy(n
->if_name
, ifn
, IF_NAMESIZE
);
2616 setup_redir_addr(char *spool_buf
, int len
, int *_ac
, char ***_av
)
2618 struct cfg_redir
*r
;
2619 struct cfg_spool
*tmp
;
2621 char tmp_spool_buf
[NAT_BUF_LEN
];
2622 int ac
, i
, space
, lsnat
;
2629 if (len
>= SOF_REDIR
) {
2630 r
= (struct cfg_redir
*)spool_buf
;
2631 /* Skip cfg_redir at beginning of buf. */
2632 spool_buf
= &spool_buf
[SOF_REDIR
];
2639 r
->mode
= REDIR_ADDR
;
2640 /* Extract local address. */
2642 errx(EX_DATAERR
, "redirect_addr: missing local address");
2644 sep
= strchr(*av
, ',');
2645 if (sep
) { /* LSNAT redirection syntax. */
2646 r
->laddr
.s_addr
= INADDR_NONE
;
2647 /* Preserve av, copy spool servers to tmp_spool_buf. */
2648 strncpy(tmp_spool_buf
, *av
, strlen(*av
)+1);
2651 str2addr(*av
, &r
->laddr
);
2655 /* Extract public address. */
2657 errx(EX_DATAERR
, "redirect_addr: missing public address");
2659 str2addr(*av
, &r
->paddr
);
2662 /* Setup LSNAT server pool. */
2664 sep
= strtok(tmp_spool_buf
, ", ");
2665 while (sep
!= NULL
) {
2666 tmp
= (struct cfg_spool
*)spool_buf
;
2667 if (len
< SOF_SPOOL
)
2672 str2addr(sep
, &tmp
->addr
);
2675 /* Point to the next possible cfg_spool. */
2676 spool_buf
= &spool_buf
[SOF_SPOOL
];
2677 sep
= strtok(NULL
, ", ");
2683 errx(EX_DATAERR
, "redirect_addr: buf is too small\n");
2687 setup_redir_port(char *spool_buf
, int len
, int *_ac
, char ***_av
)
2689 char **av
, *sep
, *protoName
;
2690 char tmp_spool_buf
[NAT_BUF_LEN
];
2691 int ac
, space
, lsnat
;
2692 struct cfg_redir
*r
;
2693 struct cfg_spool
*tmp
;
2694 u_short numLocalPorts
;
2695 port_range portRange
;
2703 if (len
>= SOF_REDIR
) {
2704 r
= (struct cfg_redir
*)spool_buf
;
2705 /* Skip cfg_redir at beginning of buf. */
2706 spool_buf
= &spool_buf
[SOF_REDIR
];
2713 r
->mode
= REDIR_PORT
;
2718 errx (EX_DATAERR
, "redirect_port: missing protocol");
2720 r
->proto
= str2proto(*av
);
2725 * Extract local address.
2728 errx (EX_DATAERR
, "redirect_port: missing local address");
2730 sep
= strchr(*av
, ',');
2731 /* LSNAT redirection syntax. */
2733 r
->laddr
.s_addr
= INADDR_NONE
;
2736 /* Preserve av, copy spool servers to tmp_spool_buf. */
2737 strncpy(tmp_spool_buf
, *av
, strlen(*av
)+1);
2740 if (str2addr_portrange (*av
, &r
->laddr
, protoName
, &portRange
) != 0)
2741 errx(EX_DATAERR
, "redirect_port:"
2742 "invalid local port range");
2744 r
->lport
= GETLOPORT(portRange
);
2745 numLocalPorts
= GETNUMPORTS(portRange
);
2750 * Extract public port and optionally address.
2753 errx (EX_DATAERR
, "redirect_port: missing public port");
2755 sep
= strchr (*av
, ':');
2757 if (str2addr_portrange (*av
, &r
->paddr
, protoName
, &portRange
) != 0)
2758 errx(EX_DATAERR
, "redirect_port:"
2759 "invalid public port range");
2761 r
->paddr
.s_addr
= INADDR_ANY
;
2762 if (str2portrange(*av
, protoName
, &portRange
) != 0)
2763 errx(EX_DATAERR
, "redirect_port:"
2764 "invalid public port range");
2767 r
->pport
= GETLOPORT(portRange
);
2768 r
->pport_cnt
= GETNUMPORTS(portRange
);
2772 * Extract remote address and optionally port.
2775 * NB: isalpha(**av) => we've to check that next parameter is really an
2776 * option for this redirect entry, else stop here processing arg[cv].
2778 if (ac
!= 0 && !isalpha(**av
)) {
2779 sep
= strchr (*av
, ':');
2781 if (str2addr_portrange (*av
, &r
->raddr
,
2782 protoName
, &portRange
) != 0)
2783 errx(EX_DATAERR
, "redirect_port:"
2784 "invalid remote port range");
2786 SETLOPORT(portRange
, 0);
2787 SETNUMPORTS(portRange
, 1);
2788 str2addr (*av
, &r
->raddr
);
2792 SETLOPORT(portRange
, 0);
2793 SETNUMPORTS(portRange
, 1);
2794 r
->raddr
.s_addr
= INADDR_ANY
;
2796 r
->rport
= GETLOPORT(portRange
);
2797 r
->rport_cnt
= GETNUMPORTS(portRange
);
2800 * Make sure port ranges match up, then add the redirect ports.
2802 if (numLocalPorts
!= r
->pport_cnt
)
2803 errx(EX_DATAERR
, "redirect_port:"
2804 "port ranges must be equal in size");
2806 /* Remote port range is allowed to be '0' which means all ports. */
2807 if (r
->rport_cnt
!= numLocalPorts
&&
2808 (r
->rport_cnt
!= 1 || r
->rport
!= 0))
2809 errx(EX_DATAERR
, "redirect_port: remote port must"
2810 "be 0 or equal to local port range in size");
2813 * Setup LSNAT server pool.
2816 sep
= strtok(tmp_spool_buf
, ", ");
2817 while (sep
!= NULL
) {
2818 tmp
= (struct cfg_spool
*)spool_buf
;
2819 if (len
< SOF_SPOOL
)
2824 if (str2addr_portrange(sep
,
2825 &tmp
->addr
, protoName
, &portRange
) != 0)
2826 errx(EX_DATAERR
, "redirect_port:"
2827 "invalid local port range");
2828 if (GETNUMPORTS(portRange
) != 1)
2829 errx(EX_DATAERR
, "redirect_port: local port"
2830 "must be single in this context");
2831 tmp
->port
= GETLOPORT(portRange
);
2833 /* Point to the next possible cfg_spool. */
2834 spool_buf
= &spool_buf
[SOF_SPOOL
];
2835 sep
= strtok(NULL
, ", ");
2841 errx(EX_DATAERR
, "redirect_port: buf is too small\n");
2845 setup_redir_proto(char *spool_buf
, int len
, int *_ac
, char ***_av
)
2847 struct protoent
*protoent
;
2848 struct cfg_redir
*r
;
2855 if (len
>= SOF_REDIR
) {
2856 r
= (struct cfg_redir
*)spool_buf
;
2857 /* Skip cfg_redir at beginning of buf. */
2858 spool_buf
= &spool_buf
[SOF_REDIR
];
2864 r
->mode
= REDIR_PROTO
;
2869 errx(EX_DATAERR
, "redirect_proto: missing protocol");
2871 protoent
= getprotobyname(*av
);
2872 if (protoent
== NULL
)
2873 errx(EX_DATAERR
, "redirect_proto: unknown protocol %s", *av
);
2875 r
->proto
= protoent
->p_proto
;
2880 * Extract local address.
2883 errx(EX_DATAERR
, "redirect_proto: missing local address");
2885 str2addr(*av
, &r
->laddr
);
2889 * Extract optional public address.
2892 r
->paddr
.s_addr
= INADDR_ANY
;
2893 r
->raddr
.s_addr
= INADDR_ANY
;
2895 /* see above in setup_redir_port() */
2896 if (!isalpha(**av
)) {
2897 str2addr(*av
, &r
->paddr
);
2901 * Extract optional remote address.
2903 /* see above in setup_redir_port() */
2904 if (ac
!= 0 && !isalpha(**av
)) {
2905 str2addr(*av
, &r
->raddr
);
2913 errx(EX_DATAERR
, "redirect_proto: buf is too small\n");
2917 show_nat_config(char *buf
) {
2919 struct cfg_redir
*t
;
2920 struct cfg_spool
*s
;
2922 int i
, cnt
, flag
, off
;
2924 n
= (struct cfg_nat
*)buf
;
2927 printf("ipfw nat %u config", n
->id
);
2928 if (strlen(n
->if_name
) != 0)
2929 printf(" if %s", n
->if_name
);
2930 else if (n
->ip
.s_addr
!= 0)
2931 printf(" ip %s", inet_ntoa(n
->ip
));
2932 while (n
->mode
!= 0) {
2933 if (n
->mode
& PKT_ALIAS_LOG
) {
2935 n
->mode
&= ~PKT_ALIAS_LOG
;
2936 } else if (n
->mode
& PKT_ALIAS_DENY_INCOMING
) {
2938 n
->mode
&= ~PKT_ALIAS_DENY_INCOMING
;
2939 } else if (n
->mode
& PKT_ALIAS_SAME_PORTS
) {
2940 printf(" same_ports");
2941 n
->mode
&= ~PKT_ALIAS_SAME_PORTS
;
2942 } else if (n
->mode
& PKT_ALIAS_UNREGISTERED_ONLY
) {
2943 printf(" unreg_only");
2944 n
->mode
&= ~PKT_ALIAS_UNREGISTERED_ONLY
;
2945 } else if (n
->mode
& PKT_ALIAS_RESET_ON_ADDR_CHANGE
) {
2947 n
->mode
&= ~PKT_ALIAS_RESET_ON_ADDR_CHANGE
;
2948 } else if (n
->mode
& PKT_ALIAS_REVERSE
) {
2950 n
->mode
&= ~PKT_ALIAS_REVERSE
;
2951 } else if (n
->mode
& PKT_ALIAS_PROXY_ONLY
) {
2952 printf(" proxy_only");
2953 n
->mode
&= ~PKT_ALIAS_PROXY_ONLY
;
2956 /* Print all the redirect's data configuration. */
2957 for (cnt
= 0; cnt
< n
->redir_cnt
; cnt
++) {
2958 t
= (struct cfg_redir
*)&buf
[off
];
2962 printf(" redirect_addr");
2963 if (t
->spool_cnt
== 0)
2964 printf(" %s", inet_ntoa(t
->laddr
));
2966 for (i
= 0; i
< t
->spool_cnt
; i
++) {
2967 s
= (struct cfg_spool
*)&buf
[off
];
2972 printf("%s", inet_ntoa(s
->addr
));
2975 printf(" %s", inet_ntoa(t
->paddr
));
2978 p
= getprotobynumber(t
->proto
);
2979 printf(" redirect_port %s ", p
->p_name
);
2980 if (!t
->spool_cnt
) {
2981 printf("%s:%u", inet_ntoa(t
->laddr
), t
->lport
);
2982 if (t
->pport_cnt
> 1)
2983 printf("-%u", t
->lport
+ t
->pport_cnt
- 1);
2985 for (i
=0; i
< t
->spool_cnt
; i
++) {
2986 s
= (struct cfg_spool
*)&buf
[off
];
2989 printf("%s:%u", inet_ntoa(s
->addr
), s
->port
);
2994 if (t
->paddr
.s_addr
)
2995 printf("%s:", inet_ntoa(t
->paddr
));
2996 printf("%u", t
->pport
);
2997 if (!t
->spool_cnt
&& t
->pport_cnt
> 1)
2998 printf("-%u", t
->pport
+ t
->pport_cnt
- 1);
3000 if (t
->raddr
.s_addr
) {
3001 printf(" %s", inet_ntoa(t
->raddr
));
3003 printf(":%u", t
->rport
);
3004 if (!t
->spool_cnt
&& t
->rport_cnt
> 1)
3005 printf("-%u", t
->rport
+
3011 p
= getprotobynumber(t
->proto
);
3012 printf(" redirect_proto %s %s", p
->p_name
,
3013 inet_ntoa(t
->laddr
));
3014 if (t
->paddr
.s_addr
!= 0) {
3015 printf(" %s", inet_ntoa(t
->paddr
));
3016 if (t
->raddr
.s_addr
)
3017 printf(" %s", inet_ntoa(t
->raddr
));
3021 errx(EX_DATAERR
, "unknown redir mode");
3030 show_nat(int ac
, char **av
) {
3032 struct cfg_redir
*e
;
3033 int i
, nbytes
, nalloc
, size
;
3034 int nat_cnt
, redir_cnt
, nat_id
;
3046 nat_id
= strtoul(*av
, NULL
, 10);
3049 while (nbytes
>= nalloc
) {
3050 nalloc
= nalloc
* 2;
3052 if ((data
= realloc(data
, nbytes
)) == NULL
) {
3053 err(EX_OSERR
, "realloc");
3055 if (do_get_x(IP_FW_NAT_GET
, data
, &nbytes
) < 0) {
3056 err(EX_OSERR
, "do_get_x(IP_FW_NAT_GET)");
3064 nat_cnt
= *((int *)data
);
3065 for (i
= sizeof(nat_cnt
); nat_cnt
; nat_cnt
--) {
3066 n
= (struct cfg_nat
*)&data
[i
];
3067 if (n
->id
>= 0 && n
->id
<= IPFW_DEFAULT_RULE
) {
3068 if (nat_id
== 0 || n
->id
== nat_id
)
3069 show_nat_config(&data
[i
]);
3071 i
+= sizeof(struct cfg_nat
);
3072 for (redir_cnt
= 0; redir_cnt
< n
->redir_cnt
; redir_cnt
++) {
3073 e
= (struct cfg_redir
*)&data
[i
];
3074 i
+= sizeof(struct cfg_redir
) +
3075 e
->spool_cnt
* sizeof(struct cfg_spool
);
3081 get_kern_boottime(void)
3083 struct timeval boottime
;
3087 mib
[1] = KERN_BOOTTIME
;
3088 size
= sizeof(boottime
);
3089 if (sysctl(mib
, 2, &boottime
, &size
, NULL
, 0) != -1 &&
3090 boottime
.tv_sec
!= 0) {
3091 return boottime
.tv_sec
;
3097 show_nat_state(int ac
, char **av
)
3110 nat_id
= strtoul(*av
, NULL
, 10);
3113 while (nbytes
>= nalloc
) {
3114 nalloc
= nalloc
* 2;
3116 if ((data
= realloc(data
, nbytes
)) == NULL
) {
3117 err(EX_OSERR
, "realloc");
3119 memcpy(data
, &nat_id
, sizeof(int));
3120 if (do_get_x(IP_FW_NAT_LOG
, data
, &nbytes
) < 0) {
3121 err(EX_OSERR
, "do_get_x(IP_FW_NAT_GET_STATE)");
3126 struct ipfw_ioc_nat_state
*nat_state
;
3127 nat_state
=(struct ipfw_ioc_nat_state
*)data
;
3128 int count
= nbytes
/ sizeof( struct ipfw_ioc_nat_state
);
3130 uptime_sec
= get_kern_boottime();
3131 for (i
= 0; i
< count
; i
++) {
3132 struct protoent
*pe
= getprotobynumber(nat_state
->link_type
);
3133 printf("%s ", pe
->p_name
);
3134 printf("%s:%hu => ",inet_ntoa(nat_state
->src_addr
),
3135 htons(nat_state
->src_port
));
3136 printf("%s:%hu",inet_ntoa(nat_state
->alias_addr
),
3137 htons(nat_state
->alias_port
));
3138 printf(" -> %s:%hu ",inet_ntoa(nat_state
->dst_addr
),
3139 htons(nat_state
->dst_port
));
3142 time_t t
= _long_to_time(uptime_sec
+ nat_state
->timestamp
);
3143 strcpy(timestr
, ctime(&t
));
3144 *strchr(timestr
, '\n') = '\0';
3145 printf("%s ", timestr
);
3146 } else if (do_time
== 2) {
3147 printf( "%10u ", uptime_sec
+ nat_state
->timestamp
);
3155 * do_set_x - extended version og do_set
3156 * insert a x_header in the beginning of the rule buf
3157 * and call setsockopt() with IP_FW_X.
3160 do_set_x(int optname
, void *rule
, int optlen
)
3164 ip_fw_x_header
*x_header
;
3165 if (ipfw_socket
< 0)
3166 err(EX_UNAVAILABLE
, "socket not avaialble");
3167 len
= optlen
+ sizeof(ip_fw_x_header
);
3168 newbuf
= malloc(len
);
3170 err(EX_OSERR
, "malloc newbuf in do_set_x");
3172 x_header
= (ip_fw_x_header
*)newbuf
;
3173 x_header
->opcode
= optname
;
3174 /* copy the rule into the newbuf, just after the x_header*/
3175 bcopy(rule
, ++x_header
, optlen
);
3176 return setsockopt(ipfw_socket
, IPPROTO_IP
, IP_FW_X
, newbuf
, len
);
3183 do_get_x(int optname
, void *rule
, int *optlen
)
3185 int len
, *newbuf
, retval
;
3187 ip_fw_x_header
*x_header
;
3188 if (ipfw_socket
< 0)
3189 err(EX_UNAVAILABLE
, "socket not avaialble");
3190 len
= *optlen
+ sizeof(ip_fw_x_header
);
3191 newbuf
= malloc(len
);
3193 err(EX_OSERR
, "malloc newbuf in do_get_x");
3195 x_header
= (ip_fw_x_header
*)newbuf
;
3196 x_header
->opcode
= optname
;
3197 /* copy the rule into the newbuf, just after the x_header*/
3198 bcopy(rule
, ++x_header
, *optlen
);
3199 retval
= getsockopt(ipfw_socket
, IPPROTO_IP
, IP_FW_X
, newbuf
, &len
);
3200 bcopy(newbuf
, rule
, len
);
3206 config_nat(int ac
, char **av
)
3208 struct cfg_nat
*n
; /* Nat instance configuration. */
3209 int i
, len
, off
, tok
;
3210 char *id
, buf
[NAT_BUF_LEN
]; /* Buffer for serialized data. */
3213 /* Offset in buf: save space for n at the beginning. */
3214 off
= sizeof(struct cfg_nat
);
3215 memset(buf
, 0, sizeof(buf
));
3216 n
= (struct cfg_nat
*)buf
;
3220 if (ac
&& isdigit(**av
)) {
3226 errx(EX_DATAERR
, "missing nat id");
3228 errx(EX_DATAERR
, "missing option");
3231 tok
= match_token(nat_params
, *av
);
3236 errx(EX_DATAERR
, "missing option");
3237 if (!inet_aton(av
[0], &(n
->ip
)))
3238 errx(EX_DATAERR
, "bad ip address ``%s''",
3244 errx(EX_DATAERR
, "missing option");
3245 set_addr_dynamic(av
[0], n
);
3249 n
->mode
|= PKT_ALIAS_LOG
;
3252 n
->mode
|= PKT_ALIAS_DENY_INCOMING
;
3254 case TOK_SAME_PORTS
:
3255 n
->mode
|= PKT_ALIAS_SAME_PORTS
;
3257 case TOK_UNREG_ONLY
:
3258 n
->mode
|= PKT_ALIAS_UNREGISTERED_ONLY
;
3260 case TOK_RESET_ADDR
:
3261 n
->mode
|= PKT_ALIAS_RESET_ON_ADDR_CHANGE
;
3264 n
->mode
|= PKT_ALIAS_REVERSE
;
3266 case TOK_PROXY_ONLY
:
3267 n
->mode
|= PKT_ALIAS_PROXY_ONLY
;
3270 * All the setup_redir_* functions work directly in the final
3271 * buffer, see above for details.
3273 case TOK_REDIR_ADDR
:
3274 case TOK_REDIR_PORT
:
3275 case TOK_REDIR_PROTO
:
3277 case TOK_REDIR_ADDR
:
3278 i
= setup_redir_addr(&buf
[off
], len
, &ac
, &av
);
3280 case TOK_REDIR_PORT
:
3281 i
= setup_redir_port(&buf
[off
], len
, &ac
, &av
);
3283 case TOK_REDIR_PROTO
:
3284 i
= setup_redir_proto(&buf
[off
], len
, &ac
, &av
);
3292 errx(EX_DATAERR
, "unrecognised option ``%s''", av
[-1]);
3295 i
= do_set_x(IP_FW_NAT_CFG
, buf
, off
);
3297 err(1, "do_set_x(%s)", "IP_FW_NAT_CFG");
3299 /* After every modification, we show the resultant rule. */
3301 char *_av
[] = {"config", id
};
3307 ipfw_main(int ac
, char **av
)
3314 /* Set the force flag for non-interactive processes */
3315 do_force
= !isatty(STDIN_FILENO
);
3317 optind
= optreset
= 1;
3318 while ((ch
= getopt(ac
, av
, "hs:acdDefNStTv")) != -1)
3320 case 'h': /* help */
3322 break; /* NOTREACHED */
3324 case 's': /* sort */
3325 do_sort
= atoi(optarg
);
3367 NEED1("bad arguments, for usage summary ``ipfw''");
3370 * optional: pipe or queue or nat
3374 if (!strncmp(*av
, "nat", strlen(*av
)))
3376 else if (!strncmp(*av
, "pipe", strlen(*av
))) {
3378 } else if (!strncmp(*av
, "queue", strlen(*av
))) {
3381 NEED1("missing command");
3384 * for pipes and queues and nat we normally say 'pipe NN config'
3385 * but the code is easier to parse as 'pipe config NN'
3386 * so we swap the two arguments.
3388 if ((do_pipe
|| do_nat
) && ac
> 2 && isdigit(*(av
[1]))) {
3394 if (!strncmp(*av
, "add", strlen(*av
))) {
3397 } else if (!strncmp(*av
, "delete", strlen(*av
))) {
3398 delete_rules(ac
, av
);
3399 } else if (!strncmp(*av
, "flush", strlen(*av
))) {
3401 } else if (!strncmp(*av
, "list", strlen(*av
))) {
3404 } else if (!strncmp(*av
, "show", strlen(*av
))) {
3408 } else if (!strncmp(*av
, "zero", strlen(*av
))) {
3410 } else if (!strncmp(*av
, "set", strlen(*av
))) {
3411 sets_handler(ac
, av
);
3412 } else if (!strncmp(*av
, "module", strlen(*av
))) {
3414 if (!strncmp(*av
, "show", strlen(*av
)) ||
3415 !strncmp(*av
, "show", strlen(*av
))) {
3416 list_modules(ac
, av
);
3418 errx(EX_USAGE
, "bad ipfw module command `%s'", *av
);
3420 } else if (!strncmp(*av
, "resetlog", strlen(*av
))) {
3422 } else if (!strncmp(*av
, "log", strlen(*av
))) {
3424 if (!strncmp(*av
, "reset", strlen(*av
))) {
3426 } else if (!strncmp(*av
, "off", strlen(*av
))) {
3428 } else if (!strncmp(*av
, "on", strlen(*av
))) {
3431 errx(EX_USAGE
, "bad command `%s'", *av
);
3433 } else if (!strncmp(*av
, "nat", strlen(*av
))) {
3435 if (!strncmp(*av
, "config", strlen(*av
))) {
3437 } else if (!strncmp(*av
, "flush", strlen(*av
))) {
3439 } else if (!strncmp(*av
, "show", strlen(*av
)) ||
3440 !strncmp(*av
, "list", strlen(*av
))) {
3441 if (ac
> 2 && isdigit(*(av
[1]))) {
3447 if (!strncmp(*av
, "config", strlen(*av
))) {
3449 } else if (!strncmp(*av
, "state", strlen(*av
))) {
3450 show_nat_state(ac
,av
);
3453 "bad nat show command `%s'", *av
);
3455 } else if (!strncmp(*av
, "delete", strlen(*av
))) {
3456 delete_nat_config(ac
, av
);
3458 errx(EX_USAGE
, "bad ipfw nat command `%s'", *av
);
3460 } else if (!strncmp(*av
, "pipe", strlen(*av
)) ||
3461 !strncmp(*av
, "queue", strlen(*av
))) {
3463 if (!strncmp(*av
, "config", strlen(*av
))) {
3464 config_dummynet(ac
, av
);
3465 } else if (!strncmp(*av
, "flush", strlen(*av
))) {
3467 } else if (!strncmp(*av
, "show", strlen(*av
))) {
3468 show_dummynet(ac
, av
);
3470 errx(EX_USAGE
, "bad ipfw pipe command `%s'", *av
);
3472 } else if (!strncmp(*av
, "state", strlen(*av
))) {
3474 if (!strncmp(*av
, "add", strlen(*av
))) {
3476 } else if (!strncmp(*av
, "delete", strlen(*av
))) {
3477 delete_state(ac
, av
);
3478 } else if (!strncmp(*av
, "flush", strlen(*av
))) {
3479 flush_state(ac
, av
);
3480 } else if (!strncmp(*av
, "list", strlen(*av
))) {
3483 } else if (!strncmp(*av
, "show", strlen(*av
))) {
3488 errx(EX_USAGE
, "bad ipfw state command `%s'", *av
);
3490 } else if (!strncmp(*av
, "table", strlen(*av
))) {
3491 if (ac
> 2 && isdigit(*(av
[1]))) {
3497 if (!strncmp(*av
, "append", strlen(*av
))) {
3498 table_append(ac
, av
);
3499 } else if (!strncmp(*av
, "remove", strlen(*av
))) {
3500 table_remove(ac
, av
);
3501 } else if (!strncmp(*av
, "flush", strlen(*av
))) {
3502 table_flush(ac
, av
);
3503 } else if (!strncmp(*av
, "list", strlen(*av
))) {
3505 } else if (!strncmp(*av
, "show", strlen(*av
))) {
3507 } else if (!strncmp(*av
, "type", strlen(*av
))) {
3508 table_create(ac
, av
);
3509 } else if (!strncmp(*av
, "delete", strlen(*av
))) {
3510 table_delete(ac
, av
);
3511 } else if (!strncmp(*av
, "test", strlen(*av
))) {
3513 } else if (!strncmp(*av
, "name", strlen(*av
))) {
3514 table_rename(ac
, av
);
3516 errx(EX_USAGE
, "bad ipfw table command `%s'", *av
);
3520 errx(EX_USAGE
, "bad ipfw command `%s'", *av
);
3526 ipfw_readfile(int ac
, char *av
[])
3529 char *a
, *p
, *args
[MAX_ARGS
], *cmd
= NULL
;
3531 int i
=0, lineno
=0, qflag
=0, pflag
=0, status
;
3536 while ((c
= getopt(ac
, av
, "D:U:p:q")) != -1) {
3540 errx(EX_USAGE
, "-D requires -p");
3541 if (i
> MAX_ARGS
- 2)
3542 errx(EX_USAGE
, "too many -D or -U options");
3549 errx(EX_USAGE
, "-U requires -p");
3550 if (i
> MAX_ARGS
- 2)
3551 errx(EX_USAGE
, "too many -D or -U options");
3568 errx(EX_USAGE
, "bad arguments, for usage"
3569 " summary ``ipfw''");
3576 errx(EX_USAGE
, "extraneous filename arguments");
3578 if ((f
= fopen(av
[0], "r")) == NULL
)
3579 err(EX_UNAVAILABLE
, "fopen: %s", av
[0]);
3582 /* pipe through preprocessor (cpp or m4) */
3587 if (pipe(pipedes
) == -1)
3588 err(EX_OSERR
, "cannot create pipe");
3590 switch ((preproc
= fork())) {
3592 err(EX_OSERR
, "cannot fork");
3596 if (dup2(fileno(f
), 0) == -1 ||
3597 dup2(pipedes
[1], 1) == -1) {
3598 err(EX_OSERR
, "dup2()");
3604 err(EX_OSERR
, "execvp(%s) failed", cmd
);
3610 if ((f
= fdopen(pipedes
[0], "r")) == NULL
) {
3611 int savederrno
= errno
;
3613 kill(preproc
, SIGTERM
);
3615 err(EX_OSERR
, "fdopen()");
3620 while (fgets(buf
, BUFSIZ
, f
)) {
3622 sprintf(linename
, "Line %d", lineno
);
3627 if ((p
= strchr(buf
, '#')) != NULL
)
3632 for (a
= strtok(buf
, WHITESP
); a
&& i
< MAX_ARGS
;
3633 a
= strtok(NULL
, WHITESP
), i
++) {
3637 if (i
== (qflag
? 2: 1))
3640 errx(EX_USAGE
, "%s: too many arguments", linename
);
3647 if (waitpid(preproc
, &status
, 0) == -1)
3648 errx(EX_OSERR
, "waitpid()");
3649 if (WIFEXITED(status
) && WEXITSTATUS(status
) != EX_OK
)
3650 errx(EX_UNAVAILABLE
, "preprocessor exited with status %d",
3651 WEXITSTATUS(status
));
3652 else if (WIFSIGNALED(status
))
3653 errx(EX_UNAVAILABLE
, "preprocessor exited with signal %d",
3659 main(int ac
, char *av
[])
3661 ipfw_socket
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
);
3662 if (ipfw_socket
< 0)
3663 err(EX_UNAVAILABLE
, "socket");
3665 memset(keywords
, 0, sizeof(struct ipfw_keyword
) * KEYWORD_SIZE
);
3666 memset(mappings
, 0, sizeof(struct ipfw_mapping
) * MAPPING_SIZE
);
3668 prepare_default_funcs();
3670 if (ac
> 1 && av
[ac
- 1][0] == '/' && access(av
[ac
- 1], R_OK
) == 0)
3671 ipfw_readfile(ac
, av
);