• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "headers.h"
2 
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);
8 
GetNextIPV6ChainedHeader(UCHAR ** ppucPayload,UCHAR * pucNextHeader,bool * bParseDone,USHORT * pusPayloadLength)9 static UCHAR *GetNextIPV6ChainedHeader(UCHAR **ppucPayload,
10 	UCHAR *pucNextHeader, bool *bParseDone, USHORT *pusPayloadLength)
11 {
12 	UCHAR *pucRetHeaderPtr = NULL;
13 	UCHAR *pucPayloadPtr = NULL;
14 	USHORT  usNextHeaderOffset = 0;
15 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
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) {
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;
41 
42 	case IPV6HDR_TYPE_ROUTING:
43 		{
44 			struct bcm_ipv6_routing_hdr *pstIpv6RoutingHeader;
45 
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;
53 		}
54 		break;
55 
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;
62 
63 	case IPV6HDR_TYPE_DESTOPTS:
64 		{
65 			struct bcm_ipv6_dest_options_hdr *pstIpv6DestOptsHdr =
66 				(struct bcm_ipv6_dest_options_hdr *)pucPayloadPtr;
67 			int nTotalOptions = pstIpv6DestOptsHdr->ucHdrExtLen;
68 
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;
75 		}
76 		break;
77 
78 
79 	case IPV6HDR_TYPE_AUTHENTICATION:
80 		{
81 			struct bcm_ipv6_authentication_hdr *pstIpv6AuthHdr =
82 				(struct bcm_ipv6_authentication_hdr *)pucPayloadPtr;
83 			int nHdrLen = pstIpv6AuthHdr->ucLength;
84 
85 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
86 					DBG_LVL_ALL,
87 					"\nIPv6 Authentication Header");
88 			usNextHeaderOffset += nHdrLen * 4;
89 		}
90 		break;
91 
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;
98 
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;
104 
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;
110 
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;
116 
117 	default:
118 		*bParseDone = TRUE;
119 		break;
120 	}
121 
122 	if (*bParseDone == false) {
123 		if (*pusPayloadLength <= usNextHeaderOffset) {
124 			*bParseDone = TRUE;
125 		} else {
126 			*pucNextHeader = *pucPayloadPtr;
127 			pucPayloadPtr += usNextHeaderOffset;
128 			(*pusPayloadLength) -= usNextHeaderOffset;
129 		}
130 
131 	}
132 
133 	*ppucPayload = pucPayloadPtr;
134 	return pucRetHeaderPtr;
135 }
136 
137 
GetIpv6ProtocolPorts(UCHAR * pucPayload,USHORT * pusSrcPort,USHORT * pusDestPort,USHORT usPayloadLength,UCHAR ucNextHeader)138 static UCHAR GetIpv6ProtocolPorts(UCHAR *pucPayload, USHORT *pusSrcPort,
139 	USHORT *pusDestPort, USHORT usPayloadLength, UCHAR ucNextHeader)
140 {
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);
146 
147 	if (!pucPayload || (usPayloadLength == 0))
148 		return 0;
149 
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));
167 			}
168 			break;
169 
170 		}
171 	}
172 	return ucHeaderType;
173 }
174 
175 
176 /*
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
180  */
IpVersion6(struct bcm_mini_adapter * Adapter,PVOID pcIpHeader,struct bcm_classifier_rule * pstClassifierRule)181 USHORT	IpVersion6(struct bcm_mini_adapter *Adapter, PVOID pcIpHeader,
182 		   struct bcm_classifier_rule *pstClassifierRule)
183 {
184 	USHORT	ushDestPort = 0;
185 	USHORT	ushSrcPort = 0;
186 	UCHAR   ucNextProtocolAboveIP = 0;
187 	struct bcm_ipv6_hdr *pstIpv6Header = NULL;
188 	bool bClassificationSucceed = false;
189 
190 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
191 			DBG_LVL_ALL, "IpVersion6 ==========>\n");
192 
193 	pstIpv6Header = pcIpHeader;
194 
195 	DumpIpv6Header(pstIpv6Header);
196 
197 	/*
198 	 * Try to get the next higher layer protocol
199 	 * and the Ports Nos if TCP or UDP
200 	 */
201 	ucNextProtocolAboveIP = GetIpv6ProtocolPorts((UCHAR *)(pcIpHeader +
202 						     sizeof(struct bcm_ipv6_hdr)),
203 						     &ushSrcPort,
204 						     &ushDestPort,
205 						     pstIpv6Header->usPayloadLength,
206 						     pstIpv6Header->ucNextHeader);
207 
208 	do {
209 		if (pstClassifierRule->ucDirection == 0) {
210 			/*
211 			 * cannot be processed for classification.
212 			 * it is a down link connection
213 			 */
214 			break;
215 		}
216 
217 		if (!pstClassifierRule->bIpv6Protocol) {
218 			/*
219 			 * We are looking for Ipv6 Classifiers
220 			 * Lets ignore this classifier and try the next one
221 			 */
222 			break;
223 		}
224 
225 		bClassificationSucceed = MatchSrcIpv6Address(pstClassifierRule,
226 							     pstIpv6Header);
227 		if (!bClassificationSucceed)
228 			break;
229 
230 		bClassificationSucceed = MatchDestIpv6Address(pstClassifierRule,
231 							      pstIpv6Header);
232 		if (!bClassificationSucceed)
233 			break;
234 
235 		/*
236 		 * Match the protocol type.
237 		 * For IPv6 the next protocol at end of
238 		 * Chain of IPv6 prot headers
239 		 */
240 		bClassificationSucceed = MatchProtocol(pstClassifierRule,
241 						       ucNextProtocolAboveIP);
242 		if (!bClassificationSucceed)
243 			break;
244 
245 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
246 				DBG_LVL_ALL, "\nIPv6 Protocol Matched");
247 
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;
258 
259 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
260 					DBG_LVL_ALL, "\nIPv6 Src Port Matched");
261 
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");
274 		}
275 	} while (0);
276 
277 	if (bClassificationSucceed == TRUE) {
278 		INT iMatchedSFQueueIndex = 0;
279 
280 		iMatchedSFQueueIndex = SearchSfid(Adapter,
281 						  pstClassifierRule->ulSFID);
282 		if ((iMatchedSFQueueIndex >= NO_OF_QUEUES) ||
283 		    (Adapter->PackInfo[iMatchedSFQueueIndex].bActive == false))
284 			bClassificationSucceed = false;
285 	}
286 
287 	return bClassificationSucceed;
288 }
289 
290 
MatchSrcIpv6Address(struct bcm_classifier_rule * pstClassifierRule,struct bcm_ipv6_hdr * pstIpv6Header)291 static bool MatchSrcIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
292 				struct bcm_ipv6_hdr *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 	union u_ip_address *src_addr = &pstClassifierRule->stSrcIpAddress;
300 
301 	/*
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
304 	 */
305 	UINT  uiCountIPSrcAddresses =
306 		(UINT)pstClassifierRule->ucIPSourceAddressLength;
307 
308 
309 	if (uiCountIPSrcAddresses == 0)
310 		return TRUE;
311 
312 
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]);
319 
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]);
332 
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]) {
339 				/*
340 				 * Match failed for current Ipv6 Address
341 				 * Try next Ipv6 Address
342 				 */
343 				break;
344 			}
345 
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;
352 			}
353 		}
354 	}
355 	return false;
356 }
357 
MatchDestIpv6Address(struct bcm_classifier_rule * pstClassifierRule,struct bcm_ipv6_hdr * pstIpv6Header)358 static bool MatchDestIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
359 				 struct bcm_ipv6_hdr *pstIpv6Header)
360 {
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;
367 
368 	/*
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
372 	 */
373 	UINT uiCountIPDestinationAddresses =
374 		(UINT)pstClassifierRule->ucIPDestinationAddressLength;
375 
376 	if (uiCountIPDestinationAddresses == 0)
377 		return TRUE;
378 
379 
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]);
386 
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]);
399 
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]) {
406 				/*
407 				 * Match failed for current Ipv6 Address.
408 				 * Try next Ipv6 Address
409 				 */
410 				break;
411 			}
412 
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;
419 			}
420 		}
421 	}
422 	return false;
423 
424 }
425 
DumpIpv6Address(ULONG * puIpv6Address)426 VOID DumpIpv6Address(ULONG *puIpv6Address)
427 {
428 	UINT uiIpv6AddrNoLongWords = 4;
429 	UINT uiIpv6AddIndex = 0;
430 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
431 
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]);
437 	}
438 
439 }
440 
DumpIpv6Header(struct bcm_ipv6_hdr * pstIpv6Header)441 static VOID DumpIpv6Header(struct bcm_ipv6_hdr *pstIpv6Header)
442 {
443 	UCHAR ucVersion;
444 	UCHAR ucPrio;
445 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
446 
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);
455 	/*
456 	 * BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
457 	 * "Flow Label : %x\n",(pstIpv6Header->ucVersionPrio &0xf0);
458 	 */
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---");
474 
475 
476 }
477