tcp.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <ip.h>
  4. #include "dat.h"
  5. #include "protos.h"
  6. typedef struct Hdr Hdr;
  7. struct Hdr
  8. {
  9. uchar sport[2];
  10. uchar dport[2];
  11. uchar seq[4];
  12. uchar ack[4];
  13. uchar flag[2];
  14. uchar win[2];
  15. uchar cksum[2];
  16. uchar urg[2];
  17. uchar opt[1];
  18. };
  19. typedef struct PseudoHdr{
  20. uchar src[4];
  21. uchar dst[4];
  22. uchar zero;
  23. uchar proto;
  24. uchar length[2];
  25. uchar hdrdata[1580];
  26. } PseudoHdr;
  27. enum
  28. {
  29. TCPLEN= 20,
  30. };
  31. enum
  32. {
  33. Os,
  34. Od,
  35. Osd,
  36. };
  37. static Field p_fields[] =
  38. {
  39. {"s", Fnum, Os, "source port", } ,
  40. {"d", Fnum, Od, "dest port", } ,
  41. {"a", Fnum, Osd, "source/dest port", } ,
  42. {"sd", Fnum, Osd, "source/dest port", } ,
  43. {0}
  44. };
  45. static Mux p_mux[] =
  46. {
  47. {"ninep", 17007, }, /* exportfs */
  48. {"ninep", 564, }, /* 9fs */
  49. {"ninep", 17005, }, /* ocpu */
  50. {"ninep", 17010, }, /* ncpu */
  51. {"ninep", 17013, }, /* cpu */
  52. {0},
  53. };
  54. enum
  55. {
  56. EOLOPT = 0,
  57. NOOPOPT = 1,
  58. MSSOPT = 2,
  59. MSS_LENGTH = 4, /* Mean segment size */
  60. WSOPT = 3,
  61. WS_LENGTH = 3, /* Bits to scale window size by */
  62. };
  63. static void
  64. p_compile(Filter *f)
  65. {
  66. Mux *m;
  67. if(f->op == '='){
  68. compile_cmp(tcp.name, f, p_fields);
  69. return;
  70. }
  71. for(m = p_mux; m->name != nil; m++)
  72. if(strcmp(f->s, m->name) == 0){
  73. f->pr = m->pr;
  74. f->ulv = m->val;
  75. f->subop = Osd;
  76. return;
  77. }
  78. sysfatal("unknown tcp field or protocol: %s", f->s);
  79. }
  80. static int
  81. p_filter(Filter *f, Msg *m)
  82. {
  83. Hdr *h;
  84. if(m->pe - m->ps < TCPLEN)
  85. return 0;
  86. h = (Hdr*)m->ps;
  87. m->ps += ((NetS(h->flag)>>10)&0x3f);
  88. switch(f->subop){
  89. case Os:
  90. return NetS(h->sport) == f->ulv;
  91. case Od:
  92. return NetS(h->dport) == f->ulv;
  93. case Osd:
  94. return NetS(h->sport) == f->ulv || NetS(h->dport) == f->ulv;
  95. }
  96. return 0;
  97. }
  98. enum
  99. {
  100. URG = 0x20, /* Data marked urgent */
  101. ACK = 0x10, /* Aknowledge is valid */
  102. PSH = 0x08, /* Whole data pipe is pushed */
  103. RST = 0x04, /* Reset connection */
  104. SYN = 0x02, /* Pkt. is synchronise */
  105. FIN = 0x01, /* Start close down */
  106. };
  107. static char*
  108. flags(int f)
  109. {
  110. static char fl[20];
  111. char *p;
  112. p = fl;
  113. if(f & URG)
  114. *p++ = 'U';
  115. if(f & ACK)
  116. *p++ = 'A';
  117. if(f & PSH)
  118. *p++ = 'P';
  119. if(f & RST)
  120. *p++ = 'R';
  121. if(f & SYN)
  122. *p++ = 'S';
  123. if(f & FIN)
  124. *p++ = 'F';
  125. *p = 0;
  126. return fl;
  127. }
  128. static int
  129. p_seprint(Msg *m)
  130. {
  131. Hdr *h;
  132. int dport, sport;
  133. int len, flag, optlen;
  134. uchar *optr;
  135. if(m->pe - m->ps < TCPLEN)
  136. return -1;
  137. h = (Hdr*)m->ps;
  138. /* get tcp header length */
  139. flag = NetS(h->flag);
  140. len = (flag>>10)&~3;
  141. flag &= 0x3ff;
  142. m->ps += len;
  143. /* next protocol */
  144. dport = NetS(h->dport);
  145. sport = NetS(h->sport);
  146. demux(p_mux, sport, dport, m, &dump);
  147. m->p = seprint(m->p, m->e, "s=%d d=%d seq=%lud ack=%lud fl=%s win=%d ck=%4.4ux",
  148. NetS(h->sport), dport,
  149. (ulong)NetL(h->seq), (ulong)NetL(h->ack),
  150. flags(flag), NetS(h->win),
  151. NetS(h->cksum));
  152. /* tcp options */
  153. len -= TCPLEN;
  154. optr = h->opt;
  155. while(len > 0) {
  156. if(*optr == EOLOPT){
  157. m->p = seprint(m->p, m->e, " opt=EOL");
  158. break;
  159. }
  160. if(*optr == NOOPOPT) {
  161. m->p = seprint(m->p, m->e, " opt=NOOP");
  162. len--;
  163. optr++;
  164. continue;
  165. }
  166. optlen = optr[1];
  167. if(optlen < 2 || optlen > len)
  168. break;
  169. switch(*optr) {
  170. case MSSOPT:
  171. m->p = seprint(m->p, m->e, " opt%d=(mss %ud)", optlen, nhgets(optr+2));
  172. break;
  173. case WSOPT:
  174. m->p = seprint(m->p, m->e, " opt%d=(wscale %ud)", optlen, *(optr+2));
  175. break;
  176. default:
  177. m->p = seprint(m->p, m->e, " opt%d=(%ud %.*H)", optlen, *optr, optlen-2,optr+2);
  178. }
  179. len -= optlen;
  180. optr += optlen;
  181. }
  182. if(Cflag){
  183. // editing in progress by ehg
  184. }
  185. return 0;
  186. }
  187. Proto tcp =
  188. {
  189. "tcp",
  190. p_compile,
  191. p_filter,
  192. p_seprint,
  193. p_mux,
  194. "%lud",
  195. p_fields,
  196. defaultframer,
  197. };