[libslirp] allow guest->host MDNS service discovery
Reproduce:
1. On host run apache-httpd
2. On host use chrome to visit "<machine-name>.local:80"
3. Observe web page response: "It Works!"
4. On GUEST use chrome to visit same URL
5. Note the timeout
BUG: 342830958
Change-Id: If590c2a49a55f6025ac9a8f47a3122f6012bde02
diff --git a/src/udp.c b/src/udp.c
index 1693ad3..a811a52 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -220,7 +220,30 @@
icmp_send_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, 0, NULL);
goto bad;
}
- setsockopt(so->s, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
+
+ /*
+ * Check for MULTICAST
+ */
+ if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
+ setsockopt(so->s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
+ DEBUG_MISC("multicast");
+ if (!slirp->disable_host_loopback) {
+ DEBUG_MISC("multicast loopback enabled");
+ int loopback = 1; // Enable loopback
+ if (setsockopt(so->s, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopback, sizeof(loopback)) == -1) {
+ DEBUG_MISC(" multicast loop errno = %d-%s", errno, strerror(errno));
+ };
+ }
+ struct ip_mreq mreq;
+ mreq.imr_multiaddr.s_addr = ip->ip_dst.s_addr; // Multicast group address
+ mreq.imr_interface.s_addr = htonl(INADDR_ANY); // Interface to use
+ if (setsockopt(so->s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq)) == -1) {
+ DEBUG_MISC(" multicast membership errno = %d-%s", errno, strerror(errno));
+ };
+ } else {
+ setsockopt(so->s, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
+ }
+
/*
* Now we sendto() the packet.
diff --git a/src/udp6.c b/src/udp6.c
index effdf77..c6a577c 100644
--- a/src/udp6.c
+++ b/src/udp6.c
@@ -128,7 +128,28 @@
icmp6_send_error(m, ICMP6_TIMXCEED, ICMP6_TIMXCEED_INTRANS);
goto bad;
}
- setsockopt(so->s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hop_limit, sizeof(hop_limit));
+
+ /*
+ * Check for MULTICAST
+ */
+ if (IN6_IS_ADDR_MULTICAST(&ip->ip_dst)) {
+ setsockopt(so->s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hop_limit, sizeof(hop_limit));
+ if (!so->slirp->disable_host_loopback) {
+ DEBUG_MISC("multicast loopback enabled\n");
+ int loopback = 1; // Enable loopback
+ if (setsockopt(so->s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *)&loopback, sizeof(loopback)) == -1) {
+ DEBUG_MISC(" multicast loop errno = %d-%s\n", errno, strerror(errno));
+ };
+ }
+ struct ipv6_mreq mreq;
+ mreq.ipv6mr_multiaddr = ip->ip_dst; // Multicast group address
+ mreq.ipv6mr_interface = 0; // The default multicast interface is used when set 0.
+ if (setsockopt(so->s, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mreq, sizeof(mreq)) == -1) {
+ DEBUG_MISC("multicast membership errno = %d-%s\n", errno, strerror(errno));
+ };
+ } else {
+ setsockopt(so->s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hop_limit, sizeof(hop_limit));
+ }
/*
* Now we sendto() the packet.