diff options
Diffstat (limited to 'src/libfreeswan/ttoaddr.c')
-rw-r--r-- | src/libfreeswan/ttoaddr.c | 471 |
1 files changed, 0 insertions, 471 deletions
diff --git a/src/libfreeswan/ttoaddr.c b/src/libfreeswan/ttoaddr.c deleted file mode 100644 index 234c9d8e7..000000000 --- a/src/libfreeswan/ttoaddr.c +++ /dev/null @@ -1,471 +0,0 @@ -/* - * conversion from text forms of addresses to internal ones - * Copyright (C) 2000 Henry Spencer. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Library General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public - * License for more details. - */ -#include <sys/socket.h> - -#include "internal.h" -#include "freeswan.h" - -/* - * Legal ASCII characters in a domain name. Underscore technically is not, - * but is a common misunderstanding. Non-ASCII characters are simply - * exempted from checking at the moment, to allow for UTF-8 encoded stuff; - * the purpose of this check is merely to catch blatant errors. - */ -static const char namechars[] = "abcdefghijklmnopqrstuvwxyz0123456789" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ-_."; -#define ISASCII(c) (((c) & 0x80) == 0) - -static err_t tryname(const char *, size_t, int, int, ip_address *); -static err_t tryhex(const char *, size_t, int, ip_address *); -static err_t trydotted(const char *, size_t, ip_address *); -static err_t getbyte(const char **, const char *, int *); -static err_t colon(const char *, size_t, ip_address *); -static err_t getpiece(const char **, const char *, unsigned *); - -/* - - ttoaddr - convert text name or dotted-decimal address to binary address - */ -err_t /* NULL for success, else string literal */ -ttoaddr(src, srclen, af, dst) -const char *src; -size_t srclen; /* 0 means "apply strlen" */ -int af; /* address family */ -ip_address *dst; -{ - err_t oops; -# define HEXLEN 10 /* strlen("0x11223344") */ - int nultermd; - - if (srclen == 0) { - srclen = strlen(src); - if (srclen == 0) - return "empty string"; - nultermd = 1; - } else - nultermd = 0; /* at least, not *known* to be terminated */ - - switch (af) { - case AF_INET: - case AF_INET6: - case 0: /* guess */ - break; - - default: - return "invalid address family"; - } - - if (af == AF_INET && srclen == HEXLEN && *src == '0') { - if (*(src+1) == 'x' || *(src+1) == 'X') - return tryhex(src+2, srclen-2, 'x', dst); - if (*(src+1) == 'h' || *(src+1) == 'H') - return tryhex(src+2, srclen-2, 'h', dst); - } - - if (memchr(src, ':', srclen) != NULL) { - if(af == 0) - { - af = AF_INET6; - } - - if (af != AF_INET6) - return "non-ipv6 address may not contain `:'"; - return colon(src, srclen, dst); - } - - if (af == 0 || af == AF_INET) { - oops = trydotted(src, srclen, dst); - if (oops == NULL) - return NULL; /* it worked */ - if (*oops != '?') - return oops; /* probably meant as d-d */ - } - - return tryname(src, srclen, nultermd, af, dst); -} - -/* - - tnatoaddr - convert text numeric address (only) to binary address - */ -err_t /* NULL for success, else string literal */ -tnatoaddr(src, srclen, af, dst) -const char *src; -size_t srclen; /* 0 means "apply strlen" */ -int af; /* address family */ -ip_address *dst; -{ - err_t oops; - - if (srclen == 0) { - srclen = strlen(src); - if (srclen == 0) - return "empty string"; - } - - switch (af) { - case 0: /* guess */ - oops = colon(src, srclen, dst); - if(oops == NULL) - { - return NULL; - } - oops = trydotted(src, srclen, dst); - if(oops == NULL) - { - return NULL; - } - return "does not appear to be either IPv4 or IPv6 numeric address"; - break; - - case AF_INET6: - return colon(src, srclen, dst); - break; - case AF_INET: - oops = trydotted(src, srclen, dst); - if (oops == NULL) - return NULL; /* it worked */ - if (*oops != '?') - return oops; /* probably meant as d-d */ - return "does not appear to be numeric address"; - break; - default: - return "unknown address family in tnatoaddr"; - break; - } -} - -/* - - tryname - try it as a name - * Slightly complicated by lack of reliable NUL termination in source. - */ -static err_t -tryname(src, srclen, nultermd, af, dst) -const char *src; -size_t srclen; -int nultermd; /* is it known to be NUL-terminated? */ -int af; -ip_address *dst; -{ - struct addrinfo hints, *res; - struct netent *ne = NULL; - char namebuf[100]; /* enough for most DNS names */ - const char *cp; - char *p = namebuf; - unsigned char *addr = NULL; - size_t n; - int error; - err_t err = NULL; - - for (cp = src, n = srclen; n > 0; cp++, n--) - if (ISASCII(*cp) && strchr(namechars, *cp) == NULL) - return "illegal (non-DNS-name) character in name"; - - if (nultermd) - cp = src; - else { - if (srclen+1 > sizeof(namebuf)) { - p = (char *) MALLOC(srclen+1); - if (p == NULL) - return "unable to get temporary space for name"; - } - p[0] = '\0'; /* strncpy semantics are wrong */ - strncat(p, src, srclen); - cp = (const char *)p; - } - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = af; - error = getaddrinfo(cp, NULL, &hints, &res); - if (error != 0) - { /* getaddrinfo failed, try getnetbyname */ - if (af == AF_INET) - { - ne = getnetbyname(cp); - if (ne != NULL) - { - ne->n_net = htonl(ne->n_net); - addr = (unsigned char*)&ne->n_net; - err = initaddr(addr, sizeof(ne->n_net), af, dst); - } - } - } - else - { - struct addrinfo *r = res; - while (r) - { - size_t addr_len; - switch (r->ai_family) - { - case AF_INET: - { - struct sockaddr_in *in = (struct sockaddr_in*)r->ai_addr; - addr_len = 4; - addr = (unsigned char*)&in->sin_addr.s_addr; - break; - } - case AF_INET6: - { - struct sockaddr_in6 *in6 = (struct sockaddr_in6*)r->ai_addr; - addr_len = 16; - addr = (unsigned char*)&in6->sin6_addr.s6_addr; - break; - } - default: - { /* unknown family, try next result */ - r = r->ai_next; - continue; - } - } - err = initaddr(addr, addr_len, r->ai_family, dst); - break; - } - freeaddrinfo(res); - } - - if (p != namebuf) - { - FREE(p); - } - - if (addr == NULL) - { - return "does not look numeric and name lookup failed"; - } - - return err; -} - -/* - - tryhex - try conversion as an eight-digit hex number (AF_INET only) - */ -static err_t -tryhex(src, srclen, flavor, dst) -const char *src; -size_t srclen; /* should be 8 */ -int flavor; /* 'x' for network order, 'h' for host order */ -ip_address *dst; -{ - err_t oops; - unsigned long ul; - union { - uint32_t addr; - unsigned char buf[4]; - } u; - - if (srclen != 8) - return "internal error, tryhex called with bad length"; - - oops = ttoul(src, srclen, 16, &ul); - if (oops != NULL) - return oops; - - u.addr = (flavor == 'h') ? ul : htonl(ul); - return initaddr(u.buf, sizeof(u.buf), AF_INET, dst); -} - -/* - - trydotted - try conversion as dotted decimal (AF_INET only) - * - * If the first char of a complaint is '?', that means "didn't look like - * dotted decimal at all". - */ -static err_t -trydotted(src, srclen, dst) -const char *src; -size_t srclen; -ip_address *dst; -{ - const char *stop = src + srclen; /* just past end */ - int byte; - err_t oops; -# define NBYTES 4 - unsigned char buf[NBYTES]; - int i; - - memset(buf, 0, sizeof(buf)); - for (i = 0; i < NBYTES && src < stop; i++) { - oops = getbyte(&src, stop, &byte); - if (oops != NULL) { - if (*oops != '?') - return oops; /* bad number */ - if (i > 1) - return oops+1; /* failed number */ - return oops; /* with leading '?' */ - } - buf[i] = byte; - if (i < 3 && src < stop && *src++ != '.') { - if (i == 0) - return "?syntax error in dotted-decimal address"; - else - return "syntax error in dotted-decimal address"; - } - } - if (src != stop) - return "extra garbage on end of dotted-decimal address"; - - return initaddr(buf, sizeof(buf), AF_INET, dst); -} - -/* - - getbyte - try to scan a byte in dotted decimal - * A subtlety here is that all this arithmetic on ASCII digits really is - * highly portable -- ANSI C guarantees that digits 0-9 are contiguous. - * It's easier to just do it ourselves than set up for a call to ttoul(). - * - * If the first char of a complaint is '?', that means "didn't look like a - * number at all". - */ -err_t -getbyte(srcp, stop, retp) -const char **srcp; /* *srcp is updated */ -const char *stop; /* first untouchable char */ -int *retp; /* return-value pointer */ -{ - char c; - const char *p; - int no; - - if (*srcp >= stop) - return "?empty number in dotted-decimal address"; - - no = 0; - p = *srcp; - while (p < stop && no <= 255 && (c = *p) >= '0' && c <= '9') { - no = no*10 + (c - '0'); - p++; - } - if (p == *srcp) - return "?non-numeric component in dotted-decimal address"; - *srcp = p; - if (no > 255) - return "byte overflow in dotted-decimal address"; - *retp = no; - return NULL; -} - -/* - - colon - convert IPv6 "numeric" address - */ -static err_t -colon(src, srclen, dst) -const char *src; -size_t srclen; /* known to be >0 */ -ip_address *dst; -{ - const char *stop = src + srclen; /* just past end */ - unsigned piece = 0; - int gapat; /* where was empty piece seen */ - err_t oops; -# define NPIECES 8 - unsigned char buf[NPIECES*2]; /* short may have wrong byte order */ - int i; - int j; -# define IT "IPv6 numeric address" - int naftergap; - - /* leading or trailing :: becomes single empty field */ - if (*src == ':') { /* legal only if leading :: */ - if (srclen == 1 || *(src+1) != ':') - return "illegal leading `:' in " IT; - if (srclen == 2) { - unspecaddr(AF_INET6, dst); - return NULL; - } - src++; /* past first but not second */ - srclen--; - } - if (*(stop-1) == ':') { /* legal only if trailing :: */ - if (srclen == 1 || *(stop-2) != ':') - return "illegal trailing `:' in " IT; - srclen--; /* leave one */ - } - - gapat = -1; - for (i = 0; i < NPIECES && src < stop; i++) { - oops = getpiece(&src, stop, &piece); - if (oops != NULL && *oops == ':') { /* empty field */ - if (gapat >= 0) - return "more than one :: in " IT; - gapat = i; - } else if (oops != NULL) - return oops; - buf[2*i] = piece >> 8; - buf[2*i + 1] = piece & 0xff; - if (i < NPIECES-1) { /* there should be more input */ - if (src == stop && gapat < 0) - return IT " ends prematurely"; - if (src != stop && *src++ != ':') - return "syntax error in " IT; - } - } - if (src != stop) - return "extra garbage on end of " IT; - - if (gapat < 0 && i < NPIECES) /* should have been caught earlier */ - return "incomplete " IT " (internal error)"; - if (gapat >= 0 && i == NPIECES) - return "non-abbreviating empty field in " IT; - if (gapat >= 0) { - naftergap = i - (gapat + 1); - for (i--, j = NPIECES-1; naftergap > 0; i--, j--, naftergap--) { - buf[2*j] = buf[2*i]; - buf[2*j + 1] = buf[2*i + 1]; - } - for (; j >= gapat; j--) - buf[2*j] = buf[2*j + 1] = 0; - } - - return initaddr(buf, sizeof(buf), AF_INET6, dst); -} - -/* - - getpiece - try to scan one 16-bit piece of an IPv6 address - */ -err_t /* ":" means "empty field seen" */ -getpiece(srcp, stop, retp) -const char **srcp; /* *srcp is updated */ -const char *stop; /* first untouchable char */ -unsigned *retp; /* return-value pointer */ -{ - const char *p; -# define NDIG 4 - int d; - unsigned long ret; - err_t oops; - - if (*srcp >= stop || **srcp == ':') { /* empty field */ - *retp = 0; - return ":"; - } - - p = *srcp; - d = 0; - while (p < stop && d < NDIG && isxdigit(*p)) { - p++; - d++; - } - if (d == 0) - return "non-hex field in IPv6 numeric address"; - if (p < stop && d == NDIG && isxdigit(*p)) - return "field in IPv6 numeric address longer than 4 hex digits"; - - oops = ttoul(*srcp, d, 16, &ret); - if (oops != NULL) /* shouldn't happen, really... */ - return oops; - - *srcp = p; - *retp = ret; - return NULL; -} |