void tprintf(char *msg, ...) { ssize_t ret; ssize_t avail; va_list vl; spinlock_lock(&buffer_lock); avail = sizeof(buffer) - buffer_use; bug_on(avail < 0); va_start(vl, msg); ret = vsnprintf(buffer + buffer_use, avail, msg, vl); va_end(vl); if (ret < 0) panic("vsnprintf screwed up in tprintf!\n"); if ((size_t) ret > sizeof(buffer)) panic("No mem in tprintf left!\n"); if (ret >= avail) { __tprintf_flush(); avail = sizeof(buffer) - buffer_use; bug_on(avail < 0); va_start(vl, msg); ret = vsnprintf(buffer + buffer_use, avail, msg, vl); va_end(vl); if (ret < 0) panic("vsnprintf screwed up in tprintf!\n"); } buffer_use += ret; spinlock_unlock(&buffer_lock); }
/* Starts the parsing process. * * Returns 0 on success; a negative enum errcode otherwise. * Returns -err_pt_lib if the pt encoder could not be initialized. * Returns -err_file_write if the .pt or .exp file could not be fully * written. */ int p_start(struct parser *p) { int errcode; if (bug_on(!p)) return -err_internal; errcode = yasm_parse(p->y); if (errcode < 0) return errcode; for (;;) { int bytes_written; struct pt_encoder *e; errcode = yasm_next_pt_directive(p->y, p->pd); if (errcode < 0) break; e = pt_alloc_encoder(p->conf); if (!e) { fprintf(stderr, "pt_alloc_encoder failed\n"); errcode = -err_pt_lib; break; } bytes_written = p_process(p, e); if (bytes_written == -stop_process) { errcode = p_gen_expfile(p); break; } if (bytes_written < 0) { errcode = bytes_written; break; } if (fwrite(p->conf->begin, 1, bytes_written, p->ptfile) != (size_t)bytes_written) { fprintf(stderr, "write %s failed", p->ptfilename); errcode = -err_file_write; break; } } /* If there is no directive left, there's nothing more to do. */ if (errcode == -err_no_directive) return 0; return errcode; }
int parse_tnt(uint64_t *tnt, uint8_t *size, char *payload) { char c; if (bug_on(!size)) return -err_internal; if (bug_on(!tnt)) return -err_internal; *size = 0; *tnt = 0ull; if (!payload) return 0; while (*payload != '\0') { c = *payload; payload++; if (isspace(c) || c == '.') continue; *size += 1; *tnt <<= 1; switch (c) { case 'n': break; case 't': *tnt |= 1; break; default: return -err_parse_unknown_char; } } return 0; }
int l_append(struct label *l, const char *name, uint64_t addr) { int errcode; if (bug_on(!l)) return -err_internal; if (bug_on(!name)) return -err_internal; /* skip to the last label. */ while (l->next) l = l->next; /* append a new label. */ l->next = l_alloc(); if (!l->next) return -err_no_mem; /* save the name. */ l->next->name = duplicate_str(name); if (!l->next->name) { errcode = -err_no_mem; goto error; } /* save the address. */ l->next->addr = addr; return 0; error: free(l->next->name); free(l->next); l->next = NULL; return errcode; }
int dlist_delete(Dlist *dl, Dlist_data *dd) { if (dl == NULL || dd == NULL) return 0; #ifdef DEBUG bug_on(__dlist_dlist(dd) != dl); #endif if (!dlist_detach(dl, dd)) return 0; destroy_dlist_data(dd); free(dd); return 1; }
int parse_uint64(uint64_t *x, char *payload) { int errcode; if (bug_on(!x)) return -err_internal; payload = strtok(payload, " ,"); if (!payload) return -err_parse_no_args; errcode = str_to_uint64(payload, x); if (errcode < 0) return errcode; return 0; }
Dlist_data * dlist_insert_object(Dlist *dl, Dlist_data *inserted, void *d, Dlist_data_destructor dddest) { Dlist_data *dd; #ifdef DEBUG bug_on(__dlist_dlist(inserted) != dl); #endif dd = dlist_data_create(dl); if (unlikely(dd == NULL)) return NULL; dlist_data(dd) = d; __dlist_data_destructor(dd) = dddest; dlist_attach(dl, dd, inserted); return dd; }
int yasm_next_line(struct yasm *y, char *dest, size_t destlen) { int errcode; if (!destlen) return 0; if (bug_on(!dest)) return -err_internal; errcode = yasm_advance_next_line(y); if (errcode < 0) return errcode; strncpy(dest, y->st_asm->line, destlen); dest[destlen-1] = '\0'; return 0; }
int parse_tma(uint16_t *ctc, uint16_t *fc, char *payload) { char *endptr; long int i; if (bug_on(!ctc || !fc)) return -err_internal; payload = strtok(payload, ","); if (!payload || *payload == '\0') return -err_parse_no_args; i = strtol(payload, &endptr, 0); if (payload == endptr || *endptr != '\0') return -err_parse_int; if (i > 0xffffl) return -err_parse_int_too_big; *ctc = (uint16_t)i; payload = strtok(NULL, " ,"); if (!payload) return -err_parse_no_args; i = strtol(payload, &endptr, 0); if (payload == endptr || *endptr != '\0') return -err_parse_int; if (i > 0xffffl) return -err_parse_int_too_big; *fc = (uint16_t)i; /* no more tokens left. */ payload = strtok(NULL, " "); if (payload) return -err_parse_trailing_tokens; return 0; }
int parse_uint8(uint8_t *x, char *payload) { char *endptr; long int i; if (bug_on(!x)) return -err_internal; payload = strtok(payload, " ,"); if (!payload) return -err_parse_no_args; i = strtol(payload, &endptr, 0); if (payload == endptr || *endptr != '\0') return -err_parse_int; if (i > 0xff) return -err_parse_int_too_big; *x = (uint8_t)i; return 0; }
int yasm_parse(struct yasm *y) { int errcode; const struct text *t; if (bug_on(!y)) return -err_internal; errcode = yasm_run(y); if (errcode < 0) goto error; errcode = fl_gettext(y->fl, &t, y->lstfile); if (errcode < 0) goto error; errcode = parse_yasm_labels(y->l, t); if (errcode < 0) goto error; error: return errcode; }
static int xmit_packet_precheck(struct ctx *ctx, unsigned int cpu) { unsigned int i; unsigned long plen_total, orig = ctx->num; size_t mtu, total_len = 0; bug_on(plen != dlen); for (i = 0; i < plen; ++i) total_len += packets[i].len; __set_state_cf(cpu, plen, total_len, CPU_STATS_STATE_CFG); plen_total = __wait_and_sum_others(ctx, cpu); if (orig > 0) { ctx->num = (unsigned long) round((1.0 * plen / plen_total) * orig); __set_state_cd(cpu, ctx->num, CPU_STATS_STATE_CHK | CPU_STATS_STATE_CFG); __correct_global_delta(ctx, cpu, orig); } if (plen == 0) { __set_state(cpu, CPU_STATS_STATE_RES); return 0; } for (mtu = device_mtu(ctx->device), i = 0; i < plen; ++i) { if (packets[i].len > mtu + PKT_MIN_LEN) panic("Device MTU < than packet%d's size!\n", i); if (packets[i].len <= PKT_MIN_LEN) panic("Packet%d's size must be > %d bytes!\n", i, PKT_MIN_LEN); } return 0; }
static int begin_multi_pcap_file(struct ctx *ctx) { int fd, ret; char fname[256]; bug_on(!__pcap_io); if (ctx->device_out[strlen(ctx->device_out) - 1] == '/') ctx->device_out[strlen(ctx->device_out) - 1] = 0; slprintf(fname, sizeof(fname), "%s/%s%lu.pcap", ctx->device_out, ctx->prefix ? : "dump-", time(0)); fd = open_or_die_m(fname, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE, DEFFILEMODE); ret = __pcap_io->push_fhdr_pcap(fd, ctx->magic, ctx->link_type); if (ret) panic("Error writing pcap header!\n"); if (__pcap_io->prepare_access_pcap) { ret = __pcap_io->prepare_access_pcap(fd, PCAP_MODE_WR, true); if (ret) panic("Error prepare writing pcap!\n"); } if (ctx->dump_mode == DUMP_INTERVAL_TIME) { interval = ctx->dump_interval; set_itimer_interval_value(&itimer, interval, 0); setitimer(ITIMER_REAL, &itimer, NULL); } else { interval = 0; } return fd; }
static void xmit_slowpath_or_die(struct ctx *ctx, int cpu, unsigned long orig_num) { int ret, icmp_sock = -1; unsigned long num = 1, i = 0; struct timeval start, end, diff; unsigned long long tx_bytes = 0, tx_packets = 0; struct packet_dyn *pktd; struct sockaddr_ll saddr = { .sll_family = PF_PACKET, .sll_halen = ETH_ALEN, .sll_ifindex = device_ifindex(ctx->device), }; if (ctx->num > 0) num = ctx->num; if (ctx->num == 0 && orig_num > 0) num = 0; if (ctx->smoke_test) icmp_sock = xmit_smoke_setup(ctx); drop_privileges(ctx->enforce, ctx->uid, ctx->gid); bug_on(gettimeofday(&start, NULL)); while (likely(sigint == 0) && likely(num > 0) && likely(plen > 0)) { pktd = &packet_dyn[i]; if (pktd->clen + pktd->rlen + pktd->slen) { apply_counter(i); apply_randomizer(i); apply_csum16(i); } retry: ret = sendto(sock, packets[i].payload, packets[i].len, 0, (struct sockaddr *) &saddr, sizeof(saddr)); if (unlikely(ret < 0)) { if (errno == ENOBUFS) { sched_yield(); goto retry; } panic("Sendto error: %s!\n", strerror(errno)); } tx_bytes += packets[i].len; tx_packets++; if (ctx->smoke_test) { ret = xmit_smoke_probe(icmp_sock, ctx); if (unlikely(ret < 0)) { printf("%sSmoke test alert:%s\n", colorize_start(bold), colorize_end()); printf(" Remote host seems to be unresponsive to ICMP probes!\n"); printf(" Last instance was packet%lu, seed:%u, trafgen snippet:\n\n", i, seed); dump_trafgen_snippet(packets[i].payload, packets[i].len); break; } } if (!ctx->rand) { i++; if (i >= plen) i = 0; } else i = rand() % plen; if (ctx->num > 0) num--; if (ctx->gap > 0) usleep(ctx->gap); } bug_on(gettimeofday(&end, NULL)); timersub(&end, &start, &diff); if (ctx->smoke_test) close(icmp_sock); stats[cpu].tx_packets = tx_packets; stats[cpu].tx_bytes = tx_bytes; stats[cpu].tv_sec = diff.tv_sec; stats[cpu].tv_usec = diff.tv_usec; stats[cpu].state |= CPU_STATS_STATE_RES; } static void xmit_fastpath_or_die(struct ctx *ctx, int cpu, unsigned long orig_num) { int ifindex = device_ifindex(ctx->device); uint8_t *out = NULL; unsigned int it = 0; unsigned long num = 1, i = 0, size; struct ring tx_ring; struct frame_map *hdr; struct timeval start, end, diff; struct packet_dyn *pktd; unsigned long long tx_bytes = 0, tx_packets = 0; fmemset(&tx_ring, 0, sizeof(tx_ring)); size = ring_size(ctx->device, ctx->reserve_size); set_sock_prio(sock, 512); set_packet_loss_discard(sock); setup_tx_ring_layout(sock, &tx_ring, size, ctx->jumbo_support); create_tx_ring(sock, &tx_ring, ctx->verbose); mmap_tx_ring(sock, &tx_ring); alloc_tx_ring_frames(sock, &tx_ring); bind_tx_ring(sock, &tx_ring, ifindex); drop_privileges(ctx->enforce, ctx->uid, ctx->gid); if (ctx->kpull) interval = ctx->kpull; if (ctx->num > 0) num = ctx->num; if (ctx->num == 0 && orig_num > 0) num = 0; set_itimer_interval_value(&itimer, 0, interval); setitimer(ITIMER_REAL, &itimer, NULL); bug_on(gettimeofday(&start, NULL)); while (likely(sigint == 0) && likely(num > 0) && likely(plen > 0)) { while (user_may_pull_from_tx(tx_ring.frames[it].iov_base) && likely(num > 0)) { hdr = tx_ring.frames[it].iov_base; out = ((uint8_t *) hdr) + TPACKET2_HDRLEN - sizeof(struct sockaddr_ll); hdr->tp_h.tp_snaplen = packets[i].len; hdr->tp_h.tp_len = packets[i].len; pktd = &packet_dyn[i]; if (pktd->clen + pktd->rlen + pktd->slen) { apply_counter(i); apply_randomizer(i); apply_csum16(i); } fmemcpy(out, packets[i].payload, packets[i].len); tx_bytes += packets[i].len; tx_packets++; if (!ctx->rand) { i++; if (i >= plen) i = 0; } else i = rand() % plen; kernel_may_pull_from_tx(&hdr->tp_h); it++; if (it >= tx_ring.layout.tp_frame_nr) it = 0; if (ctx->num > 0) num--; if (unlikely(sigint == 1)) break; } } bug_on(gettimeofday(&end, NULL)); timersub(&end, &start, &diff); timer_purge(); destroy_tx_ring(sock, &tx_ring); stats[cpu].tx_packets = tx_packets; stats[cpu].tx_bytes = tx_bytes; stats[cpu].tv_sec = diff.tv_sec; stats[cpu].tv_usec = diff.tv_usec; stats[cpu].state |= CPU_STATS_STATE_RES; }
struct yasm *yasm_alloc(const char *pttfile) { char *tmp; size_t n; struct yasm *y; if (bug_on(!pttfile)) return NULL; y = calloc(1, sizeof(*y)); if (!y) return NULL; y->fl = fl_alloc(); if (!y->fl) goto error; y->st_asm = st_alloc(); if (!y->st_asm) goto error; y->fileroot = duplicate_str(pttfile); if (!y->fileroot) goto error; y->pttfile = duplicate_str(pttfile); if (!y->pttfile) goto error; tmp = strrchr(y->fileroot, '.'); if (tmp) *tmp = '\0'; tmp = strrchr(y->fileroot, path_separator); if (tmp) { tmp += 1; memmove(y->fileroot, tmp, strlen(tmp)+1); } y->binfile = malloc(strlen(y->fileroot)+strlen(bin_suffix)+1); if (!y->binfile) goto error; y->lstfile = malloc(strlen(y->fileroot)+strlen(lst_suffix)+1); if (!y->lstfile) goto error; n = strlen(y->fileroot); strcpy(y->binfile, y->fileroot); strcpy(y->binfile+n, bin_suffix); strcpy(y->lstfile, y->fileroot); strcpy(y->lstfile+n, lst_suffix); y->l = l_alloc(); if (!y->l) goto error; return y; error: yasm_free(y); return 0; }
int parse_yasm_labels(struct label *l, const struct text *t) { int errcode, no_org_directive; size_t i; uint64_t base_addr; enum { linelen = 1024 }; char line[linelen]; if (bug_on(!t)) return -err_internal; base_addr = 0; no_org_directive = 1; /* determine base address from org directive, error out on * sections. */ for (i = 0; i < t->n; i++) { char *tmp; errcode = text_line(t, line, linelen, i); if (errcode < 0) return errcode; tmp = strstr(line, "[section"); if (tmp) return -err_section; tmp = strstr(line, "[org"); if (!tmp) continue; base_addr = strtol(tmp+strlen("[org"), NULL, 0); no_org_directive = 0; break; } if (no_org_directive) return -err_no_org_directive; for (i = 0; i < t->n; i++) { char *tmp, *name; uint64_t addr; errcode = text_line(t, line, linelen, i); if (errcode < 0) goto error; /* skip line number count. */ tmp = strtok(line, " "); if (!tmp) continue; /* the label can now be on the same line as the memory * address or on a line by its own. * we look at the next token and (1) if it looks like a * label, we search in the following lines for the * corresponding address; or (2) if it looks like an * address, we store it and see if the token after the * opcode looks like a token; or (3) none of the above, * we continue with the next line. */ /* second token after the line number count. it's * either an address; or a label. */ tmp = strtok(NULL, " "); if (!tmp) continue; if (!make_label(tmp)) { /* get address in case we find a label later. */ if (sscanf(tmp, "%" PRIx64, &addr) != 1) continue; /* skip the opcode token. */ tmp = strtok(NULL, " "); if (!tmp) continue; /* this might be a label now. */ tmp = strtok(NULL, " "); if (!make_label(tmp)) continue; errcode = l_append(l, tmp, addr + base_addr); if (errcode < 0) goto error; continue; } name = duplicate_str(tmp); if (!name) { errcode = -err_no_mem; goto error; } /* there was a label so now an address needs to * be found. */ errcode = -err_label_addr; for (i += 1; i < t->n; i++) { int errcode_text; errcode_text = text_line(t, line, linelen, i); if (errcode_text < 0) { errcode = errcode_text; break; } if (sscanf(line, "%*d %" PRIx64 " %*x %*s", &addr) == 1) { errcode = l_append(l, name, addr + base_addr); break; } } if (errcode == -err_label_addr) fprintf(stderr, "label '%s' has no address\n", name); free(name); if (errcode < 0) goto error; } return 0; error: l_free(l->next); free(l->name); l->next = NULL; l->name = NULL; return errcode; }
int pd_parse(struct pt_directive *pd, struct state *st) { char *line, *comment, *ptdirective, *openpar, *closepar; char *directive, *payload; int errcode; char *c; if (bug_on(!pd)) return -err_internal; if (bug_on(!st)) return -err_internal; line = duplicate_str(st->line); if (!line) return -err_no_mem; /* make line lower case. */ for (c = line; *c; ++c) *c = (char) tolower(*c); /* if the current line is not a comment or contains no magic marker * -err_no_directive is returned. */ errcode = -err_no_directive; /* search where the comment begins. */ comment = strchr(line, ';'); /* if there is no comment in the line, we don't have anything to * do. */ if (!comment) goto cleanup; /* search for @pt marker. */ ptdirective = strstr(comment+1, marker); /* if there is no such marker in the comment, we don't have * anything to do. */ if (!ptdirective) goto cleanup; /* directive found, now parse the payload. */ errcode = 0; /* find position of next '(', separating the directive and the * payload. */ openpar = strchr(ptdirective, '('); if (!openpar) { errcode = -err_missing_openpar; st_print_err(st, "invalid syntax", errcode); goto cleanup; } /* find position of next ')', marking the end of the payload */ closepar = strchr(openpar, ')'); if (!closepar) { errcode = -err_missing_closepar; st_print_err(st, "invalid syntax", errcode); goto cleanup; } /* make "multiple" strings by artifically terminating them with * '\0' then get directive and payload substrings, which will * have leading and trailing whitespace "removed". */ *openpar = '\0'; *closepar = '\0'; /* skip leading whitespace. */ directive = ptdirective + strlen(marker); while (isspace(*directive)) directive += 1; payload = openpar+1; errcode = pd_set(pd, directive, payload); cleanup: free(line); return errcode; }
static void recv_only_or_dump(struct ctx *ctx) { short ifflags = 0; int sock, irq, ifindex, fd = 0, ret; unsigned int size, it = 0; struct ring rx_ring; struct pollfd rx_poll; struct sock_fprog bpf_ops; struct timeval start, end, diff; struct block_desc *pbd; unsigned long frame_count = 0; sock = pf_socket(); if (ctx->rfraw) { ctx->device_trans = xstrdup(ctx->device_in); xfree(ctx->device_in); enter_rfmon_mac80211(ctx->device_trans, &ctx->device_in); ctx->link_type = LINKTYPE_IEEE802_11; } fmemset(&rx_ring, 0, sizeof(rx_ring)); fmemset(&rx_poll, 0, sizeof(rx_poll)); fmemset(&bpf_ops, 0, sizeof(bpf_ops)); ifindex = device_ifindex(ctx->device_in); size = ring_size(ctx->device_in, ctx->reserve_size); enable_kernel_bpf_jit_compiler(); bpf_parse_rules(ctx->filter, &bpf_ops, ctx->link_type); if (ctx->dump_bpf) bpf_dump_all(&bpf_ops); bpf_attach_to_sock(sock, &bpf_ops); ret = set_sockopt_hwtimestamp(sock, ctx->device_in); if (ret == 0 && ctx->verbose) printf("HW timestamping enabled\n"); setup_rx_ring_layout(sock, &rx_ring, size, true, true); create_rx_ring(sock, &rx_ring, ctx->verbose); mmap_rx_ring(sock, &rx_ring); alloc_rx_ring_frames(sock, &rx_ring); bind_rx_ring(sock, &rx_ring, ifindex); prepare_polling(sock, &rx_poll); dissector_init_all(ctx->print_mode); if (ctx->cpu >= 0 && ifindex > 0) { irq = device_irq_number(ctx->device_in); device_set_irq_affinity(irq, ctx->cpu); if (ctx->verbose) printf("IRQ: %s:%d > CPU%d\n", ctx->device_in, irq, ctx->cpu); } if (ctx->promiscuous) ifflags = enter_promiscuous_mode(ctx->device_in); if (dump_to_pcap(ctx) && __pcap_io->init_once_pcap) __pcap_io->init_once_pcap(); drop_privileges(ctx->enforce, ctx->uid, ctx->gid); if (dump_to_pcap(ctx)) { __label__ try_file; struct stat stats; fmemset(&stats, 0, sizeof(stats)); ret = stat(ctx->device_out, &stats); if (ret < 0) { ctx->dump_dir = 0; goto try_file; } ctx->dump_dir = S_ISDIR(stats.st_mode); if (ctx->dump_dir) { fd = begin_multi_pcap_file(ctx); } else { try_file: fd = begin_single_pcap_file(ctx); } } printf("Running! Hang up with ^C!\n\n"); fflush(stdout); bug_on(gettimeofday(&start, NULL)); while (likely(sigint == 0)) { while (user_may_pull_from_rx_block((pbd = (void *) rx_ring.frames[it].iov_base))) { walk_t3_block(pbd, ctx, sock, &fd, &frame_count); kernel_may_pull_from_rx_block(pbd); it = (it + 1) % rx_ring.layout3.tp_block_nr; if (unlikely(sigint == 1)) break; } poll(&rx_poll, 1, -1); } bug_on(gettimeofday(&end, NULL)); timersub(&end, &start, &diff); if (!(ctx->dump_dir && ctx->print_mode == PRINT_NONE)) { sock_rx_net_stats(sock, frame_count); printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec); } else { printf("\n\n"); fflush(stdout); } bpf_release(&bpf_ops); dissector_cleanup_all(); destroy_rx_ring(sock, &rx_ring); if (ctx->promiscuous) leave_promiscuous_mode(ctx->device_in, ifflags); if (ctx->rfraw) leave_rfmon_mac80211(ctx->device_trans, ctx->device_in); if (dump_to_pcap(ctx)) { if (ctx->dump_dir) finish_multi_pcap_file(ctx, fd); else finish_single_pcap_file(ctx, fd); } close(sock); }
static void read_pcap(struct ctx *ctx) { __label__ out; uint8_t *out; int ret, fd, fdo = 0; unsigned long trunced = 0; size_t out_len; pcap_pkthdr_t phdr; struct sock_fprog bpf_ops; struct frame_map fm; struct timeval start, end, diff; struct sockaddr_ll sll; bug_on(!__pcap_io); if (!strncmp("-", ctx->device_in, strlen("-"))) { fd = dup_or_die(fileno(stdin)); close(fileno(stdin)); if (ctx->pcap == PCAP_OPS_MM) ctx->pcap = PCAP_OPS_SG; } else { fd = open_or_die(ctx->device_in, O_RDONLY | O_LARGEFILE | O_NOATIME); } if (__pcap_io->init_once_pcap) __pcap_io->init_once_pcap(); ret = __pcap_io->pull_fhdr_pcap(fd, &ctx->magic, &ctx->link_type); if (ret) panic("Error reading pcap header!\n"); if (__pcap_io->prepare_access_pcap) { ret = __pcap_io->prepare_access_pcap(fd, PCAP_MODE_RD, ctx->jumbo); if (ret) panic("Error prepare reading pcap!\n"); } fmemset(&fm, 0, sizeof(fm)); fmemset(&bpf_ops, 0, sizeof(bpf_ops)); bpf_parse_rules(ctx->filter, &bpf_ops, ctx->link_type); if (ctx->dump_bpf) bpf_dump_all(&bpf_ops); dissector_init_all(ctx->print_mode); out_len = round_up(1024 * 1024, PAGE_SIZE); out = xmalloc_aligned(out_len, CO_CACHE_LINE_SIZE); if (ctx->device_out) { if (!strncmp("-", ctx->device_out, strlen("-"))) { fdo = dup_or_die(fileno(stdout)); close(fileno(stdout)); } else { fdo = open_or_die_m(ctx->device_out, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE, DEFFILEMODE); } } drop_privileges(ctx->enforce, ctx->uid, ctx->gid); printf("Running! Hang up with ^C!\n\n"); fflush(stdout); bug_on(gettimeofday(&start, NULL)); while (likely(sigint == 0)) { do { ret = __pcap_io->read_pcap(fd, &phdr, ctx->magic, out, out_len); if (unlikely(ret < 0)) goto out; if (unlikely(pcap_get_length(&phdr, ctx->magic) == 0)) { trunced++; continue; } if (unlikely(pcap_get_length(&phdr, ctx->magic) > out_len)) { pcap_set_length(&phdr, ctx->magic, out_len); trunced++; } } while (ctx->filter && !bpf_run_filter(&bpf_ops, out, pcap_get_length(&phdr, ctx->magic))); pcap_pkthdr_to_tpacket_hdr(&phdr, ctx->magic, &fm.tp_h, &sll); ctx->tx_bytes += fm.tp_h.tp_len; ctx->tx_packets++; show_frame_hdr(&fm, ctx->print_mode); dissector_entry_point(out, fm.tp_h.tp_snaplen, ctx->link_type, ctx->print_mode); if (ctx->device_out) translate_pcap_to_txf(fdo, out, fm.tp_h.tp_snaplen); if (frame_count_max != 0) { if (ctx->tx_packets >= frame_count_max) { sigint = 1; break; } } } out: bug_on(gettimeofday(&end, NULL)); timersub(&end, &start, &diff); bpf_release(&bpf_ops); dissector_cleanup_all(); if (__pcap_io->prepare_close_pcap) __pcap_io->prepare_close_pcap(fd, PCAP_MODE_RD); xfree(out); fflush(stdout); printf("\n"); printf("\r%12lu packets outgoing\n", ctx->tx_packets); printf("\r%12lu packets truncated in file\n", trunced); printf("\r%12lu bytes outgoing\n", ctx->tx_bytes); printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec); if (!strncmp("-", ctx->device_in, strlen("-"))) dup2(fd, fileno(stdin)); close(fd); if (ctx->device_out) { if (!strncmp("-", ctx->device_out, strlen("-"))) dup2(fdo, fileno(stdout)); close(fdo); } }
void curve25519_selftest(void) { int i; unsigned char alicesk[32] = { 0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 0x3c, 0x16, 0xc1, 0x72, 0x51, 0xb2, 0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87, 0xeb, 0xc0, 0x99, 0x2a, 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9, 0x2c, 0x2a }; unsigned char bobpk[32] = { 0xde, 0x9e, 0xdb, 0x7d, 0x7b, 0x7d, 0xc1, 0xb4, 0xd3, 0x5b, 0x61, 0xc2, 0xec, 0xe4, 0x35, 0x37, 0x3f, 0x83, 0x43, 0xc8, 0x5b, 0x78, 0x67, 0x4d, 0xad, 0xfc, 0x7e, 0x14, 0x6f, 0x88, 0x2b, 0x4f }; unsigned char nonce[24] = { 0x69, 0x69, 0x6e, 0xe9, 0x55, 0xb6, 0x2b, 0x73, 0xcd, 0x62, 0xbd, 0xa8, 0x75, 0xfc, 0x73, 0xd6, 0x82, 0x19, 0xe0, 0x03, 0x6b, 0x7a, 0x0b, 0x37 }; unsigned char m[163] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0x07, 0x5f, 0xc5, 0x3c, 0x81, 0xf2, 0xd5, 0xcf, 0x14, 0x13, 0x16, 0xeb, 0xeb, 0x0c, 0x7b, 0x52, 0x28, 0xc5, 0x2a, 0x4c, 0x62, 0xcb, 0xd4, 0x4b, 0x66, 0x84, 0x9b, 0x64, 0x24, 0x4f, 0xfc, 0xe5, 0xec, 0xba, 0xaf, 0x33, 0xbd, 0x75, 0x1a, 0x1a, 0xc7, 0x28, 0xd4, 0x5e, 0x6c, 0x61, 0x29, 0x6c, 0xdc, 0x3c, 0x01, 0x23, 0x35, 0x61, 0xf4, 0x1d, 0xb6, 0x6c, 0xce, 0x31, 0x4a, 0xdb, 0x31, 0x0e, 0x3b, 0xe8, 0x25, 0x0c, 0x46, 0xf0, 0x6d, 0xce, 0xea, 0x3a, 0x7f, 0xa1, 0x34, 0x80, 0x57, 0xe2, 0xf6, 0x55, 0x6a, 0xd6, 0xb1, 0x31, 0x8a, 0x02, 0x4a, 0x83, 0x8f, 0x21, 0xaf, 0x1f, 0xde, 0x04, 0x89, 0x77, 0xeb, 0x48, 0xf5, 0x9f, 0xfd, 0x49, 0x24, 0xca, 0x1c, 0x60, 0x90, 0x2e, 0x52, 0xf0, 0xa0, 0x89, 0xbc, 0x76, 0x89, 0x70, 0x40, 0xe0, 0x82, 0xf9, 0x37, 0x76, 0x38, 0x48, 0x64, 0x5e, 0x07, 0x05 }; unsigned char c[163]; unsigned char result[147] = { 0xf3, 0xff, 0xc7, 0x70, 0x3f, 0x94, 0x00, 0xe5, 0x2a, 0x7d, 0xfb, 0x4b, 0x3d, 0x33, 0x05, 0xd9, 0x8e, 0x99, 0x3b, 0x9f, 0x48, 0x68, 0x12, 0x73, 0xc2, 0x96, 0x50, 0xba, 0x32, 0xfc, 0x76, 0xce, 0x48, 0x33, 0x2e, 0xa7, 0x16, 0x4d, 0x96, 0xa4, 0x47, 0x6f, 0xb8, 0xc5, 0x31, 0xa1, 0x18, 0x6a, 0xc0, 0xdf, 0xc1, 0x7c, 0x98, 0xdc, 0xe8, 0x7b, 0x4d, 0xa7, 0xf0, 0x11, 0xec, 0x48, 0xc9, 0x72, 0x71, 0xd2, 0xc2, 0x0f, 0x9b, 0x92, 0x8f, 0xe2, 0x27, 0x0d, 0x6f, 0xb8, 0x63, 0xd5, 0x17, 0x38, 0xb4, 0x8e, 0xee, 0xe3, 0x14, 0xa7, 0xcc, 0x8a, 0xb9, 0x32, 0x16, 0x45, 0x48, 0xe5, 0x26, 0xae, 0x90, 0x22, 0x43, 0x68, 0x51, 0x7a, 0xcf, 0xea, 0xbd, 0x6b, 0xb3, 0x73, 0x2b, 0xc0, 0xe9, 0xda, 0x99, 0x83, 0x2b, 0x61, 0xca, 0x01, 0xb6, 0xde, 0x56, 0x24, 0x4a, 0x9e, 0x88, 0xd5, 0xf9, 0xb3, 0x79, 0x73, 0xf6, 0x22, 0xa4, 0x3d, 0x14, 0xa6, 0x59, 0x9b, 0x1f, 0x65, 0x4c, 0xb4, 0x5a, 0x74, 0xe3, 0x55, 0xa5 }; bug_on(NONCE_LENGTH != 16); crypto_box_curve25519xsalsa20poly1305(c, m, 163, nonce, bobpk, alicesk); for (i = 16; i < 163; ++i) { if (c[i] != result[i - 16]) panic("Crypto selftest failed! :-(\n"); } }
static void pcap_to_xmit(struct ctx *ctx) { __label__ out; uint8_t *out = NULL; int irq, ifindex, fd = 0, ret; unsigned int size, it = 0; unsigned long trunced = 0; struct ring tx_ring; struct frame_map *hdr; struct sock_fprog bpf_ops; struct timeval start, end, diff; pcap_pkthdr_t phdr; if (!device_up_and_running(ctx->device_out) && !ctx->rfraw) panic("Device not up and running!\n"); bug_on(!__pcap_io); tx_sock = pf_socket(); if (!strncmp("-", ctx->device_in, strlen("-"))) { fd = dup_or_die(fileno(stdin)); close(fileno(stdin)); if (ctx->pcap == PCAP_OPS_MM) ctx->pcap = PCAP_OPS_SG; } else { fd = open_or_die(ctx->device_in, O_RDONLY | O_LARGEFILE | O_NOATIME); } if (__pcap_io->init_once_pcap) __pcap_io->init_once_pcap(); ret = __pcap_io->pull_fhdr_pcap(fd, &ctx->magic, &ctx->link_type); if (ret) panic("Error reading pcap header!\n"); if (__pcap_io->prepare_access_pcap) { ret = __pcap_io->prepare_access_pcap(fd, PCAP_MODE_RD, ctx->jumbo); if (ret) panic("Error prepare reading pcap!\n"); } fmemset(&tx_ring, 0, sizeof(tx_ring)); fmemset(&bpf_ops, 0, sizeof(bpf_ops)); if (ctx->rfraw) { ctx->device_trans = xstrdup(ctx->device_out); xfree(ctx->device_out); enter_rfmon_mac80211(ctx->device_trans, &ctx->device_out); if (ctx->link_type != LINKTYPE_IEEE802_11) panic("Wrong linktype of pcap!\n"); } ifindex = device_ifindex(ctx->device_out); size = ring_size(ctx->device_out, ctx->reserve_size); bpf_parse_rules(ctx->filter, &bpf_ops, ctx->link_type); if (ctx->dump_bpf) bpf_dump_all(&bpf_ops); set_packet_loss_discard(tx_sock); setup_tx_ring_layout(tx_sock, &tx_ring, size, ctx->jumbo); create_tx_ring(tx_sock, &tx_ring, ctx->verbose); mmap_tx_ring(tx_sock, &tx_ring); alloc_tx_ring_frames(tx_sock, &tx_ring); bind_tx_ring(tx_sock, &tx_ring, ifindex); dissector_init_all(ctx->print_mode); if (ctx->cpu >= 0 && ifindex > 0) { irq = device_irq_number(ctx->device_out); device_set_irq_affinity(irq, ctx->cpu); if (ctx->verbose) printf("IRQ: %s:%d > CPU%d\n", ctx->device_out, irq, ctx->cpu); } if (ctx->kpull) interval = ctx->kpull; set_itimer_interval_value(&itimer, 0, interval); setitimer(ITIMER_REAL, &itimer, NULL); drop_privileges(ctx->enforce, ctx->uid, ctx->gid); printf("Running! Hang up with ^C!\n\n"); fflush(stdout); bug_on(gettimeofday(&start, NULL)); while (likely(sigint == 0)) { while (user_may_pull_from_tx(tx_ring.frames[it].iov_base)) { hdr = tx_ring.frames[it].iov_base; out = ((uint8_t *) hdr) + TPACKET2_HDRLEN - sizeof(struct sockaddr_ll); do { ret = __pcap_io->read_pcap(fd, &phdr, ctx->magic, out, ring_frame_size(&tx_ring)); if (unlikely(ret <= 0)) goto out; if (ring_frame_size(&tx_ring) < pcap_get_length(&phdr, ctx->magic)) { pcap_set_length(&phdr, ctx->magic, ring_frame_size(&tx_ring)); trunced++; } } while (ctx->filter && !bpf_run_filter(&bpf_ops, out, pcap_get_length(&phdr, ctx->magic))); pcap_pkthdr_to_tpacket_hdr(&phdr, ctx->magic, &hdr->tp_h, &hdr->s_ll); ctx->tx_bytes += hdr->tp_h.tp_len;; ctx->tx_packets++; show_frame_hdr(hdr, ctx->print_mode); dissector_entry_point(out, hdr->tp_h.tp_snaplen, ctx->link_type, ctx->print_mode); kernel_may_pull_from_tx(&hdr->tp_h); it++; if (it >= tx_ring.layout.tp_frame_nr) it = 0; if (unlikely(sigint == 1)) break; if (frame_count_max != 0) { if (ctx->tx_packets >= frame_count_max) { sigint = 1; break; } } } } out: bug_on(gettimeofday(&end, NULL)); timersub(&end, &start, &diff); timer_purge(); bpf_release(&bpf_ops); dissector_cleanup_all(); destroy_tx_ring(tx_sock, &tx_ring); if (ctx->rfraw) leave_rfmon_mac80211(ctx->device_trans, ctx->device_out); if (__pcap_io->prepare_close_pcap) __pcap_io->prepare_close_pcap(fd, PCAP_MODE_RD); if (!strncmp("-", ctx->device_in, strlen("-"))) dup2(fd, fileno(stdin)); close(fd); close(tx_sock); fflush(stdout); printf("\n"); printf("\r%12lu packets outgoing\n", ctx->tx_packets); printf("\r%12lu packets truncated in file\n", trunced); printf("\r%12lu bytes outgoing\n", ctx->tx_bytes); printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec); }
static void recv_only_or_dump(struct ctx *ctx) { short ifflags = 0; int sock, ifindex, fd = 0, ret; size_t size; unsigned int it = 0; struct ring rx_ring; struct pollfd rx_poll; struct sock_fprog bpf_ops; struct timeval start, end, diff; bool is_v3 = is_defined(HAVE_TPACKET3); sock = pf_socket_type(ctx->link_type); ifindex = device_ifindex(ctx->device_in); size = ring_size(ctx->device_in, ctx->reserve_size); enable_kernel_bpf_jit_compiler(); bpf_parse_rules(ctx->filter, &bpf_ops, ctx->link_type); if (ctx->dump_bpf) bpf_dump_all(&bpf_ops); bpf_attach_to_sock(sock, &bpf_ops); if (ctx->hwtimestamp) { ret = set_sockopt_hwtimestamp(sock, ctx->device_in); if (ret == 0 && ctx->verbose) printf("HW timestamping enabled\n"); } ring_rx_setup(&rx_ring, sock, size, ifindex, &rx_poll, is_v3, true, ctx->verbose, ctx->fanout_group, ctx->fanout_type); dissector_init_all(ctx->print_mode); if (ctx->cpu >= 0 && ifindex > 0) { int irq = device_irq_number(ctx->device_in); device_set_irq_affinity(irq, ctx->cpu); if (ctx->verbose) printf("IRQ: %s:%d > CPU%d\n", ctx->device_in, irq, ctx->cpu); } if (ctx->promiscuous) ifflags = device_enter_promiscuous_mode(ctx->device_in); if (dump_to_pcap(ctx) && __pcap_io->init_once_pcap) __pcap_io->init_once_pcap(true); drop_privileges(ctx->enforce, ctx->uid, ctx->gid); if (dump_to_pcap(ctx)) { struct stat stats; ret = stat(ctx->device_out, &stats); if (ret < 0) ctx->dump_dir = 0; else ctx->dump_dir = S_ISDIR(stats.st_mode); if (ctx->dump_dir) fd = begin_multi_pcap_file(ctx); else fd = begin_single_pcap_file(ctx); } printf("Running! Hang up with ^C!\n\n"); fflush(stdout); bug_on(gettimeofday(&start, NULL)); while (likely(sigint == 0)) { #ifdef HAVE_TPACKET3 struct block_desc *pbd; while (user_may_pull_from_rx_block((pbd = rx_ring.frames[it].iov_base))) { walk_t3_block(pbd, ctx, sock, &fd); kernel_may_pull_from_rx_block(pbd); it = (it + 1) % rx_ring.layout3.tp_block_nr; if (unlikely(sigint == 1)) break; } #else while (user_may_pull_from_rx(rx_ring.frames[it].iov_base)) { struct frame_map *hdr = rx_ring.frames[it].iov_base; uint8_t *packet = ((uint8_t *) hdr) + hdr->tp_h.tp_mac; pcap_pkthdr_t phdr; if (ctx->packet_type != -1) if (ctx->packet_type != hdr->s_ll.sll_pkttype) goto next; ctx->pkts_seen++; if (unlikely(ring_frame_size(&rx_ring) < hdr->tp_h.tp_snaplen)) { /* XXX: silently ignore for now. We used to * report them with dump_rx_stats() */ goto next; } if (dump_to_pcap(ctx)) { tpacket_hdr_to_pcap_pkthdr(&hdr->tp_h, &hdr->s_ll, &phdr, ctx->magic); ret = __pcap_io->write_pcap(fd, &phdr, ctx->magic, packet, pcap_get_length(&phdr, ctx->magic)); if (unlikely(ret != (int) pcap_get_total_length(&phdr, ctx->magic))) panic("Write error to pcap!\n"); } show_frame_hdr(packet, hdr->tp_h.tp_snaplen, ctx->link_type, hdr, ctx->print_mode, ctx->pkts_seen); dissector_entry_point(packet, hdr->tp_h.tp_snaplen, ctx->link_type, ctx->print_mode, &hdr->s_ll); if (frame_count_max != 0) { if (unlikely(ctx->pkts_seen >= frame_count_max)) { sigint = 1; break; } } next: kernel_may_pull_from_rx(&hdr->tp_h); it = (it + 1) % rx_ring.layout.tp_frame_nr; if (unlikely(sigint == 1)) break; update_pcap_next_dump(ctx, hdr->tp_h.tp_snaplen, &fd, sock, is_v3); } #endif /* HAVE_TPACKET3 */ ret = poll(&rx_poll, 1, -1); if (unlikely(ret < 0)) { if (errno != EINTR) panic("Poll failed!\n"); } } bug_on(gettimeofday(&end, NULL)); timersub(&end, &start, &diff); dump_rx_stats(ctx, sock, is_v3); printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec); bpf_release(&bpf_ops); dissector_cleanup_all(); destroy_rx_ring(sock, &rx_ring); if (ctx->promiscuous) device_leave_promiscuous_mode(ctx->device_in, ifflags); if (ctx->rfraw) leave_rfmon_mac80211(ctx->device_in); if (dump_to_pcap(ctx)) { if (ctx->dump_dir) finish_multi_pcap_file(ctx, fd); else finish_single_pcap_file(ctx, fd); } close(sock); }
/* Processes the current directive. * If the encoder returns an error, a message including current file and * line number together with the pt error string is printed on stderr. * * Returns 0 on success; a negative enum errcode otherwise. * Returns -err_internal if @p or @e is the NULL pointer. * Returns -err_parse_missing_directive if there was a pt directive marker, * but no directive. * Returns -stop_process if the .exp directive was encountered. * Returns -err_pt_lib if the pt encoder returned an error. * Returns -err_parse if a general parsing error was encountered. * Returns -err_parse_unknown_directive if there was an unknown pt directive. */ static int p_process(struct parser *p, struct pt_encoder *e) { int bytes_written; int errcode; char *directive, *payload, *pt_label_name, *tmp; struct pt_directive *pd; struct pt_packet packet; if (bug_on(!p)) return -err_internal; if (bug_on(!e)) return -err_internal; pd = p->pd; if (!pd) return -err_internal; directive = pd->name; payload = pd->payload; pt_label_name = NULL; bytes_written = 0; errcode = 0; /* find a label name. */ tmp = strchr(directive, ':'); if (tmp) { uint64_t x; pt_label_name = directive; directive = tmp+1; *tmp = '\0'; /* ignore whitespace between label and directive. */ while (isspace(*directive)) directive += 1; /* if we can lookup a yasm label with the same name, the * current pt directive label is invalid. */ errcode = yasm_lookup_label(p->y, &x, pt_label_name); if (errcode == 0) errcode = -err_label_not_unique; if (errcode != -err_no_label) return yasm_print_err(p->y, "label lookup", errcode); /* if we can lookup a pt directive label with the same * name, the current pt directive label is invalid. */ errcode = l_lookup(p->pt_labels, &x, pt_label_name); if (errcode == 0) errcode = -err_label_not_unique; if (errcode != -err_no_label) return yasm_print_err(p->y, "label lookup", -err_label_not_unique); } /* now try to match the directive string and call the * corresponding function that parses the payload and emits an * according packet. */ if (strcmp(directive, "") == 0) return yasm_print_err(p->y, "invalid syntax", -err_parse_missing_directive); else if (strcmp(directive, ".exp") == 0) { /* this is the end of processing pt directives, so we * add a p_last label to the pt directive labels. */ errcode = l_append(p->pt_labels, "eos", p->pt_bytes_written); if (errcode < 0) return yasm_print_err(p->y, "append label", errcode); return -stop_process; } if (strcmp(directive, "psb") == 0) { errcode = parse_empty(payload); if (errcode < 0) { yasm_print_err(p->y, "psb: parsing failed", errcode); goto error; } packet.type = ppt_psb; } else if (strcmp(directive, "psbend") == 0) { errcode = parse_empty(payload); if (errcode < 0) { yasm_print_err(p->y, "psbend: parsing failed", errcode); goto error; } packet.type = ppt_psbend; } else if (strcmp(directive, "pad") == 0) { errcode = parse_empty(payload); if (errcode < 0) { yasm_print_err(p->y, "pad: parsing failed", errcode); goto error; } packet.type = ppt_pad; } else if (strcmp(directive, "ovf") == 0) { errcode = parse_empty(payload); if (errcode < 0) { yasm_print_err(p->y, "ovf: parsing failed", errcode); goto error; } packet.type = ppt_ovf; } else if (strcmp(directive, "tnt") == 0) { errcode = parse_tnt(&packet.payload.tnt.payload, &packet.payload.tnt.bit_size, payload); if (errcode < 0) { yasm_print_err(p->y, "tnt: parsing failed", errcode); goto error; } packet.type = ppt_tnt_8; } else if (strcmp(directive, "tnt64") == 0) { errcode = parse_tnt(&packet.payload.tnt.payload, &packet.payload.tnt.bit_size, payload); if (errcode < 0) { yasm_print_err(p->y, "tnt64: parsing failed", errcode); goto error; } packet.type = ppt_tnt_64; } else if (strcmp(directive, "tip") == 0) { errcode = parse_ip(p, &packet.payload.ip.ip, &packet.payload.ip.ipc, payload); if (errcode < 0) { yasm_print_err(p->y, "tip: parsing failed", errcode); goto error; } packet.type = ppt_tip; } else if (strcmp(directive, "tip.pge") == 0) { errcode = parse_ip(p, &packet.payload.ip.ip, &packet.payload.ip.ipc, payload); if (errcode < 0) { yasm_print_err(p->y, "tip.pge: parsing failed", errcode); goto error; } packet.type = ppt_tip_pge; } else if (strcmp(directive, "tip.pgd") == 0) { errcode = parse_ip(p, &packet.payload.ip.ip, &packet.payload.ip.ipc, payload); if (errcode < 0) { yasm_print_err(p->y, "tip.pgd: parsing failed", errcode); goto error; } packet.type = ppt_tip_pgd; } else if (strcmp(directive, "fup") == 0) { errcode = parse_ip(p, &packet.payload.ip.ip, &packet.payload.ip.ipc, payload); if (errcode < 0) { yasm_print_err(p->y, "fup: parsing failed", errcode); goto error; } packet.type = ppt_fup; } else if (strcmp(directive, "mode.exec") == 0) { if (strcmp(payload, "16bit") == 0) { packet.payload.mode.bits.exec.csl = 0; packet.payload.mode.bits.exec.csd = 0; } else if (strcmp(payload, "64bit") == 0) { packet.payload.mode.bits.exec.csl = 1; packet.payload.mode.bits.exec.csd = 0; } else if (strcmp(payload, "32bit") == 0) { packet.payload.mode.bits.exec.csl = 0; packet.payload.mode.bits.exec.csd = 1; } else { errcode = yasm_print_err(p->y, "mode.exec: argument must be one of \"16bit\", \"64bit\" or \"32bit\"", -err_parse); goto error; } packet.payload.mode.leaf = pt_mol_exec; packet.type = ppt_mode; } else if (strcmp(directive, "mode.tsx") == 0) { if (strcmp(payload, "begin") == 0) { packet.payload.mode.bits.tsx.intx = 1; packet.payload.mode.bits.tsx.abrt = 0; } else if (strcmp(payload, "abort") == 0) { packet.payload.mode.bits.tsx.intx = 0; packet.payload.mode.bits.tsx.abrt = 1; } else if (strcmp(payload, "commit") == 0) { packet.payload.mode.bits.tsx.intx = 0; packet.payload.mode.bits.tsx.abrt = 0; } else { errcode = yasm_print_err(p->y, "mode.tsx: argument must be one of \"begin\", \"abort\" or \"commit\"", -err_parse); goto error; } packet.payload.mode.leaf = pt_mol_tsx; packet.type = ppt_mode; } else if (strcmp(directive, "pip") == 0) { errcode = parse_uint64(&packet.payload.pip.cr3, payload); if (errcode < 0) { yasm_print_err(p->y, "pip: parsing failed", errcode); goto error; } packet.type = ppt_pip; } else if (strcmp(directive, "tsc") == 0) { errcode = parse_uint64(&packet.payload.tsc.tsc, payload); if (errcode < 0) { yasm_print_err(p->y, "tsc: parsing failed", errcode); goto error; } packet.type = ppt_tsc; } else if (strcmp(directive, "cbr") == 0) { errcode = parse_uint8(&packet.payload.cbr.ratio, payload); if (errcode < 0) { yasm_print_err(p->y, "cbr: parsing cbr failed", errcode); goto error; } packet.type = ppt_cbr; } else { errcode = yasm_print_err(p->y, "invalid syntax", -err_parse_unknown_directive); goto error; } bytes_written = pt_enc_next(e, &packet); if (bytes_written < 0) { const char *errstr, *format; char *msg; size_t n; errstr = pt_errstr(pt_errcode(bytes_written)); format = "encoder error in directive %s (status %s)"; /* the length of format includes the "%s" (-2) * characters, we add errstr (+-0) and then we need * space for a terminating null-byte (+1). */ n = strlen(format)-4 + strlen(directive) + strlen(errstr) + 1; msg = malloc(n); if (!msg) errcode = yasm_print_err(p->y, "encoder error not enough memory to show error code", -err_pt_lib); else { sprintf(msg, format, directive, errstr); errcode = yasm_print_err(p->y, msg, -err_pt_lib); free(msg); } } else { if (pt_label_name) { errcode = l_append(p->pt_labels, pt_label_name, p->pt_bytes_written); if (errcode < 0) goto error; } p->pt_bytes_written += bytes_written; } error: if (errcode < 0) bytes_written = errcode; return bytes_written; }
static void read_pcap(struct ctx *ctx) { uint8_t *out; int ret, fd, fdo = 0; unsigned long trunced = 0; size_t out_len; pcap_pkthdr_t phdr; struct sock_fprog bpf_ops; struct frame_map fm; struct timeval start, end, diff; bool is_out_pcap = ctx->device_out && strstr(ctx->device_out, ".pcap"); const struct pcap_file_ops *pcap_out_ops = pcap_ops[PCAP_OPS_RW]; bug_on(!__pcap_io); if (!strncmp("-", ctx->device_in, strlen("-"))) { fd = dup_or_die(fileno(stdin)); close(fileno(stdin)); if (ctx->pcap == PCAP_OPS_MM) ctx->pcap = PCAP_OPS_SG; } else { /* O_NOATIME requires privileges, in case we don't have * them, retry without them at a minor cost of updating * atime in case the fs has been mounted as such. */ fd = open(ctx->device_in, O_RDONLY | O_LARGEFILE | O_NOATIME); if (fd < 0 && errno == EPERM) fd = open_or_die(ctx->device_in, O_RDONLY | O_LARGEFILE); if (fd < 0) panic("Cannot open file %s! %s.\n", ctx->device_in, strerror(errno)); } if (__pcap_io->init_once_pcap) __pcap_io->init_once_pcap(false); ret = __pcap_io->pull_fhdr_pcap(fd, &ctx->magic, &ctx->link_type); if (ret) panic("Error reading pcap header!\n"); if (__pcap_io->prepare_access_pcap) { ret = __pcap_io->prepare_access_pcap(fd, PCAP_MODE_RD, ctx->jumbo); if (ret) panic("Error prepare reading pcap!\n"); } fmemset(&fm, 0, sizeof(fm)); bpf_parse_rules(ctx->filter, &bpf_ops, ctx->link_type); if (ctx->dump_bpf) bpf_dump_all(&bpf_ops); dissector_init_all(ctx->print_mode); out_len = round_up(1024 * 1024, RUNTIME_PAGE_SIZE); out = xmalloc_aligned(out_len, CO_CACHE_LINE_SIZE); if (ctx->device_out) { if (!strncmp("-", ctx->device_out, strlen("-"))) { fdo = dup_or_die(fileno(stdout)); close(fileno(stdout)); } else { fdo = open_or_die_m(ctx->device_out, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE, DEFFILEMODE); } } if (is_out_pcap) { ret = pcap_out_ops->push_fhdr_pcap(fdo, ctx->magic, ctx->link_type); if (ret) panic("Error writing pcap header!\n"); } drop_privileges(ctx->enforce, ctx->uid, ctx->gid); printf("Running! Hang up with ^C!\n\n"); fflush(stdout); bug_on(gettimeofday(&start, NULL)); while (likely(sigint == 0)) { do { ret = __pcap_io->read_pcap(fd, &phdr, ctx->magic, out, out_len); if (unlikely(ret < 0)) goto out; if (unlikely(pcap_get_length(&phdr, ctx->magic) == 0)) { trunced++; continue; } if (unlikely(pcap_get_length(&phdr, ctx->magic) > out_len)) { pcap_set_length(&phdr, ctx->magic, out_len); trunced++; } } while (ctx->filter && !bpf_run_filter(&bpf_ops, out, pcap_get_length(&phdr, ctx->magic))); pcap_pkthdr_to_tpacket_hdr(&phdr, ctx->magic, &fm.tp_h, &fm.s_ll); ctx->tx_bytes += fm.tp_h.tp_len; ctx->tx_packets++; show_frame_hdr(out, fm.tp_h.tp_snaplen, ctx->link_type, &fm, ctx->print_mode, ctx->tx_packets); dissector_entry_point(out, fm.tp_h.tp_snaplen, ctx->link_type, ctx->print_mode, &fm.s_ll); if (is_out_pcap) { size_t pcap_len = pcap_get_length(&phdr, ctx->magic); int wlen = pcap_out_ops->write_pcap(fdo, &phdr, ctx->magic, out, pcap_len); if (unlikely(wlen != (int)pcap_get_total_length(&phdr, ctx->magic))) panic("Error writing to pcap!\n"); } else if (ctx->device_out) { translate_pcap_to_txf(fdo, out, fm.tp_h.tp_snaplen); } if (frame_count_max != 0) { if (ctx->tx_packets >= frame_count_max) { sigint = 1; break; } } } out: bug_on(gettimeofday(&end, NULL)); timersub(&end, &start, &diff); bpf_release(&bpf_ops); dissector_cleanup_all(); if (__pcap_io->prepare_close_pcap) __pcap_io->prepare_close_pcap(fd, PCAP_MODE_RD); xfree(out); fflush(stdout); printf("\n"); printf("\r%12lu packets outgoing\n", ctx->tx_packets); printf("\r%12lu packets truncated in file\n", trunced); printf("\r%12lu bytes outgoing\n", ctx->tx_bytes); printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec); if (!strncmp("-", ctx->device_in, strlen("-"))) dup2(fd, fileno(stdin)); close(fd); if (ctx->device_out) { if (!strncmp("-", ctx->device_out, strlen("-"))) dup2(fdo, fileno(stdout)); close(fdo); } }
/* Generates the content of the .exp file by printing all lines with * everything up to and including the first comment semicolon removed. * * Returns 0 on success; a negative enum errcode otherwise. * Returns -err_internal if @p is the NULL pointer. * Returns -err_file_write if the .exp file could not be fully written. */ static int p_gen_expfile(struct parser *p) { int errcode; enum { slen = 1024 }; char s[slen]; struct pt_directive *pd; char *filename; FILE *f; if (bug_on(!p)) return -err_internal; pd = p->pd; /* the directive in the current line must be the .exp directive. */ errcode = yasm_pd_parse(p->y, pd); if (bug_on(errcode < 0)) return -err_internal; if (bug_on(strcmp(pd->name, ".exp") != 0)) return -err_internal; filename = expfilename(p, pd->payload); if (!filename) return -err_no_mem; f = fopen(filename, "w"); if (!f) { free(filename); return -err_file_open; } for (;;) { int i; char *line, *comment; errcode = yasm_next_line(p->y, s, slen); if (errcode < 0) break; errcode = yasm_pd_parse(p->y, pd); if (errcode < 0 && errcode != -err_no_directive) break; if (errcode == 0 && strcmp(pd->name, ".exp") == 0) { fclose(f); printf("%s\n", filename); free(filename); filename = expfilename(p, pd->payload); if (!filename) return -err_no_mem; f = fopen(filename, "w"); if (!f) { free(filename); return -err_file_open; } continue; } line = strchr(s, ';'); if (!line) continue; line += 1; comment = strchr(line, '#'); if (comment) *comment = '\0'; /* remove trailing spaces. */ for (i = (int) strlen(line)-1; i >= 0 && isspace(line[i]); i--) line[i] = '\0'; for (;;) { char *tmp, label[256]; uint64_t addr; int i, zero_padding, qmark_padding, qmark_size, status; zero_padding = 0; qmark_padding = 0; qmark_size = 0; /* find the label character in the string. * if there is no label character, we just print * the rest of the line and end. */ tmp = strchr(line, '%'); if (!tmp) { if (fprintf(f, "%s", line) < 0) { errcode = -err_file_write; goto error; } break; } /* make the label character a null byte and * print the first portion, which does not * belong to the label into the file. */ *tmp = '\0'; if (fprintf(f, "%s", line) < 0) { errcode = -err_file_write; goto error; } /* test if there is a valid label name after the %. */ line = tmp+1; if (*line == '\0' || isspace(*line)) { errcode = -err_no_label; goto error; } /* check if zero padding is requested. */ if (*line == '0') { zero_padding = 1; line += 1; } /* chek if ? padding is requested. */ else if (*line == '?') { qmark_padding = 1; zero_padding = 1; qmark_size = 0; line += 1; } /* advance i to the first non alpha-numeric * character. all characters everything from * line[0] to line[i-1] belongs to the label * name. */ for (i = 0; islabelchar(line[i]); i++) ; if (i > 255) { errcode = -err_label_name; goto error; } strncpy(label, line, i); label[i] = '\0'; /* advance to next character. */ line = &line[i]; /* lookup the label name and print it to the * output file. */ errcode = yasm_lookup_label(p->y, &addr, label); if (errcode < 0) { errcode = l_lookup(p->pt_labels, &addr, label); if (errcode < 0) goto error; if (zero_padding) status = fprintf(f, "%016" PRIx64, addr); else status = fprintf(f, "%" PRIx64, addr); if (status < 0) { errcode = -err_file_write; goto error; } continue; } /* check if masking is requested. */ if (*line == '.') { char *endptr; long int n; line += 1; n = strtol(line, &endptr, 0); /* check if strtol made progress and * stops on a space or null byte. * otherwise the int could not be * parsed. */ if (line == endptr || (*endptr != '\0' && !isspace(*endptr) && !ispunct(*endptr))) { errcode = -err_parse_int; goto error; } addr &= (1 << (n << 3)) - 1; line = endptr; qmark_size = 8 - n; } if (qmark_padding) { int i; status = fprintf(f, "0x"); if (status < 0) { errcode = -err_file_write; goto error; } for (i = 0; i < qmark_size; ++i) { status = fprintf(f, "??"); if (status < 0) { errcode = -err_file_write; goto error; } } for (; i < 8; ++i) { uint8_t byte; byte = (uint8_t)(addr >> ((7 - i) * 8)); status = fprintf(f, "%02" PRIx8, byte); if (status < 0) { errcode = -err_file_write; goto error; } } } else if (zero_padding) status = fprintf(f, "0x%016" PRIx64, addr); else status = fprintf(f, "0x%" PRIx64, addr); if (status < 0) { errcode = -err_file_write; goto error; } } if (fprintf(f, "\n") < 0) { errcode = -err_file_write; goto error; } }
int run(const char *file, char *const argv[]) { int errcode; int i; size_t size; char *args; STARTUPINFO si; PROCESS_INFORMATION pi; DWORD exit_code; DWORD dwret; BOOL bret; errcode = 0; if (bug_on(!file)) { errcode = -err_internal; goto out; } if (bug_on(!argv)) { errcode = -err_internal; goto out; } /* calculate length of command line - this is the cumulative length of * all arguments, plus two quotation marks (to make it quoted strings * and allow for spaces in file/path names), plus a space after each * arguments as delimiter (after the last arguments it's a terminating * zero-byte instead of the space). * */ size = 0; for (i = 0; argv[i]; ++i) size += strlen(argv[i]) + 3; /* allocate command line string */ args = calloc(size, 1); if (!args) return -err_no_mem; /* construct command line string, putting quotation marks * around every argument of the vector and a space after it */ size = 0; for (i = 0; argv[i]; ++i) { args[size++] = '"'; strcpy(args + size, argv[i]); size += strlen(argv[i]); args[size++] = '"'; args[size++] = ' '; } /* transform last space into a terminating zero-byte and fix up size */ args[--size] = '\0'; /* initialize process/startup info */ memset(&pi, 0, sizeof(pi)); memset(&si, 0, sizeof(si)); si.cb = sizeof(si); /* create process - since the first parameter is NULL, the * second parameter represents a command as it would behave * on a command shell */ bret = CreateProcess(NULL, args, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); if (!bret) { errcode = -err_other; goto out_args; } dwret = WaitForSingleObject(pi.hProcess, INFINITE); if (dwret == WAIT_FAILED) { errcode = -err_other; goto out_handles; } bret = GetExitCodeProcess(pi.hProcess, &exit_code); if (!bret) { errcode = -err_other; goto out_handles; } if (exit_code != 0) errcode = -err_run; out_handles: CloseHandle(pi.hProcess); CloseHandle(pi.hThread); out_args: free(args); out: return errcode; }
static void recv_only_or_dump(struct ctx *ctx) { uint8_t *packet; short ifflags = 0; int sock, irq, ifindex, fd = 0, ret; unsigned int size, it = 0; unsigned long frame_count = 0, skipped = 0; struct ring rx_ring; struct pollfd rx_poll; struct frame_map *hdr; struct sock_fprog bpf_ops; struct timeval start, end, diff; pcap_pkthdr_t phdr; if (!device_up_and_running(ctx->device_in) && !ctx->rfraw) panic("Device not up and running!\n"); sock = pf_socket(); if (ctx->rfraw) { ctx->device_trans = xstrdup(ctx->device_in); xfree(ctx->device_in); enter_rfmon_mac80211(ctx->device_trans, &ctx->device_in); ctx->link_type = LINKTYPE_IEEE802_11; } fmemset(&rx_ring, 0, sizeof(rx_ring)); fmemset(&rx_poll, 0, sizeof(rx_poll)); fmemset(&bpf_ops, 0, sizeof(bpf_ops)); ifindex = device_ifindex(ctx->device_in); size = ring_size(ctx->device_in, ctx->reserve_size); enable_kernel_bpf_jit_compiler(); bpf_parse_rules(ctx->filter, &bpf_ops, ctx->link_type); if (ctx->dump_bpf) bpf_dump_all(&bpf_ops); bpf_attach_to_sock(sock, &bpf_ops); set_sockopt_hwtimestamp(sock, ctx->device_in); setup_rx_ring_layout(sock, &rx_ring, size, ctx->jumbo); create_rx_ring(sock, &rx_ring, ctx->verbose); mmap_rx_ring(sock, &rx_ring); alloc_rx_ring_frames(&rx_ring); bind_rx_ring(sock, &rx_ring, ifindex); prepare_polling(sock, &rx_poll); dissector_init_all(ctx->print_mode); if (ctx->cpu >= 0 && ifindex > 0) { irq = device_irq_number(ctx->device_in); device_bind_irq_to_cpu(irq, ctx->cpu); if (ctx->verbose) printf("IRQ: %s:%d > CPU%d\n", ctx->device_in, irq, ctx->cpu); } if (ctx->promiscuous) ifflags = enter_promiscuous_mode(ctx->device_in); drop_privileges(ctx->enforce, ctx->uid, ctx->gid); if (dump_to_pcap(ctx)) { __label__ try_file; struct stat stats; fmemset(&stats, 0, sizeof(stats)); ret = stat(ctx->device_out, &stats); if (ret < 0) { ctx->dump_dir = 0; goto try_file; } ctx->dump_dir = S_ISDIR(stats.st_mode); if (ctx->dump_dir) { fd = begin_multi_pcap_file(ctx); } else { try_file: fd = begin_single_pcap_file(ctx); } } printf("Running! Hang up with ^C!\n\n"); fflush(stdout); bug_on(gettimeofday(&start, NULL)); while (likely(sigint == 0)) { while (user_may_pull_from_rx(rx_ring.frames[it].iov_base)) { __label__ next; hdr = rx_ring.frames[it].iov_base; packet = ((uint8_t *) hdr) + hdr->tp_h.tp_mac; frame_count++; if (ctx->packet_type != -1) if (ctx->packet_type != hdr->s_ll.sll_pkttype) goto next; if (unlikely(ring_frame_size(&rx_ring) < hdr->tp_h.tp_snaplen)) { skipped++; goto next; } if (dump_to_pcap(ctx)) { tpacket_hdr_to_pcap_pkthdr(&hdr->tp_h, &hdr->s_ll, &phdr, ctx->magic); ret = __pcap_io->write_pcap(fd, &phdr, ctx->magic, packet, pcap_get_length(&phdr, ctx->magic)); if (unlikely(ret != pcap_get_total_length(&phdr, ctx->magic))) panic("Write error to pcap!\n"); } show_frame_hdr(hdr, ctx->print_mode); dissector_entry_point(packet, hdr->tp_h.tp_snaplen, ctx->link_type, ctx->print_mode); if (frame_count_max != 0) { if (frame_count >= frame_count_max) { sigint = 1; break; } } next: kernel_may_pull_from_rx(&hdr->tp_h); it++; if (it >= rx_ring.layout.tp_frame_nr) it = 0; if (unlikely(sigint == 1)) break; if (dump_to_pcap(ctx)) { if (ctx->dump_mode == DUMP_INTERVAL_SIZE) { interval += hdr->tp_h.tp_snaplen; if (interval > ctx->dump_interval) { next_dump = true; interval = 0; } } if (next_dump) { fd = next_multi_pcap_file(ctx, fd); next_dump = false; if (ctx->verbose) print_pcap_file_stats(sock, ctx, skipped); } } } poll(&rx_poll, 1, -1); } bug_on(gettimeofday(&end, NULL)); timersub(&end, &start, &diff); if (!(ctx->dump_dir && ctx->print_mode == PRINT_NONE)) { sock_print_net_stats(sock, skipped); printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec); } else { printf("\n\n"); fflush(stdout); } bpf_release(&bpf_ops); dissector_cleanup_all(); destroy_rx_ring(sock, &rx_ring); if (ctx->promiscuous) leave_promiscuous_mode(ctx->device_in, ifflags); if (ctx->rfraw) leave_rfmon_mac80211(ctx->device_trans, ctx->device_in); if (dump_to_pcap(ctx)) { if (ctx->dump_dir) finish_multi_pcap_file(ctx, fd); else finish_single_pcap_file(ctx, fd); } close(sock); }
static void xmit_slowpath_or_die(struct ctx *ctx, unsigned int cpu, unsigned long orig_num) { int ret, icmp_sock = -1; unsigned long num = 1, i = 0; struct timeval start, end, diff; unsigned long long tx_bytes = 0, tx_packets = 0; struct packet_dyn *pktd; struct sockaddr_ll saddr = { .sll_family = PF_PACKET, .sll_halen = ETH_ALEN, .sll_ifindex = device_ifindex(ctx->device), }; if (ctx->num > 0) num = ctx->num; if (ctx->num == 0 && orig_num > 0) num = 0; if (ctx->smoke_test) icmp_sock = xmit_smoke_setup(ctx); drop_privileges(ctx->enforce, ctx->uid, ctx->gid); bug_on(gettimeofday(&start, NULL)); while (likely(sigint == 0 && num > 0 && plen > 0)) { pktd = &packet_dyn[i]; if (pktd->clen + pktd->rlen + pktd->slen) { apply_counter(i); apply_randomizer(i); apply_csum16(i); } retry: ret = sendto(sock, packets[i].payload, packets[i].len, 0, (struct sockaddr *) &saddr, sizeof(saddr)); if (unlikely(ret < 0)) { if (errno == ENOBUFS) { sched_yield(); goto retry; } if (ctx->smoke_test) panic("Sendto error: %s!\n", strerror(errno)); } tx_bytes += packets[i].len; tx_packets++; if (ctx->smoke_test) { ret = xmit_smoke_probe(icmp_sock, ctx); if (unlikely(ret < 0)) { printf("%sSmoke test alert:%s\n", colorize_start(bold), colorize_end()); printf(" Remote host seems to be unresponsive to ICMP probes!\n"); printf(" Last instance was packet%lu, seed:%u, trafgen snippet:\n\n", i, seed); dump_trafgen_snippet(packets[i].payload, packets[i].len); break; } } if (!ctx->rand) { i++; if (i >= plen) i = 0; } else i = rand() % plen; if (ctx->num > 0) num--; if ((ctx->gap.tv_sec | ctx->gap.tv_nsec) > 0) nanosleep(&ctx->gap, NULL); } bug_on(gettimeofday(&end, NULL)); timersub(&end, &start, &diff); if (ctx->smoke_test) close(icmp_sock); stats[cpu].tx_packets = tx_packets; stats[cpu].tx_bytes = tx_bytes; stats[cpu].tv_sec = diff.tv_sec; stats[cpu].tv_usec = diff.tv_usec; stats[cpu].state |= CPU_STATS_STATE_RES; } static void xmit_fastpath_or_die(struct ctx *ctx, unsigned int cpu, unsigned long orig_num) { int ifindex = device_ifindex(ctx->device); uint8_t *out = NULL; unsigned int it = 0; unsigned long num = 1, i = 0; size_t size = ring_size(ctx->device, ctx->reserve_size); struct ring tx_ring; struct frame_map *hdr; struct timeval start, end, diff; struct packet_dyn *pktd; unsigned long long tx_bytes = 0, tx_packets = 0; set_sock_prio(sock, 512); ring_tx_setup(&tx_ring, sock, size, ifindex, ctx->jumbo_support, ctx->verbose); drop_privileges(ctx->enforce, ctx->uid, ctx->gid); if (ctx->num > 0) num = ctx->num; if (ctx->num == 0 && orig_num > 0) num = 0; bug_on(gettimeofday(&start, NULL)); while (likely(sigint == 0 && num > 0 && plen > 0)) { if (!user_may_pull_from_tx(tx_ring.frames[it].iov_base)) { int ret = pull_and_flush_tx_ring(sock); if (unlikely(ret < 0)) { /* We could hit EBADF if the socket has been closed before * the timer was triggered. */ if (errno != EBADF && errno != ENOBUFS) panic("Flushing TX_RING failed: %s!\n", strerror(errno)); } continue; } hdr = tx_ring.frames[it].iov_base; out = ((uint8_t *) hdr) + TPACKET2_HDRLEN - sizeof(struct sockaddr_ll); hdr->tp_h.tp_snaplen = packets[i].len; hdr->tp_h.tp_len = packets[i].len; pktd = &packet_dyn[i]; if (pktd->clen + pktd->rlen + pktd->slen) { apply_counter(i); apply_randomizer(i); apply_csum16(i); } fmemcpy(out, packets[i].payload, packets[i].len); tx_bytes += packets[i].len; tx_packets++; if (!ctx->rand) { i++; if (i >= plen) i = 0; } else i = rand() % plen; kernel_may_pull_from_tx(&hdr->tp_h); it++; if (it >= tx_ring.layout.tp_frame_nr) it = 0; if (ctx->num > 0) num--; } bug_on(gettimeofday(&end, NULL)); timersub(&end, &start, &diff); pull_and_flush_tx_ring_wait(sock); destroy_tx_ring(sock, &tx_ring); stats[cpu].tx_packets = tx_packets; stats[cpu].tx_bytes = tx_bytes; stats[cpu].tv_sec = diff.tv_sec; stats[cpu].tv_usec = diff.tv_usec; stats[cpu].state |= CPU_STATS_STATE_RES; }
int main(int argc, char **argv) { char *ptr; int c, i, j, cpu_tmp, opt_index, ops_touched = 0, vals[4] = {0}; bool prio_high = false, setsockmem = true; void (*main_loop)(struct ctx *ctx) = NULL; struct ctx ctx; init_ctx(&ctx); srand(time(NULL)); while ((c = getopt_long(argc, argv, short_options, long_options, &opt_index)) != EOF) { switch (c) { case 'd': case 'i': ctx.device_in = xstrdup(optarg); break; case 'o': ctx.device_out = xstrdup(optarg); break; case 'P': ctx.prefix = xstrdup(optarg); break; case 'R': ctx.rfraw = 1; break; case 'r': ctx.randomize = true; break; case 'J': ctx.jumbo = true; break; case 'T': ctx.magic = (uint32_t) strtoul(optarg, NULL, 0); pcap_check_magic(ctx.magic); break; case 'f': ctx.filter = xstrdup(optarg); break; case 'M': ctx.promiscuous = false; break; case 'N': ctx.hwtimestamp = false; break; case 'A': setsockmem = false; break; case 'u': ctx.uid = strtoul(optarg, NULL, 0); ctx.enforce = true; break; case 'g': ctx.gid = strtoul(optarg, NULL, 0); ctx.enforce = true; break; case 'C': ctx.fanout_group = strtoul(optarg, NULL, 0); if (ctx.fanout_group == 0) panic("Non-zero fanout group id required!\n"); break; case 'K': if (!strncmp(optarg, "hash", strlen("hash"))) ctx.fanout_type = PACKET_FANOUT_HASH; else if (!strncmp(optarg, "lb", strlen("lb")) || !strncmp(optarg, "rr", strlen("rr"))) ctx.fanout_type = PACKET_FANOUT_LB; else if (!strncmp(optarg, "cpu", strlen("cpu"))) ctx.fanout_type = PACKET_FANOUT_CPU; else if (!strncmp(optarg, "rnd", strlen("rnd"))) ctx.fanout_type = PACKET_FANOUT_RND; else if (!strncmp(optarg, "roll", strlen("roll"))) ctx.fanout_type = PACKET_FANOUT_ROLLOVER; else if (!strncmp(optarg, "qm", strlen("qm"))) ctx.fanout_type = PACKET_FANOUT_QM; else panic("Unknown fanout type!\n"); break; case 'L': if (!strncmp(optarg, "defrag", strlen("defrag"))) ctx.fanout_type |= PACKET_FANOUT_FLAG_DEFRAG; else if (!strncmp(optarg, "roll", strlen("roll"))) ctx.fanout_type |= PACKET_FANOUT_FLAG_ROLLOVER; else panic("Unknown fanout option!\n"); break; case 't': if (!strncmp(optarg, "host", strlen("host"))) ctx.packet_type = PACKET_HOST; else if (!strncmp(optarg, "broadcast", strlen("broadcast"))) ctx.packet_type = PACKET_BROADCAST; else if (!strncmp(optarg, "multicast", strlen("multicast"))) ctx.packet_type = PACKET_MULTICAST; else if (!strncmp(optarg, "others", strlen("others"))) ctx.packet_type = PACKET_OTHERHOST; else if (!strncmp(optarg, "outgoing", strlen("outgoing"))) ctx.packet_type = PACKET_OUTGOING; else ctx.packet_type = -1; break; case 'S': ptr = optarg; for (j = i = strlen(optarg); i > 0; --i) { if (!isdigit(optarg[j - i])) break; ptr++; } if (!strncmp(ptr, "KiB", strlen("KiB"))) ctx.reserve_size = 1 << 10; else if (!strncmp(ptr, "MiB", strlen("MiB"))) ctx.reserve_size = 1 << 20; else if (!strncmp(ptr, "GiB", strlen("GiB"))) ctx.reserve_size = 1 << 30; else panic("Syntax error in ring size param!\n"); ctx.reserve_size *= strtoul(optarg, NULL, 0); break; case 'b': cpu_tmp = strtol(optarg, NULL, 0); cpu_affinity(cpu_tmp); if (ctx.cpu != -2) ctx.cpu = cpu_tmp; break; case 'H': prio_high = true; break; case 'c': ctx.pcap = PCAP_OPS_RW; ops_touched = 1; break; case 'm': ctx.pcap = PCAP_OPS_MM; ops_touched = 1; break; case 'G': ctx.pcap = PCAP_OPS_SG; ops_touched = 1; break; case 'Q': ctx.cpu = -2; break; case 's': ctx.print_mode = PRINT_NONE; break; case 'q': ctx.print_mode = PRINT_LESS; break; case 'X': ctx.print_mode = (ctx.print_mode == PRINT_ASCII) ? PRINT_HEX_ASCII : PRINT_HEX; break; case 'l': ctx.print_mode = (ctx.print_mode == PRINT_HEX) ? PRINT_HEX_ASCII : PRINT_ASCII; break; case 'k': ctx.kpull = strtoul(optarg, NULL, 0); break; case 'n': frame_count_max = strtoul(optarg, NULL, 0); break; case 'F': ptr = optarg; for (j = i = strlen(optarg); i > 0; --i) { if (!isdigit(optarg[j - i])) break; ptr++; } if (!strncmp(ptr, "KiB", strlen("KiB"))) { ctx.dump_interval = 1 << 10; ctx.dump_mode = DUMP_INTERVAL_SIZE; } else if (!strncmp(ptr, "MiB", strlen("MiB"))) { ctx.dump_interval = 1 << 20; ctx.dump_mode = DUMP_INTERVAL_SIZE; } else if (!strncmp(ptr, "GiB", strlen("GiB"))) { ctx.dump_interval = 1 << 30; ctx.dump_mode = DUMP_INTERVAL_SIZE; } else if (!strncmp(ptr, "sec", strlen("sec"))) { ctx.dump_interval = 1; ctx.dump_mode = DUMP_INTERVAL_TIME; } else if (!strncmp(ptr, "min", strlen("min"))) { ctx.dump_interval = 60; ctx.dump_mode = DUMP_INTERVAL_TIME; } else if (!strncmp(ptr, "hrs", strlen("hrs"))) { ctx.dump_interval = 60 * 60; ctx.dump_mode = DUMP_INTERVAL_TIME; } else if (!strncmp(ptr, "s", strlen("s"))) { ctx.dump_interval = 1; ctx.dump_mode = DUMP_INTERVAL_TIME; } else { panic("Syntax error in time/size param!\n"); } ctx.dump_interval *= strtoul(optarg, NULL, 0); break; case 'V': ctx.verbose = true; break; case 'B': ctx.dump_bpf = true; break; case 'D': pcap_dump_type_features(); die(); break; case 'U': update_geoip(); die(); break; case 'w': ctx.link_type = LINKTYPE_LINUX_SLL; break; case 'v': version(); break; case 'h': help(); break; case '?': switch (optopt) { case 'd': case 'i': case 'o': case 'f': case 't': case 'P': case 'F': case 'n': case 'S': case 'b': case 'k': case 'T': case 'u': case 'g': case 'e': panic("Option -%c requires an argument!\n", optopt); default: if (isprint(optopt)) printf("Unknown option character `0x%X\'!\n", optopt); die(); } default: break; } } if (!ctx.filter && optind != argc) ctx.filter = argv2str(optind, argc, argv); if (!ctx.device_in) ctx.device_in = xstrdup("any"); register_signal(SIGINT, signal_handler); register_signal(SIGQUIT, signal_handler); register_signal(SIGTERM, signal_handler); register_signal(SIGHUP, signal_handler); tprintf_init(); if (prio_high) { set_proc_prio(-20); set_sched_status(SCHED_FIFO, sched_get_priority_max(SCHED_FIFO)); } if (device_mtu(ctx.device_in) || !strncmp("any", ctx.device_in, strlen(ctx.device_in))) { if (ctx.rfraw) setup_rfmon_mac80211_dev(&ctx, &ctx.device_in); if (!ctx.link_type) ctx.link_type = pcap_dev_to_linktype(ctx.device_in); if (link_has_sll_hdr(ctx.link_type)) { switch (ctx.magic) { case ORIGINAL_TCPDUMP_MAGIC: ctx.magic = ORIGINAL_TCPDUMP_MAGIC_LL; break; case NSEC_TCPDUMP_MAGIC: ctx.magic = NSEC_TCPDUMP_MAGIC_LL; break; case ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC): ctx.magic = ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC_LL); break; case ___constant_swab32(NSEC_TCPDUMP_MAGIC): ctx.magic = ___constant_swab32(NSEC_TCPDUMP_MAGIC_LL); break; } } if (!ctx.device_out) { ctx.dump = 0; main_loop = recv_only_or_dump; } else if (device_mtu(ctx.device_out)) { register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO); main_loop = receive_to_xmit; } else { ctx.dump = 1; register_signal_f(SIGALRM, timer_next_dump, SA_SIGINFO); main_loop = recv_only_or_dump; if (!ops_touched) ctx.pcap = PCAP_OPS_SG; } } else { if (ctx.device_out && device_mtu(ctx.device_out)) { register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO); main_loop = pcap_to_xmit; if (!ops_touched) ctx.pcap = PCAP_OPS_MM; } else { setsockmem = false; main_loop = read_pcap; if (!ops_touched) ctx.pcap = PCAP_OPS_SG; } } bug_on(!main_loop); init_geoip(0); if (setsockmem) set_system_socket_memory(vals, array_size(vals)); if (!ctx.enforce) xlockme(); if (ctx.verbose) printf("pcap file I/O method: %s\n", pcap_ops_group_to_str[ctx.pcap]); main_loop(&ctx); if (!ctx.enforce) xunlockme(); if (setsockmem) reset_system_socket_memory(vals, array_size(vals)); destroy_geoip(); device_restore_irq_affinity_list(); tprintf_cleanup(); destroy_ctx(&ctx); return 0; }
int main(int argc, char **argv) { char *ptr; int c, i, j, cpu_tmp, opt_index, ops_touched = 0, vals[4] = {0}; bool prio_high = false, setsockmem = true; void (*main_loop)(struct ctx *ctx) = NULL; struct ctx ctx; init_ctx(&ctx); srand(time(NULL)); while ((c = getopt_long(argc, argv, short_options, long_options, &opt_index)) != EOF) { switch (c) { case 'd': case 'i': ctx.device_in = xstrdup(optarg); break; case 'o': ctx.device_out = xstrdup(optarg); break; case 'P': ctx.prefix = xstrdup(optarg); break; case 'R': ctx.link_type = LINKTYPE_IEEE802_11; ctx.rfraw = 1; break; case 'r': ctx.randomize = true; break; case 'J': ctx.jumbo = true; break; case 'T': ctx.magic = (uint32_t) strtoul(optarg, NULL, 0); pcap_check_magic(ctx.magic); break; case 'f': ctx.filter = xstrdup(optarg); break; case 'M': ctx.promiscuous = false; break; case 'A': setsockmem = false; break; case 'u': ctx.uid = strtoul(optarg, NULL, 0); ctx.enforce = true; break; case 'g': ctx.gid = strtoul(optarg, NULL, 0); ctx.enforce = true; break; case 't': if (!strncmp(optarg, "host", strlen("host"))) ctx.packet_type = PACKET_HOST; else if (!strncmp(optarg, "broadcast", strlen("broadcast"))) ctx.packet_type = PACKET_BROADCAST; else if (!strncmp(optarg, "multicast", strlen("multicast"))) ctx.packet_type = PACKET_MULTICAST; else if (!strncmp(optarg, "others", strlen("others"))) ctx.packet_type = PACKET_OTHERHOST; else if (!strncmp(optarg, "outgoing", strlen("outgoing"))) ctx.packet_type = PACKET_OUTGOING; else ctx.packet_type = -1; break; case 'S': ptr = optarg; ctx.reserve_size = 0; for (j = i = strlen(optarg); i > 0; --i) { if (!isdigit(optarg[j - i])) break; ptr++; } if (!strncmp(ptr, "KiB", strlen("KiB"))) ctx.reserve_size = 1 << 10; else if (!strncmp(ptr, "MiB", strlen("MiB"))) ctx.reserve_size = 1 << 20; else if (!strncmp(ptr, "GiB", strlen("GiB"))) ctx.reserve_size = 1 << 30; else panic("Syntax error in ring size param!\n"); *ptr = 0; ctx.reserve_size *= strtol(optarg, NULL, 0); break; case 'b': cpu_tmp = strtol(optarg, NULL, 0); cpu_affinity(cpu_tmp); if (ctx.cpu != -2) ctx.cpu = cpu_tmp; break; case 'H': prio_high = true; break; case 'c': ctx.pcap = PCAP_OPS_RW; ops_touched = 1; break; case 'm': ctx.pcap = PCAP_OPS_MM; ops_touched = 1; break; case 'G': ctx.pcap = PCAP_OPS_SG; ops_touched = 1; break; case 'Q': ctx.cpu = -2; break; case 's': ctx.print_mode = PRINT_NONE; break; case 'q': ctx.print_mode = PRINT_LESS; break; case 'X': ctx.print_mode = (ctx.print_mode == PRINT_ASCII) ? PRINT_HEX_ASCII : PRINT_HEX; break; case 'l': ctx.print_mode = (ctx.print_mode == PRINT_HEX) ? PRINT_HEX_ASCII : PRINT_ASCII; break; case 'k': ctx.kpull = strtol(optarg, NULL, 0); break; case 'n': frame_count_max = strtol(optarg, NULL, 0); break; case 'F': ptr = optarg; ctx.dump_interval = 0; for (j = i = strlen(optarg); i > 0; --i) { if (!isdigit(optarg[j - i])) break; ptr++; } if (!strncmp(ptr, "KiB", strlen("KiB"))) { ctx.dump_interval = 1 << 10; ctx.dump_mode = DUMP_INTERVAL_SIZE; } else if (!strncmp(ptr, "MiB", strlen("MiB"))) { ctx.dump_interval = 1 << 20; ctx.dump_mode = DUMP_INTERVAL_SIZE; } else if (!strncmp(ptr, "GiB", strlen("GiB"))) { ctx.dump_interval = 1 << 30; ctx.dump_mode = DUMP_INTERVAL_SIZE; } else if (!strncmp(ptr, "sec", strlen("sec"))) { ctx.dump_interval = 1; ctx.dump_mode = DUMP_INTERVAL_TIME; } else if (!strncmp(ptr, "min", strlen("min"))) { ctx.dump_interval = 60; ctx.dump_mode = DUMP_INTERVAL_TIME; } else if (!strncmp(ptr, "hrs", strlen("hrs"))) { ctx.dump_interval = 60 * 60; ctx.dump_mode = DUMP_INTERVAL_TIME; } else if (!strncmp(ptr, "s", strlen("s"))) { ctx.dump_interval = 1; ctx.dump_mode = DUMP_INTERVAL_TIME; } else { panic("Syntax error in time/size param!\n"); } *ptr = 0; ctx.dump_interval *= strtol(optarg, NULL, 0); break; case 'V': ctx.verbose = 1; break; case 'B': ctx.dump_bpf = true; break; case 'D': pcap_dump_type_features(); die(); break; case 'U': update_geoip(); die(); break; case 'v': version(); break; case 'h': help(); break; case '?': switch (optopt) { case 'd': case 'i': case 'o': case 'f': case 't': case 'P': case 'F': case 'n': case 'S': case 'b': case 'k': case 'T': case 'u': case 'g': case 'e': panic("Option -%c requires an argument!\n", optopt); default: if (isprint(optopt)) printf("Unknown option character `0x%X\'!\n", optopt); die(); } default: break; } } if (!ctx.filter && optind != argc) { int ret; off_t offset = 0; for (i = optind; i < argc; ++i) { size_t alen = strlen(argv[i]) + 2; size_t flen = ctx.filter ? strlen(ctx.filter) : 0; ctx.filter = xrealloc(ctx.filter, 1, flen + alen); ret = slprintf(ctx.filter + offset, strlen(argv[i]) + 2, "%s ", argv[i]); if (ret < 0) panic("Cannot concatenate filter string!\n"); else offset += ret; } } if (!ctx.device_in) ctx.device_in = xstrdup("any"); register_signal(SIGINT, signal_handler); register_signal(SIGHUP, signal_handler); tprintf_init(); if (prio_high) { set_proc_prio(-20); set_sched_status(SCHED_FIFO, sched_get_priority_max(SCHED_FIFO)); } if (ctx.device_in && (device_mtu(ctx.device_in) || !strncmp("any", ctx.device_in, strlen(ctx.device_in)))) { if (!ctx.rfraw) ctx.link_type = pcap_devtype_to_linktype(ctx.device_in); if (!ctx.device_out) { ctx.dump = 0; main_loop = recv_only_or_dump; } else if (device_mtu(ctx.device_out)) { register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO); main_loop = receive_to_xmit; } else { ctx.dump = 1; register_signal_f(SIGALRM, timer_next_dump, SA_SIGINFO); main_loop = recv_only_or_dump; if (!ops_touched) ctx.pcap = PCAP_OPS_SG; } } else { if (ctx.device_out && device_mtu(ctx.device_out)) { register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO); main_loop = pcap_to_xmit; if (!ops_touched) ctx.pcap = PCAP_OPS_MM; } else { main_loop = read_pcap; if (!ops_touched) ctx.pcap = PCAP_OPS_SG; } } bug_on(!main_loop); init_geoip(0); if (setsockmem) set_system_socket_memory(vals, array_size(vals)); if (!ctx.enforce) xlockme(); main_loop(&ctx); if (!ctx.enforce) xunlockme(); if (setsockmem) reset_system_socket_memory(vals, array_size(vals)); destroy_geoip(); device_restore_irq_affinity_list(); tprintf_cleanup(); destroy_ctx(&ctx); return 0; }