Exemple #1
0
static bool probe_packet_resize(probe_t * probe, size_t size)
{
    size_t    offset = 0, // offset between the begining of the packet and the current position
              i, num_layers = probe_get_num_layers(probe);
    layer_t * layer;
    uint8_t * segment;

    if (!packet_resize(probe->packet, size)) {
        return false;
    }

    // TODO update bitfield

    // Update each layer's segment
    for (i = 0; i < num_layers; i++) {
        layer = probe_get_layer(probe, i);
        segment = packet_get_bytes(probe->packet) + offset;
        layer_set_segment(layer, segment);

        if (layer->protocol) {
            // We're in a layer related to a protocol. Update "length" field (if any).
            // It concerns: ipv4, ipv6, udp but not tcp, icmpv4, icmpv6
            layer_set_field_and_free(layer, I16("length", size - offset));
            offset += layer->segment_size;
        }
    }

    return true;
}
Exemple #2
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;
}
bool socketpool_send_packet(const socketpool_t * socketpool, const packet_t * packet)
{
	sockaddr_u              sock;
    int                     sockfd;
    socklen_t               socklen;
    const struct sockaddr * dst_addr;
    
    memset(&sock, 0, sizeof(sockaddr_u));

    // Prepare socket 
    // We don't care about the dst_port set in the packet
    switch (packet->dst_ip->family) {
#ifdef USE_IPV4
        case AF_INET:
            sock.sin.sin_family = AF_INET;
            sock.sin.sin_addr   = packet->dst_ip->ip.ipv4;
            sockfd = socketpool->ipv4_sockfd;
            socklen = sizeof(struct sockaddr_in);
            dst_addr = (struct sockaddr *) &sock.sin;
            break;
#endif
#ifdef USE_IPV6
        case AF_INET6:
            sock.sin6.sin6_family = AF_INET6;
            memcpy(&sock.sin6.sin6_addr, &packet->dst_ip->ip.ipv6, sizeof(ipv6_t));
            sockfd = socketpool->ipv6_sockfd;
            socklen = sizeof(struct sockaddr_in6);
            dst_addr = (struct sockaddr *) &sock.sin6;
            break;
#endif
        default:
            fprintf(stderr, "socketpool_send_packet: Address family not supported");
            goto ERR_INVALID_FAMILY;
    }

    // Send the packet
    if (sendto(sockfd, packet_get_bytes(packet), packet_get_size(packet), 0, dst_addr, socklen) == -1) {
        perror("send_data: Sending error in queue");
        goto ERR_SEND_TO;
    }

    return true;

ERR_SEND_TO:
ERR_INVALID_FAMILY:
    return false;
}
Exemple #4
0
bool probe_set_protocols(probe_t * probe, const char * name1, ...)
{
    // TODO A similar function should allow hooking into the layer structure
    // and not at the top layer

    va_list            args, args2;
    size_t             packet_size, offset, segment_size;
    const char       * name;
    layer_t          * layer = NULL,
                     * prev_layer;
    const protocol_t * protocol;

    // Remove the former layer structure
    probe_layers_clear(probe);

    // Set up the new layer structure
    va_start(args, name1);

    // Allocate the buffer according to the layer structure
    packet_size = 0;
    va_copy(args2, args);
    for (name = name1; name; name = va_arg(args2, char *)) {
        if (!(protocol = protocol_search(name))) {
            fprintf(stderr, "Cannot find %s protocol, known protocols are:", name);
            protocols_dump();
            goto ERR_PROTOCOL_SEARCH;
        }
        packet_size += protocol->write_default_header(NULL);
    }
    va_end(args2);
    if (!(packet_resize(probe->packet, packet_size))) goto ERR_PACKET_RESIZE;

    // Create each layer
    offset = 0;
    prev_layer = NULL;
    for (name = name1; name; name = va_arg(args, char *)) {
        // Associate protocol to the layer
        if (!(protocol = protocol_search(name))) goto ERR_PROTOCOL_SEARCH2;
        segment_size = protocol->write_default_header(packet_get_bytes(probe->packet) + offset);

        if (!(layer = layer_create_from_segment(protocol, packet_get_bytes(probe->packet) + offset, segment_size))) {
            fprintf(stderr, "Can't create segment for %s header\n", layer->protocol->name);
            goto ERR_LAYER_CREATE;
        }
        // TODO layer_set_mask(layer, bitfield_get_mask(probe->bitfield) + offset);

        // Update 'length' field (if any). It concerns IPv* and UDP, but not TCP or ICMPv*
        layer_set_field_and_free(layer, I16("length", packet_size - offset));

        // Update 'protocol' field of the previous inserted layer (if any)
        if (prev_layer) {
            if (!layer_set_field_and_free(prev_layer, I8("protocol", layer->protocol->protocol))) {
                fprintf(stderr, "Can't set 'protocol' in %s header\n", layer->protocol->name);
                goto ERR_SET_PROTOCOL;
            }
        }

        offset += layer->segment_size;
        if (!probe_push_layer(probe, layer)) {
            fprintf(stderr, "Can't add protocol layer\n");
            goto ERR_PUSH_LAYER;
        }
        prev_layer = layer;
    }
    va_end(args);
    layer = NULL;

    // Payload : initially empty
    if (!probe_push_payload(probe, 0)) {
        goto ERR_PUSH_PAYLOAD;
    }

    // Size and checksum are pending, they depend on payload
    return true;

ERR_PUSH_PAYLOAD:
ERR_PUSH_LAYER:
ERR_SET_PROTOCOL:
    if (layer) layer_free(layer);
ERR_LAYER_CREATE:
ERR_PROTOCOL_SEARCH2:
    probe_layers_clear(probe);
ERR_PACKET_RESIZE:
ERR_PROTOCOL_SEARCH:
    return false;
}
Exemple #5
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;
}