+int avahi_open_unicast_socket_ipv4(void) {
+ struct sockaddr_in local;
+ int fd = -1, yes;
+
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ avahi_log_warn("socket() failed: %s", strerror(errno));
+ goto fail;
+ }
+
+ memset(&local, 0, sizeof(local));
+ local.sin_family = AF_INET;
+
+ if (bind(fd, (struct sockaddr*) &local, sizeof(local)) < 0) {
+ avahi_log_warn("bind() failed: %s", strerror(errno));
+ goto fail;
+ }
+
+ yes = 1;
+ if (setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &yes, sizeof(yes)) < 0) {
+ avahi_log_warn("IP_RECVTTL failed: %s", strerror(errno));
+ goto fail;
+ }
+
+ yes = 1;
+ if (ip_pktinfo (fd, yes) < 0) {
+ goto fail;
+ }
+
+ if (avahi_set_cloexec(fd) < 0) {
+ avahi_log_warn("FD_CLOEXEC failed: %s", strerror(errno));
+ goto fail;
+ }
+
+ if (avahi_set_nonblock(fd) < 0) {
+ avahi_log_warn("O_NONBLOCK failed: %s", strerror(errno));
+ goto fail;
+ }
+
+ return fd;
+
+fail:
+ if (fd >= 0)
+ close(fd);
+
+ return -1;
+}
+
+int avahi_open_unicast_socket_ipv6(void) {
+ struct sockaddr_in6 local;
+ int fd = -1, yes;
+
+ if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ avahi_log_warn("socket() failed: %s", strerror(errno));
+ goto fail;
+ }
+
+ memset(&local, 0, sizeof(local));
+ local.sin6_family = AF_INET6;
+
+ if (bind(fd, (struct sockaddr*) &local, sizeof(local)) < 0) {
+ avahi_log_warn("bind() failed: %s", strerror(errno));
+ goto fail;
+ }
+
+#ifdef IPV6_RECVHOPS
+ yes = 1;
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPS, &yes, sizeof(yes)) < 0) {
+ avahi_log_warn("IPV6_RECVHOPS failed: %s", strerror(errno));
+ goto fail;
+ }
+#elif IPV6_RECVHOPLIMIT
+ yes = 1;
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &yes, sizeof(yes)) < 0) {
+ avahi_log_warn("IPV6_RECVHOPLIMIT failed: %s", strerror(errno));
+ goto fail;
+ }
+#elif IPV6_HOPLIMIT
+ yes = 1;
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_HOPLIMIT, &yes, sizeof(yes)) < 0) {
+ avahi_log_warn("IPV6_HOPLIMIT failed: %s", strerror(errno));
+ goto fail;
+ }
+#endif
+
+#ifdef IPV6_RECVPKTINFO
+ yes = 1;
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &yes, sizeof(yes)) < 0) {
+ avahi_log_warn("IPV6_RECVPKTINFO failed: %s", strerror(errno));
+ goto fail;
+ }
+#elif IPV6_PKTINFO
+ yes = 1;
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &yes, sizeof(yes)) < 0) {
+ avahi_log_warn("IPV6_PKTINFO failed: %s", strerror(errno));
+ goto fail;
+ }
+#endif
+
+ if (avahi_set_cloexec(fd) < 0) {
+ avahi_log_warn("FD_CLOEXEC failed: %s", strerror(errno));
+ goto fail;
+ }
+
+ if (avahi_set_nonblock(fd) < 0) {
+ avahi_log_warn("O_NONBLOCK failed: %s", strerror(errno));
+ goto fail;
+ }
+
+ return fd;
+
+fail:
+ if (fd >= 0)
+ close(fd);
+
+ return -1;
+}