Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 917f2f10 authored by David L Stevens's avatar David L Stevens Committed by David S. Miller
Browse files

[IPV4]: multicast API "join" issues



1) In the full-state API when imsf_numsrc == 0
   errno should be "0", but returns EADDRNOTAVAIL

2) An illegal filter mode change
   errno should be EINVAL, but returns EADDRNOTAVAIL

3) Trying to do an any-source option without IP_ADD_MEMBERSHIP
   errno should be EINVAL, but returns EADDRNOTAVAIL

4) Adds comments for the less obvious error return values

Signed-off-by: default avatarDavid L Stevens <dlstevens@us.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8cdaaa15
Loading
Loading
Loading
Loading
+12 −6
Original line number Diff line number Diff line
@@ -1748,12 +1748,16 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
		    && pmc->multi.imr_ifindex == imr.imr_ifindex)
			break;
	}
	if (!pmc)		/* must have a prior join */
	if (!pmc) {		/* must have a prior join */
		err = -EINVAL;
		goto done;
	}
	/* if a source filter was set, must be the same mode as before */
	if (pmc->sflist) {
		if (pmc->sfmode != omode)
		if (pmc->sfmode != omode) {
			err = -EINVAL;
			goto done;
		}
	} else if (pmc->sfmode != omode) {
		/* allow mode switches for empty-set filters */
		ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 0, NULL, 0);
@@ -1765,7 +1769,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
	psl = pmc->sflist;
	if (!add) {
		if (!psl)
			goto done;
			goto done;	/* err = -EADDRNOTAVAIL */
		rv = !0;
		for (i=0; i<psl->sl_count; i++) {
			rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
@@ -1774,7 +1778,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
				break;
		}
		if (rv)		/* source not found */
			goto done;
			goto done;	/* err = -EADDRNOTAVAIL */

		/* special case - (INCLUDE, empty) == LEAVE_GROUP */
		if (psl->sl_count == 1 && omode == MCAST_INCLUDE) {
@@ -1870,15 +1874,16 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
		err = -ENODEV;
		goto done;
	}
	err = -EADDRNOTAVAIL;

	for (pmc=inet->mc_list; pmc; pmc=pmc->next) {
		if (pmc->multi.imr_multiaddr.s_addr == msf->imsf_multiaddr &&
		    pmc->multi.imr_ifindex == imr.imr_ifindex)
			break;
	}
	if (!pmc)		/* must have a prior join */
	if (!pmc) {		/* must have a prior join */
		err = -EINVAL;
		goto done;
	}
	if (msf->imsf_numsrc) {
		newpsl = (struct ip_sf_socklist *)sock_kmalloc(sk,
				IP_SFLSIZE(msf->imsf_numsrc), GFP_KERNEL);
@@ -1907,6 +1912,7 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
			0, NULL, 0);
	pmc->sflist = newpsl;
	pmc->sfmode = msf->imsf_fmode;
	err = 0;
done:
	rtnl_shunlock();
	return err;
+12 −6
Original line number Diff line number Diff line
@@ -386,12 +386,16 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
		if (ipv6_addr_equal(&pmc->addr, group))
			break;
	}
	if (!pmc)		/* must have a prior join */
	if (!pmc) {		/* must have a prior join */
		err = -EINVAL;
		goto done;
	}
	/* if a source filter was set, must be the same mode as before */
	if (pmc->sflist) {
		if (pmc->sfmode != omode)
		if (pmc->sfmode != omode) {
			err = -EINVAL;
			goto done;
		}
	} else if (pmc->sfmode != omode) {
		/* allow mode switches for empty-set filters */
		ip6_mc_add_src(idev, group, omode, 0, NULL, 0);
@@ -402,7 +406,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
	psl = pmc->sflist;
	if (!add) {
		if (!psl)
			goto done;
			goto done;	/* err = -EADDRNOTAVAIL */
		rv = !0;
		for (i=0; i<psl->sl_count; i++) {
			rv = memcmp(&psl->sl_addr[i], source,
@@ -411,7 +415,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
				break;
		}
		if (rv)		/* source not found */
			goto done;
			goto done;	/* err = -EADDRNOTAVAIL */

		/* special case - (INCLUDE, empty) == LEAVE_GROUP */
		if (psl->sl_count == 1 && omode == MCAST_INCLUDE) {
@@ -503,7 +507,6 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
	if (!idev)
		return -ENODEV;
	dev = idev->dev;
	err = -EADDRNOTAVAIL;

	for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) {
		if (pmc->ifindex != gsf->gf_interface)
@@ -511,8 +514,10 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
		if (ipv6_addr_equal(&pmc->addr, group))
			break;
	}
	if (!pmc)		/* must have a prior join */
	if (!pmc) {		/* must have a prior join */
		err = -EINVAL;
		goto done;
	}
	if (gsf->gf_numsrc) {
		newpsl = (struct ip6_sf_socklist *)sock_kmalloc(sk,
				IP6_SFLSIZE(gsf->gf_numsrc), GFP_ATOMIC);
@@ -544,6 +549,7 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
		(void) ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0);
	pmc->sflist = newpsl;
	pmc->sfmode = gsf->gf_fmode;
	err = 0;
done:
	read_unlock_bh(&idev->lock);
	in6_dev_put(idev);