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