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

Commit 6a6ddb2a authored by Sridhar Samudrala's avatar Sridhar Samudrala Committed by David S. Miller
Browse files

[SCTP] Fix incorrect setting of sk_bound_dev_if when binding/sending to a ipv6


link local address.

Signed-off-by: default avatarSridhar Samudrala <sri@us.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cdac4e07
Loading
Loading
Loading
Loading
+15 −21
Original line number Original line Diff line number Diff line
@@ -812,26 +812,23 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
	if (addr->sa.sa_family != AF_INET6)
	if (addr->sa.sa_family != AF_INET6)
		af = sctp_get_af_specific(addr->sa.sa_family);
		af = sctp_get_af_specific(addr->sa.sa_family);
	else {
	else {
		struct sock *sk;
		int type = ipv6_addr_type(&addr->v6.sin6_addr);
		int type = ipv6_addr_type(&addr->v6.sin6_addr);
		sk = sctp_opt2sk(opt);
		struct net_device *dev;
		if (type & IPV6_ADDR_LINKLOCAL) {
			/* Note: Behavior similar to af_inet6.c:
			 *  1) Overrides previous bound_dev_if
			 *  2) Destructive even if bind isn't successful.
			 */


			if (addr->v6.sin6_scope_id)
		if (type & IPV6_ADDR_LINKLOCAL) {
				sk->sk_bound_dev_if = addr->v6.sin6_scope_id;
			if (!addr->v6.sin6_scope_id)
			if (!sk->sk_bound_dev_if)
				return 0;
			dev = dev_get_by_index(addr->v6.sin6_scope_id);
			if (!dev)
				return 0;
				return 0;
			dev_put(dev);
		}
		}
		af = opt->pf->af;
		af = opt->pf->af;
	}
	}
	return af->available(addr, opt);
	return af->available(addr, opt);
}
}


/* Verify that the provided sockaddr looks bindable.   Common verification,
/* Verify that the provided sockaddr looks sendable.   Common verification,
 * has already been taken care of.
 * has already been taken care of.
 */
 */
static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr)
static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr)
@@ -842,19 +839,16 @@ static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr)
	if (addr->sa.sa_family != AF_INET6)
	if (addr->sa.sa_family != AF_INET6)
		af = sctp_get_af_specific(addr->sa.sa_family);
		af = sctp_get_af_specific(addr->sa.sa_family);
	else {
	else {
		struct sock *sk;
		int type = ipv6_addr_type(&addr->v6.sin6_addr);
		int type = ipv6_addr_type(&addr->v6.sin6_addr);
		sk = sctp_opt2sk(opt);
		struct net_device *dev;
		if (type & IPV6_ADDR_LINKLOCAL) {
			/* Note: Behavior similar to af_inet6.c:
			 *  1) Overrides previous bound_dev_if
			 *  2) Destructive even if bind isn't successful.
			 */


			if (addr->v6.sin6_scope_id)
		if (type & IPV6_ADDR_LINKLOCAL) {
				sk->sk_bound_dev_if = addr->v6.sin6_scope_id;
			if (!addr->v6.sin6_scope_id)
			if (!sk->sk_bound_dev_if)
				return 0;
			dev = dev_get_by_index(addr->v6.sin6_scope_id);
			if (!dev)
				return 0;
				return 0;
			dev_put(dev);
		}
		}
		af = opt->pf->af;
		af = opt->pf->af;
	}
	}