| Summary: | IPv4 multicast does not work without route | ||
|---|---|---|---|
| Product: | Base System | Reporter: | root <sam> |
| Component: | kern | Assignee: | freebsd-bugs (Nobody) <bugs> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | 5.0-CURRENT | ||
| Hardware: | Any | ||
| OS: | Any | ||
<<On Thu, 8 Jun 2000 14:06:27 +0200 (CEST), sam@inf.enst.fr said: > A FreeBSD box on a private network with IPv4 routes to local > network only. No default route has been set, nor any route for > the 224.0.0.0/8 addresses. Then your configuration is broken. If you want to send multicasts, you MUST configure a route for them, end of story. This requirement has existed throughout the entire history of IP multicast under UNIX. Note that it would be an error for packets to be multicast out multiple interfaces simultaneously. The definition of the multicast service model says that hosts MUST NOT do this; only a multicast router is permitted to send the same packet in multiple directions at once. -GAWollman -- Garrett A. Wollman | O Siem / We are all family / O Siem / We're all the same wollman@lcs.mit.edu | O Siem / The fires of freedom Opinions not those of| Dance in the burning flame MIT, LCS, CRS, or NSA| - Susan Aglukark and Chad Irschick State Changed From-To: open->closed Multicast requires a route. See wollman's comments in the Audit-Trail for details. |
When trying to join a multicast group with a IPPROTO_IP/ADD_MEMBERSHIP ioctl call on a IPv4 socket, FreeBSD tries to find a suitable network interface using the regular routing table: From netinet/ip_output.c: s = splimp(); /* * If no interface address was provided, use the interface of * the route to the given multicast address. */ if (mreq.imr_interface.s_addr == INADDR_ANY) { bzero((caddr_t)&ro, sizeof(ro)); dst = (struct sockaddr_in *)&ro.ro_dst; dst->sin_len = sizeof(*dst); dst->sin_family = AF_INET; dst->sin_addr = mreq.imr_multiaddr; rtalloc(&ro); if (ro.ro_rt == NULL) { error = EADDRNOTAVAIL; splx(s); break; } ifp = ro.ro_rt->rt_ifp; rtfree(ro.ro_rt); } On a FreeBSD box with one ethernet card connected to a local network and with no default route, this means that EADDRNOTAVAIL will be returned when trying to join an IPv4 multicast group. This is not a theoritical-only case: this happens on a home network (which sometimes connects to the internet using PPP) when NTP is launched on the ntp.mcast.net address to reach the various subnets. Also, if several interfaces are multicast-capable, at most one of them will be selected. Packets emitted from the host will be sent to at most one local network (I believe, I haven't tested this configuration). Fix: (I haven't had a chance to test this, it is pure guess) When no interface is explicitely given, netinet/ip_output.c should do two things instead of looking for a suitable interface in the routing table: (1) Fill a slot in the imo structure with imo_multicast_ifp field being NULL. (2) Add a slot for every multicast-capable interface and subscribe this interface to the multicast group. Also, when an interface M_MCAST flag is set (or when the interface is brought up), a new slot should be added. Deletion of a multicast membership should follow the same logic. This way, every new interface added to the system (as I do with my laptop) will automatically start sending multicast packets if it is multicast capable. How-To-Repeat: Remove your default route, make sure that you have no explicit route for 224.0.0.0/8 addresses and start sdr. You will get an error from setsockopt (can't assign requested address).