1 /*
2 * Copyright (c) 2014 - 2018 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
5 * by Bill Yuan <bycn82@dragonflybsd.org>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #include <ctype.h>
36 #include <err.h>
37 #include <errno.h>
38 #include <grp.h>
39 #include <limits.h>
40 #include <netdb.h>
41 #include <pwd.h>
42 #include <signal.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <stdarg.h>
46 #include <string.h>
47 #include <sysexits.h>
48 #include <timeconv.h>
49 #include <unistd.h>
50
51 #include <netinet/in.h>
52
53 #include <arpa/inet.h>
54 #include <net/if.h>
55 #include <net/route.h>
56 #include <net/pfil.h>
57
58 #include <net/ipfw3/ip_fw3.h>
59 #include "../../../sbin/ipfw3/ipfw3.h"
60 #include "ipfw3_basic.h"
61
62
63 #define IP_MASK_ALL 0xffffffff
64 /*
65 * we use IPPROTO_ETHERTYPE as a fake protocol id to call the print routines
66 * This is only used in this code.
67 */
68 #define IPPROTO_ETHERTYPE 0x1000
69
70
71 struct char_int_map limit_types[] = {
72 { "src-addr", 1 },
73 { "src-port", 2 },
74 { "dst-addr", 3 },
75 { "dst-port", 4 },
76 { NULL, 0 }
77 };
78
79 static struct char_int_map ether_types[] = {
80 { "ip", 0x0800 },
81 { "ipv4", 0x0800 },
82 { "ipv6", 0x86dd },
83 { "arp", 0x0806 },
84 { "rarp", 0x8035 },
85 { "vlan", 0x8100 },
86 { "loop", 0x9000 },
87 { "trail", 0x1000 },
88 { "pppoe_disc", 0x8863 },
89 { "pppoe_sess", 0x8864 },
90 { "ipx_8022", 0x00E0 },
91 { "ipx_8023", 0x0000 },
92 { "ipx_ii", 0x8137 },
93 { "ipx_snap", 0x8137 },
94 { "ipx", 0x8137 },
95 { "ns", 0x0600 },
96 { NULL, 0 }
97 };
98
99
100 int
match_token(struct char_int_map * table,char * string)101 match_token(struct char_int_map *table, char *string)
102 {
103 while (table->key) {
104 if (strcmp(table->key, string) == 0) {
105 return table->val;
106 }
107 table++;
108 }
109 return 0;
110 }
111
112 static char *
match_token2(struct char_int_map * table,int val)113 match_token2(struct char_int_map *table, int val)
114 {
115 while (table->val) {
116 if (table->val == val)
117 return table->key;
118
119 table++;
120 }
121 return NULL;
122 };
123
124 static void
fill_iface(ipfw_insn_if * cmd,char * arg)125 fill_iface(ipfw_insn_if *cmd, char *arg)
126 {
127 cmd->name[0] = '\0';
128 cmd->o.len |= F_INSN_SIZE(ipfw_insn_if);
129
130 /* Parse the interface or address */
131 if (!strcmp(arg, "any")){
132 cmd->o.len = 0;
133 } else if (!isdigit(*arg)) {
134 strlcpy(cmd->name, arg, sizeof(cmd->name));
135 cmd->p.glob = strpbrk(arg, "*?[") != NULL ? 1 : 0;
136 } else if (!inet_aton(arg, &cmd->p.ip))
137 errx(EX_DATAERR, "bad ip address ``%s''", arg);
138 }
139
140 static int
lookup_host(char * host,struct in_addr * ipaddr)141 lookup_host (char *host, struct in_addr *ipaddr)
142 {
143 struct hostent *he;
144
145 if (!inet_aton(host, ipaddr)) {
146 if ((he = gethostbyname(host)) == NULL)
147 return -1;
148 *ipaddr = *(struct in_addr *)he->h_addr_list[0];
149 }
150 return 0;
151 }
152
153 /*
154 * Like strtol, but also translates service names into port numbers
155 * for some protocols.
156 * In particular:
157 * proto == -1 disables the protocol check;
158 * proto == IPPROTO_ETHERTYPE looks up an internal table
159 * proto == <some value in /etc/protocols> matches the values there.
160 * Returns *end == s in case the parameter is not found.
161 */
162 static int
strtoport(char * s,char ** end,int base,int proto)163 strtoport(char *s, char **end, int base, int proto)
164 {
165 char *p, *buf;
166 char *s1;
167 int i;
168
169 *end = s; /* default - not found */
170 if ( *s == '\0')
171 return 0; /* not found */
172
173 if (isdigit(*s))
174 return strtol(s, end, base);
175
176 /*
177 * find separator. '\\' escapes the next char.
178 */
179 for (s1 = s; *s1 && (isalnum(*s1) || *s1 == '\\') ; s1++) {
180 if (*s1 == '\\' && s1[1] != '\0')
181 s1++;
182 }
183
184 buf = malloc(s1 - s + 1);
185 if (buf == NULL)
186 return 0;
187
188 /*
189 * copy into a buffer skipping backslashes
190 */
191 for (p = s, i = 0; p != s1 ; p++)
192 if ( *p != '\\')
193 buf[i++] = *p;
194 buf[i++] = '\0';
195
196 if (proto == IPPROTO_ETHERTYPE) {
197 i = match_token(ether_types, buf);
198 free(buf);
199 if (i != -1) { /* found */
200 *end = s1;
201 return i;
202 }
203 } else {
204 struct protoent *pe = NULL;
205 struct servent *se;
206
207 if (proto != 0)
208 pe = getprotobynumber(proto);
209 setservent(1);
210 se = getservbyname(buf, pe ? pe->p_name : NULL);
211 free(buf);
212 if (se != NULL) {
213 *end = s1;
214 return ntohs(se->s_port);
215 }
216 }
217 return 0; /* not found */
218 }
219
220 static int
contigmask(u_char * p,int len)221 contigmask(u_char *p, int len)
222 {
223 int i, n;
224 for (i=0; i<len ; i++) {
225 if ( (p[i/8] & (1 << (7 - (i%8)))) == 0) /* first bit unset */
226 break;
227 }
228 for (n=i+1; n < len; n++) {
229 if ( (p[n/8] & (1 << (7 - (n%8)))) != 0)
230 return -1; /* mask not contiguous */
231 }
232 return i;
233 }
234
235 static ipfw_insn
add_proto(ipfw_insn * cmd,char * av)236 *add_proto(ipfw_insn *cmd, char *av)
237 {
238 struct protoent *pe;
239 u_char proto = 0;
240 if (!strncmp(av, "all", strlen(av))) {
241 ;
242 } else if ((proto = atoi(av)) > 0) {
243 ;
244 } else if ((pe = getprotobyname(av)) != NULL) {
245 proto = pe->p_proto;
246 } else {
247 errx(EX_USAGE, "protocol `%s' not recognizable\n", av);
248 }
249 if (proto != IPPROTO_IP) {
250 cmd->opcode = O_BASIC_PROTO;
251 cmd->module = MODULE_BASIC_ID;
252 cmd->len |= LEN_OF_IPFWINSN;
253 cmd->arg1 = proto;
254 }
255 return cmd;
256 }
257
258 void
parse_count(ipfw_insn ** cmd,int * ac,char ** av[])259 parse_count(ipfw_insn **cmd, int *ac, char **av[])
260 {
261 (*cmd)->opcode = O_BASIC_COUNT;
262 (*cmd)->module = MODULE_BASIC_ID;
263 (*cmd)->len |= LEN_OF_IPFWINSN;
264 NEXT_ARG1;
265 }
266
267 void
parse_skipto(ipfw_insn ** cmd,int * ac,char ** av[])268 parse_skipto(ipfw_insn **cmd, int *ac, char **av[])
269 {
270 NEXT_ARG1;
271 (*cmd)->opcode = O_BASIC_SKIPTO;
272 (*cmd)->module = MODULE_BASIC_ID;
273 (*cmd)->len |= LEN_OF_IPFWINSN;
274 (*cmd)->arg1 = strtoul(**av, NULL, 10);
275 NEXT_ARG1;
276 }
277
278 /*
279 * cmd->arg3 is count of the destination
280 * cmd->arg1 is the type, random 0, round-robin 1, sticky 2
281 */
282 void
parse_forward(ipfw_insn ** cmd,int * ac,char ** av[])283 parse_forward(ipfw_insn **cmd, int *ac, char **av[])
284 {
285 ipfw_insn_sa *p = (ipfw_insn_sa *)(*cmd);
286 struct sockaddr_in *sa;
287 char *tok, *end = NULL;
288 char *str;
289 int count, port;
290
291 (*cmd)->opcode = O_BASIC_FORWARD;
292 NEXT_ARG1;
293 /*
294 * multiple forward destinations are seperated by colon
295 * ip address and port are seperated by comma
296 * e.g. 192.168.1.1:80,192.168.1.2:8080
297 * 192.168.1.1,192.168.1.2 or keep the port the same
298 */
299 tok = strtok(**av, ",");
300 sa = &p->sa;
301 count = 0;
302 while (tok != NULL) {
303 sa->sin_len = sizeof(struct sockaddr_in);
304 sa->sin_family = AF_INET;
305 sa->sin_port = 0;
306 str = strchr(tok,':');
307 if (str != NULL) {
308 *(str++) = '\0';
309 port = strtoport(str, &end, 0, 0);
310 sa->sin_port = (u_short)port;
311 }
312 if (lookup_host(tok, &(sa->sin_addr)) != 0)
313 errx(EX_DATAERR, "forward `%s' invalid dst", tok);
314 tok = strtok (NULL, ",");
315 sa++;
316 count++;
317 }
318 (*cmd)->arg3 = count;
319 if (count == 0) {
320 errx(EX_DATAERR, "forward `%s' not recognizable", **av);
321 }
322 NEXT_ARG1;
323 if (count > 1) {
324 if (strcmp(**av, "round-robin") == 0) {
325 NEXT_ARG1;
326 (*cmd)->arg1 = 1;
327 } else if (strcmp(**av, "sticky") == 0) {
328 NEXT_ARG1;
329 (*cmd)->arg1 = 2;
330 } else {
331 /* random */
332 (*cmd)->arg1 = 0;
333 }
334 }
335 (*cmd)->len = LEN_OF_IPFWINSN + count * sizeof(struct sockaddr_in);
336 }
337
338 void
parse_in(ipfw_insn ** cmd,int * ac,char ** av[])339 parse_in(ipfw_insn **cmd, int *ac, char **av[])
340 {
341 (*cmd)->opcode = O_BASIC_IN;
342 (*cmd)->module = MODULE_BASIC_ID;
343 (*cmd)->len |= LEN_OF_IPFWINSN;
344 (*cmd)->arg1 = 0;
345 NEXT_ARG1;
346 }
347
348 void
parse_out(ipfw_insn ** cmd,int * ac,char ** av[])349 parse_out(ipfw_insn **cmd, int *ac, char **av[])
350 {
351 (*cmd)->opcode = O_BASIC_OUT;
352 (*cmd)->module = MODULE_BASIC_ID;
353 (*cmd)->len |= LEN_OF_IPFWINSN;
354 (*cmd)->arg1 = 0;
355 NEXT_ARG1;
356 }
357
358
359 void
parse_via(ipfw_insn ** cmd,int * ac,char ** av[])360 parse_via(ipfw_insn **cmd, int *ac, char **av[])
361 {
362 (*cmd)->module = MODULE_BASIC_ID;
363 (*cmd)->len |= LEN_OF_IPFWINSN;
364 if (strcmp(*av[0], "via")==0) {
365 (*cmd)->opcode = O_BASIC_VIA;
366 } else if (strcmp(*av[0], "xmit")==0) {
367 (*cmd)->opcode = O_BASIC_XMIT;
368 } else if (strcmp(*av[0], "recv")==0) {
369 (*cmd)->opcode = O_BASIC_RECV;
370 }
371 NEXT_ARG1;
372 fill_iface((ipfw_insn_if *)(*cmd), *av[0]);
373 NEXT_ARG1;
374 }
375
376 void
parse_src_port(ipfw_insn ** cmd,int * ac,char ** av[])377 parse_src_port(ipfw_insn **cmd, int *ac, char **av[])
378 {
379 NEXT_ARG1;
380 (*cmd)->opcode = O_BASIC_IP_SRCPORT;
381 (*cmd)->module = MODULE_BASIC_ID;
382 (*cmd)->len |= LEN_OF_IPFWINSN;
383 double v = strtol(**av, NULL, 0);
384 if (v <= 0 || v >= 65535)
385 errx(EX_NOHOST, "port `%s' invalid", **av);
386 (*cmd)->arg1 = v;
387 NEXT_ARG1;
388 }
389
390 void
parse_dst_port(ipfw_insn ** cmd,int * ac,char ** av[])391 parse_dst_port(ipfw_insn **cmd, int *ac, char **av[])
392 {
393 NEXT_ARG1;
394 (*cmd)->opcode = O_BASIC_IP_DSTPORT;
395 (*cmd)->module = MODULE_BASIC_ID;
396 (*cmd)->len |= LEN_OF_IPFWINSN;
397 double v = strtol(**av, NULL, 0);
398 if (v <= 0 || v >= 65535)
399 errx(EX_NOHOST, "port `%s' invalid", **av);
400 (*cmd)->arg1 = v;
401 NEXT_ARG1;
402 }
403
404 /*
405 * Below formats are supported:
406 * from table 1 O_BASIC_IP_SRC_LOOKUP
407 * from any return 0 len instruction
408 * from me O_BASIC_IP_SRC_ME
409 * from 1.2.3.4 O_BASIC_IP_SRC
410 * from 1.2.3.4/24 O_BASIC_IP_SRC_MASK
411 */
412 void
parse_from(ipfw_insn ** cmd,int * ac,char ** av[])413 parse_from(ipfw_insn **cmd, int *ac, char **av[])
414 {
415 ipfw_insn_ip *p = (ipfw_insn_ip *)(*cmd);
416 double port;
417 int i;
418
419 (*cmd)->module = MODULE_BASIC_ID;
420 NEXT_ARG1;
421 if (strcmp(**av, "table") == 0) {
422 NEXT_ARG1;
423 NEED(*ac, 1, "table id missing");
424 (*cmd)->len |= F_INSN_SIZE(ipfw_insn);
425 (*cmd)->opcode = O_BASIC_IP_SRC_LOOKUP;
426 (*cmd)->arg1 = strtoul(**av, NULL, 10);
427 } else if (strcmp(**av, "any") == 0) {
428 (*cmd)->len &= ~F_LEN_MASK;
429 } else if (strcmp(**av, "me") == 0) {
430 (*cmd)->len |= F_INSN_SIZE(ipfw_insn);
431 (*cmd)->opcode = O_BASIC_IP_SRC_ME;
432 } else {
433 char *c = NULL, md = 0;
434 c = strchr(**av, '/');
435 if (!c)
436 c = strchr(**av, ':');
437 if (c) {
438 md = *c;
439 *c++ = '\0';
440 }
441 if (lookup_host(**av, &p->addr) != 0)
442 errx(EX_NOHOST, "hostname ``%s'' unknown", **av);
443 switch (md) {
444 case ':':
445 port = strtol(c, NULL, 0);
446 if (port <= 0 || port >= 65535)
447 errx(EX_NOHOST, "port `%s' invalid", c);
448 (*cmd)->arg1 = port;
449 (*cmd)->len |= F_INSN_SIZE(ipfw_insn_ip);
450 (*cmd)->opcode = O_BASIC_IP_SRC_N_PORT;
451 break;
452 case '/':
453 i = atoi(c);
454 if (i == 0)
455 p->mask.s_addr = htonl(0);
456 else if (i > 32)
457 errx(EX_DATAERR, "bad width ``%s''", c);
458 else
459 p->mask.s_addr = htonl(~0 << (32 - i));
460 (*cmd)->len |= F_INSN_SIZE(ipfw_insn_ip);
461 (*cmd)->opcode = O_BASIC_IP_SRC_MASK;
462 p->addr.s_addr &= p->mask.s_addr;
463 break;
464 default:
465 p->mask.s_addr = htonl(~0);
466 (*cmd)->len |= F_INSN_SIZE(ipfw_insn_u32);
467 (*cmd)->opcode = O_BASIC_IP_SRC;
468 break;
469 }
470 }
471 NEXT_ARG1;
472 }
473
474 void
parse_to(ipfw_insn ** cmd,int * ac,char ** av[])475 parse_to(ipfw_insn **cmd, int *ac, char **av[])
476 {
477 ipfw_insn_ip *p = (ipfw_insn_ip *)(*cmd);
478 double port;
479 int i;
480
481 (*cmd)->module = MODULE_BASIC_ID;
482 NEXT_ARG1;
483 if (strcmp(**av, "table") == 0) {
484 NEXT_ARG1;
485 NEED(*ac, 1, "table id missing");
486 (*cmd)->len |= F_INSN_SIZE(ipfw_insn);
487 (*cmd)->opcode = O_BASIC_IP_DST_LOOKUP;
488 (*cmd)->arg1 = strtoul(**av, NULL, 10);
489 } else if (strcmp(**av, "any") == 0) {
490 (*cmd)->len &= ~F_LEN_MASK;
491 } else if (strcmp(**av, "me") == 0) {
492 (*cmd)->len |= F_INSN_SIZE(ipfw_insn);
493 (*cmd)->opcode = O_BASIC_IP_DST_ME;
494 } else {
495 char *c = NULL, md = 0;
496 c = strchr(**av, '/');
497 if (!c)
498 c = strchr(**av, ':');
499 if (c) {
500 md = *c;
501 *c++ = '\0';
502 }
503 if (lookup_host(**av, &p->addr) != 0)
504 errx(EX_NOHOST, "hostname ``%s'' unknown", **av);
505 switch (md) {
506 case ':':
507 port = strtol(c, NULL, 0);
508 if (port <= 0 || port >= 65535)
509 errx(EX_NOHOST, "port `%s' invalid", c);
510 (*cmd)->arg1 = port;
511 (*cmd)->len |= F_INSN_SIZE(ipfw_insn_ip);
512 (*cmd)->opcode = O_BASIC_IP_DST_N_PORT;
513 break;
514 case '/':
515 i = atoi(c);
516 if (i == 0)
517 p->mask.s_addr = htonl(0);
518 else if (i > 32)
519 errx(EX_DATAERR, "bad width ``%s''", c);
520 else
521 p->mask.s_addr = htonl(~0 << (32 - i));
522 (*cmd)->len |= F_INSN_SIZE(ipfw_insn_ip);
523 (*cmd)->opcode = O_BASIC_IP_DST_MASK;
524 p->addr.s_addr &= p->mask.s_addr;
525 break;
526 default:
527 p->mask.s_addr = htonl(~0);
528 (*cmd)->len |= F_INSN_SIZE(ipfw_insn_u32);
529 (*cmd)->opcode = O_BASIC_IP_DST;
530 break;
531 }
532 }
533 NEXT_ARG1;
534
535 }
536
537 void
parse_proto(ipfw_insn ** cmd,int * ac,char ** av[])538 parse_proto(ipfw_insn **cmd, int *ac, char **av[])
539 {
540 add_proto(*cmd, **av);
541 NEXT_ARG1;
542 }
543
544 void
parse_prob(ipfw_insn ** cmd,int * ac,char ** av[])545 parse_prob(ipfw_insn **cmd, int *ac, char **av[])
546 {
547 NEXT_ARG1;
548 (*cmd)->opcode = O_BASIC_PROB;
549 (*cmd)->module = MODULE_BASIC_ID;
550 (*cmd)->len |= LEN_OF_IPFWINSN;
551 (*cmd)->arg1 = strtoul(**av, NULL, 10);
552 NEXT_ARG1;
553 }
554
555 void
parse_keep_state(ipfw_insn ** cmd,int * ac,char ** av[])556 parse_keep_state(ipfw_insn **cmd, int *ac, char **av[])
557 {
558 NEXT_ARG1;
559 (*cmd)->opcode = O_BASIC_KEEP_STATE;
560 (*cmd)->module = MODULE_BASIC_ID;
561 (*cmd)->len |= LEN_OF_IPFWINSN;
562 if (strcmp(**av, "limit") == 0) {
563 NEXT_ARG1;
564 (*cmd)->arg3 = match_token(limit_types, **av);
565 if ((*cmd)->arg3 == 0)
566 errx(EX_DATAERR, "limit `%s' not recognizable", **av);
567
568 NEXT_ARG1;
569 (*cmd)->arg1 = strtoul(**av, NULL, 10);
570 if ((*cmd)->arg1 == 0)
571 errx(EX_DATAERR, "bad limit `%s'", **av);
572
573 NEXT_ARG1;
574 }
575 if (strcmp(**av, "live") == 0) {
576 NEXT_ARG1;
577 (*cmd)->arg2 = strtoul(**av, NULL, 10);
578 NEXT_ARG1;
579 }
580 }
581
582 void
parse_check_state(ipfw_insn ** cmd,int * ac,char ** av[])583 parse_check_state(ipfw_insn **cmd, int *ac, char **av[])
584 {
585 NEXT_ARG1;
586 (*cmd)->opcode = O_BASIC_CHECK_STATE;
587 (*cmd)->module = MODULE_BASIC_ID;
588 (*cmd)->len |= LEN_OF_IPFWINSN;
589 }
590
591 void
parse_tagged(ipfw_insn ** cmd,int * ac,char ** av[])592 parse_tagged(ipfw_insn **cmd, int *ac, char **av[])
593 {
594 NEXT_ARG1;
595 (*cmd)->opcode = O_BASIC_TAGGED;
596 (*cmd)->module = MODULE_BASIC_ID;
597 (*cmd)->len |= LEN_OF_IPFWINSN;
598 (*cmd)->arg1 = strtoul(**av, NULL, 10);
599 NEXT_ARG1;
600 }
601
602 void
parse_comment(ipfw_insn ** cmd,int * ac,char ** av[])603 parse_comment(ipfw_insn **cmd, int *ac, char **av[])
604 {
605 int l = 0;
606 char *p = (char *)((*cmd) + 1);
607
608 NEXT_ARG1;
609 (*cmd)->opcode = O_BASIC_COMMENT;
610 (*cmd)->module = MODULE_BASIC_ID;
611
612 while (*ac > 0) {
613 l += strlen(**av) + 1;
614 if (l > 84) {
615 errx(EX_DATAERR, "comment too long (max 80 chars)");
616 }
617 strcpy(p, **av);
618 p += strlen(**av);
619 *p++ = ' ';
620 NEXT_ARG1;
621 }
622 l = 1 + (l + 3) / 4;
623 (*cmd)->len |= l;
624 *(--p) = '\0';
625 }
626
627 void
parse_tag(ipfw_insn ** cmd,int * ac,char ** av[])628 parse_tag(ipfw_insn **cmd, int *ac, char **av[])
629 {
630 NEXT_ARG1;
631 (*cmd)->opcode = O_BASIC_TAG;
632 (*cmd)->module = MODULE_BASIC_ID;
633 (*cmd)->len |= LEN_OF_IPFWINSN;
634 (*cmd)->arg1 = strtoul(**av, NULL, 10);
635 NEXT_ARG1;
636 }
637
638 void
parse_untag(ipfw_insn ** cmd,int * ac,char ** av[])639 parse_untag(ipfw_insn **cmd, int *ac, char **av[])
640 {
641 NEXT_ARG1;
642 (*cmd)->opcode = O_BASIC_UNTAG;
643 (*cmd)->module = MODULE_BASIC_ID;
644 (*cmd)->len |= LEN_OF_IPFWINSN;
645 (*cmd)->arg1 = strtoul(**av, NULL, 10);
646 NEXT_ARG1;
647 }
648
649 void
show_count(ipfw_insn * cmd,int show_or)650 show_count(ipfw_insn *cmd, int show_or)
651 {
652 printf(" count");
653 }
654
655 void
show_skipto(ipfw_insn * cmd,int show_or)656 show_skipto(ipfw_insn *cmd, int show_or)
657 {
658 printf(" skipto %u", cmd->arg1);
659 }
660
661 void
show_forward(ipfw_insn * cmd,int show_or)662 show_forward(ipfw_insn *cmd, int show_or)
663 {
664 struct sockaddr_in *sa;
665 int i;
666
667 ipfw_insn_sa *s = (ipfw_insn_sa *)cmd;
668 sa = &s->sa;
669 printf(" forward");
670 for (i = 0; i < cmd->arg3; i++){
671 if (i > 0)
672 printf(",");
673 else
674 printf(" ");
675
676 printf("%s", inet_ntoa(sa->sin_addr));
677 if (sa->sin_port != 0)
678 printf(":%d", sa->sin_port);
679
680 sa++;
681 }
682 if (cmd->arg1 == 1)
683 printf(" round-robin");
684 else if (cmd->arg1 == 2)
685 printf(" sticky");
686
687 }
688
689 void
show_in(ipfw_insn * cmd,int show_or)690 show_in(ipfw_insn *cmd, int show_or)
691 {
692 printf(" in");
693 }
694
695 void
show_out(ipfw_insn * cmd,int show_or)696 show_out(ipfw_insn *cmd, int show_or)
697 {
698 printf(" out");
699 }
700
701 void
show_via(ipfw_insn * cmd,int show_or)702 show_via(ipfw_insn *cmd, int show_or)
703 {
704 char *s;
705 ipfw_insn_if *cmdif = (ipfw_insn_if *)cmd;
706
707 if ((int)cmd->opcode == O_BASIC_XMIT)
708 s = "xmit";
709 else if ((int)cmd->opcode == O_BASIC_RECV)
710 s = "recv";
711 else if ((int)cmd->opcode == O_BASIC_VIA)
712 s = "via";
713 else
714 s = "?huh?";
715 if (show_or)
716 s = "or";
717 if (cmdif->name[0] == '\0')
718 printf(" %s %s", s, inet_ntoa(cmdif->p.ip));
719
720 printf(" %s %s", s, cmdif->name);
721 }
722
723 void
show_src_port(ipfw_insn * cmd,int show_or)724 show_src_port(ipfw_insn *cmd, int show_or)
725 {
726 char *word = "src-port";
727 if (show_or)
728 word = "or";
729 printf(" %s %d", word, cmd->arg1);
730 }
731
732 void
show_dst_port(ipfw_insn * cmd,int show_or)733 show_dst_port(ipfw_insn *cmd, int show_or)
734 {
735 char *word = "dst-port";
736 if (show_or)
737 word = "or";
738 printf(" %s %d", word, cmd->arg1);
739 }
740
741 void
show_from(ipfw_insn * cmd,int show_or)742 show_from(ipfw_insn *cmd, int show_or)
743 {
744 char *word = "from";
745 if (show_or)
746 word = "or";
747 printf(" %s %s", word, inet_ntoa(((ipfw_insn_ip *)cmd)->addr));
748 }
749
750 void
show_from_lookup(ipfw_insn * cmd,int show_or)751 show_from_lookup(ipfw_insn *cmd, int show_or)
752 {
753 char *word = "from";
754 if (show_or)
755 word = "or";
756 printf(" %s table %d", word, cmd->arg1);
757 }
758
759 void
show_from_me(ipfw_insn * cmd,int show_or)760 show_from_me(ipfw_insn *cmd, int show_or)
761 {
762 char *word = "from";
763 if (show_or)
764 word = "or";
765 printf(" %s me", word);
766 }
767
768 void
show_from_mask(ipfw_insn * cmd,int show_or)769 show_from_mask(ipfw_insn *cmd, int show_or)
770 {
771 int mask;
772 char *word = "from";
773 if (show_or)
774 word = "or";
775 ipfw_insn_ip *p = (ipfw_insn_ip *)cmd;
776 printf(" %s %s", word, inet_ntoa(p->addr));
777
778 mask = contigmask((u_char *)&(p->mask.s_addr), 32);
779 if (mask < 32)
780 printf("/%d", mask);
781 }
782
783 void
show_from_src_n_port(ipfw_insn * cmd,int show_or)784 show_from_src_n_port(ipfw_insn *cmd, int show_or)
785 {
786 char *word = "from";
787 if (show_or)
788 word = "or";
789 ipfw_insn_ip *p = (ipfw_insn_ip *)cmd;
790 printf(" %s %s", word, inet_ntoa(p->addr));
791 printf(":%d", cmd->arg1);
792 }
793
794 void
show_to(ipfw_insn * cmd,int show_or)795 show_to(ipfw_insn *cmd, int show_or)
796 {
797 char *word = "to";
798 if (show_or)
799 word = "or";
800 ipfw_insn_ip *p = (ipfw_insn_ip *)cmd;
801 printf(" %s %s", word, inet_ntoa(p->addr));
802 }
803
804 void
show_to_lookup(ipfw_insn * cmd,int show_or)805 show_to_lookup(ipfw_insn *cmd, int show_or)
806 {
807 char *word = "to";
808 if (show_or)
809 word = "or";
810 printf(" %s table %d", word, cmd->arg1);
811 }
812
813 void
show_to_me(ipfw_insn * cmd,int show_or)814 show_to_me(ipfw_insn *cmd, int show_or)
815 {
816 char *word = "to";
817 if (show_or)
818 word = "or";
819 printf(" %s me", word);
820 }
821
822 void
show_to_mask(ipfw_insn * cmd,int show_or)823 show_to_mask(ipfw_insn *cmd, int show_or)
824 {
825 int mask;
826 char *word = "to";
827 if (show_or)
828 word = "or";
829 ipfw_insn_ip *p = (ipfw_insn_ip *)cmd;
830 printf(" %s %s", word, inet_ntoa(p->addr));
831
832 mask = contigmask((u_char *)&(p->mask.s_addr), 32);
833 if (mask < 32)
834 printf("/%d", mask);
835 }
836
837 void
show_to_src_n_port(ipfw_insn * cmd,int show_or)838 show_to_src_n_port(ipfw_insn *cmd, int show_or)
839 {
840 char *word = "to";
841 if (show_or)
842 word = "or";
843 printf(" %s %s", word, inet_ntoa(((ipfw_insn_ip *)cmd)->addr));
844 printf(":%d", cmd->arg1);
845 }
846
847 void
show_proto(ipfw_insn * cmd,int show_or)848 show_proto(ipfw_insn *cmd, int show_or)
849 {
850 struct protoent *pe;
851 u_char proto = 0;
852 proto = cmd->arg1;
853 pe = getprotobynumber(cmd->arg1);
854 printf(" %s", pe->p_name);
855 }
856
857 void
show_prob(ipfw_insn * cmd,int show_or)858 show_prob(ipfw_insn *cmd, int show_or)
859 {
860 char *word = "prob";
861 if (show_or)
862 word = "or";
863 printf(" %s %d%%", word, cmd->arg1);
864 }
865
866 void
show_keep_state(ipfw_insn * cmd,int show_or)867 show_keep_state(ipfw_insn *cmd, int show_or)
868 {
869 printf(" keep-state");
870 if (cmd->arg1 != 0) {
871 char *type=match_token2(limit_types, cmd->arg3);
872 printf(" limit %s %d", type, cmd->arg1);
873 }
874 if (cmd->arg2 != 0) {
875 printf(" live %d", cmd->arg2);
876 }
877 }
878
879 void
show_check_state(ipfw_insn * cmd,int show_or)880 show_check_state(ipfw_insn *cmd, int show_or)
881 {
882 printf(" check-state");
883 }
884
885 void
show_tagged(ipfw_insn * cmd,int show_or)886 show_tagged(ipfw_insn *cmd, int show_or)
887 {
888 printf(" tagged %d", cmd->arg1);
889 }
890
891 void
show_comment(ipfw_insn * cmd,int show_or)892 show_comment(ipfw_insn *cmd, int show_or)
893 {
894 printf(" // %s", (char *)(cmd + 1));
895 }
896
897 void
show_tag(ipfw_insn * cmd,int show_or)898 show_tag(ipfw_insn *cmd, int show_or)
899 {
900 printf(" tag %d", cmd->arg1);
901 }
902
903 void
show_untag(ipfw_insn * cmd,int show_or)904 show_untag(ipfw_insn *cmd, int show_or)
905 {
906 printf(" untag %d", cmd->arg1);
907 }
908
909 void
load_module(register_func function,register_keyword keyword)910 load_module(register_func function, register_keyword keyword)
911 {
912 keyword(MODULE_BASIC_ID, O_BASIC_COUNT, "count", ACTION);
913 function(MODULE_BASIC_ID, O_BASIC_COUNT,
914 (parser_func)parse_count, (shower_func)show_count);
915
916 keyword(MODULE_BASIC_ID, O_BASIC_SKIPTO, "skipto", ACTION);
917 function(MODULE_BASIC_ID, O_BASIC_SKIPTO,
918 (parser_func)parse_skipto, (shower_func)show_skipto);
919
920 keyword(MODULE_BASIC_ID, O_BASIC_FORWARD, "forward", ACTION);
921 function(MODULE_BASIC_ID, O_BASIC_FORWARD,
922 (parser_func)parse_forward, (shower_func)show_forward);
923
924 keyword(MODULE_BASIC_ID, O_BASIC_IN, "in", FILTER);
925 function(MODULE_BASIC_ID, O_BASIC_IN,
926 (parser_func)parse_in, (shower_func)show_in);
927
928 keyword(MODULE_BASIC_ID, O_BASIC_OUT, "out", FILTER);
929 function(MODULE_BASIC_ID, O_BASIC_OUT,
930 (parser_func)parse_out, (shower_func)show_out);
931
932 keyword(MODULE_BASIC_ID, O_BASIC_VIA, "via", FILTER);
933 function(MODULE_BASIC_ID, O_BASIC_VIA,
934 (parser_func)parse_via, (shower_func)show_via);
935
936 keyword(MODULE_BASIC_ID, O_BASIC_XMIT, "xmit", FILTER);
937 function(MODULE_BASIC_ID, O_BASIC_XMIT,
938 (parser_func)parse_via, (shower_func)show_via);
939
940 keyword(MODULE_BASIC_ID, O_BASIC_RECV, "recv", FILTER);
941 function(MODULE_BASIC_ID, O_BASIC_RECV,
942 (parser_func)parse_via, (shower_func)show_via);
943
944 keyword(MODULE_BASIC_ID, O_BASIC_IP_SRCPORT, "src-port", FILTER);
945 function(MODULE_BASIC_ID, O_BASIC_IP_SRCPORT,
946 (parser_func)parse_src_port, (shower_func)show_src_port);
947
948 keyword(MODULE_BASIC_ID, O_BASIC_IP_DSTPORT, "dst-port", FILTER);
949 function(MODULE_BASIC_ID, O_BASIC_IP_DSTPORT,
950 (parser_func)parse_dst_port, (shower_func)show_dst_port);
951
952 keyword(MODULE_BASIC_ID, O_BASIC_IP_SRC, "from", FROM);
953 function(MODULE_BASIC_ID, O_BASIC_IP_SRC,
954 (parser_func)parse_from, (shower_func)show_from);
955
956 keyword(MODULE_BASIC_ID, O_BASIC_IP_SRC_LOOKUP, "from-[table]", FROM);
957 function(MODULE_BASIC_ID, O_BASIC_IP_SRC_LOOKUP,
958 (parser_func)parse_from, (shower_func)show_from_lookup);
959
960 keyword(MODULE_BASIC_ID, O_BASIC_IP_SRC_ME, "from-[me]", FROM);
961 function(MODULE_BASIC_ID, O_BASIC_IP_SRC_ME,
962 (parser_func)parse_from, (shower_func)show_from_me);
963
964 keyword(MODULE_BASIC_ID, O_BASIC_IP_SRC_MASK, "from-[mask]", FROM);
965 function(MODULE_BASIC_ID, O_BASIC_IP_SRC_MASK,
966 (parser_func)parse_from, (shower_func)show_from_mask);
967
968 keyword(MODULE_BASIC_ID, O_BASIC_IP_SRC_N_PORT, "from-[ip:port]", FROM);
969 function(MODULE_BASIC_ID, O_BASIC_IP_SRC_N_PORT,
970 (parser_func)parse_from, (shower_func)show_from_src_n_port);
971
972 keyword(MODULE_BASIC_ID, O_BASIC_IP_DST, "to", TO);
973 function(MODULE_BASIC_ID, O_BASIC_IP_DST,
974 (parser_func)parse_to, (shower_func)show_to);
975
976 keyword(MODULE_BASIC_ID, O_BASIC_IP_DST_LOOKUP, "to-[table]", TO);
977 function(MODULE_BASIC_ID, O_BASIC_IP_DST_LOOKUP,
978 (parser_func)parse_to, (shower_func)show_to_lookup);
979
980 keyword(MODULE_BASIC_ID, O_BASIC_IP_DST_ME, "to-[me]", TO);
981 function(MODULE_BASIC_ID, O_BASIC_IP_DST_ME,
982 (parser_func)parse_to, (shower_func)show_to_me);
983
984 keyword(MODULE_BASIC_ID, O_BASIC_IP_DST_MASK, "to-[mask]", TO);
985 function(MODULE_BASIC_ID, O_BASIC_IP_DST_MASK,
986 (parser_func)parse_to, (shower_func)show_to_mask);
987
988 keyword(MODULE_BASIC_ID, O_BASIC_IP_DST_N_PORT, "to-[ip:port]", FROM);
989 function(MODULE_BASIC_ID, O_BASIC_IP_DST_N_PORT,
990 (parser_func)parse_to, (shower_func)show_to_src_n_port);
991
992 keyword(MODULE_BASIC_ID, O_BASIC_PROTO, "proto", PROTO);
993 function(MODULE_BASIC_ID, O_BASIC_PROTO,
994 (parser_func)parse_proto, (shower_func)show_proto);
995
996 keyword(MODULE_BASIC_ID, O_BASIC_PROB, "prob", FILTER);
997 function(MODULE_BASIC_ID, O_BASIC_PROB,
998 (parser_func)parse_prob, (shower_func)show_prob);
999
1000 keyword(MODULE_BASIC_ID, O_BASIC_KEEP_STATE, "keep-state", FILTER);
1001 function(MODULE_BASIC_ID, O_BASIC_KEEP_STATE,
1002 (parser_func)parse_keep_state,
1003 (shower_func)show_keep_state);
1004
1005 keyword(MODULE_BASIC_ID, O_BASIC_CHECK_STATE, "check-state", BEFORE);
1006 function(MODULE_BASIC_ID, O_BASIC_CHECK_STATE,
1007 (parser_func)parse_check_state,
1008 (shower_func)show_check_state);
1009
1010 keyword(MODULE_BASIC_ID, O_BASIC_TAG, "tag", ACTION);
1011 function(MODULE_BASIC_ID, O_BASIC_TAG,
1012 (parser_func)parse_tag, (shower_func)show_tag);
1013
1014 keyword(MODULE_BASIC_ID, O_BASIC_UNTAG, "untag", ACTION);
1015 function(MODULE_BASIC_ID, O_BASIC_UNTAG,
1016 (parser_func)parse_untag, (shower_func)show_untag);
1017
1018 keyword(MODULE_BASIC_ID, O_BASIC_TAGGED, "tagged", FILTER);
1019 function(MODULE_BASIC_ID, O_BASIC_TAGGED,
1020 (parser_func)parse_tagged, (shower_func)show_tagged);
1021
1022 keyword(MODULE_BASIC_ID, O_BASIC_COMMENT, "//", AFTER);
1023 function(MODULE_BASIC_ID, O_BASIC_COMMENT,
1024 (parser_func)parse_comment, (shower_func)show_comment);
1025 }
1026