2 This file is part of avahi.
4 avahi is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2.1 of the
7 License, or (at your option) any later version.
9 avahi is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
12 Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with avahi; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
31 #include <sys/ioctl.h>
32 #ifdef HAVE_SYS_FILIO_H
33 #include <sys/filio.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
45 #include <net/if_dl.h>
52 #include "addr-util.h"
54 /* this is a portability hack */
55 #ifndef IPV6_ADD_MEMBERSHIP
56 #ifdef IPV6_JOIN_GROUP
57 #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
61 #ifndef IPV6_DROP_MEMBERSHIP
62 #ifdef IPV6_LEAVE_GROUP
63 #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
67 static void mdns_mcast_group_ipv4(struct sockaddr_in *ret_sa) {
70 memset(ret_sa, 0, sizeof(struct sockaddr_in));
71 ret_sa->sin_family = AF_INET;
72 ret_sa->sin_port = htons(AVAHI_MDNS_PORT);
73 inet_pton(AF_INET, AVAHI_IPV4_MCAST_GROUP, &ret_sa->sin_addr);
76 static void mdns_mcast_group_ipv6(struct sockaddr_in6 *ret_sa) {
79 memset(ret_sa, 0, sizeof(struct sockaddr_in6));
80 ret_sa->sin6_family = AF_INET6;
81 ret_sa->sin6_port = htons(AVAHI_MDNS_PORT);
82 inet_pton(AF_INET6, AVAHI_IPV6_MCAST_GROUP, &ret_sa->sin6_addr);
85 static void ipv4_address_to_sockaddr(struct sockaddr_in *ret_sa, const AvahiIPv4Address *a, uint16_t port) {
90 memset(ret_sa, 0, sizeof(struct sockaddr_in));
91 ret_sa->sin_family = AF_INET;
92 ret_sa->sin_port = htons(port);
93 memcpy(&ret_sa->sin_addr, a, sizeof(AvahiIPv4Address));
96 static void ipv6_address_to_sockaddr(struct sockaddr_in6 *ret_sa, const AvahiIPv6Address *a, uint16_t port) {
101 memset(ret_sa, 0, sizeof(struct sockaddr_in6));
102 ret_sa->sin6_family = AF_INET6;
103 ret_sa->sin6_port = htons(port);
104 memcpy(&ret_sa->sin6_addr, a, sizeof(AvahiIPv6Address));
107 int avahi_mdns_mcast_join_ipv4(int fd, const AvahiIPv4Address *a, int idx, int join) {
108 #ifdef HAVE_STRUCT_IP_MREQN
109 struct ip_mreqn mreq;
113 struct sockaddr_in sa;
119 memset(&mreq, 0, sizeof(mreq));
120 #ifdef HAVE_STRUCT_IP_MREQN
121 mreq.imr_ifindex = idx;
122 mreq.imr_address.s_addr = a->address;
124 mreq.imr_interface.s_addr = a->address;
126 mdns_mcast_group_ipv4(&sa);
127 mreq.imr_multiaddr = sa.sin_addr;
129 /* Some network drivers have issues with dropping membership of
130 * mcast groups when the iface is down, but don't allow rejoining
131 * when it comes back up. This is an ugly workaround */
133 setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
135 if (setsockopt(fd, IPPROTO_IP, join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
136 avahi_log_warn("%s failed: %s", join ? "IP_ADD_MEMBERSHIP" : "IP_DROP_MEMBERSHIP", strerror(errno));
143 int avahi_mdns_mcast_join_ipv6(int fd, const AvahiIPv6Address *a, int idx, int join) {
144 struct ipv6_mreq mreq6;
145 struct sockaddr_in6 sa6;
151 memset(&mreq6, 0, sizeof(mreq6));
152 mdns_mcast_group_ipv6 (&sa6);
153 mreq6.ipv6mr_multiaddr = sa6.sin6_addr;
154 mreq6.ipv6mr_interface = idx;
157 setsockopt(fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq6, sizeof(mreq6));
159 if (setsockopt(fd, IPPROTO_IPV6, join ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) {
160 avahi_log_warn("%s failed: %s", join ? "IPV6_ADD_MEMBERSHIP" : "IPV6_DROP_MEMBERSHIP", strerror(errno));
167 static int reuseaddr(int fd) {
171 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
172 avahi_log_warn("SO_REUSEADDR failed: %s", strerror(errno));
178 if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)) < 0) {
179 avahi_log_warn("SO_REUSEPORT failed: %s", strerror(errno));
187 static int bind_with_warn(int fd, const struct sockaddr *sa, socklen_t l) {
193 if (bind(fd, sa, l) < 0) {
195 if (errno != EADDRINUSE) {
196 avahi_log_warn("bind() failed: %s", strerror(errno));
200 avahi_log_warn("*** WARNING: Detected another %s mDNS stack running on this host. This makes mDNS unreliable and is thus not recommended. ***",
201 sa->sa_family == AF_INET ? "IPv4" : "IPv6");
203 /* Try again, this time with SO_REUSEADDR set */
204 if (reuseaddr(fd) < 0)
207 if (bind(fd, sa, l) < 0) {
208 avahi_log_warn("bind() failed: %s", strerror(errno));
213 /* We enable SO_REUSEADDR afterwards, to make sure that the
214 * user may run other mDNS implementations if he really
217 if (reuseaddr(fd) < 0)
224 static int ipv4_pktinfo(int fd) {
229 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0) {
230 avahi_log_warn("IP_PKTINFO failed: %s", strerror(errno));
235 #ifdef IP_RECVINTERFACE
237 if (setsockopt (fd, IPPROTO_IP, IP_RECVINTERFACE, &yes, sizeof(yes)) < 0) {
238 avahi_log_warn("IP_RECVINTERFACE failed: %s", strerror(errno));
241 #elif defined(IP_RECVIF)
243 if (setsockopt (fd, IPPROTO_IP, IP_RECVIF, &yes, sizeof(yes)) < 0) {
244 avahi_log_warn("IP_RECVIF failed: %s", strerror(errno));
249 #ifdef IP_RECVDSTADDR
251 if (setsockopt (fd, IPPROTO_IP, IP_RECVDSTADDR, &yes, sizeof(yes)) < 0) {
252 avahi_log_warn("IP_RECVDSTADDR failed: %s", strerror(errno));
257 #endif /* IP_PKTINFO */
261 if (setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &yes, sizeof(yes)) < 0) {
262 avahi_log_warn("IP_RECVTTL failed: %s", strerror(errno));
270 static int ipv6_pktinfo(int fd) {
273 #ifdef IPV6_RECVPKTINFO
275 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &yes, sizeof(yes)) < 0) {
276 avahi_log_warn("IPV6_RECVPKTINFO failed: %s", strerror(errno));
279 #elif defined(IPV6_PKTINFO)
281 if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &yes, sizeof(yes)) < 0) {
282 avahi_log_warn("IPV6_PKTINFO failed: %s", strerror(errno));
289 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPS, &yes, sizeof(yes)) < 0) {
290 avahi_log_warn("IPV6_RECVHOPS failed: %s", strerror(errno));
293 #elif defined(IPV6_RECVHOPLIMIT)
295 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &yes, sizeof(yes)) < 0) {
296 avahi_log_warn("IPV6_RECVHOPLIMIT failed: %s", strerror(errno));
299 #elif defined(IPV6_HOPLIMIT)
301 if (setsockopt(fd, IPPROTO_IPV6, IPV6_HOPLIMIT, &yes, sizeof(yes)) < 0) {
302 avahi_log_warn("IPV6_HOPLIMIT failed: %s", strerror(errno));
310 int avahi_open_socket_ipv4(int no_reuse) {
311 struct sockaddr_in local;
312 int fd = -1, r, ittl;
315 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
316 avahi_log_warn("socket() failed: %s", strerror(errno));
321 if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) {
322 avahi_log_warn("IP_MULTICAST_TTL failed: %s", strerror(errno));
327 if (setsockopt(fd, IPPROTO_IP, IP_TTL, &ittl, sizeof(ittl)) < 0) {
328 avahi_log_warn("IP_TTL failed: %s", strerror(errno));
333 if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &cyes, sizeof(cyes)) < 0) {
334 avahi_log_warn("IP_MULTICAST_LOOP failed: %s", strerror(errno));
338 memset(&local, 0, sizeof(local));
339 local.sin_family = AF_INET;
340 local.sin_port = htons(AVAHI_MDNS_PORT);
343 r = bind(fd, (struct sockaddr*) &local, sizeof(local));
345 r = bind_with_warn(fd, (struct sockaddr*) &local, sizeof(local));
350 if (ipv4_pktinfo (fd) < 0)
353 if (avahi_set_cloexec(fd) < 0) {
354 avahi_log_warn("FD_CLOEXEC failed: %s", strerror(errno));
358 if (avahi_set_nonblock(fd) < 0) {
359 avahi_log_warn("O_NONBLOCK failed: %s", strerror(errno));
372 int avahi_open_socket_ipv6(int no_reuse) {
373 struct sockaddr_in6 sa, local;
377 mdns_mcast_group_ipv6(&sa);
379 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
380 avahi_log_warn("socket() failed: %s", strerror(errno));
385 if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) < 0) {
386 avahi_log_warn("IPV6_MULTICAST_HOPS failed: %s", strerror(errno));
391 if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)) < 0) {
392 avahi_log_warn("IPV6_UNICAST_HOPS failed: %s", strerror(errno));
397 if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes)) < 0) {
398 avahi_log_warn("IPV6_V6ONLY failed: %s", strerror(errno));
403 if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
404 avahi_log_warn("IPV6_MULTICAST_LOOP failed: %s", strerror(errno));
408 memset(&local, 0, sizeof(local));
409 local.sin6_family = AF_INET6;
410 local.sin6_port = htons(AVAHI_MDNS_PORT);
413 r = bind(fd, (struct sockaddr*) &local, sizeof(local));
415 r = bind_with_warn(fd, (struct sockaddr*) &local, sizeof(local));
420 if (ipv6_pktinfo(fd) < 0)
423 if (avahi_set_cloexec(fd) < 0) {
424 avahi_log_warn("FD_CLOEXEC failed: %s", strerror(errno));
428 if (avahi_set_nonblock(fd) < 0) {
429 avahi_log_warn("O_NONBLOCK failed: %s", strerror(errno));
442 static int sendmsg_loop(int fd, struct msghdr *msg, int flags) {
448 if (sendmsg(fd, msg, flags) >= 0)
454 if (errno != EAGAIN) {
456 struct sockaddr_in *sin = msg->msg_name;
458 inet_ntop(sin->sin_family, &sin->sin_addr, where, sizeof(where));
459 avahi_log_debug("sendmsg() to %s failed: %s", where, strerror(errno));
463 if (avahi_wait_for_write(fd) < 0)
470 int avahi_send_dns_packet_ipv4(
472 AvahiIfIndex interface,
474 const AvahiIPv4Address *src_address,
475 const AvahiIPv4Address *dst_address,
478 struct sockaddr_in sa;
482 struct cmsghdr *cmsg;
483 size_t cmsg_data[( CMSG_SPACE(sizeof(struct in_pktinfo)) / sizeof(size_t)) + 1];
484 #elif !defined(IP_MULTICAST_IF) && defined(IP_SENDSRCADDR)
485 struct cmsghdr *cmsg;
486 size_t cmsg_data[( CMSG_SPACE(sizeof(struct in_addr)) / sizeof(size_t)) + 1];
491 assert(avahi_dns_packet_check_valid(p) >= 0);
492 assert(!dst_address || dst_port > 0);
495 mdns_mcast_group_ipv4(&sa);
497 ipv4_address_to_sockaddr(&sa, dst_address, dst_port);
499 memset(&io, 0, sizeof(io));
500 io.iov_base = AVAHI_DNS_PACKET_DATA(p);
501 io.iov_len = p->size;
503 memset(&msg, 0, sizeof(msg));
505 msg.msg_namelen = sizeof(sa);
509 msg.msg_control = NULL;
510 msg.msg_controllen = 0;
513 if (interface > 0 || src_address) {
514 struct in_pktinfo *pkti;
516 memset(cmsg_data, 0, sizeof(cmsg_data));
517 msg.msg_control = cmsg_data;
518 msg.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));
520 cmsg = CMSG_FIRSTHDR(&msg);
521 cmsg->cmsg_len = msg.msg_controllen;
522 cmsg->cmsg_level = IPPROTO_IP;
523 cmsg->cmsg_type = IP_PKTINFO;
525 pkti = (struct in_pktinfo*) CMSG_DATA(cmsg);
528 pkti->ipi_ifindex = interface;
531 pkti->ipi_spec_dst.s_addr = src_address->address;
533 #elif defined(IP_MULTICAST_IF)
535 struct in_addr any = { INADDR_ANY };
536 if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, src_address ? &src_address->address : &any, sizeof(struct in_addr)) < 0) {
537 avahi_log_warn("IP_MULTICAST_IF failed: %s", strerror(errno));
541 #elif defined(IP_SENDSRCADDR)
543 struct in_addr *addr;
545 memset(cmsg_data, 0, sizeof(cmsg_data));
546 msg.msg_control = cmsg_data;
547 msg.msg_controllen = CMSG_LEN(sizeof(struct in_addr));
549 cmsg = CMSG_FIRSTHDR(&msg);
550 cmsg->cmsg_len = msg.msg_controllen;
551 cmsg->cmsg_level = IPPROTO_IP;
552 cmsg->cmsg_type = IP_SENDSRCADDR;
554 addr = (struct in_addr *)CMSG_DATA(cmsg);
555 addr->s_addr = src_address->address;
557 #elif defined(__GNUC__)
558 #warning "FIXME: We need some code to set the outgoing interface/local address here if IP_PKTINFO/IP_MULTICAST_IF is not available"
561 return sendmsg_loop(fd, &msg, 0);
564 int avahi_send_dns_packet_ipv6(
566 AvahiIfIndex interface,
568 const AvahiIPv6Address *src_address,
569 const AvahiIPv6Address *dst_address,
572 struct sockaddr_in6 sa;
575 struct cmsghdr *cmsg;
576 size_t cmsg_data[(CMSG_SPACE(sizeof(struct in6_pktinfo))/sizeof(size_t)) + 1];
580 assert(avahi_dns_packet_check_valid(p) >= 0);
581 assert(!dst_address || dst_port > 0);
584 mdns_mcast_group_ipv6(&sa);
586 ipv6_address_to_sockaddr(&sa, dst_address, dst_port);
588 memset(&io, 0, sizeof(io));
589 io.iov_base = AVAHI_DNS_PACKET_DATA(p);
590 io.iov_len = p->size;
592 memset(&msg, 0, sizeof(msg));
594 msg.msg_namelen = sizeof(sa);
599 if (interface > 0 || src_address) {
600 struct in6_pktinfo *pkti;
602 memset(cmsg_data, 0, sizeof(cmsg_data));
603 msg.msg_control = cmsg_data;
604 msg.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
606 cmsg = CMSG_FIRSTHDR(&msg);
607 cmsg->cmsg_len = msg.msg_controllen;
608 cmsg->cmsg_level = IPPROTO_IPV6;
609 cmsg->cmsg_type = IPV6_PKTINFO;
611 pkti = (struct in6_pktinfo*) CMSG_DATA(cmsg);
614 pkti->ipi6_ifindex = interface;
617 memcpy(&pkti->ipi6_addr, src_address->address, sizeof(src_address->address));
619 msg.msg_control = NULL;
620 msg.msg_controllen = 0;
623 return sendmsg_loop(fd, &msg, 0);
626 AvahiDnsPacket *avahi_recv_dns_packet_ipv4(
628 AvahiIPv4Address *ret_src_address,
629 uint16_t *ret_src_port,
630 AvahiIPv4Address *ret_dst_address,
631 AvahiIfIndex *ret_iface,
634 AvahiDnsPacket *p= NULL;
637 size_t aux[1024 / sizeof(size_t)]; /* for alignment on ia64 ! */
639 struct cmsghdr *cmsg;
642 struct sockaddr_in sa;
646 if (ioctl(fd, FIONREAD, &ms) < 0) {
647 avahi_log_warn("ioctl(): %s", strerror(errno));
652 avahi_log_warn("FIONREAD returned negative value.");
656 p = avahi_dns_packet_new(ms + AVAHI_DNS_PACKET_EXTRA_SIZE);
658 io.iov_base = AVAHI_DNS_PACKET_DATA(p);
659 io.iov_len = p->max_size;
661 memset(&msg, 0, sizeof(msg));
663 msg.msg_namelen = sizeof(sa);
666 msg.msg_control = aux;
667 msg.msg_controllen = sizeof(aux);
670 if ((l = recvmsg(fd, &msg, 0)) < 0) {
671 /* Linux returns EAGAIN when an invalid IP packet has been
672 received. We suppress warnings in this case because this might
673 create quite a bit of log traffic on machines with unstable
677 avahi_log_warn("recvmsg(): %s", strerror(errno));
682 /* For corrupt packets FIONREAD returns zero size (See rhbz #607297). So
683 * fail after having read them. */
687 if (sa.sin_addr.s_addr == INADDR_ANY)
688 /* Linux 2.4 behaves very strangely sometimes! */
691 assert(!(msg.msg_flags & MSG_CTRUNC));
692 assert(!(msg.msg_flags & MSG_TRUNC));
694 p->size = (size_t) l;
697 *ret_src_port = avahi_port_from_sockaddr((struct sockaddr*) &sa);
699 if (ret_src_address) {
701 avahi_address_from_sockaddr((struct sockaddr*) &sa, &a);
702 *ret_src_address = a.data.ipv4;
709 *ret_iface = AVAHI_IF_UNSPEC;
711 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
713 if (cmsg->cmsg_level == IPPROTO_IP) {
715 switch (cmsg->cmsg_type) {
721 *ret_ttl = (uint8_t) (*(int *) CMSG_DATA(cmsg));
727 struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg);
729 if (ret_iface && i->ipi_ifindex > 0)
730 *ret_iface = (int) i->ipi_ifindex;
733 ret_dst_address->address = i->ipi_addr.s_addr;
743 struct sockaddr_dl *sdl = (struct sockaddr_dl *) CMSG_DATA (cmsg);
747 if (*(uint_t*) sdl > 0)
748 *ret_iface = *(uint_t*) sdl;
751 if (sdl->sdl_index > 0)
752 *ret_iface = (int) sdl->sdl_index;
760 #ifdef IP_RECVDSTADDR
763 memcpy(&ret_dst_address->address, CMSG_DATA (cmsg), 4);
770 avahi_log_warn("Unhandled cmsg_type: %d", cmsg->cmsg_type);
782 avahi_dns_packet_free(p);
787 AvahiDnsPacket *avahi_recv_dns_packet_ipv6(
789 AvahiIPv6Address *ret_src_address,
790 uint16_t *ret_src_port,
791 AvahiIPv6Address *ret_dst_address,
792 AvahiIfIndex *ret_iface,
795 AvahiDnsPacket *p = NULL;
798 size_t aux[1024 / sizeof(size_t)];
801 struct cmsghdr *cmsg;
802 int found_ttl = 0, found_iface = 0;
803 struct sockaddr_in6 sa;
807 if (ioctl(fd, FIONREAD, &ms) < 0) {
808 avahi_log_warn("ioctl(): %s", strerror(errno));
813 avahi_log_warn("FIONREAD returned negative value.");
817 p = avahi_dns_packet_new(ms + AVAHI_DNS_PACKET_EXTRA_SIZE);
819 io.iov_base = AVAHI_DNS_PACKET_DATA(p);
820 io.iov_len = p->max_size;
822 memset(&msg, 0, sizeof(msg));
823 msg.msg_name = (struct sockaddr*) &sa;
824 msg.msg_namelen = sizeof(sa);
828 msg.msg_control = aux;
829 msg.msg_controllen = sizeof(aux);
832 if ((l = recvmsg(fd, &msg, 0)) < 0) {
833 /* Linux returns EAGAIN when an invalid IP packet has been
834 received. We suppress warnings in this case because this might
835 create quite a bit of log traffic on machines with unstable
839 avahi_log_warn("recvmsg(): %s", strerror(errno));
844 /* For corrupt packets FIONREAD returns zero size (See rhbz #607297). So
845 * fail after having read them. */
849 assert(!(msg.msg_flags & MSG_CTRUNC));
850 assert(!(msg.msg_flags & MSG_TRUNC));
852 p->size = (size_t) l;
855 *ret_src_port = avahi_port_from_sockaddr((struct sockaddr*) &sa);
857 if (ret_src_address) {
859 avahi_address_from_sockaddr((struct sockaddr*) &sa, &a);
860 *ret_src_address = a.data.ipv6;
863 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
865 if (cmsg->cmsg_level == IPPROTO_IPV6) {
867 switch (cmsg->cmsg_type) {
872 *ret_ttl = (uint8_t) (*(int *) CMSG_DATA(cmsg));
879 struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
881 if (ret_iface && i->ipi6_ifindex > 0)
882 *ret_iface = i->ipi6_ifindex;
885 memcpy(ret_dst_address->address, i->ipi6_addr.s6_addr, 16);
892 avahi_log_warn("Unhandled cmsg_type: %d", cmsg->cmsg_type);
905 avahi_dns_packet_free(p);
910 int avahi_open_unicast_socket_ipv4(void) {
911 struct sockaddr_in local;
914 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
915 avahi_log_warn("socket() failed: %s", strerror(errno));
919 memset(&local, 0, sizeof(local));
920 local.sin_family = AF_INET;
922 if (bind(fd, (struct sockaddr*) &local, sizeof(local)) < 0) {
923 avahi_log_warn("bind() failed: %s", strerror(errno));
927 if (ipv4_pktinfo(fd) < 0) {
931 if (avahi_set_cloexec(fd) < 0) {
932 avahi_log_warn("FD_CLOEXEC failed: %s", strerror(errno));
936 if (avahi_set_nonblock(fd) < 0) {
937 avahi_log_warn("O_NONBLOCK failed: %s", strerror(errno));
950 int avahi_open_unicast_socket_ipv6(void) {
951 struct sockaddr_in6 local;
954 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
955 avahi_log_warn("socket() failed: %s", strerror(errno));
960 if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes)) < 0) {
961 avahi_log_warn("IPV6_V6ONLY failed: %s", strerror(errno));
965 memset(&local, 0, sizeof(local));
966 local.sin6_family = AF_INET6;
968 if (bind(fd, (struct sockaddr*) &local, sizeof(local)) < 0) {
969 avahi_log_warn("bind() failed: %s", strerror(errno));
973 if (ipv6_pktinfo(fd) < 0)
976 if (avahi_set_cloexec(fd) < 0) {
977 avahi_log_warn("FD_CLOEXEC failed: %s", strerror(errno));
981 if (avahi_set_nonblock(fd) < 0) {
982 avahi_log_warn("O_NONBLOCK failed: %s", strerror(errno));