1 /* Convert a DNS domain name from presentation to wire format.
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 
22 /* Converts an ASCII string into an encoded domain name as per
23    RFC1035.  Returns -1 if it fails, 1 if string was fully qualified,
24    0 is string was not fully qualified.  Enforces label and domain
25    length limits.  */
26 int
___ns_name_pton(const char * src,unsigned char * dst,size_t dstsiz)27 ___ns_name_pton (const char *src, unsigned char *dst, size_t dstsiz)
28 {
29   unsigned char *label, *bp, *eom;
30   int c, n, escaped;
31 
32   escaped = 0;
33   bp = dst;
34   eom = dst + dstsiz;
35   label = bp++;
36 
37   while ((c = *src++) != 0)
38     {
39       if (escaped)
40         {
41           if ('0' <= c && c <= '9')
42             {
43               n = (c - '0') * 100;
44               if ((c = *src++) == 0 || c < '0' || c > '9')
45                 {
46                   __set_errno (EMSGSIZE);
47                   return -1;
48                 }
49               n += (c - '0') * 10;
50               if ((c = *src++) == 0 || c < '0' || c > '9')
51                 {
52                   __set_errno (EMSGSIZE);
53                   return -1;
54                 }
55               n += c - '0';
56               if (n > 255)
57                 {
58                   __set_errno (EMSGSIZE);
59                   return -1;
60                 }
61               c = n;
62             }
63           escaped = 0;
64         }
65       else if (c == '\\')
66         {
67           escaped = 1;
68           continue;
69         }
70       else if (c == '.')
71         {
72           c = (bp - label - 1);
73           if ((c & NS_CMPRSFLGS) != 0) /* Label too big.  */
74             {
75               __set_errno (EMSGSIZE);
76               return -1;
77             }
78           if (label >= eom)
79             {
80               __set_errno (EMSGSIZE);
81               return -1;
82             }
83           *label = c;
84           /* Fully qualified ? */
85           if (*src == '\0')
86             {
87               if (c != 0)
88                 {
89                   if (bp >= eom)
90                     {
91                       __set_errno (EMSGSIZE);
92                       return -1;
93                     }
94                   *bp++ = '\0';
95                 }
96               if ((bp - dst) > MAXCDNAME)
97                 {
98                   __set_errno (EMSGSIZE);
99                   return -1;
100                 }
101               return 1;
102             }
103           if (c == 0 || *src == '.')
104             {
105               __set_errno (EMSGSIZE);
106               return -1;
107             }
108           label = bp++;
109           continue;
110         }
111       if (bp >= eom)
112         {
113           __set_errno (EMSGSIZE);
114           return -1;
115         }
116       *bp++ = (unsigned char) c;
117     }
118   if (escaped)                  /* Trailing backslash.  */
119     {
120       __set_errno (EMSGSIZE);
121       return -1;
122     }
123   c = (bp - label - 1);
124   if ((c & NS_CMPRSFLGS) != 0)  /* Label too big.  */
125     {
126       __set_errno (EMSGSIZE);
127       return -1;
128     }
129   if (label >= eom)
130     {
131       __set_errno (EMSGSIZE);
132       return -1;
133     }
134   *label = c;
135   if (c != 0)
136     {
137       if (bp >= eom)
138         {
139           __set_errno (EMSGSIZE);
140           return -1;
141         }
142       *bp++ = 0;
143     }
144   if ((bp - dst) > MAXCDNAME)   /* src too big.  */
145     {
146       __set_errno (EMSGSIZE);
147       return -1;
148     }
149   return 0;
150 }
151 versioned_symbol (libc, ___ns_name_pton, ns_name_pton, GLIBC_2_34);
152 versioned_symbol (libc, ___ns_name_pton, __ns_name_pton, GLIBC_PRIVATE);
153 libc_hidden_ver (___ns_name_pton, __ns_name_pton)
154 
155 #if OTHER_SHLIB_COMPAT (libresolv, GLIBC_2_9, GLIBC_2_34)
156 compat_symbol (libresolv, ___ns_name_pton, ns_name_pton, GLIBC_2_9);
157 #endif
158