123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- #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(icmp.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,
- "%lud",
- p_fields,
- defaultframer,
- };
|