1 /* $OpenBSD: print-vqp.c,v 1.7 2006/08/24 05:11:43 stevesk Exp $ */ 2 3 /* 4 * Copyright (c) 2006 Kevin Steves <stevesk@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* 20 * VLAN Query Protocol (VQP) 21 * 22 * 0 1 2 3 23 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 24 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 25 * | Version | Opcode | Response Code | Data Count | 26 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 27 * | Transaction ID | 28 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 29 * | Type (1) | 30 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 31 * | Length | Data / 32 * / / 33 * / / 34 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 35 * | Type (n) | 36 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 37 * | Length | Data / 38 * / / 39 * / / 40 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 41 * 42 * VQP is layered over UDP. The default destination port is 1589. 43 * 44 */ 45 46 #include <sys/types.h> 47 #include <sys/socket.h> 48 49 #include <net/if.h> 50 #include <netinet/in.h> 51 #include <netinet/if_ether.h> 52 #include <arpa/inet.h> 53 54 #include <stdio.h> 55 #include <string.h> 56 57 #include "interface.h" 58 #include "addrtoname.h" 59 #include "extract.h" 60 61 struct vqp_hdr { 62 u_char version; 63 u_char opcode; 64 u_char rcode; 65 u_char dcount; 66 u_int32_t xid; 67 }; 68 69 #define VQP_JOIN 0x01 70 #define VQP_JOIN_RESPONSE 0x02 71 #define VQP_RECONFIRM 0x03 72 #define VQP_RECONFIRM_RESPONSE 0x04 73 74 #define VQP_NO_ERROR 0x00 75 #define VQP_WRONG_VERSION 0x01 76 #define VQP_INSUFFICIENT_RESOURCES 0x02 77 #define VQP_DENY 0x03 78 #define VQP_SHUTDOWN 0x04 79 #define VQP_WRONG_MGMT_DOMAIN 0x05 80 81 /* 4 bytes struct in_addr; IP address of VQP client */ 82 #define VQP_CLIENT_ADDR 0x00000c01 83 /* string */ 84 #define VQP_PORT_NAME 0x00000c02 85 /* string */ 86 #define VQP_VLAN_NAME 0x00000c03 87 /* string; VTP domain if set */ 88 #define VQP_DOMAIN_NAME 0x00000c04 89 /* ethernet frame */ 90 #define VQP_ETHERNET_FRAME 0x00000c05 91 /* 6 bytes, mac address */ 92 #define VQP_MAC 0x00000c06 93 /* 2 bytes? */ 94 #define VQP_UNKNOWN 0x00000c07 95 /* 6 bytes, mac address */ 96 #define VQP_COOKIE 0x00000c08 97 98 static void 99 vqp_print_opcode(u_int val) 100 { 101 switch (val) { 102 case VQP_JOIN: 103 printf("Join"); 104 break; 105 case VQP_JOIN_RESPONSE: 106 printf("JoinResp"); 107 break; 108 case VQP_RECONFIRM: 109 printf("Reconfirm"); 110 break; 111 case VQP_RECONFIRM_RESPONSE: 112 printf("ReconfirmResp"); 113 break; 114 default: 115 printf("unknown(%x)", val); 116 break; 117 } 118 } 119 120 static void 121 vqp_print_rcode(u_int val) 122 { 123 switch (val) { 124 case VQP_NO_ERROR: 125 printf("NoError"); 126 break; 127 case VQP_WRONG_VERSION: 128 printf("WrongVersion"); 129 break; 130 case VQP_INSUFFICIENT_RESOURCES: 131 printf("InsufficientResources"); 132 break; 133 case VQP_DENY: 134 printf("Deny"); 135 break; 136 case VQP_SHUTDOWN: 137 printf("Shutdown"); 138 break; 139 case VQP_WRONG_MGMT_DOMAIN: 140 printf("WrongMgmtDomain"); 141 break; 142 default: 143 printf("unknown(%x)", val); 144 break; 145 } 146 } 147 148 static void 149 print_hex(const u_char *p, u_int len) 150 { 151 while (len--) 152 printf("%02x", *p++); 153 } 154 155 static void 156 vqp_print_type(u_int type, u_int len, const u_char *p) 157 { 158 switch (type) { 159 case VQP_CLIENT_ADDR: 160 printf(" client:"); 161 if (len == sizeof(struct in_addr)) { 162 struct in_addr in; 163 memcpy(&in, p, sizeof in); 164 printf("%s", inet_ntoa(in)); 165 } else 166 print_hex(p, len); 167 break; 168 case VQP_PORT_NAME: 169 printf(" port:"); 170 fn_printn(p, len, NULL); 171 break; 172 case VQP_VLAN_NAME: 173 printf(" vlan:"); 174 fn_printn(p, len, NULL); 175 break; 176 case VQP_DOMAIN_NAME: 177 printf(" domain:"); 178 fn_printn(p, len, NULL); 179 break; 180 case VQP_ETHERNET_FRAME: 181 printf(" ethernet:"); 182 if (vflag > 1) 183 print_hex(p, len); 184 else if (len >= ETHER_ADDR_LEN * 2) { 185 p += ETHER_ADDR_LEN; /* skip dst mac */ 186 printf("%s", etheraddr_string(p)); /* src mac */ 187 } else 188 print_hex(p, len); 189 break; 190 case VQP_MAC: 191 printf(" mac:"); 192 if (len == ETHER_ADDR_LEN) 193 printf("%s", etheraddr_string(p)); 194 else 195 print_hex(p, len); 196 break; 197 case VQP_UNKNOWN: 198 printf(" unknown:"); 199 print_hex(p, len); 200 break; 201 case VQP_COOKIE: 202 printf(" cookie:"); 203 if (len == ETHER_ADDR_LEN) 204 printf("%s", etheraddr_string(p)); 205 else 206 print_hex(p, len); 207 break; 208 default: 209 printf(" unknown(%x/%u)", type, len); 210 } 211 } 212 213 void 214 vqp_print(const u_char *bp, u_int len) 215 { 216 struct vqp_hdr *p = (struct vqp_hdr *)bp; 217 u_int dcount; 218 219 TCHECK(p->version); 220 printf(" VQPv%u", p->version); 221 if (p->version != 1) 222 return; 223 TCHECK(p->opcode); 224 printf("-"); 225 vqp_print_opcode(p->opcode); 226 TCHECK(p->rcode); 227 printf(" rcode:"); 228 vqp_print_rcode(p->rcode); 229 TCHECK(p->xid); 230 printf(" xid:0x%08x", ntohl(p->xid)); 231 printf(" dcount:%u", p->dcount); 232 bp += sizeof(struct vqp_hdr); 233 234 dcount = p->dcount; 235 while (vflag && dcount > 0) { 236 u_int type, length; 237 238 TCHECK2(bp[0], 6); 239 type = EXTRACT_32BITS(bp); 240 bp += 4; 241 length = EXTRACT_16BITS(bp); 242 bp += 2; 243 TCHECK2(bp[0], length); 244 vqp_print_type(type, length, bp); 245 bp += length; 246 dcount--; 247 } 248 249 return; 250 trunc: 251 printf("[|vqp]"); 252 } 253