diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/associola.c | 29 | ||||
-rw-r--r-- | net/sctp/ipv6.c | 49 | ||||
-rw-r--r-- | net/sctp/protocol.c | 81 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 15 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 35 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 29 | ||||
-rw-r--r-- | net/sctp/socket.c | 40 |
7 files changed, 183 insertions, 95 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index db73ef97485a..df94e3cdfba3 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -1103,6 +1103,13 @@ void sctp_assoc_update(struct sctp_association *asoc, | |||
1103 | asoc->ssnmap = new->ssnmap; | 1103 | asoc->ssnmap = new->ssnmap; |
1104 | new->ssnmap = NULL; | 1104 | new->ssnmap = NULL; |
1105 | } | 1105 | } |
1106 | |||
1107 | if (!asoc->assoc_id) { | ||
1108 | /* get a new association id since we don't have one | ||
1109 | * yet. | ||
1110 | */ | ||
1111 | sctp_assoc_set_id(asoc, GFP_ATOMIC); | ||
1112 | } | ||
1106 | } | 1113 | } |
1107 | } | 1114 | } |
1108 | 1115 | ||
@@ -1375,3 +1382,25 @@ out: | |||
1375 | sctp_read_unlock(&asoc->base.addr_lock); | 1382 | sctp_read_unlock(&asoc->base.addr_lock); |
1376 | return found; | 1383 | return found; |
1377 | } | 1384 | } |
1385 | |||
1386 | /* Set an association id for a given association */ | ||
1387 | int sctp_assoc_set_id(struct sctp_association *asoc, gfp_t gfp) | ||
1388 | { | ||
1389 | int assoc_id; | ||
1390 | int error = 0; | ||
1391 | retry: | ||
1392 | if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp))) | ||
1393 | return -ENOMEM; | ||
1394 | |||
1395 | spin_lock_bh(&sctp_assocs_id_lock); | ||
1396 | error = idr_get_new_above(&sctp_assocs_id, (void *)asoc, | ||
1397 | 1, &assoc_id); | ||
1398 | spin_unlock_bh(&sctp_assocs_id_lock); | ||
1399 | if (error == -EAGAIN) | ||
1400 | goto retry; | ||
1401 | else if (error) | ||
1402 | return error; | ||
1403 | |||
1404 | asoc->assoc_id = (sctp_assoc_t) assoc_id; | ||
1405 | return error; | ||
1406 | } | ||
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index ca527a27dd05..84cd53635fe8 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -992,45 +992,52 @@ static struct sctp_pf sctp_pf_inet6_specific = { | |||
992 | .af = &sctp_ipv6_specific, | 992 | .af = &sctp_ipv6_specific, |
993 | }; | 993 | }; |
994 | 994 | ||
995 | /* Initialize IPv6 support and register with inet6 stack. */ | 995 | /* Initialize IPv6 support and register with socket layer. */ |
996 | int sctp_v6_init(void) | 996 | int sctp_v6_init(void) |
997 | { | 997 | { |
998 | int rc = proto_register(&sctpv6_prot, 1); | 998 | int rc; |
999 | 999 | ||
1000 | /* Register the SCTP specific PF_INET6 functions. */ | ||
1001 | sctp_register_pf(&sctp_pf_inet6_specific, PF_INET6); | ||
1002 | |||
1003 | /* Register the SCTP specific AF_INET6 functions. */ | ||
1004 | sctp_register_af(&sctp_ipv6_specific); | ||
1005 | |||
1006 | rc = proto_register(&sctpv6_prot, 1); | ||
1000 | if (rc) | 1007 | if (rc) |
1001 | goto out; | 1008 | return rc; |
1002 | /* Register inet6 protocol. */ | ||
1003 | rc = -EAGAIN; | ||
1004 | if (inet6_add_protocol(&sctpv6_protocol, IPPROTO_SCTP) < 0) | ||
1005 | goto out_unregister_sctp_proto; | ||
1006 | 1009 | ||
1007 | /* Add SCTPv6(UDP and TCP style) to inetsw6 linked list. */ | 1010 | /* Add SCTPv6(UDP and TCP style) to inetsw6 linked list. */ |
1008 | inet6_register_protosw(&sctpv6_seqpacket_protosw); | 1011 | inet6_register_protosw(&sctpv6_seqpacket_protosw); |
1009 | inet6_register_protosw(&sctpv6_stream_protosw); | 1012 | inet6_register_protosw(&sctpv6_stream_protosw); |
1010 | 1013 | ||
1011 | /* Register the SCTP specific PF_INET6 functions. */ | 1014 | return 0; |
1012 | sctp_register_pf(&sctp_pf_inet6_specific, PF_INET6); | 1015 | } |
1013 | |||
1014 | /* Register the SCTP specific AF_INET6 functions. */ | ||
1015 | sctp_register_af(&sctp_ipv6_specific); | ||
1016 | 1016 | ||
1017 | /* Register with inet6 layer. */ | ||
1018 | int sctp_v6_add_protocol(void) | ||
1019 | { | ||
1017 | /* Register notifier for inet6 address additions/deletions. */ | 1020 | /* Register notifier for inet6 address additions/deletions. */ |
1018 | register_inet6addr_notifier(&sctp_inet6addr_notifier); | 1021 | register_inet6addr_notifier(&sctp_inet6addr_notifier); |
1019 | rc = 0; | 1022 | |
1020 | out: | 1023 | if (inet6_add_protocol(&sctpv6_protocol, IPPROTO_SCTP) < 0) |
1021 | return rc; | 1024 | return -EAGAIN; |
1022 | out_unregister_sctp_proto: | 1025 | |
1023 | proto_unregister(&sctpv6_prot); | 1026 | return 0; |
1024 | goto out; | ||
1025 | } | 1027 | } |
1026 | 1028 | ||
1027 | /* IPv6 specific exit support. */ | 1029 | /* IPv6 specific exit support. */ |
1028 | void sctp_v6_exit(void) | 1030 | void sctp_v6_exit(void) |
1029 | { | 1031 | { |
1030 | list_del(&sctp_ipv6_specific.list); | ||
1031 | inet6_del_protocol(&sctpv6_protocol, IPPROTO_SCTP); | ||
1032 | inet6_unregister_protosw(&sctpv6_seqpacket_protosw); | 1032 | inet6_unregister_protosw(&sctpv6_seqpacket_protosw); |
1033 | inet6_unregister_protosw(&sctpv6_stream_protosw); | 1033 | inet6_unregister_protosw(&sctpv6_stream_protosw); |
1034 | unregister_inet6addr_notifier(&sctp_inet6addr_notifier); | ||
1035 | proto_unregister(&sctpv6_prot); | 1034 | proto_unregister(&sctpv6_prot); |
1035 | list_del(&sctp_ipv6_specific.list); | ||
1036 | } | ||
1037 | |||
1038 | /* Unregister with inet6 layer. */ | ||
1039 | void sctp_v6_del_protocol(void) | ||
1040 | { | ||
1041 | inet6_del_protocol(&sctpv6_protocol, IPPROTO_SCTP); | ||
1042 | unregister_inet6addr_notifier(&sctp_inet6addr_notifier); | ||
1036 | } | 1043 | } |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index c361deb6cea9..34bab36637ac 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -170,7 +170,7 @@ static void sctp_get_local_addr_list(void) | |||
170 | struct sctp_af *af; | 170 | struct sctp_af *af; |
171 | 171 | ||
172 | read_lock(&dev_base_lock); | 172 | read_lock(&dev_base_lock); |
173 | for (dev = dev_base; dev; dev = dev->next) { | 173 | for_each_netdev(dev) { |
174 | __list_for_each(pos, &sctp_address_families) { | 174 | __list_for_each(pos, &sctp_address_families) { |
175 | af = list_entry(pos, struct sctp_af, list); | 175 | af = list_entry(pos, struct sctp_af, list); |
176 | af->copy_addrlist(&sctp_local_addr_list, dev); | 176 | af->copy_addrlist(&sctp_local_addr_list, dev); |
@@ -975,28 +975,14 @@ SCTP_STATIC __init int sctp_init(void) | |||
975 | if (!sctp_sanity_check()) | 975 | if (!sctp_sanity_check()) |
976 | goto out; | 976 | goto out; |
977 | 977 | ||
978 | status = proto_register(&sctp_prot, 1); | 978 | /* Allocate bind_bucket and chunk caches. */ |
979 | if (status) | ||
980 | goto out; | ||
981 | |||
982 | /* Add SCTP to inet_protos hash table. */ | ||
983 | status = -EAGAIN; | ||
984 | if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0) | ||
985 | goto err_add_protocol; | ||
986 | |||
987 | /* Add SCTP(TCP and UDP style) to inetsw linked list. */ | ||
988 | inet_register_protosw(&sctp_seqpacket_protosw); | ||
989 | inet_register_protosw(&sctp_stream_protosw); | ||
990 | |||
991 | /* Allocate a cache pools. */ | ||
992 | status = -ENOBUFS; | 979 | status = -ENOBUFS; |
993 | sctp_bucket_cachep = kmem_cache_create("sctp_bind_bucket", | 980 | sctp_bucket_cachep = kmem_cache_create("sctp_bind_bucket", |
994 | sizeof(struct sctp_bind_bucket), | 981 | sizeof(struct sctp_bind_bucket), |
995 | 0, SLAB_HWCACHE_ALIGN, | 982 | 0, SLAB_HWCACHE_ALIGN, |
996 | NULL, NULL); | 983 | NULL, NULL); |
997 | |||
998 | if (!sctp_bucket_cachep) | 984 | if (!sctp_bucket_cachep) |
999 | goto err_bucket_cachep; | 985 | goto out; |
1000 | 986 | ||
1001 | sctp_chunk_cachep = kmem_cache_create("sctp_chunk", | 987 | sctp_chunk_cachep = kmem_cache_create("sctp_chunk", |
1002 | sizeof(struct sctp_chunk), | 988 | sizeof(struct sctp_chunk), |
@@ -1153,6 +1139,14 @@ SCTP_STATIC __init int sctp_init(void) | |||
1153 | INIT_LIST_HEAD(&sctp_address_families); | 1139 | INIT_LIST_HEAD(&sctp_address_families); |
1154 | sctp_register_af(&sctp_ipv4_specific); | 1140 | sctp_register_af(&sctp_ipv4_specific); |
1155 | 1141 | ||
1142 | status = proto_register(&sctp_prot, 1); | ||
1143 | if (status) | ||
1144 | goto err_proto_register; | ||
1145 | |||
1146 | /* Register SCTP(UDP and TCP style) with socket layer. */ | ||
1147 | inet_register_protosw(&sctp_seqpacket_protosw); | ||
1148 | inet_register_protosw(&sctp_stream_protosw); | ||
1149 | |||
1156 | status = sctp_v6_init(); | 1150 | status = sctp_v6_init(); |
1157 | if (status) | 1151 | if (status) |
1158 | goto err_v6_init; | 1152 | goto err_v6_init; |
@@ -1166,19 +1160,39 @@ SCTP_STATIC __init int sctp_init(void) | |||
1166 | 1160 | ||
1167 | /* Initialize the local address list. */ | 1161 | /* Initialize the local address list. */ |
1168 | INIT_LIST_HEAD(&sctp_local_addr_list); | 1162 | INIT_LIST_HEAD(&sctp_local_addr_list); |
1169 | |||
1170 | sctp_get_local_addr_list(); | 1163 | sctp_get_local_addr_list(); |
1171 | 1164 | ||
1172 | /* Register notifier for inet address additions/deletions. */ | 1165 | /* Register notifier for inet address additions/deletions. */ |
1173 | register_inetaddr_notifier(&sctp_inetaddr_notifier); | 1166 | register_inetaddr_notifier(&sctp_inetaddr_notifier); |
1174 | 1167 | ||
1168 | /* Register SCTP with inet layer. */ | ||
1169 | if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0) { | ||
1170 | status = -EAGAIN; | ||
1171 | goto err_add_protocol; | ||
1172 | } | ||
1173 | |||
1174 | /* Register SCTP with inet6 layer. */ | ||
1175 | status = sctp_v6_add_protocol(); | ||
1176 | if (status) | ||
1177 | goto err_v6_add_protocol; | ||
1178 | |||
1175 | __unsafe(THIS_MODULE); | 1179 | __unsafe(THIS_MODULE); |
1176 | status = 0; | 1180 | status = 0; |
1177 | out: | 1181 | out: |
1178 | return status; | 1182 | return status; |
1183 | err_v6_add_protocol: | ||
1184 | inet_del_protocol(&sctp_protocol, IPPROTO_SCTP); | ||
1185 | unregister_inetaddr_notifier(&sctp_inetaddr_notifier); | ||
1186 | err_add_protocol: | ||
1187 | sctp_free_local_addr_list(); | ||
1188 | sock_release(sctp_ctl_socket); | ||
1179 | err_ctl_sock_init: | 1189 | err_ctl_sock_init: |
1180 | sctp_v6_exit(); | 1190 | sctp_v6_exit(); |
1181 | err_v6_init: | 1191 | err_v6_init: |
1192 | inet_unregister_protosw(&sctp_stream_protosw); | ||
1193 | inet_unregister_protosw(&sctp_seqpacket_protosw); | ||
1194 | proto_unregister(&sctp_prot); | ||
1195 | err_proto_register: | ||
1182 | sctp_sysctl_unregister(); | 1196 | sctp_sysctl_unregister(); |
1183 | list_del(&sctp_ipv4_specific.list); | 1197 | list_del(&sctp_ipv4_specific.list); |
1184 | free_pages((unsigned long)sctp_port_hashtable, | 1198 | free_pages((unsigned long)sctp_port_hashtable, |
@@ -1192,19 +1206,13 @@ err_ehash_alloc: | |||
1192 | sizeof(struct sctp_hashbucket))); | 1206 | sizeof(struct sctp_hashbucket))); |
1193 | err_ahash_alloc: | 1207 | err_ahash_alloc: |
1194 | sctp_dbg_objcnt_exit(); | 1208 | sctp_dbg_objcnt_exit(); |
1195 | err_init_proc: | ||
1196 | sctp_proc_exit(); | 1209 | sctp_proc_exit(); |
1210 | err_init_proc: | ||
1197 | cleanup_sctp_mibs(); | 1211 | cleanup_sctp_mibs(); |
1198 | err_init_mibs: | 1212 | err_init_mibs: |
1199 | kmem_cache_destroy(sctp_chunk_cachep); | 1213 | kmem_cache_destroy(sctp_chunk_cachep); |
1200 | err_chunk_cachep: | 1214 | err_chunk_cachep: |
1201 | kmem_cache_destroy(sctp_bucket_cachep); | 1215 | kmem_cache_destroy(sctp_bucket_cachep); |
1202 | err_bucket_cachep: | ||
1203 | inet_del_protocol(&sctp_protocol, IPPROTO_SCTP); | ||
1204 | inet_unregister_protosw(&sctp_seqpacket_protosw); | ||
1205 | inet_unregister_protosw(&sctp_stream_protosw); | ||
1206 | err_add_protocol: | ||
1207 | proto_unregister(&sctp_prot); | ||
1208 | goto out; | 1216 | goto out; |
1209 | } | 1217 | } |
1210 | 1218 | ||
@@ -1215,8 +1223,9 @@ SCTP_STATIC __exit void sctp_exit(void) | |||
1215 | * up all the remaining associations and all that memory. | 1223 | * up all the remaining associations and all that memory. |
1216 | */ | 1224 | */ |
1217 | 1225 | ||
1218 | /* Unregister notifier for inet address additions/deletions. */ | 1226 | /* Unregister with inet6/inet layers. */ |
1219 | unregister_inetaddr_notifier(&sctp_inetaddr_notifier); | 1227 | sctp_v6_del_protocol(); |
1228 | inet_del_protocol(&sctp_protocol, IPPROTO_SCTP); | ||
1220 | 1229 | ||
1221 | /* Free the local address list. */ | 1230 | /* Free the local address list. */ |
1222 | sctp_free_local_addr_list(); | 1231 | sctp_free_local_addr_list(); |
@@ -1224,7 +1233,16 @@ SCTP_STATIC __exit void sctp_exit(void) | |||
1224 | /* Free the control endpoint. */ | 1233 | /* Free the control endpoint. */ |
1225 | sock_release(sctp_ctl_socket); | 1234 | sock_release(sctp_ctl_socket); |
1226 | 1235 | ||
1236 | /* Cleanup v6 initializations. */ | ||
1227 | sctp_v6_exit(); | 1237 | sctp_v6_exit(); |
1238 | |||
1239 | /* Unregister with socket layer. */ | ||
1240 | inet_unregister_protosw(&sctp_stream_protosw); | ||
1241 | inet_unregister_protosw(&sctp_seqpacket_protosw); | ||
1242 | |||
1243 | /* Unregister notifier for inet address additions/deletions. */ | ||
1244 | unregister_inetaddr_notifier(&sctp_inetaddr_notifier); | ||
1245 | |||
1228 | sctp_sysctl_unregister(); | 1246 | sctp_sysctl_unregister(); |
1229 | list_del(&sctp_ipv4_specific.list); | 1247 | list_del(&sctp_ipv4_specific.list); |
1230 | 1248 | ||
@@ -1236,16 +1254,13 @@ SCTP_STATIC __exit void sctp_exit(void) | |||
1236 | get_order(sctp_port_hashsize * | 1254 | get_order(sctp_port_hashsize * |
1237 | sizeof(struct sctp_bind_hashbucket))); | 1255 | sizeof(struct sctp_bind_hashbucket))); |
1238 | 1256 | ||
1239 | kmem_cache_destroy(sctp_chunk_cachep); | ||
1240 | kmem_cache_destroy(sctp_bucket_cachep); | ||
1241 | |||
1242 | sctp_dbg_objcnt_exit(); | 1257 | sctp_dbg_objcnt_exit(); |
1243 | sctp_proc_exit(); | 1258 | sctp_proc_exit(); |
1244 | cleanup_sctp_mibs(); | 1259 | cleanup_sctp_mibs(); |
1245 | 1260 | ||
1246 | inet_del_protocol(&sctp_protocol, IPPROTO_SCTP); | 1261 | kmem_cache_destroy(sctp_chunk_cachep); |
1247 | inet_unregister_protosw(&sctp_seqpacket_protosw); | 1262 | kmem_cache_destroy(sctp_bucket_cachep); |
1248 | inet_unregister_protosw(&sctp_stream_protosw); | 1263 | |
1249 | proto_unregister(&sctp_prot); | 1264 | proto_unregister(&sctp_prot); |
1250 | } | 1265 | } |
1251 | 1266 | ||
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index be783a3761c4..8d18f570c2e6 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -1939,7 +1939,6 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
1939 | * association. | 1939 | * association. |
1940 | */ | 1940 | */ |
1941 | if (!asoc->temp) { | 1941 | if (!asoc->temp) { |
1942 | int assoc_id; | ||
1943 | int error; | 1942 | int error; |
1944 | 1943 | ||
1945 | asoc->ssnmap = sctp_ssnmap_new(asoc->c.sinit_max_instreams, | 1944 | asoc->ssnmap = sctp_ssnmap_new(asoc->c.sinit_max_instreams, |
@@ -1947,19 +1946,9 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
1947 | if (!asoc->ssnmap) | 1946 | if (!asoc->ssnmap) |
1948 | goto clean_up; | 1947 | goto clean_up; |
1949 | 1948 | ||
1950 | retry: | 1949 | error = sctp_assoc_set_id(asoc, gfp); |
1951 | if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp))) | 1950 | if (error) |
1952 | goto clean_up; | 1951 | goto clean_up; |
1953 | spin_lock_bh(&sctp_assocs_id_lock); | ||
1954 | error = idr_get_new_above(&sctp_assocs_id, (void *)asoc, 1, | ||
1955 | &assoc_id); | ||
1956 | spin_unlock_bh(&sctp_assocs_id_lock); | ||
1957 | if (error == -EAGAIN) | ||
1958 | goto retry; | ||
1959 | else if (error) | ||
1960 | goto clean_up; | ||
1961 | |||
1962 | asoc->assoc_id = (sctp_assoc_t) assoc_id; | ||
1963 | } | 1952 | } |
1964 | 1953 | ||
1965 | /* ADDIP Section 4.1 ASCONF Chunk Procedures | 1954 | /* ADDIP Section 4.1 ASCONF Chunk Procedures |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index b37a7adeb150..d9fad4f6ffc3 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -862,6 +862,33 @@ static void sctp_cmd_set_sk_err(struct sctp_association *asoc, int error) | |||
862 | sk->sk_err = error; | 862 | sk->sk_err = error; |
863 | } | 863 | } |
864 | 864 | ||
865 | /* Helper function to generate an association change event */ | ||
866 | static void sctp_cmd_assoc_change(sctp_cmd_seq_t *commands, | ||
867 | struct sctp_association *asoc, | ||
868 | u8 state) | ||
869 | { | ||
870 | struct sctp_ulpevent *ev; | ||
871 | |||
872 | ev = sctp_ulpevent_make_assoc_change(asoc, 0, state, 0, | ||
873 | asoc->c.sinit_num_ostreams, | ||
874 | asoc->c.sinit_max_instreams, | ||
875 | NULL, GFP_ATOMIC); | ||
876 | if (ev) | ||
877 | sctp_ulpq_tail_event(&asoc->ulpq, ev); | ||
878 | } | ||
879 | |||
880 | /* Helper function to generate an adaptation indication event */ | ||
881 | static void sctp_cmd_adaptation_ind(sctp_cmd_seq_t *commands, | ||
882 | struct sctp_association *asoc) | ||
883 | { | ||
884 | struct sctp_ulpevent *ev; | ||
885 | |||
886 | ev = sctp_ulpevent_make_adaptation_indication(asoc, GFP_ATOMIC); | ||
887 | |||
888 | if (ev) | ||
889 | sctp_ulpq_tail_event(&asoc->ulpq, ev); | ||
890 | } | ||
891 | |||
865 | /* These three macros allow us to pull the debugging code out of the | 892 | /* These three macros allow us to pull the debugging code out of the |
866 | * main flow of sctp_do_sm() to keep attention focused on the real | 893 | * main flow of sctp_do_sm() to keep attention focused on the real |
867 | * functionality there. | 894 | * functionality there. |
@@ -1485,6 +1512,14 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1485 | case SCTP_CMD_SET_SK_ERR: | 1512 | case SCTP_CMD_SET_SK_ERR: |
1486 | sctp_cmd_set_sk_err(asoc, cmd->obj.error); | 1513 | sctp_cmd_set_sk_err(asoc, cmd->obj.error); |
1487 | break; | 1514 | break; |
1515 | case SCTP_CMD_ASSOC_CHANGE: | ||
1516 | sctp_cmd_assoc_change(commands, asoc, | ||
1517 | cmd->obj.u8); | ||
1518 | break; | ||
1519 | case SCTP_CMD_ADAPTATION_IND: | ||
1520 | sctp_cmd_adaptation_ind(commands, asoc); | ||
1521 | break; | ||
1522 | |||
1488 | default: | 1523 | default: |
1489 | printk(KERN_WARNING "Impossible command: %u, %p\n", | 1524 | printk(KERN_WARNING "Impossible command: %u, %p\n", |
1490 | cmd->verb, cmd->obj.ptr); | 1525 | cmd->verb, cmd->obj.ptr); |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 9e28a5d51200..f02ce3dddb7b 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -1656,7 +1656,6 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep, | |||
1656 | struct sctp_association *new_asoc) | 1656 | struct sctp_association *new_asoc) |
1657 | { | 1657 | { |
1658 | sctp_init_chunk_t *peer_init; | 1658 | sctp_init_chunk_t *peer_init; |
1659 | struct sctp_ulpevent *ev; | ||
1660 | struct sctp_chunk *repl; | 1659 | struct sctp_chunk *repl; |
1661 | 1660 | ||
1662 | /* new_asoc is a brand-new association, so these are not yet | 1661 | /* new_asoc is a brand-new association, so these are not yet |
@@ -1687,34 +1686,28 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep, | |||
1687 | * D) IMPLEMENTATION NOTE: An implementation may choose to | 1686 | * D) IMPLEMENTATION NOTE: An implementation may choose to |
1688 | * send the Communication Up notification to the SCTP user | 1687 | * send the Communication Up notification to the SCTP user |
1689 | * upon reception of a valid COOKIE ECHO chunk. | 1688 | * upon reception of a valid COOKIE ECHO chunk. |
1689 | * | ||
1690 | * Sadly, this needs to be implemented as a side-effect, because | ||
1691 | * we are not guaranteed to have set the association id of the real | ||
1692 | * association and so these notifications need to be delayed until | ||
1693 | * the association id is allocated. | ||
1690 | */ | 1694 | */ |
1691 | ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_COMM_UP, 0, | ||
1692 | new_asoc->c.sinit_num_ostreams, | ||
1693 | new_asoc->c.sinit_max_instreams, | ||
1694 | NULL, GFP_ATOMIC); | ||
1695 | if (!ev) | ||
1696 | goto nomem_ev; | ||
1697 | 1695 | ||
1698 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); | 1696 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_CHANGE, SCTP_U8(SCTP_COMM_UP)); |
1699 | 1697 | ||
1700 | /* Sockets API Draft Section 5.3.1.6 | 1698 | /* Sockets API Draft Section 5.3.1.6 |
1701 | * When a peer sends a Adaptation Layer Indication parameter , SCTP | 1699 | * When a peer sends a Adaptation Layer Indication parameter , SCTP |
1702 | * delivers this notification to inform the application that of the | 1700 | * delivers this notification to inform the application that of the |
1703 | * peers requested adaptation layer. | 1701 | * peers requested adaptation layer. |
1702 | * | ||
1703 | * This also needs to be done as a side effect for the same reason as | ||
1704 | * above. | ||
1704 | */ | 1705 | */ |
1705 | if (asoc->peer.adaptation_ind) { | 1706 | if (asoc->peer.adaptation_ind) |
1706 | ev = sctp_ulpevent_make_adaptation_indication(asoc, GFP_ATOMIC); | 1707 | sctp_add_cmd_sf(commands, SCTP_CMD_ADAPTATION_IND, SCTP_NULL()); |
1707 | if (!ev) | ||
1708 | goto nomem_ev; | ||
1709 | |||
1710 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, | ||
1711 | SCTP_ULPEVENT(ev)); | ||
1712 | } | ||
1713 | 1708 | ||
1714 | return SCTP_DISPOSITION_CONSUME; | 1709 | return SCTP_DISPOSITION_CONSUME; |
1715 | 1710 | ||
1716 | nomem_ev: | ||
1717 | sctp_chunk_free(repl); | ||
1718 | nomem: | 1711 | nomem: |
1719 | return SCTP_DISPOSITION_NOMEM; | 1712 | return SCTP_DISPOSITION_NOMEM; |
1720 | } | 1713 | } |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 2fc0a92caa78..9f1a908776de 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -972,6 +972,7 @@ static int __sctp_connect(struct sock* sk, | |||
972 | int walk_size = 0; | 972 | int walk_size = 0; |
973 | union sctp_addr *sa_addr; | 973 | union sctp_addr *sa_addr; |
974 | void *addr_buf; | 974 | void *addr_buf; |
975 | unsigned short port; | ||
975 | 976 | ||
976 | sp = sctp_sk(sk); | 977 | sp = sctp_sk(sk); |
977 | ep = sp->ep; | 978 | ep = sp->ep; |
@@ -992,6 +993,7 @@ static int __sctp_connect(struct sock* sk, | |||
992 | while (walk_size < addrs_size) { | 993 | while (walk_size < addrs_size) { |
993 | sa_addr = (union sctp_addr *)addr_buf; | 994 | sa_addr = (union sctp_addr *)addr_buf; |
994 | af = sctp_get_af_specific(sa_addr->sa.sa_family); | 995 | af = sctp_get_af_specific(sa_addr->sa.sa_family); |
996 | port = ntohs(sa_addr->v4.sin_port); | ||
995 | 997 | ||
996 | /* If the address family is not supported or if this address | 998 | /* If the address family is not supported or if this address |
997 | * causes the address buffer to overflow return EINVAL. | 999 | * causes the address buffer to overflow return EINVAL. |
@@ -1005,6 +1007,12 @@ static int __sctp_connect(struct sock* sk, | |||
1005 | if (err) | 1007 | if (err) |
1006 | goto out_free; | 1008 | goto out_free; |
1007 | 1009 | ||
1010 | /* Make sure the destination port is correctly set | ||
1011 | * in all addresses. | ||
1012 | */ | ||
1013 | if (asoc && asoc->peer.port && asoc->peer.port != port) | ||
1014 | goto out_free; | ||
1015 | |||
1008 | memcpy(&to, sa_addr, af->sockaddr_len); | 1016 | memcpy(&to, sa_addr, af->sockaddr_len); |
1009 | 1017 | ||
1010 | /* Check if there already is a matching association on the | 1018 | /* Check if there already is a matching association on the |
@@ -5012,7 +5020,8 @@ pp_found: | |||
5012 | struct hlist_node *node; | 5020 | struct hlist_node *node; |
5013 | 5021 | ||
5014 | SCTP_DEBUG_PRINTK("sctp_get_port() found a possible match\n"); | 5022 | SCTP_DEBUG_PRINTK("sctp_get_port() found a possible match\n"); |
5015 | if (pp->fastreuse && sk->sk_reuse) | 5023 | if (pp->fastreuse && sk->sk_reuse && |
5024 | sk->sk_state != SCTP_SS_LISTENING) | ||
5016 | goto success; | 5025 | goto success; |
5017 | 5026 | ||
5018 | /* Run through the list of sockets bound to the port | 5027 | /* Run through the list of sockets bound to the port |
@@ -5029,7 +5038,8 @@ pp_found: | |||
5029 | struct sctp_endpoint *ep2; | 5038 | struct sctp_endpoint *ep2; |
5030 | ep2 = sctp_sk(sk2)->ep; | 5039 | ep2 = sctp_sk(sk2)->ep; |
5031 | 5040 | ||
5032 | if (reuse && sk2->sk_reuse) | 5041 | if (reuse && sk2->sk_reuse && |
5042 | sk2->sk_state != SCTP_SS_LISTENING) | ||
5033 | continue; | 5043 | continue; |
5034 | 5044 | ||
5035 | if (sctp_bind_addr_match(&ep2->base.bind_addr, addr, | 5045 | if (sctp_bind_addr_match(&ep2->base.bind_addr, addr, |
@@ -5050,9 +5060,13 @@ pp_not_found: | |||
5050 | * if sk->sk_reuse is too (that is, if the caller requested | 5060 | * if sk->sk_reuse is too (that is, if the caller requested |
5051 | * SO_REUSEADDR on this socket -sk-). | 5061 | * SO_REUSEADDR on this socket -sk-). |
5052 | */ | 5062 | */ |
5053 | if (hlist_empty(&pp->owner)) | 5063 | if (hlist_empty(&pp->owner)) { |
5054 | pp->fastreuse = sk->sk_reuse ? 1 : 0; | 5064 | if (sk->sk_reuse && sk->sk_state != SCTP_SS_LISTENING) |
5055 | else if (pp->fastreuse && !sk->sk_reuse) | 5065 | pp->fastreuse = 1; |
5066 | else | ||
5067 | pp->fastreuse = 0; | ||
5068 | } else if (pp->fastreuse && | ||
5069 | (!sk->sk_reuse || sk->sk_state == SCTP_SS_LISTENING)) | ||
5056 | pp->fastreuse = 0; | 5070 | pp->fastreuse = 0; |
5057 | 5071 | ||
5058 | /* We are set, so fill up all the data in the hash table | 5072 | /* We are set, so fill up all the data in the hash table |
@@ -5060,8 +5074,8 @@ pp_not_found: | |||
5060 | * sockets FIXME: Blurry, NPI (ipg). | 5074 | * sockets FIXME: Blurry, NPI (ipg). |
5061 | */ | 5075 | */ |
5062 | success: | 5076 | success: |
5063 | inet_sk(sk)->num = snum; | ||
5064 | if (!sctp_sk(sk)->bind_hash) { | 5077 | if (!sctp_sk(sk)->bind_hash) { |
5078 | inet_sk(sk)->num = snum; | ||
5065 | sk_add_bind_node(sk, &pp->owner); | 5079 | sk_add_bind_node(sk, &pp->owner); |
5066 | sctp_sk(sk)->bind_hash = pp; | 5080 | sctp_sk(sk)->bind_hash = pp; |
5067 | } | 5081 | } |
@@ -5134,12 +5148,16 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) | |||
5134 | * This is not currently spelled out in the SCTP sockets | 5148 | * This is not currently spelled out in the SCTP sockets |
5135 | * extensions draft, but follows the practice as seen in TCP | 5149 | * extensions draft, but follows the practice as seen in TCP |
5136 | * sockets. | 5150 | * sockets. |
5151 | * | ||
5152 | * Additionally, turn off fastreuse flag since we are not listening | ||
5137 | */ | 5153 | */ |
5154 | sk->sk_state = SCTP_SS_LISTENING; | ||
5138 | if (!ep->base.bind_addr.port) { | 5155 | if (!ep->base.bind_addr.port) { |
5139 | if (sctp_autobind(sk)) | 5156 | if (sctp_autobind(sk)) |
5140 | return -EAGAIN; | 5157 | return -EAGAIN; |
5141 | } | 5158 | } else |
5142 | sk->sk_state = SCTP_SS_LISTENING; | 5159 | sctp_sk(sk)->bind_hash->fastreuse = 0; |
5160 | |||
5143 | sctp_hash_endpoint(ep); | 5161 | sctp_hash_endpoint(ep); |
5144 | return 0; | 5162 | return 0; |
5145 | } | 5163 | } |
@@ -5177,11 +5195,13 @@ SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog) | |||
5177 | * extensions draft, but follows the practice as seen in TCP | 5195 | * extensions draft, but follows the practice as seen in TCP |
5178 | * sockets. | 5196 | * sockets. |
5179 | */ | 5197 | */ |
5198 | sk->sk_state = SCTP_SS_LISTENING; | ||
5180 | if (!ep->base.bind_addr.port) { | 5199 | if (!ep->base.bind_addr.port) { |
5181 | if (sctp_autobind(sk)) | 5200 | if (sctp_autobind(sk)) |
5182 | return -EAGAIN; | 5201 | return -EAGAIN; |
5183 | } | 5202 | } else |
5184 | sk->sk_state = SCTP_SS_LISTENING; | 5203 | sctp_sk(sk)->bind_hash->fastreuse = 0; |
5204 | |||
5185 | sk->sk_max_ack_backlog = backlog; | 5205 | sk->sk_max_ack_backlog = backlog; |
5186 | sctp_hash_endpoint(ep); | 5206 | sctp_hash_endpoint(ep); |
5187 | return 0; | 5207 | return 0; |