Coverage Report

Created: 2025-07-23 06:46

/src/open62541/deps/mdnsd/libmdnsd/1035.c
Line
Count
Source (jump to first uncovered line)
1
#include "1035.h"
2
#include <string.h>
3
#include <stdio.h>
4
5
#if defined(_MSC_VER) && _MSC_VER < 1900
6
7
__inline int msnds_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
8
{
9
    int count = -1;
10
11
    if (size != 0)
12
        count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
13
    if (count == -1)
14
        count = _vscprintf(format, ap);
15
16
    return count;
17
}
18
19
__inline int msnds_snprintf(char *outBuf, size_t size, const char *format, ...)
20
{
21
    int count;
22
    va_list ap;
23
24
    va_start(ap, format);
25
    count = msnds_vsnprintf(outBuf, size, format, ap);
26
    va_end(ap);
27
28
    return count;
29
}
30
31
#else
32
33
403
#define msnds_snprintf snprintf
34
35
#endif
36
37
uint16_t net2short(const unsigned char **bufp)
38
41.6k
{
39
41.6k
  unsigned short int i;
40
41.6k
  memcpy(&i, *bufp, sizeof(short int));
41
41.6k
  *bufp += 2;
42
41.6k
  return ntohs(i);
43
41.6k
}
44
45
uint32_t net2long(const unsigned char **bufp)
46
7.69k
{
47
7.69k
  uint32_t l;
48
49
7.69k
    memcpy(&l, *bufp, sizeof(uint32_t));
50
7.69k
  *bufp += 4;
51
52
7.69k
  return ntohl(l);
53
7.69k
}
54
55
void short2net(uint16_t i, unsigned char **bufp)
56
0
{
57
0
    uint16_t x = htons(i);
58
0
    memcpy(*bufp, &x, sizeof(uint16_t));
59
0
  *bufp += 2;
60
0
}
61
62
void long2net(uint32_t l, unsigned char **bufp)
63
0
{
64
0
    uint32_t x = htonl(l);
65
0
    memcpy(*bufp, &x, sizeof(uint32_t));
66
0
  *bufp += 4;
67
0
}
68
69
static unsigned short int _ldecomp(const unsigned char *ptr)
70
2.41k
{
71
2.41k
  unsigned short int i;
72
73
2.41k
  i = (unsigned short int)(0xc0 ^ ptr[0]);
74
2.41k
  i = (unsigned short int)(i<<8);
75
2.41k
  i = (unsigned short int)(i | ptr[1]);
76
77
2.41k
  return i;
78
2.41k
}
79
80
static bool _label(struct message *m, const unsigned char **bufp, const unsigned char *bufEnd, char **namep)
81
13.9k
{
82
13.9k
  int x;
83
13.9k
  const unsigned char *label;
84
13.9k
  char *name;
85
86
  /* Set namep to the end of the block */
87
13.9k
  *namep = name = (char *)m->_packet + m->_len;
88
89
13.9k
  if (*bufp >= bufEnd)
90
47
      return false;
91
92
    // forward buffer pointer until we find the first compressed label
93
13.9k
    bool moveBufp = true;
94
  /* Loop storing label in the block */
95
33.8k
  do {
96
33.8k
      if (moveBufp) {
97
16.8k
            label = *bufp;
98
16.8k
      }
99
100
33.8k
        if (label >= bufEnd) {
101
604
            break;
102
604
        }
103
104
        /* Since every domain name ends with the null label of
105
            the root, a domain name is terminated by a length byte of zero. */
106
33.2k
        if (*label == 0) {
107
13.1k
            if (moveBufp) {
108
11.8k
                *bufp += 1;
109
11.8k
            }
110
13.1k
            break;
111
13.1k
        }
112
113
114
    /* Skip past any compression pointers, kick out if end encountered (bad data prolly) */
115
116
    /* If a label is compressed, it has following structure of 2 bytes:
117
     *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
118
       *    | 1  1|                OFFSET                   |
119
     *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
120
     *
121
     * The OFFSET field specifies an offset from
122
     * the start of the message (i.e., the first octet of the ID field in the
123
     * domain header).  A zero offset specifies the first byte of the ID field,
124
     * etc.
125
     **/
126
20.1k
    if (*label & 0xc0) {
127
2.41k
        if (label + 2 > bufEnd)
128
9
            return false;
129
2.41k
            unsigned short int offset = _ldecomp(label);
130
2.41k
            if (offset > m->_len)
131
22
                return false;
132
2.38k
            if (m->_buf + offset >= bufEnd)
133
10
                return false;
134
2.37k
            label = m->_buf + offset;
135
            // chek if label is again pointer, then abort.
136
2.37k
            if (*label & 0xc0)
137
5
                return false;
138
2.37k
            moveBufp = false;
139
2.37k
            *bufp += 2;
140
2.37k
    }
141
142
143
    /* Make sure we're not over the limits
144
     * See https://tools.ietf.org/html/rfc1035
145
     * 2.3.4. Size limits
146
     * */
147
20.0k
    const unsigned char labelLen = (unsigned char)*label;
148
20.0k
    if (labelLen > 63)
149
        // maximum label length is 63 octets
150
0
        return false;
151
20.0k
    if ((name + labelLen) - *namep > 255)
152
            // maximum names length is 255 octets
153
3
        return false;
154
155
20.0k
    if (label + 1 + labelLen > bufEnd) {
156
14
            return false;
157
14
        }
158
20.0k
        if ((unsigned char*)name + labelLen > m->_packet + MAX_PACKET_LEN) {
159
1
            return false;
160
1
        }
161
    /* Copy chars for this label */
162
20.0k
    memcpy(name, label + 1, labelLen);
163
20.0k
    name[labelLen] = '.';
164
165
20.0k
        name += labelLen + 1;
166
167
20.0k
        if (moveBufp) {
168
2.94k
            *bufp += labelLen + 1;
169
2.94k
        }
170
17.0k
        else {
171
17.0k
            label += labelLen +1;
172
17.0k
        }
173
174
20.0k
  } while (*bufp <= bufEnd);
175
176
13.8k
    if ((unsigned char*)name >= m->_packet + MAX_PACKET_LEN) {
177
4
        return false;
178
4
    }
179
180
  /* Terminate name and check for cache or cache it */
181
13.8k
  *name = '\0';
182
23.6k
  for (x = 0; x < MAX_NUM_LABELS && m->_labels[x]; x++) {
183
20.5k
    if (strcmp(*namep, m->_labels[x]))
184
9.82k
      continue;
185
186
10.7k
    *namep = m->_labels[x];
187
10.7k
    return true;
188
20.5k
  }
189
190
  /* No cache, so cache it if room */
191
3.12k
  if (x < MAX_NUM_LABELS && m->_labels[x] == 0) {
192
2.89k
        m->_labels[x] = *namep;
193
2.89k
    }
194
3.12k
    m->_len += (unsigned long)((name - *namep) + 1);
195
196
3.12k
  return true;
197
13.8k
}
198
199
/* Internal label matching */
200
static int _lmatch(struct message *m, const char *l1, const char *l2)
201
0
{
202
0
  int len;
203
204
  /* Always ensure we get called w/o a pointer */
205
0
  if (*l1 & 0xc0)
206
0
    return _lmatch(m, (char*)m->_buf + _ldecomp((const unsigned char*)l1), l2);
207
0
  if (*l2 & 0xc0)
208
0
    return _lmatch(m, l1, (char*)m->_buf + _ldecomp((const unsigned char*) l2));
209
210
  /* Same already? */
211
0
  if (l1 == l2)
212
0
    return 1;
213
214
  /* Compare all label characters */
215
0
  if (*l1 != *l2)
216
0
    return 0;
217
0
  for (len = 1; len <= *l1; len++) {
218
0
    if (l1[len] != l2[len])
219
0
      return 0;
220
0
  }
221
222
  /* Get new labels */
223
0
  l1 += *l1 + 1;
224
0
  l2 += *l2 + 1;
225
226
  /* At the end, all matched */
227
0
  if (*l1 == 0 && *l2 == 0)
228
0
    return 1;
229
230
  /* Try next labels */
231
0
  return _lmatch(m, l1, l2);
232
0
}
233
234
/* Nasty, convert host into label using compression */
235
static int _host(struct message *m, unsigned char **bufp, char *name)
236
0
{
237
0
  char label[256], *l;
238
0
  int len = 0, x = 1, y = 0, last = 0;
239
240
0
  if (name == 0)
241
0
    return 0;
242
243
  /* Make our label */
244
0
  while (name[y]) {
245
0
    if (name[y] == '.') {
246
0
      if (!name[y + 1])
247
0
        break;
248
0
      label[last] = (char)(x - (last + 1));
249
0
      last = x;
250
0
    } else {
251
0
      label[x] = name[y];
252
0
    }
253
254
0
    if (x++ == 255)
255
0
      return 0;
256
257
0
    y++;
258
0
  }
259
260
0
  label[last] = (char)(x - (last + 1));
261
0
  if (x == 1)
262
0
    x--;   /* Special case, bad names, but handle correctly */
263
0
  len = x + 1;
264
0
  label[x] = 0;   /* Always terminate w/ a 0 */
265
266
  /* Double-loop checking each label against all m->_labels for match */
267
0
  for (x = 0; label[x]; x += label[x] + 1) {
268
0
    for (y = 0; y < MAX_NUM_LABELS && m->_labels[y]; y++) {
269
0
      if (_lmatch(m, label + x, m->_labels[y])) {
270
        /* Matching label, set up pointer */
271
0
        l = label + x;
272
0
        short2net((unsigned short)((unsigned char *)m->_labels[y] - m->_packet), (unsigned char **)&l);
273
0
        label[x] = (char)(label[x] | 0xc0);
274
0
        len = x + 2;
275
0
        break;
276
0
      }
277
0
    }
278
  
279
0
    if (label[x] & 0xc0)
280
0
      break;
281
0
  }
282
283
  /* Copy into buffer, point there now */
284
0
  memcpy(*bufp, label, (size_t)len);
285
0
  l = (char *)*bufp;
286
0
  *bufp += len;
287
288
  /* For each new label, store it's location for future compression */
289
0
  for (x = 0; l[x] && m->_label < MAX_NUM_LABELS; x += l[x] + 1) {
290
0
    if (l[x] & 0xc0)
291
0
      break;
292
293
0
    m->_labels[m->_label++] = l + x;
294
0
  }
295
296
0
  return len;
297
0
}
298
299
static bool _rrparse(struct message *m, struct resource *rr, int count, const unsigned char **bufp, const unsigned char* bufferEnd)
300
3.76k
{
301
3.76k
  int i;
302
3.76k
    const unsigned char *addr_bytes = NULL;
303
304
3.76k
    if (count == 0) {
305
2.46k
        return true;
306
2.46k
    }
307
308
1.29k
    if (*bufp >= m->_bufEnd) {
309
14
        return false;
310
14
    }
311
312
8.90k
  for (i = 0; i < count; i++) {
313
7.77k
      if (*bufp >= bufferEnd) {
314
32
            return false;
315
32
        }
316
317
7.73k
    if (!_label(m, bufp, bufferEnd, &(rr[i].name))) {
318
25
            return false;
319
25
        }
320
7.71k
    if (*bufp + 10 > bufferEnd) {
321
17
            return false;
322
17
        }
323
7.69k
    rr[i].type     = net2short(bufp);
324
7.69k
    rr[i].clazz    = net2short(bufp);
325
7.69k
    rr[i].ttl      = net2long(bufp);
326
7.69k
    rr[i].rdlength = net2short(bufp);
327
//    fprintf(stderr, "Record type %d class 0x%2x ttl %lu len %d\n", rr[i].type, rr[i].clazz, rr[i].ttl, rr[i].rdlength);
328
329
    /* For the following records the rdata will be parsed later. So don't set it here:
330
     * NS, CNAME, PTR, DNAME, SOA, MX, AFSDB, RT, KX, RP, PX, SRV, NSEC
331
     * See 18.14 of https://tools.ietf.org/html/rfc6762#page-47 */
332
7.69k
    if (rr[i].type == QTYPE_NS || rr[i].type == QTYPE_CNAME || rr[i].type == QTYPE_PTR || rr[i].type == QTYPE_SRV) {
333
3.34k
      rr[i].rdlength = 0;
334
4.35k
    } else {
335
            /* If not going to overflow, make copy of source rdata */
336
4.35k
            if (*bufp + rr[i].rdlength > bufferEnd) {
337
19
                return false;
338
19
            }
339
340
4.33k
            if (m->_len + rr[i].rdlength > MAX_PACKET_LEN) {
341
2
                return false;
342
2
            }
343
4.33k
      rr[i].rdata = m->_packet + m->_len;
344
4.33k
      m->_len += rr[i].rdlength;
345
4.33k
      memcpy(rr[i].rdata, *bufp, rr[i].rdlength);
346
4.33k
    }
347
348
349
    /* Parse commonly known ones */
350
7.67k
    switch (rr[i].type) {
351
421
    case QTYPE_A:
352
421
      if (m->_len + 16 > MAX_PACKET_LEN) {
353
6
                return false;
354
6
            }
355
415
      rr[i].known.a.name = (char *)m->_packet + m->_len;
356
415
      m->_len += 16;
357
415
            if (*bufp + 4 > bufferEnd) {
358
12
                return false;
359
12
            }
360
403
      msnds_snprintf(rr[i].known.a.name,16, "%d.%d.%d.%d", (*bufp)[0], (*bufp)[1], (*bufp)[2], (*bufp)[3]);
361
403
      addr_bytes = (const unsigned char *) *bufp;
362
403
      rr[i].known.a.ip.s_addr = (in_addr_t) (
363
403
          ((in_addr_t) addr_bytes[0]) |
364
403
          (((in_addr_t) addr_bytes[1]) << 8) |
365
403
          (((in_addr_t) addr_bytes[2]) << 16) |
366
403
          (((in_addr_t) addr_bytes[3]) << 24));
367
403
            *bufp += 4;
368
403
      break;
369
370
230
    case QTYPE_AAAA:
371
230
      if (m->_len + INET6_ADDRSTRLEN > MAX_PACKET_LEN) {
372
6
        return false;
373
6
      }
374
224
      rr[i].known.aaaa.name = (char *)m->_packet + m->_len;
375
224
      m->_len += INET6_ADDRSTRLEN;
376
224
      if (*bufp + rr->rdlength > bufferEnd) {
377
8
        return false;
378
8
      }
379
216
      addr_bytes = (const unsigned char *)*bufp;
380
216
      inet_ntop(AF_INET6,addr_bytes,rr[i].known.aaaa.name,INET6_ADDRSTRLEN);
381
2.95k
      for (size_t j = 0; j < rr->rdlength; j++) {
382
2.74k
        rr[i].known.aaaa.ip6.s6_addr[j] = addr_bytes[j];
383
2.74k
      }
384
216
      *bufp += rr->rdlength;
385
216
      break;
386
387
341
    case QTYPE_NS:
388
341
      if (!_label(m, bufp, bufferEnd, &(rr[i].known.ns.name))) {
389
7
                return false;
390
7
            }
391
334
      break;
392
393
750
    case QTYPE_CNAME:
394
750
      if (!_label(m, bufp, bufferEnd, &(rr[i].known.cname.name))) {
395
5
                return false;
396
5
            }
397
745
      break;
398
399
745
    case QTYPE_PTR:
400
579
      if (!_label(m, bufp, bufferEnd, &(rr[i].known.ptr.name))) {
401
7
                return false;
402
7
            }
403
572
      break;
404
405
1.67k
    case QTYPE_SRV:
406
1.67k
            if (*bufp + 6 > bufferEnd) {
407
6
                return false;
408
6
            }
409
1.66k
      rr[i].known.srv.priority = net2short(bufp);
410
1.66k
      rr[i].known.srv.weight = net2short(bufp);
411
1.66k
      rr[i].known.srv.port = net2short(bufp);
412
1.66k
      if (!_label(m, bufp, bufferEnd, &(rr[i].known.srv.name))) {
413
2
                return false;
414
2
            }
415
1.66k
      break;
416
417
1.66k
    case QTYPE_TXT:
418
3.68k
    default:
419
3.68k
      *bufp += rr[i].rdlength;
420
7.67k
    }
421
7.67k
  }
422
423
1.13k
  return true;
424
1.28k
}
425
426
/* Keep all our mem in one (aligned) block for easy freeing */
427
#define my(x,y, cast)       \
428
6.32k
  while (m->_len & 7)     \
429
5.81k
    m->_len++;     \
430
5.81k
                            \
431
5.81k
    if (m->_len + y > MAX_PACKET_LEN) { return false; } \
432
5.81k
  x = (cast)(void *)(m->_packet + m->_len); \
433
5.76k
  m->_len += y;
434
435
bool message_parse(struct message *m, unsigned char *packet, size_t packetLen)
436
1.68k
{
437
1.68k
  int i;
438
1.68k
  const unsigned char *buf;
439
1.68k
  m->_bufEnd = packet + packetLen;
440
441
  /* Message format: https://tools.ietf.org/html/rfc1035
442
443
  +---------------------+
444
    |        Header       |
445
    +---------------------+
446
    |       Question      | the question for the name server
447
    +---------------------+
448
    |        Answer       | RRs answering the question
449
    +---------------------+
450
    |      Authority      | RRs pointing toward an authority
451
    +---------------------+
452
    |      Additional     | RRs holding additional information
453
    +---------------------+
454
    */
455
456
1.68k
  if (packet == 0 || m == 0)
457
0
    return false;
458
459
  /* See https://tools.ietf.org/html/rfc1035
460
                                  1  1  1  1  1  1
461
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
462
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
463
    |                      ID                       |
464
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
465
    |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
466
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
467
    |                    QDCOUNT                    |
468
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
469
    |                    ANCOUNT                    |
470
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
471
    |                    NSCOUNT                    |
472
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
473
    |                    ARCOUNT                    |
474
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
475
   */
476
477
  /* The header always needs to be present. Size = 12 byte */
478
1.68k
  if (packetLen < 12)
479
6
      return false;
480
481
  /* Header stuff bit crap */
482
1.68k
    buf = m->_buf = packet;
483
1.68k
  m->id = net2short(&buf);
484
1.68k
  if (buf[0] & 0x80)
485
1.28k
    m->header.qr = 1;
486
1.68k
  m->header.opcode = (unsigned short)(((buf[0] & 0x78) >> 3) & 15);
487
1.68k
  if (buf[0] & 0x04)
488
734
    m->header.aa = 1;
489
1.68k
  if (buf[0] & 0x02)
490
832
    m->header.tc = 1;
491
1.68k
  if (buf[0] & 0x01)
492
651
    m->header.rd = 1;
493
1.68k
  if (buf[1] & 0x80)
494
569
    m->header.ra = 1;
495
1.68k
  m->header.z = (unsigned short)(((buf[1] & 0x70) >> 4) & 7);
496
1.68k
  m->header.rcode = (unsigned short)(buf[1] & 0x0F);
497
1.68k
  buf += 2;
498
499
1.68k
  m->qdcount = net2short(&buf);
500
1.68k
  m->ancount = net2short(&buf);
501
1.68k
    m->nscount = net2short(&buf);
502
1.68k
    m->arcount = net2short(&buf);
503
504
    // check if the message has the correct size, i.e. the count matches the number of bytes
505
506
  /* Process questions */
507
1.68k
  my(m->qd, (sizeof(struct question) * m->qdcount), struct question *);
508
4.26k
  for (i = 0; i < m->qdcount; i++) {
509
2.87k
    if (!_label(m, &buf, m->_bufEnd, &(m->qd[i].name))) {
510
69
            return false;
511
69
        }
512
2.80k
    if (buf + 4 > m->_bufEnd) {
513
210
            return false;
514
210
        }
515
2.59k
    m->qd[i].type  = net2short(&buf);
516
2.59k
    m->qd[i].clazz = net2short(&buf);
517
2.59k
  }
518
1.39k
    if (buf > m->_bufEnd) {
519
0
        return false;
520
0
    }
521
522
  /* Process rrs */
523
2.76k
  my(m->an, (sizeof(struct resource) * m->ancount), struct resource *);
524
2.76k
  my(m->ns, (sizeof(struct resource) * m->nscount), struct resource *);
525
1.36k
  my(m->ar, (sizeof(struct resource) * m->arcount), struct resource *);
526
1.35k
  if (!_rrparse(m, m->an, m->ancount, &buf, m->_bufEnd))
527
136
    return false;
528
1.21k
  if (!_rrparse(m, m->ns, m->nscount, &buf, m->_bufEnd))
529
21
    return false;
530
1.19k
  if (!_rrparse(m, m->ar, m->arcount, &buf, m->_bufEnd))
531
11
    return false;
532
1.18k
  return true;
533
1.19k
}
534
535
void message_qd(struct message *m, char *name, unsigned short int type, unsigned short int clazz)
536
0
{
537
0
  m->qdcount++;
538
0
    if (m->_buf == 0) {
539
0
        m->_buf = m->_packet + 12;
540
0
        m->_bufEnd = m->_packet + sizeof(m->_packet);
541
0
    }
542
0
  _host(m, &(m->_buf), name);
543
0
  short2net(type, &(m->_buf));
544
0
  short2net(clazz, &(m->_buf));
545
0
}
546
547
static void _rrappend(struct message *m, char *name, unsigned short int type, unsigned short int clazz, unsigned long ttl)
548
0
{
549
0
  if (m->_buf == 0) {
550
0
        m->_buf = m->_packet + 12;
551
0
        m->_bufEnd = m->_packet + sizeof(m->_packet);
552
0
    }
553
0
  _host(m, &(m->_buf), name);
554
0
  short2net(type, &(m->_buf));
555
0
  short2net(clazz, &(m->_buf));
556
0
  long2net((uint32_t)ttl, &(m->_buf));
557
0
}
558
559
void message_an(struct message *m, char *name, unsigned short int type, unsigned short int clazz, unsigned long ttl)
560
0
{
561
0
  m->ancount++;
562
0
  _rrappend(m, name, type, clazz, ttl);
563
0
}
564
565
void message_ns(struct message *m, char *name, unsigned short int type, unsigned short int clazz, unsigned long ttl)
566
0
{
567
0
  m->nscount++;
568
0
  _rrappend(m, name, type, clazz, ttl);
569
0
}
570
571
void message_ar(struct message *m, char *name, unsigned short int type, unsigned short int clazz, unsigned long ttl)
572
0
{
573
0
  m->arcount++;
574
0
  _rrappend(m, name, type, clazz, ttl);
575
0
}
576
577
void message_rdata_long(struct message *m, struct in_addr l)
578
0
{
579
0
  short2net(4, &(m->_buf));
580
0
  long2net(l.s_addr, &(m->_buf));
581
0
}
582
583
void message_rdata_name(struct message *m, char *name)
584
0
{
585
0
  unsigned char *mybuf = m->_buf;
586
587
0
  m->_buf += 2;
588
0
  short2net((unsigned short)_host(m, &(m->_buf), name), &mybuf);
589
0
}
590
591
void message_rdata_srv(struct message *m, unsigned short int priority, unsigned short int weight, unsigned short int port, char *name)
592
0
{
593
0
  unsigned char *mybuf = m->_buf;
594
595
0
  m->_buf += 2;
596
0
  short2net(priority, &(m->_buf));
597
0
  short2net(weight, &(m->_buf));
598
0
  short2net(port, &(m->_buf));
599
0
  short2net((unsigned short)(_host(m, &(m->_buf), name) + 6), &mybuf);
600
0
}
601
602
void message_rdata_raw(struct message *m, unsigned char *rdata, unsigned short int rdlength)
603
0
{
604
0
  if (((unsigned char *)m->_buf - m->_packet) + rdlength > 4096)
605
0
    rdlength = 0;
606
0
  short2net(rdlength, &(m->_buf));
607
0
  memcpy(m->_buf, rdata, rdlength);
608
0
  m->_buf += rdlength;
609
0
}
610
611
unsigned char *message_packet(struct message *m)
612
0
{
613
0
  unsigned char c, *buf = m->_buf, *bufEnd = m->_bufEnd;
614
615
0
  m->_buf = m->_packet;
616
0
    m->_bufEnd = m->_packet + sizeof(m->_packet);
617
0
  short2net(m->id, &(m->_buf));
618
619
0
  if (m->header.qr)
620
0
    m->_buf[0] |= 0x80;
621
0
  if ((c = (unsigned char)m->header.opcode))
622
0
    m->_buf[0] |= (unsigned char)(c << 3);
623
0
  if (m->header.aa)
624
0
    m->_buf[0] |= 0x04;
625
0
  if (m->header.tc)
626
0
    m->_buf[0] |= 0x02;
627
0
  if (m->header.rd)
628
0
    m->_buf[0] |= 0x01;
629
0
  if (m->header.ra)
630
0
    m->_buf[1] |= 0x80;
631
0
  if ((c = (unsigned char)m->header.z))
632
0
    m->_buf[1] |= (unsigned char)(c << 4);
633
0
  if (m->header.rcode)
634
0
    m->_buf[1] = (unsigned char)(m->_buf[1] | m->header.rcode);
635
636
0
  m->_buf += 2;
637
0
  short2net(m->qdcount, &(m->_buf));
638
0
  short2net(m->ancount, &(m->_buf));
639
0
  short2net(m->nscount, &(m->_buf));
640
0
  short2net(m->arcount, &(m->_buf));
641
0
  m->_buf = buf;    /* Restore, so packet_len works */
642
0
  m->_bufEnd = bufEnd;
643
644
0
  return m->_packet;
645
0
}
646
647
int message_packet_len(struct message *m)
648
0
{
649
0
  if (m->_buf == 0)
650
0
    return 12;
651
652
0
  return (int)((unsigned char *)m->_buf - m->_packet);
653
0
}