1 /* $NetBSD: roken_gethostby.c,v 1.1.1.2 2014/04/24 12:45:52 pettai Exp $ */
4 * Copyright (c) 1998 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 #include <krb5/roken.h>
40 #undef roken_gethostbyname
41 #undef roken_gethostbyaddr
43 static struct sockaddr_in dns_addr
;
47 make_address(const char *address
, struct in_addr
*ip
)
49 if(inet_aton(address
, ip
) == 0){
50 /* try to resolve as hostname, it might work if the address we
51 are trying to lookup is local, for instance a web proxy */
52 struct hostent
*he
= gethostbyname(address
);
54 unsigned char *p
= (unsigned char*)he
->h_addr
;
55 ip
->s_addr
= (p
[0] << 24) | (p
[1] << 16) | (p
[2] << 8) | p
[3];
64 setup_int(const char *proxy_host
, short proxy_port
,
65 const char *dns_host
, short dns_port
,
68 memset(&dns_addr
, 0, sizeof(dns_addr
));
73 if(make_address(proxy_host
, &dns_addr
.sin_addr
) != 0)
75 dns_addr
.sin_port
= htons(proxy_port
);
76 if (asprintf(&dns_req
, "http://%s:%d%s", dns_host
, dns_port
, dns_path
) < 0)
79 if(make_address(dns_host
, &dns_addr
.sin_addr
) != 0)
81 dns_addr
.sin_port
= htons(dns_port
);
82 asprintf(&dns_req
, "%s", dns_path
);
84 dns_addr
.sin_family
= AF_INET
;
89 split_spec(const char *spec
, char **host
, int *port
, char **path
, int def_port
)
93 p
= strchr(*host
, ':');
96 if(sscanf(p
, "%d", port
) != 1)
100 p
= strchr(p
? p
: *host
, '/');
111 ROKEN_LIB_FUNCTION
int ROKEN_LIB_CALL
112 roken_gethostby_setup(const char *proxy_spec
, const char *dns_spec
)
114 char *proxy_host
= NULL
;
116 char *dns_host
, *dns_path
;
121 split_spec(dns_spec
, &dns_host
, &dns_port
, &dns_path
, 80);
125 split_spec(proxy_spec
, &proxy_host
, &proxy_port
, NULL
, 80);
126 ret
= setup_int(proxy_host
, proxy_port
, dns_host
, dns_port
, dns_path
);
135 /* Try to lookup a name or an ip-address using http as transport
136 mechanism. See the end of this file for an example program. */
137 static struct hostent
*
138 roken_gethostby(const char *hostname
)
141 struct sockaddr_in addr
;
142 char *request
= NULL
;
149 if(dns_addr
.sin_family
== 0)
150 return NULL
; /* no configured host */
152 if (asprintf(&request
, "GET %s?%s HTTP/1.0\r\n\r\n", dns_req
, hostname
) < 0)
156 s
= socket(AF_INET
, SOCK_STREAM
, 0);
161 if(connect(s
, (struct sockaddr
*)&addr
, sizeof(addr
)) < 0) {
167 len
= strlen(request
);
168 if(write(s
, request
, len
) != (ssize_t
)len
) {
175 n
= read(s
, buf
+ offset
, sizeof(buf
) - offset
);
182 p
= strstr(buf
, "\r\n\r\n"); /* find end of header */
186 p
= strtok_r(p
, " \t\r\n", &foo
);
190 /* make a hostent to return */
192 static struct hostent he
;
193 static char addrs
[4 * MAX_ADDRS
];
194 static char *addr_list
[MAX_ADDRS
+ 1];
199 he
.h_addrtype
= AF_INET
;
202 while((p
= strtok_r(NULL
, " \t\r\n", &foo
)) && num_addrs
< MAX_ADDRS
) {
205 ip
.s_addr
= ntohl(ip
.s_addr
);
206 addr_list
[num_addrs
] = &addrs
[num_addrs
* 4];
207 addrs
[num_addrs
* 4 + 0] = (ip
.s_addr
>> 24) & 0xff;
208 addrs
[num_addrs
* 4 + 1] = (ip
.s_addr
>> 16) & 0xff;
209 addrs
[num_addrs
* 4 + 2] = (ip
.s_addr
>> 8) & 0xff;
210 addrs
[num_addrs
* 4 + 3] = (ip
.s_addr
>> 0) & 0xff;
211 addr_list
[++num_addrs
] = NULL
;
213 he
.h_addr_list
= addr_list
;
218 ROKEN_LIB_FUNCTION
struct hostent
* ROKEN_LIB_CALL
219 roken_gethostbyname(const char *hostname
)
222 he
= gethostbyname(hostname
);
225 return roken_gethostby(hostname
);
228 ROKEN_LIB_FUNCTION
struct hostent
* ROKEN_LIB_CALL
229 roken_gethostbyaddr(const void *addr
, size_t len
, int type
)
234 he
= gethostbyaddr(addr
, len
, type
);
237 if(type
!= AF_INET
|| len
!= 4)
240 a
.s_addr
= htonl((p
[0] << 24) | (p
[1] << 16) | (p
[2] << 8) | p
[3]);
241 return roken_gethostby(inet_ntoa(a
));
246 /* this program can be used as a cgi `script' to lookup names and
252 #include <sys/param.h>
255 main(int argc
, char **argv
)
257 char *query
= getenv("QUERY_STRING");
258 char host
[MAXHOSTNAMELEN
];
262 printf("Content-type: text/plain\n\n");
265 he
= gethostbyname(query
);
266 strncpy(host
, he
->h_name
, sizeof(host
));
267 host
[sizeof(host
) - 1] = '\0';
268 he
= gethostbyaddr(he
->h_addr
, he
->h_length
, AF_INET
);
269 printf("%s\n", he
->h_name
);
270 for(i
= 0; he
->h_addr_list
[i
]; i
++) {
272 unsigned char *p
= (unsigned char*)he
->h_addr_list
[i
];
273 ip
.s_addr
= htonl((p
[0] << 24) | (p
[1] << 16) | (p
[2] << 8) | p
[3]);
274 printf("%s\n", inet_ntoa(ip
));