int
if_address(const struct interface *iface, const struct in_addr *address,
    const struct in_addr *netmask, const struct in_addr *broadcast,
    int action)
{
	int retval;
	struct ifaliasreq ifa;
	union {
		struct sockaddr *sa;
		struct sockaddr_in *sin;
	} _s;

	memset(&ifa, 0, sizeof(ifa));
	strlcpy(ifa.ifra_name, iface->name, sizeof(ifa.ifra_name));

#define ADDADDR(_var, _addr) {						      \
		_s.sa = &_var;						      \
		_s.sin->sin_family = AF_INET;				      \
		_s.sin->sin_len = sizeof(*_s.sin);			      \
		memcpy(&_s.sin->sin_addr, _addr, sizeof(_s.sin->sin_addr));   \
	}

	ADDADDR(ifa.ifra_addr, address);
	ADDADDR(ifa.ifra_mask, netmask);
	if (action >= 0 && broadcast) {
		ADDADDR(ifa.ifra_broadaddr, broadcast);
	}
#undef ADDADDR

	if (action < 0)
		retval = ifioctl(socket_afnet, SIOCDIFADDR, &ifa, curlwp);
	else
		retval = ifioctl(socket_afnet, SIOCAIFADDR, &ifa, curlwp);
	return retval;
}
Exemple #2
0
int
init_interface(const char *ifname, struct interface **ifacep)
{
	struct ifnet *ifp;
	struct ifreq ifr;
	struct interface *iface = NULL;
	int error;

	ifp = ifunit(ifname);
	if (!ifp)
		return EXDEV;

	memset(&ifr, 0, sizeof(ifr));
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
	if ((error = ifioctl(socket_afnet, SIOCGIFFLAGS, &ifr, curlwp)) != 0)
		goto eexit;

	iface = kmem_zalloc(sizeof(*iface), KM_SLEEP);
	strlcpy(iface->name, ifname, sizeof(iface->name));
	iface->ifp = ifp;
	iface->flags = ifr.ifr_flags;
	/* We reserve the 100 range for virtual interfaces, if and when
	 * we can work them out. */
	iface->metric = 200 + iface->ifp->if_index;
	if (getifssid(ifname, iface->ssid) == 0) {
		iface->wireless = 1;
		iface->metric += 100;
	}

	if (ifioctl(socket_afnet, SIOCGIFMTU, &ifr, curlwp) != 0)
		goto eexit;
	/* Ensure that the MTU is big enough for DHCP */
	if (ifr.ifr_mtu < MTU_MIN) {
		ifr.ifr_mtu = MTU_MIN;
		strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
		if ((error = ifioctl(socket_afnet,
		    SIOCSIFMTU, &ifr, curlwp)) != 0)
			goto eexit;
	}

	/* 0 is a valid fd, so init to -1 */
	iface->raw_fd = -1;
	iface->udp_fd = -1;
	iface->arp_fd = -1;

 eexit:
	if (error) {
		kmem_free(iface, sizeof(*iface));
		iface = NULL;
	}

	*ifacep = iface;
	return error;
}
Exemple #3
0
static int
so_ioctl (rtems_libio_t *iop, struct socket *so, uint32_t   command, void *buffer)
{
	switch (command) {
	case FIONBIO:
		if (*(int *)buffer) {
			iop->flags |= O_NONBLOCK;
			so->so_state |= SS_NBIO;
		}
		else {
			iop->flags &= ~O_NONBLOCK;
			so->so_state &= ~SS_NBIO;
		}
		return 0;

	case FIONREAD:
		*(int *)buffer = so->so_rcv.sb_cc;
		return 0;
	}

	if (IOCGROUP(command) == 'i')
		return ifioctl (so, command, buffer, NULL);
	if (IOCGROUP(command) == 'r')
		return rtioctl (command, buffer, NULL);
	return (*so->so_proto->pr_usrreqs->pru_control)(so, command, buffer, 0);
}
Exemple #4
0
static int
ff_veth_setaddr(struct ff_veth_softc *sc)
{
    struct in_aliasreq req;
    bzero(&req, sizeof req);
    strcpy(req.ifra_name, sc->ifp->if_dname);

    struct sockaddr_in sa;
    bzero(&sa, sizeof(sa));
    sa.sin_len = sizeof(sa);
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = sc->ip;
    bcopy(&sa, &req.ifra_addr, sizeof(sa));

    sa.sin_addr.s_addr = sc->netmask;
    bcopy(&sa, &req.ifra_mask, sizeof(sa));

    sa.sin_addr.s_addr = sc->broadcast;
    bcopy(&sa, &req.ifra_broadaddr, sizeof(sa));

    struct socket *so = NULL;
    socreate(AF_INET, &so, SOCK_DGRAM, 0, curthread->td_ucred, curthread);
    int ret = ifioctl(so, SIOCAIFADDR, (caddr_t)&req, curthread);

    sofree(so);

    return ret;
}
Exemple #5
0
int
nfs_boot_deladdress(struct ifnet *ifp, struct lwp *lwp, uint32_t addr)
{
	struct socket *so;
	struct ifreq ifr;
	struct sockaddr_in sin;
	struct in_addr ia = {.s_addr = addr};
	int error;

	/*
	 * Get a socket to use for various things in here.
	 * After this, use "goto out" to cleanup and return.
	 */
	error = socreate(AF_INET, &so, SOCK_DGRAM, 0, lwp, NULL);
	if (error) {
		printf("deladdress: socreate, error=%d\n", error);
		return (error);
	}

	memset(&ifr, 0, sizeof(ifr));
	memcpy(ifr.ifr_name, ifp->if_xname, IFNAMSIZ);

	sockaddr_in_init(&sin, &ia, 0);
	ifreq_setaddr(SIOCDIFADDR, &ifr, sintocsa(&sin)); 

	error = ifioctl(so, SIOCDIFADDR, &ifr, lwp);
	if (error) {
		printf("deladdress, error=%d\n", error);
		goto out;
	}

out:
	soclose(so);
	return (error);
}
Exemple #6
0
int
nfs_boot_ifupdown(struct ifnet *ifp, struct lwp *lwp, int up)
{
	struct socket *so;
	struct ifreq ireq;
	int error;

	memset(&ireq, 0, sizeof(ireq));
	memcpy(ireq.ifr_name, ifp->if_xname, IFNAMSIZ);

	/*
	 * Get a socket to use for various things in here.
	 * After this, use "goto out" to cleanup and return.
	 */
	error = socreate(AF_INET, &so, SOCK_DGRAM, 0, lwp, NULL);
	if (error) {
		printf("ifupdown: socreate, error=%d\n", error);
		return (error);
	}

	/*
	 * Bring up the interface. (just set the "up" flag)
	 * Get the old interface flags and or IFF_UP into them so
	 * things like media selection flags are not clobbered.
	 */
	error = ifioctl(so, SIOCGIFFLAGS, (void *)&ireq, lwp);
	if (error) {
		printf("ifupdown: GIFFLAGS, error=%d\n", error);
		goto out;
	}
	if (up)
		ireq.ifr_flags |= IFF_UP;
	else
		ireq.ifr_flags &= ~IFF_UP;
	error = ifioctl(so, SIOCSIFFLAGS, &ireq, lwp);
	if (error) {
		printf("ifupdown: SIFFLAGS, error=%d\n", error);
		goto out;
	}

	if (up)
		/* give the link some time to get up */
		tsleep(nfs_boot_ifupdown, PZERO, "nfsbif", 3 * hz);
out:
	soclose(so);
	return (error);
}
int
soo_ioctl(struct file *fp, u_long cmd, caddr_t data, struct proc *p)
{
	struct socket *so = (struct socket *)fp->f_data;

	switch (cmd) {

	case FIONBIO:
		if (*(int *)data)
			so->so_state |= SS_NBIO;
		else
			so->so_state &= ~SS_NBIO;
		return (0);

	case FIOASYNC:
		if (*(int *)data) {
			so->so_state |= SS_ASYNC;
			so->so_rcv.sb_flags |= SB_ASYNC;
			so->so_snd.sb_flags |= SB_ASYNC;
		} else {
			so->so_state &= ~SS_ASYNC;
			so->so_rcv.sb_flags &= ~SB_ASYNC;
			so->so_snd.sb_flags &= ~SB_ASYNC;
		}
		return (0);

	case FIONREAD:
		*(int *)data = so->so_rcv.sb_datacc;
		return (0);

	case SIOCSPGRP:
		so->so_pgid = *(int *)data;
		so->so_siguid = p->p_cred->p_ruid;
		so->so_sigeuid = p->p_ucred->cr_uid;
		return (0);

	case SIOCGPGRP:
		*(int *)data = so->so_pgid;
		return (0);

	case SIOCATMARK:
		*(int *)data = (so->so_state&SS_RCVATMARK) != 0;
		return (0);
	}
	/*
	 * Interface/routing/protocol specific ioctls:
	 * interface and routing ioctls should have a
	 * different entry since a socket's unnecessary
	 */
	if (IOCGROUP(cmd) == 'i')
		return (ifioctl(so, cmd, data, p));
	if (IOCGROUP(cmd) == 'r')
		return (rtioctl(cmd, data, p));
	return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 
	    (struct mbuf *)cmd, (struct mbuf *)data, (struct mbuf *)0, p));
}
Exemple #8
0
int
nfs_boot_setaddress(struct ifnet *ifp, struct lwp *lwp,
		uint32_t addr, uint32_t netmask, uint32_t braddr)
{
	struct socket *so;
	struct ifaliasreq iareq;
	struct sockaddr_in *sin;
	int error;

	/*
	 * Get a socket to use for various things in here.
	 * After this, use "goto out" to cleanup and return.
	 */
	error = socreate(AF_INET, &so, SOCK_DGRAM, 0, lwp, NULL);
	if (error) {
		printf("setaddress: socreate, error=%d\n", error);
		return (error);
	}

	memset(&iareq, 0, sizeof(iareq));
	memcpy(iareq.ifra_name, ifp->if_xname, IFNAMSIZ);

	/* Set the I/F address */
	sin = (struct sockaddr_in *)&iareq.ifra_addr;
	sin->sin_len = sizeof(*sin);
	sin->sin_family = AF_INET;
	sin->sin_addr.s_addr = addr;

	/* Set the netmask */
	if (netmask != INADDR_ANY) {
		sin = (struct sockaddr_in *)&iareq.ifra_mask;
		sin->sin_len = sizeof(*sin);
		sin->sin_family = AF_INET;
		sin->sin_addr.s_addr = netmask;
	} /* else leave subnetmask unspecified (len=0) */

	/* Set the broadcast addr. */
	if (braddr != INADDR_ANY) {
		sin = (struct sockaddr_in *)&iareq.ifra_broadaddr;
		sin->sin_len = sizeof(*sin);
		sin->sin_family = AF_INET;
		sin->sin_addr.s_addr = braddr;
	} /* else leave broadcast addr unspecified (len=0) */

	error = ifioctl(so, SIOCAIFADDR, (void *)&iareq, lwp);
	if (error) {
		printf("setaddress, error=%d\n", error);
		goto out;
	}

	/* give the link some time to get up */
	tsleep(nfs_boot_setaddress, PZERO, "nfsbtd", 3 * hz);
out:
	soclose(so);
	return (error);
}
Exemple #9
0
static int
uinet_ifconfig_do(struct socket *so, unsigned long what, void *req)
{
	int error;

	error = ifioctl(so, what, (caddr_t)req, curthread);
	if (error != 0)
		printf("ifioctl 0x%08lx failed %d\n", what, error);

	return (error);
}
Exemple #10
0
static int
wrapifioctl(struct socket *so, u_long cmd, void *data)
{
	int rv;

	KERNEL_LOCK(1, NULL);
	rv = ifioctl(so, cmd, data, curlwp);
	KERNEL_UNLOCK_ONE(NULL);

	return rv;
}
Exemple #11
0
int
do_mtu(const char *ifname, short int mtu)
{
	struct ifreq ifr;

	memset(&ifr, 0, sizeof(ifr));
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
	ifr.ifr_mtu = mtu;
	if (ifioctl(socket_afnet, mtu ? SIOCSIFMTU : SIOCGIFMTU, &ifr, curlwp))
		return -1;
	return ifr.ifr_mtu;
}
Exemple #12
0
int
carrier_status(struct interface *iface)
{
	int ret;
	struct ifreq ifr;
	struct ifmediareq ifmr;

	memset(&ifr, 0, sizeof(ifr));
	strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));

	if ((ret = ifioctl(socket_afnet, SIOCGIFFLAGS, &ifr, curlwp)) != 0)
		return ret;
	iface->flags = ifr.ifr_flags;

	ret = -1;
	memset(&ifmr, 0, sizeof(ifmr));
	strlcpy(ifmr.ifm_name, iface->name, sizeof(ifmr.ifm_name));
	if (ifioctl(socket_afnet, SIOCGIFMEDIA, &ifmr, curlwp) == 0 &&
	    ifmr.ifm_status & IFM_AVALID)
		ret = (ifmr.ifm_status & IFM_ACTIVE) ? 1 : 0;
	if (ret != 0)
		ret = (ifr.ifr_flags & IFF_RUNNING) ? 1 : 0;
	return ret;
}
Exemple #13
0
static int bsd_ioctl     (struct CYG_FILE_TAG *fp, CYG_ADDRWORD cmd,
                                CYG_ADDRWORD data)
{
	register struct socket *so = (struct socket *)fp->f_data;
        void *p = 0;

	switch (cmd) {

	case FIONBIO:
		if (*(int *)data)
			so->so_state |= SS_NBIO;
		else
			so->so_state &= ~SS_NBIO;
		return (0);

	case FIOASYNC:
		if (*(int *)data) {
			so->so_state |= SS_ASYNC;
			so->so_rcv.sb_flags |= SB_ASYNC;
			so->so_snd.sb_flags |= SB_ASYNC;
		} else {
			so->so_state &= ~SS_ASYNC;
			so->so_rcv.sb_flags &= ~SB_ASYNC;
			so->so_snd.sb_flags &= ~SB_ASYNC;
		}
		return (0);

	case FIONREAD:
		*(int *)data = so->so_rcv.sb_cc;
		return (0);

	case SIOCATMARK:
		*(int *)data = (so->so_state&SS_RCVATMARK) != 0;
		return (0);
	}
	/*
	 * Interface/routing/protocol specific ioctls:
	 * interface and routing ioctls should have a
	 * different entry since a socket's unnecessary
	 */
	if (IOCGROUP(cmd) == 'i')
		return (ifioctl(so, (u_long)cmd, (caddr_t)data, p));
	if (IOCGROUP(cmd) == 'r')
		return (rtioctl((u_long)cmd, (caddr_t)data, p));
	return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 
	    (struct mbuf *)cmd, (struct mbuf *)data, (struct mbuf *)0));

}
Exemple #14
0
/*
 * Create a socket and call ifioctl() to configure the interface.
 * This trickles down to virtif_ioctl().
 */
static int
configaddr(struct ifnet *ifp, struct ifaliasreq *ia)
{
	struct socket *so;
	int error;

	strcpy(ia->ifra_name, ifp->if_xname);
	error = socreate(ia->ifra_addr.sa_family, &so, SOCK_DGRAM,
	    0, curlwp, NULL);
	if (error)
		return error;
	error = ifioctl(so, SIOCAIFADDR, ia, curlwp);
	soclose(so);

	return error;
}
int
getifssid(const char *ifname, char *ssid)
{
	struct ifreq ifr;
	struct ieee80211_nwid nwid;
	int error;

	memset(&ifr, 0, sizeof(ifr));
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
	memset(&nwid, 0, sizeof(nwid));
	ifr.ifr_data = (void *)&nwid;
	if ((error = ifioctl(socket_afnet,
	    SIOCG80211NWID, &ifr, curlwp)) == 0) {
		memcpy(ssid, nwid.i_nwid, nwid.i_len);
		ssid[nwid.i_len] = '\0';
	}

	return error;
}
Exemple #16
0
static void
dhcp_context_free(struct dhcp_context * context, struct proc * procp)
{
    if (context == NULL) {
	return;
    }
    if (context->so != NULL) {
	int		error;

	/* disable reception of DHCP packets before address assignment */
	context->ifr.ifr_intval = 0;
	error = ifioctl(context->so, SIOCAUTOADDR,
			(caddr_t)&context->ifr, procp);
	if (error) {
	    printf("dhcp: SIOCAUTOADDR failed: %d\n", error);
	}
	soclose(context->so);
    }
    kfree(context, sizeof(*context));
    return;
}
Exemple #17
0
__private_extern__ int
inet_aifaddr(struct socket * so, const char * name,
	     const struct in_addr * addr, 
	     const struct in_addr * mask,
	     const struct in_addr * broadcast)
{
    struct ifaliasreq	ifra;

    bzero(&ifra, sizeof(ifra));
    strlcpy(ifra.ifra_name, name, sizeof(ifra.ifra_name));
    if (addr) {
	*((struct sockaddr_in *)&ifra.ifra_addr) = blank_sin;
	((struct sockaddr_in *)&ifra.ifra_addr)->sin_addr = *addr;
    }
    if (mask) {
	*((struct sockaddr_in *)&ifra.ifra_mask) = blank_sin;
	((struct sockaddr_in *)&ifra.ifra_mask)->sin_addr = *mask;
    }
    if (broadcast) {
	*((struct sockaddr_in *)&ifra.ifra_broadaddr) = blank_sin;
	((struct sockaddr_in *)&ifra.ifra_broadaddr)->sin_addr = *broadcast;
    }
    return (ifioctl(so, SIOCAIFADDR, (caddr_t)&ifra, current_proc()));
}
Exemple #18
0
int
libcfs_ipif_enumerate (char ***namesp)
{
        /* Allocate and fill in 'names', returning # interfaces/error */
        char           **names;
        int             toobig;
        int             nalloc;
        int             nfound;
        struct socket  *so;
        struct ifreq   *ifr;
        struct ifconf   ifc;
        int             rc;
        int             nob;
        int             i;
        CFS_DECL_FUNNEL_DATA;

        CFS_NET_IN;
        rc = socreate(PF_INET, &so, SOCK_STREAM, 0);
        CFS_NET_EX;
        if (rc != 0) {
                CERROR ("Can't create socket: %d\n", rc);
                return (-rc);
        }

        nalloc = 16;    /* first guess at max interfaces */
        toobig = 0;
        for (;;) {
                if (nalloc * sizeof(*ifr) > CFS_PAGE_SIZE) {
                        toobig = 1;
                        nalloc = CFS_PAGE_SIZE/sizeof(*ifr);
                        CWARN("Too many interfaces: only enumerating first %d\n",
                              nalloc);
                }

                LIBCFS_ALLOC(ifr, nalloc * sizeof(*ifr));
                if (ifr == NULL) {
                        CERROR ("ENOMEM enumerating up to %d interfaces\n", nalloc);
                                rc = -ENOMEM;
                        goto out0;
                }
                                
                ifc.ifc_buf = (char *)ifr;
                ifc.ifc_len = nalloc * sizeof(*ifr);
                                        
                CFS_NET_IN;
                rc = -ifioctl(so, SIOCGIFCONF, (caddr_t)&ifc, current_proc());
                CFS_NET_EX;
                                
                if (rc < 0) {
                        CERROR ("Error %d enumerating interfaces\n", rc);
                        goto out1;
                }

                nfound = ifc.ifc_len/sizeof(*ifr);
                LASSERT (nfound <= nalloc);

                if (nfound < nalloc || toobig)
                        break;

                LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
                nalloc *= 2;
        }
        if (nfound == 0)
                goto out1;

        LIBCFS_ALLOC(names, nfound * sizeof(*names));
        if (names == NULL) {
                rc = -ENOMEM;
                goto out1;
        }
        /* NULL out all names[i] */
        memset (names, 0, nfound * sizeof(*names));

        for (i = 0; i < nfound; i++) {

                nob = strnlen (ifr[i].ifr_name, IFNAMSIZ);
                if (nob == IFNAMSIZ) {
                        /* no space for terminating NULL */
                        CERROR("interface name %.*s too long (%d max)\n",
                               nob, ifr[i].ifr_name, IFNAMSIZ);
                        rc = -ENAMETOOLONG;
                        goto out2;
                }

                LIBCFS_ALLOC(names[i], IFNAMSIZ);
                if (names[i] == NULL) {
                        rc = -ENOMEM;
                        goto out2;
                }

                memcpy(names[i], ifr[i].ifr_name, nob);
                names[i][nob] = 0;
        }

        *namesp = names;
        rc = nfound;

out2:
        if (rc < 0)
                libcfs_ipif_free_enumeration(names, nfound);
out1:
        LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
out0:
        CFS_NET_IN;
        soclose(so);
        CFS_NET_EX;
        return rc;
}
Exemple #19
0
/*
 * Mount a remote root fs via. nfs. This depends on the info in the
 * nfs_diskless structure that has been filled in properly by some primary
 * bootstrap.
 * It goes something like this:
 * - do enough of "ifconfig" by calling ifioctl() so that the system
 *   can talk to the server
 * - If nfs_diskless.mygateway is filled in, use that address as
 *   a default gateway.
 * - build the rootfs mount point and call mountnfs() to do the rest.
 */
int
nfs_mountroot(struct mount *mp)
{
	struct mount  *swap_mp;
	struct nfsv3_diskless *nd = &nfsv3_diskless;
	struct socket *so;
	struct vnode *vp;
	struct thread *td = curthread;		/* XXX */
	int error, i;
	u_long l;
	char buf[128];

#if defined(BOOTP_NFSROOT) && defined(BOOTP)
	bootpc_init();		/* use bootp to get nfs_diskless filled in */
#endif

	/*
	 * XXX time must be non-zero when we init the interface or else
	 * the arp code will wedge...
	 */
	while (mycpu->gd_time_seconds == 0)
		tsleep(mycpu, 0, "arpkludge", 10);

	/*
	 * The boot code may have passed us a diskless structure.
	 */
	kprintf("DISKLESS %d\n", nfs_diskless_valid);
	if (nfs_diskless_valid == 1)
		nfs_convert_diskless();

	/*
	 * NFSv3 is required.
	 */
	nd->root_args.flags |= NFSMNT_NFSV3 | NFSMNT_RDIRPLUS;
	nd->swap_args.flags |= NFSMNT_NFSV3;

#define SINP(sockaddr)	((struct sockaddr_in *)(sockaddr))
	kprintf("nfs_mountroot: interface %s ip %s",
		nd->myif.ifra_name,
		inet_ntoa(SINP(&nd->myif.ifra_addr)->sin_addr));
	kprintf(" bcast %s",
		inet_ntoa(SINP(&nd->myif.ifra_broadaddr)->sin_addr));
	kprintf(" mask %s\n",
		inet_ntoa(SINP(&nd->myif.ifra_mask)->sin_addr));
#undef SINP

	/*
	 * XXX splnet, so networks will receive...
	 */
	crit_enter();

	/*
	 * BOOTP does not necessarily have to be compiled into the kernel
	 * for an NFS root to work.  If we inherited the network
	 * configuration for PXEBOOT then pxe_setup_nfsdiskless() has figured
	 * out our interface for us and all we need to do is ifconfig the
	 * interface.  We only do this if the interface has not already been
	 * ifconfig'd by e.g. BOOTP.
	 */
	error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0, td);
	if (error) {
		panic("nfs_mountroot: socreate(%04x): %d",
			nd->myif.ifra_addr.sa_family, error);
	}

	error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, proc0.p_ucred);
	if (error)
		panic("nfs_mountroot: SIOCAIFADDR: %d", error);

	soclose(so, FNONBLOCK);

	/*
	 * If the gateway field is filled in, set it as the default route.
	 */
	if (nd->mygateway.sin_len != 0) {
		struct sockaddr_in mask, sin;

		bzero((caddr_t)&mask, sizeof(mask));
		sin = mask;
		sin.sin_family = AF_INET;
		sin.sin_len = sizeof(sin);
		kprintf("nfs_mountroot: gateway %s\n",
			inet_ntoa(nd->mygateway.sin_addr));
		error = rtrequest_global(RTM_ADD, (struct sockaddr *)&sin,
					(struct sockaddr *)&nd->mygateway,
					(struct sockaddr *)&mask,
					RTF_UP | RTF_GATEWAY);
		if (error)
			kprintf("nfs_mountroot: unable to set gateway, error %d, continuing anyway\n", error);
	}

	/*
	 * Create the rootfs mount point.
	 */
	nd->root_args.fh = nd->root_fh;
	nd->root_args.fhsize = nd->root_fhsize;
	l = ntohl(nd->root_saddr.sin_addr.s_addr);
	ksnprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
		(l >> 24) & 0xff, (l >> 16) & 0xff,
		(l >>  8) & 0xff, (l >>  0) & 0xff,nd->root_hostnam);
	kprintf("NFS_ROOT: %s\n",buf);
	error = nfs_mountdiskless(buf, "/", MNT_RDONLY, &nd->root_saddr,
				  &nd->root_args, td, &vp, &mp);
	if (error) {
		mp->mnt_vfc->vfc_refcount--;
		crit_exit();
		return (error);
	}

	swap_mp = NULL;
	if (nd->swap_nblks) {

		/* Convert to DEV_BSIZE instead of Kilobyte */
		nd->swap_nblks *= 2;

		/*
		 * Create a fake mount point just for the swap vnode so that the
		 * swap file can be on a different server from the rootfs.
		 */
		nd->swap_args.fh = nd->swap_fh;
		nd->swap_args.fhsize = nd->swap_fhsize;
		l = ntohl(nd->swap_saddr.sin_addr.s_addr);
		ksnprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
			(l >> 24) & 0xff, (l >> 16) & 0xff,
			(l >>  8) & 0xff, (l >>  0) & 0xff,nd->swap_hostnam);
		kprintf("NFS SWAP: %s\n",buf);
		error = nfs_mountdiskless(buf, "/swap", 0, &nd->swap_saddr,
					  &nd->swap_args, td, &vp, &swap_mp);
		if (error) {
			crit_exit();
			return (error);
		}
		vfs_unbusy(swap_mp);

		VTONFS(vp)->n_size = VTONFS(vp)->n_vattr.va_size =
				nd->swap_nblks * DEV_BSIZE ;

		/*
		 * Since the swap file is not the root dir of a file system,
		 * hack it to a regular file.
		 */
		vclrflags(vp, VROOT);
		vref(vp);
		nfs_setvtype(vp, VREG);
		swaponvp(td, vp, nd->swap_nblks);
	}
int
soo_ioctl(file_t *fp, u_long cmd, void *data)
{
	struct socket *so = fp->f_data;
	int error = 0;

	switch (cmd) {

	case FIONBIO:
		solock(so);
		if (*(int *)data)
			so->so_state |= SS_NBIO;
		else 
			so->so_state &= ~SS_NBIO; 
		sounlock(so);
		break;

	case FIOASYNC:
		solock(so);
		if (*(int *)data) {
			so->so_state |= SS_ASYNC;
			so->so_rcv.sb_flags |= SB_ASYNC;
			so->so_snd.sb_flags |= SB_ASYNC;
		} else {
			so->so_state &= ~SS_ASYNC;
			so->so_rcv.sb_flags &= ~SB_ASYNC;
			so->so_snd.sb_flags &= ~SB_ASYNC;
		}
		sounlock(so);
		break;

	case FIONREAD:
		*(int *)data = so->so_rcv.sb_cc;
		break;

	case FIONWRITE:
		*(int *)data = so->so_snd.sb_cc;
		break;

	case FIONSPACE:
		/*
		 * See the comment around sbspace()'s definition
		 * in sys/socketvar.h in face of counts about maximum
		 * to understand the following test. We detect overflow
		 * and return zero.
		 */
		solock(so);
		if ((so->so_snd.sb_hiwat < so->so_snd.sb_cc)
		    || (so->so_snd.sb_mbmax < so->so_snd.sb_mbcnt))
			*(int *)data = 0;
		else
			*(int *)data = sbspace(&so->so_snd);
		sounlock(so);
		break;

	case SIOCSPGRP:
	case FIOSETOWN:
	case TIOCSPGRP:
		error = fsetown(&so->so_pgid, cmd, data);
		break;

	case SIOCGPGRP:
	case FIOGETOWN:
	case TIOCGPGRP:
		error = fgetown(so->so_pgid, cmd, data);
		break;

	case SIOCATMARK:
		*(int *)data = (so->so_state&SS_RCVATMARK) != 0;
		break;

	default:
		/*
		 * Interface/routing/protocol specific ioctls:
		 * interface and routing ioctls should have a
		 * different entry since a socket's unnecessary
		 */
		KERNEL_LOCK(1, NULL);
		if (IOCGROUP(cmd) == 'i')
			error = ifioctl(so, cmd, data, curlwp);
		else if (IOCGROUP(cmd) == 'r')
			error = rtioctl(cmd, data, curlwp);
		else {
			error = (*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
			    (struct mbuf *)cmd, (struct mbuf *)data, NULL,
			     curlwp);
		}
		KERNEL_UNLOCK_ONE(NULL);
		break;
	}


	return error;
}
Exemple #21
0
int
libcfs_ipif_query (char *name, int *up, __u32 *ip, __u32 *mask)
{
        struct socket      *so;
        struct ifreq       ifr;
        int                nob;
        int                rc;
        __u32              val;
        CFS_DECL_FUNNEL_DATA;

        CFS_NET_IN;
        rc = socreate(PF_INET, &so, SOCK_STREAM, 0);
        CFS_NET_EX;
        if (rc != 0) {
                CERROR ("Can't create socket: %d\n", rc);
                return (-rc);
        }
        nob = strnlen(name, IFNAMSIZ);
        if (nob == IFNAMSIZ) {
                CERROR("Interface name %s too long\n", name);
                rc = -EINVAL;
                goto out;
        }

        CLASSERT (sizeof(ifr.ifr_name) >= IFNAMSIZ);
        strcpy(ifr.ifr_name, name);
        CFS_NET_IN;
        rc = ifioctl(so, SIOCGIFFLAGS, (caddr_t)&ifr, current_proc());
        CFS_NET_EX;

        if (rc != 0) {
                CERROR("Can't get flags for interface %s\n", name);
                goto out;
        }
        if ((ifr.ifr_flags & IFF_UP) == 0) {
                CDEBUG(D_NET, "Interface %s down\n", name);
                *up = 0;
                *ip = *mask = 0;
                goto out;
        }
       
        *up = 1;
        strcpy(ifr.ifr_name, name);
        *((struct sockaddr_in *)&ifr.ifr_addr) = blank_sin();
        CFS_NET_IN;
        rc = ifioctl(so, SIOCGIFADDR, (caddr_t)&ifr, current_proc());
        CFS_NET_EX;

        if (rc != 0) {
                CERROR("Can't get IP address for interface %s\n", name);
                goto out;
        }

        val = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
        *ip = ntohl(val);

        strcpy(ifr.ifr_name, name);
        *((struct sockaddr_in *)&ifr.ifr_addr) = blank_sin();
        CFS_NET_IN;
        rc = ifioctl(so, SIOCGIFNETMASK, (caddr_t)&ifr, current_proc());
        CFS_NET_EX;

        if (rc != 0) {
                CERROR("Can't get netmask for interface %s\n", name);
                goto out;
        }

        val = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
        *mask = ntohl(val);
out:
        CFS_NET_IN;
        soclose(so);
        CFS_NET_EX;
        return -rc;
}
Exemple #22
0
int 
bootpc_adjust_interface(struct ifreq *ireq,struct socket *so,
			struct sockaddr_in *myaddr,
			struct sockaddr_in *netmask,
			struct sockaddr_in *gw,
			struct proc *procp)
{
  int error;
  struct sockaddr_in oldgw;
  struct sockaddr_in olddst;
  struct sockaddr_in oldmask;
  struct sockaddr_in *sin;

  /* Remove old default route to 0.0.0.0 */
  
  bzero((caddr_t) &olddst, sizeof(olddst));
  olddst.sin_len=sizeof(olddst);
  olddst.sin_family=AF_INET;
  olddst.sin_addr.s_addr = INADDR_ANY;
  
  bzero((caddr_t) &oldgw, sizeof(oldgw));
  oldgw.sin_len=sizeof(oldgw);
  oldgw.sin_family=AF_INET;
  oldgw.sin_addr.s_addr = INADDR_ANY;
  
  bzero((caddr_t) &oldmask, sizeof(oldmask));
  oldmask.sin_len=sizeof(oldmask);
  oldmask.sin_family=AF_INET;
  oldmask.sin_addr.s_addr = INADDR_ANY;
  
  error = rtrequest(RTM_DELETE, 
		    (struct sockaddr *) &olddst,
		    (struct sockaddr *) &oldgw,
		    (struct sockaddr *) &oldmask, 
		    (RTF_UP | RTF_STATIC), NULL);
  if (error) {
    printf("nfs_boot: del default route, error=%d\n", error);
    return error;
  }

  /*
   * Do enough of ifconfig(8) so that the chosen interface
   * can talk to the servers.  (just set the address)
   */
  bcopy(netmask,&ireq->ifr_addr,sizeof(*netmask));
  error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp);
  if (error) {
    printf("bootpc_adjust_interface: set netmask, error=%s\n", strerror(error));
    return error;
  }

  /* Broadcast is with host part of IP address all 1's */
  
  sin = (struct sockaddr_in *)&ireq->ifr_addr;
  bzero((caddr_t)sin, sizeof(*sin));
  sin->sin_len = sizeof(*sin);
  sin->sin_family = AF_INET;
  sin->sin_addr.s_addr = myaddr->sin_addr.s_addr | ~ netmask->sin_addr.s_addr;
  error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp);
  if (error) {
    printf("bootpc_adjust_interface: set broadcast addr, error=%s\n", strerror(error));
    return error;
  }
  
  bcopy(myaddr,&ireq->ifr_addr,sizeof(*myaddr));
  error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp);
  if (error) {
    printf("bootpc_adjust_interface: set if addr, error=%s\n", strerror(error));
    return error;
  }

  /* Add new default route */

  error = rtrequest(RTM_ADD, 
		    (struct sockaddr *) &olddst,
		    (struct sockaddr *) gw,
		    (struct sockaddr *) &oldmask,
		    (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL);
  if (error) {
    printf("bootpc_adjust_interface: add net route, error=%d\n", error);
  }

  return error;
}
Exemple #23
0
static struct dhcp_context *
dhcp_context_create(struct ifnet * ifp, int max_try,
		    struct proc * procp, int * error_p)
{
    struct dhcp_context	*	context = NULL;
    struct sockaddr_dl *	dl_p;
    struct in_addr		lo_addr;
    struct in_addr		lo_mask;
    int				error;
    struct sockaddr_in		sin;

    /* get the hardware address from the interface */
    dl_p = link_from_ifnet(ifp);
    if (dl_p == NULL) {
	printf("dhcp: can't get link address\n");
	error = ENXIO;
	goto failed;
    }

    printf("dhcp: h/w addr ");
    link_print(dl_p);
    if (dl_p->sdl_type != IFT_ETHER) {
	printf("dhcp: hardware type %d not supported\n",
	       dl_p->sdl_type);
	error = ENXIO;
	goto failed;
    }

    context = (struct dhcp_context *)kalloc(sizeof(*context));
    if (context == NULL) {
	printf("dhcp: failed to allocate context\n");
	error = ENOMEM;
	goto failed;
    }
    bzero(context, sizeof(*context));

    /* get a socket */
    error = socreate(AF_INET, &context->so, SOCK_DGRAM, 0);
    if (error != 0) {
	printf("dhcp: socreate failed %d\n", error);
	goto failed;
    }

    /* assign 127.0.0.1 to lo0 so that the bind will succeed */
    lo_addr.s_addr = htonl(INADDR_LOOPBACK);
    lo_mask.s_addr = htonl(IN_CLASSA_NET);
    error = inet_aifaddr(context->so, "lo0", &lo_addr, &lo_mask, NULL);
    if (error != 0) {
	printf("dhcp: assigning loopback address failed %d\n", error);
    }

    /* enable reception of DHCP packets before an address is assigned */
    snprintf(context->ifr.ifr_name, 
	     sizeof(context->ifr.ifr_name), "%s%d", ifp->if_name,
	     ifp->if_unit);
    context->ifr.ifr_intval = 1;

    error = ifioctl(context->so, SIOCAUTOADDR, (caddr_t)&context->ifr, procp);
    if (error) {
	printf("dhcp: SIOCAUTOADDR failed: %d\n", error);
	goto failed;
    }
    dprintf(("dhcp: SIOCAUTOADDR done\n"));

    error = ifioctl(context->so, SIOCPROTOATTACH, (caddr_t)&context->ifr, 
		    procp);
    if (error) {
	printf("dhcp: SIOCPROTOATTACH failed: %d\n", error);
	goto failed;
    }
    dprintf(("dhcp: SIOCPROTOATTACH done\n"));
    
    /* bind the socket */
    sin.sin_len = sizeof(sin);
    sin.sin_family = AF_INET;
    sin.sin_port = htons(IPPORT_BOOTPC);
    sin.sin_addr.s_addr = INADDR_ANY;
    error = sobind(context->so, (struct sockaddr *)&sin);
    if (error) {
	printf("dhcp: sobind failed, %d\n", error);
	goto failed;
    }

    /* make it non-blocking I/O */
    socket_lock(context->so, 1);
    context->so->so_state |= SS_NBIO;
    socket_unlock(context->so, 1);

    /* save passed-in information */
    context->max_try = max_try;
    context->dl_p = dl_p;
    context->ifp = ifp;

    /* get a random transaction id */
    context->xid = random();

    return (context);

 failed:
    dhcp_context_free(context, procp);
    *error_p = error;
    return (NULL);
}
Exemple #24
0
/*
 * Mount a remote root fs via. nfs. This depends on the info in the
 * nfs_diskless structure that has been filled in properly by some primary
 * bootstrap.
 * It goes something like this:
 * - do enough of "ifconfig" by calling ifioctl() so that the system
 *   can talk to the server
 * - If nfs_diskless.mygateway is filled in, use that address as
 *   a default gateway.
 * - build the rootfs mount point and call mountnfs() to do the rest.
 *
 * It is assumed to be safe to read, modify, and write the nfsv3_diskless
 * structure, as well as other global NFS client variables here, as
 * nfs_mountroot() will be called once in the boot before any other NFS
 * client activity occurs.
 */
int
nfs_mountroot(struct mount *mp)
{
	struct thread *td = curthread;
	struct nfsv3_diskless *nd = &nfsv3_diskless;
	struct socket *so;
	struct vnode *vp;
	struct ifreq ir;
	int error;
	u_long l;
	char buf[128];
	char *cp;


#if defined(BOOTP_NFSROOT) && defined(BOOTP)
	bootpc_init();		/* use bootp to get nfs_diskless filled in */
#elif defined(NFS_ROOT)
	nfs_setup_diskless();
#endif

	if (nfs_diskless_valid == 0) {
		return (-1);
	}
	if (nfs_diskless_valid == 1)
		nfs_convert_diskless();

	/*
	 * XXX splnet, so networks will receive...
	 */
	splnet();

	/*
	 * Do enough of ifconfig(8) so that the critical net interface can
	 * talk to the server.
	 */
	error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
	    td->td_ucred, td);
	if (error)
		panic("nfs_mountroot: socreate(%04x): %d",
			nd->myif.ifra_addr.sa_family, error);

#if 0 /* XXX Bad idea */
	/*
	 * We might not have been told the right interface, so we pass
	 * over the first ten interfaces of the same kind, until we get
	 * one of them configured.
	 */

	for (i = strlen(nd->myif.ifra_name) - 1;
		nd->myif.ifra_name[i] >= '0' &&
		nd->myif.ifra_name[i] <= '9';
		nd->myif.ifra_name[i] ++) {
		error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
		if(!error)
			break;
	}
#endif

	error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
	if (error)
		panic("nfs_mountroot: SIOCAIFADDR: %d", error);

	if ((cp = getenv("boot.netif.mtu")) != NULL) {
		ir.ifr_mtu = strtol(cp, NULL, 10);
		bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
		freeenv(cp);
		error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
		if (error)
			printf("nfs_mountroot: SIOCSIFMTU: %d", error);
	}
	soclose(so);

	/*
	 * If the gateway field is filled in, set it as the default route.
	 * Note that pxeboot will set a default route of 0 if the route
	 * is not set by the DHCP server.  Check also for a value of 0
	 * to avoid panicking inappropriately in that situation.
	 */
	if (nd->mygateway.sin_len != 0 &&
	    nd->mygateway.sin_addr.s_addr != 0) {
		struct sockaddr_in mask, sin;

		bzero((caddr_t)&mask, sizeof(mask));
		sin = mask;
		sin.sin_family = AF_INET;
		sin.sin_len = sizeof(sin);
                /* XXX MRT use table 0 for this sort of thing */
		CURVNET_SET(TD_TO_VNET(td));
		error = rtrequest_fib(RTM_ADD, (struct sockaddr *)&sin,
		    (struct sockaddr *)&nd->mygateway,
		    (struct sockaddr *)&mask,
		    RTF_UP | RTF_GATEWAY, NULL, RT_DEFAULT_FIB);
		CURVNET_RESTORE();
		if (error)
			panic("nfs_mountroot: RTM_ADD: %d", error);
	}

	/*
	 * Create the rootfs mount point.
	 */
	nd->root_args.fh = nd->root_fh;
	nd->root_args.fhsize = nd->root_fhsize;
	l = ntohl(nd->root_saddr.sin_addr.s_addr);
	snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
		(l >> 24) & 0xff, (l >> 16) & 0xff,
		(l >>  8) & 0xff, (l >>  0) & 0xff, nd->root_hostnam);
	printf("NFS ROOT: %s\n", buf);
	nd->root_args.hostname = buf;
	if ((error = nfs_mountdiskless(buf,
	    &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
		return (error);
	}

	/*
	 * This is not really an nfs issue, but it is much easier to
	 * set hostname here and then let the "/etc/rc.xxx" files
	 * mount the right /var based upon its preset value.
	 */
	mtx_lock(&prison0.pr_mtx);
	strlcpy(prison0.pr_hostname, nd->my_hostnam,
	    sizeof (prison0.pr_hostname));
	mtx_unlock(&prison0.pr_mtx);
	inittodr(ntohl(nd->root_time));
	return (0);
}
Exemple #25
0
int 
bootpc_fakeup_interface(struct ifreq *ireq,struct socket *so,
			struct proc *procp)
{
  struct sockaddr_in *sin;
  int error;
  struct sockaddr_in dst;
  struct sockaddr_in gw;
  struct sockaddr_in mask;

  /*
   * Bring up the interface.
   *
   * Get the old interface flags and or IFF_UP into them; if
   * IFF_UP set blindly, interface selection can be clobbered.
   */
  error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, procp);
  if (error) {
    printf("bootpc_fakeup_interface: GIFFLAGS, error=%s\n", strerror(error));
    return error;
  }
  ireq->ifr_flags |= IFF_UP;
  error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, procp);
  if (error) {
    printf("bootpc_fakeup_interface: SIFFLAGS, error=%s\n", strerror(error));
    return error;
  }

  /*
   * Do enough of ifconfig(8) so that the chosen interface
   * can talk to the servers.  (just set the address)
   */
  /* addr is 0.0.0.0 */
  
  sin = (struct sockaddr_in *)&ireq->ifr_addr;
  bzero((caddr_t)sin, sizeof(*sin));
  sin->sin_len = sizeof(*sin);
  sin->sin_family = AF_INET;
  sin->sin_addr.s_addr = INADDR_ANY;
  error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp);
  /*
   * Ignore a File already exists (EEXIST) error code. This means a
   * route for the address is already present and is returned on
   * a second pass to here.
   */
  if (error && (error != EEXIST)) {
    printf("bootpc_fakeup_interface: set if addr, error=%s\n", strerror(error));
    return error;
  }
  
  /* netmask is 0.0.0.0 */
  
  sin = (struct sockaddr_in *)&ireq->ifr_addr;
  bzero((caddr_t)sin, sizeof(*sin));
  sin->sin_len = sizeof(*sin);
  sin->sin_family = AF_INET;
  sin->sin_addr.s_addr = INADDR_ANY;
  error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp);
  if (error) {
    printf("bootpc_fakeup_interface: set if netmask, error=%s\n", strerror(error));
    return error;
  }
  
  /* Broadcast is 255.255.255.255 */
  
  sin = (struct sockaddr_in *)&ireq->ifr_addr;
  bzero((caddr_t)sin, sizeof(*sin));
  sin->sin_len = sizeof(*sin);
  sin->sin_family = AF_INET;
  sin->sin_addr.s_addr = INADDR_BROADCAST;
  error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp);
  if (error) {
    printf("bootpc_fakeup_interface: set broadcast addr, error=%s\n", strerror(error));
    return error;
  }
  
  /* Add default route to 0.0.0.0 so we can send data */
  
  bzero((caddr_t) &dst, sizeof(dst));
  dst.sin_len=sizeof(dst);
  dst.sin_family=AF_INET;
  dst.sin_addr.s_addr = htonl(0);
  
  bzero((caddr_t) &gw, sizeof(gw));
  gw.sin_len=sizeof(gw);
  gw.sin_family=AF_INET;
  gw.sin_addr.s_addr = htonl(0x0);
  
  bzero((caddr_t) &mask, sizeof(mask));
  mask.sin_len=sizeof(mask);
  mask.sin_family=AF_INET;
  mask.sin_addr.s_addr = htonl(0);
  
  error = rtrequest(RTM_ADD, 
		    (struct sockaddr *) &dst, 
		    (struct sockaddr *) &gw,
		    (struct sockaddr *) &mask, 
		    RTF_UP | RTF_STATIC
		    , NULL);
  if (error && error != EEXIST)
    printf("bootpc_fakeup_interface: add default route, error=%s\n",
           strerror(error));
  
  return error;
}
Exemple #26
0
static int
bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
    struct bootpc_globalcontext *gctx, struct thread *td)
{
	int error;
	struct sockaddr_in defdst;
	struct sockaddr_in defmask;
	struct sockaddr_in *sin;
	struct ifreq *ireq;
	struct socket *so;
	struct sockaddr_in *myaddr;
	struct sockaddr_in *netmask;
	struct sockaddr_in *gw;

	ireq = &ifctx->ireq;
	so = ifctx->so;
	myaddr = &ifctx->myaddr;
	netmask = &ifctx->netmask;
	gw = &ifctx->gw;

	if (bootpc_ifctx_isresolved(ifctx) == 0) {

		/* Shutdown interfaces where BOOTP failed */

		printf("Shutdown interface %s\n", ifctx->ireq.ifr_name);
		error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td);
		if (error != 0)
			panic("bootpc_adjust_interface: "
			      "SIOCGIFFLAGS, error=%d", error);
		ireq->ifr_flags &= ~IFF_UP;
		error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td);
		if (error != 0)
			panic("bootpc_adjust_interface: "
			      "SIOCSIFFLAGS, error=%d", error);

		sin = (struct sockaddr_in *) &ireq->ifr_addr;
		clear_sinaddr(sin);
		error = ifioctl(so, SIOCDIFADDR, (caddr_t) ireq, td);
		if (error != 0 && (error != EEXIST ||
				   ifctx == gctx->interfaces))
			panic("bootpc_adjust_interface: "
			      "SIOCDIFADDR, error=%d", error);

		return 0;
	}

	printf("Adjusted interface %s\n", ifctx->ireq.ifr_name);
	/*
	 * Do enough of ifconfig(8) so that the chosen interface
	 * can talk to the servers.  (just set the address)
	 */
	bcopy(netmask, &ireq->ifr_addr, sizeof(*netmask));
	error = ifioctl(so, SIOCSIFNETMASK, (caddr_t) ireq, td);
	if (error != 0)
		panic("bootpc_adjust_interface: "
		      "set if netmask, error=%d", error);

	/* Broadcast is with host part of IP address all 1's */

	sin = (struct sockaddr_in *) &ireq->ifr_addr;
	clear_sinaddr(sin);
	sin->sin_addr.s_addr = myaddr->sin_addr.s_addr |
		~ netmask->sin_addr.s_addr;
	error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t) ireq, td);
	if (error != 0)
		panic("bootpc_adjust_interface: "
		      "set if broadcast addr, error=%d", error);

	bcopy(myaddr, &ireq->ifr_addr, sizeof(*myaddr));
	error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td);
	if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces))
		panic("bootpc_adjust_interface: "
		      "set if addr, error=%d", error);

	/* Add new default route */

	if (ifctx->gotgw != 0 || gctx->gotgw == 0) {
		clear_sinaddr(&defdst);
		clear_sinaddr(&defmask);
		/* XXX MRT just table 0 */
		error = rtrequest_fib(RTM_ADD,
				  (struct sockaddr *) &defdst,
				  (struct sockaddr *) gw,
				  (struct sockaddr *) &defmask,
				  (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL, 0);
		if (error != 0) {
			printf("bootpc_adjust_interface: "
			       "add net route, error=%d\n", error);
			return error;
		}
	}

	return 0;
}
Exemple #27
0
static int
soo_ioctl(struct file *fp, u_long cmd, void *data, struct ucred *active_cred,
    struct thread *td)
{
	struct socket *so = fp->f_data;
	int error = 0;

	switch (cmd) {
	case FIONBIO:
		SOCK_LOCK(so);
		if (*(int *)data)
			so->so_state |= SS_NBIO;
		else
			so->so_state &= ~SS_NBIO;
		SOCK_UNLOCK(so);
		break;

	case FIOASYNC:
		/*
		 * XXXRW: This code separately acquires SOCK_LOCK(so) and
		 * SOCKBUF_LOCK(&so->so_rcv) even though they are the same
		 * mutex to avoid introducing the assumption that they are
		 * the same.
		 */
		if (*(int *)data) {
			SOCK_LOCK(so);
			so->so_state |= SS_ASYNC;
			SOCK_UNLOCK(so);
			SOCKBUF_LOCK(&so->so_rcv);
			so->so_rcv.sb_flags |= SB_ASYNC;
			SOCKBUF_UNLOCK(&so->so_rcv);
			SOCKBUF_LOCK(&so->so_snd);
			so->so_snd.sb_flags |= SB_ASYNC;
			SOCKBUF_UNLOCK(&so->so_snd);
		} else {
			SOCK_LOCK(so);
			so->so_state &= ~SS_ASYNC;
			SOCK_UNLOCK(so);
			SOCKBUF_LOCK(&so->so_rcv);
			so->so_rcv.sb_flags &= ~SB_ASYNC;
			SOCKBUF_UNLOCK(&so->so_rcv);
			SOCKBUF_LOCK(&so->so_snd);
			so->so_snd.sb_flags &= ~SB_ASYNC;
			SOCKBUF_UNLOCK(&so->so_snd);
		}
		break;

	case FIONREAD:
		/* Unlocked read. */
		*(int *)data = sbavail(&so->so_rcv);
		break;

	case FIONWRITE:
		/* Unlocked read. */
		*(int *)data = sbavail(&so->so_snd);
		break;

	case FIONSPACE:
		/* Unlocked read. */
		if ((so->so_snd.sb_hiwat < sbused(&so->so_snd)) ||
		    (so->so_snd.sb_mbmax < so->so_snd.sb_mbcnt))
			*(int *)data = 0;
		else
			*(int *)data = sbspace(&so->so_snd);
		break;

	case FIOSETOWN:
		error = fsetown(*(int *)data, &so->so_sigio);
		break;

	case FIOGETOWN:
		*(int *)data = fgetown(&so->so_sigio);
		break;

	case SIOCSPGRP:
		error = fsetown(-(*(int *)data), &so->so_sigio);
		break;

	case SIOCGPGRP:
		*(int *)data = -fgetown(&so->so_sigio);
		break;

	case SIOCATMARK:
		/* Unlocked read. */
		*(int *)data = (so->so_rcv.sb_state & SBS_RCVATMARK) != 0;
		break;
	default:
		/*
		 * Interface/routing/protocol specific ioctls: interface and
		 * routing ioctls should have a different entry since a
		 * socket is unnecessary.
		 */
		if (IOCGROUP(cmd) == 'i')
			error = ifioctl(so, cmd, data, td);
		else if (IOCGROUP(cmd) == 'r') {
			CURVNET_SET(so->so_vnet);
			error = rtioctl_fib(cmd, data, so->so_fibnum);
			CURVNET_RESTORE();
		} else {
			CURVNET_SET(so->so_vnet);
			error = ((*so->so_proto->pr_usrreqs->pru_control)
			    (so, cmd, data, 0, td));
			CURVNET_RESTORE();
		}
		break;
	}
	return (error);
}
Exemple #28
0
/*
 * MPSAFE
 */
int
soo_ioctl(struct file *fp, u_long cmd, caddr_t data,
	  struct ucred *cred, struct sysmsg *msg)
{
	struct socket *so;
	int error;

	so = (struct socket *)fp->f_data;

	switch (cmd) {
	case FIOASYNC:
		if (*(int *)data) {
			sosetstate(so, SS_ASYNC);
			atomic_set_int(&so->so_rcv.ssb_flags,  SSB_ASYNC);
			atomic_set_int(&so->so_snd.ssb_flags, SSB_ASYNC);
		} else {
			soclrstate(so, SS_ASYNC);
			atomic_clear_int(&so->so_rcv.ssb_flags, SSB_ASYNC);
			atomic_clear_int(&so->so_snd.ssb_flags, SSB_ASYNC);
		}
		error = 0;
		break;
	case FIONREAD:
		*(int *)data = so->so_rcv.ssb_cc;
		error = 0;
		break;
	case FIOSETOWN:
		error = fsetown(*(int *)data, &so->so_sigio);
		break;
	case FIOGETOWN:
		*(int *)data = fgetown(&so->so_sigio);
		error = 0;
		break;
	case SIOCSPGRP:
		error = fsetown(-(*(int *)data), &so->so_sigio);
		break;
	case SIOCGPGRP:
		*(int *)data = -fgetown(&so->so_sigio);
		error = 0;
		break;
	case SIOCATMARK:
		*(int *)data = (so->so_state&SS_RCVATMARK) != 0;
		error = 0;
		break;
	default:
		/*
		 * Interface/routing/protocol specific ioctls:
		 * interface and routing ioctls should have a
		 * different entry since a socket's unnecessary
		 */
		if (IOCGROUP(cmd) == 'i') {
			error = ifioctl(so, cmd, data, cred);
		} else if (IOCGROUP(cmd) == 'r') {
			error = rtioctl(cmd, data, cred);
		} else {
			error = so_pru_control_direct(so, cmd, data, NULL);
		}
		break;
	}
	return (error);
}
Exemple #29
0
static int
bootpc_call(struct bootpc_globalcontext *gctx, struct thread *td)
{
	struct socket *so;
	struct sockaddr_in *sin, dst;
	struct uio auio;
	struct sockopt sopt;
	struct iovec aio;
	int error, on, rcvflg, timo, len;
	time_t atimo;
	time_t rtimo;
	struct timeval tv;
	struct bootpc_ifcontext *ifctx;
	int outstanding;
	int gotrootpath;
	int retry;
	const char *s;

	/*
	 * Create socket and set its recieve timeout.
	 */
	error = socreate(AF_INET, &so, SOCK_DGRAM, 0, td->td_ucred, td);
	if (error != 0)
		goto out0;

	tv.tv_sec = 1;
	tv.tv_usec = 0;
	bzero(&sopt, sizeof(sopt));
	sopt.sopt_dir = SOPT_SET;
	sopt.sopt_level = SOL_SOCKET;
	sopt.sopt_name = SO_RCVTIMEO;
	sopt.sopt_val = &tv;
	sopt.sopt_valsize = sizeof tv;

	error = sosetopt(so, &sopt);
	if (error != 0)
		goto out;

	/*
	 * Enable broadcast.
	 */
	on = 1;
	sopt.sopt_name = SO_BROADCAST;
	sopt.sopt_val = &on;
	sopt.sopt_valsize = sizeof on;

	error = sosetopt(so, &sopt);
	if (error != 0)
		goto out;

	/*
	 * Disable routing.
	 */

	on = 1;
	sopt.sopt_name = SO_DONTROUTE;
	sopt.sopt_val = &on;
	sopt.sopt_valsize = sizeof on;

	error = sosetopt(so, &sopt);
	if (error != 0)
		goto out;

	/*
	 * Bind the local endpoint to a bootp client port.
	 */
	sin = &dst;
	clear_sinaddr(sin);
	sin->sin_port = htons(IPPORT_BOOTPC);
	error = sobind(so, (struct sockaddr *)sin, td);
	if (error != 0) {
		printf("bind failed\n");
		goto out;
	}

	/*
	 * Setup socket address for the server.
	 */
	sin = &dst;
	clear_sinaddr(sin);
	sin->sin_addr.s_addr = INADDR_BROADCAST;
	sin->sin_port = htons(IPPORT_BOOTPS);

	/*
	 * Send it, repeatedly, until a reply is received,
	 * but delay each re-send by an increasing amount.
	 * If the delay hits the maximum, start complaining.
	 */
	timo = 0;
	rtimo = 0;
	for (;;) {

		outstanding = 0;
		gotrootpath = 0;

		for (ifctx = gctx->interfaces;
		     ifctx != NULL;
		     ifctx = ifctx->next) {
			if (bootpc_ifctx_isresolved(ifctx) != 0 &&
			    bootpc_tag(&gctx->tmptag, &ifctx->reply,
				       ifctx->replylen,
				       TAG_ROOT) != NULL)
				gotrootpath = 1;
		}

		for (ifctx = gctx->interfaces;
		     ifctx != NULL;
		     ifctx = ifctx->next) {
			ifctx->outstanding = 0;
			if (bootpc_ifctx_isresolved(ifctx)  != 0 &&
			    gotrootpath != 0) {
				continue;
			}
			if (bootpc_ifctx_isfailed(ifctx) != 0)
				continue;

			outstanding++;
			ifctx->outstanding = 1;

			/* Proceed to next step in DHCP negotiation */
			if ((ifctx->state == IF_DHCP_OFFERED &&
			     ifctx->dhcpquerytype != DHCP_REQUEST) ||
			    (ifctx->state == IF_DHCP_UNRESOLVED &&
			     ifctx->dhcpquerytype != DHCP_DISCOVER) ||
			    (ifctx->state == IF_BOOTP_UNRESOLVED &&
			     ifctx->dhcpquerytype != DHCP_NOMSG)) {
				ifctx->sentmsg = 0;
				bootpc_compose_query(ifctx, gctx, td);
			}

			/* Send BOOTP request (or re-send). */

			if (ifctx->sentmsg == 0) {
				switch(ifctx->dhcpquerytype) {
				case DHCP_DISCOVER:
					s = "DHCP Discover";
					break;
				case DHCP_REQUEST:
					s = "DHCP Request";
					break;
				case DHCP_NOMSG:
				default:
					s = "BOOTP Query";
					break;
				}
				printf("Sending %s packet from "
				       "interface %s (%*D)\n",
				       s,
				       ifctx->ireq.ifr_name,
				       ifctx->sdl->sdl_alen,
				       (unsigned char *) LLADDR(ifctx->sdl),
				       ":");
				ifctx->sentmsg = 1;
			}

			aio.iov_base = (caddr_t) &ifctx->call;
			aio.iov_len = sizeof(ifctx->call);

			auio.uio_iov = &aio;
			auio.uio_iovcnt = 1;
			auio.uio_segflg = UIO_SYSSPACE;
			auio.uio_rw = UIO_WRITE;
			auio.uio_offset = 0;
			auio.uio_resid = sizeof(ifctx->call);
			auio.uio_td = td;

			/* Set netmask to 0.0.0.0 */

			sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr;
			clear_sinaddr(sin);
			error = ifioctl(ifctx->so, SIOCSIFNETMASK,
					(caddr_t) &ifctx->ireq, td);
			if (error != 0)
				panic("bootpc_call:"
				      "set if netmask, error=%d",
				      error);

			error = sosend(so, (struct sockaddr *) &dst,
				       &auio, NULL, NULL, 0, td);
			if (error != 0) {
				printf("bootpc_call: sosend: %d state %08x\n",
				       error, (int) so->so_state);
			}

			/* XXX: Is this needed ? */
			pause("bootpw", hz/10);

			/* Set netmask to 255.0.0.0 */

			sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr;
			clear_sinaddr(sin);
			sin->sin_addr.s_addr = htonl(0xff000000u);
			error = ifioctl(ifctx->so, SIOCSIFNETMASK,
					(caddr_t) &ifctx->ireq, td);
			if (error != 0)
				panic("bootpc_call:"
				      "set if netmask, error=%d",
				      error);

		}

		if (outstanding == 0 &&
		    (rtimo == 0 || time_second >= rtimo)) {
			error = 0;
			goto gotreply;
		}

		/* Determine new timeout. */
		if (timo < MAX_RESEND_DELAY)
			timo++;
		else {
			printf("DHCP/BOOTP timeout for server ");
			print_sin_addr(&dst);
			printf("\n");
		}

		/*
		 * Wait for up to timo seconds for a reply.
		 * The socket receive timeout was set to 1 second.
		 */
		atimo = timo + time_second;
		while (time_second < atimo) {
			aio.iov_base = (caddr_t) &gctx->reply;
			aio.iov_len = sizeof(gctx->reply);

			auio.uio_iov = &aio;
			auio.uio_iovcnt = 1;
			auio.uio_segflg = UIO_SYSSPACE;
			auio.uio_rw = UIO_READ;
			auio.uio_offset = 0;
			auio.uio_resid = sizeof(gctx->reply);
			auio.uio_td = td;

			rcvflg = 0;
			error = soreceive(so, NULL, &auio,
					  NULL, NULL, &rcvflg);
			gctx->secs = time_second - gctx->starttime;
			for (ifctx = gctx->interfaces;
			     ifctx != NULL;
			     ifctx = ifctx->next) {
				if (bootpc_ifctx_isresolved(ifctx) != 0 ||
				    bootpc_ifctx_isfailed(ifctx) != 0)
					continue;

				ifctx->call.secs = htons(gctx->secs);
			}
			if (error == EWOULDBLOCK)
				continue;
			if (error != 0)
				goto out;
			len = sizeof(gctx->reply) - auio.uio_resid;

			/* Do we have the required number of bytes ? */
			if (len < BOOTP_MIN_LEN)
				continue;
			gctx->replylen = len;

			/* Is it a reply? */
			if (gctx->reply.op != BOOTP_REPLY)
				continue;

			/* Is this an answer to our query */
			for (ifctx = gctx->interfaces;
			     ifctx != NULL;
			     ifctx = ifctx->next) {
				if (gctx->reply.xid != ifctx->call.xid)
					continue;

				/* Same HW address size ? */
				if (gctx->reply.hlen != ifctx->call.hlen)
					continue;

				/* Correct HW address ? */
				if (bcmp(gctx->reply.chaddr,
					 ifctx->call.chaddr,
					 ifctx->call.hlen) != 0)
					continue;

				break;
			}

			if (ifctx != NULL) {
				s =  bootpc_tag(&gctx->tmptag,
						&gctx->reply,
						gctx->replylen,
						TAG_DHCP_MSGTYPE);
				if (s != NULL) {
					switch (*s) {
					case DHCP_OFFER:
						s = "DHCP Offer";
						break;
					case DHCP_ACK:
						s = "DHCP Ack";
						break;
					default:
						s = "DHCP (unexpected)";
						break;
					}
				} else
					s = "BOOTP Reply";

				printf("Received %s packet"
				       " on %s from ",
				       s,
				       ifctx->ireq.ifr_name);
				print_in_addr(gctx->reply.siaddr);
				if (gctx->reply.giaddr.s_addr !=
				    htonl(INADDR_ANY)) {
					printf(" via ");
					print_in_addr(gctx->reply.giaddr);
				}
				if (bootpc_received(gctx, ifctx) != 0) {
					printf(" (accepted)");
					if (ifctx->outstanding) {
						ifctx->outstanding = 0;
						outstanding--;
					}
					/* Network settle delay */
					if (outstanding == 0)
						atimo = time_second +
							BOOTP_SETTLE_DELAY;
				} else
					printf(" (ignored)");
				if (ifctx->gotrootpath) {
					gotrootpath = 1;
					rtimo = time_second +
						BOOTP_SETTLE_DELAY;
					printf(" (got root path)");
				} else
					printf(" (no root path)");
				printf("\n");
			}
		} /* while secs */
#ifdef BOOTP_TIMEOUT
		if (gctx->secs > BOOTP_TIMEOUT && BOOTP_TIMEOUT > 0)
			break;
#endif
		/* Force a retry if halfway in DHCP negotiation */
		retry = 0;
		for (ifctx = gctx->interfaces; ifctx != NULL;
		     ifctx = ifctx->next) {
			if (ifctx->state == IF_DHCP_OFFERED) {
				if (ifctx->dhcpquerytype == DHCP_DISCOVER)
					retry = 1;
				else
					ifctx->state = IF_DHCP_UNRESOLVED;
			}
		}

		if (retry != 0)
			continue;

		if (gotrootpath != 0) {
			gctx->gotrootpath = gotrootpath;
			if (rtimo != 0 && time_second >= rtimo)
				break;
		}
	} /* forever send/receive */

	/*
	 * XXX: These are errors of varying seriousness being silently
	 * ignored
	 */

	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) {
		if (bootpc_ifctx_isresolved(ifctx) == 0) {
			printf("%s timeout for interface %s\n",
			       ifctx->dhcpquerytype != DHCP_NOMSG ?
			       "DHCP" : "BOOTP",
			       ifctx->ireq.ifr_name);
		}
	}
	if (gctx->gotrootpath != 0) {
#if 0
		printf("Got a root path, ignoring remaining timeout\n");
#endif
		error = 0;
		goto out;
	}
#ifndef BOOTP_NFSROOT
	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) {
		if (bootpc_ifctx_isresolved(ifctx) != 0) {
			error = 0;
			goto out;
		}
	}
#endif
	error = ETIMEDOUT;
	goto out;

gotreply:
out:
	soclose(so);
out0:
	return error;
}
Exemple #30
0
static int
bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx,
    struct bootpc_globalcontext *gctx, struct thread *td)
{
	struct sockaddr_in *sin;
	int error;
	struct ifreq *ireq;
	struct socket *so;
	struct ifaddr *ifa;
	struct sockaddr_dl *sdl;

	error = socreate(AF_INET, &ifctx->so, SOCK_DGRAM, 0, td->td_ucred, td);
	if (error != 0)
		panic("nfs_boot: socreate, error=%d", error);

	ireq = &ifctx->ireq;
	so = ifctx->so;

	/*
	 * Bring up the interface.
	 *
	 * Get the old interface flags and or IFF_UP into them; if
	 * IFF_UP set blindly, interface selection can be clobbered.
	 */
	error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td);
	if (error != 0)
		panic("bootpc_fakeup_interface: GIFFLAGS, error=%d", error);
	ireq->ifr_flags |= IFF_UP;
	error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td);
	if (error != 0)
		panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error);

	/*
	 * Do enough of ifconfig(8) so that the chosen interface
	 * can talk to the servers.  (just set the address)
	 */

	/* addr is 0.0.0.0 */

	sin = (struct sockaddr_in *) &ireq->ifr_addr;
	clear_sinaddr(sin);
	error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td);
	if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces))
		panic("bootpc_fakeup_interface: "
		      "set if addr, error=%d", error);

	/* netmask is 255.0.0.0 */

	sin = (struct sockaddr_in *) &ireq->ifr_addr;
	clear_sinaddr(sin);
	sin->sin_addr.s_addr = htonl(0xff000000u);
	error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, td);
	if (error != 0)
		panic("bootpc_fakeup_interface: set if netmask, error=%d",
		      error);

	/* Broadcast is 255.255.255.255 */

	sin = (struct sockaddr_in *)&ireq->ifr_addr;
	clear_sinaddr(sin);
	clear_sinaddr(&ifctx->broadcast);
	sin->sin_addr.s_addr = htonl(INADDR_BROADCAST);
	ifctx->broadcast.sin_addr.s_addr = sin->sin_addr.s_addr;

	error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, td);
	if (error != 0)
		panic("bootpc_fakeup_interface: "
		      "set if broadcast addr, error=%d",
		      error);

	/* Get HW address */

	sdl = NULL;
	TAILQ_FOREACH(ifa, &ifctx->ifp->if_addrhead, ifa_link)
		if (ifa->ifa_addr->sa_family == AF_LINK) {
			sdl = (struct sockaddr_dl *)ifa->ifa_addr;
			if (sdl->sdl_type == IFT_ETHER)
				break;
		}

	if (sdl == NULL)
		panic("bootpc: Unable to find HW address for %s",
		      ifctx->ireq.ifr_name);
	ifctx->sdl = sdl;

	return error;
}