summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Klauser <tklauser@distanz.ch>2017-01-06 12:02:30 +0100
committerTobias Klauser <tklauser@distanz.ch>2017-01-06 12:02:30 +0100
commit1073ece433c9922fab10edebae7b6f9d0115da8f (patch)
tree2f7248436d346ae1bf3aed6139b3eb5c78ef544a
parent95c6c530a3094f520faaea685b51f23e7257b633 (diff)
llmnr-query: Add support for FreeBSD and Darwin
Make llmnr-query work on FreeBSD and Darwin by using sendmsg() to send UDP packets. Using sendto() doesn't seem to work for IPv6 sockets. Also specify the size of the corresponding sockaddr type, not of sockaddr_storage. Tested on FreeBSD 11.0, Mac OS X 10.11. Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
-rw-r--r--llmnr-query.c36
1 files changed, 34 insertions, 2 deletions
diff --git a/llmnr-query.c b/llmnr-query.c
index 9aaeee6..7e72836 100644
--- a/llmnr-query.c
+++ b/llmnr-query.c
@@ -18,6 +18,8 @@
* along with llmnrd. If not, see <http://www.gnu.org/licenses/>.
*/
+#define _GNU_SOURCE
+#define __APPLE_USE_RFC_3542
#include <errno.h>
#include <getopt.h>
#include <stdint.h>
@@ -26,6 +28,7 @@
#include <arpa/inet.h>
#include <net/if.h>
+#include <netinet/in.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/time.h>
@@ -98,6 +101,7 @@ int main(int argc, char **argv)
uint16_t qtype = LLMNR_QTYPE_ANY;
bool ipv6 = false;
struct pkt *p;
+ unsigned int ifindex = 0;
static const int TTL = 255;
while ((c = getopt_long(argc, argv, short_ops, long_opts, NULL)) != -1) {
@@ -182,7 +186,7 @@ int main(int argc, char **argv)
}
if (iface != NULL) {
- unsigned int ifindex = if_nametoindex(iface);
+ ifindex = if_nametoindex(iface);
if (ifindex == 0 && errno != 0) {
log_err("Could not get interface %s: %s\n", iface, strerror(errno));
@@ -216,6 +220,11 @@ int main(int argc, char **argv)
for (i = 0; i < count; i++) {
struct llmnr_hdr *hdr;
struct sockaddr_storage sst;
+ socklen_t sst_len;
+ struct iovec iov[1];
+ struct msghdr msg;
+ struct in6_pktinfo ipi6;
+ uint8_t c[CMSG_SPACE(sizeof(ipi6))];
size_t query_pkt_len;
fd_set rfds;
struct timeval tv;
@@ -237,8 +246,13 @@ int main(int argc, char **argv)
pkt_put_u16(p, htons(LLMNR_QCLASS_IN));
memset(&sst, 0, sizeof(sst));
+ memset(&iov, 0, sizeof(iov));
+ memset(&msg, 0, sizeof(msg));
+ memset(&ipi6, 0, sizeof(ipi6));
+
if (ipv6) {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&sst;
+ struct cmsghdr *cmsg;
sin6->sin6_family = AF_INET6;
sin6->sin6_port = htons(LLMNR_UDP_PORT);
@@ -246,6 +260,16 @@ int main(int argc, char **argv)
log_err("Failed to convert IPv6 address: %s\n", strerror(errno));
break;
}
+ sst_len = sizeof(*sin6);
+
+ ipi6.ipi6_ifindex = ifindex;
+ msg.msg_control = c;
+ msg.msg_controllen = sizeof(c);
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = IPPROTO_IPV6;
+ cmsg->cmsg_type = IPV6_PKTINFO;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(ipi6));
+ memcpy(CMSG_DATA(cmsg), &ipi6, sizeof(ipi6));
} else {
struct sockaddr_in *sin = (struct sockaddr_in *)&sst;
@@ -255,9 +279,17 @@ int main(int argc, char **argv)
log_err("Failed to convert IPv4 address: %s\n", strerror(errno));
break;
}
+ sst_len = sizeof(*sin);
}
- if (sendto(sock, p->data, pkt_len(p), 0, (struct sockaddr *)&sst, sizeof(sst)) < 0) {
+ iov[0].iov_base = p->data;
+ iov[0].iov_len = pkt_len(p);
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_name = &sst;
+ msg.msg_namelen = sst_len;
+
+ if (sendmsg(sock, &msg, 0) < 0) {
log_err("Failed to send UDP packet: %s\n", strerror(errno));
break;
}