1 /* $OpenBSD: print-cdp.c,v 1.6 2016/03/29 04:07:50 canacar Exp $ */ 2 3 /* 4 * Copyright (c) 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 * Code by Gert Doering, SpaceNet GmbH, gert@space.net 24 * 25 * Reference documentation: 26 * http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm 27 */ 28 29 #include <sys/time.h> 30 31 #include <netinet/in.h> 32 33 #include <ctype.h> 34 #include <netdb.h> 35 #include <stdio.h> 36 #include <string.h> 37 38 #include "interface.h" 39 #include "addrtoname.h" 40 #include "extract.h" /* must come after interface.h */ 41 42 int cdp_print_addr(const u_char * p, int l); 43 void cdp_print_prefixes(const u_char * p, int l); 44 45 /* 46 * Returns non-zero IFF it succeeds in printing the header 47 */ 48 void 49 cdp_print(const u_char *p, u_int length, u_int caplen, 50 const u_char *esrc, const u_char *edst) 51 { 52 int i; 53 int type, len; 54 55 /* Cisco Discovery Protocol */ 56 57 if (caplen < 12) { 58 printf("[|cdp]"); 59 return; 60 } 61 62 i=8; /* CDP data starts at offset 8 */ 63 printf("CDP v%d, ttl=%ds", p[i], p[i+1]); 64 i+=4; /* skip version, TTL and chksum */ 65 66 while (i < length) { 67 if (i + 4 > caplen) { 68 printf("[|cdp]"); 69 return; 70 } 71 72 type = (p[i]<<8) + p[i+1]; 73 len = (p[i+2]<<8) + p[i+3]; 74 75 if (vflag) 76 printf(" %02x/%02x", type, len); 77 78 if (len < 4) 79 goto error; 80 81 if (i+len > caplen) { 82 printf("[|cdp]"); 83 return; 84 } 85 86 switch(type) { 87 case 0x01: 88 printf(" DevID '%.*s'", len - 4, p + i + 4); 89 break; 90 case 0x02: 91 printf(" Addr"); 92 if (cdp_print_addr(p + i + 4, len - 4)) 93 goto error; 94 break; 95 case 0x03: 96 printf(" PortID '%.*s'", len - 4, p + i + 4); 97 break; 98 case 0x04: 99 if (len < 8) 100 goto error; 101 printf(" CAP 0x%02x", (unsigned) p[i+7]); 102 break; 103 case 0x05: 104 if (vflag) 105 printf(" Version %.*s", len-4, p+i+4 ); 106 else 107 printf(" Version (suppressed)" ); 108 break; 109 case 0x06: 110 printf(" Platform '%.*s'", len-4, p+i+4 ); 111 break; 112 case 0x07: 113 cdp_print_prefixes(p+i+4, len-4); 114 break; 115 case 0x09: /* guess - not documented */ 116 printf(" VTP-Management-Domain '%.*s'", len-4, p+i+4 ); 117 break; 118 case 0x0a: /* guess - not documented */ 119 if (len < 6) 120 goto error; 121 printf(" Native-VLAN-ID %d", (p[i+4]<<8) + p[i+4+1] - 1 ); 122 break; 123 case 0x0b: /* guess - not documented */ 124 if (len < 5) 125 goto error; 126 printf(" Duplex %s", p[i+4] ? "full": "half" ); 127 break; 128 default: 129 printf(" unknown-type %02x len %d", type, len ); 130 } 131 132 /* avoid infinite loop */ 133 if (len == 0) 134 break; 135 i += len; 136 } 137 error: 138 printf("[!cdp]"); 139 } 140 141 #define CDP_CHECK_ACCESS(p, s) if ((endp - (p)) < (s)) return 1 142 143 int 144 cdp_print_addr(const u_char * p, int l) 145 { 146 int pl, pt, al, num; 147 const u_char * endp = p+l; 148 149 CDP_CHECK_ACCESS(p, 4); 150 num = (p[0] << 24) + (p[1]<<16) + (p[2]<<8)+ p[3]; 151 p+=4; 152 153 printf(" (%d): ", num); 154 155 while(p < endp && num >= 0) { 156 CDP_CHECK_ACCESS(p, 2); 157 pt=*p; 158 pl=*(p+1); 159 p+=2; 160 161 CDP_CHECK_ACCESS(p, 3); 162 /* special case: IPv4, protocol type=0xcc, addr. length=4 */ 163 if (pl == 1 && *p == 0xcc && p[1] == 0 && p[2] == 4) { 164 p+=3; 165 166 CDP_CHECK_ACCESS(p, 4); 167 printf("IPv4 %d.%d.%d.%d ", p[0], p[1], p[2], p[3]); 168 p+=4; 169 } else { /* generic case: just print raw data */ 170 printf("pt=0x%02x, pl=%d, pb=", pt, pl); 171 172 CDP_CHECK_ACCESS(p, pl); 173 while(pl-- > 0) 174 printf(" %02x", *p++); 175 176 CDP_CHECK_ACCESS(p, 2); 177 al=(*p << 8) + *(p+1); 178 printf(", al=%d, a=", al); 179 p+=2; 180 181 CDP_CHECK_ACCESS(p, al); 182 while(al-- > 0) 183 printf(" %02x", *p++); 184 } 185 printf(" "); 186 num--; 187 } 188 189 return 0; 190 } 191 192 193 void 194 cdp_print_prefixes(const u_char * p, int l) 195 { 196 printf(" IPv4 Prefixes (%d):", l/5); 197 198 while (l > 0) { 199 if (l >= 5) 200 printf(" %d.%d.%d.%d/%d", p[0], p[1], p[2], p[3], p[4] ); 201 l-=5; p+=5; 202 } 203 } 204