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.

5569 lines
154 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. Comm.c
  5. Abstract:
  6. This module contains COMSYS's internal functions. These functions
  7. are called by commapi functions.
  8. Functions:
  9. CommCreatePorts
  10. CommInit
  11. MonTcp
  12. MonUdp
  13. HandleMsg
  14. CommReadStream
  15. ProcTcpMsg
  16. CommCreateTcpThd
  17. CommCreateUdpThd
  18. CreateThd
  19. CommConnect
  20. CommSend
  21. CommSendAssoc
  22. CommDisc
  23. CommSendUdp
  24. ParseMsg
  25. CommAlloc
  26. CommDealloc
  27. CompareNbtReq
  28. CommEndAssoc
  29. DelAssoc
  30. CommLockBlock
  31. CommUnlockBlock
  32. InitMem
  33. ChkNtfSock
  34. RecvData
  35. Portability:
  36. This module is portable
  37. Author:
  38. Pradeep Bahl (pradeepb) 18-Nov-1992
  39. Revision History:
  40. --*/
  41. /*
  42. Includes
  43. */
  44. //
  45. // The max. number of connections that can be there to/from WINS.
  46. //
  47. // NOTE NOTE NOTE
  48. //
  49. // We specify a RCVBUF size, based on this value, for the notification socket.
  50. //
  51. #define FD_SETSIZE 300
  52. #include <sys/types.h>
  53. #include <string.h>
  54. #include <stdio.h>
  55. #include "wins.h"
  56. //
  57. // pragma to disable duplicate definition message
  58. //
  59. #pragma warning (disable : 4005)
  60. #include <winsock2.h>
  61. #include <ws2tcpip.h>
  62. #pragma warning (default : 4005)
  63. #include <nb30.h>
  64. #include <nbtioctl.h>
  65. #include <tdi.h>
  66. #include "nms.h"
  67. #include "rpl.h"
  68. #include "comm.h"
  69. #include "assoc.h"
  70. #include "winsthd.h"
  71. #include "winsque.h"
  72. #include "winsmsc.h"
  73. #include "winsevt.h"
  74. #include "winscnf.h"
  75. #if MCAST > 0
  76. #include "rnraddrs.h"
  77. #endif
  78. /*
  79. defines
  80. */
  81. #define TCP_QUE_LEN 5 /*Max # of backlog connections that can be
  82. *existent at any time. NOTE: WinsSock
  83. *api can keep a max. of 5 connection req
  84. *in the queue. So, even if we specified
  85. * a higher number, that wouldn't help.
  86. *For our purposes 5 is enough.
  87. */
  88. #define SPX_QUE_LEN 5 /*Max # of backlog connections that can be*/
  89. //
  90. // These specify the timeout value for select call that is made when
  91. // message/data is expected on a connection
  92. //
  93. //
  94. // We keep the timeout 5 mts for now to give the WINS server we are
  95. // communicating enough time to respond (in case it has been asked to send
  96. // a huge number of records.
  97. //
  98. #define SECS_TO_WAIT 300 //5 mts
  99. #define MICRO_SECS_TO_WAIT 0
  100. #define TWENTY_MTS 1200 //20 mts
  101. #define FIVE_MTS TWENTY_MTS/4 //5 mts
  102. //
  103. // The max. number of bytes we can expect in a message from another WINS over
  104. // a tcp connection
  105. //
  106. #define MAX_BYTES_IN_MSG (RPL_MAX_LIMIT_FOR_RPL * (sizeof(RPL_REC_ENTRY_T) + NMSDB_MAX_NAM_LEN + (RPL_MAX_GRP_MEMBERS * sizeof(COMM_ADD_T))) + 10000 /*pad*/)
  107. #define MCAST_PKT_LEN_M(NoOfIpAdd) (COMM_MCAST_MSG_SZ -1 + (COMM_IP_ADD_SIZE * (NoOfIpAdd)))
  108. //
  109. // This is the string used for getting the port pertaining to a nameserver
  110. // from the etc\services file (via getserverbyname)
  111. //
  112. #define NAMESERVER "nameserver"
  113. /*
  114. Globals
  115. */
  116. RTL_GENERIC_TABLE CommUdpNbtDlgTable; /*table for dialogue blocks created as
  117. *a result of nbt requests received
  118. *over the UDP port
  119. */
  120. BOOL fCommDlgError = FALSE; //set to TRUE in ChkNtfSock() fn.
  121. DWORD CommWinsTcpPortNo = COMM_DEFAULT_IP_PORT;
  122. DWORD WinsClusterIpAddress = 0;
  123. #if SPX > 0
  124. #define WINS_IPX_PORT 100
  125. DWORD CommWinsSpxPortNo;
  126. #endif
  127. /*
  128. Static variables
  129. */
  130. #ifdef WINSDBG
  131. #define SOCKET_TRACK_BUFFER_SIZE 20000
  132. DWORD CommNoOfDgrms; //for testing purposes only. It counts the
  133. //number of datagrams received
  134. DWORD CommNoOfRepeatDgrms;
  135. PUINT_PTR pTmpW;
  136. BOOL sfMemoryOverrun = FALSE;
  137. LPLONG pEndPtr;
  138. #endif
  139. DWORD CommConnCount = 0; //no of tcp connection from/to this WINS
  140. struct timeval sTimeToWait = {SECS_TO_WAIT, MICRO_SECS_TO_WAIT};
  141. STATIC HANDLE sNetbtSndEvtHdl;
  142. STATIC HANDLE sNetbtRcvEvtHdl;
  143. STATIC HANDLE sNetbtGetAddrEvtHdl;
  144. #if MCAST > 0
  145. #define COMM_MCAST_ADDR IP_S_MEMBERSHIP //just pick one in the allowed range
  146. struct sockaddr_in McastAdd;
  147. #endif
  148. //
  149. // Structures used to store information about partners discovered via
  150. // Multicasting
  151. //
  152. typedef struct _ADD_T {
  153. DWORD NoOfAdds;
  154. COMM_IP_ADD_T IpAdd[1];
  155. } ADD_T, *PADD_T;
  156. typedef struct _MCAST_PNR_STATUS_T {
  157. DWORD NoOfPnrs; //no of pnrs in pPnrStatus buffer
  158. DWORD NoOfPnrSlots; //no of pnr slots in pPnrStatus buffer
  159. BYTE Pnrs[1];
  160. } MCAST_PNR_STATUS_T, *PMCAST_PNR_STATUS_T;
  161. typedef struct _PNR_STATUS_T {
  162. COMM_IP_ADD_T IPAdd;
  163. DWORD State;
  164. } PNR_STATUS_T, *PPNR_STATUS_T;
  165. #define MCAST_PNR_STATUS_SIZE_M(_NoOfPnrs) sizeof(MCAST_PNR_STATUS_T) +\
  166. ((_NoOfPnrs) * sizeof(PNR_STATUS_T))
  167. PMCAST_PNR_STATUS_T pPnrStatus;
  168. //
  169. // To store WINS Addresses
  170. //
  171. PADD_T pWinsAddresses=NULL; //stores all the IP addresses returned by netbt
  172. /* local function prototypes */
  173. STATIC
  174. DWORD
  175. MonTcp(
  176. LPVOID
  177. );
  178. STATIC
  179. DWORD
  180. MonUdp(
  181. LPVOID
  182. );
  183. STATIC
  184. VOID
  185. HandleMsg(
  186. SOCKET SockNo,
  187. LPLONG pBytesRead,
  188. LPBOOL pfSockCl
  189. );
  190. STATIC
  191. VOID
  192. ProcTcpMsg(
  193. SOCKET SockNo,
  194. MSG_T pMsg,
  195. MSG_LEN_T MsgLen,
  196. LPBOOL pfSockCl
  197. );
  198. STATIC
  199. VOID
  200. CreateThd(
  201. DWORD (*pStartFunc)(LPVOID),
  202. WINSTHD_TYP_E ThdTyp_e
  203. );
  204. STATIC
  205. VOID
  206. ParseMsg(
  207. MSG_T pMsg,
  208. MSG_LEN_T MsgLen,
  209. COMM_TYP_E MsgType,
  210. struct sockaddr_in *pFromAdd,
  211. PCOMMASSOC_ASSOC_CTX_T pAssocCtx
  212. );
  213. STATIC
  214. VOID
  215. DelAssoc(
  216. SOCKET SockNo,
  217. PCOMMASSOC_ASSOC_CTX_T pAssocCtx
  218. );
  219. STATIC
  220. VOID
  221. InitMem(
  222. VOID
  223. );
  224. STATIC
  225. BOOL
  226. ChkNtfSock(
  227. IN fd_set *pActSocks,
  228. IN fd_set *pRdSocks
  229. );
  230. STATIC
  231. STATUS
  232. RecvData(
  233. SOCKET SockNo,
  234. LPBYTE pBuff,
  235. DWORD BytesToRead,
  236. INT Flags,
  237. DWORD SecsToWait,
  238. LPDWORD pBytesRead
  239. );
  240. STATUS
  241. CommTcp(
  242. IN PCOMM_ADD_T pHostAdd,
  243. IN SOCKET Port,
  244. OUT SOCKET *pSockNo
  245. );
  246. #if SPX > 0
  247. STATUS
  248. CommSpx(
  249. IN PCOMM_ADD_T pHostAdd,
  250. IN SOCKET Port,
  251. OUT SOCKET *pSockNo
  252. );
  253. #endif
  254. STATIC
  255. LPVOID
  256. CommHeapAlloc(
  257. IN PRTL_GENERIC_TABLE pTable,
  258. IN CLONG BuffSize
  259. );
  260. STATIC
  261. VOID
  262. CommHeapDealloc(
  263. IN PRTL_GENERIC_TABLE pTable,
  264. IN PVOID pBuff
  265. );
  266. STATIC
  267. NTSTATUS
  268. DeviceIoCtrl(
  269. IN LPHANDLE pEvtHdl,
  270. IN PVOID pDataBuffer,
  271. IN DWORD DataBufferSize,
  272. IN ULONG Ioctl
  273. );
  274. STATIC
  275. VOID
  276. SendNetbt (
  277. struct sockaddr_in *pDest,
  278. MSG_T pMsg,
  279. MSG_LEN_T MsgLen
  280. );
  281. #if MCAST > 0
  282. VOID
  283. JoinMcastGrp(
  284. VOID
  285. );
  286. BOOL
  287. CheckMcastSock(
  288. IN fd_set *pActSocks,
  289. IN fd_set *pRdSocks
  290. );
  291. #endif
  292. VOID
  293. CreateTcpIpPorts(
  294. VOID
  295. );
  296. VOID
  297. CreateSpxIpxPorts(
  298. VOID
  299. );
  300. BOOL
  301. ChkMyAdd(
  302. COMM_IP_ADD_T IpAdd
  303. );
  304. /*
  305. function definitions start here
  306. */
  307. VOID
  308. CommCreatePorts(
  309. VOID
  310. )
  311. /*++
  312. Routine Description:
  313. This function creates a TCP and UDP port for the WINS server
  314. It uses the standard WINS server port # to bind to both the TCP and the UDP
  315. sockets.
  316. Arguments:
  317. Qlen - Length of queue for incoming connects on the TCP port
  318. pTcpPortHandle - Ptr to SOCKET for the TCP port
  319. pUdpPortHandle - Ptr to SOCKET for the UDP port
  320. pNtfSockHandle - Ptr to SOCKET for receiving messages carrying socket
  321. handles
  322. pNtfAdd - Address bound to Notification socket
  323. Externals Used:
  324. None
  325. Called by:
  326. ECommInit
  327. Comments:
  328. I might want to create a PassiveSock function that would create
  329. a TCP/UDP port based on its arguments. This function would then
  330. be called from MOnTCP and MonUDP.
  331. Return Value:
  332. None
  333. --*/
  334. {
  335. CreateTcpIpPorts();
  336. #if SPX > 0
  337. CreateSpxIpxPorts();
  338. #endif
  339. }
  340. VOID
  341. CreateTcpIpPorts(
  342. VOID
  343. )
  344. {
  345. int Error;
  346. DWORD AddLen = sizeof(struct sockaddr_in);
  347. struct servent *pServEnt;
  348. struct sockaddr_in sin;
  349. int SockBuffSize;
  350. WINSMSC_FILL_MEMORY_M(&sin, sizeof(sin), 0);
  351. WINSMSC_FILL_MEMORY_M(&CommNtfSockAdd, sizeof(sin), 0);
  352. #if MCAST > 0
  353. /*
  354. Allocate a socket for UDP
  355. */
  356. if ( (CommUdpPortHandle = socket(
  357. PF_INET,
  358. SOCK_DGRAM,
  359. IPPROTO_UDP
  360. )
  361. ) == INVALID_SOCKET
  362. )
  363. {
  364. Error = WSAGetLastError();
  365. WINSEVT_LOG_M(Error, WINS_EVT_CANT_CREATE_UDP_SOCK); //log an event
  366. WINS_RAISE_EXC_M(WINS_EXC_FATAL_ERR);
  367. }
  368. DBGPRINT1(MTCAST, "Udp socket # is (%d)\n", CommUdpPortHandle);
  369. #endif
  370. sin.sin_family = PF_INET; //We are using the Internet
  371. //family
  372. if (WinsClusterIpAddress) {
  373. sin.sin_addr.s_addr = htonl(WinsClusterIpAddress); //Any network
  374. } else {
  375. sin.sin_addr.s_addr = 0; //any network
  376. }
  377. if (CommWinsTcpPortNo == COMM_DEFAULT_IP_PORT)
  378. {
  379. pServEnt = getservbyname( NAMESERVER, NULL);
  380. if (!pServEnt)
  381. {
  382. Error = WSAGetLastError();
  383. WINSEVT_LOG_M(Error, WINS_EVT_CANT_CREATE_UDP_SOCK); //log an event
  384. WINS_RAISE_EXC_M(WINS_EXC_FATAL_ERR);
  385. }
  386. sin.sin_port = pServEnt->s_port;
  387. CommWinsTcpPortNo = ntohs(sin.sin_port);
  388. }
  389. else
  390. {
  391. sin.sin_port = htons((USHORT)CommWinsTcpPortNo);
  392. }
  393. DBGPRINT1(DET, "UDP/TCP port used is (%d)\n", CommWinsTcpPortNo);
  394. #if MCAST > 0
  395. //
  396. // Initialize global with mcast address of WINS. Used by SendMcastMsg
  397. //
  398. // Do this here as against later since sin gets changed later on
  399. //
  400. McastAdd.sin_family = PF_INET; //We are using the Internet
  401. //family
  402. McastAdd.sin_addr.s_addr = ntohl(inet_addr(COMM_MCAST_ADDR));
  403. McastAdd.sin_port = sin.sin_port;
  404. /*
  405. Bind the address to the socket
  406. */
  407. if ( bind(
  408. CommUdpPortHandle,
  409. (struct sockaddr *)&sin,
  410. sizeof(sin)) == SOCKET_ERROR
  411. )
  412. {
  413. Error = WSAGetLastError();
  414. WINSEVT_LOG_M(Error, WINS_EVT_WINSOCK_BIND_ERR); //log an event
  415. WINS_RAISE_EXC_M(WINS_EXC_FATAL_ERR);
  416. }
  417. #endif
  418. /*
  419. * Allocate a socket for receiving TCP connections
  420. */
  421. if ( (CommTcpPortHandle = socket(
  422. PF_INET,
  423. SOCK_STREAM,
  424. IPPROTO_TCP
  425. )
  426. ) == INVALID_SOCKET
  427. )
  428. {
  429. Error = WSAGetLastError();
  430. WINSEVT_LOG_M(Error, WINS_EVT_CANT_CREATE_TCP_SOCK_FOR_LISTENING);
  431. WINS_RAISE_EXC_M(WINS_EXC_FATAL_ERR);
  432. }
  433. /*
  434. * Bind the address to the socket
  435. */
  436. #if 0
  437. sin.sin_port = pServEnt->s_port;
  438. CommWinsTcpPortNo = ntohs(pServEnt->s_port);
  439. DBGPRINT1(DET, "TCP port used is (%d)\n", CommWinsTcpPortNo);
  440. #endif
  441. DBGPRINT1(DET, "TCP port used is (%d)\n", ntohs(sin.sin_port));
  442. if ( bind(
  443. CommTcpPortHandle,
  444. (struct sockaddr *)&sin,
  445. sizeof(sin)
  446. ) == SOCKET_ERROR
  447. )
  448. {
  449. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_WINSOCK_BIND_ERR); //log an event
  450. WINS_RAISE_EXC_M(WINS_EXC_FAILURE);
  451. }
  452. // Inform the TCP/IP driver of the queue length for connections
  453. if ( listen(CommTcpPortHandle, TCP_QUE_LEN) == SOCKET_ERROR)
  454. {
  455. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_WINSOCK_LISTEN_ERR);
  456. WINS_RAISE_EXC_M(WINS_EXC_FAILURE);
  457. }
  458. //
  459. // Create another socket for receiving socket #s of connections
  460. // to be added/removed from the list of sockets monitored by the
  461. // TCP listener thread. An example of a connection added to the
  462. // above list is the one initiated by the PULL thread to push update
  463. // notifications to other WINSs (PULL partners of this thread). An
  464. // example of a connection removed is the one on which a PUSH
  465. // notification (trigger) is received.
  466. //
  467. if ( (CommNtfSockHandle = socket(
  468. PF_INET,
  469. #if 0
  470. SOCK_STREAM,
  471. IPPROTO_TCP,
  472. #endif
  473. SOCK_DGRAM,
  474. IPPROTO_UDP
  475. )
  476. ) == INVALID_SOCKET
  477. )
  478. {
  479. Error = WSAGetLastError();
  480. WINSEVT_LOG_M(Error, WINS_EVT_CANT_CREATE_NTF_SOCK); //log an event
  481. WINS_RAISE_EXC_M(WINS_EXC_FATAL_ERR);
  482. }
  483. sin.sin_port = 0; //Use any available port in the range 1024-5000
  484. /*
  485. Bind the address to the socket
  486. */
  487. if ( bind(
  488. CommNtfSockHandle,
  489. (struct sockaddr *)&sin,
  490. sizeof(sin)) == SOCKET_ERROR
  491. )
  492. {
  493. Error = WSAGetLastError();
  494. WINSEVT_LOG_M(Error, WINS_EVT_WINSOCK_BIND_ERR); //log an event
  495. WINS_RAISE_EXC_M(WINS_EXC_FATAL_ERR);
  496. }
  497. //
  498. // Let us get the address that we have bound the notification socket to
  499. //
  500. if (getsockname(
  501. CommNtfSockHandle,
  502. (struct sockaddr *)&CommNtfSockAdd,
  503. &AddLen
  504. ) == SOCKET_ERROR
  505. )
  506. {
  507. Error = WSAGetLastError();
  508. WINSEVT_LOG_M(Error, WINS_EVT_WINSOCK_GETSOCKNAME_ERR); //log an event
  509. WINS_RAISE_EXC_M(WINS_EXC_FATAL_ERR);
  510. }
  511. //
  512. // Set the RCVBUF to FD_SETSIZE * 128. 128 is the # of bytes used up
  513. // per msg by Afd. We can have a max of FD_SETSIZE connections initiated
  514. // to and from WINS. So, making the recv buf this size ensures that msgs
  515. // sent by push thread to the tcp thread will never get dropped.
  516. //
  517. // The above size comes out to be 38.4K for an FD_SETSIZE of 300. This
  518. // is > 8k which the default used by Afd. Note: Specifying this does
  519. // not use up memory. It is just used to set a threshold. pmon will
  520. // show a higher non-paged pool since the number it shows for the same
  521. // indicates the amount of memory charged to the process (not necessarily
  522. // allocated
  523. //
  524. SockBuffSize = FD_SETSIZE * 128;
  525. if (setsockopt(
  526. CommNtfSockHandle,
  527. SOL_SOCKET,
  528. SO_RCVBUF,
  529. (char *)&SockBuffSize,
  530. sizeof(SockBuffSize)) == SOCKET_ERROR)
  531. {
  532. Error = WSAGetLastError();
  533. DBGPRINT1(ERR, "CommCreatePorts: SetSockOpt failed", Error);
  534. }
  535. //
  536. // Initialize the address structure for this notification socket.
  537. // We can't use the address returned by getsockname() if the
  538. // machine we are running on is a multi-homed host.
  539. //
  540. // The IP address is in host byte order since we store all addresses in
  541. // host order. CommNtfSockAdd will be passed to CommSendUdp which expects
  542. // the IP address in it to be in host byte order.
  543. //
  544. // Note: the Port should be in net byte order
  545. //
  546. //
  547. // The statement within #if 0 and #endif does not work.
  548. //
  549. CommNtfSockAdd.sin_addr.s_addr = NmsLocalAdd.Add.IPAdd;
  550. #if 0
  551. CommNtfSockAdd.sin_addr.s_addr = ntohl(INADDR_LOOPBACK);
  552. #endif
  553. #if MCAST > 0
  554. JoinMcastGrp();
  555. CommSendMcastMsg(COMM_MCAST_WINS_UP);
  556. #endif
  557. return;
  558. }
  559. #if SPX > 0
  560. VOID
  561. CreateSpxIpxPorts(
  562. VOID
  563. )
  564. {
  565. int Error;
  566. DWORD AddLen = sizeof(struct sockaddr_ipx);
  567. struct servent *pServEnt;
  568. struct sockaddr_ipx sipx;
  569. struct hostent *pHostEnt;
  570. BYTE HostName[80];
  571. WINSMSC_FILL_MEMORY_M(&sipx, sizeof(sipx), 0);
  572. WINSMSC_FILL_MEMORY_M(CommNtfAdd, sizeof(sipx), 0);
  573. /*
  574. * Allocate a socket for receiving TCP connections
  575. */
  576. if ( (CommSpxPortHandle = socket(
  577. PF_IPX,
  578. SOCK_STREAM,
  579. NSPROTO_SPX
  580. )
  581. ) == INVALID_SOCKET
  582. )
  583. {
  584. Error = WSAGetLastError();
  585. WINSEVT_LOG_M(Error, WINS_EVT_CANT_CREATE_TCP_SOCK_FOR_LISTENING);
  586. WINS_RAISE_EXC_M(WINS_EXC_FATAL_ERR);
  587. }
  588. /*
  589. * Bind the address to the socket
  590. */
  591. sipx.sa_family = PF_IPX;
  592. sipx.sa_port = ntohs(WINS_IPX_PORT);
  593. CHECK("How do I specify that I want the connection from any interface")
  594. DBGPRINT1(DET, "SPX port used is (%d)\n", WINS_IPX_PORT);
  595. CommWinsSpxPortNo = WINS_IPX_PORT;
  596. if ( bind(
  597. CommSpxPortHandle,
  598. (struct sockaddr *)&sipx,
  599. sizeof(sipx)
  600. ) == SOCKET_ERROR
  601. )
  602. {
  603. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_WINSOCK_BIND_ERR); //log an event
  604. WINS_RAISE_EXC_M(WINS_EXC_FAILURE);
  605. }
  606. // Inform the TCP/IP driver of the queue length for connections
  607. if ( listen(CommSpxPortHandle, SPX_QUE_LEN) == SOCKET_ERROR)
  608. {
  609. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_WINSOCK_LISTEN_ERR);
  610. WINS_RAISE_EXC_M(WINS_EXC_FAILURE);
  611. }
  612. //
  613. // Create another socket for receiving socket #s of connections
  614. // to be added/removed from the list of sockets monitored by the
  615. // TCP listener thread. An example of a connection added to the
  616. // above list is the one initiated by the PULL thread to push update
  617. // notifications to other WINSs (PULL partners of this thread). An
  618. // example of a connection removed is the one on which a PUSH
  619. // notification (trigger) is received.
  620. //
  621. if ( (CommIpxNtfSockHandle = socket(
  622. PF_IPX,
  623. SOCK_DGRAM,
  624. NSPROTO_IPX
  625. )
  626. ) == INVALID_SOCKET
  627. )
  628. {
  629. Error = WSAGetLastError();
  630. WINSEVT_LOG_M(Error, WINS_EVT_CANT_CREATE_NTF_SOCK); //log an event
  631. WINS_RAISE_EXC_M(WINS_EXC_FATAL_ERR);
  632. }
  633. sipx.sa_port = 0; //Use any available port in the range 1024-5000
  634. /*
  635. Bind the address to the socket
  636. */
  637. if ( bind(
  638. CommIpxNtfSockHandle,
  639. (struct sockaddr *)&sipx,
  640. sizeof(sipx)) == SOCKET_ERROR
  641. )
  642. {
  643. Error = WSAGetLastError();
  644. WINSEVT_LOG_M(Error, WINS_EVT_WINSOCK_BIND_ERR); //log an event
  645. WINS_RAISE_EXC_M(WINS_EXC_FATAL_ERR);
  646. }
  647. //
  648. // Let us get the address that we have bound the notification socket to
  649. //
  650. if (getsockname(
  651. CommIpxNtfSockHandle,
  652. (struct sockaddr *)&CommIpxNtfSockAdd,
  653. &AddLen
  654. ) == SOCKET_ERROR
  655. )
  656. {
  657. Error = WSAGetLastError();
  658. WINSEVT_LOG_M(Error, WINS_EVT_WINSOCK_GETSOCKNAME_ERR); //log an event
  659. WINS_RAISE_EXC_M(WINS_EXC_FATAL_ERR);
  660. }
  661. //
  662. // Initialize the address structure for this notification socket.
  663. // We can't use the address returned by getsockname() if the
  664. // machine we are running on is a multi-homed host.
  665. //
  666. // The IP address is in host byte order since we store all addresses in
  667. // host order. *pNtfAdd will be passed to CommSendUdp which expects
  668. // the IP address in it to be in host byte order.
  669. //
  670. // Note: the Port should be in net byte order
  671. //
  672. #if 0
  673. if (gethostname(HostName, sizeof(HostName) == SOCKET_ERROR)
  674. {
  675. Error = WSAGetLastError();
  676. WINS_RAISE_EXC_M(WINS_EXC_FATAL_ERR);
  677. }
  678. if (gethostbyname(HostName, sizeof(HostName) == NULL)
  679. {
  680. Error = WSAGetLastError();
  681. WINS_RAISE_EXC_M(WINS_EXC_FATAL_ERR);
  682. }
  683. #endif
  684. //
  685. // The statement within #if 0 and #endif does not work.
  686. //
  687. CommIpxNtfSockAdd->sin_addr.s_addr = 0;
  688. #if 0
  689. pNtfAdd->sin_addr.s_addr = ntohl(INADDR_LOOPBACK);
  690. #endif
  691. return;
  692. }
  693. #endif
  694. VOID
  695. CommInit(
  696. VOID
  697. )
  698. /*++
  699. Routine Description:
  700. This function initializes all the lists, tables and memory
  701. used by COMSYS.
  702. Arguments:
  703. None
  704. Externals Used:
  705. CommAssocTable
  706. CommUdpNbtDlgTable
  707. CommExNbtDlgHdl
  708. CommUdpBuffHeapHdl
  709. Return Value:
  710. None
  711. Error Handling:
  712. Called by:
  713. ECommInit
  714. Side Effects:
  715. Comments:
  716. None
  717. --*/
  718. {
  719. PCOMMASSOC_DLG_CTX_T pDlgCtx = NULL;
  720. //
  721. // Do all memory initialization
  722. //
  723. InitMem();
  724. /*
  725. * Initialize the table that will store the dialogue context blocks
  726. * for nbt requests received over the UDP port.
  727. */
  728. WINSMSC_INIT_TBL_M(
  729. &CommUdpNbtDlgTable,
  730. CommCompareNbtReq,
  731. CommHeapAlloc,
  732. CommHeapDealloc,
  733. NULL /* table context*/
  734. );
  735. /*
  736. * Initialize the critical sections and queue heads
  737. *
  738. * The initialization is done in a CommAssoc function instead of here
  739. * to avoid recursive includes
  740. */
  741. CommAssocInit();
  742. CommExNbtDlgHdl.pEnt = CommAssocAllocDlg();
  743. pDlgCtx = CommExNbtDlgHdl.pEnt;
  744. /*
  745. * Initialize the explicit nbt dialogue handle
  746. */
  747. pDlgCtx->Typ_e = COMM_E_UDP;
  748. pDlgCtx->AssocHdl.pEnt = NULL;
  749. pDlgCtx->Role_e = COMMASSOC_DLG_E_EXPLICIT;
  750. #if USENETBT > 0
  751. //
  752. // Create two events (one for send and one for rcv to/from netbt)
  753. //
  754. WinsMscCreateEvt(NULL, FALSE, &sNetbtSndEvtHdl);
  755. WinsMscCreateEvt(NULL, FALSE, &sNetbtRcvEvtHdl);
  756. WinsMscCreateEvt(NULL, FALSE, &sNetbtGetAddrEvtHdl);
  757. #endif
  758. return;
  759. } // CommInit()
  760. DWORD
  761. MonTcp(
  762. LPVOID pArg
  763. )
  764. /*++
  765. Routine Description:
  766. This function is the thread startup function for the TCP listener
  767. thread. It monitors the TCP port and the connections that have
  768. been made and received by this process.
  769. If a connection is received, it is accepted. If there is data on
  770. a TCP connection, a function is called to process it.
  771. Arguments:
  772. pArg - Argument (Not used)
  773. Externals Used:
  774. CommTCPPortHandle -- TCP port for the process
  775. CommAssocTable
  776. Called by:
  777. ECommInit
  778. Comments:
  779. None
  780. Return Value:
  781. Sucess status codes -- WINS_SUCCESS
  782. Error status codes -- WINS_FAILURE
  783. --*/
  784. {
  785. struct sockaddr_in fsin; //address of connector
  786. #if SPX > 0
  787. struct sockaddr_ipx fsipx; //address of connector
  788. #endif
  789. SOCKET Port;
  790. LPVOID pRemAdd;
  791. fd_set RdSocks; //The read socket set
  792. fd_set ActSocks; //the active socket set
  793. int AddLen = sizeof(fsin); //length of from address
  794. u_short No; //Counter for iterating over the sock
  795. //array
  796. BOOL fSockCl = FALSE; //Was the socket closed ?
  797. SOCKET NewSock = INVALID_SOCKET;
  798. BOOL fNewAssoc = FALSE;
  799. DWORD BytesRead = 0;
  800. DWORD Error;
  801. int i = 0; //for testing purpose only
  802. SOCKET SockNo;
  803. LONG NoOfSockReady = 0;
  804. PCOMMASSOC_ASSOC_CTX_T pAssocCtx = NULL;
  805. STATUS RetStat = WINS_SUCCESS;
  806. BOOL fLimitReached = FALSE;
  807. #ifdef WINSDBG
  808. PUINT_PTR pTmpSv;
  809. DWORD Index = 0;
  810. #endif
  811. EnterCriticalSection(&NmsTermCrtSec);
  812. NmsTotalTrmThdCnt++;
  813. LeaveCriticalSection(&NmsTermCrtSec);
  814. FD_ZERO(&ActSocks); //init the Active socket array
  815. FD_ZERO(&RdSocks); //init the Read socket array
  816. FD_SET(CommTcpPortHandle, &ActSocks); /*set the TCP listening socket
  817. handle in the Active array */
  818. FD_SET(CommNtfSockHandle, &ActSocks); /*set the Notification socket
  819. *handle in the Active array */
  820. #if MCAST > 0
  821. if (CommUdpPortHandle != INVALID_SOCKET)
  822. {
  823. //
  824. // We want to monitor multicast packets also
  825. //
  826. FD_SET(CommUdpPortHandle, &ActSocks);
  827. WinsMscAlloc(MCAST_PNR_STATUS_SIZE_M(RPL_MAX_OWNERS_INITIALLY),
  828. (LPVOID *)&pPnrStatus
  829. );
  830. pPnrStatus->NoOfPnrs = 0;
  831. pPnrStatus->NoOfPnrSlots = RPL_MAX_OWNERS_INITIALLY;
  832. }
  833. #endif
  834. #if SPX > 0
  835. FD_SET(CommSpxPortHandle, &ActSocks); /*set the TCP listening socket
  836. handle in the Active array */
  837. FD_SET(CommIpxNtfSockHandle, &ActSocks); /*set the Notification socket
  838. *handle in the Active array */
  839. #endif
  840. #ifdef WINSDBG
  841. WinsMscAlloc(SOCKET_TRACK_BUFFER_SIZE, &pTmpSv);
  842. pTmpW = pTmpSv;
  843. pEndPtr = (LPLONG)((LPBYTE)pTmpSv + SOCKET_TRACK_BUFFER_SIZE);
  844. #endif
  845. LOOPTCP:
  846. try {
  847. /*
  848. Loop forever
  849. */
  850. while(TRUE)
  851. {
  852. BOOL fConnTcp;
  853. BOOL fConnSpx;
  854. fConnTcp = FALSE;
  855. fConnSpx = FALSE;
  856. /*
  857. Copy the the active socket array into the
  858. read socket array. This is done every time before calling
  859. select. This is because select changes the contents of
  860. the read socket array.
  861. */
  862. WINSMSC_COPY_MEMORY_M(&RdSocks, &ActSocks, sizeof(fd_set));
  863. /*
  864. Do a blocking select on all sockets in the array (for connections
  865. and data)
  866. */
  867. DBGPRINT1(FLOW, "Rd array count is %d \n", RdSocks.fd_count);
  868. #ifdef WINSDBG
  869. if (!sfMemoryOverrun)
  870. {
  871. if ((ULONG_PTR)(pTmpW + (10 + RdSocks.fd_count)) > (ULONG_PTR)pEndPtr)
  872. {
  873. WinsDbg |= 0x3;
  874. DBGPRINT0(ERR, "MonTcp: Stopping socket tracking to prevent Memory overrun\n")
  875. sfMemoryOverrun = TRUE;
  876. }
  877. else
  878. {
  879. *pTmpW++ = RdSocks.fd_count;
  880. *pTmpW++ = 0xFFFFFFFF;
  881. for(i = 0; i< (int)RdSocks.fd_count; i++)
  882. {
  883. *pTmpW++ = RdSocks.fd_array[i];
  884. DBGPRINT1(FLOW, "Sock no is (%d)\n", RdSocks.fd_array[i]);
  885. }
  886. *pTmpW++ = 0xFFFFFFFF;
  887. }
  888. }
  889. #endif
  890. if (
  891. (
  892. NoOfSockReady = select(
  893. FD_SETSIZE /*ignored arg*/,
  894. &RdSocks,
  895. (fd_set *)0,
  896. (fd_set *)0,
  897. (struct timeval *)0 //Infinite
  898. //timeout
  899. )
  900. ) == SOCKET_ERROR
  901. )
  902. {
  903. Error = WSAGetLastError();
  904. #ifdef WINSDBG
  905. if (Error == WSAENOTSOCK)
  906. {
  907. DWORD i;
  908. PUINT_PTR pW;
  909. WinsDbg |= 0x3;
  910. DBGPRINT0(ERR, "MonTcp: Memory dump is\n\n");
  911. for (i=0, pW = pTmpSv; pW < pTmpW; pW++,i++)
  912. {
  913. DBGPRINT1(ERR, "|%x|", *pW);
  914. if (*pW == 0xEFFFFFFE)
  915. {
  916. DBGPRINT1(ERR, "Socket closed = (%x)\n", *++pW);
  917. }
  918. if ((i == 16) || (*pW == 0xFFFFFFFF))
  919. {
  920. DBGPRINT0(ERR, "\n");
  921. }
  922. }
  923. DBGPRINT0(ERR, "Memory Dump End\n");
  924. }
  925. #endif
  926. //
  927. // If state is not terminating, we have an error. If
  928. // it is terminating, then the reason we got an error
  929. // from select is because the main thread closed the
  930. // TCP socket. In the latter case, we pass WINS_SUCCESS
  931. // to WinsMscTermThd so that we don't end up signaling
  932. // the main thread prematurely.
  933. //
  934. if (
  935. (WinsCnf.State_e == WINSCNF_E_RUNNING)
  936. ||
  937. (WinsCnf.State_e == WINSCNF_E_PAUSED)
  938. )
  939. {
  940. ASSERT(Error != WSAENOTSOCK);
  941. WINSEVT_LOG_D_M( Error, WINS_EVT_WINSOCK_SELECT_ERR );
  942. RetStat = WINS_FAILURE;
  943. }
  944. else
  945. {
  946. //
  947. // State is terminating. Error should
  948. // be WSENOTSOCK
  949. //
  950. //ASSERT(Error == WSAENOTSOCK);
  951. }
  952. WinsThdPool.CommThds[0].fTaken = FALSE;
  953. WinsMscTermThd(RetStat, WINS_NO_DB_SESSION_EXISTS);
  954. }
  955. else
  956. {
  957. DBGPRINT1(FLOW, "Select returned with success. No of Sockets ready - (%d) \n", NoOfSockReady);
  958. /*
  959. if a connection has been received on the TCP port, accept it
  960. and change the active socket array
  961. */
  962. if (FD_ISSET(CommTcpPortHandle, &RdSocks))
  963. {
  964. fConnTcp = TRUE;
  965. Port = CommTcpPortHandle;
  966. pRemAdd = &fsin;
  967. }
  968. #if SPX > 0
  969. else
  970. {
  971. if (FD_ISSET(CommSpxPortHandle, &RdSocks))
  972. {
  973. fConnSpx = TRUE;
  974. Port = CommSpxPortHandle;
  975. pRemAdd = &fsipx;
  976. }
  977. }
  978. #endif
  979. if (fConnTcp || fConnSpx)
  980. {
  981. DWORD ConnCount;
  982. //
  983. // Note: FD_SET can fail silently if the fd_set array is
  984. // full. Therefore we should check this. Do it here instead
  985. // of after the accept to save on network traffic.
  986. //
  987. ConnCount = InterlockedExchange(&CommConnCount, CommConnCount);
  988. //if (ActSocks.fd_count >= FD_SETSIZE)
  989. #ifdef WINSDBG
  990. if (ConnCount >= 200)
  991. {
  992. DBGPRINT0(ERR,
  993. "MonTcp: Connection limit of 200 reached. \n");
  994. }
  995. #endif
  996. #if 0
  997. if (ConnCount >= FD_SETSIZE)
  998. {
  999. DBGPRINT1(ERR,
  1000. "MonTcp: Connection limit of %d reached. No accept being done\n",
  1001. FD_SETSIZE);
  1002. WINSEVT_LOG_D_M(ConnCount,
  1003. WINS_EVT_CONN_LIMIT_REACHED);
  1004. fLimitReached = TRUE;
  1005. }
  1006. #endif
  1007. DBGPRINT0(FLOW, "Going to do an accept now\n");
  1008. if ( (NewSock = accept(
  1009. Port,
  1010. (struct sockaddr *)pRemAdd,
  1011. &AddLen
  1012. )
  1013. ) == INVALID_SOCKET
  1014. )
  1015. {
  1016. Error = WSAGetLastError();
  1017. if (WinsCnf.State_e != WINSCNF_E_TERMINATING)
  1018. {
  1019. WINSEVT_LOG_M(
  1020. Error,
  1021. WINS_EVT_WINSOCK_ACCEPT_ERR,
  1022. );
  1023. }
  1024. WinsThdPool.CommThds[0].fTaken = FALSE;
  1025. WinsMscTermThd(
  1026. (((Error == WSAEINTR) || (Error == WSAENOTSOCK)) ?
  1027. WINS_SUCCESS : WINS_FAILURE),
  1028. WINS_NO_DB_SESSION_EXISTS);
  1029. }
  1030. DBGPRINT1(FLOW, "New Sock value is (%d)\n", NewSock);
  1031. if (fLimitReached)
  1032. {
  1033. FUTURES("Move this into CommDisc -- add a flag to it to indicate abrupt stop")
  1034. struct linger Linger;
  1035. Linger.l_onoff = 0;
  1036. if (setsockopt(
  1037. NewSock,
  1038. SOL_SOCKET,
  1039. SO_DONTLINGER,
  1040. (char *)&Linger,
  1041. sizeof(Linger)) == SOCKET_ERROR)
  1042. {
  1043. Error = WSAGetLastError();
  1044. DBGPRINT1(ERR,
  1045. "MonTcp: SetSockOpt failed", Error);
  1046. }
  1047. fLimitReached = FALSE;
  1048. CommDisc(NewSock, FALSE); //close the socket
  1049. continue;
  1050. }
  1051. FD_SET(NewSock, &ActSocks);
  1052. InterlockedIncrement(&CommConnCount);
  1053. #ifdef WINSDBG
  1054. /*
  1055. * Let us see if the assoc. is there or not. It shouldn't be
  1056. * but let us check anyway (robust programming).
  1057. */
  1058. pAssocCtx = CommAssocLookupAssoc( NewSock );
  1059. if (!pAssocCtx)
  1060. {
  1061. #endif
  1062. pAssocCtx = CommAssocCreateAssocInTbl(NewSock);
  1063. if (!pAssocCtx)
  1064. {
  1065. WINSEVT_LOG_D_M(
  1066. WINS_OUT_OF_MEM,
  1067. WINS_EVT_CANT_ALLOC_RSP_ASSOC,
  1068. );
  1069. WinsMscTermThd(WINS_FAILURE, WINS_NO_DB_SESSION_EXISTS);
  1070. }
  1071. #ifdef WINSDBG
  1072. }
  1073. else
  1074. {
  1075. DBGPRINT0(ERR, "MonTcp: Not a new assoc. Weird\n");
  1076. //
  1077. // log an error (Cleanup was not done properly)
  1078. //
  1079. return(WINS_FAILURE);
  1080. }
  1081. #endif
  1082. pAssocCtx->State_e = COMMASSOC_ASSOC_E_NON_EXISTENT;
  1083. pAssocCtx->Role_e = COMMASSOC_ASSOC_E_RESPONDER;
  1084. pAssocCtx->DlgHdl.pEnt = NULL;
  1085. if (fConnTcp)
  1086. {
  1087. pAssocCtx->RemoteAdd.sin_addr.s_addr =
  1088. ntohl(fsin.sin_addr.s_addr);
  1089. pAssocCtx->AddTyp_e = COMM_ADD_E_TCPUDPIP;
  1090. }
  1091. #if SPX > 0
  1092. else
  1093. {
  1094. RtlCopyMemory(
  1095. pAssocCtx->RemoteAddSpx.sa_netnum,
  1096. fsipx.netnum,
  1097. sizeof(fsipx.netnum);
  1098. RtlCopyMemory(
  1099. pAssocCtx->RemoteAddSpx.sa_nodenum,
  1100. fsipx.nodenum,
  1101. sizeof(fsipx.nodenum);
  1102. pAssocCtx->AddTyp_e = COMM_ADD_E_SPXIPX;
  1103. }
  1104. #endif
  1105. }
  1106. else /* one or more sockets has received data or a disconnect*/
  1107. {
  1108. #if MCAST > 0
  1109. if (CheckMcastSock(&ActSocks, &RdSocks) == TRUE)
  1110. {
  1111. continue;
  1112. }
  1113. #endif
  1114. //
  1115. // Check if the notification socket has data in it
  1116. // If yes, continue.
  1117. //
  1118. if (ChkNtfSock(&ActSocks, &RdSocks))
  1119. {
  1120. DBGPRINT0(FLOW,
  1121. "MonTcp: Notification socket had data in it\n");
  1122. continue;
  1123. }
  1124. /*
  1125. * Handle sockets that have been set. These could have
  1126. * been set either because there is data on them or
  1127. * due to disconnects.
  1128. */
  1129. for(No = 0; No < RdSocks.fd_count; ++No)
  1130. {
  1131. SockNo = RdSocks.fd_array[No];
  1132. if (FD_ISSET(SockNo, &RdSocks))
  1133. {
  1134. BytesRead = 0;
  1135. fSockCl = FALSE;
  1136. DBGPRINT1(FLOW, "MonTcp: Socket (%d) was signaled. It has either data or a disconnect on it\n",
  1137. SockNo);
  1138. /*
  1139. * Socket has data on it or a disconnect. Call
  1140. * HandleMsg to handle either case
  1141. */
  1142. (VOID)HandleMsg(SockNo, &BytesRead, &fSockCl);
  1143. /*
  1144. * if the socket was closed due to a stop message
  1145. * having been received, let us clean up the
  1146. * socket array
  1147. */
  1148. if (fSockCl)
  1149. {
  1150. DBGPRINT1(FLOW, "MonTcp: Sock (%d) was closed\n",
  1151. SockNo);
  1152. FD_CLR(SockNo, &ActSocks);
  1153. }
  1154. else
  1155. {
  1156. /*
  1157. * if bytes read are 0, we have a disconnect
  1158. * All the processing for the disconnect should
  1159. * have been handled by HandleMsg. We just need
  1160. * to close the socket and update the socket
  1161. * array appropriately.
  1162. */
  1163. if (BytesRead == 0)
  1164. {
  1165. DBGPRINT0(FLOW,
  1166. "MonTcp: Received a disconnect\n");
  1167. //CommDisc(SockNo, TRUE);
  1168. FD_CLR(SockNo, &ActSocks);
  1169. }
  1170. }
  1171. }
  1172. } //for (loop over all sockets)
  1173. } //else (one or more sockets has received data or a disconnect
  1174. } //else clause (if select () < 0)
  1175. } // while (TRUE) loop end
  1176. } // end of try {}
  1177. except (EXCEPTION_EXECUTE_HANDLER) {
  1178. DBGPRINTEXC("MONTCP");
  1179. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_TCP_LISTENER_EXC);
  1180. #if 0
  1181. //
  1182. // Don't use WinsMscTermThd here
  1183. //
  1184. ExitThread(WINS_FAILURE);
  1185. #endif
  1186. }
  1187. goto LOOPTCP; //ugly but useful
  1188. UNREFERENCED_PARAMETER(NoOfSockReady);
  1189. // we should never hit this return
  1190. ASSERT(0);
  1191. return(WINS_FAILURE);
  1192. }
  1193. DWORD
  1194. MonUdp(
  1195. LPVOID pArg
  1196. )
  1197. /*++
  1198. Routine Description:
  1199. This function is the thread startup function for the UDP listener
  1200. thread. It monitors the UDP port for UDP messages.
  1201. Arguments:
  1202. pArg - Argument (not used)
  1203. Externals Used:
  1204. CommUDPPortHandle -- UDP port for the process
  1205. Called by:
  1206. ECommInit
  1207. Comments:
  1208. None
  1209. Return Value:
  1210. Success status codes --
  1211. Error status codes --
  1212. --*/
  1213. {
  1214. register LPBYTE pBuffer;
  1215. struct sockaddr_in FromAdd;
  1216. int AddLen = sizeof(FromAdd);
  1217. register PCOMM_BUFF_HEADER_T pBuffHdr = NULL;
  1218. DWORD DataBuffLen;
  1219. tREM_ADDRESS *pRemAdd;
  1220. NTSTATUS NTStatus;
  1221. LOOP:
  1222. try {
  1223. while(TRUE)
  1224. {
  1225. //
  1226. // Allocate a buffer to get the datagram. This buffer is prefixed
  1227. // by the COMM_BUFF_HEADER_T and tREM_ADDRESS structure.
  1228. //
  1229. pBuffHdr = WinsMscHeapAlloc (
  1230. CommUdpBuffHeapHdl,
  1231. COMM_DATAGRAM_SIZE + sizeof(COMM_BUFF_HEADER_T)
  1232. + COMM_NETBT_REM_ADD_SIZE
  1233. );
  1234. DBGPRINT2(HEAP, "MonUdp: HeapHdl = (%p), pBuffHdr=(%p)\n",
  1235. CommUdpBuffHeapHdl, pRemAdd);
  1236. pBuffHdr->Typ_e = COMM_E_UDP;
  1237. //
  1238. // Adjust pointer to point to the Remote address header
  1239. //
  1240. pRemAdd = (tREM_ADDRESS *)
  1241. ((LPBYTE)pBuffHdr + sizeof(COMM_BUFF_HEADER_T));
  1242. DataBuffLen = COMM_DATAGRAM_SIZE + COMM_NETBT_REM_ADD_SIZE;
  1243. //
  1244. // Point to the data portion (passed to ParseMsg)
  1245. //
  1246. pBuffer = (LPBYTE)pRemAdd + COMM_NETBT_REM_ADD_SIZE;
  1247. //
  1248. // read a datagram prefixed with the address of the sender from
  1249. // nbt
  1250. //
  1251. NTStatus = DeviceIoCtrl(
  1252. &sNetbtRcvEvtHdl,
  1253. pRemAdd,
  1254. DataBuffLen,
  1255. IOCTL_NETBT_WINS_RCV
  1256. );
  1257. if (!NT_SUCCESS(NTStatus))
  1258. {
  1259. //
  1260. // log the message only if WINS is not terminating
  1261. //
  1262. if (WinsCnf.State_e != WINSCNF_E_TERMINATING)
  1263. {
  1264. //
  1265. // We do not log the message if the Netbt handle is NULL
  1266. // We can have a small window when the handle may be NULL
  1267. // This happens when we get an address/device change
  1268. // notification. WINS closes the old handle and opens
  1269. // a new one after such an event if the machine has a
  1270. // a valid address that WINS can bind with. The address
  1271. // notification can occur due to ipconfig /release and
  1272. // /renew or due to psched being installed/removed.
  1273. //
  1274. if (WinsCnfNbtHandle != NULL)
  1275. {
  1276. WINSEVT_LOG_D_M(
  1277. NTStatus,
  1278. WINS_EVT_NETBT_RECV_ERR
  1279. );
  1280. }
  1281. DBGPRINT1(ERR, "MonUdp: Status = (%x)\n", NTStatus);
  1282. WinsMscHeapFree( CommUdpBuffHeapHdl, pBuffHdr);
  1283. Sleep(0); //relinquish the processor
  1284. continue;
  1285. }
  1286. else
  1287. {
  1288. DBGPRINT0(ERR, "MonUdp, Exiting Thread\n");
  1289. WinsThdPool.CommThds[1].fTaken = FALSE;
  1290. #if TEST_HEAP > 0
  1291. WinsMscHeapDestroy(CommUdpBuffHeapHdl);
  1292. DBGPRINT0(ERR, "MonUdp: Destroyed udp buff heap\n");
  1293. WinsMscHeapDestroy(CommUdpDlgHeapHdl);
  1294. DBGPRINT0(ERR, "MonUdp: Destroyed udp dlg buff heap\n");
  1295. #endif
  1296. return(WINS_FAILURE);
  1297. }
  1298. }
  1299. #ifdef WINSDBG
  1300. ++CommNoOfDgrms;
  1301. DBGPRINT1(FLOW, "UDP listener thread: Got datagram (from NETBT) no = (%d)\n", CommNoOfDgrms);
  1302. // DBGPRINT1(SPEC, "UDP listener thread: Got datagram (from NETBT) no = (%d)\n", CommNoOfDgrms);
  1303. #endif
  1304. //
  1305. // NETBT returns the same code as is in winsock.h for the
  1306. // internet family. Also, port and IpAddress returned are
  1307. // in network order
  1308. //
  1309. FromAdd.sin_family = pRemAdd->Family;
  1310. FromAdd.sin_port = pRemAdd->Port;
  1311. FromAdd.sin_addr.s_addr = ntohl(pRemAdd->IpAddress);
  1312. // from now on the memory allocated for pBuffHdr is passed down the way so consider it handled there
  1313. // There is basically no chance to hit an exception (unless everything is really messed up - like no mem)
  1314. // in ParseMsg before having this buffer passed down to a different thread for processing.
  1315. pBuffHdr = NULL;
  1316. /*
  1317. * process message
  1318. */
  1319. (void)ParseMsg(
  1320. pBuffer,
  1321. COMM_DATAGRAM_SIZE,
  1322. COMM_E_UDP,
  1323. &FromAdd,
  1324. NULL
  1325. );
  1326. } //end of while(TRUE)
  1327. } // end of try {..}
  1328. except(EXCEPTION_EXECUTE_HANDLER) {
  1329. DWORD ExcCode = GetExceptionCode();
  1330. DBGPRINT1(EXC, "MonUdp: Got Exception (%X)\n", ExcCode);
  1331. if (ExcCode == STATUS_NO_MEMORY)
  1332. {
  1333. //
  1334. //If the exception is due to insufficient resources, it could
  1335. // mean that WINS is not able to keep up with the fast arrivel
  1336. // rate of the datagrams. In such a case drop the datagram.
  1337. //
  1338. WINSEVT_LOG_M( WINS_OUT_OF_HEAP, WINS_EVT_CANT_ALLOC_UDP_BUFF);
  1339. }
  1340. else
  1341. {
  1342. WINSEVT_LOG_M(ExcCode, WINS_EVT_UDP_LISTENER_EXC);
  1343. }
  1344. PERF("Check how many cycles try consumes. If negligeble, move try inside the")
  1345. PERF("the while loop")
  1346. #if 0
  1347. //Don't use WinsMscTermThd here
  1348. ExitThread(WINS_FAILURE);
  1349. #endif
  1350. } // end of exception
  1351. if (pBuffHdr != NULL)
  1352. WinsMscHeapFree(CommUdpBuffHeapHdl, pBuffHdr);
  1353. goto LOOP; //ugly but useful
  1354. //
  1355. // we should never hit this return
  1356. //
  1357. ASSERT(0);
  1358. return(WINS_FAILURE);
  1359. }
  1360. VOID
  1361. HandleMsg(
  1362. IN SOCKET SockNo,
  1363. OUT LPLONG pBytesRead,
  1364. OUT LPBOOL pfSockCl
  1365. )
  1366. /*++
  1367. Routine Description:
  1368. This function is called to read in a message or a disconnect from
  1369. a socket and handle either appropriately.
  1370. If there were no bytes received on the socket, tt
  1371. does the cleanup
  1372. The bytes read are handed to ProcTcpMsg function.
  1373. Arguments:
  1374. SockNo - Socket to read data from
  1375. pBytesRead - # of bytes that were read
  1376. fSockCl - whether the socket is in closed condition
  1377. Externals Used:
  1378. None
  1379. Called by:
  1380. MonTcp
  1381. Comments:
  1382. None
  1383. Return Value:
  1384. None
  1385. --*/
  1386. {
  1387. MSG_T pMsg;
  1388. STATUS RetStat;
  1389. /*
  1390. * Read in the message from the socket
  1391. */
  1392. // ---ft: 06/16/2000---
  1393. // The second parameter to the call below has to be TRUE (timed receive).
  1394. // If it is not so (it was FALSE before this moment) the following scenario
  1395. // could happen.
  1396. // An attacher creates a TCP socket and connects it to port 42 to any
  1397. // WINS server and then sends 4 or less bytes on that socket. He leaves the
  1398. // connection open (doesn't close the socket) and simply unplug his net cable.
  1399. // Then he kills his app. Although his end of the connection terminates, WINS
  1400. // will have no idea about that (since the cable is disconnected) and will
  1401. // remain blocked in the call below (CommReadStrea->RecvData->recv) indefinitely
  1402. //
  1403. // Consequences:
  1404. // - WINS will never be able again to listen on the TCP port 42: push/pull replication
  1405. // is brought down along with the consistency checking.
  1406. // - WINS will not be able to terminate gracefully (in case the administrator attempts
  1407. // to shut down the service and restart it) because the MonTcp thread is in a hung state
  1408. //
  1409. // The same could happen in more usual cases (not necesarily on an intenional attack):
  1410. // While sending Push notification (which happens quite often):
  1411. // 1) the pusher is powered down (power outage)
  1412. // 2) the pusher hits a PnP event like media disconnect or adapter disabled
  1413. // 3) some router is down between the pusher and the receiving WINS.
  1414. //
  1415. // With this fix the best we can do for now is to have MonTcp thread recover in 20mts.
  1416. // Even better would be to log an event.
  1417. RetStat = CommReadStream(
  1418. SockNo,
  1419. TRUE, //don't do timed recv
  1420. &pMsg,
  1421. pBytesRead
  1422. );
  1423. //
  1424. // if either RetStat is not WINS_SUCCESS or the number of bytes
  1425. // read are 0, we need to delete the association and close the
  1426. // socket. Further, we need to set *pfSockCl to TRUE to indicate
  1427. // to the caller (MonTcp) that it should get rid of the socket
  1428. // from its array of sockets.
  1429. //
  1430. if ((RetStat != WINS_SUCCESS) || (*pBytesRead == 0))
  1431. {
  1432. /*
  1433. * No bytes received. This means that it is a disconnect
  1434. * Let us get rid of the context associated with the socket
  1435. */
  1436. DelAssoc(
  1437. SockNo,
  1438. NULL /* we don't have the ptr to assoc block*/
  1439. );
  1440. CommDisc(SockNo, TRUE);
  1441. *pfSockCl = TRUE;
  1442. }
  1443. else // means (RetStat == WINS_SUCCESS) and (*pBytesRead > 0)
  1444. {
  1445. ASSERT(*pBytesRead > 0);
  1446. /*
  1447. * process the message
  1448. */
  1449. ProcTcpMsg(
  1450. SockNo,
  1451. pMsg,
  1452. *pBytesRead,
  1453. pfSockCl
  1454. );
  1455. }
  1456. return;
  1457. } // HandleMsg()
  1458. STATUS
  1459. CommReadStream(
  1460. IN SOCKET SockNo,
  1461. IN BOOL fDoTimedRecv,
  1462. OUT PMSG_T ppMsg,
  1463. OUT LPLONG pBytesRead
  1464. )
  1465. /*++
  1466. Routine Description:
  1467. This function reads from a TCP socket. If there are no bytes
  1468. there, it means a disconnect was received on that socket.
  1469. Arguments:
  1470. SockNo - Socket to read data from
  1471. fDoTimedRecv - Whether timed receive should be done (set to TRUE only
  1472. if we are not sure whether data has arrived or not yet)
  1473. ppMsg - Buffer containing data that was read in
  1474. pBytesRead - Size of buffer
  1475. Return Value:
  1476. TBS
  1477. --*/
  1478. {
  1479. u_long MsgLen;
  1480. LONG BytesToRead;
  1481. INT Flags = 0; /*flags for recv call (PEEK and/or OOB).
  1482. * we want neither
  1483. */
  1484. WINS_MEM_T WinsMem[2];
  1485. PWINS_MEM_T pWinsMem = WinsMem;
  1486. STATUS RetStat;
  1487. PCOMM_BUFF_HEADER_T pBuffHdr;
  1488. DBGENTER("CommReadStream\n");
  1489. pWinsMem->pMem = NULL;
  1490. #ifdef WINSDBG
  1491. try {
  1492. #endif
  1493. /*
  1494. * All TCP messages are preceded by a length word (4 bytes) that
  1495. * gives the length of the message that follows. Read the length
  1496. * bytes.
  1497. */
  1498. RetStat = RecvData(
  1499. SockNo,
  1500. (LPBYTE)&MsgLen,
  1501. sizeof(u_long),
  1502. Flags,
  1503. fDoTimedRecv ? TWENTY_MTS : fDoTimedRecv,
  1504. pBytesRead
  1505. );
  1506. /*
  1507. * Check if there was an error in reading. We will have a RetStat
  1508. * of WINS_SUCCESS even if 0 bytes (meaning a disconnect) were read
  1509. * in
  1510. */
  1511. if (RetStat == WINS_SUCCESS)
  1512. {
  1513. if (*pBytesRead != 0)
  1514. {
  1515. COMM_NET_TO_HOST_L_M(MsgLen, MsgLen);
  1516. //
  1517. // Just making sure that the message length did not get
  1518. // corrupted on the way. Also, this is a good guard against
  1519. // a process that is trying to bring us down.
  1520. //
  1521. if (MsgLen <= MAX_BYTES_IN_MSG)
  1522. {
  1523. /*
  1524. * Allocate memory for the buffer. Allocate extra space
  1525. * at the top to store the Header for the buffer. This
  1526. * header is used to store information about the buffer.
  1527. * (See ECommFreeBuff also)
  1528. */
  1529. *ppMsg = WinsMscHeapAlloc(
  1530. CommAssocTcpMsgHeapHdl,
  1531. MsgLen +
  1532. #if USENETBT > 0
  1533. COMM_NETBT_REM_ADD_SIZE +
  1534. #endif
  1535. sizeof(COMM_BUFF_HEADER_T) + sizeof(LONG)
  1536. );
  1537. //
  1538. // if *ppMsg is NULL, it means that we received garabage
  1539. // in the first 4 bytes. It should have been the length
  1540. // of the message.
  1541. //
  1542. if (*ppMsg == NULL)
  1543. {
  1544. //
  1545. // return with *pBytesRead = 0
  1546. //
  1547. *pBytesRead = 0;
  1548. return(WINS_FAILURE);
  1549. }
  1550. pWinsMem->pMem = *ppMsg;
  1551. (++pWinsMem)->pMem = NULL;
  1552. /*
  1553. * Increment pointer past the buffer header and field
  1554. * storing the length of the message.
  1555. */
  1556. pBuffHdr = (PCOMM_BUFF_HEADER_T)(*ppMsg + sizeof(LONG));
  1557. *ppMsg = *ppMsg +
  1558. #if USENETBT > 0
  1559. COMM_NETBT_REM_ADD_SIZE +
  1560. #endif
  1561. sizeof(COMM_BUFF_HEADER_T) + sizeof(LONG);
  1562. #if 0
  1563. pBuffHdr =
  1564. (PCOMM_BUFF_HEADER_T)(*ppMsg - sizeof(COMM_BUFF_HEADER_T));
  1565. #endif
  1566. pBuffHdr->Typ_e = COMM_E_TCP; //store type of buffer info
  1567. BytesToRead = MsgLen;
  1568. /*
  1569. * Read the whole message into the allocated buffer
  1570. */
  1571. RetStat = RecvData(
  1572. SockNo,
  1573. *ppMsg,
  1574. BytesToRead,
  1575. Flags,
  1576. fDoTimedRecv ? FIVE_MTS : fDoTimedRecv,
  1577. pBytesRead
  1578. );
  1579. //
  1580. // If no bytes were read, deallocate memory
  1581. //
  1582. if ((*pBytesRead == 0) || (RetStat != WINS_SUCCESS))
  1583. {
  1584. ECommFreeBuff(*ppMsg);
  1585. }
  1586. }
  1587. else
  1588. {
  1589. DBGPRINT1(ERR, "CommReadStream: Message size (%x) is TOO BIG\n", MsgLen);
  1590. WINSEVT_LOG_M(MsgLen, WINS_EVT_MSG_TOO_BIG);
  1591. *pBytesRead = 0;
  1592. }
  1593. }
  1594. } // if (RetStat == WINS_SUCCESS)
  1595. #ifdef WINSDBG
  1596. else
  1597. {
  1598. //
  1599. // *pBytesRead = 0 is a valid condition. It indicates a
  1600. // disconnect from the remote WINS
  1601. //
  1602. }
  1603. #endif
  1604. #ifdef WINSDBG
  1605. } // end of try { .. }
  1606. except (EXCEPTION_EXECUTE_HANDLER) {
  1607. DBGPRINTEXC("CommReadStream");
  1608. WINS_HDL_EXC_M(WinsMem);
  1609. WINS_RERAISE_EXC_M();
  1610. }
  1611. #endif
  1612. DBGLEAVE("CommReadStream\n");
  1613. return(RetStat);
  1614. } //CommReadStream()
  1615. VOID
  1616. ProcTcpMsg(
  1617. IN SOCKET SockNo,
  1618. IN MSG_T pMsg,
  1619. IN MSG_LEN_T MsgLen,
  1620. OUT LPBOOL pfSockCl
  1621. )
  1622. /*++
  1623. Routine Description:
  1624. This function processes a TCP message after it has been read in
  1625. Arguments:
  1626. SockNo - Socket on which data was received
  1627. pMsg - Buffer containing data
  1628. MsgLen - Size of buffer
  1629. pfSockCl - Flag indicating whether the socket was closed
  1630. Externals Used:
  1631. None
  1632. Return Value:
  1633. None
  1634. Error Handling:
  1635. Called by:
  1636. HandleMsg
  1637. Side Effects:
  1638. Comments:
  1639. None
  1640. --*/
  1641. {
  1642. #if SUPPORT612WINS > 0
  1643. BYTE AssocMsg[COMMASSOC_POST_BETA1_ASSOC_MSG_SIZE];
  1644. #else
  1645. BYTE AssocMsg[COMMASSOC_ASSOC_MSG_SIZE];
  1646. #endif
  1647. DWORD Opc;
  1648. DWORD MsgTyp;
  1649. DWORD MsgSz = sizeof(AssocMsg);
  1650. PCOMMASSOC_ASSOC_CTX_T pAssocCtx;
  1651. PCOMMASSOC_DLG_CTX_T pDlgCtx;
  1652. BOOL fAssocAV = FALSE;
  1653. DBGENTER("ProcTcpMsg\n");
  1654. //#ifdef WINSDBG
  1655. try {
  1656. //#endif
  1657. /*
  1658. Get the opcode and check whether it is an NBT message or a
  1659. message from a WINSS.
  1660. */
  1661. if (NMSISNBT_M(pMsg))
  1662. {
  1663. /*
  1664. * Get the assoc. ctx block associated with the socket
  1665. */
  1666. if ( (pAssocCtx = CommAssocLookupAssoc(SockNo) ) == NULL )
  1667. {
  1668. ECommFreeBuff(pMsg);
  1669. WINSEVT_LOG_D_M(WINS_FAILURE, WINS_EVT_CANT_LOOKUP_ASSOC);
  1670. WINS_RAISE_EXC_M(WINS_EXC_FAILURE);
  1671. }
  1672. if (pAssocCtx->DlgHdl.pEnt == NULL)
  1673. {
  1674. pDlgCtx = CommAssocAllocDlg();
  1675. //
  1676. // The following will initialize the dlg and assoc ctx
  1677. // blocks. The association will be marked ACTIVE.
  1678. //
  1679. COMMASSOC_SETUP_COMM_DS_M(
  1680. pDlgCtx,
  1681. pAssocCtx,
  1682. COMM_E_NBT,
  1683. COMMASSOC_DLG_E_IMPLICIT
  1684. );
  1685. }
  1686. /*
  1687. * Parse the message
  1688. */
  1689. ParseMsg(
  1690. pMsg,
  1691. MsgLen,
  1692. pAssocCtx->Typ_e,
  1693. &pAssocCtx->RemoteAdd,
  1694. pAssocCtx
  1695. );
  1696. }
  1697. else /*message from WINS */
  1698. {
  1699. ULONG uLocalAssocCtx;
  1700. COMM_GET_HEADER_M(pMsg, Opc, uLocalAssocCtx, MsgTyp);
  1701. DBGPRINT1(REPL,"ProcTcpMsg: Got Wins msg with tag %08x.\n", uLocalAssocCtx);
  1702. pAssocCtx = (PCOMMASSOC_ASSOC_CTX_T)CommAssocTagMap(&sTagAssoc, uLocalAssocCtx);
  1703. /*
  1704. If the ptr to my assoc. ctx block is NULL, it means that
  1705. this is the "start asssoc req" message from the remote WINS.
  1706. We don't need to check MsgTyp but are doing it anyway for more
  1707. robust error checking
  1708. */
  1709. if ((pAssocCtx == NULL) && (MsgTyp == COMM_START_REQ_ASSOC_MSG))
  1710. {
  1711. /*
  1712. Get the assoc. ctx block associated with the socket
  1713. */
  1714. if ( (pAssocCtx = CommAssocLookupAssoc(SockNo)) == NULL )
  1715. {
  1716. ECommFreeBuff(pMsg);
  1717. WINSEVT_LOG_D_M(WINS_FAILURE, WINS_EVT_CANT_LOOKUP_ASSOC);
  1718. WINS_RAISE_EXC_M(WINS_EXC_FAILURE);
  1719. }
  1720. /*
  1721. Unformat the assoc. message. This function will return
  1722. with an error status if the message received is not
  1723. a start assoc. message.
  1724. */
  1725. CommAssocUfmStartAssocReq(
  1726. pMsg,
  1727. &pAssocCtx->Typ_e,
  1728. &pAssocCtx->MajVersNo,
  1729. &pAssocCtx->MinVersNo,
  1730. &pAssocCtx->uRemAssocCtx
  1731. );
  1732. #if SUPPORT612WINS > 0
  1733. if (MsgLen >= (COMMASSOC_POST_BETA1_ASSOC_MSG_SIZE - sizeof(LONG)))
  1734. {
  1735. pAssocCtx->MajVersNo = WINS_BETA2_MAJOR_VERS_NO;
  1736. }
  1737. #endif
  1738. //
  1739. // Free the buffer read in.
  1740. //
  1741. ECommFreeBuff(pMsg);
  1742. /*
  1743. check if association set up params specified in the
  1744. message are acceptable.
  1745. */
  1746. //
  1747. // if the version numbers do not match, terminate the association
  1748. // and log a message
  1749. //
  1750. #if SUPPORT612WINS > 0
  1751. if (pAssocCtx->MajVersNo != WINS_BETA2_MAJOR_VERS_NO)
  1752. {
  1753. #endif
  1754. if (pAssocCtx->MajVersNo != WINS_MAJOR_VERS)
  1755. {
  1756. DelAssoc(0, pAssocCtx);
  1757. CommDisc(SockNo, TRUE);
  1758. *pfSockCl = TRUE;
  1759. //CommDecConnCount();
  1760. WINSEVT_LOG_M(pAssocCtx->MajVersNo, WINS_EVT_VERS_MISMATCH);
  1761. DBGLEAVE("ProcTcpMsg\n");
  1762. return;
  1763. }
  1764. #if SUPPORT612WINS > 0
  1765. }
  1766. #endif
  1767. FUTURES("When we support more sophisticated association set up protocol")
  1768. FUTURES("we will check the params. A more sophisticated set up protocol")
  1769. FUTURES("is one where there is some negotiation going one. Backward")
  1770. FUTURES("compatibility is another item which would require it")
  1771. /*
  1772. * Format a start assoc. response message.
  1773. *
  1774. * The address passed to the formatting function is offset
  1775. * from the address of the buffer by a LONG so that
  1776. * CommSendAssoc can store the length of the message in it.
  1777. */
  1778. CommAssocFrmStartAssocRsp(
  1779. pAssocCtx,
  1780. AssocMsg + sizeof(LONG),
  1781. MsgSz - sizeof(LONG)
  1782. );
  1783. CommSendAssoc(
  1784. pAssocCtx->SockNo,
  1785. AssocMsg + sizeof(LONG),
  1786. MsgSz - sizeof(LONG)
  1787. );
  1788. //
  1789. // Allocate the dlg and initialize the assoc and dlg ctx blocks.
  1790. // The association is marked ACTIVE
  1791. //
  1792. pDlgCtx = CommAssocAllocDlg();
  1793. COMMASSOC_SETUP_COMM_DS_M(
  1794. pDlgCtx,
  1795. pAssocCtx,
  1796. pAssocCtx->Typ_e,
  1797. COMMASSOC_DLG_E_IMPLICIT
  1798. );
  1799. }
  1800. else /*the assoc has to be in the ACTIVE state */
  1801. {
  1802. /*
  1803. Let us check that this is not the stop assoc message
  1804. */
  1805. if (MsgTyp == COMM_STOP_REQ_ASSOC_MSG)
  1806. {
  1807. fAssocAV = TRUE;
  1808. DelAssoc(0, pAssocCtx);
  1809. fAssocAV = FALSE;
  1810. ECommFreeBuff(pMsg);
  1811. CommDisc(SockNo, TRUE);
  1812. *pfSockCl = TRUE;
  1813. //CommDecConnCount();
  1814. }
  1815. else
  1816. {
  1817. PERF("Remove this test")
  1818. CHECK("Is there any need for this test")
  1819. fAssocAV = TRUE;
  1820. if (pAssocCtx->State_e == COMMASSOC_ASSOC_E_NON_EXISTENT)
  1821. {
  1822. fAssocAV = FALSE;
  1823. ECommFreeBuff(pMsg);
  1824. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_BAD_STATE_ASSOC);
  1825. DelAssoc(0, pAssocCtx);
  1826. CommDisc(SockNo, TRUE);
  1827. *pfSockCl = TRUE;
  1828. // CommDecConnCount();
  1829. WINS_RAISE_EXC_M(WINS_EXC_BAD_STATE_ASSOC);
  1830. }
  1831. else
  1832. {
  1833. fAssocAV = FALSE;
  1834. }
  1835. /*
  1836. * Parse the message header to determine what message it is.
  1837. */
  1838. ParseMsg(
  1839. pMsg,
  1840. MsgLen,
  1841. pAssocCtx->Typ_e,
  1842. &pAssocCtx->RemoteAdd, //not used
  1843. pAssocCtx
  1844. );
  1845. } //else (msg is not stop assoc msg)
  1846. } //else (assoc is active)
  1847. } // else (message is from a remote wins
  1848. //#ifdef WINSDBG
  1849. } // end of try block
  1850. except(EXCEPTION_EXECUTE_HANDLER) {
  1851. DWORD ExcCode = GetExceptionCode();
  1852. FUTURES("Distinguish between different exceptions. Handle some. Reraise others")
  1853. DBGPRINT1(EXC, "ProcTcpMsg: Got Exception (%x)\n", ExcCode);
  1854. WINSEVT_LOG_D_M(ExcCode, WINS_EVT_SFT_ERR);
  1855. if (ExcCode == WINS_EXC_COMM_FAIL)
  1856. {
  1857. DelAssoc(0, pAssocCtx);
  1858. CommDisc(SockNo, TRUE);
  1859. *pfSockCl = TRUE;
  1860. // CommDecConnCount();
  1861. }
  1862. if (fAssocAV)
  1863. {
  1864. ECommFreeBuff(pMsg);
  1865. // Without the following the assoc and the tcp connection
  1866. // will stay until either the tcp connection gets a valid
  1867. // message (one with the correct pAssocCtx) or it gets
  1868. // terminated
  1869. #if 0
  1870. DelAssoc(SockNo, NULL);
  1871. CommDisc(SockNo, TRUE);
  1872. *pfSockCl = TRUE;
  1873. // CommDecConnCount();
  1874. #endif
  1875. }
  1876. // WINS_RERAISE_EXC_M();
  1877. }
  1878. //#endif
  1879. DBGLEAVE("ProcTcpMsg\n");
  1880. return;
  1881. } //ProcTcpMsg()
  1882. VOID
  1883. CommCreateTcpThd(
  1884. VOID
  1885. )
  1886. /*++
  1887. Routine Description:
  1888. This function creates the TCP listener thread
  1889. Arguments:
  1890. None
  1891. Externals Used:
  1892. None
  1893. Called by:
  1894. CommInit
  1895. Comments:
  1896. Return Value:
  1897. None
  1898. --*/
  1899. {
  1900. CreateThd(MonTcp, WINSTHD_E_TCP);
  1901. return;
  1902. }
  1903. VOID
  1904. CommCreateUdpThd(VOID)
  1905. /*++
  1906. Routine Description:
  1907. This function creates the UDP listener thread
  1908. Arguments:
  1909. None
  1910. Externals Used:
  1911. None
  1912. Called by:
  1913. CommInit
  1914. Comments:
  1915. Return Value:
  1916. None
  1917. --*/
  1918. {
  1919. CreateThd(MonUdp, WINSTHD_E_UDP);
  1920. return;
  1921. }
  1922. VOID
  1923. CreateThd(
  1924. DWORD (*pStartFunc)(LPVOID),
  1925. WINSTHD_TYP_E ThdTyp_e
  1926. )
  1927. /*++
  1928. Routine Description:
  1929. This function creates a COMSYS thread and initializes the
  1930. context for it.
  1931. Arguments:
  1932. pStartFunc -- address of startup function for the thread
  1933. ThdTyp_e -- Type of thread (TCP listener or UDP listener)
  1934. Externals Used:
  1935. WinsThdPool
  1936. Called by:
  1937. CommCreateTCPThd, CommCreateUDPThd
  1938. Comments:
  1939. None
  1940. Return Value:
  1941. None
  1942. --*/
  1943. {
  1944. HANDLE ThdHandle;
  1945. DWORD ThdId;
  1946. INT No;
  1947. /*
  1948. Create a thread with no sec attributes (i.e. it will take the
  1949. security attributes of the process), and default stack size
  1950. */
  1951. ThdHandle = WinsMscCreateThd(
  1952. pStartFunc,
  1953. NULL, /*no arg*/
  1954. &ThdId
  1955. );
  1956. FUTURES("Improve the following to remove knowledge of # of threads in commsys")
  1957. /*
  1958. Grab the first slot for comm threads (2 slots in total) if available.
  1959. Else, use the second one. Initialize the thread context block
  1960. */
  1961. No = (WinsThdPool.CommThds[0].fTaken == FALSE) ? 0 : 1;
  1962. {
  1963. WinsThdPool.CommThds[No].fTaken = TRUE;
  1964. WinsThdPool.CommThds[No].ThdId = ThdId;
  1965. WinsThdPool.CommThds[No].ThdHdl = ThdHandle;
  1966. WinsThdPool.CommThds[No].ThdTyp_e = ThdTyp_e;
  1967. }
  1968. WinsThdPool.ThdCount++;
  1969. return;
  1970. }
  1971. STATUS
  1972. CommConnect(
  1973. IN PCOMM_ADD_T pHostAdd,
  1974. IN SOCKET Port,
  1975. OUT SOCKET *pSockNo
  1976. )
  1977. /*++
  1978. Routine Description:
  1979. This function creates a TCP connection to a destination host
  1980. Arguments:
  1981. pHostAdd --pointer to Host's address
  1982. Port -- Port number to connect to
  1983. pSockNo -- ptr to a Socket variable
  1984. Called by:
  1985. Externals Used:
  1986. Return Value:
  1987. TBS
  1988. --*/
  1989. {
  1990. //struct sockaddr_in sin; //*Internet endpoint address
  1991. DWORD ConnCount;
  1992. ConnCount = InterlockedExchange(&CommConnCount, CommConnCount);
  1993. #ifdef WINSDBG
  1994. if (ConnCount >= 200)
  1995. {
  1996. DBGPRINT0(ERR,
  1997. "MonTcp: Connection limit of 200 reached. \n");
  1998. }
  1999. #endif
  2000. #if 0
  2001. if (ConnCount >= FD_SETSIZE)
  2002. {
  2003. DBGPRINT2(EXC, "CommConnect: Socket Limit reached. Current no = (%d). Connection not being made to WINS. Address faimly of WINS is (%s)\n",
  2004. ConnCount,
  2005. pHostAdd->AddTyp_e == COMM_ADD_E_TCPUDPIP ? "TCPIP" : "SPXIPX"
  2006. );
  2007. WINSEVT_LOG_D_M(ConnCount, WINS_EVT_CONN_LIMIT_REACHED);
  2008. WINS_RAISE_EXC_M(WINS_EXC_COMM_FAIL);
  2009. }
  2010. #endif
  2011. #if SPX == 0
  2012. if (CommTcp(pHostAdd, Port, pSockNo) != WINS_SUCCESS)
  2013. {
  2014. return(WINS_FAILURE);
  2015. }
  2016. #else
  2017. if (pHostAdd->AddTyp_e == COMM_ADD_E_TCPUDPIP)
  2018. {
  2019. if (CommTcp(pHostAdd, Port, pSockNo) != WINS_SUCCESS)
  2020. {
  2021. return(WINS_FAILURE);
  2022. }
  2023. }
  2024. else
  2025. {
  2026. if (CommSpx(pHostAdd, Port, pSockNo) != WINS_SUCCESS)
  2027. {
  2028. return(WINS_FAILURE);
  2029. }
  2030. }
  2031. //
  2032. #endif
  2033. // Connection has been made. Let us increment the connection count
  2034. //
  2035. InterlockedIncrement(&CommConnCount);
  2036. return(WINS_SUCCESS);
  2037. }
  2038. STATUS
  2039. CommTcp(
  2040. IN PCOMM_ADD_T pHostAdd,
  2041. IN SOCKET Port,
  2042. OUT SOCKET *pSockNo
  2043. )
  2044. {
  2045. struct sockaddr_in destsin; //*Internet endpoint address
  2046. struct sockaddr_in srcsin;
  2047. // DWORD ConnCount;
  2048. if (pHostAdd->Add.IPAdd == INADDR_NONE)
  2049. {
  2050. return(WINS_FAILURE);
  2051. }
  2052. //
  2053. // Create a TCP socket and connect it to the target host
  2054. //
  2055. if ((*pSockNo = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
  2056. {
  2057. WINSEVT_LOG_M(
  2058. WSAGetLastError(),
  2059. WINS_EVT_CANT_CREATE_TCP_SOCK_FOR_CONN
  2060. );
  2061. return(WINS_FAILURE);
  2062. }
  2063. if (WinsClusterIpAddress) {
  2064. WINSMSC_FILL_MEMORY_M(&srcsin, sizeof(srcsin), 0);
  2065. srcsin.sin_addr.s_addr = htonl(WinsClusterIpAddress);
  2066. srcsin.sin_family = PF_INET;
  2067. srcsin.sin_port = 0;
  2068. if ( bind(*pSockNo,(struct sockaddr *)&srcsin,sizeof(srcsin)) == SOCKET_ERROR)
  2069. {
  2070. WINSEVT_LOG_M(WSAGetLastError(), WINS_EVT_WINSOCK_BIND_ERR); //log an event
  2071. return(WINS_FAILURE);
  2072. }
  2073. }
  2074. FUTURES("May want to call setsockopt() on it to enable graceful close")
  2075. WINSMSC_FILL_MEMORY_M(&destsin, sizeof(destsin), 0);
  2076. destsin.sin_addr.s_addr = htonl(pHostAdd->Add.IPAdd);
  2077. destsin.sin_family = PF_INET;
  2078. destsin.sin_port = (u_short)htons((u_short)Port);
  2079. if (
  2080. connect(*pSockNo, (struct sockaddr *)&destsin, sizeof(destsin))
  2081. == SOCKET_ERROR
  2082. )
  2083. {
  2084. struct in_addr InAddr;
  2085. InAddr.s_addr = destsin.sin_addr.s_addr;
  2086. WinsEvtLogDetEvt(FALSE, WINS_EVT_WINSOCK_CONNECT_ERR,
  2087. NULL, __LINE__, "sd",
  2088. COMM_NETFORM_TO_ASCII_M(&InAddr),
  2089. WSAGetLastError());
  2090. WINS_RAISE_EXC_M(WINS_EXC_COMM_FAIL);
  2091. }
  2092. return(WINS_SUCCESS);
  2093. }
  2094. #if SPX > 0
  2095. STATUS
  2096. CommSpx(
  2097. IN PCOMM_ADD_T pHostAdd,
  2098. IN SOCKET Port,
  2099. OUT SOCKET *pSockNo
  2100. )
  2101. {
  2102. struct sockaddr_ipx sipx; //*SPX/IPX endpoint address
  2103. LPVOID pRemAdd;
  2104. DWORD SizeOfRemAdd;
  2105. //
  2106. // Create an SPX socket and connect it to the target host
  2107. //
  2108. if ((*pSockNo = socket(PF_IPX, SOCK_STREAM, NSPROTO_SPX)) ==
  2109. INVALID_SOCKET)
  2110. {
  2111. WINSEVT_LOG_M(WSAGetLastError(),
  2112. WINS_EVT_CANT_CREATE_TCP_SOCK_FOR_CONN);
  2113. return(WINS_FAILURE);
  2114. }
  2115. WINSMSC_FILL_MEMORY_M(&sipx, sizeof(sipx), 0);
  2116. sipx.sa_socket = htons(Port);
  2117. sipx.sa_family = PF_IPX;
  2118. RtlCopyMemory(sipx.sa_netnum, pHostAdd->Add.netnum,
  2119. sizeof(pHostAdd->Add.netnum);
  2120. RtlCopyMemory(sipx.sa_nodenum, pHostAdd->Add.nodenum,
  2121. sizeof(pHostAdd->Add.nodenum);
  2122. FUTURES("May want to call setsockopt() on it to enable graceful close")
  2123. if (
  2124. connect(*pSockNo, (struct sockaddr *)&sipx, sizeof(sipx))
  2125. == SOCKET_ERROR
  2126. )
  2127. {
  2128. PERF("Pass address as binary data. Also log WSAGetLastError()")
  2129. WinsEvtLogDetEvt(FALSE, WINS_EVT_WINSOCK_CONNECT_ERR,
  2130. NULL, __LINE__, "sd",
  2131. sipx.sa_nodenum,
  2132. WSAGetLastError());
  2133. WINS_RAISE_EXC_M(WINS_EXC_COMM_FAIL);
  2134. }
  2135. return(WINS_SUCCESS);
  2136. }
  2137. #endif
  2138. VOID
  2139. CommSend(
  2140. COMM_TYP_E CommTyp_e,
  2141. PCOMM_HDL_T pAssocHdl,
  2142. MSG_T pMsg,
  2143. MSG_LEN_T MsgLen
  2144. )
  2145. /*++
  2146. Routine Description:
  2147. This function is called to send a TCP message to a WINS server or to
  2148. an nbt client
  2149. Arguments:
  2150. CommTyp_e - Type of communication
  2151. pAssocHdl - Handle to association to send message on
  2152. pMSg - Message to send
  2153. MsgLen - Length of above message
  2154. Externals Used:
  2155. None
  2156. Called by:
  2157. Replicator code
  2158. Comments:
  2159. This function should not be called for sending assoc messages.
  2160. Return Value:
  2161. None
  2162. --*/
  2163. {
  2164. PCOMM_HEADER_T pCommHdr = NULL;
  2165. PCOMMASSOC_ASSOC_CTX_T pAssocCtx = pAssocHdl->pEnt;
  2166. LPLONG pLong;
  2167. if (!CommLockBlock(pAssocHdl))
  2168. {
  2169. WINS_RAISE_EXC_M(WINS_EXC_LOCK_ASSOC_ERR);
  2170. }
  2171. try {
  2172. /*
  2173. * If it is not an NBT message (i.e. it is a WINS message), we
  2174. * need to set the header appropriately
  2175. */
  2176. if (CommTyp_e != COMM_E_NBT)
  2177. {
  2178. pCommHdr = (PCOMM_HEADER_T)(pMsg - COMM_HEADER_SIZE);
  2179. pLong = (LPLONG) pCommHdr;
  2180. COMM_SET_HEADER_M(
  2181. pLong,
  2182. WINS_IS_NOT_NBT,
  2183. pAssocCtx->uRemAssocCtx,
  2184. COMM_RPL_MSG
  2185. );
  2186. pMsg = (LPBYTE)pCommHdr;
  2187. MsgLen = MsgLen + COMM_HEADER_SIZE;
  2188. }
  2189. /*
  2190. send the message
  2191. */
  2192. CommSendAssoc(
  2193. pAssocCtx->SockNo,
  2194. pMsg,
  2195. MsgLen
  2196. );
  2197. }
  2198. finally {
  2199. CommUnlockBlock(pAssocHdl);
  2200. }
  2201. return;
  2202. }
  2203. VOID
  2204. CommSendAssoc(
  2205. SOCKET SockNo,
  2206. MSG_T pMsg,
  2207. MSG_LEN_T MsgLen
  2208. )
  2209. /*++
  2210. Routine Description:
  2211. This function is called to interface with the TCP/IP code for
  2212. sending a message on a TCP link
  2213. Arguments:
  2214. SockNo - Socket to send message on
  2215. pMsg - Message to send
  2216. MsgLen - Length of message to send
  2217. Externals Used:
  2218. None
  2219. Called by:
  2220. CommAssocSetUpAssoc
  2221. Comments:
  2222. None
  2223. Return Value:
  2224. None
  2225. --*/
  2226. {
  2227. int Flags = 0; //flags to indicate OOB or DONTROUTE
  2228. INT Error;
  2229. int BytesSent;
  2230. LONG Len = MsgLen;
  2231. LPLONG pLong = (LPLONG)(pMsg - sizeof(LONG));
  2232. int NoOfBytesToSend;
  2233. //initialize the last four bytes with the length of
  2234. //the message
  2235. COMM_HOST_TO_NET_L_M(Len, Len);
  2236. *pLong = Len;
  2237. MsgLen = MsgLen + 4;
  2238. while(MsgLen > 0)
  2239. {
  2240. //
  2241. // Since send(...) takes an int for the size of the message, let us
  2242. // be conservative (since int could be different on different
  2243. // machines) and not specify anything larger than MAXUSHORT.
  2244. //
  2245. // This strategy is also prudent since winsock may not work
  2246. // properly for sizes > 64K
  2247. //
  2248. if ( MsgLen > MAXUSHORT)
  2249. {
  2250. NoOfBytesToSend = MAXUSHORT;
  2251. }
  2252. else
  2253. {
  2254. NoOfBytesToSend = MsgLen;
  2255. }
  2256. BytesSent = send(
  2257. SockNo,
  2258. (LPBYTE)pLong,
  2259. NoOfBytesToSend,
  2260. Flags
  2261. );
  2262. if (BytesSent == SOCKET_ERROR)
  2263. {
  2264. Error = WSAGetLastError();
  2265. if (
  2266. (Error == WSAENOTCONN) ||
  2267. (Error == WSAECONNRESET) ||
  2268. (Error == WSAECONNABORTED) ||
  2269. (Error == WSAEDISCON)
  2270. )
  2271. {
  2272. DBGPRINT1(ERR, "CommSendAssoc: send returned SOCKET_ERROR due to connection abortion or reset. Error = (%d) \n", Error);
  2273. WINSEVT_LOG_D_M(
  2274. Error,
  2275. WINS_EVT_WINSOCK_SEND_MSG_ERR
  2276. );
  2277. WINS_RAISE_EXC_M(WINS_EXC_COMM_FAIL);
  2278. // break;
  2279. }
  2280. else
  2281. {
  2282. DBGPRINT1(ERR, "CommSendAssoc: send returned SOCKET_ERROR due to severe error = (%d) \n", Error);
  2283. //
  2284. // Some severe error. Raise an exception. We
  2285. // don't want the caller to ignore this.
  2286. //
  2287. WINSEVT_LOG_M(Error, WINS_EVT_WINSOCK_SEND_ERR);
  2288. WINS_RAISE_EXC_M(WINS_EXC_COMM_FAIL);
  2289. }
  2290. }
  2291. else
  2292. {
  2293. if (BytesSent < NoOfBytesToSend)
  2294. {
  2295. DBGPRINT2(ERR, "CommSendAssoc: Bytes Sent (%d) are < Specified (%d)\n", BytesSent, NoOfBytesToSend);
  2296. WINSEVT_LOG_D_M(BytesSent, WINS_EVT_WINSOCK_SEND_MSG_ERR);
  2297. /*
  2298. * The connection could have gone down because of the
  2299. * other side aborting in the middle
  2300. *
  2301. * We should log an error but not raise an exception.
  2302. */
  2303. //WINS_RAISE_EXC_M(WINS_EXC_FAILURE);
  2304. WINS_RAISE_EXC_M(WINS_EXC_COMM_FAIL);
  2305. // break;
  2306. }
  2307. else //BytesSent == NoOfBytesToSend
  2308. {
  2309. //
  2310. // Let us update the length left and the pointer into the
  2311. // buffer to send.
  2312. //
  2313. MsgLen -= BytesSent;
  2314. pLong = (LPLONG)((LPBYTE)pLong + BytesSent);
  2315. }
  2316. }
  2317. }
  2318. return;
  2319. } // CommSendAssoc()
  2320. VOID
  2321. CommDisc(
  2322. SOCKET SockNo,
  2323. BOOL fDecCnt
  2324. )
  2325. /*++
  2326. Routine Description:
  2327. This function closes the connection (socket)
  2328. Arguments:
  2329. SockNo - Socket that needs to be disconnected
  2330. Externals Used:
  2331. None
  2332. Called by:
  2333. MonTcp, HandleMsg, ProcTcpMsg, CommEndAssoc
  2334. Comments:
  2335. None
  2336. Return Value:
  2337. None
  2338. --*/
  2339. {
  2340. DBGPRINT1(FLOW, "CommDisc: Closing socket = (%d)\n", SockNo);
  2341. if (closesocket(SockNo) == SOCKET_ERROR)
  2342. {
  2343. WINSEVT_LOG_M(WSAGetLastError(),
  2344. WINS_EVT_WINSOCK_CLOSESOCKET_ERR);
  2345. //WINS_RAISE_EXC_M(WINS_EXC_FAILURE);
  2346. }
  2347. #ifdef WINSDBG
  2348. if (!sfMemoryOverrun)
  2349. {
  2350. if ((UINT_PTR)(pTmpW + 2) < (UINT_PTR)pEndPtr)
  2351. {
  2352. *pTmpW++ = 0xEFFFFFFE;
  2353. *pTmpW++ = SockNo;
  2354. }
  2355. else
  2356. {
  2357. WinsDbg |= 0x3;
  2358. DBGPRINT0(ERR, "CommDisc: Stopping socket close tracking to prevent Memory overrun\n")
  2359. sfMemoryOverrun = TRUE;
  2360. }
  2361. }
  2362. #endif
  2363. if (fDecCnt)
  2364. {
  2365. CommDecConnCount();
  2366. }
  2367. return;
  2368. }
  2369. VOID
  2370. CommSendUdp (
  2371. SOCKET SockNo,
  2372. struct sockaddr_in *pDest,
  2373. MSG_T pMsg,
  2374. MSG_LEN_T MsgLen
  2375. )
  2376. /*++
  2377. Routine Description:
  2378. This function is called to send a message to an NBT node using the
  2379. datagram port
  2380. Arguments:
  2381. SockNo - Socket to send message on (UDP port)
  2382. pDest - Address of node to send message to
  2383. pMsg - Message to send
  2384. MsgLen - Length of message to send
  2385. Externals Used:
  2386. None
  2387. Called by:
  2388. NmsNmh functions
  2389. Comments:
  2390. None
  2391. Return Value:
  2392. None
  2393. --*/
  2394. {
  2395. DWORD BytesSent;
  2396. DWORD Error;
  2397. int Flags = 0;
  2398. struct sockaddr_in CopyOfDest;
  2399. #if USENETBT > 0
  2400. //
  2401. // When the address to send the datagram to is CommNtfSockAdd, we
  2402. // use sockets, else we send it over NETBT.
  2403. //
  2404. #if MCAST > 0
  2405. if ((pDest != &CommNtfSockAdd) && (SockNo != CommUdpPortHandle))
  2406. #else
  2407. if (pDest != &CommNtfSockAdd)
  2408. #endif
  2409. {
  2410. SendNetbt(pDest, pMsg, MsgLen);
  2411. return;
  2412. }
  2413. #endif
  2414. //
  2415. // use copy of the destination so that when we change the byte
  2416. // order in it, we don't disturb the source. This is important
  2417. // because CommSendUdp can be called multiple times by HdlPushNtf
  2418. // in the Push thread with pDest pointing to the address of the
  2419. // UDP socket used by the TCP listener thread. This address is
  2420. // in host byte order and should not be changed
  2421. //
  2422. CopyOfDest = *pDest;
  2423. CopyOfDest.sin_addr.s_addr = htonl(pDest->sin_addr.s_addr);
  2424. BytesSent = (DWORD)sendto(
  2425. SockNo,
  2426. pMsg,
  2427. MsgLen,
  2428. Flags,
  2429. (struct sockaddr *)&CopyOfDest,
  2430. sizeof(struct sockaddr)
  2431. );
  2432. if ((BytesSent != MsgLen) || (BytesSent == SOCKET_ERROR))
  2433. {
  2434. Error = WSAGetLastError();
  2435. #ifdef WINSDBG
  2436. if (BytesSent == SOCKET_ERROR)
  2437. {
  2438. DBGPRINT1(ERR, "CommSendUdp:SendTo returned socket error. Error = (%d)\n", Error);
  2439. }
  2440. else
  2441. {
  2442. DBGPRINT0(ERR, "CommSendUdp:SendTo did not send all the bytes");
  2443. }
  2444. #endif
  2445. if (WinsCnf.State_e != WINSCNF_E_TERMINATING)
  2446. {
  2447. WINSEVT_LOG_D_M(Error, WINS_EVT_WINSOCK_SENDTO_ERR);
  2448. }
  2449. //
  2450. // Don't raise exception since sendto might have failed as
  2451. // a result of wrong address in the RFC name request packet.
  2452. //
  2453. // For sending responses to name requests, there is no
  2454. // possibility of WINS using a wrong address since the
  2455. // address it uses is the one that it got from recvfrom
  2456. // (stored In FromAdd field of the dlg ctx block.
  2457. //
  2458. // The possibility of a wrong address being there is
  2459. // only there when a WACK/name query/name release is sent
  2460. // by WINS. In this case, it takes the address that is
  2461. // stored in the database for the conflicting entry (this
  2462. // address is ofcourse the one that was passed in the
  2463. // RFC packet
  2464. //
  2465. // WSAEINVAL error is returned by GetLastError if the
  2466. // address is invalid (winsock document doesn't list this --
  2467. // inform Dave Treadwell about this).
  2468. //
  2469. FUTURES("At name registration, should WINS make sure that the address in ")
  2470. FUTURES("the packet is the same as the address it got from recvfrom")
  2471. FUTURES("probably yes")
  2472. //WINS_RAISE_EXC_M(WINS_EXC_FAILURE);
  2473. }
  2474. return;
  2475. }
  2476. #if USENETBT > 0
  2477. VOID
  2478. SendNetbt (
  2479. struct sockaddr_in *pDest,
  2480. MSG_T pMsg,
  2481. MSG_LEN_T MsgLen
  2482. )
  2483. /*++
  2484. Routine Description:
  2485. This function is called to send a datagram through NETBT
  2486. Arguments:
  2487. Externals Used:
  2488. None
  2489. Return Value:
  2490. Success status codes --
  2491. Error status codes --
  2492. Error Handling:
  2493. Called by:
  2494. Side Effects:
  2495. Comments:
  2496. None
  2497. --*/
  2498. {
  2499. //
  2500. // Point to the address structure prefix
  2501. //
  2502. tREM_ADDRESS *pRemAdd = (tREM_ADDRESS *)(pMsg -
  2503. COMM_NETBT_REM_ADD_SIZE);
  2504. #ifdef JIM
  2505. {
  2506. BYTE TransId = *pMsg;
  2507. ASSERT(TransId == 0x80);
  2508. }
  2509. #endif
  2510. pRemAdd->Family = pDest->sin_family;
  2511. pRemAdd->Port = pDest->sin_port;
  2512. pRemAdd->IpAddress = htonl(pDest->sin_addr.s_addr);
  2513. #ifdef JIM
  2514. ASSERT(MsgLen > 0x20);
  2515. #endif
  2516. pRemAdd->LengthOfBuffer = MsgLen;
  2517. DeviceIoCtrl(
  2518. &sNetbtSndEvtHdl,
  2519. pRemAdd,
  2520. MsgLen + COMM_NETBT_REM_ADD_SIZE,
  2521. IOCTL_NETBT_WINS_SEND
  2522. );
  2523. return;
  2524. }
  2525. #endif
  2526. VOID
  2527. ParseMsg(
  2528. MSG_T pMsg,
  2529. MSG_LEN_T MsgLen,
  2530. COMM_TYP_E MsgTyp_e,
  2531. struct sockaddr_in *pFromAdd,
  2532. PCOMMASSOC_ASSOC_CTX_T pAssocCtx
  2533. )
  2534. /*++
  2535. Routine Description:
  2536. This function is called to process a message received on the
  2537. UDP port or a TCP connection.
  2538. Arguments:
  2539. pMsg - ptr to message received
  2540. MsgLen - length of message received
  2541. MsgType - type of message
  2542. pFromAdd - ptr to who it is from
  2543. pAssocHdl - Assoc Handle if it came on an association
  2544. Externals Used:
  2545. CommUdpNbtDlgTable
  2546. Called by:
  2547. ProcTcpMsg, MonUdp
  2548. Comments:
  2549. None
  2550. Return Value:
  2551. None
  2552. --*/
  2553. {
  2554. COMM_HDL_T DlgHdl;
  2555. COMMASSOC_DLG_CTX_T DlgCtx;
  2556. register PCOMMASSOC_DLG_CTX_T pDlgCtx;
  2557. BOOL fNewElem = FALSE;
  2558. try {
  2559. /*
  2560. * If the assoc handle is NULL, this is a UDP message
  2561. */
  2562. if (pAssocCtx == NULL)
  2563. {
  2564. /*
  2565. * Check if this message is a response. If it is, the explicit
  2566. * dialogue is used
  2567. */
  2568. if (*(pMsg + 2) & NMS_RESPONSE_MASK)
  2569. {
  2570. ENmsHandleMsg(
  2571. &CommExNbtDlgHdl,
  2572. pMsg,
  2573. MsgLen
  2574. );
  2575. return;
  2576. }
  2577. /*
  2578. * Initialize the STATIC dlg ctx block with the fields that the
  2579. * compare function will use to check if this is a duplicate
  2580. */
  2581. WINSMSC_COPY_MEMORY_M(
  2582. &DlgCtx.FromAdd,
  2583. pFromAdd,
  2584. sizeof(struct sockaddr_in)
  2585. );
  2586. //
  2587. // Copy the first four bytes of the message into the FirstWrdOfMsg
  2588. // field of the Dlg Ctx block. The first 4 bytes contain the
  2589. // transaction id and the opcode. These values along with the
  2590. // address of the sender are used by CompareNbtReq to determine
  2591. // whether a request is a repeat request or a new one.
  2592. //
  2593. // Note: The message buffer and the dlg ctx block are deleted
  2594. // in different functions, the message buffer getting deleted
  2595. // first. We can not use the pointer to the message
  2596. // buffer for the purposes of getting at the first word at
  2597. // comparison time since then we open ourselves to the possibility
  2598. // of two dialogues pointing to the same block for a finite
  2599. // window (true, when requests are coming rapidly)
  2600. //
  2601. FUTURES("Directly assign the value instead of copying it")
  2602. WINSMSC_COPY_MEMORY_M(
  2603. &DlgCtx.FirstWrdOfMsg,
  2604. pMsg,
  2605. sizeof(DWORD)
  2606. );
  2607. /*
  2608. create and insert a dlg ctx block into the table of
  2609. NBT type Implicit dialogues. The key to searching for
  2610. a duplicate inside the table comprises of the Transaction Id
  2611. of the message, and the FromAdd of the nbt node that sent the
  2612. datagram.
  2613. (refer : CheckDlgDuplicate function).
  2614. */
  2615. pDlgCtx = CommAssocInsertUdpDlgInTbl(&DlgCtx, &fNewElem);
  2616. if (pDlgCtx == NULL)
  2617. {
  2618. WINS_RAISE_EXC_M(WINS_EXC_OUT_OF_MEM);
  2619. }
  2620. /*
  2621. * If the dialogue for the particular command from the nbt node is
  2622. * already there, we will ignore this request, deallocate the
  2623. * UDP buffer and return.
  2624. */
  2625. if (!fNewElem)
  2626. {
  2627. DBGPRINT0(FLOW, "Not a new element\n");
  2628. ECommFreeBuff(pMsg);
  2629. #ifdef WINSDBG
  2630. CommNoOfRepeatDgrms++;
  2631. #endif
  2632. return;
  2633. }
  2634. /*
  2635. * Initialize the dlg ctx block that got inserted
  2636. */
  2637. pDlgCtx->Role_e = COMMASSOC_DLG_E_IMPLICIT;
  2638. pDlgCtx->Typ_e = COMM_E_UDP;
  2639. DlgHdl.pEnt = pDlgCtx;
  2640. /*
  2641. * Call name space manager to handle the request
  2642. */
  2643. ENmsHandleMsg(&DlgHdl, pMsg, MsgLen);
  2644. }
  2645. else // the request came over an association
  2646. {
  2647. pDlgCtx = pAssocCtx->DlgHdl.pEnt;
  2648. //
  2649. // required by the PULL thread (HandlePushNtf).
  2650. // and the PUSH thread to print out the address of the WINS
  2651. // that sent the push trigger or the Pull request
  2652. //
  2653. WINSMSC_COPY_MEMORY_M(
  2654. &pDlgCtx->FromAdd,
  2655. pFromAdd,
  2656. sizeof(struct sockaddr_in)
  2657. );
  2658. /*
  2659. * The request came over a TCP connection. Examine the Dlg type
  2660. * and then call the appropriate component
  2661. */
  2662. if (pAssocCtx->Typ_e == COMM_E_NBT)
  2663. {
  2664. /*
  2665. * It is an nbt request over a TCP connection. Call
  2666. * the Name Space Manager
  2667. */
  2668. ENmsHandleMsg(
  2669. &pAssocCtx->DlgHdl,
  2670. pMsg,
  2671. MsgLen
  2672. );
  2673. }
  2674. else
  2675. {
  2676. /*
  2677. * Call the replicator component
  2678. *
  2679. * Note: pMsg points to COMM_HEADER_T on top of the
  2680. * data. We strip it off
  2681. */
  2682. DBGIF(fWinsCnfRplEnabled)
  2683. ERplInsertQue(
  2684. WINS_E_COMSYS,
  2685. QUE_E_CMD_REPLICATE_MSG,
  2686. &pAssocCtx->DlgHdl,
  2687. pMsg + COMM_HEADER_SIZE,
  2688. MsgLen - COMM_HEADER_SIZE,
  2689. NULL, // no context
  2690. 0 // no magic no.
  2691. );
  2692. }
  2693. }
  2694. }
  2695. except(EXCEPTION_EXECUTE_HANDLER) {
  2696. DBGPRINTEXC("ParseMsg");
  2697. /*
  2698. * If this dialogue was allocated as a result of an Insert
  2699. * get rid of it.
  2700. */
  2701. if (fNewElem)
  2702. {
  2703. CommAssocDeleteUdpDlgInTbl( pDlgCtx );
  2704. }
  2705. WINS_RERAISE_EXC_M();
  2706. }
  2707. return;
  2708. }
  2709. LPVOID
  2710. CommAlloc(
  2711. IN PRTL_GENERIC_TABLE pTable,
  2712. IN CLONG BuffSize
  2713. )
  2714. /*++
  2715. Routine Description:
  2716. This function is called to allocate a buffer
  2717. Arguments:
  2718. pTable - Table where the buffer will be stored
  2719. BuffSize - Size of buffer to allocate
  2720. Externals Used:
  2721. None
  2722. Return Value:
  2723. Success status codes -- ptr to buffer allocated
  2724. Error status codes --
  2725. Error Handling:
  2726. Called by:
  2727. RtlInsertElementGeneric()
  2728. Side Effects:
  2729. Comments:
  2730. This function exists just because the RtlTbl functions require
  2731. this prototype for the user specified alloc function.
  2732. --*/
  2733. {
  2734. LPVOID pTmp;
  2735. UNREFERENCED_PARAMETER(pTable);
  2736. WinsMscAlloc( (DWORD) BuffSize, &pTmp );
  2737. return(pTmp);
  2738. }
  2739. VOID
  2740. CommDealloc(
  2741. IN PRTL_GENERIC_TABLE pTable,
  2742. IN PVOID pBuff
  2743. )
  2744. /*++
  2745. Routine Description:
  2746. This function is called to deallocate memory allocated via CommAlloc.
  2747. Arguments:
  2748. pTable - Table where buffer was stored
  2749. pBuff - Buffer to deallocate
  2750. Externals Used:
  2751. None
  2752. Return Value:
  2753. None
  2754. Error Handling:
  2755. Called by:
  2756. Side Effects:
  2757. Comments:
  2758. The pTable argument is required since the address of this function
  2759. is passed as an argument to RtlTbl functions
  2760. --*/
  2761. {
  2762. UNREFERENCED_PARAMETER(pTable);
  2763. WinsMscDealloc(
  2764. pBuff
  2765. );
  2766. return;
  2767. }
  2768. #if 0
  2769. RTL_GENERIC_COMPARE_RESULTS
  2770. CompareAssoc(
  2771. IN PRTL_GENERIC_TABLE pTable,
  2772. IN PVOID pFirstAssoc,
  2773. IN PVOID pSecondAssoc
  2774. )
  2775. /*++
  2776. Routine Description:
  2777. The function compares the first and the second assoc. structures
  2778. Arguments:
  2779. pTable - table where buffer (assoc. ctx block) is to be stored
  2780. pFirstAssoc - First assoc ctx block
  2781. pSecondAssoc - Second assoc ctx block
  2782. Externals Used:
  2783. None
  2784. Return Value:
  2785. Success status codes --
  2786. Error status codes --
  2787. Error Handling:
  2788. Called by:
  2789. RtlInsertElementGenericTable (called by MonTcp)
  2790. Side Effects:
  2791. Comments:
  2792. The pTable argument is ignored.
  2793. This function was once being used. Due to change in code, it is
  2794. no longer being used. It is kept here for potential future use
  2795. --*/
  2796. {
  2797. PCOMMASSOC_ASSOC_CTX_T pFirst = pFirstAssoc;
  2798. PCOMMASSOC_ASSOC_CTX_T pSecond = pSecondAssoc;
  2799. if (pFirst->SockNo == pSecond->SockNo)
  2800. {
  2801. return(GenericEqual);
  2802. }
  2803. if (pFirst->SockNo > pSecond->SockNo)
  2804. {
  2805. return(GenericGreaterThan);
  2806. }
  2807. else
  2808. {
  2809. return(GenericLessThan);
  2810. }
  2811. }
  2812. #endif
  2813. RTL_GENERIC_COMPARE_RESULTS
  2814. CommCompareNbtReq(
  2815. IN PRTL_GENERIC_TABLE pTable,
  2816. IN PVOID pFirstDlg,
  2817. IN PVOID pSecondDlg
  2818. )
  2819. /*++
  2820. Routine Description:
  2821. This function compares two dialogue context blocks. The fields
  2822. used for comparison are:
  2823. the address of the sender
  2824. the first long word of the message (contains transaction id
  2825. and opcode)
  2826. Arguments:
  2827. pTable - Table where the Dialogue for the NBT request will be stored
  2828. pFirstDlg - Dlg. ctx. block
  2829. pSecondDlg - Dlg. ctx. block
  2830. Externals Used:
  2831. None
  2832. Return Value:
  2833. Success status codes -- GenericLessThan or GenericGreaterThan
  2834. Error status codes -- GenericEqual
  2835. Error Handling:
  2836. Called by:
  2837. RtlInsertElementGenericTable (called by ParseMsg)
  2838. Side Effects:
  2839. Comments:
  2840. The pTable argument is ignored.
  2841. --*/
  2842. {
  2843. PCOMMASSOC_DLG_CTX_T pFirst = pFirstDlg;
  2844. PCOMMASSOC_DLG_CTX_T pSecond = pSecondDlg;
  2845. LONG Val = 0;
  2846. LONG FirstMsgLong = pFirst->FirstWrdOfMsg;
  2847. LONG SecondMsgLong = pSecond->FirstWrdOfMsg;
  2848. //
  2849. // There seems to be no Rtl function with the functionality of memcmp
  2850. // RtlCompareMemory does not tell you which of the comparators is
  2851. // smaller/larger
  2852. //
  2853. CHECK("Is there an Rtl function faster than memcmp in the nt arsenal\n");
  2854. if ( (Val = (long)memcmp(
  2855. &pFirst->FromAdd,
  2856. &pSecond->FromAdd,
  2857. sizeof(struct sockaddr_in)
  2858. )
  2859. ) > 0
  2860. )
  2861. {
  2862. return(GenericGreaterThan);
  2863. }
  2864. else
  2865. {
  2866. if (Val < 0)
  2867. {
  2868. return(GenericLessThan);
  2869. }
  2870. }
  2871. /*
  2872. if the addresses are the same, compare the first long word of
  2873. the message
  2874. */
  2875. Val = FirstMsgLong - SecondMsgLong;
  2876. if (Val > 0)
  2877. {
  2878. return(GenericGreaterThan);
  2879. }
  2880. else
  2881. {
  2882. if (Val < 0)
  2883. {
  2884. return(GenericLessThan);
  2885. }
  2886. }
  2887. return(GenericEqual);
  2888. } // CommCompareNbtReq()
  2889. VOID
  2890. CommEndAssoc(
  2891. IN PCOMM_HDL_T pAssocHdl
  2892. )
  2893. /*++
  2894. Routine Description:
  2895. This function is called to terminate an explicit association. It sends a stop
  2896. association response message to the WINS identified by the Address
  2897. in the assoc ctx block. It then closes the socket and deallocates the
  2898. association
  2899. Arguments:
  2900. pAssocHdl - Handle to the Association to be terminated
  2901. Externals Used:
  2902. None
  2903. Return Value:
  2904. None
  2905. Error Handling:
  2906. Called by:
  2907. ECommEndDlg (only for an explicit assoc)
  2908. Side Effects:
  2909. Comments:
  2910. --*/
  2911. {
  2912. BYTE Msg[COMMASSOC_ASSOC_MSG_SIZE];
  2913. DWORD MsgLen = COMMASSOC_ASSOC_MSG_SIZE;
  2914. PCOMMASSOC_ASSOC_CTX_T pAssocCtx = pAssocHdl->pEnt;
  2915. SOCKET SockNo;
  2916. // no need to lock the association
  2917. //
  2918. try {
  2919. /*
  2920. Format the Stop Assoc. Message
  2921. The address passed to the formatting function is offset
  2922. from the address of the buffer by a LONG so that CommSendAssoc
  2923. can store the length of the message in it.
  2924. */
  2925. CommAssocFrmStopAssocReq(
  2926. pAssocCtx,
  2927. Msg + sizeof(LONG),
  2928. MsgLen - sizeof(LONG),
  2929. COMMASSOC_E_USER_INITIATED
  2930. );
  2931. CommSendAssoc(
  2932. pAssocCtx->SockNo,
  2933. Msg + sizeof(LONG),
  2934. MsgLen - sizeof(LONG)
  2935. );
  2936. CommAssocTagFree(&sTagAssoc, pAssocCtx->nTag);
  2937. }
  2938. except(EXCEPTION_EXECUTE_HANDLER) {
  2939. DBGPRINTEXC("CommEndAssoc");
  2940. }
  2941. //
  2942. // The above call might have failed (It will fail if the connection
  2943. // is down. This can happen for instance in the case where GetReplicas()
  2944. // in rplpull gets a comm. failure due to the connection going down).
  2945. //
  2946. SockNo = pAssocCtx->SockNo;
  2947. CommAssocDeallocAssoc(pAssocCtx);
  2948. CommDisc(SockNo, TRUE);
  2949. //
  2950. // decrement the conn. count
  2951. //
  2952. //CommDecConnCount();
  2953. return;
  2954. }
  2955. VOID
  2956. DelAssoc(
  2957. IN SOCKET SockNo,
  2958. IN PCOMMASSOC_ASSOC_CTX_T pAssocCtxPassed
  2959. )
  2960. /*++
  2961. Routine Description:
  2962. This function is called only by the TCP listener thread. The
  2963. socket no. therefore maps to a RESPONDER association. The function
  2964. is called when the TCP listener thread gets an error or 0 bytes
  2965. on doing a 'recv'.
  2966. Arguments:
  2967. SockNo - Socket of association that has to be removed
  2968. pAssocCtx - Assoc. ctx block to be removed
  2969. Externals Used:
  2970. None
  2971. Return Value:
  2972. None
  2973. Error Handling:
  2974. Called by:
  2975. ProcTcpMsg, HandleMsg
  2976. Side Effects:
  2977. Comments:
  2978. This function is called from HandleMsg() which is called
  2979. only by the TCP listener thread.
  2980. --*/
  2981. {
  2982. COMM_HDL_T DlgHdl;
  2983. PCOMMASSOC_ASSOC_CTX_T pAssocCtx;
  2984. DBGPRINT1(FLOW, "ENTER: DelAssoc. Sock No is (%d)\n", SockNo);
  2985. if (pAssocCtxPassed == NULL)
  2986. {
  2987. /*
  2988. Lookup the assoc. ctx block associated with the socket
  2989. */
  2990. pAssocCtx = CommAssocLookupAssoc(SockNo);
  2991. /*
  2992. * There is no reason why the assoc. ctx block should not
  2993. * be there (a responder association is deleted only via this
  2994. * function).
  2995. */
  2996. if(!pAssocCtx)
  2997. {
  2998. WINS_RAISE_EXC_M(WINS_EXC_FAILURE);
  2999. }
  3000. }
  3001. else
  3002. {
  3003. pAssocCtx = pAssocCtxPassed;
  3004. }
  3005. /*
  3006. * Only, if the association is not in the non-existent state,
  3007. * look for a dialogue handle
  3008. */
  3009. if (pAssocCtx->State_e != COMMASSOC_ASSOC_E_NON_EXISTENT)
  3010. {
  3011. /*
  3012. * get the dialogue handle
  3013. */
  3014. DlgHdl = pAssocCtx->DlgHdl;
  3015. /*
  3016. * Lock the dialogue
  3017. *
  3018. * We have to synchronize with thread calling CommSndRsp
  3019. */
  3020. CommLockBlock(&pAssocCtx->DlgHdl);
  3021. /*
  3022. Remove the assoc. from the table. This will also put
  3023. the assoc. in the free list.
  3024. */
  3025. CommAssocDeleteAssocInTbl( pAssocCtx );
  3026. /*
  3027. dealloc the dialogue (i.e. put it in the free list)
  3028. Note: An implicit dialogue is deleted when the association(s)
  3029. it is mapped to terminates. If this dialogue was earlier
  3030. passed on to a client, the client will find out that it
  3031. has been deleted (via a communications failure exception)
  3032. when it tries to use it (which may be never) -- see ECommSndRsp
  3033. */
  3034. CommAssocDeallocDlg( DlgHdl.pEnt );
  3035. /*
  3036. Unlock the dialogue so that other threads can use it
  3037. */
  3038. CommUnlockBlock(&DlgHdl);
  3039. }
  3040. else
  3041. {
  3042. /*
  3043. Remove the assoc. from the table. This will also put
  3044. the assoc. in the free list
  3045. */
  3046. CommAssocDeleteAssocInTbl(pAssocCtx);
  3047. }
  3048. DBGLEAVE("DelAssoc\n");
  3049. return;
  3050. }
  3051. #if PRSCONN
  3052. BOOL
  3053. CommIsBlockValid (
  3054. IN PCOMM_HDL_T pEntHdl
  3055. )
  3056. /*++
  3057. Routine Description:
  3058. This function is called to check if the hdl is valid
  3059. Arguments:
  3060. pEntHdl - Handle to entity to lock
  3061. Externals Used:
  3062. None
  3063. Return Value:
  3064. Success status codes -- TRUE
  3065. Error status codes -- FALSE
  3066. Error Handling:
  3067. Called by:
  3068. Side Effects:
  3069. Comments:
  3070. None
  3071. --*/
  3072. {
  3073. //
  3074. // pEnt will be NULL for a persistent dlg that was never created during
  3075. // the lifetime of this WINS instance or one that was ended.
  3076. //
  3077. if (pEntHdl->pEnt == NULL)
  3078. {
  3079. ASSERT(pEntHdl->SeqNo == 0);
  3080. return (FALSE);
  3081. }
  3082. //
  3083. // If we can lock the block, the dlg hdl is still valid. If not, it means
  3084. // that the dlg was terminated earlier.
  3085. //
  3086. if (CommLockBlock(pEntHdl))
  3087. {
  3088. (VOID)CommUnlockBlock(pEntHdl);
  3089. return(TRUE);
  3090. }
  3091. return(FALSE);
  3092. }
  3093. #endif
  3094. BOOL
  3095. CommLockBlock(
  3096. IN PCOMM_HDL_T pEntHdl
  3097. )
  3098. /*++
  3099. Routine Description:
  3100. This function is called to lock the COMSYS entity identified by the
  3101. handle.
  3102. Arguments:
  3103. pEntHdl - Handle to entity to lock
  3104. Externals Used:
  3105. None
  3106. Return Value:
  3107. Success status codes -- TRUE
  3108. Error status codes -- FALSE
  3109. Error Handling:
  3110. Called by:
  3111. Side Effects:
  3112. Comments:
  3113. None
  3114. --*/
  3115. {
  3116. PCOMM_TOP_T pTop = pEntHdl->pEnt;
  3117. //lock before checking
  3118. #if 0
  3119. WinsMscWaitInfinite(pTop->MutexHdl);
  3120. #endif
  3121. EnterCriticalSection(&pTop->CrtSec);
  3122. if (pEntHdl->SeqNo == pTop->SeqNo)
  3123. {
  3124. return(TRUE);
  3125. }
  3126. else
  3127. {
  3128. CommUnlockBlock(pEntHdl);
  3129. return(FALSE);
  3130. }
  3131. }
  3132. __inline
  3133. STATUS
  3134. CommUnlockBlock(
  3135. PCOMM_HDL_T pEntHdl
  3136. )
  3137. /*++
  3138. Routine Description:
  3139. This function is called to unlock the COMSYS entity identified by the
  3140. handle.
  3141. Arguments:
  3142. pEntHdl - Handle to entity to unlock
  3143. Externals Used:
  3144. None
  3145. Return Value:
  3146. Success status codes -- WINS_SUCCESS
  3147. Error status codes -- WINS_FAILURE
  3148. Error Handling:
  3149. Called by:
  3150. Side Effects:
  3151. Comments:
  3152. None
  3153. --*/
  3154. {
  3155. FUTURES("Change to a macro")
  3156. #if 0
  3157. BOOL RetVal = TRUE;
  3158. BOOL RetStat = WINS_SUCCESS;
  3159. #endif
  3160. PCOMM_TOP_T pTop = pEntHdl->pEnt;
  3161. LeaveCriticalSection(&pTop->CrtSec);
  3162. #if 0
  3163. RetVal = ReleaseMutex(pTop->MutexHdl);
  3164. if (RetVal == FALSE)
  3165. {
  3166. RetStat = WINS_FAILURE;
  3167. }
  3168. #endif
  3169. return(WINS_SUCCESS);
  3170. }
  3171. VOID
  3172. InitMem(
  3173. VOID
  3174. )
  3175. /*++
  3176. Routine Description:
  3177. This function is called to do all memory initialization required
  3178. by COMSYS.
  3179. Arguments:
  3180. None
  3181. Externals Used:
  3182. None
  3183. Return Value:
  3184. None
  3185. Error Handling:
  3186. Called by:
  3187. CommInit
  3188. Side Effects:
  3189. Comments:
  3190. None
  3191. --*/
  3192. {
  3193. /*
  3194. * Create Memory heap for UDP buffers
  3195. * We want mutual exclusion and generation of exceptions
  3196. */
  3197. DBGPRINT0(HEAP_CRDL,"InitMem: Udp. Buff heap\n");
  3198. CommUdpBuffHeapHdl = WinsMscHeapCreate(
  3199. HEAP_GENERATE_EXCEPTIONS,
  3200. COMMASSOC_UDP_BUFFER_HEAP_SIZE
  3201. );
  3202. DBGPRINT0(HEAP_CRDL,"InitMem: Udp. Buff heap\n");
  3203. CommUdpDlgHeapHdl = WinsMscHeapCreate(
  3204. HEAP_GENERATE_EXCEPTIONS,
  3205. COMMASSOC_UDP_DLG_HEAP_SIZE
  3206. );
  3207. /*
  3208. * Create Memory heap for Assoc Ctx blocks.
  3209. * We want mutual exclusion and generation of exceptions
  3210. */
  3211. DBGPRINT0(HEAP_CRDL,"InitMem: Assoc. blocks heap\n");
  3212. CommAssocAssocHeapHdl = WinsMscHeapCreate(
  3213. HEAP_GENERATE_EXCEPTIONS,
  3214. COMMASSOC_ASSOC_BLKS_HEAP_SIZE
  3215. );
  3216. /*
  3217. * Create Memory heap for dlg blocks
  3218. * We want mutual exclusion and generation of exceptions
  3219. */
  3220. DBGPRINT0(HEAP_CRDL,"InitMem: Dlgs. blocks heap\n");
  3221. CommAssocDlgHeapHdl = WinsMscHeapCreate(
  3222. HEAP_GENERATE_EXCEPTIONS,
  3223. COMMASSOC_DLG_BLKS_HEAP_SIZE
  3224. );
  3225. /*
  3226. * Create Memory heap for messages on tcp connections
  3227. */
  3228. DBGPRINT0(HEAP_CRDL,"InitMem: tcp connection message heap\n");
  3229. CommAssocTcpMsgHeapHdl = WinsMscHeapCreate(
  3230. HEAP_GENERATE_EXCEPTIONS,
  3231. COMMASSOC_TCP_MSG_HEAP_SIZE
  3232. );
  3233. return;
  3234. }
  3235. BOOL
  3236. ChkNtfSock(
  3237. IN fd_set *pActSocks,
  3238. IN fd_set *pRdSocks
  3239. )
  3240. /*++
  3241. Routine Description:
  3242. This function is called to check if there is a notification message
  3243. on the Notification socket. If there is one, it reads the message.
  3244. The message contains a socket # and a command to add or remove the
  3245. socket to/from the list of sockets being monitored by the TCP
  3246. listener thread.
  3247. Arguments:
  3248. pActSocks - Array of active sockets
  3249. pRdSocks - Array of sockets returned by select
  3250. Externals Used:
  3251. CommNtfSockHandle
  3252. Return Value:
  3253. TRUE - Yes, there was a message. The Active sockets array has been
  3254. changed.
  3255. FALSE - No. There was no message
  3256. Error Handling:
  3257. In case of an error, an exception is raised
  3258. Called by:
  3259. MonTcp
  3260. Side Effects:
  3261. Comments:
  3262. None
  3263. --*/
  3264. {
  3265. DWORD Error;
  3266. int RetVal;
  3267. COMM_NTF_MSG_T NtfMsg;
  3268. PCOMMASSOC_DLG_CTX_T pDlgCtx;
  3269. PCOMMASSOC_ASSOC_CTX_T pAssocCtx;
  3270. SOCKET Sock;
  3271. BOOL fNtfSockSet = TRUE;
  3272. if (FD_ISSET(CommNtfSockHandle, pRdSocks))
  3273. {
  3274. Sock = CommNtfSockHandle;
  3275. }
  3276. else
  3277. {
  3278. #if SPX > 0
  3279. if (FD_ISSET(CommIpxNtfSockHandle, pRdSocks))
  3280. {
  3281. Sock = CommIpxNtfSockHandle;
  3282. }
  3283. #endif
  3284. fNtfSockSet = FALSE;
  3285. }
  3286. if (fNtfSockSet)
  3287. {
  3288. //do a recvfrom to read in the data.
  3289. RetVal = recvfrom(
  3290. Sock,
  3291. (char *)&NtfMsg,
  3292. COMM_NTF_MSG_SZ,
  3293. 0, //default flags (i.e. no peeking
  3294. //or reading OOB message
  3295. NULL, //don't want address of sender
  3296. 0 //length of above arg
  3297. );
  3298. if (RetVal == SOCKET_ERROR)
  3299. {
  3300. Error = WSAGetLastError();
  3301. if (WinsCnf.State_e != WINSCNF_E_TERMINATING)
  3302. {
  3303. WINSEVT_LOG_M(
  3304. Error,
  3305. WINS_EVT_WINSOCK_RECVFROM_ERR
  3306. );
  3307. }
  3308. WINS_RAISE_EXC_M(WINS_EXC_FAILURE);
  3309. }
  3310. pDlgCtx = NtfMsg.DlgHdl.pEnt;
  3311. pAssocCtx = pDlgCtx->AssocHdl.pEnt;
  3312. if (NtfMsg.Cmd_e == COMM_E_NTF_START_MON)
  3313. {
  3314. DBGPRINT1(FLOW, "ChkNtfSock: Adding Socket (%d) to monitor list\n", NtfMsg.SockNo);
  3315. //
  3316. // We do this since FD_SETSIZE can fail silently
  3317. //
  3318. if (pActSocks->fd_count < FD_SETSIZE)
  3319. {
  3320. FD_SET(NtfMsg.SockNo, pActSocks);
  3321. }
  3322. else
  3323. {
  3324. DBGPRINT1(ERR,
  3325. "ChkNtfSock: Connection limit of %d reached\n",
  3326. FD_SETSIZE);
  3327. WINSEVT_LOG_M(WINS_FAILURE,
  3328. WINS_EVT_CONN_LIMIT_REACHED);
  3329. //
  3330. //This will cleanup the dlg and assoc. ctx. blk
  3331. //
  3332. ECommEndDlg(&NtfMsg.DlgHdl);
  3333. return(TRUE);
  3334. }
  3335. //
  3336. // Add the association to the table of associations.
  3337. // Since this association will be monitored, we change
  3338. // the role of the association to RESPONDER. Also,
  3339. // change the dialogue role to IMPLICIT. These are
  3340. // sleight of hand tactics. The client who
  3341. // established the association (Replicator)
  3342. // does not care whet we do with the comm data
  3343. // structures as long as we monitor the dialogue that
  3344. // it initiated with a remote WINS
  3345. //
  3346. pAssocCtx->Role_e = COMMASSOC_ASSOC_E_RESPONDER;
  3347. pDlgCtx->Role_e = COMMASSOC_DLG_E_IMPLICIT;
  3348. pDlgCtx->FromAdd = pAssocCtx->RemoteAdd;
  3349. CommAssocInsertAssocInTbl(pAssocCtx);
  3350. }
  3351. else //COMM_NTF_STOP_MON
  3352. {
  3353. DBGPRINT1(FLOW, "ChkNtfSock: Removing Socket (%d) from monitor list\n", NtfMsg.SockNo);
  3354. FD_CLR(NtfMsg.SockNo, pActSocks);
  3355. //
  3356. //Remove the association from the table of
  3357. //associations. Since this association will not be
  3358. //monitored by the TCP thread, we change the role of
  3359. //the association to INITIATOR. Also, change the
  3360. //dialogue role to EXPLICIT. These are sleight of
  3361. //hand tactics.
  3362. //
  3363. if (CommLockBlock(&NtfMsg.DlgHdl))
  3364. {
  3365. pAssocCtx->Role_e = COMMASSOC_ASSOC_E_INITIATOR;
  3366. pDlgCtx->Role_e = COMMASSOC_DLG_E_EXPLICIT;
  3367. COMMASSOC_UNLINK_RSP_ASSOC_M(pAssocCtx);
  3368. pAssocCtx->RemoteAdd = pDlgCtx->FromAdd;
  3369. CommUnlockBlock(&NtfMsg.DlgHdl);
  3370. //
  3371. // Let us signal the PUSH thread so that it can
  3372. // hand over the connection to the PULL thread (See
  3373. // HandleUpdNtf in rplpush.c)
  3374. //
  3375. WinsMscSignalHdl(RplSyncWTcpThdEvtHdl);
  3376. }
  3377. else
  3378. {
  3379. //
  3380. //The dlg could not be locked. It means that before
  3381. //the tcp listener thread started processing this
  3382. //message, it had already processed a disconnect.
  3383. //
  3384. fCommDlgError = TRUE;
  3385. WinsMscSignalHdl(RplSyncWTcpThdEvtHdl);
  3386. }
  3387. }
  3388. return(TRUE);
  3389. }
  3390. return(FALSE);
  3391. } // ChkNtfSock()
  3392. STATUS
  3393. RecvData(
  3394. IN SOCKET SockNo,
  3395. IN LPBYTE pBuff,
  3396. IN DWORD BytesToRead,
  3397. IN INT Flags,
  3398. IN DWORD SecsToWait,
  3399. OUT LPDWORD pBytesRead
  3400. )
  3401. /*++
  3402. Routine Description:
  3403. This function is called to do a timed recv on a socket.
  3404. Arguments:
  3405. SockNo - Socket No.
  3406. pBuff - Buffer to read the data into
  3407. BytesToRead - The number of bytes to read
  3408. Flags - flag arguments for recv
  3409. SecsToWait - No of secs to wait for the first read.
  3410. pBytesRead - No of Bytes that are read
  3411. Externals Used:
  3412. None
  3413. Return Value:
  3414. Success status codes -- WINS_SUCCESS
  3415. Error status codes -- WINS_FAILURE or WINS_RECV_TIMED_OUT
  3416. Error Handling:
  3417. Called by:
  3418. CommReadStream
  3419. Side Effects:
  3420. Comments:
  3421. None
  3422. --*/
  3423. {
  3424. fd_set RdSocks;
  3425. int NoOfSockReady;
  3426. INT BytesRead = 0;
  3427. INT BytesLeft = BytesToRead;
  3428. DWORD InChars;
  3429. DWORD Error;
  3430. BOOL fFirst = TRUE;
  3431. STATUS RetStat;
  3432. FD_ZERO(&RdSocks);
  3433. FD_SET(SockNo, &RdSocks);
  3434. /*
  3435. * Read the whole message into the allocated buffer
  3436. */
  3437. for (
  3438. InChars = 0;
  3439. BytesLeft > 0;
  3440. InChars += BytesRead
  3441. )
  3442. {
  3443. //
  3444. // Check if we were told to do a timed receive. This will
  3445. // never happen in the TCP listener thread
  3446. //
  3447. if (SecsToWait)
  3448. {
  3449. //
  3450. // Block on a timed select. The first time around we want to
  3451. // wait the time specified by caller. The caller expects the other
  3452. // side to send something within this much time. For subsequent
  3453. // reads we wait a pre-defined interval since the sender has already
  3454. // accumulated all that it wants to send and has started sending it
  3455. // obviating the need for us to wait long.
  3456. //
  3457. if (fFirst)
  3458. {
  3459. sTimeToWait.tv_sec = (long)SecsToWait;
  3460. fFirst = FALSE;
  3461. }
  3462. else
  3463. {
  3464. sTimeToWait.tv_sec = SECS_TO_WAIT;
  3465. }
  3466. if (
  3467. (
  3468. NoOfSockReady = select(
  3469. FD_SETSIZE /*ignored arg*/,
  3470. &RdSocks,
  3471. (fd_set *)0,
  3472. (fd_set *)0,
  3473. &sTimeToWait
  3474. )
  3475. ) == SOCKET_ERROR
  3476. )
  3477. {
  3478. Error = WSAGetLastError();
  3479. DBGPRINT1(ERR,
  3480. "RecvData: Timed Select returned SOCKET ERROR. Error = (%d)\n",
  3481. Error);
  3482. // CommDecConnCount();
  3483. return(WINS_FAILURE);
  3484. }
  3485. else
  3486. {
  3487. DBGPRINT1(FLOW, "ReceiveData: Timed Select returned with success. No of Sockets ready - (%d) \n", NoOfSockReady);
  3488. if (NoOfSockReady == 0)
  3489. {
  3490. //
  3491. // Timing out of RecvData indicates some problem at
  3492. // the remote WINS (either it is very slow
  3493. // (overloaded) or the TCP listener thread is out of
  3494. // commission).
  3495. WINSEVT_LOG_INFO_D_M(
  3496. WINS_SUCCESS,
  3497. WINS_EVT_WINSOCK_SELECT_TIMED_OUT
  3498. );
  3499. DBGPRINT0(ERR, "ReceiveData: Select TIMED OUT\n");
  3500. *pBytesRead = 0;
  3501. *pBytesRead = BytesRead;
  3502. // CommDecConnCount();
  3503. return(WINS_RECV_TIMED_OUT);
  3504. }
  3505. }
  3506. }
  3507. //
  3508. // Do a blocking recv
  3509. //
  3510. BytesRead = recv(
  3511. SockNo,
  3512. (char *)(pBuff + InChars),
  3513. BytesLeft,
  3514. Flags
  3515. );
  3516. if (BytesRead == SOCKET_ERROR)
  3517. {
  3518. Error = WSAGetLastError();
  3519. DBGPRINT1(ERR,
  3520. "RecvData: recv returned SOCKET_ERROR. Error = (%d)\n",
  3521. Error);
  3522. /*
  3523. * If the connection was aborted or reset from the
  3524. * other end, we close the socket and return an error
  3525. */
  3526. if (
  3527. (Error == WSAECONNABORTED)
  3528. ||
  3529. (Error == WSAECONNRESET)
  3530. ||
  3531. (Error == WSAEDISCON)
  3532. )
  3533. {
  3534. DBGPRINT0(ERR,
  3535. "RecvData: Connection aborted\n");
  3536. WINSEVT_LOG_INFO_D_M(
  3537. WINS_SUCCESS,
  3538. WINS_EVT_CONN_ABORTED
  3539. );
  3540. }
  3541. *pBytesRead = BytesRead;
  3542. // CommDecConnCount();
  3543. return(WINS_FAILURE);
  3544. }
  3545. if (BytesRead == 0)
  3546. {
  3547. /*recv returns 0 (normal graceful shutdown from
  3548. * either side)
  3549. * Note:
  3550. * recv returns 0 if the connection terminated with no
  3551. * loss of data from either end point of the connection
  3552. */
  3553. //
  3554. // If we were told to do a non timed receive,
  3555. // we must be executing in the TCP listener thread
  3556. //
  3557. // We don't return an error status here since
  3558. // a disconnect is a valid condition (the other
  3559. // WINS is terminating its connection normally)
  3560. //
  3561. if (SecsToWait == 0)
  3562. {
  3563. RetStat = WINS_SUCCESS;
  3564. }
  3565. else
  3566. {
  3567. //
  3568. // The fact that we were told to do a
  3569. // timed select means that we are in
  3570. // a thread of one of the clients of
  3571. // COMSYS. We were expecting data but
  3572. // got a disconnect instead. Let us
  3573. // return an error
  3574. //
  3575. RetStat = WINS_FAILURE;
  3576. }
  3577. //
  3578. // We are done. Break out of the loop
  3579. //
  3580. *pBytesRead = BytesRead;
  3581. // CommDecConnCount();
  3582. return(RetStat);
  3583. }
  3584. BytesLeft -= BytesRead;
  3585. //
  3586. //We are here means that BytesRead > 0
  3587. //
  3588. } // end of for { ... }
  3589. *pBytesRead = InChars;
  3590. return(WINS_SUCCESS);
  3591. } // RecvData()
  3592. #if USENETBT > 0
  3593. VOID
  3594. CommOpenNbt(
  3595. DWORD FirstBindingIpAddr
  3596. )
  3597. /*++
  3598. Routine Description:
  3599. This function opens the NetBt device for the interface specified by
  3600. FirstBindingIpAddr.
  3601. Arguments:
  3602. path - path to the NETBT driver
  3603. oflag - currently ignored. In the future, O_NONBLOCK will be
  3604. relevant.
  3605. ignored - not used
  3606. Return Value:
  3607. An NT handle for the stream, or INVALID_HANDLE_VALUE if unsuccessful.
  3608. --*/
  3609. {
  3610. OBJECT_ATTRIBUTES ObjectAttributes;
  3611. IO_STATUS_BLOCK IoStatusBlock;
  3612. // STRING name_string;
  3613. UNICODE_STRING uc_name_string;
  3614. NTSTATUS status;
  3615. PFILE_FULL_EA_INFORMATION pEaBuffer;
  3616. ULONG EaBufferSize;
  3617. //
  3618. // Convert the path into UNICODE_STRING form
  3619. //
  3620. #ifdef _PNP_POWER_
  3621. RtlInitUnicodeString(&uc_name_string, L"\\Device\\NetBt_Wins_Export");
  3622. #else
  3623. #ifdef UNICODE
  3624. RtlInitUnicodeString(&uc_name_string, pWinsCnfNbtPath);
  3625. #else
  3626. RtlInitString(&name_string, pWinsCnfNbtPath);
  3627. RtlAnsiStringToUnicodeString(&uc_name_string, &name_string, TRUE);
  3628. #endif
  3629. #endif // _PNP_POWER_
  3630. InitializeObjectAttributes(
  3631. &ObjectAttributes,
  3632. &uc_name_string,
  3633. OBJ_CASE_INSENSITIVE,
  3634. (HANDLE) NULL,
  3635. (PSECURITY_DESCRIPTOR) NULL
  3636. );
  3637. EaBufferSize = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]) +
  3638. strlen(WINS_INTERFACE_NAME) + 1 +
  3639. sizeof(FirstBindingIpAddr); // EA length
  3640. WinsMscAlloc(EaBufferSize, &pEaBuffer);
  3641. if (pEaBuffer == NULL)
  3642. {
  3643. WINS_RAISE_EXC_M(WINS_EXC_OUT_OF_MEM);
  3644. }
  3645. pEaBuffer->NextEntryOffset = 0;
  3646. pEaBuffer->Flags = 0;
  3647. pEaBuffer->EaNameLength = (UCHAR)strlen(WINS_INTERFACE_NAME);
  3648. //
  3649. // put "WinsInterface" into the name
  3650. //
  3651. RtlMoveMemory(
  3652. pEaBuffer->EaName,
  3653. WINS_INTERFACE_NAME,
  3654. pEaBuffer->EaNameLength + 1);
  3655. pEaBuffer->EaValueLength = sizeof(FirstBindingIpAddr);
  3656. *(DWORD UNALIGNED *)(pEaBuffer->EaName + pEaBuffer->EaNameLength + 1) = FirstBindingIpAddr;
  3657. status =
  3658. NtCreateFile(
  3659. &WinsCnfNbtHandle,
  3660. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  3661. &ObjectAttributes,
  3662. &IoStatusBlock,
  3663. NULL,
  3664. FILE_ATTRIBUTE_NORMAL,
  3665. FILE_SHARE_READ | FILE_SHARE_WRITE,
  3666. FILE_OPEN_IF,
  3667. 0,
  3668. pEaBuffer,
  3669. EaBufferSize
  3670. );
  3671. #ifndef UNICODE
  3672. RtlFreeUnicodeString(&uc_name_string);
  3673. #endif
  3674. WinsMscDealloc(pEaBuffer);
  3675. if(!NT_SUCCESS(status))
  3676. {
  3677. WinsEvtLogDetEvt(
  3678. FALSE,
  3679. WINS_PNP_FAILURE,
  3680. NULL,
  3681. __LINE__,
  3682. "d",
  3683. status);
  3684. DBGPRINT1(EXC, "CommOpenNbt: Status from NtCreateFile is (%x)\n",
  3685. status);
  3686. WINS_RAISE_EXC_M(WINS_EXC_NBT_ERR);
  3687. }
  3688. return;
  3689. } // CommOpenNbt
  3690. //------------------------------------------------------------------------
  3691. #if NEWNETBTIF == 0
  3692. //#include "nbtioctl.sav"
  3693. STATUS
  3694. CommGetNetworkAdd(
  3695. IN OUT PCOMM_ADD_T pAdd
  3696. )
  3697. /*++
  3698. Routine Description:
  3699. This procedure does an adapter status query to get the local name table.
  3700. It either prints out the local name table or the remote (cache) table
  3701. depending on whether WhichNames is NAMES or CACHE .
  3702. Arguments:
  3703. Return Value:
  3704. 0 if successful, -1 otherwise.
  3705. --*/
  3706. {
  3707. LONG i;
  3708. PVOID pBuffer;
  3709. ULONG BufferSize=sizeof(tADAPTERSTATUS);
  3710. NTSTATUS Status;
  3711. tADAPTERSTATUS *pAdapterStatus;
  3712. ULONG QueryType;
  3713. PUCHAR pAddr;
  3714. ULONG Ioctl;
  3715. //
  3716. // Get the local name table
  3717. //
  3718. Ioctl = IOCTL_TDI_QUERY_INFORMATION;
  3719. Status = STATUS_BUFFER_OVERFLOW;
  3720. while (Status == STATUS_BUFFER_OVERFLOW)
  3721. {
  3722. WinsMscAlloc(BufferSize, &pBuffer);
  3723. Status = DeviceIoCtrl(
  3724. &sNetbtGetAddrEvtHdl,
  3725. pBuffer,
  3726. BufferSize,
  3727. Ioctl
  3728. );
  3729. if (Status == STATUS_BUFFER_OVERFLOW)
  3730. {
  3731. WinsMscDealloc(pBuffer);
  3732. BufferSize *=2;
  3733. if (BufferSize == 0xFFFF)
  3734. {
  3735. WINSEVT_LOG_D_M(BufferSize, WINS_EVT_UNABLE_TO_ALLOCATE_PACKET);
  3736. DBGPRINT1(ERR, "CommGetNetworkAdd: Unable to get address from NBT\n", BufferSize);
  3737. return(WINS_FAILURE);
  3738. }
  3739. }
  3740. }
  3741. pAdapterStatus = (tADAPTERSTATUS *)pBuffer;
  3742. if (pAdapterStatus->AdapterInfo.name_count == 0)
  3743. {
  3744. WINSEVT_LOG_D_M(WINS_FAILURE, WINS_EVT_ADAPTER_STATUS_ERR);
  3745. DBGPRINT0(ERR, "CommGetNetworkAdd: No names in NBT cache\n");
  3746. return(WINS_FAILURE);
  3747. }
  3748. //
  3749. // print out the Ip Address of this node
  3750. //
  3751. pAddr = &pAdapterStatus->AdapterInfo.adapter_address[2];
  3752. NMSMSGF_RETRIEVE_IPADD_M(pAddr, pAdd->Add.IPAdd);
  3753. WinsMscDealloc(pBuffer);
  3754. return(WINS_SUCCESS);
  3755. }
  3756. #else
  3757. STATUS
  3758. CommGetNetworkAdd(
  3759. )
  3760. /*++
  3761. Routine Description:
  3762. This routine gets all the Ip Addresses of Netbt interfaces.
  3763. Arguments:
  3764. Return Value:
  3765. 0 if successful, -1 otherwise.
  3766. --*/
  3767. {
  3768. ULONG Buffer[NBT_MAXIMUM_BINDINGS + 1];
  3769. ULONG BufferSize=sizeof(Buffer);
  3770. NTSTATUS Status;
  3771. ULONG Ioctl;
  3772. PULONG pBuffer;
  3773. PULONG pBufferSv;
  3774. DWORD i, Count;
  3775. BOOL fAlloc = FALSE;
  3776. //
  3777. // Get the local addresses
  3778. //
  3779. Ioctl = IOCTL_NETBT_GET_IP_ADDRS;
  3780. //
  3781. // NETBT does not support more than 64 adapters and not more than
  3782. // one ip address per adapter. So, there can be a max of 64 ip addresses
  3783. // which means we don't require more than 65 * 4 = 280 bytes (256 for the
  3784. // addresses followed by a delimiter address of 0.
  3785. //
  3786. Status = DeviceIoCtrl(
  3787. &sNetbtGetAddrEvtHdl,
  3788. (LPBYTE)Buffer,
  3789. BufferSize,
  3790. Ioctl
  3791. );
  3792. if (Status != STATUS_SUCCESS)
  3793. {
  3794. BufferSize *= 10; //alocate a buffer that is 10 times bigger.
  3795. //surely, netbt can not be supporting so many
  3796. //addresses. If it is, then the netbt developer
  3797. //goofed in that (s)he did not update
  3798. //NBT_MAXIMUM_BINDINGS in nbtioctl.h
  3799. WinsMscAlloc(BufferSize, &pBuffer);
  3800. DBGPRINT1(ERR, "CommGetNetworkAdd: Ioctl - GET_IP_ADDRS failed. Return code = (%x)\n", Status);
  3801. Status = DeviceIoCtrl(
  3802. &sNetbtGetAddrEvtHdl,
  3803. (LPBYTE)pBuffer,
  3804. BufferSize,
  3805. Ioctl
  3806. );
  3807. if (Status != STATUS_SUCCESS)
  3808. {
  3809. DBGPRINT1(ERR, "CommGetNetworkAdd: Ioctl - GET_IP_ADDRS failed AGAIN. Return code = (%x)\n", Status);
  3810. WINSEVT_LOG_M(Status, WINS_EVT_UNABLE_TO_GET_ADDRESSES);
  3811. WinsMscDealloc(pBuffer); //dealloc the buffer
  3812. return(WINS_FAILURE);
  3813. }
  3814. fAlloc = TRUE;
  3815. }
  3816. else
  3817. {
  3818. pBuffer = Buffer;
  3819. }
  3820. //
  3821. // Count the number of addresses returned
  3822. // The end of the address table contains -1 and any null addresses
  3823. // contain 0
  3824. //
  3825. pBufferSv = pBuffer;
  3826. for(Count=0; *pBuffer != -1; pBuffer++)
  3827. {
  3828. // Increment Count only if it is a valid address.
  3829. if ( *pBuffer ) {
  3830. Count++;
  3831. }
  3832. }
  3833. if ( !Count ) {
  3834. DBGPRINT0(ERR, "CommGetNetworkAdd: Netbt did not give any valid address\n");
  3835. WINSEVT_LOG_M(Status, WINS_EVT_UNABLE_TO_GET_ADDRESSES);
  3836. if (fAlloc)
  3837. {
  3838. WinsMscDealloc(pBufferSv);
  3839. }
  3840. return(WINS_FAILURE);
  3841. }
  3842. if (pWinsAddresses)
  3843. {
  3844. WinsMscDealloc(pWinsAddresses);
  3845. }
  3846. //
  3847. // Allocate space for the addresses
  3848. //
  3849. WinsMscAlloc(sizeof(ADD_T) + ((Count - 1) * COMM_IP_ADD_SIZE), &pWinsAddresses);
  3850. pWinsAddresses->NoOfAdds = Count;
  3851. pBuffer = pBufferSv;
  3852. // Copy all valid addresses
  3853. for (i=0; i<Count; pBuffer++)
  3854. {
  3855. if ( *pBuffer ) {
  3856. pWinsAddresses->IpAdd[i] = *pBuffer;
  3857. i++;
  3858. }
  3859. }
  3860. if (fAlloc)
  3861. {
  3862. WinsMscDealloc(pBufferSv);
  3863. }
  3864. return(WINS_SUCCESS);
  3865. }
  3866. #endif
  3867. //------------------------------------------------------------------------
  3868. NTSTATUS
  3869. DeviceIoCtrl(
  3870. IN LPHANDLE pEvtHdl,
  3871. IN PVOID pDataBuffer,
  3872. IN DWORD DataBufferSize,
  3873. IN ULONG Ioctl
  3874. )
  3875. /*++
  3876. Routine Description:
  3877. This procedure performs an ioctl(I_STR) on a stream.
  3878. Arguments:
  3879. fd - NT file handle
  3880. iocp - pointer to a strioctl structure
  3881. Return Value:
  3882. 0 if successful, -1 otherwise.
  3883. --*/
  3884. {
  3885. NTSTATUS status;
  3886. IO_STATUS_BLOCK iosb;
  3887. #if NEWNETBTIF == 0
  3888. TDI_REQUEST_QUERY_INFORMATION QueryInfo;
  3889. #endif
  3890. PVOID pInput = NULL;
  3891. ULONG SizeInput = 0;
  3892. #if NEWNETBTIF == 0
  3893. PERF("TDI_QUERY_INFORMATION is used only at WINS initialization")
  3894. if (Ioctl == IOCTL_TDI_QUERY_INFORMATION)
  3895. {
  3896. pInput = &QueryInfo;
  3897. QueryInfo.QueryType = TDI_QUERY_ADAPTER_STATUS; // node status
  3898. SizeInput = sizeof(TDI_REQUEST_QUERY_INFORMATION);
  3899. }
  3900. #endif
  3901. while (TRUE)
  3902. {
  3903. status = NtDeviceIoControlFile(
  3904. WinsCnfNbtHandle, // Handle
  3905. *pEvtHdl, // Event
  3906. NULL, // ApcRoutine
  3907. NULL, // ApcContext
  3908. &iosb, // IoStatusBlock
  3909. Ioctl, // IoControlCode
  3910. pInput, // InputBuffer
  3911. SizeInput, // Buffer Length
  3912. pDataBuffer, // Output Buffer
  3913. DataBufferSize // Output BufferSize
  3914. );
  3915. if (status == STATUS_SUCCESS)
  3916. {
  3917. return(status);
  3918. }
  3919. else
  3920. {
  3921. //
  3922. // If status is PENDING, do a wait on the event
  3923. //
  3924. if (status == STATUS_PENDING)
  3925. {
  3926. status = NtWaitForSingleObject(
  3927. *pEvtHdl, // Handle
  3928. TRUE, // Alertable
  3929. NULL); // Timeout
  3930. if (status == STATUS_SUCCESS)
  3931. {
  3932. return(status);
  3933. }
  3934. }
  3935. }
  3936. //
  3937. // status returned by NtDeviceIoCtrl or NtWaitForSingleObject is
  3938. // a failure code
  3939. //
  3940. DBGPRINT1(ERR, "DeviceIoCtrl, Status returned is (%x)\n", status);
  3941. if (status != STATUS_CANCELLED)
  3942. {
  3943. //
  3944. // If it is insufficient resources, we drop this datagram and
  3945. // try again (only for recv)
  3946. //
  3947. if (Ioctl == IOCTL_NETBT_WINS_RCV)
  3948. {
  3949. if (status == STATUS_INSUFFICIENT_RESOURCES)
  3950. {
  3951. continue;
  3952. }
  3953. }
  3954. //
  3955. // in case of a send, it can be invalid handle, invalid
  3956. // parameter or insufficient resourcesi. If it is INVALID_PARAMETER,
  3957. // it means that we passed 0 in the Address field on top of the buffer.
  3958. //
  3959. // Drop this datagram and return to the caller
  3960. //
  3961. if (Ioctl == IOCTL_NETBT_WINS_SEND)
  3962. {
  3963. if (
  3964. (status == STATUS_INSUFFICIENT_RESOURCES)
  3965. ||
  3966. (status == STATUS_INVALID_PARAMETER)
  3967. )
  3968. {
  3969. return(STATUS_SUCCESS);
  3970. }
  3971. else
  3972. {
  3973. DBGPRINT1(EXC, "NtDeviceIoCtrl returned error = (%x)\n",
  3974. status);
  3975. WINSEVT_LOG_D_M(status, WINS_EVT_NETBT_SEND_ERR);
  3976. //
  3977. // If the machine's address has gone away due to some
  3978. // reason, WinsCnfNbtHandle will have been changed
  3979. // to NULL. In this case, we will get
  3980. // STATUS_INVALID_HANDLE error. We do not check for
  3981. // handle being NULL prior to making the Nbt call
  3982. // to avoid an if check which is of no value for
  3983. // 99% of the time.
  3984. //
  3985. // An error will be logged up above. We should not see
  3986. // too many of these since the window where
  3987. // WinsCnfNbtHandle is NULL is very small unless WINS
  3988. // is terminating in which case this thread will
  3989. // just terminate as a result of the exception being
  3990. // raised below.
  3991. //
  3992. // The address can go away due to the following reasons
  3993. //
  3994. // 1) psched installation (unbind followed by bind)
  3995. // 2) Changing from dhcp/static or static/dhcp
  3996. // 3) ipconfig release/renew
  3997. //
  3998. //
  3999. // When the main thread has to terminate WINS, it
  4000. // closes WinsCnfNetbtHandle. A worker thread or a
  4001. // challenge thread might be busy dealing with its
  4002. // queue of work items (potentially long on a busy
  4003. // WINS) and may not see a termination
  4004. // signal from the main thread. This exception will
  4005. // terminate it
  4006. //
  4007. //
  4008. // Raise an exception if the wins is terminating
  4009. //
  4010. if (WinsCnf.State_e == WINSCNF_E_TERMINATING)
  4011. {
  4012. WINS_RAISE_EXC_M(WINS_EXC_NBT_ERR);
  4013. }
  4014. }
  4015. }
  4016. break;
  4017. }
  4018. break;
  4019. } // end of while (TRUE)
  4020. return(status);
  4021. }
  4022. #endif
  4023. LPVOID
  4024. CommHeapAlloc(
  4025. IN PRTL_GENERIC_TABLE pTable,
  4026. IN CLONG BuffSize
  4027. )
  4028. /*++
  4029. Routine Description:
  4030. This function is called to allocate a buffer
  4031. Arguments:
  4032. pTable - Table where the buffer will be stored
  4033. BuffSize - Size of buffer to allocate
  4034. Externals Used:
  4035. None
  4036. Return Value:
  4037. Success status codes -- ptr to buffer allocated
  4038. Error status codes --
  4039. Error Handling:
  4040. Called by:
  4041. RtlInsertElementGeneric()
  4042. Side Effects:
  4043. Comments:
  4044. This function exists just because the RtlTbl functions require
  4045. this prototype for the user specified alloc function.
  4046. --*/
  4047. {
  4048. LPVOID pTmp;
  4049. UNREFERENCED_PARAMETER(pTable);
  4050. pTmp = WinsMscHeapAlloc( CommUdpDlgHeapHdl, (DWORD) BuffSize );
  4051. return(pTmp);
  4052. }
  4053. VOID
  4054. CommHeapDealloc(
  4055. IN PRTL_GENERIC_TABLE pTable,
  4056. IN PVOID pBuff
  4057. )
  4058. /*++
  4059. Routine Description:
  4060. This function is called to deallocate memory allocated via CommAlloc.
  4061. Arguments:
  4062. pTable - Table where buffer was stored
  4063. pBuff - Buffer to deallocate
  4064. Externals Used:
  4065. None
  4066. Return Value:
  4067. None
  4068. Error Handling:
  4069. Called by:
  4070. Side Effects:
  4071. Comments:
  4072. The pTable argument is required since the address of this function
  4073. is passed as an argument to RtlTbl functions
  4074. --*/
  4075. {
  4076. UNREFERENCED_PARAMETER(pTable);
  4077. WinsMscHeapFree(
  4078. CommUdpDlgHeapHdl,
  4079. pBuff
  4080. );
  4081. return;
  4082. }
  4083. VOID
  4084. CommDecConnCount(
  4085. VOID
  4086. )
  4087. /*++
  4088. Routine Description:
  4089. This function decrements the conn. count
  4090. Arguments:
  4091. Externals Used:
  4092. None
  4093. Return Value:
  4094. Success status codes --
  4095. Error status codes --
  4096. Error Handling:
  4097. Called by:
  4098. Side Effects:
  4099. Comments:
  4100. None
  4101. --*/
  4102. {
  4103. DWORD ConnCount;
  4104. ConnCount = InterlockedExchange(&CommConnCount, CommConnCount);
  4105. if (ConnCount != 0)
  4106. {
  4107. InterlockedDecrement(&CommConnCount);
  4108. }
  4109. else
  4110. {
  4111. DBGPRINT0(ERR, "CommDecConnCount: WEIRD: ConnCount should not have been zero\n");
  4112. }
  4113. return;
  4114. }
  4115. #if PRSCONN
  4116. __inline
  4117. BOOL
  4118. CommIsDlgActive (
  4119. PCOMM_HDL_T pDlgHdl
  4120. )
  4121. {
  4122. fd_set RdSocks;
  4123. int NoOfSockReady;
  4124. BOOL fRetStat = TRUE;
  4125. DWORD Error;
  4126. PCOMMASSOC_DLG_CTX_T pDlgCtx = pDlgHdl->pEnt;
  4127. PCOMM_HDL_T pAssocHdl = &pDlgCtx->AssocHdl;
  4128. PCOMMASSOC_ASSOC_CTX_T pAssocCtx = pAssocHdl->pEnt;
  4129. if (!CommLockBlock(pAssocHdl))
  4130. {
  4131. return(FALSE);
  4132. }
  4133. try {
  4134. FD_ZERO(&RdSocks);
  4135. FD_SET(pAssocCtx->SockNo, &RdSocks);
  4136. sTimeToWait.tv_sec = 0;
  4137. //
  4138. // Pass socket and a win32 event with flag of FD_CLOSE to WSAEventSelect.
  4139. // if the socket is disconnected, the event will be set. NOTE, only one
  4140. // event select can be active on the socket at any time - vadime 9/2/98
  4141. //
  4142. FUTURES("Use WSAEventSelect for marginally better performance")
  4143. if (NoOfSockReady = select(
  4144. FD_SETSIZE /*ignored arg*/,
  4145. &RdSocks,
  4146. (fd_set *)0,
  4147. (fd_set *)0,
  4148. &sTimeToWait
  4149. ) == SOCKET_ERROR)
  4150. {
  4151. Error = WSAGetLastError();
  4152. DBGPRINT1(ERR,
  4153. "RecvData: Timed Select returned SOCKET ERROR. Error = (%d)\n",
  4154. Error);
  4155. // CommDecConnCount();
  4156. return(FALSE);
  4157. }
  4158. else
  4159. {
  4160. DBGPRINT1(FLOW, "ReceiveData: Timed Select returned with success. No of Sockets ready - (%d) \n", NoOfSockReady);
  4161. //
  4162. // Either there is data or the socket is disconnected. There
  4163. // should never be any data. We will just assume a disconnect
  4164. // is there and return FALSE. The client (RPL) will end the dlg.
  4165. //
  4166. if (NoOfSockReady == 1)
  4167. {
  4168. fRetStat = FALSE;
  4169. }
  4170. ASSERT(NoOfSockReady == 0);
  4171. }
  4172. }
  4173. finally {
  4174. CommUnlockBlock(pAssocHdl);
  4175. }
  4176. return(fRetStat);
  4177. }
  4178. #endif
  4179. #if MCAST > 0
  4180. VOID
  4181. JoinMcastGrp(
  4182. VOID
  4183. )
  4184. /*++
  4185. Routine Description:
  4186. This function is called by the comm. subsystem to make WINS join
  4187. a multicast group
  4188. Arguments:
  4189. Externals Used:
  4190. None
  4191. Return Value:
  4192. Success status codes --
  4193. Error status codes --
  4194. Error Handling:
  4195. Called by:
  4196. CommCreatePorts
  4197. Side Effects:
  4198. Comments:
  4199. None
  4200. --*/
  4201. {
  4202. int Loop = 0; //to disable loopback of multicast messages on the
  4203. //same interface
  4204. DWORD Error;
  4205. struct ip_mreq mreq;
  4206. DBGENTER("JoinMcastGrp\n");
  4207. #if 0
  4208. //
  4209. // Open a socket for sending/receiving multicast packets. We open
  4210. // a seperate socket instead of using the one for udp datagrams since
  4211. // we don't want to impact the client name packet processing with any
  4212. // sort of overhead. Also, having a seperate socket keeps things nice
  4213. // and clean.
  4214. //
  4215. if ( (CommMcastPortHandle = socket(
  4216. PF_INET,
  4217. SOCK_DGRAM,
  4218. IPPROTO_UDP
  4219. )
  4220. ) == INVALID_SOCKET
  4221. )
  4222. {
  4223. Error = WSAGetLastError();
  4224. DBGPRINT1(MTCAST, "JoinMcastGrp: Can not create MCAST socket\n", Error);
  4225. // WINSEVT_LOG_M(Error, WINS_EVT_CANT_CREATE_MCAST_SOCK); //log an event
  4226. return;
  4227. }
  4228. #endif
  4229. //
  4230. // Set TTL
  4231. //
  4232. if (setsockopt(
  4233. CommUdpPortHandle,
  4234. IPPROTO_IP,
  4235. IP_MULTICAST_TTL,
  4236. (char *)&WinsCnf.McastTtl,
  4237. sizeof((int)WinsCnf.McastTtl)) == SOCKET_ERROR)
  4238. {
  4239. closesocket(CommUdpPortHandle);
  4240. CommUdpPortHandle = INVALID_SOCKET;
  4241. Error = WSAGetLastError();
  4242. DBGPRINT1(MTCAST, "JoinMcastGrp: Can not set TTL option. Error = (%d)\n", Error);
  4243. // WINSEVT_LOG_M(Error, WINS_EVT_CANT_CREATE_MCAST_SOCK); //log an event
  4244. return;
  4245. }
  4246. #if 0
  4247. //
  4248. // Disable loopback of messages
  4249. //
  4250. if (setsockopt(CommUdpPortHandle, IPPROTO_IP, IP_MULTICAST_LOOP,
  4251. (char *)&Loop, sizeof(Loop)) == SOCKET_ERROR)
  4252. {
  4253. closesocket(CommUdpPortHandle);
  4254. CommUdpPortHandle = INVALID_SOCKET;
  4255. Error = WSAGetLastError();
  4256. DBGPRINT1(MTCAST, "JoinMcastGrp: Can not set DISABLE LOOPBACK option. Error = (%d)\n",
  4257. Error);
  4258. // WINSEVT_LOG_M(Error, WINS_EVT_CANT_CREATE_MCAST_SOCK); //log an event
  4259. return;
  4260. }
  4261. #endif
  4262. //
  4263. // Join a multicast grp
  4264. //
  4265. mreq.imr_multiaddr.s_addr = htonl(McastAdd.sin_addr.s_addr);
  4266. mreq.imr_interface.s_addr = INADDR_ANY; //use the default mcast i/f
  4267. if (setsockopt(CommUdpPortHandle, IPPROTO_IP, IP_ADD_MEMBERSHIP,
  4268. (char *)&mreq, sizeof(mreq)) == SOCKET_ERROR)
  4269. {
  4270. Error = WSAGetLastError();
  4271. closesocket(CommUdpPortHandle);
  4272. CommUdpPortHandle = INVALID_SOCKET;
  4273. DBGPRINT1(MTCAST, "JoinMcastGrp: Can not ADD SELF TO MCAST GRP. Error = (%d)\n", Error);
  4274. // WINSEVT_LOG_M(Error, WINS_EVT_CANT_CREATE_MCAST_SOCK); //log an event
  4275. return;
  4276. }
  4277. DBGLEAVE("JoinMcastGrp\n");
  4278. return;
  4279. }
  4280. VOID
  4281. CommLeaveMcastGrp(
  4282. VOID
  4283. )
  4284. /*++
  4285. Routine Description:
  4286. This function is called by the comm. subsystem to make WINS join
  4287. a multicast group
  4288. Arguments:
  4289. Externals Used:
  4290. None
  4291. Return Value:
  4292. Success status codes --
  4293. Error status codes --
  4294. Error Handling:
  4295. Called by:
  4296. CommCreatePorts
  4297. Side Effects:
  4298. Comments:
  4299. None
  4300. --*/
  4301. {
  4302. DWORD Error;
  4303. struct ip_mreq mreq;
  4304. //
  4305. // Leave a multicast grp
  4306. //
  4307. mreq.imr_multiaddr.s_addr = htonl(McastAdd.sin_addr.s_addr);
  4308. mreq.imr_interface.s_addr = INADDR_ANY; //use the default mcast i/f
  4309. if (setsockopt(CommUdpPortHandle, IPPROTO_IP, IP_DROP_MEMBERSHIP,
  4310. (char *)&mreq, sizeof(mreq)) == SOCKET_ERROR)
  4311. {
  4312. Error = WSAGetLastError();
  4313. DBGPRINT1(MTCAST, "CommLeaveMcastGrp: Can not DROP MEMBERSHIP TO MCAST GRP. Error = (%d)\n", Error);
  4314. return;
  4315. }
  4316. return;
  4317. }
  4318. BOOL
  4319. CheckMcastSock(
  4320. IN fd_set *pActSocks,
  4321. IN fd_set *pRdSocks
  4322. )
  4323. {
  4324. DWORD Error;
  4325. int RetVal;
  4326. BYTE Buff[COMM_DATAGRAM_SIZE];
  4327. PCOMM_MCAST_MSG_T pMcastMsg = (PCOMM_MCAST_MSG_T)Buff;
  4328. struct sockaddr_in RemWinsAdd;
  4329. int RemWinsAddLen = sizeof(RemWinsAdd);
  4330. LPBYTE pBody;
  4331. COMM_IP_ADD_T IPAdd;
  4332. BOOL fFound;
  4333. DWORD i, j;
  4334. DWORD NoOfAddsInPkt;
  4335. struct in_addr InAdd;
  4336. LPBYTE pAdd;
  4337. DWORD FirstDelEntryIndex;
  4338. PPNR_STATUS_T pPnrStatusTmp;
  4339. DBGENTER("CheckMcastSock\n");
  4340. if (FD_ISSET(CommUdpPortHandle, pRdSocks))
  4341. {
  4342. //do a recvfrom to read in the data.
  4343. RetVal = recvfrom(
  4344. CommUdpPortHandle,
  4345. (char *)pMcastMsg,
  4346. COMM_DATAGRAM_SIZE,
  4347. //COMM_MCAST_MSG_SZ + COMM_IP_ADD_SIZE,
  4348. 0, //default flags (i.e. no peeking
  4349. //or reading OOB message
  4350. (struct sockaddr *)&RemWinsAdd,
  4351. &RemWinsAddLen
  4352. );
  4353. if (RetVal == SOCKET_ERROR)
  4354. {
  4355. Error = WSAGetLastError();
  4356. DBGPRINT1(MTCAST, "CheckMcastSock: recvfrom failed. Error = (%d)\n", Error);
  4357. if (WinsCnf.State_e != WINSCNF_E_TERMINATING)
  4358. {
  4359. WINSEVT_LOG_M(
  4360. Error,
  4361. WINS_EVT_WINSOCK_RECVFROM_ERR
  4362. );
  4363. }
  4364. //WINS_RAISE_EXC_M(WINS_EXC_FAILURE);
  4365. }
  4366. //
  4367. // If we were told not to use self found pnrs, return
  4368. //
  4369. if (!WinsCnf.fUseSelfFndPnrs)
  4370. {
  4371. DBGLEAVE("ChkMcastSock - 99\n");
  4372. return(TRUE);
  4373. }
  4374. //
  4375. // If the sign is not in the valid range, return
  4376. //
  4377. if ((pMcastMsg->Sign < COMM_MCAST_SIGN_START) || (pMcastMsg->Sign > COMM_MCAST_SIGN_END))
  4378. {
  4379. DBGPRINT1(MTCAST, "Signature in received message = %d\n", pMcastMsg->Sign);
  4380. DBGLEAVE("CheckMcastSock - 1\n");
  4381. return(TRUE);
  4382. }
  4383. //
  4384. // Compute the number of addresses in the packet.
  4385. //
  4386. NoOfAddsInPkt = (RetVal - (COMM_MCAST_MSG_SZ - 1))/COMM_IP_ADD_SIZE;
  4387. DBGPRINT2(MTCAST, "ChkMcastSock: RetVal = (%d);NoOfAddsInPkt = (%d)\n", RetVal, NoOfAddsInPkt);
  4388. FirstDelEntryIndex = pPnrStatus->NoOfPnrs;
  4389. pBody = pMcastMsg->Body;
  4390. IPAdd = *(PCOMM_IP_ADD_T)pBody;
  4391. pBody += COMM_IP_ADD_SIZE;
  4392. //
  4393. // Loop until either all ip addresses in packets are
  4394. // exhausted or we get an ip. address of 0. If somebody
  4395. // sent a 0 address, then it is ok to ignore the rest.
  4396. //
  4397. for(
  4398. ;
  4399. (IPAdd != 0) && NoOfAddsInPkt;
  4400. IPAdd = *(PCOMM_IP_ADD_T)pBody, pBody += COMM_IP_ADD_SIZE,
  4401. NoOfAddsInPkt--
  4402. )
  4403. {
  4404. DBGPRINT1(MTCAST, "CheckMcastSock: Processing WINS address = %lx\n", ntohl(IPAdd));
  4405. fFound = FALSE;
  4406. pPnrStatusTmp = (PPNR_STATUS_T)(pPnrStatus->Pnrs);
  4407. if (pMcastMsg->Code == COMM_MCAST_WINS_UP)
  4408. {
  4409. for (i=0; i < pPnrStatus->NoOfPnrs; i++, pPnrStatusTmp++)
  4410. {
  4411. if ((FirstDelEntryIndex == pPnrStatus->NoOfPnrs)
  4412. &&
  4413. (pPnrStatusTmp->State == COMM_MCAST_WINS_DOWN))
  4414. {
  4415. FirstDelEntryIndex = i;
  4416. }
  4417. if (IPAdd == pPnrStatusTmp->IPAdd)
  4418. {
  4419. if (pPnrStatusTmp->State == COMM_MCAST_WINS_DOWN)
  4420. {
  4421. pPnrStatusTmp->State = COMM_MCAST_WINS_UP;
  4422. InAdd.s_addr = IPAdd;
  4423. pAdd = inet_ntoa(InAdd);
  4424. WinsCnfAddPnr(RPL_E_PULL, pAdd);
  4425. WinsCnfAddPnr(RPL_E_PUSH, pAdd);
  4426. }
  4427. fFound = TRUE;
  4428. break;
  4429. }
  4430. }
  4431. if (!fFound && (i <= pPnrStatus->NoOfPnrs))
  4432. {
  4433. DWORD FirstFreeIndex;
  4434. PPNR_STATUS_T pPnr;
  4435. //
  4436. // since disable loopback is not working we
  4437. // have to check for message sent by self
  4438. //
  4439. FUTURES("Remove the if when winsock is enhanced to allow loopback to be")
  4440. FUTURES("disabled")
  4441. if (!ChkMyAdd(ntohl(IPAdd)))
  4442. {
  4443. InAdd.s_addr = IPAdd;
  4444. pAdd = inet_ntoa(InAdd);
  4445. if (FirstDelEntryIndex < pPnrStatus->NoOfPnrs)
  4446. {
  4447. FirstFreeIndex = FirstDelEntryIndex;
  4448. }
  4449. else
  4450. {
  4451. FirstFreeIndex = pPnrStatus->NoOfPnrs++;
  4452. if (pPnrStatus->NoOfPnrs == pPnrStatus->NoOfPnrSlots)
  4453. {
  4454. WINSMSC_REALLOC_M(MCAST_PNR_STATUS_SIZE_M(pPnrStatus->NoOfPnrSlots * 2), (LPVOID *)&pPnrStatus);
  4455. pPnrStatus->NoOfPnrSlots *= 2;
  4456. DBGPRINT1(DET, "CheckMcastSock: NO OF PNR SLOTS INCREASED TO (%d)\n", pPnrStatus->NoOfPnrSlots);
  4457. }
  4458. }
  4459. pPnr = (PPNR_STATUS_T)(pPnrStatus->Pnrs);
  4460. (pPnr + FirstFreeIndex)->State = COMM_MCAST_WINS_UP;
  4461. (pPnr + FirstFreeIndex)->IPAdd = IPAdd;
  4462. WinsCnfAddPnr(RPL_E_PULL, pAdd);
  4463. WinsCnfAddPnr(RPL_E_PUSH, pAdd);
  4464. DBGPRINT1(MTCAST, "CheckMcastSock: ADDED WINS partner with address = %s\n", pAdd);
  4465. }
  4466. }
  4467. }
  4468. else //has to be COMM_MCAST_WINS_DOWN
  4469. {
  4470. for (i=0; i < pPnrStatus->NoOfPnrs; i++, pPnrStatusTmp++)
  4471. {
  4472. if (IPAdd == pPnrStatusTmp->IPAdd)
  4473. {
  4474. if (pPnrStatusTmp->State == COMM_MCAST_WINS_DOWN)
  4475. {
  4476. fFound = TRUE;
  4477. }
  4478. else
  4479. {
  4480. pPnrStatusTmp->State = COMM_MCAST_WINS_DOWN;
  4481. }
  4482. break;
  4483. }
  4484. }
  4485. if (!fFound)
  4486. {
  4487. InAdd.s_addr = IPAdd;
  4488. pAdd = inet_ntoa(InAdd);
  4489. DBGPRINT1(MTCAST, "CheckMcastSock: Will REMOVE WINS partner with address = %s IFF Untouched by admin\n", pAdd);
  4490. WinsCnfDelPnr(RPL_E_PULL, pAdd);
  4491. WinsCnfDelPnr(RPL_E_PUSH, pAdd);
  4492. }
  4493. }
  4494. } // end of for loop
  4495. DBGLEAVE("ChkMcastSock - 2\n");
  4496. return(TRUE);
  4497. }
  4498. DBGLEAVE("ChkMcastSock - 3\n");
  4499. return(FALSE);
  4500. }
  4501. BOOL
  4502. ChkMyAdd(
  4503. COMM_IP_ADD_T IpAdd
  4504. )
  4505. {
  4506. DWORD i;
  4507. PCOMM_IP_ADD_T pIpAdd = pWinsAddresses->IpAdd;
  4508. for (i=0; i<pWinsAddresses->NoOfAdds; i++)
  4509. {
  4510. if (IpAdd == *pIpAdd++)
  4511. {
  4512. return(TRUE);
  4513. }
  4514. }
  4515. return(FALSE);
  4516. }
  4517. VOID
  4518. CommSendMcastMsg(
  4519. DWORD Code
  4520. )
  4521. {
  4522. PCOMM_MCAST_MSG_T pMcastMsg;
  4523. DWORD McastMsgLen;
  4524. LPBYTE pBody;
  4525. DWORD i;
  4526. COMM_IP_ADD_T Add = 0;
  4527. // --ft bug #103361: no need to send CommSendMcastMsg if there
  4528. // is no nic card here
  4529. if (pWinsAddresses == NULL)
  4530. return;
  4531. McastMsgLen = MCAST_PKT_LEN_M(pWinsAddresses->NoOfAdds + 1);
  4532. WinsMscAlloc(McastMsgLen, &pMcastMsg);
  4533. pMcastMsg->Code = Code;
  4534. pMcastMsg->Sign = COMM_MCAST_SIGN_START;
  4535. pBody = pMcastMsg->Body;
  4536. //
  4537. // Insert the count in net order.
  4538. //
  4539. // NMSMSGF_INSERT_ULONG_M(pBody, pWinsAddresses->NoOfAddresses);
  4540. //
  4541. // Insert the addresses in net order
  4542. //
  4543. for (i=0; i<pWinsAddresses->NoOfAdds; i++)
  4544. {
  4545. DBGPRINT1(MTCAST, "CommSendMcastMsg: Inserting Address = (%lx)\n",
  4546. pWinsAddresses->IpAdd[i]);
  4547. NMSMSGF_INSERT_IPADD_M(pBody, pWinsAddresses->IpAdd[i]);
  4548. }
  4549. NMSMSGF_INSERT_IPADD_M(pBody, Add);
  4550. DBGPRINT1(MTCAST, "CommSendMcastMsg: Sending MCAST msg of length = (%d)\n",
  4551. McastMsgLen);
  4552. CommSendUdp (CommUdpPortHandle, &McastAdd, (MSG_T)pMcastMsg, McastMsgLen);
  4553. WinsMscDealloc(pMcastMsg);
  4554. return;
  4555. }
  4556. #endif