2 * Copyright (c) 1985, 1988 Regents of the University of California.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that: (1) source distributions retain this entire copyright
7 * notice and comment, and (2) distributions including binaries display
8 * the following acknowledgement: ``This product includes software
9 * developed by the University of California, Berkeley and its contributors''
10 * in the documentation or other materials provided with the distribution
11 * and in all advertising materials mentioning features or use of this
12 * software. Neither the name of the University nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 #if defined(LIBC_SCCS) && !defined(lint)
21 static char sccsid
[] = "@(#)gethostnamadr.c 6.41 (Berkeley) 6/1/90";
22 #endif /* LIBC_SCCS and not lint */
25 #include <sys/types.h>
31 #include <net/gen/nameser.h>
32 #include <net/gen/netdb.h>
33 #include <net/gen/in.h>
34 #include <net/gen/inet.h>
35 #include <net/gen/resolv.h>
36 #include <net/gen/socket.h>
38 #include <sys/param.h>
39 #include <sys/socket.h>
40 #include <netinet/in.h>
44 #include <arpa/inet.h>
45 #include <arpa/nameser.h>
52 static char *h_addr_ptrs
[MAXADDRS
+ 1];
57 extern int dn_skipname
_ARGS(( const u_char
*comp_dn
, const u_char
*eom
));
58 #define getshort _getshort
59 static struct hostent
*getanswer
_ARGS(( union querybuf
*answer
, int anslen
,
62 #define bcopy(s, d, l) memcpy(d, s, l)
65 static struct hostent host
;
66 static char *host_aliases
[MAXALIASES
];
67 static char hostbuf
[BUFSIZ
+1];
68 static struct in_addr host_addr
;
75 #define MAXPACKET PACKETSZ
77 #define MAXPACKET 1024
80 typedef union querybuf
83 u_char buf
[MAXPACKET
];
91 static struct hostent
*
92 getanswer(answer
, anslen
, iquery
)
97 register dns_hdr_t
*hp
;
102 int type
, class, buflen
, ancount
, qdcount
;
103 int haveanswer
, getclass
= C_ANY
;
106 eom
= answer
->buf
+ anslen
;
108 * find first satisfactory answer
111 ancount
= ntohs(hp
->dh_ancount
);
112 qdcount
= ntohs(hp
->dh_qdcount
);
114 buflen
= sizeof(hostbuf
);
115 cp
= answer
->buf
+ sizeof(dns_hdr_t
);
118 if ((n
= dn_expand((u_char
*)answer
->buf
, eom
,
119 cp
, (u_char
*)bp
, buflen
)) < 0) {
120 h_errno
= NO_RECOVERY
;
121 return ((struct hostent
*) NULL
);
129 cp
+= dn_skipname(cp
, eom
) + QFIXEDSZ
;
130 while (--qdcount
> 0)
131 cp
+= dn_skipname(cp
, eom
) + QFIXEDSZ
;
133 if (hp
->dh_flag1
& DHF_AA
)
134 h_errno
= HOST_NOT_FOUND
;
137 return ((struct hostent
*) NULL
);
141 host
.h_aliases
= host_aliases
;
144 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
145 host
.h_addr_list
= h_addr_ptrs
;
148 while (--ancount
>= 0 && cp
< eom
) {
149 if ((n
= dn_expand((u_char
*)answer
->buf
, eom
, cp
, (u_char
*)bp
,
154 cp
+= sizeof(u_short
);
155 class = getshort(cp
);
156 cp
+= sizeof(u_short
) + sizeof(u_long
);
158 cp
+= sizeof(u_short
);
159 if (type
== T_CNAME
) {
161 if (ap
>= &host_aliases
[MAXALIASES
-1])
169 if (iquery
&& type
== T_PTR
) {
170 if ((n
= dn_expand((u8_t
*)answer
->buf
, eom
,
171 cp
, (u8_t
*)bp
, buflen
)) < 0) {
179 if (iquery
|| type
!= T_A
) {
181 if (_res
.options
& RES_DEBUG
)
182 printf("unexpected answer type %d, size %d\n",
189 if (n
!= host
.h_length
) {
193 if (class != getclass
) {
200 host
.h_addrtype
= (class == C_IN
) ? AF_INET
: AF_UNSPEC
;
203 bp
+= strlen(bp
) + 1;
207 bp
+= (size_t)(sizeof(align_t
) -
208 ((u_long
)bp
% sizeof(align_t
)));
210 if (bp
+ n
>= &hostbuf
[sizeof(hostbuf
)]) {
212 if (_res
.options
& RES_DEBUG
)
213 printf("size (%d) too big\n", n
);
217 bcopy(cp
, *hap
++ = bp
, n
);
224 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
227 host
.h_addr
= h_addr_ptrs
[0];
232 return ((struct hostent
*) NULL
);
241 register _CONST
char *cp
;
245 * disallow names consisting only of digits/dots, unless
248 if (isdigit(name
[0]))
249 for (cp
= name
;; ++cp
) {
254 * All-numeric, no dot at the end.
255 * Fake up a hostent as if we'd actually
256 * done a lookup. What if someone types
257 * 255.255.255.255? The test below will
258 * succeed spuriously... ???
260 if ((host_addr
.s_addr
= inet_addr(name
)) == -1) {
261 h_errno
= HOST_NOT_FOUND
;
262 return((struct hostent
*) NULL
);
264 host
.h_name
= (char *) name
;
265 host
.h_aliases
= host_aliases
;
266 host_aliases
[0] = NULL
;
267 host
.h_addrtype
= AF_INET
;
268 host
.h_length
= sizeof(u_long
);
269 h_addr_ptrs
[0] = (char *)&host_addr
;
270 h_addr_ptrs
[1] = (char *)0;
271 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
272 host
.h_addr_list
= h_addr_ptrs
;
274 host
.h_addr
= h_addr_ptrs
[0];
278 if (!isdigit(*cp
) && *cp
!= '.')
282 if ((n
= res_search((char*)name
, C_IN
, T_A
, buf
.buf
, sizeof(buf
))) < 0) {
284 if (_res
.options
& RES_DEBUG
)
285 printf("res_search failed\n");
287 return ((struct hostent
*) NULL
);
289 return (getanswer(&buf
, n
, 0));
293 gethostbyaddr(addr
, len
, type
)
299 register struct hostent
*hp
;
303 return ((struct hostent
*) NULL
);
304 (void)sprintf(qbuf
, "%u.%u.%u.%u.in-addr.arpa",
305 ((unsigned)addr
[3] & 0xff),
306 ((unsigned)addr
[2] & 0xff),
307 ((unsigned)addr
[1] & 0xff),
308 ((unsigned)addr
[0] & 0xff));
309 n
= res_query(qbuf
, C_IN
, T_PTR
, (u8_t
*)&buf
, sizeof(buf
));
312 if (_res
.options
& RES_DEBUG
)
313 printf("res_query failed\n");
315 return ((struct hostent
*) NULL
);
317 hp
= getanswer(&buf
, n
, 1);
319 return ((struct hostent
*) NULL
);
320 hp
->h_addrtype
= type
;
322 h_addr_ptrs
[0] = (char *)&host_addr
;
323 h_addr_ptrs
[1] = (char *)0;
324 host_addr
= *(struct in_addr
*)addr
;
325 #if BSD < 43 && !defined(h_addr) /* new-style hostent structure */
326 hp
->h_addr
= h_addr_ptrs
[0];