Unified · Split
| @@ -393,7 +393,7 @@ struct ip_vs_protocol { · 392 unmodified lines | ||
| 393 | 393 | |
| 394 | 394 | void (*exit)(struct ip_vs_protocol *pp); |
| 395 | 395 | |
| 396 | − void (*init_netns)(struct net *net, struct ip_vs_proto_data *pd); | |
| 396 | + int (*init_netns)(struct net *net, struct ip_vs_proto_data *pd); | |
| 397 | 397 | |
| 398 | 398 | void (*exit_netns)(struct net *net, struct ip_vs_proto_data *pd); |
| 399 | 399 | |
| @@ -1203,6 +1203,8 @@ ip_vs_lookup_real_service(struct net *net, int af, __u16 protocol, · 803 unmodified lines | ||
| 1203 | 1203 | |
| 1204 | 1204 | extern int ip_vs_use_count_inc(void); |
| 1205 | 1205 | extern void ip_vs_use_count_dec(void); |
| 1206 | +extern int ip_vs_register_nl_ioctl(void); | |
| 1207 | +extern void ip_vs_unregister_nl_ioctl(void); | |
| 1206 | 1208 | extern int ip_vs_control_init(void); |
| 1207 | 1209 | extern void ip_vs_control_cleanup(void); |
| 1208 | 1210 | extern struct ip_vs_dest * |
| @@ -1924,6 +1924,7 @@ protocol_fail: · 1923 unmodified lines | ||
| 1924 | 1924 | control_fail: |
| 1925 | 1925 | ip_vs_estimator_net_cleanup(net); |
| 1926 | 1926 | estimator_fail: |
| 1927 | + net->ipvs = NULL; | |
| 1927 | 1928 | return -ENOMEM; |
| 1928 | 1929 | } |
| 1929 | 1930 | |
| @@ -1936,6 +1937,7 @@ static void __net_exit __ip_vs_cleanup(struct net *net) · 6 unmodified lines | ||
| 1936 | 1937 | ip_vs_control_net_cleanup(net); |
| 1937 | 1938 | ip_vs_estimator_net_cleanup(net); |
| 1938 | 1939 | IP_VS_DBG(2, "ipvs netns %d released\n", net_ipvs(net)->gen); |
| 1940 | + net->ipvs = NULL; | |
| 1939 | 1941 | } |
| 1940 | 1942 | |
| 1941 | 1943 | static void __net_exit __ip_vs_dev_cleanup(struct net *net) |
| @@ -1993,10 +1995,18 @@ static int __init ip_vs_init(void) · 51 unmodified lines | ||
| 1993 | 1995 | goto cleanup_dev; |
| 1994 | 1996 | } |
| 1995 | 1997 | |
| 1998 | + ret = ip_vs_register_nl_ioctl(); | |
| 1999 | + if (ret < 0) { | |
| 2000 | + pr_err("can't register netlink/ioctl.\n"); | |
| 2001 | + goto cleanup_hooks; | |
| 2002 | + } | |
| 2003 | + | |
| 1996 | 2004 | pr_info("ipvs loaded.\n"); |
| 1997 | 2005 | |
| 1998 | 2006 | return ret; |
| 1999 | 2007 | |
| 2008 | +cleanup_hooks: | |
| 2009 | + nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); | |
| 2000 | 2010 | cleanup_dev: |
| 2001 | 2011 | unregister_pernet_device(&ipvs_core_dev_ops); |
| 2002 | 2012 | cleanup_sub: |
| @@ -2012,6 +2022,7 @@ exit: · 9 unmodified lines | ||
| 2012 | 2022 | |
| 2013 | 2023 | static void __exit ip_vs_cleanup(void) |
| 2014 | 2024 | { |
| 2025 | + ip_vs_unregister_nl_ioctl(); | |
| 2015 | 2026 | nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); |
| 2016 | 2027 | unregister_pernet_device(&ipvs_core_dev_ops); |
| 2017 | 2028 | unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */ |
| @@ -3680,7 +3680,7 @@ int __net_init ip_vs_control_net_init_sysctl(struct net *net) · 3679 unmodified lines | ||
| 3680 | 3680 | return 0; |
| 3681 | 3681 | } |
| 3682 | 3682 | |
| 3683 | −void __net_init ip_vs_control_net_cleanup_sysctl(struct net *net) | |
| 3683 | +void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net) | |
| 3684 | 3684 | { |
| 3685 | 3685 | struct netns_ipvs *ipvs = net_ipvs(net); |
| 3686 | 3686 | |
| @@ -3692,7 +3692,7 @@ void __net_init ip_vs_control_net_cleanup_sysctl(struct net *net) · 5 unmodified lines | ||
| 3692 | 3692 | #else |
| 3693 | 3693 | |
| 3694 | 3694 | int __net_init ip_vs_control_net_init_sysctl(struct net *net) { return 0; } |
| 3695 | −void __net_init ip_vs_control_net_cleanup_sysctl(struct net *net) { } | |
| 3695 | +void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net) { } | |
| 3696 | 3696 | |
| 3697 | 3697 | #endif |
| 3698 | 3698 | |
| @@ -3750,21 +3750,10 @@ void __net_exit ip_vs_control_net_cleanup(struct net *net) · 51 unmodified lines | ||
| 3750 | 3750 | free_percpu(ipvs->tot_stats.cpustats); |
| 3751 | 3751 | } |
| 3752 | 3752 | |
| 3753 | −int __init ip_vs_control_init(void) | |
| 3753 | +int __init ip_vs_register_nl_ioctl(void) | |
| 3754 | 3754 | { |
| 3755 | − int idx; | |
| 3756 | 3755 | int ret; |
| 3757 | 3756 | |
| 3758 | − EnterFunction(2); | |
| 3759 | − | |
| 3760 | − /* Initialize svc_table, ip_vs_svc_fwm_table, rs_table */ | |
| 3761 | − for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { | |
| 3762 | − INIT_LIST_HEAD(&ip_vs_svc_table[idx]); | |
| 3763 | − INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]); | |
| 3764 | − } | |
| 3765 | − | |
| 3766 | − smp_wmb(); /* Do we really need it now ? */ | |
| 3767 | − | |
| 3768 | 3757 | ret = nf_register_sockopt(&ip_vs_sockopts); |
| 3769 | 3758 | if (ret) { |
| 3770 | 3759 | pr_err("cannot register sockopt.\n"); |
| @@ -3776,28 +3765,47 @@ int __init ip_vs_control_init(void) · 5 unmodified lines | ||
| 3776 | 3765 | pr_err("cannot register Generic Netlink interface.\n"); |
| 3777 | 3766 | goto err_genl; |
| 3778 | 3767 | } |
| 3779 | − | |
| 3780 | − ret = register_netdevice_notifier(&ip_vs_dst_notifier); | |
| 3781 | − if (ret < 0) | |
| 3782 | − goto err_notf; | |
| 3783 | − | |
| 3784 | − LeaveFunction(2); | |
| 3785 | 3768 | return 0; |
| 3786 | 3769 | |
| 3787 | −err_notf: | |
| 3788 | − ip_vs_genl_unregister(); | |
| 3789 | 3770 | err_genl: |
| 3790 | 3771 | nf_unregister_sockopt(&ip_vs_sockopts); |
| 3791 | 3772 | err_sock: |
| 3792 | 3773 | return ret; |
| 3793 | 3774 | } |
| 3794 | 3775 | |
| 3776 | +void ip_vs_unregister_nl_ioctl(void) | |
| 3777 | +{ | |
| 3778 | + ip_vs_genl_unregister(); | |
| 3779 | + nf_unregister_sockopt(&ip_vs_sockopts); | |
| 3780 | +} | |
| 3781 | + | |
| 3782 | +int __init ip_vs_control_init(void) | |
| 3783 | +{ | |
| 3784 | + int idx; | |
| 3785 | + int ret; | |
| 3786 | + | |
| 3787 | + EnterFunction(2); | |
| 3788 | + | |
| 3789 | + /* Initialize svc_table, ip_vs_svc_fwm_table, rs_table */ | |
| 3790 | + for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { | |
| 3791 | + INIT_LIST_HEAD(&ip_vs_svc_table[idx]); | |
| 3792 | + INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]); | |
| 3793 | + } | |
| 3794 | + | |
| 3795 | + smp_wmb(); /* Do we really need it now ? */ | |
| 3796 | + | |
| 3797 | + ret = register_netdevice_notifier(&ip_vs_dst_notifier); | |
| 3798 | + if (ret < 0) | |
| 3799 | + return ret; | |
| 3800 | + | |
| 3801 | + LeaveFunction(2); | |
| 3802 | + return 0; | |
| 3803 | +} | |
| 3804 | + | |
| 3795 | 3805 | |
| 3796 | 3806 | void ip_vs_control_cleanup(void) |
| 3797 | 3807 | { |
| 3798 | 3808 | EnterFunction(2); |
| 3799 | 3809 | unregister_netdevice_notifier(&ip_vs_dst_notifier); |
| 3800 | − ip_vs_genl_unregister(); | |
| 3801 | − nf_unregister_sockopt(&ip_vs_sockopts); | |
| 3802 | 3810 | LeaveFunction(2); |
| 3803 | 3811 | } |
| @@ -439,6 +439,8 @@ static int __net_init __ip_vs_ftp_init(struct net *net) · 438 unmodified lines | ||
| 439 | 439 | struct ip_vs_app *app; |
| 440 | 440 | struct netns_ipvs *ipvs = net_ipvs(net); |
| 441 | 441 | |
| 442 | + if (!ipvs) | |
| 443 | + return -ENOENT; | |
| 442 | 444 | app = kmemdup(&ip_vs_ftp, sizeof(struct ip_vs_app), GFP_KERNEL); |
| 443 | 445 | if (!app) |
| 444 | 446 | return -ENOMEM; |
| @@ -551,6 +551,9 @@ static int __net_init __ip_vs_lblc_init(struct net *net) · 550 unmodified lines | ||
| 551 | 551 | { |
| 552 | 552 | struct netns_ipvs *ipvs = net_ipvs(net); |
| 553 | 553 | |
| 554 | + if (!ipvs) | |
| 555 | + return -ENOENT; | |
| 556 | + | |
| 554 | 557 | if (!net_eq(net, &init_net)) { |
| 555 | 558 | ipvs->lblc_ctl_table = kmemdup(vs_vars_table, |
| 556 | 559 | sizeof(vs_vars_table), |
| @@ -745,6 +745,9 @@ static int __net_init __ip_vs_lblcr_init(struct net *net) · 744 unmodified lines | ||
| 745 | 745 | { |
| 746 | 746 | struct netns_ipvs *ipvs = net_ipvs(net); |
| 747 | 747 | |
| 748 | + if (!ipvs) | |
| 749 | + return -ENOENT; | |
| 750 | + | |
| 748 | 751 | if (!net_eq(net, &init_net)) { |
| 749 | 752 | ipvs->lblcr_ctl_table = kmemdup(vs_vars_table, |
| 750 | 753 | sizeof(vs_vars_table), |
| @@ -59,9 +59,6 @@ static int __used __init register_ip_vs_protocol(struct ip_vs_protocol *pp) · 58 unmodified lines | ||
| 59 | 59 | return 0; |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | −#if defined(CONFIG_IP_VS_PROTO_TCP) || defined(CONFIG_IP_VS_PROTO_UDP) || \ | |
| 63 | − defined(CONFIG_IP_VS_PROTO_SCTP) || defined(CONFIG_IP_VS_PROTO_AH) || \ | |
| 64 | − defined(CONFIG_IP_VS_PROTO_ESP) | |
| 65 | 62 | /* |
| 66 | 63 | * register an ipvs protocols netns related data |
| 67 | 64 | */ |
| @@ -81,12 +78,18 @@ register_ip_vs_proto_netns(struct net *net, struct ip_vs_protocol *pp) · 13 unmodified lines | ||
| 81 | 78 | ipvs->proto_data_table[hash] = pd; |
| 82 | 79 | atomic_set(&pd->appcnt, 0); /* Init app counter */ |
| 83 | 80 | |
| 84 | − if (pp->init_netns != NULL) | |
| 85 | − pp->init_netns(net, pd); | |
| 81 | + if (pp->init_netns != NULL) { | |
| 82 | + int ret = pp->init_netns(net, pd); | |
| 83 | + if (ret) { | |
| 84 | + /* unlink an free proto data */ | |
| 85 | + ipvs->proto_data_table[hash] = pd->next; | |
| 86 | + kfree(pd); | |
| 87 | + return ret; | |
| 88 | + } | |
| 89 | + } | |
| 86 | 90 | |
| 87 | 91 | return 0; |
| 88 | 92 | } |
| 89 | −#endif | |
| 90 | 93 | |
| 91 | 94 | /* |
| 92 | 95 | * unregister an ipvs protocol |
| @@ -316,22 +319,35 @@ ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp, · 223 unmodified lines | ||
| 316 | 319 | */ |
| 317 | 320 | int __net_init ip_vs_protocol_net_init(struct net *net) |
| 318 | 321 | { |
| 322 | + int i, ret; | |
| 323 | + static struct ip_vs_protocol *protos[] = { | |
| 319 | 324 | #ifdef CONFIG_IP_VS_PROTO_TCP |
| 320 | − register_ip_vs_proto_netns(net, &ip_vs_protocol_tcp); | |
| 325 | + &ip_vs_protocol_tcp, | |
| 321 | 326 | #endif |
| 322 | 327 | #ifdef CONFIG_IP_VS_PROTO_UDP |
| 323 | − register_ip_vs_proto_netns(net, &ip_vs_protocol_udp); | |
| 328 | + &ip_vs_protocol_udp, | |
| 324 | 329 | #endif |
| 325 | 330 | #ifdef CONFIG_IP_VS_PROTO_SCTP |
| 326 | − register_ip_vs_proto_netns(net, &ip_vs_protocol_sctp); | |
| 331 | + &ip_vs_protocol_sctp, | |
| 327 | 332 | #endif |
| 328 | 333 | #ifdef CONFIG_IP_VS_PROTO_AH |
| 329 | − register_ip_vs_proto_netns(net, &ip_vs_protocol_ah); | |
| 334 | + &ip_vs_protocol_ah, | |
| 330 | 335 | #endif |
| 331 | 336 | #ifdef CONFIG_IP_VS_PROTO_ESP |
| 332 | − register_ip_vs_proto_netns(net, &ip_vs_protocol_esp); | |
| 337 | + &ip_vs_protocol_esp, | |
| 333 | 338 | #endif |
| 339 | + }; | |
| 340 | + | |
| 341 | + for (i = 0; i < ARRAY_SIZE(protos); i++) { | |
| 342 | + ret = register_ip_vs_proto_netns(net, protos[i]); | |
| 343 | + if (ret < 0) | |
| 344 | + goto cleanup; | |
| 345 | + } | |
| 334 | 346 | return 0; |
| 347 | + | |
| 348 | +cleanup: | |
| 349 | + ip_vs_protocol_net_cleanup(net); | |
| 350 | + return ret; | |
| 335 | 351 | } |
| 336 | 352 | |
| 337 | 353 | void __net_exit ip_vs_protocol_net_cleanup(struct net *net) |
| @@ -1090,7 +1090,7 @@ out: · 1089 unmodified lines | ||
| 1090 | 1090 | * timeouts is netns related now. |
| 1091 | 1091 | * --------------------------------------------- |
| 1092 | 1092 | */ |
| 1093 | −static void __ip_vs_sctp_init(struct net *net, struct ip_vs_proto_data *pd) | |
| 1093 | +static int __ip_vs_sctp_init(struct net *net, struct ip_vs_proto_data *pd) | |
| 1094 | 1094 | { |
| 1095 | 1095 | struct netns_ipvs *ipvs = net_ipvs(net); |
| 1096 | 1096 | |
| @@ -1098,6 +1098,9 @@ static void __ip_vs_sctp_init(struct net *net, struct ip_vs_proto_data *pd) · 1 unmodified line | ||
| 1098 | 1098 | spin_lock_init(&ipvs->sctp_app_lock); |
| 1099 | 1099 | pd->timeout_table = ip_vs_create_timeout_table((int *)sctp_timeouts, |
| 1100 | 1100 | sizeof(sctp_timeouts)); |
| 1101 | + if (!pd->timeout_table) | |
| 1102 | + return -ENOMEM; | |
| 1103 | + return 0; | |
| 1101 | 1104 | } |
| 1102 | 1105 | |
| 1103 | 1106 | static void __ip_vs_sctp_exit(struct net *net, struct ip_vs_proto_data *pd) |
| @@ -677,7 +677,7 @@ void ip_vs_tcp_conn_listen(struct net *net, struct ip_vs_conn *cp) · 676 unmodified lines | ||
| 677 | 677 | * timeouts is netns related now. |
| 678 | 678 | * --------------------------------------------- |
| 679 | 679 | */ |
| 680 | −static void __ip_vs_tcp_init(struct net *net, struct ip_vs_proto_data *pd) | |
| 680 | +static int __ip_vs_tcp_init(struct net *net, struct ip_vs_proto_data *pd) | |
| 681 | 681 | { |
| 682 | 682 | struct netns_ipvs *ipvs = net_ipvs(net); |
| 683 | 683 | |
| @@ -685,7 +685,10 @@ static void __ip_vs_tcp_init(struct net *net, struct ip_vs_proto_data *pd) · 1 unmodified line | ||
| 685 | 685 | spin_lock_init(&ipvs->tcp_app_lock); |
| 686 | 686 | pd->timeout_table = ip_vs_create_timeout_table((int *)tcp_timeouts, |
| 687 | 687 | sizeof(tcp_timeouts)); |
| 688 | + if (!pd->timeout_table) | |
| 689 | + return -ENOMEM; | |
| 688 | 690 | pd->tcp_state_table = tcp_states; |
| 691 | + return 0; | |
| 689 | 692 | } |
| 690 | 693 | |
| 691 | 694 | static void __ip_vs_tcp_exit(struct net *net, struct ip_vs_proto_data *pd) |
| @@ -467,7 +467,7 @@ udp_state_transition(struct ip_vs_conn *cp, int direction, · 466 unmodified lines | ||
| 467 | 467 | cp->timeout = pd->timeout_table[IP_VS_UDP_S_NORMAL]; |
| 468 | 468 | } |
| 469 | 469 | |
| 470 | −static void __udp_init(struct net *net, struct ip_vs_proto_data *pd) | |
| 470 | +static int __udp_init(struct net *net, struct ip_vs_proto_data *pd) | |
| 471 | 471 | { |
| 472 | 472 | struct netns_ipvs *ipvs = net_ipvs(net); |
| 473 | 473 | |
| @@ -475,6 +475,9 @@ static void __udp_init(struct net *net, struct ip_vs_proto_data *pd) · 1 unmodified line | ||
| 475 | 475 | spin_lock_init(&ipvs->udp_app_lock); |
| 476 | 476 | pd->timeout_table = ip_vs_create_timeout_table((int *)udp_timeouts, |
| 477 | 477 | sizeof(udp_timeouts)); |
| 478 | + if (!pd->timeout_table) | |
| 479 | + return -ENOMEM; | |
| 480 | + return 0; | |
| 478 | 481 | } |
| 479 | 482 | |
| 480 | 483 | static void __udp_exit(struct net *net, struct ip_vs_proto_data *pd) |
| @@ -227,7 +227,7 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) · 226 unmodified lines | ||
| 227 | 227 | } |
| 228 | 228 | |
| 229 | 229 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT |
| 230 | − if (info->timeout) { | |
| 230 | + if (info->timeout[0]) { | |
| 231 | 231 | typeof(nf_ct_timeout_find_get_hook) timeout_find_get; |
| 232 | 232 | struct nf_conn_timeout *timeout_ext; |
| 233 | 233 | |