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