#include "headers.h" static BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header); static BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header); static VOID DumpIpv6Header(IPV6Header *pstIpv6Header); static UCHAR * GetNextIPV6ChainedHeader(UCHAR **ppucPayload,UCHAR *pucNextHeader,BOOLEAN *bParseDone,USHORT *pusPayloadLength) { UCHAR *pucRetHeaderPtr = NULL; UCHAR *pucPayloadPtr = NULL; USHORT usNextHeaderOffset = 0 ; PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); if((NULL == ppucPayload) || (*pusPayloadLength == 0) || (*bParseDone)) { *bParseDone = TRUE; return NULL; } pucRetHeaderPtr = *ppucPayload; pucPayloadPtr = *ppucPayload; if(!pucRetHeaderPtr || !pucPayloadPtr) { *bParseDone = TRUE; return NULL; } //Get the Nextt Header Type *bParseDone = FALSE; switch(*pucNextHeader) { case IPV6HDR_TYPE_HOPBYHOP: { BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 HopByHop Header"); usNextHeaderOffset+=sizeof(IPV6HopByHopOptionsHeader); } break; case IPV6HDR_TYPE_ROUTING: { IPV6RoutingHeader *pstIpv6RoutingHeader; BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Routing Header"); pstIpv6RoutingHeader = (IPV6RoutingHeader *)pucPayloadPtr; usNextHeaderOffset += sizeof(IPV6RoutingHeader); usNextHeaderOffset += pstIpv6RoutingHeader->ucNumAddresses * IPV6_ADDRESS_SIZEINBYTES; } break; case IPV6HDR_TYPE_FRAGMENTATION: { BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Fragmentation Header"); usNextHeaderOffset+= sizeof(IPV6FragmentHeader); } break; case IPV6HDR_TYPE_DESTOPTS: { IPV6DestOptionsHeader *pstIpv6DestOptsHdr = (IPV6DestOptionsHeader *)pucPayloadPtr; int nTotalOptions = pstIpv6DestOptsHdr->ucHdrExtLen; BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 DestOpts Header Header"); usNextHeaderOffset+= sizeof(IPV6DestOptionsHeader); usNextHeaderOffset+= nTotalOptions * IPV6_DESTOPTS_HDR_OPTIONSIZE ; } break; case IPV6HDR_TYPE_AUTHENTICATION: { IPV6AuthenticationHeader *pstIpv6AuthHdr = (IPV6AuthenticationHeader *)pucPayloadPtr; int nHdrLen = pstIpv6AuthHdr->ucLength; BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Authentication Header"); usNextHeaderOffset+= nHdrLen * 4; } break; case IPV6HDR_TYPE_ENCRYPTEDSECURITYPAYLOAD: { BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Encrypted Security Payload Header"); *bParseDone = TRUE; } break; case IPV6_ICMP_HDR_TYPE: { BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, " ICMP Header"); *bParseDone = TRUE; } break; case TCP_HEADER_TYPE: { BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, " \nTCP Header"); *bParseDone = TRUE; } break; case UDP_HEADER_TYPE: { BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, " \nUDP Header"); *bParseDone = TRUE; } break; default : { *bParseDone = TRUE; } break; } if(*bParseDone == FALSE) { if(*pusPayloadLength <= usNextHeaderOffset) { *bParseDone = TRUE; } else { *pucNextHeader = *pucPayloadPtr; pucPayloadPtr+=usNextHeaderOffset; (*pusPayloadLength)-=usNextHeaderOffset; } } *ppucPayload = pucPayloadPtr; return pucRetHeaderPtr; } static UCHAR GetIpv6ProtocolPorts(UCHAR *pucPayload,USHORT *pusSrcPort,USHORT *pusDestPort,USHORT usPayloadLength,UCHAR ucNextHeader) { UCHAR *pIpv6HdrScanContext = pucPayload; BOOLEAN bDone = FALSE; UCHAR ucHeaderType =0; UCHAR *pucNextHeader = NULL; PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); if( !pucPayload || (usPayloadLength == 0)) { return 0; } *pusSrcPort = *pusDestPort = 0; ucHeaderType = ucNextHeader; while(!bDone) { pucNextHeader = GetNextIPV6ChainedHeader(&pIpv6HdrScanContext,&ucHeaderType,&bDone,&usPayloadLength); if(bDone) { if((ucHeaderType==TCP_HEADER_TYPE) || (ucHeaderType == UDP_HEADER_TYPE)) { *pusSrcPort=*((PUSHORT)(pucNextHeader)); *pusDestPort=*((PUSHORT)(pucNextHeader+2)); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, " \nProtocol Ports - Src Port :0x%x Dest Port : 0x%x",ntohs(*pusSrcPort),ntohs(*pusDestPort)); } break; } } return ucHeaderType; } USHORT IpVersion6(PMINI_ADAPTER Adapter, /**< Pointer to the driver control structure */ PVOID pcIpHeader, /**<Pointer to the IP Hdr of the packet*/ S_CLASSIFIER_RULE *pstClassifierRule ) { USHORT ushDestPort = 0; USHORT ushSrcPort = 0; UCHAR ucNextProtocolAboveIP =0; IPV6Header *pstIpv6Header = NULL; BOOLEAN bClassificationSucceed = FALSE; BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "IpVersion6 ==========>\n"); pstIpv6Header = (IPV6Header *)pcIpHeader; DumpIpv6Header(pstIpv6Header); //Try to get the next higher layer protocol and the Ports Nos if TCP or UDP ucNextProtocolAboveIP = GetIpv6ProtocolPorts((UCHAR *)(pcIpHeader + sizeof(IPV6Header)), &ushSrcPort, &ushDestPort, pstIpv6Header->usPayloadLength, pstIpv6Header->ucNextHeader); do { if(0 == pstClassifierRule->ucDirection) { //cannot be processed for classification. // it is a down link connection break; } if(!pstClassifierRule->bIpv6Protocol) { //We are looking for Ipv6 Classifiers . Lets ignore this classifier and try the next one. break; } bClassificationSucceed=MatchSrcIpv6Address(pstClassifierRule,pstIpv6Header); if(!bClassificationSucceed) break; bClassificationSucceed=MatchDestIpv6Address(pstClassifierRule,pstIpv6Header); if(!bClassificationSucceed) break; //Match the protocol type.For IPv6 the next protocol at end of Chain of IPv6 prot headers bClassificationSucceed=MatchProtocol(pstClassifierRule,ucNextProtocolAboveIP); if(!bClassificationSucceed) break; BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Protocol Matched"); if((ucNextProtocolAboveIP == TCP_HEADER_TYPE) || (ucNextProtocolAboveIP == UDP_HEADER_TYPE)) { //Match Src Port BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Source Port:%x\n",ntohs(ushSrcPort)); bClassificationSucceed=MatchSrcPort(pstClassifierRule,ntohs(ushSrcPort)); if(!bClassificationSucceed) break; BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Src Port Matched"); //Match Dest Port BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Destination Port:%x\n",ntohs(ushDestPort)); bClassificationSucceed=MatchDestPort(pstClassifierRule,ntohs(ushDestPort)); if(!bClassificationSucceed) break; BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Dest Port Matched"); } }while(0); if(TRUE==bClassificationSucceed) { INT iMatchedSFQueueIndex = 0; iMatchedSFQueueIndex = SearchSfid(Adapter,pstClassifierRule->ulSFID); if(iMatchedSFQueueIndex >= NO_OF_QUEUES) { bClassificationSucceed = FALSE; } else { if(FALSE == Adapter->PackInfo[iMatchedSFQueueIndex].bActive) { bClassificationSucceed = FALSE; } } } return bClassificationSucceed; } static BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header) { UINT uiLoopIndex=0; UINT uiIpv6AddIndex=0; UINT uiIpv6AddrNoLongWords = 4; ULONG aulSrcIP[4]; PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); /* //This is the no. of Src Addresses ie Range of IP Addresses contained //in the classifier rule for which we need to match */ UINT uiCountIPSrcAddresses = (UINT)pstClassifierRule->ucIPSourceAddressLength; if(0 == uiCountIPSrcAddresses) return TRUE; //First Convert the Ip Address in the packet to Host Endian order for(uiIpv6AddIndex=0;uiIpv6AddIndex<uiIpv6AddrNoLongWords;uiIpv6AddIndex++) { aulSrcIP[uiIpv6AddIndex]=ntohl(pstIpv6Header->ulSrcIpAddress[uiIpv6AddIndex]); } for(uiLoopIndex=0;uiLoopIndex<uiCountIPSrcAddresses;uiLoopIndex+=uiIpv6AddrNoLongWords) { BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Src Ipv6 Address In Received Packet : \n "); DumpIpv6Address(aulSrcIP); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Src Ipv6 Mask In Classifier Rule: \n"); DumpIpv6Address(&pstClassifierRule->stSrcIpAddress.ulIpv6Mask[uiLoopIndex]); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Src Ipv6 Address In Classifier Rule : \n"); DumpIpv6Address(&pstClassifierRule->stSrcIpAddress.ulIpv6Addr[uiLoopIndex]); for(uiIpv6AddIndex=0;uiIpv6AddIndex<uiIpv6AddrNoLongWords;uiIpv6AddIndex++) { if((pstClassifierRule->stSrcIpAddress.ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] & aulSrcIP[uiIpv6AddIndex]) != pstClassifierRule->stSrcIpAddress.ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex]) { //Match failed for current Ipv6 Address.Try next Ipv6 Address break; } if(uiIpv6AddIndex == uiIpv6AddrNoLongWords-1) { //Match Found BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Ipv6 Src Ip Address Matched\n"); return TRUE; } } } return FALSE; } static BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header) { UINT uiLoopIndex=0; UINT uiIpv6AddIndex=0; UINT uiIpv6AddrNoLongWords = 4; ULONG aulDestIP[4]; PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); /* //This is the no. of Destination Addresses ie Range of IP Addresses contained //in the classifier rule for which we need to match */ UINT uiCountIPDestinationAddresses = (UINT)pstClassifierRule->ucIPDestinationAddressLength; if(0 == uiCountIPDestinationAddresses) return TRUE; //First Convert the Ip Address in the packet to Host Endian order for(uiIpv6AddIndex=0;uiIpv6AddIndex<uiIpv6AddrNoLongWords;uiIpv6AddIndex++) { aulDestIP[uiIpv6AddIndex]=ntohl(pstIpv6Header->ulDestIpAddress[uiIpv6AddIndex]); } for(uiLoopIndex=0;uiLoopIndex<uiCountIPDestinationAddresses;uiLoopIndex+=uiIpv6AddrNoLongWords) { BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Destination Ipv6 Address In Received Packet : \n "); DumpIpv6Address(aulDestIP); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Destination Ipv6 Mask In Classifier Rule: \n"); DumpIpv6Address(&pstClassifierRule->stDestIpAddress.ulIpv6Mask[uiLoopIndex]); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Destination Ipv6 Address In Classifier Rule : \n"); DumpIpv6Address(&pstClassifierRule->stDestIpAddress.ulIpv6Addr[uiLoopIndex]); for(uiIpv6AddIndex=0;uiIpv6AddIndex<uiIpv6AddrNoLongWords;uiIpv6AddIndex++) { if((pstClassifierRule->stDestIpAddress.ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] & aulDestIP[uiIpv6AddIndex]) != pstClassifierRule->stDestIpAddress.ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex]) { //Match failed for current Ipv6 Address.Try next Ipv6 Address break; } if(uiIpv6AddIndex == uiIpv6AddrNoLongWords-1) { //Match Found BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Ipv6 Destination Ip Address Matched\n"); return TRUE; } } } return FALSE; } VOID DumpIpv6Address(ULONG *puIpv6Address) { UINT uiIpv6AddrNoLongWords = 4; UINT uiIpv6AddIndex=0; PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); for(uiIpv6AddIndex=0;uiIpv6AddIndex<uiIpv6AddrNoLongWords;uiIpv6AddIndex++) { BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, ":%lx",puIpv6Address[uiIpv6AddIndex]); } } static VOID DumpIpv6Header(IPV6Header *pstIpv6Header) { UCHAR ucVersion; UCHAR ucPrio ; PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "----Ipv6 Header---"); ucVersion = pstIpv6Header->ucVersionPrio & 0xf0; BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Version : %x \n",ucVersion); ucPrio = pstIpv6Header->ucVersionPrio & 0x0f; BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Priority : %x \n",ucPrio); //BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Flow Label : %x \n",(pstIpv6Header->ucVersionPrio &0xf0); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Payload Length : %x \n",ntohs(pstIpv6Header->usPayloadLength)); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Next Header : %x \n",pstIpv6Header->ucNextHeader); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Hop Limit : %x \n",pstIpv6Header->ucHopLimit); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Src Address :\n"); DumpIpv6Address(pstIpv6Header->ulSrcIpAddress); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Dest Address :\n"); DumpIpv6Address(pstIpv6Header->ulDestIpAddress); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "----Ipv6 Header End---"); }