IPv6Protocol.c 13 KB

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