From 5532a0ea67357b4b652b556eb21eed96a606b2ff Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Wed, 7 Feb 2007 10:08:55 +0000 Subject: [PATCH] BSD needs: addrlen set when calling recvfrom. And it has length/padding for sockaddr structures. git-svn-id: file:///svn/unbound/trunk@72 be551aaa-1e26-0410-a405-d3ace91eadb9 --- doc/Changelog | 2 ++ services/listen_dnsport.c | 7 ++-- services/outside_network.c | 66 +++++++++++++++++++++++++++++++++++++- util/netevent.c | 1 + 4 files changed, 73 insertions(+), 3 deletions(-) diff --git a/doc/Changelog b/doc/Changelog index 226952be2..33a892ce4 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -3,6 +3,8 @@ - created udp forwarder test. I've done some effort to make it perform quickly. After servers are created, no big sleep statements but it checks the logfiles to see if servers have come up. Takes 0.14s. + - set addrlen value when calling recvfrom. + - comparison of addrs more portable. 6 February 2007: Wouter - reviewed code and improved in places. diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c index f28490400..c72dc6e35 100644 --- a/services/listen_dnsport.c +++ b/services/listen_dnsport.c @@ -65,8 +65,11 @@ verbose_print_addr(struct addrinfo *addr) { if(verbosity >= VERB_ALGO) { char buf[100]; - if(inet_ntop(addr->ai_family, - &((struct sockaddr_in*)addr->ai_addr)->sin_addr, buf, + void* sinaddr = &((struct sockaddr_in*)addr->ai_addr)->sin_addr; + if(addr->ai_family == AF_INET6) + sinaddr = &((struct sockaddr_in6*)addr->ai_addr)-> + sin6_addr; + if(inet_ntop(addr->ai_family, sinaddr, buf, (socklen_t)sizeof(buf)) == 0) { strncpy(buf, "(null)", sizeof(buf)); } diff --git a/services/outside_network.c b/services/outside_network.c index a93456c1a..dd349a489 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -55,12 +55,45 @@ /** number of times to retry making a random ID that is unique. */ #define MAX_ID_RETRY 1000 +/** send addr to logfile */ +static void +log_addr(struct sockaddr_storage* addr, socklen_t addrlen) +{ + uint16_t port; + const char* family = "unknown"; + char dest[100]; + int af = ((struct sockaddr_in*)addr)->sin_family; + void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; + switch(af) { + case AF_INET: family="ip4"; break; + case AF_INET6: family="ip6"; + sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; + break; + case AF_UNIX: family="unix"; break; + default: break; + } + if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { + strncpy(dest, "(inet_ntop error)", sizeof(dest)); + } + port = ntohs(((struct sockaddr_in*)addr)->sin_port); + log_info("addr fam=%s port=%d dest=%s len=%d", + family, (int)port, dest, (int)addrlen); +} + /** compare function of pending rbtree */ static int pending_cmp(const void* key1, const void* key2) { struct pending *p1 = (struct pending*)key1; struct pending *p2 = (struct pending*)key2; + struct sockaddr_in* p1_in = (struct sockaddr_in*)&p1->addr; + struct sockaddr_in* p2_in = (struct sockaddr_in*)&p2->addr; + struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)&p1->addr; + struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)&p2->addr; +/** byte size of ip4 address */ +#define INET_SIZE 4 +/** byte size of ip6 address */ +#define INET6_SIZE 16 if(p1->id < p2->id) return -1; if(p1->id > p2->id) @@ -71,7 +104,33 @@ pending_cmp(const void* key1, const void* key2) if(p1->addrlen > p2->addrlen) return 1; log_assert(p1->addrlen == p2->addrlen); - return memcmp(&p1->addr, &p2->addr, p1->addrlen); + if( p1_in->sin_family < p2_in->sin_family) + return -1; + if( p1_in->sin_family > p2_in->sin_family) + return 1; + log_assert( p1_in->sin_family == p2_in->sin_family ); + /* compare ip4 */ + if( p1_in->sin_family == AF_INET ) { + /* just order it, ntohs not required */ + if(p1_in->sin_port < p2_in->sin_port) + return -1; + if(p1_in->sin_port > p2_in->sin_port) + return 1; + log_assert(p1_in->sin_port == p2_in->sin_port); + return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); + } else if (p1_in6->sin6_family == AF_INET6) { + /* just order it, ntohs not required */ + if(p1_in6->sin6_port < p2_in6->sin6_port) + return -1; + if(p1_in6->sin6_port > p2_in6->sin6_port) + return 1; + log_assert(p1_in6->sin6_port == p2_in6->sin6_port); + return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, + INET6_SIZE); + } else { + /* eek unknown type, perform this comparison for sanity. */ + return memcmp(&p1->addr, &p2->addr, p1->addrlen); + } } /** callback for incoming udp answers from the network. */ @@ -94,8 +153,11 @@ outnet_udp_cb(struct comm_point* c, void* arg, int error, key.id = LDNS_ID_WIRE(ldns_buffer_begin(c->buffer)); memcpy(&key.addr, &reply_info->addr, reply_info->addrlen); key.addrlen = reply_info->addrlen; + log_info("Incoming reply id=%4.4x addr=", key.id); + log_addr(&key.addr, key.addrlen); /* find it, see if this thing is a valid query response */ + log_info("lookup size is %d entries", (int)outnet->pending->count); p = (struct pending*)rbtree_search(outnet->pending, &key); if(!p) { verbose(VERB_DETAIL, "received unsolicited udp reply. dropped."); @@ -391,6 +453,8 @@ new_pending(struct outside_network* outnet, ldns_buffer* packet, return NULL; } } + log_info("inserted new pending reply id=%4.4x addr=", pend->id); + log_addr(&pend->addr, pend->addrlen); return pend; } diff --git a/util/netevent.c b/util/netevent.c index 0b6eb6c24..69bf44d6e 100644 --- a/util/netevent.c +++ b/util/netevent.c @@ -224,6 +224,7 @@ comm_point_udp_callback(int fd, short event, void* arg) return; log_assert(rep.c && rep.c->buffer && rep.c->fd == fd); ldns_buffer_clear(rep.c->buffer); + rep.addrlen = (socklen_t)sizeof(rep.addr); recv = recvfrom(fd, ldns_buffer_begin(rep.c->buffer), ldns_buffer_remaining(rep.c->buffer), 0, (struct sockaddr*)&rep.addr, &rep.addrlen); -- 2.47.2