19a747e4fSDavid du Colombier #include <u.h> 29a747e4fSDavid du Colombier #include <libc.h> 39a747e4fSDavid du Colombier #include <ip.h> 49a747e4fSDavid du Colombier #include "dat.h" 59a747e4fSDavid du Colombier #include "protos.h" 69a747e4fSDavid du Colombier 79a747e4fSDavid du Colombier typedef struct Hdr Hdr; 89a747e4fSDavid du Colombier struct Hdr 99a747e4fSDavid du Colombier { 109a747e4fSDavid du Colombier uchar sport[2]; 119a747e4fSDavid du Colombier uchar dport[2]; 129a747e4fSDavid du Colombier uchar seq[4]; 139a747e4fSDavid du Colombier uchar ack[4]; 149a747e4fSDavid du Colombier uchar flag[2]; 159a747e4fSDavid du Colombier uchar win[2]; 169a747e4fSDavid du Colombier uchar cksum[2]; 179a747e4fSDavid du Colombier uchar urg[2]; 18*6b6b9ac8SDavid du Colombier uchar opt[1]; 199a747e4fSDavid du Colombier }; 209a747e4fSDavid du Colombier 219a747e4fSDavid du Colombier typedef struct PseudoHdr{ 229a747e4fSDavid du Colombier uchar src[4]; 239a747e4fSDavid du Colombier uchar dst[4]; 249a747e4fSDavid du Colombier uchar zero; 259a747e4fSDavid du Colombier uchar proto; 269a747e4fSDavid du Colombier uchar length[2]; 279a747e4fSDavid du Colombier uchar hdrdata[1580]; 289a747e4fSDavid du Colombier } PseudoHdr; 299a747e4fSDavid du Colombier 309a747e4fSDavid du Colombier enum 319a747e4fSDavid du Colombier { 329a747e4fSDavid du Colombier TCPLEN= 20, 339a747e4fSDavid du Colombier }; 349a747e4fSDavid du Colombier 359a747e4fSDavid du Colombier enum 369a747e4fSDavid du Colombier { 379a747e4fSDavid du Colombier Os, 389a747e4fSDavid du Colombier Od, 399a747e4fSDavid du Colombier Osd, 409a747e4fSDavid du Colombier }; 419a747e4fSDavid du Colombier 429a747e4fSDavid du Colombier static Field p_fields[] = 439a747e4fSDavid du Colombier { 449a747e4fSDavid du Colombier {"s", Fnum, Os, "source port", } , 459a747e4fSDavid du Colombier {"d", Fnum, Od, "dest port", } , 469a747e4fSDavid du Colombier {"sd", Fnum, Osd, "source/dest port", } , 479a747e4fSDavid du Colombier {0} 489a747e4fSDavid du Colombier }; 499a747e4fSDavid du Colombier 509a747e4fSDavid du Colombier static Mux p_mux[] = 519a747e4fSDavid du Colombier { 529a747e4fSDavid du Colombier {"ninep", 17007, }, /* exportfs */ 539a747e4fSDavid du Colombier {"ninep", 564, }, /* 9fs */ 549a747e4fSDavid du Colombier {"ninep", 17005, }, /* ocpu */ 559a747e4fSDavid du Colombier {"ninep", 17010, }, /* ncpu */ 569a747e4fSDavid du Colombier {"ninep", 17013, }, /* cpu */ 579a747e4fSDavid du Colombier {0}, 589a747e4fSDavid du Colombier }; 599a747e4fSDavid du Colombier 60*6b6b9ac8SDavid du Colombier enum 61*6b6b9ac8SDavid du Colombier { 62*6b6b9ac8SDavid du Colombier EOLOPT = 0, 63*6b6b9ac8SDavid du Colombier NOOPOPT = 1, 64*6b6b9ac8SDavid du Colombier MSSOPT = 2, 65*6b6b9ac8SDavid du Colombier MSS_LENGTH = 4, /* Mean segment size */ 66*6b6b9ac8SDavid du Colombier WSOPT = 3, 67*6b6b9ac8SDavid du Colombier WS_LENGTH = 3, /* Bits to scale window size by */ 68*6b6b9ac8SDavid du Colombier }; 69*6b6b9ac8SDavid du Colombier 709a747e4fSDavid du Colombier static void 719a747e4fSDavid du Colombier p_compile(Filter *f) 729a747e4fSDavid du Colombier { 739a747e4fSDavid du Colombier Mux *m; 749a747e4fSDavid du Colombier 759a747e4fSDavid du Colombier if(f->op == '='){ 769a747e4fSDavid du Colombier compile_cmp(udp.name, f, p_fields); 779a747e4fSDavid du Colombier return; 789a747e4fSDavid du Colombier } 799a747e4fSDavid du Colombier for(m = p_mux; m->name != nil; m++) 809a747e4fSDavid du Colombier if(strcmp(f->s, m->name) == 0){ 819a747e4fSDavid du Colombier f->pr = m->pr; 829a747e4fSDavid du Colombier f->ulv = m->val; 833ff48bf5SDavid du Colombier f->subop = Osd; 849a747e4fSDavid du Colombier return; 859a747e4fSDavid du Colombier } 869a747e4fSDavid du Colombier sysfatal("unknown tcp field or protocol: %s", f->s); 879a747e4fSDavid du Colombier } 889a747e4fSDavid du Colombier 899a747e4fSDavid du Colombier static int 909a747e4fSDavid du Colombier p_filter(Filter *f, Msg *m) 919a747e4fSDavid du Colombier { 929a747e4fSDavid du Colombier Hdr *h; 939a747e4fSDavid du Colombier 949a747e4fSDavid du Colombier if(m->pe - m->ps < TCPLEN) 959a747e4fSDavid du Colombier return 0; 969a747e4fSDavid du Colombier 979a747e4fSDavid du Colombier h = (Hdr*)m->ps; 989a747e4fSDavid du Colombier m->ps += ((NetS(h->flag)>>10)&0x3f); 999a747e4fSDavid du Colombier 1009a747e4fSDavid du Colombier switch(f->subop){ 1019a747e4fSDavid du Colombier case Os: 1029a747e4fSDavid du Colombier return NetS(h->sport) == f->ulv; 1039a747e4fSDavid du Colombier case Od: 1049a747e4fSDavid du Colombier return NetS(h->dport) == f->ulv; 1059a747e4fSDavid du Colombier case Osd: 1069a747e4fSDavid du Colombier return NetS(h->sport) == f->ulv || NetS(h->dport) == f->ulv; 1079a747e4fSDavid du Colombier } 1089a747e4fSDavid du Colombier return 0; 1099a747e4fSDavid du Colombier } 1109a747e4fSDavid du Colombier 1119a747e4fSDavid du Colombier enum 1129a747e4fSDavid du Colombier { 1139a747e4fSDavid du Colombier URG = 0x20, /* Data marked urgent */ 1149a747e4fSDavid du Colombier ACK = 0x10, /* Aknowledge is valid */ 1159a747e4fSDavid du Colombier PSH = 0x08, /* Whole data pipe is pushed */ 1169a747e4fSDavid du Colombier RST = 0x04, /* Reset connection */ 1179a747e4fSDavid du Colombier SYN = 0x02, /* Pkt. is synchronise */ 1189a747e4fSDavid du Colombier FIN = 0x01, /* Start close down */ 1199a747e4fSDavid du Colombier }; 1209a747e4fSDavid du Colombier 1219a747e4fSDavid du Colombier static char* 1229a747e4fSDavid du Colombier flags(int f) 1239a747e4fSDavid du Colombier { 1249a747e4fSDavid du Colombier static char fl[20]; 1259a747e4fSDavid du Colombier char *p; 1269a747e4fSDavid du Colombier 1279a747e4fSDavid du Colombier p = fl; 1289a747e4fSDavid du Colombier if(f & URG) 1299a747e4fSDavid du Colombier *p++ = 'U'; 1309a747e4fSDavid du Colombier if(f & ACK) 1319a747e4fSDavid du Colombier *p++ = 'A'; 1329a747e4fSDavid du Colombier if(f & PSH) 1339a747e4fSDavid du Colombier *p++ = 'P'; 1349a747e4fSDavid du Colombier if(f & RST) 1359a747e4fSDavid du Colombier *p++ = 'R'; 1369a747e4fSDavid du Colombier if(f & SYN) 1379a747e4fSDavid du Colombier *p++ = 'S'; 1389a747e4fSDavid du Colombier if(f & FIN) 1399a747e4fSDavid du Colombier *p++ = 'F'; 1409a747e4fSDavid du Colombier *p = 0; 1419a747e4fSDavid du Colombier return fl; 1429a747e4fSDavid du Colombier } 1439a747e4fSDavid du Colombier 1449a747e4fSDavid du Colombier 1459a747e4fSDavid du Colombier static int 1469a747e4fSDavid du Colombier p_seprint(Msg *m) 1479a747e4fSDavid du Colombier { 1489a747e4fSDavid du Colombier Hdr *h; 1499a747e4fSDavid du Colombier int dport, sport; 150*6b6b9ac8SDavid du Colombier int len, flag, optlen; 151*6b6b9ac8SDavid du Colombier uchar *optr; 1529a747e4fSDavid du Colombier 1539a747e4fSDavid du Colombier if(m->pe - m->ps < TCPLEN) 1549a747e4fSDavid du Colombier return -1; 1559a747e4fSDavid du Colombier h = (Hdr*)m->ps; 1569a747e4fSDavid du Colombier 1579a747e4fSDavid du Colombier /* get tcp header length */ 1589a747e4fSDavid du Colombier flag = NetS(h->flag); 159*6b6b9ac8SDavid du Colombier len = (flag>>10)&~3; 1609a747e4fSDavid du Colombier flag &= 0x3ff; 1619a747e4fSDavid du Colombier m->ps += len; 1629a747e4fSDavid du Colombier 1639a747e4fSDavid du Colombier /* next protocol */ 1649a747e4fSDavid du Colombier dport = NetS(h->dport); 1659a747e4fSDavid du Colombier sport = NetS(h->sport); 1669a747e4fSDavid du Colombier demux(p_mux, sport, dport, m, &dump); 1679a747e4fSDavid du Colombier 1689a747e4fSDavid du Colombier m->p = seprint(m->p, m->e, "s=%d d=%d seq=%lud ack=%lud fl=%s win=%d ck=%4.4ux", 1699a747e4fSDavid du Colombier NetS(h->sport), dport, 1709a747e4fSDavid du Colombier (ulong)NetL(h->seq), (ulong)NetL(h->ack), 1719a747e4fSDavid du Colombier flags(flag), NetS(h->win), 1729a747e4fSDavid du Colombier NetS(h->cksum)); 1739a747e4fSDavid du Colombier 174*6b6b9ac8SDavid du Colombier /* tcp options */ 175*6b6b9ac8SDavid du Colombier len -= TCPLEN; 176*6b6b9ac8SDavid du Colombier optr = h->opt; 177*6b6b9ac8SDavid du Colombier while(len > 0) { 178*6b6b9ac8SDavid du Colombier if(*optr == EOLOPT){ 179*6b6b9ac8SDavid du Colombier m->p = seprint(m->p, m->e, " opt=EOL"); 180*6b6b9ac8SDavid du Colombier break; 181*6b6b9ac8SDavid du Colombier } 182*6b6b9ac8SDavid du Colombier if(*optr == NOOPOPT) { 183*6b6b9ac8SDavid du Colombier m->p = seprint(m->p, m->e, " opt=NOOP"); 184*6b6b9ac8SDavid du Colombier len--; 185*6b6b9ac8SDavid du Colombier optr++; 186*6b6b9ac8SDavid du Colombier continue; 187*6b6b9ac8SDavid du Colombier } 188*6b6b9ac8SDavid du Colombier optlen = optr[1]; 189*6b6b9ac8SDavid du Colombier if(optlen < 2 || optlen > len) 190*6b6b9ac8SDavid du Colombier break; 191*6b6b9ac8SDavid du Colombier switch(*optr) { 192*6b6b9ac8SDavid du Colombier case MSSOPT: 193*6b6b9ac8SDavid du Colombier m->p = seprint(m->p, m->e, " opt%d=(mss %ud)", optlen, nhgets(optr+2)); 194*6b6b9ac8SDavid du Colombier break; 195*6b6b9ac8SDavid du Colombier case WSOPT: 196*6b6b9ac8SDavid du Colombier m->p = seprint(m->p, m->e, " opt%d=(wscale %ud)", optlen, *(optr+2)); 197*6b6b9ac8SDavid du Colombier break; 198*6b6b9ac8SDavid du Colombier default: 199*6b6b9ac8SDavid du Colombier m->p = seprint(m->p, m->e, " opt%d=(%ud %.*H)", optlen, *optr, optlen-2,optr+2); 200*6b6b9ac8SDavid du Colombier } 201*6b6b9ac8SDavid du Colombier len -= optlen; 202*6b6b9ac8SDavid du Colombier optr += optlen; 203*6b6b9ac8SDavid du Colombier } 204*6b6b9ac8SDavid du Colombier 2059a747e4fSDavid du Colombier if(Cflag){ 2069a747e4fSDavid du Colombier // editing in progress by ehg 2079a747e4fSDavid du Colombier } 2089a747e4fSDavid du Colombier return 0; 2099a747e4fSDavid du Colombier } 2109a747e4fSDavid du Colombier 2119a747e4fSDavid du Colombier Proto tcp = 2129a747e4fSDavid du Colombier { 2139a747e4fSDavid du Colombier "tcp", 2149a747e4fSDavid du Colombier p_compile, 2159a747e4fSDavid du Colombier p_filter, 2169a747e4fSDavid du Colombier p_seprint, 2179a747e4fSDavid du Colombier p_mux, 2189a747e4fSDavid du Colombier p_fields, 2193ff48bf5SDavid du Colombier defaultframer, 2209a747e4fSDavid du Colombier }; 221