AvahiDnsPacket *p= NULL;
struct msghdr msg;
struct iovec io;
- uint8_t aux[64];
+ uint8_t aux[1024];
ssize_t l;
struct cmsghdr *cmsg;
gboolean found_ttl = FALSE, found_iface = FALSE;
+ guint ms;
g_assert(fd >= 0);
g_assert(ret_sa);
g_assert(ret_iface);
g_assert(ret_ttl);
- p = avahi_dns_packet_new(0);
+ if (ioctl(fd, FIONREAD, &ms) < 0) {
+ g_warning("ioctl(): %s", strerror(errno));
+ goto fail;
+ }
+
+ p = avahi_dns_packet_new(ms + AVAHI_DNS_PACKET_EXTRA_SIZE);
io.iov_base = AVAHI_DNS_PACKET_DATA(p);
io.iov_len = p->max_size;
msg.msg_controllen = sizeof(aux);
msg.msg_flags = 0;
- if ((l = recvmsg(fd, &msg, 0)) < 0)
+ if ((l = recvmsg(fd, &msg, 0)) < 0) {
+ g_warning("recvmsg(): %s", strerror(errno));
goto fail;
+ }
+
+ if (ret_sa->sin_addr.s_addr == INADDR_ANY) {
+ /* Linux 2.4 behaves very strangely sometimes! */
+ avahi_hexdump(AVAHI_DNS_PACKET_DATA(p), l);
+
+
+ goto fail;
+ }
+
+ g_assert(!(msg.msg_flags & MSG_CTRUNC));
+ g_assert(!(msg.msg_flags & MSG_TRUNC));
p->size = (size_t) l;
*ret_ttl = 0;
+
+/* avahi_hexdump(msg.msg_control, msg.msg_controllen); */
- for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg,cmsg)) {
- if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_TTL) {
- *ret_ttl = *(uint8_t *) CMSG_DATA(cmsg);
- found_ttl = TRUE;
- }
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+
+/* avahi_hexdump(CMSG_DATA(cmsg), cmsg->cmsg_len - sizeof(struct cmsghdr)); */
+
+ if (cmsg->cmsg_level == SOL_IP) {
- if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO) {
- *ret_iface = ((struct in_pktinfo*) CMSG_DATA(cmsg))->ipi_ifindex;
- found_iface = TRUE;
+ if (cmsg->cmsg_type == IP_TTL) {
+ *ret_ttl = (uint8_t) (*(int *) CMSG_DATA(cmsg));
+ found_ttl = TRUE;
+ } else if (cmsg->cmsg_type == IP_PKTINFO) {
+ *ret_iface = (gint) ((struct in_pktinfo*) CMSG_DATA(cmsg))->ipi_ifindex;
+ found_iface = TRUE;
+ }
}
}
+/* g_message("ttl=%u iface=%i", *ret_ttl, *ret_iface); */
+
g_assert(found_iface);
g_assert(found_ttl);
struct iovec io;
uint8_t aux[64];
ssize_t l;
+ guint ms;
+
struct cmsghdr *cmsg;
gboolean found_ttl = FALSE, found_iface = FALSE;
g_assert(ret_iface);
g_assert(ret_ttl);
- p = avahi_dns_packet_new(0);
+ if (ioctl(fd, FIONREAD, &ms) < 0) {
+ g_warning("ioctl(): %s", strerror(errno));
+ goto fail;
+ }
+
+ p = avahi_dns_packet_new(ms + AVAHI_DNS_PACKET_EXTRA_SIZE);
io.iov_base = AVAHI_DNS_PACKET_DATA(p);
io.iov_len = p->max_size;
msg.msg_controllen = sizeof(aux);
msg.msg_flags = 0;
- if ((l = recvmsg(fd, &msg, 0)) < 0)
+ if ((l = recvmsg(fd, &msg, 0)) < 0) {
+ g_warning("recvmsg(): %s", strerror(errno));
goto fail;
+ }
p->size = (size_t) l;
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_level == SOL_IPV6 && cmsg->cmsg_type == IPV6_HOPLIMIT) {
- *ret_ttl = *(uint8_t *) CMSG_DATA(cmsg);
+ *ret_ttl = (uint8_t) (*(int *) CMSG_DATA(cmsg));
found_ttl = TRUE;
}
return NULL;
}
+gint avahi_open_legacy_unicast_socket_ipv4(void) {
+ struct sockaddr_in local;
+ int fd = -1, yes;
+
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ g_warning("socket() failed: %s\n", strerror(errno));
+ goto fail;
+ }
+
+ memset(&local, 0, sizeof(local));
+ local.sin_family = AF_INET;
+
+ if (bind(fd, (struct sockaddr*) &local, sizeof(local)) < 0) {
+ g_warning("bind() failed: %s\n", strerror(errno));
+ goto fail;
+ }
+
+ yes = 1;
+ if (setsockopt(fd, SOL_IP, IP_RECVTTL, &yes, sizeof(yes)) < 0) {
+ g_warning("IP_RECVTTL failed: %s\n", strerror(errno));
+ goto fail;
+ }
+
+ yes = 1;
+ if (setsockopt(fd, SOL_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0) {
+ g_warning("IP_PKTINFO failed: %s\n", strerror(errno));
+ goto fail;
+ }
+
+ if (avahi_set_cloexec(fd) < 0) {
+ g_warning("FD_CLOEXEC failed: %s\n", strerror(errno));
+ goto fail;
+ }
+
+ if (avahi_set_nonblock(fd) < 0) {
+ g_warning("O_NONBLOCK failed: %s\n", strerror(errno));
+ goto fail;
+ }
+
+ return fd;
+
+fail:
+ if (fd >= 0)
+ close(fd);
+
+ return -1;
+}
+
+gint avahi_open_legacy_unicast_socket_ipv6(void) {
+ struct sockaddr_in local;
+ int fd = -1, yes;
+
+ if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ g_warning("socket() failed: %s\n", strerror(errno));
+ goto fail;
+ }
+
+ memset(&local, 0, sizeof(local));
+ local.sin_family = AF_INET;
+
+ if (bind(fd, (struct sockaddr*) &local, sizeof(local)) < 0) {
+ g_warning("bind() failed: %s\n", strerror(errno));
+ goto fail;
+ }
+
+ yes = 1;
+ if (setsockopt(fd, SOL_IPV6, IPV6_HOPLIMIT, &yes, sizeof(yes)) < 0) {
+ g_warning("IPV6_HOPLIMIT failed: %s\n", strerror(errno));
+ goto fail;
+ }
+
+ yes = 1;
+ if (setsockopt(fd, SOL_IPV6, IPV6_PKTINFO, &yes, sizeof(yes)) < 0) {
+ g_warning("IPV6_PKTINFO failed: %s\n", strerror(errno));
+ goto fail;
+ }
+
+ if (avahi_set_cloexec(fd) < 0) {
+ g_warning("FD_CLOEXEC failed: %s\n", strerror(errno));
+ goto fail;
+ }
+
+ if (avahi_set_nonblock(fd) < 0) {
+ g_warning("O_NONBLOCK failed: %s\n", strerror(errno));
+ goto fail;
+ }
+
+ return fd;
+
+fail:
+ if (fd >= 0)
+ close(fd);
+
+ return -1;
+}