Annotation of embedaddon/curl/lib/inet_pton.c, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>