Blob
1 #include <u.h>2 #include <libc.h>3 #include <ip.h>4 #include "dat.h"5 #include "protos.h"7 typedef struct Hdr Hdr;8 struct Hdr9 { uchar type;10 uchar code;11 uchar cksum[2]; /* Checksum */12 uchar data[1];13 };15 enum16 {17 ICMPLEN= 418 };20 enum21 {22 Ot, /* type */23 Op, /* next protocol */24 };26 static Field p_fields[] =27 {28 {"t", Fnum, Ot, "type", } ,29 {0}30 };32 enum33 {34 EchoRep= 0,35 Unreachable= 3,36 SrcQuench= 4,37 Redirect= 5,38 EchoReq= 8,39 TimeExceed= 11,40 ParamProb= 12,41 TSreq= 13,42 TSrep= 14,43 InfoReq= 15,44 InfoRep= 1645 };47 static Mux p_mux[] =48 {49 {"ip", Unreachable, },50 {"ip", SrcQuench, },51 {"ip", Redirect, },52 {"ip", TimeExceed, },53 {"ip", ParamProb, },54 {0}55 };57 char *icmpmsg[256] =58 {59 [EchoRep] "EchoRep",60 [Unreachable] "Unreachable",61 [SrcQuench] "SrcQuench",62 [Redirect] "Redirect",63 [EchoReq] "EchoReq",64 [TimeExceed] "TimeExceed",65 [ParamProb] "ParamProb",66 [TSreq] "TSreq",67 [TSrep] "TSrep",68 [InfoReq] "InfoReq",69 [InfoRep] "InfoRep"70 };72 static void73 p_compile(Filter *f)74 {75 if(f->op == '='){76 compile_cmp(udp.name, f, p_fields);77 return;78 }79 if(strcmp(f->s, "ip") == 0){80 f->pr = p_mux->pr;81 f->subop = Op;82 return;83 }84 sysfatal("unknown icmp field or protocol: %s", f->s);85 }87 static int88 p_filter(Filter *f, Msg *m)89 {90 Hdr *h;92 if(m->pe - m->ps < ICMPLEN)93 return 0;95 h = (Hdr*)m->ps;96 m->ps += ICMPLEN;98 switch(f->subop){99 case Ot:100 if(h->type == f->ulv)101 return 1;102 break;103 case Op:104 switch(h->type){105 case Unreachable:106 case TimeExceed:107 case SrcQuench:108 case Redirect:109 case ParamProb:110 m->ps += 4;111 return 1;112 }113 }114 return 0;115 }117 static int118 p_seprint(Msg *m)119 {120 Hdr *h;121 char *tn;122 char *p = m->p;123 char *e = m->e;124 ushort cksum2, cksum;126 h = (Hdr*)m->ps;127 m->ps += ICMPLEN;128 m->pr = &dump;130 if(m->pe - m->ps < ICMPLEN)131 return -1;133 tn = icmpmsg[h->type];134 if(tn == nil)135 p = seprint(p, e, "t=%ud c=%d ck=%4.4ux", h->type,136 h->code, (ushort)NetS(h->cksum));137 else138 p = seprint(p, e, "t=%s c=%d ck=%4.4ux", tn,139 h->code, (ushort)NetS(h->cksum));140 if(Cflag){141 cksum = NetS(h->cksum);142 h->cksum[0] = 0;143 h->cksum[1] = 0;144 cksum2 = ~ptclbsum((uchar*)h, m->pe - m->ps + ICMPLEN) & 0xffff;145 if(cksum != cksum2)146 p = seprint(p,e, " !ck=%4.4ux", cksum2);147 }148 switch(h->type){149 case EchoRep:150 case EchoReq:151 m->ps += 4;152 p = seprint(p, e, " id=%ux seq=%ux",153 NetS(h->data), NetS(h->data+2));154 break;155 case TSreq:156 case TSrep:157 m->ps += 12;158 p = seprint(p, e, " orig=%ud rcv=%ux xmt=%ux",159 NetL(h->data), NetL(h->data+4),160 NetL(h->data+8));161 m->pr = nil;162 break;163 case InfoReq:164 case InfoRep:165 break;166 case Unreachable:167 case TimeExceed:168 case SrcQuench:169 m->ps += 4;170 m->pr = &ip;171 break;172 case Redirect:173 m->ps += 4;174 m->pr = &ip;175 p = seprint(p, e, "gw=%V", h->data);176 break;177 case ParamProb:178 m->ps += 4;179 m->pr = &ip;180 p = seprint(p, e, "ptr=%2.2ux", h->data[0]);181 break;182 }183 m->p = p;184 return 0;185 }187 Proto icmp =188 {189 "icmp",190 p_compile,191 p_filter,192 p_seprint,193 p_mux,194 "%lud",195 p_fields,196 defaultframer197 };