Files
strongswan-ext/linux/lib/libfreeswan/addrtot.c
T
Martin Willi 997358a6c4 - import of strongswan-2.7.0
- applied patch for charon
2006-04-28 07:14:48 +00:00

303 lines
7.1 KiB
C

/*
* addresses to text
* 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.
*
* RCSID $Id: addrtot.c,v 1.1 2004/03/15 20:35:25 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
#define IP4BYTES 4 /* bytes in an IPv4 address */
#define PERBYTE 4 /* three digits plus a dot or NUL */
#define IP6BYTES 16 /* bytes in an IPv6 address */
/* forwards */
static size_t normal4(const unsigned char *s, size_t len, char *b, char **dp);
static size_t normal6(const unsigned char *s, size_t len, char *b, char **dp, int squish);
static size_t reverse4(const unsigned char *s, size_t len, char *b, char **dp);
static size_t reverse6(const unsigned char *s, size_t len, char *b, char **dp);
/*
- addrtot - convert binary address to text (dotted decimal or IPv6 string)
*/
size_t /* space needed for full conversion */
addrtot(src, format, dst, dstlen)
const ip_address *src;
int format; /* character */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
const unsigned char *b;
size_t n;
char buf[1+ADDRTOT_BUF+1]; /* :address: */
char *p;
int t = addrtypeof(src);
# define TF(t, f) (((t)<<8) | (f))
n = addrbytesptr(src, &b);
if (n == 0)
return 0;
switch (TF(t, format)) {
case TF(AF_INET, 0):
n = normal4(b, n, buf, &p);
break;
case TF(AF_INET6, 0):
n = normal6(b, n, buf, &p, 1);
break;
case TF(AF_INET, 'Q'):
n = normal4(b, n, buf, &p);
break;
case TF(AF_INET6, 'Q'):
n = normal6(b, n, buf, &p, 0);
break;
case TF(AF_INET, 'r'):
n = reverse4(b, n, buf, &p);
break;
case TF(AF_INET6, 'r'):
n = reverse6(b, n, buf, &p);
break;
default: /* including (AF_INET, 'R') */
return 0;
break;
}
if (dstlen > 0) {
if (dstlen < n)
p[dstlen - 1] = '\0';
strcpy(dst, p);
}
return n;
}
/*
- normal4 - normal IPv4 address-text conversion
*/
static size_t /* size of text, including NUL */
normal4(srcp, srclen, buf, dstp)
const unsigned char *srcp;
size_t srclen;
char *buf; /* guaranteed large enough */
char **dstp; /* where to put result pointer */
{
int i;
char *p;
if (srclen != IP4BYTES) /* "can't happen" */
return 0;
p = buf;
for (i = 0; i < IP4BYTES; i++) {
p += ultot(srcp[i], 10, p, PERBYTE);
if (i != IP4BYTES - 1)
*(p-1) = '.'; /* overwrites the NUL */
}
*dstp = buf;
return p - buf;
}
/*
- normal6 - normal IPv6 address-text conversion
*/
static size_t /* size of text, including NUL */
normal6(srcp, srclen, buf, dstp, squish)
const unsigned char *srcp;
size_t srclen;
char *buf; /* guaranteed large enough, plus 2 */
char **dstp; /* where to put result pointer */
int squish; /* whether to squish out 0:0 */
{
int i;
unsigned long piece;
char *p;
char *q;
if (srclen != IP6BYTES) /* "can't happen" */
return 0;
p = buf;
*p++ = ':';
for (i = 0; i < IP6BYTES/2; i++) {
piece = (srcp[2*i] << 8) + srcp[2*i + 1];
p += ultot(piece, 16, p, 5); /* 5 = abcd + NUL */
*(p-1) = ':'; /* overwrites the NUL */
}
*p = '\0';
q = strstr(buf, ":0:0:");
if (squish && q != NULL) { /* zero squishing is possible */
p = q + 1;
while (*p == '0' && *(p+1) == ':')
p += 2;
q++;
*q++ = ':'; /* overwrite first 0 */
while (*p != '\0')
*q++ = *p++;
*q = '\0';
if (!(*(q-1) == ':' && *(q-2) == ':'))
*--q = '\0'; /* strip final : unless :: */
p = buf;
if (!(*p == ':' && *(p+1) == ':'))
p++; /* skip initial : unless :: */
} else {
q = p;
*--q = '\0'; /* strip final : */
p = buf + 1; /* skip initial : */
}
*dstp = p;
return q - p + 1;
}
/*
- reverse4 - IPv4 reverse-lookup conversion
*/
static size_t /* size of text, including NUL */
reverse4(srcp, srclen, buf, dstp)
const unsigned char *srcp;
size_t srclen;
char *buf; /* guaranteed large enough */
char **dstp; /* where to put result pointer */
{
int i;
char *p;
if (srclen != IP4BYTES) /* "can't happen" */
return 0;
p = buf;
for (i = IP4BYTES-1; i >= 0; i--) {
p += ultot(srcp[i], 10, p, PERBYTE);
*(p-1) = '.'; /* overwrites the NUL */
}
strcpy(p, "IN-ADDR.ARPA.");
*dstp = buf;
return strlen(buf) + 1;
}
/*
- reverse6 - IPv6 reverse-lookup conversion (RFC 1886)
* A trifle inefficient, really shouldn't use ultot...
*/
static size_t /* size of text, including NUL */
reverse6(srcp, srclen, buf, dstp)
const unsigned char *srcp;
size_t srclen;
char *buf; /* guaranteed large enough */
char **dstp; /* where to put result pointer */
{
int i;
unsigned long piece;
char *p;
if (srclen != IP6BYTES) /* "can't happen" */
return 0;
p = buf;
for (i = IP6BYTES-1; i >= 0; i--) {
piece = srcp[i];
p += ultot(piece&0xf, 16, p, 2);
*(p-1) = '.';
p += ultot(piece>>4, 16, p, 2);
*(p-1) = '.';
}
strcpy(p, "IP6.ARPA.");
*dstp = buf;
return strlen(buf) + 1;
}
/*
- reverse6 - modern IPv6 reverse-lookup conversion (RFC 2874)
* this version removed as it was obsoleted in the end.
*/
#ifdef ADDRTOT_MAIN
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void regress(void);
int
main(int argc, char *argv[])
{
if (argc < 2) {
fprintf(stderr, "Usage: %s {addr|net/mask|begin...end|-r}\n",
argv[0]);
exit(2);
}
if (strcmp(argv[1], "-r") == 0) {
regress();
fprintf(stderr, "regress() returned?!?\n");
exit(1);
}
exit(0);
}
struct rtab {
char *input;
char format;
char *output; /* NULL means error expected */
} rtab[] = {
{"1.2.3.0", 0, "1.2.3.0"},
{"1:2::3:4", 0, "1:2::3:4"},
{"1:2::3:4", 'Q', "1:2:0:0:0:0:3:4"},
{"1:2:0:0:3:4:0:0", 0, "1:2::3:4:0:0"},
{"1.2.3.4", 'r' , "4.3.2.1.IN-ADDR.ARPA."},
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f */
{"1:2::3:4", 'r', "4.0.0.0.3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.1.0.0.0.IP6.ARPA."},
{NULL, 0, NULL}
};
void
regress()
{
struct rtab *r;
int status = 0;
ip_address a;
char in[100];
char buf[100];
const char *oops;
size_t n;
for (r = rtab; r->input != NULL; r++) {
strcpy(in, r->input);
/* convert it *to* internal format */
oops = ttoaddr(in, strlen(in), 0, &a);
/* now convert it back */
n = addrtot(&a, r->format, buf, sizeof(buf));
if (n == 0 && r->output == NULL)
{} /* okay, error expected */
else if (n == 0) {
printf("`%s' atoasr failed\n", r->input);
status = 1;
} else if (r->output == NULL) {
printf("`%s' atoasr succeeded unexpectedly '%c'\n",
r->input, r->format);
status = 1;
} else {
if (strcasecmp(r->output, buf) != 0) {
printf("`%s' '%c' gave `%s', expected `%s'\n",
r->input, r->format, buf, r->output);
status = 1;
}
}
}
exit(status);
}
#endif /* ADDRTOT_MAIN */