Now fetches destination address from udp packets

This commit is contained in:
Erik Ekman 2008-08-07 22:12:10 +00:00
parent c96b83e3d2
commit d4e1eef6d5
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 #endif
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)); 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) if(bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
err(1, "bind"); err(1, "bind");

View File

@ -30,6 +30,14 @@
#define QUERY_NAME_SIZE 256 #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 struct packet
{ {
int len; /* Total packet length */ int len; /* Total packet length */
@ -42,6 +50,7 @@ struct query {
char name[QUERY_NAME_SIZE]; char name[QUERY_NAME_SIZE];
short type; short type;
short id; short id;
struct in_addr destination;
struct sockaddr from; struct sockaddr from;
int fromlen; int fromlen;
}; };

View File

@ -510,17 +510,39 @@ static int
read_dns(int fd, struct query *q) read_dns(int fd, struct query *q)
{ {
struct sockaddr_in from; struct sockaddr_in from;
char packet[64*1024];
socklen_t addrlen; socklen_t addrlen;
char packet[64*1024];
char address[96];
struct msghdr msg;
struct iovec iov;
struct cmsghdr *cmsg;
int r; int r;
addrlen = sizeof(struct sockaddr); 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) { if (r > 0) {
dns_decode(NULL, 0, q, QR_QUERY, packet, r); dns_decode(NULL, 0, q, QR_QUERY, packet, r);
memcpy((struct sockaddr*)&q->from, (struct sockaddr*)&from, addrlen); memcpy((struct sockaddr*)&q->from, (struct sockaddr*)&from, addrlen);
q->fromlen = 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); return strlen(q->name);
} else if (r < 0) { } else if (r < 0) {