struct spi_ep *ep_new_pkt(struct spi_source *source, spi_epaddr_t epa, const struct timeval *ts, void *data, uint32_t size) { struct spi *spi = source->spi; struct spi_ep *ep; char *key; struct spi_pkt *pkt; mmatic *mm; key = _k(source, epa); ep = thash_get(spi->eps, key); if (!ep) { mm = mmatic_create(); ep = mmatic_zalloc(mm, sizeof *ep); ep->mm = mm; ep->source = source; ep->epa = epa; thash_set(spi->eps, key, ep); source->eps++; dbg(8, "new ep %s\n", spi_epa2a(epa)); } /* make packet */ pkt = mmatic_zalloc(ep->mm, sizeof *pkt); pkt->size = size; pkt->payload = mmatic_zalloc(ep->mm, spi->options.N); memcpy(pkt->payload, data, spi->options.N); memcpy(&pkt->ts, ts, sizeof(struct timeval)); /* update last packet time */ memcpy(&ep->last, ts, sizeof(struct timeval)); /* store packet */ if (!ep->pkts) ep->pkts = tlist_create(mmatic_free, ep->mm); tlist_push(ep->pkts, pkt); /* generate event if pkts big enough */ if (ep->gclock1 == 0 && tlist_count(ep->pkts) >= spi->options.C) { ep->gclock1++; spi_announce(spi, "endpointPacketsReady", 0, ep, false); dbg(7, "ep %s ready\n", spi_epa2a(epa)); } return ep; }
int cmd_packet_init(struct line *line, const char *text) { struct mg *mg = line->mg; struct cmd_packet *cp; struct mgp_line *pl; char *errmsg; pl = mgp_parse_line(mg->mm, text, 0, NULL, &errmsg, "size", "rep", "T", "burst", NULL); if (!pl) { dbg(0, "%s: line %d: packet: parse error: %s\n", mg->options.traf_file, line->line_num, errmsg); return 1; } /* rewrite into struct cmd_packet */ cp = mmatic_zalloc(mg->mm, sizeof(struct cmd_packet)); line->prv = cp; cp->len = mgp_prepare_int(pl, "size", 100); cp->num = mgp_int(mgp_prepare_int(pl, "rep", 1)); cp->T = mgp_prepare_int(pl, "T", 1000); cp->burst = mgp_prepare_int(pl, "burst", 1); return 0; }
struct client *create_client(mmatic *mm) { struct client *client; client = mmatic_zalloc(mm, sizeof *client); client->servers = thash_create_intkey(mmatic_free, mm); return client; }
void port_add(struct sock *ss, bool local) { struct port *sp; thash *ports; pthread_mutex_lock(&ss->td->mutex_ports); if (ss->type == SOCK_DGRAM) ports = ss->td->udp_ports; else if (ss->type == SOCK_STREAM) ports = ss->td->tcp_ports; else die("invalid ss->type\n"); sp = thash_uint_get(ports, ss->port); if (!sp) { sp = mmatic_zalloc(ss->td->mm, sizeof *sp); thash_uint_set(ports, ss->port, sp); dbg(3, "port %d/%s added\n", ss->port, ss->type == SOCK_STREAM ? "TCP" : "UDP"); } gettimeofday(&sp->since, NULL); sp->local = local; sp->socknum = ss->socknum; pthread_mutex_unlock(&ss->td->mutex_ports); }
int main(int argc, char *argv[]) { mmatic *mm; struct flowcalc *fc; void *h; struct module *mod; char *name, *s; tlist *ls; void *pdata; /* * initialization */ mm = mmatic_create(); fc = mmatic_zalloc(mm, sizeof *fc); fc->mm = mm; fc->modules = tlist_create(NULL, mm); /* read options */ if (parse_argv(fc, argc, argv)) return 1; /* enable all modules found in given directory */ if (tlist_count(fc->modules) == 0) { ls = pjf_ls(fc->dir, mm); tlist_iter_loop(ls, name) { s = strrchr(name, '.'); if (s && streq(s, ".so")) { *s = 0; tlist_push(fc->modules, name); } }
bool init(struct lfc *lfc, void **pdata) { mmatic *mm; struct ndpi *ndpi; IPOQUE_PROTOCOL_BITMASK all; mm = mmatic_create(); ndpi = mmatic_zalloc(mm, sizeof *ndpi); ndpi->mm = mm; ndpi->ids = thash_create_intkey(NULL, mm); // TODO: null ffn? ndpi->ipq = ipoque_init_detection_module(1000, ma, db); // TODO: 1000? if (!ndpi->ipq) { dbg(0, "ipoque_init_detection_module() failed\n"); return false; } IPOQUE_BITMASK_SET_ALL(all); ipoque_set_protocol_detection_bitmask2(ndpi->ipq, &all); *pdata = ndpi; printf("%%%% ndpi 0.1 - nDPI\n"); printf("@attribute ndpi_proto string\n"); return true; }
/* NOTE: it might be necessary to time-out nd->ids entries in order to decrease memory consumption */ static struct ipoque_id_struct *getid(struct ndpi *nd, struct lfc_flow_addr *lfa) { struct ipoque_id_struct *id; id = thash_uint_get(nd->ids, (uint32_t) lfa->addr.ip4.s_addr); if (!id) { id = mmatic_zalloc(nd->mm, ipoque_detection_get_sizeof_ipoque_id_struct()); thash_uint_set(nd->ids, (uint32_t) lfa->addr.ip4.s_addr, id); } return id; }
void pcap_init(struct tracedump *td) { int i; struct sockaddr_ll ll; struct pcap_file_hdr ph; /* initialize */ td->pc = mmatic_zalloc(td->mm, sizeof(struct pcap)); /* open the sniffing socket */ memset(&ll, 0, sizeof ll); ll.sll_family = AF_PACKET; td->pc->fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)); if (td->pc->fd == -1) { dbg(1, "Could not connect to the sniffing socket - insufficient privileges?\n"); die_errno("socket"); } /* open the resultant file */ if (streq(td->opts.outfile, "-")) { td->pc->fp = stdout; setvbuf(stdout, 0, _IOLBF, 0); } else { td->pc->fp = fopen(td->opts.outfile, "w"); if (!td->pc->fp) { dbg(1, "Could not open the output file: %s\n", td->opts.outfile); die_errno("fopen"); } dbg(1, "Writing packets to %s\n", td->opts.outfile); } /* write the global header */ ph.magic_number = PCAP_MAGIC_NUMBER; ph.version_major = 2; ph.version_minor = 4; ph.thiszone = 0; ph.sigfigs = 0; ph.snaplen = td->opts.snaplen; ph.network = LINKTYPE_LINUX_SLL; fwrite(&ph, sizeof ph, 1, td->pc->fp); /* start the reader thread */ i = pthread_create(&td->pc->reader, NULL, sniffer_thread, td); if (i != 0) die("pthread_create(sniffer_thread) failed with error %d\n", i); /* update the filter */ pcap_update(td); }
int main(int argc, char *argv[]) { mmatic *mm; /* * initialization */ mm = mmatic_create(); fd = mmatic_zalloc(mm, sizeof *fd); fd->mm = mm; fd->cache = thash_create_intkey(mmatic_free, mm); fd->out_files = thash_create_strkey(trace_destroy_output, mm); /* catch SIGINT */ signal(SIGINT, sigint); /* read options */ if (parse_argv(argc, argv)) return 1; /* file-system init */ { if (streq(fd->arff_file, "-")) { fd->afh = stdin; } else { fd->afh = fopen(fd->arff_file, "r"); if (!fd->afh) { cleanup(); die("Reading input ARFF file '%s' failed: %s\n", fd->arff_file, strerror(errno)); } } if (pjf_mkdir(fd->dir) != 0) { cleanup(); die("Creating output directory '%s' failed\n", fd->dir); } } fd->lfc = lfc_init(); lfc_register(fd->lfc, "flowdump", sizeof(struct flow), pkt, NULL, fd); if (!lfc_run(fd->lfc, fd->pcap_file, fd->filter)) { cleanup(); die("Reading file '%s' failed\n", fd->pcap_file); } cleanup(); return 0; }
int flow_count(struct spi_source *source, spi_epaddr_t src, spi_epaddr_t dst, const struct timeval *ts) { struct spi *spi = source->spi; struct spi_flow *flow; flow = _get_flow(source, src, dst); if (!flow) { flow = mmatic_zalloc(spi, sizeof *flow); flow->source = source; flow->epa1 = MIN(src, dst); flow->epa2 = MAX(src, dst); _set_flow(source, src, dst, flow); } memcpy(&flow->last, ts, sizeof(struct timeval)); return ++flow->counter; }
void verdict_init(struct spi *spi) { struct verdict *v; spi_subscribe(spi, "endpointClassification", _verdict_new_classification, false); spi_subscribe_after(spi, "endpointVerdictChanged", _verdict_eaten, false); v = mmatic_zalloc(spi->mm, sizeof *v); spi->vdata = v; if (spi->options.verdict_simple) { v->type = SPI_VERDICT_SIMPLE; } else if (spi->options.verdict_best) { v->type = SPI_VERDICT_BEST; } else { v->type = SPI_VERDICT_EWMA; v->ewma.N = spi->options.verdict_ewma_len ? spi->options.verdict_ewma_len : 5; } }
void *port_list(struct tracedump *td, bool tcp) { char *path; char buf[BUFSIZ], *ptr1, *ptr2; FILE *fp; uint8_t *list; unsigned long port; path = tcp ? "/proc/net/tcp" : "/proc/net/udp"; fp = fopen(path, "r"); if (!fp) { dbg(1, "fopen(%s): %s\n", path, strerror(errno)); return NULL; } /* a bitmask 1: active, 0: inactive */ list = mmatic_zalloc(td->mm, UINT16_MAX / sizeof(uint8_t)); while (fgets(buf, sizeof buf, fp)) { /* first : */ ptr1 = strchr(buf, ':'); if (!ptr1) continue; ptr1++; /* second : */ ptr1 = strchr(ptr1, ':'); if (!ptr1) continue; ptr1++; /* space */ ptr2 = strchr(ptr1, ' '); if (!ptr2) continue; ptr2[0] = '\0'; /* translate */ port = strtol(ptr1, NULL, 16); PORT_SET(list, port); } fclose(fp); return list; }
struct pid *pid_get(struct tracedump *td, pid_t pid) { struct pid *sp; /* speed-up cache */ if (td->sp && td->sp->pid == pid) return td->sp; sp = thash_uint_get(td->pids, pid); if (!sp) { dbg(7, "new pid %d\n", pid); sp = mmatic_zalloc(td->mm, sizeof *sp); sp->td = td; sp->pid = pid; thash_uint_set(td->pids, pid, sp); } return sp; }
static void _ewma_verdict(struct spi *spi, struct spi_classresult *cr) { struct verdict *v = spi->vdata; struct ewma_verdict *ev = cr->ep->vdata; int i; double m1 = 0.0, m2 = 0.0; spi_label_t max_label = 0; /* special case if its first verdict request */ if (!ev) { ev = mmatic_zalloc(cr->ep->mm, sizeof *ev); cr->ep->vdata = ev; /* init EWMA with class. result */ memcpy(ev->cprob, cr->cprob, sizeof(spi_cprob_t)); /* fall-back on simple verdict */ _simple_verdict(spi, cr); } else { /* update EWMA */ for (i = 1; i <= SPI_LABEL_MAX; i++) { ev->cprob[i] = EWMA(ev->cprob[i], cr->cprob[i], v->ewma.N); /* collect info as _cprob_dist() */ if (ev->cprob[i] > m2) { if (ev->cprob[i] > m1) { max_label = i; m2 = m1; m1 = ev->cprob[i]; } else { m2 = ev->cprob[i]; } } } if (m1 - m2 > cr->ep->verdict_prob) { cr->ep->verdict = max_label; cr->ep->verdict_prob = (m1 - m2); } } }
void pkt(struct lfc *lfc, void *pdata, struct lfc_flow *lf, void *data, double ts, bool up, bool is_new, libtrace_packet_t *pkt) { struct ndpi *nd = pdata; struct flow *f = data; struct ipoque_id_struct *srcid, *dstid; uint8_t *iph; uint16_t et; uint32_t rem; uint64_t time; if (!f->ipq_flow) f->ipq_flow = mmatic_zalloc(nd->mm, ipoque_detection_get_sizeof_ipoque_flow_struct()); iph = trace_get_layer3(pkt, &et, &rem); time = ts * 1000; srcid = getid(nd, &lf->src); dstid = getid(nd, &lf->dst); f->proto = ipoque_detection_process_packet( nd->ipq, f->ipq_flow, iph, rem, time, srcid, dstid); }
int32_t inject_socketcall(struct tracedump *td, struct pid *sp, uint32_t sc_code, ...) { /* int 0x80, int3 */ unsigned char code[4] = { 0xcd, 0x80, 0xcc, 0 }; char backup[4]; struct user_regs_struct regs, regs2; int ss_vals, ss_mem, ss; va_list vl; enum arg_type type; uint32_t sv; void *ptr; uint8_t *stack, *stack_mem; uint32_t *stack32; int i, j; /* * get the required amount of stack space */ ss_vals = 0; ss_mem = 0; va_start(vl, sc_code); do { type = va_arg(vl, enum arg_type); if (type == AT_LAST) break; sv = va_arg(vl, uint32_t); /* each socketcall argument takes 4 bytes */ ss_vals += 4; /* if its memory, it takes additional sv bytes */ if (type == AT_MEM_IN || type == AT_MEM_INOUT) { ss_mem += sv; ptr = va_arg(vl, void *); } } while (true); va_end(vl); ss = ss_vals + ss_mem; /* * backup */ ptrace_getregs(sp, ®s); memcpy(®s2, ®s, sizeof regs); ptrace_read(sp, regs.eip, backup, sizeof backup); /* * write the stack */ stack = mmatic_zalloc(td->mm, ss); stack32 = (uint32_t *) stack; stack_mem = stack + ss_vals; va_start(vl, sc_code); i = 0; j = 0; do { type = va_arg(vl, enum arg_type); if (type == AT_LAST) break; sv = va_arg(vl, uint32_t); if (type == AT_VALUE) { stack32[i++] = sv; } else { /* i.e. its a memory arg */ stack32[i++] = regs.esp - ss_mem + j; /* copy the memory */ ptr = va_arg(vl, void *); memcpy(stack_mem + j, ptr, sv); j += sv; } } while (true); va_end(vl); ptrace_write(sp, regs.esp - ss, stack, ss); /* * write the code and run */ regs2.eax = 102; // socketcall regs2.ebx = sc_code; regs2.ecx = regs.esp - ss; ptrace_write(sp, regs.eip, code, sizeof code); ptrace_setregs(sp, ®s2); ptrace_cont(sp, 0, true); /* * read back */ ptrace_getregs(sp, ®s2); ptrace_read(sp, regs.esp - ss_mem, stack_mem, ss_mem); va_start(vl, sc_code); do { type = va_arg(vl, enum arg_type); if (type == AT_LAST) break; sv = va_arg(vl, uint32_t); if (type == AT_VALUE) continue; ptr = va_arg(vl, void *); if (type == AT_MEM_IN) continue; memcpy(ptr, stack_mem, sv); stack_mem += sv; } while (true); va_end(vl); /* restore */ ptrace_write(sp, regs.eip, backup, sizeof backup); ptrace_setregs(sp, ®s); mmatic_free(stack); return regs2.eax; }
int main(int argc, char *argv[]) { mmatic *mm = mmatic_create(); mmatic *mmtmp = mmatic_create(); struct mg *mg; int i; /* * initialize and parse config */ mg = mmatic_zalloc(mm, sizeof(struct mg)); mg->mm = mm; mg->mmtmp = mmtmp; apply_defaults(mg); /* get my id number from hostname */ fetch_myid(mg); /* parse command line options */ if (parse_argv(mg, argc, argv)) return 1; /* parse configuration file options */ if (mg->options.conf_file) { if (parse_config(mg)) return 4; } /* * config syntax looks OK, see if it is feasible */ /* initialize random number generator */ srand48(mg->options.myid); /* init libevent */ mg->evb = event_init(); event_set_log_callback(libevent_log); /* init stats structures so mgstats_aggregator_add() used somewhere below works */ mgstats_init(mg); /* attach to raw interfaces */ if (mgi_init(mg, handle_packet) <= 0) { dbg(0, "no available interfaces found\n"); return 2; } /* parse traffic file */ if (parse_traffic(mg)) return 3; /* * all OK, prepare to start */ /* synchronize time reference point on all nodes */ mgc_sync(mg); /* schedule stats writing */ mgstats_start(mg); /* attach global stats */ _stats_init(mg); /* schedule heartbeat and disk sync signals */ heartbeat_init(mg); sync_init(mg); /* schedule the real work of this node: line generators */ for (i = 1; i < TRAFFIC_LINE_MAX; i++) { if (!(mg->lines[i] && mg->lines[i]->my)) continue; /* this will schedule first execution */ mgs_sleep(mg->lines[i], NULL); mg->running++; } /* suppose last frame was received now */ gettimeofday(&mg->last, NULL); /* * start! */ dbg(0, "Starting\n"); event_base_dispatch(mg->evb); /*******************************/ /* * cleanup after end of libevent loop */ event_base_free(mg->evb); mmatic_free(mg->mm); mmatic_free(mg->mmtmp); fflush(NULL); sync(); return 0; }
/** Parse traffic file * @retval 0 success * @retval 1 syntax error * @retval 2 logic error */ static int parse_traffic(struct mg *mg) { FILE *fp; const char *file; char buf[BUFSIZ]; uint32_t line_num = 0; struct line *line; int i, rc; char *rest, *errmsg; struct mgp_line *pl; file = mg->options.traf_file; fp = fopen(file, "r"); if (!fp) { dbg(0, "could not open traffic file: %s: %s\n", file, strerror(errno)); return 1; } while (fgets(buf, sizeof buf, fp)) { line_num++; if (line_num >= N(mg->lines)) die("Too many lines in the traffic file"); /* skip comments */ if (buf[0] == '#' || buf[0] == '\r' || buf[0] == '\n') continue; /* parse line */ pl = mgp_parse_line(mg->mm, buf, 8, &rest, &errmsg, "s", "ms", "iface", "src", "dst", "rate", "noack", "cmd", NULL); if (!pl) { dbg(0, "%s: line %d: parse error: %s\n", file, line_num, errmsg); return 1; } /* ...and rewrite into struct line */ line = mmatic_zalloc(mg->mm, sizeof *line); mg->lines[line_num] = line; line->mg = mg; line->line_num = line_num; line->contents = mmatic_strdup(mg->mm, buf); line->stats = stats_create(mg->mm); /* time */ line->tv.tv_sec = mgp_get_int(pl, "s", 0); line->tv.tv_usec = mgp_get_int(pl, "ms", 0) * 1000; /* interface */ i = mgp_get_int(pl, "iface", 0); if (i >= IFINDEX_MAX) { dbg(0, "%s: line %d: too big interface number: %d\n", file, line_num, i); return 1; } line->interface = &mg->interface[i]; if (line->interface->fd <= 0) { dbg(0, "%s: line %d: interface not opened: %d\n", file, line_num, i); return 2; } /* src/dst */ line->srcid = mgp_get_int(pl, "src", 1); line->dstid = mgp_get_int(pl, "dst", 1); line->my = (line->srcid == mg->options.myid); /* rate/noack */ line->rate = mgp_get_float(pl, "rate", 0) * 2.0; /* driver uses "half-rates"; NB: "auto" => 0 */ line->noack = mgp_get_int(pl, "noack", 0); /* * command */ line->cmd = mgp_get_string(pl, "cmd", ""); if (!line->cmd) { dbg(0, "%s: line %d: no line command\n", file, line_num); return 2; } /* find command handlers */ if (!find_line_cmd(line)) { dbg(0, "%s: line %d: invalid command: %s\n", file, line_num, line->cmd); return 2; } /* initialize scheduler of outgoing frames */ mgs_setup(&line->schedule, mg, line->cmd_timeout, line); /* call command initializer */ rc = line->cmd_init(line, rest); if (rc != 0) return rc; } fclose(fp); return 0; }
int32_t inject_socketcall(struct tracedump *td, struct pid *sp, uint32_t sc_code, ...) { struct user_regs_struct regs, regs2; int ss_vals, ss_mem, ss; va_list vl; enum arg_type type; uint32_t sv; void *ptr; uint8_t *stack, *stack_mem; uint32_t *stack32; int i, j; /* * get the required amount of stack space */ ss_vals = 0; // stack space for immediate values ss_mem = 0; // stack space for pointer values va_start(vl, sc_code); do { type = va_arg(vl, enum arg_type); if (type == AT_LAST) break; sv = va_arg(vl, uint32_t); /* each socketcall argument takes 4 bytes */ ss_vals += 4; /* if its memory, it takes additional sv bytes */ if (type == AT_MEM_IN || type == AT_MEM_INOUT) { ss_mem += sv; ptr = va_arg(vl, void *); } } while (true); va_end(vl); ss = ss_vals + ss_mem; /* * backup */ ptrace_getregs(sp, ®s); memcpy(®s2, ®s, sizeof regs); /* * write the stack */ stack = mmatic_zalloc(td->mm, ss); // stack area for immediate values stack32 = (uint32_t *) stack; stack_mem = stack + ss_vals; // stack area for pointer values va_start(vl, sc_code); i = 0; j = 0; do { type = va_arg(vl, enum arg_type); if (type == AT_LAST) break; sv = va_arg(vl, uint32_t); if (type == AT_VALUE) { stack32[i++] = sv; } else { /* i.e. its a memory arg */ stack32[i++] = regs.esp - ss_mem + j; /* copy the memory */ ptr = va_arg(vl, void *); memcpy(stack_mem + j, ptr, sv); j += sv; } } while (true); va_end(vl); ptrace_write(sp, regs.esp - ss, stack, ss); /* * write the code and run */ _prepare(sp); regs2.eax = 102; // socketcall regs2.ebx = sc_code; regs2.ecx = regs.esp - ss; regs2.eip = sp->vdso_addr; // gateway to int3 ptrace_setregs(sp, ®s2); ptrace_cont_syscall(sp, 0, true); // enter... ptrace_cont_syscall(sp, 0, true); // ...and exit /* * read back */ ptrace_getregs(sp, ®s2); ptrace_read(sp, regs.esp - ss_mem, stack_mem, ss_mem); va_start(vl, sc_code); do { type = va_arg(vl, enum arg_type); if (type == AT_LAST) break; sv = va_arg(vl, uint32_t); if (type == AT_VALUE) continue; ptr = va_arg(vl, void *); if (type == AT_MEM_IN) continue; memcpy(ptr, stack_mem, sv); stack_mem += sv; } while (true); va_end(vl); /* restore */ ptrace_setregs(sp, ®s); mmatic_free(stack); return regs2.eax; }
static struct sock_fprog *gencode_alloc(struct tracedump *td) { struct sock_fprog *fp; int i, j; /* code locations */ int loc_1 = 0, loc_2 = loc_1 + N(check_ip), loc_3 = loc_2 + N(check_type_outbound), loc_4 = loc_3 + N(check_ports) + thash_count(td->udp_ports), loc_5 = loc_4 + N(check_ports) + thash_count(td->tcp_ports), loc_6 = loc_5 + N(check_type_inbound), loc_7 = loc_6 + N(check_ports) + thash_count(td->udp_ports), loc_accept = loc_7 + N(check_ports) + thash_count(td->tcp_ports), loc_drop = loc_accept + 1; /* allocate memory */ fp = mmatic_zalloc(td->mm, sizeof(struct sock_fprog)); fp->len = loc_drop + 1; fp->filter = mmatic_zalloc(td->mm, sizeof(struct sock_filter) * fp->len); /*printf("loc_1=%d, loc_2=%d, loc_3=%d, loc_4=%d, loc_5=%d, loc_6=%d, loc_7=%d, loc_drop=%d, loc_accept=%d\n", loc_1, loc_2, loc_3, loc_4, loc_5, loc_6, loc_7, loc_drop, loc_accept);*/ /* * Fill */ i = 0; #define SUBST_JMP(from, to) \ if (fp->filter[i+j].jt == (from)) \ fp->filter[i+j].jt = (to) - i - j - 1; \ if (fp->filter[i+j].jf == (from)) \ fp->filter[i+j].jf = (to) - i - j - 1; /* 1. check_ip */ memcpy(fp->filter + i, check_ip, sizeof check_ip); for (j = 0; j < N(check_ip); j++) { SUBST_JMP(__DROP, loc_drop); } i += j; /* 2. check_type_outbound */ memcpy(fp->filter + i, check_type_outbound, sizeof check_type_outbound); for (j = 0; j < N(check_type_outbound); j++) { SUBST_JMP(__RET1, loc_5); SUBST_JMP(__RET2, loc_4); SUBST_JMP(__DROP, loc_drop); } i += j; /* 3. OUTBOUND: check_ports: td->udp_ports */ i += gencode_check_ports(td->udp_ports, true, fp->filter+i, loc_drop-i, loc_accept-i); /* 4. OUTBOUND: check_ports: td->tcp_ports */ i += gencode_check_ports(td->tcp_ports, true, fp->filter+i, loc_drop-i, loc_accept-i); /* 5. check_type_inbound */ memcpy(fp->filter + i, check_type_inbound, sizeof check_type_inbound); for (j = 0; j < N(check_type_inbound); j++) { SUBST_JMP(__RET1, loc_7); SUBST_JMP(__DROP, loc_drop); } i += j; /* 6. INBOUND: check_ports: td->udp_ports */ i += gencode_check_ports(td->udp_ports, false, fp->filter+i, loc_drop-i, loc_accept-i); /* 7. INBOUND: check_ports: td->tcp_ports */ i += gencode_check_ports(td->tcp_ports, false, fp->filter+i, loc_drop-i, loc_accept-i); /* 8. end */ memcpy(fp->filter + i, end, sizeof end); i += N(end); return fp; }