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; }