1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2010 Hans Petter Selasky. All rights reserved. 5 * Copyright (c) 2009 Diego Giagio. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 /* 30 * Thanks to Diego Giagio for figuring out the programming details for 31 * the Apple iPhone Ethernet driver. 32 */ 33 34 #include <sys/stdint.h> 35 #include <sys/stddef.h> 36 #include <sys/param.h> 37 #include <sys/queue.h> 38 #include <sys/types.h> 39 #include <sys/systm.h> 40 #include <sys/kernel.h> 41 #include <sys/bus.h> 42 #include <sys/module.h> 43 #include <sys/lock.h> 44 #include <sys/mutex.h> 45 #include <sys/condvar.h> 46 #include <sys/socket.h> 47 #include <sys/sysctl.h> 48 #include <sys/sx.h> 49 #include <sys/unistd.h> 50 #include <sys/callout.h> 51 #include <sys/malloc.h> 52 #include <sys/priv.h> 53 54 #include <net/if.h> 55 #include <net/if_var.h> 56 57 #include <dev/usb/usb.h> 58 #include <dev/usb/usb_cdc.h> 59 #include <dev/usb/usbdi.h> 60 #include <dev/usb/usbdi_util.h> 61 #include "usbdevs.h" 62 63 #define USB_DEBUG_VAR ipheth_debug 64 #include <dev/usb/usb_debug.h> 65 #include <dev/usb/usb_process.h> 66 67 #include <dev/usb/net/usb_ethernet.h> 68 #include <dev/usb/net/if_iphethvar.h> 69 70 static device_probe_t ipheth_probe; 71 static device_attach_t ipheth_attach; 72 static device_detach_t ipheth_detach; 73 74 static usb_callback_t ipheth_bulk_write_callback; 75 static usb_callback_t ipheth_bulk_read_callback; 76 77 static uether_fn_t ipheth_attach_post; 78 static uether_fn_t ipheth_tick; 79 static uether_fn_t ipheth_init; 80 static uether_fn_t ipheth_stop; 81 static uether_fn_t ipheth_start; 82 static uether_fn_t ipheth_setmulti; 83 static uether_fn_t ipheth_setpromisc; 84 85 static ipheth_consumer_t ipheth_consume_read; 86 static ipheth_consumer_t ipheth_consume_read_ncm; 87 88 #ifdef USB_DEBUG 89 static int ipheth_debug = 0; 90 91 static SYSCTL_NODE(_hw_usb, OID_AUTO, ipheth, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 92 "USB iPhone ethernet"); 93 SYSCTL_INT(_hw_usb_ipheth, OID_AUTO, debug, CTLFLAG_RWTUN, &ipheth_debug, 0, "Debug level"); 94 #endif 95 96 static const struct usb_config ipheth_config[IPHETH_N_TRANSFER] = { 97 [IPHETH_BULK_RX] = { 98 .type = UE_BULK, 99 .endpoint = UE_ADDR_ANY, 100 .direction = UE_DIR_RX, 101 .frames = IPHETH_RX_FRAMES_MAX, 102 .bufsize = (IPHETH_RX_FRAMES_MAX * MCLBYTES), 103 .flags = {.short_frames_ok = 1, .short_xfer_ok = 1, .ext_buffer = 1,}, 104 .callback = ipheth_bulk_read_callback, 105 .timeout = 0, /* no timeout */ 106 }, 107 108 [IPHETH_BULK_TX] = { 109 .type = UE_BULK, 110 .endpoint = UE_ADDR_ANY, 111 .direction = UE_DIR_TX, 112 .frames = IPHETH_TX_FRAMES_MAX, 113 .bufsize = (IPHETH_TX_FRAMES_MAX * IPHETH_BUF_SIZE), 114 .flags = {.force_short_xfer = 1,}, 115 .callback = ipheth_bulk_write_callback, 116 .timeout = IPHETH_TX_TIMEOUT, 117 }, 118 }; 119 120 static const struct usb_config ipheth_config_ncm[IPHETH_N_TRANSFER] = { 121 [IPHETH_BULK_RX] = { 122 .type = UE_BULK, 123 .endpoint = UE_ADDR_ANY, 124 .direction = UE_DIR_RX, 125 .frames = 1, 126 .bufsize = IPHETH_RX_NCM_BUF_SIZE, 127 .flags = {.short_frames_ok = 1, .short_xfer_ok = 1,}, 128 .callback = ipheth_bulk_read_callback, 129 .timeout = 0, /* no timeout */ 130 }, 131 132 [IPHETH_BULK_TX] = { 133 .type = UE_BULK, 134 .endpoint = UE_ADDR_ANY, 135 .direction = UE_DIR_TX, 136 .frames = IPHETH_TX_FRAMES_MAX, 137 .bufsize = (IPHETH_TX_FRAMES_MAX * IPHETH_BUF_SIZE), 138 .flags = {.force_short_xfer = 1,}, 139 .callback = ipheth_bulk_write_callback, 140 .timeout = IPHETH_TX_TIMEOUT, 141 }, 142 }; 143 144 static device_method_t ipheth_methods[] = { 145 /* Device interface */ 146 DEVMETHOD(device_probe, ipheth_probe), 147 DEVMETHOD(device_attach, ipheth_attach), 148 DEVMETHOD(device_detach, ipheth_detach), 149 150 DEVMETHOD_END 151 }; 152 153 static driver_t ipheth_driver = { 154 .name = "ipheth", 155 .methods = ipheth_methods, 156 .size = sizeof(struct ipheth_softc), 157 }; 158 159 static const STRUCT_USB_HOST_ID ipheth_devs[] = { 160 #if 0 161 {IPHETH_ID(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE, 162 IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, 163 IPHETH_USBINTF_PROTO)}, 164 {IPHETH_ID(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3G, 165 IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, 166 IPHETH_USBINTF_PROTO)}, 167 {IPHETH_ID(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3GS, 168 IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, 169 IPHETH_USBINTF_PROTO)}, 170 {IPHETH_ID(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_4, 171 IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, 172 IPHETH_USBINTF_PROTO)}, 173 {IPHETH_ID(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_4S, 174 IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, 175 IPHETH_USBINTF_PROTO)}, 176 {IPHETH_ID(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_5, 177 IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, 178 IPHETH_USBINTF_PROTO)}, 179 #else 180 /* product agnostic interface match */ 181 {USB_VENDOR(USB_VENDOR_APPLE), 182 USB_IFACE_CLASS(IPHETH_USBINTF_CLASS), 183 USB_IFACE_SUBCLASS(IPHETH_USBINTF_SUBCLASS), 184 USB_IFACE_PROTOCOL(IPHETH_USBINTF_PROTO)}, 185 #endif 186 }; 187 188 DRIVER_MODULE(ipheth, uhub, ipheth_driver, NULL, NULL); 189 MODULE_VERSION(ipheth, 1); 190 MODULE_DEPEND(ipheth, uether, 1, 1, 1); 191 MODULE_DEPEND(ipheth, usb, 1, 1, 1); 192 MODULE_DEPEND(ipheth, ether, 1, 1, 1); 193 USB_PNP_HOST_INFO(ipheth_devs); 194 195 static const struct usb_ether_methods ipheth_ue_methods = { 196 .ue_attach_post = ipheth_attach_post, 197 .ue_start = ipheth_start, 198 .ue_init = ipheth_init, 199 .ue_tick = ipheth_tick, 200 .ue_stop = ipheth_stop, 201 .ue_setmulti = ipheth_setmulti, 202 .ue_setpromisc = ipheth_setpromisc, 203 }; 204 205 #define IPHETH_ID(v,p,c,sc,pt) \ 206 USB_VENDOR(v), USB_PRODUCT(p), \ 207 USB_IFACE_CLASS(c), USB_IFACE_SUBCLASS(sc), \ 208 USB_IFACE_PROTOCOL(pt) 209 210 static int 211 ipheth_get_mac_addr(struct ipheth_softc *sc) 212 { 213 struct usb_device_request req; 214 int error; 215 216 req.bmRequestType = UT_READ_VENDOR_DEVICE; 217 req.bRequest = IPHETH_CMD_GET_MACADDR; 218 req.wValue[0] = 0; 219 req.wValue[1] = 0; 220 req.wIndex[0] = sc->sc_iface_no; 221 req.wIndex[1] = 0; 222 req.wLength[0] = ETHER_ADDR_LEN; 223 req.wLength[1] = 0; 224 225 error = usbd_do_request(sc->sc_ue.ue_udev, NULL, &req, sc->sc_data); 226 227 if (error) 228 return (error); 229 230 memcpy(sc->sc_ue.ue_eaddr, sc->sc_data, ETHER_ADDR_LEN); 231 232 return (0); 233 } 234 235 static bool 236 ipheth_enable_ncm(struct ipheth_softc *sc) 237 { 238 struct usb_device_request req; 239 240 req.bmRequestType = UT_WRITE_VENDOR_INTERFACE; 241 req.bRequest = IPHETH_CMD_ENABLE_NCM; 242 USETW(req.wValue, 0); 243 req.wIndex[0] = sc->sc_iface_no; 244 req.wIndex[1] = 0; 245 USETW(req.wLength, 0); 246 247 return (usbd_do_request(sc->sc_ue.ue_udev, NULL, &req, NULL) == 0); 248 } 249 250 static int 251 ipheth_probe(device_t dev) 252 { 253 struct usb_attach_arg *uaa = device_get_ivars(dev); 254 255 if (uaa->usb_mode != USB_MODE_HOST) 256 return (ENXIO); 257 258 return (usbd_lookup_id_by_uaa(ipheth_devs, sizeof(ipheth_devs), uaa)); 259 } 260 261 static int 262 ipheth_attach(device_t dev) 263 { 264 struct ipheth_softc *sc = device_get_softc(dev); 265 struct usb_ether *ue = &sc->sc_ue; 266 struct usb_attach_arg *uaa = device_get_ivars(dev); 267 const struct usb_config *config; 268 int error; 269 270 sc->sc_iface_no = uaa->info.bIfaceIndex; 271 272 device_set_usb_desc(dev); 273 274 mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 275 276 error = usbd_set_alt_interface_index(uaa->device, 277 uaa->info.bIfaceIndex, IPHETH_ALT_INTFNUM); 278 if (error) { 279 device_printf(dev, "Cannot set alternate setting\n"); 280 goto detach; 281 } 282 283 ue->ue_sc = sc; 284 ue->ue_dev = dev; 285 ue->ue_udev = uaa->device; 286 ue->ue_mtx = &sc->sc_mtx; 287 ue->ue_methods = &ipheth_ue_methods; 288 289 if (ipheth_enable_ncm(sc)) { 290 config = ipheth_config_ncm; 291 sc->is_ncm = true; 292 sc->consume = &ipheth_consume_read_ncm; 293 } else { 294 config = ipheth_config; 295 sc->consume = &ipheth_consume_read; 296 } 297 298 error = usbd_transfer_setup(uaa->device, &sc->sc_iface_no, sc->sc_xfer, 299 config, IPHETH_N_TRANSFER, sc, &sc->sc_mtx); 300 if (error) { 301 device_printf(dev, "Cannot setup USB transfers\n"); 302 goto detach; 303 } 304 305 error = ipheth_get_mac_addr(sc); 306 if (error) { 307 device_printf(dev, "Cannot get MAC address\n"); 308 goto detach; 309 } 310 311 error = uether_ifattach(ue); 312 if (error) { 313 device_printf(dev, "could not attach interface\n"); 314 goto detach; 315 } 316 return (0); /* success */ 317 318 detach: 319 ipheth_detach(dev); 320 return (ENXIO); /* failure */ 321 } 322 323 static int 324 ipheth_detach(device_t dev) 325 { 326 struct ipheth_softc *sc = device_get_softc(dev); 327 struct usb_ether *ue = &sc->sc_ue; 328 329 /* stop all USB transfers first */ 330 usbd_transfer_unsetup(sc->sc_xfer, IPHETH_N_TRANSFER); 331 332 uether_ifdetach(ue); 333 334 mtx_destroy(&sc->sc_mtx); 335 336 return (0); 337 } 338 339 static void 340 ipheth_start(struct usb_ether *ue) 341 { 342 struct ipheth_softc *sc = uether_getsc(ue); 343 344 /* 345 * Start the USB transfers, if not already started: 346 */ 347 usbd_transfer_start(sc->sc_xfer[IPHETH_BULK_TX]); 348 usbd_transfer_start(sc->sc_xfer[IPHETH_BULK_RX]); 349 } 350 351 static void 352 ipheth_stop(struct usb_ether *ue) 353 { 354 struct ipheth_softc *sc = uether_getsc(ue); 355 356 /* 357 * Stop the USB transfers, if not already stopped: 358 */ 359 usbd_transfer_stop(sc->sc_xfer[IPHETH_BULK_TX]); 360 usbd_transfer_stop(sc->sc_xfer[IPHETH_BULK_RX]); 361 } 362 363 static void 364 ipheth_tick(struct usb_ether *ue) 365 { 366 struct ipheth_softc *sc = uether_getsc(ue); 367 struct usb_device_request req; 368 int error; 369 370 req.bmRequestType = UT_READ_VENDOR_DEVICE; 371 req.bRequest = IPHETH_CMD_CARRIER_CHECK; 372 req.wValue[0] = 0; 373 req.wValue[1] = 0; 374 req.wIndex[0] = sc->sc_iface_no; 375 req.wIndex[1] = 0; 376 req.wLength[0] = IPHETH_CTRL_BUF_SIZE; 377 req.wLength[1] = 0; 378 379 error = uether_do_request(ue, &req, sc->sc_data, IPHETH_CTRL_TIMEOUT); 380 381 if (error) 382 return; 383 384 sc->sc_carrier_on = 385 (sc->sc_data[0] == IPHETH_CARRIER_ON); 386 } 387 388 static void 389 ipheth_attach_post(struct usb_ether *ue) 390 { 391 392 } 393 394 static void 395 ipheth_init(struct usb_ether *ue) 396 { 397 struct ipheth_softc *sc = uether_getsc(ue); 398 if_t ifp = uether_getifp(ue); 399 400 IPHETH_LOCK_ASSERT(sc, MA_OWNED); 401 402 if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0); 403 404 /* stall data write direction, which depends on USB mode */ 405 usbd_xfer_set_stall(sc->sc_xfer[IPHETH_BULK_TX]); 406 407 /* start data transfers */ 408 ipheth_start(ue); 409 } 410 411 static void 412 ipheth_setmulti(struct usb_ether *ue) 413 { 414 415 } 416 417 static void 418 ipheth_setpromisc(struct usb_ether *ue) 419 { 420 421 } 422 423 static void 424 ipheth_free_queue(struct mbuf **ppm, uint8_t n) 425 { 426 uint8_t x; 427 428 for (x = 0; x != n; x++) { 429 if (ppm[x] != NULL) { 430 m_freem(ppm[x]); 431 ppm[x] = NULL; 432 } 433 } 434 } 435 436 static void 437 ipheth_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) 438 { 439 struct ipheth_softc *sc = usbd_xfer_softc(xfer); 440 if_t ifp = uether_getifp(&sc->sc_ue); 441 struct usb_page_cache *pc; 442 struct mbuf *m; 443 uint8_t x; 444 int actlen; 445 int aframes; 446 447 switch (USB_GET_STATE(xfer)) { 448 case USB_ST_TRANSFERRED: 449 usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL); 450 DPRINTFN(11, "transfer complete: %u bytes in %u frames\n", 451 actlen, aframes); 452 453 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 454 455 /* free all previous TX buffers */ 456 ipheth_free_queue(sc->sc_tx_buf, IPHETH_TX_FRAMES_MAX); 457 458 /* FALLTHROUGH */ 459 case USB_ST_SETUP: 460 tr_setup: 461 for (x = 0; x != IPHETH_TX_FRAMES_MAX; x++) { 462 m = if_dequeue(ifp); 463 464 if (m == NULL) 465 break; 466 467 usbd_xfer_set_frame_offset(xfer, 468 x * IPHETH_BUF_SIZE, x); 469 470 pc = usbd_xfer_get_frame(xfer, x); 471 472 sc->sc_tx_buf[x] = m; 473 474 if (m->m_pkthdr.len > IPHETH_BUF_SIZE) 475 m->m_pkthdr.len = IPHETH_BUF_SIZE; 476 477 usbd_m_copy_in(pc, 0, m, 0, m->m_pkthdr.len); 478 479 usbd_xfer_set_frame_len(xfer, x, IPHETH_BUF_SIZE); 480 481 if (IPHETH_BUF_SIZE != m->m_pkthdr.len) { 482 usbd_frame_zero(pc, m->m_pkthdr.len, 483 IPHETH_BUF_SIZE - m->m_pkthdr.len); 484 } 485 486 /* 487 * If there's a BPF listener, bounce a copy of 488 * this frame to him: 489 */ 490 BPF_MTAP(ifp, m); 491 } 492 if (x != 0) { 493 usbd_xfer_set_frames(xfer, x); 494 495 usbd_transfer_submit(xfer); 496 } 497 break; 498 499 default: /* Error */ 500 DPRINTFN(11, "transfer error, %s\n", 501 usbd_errstr(error)); 502 503 /* free all previous TX buffers */ 504 ipheth_free_queue(sc->sc_tx_buf, IPHETH_TX_FRAMES_MAX); 505 506 /* count output errors */ 507 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 508 509 if (error != USB_ERR_CANCELLED) { 510 /* try to clear stall first */ 511 usbd_xfer_set_stall(xfer); 512 goto tr_setup; 513 } 514 break; 515 } 516 } 517 518 static void 519 ipheth_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) 520 { 521 struct ipheth_softc *sc = usbd_xfer_softc(xfer); 522 struct mbuf *m; 523 uint8_t x; 524 int actlen; 525 int aframes; 526 527 switch (USB_GET_STATE(xfer)) { 528 case USB_ST_TRANSFERRED: 529 usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL); 530 DPRINTF("received %u bytes in %u frames\n", actlen, aframes); 531 532 for (x = 0; x != aframes; x++) 533 sc->consume(xfer, x); 534 535 /* FALLTHROUGH */ 536 case USB_ST_SETUP: 537 if (!sc->is_ncm) { 538 for (x = 0; x != IPHETH_RX_FRAMES_MAX; x++) { 539 if (sc->sc_rx_buf[x] == NULL) { 540 m = uether_newbuf(); 541 if (m == NULL) 542 goto tr_stall; 543 544 /* cancel alignment for ethernet */ 545 m_adj(m, ETHER_ALIGN); 546 547 sc->sc_rx_buf[x] = m; 548 } else { 549 m = sc->sc_rx_buf[x]; 550 } 551 usbd_xfer_set_frame_data(xfer, x, m->m_data, m->m_len); 552 } 553 usbd_xfer_set_frames(xfer, x); 554 } else { 555 usbd_xfer_set_frame_len(xfer, 0, 556 IPHETH_RX_NCM_BUF_SIZE); 557 usbd_xfer_set_frames(xfer, 1); 558 } 559 560 usbd_transfer_submit(xfer); 561 /* flush any received frames */ 562 uether_rxflush(&sc->sc_ue); 563 break; 564 565 default: /* Error */ 566 DPRINTF("error = %s\n", usbd_errstr(error)); 567 568 if (error != USB_ERR_CANCELLED) { 569 tr_stall: 570 /* try to clear stall first */ 571 usbd_xfer_set_stall(xfer); 572 usbd_xfer_set_frames(xfer, 0); 573 usbd_transfer_submit(xfer); 574 break; 575 } 576 /* need to free the RX-mbufs when we are cancelled */ 577 ipheth_free_queue(sc->sc_rx_buf, IPHETH_RX_FRAMES_MAX); 578 break; 579 } 580 } 581 582 static void 583 ipheth_consume_read(struct usb_xfer *xfer, int x) 584 { 585 struct ipheth_softc *sc = usbd_xfer_softc(xfer); 586 struct mbuf *m = sc->sc_rx_buf[x]; 587 int len; 588 589 sc->sc_rx_buf[x] = NULL; 590 len = usbd_xfer_frame_len(xfer, x); 591 592 if (len < (int)(sizeof(struct ether_header) + IPHETH_RX_ADJ)) { 593 m_freem(m); 594 return; 595 } 596 597 m_adj(m, IPHETH_RX_ADJ); 598 599 /* queue up mbuf */ 600 uether_rxmbuf(&sc->sc_ue, m, len - IPHETH_RX_ADJ); 601 } 602 603 static void 604 ipheth_consume_read_ncm(struct usb_xfer *xfer, int x) 605 { 606 struct ipheth_softc *sc = usbd_xfer_softc(xfer); 607 struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, 0); 608 struct ncm_data_cache ncm; 609 if_t ifp = uether_getifp(&sc->sc_ue); 610 struct mbuf *new_buf; 611 int i, actlen; 612 uint16_t dp_offset, dp_len; 613 614 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 615 616 if (actlen < IPHETH_NCM_HEADER_SIZE) 617 return; 618 619 usbd_copy_out(pc, 0, &ncm.hdr, sizeof(ncm.hdr)); 620 621 if (UGETDW(ncm.hdr.dwSignature) != 0x484D434E) 622 return; 623 624 /* Dpt follows the hdr on iOS */ 625 if (UGETW(ncm.hdr.wDptIndex) != (int)(sizeof(struct usb_ncm16_hdr))) 626 return; 627 628 usbd_copy_out(pc, UGETW(ncm.hdr.wDptIndex), &ncm.dpt, sizeof(ncm.dpt)); 629 630 if (UGETDW(ncm.dpt.dwSignature) != 0x304D434E) 631 return; 632 633 usbd_copy_out(pc, UGETW(ncm.hdr.wDptIndex) + sizeof(ncm.dpt), &ncm.dp, 634 sizeof(ncm.dp)); 635 636 for (i = 0; i < IPHETH_NCM_DPT_DP_NUM; ++i) { 637 dp_offset = UGETW(ncm.dp[i].wFrameIndex); 638 dp_len = UGETW(ncm.dp[i].wFrameLength); 639 640 /* (3.3.1 USB CDC NCM spec v1.0) */ 641 if (dp_offset == 0 && dp_len == 0) 642 break; 643 644 if (dp_offset < IPHETH_NCM_HEADER_SIZE || dp_offset >= actlen || 645 actlen < (dp_len + dp_offset) || 646 dp_len < sizeof(struct ether_header)) { 647 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 648 continue; 649 } 650 if (dp_len > (MCLBYTES - ETHER_ALIGN)) { 651 if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); 652 continue; 653 } 654 655 new_buf = uether_newbuf(); 656 if (new_buf == NULL) { 657 if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); 658 continue; 659 } 660 usbd_copy_out(pc, dp_offset, new_buf->m_data, dp_len); 661 uether_rxmbuf(&sc->sc_ue, new_buf, dp_len); 662 } 663 } 664