aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/protocol.c
diff options
context:
space:
mode:
authorSridhar Samudrala <sri@us.ibm.com>2007-05-04 16:36:30 -0400
committerDavid S. Miller <davem@davemloft.net>2007-05-04 16:36:30 -0400
commit827bf12236fbafc02bc899aec1b37c342c8cf4e5 (patch)
tree41101b0d866629b3cc3341712996f11e655f6250 /net/sctp/protocol.c
parentce5325c1338acf965f4300f4976eac2129aeb439 (diff)
[SCTP]: Re-order SCTP initializations to avoid race with sctp_rcv()
Signed-off-by: Sridhar Samudrala <sri@us.ibm.com> Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/protocol.c')
-rw-r--r--net/sctp/protocol.c79
1 files changed, 47 insertions, 32 deletions
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index d4afafc39138..34bab36637ac 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -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;
1177out: 1181out:
1178 return status; 1182 return status;
1183err_v6_add_protocol:
1184 inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
1185 unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
1186err_add_protocol:
1187 sctp_free_local_addr_list();
1188 sock_release(sctp_ctl_socket);
1179err_ctl_sock_init: 1189err_ctl_sock_init:
1180 sctp_v6_exit(); 1190 sctp_v6_exit();
1181err_v6_init: 1191err_v6_init:
1192 inet_unregister_protosw(&sctp_stream_protosw);
1193 inet_unregister_protosw(&sctp_seqpacket_protosw);
1194 proto_unregister(&sctp_prot);
1195err_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)));
1193err_ahash_alloc: 1207err_ahash_alloc:
1194 sctp_dbg_objcnt_exit(); 1208 sctp_dbg_objcnt_exit();
1195err_init_proc:
1196 sctp_proc_exit(); 1209 sctp_proc_exit();
1210err_init_proc:
1197 cleanup_sctp_mibs(); 1211 cleanup_sctp_mibs();
1198err_init_mibs: 1212err_init_mibs:
1199 kmem_cache_destroy(sctp_chunk_cachep); 1213 kmem_cache_destroy(sctp_chunk_cachep);
1200err_chunk_cachep: 1214err_chunk_cachep:
1201 kmem_cache_destroy(sctp_bucket_cachep); 1215 kmem_cache_destroy(sctp_bucket_cachep);
1202err_bucket_cachep:
1203 inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
1204 inet_unregister_protosw(&sctp_seqpacket_protosw);
1205 inet_unregister_protosw(&sctp_stream_protosw);
1206err_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