Middle of parsing incoming datagrams.
[adns] / src / reply.c
1 /**/
2
3 #include "internal.h"
4
5 typedef enum {
6 rcode_noerror,
7 rcode_formaterror,
8 rcode_serverfail,
9 rcode_nxdomain,
10 rcode_notimp,
11 rcode_refused
12 } dns_rcode;
13
14 void adns__procdgram(adns_state ads, const byte *dgram, int len, int serv) {
15 unsigned char *rpp;
16
17 if (len<12) {
18 adns__diag(ads,serv,"received datagram too short for message header (%d)",len);
19 return;
20 }
21 id= GFREPLYW;
22 f1= GFREPLYB;
23 f2= GFREPLYB;
24 qdcount= GFREPLYW;
25 ancount= GFREPLYW;
26 nscount= GFREPLYW;
27 arcount= GFREPLYW;
28
29 if (f1&0x80) {
30 adns__diag(ads,serv,"server sent us a query, not a response");
31 return;
32 }
33 if (f1&0x70) {
34 adns__diag(ads,serv,"server sent us unknown opcode %d (wanted 0=QUERY)",
35 (f1>>4)&0x70);
36 return;
37 }
38 if (!qdcount) {
39 adns__diag(ads,serv,"server sent reply without quoting our question");
40 return;
41 } else if (qdcount>1) {
42 adns__diag(ads,serv,"server claimed to answer %d questions with one message",
43 qdcount);
44 return;
45 }
46 for (qu= ads->timew; qu= nqu; qu++) {
47 nqu= qu->next;
48 if (qu->id != id) continue;
49 if (len < qu->querylen) continue;
50 if (memcmp(qu->querymsg+12,rpp,qu->querylen-12)) continue;
51 break;
52 }
53 if (!qu) {
54 adns__debug(ads,serv,"reply not found (id=%02x)",id);
55 return;
56 }
57 if (!(f2&0x80)) {
58 adns__diag(ads,serv,"server is not willing to do recursive lookups for us");
59 adns__query_fail(ads,qu,adns_s_norecurse);
60 return;
61 }
62 if (!(f1&0x01)) {
63 adns__diag(ads,serv,"server thinks we didn't ask for recursive lookup");
64 adns__query_fail(ads,qu,adns_s_serverfaulty);
65 return;
66 }
67 switch (f1&0x0f) {
68 case 0: /* NOERROR */
69 break;
70 case 1: /* Format error */
71 adns__diag(ads,serv,"server cannot understand our query (Format Error)");
72 adns__query_fail(ads,qu,adns_s_serverfaulty);
73 return;
74 case 2: /* Server failure */
75 adns__query_fail(ads,qu,adns_s_serverfailure);
76 return;
77 case 3: /* Name Error */
78
79 qr= f1&0x80;
80
81
82 adns__diag(ads,serv,"received datagram size %d",len);
83
84 }