2 * Copyright (c) 2004-2007 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 /* IPFW2 Backward Compatibility */
30 /* Convert to and from IPFW2 structures. */
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/errno.h>
35 #include <sys/socket.h>
36 #include <sys/socketvar.h>
38 #include <sys/types.h>
41 #include <netinet/in.h>
42 #include <netinet/in_systm.h>
43 #include <netinet/ip.h>
44 #include <netinet/ip_icmp.h>
45 #include <netinet/ip_fw.h>
46 #include <netinet/tcp.h>
48 #include "ip_fw2_compat.h"
50 #define FW2_DEBUG_VERBOSE 0
53 * _s_x is a structure that stores a string <-> token pairs, used in
54 * various places in the parser. Entries are stored in arrays,
55 * with an entry with s=NULL as terminator.
56 * The search routines are match_token() and match_value().
57 * Often, an element with x=0 contains an error string.
65 #define NO_VERSION_STR "IP_FW_VERSION_NONE"
66 #define VERSION_ZERO_STR "IP_FW_VERSION_0"
67 #define VERSION_ONE_STR "IP_FW_VERSION_1"
68 #define CURRENT_API_VERSION_STR "IP_FW_CURRENT_API_VERSION"
72 static struct _s_x f_tcpflags
[] = {
83 static struct _s_x f_tcpopts
[] = {
84 { "mss", IP_FW_TCPOPT_MSS
},
85 { "maxseg", IP_FW_TCPOPT_MSS
},
86 { "window", IP_FW_TCPOPT_WINDOW
},
87 { "sack", IP_FW_TCPOPT_SACK
},
88 { "ts", IP_FW_TCPOPT_TS
},
89 { "timestamp", IP_FW_TCPOPT_TS
},
90 { "cc", IP_FW_TCPOPT_CC
},
97 * IP options span the range 0 to 255 so we need to remap them
98 * (though in fact only the low 5 bits are significant).
100 static struct _s_x f_ipopts
[] = {
101 { "ssrr", IP_FW_IPOPT_SSRR
},
102 { "lsrr", IP_FW_IPOPT_LSRR
},
103 { "rr", IP_FW_IPOPT_RR
},
104 { "ts", IP_FW_IPOPT_TS
},
109 static struct _s_x f_iptos
[] = {
110 { "lowdelay", IPTOS_LOWDELAY
},
111 { "throughput", IPTOS_THROUGHPUT
},
112 { "reliability", IPTOS_RELIABILITY
},
113 { "mincost", IPTOS_MINCOST
},
114 { "congestion", IPTOS_CE
},
115 { "ecntransport", IPTOS_ECT
},
116 { "ip tos option", 0},
120 static struct _s_x limit_masks
[] = {
121 {"all", DYN_SRC_ADDR
|DYN_SRC_PORT
|DYN_DST_ADDR
|DYN_DST_PORT
},
122 {"src-addr", DYN_SRC_ADDR
},
123 {"src-port", DYN_SRC_PORT
},
124 {"dst-addr", DYN_DST_ADDR
},
125 {"dst-port", DYN_DST_PORT
},
129 #endif /* !FW2_DEBUG_VERBOSE */
131 #if 0 /* version #1 */
134 ipfw_print_fw_flags(u_int flags
)
137 switch (flags
& IP_FW_F_COMMAND_COMPAT
) {
138 case IP_FW_F_ACCEPT_COMPAT
:
139 printf("IP_FW_F_ACCEPT_COMPAT\n");
141 case IP_FW_F_COUNT_COMPAT
:
142 printf("IP_FW_F_COUNT_COMPAT\n");
144 case IP_FW_F_PIPE_COMPAT
:
145 printf("IP_FW_F_PIPE_COMPAT\n");
147 case IP_FW_F_QUEUE_COMPAT
:
148 printf("IP_FW_F_QUEUE_COMPAT\n");
150 case IP_FW_F_SKIPTO_COMPAT
:
151 printf("IP_FW_F_SKIPTO_COMPAT\n");
153 case IP_FW_F_DIVERT_COMPAT
:
154 printf("IP_FW_F_DIVERT_COMPAT\n");
156 case IP_FW_F_TEE_COMPAT
:
157 printf("IP_FW_F_TEE_COMPAT\n");
159 case IP_FW_F_FWD_COMPAT
:
160 printf("IP_FW_F_FWD_COMPAT\n");
162 case IP_FW_F_DENY_COMPAT
:
163 printf("IP_FW_F_DENY_COMPAT\n");
165 case IP_FW_F_REJECT_COMPAT
:
166 printf("IP_FW_F_REJECT_COMPAT\n");
168 case IP_FW_F_CHECK_S_COMPAT
:
169 printf("IP_FW_F_CHECK_S_COMPAT\n");
172 printf("No action given\n");
177 if (flags
& IP_FW_F_IN_COMPAT
) {
178 printf("IP_FW_F_IN_COMPAT\n");
180 if (flags
& IP_FW_F_OUT_COMPAT
) {
181 printf("IP_FW_F_OUT_COMPAT\n");
183 if (flags
& IP_FW_F_IIFACE_COMPAT
) {
184 printf("IP_FW_F_IIFACE_COMPAT\n");
186 if (flags
& IP_FW_F_OIFACE_COMPAT
) {
187 printf("IP_FW_F_OIFACE_COMPAT\n");
189 if (flags
& IP_FW_F_PRN_COMPAT
) {
190 printf("IP_FW_F_PRN_COMPAT\n");
192 if (flags
& IP_FW_F_SRNG_COMPAT
) {
193 printf("IP_FW_F_SRNG_COMPAT\n");
195 if (flags
& IP_FW_F_DRNG_COMPAT
) {
196 printf("IP_FW_F_DRNG_COMPAT\n");
198 if (flags
& IP_FW_F_FRAG_COMPAT
) {
199 printf("IP_FW_F_FRAG_COMPAT\n");
201 if (flags
& IP_FW_F_IIFNAME_COMPAT
) {
202 printf("IP_FW_F_IIFNAME_COMPAT\n");
204 if (flags
& IP_FW_F_OIFNAME_COMPAT
) {
205 printf("IP_FW_F_OIFNAME_COMPAT\n");
207 if (flags
& IP_FW_F_INVSRC_COMPAT
) {
208 printf("IP_FW_F_INVSRC_COMPAT\n");
210 if (flags
& IP_FW_F_INVDST_COMPAT
) {
211 printf("IP_FW_F_INVDST_COMPAT\n");
213 if (flags
& IP_FW_F_ICMPBIT_COMPAT
) {
214 printf("IP_FW_F_ICMPBIT_COMPAT\n");
216 if (flags
& IP_FW_F_UID_COMPAT
) {
217 printf("IP_FW_F_UID_COMPAT\n");
219 if (flags
& IP_FW_F_RND_MATCH_COMPAT
) {
220 printf("IP_FW_F_RND_MATCH_COMPAT\n");
222 if (flags
& IP_FW_F_SMSK_COMPAT
) {
223 printf("IP_FW_F_SMSK_COMPAT\n");
225 if (flags
& IP_FW_F_DMSK_COMPAT
) {
226 printf("IP_FW_F_DMSK_COMPAT\n");
228 if (flags
& IP_FW_BRIDGED_COMPAT
) {
229 printf("IP_FW_BRIDGED_COMPAT\n");
231 if (flags
& IP_FW_F_KEEP_S_COMPAT
) {
232 printf("IP_FW_F_KEEP_S_COMPAT\n");
234 if (flags
& IP_FW_F_CHECK_S_COMPAT
) {
235 printf("IP_FW_F_CHECK_S_COMPAT\n");
237 if (flags
& IP_FW_F_SME_COMPAT
) {
238 printf("IP_FW_F_SME_COMPAT\n");
240 if (flags
& IP_FW_F_DME_COMPAT
) {
241 printf("IP_FW_F_DME_COMPAT\n");
246 print_fw_version(u_int32_t api_version
)
248 switch (api_version
) {
249 case IP_FW_VERSION_0
:
250 printf("Version: %s\n", VERSION_ZERO_STR
);
252 case IP_FW_VERSION_1
:
253 printf("Version: %s\n", VERSION_ONE_STR
);
255 case IP_FW_CURRENT_API_VERSION
:
256 printf("Version: %s\n", CURRENT_API_VERSION_STR
);
258 case IP_FW_VERSION_NONE
:
259 printf("Version: %s\n", NO_VERSION_STR
);
262 printf("Unrecognized version\n");
268 print_icmptypes(ipfw_insn_u32
*cmd
)
273 printf(" icmptypes");
274 for (i
= 0; i
< 32; i
++) {
275 if ( (cmd
->d
[0] & (1 << (i
))) == 0)
277 printf("%c%d", sep
, i
);
283 * print flags set/clear in the two bitmasks passed as parameters.
284 * There is a specialized check for f_tcpflags.
287 print_flags(char const *name
, ipfw_insn
*cmd
, struct _s_x
*list
)
289 char const *comma
= "";
291 uint8_t set
= cmd
->arg1
& 0xff;
292 uint8_t clear
= (cmd
->arg1
>> 8) & 0xff;
294 if (list
== f_tcpflags
&& set
== TH_SYN
&& clear
== TH_ACK
) {
299 printf(" %s ", name
);
300 for (i
=0; list
[i
].x
!= 0; i
++) {
301 if (set
& list
[i
].x
) {
303 printf("%s%s", comma
, list
[i
].s
);
306 if (clear
& list
[i
].x
) {
308 printf("%s!%s", comma
, list
[i
].s
);
315 contigmask(uint8_t *p
, int len
)
319 for (i
=0; i
<len
; i
++)
320 if ( (p
[i
/8] & (1 << (7 - (i%8
)))) == 0) /* first bit unset */
322 for (n
=i
+1; n
< len
; n
++)
323 if ( (p
[n
/8] & (1 << (7 - (n%8
)))) != 0)
324 return -1; /* mask not contiguous */
329 * Print the ip address contained in a command.
332 print_ip(ipfw_insn_ip
*cmd
)
334 int len
= F_LEN((ipfw_insn
*)cmd
);
335 uint32_t *a
= ((ipfw_insn_u32
*)cmd
)->d
;
336 char ipv4str
[MAX_IPv4_STR_LEN
];
338 printf("%s ", cmd
->o
.len
& F_NOT
? " not": "");
340 if (cmd
->o
.opcode
== O_IP_SRC_ME
|| cmd
->o
.opcode
== O_IP_DST_ME
) {
346 * len == 2 indicates a single IP, whereas lists of 1 or more
347 * addr/mask pairs have len = (2n+1). We convert len to n so we
348 * use that to count the number of entries.
350 for (len
= len
/ 2; len
> 0; len
--, a
+= 2) {
351 int mb
= /* mask length */
352 (cmd
->o
.opcode
== O_IP_SRC
|| cmd
->o
.opcode
== O_IP_DST
) ?
353 32 : contigmask((uint8_t *)&(a
[1]), 32);
354 if (mb
== 0) { /* any */
356 } else { /* numeric IP followed by some kind of mask */
357 printf("%s", inet_ntop(AF_INET
, &a
[0], ipv4str
, sizeof(ipv4str
)));
359 printf(":%s", inet_ntop(AF_INET
, &a
[1], ipv4str
, sizeof(ipv4str
)));
369 * prints a MAC address/mask pair
372 print_mac(uint8_t *addr
, uint8_t *mask
)
374 int l
= contigmask(mask
, 48);
379 printf(" %02x:%02x:%02x:%02x:%02x:%02x",
380 addr
[0], addr
[1], addr
[2], addr
[3], addr
[4], addr
[5]);
382 printf("&%02x:%02x:%02x:%02x:%02x:%02x",
383 mask
[0], mask
[1], mask
[2],
384 mask
[3], mask
[4], mask
[5]);
390 #endif /* !version #1 */
392 #if FW2_DEBUG_VERBOSE
394 ipfw_print_vers2_struct(struct ip_fw
*vers2_rule
)
398 ipfw_insn_log
*logptr
= NULL
;
399 char ipv4str
[MAX_IPv4_STR_LEN
];
401 print_fw_version(vers2_rule
->version
);
403 printf("act_ofs: %d\n", vers2_rule
->act_ofs
);
404 printf("cmd_len: %d\n", vers2_rule
->cmd_len
);
405 printf("rulenum: %d\n", vers2_rule
->rulenum
);
406 printf("set: %d\n", vers2_rule
->set
);
407 printf("pcnt: %llu\n", vers2_rule
->pcnt
);
408 printf("bcnt: %llu\n", vers2_rule
->bcnt
);
409 printf("timestamp: %d\n", vers2_rule
->timestamp
);
412 * first print actions
414 for (l
= vers2_rule
->cmd_len
- vers2_rule
->act_ofs
, cmd
= ACTION_PTR(vers2_rule
);
415 l
> 0 ; l
-= F_LEN(cmd
), cmd
+= F_LEN(cmd
)) {
416 switch(cmd
->opcode
) {
418 printf("check-state");
434 if (cmd
->arg1
== ICMP_REJECT_RST
)
436 else if (cmd
->arg1
== ICMP_UNREACH_HOST
)
439 printf("unreach %u", cmd
->arg1
);
443 printf("skipto %u", cmd
->arg1
);
447 printf("pipe %u", cmd
->arg1
);
451 printf("queue %u", cmd
->arg1
);
455 printf("divert %u", cmd
->arg1
);
459 printf("tee %u", cmd
->arg1
);
464 ipfw_insn_sa
*s
= (ipfw_insn_sa
*)cmd
;
467 inet_ntop(AF_INET
, &s
->sa
.sin_addr
, ipv4str
,
470 printf(",%d", s
->sa
.sin_port
);
474 case O_LOG
: /* O_LOG is printed last */
475 logptr
= (ipfw_insn_log
*)cmd
;
479 printf("** unrecognized action %d len %d",
480 cmd
->opcode
, cmd
->len
);
484 if (logptr
->max_log
> 0)
485 printf(" log logamount %d", logptr
->max_log
);
491 * then print the body.
493 for (l
= vers2_rule
->act_ofs
, cmd
= vers2_rule
->cmd
;
494 l
> 0 ; l
-= F_LEN(cmd
) , cmd
+= F_LEN(cmd
)) {
496 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
;
498 switch(cmd
->opcode
) {
500 break; /* done already */
503 break; /* no need to print anything here */
507 ipfw_insn_mac
*m
= (ipfw_insn_mac
*)cmd
;
509 if (cmd
->len
& F_NOT
)
512 print_mac(m
->addr
, m
->mask
);
513 print_mac(m
->addr
+ 6, m
->mask
+ 6);
519 uint16_t *p
= ((ipfw_insn_u16
*)cmd
)->ports
;
522 for (i
= F_LEN((ipfw_insn
*)cmd
) - 1; i
> 0; i
--, p
+= 2) {
523 printf("0x%04x", p
[0]);
526 printf("0x%04x", p
[1]);
535 print_ip((ipfw_insn_ip
*)cmd
);
541 print_ip((ipfw_insn_ip
*)cmd
);
547 uint16_t *p
= ((ipfw_insn_u16
*)cmd
)->ports
;
550 for (i
= F_LEN((ipfw_insn
*)cmd
) - 1; i
> 0; i
--, p
+= 2) {
551 printf("0x%04x", p
[0]);
554 printf("0x%04x", p
[1]);
564 if (cmd
->len
& F_NOT
)
567 printf(" %u", cmd
->arg1
);
572 default: /*options ... */
574 if (cmd
->len
& F_NOT
&& cmd
->opcode
!= O_IN
)
576 switch(cmd
->opcode
) {
582 printf(cmd
->len
& F_NOT
? " out" : " O_IN");
593 ipfw_insn_if
*cmdif
= (ipfw_insn_if
*)cmd
;
595 if (cmd
->opcode
== O_XMIT
)
597 else if (cmd
->opcode
== O_RECV
)
599 else /* if (cmd->opcode == O_VIA) */
601 if (cmdif
->name
[0] == '\0') {
603 inet_ntop(AF_INET
, &cmdif
->p
.ip
, ipv4str
,
606 else if (cmdif
->p
.unit
== -1)
607 printf(" %s %s*", s
, cmdif
->name
);
609 printf(" %s %s%d", s
, cmdif
->name
,
616 printf(" ipid %u", cmd
->arg1
);
618 uint16_t *p
= ((ipfw_insn_u16
*)cmd
)->ports
;
621 for (i
= F_LEN((ipfw_insn
*)cmd
) - 1; i
> 0; i
--, p
+= 2) {
622 printf("0x%04x", p
[0]);
625 printf("0x%04x", p
[1]);
635 printf(" ipttl %u", cmd
->arg1
);
637 uint16_t *p
= ((ipfw_insn_u16
*)cmd
)->ports
;
640 for (i
= F_LEN((ipfw_insn
*)cmd
) - 1; i
> 0; i
--, p
+= 2) {
641 printf("0x%04x", p
[0]);
644 printf("0x%04x", p
[1]);
653 printf(" ipver %u", cmd
->arg1
);
657 printf(" ipprecedence %u", (cmd
->arg1
) >> 5 );
662 printf(" iplen %u", cmd
->arg1
);
664 uint16_t *p
= ((ipfw_insn_u16
*)cmd
)->ports
;
667 for (i
= F_LEN((ipfw_insn
*)cmd
) - 1; i
> 0; i
--, p
+= 2) {
668 printf("0x%04x", p
[0]);
671 printf("0x%04x", p
[1]);
680 print_flags("ipoptions", cmd
, f_ipopts
);
684 print_flags("iptos", cmd
, f_iptos
);
688 print_icmptypes((ipfw_insn_u32
*)cmd
);
692 printf(" established");
696 print_flags("tcpflags", cmd
, f_tcpflags
);
700 print_flags("tcpoptions", cmd
, f_tcpopts
);
704 printf(" tcpwin %d", ntohs(cmd
->arg1
));
708 printf(" tcpack %u", ntohl(cmd32
->d
[0]));
712 printf(" tcpseq %u", ntohl(cmd32
->d
[0]));
716 printf(" uid %u", cmd32
->d
[0]);
720 printf(" gid %u", cmd32
->d
[0]);
724 printf(" verrevpath");
735 printf(" keep-state");
740 struct _s_x
*p
= limit_masks
;
741 ipfw_insn_limit
*c
= (ipfw_insn_limit
*)cmd
;
742 uint8_t x
= c
->limit_mask
;
743 char const *comma
= " ";
746 for (; p
->x
!= 0 ; p
++)
747 if ((x
& p
->x
) == p
->x
) {
749 printf("%s%s", comma
, p
->s
);
752 printf(" %d", c
->conn_limit
);
758 printf(" [opcode %d len %d]",
759 cmd
->opcode
, cmd
->len
);
766 #endif /* !FW2_DEBUG_VERBOSE */
770 * helper function, updates the pointer to cmd with the length
771 * of the current command, and also cleans up the first word of
772 * the new command in case it has been clobbered before.
776 next_cmd(ipfw_insn
*cmd
)
779 bzero(cmd
, sizeof(*cmd
));
784 * A function to fill simple commands of size 1.
785 * Existing flags are preserved.
789 fill_cmd(ipfw_insn
*cmd
, enum ipfw_opcodes opcode
, uint16_t arg
)
791 cmd
->opcode
= opcode
;
792 cmd
->len
= ((cmd
->len
) & (F_NOT
| F_OR
)) | 1;
798 fill_compat_tcpflags(u_int32_t flags
) {
799 u_int32_t flags_compat
= 0;
802 flags_compat
|= IP_FW_TCPF_FIN_COMPAT
;
804 flags_compat
|= IP_FW_TCPF_SYN_COMPAT
;
806 flags_compat
|= IP_FW_TCPF_RST_COMPAT
;
808 flags_compat
|= IP_FW_TCPF_PSH_COMPAT
;
810 flags_compat
|= IP_FW_TCPF_ACK_COMPAT
;
812 flags_compat
|= IP_FW_TCPF_URG_COMPAT
;
818 /* ********************************************
819 * *********** Convert from Latest ************
820 * ********************************************/
823 * Things we're actively ignoring:
824 * sets, sets of addresses, blocks (NOT, OR)
827 ipfw_map_from_cmds_32(struct ip_fw_32
*curr_rule
, struct ip_fw_compat_32
*compat_rule
)
832 for (l
= curr_rule
->act_ofs
, cmd
= curr_rule
->cmd
;
834 l
-= F_LEN(cmd
) , cmd
+= F_LEN(cmd
)) {
836 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
;
838 switch (cmd
->opcode
) {
841 compat_rule
->fw_prot
= cmd
->arg1
;
845 compat_rule
->fw_flg
|= IP_FW_F_SME_COMPAT
;
846 if (cmd
->len
& F_NOT
) {
847 compat_rule
->fw_flg
|= IP_FW_F_INVSRC_COMPAT
;
854 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
856 compat_rule
->fw_src
= ip
->addr
;
857 compat_rule
->fw_smsk
= ip
->mask
;
858 if (cmd
->len
& F_NOT
) {
859 compat_rule
->fw_flg
|= IP_FW_F_INVSRC_COMPAT
;
867 * for now we only deal with one address
868 * per rule and ignore sets of addresses
870 compat_rule
->fw_src
.s_addr
= cmd32
->d
[0];
871 if (cmd
->len
& F_NOT
) {
872 compat_rule
->fw_flg
|= IP_FW_F_INVSRC_COMPAT
;
879 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
880 uint16_t *p
= ports
->ports
;
883 /* copy list of ports */
884 for (i
= F_LEN(cmd
) - 1, j
= 0; i
> 0; i
--, j
++, p
+= 2) {
886 /* this is a range */
887 compat_rule
->fw_flg
|= IP_FW_F_SRNG_COMPAT
;
888 compat_rule
->fw_uar_compat
.fw_pts
[j
++] = p
[0];
889 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[1];
891 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[0];
894 IP_FW_SETNSRCP_COMPAT(compat_rule
, j
);
901 compat_rule
->fw_flg
|= IP_FW_F_DME_COMPAT
;
902 if (cmd
->len
& F_NOT
) {
903 compat_rule
->fw_flg
|= IP_FW_F_INVDST_COMPAT
;
910 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
912 compat_rule
->fw_dst
= ip
->addr
;
913 compat_rule
->fw_dmsk
= ip
->mask
;
914 if (cmd
->len
& F_NOT
) {
915 compat_rule
->fw_flg
|= IP_FW_F_INVDST_COMPAT
;
922 * for now we only deal with one address
923 * per rule, and ignore sets of addresses
925 compat_rule
->fw_dst
.s_addr
= cmd32
->d
[0];
926 if (cmd
->len
& F_NOT
) {
927 compat_rule
->fw_flg
|= IP_FW_F_INVDST_COMPAT
;
934 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
935 uint16_t *p
= ports
->ports
;
937 j
= IP_FW_GETNSRCP_COMPAT(compat_rule
);
939 /* copy list of ports */
940 for (i
= F_LEN(cmd
) - 1; i
> 0; i
--, j
++, p
+= 2) {
942 /* this is a range */
943 compat_rule
->fw_flg
|= IP_FW_F_DRNG_COMPAT
;
944 compat_rule
->fw_uar_compat
.fw_pts
[j
++] = p
[0];
945 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[1];
947 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[0];
950 IP_FW_SETNDSTP_COMPAT(compat_rule
, (j
- IP_FW_GETNSRCP_COMPAT(compat_rule
)));
957 ipfw_insn_log
*c
= (ipfw_insn_log
*)cmd
;
959 compat_rule
->fw_flg
|= IP_FW_F_PRN_COMPAT
;
960 compat_rule
->fw_logamount
= c
->max_log
;
964 compat_rule
->fw_flg
|= IP_FW_F_UID_COMPAT
;
965 compat_rule
->fw_uid
= cmd32
->d
[0];
969 if (cmd
->len
& F_NOT
) {
970 compat_rule
->fw_flg
|= IP_FW_F_OUT_COMPAT
;
972 compat_rule
->fw_flg
|= IP_FW_F_IN_COMPAT
;
977 compat_rule
->fw_flg
|= IP_FW_F_KEEP_S_COMPAT
;
981 compat_rule
->fw_flg
|= IP_FW_BRIDGED_COMPAT
;
986 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
987 union ip_fw_if_compat ifu
;
989 if ((ifcmd
->o
.len
== 0) && (ifcmd
->name
[0] == '\0')) {
991 compat_rule
->fw_flg
|= IP_FW_F_OIFACE_COMPAT
;
992 ifu
.fu_via_ip
.s_addr
= 0;
994 else if (ifcmd
->p
.ip
.s_addr
!= 0) {
995 compat_rule
->fw_flg
|= IP_FW_F_OIFACE_COMPAT
;
996 ifu
.fu_via_ip
= ifcmd
->p
.ip
;
998 compat_rule
->fw_flg
|= IP_FW_F_OIFNAME_COMPAT
;
999 strncpy(ifu
.fu_via_if_compat
.name
, ifcmd
->name
, sizeof(ifu
.fu_via_if_compat
.name
));
1000 ifu
.fu_via_if_compat
.unit
= ifcmd
->p
.unit
;
1002 compat_rule
->fw_out_if
= ifu
;
1009 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1010 union ip_fw_if_compat ifu
;
1012 if ((ifcmd
->o
.len
== 0) && (ifcmd
->name
[0] == '\0')) {
1014 compat_rule
->fw_flg
|= IP_FW_F_IIFACE_COMPAT
;
1015 ifu
.fu_via_ip
.s_addr
= 0;
1017 else if (ifcmd
->p
.ip
.s_addr
!= 0) {
1018 compat_rule
->fw_flg
|= IP_FW_F_IIFACE_COMPAT
;
1019 ifu
.fu_via_ip
= ifcmd
->p
.ip
;
1021 compat_rule
->fw_flg
|= IP_FW_F_IIFNAME_COMPAT
;
1022 strncpy(ifu
.fu_via_if_compat
.name
, ifcmd
->name
, sizeof(ifu
.fu_via_if_compat
.name
));
1023 ifu
.fu_via_if_compat
.unit
= ifcmd
->p
.unit
;
1025 compat_rule
->fw_in_if
= ifu
;
1032 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1033 union ip_fw_if_compat ifu
;
1035 if ((ifcmd
->o
.len
== 0) && (ifcmd
->name
[0] == '\0')) {
1037 ifu
.fu_via_ip
.s_addr
= 0;
1039 else if (ifcmd
->name
[0] != '\0') {
1040 compat_rule
->fw_flg
|= IP_FW_F_IIFNAME_COMPAT
;
1041 strncpy(ifu
.fu_via_if_compat
.name
, ifcmd
->name
, sizeof(ifu
.fu_via_if_compat
.name
));
1042 ifu
.fu_via_if_compat
.unit
= ifcmd
->p
.unit
;
1044 ifu
.fu_via_ip
= ifcmd
->p
.ip
;
1046 compat_rule
->fw_flg
|= IF_FW_F_VIAHACK_COMPAT
;
1047 compat_rule
->fw_out_if
= compat_rule
->fw_in_if
= ifu
;
1053 compat_rule
->fw_flg
|= IP_FW_F_FRAG_COMPAT
;
1058 compat_rule
->fw_ipopt
= (cmd
->arg1
& 0xff);
1059 compat_rule
->fw_ipnopt
= ((cmd
->arg1
>> 8) & 0xff);
1063 /* check for "setup" */
1064 if ((cmd
->arg1
& 0xff) == TH_SYN
&&
1065 ((cmd
->arg1
>> 8) & 0xff) == TH_ACK
) {
1066 compat_rule
->fw_tcpf
= IP_FW_TCPF_SYN_COMPAT
;
1067 compat_rule
->fw_tcpnf
= IP_FW_TCPF_ACK_COMPAT
;
1070 compat_rule
->fw_tcpf
= fill_compat_tcpflags(cmd
->arg1
& 0xff);
1071 compat_rule
->fw_tcpnf
= fill_compat_tcpflags((cmd
->arg1
>> 8) & 0xff);
1077 compat_rule
->fw_tcpopt
= (cmd
->arg1
& 0xff);
1078 compat_rule
->fw_tcpnopt
= ((cmd
->arg1
>> 8) & 0xff);
1082 compat_rule
->fw_ipflg
|= IP_FW_IF_TCPEST_COMPAT
;
1088 /* XXX: check this */
1091 compat_rule
->fw_flg
|= IP_FW_F_ICMPBIT_COMPAT
;
1092 for (i
= 0; i
< sizeof(uint32_t) ; i
++) {
1093 type
= cmd32
->d
[0] & i
;
1095 compat_rule
->fw_uar_compat
.fw_icmptypes
[type
/ (sizeof(unsigned) * 8)] |=
1096 1 << (type
% (sizeof(unsigned) * 8));
1107 ipfw_map_from_cmds_64(struct ip_fw_64
*curr_rule
, struct ip_fw_compat_64
*compat_rule
)
1111 for (l
= curr_rule
->act_ofs
, cmd
= curr_rule
->cmd
;
1113 l
-= F_LEN(cmd
) , cmd
+= F_LEN(cmd
)) {
1115 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
;
1117 switch (cmd
->opcode
) {
1120 compat_rule
->fw_prot
= cmd
->arg1
;
1124 compat_rule
->fw_flg
|= IP_FW_F_SME_COMPAT
;
1125 if (cmd
->len
& F_NOT
) {
1126 compat_rule
->fw_flg
|= IP_FW_F_INVSRC_COMPAT
;
1133 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
1135 compat_rule
->fw_src
= ip
->addr
;
1136 compat_rule
->fw_smsk
= ip
->mask
;
1137 if (cmd
->len
& F_NOT
) {
1138 compat_rule
->fw_flg
|= IP_FW_F_INVSRC_COMPAT
;
1146 * for now we only deal with one address
1147 * per rule and ignore sets of addresses
1149 compat_rule
->fw_src
.s_addr
= cmd32
->d
[0];
1150 if (cmd
->len
& F_NOT
) {
1151 compat_rule
->fw_flg
|= IP_FW_F_INVSRC_COMPAT
;
1158 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
1159 uint16_t *p
= ports
->ports
;
1162 /* copy list of ports */
1163 for (i
= F_LEN(cmd
) - 1, j
= 0; i
> 0; i
--, j
++, p
+= 2) {
1165 /* this is a range */
1166 compat_rule
->fw_flg
|= IP_FW_F_SRNG_COMPAT
;
1167 compat_rule
->fw_uar_compat
.fw_pts
[j
++] = p
[0];
1168 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[1];
1170 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[0];
1173 IP_FW_SETNSRCP_COMPAT(compat_rule
, j
);
1180 compat_rule
->fw_flg
|= IP_FW_F_DME_COMPAT
;
1181 if (cmd
->len
& F_NOT
) {
1182 compat_rule
->fw_flg
|= IP_FW_F_INVDST_COMPAT
;
1189 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
1191 compat_rule
->fw_dst
= ip
->addr
;
1192 compat_rule
->fw_dmsk
= ip
->mask
;
1193 if (cmd
->len
& F_NOT
) {
1194 compat_rule
->fw_flg
|= IP_FW_F_INVDST_COMPAT
;
1201 * for now we only deal with one address
1202 * per rule, and ignore sets of addresses
1204 compat_rule
->fw_dst
.s_addr
= cmd32
->d
[0];
1205 if (cmd
->len
& F_NOT
) {
1206 compat_rule
->fw_flg
|= IP_FW_F_INVDST_COMPAT
;
1213 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
1214 uint16_t *p
= ports
->ports
;
1216 j
= IP_FW_GETNSRCP_COMPAT(compat_rule
);
1218 /* copy list of ports */
1219 for (i
= F_LEN(cmd
) - 1; i
> 0; i
--, j
++, p
+= 2) {
1221 /* this is a range */
1222 compat_rule
->fw_flg
|= IP_FW_F_DRNG_COMPAT
;
1223 compat_rule
->fw_uar_compat
.fw_pts
[j
++] = p
[0];
1224 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[1];
1226 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[0];
1229 IP_FW_SETNDSTP_COMPAT(compat_rule
, (j
- IP_FW_GETNSRCP_COMPAT(compat_rule
)));
1236 ipfw_insn_log
*c
= (ipfw_insn_log
*)cmd
;
1238 compat_rule
->fw_flg
|= IP_FW_F_PRN_COMPAT
;
1239 compat_rule
->fw_logamount
= c
->max_log
;
1243 compat_rule
->fw_flg
|= IP_FW_F_UID_COMPAT
;
1244 compat_rule
->fw_uid
= cmd32
->d
[0];
1248 if (cmd
->len
& F_NOT
) {
1249 compat_rule
->fw_flg
|= IP_FW_F_OUT_COMPAT
;
1251 compat_rule
->fw_flg
|= IP_FW_F_IN_COMPAT
;
1256 compat_rule
->fw_flg
|= IP_FW_F_KEEP_S_COMPAT
;
1260 compat_rule
->fw_flg
|= IP_FW_BRIDGED_COMPAT
;
1265 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1266 union ip_fw_if_compat ifu
;
1268 if ((ifcmd
->o
.len
== 0) && (ifcmd
->name
[0] == '\0')) {
1270 compat_rule
->fw_flg
|= IP_FW_F_OIFACE_COMPAT
;
1271 ifu
.fu_via_ip
.s_addr
= 0;
1273 else if (ifcmd
->p
.ip
.s_addr
!= 0) {
1274 compat_rule
->fw_flg
|= IP_FW_F_OIFACE_COMPAT
;
1275 ifu
.fu_via_ip
= ifcmd
->p
.ip
;
1277 compat_rule
->fw_flg
|= IP_FW_F_OIFNAME_COMPAT
;
1278 strncpy(ifu
.fu_via_if_compat
.name
, ifcmd
->name
, sizeof(ifu
.fu_via_if_compat
.name
));
1279 ifu
.fu_via_if_compat
.unit
= ifcmd
->p
.unit
;
1281 compat_rule
->fw_out_if
= ifu
;
1288 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1289 union ip_fw_if_compat ifu
;
1291 if ((ifcmd
->o
.len
== 0) && (ifcmd
->name
[0] == '\0')) {
1293 compat_rule
->fw_flg
|= IP_FW_F_IIFACE_COMPAT
;
1294 ifu
.fu_via_ip
.s_addr
= 0;
1296 else if (ifcmd
->p
.ip
.s_addr
!= 0) {
1297 compat_rule
->fw_flg
|= IP_FW_F_IIFACE_COMPAT
;
1298 ifu
.fu_via_ip
= ifcmd
->p
.ip
;
1300 compat_rule
->fw_flg
|= IP_FW_F_IIFNAME_COMPAT
;
1301 strncpy(ifu
.fu_via_if_compat
.name
, ifcmd
->name
, sizeof(ifu
.fu_via_if_compat
.name
));
1302 ifu
.fu_via_if_compat
.unit
= ifcmd
->p
.unit
;
1304 compat_rule
->fw_in_if
= ifu
;
1311 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1312 union ip_fw_if_compat ifu
;
1314 if ((ifcmd
->o
.len
== 0) && (ifcmd
->name
[0] == '\0')) {
1316 ifu
.fu_via_ip
.s_addr
= 0;
1318 else if (ifcmd
->name
[0] != '\0') {
1319 compat_rule
->fw_flg
|= IP_FW_F_IIFNAME_COMPAT
;
1320 strncpy(ifu
.fu_via_if_compat
.name
, ifcmd
->name
, sizeof(ifu
.fu_via_if_compat
.name
));
1321 ifu
.fu_via_if_compat
.unit
= ifcmd
->p
.unit
;
1323 ifu
.fu_via_ip
= ifcmd
->p
.ip
;
1325 compat_rule
->fw_flg
|= IF_FW_F_VIAHACK_COMPAT
;
1326 compat_rule
->fw_out_if
= compat_rule
->fw_in_if
= ifu
;
1332 compat_rule
->fw_flg
|= IP_FW_F_FRAG_COMPAT
;
1337 compat_rule
->fw_ipopt
= (cmd
->arg1
& 0xff);
1338 compat_rule
->fw_ipnopt
= ((cmd
->arg1
>> 8) & 0xff);
1342 /* check for "setup" */
1343 if ((cmd
->arg1
& 0xff) == TH_SYN
&&
1344 ((cmd
->arg1
>> 8) & 0xff) == TH_ACK
) {
1345 compat_rule
->fw_tcpf
= IP_FW_TCPF_SYN_COMPAT
;
1346 compat_rule
->fw_tcpnf
= IP_FW_TCPF_ACK_COMPAT
;
1349 compat_rule
->fw_tcpf
= fill_compat_tcpflags(cmd
->arg1
& 0xff);
1350 compat_rule
->fw_tcpnf
= fill_compat_tcpflags((cmd
->arg1
>> 8) & 0xff);
1356 compat_rule
->fw_tcpopt
= (cmd
->arg1
& 0xff);
1357 compat_rule
->fw_tcpnopt
= ((cmd
->arg1
>> 8) & 0xff);
1361 compat_rule
->fw_ipflg
|= IP_FW_IF_TCPEST_COMPAT
;
1367 /* XXX: check this */
1370 compat_rule
->fw_flg
|= IP_FW_F_ICMPBIT_COMPAT
;
1371 for (i
= 0; i
< sizeof(uint32_t) ; i
++) {
1372 type
= cmd32
->d
[0] & i
;
1374 compat_rule
->fw_uar_compat
.fw_icmptypes
[type
/ (sizeof(unsigned) * 8)] |=
1375 1 << (type
% (sizeof(unsigned) * 8));
1386 ipfw_map_from_actions_32(struct ip_fw_32
*curr_rule
, struct ip_fw_compat_32
*compat_rule
)
1391 for (l
= curr_rule
->cmd_len
- curr_rule
->act_ofs
, cmd
= ACTION_PTR(curr_rule
);
1393 l
-= F_LEN(cmd
), cmd
+= F_LEN(cmd
)) {
1394 switch (cmd
->opcode
) {
1396 compat_rule
->fw_flg
|= IP_FW_F_ACCEPT_COMPAT
;
1399 compat_rule
->fw_flg
|= IP_FW_F_COUNT_COMPAT
;
1402 compat_rule
->fw_flg
|= IP_FW_F_PIPE_COMPAT
;
1403 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1406 compat_rule
->fw_flg
|= IP_FW_F_QUEUE_COMPAT
;
1407 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1410 compat_rule
->fw_flg
|= IP_FW_F_SKIPTO_COMPAT
;
1411 compat_rule
->fw_skipto_rule_compat
= cmd
->arg1
;
1414 compat_rule
->fw_flg
|= IP_FW_F_DIVERT_COMPAT
;
1415 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1418 compat_rule
->fw_flg
|= IP_FW_F_TEE_COMPAT
;
1419 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1423 ipfw_insn_sa
*p
= (ipfw_insn_sa
*)cmd
;
1425 compat_rule
->fw_flg
|= IP_FW_F_FWD_COMPAT
;
1426 compat_rule
->fw_fwd_ip_compat
.sin_len
= p
->sa
.sin_len
;
1427 compat_rule
->fw_fwd_ip_compat
.sin_family
= p
->sa
.sin_family
;
1428 compat_rule
->fw_fwd_ip_compat
.sin_port
= p
->sa
.sin_port
;
1429 compat_rule
->fw_fwd_ip_compat
.sin_addr
= p
->sa
.sin_addr
;
1434 compat_rule
->fw_flg
|= IP_FW_F_DENY_COMPAT
;
1437 compat_rule
->fw_flg
|= IP_FW_F_REJECT_COMPAT
;
1438 compat_rule
->fw_reject_code_compat
= cmd
->arg1
;
1441 compat_rule
->fw_flg
|= IP_FW_F_CHECK_S_COMPAT
;
1450 ipfw_map_from_actions_64(struct ip_fw_64
*curr_rule
, struct ip_fw_compat_64
*compat_rule
)
1454 for (l
= curr_rule
->cmd_len
- curr_rule
->act_ofs
, cmd
= ACTION_PTR(curr_rule
);
1456 l
-= F_LEN(cmd
), cmd
+= F_LEN(cmd
)) {
1457 switch (cmd
->opcode
) {
1459 compat_rule
->fw_flg
|= IP_FW_F_ACCEPT_COMPAT
;
1462 compat_rule
->fw_flg
|= IP_FW_F_COUNT_COMPAT
;
1465 compat_rule
->fw_flg
|= IP_FW_F_PIPE_COMPAT
;
1466 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1469 compat_rule
->fw_flg
|= IP_FW_F_QUEUE_COMPAT
;
1470 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1473 compat_rule
->fw_flg
|= IP_FW_F_SKIPTO_COMPAT
;
1474 compat_rule
->fw_skipto_rule_compat
= cmd
->arg1
;
1477 compat_rule
->fw_flg
|= IP_FW_F_DIVERT_COMPAT
;
1478 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1481 compat_rule
->fw_flg
|= IP_FW_F_TEE_COMPAT
;
1482 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1486 ipfw_insn_sa
*p
= (ipfw_insn_sa
*)cmd
;
1488 compat_rule
->fw_flg
|= IP_FW_F_FWD_COMPAT
;
1489 compat_rule
->fw_fwd_ip_compat
.sin_len
= p
->sa
.sin_len
;
1490 compat_rule
->fw_fwd_ip_compat
.sin_family
= p
->sa
.sin_family
;
1491 compat_rule
->fw_fwd_ip_compat
.sin_port
= p
->sa
.sin_port
;
1492 compat_rule
->fw_fwd_ip_compat
.sin_addr
= p
->sa
.sin_addr
;
1497 compat_rule
->fw_flg
|= IP_FW_F_DENY_COMPAT
;
1500 compat_rule
->fw_flg
|= IP_FW_F_REJECT_COMPAT
;
1501 compat_rule
->fw_reject_code_compat
= cmd
->arg1
;
1504 compat_rule
->fw_flg
|= IP_FW_F_CHECK_S_COMPAT
;
1513 ipfw_version_latest_to_one_32(struct ip_fw_32
*curr_rule
, struct ip_fw_compat_32
*rule_vers1
)
1518 bzero(rule_vers1
, sizeof(struct ip_fw_compat
));
1520 rule_vers1
->version
= IP_FW_VERSION_1
;
1521 rule_vers1
->context
= CAST_DOWN_EXPLICIT(user32_addr_t
,curr_rule
->context
);
1522 rule_vers1
->fw_number
= curr_rule
->rulenum
;
1523 rule_vers1
->fw_pcnt
= curr_rule
->pcnt
;
1524 rule_vers1
->fw_bcnt
= curr_rule
->bcnt
;
1525 rule_vers1
->timestamp
= curr_rule
->timestamp
;
1527 /* convert actions */
1528 ipfw_map_from_actions_32(curr_rule
, rule_vers1
);
1530 /* convert commands */
1531 ipfw_map_from_cmds_32(curr_rule
, rule_vers1
);
1533 #if FW2_DEBUG_VERBOSE
1534 ipfw_print_vers1_struct_32(rule_vers1
);
1539 ipfw_version_latest_to_one_64(struct ip_fw_64
*curr_rule
, struct ip_fw_compat_64
*rule_vers1
)
1544 bzero(rule_vers1
, sizeof(struct ip_fw_compat
));
1546 rule_vers1
->version
= IP_FW_VERSION_1
;
1547 rule_vers1
->context
= CAST_DOWN_EXPLICIT(__uint64_t
, curr_rule
->context
);
1548 rule_vers1
->fw_number
= curr_rule
->rulenum
;
1549 rule_vers1
->fw_pcnt
= curr_rule
->pcnt
;
1550 rule_vers1
->fw_bcnt
= curr_rule
->bcnt
;
1551 rule_vers1
->timestamp
= curr_rule
->timestamp
;
1553 /* convert actions */
1554 ipfw_map_from_actions_64(curr_rule
, rule_vers1
);
1556 /* convert commands */
1557 ipfw_map_from_cmds_64(curr_rule
, rule_vers1
);
1559 #if FW2_DEBUG_VERBOSE
1560 ipfw_print_vers1_struct_64(rule_vers1
);
1564 /* first convert to version one then to version zero */
1566 ipfw_version_latest_to_zero(struct ip_fw
*curr_rule
, struct ip_old_fw
*rule_vers0
, int is64user
)
1570 struct ip_fw_compat_64 rule_vers1
;
1571 ipfw_version_latest_to_one_64((struct ip_fw_64
*)curr_rule
, &rule_vers1
);
1572 bzero(rule_vers0
, sizeof(struct ip_old_fw
));
1573 bcopy(&rule_vers1
.fw_uar_compat
, &rule_vers0
->fw_uar
, sizeof(rule_vers1
.fw_uar_compat
));
1574 bcopy(&rule_vers1
.fw_in_if
, &rule_vers0
->fw_in_if
, sizeof(rule_vers1
.fw_in_if
));
1575 bcopy(&rule_vers1
.fw_out_if
, &rule_vers0
->fw_out_if
, sizeof(rule_vers1
.fw_out_if
));
1576 bcopy(&rule_vers1
.fw_un_compat
, &rule_vers0
->fw_un
, sizeof(rule_vers1
.fw_un_compat
));
1577 rule_vers0
->fw_pcnt
= rule_vers1
.fw_pcnt
;
1578 rule_vers0
->fw_bcnt
= rule_vers1
.fw_bcnt
;
1579 rule_vers0
->fw_src
= rule_vers1
.fw_src
;
1580 rule_vers0
->fw_dst
= rule_vers1
.fw_dst
;
1581 rule_vers0
->fw_smsk
= rule_vers1
.fw_smsk
;
1582 rule_vers0
->fw_dmsk
= rule_vers1
.fw_dmsk
;
1583 rule_vers0
->fw_number
= rule_vers1
.fw_number
;
1584 rule_vers0
->fw_flg
= rule_vers1
.fw_flg
;
1585 rule_vers0
->fw_ipopt
= rule_vers1
.fw_ipopt
;
1586 rule_vers0
->fw_ipnopt
= rule_vers1
.fw_ipnopt
;
1587 rule_vers0
->fw_tcpf
= rule_vers1
.fw_tcpf
;
1588 rule_vers0
->fw_tcpnf
= rule_vers1
.fw_tcpnf
;
1589 rule_vers0
->timestamp
= rule_vers1
.timestamp
;
1590 rule_vers0
->fw_prot
= rule_vers1
.fw_prot
;
1591 rule_vers0
->fw_nports
= rule_vers1
.fw_nports
;
1592 rule_vers0
->pipe_ptr
= CAST_DOWN_EXPLICIT(void*, rule_vers1
.pipe_ptr
);
1593 rule_vers0
->next_rule_ptr
= CAST_DOWN_EXPLICIT(void*, rule_vers1
.next_rule_ptr
);
1595 if (rule_vers1
.fw_ipflg
&& IP_FW_IF_TCPEST_COMPAT
) rule_vers0
->fw_tcpf
|= IP_OLD_FW_TCPF_ESTAB
;
1598 struct ip_fw_compat_32 rule_vers1
;
1599 ipfw_version_latest_to_one_32( (struct ip_fw_32
*)curr_rule
, &rule_vers1
);
1600 bzero(rule_vers0
, sizeof(struct ip_old_fw
));
1601 bcopy(&rule_vers1
.fw_uar_compat
, &rule_vers0
->fw_uar
, sizeof(rule_vers1
.fw_uar_compat
));
1602 bcopy(&rule_vers1
.fw_in_if
, &rule_vers0
->fw_in_if
, sizeof(rule_vers1
.fw_in_if
));
1603 bcopy(&rule_vers1
.fw_out_if
, &rule_vers0
->fw_out_if
, sizeof(rule_vers1
.fw_out_if
));
1604 bcopy(&rule_vers1
.fw_un_compat
, &rule_vers0
->fw_un
, sizeof(rule_vers1
.fw_un_compat
));
1605 rule_vers0
->fw_pcnt
= rule_vers1
.fw_pcnt
;
1606 rule_vers0
->fw_bcnt
= rule_vers1
.fw_bcnt
;
1607 rule_vers0
->fw_src
= rule_vers1
.fw_src
;
1608 rule_vers0
->fw_dst
= rule_vers1
.fw_dst
;
1609 rule_vers0
->fw_smsk
= rule_vers1
.fw_smsk
;
1610 rule_vers0
->fw_dmsk
= rule_vers1
.fw_dmsk
;
1611 rule_vers0
->fw_number
= rule_vers1
.fw_number
;
1612 rule_vers0
->fw_flg
= rule_vers1
.fw_flg
;
1613 rule_vers0
->fw_ipopt
= rule_vers1
.fw_ipopt
;
1614 rule_vers0
->fw_ipnopt
= rule_vers1
.fw_ipnopt
;
1615 rule_vers0
->fw_tcpf
= rule_vers1
.fw_tcpf
;
1616 rule_vers0
->fw_tcpnf
= rule_vers1
.fw_tcpnf
;
1617 rule_vers0
->timestamp
= rule_vers1
.timestamp
;
1618 rule_vers0
->fw_prot
= rule_vers1
.fw_prot
;
1619 rule_vers0
->fw_nports
= rule_vers1
.fw_nports
;
1620 rule_vers0
->pipe_ptr
= CAST_DOWN_EXPLICIT(void*, rule_vers1
.pipe_ptr
);
1621 rule_vers0
->next_rule_ptr
= CAST_DOWN_EXPLICIT(void*, rule_vers1
.next_rule_ptr
);
1623 if (rule_vers1
.fw_ipflg
&& IP_FW_IF_TCPEST_COMPAT
) rule_vers0
->fw_tcpf
|= IP_OLD_FW_TCPF_ESTAB
;
1629 ipfw_convert_from_latest(struct ip_fw
*curr_rule
, void *old_rule
, u_int32_t api_version
, int is64user
)
1631 switch (api_version
) {
1632 case IP_FW_VERSION_0
:
1634 struct ip_old_fw
*rule_vers0
= old_rule
;
1636 ipfw_version_latest_to_zero(curr_rule
, rule_vers0
, is64user
);
1639 case IP_FW_VERSION_1
:
1642 ipfw_version_latest_to_one_64((struct ip_fw_64
*)curr_rule
, (struct ip_fw_compat_64
*)old_rule
);
1644 ipfw_version_latest_to_one_32((struct ip_fw_32
*)curr_rule
, (struct ip_fw_compat_32
*)old_rule
);
1648 case IP_FW_CURRENT_API_VERSION
:
1649 /* ipfw2 for now, don't need to do anything */
1653 /* unknown version */
1659 /* ********************************************
1660 * *********** Convert to Latest **************
1661 * ********************************************/
1665 ipfw_check_vers1_struct_32(struct ip_fw_compat_32
*frwl
)
1667 /* Check for invalid flag bits */
1668 if ((frwl
->fw_flg
& ~IP_FW_F_MASK_COMPAT
) != 0) {
1670 printf(("%s undefined flag bits set (flags=%x)\n",
1671 err_prefix, frwl->fw_flg));
1675 if (frwl
->fw_flg
== IP_FW_F_CHECK_S_COMPAT
) {
1679 /* Must apply to incoming or outgoing (or both) */
1680 if (!(frwl
->fw_flg
& (IP_FW_F_IN_COMPAT
| IP_FW_F_OUT_COMPAT
))) {
1682 printf(("%s neither in nor out\n", err_prefix));
1686 /* Empty interface name is no good */
1687 if (((frwl
->fw_flg
& IP_FW_F_IIFNAME_COMPAT
)
1688 && !*frwl
->fw_in_if
.fu_via_if_compat
.name
)
1689 || ((frwl
->fw_flg
& IP_FW_F_OIFNAME_COMPAT
)
1690 && !*frwl
->fw_out_if
.fu_via_if_compat
.name
)) {
1692 printf(("%s empty interface name\n", err_prefix));
1696 /* Sanity check interface matching */
1697 if ((frwl
->fw_flg
& IF_FW_F_VIAHACK_COMPAT
) == IF_FW_F_VIAHACK_COMPAT
) {
1698 ; /* allow "via" backwards compatibility */
1699 } else if ((frwl
->fw_flg
& IP_FW_F_IN_COMPAT
)
1700 && (frwl
->fw_flg
& IP_FW_F_OIFACE_COMPAT
)) {
1702 printf(("%s outgoing interface check on incoming\n",
1707 /* Sanity check port ranges */
1708 if ((frwl
->fw_flg
& IP_FW_F_SRNG_COMPAT
) && IP_FW_GETNSRCP_COMPAT(frwl
) < 2) {
1710 printf(("%s src range set but n_src_p=%d\n",
1711 err_prefix, IP_FW_GETNSRCP_COMPAT(frwl)));
1715 if ((frwl
->fw_flg
& IP_FW_F_DRNG_COMPAT
) && IP_FW_GETNDSTP_COMPAT(frwl
) < 2) {
1717 printf(("%s dst range set but n_dst_p=%d\n",
1718 err_prefix, IP_FW_GETNDSTP_COMPAT(frwl)));
1722 if (IP_FW_GETNSRCP_COMPAT(frwl
) + IP_FW_GETNDSTP_COMPAT(frwl
) > IP_FW_MAX_PORTS_COMPAT
) {
1724 printf(("%s too many ports (%d+%d)\n",
1725 err_prefix, IP_FW_GETNSRCP_COMPAT(frwl), IP_FW_GETNDSTP_COMPAT(frwl)));
1730 * Protocols other than TCP/UDP don't use port range
1732 if ((frwl
->fw_prot
!= IPPROTO_TCP
) &&
1733 (frwl
->fw_prot
!= IPPROTO_UDP
) &&
1734 (IP_FW_GETNSRCP_COMPAT(frwl
) || IP_FW_GETNDSTP_COMPAT(frwl
))) {
1736 printf(("%s port(s) specified for non TCP/UDP rule\n",
1743 * Rather than modify the entry to make such entries work,
1744 * we reject this rule and require user level utilities
1745 * to enforce whatever policy they deem appropriate.
1747 if ((frwl
->fw_src
.s_addr
& (~frwl
->fw_smsk
.s_addr
)) ||
1748 (frwl
->fw_dst
.s_addr
& (~frwl
->fw_dmsk
.s_addr
))) {
1750 printf(("%s rule never matches\n", err_prefix));
1755 if ((frwl
->fw_flg
& IP_FW_F_FRAG_COMPAT
) &&
1756 (frwl
->fw_prot
== IPPROTO_UDP
|| frwl
->fw_prot
== IPPROTO_TCP
)) {
1757 if (frwl
->fw_nports
) {
1759 printf(("%s cannot mix 'frag' and ports\n", err_prefix));
1763 if (frwl
->fw_prot
== IPPROTO_TCP
&&
1764 frwl
->fw_tcpf
!= frwl
->fw_tcpnf
) {
1766 printf(("%s cannot mix 'frag' and TCP flags\n", err_prefix));
1772 /* Check command specific stuff */
1773 switch (frwl
->fw_flg
& IP_FW_F_COMMAND_COMPAT
)
1775 case IP_FW_F_REJECT_COMPAT
:
1776 if (frwl
->fw_reject_code_compat
>= 0x100
1777 && !(frwl
->fw_prot
== IPPROTO_TCP
1778 && frwl
->fw_reject_code_compat
== IP_FW_REJECT_RST_COMPAT
)) {
1780 printf(("%s unknown reject code\n", err_prefix));
1785 case IP_FW_F_DIVERT_COMPAT
: /* Diverting to port zero is invalid */
1786 case IP_FW_F_TEE_COMPAT
:
1787 case IP_FW_F_PIPE_COMPAT
: /* piping through 0 is invalid */
1788 case IP_FW_F_QUEUE_COMPAT
: /* piping through 0 is invalid */
1789 if (frwl
->fw_divert_port_compat
== 0) {
1791 printf(("%s can't divert to port 0\n", err_prefix));
1796 case IP_FW_F_DENY_COMPAT
:
1797 case IP_FW_F_ACCEPT_COMPAT
:
1798 case IP_FW_F_COUNT_COMPAT
:
1799 case IP_FW_F_SKIPTO_COMPAT
:
1800 case IP_FW_F_FWD_COMPAT
:
1801 case IP_FW_F_UID_COMPAT
:
1805 printf(("%s invalid command\n", err_prefix));
1814 ipfw_check_vers1_struct_64(struct ip_fw_compat_64
*frwl
)
1816 /* Check for invalid flag bits */
1817 if ((frwl
->fw_flg
& ~IP_FW_F_MASK_COMPAT
) != 0) {
1819 printf(("%s undefined flag bits set (flags=%x)\n",
1820 err_prefix, frwl->fw_flg));
1825 if (frwl
->fw_flg
== IP_FW_F_CHECK_S_COMPAT
) {
1829 /* Must apply to incoming or outgoing (or both) */
1830 if (!(frwl
->fw_flg
& (IP_FW_F_IN_COMPAT
| IP_FW_F_OUT_COMPAT
))) {
1832 printf(("%s neither in nor out\n", err_prefix));
1837 /* Empty interface name is no good */
1838 if (((frwl
->fw_flg
& IP_FW_F_IIFNAME_COMPAT
)
1839 && !*frwl
->fw_in_if
.fu_via_if_compat
.name
)
1840 || ((frwl
->fw_flg
& IP_FW_F_OIFNAME_COMPAT
)
1841 && !*frwl
->fw_out_if
.fu_via_if_compat
.name
)) {
1843 printf(("%s empty interface name\n", err_prefix));
1848 /* Sanity check interface matching */
1849 if ((frwl
->fw_flg
& IF_FW_F_VIAHACK_COMPAT
) == IF_FW_F_VIAHACK_COMPAT
) {
1850 ; /* allow "via" backwards compatibility */
1851 } else if ((frwl
->fw_flg
& IP_FW_F_IN_COMPAT
)
1852 && (frwl
->fw_flg
& IP_FW_F_OIFACE_COMPAT
)) {
1854 printf(("%s outgoing interface check on incoming\n",
1860 /* Sanity check port ranges */
1861 if ((frwl
->fw_flg
& IP_FW_F_SRNG_COMPAT
) && IP_FW_GETNSRCP_COMPAT(frwl
) < 2) {
1863 printf(("%s src range set but n_src_p=%d\n",
1864 err_prefix, IP_FW_GETNSRCP_COMPAT(frwl)));
1869 if ((frwl
->fw_flg
& IP_FW_F_DRNG_COMPAT
) && IP_FW_GETNDSTP_COMPAT(frwl
) < 2) {
1871 printf(("%s dst range set but n_dst_p=%d\n",
1872 err_prefix, IP_FW_GETNDSTP_COMPAT(frwl)));
1877 if (IP_FW_GETNSRCP_COMPAT(frwl
) + IP_FW_GETNDSTP_COMPAT(frwl
) > IP_FW_MAX_PORTS_COMPAT
) {
1879 printf(("%s too many ports (%d+%d)\n",
1880 err_prefix, IP_FW_GETNSRCP_COMPAT(frwl), IP_FW_GETNDSTP_COMPAT(frwl)));
1886 * Protocols other than TCP/UDP don't use port range
1888 if ((frwl
->fw_prot
!= IPPROTO_TCP
) &&
1889 (frwl
->fw_prot
!= IPPROTO_UDP
) &&
1890 (IP_FW_GETNSRCP_COMPAT(frwl
) || IP_FW_GETNDSTP_COMPAT(frwl
))) {
1892 printf(("%s port(s) specified for non TCP/UDP rule\n",
1900 * Rather than modify the entry to make such entries work,
1901 * we reject this rule and require user level utilities
1902 * to enforce whatever policy they deem appropriate.
1904 if ((frwl
->fw_src
.s_addr
& (~frwl
->fw_smsk
.s_addr
)) ||
1905 (frwl
->fw_dst
.s_addr
& (~frwl
->fw_dmsk
.s_addr
))) {
1907 printf(("%s rule never matches\n", err_prefix));
1913 if ((frwl
->fw_flg
& IP_FW_F_FRAG_COMPAT
) &&
1914 (frwl
->fw_prot
== IPPROTO_UDP
|| frwl
->fw_prot
== IPPROTO_TCP
)) {
1915 if (frwl
->fw_nports
) {
1917 printf(("%s cannot mix 'frag' and ports\n", err_prefix));
1922 if (frwl
->fw_prot
== IPPROTO_TCP
&&
1923 frwl
->fw_tcpf
!= frwl
->fw_tcpnf
) {
1925 printf(("%s cannot mix 'frag' and TCP flags\n", err_prefix));
1932 /* Check command specific stuff */
1933 switch (frwl
->fw_flg
& IP_FW_F_COMMAND_COMPAT
)
1935 case IP_FW_F_REJECT_COMPAT
:
1936 if (frwl
->fw_reject_code_compat
>= 0x100
1937 && !(frwl
->fw_prot
== IPPROTO_TCP
1938 && frwl
->fw_reject_code_compat
== IP_FW_REJECT_RST_COMPAT
)) {
1940 printf(("%s unknown reject code\n", err_prefix));
1946 case IP_FW_F_DIVERT_COMPAT
: /* Diverting to port zero is invalid */
1947 case IP_FW_F_TEE_COMPAT
:
1948 case IP_FW_F_PIPE_COMPAT
: /* piping through 0 is invalid */
1949 case IP_FW_F_QUEUE_COMPAT
: /* piping through 0 is invalid */
1950 if (frwl
->fw_divert_port_compat
== 0) {
1952 printf(("%s can't divert to port 0\n", err_prefix));
1958 case IP_FW_F_DENY_COMPAT
:
1959 case IP_FW_F_ACCEPT_COMPAT
:
1960 case IP_FW_F_COUNT_COMPAT
:
1961 case IP_FW_F_SKIPTO_COMPAT
:
1962 case IP_FW_F_FWD_COMPAT
:
1963 case IP_FW_F_UID_COMPAT
:
1967 printf(("%s invalid command\n", err_prefix));
1977 ipfw_convert_to_cmds_32(struct ip_fw
*curr_rule
, struct ip_fw_compat_32
*compat_rule
)
1980 uint32_t actbuf
[255], cmdbuf
[255];
1981 ipfw_insn
*action
, *cmd
, *src
, *dst
;
1982 ipfw_insn
*have_state
= NULL
; /* track check-state or keep-state */
1984 if (!compat_rule
|| !curr_rule
|| !(curr_rule
->cmd
)) {
1988 /* preemptively check the old ip_fw rule to
1989 * make sure it's valid before starting to copy stuff
1991 if (ipfw_check_vers1_struct_32(compat_rule
)) {
1996 bzero(actbuf
, sizeof(actbuf
)); /* actions go here */
1997 bzero(cmdbuf
, sizeof(cmdbuf
));
1999 /* fill in action */
2000 action
= (ipfw_insn
*)actbuf
;
2002 u_int flag
= compat_rule
->fw_flg
;
2004 action
->len
= 1; /* default */
2006 if (flag
& IP_FW_F_CHECK_S_COMPAT
) {
2007 have_state
= action
;
2008 action
->opcode
= O_CHECK_STATE
;
2011 switch (flag
& IP_FW_F_COMMAND_COMPAT
) {
2012 case IP_FW_F_ACCEPT_COMPAT
:
2013 action
->opcode
= O_ACCEPT
;
2015 case IP_FW_F_COUNT_COMPAT
:
2016 action
->opcode
= O_COUNT
;
2018 case IP_FW_F_PIPE_COMPAT
:
2019 action
->opcode
= O_PIPE
;
2020 action
->len
= F_INSN_SIZE(ipfw_insn_pipe
);
2021 action
->arg1
= compat_rule
->fw_divert_port_compat
;
2023 case IP_FW_F_QUEUE_COMPAT
:
2024 action
->opcode
= O_QUEUE
;
2025 action
->len
= F_INSN_SIZE(ipfw_insn_pipe
);
2026 action
->arg1
= compat_rule
->fw_divert_port_compat
;
2028 case IP_FW_F_SKIPTO_COMPAT
:
2029 action
->opcode
= O_SKIPTO
;
2030 action
->arg1
= compat_rule
->fw_skipto_rule_compat
;
2032 case IP_FW_F_DIVERT_COMPAT
:
2033 action
->opcode
= O_DIVERT
;
2034 action
->arg1
= compat_rule
->fw_divert_port_compat
;
2036 case IP_FW_F_TEE_COMPAT
:
2037 action
->opcode
= O_TEE
;
2038 action
->arg1
= compat_rule
->fw_divert_port_compat
;
2040 case IP_FW_F_FWD_COMPAT
:
2042 ipfw_insn_sa
*p
= (ipfw_insn_sa
*)action
;
2044 action
->opcode
= O_FORWARD_IP
;
2045 action
->len
= F_INSN_SIZE(ipfw_insn_sa
);
2047 p
->sa
.sin_len
= compat_rule
->fw_fwd_ip_compat
.sin_len
;
2048 p
->sa
.sin_family
= compat_rule
->fw_fwd_ip_compat
.sin_family
;
2049 p
->sa
.sin_port
= compat_rule
->fw_fwd_ip_compat
.sin_port
;
2050 p
->sa
.sin_addr
= compat_rule
->fw_fwd_ip_compat
.sin_addr
;
2054 case IP_FW_F_DENY_COMPAT
:
2055 action
->opcode
= O_DENY
;
2058 case IP_FW_F_REJECT_COMPAT
:
2059 action
->opcode
= O_REJECT
;
2060 action
->arg1
= compat_rule
->fw_reject_code_compat
;
2063 action
->opcode
= O_NOP
;
2068 /* action is mandatory */
2069 if (action
->opcode
== O_NOP
) {
2073 action
= next_cmd(action
);
2076 cmd
= (ipfw_insn
*)cmdbuf
;
2078 /* this is O_CHECK_STATE, we're done */
2084 ipfw_insn
*prev
= NULL
;
2085 u_int flag
= compat_rule
->fw_flg
;
2088 if (flag
& IP_FW_F_PRN_COMPAT
) {
2089 ipfw_insn_log
*c
= (ipfw_insn_log
*)cmd
;
2091 cmd
->opcode
= O_LOG
;
2092 cmd
->len
|= F_INSN_SIZE(ipfw_insn_log
);
2093 c
->max_log
= compat_rule
->fw_logamount
;
2096 cmd
= next_cmd(cmd
);
2100 if (compat_rule
->fw_prot
!= 0) {
2101 fill_cmd(cmd
, O_PROTO
, compat_rule
->fw_prot
);
2103 cmd
= next_cmd(cmd
);
2107 if (flag
& IP_FW_F_SME_COMPAT
) {
2108 cmd
->opcode
= O_IP_SRC_ME
;
2109 cmd
->len
|= F_INSN_SIZE(ipfw_insn
);
2110 if (flag
& IP_FW_F_INVSRC_COMPAT
) {
2111 cmd
->len
^= F_NOT
; /* toggle F_NOT */
2115 cmd
= next_cmd(cmd
);
2117 if (compat_rule
->fw_smsk
.s_addr
!= 0) {
2119 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
2121 ip
->addr
= compat_rule
->fw_src
;
2122 ip
->mask
= compat_rule
->fw_smsk
;
2123 cmd
->opcode
= O_IP_SRC_MASK
;
2124 cmd
->len
|= F_INSN_SIZE(ipfw_insn_ip
); /* double check this */
2127 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
; /* alias for cmd */
2129 if (compat_rule
->fw_src
.s_addr
== 0) {
2131 cmd32
->o
.len
&= ~F_LEN_MASK
; /* zero len */
2133 cmd32
->d
[0] = compat_rule
->fw_src
.s_addr
;
2134 cmd32
->o
.opcode
= O_IP_SRC
;
2135 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
2139 if (flag
& IP_FW_F_INVSRC_COMPAT
) {
2140 cmd
->len
^= F_NOT
; /* toggle F_NOT */
2143 if (F_LEN(cmd
) != 0) { /* !any */
2145 cmd
= next_cmd(cmd
);
2151 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
2152 uint16_t *p
= ports
->ports
;
2154 nports
= IP_FW_GETNSRCP_COMPAT(compat_rule
),
2157 cmd
->opcode
= O_IP_SRCPORT
;
2158 for (i
= 0; i
< nports
; i
++) {
2159 if (((flag
& IP_FW_F_SRNG_COMPAT
) ||
2160 (flag
& IP_FW_F_SMSK_COMPAT
)) && !have_range
) {
2161 p
[0] = compat_rule
->fw_uar_compat
.fw_pts
[i
++];
2162 p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
2165 p
[0] = p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
2172 ports
->o
.len
|= j
+1; /* leave F_NOT and F_OR untouched */
2176 cmd
= next_cmd(cmd
);
2180 if (flag
& IP_FW_F_DME_COMPAT
) {
2181 cmd
->opcode
= O_IP_DST_ME
;
2182 cmd
->len
|= F_INSN_SIZE(ipfw_insn
);
2183 if (flag
& IP_FW_F_INVDST_COMPAT
) {
2184 cmd
->len
^= F_NOT
; /* toggle F_NOT */
2188 cmd
= next_cmd(cmd
);
2190 if (compat_rule
->fw_dmsk
.s_addr
!= 0) {
2192 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
2194 ip
->addr
= compat_rule
->fw_dst
;
2195 ip
->mask
= compat_rule
->fw_dmsk
;
2196 cmd
->opcode
= O_IP_DST_MASK
;
2197 cmd
->len
|= F_INSN_SIZE(ipfw_insn_ip
); /* double check this */
2200 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
; /* alias for cmd */
2202 if (compat_rule
->fw_dst
.s_addr
== 0) {
2204 cmd32
->o
.len
&= ~F_LEN_MASK
; /* zero len */
2206 cmd32
->d
[0] = compat_rule
->fw_dst
.s_addr
;
2207 cmd32
->o
.opcode
= O_IP_DST
;
2208 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
2212 if (flag
& IP_FW_F_INVDST_COMPAT
) {
2213 cmd
->len
^= F_NOT
; /* toggle F_NOT */
2216 if (F_LEN(cmd
) != 0) { /* !any */
2218 cmd
= next_cmd(cmd
);
2224 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
2225 uint16_t *p
= ports
->ports
;
2226 int i
= IP_FW_GETNSRCP_COMPAT(compat_rule
),
2228 nports
= (IP_FW_GETNDSTP_COMPAT(compat_rule
) + i
),
2231 cmd
->opcode
= O_IP_DSTPORT
;
2232 for (; i
< nports
; i
++, p
+= 2) {
2233 if (((flag
& IP_FW_F_DRNG_COMPAT
) ||
2234 (flag
& IP_FW_F_DMSK_COMPAT
)) && !have_range
) {
2236 p
[0] = compat_rule
->fw_uar_compat
.fw_pts
[i
++];
2237 p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
2240 p
[0] = p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
2246 ports
->o
.len
|= j
+1; /* leave F_NOT and F_OR untouched */
2250 cmd
= next_cmd(cmd
);
2253 if (flag
& IP_FW_F_UID_COMPAT
) {
2254 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
; /* alias for cmd */
2256 cmd32
->o
.opcode
= O_UID
;
2257 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
2258 cmd32
->d
[0] = compat_rule
->fw_uid
;
2261 cmd
= next_cmd(cmd
);
2264 if (flag
& IP_FW_F_KEEP_S_COMPAT
) {
2266 fill_cmd(cmd
, O_KEEP_STATE
, 0);
2269 cmd
= next_cmd(cmd
);
2271 if (flag
& IP_FW_BRIDGED_COMPAT
) {
2272 fill_cmd(cmd
, O_LAYER2
, 0);
2275 cmd
= next_cmd(cmd
);
2278 if ((flag
& IF_FW_F_VIAHACK_COMPAT
) == IF_FW_F_VIAHACK_COMPAT
) {
2280 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
2281 union ip_fw_if_compat ifu
= compat_rule
->fw_in_if
;
2283 cmd
->opcode
= O_VIA
;
2284 ifcmd
->o
.len
|= F_INSN_SIZE(ipfw_insn_if
);
2286 if (ifu
.fu_via_ip
.s_addr
== 0) {
2288 ifcmd
->name
[0] = '\0';
2291 else if (compat_rule
->fw_flg
& IP_FW_F_IIFNAME_COMPAT
) {
2293 strncpy(ifcmd
->name
, ifu
.fu_via_if_compat
.name
, sizeof(ifcmd
->name
));
2294 ifcmd
->p
.unit
= ifu
.fu_via_if_compat
.unit
;
2297 ifcmd
->p
.ip
= ifu
.fu_via_ip
;
2301 cmd
= next_cmd(cmd
);
2303 if (flag
& IP_FW_F_IN_COMPAT
) {
2304 fill_cmd(cmd
, O_IN
, 0);
2307 cmd
= next_cmd(cmd
);
2309 if (flag
& IP_FW_F_OUT_COMPAT
) {
2310 /* if the previous command was O_IN, and this
2311 * is being set as well, it's equivalent to not
2312 * having either command, so let's back up prev
2313 * to the cmd before it and move cmd to prev.
2315 if (prev
->opcode
== O_IN
) {
2317 bzero(cmd
, sizeof(*cmd
));
2319 cmd
->len
^= F_NOT
; /* toggle F_NOT */
2320 fill_cmd(cmd
, O_IN
, 0);
2323 cmd
= next_cmd(cmd
);
2326 if (flag
& IP_FW_F_OIFACE_COMPAT
) {
2328 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
2329 union ip_fw_if_compat ifu
= compat_rule
->fw_out_if
;
2331 cmd
->opcode
= O_XMIT
;
2332 ifcmd
->o
.len
|= F_INSN_SIZE(ipfw_insn_if
);
2334 if (ifu
.fu_via_ip
.s_addr
== 0) {
2336 ifcmd
->name
[0] = '\0';
2339 else if (flag
& IP_FW_F_OIFNAME_COMPAT
) {
2341 strncpy(ifcmd
->name
, ifu
.fu_via_if_compat
.name
, sizeof(ifcmd
->name
));
2342 ifcmd
->p
.unit
= ifu
.fu_via_if_compat
.unit
;
2345 ifcmd
->p
.ip
= ifu
.fu_via_ip
;
2349 cmd
= next_cmd(cmd
);
2351 else if (flag
& IP_FW_F_IIFACE_COMPAT
) {
2353 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
2354 union ip_fw_if_compat ifu
= compat_rule
->fw_in_if
;
2356 cmd
->opcode
= O_RECV
;
2357 ifcmd
->o
.len
|= F_INSN_SIZE(ipfw_insn_if
);
2359 if (ifu
.fu_via_ip
.s_addr
== 0) {
2361 ifcmd
->name
[0] = '\0';
2364 else if (flag
& IP_FW_F_IIFNAME_COMPAT
) {
2366 strncpy(ifcmd
->name
, ifu
.fu_via_if_compat
.name
, sizeof(ifcmd
->name
));
2367 ifcmd
->p
.unit
= ifu
.fu_via_if_compat
.unit
;
2370 ifcmd
->p
.ip
= ifu
.fu_via_ip
;
2374 cmd
= next_cmd(cmd
);
2378 if (flag
& IP_FW_F_FRAG_COMPAT
) {
2379 fill_cmd(cmd
, O_FRAG
, 0);
2382 cmd
= next_cmd(cmd
);
2386 if (compat_rule
->fw_ipopt
!= 0 || compat_rule
->fw_ipnopt
!= 0) {
2387 fill_cmd(cmd
, O_IPOPT
, (compat_rule
->fw_ipopt
& 0xff) |
2388 (compat_rule
->fw_ipnopt
& 0xff) << 8);
2391 cmd
= next_cmd(cmd
);
2394 if (compat_rule
->fw_prot
== IPPROTO_TCP
) {
2395 if (compat_rule
->fw_ipflg
& IP_FW_IF_TCPEST_COMPAT
) {
2396 fill_cmd(cmd
, O_ESTAB
, 0);
2399 cmd
= next_cmd(cmd
);
2402 /* TCP options and flags */
2403 if (compat_rule
->fw_tcpf
!= 0 || compat_rule
->fw_tcpnf
!= 0) {
2404 if ((compat_rule
->fw_tcpf
& IP_FW_TCPF_SYN_COMPAT
) &&
2405 compat_rule
->fw_tcpnf
& IP_FW_TCPF_ACK_COMPAT
) {
2406 fill_cmd(cmd
, O_TCPFLAGS
, (TH_SYN
) | ( (TH_ACK
) & 0xff) <<8);
2409 cmd
= next_cmd(cmd
);
2412 fill_cmd(cmd
, O_TCPFLAGS
, (compat_rule
->fw_tcpf
& 0xff) |
2413 (compat_rule
->fw_tcpnf
& 0xff) << 8);
2416 cmd
= next_cmd(cmd
);
2419 if (compat_rule
->fw_tcpopt
!= 0 || compat_rule
->fw_tcpnopt
!= 0) {
2420 fill_cmd(cmd
, O_TCPOPTS
, (compat_rule
->fw_tcpopt
& 0xff) |
2421 (compat_rule
->fw_tcpnopt
& 0xff) << 8);
2424 cmd
= next_cmd(cmd
);
2429 /* XXX: check this */
2430 if (flag
& IP_FW_F_ICMPBIT_COMPAT
) {
2432 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
; /* alias for cmd */
2434 cmd32
->o
.opcode
= O_ICMPTYPE
;
2435 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
2437 for (i
= 0; i
< IP_FW_ICMPTYPES_DIM_COMPAT
; i
++) {
2438 cmd32
->d
[0] |= compat_rule
->fw_uar_compat
.fw_icmptypes
[i
];
2442 cmd
= next_cmd(cmd
);
2444 } /* end commands */
2447 /* finally, copy everything into the current
2448 * rule buffer in the right order.
2450 dst
= curr_rule
->cmd
;
2452 /* first, do match probability */
2453 if (compat_rule
->fw_flg
& IP_FW_F_RND_MATCH_COMPAT
) {
2454 dst
->opcode
= O_PROB
;
2456 *((int32_t *)(dst
+1)) = compat_rule
->pipe_ptr
;
2460 /* generate O_PROBE_STATE if necessary */
2461 if (have_state
&& have_state
->opcode
!= O_CHECK_STATE
) {
2462 fill_cmd(dst
, O_PROBE_STATE
, 0);
2463 dst
= next_cmd(dst
);
2467 * copy all commands but O_LOG, O_KEEP_STATE
2469 for (src
= (ipfw_insn
*)cmdbuf
; src
!= cmd
; src
+= k
) {
2472 switch (src
->opcode
) {
2477 bcopy(src
, dst
, k
* sizeof(uint32_t));
2483 * put back the have_state command as last opcode
2485 if (have_state
&& have_state
->opcode
!= O_CHECK_STATE
) {
2486 k
= F_LEN(have_state
);
2487 bcopy(have_state
, dst
, k
* sizeof(uint32_t));
2492 * start action section
2494 curr_rule
->act_ofs
= dst
- curr_rule
->cmd
;
2497 * put back O_LOG if necessary
2499 src
= (ipfw_insn
*)cmdbuf
;
2500 if (src
->opcode
== O_LOG
) {
2502 bcopy(src
, dst
, k
* sizeof(uint32_t));
2507 * copy all other actions
2509 for (src
= (ipfw_insn
*)actbuf
; src
!= action
; src
+= k
) {
2511 bcopy(src
, dst
, k
* sizeof(uint32_t));
2515 curr_rule
->cmd_len
= (uint32_t *)dst
- (uint32_t *)(curr_rule
->cmd
);
2521 ipfw_convert_to_cmds_64(struct ip_fw
*curr_rule
, struct ip_fw_compat_64
*compat_rule
)
2524 uint32_t actbuf
[255], cmdbuf
[255];
2525 ipfw_insn
*action
, *cmd
, *src
, *dst
;
2526 ipfw_insn
*have_state
= NULL
; /* track check-state or keep-state */
2528 if (!compat_rule
|| !curr_rule
|| !(curr_rule
->cmd
)) {
2532 /* preemptively check the old ip_fw rule to
2533 * make sure it's valid before starting to copy stuff
2535 if (ipfw_check_vers1_struct_64(compat_rule
)) {
2540 bzero(actbuf
, sizeof(actbuf
)); /* actions go here */
2541 bzero(cmdbuf
, sizeof(cmdbuf
));
2542 /* fill in action */
2543 action
= (ipfw_insn
*)actbuf
;
2545 u_int flag
= compat_rule
->fw_flg
;
2547 action
->len
= 1; /* default */
2549 if (flag
& IP_FW_F_CHECK_S_COMPAT
) {
2550 have_state
= action
;
2551 action
->opcode
= O_CHECK_STATE
;
2554 switch (flag
& IP_FW_F_COMMAND_COMPAT
) {
2555 case IP_FW_F_ACCEPT_COMPAT
:
2556 action
->opcode
= O_ACCEPT
;
2558 case IP_FW_F_COUNT_COMPAT
:
2559 action
->opcode
= O_COUNT
;
2561 case IP_FW_F_PIPE_COMPAT
:
2562 action
->opcode
= O_PIPE
;
2563 action
->len
= F_INSN_SIZE(ipfw_insn_pipe
);
2564 action
->arg1
= compat_rule
->fw_divert_port_compat
;
2566 case IP_FW_F_QUEUE_COMPAT
:
2567 action
->opcode
= O_QUEUE
;
2568 action
->len
= F_INSN_SIZE(ipfw_insn_pipe
);
2569 action
->arg1
= compat_rule
->fw_divert_port_compat
;
2571 case IP_FW_F_SKIPTO_COMPAT
:
2572 action
->opcode
= O_SKIPTO
;
2573 action
->arg1
= compat_rule
->fw_skipto_rule_compat
;
2575 case IP_FW_F_DIVERT_COMPAT
:
2576 action
->opcode
= O_DIVERT
;
2577 action
->arg1
= compat_rule
->fw_divert_port_compat
;
2579 case IP_FW_F_TEE_COMPAT
:
2580 action
->opcode
= O_TEE
;
2581 action
->arg1
= compat_rule
->fw_divert_port_compat
;
2583 case IP_FW_F_FWD_COMPAT
:
2585 ipfw_insn_sa
*p
= (ipfw_insn_sa
*)action
;
2587 action
->opcode
= O_FORWARD_IP
;
2588 action
->len
= F_INSN_SIZE(ipfw_insn_sa
);
2590 p
->sa
.sin_len
= compat_rule
->fw_fwd_ip_compat
.sin_len
;
2591 p
->sa
.sin_family
= compat_rule
->fw_fwd_ip_compat
.sin_family
;
2592 p
->sa
.sin_port
= compat_rule
->fw_fwd_ip_compat
.sin_port
;
2593 p
->sa
.sin_addr
= compat_rule
->fw_fwd_ip_compat
.sin_addr
;
2597 case IP_FW_F_DENY_COMPAT
:
2598 action
->opcode
= O_DENY
;
2601 case IP_FW_F_REJECT_COMPAT
:
2602 action
->opcode
= O_REJECT
;
2603 action
->arg1
= compat_rule
->fw_reject_code_compat
;
2606 action
->opcode
= O_NOP
;
2611 /* action is mandatory */
2612 if (action
->opcode
== O_NOP
) {
2616 action
= next_cmd(action
);
2619 cmd
= (ipfw_insn
*)cmdbuf
;
2621 /* this is O_CHECK_STATE, we're done */
2627 ipfw_insn
*prev
= NULL
;
2628 u_int flag
= compat_rule
->fw_flg
;
2631 if (flag
& IP_FW_F_PRN_COMPAT
) {
2632 ipfw_insn_log
*c
= (ipfw_insn_log
*)cmd
;
2634 cmd
->opcode
= O_LOG
;
2635 cmd
->len
|= F_INSN_SIZE(ipfw_insn_log
);
2636 c
->max_log
= compat_rule
->fw_logamount
;
2639 cmd
= next_cmd(cmd
);
2643 if (compat_rule
->fw_prot
!= 0) {
2644 fill_cmd(cmd
, O_PROTO
, compat_rule
->fw_prot
);
2646 cmd
= next_cmd(cmd
);
2650 if (flag
& IP_FW_F_SME_COMPAT
) {
2651 cmd
->opcode
= O_IP_SRC_ME
;
2652 cmd
->len
|= F_INSN_SIZE(ipfw_insn
);
2653 if (flag
& IP_FW_F_INVSRC_COMPAT
) {
2654 cmd
->len
^= F_NOT
; /* toggle F_NOT */
2658 cmd
= next_cmd(cmd
);
2660 if (compat_rule
->fw_smsk
.s_addr
!= 0) {
2662 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
2664 ip
->addr
= compat_rule
->fw_src
;
2665 ip
->mask
= compat_rule
->fw_smsk
;
2666 cmd
->opcode
= O_IP_SRC_MASK
;
2667 cmd
->len
|= F_INSN_SIZE(ipfw_insn_ip
); /* double check this */
2670 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
; /* alias for cmd */
2672 if (compat_rule
->fw_src
.s_addr
== 0) {
2674 cmd32
->o
.len
&= ~F_LEN_MASK
; /* zero len */
2676 cmd32
->d
[0] = compat_rule
->fw_src
.s_addr
;
2677 cmd32
->o
.opcode
= O_IP_SRC
;
2678 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
2682 if (flag
& IP_FW_F_INVSRC_COMPAT
) {
2683 cmd
->len
^= F_NOT
; /* toggle F_NOT */
2686 if (F_LEN(cmd
) != 0) { /* !any */
2688 cmd
= next_cmd(cmd
);
2694 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
2695 uint16_t *p
= ports
->ports
;
2697 nports
= IP_FW_GETNSRCP_COMPAT(compat_rule
),
2700 cmd
->opcode
= O_IP_SRCPORT
;
2701 for (i
= 0; i
< nports
; i
++) {
2702 if (((flag
& IP_FW_F_SRNG_COMPAT
) ||
2703 (flag
& IP_FW_F_SMSK_COMPAT
)) && !have_range
) {
2704 p
[0] = compat_rule
->fw_uar_compat
.fw_pts
[i
++];
2705 p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
2708 p
[0] = p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
2715 ports
->o
.len
|= j
+1; /* leave F_NOT and F_OR untouched */
2719 cmd
= next_cmd(cmd
);
2723 if (flag
& IP_FW_F_DME_COMPAT
) {
2724 cmd
->opcode
= O_IP_DST_ME
;
2725 cmd
->len
|= F_INSN_SIZE(ipfw_insn
);
2726 if (flag
& IP_FW_F_INVDST_COMPAT
) {
2727 cmd
->len
^= F_NOT
; /* toggle F_NOT */
2731 cmd
= next_cmd(cmd
);
2733 if (compat_rule
->fw_dmsk
.s_addr
!= 0) {
2735 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
2737 ip
->addr
= compat_rule
->fw_dst
;
2738 ip
->mask
= compat_rule
->fw_dmsk
;
2739 cmd
->opcode
= O_IP_DST_MASK
;
2740 cmd
->len
|= F_INSN_SIZE(ipfw_insn_ip
); /* double check this */
2743 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
; /* alias for cmd */
2745 if (compat_rule
->fw_dst
.s_addr
== 0) {
2747 cmd32
->o
.len
&= ~F_LEN_MASK
; /* zero len */
2749 cmd32
->d
[0] = compat_rule
->fw_dst
.s_addr
;
2750 cmd32
->o
.opcode
= O_IP_DST
;
2751 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
2755 if (flag
& IP_FW_F_INVDST_COMPAT
) {
2756 cmd
->len
^= F_NOT
; /* toggle F_NOT */
2759 if (F_LEN(cmd
) != 0) { /* !any */
2761 cmd
= next_cmd(cmd
);
2767 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
2768 uint16_t *p
= ports
->ports
;
2769 int i
= IP_FW_GETNSRCP_COMPAT(compat_rule
),
2771 nports
= (IP_FW_GETNDSTP_COMPAT(compat_rule
) + i
),
2774 cmd
->opcode
= O_IP_DSTPORT
;
2775 for (; i
< nports
; i
++, p
+= 2) {
2776 if (((flag
& IP_FW_F_DRNG_COMPAT
) ||
2777 (flag
& IP_FW_F_DMSK_COMPAT
)) && !have_range
) {
2779 p
[0] = compat_rule
->fw_uar_compat
.fw_pts
[i
++];
2780 p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
2783 p
[0] = p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
2789 ports
->o
.len
|= j
+1; /* leave F_NOT and F_OR untouched */
2793 cmd
= next_cmd(cmd
);
2796 if (flag
& IP_FW_F_UID_COMPAT
) {
2797 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
; /* alias for cmd */
2799 cmd32
->o
.opcode
= O_UID
;
2800 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
2801 cmd32
->d
[0] = compat_rule
->fw_uid
;
2804 cmd
= next_cmd(cmd
);
2807 if (flag
& IP_FW_F_KEEP_S_COMPAT
) {
2809 fill_cmd(cmd
, O_KEEP_STATE
, 0);
2812 cmd
= next_cmd(cmd
);
2814 if (flag
& IP_FW_BRIDGED_COMPAT
) {
2815 fill_cmd(cmd
, O_LAYER2
, 0);
2818 cmd
= next_cmd(cmd
);
2821 if ((flag
& IF_FW_F_VIAHACK_COMPAT
) == IF_FW_F_VIAHACK_COMPAT
) {
2823 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
2824 union ip_fw_if_compat ifu
= compat_rule
->fw_in_if
;
2826 cmd
->opcode
= O_VIA
;
2827 ifcmd
->o
.len
|= F_INSN_SIZE(ipfw_insn_if
);
2829 if (ifu
.fu_via_ip
.s_addr
== 0) {
2831 ifcmd
->name
[0] = '\0';
2834 else if (compat_rule
->fw_flg
& IP_FW_F_IIFNAME_COMPAT
) {
2836 strncpy(ifcmd
->name
, ifu
.fu_via_if_compat
.name
, sizeof(ifcmd
->name
));
2837 ifcmd
->p
.unit
= ifu
.fu_via_if_compat
.unit
;
2840 ifcmd
->p
.ip
= ifu
.fu_via_ip
;
2844 cmd
= next_cmd(cmd
);
2846 if (flag
& IP_FW_F_IN_COMPAT
) {
2847 fill_cmd(cmd
, O_IN
, 0);
2850 cmd
= next_cmd(cmd
);
2852 if (flag
& IP_FW_F_OUT_COMPAT
) {
2853 /* if the previous command was O_IN, and this
2854 * is being set as well, it's equivalent to not
2855 * having either command, so let's back up prev
2856 * to the cmd before it and move cmd to prev.
2858 if (prev
->opcode
== O_IN
) {
2860 bzero(cmd
, sizeof(*cmd
));
2862 cmd
->len
^= F_NOT
; /* toggle F_NOT */
2863 fill_cmd(cmd
, O_IN
, 0);
2866 cmd
= next_cmd(cmd
);
2869 if (flag
& IP_FW_F_OIFACE_COMPAT
) {
2871 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
2872 union ip_fw_if_compat ifu
= compat_rule
->fw_out_if
;
2874 cmd
->opcode
= O_XMIT
;
2875 ifcmd
->o
.len
|= F_INSN_SIZE(ipfw_insn_if
);
2877 if (ifu
.fu_via_ip
.s_addr
== 0) {
2879 ifcmd
->name
[0] = '\0';
2882 else if (flag
& IP_FW_F_OIFNAME_COMPAT
) {
2884 strncpy(ifcmd
->name
, ifu
.fu_via_if_compat
.name
, sizeof(ifcmd
->name
));
2885 ifcmd
->p
.unit
= ifu
.fu_via_if_compat
.unit
;
2888 ifcmd
->p
.ip
= ifu
.fu_via_ip
;
2892 cmd
= next_cmd(cmd
);
2894 else if (flag
& IP_FW_F_IIFACE_COMPAT
) {
2896 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
2897 union ip_fw_if_compat ifu
= compat_rule
->fw_in_if
;
2899 cmd
->opcode
= O_RECV
;
2900 ifcmd
->o
.len
|= F_INSN_SIZE(ipfw_insn_if
);
2902 if (ifu
.fu_via_ip
.s_addr
== 0) {
2904 ifcmd
->name
[0] = '\0';
2907 else if (flag
& IP_FW_F_IIFNAME_COMPAT
) {
2909 strncpy(ifcmd
->name
, ifu
.fu_via_if_compat
.name
, sizeof(ifcmd
->name
));
2910 ifcmd
->p
.unit
= ifu
.fu_via_if_compat
.unit
;
2913 ifcmd
->p
.ip
= ifu
.fu_via_ip
;
2917 cmd
= next_cmd(cmd
);
2921 if (flag
& IP_FW_F_FRAG_COMPAT
) {
2922 fill_cmd(cmd
, O_FRAG
, 0);
2925 cmd
= next_cmd(cmd
);
2929 if (compat_rule
->fw_ipopt
!= 0 || compat_rule
->fw_ipnopt
!= 0) {
2930 fill_cmd(cmd
, O_IPOPT
, (compat_rule
->fw_ipopt
& 0xff) |
2931 (compat_rule
->fw_ipnopt
& 0xff) << 8);
2934 cmd
= next_cmd(cmd
);
2937 if (compat_rule
->fw_prot
== IPPROTO_TCP
) {
2938 if (compat_rule
->fw_ipflg
& IP_FW_IF_TCPEST_COMPAT
) {
2939 fill_cmd(cmd
, O_ESTAB
, 0);
2942 cmd
= next_cmd(cmd
);
2945 /* TCP options and flags */
2946 if (compat_rule
->fw_tcpf
!= 0 || compat_rule
->fw_tcpnf
!= 0) {
2947 if ((compat_rule
->fw_tcpf
& IP_FW_TCPF_SYN_COMPAT
) &&
2948 compat_rule
->fw_tcpnf
& IP_FW_TCPF_ACK_COMPAT
) {
2949 fill_cmd(cmd
, O_TCPFLAGS
, (TH_SYN
) | ( (TH_ACK
) & 0xff) <<8);
2952 cmd
= next_cmd(cmd
);
2955 fill_cmd(cmd
, O_TCPFLAGS
, (compat_rule
->fw_tcpf
& 0xff) |
2956 (compat_rule
->fw_tcpnf
& 0xff) << 8);
2959 cmd
= next_cmd(cmd
);
2962 if (compat_rule
->fw_tcpopt
!= 0 || compat_rule
->fw_tcpnopt
!= 0) {
2963 fill_cmd(cmd
, O_TCPOPTS
, (compat_rule
->fw_tcpopt
& 0xff) |
2964 (compat_rule
->fw_tcpnopt
& 0xff) << 8);
2967 cmd
= next_cmd(cmd
);
2972 /* XXX: check this */
2973 if (flag
& IP_FW_F_ICMPBIT_COMPAT
) {
2975 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
; /* alias for cmd */
2976 cmd32
->o
.opcode
= O_ICMPTYPE
;
2977 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
2979 for (i
= 0; i
< IP_FW_ICMPTYPES_DIM_COMPAT
; i
++) {
2980 cmd32
->d
[0] |= compat_rule
->fw_uar_compat
.fw_icmptypes
[i
];
2984 cmd
= next_cmd(cmd
);
2986 } /* end commands */
2988 /* finally, copy everything into the current
2989 * rule buffer in the right order.
2991 dst
= curr_rule
->cmd
;
2993 /* first, do match probability */
2994 if (compat_rule
->fw_flg
& IP_FW_F_RND_MATCH_COMPAT
) {
2995 dst
->opcode
= O_PROB
;
2997 *((int32_t *)(dst
+1)) = compat_rule
->pipe_ptr
;
3001 /* generate O_PROBE_STATE if necessary */
3002 if (have_state
&& have_state
->opcode
!= O_CHECK_STATE
) {
3003 fill_cmd(dst
, O_PROBE_STATE
, 0);
3004 dst
= next_cmd(dst
);
3008 * copy all commands but O_LOG, O_KEEP_STATE
3010 for (src
= (ipfw_insn
*)cmdbuf
; src
!= cmd
; src
+= k
) {
3012 switch (src
->opcode
) {
3017 bcopy(src
, dst
, k
* sizeof(uint32_t));
3023 * put back the have_state command as last opcode
3025 if (have_state
&& have_state
->opcode
!= O_CHECK_STATE
) {
3026 k
= F_LEN(have_state
);
3027 bcopy(have_state
, dst
, k
* sizeof(uint32_t));
3032 * start action section
3034 curr_rule
->act_ofs
= dst
- curr_rule
->cmd
;
3037 * put back O_LOG if necessary
3039 src
= (ipfw_insn
*)cmdbuf
;
3040 if (src
->opcode
== O_LOG
) {
3042 bcopy(src
, dst
, k
* sizeof(uint32_t));
3047 * copy all other actions
3049 for (src
= (ipfw_insn
*)actbuf
; src
!= action
; src
+= k
) {
3051 bcopy(src
, dst
, k
* sizeof(uint32_t));
3055 curr_rule
->cmd_len
= (uint32_t *)dst
- (uint32_t *)(curr_rule
->cmd
);
3060 ipfw_version_one_to_version_two_32(struct sockopt
*sopt
, struct ip_fw
*curr_rule
,
3061 struct ip_fw_compat_32
*rule_vers1
)
3064 struct ip_fw_compat_32
*rule_ptr
;
3065 struct ip_fw_compat_32 rule
;
3068 rule_ptr
= rule_vers1
;
3071 /* do some basic size checking here, more extensive checking later */
3072 if (!sopt
->sopt_val
|| sopt
->sopt_valsize
< sizeof(struct ip_fw_compat_32
))
3075 if ((err
= sooptcopyin(sopt
, &rule
, sizeof(struct ip_fw_compat_32
),
3076 sizeof(struct ip_fw_compat_32
)))) {
3083 /* deal with commands */
3084 ipfw_convert_to_cmds_32(curr_rule
, rule_ptr
);
3086 curr_rule
->version
= IP_FW_CURRENT_API_VERSION
;
3087 curr_rule
->context
= CAST_DOWN_EXPLICIT(void*, rule_ptr
->context
);
3088 curr_rule
->rulenum
= rule_ptr
->fw_number
;
3089 curr_rule
->pcnt
= rule_ptr
->fw_pcnt
;
3090 curr_rule
->bcnt
= rule_ptr
->fw_bcnt
;
3091 curr_rule
->timestamp
= rule_ptr
->timestamp
;
3094 #if FW2_DEBUG_VERBOSE
3095 ipfw_print_vers2_struct(curr_rule
);
3102 ipfw_version_one_to_version_two_64(struct sockopt
*sopt
, struct ip_fw
*curr_rule
,
3103 struct ip_fw_compat_64
*rule_vers1
)
3106 struct ip_fw_compat_64
*rule_ptr
;
3107 struct ip_fw_compat_64 rule
;
3110 rule_ptr
= rule_vers1
;
3113 /* do some basic size checking here, more extensive checking later */
3114 if (!sopt
->sopt_val
|| sopt
->sopt_valsize
< sizeof(struct ip_fw_compat_64
))
3117 if ((err
= sooptcopyin(sopt
, &rule
, sizeof(struct ip_fw_compat_64
),
3118 sizeof(struct ip_fw_compat_64
)))) {
3124 /* deal with commands */
3125 ipfw_convert_to_cmds_64(curr_rule
, rule_ptr
);
3127 curr_rule
->version
= IP_FW_CURRENT_API_VERSION
;
3128 curr_rule
->context
= CAST_DOWN_EXPLICIT( void *, rule_ptr
->context
);
3129 curr_rule
->rulenum
= rule_ptr
->fw_number
;
3130 curr_rule
->pcnt
= rule_ptr
->fw_pcnt
;
3131 curr_rule
->bcnt
= rule_ptr
->fw_bcnt
;
3132 curr_rule
->timestamp
= rule_ptr
->timestamp
;
3135 #if FW2_DEBUG_VERBOSE
3136 ipfw_print_vers2_struct(curr_rule
);
3142 /* This converts to whatever the latest version is. Currently the
3143 * latest version of the firewall is ipfw2.
3146 ipfw_version_one_to_latest_32(struct sockopt
*sopt
, struct ip_fw
*curr_rule
, struct ip_fw_compat_32
*rule_vers1
)
3150 /* if rule_vers1 is not null then this is coming from
3151 * ipfw_version_zero_to_latest(), so pass that along;
3152 * otherwise let ipfw_version_one_to_version_two()
3153 * get the rule from sopt.
3155 err
= ipfw_version_one_to_version_two_32(sopt
, curr_rule
, rule_vers1
);
3161 ipfw_version_one_to_latest_64(struct sockopt
*sopt
, struct ip_fw
*curr_rule
, struct ip_fw_compat_64
*rule_vers1
)
3165 /* if rule_vers1 is not null then this is coming from
3166 * ipfw_version_zero_to_latest(), so pass that along;
3167 * otherwise let ipfw_version_one_to_version_two()
3168 * get the rule from sopt.
3170 err
= ipfw_version_one_to_version_two_64(sopt
, curr_rule
, rule_vers1
);
3179 * XXX - ipfw_version_zero_to_one
3181 * This function is only used in version #1 of ipfw, which is now deprecated.
3186 ipfw_version_zero_to_one(struct ip_old_fw
*rule_vers0
, struct ip_fw_compat
*rule_vers1
)
3188 bzero(rule_vers1
, sizeof(struct ip_fw_compat
));
3189 bcopy(&rule_vers0
->fw_uar
, &rule_vers1
->fw_uar_compat
, sizeof(rule_vers0
->fw_uar
));
3190 bcopy(&rule_vers0
->fw_in_if
, &rule_vers1
->fw_in_if
, sizeof(rule_vers0
->fw_in_if
));
3191 bcopy(&rule_vers0
->fw_out_if
, &rule_vers1
->fw_out_if
, sizeof(rule_vers0
->fw_out_if
));
3192 bcopy(&rule_vers0
->fw_un
, &rule_vers1
->fw_un_compat
, sizeof(rule_vers0
->fw_un
));
3194 rule_vers1
->version
= 10;
3195 rule_vers1
->fw_pcnt
= rule_vers0
->fw_pcnt
;
3196 rule_vers1
->fw_bcnt
= rule_vers0
->fw_bcnt
;
3197 rule_vers1
->fw_src
= rule_vers0
->fw_src
;
3198 rule_vers1
->fw_dst
= rule_vers0
->fw_dst
;
3199 rule_vers1
->fw_smsk
= rule_vers0
->fw_smsk
;
3200 rule_vers1
->fw_dmsk
= rule_vers0
->fw_dmsk
;
3201 rule_vers1
->fw_number
= rule_vers0
->fw_number
;
3202 rule_vers1
->fw_flg
= rule_vers0
->fw_flg
;
3203 rule_vers1
->fw_ipopt
= rule_vers0
->fw_ipopt
;
3204 rule_vers1
->fw_ipnopt
= rule_vers0
->fw_ipnopt
;
3205 rule_vers1
->fw_tcpf
= rule_vers0
->fw_tcpf
& ~IP_OLD_FW_TCPF_ESTAB
;
3206 rule_vers1
->fw_tcpnf
= rule_vers0
->fw_tcpnf
;
3207 rule_vers1
->timestamp
= rule_vers0
->timestamp
;
3208 rule_vers1
->fw_prot
= rule_vers0
->fw_prot
;
3209 rule_vers1
->fw_nports
= rule_vers0
->fw_nports
;
3210 rule_vers1
->pipe_ptr
= rule_vers0
->pipe_ptr
;
3211 rule_vers1
->next_rule_ptr
= rule_vers0
->next_rule_ptr
;
3212 rule_vers1
->fw_ipflg
= (rule_vers0
->fw_tcpf
& IP_OLD_FW_TCPF_ESTAB
) ? IP_FW_IF_TCPEST_COMPAT
: 0;
3215 #endif /* !ipfw_version_zero_to_one */
3217 /* rule is a u_int32_t buffer[255] into which the converted
3218 * (if necessary) rules go.
3221 ipfw_convert_to_latest(struct sockopt
*sopt
, struct ip_fw
*curr_rule
, int api_version
, int is64user
)
3225 /* the following functions copy the rules passed in and
3226 * convert to latest structures based on version
3228 switch (api_version
) {
3229 case IP_FW_VERSION_0
:
3230 /* we're not supporting VERSION 0 */
3234 case IP_FW_VERSION_1
:
3235 /* this is the version supported in Panther */
3237 err
= ipfw_version_one_to_latest_64(sopt
, curr_rule
, NULL
);
3239 err
= ipfw_version_one_to_latest_32(sopt
, curr_rule
, NULL
);
3242 case IP_FW_CURRENT_API_VERSION
:
3244 /* do nothing here... */
3248 /* unrecognized/unsupported version */
3257 ipfw_get_command_and_version(struct sockopt
*sopt
, int *command
, u_int32_t
*api_version
)
3261 u_int32_t vers
= IP_FW_VERSION_NONE
;
3263 /* first deal with the oldest version */
3264 if (sopt
->sopt_name
== IP_OLD_FW_GET
) {
3265 vers
= IP_FW_VERSION_0
;
3268 else if (sopt
->sopt_name
== IP_OLD_FW_FLUSH
) {
3269 vers
= IP_FW_VERSION_0
;
3272 else if (sopt
->sopt_name
== IP_OLD_FW_ZERO
) {
3273 vers
= IP_FW_VERSION_0
;
3276 else if (sopt
->sopt_name
== IP_OLD_FW_ADD
) {
3277 vers
= IP_FW_VERSION_0
;
3280 else if (sopt
->sopt_name
== IP_OLD_FW_DEL
) {
3281 vers
= IP_FW_VERSION_0
;
3284 else if (sopt
->sopt_name
== IP_OLD_FW_RESETLOG
) {
3285 vers
= IP_FW_VERSION_0
;
3286 cmd
= IP_FW_RESETLOG
;
3289 cmd
= sopt
->sopt_name
;
3292 if (vers
== IP_FW_VERSION_NONE
) {
3293 /* working off the fact that the offset
3294 * is the same in both structs.
3296 struct ip_fw_64 rule
;
3299 if (proc_is64bit(sopt
->sopt_p
))
3300 copyinsize
= sizeof(struct ip_fw_64
);
3302 copyinsize
= sizeof(struct ip_fw_32
);
3304 if (!sopt
->sopt_val
|| sopt
->sopt_valsize
< copyinsize
)
3306 if ((err
= sooptcopyin(sopt
, &rule
, copyinsize
, copyinsize
))) {
3310 vers
= rule
.version
;
3317 *api_version
= vers
;