diff options
Diffstat (limited to 'net/sctp/sm_statefuns.c')
| -rw-r--r-- | net/sctp/sm_statefuns.c | 55 |
1 files changed, 31 insertions, 24 deletions
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 47bc20d3a85b..d344dc481ccc 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
| @@ -56,6 +56,7 @@ | |||
| 56 | #include <linux/ipv6.h> | 56 | #include <linux/ipv6.h> |
| 57 | #include <linux/net.h> | 57 | #include <linux/net.h> |
| 58 | #include <linux/inet.h> | 58 | #include <linux/inet.h> |
| 59 | #include <linux/slab.h> | ||
| 59 | #include <net/sock.h> | 60 | #include <net/sock.h> |
| 60 | #include <net/inet_ecn.h> | 61 | #include <net/inet_ecn.h> |
| 61 | #include <linux/skbuff.h> | 62 | #include <linux/skbuff.h> |
| @@ -1231,6 +1232,18 @@ out: | |||
| 1231 | return 0; | 1232 | return 0; |
| 1232 | } | 1233 | } |
| 1233 | 1234 | ||
| 1235 | static bool list_has_sctp_addr(const struct list_head *list, | ||
| 1236 | union sctp_addr *ipaddr) | ||
| 1237 | { | ||
| 1238 | struct sctp_transport *addr; | ||
| 1239 | |||
| 1240 | list_for_each_entry(addr, list, transports) { | ||
| 1241 | if (sctp_cmp_addr_exact(ipaddr, &addr->ipaddr)) | ||
| 1242 | return true; | ||
| 1243 | } | ||
| 1244 | |||
| 1245 | return false; | ||
| 1246 | } | ||
| 1234 | /* A restart is occurring, check to make sure no new addresses | 1247 | /* A restart is occurring, check to make sure no new addresses |
| 1235 | * are being added as we may be under a takeover attack. | 1248 | * are being added as we may be under a takeover attack. |
| 1236 | */ | 1249 | */ |
| @@ -1239,10 +1252,10 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc, | |||
| 1239 | struct sctp_chunk *init, | 1252 | struct sctp_chunk *init, |
| 1240 | sctp_cmd_seq_t *commands) | 1253 | sctp_cmd_seq_t *commands) |
| 1241 | { | 1254 | { |
| 1242 | struct sctp_transport *new_addr, *addr; | 1255 | struct sctp_transport *new_addr; |
| 1243 | int found; | 1256 | int ret = 1; |
| 1244 | 1257 | ||
| 1245 | /* Implementor's Guide - Sectin 5.2.2 | 1258 | /* Implementor's Guide - Section 5.2.2 |
| 1246 | * ... | 1259 | * ... |
| 1247 | * Before responding the endpoint MUST check to see if the | 1260 | * Before responding the endpoint MUST check to see if the |
| 1248 | * unexpected INIT adds new addresses to the association. If new | 1261 | * unexpected INIT adds new addresses to the association. If new |
| @@ -1253,31 +1266,19 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc, | |||
| 1253 | /* Search through all current addresses and make sure | 1266 | /* Search through all current addresses and make sure |
| 1254 | * we aren't adding any new ones. | 1267 | * we aren't adding any new ones. |
| 1255 | */ | 1268 | */ |
| 1256 | new_addr = NULL; | ||
| 1257 | found = 0; | ||
| 1258 | |||
| 1259 | list_for_each_entry(new_addr, &new_asoc->peer.transport_addr_list, | 1269 | list_for_each_entry(new_addr, &new_asoc->peer.transport_addr_list, |
| 1260 | transports) { | 1270 | transports) { |
| 1261 | found = 0; | 1271 | if (!list_has_sctp_addr(&asoc->peer.transport_addr_list, |
| 1262 | list_for_each_entry(addr, &asoc->peer.transport_addr_list, | 1272 | &new_addr->ipaddr)) { |
| 1263 | transports) { | 1273 | sctp_sf_send_restart_abort(&new_addr->ipaddr, init, |
| 1264 | if (sctp_cmp_addr_exact(&new_addr->ipaddr, | 1274 | commands); |
| 1265 | &addr->ipaddr)) { | 1275 | ret = 0; |
| 1266 | found = 1; | ||
| 1267 | break; | ||
| 1268 | } | ||
| 1269 | } | ||
| 1270 | if (!found) | ||
| 1271 | break; | 1276 | break; |
| 1272 | } | 1277 | } |
| 1273 | |||
| 1274 | /* If a new address was added, ABORT the sender. */ | ||
| 1275 | if (!found && new_addr) { | ||
| 1276 | sctp_sf_send_restart_abort(&new_addr->ipaddr, init, commands); | ||
| 1277 | } | 1278 | } |
| 1278 | 1279 | ||
| 1279 | /* Return success if all addresses were found. */ | 1280 | /* Return success if all addresses were found. */ |
| 1280 | return found; | 1281 | return ret; |
| 1281 | } | 1282 | } |
| 1282 | 1283 | ||
| 1283 | /* Populate the verification/tie tags based on overlapping INIT | 1284 | /* Populate the verification/tie tags based on overlapping INIT |
| @@ -3675,8 +3676,14 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, | |||
| 3675 | SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); | 3676 | SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); |
| 3676 | 3677 | ||
| 3677 | if (!sctp_process_asconf_ack((struct sctp_association *)asoc, | 3678 | if (!sctp_process_asconf_ack((struct sctp_association *)asoc, |
| 3678 | asconf_ack)) | 3679 | asconf_ack)) { |
| 3680 | /* Successfully processed ASCONF_ACK. We can | ||
| 3681 | * release the next asconf if we have one. | ||
| 3682 | */ | ||
| 3683 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_NEXT_ASCONF, | ||
| 3684 | SCTP_NULL()); | ||
| 3679 | return SCTP_DISPOSITION_CONSUME; | 3685 | return SCTP_DISPOSITION_CONSUME; |
| 3686 | } | ||
| 3680 | 3687 | ||
| 3681 | abort = sctp_make_abort(asoc, asconf_ack, | 3688 | abort = sctp_make_abort(asoc, asconf_ack, |
| 3682 | sizeof(sctp_errhdr_t)); | 3689 | sizeof(sctp_errhdr_t)); |
