#include <fcntl.h>
#include <sys/time.h>
#include <sys/ioctl.h>
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
#include <assert.h>
#include <sys/types.h>
return 0;
}
-int avahi_send_dns_packet_ipv4(int fd, AvahiIfIndex interface, AvahiDnsPacket *p, const AvahiIPv4Address *src_address, const AvahiIPv4Address *dst_address, uint16_t dst_port) {
+int avahi_send_dns_packet_ipv4(
+ int fd,
+ AvahiIfIndex interface,
+ AvahiDnsPacket *p,
+ const AvahiIPv4Address *src_address,
+ const AvahiIPv4Address *dst_address,
+ uint16_t dst_port) {
+
struct sockaddr_in sa;
struct msghdr msg;
struct iovec io;
struct in_pktinfo *pkti;
memset(cmsg_data, 0, sizeof(cmsg_data));
- cmsg = (struct cmsghdr*) 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_pktinfo));
cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = IP_PKTINFO;
if (src_address)
pkti->ipi_spec_dst.s_addr = src_address->address;
- msg.msg_control = cmsg_data;
- msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
+ msg.msg_controllen = cmsg->cmsg_len;
}
#elif defined(IP_SENDSRCADDR)
if (src_address) {
struct in_addr *addr;
-
- memset(cmsg_data, 0, sizeof(cmsg_data));
- cmsg = (struct cmsghdr*) cmsg_data;
- cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
+
+ 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);
addr->s_addr = src_address->address;
-
- msg.msg_control = cmsg_data;
- msg.msg_controllen = CMSG_SPACE(sizeof(struct in_addr));
- }
+
+ msg.msg_controllen = cmsg->cmsg_len;
+}
#elif defined(IP_MULTICAST_IF)
{
struct in_addr any = { INADDR_ANY };
return sendmsg_loop(fd, &msg, 0);
}
-int avahi_send_dns_packet_ipv6(int fd, AvahiIfIndex interface, AvahiDnsPacket *p, const AvahiIPv6Address *src_address, const AvahiIPv6Address *dst_address, uint16_t dst_port) {
+int avahi_send_dns_packet_ipv6(
+ int fd,
+ AvahiIfIndex interface,
+ AvahiDnsPacket *p,
+ const AvahiIPv6Address *src_address,
+ const AvahiIPv6Address *dst_address,
+ uint16_t dst_port) {
+
struct sockaddr_in6 sa;
struct msghdr msg;
struct iovec io;
if (interface > 0 || src_address) {
struct in6_pktinfo *pkti;
-
+
memset(cmsg_data, 0, sizeof(cmsg_data));
- cmsg = (struct cmsghdr*) cmsg_data;
+ msg.msg_control = cmsg_data;
+ msg.msg_controllen = sizeof(cmsg_data);
+
+ cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
cmsg->cmsg_level = IPPROTO_IPV6;
cmsg->cmsg_type = IPV6_PKTINFO;
if (src_address)
memcpy(&pkti->ipi6_addr, src_address->address, sizeof(src_address->address));
- msg.msg_control = cmsg_data;
- msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
+ msg.msg_controllen = cmsg->cmsg_len;
} else {
msg.msg_control = NULL;
msg.msg_controllen = 0;
return sendmsg_loop(fd, &msg, 0);
}
-AvahiDnsPacket *avahi_recv_dns_packet_ipv4(int fd, AvahiIPv4Address *ret_src_address, uint16_t *ret_src_port, AvahiIPv4Address *ret_dst_address, AvahiIfIndex *ret_iface, uint8_t *ret_ttl) {
+AvahiDnsPacket *avahi_recv_dns_packet_ipv4(
+ int fd,
+ AvahiIPv4Address *ret_src_address,
+ uint16_t *ret_src_port,
+ AvahiIPv4Address *ret_dst_address,
+ AvahiIfIndex *ret_iface,
+ uint8_t *ret_ttl) {
+
AvahiDnsPacket *p= NULL;
struct msghdr msg;
struct iovec io;
goto fail;
}
+ if (ms < 0) {
+ avahi_log_warn("FIONREAD returned negative value.");
+ goto fail;
+ }
+
p = avahi_dns_packet_new(ms + AVAHI_DNS_PACKET_EXTRA_SIZE);
io.iov_base = AVAHI_DNS_PACKET_DATA(p);
msg.msg_flags = 0;
if ((l = recvmsg(fd, &msg, 0)) < 0) {
- avahi_log_warn("recvmsg(): %s", strerror(errno));
+ /* Linux returns EAGAIN when an invalid IP packet has been
+ recieved. We suppress warnings in this case because this might
+ create quite a bit of log traffic on machines with unstable
+ links. (See #60) */
+
+ if (errno != EAGAIN)
+ avahi_log_warn("recvmsg(): %s", strerror(errno));
+
goto fail;
}
struct sockaddr_dl *sdl = (struct sockaddr_dl *) CMSG_DATA (cmsg);
if (ret_iface)
+#ifdef __sun
+ *ret_iface = *(uint_t*) sdl;
+#else
*ret_iface = (int) sdl->sdl_index;
+#endif
break;
}
return NULL;
}
-AvahiDnsPacket *avahi_recv_dns_packet_ipv6(int fd, AvahiIPv6Address *ret_src_address, uint16_t *ret_src_port, AvahiIPv6Address *ret_dst_address, AvahiIfIndex *ret_iface, uint8_t *ret_ttl) {
+AvahiDnsPacket *avahi_recv_dns_packet_ipv6(
+ int fd,
+ AvahiIPv6Address *ret_src_address,
+ uint16_t *ret_src_port,
+ AvahiIPv6Address *ret_dst_address,
+ AvahiIfIndex *ret_iface,
+ uint8_t *ret_ttl) {
+
AvahiDnsPacket *p = NULL;
struct msghdr msg;
struct iovec io;
avahi_log_warn("ioctl(): %s", strerror(errno));
goto fail;
}
+
+ if (ms < 0) {
+ avahi_log_warn("FIONREAD returned negative value.");
+ goto fail;
+ }
p = avahi_dns_packet_new(ms + AVAHI_DNS_PACKET_EXTRA_SIZE);
msg.msg_flags = 0;
if ((l = recvmsg(fd, &msg, 0)) < 0) {
- avahi_log_warn("recvmsg(): %s", strerror(errno));
+ /* Linux returns EAGAIN when an invalid IP packet has been
+ recieved. We suppress warnings in this case because this might
+ create quite a bit of log traffic on machines with unstable
+ links. (See #60) */
+
+ if (errno != EAGAIN)
+ avahi_log_warn("recvmsg(): %s", strerror(errno));
+
goto fail;
}
assert(found_iface);
assert(found_ttl);
-
+
return p;
fail:
int avahi_open_unicast_socket_ipv6(void) {
struct sockaddr_in6 local;
- int fd = -1;
+ int fd = -1, yes;
if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
avahi_log_warn("socket() failed: %s", strerror(errno));
goto fail;
}
+ yes = 1;
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes)) < 0) {
+ avahi_log_warn("IPV6_V6ONLY failed: %s", strerror(errno));
+ goto fail;
+ }
+
memset(&local, 0, sizeof(local));
local.sin6_family = AF_INET6;