From owner-svn-src-stable@freebsd.org Fri May 24 06:27:13 2019 Return-Path: Delivered-To: svn-src-stable@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 11AC7159E1DA; Fri, 24 May 2019 06:27:13 +0000 (UTC) (envelope-from glebius@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id A7F6C76CB6; Fri, 24 May 2019 06:27:12 +0000 (UTC) (envelope-from glebius@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 8351E18E31; Fri, 24 May 2019 06:27:12 +0000 (UTC) (envelope-from glebius@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x4O6RC5i052948; Fri, 24 May 2019 06:27:12 GMT (envelope-from glebius@FreeBSD.org) Received: (from glebius@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x4O6RCHe052946; Fri, 24 May 2019 06:27:12 GMT (envelope-from glebius@FreeBSD.org) Message-Id: <201905240627.x4O6RCHe052946@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: glebius set sender to glebius@FreeBSD.org using -f From: Gleb Smirnoff Date: Fri, 24 May 2019 06:27:12 +0000 (UTC) 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 X-SVN-Group: stable-12 X-SVN-Commit-Author: glebius X-SVN-Commit-Paths: in stable/12: share/man/man4 sys/netinet X-SVN-Commit-Revision: 348230 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: A7F6C76CB6 X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.97 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-1.00)[-0.997,0]; NEURAL_HAM_LONG(-1.00)[-1.000,0]; NEURAL_HAM_SHORT(-0.97)[-0.973,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US] X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 24 May 2019 06:27:13 -0000 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);