gre.c 3.2 KB

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