]> The Tcpdump Group git mirrors - tcpdump/blob - print-icmp.c
(icmp_print): check checksum if vflag. From [email protected]
[tcpdump] / print-icmp.c
1 /*
2 * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22 #ifndef lint
23 static const char rcsid[] =
24 "@(#) $Header: /tcpdump/master/tcpdump/print-icmp.c,v 1.41 1999-11-21 03:46:38 assar Exp $ (LBL)";
25 #endif
26
27 #include <sys/param.h>
28 #include <sys/time.h>
29 #include <sys/socket.h>
30
31 #if __STDC__
32 struct mbuf;
33 struct rtentry;
34 #endif
35 #include <net/if.h>
36
37 #include <netinet/in.h>
38 #include <netinet/if_ether.h>
39 #include <netinet/in_systm.h>
40 #include <netinet/ip.h>
41 #include <netinet/ip_icmp.h>
42 #include <netinet/ip_var.h>
43 #include <netinet/udp.h>
44 #include <netinet/udp_var.h>
45 #include <netinet/tcp.h>
46
47 #include <stdio.h>
48 #include <string.h>
49
50 #include "interface.h"
51 #include "addrtoname.h"
52 #include "extract.h" /* must come after interface.h */
53
54 /* rfc1700 */
55 #ifndef ICMP_UNREACH_NET_UNKNOWN
56 #define ICMP_UNREACH_NET_UNKNOWN 6 /* destination net unknown */
57 #endif
58 #ifndef ICMP_UNREACH_HOST_UNKNOWN
59 #define ICMP_UNREACH_HOST_UNKNOWN 7 /* destination host unknown */
60 #endif
61 #ifndef ICMP_UNREACH_ISOLATED
62 #define ICMP_UNREACH_ISOLATED 8 /* source host isolated */
63 #endif
64 #ifndef ICMP_UNREACH_NET_PROHIB
65 #define ICMP_UNREACH_NET_PROHIB 9 /* admin prohibited net */
66 #endif
67 #ifndef ICMP_UNREACH_HOST_PROHIB
68 #define ICMP_UNREACH_HOST_PROHIB 10 /* admin prohibited host */
69 #endif
70 #ifndef ICMP_UNREACH_TOSNET
71 #define ICMP_UNREACH_TOSNET 11 /* tos prohibited net */
72 #endif
73 #ifndef ICMP_UNREACH_TOSHOST
74 #define ICMP_UNREACH_TOSHOST 12 /* tos prohibited host */
75 #endif
76
77 /* rfc1716 */
78 #ifndef ICMP_UNREACH_FILTER_PROHIB
79 #define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */
80 #endif
81 #ifndef ICMP_UNREACH_HOST_PRECEDENCE
82 #define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host precedence violation */
83 #endif
84 #ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
85 #define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */
86 #endif
87
88 /* rfc1256 */
89 #ifndef ICMP_ROUTERADVERT
90 #define ICMP_ROUTERADVERT 9 /* router advertisement */
91 #endif
92 #ifndef ICMP_ROUTERSOLICIT
93 #define ICMP_ROUTERSOLICIT 10 /* router solicitation */
94 #endif
95
96 /* Most of the icmp types */
97 static struct tok icmp2str[] = {
98 { ICMP_ECHOREPLY, "echo reply" },
99 { ICMP_SOURCEQUENCH, "source quench" },
100 { ICMP_ECHO, "echo request" },
101 { ICMP_ROUTERSOLICIT, "router solicitation" },
102 { ICMP_TSTAMP, "time stamp request" },
103 { ICMP_TSTAMPREPLY, "time stamp reply" },
104 { ICMP_IREQ, "information request" },
105 { ICMP_IREQREPLY, "information reply" },
106 { ICMP_MASKREQ, "address mask request" },
107 { 0, NULL }
108 };
109
110 /* Formats for most of the ICMP_UNREACH codes */
111 static struct tok unreach2str[] = {
112 { ICMP_UNREACH_NET, "net %s unreachable" },
113 { ICMP_UNREACH_HOST, "host %s unreachable" },
114 { ICMP_UNREACH_SRCFAIL,
115 "%s unreachable - source route failed" },
116 { ICMP_UNREACH_NET_UNKNOWN, "net %s unreachable - unknown" },
117 { ICMP_UNREACH_HOST_UNKNOWN, "host %s unreachable - unknown" },
118 { ICMP_UNREACH_ISOLATED,
119 "%s unreachable - source host isolated" },
120 { ICMP_UNREACH_NET_PROHIB,
121 "net %s unreachable - admin prohibited" },
122 { ICMP_UNREACH_HOST_PROHIB,
123 "host %s unreachable - admin prohibited" },
124 { ICMP_UNREACH_TOSNET,
125 "net %s unreachable - tos prohibited" },
126 { ICMP_UNREACH_TOSHOST,
127 "host %s unreachable - tos prohibited" },
128 { ICMP_UNREACH_FILTER_PROHIB,
129 "host %s unreachable - admin prohibited filter" },
130 { ICMP_UNREACH_HOST_PRECEDENCE,
131 "host %s unreachable - host precedence violation" },
132 { ICMP_UNREACH_PRECEDENCE_CUTOFF,
133 "host %s unreachable - precedence cutoff" },
134 { 0, NULL }
135 };
136
137 /* Formats for the ICMP_REDIRECT codes */
138 static struct tok type2str[] = {
139 { ICMP_REDIRECT_NET, "redirect %s to net %s" },
140 { ICMP_REDIRECT_HOST, "redirect %s to host %s" },
141 { ICMP_REDIRECT_TOSNET, "redirect-tos %s to net %s" },
142 { ICMP_REDIRECT_TOSHOST, "redirect-tos %s to net %s" },
143 { 0, NULL }
144 };
145
146 /* rfc1191 */
147 struct mtu_discovery {
148 short unused;
149 short nexthopmtu;
150 };
151
152 /* rfc1256 */
153 struct ih_rdiscovery {
154 u_char ird_addrnum;
155 u_char ird_addrsiz;
156 u_short ird_lifetime;
157 };
158
159 struct id_rdiscovery {
160 u_int32_t ird_addr;
161 u_int32_t ird_pref;
162 };
163
164 void
165 icmp_print(register const u_char *bp, u_int plen, register const u_char *bp2)
166 {
167 register char *cp;
168 register const struct icmp *dp;
169 register const struct ip *ip;
170 register const char *str, *fmt;
171 register const struct ip *oip;
172 register const struct udphdr *ouh;
173 register u_int hlen, dport, mtu;
174 char buf[256];
175
176 dp = (struct icmp *)bp;
177 ip = (struct ip *)bp2;
178 str = buf;
179
180 #if 0
181 (void)printf("%s > %s: ",
182 ipaddr_string(&ip->ip_src),
183 ipaddr_string(&ip->ip_dst));
184 #endif
185
186 TCHECK(dp->icmp_code);
187 switch (dp->icmp_type) {
188
189 case ICMP_UNREACH:
190 TCHECK(dp->icmp_ip.ip_dst);
191 switch (dp->icmp_code) {
192
193 case ICMP_UNREACH_PROTOCOL:
194 TCHECK(dp->icmp_ip.ip_p);
195 (void)sprintf(buf, "%s protocol %d unreachable",
196 ipaddr_string(&dp->icmp_ip.ip_dst),
197 dp->icmp_ip.ip_p);
198 break;
199
200 case ICMP_UNREACH_PORT:
201 TCHECK(dp->icmp_ip.ip_p);
202 oip = &dp->icmp_ip;
203 hlen = oip->ip_hl * 4;
204 ouh = (struct udphdr *)(((u_char *)oip) + hlen);
205 dport = ntohs(ouh->uh_dport);
206 switch (oip->ip_p) {
207
208 case IPPROTO_TCP:
209 (void)sprintf(buf,
210 "%s tcp port %s unreachable",
211 ipaddr_string(&oip->ip_dst),
212 tcpport_string(dport));
213 break;
214
215 case IPPROTO_UDP:
216 (void)sprintf(buf,
217 "%s udp port %s unreachable",
218 ipaddr_string(&oip->ip_dst),
219 udpport_string(dport));
220 break;
221
222 default:
223 (void)sprintf(buf,
224 "%s protocol %d port %d unreachable",
225 ipaddr_string(&oip->ip_dst),
226 oip->ip_p, dport);
227 break;
228 }
229 break;
230
231 case ICMP_UNREACH_NEEDFRAG:
232 {
233 register const struct mtu_discovery *mp;
234
235 mp = (struct mtu_discovery *)&dp->icmp_void;
236 mtu = EXTRACT_16BITS(&mp->nexthopmtu);
237 if (mtu)
238 (void)sprintf(buf,
239 "%s unreachable - need to frag (mtu %d)",
240 ipaddr_string(&dp->icmp_ip.ip_dst), mtu);
241 else
242 (void)sprintf(buf,
243 "%s unreachable - need to frag",
244 ipaddr_string(&dp->icmp_ip.ip_dst));
245 }
246 break;
247
248 default:
249 fmt = tok2str(unreach2str, "#%d %%s unreachable",
250 dp->icmp_code);
251 (void)sprintf(buf, fmt,
252 ipaddr_string(&dp->icmp_ip.ip_dst));
253 break;
254 }
255 break;
256
257 case ICMP_REDIRECT:
258 TCHECK(dp->icmp_ip.ip_dst);
259 fmt = tok2str(type2str, "redirect-#%d %%s to net %%s",
260 dp->icmp_code);
261 (void)sprintf(buf, fmt,
262 ipaddr_string(&dp->icmp_ip.ip_dst),
263 ipaddr_string(&dp->icmp_gwaddr));
264 break;
265
266 case ICMP_ROUTERADVERT:
267 {
268 register const struct ih_rdiscovery *ihp;
269 register const struct id_rdiscovery *idp;
270 u_int lifetime, num, size;
271
272 (void)strcpy(buf, "router advertisement");
273 cp = buf + strlen(buf);
274
275 ihp = (struct ih_rdiscovery *)&dp->icmp_void;
276 TCHECK(*ihp);
277 (void)strcpy(cp, " lifetime ");
278 cp = buf + strlen(buf);
279 lifetime = EXTRACT_16BITS(&ihp->ird_lifetime);
280 if (lifetime < 60)
281 (void)sprintf(cp, "%u", lifetime);
282 else if (lifetime < 60 * 60)
283 (void)sprintf(cp, "%u:%02u",
284 lifetime / 60, lifetime % 60);
285 else
286 (void)sprintf(cp, "%u:%02u:%02u",
287 lifetime / 3600,
288 (lifetime % 3600) / 60,
289 lifetime % 60);
290 cp = buf + strlen(buf);
291
292 num = ihp->ird_addrnum;
293 (void)sprintf(cp, " %d:", num);
294 cp = buf + strlen(buf);
295
296 size = ihp->ird_addrsiz;
297 if (size != 2) {
298 (void)sprintf(cp, " [size %d]", size);
299 break;
300 }
301 idp = (struct id_rdiscovery *)&dp->icmp_data;
302 while (num-- > 0) {
303 TCHECK(*idp);
304 (void)sprintf(cp, " {%s %u}",
305 ipaddr_string(&idp->ird_addr),
306 EXTRACT_32BITS(&idp->ird_pref));
307 cp = buf + strlen(buf);
308 }
309 }
310 break;
311
312 case ICMP_TIMXCEED:
313 TCHECK(dp->icmp_ip.ip_dst);
314 switch (dp->icmp_code) {
315
316 case ICMP_TIMXCEED_INTRANS:
317 str = "time exceeded in-transit";
318 break;
319
320 case ICMP_TIMXCEED_REASS:
321 str = "ip reassembly time exceeded";
322 break;
323
324 default:
325 (void)sprintf(buf, "time exceeded-#%d", dp->icmp_code);
326 break;
327 }
328 break;
329
330 case ICMP_PARAMPROB:
331 if (dp->icmp_code)
332 (void)sprintf(buf, "parameter problem - code %d",
333 dp->icmp_code);
334 else {
335 TCHECK(dp->icmp_pptr);
336 (void)sprintf(buf, "parameter problem - octet %d",
337 dp->icmp_pptr);
338 }
339 break;
340
341 case ICMP_MASKREPLY:
342 TCHECK(dp->icmp_mask);
343 (void)sprintf(buf, "address mask is 0x%08x",
344 (u_int32_t)ntohl(dp->icmp_mask));
345 break;
346
347 default:
348 str = tok2str(icmp2str, "type-#%d", dp->icmp_type);
349 break;
350 }
351 (void)printf("icmp: %s", str);
352 if (vflag) {
353 if (((u_char*)bp) + plen <= snapend) {
354 if (in_cksum((u_short*)dp, plen, 0))
355 printf(" (wrong icmp csum)");
356 }
357 }
358 return;
359 trunc:
360 fputs("[|icmp]", stdout);
361 }