* bridge_ioctl: * * Handle a control request from the operator. */
| 787 | * Handle a control request from the operator. |
| 788 | */ |
| 789 | static int |
| 790 | bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) |
| 791 | { |
| 792 | struct bridge_softc *sc = ifp->if_softc; |
| 793 | struct ifreq *ifr = (struct ifreq *)data; |
| 794 | struct bridge_iflist *bif; |
| 795 | struct thread *td = curthread; |
| 796 | union { |
| 797 | struct ifbreq ifbreq; |
| 798 | struct ifbifconf ifbifconf; |
| 799 | struct ifbareq ifbareq; |
| 800 | struct ifbaconf ifbaconf; |
| 801 | struct ifbrparam ifbrparam; |
| 802 | struct ifbropreq ifbropreq; |
| 803 | } args; |
| 804 | struct ifdrv *ifd = (struct ifdrv *) data; |
| 805 | const struct bridge_control *bc; |
| 806 | int error = 0, oldmtu; |
| 807 | |
| 808 | BRIDGE_LOCK(sc); |
| 809 | |
| 810 | switch (cmd) { |
| 811 | case SIOCADDMULTI: |
| 812 | case SIOCDELMULTI: |
| 813 | break; |
| 814 | |
| 815 | case SIOCGDRVSPEC: |
| 816 | case SIOCSDRVSPEC: |
| 817 | if (ifd->ifd_cmd >= bridge_control_table_size) { |
| 818 | error = EINVAL; |
| 819 | break; |
| 820 | } |
| 821 | bc = &bridge_control_table[ifd->ifd_cmd]; |
| 822 | |
| 823 | if (cmd == SIOCGDRVSPEC && |
| 824 | (bc->bc_flags & BC_F_COPYOUT) == 0) { |
| 825 | error = EINVAL; |
| 826 | break; |
| 827 | } |
| 828 | else if (cmd == SIOCSDRVSPEC && |
| 829 | (bc->bc_flags & BC_F_COPYOUT) != 0) { |
| 830 | error = EINVAL; |
| 831 | break; |
| 832 | } |
| 833 | |
| 834 | if (bc->bc_flags & BC_F_SUSER) { |
| 835 | error = priv_check(td, PRIV_NET_BRIDGE); |
| 836 | if (error) |
| 837 | break; |
| 838 | } |
| 839 | |
| 840 | if (ifd->ifd_len != bc->bc_argsize || |
| 841 | ifd->ifd_len > sizeof(args)) { |
| 842 | error = EINVAL; |
| 843 | break; |
| 844 | } |
| 845 | |
| 846 | bzero(&args, sizeof(args)); |
nothing calls this directly
no test coverage detected