aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/cipso_ipv4.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/cipso_ipv4.c')
-rw-r--r--net/ipv4/cipso_ipv4.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index e13d6dbb66ab..23768b9d6b64 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -1810,6 +1810,80 @@ socket_setattr_failure:
1810} 1810}
1811 1811
1812/** 1812/**
1813 * cipso_v4_sock_delattr - Delete the CIPSO option from a socket
1814 * @sk: the socket
1815 *
1816 * Description:
1817 * Removes the CIPSO option from a socket, if present.
1818 *
1819 */
1820void cipso_v4_sock_delattr(struct sock *sk)
1821{
1822 u8 hdr_delta;
1823 struct ip_options *opt;
1824 struct inet_sock *sk_inet;
1825
1826 sk_inet = inet_sk(sk);
1827 opt = sk_inet->opt;
1828 if (opt == NULL || opt->cipso == 0)
1829 return;
1830
1831 if (opt->srr || opt->rr || opt->ts || opt->router_alert) {
1832 u8 cipso_len;
1833 u8 cipso_off;
1834 unsigned char *cipso_ptr;
1835 int iter;
1836 int optlen_new;
1837
1838 cipso_off = opt->cipso - sizeof(struct iphdr);
1839 cipso_ptr = &opt->__data[cipso_off];
1840 cipso_len = cipso_ptr[1];
1841
1842 if (opt->srr > opt->cipso)
1843 opt->srr -= cipso_len;
1844 if (opt->rr > opt->cipso)
1845 opt->rr -= cipso_len;
1846 if (opt->ts > opt->cipso)
1847 opt->ts -= cipso_len;
1848 if (opt->router_alert > opt->cipso)
1849 opt->router_alert -= cipso_len;
1850 opt->cipso = 0;
1851
1852 memmove(cipso_ptr, cipso_ptr + cipso_len,
1853 opt->optlen - cipso_off - cipso_len);
1854
1855 /* determining the new total option length is tricky because of
1856 * the padding necessary, the only thing i can think to do at
1857 * this point is walk the options one-by-one, skipping the
1858 * padding at the end to determine the actual option size and
1859 * from there we can determine the new total option length */
1860 iter = 0;
1861 optlen_new = 0;
1862 while (iter < opt->optlen)
1863 if (opt->__data[iter] != IPOPT_NOP) {
1864 iter += opt->__data[iter + 1];
1865 optlen_new = iter;
1866 } else
1867 iter++;
1868 hdr_delta = opt->optlen;
1869 opt->optlen = (optlen_new + 3) & ~3;
1870 hdr_delta -= opt->optlen;
1871 } else {
1872 /* only the cipso option was present on the socket so we can
1873 * remove the entire option struct */
1874 sk_inet->opt = NULL;
1875 hdr_delta = opt->optlen;
1876 kfree(opt);
1877 }
1878
1879 if (sk_inet->is_icsk && hdr_delta > 0) {
1880 struct inet_connection_sock *sk_conn = inet_csk(sk);
1881 sk_conn->icsk_ext_hdr_len -= hdr_delta;
1882 sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
1883 }
1884}
1885
1886/**
1813 * cipso_v4_getattr - Helper function for the cipso_v4_*_getattr functions 1887 * cipso_v4_getattr - Helper function for the cipso_v4_*_getattr functions
1814 * @cipso: the CIPSO v4 option 1888 * @cipso: the CIPSO v4 option
1815 * @secattr: the security attributes 1889 * @secattr: the security attributes