📄 ip.c
字号:
1 /*
2 * INET An implementation of the TCP/IP protocol suite for the LINUX
3 * operating system. INET is implemented using the BSD Socket
4 * interface as the means of communication with the user level.
5 *
6 * The Internet Protocol (IP) module.
7 *
8 * Version: @(#)ip.c 1.0.16b 9/1/93
9 *
10 * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
11 * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
12 * Donald Becker, <becker@super.org>
13 *
14 * Fixes:
15 * Alan Cox : Commented a couple of minor bits of surplus code
16 * Alan Cox : Undefining IP_FORWARD doesn't include the code
17 * (just stops a compiler warning).
18 * Alan Cox : Frames with >=MAX_ROUTE record routes, strict routes or loose routes
19 * are junked rather than corrupting things.
20 * Alan Cox : Frames to bad broadcast subnets are dumped
21 * We used to process them non broadcast and
22 * boy could that cause havoc.
23 * Alan Cox : ip_forward sets the free flag on the
24 * new frame it queues. Still crap because
25 * it copies the frame but at least it
26 * doesn't eat memory too.
27 * Alan Cox : Generic queue code and memory fixes.
28 * Fred Van Kempen : IP fragment support (borrowed from NET2E)
29 * Gerhard Koerting: Forward fragmented frames correctly.
30 * Gerhard Koerting: Fixes to my fix of the above 8-).
31 * Gerhard Koerting: IP interface addressing fix.
32 * Linus Torvalds : More robustness checks
33 * Alan Cox : Even more checks: Still not as robust as it ought to be
34 * Alan Cox : Save IP header pointer for later
35 * Alan Cox : ip option setting
36 * Alan Cox : Use ip_tos/ip_ttl settings
37 * Alan Cox : Fragmentation bogosity removed
38 * (Thanks to Mark.Bush@prg.ox.ac.uk)
39 * Dmitry Gorodchanin : Send of a raw packet crash fix.
40 * Alan Cox : Silly ip bug when an overlength
41 * fragment turns up. Now frees the
42 * queue.
43 *
44 * To Fix:
45 * IP option processing is mostly not needed. ip_forward needs to know about routing rules
46 * and time stamp but that's about all.
47 *
48 * This program is free software; you can redistribute it and/or
49 * modify it under the terms of the GNU General Public License
50 * as published by the Free Software Foundation; either version
51 * 2 of the License, or (at your option) any later version.
52 */
53 #include <asm/segment.h>
54 #include <asm/system.h>
55 #include <linux/types.h>
56 #include <linux/kernel.h>
57 #include <linux/sched.h>
58 #include <linux/string.h>
59 #include <linux/errno.h>
60 #include <linux/socket.h>
61 #include <linux/sockios.h>
62 #include <linux/in.h>
63 #include "inet.h"
64 #include "dev.h"
65 #include "eth.h"
66 #include "ip.h"
67 #include "protocol.h"
68 #include "route.h"
69 #include "tcp.h"
70 #include "skbuff.h"
71 #include "sock.h"
72 #include "arp.h"
73 #include "icmp.h"
74
75 #define CONFIG_IP_FORWARD
76 #define CONFIG_IP_DEFRAG
77
78 extern int last_retran;
79 extern void sort_send(struct sock *sk);
80
81 #define min(a,b) ((a)<(b)?(a):(b))
82
83 void
84 ip_print(struct iphdr *ip)
85 {
86 unsigned char buff[32];
87 unsigned char *ptr;
88 int addr, len, i;
89
90 if (inet_debug != DBG_IP) return;
91
92 /* Dump the IP header. */
93 printk("IP: ihl=%d, version=%d, tos=%d, tot_len=%d\n",
94 ip->ihl, ip->version, ip->tos, ntohs(ip->tot_len));
95 printk(" id=%X, ttl=%d, prot=%d, check=%X\n",
96 ip->id, ip->ttl, ip->protocol, ip->check);
97 printk(" frag_off=%d\n", ip->frag_off);
98 printk(" soucre=%s ", in_ntoa(ip->saddr));
99 printk("dest=%s\n", in_ntoa(ip->daddr));
100 printk(" ----\n");
101
102 /* Dump the data. */
103 ptr = (unsigned char *)(ip + 1);
104 addr = 0;
105 len = ntohs(ip->tot_len) - (4 * ip->ihl);
106 while (len > 0) {
107 printk(" %04X: ", addr);
108 for(i = 0; i < 16; i++) {
109 if (len > 0) {
110 printk("%02X ", (*ptr & 0xFF));
111 buff[i] = *ptr++;
112 if (buff[i] < 32 || buff[i] > 126) buff[i] = '.';
113 } else {
114 printk(" ");
115 buff[i] = ' ';
116 }
117 addr++;
118 len--;
119 };
120 buff[i] = '\0';
121 printk(" \"%s\"\n", buff);
122 }
123 printk(" ----\n\n");
124 }
125
126
127 int
128 ip_ioctl(struct sock *sk, int cmd, unsigned long arg)
129 {
130 switch(cmd) {
131 case DDIOCSDBG:
132 return(dbg_ioctl((void *) arg, DBG_IP));
133 default:
134 return(-EINVAL);
135 }
136 }
137
138
139 /* these two routines will do routining. */
140 static void
141 strict_route(struct iphdr *iph, struct options *opt)
142 {
143 }
144
145
146 static void
147 loose_route(struct iphdr *iph, struct options *opt)
148 {
149 }
150
151
152 static void
153 print_ipprot(struct inet_protocol *ipprot)
154 {
155 DPRINTF((DBG_IP, "handler = %X, protocol = %d, copy=%d \n",
156 ipprot->handler, ipprot->protocol, ipprot->copy));
157 }
158
159
160 /* This routine will check to see if we have lost a gateway. */
161 void
162 ip_route_check(unsigned long daddr)
163 {
164 }
165
166
167 #if 0
168 /* this routine puts the options at the end of an ip header. */
169 static int
170 build_options(struct iphdr *iph, struct options *opt)
171 {
172 unsigned char *ptr;
173 /* currently we don't support any options. */
174 ptr = (unsigned char *)(iph+1);
175 *ptr = 0;
176 return (4);
177 }
178 #endif
179
180
181 /* Take an skb, and fill in the MAC header. */
182 static int
183 ip_send(struct sk_buff *skb, unsigned long daddr, int len, struct device *dev,
184 unsigned long saddr)
185 {
186 unsigned char *ptr;
187 int mac;
188
189 ptr = skb->data;
190 mac = 0;
191 skb->arp = 1;
192 if (dev->hard_header) {
193 mac = dev->hard_header(ptr, dev, ETH_P_IP, daddr, saddr, len);
194 }
195 if (mac < 0) {
196 mac = -mac;
197 skb->arp = 0;
198 }
199 skb->dev = dev;
200 return(mac);
201 }
202
203
204 /*
205 * This routine builds the appropriate hardware/IP headers for
206 * the routine. It assumes that if *dev != NULL then the
207 * protocol knows what it's doing, otherwise it uses the
208 * routing/ARP tables to select a device struct.
209 */
210 int
211 ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long daddr,
212 struct device **dev, int type, struct options *opt, int len, int tos, int ttl)
213 {
214 static struct options optmem;
215 struct iphdr *iph;
216 struct rtable *rt;
217 unsigned char *buff;
218 unsigned long raddr;
219 static int count = 0;
220 int tmp;
221
222 if (saddr == 0)
223 saddr = my_addr();
224
225 DPRINTF((DBG_IP, "ip_build_header (skb=%X, saddr=%X, daddr=%X, *dev=%X,\n"
226 " type=%d, opt=%X, len = %d)\n",
227 skb, saddr, daddr, *dev, type, opt, len));
228
229 buff = skb->data;
230
231 /* See if we need to look up the device. */
232 if (*dev == NULL) {
233 rt = rt_route(daddr, &optmem);
234 if (rt == NULL)
235 return(-ENETUNREACH);
236
237 *dev = rt->rt_dev;
238 if (saddr == 0x0100007FL && daddr != 0x0100007FL)
239 saddr = rt->rt_dev->pa_addr;
240 raddr = rt->rt_gateway;
241
242 DPRINTF((DBG_IP, "ip_build_header: saddr set to %s\n", in_ntoa(saddr)));
243 opt = &optmem;
244 } else {
245 /* We still need the address of the first hop. */
246 rt = rt_route(daddr, &optmem);
247 raddr = (rt == NULL) ? 0 : rt->rt_gateway;
248 }
249 if (raddr == 0)
250 raddr = daddr;
251
252 /* Now build the MAC header. */
253 tmp = ip_send(skb, raddr, len, *dev, saddr);
254 buff += tmp;
255 len -= tmp;
256
257 skb->dev = *dev;
258 skb->saddr = saddr;
259 if (skb->sk) skb->sk->saddr = saddr;
260
261 /* Now build the IP header. */
262
263 /* If we are using IPPROTO_RAW, then we don't need an IP header, since
264 one is being supplied to us by the user */
265
266 if(type == IPPROTO_RAW) return (tmp);
267
268 iph = (struct iphdr *)buff;
269 iph->version = 4;
270 iph->tos = tos;
271 iph->frag_off = 0;
272 iph->ttl = ttl;
273 iph->daddr = daddr;
274 iph->saddr = saddr;
275 iph->protocol = type;
276 iph->ihl = 5;
277 iph->id = htons(count++);
278
279 /* Setup the IP options. */
280 #ifdef Not_Yet_Avail
281 build_options(iph, opt);
282 #endif
283
284 return(20 + tmp); /* IP header plus MAC header size */
285 }
286
287
288 static int
289 do_options(struct iphdr *iph, struct options *opt)
290 {
291 unsigned char *buff;
292 int done = 0;
293 int i, len = sizeof(struct iphdr);
294
295 /* Zero out the options. */
296 opt->record_route.route_size = 0;
297 opt->loose_route.route_size = 0;
298 opt->strict_route.route_size = 0;
299 opt->tstamp.ptr = 0;
300 opt->security = 0;
301 opt->compartment = 0;
302 opt->handling = 0;
303 opt->stream = 0;
304 opt->tcc = 0;
305 return(0);
306
307 /* Advance the pointer to start at the options. */
308 buff = (unsigned char *)(iph + 1);
309
310 /* Now start the processing. */
311 while (!done && len < iph->ihl*4) switch(*buff) {
312 case IPOPT_END:
313 done = 1;
314 break;
315 case IPOPT_NOOP:
316 buff++;
317 len++;
318 break;
319 case IPOPT_SEC:
320 buff++;
321 if (*buff != 11) return(1);
322 buff++;
323 opt->security = ntohs(*(unsigned short *)buff);
324 buff += 2;
325 opt->compartment = ntohs(*(unsigned short *)buff);
326 buff += 2;
327 opt->handling = ntohs(*(unsigned short *)buff);
328 buff += 2;
329 opt->tcc = ((*buff) << 16) + ntohs(*(unsigned short *)(buff+1));
330 buff += 3;
331 len += 11;
332 break;
333 case IPOPT_LSRR:
334 buff++;
335 if ((*buff - 3)% 4 != 0) return(1);
336 len += *buff;
337 opt->loose_route.route_size = (*buff -3)/4;
338 buff++;
339 if (*buff % 4 != 0) return(1);
340 opt->loose_route.pointer = *buff/4 - 1;
341 buff++;
342 buff++;
343 for (i = 0; i < opt->loose_route.route_size; i++) {
344 if(i>=MAX_ROUTE)
345 return(1);
346 opt->loose_route.route[i] = *(unsigned long *)buff;
347 buff += 4;
348 }
349 break;
350 case IPOPT_SSRR:
351 buff++;
352 if ((*buff - 3)% 4 != 0) return(1);
353 len += *buff;
354 opt->strict_route.route_size = (*buff -3)/4;
355 buff++;
356 if (*buff % 4 != 0) return(1);
357 opt->strict_route.pointer = *buff/4 - 1;
358 buff++;
359 buff++;
360 for (i = 0; i < opt->strict_route.route_size; i++) {
361 if(i>=MAX_ROUTE)
362 return(1);
363 opt->strict_route.route[i] = *(unsigned long *)buff;
364 buff += 4;
365 }
366 break;
367 case IPOPT_RR:
368 buff++;
369 if ((*buff - 3)% 4 != 0) return(1);
370 len += *buff;
371 opt->record_route.route_size = (*buff -3)/4;
372 buff++;
373 if (*buff % 4 != 0) return(1);
374 opt->record_route.pointer = *buff/4 - 1;
375 buff++;
376 buff++;
377 for (i = 0; i < opt->record_route.route_size; i++) {
378 if(i>=MAX_ROUTE)
379 return 1;
380 opt->record_route.route[i] = *(unsigned long *)buff;
381 buff += 4;
382 }
383 break;
384 case IPOPT_SID:
385 len += 4;
386 buff +=2;
387 opt->stream = *(unsigned short *)buff;
388 buff += 2;
389 break;
390 case IPOPT_TIMESTAMP:
391 buff++;
392 len += *buff;
393 if (*buff % 4 != 0) return(1);
394 opt->tstamp.len = *buff / 4 - 1;
395 buff++;
396 if ((*buff - 1) % 4 != 0) return(1);
397 opt->tstamp.ptr = (*buff-1)/4;
398 buff++;
399 opt->tstamp.x.full_char = *buff;
400 buff++;
401 for (i = 0; i < opt->tstamp.len; i++) {
402 opt->tstamp.data[i] = *(unsigned long *)buff;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -