xref: /openbsd/usr.sbin/tcpdump/print-usbpcap.c (revision 73471bf0)
1 /*	$OpenBSD: print-usbpcap.c,v 1.5 2020/03/23 09:38:26 patrick Exp $ */
2 
3 /*
4  * Copyright (c) 2018 Martin Pieuchot <mpi@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 #include <dev/usb/usb.h>
20 #include <dev/usb/usbpcap.h>
21 
22 #include <pcap.h>
23 
24 #include "interface.h"
25 
26 #ifndef nitems
27 #define nitems(_a)	(sizeof((_a)) / sizeof((_a)[0]))
28 #endif
29 
30 const char *usbpcap_xfer_type[] = {"isoc", "intr", "ctrl", "bulk"};
31 const char *usbpcap_control_stages[] = {"setup", "data", "status"};
32 const char *usbpcap_request_codes[] = {
33 	"GET_STATUS", "CLEAR_FEATURE", "?", "SET_FEATURE", "?", "SET_ADDRESS",
34 	"GET_DESCRIPTOR", "SET_DESCRIPTOR", "GET_CONFIG", "SET_CONFIG",
35 	"GET_INTERFACE", "SET_INTERFACE", "SYNCH_FRAME",
36 };
37 
38 void	 usbpcap_print_descriptor(int);
39 void	 usbpcap_print_request_type(uByte);
40 
41 void
42 usbpcap_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
43 {
44 	u_int length = h->len;
45 	u_int caplen = h->caplen;
46 	const struct usbpcap_pkt_hdr *uph;
47 	u_int16_t hdrlen;
48 
49 	ts_print(&h->ts);
50 
51 	/* check length */
52 	if (caplen < sizeof(uint16_t) || length < sizeof(*uph))
53 		goto trunc;
54 
55 	uph = (struct usbpcap_pkt_hdr *)p;
56 	hdrlen = letoh16(uph->uph_hlen);
57 	if (hdrlen < sizeof(*uph)) {
58 		printf("[usb: invalid header length %u!]", hdrlen);
59 		goto out;
60 	}
61 
62 	if (caplen < hdrlen)
63 		goto trunc;
64 
65 	printf("bus %u %c addr %u: ep%u",
66 	    letoh16(uph->uph_bus),
67 	     ((uph->uph_info & USBPCAP_INFO_DIRECTION_IN) ? '<' : '>'),
68 	    letoh16(uph->uph_devaddr), UE_GET_ADDR(uph->uph_epaddr));
69 
70 	if (uph->uph_xfertype < nitems(usbpcap_xfer_type))
71 		printf(" %s", usbpcap_xfer_type[uph->uph_xfertype]);
72 	else
73 		printf(" ??");
74 
75 	printf(" dlen=%u", letoh32(uph->uph_dlen));
76 
77 	if (uph->uph_xfertype == USBPCAP_TRANSFER_CONTROL) {
78 		struct usbpcap_ctl_hdr *ctl_hdr = (struct usbpcap_ctl_hdr *)p;
79 
80 		if (ctl_hdr->uch_stage < nitems(usbpcap_control_stages))
81 			printf(" stage=%s",
82 			    usbpcap_control_stages[ctl_hdr->uch_stage]);
83 		else
84 			printf(" stage=?");
85 
86 		if (ctl_hdr->uch_stage == USBPCAP_CONTROL_STAGE_SETUP) {
87 			/* Setup packets must be 8 bytes in size as per
88 			 * 9.3 USB Device Requests. */
89 			if (letoh32(uph->uph_dlen != 8))
90 				goto trunc;
91 
92 			usb_device_request_t *req = (usb_device_request_t *)
93 			    (p + sizeof(struct usbpcap_ctl_hdr));
94 
95 			usbpcap_print_request_type(req->bmRequestType);
96 
97 			if (req->bRequest < nitems(usbpcap_request_codes))
98 				printf(" bRequest=%s",
99 				    usbpcap_request_codes[req->bRequest]);
100 			else
101 				printf(" bRequest=?");
102 
103 			if (req->bRequest == UR_GET_DESCRIPTOR)
104 				usbpcap_print_descriptor(UGETW(req->wValue));
105 			else
106 				printf(" wValue=0x%04x", UGETW(req->wValue));
107 
108 			printf(" wIndex=%04x", UGETW(req->wIndex));
109 			printf(" wLength=%u", UGETW(req->wLength));
110 		}
111 	}
112 
113 	if (xflag)
114 		default_print(p + sizeof(*uph), length - sizeof(*uph));
115 out:
116 	putchar('\n');
117 	return;
118 trunc:
119 	printf("[|usb]");
120 }
121 
122 void
123 usbpcap_print_descriptor(int value)
124 {
125 	printf(" type=");
126 	switch (value >> 8) {
127 	case UDESC_DEVICE:
128 		printf("DEVICE");
129 		break;
130 	case UDESC_CONFIG:
131 		printf("CONFIGURATION");
132 		break;
133 	case UDESC_STRING:
134 		printf("STRING");
135 		break;
136 	case UDESC_INTERFACE:
137 		printf("INTERFACE");
138 		break;
139 	case UDESC_ENDPOINT:
140 		printf("ENDPOINT");
141 		break;
142 	case UDESC_DEVICE_QUALIFIER:
143 		printf("DEVICE_QUALIFIER");
144 		break;
145 	case UDESC_OTHER_SPEED_CONFIGURATION:
146 		printf("OTHER_SPEED_CONFIGURATION");
147 		break;
148 	case UDESC_INTERFACE_POWER:
149 		printf("INTERFACE_POWER");
150 		break;
151 	case UDESC_OTG:
152 		printf("OTG");
153 		break;
154 	case UDESC_DEBUG:
155 		printf("DEBUG");
156 		break;
157 	case UDESC_IFACE_ASSOC:
158 		printf("INTERFACE_ASSOCIATION");
159 		break;
160 	case UDESC_BOS:
161 		printf("BOS");
162 		break;
163 	case UDESC_DEVICE_CAPABILITY:
164 		printf("DEVICE_CAPABILITY");
165 		break;
166 	case UDESC_CS_DEVICE:
167 		printf("CS_DEVICE");
168 		break;
169 	case UDESC_CS_CONFIG:
170 		printf("CS_CONFIGURATION");
171 		break;
172 	case UDESC_CS_STRING:
173 		printf("CS_STRING");
174 		break;
175 	case UDESC_CS_INTERFACE:
176 		printf("CS_INTERFACE");
177 		break;
178 	case UDESC_CS_ENDPOINT:
179 		printf("CS_ENDPOINT");
180 		break;
181 	case UDESC_HUB:
182 		printf("HUB");
183 		break;
184 	case UDESC_SS_HUB:
185 		printf("SS_HUB");
186 		break;
187 	case UDESC_ENDPOINT_SS_COMP:
188 		printf("SS_COMPANION");
189 		break;
190 	default:
191 		printf("?");
192 	}
193 
194 	printf(" index=0x%02x", value & 0xff);
195 }
196 
197 void
198 usbpcap_print_request_type(uByte request_type)
199 {
200 	printf(" bmRequestType=");
201 
202 	switch (request_type) {
203 	case UT_READ_DEVICE:
204 		printf("UT_READ_DEVICE");
205 		break;
206 	case UT_READ_INTERFACE:
207 		printf("UT_READ_INTERFACE");
208 		break;
209 	case UT_READ_ENDPOINT:
210 		printf("UT_READ_ENDPOINT");
211 		break;
212 	case UT_WRITE_DEVICE:
213 		printf("UT_WRITE_DEVICE");
214 		break;
215 	case UT_WRITE_INTERFACE:
216 		printf("UT_WRITE_INTERFACE");
217 		break;
218 	case UT_WRITE_ENDPOINT:
219 		printf("UT_WRITE_ENDPOINT");
220 		break;
221 	case UT_READ_CLASS_DEVICE:
222 		printf("UT_READ_CLASS_DEVICE");
223 		break;
224 	case UT_READ_CLASS_INTERFACE:
225 		printf("UT_READ_CLASS_INTERFACE");
226 		break;
227 	case UT_READ_CLASS_OTHER:
228 		printf("UT_READ_CLASS_OTHER");
229 		break;
230 	case UT_READ_CLASS_ENDPOINT:
231 		printf("UT_READ_CLASS_ENDPOINT");
232 		break;
233 	case UT_WRITE_CLASS_DEVICE:
234 		printf("UT_WRITE_CLASS_DEVICE");
235 		break;
236 	case UT_WRITE_CLASS_INTERFACE:
237 		printf("UT_WRITE_CLASS_INTERFACE");
238 		break;
239 	case UT_WRITE_CLASS_OTHER:
240 		printf("UT_WRITE_CLASS_OTHER");
241 		break;
242 	case UT_WRITE_CLASS_ENDPOINT:
243 		printf("UT_WRITE_CLASS_ENDPOINT");
244 		break;
245 	case UT_READ_VENDOR_DEVICE:
246 		printf("UT_READ_VENDOR_DEVICE");
247 		break;
248 	case UT_READ_VENDOR_INTERFACE:
249 		printf("UT_READ_VENDOR_INTERFACE");
250 		break;
251 	case UT_READ_VENDOR_OTHER:
252 		printf("UT_READ_VENDOR_OTHER");
253 		break;
254 	case UT_READ_VENDOR_ENDPOINT:
255 		printf("UT_READ_VENDOR_ENDPOINT");
256 		break;
257 	case UT_WRITE_VENDOR_DEVICE:
258 		printf("UT_WRITE_VENDOR_DEVICE");
259 		break;
260 	case UT_WRITE_VENDOR_INTERFACE:
261 		printf("UT_WRITE_VENDOR_INTERFACE");
262 		break;
263 	case UT_WRITE_VENDOR_OTHER:
264 		printf("UT_WRITE_VENDOR_OTHER");
265 		break;
266 	case UT_WRITE_VENDOR_ENDPOINT:
267 		printf("UT_WRITE_VENDOR_ENDPOINT");
268 		break;
269 	default:
270 		printf("?");
271 	}
272 }
273