/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-2026 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 | 2.27M | { |
38 | 2.27M | unsigned short int i; |
39 | | |
40 | 2.27M | i = **bufp; |
41 | 2.27M | i <<= 8; |
42 | 2.27M | i |= *(*bufp + 1); |
43 | 2.27M | *bufp += 2; |
44 | | |
45 | 2.27M | return i; |
46 | 2.27M | } |
47 | | |
48 | | unsigned long int net2long(unsigned char **bufp) |
49 | 320k | { |
50 | 320k | long int l; |
51 | | |
52 | 320k | l = **bufp; |
53 | 320k | l <<= 8; |
54 | 320k | l |= *(*bufp + 1); |
55 | 320k | l <<= 8; |
56 | 320k | l |= *(*bufp + 2); |
57 | 320k | l <<= 8; |
58 | 320k | l |= *(*bufp + 3); |
59 | 320k | *bufp += 4; |
60 | | |
61 | 320k | return l; |
62 | 320k | } |
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 | 20.1k | { |
86 | 20.1k | unsigned short int i; |
87 | | |
88 | 20.1k | i = 0xc0 ^ ptr[0]; |
89 | 20.1k | i <<= 8; |
90 | 20.1k | i |= (unsigned char)ptr[1]; |
91 | 20.1k | if (i >= 4096) |
92 | 17.6k | i = 4095; |
93 | | |
94 | 20.1k | return i; |
95 | 20.1k | } |
96 | | |
97 | | static int _label(struct message *m, unsigned char **bufp, char **namep) |
98 | 978k | { |
99 | 978k | int x; |
100 | 978k | char *label, *name; |
101 | | |
102 | | |
103 | | /* Sanity check */ |
104 | 978k | if (m->_len >= (int)sizeof(m->_packet)) |
105 | 221 | return 1; |
106 | | |
107 | | /* Set namep to the end of the block */ |
108 | 977k | *namep = name = (char *)m->_packet + m->_len; |
109 | | |
110 | | /* Loop storing label in the block */ |
111 | 1.09M | 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 | 113k | int prevOffset = -1; |
114 | 127k | while (*label & 0xc0) { |
115 | 20.1k | unsigned short int offset = _ldecomp(label); |
116 | 20.1k | if (offset <= prevOffset || offset > m->_len) |
117 | 43 | return 1; |
118 | 20.0k | if (*(label = (char *)m->_buf + offset) == 0) |
119 | 6.20k | break; |
120 | 13.8k | prevOffset = offset; |
121 | 13.8k | } |
122 | | |
123 | | /* Make sure we're not over the limits, and that the source |
124 | | * label stays within the packet buffer */ |
125 | 113k | if ((name + *label) - *namep > 255 || m->_len + ((name + *label) - *namep) >= MAX_PACKET_LEN || |
126 | 113k | (label + 1 + *label) - (char *)m->_buf > MAX_PACKET_LEN) |
127 | 22 | return 1; |
128 | | |
129 | | /* Copy chars for this label */ |
130 | 113k | memcpy(name, label + 1, (size_t)*label); |
131 | 113k | name[(size_t)*label] = '.'; |
132 | 113k | } |
133 | | |
134 | | /* Advance buffer */ |
135 | 1.05M | for (label = (char *)*bufp; *label != 0 && !(*label & 0xc0 && label++); label += *label + 1) |
136 | 75.3k | ; |
137 | 977k | *bufp = (unsigned char *)(label + 1); |
138 | | |
139 | | /* Terminate name and check for cache or cache it */ |
140 | 977k | *name = '\0'; |
141 | 4.66M | for (x = 0; x < MAX_NUM_LABELS && m->_labels[x]; x++) { |
142 | 4.65M | if (strcmp(*namep, m->_labels[x])) |
143 | 3.69M | continue; |
144 | | |
145 | 966k | *namep = m->_labels[x]; |
146 | 966k | return 0; |
147 | 4.65M | } |
148 | | |
149 | | /* No cache, so cache it if room */ |
150 | 11.4k | if (x < MAX_NUM_LABELS && m->_labels[x] == 0) |
151 | 11.2k | m->_labels[x] = *namep; |
152 | 11.4k | m->_len += (int)(name - *namep) + 1; |
153 | | |
154 | 11.4k | return 0; |
155 | 977k | } |
156 | | |
157 | | /* Internal label matching */ |
158 | | static int _lmatch(const struct message *m, const char *l1, const char *l2) |
159 | 0 | { |
160 | 0 | int len; |
161 | | |
162 | | /* Always ensure we get called w/o a pointer */ |
163 | 0 | if (*l1 & 0xc0) |
164 | 0 | return _lmatch(m, (char *)m->_buf + _ldecomp(l1), l2); |
165 | 0 | if (*l2 & 0xc0) |
166 | 0 | return _lmatch(m, l1, (char *)m->_buf + _ldecomp(l2)); |
167 | | |
168 | | /* Same already? */ |
169 | 0 | if (l1 == l2) |
170 | 0 | return 1; |
171 | | |
172 | | /* Compare all label characters */ |
173 | 0 | if (*l1 != *l2) |
174 | 0 | return 0; |
175 | | |
176 | | /* Both at the root label, names matched; stop before stepping |
177 | | * past it, or the checks below read out of bounds (issue #37) */ |
178 | 0 | if (*l1 == 0) |
179 | 0 | return 1; |
180 | | |
181 | 0 | for (len = 1; len <= *l1; len++) { |
182 | 0 | if (l1[len] != l2[len]) |
183 | 0 | return 0; |
184 | 0 | } |
185 | | |
186 | | /* Get new_ labels */ |
187 | 0 | l1 += *l1 + 1; |
188 | 0 | l2 += *l2 + 1; |
189 | | |
190 | | /* At the end, all matched */ |
191 | 0 | if (*l1 == 0 && *l2 == 0) |
192 | 0 | return 1; |
193 | | |
194 | | /* Try next labels */ |
195 | 0 | return _lmatch(m, l1, l2); |
196 | 0 | } |
197 | | |
198 | | /* Nasty, convert host into label using compression */ |
199 | | static int _host(struct message *m, unsigned char **bufp, const char *name) |
200 | 0 | { |
201 | 0 | char label[256], *l; |
202 | 0 | int len = 0, x = 1, y = 0, last = 0; |
203 | |
|
204 | 0 | if (name == 0) |
205 | 0 | return 0; |
206 | | |
207 | | /* Make our label */ |
208 | 0 | while (name[y]) { |
209 | 0 | if (name[y] == '.') { |
210 | 0 | if (!name[y + 1]) |
211 | 0 | break; |
212 | 0 | label[last] = (char)(x - (last + 1)); |
213 | 0 | last = x; |
214 | 0 | } else { |
215 | 0 | label[x] = name[y]; |
216 | 0 | } |
217 | | |
218 | 0 | if (x++ == 255) |
219 | 0 | return 0; |
220 | | |
221 | 0 | y++; |
222 | 0 | } |
223 | | |
224 | 0 | label[last] = (char)(x - (last + 1)); |
225 | 0 | if (x == 1) |
226 | 0 | x--; /* Special case, bad names, but handle correctly */ |
227 | 0 | len = x + 1; |
228 | 0 | label[x] = 0; /* Always terminate w/ a 0 */ |
229 | | |
230 | | /* Double-loop checking each label against all m->_labels for match */ |
231 | 0 | for (x = 0; label[x]; x += label[x] + 1) { |
232 | 0 | for (y = 0; y < MAX_NUM_LABELS && m->_labels[y]; y++) { |
233 | 0 | if (_lmatch(m, label + x, m->_labels[y])) { |
234 | | /* Matching label, set up pointer */ |
235 | 0 | l = label + x; |
236 | 0 | short2net((unsigned char *)m->_labels[y] - m->_packet, (unsigned char **)&l); |
237 | 0 | label[x] |= '\xc0'; |
238 | 0 | len = x + 2; |
239 | 0 | break; |
240 | 0 | } |
241 | 0 | } |
242 | | |
243 | 0 | if (label[x] & 0xc0) |
244 | 0 | break; |
245 | 0 | } |
246 | | |
247 | | /* Copy into buffer, point there now */ |
248 | 0 | memcpy(*bufp, label, len); |
249 | 0 | l = (char *)*bufp; |
250 | 0 | *bufp += len; |
251 | | |
252 | | /* For each new_ label, store it's location for future compression */ |
253 | 0 | for (x = 0; l[x] && m->_label < MAX_NUM_LABELS; x += l[x] + 1) { |
254 | 0 | if (l[x] & 0xc0) |
255 | 0 | break; |
256 | | |
257 | 0 | m->_labels[m->_label++] = l + x; |
258 | 0 | } |
259 | |
|
260 | 0 | return len; |
261 | 0 | } |
262 | | |
263 | | static int _rrparse(struct message *m, struct resource *rr, int count, unsigned char **bufp) |
264 | 2.72k | { |
265 | 2.72k | int i; |
266 | | |
267 | 322k | for (i = 0; i < count; i++) { |
268 | 320k | if (_label(m, bufp, &(rr[i].name))) |
269 | 233 | return 1; |
270 | 320k | rr[i].type = net2short(bufp); |
271 | 320k | rr[i].clazz = net2short(bufp); |
272 | 320k | rr[i].ttl = net2long(bufp); |
273 | 320k | rr[i].rdlength = net2short(bufp); |
274 | | // 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); |
275 | | |
276 | | /* If not going to overflow, make copy of source rdata */ |
277 | 320k | if (rr[i].rdlength + (*bufp - m->_buf) > MAX_PACKET_LEN || m->_len + rr[i].rdlength > MAX_PACKET_LEN) { |
278 | 36 | rr[i].rdlength = 0; |
279 | 36 | return 1; |
280 | 36 | } |
281 | | |
282 | | /* For the following records the rdata will be parsed later. So don't set it here: |
283 | | * NS, CNAME, PTR, DNAME, SOA, MX, AFSDB, RT, KX, RP, PX, SRV, NSEC |
284 | | * See 18.14 of https://tools.ietf.org/html/rfc6762#page-47 */ |
285 | 320k | if (rr[i].type == QTYPE_NS || rr[i].type == QTYPE_CNAME || rr[i].type == QTYPE_PTR || rr[i].type == QTYPE_SRV) { |
286 | 1.56k | rr[i].rdlength = 0; |
287 | 318k | } else { |
288 | 318k | rr[i].rdata = m->_packet + m->_len; |
289 | 318k | m->_len += rr[i].rdlength; |
290 | 318k | memcpy(rr[i].rdata, *bufp, rr[i].rdlength); |
291 | 318k | } |
292 | | |
293 | | |
294 | | /* Parse commonly known ones */ |
295 | 320k | switch (rr[i].type) { |
296 | 522 | case QTYPE_A: |
297 | 522 | if (m->_len + INET_ADDRSTRLEN > MAX_PACKET_LEN) |
298 | 2 | return 1; |
299 | 520 | rr[i].known.a.name = (char *)m->_packet + m->_len; |
300 | 520 | m->_len += INET_ADDRSTRLEN; |
301 | 520 | inet_ntop(AF_INET, *bufp, rr[i].known.a.name, INET_ADDRSTRLEN); |
302 | 520 | memcpy(&(rr[i].known.a.ip.s_addr), *bufp, sizeof(rr[i].known.a.ip.s_addr)); |
303 | 520 | *bufp += sizeof(rr[i].known.a.ip.s_addr); |
304 | 520 | break; |
305 | | |
306 | 317 | case QTYPE_AAAA: |
307 | 317 | if (m->_len + INET6_ADDRSTRLEN > MAX_PACKET_LEN) |
308 | 2 | return 1; |
309 | 315 | rr[i].known.aaaa.name = (char *)m->_packet + m->_len; |
310 | 315 | m->_len += INET6_ADDRSTRLEN; |
311 | 315 | inet_ntop(AF_INET6, *bufp, rr[i].known.aaaa.name, INET6_ADDRSTRLEN); |
312 | 315 | memcpy(rr[i].known.aaaa.ip6.s6_addr, *bufp, sizeof(rr[i].known.aaaa.ip6.s6_addr)); |
313 | 315 | *bufp += sizeof(rr[i].known.aaaa.ip6.s6_addr); |
314 | 315 | break; |
315 | | |
316 | 396 | case QTYPE_NS: |
317 | 396 | if (_label(m, bufp, &(rr[i].known.ns.name))) |
318 | 2 | return 1; |
319 | 394 | break; |
320 | | |
321 | 493 | case QTYPE_CNAME: |
322 | 493 | if (_label(m, bufp, &(rr[i].known.cname.name))) |
323 | 3 | return 1; |
324 | 490 | break; |
325 | | |
326 | 490 | case QTYPE_PTR: |
327 | 405 | if (_label(m, bufp, &(rr[i].known.ptr.name))) |
328 | 2 | return 1; |
329 | 403 | break; |
330 | | |
331 | 403 | case QTYPE_SRV: |
332 | 269 | rr[i].known.srv.priority = net2short(bufp); |
333 | 269 | rr[i].known.srv.weight = net2short(bufp); |
334 | 269 | rr[i].known.srv.port = net2short(bufp); |
335 | 269 | if (_label(m, bufp, &(rr[i].known.srv.name))) |
336 | 2 | return 1; |
337 | 267 | break; |
338 | | |
339 | 267 | case QTYPE_TXT: |
340 | 317k | default: |
341 | 317k | *bufp += rr[i].rdlength; |
342 | 320k | } |
343 | 320k | } |
344 | | |
345 | 2.44k | return 0; |
346 | 2.72k | } |
347 | | |
348 | | /* Keep all our mem in one (aligned) block for easy freeing */ |
349 | | #define my(x,y) \ |
350 | 7.28k | while (m->_len & 7) \ |
351 | 4.34k | m->_len++; \ |
352 | 4.34k | (x) = (void *)(m->_packet + m->_len); \ |
353 | 4.34k | m->_len += (y); |
354 | | |
355 | | int message_parse(struct message *m, unsigned char *packet) |
356 | 1.18k | { |
357 | 1.18k | int i; |
358 | 1.18k | unsigned char *buf; |
359 | | |
360 | 1.18k | if (packet == 0 || m == 0) |
361 | 0 | return 1; |
362 | | |
363 | | /* Header stuff bit crap */ |
364 | 1.18k | m->_buf = buf = packet; |
365 | 1.18k | m->id = net2short(&buf); |
366 | 1.18k | if (buf[0] & 0x80) |
367 | 485 | m->header.qr = 1; |
368 | 1.18k | m->header.opcode = (buf[0] & 0x78) >> 3; |
369 | 1.18k | if (buf[0] & 0x04) |
370 | 413 | m->header.aa = 1; |
371 | 1.18k | if (buf[0] & 0x02) |
372 | 434 | m->header.tc = 1; |
373 | 1.18k | if (buf[0] & 0x01) |
374 | 683 | m->header.rd = 1; |
375 | 1.18k | if (buf[1] & 0x80) |
376 | 253 | m->header.ra = 1; |
377 | 1.18k | m->header.z = (buf[1] & 0x70) >> 4; |
378 | 1.18k | m->header.rcode = buf[1] & 0x0F; |
379 | 1.18k | buf += 2; |
380 | | |
381 | 1.18k | m->qdcount = net2short(&buf); |
382 | 1.18k | if (m->_len + (sizeof(struct question) * m->qdcount) > MAX_PACKET_LEN - 8) { |
383 | 10 | m->qdcount = 0; |
384 | 10 | return 1; |
385 | 10 | } |
386 | | |
387 | 1.17k | m->ancount = net2short(&buf); |
388 | 1.17k | if (m->_len + (sizeof(struct resource) * m->ancount) > MAX_PACKET_LEN - 8) { |
389 | 19 | m->ancount = 0; |
390 | 19 | return 1; |
391 | 19 | } |
392 | | |
393 | 1.15k | m->nscount = net2short(&buf); |
394 | 1.15k | if (m->_len + (sizeof(struct resource) * m->nscount) > MAX_PACKET_LEN - 8) { |
395 | 13 | m->nscount = 0; |
396 | 13 | return 1; |
397 | 13 | } |
398 | | |
399 | 1.14k | m->arcount = net2short(&buf); |
400 | 1.14k | if (m->_len + (sizeof(struct resource) * m->arcount) > MAX_PACKET_LEN - 8) { |
401 | 21 | m->arcount = 0; |
402 | 21 | return 1; |
403 | 21 | } |
404 | | |
405 | | /* Process questions */ |
406 | 1.12k | my(m->qd, sizeof(struct question) * m->qdcount); |
407 | 657k | for (i = 0; i < m->qdcount; i++) { |
408 | 656k | if (_label(m, &buf, &(m->qd[i].name))) |
409 | 44 | return 1; |
410 | 655k | m->qd[i].type = net2short(&buf); |
411 | 655k | m->qd[i].clazz = net2short(&buf); |
412 | 655k | } |
413 | | |
414 | | /* Process rrs */ |
415 | 1.07k | my(m->an, sizeof(struct resource) * m->ancount); |
416 | 1.07k | my(m->ns, sizeof(struct resource) * m->nscount); |
417 | 1.07k | my(m->ar, sizeof(struct resource) * m->arcount); |
418 | 1.07k | if (_rrparse(m, m->an, m->ancount, &buf)) |
419 | 230 | return 1; |
420 | 846 | if (_rrparse(m, m->ns, m->nscount, &buf)) |
421 | 44 | return 1; |
422 | 802 | if (_rrparse(m, m->ar, m->arcount, &buf)) |
423 | 8 | return 1; |
424 | | |
425 | 794 | return 0; |
426 | 802 | } |
427 | | |
428 | | void message_qd(struct message *m, char *name, unsigned short int type, unsigned short int clazz) |
429 | 0 | { |
430 | 0 | m->qdcount++; |
431 | 0 | if (m->_buf == 0) |
432 | 0 | m->_buf = m->_packet + 12; |
433 | 0 | _host(m, &(m->_buf), name); |
434 | 0 | short2net(type, &(m->_buf)); |
435 | 0 | short2net(clazz, &(m->_buf)); |
436 | 0 | } |
437 | | |
438 | | static void _rrappend(struct message *m, char *name, unsigned short int type, unsigned short int clazz, unsigned long int ttl) |
439 | 0 | { |
440 | 0 | if (m->_buf == 0) |
441 | 0 | m->_buf = m->_packet + 12; |
442 | 0 | _host(m, &(m->_buf), name); |
443 | 0 | short2net(type, &(m->_buf)); |
444 | 0 | short2net(clazz, &(m->_buf)); |
445 | 0 | long2net(ttl, &(m->_buf)); |
446 | 0 | } |
447 | | |
448 | | void message_an(struct message *m, char *name, unsigned short int type, unsigned short int clazz, unsigned long int ttl) |
449 | 0 | { |
450 | 0 | m->ancount++; |
451 | 0 | _rrappend(m, name, type, clazz, ttl); |
452 | 0 | } |
453 | | |
454 | | void message_ns(struct message *m, char *name, unsigned short int type, unsigned short int clazz, unsigned long int ttl) |
455 | 0 | { |
456 | 0 | m->nscount++; |
457 | 0 | _rrappend(m, name, type, clazz, ttl); |
458 | 0 | } |
459 | | |
460 | | void message_ar(struct message *m, char *name, unsigned short int type, unsigned short int clazz, unsigned long int ttl) |
461 | 0 | { |
462 | 0 | m->arcount++; |
463 | 0 | _rrappend(m, name, type, clazz, ttl); |
464 | 0 | } |
465 | | |
466 | | void message_rdata_long(struct message *m, unsigned long l) |
467 | 0 | { |
468 | 0 | short2net(4, &(m->_buf)); |
469 | 0 | long2net(l, &(m->_buf)); |
470 | 0 | } |
471 | | |
472 | | void message_rdata_ipv4(struct message *m, struct in_addr a) |
473 | 0 | { |
474 | 0 | short2net(4, &(m->_buf)); |
475 | 0 | memcpy(m->_buf, &a.s_addr, 4); |
476 | 0 | m->_buf += 4; |
477 | 0 | } |
478 | | |
479 | | void message_rdata_ipv6(struct message *m, struct in6_addr a6) |
480 | 0 | { |
481 | 0 | short2net(16, &(m->_buf)); |
482 | 0 | memcpy(m->_buf, a6.s6_addr, 16); |
483 | 0 | m->_buf += 16; |
484 | 0 | } |
485 | | |
486 | | void message_rdata_name(struct message *m, char *name) |
487 | 0 | { |
488 | 0 | unsigned char *mybuf = m->_buf; |
489 | |
|
490 | 0 | m->_buf += 2; |
491 | 0 | short2net(_host(m, &(m->_buf), name), &mybuf); |
492 | 0 | } |
493 | | |
494 | | void message_rdata_srv(struct message *m, unsigned short int priority, unsigned short int weight, unsigned short int port, char *name) |
495 | 0 | { |
496 | 0 | unsigned char *mybuf = m->_buf; |
497 | |
|
498 | 0 | m->_buf += 2; |
499 | 0 | short2net(priority, &(m->_buf)); |
500 | 0 | short2net(weight, &(m->_buf)); |
501 | 0 | short2net(port, &(m->_buf)); |
502 | 0 | short2net(_host(m, &(m->_buf), name) + 6, &mybuf); |
503 | 0 | } |
504 | | |
505 | | void message_rdata_raw(struct message *m, unsigned char *rdata, unsigned short int rdlength) |
506 | 0 | { |
507 | 0 | if ((m->_buf - m->_packet) + rdlength > 4096) |
508 | 0 | rdlength = 0; |
509 | 0 | short2net(rdlength, &(m->_buf)); |
510 | 0 | memcpy(m->_buf, rdata, rdlength); |
511 | 0 | m->_buf += rdlength; |
512 | 0 | } |
513 | | |
514 | | unsigned char *message_packet(struct message *m) |
515 | 0 | { |
516 | 0 | unsigned char c, *buf = m->_buf; |
517 | |
|
518 | 0 | m->_buf = m->_packet; |
519 | 0 | short2net(m->id, &(m->_buf)); |
520 | |
|
521 | 0 | if (m->header.qr) |
522 | 0 | m->_buf[0] |= 0x80; |
523 | 0 | if ((c = m->header.opcode)) |
524 | 0 | m->_buf[0] |= (c << 3); |
525 | 0 | if (m->header.aa) |
526 | 0 | m->_buf[0] |= 0x04; |
527 | 0 | if (m->header.tc) |
528 | 0 | m->_buf[0] |= 0x02; |
529 | 0 | if (m->header.rd) |
530 | 0 | m->_buf[0] |= 0x01; |
531 | 0 | if (m->header.ra) |
532 | 0 | m->_buf[1] |= 0x80; |
533 | 0 | if ((c = m->header.z)) |
534 | 0 | m->_buf[1] |= (c << 4); |
535 | 0 | if (m->header.rcode) |
536 | 0 | m->_buf[1] |= m->header.rcode; |
537 | |
|
538 | 0 | m->_buf += 2; |
539 | 0 | short2net(m->qdcount, &(m->_buf)); |
540 | 0 | short2net(m->ancount, &(m->_buf)); |
541 | 0 | short2net(m->nscount, &(m->_buf)); |
542 | 0 | short2net(m->arcount, &(m->_buf)); |
543 | 0 | m->_buf = buf; /* Restore, so packet_len works */ |
544 | |
|
545 | 0 | return m->_packet; |
546 | 0 | } |
547 | | |
548 | | int message_packet_len(struct message *m) |
549 | 0 | { |
550 | 0 | if (m->_buf == 0) |
551 | 0 | return 12; |
552 | | |
553 | 0 | return (int)(m->_buf - m->_packet); |
554 | 0 | } |