2

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.

1 Answer 1

2
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.

Sign up to request clarification or add additional context in comments.

1 Comment

Ok, thanks for your reply. Is there a way I can change the packet length to be variable based on the length of name and data strings instead of fixing 100 and 200 as the lengths. I tried using char* instead of char[100], but I get segmentation fault when I construct the packet. One more problem is that, when I do recvfrom, buf does not display the whole packet even though rval returns total num of bytes of the whole packet. I think due to the zeroes after the name string, buf is terminated and hence displays packet only till end of name. How do I fix this?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.