Unified · Split
| @@ -791,6 +791,7 @@ struct ip_vs_app { · 790 unmodified lines | ||
| 791 | 791 | /* IPVS in network namespace */ |
| 792 | 792 | struct netns_ipvs { |
| 793 | 793 | int gen; /* Generation */ |
| 794 | + int enable; /* enable like nf_hooks do */ | |
| 794 | 795 | /* |
| 795 | 796 | * Hash table: for real service lookups |
| 796 | 797 | */ |
| @@ -1089,6 +1090,22 @@ ip_vs_control_add(struct ip_vs_conn *cp, struct ip_vs_conn *ctl_cp) · 292 unmodified lines | ||
| 1089 | 1090 | atomic_inc(&ctl_cp->n_control); |
| 1090 | 1091 | } |
| 1091 | 1092 | |
| 1093 | +/* | |
| 1094 | + * IPVS netns init & cleanup functions | |
| 1095 | + */ | |
| 1096 | +extern int __ip_vs_estimator_init(struct net *net); | |
| 1097 | +extern int __ip_vs_control_init(struct net *net); | |
| 1098 | +extern int __ip_vs_protocol_init(struct net *net); | |
| 1099 | +extern int __ip_vs_app_init(struct net *net); | |
| 1100 | +extern int __ip_vs_conn_init(struct net *net); | |
| 1101 | +extern int __ip_vs_sync_init(struct net *net); | |
| 1102 | +extern void __ip_vs_conn_cleanup(struct net *net); | |
| 1103 | +extern void __ip_vs_app_cleanup(struct net *net); | |
| 1104 | +extern void __ip_vs_protocol_cleanup(struct net *net); | |
| 1105 | +extern void __ip_vs_control_cleanup(struct net *net); | |
| 1106 | +extern void __ip_vs_estimator_cleanup(struct net *net); | |
| 1107 | +extern void __ip_vs_sync_cleanup(struct net *net); | |
| 1108 | +extern void __ip_vs_service_cleanup(struct net *net); | |
| 1092 | 1109 | |
| 1093 | 1110 | /* |
| 1094 | 1111 | * IPVS application functions |
| @@ -1766,7 +1766,7 @@ static int compat_table_info(const struct ebt_table_info *info, · 1765 unmodified lines | ||
| 1766 | 1766 | |
| 1767 | 1767 | newinfo->entries_size = size; |
| 1768 | 1768 | |
| 1769 | − xt_compat_init_offsets(AF_INET, info->nentries); | |
| 1769 | + xt_compat_init_offsets(NFPROTO_BRIDGE, info->nentries); | |
| 1770 | 1770 | return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info, |
| 1771 | 1771 | entries, newinfo); |
| 1772 | 1772 | } |
| @@ -1882,7 +1882,7 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, · 109 unmodified lines | ||
| 1882 | 1882 | struct xt_match *match; |
| 1883 | 1883 | struct xt_target *wt; |
| 1884 | 1884 | void *dst = NULL; |
| 1885 | − int off, pad = 0, ret = 0; | |
| 1885 | + int off, pad = 0; | |
| 1886 | 1886 | unsigned int size_kern, entry_offset, match_size = mwt->match_size; |
| 1887 | 1887 | |
| 1888 | 1888 | strlcpy(name, mwt->u.name, sizeof(name)); |
| @@ -1935,13 +1935,6 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, · 46 unmodified lines | ||
| 1935 | 1935 | break; |
| 1936 | 1936 | } |
| 1937 | 1937 | |
| 1938 | − if (!dst) { | |
| 1939 | − ret = xt_compat_add_offset(NFPROTO_BRIDGE, entry_offset, | |
| 1940 | − off + ebt_compat_entry_padsize()); | |
| 1941 | − if (ret < 0) | |
| 1942 | − return ret; | |
| 1943 | − } | |
| 1944 | − | |
| 1945 | 1938 | state->buf_kern_offset += match_size + off; |
| 1946 | 1939 | state->buf_user_offset += match_size; |
| 1947 | 1940 | pad = XT_ALIGN(size_kern) - size_kern; |
| @@ -2016,50 +2009,6 @@ static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32, · 68 unmodified lines | ||
| 2016 | 2009 | return growth; |
| 2017 | 2010 | } |
| 2018 | 2011 | |
| 2019 | −#define EBT_COMPAT_WATCHER_ITERATE(e, fn, args...) \ | |
| 2020 | −({ \ | |
| 2021 | − unsigned int __i; \ | |
| 2022 | − int __ret = 0; \ | |
| 2023 | − struct compat_ebt_entry_mwt *__watcher; \ | |
| 2024 | − \ | |
| 2025 | − for (__i = e->watchers_offset; \ | |
| 2026 | − __i < (e)->target_offset; \ | |
| 2027 | − __i += __watcher->watcher_size + \ | |
| 2028 | − sizeof(struct compat_ebt_entry_mwt)) { \ | |
| 2029 | − __watcher = (void *)(e) + __i; \ | |
| 2030 | − __ret = fn(__watcher , ## args); \ | |
| 2031 | − if (__ret != 0) \ | |
| 2032 | − break; \ | |
| 2033 | − } \ | |
| 2034 | − if (__ret == 0) { \ | |
| 2035 | − if (__i != (e)->target_offset) \ | |
| 2036 | − __ret = -EINVAL; \ | |
| 2037 | − } \ | |
| 2038 | − __ret; \ | |
| 2039 | −}) | |
| 2040 | − | |
| 2041 | −#define EBT_COMPAT_MATCH_ITERATE(e, fn, args...) \ | |
| 2042 | −({ \ | |
| 2043 | − unsigned int __i; \ | |
| 2044 | − int __ret = 0; \ | |
| 2045 | − struct compat_ebt_entry_mwt *__match; \ | |
| 2046 | − \ | |
| 2047 | − for (__i = sizeof(struct ebt_entry); \ | |
| 2048 | − __i < (e)->watchers_offset; \ | |
| 2049 | − __i += __match->match_size + \ | |
| 2050 | − sizeof(struct compat_ebt_entry_mwt)) { \ | |
| 2051 | − __match = (void *)(e) + __i; \ | |
| 2052 | − __ret = fn(__match , ## args); \ | |
| 2053 | − if (__ret != 0) \ | |
| 2054 | − break; \ | |
| 2055 | − } \ | |
| 2056 | − if (__ret == 0) { \ | |
| 2057 | − if (__i != (e)->watchers_offset) \ | |
| 2058 | − __ret = -EINVAL; \ | |
| 2059 | − } \ | |
| 2060 | − __ret; \ | |
| 2061 | −}) | |
| 2062 | − | |
| 2063 | 2012 | /* called for all ebt_entry structures. */ |
| 2064 | 2013 | static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, |
| 2065 | 2014 | unsigned int *total, |
| @@ -2132,6 +2081,14 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, · 66 unmodified lines | ||
| 2132 | 2081 | } |
| 2133 | 2082 | } |
| 2134 | 2083 | |
| 2084 | + if (state->buf_kern_start == NULL) { | |
| 2085 | + unsigned int offset = buf_start - (char *) base; | |
| 2086 | + | |
| 2087 | + ret = xt_compat_add_offset(NFPROTO_BRIDGE, offset, new_offset); | |
| 2088 | + if (ret < 0) | |
| 2089 | + return ret; | |
| 2090 | + } | |
| 2091 | + | |
| 2135 | 2092 | startoff = state->buf_user_offset - startoff; |
| 2136 | 2093 | |
| 2137 | 2094 | BUG_ON(*total < startoff); |
| @@ -2240,6 +2197,7 @@ static int compat_do_replace(struct net *net, void __user *user, · 102 unmodified lines | ||
| 2240 | 2197 | |
| 2241 | 2198 | xt_compat_lock(NFPROTO_BRIDGE); |
| 2242 | 2199 | |
| 2200 | + xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries); | |
| 2243 | 2201 | ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state); |
| 2244 | 2202 | if (ret < 0) |
| 2245 | 2203 | goto out_unlock; |
| @@ -45,6 +45,8 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) · 44 unmodified lines | ||
| 45 | 45 | int tcphoff, needs_ack; |
| 46 | 46 | const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); |
| 47 | 47 | struct ipv6hdr *ip6h; |
| 48 | +#define DEFAULT_TOS_VALUE 0x0U | |
| 49 | + const __u8 tclass = DEFAULT_TOS_VALUE; | |
| 48 | 50 | struct dst_entry *dst = NULL; |
| 49 | 51 | u8 proto; |
| 50 | 52 | struct flowi6 fl6; |
| @@ -124,7 +126,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) · 73 unmodified lines | ||
| 124 | 126 | skb_put(nskb, sizeof(struct ipv6hdr)); |
| 125 | 127 | skb_reset_network_header(nskb); |
| 126 | 128 | ip6h = ipv6_hdr(nskb); |
| 127 | − ip6h->version = 6; | |
| 129 | + *(__be32 *)ip6h = htonl(0x60000000 | (tclass << 20)); | |
| 128 | 130 | ip6h->hop_limit = ip6_dst_hoplimit(dst); |
| 129 | 131 | ip6h->nexthdr = IPPROTO_TCP; |
| 130 | 132 | ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr); |
| @@ -576,7 +576,7 @@ static const struct file_operations ip_vs_app_fops = { · 575 unmodified lines | ||
| 576 | 576 | }; |
| 577 | 577 | #endif |
| 578 | 578 | |
| 579 | −static int __net_init __ip_vs_app_init(struct net *net) | |
| 579 | +int __net_init __ip_vs_app_init(struct net *net) | |
| 580 | 580 | { |
| 581 | 581 | struct netns_ipvs *ipvs = net_ipvs(net); |
| 582 | 582 | |
| @@ -585,26 +585,17 @@ static int __net_init __ip_vs_app_init(struct net *net) · 2 unmodified lines | ||
| 585 | 585 | return 0; |
| 586 | 586 | } |
| 587 | 587 | |
| 588 | −static void __net_exit __ip_vs_app_cleanup(struct net *net) | |
| 588 | +void __net_exit __ip_vs_app_cleanup(struct net *net) | |
| 589 | 589 | { |
| 590 | 590 | proc_net_remove(net, "ip_vs_app"); |
| 591 | 591 | } |
| 592 | 592 | |
| 593 | −static struct pernet_operations ip_vs_app_ops = { | |
| 594 | − .init = __ip_vs_app_init, | |
| 595 | − .exit = __ip_vs_app_cleanup, | |
| 596 | −}; | |
| 597 | − | |
| 598 | 593 | int __init ip_vs_app_init(void) |
| 599 | 594 | { |
| 600 | − int rv; | |
| 601 | − | |
| 602 | − rv = register_pernet_subsys(&ip_vs_app_ops); | |
| 603 | − return rv; | |
| 595 | + return 0; | |
| 604 | 596 | } |
| 605 | 597 | |
| 606 | 598 | |
| 607 | 599 | void ip_vs_app_cleanup(void) |
| 608 | 600 | { |
| 609 | − unregister_pernet_subsys(&ip_vs_app_ops); | |
| 610 | 601 | } |
| @@ -1258,22 +1258,17 @@ int __net_init __ip_vs_conn_init(struct net *net) · 1257 unmodified lines | ||
| 1258 | 1258 | return 0; |
| 1259 | 1259 | } |
| 1260 | 1260 | |
| 1261 | −static void __net_exit __ip_vs_conn_cleanup(struct net *net) | |
| 1261 | +void __net_exit __ip_vs_conn_cleanup(struct net *net) | |
| 1262 | 1262 | { |
| 1263 | 1263 | /* flush all the connection entries first */ |
| 1264 | 1264 | ip_vs_conn_flush(net); |
| 1265 | 1265 | proc_net_remove(net, "ip_vs_conn"); |
| 1266 | 1266 | proc_net_remove(net, "ip_vs_conn_sync"); |
| 1267 | 1267 | } |
| 1268 | −static struct pernet_operations ipvs_conn_ops = { | |
| 1269 | − .init = __ip_vs_conn_init, | |
| 1270 | − .exit = __ip_vs_conn_cleanup, | |
| 1271 | −}; | |
| 1272 | 1268 | |
| 1273 | 1269 | int __init ip_vs_conn_init(void) |
| 1274 | 1270 | { |
| 1275 | 1271 | int idx; |
| 1276 | − int retc; | |
| 1277 | 1272 | |
| 1278 | 1273 | /* Compute size and mask */ |
| 1279 | 1274 | ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits; |
| @@ -1309,17 +1304,14 @@ int __init ip_vs_conn_init(void) · 29 unmodified lines | ||
| 1309 | 1304 | rwlock_init(&__ip_vs_conntbl_lock_array[idx].l); |
| 1310 | 1305 | } |
| 1311 | 1306 | |
| 1312 | − retc = register_pernet_subsys(&ipvs_conn_ops); | |
| 1313 | − | |
| 1314 | 1307 | /* calculate the random value for connection hash */ |
| 1315 | 1308 | get_random_bytes(&ip_vs_conn_rnd, sizeof(ip_vs_conn_rnd)); |
| 1316 | 1309 | |
| 1317 | − return retc; | |
| 1310 | + return 0; | |
| 1318 | 1311 | } |
| 1319 | 1312 | |
| 1320 | 1313 | void ip_vs_conn_cleanup(void) |
| 1321 | 1314 | { |
| 1322 | − unregister_pernet_subsys(&ipvs_conn_ops); | |
| 1323 | 1315 | /* Release the empty cache */ |
| 1324 | 1316 | kmem_cache_destroy(ip_vs_conn_cachep); |
| 1325 | 1317 | vfree(ip_vs_conn_tab); |
| @@ -1113,6 +1113,9 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) · 1112 unmodified lines | ||
| 1113 | 1113 | return NF_ACCEPT; |
| 1114 | 1114 | |
| 1115 | 1115 | net = skb_net(skb); |
| 1116 | + if (!net_ipvs(net)->enable) | |
| 1117 | + return NF_ACCEPT; | |
| 1118 | + | |
| 1116 | 1119 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); |
| 1117 | 1120 | #ifdef CONFIG_IP_VS_IPV6 |
| 1118 | 1121 | if (af == AF_INET6) { |
| @@ -1343,6 +1346,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) · 224 unmodified lines | ||
| 1343 | 1346 | return NF_ACCEPT; /* The packet looks wrong, ignore */ |
| 1344 | 1347 | |
| 1345 | 1348 | net = skb_net(skb); |
| 1349 | + | |
| 1346 | 1350 | pd = ip_vs_proto_data_get(net, cih->protocol); |
| 1347 | 1351 | if (!pd) |
| 1348 | 1352 | return NF_ACCEPT; |
| @@ -1529,6 +1533,11 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) · 180 unmodified lines | ||
| 1529 | 1533 | IP_VS_DBG_ADDR(af, &iph.daddr), hooknum); |
| 1530 | 1534 | return NF_ACCEPT; |
| 1531 | 1535 | } |
| 1536 | + /* ipvs enabled in this netns ? */ | |
| 1537 | + net = skb_net(skb); | |
| 1538 | + if (!net_ipvs(net)->enable) | |
| 1539 | + return NF_ACCEPT; | |
| 1540 | + | |
| 1532 | 1541 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); |
| 1533 | 1542 | |
| 1534 | 1543 | /* Bad... Do not break raw sockets */ |
| @@ -1562,7 +1571,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) · 27 unmodified lines | ||
| 1562 | 1571 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); |
| 1563 | 1572 | } |
| 1564 | 1573 | |
| 1565 | − net = skb_net(skb); | |
| 1566 | 1574 | /* Protocol supported? */ |
| 1567 | 1575 | pd = ip_vs_proto_data_get(net, iph.protocol); |
| 1568 | 1576 | if (unlikely(!pd)) |
| @@ -1588,7 +1596,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) · 19 unmodified lines | ||
| 1588 | 1596 | } |
| 1589 | 1597 | |
| 1590 | 1598 | IP_VS_DBG_PKT(11, af, pp, skb, 0, "Incoming packet"); |
| 1591 | − net = skb_net(skb); | |
| 1592 | 1599 | ipvs = net_ipvs(net); |
| 1593 | 1600 | /* Check the server status */ |
| 1594 | 1601 | if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) { |
| @@ -1743,10 +1750,16 @@ ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff *skb, · 148 unmodified lines | ||
| 1743 | 1750 | int (*okfn)(struct sk_buff *)) |
| 1744 | 1751 | { |
| 1745 | 1752 | int r; |
| 1753 | + struct net *net; | |
| 1746 | 1754 | |
| 1747 | 1755 | if (ip_hdr(skb)->protocol != IPPROTO_ICMP) |
| 1748 | 1756 | return NF_ACCEPT; |
| 1749 | 1757 | |
| 1758 | + /* ipvs enabled in this netns ? */ | |
| 1759 | + net = skb_net(skb); | |
| 1760 | + if (!net_ipvs(net)->enable) | |
| 1761 | + return NF_ACCEPT; | |
| 1762 | + | |
| 1750 | 1763 | return ip_vs_in_icmp(skb, &r, hooknum); |
| 1751 | 1764 | } |
| 1752 | 1765 | |
| @@ -1757,10 +1770,16 @@ ip_vs_forward_icmp_v6(unsigned int hooknum, struct sk_buff *skb, · 4 unmodified lines | ||
| 1757 | 1770 | int (*okfn)(struct sk_buff *)) |
| 1758 | 1771 | { |
| 1759 | 1772 | int r; |
| 1773 | + struct net *net; | |
| 1760 | 1774 | |
| 1761 | 1775 | if (ipv6_hdr(skb)->nexthdr != IPPROTO_ICMPV6) |
| 1762 | 1776 | return NF_ACCEPT; |
| 1763 | 1777 | |
| 1778 | + /* ipvs enabled in this netns ? */ | |
| 1779 | + net = skb_net(skb); | |
| 1780 | + if (!net_ipvs(net)->enable) | |
| 1781 | + return NF_ACCEPT; | |
| 1782 | + | |
| 1764 | 1783 | return ip_vs_in_icmp_v6(skb, &r, hooknum); |
| 1765 | 1784 | } |
| 1766 | 1785 | #endif |
| @@ -1884,19 +1903,70 @@ static int __net_init __ip_vs_init(struct net *net) · 117 unmodified lines | ||
| 1884 | 1903 | pr_err("%s(): no memory.\n", __func__); |
| 1885 | 1904 | return -ENOMEM; |
| 1886 | 1905 | } |
| 1906 | + /* Hold the beast until a service is registerd */ | |
| 1907 | + ipvs->enable = 0; | |
| 1887 | 1908 | ipvs->net = net; |
| 1888 | 1909 | /* Counters used for creating unique names */ |
| 1889 | 1910 | ipvs->gen = atomic_read(&ipvs_netns_cnt); |
| 1890 | 1911 | atomic_inc(&ipvs_netns_cnt); |
| 1891 | 1912 | net->ipvs = ipvs; |
| 1913 | + | |
| 1914 | + if (__ip_vs_estimator_init(net) < 0) | |
| 1915 | + goto estimator_fail; | |
| 1916 | + | |
| 1917 | + if (__ip_vs_control_init(net) < 0) | |
| 1918 | + goto control_fail; | |
| 1919 | + | |
| 1920 | + if (__ip_vs_protocol_init(net) < 0) | |
| 1921 | + goto protocol_fail; | |
| 1922 | + | |
| 1923 | + if (__ip_vs_app_init(net) < 0) | |
| 1924 | + goto app_fail; | |
| 1925 | + | |
| 1926 | + if (__ip_vs_conn_init(net) < 0) | |
| 1927 | + goto conn_fail; | |
| 1928 | + | |
| 1929 | + if (__ip_vs_sync_init(net) < 0) | |
| 1930 | + goto sync_fail; | |
| 1931 | + | |
| 1892 | 1932 | printk(KERN_INFO "IPVS: Creating netns size=%zu id=%d\n", |
| 1893 | 1933 | sizeof(struct netns_ipvs), ipvs->gen); |
| 1894 | 1934 | return 0; |
| 1935 | +/* | |
| 1936 | + * Error handling | |
| 1937 | + */ | |
| 1938 | + | |
| 1939 | +sync_fail: | |
| 1940 | + __ip_vs_conn_cleanup(net); | |
| 1941 | +conn_fail: | |
| 1942 | + __ip_vs_app_cleanup(net); | |
| 1943 | +app_fail: | |
| 1944 | + __ip_vs_protocol_cleanup(net); | |
| 1945 | +protocol_fail: | |
| 1946 | + __ip_vs_control_cleanup(net); | |
| 1947 | +control_fail: | |
| 1948 | + __ip_vs_estimator_cleanup(net); | |
| 1949 | +estimator_fail: | |
| 1950 | + return -ENOMEM; | |
| 1895 | 1951 | } |
| 1896 | 1952 | |
| 1897 | 1953 | static void __net_exit __ip_vs_cleanup(struct net *net) |
| 1898 | 1954 | { |
| 1899 | − IP_VS_DBG(10, "ipvs netns %d released\n", net_ipvs(net)->gen); | |
| 1955 | + __ip_vs_service_cleanup(net); /* ip_vs_flush() with locks */ | |
| 1956 | + __ip_vs_conn_cleanup(net); | |
| 1957 | + __ip_vs_app_cleanup(net); | |
| 1958 | + __ip_vs_protocol_cleanup(net); | |
| 1959 | + __ip_vs_control_cleanup(net); | |
| 1960 | + __ip_vs_estimator_cleanup(net); | |
| 1961 | + IP_VS_DBG(2, "ipvs netns %d released\n", net_ipvs(net)->gen); | |
| 1962 | +} | |
| 1963 | + | |
| 1964 | +static void __net_exit __ip_vs_dev_cleanup(struct net *net) | |
| 1965 | +{ | |
| 1966 | + EnterFunction(2); | |
| 1967 | + net_ipvs(net)->enable = 0; /* Disable packet reception */ | |
| 1968 | + __ip_vs_sync_cleanup(net); | |
| 1969 | + LeaveFunction(2); | |
| 1900 | 1970 | } |
| 1901 | 1971 | |
| 1902 | 1972 | static struct pernet_operations ipvs_core_ops = { |
| @@ -1906,6 +1976,10 @@ static struct pernet_operations ipvs_core_ops = { · 3 unmodified lines | ||
| 1906 | 1976 | .size = sizeof(struct netns_ipvs), |
| 1907 | 1977 | }; |
| 1908 | 1978 | |
| 1979 | +static struct pernet_operations ipvs_core_dev_ops = { | |
| 1980 | + .exit = __ip_vs_dev_cleanup, | |
| 1981 | +}; | |
| 1982 | + | |
| 1909 | 1983 | /* |
| 1910 | 1984 | * Initialize IP Virtual Server |
| 1911 | 1985 | */ |
| @@ -1913,10 +1987,6 @@ static int __init ip_vs_init(void) · 1 unmodified line | ||
| 1913 | 1987 | { |
| 1914 | 1988 | int ret; |
| 1915 | 1989 | |
| 1916 | − ret = register_pernet_subsys(&ipvs_core_ops); /* Alloc ip_vs struct */ | |
| 1917 | − if (ret < 0) | |
| 1918 | − return ret; | |
| 1919 | − | |
| 1920 | 1990 | ip_vs_estimator_init(); |
| 1921 | 1991 | ret = ip_vs_control_init(); |
| 1922 | 1992 | if (ret < 0) { |
| @@ -1944,15 +2014,28 @@ static int __init ip_vs_init(void) · 21 unmodified lines | ||
| 1944 | 2014 | goto cleanup_conn; |
| 1945 | 2015 | } |
| 1946 | 2016 | |
| 2017 | + ret = register_pernet_subsys(&ipvs_core_ops); /* Alloc ip_vs struct */ | |
| 2018 | + if (ret < 0) | |
| 2019 | + goto cleanup_sync; | |
| 2020 | + | |
| 2021 | + ret = register_pernet_device(&ipvs_core_dev_ops); | |
| 2022 | + if (ret < 0) | |
| 2023 | + goto cleanup_sub; | |
| 2024 | + | |
| 1947 | 2025 | ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); |
| 1948 | 2026 | if (ret < 0) { |
| 1949 | 2027 | pr_err("can't register hooks.\n"); |
| 1950 | − goto cleanup_sync; | |
| 2028 | + goto cleanup_dev; | |
| 1951 | 2029 | } |
| 1952 | 2030 | |
| 1953 | 2031 | pr_info("ipvs loaded.\n"); |
| 2032 | + | |
| 1954 | 2033 | return ret; |
| 1955 | 2034 | |
| 2035 | +cleanup_dev: | |
| 2036 | + unregister_pernet_device(&ipvs_core_dev_ops); | |
| 2037 | +cleanup_sub: | |
| 2038 | + unregister_pernet_subsys(&ipvs_core_ops); | |
| 1956 | 2039 | cleanup_sync: |
| 1957 | 2040 | ip_vs_sync_cleanup(); |
| 1958 | 2041 | cleanup_conn: |
| @@ -1964,20 +2047,20 @@ cleanup_sync: · 5 unmodified lines | ||
| 1964 | 2047 | ip_vs_control_cleanup(); |
| 1965 | 2048 | cleanup_estimator: |
| 1966 | 2049 | ip_vs_estimator_cleanup(); |
| 1967 | − unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */ | |
| 1968 | 2050 | return ret; |
| 1969 | 2051 | } |
| 1970 | 2052 | |
| 1971 | 2053 | static void __exit ip_vs_cleanup(void) |
| 1972 | 2054 | { |
| 1973 | 2055 | nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); |
| 2056 | + unregister_pernet_device(&ipvs_core_dev_ops); | |
| 2057 | + unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */ | |
| 1974 | 2058 | ip_vs_sync_cleanup(); |
| 1975 | 2059 | ip_vs_conn_cleanup(); |
| 1976 | 2060 | ip_vs_app_cleanup(); |
| 1977 | 2061 | ip_vs_protocol_cleanup(); |
| 1978 | 2062 | ip_vs_control_cleanup(); |
| 1979 | 2063 | ip_vs_estimator_cleanup(); |
| 1980 | − unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */ | |
| 1981 | 2064 | pr_info("ipvs unloaded.\n"); |
| 1982 | 2065 | } |
| 1983 | 2066 | |
| @@ -69,6 +69,11 @@ int ip_vs_get_debug_level(void) · 68 unmodified lines | ||
| 69 | 69 | } |
| 70 | 70 | #endif |
| 71 | 71 | |
| 72 | + | |
| 73 | +/* Protos */ | |
| 74 | +static void __ip_vs_del_service(struct ip_vs_service *svc); | |
| 75 | + | |
| 76 | + | |
| 72 | 77 | #ifdef CONFIG_IP_VS_IPV6 |
| 73 | 78 | /* Taken from rt6_fill_node() in net/ipv6/route.c, is there a better way? */ |
| 74 | 79 | static int __ip_vs_addr_is_local_v6(struct net *net, |
| @@ -1214,6 +1219,8 @@ ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u, · 1139 unmodified lines | ||
| 1214 | 1219 | write_unlock_bh(&__ip_vs_svc_lock); |
| 1215 | 1220 | |
| 1216 | 1221 | *svc_p = svc; |
| 1222 | + /* Now there is a service - full throttle */ | |
| 1223 | + ipvs->enable = 1; | |
| 1217 | 1224 | return 0; |
| 1218 | 1225 | |
| 1219 | 1226 | |
| @@ -1472,6 +1479,84 @@ static int ip_vs_flush(struct net *net) · 252 unmodified lines | ||
| 1472 | 1479 | return 0; |
| 1473 | 1480 | } |
| 1474 | 1481 | |
| 1482 | +/* | |
| 1483 | + * Delete service by {netns} in the service table. | |
| 1484 | + * Called by __ip_vs_cleanup() | |
| 1485 | + */ | |
| 1486 | +void __ip_vs_service_cleanup(struct net *net) | |
| 1487 | +{ | |
| 1488 | + EnterFunction(2); | |
| 1489 | + /* Check for "full" addressed entries */ | |
| 1490 | + mutex_lock(&__ip_vs_mutex); | |
| 1491 | + ip_vs_flush(net); | |
| 1492 | + mutex_unlock(&__ip_vs_mutex); | |
| 1493 | + LeaveFunction(2); | |
| 1494 | +} | |
| 1495 | +/* | |
| 1496 | + * Release dst hold by dst_cache | |
| 1497 | + */ | |
| 1498 | +static inline void | |
| 1499 | +__ip_vs_dev_reset(struct ip_vs_dest *dest, struct net_device *dev) | |
| 1500 | +{ | |
| 1501 | + spin_lock_bh(&dest->dst_lock); | |
| 1502 | + if (dest->dst_cache && dest->dst_cache->dev == dev) { | |
| 1503 | + IP_VS_DBG_BUF(3, "Reset dev:%s dest %s:%u ,dest->refcnt=%d\n", | |
| 1504 | + dev->name, | |
| 1505 | + IP_VS_DBG_ADDR(dest->af, &dest->addr), | |
| 1506 | + ntohs(dest->port), | |
| 1507 | + atomic_read(&dest->refcnt)); | |
| 1508 | + ip_vs_dst_reset(dest); | |
| 1509 | + } | |
| 1510 | + spin_unlock_bh(&dest->dst_lock); | |
| 1511 | + | |
| 1512 | +} | |
| 1513 | +/* | |
| 1514 | + * Netdev event receiver | |
| 1515 | + * Currently only NETDEV_UNREGISTER is handled, i.e. if we hold a reference to | |
| 1516 | + * a device that is "unregister" it must be released. | |
| 1517 | + */ | |
| 1518 | +static int ip_vs_dst_event(struct notifier_block *this, unsigned long event, | |
| 1519 | + void *ptr) | |
| 1520 | +{ | |
| 1521 | + struct net_device *dev = ptr; | |
| 1522 | + struct net *net = dev_net(dev); | |
| 1523 | + struct ip_vs_service *svc; | |
| 1524 | + struct ip_vs_dest *dest; | |
| 1525 | + unsigned int idx; | |
| 1526 | + | |
| 1527 | + if (event != NETDEV_UNREGISTER) | |
| 1528 | + return NOTIFY_DONE; | |
| 1529 | + IP_VS_DBG(3, "%s() dev=%s\n", __func__, dev->name); | |
| 1530 | + EnterFunction(2); | |
| 1531 | + mutex_lock(&__ip_vs_mutex); | |
| 1532 | + for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { | |
| 1533 | + list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { | |
| 1534 | + if (net_eq(svc->net, net)) { | |
| 1535 | + list_for_each_entry(dest, &svc->destinations, | |
| 1536 | + n_list) { | |
| 1537 | + __ip_vs_dev_reset(dest, dev); | |
| 1538 | + } | |
| 1539 | + } | |
| 1540 | + } | |
| 1541 | + | |
| 1542 | + list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { | |
| 1543 | + if (net_eq(svc->net, net)) { | |
| 1544 | + list_for_each_entry(dest, &svc->destinations, | |
| 1545 | + n_list) { | |
| 1546 | + __ip_vs_dev_reset(dest, dev); | |
| 1547 | + } | |
| 1548 | + } | |
| 1549 | + | |
| 1550 | + } | |
| 1551 | + } | |
| 1552 | + | |
| 1553 | + list_for_each_entry(dest, &net_ipvs(net)->dest_trash, n_list) { | |
| 1554 | + __ip_vs_dev_reset(dest, dev); | |
| 1555 | + } | |
| 1556 | + mutex_unlock(&__ip_vs_mutex); | |
| 1557 | + LeaveFunction(2); | |
| 1558 | + return NOTIFY_DONE; | |
| 1559 | +} | |
| 1475 | 1560 | |
| 1476 | 1561 | /* |
| 1477 | 1562 | * Zero counters in a service or all services |
| @@ -3588,6 +3673,10 @@ void __net_init __ip_vs_control_cleanup_sysctl(struct net *net) { } · 2110 unmodified lines | ||
| 3588 | 3673 | |
| 3589 | 3674 | #endif |
| 3590 | 3675 | |
| 3676 | +static struct notifier_block ip_vs_dst_notifier = { | |
| 3677 | + .notifier_call = ip_vs_dst_event, | |
| 3678 | +}; | |
| 3679 | + | |
| 3591 | 3680 | int __net_init __ip_vs_control_init(struct net *net) |
| 3592 | 3681 | { |
| 3593 | 3682 | int idx; |
| @@ -3626,7 +3715,7 @@ err: · 32 unmodified lines | ||
| 3626 | 3715 | return -ENOMEM; |
| 3627 | 3716 | } |
| 3628 | 3717 | |
| 3629 | −static void __net_exit __ip_vs_control_cleanup(struct net *net) | |
| 3718 | +void __net_exit __ip_vs_control_cleanup(struct net *net) | |
| 3630 | 3719 | { |
| 3631 | 3720 | struct netns_ipvs *ipvs = net_ipvs(net); |
| 3632 | 3721 | |
| @@ -3639,11 +3728,6 @@ static void __net_exit __ip_vs_control_cleanup(struct net *net) · 6 unmodified lines | ||
| 3639 | 3728 | free_percpu(ipvs->tot_stats.cpustats); |
| 3640 | 3729 | } |
| 3641 | 3730 | |
| 3642 | −static struct pernet_operations ipvs_control_ops = { | |
| 3643 | − .init = __ip_vs_control_init, | |
| 3644 | − .exit = __ip_vs_control_cleanup, | |
| 3645 | −}; | |
| 3646 | − | |
| 3647 | 3731 | int __init ip_vs_control_init(void) |
| 3648 | 3732 | { |
| 3649 | 3733 | int idx; |
| @@ -3657,33 +3741,32 @@ int __init ip_vs_control_init(void) · 7 unmodified lines | ||
| 3657 | 3741 | INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]); |
| 3658 | 3742 | } |
| 3659 | 3743 | |
| 3660 | − ret = register_pernet_subsys(&ipvs_control_ops); | |
| 3661 | − if (ret) { | |
| 3662 | − pr_err("cannot register namespace.\n"); | |
| 3663 | − goto err; | |
| 3664 | − } | |
| 3665 | − | |
| 3666 | 3744 | smp_wmb(); /* Do we really need it now ? */ |
| 3667 | 3745 | |
| 3668 | 3746 | ret = nf_register_sockopt(&ip_vs_sockopts); |
| 3669 | 3747 | if (ret) { |
| 3670 | 3748 | pr_err("cannot register sockopt.\n"); |
| 3671 | − goto err_net; | |
| 3749 | + goto err_sock; | |
| 3672 | 3750 | } |
| 3673 | 3751 | |
| 3674 | 3752 | ret = ip_vs_genl_register(); |
| 3675 | 3753 | if (ret) { |
| 3676 | 3754 | pr_err("cannot register Generic Netlink interface.\n"); |
| 3677 | − nf_unregister_sockopt(&ip_vs_sockopts); | |
| 3678 | − goto err_net; | |
| 3755 | + goto err_genl; | |
| 3679 | 3756 | } |
| 3680 | 3757 | |
| 3758 | + ret = register_netdevice_notifier(&ip_vs_dst_notifier); | |
| 3759 | + if (ret < 0) | |
| 3760 | + goto err_notf; | |
| 3761 | + | |
| 3681 | 3762 | LeaveFunction(2); |
| 3682 | 3763 | return 0; |
| 3683 | 3764 | |
| 3684 | −err_net: | |
| 3685 | − unregister_pernet_subsys(&ipvs_control_ops); | |
| 3686 | −err: | |
| 3765 | +err_notf: | |
| 3766 | + ip_vs_genl_unregister(); | |
| 3767 | +err_genl: | |
| 3768 | + nf_unregister_sockopt(&ip_vs_sockopts); | |
| 3769 | +err_sock: | |
| 3687 | 3770 | return ret; |
| 3688 | 3771 | } |
| 3689 | 3772 | |
| @@ -3691,7 +3774,6 @@ err: · 1 unmodified line | ||
| 3691 | 3774 | void ip_vs_control_cleanup(void) |
| 3692 | 3775 | { |
| 3693 | 3776 | EnterFunction(2); |
| 3694 | − unregister_pernet_subsys(&ipvs_control_ops); | |
| 3695 | 3777 | ip_vs_genl_unregister(); |
| 3696 | 3778 | nf_unregister_sockopt(&ip_vs_sockopts); |
| 3697 | 3779 | LeaveFunction(2); |
| @@ -192,7 +192,7 @@ void ip_vs_read_estimator(struct ip_vs_stats_user *dst, · 191 unmodified lines | ||
| 192 | 192 | dst->outbps = (e->outbps + 0xF) >> 5; |
| 193 | 193 | } |
| 194 | 194 | |
| 195 | −static int __net_init __ip_vs_estimator_init(struct net *net) | |
| 195 | +int __net_init __ip_vs_estimator_init(struct net *net) | |
| 196 | 196 | { |
| 197 | 197 | struct netns_ipvs *ipvs = net_ipvs(net); |
| 198 | 198 | |
| @@ -203,24 +203,16 @@ static int __net_init __ip_vs_estimator_init(struct net *net) · 4 unmodified lines | ||
| 203 | 203 | return 0; |
| 204 | 204 | } |
| 205 | 205 | |
| 206 | −static void __net_exit __ip_vs_estimator_exit(struct net *net) | |
| 206 | +void __net_exit __ip_vs_estimator_cleanup(struct net *net) | |
| 207 | 207 | { |
| 208 | 208 | del_timer_sync(&net_ipvs(net)->est_timer); |
| 209 | 209 | } |
| 210 | −static struct pernet_operations ip_vs_app_ops = { | |
| 211 | − .init = __ip_vs_estimator_init, | |
| 212 | − .exit = __ip_vs_estimator_exit, | |
| 213 | −}; | |
| 214 | 210 | |
| 215 | 211 | int __init ip_vs_estimator_init(void) |
| 216 | 212 | { |
| 217 | − int rv; | |
| 218 | − | |
| 219 | − rv = register_pernet_subsys(&ip_vs_app_ops); | |
| 220 | − return rv; | |
| 213 | + return 0; | |
| 221 | 214 | } |
| 222 | 215 | |
| 223 | 216 | void ip_vs_estimator_cleanup(void) |
| 224 | 217 | { |
| 225 | − unregister_pernet_subsys(&ip_vs_app_ops); | |
| 226 | 218 | } |
| @@ -316,7 +316,7 @@ ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp, · 315 unmodified lines | ||
| 316 | 316 | /* |
| 317 | 317 | * per network name-space init |
| 318 | 318 | */ |
| 319 | −static int __net_init __ip_vs_protocol_init(struct net *net) | |
| 319 | +int __net_init __ip_vs_protocol_init(struct net *net) | |
| 320 | 320 | { |
| 321 | 321 | #ifdef CONFIG_IP_VS_PROTO_TCP |
| 322 | 322 | register_ip_vs_proto_netns(net, &ip_vs_protocol_tcp); |
| @@ -336,7 +336,7 @@ static int __net_init __ip_vs_protocol_init(struct net *net) · 13 unmodified lines | ||
| 336 | 336 | return 0; |
| 337 | 337 | } |
| 338 | 338 | |
| 339 | −static void __net_exit __ip_vs_protocol_cleanup(struct net *net) | |
| 339 | +void __net_exit __ip_vs_protocol_cleanup(struct net *net) | |
| 340 | 340 | { |
| 341 | 341 | struct netns_ipvs *ipvs = net_ipvs(net); |
| 342 | 342 | struct ip_vs_proto_data *pd; |
| @@ -349,11 +349,6 @@ static void __net_exit __ip_vs_protocol_cleanup(struct net *net) · 6 unmodified lines | ||
| 349 | 349 | } |
| 350 | 350 | } |
| 351 | 351 | |
| 352 | −static struct pernet_operations ipvs_proto_ops = { | |
| 353 | − .init = __ip_vs_protocol_init, | |
| 354 | − .exit = __ip_vs_protocol_cleanup, | |
| 355 | −}; | |
| 356 | − | |
| 357 | 352 | int __init ip_vs_protocol_init(void) |
| 358 | 353 | { |
| 359 | 354 | char protocols[64]; |
| @@ -382,7 +377,6 @@ int __init ip_vs_protocol_init(void) · 22 unmodified lines | ||
| 382 | 377 | REGISTER_PROTOCOL(&ip_vs_protocol_esp); |
| 383 | 378 | #endif |
| 384 | 379 | pr_info("Registered protocols (%s)\n", &protocols[2]); |
| 385 | − return register_pernet_subsys(&ipvs_proto_ops); | |
| 386 | 380 | |
| 387 | 381 | return 0; |
| 388 | 382 | } |
| @@ -393,7 +387,6 @@ void ip_vs_protocol_cleanup(void) · 4 unmodified lines | ||
| 393 | 387 | struct ip_vs_protocol *pp; |
| 394 | 388 | int i; |
| 395 | 389 | |
| 396 | − unregister_pernet_subsys(&ipvs_proto_ops); | |
| 397 | 390 | /* unregister all the ipvs protocols */ |
| 398 | 391 | for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) { |
| 399 | 392 | while ((pp = ip_vs_proto_table[i]) != NULL) |
| @@ -1303,13 +1303,18 @@ static struct socket *make_send_sock(struct net *net) · 1302 unmodified lines | ||
| 1303 | 1303 | struct socket *sock; |
| 1304 | 1304 | int result; |
| 1305 | 1305 | |
| 1306 | − /* First create a socket */ | |
| 1307 | − result = __sock_create(net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock, 1); | |
| 1306 | + /* First create a socket move it to right name space later */ | |
| 1307 | + result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock); | |
| 1308 | 1308 | if (result < 0) { |
| 1309 | 1309 | pr_err("Error during creation of socket; terminating\n"); |
| 1310 | 1310 | return ERR_PTR(result); |
| 1311 | 1311 | } |
| 1312 | − | |
| 1312 | + /* | |
| 1313 | + * Kernel sockets that are a part of a namespace, should not | |
| 1314 | + * hold a reference to a namespace in order to allow to stop it. | |
| 1315 | + * After sk_change_net should be released using sk_release_kernel. | |
| 1316 | + */ | |
| 1317 | + sk_change_net(sock->sk, net); | |
| 1313 | 1318 | result = set_mcast_if(sock->sk, ipvs->master_mcast_ifn); |
| 1314 | 1319 | if (result < 0) { |
| 1315 | 1320 | pr_err("Error setting outbound mcast interface\n"); |
| @@ -1334,8 +1339,8 @@ static struct socket *make_send_sock(struct net *net) · 18 unmodified lines | ||
| 1334 | 1339 | |
| 1335 | 1340 | return sock; |
| 1336 | 1341 | |
| 1337 | − error: | |
| 1338 | − sock_release(sock); | |
| 1342 | +error: | |
| 1343 | + sk_release_kernel(sock->sk); | |
| 1339 | 1344 | return ERR_PTR(result); |
| 1340 | 1345 | } |
| 1341 | 1346 | |
| @@ -1350,12 +1355,17 @@ static struct socket *make_receive_sock(struct net *net) · 8 unmodified lines | ||
| 1350 | 1355 | int result; |
| 1351 | 1356 | |
| 1352 | 1357 | /* First create a socket */ |
| 1353 | − result = __sock_create(net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock, 1); | |
| 1358 | + result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock); | |
| 1354 | 1359 | if (result < 0) { |
| 1355 | 1360 | pr_err("Error during creation of socket; terminating\n"); |
| 1356 | 1361 | return ERR_PTR(result); |
| 1357 | 1362 | } |
| 1358 | − | |
| 1363 | + /* | |
| 1364 | + * Kernel sockets that are a part of a namespace, should not | |
| 1365 | + * hold a reference to a namespace in order to allow to stop it. | |
| 1366 | + * After sk_change_net should be released using sk_release_kernel. | |
| 1367 | + */ | |
| 1368 | + sk_change_net(sock->sk, net); | |
| 1359 | 1369 | /* it is equivalent to the REUSEADDR option in user-space */ |
| 1360 | 1370 | sock->sk->sk_reuse = 1; |
| 1361 | 1371 | |
| @@ -1377,8 +1387,8 @@ static struct socket *make_receive_sock(struct net *net) · 15 unmodified lines | ||
| 1377 | 1387 | |
| 1378 | 1388 | return sock; |
| 1379 | 1389 | |
| 1380 | − error: | |
| 1381 | − sock_release(sock); | |
| 1390 | +error: | |
| 1391 | + sk_release_kernel(sock->sk); | |
| 1382 | 1392 | return ERR_PTR(result); |
| 1383 | 1393 | } |
| 1384 | 1394 | |
| @@ -1473,7 +1483,7 @@ static int sync_thread_master(void *data) · 88 unmodified lines | ||
| 1473 | 1483 | ip_vs_sync_buff_release(sb); |
| 1474 | 1484 | |
| 1475 | 1485 | /* release the sending multicast socket */ |
| 1476 | − sock_release(tinfo->sock); | |
| 1486 | + sk_release_kernel(tinfo->sock->sk); | |
| 1477 | 1487 | kfree(tinfo); |
| 1478 | 1488 | |
| 1479 | 1489 | return 0; |
| @@ -1513,7 +1523,7 @@ static int sync_thread_backup(void *data) · 33 unmodified lines | ||
| 1513 | 1523 | } |
| 1514 | 1524 | |
| 1515 | 1525 | /* release the sending multicast socket */ |
| 1516 | − sock_release(tinfo->sock); | |
| 1526 | + sk_release_kernel(tinfo->sock->sk); | |
| 1517 | 1527 | kfree(tinfo->buf); |
| 1518 | 1528 | kfree(tinfo); |
| 1519 | 1529 | |
| @@ -1601,7 +1611,7 @@ outtinfo: · 81 unmodified lines | ||
| 1601 | 1611 | outbuf: |
| 1602 | 1612 | kfree(buf); |
| 1603 | 1613 | outsocket: |
| 1604 | − sock_release(sock); | |
| 1614 | + sk_release_kernel(sock->sk); | |
| 1605 | 1615 | out: |
| 1606 | 1616 | return result; |
| 1607 | 1617 | } |
| @@ -1610,6 +1620,7 @@ out: · 2 unmodified lines | ||
| 1610 | 1620 | int stop_sync_thread(struct net *net, int state) |
| 1611 | 1621 | { |
| 1612 | 1622 | struct netns_ipvs *ipvs = net_ipvs(net); |
| 1623 | + int retc = -EINVAL; | |
| 1613 | 1624 | |
| 1614 | 1625 | IP_VS_DBG(7, "%s(): pid %d\n", __func__, task_pid_nr(current)); |
| 1615 | 1626 | |
| @@ -1629,7 +1640,7 @@ int stop_sync_thread(struct net *net, int state) · 13 unmodified lines | ||
| 1629 | 1640 | spin_lock_bh(&ipvs->sync_lock); |
| 1630 | 1641 | ipvs->sync_state &= ~IP_VS_STATE_MASTER; |
| 1631 | 1642 | spin_unlock_bh(&ipvs->sync_lock); |
| 1632 | − kthread_stop(ipvs->master_thread); | |
| 1643 | + retc = kthread_stop(ipvs->master_thread); | |
| 1633 | 1644 | ipvs->master_thread = NULL; |
| 1634 | 1645 | } else if (state == IP_VS_STATE_BACKUP) { |
| 1635 | 1646 | if (!ipvs->backup_thread) |
| @@ -1639,22 +1650,20 @@ int stop_sync_thread(struct net *net, int state) · 3 unmodified lines | ||
| 1639 | 1650 | task_pid_nr(ipvs->backup_thread)); |
| 1640 | 1651 | |
| 1641 | 1652 | ipvs->sync_state &= ~IP_VS_STATE_BACKUP; |
| 1642 | − kthread_stop(ipvs->backup_thread); | |
| 1653 | + retc = kthread_stop(ipvs->backup_thread); | |
| 1643 | 1654 | ipvs->backup_thread = NULL; |
| 1644 | − } else { | |
| 1645 | − return -EINVAL; | |
| 1646 | 1655 | } |
| 1647 | 1656 | |
| 1648 | 1657 | /* decrease the module use count */ |
| 1649 | 1658 | ip_vs_use_count_dec(); |
| 1650 | 1659 | |
| 1651 | − return 0; | |
| 1660 | + return retc; | |
| 1652 | 1661 | } |
| 1653 | 1662 | |
| 1654 | 1663 | /* |
| 1655 | 1664 | * Initialize data struct for each netns |
| 1656 | 1665 | */ |
| 1657 | −static int __net_init __ip_vs_sync_init(struct net *net) | |
| 1666 | +int __net_init __ip_vs_sync_init(struct net *net) | |
| 1658 | 1667 | { |
| 1659 | 1668 | struct netns_ipvs *ipvs = net_ipvs(net); |
| 1660 | 1669 | |
| @@ -1668,24 +1677,24 @@ static int __net_init __ip_vs_sync_init(struct net *net) · 7 unmodified lines | ||
| 1668 | 1677 | return 0; |
| 1669 | 1678 | } |
| 1670 | 1679 | |
| 1671 | −static void __ip_vs_sync_cleanup(struct net *net) | |
| 1680 | +void __ip_vs_sync_cleanup(struct net *net) | |
| 1672 | 1681 | { |
| 1673 | − stop_sync_thread(net, IP_VS_STATE_MASTER); | |
| 1674 | − stop_sync_thread(net, IP_VS_STATE_BACKUP); | |
| 1675 | −} | |
| 1682 | + int retc; | |
| 1676 | 1683 | |
| 1677 | −static struct pernet_operations ipvs_sync_ops = { | |
| 1678 | − .init = __ip_vs_sync_init, | |
| 1679 | − .exit = __ip_vs_sync_cleanup, | |
| 1680 | −}; | |
| 1684 | + retc = stop_sync_thread(net, IP_VS_STATE_MASTER); | |
| 1685 | + if (retc && retc != -ESRCH) | |
| 1686 | + pr_err("Failed to stop Master Daemon\n"); | |
| 1681 | 1687 | |
| 1688 | + retc = stop_sync_thread(net, IP_VS_STATE_BACKUP); | |
| 1689 | + if (retc && retc != -ESRCH) | |
| 1690 | + pr_err("Failed to stop Backup Daemon\n"); | |
| 1691 | +} | |
| 1682 | 1692 | |
| 1683 | 1693 | int __init ip_vs_sync_init(void) |
| 1684 | 1694 | { |
| 1685 | − return register_pernet_subsys(&ipvs_sync_ops); | |
| 1695 | + return 0; | |
| 1686 | 1696 | } |
| 1687 | 1697 | |
| 1688 | 1698 | void ip_vs_sync_cleanup(void) |
| 1689 | 1699 | { |
| 1690 | − unregister_pernet_subsys(&ipvs_sync_ops); | |
| 1691 | 1700 | } |
| @@ -1334,6 +1334,7 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, · 1333 unmodified lines | ||
| 1334 | 1334 | struct nf_conn *ct; |
| 1335 | 1335 | int err = -EINVAL; |
| 1336 | 1336 | struct nf_conntrack_helper *helper; |
| 1337 | + struct nf_conn_tstamp *tstamp; | |
| 1337 | 1338 | |
| 1338 | 1339 | ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC); |
| 1339 | 1340 | if (IS_ERR(ct)) |
| @@ -1451,6 +1452,9 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, · 111 unmodified lines | ||
| 1451 | 1452 | __set_bit(IPS_EXPECTED_BIT, &ct->status); |
| 1452 | 1453 | ct->master = master_ct; |
| 1453 | 1454 | } |
| 1455 | + tstamp = nf_conn_tstamp_find(ct); | |
| 1456 | + if (tstamp) | |
| 1457 | + tstamp->start = ktime_to_ns(ktime_get_real()); | |
| 1454 | 1458 | |
| 1455 | 1459 | add_timer(&ct->timeout); |
| 1456 | 1460 | nf_conntrack_hash_insert(ct); |
| @@ -455,6 +455,7 @@ void xt_compat_flush_offsets(u_int8_t af) · 454 unmodified lines | ||
| 455 | 455 | vfree(xt[af].compat_tab); |
| 456 | 456 | xt[af].compat_tab = NULL; |
| 457 | 457 | xt[af].number = 0; |
| 458 | + xt[af].cur = 0; | |
| 458 | 459 | } |
| 459 | 460 | } |
| 460 | 461 | EXPORT_SYMBOL_GPL(xt_compat_flush_offsets); |
| @@ -473,8 +474,7 @@ int xt_compat_calc_jump(u_int8_t af, unsigned int offset) · 12 unmodified lines | ||
| 473 | 474 | else |
| 474 | 475 | return mid ? tmp[mid - 1].delta : 0; |
| 475 | 476 | } |
| 476 | − WARN_ON_ONCE(1); | |
| 477 | − return 0; | |
| 477 | + return left ? tmp[left - 1].delta : 0; | |
| 478 | 478 | } |
| 479 | 479 | EXPORT_SYMBOL_GPL(xt_compat_calc_jump); |
| 480 | 480 | |
| @@ -99,7 +99,7 @@ tos_tg6(struct sk_buff *skb, const struct xt_action_param *par) · 98 unmodified lines | ||
| 99 | 99 | u_int8_t orig, nv; |
| 100 | 100 | |
| 101 | 101 | orig = ipv6_get_dsfield(iph); |
| 102 | − nv = (orig & info->tos_mask) ^ info->tos_value; | |
| 102 | + nv = (orig & ~info->tos_mask) ^ info->tos_value; | |
| 103 | 103 | |
| 104 | 104 | if (orig != nv) { |
| 105 | 105 | if (!skb_make_writable(skb, sizeof(struct iphdr))) |
| @@ -272,11 +272,6 @@ static int conntrack_mt_check(const struct xt_mtchk_param *par) · 271 unmodified lines | ||
| 272 | 272 | { |
| 273 | 273 | int ret; |
| 274 | 274 | |
| 275 | − if (strcmp(par->table, "raw") == 0) { | |
| 276 | − pr_info("state is undetermined at the time of raw table\n"); | |
| 277 | − return -EINVAL; | |
| 278 | − } | |
| 279 | − | |
| 280 | 275 | ret = nf_ct_l3proto_try_module_get(par->family); |
| 281 | 276 | if (ret < 0) |
| 282 | 277 | pr_info("cannot load conntrack support for proto=%u\n", |