From 9cc9bfa863610284ee1f24b2a787d8d8ad4a8ae4 Mon Sep 17 00:00:00 2001 From: Bart De Schuymer Date: Tue, 2 Sep 2003 22:43:25 +0000 Subject: Grzegorz Borowiak --- extensions/ebt_among.c | 233 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100644 extensions/ebt_among.c (limited to 'extensions') diff --git a/extensions/ebt_among.c b/extensions/ebt_among.c new file mode 100644 index 0000000..5ec8a45 --- /dev/null +++ b/extensions/ebt_among.c @@ -0,0 +1,233 @@ +#include +#include +#include +#include +#include +#include +#include "../include/ebtables_u.h" +#include "../include/ethernetdb.h" +#include +#include + +/* +#define DEBUG +*/ + +#define AMONG_DST '1' +#define AMONG_SRC '2' + +static struct option opts[] = +{ + { "among-dst" , required_argument, 0, AMONG_DST }, + { "among-src" , required_argument, 0, AMONG_SRC }, + { 0 } +}; + +#ifdef DEBUG +static void hexdump(const void *mem, int howmany) +{ + printf("\n"); + const unsigned char *p = mem; + int i; + for (i = 0; i < howmany; i++) { + if (i % 32 == 0) { + printf("\n%04x: ", i); + } + printf("%2.2x ", p[i]); + } + printf("\n"); +} +#endif /* DEBUG */ + +static void print_help() +{ + printf( +"`among' options:\n" +"--among-dst list : matches if ether dst is in list\n" +"--among-src list : matches if ether src is in list\n" +"list has form:\n" +"\txx:xx:xx:xx:xx:xx,yy:yy:yy:yy:yy:yy,...,zz:zz:zz:zz:zz:zz\n" +"i.e. MAC addresses separated by commas, without spaces.\n" +"Optional comma can be included after the last MAC address, i.e.:\n" +"\txx:xx:xx:xx:xx:xx,yy:yy:yy:yy:yy:yy,...,zz:zz:zz:zz:zz:zz,\n" +"Each list can contain up to 256 addresses.\n" + ); +} + +static void init(struct ebt_entry_match *match) +{ + struct ebt_among_info *amonginfo = (struct ebt_among_info *)match->data; + + memset(amonginfo, 0, sizeof(struct ebt_among_info)); +} + +static int fill_mac(char *mac, const char *string) +{ + char xnum[3]; + const char *p = string; + int i = 0; + int j = 0; + while (1) { + if (isxdigit(*p)) { + xnum[j] = *p; + j++; + if (j >= 3) { + /* 3 or more hex digits for a single byte */ + return -3; + } + } + else { + xnum[j] = 0; + j = 0; + mac[i] = strtol(xnum, 0, 16); + i++; + if (i >= 6) { + if (*p == ':') { + /* MAC address too long */ + return -2; + } + else { + return 0; + } + } + else { + if (*p != ':') { + /* MAC address too short */ + return -1; + } + } + } + p++; + } + +} + +static void fill_wormhash(struct ebt_mac_wormhash *wh, const char *arg) +{ + const char *pc = arg; + const char *anchor; + char mac[6]; + int index; + int nmacs = 0; + char *base = (char*)wh; + memset(wh, 0, sizeof(struct ebt_mac_wormhash)); + while (1) { + anchor = pc; + while (*pc && *pc != ',') pc++; + while (*pc && *pc == ',') pc++; + if (fill_mac(mac, anchor)) { + print_error("problem with MAC %20s...", anchor); + } + index = (unsigned char)mac[5]; + memcpy(((char*)wh->pool[nmacs].cmp)+2, mac, 6); + wh->pool[nmacs].next_ofs = wh->table[index]; + wh->table[index] = ((const char*)&wh->pool[nmacs]) - base; + nmacs++; + if (*pc && nmacs >= 256) { + print_error("--among-src/--among-dst list can contain no more than 256 addresses\n"); + } + if (!*pc) { + break; + } + } +} + +#define OPT_DST 0x01 +#define OPT_SRC 0x02 +static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry, + unsigned int *flags, struct ebt_entry_match **match) +{ + struct ebt_among_info *amonginfo = (struct ebt_among_info *)(*match)->data; + struct ebt_mac_wormhash *wh; + + switch (c) { + case AMONG_DST: + case AMONG_SRC: + if (c == AMONG_DST) { + check_option(flags, OPT_DST); + wh = &amonginfo->wh_dst; + amonginfo->bitmask |= EBT_AMONG_DST; + } else { + check_option(flags, OPT_SRC); + wh = &amonginfo->wh_src; + amonginfo->bitmask |= EBT_AMONG_SRC; + } + if (optind > argc) + print_error("No MAC list specified\n"); + fill_wormhash(wh, argv[optind - 1]); + break; + default: + return 0; + } + return 1; +} + +static void final_check(const struct ebt_u_entry *entry, + const struct ebt_entry_match *match, const char *name, + unsigned int hookmask, unsigned int time) +{ +} + +static void wormhash_printout(const struct ebt_mac_wormhash *wh) +{ + int i; + int offset; + for (i = 0; i < 256; i++) { + const struct ebt_mac_wormhash_tuple *p; + offset = wh->table[i]; + while (offset) { + p = (const struct ebt_mac_wormhash_tuple*)((const char*)wh + offset); + printf("%s,", ether_ntoa((const struct ether_addr *)(((const char*)&p->cmp[0]) + 2))); + offset = p->next_ofs; + } + } + printf(" "); +} + +static void print(const struct ebt_u_entry *entry, + const struct ebt_entry_match *match) +{ + struct ebt_among_info *amonginfo = (struct ebt_among_info *)match->data; + + if (amonginfo->bitmask & EBT_AMONG_DST) { + printf("--among-dst "); + wormhash_printout(&amonginfo->wh_dst); + } + if (amonginfo->bitmask & EBT_AMONG_SRC) { + printf("--among-src "); + wormhash_printout(&amonginfo->wh_src); + } +} + +static int compare(const struct ebt_entry_match *m1, + const struct ebt_entry_match *m2) +{ + struct ebt_among_info *amonginfo1 = (struct ebt_among_info *)m1->data; + struct ebt_among_info *amonginfo2 = (struct ebt_among_info *)m2->data; + +#ifdef DEBUG +// hexdump(amonginfo1, sizeof(struct ebt_among_info)); +// hexdump(amonginfo2, sizeof(struct ebt_among_info)); +#endif /* DEBUG */ + + return memcmp(amonginfo1, amonginfo2, sizeof(struct ebt_among_info)) == 0; +} + +static struct ebt_u_match among_match = +{ + EBT_AMONG_MATCH, + sizeof(struct ebt_among_info), + print_help, + init, + parse, + final_check, + print, + compare, + opts +}; + +static void _init(void) __attribute__ ((constructor)); +static void _init(void) +{ + register_match(&among_match); +} -- cgit v1.2.3