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 { uchar type; 109a747e4fSDavid du Colombier uchar code; 119a747e4fSDavid du Colombier uchar cksum[2]; /* Checksum */ 129a747e4fSDavid du Colombier uchar data[1]; 139a747e4fSDavid du Colombier }; 149a747e4fSDavid du Colombier 159a747e4fSDavid du Colombier enum 169a747e4fSDavid du Colombier { 179a747e4fSDavid du Colombier ICMPLEN= 4, 189a747e4fSDavid du Colombier }; 199a747e4fSDavid du Colombier 209a747e4fSDavid du Colombier enum 219a747e4fSDavid du Colombier { 229a747e4fSDavid du Colombier Ot, /* type */ 239a747e4fSDavid du Colombier Op, /* next protocol */ 249a747e4fSDavid du Colombier }; 259a747e4fSDavid du Colombier 269a747e4fSDavid du Colombier static Field p_fields[] = 279a747e4fSDavid du Colombier { 289a747e4fSDavid du Colombier {"t", Fnum, Ot, "type", } , 299a747e4fSDavid du Colombier {0} 309a747e4fSDavid du Colombier }; 319a747e4fSDavid du Colombier 329a747e4fSDavid du Colombier enum 339a747e4fSDavid du Colombier { 349a747e4fSDavid du Colombier EchoRep= 0, 359a747e4fSDavid du Colombier Unreachable= 3, 369a747e4fSDavid du Colombier SrcQuench= 4, 379a747e4fSDavid du Colombier Redirect= 5, 389a747e4fSDavid du Colombier EchoReq= 8, 399a747e4fSDavid du Colombier TimeExceed= 11, 409a747e4fSDavid du Colombier ParamProb= 12, 419a747e4fSDavid du Colombier TSreq= 13, 429a747e4fSDavid du Colombier TSrep= 14, 439a747e4fSDavid du Colombier InfoReq= 15, 449a747e4fSDavid du Colombier InfoRep= 16, 459a747e4fSDavid du Colombier }; 469a747e4fSDavid du Colombier 479a747e4fSDavid du Colombier static Mux p_mux[] = 489a747e4fSDavid du Colombier { 499a747e4fSDavid du Colombier {"ip", Unreachable, }, 509a747e4fSDavid du Colombier {"ip", SrcQuench, }, 519a747e4fSDavid du Colombier {"ip", Redirect, }, 529a747e4fSDavid du Colombier {"ip", TimeExceed, }, 539a747e4fSDavid du Colombier {"ip", ParamProb, }, 549a747e4fSDavid du Colombier {0}, 559a747e4fSDavid du Colombier }; 569a747e4fSDavid du Colombier 579a747e4fSDavid du Colombier char *icmpmsg[236] = 589a747e4fSDavid du Colombier { 599a747e4fSDavid du Colombier [EchoRep] "EchoRep", 609a747e4fSDavid du Colombier [Unreachable] "Unreachable", 619a747e4fSDavid du Colombier [SrcQuench] "SrcQuench", 629a747e4fSDavid du Colombier [Redirect] "Redirect", 639a747e4fSDavid du Colombier [EchoReq] "EchoReq", 649a747e4fSDavid du Colombier [TimeExceed] "TimeExceed", 659a747e4fSDavid du Colombier [ParamProb] "ParamProb", 669a747e4fSDavid du Colombier [TSreq] "TSreq", 679a747e4fSDavid du Colombier [TSrep] "TSrep", 689a747e4fSDavid du Colombier [InfoReq] "InfoReq", 699a747e4fSDavid du Colombier [InfoRep] "InfoRep", 709a747e4fSDavid du Colombier }; 719a747e4fSDavid du Colombier 729a747e4fSDavid du Colombier static void 739a747e4fSDavid du Colombier p_compile(Filter *f) 749a747e4fSDavid du Colombier { 759a747e4fSDavid du Colombier if(f->op == '='){ 76*0b9a5132SDavid du Colombier compile_cmp(icmp.name, f, p_fields); 779a747e4fSDavid du Colombier return; 789a747e4fSDavid du Colombier } 799a747e4fSDavid du Colombier if(strcmp(f->s, "ip") == 0){ 809a747e4fSDavid du Colombier f->pr = p_mux->pr; 819a747e4fSDavid du Colombier f->subop = Op; 829a747e4fSDavid du Colombier return; 839a747e4fSDavid du Colombier } 849a747e4fSDavid du Colombier sysfatal("unknown icmp field or protocol: %s", f->s); 859a747e4fSDavid du Colombier } 869a747e4fSDavid du Colombier 879a747e4fSDavid du Colombier static int 889a747e4fSDavid du Colombier p_filter(Filter *f, Msg *m) 899a747e4fSDavid du Colombier { 909a747e4fSDavid du Colombier Hdr *h; 919a747e4fSDavid du Colombier 929a747e4fSDavid du Colombier if(m->pe - m->ps < ICMPLEN) 939a747e4fSDavid du Colombier return 0; 949a747e4fSDavid du Colombier 959a747e4fSDavid du Colombier h = (Hdr*)m->ps; 969a747e4fSDavid du Colombier m->ps += ICMPLEN; 979a747e4fSDavid du Colombier 989a747e4fSDavid du Colombier switch(f->subop){ 999a747e4fSDavid du Colombier case Ot: 1009a747e4fSDavid du Colombier if(h->type == f->ulv) 1019a747e4fSDavid du Colombier return 1; 1029a747e4fSDavid du Colombier break; 1039a747e4fSDavid du Colombier case Op: 1049a747e4fSDavid du Colombier switch(h->type){ 1059a747e4fSDavid du Colombier case Unreachable: 1069a747e4fSDavid du Colombier case TimeExceed: 1079a747e4fSDavid du Colombier case SrcQuench: 1089a747e4fSDavid du Colombier case Redirect: 1099a747e4fSDavid du Colombier case ParamProb: 1109a747e4fSDavid du Colombier m->ps += 4; 1119a747e4fSDavid du Colombier return 1; 1129a747e4fSDavid du Colombier } 1139a747e4fSDavid du Colombier } 1149a747e4fSDavid du Colombier return 0; 1159a747e4fSDavid du Colombier } 1169a747e4fSDavid du Colombier 1179a747e4fSDavid du Colombier static int 1189a747e4fSDavid du Colombier p_seprint(Msg *m) 1199a747e4fSDavid du Colombier { 1209a747e4fSDavid du Colombier Hdr *h; 1219a747e4fSDavid du Colombier char *tn; 1229a747e4fSDavid du Colombier char *p = m->p; 1239a747e4fSDavid du Colombier char *e = m->e; 1249a747e4fSDavid du Colombier ushort cksum2, cksum; 1259a747e4fSDavid du Colombier 1269a747e4fSDavid du Colombier h = (Hdr*)m->ps; 1279a747e4fSDavid du Colombier m->ps += ICMPLEN; 1289a747e4fSDavid du Colombier m->pr = &dump; 1299a747e4fSDavid du Colombier 1309a747e4fSDavid du Colombier if(m->pe - m->ps < ICMPLEN) 1319a747e4fSDavid du Colombier return -1; 1329a747e4fSDavid du Colombier 1339a747e4fSDavid du Colombier tn = icmpmsg[h->type]; 1349a747e4fSDavid du Colombier if(tn == nil) 1359a747e4fSDavid du Colombier p = seprint(p, e, "t=%ud c=%d ck=%4.4ux", h->type, 1369a747e4fSDavid du Colombier h->code, (ushort)NetS(h->cksum)); 1379a747e4fSDavid du Colombier else 1389a747e4fSDavid du Colombier p = seprint(p, e, "t=%s c=%d ck=%4.4ux", tn, 1399a747e4fSDavid du Colombier h->code, (ushort)NetS(h->cksum)); 1409a747e4fSDavid du Colombier if(Cflag){ 1419a747e4fSDavid du Colombier cksum = NetS(h->cksum); 1429a747e4fSDavid du Colombier h->cksum[0] = 0; 1439a747e4fSDavid du Colombier h->cksum[1] = 0; 1449a747e4fSDavid du Colombier cksum2 = ~ptclbsum((uchar*)h, m->pe - m->ps + ICMPLEN) & 0xffff; 1459a747e4fSDavid du Colombier if(cksum != cksum2) 1469a747e4fSDavid du Colombier p = seprint(p,e, " !ck=%4.4ux", cksum2); 1479a747e4fSDavid du Colombier } 1489a747e4fSDavid du Colombier switch(h->type){ 1499a747e4fSDavid du Colombier case EchoRep: 1509a747e4fSDavid du Colombier case EchoReq: 1519a747e4fSDavid du Colombier m->ps += 4; 1529a747e4fSDavid du Colombier p = seprint(p, e, " id=%ux seq=%ux", 1539a747e4fSDavid du Colombier NetS(h->data), NetS(h->data+2)); 1549a747e4fSDavid du Colombier break; 1559a747e4fSDavid du Colombier case TSreq: 1569a747e4fSDavid du Colombier case TSrep: 1579a747e4fSDavid du Colombier m->ps += 12; 1589a747e4fSDavid du Colombier p = seprint(p, e, " orig=%ud rcv=%ux xmt=%ux", 1599a747e4fSDavid du Colombier NetL(h->data), NetL(h->data+4), 1609a747e4fSDavid du Colombier NetL(h->data+8)); 1619a747e4fSDavid du Colombier m->pr = nil; 1629a747e4fSDavid du Colombier break; 1639a747e4fSDavid du Colombier case InfoReq: 1649a747e4fSDavid du Colombier case InfoRep: 1659a747e4fSDavid du Colombier break; 1669a747e4fSDavid du Colombier case Unreachable: 1679a747e4fSDavid du Colombier case TimeExceed: 1689a747e4fSDavid du Colombier case SrcQuench: 1699a747e4fSDavid du Colombier m->ps += 4; 1709a747e4fSDavid du Colombier m->pr = &ip; 1719a747e4fSDavid du Colombier break; 1729a747e4fSDavid du Colombier case Redirect: 1739a747e4fSDavid du Colombier m->ps += 4; 1749a747e4fSDavid du Colombier m->pr = &ip; 1759a747e4fSDavid du Colombier p = seprint(p, e, "gw=%V", h->data); 1769a747e4fSDavid du Colombier break; 1779a747e4fSDavid du Colombier case ParamProb: 1789a747e4fSDavid du Colombier m->ps += 4; 1799a747e4fSDavid du Colombier m->pr = &ip; 1809a747e4fSDavid du Colombier p = seprint(p, e, "ptr=%2.2ux", h->data[0]); 1819a747e4fSDavid du Colombier break; 1829a747e4fSDavid du Colombier } 1839a747e4fSDavid du Colombier m->p = p; 1849a747e4fSDavid du Colombier return 0; 1859a747e4fSDavid du Colombier } 1869a747e4fSDavid du Colombier 1879a747e4fSDavid du Colombier Proto icmp = 1889a747e4fSDavid du Colombier { 1899a747e4fSDavid du Colombier "icmp", 1909a747e4fSDavid du Colombier p_compile, 1919a747e4fSDavid du Colombier p_filter, 1929a747e4fSDavid du Colombier p_seprint, 1939a747e4fSDavid du Colombier p_mux, 194ed397113SDavid du Colombier "%lud", 1959a747e4fSDavid du Colombier p_fields, 1963ff48bf5SDavid du Colombier defaultframer, 1979a747e4fSDavid du Colombier }; 198