diff options
Diffstat (limited to 'net/sctp/protocol.c')
| -rw-r--r-- | net/sctp/protocol.c | 129 |
1 files changed, 84 insertions, 45 deletions
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 25be8f04de6e..beea2fb18b15 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
| @@ -995,6 +995,58 @@ static void cleanup_sctp_mibs(void) | |||
| 995 | free_percpu(sctp_statistics[1]); | 995 | free_percpu(sctp_statistics[1]); |
| 996 | } | 996 | } |
| 997 | 997 | ||
| 998 | static void sctp_v4_pf_init(void) | ||
| 999 | { | ||
| 1000 | /* Initialize the SCTP specific PF functions. */ | ||
| 1001 | sctp_register_pf(&sctp_pf_inet, PF_INET); | ||
| 1002 | sctp_register_af(&sctp_af_inet); | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | static void sctp_v4_pf_exit(void) | ||
| 1006 | { | ||
| 1007 | list_del(&sctp_af_inet.list); | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | static int sctp_v4_protosw_init(void) | ||
| 1011 | { | ||
| 1012 | int rc; | ||
| 1013 | |||
| 1014 | rc = proto_register(&sctp_prot, 1); | ||
| 1015 | if (rc) | ||
| 1016 | return rc; | ||
| 1017 | |||
| 1018 | /* Register SCTP(UDP and TCP style) with socket layer. */ | ||
| 1019 | inet_register_protosw(&sctp_seqpacket_protosw); | ||
| 1020 | inet_register_protosw(&sctp_stream_protosw); | ||
| 1021 | |||
| 1022 | return 0; | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | static void sctp_v4_protosw_exit(void) | ||
| 1026 | { | ||
| 1027 | inet_unregister_protosw(&sctp_stream_protosw); | ||
| 1028 | inet_unregister_protosw(&sctp_seqpacket_protosw); | ||
| 1029 | proto_unregister(&sctp_prot); | ||
| 1030 | } | ||
| 1031 | |||
| 1032 | static int sctp_v4_add_protocol(void) | ||
| 1033 | { | ||
| 1034 | /* Register notifier for inet address additions/deletions. */ | ||
| 1035 | register_inetaddr_notifier(&sctp_inetaddr_notifier); | ||
| 1036 | |||
| 1037 | /* Register SCTP with inet layer. */ | ||
| 1038 | if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0) | ||
| 1039 | return -EAGAIN; | ||
| 1040 | |||
| 1041 | return 0; | ||
| 1042 | } | ||
| 1043 | |||
| 1044 | static void sctp_v4_del_protocol(void) | ||
| 1045 | { | ||
| 1046 | inet_del_protocol(&sctp_protocol, IPPROTO_SCTP); | ||
| 1047 | unregister_inetaddr_notifier(&sctp_inetaddr_notifier); | ||
| 1048 | } | ||
| 1049 | |||
| 998 | /* Initialize the universe into something sensible. */ | 1050 | /* Initialize the universe into something sensible. */ |
| 999 | SCTP_STATIC __init int sctp_init(void) | 1051 | SCTP_STATIC __init int sctp_init(void) |
| 1000 | { | 1052 | { |
| @@ -1038,8 +1090,6 @@ SCTP_STATIC __init int sctp_init(void) | |||
| 1038 | /* Initialize object count debugging. */ | 1090 | /* Initialize object count debugging. */ |
| 1039 | sctp_dbg_objcnt_init(); | 1091 | sctp_dbg_objcnt_init(); |
| 1040 | 1092 | ||
| 1041 | /* Initialize the SCTP specific PF functions. */ | ||
| 1042 | sctp_register_pf(&sctp_pf_inet, PF_INET); | ||
| 1043 | /* | 1093 | /* |
| 1044 | * 14. Suggested SCTP Protocol Parameter Values | 1094 | * 14. Suggested SCTP Protocol Parameter Values |
| 1045 | */ | 1095 | */ |
| @@ -1197,19 +1247,22 @@ SCTP_STATIC __init int sctp_init(void) | |||
| 1197 | sctp_sysctl_register(); | 1247 | sctp_sysctl_register(); |
| 1198 | 1248 | ||
| 1199 | INIT_LIST_HEAD(&sctp_address_families); | 1249 | INIT_LIST_HEAD(&sctp_address_families); |
| 1200 | sctp_register_af(&sctp_af_inet); | 1250 | sctp_v4_pf_init(); |
| 1251 | sctp_v6_pf_init(); | ||
| 1201 | 1252 | ||
| 1202 | status = proto_register(&sctp_prot, 1); | 1253 | /* Initialize the local address list. */ |
| 1203 | if (status) | 1254 | INIT_LIST_HEAD(&sctp_local_addr_list); |
| 1204 | goto err_proto_register; | 1255 | spin_lock_init(&sctp_local_addr_lock); |
| 1256 | sctp_get_local_addr_list(); | ||
| 1205 | 1257 | ||
| 1206 | /* Register SCTP(UDP and TCP style) with socket layer. */ | 1258 | status = sctp_v4_protosw_init(); |
| 1207 | inet_register_protosw(&sctp_seqpacket_protosw); | ||
| 1208 | inet_register_protosw(&sctp_stream_protosw); | ||
| 1209 | 1259 | ||
| 1210 | status = sctp_v6_init(); | ||
| 1211 | if (status) | 1260 | if (status) |
| 1212 | goto err_v6_init; | 1261 | goto err_protosw_init; |
| 1262 | |||
| 1263 | status = sctp_v6_protosw_init(); | ||
| 1264 | if (status) | ||
| 1265 | goto err_v6_protosw_init; | ||
| 1213 | 1266 | ||
| 1214 | /* Initialize the control inode/socket for handling OOTB packets. */ | 1267 | /* Initialize the control inode/socket for handling OOTB packets. */ |
| 1215 | if ((status = sctp_ctl_sock_init())) { | 1268 | if ((status = sctp_ctl_sock_init())) { |
| @@ -1218,19 +1271,9 @@ SCTP_STATIC __init int sctp_init(void) | |||
| 1218 | goto err_ctl_sock_init; | 1271 | goto err_ctl_sock_init; |
| 1219 | } | 1272 | } |
| 1220 | 1273 | ||
| 1221 | /* Initialize the local address list. */ | 1274 | status = sctp_v4_add_protocol(); |
| 1222 | INIT_LIST_HEAD(&sctp_local_addr_list); | 1275 | if (status) |
| 1223 | spin_lock_init(&sctp_local_addr_lock); | ||
| 1224 | sctp_get_local_addr_list(); | ||
| 1225 | |||
| 1226 | /* Register notifier for inet address additions/deletions. */ | ||
| 1227 | register_inetaddr_notifier(&sctp_inetaddr_notifier); | ||
| 1228 | |||
| 1229 | /* Register SCTP with inet layer. */ | ||
| 1230 | if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0) { | ||
| 1231 | status = -EAGAIN; | ||
| 1232 | goto err_add_protocol; | 1276 | goto err_add_protocol; |
| 1233 | } | ||
| 1234 | 1277 | ||
| 1235 | /* Register SCTP with inet6 layer. */ | 1278 | /* Register SCTP with inet6 layer. */ |
| 1236 | status = sctp_v6_add_protocol(); | 1279 | status = sctp_v6_add_protocol(); |
| @@ -1241,18 +1284,18 @@ SCTP_STATIC __init int sctp_init(void) | |||
| 1241 | out: | 1284 | out: |
| 1242 | return status; | 1285 | return status; |
| 1243 | err_v6_add_protocol: | 1286 | err_v6_add_protocol: |
| 1244 | inet_del_protocol(&sctp_protocol, IPPROTO_SCTP); | 1287 | sctp_v6_del_protocol(); |
| 1245 | unregister_inetaddr_notifier(&sctp_inetaddr_notifier); | ||
| 1246 | err_add_protocol: | 1288 | err_add_protocol: |
| 1247 | sctp_free_local_addr_list(); | 1289 | sctp_v4_del_protocol(); |
| 1248 | sock_release(sctp_ctl_socket); | 1290 | sock_release(sctp_ctl_socket); |
| 1249 | err_ctl_sock_init: | 1291 | err_ctl_sock_init: |
| 1250 | sctp_v6_exit(); | 1292 | sctp_v6_protosw_exit(); |
| 1251 | err_v6_init: | 1293 | err_v6_protosw_init: |
| 1252 | inet_unregister_protosw(&sctp_stream_protosw); | 1294 | sctp_v4_protosw_exit(); |
| 1253 | inet_unregister_protosw(&sctp_seqpacket_protosw); | 1295 | err_protosw_init: |
| 1254 | proto_unregister(&sctp_prot); | 1296 | sctp_free_local_addr_list(); |
| 1255 | err_proto_register: | 1297 | sctp_v4_pf_exit(); |
| 1298 | sctp_v6_pf_exit(); | ||
| 1256 | sctp_sysctl_unregister(); | 1299 | sctp_sysctl_unregister(); |
| 1257 | list_del(&sctp_af_inet.list); | 1300 | list_del(&sctp_af_inet.list); |
| 1258 | free_pages((unsigned long)sctp_port_hashtable, | 1301 | free_pages((unsigned long)sctp_port_hashtable, |
| @@ -1285,23 +1328,21 @@ SCTP_STATIC __exit void sctp_exit(void) | |||
| 1285 | 1328 | ||
| 1286 | /* Unregister with inet6/inet layers. */ | 1329 | /* Unregister with inet6/inet layers. */ |
| 1287 | sctp_v6_del_protocol(); | 1330 | sctp_v6_del_protocol(); |
| 1288 | inet_del_protocol(&sctp_protocol, IPPROTO_SCTP); | 1331 | sctp_v4_del_protocol(); |
| 1289 | |||
| 1290 | /* Unregister notifier for inet address additions/deletions. */ | ||
| 1291 | unregister_inetaddr_notifier(&sctp_inetaddr_notifier); | ||
| 1292 | |||
| 1293 | /* Free the local address list. */ | ||
| 1294 | sctp_free_local_addr_list(); | ||
| 1295 | 1332 | ||
| 1296 | /* Free the control endpoint. */ | 1333 | /* Free the control endpoint. */ |
| 1297 | sock_release(sctp_ctl_socket); | 1334 | sock_release(sctp_ctl_socket); |
| 1298 | 1335 | ||
| 1299 | /* Cleanup v6 initializations. */ | 1336 | /* Free protosw registrations */ |
| 1300 | sctp_v6_exit(); | 1337 | sctp_v6_protosw_exit(); |
| 1338 | sctp_v4_protosw_exit(); | ||
| 1339 | |||
| 1340 | /* Free the local address list. */ | ||
| 1341 | sctp_free_local_addr_list(); | ||
| 1301 | 1342 | ||
| 1302 | /* Unregister with socket layer. */ | 1343 | /* Unregister with socket layer. */ |
| 1303 | inet_unregister_protosw(&sctp_stream_protosw); | 1344 | sctp_v6_pf_exit(); |
| 1304 | inet_unregister_protosw(&sctp_seqpacket_protosw); | 1345 | sctp_v4_pf_exit(); |
| 1305 | 1346 | ||
| 1306 | sctp_sysctl_unregister(); | 1347 | sctp_sysctl_unregister(); |
| 1307 | list_del(&sctp_af_inet.list); | 1348 | list_del(&sctp_af_inet.list); |
| @@ -1320,8 +1361,6 @@ SCTP_STATIC __exit void sctp_exit(void) | |||
| 1320 | 1361 | ||
| 1321 | kmem_cache_destroy(sctp_chunk_cachep); | 1362 | kmem_cache_destroy(sctp_chunk_cachep); |
| 1322 | kmem_cache_destroy(sctp_bucket_cachep); | 1363 | kmem_cache_destroy(sctp_bucket_cachep); |
| 1323 | |||
| 1324 | proto_unregister(&sctp_prot); | ||
| 1325 | } | 1364 | } |
| 1326 | 1365 | ||
| 1327 | module_init(sctp_init); | 1366 | module_init(sctp_init); |
