Blame view
net/ipv4/ip_forward.c
3.29 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 |
/* * INET An implementation of the TCP/IP protocol suite for the LINUX * operating system. INET is implemented using the BSD Socket * interface as the means of communication with the user level. * * The IP forwarding functionality. |
e905a9eda [NET] IPV4: Fix w... |
7 |
* |
1da177e4c Linux-2.6.12-rc2 |
8 9 10 |
* Authors: see ip.c * * Fixes: |
e905a9eda [NET] IPV4: Fix w... |
11 |
* Many : Split from ip.c , see ip_input.c for |
1da177e4c Linux-2.6.12-rc2 |
12 |
* history. |
e905a9eda [NET] IPV4: Fix w... |
13 |
* Dave Gregorich : NULL ip_rt_put fix for multicast |
1da177e4c Linux-2.6.12-rc2 |
14 15 16 17 18 19 20 |
* routing. * Jos Vos : Add call_out_firewall before sending, * use output device for accounting. * Jos Vos : Call forward firewall after routing * (always use output device). * Mike McLagan : Routing by source */ |
1da177e4c Linux-2.6.12-rc2 |
21 22 |
#include <linux/types.h> #include <linux/mm.h> |
1da177e4c Linux-2.6.12-rc2 |
23 24 25 26 |
#include <linux/skbuff.h> #include <linux/ip.h> #include <linux/icmp.h> #include <linux/netdevice.h> |
5a0e3ad6a include cleanup: ... |
27 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
28 29 30 31 32 33 34 35 36 37 38 39 |
#include <net/sock.h> #include <net/ip.h> #include <net/tcp.h> #include <net/udp.h> #include <net/icmp.h> #include <linux/tcp.h> #include <linux/udp.h> #include <linux/netfilter_ipv4.h> #include <net/checksum.h> #include <linux/route.h> #include <net/route.h> #include <net/xfrm.h> |
861d04860 [IPV4]: Uninline ... |
40 |
static int ip_forward_finish(struct sk_buff *skb) |
1da177e4c Linux-2.6.12-rc2 |
41 42 |
{ struct ip_options * opt = &(IPCB(skb)->opt); |
adf30907d net: skb->dst acc... |
43 |
IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS); |
1da177e4c Linux-2.6.12-rc2 |
44 45 46 47 48 49 50 51 52 53 54 55 |
if (unlikely(opt->optlen)) ip_forward_options(skb); return dst_output(skb); } int ip_forward(struct sk_buff *skb) { struct iphdr *iph; /* Our header */ struct rtable *rt; /* Route we use */ struct ip_options * opt = &(IPCB(skb)->opt); |
4497b0763 net: Discard and ... |
56 57 |
if (skb_warn_if_lro(skb)) goto drop; |
1da177e4c Linux-2.6.12-rc2 |
58 59 60 61 62 63 64 65 |
if (!xfrm4_policy_check(NULL, XFRM_POLICY_FWD, skb)) goto drop; if (IPCB(skb)->opt.router_alert && ip_call_ra_chain(skb)) return NET_RX_SUCCESS; if (skb->pkt_type != PACKET_HOST) goto drop; |
35fc92a9d [NET]: Allow forw... |
66 |
skb_forward_csum(skb); |
e905a9eda [NET] IPV4: Fix w... |
67 |
|
1da177e4c Linux-2.6.12-rc2 |
68 69 70 71 72 |
/* * According to the RFC, we must first decrease the TTL field. If * that reaches zero, we must reply an ICMP control message telling * that the packet's lifetime expired. */ |
eddc9ec53 [SK_BUFF]: Introd... |
73 |
if (ip_hdr(skb)->ttl <= 1) |
e905a9eda [NET] IPV4: Fix w... |
74 |
goto too_many_hops; |
1da177e4c Linux-2.6.12-rc2 |
75 76 77 |
if (!xfrm4_route_forward(skb)) goto drop; |
511c3f92a net: skb->rtable ... |
78 |
rt = skb_rtable(skb); |
1da177e4c Linux-2.6.12-rc2 |
79 |
|
ac8a48106 ipv4: Save nextho... |
80 |
if (opt->is_strictroute && opt->nexthop != rt->rt_gateway) |
1da177e4c Linux-2.6.12-rc2 |
81 |
goto sr_failed; |
d8d1f30b9 net-next: remove ... |
82 |
if (unlikely(skb->len > dst_mtu(&rt->dst) && !skb_is_gso(skb) && |
9c681b43f [NET] IPV4: Fix w... |
83 |
(ip_hdr(skb)->frag_off & htons(IP_DF))) && !skb->local_df) { |
d8d1f30b9 net-next: remove ... |
84 |
IP_INC_STATS(dev_net(rt->dst.dev), IPSTATS_MIB_FRAGFAILS); |
9af3912ec [NET] Move DF che... |
85 |
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, |
d8d1f30b9 net-next: remove ... |
86 |
htonl(dst_mtu(&rt->dst))); |
9af3912ec [NET] Move DF che... |
87 88 |
goto drop; } |
1da177e4c Linux-2.6.12-rc2 |
89 |
/* We are about to mangle packet. Copy it! */ |
d8d1f30b9 net-next: remove ... |
90 |
if (skb_cow(skb, LL_RESERVED_SPACE(rt->dst.dev)+rt->dst.header_len)) |
1da177e4c Linux-2.6.12-rc2 |
91 |
goto drop; |
eddc9ec53 [SK_BUFF]: Introd... |
92 |
iph = ip_hdr(skb); |
1da177e4c Linux-2.6.12-rc2 |
93 94 95 96 97 98 99 100 |
/* Decrease ttl after skb cow done */ ip_decrease_ttl(iph); /* * We now generate an ICMP HOST REDIRECT giving the route * we calculated. */ |
def8b4faf net: reduce struc... |
101 |
if (rt->rt_flags&RTCF_DOREDIRECT && !opt->srr && !skb_sec_path(skb)) |
1da177e4c Linux-2.6.12-rc2 |
102 103 104 |
ip_rt_send_redirect(skb); skb->priority = rt_tos2priority(iph->tos); |
9bbc768aa netfilter: ipv4: ... |
105 |
return NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD, skb, skb->dev, |
d8d1f30b9 net-next: remove ... |
106 |
rt->dst.dev, ip_forward_finish); |
1da177e4c Linux-2.6.12-rc2 |
107 108 |
sr_failed: |
e905a9eda [NET] IPV4: Fix w... |
109 |
/* |
1da177e4c Linux-2.6.12-rc2 |
110 111 |
* Strict routing permits no gatewaying */ |
e905a9eda [NET] IPV4: Fix w... |
112 113 |
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0); goto drop; |
1da177e4c Linux-2.6.12-rc2 |
114 115 |
too_many_hops: |
e905a9eda [NET] IPV4: Fix w... |
116 |
/* Tell the sender its packet died... */ |
adf30907d net: skb->dst acc... |
117 |
IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_INHDRERRORS); |
e905a9eda [NET] IPV4: Fix w... |
118 |
icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0); |
1da177e4c Linux-2.6.12-rc2 |
119 120 121 122 |
drop: kfree_skb(skb); return NET_RX_DROP; } |