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