diff options
| -rw-r--r-- | include/net/sctp/command.h | 8 | ||||
| -rw-r--r-- | include/net/sctp/constants.h | 7 | ||||
| -rw-r--r-- | include/net/sctp/sctp.h | 17 | ||||
| -rw-r--r-- | include/net/sctp/sm.h | 8 | ||||
| -rw-r--r-- | include/net/sctp/structs.h | 41 | ||||
| -rw-r--r-- | include/net/sctp/user.h | 3 | ||||
| -rw-r--r-- | net/sctp/associola.c | 151 | ||||
| -rw-r--r-- | net/sctp/endpointola.c | 1 | ||||
| -rw-r--r-- | net/sctp/input.c | 2 | ||||
| -rw-r--r-- | net/sctp/outqueue.c | 11 | ||||
| -rw-r--r-- | net/sctp/sm_make_chunk.c | 20 | ||||
| -rw-r--r-- | net/sctp/sm_sideeffect.c | 105 | ||||
| -rw-r--r-- | net/sctp/sm_statefuns.c | 148 | ||||
| -rw-r--r-- | net/sctp/sm_statetable.c | 6 | ||||
| -rw-r--r-- | net/sctp/socket.c | 405 | ||||
| -rw-r--r-- | net/sctp/transport.c | 4 |
16 files changed, 677 insertions, 260 deletions
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h index ebc5282e6d58..dc107ffad483 100644 --- a/include/net/sctp/command.h +++ b/include/net/sctp/command.h | |||
| @@ -65,9 +65,11 @@ typedef enum { | |||
| 65 | SCTP_CMD_TIMER_START, /* Start a timer. */ | 65 | SCTP_CMD_TIMER_START, /* Start a timer. */ |
| 66 | SCTP_CMD_TIMER_RESTART, /* Restart a timer. */ | 66 | SCTP_CMD_TIMER_RESTART, /* Restart a timer. */ |
| 67 | SCTP_CMD_TIMER_STOP, /* Stop a timer. */ | 67 | SCTP_CMD_TIMER_STOP, /* Stop a timer. */ |
| 68 | SCTP_CMD_COUNTER_RESET, /* Reset a counter. */ | 68 | SCTP_CMD_INIT_CHOOSE_TRANSPORT, /* Choose transport for an INIT. */ |
| 69 | SCTP_CMD_COUNTER_INC, /* Increment a counter. */ | 69 | SCTP_CMD_INIT_COUNTER_RESET, /* Reset init counter. */ |
| 70 | SCTP_CMD_INIT_COUNTER_INC, /* Increment init counter. */ | ||
| 70 | SCTP_CMD_INIT_RESTART, /* High level, do init timer work. */ | 71 | SCTP_CMD_INIT_RESTART, /* High level, do init timer work. */ |
| 72 | SCTP_CMD_COOKIEECHO_RESTART, /* High level, do cookie-echo timer work. */ | ||
| 71 | SCTP_CMD_INIT_FAILED, /* High level, do init failure work. */ | 73 | SCTP_CMD_INIT_FAILED, /* High level, do init failure work. */ |
| 72 | SCTP_CMD_REPORT_DUP, /* Report a duplicate TSN. */ | 74 | SCTP_CMD_REPORT_DUP, /* Report a duplicate TSN. */ |
| 73 | SCTP_CMD_STRIKE, /* Mark a strike against a transport. */ | 75 | SCTP_CMD_STRIKE, /* Mark a strike against a transport. */ |
| @@ -118,7 +120,6 @@ typedef union { | |||
| 118 | int error; | 120 | int error; |
| 119 | sctp_state_t state; | 121 | sctp_state_t state; |
| 120 | sctp_event_timeout_t to; | 122 | sctp_event_timeout_t to; |
| 121 | sctp_counter_t counter; | ||
| 122 | void *ptr; | 123 | void *ptr; |
| 123 | struct sctp_chunk *chunk; | 124 | struct sctp_chunk *chunk; |
| 124 | struct sctp_association *asoc; | 125 | struct sctp_association *asoc; |
| @@ -165,7 +166,6 @@ SCTP_ARG_CONSTRUCTOR(U16, __u16, u16) | |||
| 165 | SCTP_ARG_CONSTRUCTOR(U8, __u8, u8) | 166 | SCTP_ARG_CONSTRUCTOR(U8, __u8, u8) |
| 166 | SCTP_ARG_CONSTRUCTOR(ERROR, int, error) | 167 | SCTP_ARG_CONSTRUCTOR(ERROR, int, error) |
| 167 | SCTP_ARG_CONSTRUCTOR(STATE, sctp_state_t, state) | 168 | SCTP_ARG_CONSTRUCTOR(STATE, sctp_state_t, state) |
| 168 | SCTP_ARG_CONSTRUCTOR(COUNTER, sctp_counter_t, counter) | ||
| 169 | SCTP_ARG_CONSTRUCTOR(TO, sctp_event_timeout_t, to) | 169 | SCTP_ARG_CONSTRUCTOR(TO, sctp_event_timeout_t, to) |
| 170 | SCTP_ARG_CONSTRUCTOR(PTR, void *, ptr) | 170 | SCTP_ARG_CONSTRUCTOR(PTR, void *, ptr) |
| 171 | SCTP_ARG_CONSTRUCTOR(CHUNK, struct sctp_chunk *, chunk) | 171 | SCTP_ARG_CONSTRUCTOR(CHUNK, struct sctp_chunk *, chunk) |
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h index 2b76c0f4babc..4868c7f7749d 100644 --- a/include/net/sctp/constants.h +++ b/include/net/sctp/constants.h | |||
| @@ -263,13 +263,6 @@ enum { SCTP_MIN_PMTU = 576 }; | |||
| 263 | enum { SCTP_MAX_DUP_TSNS = 16 }; | 263 | enum { SCTP_MAX_DUP_TSNS = 16 }; |
| 264 | enum { SCTP_MAX_GABS = 16 }; | 264 | enum { SCTP_MAX_GABS = 16 }; |
| 265 | 265 | ||
| 266 | typedef enum { | ||
| 267 | SCTP_COUNTER_INIT_ERROR, | ||
| 268 | } sctp_counter_t; | ||
| 269 | |||
| 270 | /* How many counters does an association need? */ | ||
| 271 | #define SCTP_NUMBER_COUNTERS 5 | ||
| 272 | |||
| 273 | /* Here we define the default timers. */ | 266 | /* Here we define the default timers. */ |
| 274 | 267 | ||
| 275 | /* cookie timer def = ? seconds */ | 268 | /* cookie timer def = ? seconds */ |
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 960abfa48d68..ef2738159ab3 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h | |||
| @@ -223,6 +223,22 @@ DECLARE_SNMP_STAT(struct sctp_mib, sctp_statistics); | |||
| 223 | extern int sctp_debug_flag; | 223 | extern int sctp_debug_flag; |
| 224 | #define SCTP_DEBUG_PRINTK(whatever...) \ | 224 | #define SCTP_DEBUG_PRINTK(whatever...) \ |
| 225 | ((void) (sctp_debug_flag && printk(KERN_DEBUG whatever))) | 225 | ((void) (sctp_debug_flag && printk(KERN_DEBUG whatever))) |
| 226 | #define SCTP_DEBUG_PRINTK_IPADDR(lead, trail, leadparm, saddr, otherparms...) \ | ||
| 227 | if (sctp_debug_flag) { \ | ||
| 228 | if (saddr->sa.sa_family == AF_INET6) { \ | ||
| 229 | printk(KERN_DEBUG \ | ||
| 230 | lead "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" trail, \ | ||
| 231 | leadparm, \ | ||
| 232 | NIP6(saddr->v6.sin6_addr), \ | ||
| 233 | otherparms); \ | ||
| 234 | } else { \ | ||
| 235 | printk(KERN_DEBUG \ | ||
| 236 | lead "%u.%u.%u.%u" trail, \ | ||
| 237 | leadparm, \ | ||
| 238 | NIPQUAD(saddr->v4.sin_addr.s_addr), \ | ||
| 239 | otherparms); \ | ||
| 240 | } \ | ||
| 241 | } | ||
| 226 | #define SCTP_ENABLE_DEBUG { sctp_debug_flag = 1; } | 242 | #define SCTP_ENABLE_DEBUG { sctp_debug_flag = 1; } |
| 227 | #define SCTP_DISABLE_DEBUG { sctp_debug_flag = 0; } | 243 | #define SCTP_DISABLE_DEBUG { sctp_debug_flag = 0; } |
| 228 | 244 | ||
| @@ -236,6 +252,7 @@ extern int sctp_debug_flag; | |||
| 236 | #else /* SCTP_DEBUG */ | 252 | #else /* SCTP_DEBUG */ |
| 237 | 253 | ||
| 238 | #define SCTP_DEBUG_PRINTK(whatever...) | 254 | #define SCTP_DEBUG_PRINTK(whatever...) |
| 255 | #define SCTP_DEBUG_PRINTK_IPADDR(whatever...) | ||
| 239 | #define SCTP_ENABLE_DEBUG | 256 | #define SCTP_ENABLE_DEBUG |
| 240 | #define SCTP_DISABLE_DEBUG | 257 | #define SCTP_DISABLE_DEBUG |
| 241 | #define SCTP_ASSERT(expr, str, func) | 258 | #define SCTP_ASSERT(expr, str, func) |
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index f4fcee104707..a53e08a45e32 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h | |||
| @@ -116,7 +116,8 @@ sctp_state_fn_t sctp_sf_eat_data_fast_4_4; | |||
| 116 | sctp_state_fn_t sctp_sf_eat_sack_6_2; | 116 | sctp_state_fn_t sctp_sf_eat_sack_6_2; |
| 117 | sctp_state_fn_t sctp_sf_tabort_8_4_8; | 117 | sctp_state_fn_t sctp_sf_tabort_8_4_8; |
| 118 | sctp_state_fn_t sctp_sf_operr_notify; | 118 | sctp_state_fn_t sctp_sf_operr_notify; |
| 119 | sctp_state_fn_t sctp_sf_t1_timer_expire; | 119 | sctp_state_fn_t sctp_sf_t1_init_timer_expire; |
| 120 | sctp_state_fn_t sctp_sf_t1_cookie_timer_expire; | ||
| 120 | sctp_state_fn_t sctp_sf_t2_timer_expire; | 121 | sctp_state_fn_t sctp_sf_t2_timer_expire; |
| 121 | sctp_state_fn_t sctp_sf_t4_timer_expire; | 122 | sctp_state_fn_t sctp_sf_t4_timer_expire; |
| 122 | sctp_state_fn_t sctp_sf_t5_timer_expire; | 123 | sctp_state_fn_t sctp_sf_t5_timer_expire; |
| @@ -258,7 +259,10 @@ struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc, | |||
| 258 | void sctp_chunk_assign_tsn(struct sctp_chunk *); | 259 | void sctp_chunk_assign_tsn(struct sctp_chunk *); |
| 259 | void sctp_chunk_assign_ssn(struct sctp_chunk *); | 260 | void sctp_chunk_assign_ssn(struct sctp_chunk *); |
| 260 | 261 | ||
| 261 | void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error); | 262 | sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, |
| 263 | __u16 error, | ||
| 264 | const struct sctp_association *asoc, | ||
| 265 | struct sctp_transport *transport); | ||
| 262 | 266 | ||
| 263 | /* Prototypes for statetable processing. */ | 267 | /* Prototypes for statetable processing. */ |
| 264 | 268 | ||
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 6c24d9cd3d66..dfad4d3c581c 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
| @@ -867,10 +867,13 @@ struct sctp_transport { | |||
| 867 | */ | 867 | */ |
| 868 | unsigned long last_time_ecne_reduced; | 868 | unsigned long last_time_ecne_reduced; |
| 869 | 869 | ||
| 870 | /* active : The current active state of this destination, | 870 | /* The number of times INIT has been sent on this transport. */ |
| 871 | * : i.e. DOWN, UP, etc. | 871 | int init_sent_count; |
| 872 | |||
| 873 | /* state : The current state of this destination, | ||
| 874 | * : i.e. SCTP_ACTIVE, SCTP_INACTIVE, SCTP_UNKOWN. | ||
| 872 | */ | 875 | */ |
| 873 | int active; | 876 | int state; |
| 874 | 877 | ||
| 875 | /* hb_allowed : The current heartbeat state of this destination, | 878 | /* hb_allowed : The current heartbeat state of this destination, |
| 876 | * : i.e. ALLOW-HB, NO-HEARTBEAT, etc. | 879 | * : i.e. ALLOW-HB, NO-HEARTBEAT, etc. |
| @@ -1222,9 +1225,6 @@ struct sctp_endpoint { | |||
| 1222 | 1225 | ||
| 1223 | /* sendbuf acct. policy. */ | 1226 | /* sendbuf acct. policy. */ |
| 1224 | __u32 sndbuf_policy; | 1227 | __u32 sndbuf_policy; |
| 1225 | |||
| 1226 | /* Name for debugging output... */ | ||
| 1227 | char *debug_name; | ||
| 1228 | }; | 1228 | }; |
| 1229 | 1229 | ||
| 1230 | /* Recover the outter endpoint structure. */ | 1230 | /* Recover the outter endpoint structure. */ |
| @@ -1314,11 +1314,23 @@ struct sctp_association { | |||
| 1314 | * : association. Normally this information is | 1314 | * : association. Normally this information is |
| 1315 | * : hashed or keyed for quick lookup and access | 1315 | * : hashed or keyed for quick lookup and access |
| 1316 | * : of the TCB. | 1316 | * : of the TCB. |
| 1317 | * : The list is also initialized with the list | ||
| 1318 | * : of addresses passed with the sctp_connectx() | ||
| 1319 | * : call. | ||
| 1317 | * | 1320 | * |
| 1318 | * It is a list of SCTP_transport's. | 1321 | * It is a list of SCTP_transport's. |
| 1319 | */ | 1322 | */ |
| 1320 | struct list_head transport_addr_list; | 1323 | struct list_head transport_addr_list; |
| 1321 | 1324 | ||
| 1325 | /* transport_count | ||
| 1326 | * | ||
| 1327 | * Peer : A count of the number of peer addresses | ||
| 1328 | * Transport : in the Peer Transport Address List. | ||
| 1329 | * Address : | ||
| 1330 | * Count : | ||
| 1331 | */ | ||
| 1332 | __u16 transport_count; | ||
| 1333 | |||
| 1322 | /* port | 1334 | /* port |
| 1323 | * The transport layer port number. | 1335 | * The transport layer port number. |
| 1324 | */ | 1336 | */ |
| @@ -1486,6 +1498,9 @@ struct sctp_association { | |||
| 1486 | /* Transport to which SHUTDOWN chunk was last sent. */ | 1498 | /* Transport to which SHUTDOWN chunk was last sent. */ |
| 1487 | struct sctp_transport *shutdown_last_sent_to; | 1499 | struct sctp_transport *shutdown_last_sent_to; |
| 1488 | 1500 | ||
| 1501 | /* Transport to which INIT chunk was last sent. */ | ||
| 1502 | struct sctp_transport *init_last_sent_to; | ||
| 1503 | |||
| 1489 | /* Next TSN : The next TSN number to be assigned to a new | 1504 | /* Next TSN : The next TSN number to be assigned to a new |
| 1490 | * : DATA chunk. This is sent in the INIT or INIT | 1505 | * : DATA chunk. This is sent in the INIT or INIT |
| 1491 | * : ACK chunk to the peer and incremented each | 1506 | * : ACK chunk to the peer and incremented each |
| @@ -1549,8 +1564,11 @@ struct sctp_association { | |||
| 1549 | /* The message size at which SCTP fragmentation will occur. */ | 1564 | /* The message size at which SCTP fragmentation will occur. */ |
| 1550 | __u32 frag_point; | 1565 | __u32 frag_point; |
| 1551 | 1566 | ||
| 1552 | /* Currently only one counter is used to count INIT errors. */ | 1567 | /* Counter used to count INIT errors. */ |
| 1553 | int counters[SCTP_NUMBER_COUNTERS]; | 1568 | int init_err_counter; |
| 1569 | |||
| 1570 | /* Count the number of INIT cycles (for doubling timeout). */ | ||
| 1571 | int init_cycle; | ||
| 1554 | 1572 | ||
| 1555 | /* Default send parameters. */ | 1573 | /* Default send parameters. */ |
| 1556 | __u16 default_stream; | 1574 | __u16 default_stream; |
| @@ -1708,6 +1726,8 @@ void sctp_association_free(struct sctp_association *); | |||
| 1708 | void sctp_association_put(struct sctp_association *); | 1726 | void sctp_association_put(struct sctp_association *); |
| 1709 | void sctp_association_hold(struct sctp_association *); | 1727 | void sctp_association_hold(struct sctp_association *); |
| 1710 | 1728 | ||
| 1729 | struct sctp_transport *sctp_assoc_choose_init_transport( | ||
| 1730 | struct sctp_association *); | ||
| 1711 | struct sctp_transport *sctp_assoc_choose_shutdown_transport( | 1731 | struct sctp_transport *sctp_assoc_choose_shutdown_transport( |
| 1712 | struct sctp_association *); | 1732 | struct sctp_association *); |
| 1713 | void sctp_assoc_update_retran_path(struct sctp_association *); | 1733 | void sctp_assoc_update_retran_path(struct sctp_association *); |
| @@ -1717,9 +1737,12 @@ int sctp_assoc_lookup_laddr(struct sctp_association *asoc, | |||
| 1717 | const union sctp_addr *laddr); | 1737 | const union sctp_addr *laddr); |
| 1718 | struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *, | 1738 | struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *, |
| 1719 | const union sctp_addr *address, | 1739 | const union sctp_addr *address, |
| 1720 | const int gfp); | 1740 | const int gfp, |
| 1741 | const int peer_state); | ||
| 1721 | void sctp_assoc_del_peer(struct sctp_association *asoc, | 1742 | void sctp_assoc_del_peer(struct sctp_association *asoc, |
| 1722 | const union sctp_addr *addr); | 1743 | const union sctp_addr *addr); |
| 1744 | void sctp_assoc_rm_peer(struct sctp_association *asoc, | ||
| 1745 | struct sctp_transport *peer); | ||
| 1723 | void sctp_assoc_control_transport(struct sctp_association *, | 1746 | void sctp_assoc_control_transport(struct sctp_association *, |
| 1724 | struct sctp_transport *, | 1747 | struct sctp_transport *, |
| 1725 | sctp_transport_cmd_t, sctp_sn_error_t); | 1748 | sctp_transport_cmd_t, sctp_sn_error_t); |
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h index 2758e8ce4f25..f6328aeddcce 100644 --- a/include/net/sctp/user.h +++ b/include/net/sctp/user.h | |||
| @@ -111,6 +111,8 @@ enum sctp_optname { | |||
| 111 | #define SCTP_GET_LOCAL_ADDRS_NUM SCTP_GET_LOCAL_ADDRS_NUM | 111 | #define SCTP_GET_LOCAL_ADDRS_NUM SCTP_GET_LOCAL_ADDRS_NUM |
| 112 | SCTP_GET_LOCAL_ADDRS, /* Get all local addresss. */ | 112 | SCTP_GET_LOCAL_ADDRS, /* Get all local addresss. */ |
| 113 | #define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS | 113 | #define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS |
| 114 | SCTP_SOCKOPT_CONNECTX, /* CONNECTX requests. */ | ||
| 115 | #define SCTP_SOCKOPT_CONNECTX SCTP_SOCKOPT_CONNECTX | ||
| 114 | }; | 116 | }; |
| 115 | 117 | ||
| 116 | /* | 118 | /* |
| @@ -527,6 +529,7 @@ struct sctp_paddrinfo { | |||
| 527 | enum sctp_spinfo_state { | 529 | enum sctp_spinfo_state { |
| 528 | SCTP_INACTIVE, | 530 | SCTP_INACTIVE, |
| 529 | SCTP_ACTIVE, | 531 | SCTP_ACTIVE, |
| 532 | SCTP_UNKNOWN = 0xffff /* Value used for transport state unknown */ | ||
| 530 | }; | 533 | }; |
| 531 | 534 | ||
| 532 | /* | 535 | /* |
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 663843d97a92..7ae6aa772dab 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
| @@ -191,10 +191,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
| 191 | asoc->last_cwr_tsn = asoc->ctsn_ack_point; | 191 | asoc->last_cwr_tsn = asoc->ctsn_ack_point; |
| 192 | asoc->unack_data = 0; | 192 | asoc->unack_data = 0; |
| 193 | 193 | ||
| 194 | SCTP_DEBUG_PRINTK("myctsnap for %s INIT as 0x%x.\n", | ||
| 195 | asoc->ep->debug_name, | ||
| 196 | asoc->ctsn_ack_point); | ||
| 197 | |||
| 198 | /* ADDIP Section 4.1 Asconf Chunk Procedures | 194 | /* ADDIP Section 4.1 Asconf Chunk Procedures |
| 199 | * | 195 | * |
| 200 | * When an endpoint has an ASCONF signaled change to be sent to the | 196 | * When an endpoint has an ASCONF signaled change to be sent to the |
| @@ -211,6 +207,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
| 211 | 207 | ||
| 212 | /* Make an empty list of remote transport addresses. */ | 208 | /* Make an empty list of remote transport addresses. */ |
| 213 | INIT_LIST_HEAD(&asoc->peer.transport_addr_list); | 209 | INIT_LIST_HEAD(&asoc->peer.transport_addr_list); |
| 210 | asoc->peer.transport_count = 0; | ||
| 214 | 211 | ||
| 215 | /* RFC 2960 5.1 Normal Establishment of an Association | 212 | /* RFC 2960 5.1 Normal Establishment of an Association |
| 216 | * | 213 | * |
| @@ -288,6 +285,7 @@ struct sctp_association *sctp_association_new(const struct sctp_endpoint *ep, | |||
| 288 | 285 | ||
| 289 | asoc->base.malloced = 1; | 286 | asoc->base.malloced = 1; |
| 290 | SCTP_DBG_OBJCNT_INC(assoc); | 287 | SCTP_DBG_OBJCNT_INC(assoc); |
| 288 | SCTP_DEBUG_PRINTK("Created asoc %p\n", asoc); | ||
| 291 | 289 | ||
| 292 | return asoc; | 290 | return asoc; |
| 293 | 291 | ||
| @@ -356,6 +354,8 @@ void sctp_association_free(struct sctp_association *asoc) | |||
| 356 | sctp_transport_free(transport); | 354 | sctp_transport_free(transport); |
| 357 | } | 355 | } |
| 358 | 356 | ||
| 357 | asoc->peer.transport_count = 0; | ||
| 358 | |||
| 359 | /* Free any cached ASCONF_ACK chunk. */ | 359 | /* Free any cached ASCONF_ACK chunk. */ |
| 360 | if (asoc->addip_last_asconf_ack) | 360 | if (asoc->addip_last_asconf_ack) |
| 361 | sctp_chunk_free(asoc->addip_last_asconf_ack); | 361 | sctp_chunk_free(asoc->addip_last_asconf_ack); |
| @@ -400,7 +400,7 @@ void sctp_assoc_set_primary(struct sctp_association *asoc, | |||
| 400 | /* If the primary path is changing, assume that the | 400 | /* If the primary path is changing, assume that the |
| 401 | * user wants to use this new path. | 401 | * user wants to use this new path. |
| 402 | */ | 402 | */ |
| 403 | if (transport->active) | 403 | if (transport->state != SCTP_INACTIVE) |
| 404 | asoc->peer.active_path = transport; | 404 | asoc->peer.active_path = transport; |
| 405 | 405 | ||
| 406 | /* | 406 | /* |
| @@ -428,10 +428,58 @@ void sctp_assoc_set_primary(struct sctp_association *asoc, | |||
| 428 | transport->cacc.next_tsn_at_change = asoc->next_tsn; | 428 | transport->cacc.next_tsn_at_change = asoc->next_tsn; |
| 429 | } | 429 | } |
| 430 | 430 | ||
| 431 | /* Remove a transport from an association. */ | ||
| 432 | void sctp_assoc_rm_peer(struct sctp_association *asoc, | ||
| 433 | struct sctp_transport *peer) | ||
| 434 | { | ||
| 435 | struct list_head *pos; | ||
| 436 | struct sctp_transport *transport; | ||
| 437 | |||
| 438 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_rm_peer:association %p addr: ", | ||
| 439 | " port: %d\n", | ||
| 440 | asoc, | ||
| 441 | (&peer->ipaddr), | ||
| 442 | peer->ipaddr.v4.sin_port); | ||
| 443 | |||
| 444 | /* If we are to remove the current retran_path, update it | ||
| 445 | * to the next peer before removing this peer from the list. | ||
| 446 | */ | ||
| 447 | if (asoc->peer.retran_path == peer) | ||
| 448 | sctp_assoc_update_retran_path(asoc); | ||
| 449 | |||
| 450 | /* Remove this peer from the list. */ | ||
| 451 | list_del(&peer->transports); | ||
| 452 | |||
| 453 | /* Get the first transport of asoc. */ | ||
| 454 | pos = asoc->peer.transport_addr_list.next; | ||
| 455 | transport = list_entry(pos, struct sctp_transport, transports); | ||
| 456 | |||
| 457 | /* Update any entries that match the peer to be deleted. */ | ||
| 458 | if (asoc->peer.primary_path == peer) | ||
| 459 | sctp_assoc_set_primary(asoc, transport); | ||
| 460 | if (asoc->peer.active_path == peer) | ||
| 461 | asoc->peer.active_path = transport; | ||
| 462 | if (asoc->peer.last_data_from == peer) | ||
| 463 | asoc->peer.last_data_from = transport; | ||
| 464 | |||
| 465 | /* If we remove the transport an INIT was last sent to, set it to | ||
| 466 | * NULL. Combined with the update of the retran path above, this | ||
| 467 | * will cause the next INIT to be sent to the next available | ||
| 468 | * transport, maintaining the cycle. | ||
| 469 | */ | ||
| 470 | if (asoc->init_last_sent_to == peer) | ||
| 471 | asoc->init_last_sent_to = NULL; | ||
| 472 | |||
| 473 | asoc->peer.transport_count--; | ||
| 474 | |||
| 475 | sctp_transport_free(peer); | ||
| 476 | } | ||
| 477 | |||
| 431 | /* Add a transport address to an association. */ | 478 | /* Add a transport address to an association. */ |
| 432 | struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | 479 | struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, |
| 433 | const union sctp_addr *addr, | 480 | const union sctp_addr *addr, |
| 434 | int gfp) | 481 | const int gfp, |
| 482 | const int peer_state) | ||
| 435 | { | 483 | { |
| 436 | struct sctp_transport *peer; | 484 | struct sctp_transport *peer; |
| 437 | struct sctp_sock *sp; | 485 | struct sctp_sock *sp; |
| @@ -442,14 +490,25 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
| 442 | /* AF_INET and AF_INET6 share common port field. */ | 490 | /* AF_INET and AF_INET6 share common port field. */ |
| 443 | port = addr->v4.sin_port; | 491 | port = addr->v4.sin_port; |
| 444 | 492 | ||
| 493 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_add_peer:association %p addr: ", | ||
| 494 | " port: %d state:%s\n", | ||
| 495 | asoc, | ||
| 496 | addr, | ||
| 497 | addr->v4.sin_port, | ||
| 498 | peer_state == SCTP_UNKNOWN?"UNKNOWN":"ACTIVE"); | ||
| 499 | |||
| 445 | /* Set the port if it has not been set yet. */ | 500 | /* Set the port if it has not been set yet. */ |
| 446 | if (0 == asoc->peer.port) | 501 | if (0 == asoc->peer.port) |
| 447 | asoc->peer.port = port; | 502 | asoc->peer.port = port; |
| 448 | 503 | ||
| 449 | /* Check to see if this is a duplicate. */ | 504 | /* Check to see if this is a duplicate. */ |
| 450 | peer = sctp_assoc_lookup_paddr(asoc, addr); | 505 | peer = sctp_assoc_lookup_paddr(asoc, addr); |
| 451 | if (peer) | 506 | if (peer) { |
| 507 | if (peer_state == SCTP_ACTIVE && | ||
| 508 | peer->state == SCTP_UNKNOWN) | ||
| 509 | peer->state = SCTP_ACTIVE; | ||
| 452 | return peer; | 510 | return peer; |
| 511 | } | ||
| 453 | 512 | ||
| 454 | peer = sctp_transport_new(addr, gfp); | 513 | peer = sctp_transport_new(addr, gfp); |
| 455 | if (!peer) | 514 | if (!peer) |
| @@ -516,8 +575,12 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
| 516 | /* Set the transport's RTO.initial value */ | 575 | /* Set the transport's RTO.initial value */ |
| 517 | peer->rto = asoc->rto_initial; | 576 | peer->rto = asoc->rto_initial; |
| 518 | 577 | ||
| 578 | /* Set the peer's active state. */ | ||
| 579 | peer->state = peer_state; | ||
| 580 | |||
| 519 | /* Attach the remote transport to our asoc. */ | 581 | /* Attach the remote transport to our asoc. */ |
| 520 | list_add_tail(&peer->transports, &asoc->peer.transport_addr_list); | 582 | list_add_tail(&peer->transports, &asoc->peer.transport_addr_list); |
| 583 | asoc->peer.transport_count++; | ||
| 521 | 584 | ||
| 522 | /* If we do not yet have a primary path, set one. */ | 585 | /* If we do not yet have a primary path, set one. */ |
| 523 | if (!asoc->peer.primary_path) { | 586 | if (!asoc->peer.primary_path) { |
| @@ -525,8 +588,9 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
| 525 | asoc->peer.retran_path = peer; | 588 | asoc->peer.retran_path = peer; |
| 526 | } | 589 | } |
| 527 | 590 | ||
| 528 | if (asoc->peer.active_path == asoc->peer.retran_path) | 591 | if (asoc->peer.active_path == asoc->peer.retran_path) { |
| 529 | asoc->peer.retran_path = peer; | 592 | asoc->peer.retran_path = peer; |
| 593 | } | ||
| 530 | 594 | ||
| 531 | return peer; | 595 | return peer; |
| 532 | } | 596 | } |
| @@ -537,37 +601,16 @@ void sctp_assoc_del_peer(struct sctp_association *asoc, | |||
| 537 | { | 601 | { |
| 538 | struct list_head *pos; | 602 | struct list_head *pos; |
| 539 | struct list_head *temp; | 603 | struct list_head *temp; |
| 540 | struct sctp_transport *peer = NULL; | ||
| 541 | struct sctp_transport *transport; | 604 | struct sctp_transport *transport; |
| 542 | 605 | ||
| 543 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { | 606 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { |
| 544 | transport = list_entry(pos, struct sctp_transport, transports); | 607 | transport = list_entry(pos, struct sctp_transport, transports); |
| 545 | if (sctp_cmp_addr_exact(addr, &transport->ipaddr)) { | 608 | if (sctp_cmp_addr_exact(addr, &transport->ipaddr)) { |
| 546 | peer = transport; | 609 | /* Do book keeping for removing the peer and free it. */ |
| 547 | list_del(pos); | 610 | sctp_assoc_rm_peer(asoc, transport); |
| 548 | break; | 611 | break; |
| 549 | } | 612 | } |
| 550 | } | 613 | } |
| 551 | |||
| 552 | /* The address we want delete is not in the association. */ | ||
| 553 | if (!peer) | ||
| 554 | return; | ||
| 555 | |||
| 556 | /* Get the first transport of asoc. */ | ||
| 557 | pos = asoc->peer.transport_addr_list.next; | ||
| 558 | transport = list_entry(pos, struct sctp_transport, transports); | ||
| 559 | |||
| 560 | /* Update any entries that match the peer to be deleted. */ | ||
| 561 | if (asoc->peer.primary_path == peer) | ||
| 562 | sctp_assoc_set_primary(asoc, transport); | ||
| 563 | if (asoc->peer.active_path == peer) | ||
| 564 | asoc->peer.active_path = transport; | ||
| 565 | if (asoc->peer.retran_path == peer) | ||
| 566 | asoc->peer.retran_path = transport; | ||
| 567 | if (asoc->peer.last_data_from == peer) | ||
| 568 | asoc->peer.last_data_from = transport; | ||
| 569 | |||
| 570 | sctp_transport_free(peer); | ||
| 571 | } | 614 | } |
| 572 | 615 | ||
| 573 | /* Lookup a transport by address. */ | 616 | /* Lookup a transport by address. */ |
| @@ -608,12 +651,12 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
| 608 | /* Record the transition on the transport. */ | 651 | /* Record the transition on the transport. */ |
| 609 | switch (command) { | 652 | switch (command) { |
| 610 | case SCTP_TRANSPORT_UP: | 653 | case SCTP_TRANSPORT_UP: |
| 611 | transport->active = SCTP_ACTIVE; | 654 | transport->state = SCTP_ACTIVE; |
| 612 | spc_state = SCTP_ADDR_AVAILABLE; | 655 | spc_state = SCTP_ADDR_AVAILABLE; |
| 613 | break; | 656 | break; |
| 614 | 657 | ||
| 615 | case SCTP_TRANSPORT_DOWN: | 658 | case SCTP_TRANSPORT_DOWN: |
| 616 | transport->active = SCTP_INACTIVE; | 659 | transport->state = SCTP_INACTIVE; |
| 617 | spc_state = SCTP_ADDR_UNREACHABLE; | 660 | spc_state = SCTP_ADDR_UNREACHABLE; |
| 618 | break; | 661 | break; |
| 619 | 662 | ||
| @@ -643,7 +686,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
| 643 | list_for_each(pos, &asoc->peer.transport_addr_list) { | 686 | list_for_each(pos, &asoc->peer.transport_addr_list) { |
| 644 | t = list_entry(pos, struct sctp_transport, transports); | 687 | t = list_entry(pos, struct sctp_transport, transports); |
| 645 | 688 | ||
| 646 | if (!t->active) | 689 | if (t->state == SCTP_INACTIVE) |
| 647 | continue; | 690 | continue; |
| 648 | if (!first || t->last_time_heard > first->last_time_heard) { | 691 | if (!first || t->last_time_heard > first->last_time_heard) { |
| 649 | second = first; | 692 | second = first; |
| @@ -663,7 +706,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
| 663 | * [If the primary is active but not most recent, bump the most | 706 | * [If the primary is active but not most recent, bump the most |
| 664 | * recently used transport.] | 707 | * recently used transport.] |
| 665 | */ | 708 | */ |
| 666 | if (asoc->peer.primary_path->active && | 709 | if (asoc->peer.primary_path->state != SCTP_INACTIVE && |
| 667 | first != asoc->peer.primary_path) { | 710 | first != asoc->peer.primary_path) { |
| 668 | second = first; | 711 | second = first; |
| 669 | first = asoc->peer.primary_path; | 712 | first = asoc->peer.primary_path; |
| @@ -958,7 +1001,7 @@ void sctp_assoc_update(struct sctp_association *asoc, | |||
| 958 | transports); | 1001 | transports); |
| 959 | if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr)) | 1002 | if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr)) |
| 960 | sctp_assoc_add_peer(asoc, &trans->ipaddr, | 1003 | sctp_assoc_add_peer(asoc, &trans->ipaddr, |
| 961 | GFP_ATOMIC); | 1004 | GFP_ATOMIC, SCTP_ACTIVE); |
| 962 | } | 1005 | } |
| 963 | 1006 | ||
| 964 | asoc->ctsn_ack_point = asoc->next_tsn - 1; | 1007 | asoc->ctsn_ack_point = asoc->next_tsn - 1; |
| @@ -998,7 +1041,7 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) | |||
| 998 | 1041 | ||
| 999 | /* Try to find an active transport. */ | 1042 | /* Try to find an active transport. */ |
| 1000 | 1043 | ||
| 1001 | if (t->active) { | 1044 | if (t->state != SCTP_INACTIVE) { |
| 1002 | break; | 1045 | break; |
| 1003 | } else { | 1046 | } else { |
| 1004 | /* Keep track of the next transport in case | 1047 | /* Keep track of the next transport in case |
| @@ -1019,6 +1062,40 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) | |||
| 1019 | } | 1062 | } |
| 1020 | 1063 | ||
| 1021 | asoc->peer.retran_path = t; | 1064 | asoc->peer.retran_path = t; |
| 1065 | |||
| 1066 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association" | ||
| 1067 | " %p addr: ", | ||
| 1068 | " port: %d\n", | ||
| 1069 | asoc, | ||
| 1070 | (&t->ipaddr), | ||
| 1071 | t->ipaddr.v4.sin_port); | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | /* Choose the transport for sending a INIT packet. */ | ||
| 1075 | struct sctp_transport *sctp_assoc_choose_init_transport( | ||
| 1076 | struct sctp_association *asoc) | ||
| 1077 | { | ||
| 1078 | struct sctp_transport *t; | ||
| 1079 | |||
| 1080 | /* Use the retran path. If the last INIT was sent over the | ||
| 1081 | * retran path, update the retran path and use it. | ||
| 1082 | */ | ||
| 1083 | if (!asoc->init_last_sent_to) { | ||
| 1084 | t = asoc->peer.active_path; | ||
| 1085 | } else { | ||
| 1086 | if (asoc->init_last_sent_to == asoc->peer.retran_path) | ||
| 1087 | sctp_assoc_update_retran_path(asoc); | ||
| 1088 | t = asoc->peer.retran_path; | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association" | ||
| 1092 | " %p addr: ", | ||
| 1093 | " port: %d\n", | ||
| 1094 | asoc, | ||
| 1095 | (&t->ipaddr), | ||
| 1096 | t->ipaddr.v4.sin_port); | ||
| 1097 | |||
| 1098 | return t; | ||
| 1022 | } | 1099 | } |
| 1023 | 1100 | ||
| 1024 | /* Choose the transport for sending a SHUTDOWN packet. */ | 1101 | /* Choose the transport for sending a SHUTDOWN packet. */ |
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 334f61773e6d..2ec0320fac3b 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c | |||
| @@ -134,7 +134,6 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, | |||
| 134 | ep->last_key = ep->current_key = 0; | 134 | ep->last_key = ep->current_key = 0; |
| 135 | ep->key_changed_at = jiffies; | 135 | ep->key_changed_at = jiffies; |
| 136 | 136 | ||
| 137 | ep->debug_name = "unnamedEndpoint"; | ||
| 138 | return ep; | 137 | return ep; |
| 139 | } | 138 | } |
| 140 | 139 | ||
diff --git a/net/sctp/input.c b/net/sctp/input.c index fffc880a646d..339f7acfdb64 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
| @@ -353,7 +353,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk, | |||
| 353 | 353 | ||
| 354 | sctp_do_sm(SCTP_EVENT_T_OTHER, | 354 | sctp_do_sm(SCTP_EVENT_T_OTHER, |
| 355 | SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), | 355 | SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), |
| 356 | asoc->state, asoc->ep, asoc, NULL, | 356 | asoc->state, asoc->ep, asoc, t, |
| 357 | GFP_ATOMIC); | 357 | GFP_ATOMIC); |
| 358 | 358 | ||
| 359 | } | 359 | } |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 1b2d4adc4ddb..4eb81a1407b7 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
| @@ -682,9 +682,9 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
| 682 | 682 | ||
| 683 | if (!new_transport) { | 683 | if (!new_transport) { |
| 684 | new_transport = asoc->peer.active_path; | 684 | new_transport = asoc->peer.active_path; |
| 685 | } else if (!new_transport->active) { | 685 | } else if (new_transport->state == SCTP_INACTIVE) { |
| 686 | /* If the chunk is Heartbeat or Heartbeat Ack, | 686 | /* If the chunk is Heartbeat or Heartbeat Ack, |
| 687 | * send it to chunk->transport, even if it's | 687 | * send it to chunk->transport, even if it's |
| 688 | * inactive. | 688 | * inactive. |
| 689 | * | 689 | * |
| 690 | * 3.3.6 Heartbeat Acknowledgement: | 690 | * 3.3.6 Heartbeat Acknowledgement: |
| @@ -840,7 +840,8 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
| 840 | * Otherwise, we want to use the active path. | 840 | * Otherwise, we want to use the active path. |
| 841 | */ | 841 | */ |
| 842 | new_transport = chunk->transport; | 842 | new_transport = chunk->transport; |
| 843 | if (!new_transport || !new_transport->active) | 843 | if (!new_transport || |
| 844 | new_transport->state == SCTP_INACTIVE) | ||
| 844 | new_transport = asoc->peer.active_path; | 845 | new_transport = asoc->peer.active_path; |
| 845 | 846 | ||
| 846 | /* Change packets if necessary. */ | 847 | /* Change packets if necessary. */ |
| @@ -1454,7 +1455,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
| 1454 | /* Mark the destination transport address as | 1455 | /* Mark the destination transport address as |
| 1455 | * active if it is not so marked. | 1456 | * active if it is not so marked. |
| 1456 | */ | 1457 | */ |
| 1457 | if (!transport->active) { | 1458 | if (transport->state == SCTP_INACTIVE) { |
| 1458 | sctp_assoc_control_transport( | 1459 | sctp_assoc_control_transport( |
| 1459 | transport->asoc, | 1460 | transport->asoc, |
| 1460 | transport, | 1461 | transport, |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 33ac8bf47b0e..5baed9bb7de5 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
| @@ -1830,7 +1830,7 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
| 1830 | * be a a better choice than any of the embedded addresses. | 1830 | * be a a better choice than any of the embedded addresses. |
| 1831 | */ | 1831 | */ |
| 1832 | if (peer_addr) | 1832 | if (peer_addr) |
| 1833 | if(!sctp_assoc_add_peer(asoc, peer_addr, gfp)) | 1833 | if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE)) |
| 1834 | goto nomem; | 1834 | goto nomem; |
| 1835 | 1835 | ||
| 1836 | /* Process the initialization parameters. */ | 1836 | /* Process the initialization parameters. */ |
| @@ -1841,6 +1841,14 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
| 1841 | goto clean_up; | 1841 | goto clean_up; |
| 1842 | } | 1842 | } |
| 1843 | 1843 | ||
| 1844 | /* Walk list of transports, removing transports in the UNKNOWN state. */ | ||
| 1845 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { | ||
| 1846 | transport = list_entry(pos, struct sctp_transport, transports); | ||
| 1847 | if (transport->state == SCTP_UNKNOWN) { | ||
| 1848 | sctp_assoc_rm_peer(asoc, transport); | ||
| 1849 | } | ||
| 1850 | } | ||
| 1851 | |||
| 1844 | /* The fixed INIT headers are always in network byte | 1852 | /* The fixed INIT headers are always in network byte |
| 1845 | * order. | 1853 | * order. |
| 1846 | */ | 1854 | */ |
| @@ -1906,7 +1914,8 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
| 1906 | * stream sequence number shall be set to 0. | 1914 | * stream sequence number shall be set to 0. |
| 1907 | */ | 1915 | */ |
| 1908 | 1916 | ||
| 1909 | /* Allocate storage for the negotiated streams if it is not a temporary * association. | 1917 | /* Allocate storage for the negotiated streams if it is not a temporary |
| 1918 | * association. | ||
| 1910 | */ | 1919 | */ |
| 1911 | if (!asoc->temp) { | 1920 | if (!asoc->temp) { |
| 1912 | int assoc_id; | 1921 | int assoc_id; |
| @@ -1952,6 +1961,9 @@ clean_up: | |||
| 1952 | list_del_init(pos); | 1961 | list_del_init(pos); |
| 1953 | sctp_transport_free(transport); | 1962 | sctp_transport_free(transport); |
| 1954 | } | 1963 | } |
| 1964 | |||
| 1965 | asoc->peer.transport_count = 0; | ||
| 1966 | |||
| 1955 | nomem: | 1967 | nomem: |
| 1956 | return 0; | 1968 | return 0; |
| 1957 | } | 1969 | } |
| @@ -1995,7 +2007,7 @@ static int sctp_process_param(struct sctp_association *asoc, | |||
| 1995 | af->from_addr_param(&addr, param.addr, asoc->peer.port, 0); | 2007 | af->from_addr_param(&addr, param.addr, asoc->peer.port, 0); |
| 1996 | scope = sctp_scope(peer_addr); | 2008 | scope = sctp_scope(peer_addr); |
| 1997 | if (sctp_in_scope(&addr, scope)) | 2009 | if (sctp_in_scope(&addr, scope)) |
| 1998 | if (!sctp_assoc_add_peer(asoc, &addr, gfp)) | 2010 | if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_ACTIVE)) |
| 1999 | return 0; | 2011 | return 0; |
| 2000 | break; | 2012 | break; |
| 2001 | 2013 | ||
| @@ -2396,7 +2408,7 @@ static __u16 sctp_process_asconf_param(struct sctp_association *asoc, | |||
| 2396 | * Due to Resource Shortage'. | 2408 | * Due to Resource Shortage'. |
| 2397 | */ | 2409 | */ |
| 2398 | 2410 | ||
| 2399 | peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC); | 2411 | peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_ACTIVE); |
| 2400 | if (!peer) | 2412 | if (!peer) |
| 2401 | return SCTP_ERROR_RSRC_LOW; | 2413 | return SCTP_ERROR_RSRC_LOW; |
| 2402 | 2414 | ||
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index f65fa441952f..778639db125a 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
| @@ -414,11 +414,13 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, | |||
| 414 | */ | 414 | */ |
| 415 | asoc->overall_error_count++; | 415 | asoc->overall_error_count++; |
| 416 | 416 | ||
| 417 | if (transport->active && | 417 | if (transport->state != SCTP_INACTIVE && |
| 418 | (transport->error_count++ >= transport->max_retrans)) { | 418 | (transport->error_count++ >= transport->max_retrans)) { |
| 419 | SCTP_DEBUG_PRINTK("transport_strike: transport " | 419 | SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p", |
| 420 | "IP:%d.%d.%d.%d failed.\n", | 420 | " transport IP: port:%d failed.\n", |
| 421 | NIPQUAD(transport->ipaddr.v4.sin_addr)); | 421 | asoc, |
| 422 | (&transport->ipaddr), | ||
| 423 | transport->ipaddr.v4.sin_port); | ||
| 422 | sctp_assoc_control_transport(asoc, transport, | 424 | sctp_assoc_control_transport(asoc, transport, |
| 423 | SCTP_TRANSPORT_DOWN, | 425 | SCTP_TRANSPORT_DOWN, |
| 424 | SCTP_FAILED_THRESHOLD); | 426 | SCTP_FAILED_THRESHOLD); |
| @@ -593,7 +595,7 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds, | |||
| 593 | /* Mark the destination transport address as active if it is not so | 595 | /* Mark the destination transport address as active if it is not so |
| 594 | * marked. | 596 | * marked. |
| 595 | */ | 597 | */ |
| 596 | if (!t->active) | 598 | if (t->state == SCTP_INACTIVE) |
| 597 | sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP, | 599 | sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP, |
| 598 | SCTP_HEARTBEAT_SUCCESS); | 600 | SCTP_HEARTBEAT_SUCCESS); |
| 599 | 601 | ||
| @@ -665,8 +667,11 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, | |||
| 665 | 667 | ||
| 666 | asoc->state = state; | 668 | asoc->state = state; |
| 667 | 669 | ||
| 670 | SCTP_DEBUG_PRINTK("sctp_cmd_new_state: asoc %p[%s]\n", | ||
| 671 | asoc, sctp_state_tbl[state]); | ||
| 672 | |||
| 668 | if (sctp_style(sk, TCP)) { | 673 | if (sctp_style(sk, TCP)) { |
| 669 | /* Change the sk->sk_state of a TCP-style socket that has | 674 | /* Change the sk->sk_state of a TCP-style socket that has |
| 670 | * sucessfully completed a connect() call. | 675 | * sucessfully completed a connect() call. |
| 671 | */ | 676 | */ |
| 672 | if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED)) | 677 | if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED)) |
| @@ -678,6 +683,16 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, | |||
| 678 | sk->sk_shutdown |= RCV_SHUTDOWN; | 683 | sk->sk_shutdown |= RCV_SHUTDOWN; |
| 679 | } | 684 | } |
| 680 | 685 | ||
| 686 | if (sctp_state(asoc, COOKIE_WAIT)) { | ||
| 687 | /* Reset init timeouts since they may have been | ||
| 688 | * increased due to timer expirations. | ||
| 689 | */ | ||
| 690 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] = | ||
| 691 | asoc->ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]; | ||
| 692 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] = | ||
| 693 | asoc->ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]; | ||
| 694 | } | ||
| 695 | |||
| 681 | if (sctp_state(asoc, ESTABLISHED) || | 696 | if (sctp_state(asoc, ESTABLISHED) || |
| 682 | sctp_state(asoc, CLOSED) || | 697 | sctp_state(asoc, CLOSED) || |
| 683 | sctp_state(asoc, SHUTDOWN_RECEIVED)) { | 698 | sctp_state(asoc, SHUTDOWN_RECEIVED)) { |
| @@ -1120,10 +1135,10 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
| 1120 | * to be executed only during failed attempts of | 1135 | * to be executed only during failed attempts of |
| 1121 | * association establishment. | 1136 | * association establishment. |
| 1122 | */ | 1137 | */ |
| 1123 | if ((asoc->peer.retran_path != | 1138 | if ((asoc->peer.retran_path != |
| 1124 | asoc->peer.primary_path) && | 1139 | asoc->peer.primary_path) && |
| 1125 | (asoc->counters[SCTP_COUNTER_INIT_ERROR] > 0)) { | 1140 | (asoc->init_err_counter > 0)) { |
| 1126 | sctp_add_cmd_sf(commands, | 1141 | sctp_add_cmd_sf(commands, |
| 1127 | SCTP_CMD_FORCE_PRIM_RETRAN, | 1142 | SCTP_CMD_FORCE_PRIM_RETRAN, |
| 1128 | SCTP_NULL()); | 1143 | SCTP_NULL()); |
| 1129 | } | 1144 | } |
| @@ -1237,18 +1252,67 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
| 1237 | sctp_association_put(asoc); | 1252 | sctp_association_put(asoc); |
| 1238 | break; | 1253 | break; |
| 1239 | 1254 | ||
| 1255 | case SCTP_CMD_INIT_CHOOSE_TRANSPORT: | ||
| 1256 | chunk = cmd->obj.ptr; | ||
| 1257 | t = sctp_assoc_choose_init_transport(asoc); | ||
| 1258 | asoc->init_last_sent_to = t; | ||
| 1259 | chunk->transport = t; | ||
| 1260 | t->init_sent_count++; | ||
| 1261 | break; | ||
| 1262 | |||
| 1240 | case SCTP_CMD_INIT_RESTART: | 1263 | case SCTP_CMD_INIT_RESTART: |
| 1241 | /* Do the needed accounting and updates | 1264 | /* Do the needed accounting and updates |
| 1242 | * associated with restarting an initialization | 1265 | * associated with restarting an initialization |
| 1243 | * timer. | 1266 | * timer. Only multiply the timeout by two if |
| 1267 | * all transports have been tried at the current | ||
| 1268 | * timeout. | ||
| 1269 | */ | ||
| 1270 | t = asoc->init_last_sent_to; | ||
| 1271 | asoc->init_err_counter++; | ||
| 1272 | |||
| 1273 | if (t->init_sent_count > (asoc->init_cycle + 1)) { | ||
| 1274 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] *= 2; | ||
| 1275 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] > | ||
| 1276 | asoc->max_init_timeo) { | ||
| 1277 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] = | ||
| 1278 | asoc->max_init_timeo; | ||
| 1279 | } | ||
| 1280 | asoc->init_cycle++; | ||
| 1281 | SCTP_DEBUG_PRINTK( | ||
| 1282 | "T1 INIT Timeout adjustment" | ||
| 1283 | " init_err_counter: %d" | ||
| 1284 | " cycle: %d" | ||
| 1285 | " timeout: %d\n", | ||
| 1286 | asoc->init_err_counter, | ||
| 1287 | asoc->init_cycle, | ||
| 1288 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]); | ||
| 1289 | } | ||
| 1290 | |||
| 1291 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | ||
| 1292 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); | ||
| 1293 | break; | ||
| 1294 | |||
| 1295 | case SCTP_CMD_COOKIEECHO_RESTART: | ||
| 1296 | /* Do the needed accounting and updates | ||
| 1297 | * associated with restarting an initialization | ||
| 1298 | * timer. Only multiply the timeout by two if | ||
| 1299 | * all transports have been tried at the current | ||
| 1300 | * timeout. | ||
| 1244 | */ | 1301 | */ |
| 1245 | asoc->counters[SCTP_COUNTER_INIT_ERROR]++; | 1302 | asoc->init_err_counter++; |
| 1246 | asoc->timeouts[cmd->obj.to] *= 2; | 1303 | |
| 1247 | if (asoc->timeouts[cmd->obj.to] > | 1304 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] *= 2; |
| 1305 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] > | ||
| 1248 | asoc->max_init_timeo) { | 1306 | asoc->max_init_timeo) { |
| 1249 | asoc->timeouts[cmd->obj.to] = | 1307 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] = |
| 1250 | asoc->max_init_timeo; | 1308 | asoc->max_init_timeo; |
| 1251 | } | 1309 | } |
| 1310 | SCTP_DEBUG_PRINTK( | ||
| 1311 | "T1 COOKIE Timeout adjustment" | ||
| 1312 | " init_err_counter: %d" | ||
| 1313 | " timeout: %d\n", | ||
| 1314 | asoc->init_err_counter, | ||
| 1315 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]); | ||
| 1252 | 1316 | ||
| 1253 | /* If we've sent any data bundled with | 1317 | /* If we've sent any data bundled with |
| 1254 | * COOKIE-ECHO we need to resend. | 1318 | * COOKIE-ECHO we need to resend. |
| @@ -1261,7 +1325,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
| 1261 | 1325 | ||
| 1262 | sctp_add_cmd_sf(commands, | 1326 | sctp_add_cmd_sf(commands, |
| 1263 | SCTP_CMD_TIMER_RESTART, | 1327 | SCTP_CMD_TIMER_RESTART, |
| 1264 | SCTP_TO(cmd->obj.to)); | 1328 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); |
| 1265 | break; | 1329 | break; |
| 1266 | 1330 | ||
| 1267 | case SCTP_CMD_INIT_FAILED: | 1331 | case SCTP_CMD_INIT_FAILED: |
| @@ -1273,12 +1337,13 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
| 1273 | subtype, chunk, cmd->obj.u32); | 1337 | subtype, chunk, cmd->obj.u32); |
| 1274 | break; | 1338 | break; |
| 1275 | 1339 | ||
| 1276 | case SCTP_CMD_COUNTER_INC: | 1340 | case SCTP_CMD_INIT_COUNTER_INC: |
| 1277 | asoc->counters[cmd->obj.counter]++; | 1341 | asoc->init_err_counter++; |
| 1278 | break; | 1342 | break; |
| 1279 | 1343 | ||
| 1280 | case SCTP_CMD_COUNTER_RESET: | 1344 | case SCTP_CMD_INIT_COUNTER_RESET: |
| 1281 | asoc->counters[cmd->obj.counter] = 0; | 1345 | asoc->init_err_counter = 0; |
| 1346 | asoc->init_cycle = 0; | ||
| 1282 | break; | 1347 | break; |
| 1283 | 1348 | ||
| 1284 | case SCTP_CMD_REPORT_DUP: | 1349 | case SCTP_CMD_REPORT_DUP: |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 8e01b8f09ac2..058189684c7c 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
| @@ -533,6 +533,9 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, | |||
| 533 | sctp_add_cmd_sf(commands, SCTP_CMD_PEER_INIT, | 533 | sctp_add_cmd_sf(commands, SCTP_CMD_PEER_INIT, |
| 534 | SCTP_PEER_INIT(initchunk)); | 534 | SCTP_PEER_INIT(initchunk)); |
| 535 | 535 | ||
| 536 | /* Reset init error count upon receipt of INIT-ACK. */ | ||
| 537 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL()); | ||
| 538 | |||
| 536 | /* 5.1 C) "A" shall stop the T1-init timer and leave | 539 | /* 5.1 C) "A" shall stop the T1-init timer and leave |
| 537 | * COOKIE-WAIT state. "A" shall then ... start the T1-cookie | 540 | * COOKIE-WAIT state. "A" shall then ... start the T1-cookie |
| 538 | * timer, and enter the COOKIE-ECHOED state. | 541 | * timer, and enter the COOKIE-ECHOED state. |
| @@ -775,8 +778,7 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep, | |||
| 775 | * from the COOKIE-ECHOED state to the COOKIE-WAIT | 778 | * from the COOKIE-ECHOED state to the COOKIE-WAIT |
| 776 | * state is performed. | 779 | * state is performed. |
| 777 | */ | 780 | */ |
| 778 | sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_RESET, | 781 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL()); |
| 779 | SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR)); | ||
| 780 | 782 | ||
| 781 | /* RFC 2960 5.1 Normal Establishment of an Association | 783 | /* RFC 2960 5.1 Normal Establishment of an Association |
| 782 | * | 784 | * |
| @@ -1019,10 +1021,22 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, | |||
| 1019 | link = sctp_assoc_lookup_paddr(asoc, &from_addr); | 1021 | link = sctp_assoc_lookup_paddr(asoc, &from_addr); |
| 1020 | 1022 | ||
| 1021 | /* This should never happen, but lets log it if so. */ | 1023 | /* This should never happen, but lets log it if so. */ |
| 1022 | if (!link) { | 1024 | if (unlikely(!link)) { |
| 1023 | printk(KERN_WARNING | 1025 | if (from_addr.sa.sa_family == AF_INET6) { |
| 1024 | "%s: Could not find address %d.%d.%d.%d\n", | 1026 | printk(KERN_WARNING |
| 1025 | __FUNCTION__, NIPQUAD(from_addr.v4.sin_addr)); | 1027 | "%s association %p could not find address " |
| 1028 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
| 1029 | __FUNCTION__, | ||
| 1030 | asoc, | ||
| 1031 | NIP6(from_addr.v6.sin6_addr)); | ||
| 1032 | } else { | ||
| 1033 | printk(KERN_WARNING | ||
| 1034 | "%s association %p could not find address " | ||
| 1035 | "%u.%u.%u.%u\n", | ||
| 1036 | __FUNCTION__, | ||
| 1037 | asoc, | ||
| 1038 | NIPQUAD(from_addr.v4.sin_addr.s_addr)); | ||
| 1039 | } | ||
| 1026 | return SCTP_DISPOSITION_DISCARD; | 1040 | return SCTP_DISPOSITION_DISCARD; |
| 1027 | } | 1041 | } |
| 1028 | 1042 | ||
| @@ -2095,9 +2109,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep, | |||
| 2095 | sctp_errhdr_t *err; | 2109 | sctp_errhdr_t *err; |
| 2096 | struct sctp_chunk *reply; | 2110 | struct sctp_chunk *reply; |
| 2097 | struct sctp_bind_addr *bp; | 2111 | struct sctp_bind_addr *bp; |
| 2098 | int attempts; | 2112 | int attempts = asoc->init_err_counter + 1; |
| 2099 | |||
| 2100 | attempts = asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1; | ||
| 2101 | 2113 | ||
| 2102 | if (attempts >= asoc->max_init_attempts) { | 2114 | if (attempts >= asoc->max_init_attempts) { |
| 2103 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 2115 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
| @@ -2157,8 +2169,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep, | |||
| 2157 | /* Cast away the const modifier, as we want to just | 2169 | /* Cast away the const modifier, as we want to just |
| 2158 | * rerun it through as a sideffect. | 2170 | * rerun it through as a sideffect. |
| 2159 | */ | 2171 | */ |
| 2160 | sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_INC, | 2172 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_INC, SCTP_NULL()); |
| 2161 | SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR)); | ||
| 2162 | 2173 | ||
| 2163 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 2174 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
| 2164 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); | 2175 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); |
| @@ -2281,8 +2292,7 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep, | |||
| 2281 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) | 2292 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) |
| 2282 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; | 2293 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; |
| 2283 | 2294 | ||
| 2284 | sctp_stop_t1_and_abort(commands, error); | 2295 | return sctp_stop_t1_and_abort(commands, error, asoc, chunk->transport); |
| 2285 | return SCTP_DISPOSITION_ABORT; | ||
| 2286 | } | 2296 | } |
| 2287 | 2297 | ||
| 2288 | /* | 2298 | /* |
| @@ -2294,8 +2304,8 @@ sctp_disposition_t sctp_sf_cookie_wait_icmp_abort(const struct sctp_endpoint *ep | |||
| 2294 | void *arg, | 2304 | void *arg, |
| 2295 | sctp_cmd_seq_t *commands) | 2305 | sctp_cmd_seq_t *commands) |
| 2296 | { | 2306 | { |
| 2297 | sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR); | 2307 | return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR, asoc, |
| 2298 | return SCTP_DISPOSITION_ABORT; | 2308 | (struct sctp_transport *)arg); |
| 2299 | } | 2309 | } |
| 2300 | 2310 | ||
| 2301 | /* | 2311 | /* |
| @@ -2318,8 +2328,12 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep, | |||
| 2318 | * | 2328 | * |
| 2319 | * This is common code called by several sctp_sf_*_abort() functions above. | 2329 | * This is common code called by several sctp_sf_*_abort() functions above. |
| 2320 | */ | 2330 | */ |
| 2321 | void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error) | 2331 | sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, |
| 2332 | __u16 error, | ||
| 2333 | const struct sctp_association *asoc, | ||
| 2334 | struct sctp_transport *transport) | ||
| 2322 | { | 2335 | { |
| 2336 | SCTP_DEBUG_PRINTK("ABORT received (INIT).\n"); | ||
| 2323 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 2337 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
| 2324 | SCTP_STATE(SCTP_STATE_CLOSED)); | 2338 | SCTP_STATE(SCTP_STATE_CLOSED)); |
| 2325 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 2339 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); |
| @@ -2328,6 +2342,7 @@ void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error) | |||
| 2328 | /* CMD_INIT_FAILED will DELETE_TCB. */ | 2342 | /* CMD_INIT_FAILED will DELETE_TCB. */ |
| 2329 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 2343 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
| 2330 | SCTP_U32(error)); | 2344 | SCTP_U32(error)); |
| 2345 | return SCTP_DISPOSITION_ABORT; | ||
| 2331 | } | 2346 | } |
| 2332 | 2347 | ||
| 2333 | /* | 2348 | /* |
| @@ -3805,6 +3820,10 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const struct sctp_endpoint *ep, | |||
| 3805 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, | 3820 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, |
| 3806 | SCTP_ASOC((struct sctp_association *) asoc)); | 3821 | SCTP_ASOC((struct sctp_association *) asoc)); |
| 3807 | 3822 | ||
| 3823 | /* Choose transport for INIT. */ | ||
| 3824 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT, | ||
| 3825 | SCTP_CHUNK(repl)); | ||
| 3826 | |||
| 3808 | /* After sending the INIT, "A" starts the T1-init timer and | 3827 | /* After sending the INIT, "A" starts the T1-init timer and |
| 3809 | * enters the COOKIE-WAIT state. | 3828 | * enters the COOKIE-WAIT state. |
| 3810 | */ | 3829 | */ |
| @@ -4589,7 +4608,7 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep, | |||
| 4589 | } | 4608 | } |
| 4590 | 4609 | ||
| 4591 | /* | 4610 | /* |
| 4592 | * sctp_sf_t1_timer_expire | 4611 | * sctp_sf_t1_init_timer_expire |
| 4593 | * | 4612 | * |
| 4594 | * Section: 4 Note: 2 | 4613 | * Section: 4 Note: 2 |
| 4595 | * Verification Tag: | 4614 | * Verification Tag: |
| @@ -4603,7 +4622,59 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep, | |||
| 4603 | * endpoint MUST abort the initialization process and report the | 4622 | * endpoint MUST abort the initialization process and report the |
| 4604 | * error to SCTP user. | 4623 | * error to SCTP user. |
| 4605 | * | 4624 | * |
| 4606 | * 3) If the T1-cookie timer expires, the endpoint MUST retransmit | 4625 | * Outputs |
| 4626 | * (timers, events) | ||
| 4627 | * | ||
| 4628 | */ | ||
| 4629 | sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep, | ||
| 4630 | const struct sctp_association *asoc, | ||
| 4631 | const sctp_subtype_t type, | ||
| 4632 | void *arg, | ||
| 4633 | sctp_cmd_seq_t *commands) | ||
| 4634 | { | ||
| 4635 | struct sctp_chunk *repl = NULL; | ||
| 4636 | struct sctp_bind_addr *bp; | ||
| 4637 | int attempts = asoc->init_err_counter + 1; | ||
| 4638 | |||
| 4639 | SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n"); | ||
| 4640 | |||
| 4641 | if (attempts < asoc->max_init_attempts) { | ||
| 4642 | bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; | ||
| 4643 | repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0); | ||
| 4644 | if (!repl) | ||
| 4645 | return SCTP_DISPOSITION_NOMEM; | ||
| 4646 | |||
| 4647 | /* Choose transport for INIT. */ | ||
| 4648 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT, | ||
| 4649 | SCTP_CHUNK(repl)); | ||
| 4650 | |||
| 4651 | /* Issue a sideeffect to do the needed accounting. */ | ||
| 4652 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_RESTART, | ||
| 4653 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); | ||
| 4654 | |||
| 4655 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | ||
| 4656 | } else { | ||
| 4657 | SCTP_DEBUG_PRINTK("Giving up on INIT, attempts: %d" | ||
| 4658 | " max_init_attempts: %d\n", | ||
| 4659 | attempts, asoc->max_init_attempts); | ||
| 4660 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | ||
| 4661 | SCTP_U32(SCTP_ERROR_NO_ERROR)); | ||
| 4662 | return SCTP_DISPOSITION_DELETE_TCB; | ||
| 4663 | } | ||
| 4664 | |||
| 4665 | return SCTP_DISPOSITION_CONSUME; | ||
| 4666 | } | ||
| 4667 | |||
| 4668 | /* | ||
| 4669 | * sctp_sf_t1_cookie_timer_expire | ||
| 4670 | * | ||
| 4671 | * Section: 4 Note: 2 | ||
| 4672 | * Verification Tag: | ||
| 4673 | * Inputs | ||
| 4674 | * (endpoint, asoc) | ||
| 4675 | * | ||
| 4676 | * RFC 2960 Section 4 Notes | ||
| 4677 | * 3) If the T1-cookie timer expires, the endpoint MUST retransmit | ||
| 4607 | * COOKIE ECHO and re-start the T1-cookie timer without changing | 4678 | * COOKIE ECHO and re-start the T1-cookie timer without changing |
| 4608 | * state. This MUST be repeated up to 'Max.Init.Retransmits' times. | 4679 | * state. This MUST be repeated up to 'Max.Init.Retransmits' times. |
| 4609 | * After that, the endpoint MUST abort the initialization process and | 4680 | * After that, the endpoint MUST abort the initialization process and |
| @@ -4613,46 +4684,26 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep, | |||
| 4613 | * (timers, events) | 4684 | * (timers, events) |
| 4614 | * | 4685 | * |
| 4615 | */ | 4686 | */ |
| 4616 | sctp_disposition_t sctp_sf_t1_timer_expire(const struct sctp_endpoint *ep, | 4687 | sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep, |
| 4617 | const struct sctp_association *asoc, | 4688 | const struct sctp_association *asoc, |
| 4618 | const sctp_subtype_t type, | 4689 | const sctp_subtype_t type, |
| 4619 | void *arg, | 4690 | void *arg, |
| 4620 | sctp_cmd_seq_t *commands) | 4691 | sctp_cmd_seq_t *commands) |
| 4621 | { | 4692 | { |
| 4622 | struct sctp_chunk *repl; | 4693 | struct sctp_chunk *repl = NULL; |
| 4623 | struct sctp_bind_addr *bp; | 4694 | int attempts = asoc->init_err_counter + 1; |
| 4624 | sctp_event_timeout_t timer = (sctp_event_timeout_t) arg; | ||
| 4625 | int timeout; | ||
| 4626 | int attempts; | ||
| 4627 | |||
| 4628 | timeout = asoc->timeouts[timer]; | ||
| 4629 | attempts = asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1; | ||
| 4630 | repl = NULL; | ||
| 4631 | 4695 | ||
| 4632 | SCTP_DEBUG_PRINTK("Timer T1 expired.\n"); | 4696 | SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n"); |
| 4633 | 4697 | ||
| 4634 | if (attempts < asoc->max_init_attempts) { | 4698 | if (attempts < asoc->max_init_attempts) { |
| 4635 | switch (timer) { | 4699 | repl = sctp_make_cookie_echo(asoc, NULL); |
| 4636 | case SCTP_EVENT_TIMEOUT_T1_INIT: | ||
| 4637 | bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; | ||
| 4638 | repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0); | ||
| 4639 | break; | ||
| 4640 | |||
| 4641 | case SCTP_EVENT_TIMEOUT_T1_COOKIE: | ||
| 4642 | repl = sctp_make_cookie_echo(asoc, NULL); | ||
| 4643 | break; | ||
| 4644 | |||
| 4645 | default: | ||
| 4646 | BUG(); | ||
| 4647 | break; | ||
| 4648 | }; | ||
| 4649 | |||
| 4650 | if (!repl) | 4700 | if (!repl) |
| 4651 | goto nomem; | 4701 | return SCTP_DISPOSITION_NOMEM; |
| 4652 | 4702 | ||
| 4653 | /* Issue a sideeffect to do the needed accounting. */ | 4703 | /* Issue a sideeffect to do the needed accounting. */ |
| 4654 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_RESTART, | 4704 | sctp_add_cmd_sf(commands, SCTP_CMD_COOKIEECHO_RESTART, |
| 4655 | SCTP_TO(timer)); | 4705 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); |
| 4706 | |||
| 4656 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | 4707 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); |
| 4657 | } else { | 4708 | } else { |
| 4658 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 4709 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
| @@ -4661,9 +4712,6 @@ sctp_disposition_t sctp_sf_t1_timer_expire(const struct sctp_endpoint *ep, | |||
| 4661 | } | 4712 | } |
| 4662 | 4713 | ||
| 4663 | return SCTP_DISPOSITION_CONSUME; | 4714 | return SCTP_DISPOSITION_CONSUME; |
| 4664 | |||
| 4665 | nomem: | ||
| 4666 | return SCTP_DISPOSITION_NOMEM; | ||
| 4667 | } | 4715 | } |
| 4668 | 4716 | ||
| 4669 | /* RFC2960 9.2 If the timer expires, the endpoint must re-send the SHUTDOWN | 4717 | /* RFC2960 9.2 If the timer expires, the endpoint must re-send the SHUTDOWN |
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 8967846f69e8..75ef10408764 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c | |||
| @@ -783,7 +783,8 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
| 783 | /* SCTP_STATE_COOKIE_WAIT */ \ | 783 | /* SCTP_STATE_COOKIE_WAIT */ \ |
| 784 | {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ | 784 | {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ |
| 785 | /* SCTP_STATE_COOKIE_ECHOED */ \ | 785 | /* SCTP_STATE_COOKIE_ECHOED */ \ |
| 786 | {.fn = sctp_sf_t1_timer_expire, .name = "sctp_sf_t1_timer_expire"}, \ | 786 | {.fn = sctp_sf_t1_cookie_timer_expire, \ |
| 787 | .name = "sctp_sf_t1_cookie_timer_expire"}, \ | ||
| 787 | /* SCTP_STATE_ESTABLISHED */ \ | 788 | /* SCTP_STATE_ESTABLISHED */ \ |
| 788 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ | 789 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ |
| 789 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ | 790 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ |
| @@ -802,7 +803,8 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
| 802 | /* SCTP_STATE_CLOSED */ \ | 803 | /* SCTP_STATE_CLOSED */ \ |
| 803 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ | 804 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ |
| 804 | /* SCTP_STATE_COOKIE_WAIT */ \ | 805 | /* SCTP_STATE_COOKIE_WAIT */ \ |
| 805 | {.fn = sctp_sf_t1_timer_expire, .name = "sctp_sf_t1_timer_expire"}, \ | 806 | {.fn = sctp_sf_t1_init_timer_expire, \ |
| 807 | .name = "sctp_sf_t1_init_timer_expire"}, \ | ||
| 806 | /* SCTP_STATE_COOKIE_ECHOED */ \ | 808 | /* SCTP_STATE_COOKIE_ECHOED */ \ |
| 807 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ | 809 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ |
| 808 | /* SCTP_STATE_ESTABLISHED */ \ | 810 | /* SCTP_STATE_ESTABLISHED */ \ |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index e6926cb19420..aad55dc3792b 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -262,18 +262,18 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk, | |||
| 262 | * sockaddr_in6 [RFC 2553]), | 262 | * sockaddr_in6 [RFC 2553]), |
| 263 | * addr_len - the size of the address structure. | 263 | * addr_len - the size of the address structure. |
| 264 | */ | 264 | */ |
| 265 | SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | 265 | SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *addr, int addr_len) |
| 266 | { | 266 | { |
| 267 | int retval = 0; | 267 | int retval = 0; |
| 268 | 268 | ||
| 269 | sctp_lock_sock(sk); | 269 | sctp_lock_sock(sk); |
| 270 | 270 | ||
| 271 | SCTP_DEBUG_PRINTK("sctp_bind(sk: %p, uaddr: %p, addr_len: %d)\n", | 271 | SCTP_DEBUG_PRINTK("sctp_bind(sk: %p, addr: %p, addr_len: %d)\n", |
| 272 | sk, uaddr, addr_len); | 272 | sk, addr, addr_len); |
| 273 | 273 | ||
| 274 | /* Disallow binding twice. */ | 274 | /* Disallow binding twice. */ |
| 275 | if (!sctp_sk(sk)->ep->base.bind_addr.port) | 275 | if (!sctp_sk(sk)->ep->base.bind_addr.port) |
| 276 | retval = sctp_do_bind(sk, (union sctp_addr *)uaddr, | 276 | retval = sctp_do_bind(sk, (union sctp_addr *)addr, |
| 277 | addr_len); | 277 | addr_len); |
| 278 | else | 278 | else |
| 279 | retval = -EINVAL; | 279 | retval = -EINVAL; |
| @@ -318,23 +318,27 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) | |||
| 318 | unsigned short snum; | 318 | unsigned short snum; |
| 319 | int ret = 0; | 319 | int ret = 0; |
| 320 | 320 | ||
| 321 | SCTP_DEBUG_PRINTK("sctp_do_bind(sk: %p, newaddr: %p, len: %d)\n", | ||
| 322 | sk, addr, len); | ||
| 323 | |||
| 324 | /* Common sockaddr verification. */ | 321 | /* Common sockaddr verification. */ |
| 325 | af = sctp_sockaddr_af(sp, addr, len); | 322 | af = sctp_sockaddr_af(sp, addr, len); |
| 326 | if (!af) | 323 | if (!af) { |
| 324 | SCTP_DEBUG_PRINTK("sctp_do_bind(sk: %p, newaddr: %p, len: %d) EINVAL\n", | ||
| 325 | sk, addr, len); | ||
| 327 | return -EINVAL; | 326 | return -EINVAL; |
| 327 | } | ||
| 328 | |||
| 329 | snum = ntohs(addr->v4.sin_port); | ||
| 330 | |||
| 331 | SCTP_DEBUG_PRINTK_IPADDR("sctp_do_bind(sk: %p, new addr: ", | ||
| 332 | ", port: %d, new port: %d, len: %d)\n", | ||
| 333 | sk, | ||
| 334 | addr, | ||
| 335 | bp->port, snum, | ||
| 336 | len); | ||
| 328 | 337 | ||
| 329 | /* PF specific bind() address verification. */ | 338 | /* PF specific bind() address verification. */ |
| 330 | if (!sp->pf->bind_verify(sp, addr)) | 339 | if (!sp->pf->bind_verify(sp, addr)) |
| 331 | return -EADDRNOTAVAIL; | 340 | return -EADDRNOTAVAIL; |
| 332 | 341 | ||
| 333 | snum= ntohs(addr->v4.sin_port); | ||
| 334 | |||
| 335 | SCTP_DEBUG_PRINTK("sctp_do_bind: port: %d, new port: %d\n", | ||
| 336 | bp->port, snum); | ||
| 337 | |||
| 338 | /* We must either be unbound, or bind to the same port. */ | 342 | /* We must either be unbound, or bind to the same port. */ |
| 339 | if (bp->port && (snum != bp->port)) { | 343 | if (bp->port && (snum != bp->port)) { |
| 340 | SCTP_DEBUG_PRINTK("sctp_do_bind:" | 344 | SCTP_DEBUG_PRINTK("sctp_do_bind:" |
| @@ -816,7 +820,8 @@ out: | |||
| 816 | * | 820 | * |
| 817 | * Basically do nothing but copying the addresses from user to kernel | 821 | * Basically do nothing but copying the addresses from user to kernel |
| 818 | * land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk. | 822 | * land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk. |
| 819 | * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() * from userspace. | 823 | * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() |
| 824 | * from userspace. | ||
| 820 | * | 825 | * |
| 821 | * We don't use copy_from_user() for optimization: we first do the | 826 | * We don't use copy_from_user() for optimization: we first do the |
| 822 | * sanity checks (buffer size -fast- and access check-healthy | 827 | * sanity checks (buffer size -fast- and access check-healthy |
| @@ -913,6 +918,243 @@ out: | |||
| 913 | return err; | 918 | return err; |
| 914 | } | 919 | } |
| 915 | 920 | ||
| 921 | /* __sctp_connect(struct sock* sk, struct sockaddr *kaddrs, int addrs_size) | ||
| 922 | * | ||
| 923 | * Common routine for handling connect() and sctp_connectx(). | ||
| 924 | * Connect will come in with just a single address. | ||
| 925 | */ | ||
| 926 | static int __sctp_connect(struct sock* sk, | ||
| 927 | struct sockaddr *kaddrs, | ||
| 928 | int addrs_size) | ||
| 929 | { | ||
| 930 | struct sctp_sock *sp; | ||
| 931 | struct sctp_endpoint *ep; | ||
| 932 | struct sctp_association *asoc = NULL; | ||
| 933 | struct sctp_association *asoc2; | ||
| 934 | struct sctp_transport *transport; | ||
| 935 | union sctp_addr to; | ||
| 936 | struct sctp_af *af; | ||
| 937 | sctp_scope_t scope; | ||
| 938 | long timeo; | ||
| 939 | int err = 0; | ||
| 940 | int addrcnt = 0; | ||
| 941 | int walk_size = 0; | ||
| 942 | struct sockaddr *sa_addr; | ||
| 943 | void *addr_buf; | ||
| 944 | |||
| 945 | sp = sctp_sk(sk); | ||
| 946 | ep = sp->ep; | ||
| 947 | |||
| 948 | /* connect() cannot be done on a socket that is already in ESTABLISHED | ||
| 949 | * state - UDP-style peeled off socket or a TCP-style socket that | ||
| 950 | * is already connected. | ||
| 951 | * It cannot be done even on a TCP-style listening socket. | ||
| 952 | */ | ||
| 953 | if (sctp_sstate(sk, ESTABLISHED) || | ||
| 954 | (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) { | ||
| 955 | err = -EISCONN; | ||
| 956 | goto out_free; | ||
| 957 | } | ||
| 958 | |||
| 959 | /* Walk through the addrs buffer and count the number of addresses. */ | ||
| 960 | addr_buf = kaddrs; | ||
| 961 | while (walk_size < addrs_size) { | ||
| 962 | sa_addr = (struct sockaddr *)addr_buf; | ||
| 963 | af = sctp_get_af_specific(sa_addr->sa_family); | ||
| 964 | |||
| 965 | /* If the address family is not supported or if this address | ||
| 966 | * causes the address buffer to overflow return EINVAL. | ||
| 967 | */ | ||
| 968 | if (!af || (walk_size + af->sockaddr_len) > addrs_size) { | ||
| 969 | err = -EINVAL; | ||
| 970 | goto out_free; | ||
| 971 | } | ||
| 972 | |||
| 973 | err = sctp_verify_addr(sk, (union sctp_addr *)sa_addr, | ||
| 974 | af->sockaddr_len); | ||
| 975 | if (err) | ||
| 976 | goto out_free; | ||
| 977 | |||
| 978 | memcpy(&to, sa_addr, af->sockaddr_len); | ||
| 979 | to.v4.sin_port = ntohs(to.v4.sin_port); | ||
| 980 | |||
| 981 | /* Check if there already is a matching association on the | ||
| 982 | * endpoint (other than the one created here). | ||
| 983 | */ | ||
| 984 | asoc2 = sctp_endpoint_lookup_assoc(ep, &to, &transport); | ||
| 985 | if (asoc2 && asoc2 != asoc) { | ||
| 986 | if (asoc2->state >= SCTP_STATE_ESTABLISHED) | ||
| 987 | err = -EISCONN; | ||
| 988 | else | ||
| 989 | err = -EALREADY; | ||
| 990 | goto out_free; | ||
| 991 | } | ||
| 992 | |||
| 993 | /* If we could not find a matching association on the endpoint, | ||
| 994 | * make sure that there is no peeled-off association matching | ||
| 995 | * the peer address even on another socket. | ||
| 996 | */ | ||
| 997 | if (sctp_endpoint_is_peeled_off(ep, &to)) { | ||
| 998 | err = -EADDRNOTAVAIL; | ||
| 999 | goto out_free; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | if (!asoc) { | ||
| 1003 | /* If a bind() or sctp_bindx() is not called prior to | ||
| 1004 | * an sctp_connectx() call, the system picks an | ||
| 1005 | * ephemeral port and will choose an address set | ||
| 1006 | * equivalent to binding with a wildcard address. | ||
| 1007 | */ | ||
| 1008 | if (!ep->base.bind_addr.port) { | ||
| 1009 | if (sctp_autobind(sk)) { | ||
| 1010 | err = -EAGAIN; | ||
| 1011 | goto out_free; | ||
| 1012 | } | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | scope = sctp_scope(&to); | ||
| 1016 | asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); | ||
| 1017 | if (!asoc) { | ||
| 1018 | err = -ENOMEM; | ||
| 1019 | goto out_free; | ||
| 1020 | } | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | /* Prime the peer's transport structures. */ | ||
| 1024 | transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, | ||
| 1025 | SCTP_UNKNOWN); | ||
| 1026 | if (!transport) { | ||
| 1027 | err = -ENOMEM; | ||
| 1028 | goto out_free; | ||
| 1029 | } | ||
| 1030 | |||
| 1031 | addrcnt++; | ||
| 1032 | addr_buf += af->sockaddr_len; | ||
| 1033 | walk_size += af->sockaddr_len; | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL); | ||
| 1037 | if (err < 0) { | ||
| 1038 | goto out_free; | ||
| 1039 | } | ||
| 1040 | |||
| 1041 | err = sctp_primitive_ASSOCIATE(asoc, NULL); | ||
| 1042 | if (err < 0) { | ||
| 1043 | goto out_free; | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | /* Initialize sk's dport and daddr for getpeername() */ | ||
| 1047 | inet_sk(sk)->dport = htons(asoc->peer.port); | ||
| 1048 | af = sctp_get_af_specific(to.sa.sa_family); | ||
| 1049 | af->to_sk_daddr(&to, sk); | ||
| 1050 | |||
| 1051 | timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK); | ||
| 1052 | err = sctp_wait_for_connect(asoc, &timeo); | ||
| 1053 | |||
| 1054 | /* Don't free association on exit. */ | ||
| 1055 | asoc = NULL; | ||
| 1056 | |||
| 1057 | out_free: | ||
| 1058 | |||
| 1059 | SCTP_DEBUG_PRINTK("About to exit __sctp_connect() free asoc: %p" | ||
| 1060 | " kaddrs: %p err: %d\n", | ||
| 1061 | asoc, kaddrs, err); | ||
| 1062 | if (asoc) | ||
| 1063 | sctp_association_free(asoc); | ||
| 1064 | return err; | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | /* Helper for tunneling sctp_connectx() requests through sctp_setsockopt() | ||
| 1068 | * | ||
| 1069 | * API 8.9 | ||
| 1070 | * int sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt); | ||
| 1071 | * | ||
| 1072 | * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses. | ||
| 1073 | * If the sd is an IPv6 socket, the addresses passed can either be IPv4 | ||
| 1074 | * or IPv6 addresses. | ||
| 1075 | * | ||
| 1076 | * A single address may be specified as INADDR_ANY or IN6ADDR_ANY, see | ||
| 1077 | * Section 3.1.2 for this usage. | ||
| 1078 | * | ||
| 1079 | * addrs is a pointer to an array of one or more socket addresses. Each | ||
| 1080 | * address is contained in its appropriate structure (i.e. struct | ||
| 1081 | * sockaddr_in or struct sockaddr_in6) the family of the address type | ||
| 1082 | * must be used to distengish the address length (note that this | ||
| 1083 | * representation is termed a "packed array" of addresses). The caller | ||
| 1084 | * specifies the number of addresses in the array with addrcnt. | ||
| 1085 | * | ||
| 1086 | * On success, sctp_connectx() returns 0. On failure, sctp_connectx() returns | ||
| 1087 | * -1, and sets errno to the appropriate error code. | ||
| 1088 | * | ||
| 1089 | * For SCTP, the port given in each socket address must be the same, or | ||
| 1090 | * sctp_connectx() will fail, setting errno to EINVAL. | ||
| 1091 | * | ||
| 1092 | * An application can use sctp_connectx to initiate an association with | ||
| 1093 | * an endpoint that is multi-homed. Much like sctp_bindx() this call | ||
| 1094 | * allows a caller to specify multiple addresses at which a peer can be | ||
| 1095 | * reached. The way the SCTP stack uses the list of addresses to set up | ||
| 1096 | * the association is implementation dependant. This function only | ||
| 1097 | * specifies that the stack will try to make use of all the addresses in | ||
| 1098 | * the list when needed. | ||
| 1099 | * | ||
| 1100 | * Note that the list of addresses passed in is only used for setting up | ||
| 1101 | * the association. It does not necessarily equal the set of addresses | ||
| 1102 | * the peer uses for the resulting association. If the caller wants to | ||
| 1103 | * find out the set of peer addresses, it must use sctp_getpaddrs() to | ||
| 1104 | * retrieve them after the association has been set up. | ||
| 1105 | * | ||
| 1106 | * Basically do nothing but copying the addresses from user to kernel | ||
| 1107 | * land and invoking either sctp_connectx(). This is used for tunneling | ||
| 1108 | * the sctp_connectx() request through sctp_setsockopt() from userspace. | ||
| 1109 | * | ||
| 1110 | * We don't use copy_from_user() for optimization: we first do the | ||
| 1111 | * sanity checks (buffer size -fast- and access check-healthy | ||
| 1112 | * pointer); if all of those succeed, then we can alloc the memory | ||
| 1113 | * (expensive operation) needed to copy the data to kernel. Then we do | ||
| 1114 | * the copying without checking the user space area | ||
| 1115 | * (__copy_from_user()). | ||
| 1116 | * | ||
| 1117 | * On exit there is no need to do sockfd_put(), sys_setsockopt() does | ||
| 1118 | * it. | ||
| 1119 | * | ||
| 1120 | * sk The sk of the socket | ||
| 1121 | * addrs The pointer to the addresses in user land | ||
| 1122 | * addrssize Size of the addrs buffer | ||
| 1123 | * | ||
| 1124 | * Returns 0 if ok, <0 errno code on error. | ||
| 1125 | */ | ||
| 1126 | SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk, | ||
| 1127 | struct sockaddr __user *addrs, | ||
| 1128 | int addrs_size) | ||
| 1129 | { | ||
| 1130 | int err = 0; | ||
| 1131 | struct sockaddr *kaddrs; | ||
| 1132 | |||
| 1133 | SCTP_DEBUG_PRINTK("%s - sk %p addrs %p addrs_size %d\n", | ||
| 1134 | __FUNCTION__, sk, addrs, addrs_size); | ||
| 1135 | |||
| 1136 | if (unlikely(addrs_size <= 0)) | ||
| 1137 | return -EINVAL; | ||
| 1138 | |||
| 1139 | /* Check the user passed a healthy pointer. */ | ||
| 1140 | if (unlikely(!access_ok(VERIFY_READ, addrs, addrs_size))) | ||
| 1141 | return -EFAULT; | ||
| 1142 | |||
| 1143 | /* Alloc space for the address array in kernel memory. */ | ||
| 1144 | kaddrs = (struct sockaddr *)kmalloc(addrs_size, GFP_KERNEL); | ||
| 1145 | if (unlikely(!kaddrs)) | ||
| 1146 | return -ENOMEM; | ||
| 1147 | |||
| 1148 | if (__copy_from_user(kaddrs, addrs, addrs_size)) { | ||
| 1149 | err = -EFAULT; | ||
| 1150 | } else { | ||
| 1151 | err = __sctp_connect(sk, kaddrs, addrs_size); | ||
| 1152 | } | ||
| 1153 | |||
| 1154 | kfree(kaddrs); | ||
| 1155 | return err; | ||
| 1156 | } | ||
| 1157 | |||
| 916 | /* API 3.1.4 close() - UDP Style Syntax | 1158 | /* API 3.1.4 close() - UDP Style Syntax |
| 917 | * Applications use close() to perform graceful shutdown (as described in | 1159 | * Applications use close() to perform graceful shutdown (as described in |
| 918 | * Section 10.1 of [SCTP]) on ALL the associations currently represented | 1160 | * Section 10.1 of [SCTP]) on ALL the associations currently represented |
| @@ -1095,7 +1337,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 1095 | sp = sctp_sk(sk); | 1337 | sp = sctp_sk(sk); |
| 1096 | ep = sp->ep; | 1338 | ep = sp->ep; |
| 1097 | 1339 | ||
| 1098 | SCTP_DEBUG_PRINTK("Using endpoint: %s.\n", ep->debug_name); | 1340 | SCTP_DEBUG_PRINTK("Using endpoint: %p.\n", ep); |
| 1099 | 1341 | ||
| 1100 | /* We cannot send a message over a TCP-style listening socket. */ | 1342 | /* We cannot send a message over a TCP-style listening socket. */ |
| 1101 | if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) { | 1343 | if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) { |
| @@ -1306,7 +1548,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 1306 | } | 1548 | } |
| 1307 | 1549 | ||
| 1308 | /* Prime the peer's transport structures. */ | 1550 | /* Prime the peer's transport structures. */ |
| 1309 | transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL); | 1551 | transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, SCTP_UNKNOWN); |
| 1310 | if (!transport) { | 1552 | if (!transport) { |
| 1311 | err = -ENOMEM; | 1553 | err = -ENOMEM; |
| 1312 | goto out_free; | 1554 | goto out_free; |
| @@ -2208,6 +2450,12 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, | |||
| 2208 | optlen, SCTP_BINDX_REM_ADDR); | 2450 | optlen, SCTP_BINDX_REM_ADDR); |
| 2209 | break; | 2451 | break; |
| 2210 | 2452 | ||
| 2453 | case SCTP_SOCKOPT_CONNECTX: | ||
| 2454 | /* 'optlen' is the size of the addresses buffer. */ | ||
| 2455 | retval = sctp_setsockopt_connectx(sk, (struct sockaddr __user *)optval, | ||
| 2456 | optlen); | ||
| 2457 | break; | ||
| 2458 | |||
| 2211 | case SCTP_DISABLE_FRAGMENTS: | 2459 | case SCTP_DISABLE_FRAGMENTS: |
| 2212 | retval = sctp_setsockopt_disable_fragments(sk, optval, optlen); | 2460 | retval = sctp_setsockopt_disable_fragments(sk, optval, optlen); |
| 2213 | break; | 2461 | break; |
| @@ -2283,112 +2531,29 @@ out_nounlock: | |||
| 2283 | * | 2531 | * |
| 2284 | * len: the size of the address. | 2532 | * len: the size of the address. |
| 2285 | */ | 2533 | */ |
| 2286 | SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr, | 2534 | SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *addr, |
| 2287 | int addr_len) | 2535 | int addr_len) |
| 2288 | { | 2536 | { |
| 2289 | struct sctp_sock *sp; | ||
| 2290 | struct sctp_endpoint *ep; | ||
| 2291 | struct sctp_association *asoc; | ||
| 2292 | struct sctp_transport *transport; | ||
| 2293 | union sctp_addr to; | ||
| 2294 | struct sctp_af *af; | ||
| 2295 | sctp_scope_t scope; | ||
| 2296 | long timeo; | ||
| 2297 | int err = 0; | 2537 | int err = 0; |
| 2538 | struct sctp_af *af; | ||
| 2298 | 2539 | ||
| 2299 | sctp_lock_sock(sk); | 2540 | sctp_lock_sock(sk); |
| 2300 | 2541 | ||
| 2301 | SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d)\n", | 2542 | SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d\n", |
| 2302 | __FUNCTION__, sk, uaddr, addr_len); | 2543 | __FUNCTION__, sk, addr, addr_len); |
| 2303 | |||
| 2304 | sp = sctp_sk(sk); | ||
| 2305 | ep = sp->ep; | ||
| 2306 | |||
| 2307 | /* connect() cannot be done on a socket that is already in ESTABLISHED | ||
| 2308 | * state - UDP-style peeled off socket or a TCP-style socket that | ||
| 2309 | * is already connected. | ||
| 2310 | * It cannot be done even on a TCP-style listening socket. | ||
| 2311 | */ | ||
| 2312 | if (sctp_sstate(sk, ESTABLISHED) || | ||
| 2313 | (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) { | ||
| 2314 | err = -EISCONN; | ||
| 2315 | goto out_unlock; | ||
| 2316 | } | ||
| 2317 | |||
| 2318 | err = sctp_verify_addr(sk, (union sctp_addr *)uaddr, addr_len); | ||
| 2319 | if (err) | ||
| 2320 | goto out_unlock; | ||
| 2321 | |||
| 2322 | if (addr_len > sizeof(to)) | ||
| 2323 | addr_len = sizeof(to); | ||
| 2324 | memcpy(&to, uaddr, addr_len); | ||
| 2325 | to.v4.sin_port = ntohs(to.v4.sin_port); | ||
| 2326 | |||
| 2327 | asoc = sctp_endpoint_lookup_assoc(ep, &to, &transport); | ||
| 2328 | if (asoc) { | ||
| 2329 | if (asoc->state >= SCTP_STATE_ESTABLISHED) | ||
| 2330 | err = -EISCONN; | ||
| 2331 | else | ||
| 2332 | err = -EALREADY; | ||
| 2333 | goto out_unlock; | ||
| 2334 | } | ||
| 2335 | |||
| 2336 | /* If we could not find a matching association on the endpoint, | ||
| 2337 | * make sure that there is no peeled-off association matching the | ||
| 2338 | * peer address even on another socket. | ||
| 2339 | */ | ||
| 2340 | if (sctp_endpoint_is_peeled_off(ep, &to)) { | ||
| 2341 | err = -EADDRNOTAVAIL; | ||
| 2342 | goto out_unlock; | ||
| 2343 | } | ||
| 2344 | |||
| 2345 | /* If a bind() or sctp_bindx() is not called prior to a connect() | ||
| 2346 | * call, the system picks an ephemeral port and will choose an address | ||
| 2347 | * set equivalent to binding with a wildcard address. | ||
| 2348 | */ | ||
| 2349 | if (!ep->base.bind_addr.port) { | ||
| 2350 | if (sctp_autobind(sk)) { | ||
| 2351 | err = -EAGAIN; | ||
| 2352 | goto out_unlock; | ||
| 2353 | } | ||
| 2354 | } | ||
| 2355 | |||
| 2356 | scope = sctp_scope(&to); | ||
| 2357 | asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); | ||
| 2358 | if (!asoc) { | ||
| 2359 | err = -ENOMEM; | ||
| 2360 | goto out_unlock; | ||
| 2361 | } | ||
| 2362 | 2544 | ||
| 2363 | /* Prime the peer's transport structures. */ | 2545 | /* Validate addr_len before calling common connect/connectx routine. */ |
| 2364 | transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL); | 2546 | af = sctp_get_af_specific(addr->sa_family); |
| 2365 | if (!transport) { | 2547 | if (!af || addr_len < af->sockaddr_len) { |
| 2366 | sctp_association_free(asoc); | 2548 | err = -EINVAL; |
| 2367 | goto out_unlock; | 2549 | } else { |
| 2368 | } | 2550 | /* Pass correct addr len to common routine (so it knows there |
| 2369 | err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL); | 2551 | * is only one address being passed. |
| 2370 | if (err < 0) { | 2552 | */ |
| 2371 | sctp_association_free(asoc); | 2553 | err = __sctp_connect(sk, addr, af->sockaddr_len); |
| 2372 | goto out_unlock; | ||
| 2373 | } | ||
| 2374 | |||
| 2375 | err = sctp_primitive_ASSOCIATE(asoc, NULL); | ||
| 2376 | if (err < 0) { | ||
| 2377 | sctp_association_free(asoc); | ||
| 2378 | goto out_unlock; | ||
| 2379 | } | 2554 | } |
| 2380 | 2555 | ||
| 2381 | /* Initialize sk's dport and daddr for getpeername() */ | ||
| 2382 | inet_sk(sk)->dport = htons(asoc->peer.port); | ||
| 2383 | af = sctp_get_af_specific(to.sa.sa_family); | ||
| 2384 | af->to_sk_daddr(&to, sk); | ||
| 2385 | |||
| 2386 | timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK); | ||
| 2387 | err = sctp_wait_for_connect(asoc, &timeo); | ||
| 2388 | |||
| 2389 | out_unlock: | ||
| 2390 | sctp_release_sock(sk); | 2556 | sctp_release_sock(sk); |
| 2391 | |||
| 2392 | return err; | 2557 | return err; |
| 2393 | } | 2558 | } |
| 2394 | 2559 | ||
| @@ -2677,12 +2842,15 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, | |||
| 2677 | /* Map ipv4 address into v4-mapped-on-v6 address. */ | 2842 | /* Map ipv4 address into v4-mapped-on-v6 address. */ |
| 2678 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), | 2843 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), |
| 2679 | (union sctp_addr *)&status.sstat_primary.spinfo_address); | 2844 | (union sctp_addr *)&status.sstat_primary.spinfo_address); |
| 2680 | status.sstat_primary.spinfo_state = transport->active; | 2845 | status.sstat_primary.spinfo_state = transport->state; |
| 2681 | status.sstat_primary.spinfo_cwnd = transport->cwnd; | 2846 | status.sstat_primary.spinfo_cwnd = transport->cwnd; |
| 2682 | status.sstat_primary.spinfo_srtt = transport->srtt; | 2847 | status.sstat_primary.spinfo_srtt = transport->srtt; |
| 2683 | status.sstat_primary.spinfo_rto = jiffies_to_msecs(transport->rto); | 2848 | status.sstat_primary.spinfo_rto = jiffies_to_msecs(transport->rto); |
| 2684 | status.sstat_primary.spinfo_mtu = transport->pmtu; | 2849 | status.sstat_primary.spinfo_mtu = transport->pmtu; |
| 2685 | 2850 | ||
| 2851 | if (status.sstat_primary.spinfo_state == SCTP_UNKNOWN) | ||
| 2852 | status.sstat_primary.spinfo_state = SCTP_ACTIVE; | ||
| 2853 | |||
| 2686 | if (put_user(len, optlen)) { | 2854 | if (put_user(len, optlen)) { |
| 2687 | retval = -EFAULT; | 2855 | retval = -EFAULT; |
| 2688 | goto out; | 2856 | goto out; |
| @@ -2733,12 +2901,15 @@ static int sctp_getsockopt_peer_addr_info(struct sock *sk, int len, | |||
| 2733 | return -EINVAL; | 2901 | return -EINVAL; |
| 2734 | 2902 | ||
| 2735 | pinfo.spinfo_assoc_id = sctp_assoc2id(transport->asoc); | 2903 | pinfo.spinfo_assoc_id = sctp_assoc2id(transport->asoc); |
| 2736 | pinfo.spinfo_state = transport->active; | 2904 | pinfo.spinfo_state = transport->state; |
| 2737 | pinfo.spinfo_cwnd = transport->cwnd; | 2905 | pinfo.spinfo_cwnd = transport->cwnd; |
| 2738 | pinfo.spinfo_srtt = transport->srtt; | 2906 | pinfo.spinfo_srtt = transport->srtt; |
| 2739 | pinfo.spinfo_rto = jiffies_to_msecs(transport->rto); | 2907 | pinfo.spinfo_rto = jiffies_to_msecs(transport->rto); |
| 2740 | pinfo.spinfo_mtu = transport->pmtu; | 2908 | pinfo.spinfo_mtu = transport->pmtu; |
| 2741 | 2909 | ||
| 2910 | if (pinfo.spinfo_state == SCTP_UNKNOWN) | ||
| 2911 | pinfo.spinfo_state = SCTP_ACTIVE; | ||
| 2912 | |||
| 2742 | if (put_user(len, optlen)) { | 2913 | if (put_user(len, optlen)) { |
| 2743 | retval = -EFAULT; | 2914 | retval = -EFAULT; |
| 2744 | goto out; | 2915 | goto out; |
| @@ -3591,7 +3762,8 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
| 3591 | int retval = 0; | 3762 | int retval = 0; |
| 3592 | int len; | 3763 | int len; |
| 3593 | 3764 | ||
| 3594 | SCTP_DEBUG_PRINTK("sctp_getsockopt(sk: %p, ...)\n", sk); | 3765 | SCTP_DEBUG_PRINTK("sctp_getsockopt(sk: %p... optname: %d)\n", |
| 3766 | sk, optname); | ||
| 3595 | 3767 | ||
| 3596 | /* I can hardly begin to describe how wrong this is. This is | 3768 | /* I can hardly begin to describe how wrong this is. This is |
| 3597 | * so broken as to be worse than useless. The API draft | 3769 | * so broken as to be worse than useless. The API draft |
| @@ -4596,8 +4768,7 @@ out: | |||
| 4596 | return err; | 4768 | return err; |
| 4597 | 4769 | ||
| 4598 | do_error: | 4770 | do_error: |
| 4599 | if (asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1 >= | 4771 | if (asoc->init_err_counter + 1 >= asoc->max_init_attempts) |
| 4600 | asoc->max_init_attempts) | ||
| 4601 | err = -ETIMEDOUT; | 4772 | err = -ETIMEDOUT; |
| 4602 | else | 4773 | else |
| 4603 | err = -ECONNREFUSED; | 4774 | err = -ECONNREFUSED; |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index f30882e1e96a..0ec0fde6e6c5 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
| @@ -83,7 +83,9 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
| 83 | peer->last_time_used = jiffies; | 83 | peer->last_time_used = jiffies; |
| 84 | peer->last_time_ecne_reduced = jiffies; | 84 | peer->last_time_ecne_reduced = jiffies; |
| 85 | 85 | ||
| 86 | peer->active = SCTP_ACTIVE; | 86 | peer->init_sent_count = 0; |
| 87 | |||
| 88 | peer->state = SCTP_ACTIVE; | ||
| 87 | peer->hb_allowed = 0; | 89 | peer->hb_allowed = 0; |
| 88 | 90 | ||
| 89 | /* Initialize the default path max_retrans. */ | 91 | /* Initialize the default path max_retrans. */ |
