ptp: fix missing break in switch
[linux/fpc-iii.git] / drivers / staging / bcm / IPv6Protocol.c
blob27f3f416f184b6dd882b23464d4ba203e4e53c3b
1 #include "headers.h"
3 static bool MatchSrcIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
4 struct bcm_ipv6_hdr *pstIpv6Header);
5 static bool MatchDestIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
6 struct bcm_ipv6_hdr *pstIpv6Header);
7 static VOID DumpIpv6Header(struct bcm_ipv6_hdr *pstIpv6Header);
9 static UCHAR *GetNextIPV6ChainedHeader(UCHAR **ppucPayload,
10 UCHAR *pucNextHeader, bool *bParseDone, USHORT *pusPayloadLength)
12 UCHAR *pucRetHeaderPtr = NULL;
13 UCHAR *pucPayloadPtr = NULL;
14 USHORT usNextHeaderOffset = 0;
15 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
17 if ((ppucPayload == NULL) || (*pusPayloadLength == 0) ||
18 (*bParseDone)) {
19 *bParseDone = TRUE;
20 return NULL;
23 pucRetHeaderPtr = *ppucPayload;
24 pucPayloadPtr = *ppucPayload;
26 if (!pucRetHeaderPtr || !pucPayloadPtr) {
27 *bParseDone = TRUE;
28 return NULL;
31 /* Get the Nextt Header Type */
32 *bParseDone = false;
35 switch (*pucNextHeader) {
36 case IPV6HDR_TYPE_HOPBYHOP:
37 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
38 DBG_LVL_ALL, "\nIPv6 HopByHop Header");
39 usNextHeaderOffset += sizeof(struct bcm_ipv6_options_hdr);
40 break;
42 case IPV6HDR_TYPE_ROUTING:
44 struct bcm_ipv6_routing_hdr *pstIpv6RoutingHeader;
46 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
47 DBG_LVL_ALL, "\nIPv6 Routing Header");
48 pstIpv6RoutingHeader =
49 (struct bcm_ipv6_routing_hdr *)pucPayloadPtr;
50 usNextHeaderOffset += sizeof(struct bcm_ipv6_routing_hdr);
51 usNextHeaderOffset += pstIpv6RoutingHeader->ucNumAddresses *
52 IPV6_ADDRESS_SIZEINBYTES;
54 break;
56 case IPV6HDR_TYPE_FRAGMENTATION:
57 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
58 DBG_LVL_ALL,
59 "\nIPv6 Fragmentation Header");
60 usNextHeaderOffset += sizeof(struct bcm_ipv6_fragment_hdr);
61 break;
63 case IPV6HDR_TYPE_DESTOPTS:
65 struct bcm_ipv6_dest_options_hdr *pstIpv6DestOptsHdr =
66 (struct bcm_ipv6_dest_options_hdr *)pucPayloadPtr;
67 int nTotalOptions = pstIpv6DestOptsHdr->ucHdrExtLen;
69 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
70 DBG_LVL_ALL,
71 "\nIPv6 DestOpts Header Header");
72 usNextHeaderOffset += sizeof(struct bcm_ipv6_dest_options_hdr);
73 usNextHeaderOffset += nTotalOptions *
74 IPV6_DESTOPTS_HDR_OPTIONSIZE;
76 break;
79 case IPV6HDR_TYPE_AUTHENTICATION:
81 struct bcm_ipv6_authentication_hdr *pstIpv6AuthHdr =
82 (struct bcm_ipv6_authentication_hdr *)pucPayloadPtr;
83 int nHdrLen = pstIpv6AuthHdr->ucLength;
85 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
86 DBG_LVL_ALL,
87 "\nIPv6 Authentication Header");
88 usNextHeaderOffset += nHdrLen * 4;
90 break;
92 case IPV6HDR_TYPE_ENCRYPTEDSECURITYPAYLOAD:
93 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
94 DBG_LVL_ALL,
95 "\nIPv6 Encrypted Security Payload Header");
96 *bParseDone = TRUE;
97 break;
99 case IPV6_ICMP_HDR_TYPE:
100 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
101 DBG_LVL_ALL, "\nICMP Header");
102 *bParseDone = TRUE;
103 break;
105 case TCP_HEADER_TYPE:
106 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
107 DBG_LVL_ALL, "\nTCP Header");
108 *bParseDone = TRUE;
109 break;
111 case UDP_HEADER_TYPE:
112 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
113 DBG_LVL_ALL, "\nUDP Header");
114 *bParseDone = TRUE;
115 break;
117 default:
118 *bParseDone = TRUE;
119 break;
122 if (*bParseDone == false) {
123 if (*pusPayloadLength <= usNextHeaderOffset) {
124 *bParseDone = TRUE;
125 } else {
126 *pucNextHeader = *pucPayloadPtr;
127 pucPayloadPtr += usNextHeaderOffset;
128 (*pusPayloadLength) -= usNextHeaderOffset;
133 *ppucPayload = pucPayloadPtr;
134 return pucRetHeaderPtr;
138 static UCHAR GetIpv6ProtocolPorts(UCHAR *pucPayload, USHORT *pusSrcPort,
139 USHORT *pusDestPort, USHORT usPayloadLength, UCHAR ucNextHeader)
141 UCHAR *pIpv6HdrScanContext = pucPayload;
142 bool bDone = false;
143 UCHAR ucHeaderType = 0;
144 UCHAR *pucNextHeader = NULL;
145 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
147 if (!pucPayload || (usPayloadLength == 0))
148 return 0;
150 *pusSrcPort = *pusDestPort = 0;
151 ucHeaderType = ucNextHeader;
152 while (!bDone) {
153 pucNextHeader = GetNextIPV6ChainedHeader(&pIpv6HdrScanContext,
154 &ucHeaderType,
155 &bDone,
156 &usPayloadLength);
157 if (bDone) {
158 if ((ucHeaderType == TCP_HEADER_TYPE) ||
159 (ucHeaderType == UDP_HEADER_TYPE)) {
160 *pusSrcPort = *((PUSHORT)(pucNextHeader));
161 *pusDestPort = *((PUSHORT)(pucNextHeader+2));
162 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
163 DBG_LVL_ALL,
164 "\nProtocol Ports - Src Port :0x%x Dest Port : 0x%x",
165 ntohs(*pusSrcPort),
166 ntohs(*pusDestPort));
168 break;
172 return ucHeaderType;
177 * Arg 1 struct bcm_mini_adapter *Adapter is a pointer ot the driver control
178 * structure
179 * Arg 2 PVOID pcIpHeader is a pointer to the IP header of the packet
181 USHORT IpVersion6(struct bcm_mini_adapter *Adapter, PVOID pcIpHeader,
182 struct bcm_classifier_rule *pstClassifierRule)
184 USHORT ushDestPort = 0;
185 USHORT ushSrcPort = 0;
186 UCHAR ucNextProtocolAboveIP = 0;
187 struct bcm_ipv6_hdr *pstIpv6Header = NULL;
188 bool bClassificationSucceed = false;
190 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
191 DBG_LVL_ALL, "IpVersion6 ==========>\n");
193 pstIpv6Header = pcIpHeader;
195 DumpIpv6Header(pstIpv6Header);
198 * Try to get the next higher layer protocol
199 * and the Ports Nos if TCP or UDP
201 ucNextProtocolAboveIP = GetIpv6ProtocolPorts((UCHAR *)(pcIpHeader +
202 sizeof(struct bcm_ipv6_hdr)),
203 &ushSrcPort,
204 &ushDestPort,
205 pstIpv6Header->usPayloadLength,
206 pstIpv6Header->ucNextHeader);
208 do {
209 if (pstClassifierRule->ucDirection == 0) {
211 * cannot be processed for classification.
212 * it is a down link connection
214 break;
217 if (!pstClassifierRule->bIpv6Protocol) {
219 * We are looking for Ipv6 Classifiers
220 * Lets ignore this classifier and try the next one
222 break;
225 bClassificationSucceed = MatchSrcIpv6Address(pstClassifierRule,
226 pstIpv6Header);
227 if (!bClassificationSucceed)
228 break;
230 bClassificationSucceed = MatchDestIpv6Address(pstClassifierRule,
231 pstIpv6Header);
232 if (!bClassificationSucceed)
233 break;
236 * Match the protocol type.
237 * For IPv6 the next protocol at end of
238 * Chain of IPv6 prot headers
240 bClassificationSucceed = MatchProtocol(pstClassifierRule,
241 ucNextProtocolAboveIP);
242 if (!bClassificationSucceed)
243 break;
245 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
246 DBG_LVL_ALL, "\nIPv6 Protocol Matched");
248 if ((ucNextProtocolAboveIP == TCP_HEADER_TYPE) ||
249 (ucNextProtocolAboveIP == UDP_HEADER_TYPE)) {
250 /* Match Src Port */
251 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
252 DBG_LVL_ALL, "\nIPv6 Source Port:%x\n",
253 ntohs(ushSrcPort));
254 bClassificationSucceed = MatchSrcPort(pstClassifierRule,
255 ntohs(ushSrcPort));
256 if (!bClassificationSucceed)
257 break;
259 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
260 DBG_LVL_ALL, "\nIPv6 Src Port Matched");
262 /* Match Dest Port */
263 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
264 DBG_LVL_ALL,
265 "\nIPv6 Destination Port:%x\n",
266 ntohs(ushDestPort));
267 bClassificationSucceed = MatchDestPort(pstClassifierRule,
268 ntohs(ushDestPort));
269 if (!bClassificationSucceed)
270 break;
271 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
272 DBG_LVL_ALL,
273 "\nIPv6 Dest Port Matched");
275 } while (0);
277 if (bClassificationSucceed == TRUE) {
278 INT iMatchedSFQueueIndex = 0;
280 iMatchedSFQueueIndex = SearchSfid(Adapter,
281 pstClassifierRule->ulSFID);
282 if ((iMatchedSFQueueIndex >= NO_OF_QUEUES) ||
283 (Adapter->PackInfo[iMatchedSFQueueIndex].bActive == false))
284 bClassificationSucceed = false;
287 return bClassificationSucceed;
291 static bool MatchSrcIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
292 struct bcm_ipv6_hdr *pstIpv6Header)
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 union u_ip_address *src_addr = &pstClassifierRule->stSrcIpAddress;
302 * This is the no. of Src Addresses ie Range of IP Addresses contained
303 * in the classifier rule for which we need to match
305 UINT uiCountIPSrcAddresses =
306 (UINT)pstClassifierRule->ucIPSourceAddressLength;
309 if (uiCountIPSrcAddresses == 0)
310 return TRUE;
313 /* First Convert the Ip Address in the packet to Host Endian order */
314 for (uiIpv6AddIndex = 0;
315 uiIpv6AddIndex < uiIpv6AddrNoLongWords;
316 uiIpv6AddIndex++)
317 aulSrcIP[uiIpv6AddIndex] =
318 ntohl(pstIpv6Header->ulSrcIpAddress[uiIpv6AddIndex]);
320 for (uiLoopIndex = 0;
321 uiLoopIndex < uiCountIPSrcAddresses;
322 uiLoopIndex += uiIpv6AddrNoLongWords) {
323 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
324 "\n Src Ipv6 Address In Received Packet :\n ");
325 DumpIpv6Address(aulSrcIP);
326 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
327 "\n Src Ipv6 Mask In Classifier Rule:\n");
328 DumpIpv6Address(&src_addr->ulIpv6Mask[uiLoopIndex]);
329 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
330 "\n Src Ipv6 Address In Classifier Rule :\n");
331 DumpIpv6Address(&src_addr->ulIpv6Addr[uiLoopIndex]);
333 for (uiIpv6AddIndex = 0;
334 uiIpv6AddIndex < uiIpv6AddrNoLongWords;
335 uiIpv6AddIndex++) {
336 if ((src_addr->ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] &
337 aulSrcIP[uiIpv6AddIndex]) !=
338 src_addr->ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex]) {
340 * Match failed for current Ipv6 Address
341 * Try next Ipv6 Address
343 break;
346 if (uiIpv6AddIndex == uiIpv6AddrNoLongWords-1) {
347 /* Match Found */
348 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
349 DBG_LVL_ALL,
350 "Ipv6 Src Ip Address Matched\n");
351 return TRUE;
355 return false;
358 static bool MatchDestIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
359 struct bcm_ipv6_hdr *pstIpv6Header)
361 UINT uiLoopIndex = 0;
362 UINT uiIpv6AddIndex = 0;
363 UINT uiIpv6AddrNoLongWords = 4;
364 ULONG aulDestIP[4];
365 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
366 union u_ip_address *dest_addr = &pstClassifierRule->stDestIpAddress;
369 * This is the no. of Destination Addresses
370 * ie Range of IP Addresses contained in the classifier rule
371 * for which we need to match
373 UINT uiCountIPDestinationAddresses =
374 (UINT)pstClassifierRule->ucIPDestinationAddressLength;
376 if (uiCountIPDestinationAddresses == 0)
377 return TRUE;
380 /* First Convert the Ip Address in the packet to Host Endian order */
381 for (uiIpv6AddIndex = 0;
382 uiIpv6AddIndex < uiIpv6AddrNoLongWords;
383 uiIpv6AddIndex++)
384 aulDestIP[uiIpv6AddIndex] =
385 ntohl(pstIpv6Header->ulDestIpAddress[uiIpv6AddIndex]);
387 for (uiLoopIndex = 0;
388 uiLoopIndex < uiCountIPDestinationAddresses;
389 uiLoopIndex += uiIpv6AddrNoLongWords) {
390 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
391 "\n Destination Ipv6 Address In Received Packet :\n ");
392 DumpIpv6Address(aulDestIP);
393 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
394 "\n Destination Ipv6 Mask In Classifier Rule :\n");
395 DumpIpv6Address(&dest_addr->ulIpv6Mask[uiLoopIndex]);
396 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
397 "\n Destination Ipv6 Address In Classifier Rule :\n");
398 DumpIpv6Address(&dest_addr->ulIpv6Addr[uiLoopIndex]);
400 for (uiIpv6AddIndex = 0;
401 uiIpv6AddIndex < uiIpv6AddrNoLongWords;
402 uiIpv6AddIndex++) {
403 if ((dest_addr->ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] &
404 aulDestIP[uiIpv6AddIndex]) !=
405 dest_addr->ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex]) {
407 * Match failed for current Ipv6 Address.
408 * Try next Ipv6 Address
410 break;
413 if (uiIpv6AddIndex == uiIpv6AddrNoLongWords-1) {
414 /* Match Found */
415 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
416 DBG_LVL_ALL,
417 "Ipv6 Destination Ip Address Matched\n");
418 return TRUE;
422 return false;
426 VOID DumpIpv6Address(ULONG *puIpv6Address)
428 UINT uiIpv6AddrNoLongWords = 4;
429 UINT uiIpv6AddIndex = 0;
430 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
432 for (uiIpv6AddIndex = 0;
433 uiIpv6AddIndex < uiIpv6AddrNoLongWords;
434 uiIpv6AddIndex++) {
435 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
436 ":%lx", puIpv6Address[uiIpv6AddIndex]);
441 static VOID DumpIpv6Header(struct bcm_ipv6_hdr *pstIpv6Header)
443 UCHAR ucVersion;
444 UCHAR ucPrio;
445 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
447 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
448 "----Ipv6 Header---");
449 ucVersion = pstIpv6Header->ucVersionPrio & 0xf0;
450 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
451 "Version : %x\n", ucVersion);
452 ucPrio = pstIpv6Header->ucVersionPrio & 0x0f;
453 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
454 "Priority : %x\n", ucPrio);
456 * BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
457 * "Flow Label : %x\n",(pstIpv6Header->ucVersionPrio &0xf0);
459 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
460 "Payload Length : %x\n",
461 ntohs(pstIpv6Header->usPayloadLength));
462 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
463 "Next Header : %x\n", pstIpv6Header->ucNextHeader);
464 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
465 "Hop Limit : %x\n", pstIpv6Header->ucHopLimit);
466 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
467 "Src Address :\n");
468 DumpIpv6Address(pstIpv6Header->ulSrcIpAddress);
469 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
470 "Dest Address :\n");
471 DumpIpv6Address(pstIpv6Header->ulDestIpAddress);
472 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
473 "----Ipv6 Header End---");