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
));
70 if(make_address(proxy_host
, &dns_addr
.sin_addr
) != 0)
72 dns_addr
.sin_port
= htons(proxy_port
);
73 asprintf(&dns_req
, "http://%s:%d%s", dns_host
, dns_port
, dns_path
);
75 if(make_address(dns_host
, &dns_addr
.sin_addr
) != 0)
77 dns_addr
.sin_port
= htons(dns_port
);
78 asprintf(&dns_req
, "%s", dns_path
);
80 dns_addr
.sin_family
= AF_INET
;
85 split_spec(const char *spec
, char **host
, int *port
, char **path
, int def_port
)
89 p
= strchr(*host
, ':');
92 if(sscanf(p
, "%d", port
) != 1)
96 p
= strchr(p
? p
: *host
, '/');
107 int ROKEN_LIB_FUNCTION
108 roken_gethostby_setup(const char *proxy_spec
, const char *dns_spec
)
110 char *proxy_host
= NULL
;
112 char *dns_host
, *dns_path
;
117 split_spec(dns_spec
, &dns_host
, &dns_port
, &dns_path
, 80);
121 split_spec(proxy_spec
, &proxy_host
, &proxy_port
, NULL
, 80);
122 ret
= setup_int(proxy_host
, proxy_port
, dns_host
, dns_port
, dns_path
);
131 /* Try to lookup a name or an ip-address using http as transport
132 mechanism. See the end of this file for an example program. */
133 static struct hostent
*
134 roken_gethostby(const char *hostname
)
137 struct sockaddr_in addr
;
144 if(dns_addr
.sin_family
== 0)
145 return NULL
; /* no configured host */
147 asprintf(&request
, "GET %s?%s HTTP/1.0\r\n\r\n", dns_req
, hostname
);
150 s
= socket(AF_INET
, SOCK_STREAM
, 0);
155 if(connect(s
, (struct sockaddr
*)&addr
, sizeof(addr
)) < 0) {
160 if(write(s
, request
, strlen(request
)) != strlen(request
)) {
167 n
= read(s
, buf
+ offset
, sizeof(buf
) - offset
);
174 p
= strstr(buf
, "\r\n\r\n"); /* find end of header */
178 p
= strtok_r(p
, " \t\r\n", &foo
);
182 /* make a hostent to return */
184 static struct hostent he
;
185 static char addrs
[4 * MAX_ADDRS
];
186 static char *addr_list
[MAX_ADDRS
+ 1];
191 he
.h_addrtype
= AF_INET
;
194 while((p
= strtok_r(NULL
, " \t\r\n", &foo
)) && num_addrs
< MAX_ADDRS
) {
197 ip
.s_addr
= ntohl(ip
.s_addr
);
198 addr_list
[num_addrs
] = &addrs
[num_addrs
* 4];
199 addrs
[num_addrs
* 4 + 0] = (ip
.s_addr
>> 24) & 0xff;
200 addrs
[num_addrs
* 4 + 1] = (ip
.s_addr
>> 16) & 0xff;
201 addrs
[num_addrs
* 4 + 2] = (ip
.s_addr
>> 8) & 0xff;
202 addrs
[num_addrs
* 4 + 3] = (ip
.s_addr
>> 0) & 0xff;
203 addr_list
[++num_addrs
] = NULL
;
205 he
.h_addr_list
= addr_list
;
211 roken_gethostbyname(const char *hostname
)
214 he
= gethostbyname(hostname
);
217 return roken_gethostby(hostname
);
220 struct hostent
* ROKEN_LIB_FUNCTION
221 roken_gethostbyaddr(const void *addr
, size_t len
, int type
)
226 he
= gethostbyaddr(addr
, len
, type
);
229 if(type
!= AF_INET
|| len
!= 4)
232 a
.s_addr
= htonl((p
[0] << 24) | (p
[1] << 16) | (p
[2] << 8) | p
[3]);
233 return roken_gethostby(inet_ntoa(a
));
238 /* this program can be used as a cgi `script' to lookup names and
244 #include <sys/param.h>
247 main(int argc
, char **argv
)
249 char *query
= getenv("QUERY_STRING");
250 char host
[MAXHOSTNAMELEN
];
254 printf("Content-type: text/plain\n\n");
257 he
= gethostbyname(query
);
258 strncpy(host
, he
->h_name
, sizeof(host
));
259 host
[sizeof(host
) - 1] = '\0';
260 he
= gethostbyaddr(he
->h_addr
, he
->h_length
, AF_INET
);
261 printf("%s\n", he
->h_name
);
262 for(i
= 0; he
->h_addr_list
[i
]; i
++) {
264 unsigned char *p
= (unsigned char*)he
->h_addr_list
[i
];
265 ip
.s_addr
= htonl((p
[0] << 24) | (p
[1] << 16) | (p
[2] << 8) | p
[3]);
266 printf("%s\n", inet_ntoa(ip
));