xref: /openbsd/sys/dev/usb/if_urndis.c (revision 990261ac)
1 /*	$OpenBSD: if_urndis.c,v 1.73 2021/11/05 11:38:52 mpi Exp $ */
2 
3 /*
4  * Copyright (c) 2010 Jonathan Armani <armani@openbsd.org>
5  * Copyright (c) 2010 Fabien Romano <fabien@openbsd.org>
6  * Copyright (c) 2010 Michael Knudsen <mk@openbsd.org>
7  * All rights reserved.
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  */
21 
22 #include "bpfilter.h"
23 
24 #include <sys/param.h>
25 #include <sys/systm.h>
26 #include <sys/sockio.h>
27 #include <sys/rwlock.h>
28 #include <sys/mbuf.h>
29 #include <sys/kernel.h>
30 #include <sys/socket.h>
31 
32 #include <sys/device.h>
33 
34 #include <machine/bus.h>
35 
36 #include <net/if.h>
37 #include <net/if_media.h>
38 
39 #if NBPFILTER > 0
40 #include <net/bpf.h>
41 #endif
42 
43 #include <netinet/in.h>
44 #include <netinet/if_ether.h>
45 
46 #include <dev/usb/usb.h>
47 #include <dev/usb/usbdi.h>
48 #include <dev/usb/usbdi_util.h>
49 #include <dev/usb/usbdivar.h>
50 #include <dev/usb/usbdevs.h>
51 
52 #include <dev/rndis.h>
53 
54 #include <dev/usb/if_urndisreg.h>
55 
56 #ifdef URNDIS_DEBUG
57 #define DPRINTF(x)      do { printf x; } while (0)
58 #else
59 #define DPRINTF(x)
60 #endif
61 
62 #define DEVNAME(sc)	((sc)->sc_dev.dv_xname)
63 
64 int urndis_newbuf(struct urndis_softc *, struct urndis_chain *);
65 
66 int urndis_ioctl(struct ifnet *, u_long, caddr_t);
67 #if 0
68 void urndis_watchdog(struct ifnet *);
69 #endif
70 
71 void urndis_start(struct ifnet *);
72 void urndis_rxeof(struct usbd_xfer *, void *, usbd_status);
73 void urndis_txeof(struct usbd_xfer *, void *, usbd_status);
74 int urndis_rx_list_init(struct urndis_softc *);
75 int urndis_tx_list_init(struct urndis_softc *);
76 
77 void urndis_init(struct urndis_softc *);
78 void urndis_stop(struct urndis_softc *);
79 
80 usbd_status urndis_ctrl_msg(struct urndis_softc *, uint8_t, uint8_t,
81     uint16_t, uint16_t, void *, size_t);
82 usbd_status urndis_ctrl_send(struct urndis_softc *, void *, size_t);
83 struct rndis_comp_hdr *urndis_ctrl_recv(struct urndis_softc *);
84 
85 u_int32_t urndis_ctrl_handle(struct urndis_softc *,
86     struct rndis_comp_hdr *, void **, size_t *);
87 u_int32_t urndis_ctrl_handle_init(struct urndis_softc *,
88     const struct rndis_comp_hdr *);
89 u_int32_t urndis_ctrl_handle_query(struct urndis_softc *,
90     const struct rndis_comp_hdr *, void **, size_t *);
91 u_int32_t urndis_ctrl_handle_reset(struct urndis_softc *,
92     const struct rndis_comp_hdr *);
93 u_int32_t urndis_ctrl_handle_status(struct urndis_softc *,
94     const struct rndis_comp_hdr *);
95 
96 u_int32_t urndis_ctrl_init(struct urndis_softc *);
97 u_int32_t urndis_ctrl_halt(struct urndis_softc *);
98 u_int32_t urndis_ctrl_query(struct urndis_softc *, u_int32_t, void *, size_t,
99     void **, size_t *);
100 u_int32_t urndis_ctrl_set(struct urndis_softc *, u_int32_t, void *, size_t);
101 u_int32_t urndis_ctrl_set_param(struct urndis_softc *, const char *, u_int32_t,
102     void *, size_t);
103 #if 0
104 u_int32_t urndis_ctrl_reset(struct urndis_softc *);
105 u_int32_t urndis_ctrl_keepalive(struct urndis_softc *);
106 #endif
107 
108 int urndis_encap(struct urndis_softc *, struct mbuf *, int);
109 void urndis_decap(struct urndis_softc *, struct urndis_chain *, u_int32_t);
110 
111 const struct urndis_class *urndis_lookup(usb_interface_descriptor_t *);
112 
113 int urndis_match(struct device *, void *, void *);
114 void urndis_attach(struct device *, struct device *, void *);
115 int urndis_detach(struct device *, int);
116 
117 struct cfdriver urndis_cd = {
118 	NULL, "urndis", DV_IFNET
119 };
120 
121 const struct cfattach urndis_ca = {
122 	sizeof(struct urndis_softc), urndis_match, urndis_attach, urndis_detach
123 };
124 
125 const struct urndis_class {
126 	u_int8_t class;
127 	u_int8_t subclass;
128 	u_int8_t protocol;
129 	const char *typestr;
130 } urndis_class[] = {
131 	{ UICLASS_CDC, UISUBCLASS_ABSTRACT_CONTROL_MODEL, 0xff, "Vendor" },
132 	{ UICLASS_WIRELESS, UISUBCLASS_RF, UIPROTO_RNDIS, "RNDIS" },
133 	{ UICLASS_MISC, UISUBCLASS_SYNC, UIPROTO_ACTIVESYNC, "Activesync" }
134 };
135 
136 usbd_status
urndis_ctrl_msg(struct urndis_softc * sc,uint8_t rt,uint8_t r,uint16_t index,uint16_t value,void * buf,size_t buflen)137 urndis_ctrl_msg(struct urndis_softc *sc, uint8_t rt, uint8_t r,
138     uint16_t index, uint16_t value, void *buf, size_t buflen)
139 {
140 	usb_device_request_t req;
141 
142 	req.bmRequestType = rt;
143 	req.bRequest = r;
144 	USETW(req.wValue, value);
145 	USETW(req.wIndex, index);
146 	USETW(req.wLength, buflen);
147 
148 	return usbd_do_request(sc->sc_udev, &req, buf);
149 }
150 
151 usbd_status
urndis_ctrl_send(struct urndis_softc * sc,void * buf,size_t len)152 urndis_ctrl_send(struct urndis_softc *sc, void *buf, size_t len)
153 {
154 	usbd_status err;
155 
156 	if (usbd_is_dying(sc->sc_udev))
157 		return(0);
158 
159 	err = urndis_ctrl_msg(sc, UT_WRITE_CLASS_INTERFACE, UR_GET_STATUS,
160 	    sc->sc_ifaceno_ctl, 0, buf, len);
161 
162 	if (err != USBD_NORMAL_COMPLETION)
163 		printf("%s: %s\n", DEVNAME(sc), usbd_errstr(err));
164 
165 	return err;
166 }
167 
168 struct rndis_comp_hdr *
urndis_ctrl_recv(struct urndis_softc * sc)169 urndis_ctrl_recv(struct urndis_softc *sc)
170 {
171 #define RNDIS_RESPONSE_LEN 0x400
172 	struct rndis_comp_hdr	*hdr;
173 	char			*buf;
174 	usbd_status		 err;
175 
176 	buf = malloc(RNDIS_RESPONSE_LEN, M_TEMP, M_WAITOK | M_CANFAIL);
177 	if (buf == NULL) {
178 		printf("%s: out of memory\n", DEVNAME(sc));
179 		return NULL;
180 	}
181 
182 	err = urndis_ctrl_msg(sc, UT_READ_CLASS_INTERFACE, UR_CLEAR_FEATURE,
183 	    sc->sc_ifaceno_ctl, 0, buf, RNDIS_RESPONSE_LEN);
184 
185 	if (err != USBD_NORMAL_COMPLETION && err != USBD_SHORT_XFER) {
186 		printf("%s: %s\n", DEVNAME(sc), usbd_errstr(err));
187 		free(buf, M_TEMP, RNDIS_RESPONSE_LEN);
188 		return NULL;
189 	}
190 
191 	hdr = (struct rndis_comp_hdr *)buf;
192 	DPRINTF(("%s: urndis_ctrl_recv: type 0x%x len %u\n",
193 	    DEVNAME(sc),
194 	    letoh32(hdr->rm_type),
195 	    letoh32(hdr->rm_len)));
196 
197 	if (letoh32(hdr->rm_len) > RNDIS_RESPONSE_LEN) {
198 		printf("%s: ctrl message error: wrong size %u > %u\n",
199 		    DEVNAME(sc),
200 		    letoh32(hdr->rm_len),
201 		    RNDIS_RESPONSE_LEN);
202 		free(buf, M_TEMP, RNDIS_RESPONSE_LEN);
203 		return NULL;
204 	}
205 
206 	return hdr;
207 }
208 
209 u_int32_t
urndis_ctrl_handle(struct urndis_softc * sc,struct rndis_comp_hdr * hdr,void ** buf,size_t * bufsz)210 urndis_ctrl_handle(struct urndis_softc *sc, struct rndis_comp_hdr *hdr,
211     void **buf, size_t *bufsz)
212 {
213 	u_int32_t rval;
214 
215 	DPRINTF(("%s: urndis_ctrl_handle\n", DEVNAME(sc)));
216 
217 	if (buf && bufsz) {
218 		*buf = NULL;
219 		*bufsz = 0;
220 	}
221 
222 	switch (letoh32(hdr->rm_type)) {
223 		case REMOTE_NDIS_INITIALIZE_CMPLT:
224 			rval = urndis_ctrl_handle_init(sc, hdr);
225 			break;
226 
227 		case REMOTE_NDIS_QUERY_CMPLT:
228 			rval = urndis_ctrl_handle_query(sc, hdr, buf, bufsz);
229 			break;
230 
231 		case REMOTE_NDIS_RESET_CMPLT:
232 			rval = urndis_ctrl_handle_reset(sc, hdr);
233 			break;
234 
235 		case REMOTE_NDIS_KEEPALIVE_CMPLT:
236 		case REMOTE_NDIS_SET_CMPLT:
237 			rval = letoh32(hdr->rm_status);
238 			break;
239 
240 		case REMOTE_NDIS_INDICATE_STATUS_MSG:
241 			rval = urndis_ctrl_handle_status(sc, hdr);
242 			break;
243 
244 		default:
245 			printf("%s: ctrl message error: unknown event 0x%x\n",
246 			    DEVNAME(sc), letoh32(hdr->rm_type));
247 			rval = RNDIS_STATUS_FAILURE;
248 	}
249 
250 	free(hdr, M_TEMP, RNDIS_RESPONSE_LEN);
251 
252 	return rval;
253 }
254 
255 u_int32_t
urndis_ctrl_handle_init(struct urndis_softc * sc,const struct rndis_comp_hdr * hdr)256 urndis_ctrl_handle_init(struct urndis_softc *sc,
257     const struct rndis_comp_hdr *hdr)
258 {
259 	const struct rndis_init_comp	*msg;
260 
261 	msg = (struct rndis_init_comp *) hdr;
262 
263 	DPRINTF(("%s: urndis_ctrl_handle_init: len %u rid %u status 0x%x "
264 	    "ver_major %u ver_minor %u devflags 0x%x medium 0x%x pktmaxcnt %u "
265 	    "pktmaxsz %u align %u aflistoffset %u aflistsz %u\n",
266 	    DEVNAME(sc),
267 	    letoh32(msg->rm_len),
268 	    letoh32(msg->rm_rid),
269 	    letoh32(msg->rm_status),
270 	    letoh32(msg->rm_ver_major),
271 	    letoh32(msg->rm_ver_minor),
272 	    letoh32(msg->rm_devflags),
273 	    letoh32(msg->rm_medium),
274 	    letoh32(msg->rm_pktmaxcnt),
275 	    letoh32(msg->rm_pktmaxsz),
276 	    letoh32(msg->rm_align),
277 	    letoh32(msg->rm_aflistoffset),
278 	    letoh32(msg->rm_aflistsz)));
279 
280 	if (letoh32(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
281 		printf("%s: init failed 0x%x\n",
282 		    DEVNAME(sc),
283 		    letoh32(msg->rm_status));
284 
285 		return letoh32(msg->rm_status);
286 	}
287 
288 	if (letoh32(msg->rm_devflags) != RNDIS_DF_CONNECTIONLESS) {
289 		printf("%s: wrong device type (current type: 0x%x)\n",
290 		    DEVNAME(sc),
291 		    letoh32(msg->rm_devflags));
292 
293 		return RNDIS_STATUS_FAILURE;
294 	}
295 
296 	if (letoh32(msg->rm_medium) != RNDIS_MEDIUM_802_3) {
297 		printf("%s: medium not 802.3 (current medium: 0x%x)\n",
298 		    DEVNAME(sc), letoh32(msg->rm_medium));
299 
300 		return RNDIS_STATUS_FAILURE;
301 	}
302 
303 	sc->sc_lim_pktsz = letoh32(msg->rm_pktmaxsz);
304 
305 	return letoh32(msg->rm_status);
306 }
307 
308 u_int32_t
urndis_ctrl_handle_query(struct urndis_softc * sc,const struct rndis_comp_hdr * hdr,void ** buf,size_t * bufsz)309 urndis_ctrl_handle_query(struct urndis_softc *sc,
310     const struct rndis_comp_hdr *hdr, void **buf, size_t *bufsz)
311 {
312 	const struct rndis_query_comp	*msg;
313 
314 	msg = (struct rndis_query_comp *) hdr;
315 
316 	DPRINTF(("%s: urndis_ctrl_handle_query: len %u rid %u status 0x%x "
317 	    "buflen %u bufoff %u\n",
318 	    DEVNAME(sc),
319 	    letoh32(msg->rm_len),
320 	    letoh32(msg->rm_rid),
321 	    letoh32(msg->rm_status),
322 	    letoh32(msg->rm_infobuflen),
323 	    letoh32(msg->rm_infobufoffset)));
324 
325 	if (buf && bufsz) {
326 		*buf = NULL;
327 		*bufsz = 0;
328 	}
329 
330 	if (letoh32(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
331 		printf("%s: query failed 0x%x\n",
332 		    DEVNAME(sc),
333 		    letoh32(msg->rm_status));
334 
335 		return letoh32(msg->rm_status);
336 	}
337 
338 	if (letoh32(msg->rm_infobuflen) + letoh32(msg->rm_infobufoffset) +
339 	    RNDIS_HEADER_OFFSET > letoh32(msg->rm_len)) {
340 		printf("%s: ctrl message error: invalid query info "
341 		    "len/offset/end_position(%u/%u/%zu) -> "
342 		    "go out of buffer limit %u\n",
343 		    DEVNAME(sc),
344 		    letoh32(msg->rm_infobuflen),
345 		    letoh32(msg->rm_infobufoffset),
346 		    letoh32(msg->rm_infobuflen) +
347 		    letoh32(msg->rm_infobufoffset) + RNDIS_HEADER_OFFSET,
348 		    letoh32(msg->rm_len));
349 		return RNDIS_STATUS_FAILURE;
350 	}
351 
352 	if (buf && bufsz) {
353 		*buf = malloc(letoh32(msg->rm_infobuflen),
354 		    M_TEMP, M_WAITOK | M_CANFAIL);
355 		if (*buf == NULL) {
356 			printf("%s: out of memory\n", DEVNAME(sc));
357 			return RNDIS_STATUS_FAILURE;
358 		} else {
359 			char *p;
360 			*bufsz = letoh32(msg->rm_infobuflen);
361 
362 			p = (char *)&msg->rm_rid;
363 			p += letoh32(msg->rm_infobufoffset);
364 			memcpy(*buf, p, letoh32(msg->rm_infobuflen));
365 		}
366 	}
367 
368 	return letoh32(msg->rm_status);
369 }
370 
371 u_int32_t
urndis_ctrl_handle_reset(struct urndis_softc * sc,const struct rndis_comp_hdr * hdr)372 urndis_ctrl_handle_reset(struct urndis_softc *sc,
373     const struct rndis_comp_hdr *hdr)
374 {
375 	const struct rndis_reset_comp	*msg;
376 	u_int32_t			 rval;
377 
378 	msg = (struct rndis_reset_comp *) hdr;
379 
380 	rval = letoh32(msg->rm_status);
381 
382 	DPRINTF(("%s: urndis_ctrl_handle_reset: len %u status 0x%x "
383 	    "adrreset %u\n",
384 	    DEVNAME(sc),
385 	    letoh32(msg->rm_len),
386 	    rval,
387 	    letoh32(msg->rm_adrreset)));
388 
389 	if (rval != RNDIS_STATUS_SUCCESS) {
390 		printf("%s: reset failed 0x%x\n", DEVNAME(sc), rval);
391 		return rval;
392 	}
393 
394 	if (letoh32(msg->rm_adrreset) != 0) {
395 		u_int32_t filter;
396 
397 		filter = htole32(sc->sc_filter);
398 		rval = urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
399 		    &filter, sizeof(filter));
400 		if (rval != RNDIS_STATUS_SUCCESS) {
401 			printf("%s: unable to reset data filters\n",
402 			    DEVNAME(sc));
403 			return rval;
404 		}
405 	}
406 
407 	return rval;
408 }
409 
410 u_int32_t
urndis_ctrl_handle_status(struct urndis_softc * sc,const struct rndis_comp_hdr * hdr)411 urndis_ctrl_handle_status(struct urndis_softc *sc,
412     const struct rndis_comp_hdr *hdr)
413 {
414 	const struct rndis_status_msg	*msg;
415 	u_int32_t			 rval;
416 
417 	msg = (struct rndis_status_msg *)hdr;
418 
419 	rval = letoh32(msg->rm_status);
420 
421 	DPRINTF(("%s: urndis_ctrl_handle_status: len %u status 0x%x "
422 	    "stbuflen %u\n",
423 	    DEVNAME(sc),
424 	    letoh32(msg->rm_len),
425 	    rval,
426 	    letoh32(msg->rm_stbuflen)));
427 
428 	switch (rval) {
429 		case RNDIS_STATUS_MEDIA_CONNECT:
430 		case RNDIS_STATUS_MEDIA_DISCONNECT:
431 		case RNDIS_STATUS_OFFLOAD_CURRENT_CONFIG:
432 			rval = RNDIS_STATUS_SUCCESS;
433 			break;
434 
435 		default:
436 			printf("%s: status 0x%x\n", DEVNAME(sc), rval);
437 	}
438 
439 	return rval;
440 }
441 
442 u_int32_t
urndis_ctrl_init(struct urndis_softc * sc)443 urndis_ctrl_init(struct urndis_softc *sc)
444 {
445 	struct rndis_init_req	*msg;
446 	u_int32_t		 rval;
447 	struct rndis_comp_hdr	*hdr;
448 
449 	msg = malloc(sizeof(*msg), M_TEMP, M_WAITOK | M_CANFAIL);
450 	if (msg == NULL) {
451 		printf("%s: out of memory\n", DEVNAME(sc));
452 		return RNDIS_STATUS_FAILURE;
453 	}
454 
455 	msg->rm_type = htole32(REMOTE_NDIS_INITIALIZE_MSG);
456 	msg->rm_len = htole32(sizeof(*msg));
457 	msg->rm_rid = htole32(0);
458 	msg->rm_ver_major = htole32(1);
459 	msg->rm_ver_minor = htole32(1);
460 	msg->rm_max_xfersz = htole32(RNDIS_BUFSZ);
461 
462 	DPRINTF(("%s: urndis_ctrl_init send: type %u len %u rid %u ver_major %u "
463 	    "ver_minor %u max_xfersz %u\n",
464 	    DEVNAME(sc),
465 	    letoh32(msg->rm_type),
466 	    letoh32(msg->rm_len),
467 	    letoh32(msg->rm_rid),
468 	    letoh32(msg->rm_ver_major),
469 	    letoh32(msg->rm_ver_minor),
470 	    letoh32(msg->rm_max_xfersz)));
471 
472 	rval = urndis_ctrl_send(sc, msg, sizeof(*msg));
473 	free(msg, M_TEMP, sizeof *msg);
474 
475 	if (rval != RNDIS_STATUS_SUCCESS) {
476 		printf("%s: init failed\n", DEVNAME(sc));
477 		return rval;
478 	}
479 
480 	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
481 		printf("%s: unable to get init response\n", DEVNAME(sc));
482 		return RNDIS_STATUS_FAILURE;
483 	}
484 	rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
485 
486 	return rval;
487 }
488 
489 u_int32_t
urndis_ctrl_halt(struct urndis_softc * sc)490 urndis_ctrl_halt(struct urndis_softc *sc)
491 {
492 	struct rndis_halt_req	*msg;
493 	u_int32_t		 rval;
494 
495 	msg = malloc(sizeof(*msg), M_TEMP, M_WAITOK | M_CANFAIL);
496 	if (msg == NULL) {
497 		printf("%s: out of memory\n", DEVNAME(sc));
498 		return RNDIS_STATUS_FAILURE;
499 	}
500 
501 	msg->rm_type = htole32(REMOTE_NDIS_HALT_MSG);
502 	msg->rm_len = htole32(sizeof(*msg));
503 	msg->rm_rid = 0;
504 
505 	DPRINTF(("%s: urndis_ctrl_halt send: type %u len %u rid %u\n",
506 	    DEVNAME(sc),
507 	    letoh32(msg->rm_type),
508 	    letoh32(msg->rm_len),
509 	    letoh32(msg->rm_rid)));
510 
511 	rval = urndis_ctrl_send(sc, msg, sizeof(*msg));
512 	free(msg, M_TEMP, sizeof *msg);
513 
514 	if (rval != RNDIS_STATUS_SUCCESS)
515 		printf("%s: halt failed\n", DEVNAME(sc));
516 
517 	return rval;
518 }
519 
520 u_int32_t
urndis_ctrl_query(struct urndis_softc * sc,u_int32_t oid,void * qbuf,size_t qlen,void ** rbuf,size_t * rbufsz)521 urndis_ctrl_query(struct urndis_softc *sc, u_int32_t oid,
522     void *qbuf, size_t qlen,
523     void **rbuf, size_t *rbufsz)
524 {
525 	struct rndis_query_req	*msg;
526 	u_int32_t		 rval;
527 	struct rndis_comp_hdr	*hdr;
528 
529 	msg = malloc(sizeof(*msg) + qlen, M_TEMP, M_WAITOK | M_CANFAIL);
530 	if (msg == NULL) {
531 		printf("%s: out of memory\n", DEVNAME(sc));
532 		return RNDIS_STATUS_FAILURE;
533 	}
534 
535 	msg->rm_type = htole32(REMOTE_NDIS_QUERY_MSG);
536 	msg->rm_len = htole32(sizeof(*msg) + qlen);
537 	msg->rm_rid = 0; /* XXX */
538 	msg->rm_oid = htole32(oid);
539 	msg->rm_infobuflen = htole32(qlen);
540 	if (qlen != 0) {
541 		msg->rm_infobufoffset = htole32(20);
542 		memcpy((char*)msg + 20, qbuf, qlen);
543 	} else
544 		msg->rm_infobufoffset = 0;
545 	msg->rm_devicevchdl = 0;
546 
547 	DPRINTF(("%s: urndis_ctrl_query send: type %u len %u rid %u oid 0x%x "
548 	    "infobuflen %u infobufoffset %u devicevchdl %u\n",
549 	    DEVNAME(sc),
550 	    letoh32(msg->rm_type),
551 	    letoh32(msg->rm_len),
552 	    letoh32(msg->rm_rid),
553 	    letoh32(msg->rm_oid),
554 	    letoh32(msg->rm_infobuflen),
555 	    letoh32(msg->rm_infobufoffset),
556 	    letoh32(msg->rm_devicevchdl)));
557 
558 	rval = urndis_ctrl_send(sc, msg, sizeof(*msg));
559 	free(msg, M_TEMP, sizeof *msg + qlen);
560 
561 	if (rval != RNDIS_STATUS_SUCCESS) {
562 		printf("%s: query failed\n", DEVNAME(sc));
563 		return rval;
564 	}
565 
566 	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
567 		printf("%s: unable to get query response\n", DEVNAME(sc));
568 		return RNDIS_STATUS_FAILURE;
569 	}
570 	rval = urndis_ctrl_handle(sc, hdr, rbuf, rbufsz);
571 
572 	return rval;
573 }
574 
575 u_int32_t
urndis_ctrl_set(struct urndis_softc * sc,u_int32_t oid,void * buf,size_t len)576 urndis_ctrl_set(struct urndis_softc *sc, u_int32_t oid, void *buf, size_t len)
577 {
578 	struct rndis_set_req	*msg;
579 	u_int32_t		 rval;
580 	struct rndis_comp_hdr	*hdr;
581 
582 	msg = malloc(sizeof(*msg) + len, M_TEMP, M_WAITOK | M_CANFAIL);
583 	if (msg == NULL) {
584 		printf("%s: out of memory\n", DEVNAME(sc));
585 		return RNDIS_STATUS_FAILURE;
586 	}
587 
588 	msg->rm_type = htole32(REMOTE_NDIS_SET_MSG);
589 	msg->rm_len = htole32(sizeof(*msg) + len);
590 	msg->rm_rid = 0; /* XXX */
591 	msg->rm_oid = htole32(oid);
592 	msg->rm_infobuflen = htole32(len);
593 	if (len != 0) {
594 		msg->rm_infobufoffset = htole32(20);
595 		memcpy((char*)msg + 28, buf, len);
596 	} else
597 		msg->rm_infobufoffset = 0;
598 	msg->rm_devicevchdl = 0;
599 
600 	DPRINTF(("%s: urndis_ctrl_set send: type %u len %u rid %u oid 0x%x "
601 	    "infobuflen %u infobufoffset %u devicevchdl %u\n",
602 	    DEVNAME(sc),
603 	    letoh32(msg->rm_type),
604 	    letoh32(msg->rm_len),
605 	    letoh32(msg->rm_rid),
606 	    letoh32(msg->rm_oid),
607 	    letoh32(msg->rm_infobuflen),
608 	    letoh32(msg->rm_infobufoffset),
609 	    letoh32(msg->rm_devicevchdl)));
610 
611 	rval = urndis_ctrl_send(sc, msg, sizeof(*msg) + len);
612 	free(msg, M_TEMP, sizeof *msg + len);
613 
614 	if (rval != RNDIS_STATUS_SUCCESS) {
615 		printf("%s: set failed\n", DEVNAME(sc));
616 		return rval;
617 	}
618 
619 	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
620 		printf("%s: unable to get set response\n", DEVNAME(sc));
621 		return RNDIS_STATUS_FAILURE;
622 	}
623 	rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
624 	if (rval != RNDIS_STATUS_SUCCESS)
625 		printf("%s: set failed 0x%x\n", DEVNAME(sc), rval);
626 
627 	return rval;
628 }
629 
630 u_int32_t
urndis_ctrl_set_param(struct urndis_softc * sc,const char * name,u_int32_t type,void * buf,size_t len)631 urndis_ctrl_set_param(struct urndis_softc *sc,
632     const char *name,
633     u_int32_t type,
634     void *buf,
635     size_t len)
636 {
637 	struct rndis_set_parameter	*param;
638 	u_int32_t			 rval;
639 	size_t				 namelen, tlen;
640 
641 	if (name)
642 		namelen = strlen(name);
643 	else
644 		namelen = 0;
645 	tlen = sizeof(*param) + len + namelen;
646 	param = malloc(tlen, M_TEMP, M_WAITOK | M_CANFAIL);
647 	if (param == NULL) {
648 		printf("%s: out of memory\n", DEVNAME(sc));
649 		return RNDIS_STATUS_FAILURE;
650 	}
651 
652 	param->rm_namelen = htole32(namelen);
653 	param->rm_valuelen = htole32(len);
654 	param->rm_type = htole32(type);
655 	if (namelen != 0) {
656 		param->rm_nameoffset = htole32(20);
657 		memcpy(param + 20, name, namelen);
658 	} else
659 		param->rm_nameoffset = 0;
660 	if (len != 0) {
661 		param->rm_valueoffset = htole32(20 + namelen);
662 		memcpy(param + 20 + namelen, buf, len);
663 	} else
664 		param->rm_valueoffset = 0;
665 
666 	DPRINTF(("%s: urndis_ctrl_set_param send: nameoffset %u namelen %u "
667 	    "type 0x%x valueoffset %u valuelen %u\n",
668 	    DEVNAME(sc),
669 	    letoh32(param->rm_nameoffset),
670 	    letoh32(param->rm_namelen),
671 	    letoh32(param->rm_type),
672 	    letoh32(param->rm_valueoffset),
673 	    letoh32(param->rm_valuelen)));
674 
675 	rval = urndis_ctrl_set(sc, OID_GEN_RNDIS_CONFIG_PARAMETER, param, tlen);
676 	free(param, M_TEMP, tlen);
677 	if (rval != RNDIS_STATUS_SUCCESS)
678 		printf("%s: set param failed 0x%x\n", DEVNAME(sc), rval);
679 
680 	return rval;
681 }
682 
683 #if 0
684 /* XXX : adrreset, get it from response */
685 u_int32_t
686 urndis_ctrl_reset(struct urndis_softc *sc)
687 {
688 	struct rndis_reset_req		*reset;
689 	u_int32_t			 rval;
690 	struct rndis_comp_hdr		*hdr;
691 
692 	reset = malloc(sizeof(*reset), M_TEMP, M_WAITOK | M_CANFAIL);
693 	if (reset == NULL) {
694 		printf("%s: out of memory\n", DEVNAME(sc));
695 		return RNDIS_STATUS_FAILURE;
696 	}
697 
698 	reset->rm_type = htole32(REMOTE_NDIS_RESET_MSG);
699 	reset->rm_len = htole32(sizeof(*reset));
700 	reset->rm_rid = 0; /* XXX rm_rid == reserved ... remove ? */
701 
702 	DPRINTF(("%s: urndis_ctrl_reset send: type %u len %u rid %u\n",
703 	    DEVNAME(sc),
704 	    letoh32(reset->rm_type),
705 	    letoh32(reset->rm_len),
706 	    letoh32(reset->rm_rid)));
707 
708 	rval = urndis_ctrl_send(sc, reset, sizeof(*reset));
709 	free(reset, M_TEMP, sizeof *reset);
710 
711 	if (rval != RNDIS_STATUS_SUCCESS) {
712 		printf("%s: reset failed\n", DEVNAME(sc));
713 		return rval;
714 	}
715 
716 	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
717 		printf("%s: unable to get reset response\n", DEVNAME(sc));
718 		return RNDIS_STATUS_FAILURE;
719 	}
720 	rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
721 
722 	return rval;
723 }
724 
725 u_int32_t
726 urndis_ctrl_keepalive(struct urndis_softc *sc)
727 {
728 	struct rndis_keepalive_req	*keep;
729 	u_int32_t			 rval;
730 	struct rndis_comp_hdr		*hdr;
731 
732 	keep = malloc(sizeof(*keep), M_TEMP, M_WAITOK | M_CANFAIL);
733 	if (keep == NULL) {
734 		printf("%s: out of memory\n", DEVNAME(sc));
735 		return RNDIS_STATUS_FAILURE;
736 	}
737 
738 	keep->rm_type = htole32(REMOTE_NDIS_KEEPALIVE_MSG);
739 	keep->rm_len = htole32(sizeof(*keep));
740 	keep->rm_rid = 0; /* XXX rm_rid == reserved ... remove ? */
741 
742 	DPRINTF(("%s: urndis_ctrl_keepalive: type %u len %u rid %u\n",
743 	    DEVNAME(sc),
744 	    letoh32(keep->rm_type),
745 	    letoh32(keep->rm_len),
746 	    letoh32(keep->rm_rid)));
747 
748 	rval = urndis_ctrl_send(sc, keep, sizeof(*keep));
749 	free(keep, M_TEMP, sizeof *keep);
750 
751 	if (rval != RNDIS_STATUS_SUCCESS) {
752 		printf("%s: keepalive failed\n", DEVNAME(sc));
753 		return rval;
754 	}
755 
756 	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
757 		printf("%s: unable to get keepalive response\n", DEVNAME(sc));
758 		return RNDIS_STATUS_FAILURE;
759 	}
760 	rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
761 	if (rval != RNDIS_STATUS_SUCCESS) {
762 		printf("%s: keepalive failed 0x%x\n", DEVNAME(sc), rval);
763 		urndis_ctrl_reset(sc);
764 	}
765 
766 	return rval;
767 }
768 #endif
769 
770 int
urndis_encap(struct urndis_softc * sc,struct mbuf * m,int idx)771 urndis_encap(struct urndis_softc *sc, struct mbuf *m, int idx)
772 {
773 	struct urndis_chain		*c;
774 	usbd_status			 err;
775 	struct rndis_packet_msg		*msg;
776 
777 	c = &sc->sc_data.sc_tx_chain[idx];
778 
779 	msg = (struct rndis_packet_msg *)c->sc_buf;
780 
781 	memset(msg, 0, sizeof(*msg));
782 	msg->rm_type = htole32(REMOTE_NDIS_PACKET_MSG);
783 	msg->rm_len = htole32(sizeof(*msg) + m->m_pkthdr.len);
784 
785 	msg->rm_dataoffset = htole32(RNDIS_DATA_OFFSET);
786 	msg->rm_datalen = htole32(m->m_pkthdr.len);
787 
788 	m_copydata(m, 0, m->m_pkthdr.len,
789 	    ((char*)msg + RNDIS_DATA_OFFSET + RNDIS_HEADER_OFFSET));
790 
791 	DPRINTF(("%s: urndis_encap type 0x%x len %u data(off %u len %u)\n",
792 	    DEVNAME(sc),
793 	    letoh32(msg->rm_type),
794 	    letoh32(msg->rm_len),
795 	    letoh32(msg->rm_dataoffset),
796 	    letoh32(msg->rm_datalen)));
797 
798 	c->sc_mbuf = m;
799 
800 	usbd_setup_xfer(c->sc_xfer, sc->sc_bulkout_pipe, c, c->sc_buf,
801 	    letoh32(msg->rm_len), USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 10000,
802 	    urndis_txeof);
803 
804 	/* Transmit */
805 	err = usbd_transfer(c->sc_xfer);
806 	if (err != USBD_IN_PROGRESS) {
807 		c->sc_mbuf = NULL;
808 		urndis_stop(sc);
809 		return(EIO);
810 	}
811 
812 	sc->sc_data.sc_tx_cnt++;
813 
814 	return(0);
815 }
816 
817 void
urndis_decap(struct urndis_softc * sc,struct urndis_chain * c,u_int32_t len)818 urndis_decap(struct urndis_softc *sc, struct urndis_chain *c, u_int32_t len)
819 {
820 	struct mbuf		*m;
821 	struct mbuf_list	 ml = MBUF_LIST_INITIALIZER();
822 	struct rndis_packet_msg	*msg;
823 	struct ifnet		*ifp;
824 	int			 s;
825 	int			 offset;
826 
827 	ifp = GET_IFP(sc);
828 	offset = 0;
829 
830 	while (len > 1) {
831 		msg = (struct rndis_packet_msg *)((char*)c->sc_buf + offset);
832 		m = c->sc_mbuf;
833 
834 		DPRINTF(("%s: urndis_decap buffer size left %u\n", DEVNAME(sc),
835 		    len));
836 
837 		if (len < sizeof(*msg)) {
838 			printf("%s: urndis_decap invalid buffer len %u < "
839 			    "minimum header %zu\n",
840 			    DEVNAME(sc),
841 			    len,
842 			    sizeof(*msg));
843 			break;
844 		}
845 
846 		DPRINTF(("%s: urndis_decap len %u data(off:%u len:%u) "
847 		    "oobdata(off:%u len:%u nb:%u) perpacket(off:%u len:%u)\n",
848 		    DEVNAME(sc),
849 		    letoh32(msg->rm_len),
850 		    letoh32(msg->rm_dataoffset),
851 		    letoh32(msg->rm_datalen),
852 		    letoh32(msg->rm_oobdataoffset),
853 		    letoh32(msg->rm_oobdatalen),
854 		    letoh32(msg->rm_oobdataelements),
855 		    letoh32(msg->rm_pktinfooffset),
856 		    letoh32(msg->rm_pktinfooffset)));
857 
858 		if (letoh32(msg->rm_type) != REMOTE_NDIS_PACKET_MSG) {
859 			printf("%s: urndis_decap invalid type 0x%x != 0x%x\n",
860 			    DEVNAME(sc),
861 			    letoh32(msg->rm_type),
862 			    REMOTE_NDIS_PACKET_MSG);
863 			break;
864 		}
865 		if (letoh32(msg->rm_len) < sizeof(*msg)) {
866 			printf("%s: urndis_decap invalid msg len %u < %zu\n",
867 			    DEVNAME(sc),
868 			    letoh32(msg->rm_len),
869 			    sizeof(*msg));
870 			break;
871 		}
872 		if (letoh32(msg->rm_len) > len) {
873 			printf("%s: urndis_decap invalid msg len %u > buffer "
874 			    "len %u\n",
875 			    DEVNAME(sc),
876 			    letoh32(msg->rm_len),
877 			    len);
878 			break;
879 		}
880 
881 		if (letoh32(msg->rm_dataoffset) +
882 		    letoh32(msg->rm_datalen) + RNDIS_HEADER_OFFSET
883 			> letoh32(msg->rm_len)) {
884 			printf("%s: urndis_decap invalid data "
885 			    "len/offset/end_position(%u/%u/%zu) -> "
886 			    "go out of receive buffer limit %u\n",
887 			    DEVNAME(sc),
888 			    letoh32(msg->rm_datalen),
889 			    letoh32(msg->rm_dataoffset),
890 			    letoh32(msg->rm_dataoffset) +
891 			    letoh32(msg->rm_datalen) + RNDIS_HEADER_OFFSET,
892 			    letoh32(msg->rm_len));
893 			break;
894 		}
895 
896 		if (letoh32(msg->rm_datalen) < sizeof(struct ether_header)) {
897 			ifp->if_ierrors++;
898 			DPRINTF(("%s: urndis_decap invalid ethernet size "
899 			    "%u < %zu\n",
900 			    DEVNAME(sc),
901 			    letoh32(msg->rm_datalen),
902 			    sizeof(struct ether_header)));
903 			break;
904 		}
905 
906 		memcpy(mtod(m, char*),
907 		    ((char*)&msg->rm_dataoffset + letoh32(msg->rm_dataoffset)),
908 		    letoh32(msg->rm_datalen));
909 		m->m_pkthdr.len = m->m_len = letoh32(msg->rm_datalen);
910 
911 		if (urndis_newbuf(sc, c) == ENOBUFS) {
912 			ifp->if_ierrors++;
913 		} else {
914 			ml_enqueue(&ml, m);
915 		}
916 
917 		offset += letoh32(msg->rm_len);
918 		len -= letoh32(msg->rm_len);
919 	}
920 	if (ml_empty(&ml))
921 		return;
922 
923 	s = splnet();
924 	if_input(ifp, &ml);
925 	splx(s);
926 }
927 
928 int
urndis_newbuf(struct urndis_softc * sc,struct urndis_chain * c)929 urndis_newbuf(struct urndis_softc *sc, struct urndis_chain *c)
930 {
931 	struct mbuf *m_new = NULL;
932 
933 	MGETHDR(m_new, M_DONTWAIT, MT_DATA);
934 	if (m_new == NULL) {
935 		printf("%s: no memory for rx list -- packet dropped!\n",
936 		    DEVNAME(sc));
937 		return (ENOBUFS);
938 	}
939 	MCLGET(m_new, M_DONTWAIT);
940 	if (!(m_new->m_flags & M_EXT)) {
941 		printf("%s: no memory for rx list -- packet dropped!\n",
942 		    DEVNAME(sc));
943 		m_freem(m_new);
944 		return (ENOBUFS);
945 	}
946 	m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
947 
948 	m_adj(m_new, ETHER_ALIGN);
949 	c->sc_mbuf = m_new;
950 	return (0);
951 }
952 
953 int
urndis_rx_list_init(struct urndis_softc * sc)954 urndis_rx_list_init(struct urndis_softc *sc)
955 {
956 	struct urndis_cdata	*cd;
957 	struct urndis_chain	*c;
958 	int			 i;
959 
960 	cd = &sc->sc_data;
961 	for (i = 0; i < RNDIS_RX_LIST_CNT; i++) {
962 		c = &cd->sc_rx_chain[i];
963 		c->sc_softc = sc;
964 		c->sc_idx = i;
965 
966 		if (urndis_newbuf(sc, c) == ENOBUFS)
967 			return (ENOBUFS);
968 
969 		if (c->sc_xfer == NULL) {
970 			c->sc_xfer = usbd_alloc_xfer(sc->sc_udev);
971 			if (c->sc_xfer == NULL)
972 				return (ENOBUFS);
973 			c->sc_buf = usbd_alloc_buffer(c->sc_xfer,
974 			    RNDIS_BUFSZ);
975 			if (c->sc_buf == NULL)
976 				return (ENOBUFS);
977 		}
978 	}
979 
980 	return (0);
981 }
982 
983 int
urndis_tx_list_init(struct urndis_softc * sc)984 urndis_tx_list_init(struct urndis_softc *sc)
985 {
986 	struct urndis_cdata	*cd;
987 	struct urndis_chain	*c;
988 	int			 i;
989 
990 	cd = &sc->sc_data;
991 	for (i = 0; i < RNDIS_TX_LIST_CNT; i++) {
992 		c = &cd->sc_tx_chain[i];
993 		c->sc_softc = sc;
994 		c->sc_idx = i;
995 		c->sc_mbuf = NULL;
996 		if (c->sc_xfer == NULL) {
997 			c->sc_xfer = usbd_alloc_xfer(sc->sc_udev);
998 			if (c->sc_xfer == NULL)
999 				return (ENOBUFS);
1000 			c->sc_buf = usbd_alloc_buffer(c->sc_xfer,
1001 			    RNDIS_BUFSZ);
1002 			if (c->sc_buf == NULL)
1003 				return (ENOBUFS);
1004 		}
1005 	}
1006 	return (0);
1007 }
1008 
1009 int
urndis_ioctl(struct ifnet * ifp,u_long command,caddr_t data)1010 urndis_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1011 {
1012 	struct urndis_softc	*sc = ifp->if_softc;
1013 	int			 s, error = 0;
1014 
1015 	if (usbd_is_dying(sc->sc_udev))
1016 		return ENXIO;
1017 
1018 	s = splnet();
1019 
1020 	switch(command) {
1021 	case SIOCSIFADDR:
1022 		ifp->if_flags |= IFF_UP;
1023 		if (!(ifp->if_flags & IFF_RUNNING))
1024 			urndis_init(sc);
1025 		break;
1026 
1027 	case SIOCSIFFLAGS:
1028 		if (ifp->if_flags & IFF_UP) {
1029 			if (ifp->if_flags & IFF_RUNNING)
1030 				error = ENETRESET;
1031 			else
1032 				urndis_init(sc);
1033 		} else {
1034 			if (ifp->if_flags & IFF_RUNNING)
1035 				urndis_stop(sc);
1036 		}
1037 		break;
1038 
1039 	default:
1040 		error = ether_ioctl(ifp, &sc->sc_arpcom, command, data);
1041 		break;
1042 	}
1043 
1044 	if (error == ENETRESET)
1045 		error = 0;
1046 
1047 	splx(s);
1048 	return (error);
1049 }
1050 
1051 #if 0
1052 void
1053 urndis_watchdog(struct ifnet *ifp)
1054 {
1055 	struct urndis_softc *sc;
1056 
1057 	sc = ifp->if_softc;
1058 
1059 	if (usbd_is_dying(sc->sc_udev))
1060 		return;
1061 
1062 	ifp->if_oerrors++;
1063 	printf("%s: watchdog timeout\n", DEVNAME(sc));
1064 
1065 	urndis_ctrl_keepalive(sc);
1066 }
1067 #endif
1068 
1069 void
urndis_init(struct urndis_softc * sc)1070 urndis_init(struct urndis_softc *sc)
1071 {
1072 	struct ifnet		*ifp = GET_IFP(sc);
1073 	int			 i, s;
1074 	usbd_status		 err;
1075 
1076 	if (urndis_ctrl_init(sc) != RNDIS_STATUS_SUCCESS)
1077 		return;
1078 
1079 	s = splnet();
1080 
1081 	if (urndis_tx_list_init(sc) == ENOBUFS) {
1082 		printf("%s: tx list init failed\n",
1083 		    DEVNAME(sc));
1084 		splx(s);
1085 		return;
1086 	}
1087 
1088 	if (urndis_rx_list_init(sc) == ENOBUFS) {
1089 		printf("%s: rx list init failed\n",
1090 		    DEVNAME(sc));
1091 		splx(s);
1092 		return;
1093 	}
1094 
1095 	err = usbd_open_pipe(sc->sc_iface_data, sc->sc_bulkin_no,
1096 	    USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
1097 	if (err) {
1098 		printf("%s: open rx pipe failed: %s\n", DEVNAME(sc),
1099 		    usbd_errstr(err));
1100 		splx(s);
1101 		return;
1102 	}
1103 
1104 	err = usbd_open_pipe(sc->sc_iface_data, sc->sc_bulkout_no,
1105 	    USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
1106 	if (err) {
1107 		printf("%s: open tx pipe failed: %s\n", DEVNAME(sc),
1108 		    usbd_errstr(err));
1109 		splx(s);
1110 		return;
1111 	}
1112 
1113 	for (i = 0; i < RNDIS_RX_LIST_CNT; i++) {
1114 		struct urndis_chain *c;
1115 
1116 		c = &sc->sc_data.sc_rx_chain[i];
1117 		usbd_setup_xfer(c->sc_xfer, sc->sc_bulkin_pipe, c,
1118 		    c->sc_buf, RNDIS_BUFSZ,
1119 		    USBD_SHORT_XFER_OK | USBD_NO_COPY,
1120 		    USBD_NO_TIMEOUT, urndis_rxeof);
1121 		usbd_transfer(c->sc_xfer);
1122 	}
1123 
1124 	ifp->if_flags |= IFF_RUNNING;
1125 	ifq_clr_oactive(&ifp->if_snd);
1126 
1127 	splx(s);
1128 }
1129 
1130 void
urndis_stop(struct urndis_softc * sc)1131 urndis_stop(struct urndis_softc *sc)
1132 {
1133 	usbd_status	 err;
1134 	struct ifnet	*ifp;
1135 	int		 i;
1136 
1137 	ifp = GET_IFP(sc);
1138 	ifp->if_timer = 0;
1139 	ifp->if_flags &= ~IFF_RUNNING;
1140 	ifq_clr_oactive(&ifp->if_snd);
1141 
1142 	if (sc->sc_bulkin_pipe != NULL) {
1143 		err = usbd_close_pipe(sc->sc_bulkin_pipe);
1144 		if (err)
1145 			printf("%s: close rx pipe failed: %s\n",
1146 			    DEVNAME(sc), usbd_errstr(err));
1147 		sc->sc_bulkin_pipe = NULL;
1148 	}
1149 
1150 	if (sc->sc_bulkout_pipe != NULL) {
1151 		err = usbd_close_pipe(sc->sc_bulkout_pipe);
1152 		if (err)
1153 			printf("%s: close tx pipe failed: %s\n",
1154 			    DEVNAME(sc), usbd_errstr(err));
1155 		sc->sc_bulkout_pipe = NULL;
1156 	}
1157 
1158 	for (i = 0; i < RNDIS_RX_LIST_CNT; i++) {
1159 		if (sc->sc_data.sc_rx_chain[i].sc_mbuf != NULL) {
1160 			m_freem(sc->sc_data.sc_rx_chain[i].sc_mbuf);
1161 			sc->sc_data.sc_rx_chain[i].sc_mbuf = NULL;
1162 		}
1163 		if (sc->sc_data.sc_rx_chain[i].sc_xfer != NULL) {
1164 			usbd_free_xfer(sc->sc_data.sc_rx_chain[i].sc_xfer);
1165 			sc->sc_data.sc_rx_chain[i].sc_xfer = NULL;
1166 		}
1167 	}
1168 
1169 	for (i = 0; i < RNDIS_TX_LIST_CNT; i++) {
1170 		if (sc->sc_data.sc_tx_chain[i].sc_mbuf != NULL) {
1171 			m_freem(sc->sc_data.sc_tx_chain[i].sc_mbuf);
1172 			sc->sc_data.sc_tx_chain[i].sc_mbuf = NULL;
1173 		}
1174 		if (sc->sc_data.sc_tx_chain[i].sc_xfer != NULL) {
1175 			usbd_free_xfer(sc->sc_data.sc_tx_chain[i].sc_xfer);
1176 			sc->sc_data.sc_tx_chain[i].sc_xfer = NULL;
1177 		}
1178 	}
1179 }
1180 
1181 void
urndis_start(struct ifnet * ifp)1182 urndis_start(struct ifnet *ifp)
1183 {
1184 	struct urndis_softc	*sc;
1185 	struct mbuf		*m_head = NULL;
1186 
1187 	sc = ifp->if_softc;
1188 
1189 	if (usbd_is_dying(sc->sc_udev) || ifq_is_oactive(&ifp->if_snd))
1190 		return;
1191 
1192 	m_head = ifq_dequeue(&ifp->if_snd);
1193 	if (m_head == NULL)
1194 		return;
1195 
1196 	if (urndis_encap(sc, m_head, 0)) {
1197 		m_freem(m_head);
1198 		ifq_set_oactive(&ifp->if_snd);
1199 		return;
1200 	}
1201 
1202 	/*
1203 	 * If there's a BPF listener, bounce a copy of this frame
1204 	 * to him.
1205 	 */
1206 #if NBPFILTER > 0
1207 	if (ifp->if_bpf)
1208 		bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
1209 #endif
1210 
1211 	ifq_set_oactive(&ifp->if_snd);
1212 
1213 	/*
1214 	 * Set a timeout in case the chip goes out to lunch.
1215 	 */
1216 	ifp->if_timer = 5;
1217 
1218 	return;
1219 }
1220 
1221 void
urndis_rxeof(struct usbd_xfer * xfer,void * priv,usbd_status status)1222 urndis_rxeof(struct usbd_xfer *xfer,
1223     void *priv,
1224     usbd_status status)
1225 {
1226 	struct urndis_chain	*c;
1227 	struct urndis_softc	*sc;
1228 	struct ifnet		*ifp;
1229 	u_int32_t		 total_len;
1230 
1231 	c = priv;
1232 	sc = c->sc_softc;
1233 	ifp = GET_IFP(sc);
1234 	total_len = 0;
1235 
1236 	if (usbd_is_dying(sc->sc_udev) || !(ifp->if_flags & IFF_RUNNING))
1237 		return;
1238 
1239 	if (status != USBD_NORMAL_COMPLETION) {
1240 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
1241 			return;
1242 		if (usbd_ratecheck(&sc->sc_rx_notice)) {
1243 			DPRINTF(("%s: usb errors on rx: %s\n",
1244 			    DEVNAME(sc), usbd_errstr(status)));
1245 		}
1246 		if (status == USBD_STALLED)
1247 			usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
1248 
1249 		ifp->if_ierrors++;
1250 		goto done;
1251 	}
1252 
1253 	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
1254 	urndis_decap(sc, c, total_len);
1255 
1256 done:
1257 	/* Setup new transfer. */
1258 	usbd_setup_xfer(c->sc_xfer, sc->sc_bulkin_pipe, c, c->sc_buf,
1259 	    RNDIS_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
1260 	    urndis_rxeof);
1261 	usbd_transfer(c->sc_xfer);
1262 }
1263 
1264 void
urndis_txeof(struct usbd_xfer * xfer,void * priv,usbd_status status)1265 urndis_txeof(struct usbd_xfer *xfer,
1266     void *priv,
1267     usbd_status status)
1268 {
1269 	struct urndis_chain	*c;
1270 	struct urndis_softc	*sc;
1271 	struct ifnet		*ifp;
1272 	usbd_status		 err;
1273 	int			 s;
1274 
1275 	c = priv;
1276 	sc = c->sc_softc;
1277 	ifp = GET_IFP(sc);
1278 
1279 	DPRINTF(("%s: urndis_txeof\n", DEVNAME(sc)));
1280 
1281 	if (usbd_is_dying(sc->sc_udev))
1282 		return;
1283 
1284 	s = splnet();
1285 
1286 	ifp->if_timer = 0;
1287 	ifq_clr_oactive(&ifp->if_snd);
1288 
1289 	if (status != USBD_NORMAL_COMPLETION) {
1290 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
1291 			splx(s);
1292 			return;
1293 		}
1294 		ifp->if_oerrors++;
1295 		DPRINTF(("%s: usb error on tx: %s\n", DEVNAME(sc),
1296 		    usbd_errstr(status)));
1297 		if (status == USBD_STALLED)
1298 			usbd_clear_endpoint_stall_async(sc->sc_bulkout_pipe);
1299 		splx(s);
1300 		return;
1301 	}
1302 
1303 	usbd_get_xfer_status(c->sc_xfer, NULL, NULL, NULL, &err);
1304 
1305 	if (c->sc_mbuf != NULL) {
1306 		m_freem(c->sc_mbuf);
1307 		c->sc_mbuf = NULL;
1308 	}
1309 
1310 	if (err)
1311 		ifp->if_oerrors++;
1312 
1313 	if (ifq_empty(&ifp->if_snd) == 0)
1314 		urndis_start(ifp);
1315 
1316 	splx(s);
1317 }
1318 
1319 const struct urndis_class *
urndis_lookup(usb_interface_descriptor_t * id)1320 urndis_lookup(usb_interface_descriptor_t *id)
1321 {
1322 	const struct urndis_class	*uc;
1323 	int				 i;
1324 
1325 	uc = urndis_class;
1326 	for (i = 0; i < nitems(urndis_class); i++, uc++) {
1327 		if (uc->class == id->bInterfaceClass &&
1328 		    uc->subclass == id->bInterfaceSubClass &&
1329 		    uc->protocol == id->bInterfaceProtocol)
1330 			return (uc);
1331 	}
1332 	return (NULL);
1333 }
1334 
1335 int
urndis_match(struct device * parent,void * match,void * aux)1336 urndis_match(struct device *parent, void *match, void *aux)
1337 {
1338 	struct usb_attach_arg		*uaa = aux;
1339 	usb_interface_descriptor_t	*id;
1340 
1341 	/* Advertises both RNDIS and CDC Ethernet, but RNDIS doesn't work. */
1342 	if (uaa->vendor == USB_VENDOR_FUJITSUCOMP &&
1343 	    uaa->product == USB_PRODUCT_FUJITSUCOMP_VIRTETH)
1344 		return (UMATCH_NONE);
1345 
1346 	if (!uaa->iface)
1347 		return (UMATCH_NONE);
1348 
1349 	id = usbd_get_interface_descriptor(uaa->iface);
1350 	if (id == NULL)
1351 		return (UMATCH_NONE);
1352 
1353 	return (urndis_lookup(id) ?
1354 	    UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO : UMATCH_NONE);
1355 }
1356 
1357 void
urndis_attach(struct device * parent,struct device * self,void * aux)1358 urndis_attach(struct device *parent, struct device *self, void *aux)
1359 {
1360 	const struct urndis_class	*uc;
1361 	struct urndis_softc		*sc;
1362 	struct usb_attach_arg		*uaa;
1363 	struct ifnet			*ifp;
1364 	usb_interface_descriptor_t	*id;
1365 	usb_endpoint_descriptor_t	*ed;
1366 	usb_config_descriptor_t		*cd;
1367 	int				 i, j, altcnt;
1368 	int				 s;
1369 	u_char				 eaddr[ETHER_ADDR_LEN];
1370 	void				*buf;
1371 	size_t				 bufsz;
1372 	u_int32_t			 filter;
1373 
1374 	sc = (void *)self;
1375 	uaa = aux;
1376 
1377 	sc->sc_attached = 0;
1378 	sc->sc_udev = uaa->device;
1379 	id = usbd_get_interface_descriptor(uaa->iface);
1380 	sc->sc_ifaceno_ctl = id->bInterfaceNumber;
1381 
1382 	for (i = 0; i < uaa->nifaces; i++) {
1383 		if (usbd_iface_claimed(sc->sc_udev, i))
1384 			continue;
1385 
1386 		if (uaa->ifaces[i] != uaa->iface) {
1387 			sc->sc_iface_data = uaa->ifaces[i];
1388 			usbd_claim_iface(sc->sc_udev, i);
1389 			break;
1390 		}
1391 	}
1392 
1393 	if (sc->sc_iface_data == NULL) {
1394 		printf("%s: no data interface\n", DEVNAME(sc));
1395 		return;
1396 	}
1397 
1398 	uc = urndis_lookup(id);
1399 	printf("%s: using %s", DEVNAME(sc), uc->typestr);
1400 
1401 	id = usbd_get_interface_descriptor(sc->sc_iface_data);
1402 	cd = usbd_get_config_descriptor(sc->sc_udev);
1403 	altcnt = usbd_get_no_alts(cd, id->bInterfaceNumber);
1404 
1405 	for (j = 0; j < altcnt; j++) {
1406 		if (usbd_set_interface(sc->sc_iface_data, j)) {
1407 			printf(": interface alternate setting %u failed\n", j);
1408 			return;
1409 		}
1410 		/* Find endpoints. */
1411 		id = usbd_get_interface_descriptor(sc->sc_iface_data);
1412 		sc->sc_bulkin_no = sc->sc_bulkout_no = -1;
1413 		for (i = 0; i < id->bNumEndpoints; i++) {
1414 			ed = usbd_interface2endpoint_descriptor(
1415 			    sc->sc_iface_data, i);
1416 			if (!ed) {
1417 				printf(": no descriptor for bulk endpoint "
1418 				    "%u\n", i);
1419 				return;
1420 			}
1421 			if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
1422 			    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
1423 				sc->sc_bulkin_no = ed->bEndpointAddress;
1424 			}
1425 			else if (
1426 			    UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
1427 			    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
1428 				sc->sc_bulkout_no = ed->bEndpointAddress;
1429 			}
1430 		}
1431 
1432 		if (sc->sc_bulkin_no != -1 && sc->sc_bulkout_no != -1) {
1433 			DPRINTF(("%s: in=0x%x, out=0x%x\n",
1434 			    DEVNAME(sc),
1435 			    sc->sc_bulkin_no,
1436 			    sc->sc_bulkout_no));
1437 			goto found;
1438 		}
1439 	}
1440 
1441 	if (sc->sc_bulkin_no == -1)
1442 		printf(": could not find data bulk in\n");
1443 	if (sc->sc_bulkout_no == -1 )
1444 		printf(": could not find data bulk out\n");
1445 	return;
1446 
1447 	found:
1448 
1449 	ifp = GET_IFP(sc);
1450 	ifp->if_softc = sc;
1451 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1452 	ifp->if_start = urndis_start;
1453 	ifp->if_ioctl = urndis_ioctl;
1454 #if 0
1455 	ifp->if_watchdog = urndis_watchdog;
1456 #endif
1457 
1458 	strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
1459 
1460 	s = splnet();
1461 
1462 	if (urndis_ctrl_query(sc, OID_802_3_PERMANENT_ADDRESS, NULL, 0,
1463 	    &buf, &bufsz) != RNDIS_STATUS_SUCCESS) {
1464 		printf(": unable to get hardware address\n");
1465 		splx(s);
1466 		return;
1467 	}
1468 
1469 	if (bufsz == ETHER_ADDR_LEN) {
1470 		memcpy(eaddr, buf, ETHER_ADDR_LEN);
1471 		printf(", address %s\n", ether_sprintf(eaddr));
1472 		free(buf, M_TEMP, bufsz);
1473 	} else {
1474 		printf(", invalid address\n");
1475 		free(buf, M_TEMP, bufsz);
1476 		splx(s);
1477 		return;
1478 	}
1479 
1480 	/* Initialize packet filter */
1481 	sc->sc_filter = NDIS_PACKET_TYPE_BROADCAST;
1482 	sc->sc_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
1483 	filter = htole32(sc->sc_filter);
1484 	if (urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER, &filter,
1485 	    sizeof(filter)) != RNDIS_STATUS_SUCCESS) {
1486 		printf("%s: unable to set data filters\n", DEVNAME(sc));
1487 		splx(s);
1488 		return;
1489 	}
1490 
1491 	bcopy(eaddr, (char *)&sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
1492 
1493 	if_attach(ifp);
1494 	ether_ifattach(ifp);
1495 	sc->sc_attached = 1;
1496 
1497 	splx(s);
1498 }
1499 
1500 int
urndis_detach(struct device * self,int flags)1501 urndis_detach(struct device *self, int flags)
1502 {
1503 	struct urndis_softc	*sc;
1504 	struct ifnet		*ifp;
1505 	int			 s;
1506 
1507 	sc = (void*)self;
1508 
1509 	DPRINTF(("urndis_detach: %s flags %u\n", DEVNAME(sc),
1510 	    flags));
1511 
1512 	if (!sc->sc_attached)
1513 		return 0;
1514 
1515 	s = splusb();
1516 
1517 	ifp = GET_IFP(sc);
1518 
1519 	if (ifp->if_softc != NULL) {
1520 		ether_ifdetach(ifp);
1521 		if_detach(ifp);
1522 	}
1523 
1524 	urndis_stop(sc);
1525 	sc->sc_attached = 0;
1526 
1527 	splx(s);
1528 
1529 	return 0;
1530 }
1531