aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_policy.c
diff options
context:
space:
mode:
authorMasahide NAKAMURA <nakam@linux-ipv6.org>2007-12-20 23:43:36 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:59:39 -0500
commit0aa647746e5602e608220c10e51f49709a030f5d (patch)
tree514cde2ddf6308b0f1dfd83039cb8dd62b2c69d2 /net/xfrm/xfrm_policy.c
parent558f82ef6e0d25e87f7468c07b6db1fbbf95a855 (diff)
[XFRM]: Support to increment packet dropping statistics.
Signed-off-by: Masahide NAKAMURA <nakam@linux-ipv6.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/xfrm/xfrm_policy.c')
-rw-r--r--net/xfrm/xfrm_policy.c63
1 files changed, 51 insertions, 12 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 32ddb7b12e7f..74807a7d3d69 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1494,8 +1494,10 @@ restart:
1494 if (sk && sk->sk_policy[XFRM_POLICY_OUT]) { 1494 if (sk && sk->sk_policy[XFRM_POLICY_OUT]) {
1495 policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl); 1495 policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
1496 err = PTR_ERR(policy); 1496 err = PTR_ERR(policy);
1497 if (IS_ERR(policy)) 1497 if (IS_ERR(policy)) {
1498 XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLERROR);
1498 goto dropdst; 1499 goto dropdst;
1500 }
1499 } 1501 }
1500 1502
1501 if (!policy) { 1503 if (!policy) {
@@ -1529,6 +1531,7 @@ restart:
1529 default: 1531 default:
1530 case XFRM_POLICY_BLOCK: 1532 case XFRM_POLICY_BLOCK:
1531 /* Prohibit the flow */ 1533 /* Prohibit the flow */
1534 XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLBLOCK);
1532 err = -EPERM; 1535 err = -EPERM;
1533 goto error; 1536 goto error;
1534 1537
@@ -1548,6 +1551,7 @@ restart:
1548 */ 1551 */
1549 dst = xfrm_find_bundle(fl, policy, family); 1552 dst = xfrm_find_bundle(fl, policy, family);
1550 if (IS_ERR(dst)) { 1553 if (IS_ERR(dst)) {
1554 XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLECHECKERROR);
1551 err = PTR_ERR(dst); 1555 err = PTR_ERR(dst);
1552 goto error; 1556 goto error;
1553 } 1557 }
@@ -1562,10 +1566,12 @@ restart:
1562 XFRM_POLICY_OUT); 1566 XFRM_POLICY_OUT);
1563 if (pols[1]) { 1567 if (pols[1]) {
1564 if (IS_ERR(pols[1])) { 1568 if (IS_ERR(pols[1])) {
1569 XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLERROR);
1565 err = PTR_ERR(pols[1]); 1570 err = PTR_ERR(pols[1]);
1566 goto error; 1571 goto error;
1567 } 1572 }
1568 if (pols[1]->action == XFRM_POLICY_BLOCK) { 1573 if (pols[1]->action == XFRM_POLICY_BLOCK) {
1574 XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLBLOCK);
1569 err = -EPERM; 1575 err = -EPERM;
1570 goto error; 1576 goto error;
1571 } 1577 }
@@ -1611,6 +1617,7 @@ restart:
1611 nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family); 1617 nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family);
1612 1618
1613 if (nx == -EAGAIN && signal_pending(current)) { 1619 if (nx == -EAGAIN && signal_pending(current)) {
1620 XFRM_INC_STATS(LINUX_MIB_XFRMOUTNOSTATES);
1614 err = -ERESTART; 1621 err = -ERESTART;
1615 goto error; 1622 goto error;
1616 } 1623 }
@@ -1621,8 +1628,10 @@ restart:
1621 } 1628 }
1622 err = nx; 1629 err = nx;
1623 } 1630 }
1624 if (err < 0) 1631 if (err < 0) {
1632 XFRM_INC_STATS(LINUX_MIB_XFRMOUTNOSTATES);
1625 goto error; 1633 goto error;
1634 }
1626 } 1635 }
1627 if (nx == 0) { 1636 if (nx == 0) {
1628 /* Flow passes not transformed. */ 1637 /* Flow passes not transformed. */
@@ -1632,8 +1641,10 @@ restart:
1632 1641
1633 dst = xfrm_bundle_create(policy, xfrm, nx, fl, dst_orig); 1642 dst = xfrm_bundle_create(policy, xfrm, nx, fl, dst_orig);
1634 err = PTR_ERR(dst); 1643 err = PTR_ERR(dst);
1635 if (IS_ERR(dst)) 1644 if (IS_ERR(dst)) {
1645 XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLEGENERROR);
1636 goto error; 1646 goto error;
1647 }
1637 1648
1638 for (pi = 0; pi < npols; pi++) { 1649 for (pi = 0; pi < npols; pi++) {
1639 read_lock_bh(&pols[pi]->lock); 1650 read_lock_bh(&pols[pi]->lock);
@@ -1652,6 +1663,10 @@ restart:
1652 if (dst) 1663 if (dst)
1653 dst_free(dst); 1664 dst_free(dst);
1654 1665
1666 if (pol_dead)
1667 XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLDEAD);
1668 else
1669 XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLECHECKERROR);
1655 err = -EHOSTUNREACH; 1670 err = -EHOSTUNREACH;
1656 goto error; 1671 goto error;
1657 } 1672 }
@@ -1664,6 +1679,7 @@ restart:
1664 write_unlock_bh(&policy->lock); 1679 write_unlock_bh(&policy->lock);
1665 if (dst) 1680 if (dst)
1666 dst_free(dst); 1681 dst_free(dst);
1682 XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLECHECKERROR);
1667 goto error; 1683 goto error;
1668 } 1684 }
1669 1685
@@ -1817,8 +1833,11 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
1817 dir &= XFRM_POLICY_MASK; 1833 dir &= XFRM_POLICY_MASK;
1818 fl_dir = policy_to_flow_dir(dir); 1834 fl_dir = policy_to_flow_dir(dir);
1819 1835
1820 if (__xfrm_decode_session(skb, &fl, family, reverse) < 0) 1836 if (__xfrm_decode_session(skb, &fl, family, reverse) < 0) {
1837 XFRM_INC_STATS(LINUX_MIB_XFRMINHDRERROR);
1821 return 0; 1838 return 0;
1839 }
1840
1822 nf_nat_decode_session(skb, &fl, family); 1841 nf_nat_decode_session(skb, &fl, family);
1823 1842
1824 /* First, check used SA against their selectors. */ 1843 /* First, check used SA against their selectors. */
@@ -1827,28 +1846,35 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
1827 1846
1828 for (i=skb->sp->len-1; i>=0; i--) { 1847 for (i=skb->sp->len-1; i>=0; i--) {
1829 struct xfrm_state *x = skb->sp->xvec[i]; 1848 struct xfrm_state *x = skb->sp->xvec[i];
1830 if (!xfrm_selector_match(&x->sel, &fl, family)) 1849 if (!xfrm_selector_match(&x->sel, &fl, family)) {
1850 XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEMISMATCH);
1831 return 0; 1851 return 0;
1852 }
1832 } 1853 }
1833 } 1854 }
1834 1855
1835 pol = NULL; 1856 pol = NULL;
1836 if (sk && sk->sk_policy[dir]) { 1857 if (sk && sk->sk_policy[dir]) {
1837 pol = xfrm_sk_policy_lookup(sk, dir, &fl); 1858 pol = xfrm_sk_policy_lookup(sk, dir, &fl);
1838 if (IS_ERR(pol)) 1859 if (IS_ERR(pol)) {
1860 XFRM_INC_STATS(LINUX_MIB_XFRMINPOLERROR);
1839 return 0; 1861 return 0;
1862 }
1840 } 1863 }
1841 1864
1842 if (!pol) 1865 if (!pol)
1843 pol = flow_cache_lookup(&fl, family, fl_dir, 1866 pol = flow_cache_lookup(&fl, family, fl_dir,
1844 xfrm_policy_lookup); 1867 xfrm_policy_lookup);
1845 1868
1846 if (IS_ERR(pol)) 1869 if (IS_ERR(pol)) {
1870 XFRM_INC_STATS(LINUX_MIB_XFRMINPOLERROR);
1847 return 0; 1871 return 0;
1872 }
1848 1873
1849 if (!pol) { 1874 if (!pol) {
1850 if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) { 1875 if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) {
1851 xfrm_secpath_reject(xerr_idx, skb, &fl); 1876 xfrm_secpath_reject(xerr_idx, skb, &fl);
1877 XFRM_INC_STATS(LINUX_MIB_XFRMINNOPOLS);
1852 return 0; 1878 return 0;
1853 } 1879 }
1854 return 1; 1880 return 1;
@@ -1864,8 +1890,10 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
1864 &fl, family, 1890 &fl, family,
1865 XFRM_POLICY_IN); 1891 XFRM_POLICY_IN);
1866 if (pols[1]) { 1892 if (pols[1]) {
1867 if (IS_ERR(pols[1])) 1893 if (IS_ERR(pols[1])) {
1894 XFRM_INC_STATS(LINUX_MIB_XFRMINPOLERROR);
1868 return 0; 1895 return 0;
1896 }
1869 pols[1]->curlft.use_time = get_seconds(); 1897 pols[1]->curlft.use_time = get_seconds();
1870 npols ++; 1898 npols ++;
1871 } 1899 }
@@ -1886,10 +1914,14 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
1886 1914
1887 for (pi = 0; pi < npols; pi++) { 1915 for (pi = 0; pi < npols; pi++) {
1888 if (pols[pi] != pol && 1916 if (pols[pi] != pol &&
1889 pols[pi]->action != XFRM_POLICY_ALLOW) 1917 pols[pi]->action != XFRM_POLICY_ALLOW) {
1918 XFRM_INC_STATS(LINUX_MIB_XFRMINPOLBLOCK);
1890 goto reject; 1919 goto reject;
1891 if (ti + pols[pi]->xfrm_nr >= XFRM_MAX_DEPTH) 1920 }
1921 if (ti + pols[pi]->xfrm_nr >= XFRM_MAX_DEPTH) {
1922 XFRM_INC_STATS(LINUX_MIB_XFRMINBUFFERERROR);
1892 goto reject_error; 1923 goto reject_error;
1924 }
1893 for (i = 0; i < pols[pi]->xfrm_nr; i++) 1925 for (i = 0; i < pols[pi]->xfrm_nr; i++)
1894 tpp[ti++] = &pols[pi]->xfrm_vec[i]; 1926 tpp[ti++] = &pols[pi]->xfrm_vec[i];
1895 } 1927 }
@@ -1911,16 +1943,20 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
1911 if (k < -1) 1943 if (k < -1)
1912 /* "-2 - errored_index" returned */ 1944 /* "-2 - errored_index" returned */
1913 xerr_idx = -(2+k); 1945 xerr_idx = -(2+k);
1946 XFRM_INC_STATS(LINUX_MIB_XFRMINTMPLMISMATCH);
1914 goto reject; 1947 goto reject;
1915 } 1948 }
1916 } 1949 }
1917 1950
1918 if (secpath_has_nontransport(sp, k, &xerr_idx)) 1951 if (secpath_has_nontransport(sp, k, &xerr_idx)) {
1952 XFRM_INC_STATS(LINUX_MIB_XFRMINTMPLMISMATCH);
1919 goto reject; 1953 goto reject;
1954 }
1920 1955
1921 xfrm_pols_put(pols, npols); 1956 xfrm_pols_put(pols, npols);
1922 return 1; 1957 return 1;
1923 } 1958 }
1959 XFRM_INC_STATS(LINUX_MIB_XFRMINPOLBLOCK);
1924 1960
1925reject: 1961reject:
1926 xfrm_secpath_reject(xerr_idx, skb, &fl); 1962 xfrm_secpath_reject(xerr_idx, skb, &fl);
@@ -1934,8 +1970,11 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
1934{ 1970{
1935 struct flowi fl; 1971 struct flowi fl;
1936 1972
1937 if (xfrm_decode_session(skb, &fl, family) < 0) 1973 if (xfrm_decode_session(skb, &fl, family) < 0) {
1974 /* XXX: we should have something like FWDHDRERROR here. */
1975 XFRM_INC_STATS(LINUX_MIB_XFRMINHDRERROR);
1938 return 0; 1976 return 0;
1977 }
1939 1978
1940 return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0; 1979 return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0;
1941} 1980}