Beispiel #1
0
static bool probe_push_payload(probe_t * probe, size_t payload_size) {
    layer_t * payload_layer,
            * first_layer;
    uint8_t * payload_bytes;
    size_t    packet_size;

    // Check whether a payload is already set
    if ((payload_layer = probe_get_layer_payload(probe))) {
        fprintf(stderr, "Payload already set\n");
        goto ERR_PAYLOAD_ALREADY_SET;
    }

    // Get the first protocol layer
    if (!(first_layer = probe_get_layer(probe, 0))) {
        fprintf(stderr, "No protocol layer defined in this probe\n");
        goto ERR_NO_FIRST_LAYER;
    }

    // The first segment stores the packet size, thus:
    // @payload = @first_segment + packet_size - payload_size
    packet_size = probe_get_size(probe) ;
    payload_bytes = packet_get_bytes(probe->packet) + packet_size - payload_size;

    if (!(payload_layer = layer_create_from_segment(NULL, payload_bytes, payload_size))) {
        goto ERR_LAYER_CREATE;
    }

    // Add the payload layer in the probe
    if (!(probe_push_layer(probe, payload_layer))) {
        fprintf(stderr, "Can't push payload layer\n");
        goto ERR_PUSH_LAYER;
    }

    // Resize the payload if required
    if (payload_size > 0) {
        if (!probe_payload_resize(probe, payload_size)) {
            fprintf(stderr, "Can't resize payload\n");
            goto ERR_PAYLOAD_RESIZE;
        }
    }

    return true;

ERR_PAYLOAD_RESIZE:
    dynarray_del_ith_element(probe->layers, probe_get_num_layers(probe) - 1, NULL);
ERR_PUSH_LAYER:
    layer_free(payload_layer);
ERR_LAYER_CREATE:
ERR_NO_FIRST_LAYER:
ERR_PAYLOAD_ALREADY_SET:
    return false;
}
static probe_t * network_get_matching_probe(network_t * network, const probe_t * reply)
{

    // Suppose we perform a traceroute measurement thanks to IPv4/UDP packet
    // We encode in the IPv4 checksum the ID of the probe.
    // Then, we should sniff an IPv4/ICMP/IPv4/UDP packet.
    // The ICMP message carries the begining of our probe packet, so we can
    // retrieve the checksum (= our probe ID) of the second IP layer, which
    // corresponds to the 3rd checksum field of our probe.

    uint16_t   tag_probe, tag_reply;
    probe_t  * probe;
    size_t     i, num_flying_probes;

    // XXX
    
    // Fetch the tag from the reply. Its the 3rd checksum field.
    if (!(reply_extract_tag(reply, &tag_reply))) {
        // This is not an IP / ICMP / IP / * reply :(
        if (network->is_verbose) fprintf(stderr, "Can't retrieve tag from reply\n");
        return NULL;
    }

    num_flying_probes = dynarray_get_size(network->probes);
    for (i = 0; i < num_flying_probes; i++) {
        probe = dynarray_get_ith_element(network->probes, i);

        // Reply / probe comparison. In our probe packet, the probe ID
        // is stored in the checksum of the (first) IP layer.
        if (probe_extract_tag(probe, &tag_probe)) {
            if (tag_reply == tag_probe) break;
        }
    }
    
/*
    // XXX BEGIN Harcoded ICMP response (JA 17/07/2014)
    tag_reply = 0; tag_probe = 0; tag_probe++; tag_reply++;

    num_flying_probes = dynarray_get_size(network->probes);
    for (i = 0; i < num_flying_probes; i++) {
        probe = dynarray_get_ith_element(network->probes, i);

        // Reply / probe comparison. In our probe packet, the probe ID
        // is stored in the checksum of the (first) IP layer.
        if (probe_match((const struct probe_s *)probe, (const struct probe_s *)reply))
            break;
    }
    // XXX END Hardcoded ICMP response
*/
    // No match found if we reached the end of the array
    if (i == num_flying_probes) {
        if (network->is_verbose) {
            fprintf(stderr, "network_get_matching_probe: This reply has been discarded: tag = 0x%x.\n", tag_reply);
            network_flying_probes_dump(network);
        }
        return NULL;
    }

    // We delete the corresponding probe

    // TODO: ... but it should be kept, for archive purposes, and to match for duplicates...
    // But we cannot reenable it until we set the probe ID into the
    // checksum, since probes with same flow_id and different TTL have the
    // same checksum

    dynarray_del_ith_element(network->probes, i, NULL);

    // The matching probe is the oldest one and there are other probes, update
    // the timer according to the next unexpired probe timeout.
    if (i == 0) {
        if (!(network_update_next_timeout(network))) {
            fprintf(stderr, "Error while updating timeout\n");
        }
    }

    return probe;
}