diff options
Diffstat (limited to 'usr/src/lib/libwrap/misc.c')
-rw-r--r-- | usr/src/lib/libwrap/misc.c | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/usr/src/lib/libwrap/misc.c b/usr/src/lib/libwrap/misc.c new file mode 100644 index 0000000000..dbc3a7cca1 --- /dev/null +++ b/usr/src/lib/libwrap/misc.c @@ -0,0 +1,200 @@ +/* + * Copyright 2001 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +#pragma ident "%Z%%M% %I% %E% SMI" + + /* + * Misc routines that are used by tcpd and by tcpdchk. + * + * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. + */ + +#ifndef lint +static char sccsic[] = "@(#) misc.c 1.2 96/02/11 17:01:29"; +#endif + +#include <sys/types.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <netdb.h> + +#include "tcpd.h" + +extern char *fgets(); + +#ifndef INADDR_NONE +#define INADDR_NONE (-1) /* XXX should be 0xffffffff */ +#endif + +/* xgets - fgets() with backslash-newline stripping */ + +char *xgets(ptr, len, fp) +char *ptr; +int len; +FILE *fp; +{ + int got; + char *start = ptr; + + while (fgets(ptr, len, fp)) { + got = strlen(ptr); + if (got >= 1 && ptr[got - 1] == '\n') { + tcpd_context.line++; + if (got >= 2 && ptr[got - 2] == '\\') { + got -= 2; + } else { + return (start); + } + } + ptr += got; + len -= got; + ptr[0] = 0; + } + return (ptr > start ? start : 0); +} + +/* split_at - break string at delimiter or return NULL */ + +char *split_at(string, delimiter) +char *string; +int delimiter; +{ + char *cp; + + if ((cp = strchr(string, delimiter)) != 0) + *cp++ = 0; + return (cp); +} + +/* dot_quad_addr - convert dotted quad to internal form */ + +unsigned long dot_quad_addr(str) +char *str; +{ + int in_run = 0; + int runs = 0; + char *cp = str; + + /* Count the number of runs of non-dot characters. */ + + while (*cp) { + if (*cp == '.') { + in_run = 0; + } else if (in_run == 0) { + in_run = 1; + runs++; + } + cp++; + } + return (runs == 4 ? inet_addr(str) : INADDR_NONE); +} + +/* numeric_addr - convert textual IP address to binary form */ + +int numeric_addr(str, addr, af, len) +char *str; +union gen_addr *addr; +int *af; +int *len; +{ + union gen_addr t; + + if (addr == NULL) + addr = &t; +#ifdef HAVE_IPV6 + if (strchr(str,':')) { + if (af) *af = AF_INET6; + if (len) *len = sizeof(struct in6_addr); + if (inet_pton(AF_INET6, str, (void*) addr) == 1) + return 0; + return -1; + } +#endif + if (af) *af = AF_INET; + if (len) *len = sizeof(struct in_addr); + addr->ga_in.s_addr = dot_quad_addr(str); + return addr->ga_in.s_addr == INADDR_NONE ? -1 : 0; +} + +/* For none RFC 2553 compliant systems */ +#ifdef USE_GETHOSTBYNAME2 +#define getipnodebyname(h,af,flags,err) gethostbyname2(h,af) +#define freehostent(x) x = 0 +#endif + +/* tcpd_gethostbyname - an IP family neutral gethostbyname */ + +struct hostent *tcpd_gethostbyname(host, af) +char *host; +int af; +{ +#ifdef HAVE_IPV6 + struct hostent *hp; + static struct hostent *hs; /* freehostent() on next call */ + int err; + + if (af == AF_INET6) { /* must be AF_INET6 */ + if (hs) + freehostent(hs); + return (hs = getipnodebyname(host, AF_INET6, 0, &err)); + } + hp = gethostbyname(host); + if (hp != NULL || af == AF_INET) { /* found or must be AF_INET */ + return hp; + } else { /* Try INET6 */ + if (hs) + freehostent(hs); + return (hs = getipnodebyname(host, AF_INET6, 0, &err)); + } +#else + return gethostbyname(host); +#endif +} + +#ifdef HAVE_IPV6 +/* + * When using IPv6 addresses, we'll be seeing lots of ":"s; + * we require the addresses to be specified as [address]. + * An IPv6 address can be specified in 3 ways: + * + * x:x:x:x:x:x:x:x (fully specified) + * x::x:x:x:x (zeroes squashed) + * ::FFFF:1.2.3.4 (IPv4 mapped) + * + * These need to be skipped to get at the ":" delimeters. + * + * We also allow a '/prefix' specifier. + */ +char *skip_ipv6_addrs(str) +char *str; +{ + char *obr, *cbr, *colon; + char *p = str; + char *q; + + while (1) { + if ((colon = strchr(p, ':')) == NULL) + return p; + if ((obr = strchr(p, '[')) == NULL || obr > colon) + return p; + if ((cbr = strchr(obr, ']')) == NULL) + return p; + + for (q = obr + 1; q < cbr; q++) { + /* + * Quick and dirty parse, cheaper than inet_pton + * Could count colons and dots (must be 0 or 3 dots, no + * colons after dots seens, only one double :, etc, etc) + */ + if (*q != ':' && *q != '.' && *q != '/' && !isxdigit(*q & 0xff)) + return p; + } + p = cbr + 1; + } +} +#endif /* HAVE_IPV6 */ |