xref: /openbsd/usr.sbin/tcpdump/print-vqp.c (revision 16ad035e)
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