From 60dfbf1b34a481cad28270883a87627dfd204799 Mon Sep 17 00:00:00 2001 From: "J. A. Bezemer" Date: Sun, 20 Sep 2009 21:10:39 +0000 Subject: [PATCH] merge dns and user #76 --- src/dns.c | 7 +++++++ src/iodined.c | 1 + src/user.c | 25 +++++++++++++++---------- src/user.h | 23 +++++++++++++++++++++++ 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/dns.c b/src/dns.c index 8f6cae8..80c31e8 100644 --- a/src/dns.c +++ b/src/dns.c @@ -356,6 +356,13 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz readshort(packet, &data, &type); readshort(packet, &data, &class); + /* if CHECKLEN okay, then we're sure to have a proper name */ + if (q != NULL) { + /* We only need the first char to check it */ + q->name[0] = name[0]; + q->name[1] = '\0'; + } + /* Assume that first answer is NULL/CNAME that we wanted */ readname(packet, packetlen, &data, name, sizeof(name)); CHECKLEN(10); diff --git a/src/iodined.c b/src/iodined.c index 6ce7d98..8babe62 100644 --- a/src/iodined.c +++ b/src/iodined.c @@ -376,6 +376,7 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len) users[userid].inpacket.seqno = 0; users[userid].inpacket.fragment = 0; users[userid].fragsize = 100; /* very safe */ + users[userid].conn = CONN_DNS_NULL; } else { /* No space for another user */ send_version_response(dns_fd, VERSION_FULL, created_users, 0, q); diff --git a/src/user.c b/src/user.c index 32b35c1..b2e8f04 100644 --- a/src/user.c +++ b/src/user.c @@ -78,14 +78,8 @@ init_users(in_addr_t my_ip, int netbits) users[i].disabled = 0; created_users++; } - users[i].inpacket.len = 0; - users[i].inpacket.offset = 0; - users[i].outpacket.len = 0; - users[i].q.id = 0; - users[i].out_acked_seqno = 0; - users[i].out_acked_fragment = 0; - users[i].fragsize = 4096; - users[i].conn = CONN_DNS_NULL; + users[i].active = 0; + /* Rest is reset on login ('V' packet) */ } return created_users; @@ -129,6 +123,11 @@ find_user_by_ip(uint32_t ip) int all_users_waiting_to_send() +/* If this returns true, then reading from tun device is blocked. + So only return true when all clients have at least one packet in + the outpacket-queue, so that sending back-to-back is possible + without going through another select loop. +*/ { time_t now; int ret; @@ -139,8 +138,14 @@ all_users_waiting_to_send() for (i = 0; i < USERS; i++) { if (users[i].active && !users[i].disabled && users[i].last_pkt + 60 > now && - ((users[i].outpacket.len == 0 && users[i].conn == CONN_DNS_NULL) - || users[i].conn == CONN_RAW_UDP)) { + ((users[i].conn == CONN_RAW_UDP) || + ((users[i].conn == CONN_DNS_NULL) +#ifdef OUTPACKETQ_LEN + && users[i].outpacketq_filled < 1 +#else + && users[i].outpacket.len == 0 +#endif + ))) { ret = 0; break; diff --git a/src/user.h b/src/user.h index 6058a8d..d3f81b4 100644 --- a/src/user.h +++ b/src/user.h @@ -19,6 +19,13 @@ #define USERS 16 +#define OUTPACKETQ_LEN 4 /* Note: 16 users * 1 packet = 1MB */ +/* Undefine to have no queue for packets coming in from tun device, which may + lead to massive dropping in multi-user situations with high traffic. */ + +#define DNSCACHE_LEN 4 +/* Undefine to disable. MUST be less than 7; also see comments in iodined.c */ + struct user { char id; int active; @@ -28,14 +35,30 @@ struct user { in_addr_t tun_ip; struct in_addr host; struct query q; + struct query q_prev; + struct query q_sendrealsoon; + int q_sendrealsoon_new; struct packet inpacket; struct packet outpacket; + int outfragresent; struct encoder *encoder; char downenc; int out_acked_seqno; int out_acked_fragment; int fragsize; enum connection conn; + int lazy; +#ifdef OUTPACKETQ_LEN + struct packet outpacketq[OUTPACKETQ_LEN]; + int outpacketq_nexttouse; + int outpacketq_filled; +#endif +#ifdef DNSCACHE_LEN + struct query dnscache_q[DNSCACHE_LEN]; + char dnscache_answer[DNSCACHE_LEN][4096]; + int dnscache_answerlen[DNSCACHE_LEN]; + int dnscache_lastfilled; +#endif }; extern struct user users[USERS];