Source code of Windows XP (NT5)
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.

476 lines
10 KiB

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