⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ip.c

📁 An implementation of the TCP/IP protocol suite for the LINUX operating system. INET is implemented u
💻 C
📖 第 1 页 / 共 4 页
字号:
  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 + -