View | Details | Raw Unified | Return to bug 245988
Collapse All | Expand All

(-)sys/netpfil/ipfw/ip_fw2.c (-1 / +1 lines)
Lines 1-3555 Link Here
1
/*-
1
/*-
2
 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
2
 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3
 *
3
 *
4
 * Copyright (c) 2002-2009 Luigi Rizzo, Universita` di Pisa
4
 * Copyright (c) 2002-2009 Luigi Rizzo, Universita` di Pisa
5
 *
5
 *
6
 * Redistribution and use in source and binary forms, with or without
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
7
 * modification, are permitted provided that the following conditions
8
 * are met:
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
13
 *    documentation and/or other materials provided with the distribution.
14
 *
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
 * SUCH DAMAGE.
25
 * SUCH DAMAGE.
26
 */
26
 */
27
27
28
#include <sys/cdefs.h>
28
#include <sys/cdefs.h>
29
__FBSDID("$FreeBSD$");
29
__FBSDID("$FreeBSD$");
30
30
31
/*
31
/*
32
 * The FreeBSD IP packet firewall, main file
32
 * The FreeBSD IP packet firewall, main file
33
 */
33
 */
34
34
35
#include "opt_ipfw.h"
35
#include "opt_ipfw.h"
36
#include "opt_ipdivert.h"
36
#include "opt_ipdivert.h"
37
#include "opt_inet.h"
37
#include "opt_inet.h"
38
#ifndef INET
38
#ifndef INET
39
#error "IPFIREWALL requires INET"
39
#error "IPFIREWALL requires INET"
40
#endif /* INET */
40
#endif /* INET */
41
#include "opt_inet6.h"
41
#include "opt_inet6.h"
42
42
43
#include <sys/param.h>
43
#include <sys/param.h>
44
#include <sys/systm.h>
44
#include <sys/systm.h>
45
#include <sys/condvar.h>
45
#include <sys/condvar.h>
46
#include <sys/counter.h>
46
#include <sys/counter.h>
47
#include <sys/eventhandler.h>
47
#include <sys/eventhandler.h>
48
#include <sys/malloc.h>
48
#include <sys/malloc.h>
49
#include <sys/mbuf.h>
49
#include <sys/mbuf.h>
50
#include <sys/kernel.h>
50
#include <sys/kernel.h>
51
#include <sys/lock.h>
51
#include <sys/lock.h>
52
#include <sys/jail.h>
52
#include <sys/jail.h>
53
#include <sys/module.h>
53
#include <sys/module.h>
54
#include <sys/priv.h>
54
#include <sys/priv.h>
55
#include <sys/proc.h>
55
#include <sys/proc.h>
56
#include <sys/rwlock.h>
56
#include <sys/rwlock.h>
57
#include <sys/rmlock.h>
57
#include <sys/rmlock.h>
58
#include <sys/socket.h>
58
#include <sys/socket.h>
59
#include <sys/socketvar.h>
59
#include <sys/socketvar.h>
60
#include <sys/sysctl.h>
60
#include <sys/sysctl.h>
61
#include <sys/syslog.h>
61
#include <sys/syslog.h>
62
#include <sys/ucred.h>
62
#include <sys/ucred.h>
63
#include <net/ethernet.h> /* for ETHERTYPE_IP */
63
#include <net/ethernet.h> /* for ETHERTYPE_IP */
64
#include <net/if.h>
64
#include <net/if.h>
65
#include <net/if_var.h>
65
#include <net/if_var.h>
66
#include <net/route.h>
66
#include <net/route.h>
67
#include <net/pfil.h>
67
#include <net/pfil.h>
68
#include <net/vnet.h>
68
#include <net/vnet.h>
69
69
70
#include <netpfil/pf/pf_mtag.h>
70
#include <netpfil/pf/pf_mtag.h>
71
71
72
#include <netinet/in.h>
72
#include <netinet/in.h>
73
#include <netinet/in_var.h>
73
#include <netinet/in_var.h>
74
#include <netinet/in_pcb.h>
74
#include <netinet/in_pcb.h>
75
#include <netinet/ip.h>
75
#include <netinet/ip.h>
76
#include <netinet/ip_var.h>
76
#include <netinet/ip_var.h>
77
#include <netinet/ip_icmp.h>
77
#include <netinet/ip_icmp.h>
78
#include <netinet/ip_fw.h>
78
#include <netinet/ip_fw.h>
79
#include <netinet/ip_carp.h>
79
#include <netinet/ip_carp.h>
80
#include <netinet/pim.h>
80
#include <netinet/pim.h>
81
#include <netinet/tcp_var.h>
81
#include <netinet/tcp_var.h>
82
#include <netinet/udp.h>
82
#include <netinet/udp.h>
83
#include <netinet/udp_var.h>
83
#include <netinet/udp_var.h>
84
#include <netinet/sctp.h>
84
#include <netinet/sctp.h>
85
#include <netinet/sctp_crc32.h>
85
#include <netinet/sctp_crc32.h>
86
#include <netinet/sctp_header.h>
86
#include <netinet/sctp_header.h>
87
87
88
#include <netinet/ip6.h>
88
#include <netinet/ip6.h>
89
#include <netinet/icmp6.h>
89
#include <netinet/icmp6.h>
90
#include <netinet/in_fib.h>
90
#include <netinet/in_fib.h>
91
#ifdef INET6
91
#ifdef INET6
92
#include <netinet6/in6_fib.h>
92
#include <netinet6/in6_fib.h>
93
#include <netinet6/in6_pcb.h>
93
#include <netinet6/in6_pcb.h>
94
#include <netinet6/scope6_var.h>
94
#include <netinet6/scope6_var.h>
95
#include <netinet6/ip6_var.h>
95
#include <netinet6/ip6_var.h>
96
#endif
96
#endif
97
97
98
#include <net/if_gre.h> /* for struct grehdr */
98
#include <net/if_gre.h> /* for struct grehdr */
99
99
100
#include <netpfil/ipfw/ip_fw_private.h>
100
#include <netpfil/ipfw/ip_fw_private.h>
101
101
102
#include <machine/in_cksum.h>	/* XXX for in_cksum */
102
#include <machine/in_cksum.h>	/* XXX for in_cksum */
103
103
104
#ifdef MAC
104
#ifdef MAC
105
#include <security/mac/mac_framework.h>
105
#include <security/mac/mac_framework.h>
106
#endif
106
#endif
107
107
108
/*
108
/*
109
 * static variables followed by global ones.
109
 * static variables followed by global ones.
110
 * All ipfw global variables are here.
110
 * All ipfw global variables are here.
111
 */
111
 */
112
112
113
VNET_DEFINE_STATIC(int, fw_deny_unknown_exthdrs);
113
VNET_DEFINE_STATIC(int, fw_deny_unknown_exthdrs);
114
#define	V_fw_deny_unknown_exthdrs	VNET(fw_deny_unknown_exthdrs)
114
#define	V_fw_deny_unknown_exthdrs	VNET(fw_deny_unknown_exthdrs)
115
115
116
VNET_DEFINE_STATIC(int, fw_permit_single_frag6) = 1;
116
VNET_DEFINE_STATIC(int, fw_permit_single_frag6) = 1;
117
#define	V_fw_permit_single_frag6	VNET(fw_permit_single_frag6)
117
#define	V_fw_permit_single_frag6	VNET(fw_permit_single_frag6)
118
118
119
#ifdef IPFIREWALL_DEFAULT_TO_ACCEPT
119
#ifdef IPFIREWALL_DEFAULT_TO_ACCEPT
120
static int default_to_accept = 1;
120
static int default_to_accept = 1;
121
#else
121
#else
122
static int default_to_accept;
122
static int default_to_accept;
123
#endif
123
#endif
124
124
125
VNET_DEFINE(int, autoinc_step);
125
VNET_DEFINE(int, autoinc_step);
126
VNET_DEFINE(int, fw_one_pass) = 1;
126
VNET_DEFINE(int, fw_one_pass) = 1;
127
127
128
VNET_DEFINE(unsigned int, fw_tables_max);
128
VNET_DEFINE(unsigned int, fw_tables_max);
129
VNET_DEFINE(unsigned int, fw_tables_sets) = 0;	/* Don't use set-aware tables */
129
VNET_DEFINE(unsigned int, fw_tables_sets) = 0;	/* Don't use set-aware tables */
130
/* Use 128 tables by default */
130
/* Use 128 tables by default */
131
static unsigned int default_fw_tables = IPFW_TABLES_DEFAULT;
131
static unsigned int default_fw_tables = IPFW_TABLES_DEFAULT;
132
132
133
#ifndef LINEAR_SKIPTO
133
#ifndef LINEAR_SKIPTO
134
static int jump_fast(struct ip_fw_chain *chain, struct ip_fw *f, int num,
134
static int jump_fast(struct ip_fw_chain *chain, struct ip_fw *f, int num,
135
    int tablearg, int jump_backwards);
135
    int tablearg, int jump_backwards);
136
#define	JUMP(ch, f, num, targ, back)	jump_fast(ch, f, num, targ, back)
136
#define	JUMP(ch, f, num, targ, back)	jump_fast(ch, f, num, targ, back)
137
#else
137
#else
138
static int jump_linear(struct ip_fw_chain *chain, struct ip_fw *f, int num,
138
static int jump_linear(struct ip_fw_chain *chain, struct ip_fw *f, int num,
139
    int tablearg, int jump_backwards);
139
    int tablearg, int jump_backwards);
140
#define	JUMP(ch, f, num, targ, back)	jump_linear(ch, f, num, targ, back)
140
#define	JUMP(ch, f, num, targ, back)	jump_linear(ch, f, num, targ, back)
141
#endif
141
#endif
142
142
143
/*
143
/*
144
 * Each rule belongs to one of 32 different sets (0..31).
144
 * Each rule belongs to one of 32 different sets (0..31).
145
 * The variable set_disable contains one bit per set.
145
 * The variable set_disable contains one bit per set.
146
 * If the bit is set, all rules in the corresponding set
146
 * If the bit is set, all rules in the corresponding set
147
 * are disabled. Set RESVD_SET(31) is reserved for the default rule
147
 * are disabled. Set RESVD_SET(31) is reserved for the default rule
148
 * and rules that are not deleted by the flush command,
148
 * and rules that are not deleted by the flush command,
149
 * and CANNOT be disabled.
149
 * and CANNOT be disabled.
150
 * Rules in set RESVD_SET can only be deleted individually.
150
 * Rules in set RESVD_SET can only be deleted individually.
151
 */
151
 */
152
VNET_DEFINE(u_int32_t, set_disable);
152
VNET_DEFINE(u_int32_t, set_disable);
153
#define	V_set_disable			VNET(set_disable)
153
#define	V_set_disable			VNET(set_disable)
154
154
155
VNET_DEFINE(int, fw_verbose);
155
VNET_DEFINE(int, fw_verbose);
156
/* counter for ipfw_log(NULL...) */
156
/* counter for ipfw_log(NULL...) */
157
VNET_DEFINE(u_int64_t, norule_counter);
157
VNET_DEFINE(u_int64_t, norule_counter);
158
VNET_DEFINE(int, verbose_limit);
158
VNET_DEFINE(int, verbose_limit);
159
159
160
/* layer3_chain contains the list of rules for layer 3 */
160
/* layer3_chain contains the list of rules for layer 3 */
161
VNET_DEFINE(struct ip_fw_chain, layer3_chain);
161
VNET_DEFINE(struct ip_fw_chain, layer3_chain);
162
162
163
/* ipfw_vnet_ready controls when we are open for business */
163
/* ipfw_vnet_ready controls when we are open for business */
164
VNET_DEFINE(int, ipfw_vnet_ready) = 0;
164
VNET_DEFINE(int, ipfw_vnet_ready) = 0;
165
165
166
VNET_DEFINE(int, ipfw_nat_ready) = 0;
166
VNET_DEFINE(int, ipfw_nat_ready) = 0;
167
167
168
ipfw_nat_t *ipfw_nat_ptr = NULL;
168
ipfw_nat_t *ipfw_nat_ptr = NULL;
169
struct cfg_nat *(*lookup_nat_ptr)(struct nat_list *, int);
169
struct cfg_nat *(*lookup_nat_ptr)(struct nat_list *, int);
170
ipfw_nat_cfg_t *ipfw_nat_cfg_ptr;
170
ipfw_nat_cfg_t *ipfw_nat_cfg_ptr;
171
ipfw_nat_cfg_t *ipfw_nat_del_ptr;
171
ipfw_nat_cfg_t *ipfw_nat_del_ptr;
172
ipfw_nat_cfg_t *ipfw_nat_get_cfg_ptr;
172
ipfw_nat_cfg_t *ipfw_nat_get_cfg_ptr;
173
ipfw_nat_cfg_t *ipfw_nat_get_log_ptr;
173
ipfw_nat_cfg_t *ipfw_nat_get_log_ptr;
174
174
175
#ifdef SYSCTL_NODE
175
#ifdef SYSCTL_NODE
176
uint32_t dummy_def = IPFW_DEFAULT_RULE;
176
uint32_t dummy_def = IPFW_DEFAULT_RULE;
177
static int sysctl_ipfw_table_num(SYSCTL_HANDLER_ARGS);
177
static int sysctl_ipfw_table_num(SYSCTL_HANDLER_ARGS);
178
static int sysctl_ipfw_tables_sets(SYSCTL_HANDLER_ARGS);
178
static int sysctl_ipfw_tables_sets(SYSCTL_HANDLER_ARGS);
179
179
180
SYSBEGIN(f3)
180
SYSBEGIN(f3)
181
181
182
SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
182
SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
183
    "Firewall");
183
    "Firewall");
184
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, one_pass,
184
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, one_pass,
185
    CTLFLAG_VNET | CTLFLAG_RW | CTLFLAG_SECURE3, &VNET_NAME(fw_one_pass), 0,
185
    CTLFLAG_VNET | CTLFLAG_RW | CTLFLAG_SECURE3, &VNET_NAME(fw_one_pass), 0,
186
    "Only do a single pass through ipfw when using dummynet(4)");
186
    "Only do a single pass through ipfw when using dummynet(4)");
187
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, autoinc_step,
187
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, autoinc_step,
188
    CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(autoinc_step), 0,
188
    CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(autoinc_step), 0,
189
    "Rule number auto-increment step");
189
    "Rule number auto-increment step");
190
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose,
190
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose,
191
    CTLFLAG_VNET | CTLFLAG_RW | CTLFLAG_SECURE3, &VNET_NAME(fw_verbose), 0,
191
    CTLFLAG_VNET | CTLFLAG_RW | CTLFLAG_SECURE3, &VNET_NAME(fw_verbose), 0,
192
    "Log matches to ipfw rules");
192
    "Log matches to ipfw rules");
193
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit,
193
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit,
194
    CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(verbose_limit), 0,
194
    CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(verbose_limit), 0,
195
    "Set upper limit of matches of ipfw rules logged");
195
    "Set upper limit of matches of ipfw rules logged");
196
SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, default_rule, CTLFLAG_RD,
196
SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, default_rule, CTLFLAG_RD,
197
    &dummy_def, 0,
197
    &dummy_def, 0,
198
    "The default/max possible rule number.");
198
    "The default/max possible rule number.");
199
SYSCTL_PROC(_net_inet_ip_fw, OID_AUTO, tables_max,
199
SYSCTL_PROC(_net_inet_ip_fw, OID_AUTO, tables_max,
200
    CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_MPSAFE,
200
    CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_MPSAFE,
201
    0, 0, sysctl_ipfw_table_num, "IU",
201
    0, 0, sysctl_ipfw_table_num, "IU",
202
    "Maximum number of concurrently used tables");
202
    "Maximum number of concurrently used tables");
203
SYSCTL_PROC(_net_inet_ip_fw, OID_AUTO, tables_sets,
203
SYSCTL_PROC(_net_inet_ip_fw, OID_AUTO, tables_sets,
204
    CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_MPSAFE,
204
    CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_MPSAFE,
205
    0, 0, sysctl_ipfw_tables_sets, "IU",
205
    0, 0, sysctl_ipfw_tables_sets, "IU",
206
    "Use per-set namespace for tables");
206
    "Use per-set namespace for tables");
207
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, default_to_accept, CTLFLAG_RDTUN,
207
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, default_to_accept, CTLFLAG_RDTUN,
208
    &default_to_accept, 0,
208
    &default_to_accept, 0,
209
    "Make the default rule accept all packets.");
209
    "Make the default rule accept all packets.");
210
TUNABLE_INT("net.inet.ip.fw.tables_max", (int *)&default_fw_tables);
210
TUNABLE_INT("net.inet.ip.fw.tables_max", (int *)&default_fw_tables);
211
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, static_count,
211
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, static_count,
212
    CTLFLAG_VNET | CTLFLAG_RD, &VNET_NAME(layer3_chain.n_rules), 0,
212
    CTLFLAG_VNET | CTLFLAG_RD, &VNET_NAME(layer3_chain.n_rules), 0,
213
    "Number of static rules");
213
    "Number of static rules");
214
214
215
#ifdef INET6
215
#ifdef INET6
216
SYSCTL_DECL(_net_inet6_ip6);
216
SYSCTL_DECL(_net_inet6_ip6);
217
SYSCTL_NODE(_net_inet6_ip6, OID_AUTO, fw, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
217
SYSCTL_NODE(_net_inet6_ip6, OID_AUTO, fw, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
218
    "Firewall");
218
    "Firewall");
219
SYSCTL_INT(_net_inet6_ip6_fw, OID_AUTO, deny_unknown_exthdrs,
219
SYSCTL_INT(_net_inet6_ip6_fw, OID_AUTO, deny_unknown_exthdrs,
220
    CTLFLAG_VNET | CTLFLAG_RW | CTLFLAG_SECURE,
220
    CTLFLAG_VNET | CTLFLAG_RW | CTLFLAG_SECURE,
221
    &VNET_NAME(fw_deny_unknown_exthdrs), 0,
221
    &VNET_NAME(fw_deny_unknown_exthdrs), 0,
222
    "Deny packets with unknown IPv6 Extension Headers");
222
    "Deny packets with unknown IPv6 Extension Headers");
223
SYSCTL_INT(_net_inet6_ip6_fw, OID_AUTO, permit_single_frag6,
223
SYSCTL_INT(_net_inet6_ip6_fw, OID_AUTO, permit_single_frag6,
224
    CTLFLAG_VNET | CTLFLAG_RW | CTLFLAG_SECURE,
224
    CTLFLAG_VNET | CTLFLAG_RW | CTLFLAG_SECURE,
225
    &VNET_NAME(fw_permit_single_frag6), 0,
225
    &VNET_NAME(fw_permit_single_frag6), 0,
226
    "Permit single packet IPv6 fragments");
226
    "Permit single packet IPv6 fragments");
227
#endif /* INET6 */
227
#endif /* INET6 */
228
228
229
SYSEND
229
SYSEND
230
230
231
#endif /* SYSCTL_NODE */
231
#endif /* SYSCTL_NODE */
232
232
233
233
234
/*
234
/*
235
 * Some macros used in the various matching options.
235
 * Some macros used in the various matching options.
236
 * L3HDR maps an ipv4 pointer into a layer3 header pointer of type T
236
 * L3HDR maps an ipv4 pointer into a layer3 header pointer of type T
237
 * Other macros just cast void * into the appropriate type
237
 * Other macros just cast void * into the appropriate type
238
 */
238
 */
239
#define	L3HDR(T, ip)	((T *)((u_int32_t *)(ip) + (ip)->ip_hl))
239
#define	L3HDR(T, ip)	((T *)((u_int32_t *)(ip) + (ip)->ip_hl))
240
#define	TCP(p)		((struct tcphdr *)(p))
240
#define	TCP(p)		((struct tcphdr *)(p))
241
#define	SCTP(p)		((struct sctphdr *)(p))
241
#define	SCTP(p)		((struct sctphdr *)(p))
242
#define	UDP(p)		((struct udphdr *)(p))
242
#define	UDP(p)		((struct udphdr *)(p))
243
#define	ICMP(p)		((struct icmphdr *)(p))
243
#define	ICMP(p)		((struct icmphdr *)(p))
244
#define	ICMP6(p)	((struct icmp6_hdr *)(p))
244
#define	ICMP6(p)	((struct icmp6_hdr *)(p))
245
245
246
static __inline int
246
static __inline int
247
icmptype_match(struct icmphdr *icmp, ipfw_insn_u32 *cmd)
247
icmptype_match(struct icmphdr *icmp, ipfw_insn_u32 *cmd)
248
{
248
{
249
	int type = icmp->icmp_type;
249
	int type = icmp->icmp_type;
250
250
251
	return (type <= ICMP_MAXTYPE && (cmd->d[0] & (1<<type)) );
251
	return (type <= ICMP_MAXTYPE && (cmd->d[0] & (1<<type)) );
252
}
252
}
253
253
254
#define TT	( (1 << ICMP_ECHO) | (1 << ICMP_ROUTERSOLICIT) | \
254
#define TT	( (1 << ICMP_ECHO) | (1 << ICMP_ROUTERSOLICIT) | \
255
    (1 << ICMP_TSTAMP) | (1 << ICMP_IREQ) | (1 << ICMP_MASKREQ) )
255
    (1 << ICMP_TSTAMP) | (1 << ICMP_IREQ) | (1 << ICMP_MASKREQ) )
256
256
257
static int
257
static int
258
is_icmp_query(struct icmphdr *icmp)
258
is_icmp_query(struct icmphdr *icmp)
259
{
259
{
260
	int type = icmp->icmp_type;
260
	int type = icmp->icmp_type;
261
261
262
	return (type <= ICMP_MAXTYPE && (TT & (1<<type)) );
262
	return (type <= ICMP_MAXTYPE && (TT & (1<<type)) );
263
}
263
}
264
#undef TT
264
#undef TT
265
265
266
/*
266
/*
267
 * The following checks use two arrays of 8 or 16 bits to store the
267
 * The following checks use two arrays of 8 or 16 bits to store the
268
 * bits that we want set or clear, respectively. They are in the
268
 * bits that we want set or clear, respectively. They are in the
269
 * low and high half of cmd->arg1 or cmd->d[0].
269
 * low and high half of cmd->arg1 or cmd->d[0].
270
 *
270
 *
271
 * We scan options and store the bits we find set. We succeed if
271
 * We scan options and store the bits we find set. We succeed if
272
 *
272
 *
273
 *	(want_set & ~bits) == 0 && (want_clear & ~bits) == want_clear
273
 *	(want_set & ~bits) == 0 && (want_clear & ~bits) == want_clear
274
 *
274
 *
275
 * The code is sometimes optimized not to store additional variables.
275
 * The code is sometimes optimized not to store additional variables.
276
 */
276
 */
277
277
278
static int
278
static int
279
flags_match(ipfw_insn *cmd, u_int8_t bits)
279
flags_match(ipfw_insn *cmd, u_int8_t bits)
280
{
280
{
281
	u_char want_clear;
281
	u_char want_clear;
282
	bits = ~bits;
282
	bits = ~bits;
283
283
284
	if ( ((cmd->arg1 & 0xff) & bits) != 0)
284
	if ( ((cmd->arg1 & 0xff) & bits) != 0)
285
		return 0; /* some bits we want set were clear */
285
		return 0; /* some bits we want set were clear */
286
	want_clear = (cmd->arg1 >> 8) & 0xff;
286
	want_clear = (cmd->arg1 >> 8) & 0xff;
287
	if ( (want_clear & bits) != want_clear)
287
	if ( (want_clear & bits) != want_clear)
288
		return 0; /* some bits we want clear were set */
288
		return 0; /* some bits we want clear were set */
289
	return 1;
289
	return 1;
290
}
290
}
291
291
292
static int
292
static int
293
ipopts_match(struct ip *ip, ipfw_insn *cmd)
293
ipopts_match(struct ip *ip, ipfw_insn *cmd)
294
{
294
{
295
	int optlen, bits = 0;
295
	int optlen, bits = 0;
296
	u_char *cp = (u_char *)(ip + 1);
296
	u_char *cp = (u_char *)(ip + 1);
297
	int x = (ip->ip_hl << 2) - sizeof (struct ip);
297
	int x = (ip->ip_hl << 2) - sizeof (struct ip);
298
298
299
	for (; x > 0; x -= optlen, cp += optlen) {
299
	for (; x > 0; x -= optlen, cp += optlen) {
300
		int opt = cp[IPOPT_OPTVAL];
300
		int opt = cp[IPOPT_OPTVAL];
301
301
302
		if (opt == IPOPT_EOL)
302
		if (opt == IPOPT_EOL)
303
			break;
303
			break;
304
		if (opt == IPOPT_NOP)
304
		if (opt == IPOPT_NOP)
305
			optlen = 1;
305
			optlen = 1;
306
		else {
306
		else {
307
			optlen = cp[IPOPT_OLEN];
307
			optlen = cp[IPOPT_OLEN];
308
			if (optlen <= 0 || optlen > x)
308
			if (optlen <= 0 || optlen > x)
309
				return 0; /* invalid or truncated */
309
				return 0; /* invalid or truncated */
310
		}
310
		}
311
		switch (opt) {
311
		switch (opt) {
312
312
313
		default:
313
		default:
314
			break;
314
			break;
315
315
316
		case IPOPT_LSRR:
316
		case IPOPT_LSRR:
317
			bits |= IP_FW_IPOPT_LSRR;
317
			bits |= IP_FW_IPOPT_LSRR;
318
			break;
318
			break;
319
319
320
		case IPOPT_SSRR:
320
		case IPOPT_SSRR:
321
			bits |= IP_FW_IPOPT_SSRR;
321
			bits |= IP_FW_IPOPT_SSRR;
322
			break;
322
			break;
323
323
324
		case IPOPT_RR:
324
		case IPOPT_RR:
325
			bits |= IP_FW_IPOPT_RR;
325
			bits |= IP_FW_IPOPT_RR;
326
			break;
326
			break;
327
327
328
		case IPOPT_TS:
328
		case IPOPT_TS:
329
			bits |= IP_FW_IPOPT_TS;
329
			bits |= IP_FW_IPOPT_TS;
330
			break;
330
			break;
331
		}
331
		}
332
	}
332
	}
333
	return (flags_match(cmd, bits));
333
	return (flags_match(cmd, bits));
334
}
334
}
335
335
336
/*
336
/*
337
 * Parse TCP options. The logic copied from tcp_dooptions().
337
 * Parse TCP options. The logic copied from tcp_dooptions().
338
 */
338
 */
339
static int
339
static int
340
tcpopts_parse(const struct tcphdr *tcp, uint16_t *mss)
340
tcpopts_parse(const struct tcphdr *tcp, uint16_t *mss)
341
{
341
{
342
	const u_char *cp = (const u_char *)(tcp + 1);
342
	const u_char *cp = (const u_char *)(tcp + 1);
343
	int optlen, bits = 0;
343
	int optlen, bits = 0;
344
	int cnt = (tcp->th_off << 2) - sizeof(struct tcphdr);
344
	int cnt = (tcp->th_off << 2) - sizeof(struct tcphdr);
345
345
346
	for (; cnt > 0; cnt -= optlen, cp += optlen) {
346
	for (; cnt > 0; cnt -= optlen, cp += optlen) {
347
		int opt = cp[0];
347
		int opt = cp[0];
348
		if (opt == TCPOPT_EOL)
348
		if (opt == TCPOPT_EOL)
349
			break;
349
			break;
350
		if (opt == TCPOPT_NOP)
350
		if (opt == TCPOPT_NOP)
351
			optlen = 1;
351
			optlen = 1;
352
		else {
352
		else {
353
			if (cnt < 2)
353
			if (cnt < 2)
354
				break;
354
				break;
355
			optlen = cp[1];
355
			optlen = cp[1];
356
			if (optlen < 2 || optlen > cnt)
356
			if (optlen < 2 || optlen > cnt)
357
				break;
357
				break;
358
		}
358
		}
359
359
360
		switch (opt) {
360
		switch (opt) {
361
		default:
361
		default:
362
			break;
362
			break;
363
363
364
		case TCPOPT_MAXSEG:
364
		case TCPOPT_MAXSEG:
365
			if (optlen != TCPOLEN_MAXSEG)
365
			if (optlen != TCPOLEN_MAXSEG)
366
				break;
366
				break;
367
			bits |= IP_FW_TCPOPT_MSS;
367
			bits |= IP_FW_TCPOPT_MSS;
368
			if (mss != NULL)
368
			if (mss != NULL)
369
				*mss = be16dec(cp + 2);
369
				*mss = be16dec(cp + 2);
370
			break;
370
			break;
371
371
372
		case TCPOPT_WINDOW:
372
		case TCPOPT_WINDOW:
373
			if (optlen == TCPOLEN_WINDOW)
373
			if (optlen == TCPOLEN_WINDOW)
374
				bits |= IP_FW_TCPOPT_WINDOW;
374
				bits |= IP_FW_TCPOPT_WINDOW;
375
			break;
375
			break;
376
376
377
		case TCPOPT_SACK_PERMITTED:
377
		case TCPOPT_SACK_PERMITTED:
378
			if (optlen == TCPOLEN_SACK_PERMITTED)
378
			if (optlen == TCPOLEN_SACK_PERMITTED)
379
				bits |= IP_FW_TCPOPT_SACK;
379
				bits |= IP_FW_TCPOPT_SACK;
380
			break;
380
			break;
381
381
382
		case TCPOPT_SACK:
382
		case TCPOPT_SACK:
383
			if (optlen > 2 && (optlen - 2) % TCPOLEN_SACK == 0)
383
			if (optlen > 2 && (optlen - 2) % TCPOLEN_SACK == 0)
384
				bits |= IP_FW_TCPOPT_SACK;
384
				bits |= IP_FW_TCPOPT_SACK;
385
			break;
385
			break;
386
386
387
		case TCPOPT_TIMESTAMP:
387
		case TCPOPT_TIMESTAMP:
388
			if (optlen == TCPOLEN_TIMESTAMP)
388
			if (optlen == TCPOLEN_TIMESTAMP)
389
				bits |= IP_FW_TCPOPT_TS;
389
				bits |= IP_FW_TCPOPT_TS;
390
			break;
390
			break;
391
		}
391
		}
392
	}
392
	}
393
	return (bits);
393
	return (bits);
394
}
394
}
395
395
396
static int
396
static int
397
tcpopts_match(struct tcphdr *tcp, ipfw_insn *cmd)
397
tcpopts_match(struct tcphdr *tcp, ipfw_insn *cmd)
398
{
398
{
399
399
400
	return (flags_match(cmd, tcpopts_parse(tcp, NULL)));
400
	return (flags_match(cmd, tcpopts_parse(tcp, NULL)));
401
}
401
}
402
402
403
static int
403
static int
404
iface_match(struct ifnet *ifp, ipfw_insn_if *cmd, struct ip_fw_chain *chain,
404
iface_match(struct ifnet *ifp, ipfw_insn_if *cmd, struct ip_fw_chain *chain,
405
    uint32_t *tablearg)
405
    uint32_t *tablearg)
406
{
406
{
407
407
408
	if (ifp == NULL)	/* no iface with this packet, match fails */
408
	if (ifp == NULL)	/* no iface with this packet, match fails */
409
		return (0);
409
		return (0);
410
410
411
	/* Check by name or by IP address */
411
	/* Check by name or by IP address */
412
	if (cmd->name[0] != '\0') { /* match by name */
412
	if (cmd->name[0] != '\0') { /* match by name */
413
		if (cmd->name[0] == '\1') /* use tablearg to match */
413
		if (cmd->name[0] == '\1') /* use tablearg to match */
414
			return ipfw_lookup_table(chain, cmd->p.kidx, 0,
414
			return ipfw_lookup_table(chain, cmd->p.kidx, 0,
415
			    &ifp->if_index, tablearg);
415
			    &ifp->if_index, tablearg);
416
		/* Check name */
416
		/* Check name */
417
		if (cmd->p.glob) {
417
		if (cmd->p.glob) {
418
			if (fnmatch(cmd->name, ifp->if_xname, 0) == 0)
418
			if (fnmatch(cmd->name, ifp->if_xname, 0) == 0)
419
				return(1);
419
				return(1);
420
		} else {
420
		} else {
421
			if (strncmp(ifp->if_xname, cmd->name, IFNAMSIZ) == 0)
421
			if (strncmp(ifp->if_xname, cmd->name, IFNAMSIZ) == 0)
422
				return(1);
422
				return(1);
423
		}
423
		}
424
	} else {
424
	} else {
425
#if !defined(USERSPACE) && defined(__FreeBSD__)	/* and OSX too ? */
425
#if !defined(USERSPACE) && defined(__FreeBSD__)	/* and OSX too ? */
426
		struct ifaddr *ia;
426
		struct ifaddr *ia;
427
427
428
		NET_EPOCH_ASSERT();
428
		NET_EPOCH_ASSERT();
429
429
430
		CK_STAILQ_FOREACH(ia, &ifp->if_addrhead, ifa_link) {
430
		CK_STAILQ_FOREACH(ia, &ifp->if_addrhead, ifa_link) {
431
			if (ia->ifa_addr->sa_family != AF_INET)
431
			if (ia->ifa_addr->sa_family != AF_INET)
432
				continue;
432
				continue;
433
			if (cmd->p.ip.s_addr == ((struct sockaddr_in *)
433
			if (cmd->p.ip.s_addr == ((struct sockaddr_in *)
434
			    (ia->ifa_addr))->sin_addr.s_addr)
434
			    (ia->ifa_addr))->sin_addr.s_addr)
435
				return (1);	/* match */
435
				return (1);	/* match */
436
		}
436
		}
437
#endif /* __FreeBSD__ */
437
#endif /* __FreeBSD__ */
438
	}
438
	}
439
	return(0);	/* no match, fail ... */
439
	return(0);	/* no match, fail ... */
440
}
440
}
441
441
442
/*
442
/*
443
 * The verify_path function checks if a route to the src exists and
443
 * The verify_path function checks if a route to the src exists and
444
 * if it is reachable via ifp (when provided).
444
 * if it is reachable via ifp (when provided).
445
 * 
445
 * 
446
 * The 'verrevpath' option checks that the interface that an IP packet
446
 * The 'verrevpath' option checks that the interface that an IP packet
447
 * arrives on is the same interface that traffic destined for the
447
 * arrives on is the same interface that traffic destined for the
448
 * packet's source address would be routed out of.
448
 * packet's source address would be routed out of.
449
 * The 'versrcreach' option just checks that the source address is
449
 * The 'versrcreach' option just checks that the source address is
450
 * reachable via any route (except default) in the routing table.
450
 * reachable via any route (except default) in the routing table.
451
 * These two are a measure to block forged packets. This is also
451
 * These two are a measure to block forged packets. This is also
452
 * commonly known as "anti-spoofing" or Unicast Reverse Path
452
 * commonly known as "anti-spoofing" or Unicast Reverse Path
453
 * Forwarding (Unicast RFP) in Cisco-ese. The name of the knobs
453
 * Forwarding (Unicast RFP) in Cisco-ese. The name of the knobs
454
 * is purposely reminiscent of the Cisco IOS command,
454
 * is purposely reminiscent of the Cisco IOS command,
455
 *
455
 *
456
 *   ip verify unicast reverse-path
456
 *   ip verify unicast reverse-path
457
 *   ip verify unicast source reachable-via any
457
 *   ip verify unicast source reachable-via any
458
 *
458
 *
459
 * which implements the same functionality. But note that the syntax
459
 * which implements the same functionality. But note that the syntax
460
 * is misleading, and the check may be performed on all IP packets
460
 * is misleading, and the check may be performed on all IP packets
461
 * whether unicast, multicast, or broadcast.
461
 * whether unicast, multicast, or broadcast.
462
 */
462
 */
463
static int
463
static int
464
verify_path(struct in_addr src, struct ifnet *ifp, u_int fib)
464
verify_path(struct in_addr src, struct ifnet *ifp, u_int fib)
465
{
465
{
466
#if defined(USERSPACE) || !defined(__FreeBSD__)
466
#if defined(USERSPACE) || !defined(__FreeBSD__)
467
	return 0;
467
	return 0;
468
#else
468
#else
469
	struct nhop4_basic nh4;
469
	struct nhop4_basic nh4;
470
470
471
	if (fib4_lookup_nh_basic(fib, src, NHR_IFAIF, 0, &nh4) != 0)
471
	if (fib4_lookup_nh_basic(fib, src, NHR_IFAIF, 0, &nh4) != 0)
472
		return (0);
472
		return (0);
473
473
474
	/*
474
	/*
475
	 * If ifp is provided, check for equality with rtentry.
475
	 * If ifp is provided, check for equality with rtentry.
476
	 * We should use rt->rt_ifa->ifa_ifp, instead of rt->rt_ifp,
476
	 * We should use rt->rt_ifa->ifa_ifp, instead of rt->rt_ifp,
477
	 * in order to pass packets injected back by if_simloop():
477
	 * in order to pass packets injected back by if_simloop():
478
	 * routing entry (via lo0) for our own address
478
	 * routing entry (via lo0) for our own address
479
	 * may exist, so we need to handle routing assymetry.
479
	 * may exist, so we need to handle routing assymetry.
480
	 */
480
	 */
481
	if (ifp != NULL && ifp != nh4.nh_ifp)
481
	if (ifp != NULL && ifp != nh4.nh_ifp)
482
		return (0);
482
		return (0);
483
483
484
	/* if no ifp provided, check if rtentry is not default route */
484
	/* if no ifp provided, check if rtentry is not default route */
485
	if (ifp == NULL && (nh4.nh_flags & NHF_DEFAULT) != 0)
485
	if (ifp == NULL && (nh4.nh_flags & NHF_DEFAULT) != 0)
486
		return (0);
486
		return (0);
487
487
488
	/* or if this is a blackhole/reject route */
488
	/* or if this is a blackhole/reject route */
489
	if (ifp == NULL && (nh4.nh_flags & (NHF_REJECT|NHF_BLACKHOLE)) != 0)
489
	if (ifp == NULL && (nh4.nh_flags & (NHF_REJECT|NHF_BLACKHOLE)) != 0)
490
		return (0);
490
		return (0);
491
491
492
	/* found valid route */
492
	/* found valid route */
493
	return 1;
493
	return 1;
494
#endif /* __FreeBSD__ */
494
#endif /* __FreeBSD__ */
495
}
495
}
496
496
497
/*
497
/*
498
 * Generate an SCTP packet containing an ABORT chunk. The verification tag
498
 * Generate an SCTP packet containing an ABORT chunk. The verification tag
499
 * is given by vtag. The T-bit is set in the ABORT chunk if and only if
499
 * is given by vtag. The T-bit is set in the ABORT chunk if and only if
500
 * reflected is not 0.
500
 * reflected is not 0.
501
 */
501
 */
502
502
503
static struct mbuf *
503
static struct mbuf *
504
ipfw_send_abort(struct mbuf *replyto, struct ipfw_flow_id *id, u_int32_t vtag,
504
ipfw_send_abort(struct mbuf *replyto, struct ipfw_flow_id *id, u_int32_t vtag,
505
    int reflected)
505
    int reflected)
506
{
506
{
507
	struct mbuf *m;
507
	struct mbuf *m;
508
	struct ip *ip;
508
	struct ip *ip;
509
#ifdef INET6
509
#ifdef INET6
510
	struct ip6_hdr *ip6;
510
	struct ip6_hdr *ip6;
511
#endif
511
#endif
512
	struct sctphdr *sctp;
512
	struct sctphdr *sctp;
513
	struct sctp_chunkhdr *chunk;
513
	struct sctp_chunkhdr *chunk;
514
	u_int16_t hlen, plen, tlen;
514
	u_int16_t hlen, plen, tlen;
515
515
516
	MGETHDR(m, M_NOWAIT, MT_DATA);
516
	MGETHDR(m, M_NOWAIT, MT_DATA);
517
	if (m == NULL)
517
	if (m == NULL)
518
		return (NULL);
518
		return (NULL);
519
519
520
	M_SETFIB(m, id->fib);
520
	M_SETFIB(m, id->fib);
521
#ifdef MAC
521
#ifdef MAC
522
	if (replyto != NULL)
522
	if (replyto != NULL)
523
		mac_netinet_firewall_reply(replyto, m);
523
		mac_netinet_firewall_reply(replyto, m);
524
	else
524
	else
525
		mac_netinet_firewall_send(m);
525
		mac_netinet_firewall_send(m);
526
#else
526
#else
527
	(void)replyto;		/* don't warn about unused arg */
527
	(void)replyto;		/* don't warn about unused arg */
528
#endif
528
#endif
529
529
530
	switch (id->addr_type) {
530
	switch (id->addr_type) {
531
	case 4:
531
	case 4:
532
		hlen = sizeof(struct ip);
532
		hlen = sizeof(struct ip);
533
		break;
533
		break;
534
#ifdef INET6
534
#ifdef INET6
535
	case 6:
535
	case 6:
536
		hlen = sizeof(struct ip6_hdr);
536
		hlen = sizeof(struct ip6_hdr);
537
		break;
537
		break;
538
#endif
538
#endif
539
	default:
539
	default:
540
		/* XXX: log me?!? */
540
		/* XXX: log me?!? */
541
		FREE_PKT(m);
541
		FREE_PKT(m);
542
		return (NULL);
542
		return (NULL);
543
	}
543
	}
544
	plen = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
544
	plen = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
545
	tlen = hlen + plen;
545
	tlen = hlen + plen;
546
	m->m_data += max_linkhdr;
546
	m->m_data += max_linkhdr;
547
	m->m_flags |= M_SKIP_FIREWALL;
547
	m->m_flags |= M_SKIP_FIREWALL;
548
	m->m_pkthdr.len = m->m_len = tlen;
548
	m->m_pkthdr.len = m->m_len = tlen;
549
	m->m_pkthdr.rcvif = NULL;
549
	m->m_pkthdr.rcvif = NULL;
550
	bzero(m->m_data, tlen);
550
	bzero(m->m_data, tlen);
551
551
552
	switch (id->addr_type) {
552
	switch (id->addr_type) {
553
	case 4:
553
	case 4:
554
		ip = mtod(m, struct ip *);
554
		ip = mtod(m, struct ip *);
555
555
556
		ip->ip_v = 4;
556
		ip->ip_v = 4;
557
		ip->ip_hl = sizeof(struct ip) >> 2;
557
		ip->ip_hl = sizeof(struct ip) >> 2;
558
		ip->ip_tos = IPTOS_LOWDELAY;
558
		ip->ip_tos = IPTOS_LOWDELAY;
559
		ip->ip_len = htons(tlen);
559
		ip->ip_len = htons(tlen);
560
		ip->ip_id = htons(0);
560
		ip->ip_id = htons(0);
561
		ip->ip_off = htons(0);
561
		ip->ip_off = htons(0);
562
		ip->ip_ttl = V_ip_defttl;
562
		ip->ip_ttl = V_ip_defttl;
563
		ip->ip_p = IPPROTO_SCTP;
563
		ip->ip_p = IPPROTO_SCTP;
564
		ip->ip_sum = 0;
564
		ip->ip_sum = 0;
565
		ip->ip_src.s_addr = htonl(id->dst_ip);
565
		ip->ip_src.s_addr = htonl(id->dst_ip);
566
		ip->ip_dst.s_addr = htonl(id->src_ip);
566
		ip->ip_dst.s_addr = htonl(id->src_ip);
567
567
568
		sctp = (struct sctphdr *)(ip + 1);
568
		sctp = (struct sctphdr *)(ip + 1);
569
		break;
569
		break;
570
#ifdef INET6
570
#ifdef INET6
571
	case 6:
571
	case 6:
572
		ip6 = mtod(m, struct ip6_hdr *);
572
		ip6 = mtod(m, struct ip6_hdr *);
573
573
574
		ip6->ip6_vfc = IPV6_VERSION;
574
		ip6->ip6_vfc = IPV6_VERSION;
575
		ip6->ip6_plen = htons(plen);
575
		ip6->ip6_plen = htons(plen);
576
		ip6->ip6_nxt = IPPROTO_SCTP;
576
		ip6->ip6_nxt = IPPROTO_SCTP;
577
		ip6->ip6_hlim = IPV6_DEFHLIM;
577
		ip6->ip6_hlim = IPV6_DEFHLIM;
578
		ip6->ip6_src = id->dst_ip6;
578
		ip6->ip6_src = id->dst_ip6;
579
		ip6->ip6_dst = id->src_ip6;
579
		ip6->ip6_dst = id->src_ip6;
580
580
581
		sctp = (struct sctphdr *)(ip6 + 1);
581
		sctp = (struct sctphdr *)(ip6 + 1);
582
		break;
582
		break;
583
#endif
583
#endif
584
	}
584
	}
585
585
586
	sctp->src_port = htons(id->dst_port);
586
	sctp->src_port = htons(id->dst_port);
587
	sctp->dest_port = htons(id->src_port);
587
	sctp->dest_port = htons(id->src_port);
588
	sctp->v_tag = htonl(vtag);
588
	sctp->v_tag = htonl(vtag);
589
	sctp->checksum = htonl(0);
589
	sctp->checksum = htonl(0);
590
590
591
	chunk = (struct sctp_chunkhdr *)(sctp + 1);
591
	chunk = (struct sctp_chunkhdr *)(sctp + 1);
592
	chunk->chunk_type = SCTP_ABORT_ASSOCIATION;
592
	chunk->chunk_type = SCTP_ABORT_ASSOCIATION;
593
	chunk->chunk_flags = 0;
593
	chunk->chunk_flags = 0;
594
	if (reflected != 0) {
594
	if (reflected != 0) {
595
		chunk->chunk_flags |= SCTP_HAD_NO_TCB;
595
		chunk->chunk_flags |= SCTP_HAD_NO_TCB;
596
	}
596
	}
597
	chunk->chunk_length = htons(sizeof(struct sctp_chunkhdr));
597
	chunk->chunk_length = htons(sizeof(struct sctp_chunkhdr));
598
598
599
	sctp->checksum = sctp_calculate_cksum(m, hlen);
599
	sctp->checksum = sctp_calculate_cksum(m, hlen);
600
600
601
	return (m);
601
	return (m);
602
}
602
}
603
603
604
/*
604
/*
605
 * Generate a TCP packet, containing either a RST or a keepalive.
605
 * Generate a TCP packet, containing either a RST or a keepalive.
606
 * When flags & TH_RST, we are sending a RST packet, because of a
606
 * When flags & TH_RST, we are sending a RST packet, because of a
607
 * "reset" action matched the packet.
607
 * "reset" action matched the packet.
608
 * Otherwise we are sending a keepalive, and flags & TH_
608
 * Otherwise we are sending a keepalive, and flags & TH_
609
 * The 'replyto' mbuf is the mbuf being replied to, if any, and is required
609
 * The 'replyto' mbuf is the mbuf being replied to, if any, and is required
610
 * so that MAC can label the reply appropriately.
610
 * so that MAC can label the reply appropriately.
611
 */
611
 */
612
struct mbuf *
612
struct mbuf *
613
ipfw_send_pkt(struct mbuf *replyto, struct ipfw_flow_id *id, u_int32_t seq,
613
ipfw_send_pkt(struct mbuf *replyto, struct ipfw_flow_id *id, u_int32_t seq,
614
    u_int32_t ack, int flags)
614
    u_int32_t ack, int flags)
615
{
615
{
616
	struct mbuf *m = NULL;		/* stupid compiler */
616
	struct mbuf *m = NULL;		/* stupid compiler */
617
	struct ip *h = NULL;		/* stupid compiler */
617
	struct ip *h = NULL;		/* stupid compiler */
618
#ifdef INET6
618
#ifdef INET6
619
	struct ip6_hdr *h6 = NULL;
619
	struct ip6_hdr *h6 = NULL;
620
#endif
620
#endif
621
	struct tcphdr *th = NULL;
621
	struct tcphdr *th = NULL;
622
	int len, dir;
622
	int len, dir;
623
623
624
	MGETHDR(m, M_NOWAIT, MT_DATA);
624
	MGETHDR(m, M_NOWAIT, MT_DATA);
625
	if (m == NULL)
625
	if (m == NULL)
626
		return (NULL);
626
		return (NULL);
627
627
628
	M_SETFIB(m, id->fib);
628
	M_SETFIB(m, id->fib);
629
#ifdef MAC
629
#ifdef MAC
630
	if (replyto != NULL)
630
	if (replyto != NULL)
631
		mac_netinet_firewall_reply(replyto, m);
631
		mac_netinet_firewall_reply(replyto, m);
632
	else
632
	else
633
		mac_netinet_firewall_send(m);
633
		mac_netinet_firewall_send(m);
634
#else
634
#else
635
	(void)replyto;		/* don't warn about unused arg */
635
	(void)replyto;		/* don't warn about unused arg */
636
#endif
636
#endif
637
637
638
	switch (id->addr_type) {
638
	switch (id->addr_type) {
639
	case 4:
639
	case 4:
640
		len = sizeof(struct ip) + sizeof(struct tcphdr);
640
		len = sizeof(struct ip) + sizeof(struct tcphdr);
641
		break;
641
		break;
642
#ifdef INET6
642
#ifdef INET6
643
	case 6:
643
	case 6:
644
		len = sizeof(struct ip6_hdr) + sizeof(struct tcphdr);
644
		len = sizeof(struct ip6_hdr) + sizeof(struct tcphdr);
645
		break;
645
		break;
646
#endif
646
#endif
647
	default:
647
	default:
648
		/* XXX: log me?!? */
648
		/* XXX: log me?!? */
649
		FREE_PKT(m);
649
		FREE_PKT(m);
650
		return (NULL);
650
		return (NULL);
651
	}
651
	}
652
	dir = ((flags & (TH_SYN | TH_RST)) == TH_SYN);
652
	dir = ((flags & (TH_SYN | TH_RST)) == TH_SYN);
653
653
654
	m->m_data += max_linkhdr;
654
	m->m_data += max_linkhdr;
655
	m->m_flags |= M_SKIP_FIREWALL;
655
	m->m_flags |= M_SKIP_FIREWALL;
656
	m->m_pkthdr.len = m->m_len = len;
656
	m->m_pkthdr.len = m->m_len = len;
657
	m->m_pkthdr.rcvif = NULL;
657
	m->m_pkthdr.rcvif = NULL;
658
	bzero(m->m_data, len);
658
	bzero(m->m_data, len);
659
659
660
	switch (id->addr_type) {
660
	switch (id->addr_type) {
661
	case 4:
661
	case 4:
662
		h = mtod(m, struct ip *);
662
		h = mtod(m, struct ip *);
663
663
664
		/* prepare for checksum */
664
		/* prepare for checksum */
665
		h->ip_p = IPPROTO_TCP;
665
		h->ip_p = IPPROTO_TCP;
666
		h->ip_len = htons(sizeof(struct tcphdr));
666
		h->ip_len = htons(sizeof(struct tcphdr));
667
		if (dir) {
667
		if (dir) {
668
			h->ip_src.s_addr = htonl(id->src_ip);
668
			h->ip_src.s_addr = htonl(id->src_ip);
669
			h->ip_dst.s_addr = htonl(id->dst_ip);
669
			h->ip_dst.s_addr = htonl(id->dst_ip);
670
		} else {
670
		} else {
671
			h->ip_src.s_addr = htonl(id->dst_ip);
671
			h->ip_src.s_addr = htonl(id->dst_ip);
672
			h->ip_dst.s_addr = htonl(id->src_ip);
672
			h->ip_dst.s_addr = htonl(id->src_ip);
673
		}
673
		}
674
674
675
		th = (struct tcphdr *)(h + 1);
675
		th = (struct tcphdr *)(h + 1);
676
		break;
676
		break;
677
#ifdef INET6
677
#ifdef INET6
678
	case 6:
678
	case 6:
679
		h6 = mtod(m, struct ip6_hdr *);
679
		h6 = mtod(m, struct ip6_hdr *);
680
680
681
		/* prepare for checksum */
681
		/* prepare for checksum */
682
		h6->ip6_nxt = IPPROTO_TCP;
682
		h6->ip6_nxt = IPPROTO_TCP;
683
		h6->ip6_plen = htons(sizeof(struct tcphdr));
683
		h6->ip6_plen = htons(sizeof(struct tcphdr));
684
		if (dir) {
684
		if (dir) {
685
			h6->ip6_src = id->src_ip6;
685
			h6->ip6_src = id->src_ip6;
686
			h6->ip6_dst = id->dst_ip6;
686
			h6->ip6_dst = id->dst_ip6;
687
		} else {
687
		} else {
688
			h6->ip6_src = id->dst_ip6;
688
			h6->ip6_src = id->dst_ip6;
689
			h6->ip6_dst = id->src_ip6;
689
			h6->ip6_dst = id->src_ip6;
690
		}
690
		}
691
691
692
		th = (struct tcphdr *)(h6 + 1);
692
		th = (struct tcphdr *)(h6 + 1);
693
		break;
693
		break;
694
#endif
694
#endif
695
	}
695
	}
696
696
697
	if (dir) {
697
	if (dir) {
698
		th->th_sport = htons(id->src_port);
698
		th->th_sport = htons(id->src_port);
699
		th->th_dport = htons(id->dst_port);
699
		th->th_dport = htons(id->dst_port);
700
	} else {
700
	} else {
701
		th->th_sport = htons(id->dst_port);
701
		th->th_sport = htons(id->dst_port);
702
		th->th_dport = htons(id->src_port);
702
		th->th_dport = htons(id->src_port);
703
	}
703
	}
704
	th->th_off = sizeof(struct tcphdr) >> 2;
704
	th->th_off = sizeof(struct tcphdr) >> 2;
705
705
706
	if (flags & TH_RST) {
706
	if (flags & TH_RST) {
707
		if (flags & TH_ACK) {
707
		if (flags & TH_ACK) {
708
			th->th_seq = htonl(ack);
708
			th->th_seq = htonl(ack);
709
			th->th_flags = TH_RST;
709
			th->th_flags = TH_RST;
710
		} else {
710
		} else {
711
			if (flags & TH_SYN)
711
			if (flags & TH_SYN)
712
				seq++;
712
				seq++;
713
			th->th_ack = htonl(seq);
713
			th->th_ack = htonl(seq);
714
			th->th_flags = TH_RST | TH_ACK;
714
			th->th_flags = TH_RST | TH_ACK;
715
		}
715
		}
716
	} else {
716
	} else {
717
		/*
717
		/*
718
		 * Keepalive - use caller provided sequence numbers
718
		 * Keepalive - use caller provided sequence numbers
719
		 */
719
		 */
720
		th->th_seq = htonl(seq);
720
		th->th_seq = htonl(seq);
721
		th->th_ack = htonl(ack);
721
		th->th_ack = htonl(ack);
722
		th->th_flags = TH_ACK;
722
		th->th_flags = TH_ACK;
723
	}
723
	}
724
724
725
	switch (id->addr_type) {
725
	switch (id->addr_type) {
726
	case 4:
726
	case 4:
727
		th->th_sum = in_cksum(m, len);
727
		th->th_sum = in_cksum(m, len);
728
728
729
		/* finish the ip header */
729
		/* finish the ip header */
730
		h->ip_v = 4;
730
		h->ip_v = 4;
731
		h->ip_hl = sizeof(*h) >> 2;
731
		h->ip_hl = sizeof(*h) >> 2;
732
		h->ip_tos = IPTOS_LOWDELAY;
732
		h->ip_tos = IPTOS_LOWDELAY;
733
		h->ip_off = htons(0);
733
		h->ip_off = htons(0);
734
		h->ip_len = htons(len);
734
		h->ip_len = htons(len);
735
		h->ip_ttl = V_ip_defttl;
735
		h->ip_ttl = V_ip_defttl;
736
		h->ip_sum = 0;
736
		h->ip_sum = 0;
737
		break;
737
		break;
738
#ifdef INET6
738
#ifdef INET6
739
	case 6:
739
	case 6:
740
		th->th_sum = in6_cksum(m, IPPROTO_TCP, sizeof(*h6),
740
		th->th_sum = in6_cksum(m, IPPROTO_TCP, sizeof(*h6),
741
		    sizeof(struct tcphdr));
741
		    sizeof(struct tcphdr));
742
742
743
		/* finish the ip6 header */
743
		/* finish the ip6 header */
744
		h6->ip6_vfc |= IPV6_VERSION;
744
		h6->ip6_vfc |= IPV6_VERSION;
745
		h6->ip6_hlim = IPV6_DEFHLIM;
745
		h6->ip6_hlim = IPV6_DEFHLIM;
746
		break;
746
		break;
747
#endif
747
#endif
748
	}
748
	}
749
749
750
	return (m);
750
	return (m);
751
}
751
}
752
752
753
#ifdef INET6
753
#ifdef INET6
754
/*
754
/*
755
 * ipv6 specific rules here...
755
 * ipv6 specific rules here...
756
 */
756
 */
757
static __inline int
757
static __inline int
758
icmp6type_match (int type, ipfw_insn_u32 *cmd)
758
icmp6type_match (int type, ipfw_insn_u32 *cmd)
759
{
759
{
760
	return (type <= ICMP6_MAXTYPE && (cmd->d[type/32] & (1<<(type%32)) ) );
760
	return (type <= ICMP6_MAXTYPE && (cmd->d[type/32] & (1<<(type%32)) ) );
761
}
761
}
762
762
763
static int
763
static int
764
flow6id_match( int curr_flow, ipfw_insn_u32 *cmd )
764
flow6id_match( int curr_flow, ipfw_insn_u32 *cmd )
765
{
765
{
766
	int i;
766
	int i;
767
	for (i=0; i <= cmd->o.arg1; ++i )
767
	for (i=0; i <= cmd->o.arg1; ++i )
768
		if (curr_flow == cmd->d[i] )
768
		if (curr_flow == cmd->d[i] )
769
			return 1;
769
			return 1;
770
	return 0;
770
	return 0;
771
}
771
}
772
772
773
/* support for IP6_*_ME opcodes */
773
/* support for IP6_*_ME opcodes */
774
static const struct in6_addr lla_mask = {{{
774
static const struct in6_addr lla_mask = {{{
775
	0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
775
	0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
776
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
776
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
777
}}};
777
}}};
778
778
779
static int
779
static int
780
ipfw_localip6(struct in6_addr *in6)
780
ipfw_localip6(struct in6_addr *in6)
781
{
781
{
782
	struct rm_priotracker in6_ifa_tracker;
782
	struct rm_priotracker in6_ifa_tracker;
783
	struct in6_ifaddr *ia;
783
	struct in6_ifaddr *ia;
784
784
785
	if (IN6_IS_ADDR_MULTICAST(in6))
785
	if (IN6_IS_ADDR_MULTICAST(in6))
786
		return (0);
786
		return (0);
787
787
788
	if (!IN6_IS_ADDR_LINKLOCAL(in6))
788
	if (!IN6_IS_ADDR_LINKLOCAL(in6))
789
		return (in6_localip(in6));
789
		return (in6_localip(in6));
790
790
791
	IN6_IFADDR_RLOCK(&in6_ifa_tracker);
791
	IN6_IFADDR_RLOCK(&in6_ifa_tracker);
792
	CK_STAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
792
	CK_STAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
793
		if (!IN6_IS_ADDR_LINKLOCAL(&ia->ia_addr.sin6_addr))
793
		if (!IN6_IS_ADDR_LINKLOCAL(&ia->ia_addr.sin6_addr))
794
			continue;
794
			continue;
795
		if (IN6_ARE_MASKED_ADDR_EQUAL(&ia->ia_addr.sin6_addr,
795
		if (IN6_ARE_MASKED_ADDR_EQUAL(&ia->ia_addr.sin6_addr,
796
		    in6, &lla_mask)) {
796
		    in6, &lla_mask)) {
797
			IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
797
			IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
798
			return (1);
798
			return (1);
799
		}
799
		}
800
	}
800
	}
801
	IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
801
	IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
802
	return (0);
802
	return (0);
803
}
803
}
804
804
805
static int
805
static int
806
verify_path6(struct in6_addr *src, struct ifnet *ifp, u_int fib)
806
verify_path6(struct in6_addr *src, struct ifnet *ifp, u_int fib)
807
{
807
{
808
	struct nhop6_basic nh6;
808
	struct nhop6_basic nh6;
809
809
810
	if (IN6_IS_SCOPE_LINKLOCAL(src))
810
	if (IN6_IS_SCOPE_LINKLOCAL(src))
811
		return (1);
811
		return (1);
812
812
813
	if (fib6_lookup_nh_basic(fib, src, 0, NHR_IFAIF, 0, &nh6) != 0)
813
	if (fib6_lookup_nh_basic(fib, src, 0, NHR_IFAIF, 0, &nh6) != 0)
814
		return (0);
814
		return (0);
815
815
816
	/* If ifp is provided, check for equality with route table. */
816
	/* If ifp is provided, check for equality with route table. */
817
	if (ifp != NULL && ifp != nh6.nh_ifp)
817
	if (ifp != NULL && ifp != nh6.nh_ifp)
818
		return (0);
818
		return (0);
819
819
820
	/* if no ifp provided, check if rtentry is not default route */
820
	/* if no ifp provided, check if rtentry is not default route */
821
	if (ifp == NULL && (nh6.nh_flags & NHF_DEFAULT) != 0)
821
	if (ifp == NULL && (nh6.nh_flags & NHF_DEFAULT) != 0)
822
		return (0);
822
		return (0);
823
823
824
	/* or if this is a blackhole/reject route */
824
	/* or if this is a blackhole/reject route */
825
	if (ifp == NULL && (nh6.nh_flags & (NHF_REJECT|NHF_BLACKHOLE)) != 0)
825
	if (ifp == NULL && (nh6.nh_flags & (NHF_REJECT|NHF_BLACKHOLE)) != 0)
826
		return (0);
826
		return (0);
827
827
828
	/* found valid route */
828
	/* found valid route */
829
	return 1;
829
	return 1;
830
}
830
}
831
831
832
static int
832
static int
833
is_icmp6_query(int icmp6_type)
833
is_icmp6_query(int icmp6_type)
834
{
834
{
835
	if ((icmp6_type <= ICMP6_MAXTYPE) &&
835
	if ((icmp6_type <= ICMP6_MAXTYPE) &&
836
	    (icmp6_type == ICMP6_ECHO_REQUEST ||
836
	    (icmp6_type == ICMP6_ECHO_REQUEST ||
837
	    icmp6_type == ICMP6_MEMBERSHIP_QUERY ||
837
	    icmp6_type == ICMP6_MEMBERSHIP_QUERY ||
838
	    icmp6_type == ICMP6_WRUREQUEST ||
838
	    icmp6_type == ICMP6_WRUREQUEST ||
839
	    icmp6_type == ICMP6_FQDN_QUERY ||
839
	    icmp6_type == ICMP6_FQDN_QUERY ||
840
	    icmp6_type == ICMP6_NI_QUERY))
840
	    icmp6_type == ICMP6_NI_QUERY))
841
		return (1);
841
		return (1);
842
842
843
	return (0);
843
	return (0);
844
}
844
}
845
845
846
static int
846
static int
847
map_icmp_unreach(int code)
847
map_icmp_unreach(int code)
848
{
848
{
849
849
850
	/* RFC 7915 p4.2 */
850
	/* RFC 7915 p4.2 */
851
	switch (code) {
851
	switch (code) {
852
	case ICMP_UNREACH_NET:
852
	case ICMP_UNREACH_NET:
853
	case ICMP_UNREACH_HOST:
853
	case ICMP_UNREACH_HOST:
854
	case ICMP_UNREACH_SRCFAIL:
854
	case ICMP_UNREACH_SRCFAIL:
855
	case ICMP_UNREACH_NET_UNKNOWN:
855
	case ICMP_UNREACH_NET_UNKNOWN:
856
	case ICMP_UNREACH_HOST_UNKNOWN:
856
	case ICMP_UNREACH_HOST_UNKNOWN:
857
	case ICMP_UNREACH_TOSNET:
857
	case ICMP_UNREACH_TOSNET:
858
	case ICMP_UNREACH_TOSHOST:
858
	case ICMP_UNREACH_TOSHOST:
859
		return (ICMP6_DST_UNREACH_NOROUTE);
859
		return (ICMP6_DST_UNREACH_NOROUTE);
860
	case ICMP_UNREACH_PORT:
860
	case ICMP_UNREACH_PORT:
861
		return (ICMP6_DST_UNREACH_NOPORT);
861
		return (ICMP6_DST_UNREACH_NOPORT);
862
	default:
862
	default:
863
		/*
863
		/*
864
		 * Map the rest of codes into admit prohibited.
864
		 * Map the rest of codes into admit prohibited.
865
		 * XXX: unreach proto should be mapped into ICMPv6
865
		 * XXX: unreach proto should be mapped into ICMPv6
866
		 * parameter problem, but we use only unreach type.
866
		 * parameter problem, but we use only unreach type.
867
		 */
867
		 */
868
		return (ICMP6_DST_UNREACH_ADMIN);
868
		return (ICMP6_DST_UNREACH_ADMIN);
869
	}
869
	}
870
}
870
}
871
871
872
static void
872
static void
873
send_reject6(struct ip_fw_args *args, int code, u_int hlen, struct ip6_hdr *ip6)
873
send_reject6(struct ip_fw_args *args, int code, u_int hlen, struct ip6_hdr *ip6)
874
{
874
{
875
	struct mbuf *m;
875
	struct mbuf *m;
876
876
877
	m = args->m;
877
	m = args->m;
878
	if (code == ICMP6_UNREACH_RST && args->f_id.proto == IPPROTO_TCP) {
878
	if (code == ICMP6_UNREACH_RST && args->f_id.proto == IPPROTO_TCP) {
879
		struct tcphdr *tcp;
879
		struct tcphdr *tcp;
880
		tcp = (struct tcphdr *)((char *)ip6 + hlen);
880
		tcp = (struct tcphdr *)((char *)ip6 + hlen);
881
881
882
		if ((tcp->th_flags & TH_RST) == 0) {
882
		if ((tcp->th_flags & TH_RST) == 0) {
883
			struct mbuf *m0;
883
			struct mbuf *m0;
884
			m0 = ipfw_send_pkt(args->m, &(args->f_id),
884
			m0 = ipfw_send_pkt(args->m, &(args->f_id),
885
			    ntohl(tcp->th_seq), ntohl(tcp->th_ack),
885
			    ntohl(tcp->th_seq), ntohl(tcp->th_ack),
886
			    tcp->th_flags | TH_RST);
886
			    tcp->th_flags | TH_RST);
887
			if (m0 != NULL)
887
			if (m0 != NULL)
888
				ip6_output(m0, NULL, NULL, 0, NULL, NULL,
888
				ip6_output(m0, NULL, NULL, 0, NULL, NULL,
889
				    NULL);
889
				    NULL);
890
		}
890
		}
891
		FREE_PKT(m);
891
		FREE_PKT(m);
892
	} else if (code == ICMP6_UNREACH_ABORT &&
892
	} else if (code == ICMP6_UNREACH_ABORT &&
893
	    args->f_id.proto == IPPROTO_SCTP) {
893
	    args->f_id.proto == IPPROTO_SCTP) {
894
		struct mbuf *m0;
894
		struct mbuf *m0;
895
		struct sctphdr *sctp;
895
		struct sctphdr *sctp;
896
		u_int32_t v_tag;
896
		u_int32_t v_tag;
897
		int reflected;
897
		int reflected;
898
898
899
		sctp = (struct sctphdr *)((char *)ip6 + hlen);
899
		sctp = (struct sctphdr *)((char *)ip6 + hlen);
900
		reflected = 1;
900
		reflected = 1;
901
		v_tag = ntohl(sctp->v_tag);
901
		v_tag = ntohl(sctp->v_tag);
902
		/* Investigate the first chunk header if available */
902
		/* Investigate the first chunk header if available */
903
		if (m->m_len >= hlen + sizeof(struct sctphdr) +
903
		if (m->m_len >= hlen + sizeof(struct sctphdr) +
904
		    sizeof(struct sctp_chunkhdr)) {
904
		    sizeof(struct sctp_chunkhdr)) {
905
			struct sctp_chunkhdr *chunk;
905
			struct sctp_chunkhdr *chunk;
906
906
907
			chunk = (struct sctp_chunkhdr *)(sctp + 1);
907
			chunk = (struct sctp_chunkhdr *)(sctp + 1);
908
			switch (chunk->chunk_type) {
908
			switch (chunk->chunk_type) {
909
			case SCTP_INITIATION:
909
			case SCTP_INITIATION:
910
				/*
910
				/*
911
				 * Packets containing an INIT chunk MUST have
911
				 * Packets containing an INIT chunk MUST have
912
				 * a zero v-tag.
912
				 * a zero v-tag.
913
				 */
913
				 */
914
				if (v_tag != 0) {
914
				if (v_tag != 0) {
915
					v_tag = 0;
915
					v_tag = 0;
916
					break;
916
					break;
917
				}
917
				}
918
				/* INIT chunk MUST NOT be bundled */
918
				/* INIT chunk MUST NOT be bundled */
919
				if (m->m_pkthdr.len >
919
				if (m->m_pkthdr.len >
920
				    hlen + sizeof(struct sctphdr) +
920
				    hlen + sizeof(struct sctphdr) +
921
				    ntohs(chunk->chunk_length) + 3) {
921
				    ntohs(chunk->chunk_length) + 3) {
922
					break;
922
					break;
923
				}
923
				}
924
				/* Use the initiate tag if available */
924
				/* Use the initiate tag if available */
925
				if ((m->m_len >= hlen + sizeof(struct sctphdr) +
925
				if ((m->m_len >= hlen + sizeof(struct sctphdr) +
926
				    sizeof(struct sctp_chunkhdr) +
926
				    sizeof(struct sctp_chunkhdr) +
927
				    offsetof(struct sctp_init, a_rwnd))) {
927
				    offsetof(struct sctp_init, a_rwnd))) {
928
					struct sctp_init *init;
928
					struct sctp_init *init;
929
929
930
					init = (struct sctp_init *)(chunk + 1);
930
					init = (struct sctp_init *)(chunk + 1);
931
					v_tag = ntohl(init->initiate_tag);
931
					v_tag = ntohl(init->initiate_tag);
932
					reflected = 0;
932
					reflected = 0;
933
				}
933
				}
934
				break;
934
				break;
935
			case SCTP_ABORT_ASSOCIATION:
935
			case SCTP_ABORT_ASSOCIATION:
936
				/*
936
				/*
937
				 * If the packet contains an ABORT chunk, don't
937
				 * If the packet contains an ABORT chunk, don't
938
				 * reply.
938
				 * reply.
939
				 * XXX: We should search through all chunks,
939
				 * XXX: We should search through all chunks,
940
				 *      but don't do to avoid attacks.
940
				 * but don't do to avoid attacks.
941
				 */
941
				 */
942
				v_tag = 0;
942
				v_tag = 0;
943
				break;
943
				break;
944
			}
944
			}
945
		}
945
		}
946
		if (v_tag == 0) {
946
		if (v_tag == 0) {
947
			m0 = NULL;
947
			m0 = NULL;
948
		} else {
948
		} else {
949
			m0 = ipfw_send_abort(args->m, &(args->f_id), v_tag,
949
			m0 = ipfw_send_abort(args->m, &(args->f_id), v_tag,
950
			    reflected);
950
			    reflected);
951
		}
951
		}
952
		if (m0 != NULL)
952
		if (m0 != NULL)
953
			ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL);
953
			ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL);
954
		FREE_PKT(m);
954
		FREE_PKT(m);
955
	} else if (code != ICMP6_UNREACH_RST && code != ICMP6_UNREACH_ABORT) {
955
	} else if (code != ICMP6_UNREACH_RST && code != ICMP6_UNREACH_ABORT) {
956
		/* Send an ICMPv6 unreach. */
956
		/* Send an ICMPv6 unreach. */
957
#if 0
957
#if 0
958
		/*
958
		/*
959
		 * Unlike above, the mbufs need to line up with the ip6 hdr,
959
		 * Unlike above, the mbufs need to line up with the ip6 hdr,
960
		 * as the contents are read. We need to m_adj() the
960
		 * as the contents are read. We need to m_adj() the
961
		 * needed amount.
961
		 * needed amount.
962
		 * The mbuf will however be thrown away so we can adjust it.
962
		 * The mbuf will however be thrown away so we can adjust it.
963
		 * Remember we did an m_pullup on it already so we
963
		 * Remember we did an m_pullup on it already so we
964
		 * can make some assumptions about contiguousness.
964
		 * can make some assumptions about contiguousness.
965
		 */
965
		 */
966
		if (args->L3offset)
966
		if (args->L3offset)
967
			m_adj(m, args->L3offset);
967
			m_adj(m, args->L3offset);
968
#endif
968
#endif
969
		icmp6_error(m, ICMP6_DST_UNREACH, code, 0);
969
		icmp6_error(m, ICMP6_DST_UNREACH, code, 0);
970
	} else
970
	} else
971
		FREE_PKT(m);
971
		FREE_PKT(m);
972
972
973
	args->m = NULL;
973
	args->m = NULL;
974
}
974
}
975
975
976
#endif /* INET6 */
976
#endif /* INET6 */
977
977
978
978
979
/*
979
/*
980
 * sends a reject message, consuming the mbuf passed as an argument.
980
 * sends a reject message, consuming the mbuf passed as an argument.
981
 */
981
 */
982
static void
982
static void
983
send_reject(struct ip_fw_args *args, int code, int iplen, struct ip *ip)
983
send_reject(struct ip_fw_args *args, int code, int iplen, struct ip *ip)
984
{
984
{
985
985
986
#if 0
986
#if 0
987
	/* XXX When ip is not guaranteed to be at mtod() we will
987
	/* XXX When ip is not guaranteed to be at mtod() we will
988
	 * need to account for this */
988
	 * need to account for this */
989
	 * The mbuf will however be thrown away so we can adjust it.
989
	 * The mbuf will however be thrown away so we can adjust it.
990
	 * Remember we did an m_pullup on it already so we
990
	 * Remember we did an m_pullup on it already so we
991
	 * can make some assumptions about contiguousness.
991
	 * can make some assumptions about contiguousness.
992
	 */
992
	 */
993
	if (args->L3offset)
993
	if (args->L3offset)
994
		m_adj(m, args->L3offset);
994
		m_adj(m, args->L3offset);
995
#endif
995
#endif
996
	if (code != ICMP_REJECT_RST && code != ICMP_REJECT_ABORT) {
996
	if (code != ICMP_REJECT_RST && code != ICMP_REJECT_ABORT) {
997
		/* Send an ICMP unreach */
997
		/* Send an ICMP unreach */
998
		icmp_error(args->m, ICMP_UNREACH, code, 0L, 0);
998
		icmp_error(args->m, ICMP_UNREACH, code, 0L, 0);
999
	} else if (code == ICMP_REJECT_RST && args->f_id.proto == IPPROTO_TCP) {
999
	} else if (code == ICMP_REJECT_RST && args->f_id.proto == IPPROTO_TCP) {
1000
		struct tcphdr *const tcp =
1000
		struct tcphdr *const tcp =
1001
		    L3HDR(struct tcphdr, mtod(args->m, struct ip *));
1001
		    L3HDR(struct tcphdr, mtod(args->m, struct ip *));
1002
		if ( (tcp->th_flags & TH_RST) == 0) {
1002
		if ( (tcp->th_flags & TH_RST) == 0) {
1003
			struct mbuf *m;
1003
			struct mbuf *m;
1004
			m = ipfw_send_pkt(args->m, &(args->f_id),
1004
			m = ipfw_send_pkt(args->m, &(args->f_id),
1005
				ntohl(tcp->th_seq), ntohl(tcp->th_ack),
1005
				ntohl(tcp->th_seq), ntohl(tcp->th_ack),
1006
				tcp->th_flags | TH_RST);
1006
				tcp->th_flags | TH_RST);
1007
			if (m != NULL)
1007
			if (m != NULL)
1008
				ip_output(m, NULL, NULL, 0, NULL, NULL);
1008
				ip_output(m, NULL, NULL, 0, NULL, NULL);
1009
		}
1009
		}
1010
		FREE_PKT(args->m);
1010
		FREE_PKT(args->m);
1011
	} else if (code == ICMP_REJECT_ABORT &&
1011
	} else if (code == ICMP_REJECT_ABORT &&
1012
	    args->f_id.proto == IPPROTO_SCTP) {
1012
	    args->f_id.proto == IPPROTO_SCTP) {
1013
		struct mbuf *m;
1013
		struct mbuf *m;
1014
		struct sctphdr *sctp;
1014
		struct sctphdr *sctp;
1015
		struct sctp_chunkhdr *chunk;
1015
		struct sctp_chunkhdr *chunk;
1016
		struct sctp_init *init;
1016
		struct sctp_init *init;
1017
		u_int32_t v_tag;
1017
		u_int32_t v_tag;
1018
		int reflected;
1018
		int reflected;
1019
1019
1020
		sctp = L3HDR(struct sctphdr, mtod(args->m, struct ip *));
1020
		sctp = L3HDR(struct sctphdr, mtod(args->m, struct ip *));
1021
		reflected = 1;
1021
		reflected = 1;
1022
		v_tag = ntohl(sctp->v_tag);
1022
		v_tag = ntohl(sctp->v_tag);
1023
		if (iplen >= (ip->ip_hl << 2) + sizeof(struct sctphdr) +
1023
		if (iplen >= (ip->ip_hl << 2) + sizeof(struct sctphdr) +
1024
		    sizeof(struct sctp_chunkhdr)) {
1024
		    sizeof(struct sctp_chunkhdr)) {
1025
			/* Look at the first chunk header if available */
1025
			/* Look at the first chunk header if available */
1026
			chunk = (struct sctp_chunkhdr *)(sctp + 1);
1026
			chunk = (struct sctp_chunkhdr *)(sctp + 1);
1027
			switch (chunk->chunk_type) {
1027
			switch (chunk->chunk_type) {
1028
			case SCTP_INITIATION:
1028
			case SCTP_INITIATION:
1029
				/*
1029
				/*
1030
				 * Packets containing an INIT chunk MUST have
1030
				 * Packets containing an INIT chunk MUST have
1031
				 * a zero v-tag.
1031
				 * a zero v-tag.
1032
				 */
1032
				 */
1033
				if (v_tag != 0) {
1033
				if (v_tag != 0) {
1034
					v_tag = 0;
1034
					v_tag = 0;
1035
					break;
1035
					break;
1036
				}
1036
				}
1037
				/* INIT chunk MUST NOT be bundled */
1037
				/* INIT chunk MUST NOT be bundled */
1038
				if (iplen >
1038
				if (iplen >
1039
				    (ip->ip_hl << 2) + sizeof(struct sctphdr) +
1039
				    (ip->ip_hl << 2) + sizeof(struct sctphdr) +
1040
				    ntohs(chunk->chunk_length) + 3) {
1040
				    ntohs(chunk->chunk_length) + 3) {
1041
					break;
1041
					break;
1042
				}
1042
				}
1043
				/* Use the initiate tag if available */
1043
				/* Use the initiate tag if available */
1044
				if ((iplen >= (ip->ip_hl << 2) +
1044
				if ((iplen >= (ip->ip_hl << 2) +
1045
				    sizeof(struct sctphdr) +
1045
				    sizeof(struct sctphdr) +
1046
				    sizeof(struct sctp_chunkhdr) +
1046
				    sizeof(struct sctp_chunkhdr) +
1047
				    offsetof(struct sctp_init, a_rwnd))) {
1047
				    offsetof(struct sctp_init, a_rwnd))) {
1048
					init = (struct sctp_init *)(chunk + 1);
1048
					init = (struct sctp_init *)(chunk + 1);
1049
					v_tag = ntohl(init->initiate_tag);
1049
					v_tag = ntohl(init->initiate_tag);
1050
					reflected = 0;
1050
					reflected = 0;
1051
				}
1051
				}
1052
				break;
1052
				break;
1053
			case SCTP_ABORT_ASSOCIATION:
1053
			case SCTP_ABORT_ASSOCIATION:
1054
				/*
1054
				/*
1055
				 * If the packet contains an ABORT chunk, don't
1055
				 * If the packet contains an ABORT chunk, don't
1056
				 * reply.
1056
				 * reply.
1057
				 * XXX: We should search through all chunks,
1057
				 * XXX: We should search through all chunks,
1058
				 * but don't do to avoid attacks.
1058
				 * but don't do to avoid attacks.
1059
				 */
1059
				 */
1060
				v_tag = 0;
1060
				v_tag = 0;
1061
				break;
1061
				break;
1062
			}
1062
			}
1063
		}
1063
		}
1064
		if (v_tag == 0) {
1064
		if (v_tag == 0) {
1065
			m = NULL;
1065
			m = NULL;
1066
		} else {
1066
		} else {
1067
			m = ipfw_send_abort(args->m, &(args->f_id), v_tag,
1067
			m = ipfw_send_abort(args->m, &(args->f_id), v_tag,
1068
			    reflected);
1068
			    reflected);
1069
		}
1069
		}
1070
		if (m != NULL)
1070
		if (m != NULL)
1071
			ip_output(m, NULL, NULL, 0, NULL, NULL);
1071
			ip_output(m, NULL, NULL, 0, NULL, NULL);
1072
		FREE_PKT(args->m);
1072
		FREE_PKT(args->m);
1073
	} else
1073
	} else
1074
		FREE_PKT(args->m);
1074
		FREE_PKT(args->m);
1075
	args->m = NULL;
1075
	args->m = NULL;
1076
}
1076
}
1077
1077
1078
/*
1078
/*
1079
 * Support for uid/gid/jail lookup. These tests are expensive
1079
 * Support for uid/gid/jail lookup. These tests are expensive
1080
 * (because we may need to look into the list of active sockets)
1080
 * (because we may need to look into the list of active sockets)
1081
 * so we cache the results. ugid_lookupp is 0 if we have not
1081
 * so we cache the results. ugid_lookupp is 0 if we have not
1082
 * yet done a lookup, 1 if we succeeded, and -1 if we tried
1082
 * yet done a lookup, 1 if we succeeded, and -1 if we tried
1083
 * and failed. The function always returns the match value.
1083
 * and failed. The function always returns the match value.
1084
 * We could actually spare the variable and use *uc, setting
1084
 * We could actually spare the variable and use *uc, setting
1085
 * it to '(void *)check_uidgid if we have no info, NULL if
1085
 * it to '(void *)check_uidgid if we have no info, NULL if
1086
 * we tried and failed, or any other value if successful.
1086
 * we tried and failed, or any other value if successful.
1087
 */
1087
 */
1088
static int
1088
static int
1089
check_uidgid(ipfw_insn_u32 *insn, struct ip_fw_args *args, int *ugid_lookupp,
1089
check_uidgid(ipfw_insn_u32 *insn, struct ip_fw_args *args, int *ugid_lookupp,
1090
    struct ucred **uc)
1090
    struct ucred **uc)
1091
{
1091
{
1092
#if defined(USERSPACE)
1092
#if defined(USERSPACE)
1093
	return 0;	// not supported in userspace
1093
	return 0;	// not supported in userspace
1094
#else
1094
#else
1095
#ifndef __FreeBSD__
1095
#ifndef __FreeBSD__
1096
	/* XXX */
1096
	/* XXX */
1097
	return cred_check(insn, proto, oif,
1097
	return cred_check(insn, proto, oif,
1098
	    dst_ip, dst_port, src_ip, src_port,
1098
	    dst_ip, dst_port, src_ip, src_port,
1099
	    (struct bsd_ucred *)uc, ugid_lookupp, ((struct mbuf *)inp)->m_skb);
1099
	    (struct bsd_ucred *)uc, ugid_lookupp, ((struct mbuf *)inp)->m_skb);
1100
#else  /* FreeBSD */
1100
#else  /* FreeBSD */
1101
	struct in_addr src_ip, dst_ip;
1101
	struct in_addr src_ip, dst_ip;
1102
	struct inpcbinfo *pi;
1102
	struct inpcbinfo *pi;
1103
	struct ipfw_flow_id *id;
1103
	struct ipfw_flow_id *id;
1104
	struct inpcb *pcb, *inp;
1104
	struct inpcb *pcb, *inp;
1105
	int lookupflags;
1105
	int lookupflags;
1106
	int match;
1106
	int match;
1107
1107
1108
	id = &args->f_id;
1108
	id = &args->f_id;
1109
	inp = args->inp;
1109
	inp = args->inp;
1110
1110
1111
	/*
1111
	/*
1112
	 * Check to see if the UDP or TCP stack supplied us with
1112
	 * Check to see if the UDP or TCP stack supplied us with
1113
	 * the PCB. If so, rather then holding a lock and looking
1113
	 * the PCB. If so, rather then holding a lock and looking
1114
	 * up the PCB, we can use the one that was supplied.
1114
	 * up the PCB, we can use the one that was supplied.
1115
	 */
1115
	 */
1116
	if (inp && *ugid_lookupp == 0) {
1116
	if (inp && *ugid_lookupp == 0) {
1117
		INP_LOCK_ASSERT(inp);
1117
		INP_LOCK_ASSERT(inp);
1118
		if (inp->inp_socket != NULL) {
1118
		if (inp->inp_socket != NULL) {
1119
			*uc = crhold(inp->inp_cred);
1119
			*uc = crhold(inp->inp_cred);
1120
			*ugid_lookupp = 1;
1120
			*ugid_lookupp = 1;
1121
		} else
1121
		} else
1122
			*ugid_lookupp = -1;
1122
			*ugid_lookupp = -1;
1123
	}
1123
	}
1124
	/*
1124
	/*
1125
	 * If we have already been here and the packet has no
1125
	 * If we have already been here and the packet has no
1126
	 * PCB entry associated with it, then we can safely
1126
	 * PCB entry associated with it, then we can safely
1127
	 * assume that this is a no match.
1127
	 * assume that this is a no match.
1128
	 */
1128
	 */
1129
	if (*ugid_lookupp == -1)
1129
	if (*ugid_lookupp == -1)
1130
		return (0);
1130
		return (0);
1131
	if (id->proto == IPPROTO_TCP) {
1131
	if (id->proto == IPPROTO_TCP) {
1132
		lookupflags = 0;
1132
		lookupflags = 0;
1133
		pi = &V_tcbinfo;
1133
		pi = &V_tcbinfo;
1134
	} else if (id->proto == IPPROTO_UDP) {
1134
	} else if (id->proto == IPPROTO_UDP) {
1135
		lookupflags = INPLOOKUP_WILDCARD;
1135
		lookupflags = INPLOOKUP_WILDCARD;
1136
		pi = &V_udbinfo;
1136
		pi = &V_udbinfo;
1137
	} else if (id->proto == IPPROTO_UDPLITE) {
1137
	} else if (id->proto == IPPROTO_UDPLITE) {
1138
		lookupflags = INPLOOKUP_WILDCARD;
1138
		lookupflags = INPLOOKUP_WILDCARD;
1139
		pi = &V_ulitecbinfo;
1139
		pi = &V_ulitecbinfo;
1140
	} else
1140
	} else
1141
		return 0;
1141
		return 0;
1142
	lookupflags |= INPLOOKUP_RLOCKPCB;
1142
	lookupflags |= INPLOOKUP_RLOCKPCB;
1143
	match = 0;
1143
	match = 0;
1144
	if (*ugid_lookupp == 0) {
1144
	if (*ugid_lookupp == 0) {
1145
		if (id->addr_type == 6) {
1145
		if (id->addr_type == 6) {
1146
#ifdef INET6
1146
#ifdef INET6
1147
			if (args->flags & IPFW_ARGS_IN)
1147
			if (args->flags & IPFW_ARGS_IN)
1148
				pcb = in6_pcblookup_mbuf(pi,
1148
				pcb = in6_pcblookup_mbuf(pi,
1149
				    &id->src_ip6, htons(id->src_port),
1149
				    &id->src_ip6, htons(id->src_port),
1150
				    &id->dst_ip6, htons(id->dst_port),
1150
				    &id->dst_ip6, htons(id->dst_port),
1151
				    lookupflags, NULL, args->m);
1151
				    lookupflags, NULL, args->m);
1152
			else
1152
			else
1153
				pcb = in6_pcblookup_mbuf(pi,
1153
				pcb = in6_pcblookup_mbuf(pi,
1154
				    &id->dst_ip6, htons(id->dst_port),
1154
				    &id->dst_ip6, htons(id->dst_port),
1155
				    &id->src_ip6, htons(id->src_port),
1155
				    &id->src_ip6, htons(id->src_port),
1156
				    lookupflags, args->ifp, args->m);
1156
				    lookupflags, args->ifp, args->m);
1157
#else
1157
#else
1158
			*ugid_lookupp = -1;
1158
			*ugid_lookupp = -1;
1159
			return (0);
1159
			return (0);
1160
#endif
1160
#endif
1161
		} else {
1161
		} else {
1162
			src_ip.s_addr = htonl(id->src_ip);
1162
			src_ip.s_addr = htonl(id->src_ip);
1163
			dst_ip.s_addr = htonl(id->dst_ip);
1163
			dst_ip.s_addr = htonl(id->dst_ip);
1164
			if (args->flags & IPFW_ARGS_IN)
1164
			if (args->flags & IPFW_ARGS_IN)
1165
				pcb = in_pcblookup_mbuf(pi,
1165
				pcb = in_pcblookup_mbuf(pi,
1166
				    src_ip, htons(id->src_port),
1166
				    src_ip, htons(id->src_port),
1167
				    dst_ip, htons(id->dst_port),
1167
				    dst_ip, htons(id->dst_port),
1168
				    lookupflags, NULL, args->m);
1168
				    lookupflags, NULL, args->m);
1169
			else
1169
			else
1170
				pcb = in_pcblookup_mbuf(pi,
1170
				pcb = in_pcblookup_mbuf(pi,
1171
				    dst_ip, htons(id->dst_port),
1171
				    dst_ip, htons(id->dst_port),
1172
				    src_ip, htons(id->src_port),
1172
				    src_ip, htons(id->src_port),
1173
				    lookupflags, args->ifp, args->m);
1173
				    lookupflags, args->ifp, args->m);
1174
		}
1174
		}
1175
		if (pcb != NULL) {
1175
		if (pcb != NULL) {
1176
			INP_RLOCK_ASSERT(pcb);
1176
			INP_RLOCK_ASSERT(pcb);
1177
			*uc = crhold(pcb->inp_cred);
1177
			*uc = crhold(pcb->inp_cred);
1178
			*ugid_lookupp = 1;
1178
			*ugid_lookupp = 1;
1179
			INP_RUNLOCK(pcb);
1179
			INP_RUNLOCK(pcb);
1180
		}
1180
		}
1181
		if (*ugid_lookupp == 0) {
1181
		if (*ugid_lookupp == 0) {
1182
			/*
1182
			/*
1183
			 * We tried and failed, set the variable to -1
1183
			 * We tried and failed, set the variable to -1
1184
			 * so we will not try again on this packet.
1184
			 * so we will not try again on this packet.
1185
			 */
1185
			 */
1186
			*ugid_lookupp = -1;
1186
			*ugid_lookupp = -1;
1187
			return (0);
1187
			return (0);
1188
		}
1188
		}
1189
	}
1189
	}
1190
	if (insn->o.opcode == O_UID)
1190
	if (insn->o.opcode == O_UID)
1191
		match = ((*uc)->cr_uid == (uid_t)insn->d[0]);
1191
		match = ((*uc)->cr_uid == (uid_t)insn->d[0]);
1192
	else if (insn->o.opcode == O_GID)
1192
	else if (insn->o.opcode == O_GID)
1193
		match = groupmember((gid_t)insn->d[0], *uc);
1193
		match = groupmember((gid_t)insn->d[0], *uc);
1194
	else if (insn->o.opcode == O_JAIL)
1194
	else if (insn->o.opcode == O_JAIL)
1195
		match = ((*uc)->cr_prison->pr_id == (int)insn->d[0]);
1195
		match = ((*uc)->cr_prison->pr_id == (int)insn->d[0]);
1196
	return (match);
1196
	return (match);
1197
#endif /* __FreeBSD__ */
1197
#endif /* __FreeBSD__ */
1198
#endif /* not supported in userspace */
1198
#endif /* not supported in userspace */
1199
}
1199
}
1200
1200
1201
/*
1201
/*
1202
 * Helper function to set args with info on the rule after the matching
1202
 * Helper function to set args with info on the rule after the matching
1203
 * one. slot is precise, whereas we guess rule_id as they are
1203
 * one. slot is precise, whereas we guess rule_id as they are
1204
 * assigned sequentially.
1204
 * assigned sequentially.
1205
 */
1205
 */
1206
static inline void
1206
static inline void
1207
set_match(struct ip_fw_args *args, int slot,
1207
set_match(struct ip_fw_args *args, int slot,
1208
	struct ip_fw_chain *chain)
1208
	struct ip_fw_chain *chain)
1209
{
1209
{
1210
	args->rule.chain_id = chain->id;
1210
	args->rule.chain_id = chain->id;
1211
	args->rule.slot = slot + 1; /* we use 0 as a marker */
1211
	args->rule.slot = slot + 1; /* we use 0 as a marker */
1212
	args->rule.rule_id = 1 + chain->map[slot]->id;
1212
	args->rule.rule_id = 1 + chain->map[slot]->id;
1213
	args->rule.rulenum = chain->map[slot]->rulenum;
1213
	args->rule.rulenum = chain->map[slot]->rulenum;
1214
	args->flags |= IPFW_ARGS_REF;
1214
	args->flags |= IPFW_ARGS_REF;
1215
}
1215
}
1216
1216
1217
#ifndef LINEAR_SKIPTO
1217
#ifndef LINEAR_SKIPTO
1218
/*
1218
/*
1219
 * Helper function to enable cached rule lookups using
1219
 * Helper function to enable cached rule lookups using
1220
 * cached_id and cached_pos fields in ipfw rule.
1220
 * cached_id and cached_pos fields in ipfw rule.
1221
 */
1221
 */
1222
static int
1222
static int
1223
jump_fast(struct ip_fw_chain *chain, struct ip_fw *f, int num,
1223
jump_fast(struct ip_fw_chain *chain, struct ip_fw *f, int num,
1224
    int tablearg, int jump_backwards)
1224
    int tablearg, int jump_backwards)
1225
{
1225
{
1226
	int f_pos;
1226
	int f_pos;
1227
1227
1228
	/* If possible use cached f_pos (in f->cached_pos),
1228
	/* If possible use cached f_pos (in f->cached_pos),
1229
	 * whose version is written in f->cached_id
1229
	 * whose version is written in f->cached_id
1230
	 * (horrible hacks to avoid changing the ABI).
1230
	 * (horrible hacks to avoid changing the ABI).
1231
	 */
1231
	 */
1232
	if (num != IP_FW_TARG && f->cached_id == chain->id)
1232
	if (num != IP_FW_TARG && f->cached_id == chain->id)
1233
		f_pos = f->cached_pos;
1233
		f_pos = f->cached_pos;
1234
	else {
1234
	else {
1235
		int i = IP_FW_ARG_TABLEARG(chain, num, skipto);
1235
		int i = IP_FW_ARG_TABLEARG(chain, num, skipto);
1236
		/* make sure we do not jump backward */
1236
		/* make sure we do not jump backward */
1237
		if (jump_backwards == 0 && i <= f->rulenum)
1237
		if (jump_backwards == 0 && i <= f->rulenum)
1238
			i = f->rulenum + 1;
1238
			i = f->rulenum + 1;
1239
		if (chain->idxmap != NULL)
1239
		if (chain->idxmap != NULL)
1240
			f_pos = chain->idxmap[i];
1240
			f_pos = chain->idxmap[i];
1241
		else
1241
		else
1242
			f_pos = ipfw_find_rule(chain, i, 0);
1242
			f_pos = ipfw_find_rule(chain, i, 0);
1243
		/* update the cache */
1243
		/* update the cache */
1244
		if (num != IP_FW_TARG) {
1244
		if (num != IP_FW_TARG) {
1245
			f->cached_id = chain->id;
1245
			f->cached_id = chain->id;
1246
			f->cached_pos = f_pos;
1246
			f->cached_pos = f_pos;
1247
		}
1247
		}
1248
	}
1248
	}
1249
1249
1250
	return (f_pos);
1250
	return (f_pos);
1251
}
1251
}
1252
#else
1252
#else
1253
/*
1253
/*
1254
 * Helper function to enable real fast rule lookups.
1254
 * Helper function to enable real fast rule lookups.
1255
 */
1255
 */
1256
static int
1256
static int
1257
jump_linear(struct ip_fw_chain *chain, struct ip_fw *f, int num,
1257
jump_linear(struct ip_fw_chain *chain, struct ip_fw *f, int num,
1258
    int tablearg, int jump_backwards)
1258
    int tablearg, int jump_backwards)
1259
{
1259
{
1260
	int f_pos;
1260
	int f_pos;
1261
1261
1262
	num = IP_FW_ARG_TABLEARG(chain, num, skipto);
1262
	num = IP_FW_ARG_TABLEARG(chain, num, skipto);
1263
	/* make sure we do not jump backward */
1263
	/* make sure we do not jump backward */
1264
	if (jump_backwards == 0 && num <= f->rulenum)
1264
	if (jump_backwards == 0 && num <= f->rulenum)
1265
		num = f->rulenum + 1;
1265
		num = f->rulenum + 1;
1266
	f_pos = chain->idxmap[num];
1266
	f_pos = chain->idxmap[num];
1267
1267
1268
	return (f_pos);
1268
	return (f_pos);
1269
}
1269
}
1270
#endif
1270
#endif
1271
1271
1272
#define	TARG(k, f)	IP_FW_ARG_TABLEARG(chain, k, f)
1272
#define	TARG(k, f)	IP_FW_ARG_TABLEARG(chain, k, f)
1273
/*
1273
/*
1274
 * The main check routine for the firewall.
1274
 * The main check routine for the firewall.
1275
 *
1275
 *
1276
 * All arguments are in args so we can modify them and return them
1276
 * All arguments are in args so we can modify them and return them
1277
 * back to the caller.
1277
 * back to the caller.
1278
 *
1278
 *
1279
 * Parameters:
1279
 * Parameters:
1280
 *
1280
 *
1281
 *	args->m	(in/out) The packet; we set to NULL when/if we nuke it.
1281
 *	args->m	(in/out) The packet; we set to NULL when/if we nuke it.
1282
 *		Starts with the IP header.
1282
 *		Starts with the IP header.
1283
 *	args->L3offset	Number of bytes bypassed if we came from L2.
1283
 *	args->L3offset	Number of bytes bypassed if we came from L2.
1284
 *			e.g. often sizeof(eh)  ** NOTYET **
1284
 *			e.g. often sizeof(eh)  ** NOTYET **
1285
 *	args->ifp	Incoming or outgoing interface.
1285
 *	args->ifp	Incoming or outgoing interface.
1286
 *	args->divert_rule (in/out)
1286
 *	args->divert_rule (in/out)
1287
 *		Skip up to the first rule past this rule number;
1287
 *		Skip up to the first rule past this rule number;
1288
 *		upon return, non-zero port number for divert or tee.
1288
 *		upon return, non-zero port number for divert or tee.
1289
 *
1289
 *
1290
 *	args->rule	Pointer to the last matching rule (in/out)
1290
 *	args->rule	Pointer to the last matching rule (in/out)
1291
 *	args->next_hop	Socket we are forwarding to (out).
1291
 *	args->next_hop	Socket we are forwarding to (out).
1292
 *	args->next_hop6	IPv6 next hop we are forwarding to (out).
1292
 *	args->next_hop6	IPv6 next hop we are forwarding to (out).
1293
 *	args->f_id	Addresses grabbed from the packet (out)
1293
 *	args->f_id	Addresses grabbed from the packet (out)
1294
 * 	args->rule.info	a cookie depending on rule action
1294
 * 	args->rule.info	a cookie depending on rule action
1295
 *
1295
 *
1296
 * Return value:
1296
 * Return value:
1297
 *
1297
 *
1298
 *	IP_FW_PASS	the packet must be accepted
1298
 *	IP_FW_PASS	the packet must be accepted
1299
 *	IP_FW_DENY	the packet must be dropped
1299
 *	IP_FW_DENY	the packet must be dropped
1300
 *	IP_FW_DIVERT	divert packet, port in m_tag
1300
 *	IP_FW_DIVERT	divert packet, port in m_tag
1301
 *	IP_FW_TEE	tee packet, port in m_tag
1301
 *	IP_FW_TEE	tee packet, port in m_tag
1302
 *	IP_FW_DUMMYNET	to dummynet, pipe in args->cookie
1302
 *	IP_FW_DUMMYNET	to dummynet, pipe in args->cookie
1303
 *	IP_FW_NETGRAPH	into netgraph, cookie args->cookie
1303
 *	IP_FW_NETGRAPH	into netgraph, cookie args->cookie
1304
 *		args->rule contains the matching rule,
1304
 *		args->rule contains the matching rule,
1305
 *		args->rule.info has additional information.
1305
 *		args->rule.info has additional information.
1306
 *
1306
 *
1307
 */
1307
 */
1308
int
1308
int
1309
ipfw_chk(struct ip_fw_args *args)
1309
ipfw_chk(struct ip_fw_args *args)
1310
{
1310
{
1311
1311
1312
	/*
1312
	/*
1313
	 * Local variables holding state while processing a packet:
1313
	 * Local variables holding state while processing a packet:
1314
	 *
1314
	 *
1315
	 * IMPORTANT NOTE: to speed up the processing of rules, there
1315
	 * IMPORTANT NOTE: to speed up the processing of rules, there
1316
	 * are some assumption on the values of the variables, which
1316
	 * are some assumption on the values of the variables, which
1317
	 * are documented here. Should you change them, please check
1317
	 * are documented here. Should you change them, please check
1318
	 * the implementation of the various instructions to make sure
1318
	 * the implementation of the various instructions to make sure
1319
	 * that they still work.
1319
	 * that they still work.
1320
	 *
1320
	 *
1321
	 * m | args->m	Pointer to the mbuf, as received from the caller.
1321
	 * m | args->m	Pointer to the mbuf, as received from the caller.
1322
	 *	It may change if ipfw_chk() does an m_pullup, or if it
1322
	 *	It may change if ipfw_chk() does an m_pullup, or if it
1323
	 *	consumes the packet because it calls send_reject().
1323
	 *	consumes the packet because it calls send_reject().
1324
	 *	XXX This has to change, so that ipfw_chk() never modifies
1324
	 *	XXX This has to change, so that ipfw_chk() never modifies
1325
	 *	or consumes the buffer.
1325
	 *	or consumes the buffer.
1326
	 *	OR
1326
	 *	OR
1327
	 * args->mem	Pointer to contigous memory chunk.
1327
	 * args->mem	Pointer to contigous memory chunk.
1328
	 * ip	Is the beginning of the ip(4 or 6) header.
1328
	 * ip	Is the beginning of the ip(4 or 6) header.
1329
	 * eh	Ethernet header in case if input is Layer2.
1329
	 * eh	Ethernet header in case if input is Layer2.
1330
	 */
1330
	 */
1331
	struct mbuf *m;
1331
	struct mbuf *m;
1332
	struct ip *ip;
1332
	struct ip *ip;
1333
	struct ether_header *eh;
1333
	struct ether_header *eh;
1334
1334
1335
	/*
1335
	/*
1336
	 * For rules which contain uid/gid or jail constraints, cache
1336
	 * For rules which contain uid/gid or jail constraints, cache
1337
	 * a copy of the users credentials after the pcb lookup has been
1337
	 * a copy of the users credentials after the pcb lookup has been
1338
	 * executed. This will speed up the processing of rules with
1338
	 * executed. This will speed up the processing of rules with
1339
	 * these types of constraints, as well as decrease contention
1339
	 * these types of constraints, as well as decrease contention
1340
	 * on pcb related locks.
1340
	 * on pcb related locks.
1341
	 */
1341
	 */
1342
#ifndef __FreeBSD__
1342
#ifndef __FreeBSD__
1343
	struct bsd_ucred ucred_cache;
1343
	struct bsd_ucred ucred_cache;
1344
#else
1344
#else
1345
	struct ucred *ucred_cache = NULL;
1345
	struct ucred *ucred_cache = NULL;
1346
#endif
1346
#endif
1347
	int ucred_lookup = 0;
1347
	int ucred_lookup = 0;
1348
	int f_pos = 0;		/* index of current rule in the array */
1348
	int f_pos = 0;		/* index of current rule in the array */
1349
	int retval = 0;
1349
	int retval = 0;
1350
	struct ifnet *oif, *iif;
1350
	struct ifnet *oif, *iif;
1351
1351
1352
	/*
1352
	/*
1353
	 * hlen	The length of the IP header.
1353
	 * hlen	The length of the IP header.
1354
	 */
1354
	 */
1355
	u_int hlen = 0;		/* hlen >0 means we have an IP pkt */
1355
	u_int hlen = 0;		/* hlen >0 means we have an IP pkt */
1356
1356
1357
	/*
1357
	/*
1358
	 * offset	The offset of a fragment. offset != 0 means that
1358
	 * offset	The offset of a fragment. offset != 0 means that
1359
	 *	we have a fragment at this offset of an IPv4 packet.
1359
	 *	we have a fragment at this offset of an IPv4 packet.
1360
	 *	offset == 0 means that (if this is an IPv4 packet)
1360
	 *	offset == 0 means that (if this is an IPv4 packet)
1361
	 *	this is the first or only fragment.
1361
	 *	this is the first or only fragment.
1362
	 *	For IPv6 offset|ip6f_mf == 0 means there is no Fragment Header
1362
	 *	For IPv6 offset|ip6f_mf == 0 means there is no Fragment Header
1363
	 *	or there is a single packet fragment (fragment header added
1363
	 *	or there is a single packet fragment (fragment header added
1364
	 *	without needed).  We will treat a single packet fragment as if
1364
	 *	without needed).  We will treat a single packet fragment as if
1365
	 *	there was no fragment header (or log/block depending on the
1365
	 *	there was no fragment header (or log/block depending on the
1366
	 *	V_fw_permit_single_frag6 sysctl setting).
1366
	 *	V_fw_permit_single_frag6 sysctl setting).
1367
	 */
1367
	 */
1368
	u_short offset = 0;
1368
	u_short offset = 0;
1369
	u_short ip6f_mf = 0;
1369
	u_short ip6f_mf = 0;
1370
1370
1371
	/*
1371
	/*
1372
	 * Local copies of addresses. They are only valid if we have
1372
	 * Local copies of addresses. They are only valid if we have
1373
	 * an IP packet.
1373
	 * an IP packet.
1374
	 *
1374
	 *
1375
	 * proto	The protocol. Set to 0 for non-ip packets,
1375
	 * proto	The protocol. Set to 0 for non-ip packets,
1376
	 *	or to the protocol read from the packet otherwise.
1376
	 *	or to the protocol read from the packet otherwise.
1377
	 *	proto != 0 means that we have an IPv4 packet.
1377
	 *	proto != 0 means that we have an IPv4 packet.
1378
	 *
1378
	 *
1379
	 * src_port, dst_port	port numbers, in HOST format. Only
1379
	 * src_port, dst_port	port numbers, in HOST format. Only
1380
	 *	valid for TCP and UDP packets.
1380
	 *	valid for TCP and UDP packets.
1381
	 *
1381
	 *
1382
	 * src_ip, dst_ip	ip addresses, in NETWORK format.
1382
	 * src_ip, dst_ip	ip addresses, in NETWORK format.
1383
	 *	Only valid for IPv4 packets.
1383
	 *	Only valid for IPv4 packets.
1384
	 */
1384
	 */
1385
	uint8_t proto;
1385
	uint8_t proto;
1386
	uint16_t src_port, dst_port;		/* NOTE: host format	*/
1386
	uint16_t src_port, dst_port;		/* NOTE: host format	*/
1387
	struct in_addr src_ip, dst_ip;		/* NOTE: network format	*/
1387
	struct in_addr src_ip, dst_ip;		/* NOTE: network format	*/
1388
	int iplen = 0;
1388
	int iplen = 0;
1389
	int pktlen;
1389
	int pktlen;
1390
1390
1391
	struct ipfw_dyn_info dyn_info;
1391
	struct ipfw_dyn_info dyn_info;
1392
	struct ip_fw *q = NULL;
1392
	struct ip_fw *q = NULL;
1393
	struct ip_fw_chain *chain = &V_layer3_chain;
1393
	struct ip_fw_chain *chain = &V_layer3_chain;
1394
1394
1395
	/*
1395
	/*
1396
	 * We store in ulp a pointer to the upper layer protocol header.
1396
	 * We store in ulp a pointer to the upper layer protocol header.
1397
	 * In the ipv4 case this is easy to determine from the header,
1397
	 * In the ipv4 case this is easy to determine from the header,
1398
	 * but for ipv6 we might have some additional headers in the middle.
1398
	 * but for ipv6 we might have some additional headers in the middle.
1399
	 * ulp is NULL if not found.
1399
	 * ulp is NULL if not found.
1400
	 */
1400
	 */
1401
	void *ulp = NULL;		/* upper layer protocol pointer. */
1401
	void *ulp = NULL;		/* upper layer protocol pointer. */
1402
1402
1403
	/* XXX ipv6 variables */
1403
	/* XXX ipv6 variables */
1404
	int is_ipv6 = 0;
1404
	int is_ipv6 = 0;
1405
	uint8_t	icmp6_type = 0;
1405
	uint8_t	icmp6_type = 0;
1406
	uint16_t ext_hd = 0;	/* bits vector for extension header filtering */
1406
	uint16_t ext_hd = 0;	/* bits vector for extension header filtering */
1407
	/* end of ipv6 variables */
1407
	/* end of ipv6 variables */
1408
1408
1409
	int is_ipv4 = 0;
1409
	int is_ipv4 = 0;
1410
1410
1411
	int done = 0;		/* flag to exit the outer loop */
1411
	int done = 0;		/* flag to exit the outer loop */
1412
	IPFW_RLOCK_TRACKER;
1412
	IPFW_RLOCK_TRACKER;
1413
	bool mem;
1413
	bool mem;
1414
1414
1415
	if ((mem = (args->flags & IPFW_ARGS_LENMASK))) {
1415
	if ((mem = (args->flags & IPFW_ARGS_LENMASK))) {
1416
		if (args->flags & IPFW_ARGS_ETHER) {
1416
		if (args->flags & IPFW_ARGS_ETHER) {
1417
			eh = (struct ether_header *)args->mem;
1417
			eh = (struct ether_header *)args->mem;
1418
			if (eh->ether_type == htons(ETHERTYPE_VLAN))
1418
			if (eh->ether_type == htons(ETHERTYPE_VLAN))
1419
				ip = (struct ip *)
1419
				ip = (struct ip *)
1420
				    ((struct ether_vlan_header *)eh + 1);
1420
				    ((struct ether_vlan_header *)eh + 1);
1421
			else
1421
			else
1422
				ip = (struct ip *)(eh + 1);
1422
				ip = (struct ip *)(eh + 1);
1423
		} else {
1423
		} else {
1424
			eh = NULL;
1424
			eh = NULL;
1425
			ip = (struct ip *)args->mem;
1425
			ip = (struct ip *)args->mem;
1426
		}
1426
		}
1427
		pktlen = IPFW_ARGS_LENGTH(args->flags);
1427
		pktlen = IPFW_ARGS_LENGTH(args->flags);
1428
		args->f_id.fib = args->ifp->if_fib;	/* best guess */
1428
		args->f_id.fib = args->ifp->if_fib;	/* best guess */
1429
	} else {
1429
	} else {
1430
		m = args->m;
1430
		m = args->m;
1431
		if (m->m_flags & M_SKIP_FIREWALL || (! V_ipfw_vnet_ready))
1431
		if (m->m_flags & M_SKIP_FIREWALL || (! V_ipfw_vnet_ready))
1432
			return (IP_FW_PASS);	/* accept */
1432
			return (IP_FW_PASS);	/* accept */
1433
		if (args->flags & IPFW_ARGS_ETHER) {
1433
		if (args->flags & IPFW_ARGS_ETHER) {
1434
	                /* We need some amount of data to be contiguous. */
1434
	                /* We need some amount of data to be contiguous. */
1435
			if (m->m_len < min(m->m_pkthdr.len, max_protohdr) &&
1435
			if (m->m_len < min(m->m_pkthdr.len, max_protohdr) &&
1436
			    (args->m = m = m_pullup(m, min(m->m_pkthdr.len,
1436
			    (args->m = m = m_pullup(m, min(m->m_pkthdr.len,
1437
			    max_protohdr))) == NULL)
1437
			    max_protohdr))) == NULL)
1438
				goto pullup_failed;
1438
				goto pullup_failed;
1439
			eh = mtod(m, struct ether_header *);
1439
			eh = mtod(m, struct ether_header *);
1440
			ip = (struct ip *)(eh + 1);
1440
			ip = (struct ip *)(eh + 1);
1441
		} else {
1441
		} else {
1442
			eh = NULL;
1442
			eh = NULL;
1443
			ip = mtod(m, struct ip *);
1443
			ip = mtod(m, struct ip *);
1444
		}
1444
		}
1445
		pktlen = m->m_pkthdr.len;
1445
		pktlen = m->m_pkthdr.len;
1446
		args->f_id.fib = M_GETFIB(m); /* mbuf not altered */
1446
		args->f_id.fib = M_GETFIB(m); /* mbuf not altered */
1447
	}
1447
	}
1448
1448
1449
	dst_ip.s_addr = 0;		/* make sure it is initialized */
1449
	dst_ip.s_addr = 0;		/* make sure it is initialized */
1450
	src_ip.s_addr = 0;		/* make sure it is initialized */
1450
	src_ip.s_addr = 0;		/* make sure it is initialized */
1451
	src_port = dst_port = 0;
1451
	src_port = dst_port = 0;
1452
1452
1453
	DYN_INFO_INIT(&dyn_info);
1453
	DYN_INFO_INIT(&dyn_info);
1454
/*
1454
/*
1455
 * PULLUP_TO(len, p, T) makes sure that len + sizeof(T) is contiguous,
1455
 * PULLUP_TO(len, p, T) makes sure that len + sizeof(T) is contiguous,
1456
 * then it sets p to point at the offset "len" in the mbuf. WARNING: the
1456
 * then it sets p to point at the offset "len" in the mbuf. WARNING: the
1457
 * pointer might become stale after other pullups (but we never use it
1457
 * pointer might become stale after other pullups (but we never use it
1458
 * this way).
1458
 * this way).
1459
 */
1459
 */
1460
#define	PULLUP_TO(_len, p, T)	PULLUP_LEN(_len, p, sizeof(T))
1460
#define	PULLUP_TO(_len, p, T)	PULLUP_LEN(_len, p, sizeof(T))
1461
#define	EHLEN	(eh != NULL ? ((char *)ip - (char *)eh) : 0)
1461
#define	EHLEN	(eh != NULL ? ((char *)ip - (char *)eh) : 0)
1462
#define	_PULLUP_LOCKED(_len, p, T, unlock)			\
1462
#define	_PULLUP_LOCKED(_len, p, T, unlock)			\
1463
do {								\
1463
do {								\
1464
	int x = (_len) + T + EHLEN;				\
1464
	int x = (_len) + T + EHLEN;				\
1465
	if (mem) {						\
1465
	if (mem) {						\
1466
		if (__predict_false(pktlen < x)) {		\
1466
		if (__predict_false(pktlen < x)) {		\
1467
			unlock;					\
1467
			unlock;					\
1468
			goto pullup_failed;			\
1468
			goto pullup_failed;			\
1469
		}						\
1469
		}						\
1470
		p = (char *)args->mem + (_len) + EHLEN;		\
1470
		p = (char *)args->mem + (_len) + EHLEN;		\
1471
	} else {						\
1471
	} else {						\
1472
		if (__predict_false((m)->m_len < x)) {		\
1472
		if (__predict_false((m)->m_len < x)) {		\
1473
			args->m = m = m_pullup(m, x);		\
1473
			args->m = m = m_pullup(m, x);		\
1474
			if (m == NULL) {			\
1474
			if (m == NULL) {			\
1475
				unlock;				\
1475
				unlock;				\
1476
				goto pullup_failed;		\
1476
				goto pullup_failed;		\
1477
			}					\
1477
			}					\
1478
		}						\
1478
		}						\
1479
		p = mtod(m, char *) + (_len) + EHLEN;		\
1479
		p = mtod(m, char *) + (_len) + EHLEN;		\
1480
	}							\
1480
	}							\
1481
} while (0)
1481
} while (0)
1482
1482
1483
#define	PULLUP_LEN(_len, p, T)	_PULLUP_LOCKED(_len, p, T, )
1483
#define	PULLUP_LEN(_len, p, T)	_PULLUP_LOCKED(_len, p, T, )
1484
#define	PULLUP_LEN_LOCKED(_len, p, T)	\
1484
#define	PULLUP_LEN_LOCKED(_len, p, T)	\
1485
    _PULLUP_LOCKED(_len, p, T, IPFW_PF_RUNLOCK(chain));	\
1485
    _PULLUP_LOCKED(_len, p, T, IPFW_PF_RUNLOCK(chain));	\
1486
    UPDATE_POINTERS()
1486
    UPDATE_POINTERS()
1487
/*
1487
/*
1488
 * In case pointers got stale after pullups, update them.
1488
 * In case pointers got stale after pullups, update them.
1489
 */
1489
 */
1490
#define	UPDATE_POINTERS()					\
1490
#define	UPDATE_POINTERS()					\
1491
do {								\
1491
do {								\
1492
	if (!mem) {						\
1492
	if (!mem) {						\
1493
		if (eh != NULL) {				\
1493
		if (eh != NULL) {				\
1494
			eh = mtod(m, struct ether_header *);	\
1494
			eh = mtod(m, struct ether_header *);	\
1495
			ip = (struct ip *)(eh + 1);		\
1495
			ip = (struct ip *)(eh + 1);		\
1496
		} else						\
1496
		} else						\
1497
			ip = mtod(m, struct ip *);		\
1497
			ip = mtod(m, struct ip *);		\
1498
		args->m = m;					\
1498
		args->m = m;					\
1499
	}							\
1499
	}							\
1500
} while (0)
1500
} while (0)
1501
1501
1502
	/* Identify IP packets and fill up variables. */
1502
	/* Identify IP packets and fill up variables. */
1503
	if (pktlen >= sizeof(struct ip6_hdr) &&
1503
	if (pktlen >= sizeof(struct ip6_hdr) &&
1504
	    (eh == NULL || eh->ether_type == htons(ETHERTYPE_IPV6)) &&
1504
	    (eh == NULL || eh->ether_type == htons(ETHERTYPE_IPV6)) &&
1505
	    ip->ip_v == 6) {
1505
	    ip->ip_v == 6) {
1506
		struct ip6_hdr *ip6 = (struct ip6_hdr *)ip;
1506
		struct ip6_hdr *ip6 = (struct ip6_hdr *)ip;
1507
1507
1508
		is_ipv6 = 1;
1508
		is_ipv6 = 1;
1509
		args->flags |= IPFW_ARGS_IP6;
1509
		args->flags |= IPFW_ARGS_IP6;
1510
		hlen = sizeof(struct ip6_hdr);
1510
		hlen = sizeof(struct ip6_hdr);
1511
		proto = ip6->ip6_nxt;
1511
		proto = ip6->ip6_nxt;
1512
		/* Search extension headers to find upper layer protocols */
1512
		/* Search extension headers to find upper layer protocols */
1513
		while (ulp == NULL && offset == 0) {
1513
		while (ulp == NULL && offset == 0) {
1514
			switch (proto) {
1514
			switch (proto) {
1515
			case IPPROTO_ICMPV6:
1515
			case IPPROTO_ICMPV6:
1516
				PULLUP_TO(hlen, ulp, struct icmp6_hdr);
1516
				PULLUP_TO(hlen, ulp, struct icmp6_hdr);
1517
				icmp6_type = ICMP6(ulp)->icmp6_type;
1517
				icmp6_type = ICMP6(ulp)->icmp6_type;
1518
				break;
1518
				break;
1519
1519
1520
			case IPPROTO_TCP:
1520
			case IPPROTO_TCP:
1521
				PULLUP_TO(hlen, ulp, struct tcphdr);
1521
				PULLUP_TO(hlen, ulp, struct tcphdr);
1522
				dst_port = TCP(ulp)->th_dport;
1522
				dst_port = TCP(ulp)->th_dport;
1523
				src_port = TCP(ulp)->th_sport;
1523
				src_port = TCP(ulp)->th_sport;
1524
				/* save flags for dynamic rules */
1524
				/* save flags for dynamic rules */
1525
				args->f_id._flags = TCP(ulp)->th_flags;
1525
				args->f_id._flags = TCP(ulp)->th_flags;
1526
				break;
1526
				break;
1527
1527
1528
			case IPPROTO_SCTP:
1528
			case IPPROTO_SCTP:
1529
				if (pktlen >= hlen + sizeof(struct sctphdr) +
1529
				if (pktlen >= hlen + sizeof(struct sctphdr) +
1530
				    sizeof(struct sctp_chunkhdr) +
1530
				    sizeof(struct sctp_chunkhdr) +
1531
				    offsetof(struct sctp_init, a_rwnd))
1531
				    offsetof(struct sctp_init, a_rwnd))
1532
					PULLUP_LEN(hlen, ulp,
1532
					PULLUP_LEN(hlen, ulp,
1533
					    sizeof(struct sctphdr) +
1533
					    sizeof(struct sctphdr) +
1534
					    sizeof(struct sctp_chunkhdr) +
1534
					    sizeof(struct sctp_chunkhdr) +
1535
					    offsetof(struct sctp_init, a_rwnd));
1535
					    offsetof(struct sctp_init, a_rwnd));
1536
				else if (pktlen >= hlen + sizeof(struct sctphdr))
1536
				else if (pktlen >= hlen + sizeof(struct sctphdr))
1537
					PULLUP_LEN(hlen, ulp, pktlen - hlen);
1537
					PULLUP_LEN(hlen, ulp, pktlen - hlen);
1538
				else
1538
				else
1539
					PULLUP_LEN(hlen, ulp,
1539
					PULLUP_LEN(hlen, ulp,
1540
					    sizeof(struct sctphdr));
1540
					    sizeof(struct sctphdr));
1541
				src_port = SCTP(ulp)->src_port;
1541
				src_port = SCTP(ulp)->src_port;
1542
				dst_port = SCTP(ulp)->dest_port;
1542
				dst_port = SCTP(ulp)->dest_port;
1543
				break;
1543
				break;
1544
1544
1545
			case IPPROTO_UDP:
1545
			case IPPROTO_UDP:
1546
			case IPPROTO_UDPLITE:
1546
			case IPPROTO_UDPLITE:
1547
				PULLUP_TO(hlen, ulp, struct udphdr);
1547
				PULLUP_TO(hlen, ulp, struct udphdr);
1548
				dst_port = UDP(ulp)->uh_dport;
1548
				dst_port = UDP(ulp)->uh_dport;
1549
				src_port = UDP(ulp)->uh_sport;
1549
				src_port = UDP(ulp)->uh_sport;
1550
				break;
1550
				break;
1551
1551
1552
			case IPPROTO_HOPOPTS:	/* RFC 2460 */
1552
			case IPPROTO_HOPOPTS:	/* RFC 2460 */
1553
				PULLUP_TO(hlen, ulp, struct ip6_hbh);
1553
				PULLUP_TO(hlen, ulp, struct ip6_hbh);
1554
				ext_hd |= EXT_HOPOPTS;
1554
				ext_hd |= EXT_HOPOPTS;
1555
				hlen += (((struct ip6_hbh *)ulp)->ip6h_len + 1) << 3;
1555
				hlen += (((struct ip6_hbh *)ulp)->ip6h_len + 1) << 3;
1556
				proto = ((struct ip6_hbh *)ulp)->ip6h_nxt;
1556
				proto = ((struct ip6_hbh *)ulp)->ip6h_nxt;
1557
				ulp = NULL;
1557
				ulp = NULL;
1558
				break;
1558
				break;
1559
1559
1560
			case IPPROTO_ROUTING:	/* RFC 2460 */
1560
			case IPPROTO_ROUTING:	/* RFC 2460 */
1561
				PULLUP_TO(hlen, ulp, struct ip6_rthdr);
1561
				PULLUP_TO(hlen, ulp, struct ip6_rthdr);
1562
				switch (((struct ip6_rthdr *)ulp)->ip6r_type) {
1562
				switch (((struct ip6_rthdr *)ulp)->ip6r_type) {
1563
				case 0:
1563
				case 0:
1564
					ext_hd |= EXT_RTHDR0;
1564
					ext_hd |= EXT_RTHDR0;
1565
					break;
1565
					break;
1566
				case 2:
1566
				case 2:
1567
					ext_hd |= EXT_RTHDR2;
1567
					ext_hd |= EXT_RTHDR2;
1568
					break;
1568
					break;
1569
				default:
1569
				default:
1570
					if (V_fw_verbose)
1570
					if (V_fw_verbose)
1571
						printf("IPFW2: IPV6 - Unknown "
1571
						printf("IPFW2: IPV6 - Unknown "
1572
						    "Routing Header type(%d)\n",
1572
						    "Routing Header type(%d)\n",
1573
						    ((struct ip6_rthdr *)
1573
						    ((struct ip6_rthdr *)
1574
						    ulp)->ip6r_type);
1574
						    ulp)->ip6r_type);
1575
					if (V_fw_deny_unknown_exthdrs)
1575
					if (V_fw_deny_unknown_exthdrs)
1576
					    return (IP_FW_DENY);
1576
					    return (IP_FW_DENY);
1577
					break;
1577
					break;
1578
				}
1578
				}
1579
				ext_hd |= EXT_ROUTING;
1579
				ext_hd |= EXT_ROUTING;
1580
				hlen += (((struct ip6_rthdr *)ulp)->ip6r_len + 1) << 3;
1580
				hlen += (((struct ip6_rthdr *)ulp)->ip6r_len + 1) << 3;
1581
				proto = ((struct ip6_rthdr *)ulp)->ip6r_nxt;
1581
				proto = ((struct ip6_rthdr *)ulp)->ip6r_nxt;
1582
				ulp = NULL;
1582
				ulp = NULL;
1583
				break;
1583
				break;
1584
1584
1585
			case IPPROTO_FRAGMENT:	/* RFC 2460 */
1585
			case IPPROTO_FRAGMENT:	/* RFC 2460 */
1586
				PULLUP_TO(hlen, ulp, struct ip6_frag);
1586
				PULLUP_TO(hlen, ulp, struct ip6_frag);
1587
				ext_hd |= EXT_FRAGMENT;
1587
				ext_hd |= EXT_FRAGMENT;
1588
				hlen += sizeof (struct ip6_frag);
1588
				hlen += sizeof (struct ip6_frag);
1589
				proto = ((struct ip6_frag *)ulp)->ip6f_nxt;
1589
				proto = ((struct ip6_frag *)ulp)->ip6f_nxt;
1590
				offset = ((struct ip6_frag *)ulp)->ip6f_offlg &
1590
				offset = ((struct ip6_frag *)ulp)->ip6f_offlg &
1591
					IP6F_OFF_MASK;
1591
					IP6F_OFF_MASK;
1592
				ip6f_mf = ((struct ip6_frag *)ulp)->ip6f_offlg &
1592
				ip6f_mf = ((struct ip6_frag *)ulp)->ip6f_offlg &
1593
					IP6F_MORE_FRAG;
1593
					IP6F_MORE_FRAG;
1594
				if (V_fw_permit_single_frag6 == 0 &&
1594
				if (V_fw_permit_single_frag6 == 0 &&
1595
				    offset == 0 && ip6f_mf == 0) {
1595
				    offset == 0 && ip6f_mf == 0) {
1596
					if (V_fw_verbose)
1596
					if (V_fw_verbose)
1597
						printf("IPFW2: IPV6 - Invalid "
1597
						printf("IPFW2: IPV6 - Invalid "
1598
						    "Fragment Header\n");
1598
						    "Fragment Header\n");
1599
					if (V_fw_deny_unknown_exthdrs)
1599
					if (V_fw_deny_unknown_exthdrs)
1600
					    return (IP_FW_DENY);
1600
					    return (IP_FW_DENY);
1601
					break;
1601
					break;
1602
				}
1602
				}
1603
				args->f_id.extra =
1603
				args->f_id.extra =
1604
				    ntohl(((struct ip6_frag *)ulp)->ip6f_ident);
1604
				    ntohl(((struct ip6_frag *)ulp)->ip6f_ident);
1605
				ulp = NULL;
1605
				ulp = NULL;
1606
				break;
1606
				break;
1607
1607
1608
			case IPPROTO_DSTOPTS:	/* RFC 2460 */
1608
			case IPPROTO_DSTOPTS:	/* RFC 2460 */
1609
				PULLUP_TO(hlen, ulp, struct ip6_hbh);
1609
				PULLUP_TO(hlen, ulp, struct ip6_hbh);
1610
				ext_hd |= EXT_DSTOPTS;
1610
				ext_hd |= EXT_DSTOPTS;
1611
				hlen += (((struct ip6_hbh *)ulp)->ip6h_len + 1) << 3;
1611
				hlen += (((struct ip6_hbh *)ulp)->ip6h_len + 1) << 3;
1612
				proto = ((struct ip6_hbh *)ulp)->ip6h_nxt;
1612
				proto = ((struct ip6_hbh *)ulp)->ip6h_nxt;
1613
				ulp = NULL;
1613
				ulp = NULL;
1614
				break;
1614
				break;
1615
1615
1616
			case IPPROTO_AH:	/* RFC 2402 */
1616
			case IPPROTO_AH:	/* RFC 2402 */
1617
				PULLUP_TO(hlen, ulp, struct ip6_ext);
1617
				PULLUP_TO(hlen, ulp, struct ip6_ext);
1618
				ext_hd |= EXT_AH;
1618
				ext_hd |= EXT_AH;
1619
				hlen += (((struct ip6_ext *)ulp)->ip6e_len + 2) << 2;
1619
				hlen += (((struct ip6_ext *)ulp)->ip6e_len + 2) << 2;
1620
				proto = ((struct ip6_ext *)ulp)->ip6e_nxt;
1620
				proto = ((struct ip6_ext *)ulp)->ip6e_nxt;
1621
				ulp = NULL;
1621
				ulp = NULL;
1622
				break;
1622
				break;
1623
1623
1624
			case IPPROTO_ESP:	/* RFC 2406 */
1624
			case IPPROTO_ESP:	/* RFC 2406 */
1625
				PULLUP_TO(hlen, ulp, uint32_t);	/* SPI, Seq# */
1625
				PULLUP_TO(hlen, ulp, uint32_t);	/* SPI, Seq# */
1626
				/* Anything past Seq# is variable length and
1626
				/* Anything past Seq# is variable length and
1627
				 * data past this ext. header is encrypted. */
1627
				 * data past this ext. header is encrypted. */
1628
				ext_hd |= EXT_ESP;
1628
				ext_hd |= EXT_ESP;
1629
				break;
1629
				break;
1630
1630
1631
			case IPPROTO_NONE:	/* RFC 2460 */
1631
			case IPPROTO_NONE:	/* RFC 2460 */
1632
				/*
1632
				/*
1633
				 * Packet ends here, and IPv6 header has
1633
				 * Packet ends here, and IPv6 header has
1634
				 * already been pulled up. If ip6e_len!=0
1634
				 * already been pulled up. If ip6e_len!=0
1635
				 * then octets must be ignored.
1635
				 * then octets must be ignored.
1636
				 */
1636
				 */
1637
				ulp = ip; /* non-NULL to get out of loop. */
1637
				ulp = ip; /* non-NULL to get out of loop. */
1638
				break;
1638
				break;
1639
1639
1640
			case IPPROTO_OSPFIGP:
1640
			case IPPROTO_OSPFIGP:
1641
				/* XXX OSPF header check? */
1641
				/* XXX OSPF header check? */
1642
				PULLUP_TO(hlen, ulp, struct ip6_ext);
1642
				PULLUP_TO(hlen, ulp, struct ip6_ext);
1643
				break;
1643
				break;
1644
1644
1645
			case IPPROTO_PIM:
1645
			case IPPROTO_PIM:
1646
				/* XXX PIM header check? */
1646
				/* XXX PIM header check? */
1647
				PULLUP_TO(hlen, ulp, struct pim);
1647
				PULLUP_TO(hlen, ulp, struct pim);
1648
				break;
1648
				break;
1649
1649
1650
			case IPPROTO_GRE:	/* RFC 1701 */
1650
			case IPPROTO_GRE:	/* RFC 1701 */
1651
				/* XXX GRE header check? */
1651
				/* XXX GRE header check? */
1652
				PULLUP_TO(hlen, ulp, struct grehdr);
1652
				PULLUP_TO(hlen, ulp, struct grehdr);
1653
				break;
1653
				break;
1654
1654
1655
			case IPPROTO_CARP:
1655
			case IPPROTO_CARP:
1656
				PULLUP_TO(hlen, ulp, offsetof(
1656
				PULLUP_TO(hlen, ulp, offsetof(
1657
				    struct carp_header, carp_counter));
1657
				    struct carp_header, carp_counter));
1658
				if (CARP_ADVERTISEMENT !=
1658
				if (CARP_ADVERTISEMENT !=
1659
				    ((struct carp_header *)ulp)->carp_type)
1659
				    ((struct carp_header *)ulp)->carp_type)
1660
					return (IP_FW_DENY);
1660
					return (IP_FW_DENY);
1661
				break;
1661
				break;
1662
1662
1663
			case IPPROTO_IPV6:	/* RFC 2893 */
1663
			case IPPROTO_IPV6:	/* RFC 2893 */
1664
				PULLUP_TO(hlen, ulp, struct ip6_hdr);
1664
				PULLUP_TO(hlen, ulp, struct ip6_hdr);
1665
				break;
1665
				break;
1666
1666
1667
			case IPPROTO_IPV4:	/* RFC 2893 */
1667
			case IPPROTO_IPV4:	/* RFC 2893 */
1668
				PULLUP_TO(hlen, ulp, struct ip);
1668
				PULLUP_TO(hlen, ulp, struct ip);
1669
				break;
1669
				break;
1670
1670
1671
			default:
1671
			default:
1672
				if (V_fw_verbose)
1672
				if (V_fw_verbose)
1673
					printf("IPFW2: IPV6 - Unknown "
1673
					printf("IPFW2: IPV6 - Unknown "
1674
					    "Extension Header(%d), ext_hd=%x\n",
1674
					    "Extension Header(%d), ext_hd=%x\n",
1675
					     proto, ext_hd);
1675
					     proto, ext_hd);
1676
				if (V_fw_deny_unknown_exthdrs)
1676
				if (V_fw_deny_unknown_exthdrs)
1677
				    return (IP_FW_DENY);
1677
				    return (IP_FW_DENY);
1678
				PULLUP_TO(hlen, ulp, struct ip6_ext);
1678
				PULLUP_TO(hlen, ulp, struct ip6_ext);
1679
				break;
1679
				break;
1680
			} /*switch */
1680
			} /*switch */
1681
		}
1681
		}
1682
		UPDATE_POINTERS();
1682
		UPDATE_POINTERS();
1683
		ip6 = (struct ip6_hdr *)ip;
1683
		ip6 = (struct ip6_hdr *)ip;
1684
		args->f_id.addr_type = 6;
1684
		args->f_id.addr_type = 6;
1685
		args->f_id.src_ip6 = ip6->ip6_src;
1685
		args->f_id.src_ip6 = ip6->ip6_src;
1686
		args->f_id.dst_ip6 = ip6->ip6_dst;
1686
		args->f_id.dst_ip6 = ip6->ip6_dst;
1687
		args->f_id.flow_id6 = ntohl(ip6->ip6_flow);
1687
		args->f_id.flow_id6 = ntohl(ip6->ip6_flow);
1688
		iplen = ntohs(ip6->ip6_plen) + sizeof(*ip6);
1688
		iplen = ntohs(ip6->ip6_plen) + sizeof(*ip6);
1689
	} else if (pktlen >= sizeof(struct ip) &&
1689
	} else if (pktlen >= sizeof(struct ip) &&
1690
	    (eh == NULL || eh->ether_type == htons(ETHERTYPE_IP)) &&
1690
	    (eh == NULL || eh->ether_type == htons(ETHERTYPE_IP)) &&
1691
	    ip->ip_v == 4) {
1691
	    ip->ip_v == 4) {
1692
		is_ipv4 = 1;
1692
		is_ipv4 = 1;
1693
		args->flags |= IPFW_ARGS_IP4;
1693
		args->flags |= IPFW_ARGS_IP4;
1694
		hlen = ip->ip_hl << 2;
1694
		hlen = ip->ip_hl << 2;
1695
		/*
1695
		/*
1696
		 * Collect parameters into local variables for faster
1696
		 * Collect parameters into local variables for faster
1697
		 * matching.
1697
		 * matching.
1698
		 */
1698
		 */
1699
		proto = ip->ip_p;
1699
		proto = ip->ip_p;
1700
		src_ip = ip->ip_src;
1700
		src_ip = ip->ip_src;
1701
		dst_ip = ip->ip_dst;
1701
		dst_ip = ip->ip_dst;
1702
		offset = ntohs(ip->ip_off) & IP_OFFMASK;
1702
		offset = ntohs(ip->ip_off) & IP_OFFMASK;
1703
		iplen = ntohs(ip->ip_len);
1703
		iplen = ntohs(ip->ip_len);
1704
1704
1705
		if (offset == 0) {
1705
		if (offset == 0) {
1706
			switch (proto) {
1706
			switch (proto) {
1707
			case IPPROTO_TCP:
1707
			case IPPROTO_TCP:
1708
				PULLUP_TO(hlen, ulp, struct tcphdr);
1708
				PULLUP_TO(hlen, ulp, struct tcphdr);
1709
				dst_port = TCP(ulp)->th_dport;
1709
				dst_port = TCP(ulp)->th_dport;
1710
				src_port = TCP(ulp)->th_sport;
1710
				src_port = TCP(ulp)->th_sport;
1711
				/* save flags for dynamic rules */
1711
				/* save flags for dynamic rules */
1712
				args->f_id._flags = TCP(ulp)->th_flags;
1712
				args->f_id._flags = TCP(ulp)->th_flags;
1713
				break;
1713
				break;
1714
1714
1715
			case IPPROTO_SCTP:
1715
			case IPPROTO_SCTP:
1716
				if (pktlen >= hlen + sizeof(struct sctphdr) +
1716
				if (pktlen >= hlen + sizeof(struct sctphdr) +
1717
				    sizeof(struct sctp_chunkhdr) +
1717
				    sizeof(struct sctp_chunkhdr) +
1718
				    offsetof(struct sctp_init, a_rwnd))
1718
				    offsetof(struct sctp_init, a_rwnd))
1719
					PULLUP_LEN(hlen, ulp,
1719
					PULLUP_LEN(hlen, ulp,
1720
					    sizeof(struct sctphdr) +
1720
					    sizeof(struct sctphdr) +
1721
					    sizeof(struct sctp_chunkhdr) +
1721
					    sizeof(struct sctp_chunkhdr) +
1722
					    offsetof(struct sctp_init, a_rwnd));
1722
					    offsetof(struct sctp_init, a_rwnd));
1723
				else if (pktlen >= hlen + sizeof(struct sctphdr))
1723
				else if (pktlen >= hlen + sizeof(struct sctphdr))
1724
					PULLUP_LEN(hlen, ulp, pktlen - hlen);
1724
					PULLUP_LEN(hlen, ulp, pktlen - hlen);
1725
				else
1725
				else
1726
					PULLUP_LEN(hlen, ulp,
1726
					PULLUP_LEN(hlen, ulp,
1727
					    sizeof(struct sctphdr));
1727
					    sizeof(struct sctphdr));
1728
				src_port = SCTP(ulp)->src_port;
1728
				src_port = SCTP(ulp)->src_port;
1729
				dst_port = SCTP(ulp)->dest_port;
1729
				dst_port = SCTP(ulp)->dest_port;
1730
				break;
1730
				break;
1731
1731
1732
			case IPPROTO_UDP:
1732
			case IPPROTO_UDP:
1733
			case IPPROTO_UDPLITE:
1733
			case IPPROTO_UDPLITE:
1734
				PULLUP_TO(hlen, ulp, struct udphdr);
1734
				PULLUP_TO(hlen, ulp, struct udphdr);
1735
				dst_port = UDP(ulp)->uh_dport;
1735
				dst_port = UDP(ulp)->uh_dport;
1736
				src_port = UDP(ulp)->uh_sport;
1736
				src_port = UDP(ulp)->uh_sport;
1737
				break;
1737
				break;
1738
1738
1739
			case IPPROTO_ICMP:
1739
			case IPPROTO_ICMP:
1740
				PULLUP_TO(hlen, ulp, struct icmphdr);
1740
				PULLUP_TO(hlen, ulp, struct icmphdr);
1741
				//args->f_id.flags = ICMP(ulp)->icmp_type;
1741
				//args->f_id.flags = ICMP(ulp)->icmp_type;
1742
				break;
1742
				break;
1743
1743
1744
			default:
1744
			default:
1745
				break;
1745
				break;
1746
			}
1746
			}
1747
		} else {
1747
		} else {
1748
			if (offset == 1 && proto == IPPROTO_TCP) {
1748
			if (offset == 1 && proto == IPPROTO_TCP) {
1749
				/* RFC 3128 */
1749
				/* RFC 3128 */
1750
				goto pullup_failed;
1750
				goto pullup_failed;
1751
			}
1751
			}
1752
		}
1752
		}
1753
1753
1754
		UPDATE_POINTERS();
1754
		UPDATE_POINTERS();
1755
		args->f_id.addr_type = 4;
1755
		args->f_id.addr_type = 4;
1756
		args->f_id.src_ip = ntohl(src_ip.s_addr);
1756
		args->f_id.src_ip = ntohl(src_ip.s_addr);
1757
		args->f_id.dst_ip = ntohl(dst_ip.s_addr);
1757
		args->f_id.dst_ip = ntohl(dst_ip.s_addr);
1758
	} else {
1758
	} else {
1759
		proto = 0;
1759
		proto = 0;
1760
		dst_ip.s_addr = src_ip.s_addr = 0;
1760
		dst_ip.s_addr = src_ip.s_addr = 0;
1761
1761
1762
		args->f_id.addr_type = 1; /* XXX */
1762
		args->f_id.addr_type = 1; /* XXX */
1763
	}
1763
	}
1764
#undef PULLUP_TO
1764
#undef PULLUP_TO
1765
	pktlen = iplen < pktlen ? iplen: pktlen;
1765
	pktlen = iplen < pktlen ? iplen: pktlen;
1766
1766
1767
	/* Properly initialize the rest of f_id */
1767
	/* Properly initialize the rest of f_id */
1768
	args->f_id.proto = proto;
1768
	args->f_id.proto = proto;
1769
	args->f_id.src_port = src_port = ntohs(src_port);
1769
	args->f_id.src_port = src_port = ntohs(src_port);
1770
	args->f_id.dst_port = dst_port = ntohs(dst_port);
1770
	args->f_id.dst_port = dst_port = ntohs(dst_port);
1771
1771
1772
	IPFW_PF_RLOCK(chain);
1772
	IPFW_PF_RLOCK(chain);
1773
	if (! V_ipfw_vnet_ready) { /* shutting down, leave NOW. */
1773
	if (! V_ipfw_vnet_ready) { /* shutting down, leave NOW. */
1774
		IPFW_PF_RUNLOCK(chain);
1774
		IPFW_PF_RUNLOCK(chain);
1775
		return (IP_FW_PASS);	/* accept */
1775
		return (IP_FW_PASS);	/* accept */
1776
	}
1776
	}
1777
	if (args->flags & IPFW_ARGS_REF) {
1777
	if (args->flags & IPFW_ARGS_REF) {
1778
		/*
1778
		/*
1779
		 * Packet has already been tagged as a result of a previous
1779
		 * Packet has already been tagged as a result of a previous
1780
		 * match on rule args->rule aka args->rule_id (PIPE, QUEUE,
1780
		 * match on rule args->rule aka args->rule_id (PIPE, QUEUE,
1781
		 * REASS, NETGRAPH, DIVERT/TEE...)
1781
		 * REASS, NETGRAPH, DIVERT/TEE...)
1782
		 * Validate the slot and continue from the next one
1782
		 * Validate the slot and continue from the next one
1783
		 * if still present, otherwise do a lookup.
1783
		 * if still present, otherwise do a lookup.
1784
		 */
1784
		 */
1785
		f_pos = (args->rule.chain_id == chain->id) ?
1785
		f_pos = (args->rule.chain_id == chain->id) ?
1786
		    args->rule.slot :
1786
		    args->rule.slot :
1787
		    ipfw_find_rule(chain, args->rule.rulenum,
1787
		    ipfw_find_rule(chain, args->rule.rulenum,
1788
			args->rule.rule_id);
1788
			args->rule.rule_id);
1789
	} else {
1789
	} else {
1790
		f_pos = 0;
1790
		f_pos = 0;
1791
	}
1791
	}
1792
1792
1793
	if (args->flags & IPFW_ARGS_IN) {
1793
	if (args->flags & IPFW_ARGS_IN) {
1794
		iif = args->ifp;
1794
		iif = args->ifp;
1795
		oif = NULL;
1795
		oif = NULL;
1796
	} else {
1796
	} else {
1797
		MPASS(args->flags & IPFW_ARGS_OUT);
1797
		MPASS(args->flags & IPFW_ARGS_OUT);
1798
		iif = mem ? NULL : m_rcvif(m);
1798
		iif = mem ? NULL : m_rcvif(m);
1799
		oif = args->ifp;
1799
		oif = args->ifp;
1800
	}
1800
	}
1801
1801
1802
	/*
1802
	/*
1803
	 * Now scan the rules, and parse microinstructions for each rule.
1803
	 * Now scan the rules, and parse microinstructions for each rule.
1804
	 * We have two nested loops and an inner switch. Sometimes we
1804
	 * We have two nested loops and an inner switch. Sometimes we
1805
	 * need to break out of one or both loops, or re-enter one of
1805
	 * need to break out of one or both loops, or re-enter one of
1806
	 * the loops with updated variables. Loop variables are:
1806
	 * the loops with updated variables. Loop variables are:
1807
	 *
1807
	 *
1808
	 *	f_pos (outer loop) points to the current rule.
1808
	 *	f_pos (outer loop) points to the current rule.
1809
	 *		On output it points to the matching rule.
1809
	 *		On output it points to the matching rule.
1810
	 *	done (outer loop) is used as a flag to break the loop.
1810
	 *	done (outer loop) is used as a flag to break the loop.
1811
	 *	l (inner loop)	residual length of current rule.
1811
	 *	l (inner loop)	residual length of current rule.
1812
	 *		cmd points to the current microinstruction.
1812
	 *		cmd points to the current microinstruction.
1813
	 *
1813
	 *
1814
	 * We break the inner loop by setting l=0 and possibly
1814
	 * We break the inner loop by setting l=0 and possibly
1815
	 * cmdlen=0 if we don't want to advance cmd.
1815
	 * cmdlen=0 if we don't want to advance cmd.
1816
	 * We break the outer loop by setting done=1
1816
	 * We break the outer loop by setting done=1
1817
	 * We can restart the inner loop by setting l>0 and f_pos, f, cmd
1817
	 * We can restart the inner loop by setting l>0 and f_pos, f, cmd
1818
	 * as needed.
1818
	 * as needed.
1819
	 */
1819
	 */
1820
	for (; f_pos < chain->n_rules; f_pos++) {
1820
	for (; f_pos < chain->n_rules; f_pos++) {
1821
		ipfw_insn *cmd;
1821
		ipfw_insn *cmd;
1822
		uint32_t tablearg = 0;
1822
		uint32_t tablearg = 0;
1823
		int l, cmdlen, skip_or; /* skip rest of OR block */
1823
		int l, cmdlen, skip_or; /* skip rest of OR block */
1824
		struct ip_fw *f;
1824
		struct ip_fw *f;
1825
1825
1826
		f = chain->map[f_pos];
1826
		f = chain->map[f_pos];
1827
		if (V_set_disable & (1 << f->set) )
1827
		if (V_set_disable & (1 << f->set) )
1828
			continue;
1828
			continue;
1829
1829
1830
		skip_or = 0;
1830
		skip_or = 0;
1831
		for (l = f->cmd_len, cmd = f->cmd ; l > 0 ;
1831
		for (l = f->cmd_len, cmd = f->cmd ; l > 0 ;
1832
		    l -= cmdlen, cmd += cmdlen) {
1832
		    l -= cmdlen, cmd += cmdlen) {
1833
			int match;
1833
			int match;
1834
1834
1835
			/*
1835
			/*
1836
			 * check_body is a jump target used when we find a
1836
			 * check_body is a jump target used when we find a
1837
			 * CHECK_STATE, and need to jump to the body of
1837
			 * CHECK_STATE, and need to jump to the body of
1838
			 * the target rule.
1838
			 * the target rule.
1839
			 */
1839
			 */
1840
1840
1841
/* check_body: */
1841
/* check_body: */
1842
			cmdlen = F_LEN(cmd);
1842
			cmdlen = F_LEN(cmd);
1843
			/*
1843
			/*
1844
			 * An OR block (insn_1 || .. || insn_n) has the
1844
			 * An OR block (insn_1 || .. || insn_n) has the
1845
			 * F_OR bit set in all but the last instruction.
1845
			 * F_OR bit set in all but the last instruction.
1846
			 * The first match will set "skip_or", and cause
1846
			 * The first match will set "skip_or", and cause
1847
			 * the following instructions to be skipped until
1847
			 * the following instructions to be skipped until
1848
			 * past the one with the F_OR bit clear.
1848
			 * past the one with the F_OR bit clear.
1849
			 */
1849
			 */
1850
			if (skip_or) {		/* skip this instruction */
1850
			if (skip_or) {		/* skip this instruction */
1851
				if ((cmd->len & F_OR) == 0)
1851
				if ((cmd->len & F_OR) == 0)
1852
					skip_or = 0;	/* next one is good */
1852
					skip_or = 0;	/* next one is good */
1853
				continue;
1853
				continue;
1854
			}
1854
			}
1855
			match = 0; /* set to 1 if we succeed */
1855
			match = 0; /* set to 1 if we succeed */
1856
1856
1857
			switch (cmd->opcode) {
1857
			switch (cmd->opcode) {
1858
			/*
1858
			/*
1859
			 * The first set of opcodes compares the packet's
1859
			 * The first set of opcodes compares the packet's
1860
			 * fields with some pattern, setting 'match' if a
1860
			 * fields with some pattern, setting 'match' if a
1861
			 * match is found. At the end of the loop there is
1861
			 * match is found. At the end of the loop there is
1862
			 * logic to deal with F_NOT and F_OR flags associated
1862
			 * logic to deal with F_NOT and F_OR flags associated
1863
			 * with the opcode.
1863
			 * with the opcode.
1864
			 */
1864
			 */
1865
			case O_NOP:
1865
			case O_NOP:
1866
				match = 1;
1866
				match = 1;
1867
				break;
1867
				break;
1868
1868
1869
			case O_FORWARD_MAC:
1869
			case O_FORWARD_MAC:
1870
				printf("ipfw: opcode %d unimplemented\n",
1870
				printf("ipfw: opcode %d unimplemented\n",
1871
				    cmd->opcode);
1871
				    cmd->opcode);
1872
				break;
1872
				break;
1873
1873
1874
			case O_GID:
1874
			case O_GID:
1875
			case O_UID:
1875
			case O_UID:
1876
			case O_JAIL:
1876
			case O_JAIL:
1877
				/*
1877
				/*
1878
				 * We only check offset == 0 && proto != 0,
1878
				 * We only check offset == 0 && proto != 0,
1879
				 * as this ensures that we have a
1879
				 * as this ensures that we have a
1880
				 * packet with the ports info.
1880
				 * packet with the ports info.
1881
				 */
1881
				 */
1882
				if (offset != 0)
1882
				if (offset != 0)
1883
					break;
1883
					break;
1884
				if (proto == IPPROTO_TCP ||
1884
				if (proto == IPPROTO_TCP ||
1885
				    proto == IPPROTO_UDP ||
1885
				    proto == IPPROTO_UDP ||
1886
				    proto == IPPROTO_UDPLITE)
1886
				    proto == IPPROTO_UDPLITE)
1887
					match = check_uidgid(
1887
					match = check_uidgid(
1888
						    (ipfw_insn_u32 *)cmd,
1888
						    (ipfw_insn_u32 *)cmd,
1889
						    args, &ucred_lookup,
1889
						    args, &ucred_lookup,
1890
#ifdef __FreeBSD__
1890
#ifdef __FreeBSD__
1891
						    &ucred_cache);
1891
						    &ucred_cache);
1892
#else
1892
#else
1893
						    (void *)&ucred_cache);
1893
						    (void *)&ucred_cache);
1894
#endif
1894
#endif
1895
				break;
1895
				break;
1896
1896
1897
			case O_RECV:
1897
			case O_RECV:
1898
				match = iface_match(iif, (ipfw_insn_if *)cmd,
1898
				match = iface_match(iif, (ipfw_insn_if *)cmd,
1899
				    chain, &tablearg);
1899
				    chain, &tablearg);
1900
				break;
1900
				break;
1901
1901
1902
			case O_XMIT:
1902
			case O_XMIT:
1903
				match = iface_match(oif, (ipfw_insn_if *)cmd,
1903
				match = iface_match(oif, (ipfw_insn_if *)cmd,
1904
				    chain, &tablearg);
1904
				    chain, &tablearg);
1905
				break;
1905
				break;
1906
1906
1907
			case O_VIA:
1907
			case O_VIA:
1908
				match = iface_match(args->ifp,
1908
				match = iface_match(args->ifp,
1909
				    (ipfw_insn_if *)cmd, chain, &tablearg);
1909
				    (ipfw_insn_if *)cmd, chain, &tablearg);
1910
				break;
1910
				break;
1911
1911
1912
			case O_MACADDR2:
1912
			case O_MACADDR2:
1913
				if (args->flags & IPFW_ARGS_ETHER) {
1913
				if (args->flags & IPFW_ARGS_ETHER) {
1914
					u_int32_t *want = (u_int32_t *)
1914
					u_int32_t *want = (u_int32_t *)
1915
						((ipfw_insn_mac *)cmd)->addr;
1915
						((ipfw_insn_mac *)cmd)->addr;
1916
					u_int32_t *mask = (u_int32_t *)
1916
					u_int32_t *mask = (u_int32_t *)
1917
						((ipfw_insn_mac *)cmd)->mask;
1917
						((ipfw_insn_mac *)cmd)->mask;
1918
					u_int32_t *hdr = (u_int32_t *)eh;
1918
					u_int32_t *hdr = (u_int32_t *)eh;
1919
1919
1920
					match =
1920
					match =
1921
					    ( want[0] == (hdr[0] & mask[0]) &&
1921
					    ( want[0] == (hdr[0] & mask[0]) &&
1922
					      want[1] == (hdr[1] & mask[1]) &&
1922
					      want[1] == (hdr[1] & mask[1]) &&
1923
					      want[2] == (hdr[2] & mask[2]) );
1923
					      want[2] == (hdr[2] & mask[2]) );
1924
				}
1924
				}
1925
				break;
1925
				break;
1926
1926
1927
			case O_MAC_TYPE:
1927
			case O_MAC_TYPE:
1928
				if (args->flags & IPFW_ARGS_ETHER) {
1928
				if (args->flags & IPFW_ARGS_ETHER) {
1929
					u_int16_t *p =
1929
					u_int16_t *p =
1930
					    ((ipfw_insn_u16 *)cmd)->ports;
1930
					    ((ipfw_insn_u16 *)cmd)->ports;
1931
					int i;
1931
					int i;
1932
1932
1933
					for (i = cmdlen - 1; !match && i>0;
1933
					for (i = cmdlen - 1; !match && i>0;
1934
					    i--, p += 2)
1934
					    i--, p += 2)
1935
						match =
1935
						match =
1936
						    (ntohs(eh->ether_type) >=
1936
						    (ntohs(eh->ether_type) >=
1937
						    p[0] &&
1937
						    p[0] &&
1938
						    ntohs(eh->ether_type) <=
1938
						    ntohs(eh->ether_type) <=
1939
						    p[1]);
1939
						    p[1]);
1940
				}
1940
				}
1941
				break;
1941
				break;
1942
1942
1943
			case O_FRAG:
1943
			case O_FRAG:
1944
				match = (offset != 0);
1944
				match = (offset != 0);
1945
				break;
1945
				break;
1946
1946
1947
			case O_IN:	/* "out" is "not in" */
1947
			case O_IN:	/* "out" is "not in" */
1948
				match = (oif == NULL);
1948
				match = (oif == NULL);
1949
				break;
1949
				break;
1950
1950
1951
			case O_LAYER2:
1951
			case O_LAYER2:
1952
				match = (args->flags & IPFW_ARGS_ETHER);
1952
				match = (args->flags & IPFW_ARGS_ETHER);
1953
				break;
1953
				break;
1954
1954
1955
			case O_DIVERTED:
1955
			case O_DIVERTED:
1956
				if ((args->flags & IPFW_ARGS_REF) == 0)
1956
				if ((args->flags & IPFW_ARGS_REF) == 0)
1957
					break;
1957
					break;
1958
				/*
1958
				/*
1959
				 * For diverted packets, args->rule.info
1959
				 * For diverted packets, args->rule.info
1960
				 * contains the divert port (in host format)
1960
				 * contains the divert port (in host format)
1961
				 * reason and direction.
1961
				 * reason and direction.
1962
				 */
1962
				 */
1963
				match = ((args->rule.info & IPFW_IS_MASK) ==
1963
				match = ((args->rule.info & IPFW_IS_MASK) ==
1964
				    IPFW_IS_DIVERT) && (
1964
				    IPFW_IS_DIVERT) && (
1965
				    ((args->rule.info & IPFW_INFO_IN) ?
1965
				    ((args->rule.info & IPFW_INFO_IN) ?
1966
					1: 2) & cmd->arg1);
1966
					1: 2) & cmd->arg1);
1967
				break;
1967
				break;
1968
1968
1969
			case O_PROTO:
1969
			case O_PROTO:
1970
				/*
1970
				/*
1971
				 * We do not allow an arg of 0 so the
1971
				 * We do not allow an arg of 0 so the
1972
				 * check of "proto" only suffices.
1972
				 * check of "proto" only suffices.
1973
				 */
1973
				 */
1974
				match = (proto == cmd->arg1);
1974
				match = (proto == cmd->arg1);
1975
				break;
1975
				break;
1976
1976
1977
			case O_IP_SRC:
1977
			case O_IP_SRC:
1978
				match = is_ipv4 &&
1978
				match = is_ipv4 &&
1979
				    (((ipfw_insn_ip *)cmd)->addr.s_addr ==
1979
				    (((ipfw_insn_ip *)cmd)->addr.s_addr ==
1980
				    src_ip.s_addr);
1980
				    src_ip.s_addr);
1981
				break;
1981
				break;
1982
1982
1983
			case O_IP_DST_LOOKUP:
1983
			case O_IP_DST_LOOKUP:
1984
			{
1984
			{
1985
				void *pkey;
1985
				void *pkey;
1986
				uint32_t vidx, key;
1986
				uint32_t vidx, key;
1987
				uint16_t keylen;
1987
				uint16_t keylen;
1988
1988
1989
				if (cmdlen > F_INSN_SIZE(ipfw_insn_u32)) {
1989
				if (cmdlen > F_INSN_SIZE(ipfw_insn_u32)) {
1990
					/* Determine lookup key type */
1990
					/* Determine lookup key type */
1991
					vidx = ((ipfw_insn_u32 *)cmd)->d[1];
1991
					vidx = ((ipfw_insn_u32 *)cmd)->d[1];
1992
					if (vidx != 4 /* uid */ &&
1992
					if (vidx != 4 /* uid */ &&
1993
					    vidx != 5 /* jail */ &&
1993
					    vidx != 5 /* jail */ &&
1994
					    is_ipv6 == 0 && is_ipv4 == 0)
1994
					    is_ipv6 == 0 && is_ipv4 == 0)
1995
						break;
1995
						break;
1996
					/* Determine key length */
1996
					/* Determine key length */
1997
					if (vidx == 0 /* dst-ip */ ||
1997
					if (vidx == 0 /* dst-ip */ ||
1998
					    vidx == 1 /* src-ip */)
1998
					    vidx == 1 /* src-ip */)
1999
						keylen = is_ipv6 ?
1999
						keylen = is_ipv6 ?
2000
						    sizeof(struct in6_addr):
2000
						    sizeof(struct in6_addr):
2001
						    sizeof(in_addr_t);
2001
						    sizeof(in_addr_t);
2002
					else {
2002
					else {
2003
						keylen = sizeof(key);
2003
						keylen = sizeof(key);
2004
						pkey = &key;
2004
						pkey = &key;
2005
					}
2005
					}
2006
					if (vidx == 0 /* dst-ip */)
2006
					if (vidx == 0 /* dst-ip */)
2007
						pkey = is_ipv4 ? (void *)&dst_ip:
2007
						pkey = is_ipv4 ? (void *)&dst_ip:
2008
						    (void *)&args->f_id.dst_ip6;
2008
						    (void *)&args->f_id.dst_ip6;
2009
					else if (vidx == 1 /* src-ip */)
2009
					else if (vidx == 1 /* src-ip */)
2010
						pkey = is_ipv4 ? (void *)&src_ip:
2010
						pkey = is_ipv4 ? (void *)&src_ip:
2011
						    (void *)&args->f_id.src_ip6;
2011
						    (void *)&args->f_id.src_ip6;
2012
					else if (vidx == 6 /* dscp */) {
2012
					else if (vidx == 6 /* dscp */) {
2013
						if (is_ipv4)
2013
						if (is_ipv4)
2014
							key = ip->ip_tos >> 2;
2014
							key = ip->ip_tos >> 2;
2015
						else {
2015
						else {
2016
							key = args->f_id.flow_id6;
2016
							key = args->f_id.flow_id6;
2017
							key = (key & 0x0f) << 2 |
2017
							key = (key & 0x0f) << 2 |
2018
							    (key & 0xf000) >> 14;
2018
							    (key & 0xf000) >> 14;
2019
						}
2019
						}
2020
						key &= 0x3f;
2020
						key &= 0x3f;
2021
					} else if (vidx == 2 /* dst-port */ ||
2021
					} else if (vidx == 2 /* dst-port */ ||
2022
					    vidx == 3 /* src-port */) {
2022
					    vidx == 3 /* src-port */) {
2023
						/* Skip fragments */
2023
						/* Skip fragments */
2024
						if (offset != 0)
2024
						if (offset != 0)
2025
							break;
2025
							break;
2026
						/* Skip proto without ports */
2026
						/* Skip proto without ports */
2027
						if (proto != IPPROTO_TCP &&
2027
						if (proto != IPPROTO_TCP &&
2028
						    proto != IPPROTO_UDP &&
2028
						    proto != IPPROTO_UDP &&
2029
						    proto != IPPROTO_UDPLITE &&
2029
						    proto != IPPROTO_UDPLITE &&
2030
						    proto != IPPROTO_SCTP)
2030
						    proto != IPPROTO_SCTP)
2031
							break;
2031
							break;
2032
						if (vidx == 2 /* dst-port */)
2032
						if (vidx == 2 /* dst-port */)
2033
							key = dst_port;
2033
							key = dst_port;
2034
						else
2034
						else
2035
							key = src_port;
2035
							key = src_port;
2036
					}
2036
					}
2037
#ifndef USERSPACE
2037
#ifndef USERSPACE
2038
					else if (vidx == 4 /* uid */ ||
2038
					else if (vidx == 4 /* uid */ ||
2039
					    vidx == 5 /* jail */) {
2039
					    vidx == 5 /* jail */) {
2040
						check_uidgid(
2040
						check_uidgid(
2041
						    (ipfw_insn_u32 *)cmd,
2041
						    (ipfw_insn_u32 *)cmd,
2042
						    args, &ucred_lookup,
2042
						    args, &ucred_lookup,
2043
#ifdef __FreeBSD__
2043
#ifdef __FreeBSD__
2044
						    &ucred_cache);
2044
						    &ucred_cache);
2045
						if (vidx == 4 /* uid */)
2045
						if (vidx == 4 /* uid */)
2046
							key = ucred_cache->cr_uid;
2046
							key = ucred_cache->cr_uid;
2047
						else if (vidx == 5 /* jail */)
2047
						else if (vidx == 5 /* jail */)
2048
							key = ucred_cache->cr_prison->pr_id;
2048
							key = ucred_cache->cr_prison->pr_id;
2049
#else /* !__FreeBSD__ */
2049
#else /* !__FreeBSD__ */
2050
						    (void *)&ucred_cache);
2050
						    (void *)&ucred_cache);
2051
						if (vidx == 4 /* uid */)
2051
						if (vidx == 4 /* uid */)
2052
							key = ucred_cache.uid;
2052
							key = ucred_cache.uid;
2053
						else if (vidx == 5 /* jail */)
2053
						else if (vidx == 5 /* jail */)
2054
							key = ucred_cache.xid;
2054
							key = ucred_cache.xid;
2055
#endif /* !__FreeBSD__ */
2055
#endif /* !__FreeBSD__ */
2056
					}
2056
					}
2057
#endif /* !USERSPACE */
2057
#endif /* !USERSPACE */
2058
					else
2058
					else
2059
						break;
2059
						break;
2060
					match = ipfw_lookup_table(chain,
2060
					match = ipfw_lookup_table(chain,
2061
					    cmd->arg1, keylen, pkey, &vidx);
2061
					    cmd->arg1, keylen, pkey, &vidx);
2062
					if (!match)
2062
					if (!match)
2063
						break;
2063
						break;
2064
					tablearg = vidx;
2064
					tablearg = vidx;
2065
					break;
2065
					break;
2066
				}
2066
				}
2067
				/* cmdlen =< F_INSN_SIZE(ipfw_insn_u32) */
2067
				/* cmdlen =< F_INSN_SIZE(ipfw_insn_u32) */
2068
				/* FALLTHROUGH */
2068
				/* FALLTHROUGH */
2069
			}
2069
			}
2070
			case O_IP_SRC_LOOKUP:
2070
			case O_IP_SRC_LOOKUP:
2071
			{
2071
			{
2072
				void *pkey;
2072
				void *pkey;
2073
				uint32_t vidx;
2073
				uint32_t vidx;
2074
				uint16_t keylen;
2074
				uint16_t keylen;
2075
2075
2076
				if (is_ipv4) {
2076
				if (is_ipv4) {
2077
					keylen = sizeof(in_addr_t);
2077
					keylen = sizeof(in_addr_t);
2078
					if (cmd->opcode == O_IP_DST_LOOKUP)
2078
					if (cmd->opcode == O_IP_DST_LOOKUP)
2079
						pkey = &dst_ip;
2079
						pkey = &dst_ip;
2080
					else
2080
					else
2081
						pkey = &src_ip;
2081
						pkey = &src_ip;
2082
				} else if (is_ipv6) {
2082
				} else if (is_ipv6) {
2083
					keylen = sizeof(struct in6_addr);
2083
					keylen = sizeof(struct in6_addr);
2084
					if (cmd->opcode == O_IP_DST_LOOKUP)
2084
					if (cmd->opcode == O_IP_DST_LOOKUP)
2085
						pkey = &args->f_id.dst_ip6;
2085
						pkey = &args->f_id.dst_ip6;
2086
					else
2086
					else
2087
						pkey = &args->f_id.src_ip6;
2087
						pkey = &args->f_id.src_ip6;
2088
				} else
2088
				} else
2089
					break;
2089
					break;
2090
				match = ipfw_lookup_table(chain, cmd->arg1,
2090
				match = ipfw_lookup_table(chain, cmd->arg1,
2091
				    keylen, pkey, &vidx);
2091
				    keylen, pkey, &vidx);
2092
				if (!match)
2092
				if (!match)
2093
					break;
2093
					break;
2094
				if (cmdlen == F_INSN_SIZE(ipfw_insn_u32)) {
2094
				if (cmdlen == F_INSN_SIZE(ipfw_insn_u32)) {
2095
					match = ((ipfw_insn_u32 *)cmd)->d[0] ==
2095
					match = ((ipfw_insn_u32 *)cmd)->d[0] ==
2096
					    TARG_VAL(chain, vidx, tag);
2096
					    TARG_VAL(chain, vidx, tag);
2097
					if (!match)
2097
					if (!match)
2098
						break;
2098
						break;
2099
				}
2099
				}
2100
				tablearg = vidx;
2100
				tablearg = vidx;
2101
				break;
2101
				break;
2102
			}
2102
			}
2103
2103
2104
			case O_IP_FLOW_LOOKUP:
2104
			case O_IP_FLOW_LOOKUP:
2105
				{
2105
				{
2106
					uint32_t v = 0;
2106
					uint32_t v = 0;
2107
					match = ipfw_lookup_table(chain,
2107
					match = ipfw_lookup_table(chain,
2108
					    cmd->arg1, 0, &args->f_id, &v);
2108
					    cmd->arg1, 0, &args->f_id, &v);
2109
					if (cmdlen == F_INSN_SIZE(ipfw_insn_u32))
2109
					if (cmdlen == F_INSN_SIZE(ipfw_insn_u32))
2110
						match = ((ipfw_insn_u32 *)cmd)->d[0] ==
2110
						match = ((ipfw_insn_u32 *)cmd)->d[0] ==
2111
						    TARG_VAL(chain, v, tag);
2111
						    TARG_VAL(chain, v, tag);
2112
					if (match)
2112
					if (match)
2113
						tablearg = v;
2113
						tablearg = v;
2114
				}
2114
				}
2115
				break;
2115
				break;
2116
			case O_IP_SRC_MASK:
2116
			case O_IP_SRC_MASK:
2117
			case O_IP_DST_MASK:
2117
			case O_IP_DST_MASK:
2118
				if (is_ipv4) {
2118
				if (is_ipv4) {
2119
				    uint32_t a =
2119
				    uint32_t a =
2120
					(cmd->opcode == O_IP_DST_MASK) ?
2120
					(cmd->opcode == O_IP_DST_MASK) ?
2121
					    dst_ip.s_addr : src_ip.s_addr;
2121
					    dst_ip.s_addr : src_ip.s_addr;
2122
				    uint32_t *p = ((ipfw_insn_u32 *)cmd)->d;
2122
				    uint32_t *p = ((ipfw_insn_u32 *)cmd)->d;
2123
				    int i = cmdlen-1;
2123
				    int i = cmdlen-1;
2124
2124
2125
				    for (; !match && i>0; i-= 2, p+= 2)
2125
				    for (; !match && i>0; i-= 2, p+= 2)
2126
					match = (p[0] == (a & p[1]));
2126
					match = (p[0] == (a & p[1]));
2127
				}
2127
				}
2128
				break;
2128
				break;
2129
2129
2130
			case O_IP_SRC_ME:
2130
			case O_IP_SRC_ME:
2131
				if (is_ipv4) {
2131
				if (is_ipv4) {
2132
					match = in_localip(src_ip);
2132
					match = in_localip(src_ip);
2133
					break;
2133
					break;
2134
				}
2134
				}
2135
#ifdef INET6
2135
#ifdef INET6
2136
				/* FALLTHROUGH */
2136
				/* FALLTHROUGH */
2137
			case O_IP6_SRC_ME:
2137
			case O_IP6_SRC_ME:
2138
				match = is_ipv6 &&
2138
				match = is_ipv6 &&
2139
				    ipfw_localip6(&args->f_id.src_ip6);
2139
				    ipfw_localip6(&args->f_id.src_ip6);
2140
#endif
2140
#endif
2141
				break;
2141
				break;
2142
2142
2143
			case O_IP_DST_SET:
2143
			case O_IP_DST_SET:
2144
			case O_IP_SRC_SET:
2144
			case O_IP_SRC_SET:
2145
				if (is_ipv4) {
2145
				if (is_ipv4) {
2146
					u_int32_t *d = (u_int32_t *)(cmd+1);
2146
					u_int32_t *d = (u_int32_t *)(cmd+1);
2147
					u_int32_t addr =
2147
					u_int32_t addr =
2148
					    cmd->opcode == O_IP_DST_SET ?
2148
					    cmd->opcode == O_IP_DST_SET ?
2149
						args->f_id.dst_ip :
2149
						args->f_id.dst_ip :
2150
						args->f_id.src_ip;
2150
						args->f_id.src_ip;
2151
2151
2152
					    if (addr < d[0])
2152
					    if (addr < d[0])
2153
						    break;
2153
						    break;
2154
					    addr -= d[0]; /* subtract base */
2154
					    addr -= d[0]; /* subtract base */
2155
					    match = (addr < cmd->arg1) &&
2155
					    match = (addr < cmd->arg1) &&
2156
						( d[ 1 + (addr>>5)] &
2156
						( d[ 1 + (addr>>5)] &
2157
						  (1<<(addr & 0x1f)) );
2157
						  (1<<(addr & 0x1f)) );
2158
				}
2158
				}
2159
				break;
2159
				break;
2160
2160
2161
			case O_IP_DST:
2161
			case O_IP_DST:
2162
				match = is_ipv4 &&
2162
				match = is_ipv4 &&
2163
				    (((ipfw_insn_ip *)cmd)->addr.s_addr ==
2163
				    (((ipfw_insn_ip *)cmd)->addr.s_addr ==
2164
				    dst_ip.s_addr);
2164
				    dst_ip.s_addr);
2165
				break;
2165
				break;
2166
2166
2167
			case O_IP_DST_ME:
2167
			case O_IP_DST_ME:
2168
				if (is_ipv4) {
2168
				if (is_ipv4) {
2169
					match = in_localip(dst_ip);
2169
					match = in_localip(dst_ip);
2170
					break;
2170
					break;
2171
				}
2171
				}
2172
#ifdef INET6
2172
#ifdef INET6
2173
				/* FALLTHROUGH */
2173
				/* FALLTHROUGH */
2174
			case O_IP6_DST_ME:
2174
			case O_IP6_DST_ME:
2175
				match = is_ipv6 &&
2175
				match = is_ipv6 &&
2176
				    ipfw_localip6(&args->f_id.dst_ip6);
2176
				    ipfw_localip6(&args->f_id.dst_ip6);
2177
#endif
2177
#endif
2178
				break;
2178
				break;
2179
2179
2180
2180
2181
			case O_IP_SRCPORT:
2181
			case O_IP_SRCPORT:
2182
			case O_IP_DSTPORT:
2182
			case O_IP_DSTPORT:
2183
				/*
2183
				/*
2184
				 * offset == 0 && proto != 0 is enough
2184
				 * offset == 0 && proto != 0 is enough
2185
				 * to guarantee that we have a
2185
				 * to guarantee that we have a
2186
				 * packet with port info.
2186
				 * packet with port info.
2187
				 */
2187
				 */
2188
				if ((proto == IPPROTO_UDP ||
2188
				if ((proto == IPPROTO_UDP ||
2189
				    proto == IPPROTO_UDPLITE ||
2189
				    proto == IPPROTO_UDPLITE ||
2190
				    proto == IPPROTO_TCP ||
2190
				    proto == IPPROTO_TCP ||
2191
				    proto == IPPROTO_SCTP) && offset == 0) {
2191
				    proto == IPPROTO_SCTP) && offset == 0) {
2192
					u_int16_t x =
2192
					u_int16_t x =
2193
					    (cmd->opcode == O_IP_SRCPORT) ?
2193
					    (cmd->opcode == O_IP_SRCPORT) ?
2194
						src_port : dst_port ;
2194
						src_port : dst_port ;
2195
					u_int16_t *p =
2195
					u_int16_t *p =
2196
					    ((ipfw_insn_u16 *)cmd)->ports;
2196
					    ((ipfw_insn_u16 *)cmd)->ports;
2197
					int i;
2197
					int i;
2198
2198
2199
					for (i = cmdlen - 1; !match && i>0;
2199
					for (i = cmdlen - 1; !match && i>0;
2200
					    i--, p += 2)
2200
					    i--, p += 2)
2201
						match = (x>=p[0] && x<=p[1]);
2201
						match = (x>=p[0] && x<=p[1]);
2202
				}
2202
				}
2203
				break;
2203
				break;
2204
2204
2205
			case O_ICMPTYPE:
2205
			case O_ICMPTYPE:
2206
				match = (offset == 0 && proto==IPPROTO_ICMP &&
2206
				match = (offset == 0 && proto==IPPROTO_ICMP &&
2207
				    icmptype_match(ICMP(ulp), (ipfw_insn_u32 *)cmd) );
2207
				    icmptype_match(ICMP(ulp), (ipfw_insn_u32 *)cmd) );
2208
				break;
2208
				break;
2209
2209
2210
#ifdef INET6
2210
#ifdef INET6
2211
			case O_ICMP6TYPE:
2211
			case O_ICMP6TYPE:
2212
				match = is_ipv6 && offset == 0 &&
2212
				match = is_ipv6 && offset == 0 &&
2213
				    proto==IPPROTO_ICMPV6 &&
2213
				    proto==IPPROTO_ICMPV6 &&
2214
				    icmp6type_match(
2214
				    icmp6type_match(
2215
					ICMP6(ulp)->icmp6_type,
2215
					ICMP6(ulp)->icmp6_type,
2216
					(ipfw_insn_u32 *)cmd);
2216
					(ipfw_insn_u32 *)cmd);
2217
				break;
2217
				break;
2218
#endif /* INET6 */
2218
#endif /* INET6 */
2219
2219
2220
			case O_IPOPT:
2220
			case O_IPOPT:
2221
				match = (is_ipv4 &&
2221
				match = (is_ipv4 &&
2222
				    ipopts_match(ip, cmd) );
2222
				    ipopts_match(ip, cmd) );
2223
				break;
2223
				break;
2224
2224
2225
			case O_IPVER:
2225
			case O_IPVER:
2226
				match = (is_ipv4 &&
2226
				match = (is_ipv4 &&
2227
				    cmd->arg1 == ip->ip_v);
2227
				    cmd->arg1 == ip->ip_v);
2228
				break;
2228
				break;
2229
2229
2230
			case O_IPID:
2230
			case O_IPID:
2231
			case O_IPTTL:
2231
			case O_IPTTL:
2232
				if (!is_ipv4)
2232
				if (!is_ipv4)
2233
					break;
2233
					break;
2234
			case O_IPLEN:
2234
			case O_IPLEN:
2235
				{	/* only for IP packets */
2235
				{	/* only for IP packets */
2236
				    uint16_t x;
2236
				    uint16_t x;
2237
				    uint16_t *p;
2237
				    uint16_t *p;
2238
				    int i;
2238
				    int i;
2239
2239
2240
				    if (cmd->opcode == O_IPLEN)
2240
				    if (cmd->opcode == O_IPLEN)
2241
					x = iplen;
2241
					x = iplen;
2242
				    else if (cmd->opcode == O_IPTTL)
2242
				    else if (cmd->opcode == O_IPTTL)
2243
					x = ip->ip_ttl;
2243
					x = ip->ip_ttl;
2244
				    else /* must be IPID */
2244
				    else /* must be IPID */
2245
					x = ntohs(ip->ip_id);
2245
					x = ntohs(ip->ip_id);
2246
				    if (cmdlen == 1) {
2246
				    if (cmdlen == 1) {
2247
					match = (cmd->arg1 == x);
2247
					match = (cmd->arg1 == x);
2248
					break;
2248
					break;
2249
				    }
2249
				    }
2250
				    /* otherwise we have ranges */
2250
				    /* otherwise we have ranges */
2251
				    p = ((ipfw_insn_u16 *)cmd)->ports;
2251
				    p = ((ipfw_insn_u16 *)cmd)->ports;
2252
				    i = cmdlen - 1;
2252
				    i = cmdlen - 1;
2253
				    for (; !match && i>0; i--, p += 2)
2253
				    for (; !match && i>0; i--, p += 2)
2254
					match = (x >= p[0] && x <= p[1]);
2254
					match = (x >= p[0] && x <= p[1]);
2255
				}
2255
				}
2256
				break;
2256
				break;
2257
2257
2258
			case O_IPPRECEDENCE:
2258
			case O_IPPRECEDENCE:
2259
				match = (is_ipv4 &&
2259
				match = (is_ipv4 &&
2260
				    (cmd->arg1 == (ip->ip_tos & 0xe0)) );
2260
				    (cmd->arg1 == (ip->ip_tos & 0xe0)) );
2261
				break;
2261
				break;
2262
2262
2263
			case O_IPTOS:
2263
			case O_IPTOS:
2264
				match = (is_ipv4 &&
2264
				match = (is_ipv4 &&
2265
				    flags_match(cmd, ip->ip_tos));
2265
				    flags_match(cmd, ip->ip_tos));
2266
				break;
2266
				break;
2267
2267
2268
			case O_DSCP:
2268
			case O_DSCP:
2269
			    {
2269
			    {
2270
				uint32_t *p;
2270
				uint32_t *p;
2271
				uint16_t x;
2271
				uint16_t x;
2272
2272
2273
				p = ((ipfw_insn_u32 *)cmd)->d;
2273
				p = ((ipfw_insn_u32 *)cmd)->d;
2274
2274
2275
				if (is_ipv4)
2275
				if (is_ipv4)
2276
					x = ip->ip_tos >> 2;
2276
					x = ip->ip_tos >> 2;
2277
				else if (is_ipv6) {
2277
				else if (is_ipv6) {
2278
					uint8_t *v;
2278
					uint8_t *v;
2279
					v = &((struct ip6_hdr *)ip)->ip6_vfc;
2279
					v = &((struct ip6_hdr *)ip)->ip6_vfc;
2280
					x = (*v & 0x0F) << 2;
2280
					x = (*v & 0x0F) << 2;
2281
					v++;
2281
					v++;
2282
					x |= *v >> 6;
2282
					x |= *v >> 6;
2283
				} else
2283
				} else
2284
					break;
2284
					break;
2285
2285
2286
				/* DSCP bitmask is stored as low_u32 high_u32 */
2286
				/* DSCP bitmask is stored as low_u32 high_u32 */
2287
				if (x >= 32)
2287
				if (x >= 32)
2288
					match = *(p + 1) & (1 << (x - 32));
2288
					match = *(p + 1) & (1 << (x - 32));
2289
				else
2289
				else
2290
					match = *p & (1 << x);
2290
					match = *p & (1 << x);
2291
			    }
2291
			    }
2292
				break;
2292
				break;
2293
2293
2294
			case O_TCPDATALEN:
2294
			case O_TCPDATALEN:
2295
				if (proto == IPPROTO_TCP && offset == 0) {
2295
				if (proto == IPPROTO_TCP && offset == 0) {
2296
				    struct tcphdr *tcp;
2296
				    struct tcphdr *tcp;
2297
				    uint16_t x;
2297
				    uint16_t x;
2298
				    uint16_t *p;
2298
				    uint16_t *p;
2299
				    int i;
2299
				    int i;
2300
#ifdef INET6
2300
#ifdef INET6
2301
				    if (is_ipv6) {
2301
				    if (is_ipv6) {
2302
					    struct ip6_hdr *ip6;
2302
					    struct ip6_hdr *ip6;
2303
2303
2304
					    ip6 = (struct ip6_hdr *)ip;
2304
					    ip6 = (struct ip6_hdr *)ip;
2305
					    if (ip6->ip6_plen == 0) {
2305
					    if (ip6->ip6_plen == 0) {
2306
						    /*
2306
						    /*
2307
						     * Jumbo payload is not
2307
						     * Jumbo payload is not
2308
						     * supported by this
2308
						     * supported by this
2309
						     * opcode.
2309
						     * opcode.
2310
						     */
2310
						     */
2311
						    break;
2311
						    break;
2312
					    }
2312
					    }
2313
					    x = iplen - hlen;
2313
					    x = iplen - hlen;
2314
				    } else
2314
				    } else
2315
#endif /* INET6 */
2315
#endif /* INET6 */
2316
					    x = iplen - (ip->ip_hl << 2);
2316
					    x = iplen - (ip->ip_hl << 2);
2317
				    tcp = TCP(ulp);
2317
				    tcp = TCP(ulp);
2318
				    x -= tcp->th_off << 2;
2318
				    x -= tcp->th_off << 2;
2319
				    if (cmdlen == 1) {
2319
				    if (cmdlen == 1) {
2320
					match = (cmd->arg1 == x);
2320
					match = (cmd->arg1 == x);
2321
					break;
2321
					break;
2322
				    }
2322
				    }
2323
				    /* otherwise we have ranges */
2323
				    /* otherwise we have ranges */
2324
				    p = ((ipfw_insn_u16 *)cmd)->ports;
2324
				    p = ((ipfw_insn_u16 *)cmd)->ports;
2325
				    i = cmdlen - 1;
2325
				    i = cmdlen - 1;
2326
				    for (; !match && i>0; i--, p += 2)
2326
				    for (; !match && i>0; i--, p += 2)
2327
					match = (x >= p[0] && x <= p[1]);
2327
					match = (x >= p[0] && x <= p[1]);
2328
				}
2328
				}
2329
				break;
2329
				break;
2330
2330
2331
			case O_TCPFLAGS:
2331
			case O_TCPFLAGS:
2332
				match = (proto == IPPROTO_TCP && offset == 0 &&
2332
				match = (proto == IPPROTO_TCP && offset == 0 &&
2333
				    flags_match(cmd, TCP(ulp)->th_flags));
2333
				    flags_match(cmd, TCP(ulp)->th_flags));
2334
				break;
2334
				break;
2335
2335
2336
			case O_TCPOPTS:
2336
			case O_TCPOPTS:
2337
				if (proto == IPPROTO_TCP && offset == 0 && ulp){
2337
				if (proto == IPPROTO_TCP && offset == 0 && ulp){
2338
					PULLUP_LEN_LOCKED(hlen, ulp,
2338
					PULLUP_LEN_LOCKED(hlen, ulp,
2339
					    (TCP(ulp)->th_off << 2));
2339
					    (TCP(ulp)->th_off << 2));
2340
					match = tcpopts_match(TCP(ulp), cmd);
2340
					match = tcpopts_match(TCP(ulp), cmd);
2341
				}
2341
				}
2342
				break;
2342
				break;
2343
2343
2344
			case O_TCPSEQ:
2344
			case O_TCPSEQ:
2345
				match = (proto == IPPROTO_TCP && offset == 0 &&
2345
				match = (proto == IPPROTO_TCP && offset == 0 &&
2346
				    ((ipfw_insn_u32 *)cmd)->d[0] ==
2346
				    ((ipfw_insn_u32 *)cmd)->d[0] ==
2347
					TCP(ulp)->th_seq);
2347
					TCP(ulp)->th_seq);
2348
				break;
2348
				break;
2349
2349
2350
			case O_TCPACK:
2350
			case O_TCPACK:
2351
				match = (proto == IPPROTO_TCP && offset == 0 &&
2351
				match = (proto == IPPROTO_TCP && offset == 0 &&
2352
				    ((ipfw_insn_u32 *)cmd)->d[0] ==
2352
				    ((ipfw_insn_u32 *)cmd)->d[0] ==
2353
					TCP(ulp)->th_ack);
2353
					TCP(ulp)->th_ack);
2354
				break;
2354
				break;
2355
2355
2356
			case O_TCPMSS:
2356
			case O_TCPMSS:
2357
				if (proto == IPPROTO_TCP &&
2357
				if (proto == IPPROTO_TCP &&
2358
				    (args->f_id._flags & TH_SYN) != 0 &&
2358
				    (args->f_id._flags & TH_SYN) != 0 &&
2359
				    ulp != NULL) {
2359
				    ulp != NULL) {
2360
					uint16_t mss, *p;
2360
					uint16_t mss, *p;
2361
					int i;
2361
					int i;
2362
2362
2363
					PULLUP_LEN_LOCKED(hlen, ulp,
2363
					PULLUP_LEN_LOCKED(hlen, ulp,
2364
					    (TCP(ulp)->th_off << 2));
2364
					    (TCP(ulp)->th_off << 2));
2365
					if ((tcpopts_parse(TCP(ulp), &mss) &
2365
					if ((tcpopts_parse(TCP(ulp), &mss) &
2366
					    IP_FW_TCPOPT_MSS) == 0)
2366
					    IP_FW_TCPOPT_MSS) == 0)
2367
						break;
2367
						break;
2368
					if (cmdlen == 1) {
2368
					if (cmdlen == 1) {
2369
						match = (cmd->arg1 == mss);
2369
						match = (cmd->arg1 == mss);
2370
						break;
2370
						break;
2371
					}
2371
					}
2372
					/* Otherwise we have ranges. */
2372
					/* Otherwise we have ranges. */
2373
					p = ((ipfw_insn_u16 *)cmd)->ports;
2373
					p = ((ipfw_insn_u16 *)cmd)->ports;
2374
					i = cmdlen - 1;
2374
					i = cmdlen - 1;
2375
					for (; !match && i > 0; i--, p += 2)
2375
					for (; !match && i > 0; i--, p += 2)
2376
						match = (mss >= p[0] &&
2376
						match = (mss >= p[0] &&
2377
						    mss <= p[1]);
2377
						    mss <= p[1]);
2378
				}
2378
				}
2379
				break;
2379
				break;
2380
2380
2381
			case O_TCPWIN:
2381
			case O_TCPWIN:
2382
				if (proto == IPPROTO_TCP && offset == 0) {
2382
				if (proto == IPPROTO_TCP && offset == 0) {
2383
				    uint16_t x;
2383
				    uint16_t x;
2384
				    uint16_t *p;
2384
				    uint16_t *p;
2385
				    int i;
2385
				    int i;
2386
2386
2387
				    x = ntohs(TCP(ulp)->th_win);
2387
				    x = ntohs(TCP(ulp)->th_win);
2388
				    if (cmdlen == 1) {
2388
				    if (cmdlen == 1) {
2389
					match = (cmd->arg1 == x);
2389
					match = (cmd->arg1 == x);
2390
					break;
2390
					break;
2391
				    }
2391
				    }
2392
				    /* Otherwise we have ranges. */
2392
				    /* Otherwise we have ranges. */
2393
				    p = ((ipfw_insn_u16 *)cmd)->ports;
2393
				    p = ((ipfw_insn_u16 *)cmd)->ports;
2394
				    i = cmdlen - 1;
2394
				    i = cmdlen - 1;
2395
				    for (; !match && i > 0; i--, p += 2)
2395
				    for (; !match && i > 0; i--, p += 2)
2396
					match = (x >= p[0] && x <= p[1]);
2396
					match = (x >= p[0] && x <= p[1]);
2397
				}
2397
				}
2398
				break;
2398
				break;
2399
2399
2400
			case O_ESTAB:
2400
			case O_ESTAB:
2401
				/* reject packets which have SYN only */
2401
				/* reject packets which have SYN only */
2402
				/* XXX should i also check for TH_ACK ? */
2402
				/* XXX should i also check for TH_ACK ? */
2403
				match = (proto == IPPROTO_TCP && offset == 0 &&
2403
				match = (proto == IPPROTO_TCP && offset == 0 &&
2404
				    (TCP(ulp)->th_flags &
2404
				    (TCP(ulp)->th_flags &
2405
				     (TH_RST | TH_ACK | TH_SYN)) != TH_SYN);
2405
				     (TH_RST | TH_ACK | TH_SYN)) != TH_SYN);
2406
				break;
2406
				break;
2407
2407
2408
			case O_ALTQ: {
2408
			case O_ALTQ: {
2409
				struct pf_mtag *at;
2409
				struct pf_mtag *at;
2410
				struct m_tag *mtag;
2410
				struct m_tag *mtag;
2411
				ipfw_insn_altq *altq = (ipfw_insn_altq *)cmd;
2411
				ipfw_insn_altq *altq = (ipfw_insn_altq *)cmd;
2412
2412
2413
				/*
2413
				/*
2414
				 * ALTQ uses mbuf tags from another
2414
				 * ALTQ uses mbuf tags from another
2415
				 * packet filtering system - pf(4).
2415
				 * packet filtering system - pf(4).
2416
				 * We allocate a tag in its format
2416
				 * We allocate a tag in its format
2417
				 * and fill it in, pretending to be pf(4).
2417
				 * and fill it in, pretending to be pf(4).
2418
				 */
2418
				 */
2419
				match = 1;
2419
				match = 1;
2420
				at = pf_find_mtag(m);
2420
				at = pf_find_mtag(m);
2421
				if (at != NULL && at->qid != 0)
2421
				if (at != NULL && at->qid != 0)
2422
					break;
2422
					break;
2423
				mtag = m_tag_get(PACKET_TAG_PF,
2423
				mtag = m_tag_get(PACKET_TAG_PF,
2424
				    sizeof(struct pf_mtag), M_NOWAIT | M_ZERO);
2424
				    sizeof(struct pf_mtag), M_NOWAIT | M_ZERO);
2425
				if (mtag == NULL) {
2425
				if (mtag == NULL) {
2426
					/*
2426
					/*
2427
					 * Let the packet fall back to the
2427
					 * Let the packet fall back to the
2428
					 * default ALTQ.
2428
					 * default ALTQ.
2429
					 */
2429
					 */
2430
					break;
2430
					break;
2431
				}
2431
				}
2432
				m_tag_prepend(m, mtag);
2432
				m_tag_prepend(m, mtag);
2433
				at = (struct pf_mtag *)(mtag + 1);
2433
				at = (struct pf_mtag *)(mtag + 1);
2434
				at->qid = altq->qid;
2434
				at->qid = altq->qid;
2435
				at->hdr = ip;
2435
				at->hdr = ip;
2436
				break;
2436
				break;
2437
			}
2437
			}
2438
2438
2439
			case O_LOG:
2439
			case O_LOG:
2440
				ipfw_log(chain, f, hlen, args,
2440
				ipfw_log(chain, f, hlen, args,
2441
				    offset | ip6f_mf, tablearg, ip);
2441
				    offset | ip6f_mf, tablearg, ip);
2442
				match = 1;
2442
				match = 1;
2443
				break;
2443
				break;
2444
2444
2445
			case O_PROB:
2445
			case O_PROB:
2446
				match = (random()<((ipfw_insn_u32 *)cmd)->d[0]);
2446
				match = (random()<((ipfw_insn_u32 *)cmd)->d[0]);
2447
				break;
2447
				break;
2448
2448
2449
			case O_VERREVPATH:
2449
			case O_VERREVPATH:
2450
				/* Outgoing packets automatically pass/match */
2450
				/* Outgoing packets automatically pass/match */
2451
				match = (args->flags & IPFW_ARGS_OUT ||
2451
				match = (args->flags & IPFW_ARGS_OUT ||
2452
				    (
2452
				    (
2453
#ifdef INET6
2453
#ifdef INET6
2454
				    is_ipv6 ?
2454
				    is_ipv6 ?
2455
					verify_path6(&(args->f_id.src_ip6),
2455
					verify_path6(&(args->f_id.src_ip6),
2456
					    iif, args->f_id.fib) :
2456
					    iif, args->f_id.fib) :
2457
#endif
2457
#endif
2458
				    verify_path(src_ip, iif, args->f_id.fib)));
2458
				    verify_path(src_ip, iif, args->f_id.fib)));
2459
				break;
2459
				break;
2460
2460
2461
			case O_VERSRCREACH:
2461
			case O_VERSRCREACH:
2462
				/* Outgoing packets automatically pass/match */
2462
				/* Outgoing packets automatically pass/match */
2463
				match = (hlen > 0 && ((oif != NULL) || (
2463
				match = (hlen > 0 && ((oif != NULL) || (
2464
#ifdef INET6
2464
#ifdef INET6
2465
				    is_ipv6 ?
2465
				    is_ipv6 ?
2466
				        verify_path6(&(args->f_id.src_ip6),
2466
				        verify_path6(&(args->f_id.src_ip6),
2467
				            NULL, args->f_id.fib) :
2467
				            NULL, args->f_id.fib) :
2468
#endif
2468
#endif
2469
				    verify_path(src_ip, NULL, args->f_id.fib))));
2469
				    verify_path(src_ip, NULL, args->f_id.fib))));
2470
				break;
2470
				break;
2471
2471
2472
			case O_ANTISPOOF:
2472
			case O_ANTISPOOF:
2473
				/* Outgoing packets automatically pass/match */
2473
				/* Outgoing packets automatically pass/match */
2474
				if (oif == NULL && hlen > 0 &&
2474
				if (oif == NULL && hlen > 0 &&
2475
				    (  (is_ipv4 && in_localaddr(src_ip))
2475
				    (  (is_ipv4 && in_localaddr(src_ip))
2476
#ifdef INET6
2476
#ifdef INET6
2477
				    || (is_ipv6 &&
2477
				    || (is_ipv6 &&
2478
				        in6_localaddr(&(args->f_id.src_ip6)))
2478
				        in6_localaddr(&(args->f_id.src_ip6)))
2479
#endif
2479
#endif
2480
				    ))
2480
				    ))
2481
					match =
2481
					match =
2482
#ifdef INET6
2482
#ifdef INET6
2483
					    is_ipv6 ? verify_path6(
2483
					    is_ipv6 ? verify_path6(
2484
					        &(args->f_id.src_ip6), iif,
2484
					        &(args->f_id.src_ip6), iif,
2485
						args->f_id.fib) :
2485
						args->f_id.fib) :
2486
#endif
2486
#endif
2487
					    verify_path(src_ip, iif,
2487
					    verify_path(src_ip, iif,
2488
					        args->f_id.fib);
2488
					        args->f_id.fib);
2489
				else
2489
				else
2490
					match = 1;
2490
					match = 1;
2491
				break;
2491
				break;
2492
2492
2493
			case O_IPSEC:
2493
			case O_IPSEC:
2494
				match = (m_tag_find(m,
2494
				match = (m_tag_find(m,
2495
				    PACKET_TAG_IPSEC_IN_DONE, NULL) != NULL);
2495
				    PACKET_TAG_IPSEC_IN_DONE, NULL) != NULL);
2496
				/* otherwise no match */
2496
				/* otherwise no match */
2497
				break;
2497
				break;
2498
2498
2499
#ifdef INET6
2499
#ifdef INET6
2500
			case O_IP6_SRC:
2500
			case O_IP6_SRC:
2501
				match = is_ipv6 &&
2501
				match = is_ipv6 &&
2502
				    IN6_ARE_ADDR_EQUAL(&args->f_id.src_ip6,
2502
				    IN6_ARE_ADDR_EQUAL(&args->f_id.src_ip6,
2503
				    &((ipfw_insn_ip6 *)cmd)->addr6);
2503
				    &((ipfw_insn_ip6 *)cmd)->addr6);
2504
				break;
2504
				break;
2505
2505
2506
			case O_IP6_DST:
2506
			case O_IP6_DST:
2507
				match = is_ipv6 &&
2507
				match = is_ipv6 &&
2508
				IN6_ARE_ADDR_EQUAL(&args->f_id.dst_ip6,
2508
				IN6_ARE_ADDR_EQUAL(&args->f_id.dst_ip6,
2509
				    &((ipfw_insn_ip6 *)cmd)->addr6);
2509
				    &((ipfw_insn_ip6 *)cmd)->addr6);
2510
				break;
2510
				break;
2511
			case O_IP6_SRC_MASK:
2511
			case O_IP6_SRC_MASK:
2512
			case O_IP6_DST_MASK:
2512
			case O_IP6_DST_MASK:
2513
				if (is_ipv6) {
2513
				if (is_ipv6) {
2514
					int i = cmdlen - 1;
2514
					int i = cmdlen - 1;
2515
					struct in6_addr p;
2515
					struct in6_addr p;
2516
					struct in6_addr *d =
2516
					struct in6_addr *d =
2517
					    &((ipfw_insn_ip6 *)cmd)->addr6;
2517
					    &((ipfw_insn_ip6 *)cmd)->addr6;
2518
2518
2519
					for (; !match && i > 0; d += 2,
2519
					for (; !match && i > 0; d += 2,
2520
					    i -= F_INSN_SIZE(struct in6_addr)
2520
					    i -= F_INSN_SIZE(struct in6_addr)
2521
					    * 2) {
2521
					    * 2) {
2522
						p = (cmd->opcode ==
2522
						p = (cmd->opcode ==
2523
						    O_IP6_SRC_MASK) ?
2523
						    O_IP6_SRC_MASK) ?
2524
						    args->f_id.src_ip6:
2524
						    args->f_id.src_ip6:
2525
						    args->f_id.dst_ip6;
2525
						    args->f_id.dst_ip6;
2526
						APPLY_MASK(&p, &d[1]);
2526
						APPLY_MASK(&p, &d[1]);
2527
						match =
2527
						match =
2528
						    IN6_ARE_ADDR_EQUAL(&d[0],
2528
						    IN6_ARE_ADDR_EQUAL(&d[0],
2529
						    &p);
2529
						    &p);
2530
					}
2530
					}
2531
				}
2531
				}
2532
				break;
2532
				break;
2533
2533
2534
			case O_FLOW6ID:
2534
			case O_FLOW6ID:
2535
				match = is_ipv6 &&
2535
				match = is_ipv6 &&
2536
				    flow6id_match(args->f_id.flow_id6,
2536
				    flow6id_match(args->f_id.flow_id6,
2537
				    (ipfw_insn_u32 *) cmd);
2537
				    (ipfw_insn_u32 *) cmd);
2538
				break;
2538
				break;
2539
2539
2540
			case O_EXT_HDR:
2540
			case O_EXT_HDR:
2541
				match = is_ipv6 &&
2541
				match = is_ipv6 &&
2542
				    (ext_hd & ((ipfw_insn *) cmd)->arg1);
2542
				    (ext_hd & ((ipfw_insn *) cmd)->arg1);
2543
				break;
2543
				break;
2544
2544
2545
			case O_IP6:
2545
			case O_IP6:
2546
				match = is_ipv6;
2546
				match = is_ipv6;
2547
				break;
2547
				break;
2548
#endif
2548
#endif
2549
2549
2550
			case O_IP4:
2550
			case O_IP4:
2551
				match = is_ipv4;
2551
				match = is_ipv4;
2552
				break;
2552
				break;
2553
2553
2554
			case O_TAG: {
2554
			case O_TAG: {
2555
				struct m_tag *mtag;
2555
				struct m_tag *mtag;
2556
				uint32_t tag = TARG(cmd->arg1, tag);
2556
				uint32_t tag = TARG(cmd->arg1, tag);
2557
2557
2558
				/* Packet is already tagged with this tag? */
2558
				/* Packet is already tagged with this tag? */
2559
				mtag = m_tag_locate(m, MTAG_IPFW, tag, NULL);
2559
				mtag = m_tag_locate(m, MTAG_IPFW, tag, NULL);
2560
2560
2561
				/* We have `untag' action when F_NOT flag is
2561
				/* We have `untag' action when F_NOT flag is
2562
				 * present. And we must remove this mtag from
2562
				 * present. And we must remove this mtag from
2563
				 * mbuf and reset `match' to zero (`match' will
2563
				 * mbuf and reset `match' to zero (`match' will
2564
				 * be inversed later).
2564
				 * be inversed later).
2565
				 * Otherwise we should allocate new mtag and
2565
				 * Otherwise we should allocate new mtag and
2566
				 * push it into mbuf.
2566
				 * push it into mbuf.
2567
				 */
2567
				 */
2568
				if (cmd->len & F_NOT) { /* `untag' action */
2568
				if (cmd->len & F_NOT) { /* `untag' action */
2569
					if (mtag != NULL)
2569
					if (mtag != NULL)
2570
						m_tag_delete(m, mtag);
2570
						m_tag_delete(m, mtag);
2571
					match = 0;
2571
					match = 0;
2572
				} else {
2572
				} else {
2573
					if (mtag == NULL) {
2573
					if (mtag == NULL) {
2574
						mtag = m_tag_alloc( MTAG_IPFW,
2574
						mtag = m_tag_alloc( MTAG_IPFW,
2575
						    tag, 0, M_NOWAIT);
2575
						    tag, 0, M_NOWAIT);
2576
						if (mtag != NULL)
2576
						if (mtag != NULL)
2577
							m_tag_prepend(m, mtag);
2577
							m_tag_prepend(m, mtag);
2578
					}
2578
					}
2579
					match = 1;
2579
					match = 1;
2580
				}
2580
				}
2581
				break;
2581
				break;
2582
			}
2582
			}
2583
2583
2584
			case O_FIB: /* try match the specified fib */
2584
			case O_FIB: /* try match the specified fib */
2585
				if (args->f_id.fib == cmd->arg1)
2585
				if (args->f_id.fib == cmd->arg1)
2586
					match = 1;
2586
					match = 1;
2587
				break;
2587
				break;
2588
2588
2589
			case O_SOCKARG:	{
2589
			case O_SOCKARG:	{
2590
#ifndef USERSPACE	/* not supported in userspace */
2590
#ifndef USERSPACE	/* not supported in userspace */
2591
				struct inpcb *inp = args->inp;
2591
				struct inpcb *inp = args->inp;
2592
				struct inpcbinfo *pi;
2592
				struct inpcbinfo *pi;
2593
				
2593
				
2594
				if (is_ipv6) /* XXX can we remove this ? */
2594
				if (is_ipv6) /* XXX can we remove this ? */
2595
					break;
2595
					break;
2596
2596
2597
				if (proto == IPPROTO_TCP)
2597
				if (proto == IPPROTO_TCP)
2598
					pi = &V_tcbinfo;
2598
					pi = &V_tcbinfo;
2599
				else if (proto == IPPROTO_UDP)
2599
				else if (proto == IPPROTO_UDP)
2600
					pi = &V_udbinfo;
2600
					pi = &V_udbinfo;
2601
				else if (proto == IPPROTO_UDPLITE)
2601
				else if (proto == IPPROTO_UDPLITE)
2602
					pi = &V_ulitecbinfo;
2602
					pi = &V_ulitecbinfo;
2603
				else
2603
				else
2604
					break;
2604
					break;
2605
2605
2606
				/*
2606
				/*
2607
				 * XXXRW: so_user_cookie should almost
2607
				 * XXXRW: so_user_cookie should almost
2608
				 * certainly be inp_user_cookie?
2608
				 * certainly be inp_user_cookie?
2609
				 */
2609
				 */
2610
2610
2611
				/* For incoming packet, lookup up the 
2611
				/* For incoming packet, lookup up the 
2612
				inpcb using the src/dest ip/port tuple */
2612
				inpcb using the src/dest ip/port tuple */
2613
				if (inp == NULL) {
2613
				if (inp == NULL) {
2614
					inp = in_pcblookup(pi, 
2614
					inp = in_pcblookup(pi, 
2615
						src_ip, htons(src_port),
2615
						src_ip, htons(src_port),
2616
						dst_ip, htons(dst_port),
2616
						dst_ip, htons(dst_port),
2617
						INPLOOKUP_RLOCKPCB, NULL);
2617
						INPLOOKUP_RLOCKPCB, NULL);
2618
					if (inp != NULL) {
2618
					if (inp != NULL) {
2619
						tablearg =
2619
						tablearg =
2620
						    inp->inp_socket->so_user_cookie;
2620
						    inp->inp_socket->so_user_cookie;
2621
						if (tablearg)
2621
						if (tablearg)
2622
							match = 1;
2622
							match = 1;
2623
						INP_RUNLOCK(inp);
2623
						INP_RUNLOCK(inp);
2624
					}
2624
					}
2625
				} else {
2625
				} else {
2626
					if (inp->inp_socket) {
2626
					if (inp->inp_socket) {
2627
						tablearg =
2627
						tablearg =
2628
						    inp->inp_socket->so_user_cookie;
2628
						    inp->inp_socket->so_user_cookie;
2629
						if (tablearg)
2629
						if (tablearg)
2630
							match = 1;
2630
							match = 1;
2631
					}
2631
					}
2632
				}
2632
				}
2633
#endif /* !USERSPACE */
2633
#endif /* !USERSPACE */
2634
				break;
2634
				break;
2635
			}
2635
			}
2636
2636
2637
			case O_TAGGED: {
2637
			case O_TAGGED: {
2638
				struct m_tag *mtag;
2638
				struct m_tag *mtag;
2639
				uint32_t tag = TARG(cmd->arg1, tag);
2639
				uint32_t tag = TARG(cmd->arg1, tag);
2640
2640
2641
				if (cmdlen == 1) {
2641
				if (cmdlen == 1) {
2642
					match = m_tag_locate(m, MTAG_IPFW,
2642
					match = m_tag_locate(m, MTAG_IPFW,
2643
					    tag, NULL) != NULL;
2643
					    tag, NULL) != NULL;
2644
					break;
2644
					break;
2645
				}
2645
				}
2646
2646
2647
				/* we have ranges */
2647
				/* we have ranges */
2648
				for (mtag = m_tag_first(m);
2648
				for (mtag = m_tag_first(m);
2649
				    mtag != NULL && !match;
2649
				    mtag != NULL && !match;
2650
				    mtag = m_tag_next(m, mtag)) {
2650
				    mtag = m_tag_next(m, mtag)) {
2651
					uint16_t *p;
2651
					uint16_t *p;
2652
					int i;
2652
					int i;
2653
2653
2654
					if (mtag->m_tag_cookie != MTAG_IPFW)
2654
					if (mtag->m_tag_cookie != MTAG_IPFW)
2655
						continue;
2655
						continue;
2656
2656
2657
					p = ((ipfw_insn_u16 *)cmd)->ports;
2657
					p = ((ipfw_insn_u16 *)cmd)->ports;
2658
					i = cmdlen - 1;
2658
					i = cmdlen - 1;
2659
					for(; !match && i > 0; i--, p += 2)
2659
					for(; !match && i > 0; i--, p += 2)
2660
						match =
2660
						match =
2661
						    mtag->m_tag_id >= p[0] &&
2661
						    mtag->m_tag_id >= p[0] &&
2662
						    mtag->m_tag_id <= p[1];
2662
						    mtag->m_tag_id <= p[1];
2663
				}
2663
				}
2664
				break;
2664
				break;
2665
			}
2665
			}
2666
				
2666
				
2667
			/*
2667
			/*
2668
			 * The second set of opcodes represents 'actions',
2668
			 * The second set of opcodes represents 'actions',
2669
			 * i.e. the terminal part of a rule once the packet
2669
			 * i.e. the terminal part of a rule once the packet
2670
			 * matches all previous patterns.
2670
			 * matches all previous patterns.
2671
			 * Typically there is only one action for each rule,
2671
			 * Typically there is only one action for each rule,
2672
			 * and the opcode is stored at the end of the rule
2672
			 * and the opcode is stored at the end of the rule
2673
			 * (but there are exceptions -- see below).
2673
			 * (but there are exceptions -- see below).
2674
			 *
2674
			 *
2675
			 * In general, here we set retval and terminate the
2675
			 * In general, here we set retval and terminate the
2676
			 * outer loop (would be a 'break 3' in some language,
2676
			 * outer loop (would be a 'break 3' in some language,
2677
			 * but we need to set l=0, done=1)
2677
			 * but we need to set l=0, done=1)
2678
			 *
2678
			 *
2679
			 * Exceptions:
2679
			 * Exceptions:
2680
			 * O_COUNT and O_SKIPTO actions:
2680
			 * O_COUNT and O_SKIPTO actions:
2681
			 *   instead of terminating, we jump to the next rule
2681
			 *   instead of terminating, we jump to the next rule
2682
			 *   (setting l=0), or to the SKIPTO target (setting
2682
			 *   (setting l=0), or to the SKIPTO target (setting
2683
			 *   f/f_len, cmd and l as needed), respectively.
2683
			 *   f/f_len, cmd and l as needed), respectively.
2684
			 *
2684
			 *
2685
			 * O_TAG, O_LOG and O_ALTQ action parameters:
2685
			 * O_TAG, O_LOG and O_ALTQ action parameters:
2686
			 *   perform some action and set match = 1;
2686
			 *   perform some action and set match = 1;
2687
			 *
2687
			 *
2688
			 * O_LIMIT and O_KEEP_STATE: these opcodes are
2688
			 * O_LIMIT and O_KEEP_STATE: these opcodes are
2689
			 *   not real 'actions', and are stored right
2689
			 *   not real 'actions', and are stored right
2690
			 *   before the 'action' part of the rule (one
2690
			 *   before the 'action' part of the rule (one
2691
			 *   exception is O_SKIP_ACTION which could be
2691
			 *   exception is O_SKIP_ACTION which could be
2692
			 *   between these opcodes and 'action' one).
2692
			 *   between these opcodes and 'action' one).
2693
			 *   These opcodes try to install an entry in the
2693
			 *   These opcodes try to install an entry in the
2694
			 *   state tables; if successful, we continue with
2694
			 *   state tables; if successful, we continue with
2695
			 *   the next opcode (match=1; break;), otherwise
2695
			 *   the next opcode (match=1; break;), otherwise
2696
			 *   the packet must be dropped (set retval,
2696
			 *   the packet must be dropped (set retval,
2697
			 *   break loops with l=0, done=1)
2697
			 *   break loops with l=0, done=1)
2698
			 *
2698
			 *
2699
			 * O_PROBE_STATE and O_CHECK_STATE: these opcodes
2699
			 * O_PROBE_STATE and O_CHECK_STATE: these opcodes
2700
			 *   cause a lookup of the state table, and a jump
2700
			 *   cause a lookup of the state table, and a jump
2701
			 *   to the 'action' part of the parent rule
2701
			 *   to the 'action' part of the parent rule
2702
			 *   if an entry is found, or
2702
			 *   if an entry is found, or
2703
			 *   (CHECK_STATE only) a jump to the next rule if
2703
			 *   (CHECK_STATE only) a jump to the next rule if
2704
			 *   the entry is not found.
2704
			 *   the entry is not found.
2705
			 *   The result of the lookup is cached so that
2705
			 *   The result of the lookup is cached so that
2706
			 *   further instances of these opcodes become NOPs.
2706
			 *   further instances of these opcodes become NOPs.
2707
			 *   The jump to the next rule is done by setting
2707
			 *   The jump to the next rule is done by setting
2708
			 *   l=0, cmdlen=0.
2708
			 *   l=0, cmdlen=0.
2709
			 *
2709
			 *
2710
			 * O_SKIP_ACTION: this opcode is not a real 'action'
2710
			 * O_SKIP_ACTION: this opcode is not a real 'action'
2711
			 *  either, and is stored right before the 'action'
2711
			 *  either, and is stored right before the 'action'
2712
			 *  part of the rule, right after the O_KEEP_STATE
2712
			 *  part of the rule, right after the O_KEEP_STATE
2713
			 *  opcode. It causes match failure so the real
2713
			 *  opcode. It causes match failure so the real
2714
			 *  'action' could be executed only if the rule
2714
			 *  'action' could be executed only if the rule
2715
			 *  is checked via dynamic rule from the state
2715
			 *  is checked via dynamic rule from the state
2716
			 *  table, as in such case execution starts
2716
			 *  table, as in such case execution starts
2717
			 *  from the true 'action' opcode directly.
2717
			 *  from the true 'action' opcode directly.
2718
			 *   
2718
			 *   
2719
			 */
2719
			 */
2720
			case O_LIMIT:
2720
			case O_LIMIT:
2721
			case O_KEEP_STATE:
2721
			case O_KEEP_STATE:
2722
				if (ipfw_dyn_install_state(chain, f,
2722
				if (ipfw_dyn_install_state(chain, f,
2723
				    (ipfw_insn_limit *)cmd, args, ulp,
2723
				    (ipfw_insn_limit *)cmd, args, ulp,
2724
				    pktlen, &dyn_info, tablearg)) {
2724
				    pktlen, &dyn_info, tablearg)) {
2725
					/* error or limit violation */
2725
					/* error or limit violation */
2726
					retval = IP_FW_DENY;
2726
					retval = IP_FW_DENY;
2727
					l = 0;	/* exit inner loop */
2727
					l = 0;	/* exit inner loop */
2728
					done = 1; /* exit outer loop */
2728
					done = 1; /* exit outer loop */
2729
				}
2729
				}
2730
				match = 1;
2730
				match = 1;
2731
				break;
2731
				break;
2732
2732
2733
			case O_PROBE_STATE:
2733
			case O_PROBE_STATE:
2734
			case O_CHECK_STATE:
2734
			case O_CHECK_STATE:
2735
				/*
2735
				/*
2736
				 * dynamic rules are checked at the first
2736
				 * dynamic rules are checked at the first
2737
				 * keep-state or check-state occurrence,
2737
				 * keep-state or check-state occurrence,
2738
				 * with the result being stored in dyn_info.
2738
				 * with the result being stored in dyn_info.
2739
				 * The compiler introduces a PROBE_STATE
2739
				 * The compiler introduces a PROBE_STATE
2740
				 * instruction for us when we have a
2740
				 * instruction for us when we have a
2741
				 * KEEP_STATE (because PROBE_STATE needs
2741
				 * KEEP_STATE (because PROBE_STATE needs
2742
				 * to be run first).
2742
				 * to be run first).
2743
				 */
2743
				 */
2744
				if (DYN_LOOKUP_NEEDED(&dyn_info, cmd) &&
2744
				if (DYN_LOOKUP_NEEDED(&dyn_info, cmd) &&
2745
				    (q = ipfw_dyn_lookup_state(args, ulp,
2745
				    (q = ipfw_dyn_lookup_state(args, ulp,
2746
				    pktlen, cmd, &dyn_info)) != NULL) {
2746
				    pktlen, cmd, &dyn_info)) != NULL) {
2747
					/*
2747
					/*
2748
					 * Found dynamic entry, jump to the
2748
					 * Found dynamic entry, jump to the
2749
					 * 'action' part of the parent rule
2749
					 * 'action' part of the parent rule
2750
					 * by setting f, cmd, l and clearing
2750
					 * by setting f, cmd, l and clearing
2751
					 * cmdlen.
2751
					 * cmdlen.
2752
					 */
2752
					 */
2753
					f = q;
2753
					f = q;
2754
					f_pos = dyn_info.f_pos;
2754
					f_pos = dyn_info.f_pos;
2755
					cmd = ACTION_PTR(f);
2755
					cmd = ACTION_PTR(f);
2756
					l = f->cmd_len - f->act_ofs;
2756
					l = f->cmd_len - f->act_ofs;
2757
					cmdlen = 0;
2757
					cmdlen = 0;
2758
					match = 1;
2758
					match = 1;
2759
					break;
2759
					break;
2760
				}
2760
				}
2761
				/*
2761
				/*
2762
				 * Dynamic entry not found. If CHECK_STATE,
2762
				 * Dynamic entry not found. If CHECK_STATE,
2763
				 * skip to next rule, if PROBE_STATE just
2763
				 * skip to next rule, if PROBE_STATE just
2764
				 * ignore and continue with next opcode.
2764
				 * ignore and continue with next opcode.
2765
				 */
2765
				 */
2766
				if (cmd->opcode == O_CHECK_STATE)
2766
				if (cmd->opcode == O_CHECK_STATE)
2767
					l = 0;	/* exit inner loop */
2767
					l = 0;	/* exit inner loop */
2768
				match = 1;
2768
				match = 1;
2769
				break;
2769
				break;
2770
2770
2771
			case O_SKIP_ACTION:
2771
			case O_SKIP_ACTION:
2772
				match = 0;	/* skip to the next rule */
2772
				match = 0;	/* skip to the next rule */
2773
				l = 0;		/* exit inner loop */
2773
				l = 0;		/* exit inner loop */
2774
				break;
2774
				break;
2775
2775
2776
			case O_ACCEPT:
2776
			case O_ACCEPT:
2777
				retval = 0;	/* accept */
2777
				retval = 0;	/* accept */
2778
				l = 0;		/* exit inner loop */
2778
				l = 0;		/* exit inner loop */
2779
				done = 1;	/* exit outer loop */
2779
				done = 1;	/* exit outer loop */
2780
				break;
2780
				break;
2781
2781
2782
			case O_PIPE:
2782
			case O_PIPE:
2783
			case O_QUEUE:
2783
			case O_QUEUE:
2784
				set_match(args, f_pos, chain);
2784
				set_match(args, f_pos, chain);
2785
				args->rule.info = TARG(cmd->arg1, pipe);
2785
				args->rule.info = TARG(cmd->arg1, pipe);
2786
				if (cmd->opcode == O_PIPE)
2786
				if (cmd->opcode == O_PIPE)
2787
					args->rule.info |= IPFW_IS_PIPE;
2787
					args->rule.info |= IPFW_IS_PIPE;
2788
				if (V_fw_one_pass)
2788
				if (V_fw_one_pass)
2789
					args->rule.info |= IPFW_ONEPASS;
2789
					args->rule.info |= IPFW_ONEPASS;
2790
				retval = IP_FW_DUMMYNET;
2790
				retval = IP_FW_DUMMYNET;
2791
				l = 0;          /* exit inner loop */
2791
				l = 0;          /* exit inner loop */
2792
				done = 1;       /* exit outer loop */
2792
				done = 1;       /* exit outer loop */
2793
				break;
2793
				break;
2794
2794
2795
			case O_DIVERT:
2795
			case O_DIVERT:
2796
			case O_TEE:
2796
			case O_TEE:
2797
				if (args->flags & IPFW_ARGS_ETHER)
2797
				if (args->flags & IPFW_ARGS_ETHER)
2798
					break;	/* not on layer 2 */
2798
					break;	/* not on layer 2 */
2799
				/* otherwise this is terminal */
2799
				/* otherwise this is terminal */
2800
				l = 0;		/* exit inner loop */
2800
				l = 0;		/* exit inner loop */
2801
				done = 1;	/* exit outer loop */
2801
				done = 1;	/* exit outer loop */
2802
				retval = (cmd->opcode == O_DIVERT) ?
2802
				retval = (cmd->opcode == O_DIVERT) ?
2803
					IP_FW_DIVERT : IP_FW_TEE;
2803
					IP_FW_DIVERT : IP_FW_TEE;
2804
				set_match(args, f_pos, chain);
2804
				set_match(args, f_pos, chain);
2805
				args->rule.info = TARG(cmd->arg1, divert);
2805
				args->rule.info = TARG(cmd->arg1, divert);
2806
				break;
2806
				break;
2807
2807
2808
			case O_COUNT:
2808
			case O_COUNT:
2809
				IPFW_INC_RULE_COUNTER(f, pktlen);
2809
				IPFW_INC_RULE_COUNTER(f, pktlen);
2810
				l = 0;		/* exit inner loop */
2810
				l = 0;		/* exit inner loop */
2811
				break;
2811
				break;
2812
2812
2813
			case O_SKIPTO:
2813
			case O_SKIPTO:
2814
			    IPFW_INC_RULE_COUNTER(f, pktlen);
2814
			    IPFW_INC_RULE_COUNTER(f, pktlen);
2815
			    f_pos = JUMP(chain, f, cmd->arg1, tablearg, 0);
2815
			    f_pos = JUMP(chain, f, cmd->arg1, tablearg, 0);
2816
			    /*
2816
			    /*
2817
			     * Skip disabled rules, and re-enter
2817
			     * Skip disabled rules, and re-enter
2818
			     * the inner loop with the correct
2818
			     * the inner loop with the correct
2819
			     * f_pos, f, l and cmd.
2819
			     * f_pos, f, l and cmd.
2820
			     * Also clear cmdlen and skip_or
2820
			     * Also clear cmdlen and skip_or
2821
			     */
2821
			     */
2822
			    for (; f_pos < chain->n_rules - 1 &&
2822
			    for (; f_pos < chain->n_rules - 1 &&
2823
				    (V_set_disable &
2823
				    (V_set_disable &
2824
				     (1 << chain->map[f_pos]->set));
2824
				     (1 << chain->map[f_pos]->set));
2825
				    f_pos++)
2825
				    f_pos++)
2826
				;
2826
				;
2827
			    /* Re-enter the inner loop at the skipto rule. */
2827
			    /* Re-enter the inner loop at the skipto rule. */
2828
			    f = chain->map[f_pos];
2828
			    f = chain->map[f_pos];
2829
			    l = f->cmd_len;
2829
			    l = f->cmd_len;
2830
			    cmd = f->cmd;
2830
			    cmd = f->cmd;
2831
			    match = 1;
2831
			    match = 1;
2832
			    cmdlen = 0;
2832
			    cmdlen = 0;
2833
			    skip_or = 0;
2833
			    skip_or = 0;
2834
			    continue;
2834
			    continue;
2835
			    break;	/* not reached */
2835
			    break;	/* not reached */
2836
2836
2837
			case O_CALLRETURN: {
2837
			case O_CALLRETURN: {
2838
				/*
2838
				/*
2839
				 * Implementation of `subroutine' call/return,
2839
				 * Implementation of `subroutine' call/return,
2840
				 * in the stack carried in an mbuf tag. This
2840
				 * in the stack carried in an mbuf tag. This
2841
				 * is different from `skipto' in that any call
2841
				 * is different from `skipto' in that any call
2842
				 * address is possible (`skipto' must prevent
2842
				 * address is possible (`skipto' must prevent
2843
				 * backward jumps to avoid endless loops).
2843
				 * backward jumps to avoid endless loops).
2844
				 * We have `return' action when F_NOT flag is
2844
				 * We have `return' action when F_NOT flag is
2845
				 * present. The `m_tag_id' field is used as
2845
				 * present. The `m_tag_id' field is used as
2846
				 * stack pointer.
2846
				 * stack pointer.
2847
				 */
2847
				 */
2848
				struct m_tag *mtag;
2848
				struct m_tag *mtag;
2849
				uint16_t jmpto, *stack;
2849
				uint16_t jmpto, *stack;
2850
2850
2851
#define	IS_CALL		((cmd->len & F_NOT) == 0)
2851
#define	IS_CALL		((cmd->len & F_NOT) == 0)
2852
#define	IS_RETURN	((cmd->len & F_NOT) != 0)
2852
#define	IS_RETURN	((cmd->len & F_NOT) != 0)
2853
				/*
2853
				/*
2854
				 * Hand-rolled version of m_tag_locate() with
2854
				 * Hand-rolled version of m_tag_locate() with
2855
				 * wildcard `type'.
2855
				 * wildcard `type'.
2856
				 * If not already tagged, allocate new tag.
2856
				 * If not already tagged, allocate new tag.
2857
				 */
2857
				 */
2858
				mtag = m_tag_first(m);
2858
				mtag = m_tag_first(m);
2859
				while (mtag != NULL) {
2859
				while (mtag != NULL) {
2860
					if (mtag->m_tag_cookie ==
2860
					if (mtag->m_tag_cookie ==
2861
					    MTAG_IPFW_CALL)
2861
					    MTAG_IPFW_CALL)
2862
						break;
2862
						break;
2863
					mtag = m_tag_next(m, mtag);
2863
					mtag = m_tag_next(m, mtag);
2864
				}
2864
				}
2865
				if (mtag == NULL && IS_CALL) {
2865
				if (mtag == NULL && IS_CALL) {
2866
					mtag = m_tag_alloc(MTAG_IPFW_CALL, 0,
2866
					mtag = m_tag_alloc(MTAG_IPFW_CALL, 0,
2867
					    IPFW_CALLSTACK_SIZE *
2867
					    IPFW_CALLSTACK_SIZE *
2868
					    sizeof(uint16_t), M_NOWAIT);
2868
					    sizeof(uint16_t), M_NOWAIT);
2869
					if (mtag != NULL)
2869
					if (mtag != NULL)
2870
						m_tag_prepend(m, mtag);
2870
						m_tag_prepend(m, mtag);
2871
				}
2871
				}
2872
2872
2873
				/*
2873
				/*
2874
				 * On error both `call' and `return' just
2874
				 * On error both `call' and `return' just
2875
				 * continue with next rule.
2875
				 * continue with next rule.
2876
				 */
2876
				 */
2877
				if (IS_RETURN && (mtag == NULL ||
2877
				if (IS_RETURN && (mtag == NULL ||
2878
				    mtag->m_tag_id == 0)) {
2878
				    mtag->m_tag_id == 0)) {
2879
					l = 0;		/* exit inner loop */
2879
					l = 0;		/* exit inner loop */
2880
					break;
2880
					break;
2881
				}
2881
				}
2882
				if (IS_CALL && (mtag == NULL ||
2882
				if (IS_CALL && (mtag == NULL ||
2883
				    mtag->m_tag_id >= IPFW_CALLSTACK_SIZE)) {
2883
				    mtag->m_tag_id >= IPFW_CALLSTACK_SIZE)) {
2884
					printf("ipfw: call stack error, "
2884
					printf("ipfw: call stack error, "
2885
					    "go to next rule\n");
2885
					    "go to next rule\n");
2886
					l = 0;		/* exit inner loop */
2886
					l = 0;		/* exit inner loop */
2887
					break;
2887
					break;
2888
				}
2888
				}
2889
2889
2890
				IPFW_INC_RULE_COUNTER(f, pktlen);
2890
				IPFW_INC_RULE_COUNTER(f, pktlen);
2891
				stack = (uint16_t *)(mtag + 1);
2891
				stack = (uint16_t *)(mtag + 1);
2892
2892
2893
				/*
2893
				/*
2894
				 * The `call' action may use cached f_pos
2894
				 * The `call' action may use cached f_pos
2895
				 * (in f->next_rule), whose version is written
2895
				 * (in f->next_rule), whose version is written
2896
				 * in f->next_rule.
2896
				 * in f->next_rule.
2897
				 * The `return' action, however, doesn't have
2897
				 * The `return' action, however, doesn't have
2898
				 * fixed jump address in cmd->arg1 and can't use
2898
				 * fixed jump address in cmd->arg1 and can't use
2899
				 * cache.
2899
				 * cache.
2900
				 */
2900
				 */
2901
				if (IS_CALL) {
2901
				if (IS_CALL) {
2902
					stack[mtag->m_tag_id] = f->rulenum;
2902
					stack[mtag->m_tag_id] = f->rulenum;
2903
					mtag->m_tag_id++;
2903
					mtag->m_tag_id++;
2904
			    		f_pos = JUMP(chain, f, cmd->arg1,
2904
			    		f_pos = JUMP(chain, f, cmd->arg1,
2905
					    tablearg, 1);
2905
					    tablearg, 1);
2906
				} else {	/* `return' action */
2906
				} else {	/* `return' action */
2907
					mtag->m_tag_id--;
2907
					mtag->m_tag_id--;
2908
					jmpto = stack[mtag->m_tag_id] + 1;
2908
					jmpto = stack[mtag->m_tag_id] + 1;
2909
					f_pos = ipfw_find_rule(chain, jmpto, 0);
2909
					f_pos = ipfw_find_rule(chain, jmpto, 0);
2910
				}
2910
				}
2911
2911
2912
				/*
2912
				/*
2913
				 * Skip disabled rules, and re-enter
2913
				 * Skip disabled rules, and re-enter
2914
				 * the inner loop with the correct
2914
				 * the inner loop with the correct
2915
				 * f_pos, f, l and cmd.
2915
				 * f_pos, f, l and cmd.
2916
				 * Also clear cmdlen and skip_or
2916
				 * Also clear cmdlen and skip_or
2917
				 */
2917
				 */
2918
				for (; f_pos < chain->n_rules - 1 &&
2918
				for (; f_pos < chain->n_rules - 1 &&
2919
				    (V_set_disable &
2919
				    (V_set_disable &
2920
				    (1 << chain->map[f_pos]->set)); f_pos++)
2920
				    (1 << chain->map[f_pos]->set)); f_pos++)
2921
					;
2921
					;
2922
				/* Re-enter the inner loop at the dest rule. */
2922
				/* Re-enter the inner loop at the dest rule. */
2923
				f = chain->map[f_pos];
2923
				f = chain->map[f_pos];
2924
				l = f->cmd_len;
2924
				l = f->cmd_len;
2925
				cmd = f->cmd;
2925
				cmd = f->cmd;
2926
				cmdlen = 0;
2926
				cmdlen = 0;
2927
				skip_or = 0;
2927
				skip_or = 0;
2928
				continue;
2928
				continue;
2929
				break;	/* NOTREACHED */
2929
				break;	/* NOTREACHED */
2930
			}
2930
			}
2931
#undef IS_CALL
2931
#undef IS_CALL
2932
#undef IS_RETURN
2932
#undef IS_RETURN
2933
2933
2934
			case O_REJECT:
2934
			case O_REJECT:
2935
				/*
2935
				/*
2936
				 * Drop the packet and send a reject notice
2936
				 * Drop the packet and send a reject notice
2937
				 * if the packet is not ICMP (or is an ICMP
2937
				 * if the packet is not ICMP (or is an ICMP
2938
				 * query), and it is not multicast/broadcast.
2938
				 * query), and it is not multicast/broadcast.
2939
				 */
2939
				 */
2940
				if (hlen > 0 && is_ipv4 && offset == 0 &&
2940
				if (hlen > 0 && is_ipv4 && offset == 0 &&
2941
				    (proto != IPPROTO_ICMP ||
2941
				    (proto != IPPROTO_ICMP ||
2942
				     is_icmp_query(ICMP(ulp))) &&
2942
				     is_icmp_query(ICMP(ulp))) &&
2943
				    !(m->m_flags & (M_BCAST|M_MCAST)) &&
2943
				    !(m->m_flags & (M_BCAST|M_MCAST)) &&
2944
				    !IN_MULTICAST(ntohl(dst_ip.s_addr))) {
2944
				    !IN_MULTICAST(ntohl(dst_ip.s_addr))) {
2945
					send_reject(args, cmd->arg1, iplen, ip);
2945
					send_reject(args, cmd->arg1, iplen, ip);
2946
					m = args->m;
2946
					m = args->m;
2947
				}
2947
				}
2948
				/* FALLTHROUGH */
2948
				/* FALLTHROUGH */
2949
#ifdef INET6
2949
#ifdef INET6
2950
			case O_UNREACH6:
2950
			case O_UNREACH6:
2951
				if (hlen > 0 && is_ipv6 &&
2951
				if (hlen > 0 && is_ipv6 &&
2952
				    ((offset & IP6F_OFF_MASK) == 0) &&
2952
				    ((offset & IP6F_OFF_MASK) == 0) &&
2953
				    (proto != IPPROTO_ICMPV6 ||
2953
				    (proto != IPPROTO_ICMPV6 ||
2954
				     (is_icmp6_query(icmp6_type) == 1)) &&
2954
				     (is_icmp6_query(icmp6_type) == 1)) &&
2955
				    !(m->m_flags & (M_BCAST|M_MCAST)) &&
2955
				    !(m->m_flags & (M_BCAST|M_MCAST)) &&
2956
				    !IN6_IS_ADDR_MULTICAST(
2956
				    !IN6_IS_ADDR_MULTICAST(
2957
					&args->f_id.dst_ip6)) {
2957
					&args->f_id.dst_ip6)) {
2958
					send_reject6(args,
2958
					send_reject6(args,
2959
					    cmd->opcode == O_REJECT ?
2959
					    cmd->opcode == O_REJECT ?
2960
					    map_icmp_unreach(cmd->arg1):
2960
					    map_icmp_unreach(cmd->arg1):
2961
					    cmd->arg1, hlen,
2961
					    cmd->arg1, hlen,
2962
					    (struct ip6_hdr *)ip);
2962
					    (struct ip6_hdr *)ip);
2963
					m = args->m;
2963
					m = args->m;
2964
				}
2964
				}
2965
				/* FALLTHROUGH */
2965
				/* FALLTHROUGH */
2966
#endif
2966
#endif
2967
			case O_DENY:
2967
			case O_DENY:
2968
				retval = IP_FW_DENY;
2968
				retval = IP_FW_DENY;
2969
				l = 0;		/* exit inner loop */
2969
				l = 0;		/* exit inner loop */
2970
				done = 1;	/* exit outer loop */
2970
				done = 1;	/* exit outer loop */
2971
				break;
2971
				break;
2972
2972
2973
			case O_FORWARD_IP:
2973
			case O_FORWARD_IP:
2974
				if (args->flags & IPFW_ARGS_ETHER)
2974
				if (args->flags & IPFW_ARGS_ETHER)
2975
					break;	/* not valid on layer2 pkts */
2975
					break;	/* not valid on layer2 pkts */
2976
				if (q != f ||
2976
				if (q != f ||
2977
				    dyn_info.direction == MATCH_FORWARD) {
2977
				    dyn_info.direction == MATCH_FORWARD) {
2978
				    struct sockaddr_in *sa;
2978
				    struct sockaddr_in *sa;
2979
2979
2980
				    sa = &(((ipfw_insn_sa *)cmd)->sa);
2980
				    sa = &(((ipfw_insn_sa *)cmd)->sa);
2981
				    if (sa->sin_addr.s_addr == INADDR_ANY) {
2981
				    if (sa->sin_addr.s_addr == INADDR_ANY) {
2982
#ifdef INET6
2982
#ifdef INET6
2983
					/*
2983
					/*
2984
					 * We use O_FORWARD_IP opcode for
2984
					 * We use O_FORWARD_IP opcode for
2985
					 * fwd rule with tablearg, but tables
2985
					 * fwd rule with tablearg, but tables
2986
					 * now support IPv6 addresses. And
2986
					 * now support IPv6 addresses. And
2987
					 * when we are inspecting IPv6 packet,
2987
					 * when we are inspecting IPv6 packet,
2988
					 * we can use nh6 field from
2988
					 * we can use nh6 field from
2989
					 * table_value as next_hop6 address.
2989
					 * table_value as next_hop6 address.
2990
					 */
2990
					 */
2991
					if (is_ipv6) {
2991
					if (is_ipv6) {
2992
						struct ip_fw_nh6 *nh6;
2992
						struct ip_fw_nh6 *nh6;
2993
2993
2994
						args->flags |= IPFW_ARGS_NH6;
2994
						args->flags |= IPFW_ARGS_NH6;
2995
						nh6 = &args->hopstore6;
2995
						nh6 = &args->hopstore6;
2996
						nh6->sin6_addr = TARG_VAL(
2996
						nh6->sin6_addr = TARG_VAL(
2997
						    chain, tablearg, nh6);
2997
						    chain, tablearg, nh6);
2998
						nh6->sin6_port = sa->sin_port;
2998
						nh6->sin6_port = sa->sin_port;
2999
						nh6->sin6_scope_id = TARG_VAL(
2999
						nh6->sin6_scope_id = TARG_VAL(
3000
						    chain, tablearg, zoneid);
3000
						    chain, tablearg, zoneid);
3001
					} else
3001
					} else
3002
#endif
3002
#endif
3003
					{
3003
					{
3004
						args->flags |= IPFW_ARGS_NH4;
3004
						args->flags |= IPFW_ARGS_NH4;
3005
						args->hopstore.sin_port =
3005
						args->hopstore.sin_port =
3006
						    sa->sin_port;
3006
						    sa->sin_port;
3007
						sa = &args->hopstore;
3007
						sa = &args->hopstore;
3008
						sa->sin_family = AF_INET;
3008
						sa->sin_family = AF_INET;
3009
						sa->sin_len = sizeof(*sa);
3009
						sa->sin_len = sizeof(*sa);
3010
						sa->sin_addr.s_addr = htonl(
3010
						sa->sin_addr.s_addr = htonl(
3011
						    TARG_VAL(chain, tablearg,
3011
						    TARG_VAL(chain, tablearg,
3012
						    nh4));
3012
						    nh4));
3013
					}
3013
					}
3014
				    } else {
3014
				    } else {
3015
					    args->flags |= IPFW_ARGS_NH4PTR;
3015
					    args->flags |= IPFW_ARGS_NH4PTR;
3016
					    args->next_hop = sa;
3016
					    args->next_hop = sa;
3017
				    }
3017
				    }
3018
				}
3018
				}
3019
				retval = IP_FW_PASS;
3019
				retval = IP_FW_PASS;
3020
				l = 0;          /* exit inner loop */
3020
				l = 0;          /* exit inner loop */
3021
				done = 1;       /* exit outer loop */
3021
				done = 1;       /* exit outer loop */
3022
				break;
3022
				break;
3023
3023
3024
#ifdef INET6
3024
#ifdef INET6
3025
			case O_FORWARD_IP6:
3025
			case O_FORWARD_IP6:
3026
				if (args->flags & IPFW_ARGS_ETHER)
3026
				if (args->flags & IPFW_ARGS_ETHER)
3027
					break;	/* not valid on layer2 pkts */
3027
					break;	/* not valid on layer2 pkts */
3028
				if (q != f ||
3028
				if (q != f ||
3029
				    dyn_info.direction == MATCH_FORWARD) {
3029
				    dyn_info.direction == MATCH_FORWARD) {
3030
					struct sockaddr_in6 *sin6;
3030
					struct sockaddr_in6 *sin6;
3031
3031
3032
					sin6 = &(((ipfw_insn_sa6 *)cmd)->sa);
3032
					sin6 = &(((ipfw_insn_sa6 *)cmd)->sa);
3033
					args->flags |= IPFW_ARGS_NH6PTR;
3033
					args->flags |= IPFW_ARGS_NH6PTR;
3034
					args->next_hop6 = sin6;
3034
					args->next_hop6 = sin6;
3035
				}
3035
				}
3036
				retval = IP_FW_PASS;
3036
				retval = IP_FW_PASS;
3037
				l = 0;		/* exit inner loop */
3037
				l = 0;		/* exit inner loop */
3038
				done = 1;	/* exit outer loop */
3038
				done = 1;	/* exit outer loop */
3039
				break;
3039
				break;
3040
#endif
3040
#endif
3041
3041
3042
			case O_NETGRAPH:
3042
			case O_NETGRAPH:
3043
			case O_NGTEE:
3043
			case O_NGTEE:
3044
				set_match(args, f_pos, chain);
3044
				set_match(args, f_pos, chain);
3045
				args->rule.info = TARG(cmd->arg1, netgraph);
3045
				args->rule.info = TARG(cmd->arg1, netgraph);
3046
				if (V_fw_one_pass)
3046
				if (V_fw_one_pass)
3047
					args->rule.info |= IPFW_ONEPASS;
3047
					args->rule.info |= IPFW_ONEPASS;
3048
				retval = (cmd->opcode == O_NETGRAPH) ?
3048
				retval = (cmd->opcode == O_NETGRAPH) ?
3049
				    IP_FW_NETGRAPH : IP_FW_NGTEE;
3049
				    IP_FW_NETGRAPH : IP_FW_NGTEE;
3050
				l = 0;          /* exit inner loop */
3050
				l = 0;          /* exit inner loop */
3051
				done = 1;       /* exit outer loop */
3051
				done = 1;       /* exit outer loop */
3052
				break;
3052
				break;
3053
3053
3054
			case O_SETFIB: {
3054
			case O_SETFIB: {
3055
				uint32_t fib;
3055
				uint32_t fib;
3056
3056
3057
				IPFW_INC_RULE_COUNTER(f, pktlen);
3057
				IPFW_INC_RULE_COUNTER(f, pktlen);
3058
				fib = TARG(cmd->arg1, fib) & 0x7FFF;
3058
				fib = TARG(cmd->arg1, fib) & 0x7FFF;
3059
				if (fib >= rt_numfibs)
3059
				if (fib >= rt_numfibs)
3060
					fib = 0;
3060
					fib = 0;
3061
				M_SETFIB(m, fib);
3061
				M_SETFIB(m, fib);
3062
				args->f_id.fib = fib; /* XXX */
3062
				args->f_id.fib = fib; /* XXX */
3063
				l = 0;		/* exit inner loop */
3063
				l = 0;		/* exit inner loop */
3064
				break;
3064
				break;
3065
		        }
3065
		        }
3066
3066
3067
			case O_SETDSCP: {
3067
			case O_SETDSCP: {
3068
				uint16_t code;
3068
				uint16_t code;
3069
3069
3070
				code = TARG(cmd->arg1, dscp) & 0x3F;
3070
				code = TARG(cmd->arg1, dscp) & 0x3F;
3071
				l = 0;		/* exit inner loop */
3071
				l = 0;		/* exit inner loop */
3072
				if (is_ipv4) {
3072
				if (is_ipv4) {
3073
					uint16_t old;
3073
					uint16_t old;
3074
3074
3075
					old = *(uint16_t *)ip;
3075
					old = *(uint16_t *)ip;
3076
					ip->ip_tos = (code << 2) |
3076
					ip->ip_tos = (code << 2) |
3077
					    (ip->ip_tos & 0x03);
3077
					    (ip->ip_tos & 0x03);
3078
					ip->ip_sum = cksum_adjust(ip->ip_sum,
3078
					ip->ip_sum = cksum_adjust(ip->ip_sum,
3079
					    old, *(uint16_t *)ip);
3079
					    old, *(uint16_t *)ip);
3080
				} else if (is_ipv6) {
3080
				} else if (is_ipv6) {
3081
					uint8_t *v;
3081
					uint8_t *v;
3082
3082
3083
					v = &((struct ip6_hdr *)ip)->ip6_vfc;
3083
					v = &((struct ip6_hdr *)ip)->ip6_vfc;
3084
					*v = (*v & 0xF0) | (code >> 2);
3084
					*v = (*v & 0xF0) | (code >> 2);
3085
					v++;
3085
					v++;
3086
					*v = (*v & 0x3F) | ((code & 0x03) << 6);
3086
					*v = (*v & 0x3F) | ((code & 0x03) << 6);
3087
				} else
3087
				} else
3088
					break;
3088
					break;
3089
3089
3090
				IPFW_INC_RULE_COUNTER(f, pktlen);
3090
				IPFW_INC_RULE_COUNTER(f, pktlen);
3091
				break;
3091
				break;
3092
			}
3092
			}
3093
3093
3094
			case O_NAT:
3094
			case O_NAT:
3095
				l = 0;          /* exit inner loop */
3095
				l = 0;          /* exit inner loop */
3096
				done = 1;       /* exit outer loop */
3096
				done = 1;       /* exit outer loop */
3097
				/*
3097
				/*
3098
				 * Ensure that we do not invoke NAT handler for
3098
				 * Ensure that we do not invoke NAT handler for
3099
				 * non IPv4 packets. Libalias expects only IPv4.
3099
				 * non IPv4 packets. Libalias expects only IPv4.
3100
				 */
3100
				 */
3101
				if (!is_ipv4 || !IPFW_NAT_LOADED) {
3101
				if (!is_ipv4 || !IPFW_NAT_LOADED) {
3102
				    retval = IP_FW_DENY;
3102
				    retval = IP_FW_DENY;
3103
				    break;
3103
				    break;
3104
				}
3104
				}
3105
3105
3106
				struct cfg_nat *t;
3106
				struct cfg_nat *t;
3107
				int nat_id;
3107
				int nat_id;
3108
3108
3109
				args->rule.info = 0;
3109
				args->rule.info = 0;
3110
				set_match(args, f_pos, chain);
3110
				set_match(args, f_pos, chain);
3111
				/* Check if this is 'global' nat rule */
3111
				/* Check if this is 'global' nat rule */
3112
				if (cmd->arg1 == IP_FW_NAT44_GLOBAL) {
3112
				if (cmd->arg1 == IP_FW_NAT44_GLOBAL) {
3113
					retval = ipfw_nat_ptr(args, NULL, m);
3113
					retval = ipfw_nat_ptr(args, NULL, m);
3114
					break;
3114
					break;
3115
				}
3115
				}
3116
				t = ((ipfw_insn_nat *)cmd)->nat;
3116
				t = ((ipfw_insn_nat *)cmd)->nat;
3117
				if (t == NULL) {
3117
				if (t == NULL) {
3118
					nat_id = TARG(cmd->arg1, nat);
3118
					nat_id = TARG(cmd->arg1, nat);
3119
					t = (*lookup_nat_ptr)(&chain->nat, nat_id);
3119
					t = (*lookup_nat_ptr)(&chain->nat, nat_id);
3120
3120
3121
					if (t == NULL) {
3121
					if (t == NULL) {
3122
					    retval = IP_FW_DENY;
3122
					    retval = IP_FW_DENY;
3123
					    break;
3123
					    break;
3124
					}
3124
					}
3125
					if (cmd->arg1 != IP_FW_TARG)
3125
					if (cmd->arg1 != IP_FW_TARG)
3126
					    ((ipfw_insn_nat *)cmd)->nat = t;
3126
					    ((ipfw_insn_nat *)cmd)->nat = t;
3127
				}
3127
				}
3128
				retval = ipfw_nat_ptr(args, t, m);
3128
				retval = ipfw_nat_ptr(args, t, m);
3129
				break;
3129
				break;
3130
3130
3131
			case O_REASS: {
3131
			case O_REASS: {
3132
				int ip_off;
3132
				int ip_off;
3133
3133
3134
				l = 0;	/* in any case exit inner loop */
3134
				l = 0;	/* in any case exit inner loop */
3135
				if (is_ipv6) /* IPv6 is not supported yet */
3135
				if (is_ipv6) /* IPv6 is not supported yet */
3136
					break;
3136
					break;
3137
				IPFW_INC_RULE_COUNTER(f, pktlen);
3137
				IPFW_INC_RULE_COUNTER(f, pktlen);
3138
				ip_off = ntohs(ip->ip_off);
3138
				ip_off = ntohs(ip->ip_off);
3139
3139
3140
				/* if not fragmented, go to next rule */
3140
				/* if not fragmented, go to next rule */
3141
				if ((ip_off & (IP_MF | IP_OFFMASK)) == 0)
3141
				if ((ip_off & (IP_MF | IP_OFFMASK)) == 0)
3142
				    break;
3142
				    break;
3143
3143
3144
				args->m = m = ip_reass(m);
3144
				args->m = m = ip_reass(m);
3145
3145
3146
				/*
3146
				/*
3147
				 * do IP header checksum fixup.
3147
				 * do IP header checksum fixup.
3148
				 */
3148
				 */
3149
				if (m == NULL) { /* fragment got swallowed */
3149
				if (m == NULL) { /* fragment got swallowed */
3150
				    retval = IP_FW_DENY;
3150
				    retval = IP_FW_DENY;
3151
				} else { /* good, packet complete */
3151
				} else { /* good, packet complete */
3152
				    int hlen;
3152
				    int hlen;
3153
3153
3154
				    ip = mtod(m, struct ip *);
3154
				    ip = mtod(m, struct ip *);
3155
				    hlen = ip->ip_hl << 2;
3155
				    hlen = ip->ip_hl << 2;
3156
				    ip->ip_sum = 0;
3156
				    ip->ip_sum = 0;
3157
				    if (hlen == sizeof(struct ip))
3157
				    if (hlen == sizeof(struct ip))
3158
					ip->ip_sum = in_cksum_hdr(ip);
3158
					ip->ip_sum = in_cksum_hdr(ip);
3159
				    else
3159
				    else
3160
					ip->ip_sum = in_cksum(m, hlen);
3160
					ip->ip_sum = in_cksum(m, hlen);
3161
				    retval = IP_FW_REASS;
3161
				    retval = IP_FW_REASS;
3162
				    args->rule.info = 0;
3162
				    args->rule.info = 0;
3163
				    set_match(args, f_pos, chain);
3163
				    set_match(args, f_pos, chain);
3164
				}
3164
				}
3165
				done = 1;	/* exit outer loop */
3165
				done = 1;	/* exit outer loop */
3166
				break;
3166
				break;
3167
			}
3167
			}
3168
			case O_EXTERNAL_ACTION:
3168
			case O_EXTERNAL_ACTION:
3169
				l = 0; /* in any case exit inner loop */
3169
				l = 0; /* in any case exit inner loop */
3170
				retval = ipfw_run_eaction(chain, args,
3170
				retval = ipfw_run_eaction(chain, args,
3171
				    cmd, &done);
3171
				    cmd, &done);
3172
				/*
3172
				/*
3173
				 * If both @retval and @done are zero,
3173
				 * If both @retval and @done are zero,
3174
				 * consider this as rule matching and
3174
				 * consider this as rule matching and
3175
				 * update counters.
3175
				 * update counters.
3176
				 */
3176
				 */
3177
				if (retval == 0 && done == 0) {
3177
				if (retval == 0 && done == 0) {
3178
					IPFW_INC_RULE_COUNTER(f, pktlen);
3178
					IPFW_INC_RULE_COUNTER(f, pktlen);
3179
					/*
3179
					/*
3180
					 * Reset the result of the last
3180
					 * Reset the result of the last
3181
					 * dynamic state lookup.
3181
					 * dynamic state lookup.
3182
					 * External action can change
3182
					 * External action can change
3183
					 * @args content, and it may be
3183
					 * @args content, and it may be
3184
					 * used for new state lookup later.
3184
					 * used for new state lookup later.
3185
					 */
3185
					 */
3186
					DYN_INFO_INIT(&dyn_info);
3186
					DYN_INFO_INIT(&dyn_info);
3187
				}
3187
				}
3188
				break;
3188
				break;
3189
3189
3190
			default:
3190
			default:
3191
				panic("-- unknown opcode %d\n", cmd->opcode);
3191
				panic("-- unknown opcode %d\n", cmd->opcode);
3192
			} /* end of switch() on opcodes */
3192
			} /* end of switch() on opcodes */
3193
			/*
3193
			/*
3194
			 * if we get here with l=0, then match is irrelevant.
3194
			 * if we get here with l=0, then match is irrelevant.
3195
			 */
3195
			 */
3196
3196
3197
			if (cmd->len & F_NOT)
3197
			if (cmd->len & F_NOT)
3198
				match = !match;
3198
				match = !match;
3199
3199
3200
			if (match) {
3200
			if (match) {
3201
				if (cmd->len & F_OR)
3201
				if (cmd->len & F_OR)
3202
					skip_or = 1;
3202
					skip_or = 1;
3203
			} else {
3203
			} else {
3204
				if (!(cmd->len & F_OR)) /* not an OR block, */
3204
				if (!(cmd->len & F_OR)) /* not an OR block, */
3205
					break;		/* try next rule    */
3205
					break;		/* try next rule    */
3206
			}
3206
			}
3207
3207
3208
		}	/* end of inner loop, scan opcodes */
3208
		}	/* end of inner loop, scan opcodes */
3209
#undef PULLUP_LEN
3209
#undef PULLUP_LEN
3210
#undef PULLUP_LEN_LOCKED
3210
#undef PULLUP_LEN_LOCKED
3211
3211
3212
		if (done)
3212
		if (done)
3213
			break;
3213
			break;
3214
3214
3215
/* next_rule:; */	/* try next rule		*/
3215
/* next_rule:; */	/* try next rule		*/
3216
3216
3217
	}		/* end of outer for, scan rules */
3217
	}		/* end of outer for, scan rules */
3218
3218
3219
	if (done) {
3219
	if (done) {
3220
		struct ip_fw *rule = chain->map[f_pos];
3220
		struct ip_fw *rule = chain->map[f_pos];
3221
		/* Update statistics */
3221
		/* Update statistics */
3222
		IPFW_INC_RULE_COUNTER(rule, pktlen);
3222
		IPFW_INC_RULE_COUNTER(rule, pktlen);
3223
	} else {
3223
	} else {
3224
		retval = IP_FW_DENY;
3224
		retval = IP_FW_DENY;
3225
		printf("ipfw: ouch!, skip past end of rules, denying packet\n");
3225
		printf("ipfw: ouch!, skip past end of rules, denying packet\n");
3226
	}
3226
	}
3227
	IPFW_PF_RUNLOCK(chain);
3227
	IPFW_PF_RUNLOCK(chain);
3228
#ifdef __FreeBSD__
3228
#ifdef __FreeBSD__
3229
	if (ucred_cache != NULL)
3229
	if (ucred_cache != NULL)
3230
		crfree(ucred_cache);
3230
		crfree(ucred_cache);
3231
#endif
3231
#endif
3232
	return (retval);
3232
	return (retval);
3233
3233
3234
pullup_failed:
3234
pullup_failed:
3235
	if (V_fw_verbose)
3235
	if (V_fw_verbose)
3236
		printf("ipfw: pullup failed\n");
3236
		printf("ipfw: pullup failed\n");
3237
	return (IP_FW_DENY);
3237
	return (IP_FW_DENY);
3238
}
3238
}
3239
3239
3240
/*
3240
/*
3241
 * Set maximum number of tables that can be used in given VNET ipfw instance.
3241
 * Set maximum number of tables that can be used in given VNET ipfw instance.
3242
 */
3242
 */
3243
#ifdef SYSCTL_NODE
3243
#ifdef SYSCTL_NODE
3244
static int
3244
static int
3245
sysctl_ipfw_table_num(SYSCTL_HANDLER_ARGS)
3245
sysctl_ipfw_table_num(SYSCTL_HANDLER_ARGS)
3246
{
3246
{
3247
	int error;
3247
	int error;
3248
	unsigned int ntables;
3248
	unsigned int ntables;
3249
3249
3250
	ntables = V_fw_tables_max;
3250
	ntables = V_fw_tables_max;
3251
3251
3252
	error = sysctl_handle_int(oidp, &ntables, 0, req);
3252
	error = sysctl_handle_int(oidp, &ntables, 0, req);
3253
	/* Read operation or some error */
3253
	/* Read operation or some error */
3254
	if ((error != 0) || (req->newptr == NULL))
3254
	if ((error != 0) || (req->newptr == NULL))
3255
		return (error);
3255
		return (error);
3256
3256
3257
	return (ipfw_resize_tables(&V_layer3_chain, ntables));
3257
	return (ipfw_resize_tables(&V_layer3_chain, ntables));
3258
}
3258
}
3259
3259
3260
/*
3260
/*
3261
 * Switches table namespace between global and per-set.
3261
 * Switches table namespace between global and per-set.
3262
 */
3262
 */
3263
static int
3263
static int
3264
sysctl_ipfw_tables_sets(SYSCTL_HANDLER_ARGS)
3264
sysctl_ipfw_tables_sets(SYSCTL_HANDLER_ARGS)
3265
{
3265
{
3266
	int error;
3266
	int error;
3267
	unsigned int sets;
3267
	unsigned int sets;
3268
3268
3269
	sets = V_fw_tables_sets;
3269
	sets = V_fw_tables_sets;
3270
3270
3271
	error = sysctl_handle_int(oidp, &sets, 0, req);
3271
	error = sysctl_handle_int(oidp, &sets, 0, req);
3272
	/* Read operation or some error */
3272
	/* Read operation or some error */
3273
	if ((error != 0) || (req->newptr == NULL))
3273
	if ((error != 0) || (req->newptr == NULL))
3274
		return (error);
3274
		return (error);
3275
3275
3276
	return (ipfw_switch_tables_namespace(&V_layer3_chain, sets));
3276
	return (ipfw_switch_tables_namespace(&V_layer3_chain, sets));
3277
}
3277
}
3278
#endif
3278
#endif
3279
3279
3280
/*
3280
/*
3281
 * Module and VNET glue
3281
 * Module and VNET glue
3282
 */
3282
 */
3283
3283
3284
/*
3284
/*
3285
 * Stuff that must be initialised only on boot or module load
3285
 * Stuff that must be initialised only on boot or module load
3286
 */
3286
 */
3287
static int
3287
static int
3288
ipfw_init(void)
3288
ipfw_init(void)
3289
{
3289
{
3290
	int error = 0;
3290
	int error = 0;
3291
3291
3292
	/*
3292
	/*
3293
 	 * Only print out this stuff the first time around,
3293
 	 * Only print out this stuff the first time around,
3294
	 * when called from the sysinit code.
3294
	 * when called from the sysinit code.
3295
	 */
3295
	 */
3296
	printf("ipfw2 "
3296
	printf("ipfw2 "
3297
#ifdef INET6
3297
#ifdef INET6
3298
		"(+ipv6) "
3298
		"(+ipv6) "
3299
#endif
3299
#endif
3300
		"initialized, divert %s, nat %s, "
3300
		"initialized, divert %s, nat %s, "
3301
		"default to %s, logging ",
3301
		"default to %s, logging ",
3302
#ifdef IPDIVERT
3302
#ifdef IPDIVERT
3303
		"enabled",
3303
		"enabled",
3304
#else
3304
#else
3305
		"loadable",
3305
		"loadable",
3306
#endif
3306
#endif
3307
#ifdef IPFIREWALL_NAT
3307
#ifdef IPFIREWALL_NAT
3308
		"enabled",
3308
		"enabled",
3309
#else
3309
#else
3310
		"loadable",
3310
		"loadable",
3311
#endif
3311
#endif
3312
		default_to_accept ? "accept" : "deny");
3312
		default_to_accept ? "accept" : "deny");
3313
3313
3314
	/*
3314
	/*
3315
	 * Note: V_xxx variables can be accessed here but the vnet specific
3315
	 * Note: V_xxx variables can be accessed here but the vnet specific
3316
	 * initializer may not have been called yet for the VIMAGE case.
3316
	 * initializer may not have been called yet for the VIMAGE case.
3317
	 * Tuneables will have been processed. We will print out values for
3317
	 * Tuneables will have been processed. We will print out values for
3318
	 * the default vnet. 
3318
	 * the default vnet. 
3319
	 * XXX This should all be rationalized AFTER 8.0
3319
	 * XXX This should all be rationalized AFTER 8.0
3320
	 */
3320
	 */
3321
	if (V_fw_verbose == 0)
3321
	if (V_fw_verbose == 0)
3322
		printf("disabled\n");
3322
		printf("disabled\n");
3323
	else if (V_verbose_limit == 0)
3323
	else if (V_verbose_limit == 0)
3324
		printf("unlimited\n");
3324
		printf("unlimited\n");
3325
	else
3325
	else
3326
		printf("limited to %d packets/entry by default\n",
3326
		printf("limited to %d packets/entry by default\n",
3327
		    V_verbose_limit);
3327
		    V_verbose_limit);
3328
3328
3329
	/* Check user-supplied table count for validness */
3329
	/* Check user-supplied table count for validness */
3330
	if (default_fw_tables > IPFW_TABLES_MAX)
3330
	if (default_fw_tables > IPFW_TABLES_MAX)
3331
	  default_fw_tables = IPFW_TABLES_MAX;
3331
	  default_fw_tables = IPFW_TABLES_MAX;
3332
3332
3333
	ipfw_init_sopt_handler();
3333
	ipfw_init_sopt_handler();
3334
	ipfw_init_obj_rewriter();
3334
	ipfw_init_obj_rewriter();
3335
	ipfw_iface_init();
3335
	ipfw_iface_init();
3336
	return (error);
3336
	return (error);
3337
}
3337
}
3338
3338
3339
/*
3339
/*
3340
 * Called for the removal of the last instance only on module unload.
3340
 * Called for the removal of the last instance only on module unload.
3341
 */
3341
 */
3342
static void
3342
static void
3343
ipfw_destroy(void)
3343
ipfw_destroy(void)
3344
{
3344
{
3345
3345
3346
	ipfw_iface_destroy();
3346
	ipfw_iface_destroy();
3347
	ipfw_destroy_sopt_handler();
3347
	ipfw_destroy_sopt_handler();
3348
	ipfw_destroy_obj_rewriter();
3348
	ipfw_destroy_obj_rewriter();
3349
	printf("IP firewall unloaded\n");
3349
	printf("IP firewall unloaded\n");
3350
}
3350
}
3351
3351
3352
/*
3352
/*
3353
 * Stuff that must be initialized for every instance
3353
 * Stuff that must be initialized for every instance
3354
 * (including the first of course).
3354
 * (including the first of course).
3355
 */
3355
 */
3356
static int
3356
static int
3357
vnet_ipfw_init(const void *unused)
3357
vnet_ipfw_init(const void *unused)
3358
{
3358
{
3359
	int error, first;
3359
	int error, first;
3360
	struct ip_fw *rule = NULL;
3360
	struct ip_fw *rule = NULL;
3361
	struct ip_fw_chain *chain;
3361
	struct ip_fw_chain *chain;
3362
3362
3363
	chain = &V_layer3_chain;
3363
	chain = &V_layer3_chain;
3364
3364
3365
	first = IS_DEFAULT_VNET(curvnet) ? 1 : 0;
3365
	first = IS_DEFAULT_VNET(curvnet) ? 1 : 0;
3366
3366
3367
	/* First set up some values that are compile time options */
3367
	/* First set up some values that are compile time options */
3368
	V_autoinc_step = 100;	/* bounded to 1..1000 in add_rule() */
3368
	V_autoinc_step = 100;	/* bounded to 1..1000 in add_rule() */
3369
	V_fw_deny_unknown_exthdrs = 1;
3369
	V_fw_deny_unknown_exthdrs = 1;
3370
#ifdef IPFIREWALL_VERBOSE
3370
#ifdef IPFIREWALL_VERBOSE
3371
	V_fw_verbose = 1;
3371
	V_fw_verbose = 1;
3372
#endif
3372
#endif
3373
#ifdef IPFIREWALL_VERBOSE_LIMIT
3373
#ifdef IPFIREWALL_VERBOSE_LIMIT
3374
	V_verbose_limit = IPFIREWALL_VERBOSE_LIMIT;
3374
	V_verbose_limit = IPFIREWALL_VERBOSE_LIMIT;
3375
#endif
3375
#endif
3376
#ifdef IPFIREWALL_NAT
3376
#ifdef IPFIREWALL_NAT
3377
	LIST_INIT(&chain->nat);
3377
	LIST_INIT(&chain->nat);
3378
#endif
3378
#endif
3379
3379
3380
	/* Init shared services hash table */
3380
	/* Init shared services hash table */
3381
	ipfw_init_srv(chain);
3381
	ipfw_init_srv(chain);
3382
3382
3383
	ipfw_init_counters();
3383
	ipfw_init_counters();
3384
	/* Set initial number of tables */
3384
	/* Set initial number of tables */
3385
	V_fw_tables_max = default_fw_tables;
3385
	V_fw_tables_max = default_fw_tables;
3386
	error = ipfw_init_tables(chain, first);
3386
	error = ipfw_init_tables(chain, first);
3387
	if (error) {
3387
	if (error) {
3388
		printf("ipfw2: setting up tables failed\n");
3388
		printf("ipfw2: setting up tables failed\n");
3389
		free(chain->map, M_IPFW);
3389
		free(chain->map, M_IPFW);
3390
		free(rule, M_IPFW);
3390
		free(rule, M_IPFW);
3391
		return (ENOSPC);
3391
		return (ENOSPC);
3392
	}
3392
	}
3393
3393
3394
	IPFW_LOCK_INIT(chain);
3394
	IPFW_LOCK_INIT(chain);
3395
3395
3396
	/* fill and insert the default rule */
3396
	/* fill and insert the default rule */
3397
	rule = ipfw_alloc_rule(chain, sizeof(struct ip_fw));
3397
	rule = ipfw_alloc_rule(chain, sizeof(struct ip_fw));
3398
	rule->flags |= IPFW_RULE_NOOPT;
3398
	rule->flags |= IPFW_RULE_NOOPT;
3399
	rule->cmd_len = 1;
3399
	rule->cmd_len = 1;
3400
	rule->cmd[0].len = 1;
3400
	rule->cmd[0].len = 1;
3401
	rule->cmd[0].opcode = default_to_accept ? O_ACCEPT : O_DENY;
3401
	rule->cmd[0].opcode = default_to_accept ? O_ACCEPT : O_DENY;
3402
	chain->default_rule = rule;
3402
	chain->default_rule = rule;
3403
	ipfw_add_protected_rule(chain, rule, 0);
3403
	ipfw_add_protected_rule(chain, rule, 0);
3404
3404
3405
	ipfw_dyn_init(chain);
3405
	ipfw_dyn_init(chain);
3406
	ipfw_eaction_init(chain, first);
3406
	ipfw_eaction_init(chain, first);
3407
#ifdef LINEAR_SKIPTO
3407
#ifdef LINEAR_SKIPTO
3408
	ipfw_init_skipto_cache(chain);
3408
	ipfw_init_skipto_cache(chain);
3409
#endif
3409
#endif
3410
	ipfw_bpf_init(first);
3410
	ipfw_bpf_init(first);
3411
3411
3412
	/* First set up some values that are compile time options */
3412
	/* First set up some values that are compile time options */
3413
	V_ipfw_vnet_ready = 1;		/* Open for business */
3413
	V_ipfw_vnet_ready = 1;		/* Open for business */
3414
3414
3415
	/*
3415
	/*
3416
	 * Hook the sockopt handler and pfil hooks for ipv4 and ipv6.
3416
	 * Hook the sockopt handler and pfil hooks for ipv4 and ipv6.
3417
	 * Even if the latter two fail we still keep the module alive
3417
	 * Even if the latter two fail we still keep the module alive
3418
	 * because the sockopt and layer2 paths are still useful.
3418
	 * because the sockopt and layer2 paths are still useful.
3419
	 * ipfw[6]_hook return 0 on success, ENOENT on failure,
3419
	 * ipfw[6]_hook return 0 on success, ENOENT on failure,
3420
	 * so we can ignore the exact return value and just set a flag.
3420
	 * so we can ignore the exact return value and just set a flag.
3421
	 *
3421
	 *
3422
	 * Note that V_fw[6]_enable are manipulated by a SYSCTL_PROC so
3422
	 * Note that V_fw[6]_enable are manipulated by a SYSCTL_PROC so
3423
	 * changes in the underlying (per-vnet) variables trigger
3423
	 * changes in the underlying (per-vnet) variables trigger
3424
	 * immediate hook()/unhook() calls.
3424
	 * immediate hook()/unhook() calls.
3425
	 * In layer2 we have the same behaviour, except that V_ether_ipfw
3425
	 * In layer2 we have the same behaviour, except that V_ether_ipfw
3426
	 * is checked on each packet because there are no pfil hooks.
3426
	 * is checked on each packet because there are no pfil hooks.
3427
	 */
3427
	 */
3428
	V_ip_fw_ctl_ptr = ipfw_ctl3;
3428
	V_ip_fw_ctl_ptr = ipfw_ctl3;
3429
	error = ipfw_attach_hooks();
3429
	error = ipfw_attach_hooks();
3430
	return (error);
3430
	return (error);
3431
}
3431
}
3432
3432
3433
/*
3433
/*
3434
 * Called for the removal of each instance.
3434
 * Called for the removal of each instance.
3435
 */
3435
 */
3436
static int
3436
static int
3437
vnet_ipfw_uninit(const void *unused)
3437
vnet_ipfw_uninit(const void *unused)
3438
{
3438
{
3439
	struct ip_fw *reap;
3439
	struct ip_fw *reap;
3440
	struct ip_fw_chain *chain = &V_layer3_chain;
3440
	struct ip_fw_chain *chain = &V_layer3_chain;
3441
	int i, last;
3441
	int i, last;
3442
3442
3443
	V_ipfw_vnet_ready = 0; /* tell new callers to go away */
3443
	V_ipfw_vnet_ready = 0; /* tell new callers to go away */
3444
	/*
3444
	/*
3445
	 * disconnect from ipv4, ipv6, layer2 and sockopt.
3445
	 * disconnect from ipv4, ipv6, layer2 and sockopt.
3446
	 * Then grab, release and grab again the WLOCK so we make
3446
	 * Then grab, release and grab again the WLOCK so we make
3447
	 * sure the update is propagated and nobody will be in.
3447
	 * sure the update is propagated and nobody will be in.
3448
	 */
3448
	 */
3449
	ipfw_detach_hooks();
3449
	ipfw_detach_hooks();
3450
	V_ip_fw_ctl_ptr = NULL;
3450
	V_ip_fw_ctl_ptr = NULL;
3451
3451
3452
	last = IS_DEFAULT_VNET(curvnet) ? 1 : 0;
3452
	last = IS_DEFAULT_VNET(curvnet) ? 1 : 0;
3453
3453
3454
	IPFW_UH_WLOCK(chain);
3454
	IPFW_UH_WLOCK(chain);
3455
	IPFW_UH_WUNLOCK(chain);
3455
	IPFW_UH_WUNLOCK(chain);
3456
3456
3457
	ipfw_dyn_uninit(0);	/* run the callout_drain */
3457
	ipfw_dyn_uninit(0);	/* run the callout_drain */
3458
3458
3459
	IPFW_UH_WLOCK(chain);
3459
	IPFW_UH_WLOCK(chain);
3460
3460
3461
	reap = NULL;
3461
	reap = NULL;
3462
	IPFW_WLOCK(chain);
3462
	IPFW_WLOCK(chain);
3463
	for (i = 0; i < chain->n_rules; i++)
3463
	for (i = 0; i < chain->n_rules; i++)
3464
		ipfw_reap_add(chain, &reap, chain->map[i]);
3464
		ipfw_reap_add(chain, &reap, chain->map[i]);
3465
	free(chain->map, M_IPFW);
3465
	free(chain->map, M_IPFW);
3466
#ifdef LINEAR_SKIPTO
3466
#ifdef LINEAR_SKIPTO
3467
	ipfw_destroy_skipto_cache(chain);
3467
	ipfw_destroy_skipto_cache(chain);
3468
#endif
3468
#endif
3469
	IPFW_WUNLOCK(chain);
3469
	IPFW_WUNLOCK(chain);
3470
	IPFW_UH_WUNLOCK(chain);
3470
	IPFW_UH_WUNLOCK(chain);
3471
	ipfw_destroy_tables(chain, last);
3471
	ipfw_destroy_tables(chain, last);
3472
	ipfw_eaction_uninit(chain, last);
3472
	ipfw_eaction_uninit(chain, last);
3473
	if (reap != NULL)
3473
	if (reap != NULL)
3474
		ipfw_reap_rules(reap);
3474
		ipfw_reap_rules(reap);
3475
	vnet_ipfw_iface_destroy(chain);
3475
	vnet_ipfw_iface_destroy(chain);
3476
	ipfw_destroy_srv(chain);
3476
	ipfw_destroy_srv(chain);
3477
	IPFW_LOCK_DESTROY(chain);
3477
	IPFW_LOCK_DESTROY(chain);
3478
	ipfw_dyn_uninit(1);	/* free the remaining parts */
3478
	ipfw_dyn_uninit(1);	/* free the remaining parts */
3479
	ipfw_destroy_counters();
3479
	ipfw_destroy_counters();
3480
	ipfw_bpf_uninit(last);
3480
	ipfw_bpf_uninit(last);
3481
	return (0);
3481
	return (0);
3482
}
3482
}
3483
3483
3484
/*
3484
/*
3485
 * Module event handler.
3485
 * Module event handler.
3486
 * In general we have the choice of handling most of these events by the
3486
 * In general we have the choice of handling most of these events by the
3487
 * event handler or by the (VNET_)SYS(UN)INIT handlers. I have chosen to
3487
 * event handler or by the (VNET_)SYS(UN)INIT handlers. I have chosen to
3488
 * use the SYSINIT handlers as they are more capable of expressing the
3488
 * use the SYSINIT handlers as they are more capable of expressing the
3489
 * flow of control during module and vnet operations, so this is just
3489
 * flow of control during module and vnet operations, so this is just
3490
 * a skeleton. Note there is no SYSINIT equivalent of the module
3490
 * a skeleton. Note there is no SYSINIT equivalent of the module
3491
 * SHUTDOWN handler, but we don't have anything to do in that case anyhow.
3491
 * SHUTDOWN handler, but we don't have anything to do in that case anyhow.
3492
 */
3492
 */
3493
static int
3493
static int
3494
ipfw_modevent(module_t mod, int type, void *unused)
3494
ipfw_modevent(module_t mod, int type, void *unused)
3495
{
3495
{
3496
	int err = 0;
3496
	int err = 0;
3497
3497
3498
	switch (type) {
3498
	switch (type) {
3499
	case MOD_LOAD:
3499
	case MOD_LOAD:
3500
		/* Called once at module load or
3500
		/* Called once at module load or
3501
	 	 * system boot if compiled in. */
3501
	 	 * system boot if compiled in. */
3502
		break;
3502
		break;
3503
	case MOD_QUIESCE:
3503
	case MOD_QUIESCE:
3504
		/* Called before unload. May veto unloading. */
3504
		/* Called before unload. May veto unloading. */
3505
		break;
3505
		break;
3506
	case MOD_UNLOAD:
3506
	case MOD_UNLOAD:
3507
		/* Called during unload. */
3507
		/* Called during unload. */
3508
		break;
3508
		break;
3509
	case MOD_SHUTDOWN:
3509
	case MOD_SHUTDOWN:
3510
		/* Called during system shutdown. */
3510
		/* Called during system shutdown. */
3511
		break;
3511
		break;
3512
	default:
3512
	default:
3513
		err = EOPNOTSUPP;
3513
		err = EOPNOTSUPP;
3514
		break;
3514
		break;
3515
	}
3515
	}
3516
	return err;
3516
	return err;
3517
}
3517
}
3518
3518
3519
static moduledata_t ipfwmod = {
3519
static moduledata_t ipfwmod = {
3520
	"ipfw",
3520
	"ipfw",
3521
	ipfw_modevent,
3521
	ipfw_modevent,
3522
	0
3522
	0
3523
};
3523
};
3524
3524
3525
/* Define startup order. */
3525
/* Define startup order. */
3526
#define	IPFW_SI_SUB_FIREWALL	SI_SUB_PROTO_FIREWALL
3526
#define	IPFW_SI_SUB_FIREWALL	SI_SUB_PROTO_FIREWALL
3527
#define	IPFW_MODEVENT_ORDER	(SI_ORDER_ANY - 255) /* On boot slot in here. */
3527
#define	IPFW_MODEVENT_ORDER	(SI_ORDER_ANY - 255) /* On boot slot in here. */
3528
#define	IPFW_MODULE_ORDER	(IPFW_MODEVENT_ORDER + 1) /* A little later. */
3528
#define	IPFW_MODULE_ORDER	(IPFW_MODEVENT_ORDER + 1) /* A little later. */
3529
#define	IPFW_VNET_ORDER		(IPFW_MODEVENT_ORDER + 2) /* Later still. */
3529
#define	IPFW_VNET_ORDER		(IPFW_MODEVENT_ORDER + 2) /* Later still. */
3530
3530
3531
DECLARE_MODULE(ipfw, ipfwmod, IPFW_SI_SUB_FIREWALL, IPFW_MODEVENT_ORDER);
3531
DECLARE_MODULE(ipfw, ipfwmod, IPFW_SI_SUB_FIREWALL, IPFW_MODEVENT_ORDER);
3532
FEATURE(ipfw_ctl3, "ipfw new sockopt calls");
3532
FEATURE(ipfw_ctl3, "ipfw new sockopt calls");
3533
MODULE_VERSION(ipfw, 3);
3533
MODULE_VERSION(ipfw, 3);
3534
/* should declare some dependencies here */
3534
/* should declare some dependencies here */
3535
3535
3536
/*
3536
/*
3537
 * Starting up. Done in order after ipfwmod() has been called.
3537
 * Starting up. Done in order after ipfwmod() has been called.
3538
 * VNET_SYSINIT is also called for each existing vnet and each new vnet.
3538
 * VNET_SYSINIT is also called for each existing vnet and each new vnet.
3539
 */
3539
 */
3540
SYSINIT(ipfw_init, IPFW_SI_SUB_FIREWALL, IPFW_MODULE_ORDER,
3540
SYSINIT(ipfw_init, IPFW_SI_SUB_FIREWALL, IPFW_MODULE_ORDER,
3541
	    ipfw_init, NULL);
3541
	    ipfw_init, NULL);
3542
VNET_SYSINIT(vnet_ipfw_init, IPFW_SI_SUB_FIREWALL, IPFW_VNET_ORDER,
3542
VNET_SYSINIT(vnet_ipfw_init, IPFW_SI_SUB_FIREWALL, IPFW_VNET_ORDER,
3543
	    vnet_ipfw_init, NULL);
3543
	    vnet_ipfw_init, NULL);
3544
 
3544
 
3545
/*
3545
/*
3546
 * Closing up shop. These are done in REVERSE ORDER, but still
3546
 * Closing up shop. These are done in REVERSE ORDER, but still
3547
 * after ipfwmod() has been called. Not called on reboot.
3547
 * after ipfwmod() has been called. Not called on reboot.
3548
 * VNET_SYSUNINIT is also called for each exiting vnet as it exits.
3548
 * VNET_SYSUNINIT is also called for each exiting vnet as it exits.
3549
 * or when the module is unloaded.
3549
 * or when the module is unloaded.
3550
 */
3550
 */
3551
SYSUNINIT(ipfw_destroy, IPFW_SI_SUB_FIREWALL, IPFW_MODULE_ORDER,
3551
SYSUNINIT(ipfw_destroy, IPFW_SI_SUB_FIREWALL, IPFW_MODULE_ORDER,
3552
	    ipfw_destroy, NULL);
3552
	    ipfw_destroy, NULL);
3553
VNET_SYSUNINIT(vnet_ipfw_uninit, IPFW_SI_SUB_FIREWALL, IPFW_VNET_ORDER,
3553
VNET_SYSUNINIT(vnet_ipfw_uninit, IPFW_SI_SUB_FIREWALL, IPFW_VNET_ORDER,
3554
	    vnet_ipfw_uninit, NULL);
3554
	    vnet_ipfw_uninit, NULL);
3555
/* end of file */
3555
/* end of file */

Return to bug 245988