Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v3.15-rc5 451 lines 14 kB view raw
1#include "headers.h" 2 3static bool MatchSrcIpv6Address(struct bcm_classifier_rule *pstClassifierRule, 4 struct bcm_ipv6_hdr *pstIpv6Header); 5static bool MatchDestIpv6Address(struct bcm_classifier_rule *pstClassifierRule, 6 struct bcm_ipv6_hdr *pstIpv6Header); 7static VOID DumpIpv6Header(struct bcm_ipv6_hdr *pstIpv6Header); 8 9static 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 { 38 39 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, 40 DBG_LVL_ALL, "\nIPv6 HopByHop Header"); 41 usNextHeaderOffset += sizeof(struct bcm_ipv6_options_hdr); 42 } 43 break; 44 45 case IPV6HDR_TYPE_ROUTING: 46 { 47 struct bcm_ipv6_routing_hdr *pstIpv6RoutingHeader; 48 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, 49 DBG_LVL_ALL, "\nIPv6 Routing Header"); 50 pstIpv6RoutingHeader = (struct bcm_ipv6_routing_hdr *)pucPayloadPtr; 51 usNextHeaderOffset += sizeof(struct bcm_ipv6_routing_hdr); 52 usNextHeaderOffset += pstIpv6RoutingHeader->ucNumAddresses * IPV6_ADDRESS_SIZEINBYTES; 53 54 } 55 break; 56 case IPV6HDR_TYPE_FRAGMENTATION: 57 { 58 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, 59 DBG_LVL_ALL, 60 "\nIPv6 Fragmentation Header"); 61 usNextHeaderOffset += sizeof(struct bcm_ipv6_fragment_hdr); 62 63 } 64 break; 65 case IPV6HDR_TYPE_DESTOPTS: 66 { 67 struct bcm_ipv6_dest_options_hdr *pstIpv6DestOptsHdr = (struct bcm_ipv6_dest_options_hdr *)pucPayloadPtr; 68 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 * IPV6_DESTOPTS_HDR_OPTIONSIZE ; 74 75 } 76 break; 77 case IPV6HDR_TYPE_AUTHENTICATION: 78 { 79 struct bcm_ipv6_authentication_hdr *pstIpv6AuthHdr = (struct bcm_ipv6_authentication_hdr *)pucPayloadPtr; 80 int nHdrLen = pstIpv6AuthHdr->ucLength; 81 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, 82 DBG_LVL_ALL, 83 "\nIPv6 Authentication Header"); 84 usNextHeaderOffset += nHdrLen * 4; 85 } 86 break; 87 case IPV6HDR_TYPE_ENCRYPTEDSECURITYPAYLOAD: 88 { 89 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, 90 DBG_LVL_ALL, 91 "\nIPv6 Encrypted Security Payload Header"); 92 *bParseDone = TRUE; 93 94 } 95 break; 96 case IPV6_ICMP_HDR_TYPE: 97 { 98 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, 99 DBG_LVL_ALL, "\nICMP Header"); 100 *bParseDone = TRUE; 101 } 102 break; 103 case TCP_HEADER_TYPE: 104 { 105 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, 106 DBG_LVL_ALL, "\nTCP Header"); 107 *bParseDone = TRUE; 108 } 109 break; 110 case UDP_HEADER_TYPE: 111 { 112 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, 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 143static UCHAR GetIpv6ProtocolPorts(UCHAR *pucPayload, USHORT *pusSrcPort, 144 USHORT *pusDestPort, USHORT usPayloadLength, UCHAR ucNextHeader) 145{ 146 UCHAR *pIpv6HdrScanContext = pucPayload; 147 bool 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)); 165 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, 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 */ 183USHORT 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 struct bcm_ipv6_hdr *pstIpv6Header = NULL; 190 bool bClassificationSucceed = false; 191 192 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, 193 DBG_LVL_ALL, "IpVersion6 ==========>\n"); 194 195 pstIpv6Header = 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(struct bcm_ipv6_hdr)), 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 246 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, 247 DBG_LVL_ALL, "\nIPv6 Protocol Matched"); 248 249 if ((ucNextProtocolAboveIP == TCP_HEADER_TYPE) || 250 (ucNextProtocolAboveIP == UDP_HEADER_TYPE)) { 251 /* Match Src Port */ 252 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, 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 260 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, 261 DBG_LVL_ALL, "\nIPv6 Src Port Matched"); 262 263 /* Match Dest Port */ 264 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, 265 DBG_LVL_ALL, "\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, "\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 291static 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 /* 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) { 315 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, 316 "\n Src Ipv6 Address In Received Packet :\n "); 317 DumpIpv6Address(aulSrcIP); 318 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, 319 "\n Src Ipv6 Mask In Classifier Rule:\n"); 320 DumpIpv6Address(&pstClassifierRule->stSrcIpAddress.ulIpv6Mask[uiLoopIndex]); 321 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, 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 */ 337 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, 338 DBG_LVL_ALL, 339 "Ipv6 Src Ip Address Matched\n"); 340 return TRUE; 341 } 342 } 343 } 344 return false; 345} 346 347static bool MatchDestIpv6Address(struct bcm_classifier_rule *pstClassifierRule, 348 struct bcm_ipv6_hdr *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) { 372 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, 373 "\n Destination Ipv6 Address In Received Packet :\n "); 374 DumpIpv6Address(aulDestIP); 375 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, 376 "\n Destination Ipv6 Mask In Classifier Rule :\n"); 377 DumpIpv6Address(&pstClassifierRule->stDestIpAddress.ulIpv6Mask[uiLoopIndex]); 378 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, 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 */ 394 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, 395 DBG_LVL_ALL, 396 "Ipv6 Destination Ip Address Matched\n"); 397 return TRUE; 398 } 399 } 400 } 401 return false; 402 403} 404 405VOID 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++) { 411 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, 412 ":%lx", puIpv6Address[uiIpv6AddIndex]); 413 } 414 415} 416 417static VOID DumpIpv6Header(struct bcm_ipv6_hdr *pstIpv6Header) 418{ 419 UCHAR ucVersion; 420 UCHAR ucPrio; 421 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 422 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, 423 "----Ipv6 Header---"); 424 ucVersion = pstIpv6Header->ucVersionPrio & 0xf0; 425 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, 426 "Version : %x\n", ucVersion); 427 ucPrio = pstIpv6Header->ucVersionPrio & 0x0f; 428 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, 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 */ 434 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, 435 "Payload Length : %x\n", 436 ntohs(pstIpv6Header->usPayloadLength)); 437 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, 438 "Next Header : %x\n", pstIpv6Header->ucNextHeader); 439 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, 440 "Hop Limit : %x\n", pstIpv6Header->ucHopLimit); 441 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, 442 "Src Address :\n"); 443 DumpIpv6Address(pstIpv6Header->ulSrcIpAddress); 444 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, 445 "Dest Address :\n"); 446 DumpIpv6Address(pstIpv6Header->ulDestIpAddress); 447 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, 448 "----Ipv6 Header End---"); 449 450 451}