1 /* 2 * Copyright 2009, Colin Günther, coling@gmx.de. 3 * Copyright 2007-2009, Axel Dörfler, axeld@pinc-software.de. 4 * Copyright 2007, Hugo Santos. All Rights Reserved. 5 * Copyright 2004, Marcus Overhagen. All Rights Reserved. 6 * 7 * Distributed under the terms of the MIT License. 8 */ 9 10 11 #include "device.h" 12 13 #include <stdio.h> 14 #include <net/if_types.h> 15 #include <sys/sockio.h> 16 17 #include <compat/sys/bus.h> 18 #include <compat/sys/kernel.h> 19 #include <compat/sys/taskqueue.h> 20 21 #include <compat/net/if.h> 22 #include <compat/net/if_arp.h> 23 #include <compat/net/if_media.h> 24 #include <compat/net/if_var.h> 25 #include <compat/sys/malloc.h> 26 27 #include <compat/net/ethernet.h> 28 29 30 int ifqmaxlen = IFQ_MAXLEN; 31 32 33 #define IFNET_HOLD (void *)(uintptr_t)(-1) 34 35 36 static void 37 insert_into_device_name_list(struct ifnet * ifp) 38 { 39 int i; 40 for (i = 0; i < MAX_DEVICES; i++) { 41 if (gDeviceNameList[i] == NULL) { 42 gDeviceNameList[i] = ifp->device_name; 43 return; 44 } 45 } 46 47 panic("too many devices"); 48 } 49 50 51 static void 52 remove_from_device_name_list(struct ifnet * ifp) 53 { 54 int i; 55 for (i = 0; i < MAX_DEVICES; i++) { 56 if (ifp->device_name == gDeviceNameList[i]) { 57 int last; 58 for (last = i + 1; last < MAX_DEVICES; last++) { 59 if (gDeviceNameList[last] == NULL) 60 break; 61 } 62 last--; 63 64 if (i == last) 65 gDeviceNameList[i] = NULL; 66 else { 67 // switch positions with the last entry 68 gDeviceNameList[i] = gDeviceNameList[last]; 69 gDeviceNameList[last] = NULL; 70 } 71 break; 72 } 73 } 74 } 75 76 77 struct ifnet * 78 ifnet_byindex(u_short idx) 79 { 80 struct ifnet *ifp; 81 82 IFNET_RLOCK_NOSLEEP(); 83 ifp = ifnet_byindex_locked(idx); 84 IFNET_RUNLOCK_NOSLEEP(); 85 86 return (ifp); 87 } 88 89 90 struct ifnet * 91 ifnet_byindex_locked(u_short idx) 92 { 93 struct ifnet *ifp; 94 95 ifp = gDevices[idx]; 96 97 return (ifp); 98 } 99 100 101 static void 102 ifnet_setbyindex_locked(u_short idx, struct ifnet *ifp) 103 { 104 gDevices[idx] = ifp; 105 } 106 107 108 static void 109 ifnet_setbyindex(u_short idx, struct ifnet *ifp) 110 { 111 IFNET_WLOCK(); 112 ifnet_setbyindex_locked(idx, ifp); 113 IFNET_WUNLOCK(); 114 } 115 116 117 static int 118 ifindex_alloc_locked(u_short *idxp) 119 { 120 u_short index; 121 122 for (index = 0; index < MAX_DEVICES; index++) { 123 if (gDevices[index] == NULL) { 124 break; 125 } 126 } 127 128 if (index == MAX_DEVICES) 129 return ENOSPC; 130 131 gDeviceCount++; 132 *idxp = index; 133 134 return ENOERR; 135 } 136 137 138 static void 139 ifindex_free_locked(u_short idx) 140 { 141 gDevices[idx] = NULL; 142 gDeviceCount--; 143 } 144 145 146 struct ifnet * 147 if_alloc(u_char type) 148 { 149 char semName[64]; 150 u_short index; 151 152 struct ifnet *ifp = _kernel_malloc(sizeof(struct ifnet), M_ZERO); 153 if (ifp == NULL) 154 return NULL; 155 156 snprintf(semName, sizeof(semName), "%s receive", gDriverName); 157 158 ifp->receive_sem = create_sem(0, semName); 159 if (ifp->receive_sem < B_OK) 160 goto err1; 161 162 switch (type) { 163 case IFT_ETHER: 164 { 165 ifp->if_l2com = _kernel_malloc(sizeof(struct arpcom), M_ZERO); 166 if (ifp->if_l2com == NULL) 167 goto err2; 168 IFP2AC(ifp)->ac_ifp = ifp; 169 break; 170 } 171 case IFT_IEEE80211: 172 { 173 if (wlan_if_l2com_alloc(ifp) != B_OK) 174 goto err2; 175 break; 176 } 177 } 178 179 ifp->link_state_sem = -1; 180 ifp->open_count = 0; 181 ifp->flags = 0; 182 ifp->if_type = type; 183 ifq_init(&ifp->receive_queue, semName); 184 185 ifp->scan_done_sem = -1; 186 // WLAN specific, doesn't hurt when initilized for other devices 187 188 // Search for the first free device slot, and use that one 189 IFNET_WLOCK(); 190 if (ifindex_alloc_locked(&index) != ENOERR) { 191 IFNET_WUNLOCK(); 192 panic("too many devices"); 193 goto err3; 194 } 195 ifnet_setbyindex_locked(index, IFNET_HOLD); 196 IFNET_WUNLOCK(); 197 198 ifp->if_index = index; 199 ifnet_setbyindex(ifp->if_index, ifp); 200 201 IF_ADDR_LOCK_INIT(ifp); 202 return ifp; 203 204 err3: 205 switch (type) { 206 case IFT_ETHER: 207 case IFT_IEEE80211: 208 _kernel_free(ifp->if_l2com); 209 break; 210 } 211 212 err2: 213 delete_sem(ifp->receive_sem); 214 215 err1: 216 _kernel_free(ifp); 217 return NULL; 218 } 219 220 221 void 222 if_free(struct ifnet *ifp) 223 { 224 // IEEE80211 devices won't be in this list, 225 // so don't try to remove them. 226 if (ifp->if_type == IFT_ETHER) 227 remove_from_device_name_list(ifp); 228 229 IFNET_WLOCK(); 230 ifindex_free_locked(ifp->if_index); 231 IFNET_WUNLOCK(); 232 233 IF_ADDR_LOCK_DESTROY(ifp); 234 switch (ifp->if_type) { 235 case IFT_ETHER: 236 case IFT_IEEE80211: 237 _kernel_free(ifp->if_l2com); 238 break; 239 } 240 241 delete_sem(ifp->receive_sem); 242 ifq_uninit(&ifp->receive_queue); 243 244 _kernel_free(ifp); 245 } 246 247 248 void 249 if_initname(struct ifnet *ifp, const char *name, int unit) 250 { 251 dprintf("if_initname(%p, %s, %d)\n", ifp, name, unit); 252 253 if (name == NULL || name[0] == '\0') 254 panic("interface goes unnamed"); 255 256 ifp->if_dname = name; 257 ifp->if_dunit = unit; 258 259 strlcpy(ifp->if_xname, name, sizeof(ifp->if_xname)); 260 261 snprintf(ifp->device_name, sizeof(ifp->device_name), "net/%s/%i", 262 gDriverName, ifp->if_index); 263 264 driver_printf("%s: /dev/%s\n", gDriverName, ifp->device_name); 265 266 // For wlan devices we only want to see the cloned wlan device 267 // in the list. 268 // Remember: For each wlan device, there is a base device of type 269 // IFT_IEEE80211. On top of that a clone device is created of 270 // type IFT_ETHER. 271 // Haiku shall only see the cloned device as it is the one 272 // FreeBSD 8 uses for wireless i/o, too. 273 if (ifp->if_type == IFT_ETHER) 274 insert_into_device_name_list(ifp); 275 276 ifp->root_device = find_root_device(unit); 277 } 278 279 280 void 281 ifq_init(struct ifqueue *ifq, const char *name) 282 { 283 ifq->ifq_head = NULL; 284 ifq->ifq_tail = NULL; 285 ifq->ifq_len = 0; 286 ifq->ifq_maxlen = IFQ_MAXLEN; 287 ifq->ifq_drops = 0; 288 289 mtx_init(&ifq->ifq_mtx, name, NULL, MTX_DEF); 290 } 291 292 293 void 294 ifq_uninit(struct ifqueue *ifq) 295 { 296 mtx_destroy(&ifq->ifq_mtx); 297 } 298 299 300 static int 301 if_transmit(struct ifnet *ifp, struct mbuf *m) 302 { 303 int error; 304 305 IFQ_HANDOFF(ifp, m, error); 306 return (error); 307 } 308 309 310 void 311 if_attach(struct ifnet *ifp) 312 { 313 TAILQ_INIT(&ifp->if_addrhead); 314 TAILQ_INIT(&ifp->if_prefixhead); 315 TAILQ_INIT(&ifp->if_multiaddrs); 316 317 IF_ADDR_LOCK_INIT(ifp); 318 319 ifp->if_lladdr.sdl_family = AF_LINK; 320 321 ifq_init((struct ifqueue *) &ifp->if_snd, ifp->if_xname); 322 323 if (ifp->if_transmit == NULL) { 324 ifp->if_transmit = if_transmit; 325 } 326 } 327 328 329 void 330 if_detach(struct ifnet *ifp) 331 { 332 if (HAIKU_DRIVER_REQUIRES(FBSD_SWI_TASKQUEUE)) 333 taskqueue_drain(taskqueue_swi, &ifp->if_linktask); 334 335 IF_ADDR_LOCK_DESTROY(ifp); 336 ifq_uninit((struct ifqueue *) &ifp->if_snd); 337 } 338 339 340 void 341 if_start(struct ifnet *ifp) 342 { 343 #ifdef IFF_NEEDSGIANT 344 if (ifp->if_flags & IFF_NEEDSGIANT) 345 panic("freebsd compat.: unsupported giant requirement"); 346 #endif 347 ifp->if_start(ifp); 348 } 349 350 351 int 352 if_printf(struct ifnet *ifp, const char *format, ...) 353 { 354 char buf[256]; 355 va_list vl; 356 va_start(vl, format); 357 vsnprintf(buf, sizeof(buf), format, vl); 358 va_end(vl); 359 360 dprintf("[%s] %s", ifp->device_name, buf); 361 return 0; 362 } 363 364 365 void 366 if_link_state_change(struct ifnet *ifp, int linkState) 367 { 368 if (ifp->if_link_state == linkState) 369 return; 370 371 ifp->if_link_state = linkState; 372 release_sem_etc(ifp->link_state_sem, 1, B_DO_NOT_RESCHEDULE); 373 } 374 375 376 static struct ifmultiaddr * 377 if_findmulti(struct ifnet *ifp, struct sockaddr *_address) 378 { 379 struct sockaddr_dl *address = (struct sockaddr_dl *) _address; 380 struct ifmultiaddr *ifma; 381 382 TAILQ_FOREACH (ifma, &ifp->if_multiaddrs, ifma_link) { 383 if (memcmp(LLADDR(address), 384 LLADDR((struct sockaddr_dl *)ifma->ifma_addr), ETHER_ADDR_LEN) == 0) 385 return ifma; 386 } 387 388 return NULL; 389 } 390 391 392 /* 393 * if_freemulti: free ifmultiaddr structure and possibly attached related 394 * addresses. The caller is responsible for implementing reference 395 * counting, notifying the driver, handling routing messages, and releasing 396 * any dependent link layer state. 397 */ 398 static void 399 if_freemulti(struct ifmultiaddr *ifma) 400 { 401 402 KASSERT(ifma->ifma_refcount == 0, ("if_freemulti: refcount %d", 403 ifma->ifma_refcount)); 404 KASSERT(ifma->ifma_protospec == NULL, 405 ("if_freemulti: protospec not NULL")); 406 407 if (ifma->ifma_lladdr != NULL) 408 free(ifma->ifma_lladdr); 409 free(ifma->ifma_addr); 410 free(ifma); 411 } 412 413 414 static struct ifmultiaddr * 415 _if_addmulti(struct ifnet *ifp, struct sockaddr *address) 416 { 417 struct ifmultiaddr *addr = if_findmulti(ifp, address); 418 419 if (addr != NULL) { 420 addr->ifma_refcount++; 421 return addr; 422 } 423 424 addr = (struct ifmultiaddr *) malloc(sizeof(struct ifmultiaddr)); 425 if (addr == NULL) 426 return NULL; 427 428 addr->ifma_lladdr = NULL; 429 addr->ifma_ifp = ifp; 430 addr->ifma_protospec = NULL; 431 432 memcpy(&addr->ifma_addr_storage, address, sizeof(struct sockaddr_dl)); 433 addr->ifma_addr = (struct sockaddr *) &addr->ifma_addr_storage; 434 435 addr->ifma_refcount = 1; 436 437 TAILQ_INSERT_HEAD(&ifp->if_multiaddrs, addr, ifma_link); 438 439 return addr; 440 } 441 442 443 int 444 if_addmulti(struct ifnet *ifp, struct sockaddr *address, 445 struct ifmultiaddr **out) 446 { 447 struct ifmultiaddr *result; 448 int refcount = 0; 449 450 IF_ADDR_LOCK(ifp); 451 result = _if_addmulti(ifp, address); 452 if (result) 453 refcount = result->ifma_refcount; 454 IF_ADDR_UNLOCK(ifp); 455 456 if (result == NULL) 457 return ENOBUFS; 458 459 if (refcount == 1 && ifp->if_ioctl != NULL) 460 ifp->if_ioctl(ifp, SIOCADDMULTI, NULL); 461 462 if (out) 463 (*out) = result; 464 465 return 0; 466 } 467 468 469 static int 470 if_delmulti_locked(struct ifnet *ifp, struct ifmultiaddr *ifma, int detaching) 471 { 472 struct ifmultiaddr *ll_ifma; 473 474 if (ifp != NULL && ifma->ifma_ifp != NULL) { 475 KASSERT(ifma->ifma_ifp == ifp, 476 ("%s: inconsistent ifp %p", __func__, ifp)); 477 IF_ADDR_LOCK_ASSERT(ifp); 478 } 479 480 ifp = ifma->ifma_ifp; 481 482 /* 483 * If the ifnet is detaching, null out references to ifnet, 484 * so that upper protocol layers will notice, and not attempt 485 * to obtain locks for an ifnet which no longer exists. The 486 * routing socket announcement must happen before the ifnet 487 * instance is detached from the system. 488 */ 489 if (detaching) { 490 #ifdef DIAGNOSTIC 491 printf("%s: detaching ifnet instance %p\n", __func__, ifp); 492 #endif 493 /* 494 * ifp may already be nulled out if we are being reentered 495 * to delete the ll_ifma. 496 */ 497 if (ifp != NULL) { 498 #ifndef __HAIKU__ 499 rt_newmaddrmsg(RTM_DELMADDR, ifma); 500 #endif 501 ifma->ifma_ifp = NULL; 502 } 503 } 504 505 if (--ifma->ifma_refcount > 0) 506 return 0; 507 508 #ifndef __HAIKU__ 509 /* 510 * If this ifma is a network-layer ifma, a link-layer ifma may 511 * have been associated with it. Release it first if so. 512 */ 513 ll_ifma = ifma->ifma_llifma; 514 if (ll_ifma != NULL) { 515 KASSERT(ifma->ifma_lladdr != NULL, 516 ("%s: llifma w/o lladdr", __func__)); 517 if (detaching) 518 ll_ifma->ifma_ifp = NULL; /* XXX */ 519 if (--ll_ifma->ifma_refcount == 0) { 520 if (ifp != NULL) { 521 TAILQ_REMOVE(&ifp->if_multiaddrs, ll_ifma, 522 ifma_link); 523 } 524 if_freemulti(ll_ifma); 525 } 526 } 527 #endif 528 529 if (ifp != NULL) 530 TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link); 531 532 if_freemulti(ifma); 533 534 /* 535 * The last reference to this instance of struct ifmultiaddr 536 * was released; the hardware should be notified of this change. 537 */ 538 return 1; 539 } 540 541 542 /* 543 * Delete all multicast group membership for an interface. 544 * Should be used to quickly flush all multicast filters. 545 */ 546 void 547 if_delallmulti(struct ifnet *ifp) 548 { 549 struct ifmultiaddr *ifma; 550 struct ifmultiaddr *next; 551 552 IF_ADDR_LOCK(ifp); 553 TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next) 554 if_delmulti_locked(ifp, ifma, 0); 555 IF_ADDR_UNLOCK(ifp); 556 } 557 558 559 static void 560 if_delete_multiaddr(struct ifnet *ifp, struct ifmultiaddr *ifma) 561 { 562 TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link); 563 free(ifma); 564 } 565 566 567 int 568 if_delmulti(struct ifnet *ifp, struct sockaddr *sa) 569 { 570 struct ifmultiaddr *ifma; 571 int lastref; 572 #ifdef INVARIANTS 573 struct ifnet *oifp; 574 575 IFNET_RLOCK_NOSLEEP(); 576 TAILQ_FOREACH(oifp, &V_ifnet, if_link) 577 if (ifp == oifp) 578 break; 579 if (ifp != oifp) 580 ifp = NULL; 581 IFNET_RUNLOCK_NOSLEEP(); 582 583 KASSERT(ifp != NULL, ("%s: ifnet went away", __func__)); 584 #endif 585 if (ifp == NULL) 586 return (ENOENT); 587 588 IF_ADDR_LOCK(ifp); 589 lastref = 0; 590 ifma = if_findmulti(ifp, sa); 591 if (ifma != NULL) 592 lastref = if_delmulti_locked(ifp, ifma, 0); 593 IF_ADDR_UNLOCK(ifp); 594 595 if (ifma == NULL) 596 return (ENOENT); 597 598 if (lastref && ifp->if_ioctl != NULL) { 599 (void)(*ifp->if_ioctl)(ifp, SIOCDELMULTI, 0); 600 } 601 602 return (0); 603 } 604 605 606 void 607 if_purgemaddrs(struct ifnet *ifp) 608 { 609 struct ifmultiaddr *ifma; 610 struct ifmultiaddr *next; 611 612 IF_ADDR_LOCK(ifp); 613 TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next) 614 if_delmulti_locked(ifp, ifma, 1); 615 IF_ADDR_UNLOCK(ifp); 616 } 617 618 619 void 620 if_addr_rlock(struct ifnet *ifp) 621 { 622 IF_ADDR_LOCK(ifp); 623 } 624 625 626 void 627 if_addr_runlock(struct ifnet *ifp) 628 { 629 IF_ADDR_UNLOCK(ifp); 630 } 631 632 633 void 634 if_maddr_rlock(struct ifnet *ifp) 635 { 636 IF_ADDR_LOCK(ifp); 637 } 638 639 640 void 641 if_maddr_runlock(struct ifnet *ifp) 642 { 643 IF_ADDR_UNLOCK(ifp); 644 } 645 646 647 int 648 ether_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 649 struct route *ro) 650 { 651 int error = 0; 652 IFQ_HANDOFF(ifp, m, error); 653 return error; 654 } 655 656 657 static void ether_input(struct ifnet *ifp, struct mbuf *m) 658 { 659 IF_ENQUEUE(&ifp->receive_queue, m); 660 release_sem_etc(ifp->receive_sem, 1, B_DO_NOT_RESCHEDULE); 661 } 662 663 664 void 665 ether_ifattach(struct ifnet *ifp, const uint8_t *macAddress) 666 { 667 ifp->if_addrlen = ETHER_ADDR_LEN; 668 ifp->if_hdrlen = ETHER_HDR_LEN; 669 if_attach(ifp); 670 ifp->if_mtu = ETHERMTU; 671 ifp->if_output = ether_output; 672 ifp->if_input = ether_input; 673 ifp->if_resolvemulti = NULL; // done in the stack 674 ifp->if_broadcastaddr = etherbroadcastaddr; 675 676 memcpy(IF_LLADDR(ifp), macAddress, ETHER_ADDR_LEN); 677 678 // TODO: according to FreeBSD's if_ethersubr.c, this should be removed 679 // once all drivers are cleaned up. 680 if (macAddress != IFP2ENADDR(ifp)) 681 memcpy(IFP2ENADDR(ifp), macAddress, ETHER_ADDR_LEN); 682 } 683 684 685 void 686 ether_ifdetach(struct ifnet *ifp) 687 { 688 if_detach(ifp); 689 } 690 691 692 int 693 ether_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 694 { 695 struct ifreq *ifr = (struct ifreq *) data; 696 697 switch (command) { 698 case SIOCSIFMTU: 699 if (ifr->ifr_mtu > ETHERMTU) 700 return EINVAL; 701 else 702 ; 703 // need to fix our ifreq to work with C... 704 // ifp->ifr_mtu = ifr->ifr_mtu; 705 break; 706 707 default: 708 return EINVAL; 709 } 710 711 return 0; 712 } 713