--- ebtables-v2.0pre10/Makefile Wed Jul 10 22:12:36 2002 +++ ebtables-v2.0-rc1.001/Makefile Wed Jul 31 19:48:25 2002 @@ -2,7 +2,7 @@ KERNEL_DIR?=/usr/src/linux PROGNAME:=ebtables -PROGVERSION:="2.0pre10 (July 2002)" +PROGVERSION:="2.0-rc1 (July 2002)" MANDIR?=/usr/local/man CFLAGS:=-Wall -Wunused --- ebtables-v2.0pre10/ebtables.c Tue Jul 16 20:36:50 2002 +++ ebtables-v2.0-rc1.001/ebtables.c Thu Jul 25 16:02:43 2002 @@ -1,5 +1,5 @@ /* - * ebtables.c, v2.0 April 2002 + * ebtables.c, v2.0 July 2002 * * Author: Bart De Schuymer * @@ -32,13 +32,12 @@ #include // the database #include #include -#include #include "include/ebtables_u.h" #include #include #include -// here are the number-name correspondences kept for the ethernet +// here are the number-name correspondences kept for the Ethernet // frame type field #define PROTOCOLFILE "/etc/ethertypes" @@ -123,8 +122,6 @@ unsigned char mac_type_broadcast[ETH_ALEN] = {255,255,255,255,255,255}; unsigned char msk_type_broadcast[ETH_ALEN] = {255,255,255,255,255,255}; -// tells what happened to the old rules -static unsigned short *counterchanges; // holds all the data static struct ebt_u_replace replace; @@ -228,8 +225,7 @@ struct ebt_u_match_list **m_list, *new; m->used = 1; - for (m_list = &new_entry->m_list; - *m_list; m_list = &(*m_list)->next); + for (m_list = &new_entry->m_list; *m_list; m_list = &(*m_list)->next); new = (struct ebt_u_match_list *) malloc(sizeof(struct ebt_u_match_list)); if (!new) @@ -245,8 +241,7 @@ struct ebt_u_watcher_list *new; w->used = 1; - for (w_list = &new_entry->w_list; - *w_list; w_list = &(*w_list)->next); + for (w_list = &new_entry->w_list; *w_list; w_list = &(*w_list)->next); new = (struct ebt_u_watcher_list *) malloc(sizeof(struct ebt_u_watcher_list)); if (!new) @@ -340,6 +335,7 @@ ebt_options = merge_options (ebt_options, t->extra_ops, &(t->option_offset)); t->init(t->t); + for (i = &targets; *i; i = &((*i)->next)); t->next = NULL; *i = t; @@ -379,7 +375,6 @@ return NULL; } -// I hate stealing, really... Lets call it a tribute. int ebtables_insmod(const char *modname, const char *modprobe) { char *buf = NULL; @@ -413,86 +408,26 @@ return 0; } - -// used to parse /etc/ethertypes -static int disregard_whitespace(char *buffer, FILE *ifp) -{ - int hlp; - - buffer[0] = '\t'; - while (buffer[0] == '\t' || buffer[0] == '\n' || buffer[0] == ' ') { - hlp = fscanf(ifp, "%c", buffer); - if (hlp == EOF || hlp == 0) return -1; - } - return 0; -} - -// used to parse /etc/ethertypes -static int disregard_tabspace(char *buffer, FILE *ifp) -{ - int hlp; - - buffer[0] = '\t'; - while (buffer[0] == '\t' || buffer[0] == ' ') { - hlp = fscanf(ifp, "%c", buffer); - if (hlp == EOF || hlp == 0) return -1; - } - return 0; -} - // helper function: processes a line of data from the file /etc/ethertypes static int get_a_line(char *buffer, char *value, FILE *ifp) { - int i, hlp; - char anotherhlp; + char line[80], *p; + const char delim[] = " \t\n"; - // discard comment lines and whitespace - while (1) { - if (disregard_whitespace(buffer, ifp)) - return -1; - if (buffer[0] == '#') - while (1) { - hlp = fscanf(ifp, "%c", &anotherhlp); - if (!hlp || hlp == EOF) - return -1; - if (anotherhlp == '\n') - break; - } - else - break; - } - - // buffer[0] already contains the first letter - for (i = 1; i < 21; i++) { - hlp = fscanf(ifp, "%c", buffer + i); - if (hlp == EOF || hlp == 0) - return -1; - if (buffer[i] == '\t' || buffer[i] == ' ') - break; - } - if (i == 21) - return -1; - buffer[i] = '\0'; - if (disregard_tabspace(value, ifp)) - return -1; - // maybe I should allow 0x0800 instead of 0800, but I'm feeling lazy - // buffer[0] already contains the first letter - for (i = 1; i < 5; i++) { - hlp = fscanf(ifp, "%c", value+i); - if (value[i] == '\n' || value[i] == '\t' || - value[i] == ' ' || hlp == EOF) - break; + while (fgets(line, sizeof(line), ifp)) { + p = strtok(line, delim); + if (!p || p[0] == '#') + continue; + if (strlen(p) > 20) + continue; + strcpy(buffer, p); + p = strtok(NULL, delim); + if (!p || strlen(p) > 10) + continue; + strcpy(value, p); + return 0; } - if (i == 5) return -1; - // discard comments at the end of a line - if (value[i] == '\t' || value[i] == ' ') - while (1) { - hlp = fscanf(ifp, "%c", &anotherhlp); - if (!hlp || hlp == EOF || anotherhlp == '\n') - break; - } - value[i] = '\0'; - return 0; + return -1; } // translate a hexadecimal number to a protocol name, parsing /etc/ethertypes @@ -500,7 +435,7 @@ int number_to_name(unsigned short proto, char *name) { FILE *ifp; - char buffer[21], value[5], *bfr; + char buffer[21], value[11], *bfr; unsigned short i; if ( !(ifp = fopen(PROTOCOLFILE, "r")) ) @@ -768,7 +703,9 @@ if (!(replace.valid_hooks & (1 << i))) continue; entries = nr_to_chain(i); - entries->hook_mask = (1 << i); + // (1 << NF_BR_NUMHOOKS) implies it's a standard chain + // (usefull in the final_check() funtions) + entries->hook_mask = (1 << i) | (1 << NF_BR_NUMHOOKS); chain_nr = i; e = entries->entries; @@ -784,7 +721,8 @@ for (k = 0; k < sp; k++) if (stack[k].chain_nr == verdict + NF_BR_NUMHOOKS) print_error("Loop from chain %s to chain %s", - nr_to_chain(chain_nr)->name, nr_to_chain(stack[k].chain_nr)->name); + nr_to_chain(chain_nr)->name, + nr_to_chain(stack[k].chain_nr)->name); // jump to the chain, make sure we know how to get back stack[sp].chain_nr = chain_nr; stack[sp].n = j; @@ -960,16 +898,16 @@ replace.num_counters = replace.nentries; if (replace.nentries) { // '+ 1' for the CNT_END - if (!(counterchanges = (unsigned short *) malloc( + if (!(replace.counterchanges = (unsigned short *) malloc( (replace.nentries + 1) * sizeof(unsigned short)))) print_memory(); // done nothing special to the rules for (i = 0; i < replace.nentries; i++) - counterchanges[i] = CNT_NORM; - counterchanges[replace.nentries] = CNT_END; + replace.counterchanges[i] = CNT_NORM; + replace.counterchanges[replace.nentries] = CNT_END; } else - counterchanges = NULL; + replace.counterchanges = NULL; } else exit(0); @@ -1026,14 +964,14 @@ if (replace.nentries) { // +1 for CNT_END - if ( !(counterchanges = (unsigned short *) + if ( !(replace.counterchanges = (unsigned short *) malloc((oldnentries + 1) * sizeof(unsigned short))) ) print_memory(); } // delete the counters belonging to the specified chain, // update counter_offset i = -1; - cnt = counterchanges; + cnt = replace.counterchanges; while (1) { i++; entries = nr_to_chain(i); @@ -1101,73 +1039,74 @@ for (i = 0; i < entries->nentries; i++, u_e = u_e->next) { if (!u_e) print_bug("Hmm, trouble"); - if ( u_e->ethproto == new_entry->ethproto - && !strcmp(u_e->in, new_entry->in) - && !strcmp(u_e->out, new_entry->out)) { - if (strcmp(u_e->logical_in, new_entry->logical_in) || - strcmp(u_e->logical_out, new_entry->logical_out)) - continue; - if (new_entry->bitmask & EBT_SOURCEMAC && - memcmp(u_e->sourcemac, new_entry->sourcemac, ETH_ALEN)) - continue; - if (new_entry->bitmask & EBT_DESTMAC && - memcmp(u_e->destmac, new_entry->destmac, ETH_ALEN)) - continue; - if (new_entry->bitmask != u_e->bitmask || - new_entry->invflags != u_e->invflags) - continue; - // compare all matches - m_l = new_entry->m_list; - j = 0; - while (m_l) { - m = (struct ebt_u_match *)(m_l->m); - m_l2 = u_e->m_list; - while (m_l2 && - strcmp(m_l2->m->u.name, m->m->u.name)) - m_l2 = m_l2->next; - if (!m_l2 || !m->compare(m->m, m_l2->m)) - goto letscontinue; - j++; - m_l = m_l->next; - } - // now be sure they have the same nr of matches - k = 0; - m_l = u_e->m_list; - while (m_l) { - k++; - m_l = m_l->next; - } - if (j != k) - continue; + if (u_e->ethproto != new_entry->ethproto) + continue; + if (strcmp(u_e->in, new_entry->in)) + continue; + if (strcmp(u_e->out, new_entry->out)) + continue; + if (strcmp(u_e->logical_in, new_entry->logical_in)) + continue; + if (strcmp(u_e->logical_out, new_entry->logical_out)) + continue; + if (new_entry->bitmask & EBT_SOURCEMAC && + memcmp(u_e->sourcemac, new_entry->sourcemac, ETH_ALEN)) + continue; + if (new_entry->bitmask & EBT_DESTMAC && + memcmp(u_e->destmac, new_entry->destmac, ETH_ALEN)) + continue; + if (new_entry->bitmask != u_e->bitmask || + new_entry->invflags != u_e->invflags) + continue; + // compare all matches + m_l = new_entry->m_list; + j = 0; + while (m_l) { + m = (struct ebt_u_match *)(m_l->m); + m_l2 = u_e->m_list; + while (m_l2 && strcmp(m_l2->m->u.name, m->m->u.name)) + m_l2 = m_l2->next; + if (!m_l2 || !m->compare(m->m, m_l2->m)) + goto letscontinue; + j++; + m_l = m_l->next; + } + // now be sure they have the same nr of matches + k = 0; + m_l = u_e->m_list; + while (m_l) { + k++; + m_l = m_l->next; + } + if (j != k) + continue; - // compare all watchers - w_l = new_entry->w_list; - j = 0; - while (w_l) { - w = (struct ebt_u_watcher *)(w_l->w); - w_l2 = u_e->w_list; - while (w_l2 && - strcmp(w_l2->w->u.name, w->w->u.name)) - w_l2 = w_l2->next; - if (!w_l2 || !w->compare(w->w, w_l2->w)) - goto letscontinue; - j++; - w_l = w_l->next; - } - k = 0; - w_l = u_e->w_list; - while (w_l) { - k++; - w_l = w_l->next; - } - if (j != k) - continue; - if (strcmp(t->t->u.name, u_e->t->u.name)) - continue; - if (!t->compare(t->t, u_e->t)) - continue; - return i; + // compare all watchers + w_l = new_entry->w_list; + j = 0; + while (w_l) { + w = (struct ebt_u_watcher *)(w_l->w); + w_l2 = u_e->w_list; + while (w_l2 && strcmp(w_l2->w->u.name, w->w->u.name)) + w_l2 = w_l2->next; + if (!w_l2 || !w->compare(w->w, w_l2->w)) + goto letscontinue; + j++; + w_l = w_l->next; + } + k = 0; + w_l = u_e->w_list; + while (w_l) { + k++; + w_l = w_l->next; } + if (j != k) + continue; + if (strcmp(t->t->u.name, u_e->t->u.name)) + continue; + if (!t->compare(t->t, u_e->t)) + continue; + return i; letscontinue: } return -1; @@ -1177,7 +1116,7 @@ static void add_rule(int rule_nr) { int i, j; - struct ebt_u_entry *u_e, *u_e2; + struct ebt_u_entry **u_e; unsigned short *cnt; struct ebt_u_match_list *m_l; struct ebt_u_watcher_list *w_l; @@ -1196,10 +1135,10 @@ // handle counter stuff // +1 for CNT_END - if ( !(counterchanges = (unsigned short *) + if ( !(replace.counterchanges = (unsigned short *) malloc((replace.nentries + 1) * sizeof(unsigned short))) ) print_memory(); - cnt = counterchanges; + cnt = replace.counterchanges; for (i = 0; i < replace.selected_hook; i++) { if (i < NF_BR_NUMHOOKS && !(replace.valid_hooks & (1 << i))) continue; @@ -1215,25 +1154,19 @@ } *cnt = CNT_ADD; cnt++; - while (cnt != counterchanges + replace.nentries) { + while (cnt != replace.counterchanges + replace.nentries) { *cnt = CNT_NORM; cnt++; } *cnt = CNT_END; // go to the right position in the chain - u_e2 = NULL; - u_e = entries->entries; - for (i = 0; i < rule_nr; i++) { - u_e2 = u_e; - u_e = u_e->next; - } + u_e = &entries->entries; + for (i = 0; i < rule_nr; i++) + u_e = &(*u_e)->next; // insert the rule - if (u_e2) - u_e2->next = new_entry; - else - entries->entries = new_entry; - new_entry->next = u_e; + new_entry->next = *u_e; + *u_e = new_entry; // put the ebt_[match, watcher, target] pointers in place m_l = new_entry->m_list; @@ -1268,7 +1201,7 @@ { int i, j, lentmp = 0; unsigned short *cnt; - struct ebt_u_entry *u_e, *u_e2; + struct ebt_u_entry **u_e, *u_e2; struct ebt_u_entries *entries = to_chain(), *entries2; if ( (i = check_rule_exists(rule_nr)) == -1 ) @@ -1277,6 +1210,7 @@ // we're deleting a rule replace.num_counters = replace.nentries; replace.nentries--; + entries->nentries--; if (replace.nentries) { for (j = 0; j < replace.selected_hook; j++) { @@ -1288,10 +1222,10 @@ } lentmp += i; // +1 for CNT_END - if ( !(counterchanges = (unsigned short *)malloc( + if ( !(replace.counterchanges = (unsigned short *)malloc( (replace.num_counters + 1) * sizeof(unsigned short))) ) print_memory(); - cnt = counterchanges; + cnt = replace.counterchanges; for (j = 0; j < lentmp; j++) { *cnt = CNT_NORM; cnt++; @@ -1308,23 +1242,16 @@ replace.num_counters = 0; // go to the right position in the chain - u_e2 = NULL; - u_e = entries->entries; - for (j = 0; j < i; j++) { - u_e2 = u_e; - u_e = u_e->next; - } - - // remove from the chain - if (u_e2) - u_e2->next = u_e->next; - else - entries->entries = u_e->next; - - entries->nentries--; + u_e = &entries->entries; + for (j = 0; j < i; j++) + u_e = &(*u_e)->next; + // remove the rule + u_e2 = *u_e; + *u_e = (*u_e)->next; // free everything - free_u_entry(u_e); - free(u_e); + free_u_entry(u_e2); + free(u_e2); + // update the counter_offset of chains behind this one i = replace.selected_hook; while (1) { @@ -1348,7 +1275,7 @@ // tell main() we don't update the counters // this results in tricking the kernel to zero its counters, // naively expecting userspace to update its counters. Muahahaha - counterchanges = NULL; + replace.counterchanges = NULL; replace.num_counters = 0; } else { int i, j; @@ -1357,11 +1284,11 @@ if (entries->nentries == 0) exit(0); - counterchanges = (unsigned short *) + replace.counterchanges = (unsigned short *) malloc((replace.nentries + 1) * sizeof(unsigned short)); - if (!counterchanges) + if (!replace.counterchanges) print_memory(); - cnt = counterchanges; + cnt = replace.counterchanges; for (i = 0; i < zerochain; i++) { if (i < NF_BR_NUMHOOKS && !(replace.valid_hooks & (1 << i))) @@ -1376,7 +1303,7 @@ *cnt = CNT_ZERO; cnt++; } - while (cnt != counterchanges + replace.nentries) { + while (cnt != replace.counterchanges + replace.nentries) { *cnt = CNT_NORM; cnt++; } @@ -1450,7 +1377,7 @@ int name_to_number(char *name, __u16 *proto) { FILE *ifp; - char buffer[21], value[5], *bfr; + char buffer[21], value[11], *bfr; unsigned short i; if (!strcasecmp("LENGTH", name)) { @@ -1461,14 +1388,15 @@ if ( !(ifp = fopen(PROTOCOLFILE, "r")) ) return -1; while (1) { - if (get_a_line(buffer, value, ifp)) return -1; + if (get_a_line(buffer, value, ifp)) + return -1; if (strcasecmp(buffer, name)) continue; + fclose(ifp); i = (unsigned short) strtol(value, &bfr, 16); if (*bfr != '\0') return -1; *proto = i; - fclose(ifp); return 0; } return -1; @@ -1587,6 +1515,19 @@ *flags |= mask; } +static void get_kernel_table(const char *modprobe) +{ + if ( !(table = find_table(replace.name)) ) + print_error("Bad table name"); + // get the kernel's information + if (get_table(&replace)) { + ebtables_insmod("ebtables", modprobe); + if (get_table(&replace)) + print_error("The kernel doesn't support the ebtables " + "%s table", replace.name); + } +} + #define OPT_COMMAND 0x01 #define OPT_TABLE 0x02 #define OPT_IN 0x04 @@ -1606,7 +1547,7 @@ // this special one for the -Z option (we can have -Z -L ) int zerochain = -1; int policy = 0; - int rule_nr = -1;// used for -D chain number + int rule_nr = -1;// used for -[D,I] chain number struct ebt_u_target *t; struct ebt_u_match *m; struct ebt_u_watcher *w; @@ -1621,6 +1562,7 @@ replace.selected_hook = -1; replace.command = 'h'; replace.filename = NULL; + replace.counterchanges = NULL; new_entry = (struct ebt_u_entry *)malloc(sizeof(struct ebt_u_entry)); if (!new_entry) @@ -1648,16 +1590,8 @@ if (replace.flags & OPT_COMMAND) print_error("Multiple commands not allowed"); replace.flags |= OPT_COMMAND; - if ( !(table = find_table(replace.name)) ) - print_error("Bad table name"); - // get the kernel's information - if (get_table(&replace)) { - ebtables_insmod("ebtables", modprobe); - if (get_table(&replace)) - print_error("can't initialize ebtables " - "table %s", replace.name); - } - if (optarg[0] == '-') + get_kernel_table(modprobe); + if (optarg[0] == '-' || !strcmp(optarg, "!")) print_error("No chain name specified"); if (c == 'N') { struct ebt_u_chain_list *cl, **cl2; @@ -1697,7 +1631,8 @@ if ((replace.selected_hook = get_hooknr(optarg)) == -1) print_error("Chain %s doesn't exist", optarg); if (c == 'E') { - if (optind >= argc || argv[optind][0] == '-') + if (optind >= argc || argv[optind][0] == '-' || + !strcmp(argv[optind], "!")) print_error("No new chain name specified"); if (strlen(argv[optind]) >= EBT_CHAIN_MAXNAMELEN) print_error("Chain name len can't exceed %d", @@ -1705,6 +1640,9 @@ if (get_hooknr(argv[optind]) != -1) print_error("Chain %s already exists", argv[optind]); + if (find_target(argv[optind])) + print_error("Target with name %s exists" + , argv[optind]); entries = to_chain(); strcpy(entries->name, argv[optind]); optind++; @@ -1719,25 +1657,21 @@ check_for_references(replace.selected_hook - NF_BR_NUMHOOKS); flush_chains(); entries = to_chain(); - if (replace.udc->udc == entries) { - cl = replace.udc; - replace.udc = replace.udc->next; - free(cl->udc); - free(cl); - break; - } cl2 = &(replace.udc); - while ((*cl2)->next->udc != entries) + while ((*cl2)->udc != entries) cl2 = &((*cl2)->next); - cl = (*cl2)->next; - (*cl2)->next = (*cl2)->next->next; + cl = (*cl2); + (*cl2) = (*cl2)->next; free(cl->udc); free(cl); break; } - if (c == 'D' && optind < argc && - argv[optind][0] != '-') { + if ( (c == 'D' && optind < argc && + argv[optind][0] != '-') || c == 'I') { + if (optind >= argc || argv[optind][0] == '-') + print_error("No rulenr for -I" + " specified"); rule_nr = strtol(argv[optind], &buffer, 10); if (*buffer != '\0' || rule_nr < 0) print_error("Problem with the " @@ -1760,16 +1694,6 @@ print_error("Wrong policy"); optind++; } - if (c == 'I') { - if (optind >= argc) - print_error("No rulenr for -I" - " specified"); - rule_nr = strtol(argv[optind], &buffer, 10); - if (*buffer != '\0' || rule_nr < 0) - print_error("Problem with the specified" - " rule number"); - optind++; - } break; case 'L': // list @@ -1791,23 +1715,14 @@ " not allowed"); replace.flags |= OPT_COMMAND; } - if ( !(table = find_table(replace.name)) ) - print_error("Bad table name"); - // get the kernel's information - if (get_table(&replace)) { - ebtables_insmod("ebtables", modprobe); - if (get_table(&replace)) - print_error("can't initialize ebtables " - "table %s", replace.name); - } + get_kernel_table(modprobe); i = -1; if (optarg) { if ( (i = get_hooknr(optarg)) == -1 ) print_error("Bad chain"); } else if (optind < argc && argv[optind][0] != '-') { - if ((i = get_hooknr(argv[optind])) - == -1) + if ((i = get_hooknr(argv[optind])) == -1) print_error("Bad chain"); optind++; } @@ -2054,7 +1969,7 @@ if (new_entry->ethproto < 1536 && !(new_entry->bitmask & EBT_802_3)) print_error("Sorry, protocols have values above" - " or equal to 1536 (0x0600)"); + " or equal to 0x0600"); break; case 'b': // allow database? @@ -2104,17 +2019,24 @@ if (replace.flags & OPT_COMMAND) print_error("Multiple commands not allowed"); replace.flags |= OPT_COMMAND; + if (replace.filename) + print_error("--atomic incompatible with " + "command"); replace.filename = (char *)malloc(strlen(optarg) + 1); strcpy(replace.filename, optarg); // get the information from the file get_table(&replace); if (replace.nentries) { - counterchanges = (unsigned short *) + replace.counterchanges = (unsigned short *) malloc(sizeof(unsigned short) * (replace.nentries + 1)); for (i = 0; i < replace.nentries; i++) - counterchanges[i] = CNT_NORM; - counterchanges[i] = CNT_END; + replace.counterchanges[i] = CNT_NORM; + replace.counterchanges[i] = CNT_END; } + // we don't want the kernel giving us its counters, they would + // overwrite the counters extracted from the file + replace.num_counters = 0; + // make sure the table will be written to the kernel free(replace.filename); replace.filename = NULL; break; @@ -2125,24 +2047,23 @@ if (replace.flags & OPT_COMMAND) print_error("Multiple commands not allowed"); replace.flags |= OPT_COMMAND; - if ( !(table = find_table(replace.name)) ) - print_error("Bad table name"); - if (get_table(&replace)) { - ebtables_insmod("ebtables", modprobe); - if (get_table(&replace)) - print_error("can't initialize ebtables " - "table %s", replace.name); - } + if (replace.filename) + print_error("--atomic incompatible with " + "command"); + get_kernel_table(modprobe); if (replace.nentries) { - counterchanges = (unsigned short *) + replace.counterchanges = (unsigned short *) malloc(sizeof(unsigned short) * (replace.nentries + 1)); for (i = 0; i < replace.nentries; i++) - counterchanges[i] = CNT_NORM; - counterchanges[i] = CNT_END; + replace.counterchanges[i] = CNT_NORM; + replace.counterchanges[i] = CNT_END; } if (c == 11) break; case 9 : // atomic + if (c == 9 && (replace.flags & OPT_COMMAND)) + print_error("--atomic has to come before" + " the command"); replace.filename = (char *)malloc(strlen(optarg) + 1); strcpy(replace.filename, optarg); break; @@ -2179,7 +2100,7 @@ check_extension: if (replace.command != 'A' && replace.command != 'I' && replace.command != 'D') - print_error("extensions only for -A, -I and -D"); + print_error("Extensions only for -A, -I and -D"); } } @@ -2195,12 +2116,6 @@ replace.flags & OPT_ZERO ) print_error("Command -Z only allowed together with command -L"); - if (replace.command == 'A' || replace.command == 'I' || - replace.command == 'D') { - if (replace.selected_hook == -1) - print_error("Not enough information"); - } - // do this after parsing everything, so we can print specific info if (replace.command == 'h' && !(replace.flags & OPT_ZERO)) print_help(); @@ -2283,7 +2198,7 @@ deliver_table(&replace); - if (counterchanges) - deliver_counters(&replace, counterchanges); + if (replace.counterchanges) + deliver_counters(&replace); return 0; } --- ebtables-v2.0pre10/communication.c Mon Jul 15 22:35:14 2002 +++ ebtables-v2.0-rc1.001/communication.c Fri Jul 26 13:33:02 2002 @@ -1,5 +1,5 @@ /* - * communication.c, v2.0 April 2002 + * communication.c, v2.0 July 2002 * * Author: Bart De Schuymer * @@ -18,9 +18,8 @@ #include #include #include -#include // the database +#include #include // IPPROTO_IP -#include #include "include/ebtables_u.h" extern char* hooknames[NF_BR_NUMHOOKS]; @@ -32,7 +31,8 @@ if (sockfd == -1) { sockfd = socket(AF_INET, SOCK_RAW, PF_INET); if (sockfd < 0) - print_error("Problem getting a socket"); + print_error("Problem getting a socket, " + "do you have the right permissions?"); } } @@ -52,7 +52,7 @@ if (!new) print_memory(); new->valid_hooks = u_repl->valid_hooks; - memcpy(new->name, u_repl->name, sizeof(new->name)); + strcpy(new->name, u_repl->name); new->nentries = u_repl->nentries; new->num_counters = u_repl->num_counters; new->counters = u_repl->counters; @@ -150,12 +150,10 @@ tmp->bitmask = e->bitmask | EBT_ENTRY_OR_ENTRIES; tmp->invflags = e->invflags; tmp->ethproto = e->ethproto; - memcpy(tmp->in, e->in, sizeof(tmp->in)); - memcpy(tmp->out, e->out, sizeof(tmp->out)); - memcpy(tmp->logical_in, e->logical_in, - sizeof(tmp->logical_in)); - memcpy(tmp->logical_out, e->logical_out, - sizeof(tmp->logical_out)); + strcpy(tmp->in, e->in); + strcpy(tmp->out, e->out); + strcpy(tmp->logical_in, e->logical_in); + strcpy(tmp->logical_out, e->logical_out); memcpy(tmp->sourcemac, e->sourcemac, sizeof(tmp->sourcemac)); memcpy(tmp->sourcemsk, e->sourcemsk, @@ -190,7 +188,8 @@ (struct ebt_standard_target *)p; // translate the jump to a udc if (st->verdict >= 0) - st->verdict = chain_offsets[st->verdict + NF_BR_NUMHOOKS]; + st->verdict = chain_offsets + [st->verdict + NF_BR_NUMHOOKS]; } p += e->t->target_size + sizeof(struct ebt_entry_target); @@ -257,23 +256,23 @@ // translate the struct ebt_u_replace to a struct ebt_replace repl = translate_user2kernel(u_repl); - // give the data to the kernel - optlen = sizeof(struct ebt_replace) + repl->entries_size; if (u_repl->filename != NULL) { store_table_in_file(u_repl->filename, repl); return; } + // give the data to the kernel + optlen = sizeof(struct ebt_replace) + repl->entries_size; get_sockfd(); if (setsockopt(sockfd, IPPROTO_IP, EBT_SO_SET_ENTRIES, repl, optlen)) print_error("The kernel doesn't support a certain ebtables" " extension, consider recompiling your kernel or insmod" - " the extension"); + " the extension"); } static void store_counters_in_file(char *filename, struct ebt_u_replace *repl) { int size = repl->nentries * sizeof(struct ebt_counter); - int entries_size; + unsigned int entries_size; struct ebt_replace hlp; FILE *file; @@ -296,12 +295,13 @@ // gets executed after deliver_table void -deliver_counters(struct ebt_u_replace *u_repl, unsigned short *counterchanges) +deliver_counters(struct ebt_u_replace *u_repl) { unsigned short *point; struct ebt_counter *old, *new, *newcounters; socklen_t optlen; struct ebt_replace repl; + unsigned short *counterchanges = u_repl->counterchanges; if (u_repl->nentries == 0) return; @@ -323,16 +323,14 @@ old++; // we've set a new counter new++; - } else - if (*point == CNT_DEL) { + } else if (*point == CNT_DEL) { // don't use this old counter old++; } else if (*point == CNT_ADD) { // new counter, let it stay 0 new++; } else { - // zero it - new->pcnt = 0; + // zero it (let it stay 0) old++; new++; } @@ -355,7 +353,7 @@ get_sockfd(); if (setsockopt(sockfd, IPPROTO_IP, EBT_SO_SET_COUNTERS, &repl, optlen)) - print_bug("couldn't update kernel counters"); + print_bug("Couldn't update kernel counters"); } static int @@ -425,12 +423,10 @@ new->bitmask &= ~EBT_ENTRY_OR_ENTRIES; new->invflags = e->invflags; new->ethproto = e->ethproto; - memcpy(new->in, e->in, sizeof(new->in)); - memcpy(new->out, e->out, sizeof(new->out)); - memcpy(new->logical_in, e->logical_in, - sizeof(new->logical_in)); - memcpy(new->logical_out, e->logical_out, - sizeof(new->logical_out)); + strcpy(new->in, e->in); + strcpy(new->out, e->out); + strcpy(new->logical_in, e->logical_in); + strcpy(new->logical_out, e->logical_out); memcpy(new->sourcemac, e->sourcemac, sizeof(new->sourcemac)); memcpy(new->sourcemsk, e->sourcemsk, sizeof(new->sourcemsk)); memcpy(new->destmac, e->destmac, sizeof(new->destmac)); @@ -500,9 +496,8 @@ while (i-- > 0) cl = cl->next; *u_e = &(cl->udc->entries); - } else { + } else *u_e = &(u_repl->hook_entry[*hook]->entries); - } return 0; } } @@ -568,7 +563,7 @@ print_error("Could not open file %s", filename); // make sure table name is right if command isn't -L or --atomic-commit if (command != 'L' && command != 8) { - hlp = (char *)malloc(strlen(repl->name)); + hlp = (char *)malloc(strlen(repl->name) + 1); if (!hlp) print_memory(); strcpy(hlp, repl->name); @@ -580,12 +575,11 @@ fclose(file); print_error("File %s contains wrong table name or is corrupt", filename); - } else - if (!find_table(repl->name)) { - fclose(file); - print_error("File %s contains invalid table name", - filename); - } + free(hlp); + } else if (!find_table(repl->name)) { + fclose(file); + print_error("File %s contains invalid table name", filename); + } size = sizeof(struct ebt_replace) + repl->nentries * sizeof(struct ebt_counter) + repl->entries_size; @@ -633,7 +627,7 @@ if (getsockopt(sockfd, IPPROTO_IP, optname, repl, &optlen)) return -1; - if ( !(repl->entries = (char *) malloc(repl->entries_size)) ) + if ( !(repl->entries = (char *)malloc(repl->entries_size)) ) print_memory(); if (repl->nentries) { if (!(repl->counters = (struct ebt_counter *) @@ -657,7 +651,6 @@ return 0; } -// talk with kernel to receive the kernel's table int get_table(struct ebt_u_replace *u_repl) { int i, j, k, hook; @@ -667,12 +660,10 @@ strcpy(repl.name, u_repl->name); if (u_repl->filename != NULL) retrieve_from_file(u_repl->filename, &repl, u_repl->command); - else - if (retrieve_from_kernel(&repl, u_repl->command) == -1) - return -1; + else if (retrieve_from_kernel(&repl, u_repl->command) == -1) + return -1; // translate the struct ebt_replace to a struct ebt_u_replace - memcpy(u_repl->name, repl.name, sizeof(u_repl->name)); u_repl->valid_hooks = repl.valid_hooks; u_repl->nentries = repl.nentries; u_repl->num_counters = repl.num_counters; --- ebtables-v2.0pre10/extensions/ebt_redirect.c Thu Jun 27 18:53:55 2002 +++ ebtables-v2.0-rc1.001/extensions/ebt_redirect.c Thu Jul 25 19:28:52 2002 @@ -12,7 +12,7 @@ #define REDIRECT_TARGET '1' static struct option opts[] = { - { "redirect-target" , required_argument, 0, REDIRECT_TARGET }, + { "redirect-target", required_argument, 0, REDIRECT_TARGET }, { 0 } }; @@ -20,7 +20,7 @@ { printf( "redirect option:\n" - " --redirect-target target : ACCEPT, DROP or CONTINUE\n"); + " --redirect-target target : ACCEPT, DROP, RETURN or CONTINUE\n"); } static void init(struct ebt_entry_target *target) @@ -62,6 +62,13 @@ const struct ebt_entry_target *target, const char *name, unsigned int hook_mask, unsigned int time) { + struct ebt_redirect_info *redirectinfo = + (struct ebt_redirect_info *)target->data; + + if ((hook_mask & (1 << NF_BR_NUMHOOKS)) && + redirectinfo->target == EBT_RETURN) + print_error("--redirect-target RETURN not allowed on base chain"); + hook_mask &= ~(1 << NF_BR_NUMHOOKS); if ( ((hook_mask & ~(1 << NF_BR_PRE_ROUTING)) || strcmp(name, "nat")) && ((hook_mask & ~(1 << NF_BR_BROUTING)) || strcmp(name, "broute")) ) print_error("Wrong chain for redirect"); --- ebtables-v2.0pre10/extensions/ebtable_broute.c Thu Jun 27 18:53:55 2002 +++ ebtables-v2.0-rc1.001/extensions/ebtable_broute.c Wed Jul 24 20:44:43 2002 @@ -5,7 +5,7 @@ static void print_help(char **hn) { - printf("Supported chain for the nat table:\n"); + printf("Supported chain for the broute table:\n"); printf("%s\n",hn[NF_BR_BROUTING]); } --- ebtables-v2.0pre10/extensions/ebt_nat.c Thu Jun 27 18:53:55 2002 +++ ebtables-v2.0-rc1.001/extensions/ebt_nat.c Thu Jul 25 16:31:01 2002 @@ -37,7 +37,7 @@ printf( "snat options:\n" " --to-src address : MAC address to map source to\n" - " --snat-target target : ACCEPT, DROP or CONTINUE\n"); + " --snat-target target : ACCEPT, DROP, RETURN or CONTINUE\n"); } static void print_help_d() @@ -45,7 +45,7 @@ printf( "dnat options:\n" " --to-dst address : MAC address to map destination to\n" - " --dnat-target target : ACCEPT, DROP or CONTINUE\n"); + " --dnat-target target : ACCEPT, DROP, RETURN or CONTINUE\n"); } static void init_s(struct ebt_entry_target *target) @@ -81,7 +81,7 @@ check_option(flags, OPT_SNAT); to_source_supplied = 1; if (!(addr = ether_aton(optarg))) - print_error("Problem with specified to-source mac"); + print_error("Problem with specified --to-source mac"); memcpy(natinfo->mac, addr, ETH_ALEN); break; case NAT_S_TARGET: @@ -116,7 +116,7 @@ to_dest_supplied = 1; if (!(addr = ether_aton(optarg))) print_error("Problem with specified " - "to-destination mac"); + "--to-destination mac"); memcpy(natinfo->mac, addr, ETH_ALEN); break; case NAT_D_TARGET: @@ -139,6 +139,11 @@ const struct ebt_entry_target *target, const char *name, unsigned int hook_mask, unsigned int time) { + struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data; + + if ((hook_mask & (1 << NF_BR_NUMHOOKS)) && natinfo->target == EBT_RETURN) + print_error("--snat-target RETURN not allowed on base chain"); + hook_mask &= ~(1 << NF_BR_NUMHOOKS); if (!(hook_mask & (1 << NF_BR_POST_ROUTING)) || strcmp(name, "nat")) print_error("Wrong chain for snat"); if (time == 0 && to_source_supplied == 0) @@ -149,6 +154,11 @@ const struct ebt_entry_target *target, const char *name, unsigned int hook_mask, unsigned int time) { + struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data; + + if ((hook_mask & (1 << NF_BR_NUMHOOKS)) && natinfo->target == EBT_RETURN) + print_error("--dnat-target RETURN not allowed on base chain"); + hook_mask &= ~(1 << NF_BR_NUMHOOKS); if (((hook_mask & ~((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT))) || strcmp(name, "nat")) && ((hook_mask & ~(1 << NF_BR_BROUTING)) || strcmp(name, "broute"))) --- ebtables-v2.0pre10/extensions/ebt_vlan.c Thu Jun 27 18:53:55 2002 +++ ebtables-v2.0-rc1.001/extensions/ebt_vlan.c Wed Jul 24 12:18:25 2002 @@ -41,7 +41,7 @@ #define GET_BITMASK(_MASK_) vlaninfo->bitmask & _MASK_ #define SET_BITMASK(_MASK_) vlaninfo->bitmask |= _MASK_ -#define INV_FLAG(_inv_flag_) (vlaninfo->invflags & _inv_flag_) ? "!" : "" +#define INV_FLAG(_inv_flag_) (vlaninfo->invflags & _inv_flag_) ? "! " : "" #define VLAN_ID 0 #define VLAN_PRIO 1 @@ -60,9 +60,9 @@ static void print_help () { printf ("802.1Q VLAN extension options:\n" - "--vlan-id [!]id : VLAN-tagged frame identifier, 0,1-4094 (integer)\n" - "--vlan-prio [!]prio : Priority-tagged frame user_priority, 0-7 (integer)\n" - "--vlan-encap [!]proto : Encapsulated protocol (hexadecimal)\n"); + "--vlan-id [!] id : VLAN-tagged frame identifier, 0,1-4094 (integer)\n" + "--vlan-prio [!] prio : Priority-tagged frame user_priority, 0-7 (integer)\n" + "--vlan-encap [!] proto : Encapsulated protocol (hexadecimal)\n"); } /* @@ -124,7 +124,7 @@ * Check arg value presence */ if (optind > argc) - print_error ("Missing VLAN ID argument value\n"); + print_error ("Missing VLAN ID argument value"); /* * Convert argv to long int, * set *end to end of argv string, @@ -136,7 +136,7 @@ */ if (i > 4094 || *end != '\0') print_error - ("Specified VLAN ID is out of range (0-4094)\n"); + ("Specified VLAN ID is out of range (0-4094)"); /* * Set up parameter value */ @@ -153,7 +153,7 @@ vlaninfo->invflags |= EBT_VLAN_PRIO; if (optind > argc) print_error - ("Missing user_priority argument value\n"); + ("Missing user_priority argument value"); /* * Convert argv to long int, * set *end to end of argv string, @@ -165,7 +165,7 @@ */ if (i >= 8 || *end != '\0') print_error - ("Specified user_priority is out of range (0-7)\n"); + ("Specified user_priority is out of range (0-7)"); /* * Set up parameter value */ @@ -182,7 +182,7 @@ vlaninfo->invflags |= EBT_VLAN_ENCAP; if (optind > argc) print_error - ("Missing encapsulated frame type argument value\n"); + ("Missing encapsulated frame type argument value"); /* * Parameter can be decimal, hexadecimal, or string. * Check arg val range (still raw area) @@ -190,12 +190,12 @@ (unsigned short) encap = strtol (argv[optind - 1], &end, 16); if (*end == '\0' && (encap < ETH_ZLEN || encap > 0xFFFF)) print_error - ("Specified encapsulated frame type is out of range\n"); + ("Specified encapsulated frame type is out of range"); if (*end != '\0') if (name_to_number (argv[optind - 1], &encap) == -1) print_error ("Problem with the specified encapsulated" - "protocol\n"); + "protocol"); /* * Set up parameter value (network notation) */ @@ -227,7 +227,7 @@ */ if (entry->bitmask & EBT_NOPROTO || entry->ethproto != ETH_P_8021Q) print_error - ("For use 802.1Q extension the protocol must be specified as 802_1Q\n"); + ("For use 802.1Q extension the protocol must be specified as 802_1Q"); /* * Check if specified vlan-id=0 (priority-tagged frame condition) * when vlan-prio was specified. @@ -235,7 +235,7 @@ if (GET_BITMASK (EBT_VLAN_PRIO)) { if (vlaninfo->id && GET_BITMASK (EBT_VLAN_ID)) print_error - ("For use user_priority the specified vlan-id must be 0\n"); + ("For use user_priority the specified vlan-id must be 0"); } } --- /dev/null Thu Aug 24 11:00:32 2000 +++ ebtables-v2.0-rc1.001/extensions/ebt_mark.c Thu Jul 25 16:51:14 2002 @@ -0,0 +1,132 @@ +#include +#include +#include +#include +#include +#include +#include "../include/ebtables_u.h" +#include + +extern char *standard_targets[NUM_STANDARD_TARGETS]; + +int mark_supplied; + +#define MARK_TARGET '1' +#define MARK_SETMARK '2' +static struct option opts[] = +{ + { "mark-target" , required_argument, 0, MARK_TARGET }, + { "set-mark" , required_argument, 0, MARK_SETMARK }, + { 0 } +}; + +static void print_help() +{ + printf( + "mark target options:\n" + " --set-mark value : Set nfmark value\n" + " --mark-target target : ACCEPT, DROP, RETURN or CONTINUE\n"); +} + +static void init(struct ebt_entry_target *target) +{ + struct ebt_mark_t_info *markinfo = + (struct ebt_mark_t_info *)target->data; + + markinfo->target = EBT_ACCEPT; + markinfo->mark = 0; + mark_supplied = 0; + return; +} + +#define OPT_MARK_TARGET 0x01 +#define OPT_MARK_SETMARK 0x02 +static int parse(int c, char **argv, int argc, + const struct ebt_u_entry *entry, unsigned int *flags, + struct ebt_entry_target **target) +{ + int i; + struct ebt_mark_t_info *markinfo = + (struct ebt_mark_t_info *)(*target)->data; + char *end; + + switch (c) { + case MARK_TARGET: + check_option(flags, OPT_MARK_TARGET); + for (i = 0; i < NUM_STANDARD_TARGETS; i++) + if (!strcmp(optarg, standard_targets[i])) { + markinfo->target = -i - 1; + break; + } + if (i == NUM_STANDARD_TARGETS) + print_error("Illegal --mark-target target"); + break; + case MARK_SETMARK: + check_option(flags, OPT_MARK_SETMARK); + markinfo->mark = strtoul(optarg, &end, 0); + if (*end != '\0' || end == optarg) + print_error("Bad MARK value '%s'", optarg); + mark_supplied = 1; + break; + default: + return 0; + } + return 1; +} + +static void final_check(const struct ebt_u_entry *entry, + const struct ebt_entry_target *target, const char *name, + unsigned int hook_mask, unsigned int time) +{ + struct ebt_mark_t_info *markinfo = + (struct ebt_mark_t_info *)target->data; + + if (time == 0 && mark_supplied == 0) + print_error("No mark value supplied"); + if ((hook_mask & (1 << NF_BR_NUMHOOKS)) && markinfo->target == EBT_RETURN) + print_error("--mark-target RETURN not allowed on base chain"); +} + +static void print(const struct ebt_u_entry *entry, + const struct ebt_entry_target *target) +{ + struct ebt_mark_t_info *markinfo = + (struct ebt_mark_t_info *)target->data; + + printf("--set-mark 0x%lx", markinfo->mark); + if (markinfo->target == EBT_ACCEPT) + return; + printf(" --mark-target %s", + standard_targets[-markinfo->target - 1]); +} + +static int compare(const struct ebt_entry_target *t1, + const struct ebt_entry_target *t2) +{ + struct ebt_mark_t_info *markinfo1 = + (struct ebt_mark_t_info *)t1->data; + struct ebt_mark_t_info *markinfo2 = + (struct ebt_mark_t_info *)t2->data; + + return markinfo1->target == markinfo2->target && + markinfo1->mark == markinfo2->mark; +} + +static struct ebt_u_target mark_target = +{ + EBT_MARK_TARGET, + sizeof(struct ebt_mark_t_info), + print_help, + init, + parse, + final_check, + print, + compare, + opts, +}; + +static void _init(void) __attribute__ ((constructor)); +static void _init(void) +{ + register_target(&mark_target); +} --- /dev/null Thu Aug 24 11:00:32 2000 +++ ebtables-v2.0-rc1.001/extensions/ebt_mark_m.c Sun Jul 21 17:12:04 2002 @@ -0,0 +1,123 @@ +#include +#include +#include +#include +#include +#include "../include/ebtables_u.h" +#include + +#define MARK '1' + +static struct option opts[] = +{ + { "mark" , required_argument, 0, MARK }, + { 0 } +}; + +static void print_help() +{ + printf( +"mark option:\n" +"--mark [!] [value][/mask]: Match nfmask value (see man page)\n"); +} + +static void init(struct ebt_entry_match *match) +{ + struct ebt_mark_m_info *markinfo = (struct ebt_mark_m_info *)match->data; + + markinfo->mark = 0; + markinfo->mask = 0; + markinfo->invert = 0; + markinfo->bitmask = 0; +} + +#define OPT_MARK 0x01 +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_mark_m_info *markinfo = (struct ebt_mark_m_info *) + (*match)->data; + char *end; + + switch (c) { + case MARK: + check_option(flags, MARK); + if (check_inverse(optarg)) + markinfo->invert = 1; + if (optind > argc) + print_error("No mark specified"); + markinfo->mark = strtoul(argv[optind - 1], &end, 0); + markinfo->bitmask = EBT_MARK_AND; + if (*end == '/') { + if (end == argv[optind - 1]) + markinfo->bitmask = EBT_MARK_OR; + markinfo->mask = strtoul(end+1, &end, 0); + } else + markinfo->mask = 0xffffffff; + if ( *end != '\0' || end == argv[optind - 1]) + print_error("Bad mark value '%s'", 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 hook_mask, unsigned int time) +{ +} + +static void print(const struct ebt_u_entry *entry, + const struct ebt_entry_match *match) +{ + struct ebt_mark_m_info *markinfo = + (struct ebt_mark_m_info *)match->data; + + printf("--mark "); + if (markinfo->invert) + printf("! "); + if (markinfo->bitmask == EBT_MARK_OR) + printf("/0x%lx ", markinfo->mask); + else if(markinfo->mask != 0xffffffff) + printf("0x%lx/0x%lx ", markinfo->mark, markinfo->mask); + else + printf("0x%lx ", markinfo->mark); +} + +static int compare(const struct ebt_entry_match *m1, + const struct ebt_entry_match *m2) +{ + struct ebt_mark_m_info *markinfo1 = (struct ebt_mark_m_info *)m1->data; + struct ebt_mark_m_info *markinfo2 = (struct ebt_mark_m_info *)m2->data; + + if (markinfo1->invert != markinfo2->invert) + return 0; + if (markinfo1->mark != markinfo2->mark) + return 0; + if (markinfo1->mask != markinfo2->mask) + return 0; + if (markinfo1->bitmask != markinfo2->bitmask) + return 0; + return 1; +} + +static struct ebt_u_match mark_match = +{ + EBT_MARK_MATCH, + sizeof(struct ebt_mark_m_info), + print_help, + init, + parse, + final_check, + print, + compare, + opts, +}; + +static void _init(void) __attribute((constructor)); +static void _init(void) +{ + register_match(&mark_match); +} --- ebtables-v2.0pre10/extensions/Makefile Thu Jun 27 18:53:55 2002 +++ ebtables-v2.0-rc1.001/extensions/Makefile Sat Jul 20 15:34:51 2002 @@ -1,6 +1,6 @@ #! /usr/bin/make -EXT_FUNC+=nat arp ip standard log redirect vlan +EXT_FUNC+=nat arp ip standard log redirect vlan mark_m mark EXT_TABLES+=filter nat broute EXT_OBJS+=$(foreach T,$(EXT_FUNC), extensions/ebt_$(T).o) EXT_OBJS+=$(foreach T,$(EXT_TABLES), extensions/ebtable_$(T).o) --- ebtables-v2.0pre10/ChangeLog Sun Jul 14 21:30:18 2002 +++ ebtables-v2.0-rc1.001/ChangeLog Tue Jul 30 23:05:30 2002 @@ -1,3 +1,16 @@ +20020730 + * other things done before 2.0-rc1 that I can think of, + including kernel: + * cache align counters for better smp performance + * simplify snat code + * check for --xxxx-target RETURN on base chain + * cleanup code + * minor bugfixes +20020724 + * code cleanup + * bugfix for --atomic-commit +20020720 + * added mark target+match 20020714 * added --atomic options 20020710 --- ebtables-v2.0pre10/ebtables.8 Mon Jul 15 21:45:55 2002 +++ ebtables-v2.0-rc1.001/ebtables.8 Thu Jul 25 17:01:17 2002 @@ -1,4 +1,4 @@ -.TH EBTABLES 8 "26 June 2002" +.TH EBTABLES 8 "23 July 2002" .\" .\" Man page written by Bart De Schuymer .\" It is based on the iptables man page. @@ -21,7 +21,7 @@ .\" .\" .SH NAME -ebtables (v.2.0) \- ethernet bridge packet table administration +ebtables (v.2.0) \- Ethernet bridge packet table administration .SH SYNOPSIS .BR "ebtables -[ADI] " "chain rule-specification " [ options ] .br @@ -335,7 +335,7 @@ .B ebtables will try to write help about those extensions. E.g. ebtables -h snat log ip arp. .TP -.BR "-b --db [" "y/n" "]" +.BR "-b --db " [ "y/n" ] Enable (y) or disable (n) the database. .TP .BR "-j, --jump " "\fItarget\fP" @@ -346,13 +346,13 @@ or a target extension, see .BR "TARGET EXTENSIONS" . .TP -.BR "--atomic " file +.B --atomic file Let the command operate on the specified file. The data of the table to operate on will be extracted from the file and the result of the operation will be saved back into the file. If specified, this option should come before the command specification. .TP -.BR "-M, --modprobe " "program" +.B -M, --modprobe program When talking to the kernel, use this program to try to automatically load missing kernel modules. .SH MATCH EXTENSIONS @@ -390,7 +390,8 @@ .BR ARP " or " RARP . .TP .BR "--arp-opcode " "[!] \fIopcode\fP" -The (r)arp opcode (decimal or a string, for more details see ebtables -h arp). +The (r)arp opcode (decimal or a string, for more details see +.BR "ebtables -h arp" ). .TP .BR "--arp-htype " "[!] \fIhardware type\fP" The hardware type, this can be a decimal or the string "Ethernet". This @@ -419,13 +420,24 @@ Required VID to be 0 (null VID) or not specified vlan-id parameter (in this case VID deliberately be set to 0). .TP .BR "--vlan-encap " "[!] \fItype\fP" -The encapsulated ethernet frame type/length, this can be a hexadecimal number from 0x0000 to 0xFFFF. +The encapsulated Ethernet frame type/length, this can be a hexadecimal +number from 0x0000 to 0xFFFF. Usually it's 0x0800 (IPv4). See also .B /etc/ethertypes file. +.SS mark_m +.TP +.BR "--mark " "[!] [\fIvalue\fP][/\fImask\fP]" +Matches frames with the given unsigned mark value. If a mark value and +mask is specified, the logical AND of the mark value of the frame and +the user specified mask is taken before comparing with the user specified +mark value. If only a mask is specified (start with '/') the logical AND +of the mark value of the frame and the user specified mark is taken and +the result is compared with zero. + .SH WATCHER EXTENSION(S) -Watchers are things that only look at frames passing by. These watchers only see the -frame if the frame passes all the matches of the rule. +Watchers are things that only look at frames passing by. These watchers only +see the frame if the frame passes all the matches of the rule. .SS log The fact that the log module is a watcher lets us log stuff while giving a target by choice. Note that the log module therefore is not a target. @@ -478,7 +490,7 @@ The default target is ACCEPT. Making it CONTINUE could let you use multiple target extensions on the same frame. Making it DROP doesn't make sense, but you could do that too. RETURN is also allowed. Note -that using RETURN in a base chain will result in the CONTINUE behaviour. +that using RETURN in a base chain is not allowed. .TP .B dnat The @@ -504,7 +516,7 @@ multiple target extensions on the same frame. Making it DROP only makes sense in the BROUTING chain but using the redirect target is more logical there. RETURN is also allowed. Note -that using RETURN in a base chain will result in the CONTINUE behaviour. +that using RETURN in a base chain is not allowed. .TP .B redirect The @@ -523,7 +535,28 @@ The default target is ACCEPT. Making it CONTINUE could let you use multiple target extensions on the same frame. Making it DROP in the BROUTING chain will let the frames be routed. RETURN is also allowed. Note -that using RETURN in a base chain will result in the CONTINUE behaviour. +that using RETURN in a base chain is not allowed. +.TP +.B mark +The mark target can be used in every chain of every table. It is possible +to use the marking of a frame/packet in both ebtables and iptables, +if the br-nf code is compiled into the kernel. Both put the marking at the +same place. So, you can consider this fact as a feature, or as something to +watch out for. +.br +.BR "--mark-target " "\fItarget\fP" +.br +Specifies the standard target. After marking the frame, the rule +still has to give a standard target so +.B ebtables +knows what to do. +The default target is ACCEPT. Making it CONTINUE can let you do other +things with the frame in other rules of the chain. +.br +.BR "--set-mark " "\fIvalue\fP" +.br +Mark the frame with the specified unsigned value. +.br .SH FILES .I /etc/ethertypes .SH BUGS --- ebtables-v2.0pre10/ethertypes Thu Jun 27 18:53:55 2002 +++ ebtables-v2.0-rc1.001/ethertypes Fri Jul 19 20:44:25 2002 @@ -3,15 +3,14 @@ # all protocol numbers are in hexadecimal form # maximum namesize = 20 characters # always put tabs or spaces between the name and the protocol number -# don't use more than 4 digits for the protocol number +# anything on a line after the protocol number is ignored # programs using this file should not be case sensitive -# that's all :-)) -IPV4 0800 put your comments behind, on the same line, after a tab -X25 0805 or whitespace +IPv4 0800 +X25 0805 ARP 0806 802_1Q 8100 802.1Q Virtual LAN tagged frame IPX 8137 -IPV6 86DD +IPv6 86DD NetBEUI 8191 BPQ 08FF G8BPQ AX.25 Ethernet Packet DEC 6000 DEC Assigned proto --- ebtables-v2.0pre10/include/ebtables_u.h Sat Jul 13 21:13:46 2002 +++ ebtables-v2.0-rc1.001/include/ebtables_u.h Fri Jul 26 14:03:04 2002 @@ -29,7 +29,7 @@ struct ebt_u_entries { int policy; - __u32 nentries; + unsigned int nentries; // counter offset for this chain unsigned int counter_offset; // used for udc @@ -42,7 +42,7 @@ { struct ebt_u_entries *udc; struct ebt_u_chain_list *next; - // this is only used internally, in communications.c + // this is only used internally, in communication.c char *kernel_start; }; @@ -68,6 +68,8 @@ int selected_hook; // used for the atomic option char *filename; + // tells what happened to the old rules + unsigned short *counterchanges; }; struct ebt_u_table @@ -92,17 +94,17 @@ struct ebt_u_entry { - __u32 bitmask; - __u32 invflags; + unsigned int bitmask; + unsigned int invflags; __u16 ethproto; - __u8 in[IFNAMSIZ]; - __u8 logical_in[IFNAMSIZ]; - __u8 out[IFNAMSIZ]; - __u8 logical_out[IFNAMSIZ]; - __u8 sourcemac[ETH_ALEN]; - __u8 sourcemsk[ETH_ALEN]; - __u8 destmac[ETH_ALEN]; - __u8 destmsk[ETH_ALEN]; + char in[IFNAMSIZ]; + char logical_in[IFNAMSIZ]; + char out[IFNAMSIZ]; + char logical_out[IFNAMSIZ]; + unsigned char sourcemac[ETH_ALEN]; + unsigned char sourcemsk[ETH_ALEN]; + unsigned char destmac[ETH_ALEN]; + unsigned char destmsk[ETH_ALEN]; struct ebt_u_match_list *m_list; struct ebt_u_watcher_list *w_list; struct ebt_entry_target *t; @@ -194,8 +196,7 @@ struct ebt_u_match *find_match(const char *name); struct ebt_u_watcher *find_watcher(const char *name); struct ebt_u_table *find_table(char *name); -void deliver_counters(struct ebt_u_replace *repl, - unsigned short * counterchanges); +void deliver_counters(struct ebt_u_replace *repl); void deliver_table(struct ebt_u_replace *repl); void get_dbinfo(struct brdb_dbinfo *nr); void get_db(int len, struct brdb_dbentry *db);