Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / lib / libwrap / misc.c
blob37f1181b4c329d5d2c5cbb5e553f045718637134
1 /*
2 * Copyright 2001 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5 #pragma ident "%Z%%M% %I% %E% SMI"
7 /*
8 * Misc routines that are used by tcpd and by tcpdchk.
9 *
10 * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
13 static char sccsic[] = "@(#) misc.c 1.2 96/02/11 17:01:29";
15 #include <sys/types.h>
16 #include <sys/param.h>
17 #include <netinet/in.h>
18 #include <arpa/inet.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <ctype.h>
22 #include <netdb.h>
24 #include "tcpd.h"
26 extern char *fgets();
28 #ifndef INADDR_NONE
29 #define INADDR_NONE (-1) /* XXX should be 0xffffffff */
30 #endif
32 /* xgets - fgets() with backslash-newline stripping */
34 char *xgets(ptr, len, fp)
35 char *ptr;
36 int len;
37 FILE *fp;
39 int got;
40 char *start = ptr;
42 while (fgets(ptr, len, fp)) {
43 got = strlen(ptr);
44 if (got >= 1 && ptr[got - 1] == '\n') {
45 tcpd_context.line++;
46 if (got >= 2 && ptr[got - 2] == '\\') {
47 got -= 2;
48 } else {
49 return (start);
52 ptr += got;
53 len -= got;
54 ptr[0] = 0;
56 return (ptr > start ? start : 0);
59 /* split_at - break string at delimiter or return NULL */
61 char *split_at(string, delimiter)
62 char *string;
63 int delimiter;
65 char *cp;
67 if ((cp = strchr(string, delimiter)) != 0)
68 *cp++ = 0;
69 return (cp);
72 /* dot_quad_addr - convert dotted quad to internal form */
74 unsigned long dot_quad_addr(str)
75 char *str;
77 int in_run = 0;
78 int runs = 0;
79 char *cp = str;
81 /* Count the number of runs of non-dot characters. */
83 while (*cp) {
84 if (*cp == '.') {
85 in_run = 0;
86 } else if (in_run == 0) {
87 in_run = 1;
88 runs++;
90 cp++;
92 return (runs == 4 ? inet_addr(str) : INADDR_NONE);
95 /* numeric_addr - convert textual IP address to binary form */
97 int numeric_addr(str, addr, af, len)
98 char *str;
99 union gen_addr *addr;
100 int *af;
101 int *len;
103 union gen_addr t;
105 if (addr == NULL)
106 addr = &t;
107 #ifdef HAVE_IPV6
108 if (strchr(str,':')) {
109 if (af) *af = AF_INET6;
110 if (len) *len = sizeof(struct in6_addr);
111 if (inet_pton(AF_INET6, str, (void*) addr) == 1)
112 return 0;
113 return -1;
115 #endif
116 if (af) *af = AF_INET;
117 if (len) *len = sizeof(struct in_addr);
118 addr->ga_in.s_addr = dot_quad_addr(str);
119 return addr->ga_in.s_addr == INADDR_NONE ? -1 : 0;
122 /* For none RFC 2553 compliant systems */
123 #ifdef USE_GETHOSTBYNAME2
124 #define getipnodebyname(h,af,flags,err) gethostbyname2(h,af)
125 #define freehostent(x) x = 0
126 #endif
128 /* tcpd_gethostbyname - an IP family neutral gethostbyname */
130 struct hostent *tcpd_gethostbyname(host, af)
131 char *host;
132 int af;
134 #ifdef HAVE_IPV6
135 struct hostent *hp;
136 static struct hostent *hs; /* freehostent() on next call */
137 int err;
139 if (af == AF_INET6) { /* must be AF_INET6 */
140 if (hs)
141 freehostent(hs);
142 return (hs = getipnodebyname(host, AF_INET6, 0, &err));
144 hp = gethostbyname(host);
145 if (hp != NULL || af == AF_INET) { /* found or must be AF_INET */
146 return hp;
147 } else { /* Try INET6 */
148 if (hs)
149 freehostent(hs);
150 return (hs = getipnodebyname(host, AF_INET6, 0, &err));
152 #else
153 return gethostbyname(host);
154 #endif
157 #ifdef HAVE_IPV6
159 * When using IPv6 addresses, we'll be seeing lots of ":"s;
160 * we require the addresses to be specified as [address].
161 * An IPv6 address can be specified in 3 ways:
163 * x:x:x:x:x:x:x:x (fully specified)
164 * x::x:x:x:x (zeroes squashed)
165 * ::FFFF:1.2.3.4 (IPv4 mapped)
167 * These need to be skipped to get at the ":" delimeters.
169 * We also allow a '/prefix' specifier.
171 char *skip_ipv6_addrs(str)
172 char *str;
174 char *obr, *cbr, *colon;
175 char *p = str;
176 char *q;
178 while (1) {
179 if ((colon = strchr(p, ':')) == NULL)
180 return p;
181 if ((obr = strchr(p, '[')) == NULL || obr > colon)
182 return p;
183 if ((cbr = strchr(obr, ']')) == NULL)
184 return p;
186 for (q = obr + 1; q < cbr; q++) {
188 * Quick and dirty parse, cheaper than inet_pton
189 * Could count colons and dots (must be 0 or 3 dots, no
190 * colons after dots seens, only one double :, etc, etc)
192 if (*q != ':' && *q != '.' && *q != '/' && !isxdigit(*q & 0xff))
193 return p;
195 p = cbr + 1;
198 #endif /* HAVE_IPV6 */