1*eb937681Sdlg /* $OpenBSD: print-vqp.c,v 1.8 2018/07/06 05:47:22 dlg 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
49163fba51Sstevesk #include <net/if.h>
50f9a530d7Sstevesk #include <netinet/in.h>
51163fba51Sstevesk #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
899e75c8adSstevesk /* ethernet frame */
909e75c8adSstevesk #define VQP_ETHERNET_FRAME 0x00000c05
91f9a530d7Sstevesk /* 6 bytes, mac address */
92f9a530d7Sstevesk #define VQP_MAC 0x00000c06
939e75c8adSstevesk /* 2 bytes? */
949e75c8adSstevesk #define VQP_UNKNOWN 0x00000c07
95f9a530d7Sstevesk /* 6 bytes, mac address */
96f9a530d7Sstevesk #define VQP_COOKIE 0x00000c08
97f9a530d7Sstevesk
98f9a530d7Sstevesk static void
vqp_print_opcode(u_int val)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
vqp_print_rcode(u_int val)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
print_hex(const u_char * p,u_int len)149f9a530d7Sstevesk print_hex(const u_char *p, u_int len)
150f9a530d7Sstevesk {
151f9a530d7Sstevesk while (len--)
152dad5b628Sstevesk printf("%02x", *p++);
153f9a530d7Sstevesk }
154f9a530d7Sstevesk
155f9a530d7Sstevesk static void
vqp_print_type(u_int type,u_int len,const u_char * p)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:");
161163fba51Sstevesk 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;
1809e75c8adSstevesk case VQP_ETHERNET_FRAME:
1819e75c8adSstevesk printf(" ethernet:");
1829e75c8adSstevesk if (vflag > 1)
1839e75c8adSstevesk print_hex(p, len);
1849e75c8adSstevesk else if (len >= ETHER_ADDR_LEN * 2) {
1859e75c8adSstevesk p += ETHER_ADDR_LEN; /* skip dst mac */
1869e75c8adSstevesk printf("%s", etheraddr_string(p)); /* src mac */
1879e75c8adSstevesk } else
188f9a530d7Sstevesk print_hex(p, len);
189f9a530d7Sstevesk break;
190f9a530d7Sstevesk case VQP_MAC:
191f9a530d7Sstevesk printf(" mac:");
192163fba51Sstevesk if (len == ETHER_ADDR_LEN)
193f9a530d7Sstevesk printf("%s", etheraddr_string(p));
194f9a530d7Sstevesk else
195f9a530d7Sstevesk print_hex(p, len);
196f9a530d7Sstevesk break;
1979e75c8adSstevesk case VQP_UNKNOWN:
1989e75c8adSstevesk printf(" unknown:");
199f9a530d7Sstevesk print_hex(p, len);
200f9a530d7Sstevesk break;
201f9a530d7Sstevesk case VQP_COOKIE:
202f9a530d7Sstevesk printf(" cookie:");
203163fba51Sstevesk if (len == ETHER_ADDR_LEN)
204f9a530d7Sstevesk printf("%s", etheraddr_string(p));
205f9a530d7Sstevesk else
206f9a530d7Sstevesk print_hex(p, len);
207f9a530d7Sstevesk break;
208f9a530d7Sstevesk default:
209f9a530d7Sstevesk printf(" unknown(%x/%u)", type, len);
210f9a530d7Sstevesk }
211f9a530d7Sstevesk }
212f9a530d7Sstevesk
213f9a530d7Sstevesk void
vqp_print(const u_char * bp,u_int len)214f9a530d7Sstevesk vqp_print(const u_char *bp, u_int len)
215f9a530d7Sstevesk {
216f9a530d7Sstevesk struct vqp_hdr *p = (struct vqp_hdr *)bp;
217f9a530d7Sstevesk u_int dcount;
218f9a530d7Sstevesk
219f9a530d7Sstevesk TCHECK(p->version);
220f9a530d7Sstevesk printf("VQPv%u", p->version);
221f9a530d7Sstevesk if (p->version != 1)
222f9a530d7Sstevesk return;
223f9a530d7Sstevesk TCHECK(p->opcode);
224f9a530d7Sstevesk printf("-");
225f9a530d7Sstevesk vqp_print_opcode(p->opcode);
226f9a530d7Sstevesk TCHECK(p->rcode);
227f9a530d7Sstevesk printf(" rcode:");
228f9a530d7Sstevesk vqp_print_rcode(p->rcode);
229f9a530d7Sstevesk TCHECK(p->xid);
230f9a530d7Sstevesk printf(" xid:0x%08x", ntohl(p->xid));
231f9a530d7Sstevesk printf(" dcount:%u", p->dcount);
232f9a530d7Sstevesk bp += sizeof(struct vqp_hdr);
233f9a530d7Sstevesk
234f9a530d7Sstevesk dcount = p->dcount;
235f9a530d7Sstevesk while (vflag && dcount > 0) {
236f8295863Sderaadt u_int type, length;
237f8295863Sderaadt
238f9a530d7Sstevesk TCHECK2(bp[0], 6);
239f8295863Sderaadt type = EXTRACT_32BITS(bp);
240f9a530d7Sstevesk bp += 4;
241f8295863Sderaadt length = EXTRACT_16BITS(bp);
242f9a530d7Sstevesk bp += 2;
243f9a530d7Sstevesk TCHECK2(bp[0], length);
244f9a530d7Sstevesk vqp_print_type(type, length, bp);
245f9a530d7Sstevesk bp += length;
246f9a530d7Sstevesk dcount--;
247f9a530d7Sstevesk }
248f9a530d7Sstevesk
249f9a530d7Sstevesk return;
250f9a530d7Sstevesk trunc:
251f9a530d7Sstevesk printf("[|vqp]");
252f9a530d7Sstevesk }
253