static void update_pcap_next_dump(struct ctx *ctx, unsigned long snaplen, int *fd, int sock, bool is_v3) { if (!dump_to_pcap(ctx)) return; if (ctx->dump_mode == DUMP_INTERVAL_SIZE) { interval += snaplen; if (interval > ctx->dump_interval) { next_dump = true; interval = 0; } } if (sighup) { if (ctx->verbose) printf("SIGHUP received, prematurely rotating pcap\n"); sighup = 0; next_dump = true; reset_interval(ctx); } if (next_dump) { *fd = next_multi_pcap_file(ctx, *fd); next_dump = false; if (update_rx_stats(ctx, sock, is_v3)) return; if (ctx->verbose && ctx->print_mode == PRINT_NONE) printf(".(+%"PRIu64"/-%"PRIu64")", ctx->pkts_recvd_last - ctx->pkts_drops_last, ctx->pkts_drops_last); } }
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 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 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 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); }