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

TCP/IP协议栈

开发平台:

Visual C++

  1. /* "Dumb terminal" mailbox interface
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  *
  4.  * May '91 Bill Simpson
  5.  * move to separate file for compilation & linking
  6.  * Sep '91 Bill Simpson
  7.  * minor changes for DTR & RLSD
  8.  */
  9. #include "global.h"
  10. #include "mbuf.h"
  11. #include "timer.h"
  12. #include "proc.h"
  13. #include "iface.h"
  14. #ifndef UNIX
  15. #include "n8250.h"
  16. #endif
  17. #include "asy.h"
  18. #include "socket.h"
  19. #include "usock.h"
  20. #include "telnet.h"
  21. #include "mailbox.h"
  22. #include "tipmail.h"
  23. #include "devparam.h"
  24. static struct tipcb {
  25. struct tipcb *next;
  26. struct proc *proc;
  27. struct proc *in;
  28. struct iface *iface;
  29. int (*rawsave)(struct iface *,struct mbuf **);
  30. FILE *network;
  31. int echo;
  32. struct timer timer;
  33. } *Tiplist;
  34. #define NULLTIP (struct tipcb *)0
  35. static void tip_in(int dev,void *n1,void *n2);
  36. static void tipidle(void *t);
  37. unsigned Tiptimeout = 180; /* Default tip inactivity timeout (seconds) */
  38. /* Input process */
  39. static void
  40. tip_in(dev,n1,n2)
  41. int dev;
  42. void *n1,*n2;
  43. {
  44. struct tipcb *tip;
  45. struct mbuf *bp;
  46. char *buf[2], line[MBXLINE];
  47. int c, ret, pos = 0;
  48. tip = (struct tipcb *) n1;
  49. while((c = get_asy(dev)) != -1){
  50. Asy[dev].iface->lastrecv = secclock();
  51. ret = 0;
  52. if(tip->echo == WONT){
  53. switch(c){
  54. case 18: /* CTRL-R */
  55. bp = NULL;
  56. pushdown(&bp,line,pos);
  57. pushdown(&bp,"^Rrn",4);
  58. ret = 1;
  59. break;
  60. case 0x7f: /* DEL */
  61. case 'b':
  62. bp = NULL;
  63. if(pos){
  64. --pos;
  65. bp = qdata("b b",3);
  66. }
  67. ret = 1;
  68. break;
  69. case 'r':
  70. c = 'n'; /* CR => NL */
  71. case 'n':
  72. bp = qdata("rn",2);
  73. break;
  74. default:
  75. bp = NULL;
  76. pushdown(&bp,NULL,1);
  77. *bp->data = c;
  78. break;
  79. }
  80. asy_send(dev,&bp);
  81. tip->iface->lastsent = secclock();
  82. if(ret)
  83. continue;
  84. }
  85. line[pos++] = c;
  86. if(pos == MBXLINE - 1 || tip->echo == WILL
  87.   || c == 'n'){
  88. line[pos] = '';
  89. pos = 0;
  90. fputs(line,tip->network);
  91. fflush(tip->network);
  92. }
  93. }
  94. /* get_asy() failed, terminate */
  95. fclose(tip->network);
  96. tip->in = tip->proc;
  97. tip->proc = Curproc;
  98. buf[1] = Asy[dev].iface->name;
  99. tip0(2,buf,NULL);
  100. }
  101. /* Start mailbox on serial line */
  102. int
  103. tipstart(argc,argv,p)
  104. int argc;
  105. char *argv[];
  106. void *p;
  107. {
  108. register struct iface *ifp;
  109. register struct asy *ap;
  110. struct tipcb *tip;
  111. struct mbuf *bp;
  112. char *buf[2];
  113. int dev, c, cmd, s[2], type = TIP;
  114. if((ifp = if_lookup(argv[1])) == NULL){
  115. printf("Interface %s unknownn",argv[1]);
  116. return 1;
  117. }
  118. for(dev=0,ap = Asy;dev < ASY_MAX;dev++,ap++)
  119. if(ap->iface == ifp)
  120. break;
  121. if(dev == ASY_MAX){
  122. printf("Interface %s not asy portn",argv[1]);
  123. return 1;
  124. }
  125. if(ifp->raw == bitbucket){
  126. printf("Tip session already active on %sn",argv[1]);
  127. return 1;
  128. }
  129. ksignal(Curproc,0); /* Don't keep the parser waiting */
  130. chname(Curproc,"Mbox tip");
  131. tip = (struct tipcb *) callocw(1,sizeof(struct tipcb));
  132. /* Save output handler and temporarily redirect output to null */
  133. tip->rawsave = ifp->raw;
  134. ifp->raw = bitbucket;
  135. tip->iface = ifp;
  136. tip->proc = Curproc;
  137. tip->timer.func = tipidle;
  138. tip->timer.arg = (void *) tip;
  139. tip->next = Tiplist;
  140. Tiplist = tip;
  141. buf[1] = ifp->name;
  142. /* Suspend packet input drivers */
  143. suspend(ifp->rxproc);
  144. for(;;) {
  145. /* Wait for DCD to be asserted */
  146. get_rlsd_asy(dev,1);
  147. if(socketpair(AF_LOCAL,SOCK_STREAM,0,s) == -1){
  148. printf("Could not create socket pair, errno %dn",errno);
  149. tip0(2,buf,p);
  150. return 1;
  151. }
  152. tip->echo = WONT;
  153. tip->network = fdopen(s[0],"r+t");
  154. newproc("mbx_incom",2048,mbx_incom,s[1],(void *)type,NULL,0);
  155. set_timer(&tip->timer,Tiptimeout*1000);
  156. start_timer(&tip->timer);
  157. /* Now fork into two paths, one rx, one tx */
  158. tip->in = newproc("Mbox tip in",
  159. 256,tip_in,dev,(void *)tip,NULL,0);
  160. while((c = getc(tip->network)) != -1) {
  161. if(c == IAC){ /* ignore most telnet options */
  162. if((cmd = getc(tip->network)) == -1)
  163. break;
  164. if(cmd > 250 && cmd < 255) {
  165. if((c = getc(tip->network)) == -1)
  166. break;
  167. switch(cmd){
  168. case WILL:
  169. if(c == TN_ECHO) {
  170. tip->echo = cmd;
  171. cmd = DO;
  172. }
  173. else
  174. cmd = DONT;
  175. break;
  176. case WONT:
  177. if(c == TN_ECHO)
  178. tip->echo = cmd;
  179. cmd = DONT;
  180. break;
  181. case DO:
  182. case DONT:
  183. cmd = WONT;
  184. break;
  185. }
  186. fprintf(tip->network,"%c%c%c",IAC,cmd,c);
  187. fflush(tip->network);
  188. }
  189. continue;
  190. }
  191. if(c == 'n')
  192. bp = qdata("rn",2);
  193. else {
  194. bp = NULL;
  195. pushdown(&bp,NULL,1);
  196. *bp->data = c;
  197. }
  198. asy_send(dev,&bp);
  199. ifp->lastsent = secclock();
  200. }
  201. fclose(tip->network);
  202. killproc(tip->in);
  203. tip->in = NULL;
  204. kwait(itop(s[1])); /* let mailbox terminate, if necessary */
  205. stop_timer(&tip->timer);
  206. /* Tell line to go down */
  207. ifp->ioctl(ifp,PARAM_DOWN,TRUE,0L);
  208. /* Wait for DCD to be dropped */
  209. get_rlsd_asy(dev,0);
  210. }
  211. }
  212. int
  213. tip0(argc,argv,p)
  214. int argc;
  215. char *argv[];
  216. void *p;
  217. {
  218. register struct iface *ifp;
  219. struct tipcb *tip, *prev = NULLTIP;
  220. struct proc *proc;
  221. if((ifp = if_lookup(argv[1])) == NULL){
  222. printf("Interface %s unknownn",argv[1]);
  223. return 1;
  224. }
  225. for(tip = Tiplist; tip != NULLTIP; prev = tip, tip = tip->next)
  226. if(tip->iface == ifp) {
  227. if(prev != NULLTIP)
  228. prev->next = tip->next;
  229. else
  230. Tiplist = tip->next;
  231. proc = tip->proc;
  232. fclose(tip->network);
  233. ifp->raw = tip->rawsave;
  234. resume(ifp->rxproc);
  235. stop_timer(&tip->timer);
  236. killproc(tip->in);
  237. free(tip);
  238. killproc(proc);
  239. return 0;
  240. }
  241. return 0;
  242. }
  243. static void
  244. tipidle(t)
  245. void *t;
  246. {
  247. struct tipcb *tip;
  248. static char *msg = "You have been idle too long. Please hang up.rn";
  249. struct mbuf *bp;
  250. tip = (struct tipcb *) t;
  251. if(secclock() - tip->iface->lastrecv < Tiptimeout){
  252. set_timer(&tip->timer,(Tiptimeout-secclock() *
  253.  tip->iface->lastrecv)*1000);
  254. start_timer(&tip->timer);
  255. return;
  256. }
  257. bp = qdata(msg,strlen(msg));
  258. asy_send(tip->iface->dev,&bp);
  259. tip->iface->lastsent = secclock();
  260. fclose(tip->network);
  261. }
  262. static int Stelnet = -1;
  263. /* Start up Telnet server */
  264. int
  265. telnet1(argc,argv,p)
  266. int argc;
  267. char *argv[];
  268. void *p;
  269. {
  270. struct sockaddr_in lsocket;
  271. int s;
  272. int type;
  273. if(Stelnet != -1){
  274. return 0;
  275. }
  276. ksignal(Curproc,0);  /* Don't keep the parser waiting */
  277. chname(Curproc,"Telnet listener");
  278. lsocket.sin_family = AF_INET;
  279. lsocket.sin_addr.s_addr = INADDR_ANY;
  280. if(argc < 2)
  281. lsocket.sin_port = IPPORT_TELNET;
  282. else
  283. lsocket.sin_port = atoi(argv[1]);
  284. Stelnet = socket(AF_INET,SOCK_STREAM,0);
  285. bind(Stelnet,(struct sockaddr *)&lsocket,sizeof(lsocket));
  286. listen(Stelnet,1);
  287. for(;;){
  288. if((s = accept(Stelnet,NULL,(int *)NULL)) == -1)
  289. break; /* Service is shutting down */
  290. if(availmem() != 0){
  291. shutdown(s,1);
  292. } else {
  293. /* Spawn a server */
  294. type = TELNET;
  295. newproc("mbox",2048,mbx_incom,s,(void *)type,NULL,0);
  296. }
  297. }
  298. return 0;
  299. }
  300. /* Stop telnet server */
  301. int
  302. telnet0(argc,argv,p)
  303. int argc;
  304. char *argv[];
  305. void *p;
  306. {
  307. close_s(Stelnet);
  308. Stelnet = -1;
  309. return 0;
  310. }