123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439 |
- #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
- {
- ICMP6LEN= 4,
- };
- enum
- {
- Ot, /* type */
- Op, /* next protocol */
- };
- static Field p_fields[] =
- {
- {"t", Fnum, Ot, "type", } ,
- {0}
- };
- enum
- {
- /* ICMPv6 types */
- EchoReply = 0,
- UnreachableV6 = 1,
- PacketTooBigV6 = 2,
- TimeExceedV6 = 3,
- ParamProblemV6 = 4,
- Redirect = 5,
- EchoRequest = 8,
- TimeExceed = 11,
- InParmProblem = 12,
- Timestamp = 13,
- TimestampReply = 14,
- InfoRequest = 15,
- InfoReply = 16,
- AddrMaskRequest = 17,
- AddrMaskReply = 18,
- EchoRequestV6 = 128,
- EchoReplyV6 = 129,
- RouterSolicit = 133,
- RouterAdvert = 134,
- NbrSolicit = 135,
- NbrAdvert = 136,
- RedirectV6 = 137,
- Maxtype6 = 137,
- };
- static Mux p_mux[] =
- {
- {"ip6", UnreachableV6, },
- {"ip6", RedirectV6, },
- {"ip6", TimeExceedV6, },
- {0},
- };
- char *icmpmsg6[256] =
- {
- [EchoReply] "EchoReply",
- [UnreachableV6] "UnreachableV6",
- [PacketTooBigV6] "PacketTooBigV6",
- [TimeExceedV6] "TimeExceedV6",
- [Redirect] "Redirect",
- [EchoRequest] "EchoRequest",
- [TimeExceed] "TimeExceed",
- [InParmProblem] "InParmProblem",
- [Timestamp] "Timestamp",
- [TimestampReply] "TimestampReply",
- [InfoRequest] "InfoRequest",
- [InfoReply] "InfoReply",
- [AddrMaskRequest] "AddrMaskRequest",
- [AddrMaskReply] "AddrMaskReply",
- [EchoRequestV6] "EchoRequestV6",
- [EchoReplyV6] "EchoReplyV6",
- [RouterSolicit] "RouterSolicit",
- [RouterAdvert] "RouterAdvert",
- [NbrSolicit] "NbrSolicit",
- [NbrAdvert] "NbrAdvert",
- [RedirectV6] "RedirectV6",
- };
- static char *unreachcode[] =
- {
- [0] "no route to destination",
- [1] "comm with destination administratively prohibited",
- [2] "icmp unreachable: unassigned error code (2)",
- [3] "address unreachable",
- [4] "port unreachable",
- [5] "icmp unreachable: unknown code",
- };
- static char *timexcode[] =
- {
- [0] "hop limit exc",
- [1] "reassmbl time exc",
- [2] "icmp time exc: unknown code",
- };
- static char *parpcode[] =
- {
- [0] "erroneous header field encountered",
- [1] "unrecognized Next Header type encountered",
- [2] "unrecognized IPv6 option encountered",
- [3] "icmp par prob: unknown code",
- };
- enum
- {
- sll = 1,
- tll = 2,
- pref = 3,
- redir = 4,
- mtu = 5,
- };
- static char *icmp6opts[256] =
- {
- [0] "unknown opt",
- [1] "sll_addr",
- [2] "tll_addr",
- [3] "pref_opt",
- [4] "redirect",
- [5] "mtu_opt",
- };
- static void
- p_compile(Filter *f)
- {
- if(f->op == '='){
- compile_cmp(icmp6.name, f, p_fields);
- return;
- }
- if(strcmp(f->s, "ip6") == 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 < ICMP6LEN)
- return 0;
- h = (Hdr*)m->ps;
- m->ps += ICMP6LEN;
- switch(f->subop){
- case Ot:
- if(h->type == f->ulv)
- return 1;
- break;
- case Op:
- switch(h->type){
- case UnreachableV6:
- case RedirectV6:
- case TimeExceedV6:
- m->ps += 4;
- return 1;
- }
- }
- return 0;
- }
- static char*
- opt_seprint(Msg *m)
- {
- int otype, osz, pktsz;
- uchar *a;
- char *p = m->p;
- char *e = m->e;
- char *opt;
- char optbuf[12];
- pktsz = m->pe - m->ps;
- a = m->ps;
- while (pktsz > 0) {
- otype = *a;
- opt = icmp6opts[otype];
- if(opt == nil){
- sprint(optbuf, "0x%ux", otype);
- opt = optbuf;
- }
- osz = (*(a+1)) * 8;
- switch (otype) {
- default:
- p = seprint(p, e, "\n option=%s ", opt);
- m->pr = &dump;
- return p;
- case sll:
- case tll:
- if (pktsz < osz || osz != 8) {
- p = seprint(p, e, "\n option=%s bad size=%d",
- opt, osz);
- m->pr = &dump;
- return p;
- }
- p = seprint(p, e, "\n option=%s maddr=%E", opt, a+2);
- pktsz -= osz;
- a += osz;
- break;
- case pref:
- if ((pktsz < osz) || (osz != 32)) {
- p = seprint(p, e, "\n option=%s: bad size=%d",
- opt, osz);
- m->pr = &dump;
- return p;
- }
- p = seprint(p, e, "\n option=%s pref=%I "
- "preflen=%3.3d lflag=%1.1d aflag=%1.1d "
- "unused1=%1.1d validlt=%d preflt=%d unused2=%1.1d",
- opt,
- a+16,
- (int) (*(a+2)),
- (*(a+3) & (1 << 7)) != 0,
- (*(a+3) & (1 << 6)) != 0,
- (*(a+3) & 63) != 0,
- NetL(a+4),
- NetL(a+8),
- NetL(a+12)!=0);
- pktsz -= osz;
- a += osz;
- break;
- case redir:
- if (pktsz < osz) {
- p = seprint(p, e, "\n option=%s: bad size=%d",
- opt, osz);
- m->pr = &dump;
- return p;
- }
- p = seprint(p, e, "\n option=%s len %d", opt, osz);
- a += osz;
- m->ps = a;
- return p;
- case mtu:
- if (pktsz < osz || osz != 8) {
- p = seprint(p, e, "\n option=%s: bad size=%d",
- opt, osz);
- m->pr = &dump;
- return p;
- }
- p = seprint(p, e, "\n option=%s unused=%1.1d mtu=%d",
- opt, NetL(a+2) != 0, NetL(a+4));
- pktsz -= osz;
- a += osz;
- break;
- }
- }
- m->ps = a;
- return p;
- }
- static int
- p_seprint(Msg *m)
- {
- int i;
- // ushort cksum2, cksum;
- char *tn;
- char *p = m->p;
- char *e = m->e;
- uchar *a;
- Hdr *h;
- h = (Hdr*)m->ps;
- m->ps += ICMP6LEN;
- m->pr = &dump;
- a = m->ps;
- if(m->pe - m->ps < ICMP6LEN)
- return -1;
- tn = icmpmsg6[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 + ICMP6LEN) & 0xffff;
- if(cksum != cksum2)
- p = seprint(p,e, " !ck=%4.4ux", cksum2);
- }
- */
- switch(h->type){
- case UnreachableV6:
- m->ps += 4;
- m->pr = &ip6;
- if (h->code >= nelem(unreachcode))
- i = nelem(unreachcode)-1;
- else
- i = h->code;
- p = seprint(p, e, " code=%s unused=%1.1d ", unreachcode[i],
- NetL(a) != 0);
- break;
- case PacketTooBigV6:
- m->ps += 4;
- m->pr = &ip6;
- p = seprint(p, e, " mtu=%4.4d ", NetL(a));
- break;
- case TimeExceedV6:
- m->ps += 4;
- m->pr = &ip6;
- if (h->code >= nelem(timexcode))
- i = nelem(timexcode)-1;
- else
- i = h->code;
- p = seprint(p, e, " code=%s unused=%1.1d ", timexcode[i],
- NetL(a) != 0);
- break;
- case ParamProblemV6:
- m->ps += 4;
- m->pr = &ip6;
- if (h->code > nelem(parpcode))
- i = nelem(parpcode)-1;
- else
- i = h->code;
- p = seprint(p, e, " code=%s ptr=%2.2ux", parpcode[i], h->data[0]);
- break;
- case EchoReplyV6:
- case EchoRequestV6:
- m->ps += 4;
- p = seprint(p, e, " id=%ux seq=%ux",
- NetS(h->data), NetS(h->data+2));
- break;
- case RouterSolicit:
- m->ps += 4;
- m->pr = nil;
- m->p = seprint(p, e, " unused=%1.1d ", NetL(a)!=0);
- p = opt_seprint(m);
- break;
- case RouterAdvert:
- m->ps += 12;
- m->pr = nil;
- m->p = seprint(p, e, " hoplim=%3.3d mflag=%1.1d oflag=%1.1d "
- "unused=%1.1d routerlt=%8.8d reachtime=%d rxmtimer=%d",
- (int) *a,
- (*(a+1) & (1 << 7)) != 0,
- (*(a+1) & (1 << 6)) != 0,
- (*(a+1) & 63) != 0,
- NetS(a+2),
- NetL(a+4),
- NetL(a+8));
- p = opt_seprint(m);
- break;
- case NbrSolicit:
- m->ps += 20;
- m->pr = nil;
- m->p = seprint(p, e, " unused=%1.1d targ %I", NetL(a) != 0, a+4);
- p = opt_seprint(m);
- break;
- case NbrAdvert:
- m->ps += 20;
- m->pr = nil;
- m->p = seprint(p, e, " rflag=%1.1d sflag=%1.1d oflag=%1.1d targ=%I",
- (*a & (1 << 7)) != 0,
- (*a & (1 << 6)) != 0,
- (*a & (1 << 5)) != 0,
- a+4);
- p = opt_seprint(m);
- break;
- case RedirectV6:
- m->ps += 36;
- m->pr = &ip6;
- m->p = seprint(p, e, " unused=%1.1d targ=%I dest=%I",
- NetL(a) != 0, a+4, a+20);
- p = opt_seprint(m);
- break;
- case Timestamp:
- case TimestampReply:
- 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 InfoRequest:
- case InfoReply:
- break;
- }
- m->p = p;
- return 0;
- }
- Proto icmp6 =
- {
- "icmp6",
- p_compile,
- p_filter,
- p_seprint,
- p_mux,
- "%lud",
- p_fields,
- defaultframer,
- };
|