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
57*e4556204SDavid du Colombier char *icmpmsg[256] =
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
p_compile(Filter * f)739a747e4fSDavid du Colombier p_compile(Filter *f)
749a747e4fSDavid du Colombier {
759a747e4fSDavid du Colombier if(f->op == '='){
760b9a5132SDavid 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
p_filter(Filter * f,Msg * m)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
p_seprint(Msg * m)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