]> git.meshlink.io Git - catta/blobdiff - avahi-core/socket.c
Make herzi sleep beter. (Closes #143)
[catta] / avahi-core / socket.c
index 453ce54d996f0a0d5c5579eebaa7e38a91e1e373..61b5eb4c868021e920be7c8b7039a5e0274fcb75 100644 (file)
@@ -31,6 +31,9 @@
 #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>
@@ -459,7 +462,14 @@ static int sendmsg_loop(int fd, struct msghdr *msg, int flags) {
     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;
@@ -499,7 +509,10 @@ int avahi_send_dns_packet_ipv4(int fd, AvahiIfIndex interface, AvahiDnsPacket *p
         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;
@@ -512,25 +525,26 @@ int avahi_send_dns_packet_ipv4(int fd, AvahiIfIndex interface, AvahiDnsPacket *p
         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 };
@@ -546,7 +560,14 @@ int avahi_send_dns_packet_ipv4(int fd, AvahiIfIndex interface, AvahiDnsPacket *p
     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;
@@ -576,9 +597,12 @@ int avahi_send_dns_packet_ipv6(int fd, AvahiIfIndex interface, AvahiDnsPacket *p
 
     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;
@@ -591,8 +615,7 @@ int avahi_send_dns_packet_ipv6(int fd, AvahiIfIndex interface, AvahiDnsPacket *p
         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;
@@ -601,7 +624,14 @@ int avahi_send_dns_packet_ipv6(int fd, AvahiIfIndex interface, AvahiDnsPacket *p
     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;
@@ -619,6 +649,11 @@ AvahiDnsPacket *avahi_recv_dns_packet_ipv4(int fd, AvahiIPv4Address *ret_src_add
         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);
@@ -634,7 +669,14 @@ AvahiDnsPacket *avahi_recv_dns_packet_ipv4(int fd, AvahiIPv4Address *ret_src_add
     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;
     }
 
@@ -698,7 +740,11 @@ AvahiDnsPacket *avahi_recv_dns_packet_ipv4(int fd, AvahiIPv4Address *ret_src_add
                     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;
                 }
@@ -731,7 +777,14 @@ fail:
     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;
@@ -748,6 +801,11 @@ AvahiDnsPacket *avahi_recv_dns_packet_ipv6(int fd, AvahiIPv6Address *ret_src_add
         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);
 
@@ -765,7 +823,14 @@ AvahiDnsPacket *avahi_recv_dns_packet_ipv6(int fd, AvahiIPv6Address *ret_src_add
     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;
     }
 
@@ -820,7 +885,7 @@ AvahiDnsPacket *avahi_recv_dns_packet_ipv6(int fd, AvahiIPv6Address *ret_src_add
 
     assert(found_iface);
     assert(found_ttl);
-
+    
     return p;
 
 fail:
@@ -872,13 +937,19 @@ 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;