inet_pton.c revision 302408
198943Sluigi/* $KAME: inet_pton.c,v 1.5 2001/08/20 02:32:40 itojun Exp $ */ 2117328Sluigi 398943Sluigi/* Copyright (c) 1996 by Internet Software Consortium. 498943Sluigi * 598943Sluigi * Permission to use, copy, modify, and distribute this software for any 698943Sluigi * purpose with or without fee is hereby granted, provided that the above 798943Sluigi * copyright notice and this permission notice appear in all copies. 898943Sluigi * 998943Sluigi * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 1098943Sluigi * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 1198943Sluigi * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 1298943Sluigi * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 1398943Sluigi * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 1498943Sluigi * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 1598943Sluigi * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 1698943Sluigi * SOFTWARE. 1798943Sluigi */ 1898943Sluigi 1998943Sluigi#include <ldns/config.h> 2098943Sluigi 2198943Sluigi#include <string.h> 2298943Sluigi#include <stdio.h> 2398943Sluigi#include <errno.h> 2498943Sluigi 2598943Sluigi/* 2698943Sluigi * WARNING: Don't even consider trying to compile this on a system where 2798943Sluigi * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. 2898943Sluigi */ 2998943Sluigi 30136071Sgreenstatic int inet_pton4 (const char *src, uint8_t *dst); 3198943Sluigistatic int inet_pton6 (const char *src, uint8_t *dst); 3298943Sluigi 3398943Sluigi/* 3498943Sluigi * 3598943Sluigi * The definitions we might miss. 3698943Sluigi * 3798943Sluigi */ 3898943Sluigi#ifndef NS_INT16SZ 3998943Sluigi#define NS_INT16SZ 2 4098943Sluigi#endif 4198943Sluigi 4298943Sluigi#ifndef NS_IN6ADDRSZ 4398943Sluigi#define NS_IN6ADDRSZ 16 44117469Sluigi#endif 4598943Sluigi 4698943Sluigi#ifndef NS_INADDRSZ 47136071Sgreen#define NS_INADDRSZ 4 48136071Sgreen#endif 4998943Sluigi 5098943Sluigi/* int 51136071Sgreen * inet_pton(af, src, dst) 52145246Sbrooks * convert from presentation format (which usually means ASCII printable) 5398943Sluigi * to network format (which is usually some kind of binary format). 5498943Sluigi * return: 5598943Sluigi * 1 if the address was valid for the specified address family 5698943Sluigi * 0 if the address wasn't valid (`dst' is untouched in this case) 57145246Sbrooks * -1 if some other error occurred (`dst' is untouched in this case, too) 5898943Sluigi * author: 5998943Sluigi * Paul Vixie, 1996. 6098943Sluigi */ 6198943Sluigiint 6298943Sluigiinet_pton(af, src, dst) 63117328Sluigi int af; 6498943Sluigi const char *src; 6598943Sluigi void *dst; 6698943Sluigi{ 6798943Sluigi switch (af) { 6898943Sluigi case AF_INET: 6998943Sluigi return (inet_pton4(src, dst)); 7098943Sluigi case AF_INET6: 71102098Sluigi return (inet_pton6(src, dst)); 72123804Smaxim default: 73101628Sluigi#ifdef EAFNOSUPPORT 74117328Sluigi errno = EAFNOSUPPORT; 75123495Sluigi#else 7698943Sluigi errno = ENOSYS; 7798943Sluigi#endif 7898943Sluigi return (-1); 79130013Scsjp } 80130013Scsjp /* NOTREACHED */ 81130013Scsjp} 82130013Scsjp 83130013Scsjp/* int 8498943Sluigi * inet_pton4(src, dst) 85158879Soleg * like inet_aton() but without all the hexadecimal and shorthand. 86158879Soleg * return: 87158879Soleg * 1 if `src' is a valid dotted quad, else 0. 88158879Soleg * notice: 89158879Soleg * does not touch `dst' unless it's returning 1. 90158879Soleg * author: 91158879Soleg * Paul Vixie, 1996. 92158879Soleg */ 93158879Solegstatic int 9498943Sluigiinet_pton4(src, dst) 95117328Sluigi const char *src; 96117328Sluigi uint8_t *dst; 97117328Sluigi{ 98117328Sluigi static const char digits[] = "0123456789"; 99117328Sluigi int saw_digit, octets, ch; 10098943Sluigi uint8_t tmp[NS_INADDRSZ], *tp; 10198943Sluigi 10298943Sluigi saw_digit = 0; 103117469Sluigi octets = 0; 10498943Sluigi *(tp = tmp) = 0; 10598943Sluigi while ((ch = *src++) != '\0') { 10698943Sluigi const char *pch; 10798943Sluigi 10898943Sluigi if ((pch = strchr(digits, ch)) != NULL) { 10998943Sluigi uint32_t new = *tp * 10 + (pch - digits); 11098943Sluigi 11198943Sluigi if (new > 255) 11298943Sluigi return (0); 11398943Sluigi *tp = new; 11498943Sluigi if (! saw_digit) { 11598943Sluigi if (++octets > 4) 11698943Sluigi return (0); 11798943Sluigi saw_digit = 1; 11898943Sluigi } 11998943Sluigi } else if (ch == '.' && saw_digit) { 12098943Sluigi if (octets == 4) 12198943Sluigi return (0); 12298943Sluigi *++tp = 0; 12398943Sluigi saw_digit = 0; 12498943Sluigi } else 12598943Sluigi return (0); 12698943Sluigi } 12798943Sluigi if (octets < 4) 12898943Sluigi return (0); 12998943Sluigi 13098943Sluigi memcpy(dst, tmp, NS_INADDRSZ); 13198943Sluigi return (1); 13298943Sluigi} 13398943Sluigi 13498943Sluigi/* int 13598943Sluigi * inet_pton6(src, dst) 13698943Sluigi * convert presentation level address to network order binary form. 13798943Sluigi * return: 13898943Sluigi * 1 if `src' is a valid [RFC1884 2.2] address, else 0. 13998943Sluigi * notice: 14098943Sluigi * (1) does not touch `dst' unless it's returning 1. 14198943Sluigi * (2) :: in a full address is silently ignored. 14298943Sluigi * credit: 14398943Sluigi * inspired by Mark Andrews. 14498943Sluigi * author: 14598943Sluigi * Paul Vixie, 1996. 14698943Sluigi */ 14798943Sluigistatic int 14898943Sluigiinet_pton6(src, dst) 14998943Sluigi const char *src; 15098943Sluigi uint8_t *dst; 15198943Sluigi{ 15298943Sluigi static const char xdigits_l[] = "0123456789abcdef", 15398943Sluigi xdigits_u[] = "0123456789ABCDEF"; 15498943Sluigi uint8_t tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; 15598943Sluigi const char *xdigits, *curtok; 15698943Sluigi int ch, saw_xdigit; 15798943Sluigi uint32_t val; 15898943Sluigi 15998943Sluigi memset((tp = tmp), '\0', NS_IN6ADDRSZ); 16098943Sluigi endp = tp + NS_IN6ADDRSZ; 16198943Sluigi colonp = NULL; 16298943Sluigi /* Leading :: requires some special handling. */ 16398943Sluigi if (*src == ':') 16498943Sluigi if (*++src != ':') 16598943Sluigi return (0); 16698943Sluigi curtok = src; 16798943Sluigi saw_xdigit = 0; 16898943Sluigi val = 0; 16998943Sluigi while ((ch = *src++) != '\0') { 17098943Sluigi const char *pch; 17198943Sluigi 17298943Sluigi if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) 17398943Sluigi pch = strchr((xdigits = xdigits_u), ch); 17498943Sluigi if (pch != NULL) { 17598943Sluigi val <<= 4; 17698943Sluigi val |= (pch - xdigits); 17798943Sluigi if (val > 0xffff) 17898943Sluigi return (0); 17998943Sluigi saw_xdigit = 1; 18098943Sluigi continue; 18198943Sluigi } 18298943Sluigi if (ch == ':') { 18398943Sluigi curtok = src; 18498943Sluigi if (!saw_xdigit) { 18598943Sluigi if (colonp) 18698943Sluigi return (0); 18798943Sluigi colonp = tp; 18898943Sluigi continue; 18998943Sluigi } 19098943Sluigi if (tp + NS_INT16SZ > endp) 19198943Sluigi return (0); 19298943Sluigi *tp++ = (uint8_t) (val >> 8) & 0xff; 19398943Sluigi *tp++ = (uint8_t) val & 0xff; 19498943Sluigi saw_xdigit = 0; 19598943Sluigi val = 0; 19698943Sluigi continue; 19798943Sluigi } 19898943Sluigi if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && 19998943Sluigi inet_pton4(curtok, tp) > 0) { 20098943Sluigi tp += NS_INADDRSZ; 20198943Sluigi saw_xdigit = 0; 20298943Sluigi break; /* '\0' was seen by inet_pton4(). */ 203101641Sluigi } 204101641Sluigi return (0); 20598943Sluigi } 20698943Sluigi if (saw_xdigit) { 20798943Sluigi if (tp + NS_INT16SZ > endp) 20898943Sluigi return (0); 20998943Sluigi *tp++ = (uint8_t) (val >> 8) & 0xff; 21098943Sluigi *tp++ = (uint8_t) val & 0xff; 21198943Sluigi } 212141351Sglebius if (colonp != NULL) { 213141351Sglebius /* 21498943Sluigi * Since some memmove()'s erroneously fail to handle 21598943Sluigi * overlapping regions, we'll do the shift by hand. 21698943Sluigi */ 21798943Sluigi const int n = tp - colonp; 21898943Sluigi int i; 21998943Sluigi 22098943Sluigi for (i = 1; i <= n; i++) { 22198943Sluigi endp[- i] = colonp[n - i]; 222136071Sgreen colonp[n - i] = 0; 223136071Sgreen } 224158879Soleg tp = endp; 225158879Soleg } 226136071Sgreen if (tp != endp) 227158879Soleg return (0); 22898943Sluigi memcpy(dst, tmp, NS_IN6ADDRSZ); 22998943Sluigi return (1); 230133600Scsjp} 23198943Sluigi