Esempio n. 1
0
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;
}
Esempio n. 2
0
// 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);
}