gre.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "../port/error.h"
  7. #include "ip.h"
  8. #define DPRINT if(0)print
  9. enum
  10. {
  11. GRE_IPONLY = 12, /* size of ip header */
  12. GRE_IPPLUSGRE = 12, /* minimum size of GRE header */
  13. IP_GREPROTO = 47,
  14. GRErxms = 200,
  15. GREtickms = 100,
  16. GREmaxxmit = 10,
  17. };
  18. typedef struct GREhdr
  19. {
  20. /* ip header */
  21. uchar vihl; /* Version and header length */
  22. uchar tos; /* Type of service */
  23. uchar len[2]; /* packet length (including headers) */
  24. uchar id[2]; /* Identification */
  25. uchar frag[2]; /* Fragment information */
  26. uchar Unused;
  27. uchar proto; /* Protocol */
  28. uchar cksum[2]; /* checksum */
  29. uchar src[4]; /* Ip source */
  30. uchar dst[4]; /* Ip destination */
  31. /* gre header */
  32. uchar flags[2];
  33. uchar eproto[2]; /* encapsulation protocol */
  34. } GREhdr;
  35. typedef struct GREpriv GREpriv;
  36. struct GREpriv
  37. {
  38. int raw; /* Raw GRE mode */
  39. /* non-MIB stats */
  40. ulong csumerr; /* checksum errors */
  41. ulong lenerr; /* short packet */
  42. };
  43. static void grekick(void *x, Block *bp);
  44. static char*
  45. greconnect(Conv *c, char **argv, int argc)
  46. {
  47. Proto *p;
  48. char *err;
  49. Conv *tc, **cp, **ecp;
  50. err = Fsstdconnect(c, argv, argc);
  51. if(err != nil)
  52. return err;
  53. /* make sure noone's already connected to this other sys */
  54. p = c->p;
  55. qlock(p);
  56. ecp = &p->conv[p->nc];
  57. for(cp = p->conv; cp < ecp; cp++){
  58. tc = *cp;
  59. if(tc == nil)
  60. break;
  61. if(tc == c)
  62. continue;
  63. if(tc->rport == c->rport && ipcmp(tc->raddr, c->raddr) == 0){
  64. err = "already connected to that addr/proto";
  65. ipmove(c->laddr, IPnoaddr);
  66. ipmove(c->raddr, IPnoaddr);
  67. break;
  68. }
  69. }
  70. qunlock(p);
  71. if(err != nil)
  72. return err;
  73. Fsconnected(c, nil);
  74. return nil;
  75. }
  76. static void
  77. grecreate(Conv *c)
  78. {
  79. c->rq = qopen(64*1024, Qmsg, 0, c);
  80. c->wq = qbypass(grekick, c);
  81. }
  82. static int
  83. grestate(Conv *c, char *state, int n)
  84. {
  85. USED(c);
  86. return snprint(state, n, "%s", "Datagram");
  87. }
  88. static char*
  89. greannounce(Conv*, char**, int)
  90. {
  91. return "pktifc does not support announce";
  92. }
  93. static void
  94. greclose(Conv *c)
  95. {
  96. qclose(c->rq);
  97. qclose(c->wq);
  98. qclose(c->eq);
  99. ipmove(c->laddr, IPnoaddr);
  100. ipmove(c->raddr, IPnoaddr);
  101. c->lport = 0;
  102. c->rport = 0;
  103. }
  104. int drop;
  105. static void
  106. grekick(void *x, Block *bp)
  107. {
  108. Conv *c = x;
  109. GREhdr *ghp;
  110. uchar laddr[IPaddrlen], raddr[IPaddrlen];
  111. if(bp == nil)
  112. return;
  113. /* Make space to fit ip header (gre header already there) */
  114. bp = padblock(bp, GRE_IPONLY);
  115. if(bp == nil)
  116. return;
  117. /* make sure the message has a GRE header */
  118. bp = pullupblock(bp, GRE_IPONLY+GRE_IPPLUSGRE);
  119. if(bp == nil)
  120. return;
  121. ghp = (GREhdr *)(bp->rp);
  122. ghp->vihl = IP_VER4;
  123. if(!((GREpriv*)c->p->priv)->raw){
  124. v4tov6(raddr, ghp->dst);
  125. if(ipcmp(raddr, v4prefix) == 0)
  126. memmove(ghp->dst, c->raddr + IPv4off, IPv4addrlen);
  127. v4tov6(laddr, ghp->src);
  128. if(ipcmp(laddr, v4prefix) == 0){
  129. if(ipcmp(c->laddr, IPnoaddr) == 0)
  130. findlocalip(c->p->f, c->laddr, raddr); /* pick interface closest to dest */
  131. memmove(ghp->src, c->laddr + IPv4off, IPv4addrlen);
  132. }
  133. hnputs(ghp->eproto, c->rport);
  134. }
  135. ghp->proto = IP_GREPROTO;
  136. ghp->frag[0] = 0;
  137. ghp->frag[1] = 0;
  138. ipoput4(c->p->f, bp, 0, c->ttl, c->tos, nil);
  139. }
  140. static void
  141. greiput(Proto *gre, Ipifc*, Block *bp)
  142. {
  143. int len;
  144. GREhdr *ghp;
  145. Conv *c, **p;
  146. ushort eproto;
  147. uchar raddr[IPaddrlen];
  148. GREpriv *gpriv;
  149. gpriv = gre->priv;
  150. ghp = (GREhdr*)(bp->rp);
  151. v4tov6(raddr, ghp->src);
  152. eproto = nhgets(ghp->eproto);
  153. qlock(gre);
  154. /* Look for a conversation structure for this port and address */
  155. c = nil;
  156. for(p = gre->conv; *p; p++) {
  157. c = *p;
  158. if(c->inuse == 0)
  159. continue;
  160. if(c->rport == eproto &&
  161. (gpriv->raw || ipcmp(c->raddr, raddr) == 0))
  162. break;
  163. }
  164. if(*p == nil) {
  165. qunlock(gre);
  166. freeblist(bp);
  167. return;
  168. }
  169. qunlock(gre);
  170. /*
  171. * Trim the packet down to data size
  172. */
  173. len = nhgets(ghp->len) - GRE_IPONLY;
  174. if(len < GRE_IPPLUSGRE){
  175. freeblist(bp);
  176. return;
  177. }
  178. bp = trimblock(bp, GRE_IPONLY, len);
  179. if(bp == nil){
  180. gpriv->lenerr++;
  181. return;
  182. }
  183. /*
  184. * Can't delimit packet so pull it all into one block.
  185. */
  186. if(qlen(c->rq) > 64*1024)
  187. freeblist(bp);
  188. else{
  189. bp = concatblock(bp);
  190. if(bp == 0)
  191. panic("greiput");
  192. qpass(c->rq, bp);
  193. }
  194. }
  195. int
  196. grestats(Proto *gre, char *buf, int len)
  197. {
  198. GREpriv *gpriv;
  199. gpriv = gre->priv;
  200. return snprint(buf, len, "gre: len %lud\n", gpriv->lenerr);
  201. }
  202. char*
  203. grectl(Conv *c, char **f, int n)
  204. {
  205. GREpriv *gpriv;
  206. gpriv = c->p->priv;
  207. if(n == 1){
  208. if(strcmp(f[0], "raw") == 0){
  209. gpriv->raw = 1;
  210. return nil;
  211. }
  212. else if(strcmp(f[0], "cooked") == 0){
  213. gpriv->raw = 0;
  214. return nil;
  215. }
  216. }
  217. return "unknown control request";
  218. }
  219. void
  220. greinit(Fs *fs)
  221. {
  222. Proto *gre;
  223. gre = smalloc(sizeof(Proto));
  224. gre->priv = smalloc(sizeof(GREpriv));
  225. gre->name = "gre";
  226. gre->connect = greconnect;
  227. gre->announce = greannounce;
  228. gre->state = grestate;
  229. gre->create = grecreate;
  230. gre->close = greclose;
  231. gre->rcv = greiput;
  232. gre->ctl = grectl;
  233. gre->advise = nil;
  234. gre->stats = grestats;
  235. gre->ipproto = IP_GREPROTO;
  236. gre->nc = 64;
  237. gre->ptclsize = 0;
  238. Fsproto(fs, gre);
  239. }