Date: Fri, 24 May 2019 06:27:12 +0000 (UTC) From: Gleb Smirnoff <glebius@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r348230 - in stable/12: share/man/man4 sys/netinet Message-ID: <201905240627.x4O6RCHe052946@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: glebius Date: Fri May 24 06:27:11 2019 New Revision: 348230 URL: https://svnweb.freebsd.org/changeset/base/348230 Log: Merge r344481: Support struct ip_mreqn as argument for IP_ADD_MEMBERSHIP. Legacy support for struct ip_mreq remains in place. The struct ip_mreqn is Linux extension to classic BSD multicast API. It has extra field allowing to specify the interface index explicitly. In Linux it used as argument for IP_MULTICAST_IF and IP_ADD_MEMBERSHIP. FreeBSD kernel also declares this structure and supports it as argument to IP_MULTICAST_IF since r170613. So, we have structure declared but not fully supported, this confused third party application configure scripts. Code handling IP_ADD_MEMBERSHIP was mixed together with code for IP_ADD_SOURCE_MEMBERSHIP. Bringing legacy and new structure support into the mess would made the "argument switcharoo" intolerable, so code was separated into its own switch case clause. Modified: stable/12/share/man/man4/ip.4 stable/12/sys/netinet/in_mcast.c Directory Properties: stable/12/ (props changed) Modified: stable/12/share/man/man4/ip.4 ============================================================================== --- stable/12/share/man/man4/ip.4 Fri May 24 06:07:33 2019 (r348229) +++ stable/12/share/man/man4/ip.4 Fri May 24 06:27:11 2019 (r348230) @@ -28,7 +28,7 @@ .\" @(#)ip.4 8.2 (Berkeley) 11/30/93 .\" $FreeBSD$ .\" -.Dd August 19, 2018 +.Dd February 22, 2019 .Dt IP 4 .Os .Sh NAME @@ -571,32 +571,55 @@ To join a multicast group, use the .Dv IP_ADD_MEMBERSHIP option: .Bd -literal -struct ip_mreq mreq; -setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); +struct ip_mreqn mreqn; +setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreqn, sizeof(mreqn)); .Ed .Pp where -.Fa mreq +.Fa mreqn is the following structure: .Bd -literal -struct ip_mreq { +struct ip_mreqn { struct in_addr imr_multiaddr; /* IP multicast address of group */ struct in_addr imr_interface; /* local IP address of interface */ + int imr_ifindex; /* interface index */ } .Ed .Pp -.Va imr_interface -should be set to the -.Tn IP -address of a particular multicast-capable interface if +.Va imr_ifindex +should be set to the index of a particular multicast-capable interface if the host is multihomed. -It may be set to -.Dv INADDR_ANY -to choose the default interface, although this is not recommended; -this is considered to be the first interface corresponding -to the default route. -Otherwise, the first multicast-capable interface -configured in the system will be used. +If +.Va imr_ifindex +is non-zero, value of +.Va imr_interface +is ignored. +Otherwise, if +.Va imr_ifindex +is 0, kernel will use IP address from +.Va imr_interface +to lookup the interface. +Value of +.Va imr_interface +may be set to +.Va INADDR_ANY +to choose the default interface, although this is not recommended; this is +considered to be the first interface corresponding to the default route. +Otherwise, the first multicast-capable interface configured in the system +will be used. +.Pp +Legacy +.Vt "struct ip_mreq" , +that lacks +.Va imr_ifindex +field is also supported by +.Dv IP_ADD_MEMBERSHIP +setsockopt. +In this case kernel would behave as if +.Va imr_ifindex +was set to zero: +.Va imr_interface +will be used to lookup interface. .Pp Prior to .Fx 7.0 , Modified: stable/12/sys/netinet/in_mcast.c ============================================================================== --- stable/12/sys/netinet/in_mcast.c Fri May 24 06:07:33 2019 (r348229) +++ stable/12/sys/netinet/in_mcast.c Fri May 24 06:27:11 2019 (r348230) @@ -2046,40 +2046,49 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt ssa->ss.ss_family = AF_UNSPEC; switch (sopt->sopt_name) { - case IP_ADD_MEMBERSHIP: - case IP_ADD_SOURCE_MEMBERSHIP: { - struct ip_mreq_source mreqs; + case IP_ADD_MEMBERSHIP: { + struct ip_mreqn mreqn; - if (sopt->sopt_name == IP_ADD_MEMBERSHIP) { - error = sooptcopyin(sopt, &mreqs, - sizeof(struct ip_mreq), - sizeof(struct ip_mreq)); - /* - * Do argument switcharoo from ip_mreq into - * ip_mreq_source to avoid using two instances. - */ - mreqs.imr_interface = mreqs.imr_sourceaddr; - mreqs.imr_sourceaddr.s_addr = INADDR_ANY; - } else if (sopt->sopt_name == IP_ADD_SOURCE_MEMBERSHIP) { - error = sooptcopyin(sopt, &mreqs, - sizeof(struct ip_mreq_source), - sizeof(struct ip_mreq_source)); - } + if (sopt->sopt_valsize == sizeof(struct ip_mreqn)) + error = sooptcopyin(sopt, &mreqn, + sizeof(struct ip_mreqn), sizeof(struct ip_mreqn)); + else + error = sooptcopyin(sopt, &mreqn, + sizeof(struct ip_mreq), sizeof(struct ip_mreq)); if (error) return (error); gsa->sin.sin_family = AF_INET; gsa->sin.sin_len = sizeof(struct sockaddr_in); - gsa->sin.sin_addr = mreqs.imr_multiaddr; + gsa->sin.sin_addr = mreqn.imr_multiaddr; + if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr))) + return (EINVAL); - if (sopt->sopt_name == IP_ADD_SOURCE_MEMBERSHIP) { - ssa->sin.sin_family = AF_INET; - ssa->sin.sin_len = sizeof(struct sockaddr_in); - ssa->sin.sin_addr = mreqs.imr_sourceaddr; - } + if (sopt->sopt_valsize == sizeof(struct ip_mreqn) && + mreqn.imr_ifindex != 0) + ifp = ifnet_byindex(mreqn.imr_ifindex); + else + ifp = inp_lookup_mcast_ifp(inp, &gsa->sin, + mreqn.imr_address); + break; + } + case IP_ADD_SOURCE_MEMBERSHIP: { + struct ip_mreq_source mreqs; + error = sooptcopyin(sopt, &mreqs, sizeof(struct ip_mreq_source), + sizeof(struct ip_mreq_source)); + if (error) + return (error); + + gsa->sin.sin_family = ssa->sin.sin_family = AF_INET; + gsa->sin.sin_len = ssa->sin.sin_len = + sizeof(struct sockaddr_in); + + gsa->sin.sin_addr = mreqs.imr_multiaddr; if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr))) return (EINVAL); + + ssa->sin.sin_addr = mreqs.imr_sourceaddr; ifp = inp_lookup_mcast_ifp(inp, &gsa->sin, mreqs.imr_interface);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201905240627.x4O6RCHe052946>