Now fetches destination address from udp packets

This commit is contained in:
Erik Ekman 2008-08-07 22:12:10 +00:00 committed by Erik Ekman
parent 02d40c1a7b
commit 35a8ffe46d
3 changed files with 36 additions and 2 deletions

View File

@ -104,6 +104,9 @@ open_dns(int localport, in_addr_t listen_ip)
#endif
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
/* To get destination address from each UDP datagram, see iodined.c:read_dns() */
setsockopt(fd, IPPROTO_IP, DSTADDR_SOCKOPT, &flag, sizeof(flag));
if(bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
err(1, "bind");

View File

@ -30,6 +30,14 @@
#define QUERY_NAME_SIZE 256
#if defined IP_RECVDSTADDR
# define DSTADDR_SOCKOPT IP_RECVDSTADDR
# define dstaddr(x) (CMSG_DATA(x))
#elif defined IP_PKTINFO
# define DSTADDR_SOCKOPT IP_PKTINFO
# define dstaddr(x) (&(((struct in_pktinfo *)(CMSG_DATA(x)))->ipi_addr))
#endif
struct packet
{
int len; /* Total packet length */
@ -42,6 +50,7 @@ struct query {
char name[QUERY_NAME_SIZE];
short type;
short id;
struct in_addr destination;
struct sockaddr from;
int fromlen;
};

View File

@ -510,17 +510,39 @@ static int
read_dns(int fd, struct query *q)
{
struct sockaddr_in from;
char packet[64*1024];
socklen_t addrlen;
char packet[64*1024];
char address[96];
struct msghdr msg;
struct iovec iov;
struct cmsghdr *cmsg;
int r;
addrlen = sizeof(struct sockaddr);
r = recvfrom(fd, packet, sizeof(packet), 0, (struct sockaddr*)&from, &addrlen);
iov.iov_base = packet;
iov.iov_len = sizeof(packet);
msg.msg_name = (caddr_t) &from;
msg.msg_namelen = (unsigned) addrlen;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = address;
msg.msg_controllen = sizeof(address);
msg.msg_flags = 0;
r = recvmsg(fd, &msg, 0);
if (r > 0) {
dns_decode(NULL, 0, q, QR_QUERY, packet, r);
memcpy((struct sockaddr*)&q->from, (struct sockaddr*)&from, addrlen);
q->fromlen = addrlen;
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == DSTADDR_SOCKOPT) {
q->destination = *dstaddr(cmsg);
break;
}
}
return strlen(q->name);
} else if (r < 0) {