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>
32 #include <net/gen/nameser.h>
33 #include <net/gen/netdb.h>
34 #include <net/gen/in.h>
35 #include <net/gen/inet.h>
36 #include <net/gen/resolv.h>
37 #include <net/gen/socket.h>
39 #include <sys/param.h>
40 #include <sys/socket.h>
41 #include <netinet/in.h>
46 #include <arpa/inet.h>
47 #include <arpa/nameser.h>
54 static char *h_addr_ptrs
[MAXADDRS
+ 1];
63 extern int dn_skipname
_ARGS(( const u_char
*comp_dn
, const u_char
*eom
));
64 #define getshort _getshort
65 static struct hostent
*getanswer
_ARGS(( union querybuf
*answer
, int anslen
,
68 #define bcopy(s, d, l) memcpy(d, s, l)
71 static struct hostent host
;
72 static char *host_aliases
[MAXALIASES
];
73 static char hostbuf
[BUFSIZ
+1];
74 static struct in_addr host_addr
;
81 #define MAXPACKET PACKETSZ
83 #define MAXPACKET 1024
86 typedef union querybuf
89 u_char buf
[MAXPACKET
];
97 static struct hostent
*
98 getanswer(answer
, anslen
, iquery
)
103 register dns_hdr_t
*hp
;
108 int type
, class, buflen
, ancount
, qdcount
;
109 int haveanswer
, getclass
= C_ANY
;
112 eom
= answer
->buf
+ anslen
;
114 * find first satisfactory answer
117 ancount
= ntohs(hp
->dh_ancount
);
118 qdcount
= ntohs(hp
->dh_qdcount
);
120 buflen
= sizeof(hostbuf
);
121 cp
= answer
->buf
+ sizeof(dns_hdr_t
);
124 if ((n
= dn_expand((u_char
*)answer
->buf
, eom
,
125 cp
, (u_char
*)bp
, buflen
)) < 0) {
126 h_errno
= NO_RECOVERY
;
127 return ((struct hostent
*) NULL
);
135 cp
+= dn_skipname(cp
, eom
) + QFIXEDSZ
;
136 while (--qdcount
> 0)
137 cp
+= dn_skipname(cp
, eom
) + QFIXEDSZ
;
139 if (hp
->dh_flag1
& DHF_AA
)
140 h_errno
= HOST_NOT_FOUND
;
143 return ((struct hostent
*) NULL
);
147 host
.h_aliases
= host_aliases
;
150 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
151 host
.h_addr_list
= h_addr_ptrs
;
154 while (--ancount
>= 0 && cp
< eom
) {
155 if ((n
= dn_expand((u_char
*)answer
->buf
, eom
, cp
, (u_char
*)bp
,
160 cp
+= sizeof(u_short
);
161 class = getshort(cp
);
162 cp
+= sizeof(u_short
) + sizeof(u_long
);
164 cp
+= sizeof(u_short
);
165 if (type
== T_CNAME
) {
167 if (ap
>= &host_aliases
[MAXALIASES
-1])
175 if (iquery
&& type
== T_PTR
) {
176 if ((n
= dn_expand((u8_t
*)answer
->buf
, eom
,
177 cp
, (u8_t
*)bp
, buflen
)) < 0) {
185 if (iquery
|| type
!= T_A
) {
187 if (_res
.options
& RES_DEBUG
)
188 printf("unexpected answer type %d, size %d\n",
195 if (n
!= host
.h_length
) {
199 if (class != getclass
) {
206 host
.h_addrtype
= (class == C_IN
) ? AF_INET
: AF_UNSPEC
;
209 bp
+= strlen(bp
) + 1;
213 bp
+= (size_t)(sizeof(align_t
) -
214 ((u_long
)bp
% sizeof(align_t
)));
216 if (bp
+ n
>= &hostbuf
[sizeof(hostbuf
)]) {
218 if (_res
.options
& RES_DEBUG
)
219 printf("size (%d) too big\n", n
);
223 bcopy(cp
, *hap
++ = bp
, n
);
230 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
233 host
.h_addr
= h_addr_ptrs
[0];
238 return ((struct hostent
*) NULL
);
247 register _CONST
char *cp
;
251 * disallow names consisting only of digits/dots, unless
254 if (isdigit(name
[0]))
255 for (cp
= name
;; ++cp
) {
260 * All-numeric, no dot at the end.
261 * Fake up a hostent as if we'd actually
262 * done a lookup. What if someone types
263 * 255.255.255.255? The test below will
264 * succeed spuriously... ???
266 if ((host_addr
.s_addr
= inet_addr(name
)) == -1) {
267 h_errno
= HOST_NOT_FOUND
;
268 return((struct hostent
*) NULL
);
270 host
.h_name
= (char *) name
;
271 host
.h_aliases
= host_aliases
;
272 host_aliases
[0] = NULL
;
273 host
.h_addrtype
= AF_INET
;
274 host
.h_length
= sizeof(u_long
);
275 h_addr_ptrs
[0] = (char *)&host_addr
;
276 h_addr_ptrs
[1] = (char *)0;
277 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
278 host
.h_addr_list
= h_addr_ptrs
;
280 host
.h_addr
= h_addr_ptrs
[0];
284 if (!isdigit(*cp
) && *cp
!= '.')
288 if ((n
= res_search((char*)name
, C_IN
, T_A
, buf
.buf
, sizeof(buf
))) < 0) {
290 if (_res
.options
& RES_DEBUG
)
291 printf("res_search failed\n");
293 return ((struct hostent
*) NULL
);
295 return (getanswer(&buf
, n
, 0));
299 gethostbyaddr(addr
, len
, type
)
305 register struct hostent
*hp
;
309 return ((struct hostent
*) NULL
);
310 (void)sprintf(qbuf
, "%u.%u.%u.%u.in-addr.arpa",
311 ((unsigned)addr
[3] & 0xff),
312 ((unsigned)addr
[2] & 0xff),
313 ((unsigned)addr
[1] & 0xff),
314 ((unsigned)addr
[0] & 0xff));
315 n
= res_query(qbuf
, C_IN
, T_PTR
, (u8_t
*)&buf
, sizeof(buf
));
318 if (_res
.options
& RES_DEBUG
)
319 printf("res_query failed\n");
321 return ((struct hostent
*) NULL
);
323 hp
= getanswer(&buf
, n
, 1);
325 return ((struct hostent
*) NULL
);
326 hp
->h_addrtype
= type
;
328 h_addr_ptrs
[0] = (char *)&host_addr
;
329 h_addr_ptrs
[1] = (char *)0;
330 host_addr
= *(struct in_addr
*)addr
;
331 #if BSD < 43 && !defined(h_addr) /* new-style hostent structure */
332 hp
->h_addr
= h_addr_ptrs
[0];