GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/tcpdump/print-icmp.c Lines: 0 128 0.0 %
Date: 2017-11-07 Branches: 0 122 0.0 %

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