155682Smarkm/* 2233294Sstas * Copyright (c) 1998 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 955682Smarkm * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 1655682Smarkm * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 2055682Smarkm * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include <config.h> 3555682Smarkm 36178825Sdfr#include "roken.h" 3755682Smarkm 3855682Smarkm#undef roken_gethostbyname 3955682Smarkm#undef roken_gethostbyaddr 4055682Smarkm 4155682Smarkmstatic struct sockaddr_in dns_addr; 4255682Smarkmstatic char *dns_req; 4355682Smarkm 4455682Smarkmstatic int 4555682Smarkmmake_address(const char *address, struct in_addr *ip) 4655682Smarkm{ 4755682Smarkm if(inet_aton(address, ip) == 0){ 4855682Smarkm /* try to resolve as hostname, it might work if the address we 4955682Smarkm are trying to lookup is local, for instance a web proxy */ 5055682Smarkm struct hostent *he = gethostbyname(address); 5155682Smarkm if(he) { 5255682Smarkm unsigned char *p = (unsigned char*)he->h_addr; 5355682Smarkm ip->s_addr = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; 5455682Smarkm } else { 5555682Smarkm return -1; 5655682Smarkm } 5755682Smarkm } 5855682Smarkm return 0; 5955682Smarkm} 6055682Smarkm 6155682Smarkmstatic int 6255682Smarkmsetup_int(const char *proxy_host, short proxy_port, 6355682Smarkm const char *dns_host, short dns_port, 6455682Smarkm const char *dns_path) 6555682Smarkm{ 6655682Smarkm memset(&dns_addr, 0, sizeof(dns_addr)); 6755682Smarkm if(dns_req) 6855682Smarkm free(dns_req); 69233294Sstas dns_req = NULL; 7055682Smarkm if(proxy_host) { 7155682Smarkm if(make_address(proxy_host, &dns_addr.sin_addr) != 0) 7255682Smarkm return -1; 7355682Smarkm dns_addr.sin_port = htons(proxy_port); 74233294Sstas if (asprintf(&dns_req, "http://%s:%d%s", dns_host, dns_port, dns_path) < 0) 75233294Sstas return -1; 7655682Smarkm } else { 7755682Smarkm if(make_address(dns_host, &dns_addr.sin_addr) != 0) 7855682Smarkm return -1; 7955682Smarkm dns_addr.sin_port = htons(dns_port); 8055682Smarkm asprintf(&dns_req, "%s", dns_path); 8155682Smarkm } 8255682Smarkm dns_addr.sin_family = AF_INET; 8355682Smarkm return 0; 8455682Smarkm} 8555682Smarkm 8655682Smarkmstatic void 8755682Smarkmsplit_spec(const char *spec, char **host, int *port, char **path, int def_port) 8855682Smarkm{ 8955682Smarkm char *p; 9055682Smarkm *host = strdup(spec); 9155682Smarkm p = strchr(*host, ':'); 9255682Smarkm if(p) { 9355682Smarkm *p++ = '\0'; 9455682Smarkm if(sscanf(p, "%d", port) != 1) 9555682Smarkm *port = def_port; 9655682Smarkm } else 9755682Smarkm *port = def_port; 9855682Smarkm p = strchr(p ? p : *host, '/'); 9955682Smarkm if(p) { 100233294Sstas if(path) 10155682Smarkm *path = strdup(p); 10255682Smarkm *p = '\0'; 10355682Smarkm }else 104233294Sstas if(path) 10555682Smarkm *path = NULL; 10655682Smarkm} 10755682Smarkm 10855682Smarkm 109233294SstasROKEN_LIB_FUNCTION int ROKEN_LIB_CALL 11055682Smarkmroken_gethostby_setup(const char *proxy_spec, const char *dns_spec) 11155682Smarkm{ 11255682Smarkm char *proxy_host = NULL; 113178825Sdfr int proxy_port = 0; 11455682Smarkm char *dns_host, *dns_path; 11555682Smarkm int dns_port; 116233294Sstas 11755682Smarkm int ret = -1; 118233294Sstas 11955682Smarkm split_spec(dns_spec, &dns_host, &dns_port, &dns_path, 80); 12055682Smarkm if(dns_path == NULL) 12155682Smarkm goto out; 12255682Smarkm if(proxy_spec) 12355682Smarkm split_spec(proxy_spec, &proxy_host, &proxy_port, NULL, 80); 12455682Smarkm ret = setup_int(proxy_host, proxy_port, dns_host, dns_port, dns_path); 12555682Smarkmout: 12655682Smarkm free(proxy_host); 12755682Smarkm free(dns_host); 12855682Smarkm free(dns_path); 12955682Smarkm return ret; 13055682Smarkm} 13155682Smarkm 132233294Sstas 13355682Smarkm/* Try to lookup a name or an ip-address using http as transport 13455682Smarkm mechanism. See the end of this file for an example program. */ 13555682Smarkmstatic struct hostent* 13655682Smarkmroken_gethostby(const char *hostname) 13755682Smarkm{ 13855682Smarkm int s; 139178825Sdfr struct sockaddr_in addr; 140233294Sstas char *request = NULL; 14155682Smarkm char buf[1024]; 14255682Smarkm int offset = 0; 14355682Smarkm int n; 14455682Smarkm char *p, *foo; 145233294Sstas size_t len; 146233294Sstas 14755682Smarkm if(dns_addr.sin_family == 0) 14855682Smarkm return NULL; /* no configured host */ 149178825Sdfr addr = dns_addr; 150233294Sstas if (asprintf(&request, "GET %s?%s HTTP/1.0\r\n\r\n", dns_req, hostname) < 0) 151233294Sstas return NULL; 15255682Smarkm if(request == NULL) 15355682Smarkm return NULL; 15455682Smarkm s = socket(AF_INET, SOCK_STREAM, 0); 15555682Smarkm if(s < 0) { 15655682Smarkm free(request); 15755682Smarkm return NULL; 15855682Smarkm } 159178825Sdfr if(connect(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) { 16055682Smarkm close(s); 16155682Smarkm free(request); 16255682Smarkm return NULL; 16355682Smarkm } 164233294Sstas 165233294Sstas len = strlen(request); 166233294Sstas if(write(s, request, len) != (ssize_t)len) { 16755682Smarkm close(s); 16855682Smarkm free(request); 16955682Smarkm return NULL; 17055682Smarkm } 17155682Smarkm free(request); 17255682Smarkm while(1) { 17355682Smarkm n = read(s, buf + offset, sizeof(buf) - offset); 17455682Smarkm if(n <= 0) 17555682Smarkm break; 17655682Smarkm offset += n; 17755682Smarkm } 17855682Smarkm buf[offset] = '\0'; 17955682Smarkm close(s); 18055682Smarkm p = strstr(buf, "\r\n\r\n"); /* find end of header */ 18155682Smarkm if(p) p += 4; 18255682Smarkm else return NULL; 18355682Smarkm foo = NULL; 18455682Smarkm p = strtok_r(p, " \t\r\n", &foo); 18555682Smarkm if(p == NULL) 18655682Smarkm return NULL; 18755682Smarkm { 18855682Smarkm /* make a hostent to return */ 18955682Smarkm#define MAX_ADDRS 16 19055682Smarkm static struct hostent he; 19155682Smarkm static char addrs[4 * MAX_ADDRS]; 192178825Sdfr static char *addr_list[MAX_ADDRS + 1]; 19355682Smarkm int num_addrs = 0; 194233294Sstas 19555682Smarkm he.h_name = p; 19655682Smarkm he.h_aliases = NULL; 19755682Smarkm he.h_addrtype = AF_INET; 19855682Smarkm he.h_length = 4; 199233294Sstas 20055682Smarkm while((p = strtok_r(NULL, " \t\r\n", &foo)) && num_addrs < MAX_ADDRS) { 20155682Smarkm struct in_addr ip; 20255682Smarkm inet_aton(p, &ip); 20355682Smarkm ip.s_addr = ntohl(ip.s_addr); 20455682Smarkm addr_list[num_addrs] = &addrs[num_addrs * 4]; 20555682Smarkm addrs[num_addrs * 4 + 0] = (ip.s_addr >> 24) & 0xff; 20655682Smarkm addrs[num_addrs * 4 + 1] = (ip.s_addr >> 16) & 0xff; 20755682Smarkm addrs[num_addrs * 4 + 2] = (ip.s_addr >> 8) & 0xff; 20855682Smarkm addrs[num_addrs * 4 + 3] = (ip.s_addr >> 0) & 0xff; 20955682Smarkm addr_list[++num_addrs] = NULL; 21055682Smarkm } 21155682Smarkm he.h_addr_list = addr_list; 21255682Smarkm return &he; 21355682Smarkm } 21455682Smarkm} 21555682Smarkm 216233294SstasROKEN_LIB_FUNCTION struct hostent* ROKEN_LIB_CALL 21755682Smarkmroken_gethostbyname(const char *hostname) 21855682Smarkm{ 21955682Smarkm struct hostent *he; 22055682Smarkm he = gethostbyname(hostname); 22155682Smarkm if(he) 22255682Smarkm return he; 22355682Smarkm return roken_gethostby(hostname); 22455682Smarkm} 22555682Smarkm 226233294SstasROKEN_LIB_FUNCTION struct hostent* ROKEN_LIB_CALL 22755682Smarkmroken_gethostbyaddr(const void *addr, size_t len, int type) 22855682Smarkm{ 22955682Smarkm struct in_addr a; 23055682Smarkm const char *p; 23155682Smarkm struct hostent *he; 23255682Smarkm he = gethostbyaddr(addr, len, type); 23355682Smarkm if(he) 23455682Smarkm return he; 23555682Smarkm if(type != AF_INET || len != 4) 23655682Smarkm return NULL; 23755682Smarkm p = addr; 23855682Smarkm a.s_addr = htonl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); 23955682Smarkm return roken_gethostby(inet_ntoa(a)); 24055682Smarkm} 24155682Smarkm 24255682Smarkm#if 0 24355682Smarkm 24455682Smarkm/* this program can be used as a cgi `script' to lookup names and 24555682Smarkm ip-addresses */ 24655682Smarkm 24755682Smarkm#include <stdio.h> 24855682Smarkm#include <stdlib.h> 24955682Smarkm#include <netdb.h> 25055682Smarkm#include <sys/param.h> 25155682Smarkm 25255682Smarkmint 25355682Smarkmmain(int argc, char **argv) 25455682Smarkm{ 25555682Smarkm char *query = getenv("QUERY_STRING"); 25655682Smarkm char host[MAXHOSTNAMELEN]; 25755682Smarkm int i; 25855682Smarkm struct hostent *he; 259233294Sstas 26055682Smarkm printf("Content-type: text/plain\n\n"); 26155682Smarkm if(query == NULL) 26255682Smarkm exit(0); 26355682Smarkm he = gethostbyname(query); 26455682Smarkm strncpy(host, he->h_name, sizeof(host)); 26555682Smarkm host[sizeof(host) - 1] = '\0'; 26655682Smarkm he = gethostbyaddr(he->h_addr, he->h_length, AF_INET); 26755682Smarkm printf("%s\n", he->h_name); 26855682Smarkm for(i = 0; he->h_addr_list[i]; i++) { 26955682Smarkm struct in_addr ip; 27055682Smarkm unsigned char *p = (unsigned char*)he->h_addr_list[i]; 27155682Smarkm ip.s_addr = htonl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); 27255682Smarkm printf("%s\n", inet_ntoa(ip)); 27355682Smarkm } 27455682Smarkm exit(0); 27555682Smarkm} 27655682Smarkm 27755682Smarkm#endif 278