gre.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <ip.h>
  12. #include "dat.h"
  13. #include "protos.h"
  14. /*
  15. GRE version 0 is specified in rfc1701.
  16. GRE version 0 has been respecified in rfc2784 as a subset of rfc1701.
  17. GRE version 1, as used by pptp, has been specified in rfc2637.
  18. */
  19. /* GRE flag bits */
  20. enum {
  21. GRE_chksum = (1<<15),
  22. GRE_routing = (1<<14),
  23. GRE_key = (1<<13),
  24. GRE_seq = (1<<12),
  25. GRE_srcrt = (1<<11),
  26. GRE_recur = (7<<8),
  27. GRE_ack = (1<<7),
  28. GRE_version = 0x7,
  29. };
  30. typedef struct Hdr Hdr;
  31. struct Hdr
  32. {
  33. uint16_t flags;
  34. uint16_t proto;
  35. uint8_t version;
  36. uint16_t chksum;
  37. uint16_t offset;
  38. uint32_t key;
  39. uint32_t seq;
  40. uint32_t route;
  41. uint32_t ack;
  42. };
  43. enum
  44. {
  45. Oproto,
  46. };
  47. static Field p_fields[] =
  48. {
  49. {"proto", Fnum, Oproto, "encapsulated protocol", } ,
  50. {0}
  51. };
  52. static Mux p_mux[] =
  53. {
  54. {"pup", 0x0200, },
  55. {"xns", 0x0600, },
  56. {"ip", 0x0800, },
  57. {"chaos", 0x0804, },
  58. {"arp", 0x0806, },
  59. {"frarp", 0x0808, },
  60. {"vines", 0x0bad, },
  61. {"vinesecho", 0x0bae, },
  62. {"vinesloop", 0x0baf, },
  63. {"ppp", 0x880b, },
  64. {"llc", 0x007a, },
  65. {"dot1q", 0x8100, },
  66. {"eapol", 0x888e, },
  67. {0},
  68. };
  69. int
  70. parthdrlen(uint16_t flags)
  71. {
  72. return 4 +
  73. (flags&GRE_chksum || flags&GRE_routing) ? 4 : 0 +
  74. flags&GRE_key ? 4 : 0 +
  75. flags&GRE_seq ? 4 : 0 +
  76. flags&GRE_ack ? 4 : 0;
  77. }
  78. int
  79. parsehdr(Hdr *h, uint8_t *s, uint8_t *e)
  80. {
  81. uint8_t *p;
  82. uint8_t n;
  83. if(e - s < 4)
  84. return -1;
  85. p = s;
  86. h->flags = NetS(p);
  87. p += 2;
  88. h->proto = NetS(p);
  89. p += 2;
  90. h->version = h->flags&GRE_version;
  91. if(parthdrlen(h->flags) > e - s)
  92. return -1;
  93. if(h->flags&(GRE_chksum|GRE_routing)){
  94. h->chksum = NetS(p);
  95. p += 2;
  96. h->offset = NetS(p);
  97. p += 2;
  98. }
  99. if(h->flags&GRE_key){
  100. h->key = NetL(p);
  101. p += 4;
  102. }
  103. if(h->flags&GRE_seq){
  104. h->seq = NetL(p);
  105. p += 4;
  106. }
  107. if(h->flags&GRE_ack){
  108. h->ack = NetL(p);
  109. p += 4;
  110. }
  111. if(h->flags&GRE_routing){
  112. for(;;){
  113. if(e - p < 4)
  114. return -1;
  115. if((n = p[3]) == 0)
  116. break;
  117. p += n;
  118. }
  119. }
  120. return p - s;
  121. }
  122. static void
  123. p_compile(Filter *f)
  124. {
  125. Mux *m;
  126. if(f->op == '='){
  127. compile_cmp(gre.name, f, p_fields);
  128. return;
  129. }
  130. for(m = p_mux; m->name != nil; m++)
  131. if(strcmp(f->s, m->name) == 0){
  132. f->pr = m->pr;
  133. f->ulv = m->val;
  134. f->subop = Oproto;
  135. return;
  136. }
  137. sysfatal("unknown gre field or protocol: %s", f->s);
  138. }
  139. static int
  140. p_filter(Filter *f, Msg *m)
  141. {
  142. Hdr h;
  143. int len;
  144. len = parsehdr(&h, m->ps, m->pe);
  145. if(len < 0)
  146. return -1;
  147. m->ps += len;
  148. switch(f->subop){
  149. case Oproto:
  150. return h.proto == f->ulv;
  151. }
  152. return 0;
  153. }
  154. static int
  155. p_seprint(Msg *m)
  156. {
  157. Hdr h;
  158. int len;
  159. len = parsehdr(&h, m->ps, m->pe);
  160. if(len < 0)
  161. return -1;
  162. m->ps += len;
  163. demux(p_mux, h.proto, h.proto, m, &dump);
  164. m->p = seprint(m->p, m->e, "version=%d proto=%#x flags=%#.4ux", h.version, h.proto, h.flags);
  165. if(h.flags&GRE_chksum)
  166. m->p = seprint(m->p, m->e, " checksum=%#.4ux", h.chksum);
  167. if(h.flags&GRE_key)
  168. m->p = seprint(m->p, m->e, " key=%#.8ulx", h.key);
  169. if(h.flags&GRE_seq)
  170. m->p = seprint(m->p, m->e, " seq=%#.8ulx", h.seq);
  171. if(h.flags&GRE_ack)
  172. m->p = seprint(m->p, m->e, " ack=%#.8ulx", h.ack);
  173. if(h.flags&GRE_routing)
  174. m->p = seprint(m->p, m->e, " offset=%#x haverouting", h.offset);
  175. if(h.version == 0)
  176. m->p = seprint(m->p, m->e, " recursion=%u", (h.flags&GRE_recur)>>8);
  177. return 0;
  178. }
  179. Proto gre =
  180. {
  181. "gre",
  182. p_compile,
  183. p_filter,
  184. p_seprint,
  185. p_mux,
  186. "%#.4ux",
  187. p_fields,
  188. defaultframer,
  189. };