Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3744 lines
109 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Module Name:
  3. packet.c
  4. Abstract:
  5. This module contains all the necesarry routines for encapsulating PPPoE
  6. packets and their related NDIS and NDISWAN packets.
  7. Author:
  8. Hakan Berk - Microsoft, Inc. (hakanb@microsoft.com) Feb-2000
  9. Environment:
  10. Windows 2000 kernel mode Miniport driver or equivalent.
  11. Revision History:
  12. ---------------------------------------------------------------------------*/
  13. #include <ntddk.h>
  14. #include <ntddndis.h>
  15. #include <ndis.h>
  16. #include <ndiswan.h>
  17. #include <ndistapi.h>
  18. #include <ntverp.h>
  19. #include "debug.h"
  20. #include "timer.h"
  21. #include "bpool.h"
  22. #include "ppool.h"
  23. #include "util.h"
  24. #include "packet.h"
  25. #include "protocol.h"
  26. #include "miniport.h"
  27. #include "tapi.h"
  28. //////////////////////////////////////////////////////////////////////////
  29. //
  30. // Variables local to packet.c
  31. // They are defined global only for debugging purposes.
  32. //
  33. ///////////////////////////////////////////////////////////////////////////
  34. //
  35. // Flag that indicates if gl_lockPools is allocated or not
  36. //
  37. BOOLEAN gl_fPoolLockAllocated = FALSE;
  38. //
  39. // Spin lock to synchronize access to gl_ulNumPackets
  40. //
  41. NDIS_SPIN_LOCK gl_lockPools;
  42. //
  43. // Our pool of PPPoE buffer descriptors
  44. //
  45. BUFFERPOOL gl_poolBuffers;
  46. //
  47. // Our pool of PPPoE packet descriptors
  48. //
  49. PACKETPOOL gl_poolPackets;
  50. //
  51. // Ndis pool of buffer descriptors
  52. //
  53. NDIS_HANDLE gl_hNdisBufferPool;
  54. //
  55. // Non-paged lookaside list for PppoePacket structures
  56. //
  57. NPAGED_LOOKASIDE_LIST gl_llistPppoePackets;
  58. //
  59. // This is for debugging purposes. Shows the number of active packets
  60. //
  61. ULONG gl_ulNumPackets = 0;
  62. //
  63. // This defines the broadcast destination address
  64. //
  65. CHAR EthernetBroadcastAddress[6] = { (CHAR) 0xff,
  66. (CHAR) 0xff,
  67. (CHAR) 0xff,
  68. (CHAR) 0xff,
  69. (CHAR) 0xff,
  70. (CHAR) 0xff };
  71. VOID
  72. ReferencePacket(
  73. IN PPPOE_PACKET* pPacket
  74. )
  75. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  76. Functional Description:
  77. This function will increment the reference count on the packet object.
  78. Parameters:
  79. pPacket _ A pointer to the packet context.
  80. Return Values:
  81. None
  82. ---------------------------------------------------------------------------*/
  83. {
  84. LONG lRef;
  85. TRACE( TL_V, TM_Pk, ("+ReferencePacket") );
  86. lRef = NdisInterlockedIncrement( &pPacket->lRef );
  87. TRACE( TL_V, TM_Pk, ("-ReferencePacket=$%x",lRef) );
  88. }
  89. VOID
  90. DereferencePacket(
  91. IN PPPOE_PACKET* pPacket
  92. )
  93. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  94. Functional Description:
  95. This function will decrement the reference count on the packet object.
  96. When ref count reaches 0, packet is cleaned up.
  97. Parameters:
  98. pPacket _ A pointer to the packet context.
  99. Return Values:
  100. None
  101. ---------------------------------------------------------------------------*/
  102. {
  103. LONG lRef;
  104. TRACE( TL_V, TM_Pk, ("+DereferencePacket") );
  105. lRef = NdisInterlockedDecrement( &pPacket->lRef );
  106. if ( lRef == 0 )
  107. {
  108. if ( pPacket->ulFlags & PCBF_BufferChainedToPacket )
  109. {
  110. //
  111. // Unchain the buffer before freeing any packets
  112. //
  113. TRACE( TL_V, TM_Pk, ("DereferencePacket: Buffer unchained from packet") );
  114. NdisUnchainBufferAtFront( pPacket->pNdisPacket, &pPacket->pNdisBuffer );
  115. }
  116. if ( pPacket->ulFlags & PCBF_BufferAllocatedFromOurBufferPool )
  117. {
  118. //
  119. // Skipping check for pBuffer == NULL as this should never happen
  120. // But call NdisAdjustBufferLength() to set the buffer length to original value
  121. //
  122. TRACE( TL_V, TM_Pk, ("DereferencePacket: Buffer returned to our pool") );
  123. NdisAdjustBufferLength( pPacket->pNdisBuffer, PPPOE_PACKET_BUFFER_SIZE );
  124. FreeBufferToPool( &gl_poolBuffers, pPacket->pHeader, TRUE );
  125. }
  126. if ( pPacket->ulFlags & PCBF_BufferAllocatedFromNdisBufferPool )
  127. {
  128. TRACE( TL_V, TM_Pk, ("DereferencePacket: Buffer returned to ndis pool") );
  129. NdisFreeBuffer( pPacket->pNdisBuffer );
  130. }
  131. if ( pPacket->ulFlags & PCBF_CallNdisMWanSendComplete )
  132. {
  133. //
  134. // Return packet back to NDISWAN
  135. //
  136. TRACE( TL_V, TM_Pk, ("DereferencePacket: Returning packet back to NDISWAN") );
  137. NdisMWanSendComplete( PacketGetMiniportAdapter( pPacket )->MiniportAdapterHandle,
  138. PacketGetRelatedNdiswanPacket( pPacket ),
  139. PacketGetSendCompletionStatus( pPacket ) );
  140. //
  141. // Indicate to miniport that the packet is returned to NDISWAN
  142. //
  143. MpPacketOwnedByNdiswanReturned( PacketGetMiniportAdapter( pPacket ) );
  144. }
  145. if ( pPacket->ulFlags & PCBF_PacketAllocatedFromOurPacketPool )
  146. {
  147. //
  148. // Skipping check for pPacketHead == NULL as this should never happen
  149. //
  150. TRACE( TL_V, TM_Pk, ("DereferencePacket: Packet returned to our pool") );
  151. NdisReinitializePacket( pPacket->pNdisPacket );
  152. FreePacketToPool( &gl_poolPackets, pPacket->pPacketHead, TRUE );
  153. }
  154. if ( pPacket->ulFlags & PCBF_CallNdisReturnPackets )
  155. {
  156. //
  157. // Return packet back to NDIS
  158. //
  159. TRACE( TL_V, TM_Pk, ("DereferencePacket: Returning packet back to NDIS") );
  160. NdisReturnPackets( &pPacket->pNdisPacket, 1 );
  161. //
  162. // Indicate to protocol that the packet is returned to NDIS.
  163. //
  164. PrPacketOwnedByNdisReturned( pPacket->pBinding );
  165. }
  166. //
  167. // Finally return PppoePacket to the lookaside list
  168. //
  169. NdisFreeToNPagedLookasideList( &gl_llistPppoePackets, (PVOID) pPacket );
  170. NdisAcquireSpinLock( &gl_lockPools );
  171. gl_ulNumPackets--;
  172. TRACE( TL_V, TM_Pk, ("DereferencePacket: gl_ulNumPacket=$%x", gl_ulNumPackets) );
  173. NdisReleaseSpinLock( &gl_lockPools );
  174. }
  175. TRACE( TL_V, TM_Pk, ("-DereferencePacket=$%x",lRef) );
  176. }
  177. VOID
  178. RetrieveTag(
  179. IN OUT PPPOE_PACKET* pPacket,
  180. IN PACKET_TAGS tagType,
  181. OUT USHORT * pTagLength,
  182. OUT CHAR** pTagValue,
  183. IN USHORT prevTagLength,
  184. IN CHAR * prevTagValue,
  185. IN BOOLEAN fSetTagInPacket
  186. )
  187. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  188. Functional Description:
  189. You can call this function on a received packet processed with one of the
  190. PacketInitialize*FromReceived() functions.
  191. It will not operate on a PAYLOAD packet, although you can call it safely.
  192. It will retrieve and return the next length - value pair for a specific tag.
  193. To retrieve the 1st one, pass 0 and NULL for prevTag* parameters.
  194. If you pass fSetTagInPacket as TRUE, and if the next tag is found and the tag is known
  195. to PppoePacket struct, then the fields for the tag in the packet are updated to point
  196. to the found tag.
  197. If there are no next tags, then *pTagValue will point to NULL, and *pTagLength
  198. will point to '0'.
  199. Parameters:
  200. pPacket _ Pointer to a packet context prepared by a PacketInitializeXXXToSend()
  201. function, or PacketInitializeFromReceived().
  202. tagType _ Type of the tag being searched for.
  203. pTagLength _ A pointer to a USHORT var that will keep the length of the returned tag.
  204. pTagValue _ A pointer to the value of the tag which is basically a blob of
  205. length *pTagLength.
  206. prevTagLength _ The length of the value of the previous tag.
  207. prevTagValue _ Points to the beginning of the value of the previous tag.
  208. fSetTagInPacket _ Indicates that if a tag is found and is native to PPPoE packet context,
  209. then PPPoE packet context must be updated to point to this new tag.
  210. Return Values:
  211. None
  212. ---------------------------------------------------------------------------*/
  213. {
  214. CHAR* pBuf = NULL;
  215. CHAR* pBufEnd = NULL;
  216. ASSERT( pPacket != NULL );
  217. ASSERT( pTagLength != NULL );
  218. ASSERT( pTagValue != NULL );
  219. TRACE( TL_V, TM_Pk, ("+RetrieveTag") );
  220. //
  221. // Initialize the output parameters
  222. //
  223. *pTagLength = (USHORT) 0;
  224. *pTagValue = NULL;
  225. //
  226. // If this is a payload packet, then do not search for any tags
  227. //
  228. if ( PacketGetCode( pPacket ) == PACKET_CODE_PAYLOAD )
  229. {
  230. TRACE( TL_V, TM_Pk, ("-RetrieveTag: No tags. Payload packet") );
  231. return;
  232. }
  233. //
  234. // Find the start point to search for the tag
  235. //
  236. if ( prevTagValue != NULL )
  237. {
  238. //
  239. // Caller wants the next tag, so make pBuf point to end of the prev tag value
  240. //
  241. pBuf = prevTagValue + prevTagLength;
  242. }
  243. else
  244. {
  245. //
  246. // Caller wants the first tag in the packet
  247. //
  248. pBuf = pPacket->pPayload;
  249. }
  250. //
  251. // Find the end point of the tag payload area
  252. //
  253. pBufEnd = pPacket->pPayload + PacketGetLength( pPacket );
  254. //
  255. // Search for the tag until we step outside the boundaries
  256. //
  257. while ( pBuf + PPPOE_TAG_HEADER_LENGTH <= pBufEnd )
  258. {
  259. USHORT usTagLength;
  260. USHORT usTagType;
  261. usTagType = ntohs( *((USHORT UNALIGNED *) pBuf) ) ;
  262. ((USHORT*) pBuf)++;
  263. usTagLength = ntohs( *((USHORT UNALIGNED *) pBuf) ) ;
  264. ((USHORT*) pBuf)++;
  265. if ( usTagType == tagType )
  266. {
  267. //
  268. // Tag found, retrieve length and values
  269. //
  270. TRACE( TL_N, TM_Pk, ("RetrieveTag: Tag found:$%x", *pTagLength) );
  271. *pTagLength = usTagLength;
  272. *pTagValue = pBuf;
  273. break;
  274. }
  275. pBuf += usTagLength;
  276. }
  277. //
  278. // Check if tag was found
  279. //
  280. if ( *pTagValue != NULL )
  281. {
  282. //
  283. // Tag found. Check if the caller wants to set it in the PppoePacket
  284. //
  285. if ( fSetTagInPacket )
  286. {
  287. TRACE( TL_V, TM_Pk, ("RetrieveTag: Setting tag in packet") );
  288. switch ( tagType )
  289. {
  290. case tagEndOfList:
  291. break;
  292. case tagServiceName:
  293. pPacket->tagServiceNameLength = *pTagLength;
  294. pPacket->tagServiceNameValue = *pTagValue;
  295. break;
  296. case tagACName:
  297. pPacket->tagACNameLength = *pTagLength;
  298. pPacket->tagACNameValue = *pTagValue;
  299. break;
  300. case tagHostUnique:
  301. pPacket->tagHostUniqueLength = *pTagLength;
  302. pPacket->tagHostUniqueValue = *pTagValue;
  303. break;
  304. case tagACCookie:
  305. pPacket->tagACCookieLength = *pTagLength;
  306. pPacket->tagACCookieValue = *pTagValue;
  307. break;
  308. case tagRelaySessionId:
  309. pPacket->tagRelaySessionIdLength = *pTagLength;
  310. pPacket->tagRelaySessionIdValue = *pTagValue;
  311. break;
  312. case tagServiceNameError:
  313. pPacket->tagErrorType = tagServiceNameError;
  314. pPacket->tagErrorTagLength = *pTagLength;
  315. pPacket->tagErrorTagValue = *pTagValue;
  316. break;
  317. case tagACSystemError:
  318. pPacket->tagErrorType = tagACSystemError;
  319. pPacket->tagErrorTagLength = *pTagLength;
  320. pPacket->tagErrorTagValue = *pTagValue;
  321. break;
  322. case tagGenericError:
  323. pPacket->tagErrorType = tagGenericError;
  324. pPacket->tagErrorTagLength = *pTagLength;
  325. pPacket->tagErrorTagValue = *pTagValue;
  326. break;
  327. default:
  328. break;
  329. }
  330. }
  331. }
  332. TRACE( TL_V, TM_Pk, ("-RetrieveTag") );
  333. }
  334. NDIS_STATUS
  335. PreparePacketForWire(
  336. IN OUT PPPOE_PACKET* pPacket
  337. )
  338. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  339. Functional Description:
  340. This function prepares the packet for wire.
  341. It must be called inside a PacketInitializeXXXToSend() function after all
  342. processing is done with the packet to prepare it to be transmitted over the wire.
  343. It basically creates and writes the tags into the payload area of the packet,
  344. and finally adjusts the length of the buffer to let Ndis know the extents of the
  345. valid data blob.
  346. Parameters:
  347. pPacket _ Pointer to a packet context prepared by a PacketInitializeXXXToSend()
  348. function.
  349. Return Values:
  350. NDIS_STATUS_SUCCESS
  351. NDIS_STATUS_INVALID_PACKET
  352. ---------------------------------------------------------------------------*/
  353. {
  354. NDIS_STATUS status = NDIS_STATUS_SUCCESS;
  355. CHAR* pBuf;
  356. ASSERT( pPacket != NULL );
  357. TRACE( TL_V, TM_Pk, ("+PreparePacketForWire") );
  358. //
  359. // Now insert the tags if packet is a Discovery Ethernet packet
  360. //
  361. switch ( PacketGetCode( pPacket ) )
  362. {
  363. case PACKET_CODE_PADI:
  364. PacketInsertTag( pPacket,
  365. tagServiceName,
  366. pPacket->tagServiceNameLength,
  367. pPacket->tagServiceNameValue,
  368. &pPacket->tagServiceNameValue);
  369. if ( pPacket->tagHostUniqueLength > 0 )
  370. {
  371. TRACE( TL_N, TM_Pk, ("PreparePacketForWire: Inserting host unique tag") );
  372. PacketInsertTag( pPacket,
  373. tagHostUnique,
  374. pPacket->tagHostUniqueLength,
  375. pPacket->tagHostUniqueValue,
  376. &pPacket->tagHostUniqueValue );
  377. }
  378. break;
  379. case PACKET_CODE_PADO:
  380. PacketInsertTag( pPacket,
  381. tagServiceName,
  382. pPacket->tagServiceNameLength,
  383. pPacket->tagServiceNameValue,
  384. &pPacket->tagServiceNameValue );
  385. if ( pPacket->tagHostUniqueLength > 0 )
  386. {
  387. TRACE( TL_N, TM_Pk, ("PreparePacketForWire: Inserting host unique tag") );
  388. PacketInsertTag( pPacket,
  389. tagHostUnique,
  390. pPacket->tagHostUniqueLength,
  391. pPacket->tagHostUniqueValue,
  392. &pPacket->tagHostUniqueValue );
  393. }
  394. if ( pPacket->tagRelaySessionIdLength > 0 )
  395. {
  396. TRACE( TL_N, TM_Pk, ("PreparePacketForWire: Inserting relay sesion id tag") );
  397. PacketInsertTag( pPacket,
  398. tagRelaySessionId,
  399. pPacket->tagRelaySessionIdLength,
  400. pPacket->tagRelaySessionIdValue,
  401. &pPacket->tagRelaySessionIdValue );
  402. }
  403. PacketInsertTag( pPacket,
  404. tagACName,
  405. pPacket->tagACNameLength,
  406. pPacket->tagACNameValue,
  407. &pPacket->tagACNameValue );
  408. PacketInsertTag( pPacket,
  409. tagACCookie,
  410. pPacket->tagACCookieLength,
  411. pPacket->tagACCookieValue,
  412. &pPacket->tagACCookieValue );
  413. break;
  414. case PACKET_CODE_PADR:
  415. PacketInsertTag( pPacket,
  416. tagServiceName,
  417. pPacket->tagServiceNameLength,
  418. pPacket->tagServiceNameValue,
  419. &pPacket->tagServiceNameValue );
  420. if ( pPacket->tagHostUniqueLength > 0 )
  421. {
  422. TRACE( TL_N, TM_Pk, ("PreparePacketForWire: Inserting host unique tag") );
  423. PacketInsertTag( pPacket,
  424. tagHostUnique,
  425. pPacket->tagHostUniqueLength,
  426. pPacket->tagHostUniqueValue,
  427. &pPacket->tagHostUniqueValue );
  428. }
  429. if ( pPacket->tagRelaySessionIdLength > 0 )
  430. {
  431. TRACE( TL_N, TM_Pk, ("PreparePacketForWire: Inserting relay sesion id tag") );
  432. PacketInsertTag( pPacket,
  433. tagRelaySessionId,
  434. pPacket->tagRelaySessionIdLength,
  435. pPacket->tagRelaySessionIdValue,
  436. &pPacket->tagRelaySessionIdValue );
  437. }
  438. if ( pPacket->tagACCookieLength > 0 )
  439. {
  440. TRACE( TL_N, TM_Pk, ("PreparePacketForWire: Inserting ac-ccokie tag") );
  441. PacketInsertTag( pPacket,
  442. tagACCookie,
  443. pPacket->tagACCookieLength,
  444. pPacket->tagACCookieValue,
  445. &pPacket->tagACCookieValue );
  446. }
  447. break;
  448. case PACKET_CODE_PADS:
  449. PacketInsertTag( pPacket,
  450. tagServiceName,
  451. pPacket->tagServiceNameLength,
  452. pPacket->tagServiceNameValue,
  453. &pPacket->tagServiceNameValue );
  454. if ( pPacket->tagHostUniqueLength > 0 )
  455. {
  456. TRACE( TL_N, TM_Pk, ("PreparePacketForWire: Inserting host unique tag") );
  457. PacketInsertTag( pPacket,
  458. tagHostUnique,
  459. pPacket->tagHostUniqueLength,
  460. pPacket->tagHostUniqueValue,
  461. &pPacket->tagHostUniqueValue );
  462. }
  463. if ( pPacket->tagRelaySessionIdLength > 0 )
  464. {
  465. TRACE( TL_N, TM_Pk, ("PreparePacketForWire: Inserting relay sesion id tag") );
  466. PacketInsertTag( pPacket,
  467. tagRelaySessionId,
  468. pPacket->tagRelaySessionIdLength,
  469. pPacket->tagRelaySessionIdValue,
  470. &pPacket->tagRelaySessionIdValue );
  471. }
  472. break;
  473. case PACKET_CODE_PADT:
  474. break;
  475. case PACKET_CODE_PAYLOAD:
  476. break;
  477. default:
  478. status = NDIS_STATUS_INVALID_PACKET;
  479. }
  480. if ( status == NDIS_STATUS_SUCCESS )
  481. {
  482. //
  483. // Adjust buffer length
  484. //
  485. NdisAdjustBufferLength( pPacket->pNdisBuffer,
  486. (UINT) ( PacketGetLength( pPacket ) + PPPOE_PACKET_HEADER_LENGTH ) );
  487. }
  488. TRACE( TL_V, TM_Pk, ("-PreparePacketForWire=$%x",status) );
  489. return status;
  490. }
  491. PPPOE_PACKET*
  492. PacketCreateSimple()
  493. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  494. Functional Description:
  495. This function allocates and initializes a simple packet.
  496. A simple packet is mainly used for control packets to be sent.
  497. Its buffer, and packet is allocated from our pools, buffer is chained to
  498. packet.
  499. On return all following values point to valid places and are safe for use:
  500. pHeader
  501. pPayload
  502. pNdisBuffer
  503. pNdisPacket
  504. Parameters:
  505. None
  506. Return Values:
  507. Pointer to an initialized PPPoE packet context.
  508. ---------------------------------------------------------------------------*/
  509. {
  510. PPPOE_PACKET* pPacket = NULL;
  511. TRACE( TL_V, TM_Pk, ("+PacketCreateSimple") );
  512. //
  513. // Allocate a packet
  514. //
  515. pPacket = PacketAlloc();
  516. if ( pPacket == NULL )
  517. {
  518. TRACE( TL_V, TM_Pk, ("-PacketCreateSimple=$%x",NULL) );
  519. return NULL;
  520. }
  521. //
  522. // Allocate NdisBuffer from our pool
  523. //
  524. pPacket->pHeader = GetBufferFromPool( &gl_poolBuffers );
  525. if ( pPacket->pHeader == NULL )
  526. {
  527. TRACE( TL_A, TM_Pk, ("PacketCreateSimple: Could not get buffer from our pool") );
  528. TRACE( TL_V, TM_Pk, ("-PacketCreateSimple=$%x",NULL) );
  529. PacketFree( pPacket );
  530. return NULL;
  531. }
  532. pPacket->ulFlags |= PCBF_BufferAllocatedFromOurBufferPool;
  533. //
  534. // Clean up the buffer area
  535. //
  536. NdisZeroMemory( pPacket->pHeader, PPPOE_PACKET_BUFFER_SIZE * sizeof( CHAR ) );
  537. //
  538. // Point built-in NDIS buffer pointer to NDIS buffer of buffer from pool
  539. //
  540. pPacket->pNdisBuffer = NdisBufferFromBuffer( pPacket->pHeader );
  541. //
  542. // Allocate an NDIS packet from our pool
  543. //
  544. pPacket->pNdisPacket = GetPacketFromPool( &gl_poolPackets, &pPacket->pPacketHead );
  545. if ( pPacket->pNdisPacket == NULL )
  546. {
  547. TRACE( TL_A, TM_Pk, ("PacketCreateSimple: Could not get packet from our pool") );
  548. TRACE( TL_V, TM_Pk, ("-PacketCreateSimple=$%x",NULL) );
  549. PacketFree( pPacket );
  550. return NULL;
  551. }
  552. pPacket->ulFlags |= PCBF_PacketAllocatedFromOurPacketPool;
  553. //
  554. // Chain buffer to packet
  555. //
  556. NdisChainBufferAtFront( pPacket->pNdisPacket, pPacket->pNdisBuffer );
  557. pPacket->ulFlags |= PCBF_BufferChainedToPacket;
  558. //
  559. // Set the payload and payload length
  560. //
  561. pPacket->pPayload = pPacket->pHeader + PPPOE_PACKET_HEADER_LENGTH;
  562. //
  563. // Set the input NDIS_PACKET to the reserved area so that we can reach it
  564. // when we have to return this packet back to the upper layer.
  565. //
  566. *((PPPOE_PACKET UNALIGNED **)(&pPacket->pNdisPacket->ProtocolReserved[0 * sizeof(PVOID)])) = pPacket;
  567. TRACE( TL_V, TM_Pk, ("-PacketCreateSimple=$%x",pPacket) );
  568. return pPacket;
  569. }
  570. PPPOE_PACKET*
  571. PacketCreateForReceived(
  572. PBINDING pBinding,
  573. PNDIS_PACKET pNdisPacket,
  574. PNDIS_BUFFER pNdisBuffer,
  575. PUCHAR pContents
  576. )
  577. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  578. Functional Description:
  579. This function allocates and initializes a packet from a received packet.
  580. This function is used for perf optimization. When the received packet has
  581. a single buffer that we can pass to the miniport.
  582. On return all following values point to valid places and are safe for use:
  583. pHeader
  584. pPayload
  585. pNdisBuffer
  586. pNdisPacket
  587. Parameters:
  588. pBinding _ The binding over which this packet is received.
  589. pNdisPacket _ Ndis Packet descriptor from the received packet.
  590. pNdisBuffer _ Ndis Buffer descriptor from the received packet.
  591. pContents _ Pointer to the contents of the buffer.
  592. Return Values:
  593. Pointer to an initialized PPPoE packet context.
  594. ---------------------------------------------------------------------------*/
  595. {
  596. PPPOE_PACKET* pPacket = NULL;
  597. TRACE( TL_V, TM_Pk, ("+PacketCreateForReceived") );
  598. //
  599. // Allocate a packet
  600. //
  601. pPacket = PacketAlloc();
  602. if ( pPacket == NULL )
  603. {
  604. TRACE( TL_V, TM_Pk, ("-PacketCreateForReceived=$%x",NULL) );
  605. return NULL;
  606. }
  607. //
  608. // Mark the packet so we return it to NDIS when it is freed
  609. //
  610. pPacket->ulFlags |= PCBF_CallNdisReturnPackets;
  611. //
  612. // Save the binding and indicate to protocol such a packet is created using
  613. // PrPacketOwnedByNdisReceived()
  614. //
  615. pPacket->pBinding = pBinding;
  616. PrPacketOwnedByNdisReceived( pBinding );
  617. //
  618. // Set the pointers
  619. //
  620. pPacket->pHeader = pContents;
  621. pPacket->pNdisBuffer = pNdisBuffer;
  622. pPacket->pNdisPacket = pNdisPacket;
  623. pPacket->pPayload = pPacket->pHeader + PPPOE_PACKET_HEADER_LENGTH;
  624. TRACE( TL_V, TM_Pk, ("-PacketCreateForReceived=$%x",pPacket) );
  625. return pPacket;
  626. }
  627. PPPOE_PACKET*
  628. PacketNdis2Pppoe(
  629. IN PBINDING pBinding,
  630. IN PNDIS_PACKET pNdisPacket,
  631. OUT PINT pRefCount
  632. )
  633. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  634. Functional Description:
  635. This function is used to convert only NDIS packets indicated by PrReceivePacket().
  636. If packet is received by PrReceive() then you should not be using this function.
  637. We look at the Ndis buffer, and if it has a single flat buffer, then we exploit it
  638. and use the original Ndis packets buffer descriptors so we do not do any copy,
  639. otherwise we create our own copy of it as PPPoE packet, and operate on it.
  640. ( AliD says, 99% of the time the single flat buffer case will be true. )
  641. If we use the original Ndis packet, then we return 1 in the pRefCount parameter,
  642. otherwise we return 0.
  643. On return all following values point to valid places and are safe for use:
  644. pHeader
  645. pPayload
  646. pNdisBuffer
  647. pNdisPacket
  648. Parameters:
  649. pBinding _ The binding over which this packet is received.
  650. pNdisPacket _ Original, unprocessed Ndis packet.
  651. This must be indicated by ProtocolReceivePacket().
  652. pRefCount _ Reference count to be returned to Ndis from ProtocolReceivePacket().
  653. We return 1 if we can use the Ndis packet and buffer descriptors, otherwise
  654. we make our own copy so we won't need the original Ndis packet, so we return 0.
  655. Return Values:
  656. Pointer to an initialized PPPoE packet context.
  657. ---------------------------------------------------------------------------*/
  658. {
  659. PPPOE_PACKET* pPacket = NULL;
  660. NDIS_BUFFER* pNdisBuffer = NULL;
  661. UINT nBufferCount = 0;
  662. UINT nTotalLength = 0;
  663. PVOID pBufferContents = NULL;
  664. UINT nBufferLength;
  665. UINT nCopiedBufferLength = 0;
  666. BOOLEAN fReturnPacket = FALSE;
  667. TRACE( TL_V, TM_Pk, ("+PacketNdis2Pppoe") );
  668. do
  669. {
  670. //
  671. // Query the packet and get the total length and the pointer to first buffer
  672. //
  673. NdisQueryPacket( pNdisPacket,
  674. NULL,
  675. &nBufferCount,
  676. &pNdisBuffer,
  677. &nTotalLength );
  678. //
  679. // Make sure indicated packet is not larger than expected
  680. //
  681. if ( nTotalLength > (UINT) PPPOE_PACKET_BUFFER_SIZE )
  682. {
  683. TRACE( TL_A, TM_Pk, ("PacketNdis2Pppoe: Packet larger than expected") );
  684. break;
  685. }
  686. if ( nBufferCount == 1 &&
  687. NDIS_GET_PACKET_STATUS(pNdisPacket) != NDIS_STATUS_RESOURCES)
  688. {
  689. //
  690. // We can handle this case efficiently
  691. //
  692. //
  693. // Since we will be using the original Ndis packet and buffers, make sure
  694. // length specified in the PPPoE packet does not exceed the total length
  695. // of the Ndis packet
  696. //
  697. USHORT usPppoePacketLength;
  698. NdisQueryBufferSafe( pNdisBuffer,
  699. &pBufferContents,
  700. &nBufferLength,
  701. NormalPagePriority );
  702. if ( pBufferContents == NULL )
  703. {
  704. TRACE( TL_A, TM_Pk, ("PacketNdis2Pppoe: System resources low, dropping packet") );
  705. break;
  706. }
  707. if ( nBufferLength < ETHERNET_HEADER_LENGTH )
  708. {
  709. TRACE( TL_A, TM_Pk, ("PacketNdis2Pppoe: Packet header smaller than expected") );
  710. break;
  711. }
  712. if ( !PacketFastIsPPPoE( pBufferContents, ETHERNET_HEADER_LENGTH ) )
  713. {
  714. TRACE( TL_V, TM_Pk, ("PacketNdis2Pppoe: Packet is not PPPoE") );
  715. break;
  716. }
  717. usPppoePacketLength = ntohs( * ( USHORT UNALIGNED * ) ( (PUCHAR) pBufferContents + PPPOE_PACKET_LENGTH_OFFSET ) );
  718. if ( (UINT) usPppoePacketLength > nTotalLength )
  719. {
  720. TRACE( TL_A, TM_Pk, ("PacketNdis2Pppoe: PPPoE Packet length larger than Ndis packet length") );
  721. break;
  722. }
  723. //
  724. // Let's create our PPPoE packet to keep the copy of the received packet
  725. //
  726. pPacket = PacketCreateForReceived( pBinding,
  727. pNdisPacket,
  728. pNdisBuffer,
  729. pBufferContents );
  730. if ( pPacket == NULL )
  731. {
  732. TRACE( TL_A, TM_Pk, ("PacketNdis2Pppoe: Could not allocate context to copy the packet") );
  733. break;
  734. }
  735. fReturnPacket = TRUE;
  736. *pRefCount = 1;
  737. }
  738. else
  739. {
  740. //
  741. // Since Ndis packet contains multiple buffers, we can not handle this case efficiently.
  742. // We need to allocate a PPPoE packet, copy the contents of the Ndis packet as a flat
  743. // buffer to this packet, and then operate on it.
  744. //
  745. //
  746. // Let's create our PPPoE packet to keep the copy of the received packet
  747. //
  748. pPacket = PacketCreateSimple();
  749. if ( pPacket == NULL )
  750. {
  751. TRACE( TL_A, TM_Pk, ("PacketNdis2Pppoe: Could not allocate context to copy the packet") );
  752. break;
  753. }
  754. //
  755. // Retrieve the header and check if the packet is a PPPoE frame or not
  756. //
  757. do
  758. {
  759. NdisQueryBufferSafe( pNdisBuffer,
  760. &pBufferContents,
  761. &nBufferLength,
  762. NormalPagePriority );
  763. if ( pBufferContents == NULL )
  764. {
  765. TRACE( TL_A, TM_Pk, ("PacketNdis2Pppoe: System resources low, dropping packet") );
  766. break;
  767. }
  768. NdisMoveMemory( pPacket->pHeader + nCopiedBufferLength,
  769. pBufferContents,
  770. nBufferLength );
  771. nCopiedBufferLength += nBufferLength;
  772. } while ( nCopiedBufferLength < ETHERNET_HEADER_LENGTH );
  773. if ( nCopiedBufferLength < ETHERNET_HEADER_LENGTH )
  774. {
  775. TRACE( TL_A, TM_Pk, ("PacketNdis2Pppoe: Header could not be retrieved") );
  776. break;
  777. }
  778. if ( !PacketFastIsPPPoE( pPacket->pHeader, ETHERNET_HEADER_LENGTH ) )
  779. {
  780. TRACE( TL_V, TM_Pk, ("PacketNdis2Pppoe: Packet is not PPPoE") );
  781. break;
  782. }
  783. //
  784. // Since we know that the packet is PPPoE, copy the rest of the data to our
  785. // own copy of the packet
  786. //
  787. NdisGetNextBuffer( pNdisBuffer,
  788. &pNdisBuffer );
  789. while ( pNdisBuffer != NULL )
  790. {
  791. NdisQueryBufferSafe( pNdisBuffer,
  792. &pBufferContents,
  793. &nBufferLength,
  794. NormalPagePriority );
  795. if ( pBufferContents == NULL )
  796. {
  797. TRACE( TL_A, TM_Pk, ("PacketNdis2Pppoe: System resources low, dropping packet") );
  798. break;
  799. }
  800. NdisMoveMemory( pPacket->pHeader + nCopiedBufferLength,
  801. pBufferContents,
  802. nBufferLength );
  803. nCopiedBufferLength += nBufferLength;
  804. NdisGetNextBuffer( pNdisBuffer,
  805. &pNdisBuffer );
  806. }
  807. //
  808. // Check if we could copy the whole chain of buffers
  809. //
  810. if ( nCopiedBufferLength < nTotalLength )
  811. {
  812. TRACE( TL_A, TM_Pk, ("PacketNdis2Pppoe: Failed to copy the whole data from all buffers") );
  813. break;
  814. }
  815. fReturnPacket = TRUE;
  816. *pRefCount = 0;
  817. }
  818. } while ( FALSE );
  819. if ( !fReturnPacket )
  820. {
  821. if ( pPacket )
  822. {
  823. PacketFree( pPacket );
  824. pPacket = NULL;
  825. }
  826. }
  827. TRACE( TL_V, TM_Pk, ("-PacketNdis2Pppoe=$%x", pPacket) );
  828. return pPacket;
  829. }
  830. BOOLEAN
  831. PacketIsPPPoE(
  832. IN PPPOE_PACKET* pPacket
  833. )
  834. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  835. Functional Description:
  836. This function is used to understand if the received packet is a PPPoE
  837. packet or not. If it is then, it should be further processed, otherwise it
  838. should be dropped.
  839. Parameters:
  840. pPacket _ Pointer to a packet context prepared.
  841. Return Values:
  842. Pointer to an initialized PPPoE packet context.
  843. ---------------------------------------------------------------------------*/
  844. {
  845. BOOLEAN fReturn = FALSE;
  846. TRACE( TL_V, TM_Pk, ("+PacketIsPPPoE") );
  847. do
  848. {
  849. //
  850. // Check packet ether type
  851. //
  852. if ( PacketGetEtherType( pPacket ) != PACKET_ETHERTYPE_DISCOVERY &&
  853. PacketGetEtherType( pPacket ) != PACKET_ETHERTYPE_PAYLOAD )
  854. {
  855. TRACE( TL_A, TM_Pk, ("PacketIsPPPoE: Unknown ether type") );
  856. break;
  857. }
  858. //
  859. // Check packet version
  860. //
  861. if ( PacketGetVersion( pPacket ) != PACKET_VERSION )
  862. {
  863. TRACE( TL_A, TM_Pk, ("PacketIsPPPoE: Unknown packet version") );
  864. break;
  865. }
  866. //
  867. // Check packet type
  868. //
  869. if ( PacketGetType( pPacket ) != PACKET_TYPE )
  870. {
  871. TRACE( TL_A, TM_Pk, ("PacketIsPPPoE: Unknown packet type") );
  872. break;
  873. }
  874. //
  875. // Make sure length does not exceed PACKET_GEN_MAX_LENGTH
  876. //
  877. if ( PacketGetLength( pPacket ) > PACKET_GEN_MAX_LENGTH )
  878. {
  879. TRACE( TL_A, TM_Pk, ("PacketIsPPPoE: Packet larger than expected") );
  880. break;
  881. }
  882. fReturn = TRUE;
  883. } while ( FALSE );
  884. TRACE( TL_V, TM_Pk, ("-PacketIsPPPoE=$%d",fReturn) );
  885. return fReturn;
  886. }
  887. BOOLEAN
  888. PacketFastIsPPPoE(
  889. IN CHAR* HeaderBuffer,
  890. IN UINT HeaderBufferSize
  891. )
  892. {
  893. BOOLEAN fRet = FALSE;
  894. USHORT usEtherType;
  895. TRACE( TL_V, TM_Pk, ("+PacketFastIsPPPoE") );
  896. do
  897. {
  898. if ( HeaderBufferSize != ETHERNET_HEADER_LENGTH )
  899. {
  900. //
  901. // Header is not ethernet, so drop the packet
  902. //
  903. TRACE( TL_A, TM_Pk, ("PacketFastIsPPPoE: Bad packet header") );
  904. break;
  905. }
  906. //
  907. // Retrieve the ether type and see if packet of any interest to us
  908. //
  909. usEtherType = ntohs( * ( USHORT UNALIGNED * ) (HeaderBuffer + PPPOE_PACKET_ETHER_TYPE_OFFSET ) );
  910. if ( usEtherType == PACKET_ETHERTYPE_DISCOVERY ||
  911. usEtherType == PACKET_ETHERTYPE_PAYLOAD )
  912. {
  913. //
  914. // Valid ethertype, so accept the packet
  915. //
  916. fRet = TRUE;
  917. }
  918. } while ( FALSE );
  919. TRACE( TL_V, TM_Pk, ("-PacketFastIsPPPoE") );
  920. return fRet;
  921. }
  922. VOID
  923. RetrieveErrorTags(
  924. IN PPPOE_PACKET* pPacket
  925. )
  926. {
  927. USHORT tagLength = 0;
  928. CHAR* tagValue = NULL;
  929. TRACE( TL_V, TM_Pk, ("+RetrieveErrorTags") );
  930. RetrieveTag( pPacket,
  931. tagServiceNameError,
  932. &tagLength,
  933. &tagValue,
  934. 0,
  935. NULL,
  936. TRUE );
  937. if ( tagValue != NULL )
  938. {
  939. TRACE( TL_V, TM_Pk, ("RetrieveErrorTags: ServiceNameError tag received") );
  940. pPacket->ulFlags |= PCBF_ErrorTagReceived;
  941. }
  942. if ( !( pPacket->ulFlags & PCBF_ErrorTagReceived ) )
  943. {
  944. RetrieveTag( pPacket,
  945. tagACSystemError,
  946. &tagLength,
  947. &tagValue,
  948. 0,
  949. NULL,
  950. TRUE );
  951. if ( tagValue != NULL )
  952. {
  953. TRACE( TL_V, TM_Pk, ("RetrieveErrorTags: ACSystemError tag received") );
  954. pPacket->ulFlags |= PCBF_ErrorTagReceived;
  955. }
  956. }
  957. if ( !( pPacket->ulFlags & PCBF_ErrorTagReceived ) )
  958. {
  959. RetrieveTag( pPacket,
  960. tagGenericError,
  961. &tagLength,
  962. &tagValue,
  963. 0,
  964. NULL,
  965. TRUE );
  966. if ( tagValue != NULL )
  967. {
  968. TRACE( TL_V, TM_Pk, ("RetrieveErrorTags: GenericError tag received") );
  969. pPacket->ulFlags |= PCBF_ErrorTagReceived;
  970. }
  971. }
  972. TRACE( TL_V, TM_Pk, ("-RetrieveErrorTags") );
  973. }
  974. ///////////////////////////////////////////////////////////////////////////
  975. //
  976. // Interface functions (exposed outside)
  977. //
  978. ///////////////////////////////////////////////////////////////////////////
  979. VOID
  980. PacketPoolInit()
  981. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  982. Functional Description:
  983. This function initializes or incements the ref count on the this module.
  984. Both miniport and protocol will call this function in their register routines
  985. to allocate packet pools. Only then they can call functions from this module.
  986. We create the packet pools if gl_ulNumPackets is 0, otherwise we just increment
  987. gl_ulNumPackets, and that reference will be removed when the caller calls
  988. PacketPoolUninit() later.
  989. Parameters:
  990. None
  991. Return Values:
  992. None
  993. ---------------------------------------------------------------------------*/
  994. {
  995. TRACE( TL_N, TM_Pk, ("+PacketPoolInit") );
  996. //
  997. // Make sure global lock is allocated
  998. //
  999. if ( !gl_fPoolLockAllocated )
  1000. {
  1001. TRACE( TL_N, TM_Pk, ("PacketPoolInit: First call, allocating global lock") );
  1002. //
  1003. // If global lock is not allocated, then this is the first call,
  1004. // so allocate the spin lock
  1005. //
  1006. NdisAllocateSpinLock( &gl_lockPools );
  1007. gl_fPoolLockAllocated = TRUE;
  1008. }
  1009. NdisAcquireSpinLock( &gl_lockPools );
  1010. if ( gl_ulNumPackets == 0 )
  1011. {
  1012. PacketPoolAlloc();
  1013. }
  1014. gl_ulNumPackets++;
  1015. NdisReleaseSpinLock( &gl_lockPools );
  1016. TRACE( TL_N, TM_Pk, ("-PacketPoolInit") );
  1017. }
  1018. VOID
  1019. PacketPoolUninit()
  1020. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1021. Functional Description:
  1022. This function uninitializes or decrements the ref count on the this module.
  1023. Both miniport and protocol will call this function when they are done with
  1024. this module, and if ref count has dropped to 0, this function will deallocate
  1025. the alloated pools.
  1026. Parameters:
  1027. None
  1028. Return Values:
  1029. None
  1030. ---------------------------------------------------------------------------*/
  1031. {
  1032. TRACE( TL_N, TM_Pk, ("+PacketPoolUninit") );
  1033. //
  1034. // Make sure global lock is allocated
  1035. //
  1036. if ( !gl_fPoolLockAllocated )
  1037. {
  1038. TRACE( TL_A, TM_Pk, ("PacketPoolUninit: Global not allocated yet") );
  1039. TRACE( TL_N, TM_Pk, ("-PacketPoolUninit") );
  1040. return;
  1041. }
  1042. NdisAcquireSpinLock( &gl_lockPools );
  1043. gl_ulNumPackets--;
  1044. if ( gl_ulNumPackets == 0 )
  1045. {
  1046. PacketPoolFree();
  1047. }
  1048. NdisReleaseSpinLock( &gl_lockPools );
  1049. TRACE( TL_N, TM_Pk, ("-PacketPoolUninit") );
  1050. }
  1051. VOID
  1052. PacketPoolAlloc()
  1053. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1054. Functional Description:
  1055. This function wraps the initialization of buffers and packet pools.
  1056. It is called from PacketPoolInit().
  1057. Parameters:
  1058. None
  1059. Return Values:
  1060. None
  1061. ---------------------------------------------------------------------------*/
  1062. {
  1063. NDIS_STATUS status;
  1064. TRACE( TL_N, TM_Pk, ("+PacketPoolAlloc") );
  1065. //
  1066. // Initialize our header pool
  1067. //
  1068. InitBufferPool( &gl_poolBuffers,
  1069. PPPOE_PACKET_BUFFER_SIZE,
  1070. 0, 10, 0,
  1071. TRUE,
  1072. MTAG_BUFFERPOOL );
  1073. //
  1074. // Initialize our packet pool
  1075. //
  1076. InitPacketPool( &gl_poolPackets,
  1077. 3 * sizeof( PVOID ), 0, 30, 0,
  1078. MTAG_PACKETPOOL );
  1079. //
  1080. // Initialize the Ndis Buffer Pool
  1081. // No need to check for status, as DDK says,
  1082. // it always returns NDIS_STATUS_SUCCESS
  1083. //
  1084. NdisAllocateBufferPool( &status,
  1085. &gl_hNdisBufferPool,
  1086. 30 );
  1087. //
  1088. // Initialize the control msg lookaside list
  1089. //
  1090. NdisInitializeNPagedLookasideList(
  1091. &gl_llistPppoePackets, // IN PNPAGED_LOOKASIDE_LIST Lookaside,
  1092. NULL, // IN PALLOCATE_FUNCTION Allocate OPTIONAL,
  1093. NULL, // IN PFREE_FUNCTION Free OPTIONAL,
  1094. 0, // IN ULONG Flags,
  1095. sizeof(PPPOE_PACKET), // IN ULONG Size,
  1096. MTAG_PPPOEPACKET, // IN ULONG Tag,
  1097. 0 // IN USHORT Depth
  1098. );
  1099. TRACE( TL_N, TM_Pk, ("-PacketPoolAlloc") );
  1100. }
  1101. VOID
  1102. PacketPoolFree()
  1103. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1104. Functional Description:
  1105. This function wraps the clean up of buffers and packet pools.
  1106. It is called from PacketPoolUninit() when gl_ulNumPackets reaches 0.
  1107. Parameters:
  1108. None
  1109. Return Values:
  1110. None
  1111. ---------------------------------------------------------------------------*/
  1112. {
  1113. TRACE( TL_N, TM_Pk, ("+PacketPoolFree") );
  1114. FreeBufferPool( &gl_poolBuffers );
  1115. FreePacketPool( &gl_poolPackets );
  1116. NdisFreeBufferPool( &gl_hNdisBufferPool );
  1117. NdisDeleteNPagedLookasideList( &gl_llistPppoePackets );
  1118. TRACE( TL_N, TM_Pk, ("-PacketPoolFree") );
  1119. }
  1120. PPPOE_PACKET*
  1121. PacketAlloc()
  1122. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1123. Functional Description:
  1124. This function allocates a PPPoE packet context, but it does not create
  1125. the packet and buffer descriptors.
  1126. Parameters:
  1127. None
  1128. Return Values:
  1129. NULL or a pointer to a new PPPoE packet context.
  1130. ---------------------------------------------------------------------------*/
  1131. {
  1132. PPPOE_PACKET* pPacket = NULL;
  1133. TRACE( TL_V, TM_Pk, ("+PacketAlloc") );
  1134. do
  1135. {
  1136. //
  1137. // Allocate a PppoePacket struct from the lookaside list
  1138. //
  1139. pPacket = (PPPOE_PACKET*) NdisAllocateFromNPagedLookasideList( &gl_llistPppoePackets );
  1140. if ( pPacket == NULL )
  1141. break;
  1142. NdisAcquireSpinLock( &gl_lockPools );
  1143. gl_ulNumPackets++;
  1144. NdisReleaseSpinLock( &gl_lockPools );
  1145. //
  1146. // Initialize the contents of the PppoePacket that will be returned
  1147. //
  1148. NdisZeroMemory( pPacket, sizeof( PPPOE_PACKET ) );
  1149. InitializeListHead( &pPacket->linkPackets );
  1150. ReferencePacket( pPacket );
  1151. } while ( FALSE );
  1152. TRACE( TL_V, TM_Pk, ("-PacketAlloc=$%x",pPacket) );
  1153. return pPacket;
  1154. }
  1155. VOID
  1156. PacketFree(
  1157. IN PPPOE_PACKET* pPacket
  1158. )
  1159. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1160. Functional Description:
  1161. This function is called to free a packet, but the effect is just decrementing
  1162. the ref count on the object.
  1163. Parameters:
  1164. pPacket _ A pointer to the packet to be freed.
  1165. Return Values:
  1166. None
  1167. ---------------------------------------------------------------------------*/
  1168. {
  1169. TRACE( TL_V, TM_Pk, ("+PacketFree") );
  1170. ASSERT( pPacket != NULL );
  1171. DereferencePacket( pPacket );
  1172. TRACE( TL_V, TM_Pk, ("-PacketFree") );
  1173. }
  1174. NDIS_STATUS
  1175. PacketInsertTag(
  1176. IN PPPOE_PACKET* pPacket,
  1177. IN PACKET_TAGS tagType,
  1178. IN USHORT tagLength,
  1179. IN CHAR* tagValue,
  1180. OUT CHAR** pNewTagValue
  1181. )
  1182. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1183. Functional Description:
  1184. This function is used to insert additional tags into a PPPoE packet.
  1185. Parameters:
  1186. pPacket _ pPacket must be pointing to a packet that was processed using
  1187. one of the PacketInitialize*ToSend() functions.
  1188. Return Values:
  1189. NDIS_STATUS_SUCCESS
  1190. NDIS_STATUS_INVALID_PACKET
  1191. ---------------------------------------------------------------------------*/
  1192. {
  1193. CHAR *pBuf = NULL;
  1194. USHORT usMaxLength = PACKET_GEN_MAX_LENGTH;
  1195. ASSERT( pPacket != NULL );
  1196. TRACE( TL_V, TM_Pk, ("+PacketInsertTag") );
  1197. //
  1198. // Check for length restrictions
  1199. //
  1200. if ( PacketGetCode( pPacket ) == (USHORT) PACKET_CODE_PADI )
  1201. usMaxLength = PACKET_PADI_MAX_LENGTH;
  1202. if ( PacketGetLength( pPacket ) + PPPOE_TAG_HEADER_LENGTH + tagLength > usMaxLength )
  1203. {
  1204. TRACE( TL_A, TM_Pk, ("PacketInsertTag: Can not insert tag, exceeding max packet length") );
  1205. TRACE( TL_V, TM_Pk, ("-PacketInsertTag") );
  1206. return NDIS_STATUS_INVALID_PACKET;
  1207. }
  1208. //
  1209. // Find the end of the payload
  1210. //
  1211. pBuf = pPacket->pPayload + PacketGetLength( pPacket );
  1212. //
  1213. // Insert the length - type - value triplet into the packet
  1214. //
  1215. *((USHORT UNALIGNED *) pBuf) = htons( tagType );
  1216. ((USHORT*) pBuf)++;
  1217. *((USHORT UNALIGNED *) pBuf) = htons( tagLength );
  1218. ((USHORT*) pBuf)++;
  1219. if ( tagLength > 0)
  1220. NdisMoveMemory( pBuf, tagValue, tagLength );
  1221. if ( pNewTagValue )
  1222. {
  1223. *pNewTagValue = pBuf;
  1224. }
  1225. //
  1226. // Update the Length field
  1227. //
  1228. PacketSetLength( pPacket, ( PacketGetLength( pPacket ) + PPPOE_TAG_HEADER_LENGTH + tagLength ) );
  1229. //
  1230. // Adjust payload buffer length
  1231. //
  1232. NdisAdjustBufferLength( pPacket->pNdisBuffer,
  1233. (UINT) PacketGetLength( pPacket ) + PPPOE_PACKET_HEADER_LENGTH );
  1234. TRACE( TL_V, TM_Pk, ("-PacketInsertTag") );
  1235. return NDIS_STATUS_SUCCESS;
  1236. }
  1237. NDIS_STATUS
  1238. PacketInitializePADIToSend(
  1239. OUT PPPOE_PACKET** ppPacket,
  1240. IN USHORT tagServiceNameLength,
  1241. IN CHAR* tagServiceNameValue,
  1242. IN USHORT tagHostUniqueLength,
  1243. IN CHAR* tagHostUniqueValue
  1244. )
  1245. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1246. Functional Description:
  1247. This function is used to create a PADI packet to send.
  1248. MANDATORY TAGS:
  1249. ===============
  1250. tagServiceName:
  1251. tagServiceNameLength MUST be non-zero
  1252. tagServiceNameValue MUST be non-NULL
  1253. OPTIONAL TAGS:
  1254. ==============
  1255. tagHostUnique:
  1256. tagHostUniqueLength can be zero
  1257. tagHostUniqueValue can be NULL
  1258. Parameters:
  1259. ppPacket _ A pointer to a PPPoE packet context pointer.
  1260. tagServiceNameLength _ Length of tagServiceNameValue blob.
  1261. tagServiceNameValue _ A blob that holds a UTF-8 service name string.
  1262. tagHostUniqueLength _ Length of tagHostUniqueValue blob.
  1263. tagHostUniqueValue _ A blob that contains a unique value to identify a packet.
  1264. Return Values:
  1265. NDIS_STATUS_SUCCESS
  1266. NDIS_STATUS_INVALID_PACKET
  1267. NDIS_STATUS_RESOURCES
  1268. ---------------------------------------------------------------------------*/
  1269. {
  1270. PPPOE_PACKET* pPacket = NULL;
  1271. USHORT usLength = 0;
  1272. NDIS_STATUS status;
  1273. TRACE( TL_N, TM_Pk, ("+PacketInitializePADIToSend") );
  1274. ASSERT( ppPacket != NULL );
  1275. //
  1276. // Check if we are safe with length restrictions
  1277. //
  1278. usLength = tagServiceNameLength +
  1279. PPPOE_TAG_HEADER_LENGTH +
  1280. tagHostUniqueLength +
  1281. ( (tagHostUniqueLength == 0) ? 0 : PPPOE_TAG_HEADER_LENGTH ) ;
  1282. if ( usLength > PACKET_PADI_MAX_LENGTH )
  1283. {
  1284. TRACE( TL_A, TM_Pk, ("PacketInitializePADIToSend: Can not init PADI to send, exceeding max length") );
  1285. TRACE( TL_N, TM_Pk, ("-PacketInitializePADIToSend=$%x",NDIS_STATUS_INVALID_PACKET) );
  1286. return NDIS_STATUS_INVALID_PACKET;
  1287. }
  1288. pPacket = PacketCreateSimple();
  1289. if ( pPacket == NULL )
  1290. {
  1291. TRACE( TL_A, TM_Pk, ("PacketInitializePADIToSend: Can not init PADI to send, resources unavailable") );
  1292. TRACE( TL_N, TM_Pk, ("-PacketInitializePADIToSend=$%x",NDIS_STATUS_RESOURCES) );
  1293. return NDIS_STATUS_RESOURCES;
  1294. }
  1295. //
  1296. // General initialization that applies to all packet codes
  1297. //
  1298. InitializeListHead( &pPacket->linkPackets );
  1299. PacketSetDestAddr( pPacket, EthernetBroadcastAddress );
  1300. PacketSetEtherType( pPacket, PACKET_ETHERTYPE_DISCOVERY );
  1301. PacketSetVersion( pPacket, PACKET_VERSION );
  1302. PacketSetType( pPacket, PACKET_TYPE );
  1303. PacketSetCode( pPacket, PACKET_CODE_PADI );
  1304. PacketSetSessionId( pPacket, PACKET_NULL_SESSION );
  1305. PacketSetLength( pPacket, 0 );
  1306. pPacket->tagServiceNameLength = tagServiceNameLength;
  1307. pPacket->tagServiceNameValue = tagServiceNameValue;
  1308. pPacket->tagHostUniqueLength = tagHostUniqueLength;
  1309. pPacket->tagHostUniqueValue = tagHostUniqueValue;
  1310. status = PreparePacketForWire( pPacket );
  1311. if ( status != NDIS_STATUS_SUCCESS )
  1312. {
  1313. TRACE( TL_A, TM_Pk, ("PacketInitializePADIToSend: PreparePacketForWire() failed:%x",status) );
  1314. PacketFree( pPacket );
  1315. pPacket = NULL;
  1316. }
  1317. *ppPacket = pPacket;
  1318. TRACE( TL_N, TM_Pk, ("-PacketInitializePADIToSend=$%x",status) );
  1319. return status;
  1320. }
  1321. NDIS_STATUS
  1322. PacketInitializePADOToSend(
  1323. IN PPPOE_PACKET* pPADI,
  1324. OUT PPPOE_PACKET** ppPacket,
  1325. IN CHAR* pSrcAddr,
  1326. IN USHORT tagServiceNameLength,
  1327. IN CHAR* tagServiceNameValue,
  1328. IN USHORT tagACNameLength,
  1329. IN CHAR* tagACNameValue,
  1330. IN BOOLEAN fInsertACCookieTag
  1331. )
  1332. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1333. Functional Description:
  1334. This function is used to create a PADO packet to send as a reply to a received
  1335. PADI packet.
  1336. Note that a PADI packet does not contain the source address information as PADI
  1337. is a broadcast packet.
  1338. MANDATORY TAGS:
  1339. ===============
  1340. tagServiceName: ()
  1341. tagServiceNameLength MUST be non-zero
  1342. tagServiceNameValue MUST be non-NULL
  1343. tagACName:
  1344. tagACNameNameLength MUST be non-zero
  1345. tagACNameNameValue MUST be non-NULL
  1346. tagACCookie: (This is optional for RFC)
  1347. tagACCookieLength can be zero
  1348. tagACCookieValue can be NULL
  1349. OPTIONAL TAGS:
  1350. ==============
  1351. tagHostUnique: (Obtained from PADI packet)
  1352. tagHostUniqueLength can be zero
  1353. tagHostUniqueValue can be NULL
  1354. tagRelaySessionId: (Obtained from PADI packet)
  1355. tagRelaySessionIdLength can be zero
  1356. tagRelaySessionIdValue can be zero
  1357. Parameters:
  1358. pPADI _ Pointer to a PPPoE packet context holding a PADI packet.
  1359. ppPacket _ A pointer to a PPPoE packet context pointer.
  1360. pSrcAddr _ Source address for the PADO packet since we can not
  1361. get it from the PADI packet.
  1362. tagServiceNameLength _ Length of tagServiceNameValue blob.
  1363. tagServiceNameValue _ A blob that holds a UTF-8 Service name string.
  1364. tagACNameLength _ Length of tagACNameValue blob.
  1365. tagACNameValue _ A blob that holds a UTF-8 AC name string.
  1366. fInsertACCookieTag _ Indicates we we should also insert an AC Cookie
  1367. tag into the PADO packet.
  1368. Return Values:
  1369. NDIS_STATUS_SUCCESS
  1370. NDIS_STATUS_INVALID_PACKET
  1371. NDIS_STATUS_RESOURCES
  1372. ---------------------------------------------------------------------------*/
  1373. {
  1374. PPPOE_PACKET* pPacket = NULL;
  1375. USHORT usLength = 0;
  1376. NDIS_STATUS status;
  1377. CHAR tagACCookieValue[PPPOE_AC_COOKIE_TAG_LENGTH];
  1378. BOOLEAN fCopyServiceNameTag = FALSE;
  1379. TRACE( TL_N, TM_Pk, ("+PacketInitializePADOToSend") );
  1380. ASSERT( pPADI != NULL );
  1381. ASSERT( ppPacket != NULL );
  1382. //
  1383. // Check if we are safe with length restrictions
  1384. //
  1385. usLength = tagServiceNameLength +
  1386. PPPOE_TAG_HEADER_LENGTH +
  1387. pPADI->tagHostUniqueLength +
  1388. ( (pPADI->tagHostUniqueLength == 0) ? 0 : PPPOE_TAG_HEADER_LENGTH ) +
  1389. pPADI->tagRelaySessionIdLength +
  1390. ( (pPADI->tagRelaySessionIdLength == 0) ? 0 : PPPOE_TAG_HEADER_LENGTH ) +
  1391. tagACNameLength +
  1392. PPPOE_TAG_HEADER_LENGTH +
  1393. ( fInsertACCookieTag ? ( PPPOE_AC_COOKIE_TAG_LENGTH + PPPOE_TAG_HEADER_LENGTH ) : 0 );
  1394. if ( usLength > PACKET_GEN_MAX_LENGTH )
  1395. {
  1396. TRACE( TL_A, TM_Pk, ("PacketInitializePADOToSend: Can not init PADO to send, exceeding max length") );
  1397. TRACE( TL_N, TM_Pk, ("-PacketInitializePADOToSend=$%x",NDIS_STATUS_INVALID_PACKET) );
  1398. return NDIS_STATUS_INVALID_PACKET;
  1399. }
  1400. pPacket = PacketCreateSimple();
  1401. if ( pPacket == NULL )
  1402. {
  1403. TRACE( TL_A, TM_Pk, ("PacketInitializePADOToSend: Can not init PADO to send, resources unavailable") );
  1404. TRACE( TL_N, TM_Pk, ("-PacketInitializePADOToSend=$%x",NDIS_STATUS_RESOURCES) );
  1405. return NDIS_STATUS_RESOURCES;
  1406. }
  1407. //
  1408. // General initialization that applies to all packet codes
  1409. //
  1410. InitializeListHead( &pPacket->linkPackets );
  1411. PacketSetDestAddr( pPacket, PacketGetSrcAddr( pPADI ) );
  1412. PacketSetSrcAddr( pPacket, pSrcAddr );
  1413. PacketSetEtherType( pPacket, PACKET_ETHERTYPE_DISCOVERY );
  1414. PacketSetVersion( pPacket, PACKET_VERSION );
  1415. PacketSetType( pPacket, PACKET_TYPE );
  1416. PacketSetCode( pPacket, PACKET_CODE_PADO );
  1417. PacketSetSessionId( pPacket, PACKET_NULL_SESSION );
  1418. PacketSetLength( pPacket, 0 );
  1419. pPacket->tagServiceNameLength = tagServiceNameLength;
  1420. pPacket->tagServiceNameValue = tagServiceNameValue;
  1421. pPacket->tagHostUniqueLength = pPADI->tagHostUniqueLength;
  1422. pPacket->tagHostUniqueValue = pPADI->tagHostUniqueValue;
  1423. pPacket->tagRelaySessionIdLength = pPADI->tagRelaySessionIdLength;
  1424. pPacket->tagRelaySessionIdValue = pPADI->tagRelaySessionIdValue;
  1425. pPacket->tagACNameLength = tagACNameLength;
  1426. pPacket->tagACNameValue = tagACNameValue;
  1427. if ( fInsertACCookieTag )
  1428. {
  1429. PacketGenerateACCookieTag( pPADI, tagACCookieValue );
  1430. pPacket->tagACCookieLength = PPPOE_AC_COOKIE_TAG_LENGTH;
  1431. pPacket->tagACCookieValue = tagACCookieValue;
  1432. }
  1433. status = PreparePacketForWire( pPacket );
  1434. if ( status != NDIS_STATUS_SUCCESS )
  1435. {
  1436. TRACE( TL_A, TM_Pk, ("PacketInitializePADOToSend: PreparePacketForWire() failed:%x",status) );
  1437. PacketFree( pPacket );
  1438. pPacket = NULL;
  1439. }
  1440. *ppPacket = pPacket;
  1441. TRACE( TL_N, TM_Pk, ("-PacketInitializePADOToSend=$%x",status) );
  1442. return status;
  1443. }
  1444. NDIS_STATUS
  1445. PacketInitializePADRToSend(
  1446. IN PPPOE_PACKET* pPADO,
  1447. OUT PPPOE_PACKET** ppPacket,
  1448. IN USHORT tagServiceNameLength,
  1449. IN CHAR* tagServiceNameValue,
  1450. IN USHORT tagHostUniqueLength,
  1451. IN CHAR* tagHostUniqueValue
  1452. )
  1453. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1454. Functional Description:
  1455. This function is used to create a PADR packet to send as a reply to a received
  1456. PADO packet.
  1457. MANDATORY TAGS:
  1458. ===============
  1459. tagServiceName:
  1460. tagServiceNameLength MUST be non-zero
  1461. tagServiceNameValue MUST be non-NULL
  1462. OPTIONAL TAGS:
  1463. ==============
  1464. tagHostUnique:
  1465. tagHostUniqueLength can be zero
  1466. tagHostUniqueValue can be NULL
  1467. tagACCookie: (Obtained from PADI packet)
  1468. tagHostUniqueLength can be zero
  1469. tagHostUniqueValue can be NULL
  1470. tagRelaySessionId: (Obtained from PADI packet)
  1471. tagRelaySessionIdLength can be zero
  1472. tagRelaySessionIdValue can be NULL
  1473. Parameters:
  1474. pPADO _ Pointer to a PPPoE packet context holding a PADO packet.
  1475. ppPacket _ A pointer to a PPPoE packet context pointer.
  1476. tagServiceNameLength _ Length of tagServiceNameValue blob.
  1477. tagServiceNameValue _ A blob that holds a UTF-8 service name string.
  1478. tagHostUniqueLength _ Length of tagHostUniqueValue blob.
  1479. tagHostUniqueValue _ A blob that contains a unique value to identify a packet.
  1480. Return Values:
  1481. NDIS_STATUS_SUCCESS
  1482. NDIS_STATUS_INVALID_PACKET
  1483. NDIS_STATUS_RESOURCES
  1484. ---------------------------------------------------------------------------*/
  1485. {
  1486. PPPOE_PACKET* pPacket = NULL;
  1487. USHORT usLength = 0;
  1488. NDIS_STATUS status;
  1489. TRACE( TL_N, TM_Pk, ("+PacketInitializePADRToSend") );
  1490. ASSERT( pPADO != NULL );
  1491. ASSERT( ppPacket != NULL );
  1492. //
  1493. // Check if we are safe with length restrictions
  1494. //
  1495. usLength = tagServiceNameLength +
  1496. PPPOE_TAG_HEADER_LENGTH +
  1497. tagHostUniqueLength +
  1498. ( (tagHostUniqueLength == 0) ? 0 : PPPOE_TAG_HEADER_LENGTH ) +
  1499. pPADO->tagRelaySessionIdLength +
  1500. ( (pPADO->tagRelaySessionIdLength == 0) ? 0 : PPPOE_TAG_HEADER_LENGTH ) +
  1501. pPADO->tagACCookieLength +
  1502. ( (pPADO->tagACCookieLength == 0) ? 0 : PPPOE_TAG_HEADER_LENGTH ) ;
  1503. if ( usLength > PACKET_GEN_MAX_LENGTH )
  1504. {
  1505. TRACE( TL_A, TM_Pk, ("PacketInitializePADRToSend: Can not init PADR to send, exceeding max length") );
  1506. TRACE( TL_N, TM_Pk, ("-PacketInitializePADRToSend=$%x",NDIS_STATUS_INVALID_PACKET) );
  1507. return NDIS_STATUS_INVALID_PACKET;
  1508. }
  1509. pPacket = PacketCreateSimple();
  1510. if ( pPacket == NULL )
  1511. {
  1512. TRACE( TL_A, TM_Pk, ("PacketInitializePADRToSend: Can not init PADR to send, resources unavailable") );
  1513. TRACE( TL_N, TM_Pk, ("-PacketInitializePADRToSend=$%x",NDIS_STATUS_RESOURCES) );
  1514. return NDIS_STATUS_RESOURCES;
  1515. }
  1516. //
  1517. // General initialization that applies to all packet codes
  1518. //
  1519. InitializeListHead( &pPacket->linkPackets );
  1520. PacketSetSrcAddr( pPacket, PacketGetDestAddr( pPADO ) );
  1521. PacketSetDestAddr( pPacket, PacketGetSrcAddr( pPADO ) );
  1522. PacketSetEtherType( pPacket, PACKET_ETHERTYPE_DISCOVERY );
  1523. PacketSetVersion( pPacket, PACKET_VERSION );
  1524. PacketSetType( pPacket, PACKET_TYPE );
  1525. PacketSetCode( pPacket, PACKET_CODE_PADR );
  1526. PacketSetSessionId( pPacket, PACKET_NULL_SESSION );
  1527. PacketSetLength( pPacket, 0 );
  1528. pPacket->tagServiceNameLength = tagServiceNameLength;
  1529. pPacket->tagServiceNameValue = tagServiceNameValue;
  1530. pPacket->tagHostUniqueLength = tagHostUniqueLength;
  1531. pPacket->tagHostUniqueValue = tagHostUniqueValue;
  1532. pPacket->tagRelaySessionIdLength = pPADO->tagRelaySessionIdLength;
  1533. pPacket->tagRelaySessionIdValue = pPADO->tagRelaySessionIdValue;
  1534. pPacket->tagACCookieLength = pPADO->tagACCookieLength;
  1535. pPacket->tagACCookieValue = pPADO->tagACCookieValue;
  1536. status = PreparePacketForWire( pPacket );
  1537. if ( status != NDIS_STATUS_SUCCESS )
  1538. {
  1539. TRACE( TL_A, TM_Pk, ("PacketInitializePADRToSend: PreparePacketForWire() failed:%x",status) );
  1540. PacketFree( pPacket );
  1541. pPacket = NULL;
  1542. }
  1543. *ppPacket = pPacket;
  1544. TRACE( TL_N, TM_Pk, ("-PacketInitializePADRToSend=$%x",status) );
  1545. return status;
  1546. }
  1547. //
  1548. // This function is used to prepare a PADS packet for a received PADR packet.
  1549. //
  1550. // The PADR packet must be processed using PREPARE_PACKET_FROM_WIRE() macro
  1551. // before feeding into this function.
  1552. //
  1553. // The PADS packet should just be a packet without and associated VCs or linked lists.
  1554. //
  1555. // If you want to insert other tags to a PADI, PADO, or PADS packet, use specific
  1556. // PacketInsertTag() function after calling this function.
  1557. //
  1558. // MANDATORY TAGS:
  1559. // ===============
  1560. // tagServiceName:
  1561. // tagServiceNameLength MUST be non-zero
  1562. // tagServiceNameValue MUST be non-NULL
  1563. //
  1564. // OPTIONAL TAGS:
  1565. // ==============
  1566. // tagHostUnique:
  1567. // tagHostUniqueLength can be zero
  1568. // tagHostUniqueValue can be zero
  1569. //
  1570. // tagRelaySessionId: (Obtained from PADI packet)
  1571. // tagRelaySessionIdLength can be zero
  1572. // tagRelaySessionIdValue can be zero
  1573. //
  1574. NDIS_STATUS
  1575. PacketInitializePADSToSend(
  1576. IN PPPOE_PACKET* pPADR,
  1577. OUT PPPOE_PACKET** ppPacket,
  1578. IN USHORT usSessionId
  1579. )
  1580. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1581. Functional Description:
  1582. This function is used to create a PADR packet to send as a reply to a received
  1583. PADO packet.
  1584. MANDATORY TAGS:
  1585. ===============
  1586. tagServiceName: (Obtained from PADR packet)
  1587. tagServiceNameLength MUST be non-zero
  1588. tagServiceNameValue MUST be non-NULL
  1589. OPTIONAL TAGS:
  1590. ==============
  1591. tagHostUnique: (Obtained from PADR packet)
  1592. tagHostUniqueLength can be zero
  1593. tagHostUniqueValue can be NULL
  1594. tagRelaySessionId: (Obtained from PADR packet)
  1595. tagRelaySessionIdLength can be zero
  1596. tagRelaySessionIdValue can be NULL
  1597. Parameters:
  1598. pPADR _ Pointer to a PPPoE packet context holding a PADR packet.
  1599. ppPacket _ A pointer to a PPPoE packet context pointer.
  1600. usSessionId _ Session id assigned to this session
  1601. Return Values:
  1602. NDIS_STATUS_SUCCESS
  1603. NDIS_STATUS_INVALID_PACKET
  1604. NDIS_STATUS_RESOURCES
  1605. ---------------------------------------------------------------------------*/
  1606. {
  1607. PPPOE_PACKET* pPacket = NULL;
  1608. USHORT usLength;
  1609. NDIS_STATUS status;
  1610. TRACE( TL_N, TM_Pk, ("+PacketInitializePADSToSend") );
  1611. ASSERT( pPADR != NULL );
  1612. ASSERT( ppPacket != NULL );
  1613. //
  1614. // Check if we are safe with length restrictions
  1615. //
  1616. usLength = pPADR->tagServiceNameLength +
  1617. PPPOE_TAG_HEADER_LENGTH +
  1618. pPADR->tagHostUniqueLength +
  1619. ( (pPADR->tagHostUniqueLength == 0) ? 0 : PPPOE_TAG_HEADER_LENGTH )+
  1620. pPADR->tagRelaySessionIdLength +
  1621. ( (pPADR->tagRelaySessionIdLength == 0) ? 0 : PPPOE_TAG_HEADER_LENGTH );
  1622. if ( usLength > PACKET_GEN_MAX_LENGTH )
  1623. {
  1624. TRACE( TL_A, TM_Pk, ("PacketInitializePADSToSend: Can not init PADS to send, exceeding max length") );
  1625. TRACE( TL_N, TM_Pk, ("-PacketInitializePADSToSend=$%x",NDIS_STATUS_INVALID_PACKET) );
  1626. return NDIS_STATUS_INVALID_PACKET;
  1627. }
  1628. pPacket = PacketCreateSimple();
  1629. if ( pPacket == NULL )
  1630. {
  1631. TRACE( TL_A, TM_Pk, ("PacketInitializePADSToSend: Can not init PADS to send, resources unavailable") );
  1632. TRACE( TL_N, TM_Pk, ("-PacketInitializePADSToSend=$%x",NDIS_STATUS_RESOURCES) );
  1633. return NDIS_STATUS_RESOURCES;
  1634. }
  1635. //
  1636. // General initialization that applies to all packet codes
  1637. //
  1638. InitializeListHead( &pPacket->linkPackets );
  1639. PacketSetSrcAddr( pPacket, PacketGetDestAddr( pPADR ) );
  1640. PacketSetDestAddr( pPacket, PacketGetSrcAddr( pPADR ) );
  1641. PacketSetEtherType( pPacket, PACKET_ETHERTYPE_DISCOVERY );
  1642. PacketSetVersion( pPacket, PACKET_VERSION );
  1643. PacketSetType( pPacket, PACKET_TYPE );
  1644. PacketSetCode( pPacket, PACKET_CODE_PADS );
  1645. PacketSetSessionId( pPacket, usSessionId );
  1646. PacketSetLength( pPacket, 0 );
  1647. pPacket->tagServiceNameLength = pPADR->tagServiceNameLength;
  1648. pPacket->tagServiceNameValue = pPADR->tagServiceNameValue;
  1649. pPacket->tagHostUniqueLength = pPADR->tagHostUniqueLength;
  1650. pPacket->tagHostUniqueValue = pPADR->tagHostUniqueValue;
  1651. pPacket->tagRelaySessionIdLength = pPADR->tagRelaySessionIdLength;
  1652. pPacket->tagRelaySessionIdValue = pPADR->tagRelaySessionIdValue;
  1653. status = PreparePacketForWire( pPacket );
  1654. if ( status != NDIS_STATUS_SUCCESS )
  1655. {
  1656. TRACE( TL_A, TM_Pk, ("PacketInitializePADSToSend: PreparePacketForWire() failed:%x",status) );
  1657. PacketFree( pPacket );
  1658. pPacket = NULL;
  1659. }
  1660. *ppPacket = pPacket;
  1661. TRACE( TL_N, TM_Pk, ("-PacketInitializePADSToSend=$%x",status) );
  1662. return status;
  1663. }
  1664. NDIS_STATUS
  1665. PacketInitializePADTToSend(
  1666. OUT PPPOE_PACKET** ppPacket,
  1667. IN CHAR* pSrcAddr,
  1668. IN CHAR* pDestAddr,
  1669. IN USHORT usSessionId
  1670. )
  1671. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1672. Functional Description:
  1673. This function is used to create a PADT packet to send to disconnect a session.
  1674. If you want to send additional tags (like error tags), use the PacketInsertTag()
  1675. function.
  1676. MANDATORY TAGS:
  1677. ===============
  1678. None
  1679. OPTIONAL TAGS:
  1680. ==============
  1681. None
  1682. Parameters:
  1683. ppPacket _ A pointer to a PPPoE packet context pointer.
  1684. pSrcAddr _ Buffer pointing to the source MAC addr of length 6
  1685. pDestAddr _ Buffer pointing to the dest MAC addr of length 6
  1686. usSessionId _ Session id assigned to this session
  1687. Return Values:
  1688. NDIS_STATUS_SUCCESS
  1689. NDIS_STATUS_INVALID_PACKET
  1690. NDIS_STATUS_RESOURCES
  1691. ---------------------------------------------------------------------------*/
  1692. {
  1693. PPPOE_PACKET* pPacket = NULL;
  1694. USHORT usLength;
  1695. NDIS_STATUS status;
  1696. TRACE( TL_N, TM_Pk, ("+PacketInitializePADTToSend") );
  1697. ASSERT( ppPacket != NULL );
  1698. ASSERT( pDestAddr != NULL );
  1699. pPacket = PacketCreateSimple();
  1700. if ( pPacket == NULL )
  1701. {
  1702. TRACE( TL_A, TM_Pk, ("PacketInitializePADTToSend: Can not init PADT to send, resources unavailable") );
  1703. TRACE( TL_N, TM_Pk, ("-PacketInitializePADTToSend=$%x",NDIS_STATUS_RESOURCES) );
  1704. return NDIS_STATUS_RESOURCES;
  1705. }
  1706. //
  1707. // General initialization that applies to all packet codes
  1708. //
  1709. InitializeListHead( &pPacket->linkPackets );
  1710. PacketSetSrcAddr( pPacket, pSrcAddr );
  1711. PacketSetDestAddr( pPacket, pDestAddr );
  1712. PacketSetEtherType( pPacket, PACKET_ETHERTYPE_DISCOVERY );
  1713. PacketSetVersion( pPacket, PACKET_VERSION );
  1714. PacketSetType( pPacket, PACKET_TYPE );
  1715. PacketSetCode( pPacket, PACKET_CODE_PADT );
  1716. PacketSetSessionId( pPacket, usSessionId );
  1717. PacketSetLength( pPacket, 0 );
  1718. status = PreparePacketForWire( pPacket );
  1719. if ( status != NDIS_STATUS_SUCCESS )
  1720. {
  1721. TRACE( TL_A, TM_Pk, ("PacketInitializePADTToSend: PreparePacketForWire() failed:%x",status) );
  1722. PacketFree( pPacket );
  1723. pPacket = NULL;
  1724. }
  1725. *ppPacket = pPacket;
  1726. TRACE( TL_N, TM_Pk, ("-PacketInitializePADTToSend=$%x",status) );
  1727. return status;
  1728. }
  1729. NDIS_STATUS
  1730. PacketInitializePAYLOADToSend(
  1731. OUT PPPOE_PACKET** ppPacket,
  1732. IN CHAR* pSrcAddr,
  1733. IN CHAR* pDestAddr,
  1734. IN USHORT usSessionId,
  1735. IN NDIS_WAN_PACKET* pWanPacket,
  1736. IN PADAPTER MiniportAdapter
  1737. )
  1738. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1739. Functional Description:
  1740. This function is used to create a PAYLOAD packet to send.
  1741. If you want to send additional tags (like error tags), use the PacketInsertTag()
  1742. function.
  1743. MANDATORY TAGS:
  1744. ===============
  1745. None
  1746. OPTIONAL TAGS:
  1747. ==============
  1748. None
  1749. Parameters:
  1750. ppPacket _ A pointer to a PPPoE packet context pointer.
  1751. pSrcAddr _ Buffer pointing to the source MAC addr of length 6
  1752. pDestAddr _ Buffer pointing to the dest MAC addr of length 6
  1753. usSessionId _ Session id assigned to this session
  1754. pWanPacket _ Pointer to an NDISWAN packet
  1755. MiniportAdapter _ This is the pointer to the miniport adapter.
  1756. It is used to indicate the completion of async sends back
  1757. to Ndiswan.
  1758. Return Values:
  1759. NDIS_STATUS_SUCCESS
  1760. NDIS_STATUS_INVALID_PACKET
  1761. NDIS_STATUS_RESOURCES
  1762. ---------------------------------------------------------------------------*/
  1763. {
  1764. NDIS_STATUS status = NDIS_STATUS_SUCCESS;
  1765. PPPOE_PACKET* pPacket = NULL;
  1766. USHORT usLength = 0;
  1767. UINT Length;
  1768. TRACE( TL_V, TM_Pk, ("+PacketInitializePAYLOADToSend") );
  1769. ASSERT( ppPacket != NULL );
  1770. ASSERT( pDestAddr != NULL );
  1771. ASSERT( pWanPacket != NULL );
  1772. //
  1773. // Validate NDISWAN packet
  1774. //
  1775. if ( pWanPacket->CurrentLength > PACKET_GEN_MAX_LENGTH )
  1776. {
  1777. TRACE( TL_A, TM_Pk, ("PacketInitializePAYLOADToSend: Can not init PAYLOAD to send, exceeding max length") );
  1778. TRACE( TL_V, TM_Pk, ("-PacketInitializePAYLOADToSend=$%x",NDIS_STATUS_INVALID_PACKET) );
  1779. return NDIS_STATUS_INVALID_PACKET;
  1780. }
  1781. if ( ( pWanPacket->CurrentBuffer - pWanPacket->StartBuffer ) < PPPOE_PACKET_HEADER_LENGTH )
  1782. {
  1783. TRACE( TL_A, TM_Pk, ("PacketInitializePAYLOADToSend: Can not init PAYLOAD to send, not enough front padding") );
  1784. TRACE( TL_V, TM_Pk, ("-PacketInitializePAYLOADToSend=$%x",NDIS_STATUS_INVALID_PACKET) );
  1785. return NDIS_STATUS_INVALID_PACKET;
  1786. }
  1787. //
  1788. // Allocate a packet
  1789. //
  1790. pPacket = PacketAlloc();
  1791. if ( pPacket == NULL )
  1792. {
  1793. TRACE( TL_A, TM_Pk, ("PacketInitializePAYLOADToSend: Can not init PAYLOAD to send, resources unavailable") );
  1794. TRACE( TL_V, TM_Pk, ("-PacketInitializePAYLOADToSend=$%x",NDIS_STATUS_RESOURCES) );
  1795. return NDIS_STATUS_RESOURCES;
  1796. }
  1797. //
  1798. // Allocate NdisBuffer
  1799. //
  1800. //
  1801. // NOTE : Using (pWanPacket->CurrentBuffer - PPPOE_PACKET_HEADER_LENGTH) instead of
  1802. // pWanPacket->StartBuffer directly gives us the flexibility of handling packets
  1803. // with different header padding values.
  1804. //
  1805. NdisAllocateBuffer( &status,
  1806. &pPacket->pNdisBuffer,
  1807. gl_hNdisBufferPool,
  1808. pWanPacket->CurrentBuffer - PPPOE_PACKET_HEADER_LENGTH,
  1809. (UINT) ( PPPOE_PACKET_HEADER_LENGTH + pWanPacket->CurrentLength ) );
  1810. if ( status != NDIS_STATUS_SUCCESS )
  1811. {
  1812. TRACE( TL_A, TM_Pk, ("PacketInitializePAYLOADToSend: NdisAllocateBuffer() failed") );
  1813. PacketFree( pPacket );
  1814. TRACE( TL_V, TM_Pk, ("-PacketInitializePAYLOADToSend=$%x",status) );
  1815. return status;
  1816. }
  1817. pPacket->ulFlags |= PCBF_BufferAllocatedFromNdisBufferPool;
  1818. //
  1819. // Query new buffer descriptor to get hold of the real memory pointer
  1820. //
  1821. pPacket->pHeader = NULL;
  1822. NdisQueryBufferSafe( pPacket->pNdisBuffer,
  1823. &pPacket->pHeader,
  1824. &Length,
  1825. NormalPagePriority );
  1826. if ( pPacket->pHeader == NULL )
  1827. {
  1828. TRACE( TL_A, TM_Pk, ("PacketInitializePAYLOADToSend: NdisQueryBufferSafe() failed") );
  1829. PacketFree( pPacket );
  1830. TRACE( TL_V, TM_Pk, ("-PacketInitializePAYLOADToSend=$%x",status) );
  1831. return NDIS_STATUS_RESOURCES;
  1832. }
  1833. //
  1834. // Allocate an NDIS packet from our pool
  1835. //
  1836. pPacket->pNdisPacket = GetPacketFromPool( &gl_poolPackets, &pPacket->pPacketHead );
  1837. if ( pPacket->pNdisPacket == NULL )
  1838. {
  1839. TRACE( TL_A, TM_Pk, ("PacketInitializePAYLOADToSend: GetPacketFromPool() failed") );
  1840. PacketFree( pPacket );
  1841. TRACE( TL_V, TM_Pk, ("-PacketInitializePAYLOADToSend=$%x",status) );
  1842. return NDIS_STATUS_RESOURCES;
  1843. }
  1844. pPacket->ulFlags |= PCBF_PacketAllocatedFromOurPacketPool;
  1845. //
  1846. // Chain buffer to packet
  1847. //
  1848. NdisChainBufferAtFront( pPacket->pNdisPacket, pPacket->pNdisBuffer );
  1849. pPacket->ulFlags |= PCBF_BufferChainedToPacket;
  1850. //
  1851. // Set the payload and payload length
  1852. //
  1853. pPacket->pPayload = pPacket->pHeader + PPPOE_PACKET_HEADER_LENGTH;
  1854. usLength = (USHORT) pWanPacket->CurrentLength;
  1855. //
  1856. // General initialization that applies to all packet codes
  1857. //
  1858. InitializeListHead( &pPacket->linkPackets );
  1859. PacketSetDestAddr( pPacket, pDestAddr );
  1860. PacketSetSrcAddr( pPacket, pSrcAddr );
  1861. PacketSetEtherType( pPacket, PACKET_ETHERTYPE_PAYLOAD );
  1862. PacketSetVersion( pPacket, PACKET_VERSION );
  1863. PacketSetType( pPacket, PACKET_TYPE );
  1864. PacketSetCode( pPacket, PACKET_CODE_PAYLOAD );
  1865. PacketSetSessionId( pPacket, usSessionId );
  1866. PacketSetLength( pPacket, usLength );
  1867. //
  1868. // Set the input NDIS_PACKET to the reserved area so that we can reach it
  1869. // when we have to return this packet back to the upper layer.
  1870. //
  1871. *((PPPOE_PACKET UNALIGNED**)(&pPacket->pNdisPacket->ProtocolReserved[0 * sizeof(PVOID)])) = pPacket;
  1872. *((NDIS_WAN_PACKET UNALIGNED**)(&pPacket->pNdisPacket->ProtocolReserved[1 * sizeof(PVOID)])) = pWanPacket;
  1873. *((ADAPTER UNALIGNED **)(&pPacket->pNdisPacket->ProtocolReserved[2 * sizeof(PVOID)])) = MiniportAdapter;
  1874. status = PreparePacketForWire( pPacket );
  1875. if ( status != NDIS_STATUS_SUCCESS )
  1876. {
  1877. TRACE( TL_A, TM_Pk, ("PacketInitializePAYLOADToSend: PreparePacketForWire() failed") );
  1878. PacketFree( pPacket );
  1879. TRACE( TL_V, TM_Pk, ("-PacketInitializePAYLOADToSend=$%x",status) );
  1880. return status;
  1881. }
  1882. //
  1883. // This must be done here as we do not want to call NdisMWanSendComplete() in PacketFree() if the
  1884. // PreparePacketForWire() fails.
  1885. //
  1886. pPacket->ulFlags |= PCBF_CallNdisMWanSendComplete;
  1887. MpPacketOwnedByNdiswanReceived( MiniportAdapter );
  1888. *ppPacket = pPacket;
  1889. TRACE( TL_V, TM_Pk, ("-PacketInitializePAYLOADToSend=$%x",status) );
  1890. return status;
  1891. }
  1892. NDIS_STATUS
  1893. PacketInitializeFromReceived(
  1894. IN PPPOE_PACKET* pPacket
  1895. )
  1896. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1897. Functional Description:
  1898. This function prepares a PPPoE packet by using the Ndis packet from wire.
  1899. This function will make sure that the packet is a PPPoE packet, and convert
  1900. it to a PPPoE packet context. It tries to do this as efficiently as possible
  1901. by trying to use the buffers of the received packet if possible.
  1902. It will also do all the validation in the packet to make sure it is
  1903. compliant with the RFC. However, it can not perform the checks that need data
  1904. from a sent packet. Caller must use various PacketRetrieve*() functions to
  1905. retrieve the necesarry data and use it to match and validate to a sent packet.
  1906. Parameters:
  1907. pPacket _ Pointer to a PPPoE packet context.
  1908. Return Values:
  1909. NDIS_STATUS_SUCCESS
  1910. NDIS_STATUS_RESOURCES
  1911. NDIS_STATUS_INVALID_PACKET
  1912. ---------------------------------------------------------------------------*/
  1913. {
  1914. NDIS_STATUS status;
  1915. ASSERT( pPacket != NULL );
  1916. TRACE( TL_V, TM_Pk, ("+PacketInitializeFromReceived") );
  1917. if ( !PacketIsPPPoE( pPacket ) )
  1918. {
  1919. status = NDIS_STATUS_INVALID_PACKET;
  1920. TRACE( TL_V, TM_Pk, ("-PacketInitializeFromReceived=$%x",status) );
  1921. return status;
  1922. }
  1923. do
  1924. {
  1925. status = NDIS_STATUS_INVALID_PACKET;
  1926. //
  1927. // Validate the tag lenghts inside the packet so that we do not
  1928. // step outside buffer boundaries further processing the packet.
  1929. // Do this only if the packet is not a payload packet!
  1930. //
  1931. if ( PacketGetCode( pPacket ) != PACKET_CODE_PAYLOAD )
  1932. {
  1933. CHAR* pBufStart;
  1934. CHAR* pBufEnd;
  1935. USHORT tagLength;
  1936. pBufStart = pPacket->pPayload;
  1937. pBufEnd = pPacket->pPayload + PacketGetLength( pPacket );
  1938. while ( pBufStart + PPPOE_TAG_HEADER_LENGTH <= pBufEnd )
  1939. {
  1940. //
  1941. // Skip the tag type field
  1942. //
  1943. ((USHORT*) pBufStart)++;
  1944. //
  1945. // Retrieve the tag length, and look at the next tag
  1946. //
  1947. tagLength = ntohs( *((USHORT UNALIGNED *) pBufStart) ) ;
  1948. ((USHORT*) pBufStart)++;
  1949. pBufStart += tagLength;
  1950. }
  1951. if ( pBufStart != pBufEnd )
  1952. break;
  1953. }
  1954. status = NDIS_STATUS_SUCCESS;
  1955. } while ( FALSE );
  1956. if ( status != NDIS_STATUS_SUCCESS )
  1957. {
  1958. TRACE( TL_A, TM_Pk, ("PacketInitializeFromReceived: Corrupt packet - invalid tags") );
  1959. TRACE( TL_V, TM_Pk, ("-PacketInitializeFromReceived=$%x",status) );
  1960. return status;
  1961. }
  1962. switch ( PacketGetCode( pPacket ) )
  1963. {
  1964. USHORT tagLength;
  1965. CHAR* tagValue;
  1966. status = NDIS_STATUS_INVALID_PACKET;
  1967. case PACKET_CODE_PADI:
  1968. TRACE( TL_N, TM_Pk, ("PacketInitializeFromReceived: Processing PADI") );
  1969. //
  1970. // Make sure we have received the correct ethertype
  1971. //
  1972. if ( PacketGetEtherType( pPacket ) != PACKET_ETHERTYPE_DISCOVERY )
  1973. {
  1974. TRACE( TL_A, TM_Pk, ("PacketInitializeFromReceived: Invalid ether type") );
  1975. break;
  1976. }
  1977. //
  1978. // Make sure session id is PACKET_NULL_SESSION
  1979. //
  1980. if ( PacketGetSessionId( pPacket ) != PACKET_NULL_SESSION )
  1981. {
  1982. TRACE( TL_A, TM_Pk, ("PacketInitializeFromReceived: Invalid session id") );
  1983. break;
  1984. }
  1985. //
  1986. // Extract mandatory tags first
  1987. //
  1988. RetrieveTag( pPacket,
  1989. tagServiceName,
  1990. &tagLength,
  1991. &tagValue,
  1992. 0,
  1993. NULL,
  1994. TRUE );
  1995. if ( tagValue == NULL )
  1996. {
  1997. TRACE( TL_A, TM_Pk, ("PacketInitializeFromReceived: Service name tag not found") );
  1998. break;
  1999. }
  2000. //
  2001. // Extract optional tags
  2002. //
  2003. RetrieveTag( pPacket,
  2004. tagHostUnique,
  2005. &tagLength,
  2006. &tagValue,
  2007. 0,
  2008. NULL,
  2009. TRUE );
  2010. //
  2011. // Extract the relay session id tag if it exists
  2012. //
  2013. RetrieveTag( pPacket,
  2014. tagRelaySessionId,
  2015. &tagLength,
  2016. &tagValue,
  2017. 0,
  2018. NULL,
  2019. TRUE );
  2020. TRACE( TL_N, TM_Pk, ("PacketInitializeFromReceived: Processed PADI succesfully") );
  2021. status = NDIS_STATUS_SUCCESS;
  2022. break;
  2023. case PACKET_CODE_PADO:
  2024. TRACE( TL_N, TM_Pk, ("PacketInitializeFromReceived: Processing PADO") );
  2025. //
  2026. // Make sure we have received the correct ethertype
  2027. //
  2028. if ( PacketGetEtherType( pPacket ) != PACKET_ETHERTYPE_DISCOVERY )
  2029. {
  2030. TRACE( TL_A, TM_Pk, ("PacketInitializeFromReceived: Invalid ether type") );
  2031. break;
  2032. }
  2033. //
  2034. // Make sure session id is PACKET_NULL_SESSION
  2035. //
  2036. if ( PacketGetSessionId( pPacket ) != PACKET_NULL_SESSION )
  2037. {
  2038. TRACE( TL_A, TM_Pk, ("PacketInitializeFromReceived: Invalid session id") );
  2039. break;
  2040. }
  2041. //
  2042. // Extract mandatory tags first
  2043. //
  2044. RetrieveTag( pPacket,
  2045. tagServiceName,
  2046. &tagLength,
  2047. &tagValue,
  2048. 0,
  2049. NULL,
  2050. TRUE );
  2051. if ( tagValue == NULL )
  2052. {
  2053. TRACE( TL_A, TM_Pk, ("PacketInitializeFromReceived: Service name tag not found") );
  2054. break;
  2055. }
  2056. RetrieveTag( pPacket,
  2057. tagACName,
  2058. &tagLength,
  2059. &tagValue,
  2060. 0,
  2061. NULL,
  2062. TRUE );
  2063. if ( tagValue == NULL )
  2064. {
  2065. TRACE( TL_A, TM_Pk, ("PacketInitializeFromReceived: AC-Name tag not found") );
  2066. break;
  2067. }
  2068. //
  2069. // Extract optional tags
  2070. //
  2071. RetrieveTag( pPacket,
  2072. tagHostUnique,
  2073. &tagLength,
  2074. &tagValue,
  2075. 0,
  2076. NULL,
  2077. TRUE );
  2078. RetrieveTag( pPacket,
  2079. tagACCookie,
  2080. &tagLength,
  2081. &tagValue,
  2082. 0,
  2083. NULL,
  2084. TRUE );
  2085. //
  2086. // Extract the relay session id tag if it exists
  2087. //
  2088. RetrieveTag( pPacket,
  2089. tagRelaySessionId,
  2090. &tagLength,
  2091. &tagValue,
  2092. 0,
  2093. NULL,
  2094. TRUE );
  2095. TRACE( TL_N, TM_Pk, ("PacketInitializeFromReceived: Processed PADO succesfully") );
  2096. status = NDIS_STATUS_SUCCESS;
  2097. break;
  2098. case PACKET_CODE_PADR:
  2099. TRACE( TL_N, TM_Pk, ("PacketInitializeFromReceived: Processing PADR") );
  2100. //
  2101. // Make sure we have received the correct ethertype
  2102. //
  2103. if ( PacketGetEtherType( pPacket ) != PACKET_ETHERTYPE_DISCOVERY )
  2104. {
  2105. TRACE( TL_A, TM_Pk, ("PacketInitializeFromReceived: Invalid ether type") );
  2106. break;
  2107. }
  2108. //
  2109. // Make sure session id is PACKET_NULL_SESSION
  2110. //
  2111. if ( PacketGetSessionId( pPacket ) != PACKET_NULL_SESSION )
  2112. {
  2113. TRACE( TL_A, TM_Pk, ("PacketInitializeFromReceived: Invalid session id") );
  2114. break;
  2115. }
  2116. //
  2117. // Extract mandatory tags first
  2118. //
  2119. RetrieveTag( pPacket,
  2120. tagServiceName,
  2121. &tagLength,
  2122. &tagValue,
  2123. 0,
  2124. NULL,
  2125. TRUE );
  2126. if ( tagValue == NULL )
  2127. {
  2128. TRACE( TL_A, TM_Pk, ("PacketInitializeFromReceived: Service name tag not found") );
  2129. break;
  2130. }
  2131. //
  2132. // Extract optional tags
  2133. //
  2134. RetrieveTag( pPacket,
  2135. tagHostUnique,
  2136. &tagLength,
  2137. &tagValue,
  2138. 0,
  2139. NULL,
  2140. TRUE );
  2141. RetrieveTag( pPacket,
  2142. tagACCookie,
  2143. &tagLength,
  2144. &tagValue,
  2145. 0,
  2146. NULL,
  2147. TRUE );
  2148. //
  2149. // Extract the relay session id tag if it exists
  2150. //
  2151. RetrieveTag( pPacket,
  2152. tagRelaySessionId,
  2153. &tagLength,
  2154. &tagValue,
  2155. 0,
  2156. NULL,
  2157. TRUE );
  2158. TRACE( TL_N, TM_Pk, ("PacketInitializeFromReceived: Processed PADR succesfully") );
  2159. status = NDIS_STATUS_SUCCESS;
  2160. break;
  2161. case PACKET_CODE_PADS:
  2162. TRACE( TL_N, TM_Pk, ("PacketInitializeFromReceived: Processing PADS") );
  2163. //
  2164. // Make sure we have received the correct ethertype
  2165. //
  2166. if ( PacketGetEtherType( pPacket ) != PACKET_ETHERTYPE_DISCOVERY )
  2167. {
  2168. TRACE( TL_A, TM_Pk, ("PacketInitializeFromReceived: Invalid ether type") );
  2169. break;
  2170. }
  2171. //
  2172. // Make sure session id is NOT PACKET_NULL_SESSION.
  2173. // However, if session id is PACKET_NULL_SESSION, then make sure we have
  2174. // a an Error tag received as per RFC 2156.
  2175. //
  2176. if ( PacketGetSessionId( pPacket ) == PACKET_NULL_SESSION )
  2177. {
  2178. RetrieveErrorTags( pPacket );
  2179. if ( !PacketAnyErrorTagsReceived( pPacket ) )
  2180. {
  2181. TRACE( TL_A, TM_Pk, ("PacketInitializeFromReceived: Invalid session id") );
  2182. break;
  2183. }
  2184. }
  2185. //
  2186. // Extract mandatory tags first
  2187. //
  2188. RetrieveTag( pPacket,
  2189. tagServiceName,
  2190. &tagLength,
  2191. &tagValue,
  2192. 0,
  2193. NULL,
  2194. TRUE );
  2195. if ( tagValue == NULL )
  2196. {
  2197. TRACE( TL_A, TM_Pk, ("PacketInitializeFromReceived: Service name tag not found") );
  2198. break;
  2199. }
  2200. //
  2201. // Extract optional tags
  2202. //
  2203. RetrieveTag( pPacket,
  2204. tagHostUnique,
  2205. &tagLength,
  2206. &tagValue,
  2207. 0,
  2208. NULL,
  2209. TRUE );
  2210. TRACE( TL_N, TM_Pk, ("PacketInitializeFromReceived: Processed PADS succesfully") );
  2211. status = NDIS_STATUS_SUCCESS;
  2212. break;
  2213. case PACKET_CODE_PADT:
  2214. TRACE( TL_N, TM_Pk, ("PacketInitializeFromReceived: Processing PADT") );
  2215. //
  2216. // Make sure we have received the correct ethertype
  2217. //
  2218. if ( PacketGetEtherType( pPacket ) != PACKET_ETHERTYPE_DISCOVERY )
  2219. {
  2220. TRACE( TL_A, TM_Pk, ("PacketInitializeFromReceived: Invalid ether type") );
  2221. break;
  2222. }
  2223. //
  2224. // Make sure session id is not PACKET_NULL_SESSION
  2225. //
  2226. if ( PacketGetSessionId( pPacket ) == PACKET_NULL_SESSION )
  2227. {
  2228. TRACE( TL_A, TM_Pk, ("PacketInitializeFromReceived: Invalid session id") );
  2229. break;
  2230. }
  2231. TRACE( TL_N, TM_Pk, ("PacketInitializeFromReceived: Processed PADT succesfully") );
  2232. status = NDIS_STATUS_SUCCESS;
  2233. break;
  2234. case PACKET_CODE_PAYLOAD:
  2235. TRACE( TL_V, TM_Pk, ("PacketInitializeFromReceived: Processing PAYLOAD") );
  2236. //
  2237. // Make sure we have received the correct ethertype
  2238. //
  2239. if ( PacketGetEtherType( pPacket ) != PACKET_ETHERTYPE_PAYLOAD )
  2240. {
  2241. TRACE( TL_A, TM_Pk, ("PacketInitializeFromReceived: Invalid ether type") );
  2242. break;
  2243. }
  2244. //
  2245. // Make sure session id is not PACKET_NULL_SESSION
  2246. //
  2247. if ( PacketGetSessionId( pPacket ) == PACKET_NULL_SESSION )
  2248. {
  2249. TRACE( TL_A, TM_Pk, ("PacketInitializeFromReceived: Invalid session id") );
  2250. break;
  2251. }
  2252. TRACE( TL_V, TM_Pk, ("PacketInitializeFromReceived: Processed PAYLOAD succesfully") );
  2253. status = NDIS_STATUS_SUCCESS;
  2254. break;
  2255. default:
  2256. //
  2257. // Unknown packet code
  2258. //
  2259. TRACE( TL_A, TM_Pk, ("PacketInitializeFromReceived: Ignoring unknown packet") );
  2260. break;
  2261. }
  2262. if ( status != NDIS_STATUS_SUCCESS )
  2263. {
  2264. TRACE( TL_V, TM_Pk, ("-PacketInitializeFromReceived=$%x",status) );
  2265. return status;
  2266. }
  2267. //
  2268. // The packet was processed succesfuly, now check if we received any error tags
  2269. //
  2270. RetrieveErrorTags( pPacket );
  2271. TRACE( TL_V, TM_Pk, ("-PacketInitializeFromReceived=$%x",status) );
  2272. return status;
  2273. }
  2274. BOOLEAN
  2275. PacketAnyErrorTagsReceived(
  2276. IN PPPOE_PACKET* pPacket
  2277. )
  2278. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2279. Functional Description:
  2280. After a received packet is first processed by a PacketInitialize*FromReceived()
  2281. function, one should call this function to understand if an error tag was
  2282. noticed in the packet.
  2283. If this function yields TRUE, then the caller should call PacketRetrieveErrorTag()
  2284. get the error type and value.
  2285. Parameters:
  2286. pPacket _ A pointer to a PPPoE packet context.
  2287. Return Values:
  2288. TRUE
  2289. FALSE
  2290. ---------------------------------------------------------------------------*/
  2291. {
  2292. ASSERT( pPacket != NULL );
  2293. return( pPacket->ulFlags & PCBF_ErrorTagReceived ) ? TRUE : FALSE;
  2294. }
  2295. VOID
  2296. PacketRetrievePayload(
  2297. IN PPPOE_PACKET* pPacket,
  2298. OUT CHAR** ppPayload,
  2299. OUT USHORT* pusLength
  2300. )
  2301. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2302. Functional Description:
  2303. After a received packet is first processed by a PacketInitializeFromReceived()
  2304. function, one should call this function to retrieve the payload portion of the
  2305. packet if the packet is a PAYLOAD packet.
  2306. Parameters:
  2307. pPacket _ A pointer to a PPPoE packet context holding a PAYLOAD packet.
  2308. Return Values:
  2309. None
  2310. ---------------------------------------------------------------------------*/
  2311. {
  2312. ASSERT( pPacket != NULL );
  2313. ASSERT( pusLength != NULL );
  2314. ASSERT( ppPayload != NULL );
  2315. *pusLength = PacketGetLength( pPacket );
  2316. *ppPayload = pPacket->pPayload;
  2317. }
  2318. VOID
  2319. PacketRetrieveServiceNameTag(
  2320. IN PPPOE_PACKET* pPacket,
  2321. OUT USHORT* pTagLength,
  2322. OUT CHAR** pTagValue,
  2323. IN USHORT prevTagLength,
  2324. IN CHAR* prevTagValue
  2325. )
  2326. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2327. Functional Description:
  2328. After a received packet is first processed by a PacketInitializeFromReceived()
  2329. function, one should call this function to retrieve the service name tag from
  2330. the packet.
  2331. If prevTagValue and prevTagLength are given, then next service name tag will
  2332. be returned, otherwise the first service name tag will be returned.
  2333. If no such service name tags are found, then 0 and NULL will be returned for
  2334. length and value parameters.
  2335. CAUTION: Note that a service name tag of length 0 is valid, and one should
  2336. check the value of pTagValue to understand if service name tag was
  2337. found in the packet or not.
  2338. Parameters:
  2339. pPacket _ A pointer to a PPPoE packet context holding a control packet.
  2340. pTagLength _ On return, holds the length of the service name tag found.
  2341. pTagValue _ On return, points to the buffer holding the service name.
  2342. Will be NULL, if no service name tags could be found.
  2343. prevTagLength _ Length of the previously returned service name tag.
  2344. prevTagValue _ Points to the buffer holding the previous service name tag.
  2345. Return Values:
  2346. None
  2347. ---------------------------------------------------------------------------*/
  2348. {
  2349. ASSERT( pPacket != NULL );
  2350. ASSERT( pTagLength != NULL );
  2351. ASSERT( pTagValue != NULL );
  2352. if ( prevTagLength == 0 &&
  2353. prevTagValue == NULL )
  2354. {
  2355. //
  2356. // Caller asks for the first Service Name Tag, and it should be ready in
  2357. // the reserved field of the PPPOE_PACKET
  2358. //
  2359. *pTagLength = pPacket->tagServiceNameLength;
  2360. *pTagValue = pPacket->tagServiceNameValue;
  2361. }
  2362. else
  2363. {
  2364. //
  2365. // Caller asks for the next Service Name Tag, so try to find and return it
  2366. //
  2367. RetrieveTag( pPacket,
  2368. tagServiceName,
  2369. pTagLength,
  2370. pTagValue,
  2371. prevTagLength,
  2372. prevTagValue,
  2373. FALSE );
  2374. }
  2375. }
  2376. VOID
  2377. PacketRetrieveHostUniqueTag(
  2378. IN PPPOE_PACKET* pPacket,
  2379. OUT USHORT* pTagLength,
  2380. OUT CHAR** pTagValue
  2381. )
  2382. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2383. Functional Description:
  2384. After a received packet is first processed by a PacketInitializeFromReceived()
  2385. function, one should call this function to retrieve the host unique tag from
  2386. the packet.
  2387. If no host unique tag is found, then 0 and NULL will be returned for
  2388. length and value parameters.
  2389. CAUTION: Note that a host unique tag of length 0 is valid, and one should
  2390. check the value of pTagValue to understand if host unique tag was
  2391. found in the packet or not.
  2392. Parameters:
  2393. pPacket _ A pointer to a PPPoE packet context holding a control packet.
  2394. pTagLength _ On return, holds the length of the host unique tag found.
  2395. pTagValue _ On return, points to the buffer holding the host unique value.
  2396. Will be NULL, if no host unique tags could be found.
  2397. Return Values:
  2398. None
  2399. ---------------------------------------------------------------------------*/
  2400. {
  2401. ASSERT( pPacket != NULL );
  2402. ASSERT( pTagLength != NULL );
  2403. ASSERT( pTagValue != NULL );
  2404. //
  2405. // Caller asks for the HostUnique, and it should be ready in
  2406. // the reserved field of the PPPOE_PACKET
  2407. //
  2408. *pTagLength = pPacket->tagHostUniqueLength;
  2409. *pTagValue = pPacket->tagHostUniqueValue;
  2410. }
  2411. VOID
  2412. PacketRetrieveACNameTag(
  2413. IN PPPOE_PACKET* pPacket,
  2414. OUT USHORT* pTagLength,
  2415. OUT CHAR** pTagValue
  2416. )
  2417. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2418. Functional Description:
  2419. After a received packet is first processed by a PacketInitializeFromReceived()
  2420. function, one should call this function to retrieve the AC name tag from
  2421. the packet.
  2422. If no AC name tag is found, then 0 and NULL will be returned for
  2423. length and value parameters.
  2424. CAUTION: Note that an AC name tag of length 0 is valid, and one should
  2425. check the value of pTagValue to understand if AC name tag was
  2426. found in the packet or not.
  2427. Parameters:
  2428. pPacket _ A pointer to a PPPoE packet context holding a control packet.
  2429. pTagLength _ On return, holds the length of the AC name tag found.
  2430. pTagValue _ On return, points to the buffer holding the AC name.
  2431. Will be NULL, if no AC name tags could be found.
  2432. Return Values:
  2433. None
  2434. ---------------------------------------------------------------------------*/
  2435. {
  2436. ASSERT( pPacket != NULL );
  2437. ASSERT( pTagLength != NULL );
  2438. ASSERT( pTagValue != NULL );
  2439. //
  2440. // Caller asks for the AC Name, and it should be ready in
  2441. // the reserved field of the PPPOE_PACKET
  2442. //
  2443. *pTagLength = pPacket->tagACNameLength;
  2444. *pTagValue = pPacket->tagACNameValue;
  2445. }
  2446. VOID
  2447. PacketRetrieveACCookieTag(
  2448. IN PPPOE_PACKET* pPacket,
  2449. OUT USHORT* pTagLength,
  2450. OUT CHAR** pTagValue
  2451. )
  2452. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2453. Functional Description:
  2454. After a received packet is first processed by a PacketInitializeFromReceived()
  2455. function, one should call this function to retrieve the AC cookie tag from
  2456. the packet.
  2457. If no AC cookie tag is found, then 0 and NULL will be returned for
  2458. length and value parameters.
  2459. CAUTION: Note that an AC cookie tag of length 0 is valid, and one should
  2460. check the value of pTagValue to understand if AC cookie tag was
  2461. found in the packet or not.
  2462. Parameters:
  2463. pPacket _ A pointer to a PPPoE packet context holding a control packet.
  2464. pTagLength _ On return, holds the length of the AC cookie tag found.
  2465. pTagValue _ On return, points to the buffer holding the AC cookie.
  2466. Will be NULL, if no AC cookie tags could be found.
  2467. Return Values:
  2468. None
  2469. ---------------------------------------------------------------------------*/
  2470. {
  2471. ASSERT( pPacket != NULL );
  2472. ASSERT( pTagLength != NULL );
  2473. ASSERT( pTagValue != NULL );
  2474. //
  2475. // Caller asks for the AC Cookie, and it should be ready in
  2476. // the reserved field of the PPPOE_PACKET
  2477. //
  2478. *pTagLength = pPacket->tagACCookieLength;
  2479. *pTagValue = pPacket->tagACCookieValue;
  2480. }
  2481. VOID
  2482. PacketRetrieveErrorTag(
  2483. IN PPPOE_PACKET* pPacket,
  2484. OUT PACKET_TAGS* pTagType,
  2485. OUT USHORT* pTagLength,
  2486. OUT CHAR** pTagValue
  2487. )
  2488. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2489. Functional Description:
  2490. After a received packet is first processed by a PacketInitializeFromReceived()
  2491. function, one should call this function to retrieve the error information from
  2492. the packet.
  2493. If no errors were found, then 0 and NULL will be returned for length and value
  2494. parameters.
  2495. CAUTION: Note that an error tag of length 0 is valid, and one should
  2496. check the value of pTagValue to understand if an error tag was
  2497. found in the packet or not.
  2498. Parameters:
  2499. pPacket _ A pointer to a PPPoE packet context holding a control packet.
  2500. pTagType _ On return, holds the type of the error tag found.
  2501. pTagLength _ On return, holds the length of the error tag found.
  2502. pTagValue _ On return, points to the buffer holding the error.
  2503. Will be NULL, if no error tags could be found.
  2504. Return Values:
  2505. None
  2506. ---------------------------------------------------------------------------*/
  2507. {
  2508. ASSERT( pPacket != NULL );
  2509. ASSERT( pTagType != NULL );
  2510. ASSERT( pTagLength != NULL );
  2511. ASSERT( pTagValue != NULL );
  2512. //
  2513. // Caller asks for the received error, and it should be ready in
  2514. // the reserved field of the PPPOE_PACKET
  2515. //
  2516. if ( pPacket->ulFlags & PCBF_ErrorTagReceived )
  2517. {
  2518. *pTagType = pPacket->tagErrorType;
  2519. *pTagLength = pPacket->tagErrorTagLength;
  2520. *pTagValue = pPacket->tagErrorTagValue;
  2521. }
  2522. else
  2523. {
  2524. *pTagLength = 0;
  2525. *pTagValue = NULL;
  2526. }
  2527. }
  2528. PPPOE_PACKET*
  2529. PacketMakeClone(
  2530. IN PPPOE_PACKET* pPacket
  2531. )
  2532. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2533. Functional Description:
  2534. This function will be used to make a clone of a packet for sending it
  2535. over multiple bindings.
  2536. CAUTION: This function only clones the NDIS_PACKET portion of PPPOE_PACKET
  2537. and leaves other fields untouched, so the clone packets should only
  2538. be used with NdisSend(), and disposed there after.
  2539. Parameters:
  2540. pPacket _ A pointer to a PPPoE packet context that will be cloned.
  2541. Return Values:
  2542. Pointer to the clone packet if succesfull, NULL otherwise.
  2543. ---------------------------------------------------------------------------*/
  2544. {
  2545. PPPOE_PACKET* pClone = NULL;
  2546. TRACE( TL_N, TM_Pk, ("+PacketMakeClone") );
  2547. //
  2548. // Allocate the clone
  2549. //
  2550. pClone = PacketCreateSimple();
  2551. if ( pClone == NULL )
  2552. {
  2553. TRACE( TL_A, TM_Pk, ("PacketMakeClone: Can not make clone, resources unavailable") );
  2554. TRACE( TL_N, TM_Pk, ("-PacketMakeClone=$%x",pClone) );
  2555. return pClone;
  2556. }
  2557. //
  2558. // Copy the clone
  2559. //
  2560. NdisMoveMemory( pClone->pHeader, pPacket->pHeader, PPPOE_PACKET_HEADER_LENGTH );
  2561. NdisMoveMemory( pClone->pPayload, pPacket->pPayload, PACKET_GEN_MAX_LENGTH );
  2562. NdisAdjustBufferLength( pClone->pNdisBuffer,
  2563. (UINT) ( PacketGetLength( pPacket ) + PPPOE_PACKET_HEADER_LENGTH ) );
  2564. TRACE( TL_N, TM_Pk, ("-PacketMakeClone=$%x",pClone) );
  2565. return pClone;
  2566. }
  2567. PPPOE_PACKET*
  2568. PacketGetRelatedPppoePacket(
  2569. IN NDIS_PACKET* pNdisPacket
  2570. )
  2571. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2572. Functional Description:
  2573. This function will be used to get the owning PPPoE packet context from an
  2574. Ndis packet.
  2575. Parameters:
  2576. pNdisPacket _ A pointer to an Ndis packet that belongs to a PPPoE packet.
  2577. Return Values:
  2578. A pointer to the owning PPPoE packet.
  2579. ---------------------------------------------------------------------------*/
  2580. {
  2581. return (*(PPPOE_PACKET**)(&pNdisPacket->ProtocolReserved[0 * sizeof(PVOID)]));
  2582. }
  2583. NDIS_WAN_PACKET*
  2584. PacketGetRelatedNdiswanPacket(
  2585. IN PPPOE_PACKET* pPacket
  2586. )
  2587. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2588. Functional Description:
  2589. This function will be used to get related NDISWAN packet from a PPPoE
  2590. payload packet that was perpared and sent.
  2591. Parameters:
  2592. pPacket _ A pointer to a PPPoE payload packet that was sent.
  2593. Return Values:
  2594. A pointer to the related NDISWAN packet.
  2595. ---------------------------------------------------------------------------*/
  2596. {
  2597. return (*(NDIS_WAN_PACKET**)(&pPacket->pNdisPacket->ProtocolReserved[1 * sizeof(PVOID)])) ;
  2598. }
  2599. PADAPTER
  2600. PacketGetMiniportAdapter(
  2601. IN PPPOE_PACKET* pPacket
  2602. )
  2603. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2604. Functional Description:
  2605. This function will be used to get miniport adapter set in
  2606. PacketInitializePAYLOADToSend() function.
  2607. Parameters:
  2608. pPacket _ A pointer to a PPPoE payload packet that was sent.
  2609. Return Values:
  2610. Miniport adapter
  2611. ---------------------------------------------------------------------------*/
  2612. {
  2613. return (*(ADAPTER**)(&pPacket->pNdisPacket->ProtocolReserved[2 * sizeof(PVOID)]));
  2614. }
  2615. VOID
  2616. PacketGenerateACCookieTag(
  2617. IN PPPOE_PACKET* pPacket,
  2618. IN CHAR tagACCookieValue[ PPPOE_AC_COOKIE_TAG_LENGTH ]
  2619. )
  2620. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2621. Functional Description:
  2622. This function is used to generate the AC Cookie tag based on the PADI
  2623. packets sources address.
  2624. Parameters:
  2625. pPacket _ A pointer to a PADI packet that was received.
  2626. Return Values:
  2627. None
  2628. ---------------------------------------------------------------------------*/
  2629. {
  2630. NdisMoveMemory( tagACCookieValue, PacketGetSrcAddr( pPacket ), 6 );
  2631. }
  2632. BOOLEAN
  2633. PacketValidateACCookieTagInPADR(
  2634. IN PPPOE_PACKET* pPacket
  2635. )
  2636. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2637. Functional Description:
  2638. This function is used to validate the AC Cookie tag in a received PADR
  2639. packet.
  2640. It basically uses the source address from the PADR packet to generate the
  2641. original AC Cookie tag and compares them. If they are equal TRUE is returned,
  2642. otherwise FALSE is returned.
  2643. Parameters:
  2644. pPacket _ A pointer to a PADR packet that was received.
  2645. Return Values:
  2646. None
  2647. ---------------------------------------------------------------------------*/
  2648. {
  2649. BOOLEAN fRet = FALSE;
  2650. CHAR tagACCookie[ PPPOE_AC_COOKIE_TAG_LENGTH ];
  2651. CHAR* tagACCookieValue = NULL;
  2652. USHORT tagACCookieLength = 0;
  2653. PacketRetrieveACCookieTag( pPacket,
  2654. &tagACCookieLength,
  2655. &tagACCookieValue );
  2656. PacketGenerateACCookieTag( pPacket, tagACCookie );
  2657. if ( NdisEqualMemory( tagACCookie, tagACCookieValue, PPPOE_AC_COOKIE_TAG_LENGTH ) )
  2658. {
  2659. fRet = TRUE;
  2660. }
  2661. return fRet;
  2662. }