2005-12-26 04:48:52 +00:00
|
|
|
#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,
|
2006-02-14 19:42:28 +00:00
|
|
|
"%lud",
|
2005-12-26 04:48:52 +00:00
|
|
|
p_fields,
|
|
|
|
|
defaultframer,
|
|
|
|
|
};
|