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.

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