diff options
Diffstat (limited to 'net/sctp/sm_make_chunk.c')
-rw-r--r-- | net/sctp/sm_make_chunk.c | 67 |
1 files changed, 42 insertions, 25 deletions
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index e8ca4e54981f..fd8acb48c3f2 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -702,12 +702,14 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc) | |||
702 | __u32 ctsn; | 702 | __u32 ctsn; |
703 | __u16 num_gabs, num_dup_tsns; | 703 | __u16 num_gabs, num_dup_tsns; |
704 | struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map; | 704 | struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map; |
705 | struct sctp_gap_ack_block gabs[SCTP_MAX_GABS]; | ||
705 | 706 | ||
707 | memset(gabs, 0, sizeof(gabs)); | ||
706 | ctsn = sctp_tsnmap_get_ctsn(map); | 708 | ctsn = sctp_tsnmap_get_ctsn(map); |
707 | SCTP_DEBUG_PRINTK("sackCTSNAck sent: 0x%x.\n", ctsn); | 709 | SCTP_DEBUG_PRINTK("sackCTSNAck sent: 0x%x.\n", ctsn); |
708 | 710 | ||
709 | /* How much room is needed in the chunk? */ | 711 | /* How much room is needed in the chunk? */ |
710 | num_gabs = sctp_tsnmap_num_gabs(map); | 712 | num_gabs = sctp_tsnmap_num_gabs(map, gabs); |
711 | num_dup_tsns = sctp_tsnmap_num_dups(map); | 713 | num_dup_tsns = sctp_tsnmap_num_dups(map); |
712 | 714 | ||
713 | /* Initialize the SACK header. */ | 715 | /* Initialize the SACK header. */ |
@@ -763,7 +765,7 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc) | |||
763 | /* Add the gap ack block information. */ | 765 | /* Add the gap ack block information. */ |
764 | if (num_gabs) | 766 | if (num_gabs) |
765 | sctp_addto_chunk(retval, sizeof(__u32) * num_gabs, | 767 | sctp_addto_chunk(retval, sizeof(__u32) * num_gabs, |
766 | sctp_tsnmap_get_gabs(map)); | 768 | gabs); |
767 | 769 | ||
768 | /* Add the duplicate TSN information. */ | 770 | /* Add the duplicate TSN information. */ |
769 | if (num_dup_tsns) | 771 | if (num_dup_tsns) |
@@ -1012,6 +1014,29 @@ end: | |||
1012 | return retval; | 1014 | return retval; |
1013 | } | 1015 | } |
1014 | 1016 | ||
1017 | struct sctp_chunk *sctp_make_violation_paramlen( | ||
1018 | const struct sctp_association *asoc, | ||
1019 | const struct sctp_chunk *chunk, | ||
1020 | struct sctp_paramhdr *param) | ||
1021 | { | ||
1022 | struct sctp_chunk *retval; | ||
1023 | static const char error[] = "The following parameter had invalid length:"; | ||
1024 | size_t payload_len = sizeof(error) + sizeof(sctp_errhdr_t) + | ||
1025 | sizeof(sctp_paramhdr_t); | ||
1026 | |||
1027 | retval = sctp_make_abort(asoc, chunk, payload_len); | ||
1028 | if (!retval) | ||
1029 | goto nodata; | ||
1030 | |||
1031 | sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, | ||
1032 | sizeof(error) + sizeof(sctp_paramhdr_t)); | ||
1033 | sctp_addto_chunk(retval, sizeof(error), error); | ||
1034 | sctp_addto_param(retval, sizeof(sctp_paramhdr_t), param); | ||
1035 | |||
1036 | nodata: | ||
1037 | return retval; | ||
1038 | } | ||
1039 | |||
1015 | /* Make a HEARTBEAT chunk. */ | 1040 | /* Make a HEARTBEAT chunk. */ |
1016 | struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, | 1041 | struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, |
1017 | const struct sctp_transport *transport, | 1042 | const struct sctp_transport *transport, |
@@ -1188,7 +1213,7 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb, | |||
1188 | */ | 1213 | */ |
1189 | retval->tsn_missing_report = 0; | 1214 | retval->tsn_missing_report = 0; |
1190 | retval->tsn_gap_acked = 0; | 1215 | retval->tsn_gap_acked = 0; |
1191 | retval->fast_retransmit = 0; | 1216 | retval->fast_retransmit = SCTP_CAN_FRTX; |
1192 | 1217 | ||
1193 | /* If this is a fragmented message, track all fragments | 1218 | /* If this is a fragmented message, track all fragments |
1194 | * of the message (for SEND_FAILED). | 1219 | * of the message (for SEND_FAILED). |
@@ -1782,11 +1807,6 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc, | |||
1782 | const struct sctp_chunk *chunk, | 1807 | const struct sctp_chunk *chunk, |
1783 | struct sctp_chunk **errp) | 1808 | struct sctp_chunk **errp) |
1784 | { | 1809 | { |
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 | 1810 | /* This is a fatal error. Any accumulated non-fatal errors are |
1791 | * not reported. | 1811 | * not reported. |
1792 | */ | 1812 | */ |
@@ -1794,14 +1814,7 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc, | |||
1794 | sctp_chunk_free(*errp); | 1814 | sctp_chunk_free(*errp); |
1795 | 1815 | ||
1796 | /* Create an error chunk and fill it in with our payload. */ | 1816 | /* Create an error chunk and fill it in with our payload. */ |
1797 | *errp = sctp_make_op_error_space(asoc, chunk, payload_len); | 1817 | *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 | 1818 | ||
1806 | return 0; | 1819 | return 0; |
1807 | } | 1820 | } |
@@ -1886,11 +1899,13 @@ static void sctp_process_ext_param(struct sctp_association *asoc, | |||
1886 | /* if the peer reports AUTH, assume that he | 1899 | /* if the peer reports AUTH, assume that he |
1887 | * supports AUTH. | 1900 | * supports AUTH. |
1888 | */ | 1901 | */ |
1889 | asoc->peer.auth_capable = 1; | 1902 | if (sctp_auth_enable) |
1903 | asoc->peer.auth_capable = 1; | ||
1890 | break; | 1904 | break; |
1891 | case SCTP_CID_ASCONF: | 1905 | case SCTP_CID_ASCONF: |
1892 | case SCTP_CID_ASCONF_ACK: | 1906 | case SCTP_CID_ASCONF_ACK: |
1893 | asoc->peer.asconf_capable = 1; | 1907 | if (sctp_addip_enable) |
1908 | asoc->peer.asconf_capable = 1; | ||
1894 | break; | 1909 | break; |
1895 | default: | 1910 | default: |
1896 | break; | 1911 | break; |
@@ -2275,8 +2290,9 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
2275 | } | 2290 | } |
2276 | 2291 | ||
2277 | /* Set up the TSN tracking pieces. */ | 2292 | /* Set up the TSN tracking pieces. */ |
2278 | sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_SIZE, | 2293 | if (!sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL, |
2279 | asoc->peer.i.initial_tsn); | 2294 | asoc->peer.i.initial_tsn, gfp)) |
2295 | goto clean_up; | ||
2280 | 2296 | ||
2281 | /* RFC 2960 6.5 Stream Identifier and Stream Sequence Number | 2297 | /* RFC 2960 6.5 Stream Identifier and Stream Sequence Number |
2282 | * | 2298 | * |
@@ -2319,12 +2335,10 @@ clean_up: | |||
2319 | /* Release the transport structures. */ | 2335 | /* Release the transport structures. */ |
2320 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { | 2336 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { |
2321 | transport = list_entry(pos, struct sctp_transport, transports); | 2337 | transport = list_entry(pos, struct sctp_transport, transports); |
2322 | list_del_init(pos); | 2338 | if (transport->state != SCTP_ACTIVE) |
2323 | sctp_transport_free(transport); | 2339 | sctp_assoc_rm_peer(asoc, transport); |
2324 | } | 2340 | } |
2325 | 2341 | ||
2326 | asoc->peer.transport_count = 0; | ||
2327 | |||
2328 | nomem: | 2342 | nomem: |
2329 | return 0; | 2343 | return 0; |
2330 | } | 2344 | } |
@@ -2456,10 +2470,13 @@ do_addr_param: | |||
2456 | break; | 2470 | break; |
2457 | 2471 | ||
2458 | case SCTP_PARAM_ADAPTATION_LAYER_IND: | 2472 | case SCTP_PARAM_ADAPTATION_LAYER_IND: |
2459 | asoc->peer.adaptation_ind = param.aind->adaptation_ind; | 2473 | asoc->peer.adaptation_ind = ntohl(param.aind->adaptation_ind); |
2460 | break; | 2474 | break; |
2461 | 2475 | ||
2462 | case SCTP_PARAM_SET_PRIMARY: | 2476 | case SCTP_PARAM_SET_PRIMARY: |
2477 | if (!sctp_addip_enable) | ||
2478 | goto fall_through; | ||
2479 | |||
2463 | addr_param = param.v + sizeof(sctp_addip_param_t); | 2480 | addr_param = param.v + sizeof(sctp_addip_param_t); |
2464 | 2481 | ||
2465 | af = sctp_get_af_specific(param_type2af(param.p->type)); | 2482 | af = sctp_get_af_specific(param_type2af(param.p->type)); |