STATUS endEtherPacketDataGet ( M_BLK_ID pMblk, LL_HDR_INFO * pLinkHdrInfo ) { struct ether_header * pEnetHdr; struct ether_header enetHdr; struct llc * pLLCHdr; struct llc llcHdr; USHORT etherType; pLinkHdrInfo->destAddrOffset = 0; pLinkHdrInfo->destSize = 6; pLinkHdrInfo->srcAddrOffset = 6; pLinkHdrInfo->srcSize = 6; /* Try for RFC 894 first as it's the most common. */ /* * make sure entire ether_header is in first M_BLK * if not then copy the data to a temporary buffer */ if (pMblk->mBlkHdr.mLen < SIZEOF_ETHERHEADER) { pEnetHdr = &enetHdr; if (netMblkOffsetToBufCopy (pMblk, 0, (char *) pEnetHdr, SIZEOF_ETHERHEADER, (FUNCPTR) bcopy) < SIZEOF_ETHERHEADER) { return(ERROR); } } else pEnetHdr = (struct ether_header *)pMblk->mBlkHdr.mData; etherType = ntohs(pEnetHdr->ether_type); /* Deal with 802.3 addressing. */ /* Here is the algorithm. */ /* If the etherType is less than or equal to the MTU then we know that */ /* this is an 802.x address from RFC 1700. */ if (etherType <= ETHERMTU) { /* * make sure entire ether_header + llc_hdr is in first M_BLK * if not then copy the data to a temporary buffer */ if (pMblk->mBlkHdr.mLen < SIZEOF_ETHERHEADER + LLC_SNAP_FRAMELEN) { pLLCHdr = &llcHdr; if (netMblkOffsetToBufCopy (pMblk, SIZEOF_ETHERHEADER, (char *) pLLCHdr, LLC_SNAP_FRAMELEN, (FUNCPTR) bcopy) < LLC_SNAP_FRAMELEN) { return(ERROR); } } else pLLCHdr = (struct llc *)((char *)pEnetHdr + SIZEOF_ETHERHEADER); /* 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 etherType. */ if (pLLCHdr->llc_dsap == LLC_SNAP_LSAP) { etherType = ntohs(pLLCHdr->llc_un.type_snap.ether_type); pLinkHdrInfo->dataOffset = SIZEOF_ETHERHEADER + 8; } else { /* no SNAP header */ pLinkHdrInfo->dataOffset = SIZEOF_ETHERHEADER + 3; etherType = pLLCHdr->llc_dsap; } } else { pLinkHdrInfo->dataOffset = SIZEOF_ETHERHEADER; } pLinkHdrInfo->pktType = etherType; return(OK); }
int wdbEndInt ( void * pCookie, long type, M_BLK_ID pMblk, LL_HDR_INFO * pLinkHdrInfo, void * pMode ) { struct mbuf * pMbuf; int size; struct udphdr * pUdpHdr; struct ip * pIpHdr; WDB_END_PKT_DEV * pPktDev = pEndPktDev; /* input buffer already in use - drop this packet */ if (wdbEndDebug) logMsg ("Got a packet!\n", 1, 2, 3, 4, 5, 6); if (pPktDev->inputBusy) { if (wdbEndDebug) logMsg ("Input busy!\n", 1, 2, 3, 4, 5, 6); /* * free the packet only if the driver is in polling mode. If not, the * packet will be freed by the MUX layer. */ if ((pMode != NULL) && (*((int *)pMode) == WDB_COMM_MODE_POLL)) netMblkClFree (pMblk); return (FALSE); } pPktDev->inputBusy = TRUE; /* Check the type before doing anything expensive. */ if ((type == 0x806) && (pMode != NULL) && (*((int *)pMode) == WDB_COMM_MODE_POLL)) { /* * In polling mode we need to answer ARP request so that * communication becomes or remains possible. */ if (wdbEndDebug) logMsg ("Type == 0x806\n", 1, 2, 3, 4, 5, 6); return (wdbEndPollArpReply (pMblk, pCookie)); } if (type != 0x800) { if (wdbEndDebug) logMsg ("Type != 0x800 && Type!= 0x806\n", 1, 2, 3, 4, 5, 6); goto wdbEndIntError; } size = pLinkHdrInfo->dataOffset + IP_HDR_SIZE + sizeof(struct udphdr); if (!(pMblk->mBlkHdr.mFlags & M_PKTHDR) || (pMblk->mBlkPktHdr.len < size)) { goto wdbEndIntError; } if (pMblk->mBlkHdr.mLen < size) { if (netMblkOffsetToBufCopy (pMblk, pLinkHdrInfo->dataOffset, pInPkt, size, NULL) == 0) goto wdbEndIntError; pIpHdr = (struct ip *) pInPkt; pUdpHdr = (struct udphdr *)(pInPkt + IP_HDR_SIZE); } else { pIpHdr = (struct ip *) (pMblk->mBlkHdr.mData + pLinkHdrInfo->dataOffset); pUdpHdr = (struct udphdr *)(pMblk->mBlkHdr.mData + pLinkHdrInfo->dataOffset + IP_HDR_SIZE); } /* If this packet is not for the agent, ignore it */ if ((pIpHdr->ip_p != IPPROTO_UDP) || (pUdpHdr->uh_dport != htons(WDBPORT))) goto wdbEndIntError; if (pPktDev->ipAddr.s_addr != pIpHdr->ip_dst.s_addr) goto wdbEndIntError; /* * Check to see whether the packet is fragmented. WDB does not * handle fragmented packets. */ if (pIpHdr->ip_off & htons(IP_MF|IP_OFFMASK)) { if (wdbEndDebug) logMsg ("Fragmented packet\n", 0, 0, 0, 0, 0, 0); goto wdbEndIntError; } if ((size = netMblkOffsetToBufCopy (pMblk, pLinkHdrInfo->dataOffset, pInPkt, M_COPYALL, NULL)) == 0) goto wdbEndIntError; bcopy ((char *)pMblk->mBlkHdr.mData + pLinkHdrInfo->srcAddrOffset, (char *)pPktDev->lastHAddr->mBlkHdr.mData, pLinkHdrInfo->srcSize); /* We're always going to send an IP packet. */ pPktDev->lastHAddr->mBlkHdr.reserved = htons (0x800); /* * Fill the input buffer with the packet. Use an mbuf cluster * to pass the packet on to the agent. */ pMbuf = wdbMbufAlloc (); if (pMbuf == NULL) goto wdbEndIntError; wdbMbufClusterInit (pMbuf, pInPkt, size, (int (*)())wdbEndInputFree, (int)pPktDev); if (wdbEndDebug) logMsg ("Passing up a packet!\n", 1, 2, 3, 4, 5, 6); (*pPktDev->wdbDrvIf.stackRcv) (pMbuf); /* invoke callback */ netMblkClFree (pMblk); return (TRUE); wdbEndIntError: { /* * drop all non wdb packets received through the poll routine * When call from muxReceive pMode is actually the spare pointer * which is initialized in the NET_PROTOCOL structure, the spare * pointer is passed as the last argument to the stackRcvRtn. * When called from wdbEndPoll it passes a mode in the void pointer * This mode is used to find out whether this routine is called from * wdbEndPoll or muxReceive. You will not be happy camper if the * spare pointer is removed from NET_PROTOCOL or if the stackRcvRtn's * API is changed. */ if ((pMode != NULL) && (*((int *)pMode) == WDB_COMM_MODE_POLL)) netMblkClFree (pMblk); DRIVER_RESET_INPUT(pPktDev); return (FALSE); } }