Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /*
3 : * INET An implementation of the TCP/IP protocol suite for the LINUX
4 : * operating system. INET is implemented using the BSD Socket
5 : * interface as the means of communication with the user level.
6 : *
7 : * The IP forwarding functionality.
8 : *
9 : * Authors: see ip.c
10 : *
11 : * Fixes:
12 : * Many : Split from ip.c , see ip_input.c for
13 : * history.
14 : * Dave Gregorich : NULL ip_rt_put fix for multicast
15 : * routing.
16 : * Jos Vos : Add call_out_firewall before sending,
17 : * use output device for accounting.
18 : * Jos Vos : Call forward firewall after routing
19 : * (always use output device).
20 : * Mike McLagan : Routing by source
21 : */
22 :
23 : #include <linux/types.h>
24 : #include <linux/mm.h>
25 : #include <linux/skbuff.h>
26 : #include <linux/ip.h>
27 : #include <linux/icmp.h>
28 : #include <linux/netdevice.h>
29 : #include <linux/slab.h>
30 : #include <net/sock.h>
31 : #include <net/ip.h>
32 : #include <net/tcp.h>
33 : #include <net/udp.h>
34 : #include <net/icmp.h>
35 : #include <linux/tcp.h>
36 : #include <linux/udp.h>
37 : #include <linux/netfilter_ipv4.h>
38 : #include <net/checksum.h>
39 : #include <linux/route.h>
40 : #include <net/route.h>
41 : #include <net/xfrm.h>
42 :
43 0 : static bool ip_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu)
44 : {
45 0 : if (skb->len <= mtu)
46 : return false;
47 :
48 0 : if (unlikely((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0))
49 : return false;
50 :
51 : /* original fragment exceeds mtu and DF is set */
52 0 : if (unlikely(IPCB(skb)->frag_max_size > mtu))
53 : return true;
54 :
55 0 : if (skb->ignore_df)
56 : return false;
57 :
58 0 : if (skb_is_gso(skb) && skb_gso_validate_network_len(skb, mtu))
59 0 : return false;
60 :
61 : return true;
62 : }
63 :
64 :
65 0 : static int ip_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
66 : {
67 0 : struct ip_options *opt = &(IPCB(skb)->opt);
68 :
69 0 : __IP_INC_STATS(net, IPSTATS_MIB_OUTFORWDATAGRAMS);
70 0 : __IP_ADD_STATS(net, IPSTATS_MIB_OUTOCTETS, skb->len);
71 :
72 : #ifdef CONFIG_NET_SWITCHDEV
73 : if (skb->offload_l3_fwd_mark) {
74 : consume_skb(skb);
75 : return 0;
76 : }
77 : #endif
78 :
79 0 : if (unlikely(opt->optlen))
80 0 : ip_forward_options(skb);
81 :
82 0 : skb->tstamp = 0;
83 0 : return dst_output(net, sk, skb);
84 : }
85 :
86 0 : int ip_forward(struct sk_buff *skb)
87 : {
88 0 : u32 mtu;
89 0 : struct iphdr *iph; /* Our header */
90 0 : struct rtable *rt; /* Route we use */
91 0 : struct ip_options *opt = &(IPCB(skb)->opt);
92 0 : struct net *net;
93 :
94 : /* that should never happen */
95 0 : if (skb->pkt_type != PACKET_HOST)
96 0 : goto drop;
97 :
98 0 : if (unlikely(skb->sk))
99 0 : goto drop;
100 :
101 0 : if (skb_warn_if_lro(skb))
102 0 : goto drop;
103 :
104 0 : if (!xfrm4_policy_check(NULL, XFRM_POLICY_FWD, skb))
105 : goto drop;
106 :
107 0 : if (IPCB(skb)->opt.router_alert && ip_call_ra_chain(skb))
108 : return NET_RX_SUCCESS;
109 :
110 0 : skb_forward_csum(skb);
111 0 : net = dev_net(skb->dev);
112 :
113 : /*
114 : * According to the RFC, we must first decrease the TTL field. If
115 : * that reaches zero, we must reply an ICMP control message telling
116 : * that the packet's lifetime expired.
117 : */
118 0 : if (ip_hdr(skb)->ttl <= 1)
119 0 : goto too_many_hops;
120 :
121 0 : if (!xfrm4_route_forward(skb))
122 : goto drop;
123 :
124 0 : rt = skb_rtable(skb);
125 :
126 0 : if (opt->is_strictroute && rt->rt_uses_gateway)
127 0 : goto sr_failed;
128 :
129 0 : IPCB(skb)->flags |= IPSKB_FORWARDED;
130 0 : mtu = ip_dst_mtu_maybe_forward(&rt->dst, true);
131 0 : if (ip_exceeds_mtu(skb, mtu)) {
132 0 : IP_INC_STATS(net, IPSTATS_MIB_FRAGFAILS);
133 0 : icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
134 : htonl(mtu));
135 0 : goto drop;
136 : }
137 :
138 : /* We are about to mangle packet. Copy it! */
139 0 : if (skb_cow(skb, LL_RESERVED_SPACE(rt->dst.dev)+rt->dst.header_len))
140 0 : goto drop;
141 0 : iph = ip_hdr(skb);
142 :
143 : /* Decrease ttl after skb cow done */
144 0 : ip_decrease_ttl(iph);
145 :
146 : /*
147 : * We now generate an ICMP HOST REDIRECT giving the route
148 : * we calculated.
149 : */
150 0 : if (IPCB(skb)->flags & IPSKB_DOREDIRECT && !opt->srr &&
151 0 : !skb_sec_path(skb))
152 0 : ip_rt_send_redirect(skb);
153 :
154 0 : if (net->ipv4.sysctl_ip_fwd_update_priority)
155 0 : skb->priority = rt_tos2priority(iph->tos);
156 :
157 0 : return NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD,
158 : net, NULL, skb, skb->dev, rt->dst.dev,
159 : ip_forward_finish);
160 :
161 0 : sr_failed:
162 : /*
163 : * Strict routing permits no gatewaying
164 : */
165 0 : icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0);
166 0 : goto drop;
167 :
168 0 : too_many_hops:
169 : /* Tell the sender its packet died... */
170 0 : __IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS);
171 0 : icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
172 0 : drop:
173 0 : kfree_skb(skb);
174 0 : return NET_RX_DROP;
175 : }
|