0

Possible Duplicate:
C - byte array to structure (dns query)

I have these structures:

typedef struct dnsQuery {
  char header[12];
  struct dnsQuerySection *querySection;
} TdnsQuery;

typedef struct dnsQuerySection {
  unsigned char *name;
  struct dnsQueryQuestion *question;
} TdnsQuerySection;

typedef struct dnsQueryQuestion {
  unsigned short qtype;
  unsigned short qclass;
} TdnsQueryQuestion;

And I have a DNS query in a byte array buf from recvfrom. I am trying to get structure from byte array like this:

TdnsQuery* dnsQuery = (TdnsQuery*)buf;

When I tried to access qtype like this:

printf("%u", dnsQuery->querySection->question.qtype);

I get seg fault 11.

Can someone help me with these structures? What's wrong with them? I tried to add structure:

typedef struct udpPacket {
  char header[8];
  structr dnsQuery query;
}

And mapped this structure from byte array but it didn't help. Can someone help me with these structures? How they should look like for DNS query with UDP protocol?

Edit: My structures now looks like this:

 typedef struct {
      unsigned short qtype;
      unsigned short qclass;
 } dnsQueryQuestion;

 typedef struct {

      dnsQueryQuestion *question;
      unsigned char *data[0];
 } dnsQuerySection;

 typedef struct {
      char header[12];
      dnsQuerySection querySection[0];
 } dnsQuery;

 typedef struct udpPacket {
      char header[8];
      dnsQuery query[0];
 } TudpPacket;

I added parse function:

void parse(unsigned char *data, unsigned short *qtype, unsigned short *qclass) {
    int i = 0;
    while (data[i]) {
        int len = data[i];
        i += len + 1;
    }
    *qtype = (unsigned short) data[i+1];
    *qclass = (unsigned short) data[i+3];
    return;
} 

and tried to parse:

TudpPacket udpPack = (TudpPacket)buf;
parse(udpPack.query.querySection.data, &(udpPack.query.querySection.question.qtype), &(udpPack.query.querySection.question.qclass));
printf("%u\n", udpPack.query.querySection.question.qtype);
Community
  • 1
  • 1
Libor Zapletal
  • 13,752
  • 20
  • 95
  • 182

1 Answers1

3

First you can start out by changing dnsQuery to this:

typedef struct dnsQuery {
  char header[12];
  struct dnsQuerySection querySection[0];
} TdnsQuery;

See the usage of zero-length array here: http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html

However, because the QNAME part in a DNS question is variable-length, you may not be able to do it separately from QTYPE and QCLASS by using struct directly. For example,

Header

00 01   - ID = 1
01 00   - RD = 1
00 01   - QD = 1
00 00   - AN
00 00   - NS
00 00   - NR

   Question  for www.google.com

   03 77   - 3 w
   77 77   - w w
   06 67   - 6 g
   6f 6f   - o o
   67 6c   - g l
   65 03   - e 3
   63 6f   - c o
   6d 00   - m 0
   00 01   - QTYPE
   00 01   - QCLASS

If you can guarantee there's only one question in the incoming request, try this:

typedef struct dnsQuerySection {
  unsigned char *data[0];
} TdnsQuerySection;

and write a function to parse it.

EDIT: Below is a sketch for the parse function, just for your convenience.

char* parse(unsigned char *data, unsigned short *qtype, unsigned short *qclass) {
    int i = 0;
    while (data[i]) {
        int len = data[i];
        i += len + 1;
    }
    /* data[i] == 0 */
    /* you may need to loop data[] again and do strcpy to get the domain name */
    *qtype = (unsigned short) data[i+1];
    *qclass = (unsigned short) data[i+3];
    return /* domain name */;
}
Xiao Jia
  • 4,169
  • 2
  • 29
  • 47
  • Thanks for this and for parse function but I have problem with that zero-length array. I get error: "array type has incomplete element type". – Libor Zapletal Nov 18 '12 at 11:12
  • @Bibo Maybe this helps: http://stackoverflow.com/questions/6957766/array-type-has-incomplete-element-type – Xiao Jia Nov 18 '12 at 11:15
  • Yea, it helps. I edited my question above and I still got seg fault. When compile I get errors: "passing argument 1 of 'parse' from incompatible pointer type" and "ISO C forbids zero-size array". Can you help me with this? For now I don´t need domain name so I remove that from your parser. – Libor Zapletal Nov 18 '12 at 11:52
  • @Bibo Are you sure your code can compile? There is mistyped `structr`. Also you are still using `->` instead of `.` – Xiao Jia Nov 18 '12 at 12:17
  • Mistyped structr was just here in code it's ok. I fixed it. When I used `.` I get error: "request for member ... in something not a structure or union" – Libor Zapletal Nov 18 '12 at 12:23
  • @Bibo Because you're still using `dnsQuerySection *querySection;`. Please use `dnsQuerySection querySection[0];` and make sure you understand the memory layout of a `struct`. Using a pointer here will of course lead to a seg fault because you're mis-reusing **data** in the buffer as pointer. – Xiao Jia Nov 18 '12 at 12:40
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/19706/discussion-between-bibo-and-xiao-jia) – Libor Zapletal Nov 18 '12 at 12:54