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 Hdr
9 { uchar type;
10 uchar code;
11 uchar cksum[2]; /* Checksum */
12 uchar data[1];
13 };
15 enum
16 {
17 ICMPLEN= 4
18 };
20 enum
21 {
22 Ot, /* type */
23 Op, /* next protocol */
24 };
26 static Field p_fields[] =
27 {
28 {"t", Fnum, Ot, "type", } ,
29 {0}
30 };
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 };
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 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 }
87 static int
88 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;
114 return 0;
117 static int
118 p_seprint(Msg *m)
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 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);
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;
183 m->p = p;
184 return 0;
187 Proto icmp =
189 "icmp",
190 p_compile,
191 p_filter,
192 p_seprint,
193 p_mux,
194 "%lud",
195 p_fields,
196 defaultframer
197 };