xref: /openbsd-src/usr.sbin/tcpdump/print-cdp.c (revision 98dbb244f271769c9a461b8976ee0261b82263f2)
1*98dbb244Smartijn /*	$OpenBSD: print-cdp.c,v 1.8 2019/09/11 15:20:30 martijn Exp $	*/
2f3cbb22dSjakob 
3f3cbb22dSjakob /*
4f3cbb22dSjakob  * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997
5f3cbb22dSjakob  *	The Regents of the University of California.  All rights reserved.
6f3cbb22dSjakob  *
7f3cbb22dSjakob  * Redistribution and use in source and binary forms, with or without
8f3cbb22dSjakob  * modification, are permitted provided that: (1) source code distributions
9f3cbb22dSjakob  * retain the above copyright notice and this paragraph in its entirety, (2)
10f3cbb22dSjakob  * distributions including binary code include the above copyright notice and
11f3cbb22dSjakob  * this paragraph in its entirety in the documentation or other materials
12f3cbb22dSjakob  * provided with the distribution, and (3) all advertising materials mentioning
13f3cbb22dSjakob  * features or use of this software display the following acknowledgement:
14f3cbb22dSjakob  * ``This product includes software developed by the University of California,
15f3cbb22dSjakob  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16f3cbb22dSjakob  * the University nor the names of its contributors may be used to endorse
17f3cbb22dSjakob  * or promote products derived from this software without specific prior
18f3cbb22dSjakob  * written permission.
19f3cbb22dSjakob  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20f3cbb22dSjakob  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21f3cbb22dSjakob  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22f3cbb22dSjakob  *
23f3cbb22dSjakob  * Code by Gert Doering, SpaceNet GmbH, gert@space.net
24f3cbb22dSjakob  *
25f3cbb22dSjakob  * Reference documentation:
26f3cbb22dSjakob  *    http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm
27f3cbb22dSjakob  */
28f3cbb22dSjakob 
29f3cbb22dSjakob #include <sys/time.h>
30f3cbb22dSjakob 
31f3cbb22dSjakob #include <netinet/in.h>
32f3cbb22dSjakob 
33f3cbb22dSjakob #include <ctype.h>
34f3cbb22dSjakob #include <netdb.h>
35f3cbb22dSjakob #include <stdio.h>
36f3cbb22dSjakob #include <string.h>
37f3cbb22dSjakob 
38f3cbb22dSjakob #include "interface.h"
39f3cbb22dSjakob #include "addrtoname.h"
40f3cbb22dSjakob #include "extract.h"			/* must come after interface.h */
41f3cbb22dSjakob 
42a91cddbcScanacar int cdp_print_addr(const u_char * p, int l);
4367038650Smickey void cdp_print_prefixes(const u_char * p, int l);
44f3cbb22dSjakob 
45f3cbb22dSjakob /*
46f3cbb22dSjakob  * Returns non-zero IFF it succeeds in printing the header
47f3cbb22dSjakob  */
48f3cbb22dSjakob void
cdp_print(const u_char * p,u_int length,u_int caplen,int i)498e229e7cSdlg cdp_print(const u_char *p, u_int length, u_int caplen, int i)
50f3cbb22dSjakob {
51f3cbb22dSjakob 	int type, len;
52f3cbb22dSjakob 
53f3cbb22dSjakob 	/* Cisco Discovery Protocol */
54f3cbb22dSjakob 
558e229e7cSdlg 	if (caplen < i + 4) {
5667038650Smickey 		printf("[|cdp]");
57f3cbb22dSjakob 		return;
58f3cbb22dSjakob 	}
59f3cbb22dSjakob 
60f3cbb22dSjakob 	printf("CDP v%d, ttl=%ds", p[i], p[i+1]);
61f3cbb22dSjakob 	i+=4;		/* skip version, TTL and chksum */
62f3cbb22dSjakob 
63f3cbb22dSjakob 	while (i < length) {
64f3cbb22dSjakob 		if (i + 4 > caplen) {
65a91cddbcScanacar 			printf("[|cdp]");
66f3cbb22dSjakob 			return;
67f3cbb22dSjakob 		}
6867038650Smickey 
69f3cbb22dSjakob 		type = (p[i]<<8) + p[i+1];
70f3cbb22dSjakob 		len  = (p[i+2]<<8) + p[i+3];
71f3cbb22dSjakob 
72f3cbb22dSjakob 		if (vflag)
7367038650Smickey 			printf(" %02x/%02x", type, len);
74f3cbb22dSjakob 
75a91cddbcScanacar 		if (len < 4)
76a91cddbcScanacar 			goto error;
77a91cddbcScanacar 
78f3cbb22dSjakob 		if (i+len > caplen) {
79a91cddbcScanacar 			printf("[|cdp]");
80f3cbb22dSjakob 			return;
81f3cbb22dSjakob 		}
82f3cbb22dSjakob 
83*98dbb244Smartijn 		/* http://www.cisco.com/c/en/us/support/docs/switches/catalyst-4500-series-switches/13414-103.html#cdp */
8467038650Smickey 		switch(type) {
85f3cbb22dSjakob 		case 0x01:
86f3cbb22dSjakob 			printf(" DevID '%.*s'", len - 4, p + i + 4);
87f3cbb22dSjakob 			break;
88f3cbb22dSjakob 		case 0x02:
89f3cbb22dSjakob 			printf(" Addr");
90a91cddbcScanacar 			if (cdp_print_addr(p + i + 4, len - 4))
91a91cddbcScanacar 				goto error;
92f3cbb22dSjakob 			break;
93f3cbb22dSjakob 		case 0x03:
94f3cbb22dSjakob 			printf(" PortID '%.*s'", len - 4, p + i + 4);
95f3cbb22dSjakob 			break;
96f3cbb22dSjakob 		case 0x04:
97a91cddbcScanacar 			if (len < 8)
98a91cddbcScanacar 				goto error;
99f3cbb22dSjakob 			printf(" CAP 0x%02x", (unsigned) p[i+7]);
100f3cbb22dSjakob 			break;
101f3cbb22dSjakob 		case 0x05:
102f3cbb22dSjakob 			if (vflag)
10367038650Smickey 				printf(" Version %.*s", len-4, p+i+4 );
104f3cbb22dSjakob 			else
10567038650Smickey 				printf(" Version (suppressed)" );
106f3cbb22dSjakob 			break;
107f3cbb22dSjakob 		case 0x06:
10867038650Smickey 			printf(" Platform '%.*s'", len-4, p+i+4 );
109f3cbb22dSjakob 			break;
110f3cbb22dSjakob 		case 0x07:
111f3cbb22dSjakob 			cdp_print_prefixes(p+i+4, len-4);
112f3cbb22dSjakob 			break;
113*98dbb244Smartijn 		case 0x09:
11467038650Smickey 			printf(" VTP-Management-Domain '%.*s'", len-4, p+i+4 );
115f3cbb22dSjakob 			break;
116*98dbb244Smartijn 		case 0x0a:
117a91cddbcScanacar 			if (len < 6)
118a91cddbcScanacar 				goto error;
119*98dbb244Smartijn 			printf(" Native-VLAN-ID %d", (p[i+4]<<8) + p[i+4+1]);
120f3cbb22dSjakob 			break;
121*98dbb244Smartijn 		case 0x0b:
122a91cddbcScanacar 			if (len < 5)
123a91cddbcScanacar 				goto error;
12467038650Smickey 			printf(" Duplex %s", p[i+4] ? "full": "half" );
125f3cbb22dSjakob 			break;
126f3cbb22dSjakob 		default:
12767038650Smickey 			printf(" unknown-type %02x len %d", type, len );
128f3cbb22dSjakob 		}
129f3cbb22dSjakob 
130f3cbb22dSjakob 		/* avoid infinite loop */
131f3cbb22dSjakob 		if (len == 0)
132f3cbb22dSjakob 			break;
133f3cbb22dSjakob 		i += len;
134f3cbb22dSjakob 	}
135a91cddbcScanacar error:
136a91cddbcScanacar 	printf("[!cdp]");
137f3cbb22dSjakob }
138f3cbb22dSjakob 
139a91cddbcScanacar #define CDP_CHECK_ACCESS(p, s) if ((endp - (p)) < (s)) return 1
140a91cddbcScanacar 
141a91cddbcScanacar int
cdp_print_addr(const u_char * p,int l)142f3cbb22dSjakob cdp_print_addr(const u_char * p, int l)
143f3cbb22dSjakob {
144a91cddbcScanacar 	int pl, pt, al, num;
145f3cbb22dSjakob 	const u_char * endp = p+l;
146f3cbb22dSjakob 
147a91cddbcScanacar 	CDP_CHECK_ACCESS(p, 4);
148f3cbb22dSjakob 	num = (p[0] << 24) + (p[1]<<16) + (p[2]<<8)+ p[3];
149f3cbb22dSjakob 	p+=4;
150f3cbb22dSjakob 
151f3cbb22dSjakob 	printf(" (%d): ", num);
152f3cbb22dSjakob 
153f3cbb22dSjakob 	while(p < endp && num >= 0) {
154a91cddbcScanacar 		CDP_CHECK_ACCESS(p, 2);
155a91cddbcScanacar 		pt=*p;
156f3cbb22dSjakob 		pl=*(p+1);
157f3cbb22dSjakob 		p+=2;
158f3cbb22dSjakob 
159a91cddbcScanacar 		CDP_CHECK_ACCESS(p, 3);
160f3cbb22dSjakob 		/* special case: IPv4, protocol type=0xcc, addr. length=4 */
16167038650Smickey 		if (pl == 1 && *p == 0xcc && p[1] == 0 && p[2] == 4) {
162f3cbb22dSjakob 			p+=3;
163f3cbb22dSjakob 
164a91cddbcScanacar 			CDP_CHECK_ACCESS(p, 4);
165f3cbb22dSjakob 			printf("IPv4 %d.%d.%d.%d ", p[0], p[1], p[2], p[3]);
166f3cbb22dSjakob 			p+=4;
167f3cbb22dSjakob 		} else {	/* generic case: just print raw data */
168a91cddbcScanacar 			printf("pt=0x%02x, pl=%d, pb=", pt, pl);
169a91cddbcScanacar 
170a91cddbcScanacar 			CDP_CHECK_ACCESS(p, pl);
171f3cbb22dSjakob 			while(pl-- > 0)
172f3cbb22dSjakob 				printf(" %02x", *p++);
173a91cddbcScanacar 
174a91cddbcScanacar 			CDP_CHECK_ACCESS(p, 2);
175f3cbb22dSjakob 			al=(*p << 8) + *(p+1);
176f3cbb22dSjakob 			printf(", al=%d, a=", al);
177f3cbb22dSjakob 			p+=2;
178a91cddbcScanacar 
179a91cddbcScanacar 			CDP_CHECK_ACCESS(p, al);
180f3cbb22dSjakob 			while(al-- > 0)
181f3cbb22dSjakob 				printf(" %02x", *p++);
182f3cbb22dSjakob 		}
183f3cbb22dSjakob 		printf("  ");
184f3cbb22dSjakob 		num--;
185f3cbb22dSjakob 	}
186a91cddbcScanacar 
187a91cddbcScanacar 	return 0;
188f3cbb22dSjakob }
189f3cbb22dSjakob 
190f3cbb22dSjakob 
19167038650Smickey void
cdp_print_prefixes(const u_char * p,int l)192f3cbb22dSjakob cdp_print_prefixes(const u_char * p, int l)
193f3cbb22dSjakob {
194f3cbb22dSjakob 	printf(" IPv4 Prefixes (%d):", l/5);
195f3cbb22dSjakob 
196f3cbb22dSjakob 	while (l > 0) {
197a91cddbcScanacar 		if (l >= 5)
198f3cbb22dSjakob 			printf(" %d.%d.%d.%d/%d", p[0], p[1], p[2], p[3], p[4] );
199f3cbb22dSjakob 		l-=5; p+=5;
200f3cbb22dSjakob 	}
201f3cbb22dSjakob }
202