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 *info = (struct ebt_among_info *) (*match)->data; struct ebt_mac_wormhash *wh; struct ebt_entry_match *h; int new_size, old_size; switch (c) { case AMONG_DST: case AMONG_SRC: if (c == AMONG_DST) { ebt_check_option2(flags, OPT_DST); } else { ebt_check_option2(flags, OPT_SRC); } if (ebt_check_inverse2(optarg)) { if (c == AMONG_DST) info->bitmask |= EBT_AMONG_DST_NEG; else info->bitmask |= EBT_AMONG_SRC_NEG; } wh = create_wormhash(optarg); if (ebt_errormsg[0] != '\0') break; old_size = sizeof(struct ebt_entry_match) + (**match).match_size; h = malloc((new_size = old_size + ebt_mac_wormhash_size(wh))); if (!h) ebt_print_memory(); memcpy(h, *match, old_size); memcpy((char *) h + old_size, wh, ebt_mac_wormhash_size(wh)); h->match_size = new_size - sizeof(struct ebt_entry_match); info = (struct ebt_among_info *) h->data; if (c == AMONG_DST) { info->wh_dst_ofs = old_size - sizeof(struct ebt_entry_match); } else { info->wh_src_ofs = old_size - sizeof(struct ebt_entry_match); } free(*match); *match = h; free(wh); break; default: return 0; } return 1; }
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 *info = (struct ebt_among_info *) (*match)->data; struct ebt_mac_wormhash *wh; struct ebt_entry_match *h; int new_size; long flen; int fd; switch (c) { case AMONG_DST_F: case AMONG_SRC_F: case AMONG_DST: case AMONG_SRC: if (c == AMONG_DST || c == AMONG_DST_F) { ebt_check_option2(flags, OPT_DST); } else { ebt_check_option2(flags, OPT_SRC); } if (ebt_check_inverse2(optarg)) { if (c == AMONG_DST || c == AMONG_DST_F) info->bitmask |= EBT_AMONG_DST_NEG; else info->bitmask |= EBT_AMONG_SRC_NEG; } if (c == AMONG_DST_F || c == AMONG_SRC_F) { struct stat stats; if ((fd = open(optarg, O_RDONLY)) == -1) ebt_print_error("Couldn't open file '%s'", optarg); fstat(fd, &stats); flen = stats.st_size; /* use mmap because the file will probably be big */ optarg = mmap(0, flen, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); if (optarg == MAP_FAILED) ebt_print_error("Couldn't map file to memory"); if (optarg[flen-1] != '\n') ebt_print_error("File should end with a newline"); if (strchr(optarg, '\n') != optarg+flen-1) ebt_print_error("File should only contain one line"); optarg[flen-1] = '\0'; if (ebt_errormsg[0] != '\0') { munmap(argv, flen); close(fd); exit(-1); } } wh = create_wormhash(optarg); if (ebt_errormsg[0] != '\0') break; new_size = old_size+ebt_mac_wormhash_size(wh); h = malloc(sizeof(struct ebt_entry_match)+EBT_ALIGN(new_size)); if (!h) ebt_print_memory(); memcpy(h, *match, old_size+sizeof(struct ebt_entry_match)); memcpy((char *)h+old_size+sizeof(struct ebt_entry_match), wh, ebt_mac_wormhash_size(wh)); h->match_size = EBT_ALIGN(new_size); info = (struct ebt_among_info *) h->data; if (c == AMONG_DST) { info->wh_dst_ofs = old_size; } else { info->wh_src_ofs = old_size; } old_size = new_size; free(*match); *match = h; free(wh); if (c == AMONG_DST_F || c == AMONG_SRC_F) { munmap(argv, flen); close(fd); } break; default: return 0; } return 1; }