Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
IPv6Protocol.c
Go to the documentation of this file.
1 #include "headers.h"
2 
3 static BOOLEAN MatchSrcIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
4  IPV6Header *pstIpv6Header);
5 static BOOLEAN MatchDestIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
6  IPV6Header *pstIpv6Header);
7 static VOID DumpIpv6Header(IPV6Header *pstIpv6Header);
8 
9 static UCHAR *GetNextIPV6ChainedHeader(UCHAR **ppucPayload,
10  UCHAR *pucNextHeader, BOOLEAN *bParseDone, USHORT *pusPayloadLength)
11 {
12  UCHAR *pucRetHeaderPtr = NULL;
13  UCHAR *pucPayloadPtr = NULL;
14  USHORT usNextHeaderOffset = 0 ;
16 
17  if ((ppucPayload == NULL) || (*pusPayloadLength == 0) ||
18  (*bParseDone)) {
19  *bParseDone = TRUE;
20  return NULL;
21  }
22 
23  pucRetHeaderPtr = *ppucPayload;
24  pucPayloadPtr = *ppucPayload;
25 
26  if (!pucRetHeaderPtr || !pucPayloadPtr) {
27  *bParseDone = TRUE;
28  return NULL;
29  }
30 
31  /* Get the Nextt Header Type */
32  *bParseDone = FALSE;
33 
34 
35  switch (*pucNextHeader) {
37  {
38 
40  DBG_LVL_ALL, "\nIPv6 HopByHop Header");
41  usNextHeaderOffset += sizeof(IPV6HopByHopOptionsHeader);
42  }
43  break;
44 
46  {
47  IPV6RoutingHeader *pstIpv6RoutingHeader;
49  DBG_LVL_ALL, "\nIPv6 Routing Header");
50  pstIpv6RoutingHeader = (IPV6RoutingHeader *)pucPayloadPtr;
51  usNextHeaderOffset += sizeof(IPV6RoutingHeader);
52  usNextHeaderOffset += pstIpv6RoutingHeader->ucNumAddresses * IPV6_ADDRESS_SIZEINBYTES;
53 
54  }
55  break;
57  {
60  "\nIPv6 Fragmentation Header");
61  usNextHeaderOffset += sizeof(IPV6FragmentHeader);
62 
63  }
64  break;
66  {
67  IPV6DestOptionsHeader *pstIpv6DestOptsHdr = (IPV6DestOptionsHeader *)pucPayloadPtr;
68  int nTotalOptions = pstIpv6DestOptsHdr->ucHdrExtLen;
71  "\nIPv6 DestOpts Header Header");
72  usNextHeaderOffset += sizeof(IPV6DestOptionsHeader);
73  usNextHeaderOffset += nTotalOptions * IPV6_DESTOPTS_HDR_OPTIONSIZE ;
74 
75  }
76  break;
78  {
79  IPV6AuthenticationHeader *pstIpv6AuthHdr = (IPV6AuthenticationHeader *)pucPayloadPtr;
80  int nHdrLen = pstIpv6AuthHdr->ucLength;
83  "\nIPv6 Authentication Header");
84  usNextHeaderOffset += nHdrLen * 4;
85  }
86  break;
88  {
91  "\nIPv6 Encrypted Security Payload Header");
92  *bParseDone = TRUE;
93 
94  }
95  break;
96  case IPV6_ICMP_HDR_TYPE:
97  {
99  DBG_LVL_ALL, "\nICMP Header");
100  *bParseDone = TRUE;
101  }
102  break;
103  case TCP_HEADER_TYPE:
104  {
106  DBG_LVL_ALL, "\nTCP Header");
107  *bParseDone = TRUE;
108  }
109  break;
110  case UDP_HEADER_TYPE:
111  {
113  DBG_LVL_ALL, "\nUDP Header");
114  *bParseDone = TRUE;
115  }
116  break;
117  default:
118  {
119  *bParseDone = TRUE;
120 
121  }
122  break;
123 
124 
125  }
126 
127  if (*bParseDone == FALSE) {
128  if (*pusPayloadLength <= usNextHeaderOffset) {
129  *bParseDone = TRUE;
130  } else {
131  *pucNextHeader = *pucPayloadPtr;
132  pucPayloadPtr += usNextHeaderOffset;
133  (*pusPayloadLength) -= usNextHeaderOffset;
134  }
135 
136  }
137 
138  *ppucPayload = pucPayloadPtr;
139  return pucRetHeaderPtr;
140 }
141 
142 
143 static UCHAR GetIpv6ProtocolPorts(UCHAR *pucPayload, USHORT *pusSrcPort,
144  USHORT *pusDestPort, USHORT usPayloadLength, UCHAR ucNextHeader)
145 {
146  UCHAR *pIpv6HdrScanContext = pucPayload;
147  BOOLEAN bDone = FALSE;
148  UCHAR ucHeaderType = 0;
149  UCHAR *pucNextHeader = NULL;
150  struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
151 
152  if (!pucPayload || (usPayloadLength == 0))
153  return 0;
154 
155  *pusSrcPort = *pusDestPort = 0;
156  ucHeaderType = ucNextHeader;
157  while (!bDone) {
158  pucNextHeader = GetNextIPV6ChainedHeader(&pIpv6HdrScanContext,
159  &ucHeaderType, &bDone, &usPayloadLength);
160  if (bDone) {
161  if ((ucHeaderType == TCP_HEADER_TYPE) ||
162  (ucHeaderType == UDP_HEADER_TYPE)) {
163  *pusSrcPort = *((PUSHORT)(pucNextHeader));
164  *pusDestPort = *((PUSHORT)(pucNextHeader+2));
166  DBG_LVL_ALL,
167  "\nProtocol Ports - Src Port :0x%x Dest Port : 0x%x",
168  ntohs(*pusSrcPort),
169  ntohs(*pusDestPort));
170  }
171  break;
172 
173  }
174  }
175  return ucHeaderType;
176 }
177 
178 
179 /*
180  * Arg 1 struct bcm_mini_adapter *Adapter is a pointer ot the driver contorl structure
181  * Arg 2 PVOID pcIpHeader is a pointer to the IP header of the packet
182  */
183 USHORT IpVersion6(struct bcm_mini_adapter *Adapter, PVOID pcIpHeader,
184  struct bcm_classifier_rule *pstClassifierRule)
185 {
186  USHORT ushDestPort = 0;
187  USHORT ushSrcPort = 0;
188  UCHAR ucNextProtocolAboveIP = 0;
189  IPV6Header *pstIpv6Header = NULL;
190  BOOLEAN bClassificationSucceed = FALSE;
191 
193  DBG_LVL_ALL, "IpVersion6 ==========>\n");
194 
195  pstIpv6Header = (IPV6Header *)pcIpHeader;
196 
197  DumpIpv6Header(pstIpv6Header);
198 
199  /*
200  * Try to get the next higher layer protocol
201  * and the Ports Nos if TCP or UDP
202  */
203  ucNextProtocolAboveIP = GetIpv6ProtocolPorts((UCHAR *)(pcIpHeader + sizeof(IPV6Header)),
204  &ushSrcPort,
205  &ushDestPort,
206  pstIpv6Header->usPayloadLength,
207  pstIpv6Header->ucNextHeader);
208 
209  do {
210  if (pstClassifierRule->ucDirection == 0) {
211  /*
212  * cannot be processed for classification.
213  * it is a down link connection
214  */
215  break;
216  }
217 
218  if (!pstClassifierRule->bIpv6Protocol) {
219  /*
220  * We are looking for Ipv6 Classifiers
221  * Lets ignore this classifier and try the next one
222  */
223  break;
224  }
225 
226  bClassificationSucceed = MatchSrcIpv6Address(pstClassifierRule,
227  pstIpv6Header);
228  if (!bClassificationSucceed)
229  break;
230 
231  bClassificationSucceed = MatchDestIpv6Address(pstClassifierRule,
232  pstIpv6Header);
233  if (!bClassificationSucceed)
234  break;
235 
236  /*
237  * Match the protocol type.
238  * For IPv6 the next protocol at end of
239  * Chain of IPv6 prot headers
240  */
241  bClassificationSucceed = MatchProtocol(pstClassifierRule,
242  ucNextProtocolAboveIP);
243  if (!bClassificationSucceed)
244  break;
245 
247  DBG_LVL_ALL, "\nIPv6 Protocol Matched");
248 
249  if ((ucNextProtocolAboveIP == TCP_HEADER_TYPE) ||
250  (ucNextProtocolAboveIP == UDP_HEADER_TYPE)) {
251  /* Match Src Port */
253  DBG_LVL_ALL, "\nIPv6 Source Port:%x\n",
254  ntohs(ushSrcPort));
255  bClassificationSucceed = MatchSrcPort(pstClassifierRule,
256  ntohs(ushSrcPort));
257  if (!bClassificationSucceed)
258  break;
259 
261  DBG_LVL_ALL, "\nIPv6 Src Port Matched");
262 
263  /* Match Dest Port */
265  DBG_LVL_ALL, "\nIPv6 Destination Port:%x\n",
266  ntohs(ushDestPort));
267  bClassificationSucceed = MatchDestPort(pstClassifierRule,
268  ntohs(ushDestPort));
269  if (!bClassificationSucceed)
270  break;
272  DBG_LVL_ALL, "\nIPv6 Dest Port Matched");
273  }
274  } while (0);
275 
276  if (bClassificationSucceed == TRUE) {
277  INT iMatchedSFQueueIndex = 0;
278  iMatchedSFQueueIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
279  if (iMatchedSFQueueIndex >= NO_OF_QUEUES) {
280  bClassificationSucceed = FALSE;
281  } else {
282  if (Adapter->PackInfo[iMatchedSFQueueIndex].bActive == FALSE)
283  bClassificationSucceed = FALSE;
284  }
285  }
286 
287  return bClassificationSucceed;
288 }
289 
290 
291 static BOOLEAN MatchSrcIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
292  IPV6Header *pstIpv6Header)
293 {
294  UINT uiLoopIndex = 0;
295  UINT uiIpv6AddIndex = 0;
296  UINT uiIpv6AddrNoLongWords = 4;
297  ULONG aulSrcIP[4];
298  struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
299  /*
300  * This is the no. of Src Addresses ie Range of IP Addresses contained
301  * in the classifier rule for which we need to match
302  */
303  UINT uiCountIPSrcAddresses = (UINT)pstClassifierRule->ucIPSourceAddressLength;
304 
305 
306  if (uiCountIPSrcAddresses == 0)
307  return TRUE;
308 
309 
310  /* First Convert the Ip Address in the packet to Host Endian order */
311  for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++)
312  aulSrcIP[uiIpv6AddIndex] = ntohl(pstIpv6Header->ulSrcIpAddress[uiIpv6AddIndex]);
313 
314  for (uiLoopIndex = 0; uiLoopIndex < uiCountIPSrcAddresses; uiLoopIndex += uiIpv6AddrNoLongWords) {
316  "\n Src Ipv6 Address In Received Packet :\n ");
317  DumpIpv6Address(aulSrcIP);
319  "\n Src Ipv6 Mask In Classifier Rule:\n");
320  DumpIpv6Address(&pstClassifierRule->stSrcIpAddress.ulIpv6Mask[uiLoopIndex]);
322  "\n Src Ipv6 Address In Classifier Rule :\n");
323  DumpIpv6Address(&pstClassifierRule->stSrcIpAddress.ulIpv6Addr[uiLoopIndex]);
324 
325  for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++) {
326  if ((pstClassifierRule->stSrcIpAddress.ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] & aulSrcIP[uiIpv6AddIndex])
327  != pstClassifierRule->stSrcIpAddress.ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex]) {
328  /*
329  * Match failed for current Ipv6 Address
330  * Try next Ipv6 Address
331  */
332  break;
333  }
334 
335  if (uiIpv6AddIndex == uiIpv6AddrNoLongWords-1) {
336  /* Match Found */
338  DBG_LVL_ALL,
339  "Ipv6 Src Ip Address Matched\n");
340  return TRUE;
341  }
342  }
343  }
344  return FALSE;
345 }
346 
347 static BOOLEAN MatchDestIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
348  IPV6Header *pstIpv6Header)
349 {
350  UINT uiLoopIndex = 0;
351  UINT uiIpv6AddIndex = 0;
352  UINT uiIpv6AddrNoLongWords = 4;
353  ULONG aulDestIP[4];
354  struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
355  /*
356  * This is the no. of Destination Addresses
357  * ie Range of IP Addresses contained in the classifier rule
358  * for which we need to match
359  */
360  UINT uiCountIPDestinationAddresses = (UINT)pstClassifierRule->ucIPDestinationAddressLength;
361 
362 
363  if (uiCountIPDestinationAddresses == 0)
364  return TRUE;
365 
366 
367  /* First Convert the Ip Address in the packet to Host Endian order */
368  for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++)
369  aulDestIP[uiIpv6AddIndex] = ntohl(pstIpv6Header->ulDestIpAddress[uiIpv6AddIndex]);
370 
371  for (uiLoopIndex = 0; uiLoopIndex < uiCountIPDestinationAddresses; uiLoopIndex += uiIpv6AddrNoLongWords) {
373  "\n Destination Ipv6 Address In Received Packet :\n ");
374  DumpIpv6Address(aulDestIP);
376  "\n Destination Ipv6 Mask In Classifier Rule :\n");
377  DumpIpv6Address(&pstClassifierRule->stDestIpAddress.ulIpv6Mask[uiLoopIndex]);
379  "\n Destination Ipv6 Address In Classifier Rule :\n");
380  DumpIpv6Address(&pstClassifierRule->stDestIpAddress.ulIpv6Addr[uiLoopIndex]);
381 
382  for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++) {
383  if ((pstClassifierRule->stDestIpAddress.ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] & aulDestIP[uiIpv6AddIndex])
384  != pstClassifierRule->stDestIpAddress.ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex]) {
385  /*
386  * Match failed for current Ipv6 Address.
387  * Try next Ipv6 Address
388  */
389  break;
390  }
391 
392  if (uiIpv6AddIndex == uiIpv6AddrNoLongWords-1) {
393  /* Match Found */
395  DBG_LVL_ALL,
396  "Ipv6 Destination Ip Address Matched\n");
397  return TRUE;
398  }
399  }
400  }
401  return FALSE;
402 
403 }
404 
405 VOID DumpIpv6Address(ULONG *puIpv6Address)
406 {
407  UINT uiIpv6AddrNoLongWords = 4;
408  UINT uiIpv6AddIndex = 0;
409  struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
410  for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++) {
412  ":%lx", puIpv6Address[uiIpv6AddIndex]);
413  }
414 
415 }
416 
417 static VOID DumpIpv6Header(IPV6Header *pstIpv6Header)
418 {
419  UCHAR ucVersion;
420  UCHAR ucPrio;
421  struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
423  "----Ipv6 Header---");
424  ucVersion = pstIpv6Header->ucVersionPrio & 0xf0;
426  "Version : %x\n", ucVersion);
427  ucPrio = pstIpv6Header->ucVersionPrio & 0x0f;
429  "Priority : %x\n", ucPrio);
430  /*
431  * BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
432  * "Flow Label : %x\n",(pstIpv6Header->ucVersionPrio &0xf0);
433  */
435  "Payload Length : %x\n",
436  ntohs(pstIpv6Header->usPayloadLength));
438  "Next Header : %x\n", pstIpv6Header->ucNextHeader);
440  "Hop Limit : %x\n", pstIpv6Header->ucHopLimit);
442  "Src Address :\n");
443  DumpIpv6Address(pstIpv6Header->ulSrcIpAddress);
445  "Dest Address :\n");
446  DumpIpv6Address(pstIpv6Header->ulDestIpAddress);
448  "----Ipv6 Header End---");
449 
450 
451 }