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.

1153 lines
43 KiB

  1. /*******************************************************************/
  2. /** Microsoft LAN Manager **/
  3. /** Copyright(c) Microsoft Corp., 1990-1993 **/
  4. /********************************************************************/
  5. /* :ts=4 */
  6. //** UDP.C - UDP protocol code.
  7. //
  8. // This file contains the code for the UDP protocol functions,
  9. // principally send and receive datagram.
  10. //
  11. #include "precomp.h"
  12. #include "addr.h"
  13. #include "udp.h"
  14. #include "tlcommon.h"
  15. #include "info.h"
  16. #include "tcpcfg.h"
  17. #include "secfltr.h"
  18. #include "tcpipbuf.h"
  19. #if GPC
  20. #include "qos.h"
  21. #include "traffic.h"
  22. #include "gpcifc.h"
  23. #include "ntddtc.h"
  24. extern GPC_HANDLE hGpcClient[];
  25. extern ULONG GpcCfCounts[];
  26. extern GPC_EXPORTED_CALLS GpcEntries;
  27. extern ULONG GPCcfInfo;
  28. extern ULONG ServiceTypeOffset;
  29. #endif
  30. NTSTATUS
  31. GetIFAndLink(void *Rce, UINT * IFIndex, IPAddr * NextHop);
  32. extern ulong DisableUserTOSSetting;
  33. ulong Fastpath = 0;
  34. void *UDPProtInfo = NULL;
  35. extern IPInfo LocalNetInfo;
  36. extern
  37. TDI_STATUS
  38. MapIPError(IP_STATUS IPError, TDI_STATUS Default);
  39. #undef SrcPort
  40. //
  41. // UDPDeliver - Deliver a datagram to a user.
  42. //
  43. // This routine delivers a datagram to a UDP user. We're called with
  44. // the AddrObj to deliver on, and with the AddrObjTable lock held.
  45. // We try to find a receive on the specified AddrObj, and if we do
  46. // we remove it and copy the data into the buffer. Otherwise we'll
  47. // call the receive datagram event handler, if there is one. If that
  48. // fails we'll discard the datagram.
  49. //
  50. // Input: RcvAO - AO to receive the datagram.
  51. // SrcIP - Source IP address of datagram.
  52. // SrcPort - Source port of datagram.
  53. // RcvBuf - The IPReceive buffer containing the data.
  54. // RcvSize - Size received, including the UDP header.
  55. // TableHandle - Lock handle for AddrObj table.
  56. // DeliverInfo - Information about the recieved packet.
  57. //
  58. // Returns: Nothing.
  59. //
  60. void
  61. UDPDeliver(AddrObj * RcvAO, IPAddr SrcIP, ushort SrcPort, IPRcvBuf * RcvBuf,
  62. uint RcvSize, IPOptInfo * OptInfo, CTELockHandle TableHandle,
  63. DGDeliverInfo * DeliverInfo)
  64. {
  65. Queue *CurrentQ;
  66. CTELockHandle AOHandle;
  67. DGRcvReq *RcvReq;
  68. uint BytesTaken = 0;
  69. uchar AddressBuffer[TCP_TA_SIZE];
  70. uint RcvdSize;
  71. EventRcvBuffer *ERB = NULL;
  72. UDPHeader UNALIGNED *UH;
  73. #if TRACE_EVENT
  74. PTDI_DATA_REQUEST_NOTIFY_ROUTINE CPCallBack;
  75. WMIData WMIInfo;
  76. #endif
  77. BOOLEAN FreeBuffer = FALSE;
  78. int BufferSize;
  79. PVOID BufferToSend = NULL;
  80. DEBUGMSG(DBG_TRACE && DBG_UDP && DBG_RX,
  81. (DTEXT("+UDPDeliver(%x, %x, %x, %x, %d, %x...)\n"),
  82. RcvAO, SrcIP, SrcPort, RcvBuf, RcvSize, OptInfo));
  83. CTEStructAssert(RcvAO, ao);
  84. CTEGetLock(&RcvAO->ao_lock, &AOHandle);
  85. CTEFreeLock(&AddrObjTableLock.Lock, AOHandle);
  86. //UH = (UDPHeader *) RcvBuf->ipr_buffer;
  87. if (DeliverInfo->Flags & NEED_CHECKSUM) {
  88. if (XsumRcvBuf(PHXSUM(SrcIP, DeliverInfo->DestAddr, PROTOCOL_UDP, RcvSize), RcvBuf) != 0xffff) {
  89. UStats.us_inerrors++;
  90. DeliverInfo->Flags &= ~NEED_CHECKSUM;
  91. CTEFreeLock(&RcvAO->ao_lock, TableHandle);
  92. return; // Checksum failed.
  93. }
  94. }
  95. if (AO_VALID(RcvAO)) {
  96. //By default broadcast rcv is set on AO
  97. if ((DeliverInfo->Flags & IS_BCAST) && !AO_BROADCAST(RcvAO)) {
  98. goto loop_exit;
  99. }
  100. if ((DeliverInfo->Flags & IS_BCAST) && (DeliverInfo->Flags & SRC_LOCAL)
  101. && (RcvAO->ao_mcast_loop == 0)) {
  102. goto loop_exit;
  103. }
  104. CurrentQ = QHEAD(&RcvAO->ao_rcvq);
  105. // Walk the list, looking for a receive buffer that matches.
  106. while (CurrentQ != QEND(&RcvAO->ao_rcvq)) {
  107. RcvReq = QSTRUCT(DGRcvReq, CurrentQ, drr_q);
  108. CTEStructAssert(RcvReq, drr);
  109. // If this request is a wildcard request, or matches the source IP
  110. // address, check the port.
  111. if (IP_ADDR_EQUAL(RcvReq->drr_addr, NULL_IP_ADDR) ||
  112. IP_ADDR_EQUAL(RcvReq->drr_addr, SrcIP)) {
  113. // The local address matches, check the port. We'll match
  114. // either 0 or the actual port.
  115. if (RcvReq->drr_port == 0 || RcvReq->drr_port == SrcPort) {
  116. TDI_STATUS Status;
  117. // The ports matched. Remove this from the queue.
  118. REMOVEQ(&RcvReq->drr_q);
  119. // We're done. We can free the AddrObj lock now.
  120. CTEFreeLock(&RcvAO->ao_lock, TableHandle);
  121. // Call CopyRcvToNdis, and then complete the request.
  122. //KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "RcvAO %x rcvbuf %x size %x\n",RcvAO,RcvReq->drr_buffer,
  123. // RcvReq->drr_size));
  124. RcvdSize = CopyRcvToNdis(RcvBuf, RcvReq->drr_buffer,
  125. RcvReq->drr_size, sizeof(UDPHeader), 0);
  126. ASSERT(RcvdSize <= RcvReq->drr_size);
  127. Status = UpdateConnInfo(RcvReq->drr_conninfo, OptInfo,
  128. SrcIP, SrcPort);
  129. UStats.us_indatagrams++;
  130. #if TRACE_EVENT
  131. CPCallBack = TCPCPHandlerRoutine;
  132. if (CPCallBack != NULL) {
  133. ulong GroupType;
  134. WMIInfo.wmi_srcport = SrcPort;
  135. WMIInfo.wmi_srcaddr = SrcIP;
  136. WMIInfo.wmi_destport = DeliverInfo->DestPort;
  137. WMIInfo.wmi_destaddr = DeliverInfo->DestAddr;
  138. WMIInfo.wmi_size = RcvdSize;
  139. WMIInfo.wmi_context = RcvAO->ao_owningpid;
  140. GroupType = EVENT_TRACE_GROUP_UDPIP + EVENT_TRACE_TYPE_RECEIVE;
  141. (*CPCallBack)( GroupType, (PVOID) &WMIInfo, sizeof(WMIInfo), NULL);
  142. }
  143. #endif
  144. DEBUGMSG(DBG_INFO && DBG_UDP && DBG_RX,
  145. (DTEXT("UDPDeliver completing RcvReq %x for Ao %x.\n"),
  146. RcvReq, RcvAO));
  147. (*RcvReq->drr_rtn) (RcvReq->drr_context, Status, RcvdSize);
  148. FreeDGRcvReq(RcvReq);
  149. return;
  150. }
  151. }
  152. // Either the IP address or the port didn't match. Get the next
  153. // one.
  154. CurrentQ = QNEXT(CurrentQ);
  155. }
  156. // We've walked the list, and not found a buffer. Call the recv.
  157. // handler now.
  158. if (RcvAO->ao_rcvdg != NULL) {
  159. PRcvDGEvent RcvEvent = RcvAO->ao_rcvdg;
  160. PVOID RcvContext = RcvAO->ao_rcvdgcontext;
  161. TDI_STATUS RcvStatus;
  162. CTELockHandle OldLevel;
  163. ULONG Flags = TDI_RECEIVE_COPY_LOOKAHEAD;
  164. REF_AO(RcvAO);
  165. CTEFreeLock(&RcvAO->ao_lock, TableHandle);
  166. BuildTDIAddress(AddressBuffer, SrcIP, SrcPort);
  167. UStats.us_indatagrams++;
  168. if (DeliverInfo->Flags & IS_BCAST) {
  169. // This flag is true if this is a multicast, subnet broadcast,
  170. // or broadcast. We need to differentiate to set the right
  171. // receive flags.
  172. //
  173. if (!CLASSD_ADDR(DeliverInfo->DestAddr)) {
  174. Flags |= TDI_RECEIVE_BROADCAST;
  175. }
  176. }
  177. // Set the buffer variables that we will send to the
  178. // receive event handler. These may change if we find
  179. // any socket option that requires ancillary data to be
  180. // passed to the handler.
  181. //
  182. BufferToSend = OptInfo->ioi_options;
  183. BufferSize = OptInfo->ioi_optlength;
  184. // If the IP_PKTINFO option was set, then create the control
  185. // information to be passed to the handler. Currently only one
  186. // such option exists, so only one ancillary data object is
  187. // created. We should be able to support an array of them as
  188. // more options are added.
  189. //
  190. if (AO_PKTINFO(RcvAO)) {
  191. BufferToSend = DGFillIpPktInfo(DeliverInfo->DestAddr,
  192. DeliverInfo->LocalAddr,
  193. &BufferSize);
  194. if (BufferToSend) {
  195. FreeBuffer = TRUE;
  196. // Set the receive flag so the receive handler knows
  197. // we are passing up control info.
  198. //
  199. Flags |= TDI_RECEIVE_CONTROL_INFO;
  200. }
  201. }
  202. DEBUGMSG(DBG_INFO && DBG_UDP && DBG_RX,
  203. (DTEXT("UDPDeliver: calling Event %x for Ao %x\n"), RcvEvent, RcvAO));
  204. RcvStatus = (*RcvEvent) (RcvContext, TCP_TA_SIZE,
  205. (PTRANSPORT_ADDRESS) AddressBuffer, BufferSize,
  206. BufferToSend, Flags,
  207. RcvBuf->ipr_size - sizeof(UDPHeader),
  208. RcvSize - sizeof(UDPHeader), &BytesTaken,
  209. RcvBuf->ipr_buffer + sizeof(UDPHeader), &ERB);
  210. if (FreeBuffer) {
  211. ExFreePool(BufferToSend);
  212. }
  213. DEBUGMSG(DBG_INFO && DBG_UDP && DBG_RX,
  214. (DTEXT("UDPDeliver: Event status for AO %x: %x \n"), RcvAO, RcvStatus));
  215. if (RcvStatus == TDI_MORE_PROCESSING) {
  216. ASSERT(ERB != NULL);
  217. // We were passed back a receive buffer. Copy the data in now.
  218. // He can't have taken more than was in the indicated
  219. // buffer, but in debug builds we'll check to make sure.
  220. ASSERT(BytesTaken <= (RcvBuf->ipr_size - sizeof(UDPHeader)));
  221. #if !MILLEN
  222. {
  223. PIO_STACK_LOCATION IrpSp;
  224. PTDI_REQUEST_KERNEL_RECEIVEDG DatagramInformation;
  225. IrpSp = IoGetCurrentIrpStackLocation(ERB);
  226. DatagramInformation = (PTDI_REQUEST_KERNEL_RECEIVEDG)
  227. & (IrpSp->Parameters);
  228. //
  229. // Copy the remaining data to the IRP.
  230. //
  231. RcvdSize = CopyRcvToMdl(RcvBuf, ERB->MdlAddress,
  232. RcvSize - sizeof(UDPHeader) - BytesTaken,
  233. sizeof(UDPHeader) + BytesTaken, 0);
  234. //
  235. // Update the return address info
  236. //
  237. RcvStatus = UpdateConnInfo(
  238. DatagramInformation->ReturnDatagramInformation,
  239. OptInfo, SrcIP, SrcPort);
  240. //
  241. // Complete the IRP.
  242. //
  243. ERB->IoStatus.Information = RcvdSize;
  244. ERB->IoStatus.Status = RcvStatus;
  245. #if TRACE_EVENT
  246. // Calling before Irp Completion. Irp could go away otherwise.
  247. CPCallBack = TCPCPHandlerRoutine;
  248. if (CPCallBack!=NULL) {
  249. ulong GroupType;
  250. WMIInfo.wmi_srcport = SrcPort;
  251. WMIInfo.wmi_srcaddr = SrcIP;
  252. WMIInfo.wmi_destport = DeliverInfo->DestPort;
  253. WMIInfo.wmi_destaddr = DeliverInfo->DestAddr;
  254. WMIInfo.wmi_context = RcvAO->ao_owningpid;
  255. WMIInfo.wmi_size = (ushort)RcvdSize + BytesTaken;
  256. GroupType = EVENT_TRACE_GROUP_UDPIP + EVENT_TRACE_TYPE_RECEIVE;
  257. (*CPCallBack)( GroupType, (PVOID) &WMIInfo, sizeof(WMIInfo), NULL);
  258. }
  259. #endif
  260. IoCompleteRequest(ERB, 2);
  261. }
  262. #else // !MILLEN
  263. RcvdSize = CopyRcvToNdis(RcvBuf, ERB->erb_buffer,
  264. RcvSize - sizeof(UDPHeader) - BytesTaken,
  265. sizeof(UDPHeader) + BytesTaken, 0);
  266. //
  267. // Call the completion routine.
  268. //
  269. (*ERB->erb_rtn)(ERB->erb_context, TDI_SUCCESS, RcvdSize);
  270. #endif // MILLEN
  271. } else {
  272. DEBUGMSG(DBG_WARN && RcvStatus != TDI_SUCCESS && RcvStatus != TDI_NOT_ACCEPTED,
  273. (DTEXT("WARN> UDPDgRcvHandler returned %x\n"), RcvStatus));
  274. ASSERT(
  275. (RcvStatus == TDI_SUCCESS) ||
  276. (RcvStatus == TDI_NOT_ACCEPTED)
  277. );
  278. ASSERT(ERB == NULL);
  279. #if TRACE_EVENT
  280. CPCallBack = TCPCPHandlerRoutine;
  281. if (CPCallBack != NULL){
  282. ulong GroupType;
  283. WMIInfo.wmi_srcport = SrcPort;
  284. WMIInfo.wmi_srcaddr = SrcIP;
  285. WMIInfo.wmi_destport = DeliverInfo->DestPort;
  286. WMIInfo.wmi_destaddr = DeliverInfo->DestAddr;
  287. WMIInfo.wmi_context = RcvAO->ao_owningpid;
  288. WMIInfo.wmi_size = (ushort)BytesTaken;
  289. GroupType = EVENT_TRACE_GROUP_UDPIP + EVENT_TRACE_TYPE_RECEIVE;
  290. (*CPCallBack)( GroupType, (PVOID)(&WMIInfo), sizeof(WMIInfo), NULL);
  291. }
  292. #endif
  293. }
  294. DELAY_DEREF_AO(RcvAO);
  295. return;
  296. } else
  297. UStats.us_inerrors++;
  298. // When we get here, we didn't have a buffer to put this data into.
  299. // Fall through to the return case.
  300. } else
  301. UStats.us_inerrors++;
  302. loop_exit:
  303. CTEFreeLock(&RcvAO->ao_lock, TableHandle);
  304. }
  305. //** UDPSend - Send a datagram.
  306. //
  307. // The real send datagram routine. We assume that the busy bit is
  308. // set on the input AddrObj, and that the address of the SendReq
  309. // has been verified.
  310. //
  311. // We start by sending the input datagram, and we loop until there's
  312. // nothing left on the send q.
  313. //
  314. // Input: SrcAO - Pointer to AddrObj doing the send.
  315. // SendReq - Pointer to sendreq describing send.
  316. //
  317. // Returns: Nothing
  318. //
  319. void
  320. UDPSend(AddrObj * SrcAO, DGSendReq * SendReq)
  321. {
  322. UDPHeader *UH;
  323. PNDIS_BUFFER UDPBuffer;
  324. CTELockHandle AOHandle;
  325. RouteCacheEntry *RCE; // RCE used for each send.
  326. IPAddr SrcAddr; // Source address IP thinks we should
  327. // use.
  328. IPAddr DestAddr;
  329. ushort DestPort;
  330. uchar DestType; // Type of destination address.
  331. ushort UDPXsum; // Checksum of packet.
  332. ushort SendSize; // Size we're sending.
  333. IP_STATUS SendStatus; // Status of send attempt.
  334. ushort MSS;
  335. uint AddrValid;
  336. IPOptInfo OptInfo;
  337. IPAddr OrigSrc;
  338. BOOLEAN SlowPath = FALSE;
  339. CTEStructAssert(SrcAO, ao);
  340. ASSERT(SrcAO->ao_usecnt != 0);
  341. //* Loop while we have something to send, and can get
  342. // resources to send.
  343. for (;;) {
  344. BOOLEAN CachedRCE = FALSE;
  345. CTEStructAssert(SendReq, dsr);
  346. // Make sure we have a UDP header buffer for this send. If we
  347. // don't, try to get one.
  348. if ((UDPBuffer = SendReq->dsr_header) == NULL) {
  349. // Don't have one, so try to get one.
  350. UDPBuffer = GetDGHeader(&UH);
  351. if (UDPBuffer != NULL) {
  352. SendReq->dsr_header = UDPBuffer;
  353. } else {
  354. // Couldn't get a header buffer. Push the send request
  355. // back on the queue, and queue the addr object for when
  356. // we get resources.
  357. CTEGetLock(&SrcAO->ao_lock, &AOHandle);
  358. PUSHQ(&SrcAO->ao_sendq, &SendReq->dsr_q);
  359. PutPendingQ(SrcAO);
  360. CTEFreeLock(&SrcAO->ao_lock, AOHandle);
  361. return;
  362. }
  363. }
  364. // At this point, we have the buffer we need. Call IP to get an
  365. // RCE (along with the source address if we need it), then compute
  366. // the checksum and send the data.
  367. ASSERT(UDPBuffer != NULL);
  368. if (!CLASSD_ADDR(SendReq->dsr_addr)) {
  369. // This isn't a multicast send, so we'll use the ordinary
  370. // information.
  371. OrigSrc = SrcAO->ao_addr;
  372. OptInfo = SrcAO->ao_opt;
  373. } else {
  374. OrigSrc = SrcAO->ao_mcastaddr;
  375. OptInfo = SrcAO->ao_mcastopt;
  376. }
  377. //KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "udpsend: ao %x, %x %x %x\n", SrcAO, SendReq, SendReq->dsr_addr,SendReq->dsr_port));
  378. if (!(SrcAO->ao_flags & AO_DHCP_FLAG)) {
  379. if (AO_CONNUDP(SrcAO) && SrcAO->ao_rce) {
  380. if (SrcAO->ao_rce->rce_flags & RCE_VALID) {
  381. SrcAddr = SrcAO->ao_rcesrc;
  382. RCE = SrcAO->ao_rce;
  383. CachedRCE = TRUE;
  384. } else {
  385. // Close the invalid RCE, and reset the cached information
  386. CTEGetLock(&SrcAO->ao_lock, &AOHandle);
  387. RCE = SrcAO->ao_rce;
  388. SrcAO->ao_rce = NULL;
  389. SrcAO->ao_rcesrc = NULL_IP_ADDR;
  390. CTEFreeLock(&SrcAO->ao_lock, AOHandle);
  391. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  392. "udpsend: closing old RCE %x %x\n",
  393. SrcAO, RCE));
  394. (*LocalNetInfo.ipi_closerce) (RCE);
  395. // retrieve the destination address to which the socket
  396. // is connected, and use it to open a new RCE, if possible.
  397. // N.B. we always open an RCE to the *connected* destination,
  398. // rather than the destination to which the user is currently
  399. // sending.
  400. GetAddress((PTRANSPORT_ADDRESS) SrcAO->ao_RemoteAddress,
  401. &DestAddr, &DestPort);
  402. SrcAddr = (*LocalNetInfo.ipi_openrce) (DestAddr, OrigSrc,
  403. &RCE, &DestType,
  404. &MSS, &OptInfo);
  405. if (!IP_ADDR_EQUAL(SrcAddr, NULL_IP_ADDR)) {
  406. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  407. "udpsend: storing new RCE %x %x\n",
  408. SrcAO, RCE));
  409. CTEGetLock(&SrcAO->ao_lock, &AOHandle);
  410. SrcAO->ao_rce = RCE;
  411. SrcAO->ao_rcesrc = SrcAddr;
  412. CachedRCE = TRUE;
  413. CTEFreeLock(&SrcAO->ao_lock, AOHandle);
  414. }
  415. }
  416. IF_TCPDBG(TCP_DEBUG_CONUDP)
  417. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  418. "udpsend: ao %x, %x %x %x %x\n", SrcAO,
  419. SrcAddr, SrcAO->ao_port, SendReq->dsr_addr,
  420. SendReq->dsr_port));
  421. Fastpath++;
  422. } else { // unconnected
  423. if ((OptInfo.ioi_mcastif) && CLASSD_ADDR(SendReq->dsr_addr)) {
  424. // mcast_if is set and this is a mcast send
  425. ASSERT(IP_ADDR_EQUAL(OrigSrc, NULL_IP_ADDR));
  426. SrcAddr = (*LocalNetInfo.ipi_isvalidindex) (OptInfo.ioi_mcastif);
  427. // go thru slow path
  428. RCE = NULL;
  429. } else {
  430. SrcAddr = (*LocalNetInfo.ipi_openrce) (SendReq->dsr_addr,
  431. OrigSrc, &RCE,
  432. &DestType, &MSS,
  433. &OptInfo);
  434. }
  435. }
  436. AddrValid = !IP_ADDR_EQUAL(SrcAddr, NULL_IP_ADDR);
  437. IF_TCPDBG(TCP_DEBUG_CONUDP)
  438. if (!AddrValid) {
  439. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "udpsend: addrinvalid!!\n"));
  440. }
  441. } else {
  442. // This is a DHCP send. He really wants to send from the
  443. // NULL IP address.
  444. SrcAddr = NULL_IP_ADDR;
  445. RCE = NULL;
  446. AddrValid = TRUE;
  447. }
  448. if (AddrValid) {
  449. //
  450. // clear the precedence bits and get ready to be set
  451. // according to the service type
  452. //
  453. if (DisableUserTOSSetting)
  454. OptInfo.ioi_tos &= TOS_MASK;
  455. #if GPC
  456. if (RCE && GPCcfInfo) {
  457. //
  458. // we'll fall into here only if the GPC client is there
  459. // and there is at least one CF_INFO_QOS installed
  460. // (counted by GPCcfInfo).
  461. //
  462. GPC_STATUS status = STATUS_SUCCESS;
  463. ulong ServiceType = 0;
  464. GPC_IP_PATTERN Pattern;
  465. //
  466. // if the packet is being sent to a different destination,
  467. // invalidate the classification handle (CH), to force a database search.
  468. // o/w, just call to classify with the current CH
  469. //
  470. if (SrcAO->ao_destaddr != SendReq->dsr_addr ||
  471. SrcAO->ao_destport != SendReq->dsr_port) {
  472. SrcAO->ao_GPCHandle = 0;
  473. }
  474. //
  475. // set the pattern
  476. //
  477. IF_TCPDBG(TCP_DEBUG_GPC)
  478. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "UDPSend: Classifying dgram ao %x\n", SrcAO));
  479. Pattern.SrcAddr = SrcAddr;
  480. Pattern.DstAddr = SendReq->dsr_addr;
  481. Pattern.ProtocolId = SrcAO->ao_prot;
  482. Pattern.gpcSrcPort = SrcAO->ao_port;
  483. Pattern.gpcDstPort = SendReq->dsr_port;
  484. if (SrcAO->ao_GPCCachedRTE != (void *)RCE->rce_rte) {
  485. //
  486. // first time we use this RTE, or it has been changed
  487. // since the last send
  488. //
  489. if (GetIFAndLink(RCE,
  490. &SrcAO->ao_GPCCachedIF,
  491. (IPAddr *) & SrcAO->ao_GPCCachedLink) == STATUS_SUCCESS) {
  492. SrcAO->ao_GPCCachedRTE = (void *)RCE->rce_rte;
  493. }
  494. //
  495. // invaludate the classification handle
  496. //
  497. SrcAO->ao_GPCHandle = 0;
  498. }
  499. Pattern.InterfaceId.InterfaceId = SrcAO->ao_GPCCachedIF;
  500. Pattern.InterfaceId.LinkId = SrcAO->ao_GPCCachedLink;
  501. IF_TCPDBG(TCP_DEBUG_GPC)
  502. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "UDPSend: IF=%x Link=%x\n",
  503. Pattern.InterfaceId.InterfaceId,
  504. Pattern.InterfaceId.LinkId));
  505. if (!SrcAO->ao_GPCHandle) {
  506. IF_TCPDBG(TCP_DEBUG_GPC)
  507. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "UDPsend: Classification Handle is NULL, getting one now.\n"));
  508. status = GpcEntries.GpcClassifyPatternHandler(
  509. hGpcClient[GPC_CF_QOS],
  510. GPC_PROTOCOL_TEMPLATE_IP,
  511. &Pattern,
  512. NULL, // context
  513. &SrcAO->ao_GPCHandle,
  514. 0,
  515. NULL,
  516. FALSE
  517. );
  518. }
  519. //
  520. // Only if QOS patterns exist, we get the TOS bits out.
  521. //
  522. if (NT_SUCCESS(status) && GpcCfCounts[GPC_CF_QOS]) {
  523. status = GpcEntries.GpcGetUlongFromCfInfoHandler(
  524. hGpcClient[GPC_CF_QOS],
  525. SrcAO->ao_GPCHandle,
  526. ServiceTypeOffset,
  527. &ServiceType
  528. );
  529. //
  530. // It is likely that the pattern has gone by now
  531. // and the handle that we are caching is INVALID.
  532. // We need to pull up a new handle and get the
  533. // TOS bit again.
  534. //
  535. if (STATUS_INVALID_HANDLE == status) {
  536. IF_TCPDBG(TCP_DEBUG_GPC)
  537. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "UDPsend: RE-Classification is required.\n"));
  538. SrcAO->ao_GPCHandle = 0;
  539. status = GpcEntries.GpcClassifyPatternHandler(
  540. hGpcClient[GPC_CF_QOS],
  541. GPC_PROTOCOL_TEMPLATE_IP,
  542. &Pattern,
  543. NULL, // context
  544. &SrcAO->ao_GPCHandle,
  545. 0,
  546. NULL,
  547. FALSE
  548. );
  549. //
  550. // Only if QOS patterns exist, we get the TOS bits out.
  551. //
  552. if (NT_SUCCESS(status) && GpcCfCounts[GPC_CF_QOS]) {
  553. status = GpcEntries.GpcGetUlongFromCfInfoHandler(
  554. hGpcClient[GPC_CF_QOS],
  555. SrcAO->ao_GPCHandle,
  556. ServiceTypeOffset,
  557. &ServiceType
  558. );
  559. }
  560. }
  561. }
  562. //
  563. // Perhaps something needs to be done if GPC_CF_IPSEC has non-zero patterns.
  564. //
  565. IF_TCPDBG(TCP_DEBUG_GPC)
  566. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "UDPsend: ServiceType(%d)=%d\n", ServiceTypeOffset, ServiceType));
  567. SrcAO->ao_opt.ioi_GPCHandle =
  568. SrcAO->ao_mcastopt.ioi_GPCHandle = (int)SrcAO->ao_GPCHandle;
  569. IF_TCPDBG(TCP_DEBUG_GPC)
  570. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "UDPSend:Got CH %x\n", SrcAO->ao_GPCHandle));
  571. if (status == STATUS_SUCCESS) {
  572. SrcAO->ao_destaddr = SendReq->dsr_addr;
  573. SrcAO->ao_destport = SendReq->dsr_port;
  574. } else {
  575. IF_TCPDBG(TCP_DEBUG_GPC)
  576. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "UDPSend: no service type found, dstip=%x, dstport=%d\n",
  577. SendReq->dsr_addr, SendReq->dsr_port));
  578. }
  579. IF_TCPDBG(TCP_DEBUG_GPC)
  580. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "UDPsend: ServiceType=%d\n", ServiceType));
  581. if (status == STATUS_SUCCESS) {
  582. OptInfo.ioi_tos |= ServiceType;
  583. }
  584. // Copy GPCHandle in the local option info.
  585. OptInfo.ioi_GPCHandle = SrcAO->ao_opt.ioi_GPCHandle;
  586. IF_TCPDBG(TCP_DEBUG_GPC)
  587. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "UDPsend: TOS set to 0x%x\n", OptInfo.ioi_tos));
  588. } // if (RCE && GPCcfInfo)
  589. #endif
  590. // The OpenRCE worked. Compute the checksum, and send it.
  591. if (!IP_ADDR_EQUAL(OrigSrc, NULL_IP_ADDR))
  592. SrcAddr = OrigSrc;
  593. UH = TcpipBufferVirtualAddress(UDPBuffer, NormalPagePriority);
  594. if (UH == NULL) {
  595. SendStatus = IP_NO_RESOURCES;
  596. } else {
  597. UH = (UDPHeader *) ((PUCHAR) UH + LocalNetInfo.ipi_hsize);
  598. NdisAdjustBufferLength(UDPBuffer, sizeof(UDPHeader));
  599. NDIS_BUFFER_LINKAGE(UDPBuffer) = SendReq->dsr_buffer;
  600. UH->uh_src = SrcAO->ao_port;
  601. UH->uh_dest = SendReq->dsr_port;
  602. SendSize = SendReq->dsr_size + sizeof(UDPHeader);
  603. UH->uh_length = net_short(SendSize);
  604. UH->uh_xsum = 0;
  605. if (AO_XSUM(SrcAO)) {
  606. // Compute the header xsum, and then call XsumNdisChain
  607. UDPXsum = XsumSendChain(PHXSUM(SrcAddr, SendReq->dsr_addr,
  608. PROTOCOL_UDP, SendSize), UDPBuffer);
  609. // We need to negate the checksum, unless it's already all
  610. // ones. In that case negating it would take it to 0, and
  611. // then we'd have to set it back to all ones.
  612. if (UDPXsum != 0xffff)
  613. UDPXsum = ~UDPXsum;
  614. UH->uh_xsum = UDPXsum;
  615. }
  616. // We've computed the xsum. Now send the packet.
  617. UStats.us_outdatagrams++;
  618. #if TRACE_EVENT
  619. SendReq->dsr_pid = SrcAO->ao_owningpid;
  620. SendReq->dsr_srcaddr = SrcAddr;
  621. SendReq->dsr_srcport = SrcAO->ao_port;
  622. #endif
  623. SendStatus = (*LocalNetInfo.ipi_xmit) (UDPProtInfo, SendReq,
  624. UDPBuffer, (uint) SendSize, SendReq->dsr_addr, SrcAddr,
  625. &OptInfo, RCE, PROTOCOL_UDP, SendReq->dsr_context);
  626. }
  627. if (!CachedRCE) {
  628. (*LocalNetInfo.ipi_closerce) (RCE);
  629. }
  630. // If it completed immediately, give it back to the user.
  631. // Otherwise we'll complete it when the SendComplete happens.
  632. // Currently, we don't map the error code from this call - we
  633. // might need to in the future.
  634. if (SendStatus != IP_PENDING)
  635. DGSendComplete(SendReq, UDPBuffer, SendStatus);
  636. } else {
  637. TDI_STATUS Status;
  638. if (DestType == DEST_INVALID)
  639. Status = TDI_BAD_ADDR;
  640. else
  641. Status = TDI_DEST_UNREACHABLE;
  642. // Complete the request with an error.
  643. (*SendReq->dsr_rtn) (SendReq->dsr_context, Status, 0);
  644. // Now free the request.
  645. SendReq->dsr_rtn = NULL;
  646. DGSendComplete(SendReq, UDPBuffer, IP_SUCCESS);
  647. }
  648. CTEGetLock(&SrcAO->ao_lock, &AOHandle);
  649. if (!EMPTYQ(&SrcAO->ao_sendq)) {
  650. DEQUEUE(&SrcAO->ao_sendq, SendReq, DGSendReq, dsr_q);
  651. CTEFreeLock(&SrcAO->ao_lock, AOHandle);
  652. } else {
  653. CLEAR_AO_REQUEST(SrcAO, AO_SEND);
  654. CTEFreeLock(&SrcAO->ao_lock, AOHandle);
  655. return;
  656. }
  657. }
  658. }
  659. //* UDPRcv - Receive a UDP datagram.
  660. //
  661. // The routine called by IP when a UDP datagram arrived. We
  662. // look up the port/local address pair in our address table,
  663. // and deliver the data to a user if we find one. For broadcast
  664. // frames we may deliver it to multiple users.
  665. //
  666. // Entry: IPContext - IPContext identifying physical i/f that
  667. // received the data.
  668. // Dest - IPAddr of destination.
  669. // Src - IPAddr of source.
  670. // LocalAddr - Local address of network which caused this to be
  671. // received.
  672. // SrcAddr - Address of local interface which received the packet
  673. // IPH - IP Header.
  674. // IPHLength - Bytes in IPH.
  675. // RcvBuf - Pointer to receive buffer chain containing data.
  676. // Size - Size in bytes of data received.
  677. // IsBCast - Boolean indicator of whether or not this came in as
  678. // a bcast.
  679. // Protocol - Protocol this came in on - should be UDP.
  680. // OptInfo - Pointer to info structure for received options.
  681. //
  682. // Returns: Status of reception. Anything other than IP_SUCCESS will cause
  683. // IP to send a 'port unreachable' message.
  684. //
  685. IP_STATUS
  686. UDPRcv(void *IPContext, IPAddr Dest, IPAddr Src, IPAddr LocalAddr,
  687. IPAddr SrcAddr, IPHeader UNALIGNED * IPH, uint IPHLength, IPRcvBuf * RcvBuf,
  688. uint IPSize, uchar IsBCast, uchar Protocol, IPOptInfo * OptInfo)
  689. {
  690. UDPHeader UNALIGNED *UH;
  691. CTELockHandle AOTableHandle;
  692. AddrObj *ReceiveingAO;
  693. uint Size;
  694. uchar DType;
  695. BOOLEAN firsttime=TRUE;
  696. DGDeliverInfo DeliverInfo = {0};
  697. DType = (*LocalNetInfo.ipi_getaddrtype) (Src);
  698. if (DType == DEST_LOCAL) {
  699. DeliverInfo.Flags |= SRC_LOCAL;
  700. }
  701. // The following code relies on DEST_INVALID being a broadcast dest type.
  702. // If this is changed the code here needs to change also.
  703. if (IS_BCAST_DEST(DType)) {
  704. if (!IP_ADDR_EQUAL(Src, NULL_IP_ADDR) || !IsBCast) {
  705. UStats.us_inerrors++;
  706. return IP_SUCCESS; // Bad src address.
  707. }
  708. }
  709. UH = (UDPHeader *) RcvBuf->ipr_buffer;
  710. Size = (uint) (net_short(UH->uh_length));
  711. if (Size < sizeof(UDPHeader)) {
  712. UStats.us_inerrors++;
  713. return IP_SUCCESS; // Size is too small.
  714. }
  715. if (Size != IPSize) {
  716. // Size doesn't match IP datagram size. If the size is larger
  717. // than the datagram, throw it away. If it's smaller, truncate the
  718. // recv. buffer.
  719. if (Size < IPSize) {
  720. IPRcvBuf *TempBuf = RcvBuf;
  721. uint TempSize = Size;
  722. while (TempBuf != NULL) {
  723. TempBuf->ipr_size = MIN(TempBuf->ipr_size, TempSize);
  724. TempSize -= TempBuf->ipr_size;
  725. TempBuf = TempBuf->ipr_next;
  726. }
  727. } else {
  728. // Size is too big, toss it.
  729. UStats.us_inerrors++;
  730. return IP_SUCCESS;
  731. }
  732. }
  733. if (UH->uh_xsum != 0) {
  734. //let udpdeliver compute the checksum
  735. DeliverInfo.Flags |= NEED_CHECKSUM;
  736. }
  737. // Set the rest of our DeliverInfo for UDPDeliver to consume.
  738. //
  739. DeliverInfo.Flags |= IsBCast ? IS_BCAST : 0;
  740. DeliverInfo.LocalAddr = LocalAddr;
  741. DeliverInfo.DestAddr = Dest;
  742. #if TRACE_EVENT
  743. DeliverInfo.DestPort = UH->uh_dest;
  744. #endif
  745. CTEGetLock(&AddrObjTableLock.Lock, &AOTableHandle);
  746. //
  747. // See if we are filtering the destination interface/port.
  748. //
  749. if (!SecurityFilteringEnabled ||
  750. IsPermittedSecurityFilter(
  751. SrcAddr,
  752. IPContext,
  753. PROTOCOL_UDP,
  754. (ulong) net_short(UH->uh_dest)
  755. )
  756. ) {
  757. // Try to find an AddrObj to give this to. In the broadcast case, we
  758. // may have to do this multiple times. If it isn't a broadcast, just
  759. // get the best match and deliver it to them.
  760. if (!IsBCast) {
  761. ReceiveingAO = GetBestAddrObj(Dest, UH->uh_dest, PROTOCOL_UDP,
  762. TRUE);
  763. if (ReceiveingAO && (ReceiveingAO->ao_rcvdg == NULL)) {
  764. AddrObj *tmpAO;
  765. tmpAO = GetNextBestAddrObj(Dest, UH->uh_dest, PROTOCOL_UDP,
  766. ReceiveingAO, TRUE);
  767. if (tmpAO != NULL) {
  768. ReceiveingAO = tmpAO;
  769. }
  770. }
  771. if (ReceiveingAO != NULL) {
  772. UDPDeliver(ReceiveingAO, Src, UH->uh_src, RcvBuf, Size,
  773. OptInfo, AOTableHandle, &DeliverInfo);
  774. return IP_SUCCESS;
  775. } else {
  776. CTEFreeLock(&AddrObjTableLock.Lock, AOTableHandle);
  777. //do the checksum and if it fails, just return IP_SUCCESS
  778. if (UH->uh_xsum != 0) {
  779. if (XsumRcvBuf(PHXSUM(Src, Dest, PROTOCOL_UDP, Size), RcvBuf) != 0xffff) {
  780. UStats.us_inerrors++;
  781. return IP_SUCCESS; // Checksum failed.
  782. }
  783. }
  784. UStats.us_noports++;
  785. return IP_GENERAL_FAILURE;
  786. }
  787. } else {
  788. // This is a broadcast, we'll need to loop.
  789. AOSearchContext Search;
  790. DType = (*LocalNetInfo.ipi_getaddrtype) (Dest);
  791. ReceiveingAO = GetFirstAddrObj(LocalAddr, UH->uh_dest, PROTOCOL_UDP,
  792. &Search);
  793. //
  794. // If there is an AO corresponding to the address of the interface
  795. // over which we got the packet, process it
  796. //
  797. if (ReceiveingAO != NULL) {
  798. do {
  799. //
  800. // If the packet is broadcast we deliver it to all clients
  801. // waiting on the dest. address (or INADDR_ANY) and port.
  802. // If the pkt is mcast, we deliver it to all clients that
  803. // are members of the mcast group and waiting on the dest
  804. // port. NOTE, if loopback is disabled, we do not deliver
  805. // to the guy who sent it
  806. if ((DType != DEST_MCAST) ||
  807. ((DType == DEST_MCAST) &&
  808. MCastAddrOnAO(ReceiveingAO, Dest, Src))) {
  809. UDPDeliver(ReceiveingAO, Src, UH->uh_src, RcvBuf, Size,
  810. OptInfo, AOTableHandle, &DeliverInfo);
  811. //turn off chksum check, since it would have been already
  812. //computed once
  813. CTEGetLock(&AddrObjTableLock.Lock, &AOTableHandle);
  814. if (UH->uh_xsum && firsttime && !(DeliverInfo.Flags & NEED_CHECKSUM)){
  815. break;
  816. }
  817. DeliverInfo.Flags &= ~NEED_CHECKSUM;
  818. firsttime=FALSE;
  819. }
  820. ReceiveingAO = GetNextAddrObj(&Search);
  821. } while (ReceiveingAO != NULL);
  822. } else
  823. UStats.us_noports++;
  824. }
  825. }
  826. CTEFreeLock(&AddrObjTableLock.Lock, AOTableHandle);
  827. return IP_SUCCESS;
  828. }
  829. //* UDPStatus - Handle a status indication.
  830. //
  831. // This is the UDP status handler, called by IP when a status event
  832. // occurs. For most of these we do nothing. For certain severe status
  833. // events we will mark the local address as invalid.
  834. //
  835. // Entry: StatusType - Type of status (NET or HW). NET status
  836. // is usually caused by a received ICMP
  837. // message. HW status indicate a HW
  838. // problem.
  839. // StatusCode - Code identifying IP_STATUS.
  840. // OrigDest - If this is NET status, the original dest. of
  841. // DG that triggered it.
  842. // OrigSrc - " " " " " , the original src.
  843. // Src - IP address of status originator (could be local
  844. // or remote).
  845. // Param - Additional information for status - i.e. the
  846. // param field of an ICMP message.
  847. // Data - Data pertaining to status - for NET status, this
  848. // is the first 8 bytes of the original DG.
  849. //
  850. // Returns: Nothing
  851. //
  852. void
  853. UDPStatus(uchar StatusType, IP_STATUS StatusCode, IPAddr OrigDest,
  854. IPAddr OrigSrc, IPAddr Src, ulong Param, void *Data)
  855. {
  856. UDPHeader UNALIGNED *UH = (UDPHeader UNALIGNED *) Data;
  857. CTELockHandle AOTableHandle, AOHandle;
  858. AddrObj *AO;
  859. IPAddr WildCardSrc = NULL_IP_ADDR;
  860. if (StatusType == IP_NET_STATUS) {
  861. ushort destport = UH->uh_dest;
  862. ushort Srcport = UH->uh_src;
  863. //KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "UdpStatus: srcport %x OrigDest %x UHdest %x \n",Srcport,OrigDest, destport));
  864. CTEGetLock(&AddrObjTableLock.Lock, &AOTableHandle);
  865. AO = GetBestAddrObj(WildCardSrc, Srcport, PROTOCOL_UDP, FALSE);
  866. if (AO == NULL) {
  867. //Let us try with local addrss
  868. AO = GetBestAddrObj(OrigSrc, Srcport, PROTOCOL_UDP, FALSE);
  869. }
  870. if (AO != NULL) {
  871. CTEGetLock(&AO->ao_lock, &AOHandle);
  872. CTEFreeLock(&AddrObjTableLock.Lock, AOTableHandle);
  873. //KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "UdpStatus: Found AO %x Ip stat %x\n", AO, StatusCode));
  874. if (AO_VALID(AO) && (AO->ao_errorex != NULL)) {
  875. PErrorEx ErrEvent = AO->ao_errorex;
  876. PVOID ErrContext = AO->ao_errorexcontext;
  877. TA_IP_ADDRESS *TAaddress;
  878. REF_AO(AO);
  879. CTEFreeLock(&AO->ao_lock, AOHandle);
  880. TAaddress = ExAllocatePoolWithTag(NonPagedPool, sizeof(TA_IP_ADDRESS), 'uPCT');
  881. if (TAaddress) {
  882. TAaddress->TAAddressCount = 1;
  883. TAaddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
  884. TAaddress->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
  885. TAaddress->Address[0].Address[0].sin_port = destport;
  886. TAaddress->Address[0].Address[0].in_addr = OrigDest;
  887. memset(TAaddress->Address[0].Address[0].sin_zero,
  888. 0,
  889. sizeof(TAaddress->Address[0].Address[0].sin_zero));
  890. (*ErrEvent) (ErrContext, MapIPError(StatusCode, TDI_DEST_UNREACHABLE), TAaddress);
  891. ExFreePool(TAaddress);
  892. }
  893. //KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "UdpStatus: Indicated error %x\n",MapIPError(StatusCode,TDI_DEST_UNREACHABLE) ));
  894. DerefAO(AO);
  895. return;
  896. }
  897. CTEFreeLock(&AO->ao_lock, AOHandle);
  898. } else {
  899. CTEFreeLock(&AddrObjTableLock.Lock, AOTableHandle);
  900. }
  901. return;
  902. }
  903. // If this is a HW status, it could be because we've had an address go
  904. // away.
  905. if (StatusType == IP_HW_STATUS) {
  906. if (StatusCode == IP_ADDR_DELETED) {
  907. //
  908. // An address has gone away. OrigDest identifies the address.
  909. //
  910. //
  911. // Delete any security filters associated with this address
  912. //
  913. DeleteProtocolSecurityFilter(OrigDest, PROTOCOL_UDP);
  914. return;
  915. }
  916. if (StatusCode == IP_ADDR_ADDED) {
  917. //
  918. // An address has materialized. OrigDest identifies the address.
  919. // Data is a handle to the IP configuration information for the
  920. // interface on which the address is instantiated.
  921. //
  922. AddProtocolSecurityFilter(OrigDest, PROTOCOL_UDP,
  923. (NDIS_HANDLE) Data);
  924. return;
  925. }
  926. }
  927. }