📄 etherlib.c
字号:
lstDelete(&inputHookList, &pHookEnt->node); free (pHookEnt); } } } else /* 4.4 case */ { for (pHookEnt = (HOOK_ENTRY *)lstFirst(&inputHookList); pHookEnt != NULL; pHookEnt = (HOOK_ENTRY *)lstNext(&index)) { index = pHookEnt->node; if (pHookEnt->routine == inputHook) { lstDelete(&inputHookList, &pHookEnt->node); free(pHookEnt); } } } if (lstCount(&inputHookList) <= 0) { etherInputHookActive = FALSE; etherInputHookRtn = NULL; lstFree (&inputHookList); } }/********************************************************************************* etherOutputHookAdd - add a routine to receive all Ethernet output packets** This routine adds a hook routine that will be called for every Ethernet* packet that is transmitted.** The calling sequence of the output hook routine is:* .CS* BOOL outputHook* (* struct ifnet *pIf, /@ interface packet will be sent on @/* char *buffer, /@ packet to transmit @/* int length /@ length of packet to transmit @/* )* .CE* The hook is called immediately before transmission. The hook routine* should return TRUE if it has handled the output packet and no further* action should be taken with it. It should return FALSE if it has not* handled the output packet and normal transmission should take place.** The Ethernet packet data is in a temporary buffer when the hook routine* is called. This buffer will be reused upon return from the hook. If* the hook routine needs to retain the output packet, it should be copied* elsewhere.** IMPLEMENTATION* A call to the function pointed to be the global function pointer* `etherOutputHookRtn' should be invoked in the transmit routine of every* network driver providing this service. For example:* .ne 14* .CS* ...* #include "etherLib.h"* ...* xxxStartOutput ()* /@ call output hook if any @/* if ((etherOutputHookRtn != NULL) &&* (* etherOutputHookRtn) (&ls->ls_if, buf0, len))* {* /@ output hook has already processed this packet @/* }* else* ...* .CE** RETURNS: OK, if the hook could be added, ERROR otherwise.*/STATUS etherOutputHookAdd ( FUNCPTR outputHook /* routine to receive Ethernet output */ ) { HOOK_ENTRY *pHookEnt; pHookEnt = malloc(sizeof(HOOK_ENTRY)); if (pHookEnt == NULL) return (ERROR); if (etherOutputHookRtn == NULL) { etherOutputHookRtn = etherOutputHook; lstInit(&outputHookList); } pHookEnt->routine = outputHook; lstAdd(&outputHookList, &pHookEnt->node); return (OK); }/********************************************************************************* etherOutputHookDelete - delete a network interface output hook routine** This routine deletes a network interface output hook, which must be supplied* as the only argument.** RETURNS: N/A*/void etherOutputHookDelete ( FUNCPTR outputHook ) { HOOK_ENTRY *pHookEnt; extern LIST outputHookList; NODE index; for (pHookEnt = (HOOK_ENTRY *)lstFirst(&outputHookList); pHookEnt != NULL; pHookEnt = (HOOK_ENTRY *)lstNext(&index)) { index = pHookEnt->node; if (pHookEnt->routine == outputHook) { lstDelete(&outputHookList, &pHookEnt->node); free(pHookEnt); } } if (lstCount(&outputHookList) <= 0) { etherOutputHookRtn = NULL; lstFree(&outputHookList); } }/********************************************************************************* etherAddrResolve - resolve 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 out 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 we should also be* able to understand 802.3 addressing. * * 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; char devName[32]; char packetData [ETHERMTU + SIZEOF_ETHERHEADER]; struct ifnet fakeIF; extern LIST inputHookList; int flags; int len; bzero ( (char *)&fakeIF, sizeof (fakeIF)); fakeIF.if_name = &devName[0]; strcpy (fakeIF.if_name, ( (END_OBJ *)pCookie)->devObject.name); fakeIF.if_unit = ( (END_OBJ *)pCookie)->devObject.unit; muxIoctl (pCookie, EIOCGFLAGS, (caddr_t)&flags); fakeIF.if_flags = flags; 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 + -