Git fork
at reftables-rust 215 lines 7.0 kB view raw
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 "../git-compat-util.h" 19 20#ifndef NS_INT16SZ 21#define NS_INT16SZ 2 22#endif 23 24#ifndef NS_INADDRSZ 25#define NS_INADDRSZ 4 26#endif 27 28#ifndef NS_IN6ADDRSZ 29#define NS_IN6ADDRSZ 16 30#endif 31 32/* 33 * WARNING: Don't even consider trying to compile this on a system where 34 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. 35 */ 36 37static int inet_pton4(const char *src, unsigned char *dst); 38#ifndef NO_IPV6 39static int inet_pton6(const char *src, unsigned char *dst); 40#endif 41 42/* int 43 * inet_pton4(src, dst) 44 * like inet_aton() but without all the hexadecimal and shorthand. 45 * return: 46 * 1 if `src' is a valid dotted quad, else 0. 47 * notice: 48 * does not touch `dst' unless it's returning 1. 49 * author: 50 * Paul Vixie, 1996. 51 */ 52static int 53inet_pton4(const char *src, unsigned char *dst) 54{ 55 static const char digits[] = "0123456789"; 56 int saw_digit, octets, ch; 57 unsigned char tmp[NS_INADDRSZ], *tp; 58 59 saw_digit = 0; 60 octets = 0; 61 *(tp = tmp) = 0; 62 while ((ch = *src++) != '\0') { 63 const char *pch; 64 65 if ((pch = strchr(digits, ch)) != NULL) { 66 unsigned int new = *tp * 10 + (pch - digits); 67 68 if (new > 255) 69 return (0); 70 *tp = new; 71 if (! saw_digit) { 72 if (++octets > 4) 73 return (0); 74 saw_digit = 1; 75 } 76 } else if (ch == '.' && saw_digit) { 77 if (octets == 4) 78 return (0); 79 *++tp = 0; 80 saw_digit = 0; 81 } else 82 return (0); 83 } 84 if (octets < 4) 85 return (0); 86 memcpy(dst, tmp, NS_INADDRSZ); 87 return (1); 88} 89 90/* int 91 * inet_pton6(src, dst) 92 * convert presentation level address to network order binary form. 93 * return: 94 * 1 if `src' is a valid [RFC1884 2.2] address, else 0. 95 * notice: 96 * (1) does not touch `dst' unless it's returning 1. 97 * (2) :: in a full address is silently ignored. 98 * credit: 99 * inspired by Mark Andrews. 100 * author: 101 * Paul Vixie, 1996. 102 */ 103 104#ifndef NO_IPV6 105static int 106inet_pton6(const char *src, unsigned char *dst) 107{ 108 static const char xdigits_l[] = "0123456789abcdef", 109 xdigits_u[] = "0123456789ABCDEF"; 110 unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; 111 const char *xdigits, *curtok; 112 int ch, saw_xdigit; 113 unsigned int val; 114 115 memset((tp = tmp), '\0', NS_IN6ADDRSZ); 116 endp = tp + NS_IN6ADDRSZ; 117 colonp = NULL; 118 /* Leading :: requires some special handling. */ 119 if (*src == ':') 120 if (*++src != ':') 121 return (0); 122 curtok = src; 123 saw_xdigit = 0; 124 val = 0; 125 while ((ch = *src++) != '\0') { 126 const char *pch; 127 128 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) 129 pch = strchr((xdigits = xdigits_u), ch); 130 if (pch != NULL) { 131 val <<= 4; 132 val |= (pch - xdigits); 133 if (val > 0xffff) 134 return (0); 135 saw_xdigit = 1; 136 continue; 137 } 138 if (ch == ':') { 139 curtok = src; 140 if (!saw_xdigit) { 141 if (colonp) 142 return (0); 143 colonp = tp; 144 continue; 145 } 146 if (tp + NS_INT16SZ > endp) 147 return (0); 148 *tp++ = (unsigned char) (val >> 8) & 0xff; 149 *tp++ = (unsigned char) val & 0xff; 150 saw_xdigit = 0; 151 val = 0; 152 continue; 153 } 154 if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && 155 inet_pton4(curtok, tp) > 0) { 156 tp += NS_INADDRSZ; 157 saw_xdigit = 0; 158 break; /* '\0' was seen by inet_pton4(). */ 159 } 160 return (0); 161 } 162 if (saw_xdigit) { 163 if (tp + NS_INT16SZ > endp) 164 return (0); 165 *tp++ = (unsigned char) (val >> 8) & 0xff; 166 *tp++ = (unsigned char) val & 0xff; 167 } 168 if (colonp != NULL) { 169 /* 170 * Since some memmove()'s erroneously fail to handle 171 * overlapping regions, we'll do the shift by hand. 172 */ 173 const int n = tp - colonp; 174 int i; 175 176 for (i = 1; i <= n; i++) { 177 endp[- i] = colonp[n - i]; 178 colonp[n - i] = 0; 179 } 180 tp = endp; 181 } 182 if (tp != endp) 183 return (0); 184 memcpy(dst, tmp, NS_IN6ADDRSZ); 185 return (1); 186} 187#endif 188 189/* int 190 * isc_net_pton(af, src, dst) 191 * convert from presentation format (which usually means ASCII printable) 192 * to network format (which is usually some kind of binary format). 193 * return: 194 * 1 if the address was valid for the specified address family 195 * 0 if the address wasn't valid (`dst' is untouched in this case) 196 * -1 if some other error occurred (`dst' is untouched in this case, too) 197 * author: 198 * Paul Vixie, 1996. 199 */ 200int 201inet_pton(int af, const char *src, void *dst) 202{ 203 switch (af) { 204 case AF_INET: 205 return (inet_pton4(src, dst)); 206#ifndef NO_IPV6 207 case AF_INET6: 208 return (inet_pton6(src, dst)); 209#endif 210 default: 211 errno = EAFNOSUPPORT; 212 return (-1); 213 } 214 /* NOTREACHED */ 215}