1 /* $OpenBSD: print-cdp.c,v 1.8 2019/09/11 15:20:30 martijn 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, int i) 50 { 51 int type, len; 52 53 /* Cisco Discovery Protocol */ 54 55 if (caplen < i + 4) { 56 printf("[|cdp]"); 57 return; 58 } 59 60 printf("CDP v%d, ttl=%ds", p[i], p[i+1]); 61 i+=4; /* skip version, TTL and chksum */ 62 63 while (i < length) { 64 if (i + 4 > caplen) { 65 printf("[|cdp]"); 66 return; 67 } 68 69 type = (p[i]<<8) + p[i+1]; 70 len = (p[i+2]<<8) + p[i+3]; 71 72 if (vflag) 73 printf(" %02x/%02x", type, len); 74 75 if (len < 4) 76 goto error; 77 78 if (i+len > caplen) { 79 printf("[|cdp]"); 80 return; 81 } 82 83 /* http://www.cisco.com/c/en/us/support/docs/switches/catalyst-4500-series-switches/13414-103.html#cdp */ 84 switch(type) { 85 case 0x01: 86 printf(" DevID '%.*s'", len - 4, p + i + 4); 87 break; 88 case 0x02: 89 printf(" Addr"); 90 if (cdp_print_addr(p + i + 4, len - 4)) 91 goto error; 92 break; 93 case 0x03: 94 printf(" PortID '%.*s'", len - 4, p + i + 4); 95 break; 96 case 0x04: 97 if (len < 8) 98 goto error; 99 printf(" CAP 0x%02x", (unsigned) p[i+7]); 100 break; 101 case 0x05: 102 if (vflag) 103 printf(" Version %.*s", len-4, p+i+4 ); 104 else 105 printf(" Version (suppressed)" ); 106 break; 107 case 0x06: 108 printf(" Platform '%.*s'", len-4, p+i+4 ); 109 break; 110 case 0x07: 111 cdp_print_prefixes(p+i+4, len-4); 112 break; 113 case 0x09: 114 printf(" VTP-Management-Domain '%.*s'", len-4, p+i+4 ); 115 break; 116 case 0x0a: 117 if (len < 6) 118 goto error; 119 printf(" Native-VLAN-ID %d", (p[i+4]<<8) + p[i+4+1]); 120 break; 121 case 0x0b: 122 if (len < 5) 123 goto error; 124 printf(" Duplex %s", p[i+4] ? "full": "half" ); 125 break; 126 default: 127 printf(" unknown-type %02x len %d", type, len ); 128 } 129 130 /* avoid infinite loop */ 131 if (len == 0) 132 break; 133 i += len; 134 } 135 error: 136 printf("[!cdp]"); 137 } 138 139 #define CDP_CHECK_ACCESS(p, s) if ((endp - (p)) < (s)) return 1 140 141 int 142 cdp_print_addr(const u_char * p, int l) 143 { 144 int pl, pt, al, num; 145 const u_char * endp = p+l; 146 147 CDP_CHECK_ACCESS(p, 4); 148 num = (p[0] << 24) + (p[1]<<16) + (p[2]<<8)+ p[3]; 149 p+=4; 150 151 printf(" (%d): ", num); 152 153 while(p < endp && num >= 0) { 154 CDP_CHECK_ACCESS(p, 2); 155 pt=*p; 156 pl=*(p+1); 157 p+=2; 158 159 CDP_CHECK_ACCESS(p, 3); 160 /* special case: IPv4, protocol type=0xcc, addr. length=4 */ 161 if (pl == 1 && *p == 0xcc && p[1] == 0 && p[2] == 4) { 162 p+=3; 163 164 CDP_CHECK_ACCESS(p, 4); 165 printf("IPv4 %d.%d.%d.%d ", p[0], p[1], p[2], p[3]); 166 p+=4; 167 } else { /* generic case: just print raw data */ 168 printf("pt=0x%02x, pl=%d, pb=", pt, pl); 169 170 CDP_CHECK_ACCESS(p, pl); 171 while(pl-- > 0) 172 printf(" %02x", *p++); 173 174 CDP_CHECK_ACCESS(p, 2); 175 al=(*p << 8) + *(p+1); 176 printf(", al=%d, a=", al); 177 p+=2; 178 179 CDP_CHECK_ACCESS(p, al); 180 while(al-- > 0) 181 printf(" %02x", *p++); 182 } 183 printf(" "); 184 num--; 185 } 186 187 return 0; 188 } 189 190 191 void 192 cdp_print_prefixes(const u_char * p, int l) 193 { 194 printf(" IPv4 Prefixes (%d):", l/5); 195 196 while (l > 0) { 197 if (l >= 5) 198 printf(" %d.%d.%d.%d/%d", p[0], p[1], p[2], p[3], p[4] ); 199 l-=5; p+=5; 200 } 201 } 202