aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-01-04 11:18:25 +0000
committerChristian Grothoff <christian@grothoff.org>2012-01-04 11:18:25 +0000
commita88b52ae2d2b3e1dadc32178edd3e540a92e3deb (patch)
treeccd3a0d3715a2628a2d9c729ff05aaa8088ef59a /src
parent3d7d5697cbc20ded49886a450937512b317f4d83 (diff)
downloadgnunet-a88b52ae2d2b3e1dadc32178edd3e540a92e3deb.tar.gz
gnunet-a88b52ae2d2b3e1dadc32178edd3e540a92e3deb.zip
-finishing DNS parser, alas untested
Diffstat (limited to 'src')
-rw-r--r--src/dns/dnsparser.c137
1 files changed, 134 insertions, 3 deletions
diff --git a/src/dns/dnsparser.c b/src/dns/dnsparser.c
index 8e2818fd8..2cd728f37 100644
--- a/src/dns/dnsparser.c
+++ b/src/dns/dnsparser.c
@@ -40,10 +40,102 @@ struct dns_header
40 uint16_t authority_rcount GNUNET_PACKED; // number of authority-records 40 uint16_t authority_rcount GNUNET_PACKED; // number of authority-records
41 uint16_t additional_rcount GNUNET_PACKED; // number of additional records 41 uint16_t additional_rcount GNUNET_PACKED; // number of additional records
42}; 42};
43
44struct query_line
45{
46 uint16_t type GNUNET_PACKED;
47 uint16_t class GNUNET_PACKED;
48};
49
50struct record_line
51{
52 uint16_t type GNUNET_PACKED;
53 uint16_t class GNUNET_PACKED;
54 uint32_t ttl GNUNET_PACKED;
55 uint16_t data_len GNUNET_PACKED;
56};
57
43GNUNET_NETWORK_STRUCT_END 58GNUNET_NETWORK_STRUCT_END
44 59
45 60
46/** 61/**
62 * Parse name inside of a DNS query or record.
63 *
64 * @param udp_payload entire UDP payload
65 * @param udp_payload_length length of udp_payload
66 * @param off pointer to the offset of the name to parse in the udp_payload (to be
67 * incremented by the size of the name)
68 * @return name as 0-terminated C string on success, NULL if the payload is malformed
69 */
70static char *
71parse_name (const char *udp_payload,
72 size_t udp_payload_length,
73 size_t *off)
74{
75 const uint8_t *input = (const uint8_t *) udp_payload;
76 char *ret;
77 char *tmp;
78 char *xstr;
79 uint8_t len;
80 size_t xoff;
81
82 ret = GNUNET_strdup ("");
83 while (1)
84 {
85 if (*off == udp_payload_length)
86 goto error;
87 len = input[*off];
88 if (0 == len)
89 break;
90 if (len < 64)
91 {
92 if (*off + 1 + len > udp_payload_length)
93 goto error;
94 GNUNET_asprintf (&tmp,
95 "%s%.*s.",
96 ret,
97 (int) len,
98 &udp_payload[*off + 1]);
99 GNUNET_free (ret);
100 ret = tmp;
101 off += 1 + len;
102 }
103 else if ((64 | 128) == (len & (64 | 128)) )
104 {
105 /* pointer to string */
106 if (*off + 1 > udp_payload_length)
107 goto error;
108 xoff = ((len - (64 | 128)) << 8) + input[*off+1];
109 xstr = parse_name (udp_payload,
110 udp_payload_length,
111 &xoff);
112 GNUNET_asprintf (&tmp,
113 "%s%s.",
114 ret,
115 xstr);
116 GNUNET_free (ret);
117 GNUNET_free (xstr);
118 ret = tmp;
119 off += 2;
120 /* pointers always terminate names */
121 break;
122 }
123 else
124 {
125 /* neither pointer nor inline string, not supported... */
126 goto error;
127 }
128 }
129 if (0 < strlen(ret))
130 ret[strlen(ret)-1] = '\0'; /* eat tailing '.' */
131 return ret;
132 error:
133 GNUNET_free (ret);
134 return NULL;
135}
136
137
138/**
47 * Parse a DNS query entry. 139 * Parse a DNS query entry.
48 * 140 *
49 * @param udp_payload entire UDP payload 141 * @param udp_payload entire UDP payload
@@ -59,7 +151,22 @@ parse_query (const char *udp_payload,
59 size_t *off, 151 size_t *off,
60 struct GNUNET_DNSPARSER_Query *q) 152 struct GNUNET_DNSPARSER_Query *q)
61{ 153{
62 return GNUNET_SYSERR; 154 char *name;
155 struct query_line ql;
156
157 name = parse_name (udp_payload,
158 udp_payload_length,
159 off);
160 if (NULL == name)
161 return GNUNET_SYSERR;
162 q->name = name;
163 if (*off + sizeof (struct query_line) > udp_payload_length)
164 return GNUNET_SYSERR;
165 memcpy (&ql, &udp_payload[*off], sizeof (ql));
166 *off += sizeof (ql);
167 q->type = ntohs (ql.type);
168 q->class = ntohs (ql.class);
169 return GNUNET_OK;
63} 170}
64 171
65 172
@@ -79,11 +186,35 @@ parse_record (const char *udp_payload,
79 size_t *off, 186 size_t *off,
80 struct GNUNET_DNSPARSER_Record *r) 187 struct GNUNET_DNSPARSER_Record *r)
81{ 188{
82 return GNUNET_SYSERR; 189 char *name;
190 struct record_line rl;
191
192 name = parse_name (udp_payload,
193 udp_payload_length,
194 off);
195 if (NULL == name)
196 return GNUNET_SYSERR;
197 r->name = name;
198 if (*off + sizeof (struct record_line) > udp_payload_length)
199 return GNUNET_SYSERR;
200 memcpy (&rl, &udp_payload[*off], sizeof (rl));
201 *off += sizeof (rl);
202 r->type = ntohs (rl.type);
203 r->class = ntohs (rl.class);
204 r->expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
205 ntohl (rl.ttl)));
206 r->data_len = ntohs (rl.data_len);
207 if (*off + r->data_len > udp_payload_length)
208 return GNUNET_SYSERR;
209 if (0 == r->data_len)
210 return GNUNET_OK;
211 r->data = GNUNET_malloc (r->data_len);
212 memcpy (r->data, &udp_payload[*off], r->data_len);
213 *off += r->data_len;
214 return GNUNET_OK;
83} 215}
84 216
85 217
86
87/** 218/**
88 * Parse a UDP payload of a DNS packet in to a nice struct for further 219 * Parse a UDP payload of a DNS packet in to a nice struct for further
89 * processing and manipulation. 220 * processing and manipulation.