From 87a52e0485d3281ebea6bf4b725aa8023690e96f Mon Sep 17 00:00:00 2001 From: rsc Date: Mon, 26 Dec 2005 04:48:52 +0000 Subject: new goodies --- src/cmd/ip/snoopy/icmp.c | 196 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100755 src/cmd/ip/snoopy/icmp.c (limited to 'src/cmd/ip/snoopy/icmp.c') diff --git a/src/cmd/ip/snoopy/icmp.c b/src/cmd/ip/snoopy/icmp.c new file mode 100755 index 00000000..cf286d87 --- /dev/null +++ b/src/cmd/ip/snoopy/icmp.c @@ -0,0 +1,196 @@ +#include +#include +#include +#include "dat.h" +#include "protos.h" + +typedef struct Hdr Hdr; +struct Hdr +{ uchar type; + uchar code; + uchar cksum[2]; /* Checksum */ + uchar data[1]; +}; + +enum +{ + ICMPLEN= 4, +}; + +enum +{ + Ot, /* type */ + Op, /* next protocol */ +}; + +static Field p_fields[] = +{ + {"t", Fnum, Ot, "type", } , + {0} +}; + +enum +{ + EchoRep= 0, + Unreachable= 3, + SrcQuench= 4, + Redirect= 5, + EchoReq= 8, + TimeExceed= 11, + ParamProb= 12, + TSreq= 13, + TSrep= 14, + InfoReq= 15, + InfoRep= 16, +}; + +static Mux p_mux[] = +{ + {"ip", Unreachable, }, + {"ip", SrcQuench, }, + {"ip", Redirect, }, + {"ip", TimeExceed, }, + {"ip", ParamProb, }, + {0}, +}; + +char *icmpmsg[236] = +{ +[EchoRep] "EchoRep", +[Unreachable] "Unreachable", +[SrcQuench] "SrcQuench", +[Redirect] "Redirect", +[EchoReq] "EchoReq", +[TimeExceed] "TimeExceed", +[ParamProb] "ParamProb", +[TSreq] "TSreq", +[TSrep] "TSrep", +[InfoReq] "InfoReq", +[InfoRep] "InfoRep", +}; + +static void +p_compile(Filter *f) +{ + if(f->op == '='){ + compile_cmp(udp.name, f, p_fields); + return; + } + if(strcmp(f->s, "ip") == 0){ + f->pr = p_mux->pr; + f->subop = Op; + return; + } + sysfatal("unknown icmp field or protocol: %s", f->s); +} + +static int +p_filter(Filter *f, Msg *m) +{ + Hdr *h; + + if(m->pe - m->ps < ICMPLEN) + return 0; + + h = (Hdr*)m->ps; + m->ps += ICMPLEN; + + switch(f->subop){ + case Ot: + if(h->type == f->ulv) + return 1; + break; + case Op: + switch(h->type){ + case Unreachable: + case TimeExceed: + case SrcQuench: + case Redirect: + case ParamProb: + m->ps += 4; + return 1; + } + } + return 0; +} + +static int +p_seprint(Msg *m) +{ + Hdr *h; + char *tn; + char *p = m->p; + char *e = m->e; + ushort cksum2, cksum; + + h = (Hdr*)m->ps; + m->ps += ICMPLEN; + m->pr = &dump; + + if(m->pe - m->ps < ICMPLEN) + return -1; + + tn = icmpmsg[h->type]; + if(tn == nil) + p = seprint(p, e, "t=%ud c=%d ck=%4.4ux", h->type, + h->code, (ushort)NetS(h->cksum)); + else + p = seprint(p, e, "t=%s c=%d ck=%4.4ux", tn, + h->code, (ushort)NetS(h->cksum)); + if(Cflag){ + cksum = NetS(h->cksum); + h->cksum[0] = 0; + h->cksum[1] = 0; + cksum2 = ~ptclbsum((uchar*)h, m->pe - m->ps + ICMPLEN) & 0xffff; + if(cksum != cksum2) + p = seprint(p,e, " !ck=%4.4ux", cksum2); + } + switch(h->type){ + case EchoRep: + case EchoReq: + m->ps += 4; + p = seprint(p, e, " id=%ux seq=%ux", + NetS(h->data), NetS(h->data+2)); + break; + case TSreq: + case TSrep: + m->ps += 12; + p = seprint(p, e, " orig=%ud rcv=%ux xmt=%ux", + NetL(h->data), NetL(h->data+4), + NetL(h->data+8)); + m->pr = nil; + break; + case InfoReq: + case InfoRep: + break; + case Unreachable: + case TimeExceed: + case SrcQuench: + m->ps += 4; + m->pr = &ip; + break; + case Redirect: + m->ps += 4; + m->pr = &ip; + p = seprint(p, e, "gw=%V", h->data); + break; + case ParamProb: + m->ps += 4; + m->pr = &ip; + p = seprint(p, e, "ptr=%2.2ux", h->data[0]); + break; + } + m->p = p; + return 0; +} + +Proto icmp = +{ + "icmp", + p_compile, + p_filter, + p_seprint, + p_mux, + p_fields, + defaultframer, +}; -- cgit v1.2.3