GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/tcpdump/print-ip.c Lines: 0 266 0.0 %
Date: 2017-11-13 Branches: 0 183 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: print-ip.c,v 1.47 2016/10/30 04:10:21 jsg Exp $	*/
2
3
/*
4
 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
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
#include <netinet/in.h>
28
#include <netinet/ip.h>
29
#include <netinet/ip_var.h>
30
#include <netinet/udp.h>
31
#include <netinet/udp_var.h>
32
#include <netinet/tcp.h>
33
34
#include <inttypes.h>
35
#include <stdio.h>
36
#include <stdlib.h>
37
#include <string.h>
38
#include <unistd.h>
39
40
#include "addrtoname.h"
41
#include "interface.h"
42
#include "extract.h"			/* must come after interface.h */
43
44
/* Compatibility */
45
#ifndef	IPPROTO_ND
46
#define	IPPROTO_ND	77
47
#endif
48
49
#ifndef IN_CLASSD
50
#define IN_CLASSD(i) (((int32_t)(i) & 0xf0000000) == 0xe0000000)
51
#endif
52
53
/* Definitions required for ECN
54
   for use if the OS running tcpdump does not have ECN */
55
#ifndef IPTOS_ECT
56
#define IPTOS_ECT	0x02	/* ECN Capable Transport in IP header*/
57
#endif
58
#ifndef IPTOS_CE
59
#define IPTOS_CE	0x01	/* ECN Cong. Experienced in IP header*/
60
#endif
61
62
/* (following from ipmulti/mrouted/prune.h) */
63
64
/*
65
 * The packet format for a traceroute request.
66
 */
67
struct tr_query {
68
	u_int  tr_src;			/* traceroute source */
69
	u_int  tr_dst;			/* traceroute destination */
70
	u_int  tr_raddr;		/* traceroute response address */
71
#if BYTE_ORDER == BIG_ENDIAN
72
	struct {
73
		u_int   ttl : 8;	/* traceroute response ttl */
74
		u_int   qid : 24;	/* traceroute query id */
75
	} q;
76
#else
77
	struct {
78
		u_int	qid : 24;	/* traceroute query id */
79
		u_int	ttl : 8;	/* traceroute response ttl */
80
	} q;
81
#endif
82
};
83
84
#define tr_rttl q.ttl
85
#define tr_qid  q.qid
86
87
/*
88
 * Traceroute response format.  A traceroute response has a tr_query at the
89
 * beginning, followed by one tr_resp for each hop taken.
90
 */
91
struct tr_resp {
92
	u_int tr_qarr;			/* query arrival time */
93
	u_int tr_inaddr;		/* incoming interface address */
94
	u_int tr_outaddr;		/* outgoing interface address */
95
	u_int tr_rmtaddr;		/* parent address in source tree */
96
	u_int tr_vifin;			/* input packet count on interface */
97
	u_int tr_vifout;		/* output packet count on interface */
98
	u_int tr_pktcnt;		/* total incoming packets for src-grp */
99
	u_char  tr_rproto;		/* routing proto deployed on router */
100
	u_char  tr_fttl;		/* ttl required to forward on outvif */
101
	u_char  tr_smask;		/* subnet mask for src addr */
102
	u_char  tr_rflags;		/* forwarding error codes */
103
};
104
105
/* defs within mtrace */
106
#define TR_QUERY 1
107
#define TR_RESP	2
108
109
/* fields for tr_rflags (forwarding error codes) */
110
#define TR_NO_ERR	0
111
#define TR_WRONG_IF	1
112
#define TR_PRUNED	2
113
#define TR_OPRUNED	3
114
#define TR_SCOPED	4
115
#define TR_NO_RTE	5
116
#define TR_NO_FWD	7
117
#define TR_NO_SPACE	0x81
118
#define TR_OLD_ROUTER	0x82
119
120
/* fields for tr_rproto (routing protocol) */
121
#define TR_PROTO_DVMRP	1
122
#define TR_PROTO_MOSPF	2
123
#define TR_PROTO_PIM	3
124
#define TR_PROTO_CBT	4
125
126
static void print_mtrace(const u_char *bp, u_int len)
127
{
128
	struct tr_query *tr = (struct tr_query *)(bp + 8);
129
130
	printf("mtrace %d: %s to %s reply-to %s", tr->tr_qid,
131
		ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst),
132
		ipaddr_string(&tr->tr_raddr));
133
	if (IN_CLASSD(ntohl(tr->tr_raddr)))
134
		printf(" with-ttl %d", tr->tr_rttl);
135
}
136
137
static void print_mresp(const u_char *bp, u_int len)
138
{
139
	struct tr_query *tr = (struct tr_query *)(bp + 8);
140
141
	printf("mresp %d: %s to %s reply-to %s", tr->tr_qid,
142
		ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst),
143
		ipaddr_string(&tr->tr_raddr));
144
	if (IN_CLASSD(ntohl(tr->tr_raddr)))
145
		printf(" with-ttl %d", tr->tr_rttl);
146
}
147
148
static void
149
igmp_print(const u_char *bp, u_int len, const u_char *bp2)
150
{
151
	const struct ip *ip;
152
153
	ip = (const struct ip *)bp2;
154
        (void)printf("%s > %s: ",
155
		ipaddr_string(&ip->ip_src),
156
		ipaddr_string(&ip->ip_dst));
157
158
	TCHECK2(bp[0], 8);
159
	switch (bp[0]) {
160
	case 0x11:
161
		(void)printf("igmp query");
162
		if (*(int *)&bp[4])
163
			(void)printf(" [gaddr %s]", ipaddr_string(&bp[4]));
164
		if (len != 8)
165
			(void)printf(" [len %d]", len);
166
		break;
167
	case 0x12:
168
		(void)printf("igmp report %s", ipaddr_string(&bp[4]));
169
		if (len != 8)
170
			(void)printf(" [len %d]", len);
171
		break;
172
	case 0x16:
173
		(void)printf("igmp nreport %s", ipaddr_string(&bp[4]));
174
		break;
175
	case 0x17:
176
		(void)printf("igmp leave %s", ipaddr_string(&bp[4]));
177
		break;
178
	case 0x13:
179
		(void)printf("igmp dvmrp");
180
		if (len < 8)
181
			(void)printf(" [len %d]", len);
182
		else
183
			dvmrp_print(bp, len);
184
		break;
185
	case 0x14:
186
		(void)printf("igmp pim");
187
		pim_print(bp, len);
188
  		break;
189
	case 0x1e:
190
		print_mresp(bp, len);
191
		break;
192
	case 0x1f:
193
		print_mtrace(bp, len);
194
		break;
195
	default:
196
		(void)printf("igmp-%d", bp[0] & 0xf);
197
		break;
198
	}
199
	if ((bp[0] >> 4) != 1)
200
		(void)printf(" [v%d]", bp[0] >> 4);
201
202
	TCHECK2(bp[0], len);
203
	if (vflag) {
204
		/* Check the IGMP checksum */
205
		u_int32_t sum = 0;
206
		int count;
207
		const u_short *sp = (u_short *)bp;
208
209
		for (count = len / 2; --count >= 0; )
210
			sum += *sp++;
211
		if (len & 1)
212
			sum += ntohs(*(u_char *) sp << 8);
213
		while (sum >> 16)
214
			sum = (sum & 0xffff) + (sum >> 16);
215
		sum = 0xffff & ~sum;
216
		if (sum != 0)
217
			printf(" bad igmp cksum %x!", EXTRACT_16BITS(&bp[2]));
218
	}
219
	return;
220
trunc:
221
	fputs("[|igmp]", stdout);
222
}
223
224
/*
225
 * print the recorded route in an IP RR, LSRR or SSRR option.
226
 */
227
static void
228
ip_printroute(const char *type, const u_char *cp, u_int length)
229
{
230
	u_int ptr = cp[2] - 1;
231
	u_int len;
232
233
	printf(" %s{", type);
234
	if ((length + 1) & 3)
235
		printf(" [bad length %d]", length);
236
	if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
237
		printf(" [bad ptr %d]", cp[2]);
238
239
	type = "";
240
	for (len = 3; len < length; len += 4) {
241
		if (ptr == len)
242
			type = "#";
243
		printf("%s%s", type, ipaddr_string(&cp[len]));
244
		type = " ";
245
	}
246
	printf("%s}", ptr == len? "#" : "");
247
}
248
249
/*
250
 * print IP options.
251
 */
252
static void
253
ip_optprint(const u_char *cp, u_int length)
254
{
255
	u_int len;
256
	int tt;
257
258
	for (; length > 0; cp += len, length -= len) {
259
		TCHECK(cp[1]);
260
		tt = *cp;
261
		len = (tt == IPOPT_NOP || tt == IPOPT_EOL) ? 1 : cp[1];
262
		if (len <= 0) {
263
			printf("[|ip op len %d]", len);
264
			return;
265
		}
266
		if (&cp[1] >= snapend || cp + len > snapend) {
267
			printf("[|ip]");
268
			return;
269
		}
270
		switch (tt) {
271
272
		case IPOPT_EOL:
273
			printf(" EOL");
274
			if (length > 1)
275
				printf("-%d", length - 1);
276
			return;
277
278
		case IPOPT_NOP:
279
			printf(" NOP");
280
			break;
281
282
		case IPOPT_TS:
283
			printf(" TS{%d}", len);
284
			break;
285
286
		case IPOPT_SECURITY:
287
			printf(" SECURITY{%d}", len);
288
			break;
289
290
		case IPOPT_RR:
291
			printf(" RR{%d}=", len);
292
			ip_printroute("RR", cp, len);
293
			break;
294
295
		case IPOPT_SSRR:
296
			ip_printroute("SSRR", cp, len);
297
			break;
298
299
		case IPOPT_LSRR:
300
			ip_printroute("LSRR", cp, len);
301
			break;
302
303
		default:
304
			printf(" IPOPT-%d{%d}", cp[0], len);
305
			break;
306
		}
307
	}
308
	return;
309
310
trunc:
311
	printf("[|ip]");
312
}
313
314
/*
315
 * compute an IP header checksum.
316
 * don't modifiy the packet.
317
 */
318
u_short
319
in_cksum(const u_short *addr, int len, int csum)
320
{
321
	int nleft = len;
322
	const u_short *w = addr;
323
	u_short answer;
324
	int sum = csum;
325
326
 	/*
327
	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
328
	 *  we add sequential 16 bit words to it, and at the end, fold
329
	 *  back all the carry bits from the top 16 bits into the lower
330
	 *  16 bits.
331
 	 */
332
	while (nleft > 1)  {
333
		sum += *w++;
334
		nleft -= 2;
335
	}
336
	if (nleft == 1)
337
		sum += htons(*(u_char *)w<<8);
338
339
	/*
340
	 * add back carry outs from top 16 bits to low 16 bits
341
	 */
342
	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
343
	sum += (sum >> 16);			/* add carry */
344
	answer = ~sum;				/* truncate to 16 bits */
345
	return (answer);
346
}
347
348
/*
349
 * print an IP datagram.
350
 */
351
void
352
ip_print(const u_char *bp, u_int length)
353
{
354
	const struct ip *ip;
355
	u_int hlen, len, off;
356
	const u_char *cp;
357
	const u_char *pktp = packetp;
358
	const u_char *send = snapend;
359
360
	TCHECK2(bp[0], 1);
361
	ip = (const struct ip *)bp;
362
363
	/*
364
	 * If the IP header is not aligned, copy into abuf.
365
	 * This will never happen with BPF.  It does happen with raw packet
366
	 * dumps from -r.
367
	 */
368
	if ((intptr_t)ip & (sizeof(u_int32_t)-1)) {
369
		static u_char *abuf = NULL;
370
		static int didwarn = 0;
371
		int clen = snapend - bp;
372
373
		if (clen > snaplen)
374
			clen = snaplen;
375
		if (abuf == NULL) {
376
			abuf = malloc(snaplen);
377
			if (abuf == NULL)
378
				error("ip_print: malloc");
379
		}
380
		memmove((char *)abuf, (char *)ip, min(length, clen));
381
		snapend = abuf + clen;
382
		packetp = abuf;
383
		ip = (struct ip *)abuf;
384
		/* We really want libpcap to give us aligned packets */
385
		if (!didwarn) {
386
			warning("compensating for unaligned libpcap packets");
387
			++didwarn;
388
		}
389
	}
390
391
	TCHECK(*ip);
392
	if (ip->ip_v != IPVERSION) {
393
		(void)printf("bad-ip-version %u", ip->ip_v);
394
		goto out;
395
	}
396
397
	len = ntohs(ip->ip_len);
398
	if (length < len) {
399
		(void)printf("truncated-ip - %d bytes missing!",
400
			len - length);
401
		len = length;
402
	}
403
404
	hlen = ip->ip_hl * 4;
405
	if (hlen < sizeof(struct ip) || hlen > len) {
406
		(void)printf("bad-hlen %d", hlen);
407
		goto out;
408
	}
409
410
	len -= hlen;
411
412
	/*
413
	 * If this is fragment zero, hand it to the next higher
414
	 * level protocol.
415
	 */
416
	off = ntohs(ip->ip_off);
417
	if ((off & 0x1fff) == 0) {
418
		cp = (const u_char *)ip + hlen;
419
		if (cp > snapend)
420
			goto trunc;
421
		switch (ip->ip_p) {
422
423
		case IPPROTO_TCP:
424
			tcp_print(cp, len, (const u_char *)ip);
425
			break;
426
427
		case IPPROTO_UDP:
428
			udp_print(cp, len, (const u_char *)ip);
429
			break;
430
431
		case IPPROTO_ICMP:
432
			icmp_print(cp, len, (const u_char *)ip);
433
			break;
434
435
#ifndef IPPROTO_IGRP
436
#define IPPROTO_IGRP 9
437
#endif
438
		case IPPROTO_IGRP:
439
			igrp_print(cp, len, (const u_char *)ip);
440
			break;
441
442
		case IPPROTO_ND:
443
			(void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
444
				ipaddr_string(&ip->ip_dst));
445
			(void)printf(" nd %d", len);
446
			break;
447
448
#ifndef IPPROTO_OSPF
449
#define IPPROTO_OSPF 89
450
#endif
451
		case IPPROTO_OSPF:
452
			ospf_print(cp, len, (const u_char *)ip);
453
			break;
454
455
#ifndef IPPROTO_IGMP
456
#define IPPROTO_IGMP 2
457
#endif
458
		case IPPROTO_IGMP:
459
			igmp_print(cp, len, (const u_char *)ip);
460
			break;
461
462
#ifndef IPPROTO_IPIP
463
#define IPPROTO_IPIP 4
464
#endif
465
		case IPPROTO_IPIP:
466
			/* ip-in-ip encapsulation */
467
			if (vflag)
468
				(void)printf("%s > %s: ",
469
					     ipaddr_string(&ip->ip_src),
470
					     ipaddr_string(&ip->ip_dst));
471
			ip_print(cp, len);
472
			if (! vflag) {
473
				printf(" (encap)");
474
				goto out;
475
			}
476
			break;
477
478
#ifdef INET6
479
#ifndef IPPROTO_IPV6
480
#define IPPROTO_IPV6
481
#endif
482
		case IPPROTO_IPV6:
483
			/* ip6-in-ip encapsulation */
484
			if (vflag)
485
				(void)printf("%s > %s: ",
486
					     ipaddr_string(&ip->ip_src),
487
					     ipaddr_string(&ip->ip_dst));
488
			ip6_print(cp, len);
489
			if (! vflag) {
490
 				printf(" (encap)");
491
				goto out;
492
 			}
493
 			break;
494
#endif /*INET6*/
495
496
#ifndef IPPROTO_GRE
497
#define IPPROTO_GRE 47
498
#endif
499
		case IPPROTO_GRE:
500
			if (vflag)
501
				(void)printf("gre %s > %s: ",
502
					     ipaddr_string(&ip->ip_src),
503
					     ipaddr_string(&ip->ip_dst));
504
			/* do it */
505
			gre_print(cp, len);
506
			if (! vflag) {
507
				printf(" (gre encap)");
508
				goto out;
509
  			}
510
  			break;
511
512
#ifndef IPPROTO_ESP
513
#define IPPROTO_ESP 50
514
#endif
515
		case IPPROTO_ESP:
516
			esp_print(cp, len, (const u_char *)ip);
517
			break;
518
519
#ifndef IPPROTO_AH
520
#define IPPROTO_AH 51
521
#endif
522
		case IPPROTO_AH:
523
			ah_print(cp, len, (const u_char *)ip);
524
			break;
525
526
#ifndef IPPROTO_MOBILE
527
#define IPPROTO_MOBILE 55
528
#endif
529
		case IPPROTO_MOBILE:
530
			if (vflag)
531
				(void)printf("mobile %s > %s: ",
532
					     ipaddr_string(&ip->ip_src),
533
					     ipaddr_string(&ip->ip_dst));
534
			mobile_print(cp, len);
535
			if (! vflag) {
536
				printf(" (mobile encap)");
537
				goto out;
538
			}
539
			break;
540
541
#ifndef IPPROTO_ETHERIP
542
#define IPPROTO_ETHERIP	97
543
#endif
544
		case IPPROTO_ETHERIP:
545
			etherip_print(cp, snapend - cp, len,
546
			    (const u_char *)ip);
547
			break;
548
549
#ifndef	IPPROTO_IPCOMP
550
#define	IPPROTO_IPCOMP	108
551
#endif
552
		case IPPROTO_IPCOMP:
553
			ipcomp_print(cp, len, (const u_char *)ip);
554
			break;
555
556
#ifndef IPPROTO_CARP
557
#define IPPROTO_CARP 112
558
#endif
559
		case IPPROTO_CARP:
560
			if (packettype == PT_VRRP) {
561
				if (vflag)
562
					(void)printf("vrrp %s > %s: ",
563
					     ipaddr_string(&ip->ip_src),
564
					     ipaddr_string(&ip->ip_dst));
565
				vrrp_print(cp, len, ip->ip_ttl);
566
			} else {
567
				if (vflag)
568
					(void)printf("carp %s > %s: ",
569
					     ipaddr_string(&ip->ip_src),
570
					     ipaddr_string(&ip->ip_dst));
571
				carp_print(cp, len, ip->ip_ttl);
572
			}
573
			break;
574
575
#ifndef IPPROTO_PFSYNC
576
#define IPPROTO_PFSYNC 240
577
#endif
578
		case IPPROTO_PFSYNC:
579
			pfsync_ip_print(cp,
580
			    (int)(snapend - (u_char *)ip) - hlen,
581
			    (const u_char *)ip);
582
			break;
583
584
		default:
585
			(void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
586
				ipaddr_string(&ip->ip_dst));
587
			(void)printf(" ip-proto-%d %d", ip->ip_p, len);
588
			break;
589
		}
590
	}
591
	/*
592
	 * for fragmented datagrams, print id:size@offset.  On all
593
	 * but the last stick a "+".  For unfragmented datagrams, note
594
	 * the don't fragment flag.
595
	 */
596
	if (off & 0x3fff) {
597
		/*
598
		 * if this isn't the first frag, we're missing the
599
		 * next level protocol header.  print the ip addr.
600
		 */
601
		if (off & 0x1fff)
602
			(void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
603
				      ipaddr_string(&ip->ip_dst));
604
		(void)printf(" (frag %d:%d@%d%s)", ntohs(ip->ip_id), len,
605
			(off & 0x1fff) * 8,
606
			(off & IP_MF)? "+" : "");
607
	}
608
	if (off & IP_DF)
609
		(void)printf(" (DF)");
610
611
	if (ip->ip_tos) {
612
		(void)printf(" [tos 0x%x", (int)ip->ip_tos);
613
		if (ip->ip_tos & (IPTOS_CE|IPTOS_ECT)) {
614
			(void)printf(" (");
615
			if (ip->ip_tos & IPTOS_ECT) {
616
				/* ECN-capable transport */
617
				putchar('E');
618
			}
619
			if (ip->ip_tos & IPTOS_CE) {
620
				/* _C_ongestion experienced (ECN) */
621
				putchar('C');
622
			}
623
			(void)printf(")");
624
  		}
625
		(void)printf("]");
626
	}
627
628
	if (ip->ip_ttl <= 1)
629
		(void)printf(" [ttl %d]", (int)ip->ip_ttl);
630
631
	if (vflag) {
632
		char *sep = "";
633
634
		printf(" (");
635
		if (ip->ip_ttl > 1) {
636
			(void)printf("%sttl %d", sep, (int)ip->ip_ttl);
637
			sep = ", ";
638
		}
639
		if ((off & 0x3fff) == 0) {
640
			(void)printf("%sid %d", sep, (int)ntohs(ip->ip_id));
641
			sep = ", ";
642
		}
643
		(void)printf("%slen %u", sep, ntohs(ip->ip_len));
644
		sep = ", ";
645
		if ((u_char *)ip + hlen <= snapend) {
646
			u_int16_t sum, ip_sum;
647
			sum = in_cksum((const u_short *)ip, hlen, 0);
648
			if (sum != 0) {
649
				ip_sum = EXTRACT_16BITS(&ip->ip_sum);
650
				(void)printf("%sbad ip cksum %x! -> %x", sep, ip_sum,
651
					     in_cksum_shouldbe(ip_sum, sum));
652
				sep = ", ";
653
			}
654
		}
655
		if (hlen > sizeof(struct ip)) {
656
			hlen -= sizeof(struct ip);
657
			(void)printf("%soptlen=%d", sep, hlen);
658
			ip_optprint((u_char *)(ip + 1), hlen);
659
		}
660
		printf(")");
661
	}
662
out:
663
	packetp = pktp;
664
	snapend = send;
665
	return;
666
667
trunc:
668
	printf("[|ip]");
669
}