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.

1377 lines
31 KiB

  1. //=============================================================================
  2. // Copyright (c) 1997 Microsoft Corporation
  3. // File Name: if.c
  4. // Abstract:
  5. //
  6. // Author: K.S.Lokesh (lokeshs@) 1-1-98
  7. //=============================================================================
  8. #include "pchdvmrp.h"
  9. #pragma hdrstop
  10. //----------------------------------------------------------------------------
  11. // _AddInterface
  12. //----------------------------------------------------------------------------
  13. DWORD
  14. WINAPI
  15. AddInterface(
  16. IN PWCHAR pInterfaceName,//not used
  17. IN ULONG IfIndex,
  18. IN NET_INTERFACE_TYPE IfType,
  19. IN DWORD MediaType,
  20. IN WORD AccessType,
  21. IN WORD ConnectionType,
  22. IN PVOID pConfig,
  23. IN ULONG StructureVersion,
  24. IN ULONG StructureSize,
  25. IN ULONG StructureCount
  26. )
  27. {
  28. DWORD Error = NO_ERROR;
  29. Trace1(ENTER, "entering AddInterface(): IfIndex:%d", IfIndex);
  30. ACQUIRE_IF_LIST_LOCK("_AddInterface");
  31. ACQUIRE_IF_LOCK_EXCLUSIVE(IfIndex, "_AddInterface");
  32. Error = AddIfEntry(IfIndex, pConfig, StructureSize);
  33. RELEASE_IF_LIST_LOCK("_AddInterface");
  34. RELEASE_IF_LOCK_EXCLUSIVE(IfIndex, "_AddInterface");
  35. Trace2(LEAVE, "leaving AddInterface(%d): %d\n", IfIndex, Error);
  36. return Error;
  37. }
  38. //----------------------------------------------------------------------------
  39. // _AddIfEntry
  40. //----------------------------------------------------------------------------
  41. DWORD
  42. AddIfEntry(
  43. ULONG IfIndex,
  44. PVOID pConfig,
  45. ULONG StructureSize
  46. )
  47. {
  48. DWORD Error = NO_ERROR;
  49. PIF_CONFIG pIfConfig = (PIF_CONFIG) pConfig;
  50. PIF_TABLE_ENTRY pite = NULL;
  51. //
  52. // validate interface config
  53. //
  54. Error = ValidateIfConfig(IfIndex, pIfConfig, StructureSize);
  55. if (Error != NO_ERROR) {
  56. Trace1(ERR,
  57. "AddInterface(%d) failed due to invalid configuration",
  58. IfIndex);
  59. return Error;
  60. }
  61. BEGIN_BREAKOUT_BLOCK1 {
  62. //
  63. // fail if the interface exists.
  64. //
  65. pite = GetIfEntry(IfIndex);
  66. if (pite != NULL) {
  67. Trace1(ERR, "interface %d already exists", IfIndex);
  68. Error = ERROR_INVALID_PARAMETER;
  69. GOTO_END_BLOCK1;
  70. }
  71. //
  72. // allocate memory for the new interface and its different fields
  73. //
  74. // allocate memory for IfTable
  75. pite = DVMRP_ALLOC_AND_ZERO(sizeof(IF_TABLE_ENTRY));
  76. PROCESS_ALLOC_FAILURE3(pite, "interface %d", Error,
  77. sizeof(IF_TABLE_ENTRY), IfIndex, GOTO_END_BLOCK1);
  78. InitializeListHead(&pite->Link);
  79. InitializeListHead(&pite->HTLink);
  80. pite->IfIndex = IfIndex;
  81. // set interface status (neither bound, enabled or activated)
  82. pite->Status = IF_CREATED_FLAG;
  83. // set base refcount to 1
  84. pite->RefCount = 1;
  85. //
  86. // allocate memory for IfConfig and copy it.
  87. //
  88. pite->pConfig = DVMRP_ALLOC_AND_ZERO(DVMRP_IF_CONFIG_SIZE(pIfConfig));
  89. PROCESS_ALLOC_FAILURE3(pite, "interface %d", Error,
  90. DVMRP_IF_CONFIG_SIZE(pIfConfig), IfIndex, GOTO_END_BLOCK1);
  91. memcpy(pite->pConfig, pIfConfig, DVMRP_IF_CONFIG_SIZE(pIfConfig));
  92. // allocate memory for IfInfo
  93. pite->pInfo = DVMRP_ALLOC_AND_ZERO(sizeof(IF_INFO));
  94. PROCESS_ALLOC_FAILURE3(pite, "interface %d", Error,
  95. sizeof(IF_INFO), IfIndex, GOTO_END_BLOCK1);
  96. //
  97. // allocate memory for Socket data
  98. //
  99. pite->pSocketData = DVMRP_ALLOC_AND_ZERO(sizeof(ASYNC_SOCKET_DATA));
  100. PROCESS_ALLOC_FAILURE3(pite, "interface %d", Error,
  101. sizeof(ASYNC_SOCKET_DATA), IfIndex, GOTO_END_BLOCK1);
  102. pite->pSocketData->WsaBuf.buf = DVMRP_ALLOC(PACKET_BUFFER_SIZE);
  103. PROCESS_ALLOC_FAILURE3(pite, "interface %d", Error,
  104. PACKET_BUFFER_SIZE, IfIndex, GOTO_END_BLOCK1);
  105. pite->pSocketData->WsaBuf.len = PACKET_BUFFER_SIZE;
  106. pite->pSocketData->pite = pite;
  107. } END_BREAKOUT_BLOCK1;
  108. // initialize the sockets to invalid_socket
  109. pite->Socket = INVALID_SOCKET;
  110. // insert the interface in the hash table at the end.
  111. InsertTailList(&G_pIfTable->IfHashTable[IF_HASH_VALUE(IfIndex)],
  112. &pite->HTLink);
  113. //
  114. // insert the entry into the interface list
  115. //
  116. {
  117. PIF_TABLE_ENTRY piteTmp;
  118. PLIST_ENTRY pHead, ple;
  119. pHead = &G_pIfTable->IfList;
  120. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  121. piteTmp = CONTAINING_RECORD(ple, IF_TABLE_ENTRY, Link);
  122. if (pite->IfIndex < piteTmp->IfIndex)
  123. break;
  124. }
  125. InsertTailList(ple, &pite->Link);
  126. }
  127. if ( (Error!=NO_ERROR)&&(pite!=NULL) ) {
  128. DeleteIfEntry(pite);
  129. }
  130. return Error;
  131. }//end AddIfEntry
  132. //-----------------------------------------------------------------------------
  133. // _DeleteIfEntry
  134. //-----------------------------------------------------------------------------
  135. VOID
  136. DeleteIfEntry(
  137. PIF_TABLE_ENTRY pite
  138. )
  139. {
  140. if (!pite)
  141. return;
  142. //
  143. // delete peers
  144. //
  145. //
  146. // remove the entry from the interface list, and hashTable
  147. //
  148. RemoveEntryList(&pite->Link);
  149. RemoveEntryList(&pite->HTLink);
  150. if (pite->Socket != INVALID_SOCKET) {
  151. closesocket(pite->Socket);
  152. }
  153. DVMRP_FREE(pite->pInfo);
  154. DVMRP_FREE(pite->pBinding);
  155. DVMRP_FREE(pite->pConfig);
  156. return;
  157. }//end _DeleteIfEntry
  158. //----------------------------------------------------------------------------
  159. // _DeleteInterface
  160. //----------------------------------------------------------------------------
  161. DWORD
  162. DeleteInterface(
  163. IN DWORD IfIndex
  164. )
  165. {
  166. DWORD Error = NO_ERROR;
  167. return Error;
  168. }//end _DeleteInterface
  169. //----------------------------------------------------------------------------
  170. // _InterfaceStatus
  171. //----------------------------------------------------------------------------
  172. DWORD
  173. WINAPI
  174. InterfaceStatus(
  175. ULONG IfIndex,
  176. BOOL IsIfActive,
  177. DWORD StatusType,
  178. PVOID pStatusInfo
  179. )
  180. {
  181. DWORD Error = NO_ERROR;
  182. switch(StatusType)
  183. {
  184. case RIS_INTERFACE_ADDRESS_CHANGE:
  185. {
  186. PIP_ADAPTER_BINDING_INFO pBindInfo
  187. = (PIP_ADAPTER_BINDING_INFO)pStatusInfo;
  188. if(pBindInfo->AddressCount)
  189. {
  190. Error = BindInterface(IfIndex, pBindInfo);
  191. }
  192. else
  193. {
  194. Error = UnBindInterface(IfIndex);
  195. }
  196. break;
  197. }
  198. case RIS_INTERFACE_ENABLED:
  199. {
  200. Error = EnableInterface(IfIndex);
  201. break;
  202. }
  203. case RIS_INTERFACE_DISABLED:
  204. {
  205. Error = DisableInterface(IfIndex);
  206. break;
  207. }
  208. }
  209. return Error;
  210. }
  211. //----------------------------------------------------------------------------
  212. // _BindInterface
  213. //----------------------------------------------------------------------------
  214. DWORD
  215. BindInterface(
  216. ULONG IfIndex,
  217. PIP_ADAPTER_BINDING_INFO pBinding
  218. )
  219. {
  220. DWORD Error = NO_ERROR;
  221. PIF_TABLE_ENTRY pite = NULL;
  222. DWORD i, Size, AddrCount;
  223. IPADDR MinAddr;
  224. PDVMRP_ADDR_MASK pAddrBinding;
  225. INT cmp;
  226. IPADDR ConfigAddr = 0;
  227. Trace1(ENTER1, "entering BindInterface: %d", IfIndex);
  228. Trace1(IF, "binding interface %d", IfIndex);
  229. // pBinding should not be NULL
  230. if (pBinding == NULL) {
  231. Trace0(IF, "error: binding struct pointer is NULL");
  232. Trace1(LEAVE, "leaving BindInterface: %d", ERROR_INVALID_PARAMETER);
  233. return ERROR_INVALID_PARAMETER;
  234. }
  235. //
  236. // take exclusive interface lock
  237. //
  238. ACQUIRE_IF_LOCK_EXCLUSIVE(IfIndex, "_BindInterface");
  239. BEGIN_BREAKOUT_BLOCK1 {
  240. AddrCount = pBinding->AddressCount;
  241. //
  242. // retrieve the interface entry
  243. //
  244. pite = GetIfByIndex(IfIndex);
  245. if (pite == NULL) {
  246. Error = ERROR_INVALID_PARAMETER;
  247. GOTO_END_BLOCK1;
  248. }
  249. //
  250. // If the interface is already bound then return error.
  251. // todo: do I need to check if the bindings are same
  252. //
  253. if (IS_IF_BOUND(pite)) {
  254. Trace1(IF, "interface %d is already bound", IfIndex);
  255. GOTO_END_BLOCK1;
  256. }
  257. //
  258. // make sure there is at least one address.
  259. //
  260. if (AddrCount==0) {
  261. Error = ERROR_CAN_NOT_COMPLETE;
  262. GOTO_END_BLOCK1;
  263. }
  264. //
  265. // if an effective address is already configured, make sure it
  266. // is present in the list of address bindings
  267. //
  268. ConfigAddr = pite->pConfig->ConfigIpAddr;
  269. if (ConfigAddr) {
  270. BOOL Found = FALSE;
  271. for (i=0; i<AddrCount; i++) {
  272. if (ConfigAddr == pBinding->Address[i].Address) {
  273. Found = TRUE;
  274. break;
  275. }
  276. }
  277. if (!Found) {
  278. Trace2(ERR,
  279. "Configured effective IP Address:%d.%d.%d.%d on interface"
  280. ":%d not part of address bindings",
  281. PRINT_IPADDR(ConfigAddr), IfIndex);
  282. Error = ERROR_CAN_NOT_COMPLETE;
  283. GOTO_END_BLOCK1;
  284. }
  285. }
  286. //
  287. // allocate memory to store the binding
  288. //
  289. Size = AddrCount * sizeof(DVMRP_ADDR_MASK);
  290. pAddrBinding = DVMRP_ALLOC(Size);
  291. PROCESS_ALLOC_FAILURE3(pAddrBinding, "binding on interface %d",
  292. Error, Size, IfIndex, GOTO_END_BLOCK1);
  293. //
  294. // copy the bindings
  295. //
  296. MinAddr = ~0;
  297. for (i=0; i<AddrCount; i++,pAddrBinding++) {
  298. pAddrBinding->IpAddr = pBinding->Address[i].Address;
  299. pAddrBinding->Mask = pBinding->Address[i].Mask;
  300. if (!ConfigAddr && (INET_CMP(MinAddr, pAddrBinding->IpAddr, cmp)>0))
  301. MinAddr = pAddrBinding->IpAddr;
  302. }
  303. //
  304. // set the Interface effective address to the smallest bound address
  305. //
  306. pite->IpAddr = ConfigAddr ? ConfigAddr : MinAddr;
  307. //
  308. // save the binding in the interface entry
  309. //
  310. pite->pBinding = pAddrBinding;
  311. pite->NumAddrBound = pBinding->AddressCount;
  312. //
  313. // mark the interface as being bound
  314. //
  315. pite->Status |= IF_BOUND_FLAG;
  316. //
  317. // if interface is also enabled, it is now active
  318. // so activate it
  319. //
  320. if (IS_IF_ENABLED_BOUND(pite)) {
  321. //
  322. // Activate the Interface
  323. //
  324. Error = ActivateInterface(pite);
  325. //
  326. // if could not activate the interface then undo the binding
  327. //
  328. if (Error != NO_ERROR) {
  329. Trace1(ERR,
  330. "Unbinding interface(%d) as it could not be activated",
  331. IfIndex);
  332. Error = ERROR_CAN_NOT_COMPLETE;
  333. GOTO_END_BLOCK1;
  334. }
  335. }
  336. } END_BREAKOUT_BLOCK1;
  337. //
  338. // if there was any error, then set the status to unbound (pite is null
  339. // if interface was not found)
  340. //
  341. if ((Error!=NO_ERROR)&&(pite!=NULL)) {
  342. pite->Status &= ~IF_BOUND_FLAG;
  343. if (pite->pBinding)
  344. DVMRP_FREE_AND_NULL(pite->pBinding);
  345. pite->NumAddrBound = 0;
  346. pite->IpAddr = 0;
  347. }
  348. RELEASE_IF_LOCK_EXCLUSIVE(IfIndex, "_BindInterface");
  349. Trace2(LEAVE1, "leaving _BindInterface(%d): %d\n", IfIndex, Error);
  350. return Error;
  351. }
  352. //-----------------------------------------------------------------------------
  353. // _EnableInterface
  354. //
  355. // sets the status to enabled. If interface is also bound and enabled in
  356. // config, then activate the interface.
  357. //
  358. // Locks: Exclusive IfLock
  359. //-----------------------------------------------------------------------------
  360. DWORD
  361. EnableInterface(
  362. IN DWORD IfIndex
  363. )
  364. {
  365. DWORD Error = NO_ERROR;
  366. Trace1(ENTER1, "entering _EnableInterface(%d):", IfIndex);
  367. Trace1(IF, "enabling interface %d", IfIndex);
  368. //
  369. // enable the interface
  370. //
  371. ACQUIRE_IF_LOCK_EXCLUSIVE(IfIndex, "_EnableInterface");
  372. Error = EnableIfEntry(IfIndex, TRUE); //enabled by RtrMgr
  373. RELEASE_IF_LOCK_EXCLUSIVE(IfIndex, "_EnableInterface");
  374. Trace2(LEAVE1, "leaving _EnableInterface(%d): %d\n", IfIndex, Error);
  375. return Error;
  376. }
  377. //-----------------------------------------------------------------------------
  378. // _EnableIfEntry
  379. //-----------------------------------------------------------------------------
  380. DWORD
  381. EnableIfEntry(
  382. DWORD IfIndex,
  383. BOOL bChangedByRtrmgr // changed by rtrmg or SetInterfaceConfigInfo
  384. )
  385. {
  386. DWORD Error = NO_ERROR;
  387. PLIST_ENTRY ple, phead;
  388. PIF_TABLE_ENTRY pite = NULL;
  389. BEGIN_BREAKOUT_BLOCK1 {
  390. //
  391. // retrieve the interface
  392. //
  393. pite = GetIfByIndex(IfIndex);
  394. if (pite == NULL) {
  395. Trace1(IF, "could not find interface %d",IfIndex);
  396. Error = ERROR_INVALID_PARAMETER;
  397. GOTO_END_BLOCK1;
  398. }
  399. if (bChangedByRtrmgr) {
  400. //
  401. // quit if the interface is already enabled by the router manager
  402. //
  403. if (IS_IF_ENABLED_BY_RTRMGR(pite)) {
  404. Trace1(IF, "interface %d is already enabled by RtrMgr",
  405. IfIndex);
  406. Error = NO_ERROR;
  407. GOTO_END_BLOCK1;
  408. }
  409. // set the flag to enabled by router manager
  410. pite->Status |= IF_ENABLED_FLAG;
  411. // print trace if enabled flag not set in the Config.
  412. if (!IS_IF_ENABLED_IN_CONFIG(pite)) {
  413. Trace1(IF,
  414. "Interface(%d) enabled by router manager but not enabled"
  415. "in the Config", pite->IfIndex);
  416. }
  417. }
  418. else {
  419. //
  420. // quit if the interface is already enabled in config
  421. //
  422. if (IS_IF_ENABLED_IN_CONFIG(pite)) {
  423. Trace1(IF, "interface %d is already enabled in Config",
  424. IfIndex);
  425. Error = NO_ERROR;
  426. GOTO_END_BLOCK1;
  427. }
  428. // set the config flag to enabled
  429. pite->pConfig->Flags |= DVMRP_IF_ENABLED_IN_CONFIG;
  430. // print trace if interface not enabled by router manager
  431. if (!IS_IF_ENABLED_BY_RTRMGR(pite)) {
  432. Trace1(IF,
  433. "Interface(%d) enabled in config but not by RtrMgr",
  434. IfIndex);
  435. Error = NO_ERROR;
  436. GOTO_END_BLOCK1;
  437. }
  438. }
  439. //
  440. // if interface is already bound, it should be activated
  441. // if the bInterfaceEnabled flag is also set in config (by the UI)
  442. //
  443. if (IS_IF_ENABLED_BOUND(pite)) {
  444. //
  445. // Activate the Interface
  446. //
  447. Error = ActivateInterface(pite);
  448. //
  449. // if could not activate the interface then disable it again
  450. //
  451. if (Error != NO_ERROR) {
  452. Trace1(ERR,
  453. "Disabling interface(%d) as it could not be activated",
  454. IfIndex);
  455. Error = ERROR_CAN_NOT_COMPLETE;
  456. GOTO_END_BLOCK1;
  457. }
  458. }
  459. } END_BREAKOUT_BLOCK1;
  460. //
  461. // if an error occured somewhere, set the interface back to the previous
  462. // disabled state.(pite may be null if interface was not found).
  463. //
  464. if ((Error!=NO_ERROR)&&(pite!=NULL)) {
  465. if (bChangedByRtrmgr)
  466. pite->Status &= ~IF_ENABLED_FLAG;
  467. else
  468. pite->pConfig->Flags &= DVMRP_IF_ENABLED_IN_CONFIG;
  469. }
  470. return Error;
  471. }//end _EnableIfEntry
  472. //-----------------------------------------------------------------------------
  473. // _DisableInterface
  474. //
  475. // If interface is activated, then deactivates it.
  476. // Locks: Runs completely in exclusive interface lock.
  477. // Calls: _DisableIfEntry()
  478. //-----------------------------------------------------------------------------
  479. DWORD
  480. DisableInterface(
  481. IN DWORD IfIndex
  482. )
  483. {
  484. DWORD Error;
  485. Trace1(ENTER, "entering DisableInterface(%d):", IfIndex);
  486. //
  487. // disable the interface
  488. //
  489. ACQUIRE_IF_LOCK_EXCLUSIVE(IfIndex, "_DisableInterface");
  490. Error = DisableIfEntry(IfIndex, TRUE); //disabled by RtrMgr
  491. RELEASE_IF_LOCK_EXCLUSIVE(IfIndex, "_DisableInterface");
  492. Trace2(LEAVE, "leaving DisableInterface(%d): %d\n", IfIndex, Error);
  493. return Error;
  494. }
  495. //-----------------------------------------------------------------------------
  496. // _DisableIfEntry
  497. //
  498. // Called by: _DisableInterface()
  499. //-----------------------------------------------------------------------------
  500. DWORD
  501. DisableIfEntry(
  502. DWORD IfIndex,
  503. BOOL bChangedByRtrmgr
  504. )
  505. {
  506. DWORD Error = NO_ERROR;
  507. PIF_TABLE_ENTRY pite, piteNew;
  508. BOOL bProxy;
  509. BEGIN_BREAKOUT_BLOCK1 {
  510. //
  511. // retrieve the interface to be disabled
  512. //
  513. pite = GetIfByIndex(IfIndex);
  514. if (pite == NULL) {
  515. Trace1(IF, "could not find interface %d", IfIndex);
  516. Error = ERROR_INVALID_PARAMETER;
  517. GOTO_END_BLOCK1;
  518. }
  519. if (bChangedByRtrmgr) {
  520. //
  521. // quit if already disabled by router manager
  522. //
  523. if (!IS_IF_ENABLED_BY_RTRMGR(pite)) {
  524. Trace1(IF, "interface %d already disabled by router manager",
  525. IfIndex);
  526. Error = ERROR_INVALID_PARAMETER;
  527. GOTO_END_BLOCK1;
  528. }
  529. }
  530. else {
  531. //
  532. // quit if already disabled in Config
  533. //
  534. if (!IS_IF_ENABLED_IN_CONFIG(pite)) {
  535. Trace1(IF, "interface %d already disabled in config",
  536. IfIndex);
  537. Error = ERROR_INVALID_PARAMETER;
  538. GOTO_END_BLOCK1;
  539. }
  540. }
  541. //
  542. // if IF activated (ie also enabled), deactivate it
  543. // note: check for activated flag, and not for enabled flag
  544. //
  545. if (IS_IF_ACTIVATED(pite)) {
  546. DeactivateInterface(pite);
  547. }
  548. //
  549. // clear the enabled flag
  550. //
  551. if (bChangedByRtrmgr)
  552. pite->Status &= ~IF_ENABLED_FLAG;
  553. else
  554. pite->pConfig->Flags &= ~DVMRP_IF_ENABLED_IN_CONFIG;
  555. } END_BREAKOUT_BLOCK1;
  556. return Error;
  557. } //end _DisableIfEntry
  558. //-----------------------------------------------------------------------------
  559. // _CreateIfSockets
  560. //-----------------------------------------------------------------------------
  561. DWORD
  562. CreateIfSockets(
  563. PIF_TABLE_ENTRY pite
  564. )
  565. {
  566. DWORD Error = NO_ERROR;
  567. DWORD Retval, SockType;
  568. DWORD IpAddr = pite->IpAddr;
  569. DWORD IfIndex = pite->IfIndex;
  570. SOCKADDR_IN saLocalIf;
  571. BEGIN_BREAKOUT_BLOCK1 {
  572. //
  573. // create input socket
  574. //
  575. pite->Socket = WSASocket(AF_INET, SOCK_RAW, IPPROTO_IGMP, NULL, 0, 0);
  576. if (pite->Socket == INVALID_SOCKET) {
  577. LPSTR lpszAddr;
  578. Error = WSAGetLastError();
  579. lpszAddr = INET_NTOA(IpAddr);
  580. Trace3(IF,
  581. "error %d creating socket for interface %d (%d.%d.%d.%d)",
  582. Error, IfIndex, PRINT_IPADDR(IpAddr));
  583. Logerr1(CREATE_SOCKET_FAILED_2, "%S", lpszAddr, Error);
  584. GOTO_END_BLOCK1;
  585. }
  586. //
  587. // bind socket to local interface. If I dont bind multicast may
  588. // not work.
  589. //
  590. ZeroMemory(&saLocalIf, sizeof(saLocalIf));
  591. saLocalIf.sin_family = PF_INET;
  592. saLocalIf.sin_addr.s_addr = IpAddr;
  593. saLocalIf.sin_port = 0; //port shouldnt matter
  594. // bind the input socket
  595. Error = bind(pite->Socket, (SOCKADDR FAR *)&saLocalIf,
  596. sizeof(SOCKADDR));
  597. if (Error == SOCKET_ERROR) {
  598. LPSTR lpszAddr;
  599. Error = WSAGetLastError();
  600. lpszAddr = INET_NTOA(IpAddr);
  601. Trace3(IF, "error %d binding on socket for interface %d (%d.%d.%d.%d)",
  602. Error, IfIndex, PRINT_IPADDR(IpAddr));
  603. Logerr1(BIND_FAILED, "S", lpszAddr, Error);
  604. GOTO_END_BLOCK1;
  605. }
  606. // set ttl to 1: not required as it is set to 1 by default.
  607. McastSetTtl(pite->Socket, 1);
  608. //
  609. // disable multicast packets from being loopedback.
  610. //
  611. {
  612. BOOL bLoopBack = FALSE;
  613. DWORD Retval;
  614. Retval = setsockopt(pite->Socket, IPPROTO_IP, IP_MULTICAST_LOOP,
  615. (char *)&bLoopBack, sizeof(BOOL));
  616. if (Retval==SOCKET_ERROR) {
  617. Trace2(ERR, "error %d disabling multicast loopBack on IfIndex %d",
  618. WSAGetLastError(), IfIndex);
  619. }
  620. }
  621. //
  622. // set the interface on which multicasts must be sent
  623. //
  624. Retval = setsockopt(pite->Socket, IPPROTO_IP, IP_MULTICAST_IF,
  625. (PBYTE)&saLocalIf.sin_addr, sizeof(IN_ADDR));
  626. if (Retval == SOCKET_ERROR) {
  627. LPSTR lpszAddr;
  628. Error = WSAGetLastError();
  629. lpszAddr = INET_NTOA(pite->IpAddr);
  630. Trace3(IF, "error %d setting interface %d (%s) to send multicast",
  631. Error, IfIndex, lpszAddr);
  632. Logerr1(SET_MCAST_IF_FAILED, "%S", lpszAddr, Error);
  633. Error = Retval;
  634. GOTO_END_BLOCK1;
  635. }
  636. //
  637. // join dvmrp multicast group
  638. //
  639. JoinMulticastGroup(pite->Socket, ALL_DVMRP_ROUTERS_MCAST_GROUP,
  640. pite->IfIndex, pite->IpAddr);
  641. // bind socket to io completion port
  642. BindIoCompletionCallback((HANDLE)pite->Socket,
  643. ProcessAsyncReceivePacket, 0);
  644. // increment refcount corresponding to the pending IO requests
  645. pite->RefCount++;
  646. // post async Read request
  647. #if 0
  648. // kslksl
  649. PostAsyncRead(pite);
  650. #endif
  651. } END_BREAKOUT_BLOCK1;
  652. if (Error!=NO_ERROR)
  653. DeleteIfSockets(pite);
  654. return Error;
  655. } //end _CreateIfSockets
  656. VOID
  657. DeleteIfSockets(
  658. PIF_TABLE_ENTRY pite
  659. )
  660. {
  661. return;
  662. }
  663. //-----------------------------------------------------------------------------
  664. // _ActivateInterface
  665. //
  666. // an interface is activated: when it is bound, enabled by RtrMgr & in config
  667. // When activated,
  668. // (1) call is made to MGM to take interface ownership,
  669. // (2) timers set and input socket is activated.
  670. //
  671. // Called by: _BindIfEntry, _EnableIfEntry,
  672. //-----------------------------------------------------------------------------
  673. DWORD
  674. ActivateInterface(
  675. PIF_TABLE_ENTRY pite
  676. )
  677. {
  678. DWORD Error = NO_ERROR, IfIndex = pite->IfIndex;
  679. LONGLONG CurTime = GetCurrentDvmrpTime();
  680. Trace2(ENTER, "entering ActivateInterface(%d:%d.%d.%d.%d)",
  681. IfIndex, PRINT_IPADDR(pite->IpAddr));
  682. BEGIN_BREAKOUT_BLOCK1 {
  683. //
  684. // set time when it is activated
  685. //
  686. pite->pInfo->TimeWhenActivated = CurTime;
  687. //
  688. // create sockets for interface
  689. //
  690. Error = CreateIfSockets(pite);
  691. if (Error != NO_ERROR) {
  692. Trace2(IF, "error %d initializing sockets for interface %d",
  693. Error, pite->IfIndex);
  694. GOTO_END_BLOCK1;
  695. }
  696. pite->CreationFlags |= IF_FLAGS_SOCKETS_CREATED;
  697. //
  698. // register the protocol with mgm if it is the first active IF
  699. //
  700. if (!G_pIfTable->NumActiveIfs++) {
  701. Error = RegisterDvmrpWithMgm();
  702. if (Error!=NO_ERROR) {
  703. G_pIfTable->NumActiveIfs--;
  704. GOTO_END_BLOCK1;
  705. }
  706. }
  707. pite->CreationFlags |= IF_FLAGS_PROTO_REGISTERED_WITH_MGM;
  708. //
  709. // take interface ownership with MGM
  710. //
  711. Error = MgmTakeInterfaceOwnership(Globals.MgmDvmrpHandle, IfIndex, 0);
  712. if (Error!=NO_ERROR) {
  713. Trace1(MGM, "MgmTakeInterfaceOwnership rejected for interface %d",
  714. IfIndex);
  715. Logerr0(MGM_TAKE_IF_OWNERSHIP_FAILED, Error);
  716. GOTO_END_BLOCK1;
  717. }
  718. else {
  719. Trace1(MGM,
  720. "MgmTakeInterfaceOwnership successful for interface %d",
  721. IfIndex);
  722. }
  723. pite->CreationFlags |= IF_FLAGS_IF_REGISTERED_WITH_MGM;
  724. //
  725. // dvmrp does a (*,*) join
  726. //
  727. Error = MgmAddGroupMembershipEntry(Globals.MgmDvmrpHandle, 0, 0, 0, 0,
  728. IfIndex, 0);
  729. if (Error!=NO_ERROR) {
  730. Trace1(ERR,
  731. "Dvmrp failed to add *,* entry to MGM on interface %d",
  732. IfIndex);
  733. GOTO_END_BLOCK1;
  734. }
  735. Trace0(MGM, "Dvmrp added *,* entry to MGM");
  736. //
  737. // create required timers
  738. //
  739. } END_BREAKOUT_BLOCK1;
  740. //
  741. // if error, deactivate interface
  742. //
  743. if (Error!=NO_ERROR) {
  744. DeactivateInterface(pite);
  745. pite->Status &= ~IF_ACTIVATED_FLAG;
  746. }
  747. else {
  748. //
  749. // set interface status to activated
  750. //
  751. pite->Status |= IF_ACTIVATED_FLAG;
  752. }
  753. Trace1(LEAVE, "leaving ActivateInterface():%d\n", Error);
  754. return Error;
  755. } //end _ActivateInterface
  756. DWORD
  757. DeactivateInterface(
  758. PIF_TABLE_ENTRY pite
  759. )
  760. {
  761. DWORD Error;
  762. // zero info
  763. Error = NO_ERROR;
  764. return Error;
  765. }
  766. //-----------------------------------------------------------------------------
  767. // UnBindInterface
  768. //-----------------------------------------------------------------------------
  769. DWORD
  770. UnBindInterface(
  771. IN DWORD IfIndex
  772. )
  773. {
  774. DWORD Error;
  775. PIF_TABLE_ENTRY pite, piteNew;
  776. Trace1(ENTER, "entering UnBindInterface(%d):", IfIndex);
  777. //
  778. // unbind the interface
  779. //
  780. //
  781. // acquire exclusive interface lock
  782. //
  783. ACQUIRE_IF_LOCK_EXCLUSIVE(IfIndex, "_UnBindInterface");
  784. BEGIN_BREAKOUT_BLOCK1 {
  785. //
  786. // retrieve the interface specified
  787. //
  788. pite = GetIfByIndex(IfIndex);
  789. if (pite == NULL) {
  790. Trace1(ERR, "UnbindInterface called for non existing If(%d)",
  791. IfIndex);
  792. Error = ERROR_INVALID_PARAMETER;
  793. GOTO_END_BLOCK1;
  794. }
  795. //
  796. // quit if the interface is already unbound
  797. //
  798. if (!IS_IF_BOUND(pite)) {
  799. Error = ERROR_INVALID_PARAMETER;
  800. Trace1(ERR, "interface %d is already unbound", IfIndex);
  801. GOTO_END_BLOCK1;
  802. }
  803. //
  804. // clear the "bound" flag
  805. //
  806. pite->Status &= ~IF_BOUND_FLAG;
  807. //
  808. // if IF activated (ie also enabled), deactivate it
  809. // note: check for activated flag, and not for enabled flag
  810. //
  811. if (IS_IF_ACTIVATED(pite)) {
  812. DeactivateInterface(pite);
  813. }
  814. //
  815. // unbind IF
  816. //
  817. DVMRP_FREE_AND_NULL(pite->pBinding);
  818. pite->NumAddrBound = 0;
  819. pite->IpAddr = 0;
  820. } END_BREAKOUT_BLOCK1;
  821. RELEASE_IF_LOCK_EXCLUSIVE(IfIndex, "_UnBindInterface");
  822. Trace2(LEAVE, "leaving UnBindInterface(%d): %d\n", IfIndex, Error);
  823. return Error;
  824. }
  825. //----------------------------------------------------------------------------
  826. // _SetInterfaceConfigInfo
  827. //----------------------------------------------------------------------------
  828. DWORD
  829. WINAPI
  830. SetInterfaceConfigInfo(
  831. IN DWORD IfIndex,
  832. IN PVOID pvConfig,
  833. IN ULONG ulStructureVersion,
  834. IN ULONG ulStructureSize,
  835. IN ULONG ulStructureCount
  836. )
  837. {
  838. DWORD Error = NO_ERROR;
  839. return Error;
  840. }
  841. //----------------------------------------------------------------------------
  842. // _GetInterfaceConfigInfo
  843. //----------------------------------------------------------------------------
  844. DWORD
  845. WINAPI
  846. GetInterfaceConfigInfo(
  847. IN DWORD IfIndex,
  848. IN OUT PVOID pvConfig,
  849. IN OUT PDWORD pdwSize,
  850. IN OUT PULONG pulStructureVersion,
  851. IN OUT PULONG pulStructureSize,
  852. IN OUT PULONG pulStructureCount
  853. )
  854. {
  855. DWORD Error = NO_ERROR;
  856. return Error;
  857. }
  858. //----------------------------------------------------------------------------
  859. // _ValidateIfConfig
  860. //----------------------------------------------------------------------------
  861. DWORD
  862. ValidateIfConfig(
  863. ULONG IfIndex,
  864. PDVMRP_IF_CONFIG pIfConfig,
  865. ULONG StructureSize
  866. )
  867. {
  868. //
  869. // check IfConfig size
  870. //
  871. if (StructureSize < sizeof(DVMRP_IF_CONFIG)
  872. || (StructureSize != DVMRP_IF_CONFIG_SIZE(pIfConfig))
  873. ){
  874. Trace1(ERR, "Dvmrp config structure for interface:%d too small.\n",
  875. IfIndex);
  876. return ERROR_INVALID_DATA;
  877. }
  878. DebugPrintIfConfig(IfIndex, pIfConfig);
  879. //
  880. // check Probe Interval
  881. //
  882. if (pIfConfig->ProbeInterval != DVMRP_PROBE_INTERVAL) {
  883. Trace2(CONFIG,
  884. "ProbeInterval being set to %d. Suggested value:%d",
  885. pIfConfig->ProbeInterval, DVMRP_PROBE_INTERVAL);
  886. }
  887. if (pIfConfig->ProbeInterval < 1000) {
  888. Trace2(ERR,
  889. "ProbeInterval has very low value:%d, suggested:%d",
  890. pIfConfig->ProbeInterval, DVMRP_PROBE_INTERVAL);
  891. return ERROR_INVALID_DATA;
  892. }
  893. //
  894. // check Peer timeout interval
  895. //
  896. if (pIfConfig->PeerTimeoutInterval != PEER_TIMEOUT_INTERVAL) {
  897. Trace2(CONFIG,
  898. "PeerTimeoutInterval being set to %d. Suggested value:%d",
  899. pIfConfig->PeerTimeoutInterval, PEER_TIMEOUT_INTERVAL);
  900. }
  901. if (pIfConfig->PeerTimeoutInterval < 1000) {
  902. Trace2(ERR,
  903. "PeerTimeoutInterval has very low value:%d, suggested:%d",
  904. pIfConfig->PeerTimeoutInterval, PEER_TIMEOUT_INTERVAL);
  905. return ERROR_INVALID_DATA;
  906. }
  907. //
  908. // check MinTriggeredUpdateInterval
  909. //
  910. if (pIfConfig->MinTriggeredUpdateInterval
  911. != MIN_TRIGGERED_UPDATE_INTERVAL
  912. ) {
  913. Trace2(CONFIG,
  914. "MinTriggeredUpdateInterval being set to %d. Suggested value:%d",
  915. pIfConfig->MinTriggeredUpdateInterval,
  916. MIN_TRIGGERED_UPDATE_INTERVAL);
  917. }
  918. //
  919. // check PeerFilterMode
  920. //
  921. switch(pIfConfig->PeerFilterMode) {
  922. case DVMRP_FILTER_DISABLED:
  923. case DVMRP_FILTER_INCLUDE:
  924. case DVMRP_FILTER_EXCLUDE:
  925. {
  926. break;
  927. }
  928. default:
  929. {
  930. Trace2(ERR, "Invalid value:%d for PeerFilterMode on Interface:%d",
  931. pIfConfig->PeerFilterMode, IfIndex);
  932. return ERROR_INVALID_DATA;
  933. }
  934. }
  935. } //end _ValidateIfConfig