summaryrefslogtreecommitdiffstats
path: root/src/query.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/query.c')
-rw-r--r--src/query.c89
1 files changed, 74 insertions, 15 deletions
diff --git a/src/query.c b/src/query.c
index fe5d541..42549bd 100644
--- a/src/query.c
+++ b/src/query.c
@@ -87,13 +87,36 @@ int mdns_open_socket(void) {
if (bind(fd, (struct sockaddr*) &sa, sizeof(sa)) < 0)
goto fail;
+#ifdef IP_PKTINFO
yes = 1;
- if (setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &yes, sizeof(yes)) < 0)
- goto fail;
-
if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0)
goto fail;
+#else
+
+#ifdef IP_RECVINTERFACE
+ yes = 1;
+ if (setsockopt (fd, IPPROTO_IP, IP_RECVINTERFACE, &yes, sizeof(yes)) < 0)
+ goto fail;
+#elif defined(IP_RECVIF)
+ yes = 1;
+ if (setsockopt (fd, IPPROTO_IP, IP_RECVIF, &yes, sizeof(yes)) < 0)
+ goto fail;
+#endif
+
+#ifdef IP_RECVDSTADDR
+ yes = 1;
+ if (setsockopt (fd, IPPROTO_IP, IP_RECVDSTADDR, &yes, sizeof(yes)) < 0)
+ goto fail;
+#endif
+
+#endif /* IP_PKTINFO */
+#ifdef IP_RECVTTL
+ yes = 1;
+ if (setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &yes, sizeof(yes)) < 0)
+ goto fail;
+#endif
+
if (set_cloexec(fd) < 0)
goto fail;
@@ -113,9 +136,15 @@ static int send_dns_packet(int fd, struct dns_packet *p) {
struct sockaddr_in sa;
struct msghdr msg;
struct iovec io;
+#ifdef IP_PKTINFO
struct cmsghdr *cmsg;
+ uint8_t cmsg_data[CMSG_SPACE(sizeof(struct in_pktinfo))];
struct in_pktinfo *pkti;
- uint8_t cmsg_data[CMSG_LEN(sizeof(struct in_pktinfo))];
+#elif defined(IP_SENDSRCADDR)
+ struct cmsghdr *cmsg;
+ uint8_t cmsg_data[CMSG_SPACE(sizeof(struct in_addr))];
+ struct in_addr *addr;
+#endif
int i, n;
struct ifreq ifreq[32];
struct ifconf ifconf;
@@ -131,24 +160,43 @@ static int send_dns_packet(int fd, struct dns_packet *p) {
io.iov_base = p->data;
io.iov_len = p->size;
- memset(cmsg_data, 0, sizeof(cmsg_data));
- cmsg = (struct cmsghdr*) cmsg_data;
- cmsg->cmsg_len = sizeof(cmsg_data);
- cmsg->cmsg_level = IPPROTO_IP;
- cmsg->cmsg_type = IP_PKTINFO;
-
- pkti = (struct in_pktinfo*) CMSG_DATA(cmsg);
- pkti->ipi_ifindex = 0;
-
memset(&msg, 0, sizeof(msg));
msg.msg_name = &sa;
msg.msg_namelen = sizeof(sa);
msg.msg_iov = &io;
msg.msg_iovlen = 1;
+ msg.msg_flags = 0;
+
+#ifdef IP_PKTINFO
+ memset(cmsg_data, 0, sizeof(cmsg_data));
msg.msg_control = cmsg_data;
msg.msg_controllen = sizeof(cmsg_data);
- msg.msg_flags = 0;
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
+ cmsg->cmsg_level = IPPROTO_IP;
+ cmsg->cmsg_type = IP_PKTINFO;
+ pkti = (struct in_pktinfo*) CMSG_DATA(cmsg);
+
+ msg.msg_controllen = cmsg->cmsg_len;
+#elif defined(IP_SENDSRCADDR)
+ memset(cmsg_data, 0, sizeof(cmsg_data));
+ msg.msg_control = cmsg_data;
+ msg.msg_controllen = sizeof(cmsg_data);
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
+ cmsg->cmsg_level = IPPROTO_IP;
+ cmsg->cmsg_type = IP_SENDSRCADDR;
+
+ addr = (struct in_addr *)CMSG_DATA(cmsg);
+
+ msg.msg_controllen = cmsg->cmsg_len;
+#elif defined(__GNUC__)
+#warning "FIXME: We need some code to set the outgoing interface/local address here if IP_PKTINFO/IP_SENDSRCADDR is not available"
+#endif
+
ifconf.ifc_req = ifreq;
ifconf.ifc_len = sizeof(ifreq);
@@ -183,6 +231,7 @@ static int send_dns_packet(int fd, struct dns_packet *p) {
if (ioctl(fd, SIOCGIFINDEX, &ifreq[i]) < 0)
continue; /* See above why we ignore this error */
+#ifdef IP_PKTINFO
/* Only send the the packet once per interface. We assume that
* multiple addresses assigned to the same interface follow
* immediately one after the other.*/
@@ -190,6 +239,11 @@ static int send_dns_packet(int fd, struct dns_packet *p) {
continue;
last_index = pkti->ipi_ifindex = ifreq[i].ifr_ifindex;
+#elif defined(IP_SENDSRCADDR)
+ addr->s_addr = ifsa->sin_addr.s_addr;
+#elif defined(__GNUC__)
+#warning "FIXME: We need some code to set the outgoing interface/local address here if IP_PKTINFO/IP_SENDSRCADDR is not available"
+#endif
for (;;) {
@@ -241,7 +295,12 @@ static int recv_dns_packet(int fd, struct dns_packet **ret_packet, uint8_t *ret_
*ret_ttl = 0;
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg,cmsg)) {
- if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_TTL) {
+#ifdef SOL_IP
+ if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_TTL)
+#else
+ if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_TTL)
+#endif
+ {
*ret_ttl = (uint8_t) (*(uint32_t*) CMSG_DATA(cmsg));
break;
}