diff options
| author | Arnaldo Carvalho de Melo <acme@ghostprotocols.net> | 2005-08-09 22:50:02 -0400 |
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 18:37:55 -0400 |
| commit | 32519f11d38ea8f4f60896763bacec7db1760f9c (patch) | |
| tree | 9e3fe09e4f7468f119350d80a6ecb8d871a86dd0 /net/ipv4 | |
| parent | 6cbb0df788b90777a7ed0f9d8261260353f48076 (diff) | |
[INET]: Introduce inet_sk_rebuild_header
From tcp_v4_rebuild_header, that already was pretty generic, I only
needed to use sk->sk_protocol instead of the hardcoded IPPROTO_TCP and
establish the requirement that INET transport layer protocols that
want to use this function map TCP_SYN_SENT to its equivalent state.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
| -rw-r--r-- | net/ipv4/af_inet.c | 113 | ||||
| -rw-r--r-- | net/ipv4/ip_output.c | 5 | ||||
| -rw-r--r-- | net/ipv4/tcp_ipv4.c | 98 |
3 files changed, 114 insertions, 102 deletions
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 | |||
| 958 | int sysctl_ip_dynaddr; | ||
| 959 | |||
| 960 | static 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 | |||
| 1010 | int 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 | |||
| 1065 | EXPORT_SYMBOL(inet_sk_rebuild_header); | ||
| 1066 | |||
| 954 | #ifdef CONFIG_IP_MULTICAST | 1067 | #ifdef CONFIG_IP_MULTICAST |
| 955 | static struct net_protocol igmp_protocol = { | 1068 | static 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 | |||
| 90 | int sysctl_ip_dynaddr; | ||
| 91 | int sysctl_ip_default_ttl = IPDEFTTL; | 86 | int 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 | ||
| 1835 | static 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 | |||
| 1884 | int 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 | |||
| 1930 | static void v4_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr) | 1835 | static 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) | |||
| 1998 | struct tcp_func ipv4_specific = { | 1903 | struct 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); | |||
| 2630 | EXPORT_SYMBOL(tcp_v4_conn_request); | 2535 | EXPORT_SYMBOL(tcp_v4_conn_request); |
| 2631 | EXPORT_SYMBOL(tcp_v4_connect); | 2536 | EXPORT_SYMBOL(tcp_v4_connect); |
| 2632 | EXPORT_SYMBOL(tcp_v4_do_rcv); | 2537 | EXPORT_SYMBOL(tcp_v4_do_rcv); |
| 2633 | EXPORT_SYMBOL(tcp_v4_rebuild_header); | ||
| 2634 | EXPORT_SYMBOL(tcp_v4_remember_stamp); | 2538 | EXPORT_SYMBOL(tcp_v4_remember_stamp); |
| 2635 | EXPORT_SYMBOL(tcp_v4_send_check); | 2539 | EXPORT_SYMBOL(tcp_v4_send_check); |
| 2636 | EXPORT_SYMBOL(tcp_v4_syn_recv_sock); | 2540 | EXPORT_SYMBOL(tcp_v4_syn_recv_sock); |
