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

📄 icmplib.c

📁 vxworks源码源码解读是学习vxworks的最佳途径
💻 C
字号:
/* icmpLib.c - VxWorks library for ICMP routines *//* Copyright 1984 - 1999 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01o,17mar99,spm  added support for identical unit numbers (SPR #20913)01n,17nov98,n_s  fixed icmpMaskGet for non-END devices. spr 23005.01m,08dec97,gnn  END code review fixes.01l,05oct97,vin  added header file ip_var.h01k,03oct97,gnn  removed necessity for endDriver global01j,25sep97,gnn  SENS beta feedback fixes01i,12aug97,gnn  changes necessitated by MUX/END update.01h,20jan97,vin  added icmpLibInit for scaling.01g,17dec96,gnn  added code to handle the new etherHooks and END stuff.01f,05aug94,dzb  set IP address of interface in arpcom struct (SPR #2706).01e,30jun92,jmm  moved checksum() to vxLib01d,11jun92,elh	 changed parameters to ipHeaderCreate.01c,26may92,rrr  the tree shuffle		  -changed includes to have absolute path from h/01b,16apr92,elh	 moved routines shared by bootpLib here.01a,11mar91,elh	 written.*//*DESCRIPTIONicmpLib contains routines that use ICMP.  icmpMaskGet is currently the only routine in this library.  icmpMaskGet generates and sendsan ICMP address mask request to obtain the subnet mask of the network.It gets called during boot time to find the mask of the boot interface.The routine icmpLibInit() is responsible for configuring the ICMP protocolwith various parameters.*//* includes */#include "vxWorks.h"#include "net/protosw.h"#include "net/domain.h"#include "netinet/in.h"#include "netinet/in_systm.h"#include "netinet/in_pcb.h"#include "netinet/ip_var.h"#include "netinet/ip.h"#include "netinet/ip_icmp.h"#include "netLib.h"#include "etherLib.h"#include "errno.h"#include "icmpLib.h"#include "sysLib.h"#include "string.h"#include "taskLib.h"#include "stdio.h"#include "tickLib.h"#include "inetLib.h"#include "vxLib.h"#include "end.h"#include "ipProto.h"#include "muxLib.h"/* externs */IMPORT int		_protoSwIndex;IMPORT struct protosw 	inetsw [IP_PROTO_NUM_MAX]; IMPORT int		icmpmaskrepl;/* defines */#define ICMP_REXMT_DELAY	1	/* retransmit delay (secs) */#define ICMP_MAX_SEND		2	/* maximum requests *//* locals */LOCAL	BOOL		maskReplyReceived;	/* recv mask reply 	*/LOCAL	char		inputBuffer [ETHERMTU]; /* input buffer 	*/LOCAL	struct icmp	*pIcmpReply;		/* pointer to reply	*/LOCAL struct    {    struct ip	ih;				/* IP header		*/    struct icmp	icmph;				/* ICMP header		*/    } icmpMsg;/* forward declarations */LOCAL BOOL icmpMaskInputHook (struct ifnet * pIf, char * pBuffer, int length);extern	   in_broadcast ();STATUS icmpLibInit     (    ICMP_CFG_PARAMS * 	icmpCfg		/* icmp configuration parameters */    )    {    FAST struct protosw	* pProtoSwitch;     if (_protoSwIndex >= sizeof(inetsw)/sizeof(inetsw[0]))	return (ERROR) ;    pProtoSwitch = &inetsw [_protoSwIndex];     if (pProtoSwitch->pr_domain != NULL)	return (OK); 				/* already initialized */    pProtoSwitch->pr_type   	=  SOCK_RAW;    pProtoSwitch->pr_domain   	=  &inetdomain;    pProtoSwitch->pr_protocol   =  IPPROTO_ICMP;    pProtoSwitch->pr_flags	=  PR_ATOMIC | PR_ADDR;    pProtoSwitch->pr_input	=  icmp_input;    pProtoSwitch->pr_output	=  rip_output;    pProtoSwitch->pr_ctlinput	=  0;    pProtoSwitch->pr_ctloutput	=  rip_ctloutput;    pProtoSwitch->pr_usrreq	=  rip_usrreq;    pProtoSwitch->pr_init	=  icmp_init;    pProtoSwitch->pr_fasttimo	=  0;    pProtoSwitch->pr_slowtimo	=  0;    pProtoSwitch->pr_drain	=  0;    pProtoSwitch->pr_sysctl	=  0;    _protoSwIndex++;     /* initialize icmp configuration parameters */    icmpmaskrepl = (icmpCfg->icmpCfgFlags & ICMP_DO_MASK_REPLY) ? TRUE : FALSE;    return (OK);     }/******************************************************************************** icmpMaskGet - obtain the subnet mask ** icmpMask broadcasts an ICMP Address Mask Request over the network* interface specified by <ifName> to obtain the subnet mask of that network.* This interface, must have been previously attached, but not necessarily* initialized.  <src> specifies the source IP address, which is required* if the interface has not already been initialized, and is optional* otherwise.  A NULL value for <src> results in the reply being broadcasted.* <dst> specifies and optional destination.  A NULL value for <dst> results* in the request being broadcasted.** The subnet mask gets returned in <pSubnet> in host byte order.** INTERNAL* icmpMaskGet uses etherhooks to access the network, because at boot* time the network is not initialized (it doesn't know its IP address).** RETURNS: OK if successful, otherwise ERROR.** ERRNO*   S_icmpLib_NO_BROADCAST*   S_icmpLib_INVALID_INTERFACE** NOMANUAL*/STATUS icmpMaskGet    (    char *		ifName,		/* network interface name */    char * 		src,		/* optional src address */    char *		dst,		/* optional dst address */    int	*		pSubnet		/* return subnet mask 	*/    )    {    FAST int 		retransmitSecs;	/* retransmit time 	*/    FAST int		tickCount;    int			ix;		/* index 		*/    struct in_addr	srcAddr;	/* source address 	*/    struct in_addr	dstAddr;	/* destination address	*/    struct ifnet *	pIf;		/* pointer to interface */    END_OBJ * 	pEnd;    if ((pIf = ifunit (ifName)) == NULL)	{	errno = S_icmpLib_INVALID_INTERFACE;	return (ERROR);				/* interface not attached */	}    pEnd = endFindByName (pIf->if_name, pIf->if_unit);    if (src == NULL)        srcAddr.s_addr = htonl (INADDR_ANY);    else					/* bind IP address to ac */	{        srcAddr.s_addr = inet_addr (src);        ((struct arpcom *) pIf)->ac_ipaddr.s_addr = srcAddr.s_addr;	}    if (dst == NULL)	{        if ((pIf->if_flags & IFF_BROADCAST) == 0)	    {	    errno = S_icmpLib_NO_BROADCAST;	    return (ERROR);				/* no broadcasts */	    }	dstAddr.s_addr = htonl (INADDR_BROADCAST);	}    else	dstAddr.s_addr = inet_addr (dst);    pIf->if_flags |= (IFF_UP | IFF_RUNNING);    retransmitSecs	= ICMP_REXMT_DELAY; 	/* set delay value */    maskReplyReceived	= FALSE;    						/* fill in icmp message */    bzero ((char *) &icmpMsg, sizeof (icmpMsg));    icmpMsg.icmph.icmp_type  = ICMP_MASKREQ;    icmpMsg.icmph.icmp_code  = 0;    icmpMsg.icmph.icmp_cksum = 0;    icmpMsg.icmph.icmp_cksum = checksum ((u_short *) &icmpMsg.icmph, 					 ICMP_MASKLEN);    ipHeaderCreate (IPPROTO_ICMP,  &srcAddr, &dstAddr, &icmpMsg.ih,	            sizeof (struct ip) + ICMP_MASKLEN);    if (pEnd)        {        etherInputHookAdd (icmpMaskInputHook, pIf->if_name, pIf->if_unit);        }    else        {        (void) etherInputHookAdd (icmpMaskInputHook, NULL, 0);        }        for (ix = 0; ix < ICMP_MAX_SEND;  ix++)	{	/* send message */	if (etherSend (pIf, &icmpMsg.ih, sizeof (struct ip) +		       ICMP_MASKLEN) == ERROR)	    {            if (pEnd)                etherInputHookDelete (icmpMaskInputHook, pIf->if_name,                                      pIf->if_unit);            else                etherInputHookDelete (icmpMaskInputHook);	    return (ERROR);	    }	/* wait for reply */	tickCount = retransmitSecs * sysClkRateGet ();	while (tickCount-- > 0)	    {	    if (maskReplyReceived)		{                if (pEnd)                    etherInputHookDelete (icmpMaskInputHook, pIf->if_name,                                          pIf->if_unit);                else                    etherInputHookDelete (icmpMaskInputHook);    		*pSubnet = ntohl (pIcmpReply->icmp_mask);    		return (OK);		}	    taskDelay (1);	    }	}    if (pEnd)        etherInputHookDelete (icmpMaskInputHook, pIf->if_name, pIf->if_unit);    else        etherInputHookDelete (icmpMaskInputHook);    errno = S_icmpLib_TIMEOUT;    return (ERROR);				/* no subnet */    }/******************************************************************************** icmpMaskInputHook - input hook to filter ICMP Address Mask Reply** This routine filters out the ICMP Address Mask Reply message from incoming* ethernet traffic.  This function is called by the network interface* driver when a new input frame comes in from the network.  It is* hooked into the driver via etherHook routines.** RETURNS:* TRUE indicating the ethernet frame is handled by this routine and* no further processing need be done by the network interface driver.* FALSE indicating the ethernet frame is to be handled by the network* interface driver.*/LOCAL BOOL icmpMaskInputHook    (    struct ifnet *	pIf, 		/* network interface 	*/    FAST char *		pBuffer,	/* input data frame 	*/    FAST int		length		/* input data length 	*/    )    {    struct ether_header	* pEh; 		/* ethernet header	*/    int			bufLen;		/* buffer length	*/    if (maskReplyReceived)		/* already got a reply */	return (FALSE);    pEh = (struct ether_header *) pBuffer;    if ((length <= SIZEOF_ETHERHEADER) ||	(ntohs (pEh->ether_type) != ETHERTYPE_IP))	return (FALSE);    /* copy into local buffer */    bufLen = length - SIZEOF_ETHERHEADER;    bcopyBytes ((char *) ((u_char *) pBuffer + SIZEOF_ETHERHEADER),		inputBuffer, bufLen);    pIcmpReply = (struct icmp *) ipHeaderVerify ((struct ip *) inputBuffer,						 bufLen, IPPROTO_ICMP);    if ((pIcmpReply == NULL) ||	(checksum ((u_short *) pIcmpReply, ICMP_MASKLEN) != 0) ||        (pIcmpReply->icmp_type != ICMP_MASKREPLY))	return (FALSE);    maskReplyReceived = TRUE;    return (TRUE);    }/******************************************************************************** ipHeaderCreate - create a simple IP header** This generates a simple IP header (with no options) and checksums it.* <proto> specifies the protocol type. <pSrcAddr> and <pDstAddr> define* the source and destination internet addresses, respectively.  Both should* be specified in network byte order.  <pih> is a pointer to an internet* datagram whose length is <length>.** RETURNS: N/A** NOMANUAL*/void ipHeaderCreate    (    int			proto,		/* protocol number	*/    struct in_addr *	pSrcAddr,	/* source ip address 	*/    struct in_addr *	pDstAddr,	/* dest ip address	*/    struct ip *		pih,		/* internet header 	*/    int			length		/* datagram size 	*/    )    {    					/* fill in the IP header */    pih->ip_v = IPVERSION;    pih->ip_hl = (sizeof (struct ip) >> 2) & 0xf;      pih->ip_len	= htons ((u_short) length);    pih->ip_id	= (u_short) (tickGet () & 0xffff);    pih->ip_ttl	= MAXTTL;    pih->ip_p	= (u_char) proto;    pih->ip_src.s_addr	= pSrcAddr->s_addr;    pih->ip_dst.s_addr	= pDstAddr->s_addr;    pih->ip_sum	= 0;	/* zero out the checksum while computing it */    pih->ip_sum = checksum ((u_short *) pih, (pih->ip_hl << 2));    }/********************************************************************************* ipHeaderVerify - simple IP header verification** ipHeaderVerify performs simple IP header verification.  It does* sanity checks and verifies the checksum.  <pih> points to an internet* datagram of length <length>.  <proto> is the expected protocol.** RETURNS: a pointer to the IP data, or NULL if not a valid IP datagram.** NOMANUAL*/u_char * ipHeaderVerify    (    struct ip *		pih, 		/* internet header	*/    int			length,		/* length of datagram 	*/    int			proto  		/* protocol */    )    {    FAST int		options;	/* options offset 	*/    /* if not minimum size, or right protocol bail */    if ((length < sizeof (struct ip)) || (pih->ip_p != (u_char) proto))	return (NULL);					/* verify checksum */    if (checksum ((u_short *) pih, (pih->ip_hl << 2)) != 0)	return (NULL);    if ((pih->ip_v != IPVERSION) ||	(ntohs ((u_short) pih->ip_off) & 0x3FFF))	return (NULL);					/* ip_hl is in words */    options = (pih->ip_hl << 2) - sizeof (struct ip);    return ((u_char *) pih + sizeof (struct ip) + options);    }/********************************************************************************* etherSend  - send an IP datagram over ether hooks.** etherSend uses etherOutput to send an IP datagram whose header is* pointed to by <pDatagram> and whose length is <length> over the network* interface specified by <pIf>.  The destination must reside on the local* network associated with <pIf> since it may try to resolve this address* via ARP.** RETURNS: OK if successful, otherwise ERROR.** NOMANUAL*/STATUS etherSend    (    struct ifnet *	pIf,		/* network interface	*/    struct ip *		pDatagram,	/* buffer pointer 	*/    int			length 		/* buffer size		*/    )    {    struct ether_header	eh; 		/* ethernet header 	*/    char	        ipDestAscii [ INET_ADDR_LEN ];    bzero ((char *) &eh, sizeof (struct ether_header));    /* if IP broadcast, then use the ethernet broadcast address */    if (in_broadcast (pDatagram->ip_dst, pIf))        bcopy ((char *) etherbroadcastaddr, (char *) eh.ether_dhost,	       sizeof (etherbroadcastaddr));    else	{				/* else use ARP to find dest */        inet_ntoa_b (pDatagram->ip_dst, ipDestAscii);        if (etherAddrResolve (pIf, ipDestAscii, (char *) eh.ether_dhost,			      5, 2 * sysClkRateGet()) == ERROR)	    return (ERROR);	}    eh.ether_type = ETHERTYPE_IP;	/* htons is in ether_output */    if (etherOutput (pIf, &eh, (char *) pDatagram, length) == ERROR)	return (ERROR);    return (OK);    }

⌨️ 快捷键说明

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