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

📄 netip.c

📁 UCOS-ii对于网络的支持代码
💻 C
字号:
/*****************************************************************************
* netip.c - Network Internet Protocol (IP) program file.
*
* portions Copyright (c) 1997 by Global Election Systems Inc.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice and the following disclaimer are included verbatim in any 
* distributions. No written agreement, license, or royalty fee is required
* for any of the authorized uses.
*
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
* REVISION HISTORY
*
* 97-11-05 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
*	Original.
*****************************************************************************/
/*
 * Copyright (c) 1982, 1986, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)ip.h	8.2 (Berkeley) 6/1/94
 */

#include "typedefs.h"
#include "avconfig.h"
#include <string.h>
#include "time.h"
#include "netbuf.h"
#include "devio.h"
#include "stdio.h"

#include "net.h"
#include "netip.h"
#include "netiphdr.h"

/* The upper layer interfaces. */
#include "nettcp.h"
#include "neticmp.h"

/* The lower layer interfaces. */
#include "netppp.h"

#include "debug.h"


/***********************************/
/*** LOCAL FUNCTION DECLARATIONS ***/
/***********************************/
static void ipDispatch(NBuf *nb);


/******************************/
/*** PUBLIC DATA STRUCTURES ***/
/******************************/
#if STATS_SUPPORT > 0
IPStats		ipStats;
#endif
u_short		ipID;					/* IP packet ctr, for ID fields. */
int			ip_defttl;				/* default IP ttl */
IfType		defIfType;				/* Default route interface type. */
int			defIfID;				/* Default route interface ID. */
u_long		defIPAddr;				/* Default route IP address. */

int	disable_defaultip;				/* Don't use hostname for default IP adrs */


/*****************************/
/*** LOCAL DATA STRUCTURES ***/
/*****************************/


/***********************************/
/*** PUBLIC FUNCTION DEFINITIONS ***/
/***********************************/
/*
 * ipInit - Initialize the IP subsystem.
 */
void ipInit(void)
{
#if STATS_SUPPORT > 0
	memset(&ipStats, 0, sizeof(IPStats));
	ipStats.headLine.fmtStr	    	= "\t\tIP STATISTICS\r\n";
	ipStats.ips_total.fmtStr		= "\tTOTAL DATAGRAMS: %5lu\r\n";
	ipStats.ips_toosmall.fmtStr		= "\tTOO SMALL      : %5lu\r\n";
	ipStats.ips_badvers.fmtStr		= "\tBAD VERSION    : %5lu\r\n";
	ipStats.ips_badhlen.fmtStr		= "\tBAD HEAD LENGTH: %5lu\r\n";
	ipStats.ips_badsum.fmtStr		= "\tBAD CHECKSUM   : %5lu\r\n";
	ipStats.ips_badlen.fmtStr		= "\tBAD LENGTH     : %5lu\r\n";
	ipStats.ips_buffers.fmtStr		= "\tNO FREE BUFFERS: %5lu\r\n";
	ipStats.ips_odropped.fmtStr		= "\tOTHER DROPPED  : %5lu\r\n";
	ipStats.ips_cantforward.fmtStr	= "\tCAN'T FORWARD  : %5lu\r\n";
	ipStats.ips_delivered.fmtStr		= "\tDELIVERED      : %5lu\r\n";
#endif

	ipID = 1;
	ip_defttl = IPTTLDEFAULT;
	netMask = 0;
	localHost = 0; /* OURADDR; */
	defIfType = IFT_UNSPEC;
	defIfID = 0;
	disable_defaultip = !0;
	
	icmpInit();
	setTraceLevel(LOG_WARNING, TL_IP);
}

/*
 * ipInput - Process a raw incoming IP datagram.
 */
void ipInput(NBuf *inBuf, IfType ifType, int ifID)
{
	IPHdr	*ip;
	u_char	hdrLen;
	
	/* Validate parameters. */
	if (inBuf == NULL)
		return;
	
	/* 
	 * If we don't have a default interface, assume that this interface
	 * is the one we want.
	 */
	if (defIfType == IFT_UNSPEC) {
		defIfType = ifType;
		defIfID = ifID;
	}
	
	/* Validate IP header. */
	STATS(ipStats.ips_total.val++;)
	if (inBuf->len < sizeof(IPHdr) &&
		    (inBuf = nPullup(inBuf, sizeof(IPHdr))) == NULL) {
		STATS(ipStats.ips_toosmall.val++;)
		IPDEBUG((LOG_ERR, TL_IP, "ipInput: Runt packet len %u", inBuf->len));
		goto abortInput;
	}
	ip = nBUFTOPTR(inBuf, IPHdr *);
	if (ip->ip_v != IPVERSION) {
		STATS(ipStats.ips_badvers.val++;)
		IPDEBUG((LOG_ERR, TL_IP, "ipInput: Bad version %u", ip->ip_v));
		goto abortInput;
	}
	hdrLen = ip->ip_hl << 2;
	if (hdrLen < sizeof(IPHdr)) {	/* minimum header length */
		STATS(ipStats.ips_badhlen.val++;)
		IPDEBUG((LOG_ERR, TL_IP, "ipInput: Bad hdr sz %u", hdrLen));
		goto abortInput;
	}
	if (hdrLen > inBuf->len) {
		if ((inBuf = nPullup(inBuf, hdrLen)) == NULL) {
			STATS(ipStats.ips_badhlen.val++;)
			goto abortInput;
		}
		ip = nBUFTOPTR(inBuf, IPHdr *);
	}
	if ((ip->ip_sum = inChkSum(inBuf, hdrLen, 0)) != 0) {
		STATS(ipStats.ips_badsum.val++;)
		IPDEBUG((LOG_ERR, TL_IP, "ipInput: Bad IP chksum"));
		goto abortInput;
	}
	
	/*
	 * Convert fields to host representation.
	 */
	NTOHS(ip->ip_len);
	if (ip->ip_len < hdrLen) {
		STATS(ipStats.ips_badlen.val++;)
		goto abortInput;
	}
	NTOHS(ip->ip_id);
	NTOHS(ip->ip_off);

	/*
	 * Adjust ip_len to not reflect header.
	 * XXX This makes it confusing since packets sent to ipRawOut()
	 * would have a normal header but other packets would not!
	ip->ip_len -= hdrLen;
	 */
	
	/* Pass the datagram along and we're done. */
	ipDispatch(inBuf);
	return;
	
abortInput:
#if DEBUG_SUPPORT > 0
	nDumpChain(inBuf);
#endif
	nFreeChain(inBuf);
	return;
}

/* 
 * ipSend - Build and send an IP datagram.
 * The Type-Of-Service is defaulted, we don't handle fragmentation, the
 * Time-To-Live is defaulted, and we don't support IP options.
 */
#pragma argsused
void ipSend(
	u_char protocol, 			/* IP protocol. */
	u_long srcAddr, 			/* Source IP address in network byte order. */
	u_long dstAddr, 			/* Destination IP address in network byte order. */
	NBuf *outBuf				/* Datagram to send. */
)
{
	IPHdr ipHdr;
	
	if (outBuf) {
		/* Build the IP header. */
		memset(&ipHdr, 0, sizeof(IPHdr));
		ipHdr.ip_v = IPVERSION;
		ipHdr.ip_hl = sizeof(IPHdr) / 4;
		ipHdr.ip_tos = 0;				/* Default Type-Of-Service */
		ipHdr.ip_len = outBuf->chainLen + sizeof(IPHdr);
		ipHdr.ip_id = IPNEWID();
		ipHdr.ip_off = 0;				/* Sorry - no fragments. */
		ipHdr.ip_ttl = ip_defttl;
		ipHdr.ip_p = protocol;
		ipHdr.ip_src.s_addr = srcAddr;
		ipHdr.ip_dst.s_addr = dstAddr;
		
		/* Prepend an IP header. */
		nPREPEND(outBuf, &ipHdr, sizeof(IPHdr));
		if (outBuf == NULL) {
			STATS(ipStats.ips_odropped.val++;)
		} else		
			/* Send the datagram. */
			ipDispatch(outBuf);
	}
}

/* 
 * ipRawOut - Send a prepared IP datagram.
 * This is where route lookup could occur.
 */
void ipRawOut(NBuf *nb)
{
	ipDispatch(nb);
}


/*
 * ripInput - Handle raw ICMP packets.
 */
void ripInput(NBuf *nb)
{
	IPDEBUG((LOG_INFO, TL_IP, "rip_input: dropping packet"));
	nFreeChain(nb);
	STATS(ipStats.ips_odropped.val++;)
}


/*
 * ipIOCtl - Get and set IP I/O configuration.
 */
#pragma argsused
int  ipIOCtl(INT cmd, void *arg)
{
	return 0;
}

/*
 * ipOptStrip - Strip off the options from the head of the buffer.
 * If the operation fails (likely failure to allocate a new nBuf),
 * then the situation is considered unrecoverable and the buffer
 * chain is dropped.
 * Return the resulting buffer chain.
 */
NBuf *ipOptStrip(NBuf *inBuf, u_int ipHeadLen)
{
	int optSize = ipHeadLen - sizeof(IPHdr);
	NBuf *n0;
	
	if (optSize < 0 || (n0 = nSplit(inBuf, ipHeadLen)) == NULL) {
		nFreeChain(inBuf);
		inBuf = NULL;
		STATS(ipStats.ips_odropped.val++;)
	} else if (nTrim(NULL, &inBuf, -optSize) < optSize) {
		nFreeChain(n0);
		nFreeChain(inBuf);
		inBuf = NULL;
		STATS(ipStats.ips_odropped.val++;)
	} else
		inBuf = nCat(inBuf, n0);
	
	return inBuf;
}

/*
 * ipMTU - Return the size in bytes of the Maximum Transmission Unit for the
 * given destination or zero if the destination is not reachable.
 */
u_int ipMTU(u_long dstAddr)
{
	u_int st;
	
	if (dstAddr == htonl(localHost) || dstAddr == htonl(LOOPADDR))
		st = NBUFSZ;
		
	else switch (defIfType) {
	case IFT_PPP:
		st = pppMTU(defIfID);
		break;
	default:
		st = 0;
		break;
	}
	
	IPDEBUG((LOG_INFO, TL_IP, "ipMTU: dst %s => %u", ip_ntoa(dstAddr), st));
	return st;
}

/*
 * ipSetDefault - set the default route.
 */
void ipSetDefault(u_int32_t l, u_int32_t g, IfType ifType, int ifID)
{
	localHost = ntohl(l);
	defIPAddr = g;
	defIfType = ifType;
	defIfID = ifID;
	IPDEBUG((LOG_INFO, TL_IP, "ipSetDefault: %s %s %d %d",
				ip_ntoa(l), 
				ip_ntoa2(g),
				ifType, ifID));
}

/*
 * ipClearDefault - clear the default route.
 */
void ipClearDefault(void)
{
	defIPAddr = 0;
	defIfType = IFT_UNSPEC;
	defIfID = 0;
	IPDEBUG((LOG_INFO, TL_IP, "ipClearDefault"));
}

/*
 * Make a string representation of a network IP address.
 * WARNING: NOT RE-ENTRANT!
 */
char *ip_ntoa(u_int32_t ipaddr)
{
	static char b[20];
	
	ipaddr = ntohl(ipaddr);
	
	sprintf(b, "%d.%d.%d.%d",
			(u_char)(ipaddr >> 24),
			(u_char)(ipaddr >> 16),
			(u_char)(ipaddr >> 8),
			(u_char)(ipaddr));
	return b;
}
/* A second buffer if you want 2 addresses in one printf. */
char *ip_ntoa2(u_int32_t ipaddr)
{
	static char b[20];
	
	ipaddr = ntohl(ipaddr);
	
	sprintf(b, "%d.%d.%d.%d",
			(u_char)(ipaddr >> 24),
			(u_char)(ipaddr >> 16),
			(u_char)(ipaddr >> 8),
			(u_char)(ipaddr));
	return b;
}

/*
 * Make a string representation of a host IP address.
 * WARNING: NOT RE-ENTRANT!
 */
char *ip_htoa(u_int32_t ipaddr)
{
	static char b[20];
		
	sprintf(b, "%d.%d.%d.%d",
			(u_char)(ipaddr >> 24),
			(u_char)(ipaddr >> 16),
			(u_char)(ipaddr >> 8),
			(u_char)(ipaddr));
	return b;
}

/**********************************/
/*** LOCAL FUNCTION DEFINITIONS ***/
/**********************************/
/*
 * ipDispatch - Dispatch a "prepared" IP datagram according to it's source
 * and destination IP addresses and its protocol.
 * By prepared, the buffer's data pointer references the start of the IP
 * header and the length, identification, and offset fields are in HOST
 * byte order.  The IP address fields are in network byte order.
 */
static void ipDispatch(NBuf *outBuf)
{
	IPHdr 	*ip			= nBUFTOPTR(outBuf, IPHdr *);
	u_char	hdrLen		= ip->ip_hl * 4;
	u_long	srcAddr		= ip->ip_src.s_addr;
	u_long	dstAddr		= ip->ip_dst.s_addr;
	
	IPDEBUG((LOG_INFO, TL_IP, "ipDispatch: len %u proto %u to %s from %s tos %d",
				ip->ip_len, ip->ip_p,
				ip_ntoa(dstAddr), 
				ip_ntoa2(srcAddr),
				ip->ip_tos));
	
	/* Validata the IP header. */
	if (ip->ip_len < hdrLen) {
		IPDEBUG((LOG_ERR, TL_IP, "ipDispatch: Dropped short len %u proto %u to %s from %s", 
				 ip->ip_len,
				 ip->ip_p,
				 ip_ntoa(dstAddr), 
				 ip_ntoa2(srcAddr)));
		STATS(ipStats.ips_badlen.val++;)
		nFreeChain(outBuf);
	}
	
	/* If destined for us, dispatch according to the protocol. */
	/* 
	 * Note: We catch the loopback address here instead of passing it
	 * to a loopback interface so that this one dispatch function may
	 * handle both input and output. 
	 */
	else if (dstAddr == htonl(localHost) || dstAddr == htonl(LOOPADDR)) {
		switch (ip->ip_p) {
		case IPPROTO_ICMP:
			icmpInput(outBuf, hdrLen);
			break;
		case IPPROTO_TCP:
			tcpInput(outBuf, hdrLen);
			break;
		default:
			IPDEBUG((LOG_ERR, TL_IP, 
					 "ipDispatch: Dropped bad protocol %d, len %u from %s to %s",
					 ip->ip_p,
					 ip->ip_len,
					 ip_ntoa(dstAddr), 
					 ip_ntoa2(srcAddr)));
			nFreeChain(outBuf);
			STATS(ipStats.ips_odropped.val++;)
		}
	}
	
	/*
	 * Otherwise, if not from us, we're not a router so drop it.
	 * XXX We could (should?) send an ICMP message. 
	 */
	else if (srcAddr != htonl(localHost)) {
		IPDEBUG((LOG_ERR, TL_IP,
				 "ipDispatch: Dropped can't fwd len %u proto %u to %s from %s",
				 ip->ip_len, ip->ip_p,
				 ip_ntoa(dstAddr), 
				 ip_ntoa2(srcAddr)));
		STATS(ipStats.ips_cantforward.val++;)
		nFreeChain(outBuf);
	}
	
	/* If we made it here, send it out. */
	else switch (defIfType) {
	case IFT_PPP:
		/* Convert fields to network representation. */
		HTONS(ip->ip_len);
		HTONS(ip->ip_id);
		HTONS(ip->ip_off);
		
		/* Checksum the header. */
		ip->ip_sum = 0;
		ip->ip_sum = inChkSum(outBuf, hdrLen, 0);
		
		pppOutput(defIfID, PPP_IP, outBuf);
		STATS(ipStats.ips_delivered.val++;)
		break;
	default:
		IPDEBUG((LOG_ERR, TL_IP,
				 "ipDispatch: Dropped bad if %d len %u proto %u to %s from %s", 
				 defIfType,
				 ip->ip_len, ip->ip_p,
				 ip_ntoa(dstAddr), 
				 ip_ntoa2(srcAddr)));
		nFreeChain(outBuf);
		STATS(ipStats.ips_odropped.val++;)
		break;
	}
}


⌨️ 快捷键说明

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