1*163fba51Sstevesk /* $OpenBSD: print-vqp.c,v 1.6 2006/08/20 23:39:42 stevesk Exp $ */ 216ad035eSstevesk 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 49*163fba51Sstevesk #include <net/if.h> 50f9a530d7Sstevesk #include <netinet/in.h> 51*163fba51Sstevesk #include <netinet/if_ether.h> 52f9a530d7Sstevesk #include <arpa/inet.h> 53f9a530d7Sstevesk 54f9a530d7Sstevesk #include <stdio.h> 55f9a530d7Sstevesk #include <string.h> 56f9a530d7Sstevesk 57f9a530d7Sstevesk #include "interface.h" 58f9a530d7Sstevesk #include "addrtoname.h" 59f9a530d7Sstevesk #include "extract.h" 60f9a530d7Sstevesk 61f9a530d7Sstevesk struct vqp_hdr { 62f9a530d7Sstevesk u_char version; 63f9a530d7Sstevesk u_char opcode; 64f9a530d7Sstevesk u_char rcode; 65f9a530d7Sstevesk u_char dcount; 66f9a530d7Sstevesk u_int32_t xid; 67f9a530d7Sstevesk }; 68f9a530d7Sstevesk 69f9a530d7Sstevesk #define VQP_JOIN 0x01 70f9a530d7Sstevesk #define VQP_JOIN_RESPONSE 0x02 71f9a530d7Sstevesk #define VQP_RECONFIRM 0x03 72f9a530d7Sstevesk #define VQP_RECONFIRM_RESPONSE 0x04 73f9a530d7Sstevesk 74f9a530d7Sstevesk #define VQP_NO_ERROR 0x00 75f9a530d7Sstevesk #define VQP_WRONG_VERSION 0x01 76f9a530d7Sstevesk #define VQP_INSUFFICIENT_RESOURCES 0x02 77f9a530d7Sstevesk #define VQP_DENY 0x03 78f9a530d7Sstevesk #define VQP_SHUTDOWN 0x04 79f9a530d7Sstevesk #define VQP_WRONG_MGMT_DOMAIN 0x05 80f9a530d7Sstevesk 81f9a530d7Sstevesk /* 4 bytes struct in_addr; IP address of VQP client */ 82f9a530d7Sstevesk #define VQP_CLIENT_ADDR 0x00000c01 83f9a530d7Sstevesk /* string */ 84f9a530d7Sstevesk #define VQP_PORT_NAME 0x00000c02 85f9a530d7Sstevesk /* string */ 86f9a530d7Sstevesk #define VQP_VLAN_NAME 0x00000c03 87f9a530d7Sstevesk /* string; VTP domain if set */ 88f9a530d7Sstevesk #define VQP_DOMAIN_NAME 0x00000c04 89f9a530d7Sstevesk /* 2 bytes? */ 90f9a530d7Sstevesk #define VQP_UNKNOWN1 0x00000c05 91f9a530d7Sstevesk /* 6 bytes, mac address */ 92f9a530d7Sstevesk #define VQP_MAC 0x00000c06 93f9a530d7Sstevesk /* unknown */ 94f9a530d7Sstevesk #define VQP_UNKNOWN2 0x00000c07 95f9a530d7Sstevesk /* 6 bytes, mac address */ 96f9a530d7Sstevesk #define VQP_COOKIE 0x00000c08 97f9a530d7Sstevesk 98f9a530d7Sstevesk static void 99f9a530d7Sstevesk vqp_print_opcode(u_int val) 100f9a530d7Sstevesk { 101f9a530d7Sstevesk switch (val) { 102f9a530d7Sstevesk case VQP_JOIN: 103f9a530d7Sstevesk printf("Join"); 104f9a530d7Sstevesk break; 105f9a530d7Sstevesk case VQP_JOIN_RESPONSE: 106f9a530d7Sstevesk printf("JoinResp"); 107f9a530d7Sstevesk break; 108f9a530d7Sstevesk case VQP_RECONFIRM: 109f9a530d7Sstevesk printf("Reconfirm"); 110f9a530d7Sstevesk break; 111f9a530d7Sstevesk case VQP_RECONFIRM_RESPONSE: 112f9a530d7Sstevesk printf("ReconfirmResp"); 113f9a530d7Sstevesk break; 114f9a530d7Sstevesk default: 115f9a530d7Sstevesk printf("unknown(%x)", val); 116f9a530d7Sstevesk break; 117f9a530d7Sstevesk } 118f9a530d7Sstevesk } 119f9a530d7Sstevesk 120f9a530d7Sstevesk static void 121f9a530d7Sstevesk vqp_print_rcode(u_int val) 122f9a530d7Sstevesk { 123f9a530d7Sstevesk switch (val) { 124f9a530d7Sstevesk case VQP_NO_ERROR: 125f9a530d7Sstevesk printf("NoError"); 126f9a530d7Sstevesk break; 127f9a530d7Sstevesk case VQP_WRONG_VERSION: 128f9a530d7Sstevesk printf("WrongVersion"); 129f9a530d7Sstevesk break; 130f9a530d7Sstevesk case VQP_INSUFFICIENT_RESOURCES: 131f9a530d7Sstevesk printf("InsufficientResources"); 132f9a530d7Sstevesk break; 133f9a530d7Sstevesk case VQP_DENY: 134f9a530d7Sstevesk printf("Deny"); 135f9a530d7Sstevesk break; 136f9a530d7Sstevesk case VQP_SHUTDOWN: 137f9a530d7Sstevesk printf("Shutdown"); 138f9a530d7Sstevesk break; 139f9a530d7Sstevesk case VQP_WRONG_MGMT_DOMAIN: 140f9a530d7Sstevesk printf("WrongMgmtDomain"); 141f9a530d7Sstevesk break; 142f9a530d7Sstevesk default: 143f9a530d7Sstevesk printf("unknown(%x)", val); 144f9a530d7Sstevesk break; 145f9a530d7Sstevesk } 146f9a530d7Sstevesk } 147f9a530d7Sstevesk 148f9a530d7Sstevesk static void 149f9a530d7Sstevesk print_hex(const u_char *p, u_int len) 150f9a530d7Sstevesk { 151f9a530d7Sstevesk while (len--) 152dad5b628Sstevesk printf("%02x", *p++); 153f9a530d7Sstevesk } 154f9a530d7Sstevesk 155f9a530d7Sstevesk static void 156f9a530d7Sstevesk vqp_print_type(u_int type, u_int len, const u_char *p) 157f9a530d7Sstevesk { 158f9a530d7Sstevesk switch (type) { 159f9a530d7Sstevesk case VQP_CLIENT_ADDR: 160f9a530d7Sstevesk printf(" client:"); 161*163fba51Sstevesk if (len == sizeof(struct in_addr)) { 162f9a530d7Sstevesk struct in_addr in; 163f9a530d7Sstevesk memcpy(&in, p, sizeof in); 164f9a530d7Sstevesk printf("%s", inet_ntoa(in)); 165f9a530d7Sstevesk } else 166f9a530d7Sstevesk print_hex(p, len); 167f9a530d7Sstevesk break; 168f9a530d7Sstevesk case VQP_PORT_NAME: 169f9a530d7Sstevesk printf(" port:"); 170f9a530d7Sstevesk fn_printn(p, len, NULL); 171f9a530d7Sstevesk break; 172f9a530d7Sstevesk case VQP_VLAN_NAME: 173f9a530d7Sstevesk printf(" vlan:"); 174f9a530d7Sstevesk fn_printn(p, len, NULL); 175f9a530d7Sstevesk break; 176f9a530d7Sstevesk case VQP_DOMAIN_NAME: 177f9a530d7Sstevesk printf(" domain:"); 178f9a530d7Sstevesk fn_printn(p, len, NULL); 179f9a530d7Sstevesk break; 180f9a530d7Sstevesk case VQP_UNKNOWN1: 181f9a530d7Sstevesk printf(" unknown1:"); 182f9a530d7Sstevesk print_hex(p, len); 183f9a530d7Sstevesk break; 184f9a530d7Sstevesk case VQP_MAC: 185f9a530d7Sstevesk printf(" mac:"); 186*163fba51Sstevesk if (len == ETHER_ADDR_LEN) 187f9a530d7Sstevesk printf("%s", etheraddr_string(p)); 188f9a530d7Sstevesk else 189f9a530d7Sstevesk print_hex(p, len); 190f9a530d7Sstevesk break; 191f9a530d7Sstevesk case VQP_UNKNOWN2: 192f9a530d7Sstevesk printf(" unknown2:"); 193f9a530d7Sstevesk print_hex(p, len); 194f9a530d7Sstevesk break; 195f9a530d7Sstevesk case VQP_COOKIE: 196f9a530d7Sstevesk printf(" cookie:"); 197*163fba51Sstevesk if (len == ETHER_ADDR_LEN) 198f9a530d7Sstevesk printf("%s", etheraddr_string(p)); 199f9a530d7Sstevesk else 200f9a530d7Sstevesk print_hex(p, len); 201f9a530d7Sstevesk break; 202f9a530d7Sstevesk default: 203f9a530d7Sstevesk printf(" unknown(%x/%u)", type, len); 204f9a530d7Sstevesk } 205f9a530d7Sstevesk } 206f9a530d7Sstevesk 207f9a530d7Sstevesk void 208f9a530d7Sstevesk vqp_print(const u_char *bp, u_int len) 209f9a530d7Sstevesk { 210f9a530d7Sstevesk struct vqp_hdr *p = (struct vqp_hdr *)bp; 211f9a530d7Sstevesk u_int dcount; 212f9a530d7Sstevesk 213f9a530d7Sstevesk TCHECK(p->version); 214f9a530d7Sstevesk printf(" VQPv%u", p->version); 215f9a530d7Sstevesk if (p->version != 1) 216f9a530d7Sstevesk return; 217f9a530d7Sstevesk TCHECK(p->opcode); 218f9a530d7Sstevesk printf("-"); 219f9a530d7Sstevesk vqp_print_opcode(p->opcode); 220f9a530d7Sstevesk TCHECK(p->rcode); 221f9a530d7Sstevesk printf(" rcode:"); 222f9a530d7Sstevesk vqp_print_rcode(p->rcode); 223f9a530d7Sstevesk TCHECK(p->xid); 224f9a530d7Sstevesk printf(" xid:0x%08x", ntohl(p->xid)); 225f9a530d7Sstevesk printf(" dcount:%u", p->dcount); 226f9a530d7Sstevesk bp += sizeof(struct vqp_hdr); 227f9a530d7Sstevesk 228f9a530d7Sstevesk dcount = p->dcount; 229f9a530d7Sstevesk while (vflag && dcount > 0) { 230f8295863Sderaadt u_int type, length; 231f8295863Sderaadt 232f9a530d7Sstevesk TCHECK2(bp[0], 6); 233f8295863Sderaadt type = EXTRACT_32BITS(bp); 234f9a530d7Sstevesk bp += 4; 235f8295863Sderaadt length = EXTRACT_16BITS(bp); 236f9a530d7Sstevesk bp += 2; 237f9a530d7Sstevesk TCHECK2(bp[0], length); 238f9a530d7Sstevesk vqp_print_type(type, length, bp); 239f9a530d7Sstevesk bp += length; 240f9a530d7Sstevesk dcount--; 241f9a530d7Sstevesk } 242f9a530d7Sstevesk 243f9a530d7Sstevesk return; 244f9a530d7Sstevesk trunc: 245f9a530d7Sstevesk printf("[|vqp]"); 246f9a530d7Sstevesk } 247