예제 #1
0
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;
}
예제 #2
0
int
rump_virtif_create(struct ifaliasreq *ia, struct ifnet **ifpp)
{

	return virtif_create(ia, ifpp);
}
예제 #3
0
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;
}