ddd
ddd

Reputation: 359

constructing and parsing network packet

I have the following packet format:

   1B       4B      1B    1B    string   2 bytes    1B      string  
+------+----------+---+--------+---~~--+---------+--------+---~~---+
| type | lifetime | 2 | length | Name  | Counter | length |  Data  |
+------+----------+---+--------+---~~--+---------+--------+---~~---+

typedef struct pkt_data {
    u_char pkt_type;
    u_int lifetime;
    u_char type;
    u_char len_name;
    u_char name[100];
    u_short counter;
    u_char len_data;
    u_char data[200];
}__attribute__((__packed__)) Data;

Here is the code for constructing and parsing the packet:

int buildDataPacket(u_int _lifetime, u_char* _name, u_short _counter, u_char* _data, u_char* _dataPacket) {
    Data *ndata=NULL;
    u_char *ptr;

    memset(_dataPacket, 0, 512);

    ndata = (Data *) _dataPacket;
    ndata->pkt_type = 2;
    ndata->lifetime = htonl(_lifetime);
    ndata->type = 2;
    ndata->len_name = strlen(_name);

    ptr = (u_char *)ndata + (3 * sizeof(u_char)) + sizeof(u_int);
    strncpy((char *)ptr, (char *)_name, strlen(_name));

    u_short counter = htons(_counter);
    u_char datalen = strlen(_data);

    ptr = ptr + strlen(_name);
    memcpy(ptr, &counter, sizeof(u_short));
    ptr = ptr + sizeof(u_short);
    memcpy(ptr, &datalen, sizeof(u_char));
    ptr = ptr + sizeof(u_char);
    strncpy((char *)ptr, (char *)_data, strlen(_data));
    ptr = ptr + strlen(_data);

    return (ptr - (u_char *)_dataPacket);
}

int processDataPacket(u_char* _dataPacket, u_short _pktLen)
{
    if (!_dataPacket || !_pktLen) {
            return -1;
    }

    Data *dataPkt;
    dataPkt = (Data *)_dataPacket;

    printf("Lifetime: %d\n", ntohl(dataPkt->lifetime));
    printf("Name: %s\n", dataPkt->name);
    printf("Counter: %d\n", dataPkt->counter);
    printf("Data: %s\n", dataPkt->data);

    return 0;
}

When I sniffed the packet in wireshark, I found that the construction of the packet is according to the format. But "counter" and "len_data" values are zero even though I set them accordingly. Also when I receive the packet, the full packet is not stored in the buffer.

rval=recvfrom(inet_sock, buf, BUFLEN-1, MSG_DONTWAIT, (struct sockaddr *) &dest_sin, &socklen);

buf[rval]=0;
fprintf(stderr, "Received: %d (%d) bytes containing %s", rval, strlen(buf), buf);

'rval' returns correct total num of bytes but 'buf' is terminated after "name". strlen(buf) returns the length of the packet only until the name. So "data" is empty in processDataPacket. Please guide me on how to construct and parse this packet.

Upvotes: 2

Views: 1790

Answers (1)

cnicutar
cnicutar

Reputation: 182714

ptr = ptr + strlen(_name);
memcpy(ptr, &counter, sizeof(u_short));

This is wrong. You're only advancing the pointer strlen(_name) positions when you should be advancing it precisely 100, since _name is u_char name[100].

Side note:

  • u_int lifetime; isn't guaranteed to be 4 bytes. Use uint32_t for that. Same goes for u_short (use uint16_t)

strlen(buf) returns the length of the packet

Since the packet isn't just a big string (it also contains non-text data, such as u_int lifetime) it's not OK to use strlen which will stop at the first 0 byte.

Upvotes: 2

Related Questions