/* Calculate final configuration values needed for ipv4-mapped-ipv6 */ static void finalize_ipv4_mapped_ipv6_config(struct config *config) { set_ipv4_defaults(config); config->live_local_ip = ipv4_parse(config->live_local_ip_string); config->live_remote_ip = ipv4_parse(config->live_remote_ip_string); config->live_prefix_len = netmask_to_prefix(config->live_netmask_ip_string); config->live_gateway_ip = ipv4_parse(config->live_gateway_ip_string); config->live_bind_ip = ipv6_parse("::"); config->live_connect_ip = ipv6_map_from_ipv4(config->live_remote_ip); config->socket_domain = AF_INET6; config->wire_protocol = AF_INET; }
/* * Convert ip v4 presentation to binary and set network mask if CIDR notation is present * * @return number of bits in the network mask, 32 if no CIDR mask is present */ int ipv4_pton(const char * p, struct in_addr * n) { char * e = strchr(p, '/'); if (e) { char * endp; uint64_t bits64 = strtoul(e + 1, &endp, 10); if (e + 1 == endp) return -1; /* digits not present */ if (* endp) return -1; /* junk after digits */ if (32 < bits64) return -1; /* out of range */ if (ipv4_parse_section(p, e - p, n)) { ipv4_set_mask(n, (int) bits64); return (int) bits64; } } else { if (ipv4_parse(p, n)) { return 32; /* no CIDR notation */ } } return -1; /* ip v4 part fails */ }
static void test(void) { unsigned i; for (i = 0; i < sizeof TestCase / sizeof TestCase[0]; i++) { char p0fbuf[256]; parse_frame pf = { PROT_IPv4, T->iplen, T->ip, NULL }; parse_frame pf2 = { PROT_TCP, T->tcplen, T->tcp, NULL }; /* print */ printf("#%2u:\n", i); /* parse ip and tcp in order */ ipv4_parse(T->ip, T->iplen, &pf, NULL); tcp_parse(T->tcp, T->tcplen, &pf2, NULL); /* generate fingerprint */ p0f2str(p0fbuf, sizeof p0fbuf, (tcp*)T->tcp, T->tcplen, (ipv4*)T->ip, T->iplen, 0); if (0 == strcmp(p0fbuf, T->expected_p0f)) { printf("OK\n"); } else { printf("%s p0f: %s\nexpected: %s)\n", "!!", p0fbuf, T->expected_p0f); printf(" IP len=%u ", T->iplen); dump_chars(T->ip, T->iplen, stdout); fputc('\n', stdout); printf(" TCP len=%u ", T->tcplen); dump_chars(T->tcp, T->tcplen, stdout); fputc('\n', stdout); ipv4_dump(&pf, 0, stdout); tcp_dump(&pf2, 0, stdout); } T++; } }
/* * IPV4 presentation parser for a subsection of a string specified by length * * @return AM_TRUE if the section of a string can be parsed as an ip v4 presentation */ static am_bool_t ipv4_parse_section(const char * p, size_t length, struct in_addr * n) { am_bool_t output; char * a = strndup(p, length); if (a) { output = ipv4_parse(a, n); free(a); } else { output = AM_FALSE; } return output; }
/* Process a command line option */ static void process_option(int opt, char *optarg, struct config *config, char *where) { int port = 0; char *end = NULL; unsigned long speed = 0; DEBUGP("process_option %d ('%c') = %s\n", opt, (char)opt, optarg); switch (opt) { case OPT_IP_VERSION: if (strcmp(optarg, "ipv4") == 0) config->ip_version = IP_VERSION_4; else if (strcmp(optarg, "ipv4-mapped-ipv6") == 0) config->ip_version = IP_VERSION_4_MAPPED_6; else if (strcmp(optarg, "ipv6") == 0) config->ip_version = IP_VERSION_6; else die("%s: bad --ip_version: %s\n", where, optarg); break; case OPT_BIND_PORT: port = atoi(optarg); if ((port <= 0) || (port > 0xffff)) die("%s: bad --bind_port: %s\n", where, optarg); //config->live_bind_port = port; config->default_live_bind_port = port; break; case OPT_CODE_COMMAND: config->code_command_line = optarg; break; case OPT_CODE_FORMAT: config->code_format = optarg; break; case OPT_CODE_SOCKOPT: config->code_sockopt = optarg; break; case OPT_CONNECT_PORT: port = atoi(optarg); if ((port <= 0) || (port > 0xffff)) die("%s: bad --connect_port: %s\n", where, optarg); config->default_live_connect_port = port; break; case OPT_REMOTE_IP: strncpy(config->live_remote_ip_string, optarg, ADDR_STR_LEN-1); break; case OPT_LOCAL_IP: strncpy(config->live_local_ip_string, optarg, ADDR_STR_LEN-1); break; case OPT_GATEWAY_IP: strncpy(config->live_gateway_ip_string, optarg, ADDR_STR_LEN-1); break; case OPT_MTU: config->mtu = atoi(optarg); if (config->mtu < 0) die("%s: bad --mtu: %s\n", where, optarg); break; case OPT_NETMASK_IP: strncpy(config->live_netmask_ip_string, optarg, ADDR_STR_LEN-1); break; case OPT_INIT_SCRIPTS: config->init_scripts = optarg; break; case OPT_NON_FATAL: parse_non_fatal_arg(optarg, config); break; case OPT_SPEED: speed = strtoul(optarg, &end, 10); if (end == optarg || *end || !is_valid_u32(speed)) die("%s: bad --speed: %s\n", where, optarg); config->speed = speed; break; case OPT_TOLERANCE_USECS: config->tolerance_usecs = atoi(optarg); if (config->tolerance_usecs <= 0) die("%s: bad --tolerance_usecs: %s\n", where, optarg); break; case OPT_TCP_TS_TICK_USECS: config->tcp_ts_tick_usecs = atoi(optarg); if (config->tcp_ts_tick_usecs < 0 || config->tcp_ts_tick_usecs > 1000000) die("%s: bad --tcp_ts_tick_usecs: %s\n", where, optarg); break; case OPT_WIRE_CLIENT: config->is_wire_client = true; break; case OPT_WIRE_SERVER: config->is_wire_server = true; break; case OPT_WIRE_SERVER_IP: config->wire_server_ip_string = strdup(optarg); config->wire_server_ip = ipv4_parse(config->wire_server_ip_string); break; case OPT_WIRE_SERVER_PORT: port = atoi(optarg); if ((port <= 0) || (port > 0xffff)) die("%s: bad --wire_server_port: %s\n", where, optarg); config->wire_server_port = port; break; case OPT_WIRE_CLIENT_DEV: config->wire_client_device = strdup(optarg); break; case OPT_WIRE_SERVER_DEV: config->wire_server_device = strdup(optarg); break; case OPT_VERBOSE: config->verbose = true; break; default: show_usage(); exit(EXIT_FAILURE); } }