nrcmd.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:22k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

  1. /* net/rom user command processing
  2.  * Copyright 1989 by Daniel M. Frank, W9NK.  Permission granted for
  3.  * non-commercial distribution only.
  4.  */
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include "global.h"
  8. #include "mbuf.h"
  9. #include "ax25.h"
  10. #include "mailbox.h"
  11. #include "netrom.h"
  12. #include "nr4.h"
  13. #include "timer.h"
  14. #include "iface.h"
  15. #include "lapb.h"
  16. #include "cmdparse.h"
  17. #include "session.h"
  18. #include "socket.h"
  19. #include "commands.h"
  20. uint8 Nr4user[AXALEN];
  21. char *Nr4states[] = {
  22. "Disconn",
  23. "Conn Pend",
  24. "Connected",
  25. "Disc Pend",
  26. "Listening"
  27. } ;
  28. char *Nr4reasons[] = {
  29. "Normal",
  30. "By Peer",
  31. "Timeout",
  32. "Reset",
  33. "Refused"
  34. } ;
  35. static int dobcnodes(int argc,char *argv[],void *p);
  36. static int dointerface(int argc,char *argv[],void *p);
  37. static int donfadd(int argc,char *argv[],void *p);
  38. static int donfdrop(int argc,char *argv[],void *p);
  39. static int donfdump(void);
  40. static int donfmode(int argc,char *argv[],void *p);
  41. static int donodefilter(int argc,char *argv[],void *p);
  42. static void donodetick(void);
  43. static int donodetimer(int argc,char *argv[],void *p);
  44. static int donracktime(int argc,char *argv[],void *p);
  45. static int donrchoketime(int argc,char *argv[],void *p);
  46. static int donrconnect(int argc,char *argv[],void *p);
  47. static int donrirtt(int argc,char *argv[],void *p);
  48. static int donrkick(int argc,char *argv[],void *p);
  49. static int dorouteadd(int argc,char *argv[],void *p);
  50. static int doroutedrop(int argc,char *argv[],void *p);
  51. static int donrqlimit(int argc,char *argv[],void *p);
  52. static int donrreset(int argc,char *argv[],void *p);
  53. static int donrretries(int argc,char *argv[],void *p);
  54. static int donrroute(int argc,char *argv[],void *p);
  55. static int donrstatus(int argc,char *argv[],void *p);
  56. static int donrttl(int argc,char *argv[],void *p);
  57. static int donruser(int argc,char *argv[],void *p);
  58. static int donrverbose(int argc,char *argv[],void *p);
  59. static int donrwindow(int argc,char *argv[],void *p);
  60. static void doobsotick(void);
  61. static int doobsotimer(int argc,char *argv[],void *p);
  62. static struct cmds Nrcmds[] = {
  63. "acktime", donracktime, 0, 0, NULL,
  64. "bcnodes", dobcnodes, 0, 2, "netrom bcnodes <interface>",
  65. "connect", donrconnect, 1024, 2, "netrom connect <node>",
  66. "choketime", donrchoketime, 0, 0, NULL,
  67. "interface", dointerface, 0, 4,
  68. "netrom interface <interface> <alias> <quality>",
  69. "irtt", donrirtt, 0, 0, NULL,
  70. "kick", donrkick, 0, 2, "netrom kick <&nrcb>",
  71. "nodefilter", donodefilter, 0, 0, NULL,
  72. "nodetimer", donodetimer, 0, 0, NULL,
  73. "obsotimer", doobsotimer, 0, 0, NULL,
  74. "qlimit", donrqlimit, 0, 0, NULL,
  75. "reset", donrreset, 0, 2, "netrom reset <&nrcb>",
  76. "retries", donrretries, 0, 0, NULL,
  77. "route", donrroute, 0, 0, NULL,
  78. "status", donrstatus, 0, 0, NULL,
  79. "ttl", donrttl, 0, 0, NULL,
  80. "user", donruser, 0, 0, NULL,
  81. "verbose", donrverbose, 0, 0, NULL,
  82. "window", donrwindow, 0, 0, NULL,
  83. NULL,
  84. } ;
  85. static struct timer Nodetimer ; /* timer for nodes broadcasts */
  86. static struct timer Obsotimer ; /* timer for aging routes */
  87. static int keychar(int c);
  88. /* Command multiplexer */
  89. int
  90. donetrom(argc,argv,p)
  91. int argc ;
  92. char *argv[] ;
  93. void *p;
  94. {
  95. return subcmd(Nrcmds,argc,argv,p) ;
  96. }
  97. static struct cmds Routecmds[] = {
  98. "add", dorouteadd, 0, 6,
  99. "netrom route add <alias> <destination> <interface> <quality> <neighbor>",
  100. "drop", doroutedrop, 0, 4,
  101. "netrom route drop <destination> <neighbor> <interface>",
  102. "info", dorouteinfo, 0, 2,
  103. "netrom route info <destination>",
  104. NULL,
  105. } ;
  106. /* Route command multiplexer */
  107. static int
  108. donrroute(argc, argv,p)
  109. int argc ;
  110. char *argv[] ;
  111. void *p;
  112. {
  113. if (argc < 2) {
  114. doroutedump() ;
  115. return 0 ;
  116. }
  117. return subcmd(Routecmds,argc,argv,p) ;
  118. }
  119. /* Dump a list of known routes */
  120. int
  121. doroutedump()
  122. {
  123. register struct nrroute_tab *rp ;
  124. register int i, column ;
  125. char buf[16] ;
  126. char *cp ;
  127. column = 1 ;
  128. for (i = 0 ; i < NRNUMCHAINS ; i++)
  129. for (rp = Nrroute_tab[i] ; rp != NULL ; rp = rp->next) {
  130. strcpy(buf,rp->alias) ;
  131. /* remove trailing spaces */
  132. if ((cp = strchr(buf,' ')) == NULL)
  133. cp = &buf[strlen(buf)] ;
  134. if (cp != buf) /* don't include colon for null alias */
  135. *cp++ = ':' ;
  136. pax25(cp,rp->call) ;
  137. printf("%-16s  ",buf) ;
  138. if (column++ == 4) {
  139. printf("n");
  140. column = 1 ;
  141. }
  142. }
  143. if (column != 1)
  144. printf("n") ;
  145. return 0 ;
  146. }
  147. /* print detailed information on an individual route */
  148. int
  149. dorouteinfo(argc,argv,p)
  150. int argc ;
  151. char *argv[] ;
  152. void *p;
  153. {
  154. register struct nrroute_tab *rp ;
  155. register struct nr_bind *bp ;
  156. register struct nrnbr_tab *np ;
  157. uint8 dest[AXALEN] ;
  158. char neighbor[AXBUF] ;
  159. if (setcall(dest,argv[1]) == -1) {
  160. printf ("bad destination namen") ;
  161. return -1 ;
  162. }
  163. if ((rp = find_nrroute(dest)) == NULL) {
  164. printf("no such routen") ;
  165. return -1 ;
  166. }
  167. for (bp = rp->routes ; bp != NULL ; bp = bp->next) {
  168. np = bp->via ;
  169. printf("%1s %3d  %3d  %-8s  %sn",
  170.  (bp->flags & NRB_PERMANENT ? "P" :
  171.  bp->flags & NRB_RECORDED ? "R" : " "),
  172.  bp->quality,bp->obsocnt,
  173.  Nrifaces[np->iface].iface->name,
  174.  pax25(neighbor,np->call));
  175. }
  176. return 0 ;
  177. }
  178. /* convert a null-terminated alias name to a blank-filled, upcased */
  179. /* version.  Return -1 on failure. */
  180. int
  181. putalias(to,from,complain)
  182. register char *to, *from ;
  183. int complain ;    
  184. {
  185. int len, i ;
  186. if ((len = strlen(from)) > ALEN) {
  187. if (complain)
  188. printf ("alias too long - six characters maxn") ;
  189. return -1 ;
  190. }
  191. for (i = 0 ; i < ALEN ; i++) {
  192. if (i < len) {
  193. if (islower(*from))
  194. *to++ = toupper(*from++) ;
  195. else
  196. *to++ = *from++ ;
  197. }
  198. else
  199. *to++ = ' ' ;
  200. }
  201. *to = '' ;
  202. return 0 ;
  203. }
  204. /* Add a route */
  205. static int
  206. dorouteadd(argc, argv,p)
  207. int argc ;
  208. char *argv[] ;
  209. void *p;
  210. {
  211. char alias[AXALEN] ;
  212. uint8 dest[AXALEN] ;
  213. unsigned quality ;
  214. uint8 neighbor[AXALEN] ;
  215. register int i ;
  216. int naddr ;
  217. /* format alias (putalias prints error message if necessary) */
  218. if (putalias(alias,argv[1],1) == -1)
  219. return -1 ;
  220. /* format destination callsign */
  221. if (setcall(dest,argv[2]) == -1) {
  222. printf("bad destination callsignn") ;
  223. return -1 ;
  224. }
  225. /* find interface */
  226. for (i = 0 ; i < Nr_numiface ; i++)
  227. if (!strcmp(Nrifaces[i].iface->name,argv[3]))
  228. break ;
  229. if (i == Nr_numiface) {
  230. printf("Interface "%s" not foundn",argv[3]) ;
  231. return -1 ;
  232. }
  233. /* get and check quality value */
  234. if ((quality = atoi(argv[4])) > 255) {
  235. printf("maximum route quality is 255n") ;
  236. return -1 ;
  237. }
  238. /* Change from 871225 -- no digis in net/rom table */
  239. naddr = argc - 5 ;
  240. if (naddr > 1) {
  241. printf("Use the ax25 route command to specify digipeatersn") ;
  242. return -1 ;
  243. }
  244. /* format neighbor address string */
  245. setcall(neighbor,argv[5]) ;
  246. return nr_routeadd(alias,dest,i,quality,neighbor,1,0) ;
  247. }
  248. /* drop a route */
  249. static int
  250. doroutedrop(argc,argv,p)
  251. int argc ;
  252. char *argv[] ;
  253. void *p;
  254. {
  255. uint8 dest[AXALEN], neighbor[AXALEN] ;
  256. register int i ;
  257. /* format destination and neighbor callsigns */
  258. if (setcall(dest,argv[1]) == -1) {
  259. printf("bad destination callsignn") ;
  260. return -1 ;
  261. }
  262. if (setcall(neighbor,argv[2]) == -1) {
  263. printf("bad neighbor callsignn") ;
  264. return -1 ;
  265. }
  266. /* find interface */
  267. for (i = 0 ; i < Nr_numiface ; i++)
  268. if (!strcmp(Nrifaces[i].iface->name,argv[3]))
  269. break ;
  270. if (i == Nr_numiface) {
  271. printf("Interface "%s" not foundn",argv[3]) ;
  272. return -1 ;
  273. }
  274. return nr_routedrop(dest,neighbor,i) ;
  275. }
  276. /* make an interface available to net/rom */
  277. static int
  278. dointerface(argc,argv,p)
  279. int argc ;
  280. char *argv[] ;
  281. void *p;
  282. {
  283. int i ;
  284. register struct iface *ifp ;
  285. if (Nr_iface == NULL) {
  286. printf("Attach netrom interface firstn") ;
  287. return 1 ;
  288. }
  289. if (Nr_numiface >= NRNUMIFACE) {
  290. printf("Only %d net/rom interfaces availablen",NRNUMIFACE) ;
  291. return 1 ;
  292. }
  293. if((ifp = if_lookup(argv[1])) == NULL){
  294. printf("Interface "%s" unknownn",argv[1]);
  295. return 1;
  296. }
  297. for (i = 0 ; i < Nr_numiface ; i++)
  298. if (Nrifaces[i].iface == ifp) {
  299. printf("Interface "%s" is already registeredn",argv[1]) ;
  300. return 1 ;
  301. }
  302. Nrifaces[Nr_numiface].iface = ifp ;
  303. if (putalias(Nrifaces[Nr_numiface].alias,argv[2],1) == -1)
  304. return 1 ;
  305. if ((Nrifaces[Nr_numiface].quality = atoi(argv[3])) > 255) {
  306. printf("Quality cannot be greater than 255n") ;
  307. return 1 ;
  308. }
  309. Nr_numiface++ ; /* accept this interface */
  310. return 0 ;
  311. }
  312. /* Broadcast nodes list on named interface. */
  313. static int
  314. dobcnodes(argc,argv,p)
  315. int argc ;
  316. char *argv[] ;
  317. void *p;
  318. {
  319. register int i ;
  320. for (i = 0 ; i < Nr_numiface ; i++)
  321. if (!strcmp(Nrifaces[i].iface->name,argv[1]))
  322. break ;
  323. if (i == Nr_numiface) {
  324. printf("Interface "%s" not foundn",argv[1]) ;
  325. return 1 ;
  326. }
  327. nr_bcnodes(i) ;
  328. return 0;
  329. }
  330. /* Set outbound node broadcast interval */
  331. static int
  332. donodetimer(argc,argv,p)
  333. int argc;
  334. char *argv[];
  335. void *p;
  336. {
  337. if(argc < 2){
  338. printf("Nodetimer %lu/%lu secondsn",
  339. read_timer(&Nodetimer)/1000L,
  340. dur_timer(&Nodetimer)/1000L);
  341. return 0;
  342. }
  343. stop_timer(&Nodetimer) ; /* in case it's already running */
  344. Nodetimer.func = (void (*)())donodetick;/* what to call on timeout */
  345. Nodetimer.arg = NULL; /* dummy value */
  346. set_timer(&Nodetimer,atoi(argv[1])*1000L);/* set timer duration */
  347. start_timer(&Nodetimer); /* and fire it up */
  348. return 0;
  349. }
  350. static void
  351. donodetick()
  352. {
  353. register int i ;
  354. for (i = 0 ; i < Nr_numiface ; i++)
  355. nr_bcnodes(i) ;
  356. /* Restart timer */
  357. start_timer(&Nodetimer) ;
  358. }
  359. /* Set timer for aging routes */
  360. static int
  361. doobsotimer(argc,argv,p)
  362. int argc;
  363. char *argv[];
  364. void *p;
  365. {
  366. if(argc < 2){
  367. printf("Obsotimer %lu/%lu secondsn",
  368. read_timer(&Obsotimer)/1000L,
  369. dur_timer(&Obsotimer)/1000L);
  370. return 0;
  371. }
  372. stop_timer(&Obsotimer) ; /* just in case it's already running */
  373. Obsotimer.func = (void (*)())doobsotick;/* what to call on timeout */
  374. Obsotimer.arg = NULL; /* dummy value */
  375. set_timer(&Obsotimer,atoi(argv[1])*1000L); /* set timer duration */
  376. start_timer(&Obsotimer); /* and fire it up */
  377. return 0;
  378. }
  379. /* Go through the routing table, reducing the obsolescence count of
  380.  * non-permanent routes, and purging them if the count reaches 0
  381.  */
  382. static void
  383. doobsotick()
  384. {
  385. register struct nrnbr_tab *np ;
  386. register struct nrroute_tab *rp, *rpnext ;
  387. register struct nr_bind *bp, *bpnext ;
  388. int i ;
  389. for (i = 0 ; i < NRNUMCHAINS ; i++) {
  390. for (rp = Nrroute_tab[i] ; rp != NULL ; rp = rpnext) {
  391. rpnext = rp->next ;  /* save in case we free this route */
  392. for (bp = rp->routes ; bp != NULL ; bp = bpnext) {
  393. bpnext = bp->next ; /* in case we free this binding */
  394. if (bp->flags & NRB_PERMANENT) /* don't age these */
  395. continue ;
  396. if (--bp->obsocnt == 0) { /* time's up! */
  397. if (bp->next != NULL)
  398. bp->next->prev = bp->prev ;
  399. if (bp->prev != NULL)
  400. bp->prev->next = bp->next ;
  401. else
  402. rp->routes = bp->next ;
  403. rp->num_routes-- ; /* one less binding */
  404. np = bp->via ; /* find the neighbor */
  405. free(bp) ; /* now we can free the bind */
  406. /* Check to see if we can free the neighbor */
  407. if (--np->refcnt == 0) {
  408. if (np->next != NULL)
  409. np->next->prev = np->prev ;
  410. if (np->prev != NULL)
  411. np->prev->next = np->next ;
  412. else {
  413. Nrnbr_tab[nrhash(np->call)] = np->next ;
  414. }
  415. free(np) ; /* free the storage */
  416. }
  417. }
  418. }
  419. if (rp->num_routes == 0) { /* did we free them all? */
  420. if (rp->next != NULL)
  421. rp->next->prev = rp->prev ;
  422. if (rp->prev != NULL)
  423. rp->prev->next = rp->next ;
  424. else
  425. Nrroute_tab[i] = rp->next ;
  426. free(rp) ;
  427. }
  428. }
  429. }
  430. start_timer(&Obsotimer) ;
  431. }
  432. static struct cmds Nfcmds[] = {
  433. "add", donfadd, 0, 3,
  434. "netrom nodefilter add <neighbor> <interface>",
  435. "drop", donfdrop, 0, 3,
  436. "netrom nodefilter drop <neighbor> <interface>",
  437. "mode", donfmode, 0, 0, NULL,
  438. NULL, NULL, 0, 0,
  439. "nodefilter subcommands: add drop mode",
  440. } ;
  441. /* nodefilter command multiplexer */
  442. static int
  443. donodefilter(argc,argv,p)
  444. int argc ;
  445. char *argv[] ;
  446. void *p;
  447. {
  448. if (argc < 2) {
  449. donfdump() ;
  450. return 0 ;
  451. }
  452. return subcmd(Nfcmds,argc,argv,p) ;
  453. }
  454. /* display a list of <callsign,interface> pairs from the filter
  455.  * list.
  456.  */
  457. static int
  458. donfdump()
  459. {
  460. int i, column = 1 ;
  461. struct nrnf_tab *fp ;
  462. char buf[16] ;
  463. for (i = 0 ; i < NRNUMCHAINS ; i++)
  464. for (fp = Nrnf_tab[i] ; fp != NULL ; fp = fp->next) {
  465. pax25(buf,fp->neighbor) ;
  466. printf("%-7s %-8s  ",
  467.  buf,Nrifaces[fp->iface].iface->name) ;
  468. if (column++ == 4) {
  469. printf("n");
  470. column = 1 ;
  471. }
  472. }
  473. if (column != 1)
  474. printf("n") ;
  475. return 0 ;
  476. }
  477. /* add an entry to the filter table */
  478. static int
  479. donfadd(argc,argv,p)
  480. int argc ;
  481. char *argv[] ;
  482. void *p;
  483. {
  484. uint8 neighbor[AXALEN] ;
  485. register int i ;
  486. /* format callsign */
  487. if (setcall(neighbor,argv[1]) == -1) {
  488. printf("bad neighbor callsignn") ;
  489. return -1 ;
  490. }
  491. /* find interface */
  492. for (i = 0 ; i < Nr_numiface ; i++)
  493. if (!strcmp(Nrifaces[i].iface->name,argv[2]))
  494. break ;
  495. if (i == Nr_numiface) {
  496. printf("Interface "%s" not foundn",argv[2]) ;
  497. return -1 ;
  498. }
  499. return nr_nfadd(neighbor,i) ;
  500. }
  501. /* drop an entry from the filter table */
  502. static int
  503. donfdrop(argc,argv,p)
  504. int argc ;
  505. char *argv[] ;
  506. void *p;
  507. {
  508. uint8 neighbor[AXALEN] ;
  509. register int i ;
  510. /* format neighbor callsign */
  511. if (setcall(neighbor,argv[1]) == -1) {
  512. printf("bad neighbor callsignn") ;
  513. return -1 ;
  514. }
  515. /* find interface */
  516. for (i = 0 ; i < Nr_numiface ; i++)
  517. if (!strcmp(Nrifaces[i].iface->name,argv[2]))
  518. break ;
  519. if (i == Nr_numiface) {
  520. printf("Interface "%s" not foundn",argv[2]) ;
  521. return -1 ;
  522. }
  523. return nr_nfdrop(neighbor,i) ;
  524. }
  525. /* nodefilter mode subcommand */
  526. static int
  527. donfmode(argc,argv,p)
  528. int argc ;
  529. char *argv[] ;
  530. void *p;
  531. {
  532. if (argc < 2) {
  533. printf("filter mode is ") ;
  534. switch (Nr_nfmode) {
  535. case NRNF_NOFILTER:
  536. printf("nonen") ;
  537. break ;
  538. case NRNF_ACCEPT:
  539. printf("acceptn") ;
  540. break ;
  541. case NRNF_REJECT:
  542. printf("rejectn") ;
  543. break ;
  544. default:
  545. printf("some strange, unknown valuen") ;
  546. }
  547. return 0 ;
  548. }
  549. switch (argv[1][0]) {
  550. case 'n':
  551. case 'N':
  552. Nr_nfmode = NRNF_NOFILTER ;
  553. break ;
  554. case 'a':
  555. case 'A':
  556. Nr_nfmode = NRNF_ACCEPT ;
  557. break ;
  558. case 'r':
  559. case 'R':
  560. Nr_nfmode = NRNF_REJECT ;
  561. break ;
  562. default:
  563. printf("modes are: none accept rejectn") ;
  564. return -1 ;
  565. }
  566. return 0 ;
  567. }
  568. /* netrom network packet time-to-live initializer */
  569. static int
  570. donrttl(argc, argv,p)
  571. int argc ;
  572. char *argv[] ;
  573. void *p;
  574. {
  575. return setshort(&Nr_ttl,"Time to live",argc,argv);
  576. }
  577. /* verbose route broadcast */
  578. static int
  579. donrverbose(argc,argv,p)
  580. int argc ;
  581. char *argv[] ;
  582. void *p;
  583. {
  584. return setbool(&Nr_verbose,"Verbose flag",argc,argv);
  585. }
  586. /* Initiate a NET/ROM transport connection */
  587. static int
  588. donrconnect(argc,argv,p)
  589. int argc ;
  590. char *argv[] ;
  591. void *p;
  592. {
  593. uint8 *np ;
  594. struct sockaddr_nr lsocket, fsocket;
  595. char alias[AXBUF];
  596. struct session *sp;
  597. int s;
  598. /* Get a session descriptor */
  599. if ((sp = newsession(Cmdline,NRSESSION,1)) == NULL) {
  600. printf("Too many sessionsn") ;
  601. return 1 ;
  602. }
  603. sp->inproc = keychar; /* Intercept ^C */
  604. if((s = socket(AF_NETROM,SOCK_SEQPACKET,0)) == -1){
  605. printf("Can't create socketn");
  606. keywait(NULL,1);
  607. freesession(sp);
  608. return 1;
  609. }
  610. lsocket.nr_family = AF_NETROM;
  611. /* Set up our local username, bind would use Mycall instead */
  612. memcpy(lsocket.nr_addr.user,Nr4user,AXALEN);
  613. /* Putting anything else than Mycall here will not work */
  614. memcpy(lsocket.nr_addr.node,Mycall,AXALEN);
  615. bind(s,(struct sockaddr *)&lsocket,sizeof(struct sockaddr_nr));
  616. /* See if the requested destination could be an alias, and */
  617. /* find and use it if it is.  Otherwise assume it is an ax.25 */
  618. /* address. */
  619. if (putalias(alias,argv[1],0) != -1 &&
  620.     (np = find_nralias(alias)) != NULL) {
  621.     memcpy(fsocket.nr_addr.user,np,AXALEN) ;
  622.     memcpy(fsocket.nr_addr.node,np,AXALEN) ;
  623. } else { /* parse ax25 callsign */
  624.     /* Only the user callsign of the remote station is never used by */
  625.     /* NET/ROM, but it is needed for the psocket() call. */
  626. setcall(fsocket.nr_addr.user,argv[1]);
  627. setcall(fsocket.nr_addr.node,argv[1]);
  628. }
  629. fsocket.nr_family = AF_NETROM;
  630. pax25(alias,fsocket.nr_addr.node);
  631. sp->network = fdopen(s,"r+t");
  632. setvbuf(sp->network,NULL,_IOLBF,BUFSIZ);
  633. if(SETSIG(EABORT)){
  634. keywait(NULL,1);
  635. freesession(sp);
  636. return 1;
  637. }
  638. return tel_connect(sp, (struct sockaddr *)&fsocket, sizeof(struct sockaddr_nr));
  639. }
  640. /* Reset a net/rom connection abruptly */
  641. static int
  642. donrreset(argc,argv,p)
  643. int argc;
  644. char *argv[];
  645. void *p;
  646. {
  647. struct nr4cb *cb ;
  648. cb = (struct nr4cb *)htol(argv[1]);
  649. if(!nr4valcb(cb)){
  650. printf(Notval);
  651. return 1;
  652. }
  653. reset_nr4(cb);
  654. return 0;
  655. }
  656. /* Force retransmission on a net/rom connection */
  657. static int
  658. donrkick(argc,argv,p)
  659. int argc;
  660. char *argv[];
  661. void *p;
  662. {
  663. struct nr4cb *cb ;
  664. cb = (struct nr4cb *)htol(argv[1]);
  665. if (kick_nr4(cb) == -1) {
  666. printf(Notval);
  667. return 1;
  668. } else
  669. return 0;
  670. }
  671. /* netrom transport ACK delay timer */
  672. static int
  673. donracktime(argc, argv,p)
  674. int argc ;
  675. char *argv[] ;
  676. void *p;
  677. {
  678. return setlong(&Nr4acktime,"Ack delay time (ms)",argc,argv);
  679. }
  680. /* netrom transport choke timeout */
  681. static int
  682. donrchoketime(argc, argv,p)
  683. int argc ;
  684. char *argv[] ;
  685. void *p;
  686. {
  687. return setlong(&Nr4choketime,"Choke timeout (ms)",argc,argv);
  688. }
  689. /* netrom transport initial round trip time */
  690. static int
  691. donrirtt(argc, argv,p)
  692. int argc ;
  693. char *argv[] ;
  694. void *p;
  695. {
  696. return setlong(&Nr4irtt,"Initial RTT (ms)",argc,argv);
  697. }
  698. /* netrom transport receive queue length limit.  This is the */
  699. /* threshhold at which we will CHOKE the sender. */
  700. static int
  701. donrqlimit(argc, argv,p)
  702. int argc ;
  703. char *argv[] ;
  704. void *p;
  705. {
  706. return setshort(&Nr4qlimit,"Queue limit (bytes)",argc,argv);
  707. }
  708. /* Display or change our NET/ROM username */
  709. static int
  710. donruser(argc,argv,p)
  711. int argc;
  712. char *argv[];
  713. void *p;
  714. {
  715. char buf[AXBUF];
  716. if(argc < 2){
  717. pax25(buf,Nr4user);
  718. printf("%sn",buf);
  719. return 0;
  720. }
  721. if(setcall(Nr4user,argv[1]) == -1)
  722. return -1;
  723. Nr4user[ALEN] |= E;
  724. return 0;
  725. }
  726. /* netrom transport maximum window.  This is the largest send and */
  727. /* receive window we may negotiate */
  728. static int
  729. donrwindow(argc, argv,p)
  730. int argc ;
  731. char *argv[] ;
  732. void *p;
  733. {
  734. return setshort(&Nr4window,"Window (frames)",argc,argv);
  735. }
  736. /* netrom transport maximum retries.  This is used in connect and */
  737. /* disconnect attempts; I haven't decided what to do about actual */
  738. /* data retries yet. */
  739. static int
  740. donrretries(argc, argv,p)
  741. int argc ;
  742. char *argv[] ;
  743. void *p;
  744. {
  745. return setshort(&Nr4retries,"Retry limit",argc,argv);
  746. }
  747. /* Display the status of NET/ROM connections */
  748. static int
  749. donrstatus(argc, argv,p)
  750. int argc ;
  751. char *argv[] ;
  752. void *p;
  753. {
  754. int i ;
  755. struct nr4cb *cb ;
  756. char luser[AXBUF], ruser[AXBUF], node[AXBUF] ;
  757. if (argc < 2) {
  758. printf("&CB       Snd-W Snd-Q Rcv-Q     LUser      RUser @Node     Staten");
  759. for (i = 0 ; i < NR4MAXCIRC ; i++) {
  760. if ((cb = Nr4circuits[i].ccb) == NULL)
  761. continue ;
  762. pax25(luser,cb->local.user) ;
  763. pax25(ruser,cb->remote.user) ;
  764. pax25(node,cb->remote.node) ;
  765. printf("%9p   %3d %5d %5d %9s  %9s %-9s %sn",
  766.  cb, cb->nbuffered, len_q(cb->txq),
  767.  len_p(cb->rxq), luser, ruser, node,
  768.  Nr4states[cb->state]);
  769. }
  770. return 0 ;
  771. }
  772. cb = (struct nr4cb *)htol(argv[1]) ;
  773. if (!nr4valcb(cb)) {
  774. printf(Notval) ;
  775. return 1 ;
  776. }
  777. donrdump(cb) ;
  778. return 0 ;
  779. }
  780. /* Dump one control block */
  781. void
  782. donrdump(cb)
  783. struct nr4cb *cb ;
  784. {
  785. char luser[AXBUF], ruser[AXBUF], node[AXBUF] ;
  786. unsigned seq ;
  787. struct nr4txbuf *b ;
  788. struct timer *t ;
  789. pax25(luser,cb->local.user) ;
  790. pax25(ruser,cb->remote.user) ;
  791. pax25(node,cb->remote.node) ;
  792. printf("Local: %s %d/%d Remote: %s @ %s %d/%d State: %sn",
  793.    luser, cb->mynum, cb->myid, ruser, node,
  794.    cb->yournum, cb->yourid, Nr4states[cb->state]) ;
  795. printf("Window: %-5u Rxpect: %-5u RxNext: %-5u RxQ: %-5d %sn",
  796.    cb->window, cb->rxpected, cb->rxpastwin,
  797.    len_p(cb->rxq), cb->qfull ? "RxCHOKED" : "") ;
  798. printf(" Unack: %-5u Txpect: %-5u TxNext: %-5u TxQ: %-5d %sn",
  799.    cb->nbuffered, cb->ackxpected, cb->nextosend,
  800.    len_q(cb->txq), cb->choked ? "TxCHOKED" : "") ;
  801. printf("TACK: ") ;
  802. if (run_timer(&cb->tack))
  803. printf("%lu", read_timer(&cb->tack)) ;
  804. else
  805. printf("stop") ;
  806. printf("/%lu ms; ", dur_timer(&cb->tack)) ;
  807. printf("TChoke: ") ;
  808. if (run_timer(&cb->tchoke))
  809. printf("%lu", read_timer(&cb->tchoke)) ;
  810. else
  811. printf("stop") ;
  812. printf("/%lu ms; ", dur_timer(&cb->tchoke)) ;
  813. printf("TCD: ") ;
  814. if (run_timer(&cb->tcd))
  815. printf("%lu", read_timer(&cb->tcd)) ;
  816. else
  817. printf("stop") ;
  818. printf("/%lu ms", dur_timer(&cb->tcd)) ;
  819. if (run_timer(&cb->tcd))
  820. printf("; Tries: %un", cb->cdtries) ;
  821. else
  822. printf("n") ;
  823. printf("Backoff Level %u SRTT %ld ms Mean dev %ld msn",
  824.    cb->blevel, cb->srtt, cb->mdev) ;
  825. /* If we are connected and the send window is open, display */
  826. /* the status of all the buffers and their timers */
  827. if (cb->state == NR4STCON && cb->nextosend != cb->ackxpected) {
  828. printf("TxBuffers:  Seq  Size  Tries  Timern") ;
  829. for (seq = cb->ackxpected ;
  830.  nr4between(cb->ackxpected, seq, cb->nextosend) ;
  831.  seq = (seq + 1) & NR4SEQMASK) {
  832. b = &cb->txbufs[seq % cb->window] ;
  833. t = &b->tretry ;
  834. printf("            %3u   %3d  %5d  %lu/%lun",
  835.  seq, len_p(b->data), b->retries + 1,
  836.  read_timer(t), dur_timer(t));
  837. }
  838. }
  839. }
  840. static int
  841. keychar(c)
  842. int c;
  843. {
  844. if(c != CTLC)
  845. return 1; /* Ignore all but ^C */
  846. fprintf(Current->output,"^Cn");
  847. alert(Current->proc,EABORT);
  848. return 0;
  849. }