bool network_process_recvq(network_t * network) { probe_t * probe, * reply; packet_t * packet; probe_reply_t * probe_reply; // Pop the packet from the queue if (!(packet = queue_pop_element(network->recvq, NULL))) { goto ERR_PACKET_POP; } // Transform the reply into a probe_t instance if(!(reply = probe_wrap_packet(packet))) { goto ERR_PROBE_WRAP_PACKET; } probe_set_recv_time(reply, get_timestamp()); if (network->is_verbose) { printf("Got reply:\n"); probe_dump(reply); } // Find the probe corresponding to this reply // The corresponding pointer (if any) is removed from network->probes if (!(probe = network_get_matching_probe(network, reply))) { goto ERR_PROBE_DISCARDED; } // Build a pair made of the probe and its corresponding reply if (!(probe_reply = probe_reply_create())) { goto ERR_PROBE_REPLY_CREATE; } // We're pass to the upper layer the probe and the reply to the upper layer. probe_reply_set_probe(probe_reply, probe); probe_reply_set_reply(probe_reply, reply); // Notify the instance which has build the probe that we've got the corresponding reply // TODO this provokes a double free: //pt_throw(NULL, probe->caller, event_create(PROBE_REPLY, probe_reply, NULL, (ELEMENT_FREE) probe_reply_free)); pt_throw(NULL, probe->caller, event_create(PROBE_REPLY, probe_reply, NULL, NULL)); // TODO probe_reply_free frees only the reply but probe_reply_deep_free cannot be used as other things may have references to its contents. return true; ERR_PROBE_REPLY_CREATE: ERR_PROBE_DISCARDED: probe_free(reply); ERR_PROBE_WRAP_PACKET: //packet_free(packet); TODO provoke segfault in case of stars ERR_PACKET_POP: return false; }
// TODO This could be replaced by watchers: FD -> action bool network_process_sendq(network_t * network) { probe_t * probe; packet_t * packet; size_t num_flying_probes; struct itimerspec new_timeout; // Probe skeleton when entering the network layer. // We have to duplicate the probe since the same address of skeleton // may have been passed to pt_send_probe. // => We duplicate this probe in the // network layer registry (network->probes) and then tagged. // Do not free probe at the end of this function. // Its address will be saved in network->probes and freed later. probe = queue_pop_element(network->sendq, NULL); // Tag the probe if (!network_tag_probe(network, probe)) { fprintf(stderr, "Can't tag probe\n"); goto ERR_TAG_PROBE; } if (network->is_verbose) { printf("Sending probe packet:\n"); probe_dump(probe); } // Make a packet from the probe structure if (!(packet = probe_create_packet(probe))) { fprintf(stderr, "Can't create packet\n"); goto ERR_CREATE_PACKET; } // Send the packet if (!(socketpool_send_packet(network->socketpool, packet))) { fprintf(stderr, "Can't send packet\n"); goto ERR_SEND_PACKET; } // Update the sending time probe_set_sending_time(probe, get_timestamp()); // Register this probe in the list of flying probes if (!(dynarray_push_element(network->probes, probe))) { fprintf(stderr, "Can't register probe\n"); goto ERR_PUSH_PROBE; } // We've just sent a probe and currently, this is the only one in transit. // So currently, there is no running timer, prepare timerfd. num_flying_probes = dynarray_get_size(network->probes); if (num_flying_probes == 1) { itimerspec_set_delay(&new_timeout, network_get_timeout(network)); if (timerfd_settime(network->timerfd, 0, &new_timeout, NULL) == -1) { fprintf(stderr, "Can't set timerfd\n"); goto ERR_TIMERFD; } } return true; ERR_TIMERFD: ERR_PUSH_PROBE: ERR_SEND_PACKET: packet_free(packet); ERR_CREATE_PACKET: ERR_TAG_PROBE: return false; }
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); }