aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ip.h2
-rw-r--r--include/net/tcp.h2
-rw-r--r--net/ipv4/af_inet.c113
-rw-r--r--net/ipv4/ip_output.c5
-rw-r--r--net/ipv4/tcp_ipv4.c98
-rw-r--r--net/ipv6/tcp_ipv6.c2
6 files changed, 117 insertions, 105 deletions
diff --git a/include/linux/ip.h b/include/linux/ip.h
index 31e7cedd9f84..33e8a19a1a0f 100644
--- a/include/linux/ip.h
+++ b/include/linux/ip.h
@@ -196,6 +196,8 @@ static inline void inet_sk_copy_descendant(struct sock *sk_to,
196#endif 196#endif
197#endif 197#endif
198 198
199extern int inet_sk_rebuild_header(struct sock *sk);
200
199struct iphdr { 201struct iphdr {
200#if defined(__LITTLE_ENDIAN_BITFIELD) 202#if defined(__LITTLE_ENDIAN_BITFIELD)
201 __u8 ihl:4, 203 __u8 ihl:4,
diff --git a/include/net/tcp.h b/include/net/tcp.h
index d95661a3aeeb..0c769adb0463 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -799,8 +799,6 @@ extern void tcp_parse_options(struct sk_buff *skb,
799 * TCP v4 functions exported for the inet6 API 799 * TCP v4 functions exported for the inet6 API
800 */ 800 */
801 801
802extern int tcp_v4_rebuild_header(struct sock *sk);
803
804extern int tcp_v4_build_header(struct sock *sk, 802extern int tcp_v4_build_header(struct sock *sk,
805 struct sk_buff *skb); 803 struct sk_buff *skb);
806 804
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 9e83d7773d8f..7137e6420d66 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -951,6 +951,119 @@ void inet_unregister_protosw(struct inet_protosw *p)
951 } 951 }
952} 952}
953 953
954/*
955 * Shall we try to damage output packets if routing dev changes?
956 */
957
958int sysctl_ip_dynaddr;
959
960static int inet_sk_reselect_saddr(struct sock *sk)
961{
962 struct inet_sock *inet = inet_sk(sk);
963 int err;
964 struct rtable *rt;
965 __u32 old_saddr = inet->saddr;
966 __u32 new_saddr;
967 __u32 daddr = inet->daddr;
968
969 if (inet->opt && inet->opt->srr)
970 daddr = inet->opt->faddr;
971
972 /* Query new route. */
973 err = ip_route_connect(&rt, daddr, 0,
974 RT_CONN_FLAGS(sk),
975 sk->sk_bound_dev_if,
976 sk->sk_protocol,
977 inet->sport, inet->dport, sk);
978 if (err)
979 return err;
980
981 sk_setup_caps(sk, &rt->u.dst);
982
983 new_saddr = rt->rt_src;
984
985 if (new_saddr == old_saddr)
986 return 0;
987
988 if (sysctl_ip_dynaddr > 1) {
989 printk(KERN_INFO "%s(): shifting inet->"
990 "saddr from %d.%d.%d.%d to %d.%d.%d.%d\n",
991 __FUNCTION__,
992 NIPQUAD(old_saddr),
993 NIPQUAD(new_saddr));
994 }
995
996 inet->saddr = inet->rcv_saddr = new_saddr;
997
998 /*
999 * XXX The only one ugly spot where we need to
1000 * XXX really change the sockets identity after
1001 * XXX it has entered the hashes. -DaveM
1002 *
1003 * Besides that, it does not check for connection
1004 * uniqueness. Wait for troubles.
1005 */
1006 __sk_prot_rehash(sk);
1007 return 0;
1008}
1009
1010int inet_sk_rebuild_header(struct sock *sk)
1011{
1012 struct inet_sock *inet = inet_sk(sk);
1013 struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0);
1014 u32 daddr;
1015 int err;
1016
1017 /* Route is OK, nothing to do. */
1018 if (rt)
1019 return 0;
1020
1021 /* Reroute. */
1022 daddr = inet->daddr;
1023 if (inet->opt && inet->opt->srr)
1024 daddr = inet->opt->faddr;
1025{
1026 struct flowi fl = {
1027 .oif = sk->sk_bound_dev_if,
1028 .nl_u = {
1029 .ip4_u = {
1030 .daddr = daddr,
1031 .saddr = inet->saddr,
1032 .tos = RT_CONN_FLAGS(sk),
1033 },
1034 },
1035 .proto = sk->sk_protocol,
1036 .uli_u = {
1037 .ports = {
1038 .sport = inet->sport,
1039 .dport = inet->dport,
1040 },
1041 },
1042 };
1043
1044 err = ip_route_output_flow(&rt, &fl, sk, 0);
1045}
1046 if (!err)
1047 sk_setup_caps(sk, &rt->u.dst);
1048 else {
1049 /* Routing failed... */
1050 sk->sk_route_caps = 0;
1051 /*
1052 * Other protocols have to map its equivalent state to TCP_SYN_SENT.
1053 * DCCP maps its DCCP_REQUESTING state to TCP_SYN_SENT. -acme
1054 */
1055 if (!sysctl_ip_dynaddr ||
1056 sk->sk_state != TCP_SYN_SENT ||
1057 (sk->sk_userlocks & SOCK_BINDADDR_LOCK) ||
1058 (err = inet_sk_reselect_saddr(sk)) != 0)
1059 sk->sk_err_soft = -err;
1060 }
1061
1062 return err;
1063}
1064
1065EXPORT_SYMBOL(inet_sk_rebuild_header);
1066
954#ifdef CONFIG_IP_MULTICAST 1067#ifdef CONFIG_IP_MULTICAST
955static struct net_protocol igmp_protocol = { 1068static struct net_protocol igmp_protocol = {
956 .handler = igmp_rcv, 1069 .handler = igmp_rcv,
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index c72fc878f06d..dd568b0b7062 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -83,11 +83,6 @@
83#include <linux/netlink.h> 83#include <linux/netlink.h>
84#include <linux/tcp.h> 84#include <linux/tcp.h>
85 85
86/*
87 * Shall we try to damage output packets if routing dev changes?
88 */
89
90int sysctl_ip_dynaddr;
91int sysctl_ip_default_ttl = IPDEFTTL; 86int sysctl_ip_default_ttl = IPDEFTTL;
92 87
93/* Generate a checksum for an outgoing IP datagram. */ 88/* Generate a checksum for an outgoing IP datagram. */
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 4a5daecbd2ac..ae6fad99a9a9 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1832,101 +1832,6 @@ do_time_wait:
1832 goto discard_it; 1832 goto discard_it;
1833} 1833}
1834 1834
1835static int tcp_v4_reselect_saddr(struct sock *sk)
1836{
1837 struct inet_sock *inet = inet_sk(sk);
1838 int err;
1839 struct rtable *rt;
1840 __u32 old_saddr = inet->saddr;
1841 __u32 new_saddr;
1842 __u32 daddr = inet->daddr;
1843
1844 if (inet->opt && inet->opt->srr)
1845 daddr = inet->opt->faddr;
1846
1847 /* Query new route. */
1848 err = ip_route_connect(&rt, daddr, 0,
1849 RT_CONN_FLAGS(sk),
1850 sk->sk_bound_dev_if,
1851 IPPROTO_TCP,
1852 inet->sport, inet->dport, sk);
1853 if (err)
1854 return err;
1855
1856 sk_setup_caps(sk, &rt->u.dst);
1857
1858 new_saddr = rt->rt_src;
1859
1860 if (new_saddr == old_saddr)
1861 return 0;
1862
1863 if (sysctl_ip_dynaddr > 1) {
1864 printk(KERN_INFO "tcp_v4_rebuild_header(): shifting inet->"
1865 "saddr from %d.%d.%d.%d to %d.%d.%d.%d\n",
1866 NIPQUAD(old_saddr),
1867 NIPQUAD(new_saddr));
1868 }
1869
1870 inet->saddr = new_saddr;
1871 inet->rcv_saddr = new_saddr;
1872
1873 /* XXX The only one ugly spot where we need to
1874 * XXX really change the sockets identity after
1875 * XXX it has entered the hashes. -DaveM
1876 *
1877 * Besides that, it does not check for connection
1878 * uniqueness. Wait for troubles.
1879 */
1880 __sk_prot_rehash(sk);
1881 return 0;
1882}
1883
1884int tcp_v4_rebuild_header(struct sock *sk)
1885{
1886 struct inet_sock *inet = inet_sk(sk);
1887 struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0);
1888 u32 daddr;
1889 int err;
1890
1891 /* Route is OK, nothing to do. */
1892 if (rt)
1893 return 0;
1894
1895 /* Reroute. */
1896 daddr = inet->daddr;
1897 if (inet->opt && inet->opt->srr)
1898 daddr = inet->opt->faddr;
1899
1900 {
1901 struct flowi fl = { .oif = sk->sk_bound_dev_if,
1902 .nl_u = { .ip4_u =
1903 { .daddr = daddr,
1904 .saddr = inet->saddr,
1905 .tos = RT_CONN_FLAGS(sk) } },
1906 .proto = IPPROTO_TCP,
1907 .uli_u = { .ports =
1908 { .sport = inet->sport,
1909 .dport = inet->dport } } };
1910
1911 err = ip_route_output_flow(&rt, &fl, sk, 0);
1912 }
1913 if (!err) {
1914 sk_setup_caps(sk, &rt->u.dst);
1915 return 0;
1916 }
1917
1918 /* Routing failed... */
1919 sk->sk_route_caps = 0;
1920
1921 if (!sysctl_ip_dynaddr ||
1922 sk->sk_state != TCP_SYN_SENT ||
1923 (sk->sk_userlocks & SOCK_BINDADDR_LOCK) ||
1924 (err = tcp_v4_reselect_saddr(sk)) != 0)
1925 sk->sk_err_soft = -err;
1926
1927 return err;
1928}
1929
1930static void v4_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr) 1835static void v4_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr)
1931{ 1836{
1932 struct sockaddr_in *sin = (struct sockaddr_in *) uaddr; 1837 struct sockaddr_in *sin = (struct sockaddr_in *) uaddr;
@@ -1998,7 +1903,7 @@ int tcp_v4_tw_remember_stamp(struct tcp_tw_bucket *tw)
1998struct tcp_func ipv4_specific = { 1903struct tcp_func ipv4_specific = {
1999 .queue_xmit = ip_queue_xmit, 1904 .queue_xmit = ip_queue_xmit,
2000 .send_check = tcp_v4_send_check, 1905 .send_check = tcp_v4_send_check,
2001 .rebuild_header = tcp_v4_rebuild_header, 1906 .rebuild_header = inet_sk_rebuild_header,
2002 .conn_request = tcp_v4_conn_request, 1907 .conn_request = tcp_v4_conn_request,
2003 .syn_recv_sock = tcp_v4_syn_recv_sock, 1908 .syn_recv_sock = tcp_v4_syn_recv_sock,
2004 .remember_stamp = tcp_v4_remember_stamp, 1909 .remember_stamp = tcp_v4_remember_stamp,
@@ -2630,7 +2535,6 @@ EXPORT_SYMBOL(tcp_unhash);
2630EXPORT_SYMBOL(tcp_v4_conn_request); 2535EXPORT_SYMBOL(tcp_v4_conn_request);
2631EXPORT_SYMBOL(tcp_v4_connect); 2536EXPORT_SYMBOL(tcp_v4_connect);
2632EXPORT_SYMBOL(tcp_v4_do_rcv); 2537EXPORT_SYMBOL(tcp_v4_do_rcv);
2633EXPORT_SYMBOL(tcp_v4_rebuild_header);
2634EXPORT_SYMBOL(tcp_v4_remember_stamp); 2538EXPORT_SYMBOL(tcp_v4_remember_stamp);
2635EXPORT_SYMBOL(tcp_v4_send_check); 2539EXPORT_SYMBOL(tcp_v4_send_check);
2636EXPORT_SYMBOL(tcp_v4_syn_recv_sock); 2540EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 885e05bd99f6..4e32a8496be3 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1983,7 +1983,7 @@ static struct tcp_func ipv6_specific = {
1983static struct tcp_func ipv6_mapped = { 1983static struct tcp_func ipv6_mapped = {
1984 .queue_xmit = ip_queue_xmit, 1984 .queue_xmit = ip_queue_xmit,
1985 .send_check = tcp_v4_send_check, 1985 .send_check = tcp_v4_send_check,
1986 .rebuild_header = tcp_v4_rebuild_header, 1986 .rebuild_header = inet_sk_rebuild_header,
1987 .conn_request = tcp_v6_conn_request, 1987 .conn_request = tcp_v6_conn_request,
1988 .syn_recv_sock = tcp_v6_syn_recv_sock, 1988 .syn_recv_sock = tcp_v6_syn_recv_sock,
1989 .remember_stamp = tcp_v4_remember_stamp, 1989 .remember_stamp = tcp_v4_remember_stamp,