void net_on_accept(struct net_connection* con, int event, void *arg) { struct hub_info* hub = (struct hub_info*) arg; struct hub_probe* probe = 0; struct ip_addr_encap ipaddr; int server_fd = net_con_get_sd(con); #ifdef PLUGIN_SUPPORT plugin_st status; #endif for (;;) { int fd = net_accept(server_fd, &ipaddr); if (fd == -1) { if (net_error() == EWOULDBLOCK) { break; } else { LOG_ERROR("Accept error: %d %s", net_error(), strerror(net_error())); break; } } #ifdef PLUGIN_SUPPORT status = plugin_check_ip_early(hub, &ipaddr); if (status == st_deny) { plugin_log_connection_denied(hub, &ipaddr); net_close(fd); continue; } plugin_log_connection_accepted(hub, &ipaddr); #endif probe = probe_create(hub, fd, &ipaddr); if (!probe) { LOG_ERROR("Unable to create probe after socket accepted. Out of memory?"); net_close(fd); break; } } }
algorithm_instance_t * pt_add_instance( struct pt_loop_s * loop, const char * name, void * options, probe_t * probe_skel ) { bool probe_allocated = false; algorithm_t * algorithm; algorithm_instance_t * instance = NULL; if (!(algorithm = algorithm_search(name))) { goto ERR_ALGORITHM_NOT_FOUND; } // If the probe skeleton does not exist, create it. if (!probe_skel) { probe_skel = probe_create(); probe_allocated = (probe_skel != NULL); if (!probe_allocated) goto ERR_PROBE_SKEL; } // Create a new instance of a running algorithm if (!(instance = algorithm_instance_create(loop, algorithm, options, probe_skel))) { goto ERR_INSTANCE; } // We need to queue a new event for the algorithm: it has been started pt_throw(NULL, instance, event_create(ALGORITHM_INIT, NULL, NULL, NULL)); // Add this algorithms to the list of handled algorithms pt_algorithm_instance_add(loop, instance); return instance; ERR_INSTANCE: ERR_PROBE_SKEL: if (probe_allocated) probe_free(probe_skel); ERR_ALGORITHM_NOT_FOUND: return NULL; }
probe_t * probe_wrap_packet(packet_t * packet) { probe_t * probe; size_t segment_size, remaining_size; layer_t * layer; uint8_t * segment; const protocol_t * protocol; if (!(probe = probe_create())) { goto ERR_PROBE_CREATE; } // Clear the probe packet_free(probe->packet); probe->packet = packet; probe_layers_clear(probe); // Prepare iteration segment = packet_get_bytes(probe->packet); remaining_size = packet_get_size(probe->packet); // Push layers for (protocol = get_first_protocol(packet); protocol; protocol = protocol->get_next_protocol(layer)) { if (remaining_size < protocol->write_default_header(NULL)) { // Not enough bytes left for the header, packet is truncated segment_size = remaining_size; } else { segment_size = protocol->get_header_size(segment); } if (!(layer = layer_create_from_segment(protocol, segment, segment_size))) { goto ERR_CREATE_LAYER; } if (!probe_push_layer(probe, layer)) { goto ERR_PUSH_LAYER; } segment += segment_size; remaining_size -= segment_size; if (remaining_size < 0) { fprintf(stderr, "probe_wrap_packet: Truncated packet\n"); goto ERR_TRUNCATED_PACKET; } if (!protocol->get_next_protocol) { break; } continue; ERR_TRUNCATED_PACKET: ERR_PUSH_LAYER: layer_free(layer); ERR_CREATE_LAYER: goto ERR_LAYER_DISCOVER_LAYER; } // Rq: Some packets (e.g ICMP type 3) do not have payload. // In this case we push an empty payload probe_push_payload(probe, remaining_size); return probe; ERR_LAYER_DISCOVER_LAYER: probe_free(probe); ERR_PROBE_CREATE: return NULL; }
int main(int argc, char ** argv) { algorithm_instance_t * instance; traceroute_options_t options = traceroute_get_default_options(); probe_t * probe; pt_loop_t * loop; int family; int ret = EXIT_FAILURE; const char * ip_protocol_name; const char * protocol_name; address_t dst_addr; // Harcoded command line parsing here char dst_ip[] = "8.8.8.8"; //char dst_ip[] = "1.1.1.2"; //char dst_ip[] = "2001:db8:85a3::8a2e:370:7338"; if (!address_guess_family(dst_ip, &family)) { fprintf(stderr, "Cannot guess family of destination address (%s)", dst_ip); goto ERR_ADDRESS_GUESS_FAMILY; } if (address_from_string(family, dst_ip, &dst_addr) != 0) { fprintf(stderr, "Cannot guess family of destination address (%s)", dst_ip); goto ERR_ADDRESS_FROM_STRING; } // Prepare options related to the 'traceroute' algorithm options.do_resolv = false; options.dst_addr = &dst_addr; options.num_probes = 1; // options.max_ttl = 1; printf("num_probes = %zu max_ttl = %u\n", options.num_probes, options.max_ttl); // Create libparistraceroute loop // No information shared by traceroute algorithm instances, so we pass NULL if (!(loop = pt_loop_create(loop_handler, NULL))) { fprintf(stderr, "Cannot create libparistraceroute loop"); goto ERR_LOOP_CREATE; } // Probe skeleton definition: IPv4/UDP probe targetting 'dst_ip' if (!(probe = probe_create())) { fprintf(stderr, "Cannot create probe skeleton"); goto ERR_PROBE_CREATE; } switch (family) { case AF_INET: ip_protocol_name = "ipv4"; protocol_name = "icmpv4"; break; case AF_INET6: ip_protocol_name = "ipv6"; protocol_name = "icmpv6"; break; default: fprintf(stderr, "Internet family not supported (%d)\n", family); goto ERR_FAMILY; } // protocol_name = "udp"; protocol_name = "tcp"; printf("protocol_name = %s\n", protocol_name); if (!probe_set_protocols(probe, ip_protocol_name, protocol_name, NULL)) { fprintf(stderr, "Can't set protocols %s/%s\n", ip_protocol_name, protocol_name); goto ERR_PROBE_SET_PROTOCOLS; } if (strncmp("icmp", protocol_name, 4) != 0) { probe_write_payload(probe, "\0\0\0\0", 4); } else { probe_set_field(probe, I32("body", 1)); } probe_set_fields(probe, ADDRESS("dst_ip", &dst_addr), I16("dst_port", 3000), NULL ); /* if (strcmp("tcp", protocol_name) == 0) { printf("setting tcp fields\n"); uint8_t one = 1; probe_set_fields(probe, BITS("reserved", 1, &one), BITS("ns", 1, &one), BITS("cwr", 1, &one), BITS("ece", 1, &one), BITS("urg", 1, &one), BITS("ack", 1, &one), BITS("psh", 1, &one), BITS("rst", 1, &one), BITS("syn", 1, &one), BITS("fin", 1, &one), NULL ); } */ probe_dump(probe); // Instanciate a 'traceroute' algorithm if (!(instance = pt_add_instance(loop, "traceroute", &options, probe))) { fprintf(stderr, "Cannot add 'traceroute' algorithm"); goto ERR_INSTANCE; } // Wait for events. They will be catched by handler_user() if (pt_loop(loop, 0) < 0) { fprintf(stderr, "Main loop interrupted"); goto ERR_IN_PT_LOOP; } ret = EXIT_SUCCESS; // Free data and quit properly ERR_IN_PT_LOOP: // instance is freed by pt_loop_free ERR_INSTANCE: ERR_PROBE_SET_PROTOCOLS: ERR_FAMILY: probe_free(probe); ERR_PROBE_CREATE: pt_loop_free(loop); ERR_LOOP_CREATE: ERR_ADDRESS_FROM_STRING: ERR_ADDRESS_GUESS_FAMILY: exit(ret); }
int main(int argc, char ** argv) { int exit_code = EXIT_FAILURE; char * version = strdup("version 1.0"); const char * usage = "usage: %s [options] host\n"; void * algorithm_options; traceroute_options_t traceroute_options; traceroute_options_t * ptraceroute_options; mda_options_t mda_options; probe_t * probe; pt_loop_t * loop; int family; address_t dst_addr; options_t * options; char * dst_ip; const char * algorithm_name; const char * protocol_name; bool use_icmp, use_udp, use_tcp; // Prepare the commande line options if (!(options = init_options(version))) { fprintf(stderr, "E: Can't initialize options\n"); goto ERR_INIT_OPTIONS; } // Retrieve values passed in the command-line if (options_parse(options, usage, argv) != 1) { fprintf(stderr, "%s: destination required\n", basename(argv[0])); goto ERR_OPT_PARSE; } // We assume that the target IP address is always the last argument dst_ip = argv[argc - 1]; algorithm_name = algorithm_names[0]; protocol_name = protocol_names[0]; // Checking if there is any conflicts between options passed in the commandline if (!check_options(is_icmp, is_tcp, is_udp, is_ipv4, is_ipv6, dst_port[3], src_port[3], protocol_name, algorithm_name)) { goto ERR_CHECK_OPTIONS; } use_icmp = is_icmp || strcmp(protocol_name, "icmp") == 0; use_tcp = is_tcp || strcmp(protocol_name, "tcp") == 0; use_udp = is_udp || strcmp(protocol_name, "udp") == 0; // If not any ip version is set, call address_guess_family. // If only one is set to true, set family to AF_INET or AF_INET6 if (is_ipv4) { family = AF_INET; } else if (is_ipv6) { family = AF_INET6; } else { // Get address family if not defined by the user if (!address_guess_family(dst_ip, &family)) goto ERR_ADDRESS_GUESS_FAMILY; } // Translate the string IP / FQDN into an address_t * instance if (address_from_string(family, dst_ip, &dst_addr) != 0) { fprintf(stderr, "E: Invalid destination address %s\n", dst_ip); goto ERR_ADDRESS_IP_FROM_STRING; } // Probe skeleton definition: IPv4/UDP probe targetting 'dst_ip' if (!(probe = probe_create())) { fprintf(stderr,"E: Cannot create probe skeleton"); goto ERR_PROBE_CREATE; } // Prepare the probe skeleton probe_set_protocols( probe, get_ip_protocol_name(family), // "ipv4" | "ipv6" get_protocol_name(family, use_icmp, use_tcp, use_udp), // "icmpv4" | "icmpv6" | "tcp" | "udp" NULL ); probe_set_field(probe, ADDRESS("dst_ip", &dst_addr)); if (send_time[3]) { if(send_time[0] <= 10) { // seconds probe_set_delay(probe, DOUBLE("delay", send_time[0])); } else { // milli-seconds probe_set_delay(probe, DOUBLE("delay", 0.001 * send_time[0])); } } // ICMPv* do not support src_port and dst_port fields nor payload. if (!use_icmp) { uint16_t sport = 0, dport = 0; if (use_udp) { // Option -U sets port to 53 (DNS) if dst_port is not explicitely set sport = src_port[3] ? src_port[0] : UDP_DEFAULT_SRC_PORT; dport = dst_port[3] ? dst_port[0] : (is_udp ? UDP_DST_PORT_USING_U : UDP_DEFAULT_DST_PORT); } else if (use_tcp) { // Option -T sets port to 80 (http) if dst_port is not explicitely set sport = src_port[3] ? src_port[0] : TCP_DEFAULT_SRC_PORT; dport = dst_port[3] ? dst_port[0] : (is_tcp ? TCP_DST_PORT_USING_T : TCP_DEFAULT_DST_PORT); } // Update ports probe_set_fields( probe, I16("src_port", sport), I16("dst_port", dport), NULL ); // Resize payload (it will be use to set our customized checksum in the {TCP, UDP} layer) probe_payload_resize(probe, 2); } // Algorithm options (dedicated options) if (strcmp(algorithm_name, "paris-traceroute") == 0) { traceroute_options = traceroute_get_default_options(); ptraceroute_options = &traceroute_options; algorithm_options = &traceroute_options; algorithm_name = "traceroute"; } else if ((strcmp(algorithm_name, "mda") == 0) || options_mda_get_is_set()) { mda_options = mda_get_default_options(); ptraceroute_options = &mda_options.traceroute_options; algorithm_options = &mda_options; options_mda_init(&mda_options); } else { fprintf(stderr, "E: Unknown algorithm"); goto ERR_UNKNOWN_ALGORITHM; } // Algorithm options (common options) options_traceroute_init(ptraceroute_options, &dst_addr); // Create libparistraceroute loop if (!(loop = pt_loop_create(loop_handler, NULL))) { fprintf(stderr, "E: Cannot create libparistraceroute loop"); goto ERR_LOOP_CREATE; } // Set network options (network and verbose) options_network_init(loop->network, is_debug); printf("%s to %s (", algorithm_name, dst_ip); address_dump(&dst_addr); printf("), %u hops max, %u bytes packets\n", ptraceroute_options->max_ttl, (unsigned int)packet_get_size(probe->packet) ); // Add an algorithm instance in the main loop if (!pt_add_instance(loop, algorithm_name, algorithm_options, probe)) { fprintf(stderr, "E: Cannot add the chosen algorithm"); goto ERR_INSTANCE; } // Wait for events. They will be catched by handler_user() if (pt_loop(loop, 0) < 0) { fprintf(stderr, "E: Main loop interrupted"); goto ERR_PT_LOOP; } exit_code = EXIT_SUCCESS; // Leave the program ERR_PT_LOOP: ERR_INSTANCE: // pt_loop_free() automatically removes algorithms instances, // probe_replies and events from the memory. // Options and probe must be manually removed. pt_loop_free(loop); ERR_LOOP_CREATE: ERR_UNKNOWN_ALGORITHM: probe_free(probe); ERR_PROBE_CREATE: ERR_ADDRESS_IP_FROM_STRING: ERR_ADDRESS_GUESS_FAMILY: if (errno) perror(gai_strerror(errno)); ERR_CHECK_OPTIONS: ERR_OPT_PARSE: ERR_INIT_OPTIONS: free(version); exit(exit_code); }