- import of strongswan-2.7.0

- applied patch for charon
This commit is contained in:
Martin Willi
2006-04-28 07:14:48 +00:00
parent 52923c9acb
commit 997358a6c4
2043 changed files with 346842 additions and 0 deletions
+18
View File
@@ -0,0 +1,18 @@
obj-y += ultoa.o
obj-y += addrtoa.o
obj-y += subnettoa.o
obj-y += subnetof.o
obj-y += goodmask.o
obj-y += datatot.o
obj-y += rangetoa.o
obj-y += satoa.o
obj-y += prng.o
obj-y += pfkey_v2_parse.o
obj-y += pfkey_v2_build.o
obj-y += pfkey_v2_debug.o
obj-y += pfkey_v2_ext_bits.o
obj-y += version.o
version.c: ${LIBFREESWANDIR}/version.in.c ${FREESWANSRCDIR}/Makefile.ver
sed '/"/s/xxx/$(IPSECVERSION)/' ${LIBFREESWANDIR}/version.in.c >$@
+68
View File
@@ -0,0 +1,68 @@
/*
* addresses to ASCII
* Copyright (C) 1998, 1999 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: addrtoa.c,v 1.1 2004/03/15 20:35:25 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
#define NBYTES 4 /* bytes in an address */
#define PERBYTE 4 /* three digits plus a dot or NUL */
#define BUFLEN (NBYTES*PERBYTE)
#if BUFLEN != ADDRTOA_BUF
#error "ADDRTOA_BUF in freeswan.h inconsistent with addrtoa() code"
#endif
/*
- addrtoa - convert binary address to ASCII dotted decimal
*/
size_t /* space needed for full conversion */
addrtoa(addr, format, dst, dstlen)
struct in_addr addr;
int format; /* character */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
unsigned long a = ntohl(addr.s_addr);
int i;
size_t n;
unsigned long byte;
char buf[BUFLEN];
char *p;
switch (format) {
case 0:
break;
default:
return 0;
break;
}
p = buf;
for (i = NBYTES-1; i >= 0; i--) {
byte = (a >> (i*8)) & 0xff;
p += ultoa(byte, 10, p, PERBYTE);
if (i != 0)
*(p-1) = '.';
}
n = p - buf;
if (dstlen > 0) {
if (n > dstlen)
buf[dstlen - 1] = '\0';
strcpy(dst, buf);
}
return n;
}
+302
View File
@@ -0,0 +1,302 @@
/*
* 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 */
+94
View File
@@ -0,0 +1,94 @@
/*
* extract parts of an ip_address
* 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: addrtypeof.c,v 1.1 2004/03/15 20:35:25 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
- addrtypeof - get the type of an ip_address
*/
int
addrtypeof(src)
const ip_address *src;
{
return src->u.v4.sin_family;
}
/*
- addrbytesptr - get pointer to the address bytes of an ip_address
*/
size_t /* 0 for error */
addrbytesptr(src, dstp)
const ip_address *src;
const unsigned char **dstp; /* NULL means just a size query */
{
const unsigned char *p;
size_t n;
switch (src->u.v4.sin_family) {
case AF_INET:
p = (const unsigned char *)&src->u.v4.sin_addr.s_addr;
n = 4;
break;
case AF_INET6:
p = (const unsigned char *)&src->u.v6.sin6_addr;
n = 16;
break;
default:
return 0;
break;
}
if (dstp != NULL)
*dstp = p;
return n;
}
/*
- addrlenof - get length of the address bytes of an ip_address
*/
size_t /* 0 for error */
addrlenof(src)
const ip_address *src;
{
return addrbytesptr(src, NULL);
}
/*
- addrbytesof - get the address bytes of an ip_address
*/
size_t /* 0 for error */
addrbytesof(src, dst, dstlen)
const ip_address *src;
unsigned char *dst;
size_t dstlen;
{
const unsigned char *p;
size_t n;
size_t ncopy;
n = addrbytesptr(src, &p);
if (n == 0)
return 0;
if (dstlen > 0) {
ncopy = n;
if (ncopy > dstlen)
ncopy = dstlen;
memcpy(dst, p, ncopy);
}
return n;
}
+87
View File
@@ -0,0 +1,87 @@
.TH IPSEC_ANYADDR 3 "8 Sept 2000"
.\" RCSID $Id: anyaddr.3,v 1.1 2004/03/15 20:35:25 as Exp $
.SH NAME
ipsec anyaddr \- get "any" address
.br
ipsec isanyaddr \- test address for equality to "any" address
.br
ipsec unspecaddr \- get "unspecified" address
.br
ipsec isunspecaddr \- test address for equality to "unspecified" address
.br
ipsec loopbackaddr \- get loopback address
.br
ipsec isloopbackaddr \- test address for equality to loopback address
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "const char *anyaddr(int af, ip_address *dst);"
.br
.B "int isanyaddr(const ip_address *src);"
.br
.B "const char *unspecaddr(int af, ip_address *dst);"
.br
.B "int isunspecaddr(const ip_address *src);"
.br
.B "const char *loopbackaddr(int af, ip_address *dst);"
.br
.B "int isloopbackaddr(const ip_address *src);"
.SH DESCRIPTION
These functions fill in, and test for, special values of the
.I ip_address
type.
.PP
.I Anyaddr
fills in the destination
.I *dst
with the ``any'' address of address family
.IR af
(normally
.B AF_INET
or
.BR AF_INET6 ).
The IPv4 ``any'' address is the one embodied in the old
.B INADDR_ANY
macro.
.PP
.I Isanyaddr
returns
.B 1
if the
.I src
address equals the ``any'' address,
and
.B 0
otherwise.
.PP
Similarly,
.I unspecaddr
supplies, and
.I isunspecaddr
tests for,
the ``unspecified'' address,
which may be the same as the ``any'' address.
.PP
Similarly,
.I loopbackaddr
supplies, and
.I islookbackaddr
tests for,
the loopback address.
.PP
.IR Anyaddr ,
.IR unspecaddr ,
and
.I loopbackaddr
return
.B NULL
for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
.SH SEE ALSO
inet(3), ipsec_addrtot(3), ipsec_sameaddr(3)
.SH DIAGNOSTICS
Fatal errors in the address-supplying functions are:
unknown address family.
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
+146
View File
@@ -0,0 +1,146 @@
/*
* special addresses
* 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: anyaddr.c,v 1.1 2004/03/15 20:35:25 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/* these are mostly fallbacks for the no-IPv6-support-in-library case */
#ifndef IN6ADDR_ANY_INIT
#define IN6ADDR_ANY_INIT {{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }}
#endif
#ifndef IN6ADDR_LOOPBACK_INIT
#define IN6ADDR_LOOPBACK_INIT {{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }}
#endif
static struct in6_addr v6any = IN6ADDR_ANY_INIT;
static struct in6_addr v6loop = IN6ADDR_LOOPBACK_INIT;
/*
- anyaddr - initialize to the any-address value
*/
err_t /* NULL for success, else string literal */
anyaddr(af, dst)
int af; /* address family */
ip_address *dst;
{
uint32_t v4any = htonl(INADDR_ANY);
switch (af) {
case AF_INET:
return initaddr((unsigned char *)&v4any, sizeof(v4any), af, dst);
break;
case AF_INET6:
return initaddr((unsigned char *)&v6any, sizeof(v6any), af, dst);
break;
default:
return "unknown address family in anyaddr/unspecaddr";
break;
}
}
/*
- unspecaddr - initialize to the unspecified-address value
*/
err_t /* NULL for success, else string literal */
unspecaddr(af, dst)
int af; /* address family */
ip_address *dst;
{
return anyaddr(af, dst);
}
/*
- loopbackaddr - initialize to the loopback-address value
*/
err_t /* NULL for success, else string literal */
loopbackaddr(af, dst)
int af; /* address family */
ip_address *dst;
{
uint32_t v4loop = htonl(INADDR_LOOPBACK);
switch (af) {
case AF_INET:
return initaddr((unsigned char *)&v4loop, sizeof(v4loop), af, dst);
break;
case AF_INET6:
return initaddr((unsigned char *)&v6loop, sizeof(v6loop), af, dst);
break;
default:
return "unknown address family in loopbackaddr";
break;
}
}
/*
- isanyaddr - test for the any-address value
*/
int
isanyaddr(src)
const ip_address *src;
{
uint32_t v4any = htonl(INADDR_ANY);
int cmp;
switch (src->u.v4.sin_family) {
case AF_INET:
cmp = memcmp(&src->u.v4.sin_addr.s_addr, &v4any, sizeof(v4any));
break;
case AF_INET6:
cmp = memcmp(&src->u.v6.sin6_addr, &v6any, sizeof(v6any));
break;
default:
return 0;
break;
}
return (cmp == 0) ? 1 : 0;
}
/*
- isunspecaddr - test for the unspecified-address value
*/
int
isunspecaddr(src)
const ip_address *src;
{
return isanyaddr(src);
}
/*
- isloopbackaddr - test for the loopback-address value
*/
int
isloopbackaddr(src)
const ip_address *src;
{
uint32_t v4loop = htonl(INADDR_LOOPBACK);
int cmp;
switch (src->u.v4.sin_family) {
case AF_INET:
cmp = memcmp(&src->u.v4.sin_addr.s_addr, &v4loop, sizeof(v4loop));
break;
case AF_INET6:
cmp = memcmp(&src->u.v6.sin6_addr, &v6loop, sizeof(v6loop));
break;
default:
return 0;
break;
}
return (cmp == 0) ? 1 : 0;
}
+294
View File
@@ -0,0 +1,294 @@
.TH IPSEC_ATOADDR 3 "11 June 2001"
.\" RCSID $Id: atoaddr.3,v 1.1 2004/03/15 20:35:25 as Exp $
.SH NAME
ipsec atoaddr, addrtoa \- convert Internet addresses to and from ASCII
.br
ipsec atosubnet, subnettoa \- convert subnet/mask ASCII form to and from addresses
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "const char *atoaddr(const char *src, size_t srclen,"
.ti +1c
.B "struct in_addr *addr);"
.br
.B "size_t addrtoa(struct in_addr addr, int format,"
.ti +1c
.B "char *dst, size_t dstlen);"
.sp
.B "const char *atosubnet(const char *src, size_t srclen,"
.ti +1c
.B "struct in_addr *addr, struct in_addr *mask);"
.br
.B "size_t subnettoa(struct in_addr addr, struct in_addr mask,"
.ti +1c
.B "int format, char *dst, size_t dstlen);"
.SH DESCRIPTION
These functions are obsolete; see
.IR ipsec_ttoaddr (3)
for their replacements.
.PP
.I Atoaddr
converts an ASCII name or dotted-decimal address into a binary address
(in network byte order).
.I Addrtoa
does the reverse conversion, back to an ASCII dotted-decimal address.
.I Atosubnet
and
.I subnettoa
do likewise for the ``address/mask'' ASCII form used to write a
specification of a subnet.
.PP
An address is specified in ASCII as a
dotted-decimal address (e.g.
.BR 1.2.3.4 ),
an eight-digit network-order hexadecimal number with the usual C prefix (e.g.
.BR 0x01020304 ,
which is synonymous with
.BR 1.2.3.4 ),
an eight-digit host-order hexadecimal number with a
.B 0h
prefix (e.g.
.BR 0h01020304 ,
which is synonymous with
.B 1.2.3.4
on a big-endian host and
.B 4.3.2.1
on a little-endian host),
a DNS name to be looked up via
.IR gethostbyname (3),
or an old-style network name to be looked up via
.IR getnetbyname (3).
.PP
A dotted-decimal address may be incomplete, in which case
ASCII-to-binary conversion implicitly appends
as many instances of
.B .0
as necessary to bring it up to four components.
The components of a dotted-decimal address are always taken as
decimal, and leading zeros are ignored.
For example,
.B 10
is synonymous with
.BR 10.0.0.0 ,
and
.B 128.009.000.032
is synonymous with
.BR 128.9.0.32
(the latter example is verbatim from RFC 1166).
The result of
.I addrtoa
is always complete and does not contain leading zeros.
.PP
The letters in
a hexadecimal address may be uppercase or lowercase or any mixture thereof.
Use of hexadecimal addresses is
.B strongly
.BR discouraged ;
they are included only to save hassles when dealing with
the handful of perverted programs which already print
network addresses in hexadecimal.
.PP
DNS names may be complete (optionally terminated with a ``.'')
or incomplete, and are looked up as specified by local system configuration
(see
.IR resolver (5)).
The
.I h_addr
value returned by
.IR gethostbyname (3)
is used,
so with current DNS implementations,
the result when the name corresponds to more than one address is
difficult to predict.
Name lookup resorts to
.IR getnetbyname (3)
only if
.IR gethostbyname (3)
fails.
.PP
A subnet specification is of the form \fInetwork\fB/\fImask\fR.
The
.I network
and
.I mask
can be any form acceptable to
.IR atoaddr .
In addition, the
.I mask
can be a decimal integer (leading zeros ignored) giving a bit count,
in which case
it stands for a mask with that number of high bits on and all others off
(e.g.,
.B 24
means
.BR 255.255.255.0 ).
In any case, the mask must be contiguous
(a sequence of high bits on and all remaining low bits off).
As a special case, the subnet specification
.B %default
is a synonym for
.BR 0.0.0.0/0 .
.PP
.I Atosubnet
ANDs the mask with the address before returning,
so that any non-network bits in the address are turned off
(e.g.,
.B 10.1.2.3/24
is synonymous with
.BR 10.1.2.0/24 ).
.I Subnettoa
generates the decimal-integer-bit-count
form of the mask,
with no leading zeros,
unless the mask is non-contiguous.
.PP
The
.I srclen
parameter of
.I atoaddr
and
.I atosubnet
specifies the length of the ASCII string pointed to by
.IR src ;
it is an error for there to be anything else
(e.g., a terminating NUL) within that length.
As a convenience for cases where an entire NUL-terminated string is
to be converted,
a
.I srclen
value of
.B 0
is taken to mean
.BR strlen(src) .
.PP
The
.I dstlen
parameter of
.I addrtoa
and
.I subnettoa
specifies the size of the
.I dst
parameter;
under no circumstances are more than
.I dstlen
bytes written to
.IR dst .
A result which will not fit is truncated.
.I Dstlen
can be zero, in which case
.I dst
need not be valid and no result is written,
but the return value is unaffected;
in all other cases, the (possibly truncated) result is NUL-terminated.
The
.I freeswan.h
header file defines constants,
.B ADDRTOA_BUF
and
.BR SUBNETTOA_BUF ,
which are the sizes of buffers just large enough for worst-case results.
.PP
The
.I format
parameter of
.I addrtoa
and
.I subnettoa
specifies what format is to be used for the conversion.
The value
.B 0
(not the ASCII character
.BR '0' ,
but a zero value)
specifies a reasonable default,
and is in fact the only format currently available.
This parameter is a hedge against future needs.
.PP
The ASCII-to-binary functions return NULL for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
The binary-to-ASCII functions return
.B 0
for a failure, and otherwise
always return the size of buffer which would
be needed to
accommodate the full conversion result, including terminating NUL;
it is the caller's responsibility to check this against the size of
the provided buffer to determine whether truncation has occurred.
.SH SEE ALSO
inet(3)
.SH DIAGNOSTICS
Fatal errors in
.I atoaddr
are:
empty input;
attempt to allocate temporary storage for a very long name failed;
name lookup failed;
syntax error in dotted-decimal form;
dotted-decimal component too large to fit in 8 bits.
.PP
Fatal errors in
.I atosubnet
are:
no
.B /
in
.IR src ;
.I atoaddr
error in conversion of
.I network
or
.IR mask ;
bit-count mask too big;
mask non-contiguous.
.PP
Fatal errors in
.I addrtoa
and
.I subnettoa
are:
unknown format.
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
The interpretation of incomplete dotted-decimal addresses
(e.g.
.B 10/24
means
.BR 10.0.0.0/24 )
differs from that of some older conversion
functions, e.g. those of
.IR inet (3).
The behavior of the older functions has never been
particularly consistent or particularly useful.
.PP
Ignoring leading zeros in dotted-decimal components and bit counts
is arguably the most useful behavior in this application,
but it might occasionally cause confusion with the historical use of leading
zeros to denote octal numbers.
.PP
It is barely possible that somebody, somewhere,
might have a legitimate use for non-contiguous subnet masks.
.PP
.IR Getnetbyname (3)
is a historical dreg.
.PP
The restriction of ASCII-to-binary error reports to literal strings
(so that callers don't need to worry about freeing them or copying them)
does limit the precision of error reporting.
.PP
The ASCII-to-binary error-reporting convention lends itself
to slightly obscure code,
because many readers will not think of NULL as signifying success.
A good way to make it clearer is to write something like:
.PP
.RS
.nf
.B "const char *error;"
.sp
.B "error = atoaddr( /* ... */ );"
.B "if (error != NULL) {"
.B " /* something went wrong */"
.fi
.RE
+238
View File
@@ -0,0 +1,238 @@
/*
* conversion from ASCII forms of addresses to internal ones
* Copyright (C) 1998, 1999 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: atoaddr.c,v 1.1 2004/03/15 20:35:25 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
* Define NOLEADINGZEROS to interpret 032 as an error, not as 32. There
* is deliberately no way to interpret it as 26 (i.e., as octal).
*/
/*
* Legal characters in a domain name. Underscore technically is not,
* but is a common misunderstanding.
*/
static const char namechars[] = "abcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ-_.";
static const char *try8hex(const char *, size_t, struct in_addr *);
static const char *try8hosthex(const char *, size_t, struct in_addr *);
static const char *trydotted(const char *, size_t, struct in_addr *);
static const char *getbyte(const char **, const char *, int *);
/*
- atoaddr - convert ASCII name or dotted-decimal address to binary address
*/
const char * /* NULL for success, else string literal */
atoaddr(src, srclen, addrp)
const char *src;
size_t srclen; /* 0 means "apply strlen" */
struct in_addr *addrp;
{
struct hostent *h;
struct netent *ne = NULL;
const char *oops;
# define HEXLEN 10 /* strlen("0x11223344") */
# ifndef ATOADDRBUF
# define ATOADDRBUF 100
# endif
char namebuf[ATOADDRBUF];
char *p = namebuf;
char *q;
if (srclen == 0)
srclen = strlen(src);
if (srclen == 0)
return "empty string";
/* might it be hex? */
if (srclen == HEXLEN && *src == '0' && CIEQ(*(src+1), 'x'))
return try8hex(src+2, srclen-2, addrp);
if (srclen == HEXLEN && *src == '0' && CIEQ(*(src+1), 'h'))
return try8hosthex(src+2, srclen-2, addrp);
/* try it as dotted decimal */
oops = trydotted(src, srclen, addrp);
if (oops == NULL)
return NULL; /* it worked */
if (*oops != '?')
return oops; /* it *was* probably meant as a d.q. */
/* try it as a name -- first, NUL-terminate it */
if (srclen > sizeof(namebuf)-1) {
p = (char *) MALLOC(srclen+1);
if (p == NULL)
return "unable to allocate temporary space for name";
}
p[0] = '\0';
strncat(p, src, srclen);
/* next, check that it's a vaguely legal name */
for (q = p; *q != '\0'; q++)
if (!isprint(*q))
return "unprintable character in name";
if (strspn(p, namechars) != srclen)
return "illegal (non-DNS-name) character in name";
/* try as host name, failing that as /etc/networks network name */
h = gethostbyname(p);
if (h == NULL)
ne = getnetbyname(p);
if (p != namebuf)
FREE(p);
if (h == NULL && ne == NULL)
return "name lookup failed";
if (h != NULL)
memcpy(&addrp->s_addr, h->h_addr, sizeof(addrp->s_addr));
else
addrp->s_addr = htonl(ne->n_net);
return NULL;
}
/*
- try8hosthex - try conversion as an eight-digit host-order hex number
*/
const char * /* NULL for success, else string literal */
try8hosthex(src, srclen, addrp)
const char *src;
size_t srclen; /* should be 8 */
struct in_addr *addrp;
{
const char *oops;
unsigned long addr;
if (srclen != 8)
return "internal error, try8hex called with bad length";
oops = atoul(src, srclen, 16, &addr);
if (oops != NULL)
return oops;
addrp->s_addr = addr;
return NULL;
}
/*
- try8hex - try conversion as an eight-digit network-order hex number
*/
const char * /* NULL for success, else string literal */
try8hex(src, srclen, addrp)
const char *src;
size_t srclen; /* should be 8 */
struct in_addr *addrp;
{
const char *oops;
oops = try8hosthex(src, srclen, addrp);
if (oops != NULL)
return oops;
addrp->s_addr = htonl(addrp->s_addr);
return NULL;
}
/*
- trydotted - try conversion as dotted decimal
*
* If the first char of a complaint is '?', that means "didn't look like
* dotted decimal at all".
*/
const char * /* NULL for success, else string literal */
trydotted(src, srclen, addrp)
const char *src;
size_t srclen;
struct in_addr *addrp;
{
const char *stop = src + srclen; /* just past end */
int byte;
const char *oops;
unsigned long addr;
int i;
# define NBYTES 4
# define BYTE 8
addr = 0;
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 '?' */
}
addr = (addr << BYTE) | 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";
}
}
addr <<= (NBYTES - i) * BYTE;
if (src != stop)
return "extra garbage on end of dotted-decimal address";
addrp->s_addr = htonl(addr);
return NULL;
}
/*
- 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 atoul().
*
* If the first char of a complaint is '?', that means "didn't look like a
* number at all".
*/
const char * /* NULL for success, else string literal */
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";
if (stop - *srcp >= 3 && **srcp == '0' && CIEQ(*(*srcp+1), 'x'))
return "hex numbers not supported in dotted-decimal addresses";
#ifdef NOLEADINGZEROS
if (stop - *srcp >= 2 && **srcp == '0' && isdigit(*(*srcp+1)))
return "octal numbers not supported in dotted-decimal addresses";
#endif /* NOLEADINGZEROS */
/* must be decimal, if it's numeric at all */
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;
}
+186
View File
@@ -0,0 +1,186 @@
.TH IPSEC_ATOASR 3 "11 June 2001"
.\" RCSID $Id: atoasr.3,v 1.1 2004/03/15 20:35:25 as Exp $
.SH NAME
ipsec atoasr \- convert ASCII to Internet address, subnet, or range
.br
ipsec rangetoa \- convert Internet address range to ASCII
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "const char *atoasr(const char *src, size_t srclen,"
.ti +1c
.B "char *type, struct in_addr *addrs);"
.br
.B "size_t rangetoa(struct in_addr *addrs, int format,
.ti +1c
.B "char *dst, size_t dstlen);"
.SH DESCRIPTION
These functions are obsolete;
there is no current equivalent,
because so far they have not proved useful.
.PP
.I Atoasr
converts an ASCII address, subnet, or address range
into a suitable combination of binary addresses
(in network byte order).
.I Rangetoa
converts an address range back into ASCII,
using dotted-decimal form for the addresses
(the other reverse conversions are handled by
.IR ipsec_addrtoa (3)
and
.IR ipsec_subnettoa (3)).
.PP
A single address can be any form acceptable to
.IR ipsec_atoaddr (3):
dotted decimal, DNS name, or hexadecimal number.
A subnet
specification uses the form \fInetwork\fB/\fImask\fR
interpreted by
.IR ipsec_atosubnet (3).
.PP
An address range is two
.IR ipsec_atoaddr (3)
addresses separated by a
.B ...
delimiter.
If there are four dots rather than three, the first is taken as
part of the begin address,
e.g. for a complete DNS name which ends with
.B .
to suppress completion attempts.
The begin address of a range must be
less than or equal to the end address.
.PP
The
.I srclen
parameter of
.I atoasr
specifies the length of the ASCII string pointed to by
.IR src ;
it is an error for there to be anything else
(e.g., a terminating NUL) within that length.
As a convenience for cases where an entire NUL-terminated string is
to be converted,
a
.I srclen
value of
.B 0
is taken to mean
.BR strlen(src) .
.PP
The
.I type
parameter of
.I atoasr
must point to a
.B char
variable used to record which form was found.
The
.I addrs
parameter must point to a two-element array of
.B "struct in_addr"
which receives the results.
The values stored into
.BR *type ,
and the corresponding values in the array, are:
.PP
.ta 3c +2c +3c
*type addrs[0] addrs[1]
.sp 0.8
address \&\fB'a'\fR address -
.br
subnet \&\fB's'\fR network mask
.br
range \&\fB'r'\fR begin end
.PP
The
.I dstlen
parameter of
.I rangetoa
specifies the size of the
.I dst
parameter;
under no circumstances are more than
.I dstlen
bytes written to
.IR dst .
A result which will not fit is truncated.
.I Dstlen
can be zero, in which case
.I dst
need not be valid and no result is written,
but the return value is unaffected;
in all other cases, the (possibly truncated) result is NUL-terminated.
The
.I freeswan.h
header file defines a constant,
.BR RANGETOA_BUF ,
which is the size of a buffer just large enough for worst-case results.
.PP
The
.I format
parameter of
.I rangetoa
specifies what format is to be used for the conversion.
The value
.B 0
(not the ASCII character
.BR '0' ,
but a zero value)
specifies a reasonable default,
and is in fact the only format currently available.
This parameter is a hedge against future needs.
.PP
.I Atoasr
returns NULL for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
.I Rangetoa
returns
.B 0
for a failure, and otherwise
always returns the size of buffer which would
be needed to
accommodate the full conversion result, including terminating NUL;
it is the caller's responsibility to check this against the size of
the provided buffer to determine whether truncation has occurred.
.SH SEE ALSO
ipsec_atoaddr(3), ipsec_atosubnet(3)
.SH DIAGNOSTICS
Fatal errors in
.I atoasr
are:
empty input;
error in
.IR ipsec_atoaddr (3)
or
.IR ipsec_atosubnet (3)
during conversion;
begin address of range exceeds end address.
.PP
Fatal errors in
.I rangetoa
are:
unknown format.
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
The restriction of error reports to literal strings
(so that callers don't need to worry about freeing them or copying them)
does limit the precision of error reporting.
.PP
The error-reporting convention lends itself
to slightly obscure code,
because many readers will not think of NULL as signifying success.
A good way to make it clearer is to write something like:
.PP
.RS
.nf
.B "const char *error;"
.sp
.B "error = atoasr( /* ... */ );"
.B "if (error != NULL) {"
.B " /* something went wrong */"
.fi
.RE
+212
View File
@@ -0,0 +1,212 @@
/*
* convert from ASCII form of address/subnet/range to binary
* Copyright (C) 1998, 1999 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: atoasr.c,v 1.1 2004/03/15 20:35:25 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
- atoasr - convert ASCII to address, subnet, or range
*/
const char * /* NULL for success, else string literal */
atoasr(src, srclen, typep, addrsp)
const char *src;
size_t srclen; /* 0 means "apply strlen" */
char *typep; /* return type code: 'a', 's', 'r' */
struct in_addr addrsp[2];
{
const char *punct;
const char *stop;
const char *oops;
if (srclen == 0)
srclen = strlen(src);
if (srclen == 0)
return "empty string";
/* subnet is easy to spot */
punct = memchr(src, '/', srclen);
if (punct != NULL) {
*typep = 's';
return atosubnet(src, srclen, &addrsp[0], &addrsp[1]);
}
/* try for a range */
stop = src + srclen;
for (punct = src; (punct = memchr(punct, '.', stop - punct)) != NULL;
punct++)
if (stop - punct > 3 && *(punct+1) == '.' && *(punct+2) == '.')
break; /* NOTE BREAK OUT */
if (punct == NULL) {
/* didn't find the range delimiter, must be plain address */
*typep = 'a';
return atoaddr(src, srclen, &addrsp[0]);
}
/* looks like a range */
*typep = 'r';
if (stop - punct > 4 && *(punct+3) == '.')
punct++; /* first dot is trailing dot of name */
oops = atoaddr(src, punct - src, &addrsp[0]);
if (oops != NULL)
return oops;
oops = atoaddr(punct+3, stop - (punct+3), &addrsp[1]);
if (oops != NULL)
return oops;
if (ntohl(addrsp[0].s_addr) > ntohl(addrsp[1].s_addr))
return "invalid range, begin > end";
return NULL;
}
#ifdef ATOASR_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[])
{
struct in_addr a[2];
char buf[100];
const char *oops;
size_t n;
char type;
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);
}
oops = atoasr(argv[1], 0, &type, a);
if (oops != NULL) {
fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
exit(1);
}
switch (type) {
case 'a':
n = addrtoa(a[0], 0, buf, sizeof(buf));
break;
case 's':
n = subnettoa(a[0], a[1], 0, buf, sizeof(buf));
break;
case 'r':
n = rangetoa(a, 0, buf, sizeof(buf));
break;
default:
fprintf(stderr, "%s: unknown type '%c'\n", argv[0], type);
exit(1);
break;
}
if (n > sizeof(buf)) {
fprintf(stderr, "%s: reverse conversion of ", argv[0]);
fprintf(stderr, "%s ", inet_ntoa(a[0]));
fprintf(stderr, "%s", inet_ntoa(a[1]));
fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
(long)n, (long)sizeof(buf));
exit(1);
}
printf("%s\n", buf);
exit(0);
}
struct rtab {
char *input;
char *output; /* NULL means error expected */
} rtab[] = {
{"1.2.3.0", "1.2.3.0"},
{"1.2.3.0/255.255.255.0", "1.2.3.0/24"},
{"1.2.3.0...1.2.3.5", "1.2.3.0...1.2.3.5"},
{"1.2.3.4.5", NULL},
{"1.2.3.4/", NULL},
{"1.2.3.4...", NULL},
{"1.2.3.4....", NULL},
{"localhost/32", "127.0.0.1/32"},
{"localhost...127.0.0.3", "127.0.0.1...127.0.0.3"},
{"127.0.0.0...localhost", "127.0.0.0...127.0.0.1"},
{"127.0.0.3...localhost", NULL},
{NULL, NULL}
};
void
regress(void)
{
struct rtab *r;
int status = 0;
struct in_addr a[2];
char in[100];
char buf[100];
const char *oops;
size_t n;
char type;
for (r = rtab; r->input != NULL; r++) {
strcpy(in, r->input);
oops = atoasr(in, 0, &type, a);
if (oops != NULL && r->output == NULL)
{} /* okay, error expected */
else if (oops != NULL) {
printf("`%s' atoasr failed: %s\n", r->input, oops);
status = 1;
} else if (r->output == NULL) {
printf("`%s' atoasr succeeded unexpectedly '%c'\n",
r->input, type);
status = 1;
} else {
switch (type) {
case 'a':
n = addrtoa(a[0], 0, buf, sizeof(buf));
break;
case 's':
n = subnettoa(a[0], a[1], 0, buf, sizeof(buf));
break;
case 'r':
n = rangetoa(a, 0, buf, sizeof(buf));
break;
default:
fprintf(stderr, "`%s' unknown type '%c'\n",
r->input, type);
n = 0;
status = 1;
break;
}
if (n > sizeof(buf)) {
printf("`%s' '%c' reverse failed: need %ld\n",
r->input, type, (long)n);
status = 1;
} else if (n > 0 && strcmp(r->output, buf) != 0) {
printf("`%s' '%c' gave `%s', expected `%s'\n",
r->input, type, buf, r->output);
status = 1;
}
}
}
exit(status);
}
#endif /* ATOASR_MAIN */
+218
View File
@@ -0,0 +1,218 @@
.TH IPSEC_ATOSA 3 "11 June 2001"
.\" RCSID $Id: atosa.3,v 1.1 2004/03/15 20:35:26 as Exp $
.SH NAME
ipsec atosa, satoa \- convert IPsec Security Association IDs to and from ASCII
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "const char *atosa(const char *src, size_t srclen,"
.ti +1c
.B "struct sa_id *sa);
.br
.B "size_t satoa(struct sa_id sa, int format,"
.ti +1c
.B "char *dst, size_t dstlen);"
.sp
.B "struct sa_id {"
.ti +1c
.B "struct in_addr dst;"
.ti +1c
.B "ipsec_spi_t spi;"
.ti +1c
.B "int proto;"
.br
.B "};"
.SH DESCRIPTION
These functions are obsolete; see
.IR ipsec_ttosa (3)
for their replacements.
.PP
.I Atosa
converts an ASCII Security Association (SA) specifier into an
.B sa_id
structure (containing
a destination-host address
in network byte order,
an SPI number in network byte order, and
a protocol code).
.I Satoa
does the reverse conversion, back to an ASCII SA specifier.
.PP
An SA is specified in ASCII with a mail-like syntax, e.g.
.BR [email protected] .
An SA specifier contains
a protocol prefix (currently
.BR ah ,
.BR esp ,
or
.BR tun ),
an unsigned integer SPI number,
and an IP address.
The SPI number can be decimal or hexadecimal
(with
.B 0x
prefix), as accepted by
.IR ipsec_atoul (3).
The IP address can be any form accepted by
.IR ipsec_atoaddr (3),
e.g. dotted-decimal address or DNS name.
.PP
As a special case, the SA specifier
.B %passthrough
signifies the special SA used to indicate that packets should be
passed through unaltered.
(At present, this is a synonym for
.BR [email protected] ,
but that is subject to change without notice.)
This form is known to both
.I atosa
and
.IR satoa ,
so the internal form of
.B %passthrough
is never visible.
.PP
The
.B <freeswan.h>
header file supplies the
.B sa_id
structure, as well as a data type
.B ipsec_spi_t
which is an unsigned 32-bit integer.
(There is no consistency between kernel and user on what such a type
is called, hence the header hides the differences.)
.PP
The protocol code uses the same numbers that IP does.
For user convenience, given the difficulty in acquiring the exact set of
protocol names used by the kernel,
.B <freeswan.h>
defines the names
.BR SA_ESP ,
.BR SA_AH ,
and
.B SA_IPIP
to have the same values as the kernel names
.BR IPPROTO_ESP ,
.BR IPPROTO_AH ,
and
.BR IPPROTO_IPIP .
.PP
The
.I srclen
parameter of
.I atosa
specifies the length of the ASCII string pointed to by
.IR src ;
it is an error for there to be anything else
(e.g., a terminating NUL) within that length.
As a convenience for cases where an entire NUL-terminated string is
to be converted,
a
.I srclen
value of
.B 0
is taken to mean
.BR strlen(src) .
.PP
The
.I dstlen
parameter of
.I satoa
specifies the size of the
.I dst
parameter;
under no circumstances are more than
.I dstlen
bytes written to
.IR dst .
A result which will not fit is truncated.
.I Dstlen
can be zero, in which case
.I dst
need not be valid and no result is written,
but the return value is unaffected;
in all other cases, the (possibly truncated) result is NUL-terminated.
The
.I freeswan.h
header file defines a constant,
.BR SATOA_BUF ,
which is the size of a buffer just large enough for worst-case results.
.PP
The
.I format
parameter of
.I satoa
specifies what format is to be used for the conversion.
The value
.B 0
(not the ASCII character
.BR '0' ,
but a zero value)
specifies a reasonable default
(currently
lowercase protocol prefix, lowercase hexadecimal SPI, dotted-decimal address).
The value
.B d
causes the SPI to be generated in decimal instead.
.PP
.I Atosa
returns
.B NULL
for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
.I Satoa
returns
.B 0
for a failure, and otherwise
always returns the size of buffer which would
be needed to
accommodate the full conversion result, including terminating NUL;
it is the caller's responsibility to check this against the size of
the provided buffer to determine whether truncation has occurred.
.SH SEE ALSO
ipsec_atoul(3), ipsec_atoaddr(3), inet(3)
.SH DIAGNOSTICS
Fatal errors in
.I atosa
are:
empty input;
input too small to be a legal SA specifier;
no
.B @
in input;
unknown protocol prefix;
conversion error in
.I atoul
or
.IR atoaddr .
.PP
Fatal errors in
.I satoa
are:
unknown format; unknown protocol code.
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
The
.B tun
protocol code is a FreeS/WANism which may eventually disappear.
.PP
The restriction of ASCII-to-binary error reports to literal strings
(so that callers don't need to worry about freeing them or copying them)
does limit the precision of error reporting.
.PP
The ASCII-to-binary error-reporting convention lends itself
to slightly obscure code,
because many readers will not think of NULL as signifying success.
A good way to make it clearer is to write something like:
.PP
.RS
.nf
.B "const char *error;"
.sp
.B "error = atoaddr( /* ... */ );"
.B "if (error != NULL) {"
.B " /* something went wrong */"
.fi
.RE
+200
View File
@@ -0,0 +1,200 @@
/*
* convert from ASCII form of SA ID to binary
* Copyright (C) 1998, 1999 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: atosa.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
static struct satype {
char *prefix;
size_t prelen; /* strlen(prefix) */
int proto;
} satypes[] = {
{ "ah", 2, SA_AH },
{ "esp", 3, SA_ESP },
{ "tun", 3, SA_IPIP },
{ "comp", 4, SA_COMP },
{ NULL, 0, 0, }
};
/*
- atosa - convert ASCII "[email protected]" to SA identifier
*/
const char * /* NULL for success, else string literal */
atosa(src, srclen, sa)
const char *src;
size_t srclen; /* 0 means "apply strlen" */
struct sa_id *sa;
{
const char *at;
const char *addr;
const char *spi = NULL;
struct satype *sat;
unsigned long ul;
const char *oops;
# define MINLEN 5 /* ah0@0 is as short as it can get */
static char ptname[] = PASSTHROUGHNAME;
# define PTNLEN (sizeof(ptname)-1) /* -1 for NUL */
if (srclen == 0)
srclen = strlen(src);
if (srclen == 0)
return "empty string";
if (srclen < MINLEN)
return "string too short to be SA specifier";
if (srclen == PTNLEN && memcmp(src, ptname, PTNLEN) == 0) {
src = PASSTHROUGHIS;
srclen = strlen(src);
}
at = memchr(src, '@', srclen);
if (at == NULL)
return "no @ in SA specifier";
for (sat = satypes; sat->prefix != NULL; sat++)
if (sat->prelen < srclen &&
strncmp(src, sat->prefix, sat->prelen) == 0) {
sa->proto = sat->proto;
spi = src + sat->prelen;
break; /* NOTE BREAK OUT */
}
if (sat->prefix == NULL)
return "SA specifier lacks valid protocol prefix";
if (spi >= at)
return "no SPI in SA specifier";
oops = atoul(spi, at - spi, 13, &ul);
if (oops != NULL)
return oops;
sa->spi = htonl(ul);
addr = at + 1;
oops = atoaddr(addr, srclen - (addr - src), &sa->dst);
if (oops != NULL)
return oops;
return NULL;
}
#ifdef ATOSA_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[])
{
struct sa_id sa;
char buf[100];
const char *oops;
size_t n;
if (argc < 2) {
fprintf(stderr, "Usage: %s {ahnnn@aaa|-r}\n", argv[0]);
exit(2);
}
if (strcmp(argv[1], "-r") == 0) {
regress();
fprintf(stderr, "regress() returned?!?\n");
exit(1);
}
oops = atosa(argv[1], 0, &sa);
if (oops != NULL) {
fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
exit(1);
}
n = satoa(sa, 0, buf, sizeof(buf));
if (n > sizeof(buf)) {
fprintf(stderr, "%s: reverse conv of `%d'", argv[0], sa.proto);
fprintf(stderr, "%lu@", (long unsigned int)sa.spi);
fprintf(stderr, "%s", inet_ntoa(sa.dst));
fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
(long)n, (long)sizeof(buf));
exit(1);
}
printf("%s\n", buf);
exit(0);
}
struct rtab {
char *input;
char *output; /* NULL means error expected */
} rtab[] = {
{"[email protected]", "[email protected]"},
{"[email protected]", "[email protected]"},
{"[email protected]", "[email protected]"},
{"", NULL},
{"_", NULL},
{"ah2.2", NULL},
{"[email protected]", NULL},
{"[email protected]", "[email protected]"},
{"[email protected]", NULL},
{"[email protected]", NULL},
{"[email protected]", NULL},
{"[email protected]", NULL},
{"[email protected]", NULL},
{PASSTHROUGHNAME, PASSTHROUGHNAME},
{NULL, NULL}
};
void
regress(void)
{
struct rtab *r;
int status = 0;
struct sa_id sa;
char in[100];
char buf[100];
const char *oops;
size_t n;
for (r = rtab; r->input != NULL; r++) {
strcpy(in, r->input);
oops = atosa(in, 0, &sa);
if (oops != NULL && r->output == NULL)
{} /* okay, error expected */
else if (oops != NULL) {
printf("`%s' atosa failed: %s\n", r->input, oops);
status = 1;
} else if (r->output == NULL) {
printf("`%s' atosa succeeded unexpectedly\n",
r->input);
status = 1;
} else {
n = satoa(sa, 'd', buf, sizeof(buf));
if (n > sizeof(buf)) {
printf("`%s' satoa failed: need %ld\n",
r->input, (long)n);
status = 1;
} else if (strcmp(r->output, buf) != 0) {
printf("`%s' gave `%s', expected `%s'\n",
r->input, buf, r->output);
status = 1;
}
}
}
exit(status);
}
#endif /* ATOSA_MAIN */
+216
View File
@@ -0,0 +1,216 @@
/*
* convert from ASCII form of subnet specification to binary
* Copyright (C) 1998, 1999 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: atosubnet.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
#ifndef DEFAULTSUBNET
#define DEFAULTSUBNET "%default"
#endif
/*
- atosubnet - convert ASCII "addr/mask" to address and mask
* Mask can be integer bit count.
*/
const char * /* NULL for success, else string literal */
atosubnet(src, srclen, addrp, maskp)
const char *src;
size_t srclen; /* 0 means "apply strlen" */
struct in_addr *addrp;
struct in_addr *maskp;
{
const char *slash;
const char *mask;
size_t mlen;
const char *oops;
unsigned long bc;
static char def[] = DEFAULTSUBNET;
# define DEFLEN (sizeof(def) - 1) /* -1 for NUL */
static char defis[] = "0/0";
# define DEFILEN (sizeof(defis) - 1)
if (srclen == 0)
srclen = strlen(src);
if (srclen == 0)
return "empty string";
if (srclen == DEFLEN && strncmp(src, def, srclen) == 0) {
src = defis;
srclen = DEFILEN;
}
slash = memchr(src, '/', srclen);
if (slash == NULL)
return "no / in subnet specification";
mask = slash + 1;
mlen = srclen - (mask - src);
oops = atoaddr(src, slash-src, addrp);
if (oops != NULL)
return oops;
oops = atoul(mask, mlen, 10, &bc);
if (oops == NULL) {
/* atoul succeeded, it's a bit-count mask */
if (bc > ABITS)
return "bit-count mask too large";
#ifdef NOLEADINGZEROS
if (mlen > 1 && *mask == '0')
return "octal not allowed in mask";
#endif /* NOLEADINGZEROS */
*maskp = bitstomask((int)bc);
} else {
oops = atoaddr(mask, mlen, maskp);
if (oops != NULL)
return oops;
if (!goodmask(*maskp))
return "non-contiguous mask";
}
addrp->s_addr &= maskp->s_addr;
return NULL;
}
#ifdef ATOSUBNET_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[])
{
struct in_addr a;
struct in_addr m;
char buf[100];
const char *oops;
size_t n;
if (argc < 2) {
fprintf(stderr, "Usage: %s {addr/mask|-r}\n", argv[0]);
exit(2);
}
if (strcmp(argv[1], "-r") == 0) {
regress();
fprintf(stderr, "regress() returned?!?\n");
exit(1);
}
oops = atosubnet(argv[1], 0, &a, &m);
if (oops != NULL) {
fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
exit(1);
}
n = subnettoa(a, m, 0, buf, sizeof(buf));
if (n > sizeof(buf)) {
fprintf(stderr, "%s: reverse conversion of ", argv[0]);
fprintf(stderr, "%s/", inet_ntoa(a));
fprintf(stderr, "%s", inet_ntoa(m));
fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
(long)n, (long)sizeof(buf));
exit(1);
}
printf("%s\n", buf);
exit(0);
}
struct rtab {
char *input;
char *output; /* NULL means error expected */
} rtab[] = {
{"1.2.3.0/255.255.255.0", "1.2.3.0/24"},
{"1.2.3.0/24", "1.2.3.0/24"},
{"1.2.3.1/255.255.255.240", "1.2.3.0/28"},
{"1.2.3.1/32", "1.2.3.1/32"},
{"1.2.3.1/0", "0.0.0.0/0"},
/* "1.2.3.1/255.255.127.0", "1.2.3.0/255.255.127.0", */
{"1.2.3.1/255.255.127.0", NULL},
{"128.009.000.032/32", "128.9.0.32/32"},
{"128.0x9.0.32/32", NULL},
{"0x80090020/32", "128.9.0.32/32"},
{"0x800x0020/32", NULL},
{"128.9.0.32/0xffFF0000", "128.9.0.0/16"},
{"128.9.0.32/0xff0000FF", NULL},
{"128.9.0.32/0x0000ffFF", NULL},
{"128.9.0.32/0x00ffFF0000", NULL},
{"128.9.0.32/0xffFF", NULL},
{"128.9.0.32.27/32", NULL},
{"128.9.0k32/32", NULL},
{"328.9.0.32/32", NULL},
{"128.9..32/32", NULL},
{"10/8", "10.0.0.0/8"},
{"10.0/8", "10.0.0.0/8"},
{"10.0.0/8", "10.0.0.0/8"},
{"10.0.1/24", "10.0.1.0/24"},
{"_", NULL},
{"_/_", NULL},
{"1.2.3.1", NULL},
{"1.2.3.1/_", NULL},
{"1.2.3.1/24._", NULL},
{"1.2.3.1/99", NULL},
{"localhost/32", "127.0.0.1/32"},
{"%default", "0.0.0.0/0"},
{NULL, NULL}
};
void
regress()
{
struct rtab *r;
int status = 0;
struct in_addr a;
struct in_addr m;
char in[100];
char buf[100];
const char *oops;
size_t n;
for (r = rtab; r->input != NULL; r++) {
strcpy(in, r->input);
oops = atosubnet(in, 0, &a, &m);
if (oops != NULL && r->output == NULL)
{} /* okay, error expected */
else if (oops != NULL) {
printf("`%s' atosubnet failed: %s\n", r->input, oops);
status = 1;
} else if (r->output == NULL) {
printf("`%s' atosubnet succeeded unexpectedly\n",
r->input);
status = 1;
} else {
n = subnettoa(a, m, 0, buf, sizeof(buf));
if (n > sizeof(buf)) {
printf("`%s' subnettoa failed: need %ld\n",
r->input, (long)n);
status = 1;
} else if (strcmp(r->output, buf) != 0) {
printf("`%s' gave `%s', expected `%s'\n",
r->input, buf, r->output);
status = 1;
}
}
}
exit(status);
}
#endif /* ATOSUBNET_MAIN */
+161
View File
@@ -0,0 +1,161 @@
.TH IPSEC_ATOUL 3 "11 June 2001"
.\" RCSID $Id: atoul.3,v 1.1 2004/03/15 20:35:26 as Exp $
.SH NAME
ipsec atoul, ultoa \- convert unsigned-long numbers to and from ASCII
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "const char *atoul(const char *src, size_t srclen,"
.ti +1c
.B "int base, unsigned long *n);"
.br
.B "size_t ultoa(unsigned long n, int base, char *dst,"
.ti +1c
.B "size_t dstlen);"
.SH DESCRIPTION
These functions are obsolete; see
.IR ipsec_ttoul (3)
for their replacements.
.PP
.I Atoul
converts an ASCII number into a binary
.B "unsigned long"
value.
.I Ultoa
does the reverse conversion, back to an ASCII version.
.PP
Numbers are specified in ASCII as
decimal (e.g.
.BR 123 ),
octal with a leading zero (e.g.
.BR 012 ,
which has value 10),
or hexadecimal with a leading
.B 0x
(e.g.
.BR 0x1f ,
which has value 31)
in either upper or lower case.
.PP
The
.I srclen
parameter of
.I atoul
specifies the length of the ASCII string pointed to by
.IR src ;
it is an error for there to be anything else
(e.g., a terminating NUL) within that length.
As a convenience for cases where an entire NUL-terminated string is
to be converted,
a
.I srclen
value of
.B 0
is taken to mean
.BR strlen(src) .
.PP
The
.I base
parameter of
.I atoul
can be
.BR 8 ,
.BR 10 ,
or
.BR 16 ,
in which case the number supplied is assumed to be of that form
(and in the case of
.BR 16 ,
to lack any
.B 0x
prefix).
It can also be
.BR 0 ,
in which case the number is examined for a leading zero
or a leading
.B 0x
to determine its base,
or
.B 13
(halfway between 10 and 16),
which has the same effect as
.B 0
except that a non-hexadecimal
number is considered decimal regardless of any leading zero.
.PP
The
.I dstlen
parameter of
.I ultoa
specifies the size of the
.I dst
parameter;
under no circumstances are more than
.I dstlen
bytes written to
.IR dst .
A result which will not fit is truncated.
.I Dstlen
can be zero, in which case
.I dst
need not be valid and no result is written,
but the return value is unaffected;
in all other cases, the (possibly truncated) result is NUL-terminated.
.PP
The
.I base
parameter of
.I ultoa
must be
.BR 8 ,
.BR 10 ,
or
.BR 16 .
.PP
.I Atoul
returns NULL for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
.I Ultoa
returns the size of buffer which would
be needed to
accommodate the full conversion result, including terminating NUL;
it is the caller's responsibility to check this against the size of
the provided buffer to determine whether truncation has occurred.
.SH SEE ALSO
atol(3), strtoul(3)
.SH DIAGNOSTICS
Fatal errors in
.I atoul
are:
empty input;
unknown
.IR base ;
non-digit character found;
number too large for an
.BR "unsigned long" .
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
There is no provision for reporting an invalid
.I base
parameter given to
.IR ultoa .
.PP
The restriction of error reports to literal strings
(so that callers don't need to worry about freeing them or copying them)
does limit the precision of error reporting.
.PP
The error-reporting convention lends itself to slightly obscure code,
because many readers will not think of NULL as signifying success.
A good way to make it clearer is to write something like:
.PP
.RS
.nf
.B "const char *error;"
.sp
.B "error = atoul( /* ... */ );"
.B "if (error != NULL) {"
.B " /* something went wrong */"
.fi
.RE
+90
View File
@@ -0,0 +1,90 @@
/*
* convert from ASCII form of unsigned long to binary
* Copyright (C) 1998, 1999 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: atoul.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
- atoul - convert ASCII substring to unsigned long number
*/
const char * /* NULL for success, else string literal */
atoul(src, srclen, base, resultp)
const char *src;
size_t srclen; /* 0 means strlen(src) */
int base; /* 0 means figure it out */
unsigned long *resultp;
{
const char *stop;
static char hex[] = "0123456789abcdef";
static char uchex[] = "0123456789ABCDEF";
int d;
char c;
char *p;
unsigned long r;
unsigned long rlimit;
int dlimit;
if (srclen == 0)
srclen = strlen(src);
if (srclen == 0)
return "empty string";
if (base == 0 || base == 13) {
if (srclen > 2 && *src == '0' && CIEQ(*(src+1), 'x'))
return atoul(src+2, srclen-2, 16, resultp);
if (srclen > 1 && *src == '0' && base != 13)
return atoul(src+1, srclen-1, 8, resultp);
return atoul(src, srclen, 10, resultp);
}
if (base != 8 && base != 10 && base != 16)
return "unsupported number base";
r = 0;
stop = src + srclen;
if (base == 16) {
while (src < stop) {
c = *src++;
p = strchr(hex, c);
if (p != NULL)
d = p - hex;
else {
p = strchr(uchex, c);
if (p == NULL)
return "non-hex-digit in hex number";
d = p - uchex;
}
r = (r << 4) | d;
}
/* defer length check to catch invalid digits first */
if (srclen > sizeof(unsigned long) * 2)
return "hex number too long";
} else {
rlimit = ULONG_MAX / base;
dlimit = (int)(ULONG_MAX - rlimit*base);
while (src < stop) {
c = *src++;
d = c - '0';
if (d < 0 || d >= base)
return "non-digit in number";
if (r > rlimit || (r == rlimit && d > dlimit))
return "unsigned-long overflow";
r = r*base + d;
}
}
*resultp = r;
return NULL;
}
+56
View File
@@ -0,0 +1,56 @@
/*
* return IPsec copyright notice
* Copyright (C) 2001, 2002 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: copyright.c,v 1.6 2005/11/02 21:51:13 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
static const char *co[] = {
"Copyright (C) 1999-2005 Henry Spencer, Richard Guy Briggs,",
" D. Hugh Redelmeier, Sandy Harris, Claudia Schmeing,",
" Michael Richardson, Angelos D. Keromytis, John Ioannidis,",
"",
" Ken Bantoft, Stephen J. Bevan, JuanJo Ciarlante, Mathieu Lafon,",
" Stephane Laroche, Kai Martius, Tuomo Soini, Herbert Xu,",
"",
" Andreas Steffen, Martin Berner, Marco Bertossa, David Buechi,",
" Ueli Galizzi, Christoph Gysin, Andreas Hess, Patric Lichtsteiner,",
" Michael Meier, Andreas Schleiss, Ariane Seiler,",
" Mario Strasser, Lukas Suter, Roger Wegmann, Simon Zwahlen,",
" Zuercher Hochschule Winterthur (Switzerland).",
"",
" Jan Hutter, Martin Willi, Andreas Steffen,",
" Hochschule fuer Technik Rapperswil (Switzerland).",
"",
"This program is free software; you can redistribute it and/or modify it",
"under the terms of the GNU 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/gpl.txt>.",
"",
"This program 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 General",
"Public License (file COPYING in the distribution) for more details.",
NULL
};
/*
- ipsec_copyright_notice - return copyright notice, as a vector of strings
*/
const char **
ipsec_copyright_notice()
{
return co;
}
+233
View File
@@ -0,0 +1,233 @@
/*
* convert from binary data (e.g. key) to text form
* 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: datatot.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
static void convert(const char *src, size_t nreal, int format, char *out);
/*
- datatot - convert data bytes to text
*/
size_t /* true length (with NUL) for success */
datatot(src, srclen, format, dst, dstlen)
const char *src;
size_t srclen;
int format; /* character indicating what format */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
size_t inblocksize; /* process this many bytes at a time */
size_t outblocksize; /* producing this many */
size_t breakevery; /* add a _ every this many (0 means don't) */
size_t sincebreak; /* output bytes since last _ */
char breakchar; /* character used to break between groups */
char inblock[10]; /* enough for any format */
char outblock[10]; /* enough for any format */
char fake[1]; /* fake output area for dstlen == 0 */
size_t needed; /* return value */
char *stop; /* where the terminating NUL will go */
size_t ntodo; /* remaining input */
size_t nreal;
char *out;
char *prefix;
breakevery = 0;
breakchar = '_';
switch (format) {
case 0:
case 'h':
format = 'x';
breakevery = 8;
/* FALLTHROUGH */
case 'x':
inblocksize = 1;
outblocksize = 2;
prefix = "0x";
break;
case ':':
format = 'x';
breakevery = 2;
breakchar = ':';
/* FALLTHROUGH */
case 16:
inblocksize = 1;
outblocksize = 2;
prefix = "";
format = 'x';
break;
case 's':
inblocksize = 3;
outblocksize = 4;
prefix = "0s";
break;
case 64: /* beware, equals ' ' */
inblocksize = 3;
outblocksize = 4;
prefix = "";
format = 's';
break;
default:
return 0;
break;
}
assert(inblocksize < sizeof(inblock));
assert(outblocksize < sizeof(outblock));
assert(breakevery % outblocksize == 0);
if (srclen == 0)
return 0;
ntodo = srclen;
if (dstlen == 0) { /* dispose of awkward special case */
dst = fake;
dstlen = 1;
}
stop = dst + dstlen - 1;
nreal = strlen(prefix);
needed = nreal; /* for starters */
if (dstlen <= nreal) { /* prefix won't fit */
strncpy(dst, prefix, dstlen - 1);
dst += dstlen - 1;
} else {
strcpy(dst, prefix);
dst += nreal;
}
assert(dst <= stop);
sincebreak = 0;
while (ntodo > 0) {
if (ntodo < inblocksize) { /* incomplete input */
memset(inblock, 0, sizeof(inblock));
memcpy(inblock, src, ntodo);
src = inblock;
nreal = ntodo;
ntodo = inblocksize;
} else
nreal = inblocksize;
out = (outblocksize > stop - dst) ? outblock : dst;
convert(src, nreal, format, out);
needed += outblocksize;
sincebreak += outblocksize;
if (dst < stop) {
if (out != dst) {
assert(outblocksize > stop - dst);
memcpy(dst, out, stop - dst);
dst = stop;
} else
dst += outblocksize;
}
src += inblocksize;
ntodo -= inblocksize;
if (breakevery != 0 && sincebreak >= breakevery && ntodo > 0) {
if (dst < stop)
*dst++ = breakchar;
needed++;
sincebreak = 0;
}
}
assert(dst <= stop);
*dst++ = '\0';
needed++;
return needed;
}
/*
- convert - convert one input block to one output block
*/
static void
convert(src, nreal, format, out)
const char *src;
size_t nreal; /* how much of the input block is real */
int format;
char *out;
{
static char hex[] = "0123456789abcdef";
static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
unsigned char c;
unsigned char c1, c2, c3;
assert(nreal > 0);
switch (format) {
case 'x':
assert(nreal == 1);
c = (unsigned char)*src;
*out++ = hex[c >> 4];
*out++ = hex[c & 0xf];
break;
case 's':
c1 = (unsigned char)*src++;
c2 = (unsigned char)*src++;
c3 = (unsigned char)*src++;
*out++ = base64[c1 >> 2]; /* top 6 bits of c1 */
c = (c1 & 0x3) << 4; /* bottom 2 of c1... */
c |= c2 >> 4; /* ...top 4 of c2 */
*out++ = base64[c];
if (nreal == 1)
*out++ = '=';
else {
c = (c2 & 0xf) << 2; /* bottom 4 of c2... */
c |= c3 >> 6; /* ...top 2 of c3 */
*out++ = base64[c];
}
if (nreal <= 2)
*out++ = '=';
else
*out++ = base64[c3 & 0x3f]; /* bottom 6 of c3 */
break;
default:
assert(nreal == 0); /* unknown format */
break;
}
}
/*
- datatoa - convert data to ASCII
* backward-compatibility synonym for datatot
*/
size_t /* true length (with NUL) for success */
datatoa(src, srclen, format, dst, dstlen)
const char *src;
size_t srclen;
int format; /* character indicating what format */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
return datatot(src, srclen, format, dst, dstlen);
}
/*
- bytestoa - convert data bytes to ASCII
* backward-compatibility synonym for datatot
*/
size_t /* true length (with NUL) for success */
bytestoa(src, srclen, format, dst, dstlen)
const char *src;
size_t srclen;
int format; /* character indicating what format */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
return datatot(src, srclen, format, dst, dstlen);
}
+57
View File
@@ -0,0 +1,57 @@
.TH IPSEC_GOODMASK 3 "11 June 2001"
.\" RCSID $Id: goodmask.3,v 1.1 2004/03/15 20:35:26 as Exp $
.SH NAME
ipsec goodmask \- is this Internet subnet mask a valid one?
.br
ipsec masktobits \- convert Internet subnet mask to bit count
.br
ipsec bitstomask \- convert bit count to Internet subnet mask
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "int goodmask(struct in_addr mask);"
.br
.B "int masktobits(struct in_addr mask);"
.br
.B "struct in_addr bitstomask(int n);"
.SH DESCRIPTION
These functions are obsolete;
see
.IR ipsec_masktocount (3)
for a partial replacement.
.PP
.I Goodmask
reports whether the subnet
.I mask
is a valid one,
i.e. consists of a (possibly empty) sequence of
.BR 1 s
followed by a (possibly empty) sequence of
.BR 0 s.
.I Masktobits
takes a (valid) subnet mask and returns the number of
.B 1
bits in it.
.I Bitstomask
reverses this,
returning the subnet mask corresponding to bit count
.IR n .
.PP
All masks are in network byte order.
.SH SEE ALSO
inet(3), ipsec_atosubnet(3)
.SH DIAGNOSTICS
.I Masktobits
returns
.B \-1
for an invalid mask.
.I Bitstomask
returns an all-zeros mask for a negative or out-of-range
.IR n .
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
The error-reporting convention of
.I bitstomask
is less than ideal;
zero is sometimes a legitimate mask.
+97
View File
@@ -0,0 +1,97 @@
/*
* minor utilities for subnet-mask manipulation
* Copyright (C) 1998, 1999 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: goodmask.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
- goodmask - is this a good (^1*0*$) subnet mask?
* You are not expected to understand this. See Henry S. Warren Jr,
* "Functions realizable with word-parallel logical and two's-complement
* addition instructions", CACM 20.6 (June 1977), p.439.
*/
int /* predicate */
goodmask(mask)
struct in_addr mask;
{
unsigned long x = ntohl(mask.s_addr);
/* clear rightmost contiguous string of 1-bits */
# define CRCS1B(x) (((x|(x-1))+1)&x)
# define TOPBIT (1UL << 31)
/* either zero, or has one string of 1-bits which is left-justified */
if (x == 0 || (CRCS1B(x) == 0 && (x&TOPBIT)))
return 1;
return 0;
}
/*
- masktobits - how many bits in this mask?
* The algorithm is essentially a binary search, but highly optimized
* for this particular task.
*/
int /* -1 means !goodmask() */
masktobits(mask)
struct in_addr mask;
{
unsigned long m = ntohl(mask.s_addr);
int masklen;
if (!goodmask(mask))
return -1;
if (m&0x00000001UL)
return 32;
masklen = 0;
if (m&(0x0000ffffUL<<1)) { /* <<1 for 1-origin numbering */
masklen |= 0x10;
m <<= 16;
}
if (m&(0x00ff0000UL<<1)) {
masklen |= 0x08;
m <<= 8;
}
if (m&(0x0f000000UL<<1)) {
masklen |= 0x04;
m <<= 4;
}
if (m&(0x30000000UL<<1)) {
masklen |= 0x02;
m <<= 2;
}
if (m&(0x40000000UL<<1))
masklen |= 0x01;
return masklen;
}
/*
- bitstomask - return a mask with this many high bits on
*/
struct in_addr
bitstomask(n)
int n;
{
struct in_addr result;
if (n > 0 && n <= ABITS)
result.s_addr = htonl(~((1UL << (ABITS - n)) - 1));
else if (n == 0)
result.s_addr = 0;
else
result.s_addr = 0; /* best error report we can do */
return result;
}
+129
View File
@@ -0,0 +1,129 @@
.TH IPSEC_INITADDR 3 "11 Sept 2000"
.\" RCSID $Id: initaddr.3,v 1.1 2004/03/15 20:35:26 as Exp $
.SH NAME
ipsec initaddr \- initialize an ip_address
.br
ipsec addrtypeof \- get address type of an ip_address
.br
ipsec addrlenof \- get length of address within an ip_address
.br
ipsec addrbytesof \- get copy of address within an ip_address
.br
ipsec addrbytesptr \- get pointer to address within an ip_address
.SH SYNOPSIS
.B "#include <freeswan.h>"
.sp
.B "const char *initaddr(const char *src, size_t srclen,"
.ti +1c
.B "int af, ip_address *dst);"
.br
.B "int addrtypeof(const ip_address *src);"
.br
.B "size_t addrlenof(const ip_address *src);"
.br
.B "size_t addrbytesof(const ip_address *src,"
.ti +1c
.B "unsigned char *dst, size_t dstlen);"
.br
.B "size_t addrbytesptr(const ip_address *src,"
.ti +1c
.B "const unsigned char **dst);"
.SH DESCRIPTION
The
.B <freeswan.h>
library uses an internal type
.I ip_address
to contain one of the (currently two) types of IP address.
These functions provide basic tools for creating and examining this type.
.PP
.I Initaddr
initializes a variable
.I *dst
of type
.I ip_address
from an address
(in network byte order,
indicated by a pointer
.I src
and a length
.IR srclen )
and an address family
.I af
(typically
.B AF_INET
or
.BR AF_INET6 ).
The length must be consistent with the address family.
.PP
.I Addrtypeof
returns the address type of an address,
normally
.B AF_INET
or
.BR AF_INET6 .
(The
.B <freeswan.h>
header file arranges to include the necessary headers for these
names to be known.)
.PP
.I Addrlenof
returns the size (in bytes) of the address within an
.IR ip_address ,
to permit storage allocation etc.
.PP
.I Addrbytesof
copies the address within the
.I ip_address
.I src
to the buffer indicated by the pointer
.I dst
and the length
.IR dstlen ,
and returns the address length (in bytes).
If the address will not fit,
as many bytes as will fit are copied;
the returned length is still the full length.
It is the caller's responsibility to check the
returned value to ensure that there was enough room.
.PP
.I Addrbytesptr
sets
.I *dst
to a pointer to the internal address within the
.IR ip_address ,
and returns the address length (in bytes).
If
.I dst
is
.BR NULL ,
it just returns the address length.
The pointer points to
.B const
to discourage misuse.
.PP
.I Initaddr
returns
.B NULL
for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
.PP
The functions which return
.I size_t
return
.B 0
for a failure.
.SH SEE ALSO
inet(3), ipsec_ttoaddr(3)
.SH DIAGNOSTICS
An unknown address family is a fatal error for any of these functions
except
.IR addrtypeof .
An address-size mismatch is a fatal error for
.IR initaddr .
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
.I Addrtypeof
should probably have been named
.IR addrfamilyof .
+51
View File
@@ -0,0 +1,51 @@
/*
* initialize address structure
* 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: initaddr.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
- initaddr - initialize ip_address from bytes
*/
err_t /* NULL for success, else string literal */
initaddr(src, srclen, af, dst)
const unsigned char *src;
size_t srclen;
int af; /* address family */
ip_address *dst;
{
switch (af) {
case AF_INET:
if (srclen != 4)
return "IPv4 address must be exactly 4 bytes";
dst->u.v4.sin_family = af;
dst->u.v4.sin_port = 0; /* unused */
memcpy((char *)&dst->u.v4.sin_addr.s_addr, src, srclen);
break;
case AF_INET6:
if (srclen != 16)
return "IPv6 address must be exactly 16 bytes";
dst->u.v6.sin6_family = af;
dst->u.v6.sin6_flowinfo = 0; /* unused */
dst->u.v6.sin6_port = 0; /* unused */
memcpy((char *)&dst->u.v6.sin6_addr, src, srclen);
break;
default:
return "unknown address family in initaddr";
break;
}
return NULL;
}
+33
View File
@@ -0,0 +1,33 @@
/*
* initialize SA ID structure
* 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: initsaid.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
- initsaid - initialize SA ID from bits
*/
void
initsaid(addr, spi, proto, dst)
const ip_address *addr;
ipsec_spi_t spi;
int proto;
ip_said *dst;
{
dst->dst = *addr;
dst->spi = spi;
dst->proto = proto;
}
+137
View File
@@ -0,0 +1,137 @@
.TH IPSEC_INITSUBNET 3 "12 March 2002"
.\" RCSID $Id: initsubnet.3,v 1.1 2004/03/15 20:35:26 as Exp $
.SH NAME
ipsec initsubnet \- initialize an ip_subnet
.br
ipsec addrtosubnet \- initialize a singleton ip_subnet
.br
ipsec subnettypeof \- get address type of an ip_subnet
.br
ipsec masktocount \- convert subnet mask to bit count
.br
ipsec networkof \- get base address of an ip_subnet
.br
ipsec maskof \- get subnet mask of an ip_subnet
.SH SYNOPSIS
.B "#include <freeswan.h>"
.sp
.B "const char *initsubnet(const ip_address *addr,"
.ti +1c
.B "int maskbits, int clash, ip_subnet *dst);"
.br
.B "const char *addrtosubnet(const ip_address *addr,"
.ti +1c
.B "ip_subnet *dst);"
.sp
.B "int subnettypeof(const ip_subnet *src);"
.br
.B "int masktocount(const ip_address *src);"
.br
.B "void networkof(const ip_subnet *src, ip_address *dst);"
.br
.B "void maskof(const ip_subnet *src, ip_address *dst);"
.SH DESCRIPTION
The
.B <freeswan.h>
library uses an internal type
.I ip_subnet
to contain a description of an IP subnet
(base address plus mask).
These functions provide basic tools for creating and examining this type.
.PP
.I Initsubnet
initializes a variable
.I *dst
of type
.I ip_subnet
from a base address and
a count of mask bits.
The
.I clash
parameter specifies what to do if the base address includes
.B 1
bits outside the prefix specified by the mask
(that is, in the ``host number'' part of the address):
.RS
.IP '0' 5
zero out host-number bits
.IP 'x'
non-zero host-number bits are an error
.RE
.PP
.I Initsubnet
returns
.B NULL
for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
.PP
.I Addrtosubnet
initializes an
.I ip_subnet
variable
.I *dst
to a ``singleton subnet'' containing the single address
.IR *addr .
It returns
.B NULL
for success and
a pointer to a string-literal error message for failure.
.PP
.I Subnettypeof
returns the address type of a subnet,
normally
.B AF_INET
or
.BR AF_INET6 .
(The
.B <freeswan.h>
header file arranges to include the necessary headers for these
names to be known.)
.PP
.I Masktocount
converts a subnet mask, expressed as an address, to a bit count
suitable for use with
.IR initsubnet .
It returns
.B \-1
for error; see DIAGNOSTICS.
.PP
.I Networkof
fills in
.I *dst
with the base address of subnet
.IR src .
.PP
.I Maskof
fills in
.I *dst
with the subnet mask of subnet
.IR src ,
expressed as an address.
.SH SEE ALSO
inet(3), ipsec_ttosubnet(3), ipsec_rangetosubnet(3)
.SH DIAGNOSTICS
Fatal errors in
.I initsubnet
are:
unknown address family;
unknown
.I clash
value;
impossible mask bit count;
non-zero host-number bits and
.I clash
is
.BR 'x' .
Fatal errors in
.I addrtosubnet
are:
unknown address family.
Fatal errors in
.I masktocount
are:
unknown address family;
mask bits not contiguous.
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
+95
View File
@@ -0,0 +1,95 @@
/*
* initialize subnet structure
* Copyright (C) 2000, 2002 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: initsubnet.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
- initsubnet - initialize ip_subnet from address and count
*
* The only hard part is checking for host-part bits turned on.
*/
err_t /* NULL for success, else string literal */
initsubnet(addr, count, clash, dst)
const ip_address *addr;
int count;
int clash; /* '0' zero host-part bits, 'x' die on them */
ip_subnet *dst;
{
unsigned char *p;
int n;
int c;
unsigned m;
int die;
dst->addr = *addr;
n = addrbytesptr(&dst->addr, (const unsigned char **)&p);
if (n == 0)
return "unknown address family";
switch (clash) {
case '0':
die = 0;
break;
case 'x':
die = 1;
break;
default:
return "unknown clash-control value in initsubnet";
break;
}
c = count / 8;
if (c > n)
return "impossible mask count";
p += c;
n -= c;
m = 0xff;
c = count % 8;
if (n > 0 && c != 0) /* partial byte */
m >>= c;
for (; n > 0; n--) {
if ((*p & m) != 0) {
if (die)
return "improper subnet, host-part bits on";
*p &= ~m;
}
m = 0xff;
p++;
}
dst->maskbits = count;
return NULL;
}
/*
- addrtosubnet - initialize ip_subnet from a single address
*/
err_t /* NULL for success, else string literal */
addrtosubnet(addr, dst)
const ip_address *addr;
ip_subnet *dst;
{
int n;
dst->addr = *addr;
n = addrbytesptr(&dst->addr, (const unsigned char **)NULL);
if (n == 0)
return "unknown address family";
dst->maskbits = n*8;
return NULL;
}
+81
View File
@@ -0,0 +1,81 @@
/*
* internal definitions for use within the library; do not export!
* Copyright (C) 1998, 1999 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: internal.h,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#ifndef ABITS
#define ABITS 32 /* bits in an IPv4 address */
#endif
/* case-independent ASCII character equality comparison */
#define CIEQ(c1, c2) ( ((c1)&~040) == ((c2)&~040) )
/* syntax for passthrough SA */
#ifndef PASSTHROUGHNAME
#define PASSTHROUGHNAME "%passthrough"
#define PASSTHROUGH4NAME "%passthrough4"
#define PASSTHROUGH6NAME "%passthrough6"
#define PASSTHROUGHIS "[email protected]"
#define PASSTHROUGH4IS "[email protected]"
#define PASSTHROUGH6IS "tun0@::"
#define PASSTHROUGHTYPE "tun"
#define PASSTHROUGHSPI 0
#define PASSTHROUGHDST 0
#endif
/*
* Headers, greatly complicated by stupid and unnecessary inconsistencies
* between the user environment and the kernel environment. These are done
* here so that this mess need exist in only one place.
*
* It may seem like a -I or two could avoid most of this, but on closer
* inspection it is not quite that easy.
*/
/* things that need to come from one place or the other, depending */
#ifdef __KERNEL__
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/string.h>
#include <linux/ctype.h>
#define assert(foo) /* nothing */
#else
#include <sys/types.h>
#include <netinet/in.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#endif
/* things that exist only in userland */
#ifndef __KERNEL__
/* You'd think this would be okay in the kernel too -- it's just a */
/* bunch of constants -- but no, in RH5.1 it screws up other things. */
/* (Credit: Mike Warfield tracked this problem down. Thanks Mike!) */
/* Fortunately, we don't need it in the kernel subset of the library. */
#include <limits.h>
/* header files for things that should never be called in kernel */
#include <netdb.h>
/* memory allocation, currently user-only, macro-ized just in case */
#include <stdlib.h>
#define MALLOC(n) malloc(n)
#define FREE(p) free(p)
#endif /* __KERNEL__ */
+103
View File
@@ -0,0 +1,103 @@
.TH IPSEC_KEYBLOBTOID 3 "25 March 2002"
.\" RCSID $Id: keyblobtoid.3,v 1.1 2004/03/15 20:35:26 as Exp $
.SH NAME
ipsec keyblobtoid, splitkeytoid \- generate key IDs from RSA keys
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "size_t keyblobtoid(const unsigned char *blob,"
.ti +1c
.B "size_t bloblen, char *dst, size_t dstlen);"
.br
.B "size_t splitkeytoid(const unsigned char *e, size_t elen,"
.ti +1c
.B "const unsigned char *m, size_t mlen, char *dst,
.ti +1c
.B "size_t dstlen);"
.SH DESCRIPTION
.I Keyblobtoid
and
.I splitkeytoid
generate
key IDs
from RSA keys,
for use in messages and reporting,
writing the result to
.IR dst .
A
.I key ID
is a short ASCII string identifying a key;
currently it is just the first nine characters of the base64
encoding of the RFC 2537/3110 ``byte blob'' representation of the key.
(Beware that no finite key ID can be collision-proof:
there is always some small chance of two random keys having the
same ID.)
.PP
.I Keyblobtoid
generates a key ID from a key which is already in the form of an
RFC 2537/3110 binary key
.I blob
(encoded exponent length, exponent, modulus).
.PP
.I Splitkeytoid
generates a key ID from a key given in the form of a separate
(binary) exponent
.I e
and modulus
.IR m .
.PP
The
.I dstlen
parameter of either
specifies the size of the
.I dst
parameter;
under no circumstances are more than
.I dstlen
bytes written to
.IR dst .
A result which will not fit is truncated.
.I Dstlen
can be zero, in which case
.I dst
need not be valid and no result is written,
but the return value is unaffected;
in all other cases, the (possibly truncated) result is NUL-terminated.
The
.I freeswan.h
header file defines a constant
.B KEYID_BUF
which is the size of a buffer large enough for worst-case results.
.PP
Both functions return
.B 0
for a failure, and otherwise
always return the size of buffer which would
be needed to
accommodate the full conversion result, including terminating NUL;
it is the caller's responsibility to check this against the size of
the provided buffer to determine whether truncation has occurred.
.P
With keys generated by
.IR ipsec_rsasigkey (3),
the first two base64 digits are always the same,
and the third carries only about one bit of information.
It's worse with keys using longer fixed exponents,
e.g. the 24-bit exponent that's common in X.509 certificates.
However, being able to relate key IDs to the full
base64 text form of keys by eye is sufficiently useful that this
waste of space seems justifiable.
The choice of nine digits is a compromise between bulk and
probability of collision.
.SH SEE ALSO
RFC 3110,
\fIRSA/SHA-1 SIGs and RSA KEYs in the Domain Name System (DNS)\fR,
Eastlake, 2001
(superseding the older but better-known RFC 2537).
.SH DIAGNOSTICS
Fatal errors are:
key too short to supply enough bits to construct a complete key ID
(almost certainly indicating a garbage key);
exponent too long for its length to be representable.
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
+148
View File
@@ -0,0 +1,148 @@
/*
* generate printable key IDs
* Copyright (C) 2002 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: keyblobtoid.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
- keyblobtoid - generate a printable key ID from an RFC 2537/3110 key blob
* Current algorithm is just to use first nine base64 digits.
*/
size_t
keyblobtoid(src, srclen, dst, dstlen)
const unsigned char *src;
size_t srclen;
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
char buf[KEYID_BUF];
size_t ret;
# define NDIG 9
if (srclen < (NDIG*6 + 7)/8) {
strcpy(buf, "?len= ?");
buf[5] = '0' + srclen;
ret = 0;
} else {
(void) datatot(src, srclen, 64, buf, NDIG+1);
ret = NDIG+1;
}
if (dstlen > 0) {
if (strlen(buf)+1 > dstlen)
*(buf + dstlen - 1) = '\0';
strcpy(dst, buf);
}
return ret;
}
/*
- splitkeytoid - generate a printable key ID from exponent/modulus pair
* Just constructs the beginnings of a key blob and calls keyblobtoid().
*/
size_t
splitkeytoid(e, elen, m, mlen, dst, dstlen)
const unsigned char *e;
size_t elen;
const unsigned char *m;
size_t mlen;
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
unsigned char buf[KEYID_BUF]; /* ample room */
unsigned char *bufend = buf + sizeof(buf);
unsigned char *p;
size_t n;
p = buf;
if (elen <= 255)
*p++ = elen;
else if ((elen &~ 0xffff) == 0) {
*p++ = 0;
*p++ = (elen>>8) & 0xff;
*p++ = elen & 0xff;
} else
return 0; /* unrepresentable exponent length */
n = bufend - p;
if (elen < n)
n = elen;
memcpy(p, e, n);
p += n;
n = bufend - p;
if (n > 0) {
if (mlen < n)
n = mlen;
memcpy(p, m, n);
p += n;
}
return keyblobtoid(buf, p - buf, dst, dstlen);
}
#ifdef KEYBLOBTOID_MAIN
#include <stdio.h>
void regress();
int
main(argc, argv)
int argc;
char *argv[];
{
typedef unsigned char uc;
uc hexblob[] = "\x01\x03\x85\xf2\xd6\x76\x9b\x03\x59\xb6\x21\x52";
uc hexe[] = "\x03";
uc hexm[] = "\x85\xf2\xd6\x76\x9b\x03\x59\xb6\x21\x52\xef\x85";
char b64nine[] = "AQOF8tZ2m";
char b64six[] = "AQOF8t";
char buf[100];
size_t n;
char *b = b64nine;
size_t bl = strlen(b) + 1;
int st = 0;
n = keyblobtoid(hexblob, strlen(hexblob), buf, sizeof(buf));
if (n != bl) {
fprintf(stderr, "%s: keyblobtoid returned %d not %d\n",
argv[0], n, bl);
st = 1;
}
if (strcmp(buf, b) != 0) {
fprintf(stderr, "%s: keyblobtoid generated `%s' not `%s'\n",
argv[0], buf, b);
st = 1;
}
n = splitkeytoid(hexe, strlen(hexe), hexm, strlen(hexm), buf,
sizeof(buf));
if (n != bl) {
fprintf(stderr, "%s: splitkeytoid returned %d not %d\n",
argv[0], n, bl);
st = 1;
}
if (strcmp(buf, b) != 0) {
fprintf(stderr, "%s: splitkeytoid generated `%s' not `%s'\n",
argv[0], buf, b);
st = 1;
}
exit(st);
}
#endif /* KEYBLOBTOID_MAIN */
+182
View File
@@ -0,0 +1,182 @@
.TH IPSEC_OPTIONSFROM 3 "16 Oct 1998"
.\" RCSID $Id: optionsfrom.3,v 1.1 2004/03/15 20:35:26 as Exp $
.SH NAME
ipsec optionsfrom \- read additional ``command-line'' options from file
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "const char *optionsfrom(char *filename, int *argcp,"
.ti +1c
.B "char ***argvp, int optind, FILE *errsto);"
.SH DESCRIPTION
.I Optionsfrom
is called from within a
.IR getopt_long (3)
scan,
as the result of the appearance of an option (preferably
.BR \-\-optionsfrom )
to insert additional ``command-line'' arguments
into the scan immediately after
the option.
Typically this would be done to pick up options which are
security-sensitive and should not be visible to
.IR ps (1)
and similar commands,
and hence cannot be supplied as part
of the actual command line or the environment.
.PP
.I Optionsfrom
reads the additional arguments from the specified
.IR filename ,
allocates a new argument vector to hold pointers to the existing
arguments plus the new ones,
and amends
.I argc
and
.I argv
(via the pointers
.I argcp
and
.IR argvp ,
which must point to the
.I argc
and
.I argv
being supplied to
.IR getopt_long (3))
accordingly.
.I Optind
must be the index, in the original argument vector,
of the next argument.
.PP
If
.I errsto
is NULL,
.I optionsfrom
returns NULL for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
If
.I errsto
is non-NULL and an error occurs,
.I optionsfrom
prints a suitable complaint onto the
.I errsto
descriptor and invokes
.I exit
with an exit status of 2;
this is a convenience for cases where more sophisticated
responses are not required.
.PP
The text of existing arguments is not disturbed by
.IR optionsfrom ,
so pointers to them and into them remain valid.
.PP
The file of additional arguments is an ASCII text file.
Lines consisting solely of white space,
and lines beginning with
.BR # ,
are comments and are ignored.
Otherwise, a line which does not begin with
.BR \-
is taken to be a single argument;
if it both begins and ends with double-quote ("),
those quotes are stripped off (note, no other processing is done within
the line!).
A line beginning with
.B \-
is considered to contain multiple arguments separated by white space.
.PP
Because
.I optionsfrom
reads its entire file before the
.IR getopt_long (3)
scan is resumed, an
.I optionsfrom
file can contain another
.B \-\-optionsfrom
option.
Obviously, infinite loops are possible here.
If
.I errsto
is non-NULL,
.I optionsfrom
considers it an error to be called more than 100 times.
If
.I errsto
is NULL,
loop detection is up to the caller
(and the internal loop counter is zeroed out).
.SH EXAMPLE
A reasonable way to invoke
.I optionsfrom
would be like so:
.PP
.nf
.ft B
#include <getopt.h>
struct option opts[] = {
/* ... */
"optionsfrom", 1, NULL, '+',
/* ... */
};
int
main(argc, argv)
int argc;
char *argv[];
{
int opt;
extern char *optarg;
extern int optind;
while ((opt = getopt_long(argc, argv, "", opts, NULL)) != EOF)
switch (opt) {
/* ... */
case '+': /* optionsfrom */
optionsfrom(optarg, &argc, &argv, optind, stderr);
/* does not return on error */
break;
/* ... */
}
/* ... */
.ft
.fi
.SH SEE ALSO
getopt_long(3)
.SH DIAGNOSTICS
Errors in
.I optionsfrom
are:
unable to open file;
attempt to allocate temporary storage for argument or
argument vector failed;
read error in file;
line too long.
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
The double-quote convention is rather simplistic.
.PP
Line length is currently limited to 1023 bytes,
and there is no continuation convention.
.PP
The restriction of error reports to literal strings
(so that callers don't need to worry about freeing them or copying them)
does limit the precision of error reporting.
.PP
The error-reporting convention lends itself
to slightly obscure code,
because many readers will not think of NULL as signifying success.
.PP
There is a certain element of unwarranted chumminess with
the insides of
.IR getopt_long (3)
here.
No non-public interfaces are actually used, but
.IR optionsfrom
does rely on
.IR getopt_long (3)
being well-behaved in certain ways that are not actually
promised by the specs.
+301
View File
@@ -0,0 +1,301 @@
/*
* pick up more options from a file, in the middle of an option scan
* Copyright (C) 1998, 1999 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: optionsfrom.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
#include <stdio.h>
#define MAX 100 /* loop-detection limit */
/* internal work area */
struct work {
# define LOTS 1024
char buf[LOTS];
char *line;
char *pending;
};
static const char *dowork(const char *, int *, char ***, int);
static const char *getanarg(FILE *, struct work *, char **);
static char *getline(FILE *, char *, size_t);
/*
- optionsfrom - add some options, taken from a file, to argc/argv
* If errsto is non-NULL, does not return in event of error.
*/
const char * /* NULL for success, else string literal */
optionsfrom(filename, argcp, argvp, optind, errsto)
const char *filename;
int *argcp; /* pointer to argc */
char ***argvp; /* pointer to argv */
int optind; /* current optind, number of next argument */
FILE *errsto; /* where to report errors (NULL means return) */
{
const char *e;
static int nuses = 0;
if (errsto != NULL) {
nuses++;
if (nuses >= MAX) {
fprintf(errsto,
"%s: optionsfrom called %d times, looping?\n",
(*argvp)[0], nuses);
exit(2);
}
} else
nuses = 0;
e = dowork(filename, argcp, argvp, optind);
if (e != NULL && errsto != NULL) {
fprintf(errsto, "%s: optionsfrom failed: %s\n", (*argvp)[0], e);
exit(2);
}
return e;
}
/*
- dowork - do all the real work of optionsfrom
* Does not alter the existing arguments, but does relocate and alter
* the argv pointer vector.
*/
static const char * /* NULL for success, else string literal */
dowork(filename, argcp, argvp, optind)
const char *filename;
int *argcp; /* pointer to argc */
char ***argvp; /* pointer to argv */
int optind; /* current optind, number of next argument */
{
char **newargv;
char **tmp;
int newargc;
int next; /* place for next argument */
int room; /* how many more new arguments we can hold */
# define SOME 10 /* first guess at how many we'll need */
FILE *f;
int i;
const char *p;
struct work wa; /* for getanarg() */
f = fopen(filename, "r");
if (f == NULL)
return "unable to open file";
newargc = *argcp + SOME;
newargv = malloc((newargc+1) * sizeof(char *));
if (newargv == NULL)
return "unable to allocate memory";
memcpy(newargv, *argvp, optind * sizeof(char *));
room = SOME;
next = optind;
newargv[next] = NULL;
wa.pending = NULL;
while ((p = getanarg(f, &wa, &newargv[next])) == NULL) {
if (room == 0) {
newargc += SOME;
tmp = realloc(newargv, (newargc+1) * sizeof(char *));
if (tmp == NULL) {
p = "out of space for new argv";
break; /* NOTE BREAK OUT */
}
newargv = tmp;
room += SOME;
}
next++;
room--;
}
if (p != NULL && !feof(f)) { /* error of some kind */
for (i = optind+1; i <= next; i++)
if (newargv[i] != NULL)
free(newargv[i]);
free(newargv);
fclose(f);
return p;
}
fclose(f);
memcpy(newargv + next, *argvp + optind,
(*argcp+1-optind) * sizeof(char *));
*argcp += next - optind;
*argvp = newargv;
return NULL;
}
/*
- getanarg - get a malloced argument from the file
*/
static const char * /* NULL for success, else string literal */
getanarg(f, w, linep)
FILE *f;
struct work *w;
char **linep; /* where to store pointer if successful */
{
size_t len;
char *p;
char *endp;
while (w->pending == NULL) { /* no pending line */
if ((w->line = getline(f, w->buf, sizeof(w->buf))) == NULL)
return "error in line read"; /* caller checks EOF */
if (w->line[0] != '#' &&
*(w->line + strspn(w->line, " \t")) != '\0')
w->pending = w->line;
}
if (w->pending == w->line && w->line[0] != '-') {
/* fresh plain line */
w->pending = NULL;
p = w->line;
endp = p + strlen(p);
if (*p == '"' && endp > p+1 && *(endp-1) == '"') {
p++;
endp--;
*endp = '\0';
}
if (w->line == w->buf) {
*linep = malloc(endp - p + 1);
if (*linep == NULL)
return "out of memory for new line";
strcpy(*linep, p);
} else /* getline already malloced it */
*linep = p;
return NULL;
}
/* chip off a piece of a pending line */
p = w->pending;
p += strspn(p, " \t");
endp = p + strcspn(p, " \t");
len = endp - p;
if (*endp != '\0') {
*endp++ = '\0';
endp += strspn(endp, " \t");
}
/* endp now points to next real character, or to line-end NUL */
*linep = malloc(len + 1);
if (*linep == NULL) {
if (w->line != w->buf)
free(w->line);
return "out of memory for new argument";
}
strcpy(*linep, p);
if (*endp == '\0') {
w->pending = NULL;
if (w->line != w->buf)
free(w->line);
} else
w->pending = endp;
return NULL;
}
/*
- getline - read a line from the file, trim newline off
*/
static char * /* pointer to line, NULL for eof/error */
getline(f, buf, bufsize)
FILE *f;
char *buf; /* buffer to use, if convenient */
size_t bufsize; /* size of buf */
{
size_t len;
if (fgets(buf, bufsize, f) == NULL)
return NULL;
len = strlen(buf);
if (len < bufsize-1 || buf[bufsize-1] == '\n') {
/* it fit */
buf[len-1] = '\0';
return buf;
}
/* oh crud, buffer overflow */
/* for now, to hell with it */
return NULL;
}
#ifdef TEST
#include <getopt.h>
char usage[] = "Usage: tester [--foo] [--bar] [--optionsfrom file] arg ...";
struct option opts[] = {
"foo", 0, NULL, 'f',
"bar", 0, NULL, 'b',
"builtin", 0, NULL, 'B',
"optionsfrom", 1, NULL, '+',
"help", 0, NULL, 'h',
"version", 0, NULL, 'v',
0, 0, NULL, 0,
};
int
main(argc, argv)
int argc;
char *argv[];
{
int opt;
extern char *optarg;
extern int optind;
int errflg = 0;
const char *p;
int i;
FILE *errs = NULL;
while ((opt = getopt_long(argc, argv, "", opts, NULL)) != EOF)
switch (opt) {
case 'f':
case 'b':
break;
case 'B':
errs = stderr;
break;
case '+': /* optionsfrom */
p = optionsfrom(optarg, &argc, &argv, optind, errs);
if (p != NULL) {
fprintf(stderr, "%s: optionsfrom error: %s\n",
argv[0], p);
exit(1);
}
break;
case 'h': /* help */
printf("%s\n", usage);
exit(0);
break;
case 'v': /* version */
printf("1\n");
exit(0);
break;
case '?':
default:
errflg = 1;
break;
}
if (errflg) {
fprintf(stderr, "%s\n", usage);
exit(2);
}
for (i = 1; i < argc; i++)
printf("%d: `%s'\n", i, argv[i]);
exit(0);
}
#endif /* TEST */
File diff suppressed because it is too large Load Diff
+179
View File
@@ -0,0 +1,179 @@
/*
* @(#) pfkey version 2 debugging messages
*
* Copyright (C) 2001 Richard Guy Briggs <[email protected]>
* and Michael Richardson <[email protected]>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU 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/gpl.txt>.
*
* This program 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 General Public License
* for more details.
*
* RCSID $Id: pfkey_v2_debug.c,v 1.2 2004/03/22 21:53:18 as Exp $
*
*/
#ifdef __KERNEL__
# include <linux/kernel.h> /* for printk */
# include "freeswan/ipsec_kversion.h" /* for malloc switch */
# ifdef MALLOC_SLAB
# include <linux/slab.h> /* kmalloc() */
# else /* MALLOC_SLAB */
# include <linux/malloc.h> /* kmalloc() */
# endif /* MALLOC_SLAB */
# include <linux/errno.h> /* error codes */
# include <linux/types.h> /* size_t */
# include <linux/interrupt.h> /* mark_bh */
# include <linux/netdevice.h> /* struct device, and other headers */
# include <linux/etherdevice.h> /* eth_type_trans */
extern int debug_pfkey;
#else /* __KERNEL__ */
# include <sys/types.h>
# include <linux/types.h>
# include <linux/errno.h>
#endif /* __KERNEL__ */
#include "freeswan.h"
#include "pfkeyv2.h"
#include "pfkey.h"
/*
* This file provides ASCII translations of PF_KEY magic numbers.
*
*/
static char *pfkey_sadb_ext_strings[]={
"reserved", /* SADB_EXT_RESERVED 0 */
"security-association", /* SADB_EXT_SA 1 */
"lifetime-current", /* SADB_EXT_LIFETIME_CURRENT 2 */
"lifetime-hard", /* SADB_EXT_LIFETIME_HARD 3 */
"lifetime-soft", /* SADB_EXT_LIFETIME_SOFT 4 */
"source-address", /* SADB_EXT_ADDRESS_SRC 5 */
"destination-address", /* SADB_EXT_ADDRESS_DST 6 */
"proxy-address", /* SADB_EXT_ADDRESS_PROXY 7 */
"authentication-key", /* SADB_EXT_KEY_AUTH 8 */
"cipher-key", /* SADB_EXT_KEY_ENCRYPT 9 */
"source-identity", /* SADB_EXT_IDENTITY_SRC 10 */
"destination-identity", /* SADB_EXT_IDENTITY_DST 11 */
"sensitivity-label", /* SADB_EXT_SENSITIVITY 12 */
"proposal", /* SADB_EXT_PROPOSAL 13 */
"supported-auth", /* SADB_EXT_SUPPORTED_AUTH 14 */
"supported-cipher", /* SADB_EXT_SUPPORTED_ENCRYPT 15 */
"spi-range", /* SADB_EXT_SPIRANGE 16 */
"X-kmpprivate", /* SADB_X_EXT_KMPRIVATE 17 */
"X-satype2", /* SADB_X_EXT_SATYPE2 18 */
"X-security-association", /* SADB_X_EXT_SA2 19 */
"X-destination-address2", /* SADB_X_EXT_ADDRESS_DST2 20 */
"X-source-flow-address", /* SADB_X_EXT_ADDRESS_SRC_FLOW 21 */
"X-dest-flow-address", /* SADB_X_EXT_ADDRESS_DST_FLOW 22 */
"X-source-mask", /* SADB_X_EXT_ADDRESS_SRC_MASK 23 */
"X-dest-mask", /* SADB_X_EXT_ADDRESS_DST_MASK 24 */
"X-set-debug", /* SADB_X_EXT_DEBUG 25 */
#ifdef NAT_TRAVERSAL
"X-NAT-T-type", /* SADB_X_EXT_NAT_T_TYPE 26 */
"X-NAT-T-sport", /* SADB_X_EXT_NAT_T_SPORT 27 */
"X-NAT-T-dport", /* SADB_X_EXT_NAT_T_DPORT 28 */
"X-NAT-T-OA", /* SADB_X_EXT_NAT_T_OA 29 */
#endif
};
const char *
pfkey_v2_sadb_ext_string(int ext)
{
if(ext <= SADB_EXT_MAX) {
return pfkey_sadb_ext_strings[ext];
} else {
return "unknown-ext";
}
}
static char *pfkey_sadb_type_strings[]={
"reserved", /* SADB_RESERVED */
"getspi", /* SADB_GETSPI */
"update", /* SADB_UPDATE */
"add", /* SADB_ADD */
"delete", /* SADB_DELETE */
"get", /* SADB_GET */
"acquire", /* SADB_ACQUIRE */
"register", /* SADB_REGISTER */
"expire", /* SADB_EXPIRE */
"flush", /* SADB_FLUSH */
"dump", /* SADB_DUMP */
"x-promisc", /* SADB_X_PROMISC */
"x-pchange", /* SADB_X_PCHANGE */
"x-groupsa", /* SADB_X_GRPSA */
"x-addflow(eroute)", /* SADB_X_ADDFLOW */
"x-delflow(eroute)", /* SADB_X_DELFLOW */
"x-debug", /* SADB_X_DEBUG */
};
const char *
pfkey_v2_sadb_type_string(int sadb_type)
{
if(sadb_type <= SADB_MAX) {
return pfkey_sadb_type_strings[sadb_type];
} else {
return "unknown-sadb-type";
}
}
/*
* $Log: pfkey_v2_debug.c,v $
* Revision 1.2 2004/03/22 21:53:18 as
* merged alg-0.8.1 branch with HEAD
*
* Revision 1.1.2.1 2004/03/15 22:30:06 as
* nat-0.6c patch merged
*
* Revision 1.1 2004/03/15 20:35:26 as
* added files from freeswan-2.04-x509-1.5.3
*
* Revision 1.7 2002/09/20 05:01:26 rgb
* Fixed limit inclusion error in both type and ext string conversion.
*
* Revision 1.6 2002/04/24 07:55:32 mcr
* #include patches and Makefiles for post-reorg compilation.
*
* Revision 1.5 2002/04/24 07:36:40 mcr
* Moved from ./lib/pfkey_v2_debug.c,v
*
* Revision 1.4 2002/01/29 22:25:36 rgb
* Re-add ipsec_kversion.h to keep MALLOC happy.
*
* Revision 1.3 2002/01/29 01:59:09 mcr
* removal of kversions.h - sources that needed it now use ipsec_param.h.
* updating of IPv6 structures to match latest in6.h version.
* removed dead code from freeswan.h that also duplicated kversions.h
* code.
*
* Revision 1.2 2002/01/20 20:34:50 mcr
* added pfkey_v2_sadb_type_string to decode sadb_type to string.
*
* Revision 1.1 2001/11/27 05:30:06 mcr
* initial set of debug strings for pfkey debugging.
* this will eventually only be included for debug builds.
*
* Revision 1.1 2001/09/21 04:12:03 mcr
* first compilable version.
*
*
* Local variables:
* c-file-style: "linux"
* End:
*
*/
+803
View File
@@ -0,0 +1,803 @@
/*
* RFC2367 PF_KEYv2 Key management API message parser
* Copyright (C) 1999, 2000, 2001 Richard Guy Briggs.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU 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/gpl.txt>.
*
* This program 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 General Public License
* for more details.
*
* RCSID $Id: pfkey_v2_ext_bits.c,v 1.2 2004/03/22 21:53:18 as Exp $
*/
/*
* Template from klips/net/ipsec/ipsec/ipsec_parse.c.
*/
char pfkey_v2_ext_bits_c_version[] = "$Id: pfkey_v2_ext_bits.c,v 1.2 2004/03/22 21:53:18 as Exp $";
/*
* Some ugly stuff to allow consistent debugging code for use in the
* kernel and in user space
*/
#ifdef __KERNEL__
# include <linux/kernel.h> /* for printk */
# include "freeswan/ipsec_kversion.h" /* for malloc switch */
# ifdef MALLOC_SLAB
# include <linux/slab.h> /* kmalloc() */
# else /* MALLOC_SLAB */
# include <linux/malloc.h> /* kmalloc() */
# endif /* MALLOC_SLAB */
# include <linux/errno.h> /* error codes */
# include <linux/types.h> /* size_t */
# include <linux/interrupt.h> /* mark_bh */
# include <linux/netdevice.h> /* struct device, and other headers */
# include <linux/etherdevice.h> /* eth_type_trans */
# include <linux/ip.h> /* struct iphdr */
# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
# include <linux/ipv6.h>
# endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
#else /* __KERNEL__ */
# include <sys/types.h>
# include <linux/types.h>
# include <linux/errno.h>
#endif
#include <freeswan.h>
#include <pfkeyv2.h>
#include <pfkey.h>
unsigned int extensions_bitmaps[2/*in/out*/][2/*perm/req*/][SADB_MAX + 1/*ext*/] = {
/* INBOUND EXTENSIONS */
{
/* PERMITTED IN */
{
/* SADB_RESERVED */
0
,
/* SADB_GETSPI */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_SPIRANGE
,
/* SADB_UPDATE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
#ifdef NAT_TRAVERSAL
| 1<<SADB_X_EXT_NAT_T_SPORT
| 1<<SADB_X_EXT_NAT_T_DPORT
#endif
,
/* SADB_ADD */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
#ifdef NAT_TRAVERSAL
| 1<<SADB_X_EXT_NAT_T_TYPE
| 1<<SADB_X_EXT_NAT_T_SPORT
| 1<<SADB_X_EXT_NAT_T_DPORT
| 1<<SADB_X_EXT_NAT_T_OA
#endif
,
/* SADB_DELETE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_GET */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_ACQUIRE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_EXT_PROPOSAL
,
/* SADB_REGISTER */
1<<SADB_EXT_RESERVED
,
/* SADB_EXPIRE */
0
,
/* SADB_FLUSH */
1<<SADB_EXT_RESERVED
,
/* SADB_DUMP */
1<<SADB_EXT_RESERVED
,
/* SADB_X_PROMISC */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_EXT_PROPOSAL
| 1<<SADB_EXT_SUPPORTED_AUTH
| 1<<SADB_EXT_SUPPORTED_ENCRYPT
| 1<<SADB_EXT_SPIRANGE
| 1<<SADB_X_EXT_KMPRIVATE
| 1<<SADB_X_EXT_SATYPE2
| 1<<SADB_X_EXT_SA2
| 1<<SADB_X_EXT_ADDRESS_DST2
,
/* SADB_X_PCHANGE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_EXT_PROPOSAL
| 1<<SADB_EXT_SUPPORTED_AUTH
| 1<<SADB_EXT_SUPPORTED_ENCRYPT
| 1<<SADB_EXT_SPIRANGE
| 1<<SADB_X_EXT_KMPRIVATE
| 1<<SADB_X_EXT_SATYPE2
| 1<<SADB_X_EXT_SA2
| 1<<SADB_X_EXT_ADDRESS_DST2
,
/* SADB_X_GRPSA */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_X_EXT_SATYPE2
| 1<<SADB_X_EXT_SA2
| 1<<SADB_X_EXT_ADDRESS_DST2
,
/* SADB_X_ADDFLOW */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
| 1<<SADB_X_EXT_ADDRESS_DST_MASK
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_X_EXT_PROTOCOL
,
/* SADB_X_DELFLOW */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
| 1<<SADB_X_EXT_ADDRESS_DST_MASK
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_X_EXT_PROTOCOL
,
/* SADB_X_DEBUG */
1<<SADB_EXT_RESERVED
| 1<<SADB_X_EXT_DEBUG
#ifdef NAT_TRAVERSAL
,
/* SADB_X_NAT_T_NEW_MAPPING */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_X_EXT_NAT_T_SPORT
| 1<<SADB_X_EXT_NAT_T_DPORT
#endif
},
/* REQUIRED IN */
{
/* SADB_RESERVED */
0
,
/* SADB_GETSPI */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_SPIRANGE
,
/* SADB_UPDATE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
/*| 1<<SADB_EXT_KEY_AUTH*/
/*| 1<<SADB_EXT_KEY_ENCRYPT*/
,
/* SADB_ADD */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
/*| 1<<SADB_EXT_KEY_AUTH*/
/*| 1<<SADB_EXT_KEY_ENCRYPT*/
,
/* SADB_DELETE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_GET */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_ACQUIRE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_PROPOSAL
,
/* SADB_REGISTER */
1<<SADB_EXT_RESERVED
,
/* SADB_EXPIRE */
0
,
/* SADB_FLUSH */
1<<SADB_EXT_RESERVED
,
/* SADB_DUMP */
1<<SADB_EXT_RESERVED
,
/* SADB_X_PROMISC */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_EXT_PROPOSAL
| 1<<SADB_EXT_SUPPORTED_AUTH
| 1<<SADB_EXT_SUPPORTED_ENCRYPT
| 1<<SADB_EXT_SPIRANGE
| 1<<SADB_X_EXT_KMPRIVATE
| 1<<SADB_X_EXT_SATYPE2
| 1<<SADB_X_EXT_SA2
| 1<<SADB_X_EXT_ADDRESS_DST2
,
/* SADB_X_PCHANGE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_EXT_PROPOSAL
| 1<<SADB_EXT_SUPPORTED_AUTH
| 1<<SADB_EXT_SUPPORTED_ENCRYPT
| 1<<SADB_EXT_SPIRANGE
| 1<<SADB_X_EXT_KMPRIVATE
| 1<<SADB_X_EXT_SATYPE2
| 1<<SADB_X_EXT_SA2
| 1<<SADB_X_EXT_ADDRESS_DST2
,
/* SADB_X_GRPSA */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_DST
/*| 1<<SADB_X_EXT_SATYPE2*/
/*| 1<<SADB_X_EXT_SA2*/
/*| 1<<SADB_X_EXT_ADDRESS_DST2*/
,
/* SADB_X_ADDFLOW */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
| 1<<SADB_X_EXT_ADDRESS_DST_MASK
,
/* SADB_X_DELFLOW */
1<<SADB_EXT_RESERVED
/*| 1<<SADB_EXT_SA*/
#if 0 /* SADB_X_CLREROUTE doesn't need all these... */
| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
| 1<<SADB_X_EXT_ADDRESS_DST_MASK
#endif
,
/* SADB_X_DEBUG */
1<<SADB_EXT_RESERVED
| 1<<SADB_X_EXT_DEBUG
#ifdef NAT_TRAVERSAL
,
/* SADB_X_NAT_T_NEW_MAPPING */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_X_EXT_NAT_T_SPORT
| 1<<SADB_X_EXT_NAT_T_DPORT
#endif
}
},
/* OUTBOUND EXTENSIONS */
{
/* PERMITTED OUT */
{
/* SADB_RESERVED */
0
,
/* SADB_GETSPI */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_UPDATE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
,
/* SADB_ADD */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
#ifdef NAT_TRAVERSAL
| 1<<SADB_X_EXT_NAT_T_TYPE
| 1<<SADB_X_EXT_NAT_T_SPORT
| 1<<SADB_X_EXT_NAT_T_DPORT
| 1<<SADB_X_EXT_NAT_T_OA
#endif
,
/* SADB_DELETE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_GET */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
,
/* SADB_ACQUIRE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_EXT_PROPOSAL
,
/* SADB_REGISTER */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SUPPORTED_AUTH
| 1<<SADB_EXT_SUPPORTED_ENCRYPT
,
/* SADB_EXPIRE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_FLUSH */
1<<SADB_EXT_RESERVED
,
/* SADB_DUMP */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
,
/* SADB_X_PROMISC */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_EXT_PROPOSAL
| 1<<SADB_EXT_SUPPORTED_AUTH
| 1<<SADB_EXT_SUPPORTED_ENCRYPT
| 1<<SADB_EXT_SPIRANGE
| 1<<SADB_X_EXT_KMPRIVATE
| 1<<SADB_X_EXT_SATYPE2
| 1<<SADB_X_EXT_SA2
| 1<<SADB_X_EXT_ADDRESS_DST2
,
/* SADB_X_PCHANGE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_EXT_PROPOSAL
| 1<<SADB_EXT_SUPPORTED_AUTH
| 1<<SADB_EXT_SUPPORTED_ENCRYPT
| 1<<SADB_EXT_SPIRANGE
| 1<<SADB_X_EXT_KMPRIVATE
| 1<<SADB_X_EXT_SATYPE2
| 1<<SADB_X_EXT_SA2
| 1<<SADB_X_EXT_ADDRESS_DST2
,
/* SADB_X_GRPSA */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_X_EXT_SATYPE2
| 1<<SADB_X_EXT_SA2
| 1<<SADB_X_EXT_ADDRESS_DST2
,
/* SADB_X_ADDFLOW */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
| 1<<SADB_X_EXT_ADDRESS_DST_MASK
| 1<<SADB_X_EXT_PROTOCOL
,
/* SADB_X_DELFLOW */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
| 1<<SADB_X_EXT_ADDRESS_DST_MASK
| 1<<SADB_X_EXT_PROTOCOL
,
/* SADB_X_DEBUG */
1<<SADB_EXT_RESERVED
| 1<<SADB_X_EXT_DEBUG
#ifdef NAT_TRAVERSAL
,
/* SADB_X_NAT_T_NEW_MAPPING */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_X_EXT_NAT_T_SPORT
| 1<<SADB_X_EXT_NAT_T_DPORT
#endif
},
/* REQUIRED OUT */
{
/* SADB_RESERVED */
0
,
/* SADB_GETSPI */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_UPDATE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_ADD */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_DELETE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_GET */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
/* | 1<<SADB_EXT_KEY_AUTH */
/* | 1<<SADB_EXT_KEY_ENCRYPT */
,
/* SADB_ACQUIRE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_PROPOSAL
,
/* SADB_REGISTER */
1<<SADB_EXT_RESERVED
/* | 1<<SADB_EXT_SUPPORTED_AUTH
| 1<<SADB_EXT_SUPPORTED_ENCRYPT */
,
/* SADB_EXPIRE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
/* | 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT */
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_FLUSH */
1<<SADB_EXT_RESERVED
,
/* SADB_DUMP */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
,
/* SADB_X_PROMISC */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_EXT_PROPOSAL
| 1<<SADB_EXT_SUPPORTED_AUTH
| 1<<SADB_EXT_SUPPORTED_ENCRYPT
| 1<<SADB_EXT_SPIRANGE
| 1<<SADB_X_EXT_KMPRIVATE
| 1<<SADB_X_EXT_SATYPE2
| 1<<SADB_X_EXT_SA2
| 1<<SADB_X_EXT_ADDRESS_DST2
,
/* SADB_X_PCHANGE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_EXT_PROPOSAL
| 1<<SADB_EXT_SUPPORTED_AUTH
| 1<<SADB_EXT_SUPPORTED_ENCRYPT
| 1<<SADB_EXT_SPIRANGE
| 1<<SADB_X_EXT_KMPRIVATE
| 1<<SADB_X_EXT_SATYPE2
| 1<<SADB_X_EXT_SA2
| 1<<SADB_X_EXT_ADDRESS_DST2
,
/* SADB_X_GRPSA */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_X_ADDFLOW */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
| 1<<SADB_X_EXT_ADDRESS_DST_MASK
,
/* SADB_X_DELFLOW */
1<<SADB_EXT_RESERVED
/*| 1<<SADB_EXT_SA*/
| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
| 1<<SADB_X_EXT_ADDRESS_DST_MASK
,
/* SADB_X_DEBUG */
1<<SADB_EXT_RESERVED
| 1<<SADB_X_EXT_DEBUG
#ifdef NAT_TRAVERSAL
,
/* SADB_X_NAT_T_NEW_MAPPING */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_X_EXT_NAT_T_SPORT
| 1<<SADB_X_EXT_NAT_T_DPORT
#endif
}
}
};
/*
* $Log: pfkey_v2_ext_bits.c,v $
* Revision 1.2 2004/03/22 21:53:18 as
* merged alg-0.8.1 branch with HEAD
*
* Revision 1.1.2.1 2004/03/15 22:30:06 as
* nat-0.6c patch merged
*
* Revision 1.1 2004/03/15 20:35:26 as
* added files from freeswan-2.04-x509-1.5.3
*
* Revision 1.15 2002/04/24 07:55:32 mcr
* #include patches and Makefiles for post-reorg compilation.
*
* Revision 1.14 2002/04/24 07:36:40 mcr
* Moved from ./lib/pfkey_v2_ext_bits.c,v
*
* Revision 1.13 2002/01/29 22:25:36 rgb
* Re-add ipsec_kversion.h to keep MALLOC happy.
*
* Revision 1.12 2002/01/29 01:59:10 mcr
* removal of kversions.h - sources that needed it now use ipsec_param.h.
* updating of IPv6 structures to match latest in6.h version.
* removed dead code from freeswan.h that also duplicated kversions.h
* code.
*
* Revision 1.11 2001/10/18 04:45:24 rgb
* 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
* lib/freeswan.h version macros moved to lib/kversions.h.
* Other compiler directive cleanups.
*
* Revision 1.10 2001/09/08 21:13:35 rgb
* Added pfkey ident extension support for ISAKMPd. (NetCelo)
*
* Revision 1.9 2001/06/14 19:35:16 rgb
* Update copyright date.
*
* Revision 1.8 2001/03/26 23:07:36 rgb
* Remove requirement for auth and enc key from UPDATE.
*
* Revision 1.7 2000/09/12 22:35:37 rgb
* Restructured to remove unused extensions from CLEARFLOW messages.
*
* Revision 1.6 2000/09/09 06:39:01 rgb
* Added comments for clarity.
*
* Revision 1.5 2000/06/02 22:54:14 rgb
* Added Gerhard Gessler's struct sockaddr_storage mods for IPv6 support.
*
* Revision 1.4 2000/01/21 06:27:56 rgb
* Added address cases for eroute flows.
* Added comments for each message type.
* Added klipsdebug switching capability.
* Fixed GRPSA bitfields.
*
* Revision 1.3 1999/12/01 22:20:27 rgb
* Remove requirement for a proxy address in an incoming getspi message.
*
* Revision 1.2 1999/11/27 11:57:06 rgb
* Consolidated the 4 1-d extension bitmap arrays into one 4-d array.
* Add CVS log entry to bottom of file.
* Cleaned out unused bits.
*
*/
File diff suppressed because it is too large Load Diff
+70
View File
@@ -0,0 +1,70 @@
.TH IPSEC_PORTOF 3 "8 Sept 2000"
.\" RCSID $Id: portof.3,v 1.1 2004/03/15 20:35:26 as Exp $
.SH NAME
ipsec portof \- get port field of an ip_address
.br
ipsec setportof \- set port field of an ip_address
.br
ipsec sockaddrof \- get pointer to internal sockaddr of an ip_address
.br
ipsec sockaddrlenof \- get length of internal sockaddr of an ip_address
.SH SYNOPSIS
.B "#include <freeswan.h>"
.sp
.B "int portof(const ip_address *src);"
.br
.B "void setportof(int port, ip_address *dst);"
.br
.B "struct sockaddr *sockaddrof(ip_address *src);"
.br
.B "size_t sockaddrlenof(const ip_address *src);"
.SH DESCRIPTION
The
.B <freeswan.h>
internal type
.I ip_address
contains one of the
.I sockaddr
types internally.
\fIReliance on this feature is discouraged\fR,
but it may occasionally be necessary.
These functions provide low-level tools for this purpose.
.PP
.I Portof
and
.I setportof
respectively read and write the port-number field of the internal
.IR sockaddr .
The values are in network byte order.
.PP
.I Sockaddrof
returns a pointer to the internal
.IR sockaddr ,
for passing to other functions.
.PP
.I Sockaddrlenof
reports the size of the internal
.IR sockaddr ,
for use in storage allocation.
.SH SEE ALSO
inet(3), ipsec_initaddr(3)
.SH DIAGNOSTICS
.I Portof
returns
.BR \-1 ,
.I sockaddrof
returns
.BR NULL ,
and
.I sockaddrlenof
returns
.B 0
if an unknown address family is found within the
.IR ip_address .
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
These functions all depend on low-level details of the
.I ip_address
type, which are in principle subject to change.
Avoid using them unless really necessary.
+96
View File
@@ -0,0 +1,96 @@
/*
* low-level ip_address ugliness
* 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: portof.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
- portof - get the port field of an ip_address
*/
int /* network order */
portof(src)
const ip_address *src;
{
switch (src->u.v4.sin_family) {
case AF_INET:
return src->u.v4.sin_port;
break;
case AF_INET6:
return src->u.v6.sin6_port;
break;
default:
return -1; /* "can't happen" */
break;
}
}
/*
- setportof - set the port field of an ip_address
*/
void
setportof(port, dst)
int port; /* network order */
ip_address *dst;
{
switch (dst->u.v4.sin_family) {
case AF_INET:
dst->u.v4.sin_port = port;
break;
case AF_INET6:
dst->u.v6.sin6_port = port;
break;
}
}
/*
- sockaddrof - get a pointer to the sockaddr hiding inside an ip_address
*/
struct sockaddr *
sockaddrof(src)
ip_address *src;
{
switch (src->u.v4.sin_family) {
case AF_INET:
return (struct sockaddr *)&src->u.v4;
break;
case AF_INET6:
return (struct sockaddr *)&src->u.v6;
break;
default:
return NULL; /* "can't happen" */
break;
}
}
/*
- sockaddrlenof - get length of the sockaddr hiding inside an ip_address
*/
size_t /* 0 for error */
sockaddrlenof(src)
const ip_address *src;
{
switch (src->u.v4.sin_family) {
case AF_INET:
return sizeof(src->u.v4);
break;
case AF_INET6:
return sizeof(src->u.v6);
break;
default:
return 0;
break;
}
}
+121
View File
@@ -0,0 +1,121 @@
.TH IPSEC_PRNG 3 "1 April 2002"
.\" RCSID $Id: prng.3,v 1.1 2004/03/15 20:35:26 as Exp $
.SH NAME
ipsec prng_init \- initialize IPsec pseudorandom-number generator
.br
ipsec prng_bytes \- get bytes from IPsec pseudorandom-number generator
.br
ipsec prng_final \- close down IPsec pseudorandom-number generator
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "void prng_init(struct prng *prng,"
.ti +1c
.B "const unsigned char *key, size_t keylen);"
.br
.B "void prng_bytes(struct prng *prng, char *dst,"
.ti +1c
.B "size_t dstlen);"
.br
.B "unsigned long prng_count(struct prng *prng);"
.br
.B "void prng_final(struct prng *prng);"
.SH DESCRIPTION
.I Prng_init
initializes a crypto-quality pseudo-random-number generator from a key;
.I prng_bytes
obtains pseudo-random bytes from it;
.I prng_count
reports the number of bytes extracted from it to date;
.I prng_final
closes it down.
It is the user's responsibility to initialize a PRNG before using it,
and not to use it again after it is closed down.
.PP
.I Prng_init
initializes,
or re-initializes,
the specified
.I prng
from the
.IR key ,
whose length is given by
.IR keylen .
The user must allocate the
.B "struct prng"
pointed to by
.IR prng .
There is no particular constraint on the length of the key,
although a key longer than 256 bytes is unnecessary because
only the first 256 would be used.
Initialization requires on the order of 3000 integer operations,
independent of key length.
.PP
.I Prng_bytes
obtains
.I dstlen
pseudo-random bytes from the PRNG and puts them in
.IR buf .
This is quite fast,
on the order of 10 integer operations per byte.
.PP
.I Prng_count
reports the number of bytes obtained from the PRNG
since it was (last) initialized.
.PP
.I Prng_final
closes down a PRNG by
zeroing its internal memory,
obliterating all trace of the state used to generate its previous output.
This requires on the order of 250 integer operations.
.PP
The
.B <freeswan.h>
header file supplies the definition of the
.B prng
structure.
Examination of its innards is discouraged, as they may change.
.PP
The PRNG algorithm
used by these functions is currently identical to that of RC4(TM).
This algorithm is cryptographically strong,
sufficiently unpredictable that even a hostile observer will
have difficulty determining the next byte of output from past history,
provided it is initialized from a reasonably large key composed of
highly random bytes (see
.IR random (4)).
The usual run of software pseudo-random-number generators
(e.g.
.IR random (3))
are
.I not
cryptographically strong.
.PP
The well-known attacks against RC4(TM),
e.g. as found in 802.11b's WEP encryption system,
apply only if multiple PRNGs are initialized with closely-related keys
(e.g., using a counter appended to a base key).
If such keys are used, the first few hundred pseudo-random bytes
from each PRNG should be discarded,
to give the PRNGs a chance to randomize their innards properly.
No useful attacks are known if the key is well randomized to begin with.
.SH SEE ALSO
random(3), random(4)
.br
Bruce Schneier,
\fIApplied Cryptography\fR, 2nd ed., 1996, ISBN 0-471-11709-9,
pp. 397-8.
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
If an attempt is made to obtain more than 4e9 bytes
between initializations,
the PRNG will continue to work but
.IR prng_count 's
output will stick at
.BR 4000000000 .
Fixing this would require a longer integer type and does
not seem worth the trouble,
since you should probably re-initialize before then anyway...
.PP
``RC4'' is a trademark of RSA Data Security, Inc.
+202
View File
@@ -0,0 +1,202 @@
/*
* crypto-class pseudorandom number generator
* currently uses same algorithm as RC4(TM), from Schneier 2nd ed p397
* Copyright (C) 2002 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: prng.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
- prng_init - initialize PRNG from a key
*/
void
prng_init(prng, key, keylen)
struct prng *prng;
const unsigned char *key;
size_t keylen;
{
unsigned char k[256];
int i, j;
unsigned const char *p;
unsigned const char *keyend = key + keylen;
unsigned char t;
for (i = 0; i <= 255; i++)
prng->sbox[i] = i;
p = key;
for (i = 0; i <= 255; i++) {
k[i] = *p++;
if (p >= keyend)
p = key;
}
j = 0;
for (i = 0; i <= 255; i++) {
j = (j + prng->sbox[i] + k[i]) & 0xff;
t = prng->sbox[i];
prng->sbox[i] = prng->sbox[j];
prng->sbox[j] = t;
k[i] = 0; /* clear out key memory */
}
prng->i = 0;
prng->j = 0;
prng->count = 0;
}
/*
- prng_bytes - get some pseudorandom bytes from PRNG
*/
void
prng_bytes(prng, dst, dstlen)
struct prng *prng;
unsigned char *dst;
size_t dstlen;
{
int i, j, t;
unsigned char *p = dst;
size_t remain = dstlen;
# define MAX 4000000000ul
while (remain > 0) {
i = (prng->i + 1) & 0xff;
prng->i = i;
j = (prng->j + prng->sbox[i]) & 0xff;
prng->j = j;
t = prng->sbox[i];
prng->sbox[i] = prng->sbox[j];
prng->sbox[j] = t;
t = (t + prng->sbox[i]) & 0xff;
*p++ = prng->sbox[t];
remain--;
}
if (prng->count < MAX - dstlen)
prng->count += dstlen;
else
prng->count = MAX;
}
/*
- prnt_count - how many bytes have been extracted from PRNG so far?
*/
unsigned long
prng_count(prng)
struct prng *prng;
{
return prng->count;
}
/*
- prng_final - clear out PRNG to ensure nothing left in memory
*/
void
prng_final(prng)
struct prng *prng;
{
int i;
for (i = 0; i <= 255; i++)
prng->sbox[i] = 0;
prng->i = 0;
prng->j = 0;
prng->count = 0; /* just for good measure */
}
#ifdef PRNG_MAIN
#include <stdio.h>
void regress();
int
main(argc, argv)
int argc;
char *argv[];
{
struct prng pr;
unsigned char buf[100];
unsigned char *p;
size_t n;
if (argc < 2) {
fprintf(stderr, "Usage: %s {key|-r}\n", argv[0]);
exit(2);
}
if (strcmp(argv[1], "-r") == 0) {
regress();
fprintf(stderr, "regress() returned?!?\n");
exit(1);
}
prng_init(&pr, argv[1], strlen(argv[1]));
prng_bytes(&pr, buf, 32);
printf("0x");
for (p = buf, n = 32; n > 0; p++, n--)
printf("%02x", *p);
printf("\n%lu bytes\n", prng_count(&pr));
prng_final(&pr);
exit(0);
}
void
regress()
{
struct prng pr;
unsigned char buf[100];
unsigned char *p;
size_t n;
/* somewhat non-random sample key */
unsigned char key[] = "here we go gathering nuts in May";
/* first thirty bytes of output from that key */
unsigned char good[] = "\x3f\x02\x8e\x4a\x2a\xea\x23\x18\x92\x7c"
"\x09\x52\x83\x61\xaa\x26\xce\xbb\x9d\x71"
"\x71\xe5\x10\x22\xaf\x60\x54\x8d\x5b\x28";
int nzero, none;
int show = 0;
prng_init(&pr, key, strlen(key));
prng_bytes(&pr, buf, sizeof(buf));
for (p = buf, n = sizeof(buf); n > 0; p++, n--) {
if (*p == 0)
nzero++;
if (*p == 255)
none++;
}
if (nzero > 3 || none > 3) {
fprintf(stderr, "suspiciously non-random output!\n");
show = 1;
}
if (memcmp(buf, good, strlen(good)) != 0) {
fprintf(stderr, "incorrect output!\n");
show = 1;
}
if (show) {
fprintf(stderr, "0x");
for (p = buf, n = sizeof(buf); n > 0; p++, n--)
fprintf(stderr, "%02x", *p);
fprintf(stderr, "\n");
exit(1);
}
if (prng_count(&pr) != sizeof(buf)) {
fprintf(stderr, "got %u bytes, but count is %lu\n",
sizeof(buf), prng_count(&pr));
exit(1);
}
prng_final(&pr);
exit(0);
}
#endif /* PRNG_MAIN */
+61
View File
@@ -0,0 +1,61 @@
/*
* convert binary form of address range to ASCII
* Copyright (C) 1998, 1999 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: rangetoa.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
- rangetoa - convert address range to ASCII
*/
size_t /* space needed for full conversion */
rangetoa(addrs, format, dst, dstlen)
struct in_addr addrs[2];
int format; /* character */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
size_t len;
size_t rest;
int n;
char *p;
switch (format) {
case 0:
break;
default:
return 0;
break;
}
len = addrtoa(addrs[0], 0, dst, dstlen);
if (len < dstlen)
for (p = dst + len - 1, n = 3; len < dstlen && n > 0;
p++, len++, n--)
*p = '.';
else
p = NULL;
if (len < dstlen)
rest = dstlen - len;
else {
if (dstlen > 0)
*(dst + dstlen - 1) = '\0';
rest = 0;
}
len += addrtoa(addrs[1], 0, p, rest);
return len;
}
+59
View File
@@ -0,0 +1,59 @@
.TH IPSEC_RANGETOSUBNET 3 "8 Sept 2000"
.\" RCSID $Id: rangetosubnet.3,v 1.1 2004/03/15 20:35:26 as Exp $
.SH NAME
ipsec rangetosubnet \- convert address range to subnet
.SH SYNOPSIS
.B "#include <freeswan.h>"
.sp
.B "const char *rangetosubnet(const ip_address *start,"
.ti +1c
.B "const ip_address *stop, ip_subnet *dst);"
.SH DESCRIPTION
.I Rangetosubnet
accepts two IP addresses which define an address range,
from
.I start
to
.I stop
inclusive,
and converts this to a subnet if possible.
The addresses must both be IPv4 or both be IPv6,
and the address family of the resulting subnet is the same.
.PP
.I Rangetosubnet
returns NULL for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
.SH SEE ALSO
ipsec_initsubnet(3), ipsec_ttosubnet(3)
.SH DIAGNOSTICS
Fatal errors in
.I rangetosubnet
are:
mixed address families;
unknown address family;
.I start
and
.I stop
do not define a subnet.
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
The restriction of error reports to literal strings
(so that callers don't need to worry about freeing them or copying them)
does limit the precision of error reporting.
.PP
The error-reporting convention lends itself
to slightly obscure code,
because many readers will not think of NULL as signifying success.
A good way to make it clearer is to write something like:
.PP
.RS
.nf
.B "const char *error;"
.sp
.B "error = rangetosubnet( /* ... */ );"
.B "if (error != NULL) {"
.B " /* something went wrong */"
.fi
.RE
+226
View File
@@ -0,0 +1,226 @@
/*
* express an address range as a subnet (if possible)
* 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: rangetosubnet.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
- rangetosubnet - turn an address range into a subnet, if possible
*
* A range which is a valid subnet will have a network part which is the
* same in the from value and the to value, followed by a host part which
* is all 0 in the from value and all 1 in the to value.
*/
err_t
rangetosubnet(from, to, dst)
const ip_address *from;
const ip_address *to;
ip_subnet *dst;
{
unsigned const char *fp;
unsigned const char *tp;
unsigned fb;
unsigned tb;
unsigned const char *f;
unsigned const char *t;
size_t n;
size_t n2;
int i;
int nnet;
unsigned m;
if (addrtypeof(from) != addrtypeof(to))
return "mismatched address types";
n = addrbytesptr(from, &fp);
if (n == 0)
return "unknown address type";
n2 = addrbytesptr(to, &tp);
if (n != n2)
return "internal size mismatch in rangetosubnet";
f = fp;
t = tp;
nnet = 0;
for (i = n; i > 0 && *f == *t; i--, f++, t++)
nnet += 8;
if (i > 0 && !(*f == 0x00 && *t == 0xff)) { /* mid-byte bdry. */
fb = *f++;
tb = *t++;
i--;
m = 0x80;
while ((fb&m) == (tb&m)) {
fb &= ~m;
tb |= m;
m >>= 1;
nnet++;
}
if (fb != 0x00 || tb != 0xff)
return "not a valid subnet";
}
for (; i > 0 && *f == 0x00 && *t == 0xff; i--, f++, t++)
continue;
if (i != 0)
return "invalid subnet";
return initsubnet(from, nnet, 'x', dst);
}
#ifdef RANGETOSUBNET_MAIN
#include <stdio.h>
void regress(void);
int
main(int argc, char *argv[])
{
ip_address start;
ip_address stop;
ip_subnet sub;
char buf[100];
const char *oops;
size_t n;
int af;
int i;
if (argc == 2 && strcmp(argv[1], "-r") == 0) {
regress();
fprintf(stderr, "regress() returned?!?\n");
exit(1);
}
if (argc < 3) {
fprintf(stderr, "Usage: %s [-6] start stop\n", argv[0]);
fprintf(stderr, " or: %s -r\n", argv[0]);
exit(2);
}
af = AF_INET;
i = 1;
if (strcmp(argv[i], "-6") == 0) {
af = AF_INET6;
i++;
}
oops = ttoaddr(argv[i], 0, af, &start);
if (oops != NULL) {
fprintf(stderr, "%s: start conversion failed: %s\n", argv[0], oops);
exit(1);
}
oops = ttoaddr(argv[i+1], 0, af, &stop);
if (oops != NULL) {
fprintf(stderr, "%s: stop conversion failed: %s\n", argv[0], oops);
exit(1);
}
oops = rangetosubnet(&start, &stop, &sub);
if (oops != NULL) {
fprintf(stderr, "%s: rangetosubnet failed: %s\n", argv[0], oops);
exit(1);
}
n = subnettot(&sub, 0, buf, sizeof(buf));
if (n > sizeof(buf)) {
fprintf(stderr, "%s: reverse conversion", argv[0]);
fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
(long)n, (long)sizeof(buf));
exit(1);
}
printf("%s\n", buf);
exit(0);
}
struct rtab {
int family;
char *start;
char *stop;
char *output; /* NULL means error expected */
} rtab[] = {
{4, "1.2.3.0", "1.2.3.255", "1.2.3.0/24"},
{4, "1.2.3.0", "1.2.3.7", "1.2.3.0/29"},
{4, "1.2.3.240", "1.2.3.255", "1.2.3.240/28"},
{4, "0.0.0.0", "255.255.255.255", "0.0.0.0/0"},
{4, "1.2.3.4", "1.2.3.4", "1.2.3.4/32"},
{4, "1.2.3.0", "1.2.3.254", NULL},
{4, "1.2.3.0", "1.2.3.126", NULL},
{4, "1.2.3.0", "1.2.3.125", NULL},
{4, "1.2.0.0", "1.2.255.255", "1.2.0.0/16"},
{4, "1.2.0.0", "1.2.0.255", "1.2.0.0/24"},
{4, "1.2.255.0", "1.2.255.255", "1.2.255.0/24"},
{4, "1.2.255.0", "1.2.254.255", NULL},
{4, "1.2.255.1", "1.2.255.255", NULL},
{4, "1.2.0.1", "1.2.255.255", NULL},
{6, "1:2:3:4:5:6:7:0", "1:2:3:4:5:6:7:ffff", "1:2:3:4:5:6:7:0/112"},
{6, "1:2:3:4:5:6:7:0", "1:2:3:4:5:6:7:fff", "1:2:3:4:5:6:7:0/116"},
{6, "1:2:3:4:5:6:7:f0", "1:2:3:4:5:6:7:ff", "1:2:3:4:5:6:7:f0/124"},
{4, NULL, NULL, NULL},
};
void
regress()
{
struct rtab *r;
int status = 0;
ip_address start;
ip_address stop;
ip_subnet sub;
char buf[100];
const char *oops;
size_t n;
int af;
for (r = rtab; r->start != NULL; r++) {
af = (r->family == 4) ? AF_INET : AF_INET6;
oops = ttoaddr(r->start, 0, af, &start);
if (oops != NULL) {
printf("surprise failure converting `%s'\n", r->start);
exit(1);
}
oops = ttoaddr(r->stop, 0, af, &stop);
if (oops != NULL) {
printf("surprise failure converting `%s'\n", r->stop);
exit(1);
}
oops = rangetosubnet(&start, &stop, &sub);
if (oops != NULL && r->output == NULL)
{} /* okay, error expected */
else if (oops != NULL) {
printf("`%s'-`%s' rangetosubnet failed: %s\n",
r->start, r->stop, oops);
status = 1;
} else if (r->output == NULL) {
printf("`%s'-`%s' rangetosubnet succeeded unexpectedly\n",
r->start, r->stop);
status = 1;
} else {
n = subnettot(&sub, 0, buf, sizeof(buf));
if (n > sizeof(buf)) {
printf("`%s'-`%s' subnettot failed: need %ld\n",
r->start, r->stop, (long)n);
status = 1;
} else if (strcmp(r->output, buf) != 0) {
printf("`%s'-`%s' gave `%s', expected `%s'\n",
r->start, r->stop, buf, r->output);
status = 1;
}
}
}
exit(status);
}
#endif /* RANGETOSUBNET_MAIN */
+165
View File
@@ -0,0 +1,165 @@
.TH IPSEC_ANYADDR 3 "28 Nov 2000"
.\" RCSID $Id: sameaddr.3,v 1.1 2004/03/15 20:35:26 as Exp $
.SH NAME
ipsec sameaddr \- are two addresses the same?
.br
ipsec addrcmp \- ordered comparison of addresses
.br
ipsec samesubnet \- are two subnets the same?
.br
ipsec addrinsubnet \- is an address within a subnet?
.br
ipsec subnetinsubnet \- is a subnet within another subnet?
.br
ipsec subnetishost \- is a subnet a single host?
.br
ipsec samesaid \- are two SA IDs the same?
.br
ipsec sameaddrtype \- are two addresses of the same address family?
.br
ipsec samesubnettype \- are two subnets of the same address family?
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "int sameaddr(const ip_address *a, const ip_address *b);"
.br
.B "int addrcmp(const ip_address *a, const ip_address *b);"
.br
.B "int samesubnet(const ip_subnet *a, const ip_subnet *b);"
.br
.B "int addrinsubnet(const ip_address *a, const ip_subnet *s);"
.br
.B "int subnetinsubnet(const ip_subnet *a, const ip_subnet *b);"
.br
.B "int subnetishost(const ip_subnet *s);"
.br
.B "int samesaid(const ip_said *a, const ip_said *b);"
.br
.B "int sameaddrtype(const ip_address *a, const ip_address *b);"
.br
.B "int samesubnettype(const ip_subnet *a, const ip_subnet *b);"
.SH DESCRIPTION
These functions do various comparisons and tests on the
.I ip_address
type and
.I ip_subnet
types.
.PP
.I Sameaddr
returns
non-zero
if addresses
.I a
and
.IR b
are identical,
and
.B 0
otherwise.
Addresses of different families are never identical.
.PP
.I Addrcmp
returns
.BR \-1 ,
.BR 0 ,
or
.BR 1
respectively
if address
.I a
is less than, equal to, or greater than
.IR b .
If they are not of the same address family,
they are never equal;
the ordering reported in this case is arbitrary
(and probably not useful) but consistent.
.PP
.I Samesubnet
returns
non-zero
if subnets
.I a
and
.IR b
are identical,
and
.B 0
otherwise.
Subnets of different address families are never identical.
.PP
.I Addrinsubnet
returns
non-zero
if address
.I a
is within subnet
.IR s
and
.B 0
otherwise.
An address is never within a
subnet of a different address family.
.PP
.I Subnetinsubnet
returns
non-zero
if subnet
.I a
is a subset of subnet
.IR b
and
.B 0
otherwise.
A subnet is deemed to be a subset of itself.
A subnet is never a subset of another
subnet if their address families differ.
.PP
.I Subnetishost
returns
non-zero
if subnet
.I s
is in fact only a single host,
and
.B 0
otherwise.
.PP
.I Samesaid
returns
non-zero
if SA IDs
.I a
and
.IR b
are identical,
and
.B 0
otherwise.
.PP
.I Sameaddrtype
returns
non-zero
if addresses
.I a
and
.IR b
are of the same address family,
and
.B 0
otherwise.
.PP
.I Samesubnettype
returns
non-zero
if subnets
.I a
and
.IR b
are of the same address family,
and
.B 0
otherwise.
.SH SEE ALSO
inet(3), ipsec_initaddr(3)
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
+190
View File
@@ -0,0 +1,190 @@
/*
* comparisons
* 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: sameaddr.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
static int samenbits(const ip_address *a, const ip_address *b, int n);
/*
- addrcmp - compare two addresses
* Caution, the order of the tests is subtle: doing type test before
* size test can yield cases where a<b, b<c, but a>c.
*/
int /* like memcmp */
addrcmp(a, b)
const ip_address *a;
const ip_address *b;
{
int at = addrtypeof(a);
int bt = addrtypeof(b);
const unsigned char *ap;
const unsigned char *bp;
size_t as = addrbytesptr(a, &ap);
size_t bs = addrbytesptr(b, &bp);
size_t n = (as < bs) ? as : bs; /* min(as, bs) */
int c = memcmp(ap, bp, n);
if (c != 0) /* bytes differ */
return (c < 0) ? -1 : 1;
if (as != bs) /* comparison incomplete: lexical order */
return (as < bs) ? -1 : 1;
if (at != bt) /* bytes same but not same type: break tie */
return (at < bt) ? -1 : 1;
return 0;
}
/*
- sameaddr - are two addresses the same?
*/
int
sameaddr(a, b)
const ip_address *a;
const ip_address *b;
{
return (addrcmp(a, b) == 0) ? 1 : 0;
}
/*
- samesubnet - are two subnets the same?
*/
int
samesubnet(a, b)
const ip_subnet *a;
const ip_subnet *b;
{
if (!sameaddr(&a->addr, &b->addr)) /* also does type check */
return 0;
if (a->maskbits != b->maskbits)
return 0;
return 1;
}
/*
- subnetishost - is a subnet in fact a single host?
*/
int
subnetishost(a)
const ip_subnet *a;
{
return (a->maskbits == addrlenof(&a->addr)*8) ? 1 : 0;
}
/*
- samesaid - are two SA IDs the same?
*/
int
samesaid(a, b)
const ip_said *a;
const ip_said *b;
{
if (a->spi != b->spi) /* test first, most likely to be different */
return 0;
if (!sameaddr(&a->dst, &b->dst))
return 0;
if (a->proto != b->proto)
return 0;
return 1;
}
/*
- sameaddrtype - do two addresses have the same type?
*/
int
sameaddrtype(a, b)
const ip_address *a;
const ip_address *b;
{
return (addrtypeof(a) == addrtypeof(b)) ? 1 : 0;
}
/*
- samesubnettype - do two subnets have the same type?
*/
int
samesubnettype(a, b)
const ip_subnet *a;
const ip_subnet *b;
{
return (subnettypeof(a) == subnettypeof(b)) ? 1 : 0;
}
/*
- addrinsubnet - is this address in this subnet?
*/
int
addrinsubnet(a, s)
const ip_address *a;
const ip_subnet *s;
{
if (addrtypeof(a) != subnettypeof(s))
return 0;
if (!samenbits(a, &s->addr, s->maskbits))
return 0;
return 1;
}
/*
- subnetinsubnet - is one subnet within another?
*/
int
subnetinsubnet(a, b)
const ip_subnet *a;
const ip_subnet *b;
{
if (subnettypeof(a) != subnettypeof(b))
return 0;
if (a->maskbits < b->maskbits) /* a is bigger than b */
return 0;
if (!samenbits(&a->addr, &b->addr, b->maskbits))
return 0;
return 1;
}
/*
- samenbits - do two addresses have the same first n bits?
*/
static int
samenbits(a, b, nbits)
const ip_address *a;
const ip_address *b;
int nbits;
{
const unsigned char *ap;
const unsigned char *bp;
size_t n;
int m;
if (addrtypeof(a) != addrtypeof(b))
return 0; /* arbitrary */
n = addrbytesptr(a, &ap);
if (n == 0)
return 0; /* arbitrary */
(void) addrbytesptr(b, &bp);
if (nbits > n*8)
return 0; /* "can't happen" */
for (; nbits >= 8 && *ap == *bp; nbits -= 8, ap++, bp++)
continue;
if (nbits >= 8)
return 0;
if (nbits > 0) { /* partial byte */
m = ~(0xff >> nbits);
if ((*ap & m) != (*bp & m))
return 0;
}
return 1;
}
+102
View File
@@ -0,0 +1,102 @@
/*
* convert from binary form of SA ID to ASCII
* Copyright (C) 1998, 1999, 2001 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: satoa.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
static struct typename {
char type;
char *name;
} typenames[] = {
{ SA_AH, "ah" },
{ SA_ESP, "esp" },
{ SA_IPIP, "tun" },
{ SA_COMP, "comp" },
{ SA_INT, "int" },
{ 0, NULL }
};
/*
- satoa - convert SA to ASCII "[email protected]"
*/
size_t /* space needed for full conversion */
satoa(sa, format, dst, dstlen)
struct sa_id sa;
int format; /* character */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
size_t len = 0; /* 0 means not handled yet */
int base;
struct typename *tn;
char buf[30+ADDRTOA_BUF];
switch (format) {
case 0:
base = 16; /* temporarily at least */
break;
case 'd':
base = 10;
break;
default:
return 0;
break;
}
for (tn = typenames; tn->name != NULL; tn++)
if (sa.proto == tn->type)
break;
if (tn->name == NULL)
return 0;
if (strcmp(tn->name, PASSTHROUGHTYPE) == 0 &&
sa.spi == PASSTHROUGHSPI &&
sa.dst.s_addr == PASSTHROUGHDST) {
strcpy(buf, PASSTHROUGHNAME);
len = strlen(buf);
} else if (sa.proto == SA_INT && sa.dst.s_addr == 0) {
char *p;
switch (ntohl(sa.spi)) {
case SPI_PASS: p = "%pass"; break;
case SPI_DROP: p = "%drop"; break;
case SPI_REJECT: p = "%reject"; break;
case SPI_HOLD: p = "%hold"; break;
case SPI_TRAP: p = "%trap"; break;
case SPI_TRAPSUBNET: p = "%trapsubnet"; break;
default: p = NULL; break;
}
if (p != NULL) {
strcpy(buf, p);
len = strlen(buf);
}
}
if (len == 0) {
strcpy(buf, tn->name);
len = strlen(buf);
len += ultoa(ntohl(sa.spi), base, buf+len, sizeof(buf)-len);
*(buf+len-1) = '@';
len += addrtoa(sa.dst, 0, buf+len, sizeof(buf)-len);
}
if (dst != NULL) {
if (len > dstlen)
*(buf+dstlen-1) = '\0';
strcpy(dst, buf);
}
return len;
}
+132
View File
@@ -0,0 +1,132 @@
/*
* convert from binary form of SA ID to text
* Copyright (C) 2000, 2001 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: satot.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
static struct typename {
char type;
char *name;
} typenames[] = {
{ SA_AH, "ah" },
{ SA_ESP, "esp" },
{ SA_IPIP, "tun" },
{ SA_COMP, "comp" },
{ SA_INT, "int" },
{ 0, NULL }
};
/*
- satot - convert SA to text "[email protected]"
*/
size_t /* space needed for full conversion */
satot(sa, format, dst, dstlen)
const ip_said *sa;
int format; /* character */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
size_t len = 0; /* 0 means "not recognized yet" */
int base;
int showversion; /* use delimiter to show IP version? */
struct typename *tn;
char *p;
char *pre;
char buf[10+1+ULTOT_BUF+ADDRTOT_BUF];
char unk[10];
switch (format) {
case 0:
base = 16;
showversion = 1;
break;
case 'f':
base = 17;
showversion = 1;
break;
case 'x':
base = 'x';
showversion = 0;
break;
case 'd':
base = 10;
showversion = 0;
break;
default:
return 0;
break;
}
pre = NULL;
for (tn = typenames; tn->name != NULL; tn++)
if (sa->proto == tn->type) {
pre = tn->name;
break; /* NOTE BREAK OUT */
}
if (pre == NULL) { /* unknown protocol */
strcpy(unk, "unk");
(void) ultot((unsigned char)sa->proto, 10, unk+strlen(unk),
sizeof(unk)-strlen(unk));
pre = unk;
}
if (strcmp(pre, PASSTHROUGHTYPE) == 0 &&
sa->spi == PASSTHROUGHSPI &&
isunspecaddr(&sa->dst)) {
strcpy(buf, (addrtypeof(&sa->dst) == AF_INET) ?
PASSTHROUGH4NAME :
PASSTHROUGH6NAME);
len = strlen(buf);
}
if (sa->proto == SA_INT && addrtypeof(&sa->dst) == AF_INET &&
isunspecaddr(&sa->dst)) {
switch (ntohl(sa->spi)) {
case SPI_PASS: p = "%pass"; break;
case SPI_DROP: p = "%drop"; break;
case SPI_REJECT: p = "%reject"; break;
case SPI_HOLD: p = "%hold"; break;
case SPI_TRAP: p = "%trap"; break;
case SPI_TRAPSUBNET: p = "%trapsubnet"; break;
default: p = NULL; break;
}
if (p != NULL) {
strcpy(buf, p);
len = strlen(buf);
}
}
if (len == 0) { /* general case needed */
strcpy(buf, pre);
len = strlen(buf);
if (showversion) {
*(buf+len) = (addrtypeof(&sa->dst) == AF_INET) ? '.' :
':';
len++;
*(buf+len) = '\0';
}
len += ultot(ntohl(sa->spi), base, buf+len, sizeof(buf)-len);
*(buf+len-1) = '@';
len += addrtot(&sa->dst, 0, buf+len, sizeof(buf)-len);
}
if (dst != NULL) {
if (len > dstlen)
*(buf+dstlen-1) = '\0';
strcpy(dst, buf);
}
return len;
}
+47
View File
@@ -0,0 +1,47 @@
.TH IPSEC_SUBNETOF 3 "11 June 2001"
.\" RCSID $Id: subnetof.3,v 1.1 2004/03/15 20:35:26 as Exp $
.SH NAME
ipsec subnetof \- given Internet address and subnet mask, return subnet number
.br
ipsec hostof \- given Internet address and subnet mask, return host part
.br
ipsec broadcastof \- given Internet address and subnet mask, return broadcast address
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "struct in_addr subnetof(struct in_addr addr,"
.ti +1c
.B "struct in_addr mask);"
.br
.B "struct in_addr hostof(struct in_addr addr,"
.ti +1c
.B "struct in_addr mask);"
.br
.B "struct in_addr broadcastof(struct in_addr addr,"
.ti +1c
.B "struct in_addr mask);"
.SH DESCRIPTION
These functions are obsolete; see
.IR ipsec_networkof (3)
for their replacements.
.PP
.I Subnetof
takes an Internet
.I address
and a subnet
.I mask
and returns the network part of the address
(all in network byte order).
.I Hostof
similarly returns the host part, and
.I broadcastof
returns the broadcast address (all-1s convention) for the network.
.PP
These functions are provided to hide the Internet bit-munging inside
an API, in hopes of easing the eventual transition to IPv6.
.SH SEE ALSO
inet(3), ipsec_atosubnet(3)
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
Calling functions for this is more costly than doing it yourself.
+60
View File
@@ -0,0 +1,60 @@
/*
* minor network-address manipulation utilities
* Copyright (C) 1998, 1999 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: subnetof.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
- subnetof - given address and mask, return subnet part
*/
struct in_addr
subnetof(addr, mask)
struct in_addr addr;
struct in_addr mask;
{
struct in_addr result;
result.s_addr = addr.s_addr & mask.s_addr;
return result;
}
/*
- hostof - given address and mask, return host part
*/
struct in_addr
hostof(addr, mask)
struct in_addr addr;
struct in_addr mask;
{
struct in_addr result;
result.s_addr = addr.s_addr & ~mask.s_addr;
return result;
}
/*
- broadcastof - given (network) address and mask, return broadcast address
*/
struct in_addr
broadcastof(addr, mask)
struct in_addr addr;
struct in_addr mask;
{
struct in_addr result;
result.s_addr = addr.s_addr | ~mask.s_addr;
return result;
}
+62
View File
@@ -0,0 +1,62 @@
/*
* convert binary form of subnet description to ASCII
* Copyright (C) 1998, 1999 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: subnettoa.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
- subnettoa - convert address and mask to ASCII "addr/mask"
* Output expresses the mask as a bit count if possible, else dotted decimal.
*/
size_t /* space needed for full conversion */
subnettoa(addr, mask, format, dst, dstlen)
struct in_addr addr;
struct in_addr mask;
int format; /* character */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
size_t len;
size_t rest;
int n;
char *p;
switch (format) {
case 0:
break;
default:
return 0;
break;
}
len = addrtoa(addr, 0, dst, dstlen);
if (len < dstlen) {
dst[len - 1] = '/';
p = dst + len;
rest = dstlen - len;
} else {
p = NULL;
rest = 0;
}
n = masktobits(mask);
if (n >= 0)
len += ultoa((unsigned long)n, 10, p, rest);
else
len += addrtoa(mask, 0, p, rest);
return len;
}
+56
View File
@@ -0,0 +1,56 @@
/*
* convert binary form of subnet description 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: subnettot.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
- subnettot - convert subnet to text "addr/bitcount"
*/
size_t /* space needed for full conversion */
subnettot(sub, format, dst, dstlen)
const ip_subnet *sub;
int format; /* character */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
size_t len;
size_t rest;
char *p;
switch (format) {
case 0:
break;
default:
return 0;
break;
}
len = addrtot(&sub->addr, format, dst, dstlen);
if (len < dstlen) {
dst[len - 1] = '/';
p = dst + len;
rest = dstlen - len;
} else {
p = NULL;
rest = 0;
}
len += ultoa((unsigned long)sub->maskbits, 10, p, rest);
return len;
}
+109
View File
@@ -0,0 +1,109 @@
/*
* extract parts of an ip_subnet, and related
* 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: subnettypeof.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
- subnettypeof - get the address type of an ip_subnet
*/
int
subnettypeof(src)
const ip_subnet *src;
{
return src->addr.u.v4.sin_family;
}
/*
- networkof - get the network address of a subnet
*/
void
networkof(src, dst)
const ip_subnet *src;
ip_address *dst;
{
*dst = src->addr;
}
/*
- maskof - get the mask of a subnet, as an address
*/
void
maskof(src, dst)
const ip_subnet *src;
ip_address *dst;
{
int b;
unsigned char buf[16];
size_t n = addrlenof(&src->addr);
unsigned char *p;
if (src->maskbits > n*8 || n > sizeof(buf))
return; /* "can't happen" */
p = buf;
for (b = src->maskbits; b >= 8; b -= 8)
*p++ = 0xff;
if (b != 0)
*p++ = (0xff << (8 - b)) & 0xff;
while (p - buf < n)
*p++ = 0;
(void) initaddr(buf, n, addrtypeof(&src->addr), dst);
}
/*
- masktocount - convert a mask, expressed as an address, to a bit count
*/
int /* -1 if not valid mask */
masktocount(src)
const ip_address *src;
{
int b;
unsigned const char *bp;
size_t n;
unsigned const char *p;
unsigned const char *stop;
n = addrbytesptr(src, &bp);
if (n == 0)
return -1;
p = bp;
stop = bp + n;
n = 0;
while (p < stop && *p == 0xff) {
p++;
n += 8;
}
if (p < stop && *p != 0) { /* boundary in mid-byte */
b = *p++;
while (b&0x80) {
b <<= 1;
n++;
}
if ((b&0xff) != 0)
return -1; /* bits not contiguous */
}
while (p < stop && *p == 0)
p++;
if (p != stop)
return -1;
return n;
}
+377
View File
@@ -0,0 +1,377 @@
.TH IPSEC_TTOADDR 3 "28 Sept 2001"
.\" RCSID $Id: ttoaddr.3,v 1.1 2004/03/15 20:35:26 as Exp $
.SH NAME
ipsec ttoaddr, tnatoaddr, addrtot \- convert Internet addresses to and from text
.br
ipsec ttosubnet, subnettot \- convert subnet/mask text form to and from addresses
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "const char *ttoaddr(const char *src, size_t srclen,"
.ti +1c
.B "int af, ip_address *addr);"
.br
.B "const char *tnatoaddr(const char *src, size_t srclen,"
.ti +1c
.B "int af, ip_address *addr);"
.br
.B "size_t addrtot(const ip_address *addr, int format,"
.ti +1c
.B "char *dst, size_t dstlen);"
.sp
.B "const char *ttosubnet(const char *src, size_t srclen,"
.ti +1c
.B "int af, ip_subnet *dst);"
.br
.B "size_t subnettot(const ip_subnet *sub, int format,"
.ti +1c
.B "char *dst, size_t dstlen);"
.SH DESCRIPTION
.I Ttoaddr
converts a text-string name or numeric address into a binary address
(in network byte order).
.I Tnatoaddr
does the same conversion,
but the only text forms it accepts are
the ``official'' forms of
numeric address (dotted-decimal for IPv4, colon-hex for IPv6).
.I Addrtot
does the reverse conversion, from binary address back to a text form.
.I Ttosubnet
and
.I subnettot
do likewise for the ``address/mask'' form used to write a
specification of a subnet.
.PP
An IPv4 address is specified in text as a
dotted-decimal address (e.g.
.BR 1.2.3.4 ),
an eight-digit network-order hexadecimal number with the usual C prefix (e.g.
.BR 0x01020304 ,
which is synonymous with
.BR 1.2.3.4 ),
an eight-digit host-order hexadecimal number with a
.B 0h
prefix (e.g.
.BR 0h01020304 ,
which is synonymous with
.B 1.2.3.4
on a big-endian host and
.B 4.3.2.1
on a little-endian host),
a DNS name to be looked up via
.IR gethostbyname (3),
or an old-style network name to be looked up via
.IR getnetbyname (3).
.PP
A dotted-decimal address may be incomplete, in which case
text-to-binary conversion implicitly appends
as many instances of
.B .0
as necessary to bring it up to four components.
The components of a dotted-decimal address are always taken as
decimal, and leading zeros are ignored.
For example,
.B 10
is synonymous with
.BR 10.0.0.0 ,
and
.B 128.009.000.032
is synonymous with
.BR 128.9.0.32
(the latter example is verbatim from RFC 1166).
The result of applying
.I addrtot
to an IPv4 address is always complete and does not contain leading zeros.
.PP
Use of hexadecimal addresses is
.B strongly
.BR discouraged ;
they are included only to save hassles when dealing with
the handful of perverted programs which already print
network addresses in hexadecimal.
.PP
An IPv6 address is specified in text with
colon-hex notation (e.g.
.BR 0:56:78ab:22:33:44:55:66 ),
colon-hex with
.B ::
abbreviating at most one subsequence of multiple zeros (e.g.
.BR 99:ab::54:068 ,
which is synonymous with
.BR 99:ab:0:0:0:0:54:68 ),
or a DNS name to be looked up via
.IR gethostbyname (3).
The result of applying
.I addrtot
to an IPv6 address will use
.B ::
abbreviation if possible,
and will not contain leading zeros.
.PP
The letters in hexadecimal
may be uppercase or lowercase or any mixture thereof.
.PP
DNS names may be complete (optionally terminated with a ``.'')
or incomplete, and are looked up as specified by local system configuration
(see
.IR resolver (5)).
The
.I h_addr
value returned by
.IR gethostbyname2 (3)
is used,
so with current DNS implementations,
the result when the name corresponds to more than one address is
difficult to predict.
IPv4 name lookup resorts to
.IR getnetbyname (3)
only if
.IR gethostbyname2 (3)
fails.
.PP
A subnet specification is of the form \fInetwork\fB/\fImask\fR.
The
.I network
and
.I mask
can be any form acceptable to
.IR ttoaddr .
In addition, and preferably, the
.I mask
can be a decimal integer (leading zeros ignored) giving a bit count,
in which case
it stands for a mask with that number of high bits on and all others off
(e.g.,
.B 24
in IPv4 means
.BR 255.255.255.0 ).
In any case, the mask must be contiguous
(a sequence of high bits on and all remaining low bits off).
As a special case, the subnet specification
.B %default
is a synonym for
.B 0.0.0.0/0
or
.B ::/0
in IPv4 or IPv6 respectively.
.PP
.I Ttosubnet
ANDs the mask with the address before returning,
so that any non-network bits in the address are turned off
(e.g.,
.B 10.1.2.3/24
is synonymous with
.BR 10.1.2.0/24 ).
.I Subnettot
always generates the decimal-integer-bit-count
form of the mask,
with no leading zeros.
.PP
The
.I srclen
parameter of
.I ttoaddr
and
.I ttosubnet
specifies the length of the text string pointed to by
.IR src ;
it is an error for there to be anything else
(e.g., a terminating NUL) within that length.
As a convenience for cases where an entire NUL-terminated string is
to be converted,
a
.I srclen
value of
.B 0
is taken to mean
.BR strlen(src) .
.PP
The
.I af
parameter of
.I ttoaddr
and
.I ttosubnet
specifies the address family of interest.
It should be either
.B AF_INET
or
.BR AF_INET6 .
.PP
The
.I dstlen
parameter of
.I addrtot
and
.I subnettot
specifies the size of the
.I dst
parameter;
under no circumstances are more than
.I dstlen
bytes written to
.IR dst .
A result which will not fit is truncated.
.I Dstlen
can be zero, in which case
.I dst
need not be valid and no result is written,
but the return value is unaffected;
in all other cases, the (possibly truncated) result is NUL-terminated.
The
.I freeswan.h
header file defines constants,
.B ADDRTOT_BUF
and
.BR SUBNETTOT_BUF ,
which are the sizes of buffers just large enough for worst-case results.
.PP
The
.I format
parameter of
.I addrtot
and
.I subnettot
specifies what format is to be used for the conversion.
The value
.B 0
(not the character
.BR '0' ,
but a zero value)
specifies a reasonable default,
and is in fact the only format currently available in
.IR subnettot .
.I Addrtot
also accepts format values
.B 'r'
(signifying a text form suitable for DNS reverse lookups,
e.g.
.B 4.3.2.1.IN-ADDR.ARPA.
for IPv4 and
RFC 2874 format for IPv6),
and
.B 'R'
(signifying an alternate reverse-lookup form,
an error for IPv4 and RFC 1886 format for IPv6).
Reverse-lookup names always end with a ``.''.
.PP
The text-to-binary functions return NULL for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
The binary-to-text functions return
.B 0
for a failure, and otherwise
always return the size of buffer which would
be needed to
accommodate the full conversion result, including terminating NUL;
it is the caller's responsibility to check this against the size of
the provided buffer to determine whether truncation has occurred.
.SH SEE ALSO
inet(3)
.SH DIAGNOSTICS
Fatal errors in
.I ttoaddr
are:
empty input;
unknown address family;
attempt to allocate temporary storage for a very long name failed;
name lookup failed;
syntax error in dotted-decimal or colon-hex form;
dotted-decimal or colon-hex component too large.
.PP
Fatal errors in
.I ttosubnet
are:
no
.B /
in
.IR src ;
.I ttoaddr
error in conversion of
.I network
or
.IR mask ;
bit-count mask too big;
mask non-contiguous.
.PP
Fatal errors in
.I addrtot
and
.I subnettot
are:
unknown format.
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
The interpretation of incomplete dotted-decimal addresses
(e.g.
.B 10/24
means
.BR 10.0.0.0/24 )
differs from that of some older conversion
functions, e.g. those of
.IR inet (3).
The behavior of the older functions has never been
particularly consistent or particularly useful.
.PP
Ignoring leading zeros in dotted-decimal components and bit counts
is arguably the most useful behavior in this application,
but it might occasionally cause confusion with the historical use of leading
zeros to denote octal numbers.
.PP
.I Ttoaddr
does not support the mixed colon-hex-dotted-decimal
convention used to embed an IPv4 address in an IPv6 address.
.PP
.I Addrtot
always uses the
.B ::
abbreviation (which can appear only once in an address) for the
.I first
sequence of multiple zeros in an IPv6 address.
One can construct addresses (unlikely ones) in which this is suboptimal.
.PP
.I Addrtot
.B 'r'
conversion of an IPv6 address uses lowercase hexadecimal,
not the uppercase used in RFC 2874's examples.
It takes careful reading of RFCs 2874, 2673, and 2234 to realize
that lowercase is technically legitimate here,
and there may be software which botches this
and hence would have trouble with lowercase hex.
.PP
Possibly
.I subnettot
ought to recognize the
.B %default
case and generate that string as its output.
Currently it doesn't.
.PP
It is barely possible that somebody, somewhere,
might have a legitimate use for non-contiguous subnet masks.
.PP
.IR Getnetbyname (3)
is a historical dreg.
.PP
.I Tnatoaddr
probably should enforce completeness of dotted-decimal addresses.
.PP
The restriction of text-to-binary error reports to literal strings
(so that callers don't need to worry about freeing them or copying them)
does limit the precision of error reporting.
.PP
The text-to-binary error-reporting convention lends itself
to slightly obscure code,
because many readers will not think of NULL as signifying success.
A good way to make it clearer is to write something like:
.PP
.RS
.nf
.B "const char *error;"
.sp
.B "error = ttoaddr( /* ... */ );"
.B "if (error != NULL) {"
.B " /* something went wrong */"
.fi
.RE
+426
View File
@@ -0,0 +1,426 @@
/*
* 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.
*
* RCSID $Id: ttoaddr.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#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 hostent *h;
struct netent *ne = NULL;
char namebuf[100]; /* enough for most DNS names */
const char *cp;
char *p = namebuf;
size_t n;
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;
}
h = gethostbyname2(cp, af);
if (h == NULL && af == AF_INET)
ne = getnetbyname(cp);
if (p != namebuf)
FREE(p);
if (h == NULL && ne == NULL)
return "does not look numeric and name lookup failed";
if (h != NULL) {
if (h->h_addrtype != af)
return "address-type mismatch from gethostbyname2!!!";
return initaddr((unsigned char *)h->h_addr, h->h_length, af, dst);
} else {
if (ne->n_addrtype != af)
return "address-type mismatch from getnetbyname!!!";
ne->n_net = htonl(ne->n_net);
return initaddr((unsigned char *)&ne->n_net, sizeof(ne->n_net),
af, dst);
}
}
/*
- 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;
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;
}
+281
View File
@@ -0,0 +1,281 @@
.TH IPSEC_TTODATA 3 "16 August 2003"
.\" RCSID $Id: ttodata.3,v 1.2 2005/07/18 20:13:42 as Exp $
.SH NAME
ipsec ttodata, datatot \- convert binary data bytes from and to text formats
.SH SYNOPSIS
.B "#include <freeswan.h>"
.sp
.B "const char *ttodata(const char *src, size_t srclen,"
.ti +1c
.B "int base, char *dst, size_t dstlen, size_t *lenp);"
.br
.B "const char *ttodatav(const char *src, size_t srclen,"
.ti +1c
.B "int base, char *dst, size_t dstlen, size_t *lenp,"
.ti +1c
.B "char *errp, size_t errlen, int flags);"
.br
.B "size_t datatot(const char *src, size_t srclen,"
.ti +1c
.B "int format, char *dst, size_t dstlen);"
.SH DESCRIPTION
.IR Ttodata ,
.IR ttodatav ,
and
.I datatot
convert arbitrary binary data (e.g. encryption or authentication keys)
from and to more-or-less human-readable text formats.
.PP
Currently supported formats are hexadecimal, base64, and characters.
.PP
A hexadecimal text value begins with a
.B 0x
(or
.BR 0X )
prefix and continues with two-digit groups
of hexadecimal digits (0-9, and a-f or A-F),
each group encoding the value of one binary byte, high-order digit first.
A single
.B _
(underscore)
between consecutive groups is ignored, permitting punctuation to improve
readability; doing this every eight digits seems about right.
.PP
A base64 text value begins with a
.B 0s
(or
.BR 0S )
prefix
and continues with four-digit groups of base64 digits (A-Z, a-z, 0-9, +, and /),
each group encoding the value of three binary bytes as described in
section 6.8 of RFC 2045.
If
.B flags
has the
.B TTODATAV_IGNORESPACE
bit on, blanks are ignore (after the prefix).
Note that the last one or two digits of a base64 group can be
.B =
to indicate that fewer than three binary bytes are encoded.
.PP
A character text value begins with a
.B 0t
(or
.BR 0T )
prefix
and continues with text characters, each being the value of one binary byte.
.PP
All these functions basically copy data from
.I src
(whose size is specified by
.IR srclen )
to
.I dst
(whose size is specified by
.IR dstlen ),
doing the conversion en route.
If the result will not fit in
.IR dst ,
it is truncated;
under no circumstances are more than
.I dstlen
bytes of result written to
.IR dst .
.I Dstlen
can be zero, in which case
.I dst
need not be valid and no result bytes are written at all.
.PP
The
.I base
parameter of
.I ttodata
and
.I ttodatav
specifies what format the input is in;
normally it should be
.B 0
to signify that this gets figured out from the prefix.
Values of
.BR 16 ,
.BR 64 ,
and
.BR 256
respectively signify hexadecimal, base64, and character-text formats
without prefixes.
.PP
The
.I format
parameter of
.IR datatot ,
a single character used as a type code,
specifies which text format is wanted.
The value
.B 0
(not ASCII
.BR '0' ,
but a zero value) specifies a reasonable default.
Other currently-supported values are:
.RS 2
.TP 4
.B 'x'
continuous lower-case hexadecimal with a
.B 0x
prefix
.TP
.B 'h'
lower-case hexadecimal with a
.B 0x
prefix and a
.B _
every eight digits
.TP
.B ':'
lower-case hexadecimal with no prefix and a
.B :
(colon) every two digits
.TP
.B 16
lower-case hexadecimal with no prefix or
.B _
.TP
.B 's'
continuous base64 with a
.B 0s
prefix
.TP
.B 64
continuous base64 with no prefix
.RE
.PP
The default format is currently
.BR 'h' .
.PP
.I Ttodata
returns NULL for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
On success,
if and only if
.I lenp
is non-NULL,
.B *lenp
is set to the number of bytes required to contain the full untruncated result.
It is the caller's responsibility to check this against
.I dstlen
to determine whether he has obtained a complete result.
The
.B *lenp
value is correct even if
.I dstlen
is zero, which offers a way to determine how much space would be needed
before having to allocate any.
.PP
.I Ttodatav
is just like
.I ttodata
except that in certain cases,
if
.I errp
is non-NULL,
the buffer pointed to by
.I errp
(whose length is given by
.IR errlen )
is used to hold a more detailed error message.
The return value is NULL for success,
and is either
.I errp
or a pointer to a string literal for failure.
If the size of the error-message buffer is
inadequate for the desired message,
.I ttodatav
will fall back on returning a pointer to a literal string instead.
The
.I freeswan.h
header file defines a constant
.B TTODATAV_BUF
which is the size of a buffer large enough for worst-case results.
.PP
The normal return value of
.IR datatot
is the number of bytes required
to contain the full untruncated result.
It is the caller's responsibility to check this against
.I dstlen
to determine whether he has obtained a complete result.
The return value is correct even if
.I dstlen
is zero, which offers a way to determine how much space would be needed
before having to allocate any.
A return value of
.B 0
signals a fatal error of some kind
(see DIAGNOSTICS).
.PP
A zero value for
.I srclen
in
.I ttodata
(but not
.IR datatot !)
is synonymous with
.BR strlen(src) .
A non-zero
.I srclen
in
.I ttodata
must not include the terminating NUL.
.PP
Unless
.I dstlen
is zero,
the result supplied by
.I datatot
is always NUL-terminated,
and its needed-size return value includes space for the terminating NUL.
.PP
Several obsolete variants of these functions
.RI ( atodata ,
.IR datatoa ,
.IR atobytes ,
and
.IR bytestoa )
are temporarily also supported.
.SH SEE ALSO
sprintf(3), ipsec_atoaddr(3)
.SH DIAGNOSTICS
Fatal errors in
.I ttodata
and
.I ttodatav
are:
unknown characters in the input;
unknown or missing prefix;
unknown base;
incomplete digit group;
non-zero padding in a base64 less-than-three-bytes digit group;
zero-length input.
.PP
Fatal errors in
.I datatot
are:
unknown format code;
zero-length input.
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
.I Datatot
should have a format code to produce character-text output.
.PP
The
.B 0s
and
.B 0t
prefixes are the author's inventions and are not a standard
of any kind.
They have been chosen to avoid collisions with existing practice
(some C implementations use
.B 0b
for binary)
and possible confusion with unprefixed hexadecimal.
+722
View File
@@ -0,0 +1,722 @@
/*
* convert from text form of arbitrary data (e.g., keys) to binary
* 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: ttodata.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/* converters and misc */
static int unhex(const char *, char *, size_t);
static int unb64(const char *, char *, size_t);
static int untext(const char *, char *, size_t);
static const char *badch(const char *, int, char *, size_t);
/* internal error codes for converters */
#define SHORT (-2) /* internal buffer too short */
#define BADPAD (-3) /* bad base64 padding */
#define BADCH0 (-4) /* invalid character 0 */
#define BADCH1 (-5) /* invalid character 1 */
#define BADCH2 (-6) /* invalid character 2 */
#define BADCH3 (-7) /* invalid character 3 */
#define BADOFF(code) (BADCH0-(code))
/*
- ttodatav - convert text to data, with verbose error reports
* If some of this looks slightly odd, it's because it has changed
* repeatedly (from the original atodata()) without a major rewrite.
*/
const char * /* NULL on success, else literal or errp */
ttodatav(src, srclen, base, dst, dstlen, lenp, errp, errlen, flags)
const char *src;
size_t srclen; /* 0 means apply strlen() */
int base; /* 0 means figure it out */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
size_t *lenp; /* where to record length (NULL is nowhere) */
char *errp; /* error buffer */
size_t errlen;
unsigned int flags;
{
size_t ingroup; /* number of input bytes converted at once */
char buf[4]; /* output from conversion */
int nbytes; /* size of output */
int (*decode)(const char *, char *, size_t);
char *stop;
int ndone;
int i;
int underscoreok;
int skipSpace = 0;
if (srclen == 0)
srclen = strlen(src);
if (dstlen == 0)
dst = buf; /* point it somewhere valid */
stop = dst + dstlen;
if (base == 0) {
if (srclen < 2)
return "input too short to be valid";
if (*src++ != '0')
return "input does not begin with format prefix";
switch (*src++) {
case 'x':
case 'X':
base = 16;
break;
case 's':
case 'S':
base = 64;
break;
case 't':
case 'T':
base = 256;
break;
default:
return "unknown format prefix";
}
srclen -= 2;
}
switch (base) {
case 16:
decode = unhex;
underscoreok = 1;
ingroup = 2;
break;
case 64:
decode = unb64;
underscoreok = 0;
ingroup = 4;
if(flags & TTODATAV_IGNORESPACE) {
skipSpace = 1;
}
break;
case 256:
decode = untext;
ingroup = 1;
underscoreok = 0;
break;
default:
return "unknown base";
}
/* proceed */
ndone = 0;
while (srclen > 0) {
char stage[4]; /* staging area for group */
size_t sl = 0;
/* Grab ingroup characters into stage,
* squeezing out blanks if we are supposed to ignore them.
*/
for (sl = 0; sl < ingroup; src++, srclen--) {
if (srclen == 0)
return "input ends in mid-byte, perhaps truncated";
else if (!(skipSpace && (*src == ' ' || *src == '\t')))
stage[sl++] = *src;
}
nbytes = (*decode)(stage, buf, sizeof(buf));
switch (nbytes) {
case BADCH0:
case BADCH1:
case BADCH2:
case BADCH3:
return badch(stage, nbytes, errp, errlen);
case SHORT:
return "internal buffer too short (\"can't happen\")";
case BADPAD:
return "bad (non-zero) padding at end of base64 input";
}
if (nbytes <= 0)
return "unknown internal error";
for (i = 0; i < nbytes; i++) {
if (dst < stop)
*dst++ = buf[i];
ndone++;
}
while (srclen >= 1 && skipSpace && (*src == ' ' || *src == '\t')){
src++;
srclen--;
}
if (underscoreok && srclen > 1 && *src == '_') {
/* srclen > 1 means not last character */
src++;
srclen--;
}
}
if (ndone == 0)
return "no data bytes specified by input";
if (lenp != NULL)
*lenp = ndone;
return NULL;
}
/*
- ttodata - convert text to data
*/
const char * /* NULL on success, else literal */
ttodata(src, srclen, base, dst, dstlen, lenp)
const char *src;
size_t srclen; /* 0 means apply strlen() */
int base; /* 0 means figure it out */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
size_t *lenp; /* where to record length (NULL is nowhere) */
{
return ttodatav(src, srclen, base, dst, dstlen, lenp, (char *)NULL,
(size_t)0, TTODATAV_SPACECOUNTS);
}
/*
- atodata - convert ASCII to data
* backward-compatibility interface
*/
size_t /* 0 for failure, true length for success */
atodata(src, srclen, dst, dstlen)
const char *src;
size_t srclen;
char *dst;
size_t dstlen;
{
size_t len;
const char *err;
err = ttodata(src, srclen, 0, dst, dstlen, &len);
if (err != NULL)
return 0;
return len;
}
/*
- atobytes - convert ASCII to data bytes
* another backward-compatibility interface
*/
const char *
atobytes(src, srclen, dst, dstlen, lenp)
const char *src;
size_t srclen;
char *dst;
size_t dstlen;
size_t *lenp;
{
return ttodata(src, srclen, 0, dst, dstlen, lenp);
}
/*
- unhex - convert two ASCII hex digits to byte
*/
static int /* number of result bytes, or error code */
unhex(src, dst, dstlen)
const char *src; /* known to be full length */
char *dst;
size_t dstlen; /* not large enough is a failure */
{
char *p;
unsigned byte;
static char hex[] = "0123456789abcdef";
if (dstlen < 1)
return SHORT;
p = strchr(hex, *src);
if (p == NULL)
p = strchr(hex, tolower(*src));
if (p == NULL)
return BADCH0;
byte = (p - hex) << 4;
src++;
p = strchr(hex, *src);
if (p == NULL)
p = strchr(hex, tolower(*src));
if (p == NULL)
return BADCH1;
byte |= (p - hex);
*dst = byte;
return 1;
}
/*
- unb64 - convert four ASCII base64 digits to three bytes
* Note that a base64 digit group is padded out with '=' if it represents
* less than three bytes: one byte is dd==, two is ddd=, three is dddd.
*/
static int /* number of result bytes, or error code */
unb64(src, dst, dstlen)
const char *src; /* known to be full length */
char *dst;
size_t dstlen;
{
char *p;
unsigned byte1;
unsigned byte2;
static char base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if (dstlen < 3)
return SHORT;
p = strchr(base64, *src++);
if (p == NULL)
return BADCH0;
byte1 = (p - base64) << 2; /* first six bits */
p = strchr(base64, *src++);
if (p == NULL) {
return BADCH1;
}
byte2 = p - base64; /* next six: two plus four */
*dst++ = byte1 | (byte2 >> 4);
byte1 = (byte2 & 0xf) << 4;
p = strchr(base64, *src++);
if (p == NULL) {
if (*(src-1) == '=' && *src == '=') {
if (byte1 != 0) /* bad padding */
return BADPAD;
return 1;
}
return BADCH2;
}
byte2 = p - base64; /* next six: four plus two */
*dst++ = byte1 | (byte2 >> 2);
byte1 = (byte2 & 0x3) << 6;
p = strchr(base64, *src++);
if (p == NULL) {
if (*(src-1) == '=') {
if (byte1 != 0) /* bad padding */
return BADPAD;
return 2;
}
return BADCH3;
}
byte2 = p - base64; /* last six */
*dst++ = byte1 | byte2;
return 3;
}
/*
- untext - convert one ASCII character to byte
*/
static int /* number of result bytes, or error code */
untext(src, dst, dstlen)
const char *src; /* known to be full length */
char *dst;
size_t dstlen; /* not large enough is a failure */
{
if (dstlen < 1)
return SHORT;
*dst = *src;
return 1;
}
/*
- badch - produce a nice complaint about an unknown character
*
* If the compiler complains that the array bigenough[] has a negative
* size, that means the TTODATAV_BUF constant has been set too small.
*/
static const char * /* literal or errp */
badch(src, errcode, errp, errlen)
const char *src;
int errcode;
char *errp; /* might be NULL */
size_t errlen;
{
static const char pre[] = "unknown character (`";
static const char suf[] = "') in input";
char buf[5];
# define REQD (sizeof(pre) - 1 + sizeof(buf) - 1 + sizeof(suf))
struct sizecheck {
char bigenough[TTODATAV_BUF - REQD]; /* see above */
};
char ch;
if (errp == NULL || errlen < REQD)
return "unknown character in input";
strcpy(errp, pre);
ch = *(src + BADOFF(errcode));
if (isprint(ch)) {
buf[0] = ch;
buf[1] = '\0';
} else {
buf[0] = '\\';
buf[1] = ((ch & 0700) >> 6) + '0';
buf[2] = ((ch & 0070) >> 3) + '0';
buf[3] = ((ch & 0007) >> 0) + '0';
buf[4] = '\0';
}
strcat(errp, buf);
strcat(errp, suf);
return (const char *)errp;
}
#ifdef TTODATA_MAIN
#include <stdio.h>
struct artab;
static void check(struct artab *r, char *buf, size_t n, err_t oops, int *status);
static void regress(char *pgm);
static void hexout(const char *s, size_t len, FILE *f);
/*
- main - convert first argument to hex, or run regression
*/
int
main(int argc, char *argv[])
{
char buf[1024];
char buf2[1024];
char err[512];
size_t n;
size_t i;
char *p = buf;
char *p2 = buf2;
char *pgm = argv[0];
const char *oops;
if (argc < 2) {
fprintf(stderr, "Usage: %s {0x<hex>|0s<base64>|-r}\n", pgm);
exit(2);
}
if (strcmp(argv[1], "-r") == 0) {
regress(pgm); /* should not return */
fprintf(stderr, "%s: regress() returned?!?\n", pgm);
exit(1);
}
oops = ttodatav(argv[1], 0, 0, buf, sizeof(buf), &n,
err, sizeof(err), TTODATAV_IGNORESPACE);
if (oops != NULL) {
fprintf(stderr, "%s: ttodata error `%s' in `%s'\n", pgm,
oops, argv[1]);
exit(1);
}
if (n > sizeof(buf)) {
p = (char *)malloc((size_t)n);
if (p == NULL) {
fprintf(stderr,
"%s: unable to malloc %d bytes for result\n",
pgm, n);
exit(1);
}
oops = ttodata(argv[1], 0, 0, p, n, &n);
if (oops != NULL) {
fprintf(stderr, "%s: error `%s' in ttodata retry?!?\n",
pgm, oops);
exit(1);
}
}
hexout(p, n, stdout);
printf("\n");
i = datatot(buf, n, 'h', buf2, sizeof(buf2));
if (i == 0) {
fprintf(stderr, "%s: datatot reports error in `%s'\n", pgm,
argv[1]);
exit(1);
}
if (i > sizeof(buf2)) {
p2 = (char *)malloc((size_t)i);
if (p == NULL) {
fprintf(stderr,
"%s: unable to malloc %d bytes for result\n",
pgm, i);
exit(1);
}
i = datatot(buf, n, 'h', p2, i);
if (i == 0) {
fprintf(stderr, "%s: error in datatoa retry?!?\n", pgm);
exit(1);
}
}
printf("%s\n", p2);
exit(0);
}
/*
- hexout - output an arbitrary-length string in hex
*/
static void
hexout(s, len, f)
const char *s;
size_t len;
FILE *f;
{
size_t i;
fprintf(f, "0x");
for (i = 0; i < len; i++)
fprintf(f, "%02x", (unsigned char)s[i]);
}
struct artab {
int base;
# define IGNORESPACE_BIAS 1000
char *ascii; /* NULL for end */
char *data; /* NULL for error expected */
} atodatatab[] = {
{ 0, "", NULL, },
{ 0, "0", NULL, },
{ 0, "0x", NULL, },
{ 0, "0xa", NULL, },
{ 0, "0xab", "\xab", },
{ 0, "0xabc", NULL, },
{ 0, "0xabcd", "\xab\xcd", },
{ 0, "0x0123456789", "\x01\x23\x45\x67\x89", },
{ 0, "0x01x", NULL, },
{ 0, "0xabcdef", "\xab\xcd\xef", },
{ 0, "0xABCDEF", "\xab\xcd\xef", },
{ 0, "0XaBc0eEd81f", "\xab\xc0\xee\xd8\x1f", },
{ 0, "0XaBc0_eEd8", "\xab\xc0\xee\xd8", },
{ 0, "0XaBc0_", NULL, },
{ 0, "0X_aBc0", NULL, },
{ 0, "0Xa_Bc0", NULL, },
{ 16, "aBc0eEd8", "\xab\xc0\xee\xd8", },
{ 0, "0s", NULL, },
{ 0, "0sA", NULL, },
{ 0, "0sBA", NULL, },
{ 0, "0sCBA", NULL, },
{ 0, "0sDCBA", "\x0c\x20\x40", },
{ 0, "0SDCBA", "\x0c\x20\x40", },
{ 0, "0sDA==", "\x0c", },
{ 0, "0sDC==", NULL, },
{ 0, "0sDCA=", "\x0c\x20", },
{ 0, "0sDCB=", NULL, },
{ 0, "0sDCAZ", "\x0c\x20\x19", },
{ 0, "0sDCAa", "\x0c\x20\x1a", },
{ 0, "0sDCAz", "\x0c\x20\x33", },
{ 0, "0sDCA0", "\x0c\x20\x34", },
{ 0, "0sDCA9", "\x0c\x20\x3d", },
{ 0, "0sDCA+", "\x0c\x20\x3e", },
{ 0, "0sDCA/", "\x0c\x20\x3f", },
{ 0, "0sAbraCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0s AbraCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sA braCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAb raCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbr aCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbra Cadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraC adabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraCa dabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraCad abra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraCada bra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraCadab ra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraCadabr a+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraCadabra +", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraCadabra+ ", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ 0, "0t", NULL, },
{ 0, "0tabc_xyz", "abc_xyz", },
{ 256, "abc_xyz", "abc_xyz", },
{ 0, NULL, NULL, },
};
struct drtab {
char *data; /* input; NULL for end */
char format;
int buflen; /* -1 means big buffer */
int outlen; /* -1 means strlen(ascii)+1 */
char *ascii; /* NULL for error expected */
} datatoatab[] = {
{ "", 'x', -1, -1, NULL, },
{ "", 'X', -1, -1, NULL, },
{ "", 'n', -1, -1, NULL, },
{ "0", 'x', -1, -1, "0x30", },
{ "0", 'x', 0, 5, "---", },
{ "0", 'x', 1, 5, "", },
{ "0", 'x', 2, 5, "0", },
{ "0", 'x', 3, 5, "0x", },
{ "0", 'x', 4, 5, "0x3", },
{ "0", 'x', 5, 5, "0x30", },
{ "0", 'x', 6, 5, "0x30", },
{ "\xab\xcd", 'x', -1, -1, "0xabcd", },
{ "\x01\x23\x45\x67\x89", 'x', -1, -1, "0x0123456789", },
{ "\xab\xcd\xef", 'x', -1, -1, "0xabcdef", },
{ "\xab\xc0\xee\xd8\x1f", 'x', -1, -1, "0xabc0eed81f", },
{ "\x01\x02", 'h', -1, -1, "0x0102", },
{ "\x01\x02\x03\x04\x05\x06", 'h', -1, -1, "0x01020304_0506", },
{ "\xab\xc0\xee\xd8\x1f", 16, -1, -1, "abc0eed81f", },
{ "\x0c\x20\x40", 's', -1, -1, "0sDCBA", },
{ "\x0c\x20\x40", 's', 0, 7, "---", },
{ "\x0c\x20\x40", 's', 1, 7, "", },
{ "\x0c\x20\x40", 's', 2, 7, "0", },
{ "\x0c\x20\x40", 's', 3, 7, "0s", },
{ "\x0c\x20\x40", 's', 4, 7, "0sD", },
{ "\x0c\x20\x40", 's', 5, 7, "0sDC", },
{ "\x0c\x20\x40", 's', 6, 7, "0sDCB", },
{ "\x0c\x20\x40", 's', 7, 7, "0sDCBA", },
{ "\x0c\x20\x40", 's', 8, 7, "0sDCBA", },
{ "\x0c", 's', -1, -1, "0sDA==", },
{ "\x0c\x20", 's', -1, -1, "0sDCA=", },
{ "\x0c\x20\x19", 's', -1, -1, "0sDCAZ", },
{ "\x0c\x20\x1a", 's', -1, -1, "0sDCAa", },
{ "\x0c\x20\x33", 's', -1, -1, "0sDCAz", },
{ "\x0c\x20\x34", 's', -1, -1, "0sDCA0", },
{ "\x0c\x20\x3d", 's', -1, -1, "0sDCA9", },
{ "\x0c\x20\x3e", 's', -1, -1, "0sDCA+", },
{ "\x0c\x20\x3f", 's', -1, -1, "0sDCA/", },
{ "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", 's', -1, -1, "0sAbraCadabra+", },
{ "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", 64, -1, -1, "AbraCadabra+", },
{ NULL, 'x', -1, -1, NULL, },
};
/*
- regress - regression-test ttodata() and datatot()
*/
static void
check(r, buf, n, oops, status)
struct artab *r;
char *buf;
size_t n;
err_t oops;
int *status;
{
if (oops != NULL && r->data == NULL)
{} /* error expected */
else if (oops != NULL) {
printf("`%s' gave error `%s', expecting %d `", r->ascii,
oops, strlen(r->data));
hexout(r->data, strlen(r->data), stdout);
printf("'\n");
*status = 1;
} else if (r->data == NULL) {
printf("`%s' gave %d `", r->ascii, n);
hexout(buf, n, stdout);
printf("', expecting error\n");
*status = 1;
} else if (n != strlen(r->data)) {
printf("length wrong in `%s': got %d `", r->ascii, n);
hexout(buf, n, stdout);
printf("', expecting %d `", strlen(r->data));
hexout(r->data, strlen(r->data), stdout);
printf("'\n");
*status = 1;
} else if (memcmp(buf, r->data, n) != 0) {
printf("`%s' gave %d `", r->ascii, n);
hexout(buf, n, stdout);
printf("', expecting %d `", strlen(r->data));
hexout(r->data, strlen(r->data), stdout);
printf("'\n");
*status = 1;
}
fflush(stdout);
}
static void /* should not return at all, in fact */
regress(pgm)
char *pgm;
{
struct artab *r;
struct drtab *dr;
char buf[100];
size_t n;
int status = 0;
for (r = atodatatab; r->ascii != NULL; r++) {
int base = r->base;
int xbase = 0;
if ((base == 0 || base == IGNORESPACE_BIAS + 0) && r->ascii[0] == '0') {
switch (r->ascii[1]) {
case 'x':
case 'X':
xbase = 16;
break;
case 's':
case 'S':
xbase = 64;
break;
case 't':
case 'T':
xbase = 256;
break;
}
}
if (base >= IGNORESPACE_BIAS) {
base = base - IGNORESPACE_BIAS;
check(r, buf, n, ttodatav(r->ascii, 0, base, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
if (xbase != 0)
check(r, buf, n, ttodatav(r->ascii+2, 0, xbase, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
} else {
check(r, buf, n, ttodata(r->ascii, 0, base, buf, sizeof(buf), &n), &status);
if (base == 64 || xbase == 64)
check(r, buf, n, ttodatav(r->ascii, 0, base, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
if (xbase != 0) {
check(r, buf, n, ttodata(r->ascii+2, 0, xbase, buf, sizeof(buf), &n), &status);
if (base == 64 || xbase == 64)
check(r, buf, n, ttodatav(r->ascii+2, 0, xbase, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
}
}
}
for (dr = datatoatab; dr->data != NULL; dr++) {
size_t should;
strcpy(buf, "---");
n = datatot(dr->data, strlen(dr->data), dr->format, buf,
(dr->buflen == -1) ? sizeof(buf) : dr->buflen);
should = (dr->ascii == NULL) ? 0 : strlen(dr->ascii) + 1;
if (dr->outlen != -1)
should = dr->outlen;
if (n == 0 && dr->ascii == NULL)
{} /* error expected */
else if (n == 0) {
printf("`");
hexout(dr->data, strlen(dr->data), stdout);
printf("' %c gave error, expecting %d `%s'\n",
dr->format, should, dr->ascii);
status = 1;
} else if (dr->ascii == NULL) {
printf("`");
hexout(dr->data, strlen(dr->data), stdout);
printf("' %c gave %d `%.*s', expecting error\n",
dr->format, n, (int)n, buf);
status = 1;
} else if (n != should) {
printf("length wrong in `");
hexout(dr->data, strlen(dr->data), stdout);
printf("': got %d `%s'", n, buf);
printf(", expecting %d `%s'\n", should, dr->ascii);
status = 1;
} else if (strcmp(buf, dr->ascii) != 0) {
printf("`");
hexout(dr->data, strlen(dr->data), stdout);
printf("' gave %d `%s'", n, buf);
printf(", expecting %d `%s'\n", should, dr->ascii);
status = 1;
}
fflush(stdout);
}
exit(status);
}
#endif /* TTODATA_MAIN */
+103
View File
@@ -0,0 +1,103 @@
/*
* conversion from protocol/port string to protocol and port
* Copyright (C) 2002 Mario Strasser <[email protected]>,
* Zuercher Hochschule Winterthur,
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU 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/gpl.txt>.
*
* This program 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 General Public License
* for more details.
*
* RCSID $Id: ttoprotoport.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
* ttoprotoport - converts from protocol/port string to protocol and port
*/
err_t
ttoprotoport(src, src_len, proto, port, has_port_wildcard)
char *src; /* input string */
size_t src_len; /* length of input string, use strlen() if 0 */
u_int8_t *proto; /* extracted protocol number */
u_int16_t *port; /* extracted port number if it exists */
int *has_port_wildcard; /* set if port is %any */
{
char *end, *service_name;
char proto_name[16];
int proto_len;
long int l;
struct protoent *protocol;
struct servent *service;
/* get the length of the string */
if (!src_len) src_len = strlen(src);
/* locate delimiter '/' between protocol and port */
end = strchr(src, '/');
if (end != NULL) {
proto_len = end - src;
service_name = end + 1;
} else {
proto_len = src_len;
service_name = src + src_len;
}
/* copy protocol name*/
memset(proto_name, '\0', sizeof(proto_name));
memcpy(proto_name, src, proto_len);
/* extract protocol by trying to resolve it by name */
protocol = getprotobyname(proto_name);
if (protocol != NULL) {
*proto = protocol->p_proto;
}
else /* failed, now try it by number */
{
l = strtol(proto_name, &end, 0);
if (*proto_name && *end)
return "<protocol> is neither a number nor a valid name";
if (l < 0 || l > 0xff)
return "<protocol> must be between 0 and 255";
*proto = (u_int8_t)l;
}
/* is there a port wildcard? */
*has_port_wildcard = (strcmp(service_name, "%any") == 0);
if (*has_port_wildcard)
{
*port = 0;
return NULL;
}
/* extract port by trying to resolve it by name */
service = getservbyname(service_name, NULL);
if (service != NULL) {
*port = ntohs(service->s_port);
}
else /* failed, now try it by number */
{
l = strtol(service_name, &end, 0);
if (*service_name && *end)
return "<port> is neither a number nor a valid name";
if (l < 0 || l > 0xffff)
return "<port> must be between 0 and 65535";
*port = (u_int16_t)l;
}
return NULL;
}
+288
View File
@@ -0,0 +1,288 @@
.TH IPSEC_TTOSA 3 "26 Nov 2001"
.\" RCSID $Id: ttosa.3,v 1.1 2004/03/15 20:35:26 as Exp $
.SH NAME
ipsec ttosa, satot \- convert IPsec Security Association IDs to and from text
.br
ipsec initsaid \- initialize an SA ID
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "typedef struct {"
.ti +1c
.B "ip_address dst;"
.ti +1c
.B "ipsec_spi_t spi;"
.ti +1c
.B "int proto;"
.br
.B "} ip_said;"
.sp
.B "const char *ttosa(const char *src, size_t srclen,"
.ti +1c
.B "ip_said *sa);
.br
.B "size_t satot(const ip_said *sa, int format,"
.ti +1c
.B "char *dst, size_t dstlen);"
.br
.B "void initsaid(const ip_address *addr, ipsec_spi_t spi,"
.ti +1c
.B "int proto, ip_said *dst);"
.SH DESCRIPTION
.I Ttosa
converts an ASCII Security Association (SA) specifier into an
.B ip_said
structure (containing
a destination-host address
in network byte order,
an SPI number in network byte order, and
a protocol code).
.I Satot
does the reverse conversion, back to a text SA specifier.
.I Initsaid
initializes an
.B ip_said
from separate items of information.
.PP
An SA is specified in text with a mail-like syntax, e.g.
.BR [email protected] .
An SA specifier contains
a protocol prefix (currently
.BR ah ,
.BR esp ,
.BR tun ,
.BR comp ,
or
.BR int ),
a single character indicating the address family
.RB ( .
for IPv4,
.B :
for IPv6),
an unsigned integer SPI number in hexadecimal (with no
.B 0x
prefix),
and an IP address.
The IP address can be any form accepted by
.IR ipsec_ttoaddr (3),
e.g. dotted-decimal IPv4 address,
colon-hex IPv6 address,
or DNS name.
.PP
As a special case, the SA specifier
.B %passthrough4
or
.B %passthrough6
signifies the special SA used to indicate that packets should be
passed through unaltered.
(At present, these are synonyms for
.B [email protected]
and
.B tun:0@::
respectively,
but that is subject to change without notice.)
.B %passthrough
is a historical synonym for
.BR %passthrough4 .
These forms are known to both
.I ttosa
and
.IR satot ,
so the internal representation is never visible.
.PP
Similarly, the SA specifiers
.BR %pass ,
.BR %drop ,
.BR %reject ,
.BR %hold ,
.BR %trap ,
and
.BR %trapsubnet
signify special ``magic'' SAs used to indicate that packets should be
passed, dropped, rejected (dropped with ICMP notification),
held,
and trapped (sent up to
.IR ipsec_pluto (8),
with either of two forms of
.B %hold
automatically installed)
respectively.
These forms too are known to both routines,
so the internal representation of the magic SAs should never be visible.
.PP
The
.B <freeswan.h>
header file supplies the
.B ip_said
structure, as well as a data type
.B ipsec_spi_t
which is an unsigned 32-bit integer.
(There is no consistency between kernel and user on what such a type
is called, hence the header hides the differences.)
.PP
The protocol code uses the same numbers that IP does.
For user convenience, given the difficulty in acquiring the exact set of
protocol names used by the kernel,
.B <freeswan.h>
defines the names
.BR SA_ESP ,
.BR SA_AH ,
.BR SA_IPIP ,
and
.BR SA_COMP
to have the same values as the kernel names
.BR IPPROTO_ESP ,
.BR IPPROTO_AH ,
.BR IPPROTO_IPIP ,
and
.BR IPPROTO_COMP .
.PP
.B <freeswan.h>
also defines
.BR SA_INT
to have the value
.BR 61
(reserved by IANA for ``any host internal protocol'')
and
.BR SPI_PASS ,
.BR SPI_DROP ,
.BR SPI_REJECT ,
.BR SPI_HOLD ,
and
.B SPI_TRAP
to have the values 256-260 (in \fIhost\fR byte order) respectively.
These are used in constructing the magic SAs
(which always have address
.BR 0.0.0.0 ).
.PP
If
.I satot
encounters an unknown protocol code, e.g. 77,
it yields output using a prefix
showing the code numerically, e.g. ``unk77''.
This form is
.I not
recognized by
.IR ttosa .
.PP
The
.I srclen
parameter of
.I ttosa
specifies the length of the string pointed to by
.IR src ;
it is an error for there to be anything else
(e.g., a terminating NUL) within that length.
As a convenience for cases where an entire NUL-terminated string is
to be converted,
a
.I srclen
value of
.B 0
is taken to mean
.BR strlen(src) .
.PP
The
.I dstlen
parameter of
.I satot
specifies the size of the
.I dst
parameter;
under no circumstances are more than
.I dstlen
bytes written to
.IR dst .
A result which will not fit is truncated.
.I Dstlen
can be zero, in which case
.I dst
need not be valid and no result is written,
but the return value is unaffected;
in all other cases, the (possibly truncated) result is NUL-terminated.
The
.B <freeswan.h>
header file defines a constant,
.BR SATOT_BUF ,
which is the size of a buffer just large enough for worst-case results.
.PP
The
.I format
parameter of
.I satot
specifies what format is to be used for the conversion.
The value
.B 0
(not the ASCII character
.BR '0' ,
but a zero value)
specifies a reasonable default
(currently
lowercase protocol prefix, lowercase hexadecimal SPI,
dotted-decimal or colon-hex address).
The value
.B 'f'
is similar except that the SPI is padded with
.BR 0 s
to a fixed 32-bit width, to ease aligning displayed tables.
.PP
.I Ttosa
returns
.B NULL
for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
.I Satot
returns
.B 0
for a failure, and otherwise
always returns the size of buffer which would
be needed to
accommodate the full conversion result, including terminating NUL;
it is the caller's responsibility to check this against the size of
the provided buffer to determine whether truncation has occurred.
.PP
There is also, temporarily, support for some obsolete
forms of SA specifier which lack the address-family indicator.
.SH SEE ALSO
ipsec_ttoul(3), ipsec_ttoaddr(3), ipsec_samesaid(3), inet(3)
.SH DIAGNOSTICS
Fatal errors in
.I ttosa
are:
empty input;
input too small to be a legal SA specifier;
no
.B @
in input;
unknown protocol prefix;
conversion error in
.I ttoul
or
.IR ttoaddr .
.PP
Fatal errors in
.I satot
are:
unknown format.
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
The restriction of text-to-binary error reports to literal strings
(so that callers don't need to worry about freeing them or copying them)
does limit the precision of error reporting.
.PP
The text-to-binary error-reporting convention lends itself
to slightly obscure code,
because many readers will not think of NULL as signifying success.
A good way to make it clearer is to write something like:
.PP
.RS
.nf
.B "const char *error;"
.sp
.B "error = ttosa( /* ... */ );"
.B "if (error != NULL) {"
.B " /* something went wrong */"
.fi
.RE
+280
View File
@@ -0,0 +1,280 @@
/*
* convert from text form of SA ID to binary
* Copyright (C) 2000, 2001 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: ttosa.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
static struct satype {
char *prefix;
size_t prelen; /* strlen(prefix) */
int proto;
} satypes[] = {
{ "ah", 2, SA_AH },
{ "esp", 3, SA_ESP },
{ "tun", 3, SA_IPIP },
{ "comp", 4, SA_COMP },
{ "int", 3, SA_INT },
{ NULL, 0, 0, }
};
static struct magic {
char *name;
char *really;
} magic[] = {
{ PASSTHROUGHNAME, PASSTHROUGH4IS },
{ PASSTHROUGH4NAME, PASSTHROUGH4IS },
{ PASSTHROUGH6NAME, PASSTHROUGH6IS },
{ "%pass", "[email protected]" },
{ "%drop", "[email protected]" },
{ "%reject", "[email protected]" },
{ "%hold", "[email protected]" },
{ "%trap", "[email protected]" },
{ "%trapsubnet", "[email protected]" },
{ NULL, NULL }
};
/*
- ttosa - convert text "[email protected]" to SA identifier
*/
err_t /* NULL for success, else string literal */
ttosa(src, srclen, sa)
const char *src;
size_t srclen; /* 0 means "apply strlen" */
ip_said *sa;
{
const char *at;
const char *addr;
size_t alen;
const char *spi = NULL;
struct satype *sat;
unsigned long ul;
const char *oops;
struct magic *mp;
size_t nlen;
# define MINLEN 5 /* ah0@0 is as short as it can get */
int af;
int base;
if (srclen == 0)
srclen = strlen(src);
if (srclen == 0)
return "empty string";
if (srclen < MINLEN)
return "string too short to be SA identifier";
if (*src == '%') {
for (mp = magic; mp->name != NULL; mp++) {
nlen = strlen(mp->name);
if (srclen == nlen && memcmp(src, mp->name, nlen) == 0)
break;
}
if (mp->name == NULL)
return "unknown % keyword";
src = mp->really;
srclen = strlen(src);
}
at = memchr(src, '@', srclen);
if (at == NULL)
return "no @ in SA specifier";
for (sat = satypes; sat->prefix != NULL; sat++)
if (sat->prelen < srclen &&
strncmp(src, sat->prefix, sat->prelen) == 0) {
sa->proto = sat->proto;
spi = src + sat->prelen;
break; /* NOTE BREAK OUT */
}
if (sat->prefix == NULL)
return "SA specifier lacks valid protocol prefix";
if (spi >= at)
return "no SPI in SA specifier";
switch (*spi) {
case '.':
af = AF_INET;
spi++;
base = 16;
break;
case ':':
af = AF_INET6;
spi++;
base = 16;
break;
default:
af = AF_UNSPEC; /* not known yet */
base = 0;
break;
}
if (spi >= at)
return "no SPI found in SA specifier";
oops = ttoul(spi, at - spi, base, &ul);
if (oops != NULL)
return oops;
sa->spi = htonl(ul);
addr = at + 1;
alen = srclen - (addr - src);
if (af == AF_UNSPEC)
af = (memchr(addr, ':', alen) != NULL) ? AF_INET6 : AF_INET;
oops = ttoaddr(addr, alen, af, &sa->dst);
if (oops != NULL)
return oops;
return NULL;
}
#ifdef TTOSA_MAIN
#include <stdio.h>
void regress(void);
int
main(int argc, char *argv[])
{
ip_said sa;
char buf[100];
char buf2[100];
const char *oops;
size_t n;
if (argc < 2) {
fprintf(stderr, "Usage: %s {ahnnn@aaa|-r}\n", argv[0]);
exit(2);
}
if (strcmp(argv[1], "-r") == 0) {
regress();
fprintf(stderr, "regress() returned?!?\n");
exit(1);
}
oops = ttosa(argv[1], 0, &sa);
if (oops != NULL) {
fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
exit(1);
}
n = satot(&sa, 0, buf, sizeof(buf));
if (n > sizeof(buf)) {
fprintf(stderr, "%s: reverse conv of `%d'", argv[0], sa.proto);
fprintf(stderr, "%lx@", (long unsigned int)sa.spi);
(void) addrtot(&sa.dst, 0, buf2, sizeof(buf2));
fprintf(stderr, "%s", buf2);
fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
(long)n, (long)sizeof(buf));
exit(1);
}
printf("%s\n", buf);
exit(0);
}
struct rtab {
int format;
# define FUDGE 0x1000
char *input;
char *output; /* NULL means error expected */
} rtab[] = {
{0, "[email protected]", "[email protected]"},
{0, "[email protected]", "[email protected]"},
{0, "[email protected]", "[email protected]"},
{0, "[email protected]", "[email protected]"},
{0, "esp257@::1", "esp:101@::1"},
{0, "esp257@0bc:12de::1", "esp:101@bc:12de::1"},
{0, "esp78@1049:1::8007:2040", "esp:4e@1049:1::8007:2040"},
{0, "esp0x78@1049:1::8007:2040", "esp:78@1049:1::8007:2040"},
{0, "ah78@1049:1::8007:2040", "ah:4e@1049:1::8007:2040"},
{0, "ah0x78@1049:1::8007:2040", "ah:78@1049:1::8007:2040"},
{0, "tun78@1049:1::8007:2040", "tun:4e@1049:1::8007:2040"},
{0, "tun0x78@1049:1::8007:2040", "tun:78@1049:1::8007:2040"},
{0, "duk99@3ffe:370:400:ff::9001:3001", NULL},
{0, "esp78x@1049:1::8007:2040", NULL},
{0, "esp0x78@1049:1:0xfff::8007:2040", NULL},
{0, "es78@1049:1::8007:2040", NULL},
{0, "", NULL},
{0, "_", NULL},
{0, "ah2.2", NULL},
{0, "[email protected]", NULL},
{0, "[email protected]", "[email protected]"},
{'f', "[email protected]", "[email protected]"},
{0, "[email protected]", NULL},
{0, "[email protected]", NULL},
{0, "[email protected]", NULL},
{0, "[email protected]", NULL},
{0, "[email protected]", NULL},
{0, PASSTHROUGHNAME, PASSTHROUGH4NAME},
{0, PASSTHROUGH6NAME, PASSTHROUGH6NAME},
{0, "%pass", "%pass"},
{0, "[email protected]", "%pass"},
{0, "%drop", "%drop"},
{0, "[email protected]", "%drop"},
{0, "%reject", "%reject"},
{0, "[email protected]", "%reject"},
{0, "%hold", "%hold"},
{0, "[email protected]", "%hold"},
{0, "%trap", "%trap"},
{0, "[email protected]", "%trap"},
{0, "%trapsubnet", "%trapsubnet"},
{0, "[email protected]", "%trapsubnet"},
{0, "[email protected]", "[email protected]"},
{FUDGE, "[email protected]", "[email protected]"},
{0, NULL, NULL}
};
void
regress(void)
{
struct rtab *r;
int status = 0;
ip_said sa;
char in[100];
char buf[100];
const char *oops;
size_t n;
for (r = rtab; r->input != NULL; r++) {
strcpy(in, r->input);
oops = ttosa(in, 0, &sa);
if (oops != NULL && r->output == NULL)
{} /* okay, error expected */
else if (oops != NULL) {
printf("`%s' ttosa failed: %s\n", r->input, oops);
status = 1;
} else if (r->output == NULL) {
printf("`%s' ttosa succeeded unexpectedly\n",
r->input);
status = 1;
} else {
if (r->format&FUDGE)
sa.proto = 77;
n = satot(&sa, (char)r->format, buf, sizeof(buf));
if (n > sizeof(buf)) {
printf("`%s' satot failed: need %ld\n",
r->input, (long)n);
status = 1;
} else if (strcmp(r->output, buf) != 0) {
printf("`%s' gave `%s', expected `%s'\n",
r->input, buf, r->output);
status = 1;
}
}
}
exit(status);
}
#endif /* TTOSA_MAIN */
+296
View File
@@ -0,0 +1,296 @@
/*
* convert from text form of subnet specification to binary
* 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: ttosubnet.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
#ifndef DEFAULTSUBNET
#define DEFAULTSUBNET "%default"
#endif
/*
- ttosubnet - convert text "addr/mask" to address and mask
* Mask can be integer bit count.
*/
err_t
ttosubnet(src, srclen, af, dst)
const char *src;
size_t srclen; /* 0 means "apply strlen" */
int af; /* AF_INET or AF_INET6 */
ip_subnet *dst;
{
const char *slash;
const char *colon;
const char *mask;
size_t mlen;
const char *oops;
unsigned long bc;
static char def[] = DEFAULTSUBNET;
# define DEFLEN (sizeof(def) - 1) /* -1 for NUL */
static char defis4[] = "0/0";
# define DEFIS4LEN (sizeof(defis4) - 1)
static char defis6[] = "::/0";
# define DEFIS6LEN (sizeof(defis6) - 1)
ip_address addrtmp;
ip_address masktmp;
int nbits;
int i;
if (srclen == 0)
srclen = strlen(src);
if (srclen == 0)
return "empty string";
switch (af) {
case AF_INET:
nbits = 32;
break;
case AF_INET6:
nbits = 128;
break;
default:
return "unknown address family in ttosubnet";
break;
}
if (srclen == DEFLEN && strncmp(src, def, srclen) == 0) {
src = (af == AF_INET) ? defis4 : defis6;
srclen = (af == AF_INET) ? DEFIS4LEN : DEFIS6LEN;
}
slash = memchr(src, '/', srclen);
if (slash == NULL)
return "no / in subnet specification";
mask = slash + 1;
mlen = srclen - (mask - src);
oops = ttoaddr(src, slash-src, af, &addrtmp);
if (oops != NULL)
return oops;
/* extract port */
colon = memchr(mask, ':', mlen);
if (colon == 0)
{
setportof(0, &addrtmp);
}
else
{
long port;
oops = ttoul(colon+1, mlen-(colon-mask+1), 10, &port);
if (oops != NULL)
return oops;
setportof(htons(port), &addrtmp);
mlen = colon - mask;
}
/*extract mask */
oops = ttoul(mask, mlen, 10, &bc);
if (oops == NULL) {
/* ttoul succeeded, it's a bit-count mask */
if (bc > nbits)
return "subnet mask bit count too large";
i = bc;
} else {
oops = ttoaddr(mask, mlen, af, &masktmp);
if (oops != NULL)
return oops;
i = masktocount(&masktmp);
if (i < 0)
return "non-contiguous or otherwise erroneous mask";
}
return initsubnet(&addrtmp, i, '0', dst);
}
#ifdef TTOSUBNET_MAIN
#include <stdio.h>
void regress(void);
int main(int argc, char *argv[])
{
ip_subnet s;
char buf[100];
char buf2[100];
const char *oops;
size_t n;
int af;
char *p;
if (argc < 2) {
fprintf(stderr, "Usage: %s [-6] addr/mask\n", argv[0]);
fprintf(stderr, " or: %s -r\n", argv[0]);
exit(2);
}
if (strcmp(argv[1], "-r") == 0) {
regress();
fprintf(stderr, "regress() returned?!?\n");
exit(1);
}
af = AF_INET;
p = argv[1];
if (strcmp(argv[1], "-6") == 0) {
af = AF_INET6;
p = argv[2];
} else if (strchr(argv[1], ':') != NULL)
af = AF_INET6;
oops = ttosubnet(p, 0, af, &s);
if (oops != NULL) {
fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
exit(1);
}
n = subnettot(&s, 0, buf, sizeof(buf));
if (n > sizeof(buf)) {
fprintf(stderr, "%s: reverse conversion of ", argv[0]);
(void) addrtot(&s.addr, 0, buf2, sizeof(buf2));
fprintf(stderr, "%s/", buf2);
fprintf(stderr, "%d", s.maskbits);
fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
(long)n, (long)sizeof(buf));
exit(1);
}
printf("%s\n", buf);
exit(0);
}
struct rtab {
int family;
char *input;
char *output; /* NULL means error expected */
} rtab[] = {
{4, "1.2.3.0/255.255.255.0", "1.2.3.0/24"},
{4, "1.2.3.0/24", "1.2.3.0/24"},
{4, "1.2.3.0/24:10", "1.2.3.0/24:10"},
{4, "1.2.3.0/24:-1", NULL},
{4, "1.2.3.0/24:none", NULL},
{4, "1.2.3.0/24:", NULL},
{4, "1.2.3.0/24:0x10", "1.2.3.0/24:16"},
{4, "1.2.3.0/24:0X10", "1.2.3.0/24:16"},
{4, "1.2.3.0/24:010", "1.2.3.0/24:8"},
{4, "1.2.3.1/255.255.255.240", "1.2.3.0/28"},
{4, "1.2.3.1/32", "1.2.3.1/32"},
{4, "1.2.3.1/0", "0.0.0.0/0"},
/* {4, "1.2.3.1/255.255.127.0", "1.2.3.0/255.255.127.0"}, */
{4, "1.2.3.1/255.255.127.0", NULL},
{4, "128.009.000.032/32", "128.9.0.32/32"},
{4, "128.0x9.0.32/32", NULL},
{4, "0x80090020/32", "128.9.0.32/32"},
{4, "0x800x0020/32", NULL},
{4, "128.9.0.32/0xffFF0000", "128.9.0.0/16"},
{4, "128.9.0.32/0xff0000FF", NULL},
{4, "128.9.0.32/0x0000ffFF", NULL},
{4, "128.9.0.32/0x00ffFF0000", NULL},
{4, "128.9.0.32/0xffFF", NULL},
{4, "128.9.0.32.27/32", NULL},
{4, "128.9.0k32/32", NULL},
{4, "328.9.0.32/32", NULL},
{4, "128.9..32/32", NULL},
{4, "10/8", "10.0.0.0/8"},
{4, "10.0/8", "10.0.0.0/8"},
{4, "10.0.0/8", "10.0.0.0/8"},
{4, "10.0.1/24", "10.0.1.0/24"},
{4, "_", NULL},
{4, "_/_", NULL},
{4, "1.2.3.1", NULL},
{4, "1.2.3.1/_", NULL},
{4, "1.2.3.1/24._", NULL},
{4, "1.2.3.1/99", NULL},
{4, "localhost/32", "127.0.0.1/32"},
{4, "%default", "0.0.0.0/0"},
{6, "3049:1::8007:2040/0", "::/0"},
{6, "3049:1::8007:2040/128", "3049:1::8007:2040/128"},
{6, "3049:1::192.168.0.1/128", NULL}, /*"3049:1::c0a8:1/128",*/
{6, "3049:1::8007::2040/128", NULL},
{6, "3049:1::8007:2040/ffff::0", "3049::/16"},
{6, "3049:1::8007:2040/64", "3049:1::/64"},
{6, "3049:1::8007:2040/ffff::", "3049::/16"},
{6, "3049:1::8007:2040/0000:ffff::0", NULL},
{6, "3049:1::8007:2040/ff1f::0", NULL},
{6, "3049:1::8007:x:2040/128", NULL},
{6, "3049:1t::8007:2040/128", NULL},
{6, "3049:1::80071:2040/128", NULL},
{6, "::/21", "::/21"},
{6, "::1/128", "::1/128"},
{6, "1::/21", "1::/21"},
{6, "1::2/128", "1::2/128"},
{6, "1:0:0:0:0:0:0:2/128", "1::2/128"},
{6, "1:0:0:0:3:0:0:2/128", "1::3:0:0:2/128"},
{6, "1:0:0:3:0:0:0:2/128", "1::3:0:0:0:2/128"},
{6, "1:0:3:0:0:0:0:2/128", "1:0:3::2/128"},
{6, "abcd:ef01:2345:6789:0:00a:000:20/128", "abcd:ef01:2345:6789:0:a:0:20/128"},
{6, "3049:1::8007:2040/ffff:ffff:", NULL},
{6, "3049:1::8007:2040/ffff:88::", NULL},
{6, "3049:12::9000:3200/ffff:fff0::", "3049:10::/28"},
{6, "3049:12::9000:3200/28", "3049:10::/28"},
{6, "3049:12::9000:3200/ff00:::", NULL},
{6, "3049:12::9000:3200/ffff:::", NULL},
{6, "3049:12::9000:3200/128_", NULL},
{6, "3049:12::9000:3200/", NULL},
{6, "%default", "::/0"},
{4, NULL, NULL}
};
void
regress(void)
{
struct rtab *r;
int status = 0;
ip_subnet s;
char in[100];
char buf[100];
const char *oops;
size_t n;
int af;
for (r = rtab; r->input != NULL; r++) {
af = (r->family == 4) ? AF_INET : AF_INET6;
strcpy(in, r->input);
oops = ttosubnet(in, 0, af, &s);
if (oops != NULL && r->output == NULL)
{} /* okay, error expected */
else if (oops != NULL) {
printf("`%s' ttosubnet failed: %s\n", r->input, oops);
status = 1;
} else if (r->output == NULL) {
printf("`%s' ttosubnet succeeded unexpectedly\n",
r->input);
status = 1;
} else {
n = subnettot(&s, 0, buf, sizeof(buf));
if (n > sizeof(buf)) {
printf("`%s' subnettot failed: need %ld\n",
r->input, (long)n);
status = 1;
} else if (strcmp(r->output, buf) != 0) {
printf("`%s' gave `%s', expected `%s'\n",
r->input, buf, r->output);
status = 1;
}
}
}
exit(status);
}
#endif /* TTOSUBNET_MAIN */
+192
View File
@@ -0,0 +1,192 @@
.TH IPSEC_TTOUL 3 "16 Aug 2000"
.\" RCSID $Id: ttoul.3,v 1.1 2004/03/15 20:35:26 as Exp $
.SH NAME
ipsec ttoul, ultot \- convert unsigned-long numbers to and from text
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "const char *ttoul(const char *src, size_t srclen,"
.ti +1c
.B "int base, unsigned long *n);"
.br
.B "size_t ultot(unsigned long n, int format, char *dst,"
.ti +1c
.B "size_t dstlen);"
.SH DESCRIPTION
.I Ttoul
converts a text-string number into a binary
.B "unsigned long"
value.
.I Ultot
does the reverse conversion, back to a text version.
.PP
Numbers are specified in text as
decimal (e.g.
.BR 123 ),
octal with a leading zero (e.g.
.BR 012 ,
which has value 10),
or hexadecimal with a leading
.B 0x
(e.g.
.BR 0x1f ,
which has value 31)
in either upper or lower case.
.PP
The
.I srclen
parameter of
.I ttoul
specifies the length of the string pointed to by
.IR src ;
it is an error for there to be anything else
(e.g., a terminating NUL) within that length.
As a convenience for cases where an entire NUL-terminated string is
to be converted,
a
.I srclen
value of
.B 0
is taken to mean
.BR strlen(src) .
.PP
The
.I base
parameter of
.I ttoul
can be
.BR 8 ,
.BR 10 ,
or
.BR 16 ,
in which case the number supplied is assumed to be of that form
(and in the case of
.BR 16 ,
to lack any
.B 0x
prefix).
It can also be
.BR 0 ,
in which case the number is examined for a leading zero
or a leading
.B 0x
to determine its base.
.PP
The
.I dstlen
parameter of
.I ultot
specifies the size of the
.I dst
parameter;
under no circumstances are more than
.I dstlen
bytes written to
.IR dst .
A result which will not fit is truncated.
.I Dstlen
can be zero, in which case
.I dst
need not be valid and no result is written,
but the return value is unaffected;
in all other cases, the (possibly truncated) result is NUL-terminated.
The
.I freeswan.h
header file defines a constant,
.BR ULTOT_BUF ,
which is the size of a buffer just large enough for worst-case results.
.PP
The
.I format
parameter of
.I ultot
must be one of:
.RS
.IP \fB'o'\fR 4
octal conversion with leading
.B 0
.IP \fB\ 8\fR
octal conversion with no leading
.B 0
.IP \fB'd'\fR
decimal conversion
.IP \fB10\fR
same as
.B d
.IP \fB'x'\fR
hexadecimal conversion, including leading
.B 0x
.IP \fB16\fR
hexadecimal conversion with no leading
.B 0x
.IP \fB17\fR
like
.B 16
except padded on left with
.BR 0 s
to eight digits (full width of a 32-bit number)
.RE
.PP
.I Ttoul
returns NULL for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
.I Ultot
returns
.B 0
for a failure, and otherwise
returns the size of buffer which would
be needed to
accommodate the full conversion result, including terminating NUL
(it is the caller's responsibility to check this against the size of
the provided buffer to determine whether truncation has occurred).
.SH SEE ALSO
atol(3), strtoul(3)
.SH DIAGNOSTICS
Fatal errors in
.I ttoul
are:
empty input;
unknown
.IR base ;
non-digit character found;
number too large for an
.BR "unsigned long" .
.PP
Fatal errors in
.I ultot
are:
unknown
.IR format .
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
Conversion of
.B 0
with format
.B o
yields
.BR 00 .
.PP
.I Ultot
format
.B 17
is a bit of a kludge.
.PP
The restriction of error reports to literal strings
(so that callers don't need to worry about freeing them or copying them)
does limit the precision of error reporting.
.PP
The error-reporting convention lends itself to slightly obscure code,
because many readers will not think of NULL as signifying success.
A good way to make it clearer is to write something like:
.PP
.RS
.nf
.B "const char *error;"
.sp
.B "error = ttoul( /* ... */ );"
.B "if (error != NULL) {"
.B " /* something went wrong */"
.fi
.RE
+91
View File
@@ -0,0 +1,91 @@
/*
* convert from text form of unsigned long to binary
* 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: ttoul.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
- ttoul - convert text substring to unsigned long number
*/
const char * /* NULL for success, else string literal */
ttoul(src, srclen, base, resultp)
const char *src;
size_t srclen; /* 0 means strlen(src) */
int base; /* 0 means figure it out */
unsigned long *resultp;
{
const char *stop;
static char hex[] = "0123456789abcdef";
static char uchex[] = "0123456789ABCDEF";
int d;
char c;
char *p;
unsigned long r;
unsigned long rlimit;
int dlimit;
if (srclen == 0)
srclen = strlen(src);
if (srclen == 0)
return "empty string";
if (base == 0) {
if (srclen > 2 && *src == '0' &&
(*(src+1) == 'x' || *(src+1) == 'X'))
return ttoul(src+2, srclen-2, 16, resultp);
if (srclen > 1 && *src == '0')
return ttoul(src+1, srclen-1, 8, resultp);
return ttoul(src, srclen, 10, resultp);
}
if (base != 8 && base != 10 && base != 16)
return "unsupported number base";
r = 0;
stop = src + srclen;
if (base == 16) {
while (src < stop) {
c = *src++;
p = strchr(hex, c);
if (p != NULL)
d = p - hex;
else {
p = strchr(uchex, c);
if (p == NULL)
return "non-hex digit in hex number";
d = p - uchex;
}
r = (r << 4) | d;
}
/* defer length check to catch invalid digits first */
if (srclen > sizeof(unsigned long) * 2)
return "hex number too long";
} else {
rlimit = ULONG_MAX / base;
dlimit = (int)(ULONG_MAX - rlimit*base);
while (src < stop) {
c = *src++;
d = c - '0';
if (d < 0 || d >= base)
return "non-digit in number";
if (r > rlimit || (r == rlimit && d > dlimit))
return "unsigned-long overflow";
r = r*base + d;
}
}
*resultp = r;
return NULL;
}
+67
View File
@@ -0,0 +1,67 @@
/*
* convert unsigned long to ASCII
* Copyright (C) 1998, 1999 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: ultoa.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
- ultoa - convert unsigned long to decimal ASCII
*/
size_t /* length required for full conversion */
ultoa(n, base, dst, dstlen)
unsigned long n;
int base;
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
char buf[3*sizeof(unsigned long) + 1];
char *bufend = buf + sizeof(buf);
size_t len;
char *p;
static char hex[] = "0123456789abcdef";
p = bufend;
*--p = '\0';
if (base == 10) {
do {
*--p = n%10 + '0';
n /= 10;
} while (n != 0);
} else if (base == 16) {
do {
*--p = hex[n&0xf];
n >>= 4;
} while (n != 0);
*--p = 'x';
*--p = '0';
} else if (base == 8) {
do {
*--p = (n&07) + '0';
n >>= 3;
} while (n != 0);
*--p = '0';
} else
*--p = '?';
len = bufend - p;
if (dstlen > 0) {
if (len > dstlen)
*(p + dstlen - 1) = '\0';
strcpy(dst, p);
}
return len;
}
+83
View File
@@ -0,0 +1,83 @@
/*
* convert unsigned long 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: ultot.c,v 1.1 2004/03/15 20:35:26 as Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
- ultot - convert unsigned long to text
*/
size_t /* length required for full conversion */
ultot(n, base, dst, dstlen)
unsigned long n;
int base;
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
char buf[3*sizeof(unsigned long) + 1];
char *bufend = buf + sizeof(buf);
size_t len;
char *p;
static char hex[] = "0123456789abcdef";
# define HEX32 (32/4)
p = bufend;
*--p = '\0';
switch (base) {
case 10:
case 'd':
do {
*--p = n%10 + '0';
n /= 10;
} while (n != 0);
break;
case 16:
case 17:
case 'x':
do {
*--p = hex[n&0xf];
n >>= 4;
} while (n != 0);
if (base == 17)
while (bufend - p < HEX32 + 1)
*--p = '0';
if (base == 'x') {
*--p = 'x';
*--p = '0';
}
break;
case 8:
case 'o':
do {
*--p = (n&07) + '0';
n >>= 3;
} while (n != 0);
if (base == 'o')
*--p = '0';
break;
default:
return 0;
break;
}
len = bufend - p;
if (dstlen > 0) {
if (len > dstlen)
*(p + dstlen - 1) = '\0';
strcpy(dst, p);
}
return len;
}
+44
View File
@@ -0,0 +1,44 @@
.TH IPSEC_VERSION 3 "21 Nov 2001"
.\" RCSID $Id: version.3,v 1.1 2004/03/15 20:35:26 as Exp $
.SH NAME
ipsec ipsec_version_code \- get IPsec version code
.br
ipsec ipsec_version_string \- get full IPsec version string
.br
ipsec ipsec_copyright_notice \- get IPsec copyright notice
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "const char *ipsec_version_code(void);"
.br
.B "const char *ipsec_version_string(void);"
.br
.B "const char **ipsec_copyright_notice(void);"
.SH DESCRIPTION
These functions provide information on version numbering and copyright
of the Linux FreeS/WAN IPsec implementation.
.PP
.I Ipsec_version_code
returns a pointer to a string constant
containing the current IPsec version code,
such as ``1.92'' or ``snap2001Nov19b''.
.PP
.I Ipsec_version_string
returns a pointer to a string constant giving a full version identification,
consisting of the version code preceded by a prefix identifying the software,
e.g. ``Linux FreeS/WAN 1.92''.
.PP
.I Ipsec_copyright_notice
returns a pointer to a vector of pointers,
terminated by a
.BR NULL ,
which is the text of a suitable copyright notice.
Each pointer points to a string constant (possibly empty) which is one line
of the somewhat-verbose copyright notice.
The strings are NUL-terminated and do not contain a newline;
supplying suitable line termination for the output device is
the caller's responsibility.
.SH SEE ALSO
ipsec(8)
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
+44
View File
@@ -0,0 +1,44 @@
/*
* return IPsec version information
* Copyright (C) 2001 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: version.in.c,v 1.2 2004/03/16 12:26:32 as Exp $
*/
#ifdef __KERNEL__
#include <linux/netdevice.h>
#endif
#include "freeswan.h"
#define V "xxx" /* substituted in by Makefile */
static const char strongswan_number[] = V;
static const char strongswan_string[] = "Linux strongSwan " V;
/*
- ipsec_version_code - return IPsec version number/code, as string
*/
const char *
ipsec_version_code()
{
return strongswan_number;
}
/*
- ipsec_version_string - return full version string
*/
const char *
ipsec_version_string()
{
return strongswan_string;
}
+121
View File
@@ -0,0 +1,121 @@
# (kernel) Makefile for IPCOMP zlib deflate code
# Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs.
# Copyright (C) 2000 Svenning Soerensen
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU 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/gpl.txt>.
#
# This program 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 General Public License
# for more details.
#
# RCSID $Id: Makefile,v 1.1 2004/03/15 20:35:26 as Exp $
#
include ../Makefile.inc
ifndef TOPDIR
TOPDIR := /usr/src/linux
endif
L_TARGET := zlib.a
obj-y :=
include Makefile.objs
EXTRA_CFLAGS += $(KLIPSCOMPILE)
EXTRA_CFLAGS += -Wall
#EXTRA_CFLAGS += -Wconversion
#EXTRA_CFLAGS += -Wmissing-prototypes
EXTRA_CFLAGS += -Wpointer-arith
#EXTRA_CFLAGS += -Wcast-qual
#EXTRA_CFLAGS += -Wmissing-declarations
EXTRA_CFLAGS += -Wstrict-prototypes
#EXTRA_CFLAGS += -pedantic
#EXTRA_CFLAGS += -W
#EXTRA_CFLAGS += -Wwrite-strings
EXTRA_CFLAGS += -Wbad-function-cast
EXTRA_CFLAGS += -DIPCOMP_PREFIX
.S.o:
$(CC) -D__ASSEMBLY__ -DNO_UNDERLINE -traditional -c $< -o $*.o
asm-obj-$(CONFIG_M586) += match586.o
asm-obj-$(CONFIG_M586TSC) += match586.o
asm-obj-$(CONFIG_M586MMX) += match586.o
asm-obj-$(CONFIG_M686) += match686.o
asm-obj-$(CONFIG_MPENTIUMIII) += match686.o
asm-obj-$(CONFIG_MPENTIUM4) += match686.o
asm-obj-$(CONFIG_MK6) += match586.o
asm-obj-$(CONFIG_MK7) += match686.o
asm-obj-$(CONFIG_MCRUSOE) += match586.o
asm-obj-$(CONFIG_MWINCHIPC6) += match586.o
asm-obj-$(CONFIG_MWINCHIP2) += match686.o
asm-obj-$(CONFIG_MWINCHIP3D) += match686.o
obj-y += $(asm-obj-y)
ifneq ($(strip $(asm-obj-y)),)
EXTRA_CFLAGS += -DASMV
endif
active-objs := $(sort $(obj-y) $(obj-m))
L_OBJS := $(obj-y)
M_OBJS := $(obj-m)
MIX_OBJS := $(filter $(export-objs), $(active-objs))
include $(TOPDIR)/Rules.make
$(obj-y) : $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h
clean:
-rm -f *.o *.a
checkprograms:
programs: $(L_TARGET)
#
# $Log: Makefile,v $
# Revision 1.1 2004/03/15 20:35:26 as
# added files from freeswan-2.04-x509-1.5.3
#
# Revision 1.9 2002/04/24 07:55:32 mcr
# #include patches and Makefiles for post-reorg compilation.
#
# Revision 1.8 2002/04/24 07:36:44 mcr
# Moved from ./zlib/Makefile,v
#
# Revision 1.7 2002/03/27 23:34:35 mcr
# added programs: target
#
# Revision 1.6 2001/12/05 20:19:08 henry
# use new compile-control variable
#
# Revision 1.5 2001/11/27 16:38:08 mcr
# added new "checkprograms" target to deal with programs that
# are required for "make check", but that may not be ready to
# build for every user due to external dependancies.
#
# Revision 1.4 2001/10/24 14:46:24 henry
# Makefile.inc
#
# Revision 1.3 2001/04/21 23:05:24 rgb
# Update asm directives for 2.4 style makefiles.
#
# Revision 1.2 2001/01/29 22:22:00 rgb
# Convert to 2.4 new style with back compat.
#
# Revision 1.1.1.1 2000/09/29 18:51:33 rgb
# zlib_beginnings
#
#
+27
View File
@@ -0,0 +1,27 @@
obj-$(CONFIG_IPSEC_IPCOMP) += adler32.o
obj-$(CONFIG_IPSEC_IPCOMP) += deflate.o
obj-$(CONFIG_IPSEC_IPCOMP) += infblock.o
obj-$(CONFIG_IPSEC_IPCOMP) += infcodes.o
obj-$(CONFIG_IPSEC_IPCOMP) += inffast.o
obj-$(CONFIG_IPSEC_IPCOMP) += inflate.o
obj-$(CONFIG_IPSEC_IPCOMP) += inftrees.o
obj-$(CONFIG_IPSEC_IPCOMP) += infutil.o
obj-$(CONFIG_IPSEC_IPCOMP) += trees.o
obj-$(CONFIG_IPSEC_IPCOMP) += zutil.o
asm-obj-$(CONFIG_M586) += ${LIBZLIBSRCDIR}/match586.o
asm-obj-$(CONFIG_M586TSC) += ${LIBZLIBSRCDIR}/match586.o
asm-obj-$(CONFIG_M586MMX) += ${LIBZLIBSRCDIR}/match586.o
asm-obj-$(CONFIG_M686) += ${LIBZLIBSRCDIR}/match686.o
asm-obj-$(CONFIG_MPENTIUMIII) += ${LIBZLIBSRCDIR}/match686.o
asm-obj-$(CONFIG_MPENTIUM4) += ${LIBZLIBSRCDIR}/match686.o
asm-obj-$(CONFIG_MK6) += ${LIBZLIBSRCDIR}/match586.o
asm-obj-$(CONFIG_MK7) += ${LIBZLIBSRCDIR}/match686.o
asm-obj-$(CONFIG_MCRUSOE) += ${LIBZLIBSRCDIR}/match586.o
asm-obj-$(CONFIG_MWINCHIPC6) += ${LIBZLIBSRCDIR}/match586.o
asm-obj-$(CONFIG_MWINCHIP2) += ${LIBZLIBSRCDIR}/match686.o
asm-obj-$(CONFIG_MWINCHIP3D) += ${LIBZLIBSRCDIR}/match686.o
EXTRA_CFLAGS += -DIPCOMP_PREFIX
+147
View File
@@ -0,0 +1,147 @@
zlib 1.1.4 is a general purpose data compression library. All the code
is thread safe. The data format used by the zlib library
is described by RFCs (Request for Comments) 1950 to 1952 in the files
http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate
format) and rfc1952.txt (gzip format). These documents are also available in
other formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
All functions of the compression library are documented in the file zlib.h
(volunteer to write man pages welcome, contact [email protected]). A usage
example of the library is given in the file example.c which also tests that
the library is working correctly. Another example is given in the file
minigzip.c. The compression library itself is composed of all source files
except example.c and minigzip.c.
To compile all files and run the test program, follow the instructions
given at the top of Makefile. In short "make test; make install"
should work for most machines. For Unix: "./configure; make test; make install"
For MSDOS, use one of the special makefiles such as Makefile.msc.
For VMS, use Make_vms.com or descrip.mms.
Questions about zlib should be sent to <[email protected]>, or to
Gilles Vollant <[email protected]> for the Windows DLL version.
The zlib home page is http://www.zlib.org or http://www.gzip.org/zlib/
Before reporting a problem, please check this site to verify that
you have the latest version of zlib; otherwise get the latest version and
check whether the problem still exists or not.
PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html
before asking for help.
Mark Nelson <[email protected]> wrote an article about zlib for the Jan. 1997
issue of Dr. Dobb's Journal; a copy of the article is available in
http://dogma.net/markn/articles/zlibtool/zlibtool.htm
The changes made in version 1.1.4 are documented in the file ChangeLog.
The only changes made since 1.1.3 are bug corrections:
- ZFREE was repeated on same allocation on some error conditions.
This creates a security problem described in
http://www.zlib.org/advisory-2002-03-11.txt
- Returned incorrect error (Z_MEM_ERROR) on some invalid data
- Avoid accesses before window for invalid distances with inflate window
less than 32K.
- force windowBits > 8 to avoid a bug in the encoder for a window size
of 256 bytes. (A complete fix will be available in 1.1.5).
The beta version 1.1.5beta includes many more changes. A new official
version 1.1.5 will be released as soon as extensive testing has been
completed on it.
Unsupported third party contributions are provided in directory "contrib".
A Java implementation of zlib is available in the Java Development Kit
http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html
See the zlib home page http://www.zlib.org for details.
A Perl interface to zlib written by Paul Marquess <[email protected]>
is in the CPAN (Comprehensive Perl Archive Network) sites
http://www.cpan.org/modules/by-module/Compress/
A Python interface to zlib written by A.M. Kuchling <[email protected]>
is available in Python 1.5 and later versions, see
http://www.python.org/doc/lib/module-zlib.html
A zlib binding for TCL written by Andreas Kupries <[email protected]>
is availlable at http://www.westend.com/~kupries/doc/trf/man/man.html
An experimental package to read and write files in .zip format,
written on top of zlib by Gilles Vollant <[email protected]>, is
available at http://www.winimage.com/zLibDll/unzip.html
and also in the contrib/minizip directory of zlib.
Notes for some targets:
- To build a Windows DLL version, include in a DLL project zlib.def, zlib.rc
and all .c files except example.c and minigzip.c; compile with -DZLIB_DLL
The zlib DLL support was initially done by Alessandro Iacopetti and is
now maintained by Gilles Vollant <[email protected]>. Check the zlib DLL
home page at http://www.winimage.com/zLibDll
From Visual Basic, you can call the DLL functions which do not take
a structure as argument: compress, uncompress and all gz* functions.
See contrib/visual-basic.txt for more information, or get
http://www.tcfb.com/dowseware/cmp-z-it.zip
- For 64-bit Irix, deflate.c must be compiled without any optimization.
With -O, one libpng test fails. The test works in 32 bit mode (with
the -n32 compiler flag). The compiler bug has been reported to SGI.
- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1
it works when compiled with cc.
- on Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1
is necessary to get gzprintf working correctly. This is done by configure.
- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works
with other compilers. Use "make test" to check your compiler.
- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers.
- For Turbo C the small model is supported only with reduced performance to
avoid any far allocation; it was tested with -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3
- For PalmOs, see http://www.cs.uit.no/~perm/PASTA/pilot/software.html
Per Harald Myrvang <[email protected]>
Acknowledgments:
The deflate format used by zlib was defined by Phil Katz. The deflate
and zlib specifications were written by L. Peter Deutsch. Thanks to all the
people who reported problems and suggested various improvements in zlib;
they are too numerous to cite here.
Copyright notice:
(C) 1995-2002 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jean-loup Gailly Mark Adler
[email protected] [email protected]
If you use the zlib library in a product, we would appreciate *not*
receiving lengthy legal documents to sign. The sources are provided
for free but without warranty of any kind. The library has been
entirely written by Jean-loup Gailly and Mark Adler; it does not
include third-party code.
If you redistribute modified sources, we would appreciate that you include
in the file ChangeLog history information documenting your changes.
+13
View File
@@ -0,0 +1,13 @@
The only changes made to these files for use in FreeS/WAN are:
- In zconf.h, macros are defined to prefix global symbols with "ipcomp_"
(or "_ipcomp"), when compiled with -DIPCOMP_PREFIX.
- The copyright strings are defined local (static)
The above changes are made to avoid name collisions with ppp_deflate
and ext2compr.
- Files not needed for FreeS/WAN have been removed
See the "README" file for information about where to obtain the complete
zlib package.
+49
View File
@@ -0,0 +1,49 @@
/* adler32.c -- compute the Adler-32 checksum of a data stream
* Copyright (C) 1995-2002 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id: adler32.c,v 1.1 2004/03/15 20:35:26 as Exp $ */
#include <zlib/zlib.h>
#include "zconf.h"
#define BASE 65521L /* largest prime smaller than 65536 */
#define NMAX 5552
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
#define DO16(buf) DO8(buf,0); DO8(buf,8);
/* ========================================================================= */
uLong ZEXPORT adler32(adler, buf, len)
uLong adler;
const Bytef *buf;
uInt len;
{
unsigned long s1 = adler & 0xffff;
unsigned long s2 = (adler >> 16) & 0xffff;
int k;
if (buf == Z_NULL) return 1L;
while (len > 0) {
k = len < NMAX ? len : NMAX;
len -= k;
while (k >= 16) {
DO16(buf);
buf += 16;
k -= 16;
}
if (k != 0) do {
s1 += *buf++;
s2 += s1;
} while (--k);
s1 %= BASE;
s2 %= BASE;
}
return (s2 << 16) | s1;
}
File diff suppressed because it is too large Load Diff
+318
View File
@@ -0,0 +1,318 @@
/* deflate.h -- internal compression state
* Copyright (C) 1995-2002 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* @(#) $Id: deflate.h,v 1.1 2004/03/15 20:35:26 as Exp $ */
#ifndef _DEFLATE_H
#define _DEFLATE_H
#include "zlib/zutil.h"
/* ===========================================================================
* Internal compression state.
*/
#define LENGTH_CODES 29
/* number of length codes, not counting the special END_BLOCK code */
#define LITERALS 256
/* number of literal bytes 0..255 */
#define L_CODES (LITERALS+1+LENGTH_CODES)
/* number of Literal or Length codes, including the END_BLOCK code */
#define D_CODES 30
/* number of distance codes */
#define BL_CODES 19
/* number of codes used to transfer the bit lengths */
#define HEAP_SIZE (2*L_CODES+1)
/* maximum heap size */
#define MAX_BITS 15
/* All codes must not exceed MAX_BITS bits */
#define INIT_STATE 42
#define BUSY_STATE 113
#define FINISH_STATE 666
/* Stream status */
/* Data structure describing a single value and its code string. */
typedef struct ct_data_s {
union {
ush freq; /* frequency count */
ush code; /* bit string */
} fc;
union {
ush dad; /* father node in Huffman tree */
ush len; /* length of bit string */
} dl;
} FAR ct_data;
#define Freq fc.freq
#define Code fc.code
#define Dad dl.dad
#define Len dl.len
typedef struct static_tree_desc_s static_tree_desc;
typedef struct tree_desc_s {
ct_data *dyn_tree; /* the dynamic tree */
int max_code; /* largest code with non zero frequency */
static_tree_desc *stat_desc; /* the corresponding static tree */
} FAR tree_desc;
typedef ush Pos;
typedef Pos FAR Posf;
typedef unsigned IPos;
/* A Pos is an index in the character window. We use short instead of int to
* save space in the various tables. IPos is used only for parameter passing.
*/
typedef struct internal_state {
z_streamp strm; /* pointer back to this zlib stream */
int status; /* as the name implies */
Bytef *pending_buf; /* output still pending */
ulg pending_buf_size; /* size of pending_buf */
Bytef *pending_out; /* next pending byte to output to the stream */
int pending; /* nb of bytes in the pending buffer */
int noheader; /* suppress zlib header and adler32 */
Byte data_type; /* UNKNOWN, BINARY or ASCII */
Byte method; /* STORED (for zip only) or DEFLATED */
int last_flush; /* value of flush param for previous deflate call */
/* used by deflate.c: */
uInt w_size; /* LZ77 window size (32K by default) */
uInt w_bits; /* log2(w_size) (8..16) */
uInt w_mask; /* w_size - 1 */
Bytef *window;
/* Sliding window. Input bytes are read into the second half of the window,
* and move to the first half later to keep a dictionary of at least wSize
* bytes. With this organization, matches are limited to a distance of
* wSize-MAX_MATCH bytes, but this ensures that IO is always
* performed with a length multiple of the block size. Also, it limits
* the window size to 64K, which is quite useful on MSDOS.
* To do: use the user input buffer as sliding window.
*/
ulg window_size;
/* Actual size of window: 2*wSize, except when the user input buffer
* is directly used as sliding window.
*/
Posf *prev;
/* Link to older string with same hash index. To limit the size of this
* array to 64K, this link is maintained only for the last 32K strings.
* An index in this array is thus a window index modulo 32K.
*/
Posf *head; /* Heads of the hash chains or NIL. */
uInt ins_h; /* hash index of string to be inserted */
uInt hash_size; /* number of elements in hash table */
uInt hash_bits; /* log2(hash_size) */
uInt hash_mask; /* hash_size-1 */
uInt hash_shift;
/* Number of bits by which ins_h must be shifted at each input
* step. It must be such that after MIN_MATCH steps, the oldest
* byte no longer takes part in the hash key, that is:
* hash_shift * MIN_MATCH >= hash_bits
*/
long block_start;
/* Window position at the beginning of the current output block. Gets
* negative when the window is moved backwards.
*/
uInt match_length; /* length of best match */
IPos prev_match; /* previous match */
int match_available; /* set if previous match exists */
uInt strstart; /* start of string to insert */
uInt match_start; /* start of matching string */
uInt lookahead; /* number of valid bytes ahead in window */
uInt prev_length;
/* Length of the best match at previous step. Matches not greater than this
* are discarded. This is used in the lazy match evaluation.
*/
uInt max_chain_length;
/* To speed up deflation, hash chains are never searched beyond this
* length. A higher limit improves compression ratio but degrades the
* speed.
*/
uInt max_lazy_match;
/* Attempt to find a better match only when the current match is strictly
* smaller than this value. This mechanism is used only for compression
* levels >= 4.
*/
# define max_insert_length max_lazy_match
/* Insert new strings in the hash table only if the match length is not
* greater than this length. This saves time but degrades compression.
* max_insert_length is used only for compression levels <= 3.
*/
int level; /* compression level (1..9) */
int strategy; /* favor or force Huffman coding*/
uInt good_match;
/* Use a faster search when the previous match is longer than this */
int nice_match; /* Stop searching when current match exceeds this */
/* used by trees.c: */
/* Didn't use ct_data typedef below to supress compiler warning */
struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
struct tree_desc_s l_desc; /* desc. for literal tree */
struct tree_desc_s d_desc; /* desc. for distance tree */
struct tree_desc_s bl_desc; /* desc. for bit length tree */
ush bl_count[MAX_BITS+1];
/* number of codes at each bit length for an optimal tree */
int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
int heap_len; /* number of elements in the heap */
int heap_max; /* element of largest frequency */
/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
* The same heap array is used to build all trees.
*/
uch depth[2*L_CODES+1];
/* Depth of each subtree used as tie breaker for trees of equal frequency
*/
uchf *l_buf; /* buffer for literals or lengths */
uInt lit_bufsize;
/* Size of match buffer for literals/lengths. There are 4 reasons for
* limiting lit_bufsize to 64K:
* - frequencies can be kept in 16 bit counters
* - if compression is not successful for the first block, all input
* data is still in the window so we can still emit a stored block even
* when input comes from standard input. (This can also be done for
* all blocks if lit_bufsize is not greater than 32K.)
* - if compression is not successful for a file smaller than 64K, we can
* even emit a stored file instead of a stored block (saving 5 bytes).
* This is applicable only for zip (not gzip or zlib).
* - creating new Huffman trees less frequently may not provide fast
* adaptation to changes in the input data statistics. (Take for
* example a binary file with poorly compressible code followed by
* a highly compressible string table.) Smaller buffer sizes give
* fast adaptation but have of course the overhead of transmitting
* trees more frequently.
* - I can't count above 4
*/
uInt last_lit; /* running index in l_buf */
ushf *d_buf;
/* Buffer for distances. To simplify the code, d_buf and l_buf have
* the same number of elements. To use different lengths, an extra flag
* array would be necessary.
*/
ulg opt_len; /* bit length of current block with optimal trees */
ulg static_len; /* bit length of current block with static trees */
uInt matches; /* number of string matches in current block */
int last_eob_len; /* bit length of EOB code for last block */
#ifdef DEBUG
ulg compressed_len; /* total bit length of compressed file mod 2^32 */
ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
#endif
ush bi_buf;
/* Output buffer. bits are inserted starting at the bottom (least
* significant bits).
*/
int bi_valid;
/* Number of valid bits in bi_buf. All bits above the last valid bit
* are always zero.
*/
} FAR deflate_state;
/* Output a byte on the stream.
* IN assertion: there is enough room in pending_buf.
*/
#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
/* Minimum amount of lookahead, except at the end of the input file.
* See deflate.c for comments about the MIN_MATCH+1.
*/
#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
/* In order to simplify the code, particularly on 16 bit machines, match
* distances are limited to MAX_DIST instead of WSIZE.
*/
/* in trees.c */
void _tr_init OF((deflate_state *s));
int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len,
int eof));
void _tr_align OF((deflate_state *s));
void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
int eof));
#define d_code(dist) \
((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
/* Mapping from a distance to a distance code. dist is the distance - 1 and
* must not have side effects. _dist_code[256] and _dist_code[257] are never
* used.
*/
#ifndef DEBUG
/* Inline versions of _tr_tally for speed: */
#if defined(GEN_TREES_H) || !defined(STDC)
extern uch _length_code[];
extern uch _dist_code[];
#else
extern const uch _length_code[];
extern const uch _dist_code[];
#endif
# define _tr_tally_lit(s, c, flush) \
{ uch cc = (c); \
s->d_buf[s->last_lit] = 0; \
s->l_buf[s->last_lit++] = cc; \
s->dyn_ltree[cc].Freq++; \
flush = (s->last_lit == s->lit_bufsize-1); \
}
# define _tr_tally_dist(s, distance, length, flush) \
{ uch len = (length); \
ush dist = (distance); \
s->d_buf[s->last_lit] = dist; \
s->l_buf[s->last_lit++] = len; \
dist--; \
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
s->dyn_dtree[d_code(dist)].Freq++; \
flush = (s->last_lit == s->lit_bufsize-1); \
}
#else
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
# define _tr_tally_dist(s, distance, length, flush) \
flush = _tr_tally(s, distance, length)
#endif
#endif /* _DEFLATE_H */
+403
View File
@@ -0,0 +1,403 @@
/* infblock.c -- interpret and process block types to last block
* Copyright (C) 1995-2002 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include <zlib/zutil.h>
#include "infblock.h"
#include "inftrees.h"
#include "infcodes.h"
#include "infutil.h"
struct inflate_codes_state {int dummy;}; /* for buggy compilers */
/* simplify the use of the inflate_huft type with some defines */
#define exop word.what.Exop
#define bits word.what.Bits
/* Table for deflate from PKZIP's appnote.txt. */
local const uInt border[] = { /* Order of the bit length code lengths */
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
/*
Notes beyond the 1.93a appnote.txt:
1. Distance pointers never point before the beginning of the output
stream.
2. Distance pointers can point back across blocks, up to 32k away.
3. There is an implied maximum of 7 bits for the bit length table and
15 bits for the actual data.
4. If only one code exists, then it is encoded using one bit. (Zero
would be more efficient, but perhaps a little confusing.) If two
codes exist, they are coded using one bit each (0 and 1).
5. There is no way of sending zero distance codes--a dummy must be
sent if there are none. (History: a pre 2.0 version of PKZIP would
store blocks with no distance codes, but this was discovered to be
too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
zero distance codes, which is sent as one code of zero bits in
length.
6. There are up to 286 literal/length codes. Code 256 represents the
end-of-block. Note however that the static length tree defines
288 codes just to fill out the Huffman codes. Codes 286 and 287
cannot be used though, since there is no length base or extra bits
defined for them. Similarily, there are up to 30 distance codes.
However, static trees define 32 codes (all 5 bits) to fill out the
Huffman codes, but the last two had better not show up in the data.
7. Unzip can check dynamic Huffman blocks for complete code sets.
The exception is that a single code would not be complete (see #4).
8. The five bits following the block type is really the number of
literal codes sent minus 257.
9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
(1+6+6). Therefore, to output three times the length, you output
three codes (1+1+1), whereas to output four times the same length,
you only need two codes (1+3). Hmm.
10. In the tree reconstruction algorithm, Code = Code + Increment
only if BitLength(i) is not zero. (Pretty obvious.)
11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
12. Note: length code 284 can represent 227-258, but length code 285
really is 258. The last length deserves its own, short code
since it gets used a lot in very redundant files. The length
258 is special since 258 - 3 (the min match length) is 255.
13. The literal/length and distance code bit lengths are read as a
single stream of lengths. It is possible (and advantageous) for
a repeat code (16, 17, or 18) to go across the boundary between
the two sets of lengths.
*/
void inflate_blocks_reset(s, z, c)
inflate_blocks_statef *s;
z_streamp z;
uLongf *c;
{
if (c != Z_NULL)
*c = s->check;
if (s->mode == BTREE || s->mode == DTREE)
ZFREE(z, s->sub.trees.blens);
if (s->mode == CODES)
inflate_codes_free(s->sub.decode.codes, z);
s->mode = TYPE;
s->bitk = 0;
s->bitb = 0;
s->read = s->write = s->window;
if (s->checkfn != Z_NULL)
z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0);
Tracev((stderr, "inflate: blocks reset\n"));
}
inflate_blocks_statef *inflate_blocks_new(z, c, w)
z_streamp z;
check_func c;
uInt w;
{
inflate_blocks_statef *s;
if ((s = (inflate_blocks_statef *)ZALLOC
(z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
return s;
if ((s->hufts =
(inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL)
{
ZFREE(z, s);
return Z_NULL;
}
if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
{
ZFREE(z, s->hufts);
ZFREE(z, s);
return Z_NULL;
}
s->end = s->window + w;
s->checkfn = c;
s->mode = TYPE;
Tracev((stderr, "inflate: blocks allocated\n"));
inflate_blocks_reset(s, z, Z_NULL);
return s;
}
int inflate_blocks(s, z, r)
inflate_blocks_statef *s;
z_streamp z;
int r;
{
uInt t; /* temporary storage */
uLong b; /* bit buffer */
uInt k; /* bits in bit buffer */
Bytef *p; /* input data pointer */
uInt n; /* bytes available there */
Bytef *q; /* output window write pointer */
uInt m; /* bytes to end of window or read pointer */
/* copy input/output information to locals (UPDATE macro restores) */
LOAD
/* process input based on current state */
while (1) switch (s->mode)
{
case TYPE:
NEEDBITS(3)
t = (uInt)b & 7;
s->last = t & 1;
switch (t >> 1)
{
case 0: /* stored */
Tracev((stderr, "inflate: stored block%s\n",
s->last ? " (last)" : ""));
DUMPBITS(3)
t = k & 7; /* go to byte boundary */
DUMPBITS(t)
s->mode = LENS; /* get length of stored block */
break;
case 1: /* fixed */
Tracev((stderr, "inflate: fixed codes block%s\n",
s->last ? " (last)" : ""));
{
uInt bl, bd;
inflate_huft *tl, *td;
inflate_trees_fixed(&bl, &bd, &tl, &td, z);
s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
if (s->sub.decode.codes == Z_NULL)
{
r = Z_MEM_ERROR;
LEAVE
}
}
DUMPBITS(3)
s->mode = CODES;
break;
case 2: /* dynamic */
Tracev((stderr, "inflate: dynamic codes block%s\n",
s->last ? " (last)" : ""));
DUMPBITS(3)
s->mode = TABLE;
break;
case 3: /* illegal */
DUMPBITS(3)
s->mode = BAD;
z->msg = (char*)"invalid block type";
r = Z_DATA_ERROR;
LEAVE
}
break;
case LENS:
NEEDBITS(32)
if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
{
s->mode = BAD;
z->msg = (char*)"invalid stored block lengths";
r = Z_DATA_ERROR;
LEAVE
}
s->sub.left = (uInt)b & 0xffff;
b = k = 0; /* dump bits */
Tracev((stderr, "inflate: stored length %u\n", s->sub.left));
s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
break;
case STORED:
if (n == 0)
LEAVE
NEEDOUT
t = s->sub.left;
if (t > n) t = n;
if (t > m) t = m;
zmemcpy(q, p, t);
p += t; n -= t;
q += t; m -= t;
if ((s->sub.left -= t) != 0)
break;
Tracev((stderr, "inflate: stored end, %lu total out\n",
z->total_out + (q >= s->read ? q - s->read :
(s->end - s->read) + (q - s->window))));
s->mode = s->last ? DRY : TYPE;
break;
case TABLE:
NEEDBITS(14)
s->sub.trees.table = t = (uInt)b & 0x3fff;
#ifndef PKZIP_BUG_WORKAROUND
if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
{
s->mode = BAD;
z->msg = (char*)"too many length or distance symbols";
r = Z_DATA_ERROR;
LEAVE
}
#endif
t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
{
r = Z_MEM_ERROR;
LEAVE
}
DUMPBITS(14)
s->sub.trees.index = 0;
Tracev((stderr, "inflate: table sizes ok\n"));
s->mode = BTREE;
case BTREE:
while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
{
NEEDBITS(3)
s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
DUMPBITS(3)
}
while (s->sub.trees.index < 19)
s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
s->sub.trees.bb = 7;
t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
&s->sub.trees.tb, s->hufts, z);
if (t != Z_OK)
{
r = t;
if (r == Z_DATA_ERROR)
{
ZFREE(z, s->sub.trees.blens);
s->mode = BAD;
}
LEAVE
}
s->sub.trees.index = 0;
Tracev((stderr, "inflate: bits tree ok\n"));
s->mode = DTREE;
case DTREE:
while (t = s->sub.trees.table,
s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
{
inflate_huft *h;
uInt i, j, c;
t = s->sub.trees.bb;
NEEDBITS(t)
h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
t = h->bits;
c = h->base;
if (c < 16)
{
DUMPBITS(t)
s->sub.trees.blens[s->sub.trees.index++] = c;
}
else /* c == 16..18 */
{
i = c == 18 ? 7 : c - 14;
j = c == 18 ? 11 : 3;
NEEDBITS(t + i)
DUMPBITS(t)
j += (uInt)b & inflate_mask[i];
DUMPBITS(i)
i = s->sub.trees.index;
t = s->sub.trees.table;
if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
(c == 16 && i < 1))
{
ZFREE(z, s->sub.trees.blens);
s->mode = BAD;
z->msg = (char*)"invalid bit length repeat";
r = Z_DATA_ERROR;
LEAVE
}
c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
do {
s->sub.trees.blens[i++] = c;
} while (--j);
s->sub.trees.index = i;
}
}
s->sub.trees.tb = Z_NULL;
{
uInt bl, bd;
inflate_huft *tl, *td;
inflate_codes_statef *c;
bl = 9; /* must be <= 9 for lookahead assumptions */
bd = 6; /* must be <= 9 for lookahead assumptions */
t = s->sub.trees.table;
t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
s->sub.trees.blens, &bl, &bd, &tl, &td,
s->hufts, z);
if (t != Z_OK)
{
if (t == (uInt)Z_DATA_ERROR)
{
ZFREE(z, s->sub.trees.blens);
s->mode = BAD;
}
r = t;
LEAVE
}
Tracev((stderr, "inflate: trees ok\n"));
if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
{
r = Z_MEM_ERROR;
LEAVE
}
s->sub.decode.codes = c;
}
ZFREE(z, s->sub.trees.blens);
s->mode = CODES;
case CODES:
UPDATE
if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
return inflate_flush(s, z, r);
r = Z_OK;
inflate_codes_free(s->sub.decode.codes, z);
LOAD
Tracev((stderr, "inflate: codes end, %lu total out\n",
z->total_out + (q >= s->read ? q - s->read :
(s->end - s->read) + (q - s->window))));
if (!s->last)
{
s->mode = TYPE;
break;
}
s->mode = DRY;
case DRY:
FLUSH
if (s->read != s->write)
LEAVE
s->mode = DONE;
case DONE:
r = Z_STREAM_END;
LEAVE
case BAD:
r = Z_DATA_ERROR;
LEAVE
default:
r = Z_STREAM_ERROR;
LEAVE
}
}
int inflate_blocks_free(s, z)
inflate_blocks_statef *s;
z_streamp z;
{
inflate_blocks_reset(s, z, Z_NULL);
ZFREE(z, s->window);
ZFREE(z, s->hufts);
ZFREE(z, s);
Tracev((stderr, "inflate: blocks freed\n"));
return Z_OK;
}
void inflate_set_dictionary(s, d, n)
inflate_blocks_statef *s;
const Bytef *d;
uInt n;
{
zmemcpy(s->window, d, n);
s->read = s->write = s->window + n;
}
/* Returns true if inflate is currently at the end of a block generated
* by Z_SYNC_FLUSH or Z_FULL_FLUSH.
* IN assertion: s != Z_NULL
*/
int inflate_blocks_sync_point(s)
inflate_blocks_statef *s;
{
return s->mode == LENS;
}
+39
View File
@@ -0,0 +1,39 @@
/* infblock.h -- header to use infblock.c
* Copyright (C) 1995-2002 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
struct inflate_blocks_state;
typedef struct inflate_blocks_state FAR inflate_blocks_statef;
extern inflate_blocks_statef * inflate_blocks_new OF((
z_streamp z,
check_func c, /* check function */
uInt w)); /* window size */
extern int inflate_blocks OF((
inflate_blocks_statef *,
z_streamp ,
int)); /* initial return code */
extern void inflate_blocks_reset OF((
inflate_blocks_statef *,
z_streamp ,
uLongf *)); /* check value on output */
extern int inflate_blocks_free OF((
inflate_blocks_statef *,
z_streamp));
extern void inflate_set_dictionary OF((
inflate_blocks_statef *s,
const Bytef *d, /* dictionary */
uInt n)); /* dictionary length */
extern int inflate_blocks_sync_point OF((
inflate_blocks_statef *s));
+251
View File
@@ -0,0 +1,251 @@
/* infcodes.c -- process literals and length/distance pairs
* Copyright (C) 1995-2002 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include <zlib/zutil.h>
#include "inftrees.h"
#include "infblock.h"
#include "infcodes.h"
#include "infutil.h"
#include "inffast.h"
/* simplify the use of the inflate_huft type with some defines */
#define exop word.what.Exop
#define bits word.what.Bits
typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
START, /* x: set up for LEN */
LEN, /* i: get length/literal/eob next */
LENEXT, /* i: getting length extra (have base) */
DIST, /* i: get distance next */
DISTEXT, /* i: getting distance extra */
COPY, /* o: copying bytes in window, waiting for space */
LIT, /* o: got literal, waiting for output space */
WASH, /* o: got eob, possibly still output waiting */
END, /* x: got eob and all data flushed */
BADCODE} /* x: got error */
inflate_codes_mode;
/* inflate codes private state */
struct inflate_codes_state {
/* mode */
inflate_codes_mode mode; /* current inflate_codes mode */
/* mode dependent information */
uInt len;
union {
struct {
inflate_huft *tree; /* pointer into tree */
uInt need; /* bits needed */
} code; /* if LEN or DIST, where in tree */
uInt lit; /* if LIT, literal */
struct {
uInt get; /* bits to get for extra */
uInt dist; /* distance back to copy from */
} copy; /* if EXT or COPY, where and how much */
} sub; /* submode */
/* mode independent information */
Byte lbits; /* ltree bits decoded per branch */
Byte dbits; /* dtree bits decoder per branch */
inflate_huft *ltree; /* literal/length/eob tree */
inflate_huft *dtree; /* distance tree */
};
inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
uInt bl, bd;
inflate_huft *tl;
inflate_huft *td; /* need separate declaration for Borland C++ */
z_streamp z;
{
inflate_codes_statef *c;
if ((c = (inflate_codes_statef *)
ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
{
c->mode = START;
c->lbits = (Byte)bl;
c->dbits = (Byte)bd;
c->ltree = tl;
c->dtree = td;
Tracev((stderr, "inflate: codes new\n"));
}
return c;
}
int inflate_codes(s, z, r)
inflate_blocks_statef *s;
z_streamp z;
int r;
{
uInt j; /* temporary storage */
inflate_huft *t; /* temporary pointer */
uInt e; /* extra bits or operation */
uLong b; /* bit buffer */
uInt k; /* bits in bit buffer */
Bytef *p; /* input data pointer */
uInt n; /* bytes available there */
Bytef *q; /* output window write pointer */
uInt m; /* bytes to end of window or read pointer */
Bytef *f; /* pointer to copy strings from */
inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
/* copy input/output information to locals (UPDATE macro restores) */
LOAD
/* process input and output based on current state */
while (1) switch (c->mode)
{ /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
case START: /* x: set up for LEN */
#ifndef SLOW
if (m >= 258 && n >= 10)
{
UPDATE
r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
LOAD
if (r != Z_OK)
{
c->mode = r == Z_STREAM_END ? WASH : BADCODE;
break;
}
}
#endif /* !SLOW */
c->sub.code.need = c->lbits;
c->sub.code.tree = c->ltree;
c->mode = LEN;
case LEN: /* i: get length/literal/eob next */
j = c->sub.code.need;
NEEDBITS(j)
t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
DUMPBITS(t->bits)
e = (uInt)(t->exop);
if (e == 0) /* literal */
{
c->sub.lit = t->base;
Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
"inflate: literal '%c'\n" :
"inflate: literal 0x%02x\n", t->base));
c->mode = LIT;
break;
}
if (e & 16) /* length */
{
c->sub.copy.get = e & 15;
c->len = t->base;
c->mode = LENEXT;
break;
}
if ((e & 64) == 0) /* next table */
{
c->sub.code.need = e;
c->sub.code.tree = t + t->base;
break;
}
if (e & 32) /* end of block */
{
Tracevv((stderr, "inflate: end of block\n"));
c->mode = WASH;
break;
}
c->mode = BADCODE; /* invalid code */
z->msg = (char*)"invalid literal/length code";
r = Z_DATA_ERROR;
LEAVE
case LENEXT: /* i: getting length extra (have base) */
j = c->sub.copy.get;
NEEDBITS(j)
c->len += (uInt)b & inflate_mask[j];
DUMPBITS(j)
c->sub.code.need = c->dbits;
c->sub.code.tree = c->dtree;
Tracevv((stderr, "inflate: length %u\n", c->len));
c->mode = DIST;
case DIST: /* i: get distance next */
j = c->sub.code.need;
NEEDBITS(j)
t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
DUMPBITS(t->bits)
e = (uInt)(t->exop);
if (e & 16) /* distance */
{
c->sub.copy.get = e & 15;
c->sub.copy.dist = t->base;
c->mode = DISTEXT;
break;
}
if ((e & 64) == 0) /* next table */
{
c->sub.code.need = e;
c->sub.code.tree = t + t->base;
break;
}
c->mode = BADCODE; /* invalid code */
z->msg = (char*)"invalid distance code";
r = Z_DATA_ERROR;
LEAVE
case DISTEXT: /* i: getting distance extra */
j = c->sub.copy.get;
NEEDBITS(j)
c->sub.copy.dist += (uInt)b & inflate_mask[j];
DUMPBITS(j)
Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));
c->mode = COPY;
case COPY: /* o: copying bytes in window, waiting for space */
f = q - c->sub.copy.dist;
while (f < s->window) /* modulo window size-"while" instead */
f += s->end - s->window; /* of "if" handles invalid distances */
while (c->len)
{
NEEDOUT
OUTBYTE(*f++)
if (f == s->end)
f = s->window;
c->len--;
}
c->mode = START;
break;
case LIT: /* o: got literal, waiting for output space */
NEEDOUT
OUTBYTE(c->sub.lit)
c->mode = START;
break;
case WASH: /* o: got eob, possibly more output */
if (k > 7) /* return unused byte, if any */
{
Assert(k < 16, "inflate_codes grabbed too many bytes")
k -= 8;
n++;
p--; /* can always return one */
}
FLUSH
if (s->read != s->write)
LEAVE
c->mode = END;
case END:
r = Z_STREAM_END;
LEAVE
case BADCODE: /* x: got error */
r = Z_DATA_ERROR;
LEAVE
default:
r = Z_STREAM_ERROR;
LEAVE
}
#ifdef NEED_DUMMY_RETURN
return Z_STREAM_ERROR; /* Some dumb compilers complain without this */
#endif
}
void inflate_codes_free(c, z)
inflate_codes_statef *c;
z_streamp z;
{
ZFREE(z, c);
Tracev((stderr, "inflate: codes free\n"));
}
+31
View File
@@ -0,0 +1,31 @@
/* infcodes.h -- header to use infcodes.c
* Copyright (C) 1995-2002 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
#ifndef _INFCODES_H
#define _INFCODES_H
struct inflate_codes_state;
typedef struct inflate_codes_state FAR inflate_codes_statef;
extern inflate_codes_statef *inflate_codes_new OF((
uInt, uInt,
inflate_huft *, inflate_huft *,
z_streamp ));
extern int inflate_codes OF((
inflate_blocks_statef *,
z_streamp ,
int));
extern void inflate_codes_free OF((
inflate_codes_statef *,
z_streamp ));
#endif /* _INFCODES_H */
+183
View File
@@ -0,0 +1,183 @@
/* inffast.c -- process literals and length/distance pairs fast
* Copyright (C) 1995-2002 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include <zlib/zutil.h>
#include "inftrees.h"
#include "infblock.h"
#include "infcodes.h"
#include "infutil.h"
#include "inffast.h"
struct inflate_codes_state {int dummy;}; /* for buggy compilers */
/* simplify the use of the inflate_huft type with some defines */
#define exop word.what.Exop
#define bits word.what.Bits
/* macros for bit input with no checking and for returning unused bytes */
#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
#define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;}
/* Called with number of bytes left to write in window at least 258
(the maximum string length) and number of input bytes available
at least ten. The ten bytes are six bytes for the longest length/
distance pair plus four bytes for overloading the bit buffer. */
int inflate_fast(bl, bd, tl, td, s, z)
uInt bl, bd;
inflate_huft *tl;
inflate_huft *td; /* need separate declaration for Borland C++ */
inflate_blocks_statef *s;
z_streamp z;
{
inflate_huft *t; /* temporary pointer */
uInt e; /* extra bits or operation */
uLong b; /* bit buffer */
uInt k; /* bits in bit buffer */
Bytef *p; /* input data pointer */
uInt n; /* bytes available there */
Bytef *q; /* output window write pointer */
uInt m; /* bytes to end of window or read pointer */
uInt ml; /* mask for literal/length tree */
uInt md; /* mask for distance tree */
uInt c; /* bytes to copy */
uInt d; /* distance back to copy from */
Bytef *r; /* copy source pointer */
/* load input, output, bit values */
LOAD
/* initialize masks */
ml = inflate_mask[bl];
md = inflate_mask[bd];
/* do until not enough input or output space for fast loop */
do { /* assume called with m >= 258 && n >= 10 */
/* get literal/length code */
GRABBITS(20) /* max bits for literal/length code */
if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
{
DUMPBITS(t->bits)
Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
"inflate: * literal '%c'\n" :
"inflate: * literal 0x%02x\n", t->base));
*q++ = (Byte)t->base;
m--;
continue;
}
do {
DUMPBITS(t->bits)
if (e & 16)
{
/* get extra bits for length */
e &= 15;
c = t->base + ((uInt)b & inflate_mask[e]);
DUMPBITS(e)
Tracevv((stderr, "inflate: * length %u\n", c));
/* decode distance base of block to copy */
GRABBITS(15); /* max bits for distance code */
e = (t = td + ((uInt)b & md))->exop;
do {
DUMPBITS(t->bits)
if (e & 16)
{
/* get extra bits to add to distance base */
e &= 15;
GRABBITS(e) /* get extra bits (up to 13) */
d = t->base + ((uInt)b & inflate_mask[e]);
DUMPBITS(e)
Tracevv((stderr, "inflate: * distance %u\n", d));
/* do the copy */
m -= c;
r = q - d;
if (r < s->window) /* wrap if needed */
{
do {
r += s->end - s->window; /* force pointer in window */
} while (r < s->window); /* covers invalid distances */
e = s->end - r;
if (c > e)
{
c -= e; /* wrapped copy */
do {
*q++ = *r++;
} while (--e);
r = s->window;
do {
*q++ = *r++;
} while (--c);
}
else /* normal copy */
{
*q++ = *r++; c--;
*q++ = *r++; c--;
do {
*q++ = *r++;
} while (--c);
}
}
else /* normal copy */
{
*q++ = *r++; c--;
*q++ = *r++; c--;
do {
*q++ = *r++;
} while (--c);
}
break;
}
else if ((e & 64) == 0)
{
t += t->base;
e = (t += ((uInt)b & inflate_mask[e]))->exop;
}
else
{
z->msg = (char*)"invalid distance code";
UNGRAB
UPDATE
return Z_DATA_ERROR;
}
} while (1);
break;
}
if ((e & 64) == 0)
{
t += t->base;
if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0)
{
DUMPBITS(t->bits)
Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
"inflate: * literal '%c'\n" :
"inflate: * literal 0x%02x\n", t->base));
*q++ = (Byte)t->base;
m--;
break;
}
}
else if (e & 32)
{
Tracevv((stderr, "inflate: * end of block\n"));
UNGRAB
UPDATE
return Z_STREAM_END;
}
else
{
z->msg = (char*)"invalid literal/length code";
UNGRAB
UPDATE
return Z_DATA_ERROR;
}
} while (1);
} while (m >= 258 && n >= 10);
/* not enough input or output--restore pointers and return */
UNGRAB
UPDATE
return Z_OK;
}
+22
View File
@@ -0,0 +1,22 @@
/* inffast.h -- header to use inffast.c
* Copyright (C) 1995-2002 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
#ifndef _INFFAST_H
#define _INFFAST_H
extern int inflate_fast OF((
uInt,
uInt,
inflate_huft *,
inflate_huft *,
inflate_blocks_statef *,
z_streamp ));
#endif /* _INFFAST_H */
+151
View File
@@ -0,0 +1,151 @@
/* inffixed.h -- table for decoding fixed codes
* Generated automatically by the maketree.c program
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
local uInt fixed_bl = 9;
local uInt fixed_bd = 5;
local inflate_huft fixed_tl[] = {
{{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
{{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192},
{{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160},
{{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224},
{{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144},
{{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208},
{{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176},
{{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240},
{{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
{{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200},
{{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168},
{{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232},
{{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152},
{{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216},
{{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184},
{{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248},
{{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
{{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196},
{{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164},
{{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228},
{{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148},
{{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212},
{{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180},
{{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244},
{{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
{{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204},
{{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172},
{{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236},
{{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156},
{{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220},
{{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188},
{{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252},
{{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
{{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194},
{{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162},
{{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226},
{{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146},
{{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210},
{{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178},
{{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242},
{{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
{{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202},
{{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170},
{{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234},
{{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154},
{{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218},
{{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186},
{{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250},
{{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
{{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198},
{{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166},
{{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230},
{{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150},
{{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214},
{{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182},
{{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246},
{{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
{{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206},
{{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174},
{{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238},
{{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158},
{{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222},
{{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190},
{{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254},
{{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
{{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193},
{{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161},
{{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225},
{{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145},
{{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209},
{{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177},
{{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241},
{{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
{{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201},
{{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169},
{{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233},
{{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153},
{{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217},
{{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185},
{{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249},
{{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
{{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197},
{{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165},
{{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229},
{{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149},
{{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213},
{{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181},
{{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245},
{{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
{{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205},
{{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173},
{{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237},
{{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157},
{{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221},
{{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189},
{{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253},
{{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
{{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195},
{{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163},
{{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227},
{{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147},
{{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211},
{{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179},
{{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243},
{{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
{{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203},
{{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171},
{{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235},
{{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155},
{{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219},
{{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187},
{{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251},
{{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
{{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199},
{{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167},
{{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231},
{{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151},
{{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215},
{{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183},
{{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247},
{{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
{{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207},
{{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175},
{{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239},
{{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159},
{{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223},
{{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191},
{{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255}
};
local inflate_huft fixed_td[] = {
{{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097},
{{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385},
{{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193},
{{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577},
{{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145},
{{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577},
{{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289},
{{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577}
};
+368
View File
@@ -0,0 +1,368 @@
/* inflate.c -- zlib interface to inflate modules
* Copyright (C) 1995-2002 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include <zlib/zutil.h>
#include "infblock.h"
struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
typedef enum {
METHOD, /* waiting for method byte */
FLAG, /* waiting for flag byte */
DICT4, /* four dictionary check bytes to go */
DICT3, /* three dictionary check bytes to go */
DICT2, /* two dictionary check bytes to go */
DICT1, /* one dictionary check byte to go */
DICT0, /* waiting for inflateSetDictionary */
BLOCKS, /* decompressing blocks */
CHECK4, /* four check bytes to go */
CHECK3, /* three check bytes to go */
CHECK2, /* two check bytes to go */
CHECK1, /* one check byte to go */
DONE, /* finished check, done */
BAD} /* got an error--stay here */
inflate_mode;
/* inflate private state */
struct internal_state {
/* mode */
inflate_mode mode; /* current inflate mode */
/* mode dependent information */
union {
uInt method; /* if FLAGS, method byte */
struct {
uLong was; /* computed check value */
uLong need; /* stream check value */
} check; /* if CHECK, check values to compare */
uInt marker; /* if BAD, inflateSync's marker bytes count */
} sub; /* submode */
/* mode independent information */
int nowrap; /* flag for no wrapper */
uInt wbits; /* log2(window size) (8..15, defaults to 15) */
inflate_blocks_statef
*blocks; /* current inflate_blocks state */
};
int ZEXPORT inflateReset(z)
z_streamp z;
{
if (z == Z_NULL || z->state == Z_NULL)
return Z_STREAM_ERROR;
z->total_in = z->total_out = 0;
z->msg = Z_NULL;
z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
inflate_blocks_reset(z->state->blocks, z, Z_NULL);
Tracev((stderr, "inflate: reset\n"));
return Z_OK;
}
int ZEXPORT inflateEnd(z)
z_streamp z;
{
if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
return Z_STREAM_ERROR;
if (z->state->blocks != Z_NULL)
inflate_blocks_free(z->state->blocks, z);
ZFREE(z, z->state);
z->state = Z_NULL;
Tracev((stderr, "inflate: end\n"));
return Z_OK;
}
int ZEXPORT inflateInit2_(z, w, version, stream_size)
z_streamp z;
int w;
const char *version;
int stream_size;
{
if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
stream_size != sizeof(z_stream))
return Z_VERSION_ERROR;
/* initialize state */
if (z == Z_NULL)
return Z_STREAM_ERROR;
z->msg = Z_NULL;
if (z->zalloc == Z_NULL)
{
return Z_STREAM_ERROR;
/* z->zalloc = zcalloc;
z->opaque = (voidpf)0;
*/
}
if (z->zfree == Z_NULL) return Z_STREAM_ERROR; /* z->zfree = zcfree; */
if ((z->state = (struct internal_state FAR *)
ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
return Z_MEM_ERROR;
z->state->blocks = Z_NULL;
/* handle undocumented nowrap option (no zlib header or check) */
z->state->nowrap = 0;
if (w < 0)
{
w = - w;
z->state->nowrap = 1;
}
/* set window size */
if (w < 8 || w > 15)
{
inflateEnd(z);
return Z_STREAM_ERROR;
}
z->state->wbits = (uInt)w;
/* create inflate_blocks state */
if ((z->state->blocks =
inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
== Z_NULL)
{
inflateEnd(z);
return Z_MEM_ERROR;
}
Tracev((stderr, "inflate: allocated\n"));
/* reset state */
inflateReset(z);
return Z_OK;
}
int ZEXPORT inflateInit_(z, version, stream_size)
z_streamp z;
const char *version;
int stream_size;
{
return inflateInit2_(z, DEF_WBITS, version, stream_size);
}
#define NEEDBYTE {if(z->avail_in==0)return r;r=f;}
#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
int ZEXPORT inflate(z, f)
z_streamp z;
int f;
{
int r;
uInt b;
if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
return Z_STREAM_ERROR;
f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
r = Z_BUF_ERROR;
while (1) switch (z->state->mode)
{
case METHOD:
NEEDBYTE
if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
{
z->state->mode = BAD;
z->msg = (char*)"unknown compression method";
z->state->sub.marker = 5; /* can't try inflateSync */
break;
}
if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
{
z->state->mode = BAD;
z->msg = (char*)"invalid window size";
z->state->sub.marker = 5; /* can't try inflateSync */
break;
}
z->state->mode = FLAG;
case FLAG:
NEEDBYTE
b = NEXTBYTE;
if (((z->state->sub.method << 8) + b) % 31)
{
z->state->mode = BAD;
z->msg = (char*)"incorrect header check";
z->state->sub.marker = 5; /* can't try inflateSync */
break;
}
Tracev((stderr, "inflate: zlib header ok\n"));
if (!(b & PRESET_DICT))
{
z->state->mode = BLOCKS;
break;
}
z->state->mode = DICT4;
case DICT4:
NEEDBYTE
z->state->sub.check.need = (uLong)NEXTBYTE << 24;
z->state->mode = DICT3;
case DICT3:
NEEDBYTE
z->state->sub.check.need += (uLong)NEXTBYTE << 16;
z->state->mode = DICT2;
case DICT2:
NEEDBYTE
z->state->sub.check.need += (uLong)NEXTBYTE << 8;
z->state->mode = DICT1;
case DICT1:
NEEDBYTE
z->state->sub.check.need += (uLong)NEXTBYTE;
z->adler = z->state->sub.check.need;
z->state->mode = DICT0;
return Z_NEED_DICT;
case DICT0:
z->state->mode = BAD;
z->msg = (char*)"need dictionary";
z->state->sub.marker = 0; /* can try inflateSync */
return Z_STREAM_ERROR;
case BLOCKS:
r = inflate_blocks(z->state->blocks, z, r);
if (r == Z_DATA_ERROR)
{
z->state->mode = BAD;
z->state->sub.marker = 0; /* can try inflateSync */
break;
}
if (r == Z_OK)
r = f;
if (r != Z_STREAM_END)
return r;
r = f;
inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
if (z->state->nowrap)
{
z->state->mode = DONE;
break;
}
z->state->mode = CHECK4;
case CHECK4:
NEEDBYTE
z->state->sub.check.need = (uLong)NEXTBYTE << 24;
z->state->mode = CHECK3;
case CHECK3:
NEEDBYTE
z->state->sub.check.need += (uLong)NEXTBYTE << 16;
z->state->mode = CHECK2;
case CHECK2:
NEEDBYTE
z->state->sub.check.need += (uLong)NEXTBYTE << 8;
z->state->mode = CHECK1;
case CHECK1:
NEEDBYTE
z->state->sub.check.need += (uLong)NEXTBYTE;
if (z->state->sub.check.was != z->state->sub.check.need)
{
z->state->mode = BAD;
z->msg = (char*)"incorrect data check";
z->state->sub.marker = 5; /* can't try inflateSync */
break;
}
Tracev((stderr, "inflate: zlib check ok\n"));
z->state->mode = DONE;
case DONE:
return Z_STREAM_END;
case BAD:
return Z_DATA_ERROR;
default:
return Z_STREAM_ERROR;
}
#ifdef NEED_DUMMY_RETURN
return Z_STREAM_ERROR; /* Some dumb compilers complain without this */
#endif
}
int ZEXPORT inflateSetDictionary(z, dictionary, dictLength)
z_streamp z;
const Bytef *dictionary;
uInt dictLength;
{
uInt length = dictLength;
if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0)
return Z_STREAM_ERROR;
if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR;
z->adler = 1L;
if (length >= ((uInt)1<<z->state->wbits))
{
length = (1<<z->state->wbits)-1;
dictionary += dictLength - length;
}
inflate_set_dictionary(z->state->blocks, dictionary, length);
z->state->mode = BLOCKS;
return Z_OK;
}
int ZEXPORT inflateSync(z)
z_streamp z;
{
uInt n; /* number of bytes to look at */
Bytef *p; /* pointer to bytes */
uInt m; /* number of marker bytes found in a row */
uLong r, w; /* temporaries to save total_in and total_out */
/* set up */
if (z == Z_NULL || z->state == Z_NULL)
return Z_STREAM_ERROR;
if (z->state->mode != BAD)
{
z->state->mode = BAD;
z->state->sub.marker = 0;
}
if ((n = z->avail_in) == 0)
return Z_BUF_ERROR;
p = z->next_in;
m = z->state->sub.marker;
/* search */
while (n && m < 4)
{
static const Byte mark[4] = {0, 0, 0xff, 0xff};
if (*p == mark[m])
m++;
else if (*p)
m = 0;
else
m = 4 - m;
p++, n--;
}
/* restore */
z->total_in += p - z->next_in;
z->next_in = p;
z->avail_in = n;
z->state->sub.marker = m;
/* return no joy or set up to restart on a new block */
if (m != 4)
return Z_DATA_ERROR;
r = z->total_in; w = z->total_out;
inflateReset(z);
z->total_in = r; z->total_out = w;
z->state->mode = BLOCKS;
return Z_OK;
}
/* Returns true if inflate is currently at the end of a block generated
* by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
* implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
* but removes the length bytes of the resulting empty stored block. When
* decompressing, PPP checks that at the end of input packet, inflate is
* waiting for these length bytes.
*/
int ZEXPORT inflateSyncPoint(z)
z_streamp z;
{
if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL)
return Z_STREAM_ERROR;
return inflate_blocks_sync_point(z->state->blocks);
}
+454
View File
@@ -0,0 +1,454 @@
/* inftrees.c -- generate Huffman trees for efficient decoding
* Copyright (C) 1995-2002 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include <zlib/zutil.h>
#include "inftrees.h"
#if !defined(BUILDFIXED) && !defined(STDC)
# define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */
#endif
local const char inflate_copyright[] =
" inflate 1.1.4 Copyright 1995-2002 Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
include such an acknowledgment, I would appreciate that you keep this
copyright string in the executable of your product.
*/
struct internal_state {int dummy;}; /* for buggy compilers */
/* simplify the use of the inflate_huft type with some defines */
#define exop word.what.Exop
#define bits word.what.Bits
local int huft_build OF((
uIntf *, /* code lengths in bits */
uInt, /* number of codes */
uInt, /* number of "simple" codes */
const uIntf *, /* list of base values for non-simple codes */
const uIntf *, /* list of extra bits for non-simple codes */
inflate_huft * FAR*,/* result: starting table */
uIntf *, /* maximum lookup bits (returns actual) */
inflate_huft *, /* space for trees */
uInt *, /* hufts used in space */
uIntf * )); /* space for values */
/* Tables for deflate from PKZIP's appnote.txt. */
local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
/* see note #13 above about 258 */
local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */
local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
8193, 12289, 16385, 24577};
local const uInt cpdext[30] = { /* Extra bits for distance codes */
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 13, 13};
/*
Huffman code decoding is performed using a multi-level table lookup.
The fastest way to decode is to simply build a lookup table whose
size is determined by the longest code. However, the time it takes
to build this table can also be a factor if the data being decoded
is not very long. The most common codes are necessarily the
shortest codes, so those codes dominate the decoding time, and hence
the speed. The idea is you can have a shorter table that decodes the
shorter, more probable codes, and then point to subsidiary tables for
the longer codes. The time it costs to decode the longer codes is
then traded against the time it takes to make longer tables.
This results of this trade are in the variables lbits and dbits
below. lbits is the number of bits the first level table for literal/
length codes can decode in one step, and dbits is the same thing for
the distance codes. Subsequent tables are also less than or equal to
those sizes. These values may be adjusted either when all of the
codes are shorter than that, in which case the longest code length in
bits is used, or when the shortest code is *longer* than the requested
table size, in which case the length of the shortest code in bits is
used.
There are two different values for the two tables, since they code a
different number of possibilities each. The literal/length table
codes 286 possible values, or in a flat code, a little over eight
bits. The distance table codes 30 possible values, or a little less
than five bits, flat. The optimum values for speed end up being
about one bit more than those, so lbits is 8+1 and dbits is 5+1.
The optimum values may differ though from machine to machine, and
possibly even between compilers. Your mileage may vary.
*/
/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
#define BMAX 15 /* maximum bit length of any code */
local int huft_build(b, n, s, d, e, t, m, hp, hn, v)
uIntf *b; /* code lengths in bits (all assumed <= BMAX) */
uInt n; /* number of codes (assumed <= 288) */
uInt s; /* number of simple-valued codes (0..s-1) */
const uIntf *d; /* list of base values for non-simple codes */
const uIntf *e; /* list of extra bits for non-simple codes */
inflate_huft * FAR *t; /* result: starting table */
uIntf *m; /* maximum lookup bits, returns actual */
inflate_huft *hp; /* space for trees */
uInt *hn; /* hufts used in space */
uIntf *v; /* working area: values in order of bit length */
/* Given a list of code lengths and a maximum table size, make a set of
tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
if the given code set is incomplete (the tables are still built in this
case), or Z_DATA_ERROR if the input is invalid. */
{
uInt a; /* counter for codes of length k */
uInt c[BMAX+1]; /* bit length count table */
uInt f; /* i repeats in table every f entries */
int g; /* maximum code length */
int h; /* table level */
register uInt i; /* counter, current code */
register uInt j; /* counter */
register int k; /* number of bits in current code */
int l; /* bits per table (returned in m) */
uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */
register uIntf *p; /* pointer into c[], b[], or v[] */
inflate_huft *q; /* points to current table */
struct inflate_huft_s r; /* table entry for structure assignment */
inflate_huft *u[BMAX]; /* table stack */
register int w; /* bits before this table == (l * h) */
uInt x[BMAX+1]; /* bit offsets, then code stack */
uIntf *xp; /* pointer into x */
int y; /* number of dummy codes added */
uInt z; /* number of entries in current table */
/* Generate counts for each bit length */
p = c;
#define C0 *p++ = 0;
#define C2 C0 C0 C0 C0
#define C4 C2 C2 C2 C2
C4 /* clear c[]--assume BMAX+1 is 16 */
p = b; i = n;
do {
c[*p++]++; /* assume all entries <= BMAX */
} while (--i);
if (c[0] == n) /* null input--all zero length codes */
{
*t = (inflate_huft *)Z_NULL;
*m = 0;
return Z_OK;
}
/* Find minimum and maximum length, bound *m by those */
l = *m;
for (j = 1; j <= BMAX; j++)
if (c[j])
break;
k = j; /* minimum code length */
if ((uInt)l < j)
l = j;
for (i = BMAX; i; i--)
if (c[i])
break;
g = i; /* maximum code length */
if ((uInt)l > i)
l = i;
*m = l;
/* Adjust last length count to fill out codes, if needed */
for (y = 1 << j; j < i; j++, y <<= 1)
if ((y -= c[j]) < 0)
return Z_DATA_ERROR;
if ((y -= c[i]) < 0)
return Z_DATA_ERROR;
c[i] += y;
/* Generate starting offsets into the value table for each length */
x[1] = j = 0;
p = c + 1; xp = x + 2;
while (--i) { /* note that i == g from above */
*xp++ = (j += *p++);
}
/* Make a table of values in order of bit lengths */
p = b; i = 0;
do {
if ((j = *p++) != 0)
v[x[j]++] = i;
} while (++i < n);
n = x[g]; /* set n to length of v */
/* Generate the Huffman codes and for each, make the table entries */
x[0] = i = 0; /* first Huffman code is zero */
p = v; /* grab values in bit order */
h = -1; /* no tables yet--level -1 */
w = -l; /* bits decoded == (l * h) */
u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */
q = (inflate_huft *)Z_NULL; /* ditto */
z = 0; /* ditto */
/* go through the bit lengths (k already is bits in shortest code) */
for (; k <= g; k++)
{
a = c[k];
while (a--)
{
/* here i is the Huffman code of length k bits for value *p */
/* make tables up to required level */
while (k > w + l)
{
h++;
w += l; /* previous table always l bits */
/* compute minimum size table less than or equal to l bits */
z = g - w;
z = z > (uInt)l ? l : z; /* table size upper limit */
if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
{ /* too few codes for k-w bit table */
f -= a + 1; /* deduct codes from patterns left */
xp = c + k;
if (j < z)
while (++j < z) /* try smaller tables up to z bits */
{
if ((f <<= 1) <= *++xp)
break; /* enough codes to use up j bits */
f -= *xp; /* else deduct codes from patterns */
}
}
z = 1 << j; /* table entries for j-bit table */
/* allocate new table */
if (*hn + z > MANY) /* (note: doesn't matter for fixed) */
return Z_DATA_ERROR; /* overflow of MANY */
u[h] = q = hp + *hn;
*hn += z;
/* connect to last table, if there is one */
if (h)
{
x[h] = i; /* save pattern for backing up */
r.bits = (Byte)l; /* bits to dump before this table */
r.exop = (Byte)j; /* bits in this table */
j = i >> (w - l);
r.base = (uInt)(q - u[h-1] - j); /* offset to this table */
u[h-1][j] = r; /* connect to last table */
}
else
*t = q; /* first table is returned result */
}
/* set up table entry in r */
r.bits = (Byte)(k - w);
if (p >= v + n)
r.exop = 128 + 64; /* out of values--invalid code */
else if (*p < s)
{
r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */
r.base = *p++; /* simple code is just the value */
}
else
{
r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
r.base = d[*p++ - s];
}
/* fill code-like entries with r */
f = 1 << (k - w);
for (j = i >> w; j < z; j += f)
q[j] = r;
/* backwards increment the k-bit code i */
for (j = 1 << (k - 1); i & j; j >>= 1)
i ^= j;
i ^= j;
/* backup over finished tables */
mask = (1 << w) - 1; /* needed on HP, cc -O bug */
while ((i & mask) != x[h])
{
h--; /* don't need to update q */
w -= l;
mask = (1 << w) - 1;
}
}
}
/* Return Z_BUF_ERROR if we were given an incomplete table */
return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
}
int inflate_trees_bits(c, bb, tb, hp, z)
uIntf *c; /* 19 code lengths */
uIntf *bb; /* bits tree desired/actual depth */
inflate_huft * FAR *tb; /* bits tree result */
inflate_huft *hp; /* space for trees */
z_streamp z; /* for messages */
{
int r;
uInt hn = 0; /* hufts used in space */
uIntf *v; /* work area for huft_build */
if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL)
return Z_MEM_ERROR;
r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL,
tb, bb, hp, &hn, v);
if (r == Z_DATA_ERROR)
z->msg = (char*)"oversubscribed dynamic bit lengths tree";
else if (r == Z_BUF_ERROR || *bb == 0)
{
z->msg = (char*)"incomplete dynamic bit lengths tree";
r = Z_DATA_ERROR;
}
ZFREE(z, v);
return r;
}
int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z)
uInt nl; /* number of literal/length codes */
uInt nd; /* number of distance codes */
uIntf *c; /* that many (total) code lengths */
uIntf *bl; /* literal desired/actual bit depth */
uIntf *bd; /* distance desired/actual bit depth */
inflate_huft * FAR *tl; /* literal/length tree result */
inflate_huft * FAR *td; /* distance tree result */
inflate_huft *hp; /* space for trees */
z_streamp z; /* for messages */
{
int r;
uInt hn = 0; /* hufts used in space */
uIntf *v; /* work area for huft_build */
/* allocate work area */
if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
return Z_MEM_ERROR;
/* build literal/length tree */
r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v);
if (r != Z_OK || *bl == 0)
{
if (r == Z_DATA_ERROR)
z->msg = (char*)"oversubscribed literal/length tree";
else if (r != Z_MEM_ERROR)
{
z->msg = (char*)"incomplete literal/length tree";
r = Z_DATA_ERROR;
}
ZFREE(z, v);
return r;
}
/* build distance tree */
r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v);
if (r != Z_OK || (*bd == 0 && nl > 257))
{
if (r == Z_DATA_ERROR)
z->msg = (char*)"oversubscribed distance tree";
else if (r == Z_BUF_ERROR) {
#ifdef PKZIP_BUG_WORKAROUND
r = Z_OK;
}
#else
z->msg = (char*)"incomplete distance tree";
r = Z_DATA_ERROR;
}
else if (r != Z_MEM_ERROR)
{
z->msg = (char*)"empty distance tree with lengths";
r = Z_DATA_ERROR;
}
ZFREE(z, v);
return r;
#endif
}
/* done */
ZFREE(z, v);
return Z_OK;
}
/* build fixed tables only once--keep them here */
#ifdef BUILDFIXED
local int fixed_built = 0;
#define FIXEDH 544 /* number of hufts used by fixed tables */
local inflate_huft fixed_mem[FIXEDH];
local uInt fixed_bl;
local uInt fixed_bd;
local inflate_huft *fixed_tl;
local inflate_huft *fixed_td;
#else
#include "inffixed.h"
#endif
int inflate_trees_fixed(bl, bd, tl, td, z)
uIntf *bl; /* literal desired/actual bit depth */
uIntf *bd; /* distance desired/actual bit depth */
inflate_huft * FAR *tl; /* literal/length tree result */
inflate_huft * FAR *td; /* distance tree result */
z_streamp z; /* for memory allocation */
{
#ifdef BUILDFIXED
/* build fixed tables if not already */
if (!fixed_built)
{
int k; /* temporary variable */
uInt f = 0; /* number of hufts used in fixed_mem */
uIntf *c; /* length list for huft_build */
uIntf *v; /* work area for huft_build */
/* allocate memory */
if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
return Z_MEM_ERROR;
if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
{
ZFREE(z, c);
return Z_MEM_ERROR;
}
/* literal table */
for (k = 0; k < 144; k++)
c[k] = 8;
for (; k < 256; k++)
c[k] = 9;
for (; k < 280; k++)
c[k] = 7;
for (; k < 288; k++)
c[k] = 8;
fixed_bl = 9;
huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl,
fixed_mem, &f, v);
/* distance table */
for (k = 0; k < 30; k++)
c[k] = 5;
fixed_bd = 5;
huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd,
fixed_mem, &f, v);
/* done */
ZFREE(z, v);
ZFREE(z, c);
fixed_built = 1;
}
#endif
*bl = fixed_bl;
*bd = fixed_bd;
*tl = fixed_tl;
*td = fixed_td;
return Z_OK;
}
+63
View File
@@ -0,0 +1,63 @@
/* inftrees.h -- header to use inftrees.c
* Copyright (C) 1995-2002 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* Huffman code lookup table entry--this entry is four bytes for machines
that have 16-bit pointers (e.g. PC's in the small or medium model). */
#ifndef _INFTREES_H
#define _INFTREES_H
typedef struct inflate_huft_s FAR inflate_huft;
struct inflate_huft_s {
union {
struct {
Byte Exop; /* number of extra bits or operation */
Byte Bits; /* number of bits in this code or subcode */
} what;
uInt pad; /* pad structure to a power of 2 (4 bytes for */
} word; /* 16-bit, 8 bytes for 32-bit int's) */
uInt base; /* literal, length base, distance base,
or table offset */
};
/* Maximum size of dynamic tree. The maximum found in a long but non-
exhaustive search was 1004 huft structures (850 for length/literals
and 154 for distances, the latter actually the result of an
exhaustive search). The actual maximum is not known, but the
value below is more than safe. */
#define MANY 1440
extern int inflate_trees_bits OF((
uIntf *, /* 19 code lengths */
uIntf *, /* bits tree desired/actual depth */
inflate_huft * FAR *, /* bits tree result */
inflate_huft *, /* space for trees */
z_streamp)); /* for messages */
extern int inflate_trees_dynamic OF((
uInt, /* number of literal/length codes */
uInt, /* number of distance codes */
uIntf *, /* that many (total) code lengths */
uIntf *, /* literal desired/actual bit depth */
uIntf *, /* distance desired/actual bit depth */
inflate_huft * FAR *, /* literal/length tree result */
inflate_huft * FAR *, /* distance tree result */
inflate_huft *, /* space for trees */
z_streamp)); /* for messages */
extern int inflate_trees_fixed OF((
uIntf *, /* literal desired/actual bit depth */
uIntf *, /* distance desired/actual bit depth */
inflate_huft * FAR *, /* literal/length tree result */
inflate_huft * FAR *, /* distance tree result */
z_streamp)); /* for memory allocation */
#endif /* _INFTREES_H */
+87
View File
@@ -0,0 +1,87 @@
/* inflate_util.c -- data and routines common to blocks and codes
* Copyright (C) 1995-2002 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include <zlib/zutil.h>
#include "infblock.h"
#include "inftrees.h"
#include "infcodes.h"
#include "infutil.h"
struct inflate_codes_state {int dummy;}; /* for buggy compilers */
/* And'ing with mask[n] masks the lower n bits */
uInt inflate_mask[17] = {
0x0000,
0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
};
/* copy as much as possible from the sliding window to the output area */
int inflate_flush(s, z, r)
inflate_blocks_statef *s;
z_streamp z;
int r;
{
uInt n;
Bytef *p;
Bytef *q;
/* local copies of source and destination pointers */
p = z->next_out;
q = s->read;
/* compute number of bytes to copy as far as end of window */
n = (uInt)((q <= s->write ? s->write : s->end) - q);
if (n > z->avail_out) n = z->avail_out;
if (n && r == Z_BUF_ERROR) r = Z_OK;
/* update counters */
z->avail_out -= n;
z->total_out += n;
/* update check information */
if (s->checkfn != Z_NULL)
z->adler = s->check = (*s->checkfn)(s->check, q, n);
/* copy as far as end of window */
zmemcpy(p, q, n);
p += n;
q += n;
/* see if more to copy at beginning of window */
if (q == s->end)
{
/* wrap pointers */
q = s->window;
if (s->write == s->end)
s->write = s->window;
/* compute bytes to copy */
n = (uInt)(s->write - q);
if (n > z->avail_out) n = z->avail_out;
if (n && r == Z_BUF_ERROR) r = Z_OK;
/* update counters */
z->avail_out -= n;
z->total_out += n;
/* update check information */
if (s->checkfn != Z_NULL)
z->adler = s->check = (*s->checkfn)(s->check, q, n);
/* copy */
zmemcpy(p, q, n);
p += n;
q += n;
}
/* update pointers */
z->next_out = p;
s->read = q;
/* done */
return r;
}
+98
View File
@@ -0,0 +1,98 @@
/* infutil.h -- types and macros common to blocks and codes
* Copyright (C) 1995-2002 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
#ifndef _INFUTIL_H
#define _INFUTIL_H
typedef enum {
TYPE, /* get type bits (3, including end bit) */
LENS, /* get lengths for stored */
STORED, /* processing stored block */
TABLE, /* get table lengths */
BTREE, /* get bit lengths tree for a dynamic block */
DTREE, /* get length, distance trees for a dynamic block */
CODES, /* processing fixed or dynamic block */
DRY, /* output remaining window bytes */
DONE, /* finished last block, done */
BAD} /* got a data error--stuck here */
inflate_block_mode;
/* inflate blocks semi-private state */
struct inflate_blocks_state {
/* mode */
inflate_block_mode mode; /* current inflate_block mode */
/* mode dependent information */
union {
uInt left; /* if STORED, bytes left to copy */
struct {
uInt table; /* table lengths (14 bits) */
uInt index; /* index into blens (or border) */
uIntf *blens; /* bit lengths of codes */
uInt bb; /* bit length tree depth */
inflate_huft *tb; /* bit length decoding tree */
} trees; /* if DTREE, decoding info for trees */
struct {
inflate_codes_statef
*codes;
} decode; /* if CODES, current state */
} sub; /* submode */
uInt last; /* true if this block is the last block */
/* mode independent information */
uInt bitk; /* bits in bit buffer */
uLong bitb; /* bit buffer */
inflate_huft *hufts; /* single malloc for tree space */
Bytef *window; /* sliding window */
Bytef *end; /* one byte after sliding window */
Bytef *read; /* window read pointer */
Bytef *write; /* window write pointer */
check_func checkfn; /* check function */
uLong check; /* check on output */
};
/* defines for inflate input/output */
/* update pointers and return */
#define UPDBITS {s->bitb=b;s->bitk=k;}
#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
#define UPDOUT {s->write=q;}
#define UPDATE {UPDBITS UPDIN UPDOUT}
#define LEAVE {UPDATE return inflate_flush(s,z,r);}
/* get bytes and bits */
#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
#define NEXTBYTE (n--,*p++)
#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
#define DUMPBITS(j) {b>>=(j);k-=(j);}
/* output bytes */
#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
/* load local pointers */
#define LOAD {LOADIN LOADOUT}
/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
extern uInt inflate_mask[17];
/* copy as much as possible from the sliding window to the output area */
extern int inflate_flush OF((
inflate_blocks_statef *,
z_streamp ,
int));
struct internal_state {int dummy;}; /* for buggy compilers */
#endif /* _INFUTIL_H */
+357
View File
@@ -0,0 +1,357 @@
/* match.s -- Pentium-optimized version of longest_match()
* Written for zlib 1.1.2
* Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License.
*/
#ifndef NO_UNDERLINE
#define match_init _ipcomp_match_init
#define longest_match _ipcomp_longest_match
#else
#define match_init ipcomp_match_init
#define longest_match ipcomp_longest_match
#endif
#define MAX_MATCH (258)
#define MIN_MATCH (3)
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7)
/* stack frame offsets */
#define wmask 0 /* local copy of s->wmask */
#define window 4 /* local copy of s->window */
#define windowbestlen 8 /* s->window + bestlen */
#define chainlenscanend 12 /* high word: current chain len */
/* low word: last bytes sought */
#define scanstart 16 /* first two bytes of string */
#define scanalign 20 /* dword-misalignment of string */
#define nicematch 24 /* a good enough match size */
#define bestlen 28 /* size of best match so far */
#define scan 32 /* ptr to string wanting match */
#define LocalVarsSize (36)
/* saved ebx 36 */
/* saved edi 40 */
/* saved esi 44 */
/* saved ebp 48 */
/* return address 52 */
#define deflatestate 56 /* the function arguments */
#define curmatch 60
/* Offsets for fields in the deflate_state structure. These numbers
* are calculated from the definition of deflate_state, with the
* assumption that the compiler will dword-align the fields. (Thus,
* changing the definition of deflate_state could easily cause this
* program to crash horribly, without so much as a warning at
* compile time. Sigh.)
*/
#define dsWSize 36
#define dsWMask 44
#define dsWindow 48
#define dsPrev 56
#define dsMatchLen 88
#define dsPrevMatch 92
#define dsStrStart 100
#define dsMatchStart 104
#define dsLookahead 108
#define dsPrevLen 112
#define dsMaxChainLen 116
#define dsGoodMatch 132
#define dsNiceMatch 136
.file "match.S"
.globl match_init, longest_match
.text
/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
longest_match:
/* Save registers that the compiler may be using, and adjust %esp to */
/* make room for our stack frame. */
pushl %ebp
pushl %edi
pushl %esi
pushl %ebx
subl $LocalVarsSize, %esp
/* Retrieve the function arguments. %ecx will hold cur_match */
/* throughout the entire function. %edx will hold the pointer to the */
/* deflate_state structure during the function's setup (before */
/* entering the main loop). */
movl deflatestate(%esp), %edx
movl curmatch(%esp), %ecx
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */
movl dsNiceMatch(%edx), %eax
movl dsLookahead(%edx), %ebx
cmpl %eax, %ebx
jl LookaheadLess
movl %eax, %ebx
LookaheadLess: movl %ebx, nicematch(%esp)
/* register Bytef *scan = s->window + s->strstart; */
movl dsWindow(%edx), %esi
movl %esi, window(%esp)
movl dsStrStart(%edx), %ebp
lea (%esi,%ebp), %edi
movl %edi, scan(%esp)
/* Determine how many bytes the scan ptr is off from being */
/* dword-aligned. */
movl %edi, %eax
negl %eax
andl $3, %eax
movl %eax, scanalign(%esp)
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
movl dsWSize(%edx), %eax
subl $MIN_LOOKAHEAD, %eax
subl %eax, %ebp
jg LimitPositive
xorl %ebp, %ebp
LimitPositive:
/* unsigned chain_length = s->max_chain_length; */
/* if (s->prev_length >= s->good_match) { */
/* chain_length >>= 2; */
/* } */
movl dsPrevLen(%edx), %eax
movl dsGoodMatch(%edx), %ebx
cmpl %ebx, %eax
movl dsMaxChainLen(%edx), %ebx
jl LastMatchGood
shrl $2, %ebx
LastMatchGood:
/* chainlen is decremented once beforehand so that the function can */
/* use the sign flag instead of the zero flag for the exit test. */
/* It is then shifted into the high word, to make room for the scanend */
/* scanend value, which it will always accompany. */
decl %ebx
shll $16, %ebx
/* int best_len = s->prev_length; */
movl dsPrevLen(%edx), %eax
movl %eax, bestlen(%esp)
/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
addl %eax, %esi
movl %esi, windowbestlen(%esp)
/* register ush scan_start = *(ushf*)scan; */
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
movw (%edi), %bx
movw %bx, scanstart(%esp)
movw -1(%edi,%eax), %bx
movl %ebx, chainlenscanend(%esp)
/* Posf *prev = s->prev; */
/* uInt wmask = s->w_mask; */
movl dsPrev(%edx), %edi
movl dsWMask(%edx), %edx
mov %edx, wmask(%esp)
/* Jump into the main loop. */
jmp LoopEntry
.balign 16
/* do {
* match = s->window + cur_match;
* if (*(ushf*)(match+best_len-1) != scan_end ||
* *(ushf*)match != scan_start) continue;
* [...]
* } while ((cur_match = prev[cur_match & wmask]) > limit
* && --chain_length != 0);
*
* Here is the inner loop of the function. The function will spend the
* majority of its time in this loop, and majority of that time will
* be spent in the first ten instructions.
*
* Within this loop:
* %ebx = chainlenscanend - i.e., ((chainlen << 16) | scanend)
* %ecx = curmatch
* %edx = curmatch & wmask
* %esi = windowbestlen - i.e., (window + bestlen)
* %edi = prev
* %ebp = limit
*
* Two optimization notes on the choice of instructions:
*
* The first instruction uses a 16-bit address, which costs an extra,
* unpairable cycle. This is cheaper than doing a 32-bit access and
* zeroing the high word, due to the 3-cycle misalignment penalty which
* would occur half the time. This also turns out to be cheaper than
* doing two separate 8-bit accesses, as the memory is so rarely in the
* L1 cache.
*
* The window buffer, however, apparently spends a lot of time in the
* cache, and so it is faster to retrieve the word at the end of the
* match string with two 8-bit loads. The instructions that test the
* word at the beginning of the match string, however, are executed
* much less frequently, and there it was cheaper to use 16-bit
* instructions, which avoided the necessity of saving off and
* subsequently reloading one of the other registers.
*/
LookupLoop:
/* 1 U & V */
movw (%edi,%edx,2), %cx /* 2 U pipe */
movl wmask(%esp), %edx /* 2 V pipe */
cmpl %ebp, %ecx /* 3 U pipe */
jbe LeaveNow /* 3 V pipe */
subl $0x00010000, %ebx /* 4 U pipe */
js LeaveNow /* 4 V pipe */
LoopEntry: movb -1(%esi,%ecx), %al /* 5 U pipe */
andl %ecx, %edx /* 5 V pipe */
cmpb %bl, %al /* 6 U pipe */
jnz LookupLoop /* 6 V pipe */
movb (%esi,%ecx), %ah
cmpb %bh, %ah
jnz LookupLoop
movl window(%esp), %eax
movw (%eax,%ecx), %ax
cmpw scanstart(%esp), %ax
jnz LookupLoop
/* Store the current value of chainlen. */
movl %ebx, chainlenscanend(%esp)
/* Point %edi to the string under scrutiny, and %esi to the string we */
/* are hoping to match it up with. In actuality, %esi and %edi are */
/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */
/* initialized to -(MAX_MATCH_8 - scanalign). */
movl window(%esp), %esi
movl scan(%esp), %edi
addl %ecx, %esi
movl scanalign(%esp), %eax
movl $(-MAX_MATCH_8), %edx
lea MAX_MATCH_8(%edi,%eax), %edi
lea MAX_MATCH_8(%esi,%eax), %esi
/* Test the strings for equality, 8 bytes at a time. At the end,
* adjust %edx so that it is offset to the exact byte that mismatched.
*
* We already know at this point that the first three bytes of the
* strings match each other, and they can be safely passed over before
* starting the compare loop. So what this code does is skip over 0-3
* bytes, as much as necessary in order to dword-align the %edi
* pointer. (%esi will still be misaligned three times out of four.)
*
* It should be confessed that this loop usually does not represent
* much of the total running time. Replacing it with a more
* straightforward "rep cmpsb" would not drastically degrade
* performance.
*/
LoopCmps:
movl (%esi,%edx), %eax
movl (%edi,%edx), %ebx
xorl %ebx, %eax
jnz LeaveLoopCmps
movl 4(%esi,%edx), %eax
movl 4(%edi,%edx), %ebx
xorl %ebx, %eax
jnz LeaveLoopCmps4
addl $8, %edx
jnz LoopCmps
jmp LenMaximum
LeaveLoopCmps4: addl $4, %edx
LeaveLoopCmps: testl $0x0000FFFF, %eax
jnz LenLower
addl $2, %edx
shrl $16, %eax
LenLower: subb $1, %al
adcl $0, %edx
/* Calculate the length of the match. If it is longer than MAX_MATCH, */
/* then automatically accept it as the best possible match and leave. */
lea (%edi,%edx), %eax
movl scan(%esp), %edi
subl %edi, %eax
cmpl $MAX_MATCH, %eax
jge LenMaximum
/* If the length of the match is not longer than the best match we */
/* have so far, then forget it and return to the lookup loop. */
movl deflatestate(%esp), %edx
movl bestlen(%esp), %ebx
cmpl %ebx, %eax
jg LongerMatch
movl chainlenscanend(%esp), %ebx
movl windowbestlen(%esp), %esi
movl dsPrev(%edx), %edi
movl wmask(%esp), %edx
andl %ecx, %edx
jmp LookupLoop
/* s->match_start = cur_match; */
/* best_len = len; */
/* if (len >= nice_match) break; */
/* scan_end = *(ushf*)(scan+best_len-1); */
LongerMatch: movl nicematch(%esp), %ebx
movl %eax, bestlen(%esp)
movl %ecx, dsMatchStart(%edx)
cmpl %ebx, %eax
jge LeaveNow
movl window(%esp), %esi
addl %eax, %esi
movl %esi, windowbestlen(%esp)
movl chainlenscanend(%esp), %ebx
movw -1(%edi,%eax), %bx
movl dsPrev(%edx), %edi
movl %ebx, chainlenscanend(%esp)
movl wmask(%esp), %edx
andl %ecx, %edx
jmp LookupLoop
/* Accept the current string, with the maximum possible length. */
LenMaximum: movl deflatestate(%esp), %edx
movl $MAX_MATCH, bestlen(%esp)
movl %ecx, dsMatchStart(%edx)
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
/* return s->lookahead; */
LeaveNow:
movl deflatestate(%esp), %edx
movl bestlen(%esp), %ebx
movl dsLookahead(%edx), %eax
cmpl %eax, %ebx
jg LookaheadRet
movl %ebx, %eax
LookaheadRet:
/* Restore the stack and return from whence we came. */
addl $LocalVarsSize, %esp
popl %ebx
popl %esi
popl %edi
popl %ebp
match_init: ret
+330
View File
@@ -0,0 +1,330 @@
/* match.s -- Pentium-Pro-optimized version of longest_match()
* Written for zlib 1.1.2
* Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License.
*/
#ifndef NO_UNDERLINE
#define match_init _ipcomp_match_init
#define longest_match _ipcomp_longest_match
#else
#define match_init ipcomp_match_init
#define longest_match ipcomp_longest_match
#endif
#define MAX_MATCH (258)
#define MIN_MATCH (3)
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7)
/* stack frame offsets */
#define chainlenwmask 0 /* high word: current chain len */
/* low word: s->wmask */
#define window 4 /* local copy of s->window */
#define windowbestlen 8 /* s->window + bestlen */
#define scanstart 16 /* first two bytes of string */
#define scanend 12 /* last two bytes of string */
#define scanalign 20 /* dword-misalignment of string */
#define nicematch 24 /* a good enough match size */
#define bestlen 28 /* size of best match so far */
#define scan 32 /* ptr to string wanting match */
#define LocalVarsSize (36)
/* saved ebx 36 */
/* saved edi 40 */
/* saved esi 44 */
/* saved ebp 48 */
/* return address 52 */
#define deflatestate 56 /* the function arguments */
#define curmatch 60
/* Offsets for fields in the deflate_state structure. These numbers
* are calculated from the definition of deflate_state, with the
* assumption that the compiler will dword-align the fields. (Thus,
* changing the definition of deflate_state could easily cause this
* program to crash horribly, without so much as a warning at
* compile time. Sigh.)
*/
#define dsWSize 36
#define dsWMask 44
#define dsWindow 48
#define dsPrev 56
#define dsMatchLen 88
#define dsPrevMatch 92
#define dsStrStart 100
#define dsMatchStart 104
#define dsLookahead 108
#define dsPrevLen 112
#define dsMaxChainLen 116
#define dsGoodMatch 132
#define dsNiceMatch 136
.file "match.S"
.globl match_init, longest_match
.text
/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
longest_match:
/* Save registers that the compiler may be using, and adjust %esp to */
/* make room for our stack frame. */
pushl %ebp
pushl %edi
pushl %esi
pushl %ebx
subl $LocalVarsSize, %esp
/* Retrieve the function arguments. %ecx will hold cur_match */
/* throughout the entire function. %edx will hold the pointer to the */
/* deflate_state structure during the function's setup (before */
/* entering the main loop). */
movl deflatestate(%esp), %edx
movl curmatch(%esp), %ecx
/* uInt wmask = s->w_mask; */
/* unsigned chain_length = s->max_chain_length; */
/* if (s->prev_length >= s->good_match) { */
/* chain_length >>= 2; */
/* } */
movl dsPrevLen(%edx), %eax
movl dsGoodMatch(%edx), %ebx
cmpl %ebx, %eax
movl dsWMask(%edx), %eax
movl dsMaxChainLen(%edx), %ebx
jl LastMatchGood
shrl $2, %ebx
LastMatchGood:
/* chainlen is decremented once beforehand so that the function can */
/* use the sign flag instead of the zero flag for the exit test. */
/* It is then shifted into the high word, to make room for the wmask */
/* value, which it will always accompany. */
decl %ebx
shll $16, %ebx
orl %eax, %ebx
movl %ebx, chainlenwmask(%esp)
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */
movl dsNiceMatch(%edx), %eax
movl dsLookahead(%edx), %ebx
cmpl %eax, %ebx
jl LookaheadLess
movl %eax, %ebx
LookaheadLess: movl %ebx, nicematch(%esp)
/* register Bytef *scan = s->window + s->strstart; */
movl dsWindow(%edx), %esi
movl %esi, window(%esp)
movl dsStrStart(%edx), %ebp
lea (%esi,%ebp), %edi
movl %edi, scan(%esp)
/* Determine how many bytes the scan ptr is off from being */
/* dword-aligned. */
movl %edi, %eax
negl %eax
andl $3, %eax
movl %eax, scanalign(%esp)
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
movl dsWSize(%edx), %eax
subl $MIN_LOOKAHEAD, %eax
subl %eax, %ebp
jg LimitPositive
xorl %ebp, %ebp
LimitPositive:
/* int best_len = s->prev_length; */
movl dsPrevLen(%edx), %eax
movl %eax, bestlen(%esp)
/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
addl %eax, %esi
movl %esi, windowbestlen(%esp)
/* register ush scan_start = *(ushf*)scan; */
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
/* Posf *prev = s->prev; */
movzwl (%edi), %ebx
movl %ebx, scanstart(%esp)
movzwl -1(%edi,%eax), %ebx
movl %ebx, scanend(%esp)
movl dsPrev(%edx), %edi
/* Jump into the main loop. */
movl chainlenwmask(%esp), %edx
jmp LoopEntry
.balign 16
/* do {
* match = s->window + cur_match;
* if (*(ushf*)(match+best_len-1) != scan_end ||
* *(ushf*)match != scan_start) continue;
* [...]
* } while ((cur_match = prev[cur_match & wmask]) > limit
* && --chain_length != 0);
*
* Here is the inner loop of the function. The function will spend the
* majority of its time in this loop, and majority of that time will
* be spent in the first ten instructions.
*
* Within this loop:
* %ebx = scanend
* %ecx = curmatch
* %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
* %esi = windowbestlen - i.e., (window + bestlen)
* %edi = prev
* %ebp = limit
*/
LookupLoop:
andl %edx, %ecx
movzwl (%edi,%ecx,2), %ecx
cmpl %ebp, %ecx
jbe LeaveNow
subl $0x00010000, %edx
js LeaveNow
LoopEntry: movzwl -1(%esi,%ecx), %eax
cmpl %ebx, %eax
jnz LookupLoop
movl window(%esp), %eax
movzwl (%eax,%ecx), %eax
cmpl scanstart(%esp), %eax
jnz LookupLoop
/* Store the current value of chainlen. */
movl %edx, chainlenwmask(%esp)
/* Point %edi to the string under scrutiny, and %esi to the string we */
/* are hoping to match it up with. In actuality, %esi and %edi are */
/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */
/* initialized to -(MAX_MATCH_8 - scanalign). */
movl window(%esp), %esi
movl scan(%esp), %edi
addl %ecx, %esi
movl scanalign(%esp), %eax
movl $(-MAX_MATCH_8), %edx
lea MAX_MATCH_8(%edi,%eax), %edi
lea MAX_MATCH_8(%esi,%eax), %esi
/* Test the strings for equality, 8 bytes at a time. At the end,
* adjust %edx so that it is offset to the exact byte that mismatched.
*
* We already know at this point that the first three bytes of the
* strings match each other, and they can be safely passed over before
* starting the compare loop. So what this code does is skip over 0-3
* bytes, as much as necessary in order to dword-align the %edi
* pointer. (%esi will still be misaligned three times out of four.)
*
* It should be confessed that this loop usually does not represent
* much of the total running time. Replacing it with a more
* straightforward "rep cmpsb" would not drastically degrade
* performance.
*/
LoopCmps:
movl (%esi,%edx), %eax
xorl (%edi,%edx), %eax
jnz LeaveLoopCmps
movl 4(%esi,%edx), %eax
xorl 4(%edi,%edx), %eax
jnz LeaveLoopCmps4
addl $8, %edx
jnz LoopCmps
jmp LenMaximum
LeaveLoopCmps4: addl $4, %edx
LeaveLoopCmps: testl $0x0000FFFF, %eax
jnz LenLower
addl $2, %edx
shrl $16, %eax
LenLower: subb $1, %al
adcl $0, %edx
/* Calculate the length of the match. If it is longer than MAX_MATCH, */
/* then automatically accept it as the best possible match and leave. */
lea (%edi,%edx), %eax
movl scan(%esp), %edi
subl %edi, %eax
cmpl $MAX_MATCH, %eax
jge LenMaximum
/* If the length of the match is not longer than the best match we */
/* have so far, then forget it and return to the lookup loop. */
movl deflatestate(%esp), %edx
movl bestlen(%esp), %ebx
cmpl %ebx, %eax
jg LongerMatch
movl windowbestlen(%esp), %esi
movl dsPrev(%edx), %edi
movl scanend(%esp), %ebx
movl chainlenwmask(%esp), %edx
jmp LookupLoop
/* s->match_start = cur_match; */
/* best_len = len; */
/* if (len >= nice_match) break; */
/* scan_end = *(ushf*)(scan+best_len-1); */
LongerMatch: movl nicematch(%esp), %ebx
movl %eax, bestlen(%esp)
movl %ecx, dsMatchStart(%edx)
cmpl %ebx, %eax
jge LeaveNow
movl window(%esp), %esi
addl %eax, %esi
movl %esi, windowbestlen(%esp)
movzwl -1(%edi,%eax), %ebx
movl dsPrev(%edx), %edi
movl %ebx, scanend(%esp)
movl chainlenwmask(%esp), %edx
jmp LookupLoop
/* Accept the current string, with the maximum possible length. */
LenMaximum: movl deflatestate(%esp), %edx
movl $MAX_MATCH, bestlen(%esp)
movl %ecx, dsMatchStart(%edx)
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
/* return s->lookahead; */
LeaveNow:
movl deflatestate(%esp), %edx
movl bestlen(%esp), %ebx
movl dsLookahead(%edx), %eax
cmpl %eax, %ebx
jg LookaheadRet
movl %ebx, %eax
LookaheadRet:
/* Restore the stack and return from whence we came. */
addl $LocalVarsSize, %esp
popl %ebx
popl %esi
popl %edi
popl %ebp
match_init: ret
File diff suppressed because it is too large Load Diff
+128
View File
@@ -0,0 +1,128 @@
/* header created automatically with -DGEN_TREES_H */
local const ct_data static_ltree[L_CODES+2] = {
{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
};
local const ct_data static_dtree[D_CODES] = {
{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
};
const uch _dist_code[DIST_CODE_LEN] = {
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
};
const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
};
local const int base_length[LENGTH_CODES] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
64, 80, 96, 112, 128, 160, 192, 224, 0
};
local const int base_dist[D_CODES] = {
0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
};
+309
View File
@@ -0,0 +1,309 @@
/* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-2002 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id: zconf.h,v 1.1 2004/03/15 20:35:26 as Exp $ */
#ifndef _ZCONF_H
#define _ZCONF_H
/*
* If you *really* need a unique prefix for all types and library functions,
* compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
*/
#ifdef IPCOMP_PREFIX
# define deflateInit_ ipcomp_deflateInit_
# define deflate ipcomp_deflate
# define deflateEnd ipcomp_deflateEnd
# define inflateInit_ ipcomp_inflateInit_
# define inflate ipcomp_inflate
# define inflateEnd ipcomp_inflateEnd
# define deflateInit2_ ipcomp_deflateInit2_
# define deflateSetDictionary ipcomp_deflateSetDictionary
# define deflateCopy ipcomp_deflateCopy
# define deflateReset ipcomp_deflateReset
# define deflateParams ipcomp_deflateParams
# define inflateInit2_ ipcomp_inflateInit2_
# define inflateSetDictionary ipcomp_inflateSetDictionary
# define inflateSync ipcomp_inflateSync
# define inflateSyncPoint ipcomp_inflateSyncPoint
# define inflateReset ipcomp_inflateReset
# define compress ipcomp_compress
# define compress2 ipcomp_compress2
# define uncompress ipcomp_uncompress
# define adler32 ipcomp_adler32
# define crc32 ipcomp_crc32
# define get_crc_table ipcomp_get_crc_table
/* SSS: these also need to be prefixed to avoid clash with ppp_deflate and ext2compression */
# define inflate_blocks ipcomp_deflate_blocks
# define inflate_blocks_free ipcomp_deflate_blocks_free
# define inflate_blocks_new ipcomp_inflate_blocks_new
# define inflate_blocks_reset ipcomp_inflate_blocks_reset
# define inflate_blocks_sync_point ipcomp_inflate_blocks_sync_point
# define inflate_set_dictionary ipcomp_inflate_set_dictionary
# define inflate_codes ipcomp_inflate_codes
# define inflate_codes_free ipcomp_inflate_codes_free
# define inflate_codes_new ipcomp_inflate_codes_new
# define inflate_fast ipcomp_inflate_fast
# define inflate_trees_bits ipcomp_inflate_trees_bits
# define inflate_trees_dynamic ipcomp_inflate_trees_dynamic
# define inflate_trees_fixed ipcomp_inflate_trees_fixed
# define inflate_flush ipcomp_inflate_flush
# define inflate_mask ipcomp_inflate_mask
# define _dist_code _ipcomp_dist_code
# define _length_code _ipcomp_length_code
# define _tr_align _ipcomp_tr_align
# define _tr_flush_block _ipcomp_tr_flush_block
# define _tr_init _ipcomp_tr_init
# define _tr_stored_block _ipcomp_tr_stored_block
# define _tr_tally _ipcomp_tr_tally
# define zError ipcomp_zError
# define z_errmsg ipcomp_z_errmsg
# define zlibVersion ipcomp_zlibVersion
# define match_init ipcomp_match_init
# define longest_match ipcomp_longest_match
#endif
#ifdef Z_PREFIX
# define Byte z_Byte
# define uInt z_uInt
# define uLong z_uLong
# define Bytef z_Bytef
# define charf z_charf
# define intf z_intf
# define uIntf z_uIntf
# define uLongf z_uLongf
# define voidpf z_voidpf
# define voidp z_voidp
#endif
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
# define WIN32
#endif
#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)
# ifndef __32BIT__
# define __32BIT__
# endif
#endif
#if defined(__MSDOS__) && !defined(MSDOS)
# define MSDOS
#endif
/*
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
* than 64k bytes at a time (needed on systems with 16-bit int).
*/
#if defined(MSDOS) && !defined(__32BIT__)
# define MAXSEG_64K
#endif
#ifdef MSDOS
# define UNALIGNED_OK
#endif
#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC)
# define STDC
#endif
#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__)
# ifndef STDC
# define STDC
# endif
#endif
#ifndef STDC
# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
# define const
# endif
#endif
/* Some Mac compilers merge all .h files incorrectly: */
#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__)
# define NO_DUMMY_DECL
#endif
/* Old Borland C incorrectly complains about missing returns: */
#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500)
# define NEED_DUMMY_RETURN
#endif
/* Maximum value for memLevel in deflateInit2 */
#ifndef MAX_MEM_LEVEL
# ifdef MAXSEG_64K
# define MAX_MEM_LEVEL 8
# else
# define MAX_MEM_LEVEL 9
# endif
#endif
/* Maximum value for windowBits in deflateInit2 and inflateInit2.
* WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
* created by gzip. (Files created by minigzip can still be extracted by
* gzip.)
*/
#ifndef MAX_WBITS
# define MAX_WBITS 15 /* 32K LZ77 window */
#endif
/* The memory requirements for deflate are (in bytes):
(1 << (windowBits+2)) + (1 << (memLevel+9))
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
plus a few kilobytes for small objects. For example, if you want to reduce
the default memory requirements from 256K to 128K, compile with
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
Of course this will generally degrade compression (there's no free lunch).
The memory requirements for inflate are (in bytes) 1 << windowBits
that is, 32K for windowBits=15 (default value) plus a few kilobytes
for small objects.
*/
/* Type declarations */
#ifndef OF /* function prototypes */
# ifdef STDC
# define OF(args) args
# else
# define OF(args) ()
# endif
#endif
/* The following definitions for FAR are needed only for MSDOS mixed
* model programming (small or medium model with some far allocations).
* This was tested only with MSC; for other MSDOS compilers you may have
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
* just define FAR to be empty.
*/
#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__)
/* MSC small or medium model */
# define SMALL_MEDIUM
# ifdef _MSC_VER
# define FAR _far
# else
# define FAR far
# endif
#endif
#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__))
# ifndef __32BIT__
# define SMALL_MEDIUM
# define FAR _far
# endif
#endif
/* Compile with -DZLIB_DLL for Windows DLL support */
#if defined(ZLIB_DLL)
# if defined(_WINDOWS) || defined(WINDOWS)
# ifdef FAR
# undef FAR
# endif
# include <windows.h>
# define ZEXPORT WINAPI
# ifdef WIN32
# define ZEXPORTVA WINAPIV
# else
# define ZEXPORTVA FAR _cdecl _export
# endif
# endif
# if defined (__BORLANDC__)
# if (__BORLANDC__ >= 0x0500) && defined (WIN32)
# include <windows.h>
# define ZEXPORT __declspec(dllexport) WINAPI
# define ZEXPORTRVA __declspec(dllexport) WINAPIV
# else
# if defined (_Windows) && defined (__DLL__)
# define ZEXPORT _export
# define ZEXPORTVA _export
# endif
# endif
# endif
#endif
#if defined (__BEOS__)
# if defined (ZLIB_DLL)
# define ZEXTERN extern __declspec(dllexport)
# else
# define ZEXTERN extern __declspec(dllimport)
# endif
#endif
#ifndef ZEXPORT
# define ZEXPORT
#endif
#ifndef ZEXPORTVA
# define ZEXPORTVA
#endif
#ifndef ZEXTERN
# define ZEXTERN extern
#endif
#ifndef FAR
# define FAR
#endif
#if !defined(MACOS) && !defined(TARGET_OS_MAC)
typedef unsigned char Byte; /* 8 bits */
#endif
typedef unsigned int uInt; /* 16 bits or more */
typedef unsigned long uLong; /* 32 bits or more */
#ifdef SMALL_MEDIUM
/* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
# define Bytef Byte FAR
#else
typedef Byte FAR Bytef;
#endif
typedef char FAR charf;
typedef int FAR intf;
typedef uInt FAR uIntf;
typedef uLong FAR uLongf;
#ifdef STDC
typedef void FAR *voidpf;
typedef void *voidp;
#else
typedef Byte FAR *voidpf;
typedef Byte *voidp;
#endif
#ifdef HAVE_UNISTD_H
# include <sys/types.h> /* for off_t */
# include <unistd.h> /* for SEEK_* and off_t */
# define z_off_t off_t
#endif
#ifndef SEEK_SET
# define SEEK_SET 0 /* Seek from beginning of file. */
# define SEEK_CUR 1 /* Seek from current position. */
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
#endif
#ifndef z_off_t
# define z_off_t long
#endif
/* MVS linker does not support external names larger than 8 bytes */
#if defined(__MVS__)
# pragma map(deflateInit_,"DEIN")
# pragma map(deflateInit2_,"DEIN2")
# pragma map(deflateEnd,"DEEND")
# pragma map(inflateInit_,"ININ")
# pragma map(inflateInit2_,"ININ2")
# pragma map(inflateEnd,"INEND")
# pragma map(inflateSync,"INSY")
# pragma map(inflateSetDictionary,"INSEDI")
# pragma map(inflate_blocks,"INBL")
# pragma map(inflate_blocks_new,"INBLNE")
# pragma map(inflate_blocks_free,"INBLFR")
# pragma map(inflate_blocks_reset,"INBLRE")
# pragma map(inflate_codes_free,"INCOFR")
# pragma map(inflate_codes,"INCO")
# pragma map(inflate_fast,"INFA")
# pragma map(inflate_flush,"INFLU")
# pragma map(inflate_mask,"INMA")
# pragma map(inflate_set_dictionary,"INSEDI2")
# pragma map(ipcomp_inflate_copyright,"INCOPY")
# pragma map(inflate_trees_bits,"INTRBI")
# pragma map(inflate_trees_dynamic,"INTRDY")
# pragma map(inflate_trees_fixed,"INTRFI")
# pragma map(inflate_trees_free,"INTRFR")
#endif
#endif /* _ZCONF_H */
+227
View File
@@ -0,0 +1,227 @@
/* zutil.c -- target dependent utility functions for the compression library
* Copyright (C) 1995-2002 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id: zutil.c,v 1.1 2004/03/15 20:35:26 as Exp $ */
#include <zlib/zutil.h>
#define MY_ZCALLOC
struct internal_state {int dummy;}; /* for buggy compilers */
#ifndef STDC
extern void exit OF((int));
#endif
const char *z_errmsg[10] = {
"need dictionary", /* Z_NEED_DICT 2 */
"stream end", /* Z_STREAM_END 1 */
"", /* Z_OK 0 */
"file error", /* Z_ERRNO (-1) */
"stream error", /* Z_STREAM_ERROR (-2) */
"data error", /* Z_DATA_ERROR (-3) */
"insufficient memory", /* Z_MEM_ERROR (-4) */
"buffer error", /* Z_BUF_ERROR (-5) */
"incompatible version",/* Z_VERSION_ERROR (-6) */
""};
const char * ZEXPORT zlibVersion()
{
return ZLIB_VERSION;
}
#ifdef DEBUG
# ifndef verbose
# define verbose 0
# endif
int z_verbose = verbose;
void z_error (m)
char *m;
{
fprintf(stderr, "%s\n", m);
exit(1);
}
#endif
/* exported to allow conversion of error code to string for compress() and
* uncompress()
*/
const char * ZEXPORT zError(err)
int err;
{
return ERR_MSG(err);
}
#ifndef HAVE_MEMCPY
void zmemcpy(dest, source, len)
Bytef* dest;
const Bytef* source;
uInt len;
{
if (len == 0) return;
do {
*dest++ = *source++; /* ??? to be unrolled */
} while (--len != 0);
}
int zmemcmp(s1, s2, len)
const Bytef* s1;
const Bytef* s2;
uInt len;
{
uInt j;
for (j = 0; j < len; j++) {
if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
}
return 0;
}
void zmemzero(dest, len)
Bytef* dest;
uInt len;
{
if (len == 0) return;
do {
*dest++ = 0; /* ??? to be unrolled */
} while (--len != 0);
}
#endif
#ifdef __TURBOC__
#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__)
/* Small and medium model in Turbo C are for now limited to near allocation
* with reduced MAX_WBITS and MAX_MEM_LEVEL
*/
# define MY_ZCALLOC
/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
* and farmalloc(64K) returns a pointer with an offset of 8, so we
* must fix the pointer. Warning: the pointer must be put back to its
* original form in order to free it, use zcfree().
*/
#define MAX_PTR 10
/* 10*64K = 640K */
local int next_ptr = 0;
typedef struct ptr_table_s {
voidpf org_ptr;
voidpf new_ptr;
} ptr_table;
local ptr_table table[MAX_PTR];
/* This table is used to remember the original form of pointers
* to large buffers (64K). Such pointers are normalized with a zero offset.
* Since MSDOS is not a preemptive multitasking OS, this table is not
* protected from concurrent access. This hack doesn't work anyway on
* a protected system like OS/2. Use Microsoft C instead.
*/
voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
{
voidpf buf = opaque; /* just to make some compilers happy */
ulg bsize = (ulg)items*size;
/* If we allocate less than 65520 bytes, we assume that farmalloc
* will return a usable pointer which doesn't have to be normalized.
*/
if (bsize < 65520L) {
buf = farmalloc(bsize);
if (*(ush*)&buf != 0) return buf;
} else {
buf = farmalloc(bsize + 16L);
}
if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
table[next_ptr].org_ptr = buf;
/* Normalize the pointer to seg:0 */
*((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
*(ush*)&buf = 0;
table[next_ptr++].new_ptr = buf;
return buf;
}
void zcfree (voidpf opaque, voidpf ptr)
{
int n;
if (*(ush*)&ptr != 0) { /* object < 64K */
farfree(ptr);
return;
}
/* Find the original pointer */
for (n = 0; n < next_ptr; n++) {
if (ptr != table[n].new_ptr) continue;
farfree(table[n].org_ptr);
while (++n < next_ptr) {
table[n-1] = table[n];
}
next_ptr--;
return;
}
ptr = opaque; /* just to make some compilers happy */
Assert(0, "zcfree: ptr not found");
}
#endif
#endif /* __TURBOC__ */
#if defined(M_I86) && !defined(__32BIT__)
/* Microsoft C in 16-bit mode */
# define MY_ZCALLOC
#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
# define _halloc halloc
# define _hfree hfree
#endif
voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
{
if (opaque) opaque = 0; /* to make compiler happy */
return _halloc((long)items, size);
}
void zcfree (voidpf opaque, voidpf ptr)
{
if (opaque) opaque = 0; /* to make compiler happy */
_hfree(ptr);
}
#endif /* MSC */
#ifndef MY_ZCALLOC /* Any system without a special alloc function */
#ifndef STDC
extern voidp calloc OF((uInt items, uInt size));
extern void free OF((voidpf ptr));
#endif
voidpf zcalloc (opaque, items, size)
voidpf opaque;
unsigned items;
unsigned size;
{
if (opaque) items += size - size; /* make compiler happy */
return (voidpf)calloc(items, size);
}
void zcfree (opaque, ptr)
voidpf opaque;
voidpf ptr;
{
free(ptr);
if (opaque) return; /* make compiler happy */
}
#endif /* MY_ZCALLOC */