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.

776 lines
27 KiB

  1. /********************************************************************/
  2. /** Microsoft LAN Manager **/
  3. /** Copyright(c) Microsoft Corp., 1990-1993 **/
  4. /********************************************************************/
  5. /* :ts=4 */
  6. //** RAW.C - Raw IP interface code.
  7. //
  8. // This file contains the code for the Raw IP interface functions,
  9. // principally send and receive datagram.
  10. //
  11. #include "precomp.h"
  12. #include "addr.h"
  13. #include "raw.h"
  14. #include "tlcommon.h"
  15. #include "info.h"
  16. #include "tcpcfg.h"
  17. #include "secfltr.h"
  18. #include "udp.h"
  19. #define NO_TCP_DEFS 1
  20. #include "tcpdeb.h"
  21. #define PROT_IGMP 2
  22. #define PROT_RSVP 46 // Protocol number for RSVP
  23. #ifdef POOL_TAGGING
  24. #ifdef ExAllocatePool
  25. #undef ExAllocatePool
  26. #endif
  27. #define ExAllocatePool(type, size) ExAllocatePoolWithTag(type, size, 'rPCT')
  28. #ifndef CTEAllocMem
  29. #error "CTEAllocMem is not already defined - will override tagging"
  30. #else
  31. #undef CTEAllocMem
  32. #endif
  33. #define CTEAllocMem(size) ExAllocatePoolWithTag(NonPagedPool, size, 'rPCT')
  34. #endif // POOL_TAGGING
  35. void *RawProtInfo = NULL;
  36. extern IPInfo LocalNetInfo;
  37. //** RawSend - Send a datagram.
  38. //
  39. // The real send datagram routine. We assume that the busy bit is
  40. // set on the input AddrObj, and that the address of the SendReq
  41. // has been verified.
  42. //
  43. // We start by sending the input datagram, and we loop until there's
  44. // nothing left on the send q.
  45. //
  46. // Input: SrcAO - Pointer to AddrObj doing the send.
  47. // SendReq - Pointer to sendreq describing send.
  48. //
  49. // Returns: Nothing
  50. //
  51. void
  52. RawSend(AddrObj * SrcAO, DGSendReq * SendReq)
  53. {
  54. PNDIS_BUFFER RawBuffer;
  55. UDPHeader *UH;
  56. CTELockHandle AOHandle;
  57. RouteCacheEntry *RCE; // RCE used for each send.
  58. IPAddr SrcAddr; // Source address IP thinks we should
  59. // use.
  60. uchar DestType; // Type of destination address.
  61. IP_STATUS SendStatus; // Status of send attempt.
  62. ushort MSS;
  63. uint AddrValid;
  64. IPOptInfo OptInfo;
  65. IPAddr OrigSrc;
  66. uchar protocol;
  67. CTEStructAssert(SrcAO, ao);
  68. ASSERT(SrcAO->ao_usecnt != 0);
  69. protocol = SrcAO->ao_prot;
  70. IF_TCPDBG(TCP_DEBUG_RAW) {
  71. TCPTRACE((
  72. "RawSend called, prot %u\n", protocol
  73. ));
  74. }
  75. //* Loop while we have something to send, and can get
  76. // resources to send.
  77. for (;;) {
  78. CTEStructAssert(SendReq, dsr);
  79. // Make sure we have a Raw header buffer for this send. If we
  80. // don't, try to get one.
  81. if ((RawBuffer = SendReq->dsr_header) == NULL) {
  82. // Don't have one, so try to get one.
  83. RawBuffer = GetDGHeader(&UH);
  84. if (RawBuffer != NULL)
  85. SendReq->dsr_header = RawBuffer;
  86. else {
  87. // Couldn't get a header buffer. Push the send request
  88. // back on the queue, and queue the addr object for when
  89. // we get resources.
  90. CTEGetLock(&SrcAO->ao_lock, &AOHandle);
  91. PUSHQ(&SrcAO->ao_sendq, &SendReq->dsr_q);
  92. PutPendingQ(SrcAO);
  93. CTEFreeLock(&SrcAO->ao_lock, AOHandle);
  94. return;
  95. }
  96. }
  97. // At this point, we have the buffer we need. Call IP to get an
  98. // RCE (along with the source address if we need it), then
  99. // send the data.
  100. ASSERT(RawBuffer != NULL);
  101. if (!CLASSD_ADDR(SendReq->dsr_addr)) {
  102. // This isn't a multicast send, so we'll use the ordinary
  103. // information.
  104. OrigSrc = SrcAO->ao_addr;
  105. OptInfo = SrcAO->ao_opt;
  106. } else {
  107. OrigSrc = SrcAO->ao_mcastaddr;
  108. OptInfo = SrcAO->ao_mcastopt;
  109. if (SrcAO->ao_opt.ioi_options &&
  110. (*SrcAO->ao_opt.ioi_options == IP_OPT_ROUTER_ALERT)) {
  111. //Temporarily point to ao_opt options to satisfy
  112. //RFC 2113 (router alerts goes onmcast address too)
  113. OptInfo.ioi_options = SrcAO->ao_opt.ioi_options;
  114. OptInfo.ioi_optlength = SrcAO->ao_opt.ioi_optlength;
  115. }
  116. }
  117. ASSERT(!(SrcAO->ao_flags & AO_DHCP_FLAG));
  118. if (SrcAO->ao_opt.ioi_ucastif) {
  119. // srcaddr = address the socket is bound to
  120. SrcAddr = SrcAO->ao_addr;
  121. // go thru slow path
  122. RCE = NULL;
  123. } else if ((OptInfo.ioi_mcastif) && CLASSD_ADDR(SendReq->dsr_addr)) {
  124. // mcast_if is set and this is a mcast send
  125. ASSERT(IP_ADDR_EQUAL(OrigSrc, NULL_IP_ADDR));
  126. SrcAddr = (*LocalNetInfo.ipi_isvalidindex) (OptInfo.ioi_mcastif);
  127. // go thru slow path
  128. RCE = NULL;
  129. } else {
  130. SrcAddr = (*LocalNetInfo.ipi_openrce) (SendReq->dsr_addr,
  131. OrigSrc, &RCE, &DestType, &MSS, &OptInfo);
  132. }
  133. AddrValid = !IP_ADDR_EQUAL(SrcAddr, NULL_IP_ADDR);
  134. if (AddrValid) {
  135. // The OpenRCE worked. Send it.
  136. if (!IP_ADDR_EQUAL(OrigSrc, NULL_IP_ADDR))
  137. SrcAddr = OrigSrc;
  138. NdisAdjustBufferLength(RawBuffer, 0);
  139. NDIS_BUFFER_LINKAGE(RawBuffer) = SendReq->dsr_buffer;
  140. // Now send the packet.
  141. IF_TCPDBG(TCP_DEBUG_RAW) {
  142. TCPTRACE(("RawSend transmitting\n"));
  143. }
  144. UStats.us_outdatagrams++;
  145. SendStatus = (*LocalNetInfo.ipi_xmit) (RawProtInfo, SendReq,
  146. RawBuffer, (uint) SendReq->dsr_size, SendReq->dsr_addr, SrcAddr,
  147. &OptInfo, RCE, protocol, SendReq->dsr_context);
  148. // closerce will just return if RCE is NULL
  149. (*LocalNetInfo.ipi_closerce) (RCE);
  150. // If it completed immediately, give it back to the user.
  151. // Otherwise we'll complete it when the SendComplete happens.
  152. // Currently, we don't map the error code from this call - we
  153. // might need to in the future.
  154. if (SendStatus != IP_PENDING)
  155. DGSendComplete(SendReq, RawBuffer, SendStatus);
  156. } else {
  157. TDI_STATUS Status;
  158. if (DestType == DEST_INVALID)
  159. Status = TDI_BAD_ADDR;
  160. else
  161. Status = TDI_DEST_UNREACHABLE;
  162. // Complete the request with an error.
  163. (*SendReq->dsr_rtn) (SendReq->dsr_context, Status, 0);
  164. // Now free the request.
  165. SendReq->dsr_rtn = NULL;
  166. DGSendComplete(SendReq, RawBuffer, IP_SUCCESS);
  167. }
  168. CTEGetLock(&SrcAO->ao_lock, &AOHandle);
  169. if (!EMPTYQ(&SrcAO->ao_sendq)) {
  170. DEQUEUE(&SrcAO->ao_sendq, SendReq, DGSendReq, dsr_q);
  171. CTEFreeLock(&SrcAO->ao_lock, AOHandle);
  172. } else {
  173. CLEAR_AO_REQUEST(SrcAO, AO_SEND);
  174. CTEFreeLock(&SrcAO->ao_lock, AOHandle);
  175. return;
  176. }
  177. }
  178. }
  179. //* RawDeliver - Deliver a datagram to a user.
  180. //
  181. // This routine delivers a datagram to a Raw user. We're called with
  182. // the AddrObj to deliver on, and with the AddrObjTable lock held.
  183. // We try to find a receive on the specified AddrObj, and if we do
  184. // we remove it and copy the data into the buffer. Otherwise we'll
  185. // call the receive datagram event handler, if there is one. If that
  186. // fails we'll discard the datagram.
  187. //
  188. // Input: RcvAO - AO to receive the datagram.
  189. // SrcIP - Source IP address of datagram.
  190. // IPH - IP Header
  191. // IPHLength - Bytes in IPH.
  192. // RcvBuf - The IPReceive buffer containing the data.
  193. // RcvSize - Size received, including the Raw header.
  194. // TableHandle - Lock handle for AddrObj table.
  195. //
  196. // Returns: Nothing.
  197. //
  198. void
  199. RawDeliver(AddrObj * RcvAO, IPAddr SrcIP, IPHeader UNALIGNED * IPH,
  200. uint IPHLength, IPRcvBuf * RcvBuf, uint RcvSize, IPOptInfo * OptInfo,
  201. CTELockHandle TableHandle, DGDeliverInfo *DeliverInfo)
  202. {
  203. Queue *CurrentQ;
  204. CTELockHandle AOHandle;
  205. DGRcvReq *RcvReq;
  206. uint BytesTaken = 0;
  207. uchar AddressBuffer[TCP_TA_SIZE];
  208. uint RcvdSize;
  209. EventRcvBuffer *ERB = NULL;
  210. int BufferSize = 0;
  211. PVOID BufferToSend = NULL;
  212. CTEStructAssert(RcvAO, ao);
  213. CTEGetLock(&RcvAO->ao_lock, &AOHandle);
  214. CTEFreeLock(&AddrObjTableLock.Lock, AOHandle);
  215. if (AO_VALID(RcvAO)) {
  216. if ((DeliverInfo->Flags & IS_BCAST) && (DeliverInfo->Flags & SRC_LOCAL)
  217. && (RcvAO->ao_mcast_loop == 0)) {
  218. goto loop_exit;
  219. }
  220. IF_TCPDBG(TCP_DEBUG_RAW) {
  221. TCPTRACE((
  222. "Raw delivering %u byte header + %u data bytes to AO %lx\n",
  223. IPHLength, RcvSize, RcvAO
  224. ));
  225. }
  226. CurrentQ = QHEAD(&RcvAO->ao_rcvq);
  227. // Walk the list, looking for a receive buffer that matches.
  228. while (CurrentQ != QEND(&RcvAO->ao_rcvq)) {
  229. RcvReq = QSTRUCT(DGRcvReq, CurrentQ, drr_q);
  230. CTEStructAssert(RcvReq, drr);
  231. // If this request is a wildcard request, or matches the source IP
  232. // address, deliver it.
  233. if (IP_ADDR_EQUAL(RcvReq->drr_addr, NULL_IP_ADDR) ||
  234. IP_ADDR_EQUAL(RcvReq->drr_addr, SrcIP)) {
  235. TDI_STATUS Status;
  236. PNDIS_BUFFER DestBuf = RcvReq->drr_buffer;
  237. uint DestOffset = 0;
  238. // Remove this from the queue.
  239. REMOVEQ(&RcvReq->drr_q);
  240. // We're done. We can free the AddrObj lock now.
  241. CTEFreeLock(&RcvAO->ao_lock, TableHandle);
  242. IF_TCPDBG(TCP_DEBUG_RAW) {
  243. TCPTRACE(("Copying to posted receive\n"));
  244. }
  245. // Copy the header
  246. DestBuf = CopyFlatToNdis(DestBuf, (uchar *) IPH, IPHLength,
  247. &DestOffset, &RcvdSize);
  248. // Copy the data and then complete the request.
  249. RcvdSize += CopyRcvToNdis(RcvBuf, DestBuf,
  250. RcvSize, 0, DestOffset);
  251. ASSERT(RcvdSize <= RcvReq->drr_size);
  252. IF_TCPDBG(TCP_DEBUG_RAW) {
  253. TCPTRACE(("Copied %u bytes\n", RcvdSize));
  254. }
  255. Status = UpdateConnInfo(RcvReq->drr_conninfo, OptInfo,
  256. SrcIP, 0);
  257. UStats.us_indatagrams++;
  258. (*RcvReq->drr_rtn) (RcvReq->drr_context, Status, RcvdSize);
  259. FreeDGRcvReq(RcvReq);
  260. return;
  261. }
  262. // Either the IP address or the port didn't match. Get the next
  263. // one.
  264. CurrentQ = QNEXT(CurrentQ);
  265. }
  266. // We've walked the list, and not found a buffer. Call the recv.
  267. // handler now.
  268. if (RcvAO->ao_rcvdg != NULL) {
  269. PRcvDGEvent RcvEvent = RcvAO->ao_rcvdg;
  270. PVOID RcvContext = RcvAO->ao_rcvdgcontext;
  271. TDI_STATUS RcvStatus;
  272. CTELockHandle OldLevel;
  273. uint IndicateSize;
  274. uint DestOffset;
  275. PNDIS_BUFFER DestBuf;
  276. ULONG Flags = TDI_RECEIVE_COPY_LOOKAHEAD;
  277. uchar *TempBuf = NULL;
  278. ulong TempBufLen = 0;
  279. REF_AO(RcvAO);
  280. CTEFreeLock(&RcvAO->ao_lock, TableHandle);
  281. BuildTDIAddress(AddressBuffer, SrcIP, 0);
  282. IndicateSize = IPHLength;
  283. if (((uchar *) IPH + IPHLength) == RcvBuf->ipr_buffer) {
  284. //
  285. // The header is contiguous with the data
  286. //
  287. IndicateSize += RcvBuf->ipr_size;
  288. IF_TCPDBG(TCP_DEBUG_RAW) {
  289. TCPTRACE(("RawRcv: header & data are contiguous\n"));
  290. }
  291. } else {
  292. //if totallength is less than 128,
  293. //put it on a staging buffer
  294. TempBufLen = 128;
  295. if ((IPHLength + RcvSize) < 128) {
  296. TempBufLen = IPHLength + RcvSize;
  297. }
  298. TempBuf = CTEAllocMem(TempBufLen);
  299. if (TempBuf) {
  300. RtlCopyMemory(TempBuf, (uchar *) IPH, IPHLength);
  301. RtlCopyMemory((TempBuf + IPHLength), RcvBuf->ipr_buffer, (TempBufLen - IPHLength));
  302. }
  303. }
  304. IF_TCPDBG(TCP_DEBUG_RAW) {
  305. TCPTRACE(("Indicating %u bytes\n", IndicateSize));
  306. }
  307. UStats.us_indatagrams++;
  308. if (DeliverInfo->Flags & IS_BCAST) {
  309. // This flag is true if this is a multicast, subnet broadcast,
  310. // or broadcast. We need to differentiate to set the right
  311. // receive flags.
  312. //
  313. if (!CLASSD_ADDR(DeliverInfo->DestAddr)) {
  314. Flags |= TDI_RECEIVE_BROADCAST;
  315. }
  316. }
  317. // If the IP_PKTINFO option was set, then create the control
  318. // information to be passed to the handler. Currently only one
  319. // such option exists, so only one ancillary data object is
  320. // created. We should be able to support an array of them as
  321. // more options are added.
  322. //
  323. if (AO_PKTINFO(RcvAO)) {
  324. BufferToSend = DGFillIpPktInfo(DeliverInfo->DestAddr,
  325. DeliverInfo->LocalAddr,
  326. &BufferSize);
  327. if (BufferToSend) {
  328. // Set the receive flag so the receive handler knows
  329. // we are passing up control info.
  330. //
  331. Flags |= TDI_RECEIVE_CONTROL_INFO;
  332. }
  333. }
  334. if (TempBuf) {
  335. RcvStatus = (*RcvEvent) (RcvContext, TCP_TA_SIZE,
  336. (PTRANSPORT_ADDRESS) AddressBuffer,
  337. BufferSize,
  338. BufferToSend, Flags,
  339. TempBufLen,
  340. IPHLength + RcvSize, &BytesTaken,
  341. (uchar *) TempBuf, &ERB);
  342. CTEFreeMem(TempBuf);
  343. } else {
  344. RcvStatus = (*RcvEvent) (RcvContext, TCP_TA_SIZE,
  345. (PTRANSPORT_ADDRESS) AddressBuffer,
  346. BufferSize, BufferToSend, Flags,
  347. IndicateSize,
  348. IPHLength + RcvSize, &BytesTaken,
  349. (uchar *) IPH, &ERB);
  350. }
  351. if (BufferToSend) {
  352. ExFreePool(BufferToSend);
  353. }
  354. if (RcvStatus == TDI_MORE_PROCESSING) {
  355. ASSERT(ERB != NULL);
  356. // We were passed back a receive buffer. Copy the data in now.
  357. // He can't have taken more than was in the indicated
  358. // buffer, but in debug builds we'll check to make sure.
  359. ASSERT(BytesTaken <= RcvBuf->ipr_size);
  360. IF_TCPDBG(TCP_DEBUG_RAW) {
  361. TCPTRACE(("ind took %u bytes\n", BytesTaken));
  362. }
  363. {
  364. #if !MILLEN
  365. PIO_STACK_LOCATION IrpSp;
  366. PTDI_REQUEST_KERNEL_RECEIVEDG DatagramInformation;
  367. IrpSp = IoGetCurrentIrpStackLocation(ERB);
  368. DatagramInformation = (PTDI_REQUEST_KERNEL_RECEIVEDG)
  369. & (IrpSp->Parameters);
  370. DestBuf = ERB->MdlAddress;
  371. #else // !MILLEN
  372. DestBuf = ERB->erb_buffer;
  373. #endif // MILLEN
  374. DestOffset = 0;
  375. if (BytesTaken < IPHLength) {
  376. // Copy the rest of the IP header
  377. DestBuf = CopyFlatToNdis(
  378. DestBuf,
  379. (uchar *) IPH + BytesTaken,
  380. IPHLength - BytesTaken,
  381. &DestOffset,
  382. &RcvdSize
  383. );
  384. BytesTaken = 0;
  385. } else {
  386. BytesTaken -= IPHLength;
  387. RcvdSize = 0;
  388. }
  389. // Copy the data
  390. RcvdSize += CopyRcvToNdis(
  391. RcvBuf,
  392. DestBuf,
  393. RcvSize - BytesTaken,
  394. BytesTaken,
  395. DestOffset
  396. );
  397. IF_TCPDBG(TCP_DEBUG_RAW) {
  398. TCPTRACE(("Copied %u bytes\n", RcvdSize));
  399. }
  400. #if !MILLEN
  401. //
  402. // Update the return address info
  403. //
  404. RcvStatus = UpdateConnInfo(
  405. DatagramInformation->ReturnDatagramInformation,
  406. OptInfo, SrcIP, 0);
  407. //
  408. // Complete the IRP.
  409. //
  410. ERB->IoStatus.Information = RcvdSize;
  411. ERB->IoStatus.Status = RcvStatus;
  412. IoCompleteRequest(ERB, 2);
  413. #else // !MILLEN
  414. //
  415. // Call the completion routine.
  416. //
  417. (*ERB->erb_rtn) (ERB->erb_context, TDI_SUCCESS, RcvdSize);
  418. #endif // MILLEN
  419. }
  420. } else {
  421. ASSERT(
  422. (RcvStatus == TDI_SUCCESS) ||
  423. (RcvStatus == TDI_NOT_ACCEPTED)
  424. );
  425. IF_TCPDBG(TCP_DEBUG_RAW) {
  426. TCPTRACE((
  427. "Data %s taken\n",
  428. (RcvStatus == TDI_SUCCESS) ? "all" : "not"
  429. ));
  430. }
  431. ASSERT(ERB == NULL);
  432. }
  433. DELAY_DEREF_AO(RcvAO);
  434. return;
  435. } else
  436. UStats.us_inerrors++;
  437. // When we get here, we didn't have a buffer to put this data into.
  438. // Fall through to the return case.
  439. } else
  440. UStats.us_inerrors++;
  441. loop_exit:
  442. CTEFreeLock(&RcvAO->ao_lock, TableHandle);
  443. }
  444. //* RawRcv - Receive a Raw datagram.
  445. //
  446. // The routine called by IP when a Raw datagram arrived. We
  447. // look up the port/local address pair in our address table,
  448. // and deliver the data to a user if we find one. For broadcast
  449. // frames we may deliver it to multiple users.
  450. //
  451. // Entry: IPContext - IPContext identifying physical i/f that
  452. // received the data.
  453. // Dest - IPAddr of destionation.
  454. // Src - IPAddr of source.
  455. // LocalAddr - Local address of network which caused this to be
  456. // received.
  457. // SrcAddr - Address of local interface which received the packet
  458. // IPH - IP Header.
  459. // IPHLength - Bytes in IPH.
  460. // RcvBuf - Pointer to receive buffer chain containing data.
  461. // Size - Size in bytes of data received.
  462. // IsBCast - Boolean indicator of whether or not this came in as
  463. // a bcast.
  464. // Protocol - Protocol this came in on - should be Raw.
  465. // OptInfo - Pointer to info structure for received options.
  466. //
  467. // Returns: Status of reception. Anything other than IP_SUCCESS will cause
  468. // IP to send a 'port unreachable' message.
  469. //
  470. IP_STATUS
  471. RawRcv(void *IPContext, IPAddr Dest, IPAddr Src, IPAddr LocalAddr,
  472. IPAddr SrcAddr, IPHeader UNALIGNED * IPH, uint IPHLength, IPRcvBuf * RcvBuf,
  473. uint Size, uchar IsBCast, uchar Protocol, IPOptInfo * OptInfo)
  474. {
  475. CTELockHandle AOTableHandle;
  476. AddrObj *ReceiveingAO;
  477. uchar SrcType, DestType;
  478. AOSearchContextEx Search;
  479. IP_STATUS Status = IP_DEST_PROT_UNREACHABLE;
  480. ulong IsLocal = 0;
  481. uint IfIndex;
  482. uint Deliver;
  483. DGDeliverInfo DeliverInfo = {0};
  484. IF_TCPDBG(TCP_DEBUG_RAW) {
  485. TCPTRACE(("RawRcv prot %u size %u\n", IPH->iph_protocol, Size));
  486. }
  487. SrcType = (*LocalNetInfo.ipi_getaddrtype) (Src);
  488. DestType = (*LocalNetInfo.ipi_getaddrtype) (Dest);
  489. if (SrcType == DEST_LOCAL) {
  490. DeliverInfo.Flags |= SRC_LOCAL;
  491. }
  492. IfIndex = (*LocalNetInfo.ipi_getifindexfromnte) (IPContext, IF_CHECK_NONE);
  493. // The following code relies on DEST_INVALID being a broadcast dest type.
  494. // If this is changed the code here needs to change also.
  495. if (IS_BCAST_DEST(SrcType)) {
  496. if (!IP_ADDR_EQUAL(Src, NULL_IP_ADDR) || !IsBCast) {
  497. UStats.us_inerrors++;
  498. return IP_SUCCESS; // Bad src address.
  499. }
  500. }
  501. // Set the rest of our DeliverInfo for RawDeliver to consume.
  502. //
  503. DeliverInfo.Flags |= IsBCast ? IS_BCAST : 0;
  504. DeliverInfo.LocalAddr = LocalAddr;
  505. DeliverInfo.DestAddr = Dest;
  506. // Get the AddrObjTable lock, and then try to find some AddrObj(s) to give
  507. // this to. We deliver to all addr objs registered for the protocol and
  508. // address.
  509. CTEGetLock(&AddrObjTableLock.Lock, &AOTableHandle);
  510. if (!SecurityFilteringEnabled ||
  511. IsPermittedSecurityFilter(SrcAddr, IPContext, PROTOCOL_RAW, Protocol)
  512. || (RcvBuf->ipr_flags & IPR_FLAG_PROMISCUOUS)) {
  513. ReceiveingAO = GetFirstAddrObjEx(
  514. LocalAddr,
  515. 0, // port is zero
  516. Protocol,
  517. IfIndex,
  518. &Search
  519. );
  520. if (ReceiveingAO != NULL) {
  521. do {
  522. // Default behavior is not to deliver unless requested
  523. Deliver = FALSE;
  524. // Deliver if socket is bound/joined appropriately
  525. // Case 1: bound to destination IP address
  526. // Case 2: bound to INADDR_ANY (but not ifindex)
  527. // Case 3: bound to ifindex
  528. if ((IP_ADDR_EQUAL(ReceiveingAO->ao_addr, LocalAddr) ||
  529. ((ReceiveingAO->ao_bindindex == 0) &&
  530. (IP_ADDR_EQUAL(ReceiveingAO->ao_addr, NULL_IP_ADDR))) ||
  531. (ReceiveingAO->ao_bindindex == IfIndex)) &&
  532. ((ReceiveingAO->ao_prot == IPH->iph_protocol) ||
  533. (ReceiveingAO->ao_prot == Protocol) ||
  534. (ReceiveingAO->ao_prot == 0))) {
  535. switch(DestType) {
  536. case DEST_LOCAL:
  537. Deliver = TRUE;
  538. break;
  539. case DEST_MCAST:
  540. Deliver = MCastAddrOnAO(ReceiveingAO, Dest, Src);
  541. break;
  542. }
  543. }
  544. // Otherwise, see whether AO is promiscuous
  545. if (!Deliver &&
  546. (IfIndex == ReceiveingAO->ao_promis_ifindex)) {
  547. if (ReceiveingAO->ao_rcvall &&
  548. ((ReceiveingAO->ao_prot == IPH->iph_protocol) ||
  549. (ReceiveingAO->ao_prot == Protocol) ||
  550. (ReceiveingAO->ao_prot == 0))) {
  551. Deliver = TRUE;
  552. } else if ((ReceiveingAO->ao_rcvall_mcast) &&
  553. CLASSD_ADDR(Dest) &&
  554. ((ReceiveingAO->ao_prot == IPH->iph_protocol) ||
  555. (ReceiveingAO->ao_prot == Protocol) ||
  556. (ReceiveingAO->ao_prot == 0))) {
  557. Deliver = TRUE;
  558. } else if ((ReceiveingAO->ao_absorb_rtralert) &&
  559. ((*LocalNetInfo.ipi_isrtralertpacket) (IPH))) {
  560. Deliver = TRUE;
  561. }
  562. }
  563. if (Deliver) {
  564. RawDeliver(
  565. ReceiveingAO, Src, IPH, IPHLength, RcvBuf, Size,
  566. OptInfo, AOTableHandle, &DeliverInfo
  567. );
  568. // RawDeliver frees the lock so we have to get it back
  569. CTEGetLock(&AddrObjTableLock.Lock, &AOTableHandle);
  570. }
  571. ReceiveingAO = GetNextAddrObjEx(&Search);
  572. } while (ReceiveingAO != NULL);
  573. Status = IP_SUCCESS;
  574. } else {
  575. UStats.us_noports++;
  576. }
  577. }
  578. CTEFreeLock(&AddrObjTableLock.Lock, AOTableHandle);
  579. return Status;
  580. }
  581. //* RawStatus - Handle a status indication.
  582. //
  583. // This is the Raw status handler, called by IP when a status event
  584. // occurs. For most of these we do nothing. For certain severe status
  585. // events we will mark the local address as invalid.
  586. //
  587. // Entry: StatusType - Type of status (NET or HW). NET status
  588. // is usually caused by a received ICMP
  589. // message. HW status indicate a HW
  590. // problem.
  591. // StatusCode - Code identifying IP_STATUS.
  592. // OrigDest - If this is NET status, the original dest. of
  593. // DG that triggered it.
  594. // OrigSrc - " " " " " , the original src.
  595. // Src - IP address of status originator (could be local
  596. // or remote).
  597. // Param - Additional information for status - i.e. the
  598. // param field of an ICMP message.
  599. // Data - Data pertaining to status - for NET status, this
  600. // is the first 8 bytes of the original DG.
  601. //
  602. // Returns: Nothing
  603. //
  604. void
  605. RawStatus(uchar StatusType, IP_STATUS StatusCode, IPAddr OrigDest,
  606. IPAddr OrigSrc, IPAddr Src, ulong Param, void *Data)
  607. {
  608. IF_TCPDBG(TCP_DEBUG_RAW) {
  609. TCPTRACE(("RawStatus called\n"));
  610. }
  611. // If this is a HW status, it could be because we've had an address go
  612. // away.
  613. if (StatusType == IP_HW_STATUS) {
  614. if (StatusCode == IP_ADDR_DELETED) {
  615. // An address has gone away. OrigDest identifies the address.
  616. //
  617. // Delete any security filters associated with this address
  618. //
  619. DeleteProtocolSecurityFilter(OrigDest, PROTOCOL_RAW);
  620. return;
  621. }
  622. if (StatusCode == IP_ADDR_ADDED) {
  623. //
  624. // An address has materialized. OrigDest identifies the address.
  625. // Data is a handle to the IP configuration information for the
  626. // interface on which the address is instantiated.
  627. //
  628. AddProtocolSecurityFilter(OrigDest, PROTOCOL_RAW,
  629. (NDIS_HANDLE) Data);
  630. return;
  631. }
  632. }
  633. }