/work/open62541_15/src_generated/mdnsd/1035.c
Line | Count | Source |
1 | | #include "open62541/config.h" |
2 | | /* Standalone DNS parsing, RFC10350 |
3 | | * |
4 | | * Copyright (c) 2003 Jeremie Miller <jer@jabber.org> |
5 | | * Copyright (c) 2016-2022 Joachim Wiberg <troglobit@gmail.com> |
6 | | * All rights reserved. |
7 | | * |
8 | | * Redistribution and use in source and binary forms, with or without |
9 | | * modification, are permitted provided that the following conditions are met: |
10 | | * * Redistributions of source code must retain the above copyright |
11 | | * notice, this list of conditions and the following disclaimer. |
12 | | * * Redistributions in binary form must reproduce the above copyright |
13 | | * notice, this list of conditions and the following disclaimer in the |
14 | | * documentation and/or other materials provided with the distribution. |
15 | | * * Neither the name of the copyright holders nor the names of its |
16 | | * contributors may be used to endorse or promote products derived from |
17 | | * this software without specific prior written permission. |
18 | | * |
19 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
20 | | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
21 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
22 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE |
23 | | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | | * POSSIBILITY OF SUCH DAMAGE. |
30 | | */ |
31 | | |
32 | | #include "1035.h" |
33 | | #include <string.h> |
34 | | #include <stdio.h> |
35 | | |
36 | | unsigned short int net2short(unsigned char **bufp) |
37 | 1.78M | { |
38 | 1.78M | unsigned short int i; |
39 | | |
40 | 1.78M | i = **bufp; |
41 | 1.78M | i <<= 8; |
42 | 1.78M | i |= *(*bufp + 1); |
43 | 1.78M | *bufp += 2; |
44 | | |
45 | 1.78M | return i; |
46 | 1.78M | } |
47 | | |
48 | | unsigned long int net2long(unsigned char **bufp) |
49 | 232k | { |
50 | 232k | long int l; |
51 | | |
52 | 232k | l = **bufp; |
53 | 232k | l <<= 8; |
54 | 232k | l |= *(*bufp + 1); |
55 | 232k | l <<= 8; |
56 | 232k | l |= *(*bufp + 2); |
57 | 232k | l <<= 8; |
58 | 232k | l |= *(*bufp + 3); |
59 | 232k | *bufp += 4; |
60 | | |
61 | 232k | return l; |
62 | 232k | } |
63 | | |
64 | | void short2net(unsigned short int i, unsigned char **bufp) |
65 | 0 | { |
66 | 0 | *(*bufp + 1) = (unsigned char)i; |
67 | 0 | i >>= 8; |
68 | 0 | **bufp = (unsigned char)i; |
69 | 0 | *bufp += 2; |
70 | 0 | } |
71 | | |
72 | | void long2net(unsigned long int l, unsigned char **bufp) |
73 | 0 | { |
74 | 0 | *(*bufp + 3) = (unsigned char)l; |
75 | 0 | l >>= 8; |
76 | 0 | *(*bufp + 2) = (unsigned char)l; |
77 | 0 | l >>= 8; |
78 | 0 | *(*bufp + 1) = (unsigned char)l; |
79 | 0 | l >>= 8; |
80 | 0 | **bufp = (unsigned char)l; |
81 | 0 | *bufp += 4; |
82 | 0 | } |
83 | | |
84 | | static unsigned short int _ldecomp(const char *ptr) |
85 | 3.94k | { |
86 | 3.94k | unsigned short int i; |
87 | | |
88 | 3.94k | i = 0xc0 ^ ptr[0]; |
89 | 3.94k | i <<= 8; |
90 | 3.94k | i |= (unsigned char)ptr[1]; |
91 | 3.94k | if (i >= 4096) |
92 | 1.65k | i = 4095; |
93 | | |
94 | 3.94k | return i; |
95 | 3.94k | } |
96 | | |
97 | | static int _label(struct message *m, unsigned char **bufp, char **namep) |
98 | 771k | { |
99 | 771k | int x; |
100 | 771k | char *label, *name; |
101 | | |
102 | | |
103 | | /* Sanity check */ |
104 | 771k | if (m->_len > (int)sizeof(m->_packet)) |
105 | 209 | return 1; |
106 | | |
107 | | /* Set namep to the end of the block */ |
108 | 771k | *namep = name = (char *)m->_packet + m->_len; |
109 | | |
110 | | /* Loop storing label in the block */ |
111 | 780k | for (label = (char *)*bufp; *label != 0; name += *label + 1, label += *label + 1) { |
112 | | /* Skip past any compression pointers, kick out if end encountered (bad data prolly) */ |
113 | 9.45k | int prevOffset = -1; |
114 | 10.4k | while (*label & 0xc0) { |
115 | 3.94k | unsigned short int offset = _ldecomp(label); |
116 | 3.94k | if (offset <= prevOffset || offset > m->_len) |
117 | 52 | return 1; |
118 | 3.89k | if (*(label = (char *)m->_buf + offset) == 0) |
119 | 2.87k | break; |
120 | 1.02k | prevOffset = offset; |
121 | 1.02k | } |
122 | | |
123 | | /* Make sure we're not over the limits */ |
124 | 9.40k | if ((name + *label) - *namep > 255 || m->_len + ((name + *label) - *namep) >= MAX_PACKET_LEN) |
125 | 28 | return 1; |
126 | | |
127 | | /* Copy chars for this label */ |
128 | 9.37k | memcpy(name, label + 1, (size_t)*label); |
129 | 9.37k | name[(size_t)*label] = '.'; |
130 | 9.37k | } |
131 | | |
132 | | /* Advance buffer */ |
133 | 775k | for (label = (char *)*bufp; *label != 0 && !(*label & 0xc0 && label++); label += *label + 1) |
134 | 3.81k | ; |
135 | 771k | *bufp = (unsigned char *)(label + 1); |
136 | | |
137 | | /* Terminate name and check for cache or cache it */ |
138 | 771k | *name = '\0'; |
139 | 1.35M | for (x = 0; x < MAX_NUM_LABELS && m->_labels[x]; x++) { |
140 | 1.35M | if (strcmp(*namep, m->_labels[x])) |
141 | 581k | continue; |
142 | | |
143 | 768k | *namep = m->_labels[x]; |
144 | 768k | return 0; |
145 | 1.35M | } |
146 | | |
147 | | /* No cache, so cache it if room */ |
148 | 2.37k | if (x < MAX_NUM_LABELS && m->_labels[x] == 0) |
149 | 2.37k | m->_labels[x] = *namep; |
150 | 2.37k | m->_len += (int)(name - *namep) + 1; |
151 | | |
152 | 2.37k | return 0; |
153 | 771k | } |
154 | | |
155 | | /* Internal label matching */ |
156 | | static int _lmatch(const struct message *m, const char *l1, const char *l2) |
157 | 0 | { |
158 | 0 | int len; |
159 | | |
160 | | /* Always ensure we get called w/o a pointer */ |
161 | 0 | if (*l1 & 0xc0) |
162 | 0 | return _lmatch(m, (char *)m->_buf + _ldecomp(l1), l2); |
163 | 0 | if (*l2 & 0xc0) |
164 | 0 | return _lmatch(m, l1, (char *)m->_buf + _ldecomp(l2)); |
165 | | |
166 | | /* Same already? */ |
167 | 0 | if (l1 == l2) |
168 | 0 | return 1; |
169 | | |
170 | | /* Compare all label characters */ |
171 | 0 | if (*l1 != *l2) |
172 | 0 | return 0; |
173 | 0 | for (len = 1; len <= *l1; len++) { |
174 | 0 | if (l1[len] != l2[len]) |
175 | 0 | return 0; |
176 | 0 | } |
177 | | |
178 | | /* Get new_ labels */ |
179 | 0 | l1 += *l1 + 1; |
180 | 0 | l2 += *l2 + 1; |
181 | | |
182 | | /* At the end, all matched */ |
183 | 0 | if (*l1 == 0 && *l2 == 0) |
184 | 0 | return 1; |
185 | | |
186 | | /* Try next labels */ |
187 | 0 | return _lmatch(m, l1, l2); |
188 | 0 | } |
189 | | |
190 | | /* Nasty, convert host into label using compression */ |
191 | | static int _host(struct message *m, unsigned char **bufp, const char *name) |
192 | 0 | { |
193 | 0 | char label[256], *l; |
194 | 0 | int len = 0, x = 1, y = 0, last = 0; |
195 | |
|
196 | 0 | if (name == 0) |
197 | 0 | return 0; |
198 | | |
199 | | /* Make our label */ |
200 | 0 | while (name[y]) { |
201 | 0 | if (name[y] == '.') { |
202 | 0 | if (!name[y + 1]) |
203 | 0 | break; |
204 | 0 | label[last] = (char)(x - (last + 1)); |
205 | 0 | last = x; |
206 | 0 | } else { |
207 | 0 | label[x] = name[y]; |
208 | 0 | } |
209 | | |
210 | 0 | if (x++ == 255) |
211 | 0 | return 0; |
212 | | |
213 | 0 | y++; |
214 | 0 | } |
215 | | |
216 | 0 | label[last] = (char)(x - (last + 1)); |
217 | 0 | if (x == 1) |
218 | 0 | x--; /* Special case, bad names, but handle correctly */ |
219 | 0 | len = x + 1; |
220 | 0 | label[x] = 0; /* Always terminate w/ a 0 */ |
221 | | |
222 | | /* Double-loop checking each label against all m->_labels for match */ |
223 | 0 | for (x = 0; label[x]; x += label[x] + 1) { |
224 | 0 | for (y = 0; y < MAX_NUM_LABELS && m->_labels[y]; y++) { |
225 | 0 | if (_lmatch(m, label + x, m->_labels[y])) { |
226 | | /* Matching label, set up pointer */ |
227 | 0 | l = label + x; |
228 | 0 | short2net((unsigned char *)m->_labels[y] - m->_packet, (unsigned char **)&l); |
229 | 0 | label[x] |= '\xc0'; |
230 | 0 | len = x + 2; |
231 | 0 | break; |
232 | 0 | } |
233 | 0 | } |
234 | | |
235 | 0 | if (label[x] & 0xc0) |
236 | 0 | break; |
237 | 0 | } |
238 | | |
239 | | /* Copy into buffer, point there now */ |
240 | 0 | memcpy(*bufp, label, len); |
241 | 0 | l = (char *)*bufp; |
242 | 0 | *bufp += len; |
243 | | |
244 | | /* For each new_ label, store it's location for future compression */ |
245 | 0 | for (x = 0; l[x] && m->_label < MAX_NUM_LABELS; x += l[x] + 1) { |
246 | 0 | if (l[x] & 0xc0) |
247 | 0 | break; |
248 | | |
249 | 0 | m->_labels[m->_label++] = l + x; |
250 | 0 | } |
251 | |
|
252 | 0 | return len; |
253 | 0 | } |
254 | | |
255 | | static int _rrparse(struct message *m, struct resource *rr, int count, unsigned char **bufp) |
256 | 2.78k | { |
257 | 2.78k | int i; |
258 | | |
259 | 235k | for (i = 0; i < count; i++) { |
260 | 233k | if (_label(m, bufp, &(rr[i].name))) |
261 | 226 | return 1; |
262 | 232k | rr[i].type = net2short(bufp); |
263 | 232k | rr[i].clazz = net2short(bufp); |
264 | 232k | rr[i].ttl = net2long(bufp); |
265 | 232k | rr[i].rdlength = net2short(bufp); |
266 | | // fprintf(stderr, "Record type %d clazz 0x%2x ttl %lu len %d\n", rr[i].type, rr[i].clazz, rr[i].ttl, rr[i].rdlength); |
267 | | |
268 | | /* If not going to overflow, make copy of source rdata */ |
269 | 232k | if (rr[i].rdlength + (*bufp - m->_buf) > MAX_PACKET_LEN || m->_len + rr[i].rdlength > MAX_PACKET_LEN) { |
270 | 36 | rr[i].rdlength = 0; |
271 | 36 | return 1; |
272 | 36 | } |
273 | | |
274 | | /* For the following records the rdata will be parsed later. So don't set it here: |
275 | | * NS, CNAME, PTR, DNAME, SOA, MX, AFSDB, RT, KX, RP, PX, SRV, NSEC |
276 | | * See 18.14 of https://tools.ietf.org/html/rfc6762#page-47 */ |
277 | 232k | if (rr[i].type == QTYPE_NS || rr[i].type == QTYPE_CNAME || rr[i].type == QTYPE_PTR || rr[i].type == QTYPE_SRV) { |
278 | 956 | rr[i].rdlength = 0; |
279 | 231k | } else { |
280 | 231k | rr[i].rdata = m->_packet + m->_len; |
281 | 231k | m->_len += rr[i].rdlength; |
282 | 231k | memcpy(rr[i].rdata, *bufp, rr[i].rdlength); |
283 | 231k | } |
284 | | |
285 | | |
286 | | /* Parse commonly known ones */ |
287 | 232k | switch (rr[i].type) { |
288 | 275 | case QTYPE_A: |
289 | 275 | if (m->_len + INET_ADDRSTRLEN > MAX_PACKET_LEN) |
290 | 3 | return 1; |
291 | 272 | rr[i].known.a.name = (char *)m->_packet + m->_len; |
292 | 272 | m->_len += INET_ADDRSTRLEN; |
293 | 272 | inet_ntop(AF_INET, *bufp, rr[i].known.a.name, INET_ADDRSTRLEN); |
294 | 272 | memcpy(&(rr[i].known.a.ip.s_addr), *bufp, sizeof(rr[i].known.a.ip.s_addr)); |
295 | 272 | *bufp += sizeof(rr[i].known.a.ip.s_addr); |
296 | 272 | break; |
297 | | |
298 | 198 | case QTYPE_AAAA: |
299 | 198 | if (m->_len + INET6_ADDRSTRLEN > MAX_PACKET_LEN) |
300 | 3 | return 1; |
301 | 195 | rr[i].known.aaaa.name = (char *)m->_packet + m->_len; |
302 | 195 | m->_len += INET6_ADDRSTRLEN; |
303 | 195 | inet_ntop(AF_INET6, *bufp, rr[i].known.aaaa.name, INET6_ADDRSTRLEN); |
304 | 195 | memcpy(rr[i].known.aaaa.ip6.s6_addr, *bufp, sizeof(rr[i].known.aaaa.ip6.s6_addr)); |
305 | 195 | *bufp += sizeof(rr[i].known.aaaa.ip6.s6_addr); |
306 | 195 | break; |
307 | | |
308 | 174 | case QTYPE_NS: |
309 | 174 | if (_label(m, bufp, &(rr[i].known.ns.name))) |
310 | 3 | return 1; |
311 | 171 | break; |
312 | | |
313 | 362 | case QTYPE_CNAME: |
314 | 362 | if (_label(m, bufp, &(rr[i].known.cname.name))) |
315 | 2 | return 1; |
316 | 360 | break; |
317 | | |
318 | 360 | case QTYPE_PTR: |
319 | 282 | if (_label(m, bufp, &(rr[i].known.ptr.name))) |
320 | 2 | return 1; |
321 | 280 | break; |
322 | | |
323 | 280 | case QTYPE_SRV: |
324 | 138 | rr[i].known.srv.priority = net2short(bufp); |
325 | 138 | rr[i].known.srv.weight = net2short(bufp); |
326 | 138 | rr[i].known.srv.port = net2short(bufp); |
327 | 138 | if (_label(m, bufp, &(rr[i].known.srv.name))) |
328 | 2 | return 1; |
329 | 136 | break; |
330 | | |
331 | 136 | case QTYPE_TXT: |
332 | 231k | default: |
333 | 231k | *bufp += rr[i].rdlength; |
334 | 232k | } |
335 | 232k | } |
336 | | |
337 | 2.51k | return 0; |
338 | 2.78k | } |
339 | | |
340 | | /* Keep all our mem in one (aligned) block for easy freeing */ |
341 | | #define my(x,y) \ |
342 | 7.00k | while (m->_len & 7) \ |
343 | 4.42k | m->_len++; \ |
344 | 4.42k | (x) = (void *)(m->_packet + m->_len); \ |
345 | 4.42k | m->_len += (y); |
346 | | |
347 | | int message_parse(struct message *m, unsigned char *packet) |
348 | 1.21k | { |
349 | 1.21k | int i; |
350 | 1.21k | unsigned char *buf; |
351 | | |
352 | 1.21k | if (packet == 0 || m == 0) |
353 | 0 | return 1; |
354 | | |
355 | | /* Header stuff bit crap */ |
356 | 1.21k | m->_buf = buf = packet; |
357 | 1.21k | m->id = net2short(&buf); |
358 | 1.21k | if (buf[0] & 0x80) |
359 | 599 | m->header.qr = 1; |
360 | 1.21k | m->header.opcode = (buf[0] & 0x78) >> 3; |
361 | 1.21k | if (buf[0] & 0x04) |
362 | 529 | m->header.aa = 1; |
363 | 1.21k | if (buf[0] & 0x02) |
364 | 588 | m->header.tc = 1; |
365 | 1.21k | if (buf[0] & 0x01) |
366 | 635 | m->header.rd = 1; |
367 | 1.21k | if (buf[1] & 0x80) |
368 | 229 | m->header.ra = 1; |
369 | 1.21k | m->header.z = (buf[1] & 0x70) >> 4; |
370 | 1.21k | m->header.rcode = buf[1] & 0x0F; |
371 | 1.21k | buf += 2; |
372 | | |
373 | 1.21k | m->qdcount = net2short(&buf); |
374 | 1.21k | if (m->_len + (sizeof(struct question) * m->qdcount) > MAX_PACKET_LEN - 8) { |
375 | 11 | m->qdcount = 0; |
376 | 11 | return 1; |
377 | 11 | } |
378 | | |
379 | 1.20k | m->ancount = net2short(&buf); |
380 | 1.20k | if (m->_len + (sizeof(struct resource) * m->ancount) > MAX_PACKET_LEN - 8) { |
381 | 31 | m->ancount = 0; |
382 | 31 | return 1; |
383 | 31 | } |
384 | | |
385 | 1.17k | m->nscount = net2short(&buf); |
386 | 1.17k | if (m->_len + (sizeof(struct resource) * m->nscount) > MAX_PACKET_LEN - 8) { |
387 | 16 | m->nscount = 0; |
388 | 16 | return 1; |
389 | 16 | } |
390 | | |
391 | 1.15k | m->arcount = net2short(&buf); |
392 | 1.15k | if (m->_len + (sizeof(struct resource) * m->arcount) > MAX_PACKET_LEN - 8) { |
393 | 12 | m->arcount = 0; |
394 | 12 | return 1; |
395 | 12 | } |
396 | | |
397 | | /* Process questions */ |
398 | 1.14k | my(m->qd, sizeof(struct question) * m->qdcount); |
399 | 538k | for (i = 0; i < m->qdcount; i++) { |
400 | 537k | if (_label(m, &buf, &(m->qd[i].name))) |
401 | 54 | return 1; |
402 | 537k | m->qd[i].type = net2short(&buf); |
403 | 537k | m->qd[i].clazz = net2short(&buf); |
404 | 537k | } |
405 | | |
406 | | /* Process rrs */ |
407 | 1.09k | my(m->an, sizeof(struct resource) * m->ancount); |
408 | 1.09k | my(m->ns, sizeof(struct resource) * m->nscount); |
409 | 1.09k | my(m->ar, sizeof(struct resource) * m->arcount); |
410 | 1.09k | if (_rrparse(m, m->an, m->ancount, &buf)) |
411 | 233 | return 1; |
412 | 860 | if (_rrparse(m, m->ns, m->nscount, &buf)) |
413 | 26 | return 1; |
414 | 834 | if (_rrparse(m, m->ar, m->arcount, &buf)) |
415 | 18 | return 1; |
416 | | |
417 | 816 | return 0; |
418 | 834 | } |
419 | | |
420 | | void message_qd(struct message *m, char *name, unsigned short int type, unsigned short int clazz) |
421 | 0 | { |
422 | 0 | m->qdcount++; |
423 | 0 | if (m->_buf == 0) |
424 | 0 | m->_buf = m->_packet + 12; |
425 | 0 | _host(m, &(m->_buf), name); |
426 | 0 | short2net(type, &(m->_buf)); |
427 | 0 | short2net(clazz, &(m->_buf)); |
428 | 0 | } |
429 | | |
430 | | static void _rrappend(struct message *m, char *name, unsigned short int type, unsigned short int clazz, unsigned long int ttl) |
431 | 0 | { |
432 | 0 | if (m->_buf == 0) |
433 | 0 | m->_buf = m->_packet + 12; |
434 | 0 | _host(m, &(m->_buf), name); |
435 | 0 | short2net(type, &(m->_buf)); |
436 | 0 | short2net(clazz, &(m->_buf)); |
437 | 0 | long2net(ttl, &(m->_buf)); |
438 | 0 | } |
439 | | |
440 | | void message_an(struct message *m, char *name, unsigned short int type, unsigned short int clazz, unsigned long int ttl) |
441 | 0 | { |
442 | 0 | m->ancount++; |
443 | 0 | _rrappend(m, name, type, clazz, ttl); |
444 | 0 | } |
445 | | |
446 | | void message_ns(struct message *m, char *name, unsigned short int type, unsigned short int clazz, unsigned long int ttl) |
447 | 0 | { |
448 | 0 | m->nscount++; |
449 | 0 | _rrappend(m, name, type, clazz, ttl); |
450 | 0 | } |
451 | | |
452 | | void message_ar(struct message *m, char *name, unsigned short int type, unsigned short int clazz, unsigned long int ttl) |
453 | 0 | { |
454 | 0 | m->arcount++; |
455 | 0 | _rrappend(m, name, type, clazz, ttl); |
456 | 0 | } |
457 | | |
458 | | void message_rdata_long(struct message *m, unsigned long l) |
459 | 0 | { |
460 | 0 | short2net(4, &(m->_buf)); |
461 | 0 | long2net(l, &(m->_buf)); |
462 | 0 | } |
463 | | |
464 | | void message_rdata_ipv4(struct message *m, struct in_addr a) |
465 | 0 | { |
466 | 0 | short2net(4, &(m->_buf)); |
467 | 0 | memcpy(m->_buf, &a.s_addr, 4); |
468 | 0 | m->_buf += 4; |
469 | 0 | } |
470 | | |
471 | | void message_rdata_ipv6(struct message *m, struct in6_addr a6) |
472 | 0 | { |
473 | 0 | short2net(16, &(m->_buf)); |
474 | 0 | memcpy(m->_buf, a6.s6_addr, 16); |
475 | 0 | m->_buf += 16; |
476 | 0 | } |
477 | | |
478 | | void message_rdata_name(struct message *m, char *name) |
479 | 0 | { |
480 | 0 | unsigned char *mybuf = m->_buf; |
481 | |
|
482 | 0 | m->_buf += 2; |
483 | 0 | short2net(_host(m, &(m->_buf), name), &mybuf); |
484 | 0 | } |
485 | | |
486 | | void message_rdata_srv(struct message *m, unsigned short int priority, unsigned short int weight, unsigned short int port, char *name) |
487 | 0 | { |
488 | 0 | unsigned char *mybuf = m->_buf; |
489 | |
|
490 | 0 | m->_buf += 2; |
491 | 0 | short2net(priority, &(m->_buf)); |
492 | 0 | short2net(weight, &(m->_buf)); |
493 | 0 | short2net(port, &(m->_buf)); |
494 | 0 | short2net(_host(m, &(m->_buf), name) + 6, &mybuf); |
495 | 0 | } |
496 | | |
497 | | void message_rdata_raw(struct message *m, unsigned char *rdata, unsigned short int rdlength) |
498 | 0 | { |
499 | 0 | if ((m->_buf - m->_packet) + rdlength > 4096) |
500 | 0 | rdlength = 0; |
501 | 0 | short2net(rdlength, &(m->_buf)); |
502 | 0 | memcpy(m->_buf, rdata, rdlength); |
503 | 0 | m->_buf += rdlength; |
504 | 0 | } |
505 | | |
506 | | unsigned char *message_packet(struct message *m) |
507 | 0 | { |
508 | 0 | unsigned char c, *buf = m->_buf; |
509 | |
|
510 | 0 | m->_buf = m->_packet; |
511 | 0 | short2net(m->id, &(m->_buf)); |
512 | |
|
513 | 0 | if (m->header.qr) |
514 | 0 | m->_buf[0] |= 0x80; |
515 | 0 | if ((c = m->header.opcode)) |
516 | 0 | m->_buf[0] |= (c << 3); |
517 | 0 | if (m->header.aa) |
518 | 0 | m->_buf[0] |= 0x04; |
519 | 0 | if (m->header.tc) |
520 | 0 | m->_buf[0] |= 0x02; |
521 | 0 | if (m->header.rd) |
522 | 0 | m->_buf[0] |= 0x01; |
523 | 0 | if (m->header.ra) |
524 | 0 | m->_buf[1] |= 0x80; |
525 | 0 | if ((c = m->header.z)) |
526 | 0 | m->_buf[1] |= (c << 4); |
527 | 0 | if (m->header.rcode) |
528 | 0 | m->_buf[1] |= m->header.rcode; |
529 | |
|
530 | 0 | m->_buf += 2; |
531 | 0 | short2net(m->qdcount, &(m->_buf)); |
532 | 0 | short2net(m->ancount, &(m->_buf)); |
533 | 0 | short2net(m->nscount, &(m->_buf)); |
534 | 0 | short2net(m->arcount, &(m->_buf)); |
535 | 0 | m->_buf = buf; /* Restore, so packet_len works */ |
536 | |
|
537 | 0 | return m->_packet; |
538 | 0 | } |
539 | | |
540 | | int message_packet_len(struct message *m) |
541 | 0 | { |
542 | 0 | if (m->_buf == 0) |
543 | 0 | return 12; |
544 | | |
545 | 0 | return (int)(m->_buf - m->_packet); |
546 | 0 | } |