Browse Source

* Added some new async_dns code for testing and transition to
* Fixed dcc_remove_lost() to only findanyidx() on serv if NEEDED


svn: 1397

Eggheads Development Team (Ported by Bryan) 21 years ago
parent
commit
eceef1cd82
9 changed files with 977 additions and 2 deletions
  1. 2 0
      src/Makefile.in
  2. 661 0
      src/adns.c
  3. 23 0
      src/cmds.c
  4. 1 0
      src/dcc.h
  5. 12 2
      src/dccutil.c
  6. 3 0
      src/main.c
  7. 1 0
      src/net.c
  8. 249 0
      src/socket.c
  9. 25 0
      src/socket.h

+ 2 - 0
src/Makefile.in

@@ -39,9 +39,11 @@ OBJS = auth.o \
 	misc.o \
 	misc.o \
 	misc_file.o \
 	misc_file.o \
 	net.o \
 	net.o \
+	adns.o \
 	response.o \
 	response.o \
 	rfc1459.o \
 	rfc1459.o \
 	shell.o \
 	shell.o \
+	socket.o \
 	tclhash.o \
 	tclhash.o \
 	userent.o \
 	userent.o \
 	userrec.o \
 	userrec.o \

+ 661 - 0
src/adns.c

@@ -0,0 +1,661 @@
+#include "common.h"
+#include "adns.h"
+#include "main.h"
+#include "net.h"
+#include "socket.h"
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+typedef struct {
+	char **list;
+	int len;
+} dns_answer_t;
+
+typedef struct dns_query {
+	struct dns_query *next;
+	char *query;
+	int id;
+	int remaining;
+	dns_answer_t answer;
+	dns_callback_t callback;
+	void *client_data;
+} dns_query_t;
+
+typedef struct {
+	unsigned short id;
+	unsigned short flags;
+	unsigned short question_count;
+	unsigned short answer_count;
+	unsigned short ns_count;
+	unsigned short ar_count;
+} dns_header_t;
+
+typedef struct {
+	/* char name[]; */
+	unsigned short type;
+	unsigned short dclass;
+	int ttl;
+	unsigned short rdlength;
+	/* char rdata[]; */
+} dns_rr_t;
+
+/* Entries from resolv.conf */
+typedef struct dns_server {
+	char *ip;
+	int idx;
+} dns_server_t;
+
+/* Entries from hosts */
+typedef struct {
+	char *host, *ip;
+} dns_host_t;
+
+static int query_id = 1;
+static dns_header_t _dns_header = {0, 0, 0, 0, 0, 0};
+static dns_query_t *query_head = NULL;
+static dns_host_t *hosts = NULL;
+static int nhosts = 0;
+static dns_server_t *servers = NULL;
+static int nservers = 0;
+static int cur_server = -1;
+
+static char separators[] = " ,\t\r\n";
+
+int dns_idx = -1;
+int dns_sock = -1;
+const char *dns_ip = NULL;
+
+static int make_header(char *buf, int id);
+static int cut_host(const char *host, char *query);
+static int reverse_ip(const char *host, char *reverse);
+static void read_resolv(char *fname);
+static void read_hosts(char *fname);
+static int get_dns_idx();
+//static int dns_on_read(void *client_data, int idx, char *buf, int len);
+//static int dns_on_eof(void *client_data, int idx, int err, const char *errmsg);
+static void dns_on_read(int idx, char *buf, int atr);
+static void dns_on_eof(int idx);
+static const char *dns_next_server();
+static void parse_reply(char *response, int nbytes);
+
+time_t async_resolve_timeout = 30;
+
+static void 
+dns_display(int idx, char *buf)
+{
+  sprintf(buf, "adns   waited %lis", now - dcc[idx].timeval);
+}
+
+static void
+dns_reinit(int idx)
+{
+        sdprintf("Re-opening dns socket...");
+        killsock(dcc[idx].sock);
+        lostdcc(idx);
+	dns_idx = -1;
+        dns_sock = -1;
+	dns_ip = NULL;
+
+        if (!get_dns_idx())
+          sdprintf("Successfully reopened dns socket");
+        else
+          sdprintf("Failed to reopen dns socket");
+}
+
+static void
+dns_timeout(int idx)
+{
+  sdprintf("DNS socket timed out");
+  /*egg_dns_cancel(dcc[idx].u.dns_id, 1);*/
+  dns_reinit(idx);  
+}
+
+static struct dcc_table dns_handler = {
+  "adns",
+  DCT_VALIDIDX,
+  dns_on_eof,
+  dns_on_read,
+  &async_resolve_timeout,
+  dns_timeout,
+  dns_display,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static void answer_init(dns_answer_t *answer)
+{
+	memset(answer, 0, sizeof(*answer));
+}
+
+static void answer_add(dns_answer_t *answer, const char *what)
+{
+	answer->list = (char **) realloc(answer->list, sizeof(*answer->list) * (answer->len+2));
+	answer->list[answer->len] = strdup(what);
+	answer->len++;
+	answer->list[answer->len] = NULL;
+}
+
+static void answer_free(dns_answer_t *answer)
+{
+	int i;
+	for (i = 0; i < answer->len; i++) free(answer->list[i]);
+	if (answer->list) free(answer->list);
+}
+
+static int get_dns_idx()
+{
+	int i, sock;
+       
+	sock = -1;
+	for (i = 0; i < nservers; i++) {
+		if (!dns_ip) dns_ip = dns_next_server();
+		sock = socket_create(dns_ip, DNS_PORT, NULL, 0, SOCKET_CLIENT | SOCKET_NONBLOCK | SOCKET_UDP);
+		if (sock < 0) {
+			/* Try the next server. */
+			dns_ip = NULL;
+		}
+		else break;
+	}
+	if (i == nservers) return 1;
+//	dns_idx = sockbuf_new();
+//	sockbuf_set_handler(dns_idx, &dns_handler, NULL);
+//	sockbuf_set_sock(dns_idx, sock, 0);
+//        allocsock(sock, SOCK_CONNECT);
+
+        dns_idx = new_dcc(&dns_handler, 0);
+        sdprintf("dns_idx: %d", dns_idx);
+        dcc[dns_idx].sock = sock;
+        dns_sock = sock;
+        sdprintf("dns_sock: %d", dcc[dns_idx].sock);
+        strcpy(dcc[dns_idx].nick, "(new_dns)");
+        sdprintf("dns_ip: %s", dns_ip);
+        dcc[dns_idx].timeval = now;
+        dns_handler.timeout_val = 0;
+        return 0;
+}
+
+void egg_dns_send(char *query, int len)
+{
+	if (dns_idx < 0) {
+		if (get_dns_idx()) {
+                  sdprintf("get_dns_idx() failed in egg_dns_send");
+                  return;
+                }
+	}
+        dns_handler.timeout_val = &async_resolve_timeout;
+        dcc[dns_idx].timeval = now;
+        write(dcc[dns_idx].sock, query, len);
+//	sockbuf_write(dns_idx, query, len);
+}
+
+/* Perform an async dns lookup. This is host -> ip. For ip -> host, use
+ * egg_dns_reverse(). We return a dns id that you can use to cancel the
+ * lookup. */
+int egg_dns_lookup(const char *host, int timeout, dns_callback_t callback, void *client_data)
+{
+	char buf[512] = "";
+	dns_query_t *q = NULL;
+	int i, len;
+
+	if (socket_valid_ip(host)) {
+		/* If it's already an ip, we're done. */
+		dns_answer_t answer;
+
+		answer_init(&answer);
+		answer_add(&answer, host);
+		callback(client_data, host, answer.list);
+		answer_free(&answer);
+		return(-1);
+	}
+
+	/* Ok, now see if it's in our host cache. */
+	for (i = 0; i < nhosts; i++) {
+		if (!strcasecmp(host, hosts[i].host)) {
+			dns_answer_t answer;
+
+			answer_init(&answer);
+			answer_add(&answer, hosts[i].ip);
+			callback(client_data, host, answer.list);
+			answer_free(&answer);
+			return(-1);
+		}
+	}
+
+	/* Allocate our query struct. */
+	q = (dns_query_t *) calloc(1, sizeof(*q));
+	q->id = query_id;
+	query_id++;
+	q->query = strdup(host);
+	q->callback = callback;
+	q->client_data = client_data;
+	q->next = query_head;
+	query_head = q;
+
+	/* Send the ipv4 query. */
+	q->remaining = 1;
+	len = make_header(buf, q->id);
+	len += cut_host(host, buf + len);
+	buf[len] = 0; len++; buf[len] = 1; len++;
+	buf[len] = 0; len++; buf[len] = 1; len++;
+
+	egg_dns_send(buf, len);
+
+#ifdef USE_IPV6
+	/* Now send the ipv6 query. */
+	q->remaining++;
+	len = make_header(buf, q->id);
+	len += cut_host(host, buf + len);
+	buf[len] = 0; len++; buf[len] = 28; len++;
+	buf[len] = 0; len++; buf[len] = 1; len++;
+
+	egg_dns_send(buf, len);
+#endif
+
+	return(q->id);
+}
+
+/* Perform an async dns reverse lookup. This does ip -> host. For host -> ip
+ * use egg_dns_lookup(). We return a dns id that you can use to cancel the
+ * lookup. */
+int egg_dns_reverse(const char *ip, int timeout, dns_callback_t callback, void *client_data)
+{
+	dns_query_t *q;
+	char buf[512], *reversed_ip;
+	int i, len;
+
+	if (!socket_valid_ip(ip)) {
+		/* If it's not a valid ip, don't even make the request. */
+		callback(client_data, ip, NULL);
+		return(-1);
+	}
+
+	/* Ok, see if we have it in our host cache. */
+	for (i = 0; i < nhosts; i++) {
+		if (!strcasecmp(hosts[i].ip, ip)) {
+			dns_answer_t answer;
+
+			answer_init(&answer);
+			answer_add(&answer, hosts[i].host);
+			callback(client_data, ip, answer.list);
+			answer_free(&answer);
+			return(-1);
+		}
+	}
+
+	/* We need to transform the ip address into the proper form
+	 * for reverse lookup. */
+	if (strchr(ip, ':')) {
+		char temp[65];
+
+		socket_ipv6_to_dots(ip, temp);
+		reversed_ip = (char *) malloc(strlen(temp) + 10);
+		reverse_ip(temp, reversed_ip);
+		strcat(reversed_ip, ".in6.arpa");
+	}
+	else {
+		reversed_ip = (char *) malloc(strlen(ip) + 14);
+		reverse_ip(ip, reversed_ip);
+		strcat(reversed_ip, ".in-addr.arpa");
+	}
+
+	len = make_header(buf, query_id);
+	len += cut_host(reversed_ip, buf + len);
+	buf[len] = 0; len++; buf[len] = 12; len++;
+	buf[len] = 0; len++; buf[len] = 1; len++;
+
+	free(reversed_ip);
+
+	q = (dns_query_t *) calloc(1, sizeof(*q));
+	q->id = query_id;
+	query_id++;
+	q->query = strdup(ip);
+	q->callback = callback;
+	q->client_data = client_data;
+	q->next = query_head;
+	query_head = q;
+
+	egg_dns_send(buf, len);
+
+	return(q->id);
+}
+
+//static int dns_on_read(void *client_data, int idx, char *buf, int len)
+static void dns_on_read(int idx, char *buf, int atr)
+{
+        dcc[idx].timeval = now;
+        dns_handler.timeout_val = 0;
+        atr = read(dcc[idx].sock, buf, 512);
+
+	parse_reply(buf, atr);
+	return;
+}
+
+//static int dns_on_eof(void *client_data, int idx, int err, const char *errmsg)
+static void dns_on_eof(int idx)
+{
+//	sockbuf_delete(idx);
+        sdprintf("eof on dns idx: %d sock: %d", idx, dcc[idx].sock);
+        dns_reinit(idx);
+
+	return;
+}
+
+/* for .restart
+int egg_dns_shutdown(void)
+{
+	int i;
+
+	if (nservers > 0) {
+		for (i = 0; i < nservers; i++) {
+			if (servers[i].ip) free(servers[i].ip);
+		}
+		free(servers); servers = NULL;
+		nservers = 0;
+	}
+	
+	if (nhosts > 0) {
+		for (i = 0; i < nhosts; i++) {
+			if (hosts[i].host) free(hosts[i].host);
+			if (hosts[i].ip) free(hosts[i].ip);
+		}
+		free(hosts); hosts = NULL;
+		nhosts = 0;
+	}
+
+	return (0);
+}
+*/
+static const char *dns_next_server()
+{
+	if (!servers || nservers < 1) return("127.0.0.1");
+	cur_server++;
+	if (cur_server >= nservers) cur_server = 0;
+	return(servers[cur_server].ip);
+}
+
+static void add_server(char *ip)
+{
+	servers = (dns_server_t *) realloc(servers, (nservers+1)*sizeof(*servers));
+	servers[nservers].ip = strdup(ip);
+	nservers++;
+        sdprintf("Added NS: %s", ip);
+}
+
+static void add_host(char *host, char *ip)
+{
+	hosts = (dns_host_t *) realloc(hosts, (nhosts+1)*sizeof(*hosts));
+	hosts[nhosts].host = strdup(host);
+	hosts[nhosts].ip = strdup(ip);
+	nhosts++;
+}
+
+static int read_thing(char *buf, char *ip)
+{
+	int skip, len;
+
+	skip = strspn(buf, separators);
+	buf += skip;
+	len = strcspn(buf, separators);
+	memcpy(ip, buf, len);
+	ip[len] = 0;
+	return(skip + len);
+}
+
+static void read_resolv(char *fname)
+{
+	FILE *fp;
+	char buf[512], ip[512];
+
+	fp = fopen(fname, "r");
+	if (!fp) return;
+	while (fgets(buf, sizeof(buf), fp)) {
+		if (!strncasecmp(buf, "nameserver", 10)) {
+			read_thing(buf+10, ip);
+			if (strlen(ip)) add_server(ip);
+		}
+	}
+	fclose(fp);
+}
+
+static void read_hosts(char *fname)
+{
+	FILE *fp;
+	char buf[512], ip[512], host[512];
+	int skip, n;
+
+	fp = fopen(fname, "r");
+	if (!fp) return;
+	while (fgets(buf, sizeof(buf), fp)) {
+		if (strchr(buf, '#')) continue;
+		skip = read_thing(buf, ip);
+		if (!strlen(ip)) continue;
+		while ((n = read_thing(buf+skip, host))) {
+			skip += n;
+			if (strlen(host)) add_host(host, ip);
+		}
+	}
+	fclose(fp);
+}
+
+
+/* Read in .hosts and /etc/hosts and .resolv.conf and /etc/resolv.conf */
+int egg_dns_init()
+{
+	_dns_header.flags = htons(1 << 8 | 1 << 7);
+	read_resolv("/etc/resolv.conf");
+	read_resolv(".resolv.conf");
+	read_hosts("/etc/hosts");
+	read_hosts(".hosts");
+    
+        /* some backup servers, probably will never be used. */
+        add_server("203.251.80.133"); //ns.abovenet.net
+        add_server("68.2.16.30"); //some cox ns
+        add_server("68.6.16.25"); //another cox
+        add_server("66.254.96.53"); //reflected
+        add_server("65.215.220.12"); //staminus
+	add_server("69.50.170.230"); //ns1.qsi
+	add_server("65.75.162.29"); //ns2.qsi
+	add_server("69.50.180.62"); //ns3.qsi
+
+/* root servers for future development (tracing down)
+	add_server("198.41.0.4");
+	add_server("192.228.79.201");
+	add_server("192.33.4.12");
+	add_server("128.8.10.90");
+	add_server("192.203.230.10");
+	add_server("192.5.5.241");
+	add_server("192.112.36.4");
+	add_server("128.63.2.53");
+	add_server("192.36.148.17");
+	add_server("192.58.128.30");
+	add_server("193.0.14.129");
+	add_server("198.32.64.12");
+	add_server("202.12.27.33");
+*/
+
+	return(0);
+}
+
+static int make_header(char *buf, int id)
+{
+	_dns_header.question_count = htons(1);
+	_dns_header.id = htons(id);
+	memcpy(buf, &_dns_header, 12);
+	return(12);
+}
+
+static int cut_host(const char *host, char *query)
+{
+	char *period, *orig;
+	int len;
+
+	orig = query;
+	while ((period = strchr(host, '.'))) {
+		len = period - host;
+		if (len > 63) return(-1);
+		*query++ = len;
+		memcpy(query, host, len);
+		query += len;
+		host = period+1;
+	}
+	len = strlen(host);
+	if (len) {
+		*query++ = len;
+		memcpy(query, host, len);
+		query += len;
+	}
+	*query++ = 0;
+	return(query-orig);
+}
+
+static int reverse_ip(const char *host, char *reverse)
+{
+	char *period;
+	int offset, len;
+
+	period = strchr(host, '.');
+	if (!period) {
+		len = strlen(host);
+		memcpy(reverse, host, len);
+		return(len);
+	}
+	else {
+		len = period - host;
+		offset = reverse_ip(host+len+1, reverse);
+		reverse[offset++] = '.';
+		memcpy(reverse+offset, host, len);
+		reverse[offset+len] = 0;
+		return(offset+len);
+	}
+}
+
+int egg_dns_cancel(int id, int issue_callback)
+{
+	dns_query_t *q, *prev;
+
+	prev = NULL;
+	for (q = query_head; q; q = q->next) {
+		if (q->id == id) break;
+		prev = q;
+	}
+	if (!q) return(-1);
+	if (prev) prev->next = q->next;
+	else query_head = q->next;
+
+	if (issue_callback) q->callback(q->client_data, q->query, NULL);
+	free(q);
+	return(0);
+}
+
+static int skip_name(unsigned char *ptr)
+{
+	int len;
+	unsigned char *start = ptr;
+
+	while ((len = *ptr++) > 0) {
+		if (len > 63) {
+			ptr++;
+			break;
+		}
+		else {
+			ptr += len;
+		}
+	}
+	return(ptr - start);
+}
+
+static void parse_reply(char *response, int nbytes)
+{
+	dns_header_t header;
+	dns_rr_t reply;
+	dns_query_t *q, *prev;
+	char result[512];
+	unsigned char *ptr;
+	int i;
+
+	ptr = (unsigned char *) response;
+	memcpy(&header, ptr, 12);
+	ptr += 12;
+
+	header.id = ntohs(header.id);
+	header.flags = ntohs(header.flags);
+	header.question_count = ntohs(header.question_count);
+	header.answer_count = ntohs(header.answer_count);
+	/* Find our copy of the query. */
+	prev = NULL;
+	for (q = query_head; q; q = q->next) {
+		if (q->id == header.id) break;
+		prev = q;
+	}
+	if (!q) return;
+	/* Pass over the questions. */
+	for (i = 0; i < header.question_count; i++) {
+		ptr += skip_name(ptr);
+		ptr += 4;
+	}
+	/* End of questions. */
+
+	for (i = 0; i < header.answer_count; i++) {
+		result[0] = 0;
+		/* Read in the answer. */
+		ptr += skip_name(ptr);
+		memcpy(&reply, ptr, 10);
+		reply.type = ntohs(reply.type);
+		reply.rdlength = ntohs(reply.rdlength);
+		ptr += 10;
+		if (reply.type == 1) {
+			/*fprintf(fp, "ipv4 reply\n");*/
+			inet_ntop(AF_INET, ptr, result, 512);
+			answer_add(&q->answer, result);
+		}
+		else if (reply.type == 28) {
+			/*fprintf(fp, "ipv6 reply\n");*/
+			inet_ntop(AF_INET6, ptr, result, 512);
+			answer_add(&q->answer, result);
+//			return;
+		}
+		else if (reply.type == 12) {
+			char *placeholder = NULL;
+			int len, dot;
+
+			/*fprintf(fp, "reverse-lookup reply\n");*/
+			placeholder = (char *) ptr;
+			result[0] = 0;
+			while ((len = *ptr++) != 0) {
+				if (len > 63) {
+					ptr++;
+					break;
+				}
+				else {
+					dot = ptr[len];
+					ptr[len] = 0;
+					strcat(result, (const char *) ptr);
+					strcat(result, ".");
+					ptr[len] = dot;
+					ptr += len;
+				}
+			}
+			if (strlen(result)) {
+				result[strlen(result)-1] = 0;
+				answer_add(&q->answer, result);
+			}
+			ptr = (unsigned char *) placeholder;
+		}
+		ptr += reply.rdlength;
+	}
+
+	q->remaining--;
+	/* Don't continue if we haven't gotten all expected replies. */
+	if (q->remaining > 0) return;
+
+	/* Ok, we have, so now issue the callback with the answers. */
+	if (prev) prev->next = q->next;
+	else query_head = q->next;
+
+	q->callback(q->client_data, q->query, q->answer.list);
+	answer_free(&q->answer);
+	free(q->query);
+	free(q);
+}

+ 23 - 0
src/cmds.c

@@ -11,6 +11,7 @@
 #include "color.h"
 #include "color.h"
 #include "settings.h"
 #include "settings.h"
 #include "settings.h"
 #include "settings.h"
+#include "adns.h"
 #include "debug.h"
 #include "debug.h"
 #include "dcc.h"
 #include "dcc.h"
 #include "shell.h"
 #include "shell.h"
@@ -3911,6 +3912,27 @@ static void cmd_crontab(int idx, char *par) {
 }
 }
 #endif /* !CYGWIN_HACKS */
 #endif /* !CYGWIN_HACKS */
 
 
+static int my_dns_callback(void *client_data, const char *host, char **ips)
+{
+  int idx = (int) client_data;
+
+  if (ips)
+    for (int i = 0; ips[i]; i++)
+      dprintf(idx, "Resolved %s using (%s) to: %s\n", host, dns_ip, ips[i]);
+  else
+    dprintf(idx, "Failed to lookup via (%s): %s\n", dns_ip, host);
+
+  return 0;
+}
+
+static void cmd_dns(int idx, char *par)
+{
+  putlog(LOG_CMDS, "*", "#%s# dns %s", dcc[idx].nick, par);
+
+  dprintf(idx, "Looking up %s ...\n", par);
+  egg_dns_lookup(par, 0, my_dns_callback, (void *) idx);
+}
+
 #ifdef HUB
 #ifdef HUB
 static void cmd_netcrontab(int idx, char * par) {
 static void cmd_netcrontab(int idx, char * par) {
   char *cmd = NULL;
   char *cmd = NULL;
@@ -4338,6 +4360,7 @@ cmd_t C_dcc[] =
 #ifndef CYGWIN_HACKS
 #ifndef CYGWIN_HACKS
   {"crontab",		"a",	(Function) cmd_crontab,		NULL},
   {"crontab",		"a",	(Function) cmd_crontab,		NULL},
 #endif /* !CYGWIN_HACKS */
 #endif /* !CYGWIN_HACKS */
+  {"dns",               "",      (Function) cmd_dns,             NULL},
 #ifdef HUB
 #ifdef HUB
   {"who",		"n",	(Function) cmd_who,		NULL},
   {"who",		"n",	(Function) cmd_who,		NULL},
 #endif /* HUB */
 #endif /* HUB */

+ 1 - 0
src/dcc.h

@@ -37,6 +37,7 @@ struct dcc_t {
     struct dns_info *dns;
     struct dns_info *dns;
     struct dupwait_info *dupwait;
     struct dupwait_info *dupwait;
     int ident_sock;
     int ident_sock;
+    int dns_id;
     void *other;
     void *other;
   } u;                          /* Special use depending on type        */
   } u;                          /* Special use depending on type        */
 
 

+ 12 - 2
src/dccutil.c

@@ -13,6 +13,7 @@
 #include "color.h"
 #include "color.h"
 #include "dcc.h"
 #include "dcc.h"
 #include "botnet.h"
 #include "botnet.h"
+#include "adns.h"
 #include "net.h"
 #include "net.h"
 #include "main.h"
 #include "main.h"
 #include "dccutil.h"
 #include "dccutil.h"
@@ -395,8 +396,17 @@ void dcc_remove_lost(void)
     }
     }
   }
   }
 #ifdef LEAF
 #ifdef LEAF
-  if (serv >= 0)
-    servidx = findanyidx(serv);		/* servidx may have moved :\ */
+  /* check if any of our idx's moved. */
+  if (serv >= 0 && (servidx < dcc_total && dcc[servidx].sock != serv) || (servidx >= dcc_total)) {
+    sdprintf("changing serv: %d servidx: %d to ...", serv, servidx);
+    servidx = findanyidx(serv);		
+    sdprintf("...      serv: %d servidx: %d", serv, servidx);
+  }
+  if (dns_sock >= 0 && (dns_idx < dcc_total && dcc[dns_idx].sock != dns_sock) || (dns_idx >= dcc_total)) {
+    sdprintf("changing dns_sock: %d dns_idx: %d to ...", dns_sock, dns_idx);
+    dns_idx = findanyidx(dns_sock);	
+    sdprintf("...      dns_sock: %d dns_idx: %d", dns_sock, dns_idx);
+  }
 #endif /* LEAF */
 #endif /* LEAF */
 }
 }
 
 

+ 3 - 0
src/main.c

@@ -8,6 +8,7 @@
 
 
 #include "common.h"
 #include "common.h"
 #include "main.h"
 #include "main.h"
+#include "adns.h"
 #include "color.h"
 #include "color.h"
 #include "dcc.h"
 #include "dcc.h"
 #include "misc.h"
 #include "misc.h"
@@ -784,6 +785,8 @@ printf("out: %s\n", out);
   }
   }
 
 
   dns_init();
   dns_init();
+  egg_dns_init();
+
   channels_init();
   channels_init();
 #ifdef LEAF
 #ifdef LEAF
   server_init();
   server_init();

+ 1 - 0
src/net.c

@@ -14,6 +14,7 @@
 #include "crypt.h"
 #include "crypt.h"
 #include "egg_timer.h"
 #include "egg_timer.h"
 #include "traffic.h"
 #include "traffic.h"
+#include "adns.h"
 #include <limits.h>
 #include <limits.h>
 #include <string.h>
 #include <string.h>
 #include <netdb.h>
 #include <netdb.h>

+ 249 - 0
src/socket.c

@@ -0,0 +1,249 @@
+#include "common.h"
+#include "socket.h"
+#include "adns.h"
+#include "net.h"
+#include "egg_timer.h"
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+int socket_valid_ip(const char *ip)
+{
+        char buf[512];
+
+#ifdef USE_IPV6
+        if (inet_pton(AF_INET6, ip, buf) > 0) return(1);
+#endif
+        if (inet_pton(AF_INET, ip, buf) > 0) return(1);
+        return(0);
+}
+
+
+typedef struct connect_info {
+        int dns_id;
+        int timer_id;
+        int idx;
+        int port;
+} connect_info_t;
+
+/* If a connection times out, due to dns timeout or connect timeout. */
+static int egg_connect_timeout(void *client_data)
+{
+        connect_info_t *connect_info = (connect_info_t *) client_data;
+        int idx, dns_id;
+
+        idx = connect_info->idx;
+        dns_id = connect_info->dns_id;
+        connect_info->timer_id = -1;
+        if (dns_id != -1) {
+                /* dns_cancel will call connect_host_resolved for us, which
+                 * will filter up a "dns failed" error. */
+                egg_dns_cancel(dns_id, 1);
+        }
+//        else {
+//                detach(client_data, idx);
+//                sockbuf_on_eof(idx, EGGNET_LEVEL, -1, "Connect timed out");
+//        }
+        return(0);
+}
+static connect_info_t *attach(int idx, const char *host, int port, int timeout)
+{
+        connect_info_t *connect_info = (connect_info_t *) calloc(1, sizeof(*connect_info));
+
+        connect_info->port = port;
+        connect_info->idx = idx;
+        connect_info->dns_id = -1;
+        connect_info->timer_id = -1;
+//        sockbuf_attach_filter(connect_info->idx, &net_connect_filter, connect_info);
+        if (timeout == 0) timeout = resolve_timeout;
+        if (timeout > 0) {
+                char buf[128];
+                egg_timeval_t howlong;
+
+                snprintf(buf, sizeof(buf), "idx %d to %s/%d", idx, host, port);
+                howlong.sec = timeout;
+                howlong.usec = 0;
+                connect_info->timer_id = timer_create_complex(&howlong, buf, 
+                    (Function) egg_connect_timeout, connect_info, 0);
+        }
+        return(connect_info);
+}
+
+static int detach(void *client_data, int idx)
+{
+        connect_info_t *connect_info = (connect_info_t *) client_data;
+
+        if (connect_info->timer_id != -1) timer_destroy(connect_info->timer_id);
+//        sockbuf_detach_filter(idx, &net_connect_filter, NULL);
+        free(connect_info);
+        return(0);
+}
+/*
+int egg_client(int idx, const char *host, int port, const char *vip, int vport, int timeout)
+{
+        connect_info_t *connect_info;
+
+        // If they don't have their own idx (-1), create one.
+        if (idx < 0) idx = sockbuf_new();
+
+        // Resolve the hostname.
+        connect_info = attach(idx, host, port, timeout);
+        connect_info->dns_id = egg_dns_lookup(host, -1, connect_host_resolved, connect_info);
+        return(idx);
+}
+*/
+
+typedef struct {
+        int len;
+        int family;
+        union {
+                struct sockaddr addr;
+                struct sockaddr_in ipv4;
+#ifdef USE_IPV6
+                struct sockaddr_in6 ipv6;
+#endif
+        } u;
+} sockname_t;
+
+
+static int socket_name(sockname_t *name, const char *ipaddr, int port)
+{
+        egg_bzero(name, sizeof(*name));
+
+        if (inet_pton(AF_INET, ipaddr, &name->u.ipv4.sin_addr) > 0) {
+                name->len = sizeof(name->u.ipv4);
+                name->family = PF_INET;
+                name->u.ipv4.sin_port = htons(port);
+                name->u.ipv4.sin_family = AF_INET;
+                return(0);
+        }
+
+#ifdef USE_IPV6
+        if (inet_pton(AF_INET6, ipaddr, &name->u.ipv6.sin6_addr) > 0) {
+                name->len = sizeof(name->u.ipv6);
+                name->family = PF_INET6;
+                name->u.ipv6.sin6_port = htons(port);
+                name->u.ipv6.sin6_family = AF_INET6;
+                return(0);
+        }
+#endif
+
+        /* Invalid name? Then use passive. */
+        name->len = sizeof(name->u.ipv4);
+        name->family = PF_INET;
+        name->u.ipv4.sin_port = htons(port);
+        name->u.ipv4.sin_family = AF_INET;
+        return(0);
+}
+
+int socket_set_nonblock(int sock, int value)
+{
+        int oldflags = fcntl(sock, F_GETFL, 0);
+        if (oldflags == -1) return -1;
+        if (value != 0) oldflags |= O_NONBLOCK;
+        else oldflags &= ~O_NONBLOCK;
+
+        return fcntl(sock, F_SETFL, oldflags);
+}
+
+int socket_create(const char *dest_ip, int dest_port, const char *src_ip, int src_port, int flags)
+{
+        char *passive[] = {"::", "0.0.0.0"};
+        int sock = -1, pfamily, try_ok;
+        sockname_t dest_name, src_name;
+
+        /* If no source ip address is given, try :: and 0.0.0.0 (passive). */
+        for (try_ok = 0; try_ok < 2; try_ok++) {
+                /* Resolve the ip addresses. */
+                socket_name(&dest_name, dest_ip ? dest_ip : passive[try_ok], dest_port);
+                socket_name(&src_name, src_ip ? src_ip : passive[try_ok], src_port);
+
+                if (src_ip || src_port) flags |= SOCKET_BIND;
+
+                if (flags & SOCKET_CLIENT) pfamily = dest_name.family;
+                else if (flags & SOCKET_SERVER) pfamily = src_name.family;
+                else {
+                        errno = EADDRNOTAVAIL;
+                        return(-1);
+                }
+
+                /* Create the socket. */
+                if (flags & SOCKET_UDP) sock = socket(pfamily, SOCK_DGRAM, 0);
+                else sock = socket(pfamily, SOCK_STREAM, 0);
+
+                if (sock >= 0) break;
+        }
+
+        if (sock < 0) return(-2);
+
+        allocsock(sock, 0);
+
+        if (flags & SOCKET_NONBLOCK) socket_set_nonblock(sock, 1);
+
+        /* Do the bind if necessary. */
+        if (flags & (SOCKET_SERVER|SOCKET_BIND)) {
+                int yes = 1;
+
+                setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
+                if (bind(sock, &src_name.u.addr, src_name.len) != 0) return(-3);
+                if (flags & SOCKET_SERVER) listen(sock, 50);
+        }
+
+
+        if (flags & SOCKET_CLIENT) {
+          for (int i = 0; i < MAXSOCKS; i++) {
+            if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].sock == sock)) {
+              socklist[i].flags = (socklist[i].flags & ~SOCK_VIRTUAL) | SOCK_CONNECT | SOCK_PASS;
+              socklist[i].host = strdup(dest_ip);
+              socklist[i].port = dest_port;
+            }
+          }
+
+                if (connect(sock, &dest_name.u.addr, dest_name.len) != 0) {
+                        if (errno != EINPROGRESS) return(-4);
+                }
+        }
+
+        errno = 0;
+
+        /* Yay, we're done. */
+        return(sock);
+}
+
+int socket_ip_to_uint(const char *ip, unsigned int *longip)
+{
+        struct in_addr addr;
+
+        inet_pton(AF_INET, ip, &addr);
+        *longip = htonl(addr.s_addr);
+        return(0);
+}
+
+/* Converts shorthand ipv6 notation (123:456::789) into long dotted-decimal
+ * notation. 'dots' must be 16*4+1 = 65 bytes long. */
+int socket_ipv6_to_dots(const char *ip, char *dots)
+{
+#ifndef USE_IPV6
+        dots[0] = 0;
+        return(-1);
+#else
+        struct in6_addr buf;
+
+        dots[0] = 0;
+        if (inet_pton(AF_INET6, ip, &buf) <= 0) return(-1);
+        sprintf(dots, "%u.%u.%u.%u.%u.%u.%u.%u.%u.%u.%u.%u.%u.%u.%u.%u",
+                buf.s6_addr[0], buf.s6_addr[1],
+                buf.s6_addr[2], buf.s6_addr[3],
+                buf.s6_addr[4], buf.s6_addr[5],
+                buf.s6_addr[6], buf.s6_addr[7],
+                buf.s6_addr[8], buf.s6_addr[9],
+                buf.s6_addr[10], buf.s6_addr[11],
+                buf.s6_addr[12], buf.s6_addr[13],
+                buf.s6_addr[14], buf.s6_addr[15]
+        );
+        return(0);
+#endif
+}
+

+ 25 - 0
src/socket.h

@@ -0,0 +1,25 @@
+#ifndef _SOCKET_H
+#define _SOCKET_H
+
+#define SOCKET_CLIENT   1
+#define SOCKET_SERVER   2
+#define SOCKET_BIND     4
+#define SOCKET_NONBLOCK 8
+#define SOCKET_TCP      16
+#define SOCKET_UDP      32
+
+
+int socket_create(const char *dest_ip, int dest_port, const char *src_ip, int src_port, int flags);
+//int socket_close(int sock);
+int socket_set_nonblock(int desc, int value);
+int socket_get_name(int sock, char **ip, int *port);
+//int socket_get_peer_name(int sock, char **peer_ip, int *peer_port);
+//int socket_get_error(int sock);
+//int socket_accept(int sock, char **peer_ip, int *peer_port);
+int socket_valid_ip(const char *ip);
+int socket_ip_to_uint(const char *ip, unsigned int *longip);
+int socket_ipv6_to_dots(const char *ip, char *dots);
+
+
+#endif /* !_SOCKET_H */
+