setsockopt(IPPROTO_IP, IP_MULTICAST_IF / IP_MULTICAST_TTL) succeeds on a raw IPv4 socket and reads back (src/bsdsocket/options.c:583-589 hands every socket kind to bsd_mcast_setopt(), which stores as_McastIf / as_McastTtl), but the raw send path uses neither.
| Option |
Raw send path |
Effect |
| IP_MULTICAST_TTL |
ttl = as_Ttl (src/bsdsocket/raw.c:601); no multicast branch unless IP_HDRINCL supplies the TTL |
a multicast datagram leaves with the unicast TTL (default 64), not the multicast default 1 or the value set |
| IP_MULTICAST_IF |
bsd_raw_route_index(dest) routes with no preference (raw.c:580-588, :695) |
the datagram leaves by the route, not the chosen interface |
UDP applies both via bsd_mcast_prepare_send() (mcast.c:234).
Repro (two interfaces, e.g. a2065 + zeth1): raw socket, protocol 253; IP_MULTICAST_TTL=1, IP_MULTICAST_IF=<zeth1 address>; sendto(239.255.42.99). Captured on the peer: TTL 64, egress on the route's interface. Expected: TTL 1, egress zeth1.
Priority below #38/#39/#42/#45. #47 covers raw IP_MULTICAST_LOOP only.
🤖 Generated with Claude Code
setsockopt(IPPROTO_IP, IP_MULTICAST_IF / IP_MULTICAST_TTL)succeeds on a raw IPv4 socket and reads back (src/bsdsocket/options.c:583-589hands every socket kind tobsd_mcast_setopt(), which storesas_McastIf/as_McastTtl), but the raw send path uses neither.ttl = as_Ttl(src/bsdsocket/raw.c:601); no multicast branch unless IP_HDRINCL supplies the TTLbsd_raw_route_index(dest)routes with no preference (raw.c:580-588,:695)UDP applies both via
bsd_mcast_prepare_send()(mcast.c:234).Repro (two interfaces, e.g. a2065 + zeth1): raw socket, protocol 253;
IP_MULTICAST_TTL=1,IP_MULTICAST_IF=<zeth1 address>;sendto(239.255.42.99). Captured on the peer: TTL 64, egress on the route's interface. Expected: TTL 1, egress zeth1.Priority below #38/#39/#42/#45. #47 covers raw IP_MULTICAST_LOOP only.
🤖 Generated with Claude Code