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

TCP/IP协议栈

开发平台:

Visual C++

  1. /* This module implements the serial line framing method used by
  2.  * net/rom nodes.  This allows the net/rom software to talk to
  3.  * an actual net/rom over its serial interface, which is useful
  4.  * if we want to do packet switching for multi-line wormholes.
  5.  *
  6.  * Copyright 1989 Dan Frank, W9NK
  7.  */
  8. #include <stdio.h>
  9. #include "global.h"
  10. #include "mbuf.h"
  11. #include "iface.h"
  12. #include "pktdrvr.h"
  13. #include "ax25.h"
  14. #include "nrs.h"
  15. #include "asy.h"
  16. #include "trace.h"
  17. #include "commands.h"
  18. static struct mbuf *nrs_encode(struct mbuf *bp);
  19. static struct mbuf *nrs_decode(int dev,uint8 c);
  20. /* control structures, sort of overlayed on async control blocks */
  21. struct nrs Nrs[ASY_MAX];
  22. int
  23. nrs_init(ifp)
  24. struct iface *ifp;
  25. {
  26. int xdev;
  27. struct nrs *np;
  28. char *ifn;
  29. /* Set up a net/rom serial iface */
  30. for(xdev = 0;xdev < NRS_MAX;xdev++){
  31. np = &Nrs[xdev];
  32. if(np->iface == NULL)
  33. break;
  34. }
  35. if(xdev >= NRS_MAX) {
  36. printf("Too many nrs devicesn");
  37. return -1;
  38. }
  39. /* no call supplied? */
  40. ifp->ioctl = asy_ioctl;
  41. ifp->raw = nrs_raw;
  42. ifp->hwaddr = mallocw(AXALEN);
  43. memcpy(ifp->hwaddr,Mycall,AXALEN);
  44. ifp->xdev = xdev;
  45. np->iface = ifp;
  46. np->send = asy_send;
  47. np->get = get_asy;
  48. ifp->rxproc = newproc( ifn = if_name( ifp, " nrs" ),
  49. 256,nrs_recv,xdev,NULL,NULL,0);
  50. free(ifn);
  51. return 0;
  52. }
  53. int
  54. nrs_free(ifp)
  55. struct iface *ifp;
  56. {
  57. if(Nrs[ifp->xdev].iface == ifp)
  58. Nrs[ifp->xdev].iface = NULL;
  59. return 0;
  60. }
  61. /* Send a raw net/rom serial frame */
  62. int
  63. nrs_raw(
  64. struct iface *iface,
  65. struct mbuf **bpp
  66. ){
  67. struct mbuf *bp1;
  68. dump(iface,IF_TRACE_OUT,*bpp);
  69. iface->rawsndcnt++;
  70. iface->lastsent = secclock();
  71. if((bp1 = nrs_encode(*bpp)) == NULL){
  72. free_p(bpp);
  73. return -1;
  74. }
  75. return Nrs[iface->xdev].send(iface->dev,&bp1);
  76. }
  77. /* Encode a packet in net/rom serial format */
  78. static struct mbuf *
  79. nrs_encode(bp)
  80. struct mbuf *bp;
  81. {
  82. struct mbuf *lbp; /* Mbuf containing line-ready packet */
  83. register uint8 *cp;
  84. int c;
  85. uint8 csum = 0;
  86. /* Allocate output mbuf that's twice as long as the packet.
  87.  * This is a worst-case guess (consider a packet full of STX's!)
  88.  * Add five bytes for STX, ETX, checksum, and two nulls.
  89.  */
  90. lbp = alloc_mbuf((uint16)(2*len_p(bp) + 5));
  91. if(lbp == NULL){
  92. /* No space; drop */
  93. free_p(&bp);
  94. return NULL;
  95. }
  96. cp = lbp->data;
  97. *cp++ = STX;
  98. /* Copy input to output, escaping special characters */
  99. while((c = PULLCHAR(&bp)) != -1){
  100. switch(c){
  101. case STX:
  102. case ETX:
  103. case DLE:
  104. *cp++ = DLE;
  105. /* notice drop through to default */
  106. default:
  107. *cp++ = c;
  108. }
  109. csum += c;
  110. }
  111. *cp++ = ETX;
  112. *cp++ = csum;
  113. *cp++ = NUL;
  114. *cp++ = NUL;
  115. lbp->cnt = cp - lbp->data;
  116. return lbp;
  117. }
  118. /* Process incoming bytes in net/rom serial format
  119.  * When a buffer is complete, return it; otherwise NULL
  120.  */
  121. static struct mbuf *
  122. nrs_decode(dev,c)
  123. int dev; /* net/rom unit number */
  124. uint8 c; /* Incoming character */
  125. {
  126. struct mbuf *bp;
  127. register struct nrs *sp;
  128. sp = &Nrs[dev];
  129. switch(sp->state) {
  130. case NRS_INTER:
  131. if(c == STX) { /* look for start of frame */
  132. sp->state = NRS_INPACK; /* we're in a packet */
  133. sp->csum = 0; /* reset checksum */
  134. }
  135. return NULL;
  136. case NRS_CSUM:
  137. bp = sp->rbp;
  138. sp->rbp = NULL;
  139. sp->rcnt = 0;
  140. sp->state = NRS_INTER; /* go back to inter-packet state */
  141. if(sp->csum == c) {
  142. sp->packets++;
  143. } else {
  144. free_p(&bp); /* drop packet with bad checksum */
  145. bp = NULL;
  146. sp->errors++; /* increment error count */
  147. }
  148. return bp;
  149. case NRS_ESCAPE:
  150. sp->state = NRS_INPACK; /* end of escape */
  151. break; /* this will drop through to char processing */
  152. case NRS_INPACK:
  153. switch (c) {
  154. /* If we see an STX in a packet, assume that previous */
  155. /* packet was trashed, and start a new packet */
  156. case STX:
  157. free_p(&sp->rbp);
  158. sp->rbp = NULL;
  159. sp->rcnt = 0;
  160. sp->csum = 0;
  161. sp->errors++;
  162. return NULL;
  163. case ETX:
  164. sp->state = NRS_CSUM; /* look for checksum */
  165. return NULL;
  166. case DLE:
  167. sp->state = NRS_ESCAPE;
  168. return NULL;
  169. }
  170. }
  171. /* If we get to here, it's with a character that's part of the packet.
  172.  * Make sure there's space for it.
  173.  */
  174. if(sp->rbp == NULL){
  175. /* Allocate first mbuf for new packet */
  176. if((sp->rbp1 = sp->rbp = alloc_mbuf(NRS_ALLOC)) == NULL) {
  177. sp->state = NRS_INTER;
  178. return NULL; /* No memory, drop */
  179. }
  180. sp->rcp = sp->rbp->data;
  181. } else if(sp->rbp1->cnt == NRS_ALLOC){
  182. /* Current mbuf is full; link in another */
  183. if((sp->rbp1->next = alloc_mbuf(NRS_ALLOC)) == NULL){
  184. /* No memory, drop whole thing */
  185. free_p(&sp->rbp);
  186. sp->rbp = NULL;
  187. sp->rcnt = 0;
  188. sp->state = NRS_INTER;
  189. return NULL;
  190. }
  191. sp->rbp1 = sp->rbp1->next;
  192. sp->rcp = sp->rbp1->data;
  193. }
  194. /* Store the character, increment fragment and total
  195.  * byte counts
  196.  */
  197. *sp->rcp++ = c;
  198. sp->rbp1->cnt++;
  199. sp->rcnt++;
  200. sp->csum += c; /* add to checksum */
  201. return NULL;
  202. }
  203. /* Process net/rom serial line I/O */
  204. void
  205. nrs_recv(dev,v1,v2)
  206. int dev;
  207. void *v1;
  208. void *v2;
  209. {
  210. char c;
  211. struct mbuf *bp;
  212. struct nrs *np;
  213. np = &Nrs[dev];
  214. /* Process any pending input */
  215. while((c = np->get(np->iface->dev)) != EOF){
  216. if((bp = nrs_decode(dev,c)) == NULL)
  217. continue;
  218. net_route(np->iface,&bp);
  219. }
  220. if(np->iface->rxproc == Curproc)
  221. np->iface->rxproc = NULL;
  222. }
  223. /* donrstat:  display status of active net/rom serial interfaces */
  224. int
  225. donrstat(argc,argv,p)
  226. int argc;
  227. char *argv[];
  228. void *p;
  229. {
  230. register struct nrs *np;
  231. register int i;
  232. printf("Interface   RcvB  NumReceived  CSumErrorsn");
  233. for(i = 0, np = Nrs; i < ASY_MAX; i++, np++)
  234. if(np->iface != NULL)
  235. printf(" %8s   %4d   %10lu  %10lun",
  236.  np->iface->name, np->rcnt,
  237.  np->packets, np->errors);
  238. return 0;
  239. }