diff options
Diffstat (limited to 'tools/remus/imqebt/communication.c')
-rw-r--r-- | tools/remus/imqebt/communication.c | 762 |
1 files changed, 0 insertions, 762 deletions
diff --git a/tools/remus/imqebt/communication.c b/tools/remus/imqebt/communication.c deleted file mode 100644 index 0c58c8fbe4..0000000000 --- a/tools/remus/imqebt/communication.c +++ /dev/null @@ -1,762 +0,0 @@ -/* - * communication.c, v2.0 July 2002 - * - * Author: Bart De Schuymer - * - */ - -/* - * All the userspace/kernel communication is in this file. - * The other code should not have to know anything about the way the - * kernel likes the structure of the table data. - * The other code works with linked lists. So, the translation is done here. - */ - -#include <getopt.h> -#include <string.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <unistd.h> -#include <sys/socket.h> -#include "include/ebtables_u.h" - -extern char* hooknames[NF_BR_NUMHOOKS]; - -#ifdef KERNEL_64_USERSPACE_32 -#define sparc_cast (uint64_t) -#else -#define sparc_cast -#endif - -int sockfd = -1; - -static int get_sockfd(void) -{ - int ret = 0; - if (sockfd == -1) { - sockfd = socket(AF_INET, SOCK_RAW, PF_INET); - if (sockfd < 0) { - ebt_print_error("Problem getting a socket, " - "you probably don't have the right " - "permissions"); - ret = -1; - } - } - return ret; -} - -static struct ebt_replace *translate_user2kernel(struct ebt_u_replace *u_repl) -{ - struct ebt_replace *new; - struct ebt_u_entry *e; - struct ebt_u_match_list *m_l; - struct ebt_u_watcher_list *w_l; - struct ebt_u_entries *entries; - char *p, *base; - int i, j; - unsigned int entries_size = 0, *chain_offsets; - - new = (struct ebt_replace *)malloc(sizeof(struct ebt_replace)); - if (!new) - ebt_print_memory(); - new->valid_hooks = u_repl->valid_hooks; - strcpy(new->name, u_repl->name); - new->nentries = u_repl->nentries; - new->num_counters = u_repl->num_counters; - new->counters = sparc_cast u_repl->counters; - chain_offsets = (unsigned int *)malloc(u_repl->num_chains * sizeof(unsigned int)); - /* Determine size */ - for (i = 0; i < u_repl->num_chains; i++) { - if (!(entries = u_repl->chains[i])) - continue; - chain_offsets[i] = entries_size; - entries_size += sizeof(struct ebt_entries); - j = 0; - e = entries->entries->next; - while (e != entries->entries) { - j++; - entries_size += sizeof(struct ebt_entry); - m_l = e->m_list; - while (m_l) { - entries_size += m_l->m->match_size + - sizeof(struct ebt_entry_match); - m_l = m_l->next; - } - w_l = e->w_list; - while (w_l) { - entries_size += w_l->w->watcher_size + - sizeof(struct ebt_entry_watcher); - w_l = w_l->next; - } - entries_size += e->t->target_size + - sizeof(struct ebt_entry_target); - e = e->next; - } - /* A little sanity check */ - if (j != entries->nentries) - ebt_print_bug("Wrong nentries: %d != %d, hook = %s", j, - entries->nentries, entries->name); - } - - new->entries_size = entries_size; - p = (char *)malloc(entries_size); - if (!p) - ebt_print_memory(); - - /* Put everything in one block */ - new->entries = sparc_cast p; - for (i = 0; i < u_repl->num_chains; i++) { - struct ebt_entries *hlp; - - hlp = (struct ebt_entries *)p; - if (!(entries = u_repl->chains[i])) - continue; - if (i < NF_BR_NUMHOOKS) - new->hook_entry[i] = sparc_cast hlp; - hlp->nentries = entries->nentries; - hlp->policy = entries->policy; - strcpy(hlp->name, entries->name); - hlp->counter_offset = entries->counter_offset; - hlp->distinguisher = 0; /* Make the kernel see the light */ - p += sizeof(struct ebt_entries); - e = entries->entries->next; - while (e != entries->entries) { - struct ebt_entry *tmp = (struct ebt_entry *)p; - - tmp->bitmask = e->bitmask | EBT_ENTRY_OR_ENTRIES; - tmp->invflags = e->invflags; - tmp->ethproto = e->ethproto; - 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, - sizeof(tmp->sourcemsk)); - memcpy(tmp->destmac, e->destmac, sizeof(tmp->destmac)); - memcpy(tmp->destmsk, e->destmsk, sizeof(tmp->destmsk)); - - base = p; - p += sizeof(struct ebt_entry); - m_l = e->m_list; - while (m_l) { - memcpy(p, m_l->m, m_l->m->match_size + - sizeof(struct ebt_entry_match)); - p += m_l->m->match_size + - sizeof(struct ebt_entry_match); - m_l = m_l->next; - } - tmp->watchers_offset = p - base; - w_l = e->w_list; - while (w_l) { - memcpy(p, w_l->w, w_l->w->watcher_size + - sizeof(struct ebt_entry_watcher)); - p += w_l->w->watcher_size + - sizeof(struct ebt_entry_watcher); - w_l = w_l->next; - } - tmp->target_offset = p - base; - memcpy(p, e->t, e->t->target_size + - sizeof(struct ebt_entry_target)); - if (!strcmp(e->t->u.name, EBT_STANDARD_TARGET)) { - struct ebt_standard_target *st = - (struct ebt_standard_target *)p; - /* Translate the jump to a udc */ - if (st->verdict >= 0) - st->verdict = chain_offsets - [st->verdict + NF_BR_NUMHOOKS]; - } - p += e->t->target_size + - sizeof(struct ebt_entry_target); - tmp->next_offset = p - base; - e = e->next; - } - } - - /* Sanity check */ - if (p - (char *)new->entries != new->entries_size) - ebt_print_bug("Entries_size bug"); - free(chain_offsets); - return new; -} - -static void store_table_in_file(char *filename, struct ebt_replace *repl) -{ - char *data; - int size; - int fd; - - /* Start from an empty file with right priviliges */ - if (!(fd = creat(filename, 0600))) { - ebt_print_error("Couldn't create file %s", filename); - return; - } - - size = sizeof(struct ebt_replace) + repl->entries_size + - repl->nentries * sizeof(struct ebt_counter); - data = (char *)malloc(size); - if (!data) - ebt_print_memory(); - memcpy(data, repl, sizeof(struct ebt_replace)); - memcpy(data + sizeof(struct ebt_replace), (char *)repl->entries, - repl->entries_size); - /* Initialize counters to zero, deliver_counters() can update them */ - memset(data + sizeof(struct ebt_replace) + repl->entries_size, - 0, repl->nentries * sizeof(struct ebt_counter)); - if (write(fd, data, size) != size) - ebt_print_error("Couldn't write everything to file %s", - filename); - close(fd); - free(data); -} - -void ebt_deliver_table(struct ebt_u_replace *u_repl) -{ - socklen_t optlen; - struct ebt_replace *repl; - - /* Translate the struct ebt_u_replace to a struct ebt_replace */ - repl = translate_user2kernel(u_repl); - if (u_repl->filename != NULL) { - store_table_in_file(u_repl->filename, repl); - goto free_repl; - } - /* Give the data to the kernel */ - optlen = sizeof(struct ebt_replace) + repl->entries_size; - if (get_sockfd()) - goto free_repl; - if (!setsockopt(sockfd, IPPROTO_IP, EBT_SO_SET_ENTRIES, repl, optlen)) - goto free_repl; - if (u_repl->command == 8) { /* The ebtables module may not - * yet be loaded with --atomic-commit */ - ebtables_insmod("ebtables"); - if (!setsockopt(sockfd, IPPROTO_IP, EBT_SO_SET_ENTRIES, - repl, optlen)) - goto free_repl; - } - - ebt_print_error("The kernel doesn't support a certain ebtables" - " extension, consider recompiling your kernel or insmod" - " the extension"); -free_repl: - if (repl) { - free(repl->entries); - free(repl); - } -} - -static int store_counters_in_file(char *filename, struct ebt_u_replace *repl) -{ - int size = repl->nentries * sizeof(struct ebt_counter), ret = 0; - unsigned int entries_size; - struct ebt_replace hlp; - FILE *file; - - if (!(file = fopen(filename, "r+b"))) { - ebt_print_error("Could not open file %s", filename); - return -1; - } - /* Find out entries_size and then set the file pointer to the - * counters */ - if (fseek(file, (char *)(&hlp.entries_size) - (char *)(&hlp), SEEK_SET) - || fread(&entries_size, sizeof(char), sizeof(unsigned int), file) != - sizeof(unsigned int) || - fseek(file, entries_size + sizeof(struct ebt_replace), SEEK_SET)) { - ebt_print_error("File %s is corrupt", filename); - ret = -1; - goto close_file; - } - if (fwrite(repl->counters, sizeof(char), size, file) != size) { - ebt_print_error("Could not write everything to file %s", - filename); - ret = -1; - } -close_file: - fclose(file); - return 0; -} - -/* Gets executed after ebt_deliver_table. Delivers the counters to the kernel - * and resets the counterchanges to CNT_NORM */ -void ebt_deliver_counters(struct ebt_u_replace *u_repl) -{ - struct ebt_counter *old, *new, *newcounters; - socklen_t optlen; - struct ebt_replace repl; - struct ebt_cntchanges *cc = u_repl->cc->next, *cc2; - struct ebt_u_entries *entries = NULL; - struct ebt_u_entry *next = NULL; - int i, chainnr = 0; - - if (u_repl->nentries == 0) - return; - - newcounters = (struct ebt_counter *) - malloc(u_repl->nentries * sizeof(struct ebt_counter)); - if (!newcounters) - ebt_print_memory(); - memset(newcounters, 0, u_repl->nentries * sizeof(struct ebt_counter)); - old = u_repl->counters; - new = newcounters; - while (cc != u_repl->cc) { - if (!next || next == entries->entries) { - while (chainnr < u_repl->num_chains && (!(entries = u_repl->chains[chainnr++]) || - (next = entries->entries->next) == entries->entries)); - if (chainnr == u_repl->num_chains) - break; - } - if (cc->type == CNT_NORM) { - /* 'Normal' rule, meaning we didn't do anything to it - * So, we just copy */ - *new = *old; - next->cnt = *new; - next->cnt_surplus.pcnt = next->cnt_surplus.bcnt = 0; - old++; /* We've used an old counter */ - new++; /* We've set a new counter */ - next = next->next; - } else if (cc->type == CNT_DEL) { - old++; /* Don't use this old counter */ - } else { - if (cc->type == CNT_CHANGE) { - if (cc->change % 3 == 1) - new->pcnt = old->pcnt + next->cnt_surplus.pcnt; - else if (cc->change % 3 == 2) - new->pcnt = old->pcnt - next->cnt_surplus.pcnt; - else - new->pcnt = next->cnt.pcnt; - if (cc->change / 3 == 1) - new->bcnt = old->bcnt + next->cnt_surplus.bcnt; - else if (cc->change / 3 == 2) - new->bcnt = old->bcnt - next->cnt_surplus.bcnt; - else - new->bcnt = next->cnt.bcnt; - } else - *new = next->cnt; - next->cnt = *new; - next->cnt_surplus.pcnt = next->cnt_surplus.bcnt = 0; - if (cc->type == CNT_ADD) - new++; - else { - old++; - new++; - } - next = next->next; - } - cc = cc->next; - } - - free(u_repl->counters); - u_repl->counters = newcounters; - u_repl->num_counters = u_repl->nentries; - /* Reset the counterchanges to CNT_NORM and delete the unused cc */ - i = 0; - cc = u_repl->cc->next; - while (cc != u_repl->cc) { - if (cc->type == CNT_DEL) { - cc->prev->next = cc->next; - cc->next->prev = cc->prev; - cc2 = cc->next; - free(cc); - cc = cc2; - } else { - cc->type = CNT_NORM; - cc->change = 0; - i++; - cc = cc->next; - } - } - if (i != u_repl->nentries) - ebt_print_bug("i != u_repl->nentries"); - if (u_repl->filename != NULL) { - store_counters_in_file(u_repl->filename, u_repl); - return; - } - optlen = u_repl->nentries * sizeof(struct ebt_counter) + - sizeof(struct ebt_replace); - /* Now put the stuff in the kernel's struct ebt_replace */ - repl.counters = sparc_cast u_repl->counters; - repl.num_counters = u_repl->num_counters; - memcpy(repl.name, u_repl->name, sizeof(repl.name)); - - if (get_sockfd()) - return; - if (setsockopt(sockfd, IPPROTO_IP, EBT_SO_SET_COUNTERS, &repl, optlen)) - ebt_print_bug("Couldn't update kernel counters"); -} - -static int -ebt_translate_match(struct ebt_entry_match *m, struct ebt_u_match_list ***l) -{ - struct ebt_u_match_list *new; - int ret = 0; - - new = (struct ebt_u_match_list *) - malloc(sizeof(struct ebt_u_match_list)); - if (!new) - ebt_print_memory(); - new->m = (struct ebt_entry_match *) - malloc(m->match_size + sizeof(struct ebt_entry_match)); - if (!new->m) - ebt_print_memory(); - memcpy(new->m, m, m->match_size + sizeof(struct ebt_entry_match)); - new->next = NULL; - **l = new; - *l = &new->next; - if (ebt_find_match(new->m->u.name) == NULL) { - ebt_print_error("Kernel match %s unsupported by userspace tool", - new->m->u.name); - ret = -1; - } - return ret; -} - -static int -ebt_translate_watcher(struct ebt_entry_watcher *w, - struct ebt_u_watcher_list ***l) -{ - struct ebt_u_watcher_list *new; - int ret = 0; - - new = (struct ebt_u_watcher_list *) - malloc(sizeof(struct ebt_u_watcher_list)); - if (!new) - ebt_print_memory(); - new->w = (struct ebt_entry_watcher *) - malloc(w->watcher_size + sizeof(struct ebt_entry_watcher)); - if (!new->w) - ebt_print_memory(); - memcpy(new->w, w, w->watcher_size + sizeof(struct ebt_entry_watcher)); - new->next = NULL; - **l = new; - *l = &new->next; - if (ebt_find_watcher(new->w->u.name) == NULL) { - ebt_print_error("Kernel watcher %s unsupported by userspace " - "tool", new->w->u.name); - ret = -1; - } - return ret; -} - -static int -ebt_translate_entry(struct ebt_entry *e, int *hook, int *n, int *cnt, - int *totalcnt, struct ebt_u_entry **u_e, struct ebt_u_replace *u_repl, - unsigned int valid_hooks, char *base, struct ebt_cntchanges **cc) -{ - /* An entry */ - if (e->bitmask & EBT_ENTRY_OR_ENTRIES) { - struct ebt_u_entry *new; - struct ebt_u_match_list **m_l; - struct ebt_u_watcher_list **w_l; - struct ebt_entry_target *t; - - new = (struct ebt_u_entry *)malloc(sizeof(struct ebt_u_entry)); - if (!new) - ebt_print_memory(); - new->bitmask = e->bitmask; - /* - * Plain userspace code doesn't know about - * EBT_ENTRY_OR_ENTRIES - */ - new->bitmask &= ~EBT_ENTRY_OR_ENTRIES; - new->invflags = e->invflags; - new->ethproto = e->ethproto; - 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)); - memcpy(new->destmsk, e->destmsk, sizeof(new->destmsk)); - if (*totalcnt >= u_repl->nentries) - ebt_print_bug("*totalcnt >= u_repl->nentries"); - new->cnt = u_repl->counters[*totalcnt]; - new->cnt_surplus.pcnt = new->cnt_surplus.bcnt = 0; - new->cc = *cc; - *cc = (*cc)->next; - new->m_list = NULL; - new->w_list = NULL; - new->next = (*u_e)->next; - new->next->prev = new; - (*u_e)->next = new; - new->prev = *u_e; - *u_e = new; - m_l = &new->m_list; - EBT_MATCH_ITERATE(e, ebt_translate_match, &m_l); - w_l = &new->w_list; - EBT_WATCHER_ITERATE(e, ebt_translate_watcher, &w_l); - - t = (struct ebt_entry_target *)(((char *)e) + e->target_offset); - new->t = (struct ebt_entry_target *) - malloc(t->target_size + sizeof(struct ebt_entry_target)); - if (!new->t) - ebt_print_memory(); - if (ebt_find_target(t->u.name) == NULL) { - ebt_print_error("Kernel target %s unsupported by " - "userspace tool", t->u.name); - return -1; - } - memcpy(new->t, t, t->target_size + - sizeof(struct ebt_entry_target)); - /* Deal with jumps to udc */ - if (!strcmp(t->u.name, EBT_STANDARD_TARGET)) { - char *tmp = base; - int verdict = ((struct ebt_standard_target *)t)->verdict; - int i; - - if (verdict >= 0) { - tmp += verdict; - for (i = NF_BR_NUMHOOKS; i < u_repl->num_chains; i++) - if (u_repl->chains[i]->kernel_start == tmp) - break; - if (i == u_repl->num_chains) - ebt_print_bug("Can't find udc for jump"); - ((struct ebt_standard_target *)new->t)->verdict = i-NF_BR_NUMHOOKS; - } - } - - (*cnt)++; - (*totalcnt)++; - return 0; - } else { /* A new chain */ - int i; - struct ebt_entries *entries = (struct ebt_entries *)e; - - if (*n != *cnt) - ebt_print_bug("Nr of entries in the chain is wrong"); - *n = entries->nentries; - *cnt = 0; - for (i = *hook + 1; i < NF_BR_NUMHOOKS; i++) - if (valid_hooks & (1 << i)) - break; - *hook = i; - *u_e = u_repl->chains[*hook]->entries; - return 0; - } -} - -/* Initialize all chain headers */ -static int -ebt_translate_chains(struct ebt_entry *e, int *hook, - struct ebt_u_replace *u_repl, unsigned int valid_hooks) -{ - int i; - struct ebt_entries *entries = (struct ebt_entries *)e; - struct ebt_u_entries *new; - - if (!(e->bitmask & EBT_ENTRY_OR_ENTRIES)) { - for (i = *hook + 1; i < NF_BR_NUMHOOKS; i++) - if (valid_hooks & (1 << i)) - break; - new = (struct ebt_u_entries *)malloc(sizeof(struct ebt_u_entries)); - if (!new) - ebt_print_memory(); - if (i == u_repl->max_chains) - ebt_double_chains(u_repl); - u_repl->chains[i] = new; - if (i >= NF_BR_NUMHOOKS) - new->kernel_start = (char *)e; - *hook = i; - new->nentries = entries->nentries; - new->policy = entries->policy; - new->entries = (struct ebt_u_entry *)malloc(sizeof(struct ebt_u_entry)); - if (!new->entries) - ebt_print_memory(); - new->entries->next = new->entries->prev = new->entries; - new->counter_offset = entries->counter_offset; - strcpy(new->name, entries->name); - } - return 0; -} - -static int retrieve_from_file(char *filename, struct ebt_replace *repl, - char command) -{ - FILE *file; - char *hlp = NULL, *entries; - struct ebt_counter *counters; - int size, ret = 0; - - if (!(file = fopen(filename, "r+b"))) { - ebt_print_error("Could not open file %s", filename); - return -1; - } - /* 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) + 1); - if (!hlp) - ebt_print_memory(); - strcpy(hlp, repl->name); - } - if (fread(repl, sizeof(char), sizeof(struct ebt_replace), file) - != sizeof(struct ebt_replace)) { - ebt_print_error("File %s is corrupt", filename); - ret = -1; - goto close_file; - } - if (command != 'L' && command != 8 && strcmp(hlp, repl->name)) { - ebt_print_error("File %s contains wrong table name or is " - "corrupt", filename); - ret = -1; - goto close_file; - } else if (!ebt_find_table(repl->name)) { - ebt_print_error("File %s contains invalid table name", - filename); - ret = -1; - goto close_file; - } - - size = sizeof(struct ebt_replace) + - repl->nentries * sizeof(struct ebt_counter) + repl->entries_size; - fseek(file, 0, SEEK_END); - if (size != ftell(file)) { - ebt_print_error("File %s has wrong size", filename); - ret = -1; - goto close_file; - } - entries = (char *)malloc(repl->entries_size); - if (!entries) - ebt_print_memory(); - repl->entries = sparc_cast entries; - if (repl->nentries) { - counters = (struct ebt_counter *) - malloc(repl->nentries * sizeof(struct ebt_counter)); - repl->counters = sparc_cast counters; - if (!repl->counters) - ebt_print_memory(); - } else - repl->counters = sparc_cast NULL; - /* Copy entries and counters */ - if (fseek(file, sizeof(struct ebt_replace), SEEK_SET) || - fread((char *)repl->entries, sizeof(char), repl->entries_size, file) - != repl->entries_size || - fseek(file, sizeof(struct ebt_replace) + repl->entries_size, - SEEK_SET) - || fread((char *)repl->counters, sizeof(char), - repl->nentries * sizeof(struct ebt_counter), file) - != repl->nentries * sizeof(struct ebt_counter)) { - ebt_print_error("File %s is corrupt", filename); - free(entries); - repl->entries = NULL; - ret = -1; - } -close_file: - fclose(file); - free(hlp); - return ret; -} - -static int retrieve_from_kernel(struct ebt_replace *repl, char command, - int init) -{ - socklen_t optlen; - int optname; - char *entries; - - optlen = sizeof(struct ebt_replace); - if (get_sockfd()) - return -1; - /* --atomic-init || --init-table */ - if (init) - optname = EBT_SO_GET_INIT_INFO; - else - optname = EBT_SO_GET_INFO; - if (getsockopt(sockfd, IPPROTO_IP, optname, repl, &optlen)) - return -1; - - if ( !(entries = (char *)malloc(repl->entries_size)) ) - ebt_print_memory(); - repl->entries = sparc_cast entries; - if (repl->nentries) { - struct ebt_counter *counters; - - if (!(counters = (struct ebt_counter *) - malloc(repl->nentries * sizeof(struct ebt_counter))) ) - ebt_print_memory(); - repl->counters = sparc_cast counters; - } - else - repl->counters = sparc_cast NULL; - - /* We want to receive the counters */ - repl->num_counters = repl->nentries; - optlen += repl->entries_size + repl->num_counters * - sizeof(struct ebt_counter); - if (init) - optname = EBT_SO_GET_INIT_ENTRIES; - else - optname = EBT_SO_GET_ENTRIES; - if (getsockopt(sockfd, IPPROTO_IP, optname, repl, &optlen)) - ebt_print_bug("Hmm, what is wrong??? bug#1"); - - return 0; -} - -int ebt_get_table(struct ebt_u_replace *u_repl, int init) -{ - int i, j, k, hook; - struct ebt_replace repl; - struct ebt_u_entry *u_e = NULL; - struct ebt_cntchanges *new_cc, *cc; - - strcpy(repl.name, u_repl->name); - if (u_repl->filename != NULL) { - if (init) - ebt_print_bug("Getting initial table data from a file is impossible"); - if (retrieve_from_file(u_repl->filename, &repl, u_repl->command)) - return -1; - /* -L with a wrong table name should be dealt with silently */ - strcpy(u_repl->name, repl.name); - } else if (retrieve_from_kernel(&repl, u_repl->command, init)) - return -1; - - /* Translate the struct ebt_replace to a struct ebt_u_replace */ - u_repl->valid_hooks = repl.valid_hooks; - u_repl->nentries = repl.nentries; - u_repl->num_counters = repl.num_counters; - u_repl->counters = repl.counters; - u_repl->cc = (struct ebt_cntchanges *)malloc(sizeof(struct ebt_cntchanges)); - if (!u_repl->cc) - ebt_print_memory(); - u_repl->cc->next = u_repl->cc->prev = u_repl->cc; - cc = u_repl->cc; - for (i = 0; i < repl.nentries; i++) { - new_cc = (struct ebt_cntchanges *)malloc(sizeof(struct ebt_cntchanges)); - if (!new_cc) - ebt_print_memory(); - new_cc->type = CNT_NORM; - new_cc->change = 0; - new_cc->prev = cc; - cc->next = new_cc; - cc = new_cc; - } - if (repl.nentries) { - new_cc->next = u_repl->cc; - u_repl->cc->prev = new_cc; - } - u_repl->chains = (struct ebt_u_entries **)calloc(EBT_ORI_MAX_CHAINS, sizeof(void *)); - u_repl->max_chains = EBT_ORI_MAX_CHAINS; - hook = -1; - /* FIXME: Clean up when an error is encountered */ - EBT_ENTRY_ITERATE(repl.entries, repl.entries_size, ebt_translate_chains, - &hook, u_repl, u_repl->valid_hooks); - if (hook >= NF_BR_NUMHOOKS) - u_repl->num_chains = hook + 1; - else - u_repl->num_chains = NF_BR_NUMHOOKS; - i = 0; /* Holds the expected nr. of entries for the chain */ - j = 0; /* Holds the up to now counted entries for the chain */ - k = 0; /* Holds the total nr. of entries, should equal u_repl->nentries afterwards */ - cc = u_repl->cc->next; - hook = -1; - EBT_ENTRY_ITERATE((char *)repl.entries, repl.entries_size, - ebt_translate_entry, &hook, &i, &j, &k, &u_e, u_repl, - u_repl->valid_hooks, (char *)repl.entries, &cc); - if (k != u_repl->nentries) - ebt_print_bug("Wrong total nentries"); - free(repl.entries); - return 0; -} |