| 549 | } |
| 550 | |
| 551 | static int |
| 552 | in_difaddr_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, struct thread *td) |
| 553 | { |
| 554 | const struct ifreq *ifr = (struct ifreq *)data; |
| 555 | const struct sockaddr_in *addr = (const struct sockaddr_in *) |
| 556 | &ifr->ifr_addr; |
| 557 | struct ifaddr *ifa; |
| 558 | struct in_ifaddr *ia; |
| 559 | bool deleteAny, iaIsLast; |
| 560 | int error; |
| 561 | |
| 562 | if (td != NULL) { |
| 563 | error = priv_check(td, PRIV_NET_DELIFADDR); |
| 564 | if (error) |
| 565 | return (error); |
| 566 | } |
| 567 | |
| 568 | if (addr->sin_len != sizeof(struct sockaddr_in) || |
| 569 | addr->sin_family != AF_INET) |
| 570 | deleteAny = true; |
| 571 | else |
| 572 | deleteAny = false; |
| 573 | |
| 574 | iaIsLast = true; |
| 575 | ia = NULL; |
| 576 | IF_ADDR_WLOCK(ifp); |
| 577 | CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { |
| 578 | struct in_ifaddr *it; |
| 579 | |
| 580 | if (ifa->ifa_addr->sa_family != AF_INET) |
| 581 | continue; |
| 582 | |
| 583 | it = (struct in_ifaddr *)ifa; |
| 584 | if (deleteAny && ia == NULL && (td == NULL || |
| 585 | prison_check_ip4(td->td_ucred, &it->ia_addr.sin_addr) == 0)) |
| 586 | ia = it; |
| 587 | |
| 588 | if (it->ia_addr.sin_addr.s_addr == addr->sin_addr.s_addr && |
| 589 | (td == NULL || prison_check_ip4(td->td_ucred, |
| 590 | &addr->sin_addr) == 0)) |
| 591 | ia = it; |
| 592 | |
| 593 | if (it != ia) |
| 594 | iaIsLast = false; |
| 595 | } |
| 596 | |
| 597 | if (ia == NULL) { |
| 598 | IF_ADDR_WUNLOCK(ifp); |
| 599 | return (EADDRNOTAVAIL); |
| 600 | } |
| 601 | |
| 602 | CK_STAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifaddr, ifa_link); |
| 603 | IF_ADDR_WUNLOCK(ifp); |
| 604 | ifa_free(&ia->ia_ifa); /* if_addrhead */ |
| 605 | |
| 606 | IN_IFADDR_WLOCK(); |
| 607 | CK_STAILQ_REMOVE(&V_in_ifaddrhead, ia, in_ifaddr, ia_link); |
| 608 | LIST_REMOVE(ia, ia_hash); |
no test coverage detected