Skip to content

Commit

Permalink
[INET]: Introduce inet_sk_rebuild_header
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Arnaldo Carvalho de Melo authored and David S. Miller committed Aug 29, 2005
1 parent 6cbb0df commit 32519f1
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 105 deletions.
2 changes: 2 additions & 0 deletions include/linux/ip.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ static inline void inet_sk_copy_descendant(struct sock *sk_to,
#endif
#endif

extern int inet_sk_rebuild_header(struct sock *sk);

struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
Expand Down
2 changes: 0 additions & 2 deletions include/net/tcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -799,8 +799,6 @@ extern void tcp_parse_options(struct sk_buff *skb,
* TCP v4 functions exported for the inet6 API
*/

extern int tcp_v4_rebuild_header(struct sock *sk);

extern int tcp_v4_build_header(struct sock *sk,
struct sk_buff *skb);

Expand Down
113 changes: 113 additions & 0 deletions net/ipv4/af_inet.c
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,119 @@ void inet_unregister_protosw(struct inet_protosw *p)
}
}

/*
* Shall we try to damage output packets if routing dev changes?
*/

int sysctl_ip_dynaddr;

static int inet_sk_reselect_saddr(struct sock *sk)
{
struct inet_sock *inet = inet_sk(sk);
int err;
struct rtable *rt;
__u32 old_saddr = inet->saddr;
__u32 new_saddr;
__u32 daddr = inet->daddr;

if (inet->opt && inet->opt->srr)
daddr = inet->opt->faddr;

/* Query new route. */
err = ip_route_connect(&rt, daddr, 0,
RT_CONN_FLAGS(sk),
sk->sk_bound_dev_if,
sk->sk_protocol,
inet->sport, inet->dport, sk);
if (err)
return err;

sk_setup_caps(sk, &rt->u.dst);

new_saddr = rt->rt_src;

if (new_saddr == old_saddr)
return 0;

if (sysctl_ip_dynaddr > 1) {
printk(KERN_INFO "%s(): shifting inet->"
"saddr from %d.%d.%d.%d to %d.%d.%d.%d\n",
__FUNCTION__,
NIPQUAD(old_saddr),
NIPQUAD(new_saddr));
}

inet->saddr = inet->rcv_saddr = new_saddr;

/*
* XXX The only one ugly spot where we need to
* XXX really change the sockets identity after
* XXX it has entered the hashes. -DaveM
*
* Besides that, it does not check for connection
* uniqueness. Wait for troubles.
*/
__sk_prot_rehash(sk);
return 0;
}

int inet_sk_rebuild_header(struct sock *sk)
{
struct inet_sock *inet = inet_sk(sk);
struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0);
u32 daddr;
int err;

/* Route is OK, nothing to do. */
if (rt)
return 0;

/* Reroute. */
daddr = inet->daddr;
if (inet->opt && inet->opt->srr)
daddr = inet->opt->faddr;
{
struct flowi fl = {
.oif = sk->sk_bound_dev_if,
.nl_u = {
.ip4_u = {
.daddr = daddr,
.saddr = inet->saddr,
.tos = RT_CONN_FLAGS(sk),
},
},
.proto = sk->sk_protocol,
.uli_u = {
.ports = {
.sport = inet->sport,
.dport = inet->dport,
},
},
};

err = ip_route_output_flow(&rt, &fl, sk, 0);
}
if (!err)
sk_setup_caps(sk, &rt->u.dst);
else {
/* Routing failed... */
sk->sk_route_caps = 0;
/*
* Other protocols have to map its equivalent state to TCP_SYN_SENT.
* DCCP maps its DCCP_REQUESTING state to TCP_SYN_SENT. -acme
*/
if (!sysctl_ip_dynaddr ||
sk->sk_state != TCP_SYN_SENT ||
(sk->sk_userlocks & SOCK_BINDADDR_LOCK) ||
(err = inet_sk_reselect_saddr(sk)) != 0)
sk->sk_err_soft = -err;
}

return err;
}

EXPORT_SYMBOL(inet_sk_rebuild_header);

#ifdef CONFIG_IP_MULTICAST
static struct net_protocol igmp_protocol = {
.handler = igmp_rcv,
Expand Down
5 changes: 0 additions & 5 deletions net/ipv4/ip_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,6 @@
#include <linux/netlink.h>
#include <linux/tcp.h>

/*
* Shall we try to damage output packets if routing dev changes?
*/

int sysctl_ip_dynaddr;
int sysctl_ip_default_ttl = IPDEFTTL;

/* Generate a checksum for an outgoing IP datagram. */
Expand Down
98 changes: 1 addition & 97 deletions net/ipv4/tcp_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -1832,101 +1832,6 @@ int tcp_v4_rcv(struct sk_buff *skb)
goto discard_it;
}

static int tcp_v4_reselect_saddr(struct sock *sk)
{
struct inet_sock *inet = inet_sk(sk);
int err;
struct rtable *rt;
__u32 old_saddr = inet->saddr;
__u32 new_saddr;
__u32 daddr = inet->daddr;

if (inet->opt && inet->opt->srr)
daddr = inet->opt->faddr;

/* Query new route. */
err = ip_route_connect(&rt, daddr, 0,
RT_CONN_FLAGS(sk),
sk->sk_bound_dev_if,
IPPROTO_TCP,
inet->sport, inet->dport, sk);
if (err)
return err;

sk_setup_caps(sk, &rt->u.dst);

new_saddr = rt->rt_src;

if (new_saddr == old_saddr)
return 0;

if (sysctl_ip_dynaddr > 1) {
printk(KERN_INFO "tcp_v4_rebuild_header(): shifting inet->"
"saddr from %d.%d.%d.%d to %d.%d.%d.%d\n",
NIPQUAD(old_saddr),
NIPQUAD(new_saddr));
}

inet->saddr = new_saddr;
inet->rcv_saddr = new_saddr;

/* XXX The only one ugly spot where we need to
* XXX really change the sockets identity after
* XXX it has entered the hashes. -DaveM
*
* Besides that, it does not check for connection
* uniqueness. Wait for troubles.
*/
__sk_prot_rehash(sk);
return 0;
}

int tcp_v4_rebuild_header(struct sock *sk)
{
struct inet_sock *inet = inet_sk(sk);
struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0);
u32 daddr;
int err;

/* Route is OK, nothing to do. */
if (rt)
return 0;

/* Reroute. */
daddr = inet->daddr;
if (inet->opt && inet->opt->srr)
daddr = inet->opt->faddr;

{
struct flowi fl = { .oif = sk->sk_bound_dev_if,
.nl_u = { .ip4_u =
{ .daddr = daddr,
.saddr = inet->saddr,
.tos = RT_CONN_FLAGS(sk) } },
.proto = IPPROTO_TCP,
.uli_u = { .ports =
{ .sport = inet->sport,
.dport = inet->dport } } };

err = ip_route_output_flow(&rt, &fl, sk, 0);
}
if (!err) {
sk_setup_caps(sk, &rt->u.dst);
return 0;
}

/* Routing failed... */
sk->sk_route_caps = 0;

if (!sysctl_ip_dynaddr ||
sk->sk_state != TCP_SYN_SENT ||
(sk->sk_userlocks & SOCK_BINDADDR_LOCK) ||
(err = tcp_v4_reselect_saddr(sk)) != 0)
sk->sk_err_soft = -err;

return err;
}

static void v4_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr)
{
struct sockaddr_in *sin = (struct sockaddr_in *) uaddr;
Expand Down Expand Up @@ -1998,7 +1903,7 @@ int tcp_v4_tw_remember_stamp(struct tcp_tw_bucket *tw)
struct tcp_func ipv4_specific = {
.queue_xmit = ip_queue_xmit,
.send_check = tcp_v4_send_check,
.rebuild_header = tcp_v4_rebuild_header,
.rebuild_header = inet_sk_rebuild_header,
.conn_request = tcp_v4_conn_request,
.syn_recv_sock = tcp_v4_syn_recv_sock,
.remember_stamp = tcp_v4_remember_stamp,
Expand Down Expand Up @@ -2630,7 +2535,6 @@ EXPORT_SYMBOL(tcp_unhash);
EXPORT_SYMBOL(tcp_v4_conn_request);
EXPORT_SYMBOL(tcp_v4_connect);
EXPORT_SYMBOL(tcp_v4_do_rcv);
EXPORT_SYMBOL(tcp_v4_rebuild_header);
EXPORT_SYMBOL(tcp_v4_remember_stamp);
EXPORT_SYMBOL(tcp_v4_send_check);
EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
Expand Down
2 changes: 1 addition & 1 deletion net/ipv6/tcp_ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -1983,7 +1983,7 @@ static struct tcp_func ipv6_specific = {
static struct tcp_func ipv6_mapped = {
.queue_xmit = ip_queue_xmit,
.send_check = tcp_v4_send_check,
.rebuild_header = tcp_v4_rebuild_header,
.rebuild_header = inet_sk_rebuild_header,
.conn_request = tcp_v6_conn_request,
.syn_recv_sock = tcp_v6_syn_recv_sock,
.remember_stamp = tcp_v4_remember_stamp,
Expand Down

0 comments on commit 32519f1

Please sign in to comment.