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

TCP/IP协议栈

开发平台:

Visual C++

  1. /* SLIP (Serial Line IP) encapsulation and control routines.
  2.  * Copyright 1991 Phil Karn
  3.  *
  4.  * Van Jacobsen header compression hooks added by Katie Stevens, UC Davis
  5.  *
  6.  * - Feb 1991 Bill_Simpson@um.cc.umich.edu
  7.  * reflect changes to header compression calls
  8.  * revise status display
  9.  */
  10. #include <stdio.h>
  11. #include "global.h"
  12. #include "mbuf.h"
  13. #include "iface.h"
  14. #include "ip.h"
  15. #include "slhc.h"
  16. #include "asy.h"
  17. #include "slip.h"
  18. #include "trace.h"
  19. #include "pktdrvr.h"
  20. static struct mbuf *slip_decode(struct slip *sp,uint8 c);
  21. static struct mbuf *slip_encode(struct mbuf **bpp);
  22. /* Slip level control structure */
  23. struct slip Slip[SLIP_MAX];
  24. int
  25. slip_init(ifp)
  26. struct iface *ifp;
  27. {
  28. int xdev;
  29. struct slip *sp;
  30. char *ifn;
  31. for(xdev = 0;xdev < SLIP_MAX;xdev++){
  32. sp = &Slip[xdev];
  33. if(sp->iface == NULL)
  34. break;
  35. }
  36. if(xdev >= SLIP_MAX) {
  37. printf("Too many slip devicesn");
  38. return -1;
  39. }
  40. ifp->ioctl = asy_ioctl;
  41. ifp->raw = slip_raw;
  42. ifp->show = slip_status;
  43. ifp->xdev = xdev;
  44. sp->iface = ifp;
  45. sp->send = asy_send;
  46. sp->get = get_asy;
  47. sp->type = CL_SERIAL_LINE;
  48. if(ifp->send == vjslip_send){
  49. sp->slcomp = slhc_init(16,16);
  50. }
  51. ifp->rxproc = newproc( ifn = if_name( ifp, " rx" ),
  52. 512,slip_rx,xdev,NULL,NULL,0);
  53. free(ifn);
  54. return 0;
  55. }
  56. int
  57. slip_free(ifp)
  58. struct iface *ifp;
  59. {
  60. struct slip *sp;
  61. sp = &Slip[ifp->xdev];
  62. if(sp->slcomp != NULL){
  63. slhc_free(sp->slcomp);
  64. sp->slcomp = NULL;
  65. }
  66. sp->iface = NULL;
  67. return 0;
  68. }
  69. /* Send routine for point-to-point slip, no VJ header compression */
  70. int
  71. slip_send(
  72. struct mbuf **bpp, /* Buffer to send */
  73. struct iface *iface, /* Pointer to interface control block */
  74. int32 gateway, /* Ignored (SLIP is point-to-point) */
  75. uint8 tos
  76. ){
  77. if(iface == NULL){
  78. free_p(bpp);
  79. return -1;
  80. }
  81. return (*iface->raw)(iface,bpp);
  82. }
  83. /* Send routine for point-to-point slip, with VJ header compression */
  84. int
  85. vjslip_send(
  86. struct mbuf **bpp, /* Buffer to send */
  87. struct iface *iface, /* Pointer to interface control block */
  88. int32 gateway, /* Ignored (SLIP is point-to-point) */
  89. uint8 tos
  90. ){
  91. register struct slip *sp;
  92. int type;
  93. if(iface == NULL){
  94. free_p(bpp);
  95. return -1;
  96. }
  97. sp = &Slip[iface->xdev];
  98. /* Attempt IP/ICP header compression */
  99. type = slhc_compress(sp->slcomp,bpp,TRUE);
  100. (*bpp)->data[0] |= type;
  101. return (*iface->raw)(iface,bpp);
  102. }
  103. /* Send a raw slip frame */
  104. int
  105. slip_raw(
  106. struct iface *iface,
  107. struct mbuf **bpp
  108. ){
  109. struct mbuf *bp1;
  110. dump(iface,IF_TRACE_OUT,*bpp);
  111. iface->rawsndcnt++;
  112. iface->lastsent = secclock();
  113. if((bp1 = slip_encode(bpp)) == NULL){
  114. return -1;
  115. }
  116. if (iface->trace & IF_TRACE_RAW)
  117. raw_dump(iface,-1,bp1);
  118. return Slip[iface->xdev].send(iface->dev,&bp1);
  119. }
  120. /* Encode a packet in SLIP format */
  121. static
  122. struct mbuf *
  123. slip_encode(struct mbuf **bpp)
  124. {
  125. struct mbuf *lbp; /* Mbuf containing line-ready packet */
  126. register uint8 *cp;
  127. int c;
  128. /* Allocate output mbuf that's twice as long as the packet.
  129.  * This is a worst-case guess (consider a packet full of FR_ENDs!)
  130.  */
  131. lbp = alloc_mbuf((uint16)(2*len_p(*bpp) + 2));
  132. if(lbp == NULL){
  133. /* No space; drop */
  134. free_p(bpp);
  135. return NULL;
  136. }
  137. cp = lbp->data;
  138. /* Flush out any line garbage */
  139. *cp++ = FR_END;
  140. /* Copy input to output, escaping special characters */
  141. while((c = PULLCHAR(bpp)) != -1){
  142. switch(c){
  143. case FR_ESC:
  144. *cp++ = FR_ESC;
  145. *cp++ = T_FR_ESC;
  146. break;
  147. case FR_END:
  148. *cp++ = FR_ESC;
  149. *cp++ = T_FR_END;
  150. break;
  151. default:
  152. *cp++ = c;
  153. }
  154. }
  155. *cp++ = FR_END;
  156. lbp->cnt = cp - lbp->data;
  157. return lbp;
  158. }
  159. /* Process incoming bytes in SLIP format
  160.  * When a buffer is complete, return it; otherwise NULL
  161.  */
  162. static
  163. struct mbuf *
  164. slip_decode(sp,c)
  165. register struct slip *sp;
  166. uint8 c; /* Incoming character */
  167. {
  168. struct mbuf *bp;
  169. switch(c){
  170. case FR_END:
  171. bp = sp->rbp_head;
  172. sp->rbp_head = NULL;
  173. if(sp->escaped){
  174. /* Treat this as an abort - discard frame */
  175. free_p(&bp);
  176. bp = NULL;
  177. }
  178. sp->escaped &= ~SLIP_FLAG;
  179. return bp; /* Will be NULL if empty frame */
  180. case FR_ESC:
  181. sp->escaped |= SLIP_FLAG;
  182. return NULL;
  183. }
  184. if(sp->escaped & SLIP_FLAG){
  185. /* Translate 2-char escape sequence back to original char */
  186. sp->escaped &= ~SLIP_FLAG;
  187. switch(c){
  188. case T_FR_ESC:
  189. c = FR_ESC;
  190. break;
  191. case T_FR_END:
  192. c = FR_END;
  193. break;
  194. default:
  195. sp->errors++;
  196. break;
  197. }
  198. }
  199. /* We reach here with a character for the buffer;
  200.  * make sure there's space for it
  201.  */
  202. if(sp->rbp_head == NULL){
  203. /* Allocate first mbuf for new packet */
  204. if((sp->rbp_tail = sp->rbp_head = alloc_mbuf(SLIP_ALLOC)) == NULL)
  205. return NULL; /* No memory, drop */
  206. sp->rcp = sp->rbp_head->data;
  207. } else if(sp->rbp_tail->cnt == SLIP_ALLOC){
  208. /* Current mbuf is full; link in another */
  209. if((sp->rbp_tail->next = alloc_mbuf(SLIP_ALLOC)) == NULL){
  210. /* No memory, drop whole thing */
  211. free_p(&sp->rbp_head);
  212. sp->rbp_head = NULL;
  213. return NULL;
  214. }
  215. sp->rbp_tail = sp->rbp_tail->next;
  216. sp->rcp = sp->rbp_tail->data;
  217. }
  218. /* Store the character, increment fragment and total
  219.  * byte counts
  220.  */
  221. *sp->rcp++ = c;
  222. sp->rbp_tail->cnt++;
  223. return NULL;
  224. }
  225. /* Process SLIP line input */
  226. void
  227. slip_rx(xdev,p1,p2)
  228. int xdev;
  229. void *p1;
  230. void *p2;
  231. {
  232. int c;
  233. struct mbuf *bp;
  234. register struct slip *sp;
  235. int cdev;
  236. sp = &Slip[xdev];
  237. cdev = sp->iface->dev;
  238. while ( (c = sp->get(cdev)) != -1 ) {
  239. if((bp = slip_decode(sp,c)) == NULL)
  240. continue; /* More to come */
  241. if (sp->iface->trace & IF_TRACE_RAW)
  242. raw_dump(sp->iface,IF_TRACE_IN,bp);
  243. if ((c = bp->data[0]) & SL_TYPE_COMPRESSED_TCP) {
  244. if ( slhc_uncompress(sp->slcomp, &bp) <= 0 ) {
  245. free_p(&bp);
  246. sp->errors++;
  247. continue;
  248. }
  249. } else if (c >= SL_TYPE_UNCOMPRESSED_TCP) {
  250. bp->data[0] &= 0x4f;
  251. if ( slhc_remember(sp->slcomp, &bp) <= 0 ) {
  252. free_p(&bp);
  253. sp->errors++;
  254. continue;
  255. }
  256. }
  257. net_route( sp->iface, &bp);
  258. /* Especially on slow machines, serial I/O can be quite
  259.  * compute intensive, so release the machine before we
  260.  * do the next packet.  This will allow this packet to
  261.  * go on toward its ultimate destination. [Karn]
  262.  */
  263. kwait(NULL);
  264. }
  265. if(sp->iface->rxproc == Curproc)
  266. sp->iface->rxproc = NULL;
  267. }
  268. /* Show serial line status */
  269. void
  270. slip_status(iface)
  271. struct iface *iface;
  272. {
  273. struct slip *sp;
  274. if (iface->xdev > SLIP_MAX)
  275. /* Must not be a SLIP device */
  276. return;
  277. sp = &Slip[iface->xdev];
  278. if (sp->iface != iface)
  279. /* Must not be a SLIP device */
  280. return;
  281. slhc_i_status(sp->slcomp);
  282. slhc_o_status(sp->slcomp);
  283. }