gre.c 5.0 KB

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