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