blob: 9a30f3ae329f0968a2a2f18bddba4127e0d25b1f [file] [log] [blame]
Bart De Schuymerff587202005-02-08 20:02:28 +00001/* ebt_among
2 *
3 * Authors:
4 * Grzegorz Borowiak <grzes@gnu.univ.gda.pl>
5 *
6 * August, 2003
7 */
8
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +00009#include <stdio.h>
10#include <string.h>
11#include <stdlib.h>
12#include <getopt.h>
13#include <ctype.h>
Bart De Schuymere1c315a2006-12-22 18:08:41 +000014#include <unistd.h>
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +000015#include <netinet/ether.h>
16#include "../include/ebtables_u.h"
17#include "../include/ethernetdb.h"
18#include <linux/if_ether.h>
19#include <linux/netfilter_bridge/ebt_among.h>
Bart De Schuymer8069b5a2006-08-17 10:18:02 +000020#include <sys/mman.h>
21#include <sys/stat.h>
22#include <fcntl.h>
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +000023
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +000024#define AMONG_DST '1'
25#define AMONG_SRC '2'
Bart De Schuymer8069b5a2006-08-17 10:18:02 +000026#define AMONG_DST_F '3'
27#define AMONG_SRC_F '4'
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +000028
gborowiak6c6d7312003-09-16 19:26:38 +000029static struct option opts[] = {
30 {"among-dst", required_argument, 0, AMONG_DST},
31 {"among-src", required_argument, 0, AMONG_SRC},
Bart De Schuymer8069b5a2006-08-17 10:18:02 +000032 {"among-dst-file", required_argument, 0, AMONG_DST_F},
33 {"among-src-file", required_argument, 0, AMONG_SRC_F},
gborowiak6c6d7312003-09-16 19:26:38 +000034 {0}
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +000035};
36
37#ifdef DEBUG
38static void hexdump(const void *mem, int howmany)
39{
40 printf("\n");
41 const unsigned char *p = mem;
42 int i;
Bart De Schuymerf8c97432003-09-27 17:39:09 +000043
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +000044 for (i = 0; i < howmany; i++) {
45 if (i % 32 == 0) {
46 printf("\n%04x: ", i);
47 }
gborowiak6c6d7312003-09-16 19:26:38 +000048 printf("%2.2x%c", p[i], ". "[i % 4 == 3]);
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +000049 }
50 printf("\n");
51}
gborowiak6c6d7312003-09-16 19:26:38 +000052#endif /* DEBUG */
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +000053
54static void print_help()
55{
56 printf(
57"`among' options:\n"
Bart De Schuymer8069b5a2006-08-17 10:18:02 +000058"--among-dst [!] list : matches if ether dst is in list\n"
59"--among-src [!] list : matches if ether src is in list\n"
60"--among-dst-file [!] file : obtain dst list from file\n"
61"--among-src-file [!] file : obtain src list from file\n"
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +000062"list has form:\n"
gborowiak6c6d7312003-09-16 19:26:38 +000063" xx:xx:xx:xx:xx:xx[=ip.ip.ip.ip],yy:yy:yy:yy:yy:yy[=ip.ip.ip.ip]"
64",...,zz:zz:zz:zz:zz:zz[=ip.ip.ip.ip][,]\n"
gborowiakc50ce6a2003-09-07 13:16:26 +000065"Things in brackets are optional.\n"
Bart De Schuymerf8c97432003-09-27 17:39:09 +000066"If you want to allow two (or more) IP addresses to one MAC address, you\n"
Bart De Schuymer7cc696b2003-10-12 12:34:10 +000067"can specify two (or more) pairs with the same MAC, e.g.\n"
gborowiakc50ce6a2003-09-07 13:16:26 +000068" 00:00:00:fa:eb:fe=153.19.120.250,00:00:00:fa:eb:fe=192.168.0.1\n"
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +000069 );
70}
Bart De Schuymer1da19992008-03-04 19:14:29 +000071static int old_size;
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +000072
73static void init(struct ebt_entry_match *match)
74{
gborowiak6c6d7312003-09-16 19:26:38 +000075 struct ebt_among_info *amonginfo =
76 (struct ebt_among_info *) match->data;
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +000077
78 memset(amonginfo, 0, sizeof(struct ebt_among_info));
Bart De Schuymer1da19992008-03-04 19:14:29 +000079 old_size = sizeof(struct ebt_among_info);
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +000080}
81
gborowiakc50ce6a2003-09-07 13:16:26 +000082static struct ebt_mac_wormhash *new_wormhash(int n)
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +000083{
gborowiak6c6d7312003-09-16 19:26:38 +000084 int size =
85 sizeof(struct ebt_mac_wormhash) +
86 n * sizeof(struct ebt_mac_wormhash_tuple);
87 struct ebt_mac_wormhash *result =
88 (struct ebt_mac_wormhash *) malloc(size);
Bart De Schuymerf8c97432003-09-27 17:39:09 +000089
Bart De Schuymerff587202005-02-08 20:02:28 +000090 if (!result)
91 ebt_print_memory();
gborowiakc50ce6a2003-09-07 13:16:26 +000092 memset(result, 0, size);
93 result->poolsize = n;
94 return result;
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +000095}
96
gborowiak6c6d7312003-09-16 19:26:38 +000097static void copy_wormhash(struct ebt_mac_wormhash *d,
98 const struct ebt_mac_wormhash *s)
gborowiakc50ce6a2003-09-07 13:16:26 +000099{
100 int dpoolsize = d->poolsize;
101 int dsize, ssize, amount;
Bart De Schuymerf8c97432003-09-27 17:39:09 +0000102
gborowiakc50ce6a2003-09-07 13:16:26 +0000103 dsize = ebt_mac_wormhash_size(d);
104 ssize = ebt_mac_wormhash_size(s);
105 amount = dsize < ssize ? dsize : ssize;
106 memcpy(d, s, amount);
107 d->poolsize = dpoolsize;
108}
109
110/* Returns:
111 * -1 when '\0' reached
112 * -2 when `n' bytes read and no delimiter found
113 * 0 when no less than `n' bytes read and delimiter found
114 * if `destbuf' is not NULL, it is filled by read bytes and ended with '\0'
115 * *pp is set on the first byte not copied to `destbuf'
116 */
gborowiak6c6d7312003-09-16 19:26:38 +0000117static int read_until(const char **pp, const char *delimiters,
118 char *destbuf, int n)
gborowiakc50ce6a2003-09-07 13:16:26 +0000119{
120 int count = 0;
121 int ret = 0;
122 char c;
Bart De Schuymerf8c97432003-09-27 17:39:09 +0000123
gborowiakc50ce6a2003-09-07 13:16:26 +0000124 while (1) {
125 c = **pp;
126 if (!c) {
127 ret = -1;
128 break;
129 }
130 if (strchr(delimiters, c)) {
131 ret = 0;
132 break;
133 }
134 if (count == n) {
135 ret = -2;
136 break;
137 }
gborowiak6c6d7312003-09-16 19:26:38 +0000138 if (destbuf)
139 destbuf[count++] = c;
gborowiakc50ce6a2003-09-07 13:16:26 +0000140 (*pp)++;
141 }
gborowiak6c6d7312003-09-16 19:26:38 +0000142 if (destbuf)
143 destbuf[count] = 0;
gborowiakc50ce6a2003-09-07 13:16:26 +0000144 return ret;
145}
146
gborowiak6c6d7312003-09-16 19:26:38 +0000147static int fcmp(const void *va, const void *vb) {
148 const struct ebt_mac_wormhash_tuple *a = va;
149 const struct ebt_mac_wormhash_tuple *b = vb;
150 int ca = ((const unsigned char*)a->cmp)[7];
151 int cb = ((const unsigned char*)b->cmp)[7];
Bart De Schuymerf8c97432003-09-27 17:39:09 +0000152
gborowiak6c6d7312003-09-16 19:26:38 +0000153 return ca - cb;
154}
155
156static void index_table(struct ebt_mac_wormhash *wh)
157{
158 int ipool, itable;
159 int c;
Bart De Schuymerf8c97432003-09-27 17:39:09 +0000160
gborowiak6c6d7312003-09-16 19:26:38 +0000161 for (itable = 0; itable <= 256; itable++) {
162 wh->table[itable] = wh->poolsize;
163 }
164 ipool = 0;
165 itable = 0;
166 while (1) {
167 wh->table[itable] = ipool;
168 c = ((const unsigned char*)wh->pool[ipool].cmp)[7];
169 if (itable <= c) {
170 itable++;
171 } else {
172 ipool++;
173 }
174 if (ipool > wh->poolsize)
175 break;
176 }
177}
178
gborowiakc50ce6a2003-09-07 13:16:26 +0000179static struct ebt_mac_wormhash *create_wormhash(const char *arg)
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000180{
181 const char *pc = arg;
182 const char *anchor;
gborowiakc50ce6a2003-09-07 13:16:26 +0000183 char *endptr;
184 struct ebt_mac_wormhash *workcopy, *result, *h;
185 unsigned char mac[6];
186 unsigned char ip[4];
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000187 int nmacs = 0;
gborowiakc50ce6a2003-09-07 13:16:26 +0000188 int i;
189 char token[4];
Bart De Schuymerf8c97432003-09-27 17:39:09 +0000190
gborowiakc50ce6a2003-09-07 13:16:26 +0000191 if (!(workcopy = new_wormhash(1024))) {
Bart De Schuymer64182a32004-01-21 20:39:54 +0000192 ebt_print_memory();
gborowiakc50ce6a2003-09-07 13:16:26 +0000193 }
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000194 while (1) {
gborowiakc50ce6a2003-09-07 13:16:26 +0000195 /* remember current position, we'll need it on error */
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000196 anchor = pc;
gborowiakc50ce6a2003-09-07 13:16:26 +0000197
gborowiak6c6d7312003-09-16 19:26:38 +0000198 /* collect MAC; all its bytes are followed by ':' (colon),
199 * except for the last one which can be followed by
200 * ',' (comma), '=' or '\0' */
gborowiakc50ce6a2003-09-07 13:16:26 +0000201 for (i = 0; i < 5; i++) {
gborowiak6c6d7312003-09-16 19:26:38 +0000202 if (read_until(&pc, ":", token, 2) < 0
203 || token[0] == 0) {
Bart De Schuymerff587202005-02-08 20:02:28 +0000204 ebt_print_error("MAC parse error: %.20s", anchor);
205 return NULL;
gborowiakc50ce6a2003-09-07 13:16:26 +0000206 }
207 mac[i] = strtol(token, &endptr, 16);
208 if (*endptr) {
Bart De Schuymerff587202005-02-08 20:02:28 +0000209 ebt_print_error("MAC parse error: %.20s", anchor);
210 return NULL;
gborowiakc50ce6a2003-09-07 13:16:26 +0000211 }
212 pc++;
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000213 }
gborowiakc50ce6a2003-09-07 13:16:26 +0000214 if (read_until(&pc, "=,", token, 2) == -2 || token[0] == 0) {
Bart De Schuymer64182a32004-01-21 20:39:54 +0000215 ebt_print_error("MAC parse error: %.20s", anchor);
Bart De Schuymerff587202005-02-08 20:02:28 +0000216 return NULL;
gborowiakc50ce6a2003-09-07 13:16:26 +0000217 }
218 mac[i] = strtol(token, &endptr, 16);
219 if (*endptr) {
Bart De Schuymer64182a32004-01-21 20:39:54 +0000220 ebt_print_error("MAC parse error: %.20s", anchor);
Bart De Schuymerff587202005-02-08 20:02:28 +0000221 return NULL;
gborowiakc50ce6a2003-09-07 13:16:26 +0000222 }
223 if (*pc == '=') {
224 /* an IP follows the MAC; collect similarly to MAC */
225 pc++;
226 anchor = pc;
227 for (i = 0; i < 3; i++) {
Bart De Schuymerff587202005-02-08 20:02:28 +0000228 if (read_until(&pc, ".", token, 3) < 0 || token[0] == 0) {
229 ebt_print_error("IP parse error: %.20s", anchor);
230 return NULL;
gborowiakc50ce6a2003-09-07 13:16:26 +0000231 }
232 ip[i] = strtol(token, &endptr, 10);
233 if (*endptr) {
Bart De Schuymerff587202005-02-08 20:02:28 +0000234 ebt_print_error("IP parse error: %.20s", anchor);
235 return NULL;
gborowiakc50ce6a2003-09-07 13:16:26 +0000236 }
237 pc++;
238 }
Bart De Schuymerff587202005-02-08 20:02:28 +0000239 if (read_until(&pc, ",", token, 3) == -2 || token[0] == 0) {
240 ebt_print_error("IP parse error: %.20s", anchor);
241 return NULL;
gborowiakc50ce6a2003-09-07 13:16:26 +0000242 }
243 ip[3] = strtol(token, &endptr, 10);
244 if (*endptr) {
Bart De Schuymerff587202005-02-08 20:02:28 +0000245 ebt_print_error("IP parse error: %.20s", anchor);
246 return NULL;
gborowiakc50ce6a2003-09-07 13:16:26 +0000247 }
gborowiak6c6d7312003-09-16 19:26:38 +0000248 if (*(uint32_t*)ip == 0) {
Bart De Schuymer64182a32004-01-21 20:39:54 +0000249 ebt_print_error("Illegal IP 0.0.0.0");
Bart De Schuymerff587202005-02-08 20:02:28 +0000250 return NULL;
gborowiak6c6d7312003-09-16 19:26:38 +0000251 }
252 } else {
gborowiakc50ce6a2003-09-07 13:16:26 +0000253 /* no IP, we set it to 0.0.0.0 */
254 memset(ip, 0, 4);
255 }
gborowiak6c6d7312003-09-16 19:26:38 +0000256
gborowiakc50ce6a2003-09-07 13:16:26 +0000257 /* we have collected MAC and IP, so we add an entry */
gborowiak6c6d7312003-09-16 19:26:38 +0000258 memcpy(((char *) workcopy->pool[nmacs].cmp) + 2, mac, 6);
259 workcopy->pool[nmacs].ip = *(const uint32_t *) ip;
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000260 nmacs++;
gborowiak6c6d7312003-09-16 19:26:38 +0000261
gborowiakc50ce6a2003-09-07 13:16:26 +0000262 /* re-allocate memory if needed */
263 if (*pc && nmacs >= workcopy->poolsize) {
264 if (!(h = new_wormhash(nmacs * 2))) {
Bart De Schuymer64182a32004-01-21 20:39:54 +0000265 ebt_print_memory();
gborowiakc50ce6a2003-09-07 13:16:26 +0000266 }
267 copy_wormhash(h, workcopy);
268 free(workcopy);
269 workcopy = h;
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000270 }
gborowiak6c6d7312003-09-16 19:26:38 +0000271
gborowiakc50ce6a2003-09-07 13:16:26 +0000272 /* check if end of string was reached */
273 if (!*pc) {
274 break;
275 }
gborowiak6c6d7312003-09-16 19:26:38 +0000276
277 /* now `pc' points to comma if we are here; */
278 /* increment this to the next char */
gborowiakc50ce6a2003-09-07 13:16:26 +0000279 /* but first assert :-> */
280 if (*pc != ',') {
Bart De Schuymer64182a32004-01-21 20:39:54 +0000281 ebt_print_error("Something went wrong; no comma...\n");
Bart De Schuymerff587202005-02-08 20:02:28 +0000282 return NULL;
gborowiakc50ce6a2003-09-07 13:16:26 +0000283 }
284 pc++;
gborowiak6c6d7312003-09-16 19:26:38 +0000285
286 /* again check if end of string was reached; */
287 /* we allow an ending comma */
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000288 if (!*pc) {
289 break;
290 }
291 }
gborowiakc50ce6a2003-09-07 13:16:26 +0000292 if (!(result = new_wormhash(nmacs))) {
Bart De Schuymer64182a32004-01-21 20:39:54 +0000293 ebt_print_memory();
gborowiakc50ce6a2003-09-07 13:16:26 +0000294 }
295 copy_wormhash(result, workcopy);
296 free(workcopy);
gborowiak6c6d7312003-09-16 19:26:38 +0000297 qsort(&result->pool, result->poolsize,
298 sizeof(struct ebt_mac_wormhash_tuple), fcmp);
299 index_table(result);
gborowiakc50ce6a2003-09-07 13:16:26 +0000300 return result;
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000301}
302
303#define OPT_DST 0x01
304#define OPT_SRC 0x02
gborowiak6c6d7312003-09-16 19:26:38 +0000305static int parse(int c, char **argv, int argc,
306 const struct ebt_u_entry *entry, unsigned int *flags,
307 struct ebt_entry_match **match)
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000308{
gborowiak6c6d7312003-09-16 19:26:38 +0000309 struct ebt_among_info *info =
310 (struct ebt_among_info *) (*match)->data;
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000311 struct ebt_mac_wormhash *wh;
gborowiakc50ce6a2003-09-07 13:16:26 +0000312 struct ebt_entry_match *h;
Bart De Schuymer1da19992008-03-04 19:14:29 +0000313 int new_size;
Bart De Schuymer8069b5a2006-08-17 10:18:02 +0000314 long flen;
315 int fd;
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000316
317 switch (c) {
Bart De Schuymer8069b5a2006-08-17 10:18:02 +0000318 case AMONG_DST_F:
319 case AMONG_SRC_F:
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000320 case AMONG_DST:
321 case AMONG_SRC:
Bart De Schuymer8069b5a2006-08-17 10:18:02 +0000322 if (c == AMONG_DST || c == AMONG_DST_F) {
Bart De Schuymerff587202005-02-08 20:02:28 +0000323 ebt_check_option2(flags, OPT_DST);
324 } else {
325 ebt_check_option2(flags, OPT_SRC);
326 }
327 if (ebt_check_inverse2(optarg)) {
Bart De Schuymer8069b5a2006-08-17 10:18:02 +0000328 if (c == AMONG_DST || c == AMONG_DST_F)
gborowiakc50ce6a2003-09-07 13:16:26 +0000329 info->bitmask |= EBT_AMONG_DST_NEG;
330 else
331 info->bitmask |= EBT_AMONG_SRC_NEG;
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000332 }
Bart De Schuymer8069b5a2006-08-17 10:18:02 +0000333 if (c == AMONG_DST_F || c == AMONG_SRC_F) {
334 struct stat stats;
335
336 if ((fd = open(optarg, O_RDONLY)) == -1)
337 ebt_print_error("Couldn't open file '%s'", optarg);
338 fstat(fd, &stats);
339 flen = stats.st_size;
340 /* use mmap because the file will probably be big */
341 optarg = mmap(0, flen, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
342 if (optarg == MAP_FAILED)
343 ebt_print_error("Couldn't map file to memory");
344 if (optarg[flen-1] != '\n')
345 ebt_print_error("File should end with a newline");
346 if (strchr(optarg, '\n') != optarg+flen-1)
347 ebt_print_error("File should only contain one line");
348 optarg[flen-1] = '\0';
349 if (ebt_errormsg[0] != '\0') {
350 munmap(argv, flen);
351 close(fd);
352 exit(-1);
353 }
354 }
Bart De Schuymerff587202005-02-08 20:02:28 +0000355 wh = create_wormhash(optarg);
356 if (ebt_errormsg[0] != '\0')
357 break;
358
Bart De Schuymer1da19992008-03-04 19:14:29 +0000359 new_size = old_size+ebt_mac_wormhash_size(wh);
360 h = malloc(sizeof(struct ebt_entry_match)+EBT_ALIGN(new_size));
Bart De Schuymerff587202005-02-08 20:02:28 +0000361 if (!h)
362 ebt_print_memory();
Bart De Schuymer1da19992008-03-04 19:14:29 +0000363 memcpy(h, *match, old_size+sizeof(struct ebt_entry_match));
364 memcpy((char *)h+old_size+sizeof(struct ebt_entry_match), wh,
365 ebt_mac_wormhash_size(wh));
366 h->match_size = EBT_ALIGN(new_size);
gborowiak6c6d7312003-09-16 19:26:38 +0000367 info = (struct ebt_among_info *) h->data;
gborowiakc50ce6a2003-09-07 13:16:26 +0000368 if (c == AMONG_DST) {
Bart De Schuymer1da19992008-03-04 19:14:29 +0000369 info->wh_dst_ofs = old_size;
gborowiakc50ce6a2003-09-07 13:16:26 +0000370 } else {
Bart De Schuymer1da19992008-03-04 19:14:29 +0000371 info->wh_src_ofs = old_size;
gborowiakc50ce6a2003-09-07 13:16:26 +0000372 }
Bart De Schuymer1da19992008-03-04 19:14:29 +0000373 old_size = new_size;
gborowiakc50ce6a2003-09-07 13:16:26 +0000374 free(*match);
375 *match = h;
376 free(wh);
Bart De Schuymer8069b5a2006-08-17 10:18:02 +0000377 if (c == AMONG_DST_F || c == AMONG_SRC_F) {
378 munmap(argv, flen);
379 close(fd);
380 }
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000381 break;
382 default:
383 return 0;
384 }
385 return 1;
386}
387
388static void final_check(const struct ebt_u_entry *entry,
gborowiak6c6d7312003-09-16 19:26:38 +0000389 const struct ebt_entry_match *match,
390 const char *name, unsigned int hookmask,
391 unsigned int time)
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000392{
393}
394
gborowiak6c6d7312003-09-16 19:26:38 +0000395#ifdef DEBUG
396static void wormhash_debug(const struct ebt_mac_wormhash *wh)
397{
398 int i;
Bart De Schuymerf8c97432003-09-27 17:39:09 +0000399
gborowiak6c6d7312003-09-16 19:26:38 +0000400 printf("poolsize: %d\n", wh->poolsize);
401 for (i = 0; i <= 256; i++) {
402 printf("%02x ", wh->table[i]);
403 if (i % 16 == 15) {
404 printf("\n");
405 }
406 }
407 printf("\n");
408}
409#endif /* DEBUG */
410
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000411static void wormhash_printout(const struct ebt_mac_wormhash *wh)
412{
413 int i;
gborowiakc50ce6a2003-09-07 13:16:26 +0000414 unsigned char *ip;
Bart De Schuymerf8c97432003-09-27 17:39:09 +0000415
gborowiak6c6d7312003-09-16 19:26:38 +0000416 for (i = 0; i < wh->poolsize; i++) {
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000417 const struct ebt_mac_wormhash_tuple *p;
Bart De Schuymerf8c97432003-09-27 17:39:09 +0000418
gborowiak6c6d7312003-09-16 19:26:38 +0000419 p = (const struct ebt_mac_wormhash_tuple *)(&wh->pool[i]);
Bart De Schuymer510c9ce2006-01-23 18:50:54 +0000420 ebt_print_mac(((const unsigned char *) &p->cmp[0]) + 2);
gborowiak6c6d7312003-09-16 19:26:38 +0000421 if (p->ip) {
422 ip = (unsigned char *) &p->ip;
423 printf("=%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000424 }
gborowiak6c6d7312003-09-16 19:26:38 +0000425 printf(",");
426 }
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000427 printf(" ");
428}
429
430static void print(const struct ebt_u_entry *entry,
gborowiak6c6d7312003-09-16 19:26:38 +0000431 const struct ebt_entry_match *match)
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000432{
gborowiakc50ce6a2003-09-07 13:16:26 +0000433 struct ebt_among_info *info = (struct ebt_among_info *)match->data;
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000434
gborowiakc50ce6a2003-09-07 13:16:26 +0000435 if (info->wh_dst_ofs) {
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000436 printf("--among-dst ");
gborowiakc50ce6a2003-09-07 13:16:26 +0000437 if (info->bitmask && EBT_AMONG_DST_NEG) {
438 printf("! ");
439 }
440 wormhash_printout(ebt_among_wh_dst(info));
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000441 }
gborowiakc50ce6a2003-09-07 13:16:26 +0000442 if (info->wh_src_ofs) {
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000443 printf("--among-src ");
gborowiakc50ce6a2003-09-07 13:16:26 +0000444 if (info->bitmask && EBT_AMONG_SRC_NEG) {
445 printf("! ");
446 }
447 wormhash_printout(ebt_among_wh_src(info));
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000448 }
449}
450
gborowiak6c6d7312003-09-16 19:26:38 +0000451static int compare_wh(const struct ebt_mac_wormhash *aw,
452 const struct ebt_mac_wormhash *bw)
gborowiakc50ce6a2003-09-07 13:16:26 +0000453{
454 int as, bs;
Bart De Schuymerf8c97432003-09-27 17:39:09 +0000455
gborowiakc50ce6a2003-09-07 13:16:26 +0000456 as = ebt_mac_wormhash_size(aw);
457 bs = ebt_mac_wormhash_size(bw);
458 if (as != bs)
459 return 0;
460 if (as && memcmp(aw, bw, as))
461 return 0;
462 return 1;
463}
464
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000465static int compare(const struct ebt_entry_match *m1,
gborowiak6c6d7312003-09-16 19:26:38 +0000466 const struct ebt_entry_match *m2)
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000467{
gborowiak6c6d7312003-09-16 19:26:38 +0000468 struct ebt_among_info *a = (struct ebt_among_info *) m1->data;
469 struct ebt_among_info *b = (struct ebt_among_info *) m2->data;
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000470
gborowiak6c6d7312003-09-16 19:26:38 +0000471 if (!compare_wh(ebt_among_wh_dst(a), ebt_among_wh_dst(b)))
472 return 0;
473 if (!compare_wh(ebt_among_wh_src(a), ebt_among_wh_src(b)))
474 return 0;
475 if (a->bitmask != b->bitmask)
476 return 0;
gborowiakc50ce6a2003-09-07 13:16:26 +0000477 return 1;
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000478}
479
gborowiak6c6d7312003-09-16 19:26:38 +0000480static struct ebt_u_match among_match = {
Bart De Schuymer138bf062009-06-21 12:38:05 +0000481 .name = "among",
gborowiak6c6d7312003-09-16 19:26:38 +0000482 .size = sizeof(struct ebt_among_info),
483 .help = print_help,
484 .init = init,
485 .parse = parse,
486 .final_check = final_check,
487 .print = print,
488 .compare = compare,
489 .extra_ops = opts,
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000490};
491
Bart De Schuymer64182a32004-01-21 20:39:54 +0000492void _init(void)
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000493{
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000494 ebt_register_match(&among_match);
Bart De Schuymer9cc9bfa2003-09-02 22:43:25 +0000495}