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 | |
18 | #include <arpa/nameser.h> |
19 | #include <errno.h> |
20 | #include <shlib-compat.h> |
21 | #include <stddef.h> |
22 | #include <string.h> |
23 | |
24 | /* Unpack a domain name from a message, source may be compressed. |
25 | Returns -1 if it fails, or consumed octets if it succeeds. */ |
26 | int |
27 | ___ns_name_unpack (const unsigned char *msg, const unsigned char *eom, |
28 | const unsigned char *src, unsigned char *dst, size_t dstsiz) |
29 | { |
30 | const unsigned char *srcp, *dstlim; |
31 | unsigned char *dstp; |
32 | int n, len, checked; |
33 | |
34 | len = -1; |
35 | checked = 0; |
36 | dstp = dst; |
37 | srcp = src; |
38 | dstlim = dst + dstsiz; |
39 | if (srcp < msg || srcp >= eom) |
40 | { |
41 | __set_errno (EMSGSIZE); |
42 | return -1; |
43 | } |
44 | /* Fetch next label in domain name. */ |
45 | while ((n = *srcp++) != 0) |
46 | { |
47 | /* Check for indirection. */ |
48 | switch (n & NS_CMPRSFLGS) |
49 | { |
50 | case 0: |
51 | /* Limit checks. */ |
52 | if (n >= 64) |
53 | { |
54 | __set_errno (EMSGSIZE); |
55 | return -1; |
56 | } |
57 | /* NB: n + 1 and >= to cover the *dstp = '\0' assignment |
58 | below. */ |
59 | if (n + 1 >= dstlim - dstp || n >= eom - srcp) |
60 | { |
61 | __set_errno (EMSGSIZE); |
62 | return -1; |
63 | } |
64 | checked += n + 1; |
65 | *dstp++ = n; |
66 | memcpy (dstp, srcp, n); |
67 | dstp += n; |
68 | srcp += n; |
69 | break; |
70 | |
71 | case NS_CMPRSFLGS: |
72 | if (srcp >= eom) |
73 | { |
74 | __set_errno (EMSGSIZE); |
75 | return -1; |
76 | } |
77 | if (len < 0) |
78 | len = srcp - src + 1; |
79 | { |
80 | int target = ((n & 0x3f) << 8) | *srcp; |
81 | if (target >= eom - msg) |
82 | { |
83 | /* Out of range. */ |
84 | __set_errno (EMSGSIZE); |
85 | return -1; |
86 | } |
87 | srcp = msg + target; |
88 | } |
89 | checked += 2; |
90 | /* Check for loops in the compressed name; if we've looked |
91 | at the whole message, there must be a loop. */ |
92 | if (checked >= eom - msg) |
93 | { |
94 | __set_errno (EMSGSIZE); |
95 | return -1; |
96 | } |
97 | break; |
98 | |
99 | default: |
100 | __set_errno (EMSGSIZE); |
101 | return -1; |
102 | } |
103 | } |
104 | *dstp = '\0'; |
105 | if (len < 0) |
106 | len = srcp - src; |
107 | return len; |
108 | } |
109 | versioned_symbol (libc, ___ns_name_unpack, ns_name_unpack, GLIBC_2_34); |
110 | versioned_symbol (libc, ___ns_name_unpack, __ns_name_unpack, GLIBC_PRIVATE); |
111 | libc_hidden_ver (___ns_name_unpack, __ns_name_unpack) |
112 | |
113 | #if OTHER_SHLIB_COMPAT (libresolv, GLIBC_2_9, GLIBC_2_34) |
114 | compat_symbol (libresolv, ___ns_name_unpack, ns_name_unpack, GLIBC_2_9); |
115 | #endif |
116 | |