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