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