ISC DHCP  4.4.3
A reference DHCPv4 and DHCPv6 implementation
ns_name.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (c) 1996-2003 by Internet Software Consortium
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  *
17  * Internet Systems Consortium, Inc.
18  * PO Box 360
19  * Newmarket, NH 03857 USA
20  * <info@isc.org>
21  * http://www.isc.org/
22  */
23 
24 #include <sys/types.h>
25 
26 #include <netinet/in.h>
27 #include <sys/socket.h>
28 
29 #include <errno.h>
30 #include <string.h>
31 #include <ctype.h>
32 
33 #include "ns_name.h"
34 #include "arpa/nameser.h"
35 
36 /* Data. */
37 
38 static const char digits[] = "0123456789";
39 
40 /* Forward. */
41 
42 static int special(int);
43 static int printable(int);
44 static int dn_find(const u_char *, const u_char *,
45  const u_char * const *,
46  const u_char * const *);
47 
48 /* Public. */
49 
50 /*
51  * MRns_name_len(eom, src)
52  * Compute the length of encoded uncompressed domain name.
53  * return:
54  * -1 if it fails, or to be consumed octets if it succeeds.
55  */
56 int
57 MRns_name_len(const u_char *eom, const u_char *src)
58 {
59  const u_char *srcp;
60  unsigned n;
61  int len;
62 
63  len = -1;
64  srcp = src;
65  if (srcp >= eom) {
66  errno = EMSGSIZE;
67  return (-1);
68  }
69  /* Fetch next label in domain name. */
70  while ((n = *srcp++) != 0) {
71  /* Limit checks. */
72  if (srcp + n >= eom) {
73  errno = EMSGSIZE;
74  return (-1);
75  }
76  srcp += n;
77  }
78  if (len < 0)
79  len = srcp - src;
80  return (len);
81 }
82 
83 /*
84  * MRns_name_ntop(src, dst, dstsiz)
85  * Convert an encoded domain name to printable ascii as per RFC1035.
86  * return:
87  * Number of bytes written to buffer, or -1 (with errno set)
88  * notes:
89  * The root is returned as "."
90  * All other domains are returned in non absolute form
91  */
92 int
93 MRns_name_ntop(const u_char *src, char *dst, size_t dstsiz) {
94  const u_char *cp;
95  char *dn, *eom;
96  u_char c;
97  u_int n;
98 
99  cp = src;
100  dn = dst;
101  eom = dst + dstsiz;
102 
103  while ((n = *cp++) != 0) {
104  if ((n & NS_CMPRSFLGS) != 0) {
105  /* Some kind of compression pointer. */
106  errno = EMSGSIZE;
107  return (-1);
108  }
109  if (dn != dst) {
110  if (dn >= eom) {
111  errno = EMSGSIZE;
112  return (-1);
113  }
114  *dn++ = '.';
115  }
116  if (dn + n >= eom) {
117  errno = EMSGSIZE;
118  return (-1);
119  }
120  for ((void)NULL; n > 0; n--) {
121  c = *cp++;
122  if (special(c)) {
123  if (dn + 1 >= eom) {
124  errno = EMSGSIZE;
125  return (-1);
126  }
127  *dn++ = '\\';
128  *dn++ = (char)c;
129  } else if (!printable(c)) {
130  if (dn + 3 >= eom) {
131  errno = EMSGSIZE;
132  return (-1);
133  }
134  *dn++ = '\\';
135  *dn++ = digits[c / 100];
136  *dn++ = digits[(c % 100) / 10];
137  *dn++ = digits[c % 10];
138  } else {
139  if (dn >= eom) {
140  errno = EMSGSIZE;
141  return (-1);
142  }
143  *dn++ = (char)c;
144  }
145  }
146  }
147  if (dn == dst) {
148  if (dn >= eom) {
149  errno = EMSGSIZE;
150  return (-1);
151  }
152  *dn++ = '.';
153  }
154  if (dn >= eom) {
155  errno = EMSGSIZE;
156  return (-1);
157  }
158  *dn++ = '\0';
159  return (dn - dst);
160 }
161 
162 /*
163  * MRns_name_pton(src, dst, dstsiz)
164  * Convert a ascii string into an encoded domain name as per RFC1035.
165  * return:
166  * -1 if it fails
167  * 1 if string was fully qualified
168  * 0 is string was not fully qualified
169  * notes:
170  * Enforces label and domain length limits.
171  */
172 
173 int
174 MRns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
175  u_char *label, *bp, *eom;
176  int c, n, escaped;
177  char *cp;
178 
179  escaped = 0;
180  bp = dst;
181  eom = dst + dstsiz;
182  label = bp++;
183 
184  while ((c = *src++) != 0) {
185  if (escaped) {
186  if ((cp = strchr(digits, c)) != NULL) {
187  n = (cp - digits) * 100;
188  if ((c = *src++) == 0 ||
189  (cp = strchr(digits, c)) == NULL) {
190  errno = EMSGSIZE;
191  return (-1);
192  }
193  n += (cp - digits) * 10;
194  if ((c = *src++) == 0 ||
195  (cp = strchr(digits, c)) == NULL) {
196  errno = EMSGSIZE;
197  return (-1);
198  }
199  n += (cp - digits);
200  if (n > 255) {
201  errno = EMSGSIZE;
202  return (-1);
203  }
204  c = n;
205  }
206  escaped = 0;
207  } else if (c == '\\') {
208  escaped = 1;
209  continue;
210  } else if (c == '.') {
211  c = (bp - label - 1);
212  if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
213  errno = EMSGSIZE;
214  return (-1);
215  }
216  if (label >= eom) {
217  errno = EMSGSIZE;
218  return (-1);
219  }
220  *label = c;
221  /* Fully qualified ? */
222  if (*src == '\0') {
223  if (c != 0) {
224  if (bp >= eom) {
225  errno = EMSGSIZE;
226  return (-1);
227  }
228  *bp++ = '\0';
229  }
230  if ((bp - dst) > MAXCDNAME) {
231  errno = EMSGSIZE;
232  return (-1);
233  }
234  return (1);
235  }
236  if (c == 0 || *src == '.') {
237  errno = EMSGSIZE;
238  return (-1);
239  }
240  label = bp++;
241  continue;
242  }
243  if (bp >= eom) {
244  errno = EMSGSIZE;
245  return (-1);
246  }
247  *bp++ = (u_char)c;
248  }
249  c = (bp - label - 1);
250  if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
251  errno = EMSGSIZE;
252  return (-1);
253  }
254  if (label >= eom) {
255  errno = EMSGSIZE;
256  return (-1);
257  }
258  *label = c;
259  if (c != 0) {
260  if (bp >= eom) {
261  errno = EMSGSIZE;
262  return (-1);
263  }
264  *bp++ = 0;
265  }
266  if ((bp - dst) > MAXCDNAME) { /* src too big */
267  errno = EMSGSIZE;
268  return (-1);
269  }
270  return (0);
271 }
272 
273 /*
274  * MRns_name_ntol(src, dst, dstsiz)
275  * Convert a network strings labels into all lowercase.
276  * return:
277  * Number of bytes written to buffer, or -1 (with errno set)
278  * notes:
279  * Enforces label and domain length limits.
280  */
281 
282 int
283 MRns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz) {
284  const u_char *cp;
285  u_char *dn, *eom;
286  u_char c;
287  u_int n;
288 
289  cp = src;
290  dn = dst;
291  eom = dst + dstsiz;
292 
293  if (dn >= eom) {
294  errno = EMSGSIZE;
295  return (-1);
296  }
297  while ((n = *cp++) != 0) {
298  if ((n & NS_CMPRSFLGS) != 0) {
299  /* Some kind of compression pointer. */
300  errno = EMSGSIZE;
301  return (-1);
302  }
303  *dn++ = n;
304  if (dn + n >= eom) {
305  errno = EMSGSIZE;
306  return (-1);
307  }
308  for ((void)NULL; n > 0; n--) {
309  c = *cp++;
310  if (isupper(c))
311  *dn++ = tolower(c);
312  else
313  *dn++ = c;
314  }
315  }
316  *dn++ = '\0';
317  return (dn - dst);
318 }
319 
320 /*
321  * MRns_name_unpack(msg, eom, src, dst, dstsiz)
322  * Unpack a domain name from a message, source may be compressed.
323  * return:
324  * -1 if it fails, or consumed octets if it succeeds.
325  */
326 int
327 MRns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
328  u_char *dst, size_t dstsiz)
329 {
330  const u_char *srcp, *dstlim;
331  u_char *dstp;
332  unsigned n;
333  int len;
334  int checked;
335 
336  len = -1;
337  checked = 0;
338  dstp = dst;
339  srcp = src;
340  dstlim = dst + dstsiz;
341  if (srcp < msg || srcp >= eom) {
342  errno = EMSGSIZE;
343  return (-1);
344  }
345  /* Fetch next label in domain name. */
346  while ((n = *srcp++) != 0) {
347  /* Check for indirection. */
348  switch (n & NS_CMPRSFLGS) {
349  case 0:
350  /* Limit checks. */
351  if (dstp + n + 1 >= dstlim || srcp + n >= eom) {
352  errno = EMSGSIZE;
353  return (-1);
354  }
355  checked += n + 1;
356  *dstp++ = n;
357  memcpy(dstp, srcp, n);
358  dstp += n;
359  srcp += n;
360  break;
361 
362  case NS_CMPRSFLGS:
363  if (srcp >= eom) {
364  errno = EMSGSIZE;
365  return (-1);
366  }
367  if (len < 0)
368  len = srcp - src + 1;
369  srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
370  if (srcp < msg || srcp >= eom) { /* Out of range. */
371  errno = EMSGSIZE;
372  return (-1);
373  }
374  checked += 2;
375  /*
376  * Check for loops in the compressed name;
377  * if we've looked at the whole message,
378  * there must be a loop.
379  */
380  if (checked >= eom - msg) {
381  errno = EMSGSIZE;
382  return (-1);
383  }
384  break;
385 
386  default:
387  errno = EMSGSIZE;
388  return (-1); /* flag error */
389  }
390  }
391  *dstp = '\0';
392  if (len < 0)
393  len = srcp - src;
394  return (len);
395 }
396 
397 /*
398  * MRns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr)
399  * Pack domain name 'domain' into 'comp_dn'.
400  * return:
401  * Size of the compressed name, or -1.
402  * notes:
403  * 'dnptrs' is an array of pointers to previous compressed names.
404  * dnptrs[0] is a pointer to the beginning of the message. The array
405  * ends with NULL.
406  * 'lastdnptr' is a pointer to the end of the array pointed to
407  * by 'dnptrs'.
408  * Side effects:
409  * The list of pointers in dnptrs is updated for labels inserted into
410  * the message as we compress the name. If 'dnptr' is NULL, we don't
411  * try to compress names. If 'lastdnptr' is NULL, we don't update the
412  * list.
413  */
414 int
415 MRns_name_pack(const u_char *src, u_char *dst, unsigned dstsiz,
416  const u_char **dnptrs, const u_char **lastdnptr)
417 {
418  u_char *dstp;
419  const u_char **cpp, **lpp, *eob, *msg;
420  const u_char *srcp;
421  unsigned n;
422  int l;
423 
424  srcp = src;
425  dstp = dst;
426  eob = dstp + dstsiz;
427  lpp = cpp = NULL;
428  if (dnptrs != NULL) {
429  if ((msg = *dnptrs++) != NULL) {
430  for (cpp = dnptrs; *cpp != NULL; cpp++)
431  (void)NULL;
432  lpp = cpp; /* end of list to search */
433  }
434  } else
435  msg = NULL;
436 
437  /* make sure the domain we are about to add is legal */
438  l = 0;
439  do {
440  n = *srcp;
441  if ((n & NS_CMPRSFLGS) != 0) {
442  errno = EMSGSIZE;
443  return (-1);
444  }
445  l += n + 1;
446  if (l > MAXCDNAME) {
447  errno = EMSGSIZE;
448  return (-1);
449  }
450  srcp += n + 1;
451  } while (n != 0);
452 
453  /* from here on we need to reset compression pointer array on error */
454  srcp = src;
455  do {
456  /* Look to see if we can use pointers. */
457  n = *srcp;
458  if (n != 0 && msg != NULL) {
459  l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
460  (const u_char * const *)lpp);
461  if (l >= 0) {
462  if (dstp + 1 >= eob) {
463  goto cleanup;
464  }
465  *dstp++ = (l >> 8) | NS_CMPRSFLGS;
466  *dstp++ = l % 256;
467  return (dstp - dst);
468  }
469  /* Not found, save it. */
470  if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
471  (dstp - msg) < 0x4000) {
472  *cpp++ = dstp;
473  *cpp = NULL;
474  }
475  }
476  /* copy label to buffer */
477  if (n & NS_CMPRSFLGS) { /* Should not happen. */
478  goto cleanup;
479  }
480  if (dstp + 1 + n >= eob) {
481  goto cleanup;
482  }
483  memcpy(dstp, srcp, n + 1);
484  srcp += n + 1;
485  dstp += n + 1;
486  } while (n != 0);
487 
488  if (dstp > eob) {
489 cleanup:
490  if (msg != NULL)
491  *lpp = NULL;
492  errno = EMSGSIZE;
493  return (-1);
494  }
495  return (dstp - dst);
496 }
497 
498 /*
499  * MRns_name_uncompress(msg, eom, src, dst, dstsiz)
500  * Expand compressed domain name to presentation format.
501  * return:
502  * Number of bytes read out of `src', or -1 (with errno set).
503  * note:
504  * Root domain returns as "." not "".
505  */
506 int
507 MRns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
508  char *dst, size_t dstsiz)
509 {
510  u_char tmp[NS_MAXCDNAME];
511  int n;
512 
513  if ((n = MRns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
514  return (-1);
515  if (MRns_name_ntop(tmp, dst, dstsiz) == -1)
516  return (-1);
517  return (n);
518 }
519 
520 /*
521  * MRns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr)
522  * Compress a domain name into wire format, using compression pointers.
523  * return:
524  * Number of bytes consumed in `dst' or -1 (with errno set).
525  * notes:
526  * 'dnptrs' is an array of pointers to previous compressed names.
527  * dnptrs[0] is a pointer to the beginning of the message.
528  * The list ends with NULL. 'lastdnptr' is a pointer to the end of the
529  * array pointed to by 'dnptrs'. Side effect is to update the list of
530  * pointers for labels inserted into the message as we compress the name.
531  * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
532  * is NULL, we don't update the list.
533  */
534 int
535 MRns_name_compress(const char *src, u_char *dst, size_t dstsiz,
536  const u_char **dnptrs, const u_char **lastdnptr)
537 {
538  u_char tmp[NS_MAXCDNAME];
539 
540  if (MRns_name_pton(src, tmp, sizeof tmp) == -1)
541  return (-1);
542  return (MRns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
543 }
544 
545 /*
546  * MRns_name_skip(ptrptr, eom)
547  * Advance *ptrptr to skip over the compressed name it points at.
548  * return:
549  * 0 on success, -1 (with errno set) on failure.
550  */
551 int
552 MRns_name_skip(const u_char **ptrptr, const u_char *eom) {
553  const u_char *cp;
554  u_int n;
555 
556  cp = *ptrptr;
557  while (cp < eom && (n = *cp++) != 0) {
558  /* Check for indirection. */
559  switch (n & NS_CMPRSFLGS) {
560  case 0: /* normal case, n == len */
561  cp += n;
562  continue;
563  case NS_CMPRSFLGS: /* indirection */
564  cp++;
565  break;
566  default: /* illegal type */
567  errno = EMSGSIZE;
568  return (-1);
569  }
570  break;
571  }
572  if (cp > eom) {
573  errno = EMSGSIZE;
574  return (-1);
575  }
576  *ptrptr = cp;
577  return (0);
578 }
579 
580 /* Private. */
581 
582 /*
583  * special(ch)
584  * Thinking in noninternationalized USASCII (per the DNS spec),
585  * is this characted special ("in need of quoting") ?
586  * return:
587  * boolean.
588  */
589 static int
590 special(int ch) {
591  switch (ch) {
592  case 0x22: /* '"' */
593  case 0x2E: /* '.' */
594  case 0x3B: /* ';' */
595  case 0x5C: /* '\\' */
596  /* Special modifiers in zone files. */
597  case 0x40: /* '@' */
598  case 0x24: /* '$' */
599  return (1);
600  default:
601  return (0);
602  }
603 }
604 
605 /*
606  * printable(ch)
607  * Thinking in noninternationalized USASCII (per the DNS spec),
608  * is this character visible and not a space when printed ?
609  * return:
610  * boolean.
611  */
612 static int
613 printable(int ch) {
614  return (ch > 0x20 && ch < 0x7f);
615 }
616 
617 /*
618  * Thinking in noninternationalized USASCII (per the DNS spec),
619  * convert this character to lower case if it's upper case.
620  */
621 static int
622 mklower(int ch) {
623  if (ch >= 0x41 && ch <= 0x5A)
624  return (ch + 0x20);
625  return (ch);
626 }
627 
628 /*
629  * dn_find(domain, msg, dnptrs, lastdnptr)
630  * Search for the counted-label name in an array of compressed names.
631  * return:
632  * offset from msg if found, or -1.
633  * notes:
634  * dnptrs is the pointer to the first name on the list,
635  * not the pointer to the start of the message.
636  */
637 static int
638 dn_find(const u_char *domain, const u_char *msg,
639  const u_char * const *dnptrs,
640  const u_char * const *lastdnptr)
641 {
642  const u_char *dn, *cp, *sp;
643  const u_char * const *cpp;
644  u_int n;
645 
646  for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
647  dn = domain;
648  sp = cp = *cpp;
649  while ((n = *cp++) != 0) {
650  /*
651  * check for indirection
652  */
653  switch (n & NS_CMPRSFLGS) {
654  case 0: /* normal case, n == len */
655  if (n != *dn++)
656  goto next;
657  for ((void)NULL; n > 0; n--)
658  if (mklower(*dn++) != mklower(*cp++))
659  goto next;
660  /* Is next root for both ? */
661  if (*dn == '\0' && *cp == '\0')
662  return (sp - msg);
663  if (*dn)
664  continue;
665  goto next;
666 
667  case NS_CMPRSFLGS: /* indirection */
668  cp = msg + (((n & 0x3f) << 8) | *cp);
669  break;
670 
671  default: /* illegal type */
672  errno = EMSGSIZE;
673  return (-1);
674  }
675  }
676  next: ;
677  }
678  errno = ENOENT;
679  return (-1);
680 }
681 
711 int MRns_name_uncompress_list(const unsigned char* buf, int buflen,
712  char* dst_buf, size_t dst_size)
713 {
714  const unsigned char* src = buf;
715  char* dst = dst_buf;
716  int consumed = 1;
717  int dst_remaining = dst_size;
718  int added_len = 0;
719  int first_pass = 1;
720 
721  if (!buf || buflen == 0 || *buf == 0x00) {
722  /* nothing to do */
723  *dst = 0;
724  return (0);
725  }
726 
727  while ((consumed > 0) && (src < (buf + buflen)))
728  {
729  if (dst_remaining <= 0) {
730  errno = EMSGSIZE;
731  return (-1);
732  }
733 
734  if (!first_pass) {
735  *dst++ = ',';
736  *dst = '\0';
737  dst_remaining--;
738  }
739 
740  consumed = MRns_name_uncompress(buf, buf + buflen, src,
741  dst, dst_remaining);
742  if (consumed < 0) {
743  return (-1);
744  }
745 
746  src += consumed;
747  added_len = strlen(dst);
748  dst_remaining -= added_len;
749  dst += added_len;
750  first_pass = 0;
751  }
752  *dst='\0';
753 
754  /* return the length of the uncompressed list string */
755  return (strlen(dst_buf));
756 }
757 
780 int MRns_name_compress_list(const char* buf, int buflen,
781  unsigned char* compbuf, size_t compbuf_size)
782 {
783  char cur_name[NS_MAXCDNAME];
784  const unsigned char *dnptrs[256], **lastdnptr;
785  const char* src;
786  const char* src_end;
787  unsigned clen = 0;
788  int result = 0;
789 
790  memset(compbuf, 0, compbuf_size);
791  memset(dnptrs, 0, sizeof(dnptrs));
792  dnptrs[0] = compbuf;
793  lastdnptr = &dnptrs[255];
794 
795  src = buf;
796  src_end = buf + buflen;
797  while (src < src_end) {
798  char *comma = strchr(src, ',');
799  int copylen = ((comma != NULL) ? comma - src : strlen(src));
800  if (copylen > (sizeof(cur_name) - 1)) {
801  errno = EMSGSIZE;
802  return (-1);
803  }
804 
805  memcpy(cur_name, src, copylen);
806  cur_name[copylen] = '\0';
807  src += copylen + 1;
808 
809  result = MRns_name_compress(cur_name, compbuf + clen,
810  compbuf_size - clen,
811  dnptrs, lastdnptr);
812 
813  if (result < 0) {
814  return (-1);
815  }
816 
817  clen += result;
818  }
819 
820  /* return size of compressed list */
821  return(clen);
822 }
void cleanup(void)
const char * printable(const char *value)
Given a char pointer, return always return a printable value.
Definition: failover.c:6555
@ special
Definition: keama.h:265
#define NS_MAXCDNAME
Definition: nameser.h:75
#define NS_CMPRSFLGS
Definition: nameser.h:85
#define MAXCDNAME
int MRns_name_ntop(const u_char *src, char *dst, size_t dstsiz)
Definition: ns_name.c:93
int MRns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz)
Definition: ns_name.c:283
int MRns_name_pack(const u_char *src, u_char *dst, unsigned dstsiz, const u_char **dnptrs, const u_char **lastdnptr)
Definition: ns_name.c:415
int MRns_name_len(const u_char *eom, const u_char *src)
Definition: ns_name.c:57
int MRns_name_compress(const char *src, u_char *dst, size_t dstsiz, const u_char **dnptrs, const u_char **lastdnptr)
Definition: ns_name.c:535
int MRns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, u_char *dst, size_t dstsiz)
Definition: ns_name.c:327
int MRns_name_uncompress_list(const unsigned char *buf, int buflen, char *dst_buf, size_t dst_size)
Creates a string of comma-separated domain-names from a compressed list.
Definition: ns_name.c:711
int MRns_name_skip(const u_char **ptrptr, const u_char *eom)
Definition: ns_name.c:552
int MRns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src, char *dst, size_t dstsiz)
Definition: ns_name.c:507
int MRns_name_compress_list(const char *buf, int buflen, unsigned char *compbuf, size_t compbuf_size)
Creates a compressed list from a string of comma-separated domain-names.
Definition: ns_name.c:780
int MRns_name_pton(const char *src, u_char *dst, size_t dstsiz)
Definition: ns_name.c:174