Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 1 | /* |
| 2 | * $Id: ebtables.c,v 1.03 2002/01/19 |
| 3 | * |
| 4 | * Copyright (C) 2001-2002 Bart De Schuymer |
| 5 | * |
| 6 | * This code is stongly inspired on the iptables code which is |
| 7 | * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling |
| 8 | * |
| 9 | * This program is free software; you can redistribute it and/or |
| 10 | * modify it under the terms of the GNU General Public License as |
| 11 | * published by the Free Software Foundation; either version 2 of the |
| 12 | * License, or (at your option) any later version. |
| 13 | * |
| 14 | * This program is distributed in the hope that it will be useful, but |
| 15 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 17 | * General Public License for more details. |
| 18 | * |
| 19 | * You should have received a copy of the GNU General Public License |
| 20 | * along with this program; if not, write to the Free Software |
| 21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 22 | */ |
| 23 | |
| 24 | #ifndef EBTABLES_U_H |
| 25 | #define EBTABLES_U_H |
Bart De Schuymer | 9cfd654 | 2002-08-13 16:08:08 +0000 | [diff] [blame] | 26 | #include <netinet/in.h> |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 27 | #include <linux/netfilter_bridge/ebtables.h> |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 28 | |
Bart De Schuymer | f81c270 | 2003-07-23 21:07:04 +0000 | [diff] [blame] | 29 | #ifndef EBT_MIN_ALIGN |
| 30 | #define EBT_MIN_ALIGN (__alignof__(struct ebt_entry_target)) |
| 31 | #endif |
| 32 | #define EBT_ALIGN(s) (((s) + (EBT_MIN_ALIGN-1)) & ~(EBT_MIN_ALIGN-1)) |
| 33 | |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 34 | struct ebt_u_entries |
| 35 | { |
Bart De Schuymer | 0976590 | 2002-06-23 08:15:51 +0000 | [diff] [blame] | 36 | int policy; |
Bart De Schuymer | 376ccfb | 2002-07-23 20:52:18 +0000 | [diff] [blame] | 37 | unsigned int nentries; |
Bart De Schuymer | 9895a8e | 2003-01-11 10:14:24 +0000 | [diff] [blame] | 38 | /* counter offset for this chain */ |
Bart De Schuymer | 0976590 | 2002-06-23 08:15:51 +0000 | [diff] [blame] | 39 | unsigned int counter_offset; |
Bart De Schuymer | 9895a8e | 2003-01-11 10:14:24 +0000 | [diff] [blame] | 40 | /* used for udc */ |
Bart De Schuymer | 0976590 | 2002-06-23 08:15:51 +0000 | [diff] [blame] | 41 | unsigned int hook_mask; |
| 42 | char name[EBT_CHAIN_MAXNAMELEN]; |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 43 | struct ebt_u_entry *entries; |
| 44 | }; |
| 45 | |
Bart De Schuymer | 0976590 | 2002-06-23 08:15:51 +0000 | [diff] [blame] | 46 | struct ebt_u_chain_list |
| 47 | { |
| 48 | struct ebt_u_entries *udc; |
| 49 | struct ebt_u_chain_list *next; |
Bart De Schuymer | 9895a8e | 2003-01-11 10:14:24 +0000 | [diff] [blame] | 50 | /* this is only used internally, in communication.c */ |
Bart De Schuymer | 0976590 | 2002-06-23 08:15:51 +0000 | [diff] [blame] | 51 | char *kernel_start; |
| 52 | }; |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 53 | |
| 54 | struct ebt_u_replace |
| 55 | { |
| 56 | char name[EBT_TABLE_MAXNAMELEN]; |
| 57 | unsigned int valid_hooks; |
Bart De Schuymer | 9895a8e | 2003-01-11 10:14:24 +0000 | [diff] [blame] | 58 | /* nr of rules in the table */ |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 59 | unsigned int nentries; |
| 60 | struct ebt_u_entries *hook_entry[NF_BR_NUMHOOKS]; |
Bart De Schuymer | 9895a8e | 2003-01-11 10:14:24 +0000 | [diff] [blame] | 61 | /* user defined chains (udc) list */ |
Bart De Schuymer | 0976590 | 2002-06-23 08:15:51 +0000 | [diff] [blame] | 62 | struct ebt_u_chain_list *udc; |
Bart De Schuymer | 9895a8e | 2003-01-11 10:14:24 +0000 | [diff] [blame] | 63 | /* nr of counters userspace expects back */ |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 64 | unsigned int num_counters; |
Bart De Schuymer | 9895a8e | 2003-01-11 10:14:24 +0000 | [diff] [blame] | 65 | /* where the kernel will put the old counters */ |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 66 | struct ebt_counter *counters; |
Bart De Schuymer | 9895a8e | 2003-01-11 10:14:24 +0000 | [diff] [blame] | 67 | /* |
| 68 | * can be used e.g. to know if a standard option |
| 69 | * has been specified twice |
| 70 | */ |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 71 | unsigned int flags; |
Bart De Schuymer | 9895a8e | 2003-01-11 10:14:24 +0000 | [diff] [blame] | 72 | /* we stick the specified command (e.g. -A) in here */ |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 73 | char command; |
Bart De Schuymer | 9895a8e | 2003-01-11 10:14:24 +0000 | [diff] [blame] | 74 | /* |
| 75 | * here we stick the hook to do our thing on (can be -1 if unspecified) |
| 76 | */ |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 77 | int selected_hook; |
Bart De Schuymer | 9895a8e | 2003-01-11 10:14:24 +0000 | [diff] [blame] | 78 | /* used for the atomic option */ |
Bart De Schuymer | 8330e89 | 2002-07-14 19:06:47 +0000 | [diff] [blame] | 79 | char *filename; |
Bart De Schuymer | 9895a8e | 2003-01-11 10:14:24 +0000 | [diff] [blame] | 80 | /* tells what happened to the old rules */ |
Bart De Schuymer | ed05343 | 2002-07-21 19:35:39 +0000 | [diff] [blame] | 81 | unsigned short *counterchanges; |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 82 | }; |
| 83 | |
| 84 | struct ebt_u_table |
| 85 | { |
| 86 | char name[EBT_TABLE_MAXNAMELEN]; |
Bart De Schuymer | f57f50f | 2002-08-29 16:52:36 +0000 | [diff] [blame] | 87 | void (*check)(struct ebt_u_replace *repl); |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 88 | void (*help)(char **); |
| 89 | struct ebt_u_table *next; |
| 90 | }; |
| 91 | |
| 92 | struct ebt_u_match_list |
| 93 | { |
| 94 | struct ebt_u_match_list *next; |
| 95 | struct ebt_entry_match *m; |
| 96 | }; |
| 97 | |
| 98 | struct ebt_u_watcher_list |
| 99 | { |
| 100 | struct ebt_u_watcher_list *next; |
| 101 | struct ebt_entry_watcher *w; |
| 102 | }; |
| 103 | |
| 104 | struct ebt_u_entry |
| 105 | { |
Bart De Schuymer | 376ccfb | 2002-07-23 20:52:18 +0000 | [diff] [blame] | 106 | unsigned int bitmask; |
| 107 | unsigned int invflags; |
Bart De Schuymer | 9cfd654 | 2002-08-13 16:08:08 +0000 | [diff] [blame] | 108 | uint16_t ethproto; |
Bart De Schuymer | 376ccfb | 2002-07-23 20:52:18 +0000 | [diff] [blame] | 109 | char in[IFNAMSIZ]; |
| 110 | char logical_in[IFNAMSIZ]; |
| 111 | char out[IFNAMSIZ]; |
| 112 | char logical_out[IFNAMSIZ]; |
Bart De Schuymer | e3cceb7 | 2002-07-26 12:47:33 +0000 | [diff] [blame] | 113 | unsigned char sourcemac[ETH_ALEN]; |
| 114 | unsigned char sourcemsk[ETH_ALEN]; |
| 115 | unsigned char destmac[ETH_ALEN]; |
| 116 | unsigned char destmsk[ETH_ALEN]; |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 117 | struct ebt_u_match_list *m_list; |
| 118 | struct ebt_u_watcher_list *w_list; |
| 119 | struct ebt_entry_target *t; |
| 120 | struct ebt_u_entry *next; |
| 121 | }; |
| 122 | |
| 123 | struct ebt_u_match |
| 124 | { |
| 125 | char name[EBT_FUNCTION_MAXNAMELEN]; |
Bart De Schuymer | 9895a8e | 2003-01-11 10:14:24 +0000 | [diff] [blame] | 126 | /* size of the real match data */ |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 127 | unsigned int size; |
| 128 | void (*help)(void); |
| 129 | void (*init)(struct ebt_entry_match *m); |
| 130 | int (*parse)(int c, char **argv, int argc, |
| 131 | const struct ebt_u_entry *entry, unsigned int *flags, |
| 132 | struct ebt_entry_match **match); |
| 133 | void (*final_check)(const struct ebt_u_entry *entry, |
| 134 | const struct ebt_entry_match *match, |
Bart De Schuymer | 76712df | 2002-08-25 21:54:06 +0000 | [diff] [blame] | 135 | const char *name, unsigned int hookmask, unsigned int time); |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 136 | void (*print)(const struct ebt_u_entry *entry, |
| 137 | const struct ebt_entry_match *match); |
| 138 | int (*compare)(const struct ebt_entry_match *m1, |
| 139 | const struct ebt_entry_match *m2); |
| 140 | const struct option *extra_ops; |
Bart De Schuymer | 9895a8e | 2003-01-11 10:14:24 +0000 | [diff] [blame] | 141 | /* |
| 142 | * can be used e.g. to check for multiple occurance of the same option |
| 143 | */ |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 144 | unsigned int flags; |
| 145 | unsigned int option_offset; |
| 146 | struct ebt_entry_match *m; |
Bart De Schuymer | 9895a8e | 2003-01-11 10:14:24 +0000 | [diff] [blame] | 147 | /* |
| 148 | * if used == 1 we no longer have to add it to |
| 149 | * the match chain of the new entry |
| 150 | */ |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 151 | unsigned int used; |
| 152 | struct ebt_u_match *next; |
| 153 | }; |
| 154 | |
| 155 | struct ebt_u_watcher |
| 156 | { |
| 157 | char name[EBT_FUNCTION_MAXNAMELEN]; |
| 158 | unsigned int size; |
| 159 | void (*help)(void); |
| 160 | void (*init)(struct ebt_entry_watcher *w); |
| 161 | int (*parse)(int c, char **argv, int argc, |
| 162 | const struct ebt_u_entry *entry, unsigned int *flags, |
| 163 | struct ebt_entry_watcher **watcher); |
| 164 | void (*final_check)(const struct ebt_u_entry *entry, |
| 165 | const struct ebt_entry_watcher *watch, const char *name, |
Bart De Schuymer | 76712df | 2002-08-25 21:54:06 +0000 | [diff] [blame] | 166 | unsigned int hookmask, unsigned int time); |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 167 | void (*print)(const struct ebt_u_entry *entry, |
| 168 | const struct ebt_entry_watcher *watcher); |
| 169 | int (*compare)(const struct ebt_entry_watcher *w1, |
| 170 | const struct ebt_entry_watcher *w2); |
| 171 | const struct option *extra_ops; |
| 172 | unsigned int flags; |
| 173 | unsigned int option_offset; |
| 174 | struct ebt_entry_watcher *w; |
| 175 | unsigned int used; |
| 176 | struct ebt_u_watcher *next; |
| 177 | }; |
| 178 | |
| 179 | struct ebt_u_target |
| 180 | { |
| 181 | char name[EBT_FUNCTION_MAXNAMELEN]; |
| 182 | unsigned int size; |
| 183 | void (*help)(void); |
| 184 | void (*init)(struct ebt_entry_target *t); |
| 185 | int (*parse)(int c, char **argv, int argc, |
| 186 | const struct ebt_u_entry *entry, unsigned int *flags, |
| 187 | struct ebt_entry_target **target); |
| 188 | void (*final_check)(const struct ebt_u_entry *entry, |
| 189 | const struct ebt_entry_target *target, const char *name, |
Bart De Schuymer | 76712df | 2002-08-25 21:54:06 +0000 | [diff] [blame] | 190 | unsigned int hookmask, unsigned int time); |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 191 | void (*print)(const struct ebt_u_entry *entry, |
| 192 | const struct ebt_entry_target *target); |
| 193 | int (*compare)(const struct ebt_entry_target *t1, |
| 194 | const struct ebt_entry_target *t2); |
| 195 | const struct option *extra_ops; |
| 196 | unsigned int option_offset; |
| 197 | unsigned int flags; |
| 198 | struct ebt_entry_target *t; |
| 199 | unsigned int used; |
| 200 | struct ebt_u_target *next; |
| 201 | }; |
| 202 | |
| 203 | void register_table(struct ebt_u_table *); |
| 204 | void register_match(struct ebt_u_match *); |
| 205 | void register_watcher(struct ebt_u_watcher *); |
| 206 | void register_target(struct ebt_u_target *t); |
Bart De Schuymer | 9ce6ee9 | 2002-06-14 21:56:35 +0000 | [diff] [blame] | 207 | int get_table(struct ebt_u_replace *repl); |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 208 | struct ebt_u_target *find_target(const char *name); |
| 209 | struct ebt_u_match *find_match(const char *name); |
| 210 | struct ebt_u_watcher *find_watcher(const char *name); |
Bart De Schuymer | 8330e89 | 2002-07-14 19:06:47 +0000 | [diff] [blame] | 211 | struct ebt_u_table *find_table(char *name); |
Bart De Schuymer | ed05343 | 2002-07-21 19:35:39 +0000 | [diff] [blame] | 212 | void deliver_counters(struct ebt_u_replace *repl); |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 213 | void deliver_table(struct ebt_u_replace *repl); |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 214 | void check_option(unsigned int *flags, unsigned int mask); |
| 215 | int check_inverse(const char option[]); |
Bart De Schuymer | 22d03a2 | 2003-05-03 20:28:22 +0000 | [diff] [blame] | 216 | void print_mac(const char *mac); |
| 217 | void print_mac_and_mask(const char *mac, const char *mask); |
Bart De Schuymer | 0cb0179 | 2003-05-04 16:52:04 +0000 | [diff] [blame] | 218 | int ebtables_insmod(const char *modname); |
Bart De Schuymer | d458648 | 2002-08-11 16:15:55 +0000 | [diff] [blame] | 219 | void __print_bug(char *file, int line, char *format, ...); |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 220 | #define print_bug(format, args...) \ |
Bart De Schuymer | d458648 | 2002-08-11 16:15:55 +0000 | [diff] [blame] | 221 | __print_bug(__FILE__, __LINE__, format, ##args) |
Bart De Schuymer | e709187 | 2003-04-16 21:18:02 +0000 | [diff] [blame] | 222 | #define print_error(format,args...) {printf(format,##args);\ |
| 223 | printf(".\n");exit(-1);} |
Bart De Schuymer | 1f7f002 | 2003-01-19 10:36:29 +0000 | [diff] [blame] | 224 | #define print_memory() {printf("Ebtables: " __FILE__ \ |
| 225 | " %s %d :Out of memory.\n", __FUNCTION__, __LINE__); exit(-1);} |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 226 | |
Bart De Schuymer | 9895a8e | 2003-01-11 10:14:24 +0000 | [diff] [blame] | 227 | /* used for keeping the rule counters right during rule adds or deletes */ |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 228 | #define CNT_NORM 0 |
| 229 | #define CNT_DEL 1 |
| 230 | #define CNT_ADD 2 |
| 231 | #define CNT_END 3 |
| 232 | #define CNT_ZERO 4 |
| 233 | |
Bart De Schuymer | 9cfd654 | 2002-08-13 16:08:08 +0000 | [diff] [blame] | 234 | extern char *standard_targets[NUM_STANDARD_TARGETS]; |
Bart De Schuymer | 9895a8e | 2003-01-11 10:14:24 +0000 | [diff] [blame] | 235 | /* |
| 236 | * Transforms a target string into the right integer, |
| 237 | * returns 0 on success. |
| 238 | */ |
Bart De Schuymer | 9cfd654 | 2002-08-13 16:08:08 +0000 | [diff] [blame] | 239 | #define FILL_TARGET(_str, _pos) ({ \ |
| 240 | int _i, _ret = 0; \ |
| 241 | for (_i = 0; _i < NUM_STANDARD_TARGETS; _i++) \ |
| 242 | if (!strcmp(_str, standard_targets[_i])) {\ |
| 243 | _pos = -_i - 1; \ |
| 244 | break; \ |
| 245 | } \ |
| 246 | if (_i == NUM_STANDARD_TARGETS) \ |
| 247 | _ret = 1; \ |
| 248 | _ret; \ |
| 249 | }) |
| 250 | |
Bart De Schuymer | 9895a8e | 2003-01-11 10:14:24 +0000 | [diff] [blame] | 251 | /* Transforms the target value to an index into standard_targets[] */ |
Bart De Schuymer | 9cfd654 | 2002-08-13 16:08:08 +0000 | [diff] [blame] | 252 | #define TARGET_INDEX(_value) (-_value - 1) |
Bart De Schuymer | 9895a8e | 2003-01-11 10:14:24 +0000 | [diff] [blame] | 253 | /* Returns a target string corresponding to the value */ |
Bart De Schuymer | 9cfd654 | 2002-08-13 16:08:08 +0000 | [diff] [blame] | 254 | #define TARGET_NAME(_value) (standard_targets[TARGET_INDEX(_value)]) |
Bart De Schuymer | 9895a8e | 2003-01-11 10:14:24 +0000 | [diff] [blame] | 255 | /* True if the hook mask denotes that the rule is in a base chain */ |
Bart De Schuymer | 76712df | 2002-08-25 21:54:06 +0000 | [diff] [blame] | 256 | #define BASE_CHAIN (hookmask & (1 << NF_BR_NUMHOOKS)) |
Bart De Schuymer | 9895a8e | 2003-01-11 10:14:24 +0000 | [diff] [blame] | 257 | /* Clear the bit in the hook_mask that tells if the rule is on a base chain */ |
Bart De Schuymer | 76712df | 2002-08-25 21:54:06 +0000 | [diff] [blame] | 258 | #define CLEAR_BASE_CHAIN_BIT (hookmask &= ~(1 << NF_BR_NUMHOOKS)) |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 259 | #endif /* EBTABLES_U_H */ |