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
This commit is contained in:
Wouter Wijngaards 2007-02-07 10:08:55 +00:00
parent fc30ae4b9e
commit 5532a0ea67
4 changed files with 73 additions and 3 deletions

View file

@ -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.

View file

@ -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));
}

View file

@ -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;
}

View file

@ -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);