Blame view
net/ipv4/ip_forward.c
3.9 KB
b24413180 License cleanup: ... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 5 6 7 |
/* * 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... |
8 |
* |
1da177e4c Linux-2.6.12-rc2 |
9 10 11 |
* Authors: see ip.c * * Fixes: |
e905a9eda [NET] IPV4: Fix w... |
12 |
* Many : Split from ip.c , see ip_input.c for |
1da177e4c Linux-2.6.12-rc2 |
13 |
* history. |
e905a9eda [NET] IPV4: Fix w... |
14 |
* Dave Gregorich : NULL ip_rt_put fix for multicast |
1da177e4c Linux-2.6.12-rc2 |
15 16 17 18 19 20 21 |
* 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 |
22 23 |
#include <linux/types.h> #include <linux/mm.h> |
1da177e4c Linux-2.6.12-rc2 |
24 25 26 27 |
#include <linux/skbuff.h> #include <linux/ip.h> #include <linux/icmp.h> #include <linux/netdevice.h> |
5a0e3ad6a include cleanup: ... |
28 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
29 30 31 32 33 34 35 36 37 38 39 40 |
#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> |
fe6cc55f3 net: ip, ipv6: ha... |
41 42 |
static bool ip_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) { |
ca6c5d4ad net: ipv4: ip_for... |
43 |
if (skb->len <= mtu) |
fe6cc55f3 net: ip, ipv6: ha... |
44 |
return false; |
cf8262443 ip: reject too-bi... |
45 46 47 48 49 50 51 52 53 |
if (unlikely((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0)) return false; /* original fragment exceeds mtu and DF is set */ if (unlikely(IPCB(skb)->frag_max_size > mtu)) return true; if (skb->ignore_df) return false; |
ae7ef81ef skbuff: introduce... |
54 |
if (skb_is_gso(skb) && skb_gso_validate_mtu(skb, mtu)) |
fe6cc55f3 net: ip, ipv6: ha... |
55 56 57 58 |
return false; return true; } |
fe6cc55f3 net: ip, ipv6: ha... |
59 |
|
0c4b51f00 netfilter: Pass n... |
60 |
static int ip_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb) |
1da177e4c Linux-2.6.12-rc2 |
61 |
{ |
5e73ea1a3 ipv4: fix checkpa... |
62 |
struct ip_options *opt = &(IPCB(skb)->opt); |
1da177e4c Linux-2.6.12-rc2 |
63 |
|
b45386efa net: rename IP_IN... |
64 |
__IP_INC_STATS(net, IPSTATS_MIB_OUTFORWDATAGRAMS); |
98f619957 net: rename IP_AD... |
65 |
__IP_ADD_STATS(net, IPSTATS_MIB_OUTOCTETS, skb->len); |
1da177e4c Linux-2.6.12-rc2 |
66 67 68 |
if (unlikely(opt->optlen)) ip_forward_options(skb); |
13206b6bf net: Pass net int... |
69 |
return dst_output(net, sk, skb); |
1da177e4c Linux-2.6.12-rc2 |
70 71 72 73 |
} int ip_forward(struct sk_buff *skb) { |
f87c10a8a ipv4: introduce i... |
74 |
u32 mtu; |
1da177e4c Linux-2.6.12-rc2 |
75 76 |
struct iphdr *iph; /* Our header */ struct rtable *rt; /* Route we use */ |
5e73ea1a3 ipv4: fix checkpa... |
77 |
struct ip_options *opt = &(IPCB(skb)->opt); |
fcad0ac2d ipv4: Compute net... |
78 |
struct net *net; |
1da177e4c Linux-2.6.12-rc2 |
79 |
|
d4f2fa6ad ipv4: ip_forward:... |
80 81 82 |
/* that should never happen */ if (skb->pkt_type != PACKET_HOST) goto drop; |
2ab957492 ip_forward: Drop ... |
83 84 |
if (unlikely(skb->sk)) goto drop; |
4497b0763 net: Discard and ... |
85 86 |
if (skb_warn_if_lro(skb)) goto drop; |
1da177e4c Linux-2.6.12-rc2 |
87 88 89 90 91 |
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; |
35fc92a9d [NET]: Allow forw... |
92 |
skb_forward_csum(skb); |
fcad0ac2d ipv4: Compute net... |
93 |
net = dev_net(skb->dev); |
e905a9eda [NET] IPV4: Fix w... |
94 |
|
1da177e4c Linux-2.6.12-rc2 |
95 96 97 98 99 |
/* * 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... |
100 |
if (ip_hdr(skb)->ttl <= 1) |
e905a9eda [NET] IPV4: Fix w... |
101 |
goto too_many_hops; |
1da177e4c Linux-2.6.12-rc2 |
102 103 104 |
if (!xfrm4_route_forward(skb)) goto drop; |
511c3f92a net: skb->rtable ... |
105 |
rt = skb_rtable(skb); |
1da177e4c Linux-2.6.12-rc2 |
106 |
|
155e8336c ipv4: introduce r... |
107 |
if (opt->is_strictroute && rt->rt_uses_gateway) |
1da177e4c Linux-2.6.12-rc2 |
108 |
goto sr_failed; |
9ee6c5dc8 ipv4: allow local... |
109 |
IPCB(skb)->flags |= IPSKB_FORWARDED; |
f87c10a8a ipv4: introduce i... |
110 |
mtu = ip_dst_mtu_maybe_forward(&rt->dst, true); |
cf8262443 ip: reject too-bi... |
111 |
if (ip_exceeds_mtu(skb, mtu)) { |
fcad0ac2d ipv4: Compute net... |
112 |
IP_INC_STATS(net, IPSTATS_MIB_FRAGFAILS); |
9af3912ec [NET] Move DF che... |
113 |
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, |
f87c10a8a ipv4: introduce i... |
114 |
htonl(mtu)); |
9af3912ec [NET] Move DF che... |
115 116 |
goto drop; } |
1da177e4c Linux-2.6.12-rc2 |
117 |
/* We are about to mangle packet. Copy it! */ |
d8d1f30b9 net-next: remove ... |
118 |
if (skb_cow(skb, LL_RESERVED_SPACE(rt->dst.dev)+rt->dst.header_len)) |
1da177e4c Linux-2.6.12-rc2 |
119 |
goto drop; |
eddc9ec53 [SK_BUFF]: Introd... |
120 |
iph = ip_hdr(skb); |
1da177e4c Linux-2.6.12-rc2 |
121 122 123 124 125 126 127 128 |
/* Decrease ttl after skb cow done */ ip_decrease_ttl(iph); /* * We now generate an ICMP HOST REDIRECT giving the route * we calculated. */ |
df4d92549 ipv4: try to cach... |
129 130 |
if (IPCB(skb)->flags & IPSKB_DOREDIRECT && !opt->srr && !skb_sec_path(skb)) |
1da177e4c Linux-2.6.12-rc2 |
131 132 133 |
ip_rt_send_redirect(skb); skb->priority = rt_tos2priority(iph->tos); |
29a26a568 netfilter: Pass s... |
134 135 136 |
return NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD, net, NULL, skb, skb->dev, rt->dst.dev, ip_forward_finish); |
1da177e4c Linux-2.6.12-rc2 |
137 138 |
sr_failed: |
e905a9eda [NET] IPV4: Fix w... |
139 |
/* |
1da177e4c Linux-2.6.12-rc2 |
140 141 |
* Strict routing permits no gatewaying */ |
e905a9eda [NET] IPV4: Fix w... |
142 143 |
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0); goto drop; |
1da177e4c Linux-2.6.12-rc2 |
144 145 |
too_many_hops: |
e905a9eda [NET] IPV4: Fix w... |
146 |
/* Tell the sender its packet died... */ |
b45386efa net: rename IP_IN... |
147 |
__IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS); |
e905a9eda [NET] IPV4: Fix w... |
148 |
icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0); |
1da177e4c Linux-2.6.12-rc2 |
149 150 151 152 |
drop: kfree_skb(skb); return NET_RX_DROP; } |