icmp.c (2963B)
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 ICMPLEN= 4 18 }; 19 20 enum 21 { 22 Ot, /* type */ 23 Op, /* next protocol */ 24 }; 25 26 static Field p_fields[] = 27 { 28 {"t", Fnum, Ot, "type", } , 29 {0} 30 }; 31 32 enum 33 { 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= 16 45 }; 46 47 static Mux p_mux[] = 48 { 49 {"ip", Unreachable, }, 50 {"ip", SrcQuench, }, 51 {"ip", Redirect, }, 52 {"ip", TimeExceed, }, 53 {"ip", ParamProb, }, 54 {0} 55 }; 56 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 }; 71 72 static void 73 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 } 86 87 static int 88 p_filter(Filter *f, Msg *m) 89 { 90 Hdr *h; 91 92 if(m->pe - m->ps < ICMPLEN) 93 return 0; 94 95 h = (Hdr*)m->ps; 96 m->ps += ICMPLEN; 97 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 } 116 117 static int 118 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; 125 126 h = (Hdr*)m->ps; 127 m->ps += ICMPLEN; 128 m->pr = &dump; 129 130 if(m->pe - m->ps < ICMPLEN) 131 return -1; 132 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 else 138 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 } 186 187 Proto icmp = 188 { 189 "icmp", 190 p_compile, 191 p_filter, 192 p_seprint, 193 p_mux, 194 "%lud", 195 p_fields, 196 defaultframer 197 };