1251875Speter/* Copyright (c) 1996 by Internet Software Consortium. 2251875Speter * 3251875Speter * Permission to use, copy, modify, and distribute this software for any 4251875Speter * purpose with or without fee is hereby granted, provided that the above 5251875Speter * copyright notice and this permission notice appear in all copies. 6251875Speter * 7251875Speter * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 8251875Speter * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 9251875Speter * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 10251875Speter * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 11251875Speter * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 12251875Speter * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 13251875Speter * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 14251875Speter * SOFTWARE. 15251875Speter */ 16251875Speter 17251875Speter#include "apr_private.h" 18251875Speter#include "apr_arch_networkio.h" 19251875Speter 20251875Speter#if APR_HAVE_SYS_TYPES_H 21251875Speter#include <sys/types.h> 22251875Speter#endif 23251875Speter#if APR_HAVE_SYS_SOCKET_H 24251875Speter#include <sys/socket.h> 25251875Speter#endif 26251875Speter#if APR_HAVE_NETINET_IN_H 27251875Speter#include <netinet/in.h> 28251875Speter#endif 29251875Speter#if APR_HAVE_ARPA_INET_H 30251875Speter#include <arpa/inet.h> 31251875Speter#endif 32251875Speter#include <string.h> 33251875Speter#if APR_HAVE_ERRNO_H 34251875Speter#include <errno.h> 35251875Speter#endif 36251875Speter 37251875Speter#ifndef IN6ADDRSZ 38251875Speter#define IN6ADDRSZ 16 39251875Speter#endif 40251875Speter 41251875Speter#ifndef INT16SZ 42251875Speter#define INT16SZ sizeof(apr_int16_t) 43251875Speter#endif 44251875Speter 45251875Speter#ifndef INADDRSZ 46251875Speter#define INADDRSZ 4 47251875Speter#endif 48251875Speter 49251875Speter#ifndef __P 50251875Speter#define __P(x) x 51251875Speter#endif 52251875Speter 53251875Speter#if !defined(EAFNOSUPPORT) && defined(WSAEAFNOSUPPORT) 54251875Speter#define EAFNOSUPPORT WSAEAFNOSUPPORT 55251875Speter#endif 56251875Speter 57251875Speter/* 58251875Speter * WARNING: Don't even consider trying to compile this on a system where 59251875Speter * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. 60251875Speter */ 61251875Speter 62251875Speterstatic int inet_pton4 __P((const char *src, unsigned char *dst)); 63251875Speter#if APR_HAVE_IPV6 64251875Speterstatic int inet_pton6 __P((const char *src, unsigned char *dst)); 65251875Speter#endif 66251875Speter 67251875Speter/* int 68251875Speter * inet_pton(af, src, dst) 69251875Speter * convert from presentation format (which usually means ASCII printable) 70251875Speter * to network format (which is usually some kind of binary format). 71251875Speter * return: 72251875Speter * 1 if the address was valid for the specified address family 73251875Speter * 0 if the address wasn't valid (`dst' is untouched in this case) 74251875Speter * -1 if some other error occurred (`dst' is untouched in this case, too) 75251875Speter * author: 76251875Speter * Paul Vixie, 1996. 77251875Speter */ 78251875Speterint 79251875Speterapr_inet_pton(int af, const char *src, void *dst) 80251875Speter{ 81251875Speter switch (af) { 82251875Speter case AF_INET: 83251875Speter return (inet_pton4(src, dst)); 84251875Speter#if APR_HAVE_IPV6 85251875Speter case AF_INET6: 86251875Speter return (inet_pton6(src, dst)); 87251875Speter#endif 88251875Speter default: 89251875Speter errno = EAFNOSUPPORT; 90251875Speter return (-1); 91251875Speter } 92251875Speter /* NOTREACHED */ 93251875Speter} 94251875Speter 95251875Speter/* int 96251875Speter * inet_pton4(src, dst) 97251875Speter * like inet_aton() but without all the hexadecimal and shorthand. 98251875Speter * return: 99251875Speter * 1 if `src' is a valid dotted quad, else 0. 100251875Speter * notice: 101251875Speter * does not touch `dst' unless it's returning 1. 102251875Speter * author: 103251875Speter * Paul Vixie, 1996. 104251875Speter */ 105251875Speterstatic int 106251875Speterinet_pton4(const char *src, unsigned char *dst) 107251875Speter{ 108251875Speter static const char digits[] = "0123456789"; 109251875Speter int saw_digit, octets, ch; 110251875Speter unsigned char tmp[INADDRSZ], *tp; 111251875Speter 112251875Speter saw_digit = 0; 113251875Speter octets = 0; 114251875Speter *(tp = tmp) = 0; 115251875Speter while ((ch = *src++) != '\0') { 116251875Speter const char *pch; 117251875Speter 118251875Speter if ((pch = strchr(digits, ch)) != NULL) { 119251875Speter unsigned int new = *tp * 10 + (unsigned int)(pch - digits); 120251875Speter 121251875Speter if (new > 255) 122251875Speter return (0); 123251875Speter *tp = new; 124251875Speter if (! saw_digit) { 125251875Speter if (++octets > 4) 126251875Speter return (0); 127251875Speter saw_digit = 1; 128251875Speter } 129251875Speter } else if (ch == '.' && saw_digit) { 130251875Speter if (octets == 4) 131251875Speter return (0); 132251875Speter *++tp = 0; 133251875Speter saw_digit = 0; 134251875Speter } else 135251875Speter return (0); 136251875Speter } 137251875Speter if (octets < 4) 138251875Speter return (0); 139251875Speter 140251875Speter memcpy(dst, tmp, INADDRSZ); 141251875Speter return (1); 142251875Speter} 143251875Speter 144251875Speter#if APR_HAVE_IPV6 145251875Speter/* int 146251875Speter * inet_pton6(src, dst) 147251875Speter * convert presentation level address to network order binary form. 148251875Speter * return: 149251875Speter * 1 if `src' is a valid [RFC1884 2.2] address, else 0. 150251875Speter * notice: 151251875Speter * (1) does not touch `dst' unless it's returning 1. 152251875Speter * (2) :: in a full address is silently ignored. 153251875Speter * credit: 154251875Speter * inspired by Mark Andrews. 155251875Speter * author: 156251875Speter * Paul Vixie, 1996. 157251875Speter */ 158251875Speterstatic int 159251875Speterinet_pton6(const char *src, unsigned char *dst) 160251875Speter{ 161251875Speter static const char xdigits_l[] = "0123456789abcdef", 162251875Speter xdigits_u[] = "0123456789ABCDEF"; 163251875Speter unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp; 164251875Speter const char *xdigits, *curtok; 165251875Speter int ch, saw_xdigit; 166251875Speter unsigned int val; 167251875Speter 168251875Speter memset((tp = tmp), '\0', IN6ADDRSZ); 169251875Speter endp = tp + IN6ADDRSZ; 170251875Speter colonp = NULL; 171251875Speter /* Leading :: requires some special handling. */ 172251875Speter if (*src == ':') 173251875Speter if (*++src != ':') 174251875Speter return (0); 175251875Speter curtok = src; 176251875Speter saw_xdigit = 0; 177251875Speter val = 0; 178251875Speter while ((ch = *src++) != '\0') { 179251875Speter const char *pch; 180251875Speter 181251875Speter if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) 182251875Speter pch = strchr((xdigits = xdigits_u), ch); 183251875Speter if (pch != NULL) { 184251875Speter val <<= 4; 185251875Speter val |= (pch - xdigits); 186251875Speter if (val > 0xffff) 187251875Speter return (0); 188251875Speter saw_xdigit = 1; 189251875Speter continue; 190251875Speter } 191251875Speter if (ch == ':') { 192251875Speter curtok = src; 193251875Speter if (!saw_xdigit) { 194251875Speter if (colonp) 195251875Speter return (0); 196251875Speter colonp = tp; 197251875Speter continue; 198251875Speter } 199251875Speter if (tp + INT16SZ > endp) 200251875Speter return (0); 201251875Speter *tp++ = (unsigned char) (val >> 8) & 0xff; 202251875Speter *tp++ = (unsigned char) val & 0xff; 203251875Speter saw_xdigit = 0; 204251875Speter val = 0; 205251875Speter continue; 206251875Speter } 207251875Speter if (ch == '.' && ((tp + INADDRSZ) <= endp) && 208251875Speter inet_pton4(curtok, tp) > 0) { 209251875Speter tp += INADDRSZ; 210251875Speter saw_xdigit = 0; 211251875Speter break; /* '\0' was seen by inet_pton4(). */ 212251875Speter } 213251875Speter return (0); 214251875Speter } 215251875Speter if (saw_xdigit) { 216251875Speter if (tp + INT16SZ > endp) 217251875Speter return (0); 218251875Speter *tp++ = (unsigned char) (val >> 8) & 0xff; 219251875Speter *tp++ = (unsigned char) val & 0xff; 220251875Speter } 221251875Speter if (colonp != NULL) { 222251875Speter /* 223251875Speter * Since some memmove()'s erroneously fail to handle 224251875Speter * overlapping regions, we'll do the shift by hand. 225251875Speter */ 226251875Speter const apr_ssize_t n = tp - colonp; 227251875Speter apr_ssize_t i; 228251875Speter 229251875Speter for (i = 1; i <= n; i++) { 230251875Speter endp[- i] = colonp[n - i]; 231251875Speter colonp[n - i] = 0; 232251875Speter } 233251875Speter tp = endp; 234251875Speter } 235251875Speter if (tp != endp) 236251875Speter return (0); 237251875Speter memcpy(dst, tmp, IN6ADDRSZ); 238251875Speter return (1); 239251875Speter} 240251875Speter#endif 241