Commit 05465343bf74e00c8c2c5a310740157de3149f27

Authored by Patrick McHardy
Committed by David S. Miller
1 parent 764d8a9f24

[NETFILTER]: Add goto target

Originally written by Henrik Nordstrom <hno@marasystems.com>, taken
from netfilter patch-o-matic and added ip6_tables support.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 4 changed files with 8 additions and 6 deletions Inline Diff

include/linux/netfilter_ipv4/ip_tables.h
1 /* 1 /*
2 * 25-Jul-1998 Major changes to allow for ip chain table 2 * 25-Jul-1998 Major changes to allow for ip chain table
3 * 3 *
4 * 3-Jan-2000 Named tables to allow packet selection for different uses. 4 * 3-Jan-2000 Named tables to allow packet selection for different uses.
5 */ 5 */
6 6
7 /* 7 /*
8 * Format of an IP firewall descriptor 8 * Format of an IP firewall descriptor
9 * 9 *
10 * src, dst, src_mask, dst_mask are always stored in network byte order. 10 * src, dst, src_mask, dst_mask are always stored in network byte order.
11 * flags are stored in host byte order (of course). 11 * flags are stored in host byte order (of course).
12 * Port numbers are stored in HOST byte order. 12 * Port numbers are stored in HOST byte order.
13 */ 13 */
14 14
15 #ifndef _IPTABLES_H 15 #ifndef _IPTABLES_H
16 #define _IPTABLES_H 16 #define _IPTABLES_H
17 17
18 #ifdef __KERNEL__ 18 #ifdef __KERNEL__
19 #include <linux/if.h> 19 #include <linux/if.h>
20 #include <linux/types.h> 20 #include <linux/types.h>
21 #include <linux/in.h> 21 #include <linux/in.h>
22 #include <linux/ip.h> 22 #include <linux/ip.h>
23 #include <linux/skbuff.h> 23 #include <linux/skbuff.h>
24 #endif 24 #endif
25 #include <linux/compiler.h> 25 #include <linux/compiler.h>
26 #include <linux/netfilter_ipv4.h> 26 #include <linux/netfilter_ipv4.h>
27 27
28 #define IPT_FUNCTION_MAXNAMELEN 30 28 #define IPT_FUNCTION_MAXNAMELEN 30
29 #define IPT_TABLE_MAXNAMELEN 32 29 #define IPT_TABLE_MAXNAMELEN 32
30 30
31 /* Yes, Virginia, you have to zero the padding. */ 31 /* Yes, Virginia, you have to zero the padding. */
32 struct ipt_ip { 32 struct ipt_ip {
33 /* Source and destination IP addr */ 33 /* Source and destination IP addr */
34 struct in_addr src, dst; 34 struct in_addr src, dst;
35 /* Mask for src and dest IP addr */ 35 /* Mask for src and dest IP addr */
36 struct in_addr smsk, dmsk; 36 struct in_addr smsk, dmsk;
37 char iniface[IFNAMSIZ], outiface[IFNAMSIZ]; 37 char iniface[IFNAMSIZ], outiface[IFNAMSIZ];
38 unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ]; 38 unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
39 39
40 /* Protocol, 0 = ANY */ 40 /* Protocol, 0 = ANY */
41 u_int16_t proto; 41 u_int16_t proto;
42 42
43 /* Flags word */ 43 /* Flags word */
44 u_int8_t flags; 44 u_int8_t flags;
45 /* Inverse flags */ 45 /* Inverse flags */
46 u_int8_t invflags; 46 u_int8_t invflags;
47 }; 47 };
48 48
49 struct ipt_entry_match 49 struct ipt_entry_match
50 { 50 {
51 union { 51 union {
52 struct { 52 struct {
53 u_int16_t match_size; 53 u_int16_t match_size;
54 54
55 /* Used by userspace */ 55 /* Used by userspace */
56 char name[IPT_FUNCTION_MAXNAMELEN-1]; 56 char name[IPT_FUNCTION_MAXNAMELEN-1];
57 57
58 u_int8_t revision; 58 u_int8_t revision;
59 } user; 59 } user;
60 struct { 60 struct {
61 u_int16_t match_size; 61 u_int16_t match_size;
62 62
63 /* Used inside the kernel */ 63 /* Used inside the kernel */
64 struct ipt_match *match; 64 struct ipt_match *match;
65 } kernel; 65 } kernel;
66 66
67 /* Total length */ 67 /* Total length */
68 u_int16_t match_size; 68 u_int16_t match_size;
69 } u; 69 } u;
70 70
71 unsigned char data[0]; 71 unsigned char data[0];
72 }; 72 };
73 73
74 struct ipt_entry_target 74 struct ipt_entry_target
75 { 75 {
76 union { 76 union {
77 struct { 77 struct {
78 u_int16_t target_size; 78 u_int16_t target_size;
79 79
80 /* Used by userspace */ 80 /* Used by userspace */
81 char name[IPT_FUNCTION_MAXNAMELEN-1]; 81 char name[IPT_FUNCTION_MAXNAMELEN-1];
82 82
83 u_int8_t revision; 83 u_int8_t revision;
84 } user; 84 } user;
85 struct { 85 struct {
86 u_int16_t target_size; 86 u_int16_t target_size;
87 87
88 /* Used inside the kernel */ 88 /* Used inside the kernel */
89 struct ipt_target *target; 89 struct ipt_target *target;
90 } kernel; 90 } kernel;
91 91
92 /* Total length */ 92 /* Total length */
93 u_int16_t target_size; 93 u_int16_t target_size;
94 } u; 94 } u;
95 95
96 unsigned char data[0]; 96 unsigned char data[0];
97 }; 97 };
98 98
99 struct ipt_standard_target 99 struct ipt_standard_target
100 { 100 {
101 struct ipt_entry_target target; 101 struct ipt_entry_target target;
102 int verdict; 102 int verdict;
103 }; 103 };
104 104
105 struct ipt_counters 105 struct ipt_counters
106 { 106 {
107 u_int64_t pcnt, bcnt; /* Packet and byte counters */ 107 u_int64_t pcnt, bcnt; /* Packet and byte counters */
108 }; 108 };
109 109
110 /* Values for "flag" field in struct ipt_ip (general ip structure). */ 110 /* Values for "flag" field in struct ipt_ip (general ip structure). */
111 #define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */ 111 #define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */
112 #define IPT_F_MASK 0x01 /* All possible flag bits mask. */ 112 #define IPT_F_GOTO 0x02 /* Set if jump is a goto */
113 #define IPT_F_MASK 0x03 /* All possible flag bits mask. */
113 114
114 /* Values for "inv" field in struct ipt_ip. */ 115 /* Values for "inv" field in struct ipt_ip. */
115 #define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */ 116 #define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */
116 #define IPT_INV_VIA_OUT 0x02 /* Invert the sense of OUT IFACE */ 117 #define IPT_INV_VIA_OUT 0x02 /* Invert the sense of OUT IFACE */
117 #define IPT_INV_TOS 0x04 /* Invert the sense of TOS. */ 118 #define IPT_INV_TOS 0x04 /* Invert the sense of TOS. */
118 #define IPT_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */ 119 #define IPT_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */
119 #define IPT_INV_DSTIP 0x10 /* Invert the sense of DST OP. */ 120 #define IPT_INV_DSTIP 0x10 /* Invert the sense of DST OP. */
120 #define IPT_INV_FRAG 0x20 /* Invert the sense of FRAG. */ 121 #define IPT_INV_FRAG 0x20 /* Invert the sense of FRAG. */
121 #define IPT_INV_PROTO 0x40 /* Invert the sense of PROTO. */ 122 #define IPT_INV_PROTO 0x40 /* Invert the sense of PROTO. */
122 #define IPT_INV_MASK 0x7F /* All possible flag bits mask. */ 123 #define IPT_INV_MASK 0x7F /* All possible flag bits mask. */
123 124
124 /* This structure defines each of the firewall rules. Consists of 3 125 /* This structure defines each of the firewall rules. Consists of 3
125 parts which are 1) general IP header stuff 2) match specific 126 parts which are 1) general IP header stuff 2) match specific
126 stuff 3) the target to perform if the rule matches */ 127 stuff 3) the target to perform if the rule matches */
127 struct ipt_entry 128 struct ipt_entry
128 { 129 {
129 struct ipt_ip ip; 130 struct ipt_ip ip;
130 131
131 /* Mark with fields that we care about. */ 132 /* Mark with fields that we care about. */
132 unsigned int nfcache; 133 unsigned int nfcache;
133 134
134 /* Size of ipt_entry + matches */ 135 /* Size of ipt_entry + matches */
135 u_int16_t target_offset; 136 u_int16_t target_offset;
136 /* Size of ipt_entry + matches + target */ 137 /* Size of ipt_entry + matches + target */
137 u_int16_t next_offset; 138 u_int16_t next_offset;
138 139
139 /* Back pointer */ 140 /* Back pointer */
140 unsigned int comefrom; 141 unsigned int comefrom;
141 142
142 /* Packet and byte counters. */ 143 /* Packet and byte counters. */
143 struct ipt_counters counters; 144 struct ipt_counters counters;
144 145
145 /* The matches (if any), then the target. */ 146 /* The matches (if any), then the target. */
146 unsigned char elems[0]; 147 unsigned char elems[0];
147 }; 148 };
148 149
149 /* 150 /*
150 * New IP firewall options for [gs]etsockopt at the RAW IP level. 151 * New IP firewall options for [gs]etsockopt at the RAW IP level.
151 * Unlike BSD Linux inherits IP options so you don't have to use a raw 152 * Unlike BSD Linux inherits IP options so you don't have to use a raw
152 * socket for this. Instead we check rights in the calls. */ 153 * socket for this. Instead we check rights in the calls. */
153 #define IPT_BASE_CTL 64 /* base for firewall socket options */ 154 #define IPT_BASE_CTL 64 /* base for firewall socket options */
154 155
155 #define IPT_SO_SET_REPLACE (IPT_BASE_CTL) 156 #define IPT_SO_SET_REPLACE (IPT_BASE_CTL)
156 #define IPT_SO_SET_ADD_COUNTERS (IPT_BASE_CTL + 1) 157 #define IPT_SO_SET_ADD_COUNTERS (IPT_BASE_CTL + 1)
157 #define IPT_SO_SET_MAX IPT_SO_SET_ADD_COUNTERS 158 #define IPT_SO_SET_MAX IPT_SO_SET_ADD_COUNTERS
158 159
159 #define IPT_SO_GET_INFO (IPT_BASE_CTL) 160 #define IPT_SO_GET_INFO (IPT_BASE_CTL)
160 #define IPT_SO_GET_ENTRIES (IPT_BASE_CTL + 1) 161 #define IPT_SO_GET_ENTRIES (IPT_BASE_CTL + 1)
161 #define IPT_SO_GET_REVISION_MATCH (IPT_BASE_CTL + 2) 162 #define IPT_SO_GET_REVISION_MATCH (IPT_BASE_CTL + 2)
162 #define IPT_SO_GET_REVISION_TARGET (IPT_BASE_CTL + 3) 163 #define IPT_SO_GET_REVISION_TARGET (IPT_BASE_CTL + 3)
163 #define IPT_SO_GET_MAX IPT_SO_GET_REVISION_TARGET 164 #define IPT_SO_GET_MAX IPT_SO_GET_REVISION_TARGET
164 165
165 /* CONTINUE verdict for targets */ 166 /* CONTINUE verdict for targets */
166 #define IPT_CONTINUE 0xFFFFFFFF 167 #define IPT_CONTINUE 0xFFFFFFFF
167 168
168 /* For standard target */ 169 /* For standard target */
169 #define IPT_RETURN (-NF_REPEAT - 1) 170 #define IPT_RETURN (-NF_REPEAT - 1)
170 171
171 /* TCP matching stuff */ 172 /* TCP matching stuff */
172 struct ipt_tcp 173 struct ipt_tcp
173 { 174 {
174 u_int16_t spts[2]; /* Source port range. */ 175 u_int16_t spts[2]; /* Source port range. */
175 u_int16_t dpts[2]; /* Destination port range. */ 176 u_int16_t dpts[2]; /* Destination port range. */
176 u_int8_t option; /* TCP Option iff non-zero*/ 177 u_int8_t option; /* TCP Option iff non-zero*/
177 u_int8_t flg_mask; /* TCP flags mask byte */ 178 u_int8_t flg_mask; /* TCP flags mask byte */
178 u_int8_t flg_cmp; /* TCP flags compare byte */ 179 u_int8_t flg_cmp; /* TCP flags compare byte */
179 u_int8_t invflags; /* Inverse flags */ 180 u_int8_t invflags; /* Inverse flags */
180 }; 181 };
181 182
182 /* Values for "inv" field in struct ipt_tcp. */ 183 /* Values for "inv" field in struct ipt_tcp. */
183 #define IPT_TCP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ 184 #define IPT_TCP_INV_SRCPT 0x01 /* Invert the sense of source ports. */
184 #define IPT_TCP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ 185 #define IPT_TCP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */
185 #define IPT_TCP_INV_FLAGS 0x04 /* Invert the sense of TCP flags. */ 186 #define IPT_TCP_INV_FLAGS 0x04 /* Invert the sense of TCP flags. */
186 #define IPT_TCP_INV_OPTION 0x08 /* Invert the sense of option test. */ 187 #define IPT_TCP_INV_OPTION 0x08 /* Invert the sense of option test. */
187 #define IPT_TCP_INV_MASK 0x0F /* All possible flags. */ 188 #define IPT_TCP_INV_MASK 0x0F /* All possible flags. */
188 189
189 /* UDP matching stuff */ 190 /* UDP matching stuff */
190 struct ipt_udp 191 struct ipt_udp
191 { 192 {
192 u_int16_t spts[2]; /* Source port range. */ 193 u_int16_t spts[2]; /* Source port range. */
193 u_int16_t dpts[2]; /* Destination port range. */ 194 u_int16_t dpts[2]; /* Destination port range. */
194 u_int8_t invflags; /* Inverse flags */ 195 u_int8_t invflags; /* Inverse flags */
195 }; 196 };
196 197
197 /* Values for "invflags" field in struct ipt_udp. */ 198 /* Values for "invflags" field in struct ipt_udp. */
198 #define IPT_UDP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ 199 #define IPT_UDP_INV_SRCPT 0x01 /* Invert the sense of source ports. */
199 #define IPT_UDP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ 200 #define IPT_UDP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */
200 #define IPT_UDP_INV_MASK 0x03 /* All possible flags. */ 201 #define IPT_UDP_INV_MASK 0x03 /* All possible flags. */
201 202
202 /* ICMP matching stuff */ 203 /* ICMP matching stuff */
203 struct ipt_icmp 204 struct ipt_icmp
204 { 205 {
205 u_int8_t type; /* type to match */ 206 u_int8_t type; /* type to match */
206 u_int8_t code[2]; /* range of code */ 207 u_int8_t code[2]; /* range of code */
207 u_int8_t invflags; /* Inverse flags */ 208 u_int8_t invflags; /* Inverse flags */
208 }; 209 };
209 210
210 /* Values for "inv" field for struct ipt_icmp. */ 211 /* Values for "inv" field for struct ipt_icmp. */
211 #define IPT_ICMP_INV 0x01 /* Invert the sense of type/code test */ 212 #define IPT_ICMP_INV 0x01 /* Invert the sense of type/code test */
212 213
213 /* The argument to IPT_SO_GET_INFO */ 214 /* The argument to IPT_SO_GET_INFO */
214 struct ipt_getinfo 215 struct ipt_getinfo
215 { 216 {
216 /* Which table: caller fills this in. */ 217 /* Which table: caller fills this in. */
217 char name[IPT_TABLE_MAXNAMELEN]; 218 char name[IPT_TABLE_MAXNAMELEN];
218 219
219 /* Kernel fills these in. */ 220 /* Kernel fills these in. */
220 /* Which hook entry points are valid: bitmask */ 221 /* Which hook entry points are valid: bitmask */
221 unsigned int valid_hooks; 222 unsigned int valid_hooks;
222 223
223 /* Hook entry points: one per netfilter hook. */ 224 /* Hook entry points: one per netfilter hook. */
224 unsigned int hook_entry[NF_IP_NUMHOOKS]; 225 unsigned int hook_entry[NF_IP_NUMHOOKS];
225 226
226 /* Underflow points. */ 227 /* Underflow points. */
227 unsigned int underflow[NF_IP_NUMHOOKS]; 228 unsigned int underflow[NF_IP_NUMHOOKS];
228 229
229 /* Number of entries */ 230 /* Number of entries */
230 unsigned int num_entries; 231 unsigned int num_entries;
231 232
232 /* Size of entries. */ 233 /* Size of entries. */
233 unsigned int size; 234 unsigned int size;
234 }; 235 };
235 236
236 /* The argument to IPT_SO_SET_REPLACE. */ 237 /* The argument to IPT_SO_SET_REPLACE. */
237 struct ipt_replace 238 struct ipt_replace
238 { 239 {
239 /* Which table. */ 240 /* Which table. */
240 char name[IPT_TABLE_MAXNAMELEN]; 241 char name[IPT_TABLE_MAXNAMELEN];
241 242
242 /* Which hook entry points are valid: bitmask. You can't 243 /* Which hook entry points are valid: bitmask. You can't
243 change this. */ 244 change this. */
244 unsigned int valid_hooks; 245 unsigned int valid_hooks;
245 246
246 /* Number of entries */ 247 /* Number of entries */
247 unsigned int num_entries; 248 unsigned int num_entries;
248 249
249 /* Total size of new entries */ 250 /* Total size of new entries */
250 unsigned int size; 251 unsigned int size;
251 252
252 /* Hook entry points. */ 253 /* Hook entry points. */
253 unsigned int hook_entry[NF_IP_NUMHOOKS]; 254 unsigned int hook_entry[NF_IP_NUMHOOKS];
254 255
255 /* Underflow points. */ 256 /* Underflow points. */
256 unsigned int underflow[NF_IP_NUMHOOKS]; 257 unsigned int underflow[NF_IP_NUMHOOKS];
257 258
258 /* Information about old entries: */ 259 /* Information about old entries: */
259 /* Number of counters (must be equal to current number of entries). */ 260 /* Number of counters (must be equal to current number of entries). */
260 unsigned int num_counters; 261 unsigned int num_counters;
261 /* The old entries' counters. */ 262 /* The old entries' counters. */
262 struct ipt_counters __user *counters; 263 struct ipt_counters __user *counters;
263 264
264 /* The entries (hang off end: not really an array). */ 265 /* The entries (hang off end: not really an array). */
265 struct ipt_entry entries[0]; 266 struct ipt_entry entries[0];
266 }; 267 };
267 268
268 /* The argument to IPT_SO_ADD_COUNTERS. */ 269 /* The argument to IPT_SO_ADD_COUNTERS. */
269 struct ipt_counters_info 270 struct ipt_counters_info
270 { 271 {
271 /* Which table. */ 272 /* Which table. */
272 char name[IPT_TABLE_MAXNAMELEN]; 273 char name[IPT_TABLE_MAXNAMELEN];
273 274
274 unsigned int num_counters; 275 unsigned int num_counters;
275 276
276 /* The counters (actually `number' of these). */ 277 /* The counters (actually `number' of these). */
277 struct ipt_counters counters[0]; 278 struct ipt_counters counters[0];
278 }; 279 };
279 280
280 /* The argument to IPT_SO_GET_ENTRIES. */ 281 /* The argument to IPT_SO_GET_ENTRIES. */
281 struct ipt_get_entries 282 struct ipt_get_entries
282 { 283 {
283 /* Which table: user fills this in. */ 284 /* Which table: user fills this in. */
284 char name[IPT_TABLE_MAXNAMELEN]; 285 char name[IPT_TABLE_MAXNAMELEN];
285 286
286 /* User fills this in: total entry size. */ 287 /* User fills this in: total entry size. */
287 unsigned int size; 288 unsigned int size;
288 289
289 /* The entries. */ 290 /* The entries. */
290 struct ipt_entry entrytable[0]; 291 struct ipt_entry entrytable[0];
291 }; 292 };
292 293
293 /* The argument to IPT_SO_GET_REVISION_*. Returns highest revision 294 /* The argument to IPT_SO_GET_REVISION_*. Returns highest revision
294 * kernel supports, if >= revision. */ 295 * kernel supports, if >= revision. */
295 struct ipt_get_revision 296 struct ipt_get_revision
296 { 297 {
297 char name[IPT_FUNCTION_MAXNAMELEN-1]; 298 char name[IPT_FUNCTION_MAXNAMELEN-1];
298 299
299 u_int8_t revision; 300 u_int8_t revision;
300 }; 301 };
301 302
302 /* Standard return verdict, or do jump. */ 303 /* Standard return verdict, or do jump. */
303 #define IPT_STANDARD_TARGET "" 304 #define IPT_STANDARD_TARGET ""
304 /* Error verdict. */ 305 /* Error verdict. */
305 #define IPT_ERROR_TARGET "ERROR" 306 #define IPT_ERROR_TARGET "ERROR"
306 307
307 /* Helper functions */ 308 /* Helper functions */
308 static __inline__ struct ipt_entry_target * 309 static __inline__ struct ipt_entry_target *
309 ipt_get_target(struct ipt_entry *e) 310 ipt_get_target(struct ipt_entry *e)
310 { 311 {
311 return (void *)e + e->target_offset; 312 return (void *)e + e->target_offset;
312 } 313 }
313 314
314 /* fn returns 0 to continue iteration */ 315 /* fn returns 0 to continue iteration */
315 #define IPT_MATCH_ITERATE(e, fn, args...) \ 316 #define IPT_MATCH_ITERATE(e, fn, args...) \
316 ({ \ 317 ({ \
317 unsigned int __i; \ 318 unsigned int __i; \
318 int __ret = 0; \ 319 int __ret = 0; \
319 struct ipt_entry_match *__match; \ 320 struct ipt_entry_match *__match; \
320 \ 321 \
321 for (__i = sizeof(struct ipt_entry); \ 322 for (__i = sizeof(struct ipt_entry); \
322 __i < (e)->target_offset; \ 323 __i < (e)->target_offset; \
323 __i += __match->u.match_size) { \ 324 __i += __match->u.match_size) { \
324 __match = (void *)(e) + __i; \ 325 __match = (void *)(e) + __i; \
325 \ 326 \
326 __ret = fn(__match , ## args); \ 327 __ret = fn(__match , ## args); \
327 if (__ret != 0) \ 328 if (__ret != 0) \
328 break; \ 329 break; \
329 } \ 330 } \
330 __ret; \ 331 __ret; \
331 }) 332 })
332 333
333 /* fn returns 0 to continue iteration */ 334 /* fn returns 0 to continue iteration */
334 #define IPT_ENTRY_ITERATE(entries, size, fn, args...) \ 335 #define IPT_ENTRY_ITERATE(entries, size, fn, args...) \
335 ({ \ 336 ({ \
336 unsigned int __i; \ 337 unsigned int __i; \
337 int __ret = 0; \ 338 int __ret = 0; \
338 struct ipt_entry *__entry; \ 339 struct ipt_entry *__entry; \
339 \ 340 \
340 for (__i = 0; __i < (size); __i += __entry->next_offset) { \ 341 for (__i = 0; __i < (size); __i += __entry->next_offset) { \
341 __entry = (void *)(entries) + __i; \ 342 __entry = (void *)(entries) + __i; \
342 \ 343 \
343 __ret = fn(__entry , ## args); \ 344 __ret = fn(__entry , ## args); \
344 if (__ret != 0) \ 345 if (__ret != 0) \
345 break; \ 346 break; \
346 } \ 347 } \
347 __ret; \ 348 __ret; \
348 }) 349 })
349 350
350 /* 351 /*
351 * Main firewall chains definitions and global var's definitions. 352 * Main firewall chains definitions and global var's definitions.
352 */ 353 */
353 #ifdef __KERNEL__ 354 #ifdef __KERNEL__
354 355
355 #include <linux/init.h> 356 #include <linux/init.h>
356 extern void ipt_init(void) __init; 357 extern void ipt_init(void) __init;
357 358
358 struct ipt_match 359 struct ipt_match
359 { 360 {
360 struct list_head list; 361 struct list_head list;
361 362
362 const char name[IPT_FUNCTION_MAXNAMELEN-1]; 363 const char name[IPT_FUNCTION_MAXNAMELEN-1];
363 364
364 u_int8_t revision; 365 u_int8_t revision;
365 366
366 /* Return true or false: return FALSE and set *hotdrop = 1 to 367 /* Return true or false: return FALSE and set *hotdrop = 1 to
367 force immediate packet drop. */ 368 force immediate packet drop. */
368 /* Arguments changed since 2.4, as this must now handle 369 /* Arguments changed since 2.4, as this must now handle
369 non-linear skbs, using skb_copy_bits and 370 non-linear skbs, using skb_copy_bits and
370 skb_ip_make_writable. */ 371 skb_ip_make_writable. */
371 int (*match)(const struct sk_buff *skb, 372 int (*match)(const struct sk_buff *skb,
372 const struct net_device *in, 373 const struct net_device *in,
373 const struct net_device *out, 374 const struct net_device *out,
374 const void *matchinfo, 375 const void *matchinfo,
375 int offset, 376 int offset,
376 int *hotdrop); 377 int *hotdrop);
377 378
378 /* Called when user tries to insert an entry of this type. */ 379 /* Called when user tries to insert an entry of this type. */
379 /* Should return true or false. */ 380 /* Should return true or false. */
380 int (*checkentry)(const char *tablename, 381 int (*checkentry)(const char *tablename,
381 const struct ipt_ip *ip, 382 const struct ipt_ip *ip,
382 void *matchinfo, 383 void *matchinfo,
383 unsigned int matchinfosize, 384 unsigned int matchinfosize,
384 unsigned int hook_mask); 385 unsigned int hook_mask);
385 386
386 /* Called when entry of this type deleted. */ 387 /* Called when entry of this type deleted. */
387 void (*destroy)(void *matchinfo, unsigned int matchinfosize); 388 void (*destroy)(void *matchinfo, unsigned int matchinfosize);
388 389
389 /* Set this to THIS_MODULE. */ 390 /* Set this to THIS_MODULE. */
390 struct module *me; 391 struct module *me;
391 }; 392 };
392 393
393 /* Registration hooks for targets. */ 394 /* Registration hooks for targets. */
394 struct ipt_target 395 struct ipt_target
395 { 396 {
396 struct list_head list; 397 struct list_head list;
397 398
398 const char name[IPT_FUNCTION_MAXNAMELEN-1]; 399 const char name[IPT_FUNCTION_MAXNAMELEN-1];
399 400
400 u_int8_t revision; 401 u_int8_t revision;
401 402
402 /* Called when user tries to insert an entry of this type: 403 /* Called when user tries to insert an entry of this type:
403 hook_mask is a bitmask of hooks from which it can be 404 hook_mask is a bitmask of hooks from which it can be
404 called. */ 405 called. */
405 /* Should return true or false. */ 406 /* Should return true or false. */
406 int (*checkentry)(const char *tablename, 407 int (*checkentry)(const char *tablename,
407 const struct ipt_entry *e, 408 const struct ipt_entry *e,
408 void *targinfo, 409 void *targinfo,
409 unsigned int targinfosize, 410 unsigned int targinfosize,
410 unsigned int hook_mask); 411 unsigned int hook_mask);
411 412
412 /* Called when entry of this type deleted. */ 413 /* Called when entry of this type deleted. */
413 void (*destroy)(void *targinfo, unsigned int targinfosize); 414 void (*destroy)(void *targinfo, unsigned int targinfosize);
414 415
415 /* Returns verdict. Argument order changed since 2.4, as this 416 /* Returns verdict. Argument order changed since 2.4, as this
416 must now handle non-linear skbs, using skb_copy_bits and 417 must now handle non-linear skbs, using skb_copy_bits and
417 skb_ip_make_writable. */ 418 skb_ip_make_writable. */
418 unsigned int (*target)(struct sk_buff **pskb, 419 unsigned int (*target)(struct sk_buff **pskb,
419 const struct net_device *in, 420 const struct net_device *in,
420 const struct net_device *out, 421 const struct net_device *out,
421 unsigned int hooknum, 422 unsigned int hooknum,
422 const void *targinfo, 423 const void *targinfo,
423 void *userdata); 424 void *userdata);
424 425
425 /* Set this to THIS_MODULE. */ 426 /* Set this to THIS_MODULE. */
426 struct module *me; 427 struct module *me;
427 }; 428 };
428 429
429 extern int ipt_register_target(struct ipt_target *target); 430 extern int ipt_register_target(struct ipt_target *target);
430 extern void ipt_unregister_target(struct ipt_target *target); 431 extern void ipt_unregister_target(struct ipt_target *target);
431 432
432 extern int ipt_register_match(struct ipt_match *match); 433 extern int ipt_register_match(struct ipt_match *match);
433 extern void ipt_unregister_match(struct ipt_match *match); 434 extern void ipt_unregister_match(struct ipt_match *match);
434 435
435 /* Furniture shopping... */ 436 /* Furniture shopping... */
436 struct ipt_table 437 struct ipt_table
437 { 438 {
438 struct list_head list; 439 struct list_head list;
439 440
440 /* A unique name... */ 441 /* A unique name... */
441 char name[IPT_TABLE_MAXNAMELEN]; 442 char name[IPT_TABLE_MAXNAMELEN];
442 443
443 /* What hooks you will enter on */ 444 /* What hooks you will enter on */
444 unsigned int valid_hooks; 445 unsigned int valid_hooks;
445 446
446 /* Lock for the curtain */ 447 /* Lock for the curtain */
447 rwlock_t lock; 448 rwlock_t lock;
448 449
449 /* Man behind the curtain... */ 450 /* Man behind the curtain... */
450 struct ipt_table_info *private; 451 struct ipt_table_info *private;
451 452
452 /* Set to THIS_MODULE. */ 453 /* Set to THIS_MODULE. */
453 struct module *me; 454 struct module *me;
454 }; 455 };
455 456
456 /* net/sched/ipt.c: Gimme access to your targets! Gets target->me. */ 457 /* net/sched/ipt.c: Gimme access to your targets! Gets target->me. */
457 extern struct ipt_target *ipt_find_target(const char *name, u8 revision); 458 extern struct ipt_target *ipt_find_target(const char *name, u8 revision);
458 459
459 /* Standard entry. */ 460 /* Standard entry. */
460 struct ipt_standard 461 struct ipt_standard
461 { 462 {
462 struct ipt_entry entry; 463 struct ipt_entry entry;
463 struct ipt_standard_target target; 464 struct ipt_standard_target target;
464 }; 465 };
465 466
466 struct ipt_error_target 467 struct ipt_error_target
467 { 468 {
468 struct ipt_entry_target target; 469 struct ipt_entry_target target;
469 char errorname[IPT_FUNCTION_MAXNAMELEN]; 470 char errorname[IPT_FUNCTION_MAXNAMELEN];
470 }; 471 };
471 472
472 struct ipt_error 473 struct ipt_error
473 { 474 {
474 struct ipt_entry entry; 475 struct ipt_entry entry;
475 struct ipt_error_target target; 476 struct ipt_error_target target;
476 }; 477 };
477 478
478 extern int ipt_register_table(struct ipt_table *table, 479 extern int ipt_register_table(struct ipt_table *table,
479 const struct ipt_replace *repl); 480 const struct ipt_replace *repl);
480 extern void ipt_unregister_table(struct ipt_table *table); 481 extern void ipt_unregister_table(struct ipt_table *table);
481 extern unsigned int ipt_do_table(struct sk_buff **pskb, 482 extern unsigned int ipt_do_table(struct sk_buff **pskb,
482 unsigned int hook, 483 unsigned int hook,
483 const struct net_device *in, 484 const struct net_device *in,
484 const struct net_device *out, 485 const struct net_device *out,
485 struct ipt_table *table, 486 struct ipt_table *table,
486 void *userdata); 487 void *userdata);
487 488
488 #define IPT_ALIGN(s) (((s) + (__alignof__(struct ipt_entry)-1)) & ~(__alignof__(struct ipt_entry)-1)) 489 #define IPT_ALIGN(s) (((s) + (__alignof__(struct ipt_entry)-1)) & ~(__alignof__(struct ipt_entry)-1))
489 #endif /*__KERNEL__*/ 490 #endif /*__KERNEL__*/
490 #endif /* _IPTABLES_H */ 491 #endif /* _IPTABLES_H */
491 492
include/linux/netfilter_ipv6/ip6_tables.h
1 /* 1 /*
2 * 25-Jul-1998 Major changes to allow for ip chain table 2 * 25-Jul-1998 Major changes to allow for ip chain table
3 * 3 *
4 * 3-Jan-2000 Named tables to allow packet selection for different uses. 4 * 3-Jan-2000 Named tables to allow packet selection for different uses.
5 */ 5 */
6 6
7 /* 7 /*
8 * Format of an IP6 firewall descriptor 8 * Format of an IP6 firewall descriptor
9 * 9 *
10 * src, dst, src_mask, dst_mask are always stored in network byte order. 10 * src, dst, src_mask, dst_mask are always stored in network byte order.
11 * flags are stored in host byte order (of course). 11 * flags are stored in host byte order (of course).
12 * Port numbers are stored in HOST byte order. 12 * Port numbers are stored in HOST byte order.
13 */ 13 */
14 14
15 #ifndef _IP6_TABLES_H 15 #ifndef _IP6_TABLES_H
16 #define _IP6_TABLES_H 16 #define _IP6_TABLES_H
17 17
18 #ifdef __KERNEL__ 18 #ifdef __KERNEL__
19 #include <linux/if.h> 19 #include <linux/if.h>
20 #include <linux/types.h> 20 #include <linux/types.h>
21 #include <linux/in6.h> 21 #include <linux/in6.h>
22 #include <linux/ipv6.h> 22 #include <linux/ipv6.h>
23 #include <linux/skbuff.h> 23 #include <linux/skbuff.h>
24 #endif 24 #endif
25 #include <linux/compiler.h> 25 #include <linux/compiler.h>
26 #include <linux/netfilter_ipv6.h> 26 #include <linux/netfilter_ipv6.h>
27 27
28 #define IP6T_FUNCTION_MAXNAMELEN 30 28 #define IP6T_FUNCTION_MAXNAMELEN 30
29 #define IP6T_TABLE_MAXNAMELEN 32 29 #define IP6T_TABLE_MAXNAMELEN 32
30 30
31 /* Yes, Virginia, you have to zero the padding. */ 31 /* Yes, Virginia, you have to zero the padding. */
32 struct ip6t_ip6 { 32 struct ip6t_ip6 {
33 /* Source and destination IP6 addr */ 33 /* Source and destination IP6 addr */
34 struct in6_addr src, dst; 34 struct in6_addr src, dst;
35 /* Mask for src and dest IP6 addr */ 35 /* Mask for src and dest IP6 addr */
36 struct in6_addr smsk, dmsk; 36 struct in6_addr smsk, dmsk;
37 char iniface[IFNAMSIZ], outiface[IFNAMSIZ]; 37 char iniface[IFNAMSIZ], outiface[IFNAMSIZ];
38 unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ]; 38 unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
39 39
40 /* ARGH, HopByHop uses 0, so can't do 0 = ANY, 40 /* ARGH, HopByHop uses 0, so can't do 0 = ANY,
41 instead IP6T_F_NOPROTO must be set */ 41 instead IP6T_F_NOPROTO must be set */
42 u_int16_t proto; 42 u_int16_t proto;
43 /* TOS to match iff flags & IP6T_F_TOS */ 43 /* TOS to match iff flags & IP6T_F_TOS */
44 u_int8_t tos; 44 u_int8_t tos;
45 45
46 /* Flags word */ 46 /* Flags word */
47 u_int8_t flags; 47 u_int8_t flags;
48 /* Inverse flags */ 48 /* Inverse flags */
49 u_int8_t invflags; 49 u_int8_t invflags;
50 }; 50 };
51 51
52 /* FIXME: If alignment in kernel different from userspace? --RR */ 52 /* FIXME: If alignment in kernel different from userspace? --RR */
53 struct ip6t_entry_match 53 struct ip6t_entry_match
54 { 54 {
55 union { 55 union {
56 struct { 56 struct {
57 u_int16_t match_size; 57 u_int16_t match_size;
58 58
59 /* Used by userspace */ 59 /* Used by userspace */
60 char name[IP6T_FUNCTION_MAXNAMELEN]; 60 char name[IP6T_FUNCTION_MAXNAMELEN];
61 } user; 61 } user;
62 struct { 62 struct {
63 u_int16_t match_size; 63 u_int16_t match_size;
64 64
65 /* Used inside the kernel */ 65 /* Used inside the kernel */
66 struct ip6t_match *match; 66 struct ip6t_match *match;
67 } kernel; 67 } kernel;
68 68
69 /* Total length */ 69 /* Total length */
70 u_int16_t match_size; 70 u_int16_t match_size;
71 } u; 71 } u;
72 72
73 unsigned char data[0]; 73 unsigned char data[0];
74 }; 74 };
75 75
76 struct ip6t_entry_target 76 struct ip6t_entry_target
77 { 77 {
78 union { 78 union {
79 struct { 79 struct {
80 u_int16_t target_size; 80 u_int16_t target_size;
81 81
82 /* Used by userspace */ 82 /* Used by userspace */
83 char name[IP6T_FUNCTION_MAXNAMELEN]; 83 char name[IP6T_FUNCTION_MAXNAMELEN];
84 } user; 84 } user;
85 struct { 85 struct {
86 u_int16_t target_size; 86 u_int16_t target_size;
87 87
88 /* Used inside the kernel */ 88 /* Used inside the kernel */
89 struct ip6t_target *target; 89 struct ip6t_target *target;
90 } kernel; 90 } kernel;
91 91
92 /* Total length */ 92 /* Total length */
93 u_int16_t target_size; 93 u_int16_t target_size;
94 } u; 94 } u;
95 95
96 unsigned char data[0]; 96 unsigned char data[0];
97 }; 97 };
98 98
99 struct ip6t_standard_target 99 struct ip6t_standard_target
100 { 100 {
101 struct ip6t_entry_target target; 101 struct ip6t_entry_target target;
102 int verdict; 102 int verdict;
103 }; 103 };
104 104
105 struct ip6t_counters 105 struct ip6t_counters
106 { 106 {
107 u_int64_t pcnt, bcnt; /* Packet and byte counters */ 107 u_int64_t pcnt, bcnt; /* Packet and byte counters */
108 }; 108 };
109 109
110 /* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */ 110 /* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */
111 #define IP6T_F_PROTO 0x01 /* Set if rule cares about upper 111 #define IP6T_F_PROTO 0x01 /* Set if rule cares about upper
112 protocols */ 112 protocols */
113 #define IP6T_F_TOS 0x02 /* Match the TOS. */ 113 #define IP6T_F_TOS 0x02 /* Match the TOS. */
114 #define IP6T_F_MASK 0x03 /* All possible flag bits mask. */ 114 #define IP6T_F_GOTO 0x04 /* Set if jump is a goto */
115 #define IP6T_F_MASK 0x07 /* All possible flag bits mask. */
115 116
116 /* Values for "inv" field in struct ip6t_ip6. */ 117 /* Values for "inv" field in struct ip6t_ip6. */
117 #define IP6T_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */ 118 #define IP6T_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */
118 #define IP6T_INV_VIA_OUT 0x02 /* Invert the sense of OUT IFACE */ 119 #define IP6T_INV_VIA_OUT 0x02 /* Invert the sense of OUT IFACE */
119 #define IP6T_INV_TOS 0x04 /* Invert the sense of TOS. */ 120 #define IP6T_INV_TOS 0x04 /* Invert the sense of TOS. */
120 #define IP6T_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */ 121 #define IP6T_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */
121 #define IP6T_INV_DSTIP 0x10 /* Invert the sense of DST OP. */ 122 #define IP6T_INV_DSTIP 0x10 /* Invert the sense of DST OP. */
122 #define IP6T_INV_FRAG 0x20 /* Invert the sense of FRAG. */ 123 #define IP6T_INV_FRAG 0x20 /* Invert the sense of FRAG. */
123 #define IP6T_INV_PROTO 0x40 /* Invert the sense of PROTO. */ 124 #define IP6T_INV_PROTO 0x40 /* Invert the sense of PROTO. */
124 #define IP6T_INV_MASK 0x7F /* All possible flag bits mask. */ 125 #define IP6T_INV_MASK 0x7F /* All possible flag bits mask. */
125 126
126 /* This structure defines each of the firewall rules. Consists of 3 127 /* This structure defines each of the firewall rules. Consists of 3
127 parts which are 1) general IP header stuff 2) match specific 128 parts which are 1) general IP header stuff 2) match specific
128 stuff 3) the target to perform if the rule matches */ 129 stuff 3) the target to perform if the rule matches */
129 struct ip6t_entry 130 struct ip6t_entry
130 { 131 {
131 struct ip6t_ip6 ipv6; 132 struct ip6t_ip6 ipv6;
132 133
133 /* Mark with fields that we care about. */ 134 /* Mark with fields that we care about. */
134 unsigned int nfcache; 135 unsigned int nfcache;
135 136
136 /* Size of ipt_entry + matches */ 137 /* Size of ipt_entry + matches */
137 u_int16_t target_offset; 138 u_int16_t target_offset;
138 /* Size of ipt_entry + matches + target */ 139 /* Size of ipt_entry + matches + target */
139 u_int16_t next_offset; 140 u_int16_t next_offset;
140 141
141 /* Back pointer */ 142 /* Back pointer */
142 unsigned int comefrom; 143 unsigned int comefrom;
143 144
144 /* Packet and byte counters. */ 145 /* Packet and byte counters. */
145 struct ip6t_counters counters; 146 struct ip6t_counters counters;
146 147
147 /* The matches (if any), then the target. */ 148 /* The matches (if any), then the target. */
148 unsigned char elems[0]; 149 unsigned char elems[0];
149 }; 150 };
150 151
151 /* 152 /*
152 * New IP firewall options for [gs]etsockopt at the RAW IP level. 153 * New IP firewall options for [gs]etsockopt at the RAW IP level.
153 * Unlike BSD Linux inherits IP options so you don't have to use 154 * Unlike BSD Linux inherits IP options so you don't have to use
154 * a raw socket for this. Instead we check rights in the calls. */ 155 * a raw socket for this. Instead we check rights in the calls. */
155 #define IP6T_BASE_CTL 64 /* base for firewall socket options */ 156 #define IP6T_BASE_CTL 64 /* base for firewall socket options */
156 157
157 #define IP6T_SO_SET_REPLACE (IP6T_BASE_CTL) 158 #define IP6T_SO_SET_REPLACE (IP6T_BASE_CTL)
158 #define IP6T_SO_SET_ADD_COUNTERS (IP6T_BASE_CTL + 1) 159 #define IP6T_SO_SET_ADD_COUNTERS (IP6T_BASE_CTL + 1)
159 #define IP6T_SO_SET_MAX IP6T_SO_SET_ADD_COUNTERS 160 #define IP6T_SO_SET_MAX IP6T_SO_SET_ADD_COUNTERS
160 161
161 #define IP6T_SO_GET_INFO (IP6T_BASE_CTL) 162 #define IP6T_SO_GET_INFO (IP6T_BASE_CTL)
162 #define IP6T_SO_GET_ENTRIES (IP6T_BASE_CTL + 1) 163 #define IP6T_SO_GET_ENTRIES (IP6T_BASE_CTL + 1)
163 #define IP6T_SO_GET_MAX IP6T_SO_GET_ENTRIES 164 #define IP6T_SO_GET_MAX IP6T_SO_GET_ENTRIES
164 165
165 /* CONTINUE verdict for targets */ 166 /* CONTINUE verdict for targets */
166 #define IP6T_CONTINUE 0xFFFFFFFF 167 #define IP6T_CONTINUE 0xFFFFFFFF
167 168
168 /* For standard target */ 169 /* For standard target */
169 #define IP6T_RETURN (-NF_REPEAT - 1) 170 #define IP6T_RETURN (-NF_REPEAT - 1)
170 171
171 /* TCP matching stuff */ 172 /* TCP matching stuff */
172 struct ip6t_tcp 173 struct ip6t_tcp
173 { 174 {
174 u_int16_t spts[2]; /* Source port range. */ 175 u_int16_t spts[2]; /* Source port range. */
175 u_int16_t dpts[2]; /* Destination port range. */ 176 u_int16_t dpts[2]; /* Destination port range. */
176 u_int8_t option; /* TCP Option iff non-zero*/ 177 u_int8_t option; /* TCP Option iff non-zero*/
177 u_int8_t flg_mask; /* TCP flags mask byte */ 178 u_int8_t flg_mask; /* TCP flags mask byte */
178 u_int8_t flg_cmp; /* TCP flags compare byte */ 179 u_int8_t flg_cmp; /* TCP flags compare byte */
179 u_int8_t invflags; /* Inverse flags */ 180 u_int8_t invflags; /* Inverse flags */
180 }; 181 };
181 182
182 /* Values for "inv" field in struct ipt_tcp. */ 183 /* Values for "inv" field in struct ipt_tcp. */
183 #define IP6T_TCP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ 184 #define IP6T_TCP_INV_SRCPT 0x01 /* Invert the sense of source ports. */
184 #define IP6T_TCP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ 185 #define IP6T_TCP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */
185 #define IP6T_TCP_INV_FLAGS 0x04 /* Invert the sense of TCP flags. */ 186 #define IP6T_TCP_INV_FLAGS 0x04 /* Invert the sense of TCP flags. */
186 #define IP6T_TCP_INV_OPTION 0x08 /* Invert the sense of option test. */ 187 #define IP6T_TCP_INV_OPTION 0x08 /* Invert the sense of option test. */
187 #define IP6T_TCP_INV_MASK 0x0F /* All possible flags. */ 188 #define IP6T_TCP_INV_MASK 0x0F /* All possible flags. */
188 189
189 /* UDP matching stuff */ 190 /* UDP matching stuff */
190 struct ip6t_udp 191 struct ip6t_udp
191 { 192 {
192 u_int16_t spts[2]; /* Source port range. */ 193 u_int16_t spts[2]; /* Source port range. */
193 u_int16_t dpts[2]; /* Destination port range. */ 194 u_int16_t dpts[2]; /* Destination port range. */
194 u_int8_t invflags; /* Inverse flags */ 195 u_int8_t invflags; /* Inverse flags */
195 }; 196 };
196 197
197 /* Values for "invflags" field in struct ipt_udp. */ 198 /* Values for "invflags" field in struct ipt_udp. */
198 #define IP6T_UDP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ 199 #define IP6T_UDP_INV_SRCPT 0x01 /* Invert the sense of source ports. */
199 #define IP6T_UDP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ 200 #define IP6T_UDP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */
200 #define IP6T_UDP_INV_MASK 0x03 /* All possible flags. */ 201 #define IP6T_UDP_INV_MASK 0x03 /* All possible flags. */
201 202
202 /* ICMP matching stuff */ 203 /* ICMP matching stuff */
203 struct ip6t_icmp 204 struct ip6t_icmp
204 { 205 {
205 u_int8_t type; /* type to match */ 206 u_int8_t type; /* type to match */
206 u_int8_t code[2]; /* range of code */ 207 u_int8_t code[2]; /* range of code */
207 u_int8_t invflags; /* Inverse flags */ 208 u_int8_t invflags; /* Inverse flags */
208 }; 209 };
209 210
210 /* Values for "inv" field for struct ipt_icmp. */ 211 /* Values for "inv" field for struct ipt_icmp. */
211 #define IP6T_ICMP_INV 0x01 /* Invert the sense of type/code test */ 212 #define IP6T_ICMP_INV 0x01 /* Invert the sense of type/code test */
212 213
213 /* The argument to IP6T_SO_GET_INFO */ 214 /* The argument to IP6T_SO_GET_INFO */
214 struct ip6t_getinfo 215 struct ip6t_getinfo
215 { 216 {
216 /* Which table: caller fills this in. */ 217 /* Which table: caller fills this in. */
217 char name[IP6T_TABLE_MAXNAMELEN]; 218 char name[IP6T_TABLE_MAXNAMELEN];
218 219
219 /* Kernel fills these in. */ 220 /* Kernel fills these in. */
220 /* Which hook entry points are valid: bitmask */ 221 /* Which hook entry points are valid: bitmask */
221 unsigned int valid_hooks; 222 unsigned int valid_hooks;
222 223
223 /* Hook entry points: one per netfilter hook. */ 224 /* Hook entry points: one per netfilter hook. */
224 unsigned int hook_entry[NF_IP6_NUMHOOKS]; 225 unsigned int hook_entry[NF_IP6_NUMHOOKS];
225 226
226 /* Underflow points. */ 227 /* Underflow points. */
227 unsigned int underflow[NF_IP6_NUMHOOKS]; 228 unsigned int underflow[NF_IP6_NUMHOOKS];
228 229
229 /* Number of entries */ 230 /* Number of entries */
230 unsigned int num_entries; 231 unsigned int num_entries;
231 232
232 /* Size of entries. */ 233 /* Size of entries. */
233 unsigned int size; 234 unsigned int size;
234 }; 235 };
235 236
236 /* The argument to IP6T_SO_SET_REPLACE. */ 237 /* The argument to IP6T_SO_SET_REPLACE. */
237 struct ip6t_replace 238 struct ip6t_replace
238 { 239 {
239 /* Which table. */ 240 /* Which table. */
240 char name[IP6T_TABLE_MAXNAMELEN]; 241 char name[IP6T_TABLE_MAXNAMELEN];
241 242
242 /* Which hook entry points are valid: bitmask. You can't 243 /* Which hook entry points are valid: bitmask. You can't
243 change this. */ 244 change this. */
244 unsigned int valid_hooks; 245 unsigned int valid_hooks;
245 246
246 /* Number of entries */ 247 /* Number of entries */
247 unsigned int num_entries; 248 unsigned int num_entries;
248 249
249 /* Total size of new entries */ 250 /* Total size of new entries */
250 unsigned int size; 251 unsigned int size;
251 252
252 /* Hook entry points. */ 253 /* Hook entry points. */
253 unsigned int hook_entry[NF_IP6_NUMHOOKS]; 254 unsigned int hook_entry[NF_IP6_NUMHOOKS];
254 255
255 /* Underflow points. */ 256 /* Underflow points. */
256 unsigned int underflow[NF_IP6_NUMHOOKS]; 257 unsigned int underflow[NF_IP6_NUMHOOKS];
257 258
258 /* Information about old entries: */ 259 /* Information about old entries: */
259 /* Number of counters (must be equal to current number of entries). */ 260 /* Number of counters (must be equal to current number of entries). */
260 unsigned int num_counters; 261 unsigned int num_counters;
261 /* The old entries' counters. */ 262 /* The old entries' counters. */
262 struct ip6t_counters __user *counters; 263 struct ip6t_counters __user *counters;
263 264
264 /* The entries (hang off end: not really an array). */ 265 /* The entries (hang off end: not really an array). */
265 struct ip6t_entry entries[0]; 266 struct ip6t_entry entries[0];
266 }; 267 };
267 268
268 /* The argument to IP6T_SO_ADD_COUNTERS. */ 269 /* The argument to IP6T_SO_ADD_COUNTERS. */
269 struct ip6t_counters_info 270 struct ip6t_counters_info
270 { 271 {
271 /* Which table. */ 272 /* Which table. */
272 char name[IP6T_TABLE_MAXNAMELEN]; 273 char name[IP6T_TABLE_MAXNAMELEN];
273 274
274 unsigned int num_counters; 275 unsigned int num_counters;
275 276
276 /* The counters (actually `number' of these). */ 277 /* The counters (actually `number' of these). */
277 struct ip6t_counters counters[0]; 278 struct ip6t_counters counters[0];
278 }; 279 };
279 280
280 /* The argument to IP6T_SO_GET_ENTRIES. */ 281 /* The argument to IP6T_SO_GET_ENTRIES. */
281 struct ip6t_get_entries 282 struct ip6t_get_entries
282 { 283 {
283 /* Which table: user fills this in. */ 284 /* Which table: user fills this in. */
284 char name[IP6T_TABLE_MAXNAMELEN]; 285 char name[IP6T_TABLE_MAXNAMELEN];
285 286
286 /* User fills this in: total entry size. */ 287 /* User fills this in: total entry size. */
287 unsigned int size; 288 unsigned int size;
288 289
289 /* The entries. */ 290 /* The entries. */
290 struct ip6t_entry entrytable[0]; 291 struct ip6t_entry entrytable[0];
291 }; 292 };
292 293
293 /* Standard return verdict, or do jump. */ 294 /* Standard return verdict, or do jump. */
294 #define IP6T_STANDARD_TARGET "" 295 #define IP6T_STANDARD_TARGET ""
295 /* Error verdict. */ 296 /* Error verdict. */
296 #define IP6T_ERROR_TARGET "ERROR" 297 #define IP6T_ERROR_TARGET "ERROR"
297 298
298 /* Helper functions */ 299 /* Helper functions */
299 static __inline__ struct ip6t_entry_target * 300 static __inline__ struct ip6t_entry_target *
300 ip6t_get_target(struct ip6t_entry *e) 301 ip6t_get_target(struct ip6t_entry *e)
301 { 302 {
302 return (void *)e + e->target_offset; 303 return (void *)e + e->target_offset;
303 } 304 }
304 305
305 /* fn returns 0 to continue iteration */ 306 /* fn returns 0 to continue iteration */
306 #define IP6T_MATCH_ITERATE(e, fn, args...) \ 307 #define IP6T_MATCH_ITERATE(e, fn, args...) \
307 ({ \ 308 ({ \
308 unsigned int __i; \ 309 unsigned int __i; \
309 int __ret = 0; \ 310 int __ret = 0; \
310 struct ip6t_entry_match *__m; \ 311 struct ip6t_entry_match *__m; \
311 \ 312 \
312 for (__i = sizeof(struct ip6t_entry); \ 313 for (__i = sizeof(struct ip6t_entry); \
313 __i < (e)->target_offset; \ 314 __i < (e)->target_offset; \
314 __i += __m->u.match_size) { \ 315 __i += __m->u.match_size) { \
315 __m = (void *)(e) + __i; \ 316 __m = (void *)(e) + __i; \
316 \ 317 \
317 __ret = fn(__m , ## args); \ 318 __ret = fn(__m , ## args); \
318 if (__ret != 0) \ 319 if (__ret != 0) \
319 break; \ 320 break; \
320 } \ 321 } \
321 __ret; \ 322 __ret; \
322 }) 323 })
323 324
324 /* fn returns 0 to continue iteration */ 325 /* fn returns 0 to continue iteration */
325 #define IP6T_ENTRY_ITERATE(entries, size, fn, args...) \ 326 #define IP6T_ENTRY_ITERATE(entries, size, fn, args...) \
326 ({ \ 327 ({ \
327 unsigned int __i; \ 328 unsigned int __i; \
328 int __ret = 0; \ 329 int __ret = 0; \
329 struct ip6t_entry *__e; \ 330 struct ip6t_entry *__e; \
330 \ 331 \
331 for (__i = 0; __i < (size); __i += __e->next_offset) { \ 332 for (__i = 0; __i < (size); __i += __e->next_offset) { \
332 __e = (void *)(entries) + __i; \ 333 __e = (void *)(entries) + __i; \
333 \ 334 \
334 __ret = fn(__e , ## args); \ 335 __ret = fn(__e , ## args); \
335 if (__ret != 0) \ 336 if (__ret != 0) \
336 break; \ 337 break; \
337 } \ 338 } \
338 __ret; \ 339 __ret; \
339 }) 340 })
340 341
341 /* 342 /*
342 * Main firewall chains definitions and global var's definitions. 343 * Main firewall chains definitions and global var's definitions.
343 */ 344 */
344 345
345 #ifdef __KERNEL__ 346 #ifdef __KERNEL__
346 347
347 #include <linux/init.h> 348 #include <linux/init.h>
348 extern void ip6t_init(void) __init; 349 extern void ip6t_init(void) __init;
349 350
350 struct ip6t_match 351 struct ip6t_match
351 { 352 {
352 struct list_head list; 353 struct list_head list;
353 354
354 const char name[IP6T_FUNCTION_MAXNAMELEN]; 355 const char name[IP6T_FUNCTION_MAXNAMELEN];
355 356
356 /* Return true or false: return FALSE and set *hotdrop = 1 to 357 /* Return true or false: return FALSE and set *hotdrop = 1 to
357 force immediate packet drop. */ 358 force immediate packet drop. */
358 /* Arguments changed since 2.6.9, as this must now handle 359 /* Arguments changed since 2.6.9, as this must now handle
359 non-linear skb, using skb_header_pointer and 360 non-linear skb, using skb_header_pointer and
360 skb_ip_make_writable. */ 361 skb_ip_make_writable. */
361 int (*match)(const struct sk_buff *skb, 362 int (*match)(const struct sk_buff *skb,
362 const struct net_device *in, 363 const struct net_device *in,
363 const struct net_device *out, 364 const struct net_device *out,
364 const void *matchinfo, 365 const void *matchinfo,
365 int offset, 366 int offset,
366 unsigned int protoff, 367 unsigned int protoff,
367 int *hotdrop); 368 int *hotdrop);
368 369
369 /* Called when user tries to insert an entry of this type. */ 370 /* Called when user tries to insert an entry of this type. */
370 /* Should return true or false. */ 371 /* Should return true or false. */
371 int (*checkentry)(const char *tablename, 372 int (*checkentry)(const char *tablename,
372 const struct ip6t_ip6 *ip, 373 const struct ip6t_ip6 *ip,
373 void *matchinfo, 374 void *matchinfo,
374 unsigned int matchinfosize, 375 unsigned int matchinfosize,
375 unsigned int hook_mask); 376 unsigned int hook_mask);
376 377
377 /* Called when entry of this type deleted. */ 378 /* Called when entry of this type deleted. */
378 void (*destroy)(void *matchinfo, unsigned int matchinfosize); 379 void (*destroy)(void *matchinfo, unsigned int matchinfosize);
379 380
380 /* Set this to THIS_MODULE if you are a module, otherwise NULL */ 381 /* Set this to THIS_MODULE if you are a module, otherwise NULL */
381 struct module *me; 382 struct module *me;
382 }; 383 };
383 384
384 /* Registration hooks for targets. */ 385 /* Registration hooks for targets. */
385 struct ip6t_target 386 struct ip6t_target
386 { 387 {
387 struct list_head list; 388 struct list_head list;
388 389
389 const char name[IP6T_FUNCTION_MAXNAMELEN]; 390 const char name[IP6T_FUNCTION_MAXNAMELEN];
390 391
391 /* Returns verdict. Argument order changed since 2.6.9, as this 392 /* Returns verdict. Argument order changed since 2.6.9, as this
392 must now handle non-linear skbs, using skb_copy_bits and 393 must now handle non-linear skbs, using skb_copy_bits and
393 skb_ip_make_writable. */ 394 skb_ip_make_writable. */
394 unsigned int (*target)(struct sk_buff **pskb, 395 unsigned int (*target)(struct sk_buff **pskb,
395 const struct net_device *in, 396 const struct net_device *in,
396 const struct net_device *out, 397 const struct net_device *out,
397 unsigned int hooknum, 398 unsigned int hooknum,
398 const void *targinfo, 399 const void *targinfo,
399 void *userdata); 400 void *userdata);
400 401
401 /* Called when user tries to insert an entry of this type: 402 /* Called when user tries to insert an entry of this type:
402 hook_mask is a bitmask of hooks from which it can be 403 hook_mask is a bitmask of hooks from which it can be
403 called. */ 404 called. */
404 /* Should return true or false. */ 405 /* Should return true or false. */
405 int (*checkentry)(const char *tablename, 406 int (*checkentry)(const char *tablename,
406 const struct ip6t_entry *e, 407 const struct ip6t_entry *e,
407 void *targinfo, 408 void *targinfo,
408 unsigned int targinfosize, 409 unsigned int targinfosize,
409 unsigned int hook_mask); 410 unsigned int hook_mask);
410 411
411 /* Called when entry of this type deleted. */ 412 /* Called when entry of this type deleted. */
412 void (*destroy)(void *targinfo, unsigned int targinfosize); 413 void (*destroy)(void *targinfo, unsigned int targinfosize);
413 414
414 /* Set this to THIS_MODULE if you are a module, otherwise NULL */ 415 /* Set this to THIS_MODULE if you are a module, otherwise NULL */
415 struct module *me; 416 struct module *me;
416 }; 417 };
417 418
418 extern int ip6t_register_target(struct ip6t_target *target); 419 extern int ip6t_register_target(struct ip6t_target *target);
419 extern void ip6t_unregister_target(struct ip6t_target *target); 420 extern void ip6t_unregister_target(struct ip6t_target *target);
420 421
421 extern int ip6t_register_match(struct ip6t_match *match); 422 extern int ip6t_register_match(struct ip6t_match *match);
422 extern void ip6t_unregister_match(struct ip6t_match *match); 423 extern void ip6t_unregister_match(struct ip6t_match *match);
423 424
424 /* Furniture shopping... */ 425 /* Furniture shopping... */
425 struct ip6t_table 426 struct ip6t_table
426 { 427 {
427 struct list_head list; 428 struct list_head list;
428 429
429 /* A unique name... */ 430 /* A unique name... */
430 char name[IP6T_TABLE_MAXNAMELEN]; 431 char name[IP6T_TABLE_MAXNAMELEN];
431 432
432 /* What hooks you will enter on */ 433 /* What hooks you will enter on */
433 unsigned int valid_hooks; 434 unsigned int valid_hooks;
434 435
435 /* Lock for the curtain */ 436 /* Lock for the curtain */
436 rwlock_t lock; 437 rwlock_t lock;
437 438
438 /* Man behind the curtain... */ 439 /* Man behind the curtain... */
439 struct ip6t_table_info *private; 440 struct ip6t_table_info *private;
440 441
441 /* Set this to THIS_MODULE if you are a module, otherwise NULL */ 442 /* Set this to THIS_MODULE if you are a module, otherwise NULL */
442 struct module *me; 443 struct module *me;
443 }; 444 };
444 445
445 extern int ip6t_register_table(struct ip6t_table *table, 446 extern int ip6t_register_table(struct ip6t_table *table,
446 const struct ip6t_replace *repl); 447 const struct ip6t_replace *repl);
447 extern void ip6t_unregister_table(struct ip6t_table *table); 448 extern void ip6t_unregister_table(struct ip6t_table *table);
448 extern unsigned int ip6t_do_table(struct sk_buff **pskb, 449 extern unsigned int ip6t_do_table(struct sk_buff **pskb,
449 unsigned int hook, 450 unsigned int hook,
450 const struct net_device *in, 451 const struct net_device *in,
451 const struct net_device *out, 452 const struct net_device *out,
452 struct ip6t_table *table, 453 struct ip6t_table *table,
453 void *userdata); 454 void *userdata);
454 455
455 /* Check for an extension */ 456 /* Check for an extension */
456 extern int ip6t_ext_hdr(u8 nexthdr); 457 extern int ip6t_ext_hdr(u8 nexthdr);
457 458
458 #define IP6T_ALIGN(s) (((s) + (__alignof__(struct ip6t_entry)-1)) & ~(__alignof__(struct ip6t_entry)-1)) 459 #define IP6T_ALIGN(s) (((s) + (__alignof__(struct ip6t_entry)-1)) & ~(__alignof__(struct ip6t_entry)-1))
459 460
460 #endif /*__KERNEL__*/ 461 #endif /*__KERNEL__*/
461 #endif /* _IP6_TABLES_H */ 462 #endif /* _IP6_TABLES_H */
462 463
net/ipv4/netfilter/ip_tables.c
1 /* 1 /*
2 * Packet matching code. 2 * Packet matching code.
3 * 3 *
4 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling 4 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
5 * Copyright (C) 2000-2004 Netfilter Core Team <coreteam@netfilter.org> 5 * Copyright (C) 2000-2004 Netfilter Core Team <coreteam@netfilter.org>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation. 9 * published by the Free Software Foundation.
10 * 10 *
11 * 19 Jan 2002 Harald Welte <laforge@gnumonks.org> 11 * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
12 * - increase module usage count as soon as we have rules inside 12 * - increase module usage count as soon as we have rules inside
13 * a table 13 * a table
14 */ 14 */
15 #include <linux/config.h> 15 #include <linux/config.h>
16 #include <linux/cache.h> 16 #include <linux/cache.h>
17 #include <linux/skbuff.h> 17 #include <linux/skbuff.h>
18 #include <linux/kmod.h> 18 #include <linux/kmod.h>
19 #include <linux/vmalloc.h> 19 #include <linux/vmalloc.h>
20 #include <linux/netdevice.h> 20 #include <linux/netdevice.h>
21 #include <linux/module.h> 21 #include <linux/module.h>
22 #include <linux/tcp.h> 22 #include <linux/tcp.h>
23 #include <linux/udp.h> 23 #include <linux/udp.h>
24 #include <linux/icmp.h> 24 #include <linux/icmp.h>
25 #include <net/ip.h> 25 #include <net/ip.h>
26 #include <asm/uaccess.h> 26 #include <asm/uaccess.h>
27 #include <asm/semaphore.h> 27 #include <asm/semaphore.h>
28 #include <linux/proc_fs.h> 28 #include <linux/proc_fs.h>
29 #include <linux/err.h> 29 #include <linux/err.h>
30 30
31 #include <linux/netfilter_ipv4/ip_tables.h> 31 #include <linux/netfilter_ipv4/ip_tables.h>
32 32
33 MODULE_LICENSE("GPL"); 33 MODULE_LICENSE("GPL");
34 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 34 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
35 MODULE_DESCRIPTION("IPv4 packet filter"); 35 MODULE_DESCRIPTION("IPv4 packet filter");
36 36
37 /*#define DEBUG_IP_FIREWALL*/ 37 /*#define DEBUG_IP_FIREWALL*/
38 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */ 38 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
39 /*#define DEBUG_IP_FIREWALL_USER*/ 39 /*#define DEBUG_IP_FIREWALL_USER*/
40 40
41 #ifdef DEBUG_IP_FIREWALL 41 #ifdef DEBUG_IP_FIREWALL
42 #define dprintf(format, args...) printk(format , ## args) 42 #define dprintf(format, args...) printk(format , ## args)
43 #else 43 #else
44 #define dprintf(format, args...) 44 #define dprintf(format, args...)
45 #endif 45 #endif
46 46
47 #ifdef DEBUG_IP_FIREWALL_USER 47 #ifdef DEBUG_IP_FIREWALL_USER
48 #define duprintf(format, args...) printk(format , ## args) 48 #define duprintf(format, args...) printk(format , ## args)
49 #else 49 #else
50 #define duprintf(format, args...) 50 #define duprintf(format, args...)
51 #endif 51 #endif
52 52
53 #ifdef CONFIG_NETFILTER_DEBUG 53 #ifdef CONFIG_NETFILTER_DEBUG
54 #define IP_NF_ASSERT(x) \ 54 #define IP_NF_ASSERT(x) \
55 do { \ 55 do { \
56 if (!(x)) \ 56 if (!(x)) \
57 printk("IP_NF_ASSERT: %s:%s:%u\n", \ 57 printk("IP_NF_ASSERT: %s:%s:%u\n", \
58 __FUNCTION__, __FILE__, __LINE__); \ 58 __FUNCTION__, __FILE__, __LINE__); \
59 } while(0) 59 } while(0)
60 #else 60 #else
61 #define IP_NF_ASSERT(x) 61 #define IP_NF_ASSERT(x)
62 #endif 62 #endif
63 #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) 63 #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
64 64
65 static DECLARE_MUTEX(ipt_mutex); 65 static DECLARE_MUTEX(ipt_mutex);
66 66
67 /* Must have mutex */ 67 /* Must have mutex */
68 #define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0) 68 #define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
69 #define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0) 69 #define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
70 #include <linux/netfilter_ipv4/listhelp.h> 70 #include <linux/netfilter_ipv4/listhelp.h>
71 71
72 #if 0 72 #if 0
73 /* All the better to debug you with... */ 73 /* All the better to debug you with... */
74 #define static 74 #define static
75 #define inline 75 #define inline
76 #endif 76 #endif
77 77
78 /* 78 /*
79 We keep a set of rules for each CPU, so we can avoid write-locking 79 We keep a set of rules for each CPU, so we can avoid write-locking
80 them in the softirq when updating the counters and therefore 80 them in the softirq when updating the counters and therefore
81 only need to read-lock in the softirq; doing a write_lock_bh() in user 81 only need to read-lock in the softirq; doing a write_lock_bh() in user
82 context stops packets coming through and allows user context to read 82 context stops packets coming through and allows user context to read
83 the counters or update the rules. 83 the counters or update the rules.
84 84
85 To be cache friendly on SMP, we arrange them like so: 85 To be cache friendly on SMP, we arrange them like so:
86 [ n-entries ] 86 [ n-entries ]
87 ... cache-align padding ... 87 ... cache-align padding ...
88 [ n-entries ] 88 [ n-entries ]
89 89
90 Hence the start of any table is given by get_table() below. */ 90 Hence the start of any table is given by get_table() below. */
91 91
92 /* The table itself */ 92 /* The table itself */
93 struct ipt_table_info 93 struct ipt_table_info
94 { 94 {
95 /* Size per table */ 95 /* Size per table */
96 unsigned int size; 96 unsigned int size;
97 /* Number of entries: FIXME. --RR */ 97 /* Number of entries: FIXME. --RR */
98 unsigned int number; 98 unsigned int number;
99 /* Initial number of entries. Needed for module usage count */ 99 /* Initial number of entries. Needed for module usage count */
100 unsigned int initial_entries; 100 unsigned int initial_entries;
101 101
102 /* Entry points and underflows */ 102 /* Entry points and underflows */
103 unsigned int hook_entry[NF_IP_NUMHOOKS]; 103 unsigned int hook_entry[NF_IP_NUMHOOKS];
104 unsigned int underflow[NF_IP_NUMHOOKS]; 104 unsigned int underflow[NF_IP_NUMHOOKS];
105 105
106 /* ipt_entry tables: one per CPU */ 106 /* ipt_entry tables: one per CPU */
107 char entries[0] ____cacheline_aligned; 107 char entries[0] ____cacheline_aligned;
108 }; 108 };
109 109
110 static LIST_HEAD(ipt_target); 110 static LIST_HEAD(ipt_target);
111 static LIST_HEAD(ipt_match); 111 static LIST_HEAD(ipt_match);
112 static LIST_HEAD(ipt_tables); 112 static LIST_HEAD(ipt_tables);
113 #define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0) 113 #define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0)
114 114
115 #ifdef CONFIG_SMP 115 #ifdef CONFIG_SMP
116 #define TABLE_OFFSET(t,p) (SMP_ALIGN((t)->size)*(p)) 116 #define TABLE_OFFSET(t,p) (SMP_ALIGN((t)->size)*(p))
117 #else 117 #else
118 #define TABLE_OFFSET(t,p) 0 118 #define TABLE_OFFSET(t,p) 0
119 #endif 119 #endif
120 120
121 #if 0 121 #if 0
122 #define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0) 122 #define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0)
123 #define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; }) 123 #define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; })
124 #define up(x) do { printk("UP:%u:" #x "\n", __LINE__); up(x); } while(0) 124 #define up(x) do { printk("UP:%u:" #x "\n", __LINE__); up(x); } while(0)
125 #endif 125 #endif
126 126
127 /* Returns whether matches rule or not. */ 127 /* Returns whether matches rule or not. */
128 static inline int 128 static inline int
129 ip_packet_match(const struct iphdr *ip, 129 ip_packet_match(const struct iphdr *ip,
130 const char *indev, 130 const char *indev,
131 const char *outdev, 131 const char *outdev,
132 const struct ipt_ip *ipinfo, 132 const struct ipt_ip *ipinfo,
133 int isfrag) 133 int isfrag)
134 { 134 {
135 size_t i; 135 size_t i;
136 unsigned long ret; 136 unsigned long ret;
137 137
138 #define FWINV(bool,invflg) ((bool) ^ !!(ipinfo->invflags & invflg)) 138 #define FWINV(bool,invflg) ((bool) ^ !!(ipinfo->invflags & invflg))
139 139
140 if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr, 140 if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
141 IPT_INV_SRCIP) 141 IPT_INV_SRCIP)
142 || FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr, 142 || FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
143 IPT_INV_DSTIP)) { 143 IPT_INV_DSTIP)) {
144 dprintf("Source or dest mismatch.\n"); 144 dprintf("Source or dest mismatch.\n");
145 145
146 dprintf("SRC: %u.%u.%u.%u. Mask: %u.%u.%u.%u. Target: %u.%u.%u.%u.%s\n", 146 dprintf("SRC: %u.%u.%u.%u. Mask: %u.%u.%u.%u. Target: %u.%u.%u.%u.%s\n",
147 NIPQUAD(ip->saddr), 147 NIPQUAD(ip->saddr),
148 NIPQUAD(ipinfo->smsk.s_addr), 148 NIPQUAD(ipinfo->smsk.s_addr),
149 NIPQUAD(ipinfo->src.s_addr), 149 NIPQUAD(ipinfo->src.s_addr),
150 ipinfo->invflags & IPT_INV_SRCIP ? " (INV)" : ""); 150 ipinfo->invflags & IPT_INV_SRCIP ? " (INV)" : "");
151 dprintf("DST: %u.%u.%u.%u Mask: %u.%u.%u.%u Target: %u.%u.%u.%u.%s\n", 151 dprintf("DST: %u.%u.%u.%u Mask: %u.%u.%u.%u Target: %u.%u.%u.%u.%s\n",
152 NIPQUAD(ip->daddr), 152 NIPQUAD(ip->daddr),
153 NIPQUAD(ipinfo->dmsk.s_addr), 153 NIPQUAD(ipinfo->dmsk.s_addr),
154 NIPQUAD(ipinfo->dst.s_addr), 154 NIPQUAD(ipinfo->dst.s_addr),
155 ipinfo->invflags & IPT_INV_DSTIP ? " (INV)" : ""); 155 ipinfo->invflags & IPT_INV_DSTIP ? " (INV)" : "");
156 return 0; 156 return 0;
157 } 157 }
158 158
159 /* Look for ifname matches; this should unroll nicely. */ 159 /* Look for ifname matches; this should unroll nicely. */
160 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) { 160 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
161 ret |= (((const unsigned long *)indev)[i] 161 ret |= (((const unsigned long *)indev)[i]
162 ^ ((const unsigned long *)ipinfo->iniface)[i]) 162 ^ ((const unsigned long *)ipinfo->iniface)[i])
163 & ((const unsigned long *)ipinfo->iniface_mask)[i]; 163 & ((const unsigned long *)ipinfo->iniface_mask)[i];
164 } 164 }
165 165
166 if (FWINV(ret != 0, IPT_INV_VIA_IN)) { 166 if (FWINV(ret != 0, IPT_INV_VIA_IN)) {
167 dprintf("VIA in mismatch (%s vs %s).%s\n", 167 dprintf("VIA in mismatch (%s vs %s).%s\n",
168 indev, ipinfo->iniface, 168 indev, ipinfo->iniface,
169 ipinfo->invflags&IPT_INV_VIA_IN ?" (INV)":""); 169 ipinfo->invflags&IPT_INV_VIA_IN ?" (INV)":"");
170 return 0; 170 return 0;
171 } 171 }
172 172
173 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) { 173 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
174 ret |= (((const unsigned long *)outdev)[i] 174 ret |= (((const unsigned long *)outdev)[i]
175 ^ ((const unsigned long *)ipinfo->outiface)[i]) 175 ^ ((const unsigned long *)ipinfo->outiface)[i])
176 & ((const unsigned long *)ipinfo->outiface_mask)[i]; 176 & ((const unsigned long *)ipinfo->outiface_mask)[i];
177 } 177 }
178 178
179 if (FWINV(ret != 0, IPT_INV_VIA_OUT)) { 179 if (FWINV(ret != 0, IPT_INV_VIA_OUT)) {
180 dprintf("VIA out mismatch (%s vs %s).%s\n", 180 dprintf("VIA out mismatch (%s vs %s).%s\n",
181 outdev, ipinfo->outiface, 181 outdev, ipinfo->outiface,
182 ipinfo->invflags&IPT_INV_VIA_OUT ?" (INV)":""); 182 ipinfo->invflags&IPT_INV_VIA_OUT ?" (INV)":"");
183 return 0; 183 return 0;
184 } 184 }
185 185
186 /* Check specific protocol */ 186 /* Check specific protocol */
187 if (ipinfo->proto 187 if (ipinfo->proto
188 && FWINV(ip->protocol != ipinfo->proto, IPT_INV_PROTO)) { 188 && FWINV(ip->protocol != ipinfo->proto, IPT_INV_PROTO)) {
189 dprintf("Packet protocol %hi does not match %hi.%s\n", 189 dprintf("Packet protocol %hi does not match %hi.%s\n",
190 ip->protocol, ipinfo->proto, 190 ip->protocol, ipinfo->proto,
191 ipinfo->invflags&IPT_INV_PROTO ? " (INV)":""); 191 ipinfo->invflags&IPT_INV_PROTO ? " (INV)":"");
192 return 0; 192 return 0;
193 } 193 }
194 194
195 /* If we have a fragment rule but the packet is not a fragment 195 /* If we have a fragment rule but the packet is not a fragment
196 * then we return zero */ 196 * then we return zero */
197 if (FWINV((ipinfo->flags&IPT_F_FRAG) && !isfrag, IPT_INV_FRAG)) { 197 if (FWINV((ipinfo->flags&IPT_F_FRAG) && !isfrag, IPT_INV_FRAG)) {
198 dprintf("Fragment rule but not fragment.%s\n", 198 dprintf("Fragment rule but not fragment.%s\n",
199 ipinfo->invflags & IPT_INV_FRAG ? " (INV)" : ""); 199 ipinfo->invflags & IPT_INV_FRAG ? " (INV)" : "");
200 return 0; 200 return 0;
201 } 201 }
202 202
203 return 1; 203 return 1;
204 } 204 }
205 205
206 static inline int 206 static inline int
207 ip_checkentry(const struct ipt_ip *ip) 207 ip_checkentry(const struct ipt_ip *ip)
208 { 208 {
209 if (ip->flags & ~IPT_F_MASK) { 209 if (ip->flags & ~IPT_F_MASK) {
210 duprintf("Unknown flag bits set: %08X\n", 210 duprintf("Unknown flag bits set: %08X\n",
211 ip->flags & ~IPT_F_MASK); 211 ip->flags & ~IPT_F_MASK);
212 return 0; 212 return 0;
213 } 213 }
214 if (ip->invflags & ~IPT_INV_MASK) { 214 if (ip->invflags & ~IPT_INV_MASK) {
215 duprintf("Unknown invflag bits set: %08X\n", 215 duprintf("Unknown invflag bits set: %08X\n",
216 ip->invflags & ~IPT_INV_MASK); 216 ip->invflags & ~IPT_INV_MASK);
217 return 0; 217 return 0;
218 } 218 }
219 return 1; 219 return 1;
220 } 220 }
221 221
222 static unsigned int 222 static unsigned int
223 ipt_error(struct sk_buff **pskb, 223 ipt_error(struct sk_buff **pskb,
224 const struct net_device *in, 224 const struct net_device *in,
225 const struct net_device *out, 225 const struct net_device *out,
226 unsigned int hooknum, 226 unsigned int hooknum,
227 const void *targinfo, 227 const void *targinfo,
228 void *userinfo) 228 void *userinfo)
229 { 229 {
230 if (net_ratelimit()) 230 if (net_ratelimit())
231 printk("ip_tables: error: `%s'\n", (char *)targinfo); 231 printk("ip_tables: error: `%s'\n", (char *)targinfo);
232 232
233 return NF_DROP; 233 return NF_DROP;
234 } 234 }
235 235
236 static inline 236 static inline
237 int do_match(struct ipt_entry_match *m, 237 int do_match(struct ipt_entry_match *m,
238 const struct sk_buff *skb, 238 const struct sk_buff *skb,
239 const struct net_device *in, 239 const struct net_device *in,
240 const struct net_device *out, 240 const struct net_device *out,
241 int offset, 241 int offset,
242 int *hotdrop) 242 int *hotdrop)
243 { 243 {
244 /* Stop iteration if it doesn't match */ 244 /* Stop iteration if it doesn't match */
245 if (!m->u.kernel.match->match(skb, in, out, m->data, offset, hotdrop)) 245 if (!m->u.kernel.match->match(skb, in, out, m->data, offset, hotdrop))
246 return 1; 246 return 1;
247 else 247 else
248 return 0; 248 return 0;
249 } 249 }
250 250
251 static inline struct ipt_entry * 251 static inline struct ipt_entry *
252 get_entry(void *base, unsigned int offset) 252 get_entry(void *base, unsigned int offset)
253 { 253 {
254 return (struct ipt_entry *)(base + offset); 254 return (struct ipt_entry *)(base + offset);
255 } 255 }
256 256
257 /* Returns one of the generic firewall policies, like NF_ACCEPT. */ 257 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
258 unsigned int 258 unsigned int
259 ipt_do_table(struct sk_buff **pskb, 259 ipt_do_table(struct sk_buff **pskb,
260 unsigned int hook, 260 unsigned int hook,
261 const struct net_device *in, 261 const struct net_device *in,
262 const struct net_device *out, 262 const struct net_device *out,
263 struct ipt_table *table, 263 struct ipt_table *table,
264 void *userdata) 264 void *userdata)
265 { 265 {
266 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); 266 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
267 u_int16_t offset; 267 u_int16_t offset;
268 struct iphdr *ip; 268 struct iphdr *ip;
269 u_int16_t datalen; 269 u_int16_t datalen;
270 int hotdrop = 0; 270 int hotdrop = 0;
271 /* Initializing verdict to NF_DROP keeps gcc happy. */ 271 /* Initializing verdict to NF_DROP keeps gcc happy. */
272 unsigned int verdict = NF_DROP; 272 unsigned int verdict = NF_DROP;
273 const char *indev, *outdev; 273 const char *indev, *outdev;
274 void *table_base; 274 void *table_base;
275 struct ipt_entry *e, *back; 275 struct ipt_entry *e, *back;
276 276
277 /* Initialization */ 277 /* Initialization */
278 ip = (*pskb)->nh.iph; 278 ip = (*pskb)->nh.iph;
279 datalen = (*pskb)->len - ip->ihl * 4; 279 datalen = (*pskb)->len - ip->ihl * 4;
280 indev = in ? in->name : nulldevname; 280 indev = in ? in->name : nulldevname;
281 outdev = out ? out->name : nulldevname; 281 outdev = out ? out->name : nulldevname;
282 /* We handle fragments by dealing with the first fragment as 282 /* We handle fragments by dealing with the first fragment as
283 * if it was a normal packet. All other fragments are treated 283 * if it was a normal packet. All other fragments are treated
284 * normally, except that they will NEVER match rules that ask 284 * normally, except that they will NEVER match rules that ask
285 * things we don't know, ie. tcp syn flag or ports). If the 285 * things we don't know, ie. tcp syn flag or ports). If the
286 * rule is also a fragment-specific rule, non-fragments won't 286 * rule is also a fragment-specific rule, non-fragments won't
287 * match it. */ 287 * match it. */
288 offset = ntohs(ip->frag_off) & IP_OFFSET; 288 offset = ntohs(ip->frag_off) & IP_OFFSET;
289 289
290 read_lock_bh(&table->lock); 290 read_lock_bh(&table->lock);
291 IP_NF_ASSERT(table->valid_hooks & (1 << hook)); 291 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
292 table_base = (void *)table->private->entries 292 table_base = (void *)table->private->entries
293 + TABLE_OFFSET(table->private, smp_processor_id()); 293 + TABLE_OFFSET(table->private, smp_processor_id());
294 e = get_entry(table_base, table->private->hook_entry[hook]); 294 e = get_entry(table_base, table->private->hook_entry[hook]);
295 295
296 #ifdef CONFIG_NETFILTER_DEBUG 296 #ifdef CONFIG_NETFILTER_DEBUG
297 /* Check noone else using our table */ 297 /* Check noone else using our table */
298 if (((struct ipt_entry *)table_base)->comefrom != 0xdead57ac 298 if (((struct ipt_entry *)table_base)->comefrom != 0xdead57ac
299 && ((struct ipt_entry *)table_base)->comefrom != 0xeeeeeeec) { 299 && ((struct ipt_entry *)table_base)->comefrom != 0xeeeeeeec) {
300 printk("ASSERT: CPU #%u, %s comefrom(%p) = %X\n", 300 printk("ASSERT: CPU #%u, %s comefrom(%p) = %X\n",
301 smp_processor_id(), 301 smp_processor_id(),
302 table->name, 302 table->name,
303 &((struct ipt_entry *)table_base)->comefrom, 303 &((struct ipt_entry *)table_base)->comefrom,
304 ((struct ipt_entry *)table_base)->comefrom); 304 ((struct ipt_entry *)table_base)->comefrom);
305 } 305 }
306 ((struct ipt_entry *)table_base)->comefrom = 0x57acc001; 306 ((struct ipt_entry *)table_base)->comefrom = 0x57acc001;
307 #endif 307 #endif
308 308
309 /* For return from builtin chain */ 309 /* For return from builtin chain */
310 back = get_entry(table_base, table->private->underflow[hook]); 310 back = get_entry(table_base, table->private->underflow[hook]);
311 311
312 do { 312 do {
313 IP_NF_ASSERT(e); 313 IP_NF_ASSERT(e);
314 IP_NF_ASSERT(back); 314 IP_NF_ASSERT(back);
315 if (ip_packet_match(ip, indev, outdev, &e->ip, offset)) { 315 if (ip_packet_match(ip, indev, outdev, &e->ip, offset)) {
316 struct ipt_entry_target *t; 316 struct ipt_entry_target *t;
317 317
318 if (IPT_MATCH_ITERATE(e, do_match, 318 if (IPT_MATCH_ITERATE(e, do_match,
319 *pskb, in, out, 319 *pskb, in, out,
320 offset, &hotdrop) != 0) 320 offset, &hotdrop) != 0)
321 goto no_match; 321 goto no_match;
322 322
323 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1); 323 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
324 324
325 t = ipt_get_target(e); 325 t = ipt_get_target(e);
326 IP_NF_ASSERT(t->u.kernel.target); 326 IP_NF_ASSERT(t->u.kernel.target);
327 /* Standard target? */ 327 /* Standard target? */
328 if (!t->u.kernel.target->target) { 328 if (!t->u.kernel.target->target) {
329 int v; 329 int v;
330 330
331 v = ((struct ipt_standard_target *)t)->verdict; 331 v = ((struct ipt_standard_target *)t)->verdict;
332 if (v < 0) { 332 if (v < 0) {
333 /* Pop from stack? */ 333 /* Pop from stack? */
334 if (v != IPT_RETURN) { 334 if (v != IPT_RETURN) {
335 verdict = (unsigned)(-v) - 1; 335 verdict = (unsigned)(-v) - 1;
336 break; 336 break;
337 } 337 }
338 e = back; 338 e = back;
339 back = get_entry(table_base, 339 back = get_entry(table_base,
340 back->comefrom); 340 back->comefrom);
341 continue; 341 continue;
342 } 342 }
343 if (table_base + v 343 if (table_base + v != (void *)e + e->next_offset
344 != (void *)e + e->next_offset) { 344 && !(e->ip.flags & IPT_F_GOTO)) {
345 /* Save old back ptr in next entry */ 345 /* Save old back ptr in next entry */
346 struct ipt_entry *next 346 struct ipt_entry *next
347 = (void *)e + e->next_offset; 347 = (void *)e + e->next_offset;
348 next->comefrom 348 next->comefrom
349 = (void *)back - table_base; 349 = (void *)back - table_base;
350 /* set back pointer to next entry */ 350 /* set back pointer to next entry */
351 back = next; 351 back = next;
352 } 352 }
353 353
354 e = get_entry(table_base, v); 354 e = get_entry(table_base, v);
355 } else { 355 } else {
356 /* Targets which reenter must return 356 /* Targets which reenter must return
357 abs. verdicts */ 357 abs. verdicts */
358 #ifdef CONFIG_NETFILTER_DEBUG 358 #ifdef CONFIG_NETFILTER_DEBUG
359 ((struct ipt_entry *)table_base)->comefrom 359 ((struct ipt_entry *)table_base)->comefrom
360 = 0xeeeeeeec; 360 = 0xeeeeeeec;
361 #endif 361 #endif
362 verdict = t->u.kernel.target->target(pskb, 362 verdict = t->u.kernel.target->target(pskb,
363 in, out, 363 in, out,
364 hook, 364 hook,
365 t->data, 365 t->data,
366 userdata); 366 userdata);
367 367
368 #ifdef CONFIG_NETFILTER_DEBUG 368 #ifdef CONFIG_NETFILTER_DEBUG
369 if (((struct ipt_entry *)table_base)->comefrom 369 if (((struct ipt_entry *)table_base)->comefrom
370 != 0xeeeeeeec 370 != 0xeeeeeeec
371 && verdict == IPT_CONTINUE) { 371 && verdict == IPT_CONTINUE) {
372 printk("Target %s reentered!\n", 372 printk("Target %s reentered!\n",
373 t->u.kernel.target->name); 373 t->u.kernel.target->name);
374 verdict = NF_DROP; 374 verdict = NF_DROP;
375 } 375 }
376 ((struct ipt_entry *)table_base)->comefrom 376 ((struct ipt_entry *)table_base)->comefrom
377 = 0x57acc001; 377 = 0x57acc001;
378 #endif 378 #endif
379 /* Target might have changed stuff. */ 379 /* Target might have changed stuff. */
380 ip = (*pskb)->nh.iph; 380 ip = (*pskb)->nh.iph;
381 datalen = (*pskb)->len - ip->ihl * 4; 381 datalen = (*pskb)->len - ip->ihl * 4;
382 382
383 if (verdict == IPT_CONTINUE) 383 if (verdict == IPT_CONTINUE)
384 e = (void *)e + e->next_offset; 384 e = (void *)e + e->next_offset;
385 else 385 else
386 /* Verdict */ 386 /* Verdict */
387 break; 387 break;
388 } 388 }
389 } else { 389 } else {
390 390
391 no_match: 391 no_match:
392 e = (void *)e + e->next_offset; 392 e = (void *)e + e->next_offset;
393 } 393 }
394 } while (!hotdrop); 394 } while (!hotdrop);
395 395
396 #ifdef CONFIG_NETFILTER_DEBUG 396 #ifdef CONFIG_NETFILTER_DEBUG
397 ((struct ipt_entry *)table_base)->comefrom = 0xdead57ac; 397 ((struct ipt_entry *)table_base)->comefrom = 0xdead57ac;
398 #endif 398 #endif
399 read_unlock_bh(&table->lock); 399 read_unlock_bh(&table->lock);
400 400
401 #ifdef DEBUG_ALLOW_ALL 401 #ifdef DEBUG_ALLOW_ALL
402 return NF_ACCEPT; 402 return NF_ACCEPT;
403 #else 403 #else
404 if (hotdrop) 404 if (hotdrop)
405 return NF_DROP; 405 return NF_DROP;
406 else return verdict; 406 else return verdict;
407 #endif 407 #endif
408 } 408 }
409 409
410 /* 410 /*
411 * These are weird, but module loading must not be done with mutex 411 * These are weird, but module loading must not be done with mutex
412 * held (since they will register), and we have to have a single 412 * held (since they will register), and we have to have a single
413 * function to use try_then_request_module(). 413 * function to use try_then_request_module().
414 */ 414 */
415 415
416 /* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ 416 /* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
417 static inline struct ipt_table *find_table_lock(const char *name) 417 static inline struct ipt_table *find_table_lock(const char *name)
418 { 418 {
419 struct ipt_table *t; 419 struct ipt_table *t;
420 420
421 if (down_interruptible(&ipt_mutex) != 0) 421 if (down_interruptible(&ipt_mutex) != 0)
422 return ERR_PTR(-EINTR); 422 return ERR_PTR(-EINTR);
423 423
424 list_for_each_entry(t, &ipt_tables, list) 424 list_for_each_entry(t, &ipt_tables, list)
425 if (strcmp(t->name, name) == 0 && try_module_get(t->me)) 425 if (strcmp(t->name, name) == 0 && try_module_get(t->me))
426 return t; 426 return t;
427 up(&ipt_mutex); 427 up(&ipt_mutex);
428 return NULL; 428 return NULL;
429 } 429 }
430 430
431 /* Find match, grabs ref. Returns ERR_PTR() on error. */ 431 /* Find match, grabs ref. Returns ERR_PTR() on error. */
432 static inline struct ipt_match *find_match(const char *name, u8 revision) 432 static inline struct ipt_match *find_match(const char *name, u8 revision)
433 { 433 {
434 struct ipt_match *m; 434 struct ipt_match *m;
435 int err = 0; 435 int err = 0;
436 436
437 if (down_interruptible(&ipt_mutex) != 0) 437 if (down_interruptible(&ipt_mutex) != 0)
438 return ERR_PTR(-EINTR); 438 return ERR_PTR(-EINTR);
439 439
440 list_for_each_entry(m, &ipt_match, list) { 440 list_for_each_entry(m, &ipt_match, list) {
441 if (strcmp(m->name, name) == 0) { 441 if (strcmp(m->name, name) == 0) {
442 if (m->revision == revision) { 442 if (m->revision == revision) {
443 if (try_module_get(m->me)) { 443 if (try_module_get(m->me)) {
444 up(&ipt_mutex); 444 up(&ipt_mutex);
445 return m; 445 return m;
446 } 446 }
447 } else 447 } else
448 err = -EPROTOTYPE; /* Found something. */ 448 err = -EPROTOTYPE; /* Found something. */
449 } 449 }
450 } 450 }
451 up(&ipt_mutex); 451 up(&ipt_mutex);
452 return ERR_PTR(err); 452 return ERR_PTR(err);
453 } 453 }
454 454
455 /* Find target, grabs ref. Returns ERR_PTR() on error. */ 455 /* Find target, grabs ref. Returns ERR_PTR() on error. */
456 static inline struct ipt_target *find_target(const char *name, u8 revision) 456 static inline struct ipt_target *find_target(const char *name, u8 revision)
457 { 457 {
458 struct ipt_target *t; 458 struct ipt_target *t;
459 int err = 0; 459 int err = 0;
460 460
461 if (down_interruptible(&ipt_mutex) != 0) 461 if (down_interruptible(&ipt_mutex) != 0)
462 return ERR_PTR(-EINTR); 462 return ERR_PTR(-EINTR);
463 463
464 list_for_each_entry(t, &ipt_target, list) { 464 list_for_each_entry(t, &ipt_target, list) {
465 if (strcmp(t->name, name) == 0) { 465 if (strcmp(t->name, name) == 0) {
466 if (t->revision == revision) { 466 if (t->revision == revision) {
467 if (try_module_get(t->me)) { 467 if (try_module_get(t->me)) {
468 up(&ipt_mutex); 468 up(&ipt_mutex);
469 return t; 469 return t;
470 } 470 }
471 } else 471 } else
472 err = -EPROTOTYPE; /* Found something. */ 472 err = -EPROTOTYPE; /* Found something. */
473 } 473 }
474 } 474 }
475 up(&ipt_mutex); 475 up(&ipt_mutex);
476 return ERR_PTR(err); 476 return ERR_PTR(err);
477 } 477 }
478 478
479 struct ipt_target *ipt_find_target(const char *name, u8 revision) 479 struct ipt_target *ipt_find_target(const char *name, u8 revision)
480 { 480 {
481 struct ipt_target *target; 481 struct ipt_target *target;
482 482
483 target = try_then_request_module(find_target(name, revision), 483 target = try_then_request_module(find_target(name, revision),
484 "ipt_%s", name); 484 "ipt_%s", name);
485 if (IS_ERR(target) || !target) 485 if (IS_ERR(target) || !target)
486 return NULL; 486 return NULL;
487 return target; 487 return target;
488 } 488 }
489 489
490 static int match_revfn(const char *name, u8 revision, int *bestp) 490 static int match_revfn(const char *name, u8 revision, int *bestp)
491 { 491 {
492 struct ipt_match *m; 492 struct ipt_match *m;
493 int have_rev = 0; 493 int have_rev = 0;
494 494
495 list_for_each_entry(m, &ipt_match, list) { 495 list_for_each_entry(m, &ipt_match, list) {
496 if (strcmp(m->name, name) == 0) { 496 if (strcmp(m->name, name) == 0) {
497 if (m->revision > *bestp) 497 if (m->revision > *bestp)
498 *bestp = m->revision; 498 *bestp = m->revision;
499 if (m->revision == revision) 499 if (m->revision == revision)
500 have_rev = 1; 500 have_rev = 1;
501 } 501 }
502 } 502 }
503 return have_rev; 503 return have_rev;
504 } 504 }
505 505
506 static int target_revfn(const char *name, u8 revision, int *bestp) 506 static int target_revfn(const char *name, u8 revision, int *bestp)
507 { 507 {
508 struct ipt_target *t; 508 struct ipt_target *t;
509 int have_rev = 0; 509 int have_rev = 0;
510 510
511 list_for_each_entry(t, &ipt_target, list) { 511 list_for_each_entry(t, &ipt_target, list) {
512 if (strcmp(t->name, name) == 0) { 512 if (strcmp(t->name, name) == 0) {
513 if (t->revision > *bestp) 513 if (t->revision > *bestp)
514 *bestp = t->revision; 514 *bestp = t->revision;
515 if (t->revision == revision) 515 if (t->revision == revision)
516 have_rev = 1; 516 have_rev = 1;
517 } 517 }
518 } 518 }
519 return have_rev; 519 return have_rev;
520 } 520 }
521 521
522 /* Returns true or false (if no such extension at all) */ 522 /* Returns true or false (if no such extension at all) */
523 static inline int find_revision(const char *name, u8 revision, 523 static inline int find_revision(const char *name, u8 revision,
524 int (*revfn)(const char *, u8, int *), 524 int (*revfn)(const char *, u8, int *),
525 int *err) 525 int *err)
526 { 526 {
527 int have_rev, best = -1; 527 int have_rev, best = -1;
528 528
529 if (down_interruptible(&ipt_mutex) != 0) { 529 if (down_interruptible(&ipt_mutex) != 0) {
530 *err = -EINTR; 530 *err = -EINTR;
531 return 1; 531 return 1;
532 } 532 }
533 have_rev = revfn(name, revision, &best); 533 have_rev = revfn(name, revision, &best);
534 up(&ipt_mutex); 534 up(&ipt_mutex);
535 535
536 /* Nothing at all? Return 0 to try loading module. */ 536 /* Nothing at all? Return 0 to try loading module. */
537 if (best == -1) { 537 if (best == -1) {
538 *err = -ENOENT; 538 *err = -ENOENT;
539 return 0; 539 return 0;
540 } 540 }
541 541
542 *err = best; 542 *err = best;
543 if (!have_rev) 543 if (!have_rev)
544 *err = -EPROTONOSUPPORT; 544 *err = -EPROTONOSUPPORT;
545 return 1; 545 return 1;
546 } 546 }
547 547
548 548
549 /* All zeroes == unconditional rule. */ 549 /* All zeroes == unconditional rule. */
550 static inline int 550 static inline int
551 unconditional(const struct ipt_ip *ip) 551 unconditional(const struct ipt_ip *ip)
552 { 552 {
553 unsigned int i; 553 unsigned int i;
554 554
555 for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++) 555 for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
556 if (((__u32 *)ip)[i]) 556 if (((__u32 *)ip)[i])
557 return 0; 557 return 0;
558 558
559 return 1; 559 return 1;
560 } 560 }
561 561
562 /* Figures out from what hook each rule can be called: returns 0 if 562 /* Figures out from what hook each rule can be called: returns 0 if
563 there are loops. Puts hook bitmask in comefrom. */ 563 there are loops. Puts hook bitmask in comefrom. */
564 static int 564 static int
565 mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks) 565 mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
566 { 566 {
567 unsigned int hook; 567 unsigned int hook;
568 568
569 /* No recursion; use packet counter to save back ptrs (reset 569 /* No recursion; use packet counter to save back ptrs (reset
570 to 0 as we leave), and comefrom to save source hook bitmask */ 570 to 0 as we leave), and comefrom to save source hook bitmask */
571 for (hook = 0; hook < NF_IP_NUMHOOKS; hook++) { 571 for (hook = 0; hook < NF_IP_NUMHOOKS; hook++) {
572 unsigned int pos = newinfo->hook_entry[hook]; 572 unsigned int pos = newinfo->hook_entry[hook];
573 struct ipt_entry *e 573 struct ipt_entry *e
574 = (struct ipt_entry *)(newinfo->entries + pos); 574 = (struct ipt_entry *)(newinfo->entries + pos);
575 575
576 if (!(valid_hooks & (1 << hook))) 576 if (!(valid_hooks & (1 << hook)))
577 continue; 577 continue;
578 578
579 /* Set initial back pointer. */ 579 /* Set initial back pointer. */
580 e->counters.pcnt = pos; 580 e->counters.pcnt = pos;
581 581
582 for (;;) { 582 for (;;) {
583 struct ipt_standard_target *t 583 struct ipt_standard_target *t
584 = (void *)ipt_get_target(e); 584 = (void *)ipt_get_target(e);
585 585
586 if (e->comefrom & (1 << NF_IP_NUMHOOKS)) { 586 if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
587 printk("iptables: loop hook %u pos %u %08X.\n", 587 printk("iptables: loop hook %u pos %u %08X.\n",
588 hook, pos, e->comefrom); 588 hook, pos, e->comefrom);
589 return 0; 589 return 0;
590 } 590 }
591 e->comefrom 591 e->comefrom
592 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS)); 592 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
593 593
594 /* Unconditional return/END. */ 594 /* Unconditional return/END. */
595 if (e->target_offset == sizeof(struct ipt_entry) 595 if (e->target_offset == sizeof(struct ipt_entry)
596 && (strcmp(t->target.u.user.name, 596 && (strcmp(t->target.u.user.name,
597 IPT_STANDARD_TARGET) == 0) 597 IPT_STANDARD_TARGET) == 0)
598 && t->verdict < 0 598 && t->verdict < 0
599 && unconditional(&e->ip)) { 599 && unconditional(&e->ip)) {
600 unsigned int oldpos, size; 600 unsigned int oldpos, size;
601 601
602 /* Return: backtrack through the last 602 /* Return: backtrack through the last
603 big jump. */ 603 big jump. */
604 do { 604 do {
605 e->comefrom ^= (1<<NF_IP_NUMHOOKS); 605 e->comefrom ^= (1<<NF_IP_NUMHOOKS);
606 #ifdef DEBUG_IP_FIREWALL_USER 606 #ifdef DEBUG_IP_FIREWALL_USER
607 if (e->comefrom 607 if (e->comefrom
608 & (1 << NF_IP_NUMHOOKS)) { 608 & (1 << NF_IP_NUMHOOKS)) {
609 duprintf("Back unset " 609 duprintf("Back unset "
610 "on hook %u " 610 "on hook %u "
611 "rule %u\n", 611 "rule %u\n",
612 hook, pos); 612 hook, pos);
613 } 613 }
614 #endif 614 #endif
615 oldpos = pos; 615 oldpos = pos;
616 pos = e->counters.pcnt; 616 pos = e->counters.pcnt;
617 e->counters.pcnt = 0; 617 e->counters.pcnt = 0;
618 618
619 /* We're at the start. */ 619 /* We're at the start. */
620 if (pos == oldpos) 620 if (pos == oldpos)
621 goto next; 621 goto next;
622 622
623 e = (struct ipt_entry *) 623 e = (struct ipt_entry *)
624 (newinfo->entries + pos); 624 (newinfo->entries + pos);
625 } while (oldpos == pos + e->next_offset); 625 } while (oldpos == pos + e->next_offset);
626 626
627 /* Move along one */ 627 /* Move along one */
628 size = e->next_offset; 628 size = e->next_offset;
629 e = (struct ipt_entry *) 629 e = (struct ipt_entry *)
630 (newinfo->entries + pos + size); 630 (newinfo->entries + pos + size);
631 e->counters.pcnt = pos; 631 e->counters.pcnt = pos;
632 pos += size; 632 pos += size;
633 } else { 633 } else {
634 int newpos = t->verdict; 634 int newpos = t->verdict;
635 635
636 if (strcmp(t->target.u.user.name, 636 if (strcmp(t->target.u.user.name,
637 IPT_STANDARD_TARGET) == 0 637 IPT_STANDARD_TARGET) == 0
638 && newpos >= 0) { 638 && newpos >= 0) {
639 /* This a jump; chase it. */ 639 /* This a jump; chase it. */
640 duprintf("Jump rule %u -> %u\n", 640 duprintf("Jump rule %u -> %u\n",
641 pos, newpos); 641 pos, newpos);
642 } else { 642 } else {
643 /* ... this is a fallthru */ 643 /* ... this is a fallthru */
644 newpos = pos + e->next_offset; 644 newpos = pos + e->next_offset;
645 } 645 }
646 e = (struct ipt_entry *) 646 e = (struct ipt_entry *)
647 (newinfo->entries + newpos); 647 (newinfo->entries + newpos);
648 e->counters.pcnt = pos; 648 e->counters.pcnt = pos;
649 pos = newpos; 649 pos = newpos;
650 } 650 }
651 } 651 }
652 next: 652 next:
653 duprintf("Finished chain %u\n", hook); 653 duprintf("Finished chain %u\n", hook);
654 } 654 }
655 return 1; 655 return 1;
656 } 656 }
657 657
658 static inline int 658 static inline int
659 cleanup_match(struct ipt_entry_match *m, unsigned int *i) 659 cleanup_match(struct ipt_entry_match *m, unsigned int *i)
660 { 660 {
661 if (i && (*i)-- == 0) 661 if (i && (*i)-- == 0)
662 return 1; 662 return 1;
663 663
664 if (m->u.kernel.match->destroy) 664 if (m->u.kernel.match->destroy)
665 m->u.kernel.match->destroy(m->data, 665 m->u.kernel.match->destroy(m->data,
666 m->u.match_size - sizeof(*m)); 666 m->u.match_size - sizeof(*m));
667 module_put(m->u.kernel.match->me); 667 module_put(m->u.kernel.match->me);
668 return 0; 668 return 0;
669 } 669 }
670 670
671 static inline int 671 static inline int
672 standard_check(const struct ipt_entry_target *t, 672 standard_check(const struct ipt_entry_target *t,
673 unsigned int max_offset) 673 unsigned int max_offset)
674 { 674 {
675 struct ipt_standard_target *targ = (void *)t; 675 struct ipt_standard_target *targ = (void *)t;
676 676
677 /* Check standard info. */ 677 /* Check standard info. */
678 if (t->u.target_size 678 if (t->u.target_size
679 != IPT_ALIGN(sizeof(struct ipt_standard_target))) { 679 != IPT_ALIGN(sizeof(struct ipt_standard_target))) {
680 duprintf("standard_check: target size %u != %u\n", 680 duprintf("standard_check: target size %u != %u\n",
681 t->u.target_size, 681 t->u.target_size,
682 IPT_ALIGN(sizeof(struct ipt_standard_target))); 682 IPT_ALIGN(sizeof(struct ipt_standard_target)));
683 return 0; 683 return 0;
684 } 684 }
685 685
686 if (targ->verdict >= 0 686 if (targ->verdict >= 0
687 && targ->verdict > max_offset - sizeof(struct ipt_entry)) { 687 && targ->verdict > max_offset - sizeof(struct ipt_entry)) {
688 duprintf("ipt_standard_check: bad verdict (%i)\n", 688 duprintf("ipt_standard_check: bad verdict (%i)\n",
689 targ->verdict); 689 targ->verdict);
690 return 0; 690 return 0;
691 } 691 }
692 692
693 if (targ->verdict < -NF_MAX_VERDICT - 1) { 693 if (targ->verdict < -NF_MAX_VERDICT - 1) {
694 duprintf("ipt_standard_check: bad negative verdict (%i)\n", 694 duprintf("ipt_standard_check: bad negative verdict (%i)\n",
695 targ->verdict); 695 targ->verdict);
696 return 0; 696 return 0;
697 } 697 }
698 return 1; 698 return 1;
699 } 699 }
700 700
701 static inline int 701 static inline int
702 check_match(struct ipt_entry_match *m, 702 check_match(struct ipt_entry_match *m,
703 const char *name, 703 const char *name,
704 const struct ipt_ip *ip, 704 const struct ipt_ip *ip,
705 unsigned int hookmask, 705 unsigned int hookmask,
706 unsigned int *i) 706 unsigned int *i)
707 { 707 {
708 struct ipt_match *match; 708 struct ipt_match *match;
709 709
710 match = try_then_request_module(find_match(m->u.user.name, 710 match = try_then_request_module(find_match(m->u.user.name,
711 m->u.user.revision), 711 m->u.user.revision),
712 "ipt_%s", m->u.user.name); 712 "ipt_%s", m->u.user.name);
713 if (IS_ERR(match) || !match) { 713 if (IS_ERR(match) || !match) {
714 duprintf("check_match: `%s' not found\n", m->u.user.name); 714 duprintf("check_match: `%s' not found\n", m->u.user.name);
715 return match ? PTR_ERR(match) : -ENOENT; 715 return match ? PTR_ERR(match) : -ENOENT;
716 } 716 }
717 m->u.kernel.match = match; 717 m->u.kernel.match = match;
718 718
719 if (m->u.kernel.match->checkentry 719 if (m->u.kernel.match->checkentry
720 && !m->u.kernel.match->checkentry(name, ip, m->data, 720 && !m->u.kernel.match->checkentry(name, ip, m->data,
721 m->u.match_size - sizeof(*m), 721 m->u.match_size - sizeof(*m),
722 hookmask)) { 722 hookmask)) {
723 module_put(m->u.kernel.match->me); 723 module_put(m->u.kernel.match->me);
724 duprintf("ip_tables: check failed for `%s'.\n", 724 duprintf("ip_tables: check failed for `%s'.\n",
725 m->u.kernel.match->name); 725 m->u.kernel.match->name);
726 return -EINVAL; 726 return -EINVAL;
727 } 727 }
728 728
729 (*i)++; 729 (*i)++;
730 return 0; 730 return 0;
731 } 731 }
732 732
733 static struct ipt_target ipt_standard_target; 733 static struct ipt_target ipt_standard_target;
734 734
735 static inline int 735 static inline int
736 check_entry(struct ipt_entry *e, const char *name, unsigned int size, 736 check_entry(struct ipt_entry *e, const char *name, unsigned int size,
737 unsigned int *i) 737 unsigned int *i)
738 { 738 {
739 struct ipt_entry_target *t; 739 struct ipt_entry_target *t;
740 struct ipt_target *target; 740 struct ipt_target *target;
741 int ret; 741 int ret;
742 unsigned int j; 742 unsigned int j;
743 743
744 if (!ip_checkentry(&e->ip)) { 744 if (!ip_checkentry(&e->ip)) {
745 duprintf("ip_tables: ip check failed %p %s.\n", e, name); 745 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
746 return -EINVAL; 746 return -EINVAL;
747 } 747 }
748 748
749 j = 0; 749 j = 0;
750 ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j); 750 ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j);
751 if (ret != 0) 751 if (ret != 0)
752 goto cleanup_matches; 752 goto cleanup_matches;
753 753
754 t = ipt_get_target(e); 754 t = ipt_get_target(e);
755 target = try_then_request_module(find_target(t->u.user.name, 755 target = try_then_request_module(find_target(t->u.user.name,
756 t->u.user.revision), 756 t->u.user.revision),
757 "ipt_%s", t->u.user.name); 757 "ipt_%s", t->u.user.name);
758 if (IS_ERR(target) || !target) { 758 if (IS_ERR(target) || !target) {
759 duprintf("check_entry: `%s' not found\n", t->u.user.name); 759 duprintf("check_entry: `%s' not found\n", t->u.user.name);
760 ret = target ? PTR_ERR(target) : -ENOENT; 760 ret = target ? PTR_ERR(target) : -ENOENT;
761 goto cleanup_matches; 761 goto cleanup_matches;
762 } 762 }
763 t->u.kernel.target = target; 763 t->u.kernel.target = target;
764 764
765 if (t->u.kernel.target == &ipt_standard_target) { 765 if (t->u.kernel.target == &ipt_standard_target) {
766 if (!standard_check(t, size)) { 766 if (!standard_check(t, size)) {
767 ret = -EINVAL; 767 ret = -EINVAL;
768 goto cleanup_matches; 768 goto cleanup_matches;
769 } 769 }
770 } else if (t->u.kernel.target->checkentry 770 } else if (t->u.kernel.target->checkentry
771 && !t->u.kernel.target->checkentry(name, e, t->data, 771 && !t->u.kernel.target->checkentry(name, e, t->data,
772 t->u.target_size 772 t->u.target_size
773 - sizeof(*t), 773 - sizeof(*t),
774 e->comefrom)) { 774 e->comefrom)) {
775 module_put(t->u.kernel.target->me); 775 module_put(t->u.kernel.target->me);
776 duprintf("ip_tables: check failed for `%s'.\n", 776 duprintf("ip_tables: check failed for `%s'.\n",
777 t->u.kernel.target->name); 777 t->u.kernel.target->name);
778 ret = -EINVAL; 778 ret = -EINVAL;
779 goto cleanup_matches; 779 goto cleanup_matches;
780 } 780 }
781 781
782 (*i)++; 782 (*i)++;
783 return 0; 783 return 0;
784 784
785 cleanup_matches: 785 cleanup_matches:
786 IPT_MATCH_ITERATE(e, cleanup_match, &j); 786 IPT_MATCH_ITERATE(e, cleanup_match, &j);
787 return ret; 787 return ret;
788 } 788 }
789 789
790 static inline int 790 static inline int
791 check_entry_size_and_hooks(struct ipt_entry *e, 791 check_entry_size_and_hooks(struct ipt_entry *e,
792 struct ipt_table_info *newinfo, 792 struct ipt_table_info *newinfo,
793 unsigned char *base, 793 unsigned char *base,
794 unsigned char *limit, 794 unsigned char *limit,
795 const unsigned int *hook_entries, 795 const unsigned int *hook_entries,
796 const unsigned int *underflows, 796 const unsigned int *underflows,
797 unsigned int *i) 797 unsigned int *i)
798 { 798 {
799 unsigned int h; 799 unsigned int h;
800 800
801 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0 801 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0
802 || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) { 802 || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
803 duprintf("Bad offset %p\n", e); 803 duprintf("Bad offset %p\n", e);
804 return -EINVAL; 804 return -EINVAL;
805 } 805 }
806 806
807 if (e->next_offset 807 if (e->next_offset
808 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) { 808 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
809 duprintf("checking: element %p size %u\n", 809 duprintf("checking: element %p size %u\n",
810 e, e->next_offset); 810 e, e->next_offset);
811 return -EINVAL; 811 return -EINVAL;
812 } 812 }
813 813
814 /* Check hooks & underflows */ 814 /* Check hooks & underflows */
815 for (h = 0; h < NF_IP_NUMHOOKS; h++) { 815 for (h = 0; h < NF_IP_NUMHOOKS; h++) {
816 if ((unsigned char *)e - base == hook_entries[h]) 816 if ((unsigned char *)e - base == hook_entries[h])
817 newinfo->hook_entry[h] = hook_entries[h]; 817 newinfo->hook_entry[h] = hook_entries[h];
818 if ((unsigned char *)e - base == underflows[h]) 818 if ((unsigned char *)e - base == underflows[h])
819 newinfo->underflow[h] = underflows[h]; 819 newinfo->underflow[h] = underflows[h];
820 } 820 }
821 821
822 /* FIXME: underflows must be unconditional, standard verdicts 822 /* FIXME: underflows must be unconditional, standard verdicts
823 < 0 (not IPT_RETURN). --RR */ 823 < 0 (not IPT_RETURN). --RR */
824 824
825 /* Clear counters and comefrom */ 825 /* Clear counters and comefrom */
826 e->counters = ((struct ipt_counters) { 0, 0 }); 826 e->counters = ((struct ipt_counters) { 0, 0 });
827 e->comefrom = 0; 827 e->comefrom = 0;
828 828
829 (*i)++; 829 (*i)++;
830 return 0; 830 return 0;
831 } 831 }
832 832
833 static inline int 833 static inline int
834 cleanup_entry(struct ipt_entry *e, unsigned int *i) 834 cleanup_entry(struct ipt_entry *e, unsigned int *i)
835 { 835 {
836 struct ipt_entry_target *t; 836 struct ipt_entry_target *t;
837 837
838 if (i && (*i)-- == 0) 838 if (i && (*i)-- == 0)
839 return 1; 839 return 1;
840 840
841 /* Cleanup all matches */ 841 /* Cleanup all matches */
842 IPT_MATCH_ITERATE(e, cleanup_match, NULL); 842 IPT_MATCH_ITERATE(e, cleanup_match, NULL);
843 t = ipt_get_target(e); 843 t = ipt_get_target(e);
844 if (t->u.kernel.target->destroy) 844 if (t->u.kernel.target->destroy)
845 t->u.kernel.target->destroy(t->data, 845 t->u.kernel.target->destroy(t->data,
846 t->u.target_size - sizeof(*t)); 846 t->u.target_size - sizeof(*t));
847 module_put(t->u.kernel.target->me); 847 module_put(t->u.kernel.target->me);
848 return 0; 848 return 0;
849 } 849 }
850 850
851 /* Checks and translates the user-supplied table segment (held in 851 /* Checks and translates the user-supplied table segment (held in
852 newinfo) */ 852 newinfo) */
853 static int 853 static int
854 translate_table(const char *name, 854 translate_table(const char *name,
855 unsigned int valid_hooks, 855 unsigned int valid_hooks,
856 struct ipt_table_info *newinfo, 856 struct ipt_table_info *newinfo,
857 unsigned int size, 857 unsigned int size,
858 unsigned int number, 858 unsigned int number,
859 const unsigned int *hook_entries, 859 const unsigned int *hook_entries,
860 const unsigned int *underflows) 860 const unsigned int *underflows)
861 { 861 {
862 unsigned int i; 862 unsigned int i;
863 int ret; 863 int ret;
864 864
865 newinfo->size = size; 865 newinfo->size = size;
866 newinfo->number = number; 866 newinfo->number = number;
867 867
868 /* Init all hooks to impossible value. */ 868 /* Init all hooks to impossible value. */
869 for (i = 0; i < NF_IP_NUMHOOKS; i++) { 869 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
870 newinfo->hook_entry[i] = 0xFFFFFFFF; 870 newinfo->hook_entry[i] = 0xFFFFFFFF;
871 newinfo->underflow[i] = 0xFFFFFFFF; 871 newinfo->underflow[i] = 0xFFFFFFFF;
872 } 872 }
873 873
874 duprintf("translate_table: size %u\n", newinfo->size); 874 duprintf("translate_table: size %u\n", newinfo->size);
875 i = 0; 875 i = 0;
876 /* Walk through entries, checking offsets. */ 876 /* Walk through entries, checking offsets. */
877 ret = IPT_ENTRY_ITERATE(newinfo->entries, newinfo->size, 877 ret = IPT_ENTRY_ITERATE(newinfo->entries, newinfo->size,
878 check_entry_size_and_hooks, 878 check_entry_size_and_hooks,
879 newinfo, 879 newinfo,
880 newinfo->entries, 880 newinfo->entries,
881 newinfo->entries + size, 881 newinfo->entries + size,
882 hook_entries, underflows, &i); 882 hook_entries, underflows, &i);
883 if (ret != 0) 883 if (ret != 0)
884 return ret; 884 return ret;
885 885
886 if (i != number) { 886 if (i != number) {
887 duprintf("translate_table: %u not %u entries\n", 887 duprintf("translate_table: %u not %u entries\n",
888 i, number); 888 i, number);
889 return -EINVAL; 889 return -EINVAL;
890 } 890 }
891 891
892 /* Check hooks all assigned */ 892 /* Check hooks all assigned */
893 for (i = 0; i < NF_IP_NUMHOOKS; i++) { 893 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
894 /* Only hooks which are valid */ 894 /* Only hooks which are valid */
895 if (!(valid_hooks & (1 << i))) 895 if (!(valid_hooks & (1 << i)))
896 continue; 896 continue;
897 if (newinfo->hook_entry[i] == 0xFFFFFFFF) { 897 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
898 duprintf("Invalid hook entry %u %u\n", 898 duprintf("Invalid hook entry %u %u\n",
899 i, hook_entries[i]); 899 i, hook_entries[i]);
900 return -EINVAL; 900 return -EINVAL;
901 } 901 }
902 if (newinfo->underflow[i] == 0xFFFFFFFF) { 902 if (newinfo->underflow[i] == 0xFFFFFFFF) {
903 duprintf("Invalid underflow %u %u\n", 903 duprintf("Invalid underflow %u %u\n",
904 i, underflows[i]); 904 i, underflows[i]);
905 return -EINVAL; 905 return -EINVAL;
906 } 906 }
907 } 907 }
908 908
909 if (!mark_source_chains(newinfo, valid_hooks)) 909 if (!mark_source_chains(newinfo, valid_hooks))
910 return -ELOOP; 910 return -ELOOP;
911 911
912 /* Finally, each sanity check must pass */ 912 /* Finally, each sanity check must pass */
913 i = 0; 913 i = 0;
914 ret = IPT_ENTRY_ITERATE(newinfo->entries, newinfo->size, 914 ret = IPT_ENTRY_ITERATE(newinfo->entries, newinfo->size,
915 check_entry, name, size, &i); 915 check_entry, name, size, &i);
916 916
917 if (ret != 0) { 917 if (ret != 0) {
918 IPT_ENTRY_ITERATE(newinfo->entries, newinfo->size, 918 IPT_ENTRY_ITERATE(newinfo->entries, newinfo->size,
919 cleanup_entry, &i); 919 cleanup_entry, &i);
920 return ret; 920 return ret;
921 } 921 }
922 922
923 /* And one copy for every other CPU */ 923 /* And one copy for every other CPU */
924 for (i = 1; i < num_possible_cpus(); i++) { 924 for (i = 1; i < num_possible_cpus(); i++) {
925 memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i, 925 memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i,
926 newinfo->entries, 926 newinfo->entries,
927 SMP_ALIGN(newinfo->size)); 927 SMP_ALIGN(newinfo->size));
928 } 928 }
929 929
930 return ret; 930 return ret;
931 } 931 }
932 932
933 static struct ipt_table_info * 933 static struct ipt_table_info *
934 replace_table(struct ipt_table *table, 934 replace_table(struct ipt_table *table,
935 unsigned int num_counters, 935 unsigned int num_counters,
936 struct ipt_table_info *newinfo, 936 struct ipt_table_info *newinfo,
937 int *error) 937 int *error)
938 { 938 {
939 struct ipt_table_info *oldinfo; 939 struct ipt_table_info *oldinfo;
940 940
941 #ifdef CONFIG_NETFILTER_DEBUG 941 #ifdef CONFIG_NETFILTER_DEBUG
942 { 942 {
943 struct ipt_entry *table_base; 943 struct ipt_entry *table_base;
944 unsigned int i; 944 unsigned int i;
945 945
946 for (i = 0; i < num_possible_cpus(); i++) { 946 for (i = 0; i < num_possible_cpus(); i++) {
947 table_base = 947 table_base =
948 (void *)newinfo->entries 948 (void *)newinfo->entries
949 + TABLE_OFFSET(newinfo, i); 949 + TABLE_OFFSET(newinfo, i);
950 950
951 table_base->comefrom = 0xdead57ac; 951 table_base->comefrom = 0xdead57ac;
952 } 952 }
953 } 953 }
954 #endif 954 #endif
955 955
956 /* Do the substitution. */ 956 /* Do the substitution. */
957 write_lock_bh(&table->lock); 957 write_lock_bh(&table->lock);
958 /* Check inside lock: is the old number correct? */ 958 /* Check inside lock: is the old number correct? */
959 if (num_counters != table->private->number) { 959 if (num_counters != table->private->number) {
960 duprintf("num_counters != table->private->number (%u/%u)\n", 960 duprintf("num_counters != table->private->number (%u/%u)\n",
961 num_counters, table->private->number); 961 num_counters, table->private->number);
962 write_unlock_bh(&table->lock); 962 write_unlock_bh(&table->lock);
963 *error = -EAGAIN; 963 *error = -EAGAIN;
964 return NULL; 964 return NULL;
965 } 965 }
966 oldinfo = table->private; 966 oldinfo = table->private;
967 table->private = newinfo; 967 table->private = newinfo;
968 newinfo->initial_entries = oldinfo->initial_entries; 968 newinfo->initial_entries = oldinfo->initial_entries;
969 write_unlock_bh(&table->lock); 969 write_unlock_bh(&table->lock);
970 970
971 return oldinfo; 971 return oldinfo;
972 } 972 }
973 973
974 /* Gets counters. */ 974 /* Gets counters. */
975 static inline int 975 static inline int
976 add_entry_to_counter(const struct ipt_entry *e, 976 add_entry_to_counter(const struct ipt_entry *e,
977 struct ipt_counters total[], 977 struct ipt_counters total[],
978 unsigned int *i) 978 unsigned int *i)
979 { 979 {
980 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); 980 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
981 981
982 (*i)++; 982 (*i)++;
983 return 0; 983 return 0;
984 } 984 }
985 985
986 static void 986 static void
987 get_counters(const struct ipt_table_info *t, 987 get_counters(const struct ipt_table_info *t,
988 struct ipt_counters counters[]) 988 struct ipt_counters counters[])
989 { 989 {
990 unsigned int cpu; 990 unsigned int cpu;
991 unsigned int i; 991 unsigned int i;
992 992
993 for (cpu = 0; cpu < num_possible_cpus(); cpu++) { 993 for (cpu = 0; cpu < num_possible_cpus(); cpu++) {
994 i = 0; 994 i = 0;
995 IPT_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu), 995 IPT_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu),
996 t->size, 996 t->size,
997 add_entry_to_counter, 997 add_entry_to_counter,
998 counters, 998 counters,
999 &i); 999 &i);
1000 } 1000 }
1001 } 1001 }
1002 1002
1003 static int 1003 static int
1004 copy_entries_to_user(unsigned int total_size, 1004 copy_entries_to_user(unsigned int total_size,
1005 struct ipt_table *table, 1005 struct ipt_table *table,
1006 void __user *userptr) 1006 void __user *userptr)
1007 { 1007 {
1008 unsigned int off, num, countersize; 1008 unsigned int off, num, countersize;
1009 struct ipt_entry *e; 1009 struct ipt_entry *e;
1010 struct ipt_counters *counters; 1010 struct ipt_counters *counters;
1011 int ret = 0; 1011 int ret = 0;
1012 1012
1013 /* We need atomic snapshot of counters: rest doesn't change 1013 /* We need atomic snapshot of counters: rest doesn't change
1014 (other than comefrom, which userspace doesn't care 1014 (other than comefrom, which userspace doesn't care
1015 about). */ 1015 about). */
1016 countersize = sizeof(struct ipt_counters) * table->private->number; 1016 countersize = sizeof(struct ipt_counters) * table->private->number;
1017 counters = vmalloc(countersize); 1017 counters = vmalloc(countersize);
1018 1018
1019 if (counters == NULL) 1019 if (counters == NULL)
1020 return -ENOMEM; 1020 return -ENOMEM;
1021 1021
1022 /* First, sum counters... */ 1022 /* First, sum counters... */
1023 memset(counters, 0, countersize); 1023 memset(counters, 0, countersize);
1024 write_lock_bh(&table->lock); 1024 write_lock_bh(&table->lock);
1025 get_counters(table->private, counters); 1025 get_counters(table->private, counters);
1026 write_unlock_bh(&table->lock); 1026 write_unlock_bh(&table->lock);
1027 1027
1028 /* ... then copy entire thing from CPU 0... */ 1028 /* ... then copy entire thing from CPU 0... */
1029 if (copy_to_user(userptr, table->private->entries, total_size) != 0) { 1029 if (copy_to_user(userptr, table->private->entries, total_size) != 0) {
1030 ret = -EFAULT; 1030 ret = -EFAULT;
1031 goto free_counters; 1031 goto free_counters;
1032 } 1032 }
1033 1033
1034 /* FIXME: use iterator macros --RR */ 1034 /* FIXME: use iterator macros --RR */
1035 /* ... then go back and fix counters and names */ 1035 /* ... then go back and fix counters and names */
1036 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){ 1036 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
1037 unsigned int i; 1037 unsigned int i;
1038 struct ipt_entry_match *m; 1038 struct ipt_entry_match *m;
1039 struct ipt_entry_target *t; 1039 struct ipt_entry_target *t;
1040 1040
1041 e = (struct ipt_entry *)(table->private->entries + off); 1041 e = (struct ipt_entry *)(table->private->entries + off);
1042 if (copy_to_user(userptr + off 1042 if (copy_to_user(userptr + off
1043 + offsetof(struct ipt_entry, counters), 1043 + offsetof(struct ipt_entry, counters),
1044 &counters[num], 1044 &counters[num],
1045 sizeof(counters[num])) != 0) { 1045 sizeof(counters[num])) != 0) {
1046 ret = -EFAULT; 1046 ret = -EFAULT;
1047 goto free_counters; 1047 goto free_counters;
1048 } 1048 }
1049 1049
1050 for (i = sizeof(struct ipt_entry); 1050 for (i = sizeof(struct ipt_entry);
1051 i < e->target_offset; 1051 i < e->target_offset;
1052 i += m->u.match_size) { 1052 i += m->u.match_size) {
1053 m = (void *)e + i; 1053 m = (void *)e + i;
1054 1054
1055 if (copy_to_user(userptr + off + i 1055 if (copy_to_user(userptr + off + i
1056 + offsetof(struct ipt_entry_match, 1056 + offsetof(struct ipt_entry_match,
1057 u.user.name), 1057 u.user.name),
1058 m->u.kernel.match->name, 1058 m->u.kernel.match->name,
1059 strlen(m->u.kernel.match->name)+1) 1059 strlen(m->u.kernel.match->name)+1)
1060 != 0) { 1060 != 0) {
1061 ret = -EFAULT; 1061 ret = -EFAULT;
1062 goto free_counters; 1062 goto free_counters;
1063 } 1063 }
1064 } 1064 }
1065 1065
1066 t = ipt_get_target(e); 1066 t = ipt_get_target(e);
1067 if (copy_to_user(userptr + off + e->target_offset 1067 if (copy_to_user(userptr + off + e->target_offset
1068 + offsetof(struct ipt_entry_target, 1068 + offsetof(struct ipt_entry_target,
1069 u.user.name), 1069 u.user.name),
1070 t->u.kernel.target->name, 1070 t->u.kernel.target->name,
1071 strlen(t->u.kernel.target->name)+1) != 0) { 1071 strlen(t->u.kernel.target->name)+1) != 0) {
1072 ret = -EFAULT; 1072 ret = -EFAULT;
1073 goto free_counters; 1073 goto free_counters;
1074 } 1074 }
1075 } 1075 }
1076 1076
1077 free_counters: 1077 free_counters:
1078 vfree(counters); 1078 vfree(counters);
1079 return ret; 1079 return ret;
1080 } 1080 }
1081 1081
1082 static int 1082 static int
1083 get_entries(const struct ipt_get_entries *entries, 1083 get_entries(const struct ipt_get_entries *entries,
1084 struct ipt_get_entries __user *uptr) 1084 struct ipt_get_entries __user *uptr)
1085 { 1085 {
1086 int ret; 1086 int ret;
1087 struct ipt_table *t; 1087 struct ipt_table *t;
1088 1088
1089 t = find_table_lock(entries->name); 1089 t = find_table_lock(entries->name);
1090 if (t && !IS_ERR(t)) { 1090 if (t && !IS_ERR(t)) {
1091 duprintf("t->private->number = %u\n", 1091 duprintf("t->private->number = %u\n",
1092 t->private->number); 1092 t->private->number);
1093 if (entries->size == t->private->size) 1093 if (entries->size == t->private->size)
1094 ret = copy_entries_to_user(t->private->size, 1094 ret = copy_entries_to_user(t->private->size,
1095 t, uptr->entrytable); 1095 t, uptr->entrytable);
1096 else { 1096 else {
1097 duprintf("get_entries: I've got %u not %u!\n", 1097 duprintf("get_entries: I've got %u not %u!\n",
1098 t->private->size, 1098 t->private->size,
1099 entries->size); 1099 entries->size);
1100 ret = -EINVAL; 1100 ret = -EINVAL;
1101 } 1101 }
1102 module_put(t->me); 1102 module_put(t->me);
1103 up(&ipt_mutex); 1103 up(&ipt_mutex);
1104 } else 1104 } else
1105 ret = t ? PTR_ERR(t) : -ENOENT; 1105 ret = t ? PTR_ERR(t) : -ENOENT;
1106 1106
1107 return ret; 1107 return ret;
1108 } 1108 }
1109 1109
1110 static int 1110 static int
1111 do_replace(void __user *user, unsigned int len) 1111 do_replace(void __user *user, unsigned int len)
1112 { 1112 {
1113 int ret; 1113 int ret;
1114 struct ipt_replace tmp; 1114 struct ipt_replace tmp;
1115 struct ipt_table *t; 1115 struct ipt_table *t;
1116 struct ipt_table_info *newinfo, *oldinfo; 1116 struct ipt_table_info *newinfo, *oldinfo;
1117 struct ipt_counters *counters; 1117 struct ipt_counters *counters;
1118 1118
1119 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1119 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1120 return -EFAULT; 1120 return -EFAULT;
1121 1121
1122 /* Hack: Causes ipchains to give correct error msg --RR */ 1122 /* Hack: Causes ipchains to give correct error msg --RR */
1123 if (len != sizeof(tmp) + tmp.size) 1123 if (len != sizeof(tmp) + tmp.size)
1124 return -ENOPROTOOPT; 1124 return -ENOPROTOOPT;
1125 1125
1126 /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ 1126 /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */
1127 if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages) 1127 if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages)
1128 return -ENOMEM; 1128 return -ENOMEM;
1129 1129
1130 newinfo = vmalloc(sizeof(struct ipt_table_info) 1130 newinfo = vmalloc(sizeof(struct ipt_table_info)
1131 + SMP_ALIGN(tmp.size) * num_possible_cpus()); 1131 + SMP_ALIGN(tmp.size) * num_possible_cpus());
1132 if (!newinfo) 1132 if (!newinfo)
1133 return -ENOMEM; 1133 return -ENOMEM;
1134 1134
1135 if (copy_from_user(newinfo->entries, user + sizeof(tmp), 1135 if (copy_from_user(newinfo->entries, user + sizeof(tmp),
1136 tmp.size) != 0) { 1136 tmp.size) != 0) {
1137 ret = -EFAULT; 1137 ret = -EFAULT;
1138 goto free_newinfo; 1138 goto free_newinfo;
1139 } 1139 }
1140 1140
1141 counters = vmalloc(tmp.num_counters * sizeof(struct ipt_counters)); 1141 counters = vmalloc(tmp.num_counters * sizeof(struct ipt_counters));
1142 if (!counters) { 1142 if (!counters) {
1143 ret = -ENOMEM; 1143 ret = -ENOMEM;
1144 goto free_newinfo; 1144 goto free_newinfo;
1145 } 1145 }
1146 memset(counters, 0, tmp.num_counters * sizeof(struct ipt_counters)); 1146 memset(counters, 0, tmp.num_counters * sizeof(struct ipt_counters));
1147 1147
1148 ret = translate_table(tmp.name, tmp.valid_hooks, 1148 ret = translate_table(tmp.name, tmp.valid_hooks,
1149 newinfo, tmp.size, tmp.num_entries, 1149 newinfo, tmp.size, tmp.num_entries,
1150 tmp.hook_entry, tmp.underflow); 1150 tmp.hook_entry, tmp.underflow);
1151 if (ret != 0) 1151 if (ret != 0)
1152 goto free_newinfo_counters; 1152 goto free_newinfo_counters;
1153 1153
1154 duprintf("ip_tables: Translated table\n"); 1154 duprintf("ip_tables: Translated table\n");
1155 1155
1156 t = try_then_request_module(find_table_lock(tmp.name), 1156 t = try_then_request_module(find_table_lock(tmp.name),
1157 "iptable_%s", tmp.name); 1157 "iptable_%s", tmp.name);
1158 if (!t || IS_ERR(t)) { 1158 if (!t || IS_ERR(t)) {
1159 ret = t ? PTR_ERR(t) : -ENOENT; 1159 ret = t ? PTR_ERR(t) : -ENOENT;
1160 goto free_newinfo_counters_untrans; 1160 goto free_newinfo_counters_untrans;
1161 } 1161 }
1162 1162
1163 /* You lied! */ 1163 /* You lied! */
1164 if (tmp.valid_hooks != t->valid_hooks) { 1164 if (tmp.valid_hooks != t->valid_hooks) {
1165 duprintf("Valid hook crap: %08X vs %08X\n", 1165 duprintf("Valid hook crap: %08X vs %08X\n",
1166 tmp.valid_hooks, t->valid_hooks); 1166 tmp.valid_hooks, t->valid_hooks);
1167 ret = -EINVAL; 1167 ret = -EINVAL;
1168 goto put_module; 1168 goto put_module;
1169 } 1169 }
1170 1170
1171 oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); 1171 oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret);
1172 if (!oldinfo) 1172 if (!oldinfo)
1173 goto put_module; 1173 goto put_module;
1174 1174
1175 /* Update module usage count based on number of rules */ 1175 /* Update module usage count based on number of rules */
1176 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n", 1176 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1177 oldinfo->number, oldinfo->initial_entries, newinfo->number); 1177 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1178 if ((oldinfo->number > oldinfo->initial_entries) || 1178 if ((oldinfo->number > oldinfo->initial_entries) ||
1179 (newinfo->number <= oldinfo->initial_entries)) 1179 (newinfo->number <= oldinfo->initial_entries))
1180 module_put(t->me); 1180 module_put(t->me);
1181 if ((oldinfo->number > oldinfo->initial_entries) && 1181 if ((oldinfo->number > oldinfo->initial_entries) &&
1182 (newinfo->number <= oldinfo->initial_entries)) 1182 (newinfo->number <= oldinfo->initial_entries))
1183 module_put(t->me); 1183 module_put(t->me);
1184 1184
1185 /* Get the old counters. */ 1185 /* Get the old counters. */
1186 get_counters(oldinfo, counters); 1186 get_counters(oldinfo, counters);
1187 /* Decrease module usage counts and free resource */ 1187 /* Decrease module usage counts and free resource */
1188 IPT_ENTRY_ITERATE(oldinfo->entries, oldinfo->size, cleanup_entry,NULL); 1188 IPT_ENTRY_ITERATE(oldinfo->entries, oldinfo->size, cleanup_entry,NULL);
1189 vfree(oldinfo); 1189 vfree(oldinfo);
1190 if (copy_to_user(tmp.counters, counters, 1190 if (copy_to_user(tmp.counters, counters,
1191 sizeof(struct ipt_counters) * tmp.num_counters) != 0) 1191 sizeof(struct ipt_counters) * tmp.num_counters) != 0)
1192 ret = -EFAULT; 1192 ret = -EFAULT;
1193 vfree(counters); 1193 vfree(counters);
1194 up(&ipt_mutex); 1194 up(&ipt_mutex);
1195 return ret; 1195 return ret;
1196 1196
1197 put_module: 1197 put_module:
1198 module_put(t->me); 1198 module_put(t->me);
1199 up(&ipt_mutex); 1199 up(&ipt_mutex);
1200 free_newinfo_counters_untrans: 1200 free_newinfo_counters_untrans:
1201 IPT_ENTRY_ITERATE(newinfo->entries, newinfo->size, cleanup_entry,NULL); 1201 IPT_ENTRY_ITERATE(newinfo->entries, newinfo->size, cleanup_entry,NULL);
1202 free_newinfo_counters: 1202 free_newinfo_counters:
1203 vfree(counters); 1203 vfree(counters);
1204 free_newinfo: 1204 free_newinfo:
1205 vfree(newinfo); 1205 vfree(newinfo);
1206 return ret; 1206 return ret;
1207 } 1207 }
1208 1208
1209 /* We're lazy, and add to the first CPU; overflow works its fey magic 1209 /* We're lazy, and add to the first CPU; overflow works its fey magic
1210 * and everything is OK. */ 1210 * and everything is OK. */
1211 static inline int 1211 static inline int
1212 add_counter_to_entry(struct ipt_entry *e, 1212 add_counter_to_entry(struct ipt_entry *e,
1213 const struct ipt_counters addme[], 1213 const struct ipt_counters addme[],
1214 unsigned int *i) 1214 unsigned int *i)
1215 { 1215 {
1216 #if 0 1216 #if 0
1217 duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n", 1217 duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n",
1218 *i, 1218 *i,
1219 (long unsigned int)e->counters.pcnt, 1219 (long unsigned int)e->counters.pcnt,
1220 (long unsigned int)e->counters.bcnt, 1220 (long unsigned int)e->counters.bcnt,
1221 (long unsigned int)addme[*i].pcnt, 1221 (long unsigned int)addme[*i].pcnt,
1222 (long unsigned int)addme[*i].bcnt); 1222 (long unsigned int)addme[*i].bcnt);
1223 #endif 1223 #endif
1224 1224
1225 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); 1225 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1226 1226
1227 (*i)++; 1227 (*i)++;
1228 return 0; 1228 return 0;
1229 } 1229 }
1230 1230
1231 static int 1231 static int
1232 do_add_counters(void __user *user, unsigned int len) 1232 do_add_counters(void __user *user, unsigned int len)
1233 { 1233 {
1234 unsigned int i; 1234 unsigned int i;
1235 struct ipt_counters_info tmp, *paddc; 1235 struct ipt_counters_info tmp, *paddc;
1236 struct ipt_table *t; 1236 struct ipt_table *t;
1237 int ret = 0; 1237 int ret = 0;
1238 1238
1239 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1239 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1240 return -EFAULT; 1240 return -EFAULT;
1241 1241
1242 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct ipt_counters)) 1242 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct ipt_counters))
1243 return -EINVAL; 1243 return -EINVAL;
1244 1244
1245 paddc = vmalloc(len); 1245 paddc = vmalloc(len);
1246 if (!paddc) 1246 if (!paddc)
1247 return -ENOMEM; 1247 return -ENOMEM;
1248 1248
1249 if (copy_from_user(paddc, user, len) != 0) { 1249 if (copy_from_user(paddc, user, len) != 0) {
1250 ret = -EFAULT; 1250 ret = -EFAULT;
1251 goto free; 1251 goto free;
1252 } 1252 }
1253 1253
1254 t = find_table_lock(tmp.name); 1254 t = find_table_lock(tmp.name);
1255 if (!t || IS_ERR(t)) { 1255 if (!t || IS_ERR(t)) {
1256 ret = t ? PTR_ERR(t) : -ENOENT; 1256 ret = t ? PTR_ERR(t) : -ENOENT;
1257 goto free; 1257 goto free;
1258 } 1258 }
1259 1259
1260 write_lock_bh(&t->lock); 1260 write_lock_bh(&t->lock);
1261 if (t->private->number != paddc->num_counters) { 1261 if (t->private->number != paddc->num_counters) {
1262 ret = -EINVAL; 1262 ret = -EINVAL;
1263 goto unlock_up_free; 1263 goto unlock_up_free;
1264 } 1264 }
1265 1265
1266 i = 0; 1266 i = 0;
1267 IPT_ENTRY_ITERATE(t->private->entries, 1267 IPT_ENTRY_ITERATE(t->private->entries,
1268 t->private->size, 1268 t->private->size,
1269 add_counter_to_entry, 1269 add_counter_to_entry,
1270 paddc->counters, 1270 paddc->counters,
1271 &i); 1271 &i);
1272 unlock_up_free: 1272 unlock_up_free:
1273 write_unlock_bh(&t->lock); 1273 write_unlock_bh(&t->lock);
1274 up(&ipt_mutex); 1274 up(&ipt_mutex);
1275 module_put(t->me); 1275 module_put(t->me);
1276 free: 1276 free:
1277 vfree(paddc); 1277 vfree(paddc);
1278 1278
1279 return ret; 1279 return ret;
1280 } 1280 }
1281 1281
1282 static int 1282 static int
1283 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) 1283 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1284 { 1284 {
1285 int ret; 1285 int ret;
1286 1286
1287 if (!capable(CAP_NET_ADMIN)) 1287 if (!capable(CAP_NET_ADMIN))
1288 return -EPERM; 1288 return -EPERM;
1289 1289
1290 switch (cmd) { 1290 switch (cmd) {
1291 case IPT_SO_SET_REPLACE: 1291 case IPT_SO_SET_REPLACE:
1292 ret = do_replace(user, len); 1292 ret = do_replace(user, len);
1293 break; 1293 break;
1294 1294
1295 case IPT_SO_SET_ADD_COUNTERS: 1295 case IPT_SO_SET_ADD_COUNTERS:
1296 ret = do_add_counters(user, len); 1296 ret = do_add_counters(user, len);
1297 break; 1297 break;
1298 1298
1299 default: 1299 default:
1300 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd); 1300 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1301 ret = -EINVAL; 1301 ret = -EINVAL;
1302 } 1302 }
1303 1303
1304 return ret; 1304 return ret;
1305 } 1305 }
1306 1306
1307 static int 1307 static int
1308 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) 1308 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1309 { 1309 {
1310 int ret; 1310 int ret;
1311 1311
1312 if (!capable(CAP_NET_ADMIN)) 1312 if (!capable(CAP_NET_ADMIN))
1313 return -EPERM; 1313 return -EPERM;
1314 1314
1315 switch (cmd) { 1315 switch (cmd) {
1316 case IPT_SO_GET_INFO: { 1316 case IPT_SO_GET_INFO: {
1317 char name[IPT_TABLE_MAXNAMELEN]; 1317 char name[IPT_TABLE_MAXNAMELEN];
1318 struct ipt_table *t; 1318 struct ipt_table *t;
1319 1319
1320 if (*len != sizeof(struct ipt_getinfo)) { 1320 if (*len != sizeof(struct ipt_getinfo)) {
1321 duprintf("length %u != %u\n", *len, 1321 duprintf("length %u != %u\n", *len,
1322 sizeof(struct ipt_getinfo)); 1322 sizeof(struct ipt_getinfo));
1323 ret = -EINVAL; 1323 ret = -EINVAL;
1324 break; 1324 break;
1325 } 1325 }
1326 1326
1327 if (copy_from_user(name, user, sizeof(name)) != 0) { 1327 if (copy_from_user(name, user, sizeof(name)) != 0) {
1328 ret = -EFAULT; 1328 ret = -EFAULT;
1329 break; 1329 break;
1330 } 1330 }
1331 name[IPT_TABLE_MAXNAMELEN-1] = '\0'; 1331 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1332 1332
1333 t = try_then_request_module(find_table_lock(name), 1333 t = try_then_request_module(find_table_lock(name),
1334 "iptable_%s", name); 1334 "iptable_%s", name);
1335 if (t && !IS_ERR(t)) { 1335 if (t && !IS_ERR(t)) {
1336 struct ipt_getinfo info; 1336 struct ipt_getinfo info;
1337 1337
1338 info.valid_hooks = t->valid_hooks; 1338 info.valid_hooks = t->valid_hooks;
1339 memcpy(info.hook_entry, t->private->hook_entry, 1339 memcpy(info.hook_entry, t->private->hook_entry,
1340 sizeof(info.hook_entry)); 1340 sizeof(info.hook_entry));
1341 memcpy(info.underflow, t->private->underflow, 1341 memcpy(info.underflow, t->private->underflow,
1342 sizeof(info.underflow)); 1342 sizeof(info.underflow));
1343 info.num_entries = t->private->number; 1343 info.num_entries = t->private->number;
1344 info.size = t->private->size; 1344 info.size = t->private->size;
1345 memcpy(info.name, name, sizeof(info.name)); 1345 memcpy(info.name, name, sizeof(info.name));
1346 1346
1347 if (copy_to_user(user, &info, *len) != 0) 1347 if (copy_to_user(user, &info, *len) != 0)
1348 ret = -EFAULT; 1348 ret = -EFAULT;
1349 else 1349 else
1350 ret = 0; 1350 ret = 0;
1351 up(&ipt_mutex); 1351 up(&ipt_mutex);
1352 module_put(t->me); 1352 module_put(t->me);
1353 } else 1353 } else
1354 ret = t ? PTR_ERR(t) : -ENOENT; 1354 ret = t ? PTR_ERR(t) : -ENOENT;
1355 } 1355 }
1356 break; 1356 break;
1357 1357
1358 case IPT_SO_GET_ENTRIES: { 1358 case IPT_SO_GET_ENTRIES: {
1359 struct ipt_get_entries get; 1359 struct ipt_get_entries get;
1360 1360
1361 if (*len < sizeof(get)) { 1361 if (*len < sizeof(get)) {
1362 duprintf("get_entries: %u < %u\n", *len, sizeof(get)); 1362 duprintf("get_entries: %u < %u\n", *len, sizeof(get));
1363 ret = -EINVAL; 1363 ret = -EINVAL;
1364 } else if (copy_from_user(&get, user, sizeof(get)) != 0) { 1364 } else if (copy_from_user(&get, user, sizeof(get)) != 0) {
1365 ret = -EFAULT; 1365 ret = -EFAULT;
1366 } else if (*len != sizeof(struct ipt_get_entries) + get.size) { 1366 } else if (*len != sizeof(struct ipt_get_entries) + get.size) {
1367 duprintf("get_entries: %u != %u\n", *len, 1367 duprintf("get_entries: %u != %u\n", *len,
1368 sizeof(struct ipt_get_entries) + get.size); 1368 sizeof(struct ipt_get_entries) + get.size);
1369 ret = -EINVAL; 1369 ret = -EINVAL;
1370 } else 1370 } else
1371 ret = get_entries(&get, user); 1371 ret = get_entries(&get, user);
1372 break; 1372 break;
1373 } 1373 }
1374 1374
1375 case IPT_SO_GET_REVISION_MATCH: 1375 case IPT_SO_GET_REVISION_MATCH:
1376 case IPT_SO_GET_REVISION_TARGET: { 1376 case IPT_SO_GET_REVISION_TARGET: {
1377 struct ipt_get_revision rev; 1377 struct ipt_get_revision rev;
1378 int (*revfn)(const char *, u8, int *); 1378 int (*revfn)(const char *, u8, int *);
1379 1379
1380 if (*len != sizeof(rev)) { 1380 if (*len != sizeof(rev)) {
1381 ret = -EINVAL; 1381 ret = -EINVAL;
1382 break; 1382 break;
1383 } 1383 }
1384 if (copy_from_user(&rev, user, sizeof(rev)) != 0) { 1384 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
1385 ret = -EFAULT; 1385 ret = -EFAULT;
1386 break; 1386 break;
1387 } 1387 }
1388 1388
1389 if (cmd == IPT_SO_GET_REVISION_TARGET) 1389 if (cmd == IPT_SO_GET_REVISION_TARGET)
1390 revfn = target_revfn; 1390 revfn = target_revfn;
1391 else 1391 else
1392 revfn = match_revfn; 1392 revfn = match_revfn;
1393 1393
1394 try_then_request_module(find_revision(rev.name, rev.revision, 1394 try_then_request_module(find_revision(rev.name, rev.revision,
1395 revfn, &ret), 1395 revfn, &ret),
1396 "ipt_%s", rev.name); 1396 "ipt_%s", rev.name);
1397 break; 1397 break;
1398 } 1398 }
1399 1399
1400 default: 1400 default:
1401 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd); 1401 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
1402 ret = -EINVAL; 1402 ret = -EINVAL;
1403 } 1403 }
1404 1404
1405 return ret; 1405 return ret;
1406 } 1406 }
1407 1407
1408 /* Registration hooks for targets. */ 1408 /* Registration hooks for targets. */
1409 int 1409 int
1410 ipt_register_target(struct ipt_target *target) 1410 ipt_register_target(struct ipt_target *target)
1411 { 1411 {
1412 int ret; 1412 int ret;
1413 1413
1414 ret = down_interruptible(&ipt_mutex); 1414 ret = down_interruptible(&ipt_mutex);
1415 if (ret != 0) 1415 if (ret != 0)
1416 return ret; 1416 return ret;
1417 list_add(&target->list, &ipt_target); 1417 list_add(&target->list, &ipt_target);
1418 up(&ipt_mutex); 1418 up(&ipt_mutex);
1419 return ret; 1419 return ret;
1420 } 1420 }
1421 1421
1422 void 1422 void
1423 ipt_unregister_target(struct ipt_target *target) 1423 ipt_unregister_target(struct ipt_target *target)
1424 { 1424 {
1425 down(&ipt_mutex); 1425 down(&ipt_mutex);
1426 LIST_DELETE(&ipt_target, target); 1426 LIST_DELETE(&ipt_target, target);
1427 up(&ipt_mutex); 1427 up(&ipt_mutex);
1428 } 1428 }
1429 1429
1430 int 1430 int
1431 ipt_register_match(struct ipt_match *match) 1431 ipt_register_match(struct ipt_match *match)
1432 { 1432 {
1433 int ret; 1433 int ret;
1434 1434
1435 ret = down_interruptible(&ipt_mutex); 1435 ret = down_interruptible(&ipt_mutex);
1436 if (ret != 0) 1436 if (ret != 0)
1437 return ret; 1437 return ret;
1438 1438
1439 list_add(&match->list, &ipt_match); 1439 list_add(&match->list, &ipt_match);
1440 up(&ipt_mutex); 1440 up(&ipt_mutex);
1441 1441
1442 return ret; 1442 return ret;
1443 } 1443 }
1444 1444
1445 void 1445 void
1446 ipt_unregister_match(struct ipt_match *match) 1446 ipt_unregister_match(struct ipt_match *match)
1447 { 1447 {
1448 down(&ipt_mutex); 1448 down(&ipt_mutex);
1449 LIST_DELETE(&ipt_match, match); 1449 LIST_DELETE(&ipt_match, match);
1450 up(&ipt_mutex); 1450 up(&ipt_mutex);
1451 } 1451 }
1452 1452
1453 int ipt_register_table(struct ipt_table *table, const struct ipt_replace *repl) 1453 int ipt_register_table(struct ipt_table *table, const struct ipt_replace *repl)
1454 { 1454 {
1455 int ret; 1455 int ret;
1456 struct ipt_table_info *newinfo; 1456 struct ipt_table_info *newinfo;
1457 static struct ipt_table_info bootstrap 1457 static struct ipt_table_info bootstrap
1458 = { 0, 0, 0, { 0 }, { 0 }, { } }; 1458 = { 0, 0, 0, { 0 }, { 0 }, { } };
1459 1459
1460 newinfo = vmalloc(sizeof(struct ipt_table_info) 1460 newinfo = vmalloc(sizeof(struct ipt_table_info)
1461 + SMP_ALIGN(repl->size) * num_possible_cpus()); 1461 + SMP_ALIGN(repl->size) * num_possible_cpus());
1462 if (!newinfo) 1462 if (!newinfo)
1463 return -ENOMEM; 1463 return -ENOMEM;
1464 1464
1465 memcpy(newinfo->entries, repl->entries, repl->size); 1465 memcpy(newinfo->entries, repl->entries, repl->size);
1466 1466
1467 ret = translate_table(table->name, table->valid_hooks, 1467 ret = translate_table(table->name, table->valid_hooks,
1468 newinfo, repl->size, 1468 newinfo, repl->size,
1469 repl->num_entries, 1469 repl->num_entries,
1470 repl->hook_entry, 1470 repl->hook_entry,
1471 repl->underflow); 1471 repl->underflow);
1472 if (ret != 0) { 1472 if (ret != 0) {
1473 vfree(newinfo); 1473 vfree(newinfo);
1474 return ret; 1474 return ret;
1475 } 1475 }
1476 1476
1477 ret = down_interruptible(&ipt_mutex); 1477 ret = down_interruptible(&ipt_mutex);
1478 if (ret != 0) { 1478 if (ret != 0) {
1479 vfree(newinfo); 1479 vfree(newinfo);
1480 return ret; 1480 return ret;
1481 } 1481 }
1482 1482
1483 /* Don't autoload: we'd eat our tail... */ 1483 /* Don't autoload: we'd eat our tail... */
1484 if (list_named_find(&ipt_tables, table->name)) { 1484 if (list_named_find(&ipt_tables, table->name)) {
1485 ret = -EEXIST; 1485 ret = -EEXIST;
1486 goto free_unlock; 1486 goto free_unlock;
1487 } 1487 }
1488 1488
1489 /* Simplifies replace_table code. */ 1489 /* Simplifies replace_table code. */
1490 table->private = &bootstrap; 1490 table->private = &bootstrap;
1491 if (!replace_table(table, 0, newinfo, &ret)) 1491 if (!replace_table(table, 0, newinfo, &ret))
1492 goto free_unlock; 1492 goto free_unlock;
1493 1493
1494 duprintf("table->private->number = %u\n", 1494 duprintf("table->private->number = %u\n",
1495 table->private->number); 1495 table->private->number);
1496 1496
1497 /* save number of initial entries */ 1497 /* save number of initial entries */
1498 table->private->initial_entries = table->private->number; 1498 table->private->initial_entries = table->private->number;
1499 1499
1500 rwlock_init(&table->lock); 1500 rwlock_init(&table->lock);
1501 list_prepend(&ipt_tables, table); 1501 list_prepend(&ipt_tables, table);
1502 1502
1503 unlock: 1503 unlock:
1504 up(&ipt_mutex); 1504 up(&ipt_mutex);
1505 return ret; 1505 return ret;
1506 1506
1507 free_unlock: 1507 free_unlock:
1508 vfree(newinfo); 1508 vfree(newinfo);
1509 goto unlock; 1509 goto unlock;
1510 } 1510 }
1511 1511
1512 void ipt_unregister_table(struct ipt_table *table) 1512 void ipt_unregister_table(struct ipt_table *table)
1513 { 1513 {
1514 down(&ipt_mutex); 1514 down(&ipt_mutex);
1515 LIST_DELETE(&ipt_tables, table); 1515 LIST_DELETE(&ipt_tables, table);
1516 up(&ipt_mutex); 1516 up(&ipt_mutex);
1517 1517
1518 /* Decrease module usage counts and free resources */ 1518 /* Decrease module usage counts and free resources */
1519 IPT_ENTRY_ITERATE(table->private->entries, table->private->size, 1519 IPT_ENTRY_ITERATE(table->private->entries, table->private->size,
1520 cleanup_entry, NULL); 1520 cleanup_entry, NULL);
1521 vfree(table->private); 1521 vfree(table->private);
1522 } 1522 }
1523 1523
1524 /* Returns 1 if the port is matched by the range, 0 otherwise */ 1524 /* Returns 1 if the port is matched by the range, 0 otherwise */
1525 static inline int 1525 static inline int
1526 port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert) 1526 port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
1527 { 1527 {
1528 int ret; 1528 int ret;
1529 1529
1530 ret = (port >= min && port <= max) ^ invert; 1530 ret = (port >= min && port <= max) ^ invert;
1531 return ret; 1531 return ret;
1532 } 1532 }
1533 1533
1534 static int 1534 static int
1535 tcp_find_option(u_int8_t option, 1535 tcp_find_option(u_int8_t option,
1536 const struct sk_buff *skb, 1536 const struct sk_buff *skb,
1537 unsigned int optlen, 1537 unsigned int optlen,
1538 int invert, 1538 int invert,
1539 int *hotdrop) 1539 int *hotdrop)
1540 { 1540 {
1541 /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ 1541 /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
1542 u_int8_t _opt[60 - sizeof(struct tcphdr)], *op; 1542 u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
1543 unsigned int i; 1543 unsigned int i;
1544 1544
1545 duprintf("tcp_match: finding option\n"); 1545 duprintf("tcp_match: finding option\n");
1546 1546
1547 if (!optlen) 1547 if (!optlen)
1548 return invert; 1548 return invert;
1549 1549
1550 /* If we don't have the whole header, drop packet. */ 1550 /* If we don't have the whole header, drop packet. */
1551 op = skb_header_pointer(skb, 1551 op = skb_header_pointer(skb,
1552 skb->nh.iph->ihl*4 + sizeof(struct tcphdr), 1552 skb->nh.iph->ihl*4 + sizeof(struct tcphdr),
1553 optlen, _opt); 1553 optlen, _opt);
1554 if (op == NULL) { 1554 if (op == NULL) {
1555 *hotdrop = 1; 1555 *hotdrop = 1;
1556 return 0; 1556 return 0;
1557 } 1557 }
1558 1558
1559 for (i = 0; i < optlen; ) { 1559 for (i = 0; i < optlen; ) {
1560 if (op[i] == option) return !invert; 1560 if (op[i] == option) return !invert;
1561 if (op[i] < 2) i++; 1561 if (op[i] < 2) i++;
1562 else i += op[i+1]?:1; 1562 else i += op[i+1]?:1;
1563 } 1563 }
1564 1564
1565 return invert; 1565 return invert;
1566 } 1566 }
1567 1567
1568 static int 1568 static int
1569 tcp_match(const struct sk_buff *skb, 1569 tcp_match(const struct sk_buff *skb,
1570 const struct net_device *in, 1570 const struct net_device *in,
1571 const struct net_device *out, 1571 const struct net_device *out,
1572 const void *matchinfo, 1572 const void *matchinfo,
1573 int offset, 1573 int offset,
1574 int *hotdrop) 1574 int *hotdrop)
1575 { 1575 {
1576 struct tcphdr _tcph, *th; 1576 struct tcphdr _tcph, *th;
1577 const struct ipt_tcp *tcpinfo = matchinfo; 1577 const struct ipt_tcp *tcpinfo = matchinfo;
1578 1578
1579 if (offset) { 1579 if (offset) {
1580 /* To quote Alan: 1580 /* To quote Alan:
1581 1581
1582 Don't allow a fragment of TCP 8 bytes in. Nobody normal 1582 Don't allow a fragment of TCP 8 bytes in. Nobody normal
1583 causes this. Its a cracker trying to break in by doing a 1583 causes this. Its a cracker trying to break in by doing a
1584 flag overwrite to pass the direction checks. 1584 flag overwrite to pass the direction checks.
1585 */ 1585 */
1586 if (offset == 1) { 1586 if (offset == 1) {
1587 duprintf("Dropping evil TCP offset=1 frag.\n"); 1587 duprintf("Dropping evil TCP offset=1 frag.\n");
1588 *hotdrop = 1; 1588 *hotdrop = 1;
1589 } 1589 }
1590 /* Must not be a fragment. */ 1590 /* Must not be a fragment. */
1591 return 0; 1591 return 0;
1592 } 1592 }
1593 1593
1594 #define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg)) 1594 #define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
1595 1595
1596 th = skb_header_pointer(skb, skb->nh.iph->ihl*4, 1596 th = skb_header_pointer(skb, skb->nh.iph->ihl*4,
1597 sizeof(_tcph), &_tcph); 1597 sizeof(_tcph), &_tcph);
1598 if (th == NULL) { 1598 if (th == NULL) {
1599 /* We've been asked to examine this packet, and we 1599 /* We've been asked to examine this packet, and we
1600 can't. Hence, no choice but to drop. */ 1600 can't. Hence, no choice but to drop. */
1601 duprintf("Dropping evil TCP offset=0 tinygram.\n"); 1601 duprintf("Dropping evil TCP offset=0 tinygram.\n");
1602 *hotdrop = 1; 1602 *hotdrop = 1;
1603 return 0; 1603 return 0;
1604 } 1604 }
1605 1605
1606 if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1], 1606 if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
1607 ntohs(th->source), 1607 ntohs(th->source),
1608 !!(tcpinfo->invflags & IPT_TCP_INV_SRCPT))) 1608 !!(tcpinfo->invflags & IPT_TCP_INV_SRCPT)))
1609 return 0; 1609 return 0;
1610 if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1], 1610 if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
1611 ntohs(th->dest), 1611 ntohs(th->dest),
1612 !!(tcpinfo->invflags & IPT_TCP_INV_DSTPT))) 1612 !!(tcpinfo->invflags & IPT_TCP_INV_DSTPT)))
1613 return 0; 1613 return 0;
1614 if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask) 1614 if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
1615 == tcpinfo->flg_cmp, 1615 == tcpinfo->flg_cmp,
1616 IPT_TCP_INV_FLAGS)) 1616 IPT_TCP_INV_FLAGS))
1617 return 0; 1617 return 0;
1618 if (tcpinfo->option) { 1618 if (tcpinfo->option) {
1619 if (th->doff * 4 < sizeof(_tcph)) { 1619 if (th->doff * 4 < sizeof(_tcph)) {
1620 *hotdrop = 1; 1620 *hotdrop = 1;
1621 return 0; 1621 return 0;
1622 } 1622 }
1623 if (!tcp_find_option(tcpinfo->option, skb, 1623 if (!tcp_find_option(tcpinfo->option, skb,
1624 th->doff*4 - sizeof(_tcph), 1624 th->doff*4 - sizeof(_tcph),
1625 tcpinfo->invflags & IPT_TCP_INV_OPTION, 1625 tcpinfo->invflags & IPT_TCP_INV_OPTION,
1626 hotdrop)) 1626 hotdrop))
1627 return 0; 1627 return 0;
1628 } 1628 }
1629 return 1; 1629 return 1;
1630 } 1630 }
1631 1631
1632 /* Called when user tries to insert an entry of this type. */ 1632 /* Called when user tries to insert an entry of this type. */
1633 static int 1633 static int
1634 tcp_checkentry(const char *tablename, 1634 tcp_checkentry(const char *tablename,
1635 const struct ipt_ip *ip, 1635 const struct ipt_ip *ip,
1636 void *matchinfo, 1636 void *matchinfo,
1637 unsigned int matchsize, 1637 unsigned int matchsize,
1638 unsigned int hook_mask) 1638 unsigned int hook_mask)
1639 { 1639 {
1640 const struct ipt_tcp *tcpinfo = matchinfo; 1640 const struct ipt_tcp *tcpinfo = matchinfo;
1641 1641
1642 /* Must specify proto == TCP, and no unknown invflags */ 1642 /* Must specify proto == TCP, and no unknown invflags */
1643 return ip->proto == IPPROTO_TCP 1643 return ip->proto == IPPROTO_TCP
1644 && !(ip->invflags & IPT_INV_PROTO) 1644 && !(ip->invflags & IPT_INV_PROTO)
1645 && matchsize == IPT_ALIGN(sizeof(struct ipt_tcp)) 1645 && matchsize == IPT_ALIGN(sizeof(struct ipt_tcp))
1646 && !(tcpinfo->invflags & ~IPT_TCP_INV_MASK); 1646 && !(tcpinfo->invflags & ~IPT_TCP_INV_MASK);
1647 } 1647 }
1648 1648
1649 static int 1649 static int
1650 udp_match(const struct sk_buff *skb, 1650 udp_match(const struct sk_buff *skb,
1651 const struct net_device *in, 1651 const struct net_device *in,
1652 const struct net_device *out, 1652 const struct net_device *out,
1653 const void *matchinfo, 1653 const void *matchinfo,
1654 int offset, 1654 int offset,
1655 int *hotdrop) 1655 int *hotdrop)
1656 { 1656 {
1657 struct udphdr _udph, *uh; 1657 struct udphdr _udph, *uh;
1658 const struct ipt_udp *udpinfo = matchinfo; 1658 const struct ipt_udp *udpinfo = matchinfo;
1659 1659
1660 /* Must not be a fragment. */ 1660 /* Must not be a fragment. */
1661 if (offset) 1661 if (offset)
1662 return 0; 1662 return 0;
1663 1663
1664 uh = skb_header_pointer(skb, skb->nh.iph->ihl*4, 1664 uh = skb_header_pointer(skb, skb->nh.iph->ihl*4,
1665 sizeof(_udph), &_udph); 1665 sizeof(_udph), &_udph);
1666 if (uh == NULL) { 1666 if (uh == NULL) {
1667 /* We've been asked to examine this packet, and we 1667 /* We've been asked to examine this packet, and we
1668 can't. Hence, no choice but to drop. */ 1668 can't. Hence, no choice but to drop. */
1669 duprintf("Dropping evil UDP tinygram.\n"); 1669 duprintf("Dropping evil UDP tinygram.\n");
1670 *hotdrop = 1; 1670 *hotdrop = 1;
1671 return 0; 1671 return 0;
1672 } 1672 }
1673 1673
1674 return port_match(udpinfo->spts[0], udpinfo->spts[1], 1674 return port_match(udpinfo->spts[0], udpinfo->spts[1],
1675 ntohs(uh->source), 1675 ntohs(uh->source),
1676 !!(udpinfo->invflags & IPT_UDP_INV_SRCPT)) 1676 !!(udpinfo->invflags & IPT_UDP_INV_SRCPT))
1677 && port_match(udpinfo->dpts[0], udpinfo->dpts[1], 1677 && port_match(udpinfo->dpts[0], udpinfo->dpts[1],
1678 ntohs(uh->dest), 1678 ntohs(uh->dest),
1679 !!(udpinfo->invflags & IPT_UDP_INV_DSTPT)); 1679 !!(udpinfo->invflags & IPT_UDP_INV_DSTPT));
1680 } 1680 }
1681 1681
1682 /* Called when user tries to insert an entry of this type. */ 1682 /* Called when user tries to insert an entry of this type. */
1683 static int 1683 static int
1684 udp_checkentry(const char *tablename, 1684 udp_checkentry(const char *tablename,
1685 const struct ipt_ip *ip, 1685 const struct ipt_ip *ip,
1686 void *matchinfo, 1686 void *matchinfo,
1687 unsigned int matchinfosize, 1687 unsigned int matchinfosize,
1688 unsigned int hook_mask) 1688 unsigned int hook_mask)
1689 { 1689 {
1690 const struct ipt_udp *udpinfo = matchinfo; 1690 const struct ipt_udp *udpinfo = matchinfo;
1691 1691
1692 /* Must specify proto == UDP, and no unknown invflags */ 1692 /* Must specify proto == UDP, and no unknown invflags */
1693 if (ip->proto != IPPROTO_UDP || (ip->invflags & IPT_INV_PROTO)) { 1693 if (ip->proto != IPPROTO_UDP || (ip->invflags & IPT_INV_PROTO)) {
1694 duprintf("ipt_udp: Protocol %u != %u\n", ip->proto, 1694 duprintf("ipt_udp: Protocol %u != %u\n", ip->proto,
1695 IPPROTO_UDP); 1695 IPPROTO_UDP);
1696 return 0; 1696 return 0;
1697 } 1697 }
1698 if (matchinfosize != IPT_ALIGN(sizeof(struct ipt_udp))) { 1698 if (matchinfosize != IPT_ALIGN(sizeof(struct ipt_udp))) {
1699 duprintf("ipt_udp: matchsize %u != %u\n", 1699 duprintf("ipt_udp: matchsize %u != %u\n",
1700 matchinfosize, IPT_ALIGN(sizeof(struct ipt_udp))); 1700 matchinfosize, IPT_ALIGN(sizeof(struct ipt_udp)));
1701 return 0; 1701 return 0;
1702 } 1702 }
1703 if (udpinfo->invflags & ~IPT_UDP_INV_MASK) { 1703 if (udpinfo->invflags & ~IPT_UDP_INV_MASK) {
1704 duprintf("ipt_udp: unknown flags %X\n", 1704 duprintf("ipt_udp: unknown flags %X\n",
1705 udpinfo->invflags); 1705 udpinfo->invflags);
1706 return 0; 1706 return 0;
1707 } 1707 }
1708 1708
1709 return 1; 1709 return 1;
1710 } 1710 }
1711 1711
1712 /* Returns 1 if the type and code is matched by the range, 0 otherwise */ 1712 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
1713 static inline int 1713 static inline int
1714 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code, 1714 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
1715 u_int8_t type, u_int8_t code, 1715 u_int8_t type, u_int8_t code,
1716 int invert) 1716 int invert)
1717 { 1717 {
1718 return ((test_type == 0xFF) || (type == test_type && code >= min_code && code <= max_code)) 1718 return ((test_type == 0xFF) || (type == test_type && code >= min_code && code <= max_code))
1719 ^ invert; 1719 ^ invert;
1720 } 1720 }
1721 1721
1722 static int 1722 static int
1723 icmp_match(const struct sk_buff *skb, 1723 icmp_match(const struct sk_buff *skb,
1724 const struct net_device *in, 1724 const struct net_device *in,
1725 const struct net_device *out, 1725 const struct net_device *out,
1726 const void *matchinfo, 1726 const void *matchinfo,
1727 int offset, 1727 int offset,
1728 int *hotdrop) 1728 int *hotdrop)
1729 { 1729 {
1730 struct icmphdr _icmph, *ic; 1730 struct icmphdr _icmph, *ic;
1731 const struct ipt_icmp *icmpinfo = matchinfo; 1731 const struct ipt_icmp *icmpinfo = matchinfo;
1732 1732
1733 /* Must not be a fragment. */ 1733 /* Must not be a fragment. */
1734 if (offset) 1734 if (offset)
1735 return 0; 1735 return 0;
1736 1736
1737 ic = skb_header_pointer(skb, skb->nh.iph->ihl*4, 1737 ic = skb_header_pointer(skb, skb->nh.iph->ihl*4,
1738 sizeof(_icmph), &_icmph); 1738 sizeof(_icmph), &_icmph);
1739 if (ic == NULL) { 1739 if (ic == NULL) {
1740 /* We've been asked to examine this packet, and we 1740 /* We've been asked to examine this packet, and we
1741 * can't. Hence, no choice but to drop. 1741 * can't. Hence, no choice but to drop.
1742 */ 1742 */
1743 duprintf("Dropping evil ICMP tinygram.\n"); 1743 duprintf("Dropping evil ICMP tinygram.\n");
1744 *hotdrop = 1; 1744 *hotdrop = 1;
1745 return 0; 1745 return 0;
1746 } 1746 }
1747 1747
1748 return icmp_type_code_match(icmpinfo->type, 1748 return icmp_type_code_match(icmpinfo->type,
1749 icmpinfo->code[0], 1749 icmpinfo->code[0],
1750 icmpinfo->code[1], 1750 icmpinfo->code[1],
1751 ic->type, ic->code, 1751 ic->type, ic->code,
1752 !!(icmpinfo->invflags&IPT_ICMP_INV)); 1752 !!(icmpinfo->invflags&IPT_ICMP_INV));
1753 } 1753 }
1754 1754
1755 /* Called when user tries to insert an entry of this type. */ 1755 /* Called when user tries to insert an entry of this type. */
1756 static int 1756 static int
1757 icmp_checkentry(const char *tablename, 1757 icmp_checkentry(const char *tablename,
1758 const struct ipt_ip *ip, 1758 const struct ipt_ip *ip,
1759 void *matchinfo, 1759 void *matchinfo,
1760 unsigned int matchsize, 1760 unsigned int matchsize,
1761 unsigned int hook_mask) 1761 unsigned int hook_mask)
1762 { 1762 {
1763 const struct ipt_icmp *icmpinfo = matchinfo; 1763 const struct ipt_icmp *icmpinfo = matchinfo;
1764 1764
1765 /* Must specify proto == ICMP, and no unknown invflags */ 1765 /* Must specify proto == ICMP, and no unknown invflags */
1766 return ip->proto == IPPROTO_ICMP 1766 return ip->proto == IPPROTO_ICMP
1767 && !(ip->invflags & IPT_INV_PROTO) 1767 && !(ip->invflags & IPT_INV_PROTO)
1768 && matchsize == IPT_ALIGN(sizeof(struct ipt_icmp)) 1768 && matchsize == IPT_ALIGN(sizeof(struct ipt_icmp))
1769 && !(icmpinfo->invflags & ~IPT_ICMP_INV); 1769 && !(icmpinfo->invflags & ~IPT_ICMP_INV);
1770 } 1770 }
1771 1771
1772 /* The built-in targets: standard (NULL) and error. */ 1772 /* The built-in targets: standard (NULL) and error. */
1773 static struct ipt_target ipt_standard_target = { 1773 static struct ipt_target ipt_standard_target = {
1774 .name = IPT_STANDARD_TARGET, 1774 .name = IPT_STANDARD_TARGET,
1775 }; 1775 };
1776 1776
1777 static struct ipt_target ipt_error_target = { 1777 static struct ipt_target ipt_error_target = {
1778 .name = IPT_ERROR_TARGET, 1778 .name = IPT_ERROR_TARGET,
1779 .target = ipt_error, 1779 .target = ipt_error,
1780 }; 1780 };
1781 1781
1782 static struct nf_sockopt_ops ipt_sockopts = { 1782 static struct nf_sockopt_ops ipt_sockopts = {
1783 .pf = PF_INET, 1783 .pf = PF_INET,
1784 .set_optmin = IPT_BASE_CTL, 1784 .set_optmin = IPT_BASE_CTL,
1785 .set_optmax = IPT_SO_SET_MAX+1, 1785 .set_optmax = IPT_SO_SET_MAX+1,
1786 .set = do_ipt_set_ctl, 1786 .set = do_ipt_set_ctl,
1787 .get_optmin = IPT_BASE_CTL, 1787 .get_optmin = IPT_BASE_CTL,
1788 .get_optmax = IPT_SO_GET_MAX+1, 1788 .get_optmax = IPT_SO_GET_MAX+1,
1789 .get = do_ipt_get_ctl, 1789 .get = do_ipt_get_ctl,
1790 }; 1790 };
1791 1791
1792 static struct ipt_match tcp_matchstruct = { 1792 static struct ipt_match tcp_matchstruct = {
1793 .name = "tcp", 1793 .name = "tcp",
1794 .match = &tcp_match, 1794 .match = &tcp_match,
1795 .checkentry = &tcp_checkentry, 1795 .checkentry = &tcp_checkentry,
1796 }; 1796 };
1797 1797
1798 static struct ipt_match udp_matchstruct = { 1798 static struct ipt_match udp_matchstruct = {
1799 .name = "udp", 1799 .name = "udp",
1800 .match = &udp_match, 1800 .match = &udp_match,
1801 .checkentry = &udp_checkentry, 1801 .checkentry = &udp_checkentry,
1802 }; 1802 };
1803 1803
1804 static struct ipt_match icmp_matchstruct = { 1804 static struct ipt_match icmp_matchstruct = {
1805 .name = "icmp", 1805 .name = "icmp",
1806 .match = &icmp_match, 1806 .match = &icmp_match,
1807 .checkentry = &icmp_checkentry, 1807 .checkentry = &icmp_checkentry,
1808 }; 1808 };
1809 1809
1810 #ifdef CONFIG_PROC_FS 1810 #ifdef CONFIG_PROC_FS
1811 static inline int print_name(const char *i, 1811 static inline int print_name(const char *i,
1812 off_t start_offset, char *buffer, int length, 1812 off_t start_offset, char *buffer, int length,
1813 off_t *pos, unsigned int *count) 1813 off_t *pos, unsigned int *count)
1814 { 1814 {
1815 if ((*count)++ >= start_offset) { 1815 if ((*count)++ >= start_offset) {
1816 unsigned int namelen; 1816 unsigned int namelen;
1817 1817
1818 namelen = sprintf(buffer + *pos, "%s\n", 1818 namelen = sprintf(buffer + *pos, "%s\n",
1819 i + sizeof(struct list_head)); 1819 i + sizeof(struct list_head));
1820 if (*pos + namelen > length) { 1820 if (*pos + namelen > length) {
1821 /* Stop iterating */ 1821 /* Stop iterating */
1822 return 1; 1822 return 1;
1823 } 1823 }
1824 *pos += namelen; 1824 *pos += namelen;
1825 } 1825 }
1826 return 0; 1826 return 0;
1827 } 1827 }
1828 1828
1829 static inline int print_target(const struct ipt_target *t, 1829 static inline int print_target(const struct ipt_target *t,
1830 off_t start_offset, char *buffer, int length, 1830 off_t start_offset, char *buffer, int length,
1831 off_t *pos, unsigned int *count) 1831 off_t *pos, unsigned int *count)
1832 { 1832 {
1833 if (t == &ipt_standard_target || t == &ipt_error_target) 1833 if (t == &ipt_standard_target || t == &ipt_error_target)
1834 return 0; 1834 return 0;
1835 return print_name((char *)t, start_offset, buffer, length, pos, count); 1835 return print_name((char *)t, start_offset, buffer, length, pos, count);
1836 } 1836 }
1837 1837
1838 static int ipt_get_tables(char *buffer, char **start, off_t offset, int length) 1838 static int ipt_get_tables(char *buffer, char **start, off_t offset, int length)
1839 { 1839 {
1840 off_t pos = 0; 1840 off_t pos = 0;
1841 unsigned int count = 0; 1841 unsigned int count = 0;
1842 1842
1843 if (down_interruptible(&ipt_mutex) != 0) 1843 if (down_interruptible(&ipt_mutex) != 0)
1844 return 0; 1844 return 0;
1845 1845
1846 LIST_FIND(&ipt_tables, print_name, void *, 1846 LIST_FIND(&ipt_tables, print_name, void *,
1847 offset, buffer, length, &pos, &count); 1847 offset, buffer, length, &pos, &count);
1848 1848
1849 up(&ipt_mutex); 1849 up(&ipt_mutex);
1850 1850
1851 /* `start' hack - see fs/proc/generic.c line ~105 */ 1851 /* `start' hack - see fs/proc/generic.c line ~105 */
1852 *start=(char *)((unsigned long)count-offset); 1852 *start=(char *)((unsigned long)count-offset);
1853 return pos; 1853 return pos;
1854 } 1854 }
1855 1855
1856 static int ipt_get_targets(char *buffer, char **start, off_t offset, int length) 1856 static int ipt_get_targets(char *buffer, char **start, off_t offset, int length)
1857 { 1857 {
1858 off_t pos = 0; 1858 off_t pos = 0;
1859 unsigned int count = 0; 1859 unsigned int count = 0;
1860 1860
1861 if (down_interruptible(&ipt_mutex) != 0) 1861 if (down_interruptible(&ipt_mutex) != 0)
1862 return 0; 1862 return 0;
1863 1863
1864 LIST_FIND(&ipt_target, print_target, struct ipt_target *, 1864 LIST_FIND(&ipt_target, print_target, struct ipt_target *,
1865 offset, buffer, length, &pos, &count); 1865 offset, buffer, length, &pos, &count);
1866 1866
1867 up(&ipt_mutex); 1867 up(&ipt_mutex);
1868 1868
1869 *start = (char *)((unsigned long)count - offset); 1869 *start = (char *)((unsigned long)count - offset);
1870 return pos; 1870 return pos;
1871 } 1871 }
1872 1872
1873 static int ipt_get_matches(char *buffer, char **start, off_t offset, int length) 1873 static int ipt_get_matches(char *buffer, char **start, off_t offset, int length)
1874 { 1874 {
1875 off_t pos = 0; 1875 off_t pos = 0;
1876 unsigned int count = 0; 1876 unsigned int count = 0;
1877 1877
1878 if (down_interruptible(&ipt_mutex) != 0) 1878 if (down_interruptible(&ipt_mutex) != 0)
1879 return 0; 1879 return 0;
1880 1880
1881 LIST_FIND(&ipt_match, print_name, void *, 1881 LIST_FIND(&ipt_match, print_name, void *,
1882 offset, buffer, length, &pos, &count); 1882 offset, buffer, length, &pos, &count);
1883 1883
1884 up(&ipt_mutex); 1884 up(&ipt_mutex);
1885 1885
1886 *start = (char *)((unsigned long)count - offset); 1886 *start = (char *)((unsigned long)count - offset);
1887 return pos; 1887 return pos;
1888 } 1888 }
1889 1889
1890 static struct { char *name; get_info_t *get_info; } ipt_proc_entry[] = 1890 static struct { char *name; get_info_t *get_info; } ipt_proc_entry[] =
1891 { { "ip_tables_names", ipt_get_tables }, 1891 { { "ip_tables_names", ipt_get_tables },
1892 { "ip_tables_targets", ipt_get_targets }, 1892 { "ip_tables_targets", ipt_get_targets },
1893 { "ip_tables_matches", ipt_get_matches }, 1893 { "ip_tables_matches", ipt_get_matches },
1894 { NULL, NULL} }; 1894 { NULL, NULL} };
1895 #endif /*CONFIG_PROC_FS*/ 1895 #endif /*CONFIG_PROC_FS*/
1896 1896
1897 static int __init init(void) 1897 static int __init init(void)
1898 { 1898 {
1899 int ret; 1899 int ret;
1900 1900
1901 /* Noone else will be downing sem now, so we won't sleep */ 1901 /* Noone else will be downing sem now, so we won't sleep */
1902 down(&ipt_mutex); 1902 down(&ipt_mutex);
1903 list_append(&ipt_target, &ipt_standard_target); 1903 list_append(&ipt_target, &ipt_standard_target);
1904 list_append(&ipt_target, &ipt_error_target); 1904 list_append(&ipt_target, &ipt_error_target);
1905 list_append(&ipt_match, &tcp_matchstruct); 1905 list_append(&ipt_match, &tcp_matchstruct);
1906 list_append(&ipt_match, &udp_matchstruct); 1906 list_append(&ipt_match, &udp_matchstruct);
1907 list_append(&ipt_match, &icmp_matchstruct); 1907 list_append(&ipt_match, &icmp_matchstruct);
1908 up(&ipt_mutex); 1908 up(&ipt_mutex);
1909 1909
1910 /* Register setsockopt */ 1910 /* Register setsockopt */
1911 ret = nf_register_sockopt(&ipt_sockopts); 1911 ret = nf_register_sockopt(&ipt_sockopts);
1912 if (ret < 0) { 1912 if (ret < 0) {
1913 duprintf("Unable to register sockopts.\n"); 1913 duprintf("Unable to register sockopts.\n");
1914 return ret; 1914 return ret;
1915 } 1915 }
1916 1916
1917 #ifdef CONFIG_PROC_FS 1917 #ifdef CONFIG_PROC_FS
1918 { 1918 {
1919 struct proc_dir_entry *proc; 1919 struct proc_dir_entry *proc;
1920 int i; 1920 int i;
1921 1921
1922 for (i = 0; ipt_proc_entry[i].name; i++) { 1922 for (i = 0; ipt_proc_entry[i].name; i++) {
1923 proc = proc_net_create(ipt_proc_entry[i].name, 0, 1923 proc = proc_net_create(ipt_proc_entry[i].name, 0,
1924 ipt_proc_entry[i].get_info); 1924 ipt_proc_entry[i].get_info);
1925 if (!proc) { 1925 if (!proc) {
1926 while (--i >= 0) 1926 while (--i >= 0)
1927 proc_net_remove(ipt_proc_entry[i].name); 1927 proc_net_remove(ipt_proc_entry[i].name);
1928 nf_unregister_sockopt(&ipt_sockopts); 1928 nf_unregister_sockopt(&ipt_sockopts);
1929 return -ENOMEM; 1929 return -ENOMEM;
1930 } 1930 }
1931 proc->owner = THIS_MODULE; 1931 proc->owner = THIS_MODULE;
1932 } 1932 }
1933 } 1933 }
1934 #endif 1934 #endif
1935 1935
1936 printk("ip_tables: (C) 2000-2002 Netfilter core team\n"); 1936 printk("ip_tables: (C) 2000-2002 Netfilter core team\n");
1937 return 0; 1937 return 0;
1938 } 1938 }
1939 1939
1940 static void __exit fini(void) 1940 static void __exit fini(void)
1941 { 1941 {
1942 nf_unregister_sockopt(&ipt_sockopts); 1942 nf_unregister_sockopt(&ipt_sockopts);
1943 #ifdef CONFIG_PROC_FS 1943 #ifdef CONFIG_PROC_FS
1944 { 1944 {
1945 int i; 1945 int i;
1946 for (i = 0; ipt_proc_entry[i].name; i++) 1946 for (i = 0; ipt_proc_entry[i].name; i++)
1947 proc_net_remove(ipt_proc_entry[i].name); 1947 proc_net_remove(ipt_proc_entry[i].name);
1948 } 1948 }
1949 #endif 1949 #endif
1950 } 1950 }
1951 1951
1952 EXPORT_SYMBOL(ipt_register_table); 1952 EXPORT_SYMBOL(ipt_register_table);
1953 EXPORT_SYMBOL(ipt_unregister_table); 1953 EXPORT_SYMBOL(ipt_unregister_table);
1954 EXPORT_SYMBOL(ipt_register_match); 1954 EXPORT_SYMBOL(ipt_register_match);
1955 EXPORT_SYMBOL(ipt_unregister_match); 1955 EXPORT_SYMBOL(ipt_unregister_match);
1956 EXPORT_SYMBOL(ipt_do_table); 1956 EXPORT_SYMBOL(ipt_do_table);
1957 EXPORT_SYMBOL(ipt_register_target); 1957 EXPORT_SYMBOL(ipt_register_target);
1958 EXPORT_SYMBOL(ipt_unregister_target); 1958 EXPORT_SYMBOL(ipt_unregister_target);
1959 EXPORT_SYMBOL(ipt_find_target); 1959 EXPORT_SYMBOL(ipt_find_target);
1960 1960
1961 module_init(init); 1961 module_init(init);
1962 module_exit(fini); 1962 module_exit(fini);
1963 1963
net/ipv6/netfilter/ip6_tables.c
1 /* 1 /*
2 * Packet matching code. 2 * Packet matching code.
3 * 3 *
4 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling 4 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
5 * Copyright (C) 2000-2002 Netfilter core team <coreteam@netfilter.org> 5 * Copyright (C) 2000-2002 Netfilter core team <coreteam@netfilter.org>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation. 9 * published by the Free Software Foundation.
10 * 10 *
11 * 19 Jan 2002 Harald Welte <laforge@gnumonks.org> 11 * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
12 * - increase module usage count as soon as we have rules inside 12 * - increase module usage count as soon as we have rules inside
13 * a table 13 * a table
14 * 06 Jun 2002 Andras Kis-Szabo <kisza@sch.bme.hu> 14 * 06 Jun 2002 Andras Kis-Szabo <kisza@sch.bme.hu>
15 * - new extension header parser code 15 * - new extension header parser code
16 */ 16 */
17 #include <linux/config.h> 17 #include <linux/config.h>
18 #include <linux/skbuff.h> 18 #include <linux/skbuff.h>
19 #include <linux/kmod.h> 19 #include <linux/kmod.h>
20 #include <linux/vmalloc.h> 20 #include <linux/vmalloc.h>
21 #include <linux/netdevice.h> 21 #include <linux/netdevice.h>
22 #include <linux/module.h> 22 #include <linux/module.h>
23 #include <linux/tcp.h> 23 #include <linux/tcp.h>
24 #include <linux/udp.h> 24 #include <linux/udp.h>
25 #include <linux/icmpv6.h> 25 #include <linux/icmpv6.h>
26 #include <net/ip.h> 26 #include <net/ip.h>
27 #include <net/ipv6.h> 27 #include <net/ipv6.h>
28 #include <asm/uaccess.h> 28 #include <asm/uaccess.h>
29 #include <asm/semaphore.h> 29 #include <asm/semaphore.h>
30 #include <linux/proc_fs.h> 30 #include <linux/proc_fs.h>
31 31
32 #include <linux/netfilter_ipv6/ip6_tables.h> 32 #include <linux/netfilter_ipv6/ip6_tables.h>
33 33
34 MODULE_LICENSE("GPL"); 34 MODULE_LICENSE("GPL");
35 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 35 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
36 MODULE_DESCRIPTION("IPv6 packet filter"); 36 MODULE_DESCRIPTION("IPv6 packet filter");
37 37
38 #define IPV6_HDR_LEN (sizeof(struct ipv6hdr)) 38 #define IPV6_HDR_LEN (sizeof(struct ipv6hdr))
39 #define IPV6_OPTHDR_LEN (sizeof(struct ipv6_opt_hdr)) 39 #define IPV6_OPTHDR_LEN (sizeof(struct ipv6_opt_hdr))
40 40
41 /*#define DEBUG_IP_FIREWALL*/ 41 /*#define DEBUG_IP_FIREWALL*/
42 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */ 42 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
43 /*#define DEBUG_IP_FIREWALL_USER*/ 43 /*#define DEBUG_IP_FIREWALL_USER*/
44 44
45 #ifdef DEBUG_IP_FIREWALL 45 #ifdef DEBUG_IP_FIREWALL
46 #define dprintf(format, args...) printk(format , ## args) 46 #define dprintf(format, args...) printk(format , ## args)
47 #else 47 #else
48 #define dprintf(format, args...) 48 #define dprintf(format, args...)
49 #endif 49 #endif
50 50
51 #ifdef DEBUG_IP_FIREWALL_USER 51 #ifdef DEBUG_IP_FIREWALL_USER
52 #define duprintf(format, args...) printk(format , ## args) 52 #define duprintf(format, args...) printk(format , ## args)
53 #else 53 #else
54 #define duprintf(format, args...) 54 #define duprintf(format, args...)
55 #endif 55 #endif
56 56
57 #ifdef CONFIG_NETFILTER_DEBUG 57 #ifdef CONFIG_NETFILTER_DEBUG
58 #define IP_NF_ASSERT(x) \ 58 #define IP_NF_ASSERT(x) \
59 do { \ 59 do { \
60 if (!(x)) \ 60 if (!(x)) \
61 printk("IP_NF_ASSERT: %s:%s:%u\n", \ 61 printk("IP_NF_ASSERT: %s:%s:%u\n", \
62 __FUNCTION__, __FILE__, __LINE__); \ 62 __FUNCTION__, __FILE__, __LINE__); \
63 } while(0) 63 } while(0)
64 #else 64 #else
65 #define IP_NF_ASSERT(x) 65 #define IP_NF_ASSERT(x)
66 #endif 66 #endif
67 #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) 67 #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
68 68
69 static DECLARE_MUTEX(ip6t_mutex); 69 static DECLARE_MUTEX(ip6t_mutex);
70 70
71 /* Must have mutex */ 71 /* Must have mutex */
72 #define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0) 72 #define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0)
73 #define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0) 73 #define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0)
74 #include <linux/netfilter_ipv4/listhelp.h> 74 #include <linux/netfilter_ipv4/listhelp.h>
75 75
76 #if 0 76 #if 0
77 /* All the better to debug you with... */ 77 /* All the better to debug you with... */
78 #define static 78 #define static
79 #define inline 79 #define inline
80 #endif 80 #endif
81 81
82 /* Locking is simple: we assume at worst case there will be one packet 82 /* Locking is simple: we assume at worst case there will be one packet
83 in user context and one from bottom halves (or soft irq if Alexey's 83 in user context and one from bottom halves (or soft irq if Alexey's
84 softnet patch was applied). 84 softnet patch was applied).
85 85
86 We keep a set of rules for each CPU, so we can avoid write-locking 86 We keep a set of rules for each CPU, so we can avoid write-locking
87 them; doing a readlock_bh() stops packets coming through if we're 87 them; doing a readlock_bh() stops packets coming through if we're
88 in user context. 88 in user context.
89 89
90 To be cache friendly on SMP, we arrange them like so: 90 To be cache friendly on SMP, we arrange them like so:
91 [ n-entries ] 91 [ n-entries ]
92 ... cache-align padding ... 92 ... cache-align padding ...
93 [ n-entries ] 93 [ n-entries ]
94 94
95 Hence the start of any table is given by get_table() below. */ 95 Hence the start of any table is given by get_table() below. */
96 96
97 /* The table itself */ 97 /* The table itself */
98 struct ip6t_table_info 98 struct ip6t_table_info
99 { 99 {
100 /* Size per table */ 100 /* Size per table */
101 unsigned int size; 101 unsigned int size;
102 /* Number of entries: FIXME. --RR */ 102 /* Number of entries: FIXME. --RR */
103 unsigned int number; 103 unsigned int number;
104 /* Initial number of entries. Needed for module usage count */ 104 /* Initial number of entries. Needed for module usage count */
105 unsigned int initial_entries; 105 unsigned int initial_entries;
106 106
107 /* Entry points and underflows */ 107 /* Entry points and underflows */
108 unsigned int hook_entry[NF_IP6_NUMHOOKS]; 108 unsigned int hook_entry[NF_IP6_NUMHOOKS];
109 unsigned int underflow[NF_IP6_NUMHOOKS]; 109 unsigned int underflow[NF_IP6_NUMHOOKS];
110 110
111 /* ip6t_entry tables: one per CPU */ 111 /* ip6t_entry tables: one per CPU */
112 char entries[0] ____cacheline_aligned; 112 char entries[0] ____cacheline_aligned;
113 }; 113 };
114 114
115 static LIST_HEAD(ip6t_target); 115 static LIST_HEAD(ip6t_target);
116 static LIST_HEAD(ip6t_match); 116 static LIST_HEAD(ip6t_match);
117 static LIST_HEAD(ip6t_tables); 117 static LIST_HEAD(ip6t_tables);
118 #define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0) 118 #define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0)
119 119
120 #ifdef CONFIG_SMP 120 #ifdef CONFIG_SMP
121 #define TABLE_OFFSET(t,p) (SMP_ALIGN((t)->size)*(p)) 121 #define TABLE_OFFSET(t,p) (SMP_ALIGN((t)->size)*(p))
122 #else 122 #else
123 #define TABLE_OFFSET(t,p) 0 123 #define TABLE_OFFSET(t,p) 0
124 #endif 124 #endif
125 125
126 #if 0 126 #if 0
127 #define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0) 127 #define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0)
128 #define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; }) 128 #define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; })
129 #define up(x) do { printk("UP:%u:" #x "\n", __LINE__); up(x); } while(0) 129 #define up(x) do { printk("UP:%u:" #x "\n", __LINE__); up(x); } while(0)
130 #endif 130 #endif
131 131
132 static int ip6_masked_addrcmp(struct in6_addr addr1, struct in6_addr mask, 132 static int ip6_masked_addrcmp(struct in6_addr addr1, struct in6_addr mask,
133 struct in6_addr addr2) 133 struct in6_addr addr2)
134 { 134 {
135 int i; 135 int i;
136 for( i = 0; i < 16; i++){ 136 for( i = 0; i < 16; i++){
137 if((addr1.s6_addr[i] & mask.s6_addr[i]) != 137 if((addr1.s6_addr[i] & mask.s6_addr[i]) !=
138 (addr2.s6_addr[i] & mask.s6_addr[i])) 138 (addr2.s6_addr[i] & mask.s6_addr[i]))
139 return 1; 139 return 1;
140 } 140 }
141 return 0; 141 return 0;
142 } 142 }
143 143
144 /* Check for an extension */ 144 /* Check for an extension */
145 int 145 int
146 ip6t_ext_hdr(u8 nexthdr) 146 ip6t_ext_hdr(u8 nexthdr)
147 { 147 {
148 return ( (nexthdr == IPPROTO_HOPOPTS) || 148 return ( (nexthdr == IPPROTO_HOPOPTS) ||
149 (nexthdr == IPPROTO_ROUTING) || 149 (nexthdr == IPPROTO_ROUTING) ||
150 (nexthdr == IPPROTO_FRAGMENT) || 150 (nexthdr == IPPROTO_FRAGMENT) ||
151 (nexthdr == IPPROTO_ESP) || 151 (nexthdr == IPPROTO_ESP) ||
152 (nexthdr == IPPROTO_AH) || 152 (nexthdr == IPPROTO_AH) ||
153 (nexthdr == IPPROTO_NONE) || 153 (nexthdr == IPPROTO_NONE) ||
154 (nexthdr == IPPROTO_DSTOPTS) ); 154 (nexthdr == IPPROTO_DSTOPTS) );
155 } 155 }
156 156
157 /* Returns whether matches rule or not. */ 157 /* Returns whether matches rule or not. */
158 static inline int 158 static inline int
159 ip6_packet_match(const struct sk_buff *skb, 159 ip6_packet_match(const struct sk_buff *skb,
160 const char *indev, 160 const char *indev,
161 const char *outdev, 161 const char *outdev,
162 const struct ip6t_ip6 *ip6info, 162 const struct ip6t_ip6 *ip6info,
163 unsigned int *protoff, 163 unsigned int *protoff,
164 int *fragoff) 164 int *fragoff)
165 { 165 {
166 size_t i; 166 size_t i;
167 unsigned long ret; 167 unsigned long ret;
168 const struct ipv6hdr *ipv6 = skb->nh.ipv6h; 168 const struct ipv6hdr *ipv6 = skb->nh.ipv6h;
169 169
170 #define FWINV(bool,invflg) ((bool) ^ !!(ip6info->invflags & invflg)) 170 #define FWINV(bool,invflg) ((bool) ^ !!(ip6info->invflags & invflg))
171 171
172 if (FWINV(ip6_masked_addrcmp(ipv6->saddr,ip6info->smsk,ip6info->src), 172 if (FWINV(ip6_masked_addrcmp(ipv6->saddr,ip6info->smsk,ip6info->src),
173 IP6T_INV_SRCIP) 173 IP6T_INV_SRCIP)
174 || FWINV(ip6_masked_addrcmp(ipv6->daddr,ip6info->dmsk,ip6info->dst), 174 || FWINV(ip6_masked_addrcmp(ipv6->daddr,ip6info->dmsk,ip6info->dst),
175 IP6T_INV_DSTIP)) { 175 IP6T_INV_DSTIP)) {
176 dprintf("Source or dest mismatch.\n"); 176 dprintf("Source or dest mismatch.\n");
177 /* 177 /*
178 dprintf("SRC: %u. Mask: %u. Target: %u.%s\n", ip->saddr, 178 dprintf("SRC: %u. Mask: %u. Target: %u.%s\n", ip->saddr,
179 ipinfo->smsk.s_addr, ipinfo->src.s_addr, 179 ipinfo->smsk.s_addr, ipinfo->src.s_addr,
180 ipinfo->invflags & IP6T_INV_SRCIP ? " (INV)" : ""); 180 ipinfo->invflags & IP6T_INV_SRCIP ? " (INV)" : "");
181 dprintf("DST: %u. Mask: %u. Target: %u.%s\n", ip->daddr, 181 dprintf("DST: %u. Mask: %u. Target: %u.%s\n", ip->daddr,
182 ipinfo->dmsk.s_addr, ipinfo->dst.s_addr, 182 ipinfo->dmsk.s_addr, ipinfo->dst.s_addr,
183 ipinfo->invflags & IP6T_INV_DSTIP ? " (INV)" : "");*/ 183 ipinfo->invflags & IP6T_INV_DSTIP ? " (INV)" : "");*/
184 return 0; 184 return 0;
185 } 185 }
186 186
187 /* Look for ifname matches; this should unroll nicely. */ 187 /* Look for ifname matches; this should unroll nicely. */
188 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) { 188 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
189 ret |= (((const unsigned long *)indev)[i] 189 ret |= (((const unsigned long *)indev)[i]
190 ^ ((const unsigned long *)ip6info->iniface)[i]) 190 ^ ((const unsigned long *)ip6info->iniface)[i])
191 & ((const unsigned long *)ip6info->iniface_mask)[i]; 191 & ((const unsigned long *)ip6info->iniface_mask)[i];
192 } 192 }
193 193
194 if (FWINV(ret != 0, IP6T_INV_VIA_IN)) { 194 if (FWINV(ret != 0, IP6T_INV_VIA_IN)) {
195 dprintf("VIA in mismatch (%s vs %s).%s\n", 195 dprintf("VIA in mismatch (%s vs %s).%s\n",
196 indev, ip6info->iniface, 196 indev, ip6info->iniface,
197 ip6info->invflags&IP6T_INV_VIA_IN ?" (INV)":""); 197 ip6info->invflags&IP6T_INV_VIA_IN ?" (INV)":"");
198 return 0; 198 return 0;
199 } 199 }
200 200
201 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) { 201 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
202 ret |= (((const unsigned long *)outdev)[i] 202 ret |= (((const unsigned long *)outdev)[i]
203 ^ ((const unsigned long *)ip6info->outiface)[i]) 203 ^ ((const unsigned long *)ip6info->outiface)[i])
204 & ((const unsigned long *)ip6info->outiface_mask)[i]; 204 & ((const unsigned long *)ip6info->outiface_mask)[i];
205 } 205 }
206 206
207 if (FWINV(ret != 0, IP6T_INV_VIA_OUT)) { 207 if (FWINV(ret != 0, IP6T_INV_VIA_OUT)) {
208 dprintf("VIA out mismatch (%s vs %s).%s\n", 208 dprintf("VIA out mismatch (%s vs %s).%s\n",
209 outdev, ip6info->outiface, 209 outdev, ip6info->outiface,
210 ip6info->invflags&IP6T_INV_VIA_OUT ?" (INV)":""); 210 ip6info->invflags&IP6T_INV_VIA_OUT ?" (INV)":"");
211 return 0; 211 return 0;
212 } 212 }
213 213
214 /* ... might want to do something with class and flowlabel here ... */ 214 /* ... might want to do something with class and flowlabel here ... */
215 215
216 /* look for the desired protocol header */ 216 /* look for the desired protocol header */
217 if((ip6info->flags & IP6T_F_PROTO)) { 217 if((ip6info->flags & IP6T_F_PROTO)) {
218 u_int8_t currenthdr = ipv6->nexthdr; 218 u_int8_t currenthdr = ipv6->nexthdr;
219 struct ipv6_opt_hdr _hdr, *hp; 219 struct ipv6_opt_hdr _hdr, *hp;
220 u_int16_t ptr; /* Header offset in skb */ 220 u_int16_t ptr; /* Header offset in skb */
221 u_int16_t hdrlen; /* Header */ 221 u_int16_t hdrlen; /* Header */
222 u_int16_t _fragoff = 0, *fp = NULL; 222 u_int16_t _fragoff = 0, *fp = NULL;
223 223
224 ptr = IPV6_HDR_LEN; 224 ptr = IPV6_HDR_LEN;
225 225
226 while (ip6t_ext_hdr(currenthdr)) { 226 while (ip6t_ext_hdr(currenthdr)) {
227 /* Is there enough space for the next ext header? */ 227 /* Is there enough space for the next ext header? */
228 if (skb->len - ptr < IPV6_OPTHDR_LEN) 228 if (skb->len - ptr < IPV6_OPTHDR_LEN)
229 return 0; 229 return 0;
230 230
231 /* NONE or ESP: there isn't protocol part */ 231 /* NONE or ESP: there isn't protocol part */
232 /* If we want to count these packets in '-p all', 232 /* If we want to count these packets in '-p all',
233 * we will change the return 0 to 1*/ 233 * we will change the return 0 to 1*/
234 if ((currenthdr == IPPROTO_NONE) || 234 if ((currenthdr == IPPROTO_NONE) ||
235 (currenthdr == IPPROTO_ESP)) 235 (currenthdr == IPPROTO_ESP))
236 break; 236 break;
237 237
238 hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); 238 hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
239 BUG_ON(hp == NULL); 239 BUG_ON(hp == NULL);
240 240
241 /* Size calculation */ 241 /* Size calculation */
242 if (currenthdr == IPPROTO_FRAGMENT) { 242 if (currenthdr == IPPROTO_FRAGMENT) {
243 fp = skb_header_pointer(skb, 243 fp = skb_header_pointer(skb,
244 ptr+offsetof(struct frag_hdr, 244 ptr+offsetof(struct frag_hdr,
245 frag_off), 245 frag_off),
246 sizeof(_fragoff), 246 sizeof(_fragoff),
247 &_fragoff); 247 &_fragoff);
248 if (fp == NULL) 248 if (fp == NULL)
249 return 0; 249 return 0;
250 250
251 _fragoff = ntohs(*fp) & ~0x7; 251 _fragoff = ntohs(*fp) & ~0x7;
252 hdrlen = 8; 252 hdrlen = 8;
253 } else if (currenthdr == IPPROTO_AH) 253 } else if (currenthdr == IPPROTO_AH)
254 hdrlen = (hp->hdrlen+2)<<2; 254 hdrlen = (hp->hdrlen+2)<<2;
255 else 255 else
256 hdrlen = ipv6_optlen(hp); 256 hdrlen = ipv6_optlen(hp);
257 257
258 currenthdr = hp->nexthdr; 258 currenthdr = hp->nexthdr;
259 ptr += hdrlen; 259 ptr += hdrlen;
260 /* ptr is too large */ 260 /* ptr is too large */
261 if ( ptr > skb->len ) 261 if ( ptr > skb->len )
262 return 0; 262 return 0;
263 if (_fragoff) { 263 if (_fragoff) {
264 if (ip6t_ext_hdr(currenthdr)) 264 if (ip6t_ext_hdr(currenthdr))
265 return 0; 265 return 0;
266 break; 266 break;
267 } 267 }
268 } 268 }
269 269
270 *protoff = ptr; 270 *protoff = ptr;
271 *fragoff = _fragoff; 271 *fragoff = _fragoff;
272 272
273 /* currenthdr contains the protocol header */ 273 /* currenthdr contains the protocol header */
274 274
275 dprintf("Packet protocol %hi ?= %s%hi.\n", 275 dprintf("Packet protocol %hi ?= %s%hi.\n",
276 currenthdr, 276 currenthdr,
277 ip6info->invflags & IP6T_INV_PROTO ? "!":"", 277 ip6info->invflags & IP6T_INV_PROTO ? "!":"",
278 ip6info->proto); 278 ip6info->proto);
279 279
280 if (ip6info->proto == currenthdr) { 280 if (ip6info->proto == currenthdr) {
281 if(ip6info->invflags & IP6T_INV_PROTO) { 281 if(ip6info->invflags & IP6T_INV_PROTO) {
282 return 0; 282 return 0;
283 } 283 }
284 return 1; 284 return 1;
285 } 285 }
286 286
287 /* We need match for the '-p all', too! */ 287 /* We need match for the '-p all', too! */
288 if ((ip6info->proto != 0) && 288 if ((ip6info->proto != 0) &&
289 !(ip6info->invflags & IP6T_INV_PROTO)) 289 !(ip6info->invflags & IP6T_INV_PROTO))
290 return 0; 290 return 0;
291 } 291 }
292 return 1; 292 return 1;
293 } 293 }
294 294
295 /* should be ip6 safe */ 295 /* should be ip6 safe */
296 static inline int 296 static inline int
297 ip6_checkentry(const struct ip6t_ip6 *ipv6) 297 ip6_checkentry(const struct ip6t_ip6 *ipv6)
298 { 298 {
299 if (ipv6->flags & ~IP6T_F_MASK) { 299 if (ipv6->flags & ~IP6T_F_MASK) {
300 duprintf("Unknown flag bits set: %08X\n", 300 duprintf("Unknown flag bits set: %08X\n",
301 ipv6->flags & ~IP6T_F_MASK); 301 ipv6->flags & ~IP6T_F_MASK);
302 return 0; 302 return 0;
303 } 303 }
304 if (ipv6->invflags & ~IP6T_INV_MASK) { 304 if (ipv6->invflags & ~IP6T_INV_MASK) {
305 duprintf("Unknown invflag bits set: %08X\n", 305 duprintf("Unknown invflag bits set: %08X\n",
306 ipv6->invflags & ~IP6T_INV_MASK); 306 ipv6->invflags & ~IP6T_INV_MASK);
307 return 0; 307 return 0;
308 } 308 }
309 return 1; 309 return 1;
310 } 310 }
311 311
312 static unsigned int 312 static unsigned int
313 ip6t_error(struct sk_buff **pskb, 313 ip6t_error(struct sk_buff **pskb,
314 const struct net_device *in, 314 const struct net_device *in,
315 const struct net_device *out, 315 const struct net_device *out,
316 unsigned int hooknum, 316 unsigned int hooknum,
317 const void *targinfo, 317 const void *targinfo,
318 void *userinfo) 318 void *userinfo)
319 { 319 {
320 if (net_ratelimit()) 320 if (net_ratelimit())
321 printk("ip6_tables: error: `%s'\n", (char *)targinfo); 321 printk("ip6_tables: error: `%s'\n", (char *)targinfo);
322 322
323 return NF_DROP; 323 return NF_DROP;
324 } 324 }
325 325
326 static inline 326 static inline
327 int do_match(struct ip6t_entry_match *m, 327 int do_match(struct ip6t_entry_match *m,
328 const struct sk_buff *skb, 328 const struct sk_buff *skb,
329 const struct net_device *in, 329 const struct net_device *in,
330 const struct net_device *out, 330 const struct net_device *out,
331 int offset, 331 int offset,
332 unsigned int protoff, 332 unsigned int protoff,
333 int *hotdrop) 333 int *hotdrop)
334 { 334 {
335 /* Stop iteration if it doesn't match */ 335 /* Stop iteration if it doesn't match */
336 if (!m->u.kernel.match->match(skb, in, out, m->data, 336 if (!m->u.kernel.match->match(skb, in, out, m->data,
337 offset, protoff, hotdrop)) 337 offset, protoff, hotdrop))
338 return 1; 338 return 1;
339 else 339 else
340 return 0; 340 return 0;
341 } 341 }
342 342
343 static inline struct ip6t_entry * 343 static inline struct ip6t_entry *
344 get_entry(void *base, unsigned int offset) 344 get_entry(void *base, unsigned int offset)
345 { 345 {
346 return (struct ip6t_entry *)(base + offset); 346 return (struct ip6t_entry *)(base + offset);
347 } 347 }
348 348
349 /* Returns one of the generic firewall policies, like NF_ACCEPT. */ 349 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
350 unsigned int 350 unsigned int
351 ip6t_do_table(struct sk_buff **pskb, 351 ip6t_do_table(struct sk_buff **pskb,
352 unsigned int hook, 352 unsigned int hook,
353 const struct net_device *in, 353 const struct net_device *in,
354 const struct net_device *out, 354 const struct net_device *out,
355 struct ip6t_table *table, 355 struct ip6t_table *table,
356 void *userdata) 356 void *userdata)
357 { 357 {
358 static const char nulldevname[IFNAMSIZ]; 358 static const char nulldevname[IFNAMSIZ];
359 int offset = 0; 359 int offset = 0;
360 unsigned int protoff = 0; 360 unsigned int protoff = 0;
361 int hotdrop = 0; 361 int hotdrop = 0;
362 /* Initializing verdict to NF_DROP keeps gcc happy. */ 362 /* Initializing verdict to NF_DROP keeps gcc happy. */
363 unsigned int verdict = NF_DROP; 363 unsigned int verdict = NF_DROP;
364 const char *indev, *outdev; 364 const char *indev, *outdev;
365 void *table_base; 365 void *table_base;
366 struct ip6t_entry *e, *back; 366 struct ip6t_entry *e, *back;
367 367
368 /* Initialization */ 368 /* Initialization */
369 indev = in ? in->name : nulldevname; 369 indev = in ? in->name : nulldevname;
370 outdev = out ? out->name : nulldevname; 370 outdev = out ? out->name : nulldevname;
371 371
372 /* We handle fragments by dealing with the first fragment as 372 /* We handle fragments by dealing with the first fragment as
373 * if it was a normal packet. All other fragments are treated 373 * if it was a normal packet. All other fragments are treated
374 * normally, except that they will NEVER match rules that ask 374 * normally, except that they will NEVER match rules that ask
375 * things we don't know, ie. tcp syn flag or ports). If the 375 * things we don't know, ie. tcp syn flag or ports). If the
376 * rule is also a fragment-specific rule, non-fragments won't 376 * rule is also a fragment-specific rule, non-fragments won't
377 * match it. */ 377 * match it. */
378 378
379 read_lock_bh(&table->lock); 379 read_lock_bh(&table->lock);
380 IP_NF_ASSERT(table->valid_hooks & (1 << hook)); 380 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
381 table_base = (void *)table->private->entries 381 table_base = (void *)table->private->entries
382 + TABLE_OFFSET(table->private, smp_processor_id()); 382 + TABLE_OFFSET(table->private, smp_processor_id());
383 e = get_entry(table_base, table->private->hook_entry[hook]); 383 e = get_entry(table_base, table->private->hook_entry[hook]);
384 384
385 #ifdef CONFIG_NETFILTER_DEBUG 385 #ifdef CONFIG_NETFILTER_DEBUG
386 /* Check noone else using our table */ 386 /* Check noone else using our table */
387 if (((struct ip6t_entry *)table_base)->comefrom != 0xdead57ac 387 if (((struct ip6t_entry *)table_base)->comefrom != 0xdead57ac
388 && ((struct ip6t_entry *)table_base)->comefrom != 0xeeeeeeec) { 388 && ((struct ip6t_entry *)table_base)->comefrom != 0xeeeeeeec) {
389 printk("ASSERT: CPU #%u, %s comefrom(%p) = %X\n", 389 printk("ASSERT: CPU #%u, %s comefrom(%p) = %X\n",
390 smp_processor_id(), 390 smp_processor_id(),
391 table->name, 391 table->name,
392 &((struct ip6t_entry *)table_base)->comefrom, 392 &((struct ip6t_entry *)table_base)->comefrom,
393 ((struct ip6t_entry *)table_base)->comefrom); 393 ((struct ip6t_entry *)table_base)->comefrom);
394 } 394 }
395 ((struct ip6t_entry *)table_base)->comefrom = 0x57acc001; 395 ((struct ip6t_entry *)table_base)->comefrom = 0x57acc001;
396 #endif 396 #endif
397 397
398 /* For return from builtin chain */ 398 /* For return from builtin chain */
399 back = get_entry(table_base, table->private->underflow[hook]); 399 back = get_entry(table_base, table->private->underflow[hook]);
400 400
401 do { 401 do {
402 IP_NF_ASSERT(e); 402 IP_NF_ASSERT(e);
403 IP_NF_ASSERT(back); 403 IP_NF_ASSERT(back);
404 if (ip6_packet_match(*pskb, indev, outdev, &e->ipv6, 404 if (ip6_packet_match(*pskb, indev, outdev, &e->ipv6,
405 &protoff, &offset)) { 405 &protoff, &offset)) {
406 struct ip6t_entry_target *t; 406 struct ip6t_entry_target *t;
407 407
408 if (IP6T_MATCH_ITERATE(e, do_match, 408 if (IP6T_MATCH_ITERATE(e, do_match,
409 *pskb, in, out, 409 *pskb, in, out,
410 offset, protoff, &hotdrop) != 0) 410 offset, protoff, &hotdrop) != 0)
411 goto no_match; 411 goto no_match;
412 412
413 ADD_COUNTER(e->counters, 413 ADD_COUNTER(e->counters,
414 ntohs((*pskb)->nh.ipv6h->payload_len) 414 ntohs((*pskb)->nh.ipv6h->payload_len)
415 + IPV6_HDR_LEN, 415 + IPV6_HDR_LEN,
416 1); 416 1);
417 417
418 t = ip6t_get_target(e); 418 t = ip6t_get_target(e);
419 IP_NF_ASSERT(t->u.kernel.target); 419 IP_NF_ASSERT(t->u.kernel.target);
420 /* Standard target? */ 420 /* Standard target? */
421 if (!t->u.kernel.target->target) { 421 if (!t->u.kernel.target->target) {
422 int v; 422 int v;
423 423
424 v = ((struct ip6t_standard_target *)t)->verdict; 424 v = ((struct ip6t_standard_target *)t)->verdict;
425 if (v < 0) { 425 if (v < 0) {
426 /* Pop from stack? */ 426 /* Pop from stack? */
427 if (v != IP6T_RETURN) { 427 if (v != IP6T_RETURN) {
428 verdict = (unsigned)(-v) - 1; 428 verdict = (unsigned)(-v) - 1;
429 break; 429 break;
430 } 430 }
431 e = back; 431 e = back;
432 back = get_entry(table_base, 432 back = get_entry(table_base,
433 back->comefrom); 433 back->comefrom);
434 continue; 434 continue;
435 } 435 }
436 if (table_base + v 436 if (table_base + v != (void *)e + e->next_offset
437 != (void *)e + e->next_offset) { 437 && !(e->ipv6.flags & IP6T_F_GOTO)) {
438 /* Save old back ptr in next entry */ 438 /* Save old back ptr in next entry */
439 struct ip6t_entry *next 439 struct ip6t_entry *next
440 = (void *)e + e->next_offset; 440 = (void *)e + e->next_offset;
441 next->comefrom 441 next->comefrom
442 = (void *)back - table_base; 442 = (void *)back - table_base;
443 /* set back pointer to next entry */ 443 /* set back pointer to next entry */
444 back = next; 444 back = next;
445 } 445 }
446 446
447 e = get_entry(table_base, v); 447 e = get_entry(table_base, v);
448 } else { 448 } else {
449 /* Targets which reenter must return 449 /* Targets which reenter must return
450 abs. verdicts */ 450 abs. verdicts */
451 #ifdef CONFIG_NETFILTER_DEBUG 451 #ifdef CONFIG_NETFILTER_DEBUG
452 ((struct ip6t_entry *)table_base)->comefrom 452 ((struct ip6t_entry *)table_base)->comefrom
453 = 0xeeeeeeec; 453 = 0xeeeeeeec;
454 #endif 454 #endif
455 verdict = t->u.kernel.target->target(pskb, 455 verdict = t->u.kernel.target->target(pskb,
456 in, out, 456 in, out,
457 hook, 457 hook,
458 t->data, 458 t->data,
459 userdata); 459 userdata);
460 460
461 #ifdef CONFIG_NETFILTER_DEBUG 461 #ifdef CONFIG_NETFILTER_DEBUG
462 if (((struct ip6t_entry *)table_base)->comefrom 462 if (((struct ip6t_entry *)table_base)->comefrom
463 != 0xeeeeeeec 463 != 0xeeeeeeec
464 && verdict == IP6T_CONTINUE) { 464 && verdict == IP6T_CONTINUE) {
465 printk("Target %s reentered!\n", 465 printk("Target %s reentered!\n",
466 t->u.kernel.target->name); 466 t->u.kernel.target->name);
467 verdict = NF_DROP; 467 verdict = NF_DROP;
468 } 468 }
469 ((struct ip6t_entry *)table_base)->comefrom 469 ((struct ip6t_entry *)table_base)->comefrom
470 = 0x57acc001; 470 = 0x57acc001;
471 #endif 471 #endif
472 if (verdict == IP6T_CONTINUE) 472 if (verdict == IP6T_CONTINUE)
473 e = (void *)e + e->next_offset; 473 e = (void *)e + e->next_offset;
474 else 474 else
475 /* Verdict */ 475 /* Verdict */
476 break; 476 break;
477 } 477 }
478 } else { 478 } else {
479 479
480 no_match: 480 no_match:
481 e = (void *)e + e->next_offset; 481 e = (void *)e + e->next_offset;
482 } 482 }
483 } while (!hotdrop); 483 } while (!hotdrop);
484 484
485 #ifdef CONFIG_NETFILTER_DEBUG 485 #ifdef CONFIG_NETFILTER_DEBUG
486 ((struct ip6t_entry *)table_base)->comefrom = 0xdead57ac; 486 ((struct ip6t_entry *)table_base)->comefrom = 0xdead57ac;
487 #endif 487 #endif
488 read_unlock_bh(&table->lock); 488 read_unlock_bh(&table->lock);
489 489
490 #ifdef DEBUG_ALLOW_ALL 490 #ifdef DEBUG_ALLOW_ALL
491 return NF_ACCEPT; 491 return NF_ACCEPT;
492 #else 492 #else
493 if (hotdrop) 493 if (hotdrop)
494 return NF_DROP; 494 return NF_DROP;
495 else return verdict; 495 else return verdict;
496 #endif 496 #endif
497 } 497 }
498 498
499 /* If it succeeds, returns element and locks mutex */ 499 /* If it succeeds, returns element and locks mutex */
500 static inline void * 500 static inline void *
501 find_inlist_lock_noload(struct list_head *head, 501 find_inlist_lock_noload(struct list_head *head,
502 const char *name, 502 const char *name,
503 int *error, 503 int *error,
504 struct semaphore *mutex) 504 struct semaphore *mutex)
505 { 505 {
506 void *ret; 506 void *ret;
507 507
508 #if 1 508 #if 1
509 duprintf("find_inlist: searching for `%s' in %s.\n", 509 duprintf("find_inlist: searching for `%s' in %s.\n",
510 name, head == &ip6t_target ? "ip6t_target" 510 name, head == &ip6t_target ? "ip6t_target"
511 : head == &ip6t_match ? "ip6t_match" 511 : head == &ip6t_match ? "ip6t_match"
512 : head == &ip6t_tables ? "ip6t_tables" : "UNKNOWN"); 512 : head == &ip6t_tables ? "ip6t_tables" : "UNKNOWN");
513 #endif 513 #endif
514 514
515 *error = down_interruptible(mutex); 515 *error = down_interruptible(mutex);
516 if (*error != 0) 516 if (*error != 0)
517 return NULL; 517 return NULL;
518 518
519 ret = list_named_find(head, name); 519 ret = list_named_find(head, name);
520 if (!ret) { 520 if (!ret) {
521 *error = -ENOENT; 521 *error = -ENOENT;
522 up(mutex); 522 up(mutex);
523 } 523 }
524 return ret; 524 return ret;
525 } 525 }
526 526
527 #ifndef CONFIG_KMOD 527 #ifndef CONFIG_KMOD
528 #define find_inlist_lock(h,n,p,e,m) find_inlist_lock_noload((h),(n),(e),(m)) 528 #define find_inlist_lock(h,n,p,e,m) find_inlist_lock_noload((h),(n),(e),(m))
529 #else 529 #else
530 static void * 530 static void *
531 find_inlist_lock(struct list_head *head, 531 find_inlist_lock(struct list_head *head,
532 const char *name, 532 const char *name,
533 const char *prefix, 533 const char *prefix,
534 int *error, 534 int *error,
535 struct semaphore *mutex) 535 struct semaphore *mutex)
536 { 536 {
537 void *ret; 537 void *ret;
538 538
539 ret = find_inlist_lock_noload(head, name, error, mutex); 539 ret = find_inlist_lock_noload(head, name, error, mutex);
540 if (!ret) { 540 if (!ret) {
541 duprintf("find_inlist: loading `%s%s'.\n", prefix, name); 541 duprintf("find_inlist: loading `%s%s'.\n", prefix, name);
542 request_module("%s%s", prefix, name); 542 request_module("%s%s", prefix, name);
543 ret = find_inlist_lock_noload(head, name, error, mutex); 543 ret = find_inlist_lock_noload(head, name, error, mutex);
544 } 544 }
545 545
546 return ret; 546 return ret;
547 } 547 }
548 #endif 548 #endif
549 549
550 static inline struct ip6t_table * 550 static inline struct ip6t_table *
551 ip6t_find_table_lock(const char *name, int *error, struct semaphore *mutex) 551 ip6t_find_table_lock(const char *name, int *error, struct semaphore *mutex)
552 { 552 {
553 return find_inlist_lock(&ip6t_tables, name, "ip6table_", error, mutex); 553 return find_inlist_lock(&ip6t_tables, name, "ip6table_", error, mutex);
554 } 554 }
555 555
556 static inline struct ip6t_match * 556 static inline struct ip6t_match *
557 find_match_lock(const char *name, int *error, struct semaphore *mutex) 557 find_match_lock(const char *name, int *error, struct semaphore *mutex)
558 { 558 {
559 return find_inlist_lock(&ip6t_match, name, "ip6t_", error, mutex); 559 return find_inlist_lock(&ip6t_match, name, "ip6t_", error, mutex);
560 } 560 }
561 561
562 static struct ip6t_target * 562 static struct ip6t_target *
563 ip6t_find_target_lock(const char *name, int *error, struct semaphore *mutex) 563 ip6t_find_target_lock(const char *name, int *error, struct semaphore *mutex)
564 { 564 {
565 return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex); 565 return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
566 } 566 }
567 567
568 /* All zeroes == unconditional rule. */ 568 /* All zeroes == unconditional rule. */
569 static inline int 569 static inline int
570 unconditional(const struct ip6t_ip6 *ipv6) 570 unconditional(const struct ip6t_ip6 *ipv6)
571 { 571 {
572 unsigned int i; 572 unsigned int i;
573 573
574 for (i = 0; i < sizeof(*ipv6); i++) 574 for (i = 0; i < sizeof(*ipv6); i++)
575 if (((char *)ipv6)[i]) 575 if (((char *)ipv6)[i])
576 break; 576 break;
577 577
578 return (i == sizeof(*ipv6)); 578 return (i == sizeof(*ipv6));
579 } 579 }
580 580
581 /* Figures out from what hook each rule can be called: returns 0 if 581 /* Figures out from what hook each rule can be called: returns 0 if
582 there are loops. Puts hook bitmask in comefrom. */ 582 there are loops. Puts hook bitmask in comefrom. */
583 static int 583 static int
584 mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks) 584 mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
585 { 585 {
586 unsigned int hook; 586 unsigned int hook;
587 587
588 /* No recursion; use packet counter to save back ptrs (reset 588 /* No recursion; use packet counter to save back ptrs (reset
589 to 0 as we leave), and comefrom to save source hook bitmask */ 589 to 0 as we leave), and comefrom to save source hook bitmask */
590 for (hook = 0; hook < NF_IP6_NUMHOOKS; hook++) { 590 for (hook = 0; hook < NF_IP6_NUMHOOKS; hook++) {
591 unsigned int pos = newinfo->hook_entry[hook]; 591 unsigned int pos = newinfo->hook_entry[hook];
592 struct ip6t_entry *e 592 struct ip6t_entry *e
593 = (struct ip6t_entry *)(newinfo->entries + pos); 593 = (struct ip6t_entry *)(newinfo->entries + pos);
594 594
595 if (!(valid_hooks & (1 << hook))) 595 if (!(valid_hooks & (1 << hook)))
596 continue; 596 continue;
597 597
598 /* Set initial back pointer. */ 598 /* Set initial back pointer. */
599 e->counters.pcnt = pos; 599 e->counters.pcnt = pos;
600 600
601 for (;;) { 601 for (;;) {
602 struct ip6t_standard_target *t 602 struct ip6t_standard_target *t
603 = (void *)ip6t_get_target(e); 603 = (void *)ip6t_get_target(e);
604 604
605 if (e->comefrom & (1 << NF_IP6_NUMHOOKS)) { 605 if (e->comefrom & (1 << NF_IP6_NUMHOOKS)) {
606 printk("iptables: loop hook %u pos %u %08X.\n", 606 printk("iptables: loop hook %u pos %u %08X.\n",
607 hook, pos, e->comefrom); 607 hook, pos, e->comefrom);
608 return 0; 608 return 0;
609 } 609 }
610 e->comefrom 610 e->comefrom
611 |= ((1 << hook) | (1 << NF_IP6_NUMHOOKS)); 611 |= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
612 612
613 /* Unconditional return/END. */ 613 /* Unconditional return/END. */
614 if (e->target_offset == sizeof(struct ip6t_entry) 614 if (e->target_offset == sizeof(struct ip6t_entry)
615 && (strcmp(t->target.u.user.name, 615 && (strcmp(t->target.u.user.name,
616 IP6T_STANDARD_TARGET) == 0) 616 IP6T_STANDARD_TARGET) == 0)
617 && t->verdict < 0 617 && t->verdict < 0
618 && unconditional(&e->ipv6)) { 618 && unconditional(&e->ipv6)) {
619 unsigned int oldpos, size; 619 unsigned int oldpos, size;
620 620
621 /* Return: backtrack through the last 621 /* Return: backtrack through the last
622 big jump. */ 622 big jump. */
623 do { 623 do {
624 e->comefrom ^= (1<<NF_IP6_NUMHOOKS); 624 e->comefrom ^= (1<<NF_IP6_NUMHOOKS);
625 #ifdef DEBUG_IP_FIREWALL_USER 625 #ifdef DEBUG_IP_FIREWALL_USER
626 if (e->comefrom 626 if (e->comefrom
627 & (1 << NF_IP6_NUMHOOKS)) { 627 & (1 << NF_IP6_NUMHOOKS)) {
628 duprintf("Back unset " 628 duprintf("Back unset "
629 "on hook %u " 629 "on hook %u "
630 "rule %u\n", 630 "rule %u\n",
631 hook, pos); 631 hook, pos);
632 } 632 }
633 #endif 633 #endif
634 oldpos = pos; 634 oldpos = pos;
635 pos = e->counters.pcnt; 635 pos = e->counters.pcnt;
636 e->counters.pcnt = 0; 636 e->counters.pcnt = 0;
637 637
638 /* We're at the start. */ 638 /* We're at the start. */
639 if (pos == oldpos) 639 if (pos == oldpos)
640 goto next; 640 goto next;
641 641
642 e = (struct ip6t_entry *) 642 e = (struct ip6t_entry *)
643 (newinfo->entries + pos); 643 (newinfo->entries + pos);
644 } while (oldpos == pos + e->next_offset); 644 } while (oldpos == pos + e->next_offset);
645 645
646 /* Move along one */ 646 /* Move along one */
647 size = e->next_offset; 647 size = e->next_offset;
648 e = (struct ip6t_entry *) 648 e = (struct ip6t_entry *)
649 (newinfo->entries + pos + size); 649 (newinfo->entries + pos + size);
650 e->counters.pcnt = pos; 650 e->counters.pcnt = pos;
651 pos += size; 651 pos += size;
652 } else { 652 } else {
653 int newpos = t->verdict; 653 int newpos = t->verdict;
654 654
655 if (strcmp(t->target.u.user.name, 655 if (strcmp(t->target.u.user.name,
656 IP6T_STANDARD_TARGET) == 0 656 IP6T_STANDARD_TARGET) == 0
657 && newpos >= 0) { 657 && newpos >= 0) {
658 /* This a jump; chase it. */ 658 /* This a jump; chase it. */
659 duprintf("Jump rule %u -> %u\n", 659 duprintf("Jump rule %u -> %u\n",
660 pos, newpos); 660 pos, newpos);
661 } else { 661 } else {
662 /* ... this is a fallthru */ 662 /* ... this is a fallthru */
663 newpos = pos + e->next_offset; 663 newpos = pos + e->next_offset;
664 } 664 }
665 e = (struct ip6t_entry *) 665 e = (struct ip6t_entry *)
666 (newinfo->entries + newpos); 666 (newinfo->entries + newpos);
667 e->counters.pcnt = pos; 667 e->counters.pcnt = pos;
668 pos = newpos; 668 pos = newpos;
669 } 669 }
670 } 670 }
671 next: 671 next:
672 duprintf("Finished chain %u\n", hook); 672 duprintf("Finished chain %u\n", hook);
673 } 673 }
674 return 1; 674 return 1;
675 } 675 }
676 676
677 static inline int 677 static inline int
678 cleanup_match(struct ip6t_entry_match *m, unsigned int *i) 678 cleanup_match(struct ip6t_entry_match *m, unsigned int *i)
679 { 679 {
680 if (i && (*i)-- == 0) 680 if (i && (*i)-- == 0)
681 return 1; 681 return 1;
682 682
683 if (m->u.kernel.match->destroy) 683 if (m->u.kernel.match->destroy)
684 m->u.kernel.match->destroy(m->data, 684 m->u.kernel.match->destroy(m->data,
685 m->u.match_size - sizeof(*m)); 685 m->u.match_size - sizeof(*m));
686 module_put(m->u.kernel.match->me); 686 module_put(m->u.kernel.match->me);
687 return 0; 687 return 0;
688 } 688 }
689 689
690 static inline int 690 static inline int
691 standard_check(const struct ip6t_entry_target *t, 691 standard_check(const struct ip6t_entry_target *t,
692 unsigned int max_offset) 692 unsigned int max_offset)
693 { 693 {
694 struct ip6t_standard_target *targ = (void *)t; 694 struct ip6t_standard_target *targ = (void *)t;
695 695
696 /* Check standard info. */ 696 /* Check standard info. */
697 if (t->u.target_size 697 if (t->u.target_size
698 != IP6T_ALIGN(sizeof(struct ip6t_standard_target))) { 698 != IP6T_ALIGN(sizeof(struct ip6t_standard_target))) {
699 duprintf("standard_check: target size %u != %u\n", 699 duprintf("standard_check: target size %u != %u\n",
700 t->u.target_size, 700 t->u.target_size,
701 IP6T_ALIGN(sizeof(struct ip6t_standard_target))); 701 IP6T_ALIGN(sizeof(struct ip6t_standard_target)));
702 return 0; 702 return 0;
703 } 703 }
704 704
705 if (targ->verdict >= 0 705 if (targ->verdict >= 0
706 && targ->verdict > max_offset - sizeof(struct ip6t_entry)) { 706 && targ->verdict > max_offset - sizeof(struct ip6t_entry)) {
707 duprintf("ip6t_standard_check: bad verdict (%i)\n", 707 duprintf("ip6t_standard_check: bad verdict (%i)\n",
708 targ->verdict); 708 targ->verdict);
709 return 0; 709 return 0;
710 } 710 }
711 711
712 if (targ->verdict < -NF_MAX_VERDICT - 1) { 712 if (targ->verdict < -NF_MAX_VERDICT - 1) {
713 duprintf("ip6t_standard_check: bad negative verdict (%i)\n", 713 duprintf("ip6t_standard_check: bad negative verdict (%i)\n",
714 targ->verdict); 714 targ->verdict);
715 return 0; 715 return 0;
716 } 716 }
717 return 1; 717 return 1;
718 } 718 }
719 719
720 static inline int 720 static inline int
721 check_match(struct ip6t_entry_match *m, 721 check_match(struct ip6t_entry_match *m,
722 const char *name, 722 const char *name,
723 const struct ip6t_ip6 *ipv6, 723 const struct ip6t_ip6 *ipv6,
724 unsigned int hookmask, 724 unsigned int hookmask,
725 unsigned int *i) 725 unsigned int *i)
726 { 726 {
727 int ret; 727 int ret;
728 struct ip6t_match *match; 728 struct ip6t_match *match;
729 729
730 match = find_match_lock(m->u.user.name, &ret, &ip6t_mutex); 730 match = find_match_lock(m->u.user.name, &ret, &ip6t_mutex);
731 if (!match) { 731 if (!match) {
732 // duprintf("check_match: `%s' not found\n", m->u.name); 732 // duprintf("check_match: `%s' not found\n", m->u.name);
733 return ret; 733 return ret;
734 } 734 }
735 if (!try_module_get(match->me)) { 735 if (!try_module_get(match->me)) {
736 up(&ip6t_mutex); 736 up(&ip6t_mutex);
737 return -ENOENT; 737 return -ENOENT;
738 } 738 }
739 m->u.kernel.match = match; 739 m->u.kernel.match = match;
740 up(&ip6t_mutex); 740 up(&ip6t_mutex);
741 741
742 if (m->u.kernel.match->checkentry 742 if (m->u.kernel.match->checkentry
743 && !m->u.kernel.match->checkentry(name, ipv6, m->data, 743 && !m->u.kernel.match->checkentry(name, ipv6, m->data,
744 m->u.match_size - sizeof(*m), 744 m->u.match_size - sizeof(*m),
745 hookmask)) { 745 hookmask)) {
746 module_put(m->u.kernel.match->me); 746 module_put(m->u.kernel.match->me);
747 duprintf("ip_tables: check failed for `%s'.\n", 747 duprintf("ip_tables: check failed for `%s'.\n",
748 m->u.kernel.match->name); 748 m->u.kernel.match->name);
749 return -EINVAL; 749 return -EINVAL;
750 } 750 }
751 751
752 (*i)++; 752 (*i)++;
753 return 0; 753 return 0;
754 } 754 }
755 755
756 static struct ip6t_target ip6t_standard_target; 756 static struct ip6t_target ip6t_standard_target;
757 757
758 static inline int 758 static inline int
759 check_entry(struct ip6t_entry *e, const char *name, unsigned int size, 759 check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
760 unsigned int *i) 760 unsigned int *i)
761 { 761 {
762 struct ip6t_entry_target *t; 762 struct ip6t_entry_target *t;
763 struct ip6t_target *target; 763 struct ip6t_target *target;
764 int ret; 764 int ret;
765 unsigned int j; 765 unsigned int j;
766 766
767 if (!ip6_checkentry(&e->ipv6)) { 767 if (!ip6_checkentry(&e->ipv6)) {
768 duprintf("ip_tables: ip check failed %p %s.\n", e, name); 768 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
769 return -EINVAL; 769 return -EINVAL;
770 } 770 }
771 771
772 j = 0; 772 j = 0;
773 ret = IP6T_MATCH_ITERATE(e, check_match, name, &e->ipv6, e->comefrom, &j); 773 ret = IP6T_MATCH_ITERATE(e, check_match, name, &e->ipv6, e->comefrom, &j);
774 if (ret != 0) 774 if (ret != 0)
775 goto cleanup_matches; 775 goto cleanup_matches;
776 776
777 t = ip6t_get_target(e); 777 t = ip6t_get_target(e);
778 target = ip6t_find_target_lock(t->u.user.name, &ret, &ip6t_mutex); 778 target = ip6t_find_target_lock(t->u.user.name, &ret, &ip6t_mutex);
779 if (!target) { 779 if (!target) {
780 duprintf("check_entry: `%s' not found\n", t->u.user.name); 780 duprintf("check_entry: `%s' not found\n", t->u.user.name);
781 goto cleanup_matches; 781 goto cleanup_matches;
782 } 782 }
783 if (!try_module_get(target->me)) { 783 if (!try_module_get(target->me)) {
784 up(&ip6t_mutex); 784 up(&ip6t_mutex);
785 ret = -ENOENT; 785 ret = -ENOENT;
786 goto cleanup_matches; 786 goto cleanup_matches;
787 } 787 }
788 t->u.kernel.target = target; 788 t->u.kernel.target = target;
789 up(&ip6t_mutex); 789 up(&ip6t_mutex);
790 if (!t->u.kernel.target) { 790 if (!t->u.kernel.target) {
791 ret = -EBUSY; 791 ret = -EBUSY;
792 goto cleanup_matches; 792 goto cleanup_matches;
793 } 793 }
794 if (t->u.kernel.target == &ip6t_standard_target) { 794 if (t->u.kernel.target == &ip6t_standard_target) {
795 if (!standard_check(t, size)) { 795 if (!standard_check(t, size)) {
796 ret = -EINVAL; 796 ret = -EINVAL;
797 goto cleanup_matches; 797 goto cleanup_matches;
798 } 798 }
799 } else if (t->u.kernel.target->checkentry 799 } else if (t->u.kernel.target->checkentry
800 && !t->u.kernel.target->checkentry(name, e, t->data, 800 && !t->u.kernel.target->checkentry(name, e, t->data,
801 t->u.target_size 801 t->u.target_size
802 - sizeof(*t), 802 - sizeof(*t),
803 e->comefrom)) { 803 e->comefrom)) {
804 module_put(t->u.kernel.target->me); 804 module_put(t->u.kernel.target->me);
805 duprintf("ip_tables: check failed for `%s'.\n", 805 duprintf("ip_tables: check failed for `%s'.\n",
806 t->u.kernel.target->name); 806 t->u.kernel.target->name);
807 ret = -EINVAL; 807 ret = -EINVAL;
808 goto cleanup_matches; 808 goto cleanup_matches;
809 } 809 }
810 810
811 (*i)++; 811 (*i)++;
812 return 0; 812 return 0;
813 813
814 cleanup_matches: 814 cleanup_matches:
815 IP6T_MATCH_ITERATE(e, cleanup_match, &j); 815 IP6T_MATCH_ITERATE(e, cleanup_match, &j);
816 return ret; 816 return ret;
817 } 817 }
818 818
819 static inline int 819 static inline int
820 check_entry_size_and_hooks(struct ip6t_entry *e, 820 check_entry_size_and_hooks(struct ip6t_entry *e,
821 struct ip6t_table_info *newinfo, 821 struct ip6t_table_info *newinfo,
822 unsigned char *base, 822 unsigned char *base,
823 unsigned char *limit, 823 unsigned char *limit,
824 const unsigned int *hook_entries, 824 const unsigned int *hook_entries,
825 const unsigned int *underflows, 825 const unsigned int *underflows,
826 unsigned int *i) 826 unsigned int *i)
827 { 827 {
828 unsigned int h; 828 unsigned int h;
829 829
830 if ((unsigned long)e % __alignof__(struct ip6t_entry) != 0 830 if ((unsigned long)e % __alignof__(struct ip6t_entry) != 0
831 || (unsigned char *)e + sizeof(struct ip6t_entry) >= limit) { 831 || (unsigned char *)e + sizeof(struct ip6t_entry) >= limit) {
832 duprintf("Bad offset %p\n", e); 832 duprintf("Bad offset %p\n", e);
833 return -EINVAL; 833 return -EINVAL;
834 } 834 }
835 835
836 if (e->next_offset 836 if (e->next_offset
837 < sizeof(struct ip6t_entry) + sizeof(struct ip6t_entry_target)) { 837 < sizeof(struct ip6t_entry) + sizeof(struct ip6t_entry_target)) {
838 duprintf("checking: element %p size %u\n", 838 duprintf("checking: element %p size %u\n",
839 e, e->next_offset); 839 e, e->next_offset);
840 return -EINVAL; 840 return -EINVAL;
841 } 841 }
842 842
843 /* Check hooks & underflows */ 843 /* Check hooks & underflows */
844 for (h = 0; h < NF_IP6_NUMHOOKS; h++) { 844 for (h = 0; h < NF_IP6_NUMHOOKS; h++) {
845 if ((unsigned char *)e - base == hook_entries[h]) 845 if ((unsigned char *)e - base == hook_entries[h])
846 newinfo->hook_entry[h] = hook_entries[h]; 846 newinfo->hook_entry[h] = hook_entries[h];
847 if ((unsigned char *)e - base == underflows[h]) 847 if ((unsigned char *)e - base == underflows[h])
848 newinfo->underflow[h] = underflows[h]; 848 newinfo->underflow[h] = underflows[h];
849 } 849 }
850 850
851 /* FIXME: underflows must be unconditional, standard verdicts 851 /* FIXME: underflows must be unconditional, standard verdicts
852 < 0 (not IP6T_RETURN). --RR */ 852 < 0 (not IP6T_RETURN). --RR */
853 853
854 /* Clear counters and comefrom */ 854 /* Clear counters and comefrom */
855 e->counters = ((struct ip6t_counters) { 0, 0 }); 855 e->counters = ((struct ip6t_counters) { 0, 0 });
856 e->comefrom = 0; 856 e->comefrom = 0;
857 857
858 (*i)++; 858 (*i)++;
859 return 0; 859 return 0;
860 } 860 }
861 861
862 static inline int 862 static inline int
863 cleanup_entry(struct ip6t_entry *e, unsigned int *i) 863 cleanup_entry(struct ip6t_entry *e, unsigned int *i)
864 { 864 {
865 struct ip6t_entry_target *t; 865 struct ip6t_entry_target *t;
866 866
867 if (i && (*i)-- == 0) 867 if (i && (*i)-- == 0)
868 return 1; 868 return 1;
869 869
870 /* Cleanup all matches */ 870 /* Cleanup all matches */
871 IP6T_MATCH_ITERATE(e, cleanup_match, NULL); 871 IP6T_MATCH_ITERATE(e, cleanup_match, NULL);
872 t = ip6t_get_target(e); 872 t = ip6t_get_target(e);
873 if (t->u.kernel.target->destroy) 873 if (t->u.kernel.target->destroy)
874 t->u.kernel.target->destroy(t->data, 874 t->u.kernel.target->destroy(t->data,
875 t->u.target_size - sizeof(*t)); 875 t->u.target_size - sizeof(*t));
876 module_put(t->u.kernel.target->me); 876 module_put(t->u.kernel.target->me);
877 return 0; 877 return 0;
878 } 878 }
879 879
880 /* Checks and translates the user-supplied table segment (held in 880 /* Checks and translates the user-supplied table segment (held in
881 newinfo) */ 881 newinfo) */
882 static int 882 static int
883 translate_table(const char *name, 883 translate_table(const char *name,
884 unsigned int valid_hooks, 884 unsigned int valid_hooks,
885 struct ip6t_table_info *newinfo, 885 struct ip6t_table_info *newinfo,
886 unsigned int size, 886 unsigned int size,
887 unsigned int number, 887 unsigned int number,
888 const unsigned int *hook_entries, 888 const unsigned int *hook_entries,
889 const unsigned int *underflows) 889 const unsigned int *underflows)
890 { 890 {
891 unsigned int i; 891 unsigned int i;
892 int ret; 892 int ret;
893 893
894 newinfo->size = size; 894 newinfo->size = size;
895 newinfo->number = number; 895 newinfo->number = number;
896 896
897 /* Init all hooks to impossible value. */ 897 /* Init all hooks to impossible value. */
898 for (i = 0; i < NF_IP6_NUMHOOKS; i++) { 898 for (i = 0; i < NF_IP6_NUMHOOKS; i++) {
899 newinfo->hook_entry[i] = 0xFFFFFFFF; 899 newinfo->hook_entry[i] = 0xFFFFFFFF;
900 newinfo->underflow[i] = 0xFFFFFFFF; 900 newinfo->underflow[i] = 0xFFFFFFFF;
901 } 901 }
902 902
903 duprintf("translate_table: size %u\n", newinfo->size); 903 duprintf("translate_table: size %u\n", newinfo->size);
904 i = 0; 904 i = 0;
905 /* Walk through entries, checking offsets. */ 905 /* Walk through entries, checking offsets. */
906 ret = IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size, 906 ret = IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size,
907 check_entry_size_and_hooks, 907 check_entry_size_and_hooks,
908 newinfo, 908 newinfo,
909 newinfo->entries, 909 newinfo->entries,
910 newinfo->entries + size, 910 newinfo->entries + size,
911 hook_entries, underflows, &i); 911 hook_entries, underflows, &i);
912 if (ret != 0) 912 if (ret != 0)
913 return ret; 913 return ret;
914 914
915 if (i != number) { 915 if (i != number) {
916 duprintf("translate_table: %u not %u entries\n", 916 duprintf("translate_table: %u not %u entries\n",
917 i, number); 917 i, number);
918 return -EINVAL; 918 return -EINVAL;
919 } 919 }
920 920
921 /* Check hooks all assigned */ 921 /* Check hooks all assigned */
922 for (i = 0; i < NF_IP6_NUMHOOKS; i++) { 922 for (i = 0; i < NF_IP6_NUMHOOKS; i++) {
923 /* Only hooks which are valid */ 923 /* Only hooks which are valid */
924 if (!(valid_hooks & (1 << i))) 924 if (!(valid_hooks & (1 << i)))
925 continue; 925 continue;
926 if (newinfo->hook_entry[i] == 0xFFFFFFFF) { 926 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
927 duprintf("Invalid hook entry %u %u\n", 927 duprintf("Invalid hook entry %u %u\n",
928 i, hook_entries[i]); 928 i, hook_entries[i]);
929 return -EINVAL; 929 return -EINVAL;
930 } 930 }
931 if (newinfo->underflow[i] == 0xFFFFFFFF) { 931 if (newinfo->underflow[i] == 0xFFFFFFFF) {
932 duprintf("Invalid underflow %u %u\n", 932 duprintf("Invalid underflow %u %u\n",
933 i, underflows[i]); 933 i, underflows[i]);
934 return -EINVAL; 934 return -EINVAL;
935 } 935 }
936 } 936 }
937 937
938 if (!mark_source_chains(newinfo, valid_hooks)) 938 if (!mark_source_chains(newinfo, valid_hooks))
939 return -ELOOP; 939 return -ELOOP;
940 940
941 /* Finally, each sanity check must pass */ 941 /* Finally, each sanity check must pass */
942 i = 0; 942 i = 0;
943 ret = IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size, 943 ret = IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size,
944 check_entry, name, size, &i); 944 check_entry, name, size, &i);
945 945
946 if (ret != 0) { 946 if (ret != 0) {
947 IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size, 947 IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size,
948 cleanup_entry, &i); 948 cleanup_entry, &i);
949 return ret; 949 return ret;
950 } 950 }
951 951
952 /* And one copy for every other CPU */ 952 /* And one copy for every other CPU */
953 for (i = 1; i < num_possible_cpus(); i++) { 953 for (i = 1; i < num_possible_cpus(); i++) {
954 memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i, 954 memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i,
955 newinfo->entries, 955 newinfo->entries,
956 SMP_ALIGN(newinfo->size)); 956 SMP_ALIGN(newinfo->size));
957 } 957 }
958 958
959 return ret; 959 return ret;
960 } 960 }
961 961
962 static struct ip6t_table_info * 962 static struct ip6t_table_info *
963 replace_table(struct ip6t_table *table, 963 replace_table(struct ip6t_table *table,
964 unsigned int num_counters, 964 unsigned int num_counters,
965 struct ip6t_table_info *newinfo, 965 struct ip6t_table_info *newinfo,
966 int *error) 966 int *error)
967 { 967 {
968 struct ip6t_table_info *oldinfo; 968 struct ip6t_table_info *oldinfo;
969 969
970 #ifdef CONFIG_NETFILTER_DEBUG 970 #ifdef CONFIG_NETFILTER_DEBUG
971 { 971 {
972 struct ip6t_entry *table_base; 972 struct ip6t_entry *table_base;
973 unsigned int i; 973 unsigned int i;
974 974
975 for (i = 0; i < num_possible_cpus(); i++) { 975 for (i = 0; i < num_possible_cpus(); i++) {
976 table_base = 976 table_base =
977 (void *)newinfo->entries 977 (void *)newinfo->entries
978 + TABLE_OFFSET(newinfo, i); 978 + TABLE_OFFSET(newinfo, i);
979 979
980 table_base->comefrom = 0xdead57ac; 980 table_base->comefrom = 0xdead57ac;
981 } 981 }
982 } 982 }
983 #endif 983 #endif
984 984
985 /* Do the substitution. */ 985 /* Do the substitution. */
986 write_lock_bh(&table->lock); 986 write_lock_bh(&table->lock);
987 /* Check inside lock: is the old number correct? */ 987 /* Check inside lock: is the old number correct? */
988 if (num_counters != table->private->number) { 988 if (num_counters != table->private->number) {
989 duprintf("num_counters != table->private->number (%u/%u)\n", 989 duprintf("num_counters != table->private->number (%u/%u)\n",
990 num_counters, table->private->number); 990 num_counters, table->private->number);
991 write_unlock_bh(&table->lock); 991 write_unlock_bh(&table->lock);
992 *error = -EAGAIN; 992 *error = -EAGAIN;
993 return NULL; 993 return NULL;
994 } 994 }
995 oldinfo = table->private; 995 oldinfo = table->private;
996 table->private = newinfo; 996 table->private = newinfo;
997 newinfo->initial_entries = oldinfo->initial_entries; 997 newinfo->initial_entries = oldinfo->initial_entries;
998 write_unlock_bh(&table->lock); 998 write_unlock_bh(&table->lock);
999 999
1000 return oldinfo; 1000 return oldinfo;
1001 } 1001 }
1002 1002
1003 /* Gets counters. */ 1003 /* Gets counters. */
1004 static inline int 1004 static inline int
1005 add_entry_to_counter(const struct ip6t_entry *e, 1005 add_entry_to_counter(const struct ip6t_entry *e,
1006 struct ip6t_counters total[], 1006 struct ip6t_counters total[],
1007 unsigned int *i) 1007 unsigned int *i)
1008 { 1008 {
1009 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); 1009 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
1010 1010
1011 (*i)++; 1011 (*i)++;
1012 return 0; 1012 return 0;
1013 } 1013 }
1014 1014
1015 static void 1015 static void
1016 get_counters(const struct ip6t_table_info *t, 1016 get_counters(const struct ip6t_table_info *t,
1017 struct ip6t_counters counters[]) 1017 struct ip6t_counters counters[])
1018 { 1018 {
1019 unsigned int cpu; 1019 unsigned int cpu;
1020 unsigned int i; 1020 unsigned int i;
1021 1021
1022 for (cpu = 0; cpu < num_possible_cpus(); cpu++) { 1022 for (cpu = 0; cpu < num_possible_cpus(); cpu++) {
1023 i = 0; 1023 i = 0;
1024 IP6T_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu), 1024 IP6T_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu),
1025 t->size, 1025 t->size,
1026 add_entry_to_counter, 1026 add_entry_to_counter,
1027 counters, 1027 counters,
1028 &i); 1028 &i);
1029 } 1029 }
1030 } 1030 }
1031 1031
1032 static int 1032 static int
1033 copy_entries_to_user(unsigned int total_size, 1033 copy_entries_to_user(unsigned int total_size,
1034 struct ip6t_table *table, 1034 struct ip6t_table *table,
1035 void __user *userptr) 1035 void __user *userptr)
1036 { 1036 {
1037 unsigned int off, num, countersize; 1037 unsigned int off, num, countersize;
1038 struct ip6t_entry *e; 1038 struct ip6t_entry *e;
1039 struct ip6t_counters *counters; 1039 struct ip6t_counters *counters;
1040 int ret = 0; 1040 int ret = 0;
1041 1041
1042 /* We need atomic snapshot of counters: rest doesn't change 1042 /* We need atomic snapshot of counters: rest doesn't change
1043 (other than comefrom, which userspace doesn't care 1043 (other than comefrom, which userspace doesn't care
1044 about). */ 1044 about). */
1045 countersize = sizeof(struct ip6t_counters) * table->private->number; 1045 countersize = sizeof(struct ip6t_counters) * table->private->number;
1046 counters = vmalloc(countersize); 1046 counters = vmalloc(countersize);
1047 1047
1048 if (counters == NULL) 1048 if (counters == NULL)
1049 return -ENOMEM; 1049 return -ENOMEM;
1050 1050
1051 /* First, sum counters... */ 1051 /* First, sum counters... */
1052 memset(counters, 0, countersize); 1052 memset(counters, 0, countersize);
1053 write_lock_bh(&table->lock); 1053 write_lock_bh(&table->lock);
1054 get_counters(table->private, counters); 1054 get_counters(table->private, counters);
1055 write_unlock_bh(&table->lock); 1055 write_unlock_bh(&table->lock);
1056 1056
1057 /* ... then copy entire thing from CPU 0... */ 1057 /* ... then copy entire thing from CPU 0... */
1058 if (copy_to_user(userptr, table->private->entries, total_size) != 0) { 1058 if (copy_to_user(userptr, table->private->entries, total_size) != 0) {
1059 ret = -EFAULT; 1059 ret = -EFAULT;
1060 goto free_counters; 1060 goto free_counters;
1061 } 1061 }
1062 1062
1063 /* FIXME: use iterator macros --RR */ 1063 /* FIXME: use iterator macros --RR */
1064 /* ... then go back and fix counters and names */ 1064 /* ... then go back and fix counters and names */
1065 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){ 1065 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
1066 unsigned int i; 1066 unsigned int i;
1067 struct ip6t_entry_match *m; 1067 struct ip6t_entry_match *m;
1068 struct ip6t_entry_target *t; 1068 struct ip6t_entry_target *t;
1069 1069
1070 e = (struct ip6t_entry *)(table->private->entries + off); 1070 e = (struct ip6t_entry *)(table->private->entries + off);
1071 if (copy_to_user(userptr + off 1071 if (copy_to_user(userptr + off
1072 + offsetof(struct ip6t_entry, counters), 1072 + offsetof(struct ip6t_entry, counters),
1073 &counters[num], 1073 &counters[num],
1074 sizeof(counters[num])) != 0) { 1074 sizeof(counters[num])) != 0) {
1075 ret = -EFAULT; 1075 ret = -EFAULT;
1076 goto free_counters; 1076 goto free_counters;
1077 } 1077 }
1078 1078
1079 for (i = sizeof(struct ip6t_entry); 1079 for (i = sizeof(struct ip6t_entry);
1080 i < e->target_offset; 1080 i < e->target_offset;
1081 i += m->u.match_size) { 1081 i += m->u.match_size) {
1082 m = (void *)e + i; 1082 m = (void *)e + i;
1083 1083
1084 if (copy_to_user(userptr + off + i 1084 if (copy_to_user(userptr + off + i
1085 + offsetof(struct ip6t_entry_match, 1085 + offsetof(struct ip6t_entry_match,
1086 u.user.name), 1086 u.user.name),
1087 m->u.kernel.match->name, 1087 m->u.kernel.match->name,
1088 strlen(m->u.kernel.match->name)+1) 1088 strlen(m->u.kernel.match->name)+1)
1089 != 0) { 1089 != 0) {
1090 ret = -EFAULT; 1090 ret = -EFAULT;
1091 goto free_counters; 1091 goto free_counters;
1092 } 1092 }
1093 } 1093 }
1094 1094
1095 t = ip6t_get_target(e); 1095 t = ip6t_get_target(e);
1096 if (copy_to_user(userptr + off + e->target_offset 1096 if (copy_to_user(userptr + off + e->target_offset
1097 + offsetof(struct ip6t_entry_target, 1097 + offsetof(struct ip6t_entry_target,
1098 u.user.name), 1098 u.user.name),
1099 t->u.kernel.target->name, 1099 t->u.kernel.target->name,
1100 strlen(t->u.kernel.target->name)+1) != 0) { 1100 strlen(t->u.kernel.target->name)+1) != 0) {
1101 ret = -EFAULT; 1101 ret = -EFAULT;
1102 goto free_counters; 1102 goto free_counters;
1103 } 1103 }
1104 } 1104 }
1105 1105
1106 free_counters: 1106 free_counters:
1107 vfree(counters); 1107 vfree(counters);
1108 return ret; 1108 return ret;
1109 } 1109 }
1110 1110
1111 static int 1111 static int
1112 get_entries(const struct ip6t_get_entries *entries, 1112 get_entries(const struct ip6t_get_entries *entries,
1113 struct ip6t_get_entries __user *uptr) 1113 struct ip6t_get_entries __user *uptr)
1114 { 1114 {
1115 int ret; 1115 int ret;
1116 struct ip6t_table *t; 1116 struct ip6t_table *t;
1117 1117
1118 t = ip6t_find_table_lock(entries->name, &ret, &ip6t_mutex); 1118 t = ip6t_find_table_lock(entries->name, &ret, &ip6t_mutex);
1119 if (t) { 1119 if (t) {
1120 duprintf("t->private->number = %u\n", 1120 duprintf("t->private->number = %u\n",
1121 t->private->number); 1121 t->private->number);
1122 if (entries->size == t->private->size) 1122 if (entries->size == t->private->size)
1123 ret = copy_entries_to_user(t->private->size, 1123 ret = copy_entries_to_user(t->private->size,
1124 t, uptr->entrytable); 1124 t, uptr->entrytable);
1125 else { 1125 else {
1126 duprintf("get_entries: I've got %u not %u!\n", 1126 duprintf("get_entries: I've got %u not %u!\n",
1127 t->private->size, 1127 t->private->size,
1128 entries->size); 1128 entries->size);
1129 ret = -EINVAL; 1129 ret = -EINVAL;
1130 } 1130 }
1131 up(&ip6t_mutex); 1131 up(&ip6t_mutex);
1132 } else 1132 } else
1133 duprintf("get_entries: Can't find %s!\n", 1133 duprintf("get_entries: Can't find %s!\n",
1134 entries->name); 1134 entries->name);
1135 1135
1136 return ret; 1136 return ret;
1137 } 1137 }
1138 1138
1139 static int 1139 static int
1140 do_replace(void __user *user, unsigned int len) 1140 do_replace(void __user *user, unsigned int len)
1141 { 1141 {
1142 int ret; 1142 int ret;
1143 struct ip6t_replace tmp; 1143 struct ip6t_replace tmp;
1144 struct ip6t_table *t; 1144 struct ip6t_table *t;
1145 struct ip6t_table_info *newinfo, *oldinfo; 1145 struct ip6t_table_info *newinfo, *oldinfo;
1146 struct ip6t_counters *counters; 1146 struct ip6t_counters *counters;
1147 1147
1148 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1148 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1149 return -EFAULT; 1149 return -EFAULT;
1150 1150
1151 /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ 1151 /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */
1152 if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages) 1152 if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages)
1153 return -ENOMEM; 1153 return -ENOMEM;
1154 1154
1155 newinfo = vmalloc(sizeof(struct ip6t_table_info) 1155 newinfo = vmalloc(sizeof(struct ip6t_table_info)
1156 + SMP_ALIGN(tmp.size) * num_possible_cpus()); 1156 + SMP_ALIGN(tmp.size) * num_possible_cpus());
1157 if (!newinfo) 1157 if (!newinfo)
1158 return -ENOMEM; 1158 return -ENOMEM;
1159 1159
1160 if (copy_from_user(newinfo->entries, user + sizeof(tmp), 1160 if (copy_from_user(newinfo->entries, user + sizeof(tmp),
1161 tmp.size) != 0) { 1161 tmp.size) != 0) {
1162 ret = -EFAULT; 1162 ret = -EFAULT;
1163 goto free_newinfo; 1163 goto free_newinfo;
1164 } 1164 }
1165 1165
1166 counters = vmalloc(tmp.num_counters * sizeof(struct ip6t_counters)); 1166 counters = vmalloc(tmp.num_counters * sizeof(struct ip6t_counters));
1167 if (!counters) { 1167 if (!counters) {
1168 ret = -ENOMEM; 1168 ret = -ENOMEM;
1169 goto free_newinfo; 1169 goto free_newinfo;
1170 } 1170 }
1171 memset(counters, 0, tmp.num_counters * sizeof(struct ip6t_counters)); 1171 memset(counters, 0, tmp.num_counters * sizeof(struct ip6t_counters));
1172 1172
1173 ret = translate_table(tmp.name, tmp.valid_hooks, 1173 ret = translate_table(tmp.name, tmp.valid_hooks,
1174 newinfo, tmp.size, tmp.num_entries, 1174 newinfo, tmp.size, tmp.num_entries,
1175 tmp.hook_entry, tmp.underflow); 1175 tmp.hook_entry, tmp.underflow);
1176 if (ret != 0) 1176 if (ret != 0)
1177 goto free_newinfo_counters; 1177 goto free_newinfo_counters;
1178 1178
1179 duprintf("ip_tables: Translated table\n"); 1179 duprintf("ip_tables: Translated table\n");
1180 1180
1181 t = ip6t_find_table_lock(tmp.name, &ret, &ip6t_mutex); 1181 t = ip6t_find_table_lock(tmp.name, &ret, &ip6t_mutex);
1182 if (!t) 1182 if (!t)
1183 goto free_newinfo_counters_untrans; 1183 goto free_newinfo_counters_untrans;
1184 1184
1185 /* You lied! */ 1185 /* You lied! */
1186 if (tmp.valid_hooks != t->valid_hooks) { 1186 if (tmp.valid_hooks != t->valid_hooks) {
1187 duprintf("Valid hook crap: %08X vs %08X\n", 1187 duprintf("Valid hook crap: %08X vs %08X\n",
1188 tmp.valid_hooks, t->valid_hooks); 1188 tmp.valid_hooks, t->valid_hooks);
1189 ret = -EINVAL; 1189 ret = -EINVAL;
1190 goto free_newinfo_counters_untrans_unlock; 1190 goto free_newinfo_counters_untrans_unlock;
1191 } 1191 }
1192 1192
1193 /* Get a reference in advance, we're not allowed fail later */ 1193 /* Get a reference in advance, we're not allowed fail later */
1194 if (!try_module_get(t->me)) { 1194 if (!try_module_get(t->me)) {
1195 ret = -EBUSY; 1195 ret = -EBUSY;
1196 goto free_newinfo_counters_untrans_unlock; 1196 goto free_newinfo_counters_untrans_unlock;
1197 } 1197 }
1198 1198
1199 oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); 1199 oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret);
1200 if (!oldinfo) 1200 if (!oldinfo)
1201 goto put_module; 1201 goto put_module;
1202 1202
1203 /* Update module usage count based on number of rules */ 1203 /* Update module usage count based on number of rules */
1204 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n", 1204 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1205 oldinfo->number, oldinfo->initial_entries, newinfo->number); 1205 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1206 if ((oldinfo->number > oldinfo->initial_entries) || 1206 if ((oldinfo->number > oldinfo->initial_entries) ||
1207 (newinfo->number <= oldinfo->initial_entries)) 1207 (newinfo->number <= oldinfo->initial_entries))
1208 module_put(t->me); 1208 module_put(t->me);
1209 if ((oldinfo->number > oldinfo->initial_entries) && 1209 if ((oldinfo->number > oldinfo->initial_entries) &&
1210 (newinfo->number <= oldinfo->initial_entries)) 1210 (newinfo->number <= oldinfo->initial_entries))
1211 module_put(t->me); 1211 module_put(t->me);
1212 1212
1213 /* Get the old counters. */ 1213 /* Get the old counters. */
1214 get_counters(oldinfo, counters); 1214 get_counters(oldinfo, counters);
1215 /* Decrease module usage counts and free resource */ 1215 /* Decrease module usage counts and free resource */
1216 IP6T_ENTRY_ITERATE(oldinfo->entries, oldinfo->size, cleanup_entry,NULL); 1216 IP6T_ENTRY_ITERATE(oldinfo->entries, oldinfo->size, cleanup_entry,NULL);
1217 vfree(oldinfo); 1217 vfree(oldinfo);
1218 /* Silent error: too late now. */ 1218 /* Silent error: too late now. */
1219 if (copy_to_user(tmp.counters, counters, 1219 if (copy_to_user(tmp.counters, counters,
1220 sizeof(struct ip6t_counters) * tmp.num_counters) != 0) 1220 sizeof(struct ip6t_counters) * tmp.num_counters) != 0)
1221 ret = -EFAULT; 1221 ret = -EFAULT;
1222 vfree(counters); 1222 vfree(counters);
1223 up(&ip6t_mutex); 1223 up(&ip6t_mutex);
1224 return ret; 1224 return ret;
1225 1225
1226 put_module: 1226 put_module:
1227 module_put(t->me); 1227 module_put(t->me);
1228 free_newinfo_counters_untrans_unlock: 1228 free_newinfo_counters_untrans_unlock:
1229 up(&ip6t_mutex); 1229 up(&ip6t_mutex);
1230 free_newinfo_counters_untrans: 1230 free_newinfo_counters_untrans:
1231 IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size, cleanup_entry,NULL); 1231 IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size, cleanup_entry,NULL);
1232 free_newinfo_counters: 1232 free_newinfo_counters:
1233 vfree(counters); 1233 vfree(counters);
1234 free_newinfo: 1234 free_newinfo:
1235 vfree(newinfo); 1235 vfree(newinfo);
1236 return ret; 1236 return ret;
1237 } 1237 }
1238 1238
1239 /* We're lazy, and add to the first CPU; overflow works its fey magic 1239 /* We're lazy, and add to the first CPU; overflow works its fey magic
1240 * and everything is OK. */ 1240 * and everything is OK. */
1241 static inline int 1241 static inline int
1242 add_counter_to_entry(struct ip6t_entry *e, 1242 add_counter_to_entry(struct ip6t_entry *e,
1243 const struct ip6t_counters addme[], 1243 const struct ip6t_counters addme[],
1244 unsigned int *i) 1244 unsigned int *i)
1245 { 1245 {
1246 #if 0 1246 #if 0
1247 duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n", 1247 duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n",
1248 *i, 1248 *i,
1249 (long unsigned int)e->counters.pcnt, 1249 (long unsigned int)e->counters.pcnt,
1250 (long unsigned int)e->counters.bcnt, 1250 (long unsigned int)e->counters.bcnt,
1251 (long unsigned int)addme[*i].pcnt, 1251 (long unsigned int)addme[*i].pcnt,
1252 (long unsigned int)addme[*i].bcnt); 1252 (long unsigned int)addme[*i].bcnt);
1253 #endif 1253 #endif
1254 1254
1255 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); 1255 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1256 1256
1257 (*i)++; 1257 (*i)++;
1258 return 0; 1258 return 0;
1259 } 1259 }
1260 1260
1261 static int 1261 static int
1262 do_add_counters(void __user *user, unsigned int len) 1262 do_add_counters(void __user *user, unsigned int len)
1263 { 1263 {
1264 unsigned int i; 1264 unsigned int i;
1265 struct ip6t_counters_info tmp, *paddc; 1265 struct ip6t_counters_info tmp, *paddc;
1266 struct ip6t_table *t; 1266 struct ip6t_table *t;
1267 int ret; 1267 int ret;
1268 1268
1269 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1269 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1270 return -EFAULT; 1270 return -EFAULT;
1271 1271
1272 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct ip6t_counters)) 1272 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct ip6t_counters))
1273 return -EINVAL; 1273 return -EINVAL;
1274 1274
1275 paddc = vmalloc(len); 1275 paddc = vmalloc(len);
1276 if (!paddc) 1276 if (!paddc)
1277 return -ENOMEM; 1277 return -ENOMEM;
1278 1278
1279 if (copy_from_user(paddc, user, len) != 0) { 1279 if (copy_from_user(paddc, user, len) != 0) {
1280 ret = -EFAULT; 1280 ret = -EFAULT;
1281 goto free; 1281 goto free;
1282 } 1282 }
1283 1283
1284 t = ip6t_find_table_lock(tmp.name, &ret, &ip6t_mutex); 1284 t = ip6t_find_table_lock(tmp.name, &ret, &ip6t_mutex);
1285 if (!t) 1285 if (!t)
1286 goto free; 1286 goto free;
1287 1287
1288 write_lock_bh(&t->lock); 1288 write_lock_bh(&t->lock);
1289 if (t->private->number != paddc->num_counters) { 1289 if (t->private->number != paddc->num_counters) {
1290 ret = -EINVAL; 1290 ret = -EINVAL;
1291 goto unlock_up_free; 1291 goto unlock_up_free;
1292 } 1292 }
1293 1293
1294 i = 0; 1294 i = 0;
1295 IP6T_ENTRY_ITERATE(t->private->entries, 1295 IP6T_ENTRY_ITERATE(t->private->entries,
1296 t->private->size, 1296 t->private->size,
1297 add_counter_to_entry, 1297 add_counter_to_entry,
1298 paddc->counters, 1298 paddc->counters,
1299 &i); 1299 &i);
1300 unlock_up_free: 1300 unlock_up_free:
1301 write_unlock_bh(&t->lock); 1301 write_unlock_bh(&t->lock);
1302 up(&ip6t_mutex); 1302 up(&ip6t_mutex);
1303 free: 1303 free:
1304 vfree(paddc); 1304 vfree(paddc);
1305 1305
1306 return ret; 1306 return ret;
1307 } 1307 }
1308 1308
1309 static int 1309 static int
1310 do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) 1310 do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1311 { 1311 {
1312 int ret; 1312 int ret;
1313 1313
1314 if (!capable(CAP_NET_ADMIN)) 1314 if (!capable(CAP_NET_ADMIN))
1315 return -EPERM; 1315 return -EPERM;
1316 1316
1317 switch (cmd) { 1317 switch (cmd) {
1318 case IP6T_SO_SET_REPLACE: 1318 case IP6T_SO_SET_REPLACE:
1319 ret = do_replace(user, len); 1319 ret = do_replace(user, len);
1320 break; 1320 break;
1321 1321
1322 case IP6T_SO_SET_ADD_COUNTERS: 1322 case IP6T_SO_SET_ADD_COUNTERS:
1323 ret = do_add_counters(user, len); 1323 ret = do_add_counters(user, len);
1324 break; 1324 break;
1325 1325
1326 default: 1326 default:
1327 duprintf("do_ip6t_set_ctl: unknown request %i\n", cmd); 1327 duprintf("do_ip6t_set_ctl: unknown request %i\n", cmd);
1328 ret = -EINVAL; 1328 ret = -EINVAL;
1329 } 1329 }
1330 1330
1331 return ret; 1331 return ret;
1332 } 1332 }
1333 1333
1334 static int 1334 static int
1335 do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) 1335 do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1336 { 1336 {
1337 int ret; 1337 int ret;
1338 1338
1339 if (!capable(CAP_NET_ADMIN)) 1339 if (!capable(CAP_NET_ADMIN))
1340 return -EPERM; 1340 return -EPERM;
1341 1341
1342 switch (cmd) { 1342 switch (cmd) {
1343 case IP6T_SO_GET_INFO: { 1343 case IP6T_SO_GET_INFO: {
1344 char name[IP6T_TABLE_MAXNAMELEN]; 1344 char name[IP6T_TABLE_MAXNAMELEN];
1345 struct ip6t_table *t; 1345 struct ip6t_table *t;
1346 1346
1347 if (*len != sizeof(struct ip6t_getinfo)) { 1347 if (*len != sizeof(struct ip6t_getinfo)) {
1348 duprintf("length %u != %u\n", *len, 1348 duprintf("length %u != %u\n", *len,
1349 sizeof(struct ip6t_getinfo)); 1349 sizeof(struct ip6t_getinfo));
1350 ret = -EINVAL; 1350 ret = -EINVAL;
1351 break; 1351 break;
1352 } 1352 }
1353 1353
1354 if (copy_from_user(name, user, sizeof(name)) != 0) { 1354 if (copy_from_user(name, user, sizeof(name)) != 0) {
1355 ret = -EFAULT; 1355 ret = -EFAULT;
1356 break; 1356 break;
1357 } 1357 }
1358 name[IP6T_TABLE_MAXNAMELEN-1] = '\0'; 1358 name[IP6T_TABLE_MAXNAMELEN-1] = '\0';
1359 t = ip6t_find_table_lock(name, &ret, &ip6t_mutex); 1359 t = ip6t_find_table_lock(name, &ret, &ip6t_mutex);
1360 if (t) { 1360 if (t) {
1361 struct ip6t_getinfo info; 1361 struct ip6t_getinfo info;
1362 1362
1363 info.valid_hooks = t->valid_hooks; 1363 info.valid_hooks = t->valid_hooks;
1364 memcpy(info.hook_entry, t->private->hook_entry, 1364 memcpy(info.hook_entry, t->private->hook_entry,
1365 sizeof(info.hook_entry)); 1365 sizeof(info.hook_entry));
1366 memcpy(info.underflow, t->private->underflow, 1366 memcpy(info.underflow, t->private->underflow,
1367 sizeof(info.underflow)); 1367 sizeof(info.underflow));
1368 info.num_entries = t->private->number; 1368 info.num_entries = t->private->number;
1369 info.size = t->private->size; 1369 info.size = t->private->size;
1370 memcpy(info.name, name, sizeof(info.name)); 1370 memcpy(info.name, name, sizeof(info.name));
1371 1371
1372 if (copy_to_user(user, &info, *len) != 0) 1372 if (copy_to_user(user, &info, *len) != 0)
1373 ret = -EFAULT; 1373 ret = -EFAULT;
1374 else 1374 else
1375 ret = 0; 1375 ret = 0;
1376 1376
1377 up(&ip6t_mutex); 1377 up(&ip6t_mutex);
1378 } 1378 }
1379 } 1379 }
1380 break; 1380 break;
1381 1381
1382 case IP6T_SO_GET_ENTRIES: { 1382 case IP6T_SO_GET_ENTRIES: {
1383 struct ip6t_get_entries get; 1383 struct ip6t_get_entries get;
1384 1384
1385 if (*len < sizeof(get)) { 1385 if (*len < sizeof(get)) {
1386 duprintf("get_entries: %u < %u\n", *len, sizeof(get)); 1386 duprintf("get_entries: %u < %u\n", *len, sizeof(get));
1387 ret = -EINVAL; 1387 ret = -EINVAL;
1388 } else if (copy_from_user(&get, user, sizeof(get)) != 0) { 1388 } else if (copy_from_user(&get, user, sizeof(get)) != 0) {
1389 ret = -EFAULT; 1389 ret = -EFAULT;
1390 } else if (*len != sizeof(struct ip6t_get_entries) + get.size) { 1390 } else if (*len != sizeof(struct ip6t_get_entries) + get.size) {
1391 duprintf("get_entries: %u != %u\n", *len, 1391 duprintf("get_entries: %u != %u\n", *len,
1392 sizeof(struct ip6t_get_entries) + get.size); 1392 sizeof(struct ip6t_get_entries) + get.size);
1393 ret = -EINVAL; 1393 ret = -EINVAL;
1394 } else 1394 } else
1395 ret = get_entries(&get, user); 1395 ret = get_entries(&get, user);
1396 break; 1396 break;
1397 } 1397 }
1398 1398
1399 default: 1399 default:
1400 duprintf("do_ip6t_get_ctl: unknown request %i\n", cmd); 1400 duprintf("do_ip6t_get_ctl: unknown request %i\n", cmd);
1401 ret = -EINVAL; 1401 ret = -EINVAL;
1402 } 1402 }
1403 1403
1404 return ret; 1404 return ret;
1405 } 1405 }
1406 1406
1407 /* Registration hooks for targets. */ 1407 /* Registration hooks for targets. */
1408 int 1408 int
1409 ip6t_register_target(struct ip6t_target *target) 1409 ip6t_register_target(struct ip6t_target *target)
1410 { 1410 {
1411 int ret; 1411 int ret;
1412 1412
1413 ret = down_interruptible(&ip6t_mutex); 1413 ret = down_interruptible(&ip6t_mutex);
1414 if (ret != 0) 1414 if (ret != 0)
1415 return ret; 1415 return ret;
1416 1416
1417 if (!list_named_insert(&ip6t_target, target)) { 1417 if (!list_named_insert(&ip6t_target, target)) {
1418 duprintf("ip6t_register_target: `%s' already in list!\n", 1418 duprintf("ip6t_register_target: `%s' already in list!\n",
1419 target->name); 1419 target->name);
1420 ret = -EINVAL; 1420 ret = -EINVAL;
1421 } 1421 }
1422 up(&ip6t_mutex); 1422 up(&ip6t_mutex);
1423 return ret; 1423 return ret;
1424 } 1424 }
1425 1425
1426 void 1426 void
1427 ip6t_unregister_target(struct ip6t_target *target) 1427 ip6t_unregister_target(struct ip6t_target *target)
1428 { 1428 {
1429 down(&ip6t_mutex); 1429 down(&ip6t_mutex);
1430 LIST_DELETE(&ip6t_target, target); 1430 LIST_DELETE(&ip6t_target, target);
1431 up(&ip6t_mutex); 1431 up(&ip6t_mutex);
1432 } 1432 }
1433 1433
1434 int 1434 int
1435 ip6t_register_match(struct ip6t_match *match) 1435 ip6t_register_match(struct ip6t_match *match)
1436 { 1436 {
1437 int ret; 1437 int ret;
1438 1438
1439 ret = down_interruptible(&ip6t_mutex); 1439 ret = down_interruptible(&ip6t_mutex);
1440 if (ret != 0) 1440 if (ret != 0)
1441 return ret; 1441 return ret;
1442 1442
1443 if (!list_named_insert(&ip6t_match, match)) { 1443 if (!list_named_insert(&ip6t_match, match)) {
1444 duprintf("ip6t_register_match: `%s' already in list!\n", 1444 duprintf("ip6t_register_match: `%s' already in list!\n",
1445 match->name); 1445 match->name);
1446 ret = -EINVAL; 1446 ret = -EINVAL;
1447 } 1447 }
1448 up(&ip6t_mutex); 1448 up(&ip6t_mutex);
1449 1449
1450 return ret; 1450 return ret;
1451 } 1451 }
1452 1452
1453 void 1453 void
1454 ip6t_unregister_match(struct ip6t_match *match) 1454 ip6t_unregister_match(struct ip6t_match *match)
1455 { 1455 {
1456 down(&ip6t_mutex); 1456 down(&ip6t_mutex);
1457 LIST_DELETE(&ip6t_match, match); 1457 LIST_DELETE(&ip6t_match, match);
1458 up(&ip6t_mutex); 1458 up(&ip6t_mutex);
1459 } 1459 }
1460 1460
1461 int ip6t_register_table(struct ip6t_table *table, 1461 int ip6t_register_table(struct ip6t_table *table,
1462 const struct ip6t_replace *repl) 1462 const struct ip6t_replace *repl)
1463 { 1463 {
1464 int ret; 1464 int ret;
1465 struct ip6t_table_info *newinfo; 1465 struct ip6t_table_info *newinfo;
1466 static struct ip6t_table_info bootstrap 1466 static struct ip6t_table_info bootstrap
1467 = { 0, 0, 0, { 0 }, { 0 }, { } }; 1467 = { 0, 0, 0, { 0 }, { 0 }, { } };
1468 1468
1469 newinfo = vmalloc(sizeof(struct ip6t_table_info) 1469 newinfo = vmalloc(sizeof(struct ip6t_table_info)
1470 + SMP_ALIGN(repl->size) * num_possible_cpus()); 1470 + SMP_ALIGN(repl->size) * num_possible_cpus());
1471 if (!newinfo) 1471 if (!newinfo)
1472 return -ENOMEM; 1472 return -ENOMEM;
1473 1473
1474 memcpy(newinfo->entries, repl->entries, repl->size); 1474 memcpy(newinfo->entries, repl->entries, repl->size);
1475 1475
1476 ret = translate_table(table->name, table->valid_hooks, 1476 ret = translate_table(table->name, table->valid_hooks,
1477 newinfo, repl->size, 1477 newinfo, repl->size,
1478 repl->num_entries, 1478 repl->num_entries,
1479 repl->hook_entry, 1479 repl->hook_entry,
1480 repl->underflow); 1480 repl->underflow);
1481 if (ret != 0) { 1481 if (ret != 0) {
1482 vfree(newinfo); 1482 vfree(newinfo);
1483 return ret; 1483 return ret;
1484 } 1484 }
1485 1485
1486 ret = down_interruptible(&ip6t_mutex); 1486 ret = down_interruptible(&ip6t_mutex);
1487 if (ret != 0) { 1487 if (ret != 0) {
1488 vfree(newinfo); 1488 vfree(newinfo);
1489 return ret; 1489 return ret;
1490 } 1490 }
1491 1491
1492 /* Don't autoload: we'd eat our tail... */ 1492 /* Don't autoload: we'd eat our tail... */
1493 if (list_named_find(&ip6t_tables, table->name)) { 1493 if (list_named_find(&ip6t_tables, table->name)) {
1494 ret = -EEXIST; 1494 ret = -EEXIST;
1495 goto free_unlock; 1495 goto free_unlock;
1496 } 1496 }
1497 1497
1498 /* Simplifies replace_table code. */ 1498 /* Simplifies replace_table code. */
1499 table->private = &bootstrap; 1499 table->private = &bootstrap;
1500 if (!replace_table(table, 0, newinfo, &ret)) 1500 if (!replace_table(table, 0, newinfo, &ret))
1501 goto free_unlock; 1501 goto free_unlock;
1502 1502
1503 duprintf("table->private->number = %u\n", 1503 duprintf("table->private->number = %u\n",
1504 table->private->number); 1504 table->private->number);
1505 1505
1506 /* save number of initial entries */ 1506 /* save number of initial entries */
1507 table->private->initial_entries = table->private->number; 1507 table->private->initial_entries = table->private->number;
1508 1508
1509 rwlock_init(&table->lock); 1509 rwlock_init(&table->lock);
1510 list_prepend(&ip6t_tables, table); 1510 list_prepend(&ip6t_tables, table);
1511 1511
1512 unlock: 1512 unlock:
1513 up(&ip6t_mutex); 1513 up(&ip6t_mutex);
1514 return ret; 1514 return ret;
1515 1515
1516 free_unlock: 1516 free_unlock:
1517 vfree(newinfo); 1517 vfree(newinfo);
1518 goto unlock; 1518 goto unlock;
1519 } 1519 }
1520 1520
1521 void ip6t_unregister_table(struct ip6t_table *table) 1521 void ip6t_unregister_table(struct ip6t_table *table)
1522 { 1522 {
1523 down(&ip6t_mutex); 1523 down(&ip6t_mutex);
1524 LIST_DELETE(&ip6t_tables, table); 1524 LIST_DELETE(&ip6t_tables, table);
1525 up(&ip6t_mutex); 1525 up(&ip6t_mutex);
1526 1526
1527 /* Decrease module usage counts and free resources */ 1527 /* Decrease module usage counts and free resources */
1528 IP6T_ENTRY_ITERATE(table->private->entries, table->private->size, 1528 IP6T_ENTRY_ITERATE(table->private->entries, table->private->size,
1529 cleanup_entry, NULL); 1529 cleanup_entry, NULL);
1530 vfree(table->private); 1530 vfree(table->private);
1531 } 1531 }
1532 1532
1533 /* Returns 1 if the port is matched by the range, 0 otherwise */ 1533 /* Returns 1 if the port is matched by the range, 0 otherwise */
1534 static inline int 1534 static inline int
1535 port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert) 1535 port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
1536 { 1536 {
1537 int ret; 1537 int ret;
1538 1538
1539 ret = (port >= min && port <= max) ^ invert; 1539 ret = (port >= min && port <= max) ^ invert;
1540 return ret; 1540 return ret;
1541 } 1541 }
1542 1542
1543 static int 1543 static int
1544 tcp_find_option(u_int8_t option, 1544 tcp_find_option(u_int8_t option,
1545 const struct sk_buff *skb, 1545 const struct sk_buff *skb,
1546 unsigned int tcpoff, 1546 unsigned int tcpoff,
1547 unsigned int optlen, 1547 unsigned int optlen,
1548 int invert, 1548 int invert,
1549 int *hotdrop) 1549 int *hotdrop)
1550 { 1550 {
1551 /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ 1551 /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
1552 u_int8_t _opt[60 - sizeof(struct tcphdr)], *op; 1552 u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
1553 unsigned int i; 1553 unsigned int i;
1554 1554
1555 duprintf("tcp_match: finding option\n"); 1555 duprintf("tcp_match: finding option\n");
1556 if (!optlen) 1556 if (!optlen)
1557 return invert; 1557 return invert;
1558 /* If we don't have the whole header, drop packet. */ 1558 /* If we don't have the whole header, drop packet. */
1559 op = skb_header_pointer(skb, tcpoff + sizeof(struct tcphdr), optlen, 1559 op = skb_header_pointer(skb, tcpoff + sizeof(struct tcphdr), optlen,
1560 _opt); 1560 _opt);
1561 if (op == NULL) { 1561 if (op == NULL) {
1562 *hotdrop = 1; 1562 *hotdrop = 1;
1563 return 0; 1563 return 0;
1564 } 1564 }
1565 1565
1566 for (i = 0; i < optlen; ) { 1566 for (i = 0; i < optlen; ) {
1567 if (op[i] == option) return !invert; 1567 if (op[i] == option) return !invert;
1568 if (op[i] < 2) i++; 1568 if (op[i] < 2) i++;
1569 else i += op[i+1]?:1; 1569 else i += op[i+1]?:1;
1570 } 1570 }
1571 1571
1572 return invert; 1572 return invert;
1573 } 1573 }
1574 1574
1575 static int 1575 static int
1576 tcp_match(const struct sk_buff *skb, 1576 tcp_match(const struct sk_buff *skb,
1577 const struct net_device *in, 1577 const struct net_device *in,
1578 const struct net_device *out, 1578 const struct net_device *out,
1579 const void *matchinfo, 1579 const void *matchinfo,
1580 int offset, 1580 int offset,
1581 unsigned int protoff, 1581 unsigned int protoff,
1582 int *hotdrop) 1582 int *hotdrop)
1583 { 1583 {
1584 struct tcphdr _tcph, *th; 1584 struct tcphdr _tcph, *th;
1585 const struct ip6t_tcp *tcpinfo = matchinfo; 1585 const struct ip6t_tcp *tcpinfo = matchinfo;
1586 1586
1587 if (offset) { 1587 if (offset) {
1588 /* To quote Alan: 1588 /* To quote Alan:
1589 1589
1590 Don't allow a fragment of TCP 8 bytes in. Nobody normal 1590 Don't allow a fragment of TCP 8 bytes in. Nobody normal
1591 causes this. Its a cracker trying to break in by doing a 1591 causes this. Its a cracker trying to break in by doing a
1592 flag overwrite to pass the direction checks. 1592 flag overwrite to pass the direction checks.
1593 */ 1593 */
1594 if (offset == 1) { 1594 if (offset == 1) {
1595 duprintf("Dropping evil TCP offset=1 frag.\n"); 1595 duprintf("Dropping evil TCP offset=1 frag.\n");
1596 *hotdrop = 1; 1596 *hotdrop = 1;
1597 } 1597 }
1598 /* Must not be a fragment. */ 1598 /* Must not be a fragment. */
1599 return 0; 1599 return 0;
1600 } 1600 }
1601 1601
1602 #define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg)) 1602 #define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
1603 1603
1604 th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); 1604 th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
1605 if (th == NULL) { 1605 if (th == NULL) {
1606 /* We've been asked to examine this packet, and we 1606 /* We've been asked to examine this packet, and we
1607 can't. Hence, no choice but to drop. */ 1607 can't. Hence, no choice but to drop. */
1608 duprintf("Dropping evil TCP offset=0 tinygram.\n"); 1608 duprintf("Dropping evil TCP offset=0 tinygram.\n");
1609 *hotdrop = 1; 1609 *hotdrop = 1;
1610 return 0; 1610 return 0;
1611 } 1611 }
1612 1612
1613 if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1], 1613 if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
1614 ntohs(th->source), 1614 ntohs(th->source),
1615 !!(tcpinfo->invflags & IP6T_TCP_INV_SRCPT))) 1615 !!(tcpinfo->invflags & IP6T_TCP_INV_SRCPT)))
1616 return 0; 1616 return 0;
1617 if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1], 1617 if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
1618 ntohs(th->dest), 1618 ntohs(th->dest),
1619 !!(tcpinfo->invflags & IP6T_TCP_INV_DSTPT))) 1619 !!(tcpinfo->invflags & IP6T_TCP_INV_DSTPT)))
1620 return 0; 1620 return 0;
1621 if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask) 1621 if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
1622 == tcpinfo->flg_cmp, 1622 == tcpinfo->flg_cmp,
1623 IP6T_TCP_INV_FLAGS)) 1623 IP6T_TCP_INV_FLAGS))
1624 return 0; 1624 return 0;
1625 if (tcpinfo->option) { 1625 if (tcpinfo->option) {
1626 if (th->doff * 4 < sizeof(_tcph)) { 1626 if (th->doff * 4 < sizeof(_tcph)) {
1627 *hotdrop = 1; 1627 *hotdrop = 1;
1628 return 0; 1628 return 0;
1629 } 1629 }
1630 if (!tcp_find_option(tcpinfo->option, skb, protoff, 1630 if (!tcp_find_option(tcpinfo->option, skb, protoff,
1631 th->doff*4 - sizeof(*th), 1631 th->doff*4 - sizeof(*th),
1632 tcpinfo->invflags & IP6T_TCP_INV_OPTION, 1632 tcpinfo->invflags & IP6T_TCP_INV_OPTION,
1633 hotdrop)) 1633 hotdrop))
1634 return 0; 1634 return 0;
1635 } 1635 }
1636 return 1; 1636 return 1;
1637 } 1637 }
1638 1638
1639 /* Called when user tries to insert an entry of this type. */ 1639 /* Called when user tries to insert an entry of this type. */
1640 static int 1640 static int
1641 tcp_checkentry(const char *tablename, 1641 tcp_checkentry(const char *tablename,
1642 const struct ip6t_ip6 *ipv6, 1642 const struct ip6t_ip6 *ipv6,
1643 void *matchinfo, 1643 void *matchinfo,
1644 unsigned int matchsize, 1644 unsigned int matchsize,
1645 unsigned int hook_mask) 1645 unsigned int hook_mask)
1646 { 1646 {
1647 const struct ip6t_tcp *tcpinfo = matchinfo; 1647 const struct ip6t_tcp *tcpinfo = matchinfo;
1648 1648
1649 /* Must specify proto == TCP, and no unknown invflags */ 1649 /* Must specify proto == TCP, and no unknown invflags */
1650 return ipv6->proto == IPPROTO_TCP 1650 return ipv6->proto == IPPROTO_TCP
1651 && !(ipv6->invflags & IP6T_INV_PROTO) 1651 && !(ipv6->invflags & IP6T_INV_PROTO)
1652 && matchsize == IP6T_ALIGN(sizeof(struct ip6t_tcp)) 1652 && matchsize == IP6T_ALIGN(sizeof(struct ip6t_tcp))
1653 && !(tcpinfo->invflags & ~IP6T_TCP_INV_MASK); 1653 && !(tcpinfo->invflags & ~IP6T_TCP_INV_MASK);
1654 } 1654 }
1655 1655
1656 static int 1656 static int
1657 udp_match(const struct sk_buff *skb, 1657 udp_match(const struct sk_buff *skb,
1658 const struct net_device *in, 1658 const struct net_device *in,
1659 const struct net_device *out, 1659 const struct net_device *out,
1660 const void *matchinfo, 1660 const void *matchinfo,
1661 int offset, 1661 int offset,
1662 unsigned int protoff, 1662 unsigned int protoff,
1663 int *hotdrop) 1663 int *hotdrop)
1664 { 1664 {
1665 struct udphdr _udph, *uh; 1665 struct udphdr _udph, *uh;
1666 const struct ip6t_udp *udpinfo = matchinfo; 1666 const struct ip6t_udp *udpinfo = matchinfo;
1667 1667
1668 /* Must not be a fragment. */ 1668 /* Must not be a fragment. */
1669 if (offset) 1669 if (offset)
1670 return 0; 1670 return 0;
1671 1671
1672 uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph); 1672 uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph);
1673 if (uh == NULL) { 1673 if (uh == NULL) {
1674 /* We've been asked to examine this packet, and we 1674 /* We've been asked to examine this packet, and we
1675 can't. Hence, no choice but to drop. */ 1675 can't. Hence, no choice but to drop. */
1676 duprintf("Dropping evil UDP tinygram.\n"); 1676 duprintf("Dropping evil UDP tinygram.\n");
1677 *hotdrop = 1; 1677 *hotdrop = 1;
1678 return 0; 1678 return 0;
1679 } 1679 }
1680 1680
1681 return port_match(udpinfo->spts[0], udpinfo->spts[1], 1681 return port_match(udpinfo->spts[0], udpinfo->spts[1],
1682 ntohs(uh->source), 1682 ntohs(uh->source),
1683 !!(udpinfo->invflags & IP6T_UDP_INV_SRCPT)) 1683 !!(udpinfo->invflags & IP6T_UDP_INV_SRCPT))
1684 && port_match(udpinfo->dpts[0], udpinfo->dpts[1], 1684 && port_match(udpinfo->dpts[0], udpinfo->dpts[1],
1685 ntohs(uh->dest), 1685 ntohs(uh->dest),
1686 !!(udpinfo->invflags & IP6T_UDP_INV_DSTPT)); 1686 !!(udpinfo->invflags & IP6T_UDP_INV_DSTPT));
1687 } 1687 }
1688 1688
1689 /* Called when user tries to insert an entry of this type. */ 1689 /* Called when user tries to insert an entry of this type. */
1690 static int 1690 static int
1691 udp_checkentry(const char *tablename, 1691 udp_checkentry(const char *tablename,
1692 const struct ip6t_ip6 *ipv6, 1692 const struct ip6t_ip6 *ipv6,
1693 void *matchinfo, 1693 void *matchinfo,
1694 unsigned int matchinfosize, 1694 unsigned int matchinfosize,
1695 unsigned int hook_mask) 1695 unsigned int hook_mask)
1696 { 1696 {
1697 const struct ip6t_udp *udpinfo = matchinfo; 1697 const struct ip6t_udp *udpinfo = matchinfo;
1698 1698
1699 /* Must specify proto == UDP, and no unknown invflags */ 1699 /* Must specify proto == UDP, and no unknown invflags */
1700 if (ipv6->proto != IPPROTO_UDP || (ipv6->invflags & IP6T_INV_PROTO)) { 1700 if (ipv6->proto != IPPROTO_UDP || (ipv6->invflags & IP6T_INV_PROTO)) {
1701 duprintf("ip6t_udp: Protocol %u != %u\n", ipv6->proto, 1701 duprintf("ip6t_udp: Protocol %u != %u\n", ipv6->proto,
1702 IPPROTO_UDP); 1702 IPPROTO_UDP);
1703 return 0; 1703 return 0;
1704 } 1704 }
1705 if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_udp))) { 1705 if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_udp))) {
1706 duprintf("ip6t_udp: matchsize %u != %u\n", 1706 duprintf("ip6t_udp: matchsize %u != %u\n",
1707 matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_udp))); 1707 matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_udp)));
1708 return 0; 1708 return 0;
1709 } 1709 }
1710 if (udpinfo->invflags & ~IP6T_UDP_INV_MASK) { 1710 if (udpinfo->invflags & ~IP6T_UDP_INV_MASK) {
1711 duprintf("ip6t_udp: unknown flags %X\n", 1711 duprintf("ip6t_udp: unknown flags %X\n",
1712 udpinfo->invflags); 1712 udpinfo->invflags);
1713 return 0; 1713 return 0;
1714 } 1714 }
1715 1715
1716 return 1; 1716 return 1;
1717 } 1717 }
1718 1718
1719 /* Returns 1 if the type and code is matched by the range, 0 otherwise */ 1719 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
1720 static inline int 1720 static inline int
1721 icmp6_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code, 1721 icmp6_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
1722 u_int8_t type, u_int8_t code, 1722 u_int8_t type, u_int8_t code,
1723 int invert) 1723 int invert)
1724 { 1724 {
1725 return (type == test_type && code >= min_code && code <= max_code) 1725 return (type == test_type && code >= min_code && code <= max_code)
1726 ^ invert; 1726 ^ invert;
1727 } 1727 }
1728 1728
1729 static int 1729 static int
1730 icmp6_match(const struct sk_buff *skb, 1730 icmp6_match(const struct sk_buff *skb,
1731 const struct net_device *in, 1731 const struct net_device *in,
1732 const struct net_device *out, 1732 const struct net_device *out,
1733 const void *matchinfo, 1733 const void *matchinfo,
1734 int offset, 1734 int offset,
1735 unsigned int protoff, 1735 unsigned int protoff,
1736 int *hotdrop) 1736 int *hotdrop)
1737 { 1737 {
1738 struct icmp6hdr _icmp, *ic; 1738 struct icmp6hdr _icmp, *ic;
1739 const struct ip6t_icmp *icmpinfo = matchinfo; 1739 const struct ip6t_icmp *icmpinfo = matchinfo;
1740 1740
1741 /* Must not be a fragment. */ 1741 /* Must not be a fragment. */
1742 if (offset) 1742 if (offset)
1743 return 0; 1743 return 0;
1744 1744
1745 ic = skb_header_pointer(skb, protoff, sizeof(_icmp), &_icmp); 1745 ic = skb_header_pointer(skb, protoff, sizeof(_icmp), &_icmp);
1746 if (ic == NULL) { 1746 if (ic == NULL) {
1747 /* We've been asked to examine this packet, and we 1747 /* We've been asked to examine this packet, and we
1748 can't. Hence, no choice but to drop. */ 1748 can't. Hence, no choice but to drop. */
1749 duprintf("Dropping evil ICMP tinygram.\n"); 1749 duprintf("Dropping evil ICMP tinygram.\n");
1750 *hotdrop = 1; 1750 *hotdrop = 1;
1751 return 0; 1751 return 0;
1752 } 1752 }
1753 1753
1754 return icmp6_type_code_match(icmpinfo->type, 1754 return icmp6_type_code_match(icmpinfo->type,
1755 icmpinfo->code[0], 1755 icmpinfo->code[0],
1756 icmpinfo->code[1], 1756 icmpinfo->code[1],
1757 ic->icmp6_type, ic->icmp6_code, 1757 ic->icmp6_type, ic->icmp6_code,
1758 !!(icmpinfo->invflags&IP6T_ICMP_INV)); 1758 !!(icmpinfo->invflags&IP6T_ICMP_INV));
1759 } 1759 }
1760 1760
1761 /* Called when user tries to insert an entry of this type. */ 1761 /* Called when user tries to insert an entry of this type. */
1762 static int 1762 static int
1763 icmp6_checkentry(const char *tablename, 1763 icmp6_checkentry(const char *tablename,
1764 const struct ip6t_ip6 *ipv6, 1764 const struct ip6t_ip6 *ipv6,
1765 void *matchinfo, 1765 void *matchinfo,
1766 unsigned int matchsize, 1766 unsigned int matchsize,
1767 unsigned int hook_mask) 1767 unsigned int hook_mask)
1768 { 1768 {
1769 const struct ip6t_icmp *icmpinfo = matchinfo; 1769 const struct ip6t_icmp *icmpinfo = matchinfo;
1770 1770
1771 /* Must specify proto == ICMP, and no unknown invflags */ 1771 /* Must specify proto == ICMP, and no unknown invflags */
1772 return ipv6->proto == IPPROTO_ICMPV6 1772 return ipv6->proto == IPPROTO_ICMPV6
1773 && !(ipv6->invflags & IP6T_INV_PROTO) 1773 && !(ipv6->invflags & IP6T_INV_PROTO)
1774 && matchsize == IP6T_ALIGN(sizeof(struct ip6t_icmp)) 1774 && matchsize == IP6T_ALIGN(sizeof(struct ip6t_icmp))
1775 && !(icmpinfo->invflags & ~IP6T_ICMP_INV); 1775 && !(icmpinfo->invflags & ~IP6T_ICMP_INV);
1776 } 1776 }
1777 1777
1778 /* The built-in targets: standard (NULL) and error. */ 1778 /* The built-in targets: standard (NULL) and error. */
1779 static struct ip6t_target ip6t_standard_target = { 1779 static struct ip6t_target ip6t_standard_target = {
1780 .name = IP6T_STANDARD_TARGET, 1780 .name = IP6T_STANDARD_TARGET,
1781 }; 1781 };
1782 1782
1783 static struct ip6t_target ip6t_error_target = { 1783 static struct ip6t_target ip6t_error_target = {
1784 .name = IP6T_ERROR_TARGET, 1784 .name = IP6T_ERROR_TARGET,
1785 .target = ip6t_error, 1785 .target = ip6t_error,
1786 }; 1786 };
1787 1787
1788 static struct nf_sockopt_ops ip6t_sockopts = { 1788 static struct nf_sockopt_ops ip6t_sockopts = {
1789 .pf = PF_INET6, 1789 .pf = PF_INET6,
1790 .set_optmin = IP6T_BASE_CTL, 1790 .set_optmin = IP6T_BASE_CTL,
1791 .set_optmax = IP6T_SO_SET_MAX+1, 1791 .set_optmax = IP6T_SO_SET_MAX+1,
1792 .set = do_ip6t_set_ctl, 1792 .set = do_ip6t_set_ctl,
1793 .get_optmin = IP6T_BASE_CTL, 1793 .get_optmin = IP6T_BASE_CTL,
1794 .get_optmax = IP6T_SO_GET_MAX+1, 1794 .get_optmax = IP6T_SO_GET_MAX+1,
1795 .get = do_ip6t_get_ctl, 1795 .get = do_ip6t_get_ctl,
1796 }; 1796 };
1797 1797
1798 static struct ip6t_match tcp_matchstruct = { 1798 static struct ip6t_match tcp_matchstruct = {
1799 .name = "tcp", 1799 .name = "tcp",
1800 .match = &tcp_match, 1800 .match = &tcp_match,
1801 .checkentry = &tcp_checkentry, 1801 .checkentry = &tcp_checkentry,
1802 }; 1802 };
1803 1803
1804 static struct ip6t_match udp_matchstruct = { 1804 static struct ip6t_match udp_matchstruct = {
1805 .name = "udp", 1805 .name = "udp",
1806 .match = &udp_match, 1806 .match = &udp_match,
1807 .checkentry = &udp_checkentry, 1807 .checkentry = &udp_checkentry,
1808 }; 1808 };
1809 1809
1810 static struct ip6t_match icmp6_matchstruct = { 1810 static struct ip6t_match icmp6_matchstruct = {
1811 .name = "icmp6", 1811 .name = "icmp6",
1812 .match = &icmp6_match, 1812 .match = &icmp6_match,
1813 .checkentry = &icmp6_checkentry, 1813 .checkentry = &icmp6_checkentry,
1814 }; 1814 };
1815 1815
1816 #ifdef CONFIG_PROC_FS 1816 #ifdef CONFIG_PROC_FS
1817 static inline int print_name(const char *i, 1817 static inline int print_name(const char *i,
1818 off_t start_offset, char *buffer, int length, 1818 off_t start_offset, char *buffer, int length,
1819 off_t *pos, unsigned int *count) 1819 off_t *pos, unsigned int *count)
1820 { 1820 {
1821 if ((*count)++ >= start_offset) { 1821 if ((*count)++ >= start_offset) {
1822 unsigned int namelen; 1822 unsigned int namelen;
1823 1823
1824 namelen = sprintf(buffer + *pos, "%s\n", 1824 namelen = sprintf(buffer + *pos, "%s\n",
1825 i + sizeof(struct list_head)); 1825 i + sizeof(struct list_head));
1826 if (*pos + namelen > length) { 1826 if (*pos + namelen > length) {
1827 /* Stop iterating */ 1827 /* Stop iterating */
1828 return 1; 1828 return 1;
1829 } 1829 }
1830 *pos += namelen; 1830 *pos += namelen;
1831 } 1831 }
1832 return 0; 1832 return 0;
1833 } 1833 }
1834 1834
1835 static inline int print_target(const struct ip6t_target *t, 1835 static inline int print_target(const struct ip6t_target *t,
1836 off_t start_offset, char *buffer, int length, 1836 off_t start_offset, char *buffer, int length,
1837 off_t *pos, unsigned int *count) 1837 off_t *pos, unsigned int *count)
1838 { 1838 {
1839 if (t == &ip6t_standard_target || t == &ip6t_error_target) 1839 if (t == &ip6t_standard_target || t == &ip6t_error_target)
1840 return 0; 1840 return 0;
1841 return print_name((char *)t, start_offset, buffer, length, pos, count); 1841 return print_name((char *)t, start_offset, buffer, length, pos, count);
1842 } 1842 }
1843 1843
1844 static int ip6t_get_tables(char *buffer, char **start, off_t offset, int length) 1844 static int ip6t_get_tables(char *buffer, char **start, off_t offset, int length)
1845 { 1845 {
1846 off_t pos = 0; 1846 off_t pos = 0;
1847 unsigned int count = 0; 1847 unsigned int count = 0;
1848 1848
1849 if (down_interruptible(&ip6t_mutex) != 0) 1849 if (down_interruptible(&ip6t_mutex) != 0)
1850 return 0; 1850 return 0;
1851 1851
1852 LIST_FIND(&ip6t_tables, print_name, char *, 1852 LIST_FIND(&ip6t_tables, print_name, char *,
1853 offset, buffer, length, &pos, &count); 1853 offset, buffer, length, &pos, &count);
1854 1854
1855 up(&ip6t_mutex); 1855 up(&ip6t_mutex);
1856 1856
1857 /* `start' hack - see fs/proc/generic.c line ~105 */ 1857 /* `start' hack - see fs/proc/generic.c line ~105 */
1858 *start=(char *)((unsigned long)count-offset); 1858 *start=(char *)((unsigned long)count-offset);
1859 return pos; 1859 return pos;
1860 } 1860 }
1861 1861
1862 static int ip6t_get_targets(char *buffer, char **start, off_t offset, int length) 1862 static int ip6t_get_targets(char *buffer, char **start, off_t offset, int length)
1863 { 1863 {
1864 off_t pos = 0; 1864 off_t pos = 0;
1865 unsigned int count = 0; 1865 unsigned int count = 0;
1866 1866
1867 if (down_interruptible(&ip6t_mutex) != 0) 1867 if (down_interruptible(&ip6t_mutex) != 0)
1868 return 0; 1868 return 0;
1869 1869
1870 LIST_FIND(&ip6t_target, print_target, struct ip6t_target *, 1870 LIST_FIND(&ip6t_target, print_target, struct ip6t_target *,
1871 offset, buffer, length, &pos, &count); 1871 offset, buffer, length, &pos, &count);
1872 1872
1873 up(&ip6t_mutex); 1873 up(&ip6t_mutex);
1874 1874
1875 *start = (char *)((unsigned long)count - offset); 1875 *start = (char *)((unsigned long)count - offset);
1876 return pos; 1876 return pos;
1877 } 1877 }
1878 1878
1879 static int ip6t_get_matches(char *buffer, char **start, off_t offset, int length) 1879 static int ip6t_get_matches(char *buffer, char **start, off_t offset, int length)
1880 { 1880 {
1881 off_t pos = 0; 1881 off_t pos = 0;
1882 unsigned int count = 0; 1882 unsigned int count = 0;
1883 1883
1884 if (down_interruptible(&ip6t_mutex) != 0) 1884 if (down_interruptible(&ip6t_mutex) != 0)
1885 return 0; 1885 return 0;
1886 1886
1887 LIST_FIND(&ip6t_match, print_name, char *, 1887 LIST_FIND(&ip6t_match, print_name, char *,
1888 offset, buffer, length, &pos, &count); 1888 offset, buffer, length, &pos, &count);
1889 1889
1890 up(&ip6t_mutex); 1890 up(&ip6t_mutex);
1891 1891
1892 *start = (char *)((unsigned long)count - offset); 1892 *start = (char *)((unsigned long)count - offset);
1893 return pos; 1893 return pos;
1894 } 1894 }
1895 1895
1896 static struct { char *name; get_info_t *get_info; } ip6t_proc_entry[] = 1896 static struct { char *name; get_info_t *get_info; } ip6t_proc_entry[] =
1897 { { "ip6_tables_names", ip6t_get_tables }, 1897 { { "ip6_tables_names", ip6t_get_tables },
1898 { "ip6_tables_targets", ip6t_get_targets }, 1898 { "ip6_tables_targets", ip6t_get_targets },
1899 { "ip6_tables_matches", ip6t_get_matches }, 1899 { "ip6_tables_matches", ip6t_get_matches },
1900 { NULL, NULL} }; 1900 { NULL, NULL} };
1901 #endif /*CONFIG_PROC_FS*/ 1901 #endif /*CONFIG_PROC_FS*/
1902 1902
1903 static int __init init(void) 1903 static int __init init(void)
1904 { 1904 {
1905 int ret; 1905 int ret;
1906 1906
1907 /* Noone else will be downing sem now, so we won't sleep */ 1907 /* Noone else will be downing sem now, so we won't sleep */
1908 down(&ip6t_mutex); 1908 down(&ip6t_mutex);
1909 list_append(&ip6t_target, &ip6t_standard_target); 1909 list_append(&ip6t_target, &ip6t_standard_target);
1910 list_append(&ip6t_target, &ip6t_error_target); 1910 list_append(&ip6t_target, &ip6t_error_target);
1911 list_append(&ip6t_match, &tcp_matchstruct); 1911 list_append(&ip6t_match, &tcp_matchstruct);
1912 list_append(&ip6t_match, &udp_matchstruct); 1912 list_append(&ip6t_match, &udp_matchstruct);
1913 list_append(&ip6t_match, &icmp6_matchstruct); 1913 list_append(&ip6t_match, &icmp6_matchstruct);
1914 up(&ip6t_mutex); 1914 up(&ip6t_mutex);
1915 1915
1916 /* Register setsockopt */ 1916 /* Register setsockopt */
1917 ret = nf_register_sockopt(&ip6t_sockopts); 1917 ret = nf_register_sockopt(&ip6t_sockopts);
1918 if (ret < 0) { 1918 if (ret < 0) {
1919 duprintf("Unable to register sockopts.\n"); 1919 duprintf("Unable to register sockopts.\n");
1920 return ret; 1920 return ret;
1921 } 1921 }
1922 1922
1923 #ifdef CONFIG_PROC_FS 1923 #ifdef CONFIG_PROC_FS
1924 { 1924 {
1925 struct proc_dir_entry *proc; 1925 struct proc_dir_entry *proc;
1926 int i; 1926 int i;
1927 1927
1928 for (i = 0; ip6t_proc_entry[i].name; i++) { 1928 for (i = 0; ip6t_proc_entry[i].name; i++) {
1929 proc = proc_net_create(ip6t_proc_entry[i].name, 0, 1929 proc = proc_net_create(ip6t_proc_entry[i].name, 0,
1930 ip6t_proc_entry[i].get_info); 1930 ip6t_proc_entry[i].get_info);
1931 if (!proc) { 1931 if (!proc) {
1932 while (--i >= 0) 1932 while (--i >= 0)
1933 proc_net_remove(ip6t_proc_entry[i].name); 1933 proc_net_remove(ip6t_proc_entry[i].name);
1934 nf_unregister_sockopt(&ip6t_sockopts); 1934 nf_unregister_sockopt(&ip6t_sockopts);
1935 return -ENOMEM; 1935 return -ENOMEM;
1936 } 1936 }
1937 proc->owner = THIS_MODULE; 1937 proc->owner = THIS_MODULE;
1938 } 1938 }
1939 } 1939 }
1940 #endif 1940 #endif
1941 1941
1942 printk("ip6_tables: (C) 2000-2002 Netfilter core team\n"); 1942 printk("ip6_tables: (C) 2000-2002 Netfilter core team\n");
1943 return 0; 1943 return 0;
1944 } 1944 }
1945 1945
1946 static void __exit fini(void) 1946 static void __exit fini(void)
1947 { 1947 {
1948 nf_unregister_sockopt(&ip6t_sockopts); 1948 nf_unregister_sockopt(&ip6t_sockopts);
1949 #ifdef CONFIG_PROC_FS 1949 #ifdef CONFIG_PROC_FS
1950 { 1950 {
1951 int i; 1951 int i;
1952 for (i = 0; ip6t_proc_entry[i].name; i++) 1952 for (i = 0; ip6t_proc_entry[i].name; i++)
1953 proc_net_remove(ip6t_proc_entry[i].name); 1953 proc_net_remove(ip6t_proc_entry[i].name);
1954 } 1954 }
1955 #endif 1955 #endif
1956 } 1956 }
1957 1957
1958 EXPORT_SYMBOL(ip6t_register_table); 1958 EXPORT_SYMBOL(ip6t_register_table);
1959 EXPORT_SYMBOL(ip6t_unregister_table); 1959 EXPORT_SYMBOL(ip6t_unregister_table);
1960 EXPORT_SYMBOL(ip6t_do_table); 1960 EXPORT_SYMBOL(ip6t_do_table);
1961 EXPORT_SYMBOL(ip6t_register_match); 1961 EXPORT_SYMBOL(ip6t_register_match);
1962 EXPORT_SYMBOL(ip6t_unregister_match); 1962 EXPORT_SYMBOL(ip6t_unregister_match);
1963 EXPORT_SYMBOL(ip6t_register_target); 1963 EXPORT_SYMBOL(ip6t_register_target);
1964 EXPORT_SYMBOL(ip6t_unregister_target); 1964 EXPORT_SYMBOL(ip6t_unregister_target);
1965 EXPORT_SYMBOL(ip6t_ext_hdr); 1965 EXPORT_SYMBOL(ip6t_ext_hdr);
1966 1966
1967 module_init(init); 1967 module_init(init);
1968 module_exit(fini); 1968 module_exit(fini);
1969 1969