简体   繁体   中英

Sending structs over a C socket

I'm writing a DNS query client and can't understand how my data is being sent and how to make it work correctly.

In Wireshark, I'm getting a lot of random data with MALFORMED PACKET warnings, and no response from the DNS server I'm testing with. (currently Google's DNS... 8.8.8.8)

A snippet...

typedef struct DNS_HEADER {

    // id to identify the request
    int16_t id;

    // query or response flag; default is 0
    uint8_t qr :1;

    // type of query; default is 0
    uint8_t opcode :4;

    // authoritative answer
    uint8_t aa :1;

    // message was truncated
    uint8_t tc :1;

    // recursion desired; default is yes
    uint8_t rd :1;

    // recursion available
    uint8_t ra :1;

    // unused
    uint8_t z :1;

    // response code
    uint8_t rcode :4;

    // entries in the question section; default is 1
    uint16_t qdcount;

    // resource records
    uint16_t ancount;

    // server resource records (in the authority section)
    uint16_t nscount;

    // resource records (in addl. section)
    uint16_t arcount;

} dns_h;

header->qr = 0;
header->opcode = 0;
...
header->qdcount = htons(1);
...

And my sendto...

char buffer[sizeof(*header) * sizeof(*question) * 2];
int offset = 0;
memcpy(buffer, header, sizeof(*header));
offset += sizeof(*header);
memcpy(buffer + offset, question, sizeof(*question)); 

ssize_t sent = sendto(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)addr, sizeof(*addr));

What am I doing wrong? Is this the recommended way to send a struct over a socket? I've set most fields in the header to 0 and anything I've set to 1 I've used htons

Two problems with your header struct:

  • The z field is 3 bits, not 1. So the rcode field is two bits left of where it should be.
  • The fact that you're using bitfields at all. To get this right you'd need to know the endianness at compile time and there's no portable way to do this. You're better off declaring a single 16-bit field (or 2 8-bit fields) for everything and bit shifting to read/write the proper values.

You don't show the code where you're creating the header, but make sure you use htons when setting the fields so that the values are in network byte order.

Also, take a close look at the binary data in the packet in Wireshark. Compare that with the values you put in to see what's out of place.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM