ns_name_unpack.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /* De-compressing DNS domain names into binary-encoded uncompressed name.
  2. * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (c) 1996,1999 by Internet Software Consortium.
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  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. #include <arpa/nameser.h>
  18. #include <errno.h>
  19. #include <shlib-compat.h>
  20. #include <stddef.h>
  21. #include <string.h>
  22. /* Unpack a domain name from a message, source may be compressed.
  23. Returns -1 if it fails, or consumed octets if it succeeds. */
  24. int
  25. ___ns_name_unpack (const unsigned char *msg, const unsigned char *eom,
  26. const unsigned char *src, unsigned char *dst, size_t dstsiz)
  27. {
  28. const unsigned char *srcp, *dstlim;
  29. unsigned char *dstp;
  30. int n, len, checked;
  31. len = -1;
  32. checked = 0;
  33. dstp = dst;
  34. srcp = src;
  35. dstlim = dst + dstsiz;
  36. if (srcp < msg || srcp >= eom)
  37. {
  38. __set_errno (EMSGSIZE);
  39. return -1;
  40. }
  41. /* Fetch next label in domain name. */
  42. while ((n = *srcp++) != 0)
  43. {
  44. /* Check for indirection. */
  45. switch (n & NS_CMPRSFLGS)
  46. {
  47. case 0:
  48. /* Limit checks. */
  49. if (n >= 64)
  50. {
  51. __set_errno (EMSGSIZE);
  52. return -1;
  53. }
  54. /* NB: n + 1 and >= to cover the *dstp = '\0' assignment
  55. below. */
  56. if (n + 1 >= dstlim - dstp || n >= eom - srcp)
  57. {
  58. __set_errno (EMSGSIZE);
  59. return -1;
  60. }
  61. checked += n + 1;
  62. *dstp++ = n;
  63. memcpy (dstp, srcp, n);
  64. dstp += n;
  65. srcp += n;
  66. break;
  67. case NS_CMPRSFLGS:
  68. if (srcp >= eom)
  69. {
  70. __set_errno (EMSGSIZE);
  71. return -1;
  72. }
  73. if (len < 0)
  74. len = srcp - src + 1;
  75. {
  76. int target = ((n & 0x3f) << 8) | *srcp;
  77. if (target >= eom - msg)
  78. {
  79. /* Out of range. */
  80. __set_errno (EMSGSIZE);
  81. return -1;
  82. }
  83. srcp = msg + target;
  84. }
  85. checked += 2;
  86. /* Check for loops in the compressed name; if we've looked
  87. at the whole message, there must be a loop. */
  88. if (checked >= eom - msg)
  89. {
  90. __set_errno (EMSGSIZE);
  91. return -1;
  92. }
  93. break;
  94. default:
  95. __set_errno (EMSGSIZE);
  96. return -1;
  97. }
  98. }
  99. *dstp = '\0';
  100. if (len < 0)
  101. len = srcp - src;
  102. return len;
  103. }
  104. versioned_symbol (libc, ___ns_name_unpack, ns_name_unpack, GLIBC_2_34);
  105. versioned_symbol (libc, ___ns_name_unpack, __ns_name_unpack, GLIBC_PRIVATE);
  106. libc_hidden_ver (___ns_name_unpack, __ns_name_unpack)
  107. #if OTHER_SHLIB_COMPAT (libresolv, GLIBC_2_9, GLIBC_2_34)
  108. compat_symbol (libresolv, ___ns_name_unpack, ns_name_unpack, GLIBC_2_9);
  109. #endif