1 /* IPFW2 Backward Compatibility */
3 /* Convert to and from IPFW2 structures. */
8 #include <sys/socket.h>
9 #include <sys/socketvar.h>
11 #include <sys/types.h>
14 #include <netinet/in.h>
15 #include <netinet/in_systm.h>
16 #include <netinet/ip.h>
17 #include <netinet/ip_icmp.h>
18 #include <netinet/ip_fw.h>
19 #include <netinet/tcp.h>
21 #include "ip_fw2_compat.h"
23 #define FW2_DEBUG_VERBOSE 0
26 * _s_x is a structure that stores a string <-> token pairs, used in
27 * various places in the parser. Entries are stored in arrays,
28 * with an entry with s=NULL as terminator.
29 * The search routines are match_token() and match_value().
30 * Often, an element with x=0 contains an error string.
38 #define NO_VERSION_STR "IP_FW_VERSION_NONE"
39 #define VERSION_ZERO_STR "IP_FW_VERSION_0"
40 #define VERSION_ONE_STR "IP_FW_VERSION_1"
41 #define CURRENT_API_VERSION_STR "IP_FW_CURRENT_API_VERSION"
43 static struct _s_x f_tcpflags
[] = {
54 static struct _s_x f_tcpopts
[] = {
55 { "mss", IP_FW_TCPOPT_MSS
},
56 { "maxseg", IP_FW_TCPOPT_MSS
},
57 { "window", IP_FW_TCPOPT_WINDOW
},
58 { "sack", IP_FW_TCPOPT_SACK
},
59 { "ts", IP_FW_TCPOPT_TS
},
60 { "timestamp", IP_FW_TCPOPT_TS
},
61 { "cc", IP_FW_TCPOPT_CC
},
67 * IP options span the range 0 to 255 so we need to remap them
68 * (though in fact only the low 5 bits are significant).
70 static struct _s_x f_ipopts
[] = {
71 { "ssrr", IP_FW_IPOPT_SSRR
},
72 { "lsrr", IP_FW_IPOPT_LSRR
},
73 { "rr", IP_FW_IPOPT_RR
},
74 { "ts", IP_FW_IPOPT_TS
},
79 static struct _s_x f_iptos
[] = {
80 { "lowdelay", IPTOS_LOWDELAY
},
81 { "throughput", IPTOS_THROUGHPUT
},
82 { "reliability", IPTOS_RELIABILITY
},
83 { "mincost", IPTOS_MINCOST
},
84 { "congestion", IPTOS_CE
},
85 { "ecntransport", IPTOS_ECT
},
86 { "ip tos option", 0},
90 static struct _s_x limit_masks
[] = {
91 {"all", DYN_SRC_ADDR
|DYN_SRC_PORT
|DYN_DST_ADDR
|DYN_DST_PORT
},
92 {"src-addr", DYN_SRC_ADDR
},
93 {"src-port", DYN_SRC_PORT
},
94 {"dst-addr", DYN_DST_ADDR
},
95 {"dst-port", DYN_DST_PORT
},
100 ipfw_print_fw_flags(u_int flags
)
103 switch (flags
& IP_FW_F_COMMAND_COMPAT
) {
104 case IP_FW_F_ACCEPT_COMPAT
:
105 printf("IP_FW_F_ACCEPT_COMPAT\n");
107 case IP_FW_F_COUNT_COMPAT
:
108 printf("IP_FW_F_COUNT_COMPAT\n");
110 case IP_FW_F_PIPE_COMPAT
:
111 printf("IP_FW_F_PIPE_COMPAT\n");
113 case IP_FW_F_QUEUE_COMPAT
:
114 printf("IP_FW_F_QUEUE_COMPAT\n");
116 case IP_FW_F_SKIPTO_COMPAT
:
117 printf("IP_FW_F_SKIPTO_COMPAT\n");
119 case IP_FW_F_DIVERT_COMPAT
:
120 printf("IP_FW_F_DIVERT_COMPAT\n");
122 case IP_FW_F_TEE_COMPAT
:
123 printf("IP_FW_F_TEE_COMPAT\n");
125 case IP_FW_F_FWD_COMPAT
:
126 printf("IP_FW_F_FWD_COMPAT\n");
128 case IP_FW_F_DENY_COMPAT
:
129 printf("IP_FW_F_DENY_COMPAT\n");
131 case IP_FW_F_REJECT_COMPAT
:
132 printf("IP_FW_F_REJECT_COMPAT\n");
134 case IP_FW_F_CHECK_S_COMPAT
:
135 printf("IP_FW_F_CHECK_S_COMPAT\n");
138 printf("No action given\n");
143 if (flags
& IP_FW_F_IN_COMPAT
) {
144 printf("IP_FW_F_IN_COMPAT\n");
146 if (flags
& IP_FW_F_OUT_COMPAT
) {
147 printf("IP_FW_F_OUT_COMPAT\n");
149 if (flags
& IP_FW_F_IIFACE_COMPAT
) {
150 printf("IP_FW_F_IIFACE_COMPAT\n");
152 if (flags
& IP_FW_F_OIFACE_COMPAT
) {
153 printf("IP_FW_F_OIFACE_COMPAT\n");
155 if (flags
& IP_FW_F_PRN_COMPAT
) {
156 printf("IP_FW_F_PRN_COMPAT\n");
158 if (flags
& IP_FW_F_SRNG_COMPAT
) {
159 printf("IP_FW_F_SRNG_COMPAT\n");
161 if (flags
& IP_FW_F_DRNG_COMPAT
) {
162 printf("IP_FW_F_DRNG_COMPAT\n");
164 if (flags
& IP_FW_F_FRAG_COMPAT
) {
165 printf("IP_FW_F_FRAG_COMPAT\n");
167 if (flags
& IP_FW_F_IIFNAME_COMPAT
) {
168 printf("IP_FW_F_IIFNAME_COMPAT\n");
170 if (flags
& IP_FW_F_OIFNAME_COMPAT
) {
171 printf("IP_FW_F_OIFNAME_COMPAT\n");
173 if (flags
& IP_FW_F_INVSRC_COMPAT
) {
174 printf("IP_FW_F_INVSRC_COMPAT\n");
176 if (flags
& IP_FW_F_INVDST_COMPAT
) {
177 printf("IP_FW_F_INVDST_COMPAT\n");
179 if (flags
& IP_FW_F_ICMPBIT_COMPAT
) {
180 printf("IP_FW_F_ICMPBIT_COMPAT\n");
182 if (flags
& IP_FW_F_UID_COMPAT
) {
183 printf("IP_FW_F_UID_COMPAT\n");
185 if (flags
& IP_FW_F_RND_MATCH_COMPAT
) {
186 printf("IP_FW_F_RND_MATCH_COMPAT\n");
188 if (flags
& IP_FW_F_SMSK_COMPAT
) {
189 printf("IP_FW_F_SMSK_COMPAT\n");
191 if (flags
& IP_FW_F_DMSK_COMPAT
) {
192 printf("IP_FW_F_DMSK_COMPAT\n");
194 if (flags
& IP_FW_BRIDGED_COMPAT
) {
195 printf("IP_FW_BRIDGED_COMPAT\n");
197 if (flags
& IP_FW_F_KEEP_S_COMPAT
) {
198 printf("IP_FW_F_KEEP_S_COMPAT\n");
200 if (flags
& IP_FW_F_CHECK_S_COMPAT
) {
201 printf("IP_FW_F_CHECK_S_COMPAT\n");
203 if (flags
& IP_FW_F_SME_COMPAT
) {
204 printf("IP_FW_F_SME_COMPAT\n");
206 if (flags
& IP_FW_F_DME_COMPAT
) {
207 printf("IP_FW_F_DME_COMPAT\n");
212 print_fw_version(u_int32_t api_version
)
214 switch (api_version
) {
215 case IP_FW_VERSION_0
:
216 printf("Version: %s\n", VERSION_ZERO_STR
);
218 case IP_FW_VERSION_1
:
219 printf("Version: %s\n", VERSION_ONE_STR
);
221 case IP_FW_CURRENT_API_VERSION
:
222 printf("Version: %s\n", CURRENT_API_VERSION_STR
);
224 case IP_FW_VERSION_NONE
:
225 printf("Version: %s\n", NO_VERSION_STR
);
228 printf("Unrecognized version\n");
234 ipfw_print_vers1_struct(struct ip_fw_compat
*vers1_rule
)
236 char ipv4str
[MAX_IPv4_STR_LEN
];
237 print_fw_version(vers1_rule
->version
);
238 printf("Rule #%d\n", vers1_rule
->fw_number
);
240 ipfw_print_fw_flags(vers1_rule
->fw_flg
);
242 printf("fw_pcnt: %d\n", vers1_rule
->fw_pcnt
);
243 printf("fw_bcnt: %d\n", vers1_rule
->fw_bcnt
);
244 printf("fw_src: %s\n",
245 inet_ntop(AF_INET
, &vers1_rule
->fw_src
, ipv4str
, sizeof(ipv4str
)));
246 printf("fw_dst: %s\n",
247 inet_ntop(AF_INET
, &vers1_rule
->fw_dst
, ipv4str
, sizeof(ipv4str
)));
248 printf("fw_smsk: %s\n",
249 inet_ntop(AF_INET
, &vers1_rule
->fw_smsk
, ipv4str
, sizeof(ipv4str
)));
250 printf("fw_dmsk: %s\n",
251 inet_ntop(AF_INET
, &vers1_rule
->fw_dmsk
, ipv4str
, sizeof(ipv4str
)));
253 if (vers1_rule
->fw_flg
& IP_FW_F_ICMPBIT_COMPAT
) {
260 type_index
< (IP_FW_ICMPTYPES_DIM_COMPAT
* sizeof(unsigned) * 8);
262 if (vers1_rule
->fw_uar_compat
.fw_icmptypes
[type_index
/ (sizeof(unsigned) * 8)] &
263 (1U << (type_index
% (sizeof(unsigned) * 8)))) {
264 printf("%c%d", first
== 1 ? ' ' : ',', type_index
);
271 nsp
= IP_FW_GETNSRCP_COMPAT(vers1_rule
);
272 for (i
= 0; i
< nsp
; i
++) {
273 printf("source ports: fw_uar_compat.fw_pts: %04x", vers1_rule
->fw_uar_compat
.fw_pts
[i
]);
274 if (i
== 0 && (vers1_rule
->fw_flg
& IP_FW_F_SRNG_COMPAT
))
276 else if (i
== 0 && (vers1_rule
->fw_flg
& IP_FW_F_SMSK_COMPAT
))
284 ndp
= IP_FW_GETNDSTP_COMPAT(vers1_rule
);
285 for (i
= 0; i
< ndp
; i
++) {
286 printf("source ports: fw_uar_compat.fw_pts: %04x", vers1_rule
->fw_uar_compat
.fw_pts
[nsp
+i
]);
287 if (i
== 0 && (vers1_rule
->fw_flg
& IP_FW_F_DRNG_COMPAT
))
289 else if (i
== 0 && (vers1_rule
->fw_flg
& IP_FW_F_DMSK_COMPAT
))
298 printf("fw_ipflg: %d\n", vers1_rule
->fw_ipflg
);
299 printf("fw_ipopt: %d\n", vers1_rule
->fw_ipopt
);
300 printf("fw_ipnopt: %d\n", vers1_rule
->fw_ipnopt
);
301 printf("fw_tcpopt: %d\n", vers1_rule
->fw_tcpopt
);
302 printf("fw_tcpnopt: %d\n", vers1_rule
->fw_tcpnopt
);
303 printf("fw_tcpf: %d\n", vers1_rule
->fw_tcpf
);
304 printf("fw_tcpnf: %d\n", vers1_rule
->fw_tcpnf
);
305 printf("timestamp: %d\n", vers1_rule
->timestamp
);
307 if ((vers1_rule
->fw_flg
& IF_FW_F_VIAHACK_COMPAT
) == IF_FW_F_VIAHACK_COMPAT
) {
308 printf("fw_in_if: ");
309 inet_ntop(AF_INET
, &vers1_rule
->fw_in_if
.fu_via_ip
, ipv4str
,
311 printf("fu_via_ip: %s\n", ipv4str
);
312 printf("fu_via_if_compat.name: %s\n", vers1_rule
->fw_in_if
.fu_via_if_compat
.name
);
313 printf("fu_via_if_compat.unit: %d\n", vers1_rule
->fw_in_if
.fu_via_if_compat
.unit
);
315 if (vers1_rule
->fw_flg
& IP_FW_F_IIFACE_COMPAT
) {
316 printf("fw_in_if: ");
317 printf("fu_via_ip: %s\n",
318 inet_ntop(AF_INET
, &vers1_rule
->fw_in_if
.fu_via_ip
, ipv4str
,
320 printf("fu_via_if_compat.name: %s\n", vers1_rule
->fw_in_if
.fu_via_if_compat
.name
);
321 printf("fu_via_if_compat.unit: %d\n", vers1_rule
->fw_in_if
.fu_via_if_compat
.unit
);
323 if (vers1_rule
->fw_flg
& IP_FW_F_OIFACE_COMPAT
) {
324 printf("fw_out_if: ");
325 printf("fu_via_ip: %s\n",
326 inet_ntop(AF_INET
, &vers1_rule
->fw_out_if
.fu_via_ip
,
327 ipv4str
, sizeof(ipv4str
)));
328 printf("fu_via_if_compat.name: %s\n", vers1_rule
->fw_out_if
.fu_via_if_compat
.name
);
329 printf("fu_via_if_compat.unit: %d\n", vers1_rule
->fw_out_if
.fu_via_if_compat
.unit
);
333 printf("fw_prot: %d\n", vers1_rule
->fw_prot
);
334 printf("fw_nports: %d\n", vers1_rule
->fw_nports
);
335 printf("pipe_ptr: %x\n", vers1_rule
->pipe_ptr
);
336 printf("next_rule_ptr: %x\n", vers1_rule
->next_rule_ptr
);
337 printf("fw_uid: %d\n", vers1_rule
->fw_uid
);
338 printf("fw_logamount: %d\n", vers1_rule
->fw_logamount
);
339 printf("fw_loghighest: %d\n", vers1_rule
->fw_loghighest
);
343 print_icmptypes(ipfw_insn_u32
*cmd
)
348 printf(" icmptypes");
349 for (i
= 0; i
< 32; i
++) {
350 if ( (cmd
->d
[0] & (1 << (i
))) == 0)
352 printf("%c%d", sep
, i
);
358 * print flags set/clear in the two bitmasks passed as parameters.
359 * There is a specialized check for f_tcpflags.
362 print_flags(char const *name
, ipfw_insn
*cmd
, struct _s_x
*list
)
364 char const *comma
= "";
366 uint8_t set
= cmd
->arg1
& 0xff;
367 uint8_t clear
= (cmd
->arg1
>> 8) & 0xff;
369 if (list
== f_tcpflags
&& set
== TH_SYN
&& clear
== TH_ACK
) {
374 printf(" %s ", name
);
375 for (i
=0; list
[i
].x
!= 0; i
++) {
376 if (set
& list
[i
].x
) {
378 printf("%s%s", comma
, list
[i
].s
);
381 if (clear
& list
[i
].x
) {
383 printf("%s!%s", comma
, list
[i
].s
);
390 contigmask(uint8_t *p
, int len
)
394 for (i
=0; i
<len
; i
++)
395 if ( (p
[i
/8] & (1 << (7 - (i%8
)))) == 0) /* first bit unset */
397 for (n
=i
+1; n
< len
; n
++)
398 if ( (p
[n
/8] & (1 << (7 - (n%8
)))) != 0)
399 return -1; /* mask not contiguous */
404 * Print the ip address contained in a command.
407 print_ip(ipfw_insn_ip
*cmd
)
409 int len
= F_LEN((ipfw_insn
*)cmd
);
410 uint32_t *a
= ((ipfw_insn_u32
*)cmd
)->d
;
411 char ipv4str
[MAX_IPv4_STR_LEN
];
413 printf("%s ", cmd
->o
.len
& F_NOT
? " not": "");
415 if (cmd
->o
.opcode
== O_IP_SRC_ME
|| cmd
->o
.opcode
== O_IP_DST_ME
) {
421 * len == 2 indicates a single IP, whereas lists of 1 or more
422 * addr/mask pairs have len = (2n+1). We convert len to n so we
423 * use that to count the number of entries.
425 for (len
= len
/ 2; len
> 0; len
--, a
+= 2) {
426 int mb
= /* mask length */
427 (cmd
->o
.opcode
== O_IP_SRC
|| cmd
->o
.opcode
== O_IP_DST
) ?
428 32 : contigmask((uint8_t *)&(a
[1]), 32);
429 if (mb
== 0) { /* any */
431 } else { /* numeric IP followed by some kind of mask */
432 printf("%s", inet_ntop(AF_INET
, &a
[0], ipv4str
, sizeof(ipv4str
)));
434 printf(":%s", inet_ntop(AF_INET
, &a
[1], ipv4str
, sizeof(ipv4str
)));
444 * prints a MAC address/mask pair
447 print_mac(uint8_t *addr
, uint8_t *mask
)
449 int l
= contigmask(mask
, 48);
454 printf(" %02x:%02x:%02x:%02x:%02x:%02x",
455 addr
[0], addr
[1], addr
[2], addr
[3], addr
[4], addr
[5]);
457 printf("&%02x:%02x:%02x:%02x:%02x:%02x",
458 mask
[0], mask
[1], mask
[2],
459 mask
[3], mask
[4], mask
[5]);
466 ipfw_print_vers2_struct(struct ip_fw
*vers2_rule
)
470 ipfw_insn_log
*logptr
= NULL
;
471 char ipv4str
[MAX_IPv4_STR_LEN
];
473 print_fw_version(vers2_rule
->version
);
475 printf("act_ofs: %d\n", vers2_rule
->act_ofs
);
476 printf("cmd_len: %d\n", vers2_rule
->cmd_len
);
477 printf("rulenum: %d\n", vers2_rule
->rulenum
);
478 printf("set: %d\n", vers2_rule
->set
);
479 printf("pcnt: %d\n", vers2_rule
->pcnt
);
480 printf("bcnt: %d\n", vers2_rule
->bcnt
);
481 printf("timestamp: %d\n", vers2_rule
->timestamp
);
484 * first print actions
486 for (l
= vers2_rule
->cmd_len
- vers2_rule
->act_ofs
, cmd
= ACTION_PTR(vers2_rule
);
487 l
> 0 ; l
-= F_LEN(cmd
), cmd
+= F_LEN(cmd
)) {
488 switch(cmd
->opcode
) {
490 printf("check-state");
506 if (cmd
->arg1
== ICMP_REJECT_RST
)
508 else if (cmd
->arg1
== ICMP_UNREACH_HOST
)
511 printf("unreach %u", cmd
->arg1
);
515 printf("skipto %u", cmd
->arg1
);
519 printf("pipe %u", cmd
->arg1
);
523 printf("queue %u", cmd
->arg1
);
527 printf("divert %u", cmd
->arg1
);
531 printf("tee %u", cmd
->arg1
);
536 ipfw_insn_sa
*s
= (ipfw_insn_sa
*)cmd
;
539 inet_ntop(AF_INET
, &s
->sa
.sin_addr
, ipv4str
,
542 printf(",%d", s
->sa
.sin_port
);
546 case O_LOG
: /* O_LOG is printed last */
547 logptr
= (ipfw_insn_log
*)cmd
;
551 printf("** unrecognized action %d len %d",
552 cmd
->opcode
, cmd
->len
);
556 if (logptr
->max_log
> 0)
557 printf(" log logamount %d", logptr
->max_log
);
563 * then print the body.
565 for (l
= vers2_rule
->act_ofs
, cmd
= vers2_rule
->cmd
;
566 l
> 0 ; l
-= F_LEN(cmd
) , cmd
+= F_LEN(cmd
)) {
568 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
;
570 switch(cmd
->opcode
) {
572 break; /* done already */
575 break; /* no need to print anything here */
579 ipfw_insn_mac
*m
= (ipfw_insn_mac
*)cmd
;
581 if (cmd
->len
& F_NOT
)
584 print_mac(m
->addr
, m
->mask
);
585 print_mac(m
->addr
+ 6, m
->mask
+ 6);
591 uint16_t *p
= ((ipfw_insn_u16
*)cmd
)->ports
;
594 for (i
= F_LEN((ipfw_insn
*)cmd
) - 1; i
> 0; i
--, p
+= 2) {
595 printf("0x%04x", p
[0]);
598 printf("0x%04x", p
[1]);
607 print_ip((ipfw_insn_ip
*)cmd
);
613 print_ip((ipfw_insn_ip
*)cmd
);
619 uint16_t *p
= ((ipfw_insn_u16
*)cmd
)->ports
;
622 for (i
= F_LEN((ipfw_insn
*)cmd
) - 1; i
> 0; i
--, p
+= 2) {
623 printf("0x%04x", p
[0]);
626 printf("0x%04x", p
[1]);
636 if (cmd
->len
& F_NOT
)
639 printf(" %u", cmd
->arg1
);
644 default: /*options ... */
646 if (cmd
->len
& F_NOT
&& cmd
->opcode
!= O_IN
)
648 switch(cmd
->opcode
) {
654 printf(cmd
->len
& F_NOT
? " out" : " O_IN");
665 ipfw_insn_if
*cmdif
= (ipfw_insn_if
*)cmd
;
667 if (cmd
->opcode
== O_XMIT
)
669 else if (cmd
->opcode
== O_RECV
)
671 else /* if (cmd->opcode == O_VIA) */
673 if (cmdif
->name
[0] == '\0') {
675 inet_ntop(AF_INET
, &cmdif
->p
.ip
, ipv4str
,
678 else if (cmdif
->p
.unit
== -1)
679 printf(" %s %s*", s
, cmdif
->name
);
681 printf(" %s %s%d", s
, cmdif
->name
,
688 printf(" ipid %u", cmd
->arg1
);
690 uint16_t *p
= ((ipfw_insn_u16
*)cmd
)->ports
;
693 for (i
= F_LEN((ipfw_insn
*)cmd
) - 1; i
> 0; i
--, p
+= 2) {
694 printf("0x%04x", p
[0]);
697 printf("0x%04x", p
[1]);
707 printf(" ipttl %u", cmd
->arg1
);
709 uint16_t *p
= ((ipfw_insn_u16
*)cmd
)->ports
;
712 for (i
= F_LEN((ipfw_insn
*)cmd
) - 1; i
> 0; i
--, p
+= 2) {
713 printf("0x%04x", p
[0]);
716 printf("0x%04x", p
[1]);
725 printf(" ipver %u", cmd
->arg1
);
729 printf(" ipprecedence %u", (cmd
->arg1
) >> 5 );
734 printf(" iplen %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 print_flags("ipoptions", cmd
, f_ipopts
);
756 print_flags("iptos", cmd
, f_iptos
);
760 print_icmptypes((ipfw_insn_u32
*)cmd
);
764 printf(" established");
768 print_flags("tcpflags", cmd
, f_tcpflags
);
772 print_flags("tcpoptions", cmd
, f_tcpopts
);
776 printf(" tcpwin %d", ntohs(cmd
->arg1
));
780 printf(" tcpack %ld", ntohl(cmd32
->d
[0]));
784 printf(" tcpseq %ld", ntohl(cmd32
->d
[0]));
788 printf(" uid %u", cmd32
->d
[0]);
792 printf(" gid %u", cmd32
->d
[0]);
796 printf(" verrevpath");
807 printf(" keep-state");
812 struct _s_x
*p
= limit_masks
;
813 ipfw_insn_limit
*c
= (ipfw_insn_limit
*)cmd
;
814 uint8_t x
= c
->limit_mask
;
815 char const *comma
= " ";
818 for (; p
->x
!= 0 ; p
++)
819 if ((x
& p
->x
) == p
->x
) {
821 printf("%s%s", comma
, p
->s
);
824 printf(" %d", c
->conn_limit
);
830 printf(" [opcode %d len %d]",
831 cmd
->opcode
, cmd
->len
);
839 * helper function, updates the pointer to cmd with the length
840 * of the current command, and also cleans up the first word of
841 * the new command in case it has been clobbered before.
845 next_cmd(ipfw_insn
*cmd
)
848 bzero(cmd
, sizeof(*cmd
));
853 * A function to fill simple commands of size 1.
854 * Existing flags are preserved.
858 fill_cmd(ipfw_insn
*cmd
, enum ipfw_opcodes opcode
, uint16_t arg
)
860 cmd
->opcode
= opcode
;
861 cmd
->len
= ((cmd
->len
) & (F_NOT
| F_OR
)) | 1;
867 fill_compat_tcpflags(u_int32_t flags
) {
868 u_int32_t flags_compat
= 0;
871 flags_compat
|= IP_FW_TCPF_FIN_COMPAT
;
873 flags_compat
|= IP_FW_TCPF_SYN_COMPAT
;
875 flags_compat
|= IP_FW_TCPF_RST_COMPAT
;
877 flags_compat
|= IP_FW_TCPF_PSH_COMPAT
;
879 flags_compat
|= IP_FW_TCPF_ACK_COMPAT
;
881 flags_compat
|= IP_FW_TCPF_URG_COMPAT
;
887 /* ********************************************
888 * *********** Convert from Latest ************
889 * ********************************************/
892 * Things we're actively ignoring:
893 * sets, sets of addresses, blocks (NOT, OR)
896 ipfw_map_from_cmds(struct ip_fw
*curr_rule
, struct ip_fw_compat
*compat_rule
)
901 for (l
= curr_rule
->act_ofs
, cmd
= curr_rule
->cmd
;
903 l
-= F_LEN(cmd
) , cmd
+= F_LEN(cmd
)) {
905 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
;
907 switch (cmd
->opcode
) {
910 compat_rule
->fw_prot
= cmd
->arg1
;
914 compat_rule
->fw_flg
|= IP_FW_F_SME_COMPAT
;
915 if (cmd
->len
& F_NOT
) {
916 compat_rule
->fw_flg
|= IP_FW_F_INVSRC_COMPAT
;
923 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
925 compat_rule
->fw_src
= ip
->addr
;
926 compat_rule
->fw_smsk
= ip
->mask
;
927 if (cmd
->len
& F_NOT
) {
928 compat_rule
->fw_flg
|= IP_FW_F_INVSRC_COMPAT
;
936 * for now we only deal with one address
937 * per rule and ignore sets of addresses
939 compat_rule
->fw_src
.s_addr
= cmd32
->d
[0];
940 if (cmd
->len
& F_NOT
) {
941 compat_rule
->fw_flg
|= IP_FW_F_INVSRC_COMPAT
;
948 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
949 uint16_t *p
= ports
->ports
;
952 /* copy list of ports */
953 for (i
= F_LEN(cmd
) - 1, j
= 0; i
> 0; i
--, j
++, p
+= 2) {
955 /* this is a range */
956 compat_rule
->fw_flg
|= IP_FW_F_SRNG_COMPAT
;
957 compat_rule
->fw_uar_compat
.fw_pts
[j
++] = p
[0];
958 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[1];
960 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[0];
963 IP_FW_SETNSRCP_COMPAT(compat_rule
, j
);
970 compat_rule
->fw_flg
|= IP_FW_F_DME_COMPAT
;
971 if (cmd
->len
& F_NOT
) {
972 compat_rule
->fw_flg
|= IP_FW_F_INVDST_COMPAT
;
979 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
981 compat_rule
->fw_dst
= ip
->addr
;
982 compat_rule
->fw_dmsk
= ip
->mask
;
983 if (cmd
->len
& F_NOT
) {
984 compat_rule
->fw_flg
|= IP_FW_F_INVDST_COMPAT
;
991 * for now we only deal with one address
992 * per rule, and ignore sets of addresses
994 compat_rule
->fw_dst
.s_addr
= cmd32
->d
[0];
995 if (cmd
->len
& F_NOT
) {
996 compat_rule
->fw_flg
|= IP_FW_F_INVDST_COMPAT
;
1003 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
1004 uint16_t *p
= ports
->ports
;
1006 j
= IP_FW_GETNSRCP_COMPAT(compat_rule
);
1008 /* copy list of ports */
1009 for (i
= F_LEN(cmd
) - 1; i
> 0; i
--, j
++, p
+= 2) {
1011 /* this is a range */
1012 compat_rule
->fw_flg
|= IP_FW_F_DRNG_COMPAT
;
1013 compat_rule
->fw_uar_compat
.fw_pts
[j
++] = p
[0];
1014 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[1];
1016 compat_rule
->fw_uar_compat
.fw_pts
[j
] = p
[0];
1019 IP_FW_SETNDSTP_COMPAT(compat_rule
, (j
- IP_FW_GETNSRCP_COMPAT(compat_rule
)));
1026 ipfw_insn_log
*c
= (ipfw_insn_log
*)cmd
;
1028 compat_rule
->fw_flg
|= IP_FW_F_PRN_COMPAT
;
1029 compat_rule
->fw_logamount
= c
->max_log
;
1033 compat_rule
->fw_flg
|= IP_FW_F_UID_COMPAT
;
1034 compat_rule
->fw_uid
= cmd32
->d
[0];
1038 if (cmd
->len
& F_NOT
) {
1039 compat_rule
->fw_flg
|= IP_FW_F_OUT_COMPAT
;
1041 compat_rule
->fw_flg
|= IP_FW_F_IN_COMPAT
;
1046 compat_rule
->fw_flg
|= IP_FW_F_KEEP_S_COMPAT
;
1050 compat_rule
->fw_flg
|= IP_FW_BRIDGED_COMPAT
;
1055 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1056 union ip_fw_if_compat ifu
;
1058 if ((ifcmd
->o
.len
== 0) && (ifcmd
->name
[0] == '\0')) {
1060 compat_rule
->fw_flg
|= IP_FW_F_OIFACE_COMPAT
;
1061 ifu
.fu_via_ip
.s_addr
= 0;
1063 else if (ifcmd
->p
.ip
.s_addr
!= 0) {
1064 compat_rule
->fw_flg
|= IP_FW_F_OIFACE_COMPAT
;
1065 ifu
.fu_via_ip
= ifcmd
->p
.ip
;
1067 compat_rule
->fw_flg
|= IP_FW_F_OIFNAME_COMPAT
;
1068 strncpy(ifu
.fu_via_if_compat
.name
, ifcmd
->name
, sizeof(ifu
.fu_via_if_compat
.name
));
1069 ifu
.fu_via_if_compat
.unit
= ifcmd
->p
.unit
;
1071 compat_rule
->fw_out_if
= ifu
;
1078 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1079 union ip_fw_if_compat ifu
;
1081 if ((ifcmd
->o
.len
== 0) && (ifcmd
->name
[0] == '\0')) {
1083 compat_rule
->fw_flg
|= IP_FW_F_IIFACE_COMPAT
;
1084 ifu
.fu_via_ip
.s_addr
= 0;
1086 else if (ifcmd
->p
.ip
.s_addr
!= 0) {
1087 compat_rule
->fw_flg
|= IP_FW_F_IIFACE_COMPAT
;
1088 ifu
.fu_via_ip
= ifcmd
->p
.ip
;
1090 compat_rule
->fw_flg
|= IP_FW_F_IIFNAME_COMPAT
;
1091 strncpy(ifu
.fu_via_if_compat
.name
, ifcmd
->name
, sizeof(ifu
.fu_via_if_compat
.name
));
1092 ifu
.fu_via_if_compat
.unit
= ifcmd
->p
.unit
;
1094 compat_rule
->fw_in_if
= ifu
;
1101 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1102 union ip_fw_if_compat ifu
;
1104 if ((ifcmd
->o
.len
== 0) && (ifcmd
->name
[0] == '\0')) {
1106 ifu
.fu_via_ip
.s_addr
= 0;
1108 else if (ifcmd
->name
[0] != '\0') {
1109 compat_rule
->fw_flg
|= IP_FW_F_IIFNAME_COMPAT
;
1110 strncpy(ifu
.fu_via_if_compat
.name
, ifcmd
->name
, sizeof(ifu
.fu_via_if_compat
.name
));
1111 ifu
.fu_via_if_compat
.unit
= ifcmd
->p
.unit
;
1113 ifu
.fu_via_ip
= ifcmd
->p
.ip
;
1115 compat_rule
->fw_flg
|= IF_FW_F_VIAHACK_COMPAT
;
1116 compat_rule
->fw_out_if
= compat_rule
->fw_in_if
= ifu
;
1122 compat_rule
->fw_flg
|= IP_FW_F_FRAG_COMPAT
;
1127 compat_rule
->fw_ipopt
= (cmd
->arg1
& 0xff);
1128 compat_rule
->fw_ipnopt
= ((cmd
->arg1
>> 8) & 0xff);
1132 /* check for "setup" */
1133 if ((cmd
->arg1
& 0xff) == TH_SYN
&&
1134 ((cmd
->arg1
>> 8) & 0xff) == TH_ACK
) {
1135 compat_rule
->fw_tcpf
= IP_FW_TCPF_SYN_COMPAT
;
1136 compat_rule
->fw_tcpnf
= IP_FW_TCPF_ACK_COMPAT
;
1139 compat_rule
->fw_tcpf
= fill_compat_tcpflags(cmd
->arg1
& 0xff);
1140 compat_rule
->fw_tcpnf
= fill_compat_tcpflags((cmd
->arg1
>> 8) & 0xff);
1146 compat_rule
->fw_tcpopt
= (cmd
->arg1
& 0xff);
1147 compat_rule
->fw_tcpnopt
= ((cmd
->arg1
>> 8) & 0xff);
1151 compat_rule
->fw_ipflg
|= IP_FW_IF_TCPEST_COMPAT
;
1157 /* XXX: check this */
1160 compat_rule
->fw_flg
|= IP_FW_F_ICMPBIT_COMPAT
;
1161 for (i
= 0; i
< sizeof(uint32_t) ; i
++) {
1162 type
= cmd32
->d
[0] & i
;
1164 compat_rule
->fw_uar_compat
.fw_icmptypes
[type
/ (sizeof(unsigned) * 8)] |=
1165 1 << (type
% (sizeof(unsigned) * 8));
1176 ipfw_map_from_actions(struct ip_fw
*curr_rule
, struct ip_fw_compat
*compat_rule
)
1181 for (l
= curr_rule
->cmd_len
- curr_rule
->act_ofs
, cmd
= ACTION_PTR(curr_rule
);
1183 l
-= F_LEN(cmd
), cmd
+= F_LEN(cmd
)) {
1184 switch (cmd
->opcode
) {
1186 compat_rule
->fw_flg
|= IP_FW_F_ACCEPT_COMPAT
;
1189 compat_rule
->fw_flg
|= IP_FW_F_COUNT_COMPAT
;
1192 compat_rule
->fw_flg
|= IP_FW_F_PIPE_COMPAT
;
1193 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1196 compat_rule
->fw_flg
|= IP_FW_F_QUEUE_COMPAT
;
1197 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1200 compat_rule
->fw_flg
|= IP_FW_F_SKIPTO_COMPAT
;
1201 compat_rule
->fw_skipto_rule_compat
= cmd
->arg1
;
1204 compat_rule
->fw_flg
|= IP_FW_F_DIVERT_COMPAT
;
1205 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1208 compat_rule
->fw_flg
|= IP_FW_F_TEE_COMPAT
;
1209 compat_rule
->fw_divert_port_compat
= cmd
->arg1
;
1213 ipfw_insn_sa
*p
= (ipfw_insn_sa
*)cmd
;
1215 compat_rule
->fw_flg
|= IP_FW_F_FWD_COMPAT
;
1216 compat_rule
->fw_fwd_ip_compat
.sin_len
= p
->sa
.sin_len
;
1217 compat_rule
->fw_fwd_ip_compat
.sin_family
= p
->sa
.sin_family
;
1218 compat_rule
->fw_fwd_ip_compat
.sin_port
= p
->sa
.sin_port
;
1219 compat_rule
->fw_fwd_ip_compat
.sin_addr
= p
->sa
.sin_addr
;
1224 compat_rule
->fw_flg
|= IP_FW_F_DENY_COMPAT
;
1227 compat_rule
->fw_flg
|= IP_FW_F_REJECT_COMPAT
;
1228 compat_rule
->fw_reject_code_compat
= cmd
->arg1
;
1231 compat_rule
->fw_flg
|= IP_FW_F_CHECK_S_COMPAT
;
1240 ipfw_version_latest_to_one(struct ip_fw
*curr_rule
, struct ip_fw_compat
*rule_vers1
)
1245 bzero(rule_vers1
, sizeof(struct ip_fw_compat
));
1247 rule_vers1
->version
= IP_FW_VERSION_1
;
1248 rule_vers1
->context
= curr_rule
->context
;
1249 rule_vers1
->fw_number
= curr_rule
->rulenum
;
1250 rule_vers1
->fw_pcnt
= curr_rule
->pcnt
;
1251 rule_vers1
->fw_bcnt
= curr_rule
->bcnt
;
1252 rule_vers1
->timestamp
= curr_rule
->timestamp
;
1254 /* convert actions */
1255 ipfw_map_from_actions(curr_rule
, rule_vers1
);
1257 /* convert commands */
1258 ipfw_map_from_cmds(curr_rule
, rule_vers1
);
1260 #if FW2_DEBUG_VERBOSE
1261 ipfw_print_vers1_struct(rule_vers1
);
1265 /* first convert to version one then to version zero */
1267 ipfw_version_latest_to_zero(struct ip_fw
*curr_rule
, struct ip_old_fw
*rule_vers0
)
1269 struct ip_fw_compat rule_vers1
;
1271 ipfw_version_latest_to_one(curr_rule
, &rule_vers1
);
1273 bzero(rule_vers0
, sizeof(struct ip_old_fw
));
1274 bcopy(&rule_vers1
.fw_uar_compat
, &rule_vers0
->fw_uar
, sizeof(rule_vers1
.fw_uar_compat
));
1275 bcopy(&rule_vers1
.fw_in_if
, &rule_vers0
->fw_in_if
, sizeof(rule_vers1
.fw_in_if
));
1276 bcopy(&rule_vers1
.fw_out_if
, &rule_vers0
->fw_out_if
, sizeof(rule_vers1
.fw_out_if
));
1277 bcopy(&rule_vers1
.fw_un_compat
, &rule_vers0
->fw_un
, sizeof(rule_vers1
.fw_un_compat
));
1279 rule_vers0
->fw_pcnt
= rule_vers1
.fw_pcnt
;
1280 rule_vers0
->fw_bcnt
= rule_vers1
.fw_bcnt
;
1281 rule_vers0
->fw_src
= rule_vers1
.fw_src
;
1282 rule_vers0
->fw_dst
= rule_vers1
.fw_dst
;
1283 rule_vers0
->fw_smsk
= rule_vers1
.fw_smsk
;
1284 rule_vers0
->fw_dmsk
= rule_vers1
.fw_dmsk
;
1285 rule_vers0
->fw_number
= rule_vers1
.fw_number
;
1286 rule_vers0
->fw_flg
= rule_vers1
.fw_flg
;
1287 rule_vers0
->fw_ipopt
= rule_vers1
.fw_ipopt
;
1288 rule_vers0
->fw_ipnopt
= rule_vers1
.fw_ipnopt
;
1289 rule_vers0
->fw_tcpf
= rule_vers1
.fw_tcpf
;
1290 rule_vers0
->fw_tcpnf
= rule_vers1
.fw_tcpnf
;
1291 rule_vers0
->timestamp
= rule_vers1
.timestamp
;
1292 rule_vers0
->fw_prot
= rule_vers1
.fw_prot
;
1293 rule_vers0
->fw_nports
= rule_vers1
.fw_nports
;
1294 rule_vers0
->pipe_ptr
= rule_vers1
.pipe_ptr
;
1295 rule_vers0
->next_rule_ptr
= rule_vers1
.next_rule_ptr
;
1297 if (rule_vers1
.fw_ipflg
&& IP_FW_IF_TCPEST_COMPAT
) rule_vers0
->fw_tcpf
|= IP_OLD_FW_TCPF_ESTAB
;
1301 ipfw_convert_from_latest(struct ip_fw
*curr_rule
, void *old_rule
, u_int32_t api_version
)
1303 switch (api_version
) {
1304 case IP_FW_VERSION_0
:
1306 struct ip_old_fw
*rule_vers0
= old_rule
;
1308 ipfw_version_latest_to_zero(curr_rule
, rule_vers0
);
1311 case IP_FW_VERSION_1
:
1313 struct ip_fw_compat
*rule_vers1
= old_rule
;
1315 ipfw_version_latest_to_one(curr_rule
, rule_vers1
);
1318 case IP_FW_CURRENT_API_VERSION
:
1319 /* ipfw2 for now, don't need to do anything */
1323 /* unknown version */
1329 /* ********************************************
1330 * *********** Convert to Latest **************
1331 * ********************************************/
1335 ipfw_check_vers1_struct(struct ip_fw_compat
*frwl
)
1337 /* Check for invalid flag bits */
1338 if ((frwl
->fw_flg
& ~IP_FW_F_MASK_COMPAT
) != 0) {
1340 printf(("%s undefined flag bits set (flags=%x)\n",
1341 err_prefix, frwl->fw_flg));
1345 if (frwl
->fw_flg
== IP_FW_F_CHECK_S_COMPAT
) {
1349 /* Must apply to incoming or outgoing (or both) */
1350 if (!(frwl
->fw_flg
& (IP_FW_F_IN_COMPAT
| IP_FW_F_OUT_COMPAT
))) {
1352 printf(("%s neither in nor out\n", err_prefix));
1356 /* Empty interface name is no good */
1357 if (((frwl
->fw_flg
& IP_FW_F_IIFNAME_COMPAT
)
1358 && !*frwl
->fw_in_if
.fu_via_if_compat
.name
)
1359 || ((frwl
->fw_flg
& IP_FW_F_OIFNAME_COMPAT
)
1360 && !*frwl
->fw_out_if
.fu_via_if_compat
.name
)) {
1362 printf(("%s empty interface name\n", err_prefix));
1366 /* Sanity check interface matching */
1367 if ((frwl
->fw_flg
& IF_FW_F_VIAHACK_COMPAT
) == IF_FW_F_VIAHACK_COMPAT
) {
1368 ; /* allow "via" backwards compatibility */
1369 } else if ((frwl
->fw_flg
& IP_FW_F_IN_COMPAT
)
1370 && (frwl
->fw_flg
& IP_FW_F_OIFACE_COMPAT
)) {
1372 printf(("%s outgoing interface check on incoming\n",
1377 /* Sanity check port ranges */
1378 if ((frwl
->fw_flg
& IP_FW_F_SRNG_COMPAT
) && IP_FW_GETNSRCP_COMPAT(frwl
) < 2) {
1380 printf(("%s src range set but n_src_p=%d\n",
1381 err_prefix, IP_FW_GETNSRCP_COMPAT(frwl)));
1385 if ((frwl
->fw_flg
& IP_FW_F_DRNG_COMPAT
) && IP_FW_GETNDSTP_COMPAT(frwl
) < 2) {
1387 printf(("%s dst range set but n_dst_p=%d\n",
1388 err_prefix, IP_FW_GETNDSTP_COMPAT(frwl)));
1392 if (IP_FW_GETNSRCP_COMPAT(frwl
) + IP_FW_GETNDSTP_COMPAT(frwl
) > IP_FW_MAX_PORTS_COMPAT
) {
1394 printf(("%s too many ports (%d+%d)\n",
1395 err_prefix, IP_FW_GETNSRCP_COMPAT(frwl), IP_FW_GETNDSTP_COMPAT(frwl)));
1400 * Protocols other than TCP/UDP don't use port range
1402 if ((frwl
->fw_prot
!= IPPROTO_TCP
) &&
1403 (frwl
->fw_prot
!= IPPROTO_UDP
) &&
1404 (IP_FW_GETNSRCP_COMPAT(frwl
) || IP_FW_GETNDSTP_COMPAT(frwl
))) {
1406 printf(("%s port(s) specified for non TCP/UDP rule\n",
1413 * Rather than modify the entry to make such entries work,
1414 * we reject this rule and require user level utilities
1415 * to enforce whatever policy they deem appropriate.
1417 if ((frwl
->fw_src
.s_addr
& (~frwl
->fw_smsk
.s_addr
)) ||
1418 (frwl
->fw_dst
.s_addr
& (~frwl
->fw_dmsk
.s_addr
))) {
1420 printf(("%s rule never matches\n", err_prefix));
1425 if ((frwl
->fw_flg
& IP_FW_F_FRAG_COMPAT
) &&
1426 (frwl
->fw_prot
== IPPROTO_UDP
|| frwl
->fw_prot
== IPPROTO_TCP
)) {
1427 if (frwl
->fw_nports
) {
1429 printf(("%s cannot mix 'frag' and ports\n", err_prefix));
1433 if (frwl
->fw_prot
== IPPROTO_TCP
&&
1434 frwl
->fw_tcpf
!= frwl
->fw_tcpnf
) {
1436 printf(("%s cannot mix 'frag' and TCP flags\n", err_prefix));
1442 /* Check command specific stuff */
1443 switch (frwl
->fw_flg
& IP_FW_F_COMMAND_COMPAT
)
1445 case IP_FW_F_REJECT_COMPAT
:
1446 if (frwl
->fw_reject_code_compat
>= 0x100
1447 && !(frwl
->fw_prot
== IPPROTO_TCP
1448 && frwl
->fw_reject_code_compat
== IP_FW_REJECT_RST_COMPAT
)) {
1450 printf(("%s unknown reject code\n", err_prefix));
1455 case IP_FW_F_DIVERT_COMPAT
: /* Diverting to port zero is invalid */
1456 case IP_FW_F_TEE_COMPAT
:
1457 case IP_FW_F_PIPE_COMPAT
: /* piping through 0 is invalid */
1458 case IP_FW_F_QUEUE_COMPAT
: /* piping through 0 is invalid */
1459 if (frwl
->fw_divert_port_compat
== 0) {
1461 printf(("%s can't divert to port 0\n", err_prefix));
1466 case IP_FW_F_DENY_COMPAT
:
1467 case IP_FW_F_ACCEPT_COMPAT
:
1468 case IP_FW_F_COUNT_COMPAT
:
1469 case IP_FW_F_SKIPTO_COMPAT
:
1470 case IP_FW_F_FWD_COMPAT
:
1471 case IP_FW_F_UID_COMPAT
:
1475 printf(("%s invalid command\n", err_prefix));
1484 ipfw_convert_to_cmds(struct ip_fw
*curr_rule
, struct ip_fw_compat
*compat_rule
)
1487 uint32_t actbuf
[255], cmdbuf
[255];
1488 ipfw_insn
*action
, *cmd
, *src
, *dst
;
1489 ipfw_insn
*have_state
= NULL
, /* track check-state or keep-state */
1493 if (!compat_rule
|| !curr_rule
|| !(curr_rule
->cmd
)) {
1497 /* preemptively check the old ip_fw rule to
1498 * make sure it's valid before starting to copy stuff
1500 if (ipfw_check_vers1_struct(compat_rule
)) {
1505 bzero(actbuf
, sizeof(actbuf
)); /* actions go here */
1506 bzero(cmdbuf
, sizeof(cmdbuf
));
1508 /* fill in action */
1509 action
= (ipfw_insn
*)actbuf
;
1511 u_int flag
= compat_rule
->fw_flg
;
1513 action
->len
= 1; /* default */
1515 if (flag
& IP_FW_F_CHECK_S_COMPAT
) {
1516 have_state
= action
;
1517 action
->opcode
= O_CHECK_STATE
;
1520 switch (flag
& IP_FW_F_COMMAND_COMPAT
) {
1521 case IP_FW_F_ACCEPT_COMPAT
:
1522 action
->opcode
= O_ACCEPT
;
1524 case IP_FW_F_COUNT_COMPAT
:
1525 action
->opcode
= O_COUNT
;
1527 case IP_FW_F_PIPE_COMPAT
:
1528 action
->opcode
= O_PIPE
;
1529 action
->len
= F_INSN_SIZE(ipfw_insn_pipe
);
1530 action
->arg1
= compat_rule
->fw_divert_port_compat
;
1532 case IP_FW_F_QUEUE_COMPAT
:
1533 action
->opcode
= O_QUEUE
;
1534 action
->len
= F_INSN_SIZE(ipfw_insn_pipe
);
1535 action
->arg1
= compat_rule
->fw_divert_port_compat
;
1537 case IP_FW_F_SKIPTO_COMPAT
:
1538 action
->opcode
= O_SKIPTO
;
1539 action
->arg1
= compat_rule
->fw_skipto_rule_compat
;
1541 case IP_FW_F_DIVERT_COMPAT
:
1542 action
->opcode
= O_DIVERT
;
1543 action
->arg1
= compat_rule
->fw_divert_port_compat
;
1545 case IP_FW_F_TEE_COMPAT
:
1546 action
->opcode
= O_TEE
;
1547 action
->arg1
= compat_rule
->fw_divert_port_compat
;
1549 case IP_FW_F_FWD_COMPAT
:
1551 ipfw_insn_sa
*p
= (ipfw_insn_sa
*)action
;
1553 action
->opcode
= O_FORWARD_IP
;
1554 action
->len
= F_INSN_SIZE(ipfw_insn_sa
);
1556 p
->sa
.sin_len
= compat_rule
->fw_fwd_ip_compat
.sin_len
;
1557 p
->sa
.sin_family
= compat_rule
->fw_fwd_ip_compat
.sin_family
;
1558 p
->sa
.sin_port
= compat_rule
->fw_fwd_ip_compat
.sin_port
;
1559 p
->sa
.sin_addr
= compat_rule
->fw_fwd_ip_compat
.sin_addr
;
1563 case IP_FW_F_DENY_COMPAT
:
1564 action
->opcode
= O_DENY
;
1567 case IP_FW_F_REJECT_COMPAT
:
1568 action
->opcode
= O_REJECT
;
1569 action
->arg1
= compat_rule
->fw_reject_code_compat
;
1572 action
->opcode
= O_NOP
;
1577 /* action is mandatory */
1578 if (action
->opcode
== O_NOP
) {
1582 action
= next_cmd(action
);
1585 cmd
= (ipfw_insn
*)cmdbuf
;
1587 /* this is O_CHECK_STATE, we're done */
1593 ipfw_insn
*prev
= NULL
;
1594 u_int flag
= compat_rule
->fw_flg
;
1597 if (flag
& IP_FW_F_PRN_COMPAT
) {
1598 ipfw_insn_log
*c
= (ipfw_insn_log
*)cmd
;
1600 cmd
->opcode
= O_LOG
;
1601 cmd
->len
|= F_INSN_SIZE(ipfw_insn_log
);
1602 c
->max_log
= compat_rule
->fw_logamount
;
1605 cmd
= next_cmd(cmd
);
1609 if (compat_rule
->fw_prot
!= 0) {
1610 fill_cmd(cmd
, O_PROTO
, compat_rule
->fw_prot
);
1612 cmd
= next_cmd(cmd
);
1616 if (flag
& IP_FW_F_SME_COMPAT
) {
1617 cmd
->opcode
= O_IP_SRC_ME
;
1618 cmd
->len
|= F_INSN_SIZE(ipfw_insn
);
1619 if (flag
& IP_FW_F_INVSRC_COMPAT
) {
1620 cmd
->len
^= F_NOT
; /* toggle F_NOT */
1624 cmd
= next_cmd(cmd
);
1626 if (compat_rule
->fw_smsk
.s_addr
!= 0) {
1628 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
1630 ip
->addr
= compat_rule
->fw_src
;
1631 ip
->mask
= compat_rule
->fw_smsk
;
1632 cmd
->opcode
= O_IP_SRC_MASK
;
1633 cmd
->len
|= F_INSN_SIZE(ipfw_insn_ip
); /* double check this */
1636 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
; /* alias for cmd */
1638 if (compat_rule
->fw_src
.s_addr
== 0) {
1640 cmd32
->o
.len
&= ~F_LEN_MASK
; /* zero len */
1642 cmd32
->d
[0] = compat_rule
->fw_src
.s_addr
;
1643 cmd32
->o
.opcode
= O_IP_SRC
;
1644 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
1648 if (flag
& IP_FW_F_INVSRC_COMPAT
) {
1649 cmd
->len
^= F_NOT
; /* toggle F_NOT */
1652 if (F_LEN(cmd
) != 0) { /* !any */
1654 cmd
= next_cmd(cmd
);
1660 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
1661 uint16_t *p
= ports
->ports
;
1663 nports
= IP_FW_GETNSRCP_COMPAT(compat_rule
),
1666 cmd
->opcode
= O_IP_SRCPORT
;
1667 for (i
= 0; i
< nports
; i
++) {
1668 if (((flag
& IP_FW_F_SRNG_COMPAT
) ||
1669 (flag
& IP_FW_F_SMSK_COMPAT
)) && !have_range
) {
1670 p
[0] = compat_rule
->fw_uar_compat
.fw_pts
[i
++];
1671 p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
1674 p
[0] = p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
1681 ports
->o
.len
|= j
+1; /* leave F_NOT and F_OR untouched */
1685 cmd
= next_cmd(cmd
);
1689 if (flag
& IP_FW_F_DME_COMPAT
) {
1690 cmd
->opcode
= O_IP_DST_ME
;
1691 cmd
->len
|= F_INSN_SIZE(ipfw_insn
);
1692 if (flag
& IP_FW_F_INVDST_COMPAT
) {
1693 cmd
->len
^= F_NOT
; /* toggle F_NOT */
1697 cmd
= next_cmd(cmd
);
1699 if (compat_rule
->fw_dmsk
.s_addr
!= 0) {
1701 ipfw_insn_ip
*ip
= (ipfw_insn_ip
*)cmd
;
1703 ip
->addr
= compat_rule
->fw_dst
;
1704 ip
->mask
= compat_rule
->fw_dmsk
;
1705 cmd
->opcode
= O_IP_DST_MASK
;
1706 cmd
->len
|= F_INSN_SIZE(ipfw_insn_ip
); /* double check this */
1709 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
; /* alias for cmd */
1711 if (compat_rule
->fw_dst
.s_addr
== 0) {
1713 cmd32
->o
.len
&= ~F_LEN_MASK
; /* zero len */
1715 cmd32
->d
[0] = compat_rule
->fw_dst
.s_addr
;
1716 cmd32
->o
.opcode
= O_IP_DST
;
1717 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
1721 if (flag
& IP_FW_F_INVDST_COMPAT
) {
1722 cmd
->len
^= F_NOT
; /* toggle F_NOT */
1725 if (F_LEN(cmd
) != 0) { /* !any */
1727 cmd
= next_cmd(cmd
);
1733 ipfw_insn_u16
*ports
= (ipfw_insn_u16
*)cmd
;
1734 uint16_t *p
= ports
->ports
;
1735 int i
= IP_FW_GETNSRCP_COMPAT(compat_rule
),
1737 nports
= (IP_FW_GETNDSTP_COMPAT(compat_rule
) + i
),
1740 cmd
->opcode
= O_IP_DSTPORT
;
1741 for (; i
< nports
; i
++, p
+= 2) {
1742 if (((flag
& IP_FW_F_DRNG_COMPAT
) ||
1743 (flag
& IP_FW_F_DMSK_COMPAT
)) && !have_range
) {
1745 p
[0] = compat_rule
->fw_uar_compat
.fw_pts
[i
++];
1746 p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
1749 p
[0] = p
[1] = compat_rule
->fw_uar_compat
.fw_pts
[i
];
1755 ports
->o
.len
|= j
+1; /* leave F_NOT and F_OR untouched */
1759 cmd
= next_cmd(cmd
);
1762 if (flag
& IP_FW_F_UID_COMPAT
) {
1763 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
; /* alias for cmd */
1765 cmd32
->o
.opcode
= O_UID
;
1766 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
1767 cmd32
->d
[0] = compat_rule
->fw_uid
;
1770 cmd
= next_cmd(cmd
);
1773 if (flag
& IP_FW_F_KEEP_S_COMPAT
) {
1775 fill_cmd(cmd
, O_KEEP_STATE
, 0);
1778 cmd
= next_cmd(cmd
);
1780 if (flag
& IP_FW_BRIDGED_COMPAT
) {
1781 fill_cmd(cmd
, O_LAYER2
, 0);
1784 cmd
= next_cmd(cmd
);
1787 if ((flag
& IF_FW_F_VIAHACK_COMPAT
) == IF_FW_F_VIAHACK_COMPAT
) {
1789 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1790 union ip_fw_if_compat ifu
= compat_rule
->fw_in_if
;
1792 cmd
->opcode
= O_VIA
;
1793 ifcmd
->o
.len
|= F_INSN_SIZE(ipfw_insn_if
);
1795 if (ifu
.fu_via_ip
.s_addr
== 0) {
1797 ifcmd
->name
[0] = '\0';
1800 else if (compat_rule
->fw_flg
& IP_FW_F_IIFNAME_COMPAT
) {
1802 strncpy(ifcmd
->name
, ifu
.fu_via_if_compat
.name
, sizeof(ifcmd
->name
));
1803 ifcmd
->p
.unit
= ifu
.fu_via_if_compat
.unit
;
1806 ifcmd
->p
.ip
= ifu
.fu_via_ip
;
1810 cmd
= next_cmd(cmd
);
1812 if (flag
& IP_FW_F_IN_COMPAT
) {
1813 fill_cmd(cmd
, O_IN
, 0);
1816 cmd
= next_cmd(cmd
);
1818 if (flag
& IP_FW_F_OUT_COMPAT
) {
1819 /* if the previous command was O_IN, and this
1820 * is being set as well, it's equivalent to not
1821 * having either command, so let's back up prev
1822 * to the cmd before it and move cmd to prev.
1824 if (prev
->opcode
== O_IN
) {
1826 bzero(cmd
, sizeof(*cmd
));
1828 cmd
->len
^= F_NOT
; /* toggle F_NOT */
1829 fill_cmd(cmd
, O_IN
, 0);
1832 cmd
= next_cmd(cmd
);
1835 if (flag
& IP_FW_F_OIFACE_COMPAT
) {
1837 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1838 union ip_fw_if_compat ifu
= compat_rule
->fw_out_if
;
1840 cmd
->opcode
= O_XMIT
;
1841 ifcmd
->o
.len
|= F_INSN_SIZE(ipfw_insn_if
);
1843 if (ifu
.fu_via_ip
.s_addr
== 0) {
1845 ifcmd
->name
[0] = '\0';
1848 else if (flag
& IP_FW_F_OIFNAME_COMPAT
) {
1850 strncpy(ifcmd
->name
, ifu
.fu_via_if_compat
.name
, sizeof(ifcmd
->name
));
1851 ifcmd
->p
.unit
= ifu
.fu_via_if_compat
.unit
;
1854 ifcmd
->p
.ip
= ifu
.fu_via_ip
;
1858 cmd
= next_cmd(cmd
);
1860 else if (flag
& IP_FW_F_IIFACE_COMPAT
) {
1862 ipfw_insn_if
*ifcmd
= (ipfw_insn_if
*)cmd
;
1863 union ip_fw_if_compat ifu
= compat_rule
->fw_in_if
;
1865 cmd
->opcode
= O_RECV
;
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_IIFNAME_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
);
1887 if (flag
& IP_FW_F_FRAG_COMPAT
) {
1888 fill_cmd(cmd
, O_FRAG
, 0);
1891 cmd
= next_cmd(cmd
);
1895 if (compat_rule
->fw_ipopt
!= 0 || compat_rule
->fw_ipnopt
!= 0) {
1896 fill_cmd(cmd
, O_IPOPT
, (compat_rule
->fw_ipopt
& 0xff) |
1897 (compat_rule
->fw_ipnopt
& 0xff) << 8);
1900 cmd
= next_cmd(cmd
);
1903 if (compat_rule
->fw_prot
== IPPROTO_TCP
) {
1904 if (compat_rule
->fw_ipflg
& IP_FW_IF_TCPEST_COMPAT
) {
1905 fill_cmd(cmd
, O_ESTAB
, 0);
1908 cmd
= next_cmd(cmd
);
1911 /* TCP options and flags */
1912 if (compat_rule
->fw_tcpf
!= 0 || compat_rule
->fw_tcpnf
!= 0) {
1913 if ((compat_rule
->fw_tcpf
& IP_FW_TCPF_SYN_COMPAT
) &&
1914 compat_rule
->fw_tcpnf
& IP_FW_TCPF_ACK_COMPAT
) {
1915 fill_cmd(cmd
, O_TCPFLAGS
, (TH_SYN
) | ( (TH_ACK
) & 0xff) <<8);
1918 cmd
= next_cmd(cmd
);
1921 fill_cmd(cmd
, O_TCPFLAGS
, (compat_rule
->fw_tcpf
& 0xff) |
1922 (compat_rule
->fw_tcpnf
& 0xff) << 8);
1925 cmd
= next_cmd(cmd
);
1928 if (compat_rule
->fw_tcpopt
!= 0 || compat_rule
->fw_tcpnopt
!= 0) {
1929 fill_cmd(cmd
, O_TCPOPTS
, (compat_rule
->fw_tcpopt
& 0xff) |
1930 (compat_rule
->fw_tcpnopt
& 0xff) << 8);
1933 cmd
= next_cmd(cmd
);
1938 /* XXX: check this */
1939 if (flag
& IP_FW_F_ICMPBIT_COMPAT
) {
1941 ipfw_insn_u32
*cmd32
= (ipfw_insn_u32
*)cmd
; /* alias for cmd */
1943 cmd32
->o
.opcode
= O_ICMPTYPE
;
1944 cmd32
->o
.len
|= F_INSN_SIZE(ipfw_insn_u32
);
1946 for (i
= 0; i
< IP_FW_ICMPTYPES_DIM_COMPAT
; i
++) {
1947 cmd32
->d
[0] |= compat_rule
->fw_uar_compat
.fw_icmptypes
[i
];
1951 cmd
= next_cmd(cmd
);
1953 } /* end commands */
1956 /* finally, copy everything into the current
1957 * rule buffer in the right order.
1959 dst
= curr_rule
->cmd
;
1961 /* first, do match probability */
1962 if (compat_rule
->fw_flg
& IP_FW_F_RND_MATCH_COMPAT
) {
1963 dst
->opcode
= O_PROB
;
1965 *((int32_t *)(dst
+1)) = compat_rule
->pipe_ptr
;
1969 /* generate O_PROBE_STATE if necessary */
1970 if (have_state
&& have_state
->opcode
!= O_CHECK_STATE
) {
1971 fill_cmd(dst
, O_PROBE_STATE
, 0);
1972 dst
= next_cmd(dst
);
1976 * copy all commands but O_LOG, O_KEEP_STATE
1978 for (src
= (ipfw_insn
*)cmdbuf
; src
!= cmd
; src
+= k
) {
1981 switch (src
->opcode
) {
1986 bcopy(src
, dst
, k
* sizeof(uint32_t));
1992 * put back the have_state command as last opcode
1994 if (have_state
&& have_state
->opcode
!= O_CHECK_STATE
) {
1995 k
= F_LEN(have_state
);
1996 bcopy(have_state
, dst
, k
* sizeof(uint32_t));
2001 * start action section
2003 curr_rule
->act_ofs
= dst
- curr_rule
->cmd
;
2006 * put back O_LOG if necessary
2008 src
= (ipfw_insn
*)cmdbuf
;
2009 if (src
->opcode
== O_LOG
) {
2011 bcopy(src
, dst
, k
* sizeof(uint32_t));
2016 * copy all other actions
2018 for (src
= (ipfw_insn
*)actbuf
; src
!= action
; src
+= k
) {
2020 bcopy(src
, dst
, k
* sizeof(uint32_t));
2024 curr_rule
->cmd_len
= (uint32_t *)dst
- (uint32_t *)(curr_rule
->cmd
);
2030 ipfw_version_one_to_version_two(struct sockopt
*sopt
, struct ip_fw
*curr_rule
,
2031 struct ip_fw_compat
*rule_vers1
)
2034 struct ip_fw_compat
*rule_ptr
;
2035 struct ip_fw_compat rule
;
2038 rule_ptr
= rule_vers1
;
2041 /* do some basic size checking here, more extensive checking later */
2042 if (!sopt
->sopt_val
|| sopt
->sopt_valsize
< sizeof(struct ip_fw_compat
))
2045 if ((err
= sooptcopyin(sopt
, &rule
, sizeof(struct ip_fw_compat
),
2046 sizeof(struct ip_fw_compat
)))) {
2053 /* deal with commands */
2054 ipfw_convert_to_cmds(curr_rule
, rule_ptr
);
2056 curr_rule
->version
= IP_FW_CURRENT_API_VERSION
;
2057 curr_rule
->context
= rule_ptr
->context
;
2058 curr_rule
->rulenum
= rule_ptr
->fw_number
;
2059 curr_rule
->pcnt
= rule_ptr
->fw_pcnt
;
2060 curr_rule
->bcnt
= rule_ptr
->fw_bcnt
;
2061 curr_rule
->timestamp
= rule_ptr
->timestamp
;
2064 #if FW2_DEBUG_VERBOSE
2065 ipfw_print_vers2_struct(curr_rule
);
2066 #endif /* FW2_DEBUG_VERBOSE */
2071 /* This converts to whatever the latest version is. Currently the
2072 * latest version of the firewall is ipfw2.
2075 ipfw_version_one_to_latest(struct sockopt
*sopt
, struct ip_fw
*curr_rule
, struct ip_fw_compat
*rule_vers1
)
2079 /* if rule_vers1 is not null then this is coming from
2080 * ipfw_version_zero_to_latest(), so pass that along;
2081 * otherwise let ipfw_version_one_to_version_two()
2082 * get the rule from sopt.
2084 err
= ipfw_version_one_to_version_two(sopt
, curr_rule
, rule_vers1
);
2090 ipfw_version_zero_to_one(struct ip_old_fw
*rule_vers0
, struct ip_fw_compat
*rule_vers1
)
2092 bzero(rule_vers1
, sizeof(struct ip_fw_compat
));
2093 bcopy(&rule_vers0
->fw_uar
, &rule_vers1
->fw_uar_compat
, sizeof(rule_vers0
->fw_uar
));
2094 bcopy(&rule_vers0
->fw_in_if
, &rule_vers1
->fw_in_if
, sizeof(rule_vers0
->fw_in_if
));
2095 bcopy(&rule_vers0
->fw_out_if
, &rule_vers1
->fw_out_if
, sizeof(rule_vers0
->fw_out_if
));
2096 bcopy(&rule_vers0
->fw_un
, &rule_vers1
->fw_un_compat
, sizeof(rule_vers0
->fw_un
));
2098 rule_vers1
->version
= 10;
2099 rule_vers1
->fw_pcnt
= rule_vers0
->fw_pcnt
;
2100 rule_vers1
->fw_bcnt
= rule_vers0
->fw_bcnt
;
2101 rule_vers1
->fw_src
= rule_vers0
->fw_src
;
2102 rule_vers1
->fw_dst
= rule_vers0
->fw_dst
;
2103 rule_vers1
->fw_smsk
= rule_vers0
->fw_smsk
;
2104 rule_vers1
->fw_dmsk
= rule_vers0
->fw_dmsk
;
2105 rule_vers1
->fw_number
= rule_vers0
->fw_number
;
2106 rule_vers1
->fw_flg
= rule_vers0
->fw_flg
;
2107 rule_vers1
->fw_ipopt
= rule_vers0
->fw_ipopt
;
2108 rule_vers1
->fw_ipnopt
= rule_vers0
->fw_ipnopt
;
2109 rule_vers1
->fw_tcpf
= rule_vers0
->fw_tcpf
& ~IP_OLD_FW_TCPF_ESTAB
;
2110 rule_vers1
->fw_tcpnf
= rule_vers0
->fw_tcpnf
;
2111 rule_vers1
->timestamp
= rule_vers0
->timestamp
;
2112 rule_vers1
->fw_prot
= rule_vers0
->fw_prot
;
2113 rule_vers1
->fw_nports
= rule_vers0
->fw_nports
;
2114 rule_vers1
->pipe_ptr
= rule_vers0
->pipe_ptr
;
2115 rule_vers1
->next_rule_ptr
= rule_vers0
->next_rule_ptr
;
2116 rule_vers1
->fw_ipflg
= (rule_vers0
->fw_tcpf
& IP_OLD_FW_TCPF_ESTAB
) ? IP_FW_IF_TCPEST_COMPAT
: 0;
2119 /* first convert to version one, then to version two */
2121 ipfw_version_zero_to_latest(struct sockopt
*sopt
, struct ip_fw
*curr_rule
)
2124 struct ip_old_fw rule_vers0
;
2125 struct ip_fw_compat rule_vers1
;
2127 if (sopt
->sopt_name
== IP_OLD_FW_GET
||
2128 sopt
->sopt_name
== IP_OLD_FW_FLUSH
||
2129 sopt
->sopt_val
== NULL
) {
2130 /* In the old-style API, it was legal to not pass in a rule
2131 * structure for certain firewall operations (e.g. flush,
2132 * reset log). If that's the situation, we pretend we received
2133 * a blank structure. */
2134 bzero(curr_rule
, sizeof(struct ip_fw
));
2135 curr_rule
->version
= 10;
2138 if (!sopt
->sopt_val
|| sopt
->sopt_valsize
< sizeof(struct ip_old_fw
)) {
2142 err
= sooptcopyin(sopt
, &rule_vers0
, sizeof(struct ip_old_fw
),
2143 sizeof(struct ip_old_fw
));
2148 ipfw_version_zero_to_one(&rule_vers0
, &rule_vers1
);
2151 return (ipfw_version_one_to_latest(sopt
, curr_rule
, &rule_vers1
));
2154 /* rule is a u_int32_t buffer[255] into which the converted
2155 * (if necessary) rules go.
2158 ipfw_convert_to_latest(struct sockopt
*sopt
, struct ip_fw
*curr_rule
, int api_version
)
2162 /* the following functions copy the rules passed in and
2163 * convert to latest structures based on version
2165 switch (api_version
) {
2166 case IP_FW_VERSION_0
:
2167 /* this is the oldest version we support */
2168 err
= ipfw_version_zero_to_latest(sopt
, curr_rule
);
2171 case IP_FW_VERSION_1
:
2172 /* this is the version supported in Panther */
2173 err
= ipfw_version_one_to_latest(sopt
, curr_rule
, NULL
);
2176 case IP_FW_CURRENT_API_VERSION
:
2178 /* do nothing here... */
2182 /* unrecognized/unsupported version */
2191 ipfw_get_command_and_version(struct sockopt
*sopt
, int *command
, u_int32_t
*api_version
)
2195 u_int32_t vers
= IP_FW_VERSION_NONE
;
2197 /* first deal with the oldest version */
2198 if (sopt
->sopt_name
== IP_OLD_FW_GET
) {
2199 vers
= IP_FW_VERSION_0
;
2202 else if (sopt
->sopt_name
== IP_OLD_FW_FLUSH
) {
2203 vers
= IP_FW_VERSION_0
;
2206 else if (sopt
->sopt_name
== IP_OLD_FW_ZERO
) {
2207 vers
= IP_FW_VERSION_0
;
2210 else if (sopt
->sopt_name
== IP_OLD_FW_ADD
) {
2211 vers
= IP_FW_VERSION_0
;
2214 else if (sopt
->sopt_name
== IP_OLD_FW_DEL
) {
2215 vers
= IP_FW_VERSION_0
;
2218 else if (sopt
->sopt_name
== IP_OLD_FW_RESETLOG
) {
2219 vers
= IP_FW_VERSION_0
;
2220 cmd
= IP_FW_RESETLOG
;
2223 cmd
= sopt
->sopt_name
;
2226 if (vers
== IP_FW_VERSION_NONE
) {
2227 /* working off the fact that the offset
2228 * is the same in both structs.
2232 if (!sopt
->sopt_val
|| sopt
->sopt_valsize
< sizeof(struct ip_fw
))
2235 if ((err
= sooptcopyin(sopt
, &rule
, sizeof(struct ip_fw
),
2236 sizeof(struct ip_fw
)))) {
2240 vers
= rule
.version
;
2248 *api_version
= vers
;