struct filter *convert_chaingroup_specifier(struct chaingroup_specifier_s *n, struct filtergen_opts *o) { struct filter *res = NULL, *sub = NULL; char *name = NULL; if (n->name) { name = n->name; } else { /* Allocate a filter name */ static int ccount = 0; if (asprintf(&name, "chain_%d", ccount++) < 0) { filter_error( n->pos, "error: asprintf allocation failed when creating a filter name " "for chain %d\n", ccount); } } if (n->list) { sub = convert_subrule_list(n->list, o); if (sub) { res = new_filter_subgroup(name, sub); } } else { filter_error(n->pos, "no list in chaingroup"); } if (res) res->pos = n->pos; free(n); return res; }
struct filter *convert_specifier(struct specifier_s *r, struct filtergen_opts *o) { struct filter *res = NULL; eprint("converting specifier\n"); if (r->compound) { eprint("converting compound specifier\n"); res = convert_compound_specifier(r->compound, o); } else if (r->direction) { res = convert_direction(r->direction, o); } else if (r->target) { enum filtertype type; eprint("converting target specifier\n"); switch (r->target->type) { case TOK_ACCEPT: type = T_ACCEPT; break; case TOK_REJECT: type = T_REJECT; break; case TOK_DROP: type = DROP; break; case TOK_MASQ: type = MASQ; break; case TOK_PROXY: type = REDIRECT; break; case TOK_REDIRECT: type = REDIRECT; break; default: filter_error(r->pos, "incorrect target type encountered"); type = YYEOF; break; } res = new_filter_target(type, r->pos); } else if (r->host) { res = convert_host_specifier(r->host, o); } else if (r->protocol) { res = convert_protocol_specifier(r->protocol, o); } else if (r->port) { res = convert_port_specifier(r->port, o); } else if (r->icmptype) { res = convert_icmptype_specifier(r->icmptype, o); } else if (r->option) { res = convert_option_specifier(r->option); } else if (r->chaingroup) { res = convert_chaingroup_specifier(r->chaingroup, o); } else { filter_error(r->pos, "no specifiers"); } if (res) res->pos = r->pos; free(r); return res; }
struct filter *convert_direction(struct direction_specifier_s *n, struct filtergen_opts *o) { struct filter *res = NULL; int type; eprint("converting direction specifier\n"); switch (n->type) { case TOK_INPUT: type = INPUT; break; case TOK_OUTPUT: type = OUTPUT; break; default: filter_error(n->pos, "incorrect direction type encountered"); type = YYEOF; break; } if (n->list) { res = new_filter_sibs(convert_direction_argument_list(n->list, type, o)); } else { filter_error(n->pos, "no direction argument list"); } if (res) res->pos = n->pos; free(n); return res; }
struct filter *convert_port_specifier(struct port_specifier_s *n, struct filtergen_opts *o) { struct filter *res = NULL; enum filtertype type; eprint("converting port specifier\n"); switch (n->type) { case TOK_SPORT: type = F_SPORT; break; case TOK_DPORT: type = F_DPORT; break; default: filter_error(n->pos, "incorrect port type encountered"); type = YYEOF; break; } if (n->list) { res = new_filter_sibs(convert_port_argument_list(n->list, type, o)); } else { filter_error(n->pos, "no port argument list"); } if (res) res->pos = n->pos; free(n); return res; }
struct filter *convert_subrule_list(struct subrule_list_s *n, struct filtergen_opts *o) { struct filter *res = NULL, *end = NULL; eprint("converting subrule_list\n"); if (n->subrule_list) { res = convert_subrule_list(n->subrule_list, o); if (res) { end = res; while (end->next) { end = end->next; } if (n->specifier_list) { end->next = convert_specifier_list(n->specifier_list, o); } } else { filter_error(n->pos, "warning: convert_subrule_list returned NULL"); } } else if (n->specifier_list) { res = convert_specifier_list(n->specifier_list, o); } else { filter_error(n->pos, "no content in subrule_list"); } if (res) res->pos = n->pos; free(n); return res; }
struct filter *convert_port_argument(struct port_argument_s *n, int type) { struct filter *res = NULL; char *p; eprint("converting port argument\n"); if (n->port_min) { if (n->port_max) { if (asprintf(&p, "%s:%s", n->port_min, n->port_max) < 0) { filter_error( n->pos, "error: asprintf allocation failed when emitting port range " "%s:%s\n", n->port_min, n->port_max); } } else { p = n->port_min; } res = new_filter_ports(type, p, n->pos); } else { filter_error(n->pos, "no port argument contents"); } if (res) res->pos = n->pos; free(n); return res; }
struct filter *convert_host_argument(struct host_argument_s *n, int type, struct filtergen_opts *o) { struct filter *res = NULL; char *h; eprint("converting host_argument\n"); if (n->host) { if (n->mask) { if (asprintf(&h, "%s/%s", n->host, n->mask) < 0) { filter_error(n->pos, "error: asprintf allocation failed when converting host " "argument %s/%s", n->host, n->mask); } } else { h = n->host; } res = new_filter_host(type, h, o->family, n->pos); } else { filter_error(n->pos, "no host part"); } if (res) res->pos = n->pos; free(n); return res; }
struct filter *convert_specifier_list(struct specifier_list_s *n, struct filtergen_opts *o) { struct filter *res = NULL, *end = NULL; eprint("converting specifier_list\n"); if (n->list) { res = convert_specifier_list(n->list, o); if (res) { end = res; while (end->child) { end = end->child; } if (n->spec) { end->child = convert_negated_specifier(n->spec, o); } } else { filter_error(n->pos, "warning: convert_specifier_list returned NULL"); } } else { if (n->spec) res = convert_negated_specifier(n->spec, o); } if (res) res->pos = n->pos; free(n); return res; }
struct filter *convert_option_specifier(struct option_specifier_s *n) { struct filter *res = NULL; eprint("converting option specifier\n"); switch (n->type) { case TOK_LOCAL: res = new_filter_rtype(LOCALONLY, n->pos); break; case TOK_FORWARD: res = new_filter_rtype(ROUTEDONLY, n->pos); break; case TOK_ONEWAY: res = new_filter_rtype(F_ONEWAY, n->pos); break; case TOK_LOG: res = new_filter_log(F_LOG, n->logmsg, n->pos); break; default: filter_error(n->pos, "incorrect option type encountered"); break; } if (res) res->pos = n->pos; free(n); return res; }
struct filter * convert_icmptype_argument_list(struct icmptype_argument_list_s *n, struct filtergen_opts *o) { struct filter *res = NULL, *end = NULL; eprint("converting icmptype argument list\n"); if (n->list) { res = convert_icmptype_argument_list(n->list, o); if (res) { end = res; while (end->next) { end = end->next; } if (n->arg) { end->next = convert_icmptype_argument(n->arg); } } else { filter_error(n->pos, "warning: convert_icmptype_argument_list returned NULL\n"); } } else { if (n->arg) res = convert_icmptype_argument(n->arg); } if (res) res->pos = n->pos; free(n); return res; }
struct filter *convert_direction_argument(struct direction_argument_s *n, int type) { struct filter *res = NULL; if (n->direction) { res = new_filter_device(type, n->direction, n->pos); } else { filter_error(n->pos, "no direction argument contents"); } if (res) res->pos = n->pos; free(n); return res; }
void Dictionary::fillDecodedString(unsigned code) { decodedString.clear(); unsigned int safety = 0; auto tableSize = table.size(); while (code != ~0U) { if (code >= tableSize) throw filter_error("LZW data is corrupted - " "codeword was larger than the number of entries in the dictionary!"); const CodeString& cs = table[code]; decodedString.push_back(cs.k); // Make sure this codeword's prefix is not itself, otherwise we'll get // stuck in an infinite loop! if (cs.prefixIndex == code) throw filter_error("LZW data is corrupted - " "codeword's prefix is itself, cannot continue as this would cause an " "infinite loop!"); code = cs.prefixIndex; if (++safety > tableSize * 2) { throw filter_error("LZW data is corrupted - searched through the " "dictionary twice but the code never mapped to a byte value!"); } } }
struct filter *convert_icmptype_argument(struct icmptype_argument_s *n) { struct filter *res = NULL; eprint("converting icmptype_argument\n"); if (n->icmptype) { res = new_filter_icmp(F_ICMPTYPE, n->icmptype, n->pos); } else { filter_error(n->pos, "no icmptype argument contents"); } if (res) res->pos = n->pos; free(n); return res; }
struct filter *convert_protocol_argument(struct protocol_argument_s *n) { struct filter *res = NULL; eprint("converting protocol argument\n"); if (n->proto) { res = new_filter_proto(F_PROTO, n->proto, n->pos); } else { filter_error(n->pos, "no protocol argument contents"); } if (res) res->pos = n->pos; free(n); return res; }
struct filter *convert_icmptype_specifier(struct icmptype_specifier_s *n, struct filtergen_opts *o) { struct filter *res = NULL; eprint("converting icmptype specifier\n"); if (n->list) { res = new_filter_sibs(convert_icmptype_argument_list(n->list, o)); } else { filter_error(n->pos, "no icmptype argument list"); } if (res) res->pos = n->pos; free(n); return res; }
/* include a file or directory */ void include_file(YYLTYPE *yylloc, const char *name) { struct stat st; struct dirent **namelist; char *fn; int n; struct sourceposition *pos; pos = make_sourcepos(yylloc); if (stat(name, &st)) { if (errno == ENOENT && (index(name, '*') != NULL || index(name, '?') != NULL || index(name, '[') != NULL)) { /* Globbing fiesta! */ glob_t glob_buf; if (glob(name, 0, NULL, &glob_buf) != 0) { filter_error(pos, "failed to glob \"%s\": %s", name, strerror(errno)); } else { /* We go through the list of files backwards, because * step_into_include_file() creates a stack of all the * files processed and then works on them in a LIFO * fashion -- which would make all of our rules files * go backwards. Since I can't wrap my head around * why that is, exactly, I'm hacking it up with * this instead. Fixination appreciated. */ for (n = glob_buf.gl_pathc - 1; n >= 0; n--) { if (stat(glob_buf.gl_pathv[n], &st)) { filter_error(pos, "stat failed on globbed \"%s\": %s", glob_buf.gl_pathv[n], strerror(errno)); } else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) { if (sourcefile_push(pos, glob_buf.gl_pathv[n])) { filtergen_in = current_srcfile->f; filtergen_lineno = current_srcfile->lineno; // yycolumn = current_srcfile->column; if (!filtergen_in) { filter_error(pos, "failed to open %s", glob_buf.gl_pathv[n]); } else { filtergen_push_buffer_state( filtergen__create_buffer(filtergen_in, YY_BUF_SIZE)); } } } } } globfree(&glob_buf); } else { filter_error(pos, "stat failed on \"%s\": %s", name, strerror(errno)); } } else { if (S_ISDIR(st.st_mode)) { char *b = strdup(name); char *base = basename(b); if (strcmp("/", base) == 0) { filter_error(pos, "cannot include / path; skipping"); free(b); return; } free(b); if ((n = scandir(name, &namelist, NULL, alphasort)) < 0) { filter_error(pos, "scandir failed on \"%s\": %s", name, strerror(errno)); } else { while (n--) { /* FIXME: assumes d_name */ if (namelist[n]->d_name[0] == '.') { free(namelist[n]); continue; } if (asprintf(&fn, "%s/%s", name, namelist[n]->d_name) < 0) { filter_error( NULL, "internal error: asprintf failed constructing pathname " "for included file \"%s\"", namelist[n]->d_name); free(fn); } else { include_file(yylloc, fn); free(fn); } free(namelist[n]); } free(namelist); } } else { if (sourcefile_push(pos, name)) { filtergen_in = current_srcfile->f; filtergen_lineno = current_srcfile->lineno; // yycolumn = current_srcfile->column; if (!filtergen_in) { filter_error(pos, "failed to open %s", name); } else { filtergen_push_buffer_state( filtergen__create_buffer(filtergen_in, YY_BUF_SIZE)); } } } } }
void filter_ccomic_unrle::transform(uint8_t *out, stream::len *lenOut, const uint8_t *in, stream::len *lenIn) { stream::len r = 0, w = 0; if ((lenBlock == 0) && (*lenIn != 0)) { // Need to read block size at start if (*lenIn - r < 2) throw filter_error("No room to read plane size"); this->lenBlock = *in++; this->lenBlock |= (*in++) << 8; r += 2; this->lenBlock *= 4; // number of planes } // While there's more space to write, and either more data to read or // more data to write while ( // while there is... (w < *lenOut) // more space to write into, and && ( (r+1 < *lenIn) // more data to read, or || (this->repeat) // more data to write without reading any more || ( this->escape // or there is escaped data && (r < *lenIn) // and one last byte in the buffer ) ) && lenBlock // and the format says there's data to read ) { // Write out any repeats we've got stored up while ((w < *lenOut) && this->repeat && lenBlock) { *out++ = this->val; this->repeat--; this->lenBlock--; w++; } // Write out any escaped data while ((r < *lenIn) && (w < *lenOut) && this->escape && lenBlock) { *out++ = *in++; this->escape--; this->lenBlock--; r++; w++; } // Loop while there's no bytes to write but more to read while ((this->repeat == 0) && (this->escape == 0) && (r < *lenIn - 1) && lenBlock) { if (*in & 0x80) { // RLE trigger this->repeat = (*in++) & 0x7F; this->val = *in++; r += 2; } else { // escaped byte this->escape = *in++; r++; } } } *lenOut = w; *lenIn = r; return; }
void filter_z66_decompress::transform(uint8_t *out, stream::len *lenOut, const uint8_t *in, stream::len *lenIn) { stream::len r = 0, w = 0; fn_getnextchar cbNext = boost::bind(&filter_z66_decompress::nextChar, this, &in, lenIn, &r, _1); while ( (w < *lenOut) // while there is more space to write into && ( (r + 2 < *lenIn) // and there's at least two more bytes to read || ( (*lenIn < 10) // or there's less than 10 bytes to read in this buffer (i.e. near EOF) && (r < *lenIn) // and there's at least one more byte to read ) || (this->state > 1) // or we're still processing what we read previously ) && (this->totalWritten < this->outputLimit) // and we haven't reached the target file size yet ) { switch (this->state) { case 0: { // Read the first four bytes (decompressed size) so we can limit the // output size appropriately. this->data.changeEndian(bitstream::littleEndian); this->data.read(cbNext, 32, &this->outputLimit); this->data.changeEndian(bitstream::bigEndian); this->state++; break; } case 1: { if (this->data.read(cbNext, this->codeLength, &this->code) != this->codeLength) { goto done; } this->curCode = this->code; this->state++; break; } case 2: if (this->curCode < 256) { *out++ = this->curCode; w++; this->totalWritten++; if (!this->stack.empty()) { this->curCode = this->stack.top(); this->stack.pop(); } else { this->state++; break; } } else { this->curCode -= 256; this->stack.push(this->nodes[this->curCode].nextCode); this->curCode = this->nodes[this->curCode].code; if (this->stack.size() > 65534) { throw filter_error("Corrupted Zone 66 data - token stack > 64k"); } } break; case 3: { unsigned int value; if (this->data.read(cbNext, 8, &value) != 8) goto done; *out++ = value; w++; this->totalWritten++; if (this->code >= 0x100u + this->curDicIndex) { // This code hasn't been put in the dictionary yet (tpal.z66) this->code = 0x100; } nodes[this->curDicIndex].code = this->code; nodes[this->curDicIndex].nextCode = value; this->curDicIndex++; if (this->curDicIndex >= this->maxDicIndex) { this->codeLength++; if (this->codeLength == 13) { this->codeLength = 9; this->curDicIndex = 64; this->maxDicIndex = 255; } else { this->maxDicIndex = (1 << this->codeLength) - 257; } } this->state = 1; break; } // case 4 } // switch(state) } // while (more data to be read) done: *lenIn = r; *lenOut = w; return; }