Linux 3.3-rc6
[linux/fpc-iii.git] / drivers / staging / bcm / IPv6Protocol.c
blob5b4fd372ec367a4a818ddf34e9921b27eea36987
1 #include "headers.h"
3 static BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header);
4 static BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header);
5 static VOID DumpIpv6Header(IPV6Header *pstIpv6Header);
7 static UCHAR * GetNextIPV6ChainedHeader(UCHAR **ppucPayload,UCHAR *pucNextHeader,BOOLEAN *bParseDone,USHORT *pusPayloadLength)
9 UCHAR *pucRetHeaderPtr = NULL;
10 UCHAR *pucPayloadPtr = NULL;
11 USHORT usNextHeaderOffset = 0 ;
12 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
14 if((NULL == ppucPayload) || (*pusPayloadLength == 0) || (*bParseDone))
16 *bParseDone = TRUE;
17 return NULL;
21 pucRetHeaderPtr = *ppucPayload;
22 pucPayloadPtr = *ppucPayload;
24 if(!pucRetHeaderPtr || !pucPayloadPtr)
26 *bParseDone = TRUE;
27 return NULL;
30 //Get the Nextt Header Type
31 *bParseDone = FALSE;
35 switch(*pucNextHeader)
37 case IPV6HDR_TYPE_HOPBYHOP:
40 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 HopByHop Header");
41 usNextHeaderOffset+=sizeof(IPV6HopByHopOptionsHeader);
43 break;
45 case IPV6HDR_TYPE_ROUTING:
47 IPV6RoutingHeader *pstIpv6RoutingHeader;
48 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Routing Header");
49 pstIpv6RoutingHeader = (IPV6RoutingHeader *)pucPayloadPtr;
50 usNextHeaderOffset += sizeof(IPV6RoutingHeader);
51 usNextHeaderOffset += pstIpv6RoutingHeader->ucNumAddresses * IPV6_ADDRESS_SIZEINBYTES;
54 break;
55 case IPV6HDR_TYPE_FRAGMENTATION:
57 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Fragmentation Header");
58 usNextHeaderOffset+= sizeof(IPV6FragmentHeader);
61 break;
62 case IPV6HDR_TYPE_DESTOPTS:
64 IPV6DestOptionsHeader *pstIpv6DestOptsHdr = (IPV6DestOptionsHeader *)pucPayloadPtr;
65 int nTotalOptions = pstIpv6DestOptsHdr->ucHdrExtLen;
66 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 DestOpts Header Header");
67 usNextHeaderOffset+= sizeof(IPV6DestOptionsHeader);
68 usNextHeaderOffset+= nTotalOptions * IPV6_DESTOPTS_HDR_OPTIONSIZE ;
71 break;
72 case IPV6HDR_TYPE_AUTHENTICATION:
74 IPV6AuthenticationHeader *pstIpv6AuthHdr = (IPV6AuthenticationHeader *)pucPayloadPtr;
75 int nHdrLen = pstIpv6AuthHdr->ucLength;
76 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Authentication Header");
77 usNextHeaderOffset+= nHdrLen * 4;
79 break;
80 case IPV6HDR_TYPE_ENCRYPTEDSECURITYPAYLOAD:
82 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Encrypted Security Payload Header");
83 *bParseDone = TRUE;
86 break;
87 case IPV6_ICMP_HDR_TYPE:
89 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, " ICMP Header");
90 *bParseDone = TRUE;
92 break;
93 case TCP_HEADER_TYPE:
95 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, " \nTCP Header");
96 *bParseDone = TRUE;
98 break;
99 case UDP_HEADER_TYPE:
101 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, " \nUDP Header");
102 *bParseDone = TRUE;
104 break;
105 default :
107 *bParseDone = TRUE;
110 break;
115 if(*bParseDone == FALSE)
117 if(*pusPayloadLength <= usNextHeaderOffset)
119 *bParseDone = TRUE;
121 else
123 *pucNextHeader = *pucPayloadPtr;
124 pucPayloadPtr+=usNextHeaderOffset;
125 (*pusPayloadLength)-=usNextHeaderOffset;
132 *ppucPayload = pucPayloadPtr;
133 return pucRetHeaderPtr;
137 static UCHAR GetIpv6ProtocolPorts(UCHAR *pucPayload,USHORT *pusSrcPort,USHORT *pusDestPort,USHORT usPayloadLength,UCHAR ucNextHeader)
139 UCHAR *pIpv6HdrScanContext = pucPayload;
140 BOOLEAN bDone = FALSE;
141 UCHAR ucHeaderType =0;
142 UCHAR *pucNextHeader = NULL;
143 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
145 if( !pucPayload || (usPayloadLength == 0))
147 return 0;
150 *pusSrcPort = *pusDestPort = 0;
151 ucHeaderType = ucNextHeader;
152 while(!bDone)
154 pucNextHeader = GetNextIPV6ChainedHeader(&pIpv6HdrScanContext,&ucHeaderType,&bDone,&usPayloadLength);
155 if(bDone)
157 if((ucHeaderType==TCP_HEADER_TYPE) || (ucHeaderType == UDP_HEADER_TYPE))
159 *pusSrcPort=*((PUSHORT)(pucNextHeader));
160 *pusDestPort=*((PUSHORT)(pucNextHeader+2));
161 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));
163 break;
167 return ucHeaderType;
172 USHORT IpVersion6(PMINI_ADAPTER Adapter, /**< Pointer to the driver control structure */
173 PVOID pcIpHeader, /**<Pointer to the IP Hdr of the packet*/
174 S_CLASSIFIER_RULE *pstClassifierRule )
176 USHORT ushDestPort = 0;
177 USHORT ushSrcPort = 0;
178 UCHAR ucNextProtocolAboveIP =0;
179 IPV6Header *pstIpv6Header = NULL;
180 BOOLEAN bClassificationSucceed = FALSE;
182 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "IpVersion6 ==========>\n");
184 pstIpv6Header = (IPV6Header *)pcIpHeader;
186 DumpIpv6Header(pstIpv6Header);
188 //Try to get the next higher layer protocol and the Ports Nos if TCP or UDP
189 ucNextProtocolAboveIP = GetIpv6ProtocolPorts((UCHAR *)(pcIpHeader + sizeof(IPV6Header)),
190 &ushSrcPort,
191 &ushDestPort,
192 pstIpv6Header->usPayloadLength,
193 pstIpv6Header->ucNextHeader);
197 if(0 == pstClassifierRule->ucDirection)
199 //cannot be processed for classification.
200 // it is a down link connection
201 break;
204 if(!pstClassifierRule->bIpv6Protocol)
206 //We are looking for Ipv6 Classifiers . Lets ignore this classifier and try the next one.
207 break;
210 bClassificationSucceed=MatchSrcIpv6Address(pstClassifierRule,pstIpv6Header);
211 if(!bClassificationSucceed)
212 break;
214 bClassificationSucceed=MatchDestIpv6Address(pstClassifierRule,pstIpv6Header);
215 if(!bClassificationSucceed)
216 break;
218 //Match the protocol type.For IPv6 the next protocol at end of Chain of IPv6 prot headers
219 bClassificationSucceed=MatchProtocol(pstClassifierRule,ucNextProtocolAboveIP);
220 if(!bClassificationSucceed)
221 break;
222 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Protocol Matched");
224 if((ucNextProtocolAboveIP == TCP_HEADER_TYPE) || (ucNextProtocolAboveIP == UDP_HEADER_TYPE))
226 //Match Src Port
227 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Source Port:%x\n",ntohs(ushSrcPort));
228 bClassificationSucceed=MatchSrcPort(pstClassifierRule,ntohs(ushSrcPort));
229 if(!bClassificationSucceed)
230 break;
232 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Src Port Matched");
234 //Match Dest Port
235 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Destination Port:%x\n",ntohs(ushDestPort));
236 bClassificationSucceed=MatchDestPort(pstClassifierRule,ntohs(ushDestPort));
237 if(!bClassificationSucceed)
238 break;
239 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Dest Port Matched");
241 }while(0);
243 if(TRUE==bClassificationSucceed)
245 INT iMatchedSFQueueIndex = 0;
246 iMatchedSFQueueIndex = SearchSfid(Adapter,pstClassifierRule->ulSFID);
247 if(iMatchedSFQueueIndex >= NO_OF_QUEUES)
249 bClassificationSucceed = FALSE;
251 else
253 if(FALSE == Adapter->PackInfo[iMatchedSFQueueIndex].bActive)
255 bClassificationSucceed = FALSE;
260 return bClassificationSucceed;
264 static BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header)
266 UINT uiLoopIndex=0;
267 UINT uiIpv6AddIndex=0;
268 UINT uiIpv6AddrNoLongWords = 4;
269 ULONG aulSrcIP[4];
270 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
272 //This is the no. of Src Addresses ie Range of IP Addresses contained
273 //in the classifier rule for which we need to match
275 UINT uiCountIPSrcAddresses = (UINT)pstClassifierRule->ucIPSourceAddressLength;
278 if(0 == uiCountIPSrcAddresses)
279 return TRUE;
282 //First Convert the Ip Address in the packet to Host Endian order
283 for(uiIpv6AddIndex=0;uiIpv6AddIndex<uiIpv6AddrNoLongWords;uiIpv6AddIndex++)
285 aulSrcIP[uiIpv6AddIndex]=ntohl(pstIpv6Header->ulSrcIpAddress[uiIpv6AddIndex]);
288 for(uiLoopIndex=0;uiLoopIndex<uiCountIPSrcAddresses;uiLoopIndex+=uiIpv6AddrNoLongWords)
290 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Src Ipv6 Address In Received Packet : \n ");
291 DumpIpv6Address(aulSrcIP);
292 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Src Ipv6 Mask In Classifier Rule: \n");
293 DumpIpv6Address(&pstClassifierRule->stSrcIpAddress.ulIpv6Mask[uiLoopIndex]);
294 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Src Ipv6 Address In Classifier Rule : \n");
295 DumpIpv6Address(&pstClassifierRule->stSrcIpAddress.ulIpv6Addr[uiLoopIndex]);
297 for(uiIpv6AddIndex=0;uiIpv6AddIndex<uiIpv6AddrNoLongWords;uiIpv6AddIndex++)
299 if((pstClassifierRule->stSrcIpAddress.ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] & aulSrcIP[uiIpv6AddIndex])
300 != pstClassifierRule->stSrcIpAddress.ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex])
302 //Match failed for current Ipv6 Address.Try next Ipv6 Address
303 break;
306 if(uiIpv6AddIndex == uiIpv6AddrNoLongWords-1)
308 //Match Found
309 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Ipv6 Src Ip Address Matched\n");
310 return TRUE;
314 return FALSE;
317 static BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header)
319 UINT uiLoopIndex=0;
320 UINT uiIpv6AddIndex=0;
321 UINT uiIpv6AddrNoLongWords = 4;
322 ULONG aulDestIP[4];
323 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
325 //This is the no. of Destination Addresses ie Range of IP Addresses contained
326 //in the classifier rule for which we need to match
328 UINT uiCountIPDestinationAddresses = (UINT)pstClassifierRule->ucIPDestinationAddressLength;
331 if(0 == uiCountIPDestinationAddresses)
332 return TRUE;
335 //First Convert the Ip Address in the packet to Host Endian order
336 for(uiIpv6AddIndex=0;uiIpv6AddIndex<uiIpv6AddrNoLongWords;uiIpv6AddIndex++)
338 aulDestIP[uiIpv6AddIndex]=ntohl(pstIpv6Header->ulDestIpAddress[uiIpv6AddIndex]);
341 for(uiLoopIndex=0;uiLoopIndex<uiCountIPDestinationAddresses;uiLoopIndex+=uiIpv6AddrNoLongWords)
343 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Destination Ipv6 Address In Received Packet : \n ");
344 DumpIpv6Address(aulDestIP);
345 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Destination Ipv6 Mask In Classifier Rule: \n");
346 DumpIpv6Address(&pstClassifierRule->stDestIpAddress.ulIpv6Mask[uiLoopIndex]);
347 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Destination Ipv6 Address In Classifier Rule : \n");
348 DumpIpv6Address(&pstClassifierRule->stDestIpAddress.ulIpv6Addr[uiLoopIndex]);
350 for(uiIpv6AddIndex=0;uiIpv6AddIndex<uiIpv6AddrNoLongWords;uiIpv6AddIndex++)
352 if((pstClassifierRule->stDestIpAddress.ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] & aulDestIP[uiIpv6AddIndex])
353 != pstClassifierRule->stDestIpAddress.ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex])
355 //Match failed for current Ipv6 Address.Try next Ipv6 Address
356 break;
359 if(uiIpv6AddIndex == uiIpv6AddrNoLongWords-1)
361 //Match Found
362 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Ipv6 Destination Ip Address Matched\n");
363 return TRUE;
367 return FALSE;
371 VOID DumpIpv6Address(ULONG *puIpv6Address)
373 UINT uiIpv6AddrNoLongWords = 4;
374 UINT uiIpv6AddIndex=0;
375 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
376 for(uiIpv6AddIndex=0;uiIpv6AddIndex<uiIpv6AddrNoLongWords;uiIpv6AddIndex++)
378 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, ":%lx",puIpv6Address[uiIpv6AddIndex]);
383 static VOID DumpIpv6Header(IPV6Header *pstIpv6Header)
385 UCHAR ucVersion;
386 UCHAR ucPrio ;
387 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
388 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "----Ipv6 Header---");
389 ucVersion = pstIpv6Header->ucVersionPrio & 0xf0;
390 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Version : %x \n",ucVersion);
391 ucPrio = pstIpv6Header->ucVersionPrio & 0x0f;
392 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Priority : %x \n",ucPrio);
393 //BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Flow Label : %x \n",(pstIpv6Header->ucVersionPrio &0xf0);
394 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Payload Length : %x \n",ntohs(pstIpv6Header->usPayloadLength));
395 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Next Header : %x \n",pstIpv6Header->ucNextHeader);
396 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Hop Limit : %x \n",pstIpv6Header->ucHopLimit);
397 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Src Address :\n");
398 DumpIpv6Address(pstIpv6Header->ulSrcIpAddress);
399 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Dest Address :\n");
400 DumpIpv6Address(pstIpv6Header->ulDestIpAddress);
401 BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "----Ipv6 Header End---");