| 1 | /*
 | 
|---|
| 2 |  * Copyright (C) 1996-2001  Internet Software Consortium.
 | 
|---|
| 3 |  *
 | 
|---|
| 4 |  * Permission to use, copy, modify, and distribute this software for any
 | 
|---|
| 5 |  * purpose with or without fee is hereby granted, provided that the above
 | 
|---|
| 6 |  * copyright notice and this permission notice appear in all copies.
 | 
|---|
| 7 |  *
 | 
|---|
| 8 |  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
 | 
|---|
| 9 |  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
 | 
|---|
| 10 |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
 | 
|---|
| 11 |  * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
 | 
|---|
| 12 |  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 | 
|---|
| 13 |  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 | 
|---|
| 14 |  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 | 
|---|
| 15 |  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
|---|
| 16 |  */
 | 
|---|
| 17 | 
 | 
|---|
| 18 | #include "replace.h"
 | 
|---|
| 19 | #include "system/network.h"
 | 
|---|
| 20 | 
 | 
|---|
| 21 | #define NS_INT16SZ       2
 | 
|---|
| 22 | #define NS_INADDRSZ      4
 | 
|---|
| 23 | #define NS_IN6ADDRSZ    16
 | 
|---|
| 24 | 
 | 
|---|
| 25 | /*
 | 
|---|
| 26 |  * WARNING: Don't even consider trying to compile this on a system where
 | 
|---|
| 27 |  * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
 | 
|---|
| 28 |  */
 | 
|---|
| 29 | 
 | 
|---|
| 30 | static int inet_pton4(const char *src, unsigned char *dst);
 | 
|---|
| 31 | #ifdef AF_INET6
 | 
|---|
| 32 | static int inet_pton6(const char *src, unsigned char *dst);
 | 
|---|
| 33 | #endif
 | 
|---|
| 34 | 
 | 
|---|
| 35 | /* int
 | 
|---|
| 36 |  * inet_pton(af, src, dst)
 | 
|---|
| 37 |  *      convert from presentation format (which usually means ASCII printable)
 | 
|---|
| 38 |  *      to network format (which is usually some kind of binary format).
 | 
|---|
| 39 |  * return:
 | 
|---|
| 40 |  *      1 if the address was valid for the specified address family
 | 
|---|
| 41 |  *      0 if the address wasn't valid (`dst' is untouched in this case)
 | 
|---|
| 42 |  *      -1 if some other error occurred (`dst' is untouched in this case, too)
 | 
|---|
| 43 |  * author:
 | 
|---|
| 44 |  *      Paul Vixie, 1996.
 | 
|---|
| 45 |  */
 | 
|---|
| 46 | int
 | 
|---|
| 47 | rep_inet_pton(int af,
 | 
|---|
| 48 |           const char *src,
 | 
|---|
| 49 |           void *dst)
 | 
|---|
| 50 | {
 | 
|---|
| 51 |         switch (af) {
 | 
|---|
| 52 |         case AF_INET:
 | 
|---|
| 53 |                 return (inet_pton4(src, dst));
 | 
|---|
| 54 | #ifdef AF_INET6
 | 
|---|
| 55 |         case AF_INET6:
 | 
|---|
| 56 |                 return (inet_pton6(src, dst));
 | 
|---|
| 57 | #endif
 | 
|---|
| 58 |         default:
 | 
|---|
| 59 |                 errno = EAFNOSUPPORT;
 | 
|---|
| 60 |                 return (-1);
 | 
|---|
| 61 |         }
 | 
|---|
| 62 |         /* NOTREACHED */
 | 
|---|
| 63 | }
 | 
|---|
| 64 | 
 | 
|---|
| 65 | /* int
 | 
|---|
| 66 |  * inet_pton4(src, dst)
 | 
|---|
| 67 |  *      like inet_aton() but without all the hexadecimal and shorthand.
 | 
|---|
| 68 |  * return:
 | 
|---|
| 69 |  *      1 if `src' is a valid dotted quad, else 0.
 | 
|---|
| 70 |  * notice:
 | 
|---|
| 71 |  *      does not touch `dst' unless it's returning 1.
 | 
|---|
| 72 |  * author:
 | 
|---|
| 73 |  *      Paul Vixie, 1996.
 | 
|---|
| 74 |  */
 | 
|---|
| 75 | static int
 | 
|---|
| 76 | inet_pton4(src, dst)
 | 
|---|
| 77 |         const char *src;
 | 
|---|
| 78 |         unsigned char *dst;
 | 
|---|
| 79 | {
 | 
|---|
| 80 |         static const char digits[] = "0123456789";
 | 
|---|
| 81 |         int saw_digit, octets, ch;
 | 
|---|
| 82 |         unsigned char tmp[NS_INADDRSZ], *tp;
 | 
|---|
| 83 | 
 | 
|---|
| 84 |         saw_digit = 0;
 | 
|---|
| 85 |         octets = 0;
 | 
|---|
| 86 |         *(tp = tmp) = 0;
 | 
|---|
| 87 |         while ((ch = *src++) != '\0') {
 | 
|---|
| 88 |                 const char *pch;
 | 
|---|
| 89 | 
 | 
|---|
| 90 |                 if ((pch = strchr(digits, ch)) != NULL) {
 | 
|---|
| 91 |                         unsigned int new = *tp * 10 + (pch - digits);
 | 
|---|
| 92 | 
 | 
|---|
| 93 |                         if (new > 255)
 | 
|---|
| 94 |                                 return (0);
 | 
|---|
| 95 |                         *tp = new;
 | 
|---|
| 96 |                         if (! saw_digit) {
 | 
|---|
| 97 |                                 if (++octets > 4)
 | 
|---|
| 98 |                                         return (0);
 | 
|---|
| 99 |                                 saw_digit = 1;
 | 
|---|
| 100 |                         }
 | 
|---|
| 101 |                 } else if (ch == '.' && saw_digit) {
 | 
|---|
| 102 |                         if (octets == 4)
 | 
|---|
| 103 |                                 return (0);
 | 
|---|
| 104 |                         *++tp = 0;
 | 
|---|
| 105 |                         saw_digit = 0;
 | 
|---|
| 106 |                 } else
 | 
|---|
| 107 |                         return (0);
 | 
|---|
| 108 |         }
 | 
|---|
| 109 |         if (octets < 4)
 | 
|---|
| 110 |                 return (0);
 | 
|---|
| 111 |         memcpy(dst, tmp, NS_INADDRSZ);
 | 
|---|
| 112 |         return (1);
 | 
|---|
| 113 | }
 | 
|---|
| 114 | 
 | 
|---|
| 115 | /* int
 | 
|---|
| 116 |  * inet_pton6(src, dst)
 | 
|---|
| 117 |  *      convert presentation level address to network order binary form.
 | 
|---|
| 118 |  * return:
 | 
|---|
| 119 |  *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
 | 
|---|
| 120 |  * notice:
 | 
|---|
| 121 |  *      (1) does not touch `dst' unless it's returning 1.
 | 
|---|
| 122 |  *      (2) :: in a full address is silently ignored.
 | 
|---|
| 123 |  * credit:
 | 
|---|
| 124 |  *      inspired by Mark Andrews.
 | 
|---|
| 125 |  * author:
 | 
|---|
| 126 |  *      Paul Vixie, 1996.
 | 
|---|
| 127 |  */
 | 
|---|
| 128 | #ifdef AF_INET6
 | 
|---|
| 129 | static int
 | 
|---|
| 130 | inet_pton6(src, dst)
 | 
|---|
| 131 |         const char *src;
 | 
|---|
| 132 |         unsigned char *dst;
 | 
|---|
| 133 | {
 | 
|---|
| 134 |         static const char xdigits_l[] = "0123456789abcdef",
 | 
|---|
| 135 |                           xdigits_u[] = "0123456789ABCDEF";
 | 
|---|
| 136 |         unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
 | 
|---|
| 137 |         const char *xdigits, *curtok;
 | 
|---|
| 138 |         int ch, saw_xdigit;
 | 
|---|
| 139 |         unsigned int val;
 | 
|---|
| 140 | 
 | 
|---|
| 141 |         memset((tp = tmp), '\0', NS_IN6ADDRSZ);
 | 
|---|
| 142 |         endp = tp + NS_IN6ADDRSZ;
 | 
|---|
| 143 |         colonp = NULL;
 | 
|---|
| 144 |         /* Leading :: requires some special handling. */
 | 
|---|
| 145 |         if (*src == ':')
 | 
|---|
| 146 |                 if (*++src != ':')
 | 
|---|
| 147 |                         return (0);
 | 
|---|
| 148 |         curtok = src;
 | 
|---|
| 149 |         saw_xdigit = 0;
 | 
|---|
| 150 |         val = 0;
 | 
|---|
| 151 |         while ((ch = *src++) != '\0') {
 | 
|---|
| 152 |                 const char *pch;
 | 
|---|
| 153 | 
 | 
|---|
| 154 |                 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
 | 
|---|
| 155 |                         pch = strchr((xdigits = xdigits_u), ch);
 | 
|---|
| 156 |                 if (pch != NULL) {
 | 
|---|
| 157 |                         val <<= 4;
 | 
|---|
| 158 |                         val |= (pch - xdigits);
 | 
|---|
| 159 |                         if (val > 0xffff)
 | 
|---|
| 160 |                                 return (0);
 | 
|---|
| 161 |                         saw_xdigit = 1;
 | 
|---|
| 162 |                         continue;
 | 
|---|
| 163 |                 }
 | 
|---|
| 164 |                 if (ch == ':') {
 | 
|---|
| 165 |                         curtok = src;
 | 
|---|
| 166 |                         if (!saw_xdigit) {
 | 
|---|
| 167 |                                 if (colonp)
 | 
|---|
| 168 |                                         return (0);
 | 
|---|
| 169 |                                 colonp = tp;
 | 
|---|
| 170 |                                 continue;
 | 
|---|
| 171 |                         }
 | 
|---|
| 172 |                         if (tp + NS_INT16SZ > endp)
 | 
|---|
| 173 |                                 return (0);
 | 
|---|
| 174 |                         *tp++ = (unsigned char) (val >> 8) & 0xff;
 | 
|---|
| 175 |                         *tp++ = (unsigned char) val & 0xff;
 | 
|---|
| 176 |                         saw_xdigit = 0;
 | 
|---|
| 177 |                         val = 0;
 | 
|---|
| 178 |                         continue;
 | 
|---|
| 179 |                 }
 | 
|---|
| 180 |                 if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
 | 
|---|
| 181 |                     inet_pton4(curtok, tp) > 0) {
 | 
|---|
| 182 |                         tp += NS_INADDRSZ;
 | 
|---|
| 183 |                         saw_xdigit = 0;
 | 
|---|
| 184 |                         break;  /* '\0' was seen by inet_pton4(). */
 | 
|---|
| 185 |                 }
 | 
|---|
| 186 |                 return (0);
 | 
|---|
| 187 |         }
 | 
|---|
| 188 |         if (saw_xdigit) {
 | 
|---|
| 189 |                 if (tp + NS_INT16SZ > endp)
 | 
|---|
| 190 |                         return (0);
 | 
|---|
| 191 |                 *tp++ = (unsigned char) (val >> 8) & 0xff;
 | 
|---|
| 192 |                 *tp++ = (unsigned char) val & 0xff;
 | 
|---|
| 193 |         }
 | 
|---|
| 194 |         if (colonp != NULL) {
 | 
|---|
| 195 |                 /*
 | 
|---|
| 196 |                  * Since some memmove()'s erroneously fail to handle
 | 
|---|
| 197 |                  * overlapping regions, we'll do the shift by hand.
 | 
|---|
| 198 |                  */
 | 
|---|
| 199 |                 const int n = tp - colonp;
 | 
|---|
| 200 |                 int i;
 | 
|---|
| 201 | 
 | 
|---|
| 202 |                 for (i = 1; i <= n; i++) {
 | 
|---|
| 203 |                         endp[- i] = colonp[n - i];
 | 
|---|
| 204 |                         colonp[n - i] = 0;
 | 
|---|
| 205 |                 }
 | 
|---|
| 206 |                 tp = endp;
 | 
|---|
| 207 |         }
 | 
|---|
| 208 |         if (tp != endp)
 | 
|---|
| 209 |                 return (0);
 | 
|---|
| 210 |         memcpy(dst, tmp, NS_IN6ADDRSZ);
 | 
|---|
| 211 |         return (1);
 | 
|---|
| 212 | }
 | 
|---|
| 213 | #endif
 | 
|---|