diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/associola.c | 9 | ||||
-rw-r--r-- | net/sctp/output.c | 3 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 52 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 48 |
4 files changed, 77 insertions, 35 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 8472b8b349c4..abd51cef2413 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -599,11 +599,12 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
599 | /* Check to see if this is a duplicate. */ | 599 | /* Check to see if this is a duplicate. */ |
600 | peer = sctp_assoc_lookup_paddr(asoc, addr); | 600 | peer = sctp_assoc_lookup_paddr(asoc, addr); |
601 | if (peer) { | 601 | if (peer) { |
602 | /* An UNKNOWN state is only set on transports added by | ||
603 | * user in sctp_connectx() call. Such transports should be | ||
604 | * considered CONFIRMED per RFC 4960, Section 5.4. | ||
605 | */ | ||
602 | if (peer->state == SCTP_UNKNOWN) { | 606 | if (peer->state == SCTP_UNKNOWN) { |
603 | if (peer_state == SCTP_ACTIVE) | 607 | peer->state = SCTP_ACTIVE; |
604 | peer->state = SCTP_ACTIVE; | ||
605 | if (peer_state == SCTP_UNCONFIRMED) | ||
606 | peer->state = SCTP_UNCONFIRMED; | ||
607 | } | 608 | } |
608 | return peer; | 609 | return peer; |
609 | } | 610 | } |
diff --git a/net/sctp/output.c b/net/sctp/output.c index 0dc4a7dfb234..225c7123c41f 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -533,7 +533,8 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
533 | if (!(dst->dev->features & NETIF_F_NO_CSUM)) { | 533 | if (!(dst->dev->features & NETIF_F_NO_CSUM)) { |
534 | crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); | 534 | crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); |
535 | crc32 = sctp_end_cksum(crc32); | 535 | crc32 = sctp_end_cksum(crc32); |
536 | } | 536 | } else |
537 | nskb->ip_summed = CHECKSUM_UNNECESSARY; | ||
537 | 538 | ||
538 | /* 3) Put the resultant value into the checksum field in the | 539 | /* 3) Put the resultant value into the checksum field in the |
539 | * common header, and leave the rest of the bits unchanged. | 540 | * common header, and leave the rest of the bits unchanged. |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index e8ca4e54981f..d68869f966c3 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -1012,6 +1012,29 @@ end: | |||
1012 | return retval; | 1012 | return retval; |
1013 | } | 1013 | } |
1014 | 1014 | ||
1015 | struct sctp_chunk *sctp_make_violation_paramlen( | ||
1016 | const struct sctp_association *asoc, | ||
1017 | const struct sctp_chunk *chunk, | ||
1018 | struct sctp_paramhdr *param) | ||
1019 | { | ||
1020 | struct sctp_chunk *retval; | ||
1021 | static const char error[] = "The following parameter had invalid length:"; | ||
1022 | size_t payload_len = sizeof(error) + sizeof(sctp_errhdr_t) + | ||
1023 | sizeof(sctp_paramhdr_t); | ||
1024 | |||
1025 | retval = sctp_make_abort(asoc, chunk, payload_len); | ||
1026 | if (!retval) | ||
1027 | goto nodata; | ||
1028 | |||
1029 | sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, | ||
1030 | sizeof(error) + sizeof(sctp_paramhdr_t)); | ||
1031 | sctp_addto_chunk(retval, sizeof(error), error); | ||
1032 | sctp_addto_param(retval, sizeof(sctp_paramhdr_t), param); | ||
1033 | |||
1034 | nodata: | ||
1035 | return retval; | ||
1036 | } | ||
1037 | |||
1015 | /* Make a HEARTBEAT chunk. */ | 1038 | /* Make a HEARTBEAT chunk. */ |
1016 | struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, | 1039 | struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, |
1017 | const struct sctp_transport *transport, | 1040 | const struct sctp_transport *transport, |
@@ -1782,11 +1805,6 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc, | |||
1782 | const struct sctp_chunk *chunk, | 1805 | const struct sctp_chunk *chunk, |
1783 | struct sctp_chunk **errp) | 1806 | struct sctp_chunk **errp) |
1784 | { | 1807 | { |
1785 | static const char error[] = "The following parameter had invalid length:"; | ||
1786 | size_t payload_len = WORD_ROUND(sizeof(error)) + | ||
1787 | sizeof(sctp_paramhdr_t); | ||
1788 | |||
1789 | |||
1790 | /* This is a fatal error. Any accumulated non-fatal errors are | 1808 | /* This is a fatal error. Any accumulated non-fatal errors are |
1791 | * not reported. | 1809 | * not reported. |
1792 | */ | 1810 | */ |
@@ -1794,14 +1812,7 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc, | |||
1794 | sctp_chunk_free(*errp); | 1812 | sctp_chunk_free(*errp); |
1795 | 1813 | ||
1796 | /* Create an error chunk and fill it in with our payload. */ | 1814 | /* Create an error chunk and fill it in with our payload. */ |
1797 | *errp = sctp_make_op_error_space(asoc, chunk, payload_len); | 1815 | *errp = sctp_make_violation_paramlen(asoc, chunk, param); |
1798 | |||
1799 | if (*errp) { | ||
1800 | sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, | ||
1801 | sizeof(error) + sizeof(sctp_paramhdr_t)); | ||
1802 | sctp_addto_chunk(*errp, sizeof(error), error); | ||
1803 | sctp_addto_param(*errp, sizeof(sctp_paramhdr_t), param); | ||
1804 | } | ||
1805 | 1816 | ||
1806 | return 0; | 1817 | return 0; |
1807 | } | 1818 | } |
@@ -1886,11 +1897,13 @@ static void sctp_process_ext_param(struct sctp_association *asoc, | |||
1886 | /* if the peer reports AUTH, assume that he | 1897 | /* if the peer reports AUTH, assume that he |
1887 | * supports AUTH. | 1898 | * supports AUTH. |
1888 | */ | 1899 | */ |
1889 | asoc->peer.auth_capable = 1; | 1900 | if (sctp_auth_enable) |
1901 | asoc->peer.auth_capable = 1; | ||
1890 | break; | 1902 | break; |
1891 | case SCTP_CID_ASCONF: | 1903 | case SCTP_CID_ASCONF: |
1892 | case SCTP_CID_ASCONF_ACK: | 1904 | case SCTP_CID_ASCONF_ACK: |
1893 | asoc->peer.asconf_capable = 1; | 1905 | if (sctp_addip_enable) |
1906 | asoc->peer.asconf_capable = 1; | ||
1894 | break; | 1907 | break; |
1895 | default: | 1908 | default: |
1896 | break; | 1909 | break; |
@@ -2319,12 +2332,10 @@ clean_up: | |||
2319 | /* Release the transport structures. */ | 2332 | /* Release the transport structures. */ |
2320 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { | 2333 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { |
2321 | transport = list_entry(pos, struct sctp_transport, transports); | 2334 | transport = list_entry(pos, struct sctp_transport, transports); |
2322 | list_del_init(pos); | 2335 | if (transport->state != SCTP_ACTIVE) |
2323 | sctp_transport_free(transport); | 2336 | sctp_assoc_rm_peer(asoc, transport); |
2324 | } | 2337 | } |
2325 | 2338 | ||
2326 | asoc->peer.transport_count = 0; | ||
2327 | |||
2328 | nomem: | 2339 | nomem: |
2329 | return 0; | 2340 | return 0; |
2330 | } | 2341 | } |
@@ -2460,6 +2471,9 @@ do_addr_param: | |||
2460 | break; | 2471 | break; |
2461 | 2472 | ||
2462 | case SCTP_PARAM_SET_PRIMARY: | 2473 | case SCTP_PARAM_SET_PRIMARY: |
2474 | if (!sctp_addip_enable) | ||
2475 | goto fall_through; | ||
2476 | |||
2463 | addr_param = param.v + sizeof(sctp_addip_param_t); | 2477 | addr_param = param.v + sizeof(sctp_addip_param_t); |
2464 | 2478 | ||
2465 | af = sctp_get_af_specific(param_type2af(param.p->type)); | 2479 | af = sctp_get_af_specific(param_type2af(param.p->type)); |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 8848d329aa2c..7c622af2ce55 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -119,7 +119,7 @@ static sctp_disposition_t sctp_sf_violation_paramlen( | |||
119 | const struct sctp_endpoint *ep, | 119 | const struct sctp_endpoint *ep, |
120 | const struct sctp_association *asoc, | 120 | const struct sctp_association *asoc, |
121 | const sctp_subtype_t type, | 121 | const sctp_subtype_t type, |
122 | void *arg, | 122 | void *arg, void *ext, |
123 | sctp_cmd_seq_t *commands); | 123 | sctp_cmd_seq_t *commands); |
124 | 124 | ||
125 | static sctp_disposition_t sctp_sf_violation_ctsn( | 125 | static sctp_disposition_t sctp_sf_violation_ctsn( |
@@ -3425,7 +3425,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, | |||
3425 | addr_param = (union sctp_addr_param *)hdr->params; | 3425 | addr_param = (union sctp_addr_param *)hdr->params; |
3426 | length = ntohs(addr_param->p.length); | 3426 | length = ntohs(addr_param->p.length); |
3427 | if (length < sizeof(sctp_paramhdr_t)) | 3427 | if (length < sizeof(sctp_paramhdr_t)) |
3428 | return sctp_sf_violation_paramlen(ep, asoc, type, | 3428 | return sctp_sf_violation_paramlen(ep, asoc, type, arg, |
3429 | (void *)addr_param, commands); | 3429 | (void *)addr_param, commands); |
3430 | 3430 | ||
3431 | /* Verify the ASCONF chunk before processing it. */ | 3431 | /* Verify the ASCONF chunk before processing it. */ |
@@ -3433,8 +3433,8 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, | |||
3433 | (sctp_paramhdr_t *)((void *)addr_param + length), | 3433 | (sctp_paramhdr_t *)((void *)addr_param + length), |
3434 | (void *)chunk->chunk_end, | 3434 | (void *)chunk->chunk_end, |
3435 | &err_param)) | 3435 | &err_param)) |
3436 | return sctp_sf_violation_paramlen(ep, asoc, type, | 3436 | return sctp_sf_violation_paramlen(ep, asoc, type, arg, |
3437 | (void *)&err_param, commands); | 3437 | (void *)err_param, commands); |
3438 | 3438 | ||
3439 | /* ADDIP 5.2 E1) Compare the value of the serial number to the value | 3439 | /* ADDIP 5.2 E1) Compare the value of the serial number to the value |
3440 | * the endpoint stored in a new association variable | 3440 | * the endpoint stored in a new association variable |
@@ -3542,8 +3542,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, | |||
3542 | (sctp_paramhdr_t *)addip_hdr->params, | 3542 | (sctp_paramhdr_t *)addip_hdr->params, |
3543 | (void *)asconf_ack->chunk_end, | 3543 | (void *)asconf_ack->chunk_end, |
3544 | &err_param)) | 3544 | &err_param)) |
3545 | return sctp_sf_violation_paramlen(ep, asoc, type, | 3545 | return sctp_sf_violation_paramlen(ep, asoc, type, arg, |
3546 | (void *)&err_param, commands); | 3546 | (void *)err_param, commands); |
3547 | 3547 | ||
3548 | if (last_asconf) { | 3548 | if (last_asconf) { |
3549 | addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr; | 3549 | addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr; |
@@ -4240,12 +4240,38 @@ static sctp_disposition_t sctp_sf_violation_paramlen( | |||
4240 | const struct sctp_endpoint *ep, | 4240 | const struct sctp_endpoint *ep, |
4241 | const struct sctp_association *asoc, | 4241 | const struct sctp_association *asoc, |
4242 | const sctp_subtype_t type, | 4242 | const sctp_subtype_t type, |
4243 | void *arg, | 4243 | void *arg, void *ext, |
4244 | sctp_cmd_seq_t *commands) { | 4244 | sctp_cmd_seq_t *commands) |
4245 | static const char err_str[] = "The following parameter had invalid length:"; | 4245 | { |
4246 | struct sctp_chunk *chunk = arg; | ||
4247 | struct sctp_paramhdr *param = ext; | ||
4248 | struct sctp_chunk *abort = NULL; | ||
4246 | 4249 | ||
4247 | return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str, | 4250 | if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) |
4248 | sizeof(err_str)); | 4251 | goto discard; |
4252 | |||
4253 | /* Make the abort chunk. */ | ||
4254 | abort = sctp_make_violation_paramlen(asoc, chunk, param); | ||
4255 | if (!abort) | ||
4256 | goto nomem; | ||
4257 | |||
4258 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); | ||
4259 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | ||
4260 | |||
4261 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
4262 | SCTP_ERROR(ECONNABORTED)); | ||
4263 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | ||
4264 | SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); | ||
4265 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | ||
4266 | |||
4267 | discard: | ||
4268 | sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands); | ||
4269 | |||
4270 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | ||
4271 | |||
4272 | return SCTP_DISPOSITION_ABORT; | ||
4273 | nomem: | ||
4274 | return SCTP_DISPOSITION_NOMEM; | ||
4249 | } | 4275 | } |
4250 | 4276 | ||
4251 | /* Handle a protocol violation when the peer trying to advance the | 4277 | /* Handle a protocol violation when the peer trying to advance the |