2 * Copyright (c) 1998 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 #undef roken_gethostbyname
39 #undef roken_gethostbyaddr
41 static struct sockaddr_in dns_addr
;
45 make_address(const char *address
, struct in_addr
*ip
)
47 if(inet_aton(address
, ip
) == 0){
48 /* try to resolve as hostname, it might work if the address we
49 are trying to lookup is local, for instance a web proxy */
50 struct hostent
*he
= gethostbyname(address
);
52 unsigned char *p
= (unsigned char*)he
->h_addr
;
53 ip
->s_addr
= (p
[0] << 24) | (p
[1] << 16) | (p
[2] << 8) | p
[3];
62 setup_int(const char *proxy_host
, short proxy_port
,
63 const char *dns_host
, short dns_port
,
66 memset(&dns_addr
, 0, sizeof(dns_addr
));
71 if(make_address(proxy_host
, &dns_addr
.sin_addr
) != 0)
73 dns_addr
.sin_port
= htons(proxy_port
);
74 if (asprintf(&dns_req
, "http://%s:%d%s", dns_host
, dns_port
, dns_path
) < 0)
77 if(make_address(dns_host
, &dns_addr
.sin_addr
) != 0)
79 dns_addr
.sin_port
= htons(dns_port
);
80 if (asprintf(&dns_req
, "%s", dns_path
) < 0)
83 dns_addr
.sin_family
= AF_INET
;
88 split_spec(const char *spec
, char **host
, int *port
, char **path
, int def_port
)
94 p
= strchr(*host
, ':');
97 if(sscanf(p
, "%d", port
) != 1)
101 p
= strchr(p
? p
: *host
, '/');
119 ROKEN_LIB_FUNCTION
int ROKEN_LIB_CALL
120 roken_gethostby_setup(const char *proxy_spec
, const char *dns_spec
)
122 char *proxy_host
= NULL
;
124 char *dns_host
= NULL
, *dns_path
= NULL
;
128 ret
= split_spec(dns_spec
, &dns_host
, &dns_port
, &dns_path
, 80);
132 ret
= split_spec(proxy_spec
, &proxy_host
, &proxy_port
, NULL
, 80);
136 ret
= setup_int(proxy_host
, proxy_port
, dns_host
, dns_port
, dns_path
);
148 /* Try to lookup a name or an ip-address using http as transport
149 mechanism. See the end of this file for an example program. */
150 static struct hostent
*
151 roken_gethostby(const char *hostname
)
154 struct sockaddr_in addr
;
155 char *request
= NULL
;
162 if(dns_addr
.sin_family
== 0)
163 return NULL
; /* no configured host */
165 if (asprintf(&request
, "GET %s?%s HTTP/1.0\r\n\r\n", dns_req
, hostname
) < 0)
169 s
= socket(AF_INET
, SOCK_STREAM
, 0);
174 if(connect(s
, (struct sockaddr
*)&addr
, sizeof(addr
)) < 0) {
180 len
= strlen(request
);
181 if(write(s
, request
, len
) != (ssize_t
)len
) {
188 n
= read(s
, buf
+ offset
, sizeof(buf
) - offset
);
195 p
= strstr(buf
, "\r\n\r\n"); /* find end of header */
199 p
= strtok_r(p
, " \t\r\n", &foo
);
203 /* make a hostent to return */
205 static struct hostent he
;
206 static char addrs
[4 * MAX_ADDRS
];
207 static char *addr_list
[MAX_ADDRS
+ 1];
212 he
.h_addrtype
= AF_INET
;
215 while((p
= strtok_r(NULL
, " \t\r\n", &foo
)) && num_addrs
< MAX_ADDRS
) {
218 ip
.s_addr
= ntohl(ip
.s_addr
);
219 addr_list
[num_addrs
] = &addrs
[num_addrs
* 4];
220 addrs
[num_addrs
* 4 + 0] = (ip
.s_addr
>> 24) & 0xff;
221 addrs
[num_addrs
* 4 + 1] = (ip
.s_addr
>> 16) & 0xff;
222 addrs
[num_addrs
* 4 + 2] = (ip
.s_addr
>> 8) & 0xff;
223 addrs
[num_addrs
* 4 + 3] = (ip
.s_addr
>> 0) & 0xff;
224 addr_list
[++num_addrs
] = NULL
;
226 he
.h_addr_list
= addr_list
;
231 ROKEN_LIB_FUNCTION
struct hostent
* ROKEN_LIB_CALL
232 roken_gethostbyname(const char *hostname
)
235 he
= gethostbyname(hostname
);
238 return roken_gethostby(hostname
);
241 ROKEN_LIB_FUNCTION
struct hostent
* ROKEN_LIB_CALL
242 roken_gethostbyaddr(const void *addr
, size_t len
, int type
)
247 he
= gethostbyaddr(addr
, len
, type
);
250 if(type
!= AF_INET
|| len
!= 4)
253 a
.s_addr
= htonl((p
[0] << 24) | (p
[1] << 16) | (p
[2] << 8) | p
[3]);
254 return roken_gethostby(inet_ntoa(a
));
259 /* this program can be used as a cgi `script' to lookup names and
265 #include <sys/param.h>
268 main(int argc
, char **argv
)
270 char *query
= getenv("QUERY_STRING");
271 char host
[MAXHOSTNAMELEN
];
275 printf("Content-type: text/plain\n\n");
278 he
= gethostbyname(query
);
279 strncpy(host
, he
->h_name
, sizeof(host
));
280 host
[sizeof(host
) - 1] = '\0';
281 he
= gethostbyaddr(he
->h_addr
, he
->h_length
, AF_INET
);
282 printf("%s\n", he
->h_name
);
283 for(i
= 0; he
->h_addr_list
[i
]; i
++) {
285 unsigned char *p
= (unsigned char*)he
->h_addr_list
[i
];
286 ip
.s_addr
= htonl((p
[0] << 24) | (p
[1] << 16) | (p
[2] << 8) | p
[3]);
287 printf("%s\n", inet_ntoa(ip
));