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