summaryrefslogtreecommitdiff
path: root/src/libfreeswan/ttoaddr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libfreeswan/ttoaddr.c')
-rw-r--r--src/libfreeswan/ttoaddr.c471
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;
-}