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

📄 ip.c

📁 LINUX1.0内核源代码,学习LINUX编程的一定要看。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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 Internet Protocol (IP) module. * * Version:	@(#)ip.c	1.0.16b	9/1/93 * * Authors:	Ross Biro, <bir7@leland.Stanford.Edu> *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> *		Donald Becker, <becker@super.org> * * Fixes: *		Alan Cox	:	Commented a couple of minor bits of surplus code *		Alan Cox	:	Undefining IP_FORWARD doesn't include the code *					(just stops a compiler warning). *		Alan Cox	:	Frames with >=MAX_ROUTE record routes, strict routes or loose routes *					are junked rather than corrupting things. *		Alan Cox	:	Frames to bad broadcast subnets are dumped *					We used to process them non broadcast and *					boy could that cause havoc. *		Alan Cox	:	ip_forward sets the free flag on the  *					new frame it queues. Still crap because *					it copies the frame but at least it  *					doesn't eat memory too. *		Alan Cox	:	Generic queue code and memory fixes. *		Fred Van Kempen :	IP fragment support (borrowed from NET2E) *		Gerhard Koerting:	Forward fragmented frames correctly. *		Gerhard Koerting: 	Fixes to my fix of the above 8-). *		Gerhard Koerting:	IP interface addressing fix. *		Linus Torvalds	:	More robustness checks *		Alan Cox	:	Even more checks: Still not as robust as it ought to be *		Alan Cox	:	Save IP header pointer for later *		Alan Cox	:	ip option setting *		Alan Cox	:	Use ip_tos/ip_ttl settings *		Alan Cox	:	Fragmentation bogosity removed *					(Thanks to Mark.Bush@prg.ox.ac.uk) *		Dmitry Gorodchanin :	Send of a raw packet crash fix. *		Alan Cox	:	Silly ip bug when an overlength *					fragment turns up. Now frees the *					queue. * * To Fix: *		IP option processing is mostly not needed. ip_forward needs to know about routing rules *		and time stamp but that's about all. * *		This program is free software; you can redistribute it and/or *		modify it under the terms of the GNU General Public License *		as published by the Free Software Foundation; either version *		2 of the License, or (at your option) any later version. */#include <asm/segment.h>#include <asm/system.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/string.h>#include <linux/errno.h>#include <linux/socket.h>#include <linux/sockios.h>#include <linux/in.h>#include "inet.h"#include "dev.h"#include "eth.h"#include "ip.h"#include "protocol.h"#include "route.h"#include "tcp.h"#include "skbuff.h"#include "sock.h"#include "arp.h"#include "icmp.h"#define CONFIG_IP_FORWARD#define CONFIG_IP_DEFRAGextern int last_retran;extern void sort_send(struct sock *sk);#define min(a,b)	((a)<(b)?(a):(b))voidip_print(struct iphdr *ip){  unsigned char buff[32];  unsigned char *ptr;  int addr, len, i;  if (inet_debug != DBG_IP) return;  /* Dump the IP header. */  printk("IP: ihl=%d, version=%d, tos=%d, tot_len=%d\n",	   ip->ihl, ip->version, ip->tos, ntohs(ip->tot_len));  printk("    id=%X, ttl=%d, prot=%d, check=%X\n",	   ip->id, ip->ttl, ip->protocol, ip->check);  printk("    frag_off=%d\n", ip->frag_off);  printk("    soucre=%s ", in_ntoa(ip->saddr));  printk("dest=%s\n", in_ntoa(ip->daddr));  printk("    ----\n");  /* Dump the data. */  ptr = (unsigned char *)(ip + 1);  addr = 0;  len = ntohs(ip->tot_len) - (4 * ip->ihl);  while (len > 0) {	printk("    %04X: ", addr);	for(i = 0; i < 16; i++) {		if (len > 0) {			printk("%02X ", (*ptr & 0xFF));			buff[i] = *ptr++;			if (buff[i] < 32 || buff[i] > 126) buff[i] = '.';		} else {			printk("   ");			buff[i] = ' ';		}		addr++;		len--;	};	buff[i] = '\0';	printk("  \"%s\"\n", buff);  }  printk("    ----\n\n");}intip_ioctl(struct sock *sk, int cmd, unsigned long arg){  switch(cmd) {	case DDIOCSDBG:		return(dbg_ioctl((void *) arg, DBG_IP));	default:		return(-EINVAL);  }}/* these two routines will do routining. */static voidstrict_route(struct iphdr *iph, struct options *opt){}static voidloose_route(struct iphdr *iph, struct options *opt){}static voidprint_ipprot(struct inet_protocol *ipprot){  DPRINTF((DBG_IP, "handler = %X, protocol = %d, copy=%d \n",	   ipprot->handler, ipprot->protocol, ipprot->copy));}/* This routine will check to see if we have lost a gateway. */voidip_route_check(unsigned long daddr){}#if 0/* this routine puts the options at the end of an ip header. */static intbuild_options(struct iphdr *iph, struct options *opt){  unsigned char *ptr;  /* currently we don't support any options. */  ptr = (unsigned char *)(iph+1);  *ptr = 0;  return (4);}#endif/* Take an skb, and fill in the MAC header. */static intip_send(struct sk_buff *skb, unsigned long daddr, int len, struct device *dev,	unsigned long saddr){  unsigned char *ptr;  int mac;  ptr = skb->data;  mac = 0;  skb->arp = 1;  if (dev->hard_header) {	mac = dev->hard_header(ptr, dev, ETH_P_IP, daddr, saddr, len);  }  if (mac < 0) {	mac = -mac;	skb->arp = 0;  }  skb->dev = dev;  return(mac);}/* * This routine builds the appropriate hardware/IP headers for * the routine.  It assumes that if *dev != NULL then the * protocol knows what it's doing, otherwise it uses the * routing/ARP tables to select a device struct. */intip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long daddr,		struct device **dev, int type, struct options *opt, int len, int tos, int ttl){  static struct options optmem;  struct iphdr *iph;  struct rtable *rt;  unsigned char *buff;  unsigned long raddr;  static int count = 0;  int tmp;  if (saddr == 0)   	saddr = my_addr();  	  DPRINTF((DBG_IP, "ip_build_header (skb=%X, saddr=%X, daddr=%X, *dev=%X,\n"	   "                 type=%d, opt=%X, len = %d)\n",	   skb, saddr, daddr, *dev, type, opt, len));	     buff = skb->data;  /* See if we need to look up the device. */  if (*dev == NULL) {	rt = rt_route(daddr, &optmem);	if (rt == NULL) 		return(-ENETUNREACH);	*dev = rt->rt_dev;	if (saddr == 0x0100007FL && daddr != 0x0100007FL) 		saddr = rt->rt_dev->pa_addr;	raddr = rt->rt_gateway;	DPRINTF((DBG_IP, "ip_build_header: saddr set to %s\n", in_ntoa(saddr)));	opt = &optmem;  } else {	/* We still need the address of the first hop. */	rt = rt_route(daddr, &optmem);	raddr = (rt == NULL) ? 0 : rt->rt_gateway;  }  if (raddr == 0)  	raddr = daddr;  /* Now build the MAC header. */  tmp = ip_send(skb, raddr, len, *dev, saddr);  buff += tmp;  len -= tmp;  skb->dev = *dev;  skb->saddr = saddr;  if (skb->sk) skb->sk->saddr = saddr;  /* Now build the IP header. */  /* If we are using IPPROTO_RAW, then we don't need an IP header, since     one is being supplied to us by the user */  if(type == IPPROTO_RAW) return (tmp);  iph = (struct iphdr *)buff;  iph->version  = 4;  iph->tos      = tos;  iph->frag_off = 0;  iph->ttl      = ttl;  iph->daddr    = daddr;  iph->saddr    = saddr;  iph->protocol = type;  iph->ihl      = 5;  iph->id       = htons(count++);  /* Setup the IP options. */#ifdef Not_Yet_Avail  build_options(iph, opt);#endif  return(20 + tmp);	/* IP header plus MAC header size */}static intdo_options(struct iphdr *iph, struct options *opt){  unsigned char *buff;  int done = 0;  int i, len = sizeof(struct iphdr);  /* Zero out the options. */  opt->record_route.route_size = 0;  opt->loose_route.route_size  = 0;  opt->strict_route.route_size = 0;  opt->tstamp.ptr              = 0;  opt->security                = 0;  opt->compartment             = 0;  opt->handling                = 0;  opt->stream                  = 0;  opt->tcc                     = 0;  return(0);  /* Advance the pointer to start at the options. */  buff = (unsigned char *)(iph + 1);  /* Now start the processing. */  while (!done && len < iph->ihl*4) switch(*buff) {	case IPOPT_END:		done = 1;		break;	case IPOPT_NOOP:		buff++;		len++;		break;	case IPOPT_SEC:		buff++;		if (*buff != 11) return(1);		buff++;		opt->security = ntohs(*(unsigned short *)buff);		buff += 2;		opt->compartment = ntohs(*(unsigned short *)buff);		buff += 2;		opt->handling = ntohs(*(unsigned short *)buff);		buff += 2;	  	opt->tcc = ((*buff) << 16) + ntohs(*(unsigned short *)(buff+1));	  	buff += 3;	  	len += 11;	  	break;	case IPOPT_LSRR:		buff++;		if ((*buff - 3)% 4 != 0) return(1);		len += *buff;		opt->loose_route.route_size = (*buff -3)/4;		buff++;		if (*buff % 4 != 0) return(1);		opt->loose_route.pointer = *buff/4 - 1;		buff++;		buff++;		for (i = 0; i < opt->loose_route.route_size; i++) {			if(i>=MAX_ROUTE)				return(1);			opt->loose_route.route[i] = *(unsigned long *)buff;			buff += 4;		}		break;	case IPOPT_SSRR:		buff++;		if ((*buff - 3)% 4 != 0) return(1);		len += *buff;		opt->strict_route.route_size = (*buff -3)/4;		buff++;		if (*buff % 4 != 0) return(1);		opt->strict_route.pointer = *buff/4 - 1;		buff++;		buff++;		for (i = 0; i < opt->strict_route.route_size; i++) {			if(i>=MAX_ROUTE)				return(1);			opt->strict_route.route[i] = *(unsigned long *)buff;			buff += 4;		}		break;	case IPOPT_RR:		buff++;		if ((*buff - 3)% 4 != 0) return(1);		len += *buff;		opt->record_route.route_size = (*buff -3)/4;		buff++;		if (*buff % 4 != 0) return(1);		opt->record_route.pointer = *buff/4 - 1;		buff++;		buff++;		for (i = 0; i < opt->record_route.route_size; i++) {			if(i>=MAX_ROUTE)				return 1;			opt->record_route.route[i] = *(unsigned long *)buff;			buff += 4;		}		break;	case IPOPT_SID:		len += 4;		buff +=2;		opt->stream = *(unsigned short *)buff;		buff += 2;		break;	case IPOPT_TIMESTAMP:		buff++;		len += *buff;		if (*buff % 4 != 0) return(1);		opt->tstamp.len = *buff / 4 - 1;		buff++;		if ((*buff - 1) % 4 != 0) return(1);		opt->tstamp.ptr = (*buff-1)/4;		buff++;		opt->tstamp.x.full_char = *buff;		buff++;		for (i = 0; i < opt->tstamp.len; i++) {			opt->tstamp.data[i] = *(unsigned long *)buff;			buff += 4;		}		break;	default:		return(1);  }  if (opt->record_route.route_size == 0) {	if (opt->strict_route.route_size != 0) {		memcpy(&(opt->record_route), &(opt->strict_route),					     sizeof(opt->record_route));	} else if (opt->loose_route.route_size != 0) {		memcpy(&(opt->record_route), &(opt->loose_route),					     sizeof(opt->record_route));	}  }  if (opt->strict_route.route_size != 0 &&      opt->strict_route.route_size != opt->strict_route.pointer) {	strict_route(iph, opt);	return(0);  }  if (opt->loose_route.route_size != 0 &&      opt->loose_route.route_size != opt->loose_route.pointer) {	loose_route(iph, opt);	return(0);  }  return(0);}/* This is a version of ip_compute_csum() optimized for IP headers, which   always checksum on 4 octet boundaries. */static inline unsigned shortip_fast_csum(unsigned char * buff, int wlen){    unsigned long sum = 0;    if (wlen) {    	unsigned long bogus;	 __asm__("clc\n"		"1:\t"		"lodsl\n\t"		"adcl %3, %0\n\t"		"decl %2\n\t"		"jne 1b\n\t"		"adcl $0, %0\n\t"		"movl %0, %3\n\t"		"shrl $16, %3\n\t"		"addw %w3, %w0\n\t"		"adcw $0, %w0"	    : "=r" (sum), "=S" (buff), "=r" (wlen), "=a" (bogus)	    : "0"  (sum),  "1" (buff),  "2" (wlen));    }    return (~sum) & 0xffff;}/* * This routine does all the checksum computations that don't * require anything special (like copying or special headers). */unsigned shortip_compute_csum(unsigned char * buff, int len){  unsigned long sum = 0;  /* Do the first multiple of 4 bytes and convert to 16 bits. */  if (len > 3) {	__asm__("clc\n"	        "1:\t"	    	"lodsl\n\t"	    	"adcl %%eax, %%ebx\n\t"	    	"loop 1b\n\t"	    	"adcl $0, %%ebx\n\t"	    	"movl %%ebx, %%eax\n\t"	    	"shrl $16, %%eax\n\t"	    	"addw %%ax, %%bx\n\t"	    	"adcw $0, %%bx"	        : "=b" (sum) , "=S" (buff)	        : "0" (sum), "c" (len >> 2) ,"1" (buff)	        : "ax", "cx", "si", "bx" );  }  if (len & 2) {	__asm__("lodsw\n\t"	    	"addw %%ax, %%bx\n\t"	    	"adcw $0, %%bx"	        : "=b" (sum), "=S" (buff)	        : "0" (sum), "1" (buff)	        : "bx", "ax", "si");  }  if (len & 1) {	__asm__("lodsb\n\t"	    	"movb $0, %%ah\n\t"	    	"addw %%ax, %%bx\n\t"	    	"adcw $0, %%bx"	        : "=b" (sum), "=S" (buff)	        : "0" (sum), "1" (buff)	        : "bx", "ax", "si");  }  sum =~sum;  return(sum & 0xffff);}/* Check the header of an incoming IP datagram.  This version is still used in slhc.c. */intip_csum(struct iphdr *iph){  return ip_fast_csum((unsigned char *)iph, iph->ihl);}/* Generate a checksym for an outgoing IP datagram. */static voidip_send_check(struct iphdr *iph){   iph->check = 0;   iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);}/************************ Fragment Handlers From NET2E not yet with tweaks to beat 4K **********************************/static struct ipq *ipqueue = NULL;		/* IP fragment queue	*/ /* Create a new fragment entry. */static struct ipfrag *ip_frag_create(int offset, int end, struct sk_buff *skb, unsigned char *ptr){   	struct ipfrag *fp;    	fp = (struct ipfrag *) kmalloc(sizeof(struct ipfrag), GFP_ATOMIC);   	if (fp == NULL)    	{	 	printk("IP: frag_create: no memory left !\n");	 	return(NULL);   	}  	memset(fp, 0, sizeof(struct ipfrag));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -