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"
70 static struct _s_x f_tcpflags
[] = {
81 static struct _s_x f_tcpopts
[] = {
82 { "mss", IP_FW_TCPOPT_MSS
},
83 { "maxseg", IP_FW_TCPOPT_MSS
},
84 { "window", IP_FW_TCPOPT_WINDOW
},
85 { "sack", IP_FW_TCPOPT_SACK
},
86 { "ts", IP_FW_TCPOPT_TS
},
87 { "timestamp", IP_FW_TCPOPT_TS
},
88 { "cc", IP_FW_TCPOPT_CC
},
94 * IP options span the range 0 to 255 so we need to remap them
95 * (though in fact only the low 5 bits are significant).
97 static struct _s_x f_ipopts
[] = {
98 { "ssrr", IP_FW_IPOPT_SSRR
},
99 { "lsrr", IP_FW_IPOPT_LSRR
},
100 { "rr", IP_FW_IPOPT_RR
},
101 { "ts", IP_FW_IPOPT_TS
},
106 static struct _s_x f_iptos
[] = {
107 { "lowdelay", IPTOS_LOWDELAY
},
108 { "throughput", IPTOS_THROUGHPUT
},
109 { "reliability", IPTOS_RELIABILITY
},
110 { "mincost", IPTOS_MINCOST
},
111 { "congestion", IPTOS_CE
},
112 { "ecntransport", IPTOS_ECT
},
113 { "ip tos option", 0},
117 static struct _s_x limit_masks
[] = {
118 {"all", DYN_SRC_ADDR
|DYN_SRC_PORT
|DYN_DST_ADDR
|DYN_DST_PORT
},
119 {"src-addr", DYN_SRC_ADDR
},
120 {"src-port", DYN_SRC_PORT
},
121 {"dst-addr", DYN_DST_ADDR
},
122 {"dst-port", DYN_DST_PORT
},
127 ipfw_print_fw_flags(u_int flags
)
130 switch (flags
& IP_FW_F_COMMAND_COMPAT
) {
131 case IP_FW_F_ACCEPT_COMPAT
:
132 printf("IP_FW_F_ACCEPT_COMPAT\n");
134 case IP_FW_F_COUNT_COMPAT
:
135 printf("IP_FW_F_COUNT_COMPAT\n");
137 case IP_FW_F_PIPE_COMPAT
:
138 printf("IP_FW_F_PIPE_COMPAT\n");
140 case IP_FW_F_QUEUE_COMPAT
:
141 printf("IP_FW_F_QUEUE_COMPAT\n");
143 case IP_FW_F_SKIPTO_COMPAT
:
144 printf("IP_FW_F_SKIPTO_COMPAT\n");
146 case IP_FW_F_DIVERT_COMPAT
:
147 printf("IP_FW_F_DIVERT_COMPAT\n");
149 case IP_FW_F_TEE_COMPAT
:
150 printf("IP_FW_F_TEE_COMPAT\n");
152 case IP_FW_F_FWD_COMPAT
:
153 printf("IP_FW_F_FWD_COMPAT\n");
155 case IP_FW_F_DENY_COMPAT
:
156 printf("IP_FW_F_DENY_COMPAT\n");
158 case IP_FW_F_REJECT_COMPAT
:
159 printf("IP_FW_F_REJECT_COMPAT\n");
161 case IP_FW_F_CHECK_S_COMPAT
:
162 printf("IP_FW_F_CHECK_S_COMPAT\n");
165 printf("No action given\n");
170 if (flags
& IP_FW_F_IN_COMPAT
) {
171 printf("IP_FW_F_IN_COMPAT\n");
173 if (flags
& IP_FW_F_OUT_COMPAT
) {
174 printf("IP_FW_F_OUT_COMPAT\n");
176 if (flags
& IP_FW_F_IIFACE_COMPAT
) {
177 printf("IP_FW_F_IIFACE_COMPAT\n");
179 if (flags
& IP_FW_F_OIFACE_COMPAT
) {
180 printf("IP_FW_F_OIFACE_COMPAT\n");
182 if (flags
& IP_FW_F_PRN_COMPAT
) {
183 printf("IP_FW_F_PRN_COMPAT\n");
185 if (flags
& IP_FW_F_SRNG_COMPAT
) {
186 printf("IP_FW_F_SRNG_COMPAT\n");
188 if (flags
& IP_FW_F_DRNG_COMPAT
) {
189 printf("IP_FW_F_DRNG_COMPAT\n");
191 if (flags
& IP_FW_F_FRAG_COMPAT
) {
192 printf("IP_FW_F_FRAG_COMPAT\n");
194 if (flags
& IP_FW_F_IIFNAME_COMPAT
) {
195 printf("IP_FW_F_IIFNAME_COMPAT\n");
197 if (flags
& IP_FW_F_OIFNAME_COMPAT
) {
198 printf("IP_FW_F_OIFNAME_COMPAT\n");
200 if (flags
& IP_FW_F_INVSRC_COMPAT
) {
201 printf("IP_FW_F_INVSRC_COMPAT\n");
203 if (flags
& IP_FW_F_INVDST_COMPAT
) {
204 printf("IP_FW_F_INVDST_COMPAT\n");
206 if (flags
& IP_FW_F_ICMPBIT_COMPAT
) {
207 printf("IP_FW_F_ICMPBIT_COMPAT\n");
209 if (flags
& IP_FW_F_UID_COMPAT
) {
210 printf("IP_FW_F_UID_COMPAT\n");
212 if (flags
& IP_FW_F_RND_MATCH_COMPAT
) {
213 printf("IP_FW_F_RND_MATCH_COMPAT\n");
215 if (flags
& IP_FW_F_SMSK_COMPAT
) {
216 printf("IP_FW_F_SMSK_COMPAT\n");
218 if (flags
& IP_FW_F_DMSK_COMPAT
) {
219 printf("IP_FW_F_DMSK_COMPAT\n");
221 if (flags
& IP_FW_BRIDGED_COMPAT
) {
222 printf("IP_FW_BRIDGED_COMPAT\n");
224 if (flags
& IP_FW_F_KEEP_S_COMPAT
) {
225 printf("IP_FW_F_KEEP_S_COMPAT\n");
227 if (flags
& IP_FW_F_CHECK_S_COMPAT
) {
228 printf("IP_FW_F_CHECK_S_COMPAT\n");
230 if (flags
& IP_FW_F_SME_COMPAT
) {
231 printf("IP_FW_F_SME_COMPAT\n");
233 if (flags
& IP_FW_F_DME_COMPAT
) {
234 printf("IP_FW_F_DME_COMPAT\n");
239 print_fw_version(u_int32_t api_version
)
241 switch (api_version
) {
242 case IP_FW_VERSION_0
:
243 printf("Version: %s\n", VERSION_ZERO_STR
);
245 case IP_FW_VERSION_1
:
246 printf("Version: %s\n", VERSION_ONE_STR
);
248 case IP_FW_CURRENT_API_VERSION
:
249 printf("Version: %s\n", CURRENT_API_VERSION_STR
);
251 case IP_FW_VERSION_NONE
:
252 printf("Version: %s\n", NO_VERSION_STR
);
255 printf("Unrecognized version\n");
261 ipfw_print_vers1_struct(struct ip_fw_compat
*vers1_rule
)
263 char ipv4str
[MAX_IPv4_STR_LEN
];
264 print_fw_version(vers1_rule
->version
);
265 printf("Rule #%d\n", vers1_rule
->fw_number
);
267 ipfw_print_fw_flags(vers1_rule
->fw_flg
);
269 printf("fw_pcnt: %llu\n", vers1_rule
->fw_pcnt
);
270 printf("fw_bcnt: %llu\n", vers1_rule
->fw_bcnt
);
271 printf("fw_src: %s\n",
272 inet_ntop(AF_INET
, &vers1_rule
->fw_src
, ipv4str
, sizeof(ipv4str
)));
273 printf("fw_dst: %s\n",
274 inet_ntop(AF_INET
, &vers1_rule
->fw_dst
, ipv4str
, sizeof(ipv4str
)));
275 printf("fw_smsk: %s\n",
276 inet_ntop(AF_INET
, &vers1_rule
->fw_smsk
, ipv4str
, sizeof(ipv4str
)));
277 printf("fw_dmsk: %s\n",
278 inet_ntop(AF_INET
, &vers1_rule
->fw_dmsk
, ipv4str
, sizeof(ipv4str
)));
280 if (vers1_rule
->fw_flg
& IP_FW_F_ICMPBIT_COMPAT
) {
287 type_index
< (IP_FW_ICMPTYPES_DIM_COMPAT
* sizeof(unsigned) * 8);
289 if (vers1_rule
->fw_uar_compat
.fw_icmptypes
[type_index
/ (sizeof(unsigned) * 8)] &
290 (1U << (type_index
% (sizeof(unsigned) * 8)))) {
291 printf("%c%d", first
== 1 ? ' ' : ',', type_index
);
298 nsp
= IP_FW_GETNSRCP_COMPAT(vers1_rule
);
299 for (i
= 0; i
< nsp
; i
++) {
300 printf("source ports: fw_uar_compat.fw_pts: %04x", vers1_rule
->fw_uar_compat
.fw_pts
[i
]);
301 if (i
== 0 && (vers1_rule
->fw_flg
& IP_FW_F_SRNG_COMPAT
))
303 else if (i
== 0 && (vers1_rule
->fw_flg
& IP_FW_F_SMSK_COMPAT
))
311 ndp
= IP_FW_GETNDSTP_COMPAT(vers1_rule
);
312 for (i
= 0; i
< ndp
; i
++) {
313 printf("source ports: fw_uar_compat.fw_pts: %04x", vers1_rule
->fw_uar_compat
.fw_pts
[nsp
+i
]);
314 if (i
== 0 && (vers1_rule
->fw_flg
& IP_FW_F_DRNG_COMPAT
))
316 else if (i
== 0 && (vers1_rule
->fw_flg
& IP_FW_F_DMSK_COMPAT
))
325 printf("fw_ipflg: %d\n", vers1_rule
->fw_ipflg
);
326 printf("fw_ipopt: %d\n", vers1_rule
->fw_ipopt
);
327 printf("fw_ipnopt: %d\n", vers1_rule
->fw_ipnopt
);
328 printf("fw_tcpopt: %d\n", vers1_rule
->fw_tcpopt
);
329 printf("fw_tcpnopt: %d\n", vers1_rule
->fw_tcpnopt
);
330 printf("fw_tcpf: %d\n", vers1_rule
->fw_tcpf
);
331 printf("fw_tcpnf: %d\n", vers1_rule
->fw_tcpnf
);
332 printf("timestamp: %ld\n", vers1_rule
->timestamp
);
334 if ((vers1_rule
->fw_flg
& IF_FW_F_VIAHACK_COMPAT
) == IF_FW_F_VIAHACK_COMPAT
) {
335 printf("fw_in_if: ");
336 inet_ntop(AF_INET
, &vers1_rule
->fw_in_if
.fu_via_ip
, ipv4str
,
338 printf("fu_via_ip: %s\n", ipv4str
);
339 printf("fu_via_if_compat.name: %s\n", vers1_rule
->fw_in_if
.fu_via_if_compat
.name
);
340 printf("fu_via_if_compat.unit: %d\n", vers1_rule
->fw_in_if
.fu_via_if_compat
.unit
);
342 if (vers1_rule
->fw_flg
& IP_FW_F_IIFACE_COMPAT
) {
343 printf("fw_in_if: ");
344 printf("fu_via_ip: %s\n",
345 inet_ntop(AF_INET
, &vers1_rule
->fw_in_if
.fu_via_ip
, ipv4str
,
347 printf("fu_via_if_compat.name: %s\n", vers1_rule
->fw_in_if
.fu_via_if_compat
.name
);
348 printf("fu_via_if_compat.unit: %d\n", vers1_rule
->fw_in_if
.fu_via_if_compat
.unit
);
350 if (vers1_rule
->fw_flg
& IP_FW_F_OIFACE_COMPAT
) {
351 printf("fw_out_if: ");
352 printf("fu_via_ip: %s\n",
353 inet_ntop(AF_INET
, &vers1_rule
->fw_out_if
.fu_via_ip
,
354 ipv4str
, sizeof(ipv4str
)));
355 printf("fu_via_if_compat.name: %s\n", vers1_rule
->fw_out_if
.fu_via_if_compat
.name
);
356 printf("fu_via_if_compat.unit: %d\n", vers1_rule
->fw_out_if
.fu_via_if_compat
.unit
);
360 printf("fw_prot: %d\n", vers1_rule
->fw_prot
);
361 printf("fw_nports: %d\n", vers1_rule
->fw_nports
);
362 printf("pipe_ptr: %p\n", vers1_rule
->pipe_ptr
);
363 printf("next_rule_ptr: %p\n", vers1_rule
->next_rule_ptr
);
364 printf("fw_uid: %d\n", vers1_rule
->fw_uid
);
365 printf("fw_logamount: %d\n", vers1_rule
->fw_logamount
);
366 printf("fw_loghighest: %llu\n", vers1_rule
->fw_loghighest
);
370 print_icmptypes(ipfw_insn_u32
*cmd
)
375 printf(" icmptypes");
376 for (i
= 0; i
< 32; i
++) {
377 if ( (cmd
->d
[0] & (1 << (i
))) == 0)
379 printf("%c%d", sep
, i
);
385 * print flags set/clear in the two bitmasks passed as parameters.
386 * There is a specialized check for f_tcpflags.
389 print_flags(char const *name
, ipfw_insn
*cmd
, struct _s_x
*list
)
391 char const *comma
= "";
393 uint8_t set
= cmd
->arg1
& 0xff;
394 uint8_t clear
= (cmd
->arg1
>> 8) & 0xff;
396 if (list
== f_tcpflags
&& set
== TH_SYN
&& clear
== TH_ACK
) {
401 printf(" %s ", name
);
402 for (i
=0; list
[i
].x
!= 0; i
++) {
403 if (set
& list
[i
].x
) {
405 printf("%s%s", comma
, list
[i
].s
);
408 if (clear
& list
[i
].x
) {
410 printf("%s!%s", comma
, list
[i
].s
);
417 contigmask(uint8_t *p
, int len
)
421 for (i
=0; i
<len
; i
++)
422 if ( (p
[i
/8] & (1 << (7 - (i%8
)))) == 0) /* first bit unset */
424 for (n
=i
+1; n
< len
; n
++)
425 if ( (p
[n
/8] & (1 << (7 - (n%8
)))) != 0)
426 return -1; /* mask not contiguous */
431 * Print the ip address contained in a command.
434 print_ip(ipfw_insn_ip
*cmd
)
436 int len
= F_LEN((ipfw_insn
*)cmd
);
437 uint32_t *a
= ((ipfw_insn_u32
*)cmd
)->d
;
438 char ipv4str
[MAX_IPv4_STR_LEN
];
440 printf("%s ", cmd
->o
.len
& F_NOT
? " not": "");
442 if (cmd
->o
.opcode
== O_IP_SRC_ME
|| cmd
->o
.opcode
== O_IP_DST_ME
) {
448 * len == 2 indicates a single IP, whereas lists of 1 or more
449 * addr/mask pairs have len = (2n+1). We convert len to n so we
450 * use that to count the number of entries.
452 for (len
= len
/ 2; len
> 0; len
--, a
+= 2) {
453 int mb
= /* mask length */
454 (cmd
->o
.opcode
== O_IP_SRC
|| cmd
->o
.opcode
== O_IP_DST
) ?
455 32 : contigmask((uint8_t *)&(a
[1]), 32);
456 if (mb
== 0) { /* any */
458 } else { /* numeric IP followed by some kind of mask */
459 printf("%s", inet_ntop(AF_INET
, &a
[0], ipv4str
, sizeof(ipv4str
)));
461 printf(":%s", inet_ntop(AF_INET
, &a
[1], ipv4str
, sizeof(ipv4str
)));
471 * prints a MAC address/mask pair
474 print_mac(uint8_t *addr
, uint8_t *mask
)
476 int l
= contigmask(mask
, 48);
481 printf(" %02x:%02x:%02x:%02x:%02x:%02x",
482 addr
[0], addr
[1], addr
[2], addr
[3], addr
[4], addr
[5]);
484 printf("&%02x:%02x:%02x:%02x:%02x:%02x",
485 mask
[0], mask
[1], mask
[2],
486 mask
[3], mask
[4], mask
[5]);
493 ipfw_print_vers2_struct(struct ip_fw
*vers2_rule
)
497 ipfw_insn_log
*logptr
= NULL
;
498 char ipv4str
[MAX_IPv4_STR_LEN
];
500 print_fw_version(vers2_rule
->version
);
502 printf("act_ofs: %d\n", vers2_rule
->act_ofs
);
503 printf("cmd_len: %d\n", vers2_rule
->cmd_len
);
504 printf("rulenum: %d\n", vers2_rule
->rulenum
);
505 printf("set: %d\n", vers2_rule
->set
);
506 printf("pcnt: %llu\n", vers2_rule
->pcnt
);
507 printf("bcnt: %llu\n", vers2_rule
->bcnt
);
508 printf("timestamp: %d\n", vers2_rule
->timestamp
);
511 * first print actions
513 for (l
= vers2_rule
->cmd_len
- vers2_rule
->act_ofs
, cmd
= ACTION_PTR(vers2_rule
);
514 l
> 0 ; l
-= F_LEN(cmd
), cmd
+= F_LEN(cmd
)) {
515 switch(cmd
->opcode
) {
517 printf("check-state");
533 if (cmd
->arg1
== ICMP_REJECT_RST
)
535 else if (cmd
->arg1
== ICMP_UNREACH_HOST
)
538 printf("unreach %u", cmd
->arg1
);
542 printf("skipto %u", cmd
->arg1
);
546 printf("pipe %u", cmd
->arg1
);
550 printf("queue %u", cmd
->arg1
);
554 printf("divert %u", cmd
->arg1
);
558 printf("tee %u", cmd
->arg1
);
563 ipfw_insn_sa
*s
= (ipfw_insn_sa
*)cmd
;
566 inet_ntop(AF_INET
, &s
->sa
.sin_addr
, ipv4str
,
569 printf(",%d", s
->sa
.sin_port
);
573 case O_LOG
: /* O_LOG is printed last */
574 logptr
= (ipfw_insn_log
*)cmd
;
578 printf("** unrecognized action %d len %d",
579 cmd
->opcode
, cmd
->len
);
583 if (logptr
->max_log
> 0)
584 printf(" log logamount %d", logptr
->max_log
);
590 * then print the body.
592 for (l
= vers2_rule
->act_ofs
, cmd
= vers2_rule
->cmd
;
593 l
> 0 ; l
-= F_LEN(cmd
) , cmd
+= F_LEN(cmd
)) {
595 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
;
597 switch(cmd
->opcode
) {
599 break; /* done already */
602 break; /* no need to print anything here */
606 ipfw_insn_mac
*m
= (ipfw_insn_mac
*)cmd
;
608 if (cmd
->len
& F_NOT
)
611 print_mac(m
->addr
, m
->mask
);
612 print_mac(m
->addr
+ 6, m
->mask
+ 6);
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]);
634 print_ip((ipfw_insn_ip
*)cmd
);
640 print_ip((ipfw_insn_ip
*)cmd
);
646 uint16_t *p
= ((ipfw_insn_u16
*)cmd
)->ports
;
649 for (i
= F_LEN((ipfw_insn
*)cmd
) - 1; i
> 0; i
--, p
+= 2) {
650 printf("0x%04x", p
[0]);
653 printf("0x%04x", p
[1]);
663 if (cmd
->len
& F_NOT
)
666 printf(" %u", cmd
->arg1
);
671 default: /*options ... */
673 if (cmd
->len
& F_NOT
&& cmd
->opcode
!= O_IN
)
675 switch(cmd
->opcode
) {
681 printf(cmd
->len
& F_NOT
? " out" : " O_IN");
692 ipfw_insn_if
*cmdif
= (ipfw_insn_if
*)cmd
;
694 if (cmd
->opcode
== O_XMIT
)
696 else if (cmd
->opcode
== O_RECV
)
698 else /* if (cmd->opcode == O_VIA) */
700 if (cmdif
->name
[0] == '\0') {
702 inet_ntop(AF_INET
, &cmdif
->p
.ip
, ipv4str
,
705 else if (cmdif
->p
.unit
== -1)
706 printf(" %s %s*", s
, cmdif
->name
);
708 printf(" %s %s%d", s
, cmdif
->name
,
715 printf(" ipid %u", cmd
->arg1
);
717 uint16_t *p
= ((ipfw_insn_u16
*)cmd
)->ports
;
720 for (i
= F_LEN((ipfw_insn
*)cmd
) - 1; i
> 0; i
--, p
+= 2) {
721 printf("0x%04x", p
[0]);
724 printf("0x%04x", p
[1]);
734 printf(" ipttl %u", cmd
->arg1
);
736 uint16_t *p
= ((ipfw_insn_u16
*)cmd
)->ports
;
739 for (i
= F_LEN((ipfw_insn
*)cmd
) - 1; i
> 0; i
--, p
+= 2) {
740 printf("0x%04x", p
[0]);
743 printf("0x%04x", p
[1]);
752 printf(" ipver %u", cmd
->arg1
);
756 printf(" ipprecedence %u", (cmd
->arg1
) >> 5 );
761 printf(" iplen %u", cmd
->arg1
);
763 uint16_t *p
= ((ipfw_insn_u16
*)cmd
)->ports
;
766 for (i
= F_LEN((ipfw_insn
*)cmd
) - 1; i
> 0; i
--, p
+= 2) {
767 printf("0x%04x", p
[0]);
770 printf("0x%04x", p
[1]);
779 print_flags("ipoptions", cmd
, f_ipopts
);
783 print_flags("iptos", cmd
, f_iptos
);
787 print_icmptypes((ipfw_insn_u32
*)cmd
);
791 printf(" established");
795 print_flags("tcpflags", cmd
, f_tcpflags
);
799 print_flags("tcpoptions", cmd
, f_tcpopts
);
803 printf(" tcpwin %d", ntohs(cmd
->arg1
));
807 printf(" tcpack %u", ntohl(cmd32
->d
[0]));
811 printf(" tcpseq %u", ntohl(cmd32
->d
[0]));
815 printf(" uid %u", cmd32
->d
[0]);
819 printf(" gid %u", cmd32
->d
[0]);
823 printf(" verrevpath");
834 printf(" keep-state");
839 struct _s_x
*p
= limit_masks
;
840 ipfw_insn_limit
*c
= (ipfw_insn_limit
*)cmd
;
841 uint8_t x
= c
->limit_mask
;
842 char const *comma
= " ";
845 for (; p
->x
!= 0 ; p
++)
846 if ((x
& p
->x
) == p
->x
) {
848 printf("%s%s", comma
, p
->s
);
851 printf(" %d", c
->conn_limit
);
857 printf(" [opcode %d len %d]",
858 cmd
->opcode
, cmd
->len
);
866 * helper function, updates the pointer to cmd with the length
867 * of the current command, and also cleans up the first word of
868 * the new command in case it has been clobbered before.
872 next_cmd(ipfw_insn
*cmd
)
875 bzero(cmd
, sizeof(*cmd
));
880 * A function to fill simple commands of size 1.
881 * Existing flags are preserved.
885 fill_cmd(ipfw_insn
*cmd
, enum ipfw_opcodes opcode
, uint16_t arg
)
887 cmd
->opcode
= opcode
;
888 cmd
->len
= ((cmd
->len
) & (F_NOT
| F_OR
)) | 1;
894 fill_compat_tcpflags(u_int32_t flags
) {
895 u_int32_t flags_compat
= 0;
898 flags_compat
|= IP_FW_TCPF_FIN_COMPAT
;
900 flags_compat
|= IP_FW_TCPF_SYN_COMPAT
;
902 flags_compat
|= IP_FW_TCPF_RST_COMPAT
;
904 flags_compat
|= IP_FW_TCPF_PSH_COMPAT
;
906 flags_compat
|= IP_FW_TCPF_ACK_COMPAT
;
908 flags_compat
|= IP_FW_TCPF_URG_COMPAT
;
914 /* ********************************************
915 * *********** Convert from Latest ************
916 * ********************************************/
919 * Things we're actively ignoring:
920 * sets, sets of addresses, blocks (NOT, OR)
923 ipfw_map_from_cmds(struct ip_fw
*curr_rule
, struct ip_fw_compat
*compat_rule
)
928 for (l
= curr_rule
->act_ofs
, cmd
= curr_rule
->cmd
;
930 l
-= F_LEN(cmd
) , cmd
+= F_LEN(cmd
)) {
932 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
;
934 switch (cmd
->opcode
) {
937 compat_rule
->fw_prot
= cmd
->arg1
;
941 compat_rule
->fw_flg
|= IP_FW_F_SME_COMPAT
;
942 if (cmd
->len
& F_NOT
) {
943 compat_rule
->fw_flg
|= IP_FW_F_INVSRC_COMPAT
;
950 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
952 compat_rule
->fw_src
= ip
->addr
;
953 compat_rule
->fw_smsk
= ip
->mask
;
954 if (cmd
->len
& F_NOT
) {
955 compat_rule
->fw_flg
|= IP_FW_F_INVSRC_COMPAT
;
963 * for now we only deal with one address
964 * per rule and ignore sets of addresses
966 compat_rule
->fw_src
.s_addr
= cmd32
->d
[0];
967 if (cmd
->len
& F_NOT
) {
968 compat_rule
->fw_flg
|= IP_FW_F_INVSRC_COMPAT
;
975 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
976 uint16_t *p
= ports
->ports
;
979 /* copy list of ports */
980 for (i
= F_LEN(cmd
) - 1, j
= 0; i
> 0; i
--, j
++, p
+= 2) {
982 /* this is a range */
983 compat_rule
->fw_flg
|= IP_FW_F_SRNG_COMPAT
;
984 compat_rule
->fw_uar_compat
.fw_pts
[j
++] = p
[0];
985 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[1];
987 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[0];
990 IP_FW_SETNSRCP_COMPAT(compat_rule
, j
);
997 compat_rule
->fw_flg
|= IP_FW_F_DME_COMPAT
;
998 if (cmd
->len
& F_NOT
) {
999 compat_rule
->fw_flg
|= IP_FW_F_INVDST_COMPAT
;
1006 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
1008 compat_rule
->fw_dst
= ip
->addr
;
1009 compat_rule
->fw_dmsk
= ip
->mask
;
1010 if (cmd
->len
& F_NOT
) {
1011 compat_rule
->fw_flg
|= IP_FW_F_INVDST_COMPAT
;
1018 * for now we only deal with one address
1019 * per rule, and ignore sets of addresses
1021 compat_rule
->fw_dst
.s_addr
= cmd32
->d
[0];
1022 if (cmd
->len
& F_NOT
) {
1023 compat_rule
->fw_flg
|= IP_FW_F_INVDST_COMPAT
;
1030 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
1031 uint16_t *p
= ports
->ports
;
1033 j
= IP_FW_GETNSRCP_COMPAT(compat_rule
);
1035 /* copy list of ports */
1036 for (i
= F_LEN(cmd
) - 1; i
> 0; i
--, j
++, p
+= 2) {
1038 /* this is a range */
1039 compat_rule
->fw_flg
|= IP_FW_F_DRNG_COMPAT
;
1040 compat_rule
->fw_uar_compat
.fw_pts
[j
++] = p
[0];
1041 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[1];
1043 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[0];
1046 IP_FW_SETNDSTP_COMPAT(compat_rule
, (j
- IP_FW_GETNSRCP_COMPAT(compat_rule
)));
1053 ipfw_insn_log
*c
= (ipfw_insn_log
*)cmd
;
1055 compat_rule
->fw_flg
|= IP_FW_F_PRN_COMPAT
;
1056 compat_rule
->fw_logamount
= c
->max_log
;
1060 compat_rule
->fw_flg
|= IP_FW_F_UID_COMPAT
;
1061 compat_rule
->fw_uid
= cmd32
->d
[0];
1065 if (cmd
->len
& F_NOT
) {
1066 compat_rule
->fw_flg
|= IP_FW_F_OUT_COMPAT
;
1068 compat_rule
->fw_flg
|= IP_FW_F_IN_COMPAT
;
1073 compat_rule
->fw_flg
|= IP_FW_F_KEEP_S_COMPAT
;
1077 compat_rule
->fw_flg
|= IP_FW_BRIDGED_COMPAT
;
1082 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1083 union ip_fw_if_compat ifu
;
1085 if ((ifcmd
->o
.len
== 0) && (ifcmd
->name
[0] == '\0')) {
1087 compat_rule
->fw_flg
|= IP_FW_F_OIFACE_COMPAT
;
1088 ifu
.fu_via_ip
.s_addr
= 0;
1090 else if (ifcmd
->p
.ip
.s_addr
!= 0) {
1091 compat_rule
->fw_flg
|= IP_FW_F_OIFACE_COMPAT
;
1092 ifu
.fu_via_ip
= ifcmd
->p
.ip
;
1094 compat_rule
->fw_flg
|= IP_FW_F_OIFNAME_COMPAT
;
1095 strncpy(ifu
.fu_via_if_compat
.name
, ifcmd
->name
, sizeof(ifu
.fu_via_if_compat
.name
));
1096 ifu
.fu_via_if_compat
.unit
= ifcmd
->p
.unit
;
1098 compat_rule
->fw_out_if
= ifu
;
1105 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1106 union ip_fw_if_compat ifu
;
1108 if ((ifcmd
->o
.len
== 0) && (ifcmd
->name
[0] == '\0')) {
1110 compat_rule
->fw_flg
|= IP_FW_F_IIFACE_COMPAT
;
1111 ifu
.fu_via_ip
.s_addr
= 0;
1113 else if (ifcmd
->p
.ip
.s_addr
!= 0) {
1114 compat_rule
->fw_flg
|= IP_FW_F_IIFACE_COMPAT
;
1115 ifu
.fu_via_ip
= ifcmd
->p
.ip
;
1117 compat_rule
->fw_flg
|= IP_FW_F_IIFNAME_COMPAT
;
1118 strncpy(ifu
.fu_via_if_compat
.name
, ifcmd
->name
, sizeof(ifu
.fu_via_if_compat
.name
));
1119 ifu
.fu_via_if_compat
.unit
= ifcmd
->p
.unit
;
1121 compat_rule
->fw_in_if
= ifu
;
1128 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1129 union ip_fw_if_compat ifu
;
1131 if ((ifcmd
->o
.len
== 0) && (ifcmd
->name
[0] == '\0')) {
1133 ifu
.fu_via_ip
.s_addr
= 0;
1135 else if (ifcmd
->name
[0] != '\0') {
1136 compat_rule
->fw_flg
|= IP_FW_F_IIFNAME_COMPAT
;
1137 strncpy(ifu
.fu_via_if_compat
.name
, ifcmd
->name
, sizeof(ifu
.fu_via_if_compat
.name
));
1138 ifu
.fu_via_if_compat
.unit
= ifcmd
->p
.unit
;
1140 ifu
.fu_via_ip
= ifcmd
->p
.ip
;
1142 compat_rule
->fw_flg
|= IF_FW_F_VIAHACK_COMPAT
;
1143 compat_rule
->fw_out_if
= compat_rule
->fw_in_if
= ifu
;
1149 compat_rule
->fw_flg
|= IP_FW_F_FRAG_COMPAT
;
1154 compat_rule
->fw_ipopt
= (cmd
->arg1
& 0xff);
1155 compat_rule
->fw_ipnopt
= ((cmd
->arg1
>> 8) & 0xff);
1159 /* check for "setup" */
1160 if ((cmd
->arg1
& 0xff) == TH_SYN
&&
1161 ((cmd
->arg1
>> 8) & 0xff) == TH_ACK
) {
1162 compat_rule
->fw_tcpf
= IP_FW_TCPF_SYN_COMPAT
;
1163 compat_rule
->fw_tcpnf
= IP_FW_TCPF_ACK_COMPAT
;
1166 compat_rule
->fw_tcpf
= fill_compat_tcpflags(cmd
->arg1
& 0xff);
1167 compat_rule
->fw_tcpnf
= fill_compat_tcpflags((cmd
->arg1
>> 8) & 0xff);
1173 compat_rule
->fw_tcpopt
= (cmd
->arg1
& 0xff);
1174 compat_rule
->fw_tcpnopt
= ((cmd
->arg1
>> 8) & 0xff);
1178 compat_rule
->fw_ipflg
|= IP_FW_IF_TCPEST_COMPAT
;
1184 /* XXX: check this */
1187 compat_rule
->fw_flg
|= IP_FW_F_ICMPBIT_COMPAT
;
1188 for (i
= 0; i
< sizeof(uint32_t) ; i
++) {
1189 type
= cmd32
->d
[0] & i
;
1191 compat_rule
->fw_uar_compat
.fw_icmptypes
[type
/ (sizeof(unsigned) * 8)] |=
1192 1 << (type
% (sizeof(unsigned) * 8));
1203 ipfw_map_from_actions(struct ip_fw
*curr_rule
, struct ip_fw_compat
*compat_rule
)
1208 for (l
= curr_rule
->cmd_len
- curr_rule
->act_ofs
, cmd
= ACTION_PTR(curr_rule
);
1210 l
-= F_LEN(cmd
), cmd
+= F_LEN(cmd
)) {
1211 switch (cmd
->opcode
) {
1213 compat_rule
->fw_flg
|= IP_FW_F_ACCEPT_COMPAT
;
1216 compat_rule
->fw_flg
|= IP_FW_F_COUNT_COMPAT
;
1219 compat_rule
->fw_flg
|= IP_FW_F_PIPE_COMPAT
;
1220 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1223 compat_rule
->fw_flg
|= IP_FW_F_QUEUE_COMPAT
;
1224 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1227 compat_rule
->fw_flg
|= IP_FW_F_SKIPTO_COMPAT
;
1228 compat_rule
->fw_skipto_rule_compat
= cmd
->arg1
;
1231 compat_rule
->fw_flg
|= IP_FW_F_DIVERT_COMPAT
;
1232 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1235 compat_rule
->fw_flg
|= IP_FW_F_TEE_COMPAT
;
1236 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1240 ipfw_insn_sa
*p
= (ipfw_insn_sa
*)cmd
;
1242 compat_rule
->fw_flg
|= IP_FW_F_FWD_COMPAT
;
1243 compat_rule
->fw_fwd_ip_compat
.sin_len
= p
->sa
.sin_len
;
1244 compat_rule
->fw_fwd_ip_compat
.sin_family
= p
->sa
.sin_family
;
1245 compat_rule
->fw_fwd_ip_compat
.sin_port
= p
->sa
.sin_port
;
1246 compat_rule
->fw_fwd_ip_compat
.sin_addr
= p
->sa
.sin_addr
;
1251 compat_rule
->fw_flg
|= IP_FW_F_DENY_COMPAT
;
1254 compat_rule
->fw_flg
|= IP_FW_F_REJECT_COMPAT
;
1255 compat_rule
->fw_reject_code_compat
= cmd
->arg1
;
1258 compat_rule
->fw_flg
|= IP_FW_F_CHECK_S_COMPAT
;
1267 ipfw_version_latest_to_one(struct ip_fw
*curr_rule
, struct ip_fw_compat
*rule_vers1
)
1272 bzero(rule_vers1
, sizeof(struct ip_fw_compat
));
1274 rule_vers1
->version
= IP_FW_VERSION_1
;
1275 rule_vers1
->context
= curr_rule
->context
;
1276 rule_vers1
->fw_number
= curr_rule
->rulenum
;
1277 rule_vers1
->fw_pcnt
= curr_rule
->pcnt
;
1278 rule_vers1
->fw_bcnt
= curr_rule
->bcnt
;
1279 rule_vers1
->timestamp
= curr_rule
->timestamp
;
1281 /* convert actions */
1282 ipfw_map_from_actions(curr_rule
, rule_vers1
);
1284 /* convert commands */
1285 ipfw_map_from_cmds(curr_rule
, rule_vers1
);
1287 #if FW2_DEBUG_VERBOSE
1288 ipfw_print_vers1_struct(rule_vers1
);
1292 /* first convert to version one then to version zero */
1294 ipfw_version_latest_to_zero(struct ip_fw
*curr_rule
, struct ip_old_fw
*rule_vers0
)
1296 struct ip_fw_compat rule_vers1
;
1298 ipfw_version_latest_to_one(curr_rule
, &rule_vers1
);
1300 bzero(rule_vers0
, sizeof(struct ip_old_fw
));
1301 bcopy(&rule_vers1
.fw_uar_compat
, &rule_vers0
->fw_uar
, sizeof(rule_vers1
.fw_uar_compat
));
1302 bcopy(&rule_vers1
.fw_in_if
, &rule_vers0
->fw_in_if
, sizeof(rule_vers1
.fw_in_if
));
1303 bcopy(&rule_vers1
.fw_out_if
, &rule_vers0
->fw_out_if
, sizeof(rule_vers1
.fw_out_if
));
1304 bcopy(&rule_vers1
.fw_un_compat
, &rule_vers0
->fw_un
, sizeof(rule_vers1
.fw_un_compat
));
1306 rule_vers0
->fw_pcnt
= rule_vers1
.fw_pcnt
;
1307 rule_vers0
->fw_bcnt
= rule_vers1
.fw_bcnt
;
1308 rule_vers0
->fw_src
= rule_vers1
.fw_src
;
1309 rule_vers0
->fw_dst
= rule_vers1
.fw_dst
;
1310 rule_vers0
->fw_smsk
= rule_vers1
.fw_smsk
;
1311 rule_vers0
->fw_dmsk
= rule_vers1
.fw_dmsk
;
1312 rule_vers0
->fw_number
= rule_vers1
.fw_number
;
1313 rule_vers0
->fw_flg
= rule_vers1
.fw_flg
;
1314 rule_vers0
->fw_ipopt
= rule_vers1
.fw_ipopt
;
1315 rule_vers0
->fw_ipnopt
= rule_vers1
.fw_ipnopt
;
1316 rule_vers0
->fw_tcpf
= rule_vers1
.fw_tcpf
;
1317 rule_vers0
->fw_tcpnf
= rule_vers1
.fw_tcpnf
;
1318 rule_vers0
->timestamp
= rule_vers1
.timestamp
;
1319 rule_vers0
->fw_prot
= rule_vers1
.fw_prot
;
1320 rule_vers0
->fw_nports
= rule_vers1
.fw_nports
;
1321 rule_vers0
->pipe_ptr
= rule_vers1
.pipe_ptr
;
1322 rule_vers0
->next_rule_ptr
= rule_vers1
.next_rule_ptr
;
1324 if (rule_vers1
.fw_ipflg
&& IP_FW_IF_TCPEST_COMPAT
) rule_vers0
->fw_tcpf
|= IP_OLD_FW_TCPF_ESTAB
;
1328 ipfw_convert_from_latest(struct ip_fw
*curr_rule
, void *old_rule
, u_int32_t api_version
)
1330 switch (api_version
) {
1331 case IP_FW_VERSION_0
:
1333 struct ip_old_fw
*rule_vers0
= old_rule
;
1335 ipfw_version_latest_to_zero(curr_rule
, rule_vers0
);
1338 case IP_FW_VERSION_1
:
1340 struct ip_fw_compat
*rule_vers1
= old_rule
;
1342 ipfw_version_latest_to_one(curr_rule
, rule_vers1
);
1345 case IP_FW_CURRENT_API_VERSION
:
1346 /* ipfw2 for now, don't need to do anything */
1350 /* unknown version */
1356 /* ********************************************
1357 * *********** Convert to Latest **************
1358 * ********************************************/
1362 ipfw_check_vers1_struct(struct ip_fw_compat
*frwl
)
1364 /* Check for invalid flag bits */
1365 if ((frwl
->fw_flg
& ~IP_FW_F_MASK_COMPAT
) != 0) {
1367 printf(("%s undefined flag bits set (flags=%x)\n",
1368 err_prefix, frwl->fw_flg));
1372 if (frwl
->fw_flg
== IP_FW_F_CHECK_S_COMPAT
) {
1376 /* Must apply to incoming or outgoing (or both) */
1377 if (!(frwl
->fw_flg
& (IP_FW_F_IN_COMPAT
| IP_FW_F_OUT_COMPAT
))) {
1379 printf(("%s neither in nor out\n", err_prefix));
1383 /* Empty interface name is no good */
1384 if (((frwl
->fw_flg
& IP_FW_F_IIFNAME_COMPAT
)
1385 && !*frwl
->fw_in_if
.fu_via_if_compat
.name
)
1386 || ((frwl
->fw_flg
& IP_FW_F_OIFNAME_COMPAT
)
1387 && !*frwl
->fw_out_if
.fu_via_if_compat
.name
)) {
1389 printf(("%s empty interface name\n", err_prefix));
1393 /* Sanity check interface matching */
1394 if ((frwl
->fw_flg
& IF_FW_F_VIAHACK_COMPAT
) == IF_FW_F_VIAHACK_COMPAT
) {
1395 ; /* allow "via" backwards compatibility */
1396 } else if ((frwl
->fw_flg
& IP_FW_F_IN_COMPAT
)
1397 && (frwl
->fw_flg
& IP_FW_F_OIFACE_COMPAT
)) {
1399 printf(("%s outgoing interface check on incoming\n",
1404 /* Sanity check port ranges */
1405 if ((frwl
->fw_flg
& IP_FW_F_SRNG_COMPAT
) && IP_FW_GETNSRCP_COMPAT(frwl
) < 2) {
1407 printf(("%s src range set but n_src_p=%d\n",
1408 err_prefix, IP_FW_GETNSRCP_COMPAT(frwl)));
1412 if ((frwl
->fw_flg
& IP_FW_F_DRNG_COMPAT
) && IP_FW_GETNDSTP_COMPAT(frwl
) < 2) {
1414 printf(("%s dst range set but n_dst_p=%d\n",
1415 err_prefix, IP_FW_GETNDSTP_COMPAT(frwl)));
1419 if (IP_FW_GETNSRCP_COMPAT(frwl
) + IP_FW_GETNDSTP_COMPAT(frwl
) > IP_FW_MAX_PORTS_COMPAT
) {
1421 printf(("%s too many ports (%d+%d)\n",
1422 err_prefix, IP_FW_GETNSRCP_COMPAT(frwl), IP_FW_GETNDSTP_COMPAT(frwl)));
1427 * Protocols other than TCP/UDP don't use port range
1429 if ((frwl
->fw_prot
!= IPPROTO_TCP
) &&
1430 (frwl
->fw_prot
!= IPPROTO_UDP
) &&
1431 (IP_FW_GETNSRCP_COMPAT(frwl
) || IP_FW_GETNDSTP_COMPAT(frwl
))) {
1433 printf(("%s port(s) specified for non TCP/UDP rule\n",
1440 * Rather than modify the entry to make such entries work,
1441 * we reject this rule and require user level utilities
1442 * to enforce whatever policy they deem appropriate.
1444 if ((frwl
->fw_src
.s_addr
& (~frwl
->fw_smsk
.s_addr
)) ||
1445 (frwl
->fw_dst
.s_addr
& (~frwl
->fw_dmsk
.s_addr
))) {
1447 printf(("%s rule never matches\n", err_prefix));
1452 if ((frwl
->fw_flg
& IP_FW_F_FRAG_COMPAT
) &&
1453 (frwl
->fw_prot
== IPPROTO_UDP
|| frwl
->fw_prot
== IPPROTO_TCP
)) {
1454 if (frwl
->fw_nports
) {
1456 printf(("%s cannot mix 'frag' and ports\n", err_prefix));
1460 if (frwl
->fw_prot
== IPPROTO_TCP
&&
1461 frwl
->fw_tcpf
!= frwl
->fw_tcpnf
) {
1463 printf(("%s cannot mix 'frag' and TCP flags\n", err_prefix));
1469 /* Check command specific stuff */
1470 switch (frwl
->fw_flg
& IP_FW_F_COMMAND_COMPAT
)
1472 case IP_FW_F_REJECT_COMPAT
:
1473 if (frwl
->fw_reject_code_compat
>= 0x100
1474 && !(frwl
->fw_prot
== IPPROTO_TCP
1475 && frwl
->fw_reject_code_compat
== IP_FW_REJECT_RST_COMPAT
)) {
1477 printf(("%s unknown reject code\n", err_prefix));
1482 case IP_FW_F_DIVERT_COMPAT
: /* Diverting to port zero is invalid */
1483 case IP_FW_F_TEE_COMPAT
:
1484 case IP_FW_F_PIPE_COMPAT
: /* piping through 0 is invalid */
1485 case IP_FW_F_QUEUE_COMPAT
: /* piping through 0 is invalid */
1486 if (frwl
->fw_divert_port_compat
== 0) {
1488 printf(("%s can't divert to port 0\n", err_prefix));
1493 case IP_FW_F_DENY_COMPAT
:
1494 case IP_FW_F_ACCEPT_COMPAT
:
1495 case IP_FW_F_COUNT_COMPAT
:
1496 case IP_FW_F_SKIPTO_COMPAT
:
1497 case IP_FW_F_FWD_COMPAT
:
1498 case IP_FW_F_UID_COMPAT
:
1502 printf(("%s invalid command\n", err_prefix));
1511 ipfw_convert_to_cmds(struct ip_fw
*curr_rule
, struct ip_fw_compat
*compat_rule
)
1514 uint32_t actbuf
[255], cmdbuf
[255];
1515 ipfw_insn
*action
, *cmd
, *src
, *dst
;
1516 ipfw_insn
*have_state
= NULL
; /* track check-state or keep-state */
1518 if (!compat_rule
|| !curr_rule
|| !(curr_rule
->cmd
)) {
1522 /* preemptively check the old ip_fw rule to
1523 * make sure it's valid before starting to copy stuff
1525 if (ipfw_check_vers1_struct(compat_rule
)) {
1530 bzero(actbuf
, sizeof(actbuf
)); /* actions go here */
1531 bzero(cmdbuf
, sizeof(cmdbuf
));
1533 /* fill in action */
1534 action
= (ipfw_insn
*)actbuf
;
1536 u_int flag
= compat_rule
->fw_flg
;
1538 action
->len
= 1; /* default */
1540 if (flag
& IP_FW_F_CHECK_S_COMPAT
) {
1541 have_state
= action
;
1542 action
->opcode
= O_CHECK_STATE
;
1545 switch (flag
& IP_FW_F_COMMAND_COMPAT
) {
1546 case IP_FW_F_ACCEPT_COMPAT
:
1547 action
->opcode
= O_ACCEPT
;
1549 case IP_FW_F_COUNT_COMPAT
:
1550 action
->opcode
= O_COUNT
;
1552 case IP_FW_F_PIPE_COMPAT
:
1553 action
->opcode
= O_PIPE
;
1554 action
->len
= F_INSN_SIZE(ipfw_insn_pipe
);
1555 action
->arg1
= compat_rule
->fw_divert_port_compat
;
1557 case IP_FW_F_QUEUE_COMPAT
:
1558 action
->opcode
= O_QUEUE
;
1559 action
->len
= F_INSN_SIZE(ipfw_insn_pipe
);
1560 action
->arg1
= compat_rule
->fw_divert_port_compat
;
1562 case IP_FW_F_SKIPTO_COMPAT
:
1563 action
->opcode
= O_SKIPTO
;
1564 action
->arg1
= compat_rule
->fw_skipto_rule_compat
;
1566 case IP_FW_F_DIVERT_COMPAT
:
1567 action
->opcode
= O_DIVERT
;
1568 action
->arg1
= compat_rule
->fw_divert_port_compat
;
1570 case IP_FW_F_TEE_COMPAT
:
1571 action
->opcode
= O_TEE
;
1572 action
->arg1
= compat_rule
->fw_divert_port_compat
;
1574 case IP_FW_F_FWD_COMPAT
:
1576 ipfw_insn_sa
*p
= (ipfw_insn_sa
*)action
;
1578 action
->opcode
= O_FORWARD_IP
;
1579 action
->len
= F_INSN_SIZE(ipfw_insn_sa
);
1581 p
->sa
.sin_len
= compat_rule
->fw_fwd_ip_compat
.sin_len
;
1582 p
->sa
.sin_family
= compat_rule
->fw_fwd_ip_compat
.sin_family
;
1583 p
->sa
.sin_port
= compat_rule
->fw_fwd_ip_compat
.sin_port
;
1584 p
->sa
.sin_addr
= compat_rule
->fw_fwd_ip_compat
.sin_addr
;
1588 case IP_FW_F_DENY_COMPAT
:
1589 action
->opcode
= O_DENY
;
1592 case IP_FW_F_REJECT_COMPAT
:
1593 action
->opcode
= O_REJECT
;
1594 action
->arg1
= compat_rule
->fw_reject_code_compat
;
1597 action
->opcode
= O_NOP
;
1602 /* action is mandatory */
1603 if (action
->opcode
== O_NOP
) {
1607 action
= next_cmd(action
);
1610 cmd
= (ipfw_insn
*)cmdbuf
;
1612 /* this is O_CHECK_STATE, we're done */
1618 ipfw_insn
*prev
= NULL
;
1619 u_int flag
= compat_rule
->fw_flg
;
1622 if (flag
& IP_FW_F_PRN_COMPAT
) {
1623 ipfw_insn_log
*c
= (ipfw_insn_log
*)cmd
;
1625 cmd
->opcode
= O_LOG
;
1626 cmd
->len
|= F_INSN_SIZE(ipfw_insn_log
);
1627 c
->max_log
= compat_rule
->fw_logamount
;
1630 cmd
= next_cmd(cmd
);
1634 if (compat_rule
->fw_prot
!= 0) {
1635 fill_cmd(cmd
, O_PROTO
, compat_rule
->fw_prot
);
1637 cmd
= next_cmd(cmd
);
1641 if (flag
& IP_FW_F_SME_COMPAT
) {
1642 cmd
->opcode
= O_IP_SRC_ME
;
1643 cmd
->len
|= F_INSN_SIZE(ipfw_insn
);
1644 if (flag
& IP_FW_F_INVSRC_COMPAT
) {
1645 cmd
->len
^= F_NOT
; /* toggle F_NOT */
1649 cmd
= next_cmd(cmd
);
1651 if (compat_rule
->fw_smsk
.s_addr
!= 0) {
1653 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
1655 ip
->addr
= compat_rule
->fw_src
;
1656 ip
->mask
= compat_rule
->fw_smsk
;
1657 cmd
->opcode
= O_IP_SRC_MASK
;
1658 cmd
->len
|= F_INSN_SIZE(ipfw_insn_ip
); /* double check this */
1661 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
; /* alias for cmd */
1663 if (compat_rule
->fw_src
.s_addr
== 0) {
1665 cmd32
->o
.len
&= ~F_LEN_MASK
; /* zero len */
1667 cmd32
->d
[0] = compat_rule
->fw_src
.s_addr
;
1668 cmd32
->o
.opcode
= O_IP_SRC
;
1669 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
1673 if (flag
& IP_FW_F_INVSRC_COMPAT
) {
1674 cmd
->len
^= F_NOT
; /* toggle F_NOT */
1677 if (F_LEN(cmd
) != 0) { /* !any */
1679 cmd
= next_cmd(cmd
);
1685 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
1686 uint16_t *p
= ports
->ports
;
1688 nports
= IP_FW_GETNSRCP_COMPAT(compat_rule
),
1691 cmd
->opcode
= O_IP_SRCPORT
;
1692 for (i
= 0; i
< nports
; i
++) {
1693 if (((flag
& IP_FW_F_SRNG_COMPAT
) ||
1694 (flag
& IP_FW_F_SMSK_COMPAT
)) && !have_range
) {
1695 p
[0] = compat_rule
->fw_uar_compat
.fw_pts
[i
++];
1696 p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
1699 p
[0] = p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
1706 ports
->o
.len
|= j
+1; /* leave F_NOT and F_OR untouched */
1710 cmd
= next_cmd(cmd
);
1714 if (flag
& IP_FW_F_DME_COMPAT
) {
1715 cmd
->opcode
= O_IP_DST_ME
;
1716 cmd
->len
|= F_INSN_SIZE(ipfw_insn
);
1717 if (flag
& IP_FW_F_INVDST_COMPAT
) {
1718 cmd
->len
^= F_NOT
; /* toggle F_NOT */
1722 cmd
= next_cmd(cmd
);
1724 if (compat_rule
->fw_dmsk
.s_addr
!= 0) {
1726 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
1728 ip
->addr
= compat_rule
->fw_dst
;
1729 ip
->mask
= compat_rule
->fw_dmsk
;
1730 cmd
->opcode
= O_IP_DST_MASK
;
1731 cmd
->len
|= F_INSN_SIZE(ipfw_insn_ip
); /* double check this */
1734 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
; /* alias for cmd */
1736 if (compat_rule
->fw_dst
.s_addr
== 0) {
1738 cmd32
->o
.len
&= ~F_LEN_MASK
; /* zero len */
1740 cmd32
->d
[0] = compat_rule
->fw_dst
.s_addr
;
1741 cmd32
->o
.opcode
= O_IP_DST
;
1742 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
1746 if (flag
& IP_FW_F_INVDST_COMPAT
) {
1747 cmd
->len
^= F_NOT
; /* toggle F_NOT */
1750 if (F_LEN(cmd
) != 0) { /* !any */
1752 cmd
= next_cmd(cmd
);
1758 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
1759 uint16_t *p
= ports
->ports
;
1760 int i
= IP_FW_GETNSRCP_COMPAT(compat_rule
),
1762 nports
= (IP_FW_GETNDSTP_COMPAT(compat_rule
) + i
),
1765 cmd
->opcode
= O_IP_DSTPORT
;
1766 for (; i
< nports
; i
++, p
+= 2) {
1767 if (((flag
& IP_FW_F_DRNG_COMPAT
) ||
1768 (flag
& IP_FW_F_DMSK_COMPAT
)) && !have_range
) {
1770 p
[0] = compat_rule
->fw_uar_compat
.fw_pts
[i
++];
1771 p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
1774 p
[0] = p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
1780 ports
->o
.len
|= j
+1; /* leave F_NOT and F_OR untouched */
1784 cmd
= next_cmd(cmd
);
1787 if (flag
& IP_FW_F_UID_COMPAT
) {
1788 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
; /* alias for cmd */
1790 cmd32
->o
.opcode
= O_UID
;
1791 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
1792 cmd32
->d
[0] = compat_rule
->fw_uid
;
1795 cmd
= next_cmd(cmd
);
1798 if (flag
& IP_FW_F_KEEP_S_COMPAT
) {
1800 fill_cmd(cmd
, O_KEEP_STATE
, 0);
1803 cmd
= next_cmd(cmd
);
1805 if (flag
& IP_FW_BRIDGED_COMPAT
) {
1806 fill_cmd(cmd
, O_LAYER2
, 0);
1809 cmd
= next_cmd(cmd
);
1812 if ((flag
& IF_FW_F_VIAHACK_COMPAT
) == IF_FW_F_VIAHACK_COMPAT
) {
1814 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1815 union ip_fw_if_compat ifu
= compat_rule
->fw_in_if
;
1817 cmd
->opcode
= O_VIA
;
1818 ifcmd
->o
.len
|= F_INSN_SIZE(ipfw_insn_if
);
1820 if (ifu
.fu_via_ip
.s_addr
== 0) {
1822 ifcmd
->name
[0] = '\0';
1825 else if (compat_rule
->fw_flg
& IP_FW_F_IIFNAME_COMPAT
) {
1827 strncpy(ifcmd
->name
, ifu
.fu_via_if_compat
.name
, sizeof(ifcmd
->name
));
1828 ifcmd
->p
.unit
= ifu
.fu_via_if_compat
.unit
;
1831 ifcmd
->p
.ip
= ifu
.fu_via_ip
;
1835 cmd
= next_cmd(cmd
);
1837 if (flag
& IP_FW_F_IN_COMPAT
) {
1838 fill_cmd(cmd
, O_IN
, 0);
1841 cmd
= next_cmd(cmd
);
1843 if (flag
& IP_FW_F_OUT_COMPAT
) {
1844 /* if the previous command was O_IN, and this
1845 * is being set as well, it's equivalent to not
1846 * having either command, so let's back up prev
1847 * to the cmd before it and move cmd to prev.
1849 if (prev
->opcode
== O_IN
) {
1851 bzero(cmd
, sizeof(*cmd
));
1853 cmd
->len
^= F_NOT
; /* toggle F_NOT */
1854 fill_cmd(cmd
, O_IN
, 0);
1857 cmd
= next_cmd(cmd
);
1860 if (flag
& IP_FW_F_OIFACE_COMPAT
) {
1862 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1863 union ip_fw_if_compat ifu
= compat_rule
->fw_out_if
;
1865 cmd
->opcode
= O_XMIT
;
1866 ifcmd
->o
.len
|= F_INSN_SIZE(ipfw_insn_if
);
1868 if (ifu
.fu_via_ip
.s_addr
== 0) {
1870 ifcmd
->name
[0] = '\0';
1873 else if (flag
& IP_FW_F_OIFNAME_COMPAT
) {
1875 strncpy(ifcmd
->name
, ifu
.fu_via_if_compat
.name
, sizeof(ifcmd
->name
));
1876 ifcmd
->p
.unit
= ifu
.fu_via_if_compat
.unit
;
1879 ifcmd
->p
.ip
= ifu
.fu_via_ip
;
1883 cmd
= next_cmd(cmd
);
1885 else if (flag
& IP_FW_F_IIFACE_COMPAT
) {
1887 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1888 union ip_fw_if_compat ifu
= compat_rule
->fw_in_if
;
1890 cmd
->opcode
= O_RECV
;
1891 ifcmd
->o
.len
|= F_INSN_SIZE(ipfw_insn_if
);
1893 if (ifu
.fu_via_ip
.s_addr
== 0) {
1895 ifcmd
->name
[0] = '\0';
1898 else if (flag
& IP_FW_F_IIFNAME_COMPAT
) {
1900 strncpy(ifcmd
->name
, ifu
.fu_via_if_compat
.name
, sizeof(ifcmd
->name
));
1901 ifcmd
->p
.unit
= ifu
.fu_via_if_compat
.unit
;
1904 ifcmd
->p
.ip
= ifu
.fu_via_ip
;
1908 cmd
= next_cmd(cmd
);
1912 if (flag
& IP_FW_F_FRAG_COMPAT
) {
1913 fill_cmd(cmd
, O_FRAG
, 0);
1916 cmd
= next_cmd(cmd
);
1920 if (compat_rule
->fw_ipopt
!= 0 || compat_rule
->fw_ipnopt
!= 0) {
1921 fill_cmd(cmd
, O_IPOPT
, (compat_rule
->fw_ipopt
& 0xff) |
1922 (compat_rule
->fw_ipnopt
& 0xff) << 8);
1925 cmd
= next_cmd(cmd
);
1928 if (compat_rule
->fw_prot
== IPPROTO_TCP
) {
1929 if (compat_rule
->fw_ipflg
& IP_FW_IF_TCPEST_COMPAT
) {
1930 fill_cmd(cmd
, O_ESTAB
, 0);
1933 cmd
= next_cmd(cmd
);
1936 /* TCP options and flags */
1937 if (compat_rule
->fw_tcpf
!= 0 || compat_rule
->fw_tcpnf
!= 0) {
1938 if ((compat_rule
->fw_tcpf
& IP_FW_TCPF_SYN_COMPAT
) &&
1939 compat_rule
->fw_tcpnf
& IP_FW_TCPF_ACK_COMPAT
) {
1940 fill_cmd(cmd
, O_TCPFLAGS
, (TH_SYN
) | ( (TH_ACK
) & 0xff) <<8);
1943 cmd
= next_cmd(cmd
);
1946 fill_cmd(cmd
, O_TCPFLAGS
, (compat_rule
->fw_tcpf
& 0xff) |
1947 (compat_rule
->fw_tcpnf
& 0xff) << 8);
1950 cmd
= next_cmd(cmd
);
1953 if (compat_rule
->fw_tcpopt
!= 0 || compat_rule
->fw_tcpnopt
!= 0) {
1954 fill_cmd(cmd
, O_TCPOPTS
, (compat_rule
->fw_tcpopt
& 0xff) |
1955 (compat_rule
->fw_tcpnopt
& 0xff) << 8);
1958 cmd
= next_cmd(cmd
);
1963 /* XXX: check this */
1964 if (flag
& IP_FW_F_ICMPBIT_COMPAT
) {
1966 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
; /* alias for cmd */
1968 cmd32
->o
.opcode
= O_ICMPTYPE
;
1969 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
1971 for (i
= 0; i
< IP_FW_ICMPTYPES_DIM_COMPAT
; i
++) {
1972 cmd32
->d
[0] |= compat_rule
->fw_uar_compat
.fw_icmptypes
[i
];
1976 cmd
= next_cmd(cmd
);
1978 } /* end commands */
1981 /* finally, copy everything into the current
1982 * rule buffer in the right order.
1984 dst
= curr_rule
->cmd
;
1986 /* first, do match probability */
1987 if (compat_rule
->fw_flg
& IP_FW_F_RND_MATCH_COMPAT
) {
1988 dst
->opcode
= O_PROB
;
1990 *((int32_t *)(dst
+1)) = compat_rule
->pipe_ptr
;
1994 /* generate O_PROBE_STATE if necessary */
1995 if (have_state
&& have_state
->opcode
!= O_CHECK_STATE
) {
1996 fill_cmd(dst
, O_PROBE_STATE
, 0);
1997 dst
= next_cmd(dst
);
2001 * copy all commands but O_LOG, O_KEEP_STATE
2003 for (src
= (ipfw_insn
*)cmdbuf
; src
!= cmd
; src
+= k
) {
2006 switch (src
->opcode
) {
2011 bcopy(src
, dst
, k
* sizeof(uint32_t));
2017 * put back the have_state command as last opcode
2019 if (have_state
&& have_state
->opcode
!= O_CHECK_STATE
) {
2020 k
= F_LEN(have_state
);
2021 bcopy(have_state
, dst
, k
* sizeof(uint32_t));
2026 * start action section
2028 curr_rule
->act_ofs
= dst
- curr_rule
->cmd
;
2031 * put back O_LOG if necessary
2033 src
= (ipfw_insn
*)cmdbuf
;
2034 if (src
->opcode
== O_LOG
) {
2036 bcopy(src
, dst
, k
* sizeof(uint32_t));
2041 * copy all other actions
2043 for (src
= (ipfw_insn
*)actbuf
; src
!= action
; src
+= k
) {
2045 bcopy(src
, dst
, k
* sizeof(uint32_t));
2049 curr_rule
->cmd_len
= (uint32_t *)dst
- (uint32_t *)(curr_rule
->cmd
);
2055 ipfw_version_one_to_version_two(struct sockopt
*sopt
, struct ip_fw
*curr_rule
,
2056 struct ip_fw_compat
*rule_vers1
)
2059 struct ip_fw_compat
*rule_ptr
;
2060 struct ip_fw_compat rule
;
2063 rule_ptr
= rule_vers1
;
2066 /* do some basic size checking here, more extensive checking later */
2067 if (!sopt
->sopt_val
|| sopt
->sopt_valsize
< sizeof(struct ip_fw_compat
))
2070 if ((err
= sooptcopyin(sopt
, &rule
, sizeof(struct ip_fw_compat
),
2071 sizeof(struct ip_fw_compat
)))) {
2078 /* deal with commands */
2079 ipfw_convert_to_cmds(curr_rule
, rule_ptr
);
2081 curr_rule
->version
= IP_FW_CURRENT_API_VERSION
;
2082 curr_rule
->context
= rule_ptr
->context
;
2083 curr_rule
->rulenum
= rule_ptr
->fw_number
;
2084 curr_rule
->pcnt
= rule_ptr
->fw_pcnt
;
2085 curr_rule
->bcnt
= rule_ptr
->fw_bcnt
;
2086 curr_rule
->timestamp
= rule_ptr
->timestamp
;
2089 #if FW2_DEBUG_VERBOSE
2090 ipfw_print_vers2_struct(curr_rule
);
2091 #endif /* FW2_DEBUG_VERBOSE */
2096 /* This converts to whatever the latest version is. Currently the
2097 * latest version of the firewall is ipfw2.
2100 ipfw_version_one_to_latest(struct sockopt
*sopt
, struct ip_fw
*curr_rule
, struct ip_fw_compat
*rule_vers1
)
2104 /* if rule_vers1 is not null then this is coming from
2105 * ipfw_version_zero_to_latest(), so pass that along;
2106 * otherwise let ipfw_version_one_to_version_two()
2107 * get the rule from sopt.
2109 err
= ipfw_version_one_to_version_two(sopt
, curr_rule
, rule_vers1
);
2115 ipfw_version_zero_to_one(struct ip_old_fw
*rule_vers0
, struct ip_fw_compat
*rule_vers1
)
2117 bzero(rule_vers1
, sizeof(struct ip_fw_compat
));
2118 bcopy(&rule_vers0
->fw_uar
, &rule_vers1
->fw_uar_compat
, sizeof(rule_vers0
->fw_uar
));
2119 bcopy(&rule_vers0
->fw_in_if
, &rule_vers1
->fw_in_if
, sizeof(rule_vers0
->fw_in_if
));
2120 bcopy(&rule_vers0
->fw_out_if
, &rule_vers1
->fw_out_if
, sizeof(rule_vers0
->fw_out_if
));
2121 bcopy(&rule_vers0
->fw_un
, &rule_vers1
->fw_un_compat
, sizeof(rule_vers0
->fw_un
));
2123 rule_vers1
->version
= 10;
2124 rule_vers1
->fw_pcnt
= rule_vers0
->fw_pcnt
;
2125 rule_vers1
->fw_bcnt
= rule_vers0
->fw_bcnt
;
2126 rule_vers1
->fw_src
= rule_vers0
->fw_src
;
2127 rule_vers1
->fw_dst
= rule_vers0
->fw_dst
;
2128 rule_vers1
->fw_smsk
= rule_vers0
->fw_smsk
;
2129 rule_vers1
->fw_dmsk
= rule_vers0
->fw_dmsk
;
2130 rule_vers1
->fw_number
= rule_vers0
->fw_number
;
2131 rule_vers1
->fw_flg
= rule_vers0
->fw_flg
;
2132 rule_vers1
->fw_ipopt
= rule_vers0
->fw_ipopt
;
2133 rule_vers1
->fw_ipnopt
= rule_vers0
->fw_ipnopt
;
2134 rule_vers1
->fw_tcpf
= rule_vers0
->fw_tcpf
& ~IP_OLD_FW_TCPF_ESTAB
;
2135 rule_vers1
->fw_tcpnf
= rule_vers0
->fw_tcpnf
;
2136 rule_vers1
->timestamp
= rule_vers0
->timestamp
;
2137 rule_vers1
->fw_prot
= rule_vers0
->fw_prot
;
2138 rule_vers1
->fw_nports
= rule_vers0
->fw_nports
;
2139 rule_vers1
->pipe_ptr
= rule_vers0
->pipe_ptr
;
2140 rule_vers1
->next_rule_ptr
= rule_vers0
->next_rule_ptr
;
2141 rule_vers1
->fw_ipflg
= (rule_vers0
->fw_tcpf
& IP_OLD_FW_TCPF_ESTAB
) ? IP_FW_IF_TCPEST_COMPAT
: 0;
2144 /* first convert to version one, then to version two */
2146 ipfw_version_zero_to_latest(struct sockopt
*sopt
, struct ip_fw
*curr_rule
)
2149 struct ip_old_fw rule_vers0
;
2150 struct ip_fw_compat rule_vers1
;
2152 if (sopt
->sopt_name
== IP_OLD_FW_GET
||
2153 sopt
->sopt_name
== IP_OLD_FW_FLUSH
||
2154 sopt
->sopt_val
== USER_ADDR_NULL
) {
2155 /* In the old-style API, it was legal to not pass in a rule
2156 * structure for certain firewall operations (e.g. flush,
2157 * reset log). If that's the situation, we pretend we received
2158 * a blank structure. */
2159 bzero(curr_rule
, sizeof(struct ip_fw
));
2160 curr_rule
->version
= 10;
2163 if (!sopt
->sopt_val
|| sopt
->sopt_valsize
< sizeof(struct ip_old_fw
)) {
2167 err
= sooptcopyin(sopt
, &rule_vers0
, sizeof(struct ip_old_fw
),
2168 sizeof(struct ip_old_fw
));
2173 ipfw_version_zero_to_one(&rule_vers0
, &rule_vers1
);
2176 return (ipfw_version_one_to_latest(sopt
, curr_rule
, &rule_vers1
));
2179 /* rule is a u_int32_t buffer[255] into which the converted
2180 * (if necessary) rules go.
2183 ipfw_convert_to_latest(struct sockopt
*sopt
, struct ip_fw
*curr_rule
, int api_version
)
2187 /* the following functions copy the rules passed in and
2188 * convert to latest structures based on version
2190 switch (api_version
) {
2191 case IP_FW_VERSION_0
:
2192 /* this is the oldest version we support */
2193 err
= ipfw_version_zero_to_latest(sopt
, curr_rule
);
2196 case IP_FW_VERSION_1
:
2197 /* this is the version supported in Panther */
2198 err
= ipfw_version_one_to_latest(sopt
, curr_rule
, NULL
);
2201 case IP_FW_CURRENT_API_VERSION
:
2203 /* do nothing here... */
2207 /* unrecognized/unsupported version */
2216 ipfw_get_command_and_version(struct sockopt
*sopt
, int *command
, u_int32_t
*api_version
)
2220 u_int32_t vers
= IP_FW_VERSION_NONE
;
2222 /* first deal with the oldest version */
2223 if (sopt
->sopt_name
== IP_OLD_FW_GET
) {
2224 vers
= IP_FW_VERSION_0
;
2227 else if (sopt
->sopt_name
== IP_OLD_FW_FLUSH
) {
2228 vers
= IP_FW_VERSION_0
;
2231 else if (sopt
->sopt_name
== IP_OLD_FW_ZERO
) {
2232 vers
= IP_FW_VERSION_0
;
2235 else if (sopt
->sopt_name
== IP_OLD_FW_ADD
) {
2236 vers
= IP_FW_VERSION_0
;
2239 else if (sopt
->sopt_name
== IP_OLD_FW_DEL
) {
2240 vers
= IP_FW_VERSION_0
;
2243 else if (sopt
->sopt_name
== IP_OLD_FW_RESETLOG
) {
2244 vers
= IP_FW_VERSION_0
;
2245 cmd
= IP_FW_RESETLOG
;
2248 cmd
= sopt
->sopt_name
;
2251 if (vers
== IP_FW_VERSION_NONE
) {
2252 /* working off the fact that the offset
2253 * is the same in both structs.
2257 if (!sopt
->sopt_val
|| sopt
->sopt_valsize
< sizeof(struct ip_fw
))
2260 if ((err
= sooptcopyin(sopt
, &rule
, sizeof(struct ip_fw
),
2261 sizeof(struct ip_fw
)))) {
2265 vers
= rule
.version
;
2273 *api_version
= vers
;