~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to net/ipv4/cipso_ipv4.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
112
112
/* The maximum number of category ranges permitted in the ranged category tag
113
113
 * (tag #5).  You may note that the IETF draft states that the maximum number
114
114
 * of category ranges is 7, but if the low end of the last category range is
115
 
 * zero then it is possibile to fit 8 category ranges because the zero should
 
115
 * zero then it is possible to fit 8 category ranges because the zero should
116
116
 * be omitted. */
117
117
#define CIPSO_V4_TAG_RNG_CAT_MAX      8
118
118
 
438
438
 *
439
439
 * Description:
440
440
 * Search the DOI definition list for a DOI definition with a DOI value that
441
 
 * matches @doi.  The caller is responsibile for calling rcu_read_[un]lock().
 
441
 * matches @doi.  The caller is responsible for calling rcu_read_[un]lock().
442
442
 * Returns a pointer to the DOI definition on success and NULL on failure.
443
443
 */
444
444
static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi)
1293
1293
                        return ret_val;
1294
1294
 
1295
1295
                /* This will send packets using the "optimized" format when
1296
 
                 * possibile as specified in  section 3.4.2.6 of the
 
1296
                 * possible as specified in  section 3.4.2.6 of the
1297
1297
                 * CIPSO draft. */
1298
1298
                if (cipso_v4_rbm_optfmt && ret_val > 0 && ret_val <= 10)
1299
1299
                        tag_len = 14;
1752
1752
}
1753
1753
 
1754
1754
/**
1755
 
 * cipso_v4_error - Send the correct reponse for a bad packet
 
1755
 * cipso_v4_error - Send the correct response for a bad packet
1756
1756
 * @skb: the packet
1757
1757
 * @error: the error code
1758
1758
 * @gateway: CIPSO gateway flag
1857
1857
        return CIPSO_V4_HDR_LEN + ret_val;
1858
1858
}
1859
1859
 
 
1860
static void opt_kfree_rcu(struct rcu_head *head)
 
1861
{
 
1862
        kfree(container_of(head, struct ip_options_rcu, rcu));
 
1863
}
 
1864
 
1860
1865
/**
1861
1866
 * cipso_v4_sock_setattr - Add a CIPSO option to a socket
1862
1867
 * @sk: the socket
1879
1884
        unsigned char *buf = NULL;
1880
1885
        u32 buf_len;
1881
1886
        u32 opt_len;
1882
 
        struct ip_options *opt = NULL;
 
1887
        struct ip_options_rcu *old, *opt = NULL;
1883
1888
        struct inet_sock *sk_inet;
1884
1889
        struct inet_connection_sock *sk_conn;
1885
1890
 
1915
1920
                ret_val = -ENOMEM;
1916
1921
                goto socket_setattr_failure;
1917
1922
        }
1918
 
        memcpy(opt->__data, buf, buf_len);
1919
 
        opt->optlen = opt_len;
1920
 
        opt->cipso = sizeof(struct iphdr);
 
1923
        memcpy(opt->opt.__data, buf, buf_len);
 
1924
        opt->opt.optlen = opt_len;
 
1925
        opt->opt.cipso = sizeof(struct iphdr);
1921
1926
        kfree(buf);
1922
1927
        buf = NULL;
1923
1928
 
1924
1929
        sk_inet = inet_sk(sk);
 
1930
 
 
1931
        old = rcu_dereference_protected(sk_inet->inet_opt, sock_owned_by_user(sk));
1925
1932
        if (sk_inet->is_icsk) {
1926
1933
                sk_conn = inet_csk(sk);
1927
 
                if (sk_inet->opt)
1928
 
                        sk_conn->icsk_ext_hdr_len -= sk_inet->opt->optlen;
1929
 
                sk_conn->icsk_ext_hdr_len += opt->optlen;
 
1934
                if (old)
 
1935
                        sk_conn->icsk_ext_hdr_len -= old->opt.optlen;
 
1936
                sk_conn->icsk_ext_hdr_len += opt->opt.optlen;
1930
1937
                sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
1931
1938
        }
1932
 
        opt = xchg(&sk_inet->opt, opt);
1933
 
        kfree(opt);
 
1939
        rcu_assign_pointer(sk_inet->inet_opt, opt);
 
1940
        if (old)
 
1941
                call_rcu(&old->rcu, opt_kfree_rcu);
1934
1942
 
1935
1943
        return 0;
1936
1944
 
1960
1968
        unsigned char *buf = NULL;
1961
1969
        u32 buf_len;
1962
1970
        u32 opt_len;
1963
 
        struct ip_options *opt = NULL;
 
1971
        struct ip_options_rcu *opt = NULL;
1964
1972
        struct inet_request_sock *req_inet;
1965
1973
 
1966
1974
        /* We allocate the maximum CIPSO option size here so we are probably
1988
1996
                ret_val = -ENOMEM;
1989
1997
                goto req_setattr_failure;
1990
1998
        }
1991
 
        memcpy(opt->__data, buf, buf_len);
1992
 
        opt->optlen = opt_len;
1993
 
        opt->cipso = sizeof(struct iphdr);
 
1999
        memcpy(opt->opt.__data, buf, buf_len);
 
2000
        opt->opt.optlen = opt_len;
 
2001
        opt->opt.cipso = sizeof(struct iphdr);
1994
2002
        kfree(buf);
1995
2003
        buf = NULL;
1996
2004
 
1997
2005
        req_inet = inet_rsk(req);
1998
2006
        opt = xchg(&req_inet->opt, opt);
1999
 
        kfree(opt);
 
2007
        if (opt)
 
2008
                call_rcu(&opt->rcu, opt_kfree_rcu);
2000
2009
 
2001
2010
        return 0;
2002
2011
 
2016
2025
 * values on failure.
2017
2026
 *
2018
2027
 */
2019
 
static int cipso_v4_delopt(struct ip_options **opt_ptr)
 
2028
static int cipso_v4_delopt(struct ip_options_rcu **opt_ptr)
2020
2029
{
2021
2030
        int hdr_delta = 0;
2022
 
        struct ip_options *opt = *opt_ptr;
 
2031
        struct ip_options_rcu *opt = *opt_ptr;
2023
2032
 
2024
 
        if (opt->srr || opt->rr || opt->ts || opt->router_alert) {
 
2033
        if (opt->opt.srr || opt->opt.rr || opt->opt.ts || opt->opt.router_alert) {
2025
2034
                u8 cipso_len;
2026
2035
                u8 cipso_off;
2027
2036
                unsigned char *cipso_ptr;
2028
2037
                int iter;
2029
2038
                int optlen_new;
2030
2039
 
2031
 
                cipso_off = opt->cipso - sizeof(struct iphdr);
2032
 
                cipso_ptr = &opt->__data[cipso_off];
 
2040
                cipso_off = opt->opt.cipso - sizeof(struct iphdr);
 
2041
                cipso_ptr = &opt->opt.__data[cipso_off];
2033
2042
                cipso_len = cipso_ptr[1];
2034
2043
 
2035
 
                if (opt->srr > opt->cipso)
2036
 
                        opt->srr -= cipso_len;
2037
 
                if (opt->rr > opt->cipso)
2038
 
                        opt->rr -= cipso_len;
2039
 
                if (opt->ts > opt->cipso)
2040
 
                        opt->ts -= cipso_len;
2041
 
                if (opt->router_alert > opt->cipso)
2042
 
                        opt->router_alert -= cipso_len;
2043
 
                opt->cipso = 0;
 
2044
                if (opt->opt.srr > opt->opt.cipso)
 
2045
                        opt->opt.srr -= cipso_len;
 
2046
                if (opt->opt.rr > opt->opt.cipso)
 
2047
                        opt->opt.rr -= cipso_len;
 
2048
                if (opt->opt.ts > opt->opt.cipso)
 
2049
                        opt->opt.ts -= cipso_len;
 
2050
                if (opt->opt.router_alert > opt->opt.cipso)
 
2051
                        opt->opt.router_alert -= cipso_len;
 
2052
                opt->opt.cipso = 0;
2044
2053
 
2045
2054
                memmove(cipso_ptr, cipso_ptr + cipso_len,
2046
 
                        opt->optlen - cipso_off - cipso_len);
 
2055
                        opt->opt.optlen - cipso_off - cipso_len);
2047
2056
 
2048
2057
                /* determining the new total option length is tricky because of
2049
2058
                 * the padding necessary, the only thing i can think to do at
2052
2061
                 * from there we can determine the new total option length */
2053
2062
                iter = 0;
2054
2063
                optlen_new = 0;
2055
 
                while (iter < opt->optlen)
2056
 
                        if (opt->__data[iter] != IPOPT_NOP) {
2057
 
                                iter += opt->__data[iter + 1];
 
2064
                while (iter < opt->opt.optlen)
 
2065
                        if (opt->opt.__data[iter] != IPOPT_NOP) {
 
2066
                                iter += opt->opt.__data[iter + 1];
2058
2067
                                optlen_new = iter;
2059
2068
                        } else
2060
2069
                                iter++;
2061
 
                hdr_delta = opt->optlen;
2062
 
                opt->optlen = (optlen_new + 3) & ~3;
2063
 
                hdr_delta -= opt->optlen;
 
2070
                hdr_delta = opt->opt.optlen;
 
2071
                opt->opt.optlen = (optlen_new + 3) & ~3;
 
2072
                hdr_delta -= opt->opt.optlen;
2064
2073
        } else {
2065
2074
                /* only the cipso option was present on the socket so we can
2066
2075
                 * remove the entire option struct */
2067
2076
                *opt_ptr = NULL;
2068
 
                hdr_delta = opt->optlen;
2069
 
                kfree(opt);
 
2077
                hdr_delta = opt->opt.optlen;
 
2078
                call_rcu(&opt->rcu, opt_kfree_rcu);
2070
2079
        }
2071
2080
 
2072
2081
        return hdr_delta;
2083
2092
void cipso_v4_sock_delattr(struct sock *sk)
2084
2093
{
2085
2094
        int hdr_delta;
2086
 
        struct ip_options *opt;
 
2095
        struct ip_options_rcu *opt;
2087
2096
        struct inet_sock *sk_inet;
2088
2097
 
2089
2098
        sk_inet = inet_sk(sk);
2090
 
        opt = sk_inet->opt;
2091
 
        if (opt == NULL || opt->cipso == 0)
 
2099
        opt = rcu_dereference_protected(sk_inet->inet_opt, 1);
 
2100
        if (opt == NULL || opt->opt.cipso == 0)
2092
2101
                return;
2093
2102
 
2094
 
        hdr_delta = cipso_v4_delopt(&sk_inet->opt);
 
2103
        hdr_delta = cipso_v4_delopt(&sk_inet->inet_opt);
2095
2104
        if (sk_inet->is_icsk && hdr_delta > 0) {
2096
2105
                struct inet_connection_sock *sk_conn = inet_csk(sk);
2097
2106
                sk_conn->icsk_ext_hdr_len -= hdr_delta;
2109
2118
 */
2110
2119
void cipso_v4_req_delattr(struct request_sock *req)
2111
2120
{
2112
 
        struct ip_options *opt;
 
2121
        struct ip_options_rcu *opt;
2113
2122
        struct inet_request_sock *req_inet;
2114
2123
 
2115
2124
        req_inet = inet_rsk(req);
2116
2125
        opt = req_inet->opt;
2117
 
        if (opt == NULL || opt->cipso == 0)
 
2126
        if (opt == NULL || opt->opt.cipso == 0)
2118
2127
                return;
2119
2128
 
2120
2129
        cipso_v4_delopt(&req_inet->opt);
2184
2193
 */
2185
2194
int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
2186
2195
{
2187
 
        struct ip_options *opt;
2188
 
 
2189
 
        opt = inet_sk(sk)->opt;
2190
 
        if (opt == NULL || opt->cipso == 0)
2191
 
                return -ENOMSG;
2192
 
 
2193
 
        return cipso_v4_getattr(opt->__data + opt->cipso - sizeof(struct iphdr),
2194
 
                                secattr);
 
2196
        struct ip_options_rcu *opt;
 
2197
        int res = -ENOMSG;
 
2198
 
 
2199
        rcu_read_lock();
 
2200
        opt = rcu_dereference(inet_sk(sk)->inet_opt);
 
2201
        if (opt && opt->opt.cipso)
 
2202
                res = cipso_v4_getattr(opt->opt.__data +
 
2203
                                                opt->opt.cipso -
 
2204
                                                sizeof(struct iphdr),
 
2205
                                       secattr);
 
2206
        rcu_read_unlock();
 
2207
        return res;
2195
2208
}
2196
2209
 
2197
2210
/**