static void walk_t3_block(struct block_desc *pbd, struct ctx *ctx, int sock, int *fd) { int num_pkts = pbd->h1.num_pkts, i; struct tpacket3_hdr *hdr; struct sockaddr_ll *sll; hdr = (void *) ((uint8_t *) pbd + pbd->h1.offset_to_first_pkt); sll = (void *) ((uint8_t *) hdr + TPACKET_ALIGN(sizeof(*hdr))); for (i = 0; i < num_pkts && likely(sigint == 0); ++i) { uint8_t *packet = ((uint8_t *) hdr + hdr->tp_mac); pcap_pkthdr_t phdr; if (ctx->packet_type != -1) if (ctx->packet_type != sll->sll_pkttype) goto next; ctx->pkts_seen++; if (dump_to_pcap(ctx)) { int ret; tpacket3_hdr_to_pcap_pkthdr(hdr, sll, &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_snaplen, ctx->link_type, sll, hdr, ctx->print_mode, true, ctx->pkts_seen); dissector_entry_point(packet, hdr->tp_snaplen, ctx->link_type, ctx->print_mode, sll); next: hdr = (void *) ((uint8_t *) hdr + hdr->tp_next_offset); sll = (void *) ((uint8_t *) hdr + TPACKET_ALIGN(sizeof(*hdr))); if (frame_count_max != 0) { if (unlikely(ctx->pkts_seen >= frame_count_max)) { sigint = 1; break; } } update_pcap_next_dump(ctx, hdr->tp_snaplen, fd, sock, true); } }
static void walk_t3_block(struct block_desc *pbd, struct ctx *ctx, int sock, int *fd, unsigned long *frame_count) { uint8_t *packet; int num_pkts = pbd->h1.num_pkts, i, ret; struct tpacket3_hdr *hdr; pcap_pkthdr_t phdr; struct sockaddr_ll *sll; hdr = (void *) ((uint8_t *) pbd + pbd->h1.offset_to_first_pkt); sll = (void *) ((uint8_t *) hdr + TPACKET_ALIGN(sizeof(*hdr))); for (i = 0; i < num_pkts && likely(sigint == 0); ++i) { __label__ next; packet = ((uint8_t *) hdr + hdr->tp_mac); if (ctx->packet_type != -1) if (ctx->packet_type != sll->sll_pkttype) goto next; (*frame_count)++; if (dump_to_pcap(ctx)) { tpacket3_hdr_to_pcap_pkthdr(hdr, sll, &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(sll, hdr, ctx->print_mode, true); dissector_entry_point(packet, hdr->tp_snaplen, ctx->link_type, ctx->print_mode); next: hdr = (void *) ((uint8_t *) hdr + hdr->tp_next_offset); sll = (void *) ((uint8_t *) hdr + TPACKET_ALIGN(sizeof(*hdr))); if (frame_count_max != 0) { if (unlikely(*frame_count >= frame_count_max)) { sigint = 1; break; } } if (dump_to_pcap(ctx)) { if (ctx->dump_mode == DUMP_INTERVAL_SIZE) { interval += hdr->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 (unlikely(ctx->verbose)) print_pcap_file_stats(sock, ctx); } } } }
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); }
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); } }
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); }