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 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); } }
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); } }