summaryrefslogtreecommitdiff
path: root/usr/src/lib/libwrap/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libwrap/misc.c')
-rw-r--r--usr/src/lib/libwrap/misc.c200
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 */