Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

977 lines
19 KiB

  1. /*++
  2. Copyright (c) 1990-1998 Microsoft Corporation, All Rights Reserved.
  3. Module Name:
  4. atmsmapp.c
  5. Abstract:
  6. This is the user mode app that controls the sample ATM client.
  7. It can be used for
  8. 1. Starting / Stopping the driver.
  9. 2. Sending to one (point - point) or more (PMP) destinations.
  10. 3. Receive packets that come on any VC to our SAP.
  11. Author:
  12. Anil Francis Thomas (10/98)
  13. Environment:
  14. User mode
  15. Revision History:
  16. --*/
  17. #include <windows.h>
  18. #include <winioctl.h>
  19. #include <tchar.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <assert.h>
  23. #include "atmsample.h"
  24. #include "utils.h"
  25. #include "atmsmapp.h"
  26. PROGRAM_OPTIONS g_ProgramOptions;
  27. int __cdecl main(int argc, char *argv[])
  28. {
  29. DWORD dwRetVal = NO_ERROR;
  30. memset(&g_ProgramOptions, 0, sizeof(PROGRAM_OPTIONS));
  31. g_ProgramOptions.dwPktSize = DEFAULT_PKT_SIZE;
  32. g_ProgramOptions.dwPktInterval = DEFAULT_PKT_INTERVAL;
  33. g_ProgramOptions.dwNumPkts = DEFAULT_NUM_OF_PKTS;
  34. // parse the command line parameters
  35. if((argc < 2) || (FALSE == ParseCommandLine(argc, argv)))
  36. {
  37. Usage();
  38. return 1;
  39. }
  40. // Is any driver option specified - start, stop etc
  41. if(g_ProgramOptions.usDrvAction)
  42. {
  43. switch(g_ProgramOptions.usDrvAction)
  44. {
  45. case START_DRV:
  46. dwRetVal = AtmSmDriverStart();
  47. if(NO_ERROR != dwRetVal)
  48. {
  49. printf("Failed to start driver. Error %u\n",
  50. dwRetVal);
  51. }
  52. else
  53. printf("Successfully started the driver.\n");
  54. break;
  55. case STOP_DRV:
  56. dwRetVal = AtmSmDriverStop();
  57. if(NO_ERROR != dwRetVal)
  58. {
  59. printf("Failed to stop driver. Error %u\n",
  60. dwRetVal);
  61. return 1;
  62. }
  63. else
  64. {
  65. printf("Successfully stopped the driver.\n");
  66. return 0; // we are done
  67. }
  68. break;
  69. }
  70. }
  71. if(NO_ERROR != dwRetVal)
  72. return dwRetVal;
  73. do
  74. { // break off loop
  75. dwRetVal = AtmSmOpenDriver(&g_ProgramOptions.hDriver);
  76. if(NO_ERROR != dwRetVal)
  77. break;
  78. // enumerate the interfaces
  79. if(g_ProgramOptions.fEnumInterfaces)
  80. EnumerateInterfaces();
  81. if(g_ProgramOptions.fLocalIntf)
  82. printf("\nLocal Interface Address - %s\n",
  83. FormatATMAddr(g_ProgramOptions.ucLocalIntf));
  84. if(g_ProgramOptions.dwNumDsts)
  85. {
  86. DWORD dw;
  87. printf("\nDestinations specified : %u\n",
  88. g_ProgramOptions.dwNumDsts);
  89. for(dw = 0; dw < g_ProgramOptions.dwNumDsts; dw++)
  90. printf(" %u - %s\n", dw+1,
  91. FormatATMAddr(g_ProgramOptions.ucDstAddrs[dw]));
  92. }
  93. if(g_ProgramOptions.usSendRecvAction && !g_ProgramOptions.fLocalIntf)
  94. {
  95. // for sends and recv we need a local intf
  96. printf("Error! Specify a local interface to send and recv\n");
  97. dwRetVal = 1;
  98. break;
  99. }
  100. if((SEND_PKTS == g_ProgramOptions.usSendRecvAction)
  101. && !g_ProgramOptions.dwNumDsts)
  102. {
  103. // for sends and recv we need a local intf
  104. printf("Error! Specify destination address(s) to send packets\n");
  105. dwRetVal = 1;
  106. break;
  107. }
  108. // Set the Cntrl - C Handler
  109. SetConsoleCtrlHandler(CtrlCHandler, TRUE);
  110. if(SEND_PKTS == g_ProgramOptions.usSendRecvAction)
  111. dwRetVal = DoSendPacketsToDestinations();
  112. else
  113. if(RECEIVE_PKTS == g_ProgramOptions.usSendRecvAction)
  114. dwRetVal = DoRecvPacketsOnAdapter();
  115. }while(FALSE);
  116. if(NULL != g_ProgramOptions.hDriver)
  117. AtmSmCloseDriver(g_ProgramOptions.hDriver);
  118. return(int)dwRetVal;
  119. }
  120. void EnumerateInterfaces()
  121. /*++
  122. Routine Description:
  123. Enumerate all the adapters that the driver is bound to. You get the
  124. NSAP addresses for these interfaces.
  125. Arguments:
  126. NONE
  127. Return Value:
  128. NONE
  129. --*/
  130. {
  131. DWORD dw, dwRetVal, dwSize;
  132. PADAPTER_INFO pAI;
  133. dwSize = sizeof(ADAPTER_INFO) + (sizeof(UCHAR) * 5 * NSAP_ADDRESS_LEN);
  134. pAI = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
  135. if(!pAI)
  136. {
  137. printf("Error not enough memory\n");
  138. return;
  139. }
  140. do
  141. { // break off loop
  142. dwRetVal = AtmSmEnumerateAdapters(
  143. g_ProgramOptions.hDriver,
  144. pAI,
  145. &dwSize);
  146. if(NO_ERROR != dwRetVal)
  147. {
  148. printf("Failed to enumerate adapters. Error - %u\n",
  149. dwRetVal);
  150. break;
  151. }
  152. printf("\nNumber of adapters - %u\n", pAI->ulNumAdapters);
  153. for(dw = 0; dw < pAI->ulNumAdapters; dw++)
  154. {
  155. printf(" Adapter [%u] - %s\n", dw+1,
  156. FormatATMAddr(pAI->ucLocalATMAddr[dw]));
  157. }
  158. }while(FALSE);
  159. HeapFree(GetProcessHeap(), 0, pAI);
  160. return;
  161. }
  162. DWORD DoSendPacketsToDestinations()
  163. /*++
  164. Routine Description:
  165. This routine does the sending of packets to one or more destinations.
  166. First a connect call is made to get a handle. That handle is used for
  167. further sends.
  168. Arguments:
  169. NONE
  170. Return Value:
  171. Status
  172. --*/
  173. {
  174. DWORD dw, dwSize;
  175. PCONNECT_INFO pCI;
  176. OVERLAPPED Overlapped;
  177. BOOL bResult;
  178. DWORD dwReturnBytes;
  179. PUCHAR pBuffer = NULL;
  180. DWORD dwStatus = NO_ERROR;
  181. memset(&Overlapped, 0, sizeof(OVERLAPPED));
  182. dwSize = sizeof(CONNECT_INFO) + (sizeof(UCHAR) *
  183. g_ProgramOptions.dwNumDsts * NSAP_ADDRESS_LEN);
  184. pCI = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
  185. if(!pCI)
  186. {
  187. printf("Error not enough memory\n");
  188. return ERROR_NOT_ENOUGH_MEMORY;
  189. }
  190. pCI->bPMP = g_ProgramOptions.fPMP;
  191. pCI->ulNumDsts = g_ProgramOptions.dwNumDsts;
  192. memcpy(pCI->ucLocalATMAddr, g_ProgramOptions.ucLocalIntf,
  193. (sizeof(UCHAR) * NSAP_ADDR_LEN));
  194. for(dw = 0; dw < g_ProgramOptions.dwNumDsts; dw++)
  195. memcpy(pCI->ucDstATMAddrs[dw], g_ProgramOptions.ucDstAddrs[dw],
  196. (sizeof(UCHAR) * NSAP_ADDR_LEN));
  197. do
  198. { // break off loop
  199. Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  200. if(NULL == Overlapped.hEvent)
  201. {
  202. dwStatus = GetLastError();
  203. printf("Failed to create event. Error %u\n", dwStatus);
  204. break;
  205. }
  206. dwReturnBytes = 0;
  207. // Initiate a connection to destinations
  208. bResult = DeviceIoControl(
  209. g_ProgramOptions.hDriver,
  210. (ULONG)IOCTL_CONNECT_TO_DSTS,
  211. pCI,
  212. dwSize,
  213. &g_ProgramOptions.hSend,
  214. sizeof(HANDLE),
  215. &dwReturnBytes,
  216. &Overlapped);
  217. if(!bResult)
  218. {
  219. dwStatus = GetLastError();
  220. if(ERROR_IO_PENDING != dwStatus)
  221. {
  222. printf("Failed to connect to destinations. Error %u\n",
  223. dwStatus);
  224. break;
  225. }
  226. // the operation is pending
  227. bResult = GetOverlappedResult(
  228. g_ProgramOptions.hDriver,
  229. &Overlapped,
  230. &dwReturnBytes,
  231. TRUE
  232. );
  233. if(!bResult)
  234. {
  235. dwStatus = GetLastError();
  236. printf("Wait for connection to complete failed. Error - %u\n",
  237. dwStatus);
  238. break;
  239. }
  240. }
  241. // successfully connected
  242. printf("Successfully connected to destination(s) - Handle - 0x%p\n",
  243. g_ProgramOptions.hSend);
  244. // allocate a buffer to send
  245. dwSize = g_ProgramOptions.dwPktSize;
  246. pBuffer = HeapAlloc(GetProcessHeap(), 0, dwSize);
  247. if(!pBuffer)
  248. {
  249. printf("Error not enough memory\n");
  250. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  251. break;
  252. }
  253. FillPattern(pBuffer, dwSize);
  254. // do the number of sends that were asked to do
  255. for(dw = 0; dw < g_ProgramOptions.dwNumPkts; dw++)
  256. {
  257. ResetEvent(Overlapped.hEvent);
  258. dwReturnBytes = 0;
  259. bResult = DeviceIoControl(
  260. g_ProgramOptions.hDriver,
  261. (ULONG)IOCTL_SEND_TO_DSTS,
  262. &g_ProgramOptions.hSend,
  263. sizeof(HANDLE),
  264. pBuffer, //Note! the buffer given here
  265. dwSize, //Note! the size given here
  266. &dwReturnBytes,
  267. &Overlapped);
  268. if(!bResult)
  269. {
  270. dwStatus = GetLastError();
  271. if(ERROR_IO_PENDING != dwStatus)
  272. {
  273. printf("Failed to do sends to destinations. Error %u\n",
  274. dwStatus);
  275. break;
  276. }
  277. // the operation is pending
  278. bResult = GetOverlappedResult(
  279. g_ProgramOptions.hDriver,
  280. &Overlapped,
  281. &dwReturnBytes,
  282. TRUE
  283. );
  284. if(!bResult)
  285. {
  286. dwStatus = GetLastError();
  287. printf("Wait for send to complete failed. Error - %u\n",
  288. dwStatus);
  289. break;
  290. }
  291. printf("Successfully send packet number %u\n", dw+1);
  292. Sleep(g_ProgramOptions.dwPktInterval);
  293. }
  294. }
  295. } while(FALSE);
  296. if(g_ProgramOptions.hSend)
  297. {
  298. CloseConnectHandle(&Overlapped);
  299. g_ProgramOptions.hSend = NULL;
  300. }
  301. if(pCI)
  302. HeapFree(GetProcessHeap(), 0, pCI);
  303. if(pBuffer)
  304. HeapFree(GetProcessHeap(), 0, pBuffer);
  305. if(Overlapped.hEvent)
  306. CloseHandle(Overlapped.hEvent);
  307. return dwStatus;
  308. }
  309. DWORD DoRecvPacketsOnAdapter()
  310. /*++
  311. Routine Description:
  312. This routine is used to receive packets that come to our SAP on any VCs.
  313. Note: Only one recv can pend at a time.
  314. Arguments:
  315. NONE
  316. Return Value:
  317. Status
  318. --*/
  319. {
  320. DWORD dw, dwSize;
  321. POPEN_FOR_RECV_INFO pORI;
  322. OVERLAPPED Overlapped;
  323. BOOL bResult;
  324. DWORD dwReturnBytes;
  325. PUCHAR pBuffer = NULL;
  326. DWORD dwStatus = NO_ERROR;
  327. memset(&Overlapped, 0, sizeof(OVERLAPPED));
  328. dwSize = sizeof(OPEN_FOR_RECV_INFO);
  329. pORI = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
  330. if(!pORI)
  331. {
  332. printf("Error not enough memory\n");
  333. return ERROR_NOT_ENOUGH_MEMORY;
  334. }
  335. memcpy(pORI->ucLocalATMAddr, g_ProgramOptions.ucLocalIntf,
  336. (sizeof(UCHAR) * NSAP_ADDR_LEN));
  337. do
  338. { // break off loop
  339. Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  340. if(NULL == Overlapped.hEvent)
  341. {
  342. dwStatus = GetLastError();
  343. printf("Failed to create event. Error %u\n", dwStatus);
  344. break;
  345. }
  346. dwReturnBytes = 0;
  347. // Open the adapter for recvs
  348. bResult = DeviceIoControl(
  349. g_ProgramOptions.hDriver,
  350. (ULONG)IOCTL_OPEN_FOR_RECV,
  351. pORI,
  352. dwSize,
  353. &g_ProgramOptions.hReceive,
  354. sizeof(HANDLE),
  355. &dwReturnBytes,
  356. &Overlapped);
  357. if(!bResult)
  358. {
  359. dwStatus = GetLastError();
  360. if(ERROR_IO_PENDING != dwStatus)
  361. {
  362. printf("Failed to open adapter for recvs. Error %u\n",
  363. dwStatus);
  364. break;
  365. }
  366. // the operation is pending
  367. bResult = GetOverlappedResult(
  368. g_ProgramOptions.hDriver,
  369. &Overlapped,
  370. &dwReturnBytes,
  371. TRUE
  372. );
  373. if(!bResult)
  374. {
  375. dwStatus = GetLastError();
  376. printf("Wait for open to complete failed. Error - %u\n",
  377. dwStatus);
  378. break;
  379. }
  380. }
  381. // successfully connected
  382. printf("Successfully opened adapter for recvs - Handle - 0x%p\n",
  383. g_ProgramOptions.hReceive);
  384. // allocate a buffer to receive data into
  385. dwSize = MAX_PKT_SIZE;
  386. pBuffer = HeapAlloc(GetProcessHeap(), 0, dwSize);
  387. if(!pBuffer)
  388. {
  389. printf("Error not enough memory\n");
  390. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  391. break;
  392. }
  393. // start receiving packets
  394. dw = 0;
  395. while(TRUE)
  396. {
  397. dwReturnBytes = 0;
  398. ResetEvent(Overlapped.hEvent);
  399. memset(pBuffer, 0, dwSize);
  400. bResult = DeviceIoControl(
  401. g_ProgramOptions.hDriver,
  402. (ULONG)IOCTL_RECV_DATA,
  403. &g_ProgramOptions.hReceive,
  404. sizeof(HANDLE),
  405. pBuffer,
  406. dwSize,
  407. &dwReturnBytes,
  408. &Overlapped);
  409. if(!bResult)
  410. {
  411. dwStatus = GetLastError();
  412. if(ERROR_IO_PENDING != dwStatus)
  413. {
  414. printf("Failed to receive data. Error %u\n", dwStatus);
  415. break;
  416. }
  417. // the operation is pending
  418. bResult = GetOverlappedResult(
  419. g_ProgramOptions.hDriver,
  420. &Overlapped,
  421. &dwReturnBytes,
  422. TRUE
  423. );
  424. if(!bResult)
  425. {
  426. dwStatus = GetLastError();
  427. if(dwStatus == ERROR_OPERATION_ABORTED)
  428. {
  429. printf("Receive operation is aborted.\n");
  430. }
  431. else
  432. {
  433. printf("Wait for recv to complete failed. Error - %u\n",
  434. dwStatus);
  435. }
  436. break;
  437. }
  438. printf("Successfully received a packet (%u). Size %u\n",
  439. dw+1, dwReturnBytes);
  440. VerifyPattern(pBuffer, dwReturnBytes);
  441. }
  442. dw++;
  443. }
  444. } while(FALSE);
  445. if(g_ProgramOptions.hReceive)
  446. {
  447. CloseReceiveHandle(&Overlapped);
  448. }
  449. if(pORI)
  450. HeapFree(GetProcessHeap(), 0, pORI);
  451. if(pBuffer)
  452. HeapFree(GetProcessHeap(), 0, pBuffer);
  453. if(Overlapped.hEvent)
  454. CloseHandle(Overlapped.hEvent);
  455. return dwStatus;
  456. }
  457. BOOL WINAPI CtrlCHandler(
  458. DWORD dwCtrlType
  459. )
  460. /*++
  461. Routine Description:
  462. This routine is called when Cntrl-C is used to exit the app from recv loop
  463. or during sends. It just cleans up the handles.
  464. Arguments:
  465. Return Value:
  466. --*/
  467. {
  468. OVERLAPPED Overlapped;
  469. printf("Control - C Handler\n");
  470. memset(&Overlapped, 0, sizeof(OVERLAPPED));
  471. Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  472. if(NULL == Overlapped.hEvent)
  473. {
  474. printf("Failed to create event. Error %u\n", GetLastError());
  475. return FALSE;
  476. }
  477. // If Recv was enabled then close that handle
  478. if(g_ProgramOptions.hReceive)
  479. {
  480. CloseReceiveHandle(&Overlapped);
  481. }
  482. printf("###-1\n");
  483. // If Send was enabled then close that handle
  484. if(g_ProgramOptions.hSend)
  485. {
  486. CloseConnectHandle(&Overlapped);
  487. g_ProgramOptions.hSend = NULL;
  488. }
  489. CloseHandle(Overlapped.hEvent);
  490. printf("###-2\n");
  491. return FALSE; // causes the app to exit
  492. }
  493. void Usage()
  494. {
  495. printf( "\n This program is used for sending or receiving data over ATM"
  496. "\n using the ATMSMDRV.SYS.\n\n");
  497. printf( " Mandatory Arguments:\n\n"
  498. " For SEND and RECV:\n"
  499. " /INTF:3908...0C100 - Local ATM adapter to use\n\n");
  500. printf( " Optional Arguments:\n\n"
  501. " /START - Start the driver.\n"
  502. " /STOP - Stop the driver.\n"
  503. " /ENUM - Enumerate interfaces.\n\n"
  504. " For SEND:\n"
  505. " /SEND:39..C100,49.. - ATM addresses of destinations\n"
  506. " /PMP - Make a PMP call.\n"
  507. " /INTVL:100 - Time interval between sends"
  508. " (millisec).\n"
  509. " /SIZE:512 - Packet Size (bytes).\n"
  510. " /NUMPKTS:10 - No. of packets to send.\n\n"
  511. " For RECV:\n"
  512. " /RECV - Receive pkts on the adapter\n\n");
  513. printf( " Example:\n\n"
  514. " AtmSmApp /INTF:4700918100000000613E5BFE010000C100741F00 "
  515. "/RECV\n"
  516. " AtmSmApp /INTF:4700...41F00 /SEND:4700...41F00,4700...123F00"
  517. " \n\n");
  518. printf( " Notes:\n\n"
  519. " A PMP call is made, when multiple destinations are specified."
  520. "\n"
  521. " Full NSAP address should be specified. Selector Byte defaults"
  522. " to 05.\n");
  523. }
  524. //
  525. // Options are of the form
  526. //
  527. // /START
  528. // /NUMPKTS:12
  529. #define START_DRV_OPT 101
  530. #define STOP_DRV_OPT 102
  531. #define ENUM_INTFS_OPT 103
  532. #define LOCAL_INTF_OPT 104
  533. #define SEND_ADDRS_OPT 105
  534. #define RECV_PKTS_OPT 106
  535. #define PKT_INTERVAL_OPT 107
  536. #define PKT_SIZE_OPT 108
  537. #define NUM_PKTS_OPT 109
  538. #define PMP_CONNECTION 110
  539. #define UNKNOWN_OPTION 111
  540. struct _CmdOptions
  541. {
  542. LPTSTR lptOption;
  543. UINT uOpt;
  544. } CmdOptions[] = {
  545. {_T("/START") , START_DRV_OPT},
  546. {_T("/STOP") , STOP_DRV_OPT},
  547. {_T("/ENUM") , ENUM_INTFS_OPT},
  548. {_T("/INTF:") , LOCAL_INTF_OPT},
  549. {_T("/SEND:") , SEND_ADDRS_OPT},
  550. {_T("/RECV") , RECV_PKTS_OPT},
  551. {_T("/INTVL:") , PKT_INTERVAL_OPT},
  552. {_T("/SIZE:") , PKT_SIZE_OPT},
  553. {_T("/NUMPKTS:") , NUM_PKTS_OPT},
  554. {_T("/PMP") , PMP_CONNECTION},
  555. };
  556. INT iCmdOptionsCounts = sizeof(CmdOptions)/sizeof(struct _CmdOptions);
  557. BOOL ParseCommandLine(
  558. int argc,
  559. char * argv[]
  560. )
  561. /*++
  562. Routine Description:
  563. Parse the command line parameters.
  564. Arguments:
  565. argc - number of arguments
  566. argv - arguments
  567. Return Value:
  568. TRUE - if successful
  569. FALSE - failure
  570. --*/
  571. {
  572. BOOL bRetVal = TRUE;
  573. int iIndx;
  574. UINT uOpt;
  575. char *pVal;
  576. for(iIndx = 1; iIndx < argc; iIndx++)
  577. {
  578. uOpt = FindOption(argv[iIndx], &pVal);
  579. switch(uOpt)
  580. {
  581. case START_DRV_OPT:
  582. g_ProgramOptions.usDrvAction = START_DRV;
  583. break;
  584. case STOP_DRV_OPT:
  585. g_ProgramOptions.usDrvAction = STOP_DRV;
  586. break;
  587. case ENUM_INTFS_OPT:
  588. g_ProgramOptions.fEnumInterfaces = TRUE;
  589. break;
  590. case LOCAL_INTF_OPT:
  591. if(!GetATMAddrs(pVal, g_ProgramOptions.ucLocalIntf))
  592. {
  593. printf("Local Interface address specified - Bad characters!\n");
  594. return FALSE;
  595. }
  596. g_ProgramOptions.fLocalIntf = TRUE;
  597. break;
  598. case SEND_ADDRS_OPT:
  599. g_ProgramOptions.usSendRecvAction = SEND_PKTS;
  600. if(!GetSpecifiedDstAddrs(pVal))
  601. {
  602. printf("Destination address(es) specified - Bad characters!\n");
  603. return FALSE;
  604. }
  605. // more than 1 destinations, it is a PMP VC
  606. if(1 < g_ProgramOptions.dwNumDsts)
  607. g_ProgramOptions.fPMP = TRUE;
  608. break;
  609. case RECV_PKTS_OPT:
  610. g_ProgramOptions.usSendRecvAction = RECEIVE_PKTS;
  611. break;
  612. case PKT_INTERVAL_OPT:
  613. g_ProgramOptions.dwPktInterval = atol(pVal);
  614. break;
  615. case PKT_SIZE_OPT:
  616. g_ProgramOptions.dwPktSize = atol(pVal);
  617. if(g_ProgramOptions.dwPktSize > MAX_PKT_SIZE)
  618. g_ProgramOptions.dwPktSize = MAX_PKT_SIZE;
  619. break;
  620. case NUM_PKTS_OPT:
  621. g_ProgramOptions.dwNumPkts = atol(pVal);
  622. break;
  623. case PMP_CONNECTION:
  624. g_ProgramOptions.fPMP = TRUE;
  625. break;
  626. default:
  627. printf("Unknown switch - %s\n", argv[iIndx]);
  628. return FALSE;
  629. }
  630. }
  631. return bRetVal;
  632. }
  633. UINT FindOption(
  634. char *lptOpt,
  635. char **ppVal
  636. )
  637. /*++
  638. Routine Description:
  639. Find the option number based on the command line switch.
  640. Arguments:
  641. lptOpt - command line option
  642. ppVal - Value associated with the option
  643. Return Value:
  644. OPTION_NUMBER - if success
  645. --*/
  646. {
  647. int i;
  648. UINT iLen;
  649. for(i = 0; i < iCmdOptionsCounts; i++)
  650. {
  651. if(strlen(lptOpt) >= (iLen = strlen(CmdOptions[i].lptOption)))
  652. if(0 == _strnicmp(lptOpt, CmdOptions[i].lptOption, iLen))
  653. {
  654. *ppVal = lptOpt + iLen;
  655. return CmdOptions[i].uOpt;
  656. }
  657. }
  658. return UNKNOWN_OPTION;
  659. }
  660. BOOL GetSpecifiedDstAddrs(
  661. char *pStr
  662. )
  663. /*++
  664. Routine Description:
  665. Get all the ATM destination addresses specified based from the
  666. command line parameter (after /SEND:)
  667. Arguments:
  668. pStr - pointer to what follows after /SEND:
  669. Return Value:
  670. TRUE - if successful
  671. FALSE - failure
  672. --*/
  673. {
  674. char szTmp[512];
  675. char *pToken;
  676. int i;
  677. strcpy(szTmp, pStr);
  678. pToken = strtok(szTmp, DELIMITOR_CHARS);
  679. i = 0;
  680. while(pToken)
  681. {
  682. if(!GetATMAddrs(pToken, g_ProgramOptions.ucDstAddrs[i]))
  683. return FALSE;
  684. pToken = strtok(NULL, DELIMITOR_CHARS);
  685. i++;
  686. }
  687. g_ProgramOptions.dwNumDsts = i;
  688. return TRUE;
  689. }
  690. BOOL GetATMAddrs(
  691. char *pStr,
  692. UCHAR ucAddr[]
  693. )
  694. /*++
  695. Routine Description:
  696. Parse the string specified as an ATM (NSAP)address into a 20byte
  697. array to hold the address
  698. Arguments:
  699. pStr - pointer to the string holding the address
  700. ucAddr - 20Byte Array holding the ATM address
  701. Return Value:
  702. TRUE - if successful
  703. FALSE - failure
  704. --*/
  705. {
  706. UCHAR ucVal;
  707. int i;
  708. for(i = 0; (*pStr != '\0') && (i < NSAP_ADDR_LEN); i++)
  709. {
  710. CharToHex(*pStr, ucVal);
  711. if((UCHAR)-1 == ucVal)
  712. return FALSE;
  713. ucAddr[i] = (UCHAR)(ucVal * 16);
  714. pStr++;
  715. CharToHex(*pStr, ucVal);
  716. if((UCHAR)-1 == ucVal)
  717. return FALSE;
  718. ucAddr[i] = (UCHAR)(ucAddr[i] + ucVal);
  719. pStr++;
  720. }
  721. return TRUE;
  722. }
  723. char * FormatATMAddr(
  724. UCHAR ucAddr[]
  725. )
  726. /*++
  727. Routine Description:
  728. Format a 20 byte ATM [NSAP] address into a character array for printing.
  729. Arguments:
  730. ucAddr - 20Byte Array holding the ATM address
  731. Return Value:
  732. String - pointer to the string holding the address
  733. --*/
  734. {
  735. static char szStr[NSAP_ADDR_LEN * 2 + 1];
  736. int i,j;
  737. char HexChars[] = "0123456789ABCDEF";
  738. j = 0;
  739. for(i = 0; i < NSAP_ADDR_LEN; i++)
  740. {
  741. szStr[j++] = HexChars[(ucAddr[i] >> 4)];
  742. szStr[j++] = HexChars[(ucAddr[i] &0xF)];
  743. }
  744. szStr[j] = '\0';
  745. return szStr;
  746. }