1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include <linux/config.h>
25#include <linux/types.h>
26#include <linux/mm.h>
27#include <linux/sched.h>
28#include <linux/skbuff.h>
29#include <linux/ip.h>
30#include <linux/icmp.h>
31#include <linux/netdevice.h>
32#include <net/sock.h>
33#include <net/ip.h>
34#include <net/tcp.h>
35#include <net/udp.h>
36#include <net/icmp.h>
37#include <linux/tcp.h>
38#include <linux/udp.h>
39#include <linux/firewall.h>
40#include <linux/ip_fw.h>
41#ifdef CONFIG_IP_MASQUERADE
42#include <net/ip_masq.h>
43#endif
44#include <net/checksum.h>
45#include <linux/route.h>
46#include <net/route.h>
47
48#ifdef CONFIG_IP_TRANSPARENT_PROXY
49
50
51
52
53
54
55int ip_chksock(struct sk_buff *skb)
56{
57 switch (skb->nh.iph->protocol) {
58 case IPPROTO_ICMP:
59 return icmp_chkaddr(skb);
60 case IPPROTO_TCP:
61 return tcp_chkaddr(skb);
62 case IPPROTO_UDP:
63 return udp_chkaddr(skb);
64 default:
65 return 0;
66 }
67}
68#endif
69
70
71int ip_forward(struct sk_buff *skb)
72{
73 struct device *dev2;
74 struct iphdr *iph;
75 struct rtable *rt;
76 struct ip_options * opt = &(IPCB(skb)->opt);
77 unsigned short mtu;
78#if defined(CONFIG_FIREWALL) || defined(CONFIG_IP_MASQUERADE)
79 int fw_res = 0;
80#endif
81
82 if (IPCB(skb)->opt.router_alert && ip_call_ra_chain(skb))
83 return 0;
84
85 if (skb->pkt_type != PACKET_HOST)
86 goto drop;
87
88
89
90
91
92
93
94 iph = skb->nh.iph;
95 rt = (struct rtable*)skb->dst;
96
97#ifdef CONFIG_CPU_IS_SLOW
98 if (net_cpu_congestion > 1 && !(iph->tos&IPTOS_RELIABILITY) &&
99 IPTOS_PREC(iph->tos) < IPTOS_PREC_INTERNETCONTROL) {
100 if (((xtime.tv_usec&0xF)<<net_cpu_congestion) > 0x1C)
101 goto drop;
102 }
103#endif
104
105
106#ifdef CONFIG_IP_TRANSPARENT_PROXY
107 if (ip_chksock(skb))
108 goto local_pkt;
109#endif
110
111 if (iph->ttl <= 1)
112 goto too_many_hops;
113
114 if (opt->is_strictroute && rt->rt_dst != rt->rt_gateway)
115 goto sr_failed;
116
117
118
119
120
121
122 skb->priority = rt_tos2priority(iph->tos);
123 dev2 = rt->u.dst.dev;
124 mtu = rt->u.dst.pmtu;
125
126#ifdef CONFIG_NET_SECURITY
127 call_fw_firewall(PF_SECURITY, dev2, NULL, &mtu, NULL);
128#endif
129
130
131
132
133
134 if (rt->rt_flags&RTCF_DOREDIRECT && !opt->srr)
135 ip_rt_send_redirect(skb);
136
137
138 if ((skb = skb_cow(skb, dev2->hard_header_len)) == NULL)
139 return -1;
140 iph = skb->nh.iph;
141 opt = &(IPCB(skb)->opt);
142
143
144 ip_decrease_ttl(iph);
145
146
147
148
149
150
151 if (skb->len > mtu && (ntohs(iph->frag_off) & IP_DF))
152 goto frag_needed;
153
154#ifdef CONFIG_IP_ROUTE_NAT
155 if (rt->rt_flags & RTCF_NAT) {
156 if (ip_do_nat(skb)) {
157 kfree_skb(skb);
158 return -1;
159 }
160 }
161#endif
162
163#ifdef CONFIG_IP_MASQUERADE
164 if(!(IPCB(skb)->flags&IPSKB_MASQUERADED)) {
165
166
167
168
169
170 if (iph->protocol == IPPROTO_ICMP) {
171 __u32 maddr;
172#ifdef CONFIG_IP_MASQUERADE_ICMP
173 struct icmphdr *icmph = (struct icmphdr *)((char*)iph + (iph->ihl << 2));
174 if ((icmph->type==ICMP_DEST_UNREACH)||
175 (icmph->type==ICMP_SOURCE_QUENCH)||
176 (icmph->type==ICMP_TIME_EXCEEDED))
177 {
178#endif
179 maddr = inet_select_addr(dev2, rt->rt_gateway, RT_SCOPE_UNIVERSE);
180 fw_res = ip_fw_masq_icmp(&skb, maddr);
181 if (fw_res < 0) {
182 kfree_skb(skb);
183 return -1;
184 }
185
186 if (fw_res)
187
188 goto skip_call_fw_firewall;
189#ifdef CONFIG_IP_MASQUERADE_ICMP
190 }
191#endif
192 }
193 if (rt->rt_flags&RTCF_MASQ)
194 goto skip_call_fw_firewall;
195#endif
196
197#ifdef CONFIG_FIREWALL
198 fw_res=call_fw_firewall(PF_INET, dev2, iph, NULL, &skb);
199 switch (fw_res) {
200 case FW_ACCEPT:
201 case FW_MASQUERADE:
202 break;
203 case FW_REJECT:
204 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
205
206 default:
207 kfree_skb(skb);
208 return -1;
209 }
210#endif
211
212#ifdef CONFIG_IP_MASQUERADE
213 }
214
215skip_call_fw_firewall:
216
217
218
219
220 if (!(IPCB(skb)->flags&IPSKB_MASQUERADED) &&
221 (fw_res==FW_MASQUERADE || rt->rt_flags&RTCF_MASQ)) {
222 u32 maddr;
223
224#ifdef CONFIG_IP_ROUTE_NAT
225 maddr = (rt->rt_flags&RTCF_MASQ) ? rt->rt_src_map : 0;
226
227 if (maddr == 0)
228#endif
229 maddr = inet_select_addr(dev2, rt->rt_gateway, RT_SCOPE_UNIVERSE);
230
231 if (ip_fw_masquerade(&skb, maddr) < 0) {
232 kfree_skb(skb);
233 return -1;
234 } else {
235
236
237
238 iph = skb->nh.iph;
239 opt = &(IPCB(skb)->opt);
240 }
241 }
242#endif
243
244
245#ifdef CONFIG_FIREWALL
246 if ((fw_res = call_out_firewall(PF_INET, dev2, iph, NULL,&skb)) < FW_ACCEPT) {
247
248
249 if (fw_res == FW_REJECT)
250 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
251 kfree_skb(skb);
252 return -1;
253 }
254#endif
255
256 ip_statistics.IpForwDatagrams++;
257
258 if (opt->optlen == 0) {
259#ifdef CONFIG_NET_FASTROUTE
260 if (rt->rt_flags&RTCF_FAST && !netdev_fastroute_obstacles) {
261 unsigned h = ((*(u8*)&rt->key.dst)^(*(u8*)&rt->key.src))&NETDEV_FASTROUTE_HMASK;
262
263 dst_release_irqwait(xchg(&skb->dev->fastpath[h], dst_clone(&rt->u.dst)));
264 }
265#endif
266 ip_send(skb);
267 return 0;
268 }
269
270 ip_forward_options(skb);
271 ip_send(skb);
272 return 0;
273
274#ifdef CONFIG_IP_TRANSPARENT_PROXY
275local_pkt:
276 return ip_local_deliver(skb);
277#endif
278
279frag_needed:
280 ip_statistics.IpFragFails++;
281 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
282 goto drop;
283
284sr_failed:
285
286
287
288 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0);
289 goto drop;
290
291too_many_hops:
292
293 icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
294drop:
295 kfree_skb(skb);
296 return -1;
297}
298