]>
Commit | Line | Data |
---|---|---|
5cd1adba SH |
1 | #ifndef _XTABLES_H |
2 | #define _XTABLES_H | |
3 | ||
4 | /* | |
5 | * Changing any structs/functions may incur a needed change | |
6 | * in libxtables_vcurrent/vage too. | |
7 | */ | |
8 | ||
9 | #include <sys/socket.h> /* PF_* */ | |
10 | #include <sys/types.h> | |
11 | #include <limits.h> | |
12 | #include <stdbool.h> | |
13 | #include <stddef.h> | |
14 | #include <stdint.h> | |
15 | #include <netinet/in.h> | |
16 | #include <net/if.h> | |
17 | #include <linux/types.h> | |
18 | #include <linux/netfilter.h> | |
19 | #include <linux/netfilter/x_tables.h> | |
20 | ||
21 | #ifndef IPPROTO_SCTP | |
22 | #define IPPROTO_SCTP 132 | |
23 | #endif | |
24 | #ifndef IPPROTO_DCCP | |
25 | #define IPPROTO_DCCP 33 | |
26 | #endif | |
27 | #ifndef IPPROTO_MH | |
28 | # define IPPROTO_MH 135 | |
29 | #endif | |
30 | #ifndef IPPROTO_UDPLITE | |
31 | #define IPPROTO_UDPLITE 136 | |
32 | #endif | |
33 | ||
34 | #include <xtables-version.h> | |
35 | ||
36 | struct in_addr; | |
37 | ||
38 | /* | |
39 | * .size is here so that there is a somewhat reasonable check | |
40 | * against the chosen .type. | |
41 | */ | |
42 | #define XTOPT_POINTER(stype, member) \ | |
43 | .ptroff = offsetof(stype, member), \ | |
44 | .size = sizeof(((stype *)NULL)->member) | |
45 | #define XTOPT_TABLEEND {.name = NULL} | |
46 | ||
47 | /** | |
48 | * Select the format the input has to conform to, as well as the target type | |
49 | * (area pointed to with XTOPT_POINTER). Note that the storing is not always | |
50 | * uniform. @cb->val will be populated with as much as there is space, i.e. | |
51 | * exactly 2 items for ranges, but the target area can receive more values | |
52 | * (e.g. in case of ranges), or less values (e.g. %XTTYPE_HOSTMASK). | |
53 | * | |
54 | * %XTTYPE_NONE: option takes no argument | |
55 | * %XTTYPE_UINT*: standard integer | |
56 | * %XTTYPE_UINT*RC: colon-separated range of standard integers | |
57 | * %XTTYPE_DOUBLE: double-precision floating point number | |
58 | * %XTTYPE_STRING: arbitrary string | |
59 | * %XTTYPE_TOSMASK: 8-bit TOS value with optional mask | |
60 | * %XTTYPE_MARKMASK32: 32-bit mark with optional mask | |
61 | * %XTTYPE_SYSLOGLEVEL: syslog level by name or number | |
62 | * %XTTYPE_HOST: one host or address (ptr: union nf_inet_addr) | |
63 | * %XTTYPE_HOSTMASK: one host or address, with an optional prefix length | |
64 | * (ptr: union nf_inet_addr; only host portion is stored) | |
65 | * %XTTYPE_PROTOCOL: protocol number/name from /etc/protocols (ptr: uint8_t) | |
66 | * %XTTYPE_PORT: 16-bit port name or number (supports %XTOPT_NBO) | |
67 | * %XTTYPE_PORTRC: colon-separated port range (names acceptable), | |
68 | * (supports %XTOPT_NBO) | |
69 | * %XTTYPE_PLEN: prefix length | |
70 | * %XTTYPE_PLENMASK: prefix length (ptr: union nf_inet_addr) | |
71 | * %XTTYPE_ETHERMAC: Ethernet MAC address in hex form | |
72 | */ | |
73 | enum xt_option_type { | |
74 | XTTYPE_NONE, | |
75 | XTTYPE_UINT8, | |
76 | XTTYPE_UINT16, | |
77 | XTTYPE_UINT32, | |
78 | XTTYPE_UINT64, | |
79 | XTTYPE_UINT8RC, | |
80 | XTTYPE_UINT16RC, | |
81 | XTTYPE_UINT32RC, | |
82 | XTTYPE_UINT64RC, | |
83 | XTTYPE_DOUBLE, | |
84 | XTTYPE_STRING, | |
85 | XTTYPE_TOSMASK, | |
86 | XTTYPE_MARKMASK32, | |
87 | XTTYPE_SYSLOGLEVEL, | |
88 | XTTYPE_HOST, | |
89 | XTTYPE_HOSTMASK, | |
90 | XTTYPE_PROTOCOL, | |
91 | XTTYPE_PORT, | |
92 | XTTYPE_PORTRC, | |
93 | XTTYPE_PLEN, | |
94 | XTTYPE_PLENMASK, | |
95 | XTTYPE_ETHERMAC, | |
96 | }; | |
97 | ||
98 | /** | |
99 | * %XTOPT_INVERT: option is invertible (usable with !) | |
100 | * %XTOPT_MAND: option is mandatory | |
101 | * %XTOPT_MULTI: option may be specified multiple times | |
102 | * %XTOPT_PUT: store value into memory at @ptroff | |
103 | * %XTOPT_NBO: store value in network-byte order | |
104 | * (only certain XTTYPEs recognize this) | |
105 | */ | |
106 | enum xt_option_flags { | |
107 | XTOPT_INVERT = 1 << 0, | |
108 | XTOPT_MAND = 1 << 1, | |
109 | XTOPT_MULTI = 1 << 2, | |
110 | XTOPT_PUT = 1 << 3, | |
111 | XTOPT_NBO = 1 << 4, | |
112 | }; | |
113 | ||
114 | /** | |
115 | * @name: name of option | |
116 | * @type: type of input and validation method, see %XTTYPE_* | |
117 | * @id: unique number (within extension) for option, 0-31 | |
118 | * @excl: bitmask of flags that cannot be used with this option | |
119 | * @also: bitmask of flags that must be used with this option | |
120 | * @flags: bitmask of option flags, see %XTOPT_* | |
121 | * @ptroff: offset into private structure for member | |
122 | * @size: size of the item pointed to by @ptroff; this is a safeguard | |
123 | * @min: lowest allowed value (for singular integral types) | |
124 | * @max: highest allowed value (for singular integral types) | |
125 | */ | |
126 | struct xt_option_entry { | |
127 | const char *name; | |
128 | enum xt_option_type type; | |
129 | unsigned int id, excl, also, flags; | |
130 | unsigned int ptroff; | |
131 | size_t size; | |
132 | unsigned int min, max; | |
133 | }; | |
134 | ||
135 | /** | |
136 | * @arg: input from command line | |
137 | * @ext_name: name of extension currently being processed | |
138 | * @entry: current option being processed | |
139 | * @data: per-extension kernel data block | |
140 | * @xflags: options of the extension that have been used | |
141 | * @invert: whether option was used with ! | |
142 | * @nvals: number of results in uXX_multi | |
143 | * @val: parsed result | |
144 | * @udata: per-extension private scratch area | |
145 | * (cf. xtables_{match,target}->udata_size) | |
146 | */ | |
147 | struct xt_option_call { | |
148 | const char *arg, *ext_name; | |
149 | const struct xt_option_entry *entry; | |
150 | void *data; | |
151 | unsigned int xflags; | |
152 | bool invert; | |
153 | uint8_t nvals; | |
154 | union { | |
155 | uint8_t u8, u8_range[2], syslog_level, protocol; | |
156 | uint16_t u16, u16_range[2], port, port_range[2]; | |
157 | uint32_t u32, u32_range[2]; | |
158 | uint64_t u64, u64_range[2]; | |
159 | double dbl; | |
160 | struct { | |
161 | union nf_inet_addr haddr, hmask; | |
162 | uint8_t hlen; | |
163 | }; | |
164 | struct { | |
165 | uint8_t tos_value, tos_mask; | |
166 | }; | |
167 | struct { | |
168 | uint32_t mark, mask; | |
169 | }; | |
170 | uint8_t ethermac[6]; | |
171 | } val; | |
172 | /* Wished for a world where the ones below were gone: */ | |
173 | union { | |
174 | struct xt_entry_match **match; | |
175 | struct xt_entry_target **target; | |
176 | }; | |
177 | void *xt_entry; | |
178 | void *udata; | |
179 | }; | |
180 | ||
181 | /** | |
182 | * @ext_name: name of extension currently being processed | |
183 | * @data: per-extension (kernel) data block | |
184 | * @udata: per-extension private scratch area | |
185 | * (cf. xtables_{match,target}->udata_size) | |
186 | * @xflags: options of the extension that have been used | |
187 | */ | |
188 | struct xt_fcheck_call { | |
189 | const char *ext_name; | |
190 | void *data, *udata; | |
191 | unsigned int xflags; | |
192 | }; | |
193 | ||
194 | /** | |
195 | * A "linear"/linked-list based name<->id map, for files similar to | |
196 | * /etc/iproute2/. | |
197 | */ | |
198 | struct xtables_lmap { | |
199 | char *name; | |
200 | int id; | |
201 | struct xtables_lmap *next; | |
202 | }; | |
203 | ||
204 | enum xtables_ext_flags { | |
205 | XTABLES_EXT_ALIAS = 1 << 0, | |
206 | }; | |
207 | ||
208 | /* Include file for additions: new matches and targets. */ | |
209 | struct xtables_match | |
210 | { | |
211 | /* | |
212 | * ABI/API version this module requires. Must be first member, | |
213 | * as the rest of this struct may be subject to ABI changes. | |
214 | */ | |
215 | const char *version; | |
216 | ||
217 | struct xtables_match *next; | |
218 | ||
219 | const char *name; | |
220 | const char *real_name; | |
221 | ||
222 | /* Revision of match (0 by default). */ | |
223 | uint8_t revision; | |
224 | ||
225 | /* Extension flags */ | |
226 | uint8_t ext_flags; | |
227 | ||
228 | uint16_t family; | |
229 | ||
230 | /* Size of match data. */ | |
231 | size_t size; | |
232 | ||
233 | /* Size of match data relevant for userspace comparison purposes */ | |
234 | size_t userspacesize; | |
235 | ||
236 | /* Function which prints out usage message. */ | |
237 | void (*help)(void); | |
238 | ||
239 | /* Initialize the match. */ | |
240 | void (*init)(struct xt_entry_match *m); | |
241 | ||
242 | /* Function which parses command options; returns true if it | |
243 | ate an option */ | |
244 | /* entry is struct ipt_entry for example */ | |
245 | int (*parse)(int c, char **argv, int invert, unsigned int *flags, | |
246 | const void *entry, | |
247 | struct xt_entry_match **match); | |
248 | ||
249 | /* Final check; exit if not ok. */ | |
250 | void (*final_check)(unsigned int flags); | |
251 | ||
252 | /* Prints out the match iff non-NULL: put space at end */ | |
253 | /* ip is struct ipt_ip * for example */ | |
254 | void (*print)(const void *ip, | |
255 | const struct xt_entry_match *match, int numeric); | |
256 | ||
257 | /* Saves the match info in parsable form to stdout. */ | |
258 | /* ip is struct ipt_ip * for example */ | |
259 | void (*save)(const void *ip, const struct xt_entry_match *match); | |
260 | ||
261 | /* Print match name or alias */ | |
262 | const char *(*alias)(const struct xt_entry_match *match); | |
263 | ||
264 | /* Pointer to list of extra command-line options */ | |
265 | const struct option *extra_opts; | |
266 | ||
267 | /* New parser */ | |
268 | void (*x6_parse)(struct xt_option_call *); | |
269 | void (*x6_fcheck)(struct xt_fcheck_call *); | |
270 | const struct xt_option_entry *x6_options; | |
271 | ||
272 | /* Size of per-extension instance extra "global" scratch space */ | |
273 | size_t udata_size; | |
274 | ||
275 | /* Ignore these men behind the curtain: */ | |
276 | void *udata; | |
277 | unsigned int option_offset; | |
278 | struct xt_entry_match *m; | |
279 | unsigned int mflags; | |
280 | unsigned int loaded; /* simulate loading so options are merged properly */ | |
281 | }; | |
282 | ||
283 | struct xtables_target | |
284 | { | |
285 | /* | |
286 | * ABI/API version this module requires. Must be first member, | |
287 | * as the rest of this struct may be subject to ABI changes. | |
288 | */ | |
289 | const char *version; | |
290 | ||
291 | struct xtables_target *next; | |
292 | ||
293 | ||
294 | const char *name; | |
295 | ||
296 | /* Real target behind this, if any. */ | |
297 | const char *real_name; | |
298 | ||
299 | /* Revision of target (0 by default). */ | |
300 | uint8_t revision; | |
301 | ||
302 | /* Extension flags */ | |
303 | uint8_t ext_flags; | |
304 | ||
305 | uint16_t family; | |
306 | ||
307 | ||
308 | /* Size of target data. */ | |
309 | size_t size; | |
310 | ||
311 | /* Size of target data relevant for userspace comparison purposes */ | |
312 | size_t userspacesize; | |
313 | ||
314 | /* Function which prints out usage message. */ | |
315 | void (*help)(void); | |
316 | ||
317 | /* Initialize the target. */ | |
318 | void (*init)(struct xt_entry_target *t); | |
319 | ||
320 | /* Function which parses command options; returns true if it | |
321 | ate an option */ | |
322 | /* entry is struct ipt_entry for example */ | |
323 | int (*parse)(int c, char **argv, int invert, unsigned int *flags, | |
324 | const void *entry, | |
325 | struct xt_entry_target **targetinfo); | |
326 | ||
327 | /* Final check; exit if not ok. */ | |
328 | void (*final_check)(unsigned int flags); | |
329 | ||
330 | /* Prints out the target iff non-NULL: put space at end */ | |
331 | void (*print)(const void *ip, | |
332 | const struct xt_entry_target *target, int numeric); | |
333 | ||
334 | /* Saves the targinfo in parsable form to stdout. */ | |
335 | void (*save)(const void *ip, | |
336 | const struct xt_entry_target *target); | |
337 | ||
338 | /* Print target name or alias */ | |
339 | const char *(*alias)(const struct xt_entry_target *target); | |
340 | ||
341 | /* Pointer to list of extra command-line options */ | |
342 | const struct option *extra_opts; | |
343 | ||
344 | /* New parser */ | |
345 | void (*x6_parse)(struct xt_option_call *); | |
346 | void (*x6_fcheck)(struct xt_fcheck_call *); | |
347 | const struct xt_option_entry *x6_options; | |
348 | ||
349 | size_t udata_size; | |
350 | ||
351 | /* Ignore these men behind the curtain: */ | |
352 | void *udata; | |
353 | unsigned int option_offset; | |
354 | struct xt_entry_target *t; | |
355 | unsigned int tflags; | |
356 | unsigned int used; | |
357 | unsigned int loaded; /* simulate loading so options are merged properly */ | |
358 | }; | |
359 | ||
360 | struct xtables_rule_match { | |
361 | struct xtables_rule_match *next; | |
362 | struct xtables_match *match; | |
363 | /* Multiple matches of the same type: the ones before | |
364 | the current one are completed from parsing point of view */ | |
365 | bool completed; | |
366 | }; | |
367 | ||
368 | /** | |
369 | * struct xtables_pprot - | |
370 | * | |
371 | * A few hardcoded protocols for 'all' and in case the user has no | |
372 | * /etc/protocols. | |
373 | */ | |
374 | struct xtables_pprot { | |
375 | const char *name; | |
376 | uint8_t num; | |
377 | }; | |
378 | ||
379 | enum xtables_tryload { | |
380 | XTF_DONT_LOAD, | |
381 | XTF_DURING_LOAD, | |
382 | XTF_TRY_LOAD, | |
383 | XTF_LOAD_MUST_SUCCEED, | |
384 | }; | |
385 | ||
386 | enum xtables_exittype { | |
387 | OTHER_PROBLEM = 1, | |
388 | PARAMETER_PROBLEM, | |
389 | VERSION_PROBLEM, | |
390 | RESOURCE_PROBLEM, | |
391 | XTF_ONLY_ONCE, | |
392 | XTF_NO_INVERT, | |
393 | XTF_BAD_VALUE, | |
394 | XTF_ONE_ACTION, | |
395 | }; | |
396 | ||
397 | struct xtables_globals | |
398 | { | |
399 | unsigned int option_offset; | |
400 | const char *program_name, *program_version; | |
401 | struct option *orig_opts; | |
402 | struct option *opts; | |
403 | void (*exit_err)(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3))); | |
404 | int (*compat_rev)(const char *name, uint8_t rev, int opt); | |
405 | }; | |
406 | ||
407 | #define XT_GETOPT_TABLEEND {.name = NULL, .has_arg = false} | |
408 | ||
409 | #ifdef __cplusplus | |
410 | extern "C" { | |
411 | #endif | |
412 | ||
413 | extern const char *xtables_modprobe_program; | |
414 | extern struct xtables_match *xtables_matches; | |
415 | extern struct xtables_target *xtables_targets; | |
416 | ||
417 | extern void xtables_init(void); | |
418 | extern void xtables_set_nfproto(uint8_t); | |
419 | extern void *xtables_calloc(size_t, size_t); | |
420 | extern void *xtables_malloc(size_t); | |
421 | extern void *xtables_realloc(void *, size_t); | |
422 | ||
423 | extern int xtables_insmod(const char *, const char *, bool); | |
424 | extern int xtables_load_ko(const char *, bool); | |
425 | extern int xtables_set_params(struct xtables_globals *xtp); | |
426 | extern void xtables_free_opts(int reset_offset); | |
427 | extern struct option *xtables_merge_options(struct option *origopts, | |
428 | struct option *oldopts, const struct option *newopts, | |
429 | unsigned int *option_offset); | |
430 | ||
431 | extern int xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto); | |
432 | extern struct xtables_match *xtables_find_match(const char *name, | |
433 | enum xtables_tryload, struct xtables_rule_match **match); | |
434 | extern struct xtables_target *xtables_find_target(const char *name, | |
435 | enum xtables_tryload); | |
436 | extern int xtables_compatible_revision(const char *name, uint8_t revision, | |
437 | int opt); | |
438 | ||
439 | extern void xtables_rule_matches_free(struct xtables_rule_match **matches); | |
440 | ||
441 | /* Your shared library should call one of these. */ | |
442 | extern void xtables_register_match(struct xtables_match *me); | |
443 | extern void xtables_register_matches(struct xtables_match *, unsigned int); | |
444 | extern void xtables_register_target(struct xtables_target *me); | |
445 | extern void xtables_register_targets(struct xtables_target *, unsigned int); | |
446 | ||
447 | extern bool xtables_strtoul(const char *, char **, uintmax_t *, | |
448 | uintmax_t, uintmax_t); | |
449 | extern bool xtables_strtoui(const char *, char **, unsigned int *, | |
450 | unsigned int, unsigned int); | |
451 | extern int xtables_service_to_port(const char *name, const char *proto); | |
452 | extern uint16_t xtables_parse_port(const char *port, const char *proto); | |
453 | extern void | |
454 | xtables_parse_interface(const char *arg, char *vianame, unsigned char *mask); | |
455 | ||
456 | /* this is a special 64bit data type that is 8-byte aligned */ | |
457 | #define aligned_u64 uint64_t __attribute__((aligned(8))) | |
458 | ||
459 | extern struct xtables_globals *xt_params; | |
460 | #define xtables_error (xt_params->exit_err) | |
461 | ||
462 | extern void xtables_param_act(unsigned int, const char *, ...); | |
463 | ||
464 | extern const char *xtables_ipaddr_to_numeric(const struct in_addr *); | |
465 | extern const char *xtables_ipaddr_to_anyname(const struct in_addr *); | |
466 | extern const char *xtables_ipmask_to_numeric(const struct in_addr *); | |
467 | extern struct in_addr *xtables_numeric_to_ipaddr(const char *); | |
468 | extern struct in_addr *xtables_numeric_to_ipmask(const char *); | |
469 | extern int xtables_ipmask_to_cidr(const struct in_addr *); | |
470 | extern void xtables_ipparse_any(const char *, struct in_addr **, | |
471 | struct in_addr *, unsigned int *); | |
472 | extern void xtables_ipparse_multiple(const char *, struct in_addr **, | |
473 | struct in_addr **, unsigned int *); | |
474 | ||
475 | extern struct in6_addr *xtables_numeric_to_ip6addr(const char *); | |
476 | extern const char *xtables_ip6addr_to_numeric(const struct in6_addr *); | |
477 | extern const char *xtables_ip6addr_to_anyname(const struct in6_addr *); | |
478 | extern const char *xtables_ip6mask_to_numeric(const struct in6_addr *); | |
479 | extern int xtables_ip6mask_to_cidr(const struct in6_addr *); | |
480 | extern void xtables_ip6parse_any(const char *, struct in6_addr **, | |
481 | struct in6_addr *, unsigned int *); | |
482 | extern void xtables_ip6parse_multiple(const char *, struct in6_addr **, | |
483 | struct in6_addr **, unsigned int *); | |
484 | ||
485 | /** | |
486 | * Print the specified value to standard output, quoting dangerous | |
487 | * characters if required. | |
488 | */ | |
489 | extern void xtables_save_string(const char *value); | |
490 | ||
491 | #define FMT_NUMERIC 0x0001 | |
492 | #define FMT_NOCOUNTS 0x0002 | |
493 | #define FMT_KILOMEGAGIGA 0x0004 | |
494 | #define FMT_OPTIONS 0x0008 | |
495 | #define FMT_NOTABLE 0x0010 | |
496 | #define FMT_NOTARGET 0x0020 | |
497 | #define FMT_VIA 0x0040 | |
498 | #define FMT_NONEWLINE 0x0080 | |
499 | #define FMT_LINENUMBERS 0x0100 | |
500 | ||
501 | #define FMT_PRINT_RULE (FMT_NOCOUNTS | FMT_OPTIONS | FMT_VIA \ | |
502 | | FMT_NUMERIC | FMT_NOTABLE) | |
503 | #define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab)) | |
504 | ||
505 | extern void xtables_print_num(uint64_t number, unsigned int format); | |
506 | ||
507 | #if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS) | |
508 | # ifdef _INIT | |
509 | # undef _init | |
510 | # define _init _INIT | |
511 | # endif | |
512 | extern void init_extensions(void); | |
513 | extern void init_extensions4(void); | |
514 | extern void init_extensions6(void); | |
515 | #else | |
516 | # define _init __attribute__((constructor)) _INIT | |
517 | #endif | |
518 | ||
519 | extern const struct xtables_pprot xtables_chain_protos[]; | |
520 | extern uint16_t xtables_parse_protocol(const char *s); | |
521 | ||
522 | /* kernel revision handling */ | |
523 | extern int kernel_version; | |
524 | extern void get_kernel_version(void); | |
525 | #define LINUX_VERSION(x,y,z) (0x10000*(x) + 0x100*(y) + z) | |
526 | #define LINUX_VERSION_MAJOR(x) (((x)>>16) & 0xFF) | |
527 | #define LINUX_VERSION_MINOR(x) (((x)>> 8) & 0xFF) | |
528 | #define LINUX_VERSION_PATCH(x) ( (x) & 0xFF) | |
529 | ||
530 | /* xtoptions.c */ | |
531 | extern void xtables_option_metavalidate(const char *, | |
532 | const struct xt_option_entry *); | |
533 | extern struct option *xtables_options_xfrm(struct option *, struct option *, | |
534 | const struct xt_option_entry *, | |
535 | unsigned int *); | |
536 | extern void xtables_option_parse(struct xt_option_call *); | |
537 | extern void xtables_option_tpcall(unsigned int, char **, bool, | |
538 | struct xtables_target *, void *); | |
539 | extern void xtables_option_mpcall(unsigned int, char **, bool, | |
540 | struct xtables_match *, void *); | |
541 | extern void xtables_option_tfcall(struct xtables_target *); | |
542 | extern void xtables_option_mfcall(struct xtables_match *); | |
543 | extern void xtables_options_fcheck(const char *, unsigned int, | |
544 | const struct xt_option_entry *); | |
545 | ||
546 | extern struct xtables_lmap *xtables_lmap_init(const char *); | |
547 | extern void xtables_lmap_free(struct xtables_lmap *); | |
548 | extern int xtables_lmap_name2id(const struct xtables_lmap *, const char *); | |
549 | extern const char *xtables_lmap_id2name(const struct xtables_lmap *, int); | |
550 | ||
551 | #ifdef XTABLES_INTERNAL | |
552 | ||
553 | /* Shipped modules rely on this... */ | |
554 | ||
555 | # ifndef ARRAY_SIZE | |
556 | # define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) | |
557 | # endif | |
558 | ||
559 | extern void _init(void); | |
560 | ||
561 | #endif | |
562 | ||
563 | #ifdef __cplusplus | |
564 | } /* extern "C" */ | |
565 | #endif | |
566 | ||
567 | #endif /* _XTABLES_H */ |