|
@@ -583,10 +583,6 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
- retval = sctp_send_asconf(asoc, chunk);
|
|
|
|
- if (retval)
|
|
|
|
- goto out;
|
|
|
|
-
|
|
|
|
/* Add the new addresses to the bind address list with
|
|
/* Add the new addresses to the bind address list with
|
|
* use_as_src set to 0.
|
|
* use_as_src set to 0.
|
|
*/
|
|
*/
|
|
@@ -599,6 +595,23 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
|
|
SCTP_ADDR_NEW, GFP_ATOMIC);
|
|
SCTP_ADDR_NEW, GFP_ATOMIC);
|
|
addr_buf += af->sockaddr_len;
|
|
addr_buf += af->sockaddr_len;
|
|
}
|
|
}
|
|
|
|
+ if (asoc->src_out_of_asoc_ok) {
|
|
|
|
+ struct sctp_transport *trans;
|
|
|
|
+
|
|
|
|
+ list_for_each_entry(trans,
|
|
|
|
+ &asoc->peer.transport_addr_list, transports) {
|
|
|
|
+ /* Clear the source and route cache */
|
|
|
|
+ dst_release(trans->dst);
|
|
|
|
+ trans->cwnd = min(4*asoc->pathmtu, max_t(__u32,
|
|
|
|
+ 2*asoc->pathmtu, 4380));
|
|
|
|
+ trans->ssthresh = asoc->peer.i.a_rwnd;
|
|
|
|
+ trans->rto = asoc->rto_initial;
|
|
|
|
+ trans->rtt = trans->srtt = trans->rttvar = 0;
|
|
|
|
+ sctp_transport_route(trans, NULL,
|
|
|
|
+ sctp_sk(asoc->base.sk));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ retval = sctp_send_asconf(asoc, chunk);
|
|
}
|
|
}
|
|
|
|
|
|
out:
|
|
out:
|
|
@@ -715,7 +728,9 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
|
|
struct sctp_sockaddr_entry *saddr;
|
|
struct sctp_sockaddr_entry *saddr;
|
|
int i;
|
|
int i;
|
|
int retval = 0;
|
|
int retval = 0;
|
|
|
|
+ int stored = 0;
|
|
|
|
|
|
|
|
+ chunk = NULL;
|
|
if (!sctp_addip_enable)
|
|
if (!sctp_addip_enable)
|
|
return retval;
|
|
return retval;
|
|
|
|
|
|
@@ -766,8 +781,33 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
|
|
bp = &asoc->base.bind_addr;
|
|
bp = &asoc->base.bind_addr;
|
|
laddr = sctp_find_unmatch_addr(bp, (union sctp_addr *)addrs,
|
|
laddr = sctp_find_unmatch_addr(bp, (union sctp_addr *)addrs,
|
|
addrcnt, sp);
|
|
addrcnt, sp);
|
|
- if (!laddr)
|
|
|
|
- continue;
|
|
|
|
|
|
+ if ((laddr == NULL) && (addrcnt == 1)) {
|
|
|
|
+ if (asoc->asconf_addr_del_pending)
|
|
|
|
+ continue;
|
|
|
|
+ asoc->asconf_addr_del_pending =
|
|
|
|
+ kzalloc(sizeof(union sctp_addr), GFP_ATOMIC);
|
|
|
|
+ asoc->asconf_addr_del_pending->sa.sa_family =
|
|
|
|
+ addrs->sa_family;
|
|
|
|
+ asoc->asconf_addr_del_pending->v4.sin_port =
|
|
|
|
+ htons(bp->port);
|
|
|
|
+ if (addrs->sa_family == AF_INET) {
|
|
|
|
+ struct sockaddr_in *sin;
|
|
|
|
+
|
|
|
|
+ sin = (struct sockaddr_in *)addrs;
|
|
|
|
+ asoc->asconf_addr_del_pending->v4.sin_addr.s_addr = sin->sin_addr.s_addr;
|
|
|
|
+ } else if (addrs->sa_family == AF_INET6) {
|
|
|
|
+ struct sockaddr_in6 *sin6;
|
|
|
|
+
|
|
|
|
+ sin6 = (struct sockaddr_in6 *)addrs;
|
|
|
|
+ ipv6_addr_copy(&asoc->asconf_addr_del_pending->v6.sin6_addr, &sin6->sin6_addr);
|
|
|
|
+ }
|
|
|
|
+ SCTP_DEBUG_PRINTK_IPADDR("send_asconf_del_ip: keep the last address asoc: %p ",
|
|
|
|
+ " at %p\n", asoc, asoc->asconf_addr_del_pending,
|
|
|
|
+ asoc->asconf_addr_del_pending);
|
|
|
|
+ asoc->src_out_of_asoc_ok = 1;
|
|
|
|
+ stored = 1;
|
|
|
|
+ goto skip_mkasconf;
|
|
|
|
+ }
|
|
|
|
|
|
/* We do not need RCU protection throughout this loop
|
|
/* We do not need RCU protection throughout this loop
|
|
* because this is done under a socket lock from the
|
|
* because this is done under a socket lock from the
|
|
@@ -780,6 +820,7 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+skip_mkasconf:
|
|
/* Reset use_as_src flag for the addresses in the bind address
|
|
/* Reset use_as_src flag for the addresses in the bind address
|
|
* list that are to be deleted.
|
|
* list that are to be deleted.
|
|
*/
|
|
*/
|
|
@@ -805,6 +846,9 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
|
|
sctp_sk(asoc->base.sk));
|
|
sctp_sk(asoc->base.sk));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (stored)
|
|
|
|
+ /* We don't need to transmit ASCONF */
|
|
|
|
+ continue;
|
|
retval = sctp_send_asconf(asoc, chunk);
|
|
retval = sctp_send_asconf(asoc, chunk);
|
|
}
|
|
}
|
|
out:
|
|
out:
|