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