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