2 * Copyright (c) 2014 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Bill Yuan <bycn82@gmail.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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
51 #include <netinet/in.h>
53 #include <arpa/inet.h>
55 #include <net/route.h>
58 #include "../../../sys/net/ipfw3/ip_fw3.h"
59 #include "../../../sbin/ipfw3/ipfw.h"
60 #include "ipfw3_basic.h"
63 #define IP_MASK_ALL 0xffffffff
65 * we use IPPROTO_ETHERTYPE as a fake protocol id to call the print routines
66 * This is only used in this code.
68 #define IPPROTO_ETHERTYPE 0x1000
71 struct char_int_map limit_types
[] = {
79 static struct char_int_map ether_types
[] = {
88 { "pppoe_disc", 0x8863 },
89 { "pppoe_sess", 0x8864 },
90 { "ipx_8022", 0x00E0 },
91 { "ipx_8023", 0x0000 },
93 { "ipx_snap", 0x8137 },
100 * match_token takes a table and a string, returns the value associated
101 * with the string (0 meaning an error in most cases)
104 match_token(struct char_int_map
*table
, char *string
)
107 if (strcmp(table
->key
, string
) == 0)
116 match_token2(struct char_int_map
*table
, int val
)
119 if (table
->val
== val
)
128 fill_iface(ipfw_insn_if
*cmd
, char *arg
)
131 cmd
->o
.len
|= F_INSN_SIZE(ipfw_insn_if
);
133 /* Parse the interface or address */
134 if (!strcmp(arg
, "any")){
136 } else if (!isdigit(*arg
)) {
137 strlcpy(cmd
->name
, arg
, sizeof(cmd
->name
));
138 cmd
->p
.glob
= strpbrk(arg
, "*?[") != NULL
? 1 : 0;
139 } else if (!inet_aton(arg
, &cmd
->p
.ip
))
140 errx(EX_DATAERR
, "bad ip address ``%s''", arg
);
144 lookup_host (char *host
, struct in_addr
*ipaddr
)
148 if (!inet_aton(host
, ipaddr
)) {
149 if ((he
= gethostbyname(host
)) == NULL
)
151 *ipaddr
= *(struct in_addr
*)he
->h_addr_list
[0];
157 * Like strtol, but also translates service names into port numbers
158 * for some protocols.
160 * proto == -1 disables the protocol check;
161 * proto == IPPROTO_ETHERTYPE looks up an internal table
162 * proto == <some value in /etc/protocols> matches the values there.
163 * Returns *end == s in case the parameter is not found.
166 strtoport(char *s
, char **end
, int base
, int proto
)
172 *end
= s
; /* default - not found */
174 return 0; /* not found */
177 return strtol(s
, end
, base
);
180 * find separator. '\\' escapes the next char.
182 for (s1
= s
; *s1
&& (isalnum(*s1
) || *s1
== '\\') ; s1
++) {
183 if (*s1
== '\\' && s1
[1] != '\0')
187 buf
= malloc(s1
- s
+ 1);
192 * copy into a buffer skipping backslashes
194 for (p
= s
, i
= 0; p
!= s1
; p
++)
199 if (proto
== IPPROTO_ETHERTYPE
) {
200 i
= match_token(ether_types
, buf
);
202 if (i
!= -1) { /* found */
207 struct protoent
*pe
= NULL
;
211 pe
= getprotobynumber(proto
);
213 se
= getservbyname(buf
, pe
? pe
->p_name
: NULL
);
217 return ntohs(se
->s_port
);
220 return 0; /* not found */
224 contigmask(u_char
*p
, int len
)
227 for (i
=0; i
<len
; i
++) {
228 if ( (p
[i
/8] & (1 << (7 - (i
%8)))) == 0) /* first bit unset */
231 for (n
=i
+1; n
< len
; n
++) {
232 if ( (p
[n
/8] & (1 << (7 - (n
%8)))) != 0)
233 return -1; /* mask not contiguous */
238 static ipfw_insn
*add_proto(ipfw_insn
*cmd
, char *av
)
242 if (!strncmp(av
, "all", strlen(av
))) {
244 } else if ((proto
= atoi(av
)) > 0) {
246 } else if ((pe
= getprotobyname(av
)) != NULL
) {
249 errx(EX_USAGE
, "protocol `%s' not recognizable\n", av
);
251 if (proto
!= IPPROTO_IP
) {
252 cmd
->opcode
= O_BASIC_PROTO
;
253 cmd
->module
= MODULE_BASIC_ID
;
254 cmd
->len
= cmd
->len
|LEN_OF_IPFWINSN
;
261 parse_count(ipfw_insn
**cmd
, int *ac
, char **av
[])
263 (*cmd
)->opcode
= O_BASIC_COUNT
;
264 (*cmd
)->module
= MODULE_BASIC_ID
;
265 (*cmd
)->len
= LEN_OF_IPFWINSN
;
270 parse_skipto(ipfw_insn
**cmd
, int *ac
, char **av
[])
273 (*cmd
)->opcode
= O_BASIC_SKIPTO
;
274 (*cmd
)->module
= MODULE_BASIC_ID
;
275 (*cmd
)->len
= LEN_OF_IPFWINSN
;
276 (*cmd
)->arg1
= strtoul(**av
, NULL
, 10);
281 * cmd->arg3 is count of the destination
282 * cmd->arg1 is the type, random 0, round-robin 1, sticky 2
285 parse_forward(ipfw_insn
**cmd
, int *ac
, char **av
[])
287 ipfw_insn_sa
*p
= (ipfw_insn_sa
*)(*cmd
);
288 struct sockaddr_in
*sa
;
289 char *tok
, *end
= '\0';
293 (*cmd
)->opcode
= O_BASIC_FORWARD
;
296 * multiple forward destinations are seperated by colon
297 * ip address and port are seperated by comma
298 * e.g. 192.168.1.1:80,192.168.1.2:8080
299 * 192.168.1.1,192.168.1.2 or keep the port the same
301 tok
= strtok(**av
, ",");
304 while (tok
!= NULL
) {
305 sa
->sin_len
= sizeof(struct sockaddr_in
);
306 sa
->sin_family
= AF_INET
;
308 str
= strchr(tok
,':');
311 port
= strtoport(str
, &end
, 0, 0);
312 sa
->sin_port
= (u_short
)port
;
314 lookup_host(tok
, &(sa
->sin_addr
));
315 tok
= strtok (NULL
, ",");
319 (*cmd
)->arg3
= count
;
321 errx(EX_DATAERR
, "forward `%s' not recognizable", **av
);
325 if (strcmp(**av
, "round-robin") == 0) {
328 } else if (strcmp(**av
, "sticky") == 0) {
336 (*cmd
)->len
= LEN_OF_IPFWINSN
+ count
* sizeof(struct sockaddr_in
);
340 parse_in(ipfw_insn
**cmd
, int *ac
, char **av
[])
342 (*cmd
)->opcode
= O_BASIC_IN
;
343 (*cmd
)->module
= MODULE_BASIC_ID
;
344 (*cmd
)->len
= LEN_OF_IPFWINSN
;
350 parse_out(ipfw_insn
**cmd
, int *ac
, char **av
[])
352 (*cmd
)->opcode
= O_BASIC_OUT
;
353 (*cmd
)->module
= MODULE_BASIC_ID
;
354 (*cmd
)->len
= LEN_OF_IPFWINSN
;
361 parse_via(ipfw_insn
**cmd
, int *ac
, char **av
[])
363 (*cmd
)->module
= MODULE_BASIC_ID
;
364 (*cmd
)->len
= LEN_OF_IPFWINSN
;
365 if (strcmp(*av
[0], "via")==0) {
366 (*cmd
)->opcode
= O_BASIC_VIA
;
367 } else if (strcmp(*av
[0], "xmit")==0) {
368 (*cmd
)->opcode
= O_BASIC_XMIT
;
369 } else if (strcmp(*av
[0], "recv")==0) {
370 (*cmd
)->opcode
= O_BASIC_RECV
;
373 fill_iface((ipfw_insn_if
*)(*cmd
), *av
[0]);
378 * Below formats are supported:
379 * from table 1 O_BASIC_IP_SRC_LOOKUP
380 * from any return 0 len instruction
381 * from me O_BASIC_IP_SRC_ME
382 * from 1.2.3.4 O_BASIC_IP_SRC
383 * from 1.2.3.4/24 O_BASIC_IP_SRC_MASK
386 parse_from(ipfw_insn
**cmd
, int *ac
, char **av
[])
388 ipfw_insn_ip
*p
= (ipfw_insn_ip
*)(*cmd
);
391 (*cmd
)->module
= MODULE_BASIC_ID
;
393 if (strcmp(**av
, "table") == 0) {
395 NEED(*ac
, 1, "table id missing");
396 (*cmd
)->len
= F_INSN_SIZE(ipfw_insn
);
397 (*cmd
)->opcode
= O_BASIC_IP_SRC_LOOKUP
;
398 (*cmd
)->arg1
= strtoul(**av
, NULL
, 10);
399 } else if (strcmp(**av
, "any") == 0) {
400 (*cmd
)->len
&= ~F_LEN_MASK
;
401 } else if (strcmp(**av
, "me") == 0) {
402 (*cmd
)->len
|= F_INSN_SIZE(ipfw_insn
);
403 (*cmd
)->opcode
= O_BASIC_IP_SRC_ME
;
405 char *c
= NULL
, md
= 0;
406 c
= strchr(**av
, '/');
411 if (lookup_host(**av
, &p
->addr
) != 0)
412 errx(EX_NOHOST
, "hostname ``%s'' unknown", **av
);
417 p
->mask
.s_addr
= htonl(0);
419 errx(EX_DATAERR
, "bad width ``%s''", c
);
421 p
->mask
.s_addr
= htonl(~0 << (32 - i
));
424 p
->mask
.s_addr
= htonl(~0);
427 p
->addr
.s_addr
&= p
->mask
.s_addr
;
428 if (p
->mask
.s_addr
== 0) {
430 } else if (p
->mask
.s_addr
== IP_MASK_ALL
) {
431 (*cmd
)->len
|= F_INSN_SIZE(ipfw_insn_u32
);
432 (*cmd
)->opcode
= O_BASIC_IP_SRC
;
434 (*cmd
)->len
|= F_INSN_SIZE(ipfw_insn_ip
);
435 (*cmd
)->opcode
= O_BASIC_IP_SRC_MASK
;
442 parse_to(ipfw_insn
**cmd
, int *ac
, char **av
[])
444 ipfw_insn_ip
*p
= (ipfw_insn_ip
*)(*cmd
);
447 (*cmd
)->module
= MODULE_BASIC_ID
;
449 if (strcmp(**av
, "table") == 0) {
451 NEED(*ac
, 1, "table id missing");
452 (*cmd
)->len
= F_INSN_SIZE(ipfw_insn
);
453 (*cmd
)->opcode
= O_BASIC_IP_DST_LOOKUP
;
454 (*cmd
)->arg1
= strtoul(**av
, NULL
, 10);
455 }else if (strcmp(**av
, "any") == 0) {
456 (*cmd
)->len
&= ~F_LEN_MASK
;
457 } else if (strcmp(**av
, "me") == 0) {
458 (*cmd
)->len
|= F_INSN_SIZE(ipfw_insn
);
459 (*cmd
)->opcode
= O_BASIC_IP_DST_ME
;
461 char *c
= NULL
, md
= 0;
462 c
= strchr(**av
, '/');
467 if (lookup_host(**av
, &p
->addr
) != 0)
468 errx(EX_NOHOST
, "hostname ``%s'' unknown", **av
);
473 p
->mask
.s_addr
= htonl(0);
475 errx(EX_DATAERR
, "bad width ``%s''", c
);
477 p
->mask
.s_addr
= htonl(~0 << (32 - i
));
480 p
->mask
.s_addr
= htonl(~0);
483 p
->addr
.s_addr
&= p
->mask
.s_addr
;
484 if (p
->mask
.s_addr
== 0) {
486 } else if (p
->mask
.s_addr
== IP_MASK_ALL
) {
487 (*cmd
)->len
|= F_INSN_SIZE(ipfw_insn_u32
);
488 (*cmd
)->opcode
= O_BASIC_IP_DST
;
490 (*cmd
)->len
|= F_INSN_SIZE(ipfw_insn_ip
);
491 (*cmd
)->opcode
= O_BASIC_IP_DST_MASK
;
498 parse_proto(ipfw_insn
**cmd
, int *ac
, char **av
[])
500 add_proto(*cmd
, **av
);
505 parse_prob(ipfw_insn
**cmd
, int *ac
, char **av
[])
508 (*cmd
)->opcode
= O_BASIC_PROB
;
509 (*cmd
)->module
= MODULE_BASIC_ID
;
510 (*cmd
)->len
= LEN_OF_IPFWINSN
;
511 (*cmd
)->arg1
= strtoul(**av
, NULL
, 10);
516 parse_keep_state(ipfw_insn
**cmd
, int *ac
, char **av
[])
519 (*cmd
)->opcode
= O_BASIC_KEEP_STATE
;
520 (*cmd
)->module
= MODULE_BASIC_ID
;
521 (*cmd
)->len
= LEN_OF_IPFWINSN
;
522 if (strcmp(**av
, "limit") == 0) {
524 (*cmd
)->arg3
= match_token(limit_types
, **av
);
525 if ((*cmd
)->arg3
== 0)
526 errx(EX_DATAERR
, "limit `%s' not recognizable", **av
);
529 (*cmd
)->arg1
= strtoul(**av
, NULL
, 10);
530 if ((*cmd
)->arg1
== 0)
531 errx(EX_DATAERR
, "bad limit `%s'", **av
);
535 if (strcmp(**av
, "live") == 0) {
537 (*cmd
)->arg2
= strtoul(**av
, NULL
, 10);
543 parse_check_state(ipfw_insn
**cmd
, int *ac
, char **av
[])
546 (*cmd
)->opcode
= O_BASIC_CHECK_STATE
;
547 (*cmd
)->module
= MODULE_BASIC_ID
;
548 (*cmd
)->len
= LEN_OF_IPFWINSN
;
552 parse_tagged(ipfw_insn
**cmd
, int *ac
, char **av
[])
555 (*cmd
)->opcode
= O_BASIC_TAGGED
;
556 (*cmd
)->module
= MODULE_BASIC_ID
;
557 (*cmd
)->len
= LEN_OF_IPFWINSN
;
558 (*cmd
)->arg1
= strtoul(**av
, NULL
, 10);
563 parse_comment(ipfw_insn
**cmd
, int *ac
, char **av
[])
566 char *p
= (char *)((*cmd
) + 1);
569 (*cmd
)->opcode
= O_BASIC_COMMENT
;
570 (*cmd
)->module
= MODULE_BASIC_ID
;
573 l
+= strlen(**av
) + 1;
575 errx(EX_DATAERR
, "comment too long (max 80 chars)");
588 parse_tag(ipfw_insn
**cmd
, int *ac
, char **av
[])
591 (*cmd
)->opcode
= O_BASIC_TAG
;
592 (*cmd
)->module
= MODULE_BASIC_ID
;
593 (*cmd
)->len
= LEN_OF_IPFWINSN
;
594 (*cmd
)->arg1
= strtoul(**av
, NULL
, 10);
599 parse_untag(ipfw_insn
**cmd
, int *ac
, char **av
[])
602 (*cmd
)->opcode
= O_BASIC_UNTAG
;
603 (*cmd
)->module
= MODULE_BASIC_ID
;
604 (*cmd
)->len
= LEN_OF_IPFWINSN
;
605 (*cmd
)->arg1
= strtoul(**av
, NULL
, 10);
610 show_count(ipfw_insn
*cmd
, int show_or
)
616 show_skipto(ipfw_insn
*cmd
, int show_or
)
618 printf(" skipto %u", cmd
->arg1
);
622 show_forward(ipfw_insn
*cmd
, int show_or
)
624 struct sockaddr_in
*sa
;
627 ipfw_insn_sa
*s
= (ipfw_insn_sa
*)cmd
;
630 for (i
= 0; i
< cmd
->arg3
; i
++){
636 printf("%s", inet_ntoa(sa
->sin_addr
));
637 if (sa
->sin_port
!= 0)
638 printf(":%d", sa
->sin_port
);
643 printf(" round-robin");
644 else if (cmd
->arg1
== 2)
650 show_in(ipfw_insn
*cmd
, int show_or
)
656 show_out(ipfw_insn
*cmd
, int show_or
)
662 show_via(ipfw_insn
*cmd
, int show_or
)
665 ipfw_insn_if
*cmdif
= (ipfw_insn_if
*)cmd
;
667 if ((int)cmd
->opcode
== O_BASIC_XMIT
)
669 else if ((int)cmd
->opcode
== O_BASIC_RECV
)
671 else if ((int)cmd
->opcode
== O_BASIC_VIA
)
677 if (cmdif
->name
[0] == '\0')
678 printf(" %s %s", s
, inet_ntoa(cmdif
->p
.ip
));
680 printf(" %s %s", s
, cmdif
->name
);
684 show_from(ipfw_insn
*cmd
, int show_or
)
689 printf(" %s %s", word
, inet_ntoa(((ipfw_insn_ip
*)cmd
)->addr
));
693 show_from_lookup(ipfw_insn
*cmd
, int show_or
)
698 printf(" %s table %d", word
, cmd
->arg1
);
702 show_from_me(ipfw_insn
*cmd
, int show_or
)
707 printf(" %s me", word
);
711 show_from_mask(ipfw_insn
*cmd
, int show_or
)
717 ipfw_insn_ip
*p
= (ipfw_insn_ip
*)cmd
;
718 printf(" %s %s", word
, inet_ntoa(p
->addr
));
720 mask
= contigmask((u_char
*)&(p
->mask
.s_addr
), 32);
726 show_to(ipfw_insn
*cmd
, int show_or
)
731 printf(" %s %s", word
, inet_ntoa(((ipfw_insn_ip
*)cmd
)->addr
));
735 show_to_lookup(ipfw_insn
*cmd
, int show_or
)
740 printf(" %s table %d", word
, cmd
->arg1
);
744 show_to_me(ipfw_insn
*cmd
, int show_or
)
749 printf(" %s me", word
);
753 show_to_mask(ipfw_insn
*cmd
, int show_or
)
759 ipfw_insn_ip
*p
= (ipfw_insn_ip
*)cmd
;
760 printf(" %s %s", word
, inet_ntoa(p
->addr
));
762 mask
= contigmask((u_char
*)&(p
->mask
.s_addr
), 32);
768 show_proto(ipfw_insn
*cmd
, int show_or
)
773 pe
= getprotobynumber(cmd
->arg1
);
774 printf(" %s", pe
->p_name
);
778 show_prob(ipfw_insn
*cmd
, int show_or
)
780 printf(" prob %d%%", cmd
->arg1
);
784 show_keep_state(ipfw_insn
*cmd
, int show_or
)
786 printf(" keep-state");
787 if (cmd
->arg1
!= 0) {
788 char *type
=match_token2(limit_types
, cmd
->arg3
);
789 printf(" limit %s %d", type
, cmd
->arg1
);
791 if (cmd
->arg2
!= 0) {
792 printf(" live %d", cmd
->arg2
);
797 show_check_state(ipfw_insn
*cmd
, int show_or
)
799 printf(" check-state");
803 show_tagged(ipfw_insn
*cmd
, int show_or
)
805 printf(" tagged %d", cmd
->arg1
);
809 show_comment(ipfw_insn
*cmd
, int show_or
)
811 printf(" // %s", (char *)(cmd
+ 1));
815 show_tag(ipfw_insn
*cmd
, int show_or
)
817 printf(" tag %d", cmd
->arg1
);
821 show_untag(ipfw_insn
*cmd
, int show_or
)
823 printf(" untag %d", cmd
->arg1
);
827 load_module(register_func function
, register_keyword keyword
)
829 keyword(MODULE_BASIC_ID
, O_BASIC_COUNT
, "count", ACTION
);
830 function(MODULE_BASIC_ID
, O_BASIC_COUNT
,
831 (parser_func
)parse_count
, (shower_func
)show_count
);
833 keyword(MODULE_BASIC_ID
, O_BASIC_SKIPTO
, "skipto", ACTION
);
834 function(MODULE_BASIC_ID
, O_BASIC_SKIPTO
,
835 (parser_func
)parse_skipto
, (shower_func
)show_skipto
);
837 keyword(MODULE_BASIC_ID
, O_BASIC_FORWARD
, "forward", ACTION
);
838 function(MODULE_BASIC_ID
, O_BASIC_FORWARD
,
839 (parser_func
)parse_forward
, (shower_func
)show_forward
);
841 keyword(MODULE_BASIC_ID
, O_BASIC_IN
, "in", FILTER
);
842 function(MODULE_BASIC_ID
, O_BASIC_IN
,
843 (parser_func
)parse_in
, (shower_func
)show_in
);
845 keyword(MODULE_BASIC_ID
, O_BASIC_OUT
, "out", FILTER
);
846 function(MODULE_BASIC_ID
, O_BASIC_OUT
,
847 (parser_func
)parse_out
, (shower_func
)show_out
);
849 keyword(MODULE_BASIC_ID
, O_BASIC_VIA
, "via", FILTER
);
850 function(MODULE_BASIC_ID
, O_BASIC_VIA
,
851 (parser_func
)parse_via
, (shower_func
)show_via
);
853 keyword(MODULE_BASIC_ID
, O_BASIC_XMIT
, "xmit", FILTER
);
854 function(MODULE_BASIC_ID
, O_BASIC_XMIT
,
855 (parser_func
)parse_via
, (shower_func
)show_via
);
857 keyword(MODULE_BASIC_ID
, O_BASIC_RECV
, "recv", FILTER
);
858 function(MODULE_BASIC_ID
, O_BASIC_RECV
,
859 (parser_func
)parse_via
, (shower_func
)show_via
);
861 keyword(MODULE_BASIC_ID
, O_BASIC_IP_SRC
, "from", FROM
);
862 function(MODULE_BASIC_ID
, O_BASIC_IP_SRC
,
863 (parser_func
)parse_from
, (shower_func
)show_from
);
865 keyword(MODULE_BASIC_ID
, O_BASIC_IP_SRC_LOOKUP
, "[from table]", FROM
);
866 function(MODULE_BASIC_ID
, O_BASIC_IP_SRC_LOOKUP
,
867 (parser_func
)parse_from
, (shower_func
)show_from_lookup
);
869 keyword(MODULE_BASIC_ID
, O_BASIC_IP_SRC_ME
, "[from me]", FROM
);
870 function(MODULE_BASIC_ID
, O_BASIC_IP_SRC_ME
,
871 (parser_func
)parse_from
, (shower_func
)show_from_me
);
872 keyword(MODULE_BASIC_ID
, O_BASIC_IP_SRC_MASK
, "[from mask]", FROM
);
873 function(MODULE_BASIC_ID
, O_BASIC_IP_SRC_MASK
,
874 (parser_func
)parse_from
, (shower_func
)show_from_mask
);
875 keyword(MODULE_BASIC_ID
, O_BASIC_IP_DST
, "to", TO
);
876 function(MODULE_BASIC_ID
, O_BASIC_IP_DST
,
877 (parser_func
)parse_to
, (shower_func
)show_to
);
879 keyword(MODULE_BASIC_ID
, O_BASIC_IP_DST_LOOKUP
, "[to table]", TO
);
880 function(MODULE_BASIC_ID
, O_BASIC_IP_DST_LOOKUP
,
881 (parser_func
)parse_to
, (shower_func
)show_to_lookup
);
883 keyword(MODULE_BASIC_ID
, O_BASIC_IP_DST_ME
, "[to me]", TO
);
884 function(MODULE_BASIC_ID
, O_BASIC_IP_DST_ME
,
885 (parser_func
)parse_to
, (shower_func
)show_to_me
);
886 keyword(MODULE_BASIC_ID
, O_BASIC_IP_DST_MASK
, "[to mask]", TO
);
887 function(MODULE_BASIC_ID
, O_BASIC_IP_DST_MASK
,
888 (parser_func
)parse_to
, (shower_func
)show_to_mask
);
890 keyword(MODULE_BASIC_ID
, O_BASIC_PROTO
, "proto", PROTO
);
891 function(MODULE_BASIC_ID
, O_BASIC_PROTO
,
892 (parser_func
)parse_proto
, (shower_func
)show_proto
);
894 keyword(MODULE_BASIC_ID
, O_BASIC_PROB
, "prob", FILTER
);
895 function(MODULE_BASIC_ID
, O_BASIC_PROB
,
896 (parser_func
)parse_prob
, (shower_func
)show_prob
);
898 keyword(MODULE_BASIC_ID
, O_BASIC_KEEP_STATE
, "keep-state", FILTER
);
899 function(MODULE_BASIC_ID
, O_BASIC_KEEP_STATE
,
900 (parser_func
)parse_keep_state
,
901 (shower_func
)show_keep_state
);
903 keyword(MODULE_BASIC_ID
, O_BASIC_CHECK_STATE
, "check-state", ACTION
);
904 function(MODULE_BASIC_ID
, O_BASIC_CHECK_STATE
,
905 (parser_func
)parse_check_state
,
906 (shower_func
)show_check_state
);
908 keyword(MODULE_BASIC_ID
, O_BASIC_TAG
, "tag", ACTION
);
909 function(MODULE_BASIC_ID
, O_BASIC_TAG
,
910 (parser_func
)parse_tag
, (shower_func
)show_tag
);
912 keyword(MODULE_BASIC_ID
, O_BASIC_UNTAG
, "untag", ACTION
);
913 function(MODULE_BASIC_ID
, O_BASIC_UNTAG
,
914 (parser_func
)parse_untag
, (shower_func
)show_untag
);
916 keyword(MODULE_BASIC_ID
, O_BASIC_TAGGED
, "tagged", FILTER
);
917 function(MODULE_BASIC_ID
, O_BASIC_TAGGED
,
918 (parser_func
)parse_tagged
, (shower_func
)show_tagged
);
920 keyword(MODULE_BASIC_ID
, O_BASIC_COMMENT
, "//", AFTER
);
921 function(MODULE_BASIC_ID
, O_BASIC_COMMENT
,
922 (parser_func
)parse_comment
, (shower_func
)show_comment
);