aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/ip/snoopy/icmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/ip/snoopy/icmp.c')
-rwxr-xr-xsrc/cmd/ip/snoopy/icmp.c196
1 files changed, 196 insertions, 0 deletions
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 <u.h>
+#include <libc.h>
+#include <ip.h>
+#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,
+};