Deleted Added
full compact
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 * $FreeBSD: head/contrib/tcpdump/print-icmp.c 56896 2000-01-30 01:05:24Z fenner $
21 * $FreeBSD: head/contrib/tcpdump/print-icmp.c 66644 2000-10-05 02:49:49Z kris $
22 */
23
24#ifndef lint
25static const char rcsid[] =
26 "@(#) $Header: /tcpdump/master/tcpdump/print-icmp.c,v 1.43 1999/11/22 04:28:21 fenner Exp $ (LBL)";
27#endif
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include <sys/param.h>
34#include <sys/time.h>
35#include <sys/socket.h>
36
37#if __STDC__
38struct mbuf;
39struct rtentry;
40#endif
41#include <net/if.h>
42
43#include <netinet/in.h>
44#include <net/ethernet.h>
45#include <netinet/in_systm.h>
46#include <netinet/ip.h>
47#include <netinet/ip_icmp.h>
48#include <netinet/ip_var.h>
49#include <netinet/udp.h>
50#include <netinet/udp_var.h>
51#include <netinet/tcp.h>
52
53#include <stdio.h>
54#include <string.h>
55
56#include "interface.h"
57#include "addrtoname.h"
58#include "extract.h" /* must come after interface.h */
59
60/* rfc1700 */
61#ifndef ICMP_UNREACH_NET_UNKNOWN
62#define ICMP_UNREACH_NET_UNKNOWN 6 /* destination net unknown */
63#endif
64#ifndef ICMP_UNREACH_HOST_UNKNOWN
65#define ICMP_UNREACH_HOST_UNKNOWN 7 /* destination host unknown */
66#endif
67#ifndef ICMP_UNREACH_ISOLATED
68#define ICMP_UNREACH_ISOLATED 8 /* source host isolated */
69#endif
70#ifndef ICMP_UNREACH_NET_PROHIB
71#define ICMP_UNREACH_NET_PROHIB 9 /* admin prohibited net */
72#endif
73#ifndef ICMP_UNREACH_HOST_PROHIB
74#define ICMP_UNREACH_HOST_PROHIB 10 /* admin prohibited host */
75#endif
76#ifndef ICMP_UNREACH_TOSNET
77#define ICMP_UNREACH_TOSNET 11 /* tos prohibited net */
78#endif
79#ifndef ICMP_UNREACH_TOSHOST
80#define ICMP_UNREACH_TOSHOST 12 /* tos prohibited host */
81#endif
82
83/* rfc1716 */
84#ifndef ICMP_UNREACH_FILTER_PROHIB
85#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */
86#endif
87#ifndef ICMP_UNREACH_HOST_PRECEDENCE
88#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host precedence violation */
89#endif
90#ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
91#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */
92#endif
93
94/* rfc1256 */
95#ifndef ICMP_ROUTERADVERT
96#define ICMP_ROUTERADVERT 9 /* router advertisement */
97#endif
98#ifndef ICMP_ROUTERSOLICIT
99#define ICMP_ROUTERSOLICIT 10 /* router solicitation */
100#endif
101
102/* Most of the icmp types */
103static struct tok icmp2str[] = {
104 { ICMP_ECHOREPLY, "echo reply" },
105 { ICMP_SOURCEQUENCH, "source quench" },
106 { ICMP_ECHO, "echo request" },
107 { ICMP_ROUTERSOLICIT, "router solicitation" },
108 { ICMP_TSTAMP, "time stamp request" },
109 { ICMP_TSTAMPREPLY, "time stamp reply" },
110 { ICMP_IREQ, "information request" },
111 { ICMP_IREQREPLY, "information reply" },
112 { ICMP_MASKREQ, "address mask request" },
113 { 0, NULL }
114};
115
116/* Formats for most of the ICMP_UNREACH codes */
117static struct tok unreach2str[] = {
118 { ICMP_UNREACH_NET, "net %s unreachable" },
119 { ICMP_UNREACH_HOST, "host %s unreachable" },
120 { ICMP_UNREACH_SRCFAIL,
121 "%s unreachable - source route failed" },
122 { ICMP_UNREACH_NET_UNKNOWN, "net %s unreachable - unknown" },
123 { ICMP_UNREACH_HOST_UNKNOWN, "host %s unreachable - unknown" },
124 { ICMP_UNREACH_ISOLATED,
125 "%s unreachable - source host isolated" },
126 { ICMP_UNREACH_NET_PROHIB,
127 "net %s unreachable - admin prohibited" },
128 { ICMP_UNREACH_HOST_PROHIB,
129 "host %s unreachable - admin prohibited" },
130 { ICMP_UNREACH_TOSNET,
131 "net %s unreachable - tos prohibited" },
132 { ICMP_UNREACH_TOSHOST,
133 "host %s unreachable - tos prohibited" },
134 { ICMP_UNREACH_FILTER_PROHIB,
135 "host %s unreachable - admin prohibited filter" },
136 { ICMP_UNREACH_HOST_PRECEDENCE,
137 "host %s unreachable - host precedence violation" },
138 { ICMP_UNREACH_PRECEDENCE_CUTOFF,
139 "host %s unreachable - precedence cutoff" },
140 { 0, NULL }
141};
142
143/* Formats for the ICMP_REDIRECT codes */
144static struct tok type2str[] = {
145 { ICMP_REDIRECT_NET, "redirect %s to net %s" },
146 { ICMP_REDIRECT_HOST, "redirect %s to host %s" },
147 { ICMP_REDIRECT_TOSNET, "redirect-tos %s to net %s" },
148 { ICMP_REDIRECT_TOSHOST, "redirect-tos %s to net %s" },
149 { 0, NULL }
150};
151
152/* rfc1191 */
153struct mtu_discovery {
154 short unused;
155 short nexthopmtu;
156};
157
158/* rfc1256 */
159struct ih_rdiscovery {
160 u_char ird_addrnum;
161 u_char ird_addrsiz;
162 u_short ird_lifetime;
163};
164
165struct id_rdiscovery {
166 u_int32_t ird_addr;
167 u_int32_t ird_pref;
168};
169
170void
171icmp_print(register const u_char *bp, u_int plen, register const u_char *bp2)
172{
173 register char *cp;
174 register const struct icmp *dp;
175 register const struct ip *ip;
176 register const char *str, *fmt;
177 register const struct ip *oip;
178 register const struct udphdr *ouh;
179 register u_int hlen, dport, mtu;
180 char buf[256];
180 char buf[MAXHOSTNAMELEN + 100];
181
182 dp = (struct icmp *)bp;
183 ip = (struct ip *)bp2;
184 str = buf;
185
186#if 0
187 (void)printf("%s > %s: ",
188 ipaddr_string(&ip->ip_src),
189 ipaddr_string(&ip->ip_dst));
190#endif
191
192 TCHECK(dp->icmp_code);
193 switch (dp->icmp_type) {
194
195 case ICMP_UNREACH:
196 TCHECK(dp->icmp_ip.ip_dst);
197 switch (dp->icmp_code) {
198
199 case ICMP_UNREACH_PROTOCOL:
200 TCHECK(dp->icmp_ip.ip_p);
201 (void)sprintf(buf, "%s protocol %d unreachable",
201 (void)snprintf(buf, sizeof(buf), "%s protocol %d unreachable",
202 ipaddr_string(&dp->icmp_ip.ip_dst),
203 dp->icmp_ip.ip_p);
204 break;
205
206 case ICMP_UNREACH_PORT:
207 TCHECK(dp->icmp_ip.ip_p);
208 oip = &dp->icmp_ip;
209 hlen = oip->ip_hl * 4;
210 ouh = (struct udphdr *)(((u_char *)oip) + hlen);
211 dport = ntohs(ouh->uh_dport);
212 switch (oip->ip_p) {
213
214 case IPPROTO_TCP:
215 (void)sprintf(buf,
215 (void)snprintf(buf, sizeof(buf),
216 "%s tcp port %s unreachable",
217 ipaddr_string(&oip->ip_dst),
218 tcpport_string(dport));
219 break;
220
221 case IPPROTO_UDP:
222 (void)sprintf(buf,
222 (void)snprintf(buf, sizeof(buf),
223 "%s udp port %s unreachable",
224 ipaddr_string(&oip->ip_dst),
225 udpport_string(dport));
226 break;
227
228 default:
229 (void)sprintf(buf,
229 (void)snprintf(buf, sizeof(buf),
230 "%s protocol %d port %d unreachable",
231 ipaddr_string(&oip->ip_dst),
232 oip->ip_p, dport);
233 break;
234 }
235 break;
236
237 case ICMP_UNREACH_NEEDFRAG:
238 {
239 register const struct mtu_discovery *mp;
240
241 mp = (struct mtu_discovery *)&dp->icmp_void;
242 mtu = EXTRACT_16BITS(&mp->nexthopmtu);
243 if (mtu)
244 (void)sprintf(buf,
244 (void)snprintf(buf, sizeof(buf),
245 "%s unreachable - need to frag (mtu %d)",
246 ipaddr_string(&dp->icmp_ip.ip_dst), mtu);
247 else
248 (void)sprintf(buf,
248 (void)snprintf(buf, sizeof(buf),
249 "%s unreachable - need to frag",
250 ipaddr_string(&dp->icmp_ip.ip_dst));
251 }
252 break;
253
254 default:
255 fmt = tok2str(unreach2str, "#%d %%s unreachable",
256 dp->icmp_code);
257 (void)sprintf(buf, fmt,
257 (void)snprintf(buf, sizeof(buf), fmt,
258 ipaddr_string(&dp->icmp_ip.ip_dst));
259 break;
260 }
261 break;
262
263 case ICMP_REDIRECT:
264 TCHECK(dp->icmp_ip.ip_dst);
265 fmt = tok2str(type2str, "redirect-#%d %%s to net %%s",
266 dp->icmp_code);
267 (void)sprintf(buf, fmt,
267 (void)snprintf(buf, sizeof(buf), fmt,
268 ipaddr_string(&dp->icmp_ip.ip_dst),
269 ipaddr_string(&dp->icmp_gwaddr));
270 break;
271
272 case ICMP_ROUTERADVERT:
273 {
274 register const struct ih_rdiscovery *ihp;
275 register const struct id_rdiscovery *idp;
276 u_int lifetime, num, size;
277
278 (void)strcpy(buf, "router advertisement");
279 cp = buf + strlen(buf);
280
281 ihp = (struct ih_rdiscovery *)&dp->icmp_void;
282 TCHECK(*ihp);
283 (void)strcpy(cp, " lifetime ");
284 cp = buf + strlen(buf);
285 lifetime = EXTRACT_16BITS(&ihp->ird_lifetime);
286 if (lifetime < 60)
287 (void)sprintf(cp, "%u", lifetime);
287 (void)snprintf(cp, sizeof(buf) - strlen(buf), "%u", lifetime);
288 else if (lifetime < 60 * 60)
289 (void)sprintf(cp, "%u:%02u",
289 (void)snprintf(cp, sizeof(buf) - strlen(buf), "%u:%02u",
290 lifetime / 60, lifetime % 60);
291 else
292 (void)sprintf(cp, "%u:%02u:%02u",
292 (void)snprintf(cp, sizeof(buf) - strlen(buf), "%u:%02u:%02u",
293 lifetime / 3600,
294 (lifetime % 3600) / 60,
295 lifetime % 60);
296 cp = buf + strlen(buf);
297
298 num = ihp->ird_addrnum;
299 (void)sprintf(cp, " %d:", num);
299 (void)snprintf(cp, sizeof(buf) - strlen(buf), " %d:", num);
300 cp = buf + strlen(buf);
301
302 size = ihp->ird_addrsiz;
303 if (size != 2) {
304 (void)sprintf(cp, " [size %d]", size);
304 (void)snprintf(cp, sizeof(buf) - strlen(buf), " [size %d]", size);
305 break;
306 }
307 idp = (struct id_rdiscovery *)&dp->icmp_data;
308 while (num-- > 0) {
309 TCHECK(*idp);
310 (void)sprintf(cp, " {%s %u}",
310 (void)snprintf(cp, sizeof(buf) - strlen(buf), " {%s %u}",
311 ipaddr_string(&idp->ird_addr),
312 EXTRACT_32BITS(&idp->ird_pref));
313 cp = buf + strlen(buf);
314 }
315 }
316 break;
317
318 case ICMP_TIMXCEED:
319 TCHECK(dp->icmp_ip.ip_dst);
320 switch (dp->icmp_code) {
321
322 case ICMP_TIMXCEED_INTRANS:
323 str = "time exceeded in-transit";
324 break;
325
326 case ICMP_TIMXCEED_REASS:
327 str = "ip reassembly time exceeded";
328 break;
329
330 default:
331 (void)sprintf(buf, "time exceeded-#%d", dp->icmp_code);
331 (void)snprintf(buf, sizeof(buf), "time exceeded-#%d", dp->icmp_code);
332 break;
333 }
334 break;
335
336 case ICMP_PARAMPROB:
337 if (dp->icmp_code)
338 (void)sprintf(buf, "parameter problem - code %d",
338 (void)snprintf(buf, sizeof(buf), "parameter problem - code %d",
339 dp->icmp_code);
340 else {
341 TCHECK(dp->icmp_pptr);
342 (void)sprintf(buf, "parameter problem - octet %d",
342 (void)snprintf(buf, sizeof(buf), "parameter problem - octet %d",
343 dp->icmp_pptr);
344 }
345 break;
346
347 case ICMP_MASKREPLY:
348 TCHECK(dp->icmp_mask);
349 (void)sprintf(buf, "address mask is 0x%08x",
349 (void)snprintf(buf, sizeof(buf), "address mask is 0x%08x",
350 (u_int32_t)ntohl(dp->icmp_mask));
351 break;
352
353 default:
354 str = tok2str(icmp2str, "type-#%d", dp->icmp_type);
355 break;
356 }
357 (void)printf("icmp: %s", str);
358 if (vflag) {
359 if (TTEST2(*bp, plen)) {
360 if (in_cksum((u_short*)dp, plen, 0))
361 printf(" (wrong icmp csum)");
362 }
363 }
364 if (vflag > 1 && !ICMP_INFOTYPE(dp->icmp_type)) {
365 bp += 8;
366 (void)printf(" for ");
367 ip = (struct ip *)bp;
368 snaplen = snapend - bp;
369 ip_print(bp, ntohs(ip->ip_len));
370 }
371 return;
372trunc:
373 fputs("[|icmp]", stdout);
374}