int mpw_clone_destroy(struct ifnet *ifp) { struct mpw_softc *sc = ifp->if_softc; int s; ifp->if_flags &= ~IFF_RUNNING; if (sc->sc_smpls.smpls_label) { s = splsoftnet(); rt_ifa_del(&sc->sc_ifa, RTF_MPLS, smplstosa(&sc->sc_smpls)); splx(s); } if_ih_remove(ifp, mpw_input, NULL); if_detach(ifp); free(sc, M_DEVBUF, sizeof(*sc)); return (0); }
int mpw_clone_destroy(struct ifnet *ifp) { struct mpw_softc *sc = ifp->if_softc; struct ifih *ifih = SLIST_FIRST(&ifp->if_inputs); int s; ifp->if_flags &= ~IFF_RUNNING; if (sc->sc_smpls.smpls_label) { s = splsoftnet(); rt_ifa_del(&sc->sc_ifa, RTF_MPLS | RTF_UP, smplstosa(&sc->sc_smpls)); splx(s); } SLIST_REMOVE(&ifp->if_inputs, ifih, ifih, ifih_next); free(ifih, M_DEVBUF, sizeof(*ifih)); if_detach(ifp); free(sc, M_DEVBUF, sizeof(*sc)); return (0); }
int mpw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct ifreq *ifr = (struct ifreq *) data; struct mpw_softc *sc = ifp->if_softc; struct sockaddr_in *sin; struct sockaddr_in *sin_nexthop; int error = 0; int s; struct ifmpwreq imr; switch (cmd) { case SIOCSIFMTU: if (ifr->ifr_mtu < MPE_MTU_MIN || ifr->ifr_mtu > MPE_MTU_MAX) error = EINVAL; else ifp->if_mtu = ifr->ifr_mtu; break; case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_UP)) ifp->if_flags |= IFF_RUNNING; else ifp->if_flags &= ~IFF_RUNNING; break; case SIOCSETMPWCFG: error = suser(curproc, 0); if (error != 0) break; error = copyin(ifr->ifr_data, &imr, sizeof(imr)); if (error != 0) break; /* Teardown all configuration if got no nexthop */ sin = (struct sockaddr_in *) &imr.imr_nexthop; if (sin->sin_addr.s_addr == 0) { s = splsoftnet(); if (rt_ifa_del(&sc->sc_ifa, RTF_MPLS, smplstosa(&sc->sc_smpls)) == 0) sc->sc_smpls.smpls_label = 0; splx(s); memset(&sc->sc_rshim, 0, sizeof(sc->sc_rshim)); memset(&sc->sc_nexthop, 0, sizeof(sc->sc_nexthop)); sc->sc_flags = 0; sc->sc_type = 0; break; } /* Validate input */ if (sin->sin_family != AF_INET || imr.imr_lshim.shim_label > MPLS_LABEL_MAX || imr.imr_lshim.shim_label <= MPLS_LABEL_RESERVED_MAX || imr.imr_rshim.shim_label > MPLS_LABEL_MAX || imr.imr_rshim.shim_label <= MPLS_LABEL_RESERVED_MAX) { error = EINVAL; break; } /* Setup labels and create inbound route */ imr.imr_lshim.shim_label = htonl(imr.imr_lshim.shim_label << MPLS_LABEL_OFFSET); imr.imr_rshim.shim_label = htonl(imr.imr_rshim.shim_label << MPLS_LABEL_OFFSET); if (sc->sc_smpls.smpls_label != imr.imr_lshim.shim_label) { s = splsoftnet(); if (sc->sc_smpls.smpls_label) rt_ifa_del(&sc->sc_ifa, RTF_MPLS, smplstosa(&sc->sc_smpls)); sc->sc_smpls.smpls_label = imr.imr_lshim.shim_label; error = rt_ifa_add(&sc->sc_ifa, RTF_MPLS, smplstosa(&sc->sc_smpls)); splx(s); if (error != 0) { sc->sc_smpls.smpls_label = 0; break; } } /* Apply configuration */ sc->sc_flags = imr.imr_flags; sc->sc_type = imr.imr_type; sc->sc_rshim.shim_label = imr.imr_rshim.shim_label; sc->sc_rshim.shim_label |= MPLS_BOS_MASK; memset(&sc->sc_nexthop, 0, sizeof(sc->sc_nexthop)); sin_nexthop = (struct sockaddr_in *) &sc->sc_nexthop; sin_nexthop->sin_family = sin->sin_family; sin_nexthop->sin_len = sizeof(struct sockaddr_in); sin_nexthop->sin_addr.s_addr = sin->sin_addr.s_addr; break; case SIOCGETMPWCFG: imr.imr_flags = sc->sc_flags; imr.imr_type = sc->sc_type; imr.imr_lshim.shim_label = ((ntohl(sc->sc_smpls.smpls_label & MPLS_LABEL_MASK)) >> MPLS_LABEL_OFFSET); imr.imr_rshim.shim_label = ((ntohl(sc->sc_rshim.shim_label & MPLS_LABEL_MASK)) >> MPLS_LABEL_OFFSET); memcpy(&imr.imr_nexthop, &sc->sc_nexthop, sizeof(imr.imr_nexthop)); error = copyout(&imr, ifr->ifr_data, sizeof(imr)); break; default: error = ENOTTY; break; } return (error); }