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.
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>
29 #define INADDR_NONE (-1) /* XXX should be 0xffffffff */
32 /* xgets - fgets() with backslash-newline stripping */
34 char *xgets(ptr
, len
, fp
)
42 while (fgets(ptr
, len
, fp
)) {
44 if (got
>= 1 && ptr
[got
- 1] == '\n') {
46 if (got
>= 2 && ptr
[got
- 2] == '\\') {
56 return (ptr
> start
? start
: 0);
59 /* split_at - break string at delimiter or return NULL */
61 char *split_at(string
, delimiter
)
67 if ((cp
= strchr(string
, delimiter
)) != 0)
72 /* dot_quad_addr - convert dotted quad to internal form */
74 unsigned long dot_quad_addr(str
)
81 /* Count the number of runs of non-dot characters. */
86 } else if (in_run
== 0) {
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
)
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)
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
128 /* tcpd_gethostbyname - an IP family neutral gethostbyname */
130 struct hostent
*tcpd_gethostbyname(host
, af
)
136 static struct hostent
*hs
; /* freehostent() on next call */
139 if (af
== AF_INET6
) { /* must be AF_INET6 */
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 */
147 } else { /* Try INET6 */
150 return (hs
= getipnodebyname(host
, AF_INET6
, 0, &err
));
153 return gethostbyname(host
);
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
)
174 char *obr
, *cbr
, *colon
;
179 if ((colon
= strchr(p
, ':')) == NULL
)
181 if ((obr
= strchr(p
, '[')) == NULL
|| obr
> colon
)
183 if ((cbr
= strchr(obr
, ']')) == NULL
)
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))
198 #endif /* HAVE_IPV6 */