URI:
       ticmp6.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       ticmp6.c (7718B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <ip.h>
            4 #include "dat.h"
            5 #include "protos.h"
            6 
            7 typedef struct Hdr        Hdr;
            8 struct Hdr
            9 {        uchar        type;
           10         uchar        code;
           11         uchar        cksum[2];        /* Checksum */
           12         uchar        data[1];
           13 };
           14 
           15 enum
           16 {
           17         ICMP6LEN=        4
           18 };
           19 
           20 enum
           21 {
           22         Ot,        /* type */
           23         Op,        /* next protocol */};
           24 
           25 static Field p_fields[] =
           26 {
           27         {"t",                Fnum,        Ot,        "type",        } ,
           28         {0}
           29 };
           30 
           31 enum
           32 {
           33         /* ICMPv6 types */
           34         EchoReply        = 0,
           35         UnreachableV6        = 1,
           36         PacketTooBigV6        = 2,
           37         TimeExceedV6        = 3,
           38         ParamProblemV6        = 4,
           39         Redirect        = 5,
           40         EchoRequest        = 8,
           41         TimeExceed        = 11,
           42         InParmProblem        = 12,
           43         Timestamp        = 13,
           44         TimestampReply        = 14,
           45         InfoRequest        = 15,
           46         InfoReply        = 16,
           47         AddrMaskRequest = 17,
           48         AddrMaskReply   = 18,
           49         EchoRequestV6        = 128,
           50         EchoReplyV6        = 129,
           51         RouterSolicit        = 133,
           52         RouterAdvert        = 134,
           53         NbrSolicit        = 135,
           54         NbrAdvert        = 136,
           55         RedirectV6        = 137,
           56 
           57         Maxtype6        = 137
           58 };
           59 
           60 static Mux p_mux[] =
           61 {
           62         {"ip6",        UnreachableV6, },
           63         {"ip6",        RedirectV6, },
           64         {"ip6",        TimeExceedV6, },
           65         {0}
           66 };
           67 
           68 char *icmpmsg6[256] =
           69 {
           70 [EchoReply]                "EchoReply",
           71 [UnreachableV6]                "UnreachableV6",
           72 [PacketTooBigV6]        "PacketTooBigV6",
           73 [TimeExceedV6]                "TimeExceedV6",
           74 [Redirect]                "Redirect",
           75 [EchoRequest]                "EchoRequest",
           76 [TimeExceed]                "TimeExceed",
           77 [InParmProblem]                "InParmProblem",
           78 [Timestamp]                "Timestamp",
           79 [TimestampReply]        "TimestampReply",
           80 [InfoRequest]                "InfoRequest",
           81 [InfoReply]                "InfoReply",
           82 [AddrMaskRequest]        "AddrMaskRequest",
           83 [AddrMaskReply]                "AddrMaskReply",
           84 [EchoRequestV6]                "EchoRequestV6",
           85 [EchoReplyV6]                "EchoReplyV6",
           86 [RouterSolicit]                "RouterSolicit",
           87 [RouterAdvert]                "RouterAdvert",
           88 [NbrSolicit]                "NbrSolicit",
           89 [NbrAdvert]                "NbrAdvert",
           90 [RedirectV6]                "RedirectV6"
           91 };
           92 
           93 static char *unreachcode[] =
           94 {
           95 [0]        "no route to destination",
           96 [1]        "comm with destination administratively prohibited",
           97 [2]        "icmp unreachable: unassigned error code (2)",
           98 [3]        "address unreachable",
           99 [4]        "port unreachable",
          100 [5]        "icmp unreachable: unknown code"
          101 };
          102 
          103 static char *timexcode[] =
          104 {
          105 [0]        "hop limit exc",
          106 [1]        "reassmbl time exc",
          107 [2]        "icmp time exc: unknown code"
          108 };
          109 
          110 static char *parpcode[] =
          111 {
          112 [0]        "erroneous header field encountered",
          113 [1]        "unrecognized Next Header type encountered",
          114 [2]        "unrecognized IPv6 option encountered",
          115 [3]        "icmp par prob: unknown code"
          116 };
          117 enum
          118 {
          119         sll        = 1,
          120         tll        = 2,
          121         pref        = 3,
          122         redir        = 4,
          123         mtu        = 5
          124 };
          125 
          126 static char *icmp6opts[256] =
          127 {
          128 [0]        "unknown opt",
          129 [1]        "sll_addr",
          130 [2]        "tll_addr",
          131 [3]        "pref_opt",
          132 [4]        "redirect",
          133 [5]        "mtu_opt"
          134 };
          135 
          136 static void
          137 p_compile(Filter *f)
          138 {
          139         if(f->op == '='){
          140                 compile_cmp(icmp6.name, f, p_fields);
          141                 return;
          142         }
          143         if(strcmp(f->s, "ip6") == 0){
          144                 f->pr = p_mux->pr;
          145                 f->subop = Op;
          146                 return;
          147         }
          148         sysfatal("unknown icmp field or protocol: %s", f->s);
          149 }
          150 
          151 static int
          152 p_filter(Filter *f, Msg *m)
          153 {
          154         Hdr *h;
          155 
          156         if(m->pe - m->ps < ICMP6LEN)
          157                 return 0;
          158 
          159         h = (Hdr*)m->ps;
          160         m->ps += ICMP6LEN;
          161 
          162         switch(f->subop){
          163 
          164         case Ot:
          165                 if(h->type == f->ulv)
          166                         return 1;
          167                 break;
          168         case Op:
          169                 switch(h->type){
          170                 case UnreachableV6:
          171                 case RedirectV6:
          172                 case TimeExceedV6:
          173                         m->ps += 4;
          174                         return 1;
          175                 }
          176         }
          177         return 0;
          178 }
          179 
          180 static char*
          181 opt_seprint(Msg *m)
          182 {
          183         int otype, osz, pktsz;
          184         uchar *a;
          185         char *p = m->p;
          186         char *e = m->e;
          187         char *opt;
          188         char optbuf[12];
          189 
          190         pktsz = m->pe - m->ps;
          191         a = m->ps;
          192         while (pktsz > 0) {
          193                 otype = *a;
          194                 opt = icmp6opts[otype];
          195                 if(opt == nil){
          196                         sprint(optbuf, "0x%ux", otype);
          197                         opt = optbuf;
          198                 }
          199                 osz = (*(a+1)) * 8;
          200 
          201                 switch (otype) {
          202                 default:
          203                         p = seprint(p, e, "\n          option=%s ", opt);
          204                         m->pr = &dump;
          205                         return p;
          206 
          207                 case sll:
          208                 case tll:
          209                         if ((pktsz < osz) || (osz != 8)) {
          210                                 p = seprint(p, e, "\n          option=%s bad size=%d", opt, osz);
          211                                 m->pr = &dump;
          212                                 return p;
          213                         }
          214                         p = seprint(p, e, "\n          option=%s maddr=%E", opt, a+2);
          215                         pktsz -= osz;
          216                         a += osz;
          217                         break;
          218 
          219                 case pref:
          220                         if ((pktsz < osz) || (osz != 32)) {
          221                                 p = seprint(p, e, "\n          option=%s: bad size=%d", opt, osz);
          222                                 m->pr = &dump;
          223                                 return p;
          224                         }
          225 
          226                         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",
          227                                 opt,
          228                                 a+16,
          229                                 (int) (*(a+2)),
          230                                 (*(a+3) & (1 << 7))!=0,
          231                                 (*(a+3) & (1 << 6))!=0,
          232                                 (*(a+3) & 63) != 0,
          233                                 NetL(a+4),
          234                                 NetL(a+8),
          235                                 NetL(a+12)!=0);
          236 
          237                         pktsz -= osz;
          238                         a += osz;
          239                         break;
          240 
          241                 case redir:
          242                         if (pktsz < osz) {
          243                                 p = seprint(p, e, "\n          option=%s: bad size=%d", opt, osz);
          244                                 m->pr = &dump;
          245                                 return p;
          246                         }
          247 
          248                         p = seprint(p, e, "\n          option=%s len %d", opt, osz);
          249                         a += osz;
          250                         m->ps = a;
          251                         return p;
          252                         break;
          253 
          254                 case mtu:
          255                         if ((pktsz < osz) || (osz != 8)) {
          256                                 p = seprint(p, e, "\n          option=%s: bad size=%d", opt, osz);
          257                                 m->pr = &dump;
          258                                 return p;
          259                         }
          260 
          261                         p = seprint(p, e, "\n          option=%s unused=%1.1d mtu=%d", opt, NetL(a+2)!=0, NetL(a+4));
          262                         pktsz -= osz;
          263                         a += osz;
          264                         break;
          265                 }
          266         }
          267 
          268         m->ps = a;
          269         return p;
          270 }
          271 
          272 static int
          273 p_seprint(Msg *m)
          274 {
          275         Hdr *h;
          276         char *tn;
          277         char *p = m->p;
          278         char *e = m->e;
          279         int i;
          280         uchar *a;
          281 /*        ushort cksum2, cksum; */
          282 
          283         h = (Hdr*)m->ps;
          284         m->ps += ICMP6LEN;
          285         m->pr = &dump;
          286         a = m->ps;
          287 
          288         if(m->pe - m->ps < ICMP6LEN)
          289                 return -1;
          290 
          291         tn = icmpmsg6[h->type];
          292         if(tn == nil)
          293                 p = seprint(p, e, "t=%ud c=%d ck=%4.4ux", h->type,
          294                         h->code, (ushort)NetS(h->cksum));
          295         else
          296                 p = seprint(p, e, "t=%s c=%d ck=%4.4ux", tn,
          297                         h->code, (ushort)NetS(h->cksum));
          298 
          299         /*
          300         if(Cflag){
          301                 cksum = NetS(h->cksum);
          302                 h->cksum[0] = 0;
          303                 h->cksum[1] = 0;
          304                 cksum2 = ~ptclbsum((uchar*)h, m->pe - m->ps + ICMP6LEN) & 0xffff;
          305                 if(cksum != cksum2)
          306                         p = seprint(p,e, " !ck=%4.4ux", cksum2);
          307         }
          308         */
          309 
          310         switch(h->type){
          311 
          312         case UnreachableV6:
          313                 m->ps += 4;
          314                 m->pr = &ip6;
          315                 if (h->code >= nelem(unreachcode))
          316                         i = nelem(unreachcode)-1;
          317                 else
          318                         i = h->code;
          319                 p = seprint(p, e, " code=%s unused=%1.1d ", unreachcode[i], NetL(a)!=0);
          320                 break;
          321 
          322         case PacketTooBigV6:
          323                 m->ps += 4;
          324                 m->pr = &ip6;
          325                 p = seprint(p, e, " mtu=%4.4d ", NetL(a));
          326                 break;
          327 
          328         case TimeExceedV6:
          329                 m->ps += 4;
          330                 m->pr = &ip6;
          331                 if (h->code >= nelem(timexcode))
          332                         i = nelem(timexcode)-1;
          333                 else
          334                         i = h->code;
          335                 p = seprint(p, e, " code=%s unused=%1.1d ", timexcode[i], NetL(a)!=0);
          336                 break;
          337 
          338         case ParamProblemV6:
          339                 m->ps += 4;
          340                 m->pr = &ip6;
          341                 if (h->code > nelem(parpcode))
          342                         i = nelem(parpcode)-1;
          343                 else
          344                         i = h->code;
          345                 p = seprint(p, e, " code=%s ptr=%2.2ux", parpcode[i], h->data[0]);
          346                 break;
          347 
          348         case EchoReplyV6:
          349         case EchoRequestV6:
          350                 m->ps += 4;
          351                 p = seprint(p, e, " id=%ux seq=%ux",
          352                         NetS(h->data), NetS(h->data+2));
          353                 break;
          354 
          355         case RouterSolicit:
          356                 m->ps += 4;
          357                 m->pr = nil;
          358                 m->p = seprint(p, e, " unused=%1.1d ", NetL(a)!=0);
          359                 p = opt_seprint(m);
          360                 break;
          361 
          362         case RouterAdvert:
          363                 m->ps += 12;
          364                 m->pr = nil;
          365                 m->p = seprint(p, e, " hoplim=%3.3d mflag=%1.1d oflag=%1.1d unused=%1.1d routerlt=%8.8d reachtime=%d rxmtimer=%d",
          366                         (int) *a,
          367                         (*(a+1) & (1 << 7)) != 0,
          368                         (*(a+1) & (1 << 6)) != 0,
          369                         (*(a+1) & 63) != 0,
          370                         NetS(a+2),
          371                         NetL(a+4),
          372                         NetL(a+8));
          373                 p = opt_seprint(m);
          374                 break;
          375 
          376         case NbrSolicit:
          377                 m->ps += 20;
          378                 m->pr = nil;
          379                 m->p = seprint(p, e, " unused=%1.1d targ %I", NetL(a)!=0, a+4);
          380                 p = opt_seprint(m);
          381                 break;
          382 
          383         case NbrAdvert:
          384                 m->ps += 20;
          385                 m->pr = nil;
          386                 m->p = seprint(p, e, " rflag=%1.1d sflag=%1.1d oflag=%1.1d targ=%I",
          387                         (*a & (1 << 7)) != 0,
          388                         (*a & (1 << 6)) != 0,
          389                         (*a & (1 << 5)) != 0,
          390                         a+4);
          391                 p = opt_seprint(m);
          392                 break;
          393 
          394         case RedirectV6:
          395                 m->ps += 36;
          396                 m->pr = &ip6;
          397                 m->p = seprint(p, e, " unused=%1.1d targ=%I dest=%I", NetL(a)!=0, a+4, a+20);
          398                 p = opt_seprint(m);
          399                 break;
          400 
          401         case Timestamp:
          402         case TimestampReply:
          403                 m->ps += 12;
          404                 p = seprint(p, e, " orig=%ud rcv=%ux xmt=%ux",
          405                         NetL(h->data), NetL(h->data+4),
          406                         NetL(h->data+8));
          407                 m->pr = nil;
          408                 break;
          409 
          410         case InfoRequest:
          411         case InfoReply:
          412                 break;
          413 
          414         }
          415         m->p = p;
          416         return 0;
          417 }
          418 
          419 Proto icmp6 =
          420 {
          421         "icmp6",
          422         p_compile,
          423         p_filter,
          424         p_seprint,
          425         p_mux,
          426         "%lud",
          427         p_fields,
          428         defaultframer
          429 };