diff options
Diffstat (limited to 'net/xfrm/xfrm_policy.c')
-rw-r--r-- | net/xfrm/xfrm_policy.c | 82 |
1 files changed, 47 insertions, 35 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index fcf8c928285a..e239a25e571c 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -36,11 +36,6 @@ | |||
36 | 36 | ||
37 | int sysctl_xfrm_larval_drop __read_mostly = 1; | 37 | int sysctl_xfrm_larval_drop __read_mostly = 1; |
38 | 38 | ||
39 | #ifdef CONFIG_XFRM_STATISTICS | ||
40 | DEFINE_SNMP_STAT(struct linux_xfrm_mib, xfrm_statistics) __read_mostly; | ||
41 | EXPORT_SYMBOL(xfrm_statistics); | ||
42 | #endif | ||
43 | |||
44 | DEFINE_MUTEX(xfrm_cfg_mutex); | 39 | DEFINE_MUTEX(xfrm_cfg_mutex); |
45 | EXPORT_SYMBOL(xfrm_cfg_mutex); | 40 | EXPORT_SYMBOL(xfrm_cfg_mutex); |
46 | 41 | ||
@@ -1570,7 +1565,7 @@ restart: | |||
1570 | policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl); | 1565 | policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl); |
1571 | err = PTR_ERR(policy); | 1566 | err = PTR_ERR(policy); |
1572 | if (IS_ERR(policy)) { | 1567 | if (IS_ERR(policy)) { |
1573 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLERROR); | 1568 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR); |
1574 | goto dropdst; | 1569 | goto dropdst; |
1575 | } | 1570 | } |
1576 | } | 1571 | } |
@@ -1585,7 +1580,7 @@ restart: | |||
1585 | dir, xfrm_policy_lookup); | 1580 | dir, xfrm_policy_lookup); |
1586 | err = PTR_ERR(policy); | 1581 | err = PTR_ERR(policy); |
1587 | if (IS_ERR(policy)) { | 1582 | if (IS_ERR(policy)) { |
1588 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLERROR); | 1583 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR); |
1589 | goto dropdst; | 1584 | goto dropdst; |
1590 | } | 1585 | } |
1591 | } | 1586 | } |
@@ -1608,7 +1603,7 @@ restart: | |||
1608 | default: | 1603 | default: |
1609 | case XFRM_POLICY_BLOCK: | 1604 | case XFRM_POLICY_BLOCK: |
1610 | /* Prohibit the flow */ | 1605 | /* Prohibit the flow */ |
1611 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLBLOCK); | 1606 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLBLOCK); |
1612 | err = -EPERM; | 1607 | err = -EPERM; |
1613 | goto error; | 1608 | goto error; |
1614 | 1609 | ||
@@ -1628,7 +1623,7 @@ restart: | |||
1628 | */ | 1623 | */ |
1629 | dst = xfrm_find_bundle(fl, policy, family); | 1624 | dst = xfrm_find_bundle(fl, policy, family); |
1630 | if (IS_ERR(dst)) { | 1625 | if (IS_ERR(dst)) { |
1631 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLECHECKERROR); | 1626 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR); |
1632 | err = PTR_ERR(dst); | 1627 | err = PTR_ERR(dst); |
1633 | goto error; | 1628 | goto error; |
1634 | } | 1629 | } |
@@ -1644,12 +1639,12 @@ restart: | |||
1644 | XFRM_POLICY_OUT); | 1639 | XFRM_POLICY_OUT); |
1645 | if (pols[1]) { | 1640 | if (pols[1]) { |
1646 | if (IS_ERR(pols[1])) { | 1641 | if (IS_ERR(pols[1])) { |
1647 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLERROR); | 1642 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR); |
1648 | err = PTR_ERR(pols[1]); | 1643 | err = PTR_ERR(pols[1]); |
1649 | goto error; | 1644 | goto error; |
1650 | } | 1645 | } |
1651 | if (pols[1]->action == XFRM_POLICY_BLOCK) { | 1646 | if (pols[1]->action == XFRM_POLICY_BLOCK) { |
1652 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLBLOCK); | 1647 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLBLOCK); |
1653 | err = -EPERM; | 1648 | err = -EPERM; |
1654 | goto error; | 1649 | goto error; |
1655 | } | 1650 | } |
@@ -1680,7 +1675,7 @@ restart: | |||
1680 | /* EREMOTE tells the caller to generate | 1675 | /* EREMOTE tells the caller to generate |
1681 | * a one-shot blackhole route. | 1676 | * a one-shot blackhole route. |
1682 | */ | 1677 | */ |
1683 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTNOSTATES); | 1678 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); |
1684 | xfrm_pol_put(policy); | 1679 | xfrm_pol_put(policy); |
1685 | return -EREMOTE; | 1680 | return -EREMOTE; |
1686 | } | 1681 | } |
@@ -1696,7 +1691,7 @@ restart: | |||
1696 | nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family); | 1691 | nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family); |
1697 | 1692 | ||
1698 | if (nx == -EAGAIN && signal_pending(current)) { | 1693 | if (nx == -EAGAIN && signal_pending(current)) { |
1699 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTNOSTATES); | 1694 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); |
1700 | err = -ERESTART; | 1695 | err = -ERESTART; |
1701 | goto error; | 1696 | goto error; |
1702 | } | 1697 | } |
@@ -1708,7 +1703,7 @@ restart: | |||
1708 | err = nx; | 1703 | err = nx; |
1709 | } | 1704 | } |
1710 | if (err < 0) { | 1705 | if (err < 0) { |
1711 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTNOSTATES); | 1706 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); |
1712 | goto error; | 1707 | goto error; |
1713 | } | 1708 | } |
1714 | } | 1709 | } |
@@ -1721,7 +1716,7 @@ restart: | |||
1721 | dst = xfrm_bundle_create(policy, xfrm, nx, fl, dst_orig); | 1716 | dst = xfrm_bundle_create(policy, xfrm, nx, fl, dst_orig); |
1722 | err = PTR_ERR(dst); | 1717 | err = PTR_ERR(dst); |
1723 | if (IS_ERR(dst)) { | 1718 | if (IS_ERR(dst)) { |
1724 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLEGENERROR); | 1719 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLEGENERROR); |
1725 | goto error; | 1720 | goto error; |
1726 | } | 1721 | } |
1727 | 1722 | ||
@@ -1742,9 +1737,9 @@ restart: | |||
1742 | dst_free(dst); | 1737 | dst_free(dst); |
1743 | 1738 | ||
1744 | if (pol_dead) | 1739 | if (pol_dead) |
1745 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLDEAD); | 1740 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLDEAD); |
1746 | else | 1741 | else |
1747 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLECHECKERROR); | 1742 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR); |
1748 | err = -EHOSTUNREACH; | 1743 | err = -EHOSTUNREACH; |
1749 | goto error; | 1744 | goto error; |
1750 | } | 1745 | } |
@@ -1756,7 +1751,7 @@ restart: | |||
1756 | if (unlikely(err)) { | 1751 | if (unlikely(err)) { |
1757 | write_unlock_bh(&policy->lock); | 1752 | write_unlock_bh(&policy->lock); |
1758 | dst_free(dst); | 1753 | dst_free(dst); |
1759 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLECHECKERROR); | 1754 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR); |
1760 | goto error; | 1755 | goto error; |
1761 | } | 1756 | } |
1762 | 1757 | ||
@@ -1912,7 +1907,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
1912 | fl_dir = policy_to_flow_dir(dir); | 1907 | fl_dir = policy_to_flow_dir(dir); |
1913 | 1908 | ||
1914 | if (__xfrm_decode_session(skb, &fl, family, reverse) < 0) { | 1909 | if (__xfrm_decode_session(skb, &fl, family, reverse) < 0) { |
1915 | XFRM_INC_STATS(LINUX_MIB_XFRMINHDRERROR); | 1910 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR); |
1916 | return 0; | 1911 | return 0; |
1917 | } | 1912 | } |
1918 | 1913 | ||
@@ -1925,7 +1920,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
1925 | for (i=skb->sp->len-1; i>=0; i--) { | 1920 | for (i=skb->sp->len-1; i>=0; i--) { |
1926 | struct xfrm_state *x = skb->sp->xvec[i]; | 1921 | struct xfrm_state *x = skb->sp->xvec[i]; |
1927 | if (!xfrm_selector_match(&x->sel, &fl, family)) { | 1922 | if (!xfrm_selector_match(&x->sel, &fl, family)) { |
1928 | XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEMISMATCH); | 1923 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMISMATCH); |
1929 | return 0; | 1924 | return 0; |
1930 | } | 1925 | } |
1931 | } | 1926 | } |
@@ -1935,7 +1930,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
1935 | if (sk && sk->sk_policy[dir]) { | 1930 | if (sk && sk->sk_policy[dir]) { |
1936 | pol = xfrm_sk_policy_lookup(sk, dir, &fl); | 1931 | pol = xfrm_sk_policy_lookup(sk, dir, &fl); |
1937 | if (IS_ERR(pol)) { | 1932 | if (IS_ERR(pol)) { |
1938 | XFRM_INC_STATS(LINUX_MIB_XFRMINPOLERROR); | 1933 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR); |
1939 | return 0; | 1934 | return 0; |
1940 | } | 1935 | } |
1941 | } | 1936 | } |
@@ -1945,14 +1940,14 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
1945 | xfrm_policy_lookup); | 1940 | xfrm_policy_lookup); |
1946 | 1941 | ||
1947 | if (IS_ERR(pol)) { | 1942 | if (IS_ERR(pol)) { |
1948 | XFRM_INC_STATS(LINUX_MIB_XFRMINPOLERROR); | 1943 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR); |
1949 | return 0; | 1944 | return 0; |
1950 | } | 1945 | } |
1951 | 1946 | ||
1952 | if (!pol) { | 1947 | if (!pol) { |
1953 | if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) { | 1948 | if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) { |
1954 | xfrm_secpath_reject(xerr_idx, skb, &fl); | 1949 | xfrm_secpath_reject(xerr_idx, skb, &fl); |
1955 | XFRM_INC_STATS(LINUX_MIB_XFRMINNOPOLS); | 1950 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOPOLS); |
1956 | return 0; | 1951 | return 0; |
1957 | } | 1952 | } |
1958 | return 1; | 1953 | return 1; |
@@ -1969,7 +1964,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
1969 | XFRM_POLICY_IN); | 1964 | XFRM_POLICY_IN); |
1970 | if (pols[1]) { | 1965 | if (pols[1]) { |
1971 | if (IS_ERR(pols[1])) { | 1966 | if (IS_ERR(pols[1])) { |
1972 | XFRM_INC_STATS(LINUX_MIB_XFRMINPOLERROR); | 1967 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR); |
1973 | return 0; | 1968 | return 0; |
1974 | } | 1969 | } |
1975 | pols[1]->curlft.use_time = get_seconds(); | 1970 | pols[1]->curlft.use_time = get_seconds(); |
@@ -1993,11 +1988,11 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
1993 | for (pi = 0; pi < npols; pi++) { | 1988 | for (pi = 0; pi < npols; pi++) { |
1994 | if (pols[pi] != pol && | 1989 | if (pols[pi] != pol && |
1995 | pols[pi]->action != XFRM_POLICY_ALLOW) { | 1990 | pols[pi]->action != XFRM_POLICY_ALLOW) { |
1996 | XFRM_INC_STATS(LINUX_MIB_XFRMINPOLBLOCK); | 1991 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLBLOCK); |
1997 | goto reject; | 1992 | goto reject; |
1998 | } | 1993 | } |
1999 | if (ti + pols[pi]->xfrm_nr >= XFRM_MAX_DEPTH) { | 1994 | if (ti + pols[pi]->xfrm_nr >= XFRM_MAX_DEPTH) { |
2000 | XFRM_INC_STATS(LINUX_MIB_XFRMINBUFFERERROR); | 1995 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR); |
2001 | goto reject_error; | 1996 | goto reject_error; |
2002 | } | 1997 | } |
2003 | for (i = 0; i < pols[pi]->xfrm_nr; i++) | 1998 | for (i = 0; i < pols[pi]->xfrm_nr; i++) |
@@ -2021,20 +2016,20 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
2021 | if (k < -1) | 2016 | if (k < -1) |
2022 | /* "-2 - errored_index" returned */ | 2017 | /* "-2 - errored_index" returned */ |
2023 | xerr_idx = -(2+k); | 2018 | xerr_idx = -(2+k); |
2024 | XFRM_INC_STATS(LINUX_MIB_XFRMINTMPLMISMATCH); | 2019 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINTMPLMISMATCH); |
2025 | goto reject; | 2020 | goto reject; |
2026 | } | 2021 | } |
2027 | } | 2022 | } |
2028 | 2023 | ||
2029 | if (secpath_has_nontransport(sp, k, &xerr_idx)) { | 2024 | if (secpath_has_nontransport(sp, k, &xerr_idx)) { |
2030 | XFRM_INC_STATS(LINUX_MIB_XFRMINTMPLMISMATCH); | 2025 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINTMPLMISMATCH); |
2031 | goto reject; | 2026 | goto reject; |
2032 | } | 2027 | } |
2033 | 2028 | ||
2034 | xfrm_pols_put(pols, npols); | 2029 | xfrm_pols_put(pols, npols); |
2035 | return 1; | 2030 | return 1; |
2036 | } | 2031 | } |
2037 | XFRM_INC_STATS(LINUX_MIB_XFRMINPOLBLOCK); | 2032 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLBLOCK); |
2038 | 2033 | ||
2039 | reject: | 2034 | reject: |
2040 | xfrm_secpath_reject(xerr_idx, skb, &fl); | 2035 | xfrm_secpath_reject(xerr_idx, skb, &fl); |
@@ -2051,7 +2046,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) | |||
2051 | 2046 | ||
2052 | if (xfrm_decode_session(skb, &fl, family) < 0) { | 2047 | if (xfrm_decode_session(skb, &fl, family) < 0) { |
2053 | /* XXX: we should have something like FWDHDRERROR here. */ | 2048 | /* XXX: we should have something like FWDHDRERROR here. */ |
2054 | XFRM_INC_STATS(LINUX_MIB_XFRMINHDRERROR); | 2049 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR); |
2055 | return 0; | 2050 | return 0; |
2056 | } | 2051 | } |
2057 | 2052 | ||
@@ -2380,13 +2375,27 @@ static struct notifier_block xfrm_dev_notifier = { | |||
2380 | }; | 2375 | }; |
2381 | 2376 | ||
2382 | #ifdef CONFIG_XFRM_STATISTICS | 2377 | #ifdef CONFIG_XFRM_STATISTICS |
2383 | static int __init xfrm_statistics_init(void) | 2378 | static int __net_init xfrm_statistics_init(struct net *net) |
2384 | { | 2379 | { |
2385 | if (snmp_mib_init((void **)xfrm_statistics, | 2380 | if (snmp_mib_init((void **)net->mib.xfrm_statistics, |
2386 | sizeof(struct linux_xfrm_mib)) < 0) | 2381 | sizeof(struct linux_xfrm_mib)) < 0) |
2387 | return -ENOMEM; | 2382 | return -ENOMEM; |
2388 | return 0; | 2383 | return 0; |
2389 | } | 2384 | } |
2385 | |||
2386 | static void xfrm_statistics_fini(struct net *net) | ||
2387 | { | ||
2388 | snmp_mib_free((void **)net->mib.xfrm_statistics); | ||
2389 | } | ||
2390 | #else | ||
2391 | static int __net_init xfrm_statistics_init(struct net *net) | ||
2392 | { | ||
2393 | return 0; | ||
2394 | } | ||
2395 | |||
2396 | static void xfrm_statistics_fini(struct net *net) | ||
2397 | { | ||
2398 | } | ||
2390 | #endif | 2399 | #endif |
2391 | 2400 | ||
2392 | static int __net_init xfrm_policy_init(struct net *net) | 2401 | static int __net_init xfrm_policy_init(struct net *net) |
@@ -2480,6 +2489,9 @@ static int __net_init xfrm_net_init(struct net *net) | |||
2480 | { | 2489 | { |
2481 | int rv; | 2490 | int rv; |
2482 | 2491 | ||
2492 | rv = xfrm_statistics_init(net); | ||
2493 | if (rv < 0) | ||
2494 | goto out_statistics; | ||
2483 | rv = xfrm_state_init(net); | 2495 | rv = xfrm_state_init(net); |
2484 | if (rv < 0) | 2496 | if (rv < 0) |
2485 | goto out_state; | 2497 | goto out_state; |
@@ -2491,6 +2503,8 @@ static int __net_init xfrm_net_init(struct net *net) | |||
2491 | out_policy: | 2503 | out_policy: |
2492 | xfrm_state_fini(net); | 2504 | xfrm_state_fini(net); |
2493 | out_state: | 2505 | out_state: |
2506 | xfrm_statistics_fini(net); | ||
2507 | out_statistics: | ||
2494 | return rv; | 2508 | return rv; |
2495 | } | 2509 | } |
2496 | 2510 | ||
@@ -2498,6 +2512,7 @@ static void __net_exit xfrm_net_exit(struct net *net) | |||
2498 | { | 2512 | { |
2499 | xfrm_policy_fini(net); | 2513 | xfrm_policy_fini(net); |
2500 | xfrm_state_fini(net); | 2514 | xfrm_state_fini(net); |
2515 | xfrm_statistics_fini(net); | ||
2501 | } | 2516 | } |
2502 | 2517 | ||
2503 | static struct pernet_operations __net_initdata xfrm_net_ops = { | 2518 | static struct pernet_operations __net_initdata xfrm_net_ops = { |
@@ -2508,9 +2523,6 @@ static struct pernet_operations __net_initdata xfrm_net_ops = { | |||
2508 | void __init xfrm_init(void) | 2523 | void __init xfrm_init(void) |
2509 | { | 2524 | { |
2510 | register_pernet_subsys(&xfrm_net_ops); | 2525 | register_pernet_subsys(&xfrm_net_ops); |
2511 | #ifdef CONFIG_XFRM_STATISTICS | ||
2512 | xfrm_statistics_init(); | ||
2513 | #endif | ||
2514 | xfrm_input_init(); | 2526 | xfrm_input_init(); |
2515 | #ifdef CONFIG_XFRM_STATISTICS | 2527 | #ifdef CONFIG_XFRM_STATISTICS |
2516 | xfrm_proc_init(); | 2528 | xfrm_proc_init(); |