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

TCP/IP协议栈

开发平台:

Visual C++

  1. /* Automatic line dialer for asynch ports running SLIP, PPP, etc.
  2.  *
  3.  * Copyright 1991 Phil Karn, KA9Q
  4.  *
  5.  * Mar '91 Bill Simpson & Glenn McGregor
  6.  * completely re-written;
  7.  * human readable control file;
  8.  * includes wait for string, and speed sense;
  9.  * dials immediately when invoked.
  10.  * May '91 Bill Simpson
  11.  * re-ordered command line;
  12.  * allow dial only;
  13.  * allow inactivity timeout without ping.
  14.  * Sep '91 Bill Simpson
  15.  * Check known DTR & RSLD state for redial decision
  16.  * Mar '92 Phil Karn
  17.  * autosense modem control stuff removed
  18.  * Largely rewritten to do demand dialing
  19.  */
  20. #include <stdio.h>
  21. #include <ctype.h>
  22. #include <stdlib.h>
  23. #include "global.h"
  24. #include "mbuf.h"
  25. #include "timer.h"
  26. #include "proc.h"
  27. #include "iface.h"
  28. #include "netuser.h"
  29. #include "n8250.h"
  30. #include "asy.h"
  31. #include "tty.h"
  32. #include "socket.h"
  33. #include "cmdparse.h"
  34. #include "devparam.h"
  35. #include "files.h"
  36. #include "main.h"
  37. #include "trace.h"
  38. #include "commands.h"
  39. #include "dialer.h"
  40. static int redial(struct iface *ifp,char *file);
  41. static void dropline(void *);
  42. static void dropit(int,void *,void *);
  43. int dialer_kick(struct iface *ifp);
  44. void sd_answer(int,void *,void *);
  45. static int dodial_control(int argc,char *argv[],void *p);
  46. static int dodial_send(int argc,char *argv[],void *p);
  47. static int dodial_speed(int argc,char *argv[],void *p);
  48. static int dodial_status(int argc,char *argv[],void *p);
  49. static int dodial_wait(int argc,char *argv[],void *p);
  50. static struct cmds Dial_cmds[] = {
  51. "", donothing, 0, 0, "",
  52. "control", dodial_control, 0, 2, "control up | down",
  53. "send", dodial_send, 0, 2,
  54. "send "string" [<milliseconds>]",
  55. "speed", dodial_speed, 0, 2, "speed <bps>",
  56. "status", dodial_status, 0, 2, "status up | down",
  57. "wait", dodial_wait, 0, 2,
  58. "wait <milliseconds> [ "string" [speed] ]",
  59. NULL, NULL, 0, 0, "Unknown command",
  60. };
  61. /* Set up demand dialing on an asy link. Called from dodialer command
  62.  * in iface.c.
  63.  */
  64. int
  65. sd_init(ifp,timeout,argc,argv)
  66. struct iface *ifp;
  67. int32 timeout;
  68. int argc;
  69. char *argv[];
  70. {
  71. struct asy *ap;
  72. struct asydialer *dialer;
  73. char *cp;
  74. if(ifp->dev >= ASY_MAX || Asy[ifp->dev].iface != ifp){
  75. /* "Can't happen" */
  76. printf("Interface %s not asy portn",argv[1]);
  77. return 1;
  78. }
  79. ap = &Asy[ifp->dev];
  80. if(timeout != 0 && argc < 3){
  81. printf("Usage: dial <iface> <timeout> <raisefile> <dropfile> <ringfile>n");
  82. printf("       dial <iface> 0n");
  83. return 1;
  84. }
  85. if(!ap->rlsd){
  86. printf("Must set 'r' flag at attach timen");
  87. return 1;
  88. }
  89. if(ifp->dstate != NULL){
  90. /* Get rid of the old dialer info */
  91. dialer = (struct asydialer *)ifp->dstate;
  92. stop_timer(&dialer->idle);
  93. if(dialer->actfile != NULL){
  94. free(dialer->actfile);
  95. dialer->actfile = NULL;
  96. }
  97. if(dialer->dropfile != NULL){
  98. free(dialer->dropfile);
  99. dialer->dropfile = NULL;
  100. }
  101. if(dialer->ansfile != NULL){
  102. free(dialer->ansfile);
  103. dialer->ansfile = NULL;
  104. }
  105. free(ifp->dstate);
  106. ifp->dstate = NULL;
  107. }
  108. killproc(ifp->supv);
  109. ifp->supv = NULL;
  110. dialer = (struct asydialer *)calloc(1,sizeof(struct asydialer));
  111. ifp->dstate = dialer;
  112. ifp->dtickle = dialer_kick;
  113. set_timer(&dialer->idle,timeout);
  114. dialer->idle.func = dropline;
  115. dialer->idle.arg = ifp;
  116. if(timeout != 0){
  117. dialer->actfile = strdup(argv[0]);
  118. dialer->dropfile = strdup(argv[1]);
  119. dialer->ansfile = strdup(argv[2]);
  120. cp = if_name(ifp," answerer");
  121. ifp->supv = newproc(cp,768,sd_answer,ifp->dev,ifp,NULL,0);
  122. }
  123. return 0;
  124. }
  125. /* Display status of asynch dialer. Called from dodialer command in
  126.  * iface.c when invoked without full args
  127.  */
  128. int
  129. sd_stat(ifp)
  130. struct iface *ifp;
  131. {
  132. struct asydialer *dialer = (struct asydialer *)ifp->dstate;
  133. struct asy *ap;
  134. if(dialer == NULL){
  135. printf("No dialer active on %sn",ifp->name);
  136. return 1;
  137. }
  138. ap = &Asy[ifp->dev];
  139. printf("%s: %s,",ifp->name,(ap->msr & MSR_RLSD) ? "UP":"DOWN");
  140. printf(" idle timer %lu/%lu secn",read_timer(&dialer->idle)/1000L,
  141.   dur_timer(&dialer->idle)/1000L);
  142. if(dialer->actfile != NULL)
  143. printf("up script: %sn",dialer->actfile);
  144. if(dialer->dropfile != NULL)
  145. printf("down script: %sn",dialer->dropfile);
  146. if(dialer->ansfile != NULL)
  147. printf("answer script: %sn",dialer->ansfile);
  148. printf("Calls originated %lu, Calls answered %lun",
  149. dialer->originates,dialer->answers);
  150. printf("Calls timed out %lu, carrier transitions %lun",
  151. dialer->localdrops,ap->cdchanges);
  152. return 0;
  153. }
  154. /* Called by interface output routine just before sending each packet */
  155. int
  156. dialer_kick(ifp)
  157. struct iface *ifp;
  158. {
  159. struct asy *asyp;
  160. struct asydialer *dialer;
  161. dialer = (struct asydialer *)ifp->dstate;
  162. asyp = &Asy[ifp->dev];
  163. stop_timer(&dialer->idle);
  164. if(asyp->rlsd && !(asyp->msr & MSR_RLSD)
  165.  && dialer->actfile != NULL){
  166. /* Line down, try a redial */
  167. dialer->originates++;
  168. if(redial(ifp,dialer->actfile) != 0 
  169.  || !(asyp->msr & MSR_RLSD)){
  170. /* Redial failed, drop line and return failure */
  171. dialer->localdrops++;
  172. redial(ifp,dialer->dropfile);
  173. return -1;
  174. }
  175. }
  176. start_timer(&dialer->idle);
  177. return 0;
  178. }
  179. /* Called when idle line timer expires -- executes script to drop line */
  180. static void
  181. dropline(p)
  182. void *p;
  183. {
  184. /* Fork this off to prevent wedging the timer task */
  185. newproc("dropit",1024,dropit,0,p,NULL,0);
  186. }
  187. static void
  188. dropit(i,p,u)
  189. int i;
  190. void *p;
  191. void *u;
  192. {
  193. struct iface *ifp = p;
  194. struct asy *ap;
  195. struct asydialer *dialer;
  196. dialer = (struct asydialer *)ifp->dstate;
  197. ap = &Asy[ifp->dev];
  198. if(ap->msr & MSR_RLSD){
  199. dialer->localdrops++;
  200. redial(ifp,dialer->dropfile); /* Drop only if still up */
  201. }
  202. }
  203. void
  204. sd_answer(dev,p1,p2)
  205. int dev;
  206. void *p1,*p2;
  207. {
  208. struct iface *ifp;
  209. struct asydialer *dialer;
  210. struct asy *asyp;
  211. ifp = (struct iface *)p1;
  212. asyp = &Asy[dev];
  213. dialer = (struct asydialer *)ifp->dstate;
  214. if(dialer == NULL)
  215. return; /* Can't happen */
  216. for(;;){
  217. while((asyp->msr & MSR_TERI) == 0)
  218. kwait(&asyp->msr);
  219. asyp->msr &= ~MSR_TERI;
  220. dialer->answers++;
  221. redial(ifp,dialer->ansfile);
  222. }
  223. }
  224. /* execute dialer commands
  225.  * returns: -1 fatal error, 0 OK, 1 try again
  226.  */
  227. static int
  228. redial(ifp,file)
  229. struct iface *ifp;
  230. char *file;
  231. {
  232. char *inbuf;
  233. FILE *fp;
  234. int (*rawsave)(struct iface *,struct mbuf **);
  235. int result = 0;
  236. if((fp = fopen(file,READ_TEXT)) == NULL){
  237. if(ifp->trace & (IF_TRACE_IN|IF_TRACE_OUT))
  238. tprintf(ifp,"redial: can't read %sn",file);
  239. return -1;
  240. }
  241. /* Save output handler and temporarily redirect output to null */
  242. if(ifp->raw == bitbucket){
  243. if(ifp->trace & (IF_TRACE_IN|IF_TRACE_OUT))
  244. tprintf(ifp,"redial: tip or dialer already active on %sn",ifp->name);
  245. return -1;
  246. }
  247. if(ifp->trace & (IF_TRACE_IN|IF_TRACE_OUT))
  248. tprintf(ifp,"Commands to %s:n",ifp->name);
  249. /* Save output handler and temporarily redirect output to null */
  250. rawsave = ifp->raw;
  251. ifp->raw = bitbucket;
  252. /* Suspend the packet input driver. Note that the transmit driver
  253.  * is left running since we use it to send buffers to the line.
  254.  */
  255. suspend(ifp->rxproc);
  256. inbuf = mallocw(BUFSIZ);
  257. while(fgets(inbuf,BUFSIZ,fp) != NULL){
  258. rip(inbuf);
  259. logmsg(-1,"%s dialer: %s",ifp->name,inbuf);
  260. if(ifp->trace & (IF_TRACE_IN|IF_TRACE_OUT))
  261. tprintf(ifp,"%sn",inbuf);
  262. if((result = cmdparse(Dial_cmds,inbuf,ifp)) != 0){
  263. break;
  264. }
  265. }
  266. free(inbuf);
  267. fclose(fp);
  268. if(result == 0){
  269. ifp->lastsent = ifp->lastrecv = secclock();
  270. }
  271. ifp->raw = rawsave;
  272. resume(ifp->rxproc);
  273. if(ifp->trace & (IF_TRACE_IN|IF_TRACE_OUT))
  274. tprintf(ifp,"nDial %s completen",ifp->name);
  275. return result;
  276. }
  277. static int
  278. dodial_control(argc,argv,p)
  279. int argc;
  280. char *argv[];
  281. void *p;
  282. {
  283. struct iface *ifp = p;
  284. int param;
  285. int32 arg = 0;
  286. if(ifp->ioctl == NULL)
  287. return -1;
  288. if((param = devparam(argv[1])) == -1) 
  289. return -1;
  290. if(argc > 2)
  291. arg = atol(argv[2]);
  292. (*ifp->ioctl)(ifp,param,TRUE,arg);
  293. return 0;
  294. }
  295. static int
  296. dodial_send(argc,argv,p)
  297. int argc;
  298. char *argv[];
  299. void *p;
  300. {
  301. struct iface *ifp = p;
  302. struct mbuf *bp;
  303. if(argc > 2){
  304. /* Send characters with inter-character delay
  305.  * (for dealing with prehistoric Micom switches that
  306.  * can't take back-to-back characters...yes, they
  307.  * still exist.)
  308.  */
  309. char *cp;
  310. int32 cdelay = atol(argv[2]);
  311. for(cp = argv[1];*cp != '';cp++){
  312. asy_write(ifp->dev,(uint8 *)cp,1);
  313. ppause(cdelay);
  314. }
  315. } else {
  316. if (ifp->trace & IF_TRACE_RAW)
  317. raw_dump( ifp, IF_TRACE_OUT, bp );
  318. asy_write(ifp->dev,(uint8 *)argv[1],strlen(argv[1]));
  319. }
  320. return 0;
  321. }
  322. static int
  323. dodial_speed(argc,argv,p)
  324. int argc;
  325. char *argv[];
  326. void *p;
  327. {
  328. struct iface *ifp = p;
  329. if ( argc < 2 ) {
  330. if(ifp->trace & (IF_TRACE_IN|IF_TRACE_OUT))
  331. tprintf(ifp,"current speed = %u bpsn", Asy[ifp->dev].speed);
  332. return 0;
  333. }
  334. return asy_speed(ifp->dev,(uint16)atol(argv[1]));
  335. }
  336. static int
  337. dodial_status(argc,argv,p)
  338. int argc;
  339. char *argv[];
  340. void *p;
  341. {
  342. struct iface *ifp = p;
  343. int param;
  344. if(ifp->iostatus == NULL)
  345. return -1;
  346. if((param = devparam(argv[1])) == -1)
  347. return -1;
  348. (*ifp->iostatus)(ifp,param,atol(argv[2]));
  349. return 0;
  350. }
  351. static int
  352. dodial_wait(argc,argv,p)
  353. int argc;
  354. char *argv[];
  355. void *p;
  356. {
  357. struct iface *ifp = p;
  358. register int c = -1;
  359. char *cp;
  360. kalarm(atol(argv[1]));
  361. if(argc == 2){
  362. while((c = get_asy(ifp->dev)) != -1 && errno != EALARM){
  363. if(ifp->trace & IF_TRACE_IN){
  364. fputc(c,ifp->trfp);
  365. fflush(ifp->trfp);
  366. }
  367. }
  368. kalarm(0L);
  369. return 0;
  370. }
  371. /* argc > 2 */
  372. cp = argv[2];
  373. while(*cp != '' && (c = get_asy(ifp->dev)) != -1){
  374. if(ifp->trace & IF_TRACE_IN){
  375. fputc(c,ifp->trfp);
  376. fflush(ifp->trfp);
  377. }
  378. if(*cp++ != c){
  379. cp = argv[2];
  380. }
  381. }
  382. if(argc > 3){
  383. uint16 speed = 0;
  384. if(stricmp(argv[3], "speed") != 0)
  385. return -1;
  386. while((c = get_asy(ifp->dev)) != -1){
  387. if(ifp->trace & IF_TRACE_IN){
  388. fputc(c,ifp->trfp);
  389. fflush(ifp->trfp);
  390. }
  391. if(isdigit(c)){
  392. speed *= 10;
  393. speed += c - '0';
  394. } else {
  395. kalarm(0L);
  396. return asy_speed(ifp->dev,speed);
  397. }
  398. }
  399. }
  400. kalarm(0L);
  401. return (c == -1);
  402. }