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.

1393 lines
38 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. arapatk.c
  5. Abstract:
  6. This module implements routines that directly interface with Atalk stack
  7. Author:
  8. Shirish Koti
  9. Revision History:
  10. 15 Nov 1996 Initial Version
  11. --*/
  12. #define ARAP_LOCALS
  13. #include <atalk.h>
  14. #pragma hdrstop
  15. #define FILENUM ARAPATK
  16. #ifdef ALLOC_PRAGMA
  17. #pragma alloc_text(PAGE_ARAP, ArapRoutePacketFromWan)
  18. #pragma alloc_text(PAGE_ARAP, ArapRoutePacketToWan)
  19. #pragma alloc_text(PAGE_ARAP, ArapOkToForward)
  20. #pragma alloc_text(PAGE_ARAP, ArapAddArapRoute)
  21. #pragma alloc_text(PAGE_ARAP, ArapDeleteArapRoute)
  22. #pragma alloc_text(PAGE_ARAP, ArapGetDynamicAddr)
  23. #pragma alloc_text(PAGE_ARAP, ArapGetStaticAddr)
  24. #pragma alloc_text(PAGE_ARAP, ArapValidNetrange)
  25. #pragma alloc_text(PAGE_ARAP, ArapZipGetZoneStat)
  26. #pragma alloc_text(PAGE_ARAP, ArapZipGetZoneStatCompletion)
  27. #endif
  28. //***
  29. //
  30. // Function: ArapRoutePacketFromWan
  31. // This routine picks up a packet from the phone line and forwards
  32. // it on to the lan. It does some "fixing up" of the packet so that
  33. // to the stack, it looks like any other packet from the lan
  34. //
  35. // Parameters: pArapConn - connection element for whom data has come in
  36. // pArapBuf - buffer containing the packet
  37. //
  38. // Return: none
  39. //
  40. //***$
  41. VOID
  42. ArapRoutePacketFromWan(
  43. IN PARAPCONN pArapConn,
  44. IN PARAPBUF pArapBuf
  45. )
  46. {
  47. PBYTE packet;
  48. USHORT DataSize;
  49. USHORT checksum;
  50. USHORT RevNet;
  51. BYTE RevNode;
  52. PBYTE pZoneNamePtr;
  53. USHORT BytesToZoneName=0;
  54. LONG CurrentTime;
  55. DBG_ARAP_CHECK_PAGED_CODE();
  56. DBGDUMPBYTES("ArapRoutePacketFromWan:",&pArapBuf->Buffer[0], pArapBuf->DataSize,4);
  57. packet = pArapBuf->CurrentBuffer;
  58. DataSize = pArapBuf->DataSize;
  59. ASSERT(packet[2] == 0x50);
  60. ASSERT(packet[3] == 0 && packet[4] == 0 && packet[5] == 2);
  61. // skip 3 bytes (past the SrpLen (2) and Dgroup (1) bytes)
  62. packet += ARAP_DATA_OFFSET;
  63. DataSize -= ARAP_DATA_OFFSET;
  64. //
  65. // see if we need to calculate the checksum. The LAP header is 0's if
  66. // checksum is not included in the pkt, 1's otherwise.
  67. //
  68. checksum = 0;
  69. if (*packet == 1 && *(packet+1) == 1)
  70. {
  71. checksum = 1;
  72. }
  73. // skip the LAP header
  74. packet += ARAP_LAP_HDRSIZE;
  75. DataSize -= ARAP_LAP_HDRSIZE;
  76. #if DBG
  77. if (packet[LDDP_PROTO_TYPE_OFFSET] == DDPPROTO_RTMPRESPONSEORDATA)
  78. {
  79. DBGPRINT(DBG_COMP_ROUTER, DBG_LEVEL_ERR,
  80. ("ArapRoutePacketFromWan: got RTMPRESPONSEORDATA pkt!!\n"));
  81. ASSERT(0);
  82. }
  83. if (packet[LDDP_PROTO_TYPE_OFFSET] == DDPPROTO_RTMPREQUEST)
  84. {
  85. DBGPRINT(DBG_COMP_ROUTER, DBG_LEVEL_ERR,
  86. ("ArapRoutePacketFromWan: got RTMPREQUEST pkt!!\n"));
  87. ASSERT(0);
  88. }
  89. if (packet[LDDP_PROTO_TYPE_OFFSET] == DDPPROTO_ZIP)
  90. {
  91. DBGPRINT(DBG_COMP_ROUTER, DBG_LEVEL_ERR,
  92. ("ArapRoutePacketFromWan: got ZIP pkt!!\n"));
  93. ASSERT(0);
  94. }
  95. #endif
  96. // fill in the length and checksum in the ddp header ("fix-up" ddp hdr)
  97. PUTSHORT2SHORT(&packet[LDDP_LEN_OFFSET], DataSize);
  98. PUTSHORT2SHORT(&packet[LDDP_CHECKSUM_OFFSET], 0);
  99. //
  100. // we need to "fix up" NBP requests. If this is a BrRq request (Function=1,
  101. // and TupleCount=1), we need to patch up the datagram
  102. //
  103. if (packet[LDDP_PROTO_TYPE_OFFSET] == DDPPROTO_NBP &&
  104. packet[LDDP_DGRAM_OFFSET] == ARAP_NBP_BRRQ)
  105. {
  106. //
  107. // let's treat nbp lookups as lower priority items!
  108. // if we have a lot of stuff sitting on the recv or the send the queue
  109. // then drop this nbp lookup broadcast (because otherwise it will only
  110. // generate more packets (and chooser won't deal with them anyway!)
  111. //
  112. if ((packet[LDDP_DEST_NODE_OFFSET] == ATALK_BROADCAST_NODE) &&
  113. ((pArapConn->SendsPending > ARAP_SENDQ_LOWER_LIMIT) ||
  114. (pArapConn->RecvsPending > ARAP_SENDQ_LOWER_LIMIT)) )
  115. {
  116. DBGPRINT(DBG_COMP_ROUTER, DBG_LEVEL_ERR,
  117. ("ArapRoutePacketFromWan: dropping NBP bcast to lan (%d %d bytes)\n",
  118. pArapConn->SendsPending,pArapConn->RecvsPending));
  119. return;
  120. }
  121. #if 0
  122. need to save old packet. Drop this packet only if it compares with the old one
  123. If something changed (say zone name!), send the packet over even if it's less than
  124. 5 sec. Also, delta should be probably 35 or something (for 3 pkts)
  125. CurrentTime = AtalkGetCurrentTick();
  126. //
  127. // Chooser keeps sending the Brrq request out. Cut it out! If we have
  128. // sent a request out (on Mac's behalf) less than 5 seconds ago, drop this!
  129. //
  130. if (CurrentTime - pArapConn->LastNpbBrrq < 50)
  131. {
  132. DBGPRINT(DBG_COMP_ROUTER, DBG_LEVEL_ERR,
  133. ("ArapRoutePacketFromWan: dropping NBP_BRRQ (last %ld now %ld)\n",
  134. pArapConn->LastNpbBrrq,CurrentTime));
  135. return;
  136. }
  137. pArapConn->LastNpbBrrq = CurrentTime;
  138. #endif
  139. #if 0
  140. // get to where the zone name is
  141. BytesToZoneName = ARAP_NBP_OBJLEN_OFFSET;
  142. // skip the object (along with the object len byte)
  143. BytesToZoneName += packet[ARAP_NBP_OBJLEN_OFFSET] + 1;
  144. // skip the type (along with the object len byte)
  145. BytesToZoneName += packet[BytesToZoneName] + 1;
  146. // this is where the zonelen field starts
  147. pZoneNamePtr = packet + BytesToZoneName;
  148. if (*pZoneNamePtr == 0 || *(pZoneNamePtr+1) == '*')
  149. {
  150. DBGPRINT(DBG_COMP_ROUTER, DBG_LEVEL_ERR,
  151. ("ArapRoutePacketFromWan: * zone name (%lx,%lx)\n",packet,pZoneNamePtr));
  152. }
  153. #endif
  154. if (ArapGlobs.NetworkAccess)
  155. {
  156. //
  157. // if router is running, fix the packet so that the router thinks this
  158. // is a pkt from any other net client on the lan
  159. //
  160. if (AtalkDefaultPort->pd_Flags & PD_ROUTER_RUNNING)
  161. {
  162. RevNet = AtalkDefaultPort->pd_RouterNode->an_NodeAddr.atn_Network;
  163. RevNode = AtalkDefaultPort->pd_RouterNode->an_NodeAddr.atn_Node;
  164. }
  165. //
  166. // router is not running. Do we know who the router is?
  167. //
  168. else if (AtalkDefaultPort->pd_Flags & PD_SEEN_ROUTER_RECENTLY)
  169. {
  170. RevNet = AtalkDefaultPort->pd_ARouter.atn_Network;
  171. RevNode = AtalkDefaultPort->pd_ARouter.atn_Node;
  172. }
  173. //
  174. // nope, send it to cable-wide bcast
  175. //
  176. else
  177. {
  178. // "fix-up" the nbp request
  179. packet[LDDP_DGRAM_OFFSET] = ARAP_NBP_LKRQ;
  180. RevNet = CABLEWIDE_BROADCAST_NETWORK;
  181. RevNode = ATALK_BROADCAST_NODE;
  182. }
  183. }
  184. //
  185. // hmmm: client is not allowed to access network resources: just pretend
  186. // it's local broadcast, and pkt-forwarding logic will take care of it
  187. //
  188. else
  189. {
  190. // "fix-up" the nbp request
  191. packet[LDDP_DGRAM_OFFSET] = ARAP_NBP_LKRQ;
  192. RevNet = CABLEWIDE_BROADCAST_NETWORK;
  193. RevNode = ATALK_BROADCAST_NODE;
  194. }
  195. PUTSHORT2SHORT(&packet[LDDP_DEST_NETWORK_OFFSET], RevNet);
  196. packet[LDDP_DEST_NODE_OFFSET] = RevNode;
  197. }
  198. if (checksum)
  199. {
  200. checksum = AtalkDdpCheckSumBuffer(packet, DataSize, 0);
  201. PUTSHORT2SHORT(&packet[LDDP_CHECKSUM_OFFSET], checksum);
  202. }
  203. AtalkDdpPacketIn(AtalkDefaultPort, NULL, packet, DataSize, TRUE);
  204. }
  205. //***
  206. //
  207. // Function: ArapRoutePacketToWan
  208. // This routine picks up a packet from the lan, checks to see if
  209. // it must be forwarded to any of the ARAP clients and does the
  210. // good deed.
  211. //
  212. // Parameters: pDestAddr - who is this packet addressed to? (potentially bcast)
  213. // pSrcAddr - who sent this packet
  214. // Protocol - what packet is it? (ATP, NBP, etc.)
  215. // packet - buffer containing the packet
  216. // PktLen - how big is the packet
  217. // broadcast - is this a broadcast packet?
  218. // pDelivered - set on return: did we forward it to any dial-in
  219. // client (set to TRUE only for directed dgrams)
  220. //
  221. // Return: none
  222. //
  223. //***$
  224. VOID
  225. ArapRoutePacketToWan(
  226. IN ATALK_ADDR *pDestAddr,
  227. IN ATALK_ADDR *pSrcAddr,
  228. IN BYTE Protocol,
  229. IN PBYTE packet,
  230. IN USHORT PktLen,
  231. IN BOOLEAN broadcast,
  232. OUT PBOOLEAN pDelivered
  233. )
  234. {
  235. KIRQL OldIrql;
  236. PARAPCONN pArapConn;
  237. PARAPCONN pPrevArapConn;
  238. PLIST_ENTRY pConnList;
  239. BUFFER_DESC InBuffDesc;
  240. BUFFER_DESC BuffDesc;
  241. BYTE ArapHdr[ARAP_LAP_HDRSIZE + ARAP_HDRSIZE];
  242. PBYTE pArapHdrPtr;
  243. ATALK_NODEADDR DestNode;
  244. DWORD StatusCode;
  245. DWORD dwFlags;
  246. USHORT SrpLen;
  247. DWORD Priority;
  248. DBG_ARAP_CHECK_PAGED_CODE();
  249. // assume for now
  250. *pDelivered = FALSE;
  251. // no network access for dial-in guys? don't send this out to them
  252. if (!ArapGlobs.NetworkAccess)
  253. {
  254. return;
  255. }
  256. //
  257. // if this is an RTMP or ZIP bcast, drop it since ARAP clients don't
  258. // care for these packets
  259. //
  260. if (broadcast)
  261. {
  262. if ((packet[LDDP_PROTO_TYPE_OFFSET] == DDPPROTO_RTMPREQUEST) ||
  263. (packet[LDDP_PROTO_TYPE_OFFSET] == DDPPROTO_RTMPRESPONSEORDATA) )
  264. {
  265. DBGDUMPBYTES("ArapFrmLan: bcast pkt:",packet, LDDP_HDR_LEN+4,6);
  266. return;
  267. }
  268. if (packet[LDDP_PROTO_TYPE_OFFSET] == DDPPROTO_ZIP)
  269. {
  270. DBGDUMPBYTES("ArapFrmLan: bcast pkt:",packet, LDDP_HDR_LEN+4,6);
  271. return;
  272. }
  273. }
  274. //
  275. // this is a unicast: see if this addr belongs to an ARAP client
  276. //
  277. else
  278. {
  279. DestNode.atn_Network = pDestAddr->ata_Network;
  280. DestNode.atn_Node = pDestAddr->ata_Node;
  281. pArapConn = FindAndRefArapConnByAddr(DestNode, &dwFlags);
  282. // no ARAP client for this dest. address? Done here
  283. if (pArapConn == NULL)
  284. {
  285. return;
  286. }
  287. if (!(dwFlags & ARAP_CONNECTION_UP))
  288. {
  289. DerefArapConn(pArapConn);
  290. return;
  291. }
  292. }
  293. // setup a buffer descriptor for the incoming packet
  294. InBuffDesc.bd_Next = NULL;
  295. InBuffDesc.bd_Length = PktLen;
  296. InBuffDesc.bd_CharBuffer = packet;
  297. InBuffDesc.bd_Flags = BD_CHAR_BUFFER;
  298. //
  299. // setup the header
  300. //
  301. pArapHdrPtr = &ArapHdr[0];
  302. // don't count the 2 length bytes
  303. SrpLen = PktLen + ARAP_LAP_HDRSIZE + ARAP_HDRSIZE - sizeof(USHORT);
  304. PUTSHORT2SHORT(pArapHdrPtr, SrpLen);
  305. pArapHdrPtr += sizeof(USHORT);
  306. // the Dgroup byte
  307. *pArapHdrPtr++ = (ARAP_SFLAG_PKT_DATA | ARAP_SFLAG_LAST_GROUP);
  308. // the LAP hdr
  309. *pArapHdrPtr++ = 0;
  310. *pArapHdrPtr++ = 0;
  311. *pArapHdrPtr++ = 2;
  312. // setup a buffer descriptor for the header we are going to put
  313. BuffDesc.bd_Next = &InBuffDesc;
  314. BuffDesc.bd_Length = ARAP_LAP_HDRSIZE + ARAP_HDRSIZE;
  315. BuffDesc.bd_CharBuffer = &ArapHdr[0];
  316. BuffDesc.bd_Flags = BD_CHAR_BUFFER;
  317. //
  318. // if this datagram is not a broadcast, see if we can find a dial-in client
  319. // with this destination address
  320. //
  321. if (!broadcast)
  322. {
  323. //
  324. // ok, we found a connection: whether or not we actually give data to
  325. // him, let the caller know that we found who this data was meant for
  326. //
  327. *pDelivered = TRUE;
  328. //
  329. // some packets can't be sent to the dial-in client: how about this one?
  330. //
  331. if (!ArapOkToForward(pArapConn,packet,PktLen, &Priority))
  332. {
  333. DerefArapConn(pArapConn);
  334. return;
  335. }
  336. DBGDUMPBYTES("ArapRoutePacketToWan Directed Dgram:",packet,PktLen,4);
  337. //
  338. // ok, this packet is for the dial-in guy: send it
  339. //
  340. StatusCode = ArapSendPrepare(pArapConn, &BuffDesc, Priority);
  341. if (StatusCode == ARAPERR_NO_ERROR)
  342. {
  343. // Send the packet(s)
  344. ArapNdisSend(pArapConn, &pArapConn->HighPriSendQ);
  345. }
  346. else
  347. {
  348. DBGPRINT(DBG_COMP_ROUTER, DBG_LEVEL_ERR,
  349. ("ArapRoutePacketToWan: (%lx) Prep failed %d\n",pArapConn,StatusCode));
  350. }
  351. // remove that refcount put in by FindAndRefArapConnByAddr
  352. DerefArapConn(pArapConn);
  353. return;
  354. }
  355. DBGDUMPBYTES("ArapRoutePacketToWan Broadcast Dgram:",packet,PktLen,4);
  356. //
  357. // it's a broadcast packet: must send it to all the dial-in guys
  358. //
  359. pArapConn = NULL;
  360. pPrevArapConn = NULL;
  361. while (1)
  362. {
  363. ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
  364. //
  365. // first, let's find the right connection to work on
  366. //
  367. while (1)
  368. {
  369. // if we're in the middle of the list, get to the next guy
  370. if (pArapConn != NULL)
  371. {
  372. pConnList = pArapConn->Linkage.Flink;
  373. }
  374. // we're just starting: get the guy at the head of the list
  375. else
  376. {
  377. pConnList = RasPortDesc->pd_ArapConnHead.Flink;
  378. }
  379. // finished all?
  380. if (pConnList == &RasPortDesc->pd_ArapConnHead)
  381. {
  382. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  383. if (pPrevArapConn)
  384. {
  385. DerefArapConn(pPrevArapConn);
  386. }
  387. return;
  388. }
  389. pArapConn = CONTAINING_RECORD(pConnList, ARAPCONN, Linkage);
  390. // make sure this connection needs rcv processing
  391. ACQUIRE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  392. //
  393. // if this connection is being disconnected, skip it
  394. //
  395. if (pArapConn->State >= MNP_LDISCONNECTING)
  396. {
  397. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_WARN,
  398. ("ArapRoutePacketToWan: (%lx) invalid state %d, skipping\n",
  399. pArapConn,pArapConn->State));
  400. RELEASE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  401. // go try the next connection
  402. continue;
  403. }
  404. // let's make sure this connection stays around till we finish
  405. pArapConn->RefCount++;
  406. RELEASE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  407. break;
  408. }
  409. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  410. //
  411. // remove the refcount on the previous connection we put in earlier
  412. //
  413. if (pPrevArapConn)
  414. {
  415. DerefArapConn(pPrevArapConn);
  416. }
  417. ASSERT(pPrevArapConn != pArapConn);
  418. pPrevArapConn = pArapConn;
  419. //
  420. // if the connection isn't up yet, don't forward this
  421. // (note that we don't hold spinlock here, this being a hot path:
  422. // the worst that can happen is we'll drop a broadcast: big deal!)
  423. //
  424. if (!(pArapConn->Flags & ARAP_CONNECTION_UP))
  425. {
  426. continue;
  427. }
  428. //
  429. // is it ok for us send this packet to this client ?
  430. //
  431. if (!ArapOkToForward(pArapConn,packet,PktLen, &Priority))
  432. {
  433. continue;
  434. }
  435. StatusCode = ArapSendPrepare(pArapConn, &BuffDesc, Priority);
  436. if (StatusCode == ARAPERR_NO_ERROR)
  437. {
  438. // Send the packet(s)
  439. ArapNdisSend(pArapConn, &pArapConn->HighPriSendQ);
  440. }
  441. else
  442. {
  443. DBGPRINT(DBG_COMP_ROUTER, DBG_LEVEL_ERR,
  444. ("Arap...FromLan: (%lx) Arap..Prep failed %d\n",pArapConn,StatusCode));
  445. }
  446. }
  447. }
  448. //***
  449. //
  450. // Function: ArapOkToForward
  451. // This routine checks to see if we can (or must) forward this
  452. // packet to the dial-in client. Certain packets (e.g. a bcast pkt
  453. // that originated from this client) shouldn't be sent back to the
  454. // client: this routine makes those checks.
  455. //
  456. // Parameters: pArapConn - the connection in question
  457. // packet - buffer containing the packet
  458. // packetLen - how big is the packet
  459. // pPriority - set on return:
  460. // 1 - all non-NBP data directed to this client
  461. // 2 - all NBP data directed to this client
  462. // 3 - all broadcast data
  463. //
  464. // Return: TRUE if it's ok to (or if we must!) forward the packet,
  465. // FALSE otherwise
  466. //
  467. //***$
  468. BOOLEAN
  469. ArapOkToForward(
  470. IN PARAPCONN pArapConn,
  471. IN PBYTE packet,
  472. IN USHORT packetLen,
  473. OUT DWORD *pPriority
  474. )
  475. {
  476. ATALK_NODEADDR NetAddr;
  477. BOOLEAN fBcastPkt=FALSE;
  478. BOOLEAN fNbpPkt=FALSE;
  479. DBG_ARAP_CHECK_PAGED_CODE();
  480. GETSHORT2SHORT(&NetAddr.atn_Network, &packet[LDDP_SRC_NETWORK_OFFSET]);
  481. NetAddr.atn_Node = packet[LDDP_SRC_NODE_OFFSET];
  482. //
  483. // packet has client's own addr as DDP src addr? if so, drop it
  484. //
  485. if (NODEADDR_EQUAL(&NetAddr, &pArapConn->NetAddr))
  486. {
  487. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO,
  488. ("ArapOkToForward: dropping pkt: DDP src=client's addr (%lx)\n",pArapConn));
  489. return(FALSE);
  490. }
  491. if (packet[LDDP_PROTO_TYPE_OFFSET] == DDPPROTO_NBP)
  492. {
  493. fNbpPkt = TRUE;
  494. }
  495. if (packet[LDDP_DEST_NODE_OFFSET] == ATALK_BROADCAST_NODE)
  496. {
  497. fBcastPkt = TRUE;
  498. //
  499. // is this an nbp query packet?
  500. //
  501. if (fNbpPkt && (packet[LDDP_DGRAM_OFFSET] == 0x21))
  502. {
  503. GETSHORT2SHORT(&NetAddr.atn_Network, &packet[15]);
  504. NetAddr.atn_Node = packet[17];
  505. // originated from the client? if so, we shouldn't return this!
  506. if (NODEADDR_EQUAL(&NetAddr, &pArapConn->NetAddr))
  507. {
  508. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO,
  509. ("ArapOkToForward: dropping pkt originating from client!\n"));
  510. return(FALSE);
  511. }
  512. }
  513. }
  514. //
  515. // if this is a broadcast packet, then we drop it under certain conditions:
  516. // (no need for spinlock here: if we make a wrong decision, no big deal)
  517. //
  518. if (fBcastPkt)
  519. {
  520. // are in currently in the retransmit mode? if so, drop this bcast pkt
  521. if (pArapConn->MnpState.RetransmitMode)
  522. {
  523. return(FALSE);
  524. }
  525. //
  526. // queue getting full? drop this broadcast packet to make room for more
  527. // important pkts
  528. //
  529. if (pArapConn->SendsPending >= ARAP_SENDQ_LOWER_LIMIT)
  530. {
  531. // make sure it's not gone negative..
  532. ASSERT(pArapConn->SendsPending < 0x100000);
  533. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  534. ("ArapOkToForward: (%lx) send getting full (%ld), dropping nbp pkt\n",
  535. pArapConn,pArapConn->SendsPending));
  536. return(FALSE);
  537. }
  538. }
  539. //
  540. // now that we are forwarding the packet to the client, set the priority
  541. // right. All broadcast packets are lowest priority, no big deal if they are
  542. // delivered late (or never). Nbp packets are usually for chooser: put them
  543. // after the directed data packets
  544. //
  545. if (fBcastPkt)
  546. {
  547. *pPriority = ARAP_SEND_PRIORITY_LOW;
  548. }
  549. else if (fNbpPkt)
  550. {
  551. *pPriority = ARAP_SEND_PRIORITY_MED;
  552. }
  553. else
  554. {
  555. *pPriority = ARAP_SEND_PRIORITY_HIGH;
  556. }
  557. return(TRUE);
  558. }
  559. //***
  560. //
  561. // Function: ArapGetDynamicAddr
  562. // This routine gets a network address for a dial-in client.
  563. // It does the same AARP logic as if it were acquiring a
  564. // node-address for the host itself.
  565. // This routine is called only if we are in the dynamic mode.
  566. //
  567. // Parameters: pArapConn - the connection for which we need a network addr
  568. //
  569. // Return: ARAPERR_NO_ERROR if all went well.
  570. //
  571. //***$
  572. DWORD
  573. ArapGetDynamicAddr(
  574. IN PARAPCONN pArapConn
  575. )
  576. {
  577. ATALK_NODEADDR NetAddr;
  578. ATALK_NETWORKRANGE NetRange;
  579. BOOLEAN fFound=FALSE;
  580. KIRQL OldIrql;
  581. DWORD StatusCode=ARAPERR_STACK_NOT_UP;
  582. DBG_ARAP_CHECK_PAGED_CODE();
  583. ASSERT(AtalkDefaultPort != NULL);
  584. //
  585. // go find a node address on the default port (we'll never get this far if
  586. // default port isn't up yet)
  587. //
  588. ACQUIRE_SPIN_LOCK(&pArapConn->SpinLock, &OldIrql);
  589. ASSERT(!(pArapConn->Flags & ARAP_FINDING_NODE));
  590. pArapConn->Flags |= ARAP_FINDING_NODE;
  591. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  592. AtalkLockInitIfNecessary();
  593. // if we are stuck in the startup range, use that range for dial-in guys, too
  594. if (WITHIN_NETWORK_RANGE(AtalkDefaultPort->pd_NetworkRange.anr_LastNetwork,
  595. &AtalkStartupNetworkRange))
  596. {
  597. NetRange = AtalkStartupNetworkRange;
  598. }
  599. else
  600. {
  601. NetRange = AtalkDefaultPort->pd_NetworkRange;
  602. }
  603. fFound = AtalkInitAarpForNodeInRange(AtalkDefaultPort,
  604. (PVOID)pArapConn,
  605. FALSE,
  606. NetRange,
  607. &NetAddr);
  608. AtalkUnlockInitIfNecessary();
  609. ACQUIRE_SPIN_LOCK(&pArapConn->SpinLock, &OldIrql);
  610. pArapConn->Flags &= ~ARAP_FINDING_NODE;
  611. if (fFound)
  612. {
  613. // store that adddr!
  614. pArapConn->NetAddr.atn_Network = NetAddr.atn_Network;
  615. pArapConn->NetAddr.atn_Node = NetAddr.atn_Node;
  616. pArapConn->Flags |= ARAP_NODE_IN_USE;
  617. StatusCode = ARAPERR_NO_ERROR;
  618. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO,
  619. ("ArapGetDynamicAddr: found addr for ARAP client = %lx %lx\n",
  620. NetAddr.atn_Network,NetAddr.atn_Node));
  621. }
  622. else
  623. {
  624. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  625. ("ArapGetDynamicAddr: ARAP: no more network addr left?\n"));
  626. pArapConn->Flags &= ~ARAP_NODE_IN_USE;
  627. pArapConn->NetAddr.atn_Network = 0;
  628. pArapConn->NetAddr.atn_Node = 0;
  629. StatusCode = ARAPERR_NO_NETWORK_ADDR;
  630. }
  631. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  632. return(StatusCode);
  633. }
  634. //***
  635. //
  636. // Function: ArapZipGetZoneStat
  637. // This routine is called to find out the names (or number) of all
  638. // the zones on the network.
  639. //
  640. // Parameters: pZoneStat - on return, we fill this structure in with the
  641. // requested info (number and/or names of all the zones)
  642. // Request - caller wants just the number of zones or names, too
  643. //
  644. // Return: Nothing
  645. //
  646. //***$
  647. VOID
  648. ArapZipGetZoneStat(
  649. IN OUT PZONESTAT pZoneStat
  650. )
  651. {
  652. int i;
  653. PZONE pZone;
  654. DWORD NumZones;
  655. DWORD StatusCode;
  656. KIRQL OldIrql;
  657. PBYTE pBufPtr;
  658. PBYTE pAllocedBuf=NULL;
  659. DWORD BufferSize;
  660. DWORD BytesCopied;
  661. DWORD BytesNeeded;
  662. ATALK_ERROR Status;
  663. PZIPCOMPLETIONINFO pZci;
  664. PMDL pMdl=NULL;
  665. ACTREQ ActReq;
  666. ZIP_GETZONELIST_PARAMS ZipParms;
  667. KEVENT ZoneComplEvent;
  668. DBG_ARAP_CHECK_PAGED_CODE();
  669. BufferSize = pZoneStat->BufLen;
  670. pBufPtr = &pZoneStat->ZoneNames[0];
  671. StatusCode = ARAPERR_NO_ERROR;
  672. BytesCopied = 0;
  673. NumZones = 0;
  674. if (AtalkDefaultPort->pd_Flags & PD_ROUTER_RUNNING)
  675. {
  676. BytesNeeded = 0;
  677. ACQUIRE_SPIN_LOCK(&AtalkZoneLock, &OldIrql);
  678. for (i = 0; (i < NUM_ZONES_HASH_BUCKETS); i++)
  679. {
  680. for (pZone = AtalkZonesTable[i]; pZone != NULL; pZone = pZone->zn_Next)
  681. {
  682. NumZones++;
  683. BytesNeeded += (pZone->zn_ZoneLen + 1);
  684. // if there is room, copy it in
  685. if (BufferSize >= BytesNeeded)
  686. {
  687. RtlCopyMemory(pBufPtr,
  688. &pZone->zn_Zone[0],
  689. pZone->zn_ZoneLen);
  690. pBufPtr += pZone->zn_ZoneLen;
  691. *pBufPtr++ = '\0';
  692. BytesCopied += (pZone->zn_ZoneLen + 1);
  693. }
  694. else
  695. {
  696. StatusCode = ARAPERR_BUF_TOO_SMALL;
  697. break;
  698. }
  699. }
  700. }
  701. RELEASE_SPIN_LOCK(&AtalkZoneLock, OldIrql);
  702. }
  703. //
  704. // we are not a router: send the request over to the A-router
  705. //
  706. else
  707. {
  708. BytesNeeded = BufferSize;
  709. pMdl = AtalkAllocAMdl(pBufPtr,BufferSize);
  710. if (pMdl == NULL)
  711. {
  712. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  713. ("ArapZipGetZoneStat: couldn't allocate Mdl\n"));
  714. StatusCode = ARAPERR_OUT_OF_RESOURCES;
  715. goto ArapZipGetZoneStat_Exit;
  716. }
  717. KeInitializeEvent(&ZoneComplEvent, NotificationEvent, FALSE);
  718. pZci = (PZIPCOMPLETIONINFO)AtalkAllocMemory(sizeof(ZIPCOMPLETIONINFO));
  719. if (pZci == NULL)
  720. {
  721. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  722. ("ArapZipGetZoneStat: couldn't allocate pZci\n"));
  723. StatusCode = ARAPERR_OUT_OF_RESOURCES;
  724. goto ArapZipGetZoneStat_Exit;
  725. }
  726. ZipParms.ZonesAvailable = 0;
  727. ActReq.ar_StatusCode = ARAPERR_NO_ERROR;
  728. #if DBG
  729. ActReq.ar_Signature = ACTREQ_SIGNATURE;
  730. #endif
  731. ActReq.ar_pIrp = NULL;
  732. ActReq.ar_pParms = &ZipParms;
  733. ActReq.ar_pAMdl = NULL;
  734. ActReq.ar_MdlSize = 0;
  735. ActReq.ar_ActionCode = 0;
  736. ActReq.ar_DevType = 0;
  737. ActReq.ar_Completion = ArapZipGetZoneStatCompletion;
  738. ActReq.ar_CmplEvent = &ZoneComplEvent;
  739. ActReq.ar_pZci = (PVOID)pZci;
  740. // Initialize completion info
  741. #if DBG
  742. pZci->zci_Signature = ZCI_SIGNATURE;
  743. #endif
  744. INITIALIZE_SPIN_LOCK(&pZci->zci_Lock);
  745. pZci->zci_RefCount = 1;
  746. pZci->zci_pPortDesc = AtalkDefaultPort;
  747. pZci->zci_pDdpAddr = NULL;
  748. pZci->zci_pAMdl = pMdl;
  749. pZci->zci_BufLen = BufferSize;
  750. pZci->zci_pActReq = &ActReq;
  751. pZci->zci_Router.ata_Network = AtalkDefaultPort->pd_ARouter.atn_Network;
  752. pZci->zci_Router.ata_Node = AtalkDefaultPort->pd_ARouter.atn_Node;
  753. pZci->zci_Router.ata_Socket = ZONESINFORMATION_SOCKET;
  754. pZci->zci_ExpirationCount = ZIP_GET_ZONEINFO_RETRIES;
  755. pZci->zci_NextZoneOff = 0;
  756. pZci->zci_ZoneCount = 0;
  757. pZci->zci_AtpRequestType = ZIP_GET_ZONE_LIST;
  758. AtalkTimerInitialize(&pZci->zci_Timer,
  759. atalkZipZoneInfoTimer,
  760. ZIP_GET_ZONEINFO_TIMER);
  761. pZci->zci_Handler = atalkZipGetZoneListReply;
  762. // completion routine will unlock
  763. AtalkLockZipIfNecessary();
  764. Status = atalkZipSendPacket(pZci, TRUE);
  765. if (!ATALK_SUCCESS(Status))
  766. {
  767. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  768. ("ArapZipGetZoneStat: atalkZipSendPacket failed %ld\n", Status));
  769. pZci->zci_FinalStatus = Status;
  770. atalkZipDereferenceZci(pZci);
  771. }
  772. KeWaitForSingleObject(&ZoneComplEvent,
  773. Executive,
  774. KernelMode,
  775. FALSE,
  776. NULL);
  777. NumZones = ZipParms.ZonesAvailable;
  778. StatusCode = ActReq.ar_StatusCode;
  779. if (StatusCode == ARAPERR_BUF_TOO_SMALL)
  780. {
  781. BytesNeeded = (2*BufferSize);
  782. }
  783. BytesCopied = BufferSize;
  784. AtalkFreeAMdl(pMdl);
  785. }
  786. ArapZipGetZoneStat_Exit:
  787. pZoneStat->NumZones = NumZones;
  788. pZoneStat->BufLen = BytesCopied;
  789. pZoneStat->BytesNeeded = BytesNeeded;
  790. pZoneStat->StatusCode = StatusCode;
  791. }
  792. //***
  793. //
  794. // Function: ArapZipGetZoneStatCompletion
  795. // This routine is the completion routine: after we get all the
  796. // responses for the zone query, this gets called. Simply set an
  797. // event so the caller is unblocked
  798. //
  799. // Parameters: pActReq - context
  800. //
  801. // Return: Nothing
  802. //
  803. //***$
  804. VOID
  805. ArapZipGetZoneStatCompletion(
  806. IN ATALK_ERROR ErrorCode,
  807. IN PACTREQ pActReq
  808. )
  809. {
  810. PKEVENT pEvent;
  811. PZIPCOMPLETIONINFO pZci;
  812. DBG_ARAP_CHECK_PAGED_CODE();
  813. if (ErrorCode != ATALK_NO_ERROR && ErrorCode != ATALK_BUFFER_TOO_SMALL)
  814. {
  815. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  816. ("ArapZipGetZoneStatCompletion: failure %lx\n", ErrorCode));
  817. }
  818. pZci = (PZIPCOMPLETIONINFO)(pActReq->ar_pZci);
  819. pEvent = pActReq->ar_CmplEvent;
  820. ASSERT((pZci->zci_FinalStatus == ATALK_NO_ERROR) ||
  821. (pZci->zci_FinalStatus == ATALK_BUFFER_TOO_SMALL));
  822. if (pZci->zci_FinalStatus == ATALK_NO_ERROR)
  823. {
  824. pActReq->ar_StatusCode = ARAPERR_NO_ERROR;
  825. }
  826. else if (pZci->zci_FinalStatus == ATALK_BUFFER_TOO_SMALL)
  827. {
  828. pActReq->ar_StatusCode = ARAPERR_BUF_TOO_SMALL;
  829. }
  830. else
  831. {
  832. pActReq->ar_StatusCode = ARAPERR_UNEXPECTED_RESPONSE;
  833. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  834. ("ArapZipGetZoneStat: failure %lx\n", pZci->zci_FinalStatus));
  835. }
  836. KeSetEvent(pEvent,IO_NETWORK_INCREMENT,FALSE);
  837. }
  838. #if ARAP_STATIC_MODE
  839. //***
  840. //
  841. // Function: ArapGetStaticAddr
  842. // Get a network address for the remote client when we are
  843. // configured for static addressing
  844. // We represent every client as one bit: if the bit is on, the
  845. // corresponding address is taken, otherwise it's free.
  846. // So, 255 clients represented using 32 bytes. Each pAddrMgmt
  847. // block represents 255 clients (scalability not a problem here!)
  848. //
  849. // Parameters: pArapConn - connection element for the remote client in question
  850. //
  851. // Return: status of the operation (ARAPERR_....)
  852. //
  853. //***$
  854. DWORD
  855. ArapGetStaticAddr(
  856. IN PARAPCONN pArapConn
  857. )
  858. {
  859. KIRQL OldIrql;
  860. PADDRMGMT pAddrMgmt;
  861. PADDRMGMT pPrevAddrMgmt;
  862. USHORT Network;
  863. BYTE Node;
  864. BOOLEAN found=FALSE;
  865. BYTE BitMask;
  866. DWORD i;
  867. DBG_ARAP_CHECK_PAGED_CODE();
  868. ARAPTRACE(("Entered ArapGetStaticAddr (%lx)\n",pArapConn));
  869. ACQUIRE_SPIN_LOCK(&ArapSpinLock, &OldIrql);
  870. pAddrMgmt = ArapGlobs.pAddrMgmt;
  871. while (1)
  872. {
  873. Network = pAddrMgmt->Network;
  874. // see if there is any open slot. 255 nodes represented by 32x8 bits
  875. for (i=0; i<32; i++)
  876. {
  877. if (pAddrMgmt->NodeBitMap[i] != 0xff)
  878. {
  879. found = TRUE;
  880. break;
  881. }
  882. }
  883. if (found)
  884. {
  885. // find out the first bit in this byte that is off
  886. BitMask = 0x1;
  887. Node = 0;
  888. while (pAddrMgmt->NodeBitMap[i] & BitMask)
  889. {
  890. BitMask <<= 1;
  891. Node += 1;
  892. }
  893. // we are taking this node: set that bit!
  894. pAddrMgmt->NodeBitMap[i] |= BitMask;
  895. // now, account for all the previous bytes that were full
  896. Node += (BYTE)(i*8);
  897. break;
  898. }
  899. // all the nodes on this network are taken! move to the next network
  900. pPrevAddrMgmt = pAddrMgmt;
  901. pAddrMgmt = pAddrMgmt->Next;
  902. // looks like we need to allocate the next network structure
  903. if (pAddrMgmt == NULL)
  904. {
  905. //
  906. // we just finished looking at the high end of the permissible network
  907. // range? well, out of luck then!
  908. //
  909. if (Network == ArapGlobs.NetRange.HighEnd)
  910. {
  911. RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
  912. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  913. ("ArapGetStaticAddr: no more network addr left\n"));
  914. return(ARAPERR_NO_NETWORK_ADDR);
  915. }
  916. if ( (pAddrMgmt = AtalkAllocZeroedMemory(sizeof(ADDRMGMT))) == NULL)
  917. {
  918. RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
  919. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  920. ("ArapGetStaticAddr: alloc failed\n"));
  921. return(ARAPERR_OUT_OF_RESOURCES);
  922. }
  923. Network++;
  924. pAddrMgmt->Next = NULL;
  925. pAddrMgmt->Network = Network;
  926. pPrevAddrMgmt->Next = pAddrMgmt;
  927. Node = 1;
  928. //
  929. // node numbers 0 and 255 are reserved, so mark them as occupied.
  930. // Also, we just took node 1, so mark that as well
  931. //
  932. pAddrMgmt->NodeBitMap[0] |= (0x1 | 0x2);
  933. pAddrMgmt->NodeBitMap[31] |= 0x80;
  934. break;
  935. }
  936. }
  937. RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
  938. // store that adddr!
  939. ACQUIRE_SPIN_LOCK(&pArapConn->SpinLock, &OldIrql);
  940. pArapConn->NetAddr.atn_Network = Network;
  941. pArapConn->NetAddr.atn_Node = Node;
  942. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  943. return( ARAPERR_NO_ERROR );
  944. }
  945. //***
  946. //
  947. // Function: ArapAddArapRoute
  948. // If we are in the static mode of network address allocation, we
  949. // need to add a route in our table corresponding to the network
  950. // range allocated for the dial-in clients.
  951. // This routine does that. In case of dynamic mode, it's a no-op.
  952. // This is a one-time thing, and we only do it when the first
  953. // connection comes in (instead of doing at startup).
  954. //
  955. // Parameters: None
  956. //
  957. // Return: None
  958. //
  959. //***$
  960. VOID
  961. ArapAddArapRoute(
  962. IN VOID
  963. )
  964. {
  965. ATALK_NETWORKRANGE NwRange;
  966. KIRQL OldIrql;
  967. BOOLEAN fAddRoute = FALSE;
  968. DBG_ARAP_CHECK_PAGED_CODE();
  969. //
  970. // add a route only if router is enabled, and we are in the Static mode of
  971. // network allocation, and we haven't already added it
  972. //
  973. ACQUIRE_SPIN_LOCK(&ArapSpinLock, &OldIrql);
  974. if ((AtalkDefaultPort->pd_Flags & PD_ROUTER_RUNNING) &&
  975. (!ArapGlobs.DynamicMode) &&
  976. (!ArapGlobs.RouteAdded))
  977. {
  978. ArapGlobs.RouteAdded = TRUE;
  979. fAddRoute = TRUE;
  980. ASSERT(ArapConnections >= 1);
  981. }
  982. RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
  983. if (fAddRoute)
  984. {
  985. NwRange.anr_FirstNetwork = ArapGlobs.NetRange.LowEnd;
  986. NwRange.anr_LastNetwork = ArapGlobs.NetRange.HighEnd;
  987. atalkRtmpCreateRte(NwRange,
  988. RasPortDesc,
  989. &AtalkDefaultPort->pd_Nodes->an_NodeAddr,
  990. 0);
  991. }
  992. }
  993. //***
  994. //
  995. // Function: ArapDeleteArapRoute
  996. // If there is a routine called ArapAddArapRoute, we have got to
  997. // have a routine called ArapDeleteArapRoute.
  998. //
  999. // Parameters: None
  1000. //
  1001. // Return: None
  1002. //
  1003. //***$
  1004. VOID
  1005. ArapDeleteArapRoute(
  1006. IN VOID
  1007. )
  1008. {
  1009. KIRQL OldIrql;
  1010. BOOLEAN fDeleteRoute = FALSE;
  1011. DBG_ARAP_CHECK_PAGED_CODE();
  1012. //
  1013. // delete a route only if added it earlier and the connections went to 0
  1014. //
  1015. ACQUIRE_SPIN_LOCK(&ArapSpinLock, &OldIrql);
  1016. if (ArapGlobs.RouteAdded && ArapConnections == 0)
  1017. {
  1018. ArapGlobs.RouteAdded = FALSE;
  1019. fDeleteRoute = TRUE;
  1020. }
  1021. RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
  1022. if (fDeleteRoute)
  1023. {
  1024. atalkRtmpRemoveRte(ArapGlobs.NetRange.LowEnd);
  1025. }
  1026. }
  1027. //***
  1028. //
  1029. // Function: ArapValidNetrange
  1030. // This routine is called if we configured to be in the static
  1031. // mode of addr allocation, when the dll first "binds" to us.
  1032. // It verifies that the network range allocated by the admin is
  1033. // valid and doesn't overlap with any of the network ranges known
  1034. // to us through the route table.
  1035. //
  1036. // Parameters: NetRange - the network range configured for dial-in clients
  1037. //
  1038. // Return: TRUE if the range is valid,
  1039. // FALSE if it overlaps with any of the existing network ranges
  1040. //
  1041. //***$
  1042. BOOLEAN
  1043. ArapValidNetrange(
  1044. IN NETWORKRANGE NetRange
  1045. )
  1046. {
  1047. BOOLEAN fRangeIsValid=TRUE;
  1048. KIRQL OldIrql;
  1049. PRTE pRte, pNext;
  1050. int i;
  1051. DBG_ARAP_CHECK_PAGED_CODE();
  1052. if (NetRange.LowEnd == 0 || NetRange.HighEnd == 0)
  1053. {
  1054. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1055. ("ArapValidNetrange: Invalid network range\n"));
  1056. #if DBG
  1057. DbgDumpNetworkNumbers();
  1058. #endif
  1059. return(FALSE);
  1060. }
  1061. fRangeIsValid = TRUE;
  1062. ACQUIRE_SPIN_LOCK(&AtalkRteLock, &OldIrql);
  1063. for (i = 0; i < NUM_RTMP_HASH_BUCKETS; i++)
  1064. {
  1065. for (pRte = AtalkRoutingTable[i]; pRte != NULL; pRte = pNext)
  1066. {
  1067. pNext = pRte->rte_Next;
  1068. ACQUIRE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  1069. if ( (IN_NETWORK_RANGE(NetRange.LowEnd,pRte)) ||
  1070. (IN_NETWORK_RANGE(NetRange.HighEnd,pRte)) )
  1071. {
  1072. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1073. ("ArapValidNetrange: range in conflict\n"));
  1074. fRangeIsValid = FALSE;
  1075. RELEASE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  1076. break;
  1077. }
  1078. RELEASE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  1079. }
  1080. if (!fRangeIsValid)
  1081. {
  1082. break;
  1083. }
  1084. }
  1085. RELEASE_SPIN_LOCK(&AtalkRteLock, OldIrql);
  1086. #if DBG
  1087. if (!fRangeIsValid)
  1088. {
  1089. DbgDumpNetworkNumbers();
  1090. }
  1091. #endif
  1092. return(fRangeIsValid);
  1093. }
  1094. #endif //ARAP_STATIC_MODE