2 * Copyright 2001 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
5 #pragma ident "%Z%%M% %I% %E% SMI"
8 * Misc routines that are used by tcpd and by tcpdchk.
10 * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
14 static char sccsic
[] = "@(#) misc.c 1.2 96/02/11 17:01:29";
17 #include <sys/types.h>
18 #include <sys/param.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
31 #define INADDR_NONE (-1) /* XXX should be 0xffffffff */
34 /* xgets - fgets() with backslash-newline stripping */
36 char *xgets(ptr
, len
, fp
)
44 while (fgets(ptr
, len
, fp
)) {
46 if (got
>= 1 && ptr
[got
- 1] == '\n') {
48 if (got
>= 2 && ptr
[got
- 2] == '\\') {
58 return (ptr
> start
? start
: 0);
61 /* split_at - break string at delimiter or return NULL */
63 char *split_at(string
, delimiter
)
69 if ((cp
= strchr(string
, delimiter
)) != 0)
74 /* dot_quad_addr - convert dotted quad to internal form */
76 unsigned long dot_quad_addr(str
)
83 /* Count the number of runs of non-dot characters. */
88 } else if (in_run
== 0) {
94 return (runs
== 4 ? inet_addr(str
) : INADDR_NONE
);
97 /* numeric_addr - convert textual IP address to binary form */
99 int numeric_addr(str
, addr
, af
, len
)
101 union gen_addr
*addr
;
110 if (strchr(str
,':')) {
111 if (af
) *af
= AF_INET6
;
112 if (len
) *len
= sizeof(struct in6_addr
);
113 if (inet_pton(AF_INET6
, str
, (void*) addr
) == 1)
118 if (af
) *af
= AF_INET
;
119 if (len
) *len
= sizeof(struct in_addr
);
120 addr
->ga_in
.s_addr
= dot_quad_addr(str
);
121 return addr
->ga_in
.s_addr
== INADDR_NONE
? -1 : 0;
124 /* For none RFC 2553 compliant systems */
125 #ifdef USE_GETHOSTBYNAME2
126 #define getipnodebyname(h,af,flags,err) gethostbyname2(h,af)
127 #define freehostent(x) x = 0
130 /* tcpd_gethostbyname - an IP family neutral gethostbyname */
132 struct hostent
*tcpd_gethostbyname(host
, af
)
138 static struct hostent
*hs
; /* freehostent() on next call */
141 if (af
== AF_INET6
) { /* must be AF_INET6 */
144 return (hs
= getipnodebyname(host
, AF_INET6
, 0, &err
));
146 hp
= gethostbyname(host
);
147 if (hp
!= NULL
|| af
== AF_INET
) { /* found or must be AF_INET */
149 } else { /* Try INET6 */
152 return (hs
= getipnodebyname(host
, AF_INET6
, 0, &err
));
155 return gethostbyname(host
);
161 * When using IPv6 addresses, we'll be seeing lots of ":"s;
162 * we require the addresses to be specified as [address].
163 * An IPv6 address can be specified in 3 ways:
165 * x:x:x:x:x:x:x:x (fully specified)
166 * x::x:x:x:x (zeroes squashed)
167 * ::FFFF:1.2.3.4 (IPv4 mapped)
169 * These need to be skipped to get at the ":" delimeters.
171 * We also allow a '/prefix' specifier.
173 char *skip_ipv6_addrs(str
)
176 char *obr
, *cbr
, *colon
;
181 if ((colon
= strchr(p
, ':')) == NULL
)
183 if ((obr
= strchr(p
, '[')) == NULL
|| obr
> colon
)
185 if ((cbr
= strchr(obr
, ']')) == NULL
)
188 for (q
= obr
+ 1; q
< cbr
; q
++) {
190 * Quick and dirty parse, cheaper than inet_pton
191 * Could count colons and dots (must be 0 or 3 dots, no
192 * colons after dots seens, only one double :, etc, etc)
194 if (*q
!= ':' && *q
!= '.' && *q
!= '/' && !isxdigit(*q
& 0xff))
200 #endif /* HAVE_IPV6 */