diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2012-08-06 04:42:04 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-08-15 02:12:17 -0400 |
commit | 4db67e808640e3934d82ce61ee8e2e89fd877ba8 (patch) | |
tree | ff02e330187c41970c75f6d8a6275e1cc25165f0 /net/sctp/protocol.c | |
parent | 4110cc255ddec59c79fba4d71cdd948d0a382140 (diff) |
sctp: Make the address lists per network namespace
- Move the address lists into struct net
- Add per network namespace initialization and cleanup
- Pass around struct net so it is everywhere I need it.
- Rename all of the global variable references into references
to the variables moved into struct net
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Acked-by: Vlad Yasevich <vyasevich@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/protocol.c')
-rw-r--r-- | net/sctp/protocol.c | 143 |
1 files changed, 82 insertions, 61 deletions
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 1f89c4e69645..7025d96bae5f 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -201,29 +201,29 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist, | |||
201 | /* Extract our IP addresses from the system and stash them in the | 201 | /* Extract our IP addresses from the system and stash them in the |
202 | * protocol structure. | 202 | * protocol structure. |
203 | */ | 203 | */ |
204 | static void sctp_get_local_addr_list(void) | 204 | static void sctp_get_local_addr_list(struct net *net) |
205 | { | 205 | { |
206 | struct net_device *dev; | 206 | struct net_device *dev; |
207 | struct list_head *pos; | 207 | struct list_head *pos; |
208 | struct sctp_af *af; | 208 | struct sctp_af *af; |
209 | 209 | ||
210 | rcu_read_lock(); | 210 | rcu_read_lock(); |
211 | for_each_netdev_rcu(&init_net, dev) { | 211 | for_each_netdev_rcu(net, dev) { |
212 | __list_for_each(pos, &sctp_address_families) { | 212 | __list_for_each(pos, &sctp_address_families) { |
213 | af = list_entry(pos, struct sctp_af, list); | 213 | af = list_entry(pos, struct sctp_af, list); |
214 | af->copy_addrlist(&sctp_local_addr_list, dev); | 214 | af->copy_addrlist(&net->sctp.local_addr_list, dev); |
215 | } | 215 | } |
216 | } | 216 | } |
217 | rcu_read_unlock(); | 217 | rcu_read_unlock(); |
218 | } | 218 | } |
219 | 219 | ||
220 | /* Free the existing local addresses. */ | 220 | /* Free the existing local addresses. */ |
221 | static void sctp_free_local_addr_list(void) | 221 | static void sctp_free_local_addr_list(struct net *net) |
222 | { | 222 | { |
223 | struct sctp_sockaddr_entry *addr; | 223 | struct sctp_sockaddr_entry *addr; |
224 | struct list_head *pos, *temp; | 224 | struct list_head *pos, *temp; |
225 | 225 | ||
226 | list_for_each_safe(pos, temp, &sctp_local_addr_list) { | 226 | list_for_each_safe(pos, temp, &net->sctp.local_addr_list) { |
227 | addr = list_entry(pos, struct sctp_sockaddr_entry, list); | 227 | addr = list_entry(pos, struct sctp_sockaddr_entry, list); |
228 | list_del(pos); | 228 | list_del(pos); |
229 | kfree(addr); | 229 | kfree(addr); |
@@ -231,14 +231,14 @@ static void sctp_free_local_addr_list(void) | |||
231 | } | 231 | } |
232 | 232 | ||
233 | /* Copy the local addresses which are valid for 'scope' into 'bp'. */ | 233 | /* Copy the local addresses which are valid for 'scope' into 'bp'. */ |
234 | int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope, | 234 | int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp, |
235 | gfp_t gfp, int copy_flags) | 235 | sctp_scope_t scope, gfp_t gfp, int copy_flags) |
236 | { | 236 | { |
237 | struct sctp_sockaddr_entry *addr; | 237 | struct sctp_sockaddr_entry *addr; |
238 | int error = 0; | 238 | int error = 0; |
239 | 239 | ||
240 | rcu_read_lock(); | 240 | rcu_read_lock(); |
241 | list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) { | 241 | list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) { |
242 | if (!addr->valid) | 242 | if (!addr->valid) |
243 | continue; | 243 | continue; |
244 | if (sctp_in_scope(&addr->a, scope)) { | 244 | if (sctp_in_scope(&addr->a, scope)) { |
@@ -627,14 +627,15 @@ static void sctp_v4_ecn_capable(struct sock *sk) | |||
627 | 627 | ||
628 | void sctp_addr_wq_timeout_handler(unsigned long arg) | 628 | void sctp_addr_wq_timeout_handler(unsigned long arg) |
629 | { | 629 | { |
630 | struct net *net = (struct net *)arg; | ||
630 | struct sctp_sockaddr_entry *addrw, *temp; | 631 | struct sctp_sockaddr_entry *addrw, *temp; |
631 | struct sctp_sock *sp; | 632 | struct sctp_sock *sp; |
632 | 633 | ||
633 | spin_lock_bh(&sctp_addr_wq_lock); | 634 | spin_lock_bh(&net->sctp.addr_wq_lock); |
634 | 635 | ||
635 | list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) { | 636 | list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) { |
636 | SCTP_DEBUG_PRINTK_IPADDR("sctp_addrwq_timo_handler: the first ent in wq %p is ", | 637 | SCTP_DEBUG_PRINTK_IPADDR("sctp_addrwq_timo_handler: the first ent in wq %p is ", |
637 | " for cmd %d at entry %p\n", &sctp_addr_waitq, &addrw->a, addrw->state, | 638 | " for cmd %d at entry %p\n", &net->sctp.addr_waitq, &addrw->a, addrw->state, |
638 | addrw); | 639 | addrw); |
639 | 640 | ||
640 | #if IS_ENABLED(CONFIG_IPV6) | 641 | #if IS_ENABLED(CONFIG_IPV6) |
@@ -648,7 +649,7 @@ void sctp_addr_wq_timeout_handler(unsigned long arg) | |||
648 | goto free_next; | 649 | goto free_next; |
649 | 650 | ||
650 | in6 = (struct in6_addr *)&addrw->a.v6.sin6_addr; | 651 | in6 = (struct in6_addr *)&addrw->a.v6.sin6_addr; |
651 | if (ipv6_chk_addr(&init_net, in6, NULL, 0) == 0 && | 652 | if (ipv6_chk_addr(net, in6, NULL, 0) == 0 && |
652 | addrw->state == SCTP_ADDR_NEW) { | 653 | addrw->state == SCTP_ADDR_NEW) { |
653 | unsigned long timeo_val; | 654 | unsigned long timeo_val; |
654 | 655 | ||
@@ -656,12 +657,12 @@ void sctp_addr_wq_timeout_handler(unsigned long arg) | |||
656 | SCTP_ADDRESS_TICK_DELAY); | 657 | SCTP_ADDRESS_TICK_DELAY); |
657 | timeo_val = jiffies; | 658 | timeo_val = jiffies; |
658 | timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY); | 659 | timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY); |
659 | mod_timer(&sctp_addr_wq_timer, timeo_val); | 660 | mod_timer(&net->sctp.addr_wq_timer, timeo_val); |
660 | break; | 661 | break; |
661 | } | 662 | } |
662 | } | 663 | } |
663 | #endif | 664 | #endif |
664 | list_for_each_entry(sp, &sctp_auto_asconf_splist, auto_asconf_list) { | 665 | list_for_each_entry(sp, &net->sctp.auto_asconf_splist, auto_asconf_list) { |
665 | struct sock *sk; | 666 | struct sock *sk; |
666 | 667 | ||
667 | sk = sctp_opt2sk(sp); | 668 | sk = sctp_opt2sk(sp); |
@@ -679,31 +680,32 @@ free_next: | |||
679 | list_del(&addrw->list); | 680 | list_del(&addrw->list); |
680 | kfree(addrw); | 681 | kfree(addrw); |
681 | } | 682 | } |
682 | spin_unlock_bh(&sctp_addr_wq_lock); | 683 | spin_unlock_bh(&net->sctp.addr_wq_lock); |
683 | } | 684 | } |
684 | 685 | ||
685 | static void sctp_free_addr_wq(void) | 686 | static void sctp_free_addr_wq(struct net *net) |
686 | { | 687 | { |
687 | struct sctp_sockaddr_entry *addrw; | 688 | struct sctp_sockaddr_entry *addrw; |
688 | struct sctp_sockaddr_entry *temp; | 689 | struct sctp_sockaddr_entry *temp; |
689 | 690 | ||
690 | spin_lock_bh(&sctp_addr_wq_lock); | 691 | spin_lock_bh(&net->sctp.addr_wq_lock); |
691 | del_timer(&sctp_addr_wq_timer); | 692 | del_timer(&net->sctp.addr_wq_timer); |
692 | list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) { | 693 | list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) { |
693 | list_del(&addrw->list); | 694 | list_del(&addrw->list); |
694 | kfree(addrw); | 695 | kfree(addrw); |
695 | } | 696 | } |
696 | spin_unlock_bh(&sctp_addr_wq_lock); | 697 | spin_unlock_bh(&net->sctp.addr_wq_lock); |
697 | } | 698 | } |
698 | 699 | ||
699 | /* lookup the entry for the same address in the addr_waitq | 700 | /* lookup the entry for the same address in the addr_waitq |
700 | * sctp_addr_wq MUST be locked | 701 | * sctp_addr_wq MUST be locked |
701 | */ | 702 | */ |
702 | static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct sctp_sockaddr_entry *addr) | 703 | static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct net *net, |
704 | struct sctp_sockaddr_entry *addr) | ||
703 | { | 705 | { |
704 | struct sctp_sockaddr_entry *addrw; | 706 | struct sctp_sockaddr_entry *addrw; |
705 | 707 | ||
706 | list_for_each_entry(addrw, &sctp_addr_waitq, list) { | 708 | list_for_each_entry(addrw, &net->sctp.addr_waitq, list) { |
707 | if (addrw->a.sa.sa_family != addr->a.sa.sa_family) | 709 | if (addrw->a.sa.sa_family != addr->a.sa.sa_family) |
708 | continue; | 710 | continue; |
709 | if (addrw->a.sa.sa_family == AF_INET) { | 711 | if (addrw->a.sa.sa_family == AF_INET) { |
@@ -719,7 +721,7 @@ static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct sctp_sockaddr_entr | |||
719 | return NULL; | 721 | return NULL; |
720 | } | 722 | } |
721 | 723 | ||
722 | void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd) | 724 | void sctp_addr_wq_mgmt(struct net *net, struct sctp_sockaddr_entry *addr, int cmd) |
723 | { | 725 | { |
724 | struct sctp_sockaddr_entry *addrw; | 726 | struct sctp_sockaddr_entry *addrw; |
725 | unsigned long timeo_val; | 727 | unsigned long timeo_val; |
@@ -730,38 +732,38 @@ void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd) | |||
730 | * new address after a couple of addition and deletion of that address | 732 | * new address after a couple of addition and deletion of that address |
731 | */ | 733 | */ |
732 | 734 | ||
733 | spin_lock_bh(&sctp_addr_wq_lock); | 735 | spin_lock_bh(&net->sctp.addr_wq_lock); |
734 | /* Offsets existing events in addr_wq */ | 736 | /* Offsets existing events in addr_wq */ |
735 | addrw = sctp_addr_wq_lookup(addr); | 737 | addrw = sctp_addr_wq_lookup(net, addr); |
736 | if (addrw) { | 738 | if (addrw) { |
737 | if (addrw->state != cmd) { | 739 | if (addrw->state != cmd) { |
738 | SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt offsets existing entry for %d ", | 740 | SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt offsets existing entry for %d ", |
739 | " in wq %p\n", addrw->state, &addrw->a, | 741 | " in wq %p\n", addrw->state, &addrw->a, |
740 | &sctp_addr_waitq); | 742 | &net->sctp.addr_waitq); |
741 | list_del(&addrw->list); | 743 | list_del(&addrw->list); |
742 | kfree(addrw); | 744 | kfree(addrw); |
743 | } | 745 | } |
744 | spin_unlock_bh(&sctp_addr_wq_lock); | 746 | spin_unlock_bh(&net->sctp.addr_wq_lock); |
745 | return; | 747 | return; |
746 | } | 748 | } |
747 | 749 | ||
748 | /* OK, we have to add the new address to the wait queue */ | 750 | /* OK, we have to add the new address to the wait queue */ |
749 | addrw = kmemdup(addr, sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC); | 751 | addrw = kmemdup(addr, sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC); |
750 | if (addrw == NULL) { | 752 | if (addrw == NULL) { |
751 | spin_unlock_bh(&sctp_addr_wq_lock); | 753 | spin_unlock_bh(&net->sctp.addr_wq_lock); |
752 | return; | 754 | return; |
753 | } | 755 | } |
754 | addrw->state = cmd; | 756 | addrw->state = cmd; |
755 | list_add_tail(&addrw->list, &sctp_addr_waitq); | 757 | list_add_tail(&addrw->list, &net->sctp.addr_waitq); |
756 | SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt add new entry for cmd:%d ", | 758 | SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt add new entry for cmd:%d ", |
757 | " in wq %p\n", addrw->state, &addrw->a, &sctp_addr_waitq); | 759 | " in wq %p\n", addrw->state, &addrw->a, &net->sctp.addr_waitq); |
758 | 760 | ||
759 | if (!timer_pending(&sctp_addr_wq_timer)) { | 761 | if (!timer_pending(&net->sctp.addr_wq_timer)) { |
760 | timeo_val = jiffies; | 762 | timeo_val = jiffies; |
761 | timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY); | 763 | timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY); |
762 | mod_timer(&sctp_addr_wq_timer, timeo_val); | 764 | mod_timer(&net->sctp.addr_wq_timer, timeo_val); |
763 | } | 765 | } |
764 | spin_unlock_bh(&sctp_addr_wq_lock); | 766 | spin_unlock_bh(&net->sctp.addr_wq_lock); |
765 | } | 767 | } |
766 | 768 | ||
767 | /* Event handler for inet address addition/deletion events. | 769 | /* Event handler for inet address addition/deletion events. |
@@ -776,11 +778,9 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, | |||
776 | struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; | 778 | struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; |
777 | struct sctp_sockaddr_entry *addr = NULL; | 779 | struct sctp_sockaddr_entry *addr = NULL; |
778 | struct sctp_sockaddr_entry *temp; | 780 | struct sctp_sockaddr_entry *temp; |
781 | struct net *net = dev_net(ifa->ifa_dev->dev); | ||
779 | int found = 0; | 782 | int found = 0; |
780 | 783 | ||
781 | if (!net_eq(dev_net(ifa->ifa_dev->dev), &init_net)) | ||
782 | return NOTIFY_DONE; | ||
783 | |||
784 | switch (ev) { | 784 | switch (ev) { |
785 | case NETDEV_UP: | 785 | case NETDEV_UP: |
786 | addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC); | 786 | addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC); |
@@ -789,27 +789,27 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, | |||
789 | addr->a.v4.sin_port = 0; | 789 | addr->a.v4.sin_port = 0; |
790 | addr->a.v4.sin_addr.s_addr = ifa->ifa_local; | 790 | addr->a.v4.sin_addr.s_addr = ifa->ifa_local; |
791 | addr->valid = 1; | 791 | addr->valid = 1; |
792 | spin_lock_bh(&sctp_local_addr_lock); | 792 | spin_lock_bh(&net->sctp.local_addr_lock); |
793 | list_add_tail_rcu(&addr->list, &sctp_local_addr_list); | 793 | list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list); |
794 | sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW); | 794 | sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW); |
795 | spin_unlock_bh(&sctp_local_addr_lock); | 795 | spin_unlock_bh(&net->sctp.local_addr_lock); |
796 | } | 796 | } |
797 | break; | 797 | break; |
798 | case NETDEV_DOWN: | 798 | case NETDEV_DOWN: |
799 | spin_lock_bh(&sctp_local_addr_lock); | 799 | spin_lock_bh(&net->sctp.local_addr_lock); |
800 | list_for_each_entry_safe(addr, temp, | 800 | list_for_each_entry_safe(addr, temp, |
801 | &sctp_local_addr_list, list) { | 801 | &net->sctp.local_addr_list, list) { |
802 | if (addr->a.sa.sa_family == AF_INET && | 802 | if (addr->a.sa.sa_family == AF_INET && |
803 | addr->a.v4.sin_addr.s_addr == | 803 | addr->a.v4.sin_addr.s_addr == |
804 | ifa->ifa_local) { | 804 | ifa->ifa_local) { |
805 | sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL); | 805 | sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL); |
806 | found = 1; | 806 | found = 1; |
807 | addr->valid = 0; | 807 | addr->valid = 0; |
808 | list_del_rcu(&addr->list); | 808 | list_del_rcu(&addr->list); |
809 | break; | 809 | break; |
810 | } | 810 | } |
811 | } | 811 | } |
812 | spin_unlock_bh(&sctp_local_addr_lock); | 812 | spin_unlock_bh(&net->sctp.local_addr_lock); |
813 | if (found) | 813 | if (found) |
814 | kfree_rcu(addr, rcu); | 814 | kfree_rcu(addr, rcu); |
815 | break; | 815 | break; |
@@ -1194,6 +1194,36 @@ static void sctp_v4_del_protocol(void) | |||
1194 | unregister_inetaddr_notifier(&sctp_inetaddr_notifier); | 1194 | unregister_inetaddr_notifier(&sctp_inetaddr_notifier); |
1195 | } | 1195 | } |
1196 | 1196 | ||
1197 | static int sctp_net_init(struct net *net) | ||
1198 | { | ||
1199 | /* Initialize the local address list. */ | ||
1200 | INIT_LIST_HEAD(&net->sctp.local_addr_list); | ||
1201 | spin_lock_init(&net->sctp.local_addr_lock); | ||
1202 | sctp_get_local_addr_list(net); | ||
1203 | |||
1204 | /* Initialize the address event list */ | ||
1205 | INIT_LIST_HEAD(&net->sctp.addr_waitq); | ||
1206 | INIT_LIST_HEAD(&net->sctp.auto_asconf_splist); | ||
1207 | spin_lock_init(&net->sctp.addr_wq_lock); | ||
1208 | net->sctp.addr_wq_timer.expires = 0; | ||
1209 | setup_timer(&net->sctp.addr_wq_timer, sctp_addr_wq_timeout_handler, | ||
1210 | (unsigned long)net); | ||
1211 | |||
1212 | return 0; | ||
1213 | } | ||
1214 | |||
1215 | static void sctp_net_exit(struct net *net) | ||
1216 | { | ||
1217 | /* Free the local address list */ | ||
1218 | sctp_free_addr_wq(net); | ||
1219 | sctp_free_local_addr_list(net); | ||
1220 | } | ||
1221 | |||
1222 | static struct pernet_operations sctp_net_ops = { | ||
1223 | .init = sctp_net_init, | ||
1224 | .exit = sctp_net_exit, | ||
1225 | }; | ||
1226 | |||
1197 | /* Initialize the universe into something sensible. */ | 1227 | /* Initialize the universe into something sensible. */ |
1198 | SCTP_STATIC __init int sctp_init(void) | 1228 | SCTP_STATIC __init int sctp_init(void) |
1199 | { | 1229 | { |
@@ -1399,18 +1429,6 @@ SCTP_STATIC __init int sctp_init(void) | |||
1399 | sctp_v4_pf_init(); | 1429 | sctp_v4_pf_init(); |
1400 | sctp_v6_pf_init(); | 1430 | sctp_v6_pf_init(); |
1401 | 1431 | ||
1402 | /* Initialize the local address list. */ | ||
1403 | INIT_LIST_HEAD(&sctp_local_addr_list); | ||
1404 | spin_lock_init(&sctp_local_addr_lock); | ||
1405 | sctp_get_local_addr_list(); | ||
1406 | |||
1407 | /* Initialize the address event list */ | ||
1408 | INIT_LIST_HEAD(&sctp_addr_waitq); | ||
1409 | INIT_LIST_HEAD(&sctp_auto_asconf_splist); | ||
1410 | spin_lock_init(&sctp_addr_wq_lock); | ||
1411 | sctp_addr_wq_timer.expires = 0; | ||
1412 | setup_timer(&sctp_addr_wq_timer, sctp_addr_wq_timeout_handler, 0); | ||
1413 | |||
1414 | status = sctp_v4_protosw_init(); | 1432 | status = sctp_v4_protosw_init(); |
1415 | 1433 | ||
1416 | if (status) | 1434 | if (status) |
@@ -1426,6 +1444,10 @@ SCTP_STATIC __init int sctp_init(void) | |||
1426 | goto err_ctl_sock_init; | 1444 | goto err_ctl_sock_init; |
1427 | } | 1445 | } |
1428 | 1446 | ||
1447 | status = register_pernet_subsys(&sctp_net_ops); | ||
1448 | if (status) | ||
1449 | goto err_register_pernet_subsys; | ||
1450 | |||
1429 | status = sctp_v4_add_protocol(); | 1451 | status = sctp_v4_add_protocol(); |
1430 | if (status) | 1452 | if (status) |
1431 | goto err_add_protocol; | 1453 | goto err_add_protocol; |
@@ -1441,13 +1463,14 @@ out: | |||
1441 | err_v6_add_protocol: | 1463 | err_v6_add_protocol: |
1442 | sctp_v4_del_protocol(); | 1464 | sctp_v4_del_protocol(); |
1443 | err_add_protocol: | 1465 | err_add_protocol: |
1466 | unregister_pernet_subsys(&sctp_net_ops); | ||
1467 | err_register_pernet_subsys: | ||
1444 | inet_ctl_sock_destroy(sctp_ctl_sock); | 1468 | inet_ctl_sock_destroy(sctp_ctl_sock); |
1445 | err_ctl_sock_init: | 1469 | err_ctl_sock_init: |
1446 | sctp_v6_protosw_exit(); | 1470 | sctp_v6_protosw_exit(); |
1447 | err_v6_protosw_init: | 1471 | err_v6_protosw_init: |
1448 | sctp_v4_protosw_exit(); | 1472 | sctp_v4_protosw_exit(); |
1449 | err_protosw_init: | 1473 | err_protosw_init: |
1450 | sctp_free_local_addr_list(); | ||
1451 | sctp_v4_pf_exit(); | 1474 | sctp_v4_pf_exit(); |
1452 | sctp_v6_pf_exit(); | 1475 | sctp_v6_pf_exit(); |
1453 | sctp_sysctl_unregister(); | 1476 | sctp_sysctl_unregister(); |
@@ -1482,18 +1505,16 @@ SCTP_STATIC __exit void sctp_exit(void) | |||
1482 | /* Unregister with inet6/inet layers. */ | 1505 | /* Unregister with inet6/inet layers. */ |
1483 | sctp_v6_del_protocol(); | 1506 | sctp_v6_del_protocol(); |
1484 | sctp_v4_del_protocol(); | 1507 | sctp_v4_del_protocol(); |
1485 | sctp_free_addr_wq(); | ||
1486 | 1508 | ||
1487 | /* Free the control endpoint. */ | 1509 | /* Free the control endpoint. */ |
1488 | inet_ctl_sock_destroy(sctp_ctl_sock); | 1510 | inet_ctl_sock_destroy(sctp_ctl_sock); |
1489 | 1511 | ||
1512 | unregister_pernet_subsys(&sctp_net_ops); | ||
1513 | |||
1490 | /* Free protosw registrations */ | 1514 | /* Free protosw registrations */ |
1491 | sctp_v6_protosw_exit(); | 1515 | sctp_v6_protosw_exit(); |
1492 | sctp_v4_protosw_exit(); | 1516 | sctp_v4_protosw_exit(); |
1493 | 1517 | ||
1494 | /* Free the local address list. */ | ||
1495 | sctp_free_local_addr_list(); | ||
1496 | |||
1497 | /* Unregister with socket layer. */ | 1518 | /* Unregister with socket layer. */ |
1498 | sctp_v6_pf_exit(); | 1519 | sctp_v6_pf_exit(); |
1499 | sctp_v4_pf_exit(); | 1520 | sctp_v4_pf_exit(); |