diff --git a/src/recv.c b/src/recv.c index 8514144..990762c 100644 --- a/src/recv.c +++ b/src/recv.c @@ -74,13 +74,13 @@ void packet_cb(u_char __attribute__((__unused__)) *user, // length of entire packet captured by libpcap uint32_t buflen = (uint32_t) p->caplen; - if ((sizeof(struct iphdr) + sizeof(struct ethhdr)) > buflen) { + if ((sizeof(struct iphdr) + (zconf.send_ip_pkts ? 0 : sizeof(struct ethhdr))) > buflen) { // buffer not large enough to contain ethernet // and ip headers. further action would overrun buf return; } - struct iphdr *ip_hdr = (struct iphdr *)&bytes[sizeof(struct ethhdr)]; - + struct iphdr *ip_hdr = (struct iphdr *)&bytes[(zconf.send_ip_pkts ? 0 : sizeof(struct ethhdr))]; + uint32_t src_ip = ip_hdr->saddr; uint32_t validation[VALIDATE_BYTES/sizeof(uint8_t)]; @@ -88,7 +88,7 @@ void packet_cb(u_char __attribute__((__unused__)) *user, // and we must calculate off potential payload message instead validate_gen(ip_hdr->daddr, ip_hdr->saddr, (uint8_t *)validation); - if (!zconf.probe_module->validate_packet(ip_hdr, buflen - sizeof(struct ethhdr), + if (!zconf.probe_module->validate_packet(ip_hdr, buflen - (zconf.send_ip_pkts ? 0 : sizeof(struct ethhdr)), &src_ip, validation)) { return; } @@ -97,25 +97,35 @@ void packet_cb(u_char __attribute__((__unused__)) *user, fieldset_t *fs = fs_new_fieldset(); fs_add_ip_fields(fs, ip_hdr); - zconf.probe_module->process_packet(bytes, buflen, fs); + // HACK !!! FIXME !!! TODO !!! BAD BAD BAD + // probe modules for whatever reason expect the full ethernet frame + // in process_packet. For VPN, we only get back an IP frame + // so we COULD malloc a fake ethernet frame and copy over this payload + // but waaaaaaahhhh performanceeee. + // so instead, we will ASSUME (!) that the probe module will only care about + // the IP header, and do ip_hdr = &packet[sizeof(struct ethhdr)] the first thing + // in their function (tcp, icmp and udp probe modules all do). + // + // !!!IF YOUR PROBE MODULE USES THE ETH PACKET, AND YOU USE THE --vpn OPTION, YOU _WILL_ BE OWNED!!!! + // + zconf.probe_module->process_packet(bytes - (zconf.send_ip_pkts * sizeof(struct ethhdr)), buflen + (zconf.send_ip_pkts * sizeof(struct ethhdr)), fs); fs_add_system_fields(fs, is_repeat, zsend.complete); int success_index = zconf.fsconf.success_index; assert(success_index < fs->len); int is_success = fs_get_uint64_by_index(fs, success_index); - + if (is_success) { zrecv.success_total++; if (!is_repeat) { zrecv.success_unique++; set_ip(src_ip); } - if (zsend.complete) { + if (zsend.complete) { zrecv.cooldown_total++; if (!is_repeat) { zrecv.cooldown_unique++; } } - } else { zrecv.failure_total++; } diff --git a/src/send.c b/src/send.c index c76f87e..ebb971c 100644 --- a/src/send.c +++ b/src/send.c @@ -288,7 +288,7 @@ int send_run(int sock) zconf.probe_module->print_packet(stdout, buf); } else { int l = zconf.probe_module->packet_length; - int rc = sendto(sock, buf, + int rc = sendto(sock, buf + zconf.send_ip_pkts*sizeof(struct ethhdr), l, 0, (struct sockaddr *)&sockaddr, sizeof(struct sockaddr_ll)); diff --git a/src/state.c b/src/state.c index 62d5a95..2742c7e 100644 --- a/src/state.c +++ b/src/state.c @@ -14,7 +14,7 @@ struct state_conf zconf = { .log_level = LOG_INFO, .source_port_first = 32768, // (these are the default - .source_port_last = 61000, // ephemeral range on Linux) + .source_port_last = 61000, // ephemeral range on Linux) .output_filename = NULL, .blacklist_filename = NULL, .whitelist_filename = NULL, @@ -36,6 +36,7 @@ struct state_conf zconf = { .probe_args = NULL, .gw_mac = {0}, .gw_mac_set = 0, + .send_ip_pkts = 0, .source_ip_first = NULL, .source_ip_last = NULL, .raw_output_fields = NULL, diff --git a/src/state.h b/src/state.h index a9f8f22..5bd3f75 100644 --- a/src/state.h +++ b/src/state.h @@ -70,7 +70,8 @@ struct state_conf { char *probe_args; char *output_args; macaddr_t gw_mac[IFHWADDRLEN]; - int gw_mac_set; + int gw_mac_set; + int send_ip_pkts; char *source_ip_first; char *source_ip_last; char *output_filename; diff --git a/src/zmap.c b/src/zmap.c index abc2153..9226638 100644 --- a/src/zmap.c +++ b/src/zmap.c @@ -397,6 +397,11 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } } + if (args.vpn_given) { + zconf.send_ip_pkts = 1; + zconf.gw_mac_set = 1; + memset(zconf.gw_mac, 0, IFHWADDRLEN); + } if (cmdline_parser_required(&args, CMDLINE_PARSER_PACKAGE) != 0) { exit(EXIT_FAILURE); } diff --git a/src/zopt.c b/src/zopt.c index 24d2cab..ec622dd 100644 --- a/src/zopt.c +++ b/src/zopt.c @@ -54,6 +54,7 @@ const char *gengetopt_args_info_help[] = { " -S, --source-ip=ip|range Source address(es) for scan packets", " -G, --gateway-mac=addr Specify gateway MAC address", " -i, --interface=name Specify network interface to use", + " -X, --vpn Sends IP packets instead of Ethernet (for VPNs)", "\nAdvanced options:", " -M, --probe-module=name Select probe module (default=`tcp_synscan')", " -O, --output-module=name Select output module (default=`csv')", @@ -137,6 +138,7 @@ void clear_given (struct gengetopt_args_info *args_info) args_info->source_ip_given = 0 ; args_info->gateway_mac_given = 0 ; args_info->interface_given = 0 ; + args_info->vpn_given = 0 ; args_info->probe_module_given = 0 ; args_info->output_module_given = 0 ; args_info->probe_args_given = 0 ; @@ -226,19 +228,20 @@ void init_args_info(struct gengetopt_args_info *args_info) args_info->source_ip_help = gengetopt_args_info_help[19] ; args_info->gateway_mac_help = gengetopt_args_info_help[20] ; args_info->interface_help = gengetopt_args_info_help[21] ; - args_info->probe_module_help = gengetopt_args_info_help[23] ; - args_info->output_module_help = gengetopt_args_info_help[24] ; - args_info->probe_args_help = gengetopt_args_info_help[25] ; - args_info->output_args_help = gengetopt_args_info_help[26] ; - args_info->list_output_modules_help = gengetopt_args_info_help[27] ; - args_info->list_probe_modules_help = gengetopt_args_info_help[28] ; - args_info->list_output_fields_help = gengetopt_args_info_help[29] ; - args_info->config_help = gengetopt_args_info_help[31] ; - args_info->quiet_help = gengetopt_args_info_help[32] ; - args_info->summary_help = gengetopt_args_info_help[33] ; - args_info->verbosity_help = gengetopt_args_info_help[34] ; - args_info->help_help = gengetopt_args_info_help[35] ; - args_info->version_help = gengetopt_args_info_help[36] ; + args_info->vpn_help = gengetopt_args_info_help[22] ; + args_info->probe_module_help = gengetopt_args_info_help[24] ; + args_info->output_module_help = gengetopt_args_info_help[25] ; + args_info->probe_args_help = gengetopt_args_info_help[26] ; + args_info->output_args_help = gengetopt_args_info_help[27] ; + args_info->list_output_modules_help = gengetopt_args_info_help[28] ; + args_info->list_probe_modules_help = gengetopt_args_info_help[29] ; + args_info->list_output_fields_help = gengetopt_args_info_help[30] ; + args_info->config_help = gengetopt_args_info_help[32] ; + args_info->quiet_help = gengetopt_args_info_help[33] ; + args_info->summary_help = gengetopt_args_info_help[34] ; + args_info->verbosity_help = gengetopt_args_info_help[35] ; + args_info->help_help = gengetopt_args_info_help[36] ; + args_info->version_help = gengetopt_args_info_help[37] ; } @@ -426,6 +429,8 @@ cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info) write_into_file(outfile, "gateway-mac", args_info->gateway_mac_orig, 0); if (args_info->interface_given) write_into_file(outfile, "interface", args_info->interface_orig, 0); + if (args_info->vpn_given) + write_into_file(outfile, "vpn", 0, 0 ); if (args_info->probe_module_given) write_into_file(outfile, "probe-module", args_info->probe_module_orig, 0); if (args_info->output_module_given) @@ -721,6 +726,7 @@ cmdline_parser_internal ( { "source-ip", 1, NULL, 'S' }, { "gateway-mac", 1, NULL, 'G' }, { "interface", 1, NULL, 'i' }, + { "vpn", 0, NULL, 'X' }, { "probe-module", 1, NULL, 'M' }, { "output-module", 1, NULL, 'O' }, { "probe-args", 1, NULL, 0 }, @@ -737,7 +743,7 @@ cmdline_parser_internal ( { 0, 0, 0, 0 } }; - c = getopt_long (argc, argv, "p:o:b:w:f:n:N:t:r:B:c:e:T:P:ds:S:G:i:M:O:C:qgv:hV", long_options, &option_index); + c = getopt_long (argc, argv, "p:o:b:w:f:n:N:t:r:B:c:e:T:P:ds:S:G:i:XM:O:C:qgv:hV", long_options, &option_index); if (c == -1) break; /* Exit from `while (1)' loop. */ @@ -970,6 +976,18 @@ cmdline_parser_internal ( additional_error)) goto failure; + break; + case 'X': /* Sends IP packets instead of Ethernet (for VPNs). */ + + + if (update_arg( 0 , + 0 , &(args_info->vpn_given), + &(local_args_info.vpn_given), optarg, 0, 0, ARG_NO, + check_ambiguity, override, 0, 0, + "vpn", 'X', + additional_error)) + goto failure; + break; case 'M': /* Select probe module. */ @@ -988,7 +1006,7 @@ cmdline_parser_internal ( if (update_arg( (void *)&(args_info->output_module_arg), &(args_info->output_module_orig), &(args_info->output_module_given), - &(local_args_info.output_module_given), optarg, 0, "simple_file", ARG_STRING, + &(local_args_info.output_module_given), optarg, 0, "csv", ARG_STRING, check_ambiguity, override, 0, 0, "output-module", 'O', additional_error)) diff --git a/src/zopt.ggo b/src/zopt.ggo index 0446738..8067994 100644 --- a/src/zopt.ggo +++ b/src/zopt.ggo @@ -75,6 +75,8 @@ option "gateway-mac" G "Specify gateway MAC address" option "interface" i "Specify network interface to use" typestr="name" optional string +option "vpn" X "Sends IP packets instead of Ethernet (for VPNs)" + optional section "Advanced options" @@ -84,7 +86,7 @@ option "probe-module" M "Select probe module" optional string option "output-module" O "Select output module" typestr="name" - default="simple_file" + default="csv" optional string option "probe-args" - "Arguments to pass to probe module" typestr="args" diff --git a/src/zopt.h b/src/zopt.h index c1fe727..25ab955 100644 --- a/src/zopt.h +++ b/src/zopt.h @@ -92,10 +92,11 @@ struct gengetopt_args_info char * interface_arg; /**< @brief Specify network interface to use. */ char * interface_orig; /**< @brief Specify network interface to use original value given at command line. */ const char *interface_help; /**< @brief Specify network interface to use help description. */ + const char *vpn_help; /**< @brief Sends IP packets instead of Ethernet (for VPNs) help description. */ char * probe_module_arg; /**< @brief Select probe module (default='tcp_synscan'). */ char * probe_module_orig; /**< @brief Select probe module original value given at command line. */ const char *probe_module_help; /**< @brief Select probe module help description. */ - char * output_module_arg; /**< @brief Select output module (default='simple_file'). */ + char * output_module_arg; /**< @brief Select output module (default='csv'). */ char * output_module_orig; /**< @brief Select output module original value given at command line. */ const char *output_module_help; /**< @brief Select output module help description. */ char * probe_args_arg; /**< @brief Arguments to pass to probe module. */ @@ -137,6 +138,7 @@ struct gengetopt_args_info unsigned int source_ip_given ; /**< @brief Whether source-ip was given. */ unsigned int gateway_mac_given ; /**< @brief Whether gateway-mac was given. */ unsigned int interface_given ; /**< @brief Whether interface was given. */ + unsigned int vpn_given ; /**< @brief Whether vpn was given. */ unsigned int probe_module_given ; /**< @brief Whether probe-module was given. */ unsigned int output_module_given ; /**< @brief Whether output-module was given. */ unsigned int probe_args_given ; /**< @brief Whether probe-args was given. */