📄 etherlib.c
字号:
}/********************************************************************************* etherAddrResolve - find an Ethernet address for a specified Internet address** This routine uses the Address Resolution Protocol (ARP) and internal ARP* cache to resolve the Ethernet address of a machine that owns the Internet* address given in <targetAddr>.** The first argument <pIf> is a pointer to a variable of type `struct ifnet'* which identifies the network interface through which the ARP request messages* are to be sent out. The routine ifunit() is used to retrieve this pointer* from the system in the following way:* .CS* struct ifnet *pIf;* ...* pIf = ifunit ("ln0");* .CE* If ifunit() returns a non-NULL pointer, it is a valid pointer to* the named network interface device structure of type `struct ifnet'.* In the above example, <pIf> will be pointing to the data structure that* describes the first LANCE network interface device if ifunit() is* successful.** The six-byte Ethernet address is copied to <eHdr>, if the resolution of* <targetAddr> is successful. <eHdr> must point to a buffer of at least* six bytes.** RETURNS:* OK if the address is resolved successfully, or ERROR if <eHdr> is NULL,* <targetAddr> is invalid, or address resolution is unsuccessful.** SEE ALSO:* etherOutput()*/STATUS etherAddrResolve ( struct ifnet *pIf, /* interface on which to send ARP req */ char *targetAddr, /* name or Internet address of target */ char *eHdr, /* where to return the Ethernet addr */ int numTries, /* number of times to try ARPing */ int numTicks /* number of ticks between ARPing */ ) { struct sockaddr_in sockInetAddr; unsigned long addr; int retVal = 0; if (eHdr == NULL) /* user messed up */ return (ERROR); /* the 'targetAddr' can either be the hostname or the actual Internet * address. */ if ((addr = (unsigned long) hostGetByName (targetAddr)) == ERROR && (addr = inet_addr (targetAddr)) == ERROR) return (ERROR); sockInetAddr.sin_len = sizeof(struct sockaddr_in); sockInetAddr.sin_family = AF_INET; sockInetAddr.sin_addr.s_addr = addr; /* return 0xffffffffffff for broadcast Internet address */ if (in_broadcast (sockInetAddr.sin_addr, pIf)) { bcopy ((char *) etherbroadcastaddr, eHdr, sizeof (etherbroadcastaddr)); return (OK); } /* * Try to resolve the Ethernet address by calling arpresolve() which * may send ARP request messages out onto the Ethernet wire. */ while ((numTries == -1 || numTries-- > 0) && (retVal = arpresolve ((struct arpcom *) pIf, (struct rtentry *)NULL, (struct mbuf *) NULL, (struct sockaddr *)&sockInetAddr, (UCHAR *)eHdr)) == 0) taskDelay (numTicks); if (retVal == 0) /* unsuccessful resolution */ return (ERROR); return (OK); }/********************************************************************************* etherTypeGet - get the type from an ethernet packet** This routine returns a short that is the ethertype (defined in RFC* 1700) from either an 802.3 addressed packet or an RFC 894 packet.* Most packets are encoded as described in RFC 894 but 802.3 addressing* is also recognized.* * RETURNS: A USHORT value that is the ethertype, or 0 on error.** SEE ALSO:* .I "RFC 894, TCP/IP Illustrated,"* Volume 1, by Richard Stevens.*/USHORT etherTypeGet ( char *pPacket /* pointer to the beginning of the packet */ ) { ENET_HDR* pEnetHdr; struct llc* pLLCHdr; USHORT ether_type; /* Try for RFC 894 first as it's the most common. */ pEnetHdr = (ENET_HDR *)pPacket; ether_type = ntohs(pEnetHdr->type); /* Deal with 802.3 addressing. */ /* Here is the algorithm. */ /* If the ether_type is less than the MTU then we know that */ /* this is an 802.x address from RFC 1700. */ if (ether_type < ETHERMTU) { pLLCHdr = (struct llc *) pPacket; /* Now it may be IP over 802.x so we check to see if the */ /* destination SAP is IP, if so we snag the ethertype from the */ /* proper place. */ /* Now if it's NOT IP over 802.x then we just used the DSAP as */ /* the ether_type. */ if (pLLCHdr->llc_dsap == LLC_SNAP_LSAP) ether_type = ntohs(pLLCHdr->llc_un.type_snap.ether_type); else ether_type = pLLCHdr->llc_dsap; } /* Finally! Now, who says we should have standards comittees? */ /* Wouldn't it be easier, and cheaper just to shoot these losers? */ return (ether_type); }/******************************************************************************** etherInputHook - the system etherInputHook** This routine multiplexes packets to multiple input hooks.** RETURNS: TRUE if one of the routines that it called returns TRUE indicating* that the hook routine "ate" the packet, otherwise it returns FALSE.** NOMANUAL**/LOCAL BOOL etherInputHook ( struct ifnet *pIf, char *buffer, int length ) { HOOK_ENTRY *pHookEnt; extern LIST inputHookList; for (pHookEnt = (HOOK_ENTRY *)lstFirst(&inputHookList); pHookEnt != NULL; pHookEnt = (HOOK_ENTRY *)lstNext(&pHookEnt->node)) { if ((* pHookEnt->routine) (pIf, buffer, length)) return (TRUE); } return (FALSE); }/******************************************************************************** etherOutputHook - the system etherOutputHook** This routine is used to multiplex access to output hooks.** RETURNS: TRUE if one of its callee consumed the packet otherwise returns* FALSE.** NOMANUAL*/LOCAL BOOL etherOutputHook ( struct ifnet *pIf, char *buffer, int length ) { HOOK_ENTRY* pHookEnt; extern LIST outputHookList; for (pHookEnt = (HOOK_ENTRY *)lstFirst(&outputHookList); pHookEnt != NULL; pHookEnt = (HOOK_ENTRY *)lstNext(&pHookEnt->node)) { if ((* pHookEnt->routine) (pIf, buffer, length)) return (TRUE); } return (FALSE); }LOCAL BOOL endEtherInputHookRtn ( void * pCookie, long type, M_BLK_ID pMblk, /* Received frame (with link-level header). */ LL_HDR_INFO * pLinkHdrInfo, void * pSpare /* Extra protocol data. Unused. */ ) { HOOK_ENTRY * pHookEnt = (HOOK_ENTRY*) pSpare; char devName[32]; char packetData [ETHERMTU + SIZEOF_ETHERHEADER]; struct ifnet fakeIF; extern LIST inputHookList; int flags; int len; END_OBJ* pEnd=(END_OBJ*)pCookie; int ifHdrLen=0; bzero ( (char *)&fakeIF, sizeof (fakeIF)); fakeIF.if_name = &devName[0]; strcpy (fakeIF.if_name, pEnd->devObject.name); fakeIF.if_unit = pEnd->devObject.unit; muxIoctl (pHookEnt->pCookie, EIOCGFLAGS, (caddr_t)&flags); fakeIF.if_flags = flags; /* Get the Link Level header length . */ if (muxIoctl (pHookEnt->pCookie, EIOCGHDRLEN, (caddr_t)&ifHdrLen) != OK) fakeIF.if_hdrlen = 0; else fakeIF.if_hdrlen = (UCHAR)ifHdrLen; len = netMblkToBufCopy(pMblk, (char *)packetData, NULL); for (pHookEnt = (HOOK_ENTRY *)lstFirst (&inputHookList); pHookEnt != NULL; pHookEnt = (HOOK_ENTRY *)lstNext (&pHookEnt->node)) { if ( (* pHookEnt->routine) (&fakeIF, packetData, len)) { netMblkClChainFree (pMblk); /* hook has consumed the packet */ return (TRUE); } } return (FALSE); }/********************************************************************************** nptEtherInputHookRtn- EtherInputHook Receive Routine** This is the receive routine for the etherInputHook while binding to an NPT * device. This is very similar to endEtherInputHook except that it takes a* different arguments.**/LOCAL BOOL nptEtherInputHookRtn ( void * pCallBackId, /* Sent down in muxTkBind(); same as pSpare as in muxBind() */ long type, /* SNARF */ M_BLK_ID pMblk, /* Received frame (with link-level header). */ void * pSpareData /* Extra protocol data */ ) { HOOK_ENTRY * pHookEnt = (HOOK_ENTRY*) pCallBackId; char devName[32]; char packetData [ETHERMTU + SIZEOF_ETHERHEADER]; struct ifnet fakeIF; extern LIST inputHookList; int flags; int len; END_OBJ* pEnd=PCOOKIE_TO_ENDOBJ(pHookEnt->pCookie); int ifHdrLen=0; bzero ( (char *)&fakeIF, sizeof (fakeIF)); fakeIF.if_name = &devName[0]; strcpy (fakeIF.if_name, pEnd->devObject.name); fakeIF.if_unit = pEnd->devObject.unit; muxIoctl (pHookEnt->pCookie, EIOCGFLAGS, (caddr_t)&flags); fakeIF.if_flags = flags; /* Get the Link Level header length . */ if (muxIoctl (pHookEnt->pCookie, EIOCGHDRLEN, (caddr_t)&ifHdrLen) != OK) fakeIF.if_hdrlen = 0; else fakeIF.if_hdrlen = (UCHAR)ifHdrLen; len = netMblkToBufCopy(pMblk, (char *)packetData, NULL); for (pHookEnt = (HOOK_ENTRY *)lstFirst (&inputHookList); pHookEnt != NULL; pHookEnt = (HOOK_ENTRY *)lstNext (&pHookEnt->node)) { if ( (* pHookEnt->routine) (&fakeIF, packetData, len)) { netMblkClChainFree (pMblk); /* hook has consumed the packet */ return (TRUE); } } return (FALSE); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -