Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2836 lines
96 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. action.c
  5. Abstract:
  6. This module contains code which performs the following TDI services:
  7. o TdiAction
  8. Environment:
  9. Kernel mode
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include <packon.h>
  15. //
  16. // Line ups when indicated up should have this length subtracted from the
  17. // max. send size that ndis indicated to us for the line
  18. //
  19. #define HDR_LEN_802_3 14
  20. #define ASYNC_MEDIUM_HDR_LEN HDR_LEN_802_3
  21. typedef struct _GET_PKT_SIZE {
  22. ULONG Unknown;
  23. ULONG MaxDatagramSize;
  24. } GET_PKT_SIZE, *PGET_PKT_SIZE;
  25. //
  26. // These structures are used to set and query information
  27. // about our source routing table.
  28. //
  29. typedef struct _SR_GET_PARAMETERS {
  30. ULONG BoardNumber; // 0-based
  31. ULONG SrDefault; // 0 = single route, 1 = all routes
  32. ULONG SrBroadcast;
  33. ULONG SrMulticast;
  34. } SR_GET_PARAMETERS, *PSR_GET_PARAMETERS;
  35. typedef struct _SR_SET_PARAMETER {
  36. ULONG BoardNumber; // 0-based
  37. ULONG Parameter; // 0 = single route, 1 = all routes
  38. } SR_SET_PARAMETER, *PSR_SET_PARAMETER;
  39. typedef struct _SR_SET_REMOVE {
  40. ULONG BoardNumber; // 0-based
  41. UCHAR MacAddress[6]; // remote to drop routing for
  42. } SR_SET_REMOVE, *PSR_SET_REMOVE;
  43. typedef struct _SR_SET_CLEAR {
  44. ULONG BoardNumber; // 0-based
  45. } SR_SET_CLEAR, *PSR_SET_CLEAR;
  46. #include <packoff.h>
  47. NTSTATUS
  48. IpxTdiAction(
  49. IN PDEVICE Device,
  50. IN PREQUEST Request
  51. )
  52. /*++
  53. Routine Description:
  54. This routine performs the TdiAction request for the transport
  55. provider.
  56. Arguments:
  57. Device - The device for the operation.
  58. Request - Describes the action request.
  59. Return Value:
  60. NTSTATUS - status of operation.
  61. --*/
  62. {
  63. NTSTATUS Status;
  64. PADDRESS_FILE AddressFile;
  65. UINT BufferLength;
  66. UINT DataLength;
  67. PNDIS_BUFFER NdisBuffer;
  68. CTELockHandle LockHandle;
  69. PBINDING Binding, MasterBinding;
  70. PADAPTER Adapter;
  71. union {
  72. PISN_ACTION_GET_LOCAL_TARGET GetLocalTarget;
  73. PISN_ACTION_GET_NETWORK_INFO GetNetworkInfo;
  74. PISN_ACTION_GET_DETAILS GetDetails;
  75. PSR_GET_PARAMETERS GetSrParameters;
  76. PSR_SET_PARAMETER SetSrParameter;
  77. PSR_SET_REMOVE SetSrRemove;
  78. PSR_SET_CLEAR SetSrClear;
  79. PIPX_ADDRESS_DATA IpxAddressData;
  80. PGET_PKT_SIZE GetPktSize;
  81. PIPX_NETNUM_DATA IpxNetnumData;
  82. PIPX_QUERY_WAN_INACTIVITY QueryWanInactivity;
  83. PIPXWAN_CONFIG_DONE IpxwanConfigDone;
  84. } u; // Make these unaligned??
  85. PIPX_ROUTE_ENTRY RouteEntry;
  86. PNWLINK_ACTION NwlinkAction;
  87. ULONG Segment;
  88. ULONG AdapterNum;
  89. static UCHAR BogusId[4] = { 0x01, 0x00, 0x00, 0x00 }; // old nwrdr uses this
  90. IPX_FIND_ROUTE_REQUEST routeEntry;
  91. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  92. //
  93. // To maintain some compatibility with the NWLINK streams-
  94. // based transport, we use the streams header format for
  95. // our actions. The old transport expected the action header
  96. // to be in InputBuffer and the output to go in OutputBuffer.
  97. // We follow the TDI spec, which states that OutputBuffer
  98. // is used for both input and output. Since IOCTL_TDI_ACTION
  99. // is method out direct, this means that the output buffer
  100. // is mapped by the MDL chain; for action the chain will
  101. // only have one piece so we use it for input and output.
  102. //
  103. NdisBuffer = REQUEST_NDIS_BUFFER(Request);
  104. if (NdisBuffer == NULL) {
  105. return STATUS_INVALID_PARAMETER;
  106. }
  107. NdisQueryBufferSafe (REQUEST_NDIS_BUFFER(Request), (PVOID *)&NwlinkAction, &BufferLength, NormalPagePriority);
  108. if (NwlinkAction == NULL) {
  109. return STATUS_INSUFFICIENT_RESOURCES;
  110. }
  111. //
  112. // Make sure we have enough room for just the header not
  113. // including the data.
  114. //
  115. if (BufferLength < (UINT)(FIELD_OFFSET(NWLINK_ACTION, Data[0]))) {
  116. IPX_DEBUG (ACTION, ("Nwlink action failed, buffer too small\n"));
  117. return STATUS_BUFFER_TOO_SMALL;
  118. }
  119. if ((!RtlEqualMemory ((PVOID) (UNALIGNED ULONG *) (&NwlinkAction->Header.TransportId), "MISN", 4)) &&
  120. (!RtlEqualMemory ((PVOID) (UNALIGNED ULONG *) (&NwlinkAction->Header.TransportId), "MIPX", 4)) &&
  121. (!RtlEqualMemory ((PVOID) (UNALIGNED ULONG *) (&NwlinkAction->Header.TransportId), "XPIM", 4)) &&
  122. (!RtlEqualMemory ((PVOID) (UNALIGNED ULONG *) (&NwlinkAction->Header.TransportId), BogusId, 4))) {
  123. return STATUS_NOT_SUPPORTED;
  124. }
  125. DataLength = BufferLength - FIELD_OFFSET(NWLINK_ACTION, Data[0]);
  126. //
  127. // Make sure that the correct file object is being used.
  128. //
  129. if (NwlinkAction->OptionType == NWLINK_OPTION_ADDRESS) {
  130. if (REQUEST_OPEN_TYPE(Request) != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
  131. IPX_DEBUG (ACTION, ("Nwlink action failed, not address file\n"));
  132. return STATUS_INVALID_HANDLE;
  133. }
  134. AddressFile = (PADDRESS_FILE)REQUEST_OPEN_CONTEXT(Request);
  135. if ((AddressFile->Size != sizeof (ADDRESS_FILE)) ||
  136. (AddressFile->Type != IPX_ADDRESSFILE_SIGNATURE)) {
  137. IPX_DEBUG (ACTION, ("Nwlink action failed, bad address file\n"));
  138. return STATUS_INVALID_HANDLE;
  139. }
  140. } else if (NwlinkAction->OptionType != NWLINK_OPTION_CONTROL) {
  141. IPX_DEBUG (ACTION, ("Nwlink action failed, option type %d\n", NwlinkAction->OptionType));
  142. return STATUS_NOT_SUPPORTED;
  143. }
  144. //
  145. // Handle the requests based on the action code. For these
  146. // requests ActionHeader->ActionCode is 0, we use the
  147. // Option field in the streams header instead.
  148. //
  149. Status = STATUS_SUCCESS;
  150. switch (NwlinkAction->Option) {
  151. IPX_DEBUG (ACTION, ("NwlinkAction->Option is (%x)\n", NwlinkAction->Option));
  152. //DbgPrint("NwlinkAction->Option is (%x)\n", NwlinkAction->Option);
  153. //
  154. // This first group support the winsock helper dll.
  155. // In most cases the corresponding sockopt is shown in
  156. // the comment, as well as the contents of the Data
  157. // part of the action buffer.
  158. //
  159. case MIPX_SETSENDPTYPE:
  160. //
  161. // IPX_PTYPE: Data is a single byte packet type.
  162. //
  163. if (DataLength >= 1) {
  164. IPX_DEBUG (ACTION, ("%lx: MIPX_SETSENDPTYPE %x\n", AddressFile, NwlinkAction->Data[0]));
  165. AddressFile->DefaultPacketType = NwlinkAction->Data[0];
  166. } else {
  167. Status = STATUS_BUFFER_TOO_SMALL;
  168. }
  169. break;
  170. case MIPX_FILTERPTYPE:
  171. //
  172. // IPX_FILTERPTYPE: Data is a single byte to filter on.
  173. //
  174. if (DataLength >= 1) {
  175. IPX_DEBUG (ACTION, ("%lx: MIPX_FILTERPTYPE %x\n", AddressFile, NwlinkAction->Data[0]));
  176. AddressFile->FilteredType = NwlinkAction->Data[0];
  177. AddressFile->FilterOnPacketType = TRUE;
  178. AddressFile->SpecialReceiveProcessing = TRUE;
  179. } else {
  180. Status = STATUS_BUFFER_TOO_SMALL;
  181. }
  182. break;
  183. case MIPX_NOFILTERPTYPE:
  184. //
  185. // IPX_STOPFILTERPTYPE.
  186. //
  187. IPX_DEBUG (ACTION, ("%lx: MIPX_NOFILTERPTYPE\n", AddressFile));
  188. AddressFile->FilterOnPacketType = FALSE;
  189. AddressFile->SpecialReceiveProcessing = (BOOLEAN)
  190. (AddressFile->ExtendedAddressing || AddressFile->ReceiveFlagsAddressing ||
  191. AddressFile->ReceiveIpxHeader || AddressFile->IsSapSocket);
  192. break;
  193. case MIPX_SENDADDROPT:
  194. //
  195. // IPX_EXTENDED_ADDRESS (TRUE).
  196. //
  197. IPX_DEBUG (ACTION, ("%lx: MIPX_SENDADDROPT\n", AddressFile));
  198. AddressFile->ExtendedAddressing = TRUE;
  199. AddressFile->SpecialReceiveProcessing = TRUE;
  200. break;
  201. case MIPX_NOSENDADDROPT:
  202. //
  203. // IPX_EXTENDED_ADDRESS (FALSE).
  204. //
  205. IPX_DEBUG (ACTION, ("%lx: MIPX_NOSENDADDROPT\n", AddressFile));
  206. AddressFile->ExtendedAddressing = FALSE;
  207. AddressFile->SpecialReceiveProcessing = (BOOLEAN)
  208. (AddressFile->ReceiveFlagsAddressing || AddressFile->ReceiveIpxHeader ||
  209. AddressFile->FilterOnPacketType || AddressFile->IsSapSocket);
  210. break;
  211. #if 0
  212. case MIPX_SETNIC:
  213. //
  214. // IPX_NIC_ADDRESS TRUE
  215. //
  216. IPX_DEBUG (ACTION, ("%lx: MIPX_SETNIC\n", AddressFile));
  217. AddressFile->NicAddressing = TRUE;
  218. AddressFile->SpecialReceiveProcessing = TRUE;
  219. break;
  220. case MIPX_NOSETNIC:
  221. //
  222. // IPX_NIC_ADDRESS (FALSE).
  223. //
  224. IPX_DEBUG (ACTION, ("%lx: MIPX_NOSETNIC\n", AddressFile));
  225. AddressFile->NicAddressing = FALSE;
  226. AddressFile->SpecialReceiveProcessing = (BOOLEAN)
  227. (AddressFile->ReceiveFlagsAddressing ||
  228. AddressFile->ReceiveIpxHeader ||
  229. AddressFile->FilterOnPacketType || AddressFile->IsSapSocket ||
  230. AddressFile->NicAddressing);
  231. break;
  232. #endif
  233. case MIPX_SETRCVFLAGS:
  234. //
  235. // No sockopt yet.
  236. //
  237. IPX_DEBUG (ACTION, ("%lx: MIPX_SETRCVFLAGS\n", AddressFile));
  238. AddressFile->ReceiveFlagsAddressing = TRUE;
  239. AddressFile->SpecialReceiveProcessing = TRUE;
  240. break;
  241. case MIPX_NORCVFLAGS:
  242. //
  243. // No sockopt yet.
  244. //
  245. IPX_DEBUG (ACTION, ("%lx: MIPX_NORCVFLAGS\n", AddressFile));
  246. AddressFile->ReceiveFlagsAddressing = FALSE;
  247. AddressFile->SpecialReceiveProcessing = (BOOLEAN)
  248. (AddressFile->ExtendedAddressing || AddressFile->ReceiveIpxHeader ||
  249. AddressFile->FilterOnPacketType || AddressFile->IsSapSocket);
  250. break;
  251. case MIPX_SENDHEADER:
  252. //
  253. // IPX_RECVHDR (TRUE);
  254. //
  255. IPX_DEBUG (ACTION, ("%lx: MIPX_SENDHEADER\n", AddressFile));
  256. AddressFile->ReceiveIpxHeader = TRUE;
  257. AddressFile->SpecialReceiveProcessing = TRUE;
  258. break;
  259. case MIPX_NOSENDHEADER:
  260. //
  261. // IPX_RECVHDR (FALSE);
  262. //
  263. IPX_DEBUG (ACTION, ("%lx: MIPX_NOSENDHEADER\n", AddressFile));
  264. AddressFile->ReceiveIpxHeader = FALSE;
  265. AddressFile->SpecialReceiveProcessing = (BOOLEAN)
  266. (AddressFile->ExtendedAddressing || AddressFile->ReceiveFlagsAddressing ||
  267. AddressFile->FilterOnPacketType || AddressFile->IsSapSocket);
  268. break;
  269. case MIPX_RCVBCAST:
  270. //
  271. // Broadcast reception enabled.
  272. //
  273. IPX_DEBUG (ACTION, ("%lx: MIPX_RCVBCAST\n", AddressFile));
  274. //
  275. // It's enabled by default now
  276. //
  277. /*
  278. CTEGetLock (&Device->Lock, &LockHandle);
  279. if (!AddressFile->EnableBroadcast) {
  280. AddressFile->EnableBroadcast = TRUE;
  281. IpxAddBroadcast (Device);
  282. }
  283. CTEFreeLock (&Device->Lock, LockHandle);
  284. */
  285. break;
  286. case MIPX_NORCVBCAST:
  287. //
  288. // Broadcast reception disabled.
  289. //
  290. IPX_DEBUG (ACTION, ("%lx: MIPX_NORCVBCAST\n", AddressFile));
  291. //
  292. // It's enabled by default now
  293. //
  294. /*
  295. CTEGetLock (&Device->Lock, &LockHandle);
  296. if (AddressFile->EnableBroadcast) {
  297. AddressFile->EnableBroadcast = FALSE;
  298. IpxRemoveBroadcast (Device);
  299. }
  300. CTEFreeLock (&Device->Lock, LockHandle);
  301. */
  302. break;
  303. case MIPX_GETPKTSIZE:
  304. //
  305. // IPX_MAXSIZE.
  306. //
  307. // Figure out what the first length is for.
  308. //
  309. IPX_DEBUG (ACTION, ("%lx: MIPX_GETPKTSIZE\n", AddressFile));
  310. if (DataLength >= sizeof(GET_PKT_SIZE)) {
  311. u.GetPktSize = (PGET_PKT_SIZE)(NwlinkAction->Data);
  312. u.GetPktSize->Unknown = 0;
  313. u.GetPktSize->MaxDatagramSize = Device->Information.MaxDatagramSize;
  314. } else {
  315. Status = STATUS_BUFFER_TOO_SMALL;
  316. }
  317. break;
  318. case MIPX_ADAPTERNUM:
  319. //
  320. // IPX_MAX_ADAPTER_NUM.
  321. //
  322. IPX_DEBUG (ACTION, ("%lx: MIPX_ADAPTERNUM\n", AddressFile));
  323. if (DataLength >= sizeof(ULONG)) {
  324. *(UNALIGNED ULONG *)(NwlinkAction->Data) = Device->SapNicCount;
  325. } else {
  326. Status = STATUS_BUFFER_TOO_SMALL;
  327. }
  328. break;
  329. case MIPX_ADAPTERNUM2:
  330. //
  331. // IPX_MAX_ADAPTER_NUM.
  332. //
  333. IPX_DEBUG (ACTION, ("%lx: MIPX_ADAPTERNUM2\n", AddressFile));
  334. if (DataLength >= sizeof(ULONG)) {
  335. *(UNALIGNED ULONG *)(NwlinkAction->Data) = MIN (Device->MaxBindings, Device->ValidBindings);
  336. } else {
  337. Status = STATUS_BUFFER_TOO_SMALL;
  338. }
  339. break;
  340. case MIPX_GETCARDINFO:
  341. case MIPX_GETCARDINFO2:
  342. //
  343. // GETCARDINFO is IPX_ADDRESS.
  344. //
  345. IPX_DEBUG (ACTION, ("%lx: MIPX_GETCARDINFO (%d)\n",
  346. AddressFile, *(UNALIGNED UINT *)NwlinkAction->Data));
  347. if (DataLength >= sizeof(IPX_ADDRESS_DATA)) {
  348. u.IpxAddressData = (PIPX_ADDRESS_DATA)(NwlinkAction->Data);
  349. AdapterNum = u.IpxAddressData->adapternum+1;
  350. if (((AdapterNum >= 1) && (AdapterNum <= Device->SapNicCount)) ||
  351. ((NwlinkAction->Option == MIPX_GETCARDINFO2) && (AdapterNum <= (ULONG) MIN (Device->MaxBindings, Device->ValidBindings)))) {
  352. // Get lock
  353. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  354. Binding = NIC_ID_TO_BINDING(Device, AdapterNum);
  355. if (Binding == NULL) {
  356. //
  357. // This should be a binding in the WAN range
  358. // of an adapter which is currently not
  359. // allocated. We scan back to the previous
  360. // non-NULL binding, which should be on the
  361. // same adapter, and return a down line with
  362. // the same characteristics as that binding.
  363. //
  364. UINT i = AdapterNum;
  365. do {
  366. --i;
  367. Binding = NIC_ID_TO_BINDING(Device, i);
  368. } while (Binding == NULL);
  369. //CTEAssert (Binding->Adapter->MacInfo.MediumAsync);
  370. //CTEAssert (i >= Binding->Adapter->FirstWanNicId);
  371. //CTEAssert (AdapterNum <= Binding->Adapter->LastWanNicId);
  372. // take out assertion because srv might have gotten the number
  373. // of adapters before we finished bindadapters.
  374. u.IpxAddressData->status = FALSE;
  375. *(UNALIGNED ULONG *)u.IpxAddressData->netnum = Binding->LocalAddress.NetworkAddress;
  376. } else {
  377. if ((Binding->Adapter->MacInfo.MediumAsync) &&
  378. (Device->WanGlobalNetworkNumber)) {
  379. //
  380. // In this case we make it look like one big wan
  381. // net, so the line is "up" or "down" depending
  382. // on whether we have given him the first indication
  383. // or not.
  384. //
  385. u.IpxAddressData->status = Device->GlobalNetworkIndicated;
  386. *(UNALIGNED ULONG *)u.IpxAddressData->netnum = Device->GlobalWanNetwork;
  387. } else {
  388. #ifdef SUNDOWN
  389. u.IpxAddressData->status = (unsigned char) Binding->LineUp;
  390. #else
  391. u.IpxAddressData->status = Binding->LineUp;
  392. #endif
  393. *(UNALIGNED ULONG *)u.IpxAddressData->netnum = Binding->LocalAddress.NetworkAddress;
  394. }
  395. }
  396. RtlCopyMemory(u.IpxAddressData->nodenum, Binding->LocalAddress.NodeAddress, 6);
  397. Adapter = Binding->Adapter;
  398. u.IpxAddressData->wan = Adapter->MacInfo.MediumAsync;
  399. u.IpxAddressData->maxpkt =
  400. (NwlinkAction->Option == MIPX_GETCARDINFO) ?
  401. Binding->AnnouncedMaxDatagramSize :
  402. Binding->RealMaxDatagramSize;
  403. u.IpxAddressData->linkspeed = Binding->MediumSpeed;
  404. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  405. } else {
  406. Status = STATUS_INVALID_PARAMETER;
  407. }
  408. } else {
  409. #if 1
  410. //
  411. // Support the old format query for now.
  412. //
  413. typedef struct _IPX_OLD_ADDRESS_DATA {
  414. UINT adapternum;
  415. UCHAR netnum[4];
  416. UCHAR nodenum[6];
  417. } IPX_OLD_ADDRESS_DATA, *PIPX_OLD_ADDRESS_DATA;
  418. if (DataLength >= sizeof(IPX_OLD_ADDRESS_DATA)) {
  419. u.IpxAddressData = (PIPX_ADDRESS_DATA)(NwlinkAction->Data);
  420. AdapterNum = u.IpxAddressData->adapternum+1;
  421. if ((AdapterNum >= 1) && (AdapterNum <= Device->SapNicCount)) {
  422. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  423. if (Binding = NIC_ID_TO_BINDING(Device, AdapterNum)) {
  424. *(UNALIGNED ULONG *)u.IpxAddressData->netnum = Binding->LocalAddress.NetworkAddress;
  425. RtlCopyMemory(u.IpxAddressData->nodenum, Binding->LocalAddress.NodeAddress, 6);
  426. } else {
  427. Status = STATUS_INVALID_PARAMETER;
  428. }
  429. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  430. } else {
  431. Status = STATUS_INVALID_PARAMETER;
  432. }
  433. } else {
  434. Status = STATUS_BUFFER_TOO_SMALL;
  435. }
  436. #else
  437. Status = STATUS_BUFFER_TOO_SMALL;
  438. #endif
  439. }
  440. break;
  441. case MIPX_NOTIFYCARDINFO:
  442. //
  443. // IPX_ADDRESS_NOTIFY.
  444. //
  445. IPX_DEBUG (ACTION, ("%lx: MIPX_NOTIFYCARDINFO (%lx)\n", AddressFile, Request));
  446. CTEGetLock (&Device->Lock, &LockHandle);
  447. //
  448. // If the device is open and there is room in the
  449. // buffer for the data, insert it in our queue.
  450. // It will be completed when a change happens or
  451. // the driver is unloaded.
  452. //
  453. if (Device->State == DEVICE_STATE_OPEN) {
  454. if (DataLength >= sizeof(IPX_ADDRESS_DATA)) {
  455. InsertTailList(
  456. &Device->AddressNotifyQueue,
  457. REQUEST_LINKAGE(Request)
  458. );
  459. IoSetCancelRoutine (Request, IpxCancelAction);
  460. // If IO Manager calls the cancel routine, then it will
  461. // set the cancel routine to be NULL.
  462. // IoSetCancelRoutine returns the previous cancel
  463. // routine, if the return value is null, then IO Manager
  464. // has called the cancel routine. If not null, then
  465. // the cancel routine has not been called and the irp
  466. // was canceled before we set the cancel routine.
  467. if (Request->Cancel &&
  468. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL) != NULL) {
  469. (VOID)RemoveTailList (&Device->AddressNotifyQueue);
  470. Status = STATUS_CANCELLED;
  471. } else {
  472. IpxReferenceDevice (Device, DREF_ADDRESS_NOTIFY);
  473. Status = STATUS_PENDING;
  474. }
  475. } else {
  476. Status = STATUS_BUFFER_TOO_SMALL;
  477. }
  478. } else {
  479. Status = STATUS_DEVICE_NOT_READY;
  480. }
  481. CTEFreeLock (&Device->Lock, LockHandle);
  482. break;
  483. case MIPX_LINECHANGE:
  484. //
  485. // IPX_ADDRESS_NOTIFY.
  486. //
  487. IPX_DEBUG (ACTION, ("MIPX_LINECHANGE (%lx)\n", Request));
  488. CTEGetLock (&Device->Lock, &LockHandle);
  489. //
  490. // If the device is open and there is room in the
  491. // buffer for the data, insert it in our queue.
  492. // It will be completed when a change happens or
  493. // the driver is unloaded.
  494. //
  495. if (Device->State == DEVICE_STATE_OPEN) {
  496. InsertTailList(
  497. &Device->LineChangeQueue,
  498. REQUEST_LINKAGE(Request)
  499. );
  500. IoSetCancelRoutine (Request, IpxCancelAction);
  501. if (Request->Cancel &&
  502. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL) != NULL) {
  503. (VOID)RemoveTailList (&Device->LineChangeQueue);
  504. Status = STATUS_CANCELLED;
  505. } else {
  506. IpxReferenceDevice (Device, DREF_LINE_CHANGE);
  507. Status = STATUS_PENDING;
  508. }
  509. } else {
  510. Status = STATUS_DEVICE_NOT_READY;
  511. }
  512. CTEFreeLock (&Device->Lock, LockHandle);
  513. break;
  514. case MIPX_GETNETINFO_NR:
  515. //
  516. // A request for network information about the immediate
  517. // route to a network (this is called by sockets apps).
  518. //
  519. if (DataLength < sizeof(IPX_NETNUM_DATA)) {
  520. return STATUS_BUFFER_TOO_SMALL;
  521. }
  522. u.IpxNetnumData = (PIPX_NETNUM_DATA)(NwlinkAction->Data);
  523. //
  524. // A query on network 0 means that the caller wants
  525. // information about our directly attached net.
  526. //
  527. if (*(UNALIGNED ULONG *)u.IpxNetnumData->netnum == 0) {
  528. //
  529. // The tick count is the number of 1/18.21 second ticks
  530. // it takes to deliver a 576-byte packet. Our link speed
  531. // is in 100 bit-per-second units. We calculate it as
  532. // follows (LS is the LinkSpeed):
  533. //
  534. // 576 bytes 8 bits 1 second 1821 ticks
  535. // * ------ * ------------- * ----------
  536. // 1 byte LS * 100 bits 100 seconds
  537. //
  538. // which becomes 839 / LinkSpeed -- we add LinkSpeed
  539. // to the top to round up.
  540. //
  541. if (Device->LinkSpeed == 0) {
  542. u.IpxNetnumData->netdelay = 16;
  543. } else {
  544. u.IpxNetnumData->netdelay = (USHORT)((839 + Device->LinkSpeed) /
  545. (Device->LinkSpeed));
  546. }
  547. u.IpxNetnumData->hopcount = 0;
  548. u.IpxNetnumData->cardnum = 0;
  549. RtlMoveMemory (u.IpxNetnumData->router, Device->SourceAddress.NodeAddress, 6);
  550. } else {
  551. if (Device->ForwarderBound) {
  552. //
  553. // [FW] Call the Forwarder's FindRoute if installed
  554. //
  555. //
  556. // What about the node number here?
  557. //
  558. Status = (*Device->UpperDrivers[IDENTIFIER_RIP].FindRouteHandler) (
  559. u.IpxNetnumData->netnum,
  560. NULL, // FindRouteRequest->Node,
  561. &routeEntry);
  562. if (Status != STATUS_SUCCESS) {
  563. IPX_DEBUG (ACTION, (" MIPX_GETNETINFO_NR failed net %lx",
  564. REORDER_ULONG(*(UNALIGNED ULONG *)(u.IpxNetnumData->netnum))));
  565. Status = STATUS_BAD_NETWORK_PATH;
  566. } else {
  567. //
  568. // Fill in the information
  569. //
  570. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  571. if (Binding = NIC_ID_TO_BINDING(Device, routeEntry.LocalTarget.NicId)) {
  572. u.IpxNetnumData->hopcount = routeEntry.HopCount;
  573. u.IpxNetnumData->netdelay = routeEntry.TickCount;
  574. if (Binding->BindingSetMember) {
  575. u.IpxNetnumData->cardnum = (INT)(Binding->MasterBinding->NicId - 1);
  576. } else {
  577. u.IpxNetnumData->cardnum = (INT)(routeEntry.LocalTarget.NicId - 1);
  578. }
  579. // RtlMoveMemory (u.IpxNetnumData->router, routeEntry.LocalTarget.MacAddress, 6);
  580. *((UNALIGNED ULONG *)u.IpxNetnumData->router) =
  581. *((UNALIGNED ULONG *)routeEntry.LocalTarget.MacAddress);
  582. *((UNALIGNED ULONG *)(u.IpxNetnumData->router+4)) =
  583. *((UNALIGNED ULONG *)(routeEntry.LocalTarget.MacAddress+4));
  584. }
  585. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  586. }
  587. } else {
  588. Segment = RipGetSegment(u.IpxNetnumData->netnum);
  589. //
  590. // To maintain the lock order: BindAccessLock > RIP table
  591. //
  592. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  593. CTEGetLock (&Device->SegmentLocks[Segment], &LockHandle);
  594. //
  595. // See which net card this is routed on.
  596. //
  597. RouteEntry = RipGetRoute (Segment, u.IpxNetnumData->netnum);
  598. if ((RouteEntry != NULL) &&
  599. (Binding = NIC_ID_TO_BINDING(Device, RouteEntry->NicId))) {
  600. u.IpxNetnumData->hopcount = RouteEntry->HopCount;
  601. u.IpxNetnumData->netdelay = RouteEntry->TickCount;
  602. if (Binding->BindingSetMember) {
  603. u.IpxNetnumData->cardnum = (INT)(MIN (Device->MaxBindings, Binding->MasterBinding->NicId) - 1);
  604. } else {
  605. u.IpxNetnumData->cardnum = (INT)(RouteEntry->NicId - 1);
  606. }
  607. RtlMoveMemory (u.IpxNetnumData->router, RouteEntry->NextRouter, 6);
  608. } else {
  609. //
  610. // Fail the call, we don't have a route yet.
  611. //
  612. IPX_DEBUG (ACTION, ("MIPX_GETNETINFO_NR failed net %lx\n",
  613. REORDER_ULONG(*(UNALIGNED ULONG *)(u.IpxNetnumData->netnum))));
  614. Status = STATUS_BAD_NETWORK_PATH;
  615. }
  616. CTEFreeLock (&Device->SegmentLocks[Segment], LockHandle);
  617. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  618. }
  619. }
  620. break;
  621. case MIPX_RERIPNETNUM:
  622. //
  623. // We dont really support Re-RIP in the case of Forwarder above us
  624. //
  625. //
  626. // A request for network information about the immediate
  627. // route to a network (this is called by sockets apps).
  628. //
  629. if (DataLength < sizeof(IPX_NETNUM_DATA)) {
  630. return STATUS_BUFFER_TOO_SMALL;
  631. }
  632. u.IpxNetnumData = (PIPX_NETNUM_DATA)(NwlinkAction->Data);
  633. //
  634. // Allow net 0 queries??
  635. //
  636. if (*(UNALIGNED ULONG *)u.IpxNetnumData->netnum == 0) {
  637. if (Device->LinkSpeed == 0) {
  638. u.IpxNetnumData->netdelay = 16;
  639. } else {
  640. u.IpxNetnumData->netdelay = (USHORT)((839 + Device->LinkSpeed) /
  641. (Device->LinkSpeed));
  642. }
  643. u.IpxNetnumData->hopcount = 0;
  644. u.IpxNetnumData->cardnum = 0;
  645. RtlMoveMemory (u.IpxNetnumData->router, Device->SourceAddress.NodeAddress, 6);
  646. } else {
  647. if (Device->ForwarderBound) {
  648. //
  649. // [FW] Call the Forwarder's FindRoute if installed
  650. //
  651. //
  652. // What about the node number here?
  653. //
  654. Status = (*Device->UpperDrivers[IDENTIFIER_RIP].FindRouteHandler) (
  655. u.IpxNetnumData->netnum,
  656. NULL, // FindRouteRequest->Node,
  657. &routeEntry);
  658. if (Status != STATUS_SUCCESS) {
  659. IPX_DEBUG (ACTION, (" MIPX_RERIPNETNUM failed net %lx",
  660. REORDER_ULONG(*(UNALIGNED ULONG *)(u.IpxNetnumData->netnum))));
  661. Status = STATUS_BAD_NETWORK_PATH;
  662. } else {
  663. //
  664. // Fill in the information
  665. //
  666. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  667. if (Binding = NIC_ID_TO_BINDING(Device, routeEntry.LocalTarget.NicId)) {
  668. u.IpxNetnumData->hopcount = routeEntry.HopCount;
  669. u.IpxNetnumData->netdelay = routeEntry.TickCount;
  670. if (Binding->BindingSetMember) {
  671. u.IpxNetnumData->cardnum = (INT)(Binding->MasterBinding->NicId - 1);
  672. } else {
  673. u.IpxNetnumData->cardnum = (INT)(routeEntry.LocalTarget.NicId - 1);
  674. }
  675. // RtlMoveMemory (u.IpxNetnumData->router, routeEntry.LocalTarget.MacAddress, 6);
  676. *((UNALIGNED ULONG *)u.IpxNetnumData->router) =
  677. *((UNALIGNED ULONG *)routeEntry.LocalTarget.MacAddress);
  678. *((UNALIGNED ULONG *)(u.IpxNetnumData->router+4)) =
  679. *((UNALIGNED ULONG *)(routeEntry.LocalTarget.MacAddress+4));
  680. }
  681. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  682. }
  683. } else {
  684. Segment = RipGetSegment(u.IpxNetnumData->netnum);
  685. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  686. CTEGetLock (&Device->SegmentLocks[Segment], &LockHandle);
  687. //
  688. // See which net card this is routed on.
  689. //
  690. RouteEntry = RipGetRoute (Segment, u.IpxNetnumData->netnum);
  691. if ((RouteEntry != NULL) &&
  692. (Binding = NIC_ID_TO_BINDING(Device, RouteEntry->NicId)) &&
  693. (RouteEntry->Flags & IPX_ROUTER_PERMANENT_ENTRY)) {
  694. u.IpxNetnumData->hopcount = RouteEntry->HopCount;
  695. u.IpxNetnumData->netdelay = RouteEntry->TickCount;
  696. if (Binding->BindingSetMember) {
  697. u.IpxNetnumData->cardnum = (INT)(MIN (Device->MaxBindings, Binding->MasterBinding->NicId) - 1);
  698. } else {
  699. u.IpxNetnumData->cardnum = (INT)(RouteEntry->NicId - 1);
  700. }
  701. RtlMoveMemory (u.IpxNetnumData->router, RouteEntry->NextRouter, 6);
  702. } else {
  703. //
  704. // This call will return STATUS_PENDING if we successfully
  705. // queue a RIP request for the packet.
  706. //
  707. Status = RipQueueRequest (*(UNALIGNED ULONG *)u.IpxNetnumData->netnum, RIP_REQUEST);
  708. CTEAssert (Status != STATUS_SUCCESS);
  709. if (Status == STATUS_PENDING) {
  710. //
  711. // A RIP request went out on the network; we queue
  712. // this request for completion when the RIP response
  713. // arrives. We save the network in the information
  714. // field for easier retrieval later.
  715. //
  716. #ifdef SUNDOWN
  717. REQUEST_INFORMATION(Request) = (ULONG_PTR)u.IpxNetnumData;
  718. #else
  719. REQUEST_INFORMATION(Request) = (ULONG)u.IpxNetnumData;
  720. #endif
  721. InsertTailList(
  722. &Device->Segments[Segment].WaitingReripNetnum,
  723. REQUEST_LINKAGE(Request));
  724. IPX_DEBUG (ACTION, ("MIPX_RERIPNETNUM queued net %lx\n",
  725. REORDER_ULONG(*(UNALIGNED ULONG *)(u.IpxNetnumData->netnum))));
  726. }
  727. }
  728. CTEFreeLock (&Device->SegmentLocks[Segment], LockHandle);
  729. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  730. }
  731. }
  732. break;
  733. case MIPX_GETNETINFO:
  734. //
  735. // A request for network information about the immediate
  736. // route to a network (this is called by sockets apps).
  737. //
  738. if (DataLength < sizeof(IPX_NETNUM_DATA)) {
  739. return STATUS_BUFFER_TOO_SMALL;
  740. }
  741. u.IpxNetnumData = (PIPX_NETNUM_DATA)(NwlinkAction->Data);
  742. //
  743. // Allow net 0 queries??
  744. //
  745. if (*(UNALIGNED ULONG *)u.IpxNetnumData->netnum == 0) {
  746. if (Device->LinkSpeed == 0) {
  747. u.IpxNetnumData->netdelay = 16;
  748. } else {
  749. u.IpxNetnumData->netdelay = (USHORT)((839 + Device->LinkSpeed) /
  750. (Device->LinkSpeed));
  751. }
  752. u.IpxNetnumData->hopcount = 0;
  753. u.IpxNetnumData->cardnum = 0;
  754. RtlMoveMemory (u.IpxNetnumData->router, Device->SourceAddress.NodeAddress, 6);
  755. } else {
  756. if (Device->ForwarderBound) {
  757. //
  758. // [FW] Call the Forwarder's FindRoute if installed
  759. //
  760. //
  761. // What about the node number here?
  762. //
  763. Status = (*Device->UpperDrivers[IDENTIFIER_RIP].FindRouteHandler) (
  764. u.IpxNetnumData->netnum,
  765. NULL, // FindRouteRequest->Node,
  766. &routeEntry);
  767. if (Status != STATUS_SUCCESS) {
  768. IPX_DEBUG (ACTION, (" MIPX_GETNETINFO failed net %lx",
  769. REORDER_ULONG(*(UNALIGNED ULONG *)(u.IpxNetnumData->netnum))));
  770. Status = STATUS_BAD_NETWORK_PATH;
  771. } else {
  772. //
  773. // Fill in the information
  774. //
  775. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  776. if (Binding = NIC_ID_TO_BINDING(Device, routeEntry.LocalTarget.NicId)) {
  777. u.IpxNetnumData->hopcount = routeEntry.HopCount;
  778. u.IpxNetnumData->netdelay = routeEntry.TickCount;
  779. if (Binding->BindingSetMember) {
  780. u.IpxNetnumData->cardnum = (INT)(Binding->MasterBinding->NicId - 1);
  781. } else {
  782. u.IpxNetnumData->cardnum = (INT)(routeEntry.LocalTarget.NicId - 1);
  783. }
  784. // RtlMoveMemory (u.IpxNetnumData->router, routeEntry.LocalTarget.MacAddress, 6);
  785. *((UNALIGNED ULONG *)u.IpxNetnumData->router) =
  786. *((UNALIGNED ULONG *)routeEntry.LocalTarget.MacAddress);
  787. *((UNALIGNED ULONG *)(u.IpxNetnumData->router+4)) =
  788. *((UNALIGNED ULONG *)(routeEntry.LocalTarget.MacAddress+4));
  789. }
  790. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  791. }
  792. } else {
  793. Segment = RipGetSegment(u.IpxNetnumData->netnum);
  794. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  795. CTEGetLock (&Device->SegmentLocks[Segment], &LockHandle);
  796. //
  797. // See which net card this is routed on.
  798. //
  799. RouteEntry = RipGetRoute (Segment, u.IpxNetnumData->netnum);
  800. if ((RouteEntry != NULL) &&
  801. (Binding = NIC_ID_TO_BINDING(Device, RouteEntry->NicId))) {
  802. u.IpxNetnumData->hopcount = RouteEntry->HopCount;
  803. u.IpxNetnumData->netdelay = RouteEntry->TickCount;
  804. if (Binding->BindingSetMember) {
  805. u.IpxNetnumData->cardnum = (INT)(MIN (Device->MaxBindings, Binding->MasterBinding->NicId) - 1);
  806. } else {
  807. u.IpxNetnumData->cardnum = (INT)(RouteEntry->NicId - 1);
  808. }
  809. RtlMoveMemory (u.IpxNetnumData->router, RouteEntry->NextRouter, 6);
  810. } else {
  811. //
  812. // This call will return STATUS_PENDING if we successfully
  813. // queue a RIP request for the packet.
  814. //
  815. Status = RipQueueRequest (*(UNALIGNED ULONG *)u.IpxNetnumData->netnum, RIP_REQUEST);
  816. CTEAssert (Status != STATUS_SUCCESS);
  817. if (Status == STATUS_PENDING) {
  818. //
  819. // A RIP request went out on the network; we queue
  820. // this request for completion when the RIP response
  821. // arrives. We save the network in the information
  822. // field for easier retrieval later.
  823. //
  824. #ifdef SUNDOWN
  825. REQUEST_INFORMATION(Request) = (ULONG_PTR)u.IpxNetnumData;
  826. #else
  827. REQUEST_INFORMATION(Request) = (ULONG)u.IpxNetnumData;
  828. #endif
  829. InsertTailList(
  830. &Device->Segments[Segment].WaitingReripNetnum,
  831. REQUEST_LINKAGE(Request));
  832. IPX_DEBUG (ACTION, ("MIPX_GETNETINFO queued net %lx\n",
  833. REORDER_ULONG(*(UNALIGNED ULONG *)(u.IpxNetnumData->netnum))));
  834. }
  835. }
  836. CTEFreeLock (&Device->SegmentLocks[Segment], LockHandle);
  837. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  838. }
  839. }
  840. break;
  841. case MIPX_SENDPTYPE:
  842. case MIPX_NOSENDPTYPE:
  843. //
  844. // For the moment just use OptionsLength >= 1 to indicate
  845. // that the send options include the packet type.
  846. //
  847. // Do we need to worry about card num being there?
  848. //
  849. #if 0
  850. IPX_DEBUG (ACTION, ("%lx: MIPS_%sSENDPTYPE\n", AddressFile,
  851. NwlinkAction->Option == MIPX_SENDPTYPE ? "" : "NO"));
  852. #endif
  853. break;
  854. case MIPX_ZEROSOCKET:
  855. //
  856. // Sends from this address should be from socket 0;
  857. // This is done the simple way by just putting the
  858. // information in the address itself, instead of
  859. // making it per address file (this is OK since
  860. // this call is not exposed through winsock).
  861. //
  862. IPX_DEBUG (ACTION, ("%lx: MIPX_ZEROSOCKET\n", AddressFile));
  863. AddressFile->Address->SendSourceSocket = 0;
  864. AddressFile->Address->LocalAddress.Socket = 0;
  865. break;
  866. //
  867. // This next batch are the source routing options. They
  868. // are submitted by the IPXROUTE program.
  869. //
  870. // Do we expose all binding set members to this?
  871. case MIPX_SRGETPARMS:
  872. if (DataLength >= sizeof(SR_GET_PARAMETERS)) {
  873. u.GetSrParameters = (PSR_GET_PARAMETERS)(NwlinkAction->Data);
  874. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  875. if (Binding = NIC_ID_TO_BINDING(Device, u.GetSrParameters->BoardNumber+1)) {
  876. IPX_DEBUG (ACTION, ("MIPX_SRGETPARMS (%d)\n", u.GetSrParameters->BoardNumber+1));
  877. u.GetSrParameters->SrDefault = (Binding->AllRouteDirected) ? 1 : 0;
  878. u.GetSrParameters->SrBroadcast = (Binding->AllRouteBroadcast) ? 1 : 0;
  879. u.GetSrParameters->SrMulticast = (Binding->AllRouteMulticast) ? 1 : 0;
  880. } else {
  881. Status = STATUS_INVALID_PARAMETER;
  882. }
  883. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  884. } else {
  885. Status = STATUS_BUFFER_TOO_SMALL;
  886. }
  887. break;
  888. case MIPX_SRDEF:
  889. case MIPX_SRBCAST:
  890. case MIPX_SRMULTI:
  891. if (DataLength >= sizeof(SR_SET_PARAMETER)) {
  892. u.SetSrParameter = (PSR_SET_PARAMETER)(NwlinkAction->Data);
  893. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  894. if (Binding = NIC_ID_TO_BINDING(Device, u.SetSrParameter->BoardNumber+1)) {
  895. if (NwlinkAction->Option == MIPX_SRDEF) {
  896. //
  897. // The compiler generates strange
  898. // code which always makes this path be
  899. // taken????
  900. //
  901. IPX_DEBUG (ACTION, ("MIPX_SRDEF %d (%d)\n",
  902. u.SetSrParameter->Parameter, u.SetSrParameter->BoardNumber+1));
  903. Binding->AllRouteDirected = (BOOLEAN)u.SetSrParameter->Parameter;
  904. } else if (NwlinkAction->Option == MIPX_SRBCAST) {
  905. IPX_DEBUG (ACTION, ("MIPX_SRBCAST %d (%d)\n",
  906. u.SetSrParameter->Parameter, u.SetSrParameter->BoardNumber+1));
  907. Binding->AllRouteBroadcast = (BOOLEAN)u.SetSrParameter->Parameter;
  908. } else {
  909. IPX_DEBUG (ACTION, ("MIPX_SRMCAST %d (%d)\n",
  910. u.SetSrParameter->Parameter, u.SetSrParameter->BoardNumber+1));
  911. Binding->AllRouteMulticast = (BOOLEAN)u.SetSrParameter->Parameter;
  912. }
  913. } else {
  914. Status = STATUS_INVALID_PARAMETER;
  915. }
  916. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  917. } else {
  918. Status = STATUS_BUFFER_TOO_SMALL;
  919. }
  920. break;
  921. case MIPX_SRREMOVE:
  922. if (DataLength >= sizeof(SR_SET_REMOVE)) {
  923. u.SetSrRemove = (PSR_SET_REMOVE)(NwlinkAction->Data);
  924. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  925. if (Binding = NIC_ID_TO_BINDING(Device, u.SetSrRemove->BoardNumber+1)) {
  926. IPX_DEBUG (ACTION, ("MIPX_SRREMOVE %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x (%d)\n",
  927. u.SetSrRemove->MacAddress[0],
  928. u.SetSrRemove->MacAddress[1],
  929. u.SetSrRemove->MacAddress[2],
  930. u.SetSrRemove->MacAddress[3],
  931. u.SetSrRemove->MacAddress[4],
  932. u.SetSrRemove->MacAddress[5],
  933. u.SetSrRemove->BoardNumber+1));
  934. MacSourceRoutingRemove (Binding, u.SetSrRemove->MacAddress);
  935. } else {
  936. Status = STATUS_INVALID_PARAMETER;
  937. }
  938. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  939. } else {
  940. Status = STATUS_BUFFER_TOO_SMALL;
  941. }
  942. break;
  943. case MIPX_SRCLEAR:
  944. if (DataLength >= sizeof(SR_SET_CLEAR)) {
  945. u.SetSrClear = (PSR_SET_CLEAR)(NwlinkAction->Data);
  946. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  947. if (Binding = NIC_ID_TO_BINDING(Device, u.SetSrClear->BoardNumber+1)) {
  948. IPX_DEBUG (ACTION, ("MIPX_SRCLEAR (%d)\n", u.SetSrClear->BoardNumber+1));
  949. MacSourceRoutingClear (Binding);
  950. } else {
  951. Status = STATUS_INVALID_PARAMETER;
  952. }
  953. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  954. } else {
  955. Status = STATUS_BUFFER_TOO_SMALL;
  956. }
  957. break;
  958. //
  959. // These are new for ISN (not supported in NWLINK).
  960. //
  961. case MIPX_LOCALTARGET:
  962. //
  963. // A request for the local target for an IPX address.
  964. //
  965. if (DataLength < sizeof(ISN_ACTION_GET_LOCAL_TARGET)) {
  966. return STATUS_BUFFER_TOO_SMALL;
  967. }
  968. u.GetLocalTarget = (PISN_ACTION_GET_LOCAL_TARGET)(NwlinkAction->Data);
  969. if (Device->ForwarderBound) {
  970. //
  971. // [FW] Call the Forwarder's FindRoute if installed
  972. //
  973. //
  974. // What about the node number here?
  975. //
  976. Status = (*Device->UpperDrivers[IDENTIFIER_RIP].FindRouteHandler) (
  977. (PUCHAR)&u.GetLocalTarget->IpxAddress.NetworkAddress,
  978. NULL, // FindRouteRequest->Node,
  979. &routeEntry);
  980. if (Status != STATUS_SUCCESS) {
  981. IPX_DEBUG (ACTION, (" MIPX_LOCALTARGET failed net %lx",
  982. REORDER_ULONG(u.GetLocalTarget->IpxAddress.NetworkAddress)));
  983. Status = STATUS_BAD_NETWORK_PATH;
  984. } else {
  985. //
  986. // Fill in the information
  987. //
  988. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  989. //
  990. // What about check for IPX_ROUTER_LOCAL_NET
  991. //
  992. if (Binding = NIC_ID_TO_BINDING(Device, routeEntry.LocalTarget.NicId)) {
  993. if (Binding->BindingSetMember) {
  994. //
  995. // It's a binding set member, we round-robin the
  996. // responses across all the cards to distribute
  997. // the traffic.
  998. //
  999. MasterBinding = Binding->MasterBinding;
  1000. Binding = MasterBinding->CurrentSendBinding;
  1001. MasterBinding->CurrentSendBinding = Binding->NextBinding;
  1002. u.GetLocalTarget->LocalTarget.NicId = Binding->NicId;
  1003. } else {
  1004. u.GetLocalTarget->LocalTarget.NicId = routeEntry.LocalTarget.NicId;
  1005. }
  1006. *((UNALIGNED ULONG *)u.GetLocalTarget->LocalTarget.MacAddress) =
  1007. *((UNALIGNED ULONG *)routeEntry.LocalTarget.MacAddress);
  1008. *((UNALIGNED ULONG *)(u.GetLocalTarget->LocalTarget.MacAddress+4)) =
  1009. *((UNALIGNED ULONG *)(routeEntry.LocalTarget.MacAddress+4));
  1010. }
  1011. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1012. }
  1013. } else {
  1014. Segment = RipGetSegment((PUCHAR)&u.GetLocalTarget->IpxAddress.NetworkAddress);
  1015. CTEGetLock (&Device->SegmentLocks[Segment], &LockHandle);
  1016. //
  1017. // See if this route is local.
  1018. //
  1019. RouteEntry = RipGetRoute (Segment, (PUCHAR)&u.GetLocalTarget->IpxAddress.NetworkAddress);
  1020. if ((RouteEntry != NULL) &&
  1021. (RouteEntry->Flags & IPX_ROUTER_PERMANENT_ENTRY)) {
  1022. //
  1023. // This is a local net, to send to it you just use
  1024. // the appropriate NIC ID and the real MAC address.
  1025. //
  1026. if ((RouteEntry->Flags & IPX_ROUTER_LOCAL_NET) == 0) {
  1027. //
  1028. // It's the virtual net, send via the first card.
  1029. //
  1030. FILL_LOCAL_TARGET(&u.GetLocalTarget->LocalTarget, 1);
  1031. CTEFreeLock (&Device->SegmentLocks[Segment], LockHandle);
  1032. } else {
  1033. CTEFreeLock (&Device->SegmentLocks[Segment], LockHandle);
  1034. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  1035. Binding = NIC_ID_TO_BINDING(Device, RouteEntry->NicId);
  1036. if (Binding->BindingSetMember) {
  1037. //
  1038. // It's a binding set member, we round-robin the
  1039. // responses across all the cards to distribute
  1040. // the traffic.
  1041. //
  1042. MasterBinding = Binding->MasterBinding;
  1043. Binding = MasterBinding->CurrentSendBinding;
  1044. MasterBinding->CurrentSendBinding = Binding->NextBinding;
  1045. FILL_LOCAL_TARGET(&u.GetLocalTarget->LocalTarget, MIN( Device->MaxBindings, Binding->NicId));
  1046. } else {
  1047. FILL_LOCAL_TARGET(&u.GetLocalTarget->LocalTarget, RouteEntry->NicId);
  1048. }
  1049. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1050. }
  1051. RtlCopyMemory(
  1052. u.GetLocalTarget->LocalTarget.MacAddress,
  1053. u.GetLocalTarget->IpxAddress.NodeAddress,
  1054. 6);
  1055. } else {
  1056. //
  1057. // This call will return STATUS_PENDING if we successfully
  1058. // queue a RIP request for the packet.
  1059. //
  1060. Status = RipQueueRequest (u.GetLocalTarget->IpxAddress.NetworkAddress, RIP_REQUEST);
  1061. CTEAssert (Status != STATUS_SUCCESS);
  1062. if (Status == STATUS_PENDING) {
  1063. //
  1064. // A RIP request went out on the network; we queue
  1065. // this request for completion when the RIP response
  1066. // arrives. We save the network in the information
  1067. // field for easier retrieval later.
  1068. //
  1069. #ifdef SUNDOWN
  1070. REQUEST_INFORMATION(Request) = (ULONG_PTR)u.GetLocalTarget;
  1071. #else
  1072. REQUEST_INFORMATION(Request) = (ULONG)u.GetLocalTarget;
  1073. #endif
  1074. InsertTailList(
  1075. &Device->Segments[Segment].WaitingLocalTarget,
  1076. REQUEST_LINKAGE(Request));
  1077. }
  1078. CTEFreeLock (&Device->SegmentLocks[Segment], LockHandle);
  1079. }
  1080. }
  1081. break;
  1082. case MIPX_NETWORKINFO:
  1083. //
  1084. // A request for network information about the immediate
  1085. // route to a network.
  1086. //
  1087. if (DataLength < sizeof(ISN_ACTION_GET_NETWORK_INFO)) {
  1088. return STATUS_BUFFER_TOO_SMALL;
  1089. }
  1090. u.GetNetworkInfo = (PISN_ACTION_GET_NETWORK_INFO)(NwlinkAction->Data);
  1091. if (u.GetNetworkInfo->Network == 0) {
  1092. //
  1093. // This is information about the local card.
  1094. //
  1095. u.GetNetworkInfo->LinkSpeed = Device->LinkSpeed * 12;
  1096. u.GetNetworkInfo->MaximumPacketSize = Device->Information.MaxDatagramSize;
  1097. } else {
  1098. if (Device->ForwarderBound) {
  1099. //
  1100. // [FW] Call the Forwarder's FindRoute if installed
  1101. //
  1102. //
  1103. // What about the node number here?
  1104. //
  1105. Status = (*Device->UpperDrivers[IDENTIFIER_RIP].FindRouteHandler) (
  1106. (PUCHAR)&u.GetNetworkInfo->Network,
  1107. NULL, // FindRouteRequest->Node,
  1108. &routeEntry);
  1109. if (Status != STATUS_SUCCESS) {
  1110. IPX_DEBUG (ACTION, (" MIPX_GETNETINFO_NR failed net %lx",
  1111. REORDER_ULONG(u.GetNetworkInfo->Network)));
  1112. Status = STATUS_BAD_NETWORK_PATH;
  1113. } else {
  1114. //
  1115. // Fill in the information
  1116. //
  1117. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  1118. if (Binding = NIC_ID_TO_BINDING(Device, routeEntry.LocalTarget.NicId)) {
  1119. //
  1120. // Our medium speed is stored in 100 bps, we
  1121. // convert to bytes/sec by multiplying by 12
  1122. // (should really be 100/8 = 12.5).
  1123. //
  1124. u.GetNetworkInfo->LinkSpeed = Binding->MediumSpeed * 12;
  1125. u.GetNetworkInfo->MaximumPacketSize = Binding->AnnouncedMaxDatagramSize;
  1126. }
  1127. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1128. }
  1129. } else {
  1130. Segment = RipGetSegment((PUCHAR)&u.GetNetworkInfo->Network);
  1131. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  1132. CTEGetLock (&Device->SegmentLocks[Segment], &LockHandle);
  1133. //
  1134. // See which net card this is routed on.
  1135. //
  1136. RouteEntry = RipGetRoute (Segment, (PUCHAR)&u.GetNetworkInfo->Network);
  1137. if ((RouteEntry != NULL) &&
  1138. (Binding = NIC_ID_TO_BINDING(Device, RouteEntry->NicId))) {
  1139. //
  1140. // Our medium speed is stored in 100 bps, we
  1141. // convert to bytes/sec by multiplying by 12
  1142. // (should really be 100/8 = 12.5).
  1143. //
  1144. u.GetNetworkInfo->LinkSpeed = Binding->MediumSpeed * 12;
  1145. u.GetNetworkInfo->MaximumPacketSize = Binding->AnnouncedMaxDatagramSize;
  1146. } else {
  1147. //
  1148. // Fail the call, we don't have a route yet.
  1149. // This requires that a packet has been
  1150. // sent to this net already; nwrdr says this is
  1151. // OK, they will send their connect request
  1152. // before they query. On the server it should
  1153. // have RIP running so all nets should be in
  1154. // the database.
  1155. //
  1156. Status = STATUS_BAD_NETWORK_PATH;
  1157. }
  1158. CTEFreeLock (&Device->SegmentLocks[Segment], LockHandle);
  1159. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1160. }
  1161. }
  1162. break;
  1163. case MIPX_CONFIG:
  1164. //
  1165. // A request for details on every binding.
  1166. //
  1167. if (DataLength < sizeof(ISN_ACTION_GET_DETAILS)) {
  1168. IPX_DEBUG(ACTION, ("Not enought buffer %d < %d\n", DataLength,sizeof(ISN_ACTION_GET_DETAILS) ));
  1169. return STATUS_BUFFER_TOO_SMALL;
  1170. }
  1171. u.GetDetails = (PISN_ACTION_GET_DETAILS)(NwlinkAction->Data);
  1172. if (u.GetDetails->NicId == 0) {
  1173. //
  1174. // This is information about the local card. We also
  1175. // tell him the total number of bindings in NicId.
  1176. //
  1177. u.GetDetails->NetworkNumber = Device->VirtualNetworkNumber;
  1178. u.GetDetails->NicId = (USHORT)MIN (Device->MaxBindings, Device->ValidBindings);
  1179. } else {
  1180. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  1181. Binding = NIC_ID_TO_BINDING(Device, u.GetDetails->NicId);
  1182. if ((Binding != NULL) &&
  1183. (u.GetDetails->NicId <= MIN (Device->MaxBindings, Device->ValidBindings))) {
  1184. ULONG StringLoc;
  1185. IpxReferenceBinding1(Binding, BREF_DEVICE_ACCESS);
  1186. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1187. u.GetDetails->NetworkNumber = Binding->LocalAddress.NetworkAddress;
  1188. if (Binding->Adapter->MacInfo.MediumType == NdisMediumArcnet878_2) {
  1189. u.GetDetails->FrameType = ISN_FRAME_TYPE_ARCNET;
  1190. } else {
  1191. u.GetDetails->FrameType = Binding->FrameType;
  1192. }
  1193. u.GetDetails->BindingSet = Binding->BindingSetMember;
  1194. if (Binding->Adapter->MacInfo.MediumAsync) {
  1195. if (Binding->LineUp) {
  1196. u.GetDetails->Type = 2;
  1197. } else {
  1198. u.GetDetails->Type = 3;
  1199. }
  1200. } else {
  1201. u.GetDetails->Type = 1;
  1202. }
  1203. RtlCopyMemory (u.GetDetails->Node, Binding->LocalMacAddress.Address, 6);
  1204. //
  1205. // Copy the adapter name, including the final NULL.
  1206. //
  1207. StringLoc = (Binding->Adapter->AdapterNameLength / sizeof(WCHAR)) - 2;
  1208. while (Binding->Adapter->AdapterName[StringLoc] != L'\\') {
  1209. --StringLoc;
  1210. }
  1211. RtlCopyMemory(
  1212. u.GetDetails->AdapterName,
  1213. &Binding->Adapter->AdapterName[StringLoc+1],
  1214. Binding->Adapter->AdapterNameLength - ((StringLoc+1) * sizeof(WCHAR)));
  1215. IpxDereferenceBinding1(Binding, BREF_DEVICE_ACCESS);
  1216. } else {
  1217. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1218. IPX_DEBUG(ACTION, ("Bad nic id %d\n",u.GetDetails->NicId));
  1219. Status = STATUS_INVALID_PARAMETER;
  1220. }
  1221. }
  1222. break;
  1223. //
  1224. // Return new nic info to the requestor. Currently, no check for
  1225. // who retrieved the info earlier.
  1226. //
  1227. case MIPX_GETNEWNICINFO:
  1228. IPX_DEBUG (ACTION, ("%lx: MIPX_GETNEWNICINFO (%lx)\n", AddressFile,
  1229. Request));
  1230. //
  1231. // a request for details on new bindings.
  1232. //
  1233. Status = GetNewNics(Device, Request, TRUE, NwlinkAction, BufferLength, FALSE);
  1234. break;
  1235. //
  1236. // In case a LineUp occurs with the IpxwanConfigRequired, this is used
  1237. // to indicate to IPX that the config is done and that the LineUp
  1238. // can be indicated to the other clients.
  1239. //
  1240. case MIPX_IPXWAN_CONFIG_DONE:
  1241. IPX_DEBUG (ACTION, ("MIPX_IPXWAN_CONFIG_DONE (%lx)\n", Request));
  1242. if (DataLength < sizeof(IPXWAN_CONFIG_DONE)) {
  1243. return STATUS_BUFFER_TOO_SMALL;
  1244. }
  1245. u.IpxwanConfigDone = (PIPXWAN_CONFIG_DONE)(NwlinkAction->Data);
  1246. Status = IpxIndicateLineUp( IpxDevice,
  1247. u.IpxwanConfigDone->NicId,
  1248. u.IpxwanConfigDone->Network,
  1249. u.IpxwanConfigDone->LocalNode,
  1250. u.IpxwanConfigDone->RemoteNode);
  1251. break;
  1252. //
  1253. // Used to query the WAN inactivity counter for a given NicId
  1254. //
  1255. case MIPX_QUERY_WAN_INACTIVITY: {
  1256. USHORT NicId;
  1257. IPX_DEBUG (ACTION, ("MIPX_QUERY_WAN_INACTIVITY (%lx)\n", Request));
  1258. if (DataLength < sizeof(IPX_QUERY_WAN_INACTIVITY)) {
  1259. return STATUS_BUFFER_TOO_SMALL;
  1260. }
  1261. u.QueryWanInactivity = (PIPX_QUERY_WAN_INACTIVITY)(NwlinkAction->Data);
  1262. //
  1263. // If this is an invalid Nic, then we need to associate a Nic with the ConnectionId that
  1264. // was passed in.
  1265. // This should happen only once per line up.
  1266. //
  1267. if (u.QueryWanInactivity->NicId == INVALID_NICID) {
  1268. PBINDING Binding;
  1269. {
  1270. ULONG Index = MIN (Device->MaxBindings, Device->HighestExternalNicId);
  1271. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  1272. for ( NicId = Device->HighestLanNicId+1;NicId < Index;NicId++ ) {
  1273. Binding = NIC_ID_TO_BINDING(Device, NicId);
  1274. if (Binding && (Binding->ConnectionId == u.QueryWanInactivity->ConnectionId)) {
  1275. CTEAssert(Binding->Adapter->MacInfo.MediumAsync);
  1276. if (Binding->LineUp != LINE_CONFIG) {
  1277. IPX_DEBUG (WAN, ("Binding is not in config state yet got QUERY_WAN_INACTIVITY %lx %lx", Binding, Request));
  1278. NicId = 0;
  1279. }
  1280. u.QueryWanInactivity->NicId = NicId;
  1281. break;
  1282. }
  1283. }
  1284. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1285. }
  1286. }
  1287. if (NicId) {
  1288. u.QueryWanInactivity->WanInactivityCounter = IpxInternalQueryWanInactivity(NicId);
  1289. Status = STATUS_SUCCESS;
  1290. } else {
  1291. Status = STATUS_INVALID_PARAMETER;
  1292. }
  1293. break;
  1294. }
  1295. //
  1296. // The Option was not supported, so fail.
  1297. //
  1298. default:
  1299. Status = STATUS_NOT_SUPPORTED;
  1300. break;
  1301. } // end of the long switch on NwlinkAction->Option
  1302. #if DBG
  1303. if (!NT_SUCCESS(Status)) {
  1304. IPX_DEBUG (ACTION, ("Nwlink action %lx failed, status %lx\n", NwlinkAction->Option, Status));
  1305. }
  1306. #endif
  1307. return Status;
  1308. } /* IpxTdiAction */
  1309. VOID
  1310. IpxCancelAction(
  1311. IN PDEVICE_OBJECT DeviceObject,
  1312. IN PIRP Irp
  1313. )
  1314. /*++
  1315. Routine Description:
  1316. This routine is called by the I/O system to cancel an Action.
  1317. What is done to cancel it is specific to each action.
  1318. NOTE: This routine is called with the CancelSpinLock held and
  1319. is responsible for releasing it.
  1320. Arguments:
  1321. DeviceObject - Pointer to the device object for this driver.
  1322. Irp - Pointer to the request packet representing the I/O request.
  1323. Return Value:
  1324. none.
  1325. --*/
  1326. {
  1327. PDEVICE Device = IpxDevice;
  1328. PREQUEST Request = (PREQUEST)Irp;
  1329. CTELockHandle LockHandle;
  1330. PLIST_ENTRY p;
  1331. BOOLEAN Found;
  1332. UINT IOCTLType;
  1333. ASSERT( DeviceObject->DeviceExtension == IpxDevice );
  1334. //
  1335. // Find the request on the address notify queue.
  1336. //
  1337. Found = FALSE;
  1338. CTEGetLock (&Device->Lock, &LockHandle);
  1339. for (p = Device->AddressNotifyQueue.Flink;
  1340. p != &Device->AddressNotifyQueue;
  1341. p = p->Flink) {
  1342. if (LIST_ENTRY_TO_REQUEST(p) == Request) {
  1343. RemoveEntryList (p);
  1344. Found = TRUE;
  1345. IOCTLType = MIPX_NOTIFYCARDINFO;
  1346. break;
  1347. }
  1348. }
  1349. if (!Found) {
  1350. for (p = Device->LineChangeQueue.Flink;
  1351. p != &Device->LineChangeQueue;
  1352. p = p->Flink) {
  1353. if (LIST_ENTRY_TO_REQUEST(p) == Request) {
  1354. RemoveEntryList (p);
  1355. Found = TRUE;
  1356. IOCTLType = MIPX_LINECHANGE;
  1357. break;
  1358. }
  1359. }
  1360. }
  1361. if (!Found) {
  1362. for (p = Device->NicNtfQueue.Flink;
  1363. p != &Device->NicNtfQueue;
  1364. p = p->Flink) {
  1365. if (LIST_ENTRY_TO_REQUEST(p) == Request) {
  1366. RemoveEntryList (p);
  1367. Found = TRUE;
  1368. IOCTLType = MIPX_GETNEWNICINFO;
  1369. break;
  1370. }
  1371. }
  1372. }
  1373. CTEFreeLock (&Device->Lock, LockHandle);
  1374. IoReleaseCancelSpinLock (Irp->CancelIrql);
  1375. if (Found) {
  1376. REQUEST_INFORMATION(Request) = 0;
  1377. REQUEST_STATUS(Request) = STATUS_CANCELLED;
  1378. IpxCompleteRequest (Request);
  1379. IpxFreeRequest(Device, Request);
  1380. if (IOCTLType == MIPX_NOTIFYCARDINFO) {
  1381. IPX_DEBUG(ACTION, ("Cancelled action NOTIFYCARDINFO %lx\n", Request));
  1382. IpxDereferenceDevice (Device, DREF_ADDRESS_NOTIFY);
  1383. } else {
  1384. if (IOCTLType == MIPX_LINECHANGE) {
  1385. IPX_DEBUG(ACTION, ("Cancelled action LINECHANGE %lx\n", Request));
  1386. IpxDereferenceDevice (Device, DREF_LINE_CHANGE);
  1387. } else {
  1388. IPX_DEBUG(ACTION, ("Cancelled action LINECHANGE %lx\n", Request));
  1389. IpxDereferenceDevice (Device, DREF_NIC_NOTIFY);
  1390. }
  1391. }
  1392. }
  1393. #if DBG
  1394. else {
  1395. IPX_DEBUG(ACTION, ("Cancelled action orphan %lx\n", Request));
  1396. }
  1397. #endif
  1398. } /* IpxCancelAction */
  1399. VOID
  1400. IpxAbortLineChanges(
  1401. IN PVOID ControlChannelContext
  1402. )
  1403. /*++
  1404. Routine Description:
  1405. This routine aborts any line change IRPs posted by the
  1406. control channel with the specified open context. It is
  1407. called when a control channel is being shut down.
  1408. Arguments:
  1409. ControlChannelContext - The context assigned to the control
  1410. channel when it was opened.
  1411. Return Value:
  1412. none.
  1413. --*/
  1414. {
  1415. PDEVICE Device = IpxDevice;
  1416. CTELockHandle LockHandle;
  1417. LIST_ENTRY AbortList;
  1418. PLIST_ENTRY p;
  1419. PREQUEST Request;
  1420. KIRQL irql;
  1421. InitializeListHead (&AbortList);
  1422. IoAcquireCancelSpinLock( &irql );
  1423. CTEGetLock (&Device->Lock, &LockHandle);
  1424. p = Device->LineChangeQueue.Flink;
  1425. while (p != &Device->LineChangeQueue) {
  1426. LARGE_INTEGER ControlChId;
  1427. Request = LIST_ENTRY_TO_REQUEST(p);
  1428. CCID_FROM_REQUEST(ControlChId, Request);
  1429. p = p->Flink;
  1430. if (ControlChId.QuadPart == ((PLARGE_INTEGER)ControlChannelContext)->QuadPart) {
  1431. RemoveEntryList (REQUEST_LINKAGE(Request));
  1432. InsertTailList (&AbortList, REQUEST_LINKAGE(Request));
  1433. }
  1434. }
  1435. while (!IsListEmpty (&AbortList)) {
  1436. p = RemoveHeadList (&AbortList);
  1437. Request = LIST_ENTRY_TO_REQUEST(p);
  1438. IPX_DEBUG(ACTION, ("Aborting line change %lx\n", Request));
  1439. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
  1440. REQUEST_INFORMATION(Request) = 0;
  1441. REQUEST_STATUS(Request) = STATUS_CANCELLED;
  1442. CTEFreeLock(&Device->Lock, LockHandle);
  1443. IoReleaseCancelSpinLock( irql );
  1444. IpxCompleteRequest (Request);
  1445. IpxFreeRequest(Device, Request);
  1446. IpxDereferenceDevice (Device, DREF_LINE_CHANGE);
  1447. IoAcquireCancelSpinLock( &irql );
  1448. CTEGetLock(&Device->Lock, &LockHandle);
  1449. }
  1450. CTEFreeLock(&Device->Lock, LockHandle);
  1451. IoReleaseCancelSpinLock( irql );
  1452. } /* IpxAbortLineChanges */
  1453. #define ROUTER_INFORMED_OF_NIC_CREATION 2
  1454. NTSTATUS
  1455. GetNewNics(
  1456. PDEVICE Device,
  1457. IN PREQUEST Request,
  1458. BOOLEAN fCheck,
  1459. PNWLINK_ACTION NwlinkAction,
  1460. UINT BufferLength,
  1461. BOOLEAN OldIrp
  1462. )
  1463. {
  1464. NTSTATUS Status = STATUS_SUCCESS;
  1465. UINT DataLength;
  1466. PNDIS_BUFFER NdisBuffer;
  1467. CTELockHandle LockHandle;
  1468. CTELockHandle LockHandle1;
  1469. PBINDING Binding;
  1470. ULONG NoOfNullNics = 0;
  1471. PIPX_NICS pNics;
  1472. PIPX_NIC_INFO pNicInfo;
  1473. PIPX_NIC_INFO pLastNicInfo;
  1474. UINT LengthOfHeader;
  1475. ULONG n, i;
  1476. KIRQL OldIrql;
  1477. BOOLEAN fIncDec = FALSE;
  1478. ULONG StringLoc = 0;
  1479. LengthOfHeader = (UINT)(FIELD_OFFSET(NWLINK_ACTION, Data[0]));
  1480. if (fCheck)
  1481. {
  1482. if (BufferLength < (LengthOfHeader + FIELD_OFFSET(IPX_NICS, Data[0]) + sizeof(IPX_NIC_INFO)))
  1483. {
  1484. IPX_DEBUG (ACTION, ("Nwlink action failed, buffer too small for even one NICs info\n"));
  1485. return STATUS_BUFFER_TOO_SMALL;
  1486. }
  1487. }
  1488. else
  1489. {
  1490. NdisQueryBufferSafe (REQUEST_NDIS_BUFFER(Request), (PVOID *)&NwlinkAction, &BufferLength, NormalPagePriority);
  1491. if (NwlinkAction == NULL) {
  1492. return STATUS_INSUFFICIENT_RESOURCES;
  1493. }
  1494. }
  1495. pNics = (PIPX_NICS)(NwlinkAction->Data);
  1496. pNicInfo = (PIPX_NIC_INFO)(pNics->Data);
  1497. pLastNicInfo = pNicInfo + ((BufferLength - LengthOfHeader - FIELD_OFFSET(IPX_NICS, Data[0]))/sizeof(IPX_NIC_INFO)) - 1;
  1498. IPX_DEBUG(BIND, ("GetNewNicInfo: pNicInfo=(%x), pLastNicInfo=(%x),LengthOfHeader=(%x), BindingCount=(%x)\n", pNicInfo, pLastNicInfo, LengthOfHeader, Device->ValidBindings));
  1499. IPX_DEBUG(BIND, ("BufferLength is (%d). Length for storing NICS is (%d)\n", BufferLength, (BufferLength - LengthOfHeader - FIELD_OFFSET(IPX_NICS, Data[0]))));
  1500. if (pNics->fAllNicsDesired) {
  1501. IPX_DEBUG(BIND, ("Yes, All NICs desired\n"));
  1502. } else {
  1503. IPX_DEBUG(BIND, ("No, All NICs NOT desired\n"));
  1504. }
  1505. //
  1506. // Optimize since we don't want to go over the array all the time.
  1507. //
  1508. CTEGetLock (&Device->Lock, &LockHandle);
  1509. {
  1510. ULONG Index = MIN (Device->MaxBindings, Device->ValidBindings);
  1511. //
  1512. // If all nics are desired, then mark them ALL as dirty,
  1513. // for the subsequent IRPs that do not have this flag.
  1514. //
  1515. if (pNics->fAllNicsDesired) {
  1516. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  1517. for (n=0, i=LOOPBACK_NIC_ID; i<=Index; i++) {
  1518. Binding = NIC_ID_TO_BINDING(Device, i);
  1519. if (Binding) {
  1520. Binding->fInfoIndicated = FALSE;
  1521. }
  1522. }
  1523. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1524. }
  1525. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  1526. for (n=0, i=LOOPBACK_NIC_ID; i<=Index; i++)
  1527. {
  1528. Binding = NIC_ID_TO_BINDING(Device, i);
  1529. if (!Binding)
  1530. {
  1531. NoOfNullNics++;
  1532. continue;
  1533. }
  1534. //
  1535. // If the binding is of type autodetect *and* we haven't gotten a response on the adapter,
  1536. // that means IPX is still Autodetecting for this card. Do NOT tell FWD about it [shreem]
  1537. //
  1538. if (!Binding->PastAutoDetection) {
  1539. IPX_DEBUG(BIND, ("Binding[%d] Dont Tell FWD!\n", i));
  1540. NoOfNullNics++;
  1541. continue;
  1542. } else {
  1543. IPX_DEBUG(BIND, ("Binding[%d] Tell FWD about it (past auto detect)!\n", i));
  1544. }
  1545. //
  1546. // If we have already indicated info about this NIC, go on to the
  1547. // next nic.
  1548. //
  1549. if ((Binding->fInfoIndicated && !pNics->fAllNicsDesired)
  1550. || (pNicInfo > pLastNicInfo))
  1551. {
  1552. if (Binding->fInfoIndicated) {
  1553. IPX_DEBUG(BIND, ("-------------------------> %d already indicated\n", i));
  1554. } else {
  1555. IPX_DEBUG(BIND, ("*********** Continue for another reason! (%d) \n", i));
  1556. }
  1557. if (pNicInfo > pLastNicInfo) {
  1558. IPX_DEBUG(BIND, ("pNicInfo: %x pLastNicInfo %x\n", pNicInfo, pLastNicInfo));
  1559. }
  1560. continue;
  1561. }
  1562. //
  1563. // If we have a WAN nic, indicate the line up/down status. Also,
  1564. // copy the remote address into the app. field
  1565. //
  1566. if (Binding->Adapter->MacInfo.MediumAsync)
  1567. {
  1568. RtlCopyMemory(pNicInfo->RemoteNodeAddress, Binding->WanRemoteNode, HARDWARE_ADDRESS_LENGTH);
  1569. if (Binding->LineUp)
  1570. {
  1571. // pNicInfo->Status = NIC_LINE_UP;
  1572. pNicInfo->Status = NIC_CREATED;
  1573. //fIncDec = NIC_OPCODE_INCREMENT_NICIDS;
  1574. }
  1575. else
  1576. {
  1577. // pNicInfo->Status = NIC_LINE_DOWN;
  1578. pNicInfo->Status = NIC_DELETED;
  1579. //fIncDec = NIC_OPCODE_DECREMENT_NICIDS;
  1580. }
  1581. pNicInfo->InterfaceIndex = Binding->InterfaceIndex;
  1582. pNicInfo->MaxPacketSize =
  1583. Binding->MaxSendPacketSize - ASYNC_MEDIUM_HDR_LEN;
  1584. }
  1585. else
  1586. {
  1587. if (Binding->LocalAddress.NetworkAddress == 0)
  1588. {
  1589. pNicInfo->Status = NIC_CREATED;
  1590. if (ROUTER_INFORMED_OF_NIC_CREATION != Binding->PastAutoDetection) {
  1591. IPX_DEBUG(BIND, ("!!!!!!!---- Increment on Binding %x, index (%d)\n", Binding,i));
  1592. fIncDec = NIC_OPCODE_INCREMENT_NICIDS;
  1593. } else {
  1594. IPX_DEBUG(BIND, ("Already informed. No increment on Binding %x, index (%d)\n", Binding,i));
  1595. }
  1596. }
  1597. else
  1598. {
  1599. pNicInfo->Status = NIC_CONFIGURED;
  1600. //
  1601. // IPX might have already informed the Router of the
  1602. // creation of this NicId, in which case, we dont ask
  1603. // it to increment the NicIds [ShreeM]
  1604. //
  1605. if (ROUTER_INFORMED_OF_NIC_CREATION != Binding->PastAutoDetection) {
  1606. IPX_DEBUG(BIND, ("!!!!!!!!! --------Increment on Binding %x, index (%d)\n", Binding,i));
  1607. fIncDec = NIC_OPCODE_INCREMENT_NICIDS;
  1608. }
  1609. }
  1610. //
  1611. // Router pnp changes [ShreeM]
  1612. //
  1613. if (FALSE == Binding->LineUp) {
  1614. pNicInfo->Status = NIC_DELETED;
  1615. fIncDec = NIC_OPCODE_DECREMENT_NICIDS;
  1616. }
  1617. //
  1618. // Loopback Adapter
  1619. //
  1620. if (LOOPBACK_NIC_ID == Binding->NicId) {
  1621. pNicInfo->Status = NIC_CONFIGURED;
  1622. fIncDec = NIC_OPCODE_INCREMENT_NICIDS;
  1623. }
  1624. //
  1625. // RealMaxDatagramSize does not include space for ipx
  1626. // header. The forwarder needs to have it included since
  1627. // we give the entire packet (mimus the mac header) to
  1628. // the forwarder
  1629. //
  1630. pNicInfo->MaxPacketSize =
  1631. Binding->RealMaxDatagramSize + sizeof(IPX_HEADER);
  1632. }
  1633. pNicInfo->NdisMediumType= Binding->Adapter->MacInfo.RealMediumType;
  1634. pNicInfo->LinkSpeed = Binding->MediumSpeed;
  1635. pNicInfo->PacketType = Binding->FrameType;
  1636. //
  1637. // Zero the stuff out and then set fields that make sense.
  1638. //
  1639. RtlZeroMemory(&pNicInfo->Details, sizeof(ISN_ACTION_GET_DETAILS));
  1640. pNicInfo->Details.NetworkNumber = Binding->LocalAddress.NetworkAddress;
  1641. RtlCopyMemory(pNicInfo->Details.Node, Binding->LocalAddress.NodeAddress, HARDWARE_ADDRESS_LENGTH);
  1642. pNicInfo->Details.NicId = Binding->NicId;
  1643. pNicInfo->Details.BindingSet = Binding->BindingSetMember;
  1644. pNicInfo->Details.FrameType = Binding->FrameType;
  1645. if (Binding->Adapter->MacInfo.MediumAsync) {
  1646. if (Binding->LineUp) {
  1647. pNicInfo->Details.Type = 2;
  1648. } else {
  1649. pNicInfo->Details.Type = 3;
  1650. }
  1651. } else {
  1652. pNicInfo->Details.Type = 1;
  1653. }
  1654. //
  1655. // Copy the adapter name, including the final NULL.
  1656. //
  1657. StringLoc = (Binding->Adapter->AdapterNameLength / sizeof(WCHAR)) - 2;
  1658. while (Binding->Adapter->AdapterName[StringLoc] != L'\\') {
  1659. --StringLoc;
  1660. }
  1661. RtlCopyMemory(
  1662. pNicInfo->Details.AdapterName,
  1663. &Binding->Adapter->AdapterName[StringLoc+1],
  1664. Binding->Adapter->AdapterNameLength - ((StringLoc+1) * sizeof(WCHAR)));
  1665. //
  1666. // Tell the forwarder that the rest of the NICIDs are to be moved up/down
  1667. // only if it is not asking for ALL of them
  1668. //
  1669. if (!pNics->fAllNicsDesired) {
  1670. pNicInfo->Status |= fIncDec;
  1671. }
  1672. pNicInfo->ConnectionId = Binding->ConnectionId;
  1673. pNicInfo->IpxwanConfigRequired = Binding->IpxwanConfigRequired;
  1674. #if DBG
  1675. //
  1676. // Dump the IPX_NIC_INFO Structure.
  1677. //
  1678. IPX_DEBUG(BIND, ("%d.\nNICID= %d, Interface Index = %d\n", i, pNicInfo->Details.NicId, pNicInfo->InterfaceIndex));
  1679. IPX_DEBUG(BIND, ("Interface Index = %d\n", pNicInfo->InterfaceIndex));
  1680. IPX_DEBUG(BIND, ("LinkSpeed = %d\n", pNicInfo->LinkSpeed));
  1681. IPX_DEBUG(BIND, ("PacketType = %d\n", pNicInfo->PacketType));
  1682. IPX_DEBUG(BIND, ("MaxPacketSize = %d\n", pNicInfo->MaxPacketSize));
  1683. IPX_DEBUG(BIND, ("NdisMediumType = %d\n", pNicInfo->NdisMediumType));
  1684. IPX_DEBUG(BIND, ("NdisMediumSubtype = %d\n", pNicInfo->NdisMediumSubtype));
  1685. IPX_DEBUG(BIND, ("Status = %d\n", (ULONG) pNicInfo->Status));
  1686. IPX_DEBUG(BIND, ("ConnectionID = %d\n", pNicInfo->ConnectionId));
  1687. IPX_DEBUG(BIND, ("IpxwanConfigRequired = %d\n", pNicInfo->IpxwanConfigRequired));
  1688. IPX_DEBUG(BIND, ("FrameType = %d\n", pNicInfo->Details.FrameType));
  1689. IPX_DEBUG(BIND, ("Type = %d\n", pNicInfo->Details.Type));
  1690. IPX_DEBUG(BIND, ("NetworkNumber = %d\n", pNicInfo->Details.NetworkNumber));
  1691. IPX_DEBUG(BIND, ("BindingSet = %d\n", pNicInfo->Details.BindingSet));
  1692. IPX_DEBUG(BIND, ("LocalNode = %x-%x-%x-%x-%x-%x\n", pNicInfo->Details.Node[0],
  1693. pNicInfo->Details.Node[1],
  1694. pNicInfo->Details.Node[2],
  1695. pNicInfo->Details.Node[3],
  1696. pNicInfo->Details.Node[4],
  1697. pNicInfo->Details.Node[5]));
  1698. IPX_DEBUG(BIND, ("RemoteNode = %x-%x-%x-%x-%x-%x\n", pNicInfo->RemoteNodeAddress[0],
  1699. pNicInfo->RemoteNodeAddress[1],
  1700. pNicInfo->RemoteNodeAddress[2],
  1701. pNicInfo->RemoteNodeAddress[3],
  1702. pNicInfo->RemoteNodeAddress[4],
  1703. pNicInfo->RemoteNodeAddress[5]));
  1704. //IPX_DEBUG(BIND, ("AdadpterName = %ws\n", pNicInfo->Details.AdapterName));
  1705. #endif
  1706. pNicInfo++; //increment to store next nic info
  1707. n++; //indicates the # of nics processed so far.
  1708. Binding->fInfoIndicated = TRUE;
  1709. Binding->PastAutoDetection = ROUTER_INFORMED_OF_NIC_CREATION;
  1710. IPX_DEBUG(BIND, ("Iteration no = (%d) complete : reporting NicId:(%lx)\n", n, Binding->NicId));
  1711. }
  1712. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1713. }
  1714. CTEFreeLock (&Device->Lock, LockHandle);
  1715. pNics->NoOfNics = n;
  1716. pNics->TotalNoOfNics = Device->ValidBindings - NoOfNullNics;
  1717. //
  1718. // If no nics. to report, queue the request
  1719. //
  1720. if (!n) {
  1721. IPX_DEBUG(BIND, ("GetNewNicInfo: Inserting Irp\n"));
  1722. CTEGetLock (&Device->Lock, &LockHandle);
  1723. InsertTailList( &Device->NicNtfQueue, REQUEST_LINKAGE(Request) );
  1724. if (!OldIrp)
  1725. {
  1726. IoSetCancelRoutine (Request, IpxCancelAction);
  1727. }
  1728. if (Request->Cancel &&
  1729. IoSetCancelRoutine(Request, (PDRIVER_CANCEL)NULL)) {
  1730. IPX_DEBUG(BIND, ("GetNewNicInfo:Cancelling Irp\n"));
  1731. (VOID)RemoveTailList (&Device->NicNtfQueue);
  1732. CTEFreeLock (&Device->Lock, LockHandle);
  1733. Status = STATUS_CANCELLED;
  1734. } else {
  1735. if (!OldIrp)
  1736. {
  1737. IpxReferenceDevice (Device, DREF_NIC_NOTIFY);
  1738. }
  1739. Status = STATUS_PENDING;
  1740. CTEFreeLock (&Device->Lock, LockHandle);
  1741. }
  1742. }
  1743. else
  1744. {
  1745. IPX_DEBUG(BIND, ("Reporting (%d) nics\n", n));
  1746. }
  1747. return(Status);
  1748. }
  1749. VOID
  1750. IpxAbortNtfChanges(
  1751. IN PVOID ControlChannelContext
  1752. )
  1753. /*++
  1754. Routine Description:
  1755. This routine aborts any line change IRPs posted by the
  1756. control channel with the specified open context. It is
  1757. called when a control channel is being shut down.
  1758. Arguments:
  1759. ControlChannelContext - The context assigned to the control
  1760. channel when it was opened.
  1761. Return Value:
  1762. none.
  1763. --*/
  1764. {
  1765. PDEVICE Device = IpxDevice;
  1766. CTELockHandle LockHandle;
  1767. LIST_ENTRY AbortList;
  1768. PLIST_ENTRY p;
  1769. PREQUEST Request;
  1770. KIRQL irql;
  1771. InitializeListHead (&AbortList);
  1772. IoAcquireCancelSpinLock( &irql );
  1773. CTEGetLock (&Device->Lock, &LockHandle);
  1774. p = Device->NicNtfQueue.Flink;
  1775. while (p != &Device->NicNtfQueue) {
  1776. LARGE_INTEGER ControlChId;
  1777. Request = LIST_ENTRY_TO_REQUEST(p);
  1778. CCID_FROM_REQUEST(ControlChId, Request);
  1779. IPX_DEBUG(BIND, ("IpxAbortNtfChange: There is at least one IRP in the queue\n"));
  1780. p = p->Flink;
  1781. if (ControlChId.QuadPart == ((PLARGE_INTEGER)ControlChannelContext)->QuadPart) {
  1782. IPX_DEBUG(BIND, ("IpxAbortNtfChanges: Dequeing an Irp\n"));
  1783. RemoveEntryList (REQUEST_LINKAGE(Request));
  1784. InsertTailList (&AbortList, REQUEST_LINKAGE(Request));
  1785. }
  1786. }
  1787. while (!IsListEmpty (&AbortList)) {
  1788. p = RemoveHeadList (&AbortList);
  1789. Request = LIST_ENTRY_TO_REQUEST(p);
  1790. IPX_DEBUG(ACTION, ("Aborting line change %lx\n", Request));
  1791. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
  1792. REQUEST_INFORMATION(Request) = 0;
  1793. REQUEST_STATUS(Request) = STATUS_CANCELLED;
  1794. CTEFreeLock(&Device->Lock, LockHandle);
  1795. IoReleaseCancelSpinLock( irql );
  1796. IPX_DEBUG(BIND, ("IpxAbortNtfChanges: Cancelling the dequeued Irp\n"));
  1797. IpxCompleteRequest (Request);
  1798. IpxFreeRequest(Device, Request);
  1799. IpxDereferenceDevice (Device, DREF_NIC_NOTIFY);
  1800. IoAcquireCancelSpinLock( &irql );
  1801. CTEGetLock(&Device->Lock, &LockHandle);
  1802. }
  1803. CTEFreeLock(&Device->Lock, LockHandle);
  1804. IoReleaseCancelSpinLock( irql );
  1805. } /* IpxAbortNtfChanges */
  1806. NTSTATUS
  1807. IpxIndicateLineUp(
  1808. IN PDEVICE Device,
  1809. IN USHORT NicId,
  1810. IN ULONG Network,
  1811. IN UCHAR LocalNode[6],
  1812. IN UCHAR RemoteNode[6]
  1813. )
  1814. /*++
  1815. Routine Description:
  1816. This routine indicates a line-up to all the concerned clients once
  1817. the line is up.
  1818. For now, called only if the MIPX_IPXWAN_CONFIG_DONE IOCTL is received.
  1819. Arguments:
  1820. Device - The device for the operation.
  1821. NicId - The NicId corresponding to the binding that is up.
  1822. Network, LocalNode, RemoteNode - addresses corresponding to this lineup.
  1823. Return Value:
  1824. NTSTATUS - status of operation.
  1825. --*/
  1826. {
  1827. PBINDING Binding = NIC_ID_TO_BINDING(Device, NicId);
  1828. IPX_LINE_INFO LineInfo;
  1829. USHORT i;
  1830. PLIST_ENTRY p;
  1831. PREQUEST Request;
  1832. PNDIS_BUFFER NdisBuffer;
  1833. PNWLINK_ACTION NwlinkAction;
  1834. UINT BufferLength;
  1835. PIPX_ADDRESS_DATA IpxAddressData;
  1836. IPXCP_CONFIGURATION Configuration;
  1837. KIRQL irql, OldIrq;
  1838. NTSTATUS Status;
  1839. NTSTATUS ntStatus;
  1840. KIRQL OldIrql;
  1841. IPX_DEFINE_LOCK_HANDLE (LockHandle)
  1842. if (!(Binding &&
  1843. Binding->Adapter->MacInfo.MediumAsync &&
  1844. Binding->LineUp == LINE_CONFIG)) {
  1845. IPX_DEBUG(WAN, ("Indicate line up on invalid line: %lu\n", NicId));
  1846. return STATUS_INVALID_PARAMETER;
  1847. }
  1848. // take bindaccesslock here...
  1849. //
  1850. //
  1851. // If we are here, then this flag was set on a line up.
  1852. // We turn it off now so that the adapter dll above us can decide
  1853. // to indicate this lineup to the router module instead of the IpxWan module
  1854. //
  1855. CTEAssert(Binding->IpxwanConfigRequired);
  1856. Binding->IpxwanConfigRequired = 0;
  1857. Binding->LineUp = LINE_UP;
  1858. //
  1859. // Indicate to the upper drivers.
  1860. //
  1861. LineInfo.LinkSpeed = Binding->MediumSpeed;
  1862. LineInfo.MaximumPacketSize = Binding->MaxSendPacketSize - 14;
  1863. LineInfo.MaximumSendSize = Binding->MaxSendPacketSize - 14;
  1864. LineInfo.MacOptions = Binding->Adapter->MacInfo.MacOptions;
  1865. //
  1866. // Fill-in the addresses into the bindings
  1867. //
  1868. Binding->LocalAddress.NetworkAddress = Network;
  1869. *(UNALIGNED ULONG *)Binding->LocalAddress.NodeAddress = *(UNALIGNED ULONG *)LocalNode;
  1870. *(UNALIGNED ULONG *)(Binding->LocalAddress.NodeAddress+4) = *(UNALIGNED ULONG *)(LocalNode+4);
  1871. *(UNALIGNED ULONG *)Binding->WanRemoteNode = *(UNALIGNED ULONG *)RemoteNode;
  1872. *(UNALIGNED ULONG *)(Binding->WanRemoteNode+4) = *(UNALIGNED ULONG *)(RemoteNode+4);
  1873. //
  1874. // Fill in the IPXCP_CONFIGURATION structure from the binding.
  1875. //
  1876. *(UNALIGNED ULONG *)Configuration.Network = Binding->LocalAddress.NetworkAddress;
  1877. *(UNALIGNED ULONG *)Configuration.LocalNode = *(UNALIGNED ULONG *)Binding->LocalAddress.NodeAddress;
  1878. *(UNALIGNED USHORT *)(Configuration.LocalNode+4) = *(UNALIGNED USHORT *)(Binding->LocalAddress.NodeAddress+4);
  1879. *(UNALIGNED ULONG *)Configuration.RemoteNode = *(UNALIGNED ULONG *)RemoteNode;
  1880. *(UNALIGNED USHORT *)(Configuration.RemoteNode+4) = *(UNALIGNED USHORT *)(RemoteNode+4);
  1881. Configuration.InterfaceIndex = Binding->InterfaceIndex;
  1882. Configuration.ConnectionClient = Binding->DialOutAsync;
  1883. //
  1884. // We dont give lineups; instead indicate only if the PnP reserved address
  1885. // changed to SPX. NB gets all PnP indications with the reserved address case
  1886. // marked out.
  1887. //
  1888. {
  1889. IPX_PNP_INFO NBPnPInfo;
  1890. if ((!Device->MultiCardZeroVirtual) || (Binding->NicId == 1)) {
  1891. //
  1892. // NB's reserved address changed.
  1893. //
  1894. NBPnPInfo.NewReservedAddress = TRUE;
  1895. if (!Device->VirtualNetwork) {
  1896. //
  1897. // Let SPX know because it fills in its own headers.
  1898. //
  1899. if (Device->UpperDriverBound[IDENTIFIER_SPX]) {
  1900. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  1901. IPX_PNP_INFO IpxPnPInfo;
  1902. IpxPnPInfo.NewReservedAddress = TRUE;
  1903. IpxPnPInfo.NetworkAddress = Binding->LocalAddress.NetworkAddress;
  1904. IpxPnPInfo.FirstORLastDevice = FALSE;
  1905. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  1906. RtlCopyMemory(IpxPnPInfo.NodeAddress, Binding->LocalAddress.NodeAddress, 6);
  1907. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, Binding->NicId);
  1908. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1909. //
  1910. // give the PnP indication
  1911. //
  1912. (*Device->UpperDrivers[IDENTIFIER_SPX].PnPHandler) (
  1913. IPX_PNP_ADDRESS_CHANGE,
  1914. &IpxPnPInfo);
  1915. IPX_DEBUG(AUTO_DETECT, ("IPX_PNP_ADDRESS_CHANGED to SPX: net addr: %lx\n", Binding->LocalAddress.NetworkAddress));
  1916. }
  1917. }
  1918. } else {
  1919. NBPnPInfo.NewReservedAddress = FALSE;
  1920. }
  1921. if (Device->UpperDriverBound[IDENTIFIER_NB]) {
  1922. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  1923. Binding->IsnInformed[IDENTIFIER_NB] = TRUE;
  1924. NBPnPInfo.LineInfo.LinkSpeed = Device->LinkSpeed;
  1925. NBPnPInfo.LineInfo.MaximumPacketSize =
  1926. Device->Information.MaximumLookaheadData + sizeof(IPX_HEADER);
  1927. NBPnPInfo.LineInfo.MaximumSendSize =
  1928. Device->Information.MaxDatagramSize + sizeof(IPX_HEADER);
  1929. NBPnPInfo.LineInfo.MacOptions = Device->MacOptions;
  1930. NBPnPInfo.NetworkAddress = Binding->LocalAddress.NetworkAddress;
  1931. NBPnPInfo.FirstORLastDevice = FALSE;
  1932. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  1933. RtlCopyMemory(NBPnPInfo.NodeAddress, Binding->LocalAddress.NodeAddress, 6);
  1934. NIC_HANDLE_FROM_NIC(NBPnPInfo.NicHandle, Binding->NicId);
  1935. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1936. //
  1937. // give the PnP indication
  1938. //
  1939. (*Device->UpperDrivers[IDENTIFIER_NB].PnPHandler) (
  1940. IPX_PNP_ADD_DEVICE,
  1941. &NBPnPInfo);
  1942. IPX_DEBUG(AUTO_DETECT, ("IPX_PNP_ADD_DEVICE (lineup) to NB: net addr: %lx\n", Binding->LocalAddress.NetworkAddress));
  1943. }
  1944. //
  1945. // Register this address with the TDI clients.
  1946. //
  1947. RtlCopyMemory (Device->TdiRegistrationAddress->Address, &Binding->LocalAddress, sizeof(TDI_ADDRESS_IPX));
  1948. if ((ntStatus = TdiRegisterNetAddress(
  1949. Device->TdiRegistrationAddress,
  1950. #if defined(_PNP_POWER_)
  1951. &IpxDeviceName,
  1952. NULL,
  1953. #endif _PNP_POWER_
  1954. &Binding->TdiRegistrationHandle)) != STATUS_SUCCESS) {
  1955. IPX_DEBUG(PNP, ("TdiRegisterNetAddress failed: %lx", ntStatus));
  1956. }
  1957. }
  1958. //
  1959. // Indicate to the upper drivers.
  1960. //
  1961. //
  1962. // Give line up to RIP as it is not PnP aware.
  1963. //
  1964. if (Device->UpperDriverBound[IDENTIFIER_RIP]) {
  1965. Binding->IsnInformed[IDENTIFIER_RIP] = TRUE;
  1966. (*Device->UpperDrivers[IDENTIFIER_RIP].LineUpHandler)(
  1967. Binding->NicId,
  1968. &LineInfo,
  1969. NdisMediumWan,
  1970. &Configuration);
  1971. }
  1972. //
  1973. // Add router entry for this net since it was not done on LineUp.
  1974. // Also, update the addresses' pre-constructed local IPX address.
  1975. //
  1976. {
  1977. ULONG CurrentHash;
  1978. PADAPTER Adapter = Binding->Adapter;
  1979. PADDRESS Address;
  1980. //
  1981. // Add a router entry for this net if there is no router.
  1982. // We want the number of ticks for a 576-byte frame,
  1983. // given the link speed in 100 bps units, so we calculate
  1984. // as:
  1985. //
  1986. // seconds 18.21 ticks 4608 bits
  1987. // --------------------- * ----------- * ---------
  1988. // link_speed * 100 bits second frame
  1989. //
  1990. // to get the formula
  1991. //
  1992. // ticks/frame = 839 / link_speed.
  1993. //
  1994. // We add link_speed to the numerator also to ensure
  1995. // that the value is at least 1.
  1996. //
  1997. if ((!Device->UpperDriverBound[IDENTIFIER_RIP]) &&
  1998. (*(UNALIGNED ULONG *)Configuration.Network != 0)) {
  1999. if (RipInsertLocalNetwork(
  2000. *(UNALIGNED ULONG *)Configuration.Network,
  2001. Binding->NicId,
  2002. Adapter->NdisBindingHandle,
  2003. (USHORT)((839 + Binding->MediumSpeed) / Binding->MediumSpeed)) != STATUS_SUCCESS) {
  2004. //
  2005. // This means we couldn't allocate memory, or
  2006. // the entry already existed. If it already
  2007. // exists we can ignore it for the moment.
  2008. //
  2009. // Now it will succeed if the network exists.
  2010. //
  2011. IPX_DEBUG (WAN, ("Line up, could not insert local network\n"));
  2012. // [FW] Binding->LineUp = FALSE;
  2013. Binding->LineUp = LINE_DOWN;
  2014. return STATUS_SUCCESS;
  2015. }
  2016. }
  2017. //
  2018. // Update the device node and all the address
  2019. // nodes if we have only one bound, or this is
  2020. // binding one.
  2021. //
  2022. if (!Device->VirtualNetwork) {
  2023. if ((!Device->MultiCardZeroVirtual) || (Binding->NicId == 1)) {
  2024. Device->SourceAddress.NetworkAddress = *(UNALIGNED ULONG *)(Configuration.Network);
  2025. RtlCopyMemory (Device->SourceAddress.NodeAddress, Configuration.LocalNode, 6);
  2026. }
  2027. //
  2028. // Scan through all the addresses that exist and modify
  2029. // their pre-constructed local IPX address to reflect
  2030. // the new local net and node.
  2031. //
  2032. IPX_GET_LOCK (&Device->Lock, &LockHandle);
  2033. for (CurrentHash = 0; CurrentHash < IPX_ADDRESS_HASH_COUNT; CurrentHash++) {
  2034. for (p = Device->AddressDatabases[CurrentHash].Flink;
  2035. p != &Device->AddressDatabases[CurrentHash];
  2036. p = p->Flink) {
  2037. Address = CONTAINING_RECORD (p, ADDRESS, Linkage);
  2038. Address->LocalAddress.NetworkAddress = *(UNALIGNED ULONG *)Configuration.Network;
  2039. RtlCopyMemory (Address->LocalAddress.NodeAddress, Configuration.LocalNode, 6);
  2040. }
  2041. }
  2042. IPX_FREE_LOCK (&Device->Lock, LockHandle);
  2043. }
  2044. }
  2045. //
  2046. // [FW] IpxWan config state will not be entered if only the line params are getting
  2047. // updated.
  2048. //
  2049. // if (!UpdateLineUp) {
  2050. //
  2051. // Instead of the check for ConnectionClient, use the DialOutAsync flag
  2052. //
  2053. if ((Device->SingleNetworkActive) &&
  2054. /*(LineUp->Configuration.ConnectionClient == 1)*/
  2055. Binding->DialOutAsync) {
  2056. //
  2057. // Drop all entries in the database if rip is not bound.
  2058. //
  2059. if (!Device->UpperDriverBound[IDENTIFIER_RIP]) {
  2060. RipDropRemoteEntries();
  2061. }
  2062. Device->ActiveNetworkWan = TRUE;
  2063. //
  2064. // Find a queued line change and complete it.
  2065. //
  2066. if ((p = ExInterlockedRemoveHeadList(
  2067. &Device->LineChangeQueue,
  2068. &Device->Lock)) != NULL) {
  2069. Request = LIST_ENTRY_TO_REQUEST(p);
  2070. IoAcquireCancelSpinLock( &irql );
  2071. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
  2072. IoReleaseCancelSpinLock( irql );
  2073. REQUEST_STATUS(Request) = STATUS_SUCCESS;
  2074. //
  2075. // NwRdr assumes that Line-up completions are at DPC
  2076. //
  2077. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  2078. IpxCompleteRequest (Request);
  2079. KeLowerIrql(OldIrql);
  2080. IpxFreeRequest (Device, Request);
  2081. IpxDereferenceDevice (Device, DREF_LINE_CHANGE);
  2082. }
  2083. }
  2084. //
  2085. // If we have a virtual net, do a broadcast now so
  2086. // the router on the other end will know about us.
  2087. //
  2088. // Use RipSendResponse, and do it even
  2089. // if SingleNetworkActive is FALSE??
  2090. //
  2091. if (Device->RipResponder && Binding->DialOutAsync) {
  2092. (VOID)RipQueueRequest (Device->VirtualNetworkNumber, RIP_RESPONSE);
  2093. }
  2094. //
  2095. // Find a queued address notify and complete it.
  2096. // If WanGlobalNetworkNumber is TRUE, we only do
  2097. // this when the first dialin line comes up.
  2098. //
  2099. if ((!Device->WanGlobalNetworkNumber ||
  2100. (!Device->GlobalNetworkIndicated && !Binding->DialOutAsync))
  2101. &&
  2102. ((p = ExInterlockedRemoveHeadList(
  2103. &Device->AddressNotifyQueue,
  2104. &Device->Lock)) != NULL)) {
  2105. if (Device->WanGlobalNetworkNumber) {
  2106. Device->GlobalWanNetwork = Binding->LocalAddress.NetworkAddress;
  2107. Device->GlobalNetworkIndicated = TRUE;
  2108. }
  2109. Request = LIST_ENTRY_TO_REQUEST(p);
  2110. NdisBuffer = REQUEST_NDIS_BUFFER(Request);
  2111. NdisQueryBufferSafe (REQUEST_NDIS_BUFFER(Request), (PVOID *)&NwlinkAction, &BufferLength, HighPagePriority);
  2112. if (NwlinkAction == NULL) {
  2113. return STATUS_INSUFFICIENT_RESOURCES;
  2114. }
  2115. IpxAddressData = (PIPX_ADDRESS_DATA)(NwlinkAction->Data);
  2116. if (Device->WanGlobalNetworkNumber) {
  2117. IpxAddressData->adapternum = Device->SapNicCount - 1;
  2118. } else {
  2119. IpxAddressData->adapternum = Binding->NicId - 1;
  2120. }
  2121. *(UNALIGNED ULONG *)IpxAddressData->netnum = Binding->LocalAddress.NetworkAddress;
  2122. RtlCopyMemory(IpxAddressData->nodenum, Binding->LocalAddress.NodeAddress, 6);
  2123. IpxAddressData->wan = TRUE;
  2124. IpxAddressData->status = TRUE;
  2125. IpxAddressData->maxpkt = Binding->AnnouncedMaxDatagramSize; // Use real?
  2126. IpxAddressData->linkspeed = Binding->MediumSpeed;
  2127. IoAcquireCancelSpinLock( &irql );
  2128. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
  2129. IoReleaseCancelSpinLock( irql );
  2130. REQUEST_STATUS(Request) = STATUS_SUCCESS;
  2131. IpxCompleteRequest (Request);
  2132. IpxFreeRequest (Device, Request);
  2133. IpxDereferenceDevice (Device, DREF_ADDRESS_NOTIFY);
  2134. }
  2135. Binding->fInfoIndicated = FALSE;
  2136. if ((p = ExInterlockedRemoveHeadList(
  2137. &Device->NicNtfQueue,
  2138. &Device->Lock)) != NULL)
  2139. {
  2140. Request = LIST_ENTRY_TO_REQUEST(p);
  2141. IPX_DEBUG(BIND, ("IpxStatus: WAN LINE UP\n"));
  2142. Status = GetNewNics(Device, Request, FALSE, NULL, 0, TRUE);
  2143. if (Status == STATUS_PENDING)
  2144. {
  2145. IPX_DEBUG(BIND, ("WANLineUp may not be responding properly\n"));
  2146. }
  2147. else
  2148. {
  2149. IoAcquireCancelSpinLock(&OldIrq);
  2150. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
  2151. IoReleaseCancelSpinLock(OldIrq);
  2152. REQUEST_STATUS(Request) = Status;
  2153. IpxCompleteRequest (Request);
  2154. IpxFreeRequest (Device, Request);
  2155. IpxDereferenceDevice (Device, DREF_NIC_NOTIFY);
  2156. }
  2157. }
  2158. // }
  2159. return STATUS_SUCCESS;
  2160. }