2 * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996
3 * The Regents of the University of California. All rights reserved.
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
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.
23 static const char rcsid
[] =
24 "@(#) $Header: /tcpdump/master/tcpdump/print-icmp.c,v 1.48 2000-07-01 03:39:03 assar Exp $ (LBL)";
31 #include <sys/param.h>
33 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <netinet/if_ether.h>
41 #include <netinet/in_systm.h>
42 #include <netinet/ip.h>
43 #include <netinet/ip_icmp.h>
44 #include <netinet/ip_var.h>
45 #include <netinet/udp.h>
46 #include <netinet/udp_var.h>
47 #include <netinet/tcp.h>
52 #include "interface.h"
53 #include "addrtoname.h"
54 #include "extract.h" /* must come after interface.h */
57 #ifndef ICMP_UNREACH_NET_UNKNOWN
58 #define ICMP_UNREACH_NET_UNKNOWN 6 /* destination net unknown */
60 #ifndef ICMP_UNREACH_HOST_UNKNOWN
61 #define ICMP_UNREACH_HOST_UNKNOWN 7 /* destination host unknown */
63 #ifndef ICMP_UNREACH_ISOLATED
64 #define ICMP_UNREACH_ISOLATED 8 /* source host isolated */
66 #ifndef ICMP_UNREACH_NET_PROHIB
67 #define ICMP_UNREACH_NET_PROHIB 9 /* admin prohibited net */
69 #ifndef ICMP_UNREACH_HOST_PROHIB
70 #define ICMP_UNREACH_HOST_PROHIB 10 /* admin prohibited host */
72 #ifndef ICMP_UNREACH_TOSNET
73 #define ICMP_UNREACH_TOSNET 11 /* tos prohibited net */
75 #ifndef ICMP_UNREACH_TOSHOST
76 #define ICMP_UNREACH_TOSHOST 12 /* tos prohibited host */
80 #ifndef ICMP_UNREACH_FILTER_PROHIB
81 #define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */
83 #ifndef ICMP_UNREACH_HOST_PRECEDENCE
84 #define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host precedence violation */
86 #ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
87 #define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */
91 #ifndef ICMP_ROUTERADVERT
92 #define ICMP_ROUTERADVERT 9 /* router advertisement */
94 #ifndef ICMP_ROUTERSOLICIT
95 #define ICMP_ROUTERSOLICIT 10 /* router solicitation */
98 /* Most of the icmp types */
99 static struct tok icmp2str
[] = {
100 { ICMP_ECHOREPLY
, "echo reply" },
101 { ICMP_SOURCEQUENCH
, "source quench" },
102 { ICMP_ECHO
, "echo request" },
103 { ICMP_ROUTERSOLICIT
, "router solicitation" },
104 { ICMP_TSTAMP
, "time stamp request" },
105 { ICMP_TSTAMPREPLY
, "time stamp reply" },
106 { ICMP_IREQ
, "information request" },
107 { ICMP_IREQREPLY
, "information reply" },
108 { ICMP_MASKREQ
, "address mask request" },
112 /* Formats for most of the ICMP_UNREACH codes */
113 static struct tok unreach2str
[] = {
114 { ICMP_UNREACH_NET
, "net %s unreachable" },
115 { ICMP_UNREACH_HOST
, "host %s unreachable" },
116 { ICMP_UNREACH_SRCFAIL
,
117 "%s unreachable - source route failed" },
118 { ICMP_UNREACH_NET_UNKNOWN
, "net %s unreachable - unknown" },
119 { ICMP_UNREACH_HOST_UNKNOWN
, "host %s unreachable - unknown" },
120 { ICMP_UNREACH_ISOLATED
,
121 "%s unreachable - source host isolated" },
122 { ICMP_UNREACH_NET_PROHIB
,
123 "net %s unreachable - admin prohibited" },
124 { ICMP_UNREACH_HOST_PROHIB
,
125 "host %s unreachable - admin prohibited" },
126 { ICMP_UNREACH_TOSNET
,
127 "net %s unreachable - tos prohibited" },
128 { ICMP_UNREACH_TOSHOST
,
129 "host %s unreachable - tos prohibited" },
130 { ICMP_UNREACH_FILTER_PROHIB
,
131 "host %s unreachable - admin prohibited filter" },
132 { ICMP_UNREACH_HOST_PRECEDENCE
,
133 "host %s unreachable - host precedence violation" },
134 { ICMP_UNREACH_PRECEDENCE_CUTOFF
,
135 "host %s unreachable - precedence cutoff" },
139 /* Formats for the ICMP_REDIRECT codes */
140 static struct tok type2str
[] = {
141 { ICMP_REDIRECT_NET
, "redirect %s to net %s" },
142 { ICMP_REDIRECT_HOST
, "redirect %s to host %s" },
143 { ICMP_REDIRECT_TOSNET
, "redirect-tos %s to net %s" },
144 { ICMP_REDIRECT_TOSHOST
, "redirect-tos %s to net %s" },
149 struct mtu_discovery
{
155 struct ih_rdiscovery
{
158 u_short ird_lifetime
;
161 struct id_rdiscovery
{
167 icmp_print(register const u_char
*bp
, u_int plen
, register const u_char
*bp2
)
170 register const struct icmp
*dp
;
171 register const struct ip
*ip
;
172 register const char *str
, *fmt
;
173 register const struct ip
*oip
;
174 register const struct udphdr
*ouh
;
175 register u_int hlen
, dport
, mtu
;
178 dp
= (struct icmp
*)bp
;
179 ip
= (struct ip
*)bp2
;
183 (void)printf("%s > %s: ",
184 ipaddr_string(&ip
->ip_src
),
185 ipaddr_string(&ip
->ip_dst
));
188 TCHECK(dp
->icmp_code
);
189 switch (dp
->icmp_type
) {
192 TCHECK(dp
->icmp_ip
.ip_dst
);
193 switch (dp
->icmp_code
) {
195 case ICMP_UNREACH_PROTOCOL
:
196 TCHECK(dp
->icmp_ip
.ip_p
);
197 (void)snprintf(buf
, sizeof(buf
),
198 "%s protocol %d unreachable",
199 ipaddr_string(&dp
->icmp_ip
.ip_dst
),
203 case ICMP_UNREACH_PORT
:
204 TCHECK(dp
->icmp_ip
.ip_p
);
206 hlen
= oip
->ip_hl
* 4;
207 ouh
= (struct udphdr
*)(((u_char
*)oip
) + hlen
);
208 dport
= ntohs(ouh
->uh_dport
);
212 (void)snprintf(buf
, sizeof(buf
),
213 "%s tcp port %s unreachable",
214 ipaddr_string(&oip
->ip_dst
),
215 tcpport_string(dport
));
219 (void)snprintf(buf
, sizeof(buf
),
220 "%s udp port %s unreachable",
221 ipaddr_string(&oip
->ip_dst
),
222 udpport_string(dport
));
226 (void)snprintf(buf
, sizeof(buf
),
227 "%s protocol %d port %d unreachable",
228 ipaddr_string(&oip
->ip_dst
),
234 case ICMP_UNREACH_NEEDFRAG
:
236 register const struct mtu_discovery
*mp
;
237 mp
= (struct mtu_discovery
*)&dp
->icmp_void
;
238 mtu
= EXTRACT_16BITS(&mp
->nexthopmtu
);
240 (void)snprintf(buf
, sizeof(buf
),
241 "%s unreachable - need to frag (mtu %d)",
242 ipaddr_string(&dp
->icmp_ip
.ip_dst
), mtu
);
244 (void)snprintf(buf
, sizeof(buf
),
245 "%s unreachable - need to frag",
246 ipaddr_string(&dp
->icmp_ip
.ip_dst
));
252 fmt
= tok2str(unreach2str
, "#%d %%s unreachable",
254 (void)snprintf(buf
, sizeof(buf
), fmt
,
255 ipaddr_string(&dp
->icmp_ip
.ip_dst
));
261 TCHECK(dp
->icmp_ip
.ip_dst
);
262 fmt
= tok2str(type2str
, "redirect-#%d %%s to net %%s",
264 (void)snprintf(buf
, sizeof(buf
), fmt
,
265 ipaddr_string(&dp
->icmp_ip
.ip_dst
),
266 ipaddr_string(&dp
->icmp_gwaddr
));
269 case ICMP_ROUTERADVERT
:
271 register const struct ih_rdiscovery
*ihp
;
272 register const struct id_rdiscovery
*idp
;
273 u_int lifetime
, num
, size
;
275 (void)snprintf(buf
, sizeof(buf
), "router advertisement");
276 cp
= buf
+ strlen(buf
);
278 ihp
= (struct ih_rdiscovery
*)&dp
->icmp_void
;
280 (void)strncpy(cp
, " lifetime ", sizeof(buf
) - (cp
- buf
));
281 cp
= buf
+ strlen(buf
);
282 lifetime
= EXTRACT_16BITS(&ihp
->ird_lifetime
);
284 (void)snprintf(cp
, sizeof(buf
) - (cp
- buf
), "%u",
286 } else if (lifetime
< 60 * 60) {
287 (void)snprintf(cp
, sizeof(buf
) - (cp
- buf
), "%u:%02u",
288 lifetime
/ 60, lifetime
% 60);
290 (void)snprintf(cp
, sizeof(buf
) - (cp
- buf
),
293 (lifetime
% 3600) / 60,
296 cp
= buf
+ strlen(buf
);
298 num
= ihp
->ird_addrnum
;
299 (void)snprintf(cp
, sizeof(buf
) - (cp
- buf
), " %d:", num
);
300 cp
= buf
+ strlen(buf
);
302 size
= ihp
->ird_addrsiz
;
304 (void)snprintf(cp
, sizeof(buf
) - (cp
- buf
),
308 idp
= (struct id_rdiscovery
*)&dp
->icmp_data
;
311 (void)snprintf(cp
, sizeof(buf
) - (cp
- buf
), " {%s %u}",
312 ipaddr_string(&idp
->ird_addr
),
313 EXTRACT_32BITS(&idp
->ird_pref
));
314 cp
= buf
+ strlen(buf
);
321 TCHECK(dp
->icmp_ip
.ip_dst
);
322 switch (dp
->icmp_code
) {
324 case ICMP_TIMXCEED_INTRANS
:
325 str
= "time exceeded in-transit";
328 case ICMP_TIMXCEED_REASS
:
329 str
= "ip reassembly time exceeded";
333 (void)snprintf(buf
, sizeof(buf
), "time exceeded-#%d",
341 (void)snprintf(buf
, sizeof(buf
),
342 "parameter problem - code %d", dp
->icmp_code
);
344 TCHECK(dp
->icmp_pptr
);
345 (void)snprintf(buf
, sizeof(buf
),
346 "parameter problem - octet %d", dp
->icmp_pptr
);
351 TCHECK(dp
->icmp_mask
);
352 (void)snprintf(buf
, sizeof(buf
), "address mask is 0x%08x",
353 (unsigned)ntohl(dp
->icmp_mask
));
357 TCHECK(dp
->icmp_seq
);
358 (void)sprintf(buf
, "time stamp query id %u seq %u",
359 (unsigned)ntohs(dp
->icmp_id
),
360 (unsigned)ntohs(dp
->icmp_seq
));
363 case ICMP_TSTAMPREPLY
:
364 TCHECK(dp
->icmp_ttime
);
365 (void)sprintf(buf
, "time stamp reply id %u seq %u : org 0x%lx recv 0x%lx xmit 0x%lx",
366 (unsigned)ntohs(dp
->icmp_id
),
367 (unsigned)ntohs(dp
->icmp_seq
),
368 (unsigned long)ntohl(dp
->icmp_otime
),
369 (unsigned long)ntohl(dp
->icmp_rtime
),
370 (unsigned long)ntohl(dp
->icmp_ttime
));
374 str
= tok2str(icmp2str
, "type-#%d", dp
->icmp_type
);
377 (void)printf("icmp: %s", str
);
379 if (TTEST2(*bp
, plen
)) {
380 if (in_cksum((u_short
*)dp
, plen
, 0))
381 printf(" (wrong icmp csum)");
384 if (vflag
> 1 && !ICMP_INFOTYPE(dp
->icmp_type
)) {
386 (void)printf(" for ");
387 ip
= (struct ip
*)bp
;
388 snaplen
= snapend
- bp
;
389 ip_print(bp
, ntohs(ip
->ip_len
));
393 fputs("[|icmp]", stdout
);