1*0a6a1f1dSLionel Sambuc /* $NetBSD: roken_gethostby.c,v 1.1.1.2 2014/04/24 12:45:52 pettai Exp $ */
2ebfedea0SLionel Sambuc
3ebfedea0SLionel Sambuc /*
4ebfedea0SLionel Sambuc * Copyright (c) 1998 Kungliga Tekniska Högskolan
5ebfedea0SLionel Sambuc * (Royal Institute of Technology, Stockholm, Sweden).
6ebfedea0SLionel Sambuc * All rights reserved.
7ebfedea0SLionel Sambuc *
8ebfedea0SLionel Sambuc * Redistribution and use in source and binary forms, with or without
9ebfedea0SLionel Sambuc * modification, are permitted provided that the following conditions
10ebfedea0SLionel Sambuc * are met:
11ebfedea0SLionel Sambuc *
12ebfedea0SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
13ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer.
14ebfedea0SLionel Sambuc *
15ebfedea0SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
16ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
17ebfedea0SLionel Sambuc * documentation and/or other materials provided with the distribution.
18ebfedea0SLionel Sambuc *
19ebfedea0SLionel Sambuc * 3. Neither the name of the Institute nor the names of its contributors
20ebfedea0SLionel Sambuc * may be used to endorse or promote products derived from this software
21ebfedea0SLionel Sambuc * without specific prior written permission.
22ebfedea0SLionel Sambuc *
23ebfedea0SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ebfedea0SLionel Sambuc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ebfedea0SLionel Sambuc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ebfedea0SLionel Sambuc * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ebfedea0SLionel Sambuc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ebfedea0SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ebfedea0SLionel Sambuc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ebfedea0SLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ebfedea0SLionel Sambuc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ebfedea0SLionel Sambuc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ebfedea0SLionel Sambuc * SUCH DAMAGE.
34ebfedea0SLionel Sambuc */
35ebfedea0SLionel Sambuc
36ebfedea0SLionel Sambuc #include <config.h>
37ebfedea0SLionel Sambuc
38ebfedea0SLionel Sambuc #include <krb5/roken.h>
39ebfedea0SLionel Sambuc
40ebfedea0SLionel Sambuc #undef roken_gethostbyname
41ebfedea0SLionel Sambuc #undef roken_gethostbyaddr
42ebfedea0SLionel Sambuc
43ebfedea0SLionel Sambuc static struct sockaddr_in dns_addr;
44ebfedea0SLionel Sambuc static char *dns_req;
45ebfedea0SLionel Sambuc
46ebfedea0SLionel Sambuc static int
make_address(const char * address,struct in_addr * ip)47ebfedea0SLionel Sambuc make_address(const char *address, struct in_addr *ip)
48ebfedea0SLionel Sambuc {
49ebfedea0SLionel Sambuc if(inet_aton(address, ip) == 0){
50ebfedea0SLionel Sambuc /* try to resolve as hostname, it might work if the address we
51ebfedea0SLionel Sambuc are trying to lookup is local, for instance a web proxy */
52ebfedea0SLionel Sambuc struct hostent *he = gethostbyname(address);
53ebfedea0SLionel Sambuc if(he) {
54ebfedea0SLionel Sambuc unsigned char *p = (unsigned char*)he->h_addr;
55ebfedea0SLionel Sambuc ip->s_addr = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
56ebfedea0SLionel Sambuc } else {
57ebfedea0SLionel Sambuc return -1;
58ebfedea0SLionel Sambuc }
59ebfedea0SLionel Sambuc }
60ebfedea0SLionel Sambuc return 0;
61ebfedea0SLionel Sambuc }
62ebfedea0SLionel Sambuc
63ebfedea0SLionel Sambuc static int
setup_int(const char * proxy_host,short proxy_port,const char * dns_host,short dns_port,const char * dns_path)64ebfedea0SLionel Sambuc setup_int(const char *proxy_host, short proxy_port,
65ebfedea0SLionel Sambuc const char *dns_host, short dns_port,
66ebfedea0SLionel Sambuc const char *dns_path)
67ebfedea0SLionel Sambuc {
68ebfedea0SLionel Sambuc memset(&dns_addr, 0, sizeof(dns_addr));
69ebfedea0SLionel Sambuc if(dns_req)
70ebfedea0SLionel Sambuc free(dns_req);
71ebfedea0SLionel Sambuc dns_req = NULL;
72ebfedea0SLionel Sambuc if(proxy_host) {
73ebfedea0SLionel Sambuc if(make_address(proxy_host, &dns_addr.sin_addr) != 0)
74ebfedea0SLionel Sambuc return -1;
75ebfedea0SLionel Sambuc dns_addr.sin_port = htons(proxy_port);
76ebfedea0SLionel Sambuc if (asprintf(&dns_req, "http://%s:%d%s", dns_host, dns_port, dns_path) < 0)
77ebfedea0SLionel Sambuc return -1;
78ebfedea0SLionel Sambuc } else {
79ebfedea0SLionel Sambuc if(make_address(dns_host, &dns_addr.sin_addr) != 0)
80ebfedea0SLionel Sambuc return -1;
81ebfedea0SLionel Sambuc dns_addr.sin_port = htons(dns_port);
82ebfedea0SLionel Sambuc asprintf(&dns_req, "%s", dns_path);
83ebfedea0SLionel Sambuc }
84ebfedea0SLionel Sambuc dns_addr.sin_family = AF_INET;
85ebfedea0SLionel Sambuc return 0;
86ebfedea0SLionel Sambuc }
87ebfedea0SLionel Sambuc
88ebfedea0SLionel Sambuc static void
split_spec(const char * spec,char ** host,int * port,char ** path,int def_port)89ebfedea0SLionel Sambuc split_spec(const char *spec, char **host, int *port, char **path, int def_port)
90ebfedea0SLionel Sambuc {
91ebfedea0SLionel Sambuc char *p;
92ebfedea0SLionel Sambuc *host = strdup(spec);
93ebfedea0SLionel Sambuc p = strchr(*host, ':');
94ebfedea0SLionel Sambuc if(p) {
95ebfedea0SLionel Sambuc *p++ = '\0';
96ebfedea0SLionel Sambuc if(sscanf(p, "%d", port) != 1)
97ebfedea0SLionel Sambuc *port = def_port;
98ebfedea0SLionel Sambuc } else
99ebfedea0SLionel Sambuc *port = def_port;
100ebfedea0SLionel Sambuc p = strchr(p ? p : *host, '/');
101ebfedea0SLionel Sambuc if(p) {
102ebfedea0SLionel Sambuc if(path)
103ebfedea0SLionel Sambuc *path = strdup(p);
104ebfedea0SLionel Sambuc *p = '\0';
105ebfedea0SLionel Sambuc }else
106ebfedea0SLionel Sambuc if(path)
107ebfedea0SLionel Sambuc *path = NULL;
108ebfedea0SLionel Sambuc }
109ebfedea0SLionel Sambuc
110ebfedea0SLionel Sambuc
111ebfedea0SLionel Sambuc ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
roken_gethostby_setup(const char * proxy_spec,const char * dns_spec)112ebfedea0SLionel Sambuc roken_gethostby_setup(const char *proxy_spec, const char *dns_spec)
113ebfedea0SLionel Sambuc {
114ebfedea0SLionel Sambuc char *proxy_host = NULL;
115ebfedea0SLionel Sambuc int proxy_port = 0;
116ebfedea0SLionel Sambuc char *dns_host, *dns_path;
117ebfedea0SLionel Sambuc int dns_port;
118ebfedea0SLionel Sambuc
119ebfedea0SLionel Sambuc int ret = -1;
120ebfedea0SLionel Sambuc
121ebfedea0SLionel Sambuc split_spec(dns_spec, &dns_host, &dns_port, &dns_path, 80);
122ebfedea0SLionel Sambuc if(dns_path == NULL)
123ebfedea0SLionel Sambuc goto out;
124ebfedea0SLionel Sambuc if(proxy_spec)
125ebfedea0SLionel Sambuc split_spec(proxy_spec, &proxy_host, &proxy_port, NULL, 80);
126ebfedea0SLionel Sambuc ret = setup_int(proxy_host, proxy_port, dns_host, dns_port, dns_path);
127ebfedea0SLionel Sambuc out:
128ebfedea0SLionel Sambuc free(proxy_host);
129ebfedea0SLionel Sambuc free(dns_host);
130ebfedea0SLionel Sambuc free(dns_path);
131ebfedea0SLionel Sambuc return ret;
132ebfedea0SLionel Sambuc }
133ebfedea0SLionel Sambuc
134ebfedea0SLionel Sambuc
135ebfedea0SLionel Sambuc /* Try to lookup a name or an ip-address using http as transport
136ebfedea0SLionel Sambuc mechanism. See the end of this file for an example program. */
137ebfedea0SLionel Sambuc static struct hostent*
roken_gethostby(const char * hostname)138ebfedea0SLionel Sambuc roken_gethostby(const char *hostname)
139ebfedea0SLionel Sambuc {
140ebfedea0SLionel Sambuc int s;
141ebfedea0SLionel Sambuc struct sockaddr_in addr;
142ebfedea0SLionel Sambuc char *request = NULL;
143ebfedea0SLionel Sambuc char buf[1024];
144ebfedea0SLionel Sambuc int offset = 0;
145ebfedea0SLionel Sambuc int n;
146ebfedea0SLionel Sambuc char *p, *foo;
147*0a6a1f1dSLionel Sambuc size_t len;
148ebfedea0SLionel Sambuc
149ebfedea0SLionel Sambuc if(dns_addr.sin_family == 0)
150ebfedea0SLionel Sambuc return NULL; /* no configured host */
151ebfedea0SLionel Sambuc addr = dns_addr;
152ebfedea0SLionel Sambuc if (asprintf(&request, "GET %s?%s HTTP/1.0\r\n\r\n", dns_req, hostname) < 0)
153ebfedea0SLionel Sambuc return NULL;
154ebfedea0SLionel Sambuc if(request == NULL)
155ebfedea0SLionel Sambuc return NULL;
156ebfedea0SLionel Sambuc s = socket(AF_INET, SOCK_STREAM, 0);
157ebfedea0SLionel Sambuc if(s < 0) {
158ebfedea0SLionel Sambuc free(request);
159ebfedea0SLionel Sambuc return NULL;
160ebfedea0SLionel Sambuc }
161ebfedea0SLionel Sambuc if(connect(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
162ebfedea0SLionel Sambuc close(s);
163ebfedea0SLionel Sambuc free(request);
164ebfedea0SLionel Sambuc return NULL;
165ebfedea0SLionel Sambuc }
166*0a6a1f1dSLionel Sambuc
167*0a6a1f1dSLionel Sambuc len = strlen(request);
168*0a6a1f1dSLionel Sambuc if(write(s, request, len) != (ssize_t)len) {
169ebfedea0SLionel Sambuc close(s);
170ebfedea0SLionel Sambuc free(request);
171ebfedea0SLionel Sambuc return NULL;
172ebfedea0SLionel Sambuc }
173ebfedea0SLionel Sambuc free(request);
174ebfedea0SLionel Sambuc while(1) {
175ebfedea0SLionel Sambuc n = read(s, buf + offset, sizeof(buf) - offset);
176ebfedea0SLionel Sambuc if(n <= 0)
177ebfedea0SLionel Sambuc break;
178ebfedea0SLionel Sambuc offset += n;
179ebfedea0SLionel Sambuc }
180ebfedea0SLionel Sambuc buf[offset] = '\0';
181ebfedea0SLionel Sambuc close(s);
182ebfedea0SLionel Sambuc p = strstr(buf, "\r\n\r\n"); /* find end of header */
183ebfedea0SLionel Sambuc if(p) p += 4;
184ebfedea0SLionel Sambuc else return NULL;
185ebfedea0SLionel Sambuc foo = NULL;
186ebfedea0SLionel Sambuc p = strtok_r(p, " \t\r\n", &foo);
187ebfedea0SLionel Sambuc if(p == NULL)
188ebfedea0SLionel Sambuc return NULL;
189ebfedea0SLionel Sambuc {
190ebfedea0SLionel Sambuc /* make a hostent to return */
191ebfedea0SLionel Sambuc #define MAX_ADDRS 16
192ebfedea0SLionel Sambuc static struct hostent he;
193ebfedea0SLionel Sambuc static char addrs[4 * MAX_ADDRS];
194ebfedea0SLionel Sambuc static char *addr_list[MAX_ADDRS + 1];
195ebfedea0SLionel Sambuc int num_addrs = 0;
196ebfedea0SLionel Sambuc
197ebfedea0SLionel Sambuc he.h_name = p;
198ebfedea0SLionel Sambuc he.h_aliases = NULL;
199ebfedea0SLionel Sambuc he.h_addrtype = AF_INET;
200ebfedea0SLionel Sambuc he.h_length = 4;
201ebfedea0SLionel Sambuc
202ebfedea0SLionel Sambuc while((p = strtok_r(NULL, " \t\r\n", &foo)) && num_addrs < MAX_ADDRS) {
203ebfedea0SLionel Sambuc struct in_addr ip;
204ebfedea0SLionel Sambuc inet_aton(p, &ip);
205ebfedea0SLionel Sambuc ip.s_addr = ntohl(ip.s_addr);
206ebfedea0SLionel Sambuc addr_list[num_addrs] = &addrs[num_addrs * 4];
207ebfedea0SLionel Sambuc addrs[num_addrs * 4 + 0] = (ip.s_addr >> 24) & 0xff;
208ebfedea0SLionel Sambuc addrs[num_addrs * 4 + 1] = (ip.s_addr >> 16) & 0xff;
209ebfedea0SLionel Sambuc addrs[num_addrs * 4 + 2] = (ip.s_addr >> 8) & 0xff;
210ebfedea0SLionel Sambuc addrs[num_addrs * 4 + 3] = (ip.s_addr >> 0) & 0xff;
211ebfedea0SLionel Sambuc addr_list[++num_addrs] = NULL;
212ebfedea0SLionel Sambuc }
213ebfedea0SLionel Sambuc he.h_addr_list = addr_list;
214ebfedea0SLionel Sambuc return &he;
215ebfedea0SLionel Sambuc }
216ebfedea0SLionel Sambuc }
217ebfedea0SLionel Sambuc
218ebfedea0SLionel Sambuc ROKEN_LIB_FUNCTION struct hostent* ROKEN_LIB_CALL
roken_gethostbyname(const char * hostname)219ebfedea0SLionel Sambuc roken_gethostbyname(const char *hostname)
220ebfedea0SLionel Sambuc {
221ebfedea0SLionel Sambuc struct hostent *he;
222ebfedea0SLionel Sambuc he = gethostbyname(hostname);
223ebfedea0SLionel Sambuc if(he)
224ebfedea0SLionel Sambuc return he;
225ebfedea0SLionel Sambuc return roken_gethostby(hostname);
226ebfedea0SLionel Sambuc }
227ebfedea0SLionel Sambuc
228ebfedea0SLionel Sambuc ROKEN_LIB_FUNCTION struct hostent* ROKEN_LIB_CALL
roken_gethostbyaddr(const void * addr,size_t len,int type)229ebfedea0SLionel Sambuc roken_gethostbyaddr(const void *addr, size_t len, int type)
230ebfedea0SLionel Sambuc {
231ebfedea0SLionel Sambuc struct in_addr a;
232ebfedea0SLionel Sambuc const char *p;
233ebfedea0SLionel Sambuc struct hostent *he;
234ebfedea0SLionel Sambuc he = gethostbyaddr(addr, len, type);
235ebfedea0SLionel Sambuc if(he)
236ebfedea0SLionel Sambuc return he;
237ebfedea0SLionel Sambuc if(type != AF_INET || len != 4)
238ebfedea0SLionel Sambuc return NULL;
239ebfedea0SLionel Sambuc p = addr;
240ebfedea0SLionel Sambuc a.s_addr = htonl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
241ebfedea0SLionel Sambuc return roken_gethostby(inet_ntoa(a));
242ebfedea0SLionel Sambuc }
243ebfedea0SLionel Sambuc
244ebfedea0SLionel Sambuc #if 0
245ebfedea0SLionel Sambuc
246ebfedea0SLionel Sambuc /* this program can be used as a cgi `script' to lookup names and
247ebfedea0SLionel Sambuc ip-addresses */
248ebfedea0SLionel Sambuc
249ebfedea0SLionel Sambuc #include <stdio.h>
250ebfedea0SLionel Sambuc #include <stdlib.h>
251ebfedea0SLionel Sambuc #include <netdb.h>
252ebfedea0SLionel Sambuc #include <sys/param.h>
253ebfedea0SLionel Sambuc
254ebfedea0SLionel Sambuc int
255ebfedea0SLionel Sambuc main(int argc, char **argv)
256ebfedea0SLionel Sambuc {
257ebfedea0SLionel Sambuc char *query = getenv("QUERY_STRING");
258ebfedea0SLionel Sambuc char host[MAXHOSTNAMELEN];
259ebfedea0SLionel Sambuc int i;
260ebfedea0SLionel Sambuc struct hostent *he;
261ebfedea0SLionel Sambuc
262ebfedea0SLionel Sambuc printf("Content-type: text/plain\n\n");
263ebfedea0SLionel Sambuc if(query == NULL)
264ebfedea0SLionel Sambuc exit(0);
265ebfedea0SLionel Sambuc he = gethostbyname(query);
266ebfedea0SLionel Sambuc strncpy(host, he->h_name, sizeof(host));
267ebfedea0SLionel Sambuc host[sizeof(host) - 1] = '\0';
268ebfedea0SLionel Sambuc he = gethostbyaddr(he->h_addr, he->h_length, AF_INET);
269ebfedea0SLionel Sambuc printf("%s\n", he->h_name);
270ebfedea0SLionel Sambuc for(i = 0; he->h_addr_list[i]; i++) {
271ebfedea0SLionel Sambuc struct in_addr ip;
272ebfedea0SLionel Sambuc unsigned char *p = (unsigned char*)he->h_addr_list[i];
273ebfedea0SLionel Sambuc ip.s_addr = htonl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
274ebfedea0SLionel Sambuc printf("%s\n", inet_ntoa(ip));
275ebfedea0SLionel Sambuc }
276ebfedea0SLionel Sambuc exit(0);
277ebfedea0SLionel Sambuc }
278ebfedea0SLionel Sambuc
279ebfedea0SLionel Sambuc #endif
280