]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-cdp.c
This commit was generated by cvs2svn to compensate for changes in r105081,
[FreeBSD/FreeBSD.git] / contrib / tcpdump / print-cdp.c
1 /*
2  * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997
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  * Code by Gert Doering, SpaceNet GmbH, gert@space.net
22  *
23  * Reference documentation:
24  *    http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm
25  */
26
27 #ifndef lint
28 static const char rcsid[] =
29     "@(#) $Header: /tcpdump/master/tcpdump/print-cdp.c,v 1.11 2001/09/17 21:57:56 fenner Exp $";
30 #endif
31
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include <sys/param.h>
37 #include <sys/time.h>
38
39 #include <netinet/in.h>
40
41 #include <ctype.h>
42 #include <netdb.h>
43 #include <stdio.h>
44 #include <string.h>
45
46 #include "interface.h"
47 #include "addrtoname.h"
48 #include "extract.h"                    /* must come after interface.h */
49
50 static int cdp_print_addr(const u_char *, int);
51 static int cdp_print_prefixes(const u_char *, int);
52
53 void
54 cdp_print(const u_char *p, u_int length, u_int caplen,
55           const u_char *esrc, const u_char *edst)
56 {
57         u_int i;
58         int type, len;
59
60         /* Cisco Discovery Protocol */
61
62         if (caplen < 4) {
63                 (void)printf("[|cdp]");
64                 return;
65         }
66
67         i = 0;          /* CDP data starts at offset 0 */
68         printf("CDP v%u, ttl=%us", p[i], p[i + 1]);
69         i += 4;         /* skip version, TTL and chksum */
70
71         while (i < length) {
72                 if (i + 4 > caplen)
73                         goto trunc;
74                 type = (p[i] <<  8) + p[i + 1];
75                 len  = (p[i + 2] << 8) + p[i + 3];
76
77                 if (vflag > 1)
78                         printf("\n\t");
79
80                 if (vflag)
81                         printf(" %02x/%02x", type, len);
82
83                 if (i + len > caplen)
84                         goto trunc;
85
86                 switch (type) {
87                 case 0x00:
88                         printf(" Goodbye");
89                         break;
90                 case 0x01:
91                         printf(" DevID '%.*s'", len - 4, p + i + 4);
92                         break;
93                 case 0x02:
94                         printf(" Addr");
95                         if (cdp_print_addr(p + i + 4, len - 4) < 0)
96                                 goto trunc;
97                         break;
98                 case 0x03:
99                         printf(" PortID '%.*s'", len - 4, p + i + 4);
100                         break;
101                 case 0x04:
102                         printf(" CAP 0x%02x", (unsigned) p[i + 7]);
103                         break;
104                 case 0x05:
105                         if (vflag > 1)
106                                 printf(" Version:\n%.*s", len - 4, p + i + 4);
107                         else
108                                 printf(" Version: (suppressed)");
109                         break;
110                 case 0x06:
111                         printf(" Platform: '%.*s'", len - 4, p + i + 4);
112                         break;
113                 case 0x07:
114                         if (cdp_print_prefixes(p + i + 4, len - 4) < 0)
115                                 goto trunc;
116                         break;
117                 case 0x09:              /* guess - not documented */
118                         printf(" VTP Management Domain: '%.*s'", len - 4,
119                             p + i + 4);
120                         break;
121                 case 0x0a:              /* guess - not documented */
122                         printf(" Native VLAN ID: %d",
123                             (p[i + 4] << 8) + p[i + 4 + 1] - 1);
124                         break;
125                 case 0x0b:              /* guess - not documented */
126                         printf(" Duplex: %s", p[i + 4] ? "full": "half");
127                         break;
128                 default:
129                         printf(" unknown field type %02x, len %d", type, len);
130                         break;
131                 }
132
133                 /* avoid infinite loop */
134                 if (len == 0)
135                         break;
136                 i += len;
137         }
138
139         return;
140
141 trunc:
142         printf("[|cdp]");
143 }
144
145 /*
146  * Protocol type values.
147  *
148  * PT_NLPID means that the protocol type field contains an OSI NLPID.
149  *
150  * PT_IEEE_802_2 means that the protocol type field contains an IEEE 802.2
151  * LLC header that specifies that the payload is for that protocol.
152  */
153 #define PT_NLPID                1       /* OSI NLPID */
154 #define PT_IEEE_802_2           2       /* IEEE 802.2 LLC header */
155
156 static int
157 cdp_print_addr(const u_char * p, int l)
158 {
159         int pt, pl, al, num;
160         const u_char *endp = p + l;
161 #ifdef INET6
162         static u_char prot_ipv6[] = {
163                 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x86, 0xdd
164         };
165 #endif
166
167         num = EXTRACT_32BITS(p);
168         p += 4;
169
170         printf(" (%d): ", num);
171
172         while (p < endp && num >= 0) {
173                 if (p + 2 > endp)
174                         goto trunc;
175                 pt = p[0];              /* type of "protocol" field */
176                 pl = p[1];              /* length of "protocol" field */
177                 p += 2;
178
179                 if (p + pl + 2 > endp)
180                         goto trunc;
181                 al = EXTRACT_16BITS(&p[pl]);    /* address length */
182
183                 if (pt == PT_NLPID && pl == 1 && *p == 0xcc && al == 4) {
184                         /*
185                          * IPv4: protocol type = NLPID, protocol length = 1
186                          * (1-byte NLPID), protocol = 0xcc (NLPID for IPv4),
187                          * address length = 4
188                          */
189                         p += 3;
190
191                         if (p + 4 > endp)
192                                 goto trunc;
193                         printf("IPv4 %u.%u.%u.%u", p[0], p[1], p[2], p[3]);
194                         p += 4;
195                 }
196 #ifdef INET6
197                 else if (pt == PT_IEEE_802_2 && pl == 8 &&
198                     memcmp(p, prot_ipv6, 8) == 0 && al == 16) {
199                         /*
200                          * IPv6: protocol type = IEEE 802.2 header,
201                          * protocol length = 8 (size of LLC+SNAP header),
202                          * protocol = LLC+SNAP header with the IPv6
203                          * Ethertype, address length = 16
204                          */
205                         p += 10; 
206                         if (p + al > endp)
207                                 goto trunc;
208
209                         printf("IPv6 %s", ip6addr_string(p));
210                         p += al;
211                 }
212 #endif
213                 else {
214                         /*
215                          * Generic case: just print raw data
216                          */
217                         if (p + pl > endp)
218                                 goto trunc;
219                         printf("pt=0x%02x, pl=%d, pb=", *(p - 2), pl);
220                         while (pl-- > 0)
221                                 printf(" %02x", *p++);
222                         if (p + 2 > endp)
223                                 goto trunc;
224                         al = (*p << 8) + *(p + 1);
225                         printf(", al=%d, a=", al);
226                         p += 2;
227                         if (p + al > endp)
228                                 goto trunc;
229                         while (al-- > 0)
230                                 printf(" %02x", *p++);
231                 }
232                 num--;
233                 if (num)
234                         printf(" ");
235         }
236
237         return 0;
238
239 trunc:
240         return -1;
241 }
242
243
244 static int
245 cdp_print_prefixes(const u_char * p, int l)
246 {
247         if (l % 5)
248                 goto trunc;
249
250         printf(" IPv4 Prefixes (%d):", l / 5);
251
252         while (l > 0) {
253                 printf(" %u.%u.%u.%u/%u", p[0], p[1], p[2], p[3], p[4]);
254                 l -= 5;
255                 p += 5;
256         }
257
258         return 0;
259
260 trunc:
261         return -1;
262 }