2 * Copyright (c) 2004-2012 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) {
278 printf("%c%d", sep
, i
);
284 * print flags set/clear in the two bitmasks passed as parameters.
285 * There is a specialized check for f_tcpflags.
288 print_flags(char const *name
, ipfw_insn
*cmd
, struct _s_x
*list
)
290 char const *comma
= "";
292 uint8_t set
= cmd
->arg1
& 0xff;
293 uint8_t clear
= (cmd
->arg1
>> 8) & 0xff;
295 if (list
== f_tcpflags
&& set
== TH_SYN
&& clear
== TH_ACK
) {
300 printf(" %s ", name
);
301 for (i
= 0; list
[i
].x
!= 0; i
++) {
302 if (set
& list
[i
].x
) {
304 printf("%s%s", comma
, list
[i
].s
);
307 if (clear
& list
[i
].x
) {
309 printf("%s!%s", comma
, list
[i
].s
);
316 contigmask(uint8_t *p
, int len
)
320 for (i
= 0; i
< len
; i
++) {
321 if ((p
[i
/ 8] & (1 << (7 - (i
% 8)))) == 0) { /* first bit unset */
325 for (n
= i
+ 1; n
< len
; n
++) {
326 if ((p
[n
/ 8] & (1 << (7 - (n
% 8)))) != 0) {
327 return -1; /* mask not contiguous */
334 * Print the ip address contained in a command.
337 print_ip(ipfw_insn_ip
*cmd
)
339 int len
= F_LEN((ipfw_insn
*)cmd
);
340 uint32_t *a
= ((ipfw_insn_u32
*)cmd
)->d
;
341 char ipv4str
[MAX_IPv4_STR_LEN
];
343 printf("%s ", cmd
->o
.len
& F_NOT
? " not": "");
345 if (cmd
->o
.opcode
== O_IP_SRC_ME
|| cmd
->o
.opcode
== O_IP_DST_ME
) {
351 * len == 2 indicates a single IP, whereas lists of 1 or more
352 * addr/mask pairs have len = (2n+1). We convert len to n so we
353 * use that to count the number of entries.
355 for (len
= len
/ 2; len
> 0; len
--, a
+= 2) {
356 int mb
= /* mask length */
357 (cmd
->o
.opcode
== O_IP_SRC
|| cmd
->o
.opcode
== O_IP_DST
) ?
358 32 : contigmask((uint8_t *)&(a
[1]), 32);
359 if (mb
== 0) { /* any */
361 } else { /* numeric IP followed by some kind of mask */
362 printf("%s", inet_ntop(AF_INET
, &a
[0], ipv4str
, sizeof(ipv4str
)));
364 printf(":%s", inet_ntop(AF_INET
, &a
[1], ipv4str
, sizeof(ipv4str
)));
365 } else if (mb
< 32) {
376 * prints a MAC address/mask pair
379 print_mac(uint8_t *addr
, uint8_t *mask
)
381 int l
= contigmask(mask
, 48);
386 printf(" %02x:%02x:%02x:%02x:%02x:%02x",
387 addr
[0], addr
[1], addr
[2], addr
[3], addr
[4], addr
[5]);
389 printf("&%02x:%02x:%02x:%02x:%02x:%02x",
390 mask
[0], mask
[1], mask
[2],
391 mask
[3], mask
[4], mask
[5]);
398 #endif /* !version #1 */
400 #if FW2_DEBUG_VERBOSE
402 ipfw_print_vers2_struct(struct ip_fw
*vers2_rule
)
406 ipfw_insn_log
*logptr
= NULL
;
407 char ipv4str
[MAX_IPv4_STR_LEN
];
409 print_fw_version(vers2_rule
->version
);
411 printf("act_ofs: %d\n", vers2_rule
->act_ofs
);
412 printf("cmd_len: %d\n", vers2_rule
->cmd_len
);
413 printf("rulenum: %d\n", vers2_rule
->rulenum
);
414 printf("set: %d\n", vers2_rule
->set
);
415 printf("pcnt: %llu\n", vers2_rule
->pcnt
);
416 printf("bcnt: %llu\n", vers2_rule
->bcnt
);
417 printf("timestamp: %d\n", vers2_rule
->timestamp
);
420 * first print actions
422 for (l
= vers2_rule
->cmd_len
- vers2_rule
->act_ofs
, cmd
= ACTION_PTR(vers2_rule
);
423 l
> 0; l
-= F_LEN(cmd
), cmd
+= F_LEN(cmd
)) {
424 switch (cmd
->opcode
) {
426 printf("check-state");
442 if (cmd
->arg1
== ICMP_REJECT_RST
) {
444 } else if (cmd
->arg1
== ICMP_UNREACH_HOST
) {
447 printf("unreach %u", cmd
->arg1
);
452 printf("skipto %u", cmd
->arg1
);
456 printf("pipe %u", cmd
->arg1
);
460 printf("queue %u", cmd
->arg1
);
464 printf("divert %u", cmd
->arg1
);
468 printf("tee %u", cmd
->arg1
);
473 ipfw_insn_sa
*s
= (ipfw_insn_sa
*)cmd
;
476 inet_ntop(AF_INET
, &s
->sa
.sin_addr
, ipv4str
,
478 if (s
->sa
.sin_port
) {
479 printf(",%d", s
->sa
.sin_port
);
484 case O_LOG
: /* O_LOG is printed last */
485 logptr
= (ipfw_insn_log
*)cmd
;
489 printf("** unrecognized action %d len %d",
490 cmd
->opcode
, cmd
->len
);
494 if (logptr
->max_log
> 0) {
495 printf(" log logamount %d", logptr
->max_log
);
502 * then print the body.
504 for (l
= vers2_rule
->act_ofs
, cmd
= vers2_rule
->cmd
;
505 l
> 0; l
-= F_LEN(cmd
), cmd
+= F_LEN(cmd
)) {
507 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
;
509 switch (cmd
->opcode
) {
511 break; /* done already */
514 break; /* no need to print anything here */
518 ipfw_insn_mac
*m
= (ipfw_insn_mac
*)cmd
;
520 if (cmd
->len
& F_NOT
) {
524 print_mac(m
->addr
, m
->mask
);
525 print_mac(m
->addr
+ 6, m
->mask
+ 6);
531 uint16_t *p
= ((ipfw_insn_u16
*)cmd
)->ports
;
534 for (i
= F_LEN((ipfw_insn
*)cmd
) - 1; i
> 0; i
--, p
+= 2) {
535 printf("0x%04x", p
[0]);
538 printf("0x%04x", p
[1]);
547 print_ip((ipfw_insn_ip
*)cmd
);
553 print_ip((ipfw_insn_ip
*)cmd
);
559 uint16_t *p
= ((ipfw_insn_u16
*)cmd
)->ports
;
562 for (i
= F_LEN((ipfw_insn
*)cmd
) - 1; i
> 0; i
--, p
+= 2) {
563 printf("0x%04x", p
[0]);
566 printf("0x%04x", p
[1]);
576 if (cmd
->len
& F_NOT
) {
580 printf(" %u", cmd
->arg1
);
585 default: /*options ... */
587 if (cmd
->len
& F_NOT
&& cmd
->opcode
!= O_IN
) {
590 switch (cmd
->opcode
) {
596 printf(cmd
->len
& F_NOT
? " out" : " O_IN");
607 ipfw_insn_if
*cmdif
= (ipfw_insn_if
*)cmd
;
609 if (cmd
->opcode
== O_XMIT
) {
611 } else if (cmd
->opcode
== O_RECV
) {
613 } else { /* if (cmd->opcode == O_VIA) */
616 if (cmdif
->name
[0] == '\0') {
618 inet_ntop(AF_INET
, &cmdif
->p
.ip
, ipv4str
,
620 } else if (cmdif
->p
.unit
== -1) {
621 printf(" %s %s*", s
, cmdif
->name
);
623 printf(" %s %s%d", s
, cmdif
->name
,
630 if (F_LEN(cmd
) == 1) {
631 printf(" ipid %u", cmd
->arg1
);
633 uint16_t *p
= ((ipfw_insn_u16
*)cmd
)->ports
;
636 for (i
= F_LEN((ipfw_insn
*)cmd
) - 1; i
> 0; i
--, p
+= 2) {
637 printf("0x%04x", p
[0]);
640 printf("0x%04x", p
[1]);
649 if (F_LEN(cmd
) == 1) {
650 printf(" ipttl %u", cmd
->arg1
);
652 uint16_t *p
= ((ipfw_insn_u16
*)cmd
)->ports
;
655 for (i
= F_LEN((ipfw_insn
*)cmd
) - 1; i
> 0; i
--, p
+= 2) {
656 printf("0x%04x", p
[0]);
659 printf("0x%04x", p
[1]);
668 printf(" ipver %u", cmd
->arg1
);
672 printf(" ipprecedence %u", (cmd
->arg1
) >> 5 );
676 if (F_LEN(cmd
) == 1) {
677 printf(" iplen %u", cmd
->arg1
);
679 uint16_t *p
= ((ipfw_insn_u16
*)cmd
)->ports
;
682 for (i
= F_LEN((ipfw_insn
*)cmd
) - 1; i
> 0; i
--, p
+= 2) {
683 printf("0x%04x", p
[0]);
686 printf("0x%04x", p
[1]);
695 print_flags("ipoptions", cmd
, f_ipopts
);
699 print_flags("iptos", cmd
, f_iptos
);
703 print_icmptypes((ipfw_insn_u32
*)cmd
);
707 printf(" established");
711 print_flags("tcpflags", cmd
, f_tcpflags
);
715 print_flags("tcpoptions", cmd
, f_tcpopts
);
719 printf(" tcpwin %d", ntohs(cmd
->arg1
));
723 printf(" tcpack %u", ntohl(cmd32
->d
[0]));
727 printf(" tcpseq %u", ntohl(cmd32
->d
[0]));
731 printf(" uid %u", cmd32
->d
[0]);
735 printf(" gid %u", cmd32
->d
[0]);
739 printf(" verrevpath");
750 printf(" keep-state");
755 struct _s_x
*p
= limit_masks
;
756 ipfw_insn_limit
*c
= (ipfw_insn_limit
*)cmd
;
757 uint8_t x
= c
->limit_mask
;
758 char const *comma
= " ";
761 for (; p
->x
!= 0; p
++) {
762 if ((x
& p
->x
) == p
->x
) {
764 printf("%s%s", comma
, p
->s
);
768 printf(" %d", c
->conn_limit
);
774 printf(" [opcode %d len %d]",
775 cmd
->opcode
, cmd
->len
);
782 #endif /* !FW2_DEBUG_VERBOSE */
786 * helper function, updates the pointer to cmd with the length
787 * of the current command, and also cleans up the first word of
788 * the new command in case it has been clobbered before.
792 next_cmd(ipfw_insn
*cmd
)
795 bzero(cmd
, sizeof(*cmd
));
800 * A function to fill simple commands of size 1.
801 * Existing flags are preserved.
805 fill_cmd(ipfw_insn
*cmd
, enum ipfw_opcodes opcode
, uint16_t arg
)
807 cmd
->opcode
= opcode
;
808 cmd
->len
= ((cmd
->len
) & (F_NOT
| F_OR
)) | 1;
814 fill_compat_tcpflags(u_int32_t flags
)
816 u_int32_t flags_compat
= 0;
818 if (flags
& TH_FIN
) {
819 flags_compat
|= IP_FW_TCPF_FIN_COMPAT
;
821 if (flags
& TH_SYN
) {
822 flags_compat
|= IP_FW_TCPF_SYN_COMPAT
;
824 if (flags
& TH_RST
) {
825 flags_compat
|= IP_FW_TCPF_RST_COMPAT
;
827 if (flags
& TH_PUSH
) {
828 flags_compat
|= IP_FW_TCPF_PSH_COMPAT
;
830 if (flags
& TH_ACK
) {
831 flags_compat
|= IP_FW_TCPF_ACK_COMPAT
;
833 if (flags
& TH_URG
) {
834 flags_compat
|= IP_FW_TCPF_URG_COMPAT
;
841 /* ********************************************
842 * *********** Convert from Latest ************
843 * ********************************************/
846 * Things we're actively ignoring:
847 * sets, sets of addresses, blocks (NOT, OR)
850 ipfw_map_from_cmds_32(struct ip_fw_32
*curr_rule
, struct ip_fw_compat_32
*compat_rule
)
855 for (l
= curr_rule
->act_ofs
, cmd
= curr_rule
->cmd
;
857 l
-= F_LEN(cmd
), cmd
+= F_LEN(cmd
)) {
859 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
;
861 switch (cmd
->opcode
) {
864 compat_rule
->fw_prot
= cmd
->arg1
;
868 compat_rule
->fw_flg
|= IP_FW_F_SME_COMPAT
;
869 if (cmd
->len
& F_NOT
) {
870 compat_rule
->fw_flg
|= IP_FW_F_INVSRC_COMPAT
;
877 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
879 compat_rule
->fw_src
= ip
->addr
;
880 compat_rule
->fw_smsk
= ip
->mask
;
881 if (cmd
->len
& F_NOT
) {
882 compat_rule
->fw_flg
|= IP_FW_F_INVSRC_COMPAT
;
890 * for now we only deal with one address
891 * per rule and ignore sets of addresses
893 compat_rule
->fw_src
.s_addr
= cmd32
->d
[0];
894 if (cmd
->len
& F_NOT
) {
895 compat_rule
->fw_flg
|= IP_FW_F_INVSRC_COMPAT
;
902 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
903 uint16_t *p
= ports
->ports
;
906 /* copy list of ports */
907 for (i
= F_LEN(cmd
) - 1, j
= 0; i
> 0; i
--, j
++, p
+= 2) {
909 /* this is a range */
910 compat_rule
->fw_flg
|= IP_FW_F_SRNG_COMPAT
;
911 compat_rule
->fw_uar_compat
.fw_pts
[j
++] = p
[0];
912 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[1];
914 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[0];
917 IP_FW_SETNSRCP_COMPAT(compat_rule
, j
);
924 compat_rule
->fw_flg
|= IP_FW_F_DME_COMPAT
;
925 if (cmd
->len
& F_NOT
) {
926 compat_rule
->fw_flg
|= IP_FW_F_INVDST_COMPAT
;
933 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
935 compat_rule
->fw_dst
= ip
->addr
;
936 compat_rule
->fw_dmsk
= ip
->mask
;
937 if (cmd
->len
& F_NOT
) {
938 compat_rule
->fw_flg
|= IP_FW_F_INVDST_COMPAT
;
945 * for now we only deal with one address
946 * per rule, and ignore sets of addresses
948 compat_rule
->fw_dst
.s_addr
= cmd32
->d
[0];
949 if (cmd
->len
& F_NOT
) {
950 compat_rule
->fw_flg
|= IP_FW_F_INVDST_COMPAT
;
957 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
958 uint16_t *p
= ports
->ports
;
960 j
= IP_FW_GETNSRCP_COMPAT(compat_rule
);
962 /* copy list of ports */
963 for (i
= F_LEN(cmd
) - 1; i
> 0; i
--, j
++, p
+= 2) {
965 /* this is a range */
966 compat_rule
->fw_flg
|= IP_FW_F_DRNG_COMPAT
;
967 compat_rule
->fw_uar_compat
.fw_pts
[j
++] = p
[0];
968 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[1];
970 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[0];
973 IP_FW_SETNDSTP_COMPAT(compat_rule
, (j
- IP_FW_GETNSRCP_COMPAT(compat_rule
)));
980 ipfw_insn_log
*c
= (ipfw_insn_log
*)cmd
;
982 compat_rule
->fw_flg
|= IP_FW_F_PRN_COMPAT
;
983 compat_rule
->fw_logamount
= c
->max_log
;
987 compat_rule
->fw_flg
|= IP_FW_F_UID_COMPAT
;
988 compat_rule
->fw_uid
= cmd32
->d
[0];
992 if (cmd
->len
& F_NOT
) {
993 compat_rule
->fw_flg
|= IP_FW_F_OUT_COMPAT
;
995 compat_rule
->fw_flg
|= IP_FW_F_IN_COMPAT
;
1000 compat_rule
->fw_flg
|= IP_FW_F_KEEP_S_COMPAT
;
1004 compat_rule
->fw_flg
|= IP_FW_BRIDGED_COMPAT
;
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_OIFACE_COMPAT
;
1015 ifu
.fu_via_ip
.s_addr
= 0;
1016 } else if (ifcmd
->p
.ip
.s_addr
!= 0) {
1017 compat_rule
->fw_flg
|= IP_FW_F_OIFACE_COMPAT
;
1018 ifu
.fu_via_ip
= ifcmd
->p
.ip
;
1020 compat_rule
->fw_flg
|= IP_FW_F_OIFNAME_COMPAT
;
1021 strncpy(ifu
.fu_via_if_compat
.name
, ifcmd
->name
, sizeof(ifu
.fu_via_if_compat
.name
));
1022 ifu
.fu_via_if_compat
.unit
= ifcmd
->p
.unit
;
1024 compat_rule
->fw_out_if
= ifu
;
1031 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1032 union ip_fw_if_compat ifu
;
1034 if ((ifcmd
->o
.len
== 0) && (ifcmd
->name
[0] == '\0')) {
1036 compat_rule
->fw_flg
|= IP_FW_F_IIFACE_COMPAT
;
1037 ifu
.fu_via_ip
.s_addr
= 0;
1038 } else if (ifcmd
->p
.ip
.s_addr
!= 0) {
1039 compat_rule
->fw_flg
|= IP_FW_F_IIFACE_COMPAT
;
1040 ifu
.fu_via_ip
= ifcmd
->p
.ip
;
1042 compat_rule
->fw_flg
|= IP_FW_F_IIFNAME_COMPAT
;
1043 strncpy(ifu
.fu_via_if_compat
.name
, ifcmd
->name
, sizeof(ifu
.fu_via_if_compat
.name
));
1044 ifu
.fu_via_if_compat
.unit
= ifcmd
->p
.unit
;
1046 compat_rule
->fw_in_if
= ifu
;
1053 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1054 union ip_fw_if_compat ifu
;
1056 if ((ifcmd
->o
.len
== 0) && (ifcmd
->name
[0] == '\0')) {
1058 ifu
.fu_via_ip
.s_addr
= 0;
1059 } else if (ifcmd
->name
[0] != '\0') {
1060 compat_rule
->fw_flg
|= IP_FW_F_IIFNAME_COMPAT
;
1061 strncpy(ifu
.fu_via_if_compat
.name
, ifcmd
->name
, sizeof(ifu
.fu_via_if_compat
.name
));
1062 ifu
.fu_via_if_compat
.unit
= ifcmd
->p
.unit
;
1064 ifu
.fu_via_ip
= ifcmd
->p
.ip
;
1066 compat_rule
->fw_flg
|= IF_FW_F_VIAHACK_COMPAT
;
1067 compat_rule
->fw_out_if
= compat_rule
->fw_in_if
= ifu
;
1073 compat_rule
->fw_flg
|= IP_FW_F_FRAG_COMPAT
;
1078 compat_rule
->fw_ipopt
= (cmd
->arg1
& 0xff);
1079 compat_rule
->fw_ipnopt
= ((cmd
->arg1
>> 8) & 0xff);
1083 /* check for "setup" */
1084 if ((cmd
->arg1
& 0xff) == TH_SYN
&&
1085 ((cmd
->arg1
>> 8) & 0xff) == TH_ACK
) {
1086 compat_rule
->fw_tcpf
= IP_FW_TCPF_SYN_COMPAT
;
1087 compat_rule
->fw_tcpnf
= IP_FW_TCPF_ACK_COMPAT
;
1089 compat_rule
->fw_tcpf
= fill_compat_tcpflags(cmd
->arg1
& 0xff);
1090 compat_rule
->fw_tcpnf
= fill_compat_tcpflags((cmd
->arg1
>> 8) & 0xff);
1096 compat_rule
->fw_tcpopt
= (cmd
->arg1
& 0xff);
1097 compat_rule
->fw_tcpnopt
= ((cmd
->arg1
>> 8) & 0xff);
1101 compat_rule
->fw_ipflg
|= IP_FW_IF_TCPEST_COMPAT
;
1107 /* XXX: check this */
1110 compat_rule
->fw_flg
|= IP_FW_F_ICMPBIT_COMPAT
;
1111 for (i
= 0; i
< sizeof(uint32_t); i
++) {
1112 type
= cmd32
->d
[0] & i
;
1114 compat_rule
->fw_uar_compat
.fw_icmptypes
[type
/ (sizeof(unsigned) * 8)] |=
1115 1 << (type
% (sizeof(unsigned) * 8));
1126 ipfw_map_from_cmds_64(struct ip_fw_64
*curr_rule
, struct ip_fw_compat_64
*compat_rule
)
1130 for (l
= curr_rule
->act_ofs
, cmd
= curr_rule
->cmd
;
1132 l
-= F_LEN(cmd
), cmd
+= F_LEN(cmd
)) {
1134 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
;
1136 switch (cmd
->opcode
) {
1139 compat_rule
->fw_prot
= cmd
->arg1
;
1143 compat_rule
->fw_flg
|= IP_FW_F_SME_COMPAT
;
1144 if (cmd
->len
& F_NOT
) {
1145 compat_rule
->fw_flg
|= IP_FW_F_INVSRC_COMPAT
;
1152 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
1154 compat_rule
->fw_src
= ip
->addr
;
1155 compat_rule
->fw_smsk
= ip
->mask
;
1156 if (cmd
->len
& F_NOT
) {
1157 compat_rule
->fw_flg
|= IP_FW_F_INVSRC_COMPAT
;
1165 * for now we only deal with one address
1166 * per rule and ignore sets of addresses
1168 compat_rule
->fw_src
.s_addr
= cmd32
->d
[0];
1169 if (cmd
->len
& F_NOT
) {
1170 compat_rule
->fw_flg
|= IP_FW_F_INVSRC_COMPAT
;
1177 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
1178 uint16_t *p
= ports
->ports
;
1181 /* copy list of ports */
1182 for (i
= F_LEN(cmd
) - 1, j
= 0; i
> 0; i
--, j
++, p
+= 2) {
1184 /* this is a range */
1185 compat_rule
->fw_flg
|= IP_FW_F_SRNG_COMPAT
;
1186 compat_rule
->fw_uar_compat
.fw_pts
[j
++] = p
[0];
1187 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[1];
1189 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[0];
1192 IP_FW_SETNSRCP_COMPAT(compat_rule
, j
);
1199 compat_rule
->fw_flg
|= IP_FW_F_DME_COMPAT
;
1200 if (cmd
->len
& F_NOT
) {
1201 compat_rule
->fw_flg
|= IP_FW_F_INVDST_COMPAT
;
1208 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
1210 compat_rule
->fw_dst
= ip
->addr
;
1211 compat_rule
->fw_dmsk
= ip
->mask
;
1212 if (cmd
->len
& F_NOT
) {
1213 compat_rule
->fw_flg
|= IP_FW_F_INVDST_COMPAT
;
1220 * for now we only deal with one address
1221 * per rule, and ignore sets of addresses
1223 compat_rule
->fw_dst
.s_addr
= cmd32
->d
[0];
1224 if (cmd
->len
& F_NOT
) {
1225 compat_rule
->fw_flg
|= IP_FW_F_INVDST_COMPAT
;
1232 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
1233 uint16_t *p
= ports
->ports
;
1235 j
= IP_FW_GETNSRCP_COMPAT(compat_rule
);
1237 /* copy list of ports */
1238 for (i
= F_LEN(cmd
) - 1; i
> 0; i
--, j
++, p
+= 2) {
1240 /* this is a range */
1241 compat_rule
->fw_flg
|= IP_FW_F_DRNG_COMPAT
;
1242 compat_rule
->fw_uar_compat
.fw_pts
[j
++] = p
[0];
1243 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[1];
1245 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[0];
1248 IP_FW_SETNDSTP_COMPAT(compat_rule
, (j
- IP_FW_GETNSRCP_COMPAT(compat_rule
)));
1255 ipfw_insn_log
*c
= (ipfw_insn_log
*)cmd
;
1257 compat_rule
->fw_flg
|= IP_FW_F_PRN_COMPAT
;
1258 compat_rule
->fw_logamount
= c
->max_log
;
1262 compat_rule
->fw_flg
|= IP_FW_F_UID_COMPAT
;
1263 compat_rule
->fw_uid
= cmd32
->d
[0];
1267 if (cmd
->len
& F_NOT
) {
1268 compat_rule
->fw_flg
|= IP_FW_F_OUT_COMPAT
;
1270 compat_rule
->fw_flg
|= IP_FW_F_IN_COMPAT
;
1275 compat_rule
->fw_flg
|= IP_FW_F_KEEP_S_COMPAT
;
1279 compat_rule
->fw_flg
|= IP_FW_BRIDGED_COMPAT
;
1284 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1285 union ip_fw_if_compat ifu
;
1287 if ((ifcmd
->o
.len
== 0) && (ifcmd
->name
[0] == '\0')) {
1289 compat_rule
->fw_flg
|= IP_FW_F_OIFACE_COMPAT
;
1290 ifu
.fu_via_ip
.s_addr
= 0;
1291 } else if (ifcmd
->p
.ip
.s_addr
!= 0) {
1292 compat_rule
->fw_flg
|= IP_FW_F_OIFACE_COMPAT
;
1293 ifu
.fu_via_ip
= ifcmd
->p
.ip
;
1295 compat_rule
->fw_flg
|= IP_FW_F_OIFNAME_COMPAT
;
1296 strncpy(ifu
.fu_via_if_compat
.name
, ifcmd
->name
, sizeof(ifu
.fu_via_if_compat
.name
));
1297 ifu
.fu_via_if_compat
.unit
= ifcmd
->p
.unit
;
1299 compat_rule
->fw_out_if
= ifu
;
1306 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1307 union ip_fw_if_compat ifu
;
1309 if ((ifcmd
->o
.len
== 0) && (ifcmd
->name
[0] == '\0')) {
1311 compat_rule
->fw_flg
|= IP_FW_F_IIFACE_COMPAT
;
1312 ifu
.fu_via_ip
.s_addr
= 0;
1313 } else if (ifcmd
->p
.ip
.s_addr
!= 0) {
1314 compat_rule
->fw_flg
|= IP_FW_F_IIFACE_COMPAT
;
1315 ifu
.fu_via_ip
= ifcmd
->p
.ip
;
1317 compat_rule
->fw_flg
|= IP_FW_F_IIFNAME_COMPAT
;
1318 strncpy(ifu
.fu_via_if_compat
.name
, ifcmd
->name
, sizeof(ifu
.fu_via_if_compat
.name
));
1319 ifu
.fu_via_if_compat
.unit
= ifcmd
->p
.unit
;
1321 compat_rule
->fw_in_if
= ifu
;
1328 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1329 union ip_fw_if_compat ifu
;
1331 if ((ifcmd
->o
.len
== 0) && (ifcmd
->name
[0] == '\0')) {
1333 ifu
.fu_via_ip
.s_addr
= 0;
1334 } else if (ifcmd
->name
[0] != '\0') {
1335 compat_rule
->fw_flg
|= IP_FW_F_IIFNAME_COMPAT
;
1336 strncpy(ifu
.fu_via_if_compat
.name
, ifcmd
->name
, sizeof(ifu
.fu_via_if_compat
.name
));
1337 ifu
.fu_via_if_compat
.unit
= ifcmd
->p
.unit
;
1339 ifu
.fu_via_ip
= ifcmd
->p
.ip
;
1341 compat_rule
->fw_flg
|= IF_FW_F_VIAHACK_COMPAT
;
1342 compat_rule
->fw_out_if
= compat_rule
->fw_in_if
= ifu
;
1348 compat_rule
->fw_flg
|= IP_FW_F_FRAG_COMPAT
;
1353 compat_rule
->fw_ipopt
= (cmd
->arg1
& 0xff);
1354 compat_rule
->fw_ipnopt
= ((cmd
->arg1
>> 8) & 0xff);
1358 /* check for "setup" */
1359 if ((cmd
->arg1
& 0xff) == TH_SYN
&&
1360 ((cmd
->arg1
>> 8) & 0xff) == TH_ACK
) {
1361 compat_rule
->fw_tcpf
= IP_FW_TCPF_SYN_COMPAT
;
1362 compat_rule
->fw_tcpnf
= IP_FW_TCPF_ACK_COMPAT
;
1364 compat_rule
->fw_tcpf
= fill_compat_tcpflags(cmd
->arg1
& 0xff);
1365 compat_rule
->fw_tcpnf
= fill_compat_tcpflags((cmd
->arg1
>> 8) & 0xff);
1371 compat_rule
->fw_tcpopt
= (cmd
->arg1
& 0xff);
1372 compat_rule
->fw_tcpnopt
= ((cmd
->arg1
>> 8) & 0xff);
1376 compat_rule
->fw_ipflg
|= IP_FW_IF_TCPEST_COMPAT
;
1382 /* XXX: check this */
1385 compat_rule
->fw_flg
|= IP_FW_F_ICMPBIT_COMPAT
;
1386 for (i
= 0; i
< sizeof(uint32_t); i
++) {
1387 type
= cmd32
->d
[0] & i
;
1389 compat_rule
->fw_uar_compat
.fw_icmptypes
[type
/ (sizeof(unsigned) * 8)] |=
1390 1 << (type
% (sizeof(unsigned) * 8));
1401 ipfw_map_from_actions_32(struct ip_fw_32
*curr_rule
, struct ip_fw_compat_32
*compat_rule
)
1406 for (l
= curr_rule
->cmd_len
- curr_rule
->act_ofs
, cmd
= ACTION_PTR(curr_rule
);
1408 l
-= F_LEN(cmd
), cmd
+= F_LEN(cmd
)) {
1409 switch (cmd
->opcode
) {
1411 compat_rule
->fw_flg
|= IP_FW_F_ACCEPT_COMPAT
;
1414 compat_rule
->fw_flg
|= IP_FW_F_COUNT_COMPAT
;
1417 compat_rule
->fw_flg
|= IP_FW_F_PIPE_COMPAT
;
1418 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1421 compat_rule
->fw_flg
|= IP_FW_F_QUEUE_COMPAT
;
1422 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1425 compat_rule
->fw_flg
|= IP_FW_F_SKIPTO_COMPAT
;
1426 compat_rule
->fw_skipto_rule_compat
= cmd
->arg1
;
1429 compat_rule
->fw_flg
|= IP_FW_F_DIVERT_COMPAT
;
1430 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1433 compat_rule
->fw_flg
|= IP_FW_F_TEE_COMPAT
;
1434 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1438 ipfw_insn_sa
*p
= (ipfw_insn_sa
*)cmd
;
1440 compat_rule
->fw_flg
|= IP_FW_F_FWD_COMPAT
;
1441 compat_rule
->fw_fwd_ip_compat
.sin_len
= p
->sa
.sin_len
;
1442 compat_rule
->fw_fwd_ip_compat
.sin_family
= p
->sa
.sin_family
;
1443 compat_rule
->fw_fwd_ip_compat
.sin_port
= p
->sa
.sin_port
;
1444 compat_rule
->fw_fwd_ip_compat
.sin_addr
= p
->sa
.sin_addr
;
1449 compat_rule
->fw_flg
|= IP_FW_F_DENY_COMPAT
;
1452 compat_rule
->fw_flg
|= IP_FW_F_REJECT_COMPAT
;
1453 compat_rule
->fw_reject_code_compat
= cmd
->arg1
;
1456 compat_rule
->fw_flg
|= IP_FW_F_CHECK_S_COMPAT
;
1465 ipfw_map_from_actions_64(struct ip_fw_64
*curr_rule
, struct ip_fw_compat_64
*compat_rule
)
1469 for (l
= curr_rule
->cmd_len
- curr_rule
->act_ofs
, cmd
= ACTION_PTR(curr_rule
);
1471 l
-= F_LEN(cmd
), cmd
+= F_LEN(cmd
)) {
1472 switch (cmd
->opcode
) {
1474 compat_rule
->fw_flg
|= IP_FW_F_ACCEPT_COMPAT
;
1477 compat_rule
->fw_flg
|= IP_FW_F_COUNT_COMPAT
;
1480 compat_rule
->fw_flg
|= IP_FW_F_PIPE_COMPAT
;
1481 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1484 compat_rule
->fw_flg
|= IP_FW_F_QUEUE_COMPAT
;
1485 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1488 compat_rule
->fw_flg
|= IP_FW_F_SKIPTO_COMPAT
;
1489 compat_rule
->fw_skipto_rule_compat
= cmd
->arg1
;
1492 compat_rule
->fw_flg
|= IP_FW_F_DIVERT_COMPAT
;
1493 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1496 compat_rule
->fw_flg
|= IP_FW_F_TEE_COMPAT
;
1497 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1501 ipfw_insn_sa
*p
= (ipfw_insn_sa
*)cmd
;
1503 compat_rule
->fw_flg
|= IP_FW_F_FWD_COMPAT
;
1504 compat_rule
->fw_fwd_ip_compat
.sin_len
= p
->sa
.sin_len
;
1505 compat_rule
->fw_fwd_ip_compat
.sin_family
= p
->sa
.sin_family
;
1506 compat_rule
->fw_fwd_ip_compat
.sin_port
= p
->sa
.sin_port
;
1507 compat_rule
->fw_fwd_ip_compat
.sin_addr
= p
->sa
.sin_addr
;
1512 compat_rule
->fw_flg
|= IP_FW_F_DENY_COMPAT
;
1515 compat_rule
->fw_flg
|= IP_FW_F_REJECT_COMPAT
;
1516 compat_rule
->fw_reject_code_compat
= cmd
->arg1
;
1519 compat_rule
->fw_flg
|= IP_FW_F_CHECK_S_COMPAT
;
1528 ipfw_version_latest_to_one_32(struct ip_fw_32
*curr_rule
, struct ip_fw_compat_32
*rule_vers1
)
1534 bzero(rule_vers1
, sizeof(struct ip_fw_compat_32
));
1536 rule_vers1
->version
= IP_FW_VERSION_1
;
1537 rule_vers1
->context
= CAST_DOWN_EXPLICIT(user32_addr_t
, curr_rule
->context
);
1538 rule_vers1
->fw_number
= curr_rule
->rulenum
;
1539 rule_vers1
->fw_pcnt
= curr_rule
->pcnt
;
1540 rule_vers1
->fw_bcnt
= curr_rule
->bcnt
;
1541 rule_vers1
->timestamp
= curr_rule
->timestamp
;
1543 /* convert actions */
1544 ipfw_map_from_actions_32(curr_rule
, rule_vers1
);
1546 /* convert commands */
1547 ipfw_map_from_cmds_32(curr_rule
, rule_vers1
);
1549 #if FW2_DEBUG_VERBOSE
1550 ipfw_print_vers1_struct_32(rule_vers1
);
1555 ipfw_version_latest_to_one_64(struct ip_fw_64
*curr_rule
, struct ip_fw_compat_64
*rule_vers1
)
1561 bzero(rule_vers1
, sizeof(struct ip_fw_compat_64
));
1563 rule_vers1
->version
= IP_FW_VERSION_1
;
1564 rule_vers1
->context
= CAST_DOWN_EXPLICIT(__uint64_t
, curr_rule
->context
);
1565 rule_vers1
->fw_number
= curr_rule
->rulenum
;
1566 rule_vers1
->fw_pcnt
= curr_rule
->pcnt
;
1567 rule_vers1
->fw_bcnt
= curr_rule
->bcnt
;
1568 rule_vers1
->timestamp
= curr_rule
->timestamp
;
1570 /* convert actions */
1571 ipfw_map_from_actions_64(curr_rule
, rule_vers1
);
1573 /* convert commands */
1574 ipfw_map_from_cmds_64(curr_rule
, rule_vers1
);
1576 #if FW2_DEBUG_VERBOSE
1577 ipfw_print_vers1_struct_64(rule_vers1
);
1581 /* first convert to version one then to version zero */
1583 ipfw_version_latest_to_zero(struct ip_fw
*curr_rule
, struct ip_old_fw
*rule_vers0
, int is64user
)
1586 struct ip_fw_compat_64 rule_vers1
;
1587 ipfw_version_latest_to_one_64((struct ip_fw_64
*)curr_rule
, &rule_vers1
);
1588 bzero(rule_vers0
, sizeof(struct ip_old_fw
));
1589 bcopy(&rule_vers1
.fw_uar_compat
, &rule_vers0
->fw_uar
, sizeof(rule_vers1
.fw_uar_compat
));
1590 bcopy(&rule_vers1
.fw_in_if
, &rule_vers0
->fw_in_if
, sizeof(rule_vers1
.fw_in_if
));
1591 bcopy(&rule_vers1
.fw_out_if
, &rule_vers0
->fw_out_if
, sizeof(rule_vers1
.fw_out_if
));
1592 bcopy(&rule_vers1
.fw_un_compat
, &rule_vers0
->fw_un
, sizeof(rule_vers1
.fw_un_compat
));
1593 rule_vers0
->fw_pcnt
= rule_vers1
.fw_pcnt
;
1594 rule_vers0
->fw_bcnt
= rule_vers1
.fw_bcnt
;
1595 rule_vers0
->fw_src
= rule_vers1
.fw_src
;
1596 rule_vers0
->fw_dst
= rule_vers1
.fw_dst
;
1597 rule_vers0
->fw_smsk
= rule_vers1
.fw_smsk
;
1598 rule_vers0
->fw_dmsk
= rule_vers1
.fw_dmsk
;
1599 rule_vers0
->fw_number
= rule_vers1
.fw_number
;
1600 rule_vers0
->fw_flg
= rule_vers1
.fw_flg
;
1601 rule_vers0
->fw_ipopt
= rule_vers1
.fw_ipopt
;
1602 rule_vers0
->fw_ipnopt
= rule_vers1
.fw_ipnopt
;
1603 rule_vers0
->fw_tcpf
= rule_vers1
.fw_tcpf
;
1604 rule_vers0
->fw_tcpnf
= rule_vers1
.fw_tcpnf
;
1605 rule_vers0
->timestamp
= rule_vers1
.timestamp
;
1606 rule_vers0
->fw_prot
= rule_vers1
.fw_prot
;
1607 rule_vers0
->fw_nports
= rule_vers1
.fw_nports
;
1608 rule_vers0
->pipe_ptr
= CAST_DOWN_EXPLICIT(void*, rule_vers1
.pipe_ptr
);
1609 rule_vers0
->next_rule_ptr
= CAST_DOWN_EXPLICIT(void*, rule_vers1
.next_rule_ptr
);
1611 if (rule_vers1
.fw_ipflg
& IP_FW_IF_TCPEST_COMPAT
) {
1612 rule_vers0
->fw_tcpf
|= IP_OLD_FW_TCPF_ESTAB
;
1615 struct ip_fw_compat_32 rule_vers1
;
1616 ipfw_version_latest_to_one_32((struct ip_fw_32
*)curr_rule
, &rule_vers1
);
1617 bzero(rule_vers0
, sizeof(struct ip_old_fw
));
1618 bcopy(&rule_vers1
.fw_uar_compat
, &rule_vers0
->fw_uar
, sizeof(rule_vers1
.fw_uar_compat
));
1619 bcopy(&rule_vers1
.fw_in_if
, &rule_vers0
->fw_in_if
, sizeof(rule_vers1
.fw_in_if
));
1620 bcopy(&rule_vers1
.fw_out_if
, &rule_vers0
->fw_out_if
, sizeof(rule_vers1
.fw_out_if
));
1621 bcopy(&rule_vers1
.fw_un_compat
, &rule_vers0
->fw_un
, sizeof(rule_vers1
.fw_un_compat
));
1622 rule_vers0
->fw_pcnt
= rule_vers1
.fw_pcnt
;
1623 rule_vers0
->fw_bcnt
= rule_vers1
.fw_bcnt
;
1624 rule_vers0
->fw_src
= rule_vers1
.fw_src
;
1625 rule_vers0
->fw_dst
= rule_vers1
.fw_dst
;
1626 rule_vers0
->fw_smsk
= rule_vers1
.fw_smsk
;
1627 rule_vers0
->fw_dmsk
= rule_vers1
.fw_dmsk
;
1628 rule_vers0
->fw_number
= rule_vers1
.fw_number
;
1629 rule_vers0
->fw_flg
= rule_vers1
.fw_flg
;
1630 rule_vers0
->fw_ipopt
= rule_vers1
.fw_ipopt
;
1631 rule_vers0
->fw_ipnopt
= rule_vers1
.fw_ipnopt
;
1632 rule_vers0
->fw_tcpf
= rule_vers1
.fw_tcpf
;
1633 rule_vers0
->fw_tcpnf
= rule_vers1
.fw_tcpnf
;
1634 rule_vers0
->timestamp
= rule_vers1
.timestamp
;
1635 rule_vers0
->fw_prot
= rule_vers1
.fw_prot
;
1636 rule_vers0
->fw_nports
= rule_vers1
.fw_nports
;
1637 rule_vers0
->pipe_ptr
= CAST_DOWN_EXPLICIT(void*, rule_vers1
.pipe_ptr
);
1638 rule_vers0
->next_rule_ptr
= CAST_DOWN_EXPLICIT(void*, rule_vers1
.next_rule_ptr
);
1640 if (rule_vers1
.fw_ipflg
& IP_FW_IF_TCPEST_COMPAT
) {
1641 rule_vers0
->fw_tcpf
|= IP_OLD_FW_TCPF_ESTAB
;
1647 ipfw_convert_from_latest(struct ip_fw
*curr_rule
, void *old_rule
, u_int32_t api_version
, int is64user
)
1649 switch (api_version
) {
1650 case IP_FW_VERSION_0
:
1652 struct ip_old_fw
*rule_vers0
= old_rule
;
1654 ipfw_version_latest_to_zero(curr_rule
, rule_vers0
, is64user
);
1657 case IP_FW_VERSION_1
:
1660 ipfw_version_latest_to_one_64((struct ip_fw_64
*)curr_rule
, (struct ip_fw_compat_64
*)old_rule
);
1662 ipfw_version_latest_to_one_32((struct ip_fw_32
*)curr_rule
, (struct ip_fw_compat_32
*)old_rule
);
1667 case IP_FW_CURRENT_API_VERSION
:
1668 /* ipfw2 for now, don't need to do anything */
1672 /* unknown version */
1678 /* ********************************************
1679 * *********** Convert to Latest **************
1680 * ********************************************/
1684 ipfw_check_vers1_struct_32(struct ip_fw_compat_32
*frwl
)
1686 /* Check for invalid flag bits */
1687 if ((frwl
->fw_flg
& ~IP_FW_F_MASK_COMPAT
) != 0) {
1689 * printf(("%s undefined flag bits set (flags=%x)\n",
1690 * err_prefix, frwl->fw_flg));
1694 if (frwl
->fw_flg
== IP_FW_F_CHECK_S_COMPAT
) {
1698 /* Must apply to incoming or outgoing (or both) */
1699 if (!(frwl
->fw_flg
& (IP_FW_F_IN_COMPAT
| IP_FW_F_OUT_COMPAT
))) {
1701 * printf(("%s neither in nor out\n", err_prefix));
1705 /* Empty interface name is no good */
1706 if (((frwl
->fw_flg
& IP_FW_F_IIFNAME_COMPAT
)
1707 && !*frwl
->fw_in_if
.fu_via_if_compat
.name
)
1708 || ((frwl
->fw_flg
& IP_FW_F_OIFNAME_COMPAT
)
1709 && !*frwl
->fw_out_if
.fu_via_if_compat
.name
)) {
1711 * printf(("%s empty interface name\n", err_prefix));
1715 /* Sanity check interface matching */
1716 if ((frwl
->fw_flg
& IF_FW_F_VIAHACK_COMPAT
) == IF_FW_F_VIAHACK_COMPAT
) {
1717 ; /* allow "via" backwards compatibility */
1718 } else if ((frwl
->fw_flg
& IP_FW_F_IN_COMPAT
)
1719 && (frwl
->fw_flg
& IP_FW_F_OIFACE_COMPAT
)) {
1721 * printf(("%s outgoing interface check on incoming\n",
1726 /* Sanity check port ranges */
1727 if ((frwl
->fw_flg
& IP_FW_F_SRNG_COMPAT
) && IP_FW_GETNSRCP_COMPAT(frwl
) < 2) {
1729 * printf(("%s src range set but n_src_p=%d\n",
1730 * err_prefix, IP_FW_GETNSRCP_COMPAT(frwl)));
1734 if ((frwl
->fw_flg
& IP_FW_F_DRNG_COMPAT
) && IP_FW_GETNDSTP_COMPAT(frwl
) < 2) {
1736 * printf(("%s dst range set but n_dst_p=%d\n",
1737 * err_prefix, IP_FW_GETNDSTP_COMPAT(frwl)));
1741 if (IP_FW_GETNSRCP_COMPAT(frwl
) + IP_FW_GETNDSTP_COMPAT(frwl
) > IP_FW_MAX_PORTS_COMPAT
) {
1743 * printf(("%s too many ports (%d+%d)\n",
1744 * err_prefix, IP_FW_GETNSRCP_COMPAT(frwl), IP_FW_GETNDSTP_COMPAT(frwl)));
1749 * Protocols other than TCP/UDP don't use port range
1751 if ((frwl
->fw_prot
!= IPPROTO_TCP
) &&
1752 (frwl
->fw_prot
!= IPPROTO_UDP
) &&
1753 (IP_FW_GETNSRCP_COMPAT(frwl
) || IP_FW_GETNDSTP_COMPAT(frwl
))) {
1755 * printf(("%s port(s) specified for non TCP/UDP rule\n",
1762 * Rather than modify the entry to make such entries work,
1763 * we reject this rule and require user level utilities
1764 * to enforce whatever policy they deem appropriate.
1766 if ((frwl
->fw_src
.s_addr
& (~frwl
->fw_smsk
.s_addr
)) ||
1767 (frwl
->fw_dst
.s_addr
& (~frwl
->fw_dmsk
.s_addr
))) {
1769 * printf(("%s rule never matches\n", err_prefix));
1774 if ((frwl
->fw_flg
& IP_FW_F_FRAG_COMPAT
) &&
1775 (frwl
->fw_prot
== IPPROTO_UDP
|| frwl
->fw_prot
== IPPROTO_TCP
)) {
1776 if (frwl
->fw_nports
) {
1778 * printf(("%s cannot mix 'frag' and ports\n", err_prefix));
1782 if (frwl
->fw_prot
== IPPROTO_TCP
&&
1783 frwl
->fw_tcpf
!= frwl
->fw_tcpnf
) {
1785 * printf(("%s cannot mix 'frag' and TCP flags\n", err_prefix));
1791 /* Check command specific stuff */
1792 switch (frwl
->fw_flg
& IP_FW_F_COMMAND_COMPAT
) {
1793 case IP_FW_F_REJECT_COMPAT
:
1794 if (frwl
->fw_reject_code_compat
>= 0x100
1795 && !(frwl
->fw_prot
== IPPROTO_TCP
1796 && frwl
->fw_reject_code_compat
== IP_FW_REJECT_RST_COMPAT
)) {
1798 * printf(("%s unknown reject code\n", err_prefix));
1803 case IP_FW_F_DIVERT_COMPAT
: /* Diverting to port zero is invalid */
1804 case IP_FW_F_TEE_COMPAT
:
1805 case IP_FW_F_PIPE_COMPAT
: /* piping through 0 is invalid */
1806 case IP_FW_F_QUEUE_COMPAT
: /* piping through 0 is invalid */
1807 if (frwl
->fw_divert_port_compat
== 0) {
1809 * printf(("%s can't divert to port 0\n", err_prefix));
1814 case IP_FW_F_DENY_COMPAT
:
1815 case IP_FW_F_ACCEPT_COMPAT
:
1816 case IP_FW_F_COUNT_COMPAT
:
1817 case IP_FW_F_SKIPTO_COMPAT
:
1818 case IP_FW_F_FWD_COMPAT
:
1819 case IP_FW_F_UID_COMPAT
:
1823 * printf(("%s invalid command\n", err_prefix));
1832 ipfw_check_vers1_struct_64(struct ip_fw_compat_64
*frwl
)
1834 /* Check for invalid flag bits */
1835 if ((frwl
->fw_flg
& ~IP_FW_F_MASK_COMPAT
) != 0) {
1837 * printf(("%s undefined flag bits set (flags=%x)\n",
1838 * err_prefix, frwl->fw_flg));
1843 if (frwl
->fw_flg
== IP_FW_F_CHECK_S_COMPAT
) {
1847 /* Must apply to incoming or outgoing (or both) */
1848 if (!(frwl
->fw_flg
& (IP_FW_F_IN_COMPAT
| IP_FW_F_OUT_COMPAT
))) {
1850 * printf(("%s neither in nor out\n", err_prefix));
1855 /* Empty interface name is no good */
1856 if (((frwl
->fw_flg
& IP_FW_F_IIFNAME_COMPAT
)
1857 && !*frwl
->fw_in_if
.fu_via_if_compat
.name
)
1858 || ((frwl
->fw_flg
& IP_FW_F_OIFNAME_COMPAT
)
1859 && !*frwl
->fw_out_if
.fu_via_if_compat
.name
)) {
1861 * printf(("%s empty interface name\n", err_prefix));
1866 /* Sanity check interface matching */
1867 if ((frwl
->fw_flg
& IF_FW_F_VIAHACK_COMPAT
) == IF_FW_F_VIAHACK_COMPAT
) {
1868 ; /* allow "via" backwards compatibility */
1869 } else if ((frwl
->fw_flg
& IP_FW_F_IN_COMPAT
)
1870 && (frwl
->fw_flg
& IP_FW_F_OIFACE_COMPAT
)) {
1872 * printf(("%s outgoing interface check on incoming\n",
1878 /* Sanity check port ranges */
1879 if ((frwl
->fw_flg
& IP_FW_F_SRNG_COMPAT
) && IP_FW_GETNSRCP_COMPAT(frwl
) < 2) {
1881 * printf(("%s src range set but n_src_p=%d\n",
1882 * err_prefix, IP_FW_GETNSRCP_COMPAT(frwl)));
1887 if ((frwl
->fw_flg
& IP_FW_F_DRNG_COMPAT
) && IP_FW_GETNDSTP_COMPAT(frwl
) < 2) {
1889 * printf(("%s dst range set but n_dst_p=%d\n",
1890 * err_prefix, IP_FW_GETNDSTP_COMPAT(frwl)));
1895 if (IP_FW_GETNSRCP_COMPAT(frwl
) + IP_FW_GETNDSTP_COMPAT(frwl
) > IP_FW_MAX_PORTS_COMPAT
) {
1897 * printf(("%s too many ports (%d+%d)\n",
1898 * err_prefix, IP_FW_GETNSRCP_COMPAT(frwl), IP_FW_GETNDSTP_COMPAT(frwl)));
1904 * Protocols other than TCP/UDP don't use port range
1906 if ((frwl
->fw_prot
!= IPPROTO_TCP
) &&
1907 (frwl
->fw_prot
!= IPPROTO_UDP
) &&
1908 (IP_FW_GETNSRCP_COMPAT(frwl
) || IP_FW_GETNDSTP_COMPAT(frwl
))) {
1910 * printf(("%s port(s) specified for non TCP/UDP rule\n",
1918 * Rather than modify the entry to make such entries work,
1919 * we reject this rule and require user level utilities
1920 * to enforce whatever policy they deem appropriate.
1922 if ((frwl
->fw_src
.s_addr
& (~frwl
->fw_smsk
.s_addr
)) ||
1923 (frwl
->fw_dst
.s_addr
& (~frwl
->fw_dmsk
.s_addr
))) {
1925 * printf(("%s rule never matches\n", err_prefix));
1931 if ((frwl
->fw_flg
& IP_FW_F_FRAG_COMPAT
) &&
1932 (frwl
->fw_prot
== IPPROTO_UDP
|| frwl
->fw_prot
== IPPROTO_TCP
)) {
1933 if (frwl
->fw_nports
) {
1935 * printf(("%s cannot mix 'frag' and ports\n", err_prefix));
1940 if (frwl
->fw_prot
== IPPROTO_TCP
&&
1941 frwl
->fw_tcpf
!= frwl
->fw_tcpnf
) {
1943 * printf(("%s cannot mix 'frag' and TCP flags\n", err_prefix));
1950 /* Check command specific stuff */
1951 switch (frwl
->fw_flg
& IP_FW_F_COMMAND_COMPAT
) {
1952 case IP_FW_F_REJECT_COMPAT
:
1953 if (frwl
->fw_reject_code_compat
>= 0x100
1954 && !(frwl
->fw_prot
== IPPROTO_TCP
1955 && frwl
->fw_reject_code_compat
== IP_FW_REJECT_RST_COMPAT
)) {
1957 * printf(("%s unknown reject code\n", err_prefix));
1963 case IP_FW_F_DIVERT_COMPAT
: /* Diverting to port zero is invalid */
1964 case IP_FW_F_TEE_COMPAT
:
1965 case IP_FW_F_PIPE_COMPAT
: /* piping through 0 is invalid */
1966 case IP_FW_F_QUEUE_COMPAT
: /* piping through 0 is invalid */
1967 if (frwl
->fw_divert_port_compat
== 0) {
1969 * printf(("%s can't divert to port 0\n", err_prefix));
1975 case IP_FW_F_DENY_COMPAT
:
1976 case IP_FW_F_ACCEPT_COMPAT
:
1977 case IP_FW_F_COUNT_COMPAT
:
1978 case IP_FW_F_SKIPTO_COMPAT
:
1979 case IP_FW_F_FWD_COMPAT
:
1980 case IP_FW_F_UID_COMPAT
:
1984 * printf(("%s invalid command\n", err_prefix));
1994 ipfw_convert_to_cmds_32(struct ip_fw
*curr_rule
, struct ip_fw_compat_32
*compat_rule
)
1997 uint32_t actbuf
[255], cmdbuf
[255];
1998 ipfw_insn
*action
, *cmd
, *src
, *dst
;
1999 ipfw_insn
*have_state
= NULL
; /* track check-state or keep-state */
2001 if (!compat_rule
|| !curr_rule
) {
2005 /* preemptively check the old ip_fw rule to
2006 * make sure it's valid before starting to copy stuff
2008 if (ipfw_check_vers1_struct_32(compat_rule
)) {
2013 bzero(actbuf
, sizeof(actbuf
)); /* actions go here */
2014 bzero(cmdbuf
, sizeof(cmdbuf
));
2016 /* fill in action */
2017 action
= (ipfw_insn
*)actbuf
;
2019 u_int flag
= compat_rule
->fw_flg
;
2021 action
->len
= 1; /* default */
2023 if (flag
& IP_FW_F_CHECK_S_COMPAT
) {
2024 have_state
= action
;
2025 action
->opcode
= O_CHECK_STATE
;
2027 switch (flag
& IP_FW_F_COMMAND_COMPAT
) {
2028 case IP_FW_F_ACCEPT_COMPAT
:
2029 action
->opcode
= O_ACCEPT
;
2031 case IP_FW_F_COUNT_COMPAT
:
2032 action
->opcode
= O_COUNT
;
2034 case IP_FW_F_PIPE_COMPAT
:
2035 action
->opcode
= O_PIPE
;
2036 action
->len
= F_INSN_SIZE(ipfw_insn_pipe
);
2037 action
->arg1
= compat_rule
->fw_divert_port_compat
;
2039 case IP_FW_F_QUEUE_COMPAT
:
2040 action
->opcode
= O_QUEUE
;
2041 action
->len
= F_INSN_SIZE(ipfw_insn_pipe
);
2042 action
->arg1
= compat_rule
->fw_divert_port_compat
;
2044 case IP_FW_F_SKIPTO_COMPAT
:
2045 action
->opcode
= O_SKIPTO
;
2046 action
->arg1
= compat_rule
->fw_skipto_rule_compat
;
2048 case IP_FW_F_DIVERT_COMPAT
:
2049 action
->opcode
= O_DIVERT
;
2050 action
->arg1
= compat_rule
->fw_divert_port_compat
;
2052 case IP_FW_F_TEE_COMPAT
:
2053 action
->opcode
= O_TEE
;
2054 action
->arg1
= compat_rule
->fw_divert_port_compat
;
2056 case IP_FW_F_FWD_COMPAT
:
2058 ipfw_insn_sa
*p
= (ipfw_insn_sa
*)action
;
2060 action
->opcode
= O_FORWARD_IP
;
2061 action
->len
= F_INSN_SIZE(ipfw_insn_sa
);
2063 p
->sa
.sin_len
= compat_rule
->fw_fwd_ip_compat
.sin_len
;
2064 p
->sa
.sin_family
= compat_rule
->fw_fwd_ip_compat
.sin_family
;
2065 p
->sa
.sin_port
= compat_rule
->fw_fwd_ip_compat
.sin_port
;
2066 p
->sa
.sin_addr
= compat_rule
->fw_fwd_ip_compat
.sin_addr
;
2070 case IP_FW_F_DENY_COMPAT
:
2071 action
->opcode
= O_DENY
;
2074 case IP_FW_F_REJECT_COMPAT
:
2075 action
->opcode
= O_REJECT
;
2076 action
->arg1
= compat_rule
->fw_reject_code_compat
;
2079 action
->opcode
= O_NOP
;
2084 /* action is mandatory */
2085 if (action
->opcode
== O_NOP
) {
2089 action
= next_cmd(action
);
2092 cmd
= (ipfw_insn
*)cmdbuf
;
2094 /* this is O_CHECK_STATE, we're done */
2100 ipfw_insn
*prev
= NULL
;
2101 u_int flag
= compat_rule
->fw_flg
;
2104 if (flag
& IP_FW_F_PRN_COMPAT
) {
2105 ipfw_insn_log
*c
= (ipfw_insn_log
*)cmd
;
2107 cmd
->opcode
= O_LOG
;
2108 cmd
->len
|= F_INSN_SIZE(ipfw_insn_log
);
2109 c
->max_log
= compat_rule
->fw_logamount
;
2112 cmd
= next_cmd(cmd
);
2116 if (compat_rule
->fw_prot
!= 0) {
2117 fill_cmd(cmd
, O_PROTO
, compat_rule
->fw_prot
);
2119 cmd
= next_cmd(cmd
);
2123 if (flag
& IP_FW_F_SME_COMPAT
) {
2124 cmd
->opcode
= O_IP_SRC_ME
;
2125 cmd
->len
|= F_INSN_SIZE(ipfw_insn
);
2126 if (flag
& IP_FW_F_INVSRC_COMPAT
) {
2127 cmd
->len
^= F_NOT
; /* toggle F_NOT */
2131 cmd
= next_cmd(cmd
);
2133 if (compat_rule
->fw_smsk
.s_addr
!= 0) {
2135 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
2137 ip
->addr
= compat_rule
->fw_src
;
2138 ip
->mask
= compat_rule
->fw_smsk
;
2139 cmd
->opcode
= O_IP_SRC_MASK
;
2140 cmd
->len
|= F_INSN_SIZE(ipfw_insn_ip
); /* double check this */
2143 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
;/* alias for cmd */
2145 if (compat_rule
->fw_src
.s_addr
== 0) {
2147 cmd32
->o
.len
&= ~F_LEN_MASK
; /* zero len */
2149 cmd32
->d
[0] = compat_rule
->fw_src
.s_addr
;
2150 cmd32
->o
.opcode
= O_IP_SRC
;
2151 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
2155 if (flag
& IP_FW_F_INVSRC_COMPAT
) {
2156 cmd
->len
^= F_NOT
; /* toggle F_NOT */
2159 if (F_LEN(cmd
) != 0) { /* !any */
2161 cmd
= next_cmd(cmd
);
2167 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
2168 uint16_t *p
= ports
->ports
;
2170 nports
= IP_FW_GETNSRCP_COMPAT(compat_rule
),
2173 cmd
->opcode
= O_IP_SRCPORT
;
2174 for (i
= 0; i
< nports
; i
++) {
2175 if (((flag
& IP_FW_F_SRNG_COMPAT
) ||
2176 (flag
& IP_FW_F_SMSK_COMPAT
)) && !have_range
) {
2177 p
[0] = compat_rule
->fw_uar_compat
.fw_pts
[i
++];
2178 p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
2181 p
[0] = p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
2188 ports
->o
.len
|= j
+ 1; /* leave F_NOT and F_OR untouched */
2192 cmd
= next_cmd(cmd
);
2196 if (flag
& IP_FW_F_DME_COMPAT
) {
2197 cmd
->opcode
= O_IP_DST_ME
;
2198 cmd
->len
|= F_INSN_SIZE(ipfw_insn
);
2199 if (flag
& IP_FW_F_INVDST_COMPAT
) {
2200 cmd
->len
^= F_NOT
; /* toggle F_NOT */
2204 cmd
= next_cmd(cmd
);
2206 if (compat_rule
->fw_dmsk
.s_addr
!= 0) {
2208 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
2210 ip
->addr
= compat_rule
->fw_dst
;
2211 ip
->mask
= compat_rule
->fw_dmsk
;
2212 cmd
->opcode
= O_IP_DST_MASK
;
2213 cmd
->len
|= F_INSN_SIZE(ipfw_insn_ip
); /* double check this */
2216 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
;/* alias for cmd */
2218 if (compat_rule
->fw_dst
.s_addr
== 0) {
2220 cmd32
->o
.len
&= ~F_LEN_MASK
; /* zero len */
2222 cmd32
->d
[0] = compat_rule
->fw_dst
.s_addr
;
2223 cmd32
->o
.opcode
= O_IP_DST
;
2224 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
2228 if (flag
& IP_FW_F_INVDST_COMPAT
) {
2229 cmd
->len
^= F_NOT
; /* toggle F_NOT */
2232 if (F_LEN(cmd
) != 0) { /* !any */
2234 cmd
= next_cmd(cmd
);
2240 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
2241 uint16_t *p
= ports
->ports
;
2242 int i
= IP_FW_GETNSRCP_COMPAT(compat_rule
),
2244 nports
= (IP_FW_GETNDSTP_COMPAT(compat_rule
) + i
),
2247 cmd
->opcode
= O_IP_DSTPORT
;
2248 for (; i
< nports
; i
++, p
+= 2) {
2249 if (((flag
& IP_FW_F_DRNG_COMPAT
) ||
2250 (flag
& IP_FW_F_DMSK_COMPAT
)) && !have_range
) {
2252 p
[0] = compat_rule
->fw_uar_compat
.fw_pts
[i
++];
2253 p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
2256 p
[0] = p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
2262 ports
->o
.len
|= j
+ 1; /* leave F_NOT and F_OR untouched */
2266 cmd
= next_cmd(cmd
);
2269 if (flag
& IP_FW_F_UID_COMPAT
) {
2270 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
;/* alias for cmd */
2272 cmd32
->o
.opcode
= O_UID
;
2273 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
2274 cmd32
->d
[0] = compat_rule
->fw_uid
;
2277 cmd
= next_cmd(cmd
);
2280 if (flag
& IP_FW_F_KEEP_S_COMPAT
) {
2282 fill_cmd(cmd
, O_KEEP_STATE
, 0);
2285 cmd
= next_cmd(cmd
);
2287 if (flag
& IP_FW_BRIDGED_COMPAT
) {
2288 fill_cmd(cmd
, O_LAYER2
, 0);
2291 cmd
= next_cmd(cmd
);
2294 if ((flag
& IF_FW_F_VIAHACK_COMPAT
) == IF_FW_F_VIAHACK_COMPAT
) {
2296 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
2297 union ip_fw_if_compat ifu
= compat_rule
->fw_in_if
;
2299 cmd
->opcode
= O_VIA
;
2300 ifcmd
->o
.len
|= F_INSN_SIZE(ipfw_insn_if
);
2302 if (ifu
.fu_via_ip
.s_addr
== 0) {
2304 ifcmd
->name
[0] = '\0';
2306 } else if (compat_rule
->fw_flg
& IP_FW_F_IIFNAME_COMPAT
) {
2308 strncpy(ifcmd
->name
, ifu
.fu_via_if_compat
.name
, sizeof(ifcmd
->name
));
2309 ifcmd
->p
.unit
= ifu
.fu_via_if_compat
.unit
;
2312 ifcmd
->p
.ip
= ifu
.fu_via_ip
;
2316 cmd
= next_cmd(cmd
);
2318 if (flag
& IP_FW_F_IN_COMPAT
) {
2319 fill_cmd(cmd
, O_IN
, 0);
2322 cmd
= next_cmd(cmd
);
2324 if (flag
& IP_FW_F_OUT_COMPAT
) {
2325 /* if the previous command was O_IN, and this
2326 * is being set as well, it's equivalent to not
2327 * having either command, so let's back up prev
2328 * to the cmd before it and move cmd to prev.
2330 if (prev
->opcode
== O_IN
) {
2332 bzero(cmd
, sizeof(*cmd
));
2334 cmd
->len
^= F_NOT
; /* toggle F_NOT */
2335 fill_cmd(cmd
, O_IN
, 0);
2338 cmd
= next_cmd(cmd
);
2341 if (flag
& IP_FW_F_OIFACE_COMPAT
) {
2343 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
2344 union ip_fw_if_compat ifu
= compat_rule
->fw_out_if
;
2346 cmd
->opcode
= O_XMIT
;
2347 ifcmd
->o
.len
|= F_INSN_SIZE(ipfw_insn_if
);
2349 if (ifu
.fu_via_ip
.s_addr
== 0) {
2351 ifcmd
->name
[0] = '\0';
2353 } else if (flag
& IP_FW_F_OIFNAME_COMPAT
) {
2355 strncpy(ifcmd
->name
, ifu
.fu_via_if_compat
.name
, sizeof(ifcmd
->name
));
2356 ifcmd
->p
.unit
= ifu
.fu_via_if_compat
.unit
;
2359 ifcmd
->p
.ip
= ifu
.fu_via_ip
;
2363 cmd
= next_cmd(cmd
);
2364 } else if (flag
& IP_FW_F_IIFACE_COMPAT
) {
2366 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
2367 union ip_fw_if_compat ifu
= compat_rule
->fw_in_if
;
2369 cmd
->opcode
= O_RECV
;
2370 ifcmd
->o
.len
|= F_INSN_SIZE(ipfw_insn_if
);
2372 if (ifu
.fu_via_ip
.s_addr
== 0) {
2374 ifcmd
->name
[0] = '\0';
2376 } else if (flag
& IP_FW_F_IIFNAME_COMPAT
) {
2378 strncpy(ifcmd
->name
, ifu
.fu_via_if_compat
.name
, sizeof(ifcmd
->name
));
2379 ifcmd
->p
.unit
= ifu
.fu_via_if_compat
.unit
;
2382 ifcmd
->p
.ip
= ifu
.fu_via_ip
;
2386 cmd
= next_cmd(cmd
);
2390 if (flag
& IP_FW_F_FRAG_COMPAT
) {
2391 fill_cmd(cmd
, O_FRAG
, 0);
2394 cmd
= next_cmd(cmd
);
2398 if (compat_rule
->fw_ipopt
!= 0 || compat_rule
->fw_ipnopt
!= 0) {
2399 fill_cmd(cmd
, O_IPOPT
, (compat_rule
->fw_ipopt
& 0xff) |
2400 (compat_rule
->fw_ipnopt
& 0xff) << 8);
2403 cmd
= next_cmd(cmd
);
2406 if (compat_rule
->fw_prot
== IPPROTO_TCP
) {
2407 if (compat_rule
->fw_ipflg
& IP_FW_IF_TCPEST_COMPAT
) {
2408 fill_cmd(cmd
, O_ESTAB
, 0);
2411 cmd
= next_cmd(cmd
);
2414 /* TCP options and flags */
2415 if (compat_rule
->fw_tcpf
!= 0 || compat_rule
->fw_tcpnf
!= 0) {
2416 if ((compat_rule
->fw_tcpf
& IP_FW_TCPF_SYN_COMPAT
) &&
2417 compat_rule
->fw_tcpnf
& IP_FW_TCPF_ACK_COMPAT
) {
2418 fill_cmd(cmd
, O_TCPFLAGS
, (TH_SYN
) | ((TH_ACK
) & 0xff) << 8);
2421 cmd
= next_cmd(cmd
);
2423 fill_cmd(cmd
, O_TCPFLAGS
, (compat_rule
->fw_tcpf
& 0xff) |
2424 (compat_rule
->fw_tcpnf
& 0xff) << 8);
2427 cmd
= next_cmd(cmd
);
2430 if (compat_rule
->fw_tcpopt
!= 0 || compat_rule
->fw_tcpnopt
!= 0) {
2431 fill_cmd(cmd
, O_TCPOPTS
, (compat_rule
->fw_tcpopt
& 0xff) |
2432 (compat_rule
->fw_tcpnopt
& 0xff) << 8);
2435 cmd
= next_cmd(cmd
);
2440 /* XXX: check this */
2441 if (flag
& IP_FW_F_ICMPBIT_COMPAT
) {
2443 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
;/* alias for cmd */
2445 cmd32
->o
.opcode
= O_ICMPTYPE
;
2446 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
2448 for (i
= 0; i
< IP_FW_ICMPTYPES_DIM_COMPAT
; i
++) {
2449 cmd32
->d
[0] |= compat_rule
->fw_uar_compat
.fw_icmptypes
[i
];
2453 cmd
= next_cmd(cmd
);
2455 } /* end commands */
2458 /* finally, copy everything into the current
2459 * rule buffer in the right order.
2461 dst
= curr_rule
->cmd
;
2463 /* first, do match probability */
2464 if (compat_rule
->fw_flg
& IP_FW_F_RND_MATCH_COMPAT
) {
2465 dst
->opcode
= O_PROB
;
2467 *((int32_t *)(dst
+ 1)) = compat_rule
->pipe_ptr
;
2471 /* generate O_PROBE_STATE if necessary */
2472 if (have_state
&& have_state
->opcode
!= O_CHECK_STATE
) {
2473 fill_cmd(dst
, O_PROBE_STATE
, 0);
2474 dst
= next_cmd(dst
);
2478 * copy all commands but O_LOG, O_KEEP_STATE
2480 for (src
= (ipfw_insn
*)cmdbuf
; src
!= cmd
; src
+= k
) {
2483 switch (src
->opcode
) {
2488 bcopy(src
, dst
, k
* sizeof(uint32_t));
2494 * put back the have_state command as last opcode
2496 if (have_state
&& have_state
->opcode
!= O_CHECK_STATE
) {
2497 k
= F_LEN(have_state
);
2498 bcopy(have_state
, dst
, k
* sizeof(uint32_t));
2503 * start action section
2505 curr_rule
->act_ofs
= dst
- curr_rule
->cmd
;
2508 * put back O_LOG if necessary
2510 src
= (ipfw_insn
*)cmdbuf
;
2511 if (src
->opcode
== O_LOG
) {
2513 bcopy(src
, dst
, k
* sizeof(uint32_t));
2518 * copy all other actions
2520 for (src
= (ipfw_insn
*)actbuf
; src
!= action
; src
+= k
) {
2522 bcopy(src
, dst
, k
* sizeof(uint32_t));
2526 curr_rule
->cmd_len
= (uint32_t *)dst
- (uint32_t *)(curr_rule
->cmd
);
2532 ipfw_convert_to_cmds_64(struct ip_fw
*curr_rule
, struct ip_fw_compat_64
*compat_rule
)
2535 uint32_t actbuf
[255], cmdbuf
[255];
2536 ipfw_insn
*action
, *cmd
, *src
, *dst
;
2537 ipfw_insn
*have_state
= NULL
; /* track check-state or keep-state */
2539 if (!compat_rule
|| !curr_rule
) {
2543 /* preemptively check the old ip_fw rule to
2544 * make sure it's valid before starting to copy stuff
2546 if (ipfw_check_vers1_struct_64(compat_rule
)) {
2551 bzero(actbuf
, sizeof(actbuf
)); /* actions go here */
2552 bzero(cmdbuf
, sizeof(cmdbuf
));
2553 /* fill in action */
2554 action
= (ipfw_insn
*)actbuf
;
2556 u_int flag
= compat_rule
->fw_flg
;
2558 action
->len
= 1; /* default */
2560 if (flag
& IP_FW_F_CHECK_S_COMPAT
) {
2561 have_state
= action
;
2562 action
->opcode
= O_CHECK_STATE
;
2564 switch (flag
& IP_FW_F_COMMAND_COMPAT
) {
2565 case IP_FW_F_ACCEPT_COMPAT
:
2566 action
->opcode
= O_ACCEPT
;
2568 case IP_FW_F_COUNT_COMPAT
:
2569 action
->opcode
= O_COUNT
;
2571 case IP_FW_F_PIPE_COMPAT
:
2572 action
->opcode
= O_PIPE
;
2573 action
->len
= F_INSN_SIZE(ipfw_insn_pipe
);
2574 action
->arg1
= compat_rule
->fw_divert_port_compat
;
2576 case IP_FW_F_QUEUE_COMPAT
:
2577 action
->opcode
= O_QUEUE
;
2578 action
->len
= F_INSN_SIZE(ipfw_insn_pipe
);
2579 action
->arg1
= compat_rule
->fw_divert_port_compat
;
2581 case IP_FW_F_SKIPTO_COMPAT
:
2582 action
->opcode
= O_SKIPTO
;
2583 action
->arg1
= compat_rule
->fw_skipto_rule_compat
;
2585 case IP_FW_F_DIVERT_COMPAT
:
2586 action
->opcode
= O_DIVERT
;
2587 action
->arg1
= compat_rule
->fw_divert_port_compat
;
2589 case IP_FW_F_TEE_COMPAT
:
2590 action
->opcode
= O_TEE
;
2591 action
->arg1
= compat_rule
->fw_divert_port_compat
;
2593 case IP_FW_F_FWD_COMPAT
:
2595 ipfw_insn_sa
*p
= (ipfw_insn_sa
*)action
;
2597 action
->opcode
= O_FORWARD_IP
;
2598 action
->len
= F_INSN_SIZE(ipfw_insn_sa
);
2600 p
->sa
.sin_len
= compat_rule
->fw_fwd_ip_compat
.sin_len
;
2601 p
->sa
.sin_family
= compat_rule
->fw_fwd_ip_compat
.sin_family
;
2602 p
->sa
.sin_port
= compat_rule
->fw_fwd_ip_compat
.sin_port
;
2603 p
->sa
.sin_addr
= compat_rule
->fw_fwd_ip_compat
.sin_addr
;
2607 case IP_FW_F_DENY_COMPAT
:
2608 action
->opcode
= O_DENY
;
2611 case IP_FW_F_REJECT_COMPAT
:
2612 action
->opcode
= O_REJECT
;
2613 action
->arg1
= compat_rule
->fw_reject_code_compat
;
2616 action
->opcode
= O_NOP
;
2621 /* action is mandatory */
2622 if (action
->opcode
== O_NOP
) {
2626 action
= next_cmd(action
);
2629 cmd
= (ipfw_insn
*)cmdbuf
;
2631 /* this is O_CHECK_STATE, we're done */
2637 ipfw_insn
*prev
= NULL
;
2638 u_int flag
= compat_rule
->fw_flg
;
2641 if (flag
& IP_FW_F_PRN_COMPAT
) {
2642 ipfw_insn_log
*c
= (ipfw_insn_log
*)cmd
;
2644 cmd
->opcode
= O_LOG
;
2645 cmd
->len
|= F_INSN_SIZE(ipfw_insn_log
);
2646 c
->max_log
= compat_rule
->fw_logamount
;
2649 cmd
= next_cmd(cmd
);
2653 if (compat_rule
->fw_prot
!= 0) {
2654 fill_cmd(cmd
, O_PROTO
, compat_rule
->fw_prot
);
2656 cmd
= next_cmd(cmd
);
2660 if (flag
& IP_FW_F_SME_COMPAT
) {
2661 cmd
->opcode
= O_IP_SRC_ME
;
2662 cmd
->len
|= F_INSN_SIZE(ipfw_insn
);
2663 if (flag
& IP_FW_F_INVSRC_COMPAT
) {
2664 cmd
->len
^= F_NOT
; /* toggle F_NOT */
2668 cmd
= next_cmd(cmd
);
2670 if (compat_rule
->fw_smsk
.s_addr
!= 0) {
2672 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
2674 ip
->addr
= compat_rule
->fw_src
;
2675 ip
->mask
= compat_rule
->fw_smsk
;
2676 cmd
->opcode
= O_IP_SRC_MASK
;
2677 cmd
->len
|= F_INSN_SIZE(ipfw_insn_ip
); /* double check this */
2680 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
;/* alias for cmd */
2682 if (compat_rule
->fw_src
.s_addr
== 0) {
2684 cmd32
->o
.len
&= ~F_LEN_MASK
; /* zero len */
2686 cmd32
->d
[0] = compat_rule
->fw_src
.s_addr
;
2687 cmd32
->o
.opcode
= O_IP_SRC
;
2688 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
2692 if (flag
& IP_FW_F_INVSRC_COMPAT
) {
2693 cmd
->len
^= F_NOT
; /* toggle F_NOT */
2696 if (F_LEN(cmd
) != 0) { /* !any */
2698 cmd
= next_cmd(cmd
);
2704 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
2705 uint16_t *p
= ports
->ports
;
2707 nports
= IP_FW_GETNSRCP_COMPAT(compat_rule
),
2710 cmd
->opcode
= O_IP_SRCPORT
;
2711 for (i
= 0; i
< nports
; i
++) {
2712 if (((flag
& IP_FW_F_SRNG_COMPAT
) ||
2713 (flag
& IP_FW_F_SMSK_COMPAT
)) && !have_range
) {
2714 p
[0] = compat_rule
->fw_uar_compat
.fw_pts
[i
++];
2715 p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
2718 p
[0] = p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
2725 ports
->o
.len
|= j
+ 1; /* leave F_NOT and F_OR untouched */
2729 cmd
= next_cmd(cmd
);
2733 if (flag
& IP_FW_F_DME_COMPAT
) {
2734 cmd
->opcode
= O_IP_DST_ME
;
2735 cmd
->len
|= F_INSN_SIZE(ipfw_insn
);
2736 if (flag
& IP_FW_F_INVDST_COMPAT
) {
2737 cmd
->len
^= F_NOT
; /* toggle F_NOT */
2741 cmd
= next_cmd(cmd
);
2743 if (compat_rule
->fw_dmsk
.s_addr
!= 0) {
2745 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
2747 ip
->addr
= compat_rule
->fw_dst
;
2748 ip
->mask
= compat_rule
->fw_dmsk
;
2749 cmd
->opcode
= O_IP_DST_MASK
;
2750 cmd
->len
|= F_INSN_SIZE(ipfw_insn_ip
); /* double check this */
2753 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
;/* alias for cmd */
2755 if (compat_rule
->fw_dst
.s_addr
== 0) {
2757 cmd32
->o
.len
&= ~F_LEN_MASK
; /* zero len */
2759 cmd32
->d
[0] = compat_rule
->fw_dst
.s_addr
;
2760 cmd32
->o
.opcode
= O_IP_DST
;
2761 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
2765 if (flag
& IP_FW_F_INVDST_COMPAT
) {
2766 cmd
->len
^= F_NOT
; /* toggle F_NOT */
2769 if (F_LEN(cmd
) != 0) { /* !any */
2771 cmd
= next_cmd(cmd
);
2777 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
2778 uint16_t *p
= ports
->ports
;
2779 int i
= IP_FW_GETNSRCP_COMPAT(compat_rule
),
2781 nports
= (IP_FW_GETNDSTP_COMPAT(compat_rule
) + i
),
2784 cmd
->opcode
= O_IP_DSTPORT
;
2785 for (; i
< nports
; i
++, p
+= 2) {
2786 if (((flag
& IP_FW_F_DRNG_COMPAT
) ||
2787 (flag
& IP_FW_F_DMSK_COMPAT
)) && !have_range
) {
2789 p
[0] = compat_rule
->fw_uar_compat
.fw_pts
[i
++];
2790 p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
2793 p
[0] = p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
2799 ports
->o
.len
|= j
+ 1; /* leave F_NOT and F_OR untouched */
2803 cmd
= next_cmd(cmd
);
2806 if (flag
& IP_FW_F_UID_COMPAT
) {
2807 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
;/* alias for cmd */
2809 cmd32
->o
.opcode
= O_UID
;
2810 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
2811 cmd32
->d
[0] = compat_rule
->fw_uid
;
2814 cmd
= next_cmd(cmd
);
2817 if (flag
& IP_FW_F_KEEP_S_COMPAT
) {
2819 fill_cmd(cmd
, O_KEEP_STATE
, 0);
2822 cmd
= next_cmd(cmd
);
2824 if (flag
& IP_FW_BRIDGED_COMPAT
) {
2825 fill_cmd(cmd
, O_LAYER2
, 0);
2828 cmd
= next_cmd(cmd
);
2831 if ((flag
& IF_FW_F_VIAHACK_COMPAT
) == IF_FW_F_VIAHACK_COMPAT
) {
2833 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
2834 union ip_fw_if_compat ifu
= compat_rule
->fw_in_if
;
2836 cmd
->opcode
= O_VIA
;
2837 ifcmd
->o
.len
|= F_INSN_SIZE(ipfw_insn_if
);
2839 if (ifu
.fu_via_ip
.s_addr
== 0) {
2841 ifcmd
->name
[0] = '\0';
2843 } else if (compat_rule
->fw_flg
& IP_FW_F_IIFNAME_COMPAT
) {
2845 strncpy(ifcmd
->name
, ifu
.fu_via_if_compat
.name
, sizeof(ifcmd
->name
));
2846 ifcmd
->p
.unit
= ifu
.fu_via_if_compat
.unit
;
2849 ifcmd
->p
.ip
= ifu
.fu_via_ip
;
2853 cmd
= next_cmd(cmd
);
2855 if (flag
& IP_FW_F_IN_COMPAT
) {
2856 fill_cmd(cmd
, O_IN
, 0);
2859 cmd
= next_cmd(cmd
);
2861 if (flag
& IP_FW_F_OUT_COMPAT
) {
2862 /* if the previous command was O_IN, and this
2863 * is being set as well, it's equivalent to not
2864 * having either command, so let's back up prev
2865 * to the cmd before it and move cmd to prev.
2867 if (prev
->opcode
== O_IN
) {
2869 bzero(cmd
, sizeof(*cmd
));
2871 cmd
->len
^= F_NOT
; /* toggle F_NOT */
2872 fill_cmd(cmd
, O_IN
, 0);
2875 cmd
= next_cmd(cmd
);
2878 if (flag
& IP_FW_F_OIFACE_COMPAT
) {
2880 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
2881 union ip_fw_if_compat ifu
= compat_rule
->fw_out_if
;
2883 cmd
->opcode
= O_XMIT
;
2884 ifcmd
->o
.len
|= F_INSN_SIZE(ipfw_insn_if
);
2886 if (ifu
.fu_via_ip
.s_addr
== 0) {
2888 ifcmd
->name
[0] = '\0';
2890 } else if (flag
& IP_FW_F_OIFNAME_COMPAT
) {
2892 strncpy(ifcmd
->name
, ifu
.fu_via_if_compat
.name
, sizeof(ifcmd
->name
));
2893 ifcmd
->p
.unit
= ifu
.fu_via_if_compat
.unit
;
2896 ifcmd
->p
.ip
= ifu
.fu_via_ip
;
2900 cmd
= next_cmd(cmd
);
2901 } else if (flag
& IP_FW_F_IIFACE_COMPAT
) {
2903 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
2904 union ip_fw_if_compat ifu
= compat_rule
->fw_in_if
;
2906 cmd
->opcode
= O_RECV
;
2907 ifcmd
->o
.len
|= F_INSN_SIZE(ipfw_insn_if
);
2909 if (ifu
.fu_via_ip
.s_addr
== 0) {
2911 ifcmd
->name
[0] = '\0';
2913 } else if (flag
& IP_FW_F_IIFNAME_COMPAT
) {
2915 strncpy(ifcmd
->name
, ifu
.fu_via_if_compat
.name
, sizeof(ifcmd
->name
));
2916 ifcmd
->p
.unit
= ifu
.fu_via_if_compat
.unit
;
2919 ifcmd
->p
.ip
= ifu
.fu_via_ip
;
2923 cmd
= next_cmd(cmd
);
2927 if (flag
& IP_FW_F_FRAG_COMPAT
) {
2928 fill_cmd(cmd
, O_FRAG
, 0);
2931 cmd
= next_cmd(cmd
);
2935 if (compat_rule
->fw_ipopt
!= 0 || compat_rule
->fw_ipnopt
!= 0) {
2936 fill_cmd(cmd
, O_IPOPT
, (compat_rule
->fw_ipopt
& 0xff) |
2937 (compat_rule
->fw_ipnopt
& 0xff) << 8);
2940 cmd
= next_cmd(cmd
);
2943 if (compat_rule
->fw_prot
== IPPROTO_TCP
) {
2944 if (compat_rule
->fw_ipflg
& IP_FW_IF_TCPEST_COMPAT
) {
2945 fill_cmd(cmd
, O_ESTAB
, 0);
2948 cmd
= next_cmd(cmd
);
2951 /* TCP options and flags */
2952 if (compat_rule
->fw_tcpf
!= 0 || compat_rule
->fw_tcpnf
!= 0) {
2953 if ((compat_rule
->fw_tcpf
& IP_FW_TCPF_SYN_COMPAT
) &&
2954 compat_rule
->fw_tcpnf
& IP_FW_TCPF_ACK_COMPAT
) {
2955 fill_cmd(cmd
, O_TCPFLAGS
, (TH_SYN
) | ((TH_ACK
) & 0xff) << 8);
2958 cmd
= next_cmd(cmd
);
2960 fill_cmd(cmd
, O_TCPFLAGS
, (compat_rule
->fw_tcpf
& 0xff) |
2961 (compat_rule
->fw_tcpnf
& 0xff) << 8);
2964 cmd
= next_cmd(cmd
);
2967 if (compat_rule
->fw_tcpopt
!= 0 || compat_rule
->fw_tcpnopt
!= 0) {
2968 fill_cmd(cmd
, O_TCPOPTS
, (compat_rule
->fw_tcpopt
& 0xff) |
2969 (compat_rule
->fw_tcpnopt
& 0xff) << 8);
2972 cmd
= next_cmd(cmd
);
2977 /* XXX: check this */
2978 if (flag
& IP_FW_F_ICMPBIT_COMPAT
) {
2980 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
;/* alias for cmd */
2981 cmd32
->o
.opcode
= O_ICMPTYPE
;
2982 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
2984 for (i
= 0; i
< IP_FW_ICMPTYPES_DIM_COMPAT
; i
++) {
2985 cmd32
->d
[0] |= compat_rule
->fw_uar_compat
.fw_icmptypes
[i
];
2989 cmd
= next_cmd(cmd
);
2991 } /* end commands */
2993 /* finally, copy everything into the current
2994 * rule buffer in the right order.
2996 dst
= curr_rule
->cmd
;
2998 /* first, do match probability */
2999 if (compat_rule
->fw_flg
& IP_FW_F_RND_MATCH_COMPAT
) {
3000 dst
->opcode
= O_PROB
;
3002 *((int32_t *)(dst
+ 1)) = compat_rule
->pipe_ptr
;
3006 /* generate O_PROBE_STATE if necessary */
3007 if (have_state
&& have_state
->opcode
!= O_CHECK_STATE
) {
3008 fill_cmd(dst
, O_PROBE_STATE
, 0);
3009 dst
= next_cmd(dst
);
3013 * copy all commands but O_LOG, O_KEEP_STATE
3015 for (src
= (ipfw_insn
*)cmdbuf
; src
!= cmd
; src
+= k
) {
3017 switch (src
->opcode
) {
3022 bcopy(src
, dst
, k
* sizeof(uint32_t));
3028 * put back the have_state command as last opcode
3030 if (have_state
&& have_state
->opcode
!= O_CHECK_STATE
) {
3031 k
= F_LEN(have_state
);
3032 bcopy(have_state
, dst
, k
* sizeof(uint32_t));
3037 * start action section
3039 curr_rule
->act_ofs
= dst
- curr_rule
->cmd
;
3042 * put back O_LOG if necessary
3044 src
= (ipfw_insn
*)cmdbuf
;
3045 if (src
->opcode
== O_LOG
) {
3047 bcopy(src
, dst
, k
* sizeof(uint32_t));
3052 * copy all other actions
3054 for (src
= (ipfw_insn
*)actbuf
; src
!= action
; src
+= k
) {
3056 bcopy(src
, dst
, k
* sizeof(uint32_t));
3060 curr_rule
->cmd_len
= (uint32_t *)dst
- (uint32_t *)(curr_rule
->cmd
);
3065 ipfw_version_one_to_version_two_32(struct sockopt
*sopt
, struct ip_fw
*curr_rule
,
3066 struct ip_fw_compat_32
*rule_vers1
)
3069 struct ip_fw_compat_32
*rule_ptr
;
3070 struct ip_fw_compat_32 rule
;
3073 rule_ptr
= rule_vers1
;
3076 /* do some basic size checking here, more extensive checking later */
3077 if (!sopt
->sopt_val
|| sopt
->sopt_valsize
< sizeof(struct ip_fw_compat_32
)) {
3081 if ((err
= sooptcopyin(sopt
, &rule
, sizeof(struct ip_fw_compat_32
),
3082 sizeof(struct ip_fw_compat_32
)))) {
3089 /* deal with commands */
3090 ipfw_convert_to_cmds_32(curr_rule
, rule_ptr
);
3092 curr_rule
->version
= IP_FW_CURRENT_API_VERSION
;
3093 curr_rule
->context
= CAST_DOWN_EXPLICIT(void*, rule_ptr
->context
);
3094 curr_rule
->rulenum
= rule_ptr
->fw_number
;
3095 curr_rule
->pcnt
= rule_ptr
->fw_pcnt
;
3096 curr_rule
->bcnt
= rule_ptr
->fw_bcnt
;
3097 curr_rule
->timestamp
= rule_ptr
->timestamp
;
3100 #if FW2_DEBUG_VERBOSE
3101 ipfw_print_vers2_struct(curr_rule
);
3108 ipfw_version_one_to_version_two_64(struct sockopt
*sopt
, struct ip_fw
*curr_rule
,
3109 struct ip_fw_compat_64
*rule_vers1
)
3112 struct ip_fw_compat_64
*rule_ptr
;
3113 struct ip_fw_compat_64 rule
;
3116 rule_ptr
= rule_vers1
;
3119 /* do some basic size checking here, more extensive checking later */
3120 if (!sopt
->sopt_val
|| sopt
->sopt_valsize
< sizeof(struct ip_fw_compat_64
)) {
3124 if ((err
= sooptcopyin(sopt
, &rule
, sizeof(struct ip_fw_compat_64
),
3125 sizeof(struct ip_fw_compat_64
)))) {
3131 /* deal with commands */
3132 ipfw_convert_to_cmds_64(curr_rule
, rule_ptr
);
3134 curr_rule
->version
= IP_FW_CURRENT_API_VERSION
;
3135 curr_rule
->context
= CAST_DOWN_EXPLICIT( void *, rule_ptr
->context
);
3136 curr_rule
->rulenum
= rule_ptr
->fw_number
;
3137 curr_rule
->pcnt
= rule_ptr
->fw_pcnt
;
3138 curr_rule
->bcnt
= rule_ptr
->fw_bcnt
;
3139 curr_rule
->timestamp
= rule_ptr
->timestamp
;
3142 #if FW2_DEBUG_VERBOSE
3143 ipfw_print_vers2_struct(curr_rule
);
3149 /* This converts to whatever the latest version is. Currently the
3150 * latest version of the firewall is ipfw2.
3153 ipfw_version_one_to_latest_32(struct sockopt
*sopt
, struct ip_fw
*curr_rule
, struct ip_fw_compat_32
*rule_vers1
)
3157 /* if rule_vers1 is not null then this is coming from
3158 * ipfw_version_zero_to_latest(), so pass that along;
3159 * otherwise let ipfw_version_one_to_version_two()
3160 * get the rule from sopt.
3162 err
= ipfw_version_one_to_version_two_32(sopt
, curr_rule
, rule_vers1
);
3168 ipfw_version_one_to_latest_64(struct sockopt
*sopt
, struct ip_fw
*curr_rule
, struct ip_fw_compat_64
*rule_vers1
)
3172 /* if rule_vers1 is not null then this is coming from
3173 * ipfw_version_zero_to_latest(), so pass that along;
3174 * otherwise let ipfw_version_one_to_version_two()
3175 * get the rule from sopt.
3177 err
= ipfw_version_one_to_version_two_64(sopt
, curr_rule
, rule_vers1
);
3186 * XXX - ipfw_version_zero_to_one
3188 * This function is only used in version #1 of ipfw, which is now deprecated.
3193 ipfw_version_zero_to_one(struct ip_old_fw
*rule_vers0
, struct ip_fw_compat
*rule_vers1
)
3195 bzero(rule_vers1
, sizeof(struct ip_fw_compat
));
3196 bcopy(&rule_vers0
->fw_uar
, &rule_vers1
->fw_uar_compat
, sizeof(rule_vers0
->fw_uar
));
3197 bcopy(&rule_vers0
->fw_in_if
, &rule_vers1
->fw_in_if
, sizeof(rule_vers0
->fw_in_if
));
3198 bcopy(&rule_vers0
->fw_out_if
, &rule_vers1
->fw_out_if
, sizeof(rule_vers0
->fw_out_if
));
3199 bcopy(&rule_vers0
->fw_un
, &rule_vers1
->fw_un_compat
, sizeof(rule_vers0
->fw_un
));
3201 rule_vers1
->version
= 10;
3202 rule_vers1
->fw_pcnt
= rule_vers0
->fw_pcnt
;
3203 rule_vers1
->fw_bcnt
= rule_vers0
->fw_bcnt
;
3204 rule_vers1
->fw_src
= rule_vers0
->fw_src
;
3205 rule_vers1
->fw_dst
= rule_vers0
->fw_dst
;
3206 rule_vers1
->fw_smsk
= rule_vers0
->fw_smsk
;
3207 rule_vers1
->fw_dmsk
= rule_vers0
->fw_dmsk
;
3208 rule_vers1
->fw_number
= rule_vers0
->fw_number
;
3209 rule_vers1
->fw_flg
= rule_vers0
->fw_flg
;
3210 rule_vers1
->fw_ipopt
= rule_vers0
->fw_ipopt
;
3211 rule_vers1
->fw_ipnopt
= rule_vers0
->fw_ipnopt
;
3212 rule_vers1
->fw_tcpf
= rule_vers0
->fw_tcpf
& ~IP_OLD_FW_TCPF_ESTAB
;
3213 rule_vers1
->fw_tcpnf
= rule_vers0
->fw_tcpnf
;
3214 rule_vers1
->timestamp
= rule_vers0
->timestamp
;
3215 rule_vers1
->fw_prot
= rule_vers0
->fw_prot
;
3216 rule_vers1
->fw_nports
= rule_vers0
->fw_nports
;
3217 rule_vers1
->pipe_ptr
= rule_vers0
->pipe_ptr
;
3218 rule_vers1
->next_rule_ptr
= rule_vers0
->next_rule_ptr
;
3219 rule_vers1
->fw_ipflg
= (rule_vers0
->fw_tcpf
& IP_OLD_FW_TCPF_ESTAB
) ? IP_FW_IF_TCPEST_COMPAT
: 0;
3222 #endif /* !ipfw_version_zero_to_one */
3224 /* rule is a u_int32_t buffer[255] into which the converted
3225 * (if necessary) rules go.
3228 ipfw_convert_to_latest(struct sockopt
*sopt
, struct ip_fw
*curr_rule
, int api_version
, int is64user
)
3232 /* the following functions copy the rules passed in and
3233 * convert to latest structures based on version
3235 switch (api_version
) {
3236 case IP_FW_VERSION_0
:
3237 /* we're not supporting VERSION 0 */
3241 case IP_FW_VERSION_1
:
3242 /* this is the version supported in Panther */
3244 err
= ipfw_version_one_to_latest_64(sopt
, curr_rule
, NULL
);
3246 err
= ipfw_version_one_to_latest_32(sopt
, curr_rule
, NULL
);
3250 case IP_FW_CURRENT_API_VERSION
:
3252 /* do nothing here... */
3256 /* unrecognized/unsupported version */
3265 ipfw_get_command_and_version(struct sockopt
*sopt
, int *command
, u_int32_t
*api_version
)
3269 u_int32_t vers
= IP_FW_VERSION_NONE
;
3271 /* first deal with the oldest version */
3272 if (sopt
->sopt_name
== IP_OLD_FW_GET
) {
3273 vers
= IP_FW_VERSION_0
;
3275 } else if (sopt
->sopt_name
== IP_OLD_FW_FLUSH
) {
3276 vers
= IP_FW_VERSION_0
;
3278 } else if (sopt
->sopt_name
== IP_OLD_FW_ZERO
) {
3279 vers
= IP_FW_VERSION_0
;
3281 } else if (sopt
->sopt_name
== IP_OLD_FW_ADD
) {
3282 vers
= IP_FW_VERSION_0
;
3284 } else if (sopt
->sopt_name
== IP_OLD_FW_DEL
) {
3285 vers
= IP_FW_VERSION_0
;
3287 } else if (sopt
->sopt_name
== IP_OLD_FW_RESETLOG
) {
3288 vers
= IP_FW_VERSION_0
;
3289 cmd
= IP_FW_RESETLOG
;
3291 cmd
= sopt
->sopt_name
;
3294 if (vers
== IP_FW_VERSION_NONE
) {
3295 /* working off the fact that the offset
3296 * is the same in both structs.
3298 struct ip_fw_64 rule
;
3301 if (proc_is64bit(sopt
->sopt_p
)) {
3302 copyinsize
= sizeof(struct ip_fw_64
);
3304 copyinsize
= sizeof(struct ip_fw_32
);
3307 if (!sopt
->sopt_val
|| sopt
->sopt_valsize
< copyinsize
) {
3310 if ((err
= sooptcopyin(sopt
, &rule
, copyinsize
, copyinsize
))) {
3314 vers
= rule
.version
;
3321 *api_version
= vers
;