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

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

[SCTP]: ADDIP: Don't use an address as source until it is ASCONF-ACKed



This implements Rules D1 and D4 of Sec 4.3 in the ADDIP draft.

Signed-off-by: default avatarSridhar Samudrala <sri@us.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9faa730f
Loading
Loading
Loading
Loading
+2 −5
Original line number Diff line number Diff line
@@ -731,13 +731,10 @@ void sctp_init_addrs(struct sctp_chunk *, union sctp_addr *,
const union sctp_addr *sctp_source(const struct sctp_chunk *chunk);

/* This is a structure for holding either an IPv6 or an IPv4 address.  */
/* sin_family -- AF_INET or AF_INET6
 * sin_port -- ordinary port number
 * sin_addr -- cast to either (struct in_addr) or (struct in6_addr)
 */
struct sctp_sockaddr_entry {
	struct list_head list;
	union sctp_addr a;
	__u8 use_as_src;
};

typedef struct sctp_chunk *(sctp_packet_phandler_t)(struct sctp_association *);
@@ -1142,7 +1139,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
			sctp_scope_t scope, gfp_t gfp,
			int flags);
int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
		       gfp_t gfp);
		       __u8 use_as_src, gfp_t gfp);
int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *);
int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *,
			 struct sctp_sock *);
+5 −3
Original line number Diff line number Diff line
@@ -146,7 +146,7 @@ void sctp_bind_addr_free(struct sctp_bind_addr *bp)

/* Add an address to the bind address list in the SCTP_bind_addr structure. */
int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
		       gfp_t gfp)
		       __u8 use_as_src, gfp_t gfp)
{
	struct sctp_sockaddr_entry *addr;

@@ -163,6 +163,8 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
	if (!addr->a.v4.sin_port)
		addr->a.v4.sin_port = bp->port;

	addr->use_as_src = use_as_src;

	INIT_LIST_HEAD(&addr->list);
	list_add_tail(&addr->list, &bp->address_list);
	SCTP_DBG_OBJCNT_INC(addr);
@@ -274,7 +276,7 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list,
		}

		af->from_addr_param(&addr, rawaddr, port, 0);
		retval = sctp_add_bind_addr(bp, &addr, gfp);
		retval = sctp_add_bind_addr(bp, &addr, 1, gfp);
		if (retval) {
			/* Can't finish building the list, clean up. */
			sctp_bind_addr_clean(bp);
@@ -367,7 +369,7 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest,
		    (((AF_INET6 == addr->sa.sa_family) &&
		      (flags & SCTP_ADDR6_ALLOWED) &&
		      (flags & SCTP_ADDR6_PEERSUPP))))
			error = sctp_add_bind_addr(dest, addr, gfp);
			error = sctp_add_bind_addr(dest, addr, 1, gfp);
	}

	return error;
+2 −1
Original line number Diff line number Diff line
@@ -290,7 +290,8 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc,
	sctp_read_lock(addr_lock);
	list_for_each(pos, &bp->address_list) {
		laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
		if ((laddr->a.sa.sa_family == AF_INET6) &&
		if ((laddr->use_as_src) &&
		    (laddr->a.sa.sa_family == AF_INET6) &&
		    (scope <= sctp_scope(&laddr->a))) {
			bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a);
			if (!baddr || (matchlen < bmatchlen)) {
+5 −2
Original line number Diff line number Diff line
@@ -240,7 +240,7 @@ int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope,
			    (((AF_INET6 == addr->a.sa.sa_family) &&
			      (copy_flags & SCTP_ADDR6_ALLOWED) &&
			      (copy_flags & SCTP_ADDR6_PEERSUPP)))) {
				error = sctp_add_bind_addr(bp, &addr->a, 
				error = sctp_add_bind_addr(bp, &addr->a, 1,
							   GFP_ATOMIC);
				if (error)
					goto end_copy;
@@ -486,6 +486,8 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
		list_for_each(pos, &bp->address_list) {
			laddr = list_entry(pos, struct sctp_sockaddr_entry,
					   list);
			if (!laddr->use_as_src)
				continue;
			sctp_v4_dst_saddr(&dst_saddr, dst, bp->port);
			if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a))
				goto out_unlock;
@@ -506,7 +508,8 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
	list_for_each(pos, &bp->address_list) {
		laddr = list_entry(pos, struct sctp_sockaddr_entry, list);

		if (AF_INET == laddr->a.sa.sa_family) {
		if ((laddr->use_as_src) &&
		    (AF_INET == laddr->a.sa.sa_family)) {
			fl.fl4_src = laddr->a.v4.sin_addr.s_addr;
			if (!ip_route_output_key(&rt, &fl)) {
				dst = &rt->u.dst;
+8 −2
Original line number Diff line number Diff line
@@ -1493,7 +1493,7 @@ struct sctp_association *sctp_unpack_cookie(

	/* Also, add the destination address. */
	if (list_empty(&retval->base.bind_addr.address_list)) {
		sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest,
		sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest, 1,
				   GFP_ATOMIC);
	}

@@ -2565,6 +2565,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
	union sctp_addr_param *addr_param;
	struct list_head *pos;
	struct sctp_transport *transport;
	struct sctp_sockaddr_entry *saddr;
	int retval = 0;

	addr_param = (union sctp_addr_param *)
@@ -2578,7 +2579,11 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
	case SCTP_PARAM_ADD_IP:
		sctp_local_bh_disable();
		sctp_write_lock(&asoc->base.addr_lock);
		retval = sctp_add_bind_addr(bp, &addr, GFP_ATOMIC);
		list_for_each(pos, &bp->address_list) {
			saddr = list_entry(pos, struct sctp_sockaddr_entry, list);
			if (sctp_cmp_addr_exact(&saddr->a, &addr))
				saddr->use_as_src = 1;
		}
		sctp_write_unlock(&asoc->base.addr_lock);
		sctp_local_bh_enable();
		break;
@@ -2591,6 +2596,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
		list_for_each(pos, &asoc->peer.transport_addr_list) {
			transport = list_entry(pos, struct sctp_transport,
						 transports);
			dst_release(transport->dst);
			sctp_transport_route(transport, NULL,
					     sctp_sk(asoc->base.sk));
		}
Loading