static int virtif_clone(struct if_clone *ifc, int num) { struct virtif_sc *sc; struct ifnet *ifp; int error = 0; sc = kmem_zalloc(sizeof(*sc), KM_SLEEP); sc->sc_num = num; ifp = &sc->sc_ec.ec_if; if_initname(ifp, VIF_NAME, num); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_init = virtif_init; ifp->if_ioctl = virtif_ioctl; ifp->if_start = virtif_start; ifp->if_stop = virtif_stop; ifp->if_mtu = ETHERMTU; ifp->if_dlt = DLT_EN10MB; if_attach(ifp); #ifndef RUMP_VIF_LINKSTR /* * if the underlying interface does not expect linkstr, we can * create everything now. Otherwise, we need to wait for * SIOCSLINKSTR. */ #define LINKSTRNUMLEN 16 sc->sc_linkstr = kmem_alloc(LINKSTRNUMLEN, KM_SLEEP); snprintf(sc->sc_linkstr, LINKSTRNUMLEN, "%d", sc->sc_num); #undef LINKSTRNUMLEN error = virtif_create(ifp); if (error) { if_detach(ifp); kmem_free(sc, sizeof(*sc)); ifp->if_softc = NULL; } #endif /* !RUMP_VIF_LINKSTR */ return error; }
int rump_virtif_create(struct ifaliasreq *ia, struct ifnet **ifpp) { return virtif_create(ia, ifpp); }
static int virtif_ioctl(struct ifnet *ifp, u_long cmd, void *data) { struct virtif_sc *sc = ifp->if_softc; int rv; switch (cmd) { #ifdef RUMP_VIF_LINKSTR struct ifdrv *ifd; size_t linkstrlen; #ifndef RUMP_VIF_LINKSTRMAX #define RUMP_VIF_LINKSTRMAX 4096 #endif case SIOCGLINKSTR: ifd = data; if (!sc->sc_linkstr) { rv = ENOENT; break; } linkstrlen = strlen(sc->sc_linkstr)+1; if (ifd->ifd_cmd == IFLINKSTR_QUERYLEN) { ifd->ifd_len = linkstrlen; rv = 0; break; } if (ifd->ifd_cmd != 0) { rv = ENOTTY; break; } rv = copyoutstr(sc->sc_linkstr, ifd->ifd_data, MIN(ifd->ifd_len,linkstrlen), NULL); break; case SIOCSLINKSTR: if (ifp->if_flags & IFF_UP) { rv = EBUSY; break; } ifd = data; if (ifd->ifd_cmd == IFLINKSTR_UNSET) { panic("unset linkstr not implemented"); } else if (ifd->ifd_cmd != 0) { rv = ENOTTY; break; } else if (sc->sc_linkstr) { rv = EBUSY; break; } if (ifd->ifd_len > RUMP_VIF_LINKSTRMAX) { rv = E2BIG; break; } else if (ifd->ifd_len < 1) { rv = EINVAL; break; } sc->sc_linkstr = kmem_alloc(ifd->ifd_len, KM_SLEEP); rv = copyinstr(ifd->ifd_data, sc->sc_linkstr, ifd->ifd_len, NULL); if (rv) { kmem_free(sc->sc_linkstr, ifd->ifd_len); break; } rv = virtif_create(ifp); if (rv) { kmem_free(sc->sc_linkstr, ifd->ifd_len); } break; #endif /* RUMP_VIF_LINKSTR */ default: if (!sc->sc_linkstr) rv = ENXIO; else rv = ether_ioctl(ifp, cmd, data); if (rv == ENETRESET) rv = 0; break; } return rv; }