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 void enter_mode_read_pcap(struct mode *mode) { int ret, fd; struct pcap_pkthdr phdr; struct sock_fprog bpf_ops; struct tx_stats stats; struct frame_map fm; uint8_t *out; size_t out_len; if (!pcap_ops[mode->pcap]) panic("pcap group not supported!\n"); fd = open_or_die(mode->device_in, O_RDONLY | O_LARGEFILE | O_NOATIME); ret = pcap_ops[mode->pcap]->pull_file_header(fd); if (ret) panic("error reading pcap header!\n"); if (pcap_ops[mode->pcap]->prepare_reading_pcap) { ret = pcap_ops[mode->pcap]->prepare_reading_pcap(fd); if (ret) panic("error prepare reading pcap!\n"); } memset(&fm, 0, sizeof(fm)); memset(&bpf_ops, 0, sizeof(bpf_ops)); memset(&stats, 0, sizeof(stats)); bpf_parse_rules(mode->filter, &bpf_ops); dissector_init_all(mode->print_mode); out_len = device_mtu("lo"); out = xmalloc_aligned(out_len, 64); printf("BPF:\n"); bpf_dump_all(&bpf_ops); printf("MD: RD %s\n\n", pcap_ops[mode->pcap]->name); while (likely(sigint == 0)) { do { ret = pcap_ops[mode->pcap]->read_pcap_pkt(fd, &phdr, out, out_len); if (unlikely(ret <= 0)) goto out; } while (mode->filter && !bpf_run_filter(&bpf_ops, out, phdr.len)); pcap_pkthdr_to_tpacket_hdr(&phdr, &fm.tp_h); stats.tx_bytes += fm.tp_h.tp_len;; stats.tx_packets++; show_frame_hdr(&fm, mode->print_mode, RING_MODE_EGRESS); dissector_entry_point(out, fm.tp_h.tp_snaplen, mode->link_type); if (frame_cnt_max != 0 && stats.tx_packets >= frame_cnt_max) { sigint = 1; break; } } out: fflush(stdout); printf("\n"); printf("\r%12lu frames outgoing\n", stats.tx_packets); printf("\r%12lu bytes outgoing\n", stats.tx_bytes); xfree(out); dissector_cleanup_all(); if (pcap_ops[mode->pcap]->prepare_close_pcap) pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_READ); close(fd); }
int main(int argc, char **argv) { int c, i, j, opt_index; char *ptr; bool prio_high = false; struct mode mode; void (*enter_mode)(struct mode *mode) = NULL; check_for_root_maybe_die(); memset(&mode, 0, sizeof(mode)); mode.link_type = LINKTYPE_EN10MB; mode.print_mode = FNTTYPE_PRINT_NORM; mode.cpu = CPU_UNKNOWN; mode.packet_type = PACKET_ALL; mode.promiscuous = true; mode.randomize = false; mode.pcap = PCAP_OPS_SG; mode.dump_interval = DUMP_INTERVAL; while ((c = getopt_long(argc, argv, short_options, long_options, &opt_index)) != EOF) { switch (c) { case 'd': case 'i': mode.device_in = xstrdup(optarg); break; case 'o': mode.device_out = xstrdup(optarg); break; case 'r': mode.randomize = true; break; case 'J': mode.jumbo_support = 1; break; case 'f': mode.filter = xstrdup(optarg); break; case 'M': mode.promiscuous = false; break; case 't': if (!strncmp(optarg, "host", strlen("host"))) mode.packet_type = PACKET_HOST; else if (!strncmp(optarg, "broadcast", strlen("broadcast"))) mode.packet_type = PACKET_BROADCAST; else if (!strncmp(optarg, "multicast", strlen("multicast"))) mode.packet_type = PACKET_MULTICAST; else if (!strncmp(optarg, "others", strlen("others"))) mode.packet_type = PACKET_OTHERHOST; else if (!strncmp(optarg, "outgoing", strlen("outgoing"))) mode.packet_type = PACKET_OUTGOING; else mode.packet_type = PACKET_ALL; break; case 'S': ptr = optarg; mode.reserve_size = 0; for (j = i = strlen(optarg); i > 0; --i) { if (!isdigit(optarg[j - i])) break; ptr++; } if (!strncmp(ptr, "KB", strlen("KB"))) mode.reserve_size = 1 << 10; else if (!strncmp(ptr, "MB", strlen("MB"))) mode.reserve_size = 1 << 20; else if (!strncmp(ptr, "GB", strlen("GB"))) mode.reserve_size = 1 << 30; else panic("Syntax error in ring size param!\n"); *ptr = 0; mode.reserve_size *= atoi(optarg); break; case 'b': set_cpu_affinity(optarg, 0); if (mode.cpu != CPU_NOTOUCH) mode.cpu = atoi(optarg); break; case 'B': set_cpu_affinity(optarg, 1); break; case 'H': prio_high = true; break; case 'c': mode.pcap = PCAP_OPS_RW; break; case 'm': mode.pcap = PCAP_OPS_MMAP; break; case 'Q': mode.cpu = CPU_NOTOUCH; break; case 's': mode.print_mode = FNTTYPE_PRINT_NONE; break; case 'q': mode.print_mode = FNTTYPE_PRINT_LESS; break; case 'l': mode.print_mode = FNTTYPE_PRINT_CHR1; break; case 'x': mode.print_mode = FNTTYPE_PRINT_HEX1; break; case 'C': mode.print_mode = FNTTYPE_PRINT_PAAC; break; case 'X': mode.print_mode = FNTTYPE_PRINT_HEX2; break; case 'N': mode.print_mode = FNTTYPE_PRINT_NOPA; break; case 'k': mode.kpull = (unsigned long) atol(optarg); break; case 'n': frame_cnt_max = (unsigned long) atol(optarg); break; case 'F': mode.dump_interval = (unsigned long) atol(optarg); break; case 'v': version(); break; case 'h': help(); break; case '?': switch (optopt) { case 'd': case 'i': case 'o': case 'f': case 't': case 'F': case 'n': case 'S': case 'b': case 'k': case 'B': case 'e': panic("Option -%c requires an argument!\n", optopt); default: if (isprint(optopt)) whine("Unknown option character " "`0x%X\'!\n", optopt); die(); } default: break; } } if (!mode.device_in) mode.device_in = xstrdup("any"); register_signal(SIGINT, signal_handler); register_signal(SIGHUP, signal_handler); init_pcap(mode.jumbo_support); tprintf_init(); header(); if (prio_high == true) { set_proc_prio(get_default_proc_prio()); set_sched_status(get_default_sched_policy(), get_default_sched_prio()); } if (mode.device_in && (device_mtu(mode.device_in) || !strncmp("any", mode.device_in, strlen(mode.device_in)))) { if (!mode.device_out) { mode.dump = 0; enter_mode = enter_mode_rx_only_or_dump; } else if (device_mtu(mode.device_out)) { register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO); enter_mode = enter_mode_rx_to_tx; } else { mode.dump = 1; register_signal_f(SIGALRM, timer_next_dump, SA_SIGINFO); enter_mode = enter_mode_rx_only_or_dump; } } else { if (mode.device_out && device_mtu(mode.device_out)) { register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO); enter_mode = enter_mode_pcap_to_tx; } else { enter_mode = enter_mode_read_pcap; } } if (!enter_mode) panic("Selection not supported!\n"); enter_mode(&mode); tprintf_cleanup(); cleanup_pcap(); if (mode.device_in) xfree(mode.device_in); if (mode.device_out) xfree(mode.device_out); 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; }
int main(int argc, char **argv) { bool slow = false, invoke_cpp = false, reseed = true; int c, opt_index, i, j, vals[4] = {0}, irq; char *confname = NULL, *ptr; unsigned long cpus_tmp, orig_num = 0; unsigned long long tx_packets, tx_bytes; struct ctx ctx; fmemset(&ctx, 0, sizeof(ctx)); ctx.cpus = get_number_cpus_online(); ctx.uid = getuid(); ctx.gid = getgid(); while ((c = getopt_long(argc, argv, short_options, long_options, &opt_index)) != EOF) { switch (c) { case 'h': help(); break; case 'v': version(); break; case 'e': example(); break; case 'p': invoke_cpp = true; break; case 'V': ctx.verbose = true; break; case 'P': cpus_tmp = strtoul(optarg, NULL, 0); if (cpus_tmp > 0 && cpus_tmp < ctx.cpus) ctx.cpus = cpus_tmp; break; case 'd': case 'o': ctx.device = xstrndup(optarg, IFNAMSIZ); break; case 'r': ctx.rand = true; break; case 's': slow = true; ctx.cpus = 1; ctx.smoke_test = true; ctx.rhost = xstrdup(optarg); break; case 'R': ctx.rfraw = true; break; case 'J': ctx.jumbo_support = true; break; case 'c': case 'i': confname = xstrdup(optarg); if (!strncmp("-", confname, strlen("-"))) ctx.cpus = 1; 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 'k': ctx.kpull = strtoul(optarg, NULL, 0); break; case 'E': seed = strtoul(optarg, NULL, 0); reseed = false; break; case 'n': orig_num = strtoul(optarg, NULL, 0); ctx.num = orig_num; break; case 't': slow = true; ctx.gap = strtoul(optarg, NULL, 0); if (ctx.gap > 0) /* Fall back to single core to not * mess up correct timing. We are slow * anyway! */ ctx.cpus = 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 '?': switch (optopt) { case 'd': case 'c': case 'n': case 'S': case 's': case 'P': case 'o': case 'E': case 'i': case 'k': case 'u': case 'g': case 't': panic("Option -%c requires an argument!\n", optopt); default: if (isprint(optopt)) printf("Unknown option character `0x%X\'!\n", optopt); die(); } default: break; } } if (argc < 5) help(); if (ctx.device == NULL) panic("No networking device given!\n"); if (confname == NULL) panic("No configuration file given!\n"); if (device_mtu(ctx.device) == 0) panic("This is no networking device!\n"); register_signal(SIGINT, signal_handler); register_signal(SIGHUP, signal_handler); register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO); set_system_socket_memory(vals, array_size(vals)); xlockme(); if (ctx.rfraw) { ctx.device_trans = xstrdup(ctx.device); xfree(ctx.device); enter_rfmon_mac80211(ctx.device_trans, &ctx.device); sleep(0); } irq = device_irq_number(ctx.device); device_set_irq_affinity_list(irq, 0, ctx.cpus - 1); stats = setup_shared_var(ctx.cpus); for (i = 0; i < ctx.cpus; i++) { pid_t pid = fork(); switch (pid) { case 0: if (reseed) seed = generate_srand_seed(); srand(seed); cpu_affinity(i); main_loop(&ctx, confname, slow, i, invoke_cpp, orig_num); goto thread_out; case -1: panic("Cannot fork processes!\n"); } } for (i = 0; i < ctx.cpus; i++) { int status; wait(&status); if (WEXITSTATUS(status) == EXIT_FAILURE) die(); } if (ctx.rfraw) leave_rfmon_mac80211(ctx.device_trans, ctx.device); reset_system_socket_memory(vals, array_size(vals)); for (i = 0, tx_packets = tx_bytes = 0; i < ctx.cpus; i++) { while ((__get_state(i) & CPU_STATS_STATE_RES) == 0) sched_yield(); tx_packets += stats[i].tx_packets; tx_bytes += stats[i].tx_bytes; } fflush(stdout); printf("\n"); printf("\r%12llu packets outgoing\n", tx_packets); printf("\r%12llu bytes outgoing\n", tx_bytes); for (i = 0; i < ctx.cpus; i++) { printf("\r%12lu sec, %lu usec on CPU%d (%llu packets)\n", stats[i].tv_sec, stats[i].tv_usec, i, stats[i].tx_packets); } thread_out: xunlockme(); destroy_shared_var(stats, ctx.cpus); device_restore_irq_affinity_list(); free(ctx.device); free(ctx.device_trans); free(ctx.rhost); free(confname); 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.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) { bool slow = false, invoke_cpp = false, reseed = true, cpustats = true; bool prio_high = false, set_irq_aff = true, set_sock_mem = true; int c, opt_index, vals[4] = {0}, irq; uint64_t gap = 0; unsigned int i, j; char *confname = NULL, *ptr; unsigned long cpus_tmp, orig_num = 0; unsigned long long tx_packets, tx_bytes; struct ctx ctx; fmemset(&ctx, 0, sizeof(ctx)); ctx.cpus = get_number_cpus_online(); ctx.uid = getuid(); ctx.gid = getgid(); ctx.qdisc_path = false; /* Keep an initial small default size to reduce cache-misses. */ ctx.reserve_size = 512 * (1 << 10); while ((c = getopt_long(argc, argv, short_options, long_options, &opt_index)) != EOF) { switch (c) { case 'h': help(); break; case 'v': version(); break; case 'C': cpustats = false; break; case 'e': example(); break; case 'p': invoke_cpp = true; break; case 'V': ctx.verbose = true; break; case 'P': cpus_tmp = strtoul(optarg, NULL, 0); if (cpus_tmp > 0 && cpus_tmp < ctx.cpus) ctx.cpus = cpus_tmp; break; case 'd': case 'o': ctx.device = xstrndup(optarg, IFNAMSIZ); break; case 'H': prio_high = true; break; case 'A': set_sock_mem = false; break; case 'Q': set_irq_aff = false; break; case 'q': ctx.qdisc_path = true; break; case 'r': ctx.rand = true; break; case 's': slow = true; ctx.cpus = 1; ctx.smoke_test = true; ctx.rhost = xstrdup(optarg); break; case 'R': ctx.rfraw = true; break; case 'J': ctx.jumbo_support = true; break; case 'c': case 'i': confname = xstrdup(optarg); if (!strncmp("-", confname, strlen("-"))) ctx.cpus = 1; 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 'k': printf("Option -k/--kernel-pull is no longer used and " "will be removed in a future release!\n"); break; case 'E': seed = strtoul(optarg, NULL, 0); reseed = false; break; case 'n': orig_num = strtoul(optarg, NULL, 0); ctx.num = orig_num; break; case 't': slow = true; ptr = optarg; prctl(PR_SET_TIMERSLACK, 1UL); gap = strtoul(optarg, NULL, 0); for (j = i = strlen(optarg); i > 0; --i) { if (!isdigit(optarg[j - i])) break; ptr++; } if (!strncmp(ptr, "ns", strlen("ns"))) { ctx.gap.tv_sec = gap / 1000000000; ctx.gap.tv_nsec = gap % 1000000000; } else if (*ptr == '\0' || !strncmp(ptr, "us", strlen("us"))) { /* Default to microseconds for backwards * compatibility if no postfix is given. */ ctx.gap.tv_sec = gap / 1000000; ctx.gap.tv_nsec = (gap % 1000000) * 1000; } else if (!strncmp(ptr, "ms", strlen("ms"))) { ctx.gap.tv_sec = gap / 1000; ctx.gap.tv_nsec = (gap % 1000) * 1000000; } else if (!strncmp(ptr, "s", strlen("s"))) { ctx.gap.tv_sec = gap; ctx.gap.tv_nsec = 0; } else panic("Syntax error in time param!\n"); if (gap > 0) /* Fall back to single core to not mess up * correct timing. We are slow anyway! */ ctx.cpus = 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 '?': switch (optopt) { case 'd': case 'c': case 'n': case 'S': case 's': case 'P': case 'o': case 'E': case 'i': case 'k': case 'u': case 'g': case 't': panic("Option -%c requires an argument!\n", optopt); default: if (isprint(optopt)) printf("Unknown option character `0x%X\'!\n", optopt); die(); } default: break; } } if (argc < 5) help(); if (ctx.device == NULL) panic("No networking device given!\n"); if (confname == NULL) panic("No configuration file given!\n"); if (device_mtu(ctx.device) == 0) panic("This is no networking device!\n"); register_signal(SIGINT, signal_handler); register_signal(SIGQUIT, signal_handler); register_signal(SIGTERM, signal_handler); register_signal(SIGHUP, signal_handler); if (prio_high) { set_proc_prio(-20); set_sched_status(SCHED_FIFO, sched_get_priority_max(SCHED_FIFO)); } if (set_sock_mem) set_system_socket_memory(vals, array_size(vals)); xlockme(); if (ctx.rfraw) { ctx.device_trans = xstrdup(ctx.device); xfree(ctx.device); enter_rfmon_mac80211(ctx.device_trans, &ctx.device); panic_handler_add(on_panic_del_rfmon, ctx.device); sleep(0); } /* * If number of packets is smaller than number of CPUs use only as * many CPUs as there are packets. Otherwise we end up sending more * packets than intended or none at all. */ if (ctx.num) ctx.cpus = min_t(unsigned int, ctx.num, ctx.cpus); irq = device_irq_number(ctx.device); if (set_irq_aff) device_set_irq_affinity_list(irq, 0, ctx.cpus - 1); stats = setup_shared_var(ctx.cpus); for (i = 0; i < ctx.cpus; i++) { pid_t pid = fork(); switch (pid) { case 0: if (reseed) seed = generate_srand_seed(); srand(seed); cpu_affinity(i); main_loop(&ctx, confname, slow, i, invoke_cpp, orig_num); goto thread_out; case -1: panic("Cannot fork processes!\n"); } } for (i = 0; i < ctx.cpus; i++) { int status; wait(&status); if (WEXITSTATUS(status) == EXIT_FAILURE) die(); } if (ctx.rfraw) leave_rfmon_mac80211(ctx.device); if (set_sock_mem) reset_system_socket_memory(vals, array_size(vals)); for (i = 0, tx_packets = tx_bytes = 0; i < ctx.cpus; i++) { while ((__get_state(i) & CPU_STATS_STATE_RES) == 0) sched_yield(); tx_packets += stats[i].tx_packets; tx_bytes += stats[i].tx_bytes; } fflush(stdout); printf("\n"); printf("\r%12llu packets outgoing\n", tx_packets); printf("\r%12llu bytes outgoing\n", tx_bytes); for (i = 0; cpustats && i < ctx.cpus; i++) { printf("\r%12lu sec, %lu usec on CPU%d (%llu packets)\n", stats[i].tv_sec, stats[i].tv_usec, i, stats[i].tx_packets); } thread_out: xunlockme(); destroy_shared_var(stats, ctx.cpus); if (set_irq_aff) device_restore_irq_affinity_list(); free(ctx.device); free(ctx.device_trans); free(ctx.rhost); free(confname); return 0; }
int main(int argc, char **argv) { int c, i, j, opt_index, ops_touched = 0; char *ptr; bool prio_high = false; struct mode mode; void (*enter_mode) (struct mode * mode) = NULL; check_for_root_maybe_die(); fmemset(&mode, 0, sizeof(mode)); mode.link_type = LINKTYPE_EN10MB; mode.print_mode = FNTTYPE_PRINT_NORM; mode.cpu = CPU_UNKNOWN; mode.packet_type = PACKET_ALL; mode.promiscuous = true; mode.randomize = false; mode.pcap = PCAP_OPS_SG; mode.dump_interval = DUMP_INTERVAL; while ((c = getopt_long(argc, argv, short_options, long_options, &opt_index)) != EOF) { switch (c) { case 'd': case 'i': mode.device_in = xstrdup(optarg); break; case 'o': mode.device_out = xstrdup(optarg); break; case 'R': mode.link_type = LINKTYPE_IEEE802_11; mode.rfraw = 1; break; case 'r': mode.randomize = true; break; case 'J': mode.jumbo_support = 1; break; case 'f': mode.filter = xstrdup(optarg); break; case 'M': mode.promiscuous = false; break; case 't': if (!strncmp(optarg, "host", strlen("host"))) mode.packet_type = PACKET_HOST; else if (!strncmp (optarg, "broadcast", strlen("broadcast"))) mode.packet_type = PACKET_BROADCAST; else if (!strncmp (optarg, "multicast", strlen("multicast"))) mode.packet_type = PACKET_MULTICAST; else if (!strncmp(optarg, "others", strlen("others"))) mode.packet_type = PACKET_OTHERHOST; else if (!strncmp (optarg, "outgoing", strlen("outgoing"))) mode.packet_type = PACKET_OUTGOING; else mode.packet_type = PACKET_ALL; break; case 'S': ptr = optarg; mode.reserve_size = 0; for (j = i = strlen(optarg); i > 0; --i) { if (!isdigit(optarg[j - i])) break; ptr++; } if (!strncmp(ptr, "KB", strlen("KB"))) mode.reserve_size = 1 << 10; else if (!strncmp(ptr, "MB", strlen("MB"))) mode.reserve_size = 1 << 20; else if (!strncmp(ptr, "GB", strlen("GB"))) mode.reserve_size = 1 << 30; else panic("Syntax error in ring size param!\n"); *ptr = 0; mode.reserve_size *= atoi(optarg); break; case 'b': set_cpu_affinity(optarg, 0); if (mode.cpu != CPU_NOTOUCH) mode.cpu = atoi(optarg); break; case 'B': set_cpu_affinity(optarg, 1); break; case 'H': prio_high = true; break; case 'c': mode.pcap = PCAP_OPS_RW; ops_touched = 1; break; case 'm': mode.pcap = PCAP_OPS_MMAP; ops_touched = 1; break; case 'g': mode.pcap = PCAP_OPS_SG; ops_touched = 1; break; case 'Q': mode.cpu = CPU_NOTOUCH; break; case 's': mode.print_mode = FNTTYPE_PRINT_NONE; break; case 'q': mode.print_mode = FNTTYPE_PRINT_LESS; break; case 'X': mode.print_mode = (mode.print_mode == FNTTYPE_PRINT_ASCII) ? FNTTYPE_PRINT_HEX_ASCII : FNTTYPE_PRINT_HEX; break; case 'l': mode.print_mode = (mode.print_mode == FNTTYPE_PRINT_HEX) ? FNTTYPE_PRINT_HEX_ASCII : FNTTYPE_PRINT_ASCII; break; case 'k': mode.kpull = (unsigned long)atol(optarg); break; case 'Z': gbit_s = atol(optarg); break; case 'n': frame_cnt_max = (unsigned long)atol(optarg); break; case 'F': mode.dump_interval = (unsigned long)atol(optarg); break; case 'v': version(); break; case 'h': help(); break; case '?': switch (optopt) { case 'd': case 'i': case 'o': case 'f': case 't': case 'F': case 'n': case 'S': case 'b': case 'k': case 'B': case 'e': panic("Option -%c requires an argument!\n", optopt); default: if (isprint(optopt)) whine("Unknown option character " "`0x%X\'!\n", optopt); die(); } default: break; } } if (!mode.device_in) mode.device_in = xstrdup("any"); register_signal(SIGINT, signal_handler); register_signal(SIGHUP, signal_handler); init_pcap(mode.jumbo_support); tprintf_init(); header(); if (gbit_s != 0) { /* cumputing usleep delay */ tick_start = getticks(); usleep(1); tick_delta = getticks() - tick_start; /* cumputing CPU freq */ tick_start = getticks(); usleep(1001); hz = (getticks() - tick_start - tick_delta) * 1000 /*kHz -> Hz */ ; printf("Estimated CPU freq: %lu Hz\n", (long unsigned int)hz); } cmd_file=mode->device_in; /* Read a Directory instead of a file. I will add it to command line later */ int r = walk_dir(cmd_file, ".\\.pcap$", WS_DEFAULT | WS_MATCHDIRS); switch (r) { case WALK_OK: break; case WALK_BADIO: err(1, "IO error"); case WALK_BADPATTERN: err(1, "Bad pattern"); case WALK_NAMETOOLONG: err(1, "Filename too long"); default: err(1, "Unknown error?"); } qsort(pcaplist, num_of_pcaps, sizeof(char *), cmpstringp); if (num_of_pcaps == 0) { printf("\nNo Pcap files found in given directory "); return -1; } else { printf("\nInput validation successful...\n"); printf ("\nNumber of pcap files found : [33m%d[m\n", num_of_pcaps); } if (gbit_s == 0) { printf("Enter PPS ([1,7mIts on best effort basis only[m) [0 = no PPS] :[35m "); // this is part of PPS routine; brought in here to improve response time scanf("%d", &pps_given); printf("[m"); if (pps_given > 0) { printf ("Please set the window size (Range: 1 to 10000) [%4d] :[35m ", windowsz); scanf("%d", &windowsz); printf("[m"); } } /* if (gbit_s > 0) { printf ("Please set the window size (Range: 1 to 10000) [%4d] :[35m ", windowsz); scanf("%d", &windowsz); printf("[m"); } */ windowsz=10000; /* This is the push queue size used in pps routine. Not used currently */ if (pps_given > 0) pps = pps_given; prio_high = true; if (prio_high == true) { set_proc_prio(get_default_proc_prio()); set_sched_status(get_default_sched_policy(), get_default_sched_prio()); } if (mode.device_in && (device_mtu(mode.device_in) || !strncmp("any", mode.device_in, strlen(mode.device_in)))) { if (!mode.device_out) { mode.dump = 0; enter_mode = enter_mode_rx_only_or_dump; } else if (device_mtu(mode.device_out)) { register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO); enter_mode = enter_mode_rx_to_tx; //Bridge Mode } else { mode.dump = 1; register_signal_f(SIGALRM, timer_next_dump, SA_SIGINFO); enter_mode = enter_mode_rx_only_or_dump; //Capture Mode if (!ops_touched) mode.pcap = PCAP_OPS_SG; } } else { if (mode.device_out && device_mtu(mode.device_out)) { register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO); enter_mode = enter_mode_pcap_to_tx; //Tx Mode if (!ops_touched) mode.pcap = PCAP_OPS_MMAP; } else { enter_mode = enter_mode_read_pcap; if (!ops_touched) mode.pcap = PCAP_OPS_SG; } } if (!enter_mode) panic("Selection not supported!\n"); enter_mode(&mode); tprintf_cleanup(); cleanup_pcap(); if (mode.device_in) xfree(mode.device_in); if (mode.device_out) xfree(mode.device_out); if (mode.device_trans) xfree(mode.device_trans); return 0; }