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.

480 lines
11 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. net\routing\ip\wanarp2\rcv.c
  5. Abstract:
  6. Revision History:
  7. --*/
  8. #define __FILE_SIG__ RCV_SIG
  9. #include "inc.h"
  10. INT
  11. WanNdisReceivePacket(
  12. IN NDIS_HANDLE nhProtocolContext,
  13. IN PNDIS_PACKET pnpPacket
  14. )
  15. {
  16. PNDIS_BUFFER pnbBuffer;
  17. PVOID pvFirstBuffer;
  18. UINT uiFirstBufLen, uiTotalPacketLen;
  19. INT iClientCount;
  20. NDIS_STATUS nsStatus;
  21. TraceEnter(RCV, "NdisReceivePacket");
  22. NdisGetFirstBufferFromPacket(pnpPacket,
  23. &pnbBuffer,
  24. &pvFirstBuffer,
  25. &uiFirstBufLen,
  26. &uiTotalPacketLen);
  27. if (pvFirstBuffer==NULL)
  28. return 0;
  29. //
  30. // The first buffer better contain enough data
  31. //
  32. if (uiFirstBufLen < sizeof(ETH_HEADER) + sizeof(IP_HEADER))
  33. return 0;
  34. iClientCount = 0;
  35. nsStatus = WanReceiveCommon(nhProtocolContext,
  36. pnpPacket,
  37. pvFirstBuffer,
  38. sizeof(ETH_HEADER),
  39. (PVOID)((ULONG_PTR)pvFirstBuffer + sizeof(ETH_HEADER)),
  40. uiFirstBufLen - sizeof(ETH_HEADER),
  41. uiTotalPacketLen - sizeof(ETH_HEADER),
  42. pnbBuffer,
  43. &iClientCount);
  44. return iClientCount;
  45. }
  46. NDIS_STATUS
  47. WanNdisReceive(
  48. NDIS_HANDLE nhProtocolContext,
  49. NDIS_HANDLE nhXferContext,
  50. VOID UNALIGNED *pvHeader,
  51. UINT uiHeaderLen,
  52. VOID UNALIGNED *pvData,
  53. UINT uiFirstBufferLen,
  54. UINT uiTotalDataLen
  55. )
  56. {
  57. TraceEnter(RCV, "NdisReceive");
  58. return WanReceiveCommon(nhProtocolContext,
  59. nhXferContext,
  60. pvHeader,
  61. uiHeaderLen,
  62. pvData,
  63. uiFirstBufferLen,
  64. uiTotalDataLen,
  65. NULL,
  66. NULL);
  67. }
  68. NDIS_STATUS
  69. WanReceiveCommon(
  70. NDIS_HANDLE nhProtocolContext,
  71. NDIS_HANDLE nhXferContext,
  72. VOID UNALIGNED *pvHeader,
  73. UINT uiHeaderLen,
  74. VOID UNALIGNED *pvData,
  75. UINT uiFirstBufferLen,
  76. UINT uiTotalDataLen,
  77. PMDL pMdl,
  78. PINT piClientCount
  79. )
  80. /*++
  81. Routine Description:
  82. The common receive handler for packet based or buffer based receives
  83. Locks:
  84. Called at DPC (usually).
  85. Acquires the g_rlConnTable lock to get a pointer to the connection
  86. entry. Then locks either the entry itself or the adapter.
  87. Arguments:
  88. nhProtocolContext
  89. nhXferContext
  90. pvHeader
  91. uiHeaderLen
  92. pvData
  93. uiFirstBufferLen
  94. uiTotalDataLen
  95. pMdl
  96. piClientCount
  97. Return Value:
  98. NDIS_STATUS_NOT_ACCEPTED
  99. --*/
  100. {
  101. PCONN_ENTRY pConnEntry;
  102. PADAPTER pAdapter;
  103. PUMODE_INTERFACE pInterface;
  104. ETH_HEADER UNALIGNED *pEthHeader;
  105. KIRQL kiIrql;
  106. WORD wType;
  107. ULONG ulIndex;
  108. BOOLEAN bNonUnicast;
  109. #if DBG
  110. IP_HEADER UNALIGNED *pIpHeader;
  111. #endif
  112. //
  113. // Pick out connection index from the buffer
  114. //
  115. pEthHeader = (ETH_HEADER UNALIGNED *)pvHeader;
  116. ulIndex = GetConnIndexFromAddr(pEthHeader->rgbyDestAddr);
  117. RtAcquireSpinLock(&g_rlConnTableLock,
  118. &kiIrql);
  119. if(ulIndex >= g_ulConnTableSize)
  120. {
  121. Trace(RCV, ERROR,
  122. ("ReceiveCommon: Invalid index for conn entry %d\n",
  123. ulIndex));
  124. RtReleaseSpinLock(&g_rlConnTableLock,
  125. kiIrql);
  126. return NDIS_STATUS_NOT_ACCEPTED;
  127. }
  128. pConnEntry = GetConnEntryGivenIndex(ulIndex);
  129. if(pConnEntry is NULL)
  130. {
  131. Trace(RCV, ERROR,
  132. ("ReceiveCommon: Couldnt find entry for conn %d\n",
  133. ulIndex));
  134. RtReleaseSpinLock(&g_rlConnTableLock,
  135. kiIrql);
  136. return NDIS_STATUS_NOT_ACCEPTED;
  137. }
  138. //
  139. // Lock the connection entry or adapter
  140. //
  141. RtAcquireSpinLockAtDpcLevel(pConnEntry->prlLock);
  142. RtReleaseSpinLockFromDpcLevel(&g_rlConnTableLock);
  143. //
  144. // We can get this only on a connected entry
  145. //
  146. RtAssert(pConnEntry->byState is CS_CONNECTED);
  147. pAdapter = pConnEntry->pAdapter;
  148. //
  149. // A connected entry must have an adapter
  150. //
  151. RtAssert(pAdapter);
  152. //
  153. // The interface better also be present
  154. //
  155. pInterface = pAdapter->pInterface;
  156. RtAssert(pInterface);
  157. if(pConnEntry->duUsage isnot DU_CALLIN)
  158. {
  159. //
  160. // For non clients, also lock the interface
  161. //
  162. RtAcquireSpinLockAtDpcLevel(&(pInterface->rlLock));
  163. }
  164. #if DBG
  165. Trace(RCV, INFO,
  166. ("ReceiveCommon: Extracted adapter %x with name %s\n",
  167. pAdapter,
  168. pAdapter->asDeviceNameA.Buffer));
  169. pIpHeader = (IP_HEADER UNALIGNED *)pvData;
  170. RtAssert((pIpHeader->byVerLen & 0xF0) is 0x40);
  171. RtAssert(LengthOfIpHeader(pIpHeader) >= 20);
  172. //
  173. // If the packet is not fragmented, then the data from its header
  174. // should be <= the data ndis gives us (<= because there may be
  175. // padding and ndis may be giving us trailing bytes)
  176. //
  177. //RtAssert(RtlUshortByteSwap(pIpHeader->wLength) <= uiTotalDataLen);
  178. #endif
  179. //
  180. // Increment some stats. For the server interface, these can be
  181. // inconsistent
  182. //
  183. pInterface->ulInOctets += (uiTotalDataLen + uiHeaderLen);
  184. //
  185. // Verify this is a well formed packet
  186. //
  187. wType = RtlUshortByteSwap(pEthHeader->wType);
  188. if(wType isnot ARP_ETYPE_IP)
  189. {
  190. pInterface->ulInUnknownProto++;
  191. Trace(RCV, ERROR,
  192. ("ReceiveCommon: Type %d is wrong\n", wType));
  193. if(pConnEntry->duUsage isnot DU_CALLIN)
  194. {
  195. RtReleaseSpinLockFromDpcLevel(&(pInterface->rlLock));
  196. }
  197. RtReleaseSpinLock(pConnEntry->prlLock,
  198. kiIrql);
  199. DereferenceConnEntry(pConnEntry);
  200. return NDIS_STATUS_NOT_RECOGNIZED;
  201. }
  202. //
  203. // Need to figure out if this is a unicast or a broadcast. At the
  204. // link layer we dont have a concept of broadcast. So, we always mark
  205. // this as unicast. We can be smarter about this and look at the
  206. // IPHeader and decide based on the IP dest addr
  207. //
  208. bNonUnicast = FALSE;
  209. pInterface->ulInUniPkts++;
  210. //
  211. // Check if the filtering of the Netbios packets is enabled on this
  212. // connection. If so then do not indicate the packet.
  213. //
  214. if((pConnEntry->bFilterNetBios is TRUE) and
  215. (WanpDropNetbiosPacket((PBYTE)pvData,uiFirstBufferLen)))
  216. {
  217. pInterface->ulInDiscards++;
  218. Trace(RCV, TRACE,
  219. ("ReceiveCommon: Dropping Netbios packet\n", wType));
  220. if(pConnEntry->duUsage isnot DU_CALLIN)
  221. {
  222. RtReleaseSpinLockFromDpcLevel(&(pInterface->rlLock));
  223. }
  224. RtReleaseSpinLock(pConnEntry->prlLock,
  225. kiIrql);
  226. DereferenceConnEntry(pConnEntry);
  227. return NDIS_STATUS_NOT_ACCEPTED;
  228. }
  229. //
  230. // Release the lock BEFORE we tell IP
  231. //
  232. if(pConnEntry->duUsage isnot DU_CALLIN)
  233. {
  234. RtReleaseSpinLockFromDpcLevel(&(pInterface->rlLock));
  235. }
  236. RtReleaseSpinLock(pConnEntry->prlLock,
  237. kiIrql);
  238. #if PKT_DBG
  239. Trace(RCV, ERROR,
  240. ("ReceiveCommon: \nMdl %x Pkt %x Hdr %x Data %x\n",
  241. pMdl,
  242. nhXferContext,
  243. pvHeader,
  244. pvData));
  245. #endif // PKT_DBG
  246. if(pMdl)
  247. {
  248. g_pfnIpRcvPkt(pAdapter->pvIpContext,
  249. (PBYTE)pvData,
  250. uiFirstBufferLen,
  251. uiTotalDataLen,
  252. nhXferContext,
  253. 0,
  254. bNonUnicast,
  255. sizeof(ETH_HEADER),
  256. pMdl,
  257. piClientCount,
  258. pConnEntry->pvIpLinkContext);
  259. }
  260. else
  261. {
  262. g_pfnIpRcv(pAdapter->pvIpContext,
  263. (PBYTE)pvData,
  264. uiFirstBufferLen,
  265. uiTotalDataLen,
  266. nhXferContext,
  267. 0,
  268. bNonUnicast,
  269. pConnEntry->pvIpLinkContext);
  270. }
  271. DereferenceConnEntry(pConnEntry);
  272. return NDIS_STATUS_SUCCESS;
  273. }
  274. VOID
  275. WanNdisReceiveComplete(
  276. NDIS_HANDLE nhBindHandle
  277. )
  278. {
  279. TraceEnter(RCV, "NdisReceiveComplete");
  280. g_pfnIpRcvComplete();
  281. }
  282. NDIS_STATUS
  283. WanIpTransferData(
  284. PVOID pvContext,
  285. NDIS_HANDLE nhMacContext,
  286. UINT uiProtoOffset,
  287. UINT uiTransferOffset,
  288. UINT uiTransferLength,
  289. PNDIS_PACKET pnpPacket,
  290. PUINT puiTransferred
  291. )
  292. {
  293. RtAssert(FALSE);
  294. return NDIS_STATUS_SUCCESS;
  295. }
  296. VOID
  297. WanNdisTransferDataComplete(
  298. NDIS_HANDLE nhProtocolContext,
  299. PNDIS_PACKET pnpPacket,
  300. NDIS_STATUS nsStatus,
  301. UINT uiBytesCopied
  302. )
  303. {
  304. RtAssert(FALSE);
  305. return;
  306. }
  307. UINT
  308. WanIpReturnPacket(
  309. PVOID pvContext,
  310. PNDIS_PACKET pnpPacket
  311. )
  312. {
  313. Trace(RCV, ERROR,
  314. ("IpReturnPacket: %x\n",
  315. pnpPacket));
  316. NdisReturnPackets(&pnpPacket,
  317. 1);
  318. return TRUE;
  319. }
  320. BOOLEAN
  321. WanpDropNetbiosPacket(
  322. PBYTE pbyBuffer,
  323. ULONG ulBufferLen
  324. )
  325. {
  326. IP_HEADER UNALIGNED *pIpHeader;
  327. PBYTE pbyUdpPacket;
  328. WORD wSrcPort;
  329. ULONG ulIpHdrLen;
  330. pIpHeader = (IP_HEADER UNALIGNED *)pbyBuffer;
  331. if(pIpHeader->byProtocol is 0x11)
  332. {
  333. ulIpHdrLen = LengthOfIpHeader(pIpHeader);
  334. //
  335. // If we cant get to the 10th byte in the UDP packet in this
  336. // buffer, we just let the packet go
  337. //
  338. if(ulBufferLen < ulIpHdrLen + 10)
  339. {
  340. return FALSE;
  341. }
  342. pbyUdpPacket = (PBYTE)((ULONG_PTR)pbyBuffer + ulIpHdrLen);
  343. wSrcPort = *((WORD UNALIGNED *)pbyUdpPacket);
  344. if(wSrcPort is PORT137_NBO)
  345. {
  346. //
  347. // UDP port 137 is NETBIOS/IP traffic
  348. //
  349. //
  350. // Allow only WINS Query Requests to go through
  351. // WINS Query packets have x0000xxx in the 10th byte
  352. //
  353. if(((*(pbyUdpPacket + 10)) & 0x78) isnot 0)
  354. {
  355. return TRUE;
  356. }
  357. }
  358. }
  359. return FALSE;
  360. }