Introduce network device nodes. Network devices will now automatically
appear in /dev. Interface hardware ioctls (not protocol or routing) can be performed on the descriptor. The SIOCGIFCONF ioctl may be performed on the special /dev/network node.
This commit is contained in:
parent
a35b06c555
commit
f13ad20660
@ -180,6 +180,7 @@ chrdev name comments
|
|||||||
162 digi Digiboard
|
162 digi Digiboard
|
||||||
163 gdt ICP Vortex RAID controller
|
163 gdt ICP Vortex RAID controller
|
||||||
164 src Intel SRC RAID controller
|
164 src Intel SRC RAID controller
|
||||||
|
165 net Network drivers <jlemon>
|
||||||
200 ?? entries from 200-252 are reserved for local use
|
200 ?? entries from 200-252 are reserved for local use
|
||||||
252 ?? entries from 200-252 are reserved for local use
|
252 ?? entries from 200-252 are reserved for local use
|
||||||
254 internal Used internally by the kernel
|
254 internal Used internally by the kernel
|
||||||
|
192
sys/net/if.c
192
sys/net/if.c
@ -39,6 +39,7 @@
|
|||||||
#include "opt_inet.h"
|
#include "opt_inet.h"
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
#include <sys/conf.h>
|
||||||
#include <sys/malloc.h>
|
#include <sys/malloc.h>
|
||||||
#include <sys/mbuf.h>
|
#include <sys/mbuf.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
@ -80,6 +81,7 @@ static void link_rtrequest(int, struct rtentry *, struct sockaddr *);
|
|||||||
static int if_rtdel(struct radix_node *, void *);
|
static int if_rtdel(struct radix_node *, void *);
|
||||||
static struct if_clone *if_clone_lookup(const char *, int *);
|
static struct if_clone *if_clone_lookup(const char *, int *);
|
||||||
static int if_clone_list(struct if_clonereq *);
|
static int if_clone_list(struct if_clonereq *);
|
||||||
|
static int ifhwioctl(u_long, struct ifnet *, caddr_t, struct thread *);
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
/*
|
/*
|
||||||
* XXX: declare here to avoid to include many inet6 related files..
|
* XXX: declare here to avoid to include many inet6 related files..
|
||||||
@ -96,6 +98,7 @@ int if_cloners_count;
|
|||||||
LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
|
LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
|
||||||
|
|
||||||
static int if_indexlim = 8;
|
static int if_indexlim = 8;
|
||||||
|
static struct klist ifklist;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* System initialization
|
* System initialization
|
||||||
@ -106,6 +109,69 @@ SYSINIT(interface_check, SI_SUB_PROTO_IF, SI_ORDER_FIRST, if_check, NULL)
|
|||||||
MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address");
|
MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address");
|
||||||
MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address");
|
MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address");
|
||||||
|
|
||||||
|
#define CDEV_MAJOR 165
|
||||||
|
|
||||||
|
static d_open_t netopen;
|
||||||
|
static d_close_t netclose;
|
||||||
|
static d_ioctl_t netioctl;
|
||||||
|
|
||||||
|
static struct cdevsw net_cdevsw = {
|
||||||
|
/* open */ netopen,
|
||||||
|
/* close */ netclose,
|
||||||
|
/* read */ noread,
|
||||||
|
/* write */ nowrite,
|
||||||
|
/* ioctl */ netioctl,
|
||||||
|
/* poll */ nopoll,
|
||||||
|
/* mmap */ nommap,
|
||||||
|
/* strategy */ nostrategy,
|
||||||
|
/* name */ "net",
|
||||||
|
/* maj */ CDEV_MAJOR,
|
||||||
|
/* dump */ nodump,
|
||||||
|
/* psize */ nopsize,
|
||||||
|
/* flags */ 0
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
netopen(dev_t dev, int flag, int mode, struct thread *td)
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
netclose(dev_t dev, int flags, int fmt, struct thread *td)
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
netioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||||
|
{
|
||||||
|
struct ifnet *ifp;
|
||||||
|
int error, idx;
|
||||||
|
|
||||||
|
/* only support interface specific ioctls */
|
||||||
|
if (IOCGROUP(cmd) != 'i')
|
||||||
|
return (EOPNOTSUPP);
|
||||||
|
idx = minor(dev);
|
||||||
|
if (idx == 0) {
|
||||||
|
/*
|
||||||
|
* special network device, not interface.
|
||||||
|
*/
|
||||||
|
if (cmd == SIOCGIFCONF)
|
||||||
|
return (ifconf(cmd, data)); /* XXX remove cmd */
|
||||||
|
return (EOPNOTSUPP);
|
||||||
|
}
|
||||||
|
|
||||||
|
ifp = ifnet_byindex(idx);
|
||||||
|
if (ifp == NULL)
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
error = ifhwioctl(cmd, ifp, data, td);
|
||||||
|
if (error == ENOIOCTL)
|
||||||
|
error = EOPNOTSUPP;
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Network interface utility routines.
|
* Network interface utility routines.
|
||||||
*
|
*
|
||||||
@ -119,7 +185,10 @@ if_init(dummy)
|
|||||||
{
|
{
|
||||||
|
|
||||||
TAILQ_INIT(&ifnet);
|
TAILQ_INIT(&ifnet);
|
||||||
|
SLIST_INIT(&ifklist);
|
||||||
if_grow(); /* create initial table */
|
if_grow(); /* create initial table */
|
||||||
|
ifdev_byindex(0) = make_dev(&net_cdevsw, 0,
|
||||||
|
UID_ROOT, GID_WHEEL, 0600, "network");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -194,6 +263,12 @@ if_attach(ifp)
|
|||||||
if_grow();
|
if_grow();
|
||||||
|
|
||||||
ifnet_byindex(if_index) = ifp;
|
ifnet_byindex(if_index) = ifp;
|
||||||
|
ifdev_byindex(if_index) = make_dev(&net_cdevsw, if_index,
|
||||||
|
UID_ROOT, GID_WHEEL, 0600, "%s%d", ifp->if_name, ifp->if_unit);
|
||||||
|
#if 0
|
||||||
|
make_dev_alias(ifdev_byindex(if_index), "%s%d", "net", if_index - 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
mtx_init(&ifp->if_snd.ifq_mtx, ifp->if_name, MTX_DEF);
|
mtx_init(&ifp->if_snd.ifq_mtx, ifp->if_name, MTX_DEF);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -255,6 +330,8 @@ if_detach(ifp)
|
|||||||
* Clean up all addresses.
|
* Clean up all addresses.
|
||||||
*/
|
*/
|
||||||
ifaddr_byindex(ifp->if_index) = NULL;
|
ifaddr_byindex(ifp->if_index) = NULL;
|
||||||
|
destroy_dev(ifdev_byindex(ifp->if_index));
|
||||||
|
ifdev_byindex(ifp->if_index) = NULL;
|
||||||
|
|
||||||
while (if_index > 0 && ifaddr_byindex(if_index) == NULL)
|
while (if_index > 0 && ifaddr_byindex(if_index) == NULL)
|
||||||
if_index--;
|
if_index--;
|
||||||
@ -947,49 +1024,18 @@ if_withname(sa)
|
|||||||
return ifunit(ifname);
|
return ifunit(ifname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Interface ioctls.
|
* Hardware specific interface ioctls.
|
||||||
*/
|
*/
|
||||||
int
|
static int
|
||||||
ifioctl(so, cmd, data, td)
|
ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
|
||||||
struct socket *so;
|
|
||||||
u_long cmd;
|
|
||||||
caddr_t data;
|
|
||||||
struct thread *td;
|
|
||||||
{
|
{
|
||||||
register struct ifnet *ifp;
|
struct ifreq *ifr;
|
||||||
register struct ifreq *ifr;
|
|
||||||
struct ifstat *ifs;
|
struct ifstat *ifs;
|
||||||
int error;
|
int error = 0;
|
||||||
short oif_flags;
|
|
||||||
|
|
||||||
switch (cmd) {
|
|
||||||
|
|
||||||
case SIOCGIFCONF:
|
|
||||||
case OSIOCGIFCONF:
|
|
||||||
return (ifconf(cmd, data));
|
|
||||||
}
|
|
||||||
ifr = (struct ifreq *)data;
|
ifr = (struct ifreq *)data;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case SIOCIFCREATE:
|
|
||||||
case SIOCIFDESTROY:
|
|
||||||
if ((error = suser_td(td)) != 0)
|
|
||||||
return (error);
|
|
||||||
return ((cmd == SIOCIFCREATE) ?
|
|
||||||
if_clone_create(ifr->ifr_name, sizeof(ifr->ifr_name)) :
|
|
||||||
if_clone_destroy(ifr->ifr_name));
|
|
||||||
|
|
||||||
case SIOCIFGCLONERS:
|
|
||||||
return (if_clone_list((struct if_clonereq *)data));
|
|
||||||
}
|
|
||||||
|
|
||||||
ifp = ifunit(ifr->ifr_name);
|
|
||||||
if (ifp == 0)
|
|
||||||
return (ENXIO);
|
|
||||||
switch (cmd) {
|
|
||||||
|
|
||||||
case SIOCGIFFLAGS:
|
case SIOCGIFFLAGS:
|
||||||
ifr->ifr_flags = ifp->if_flags;
|
ifr->ifr_flags = ifp->if_flags;
|
||||||
break;
|
break;
|
||||||
@ -1071,10 +1117,10 @@ ifioctl(so, cmd, data, td)
|
|||||||
error = suser_td(td);
|
error = suser_td(td);
|
||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
if (ifp->if_ioctl == NULL)
|
|
||||||
return (EOPNOTSUPP);
|
|
||||||
if (ifr->ifr_mtu < IF_MINMTU || ifr->ifr_mtu > IF_MAXMTU)
|
if (ifr->ifr_mtu < IF_MINMTU || ifr->ifr_mtu > IF_MAXMTU)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
if (ifp->if_ioctl == NULL)
|
||||||
|
return (EOPNOTSUPP);
|
||||||
error = (*ifp->if_ioctl)(ifp, cmd, data);
|
error = (*ifp->if_ioctl)(ifp, cmd, data);
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
getmicrotime(&ifp->if_lastchange);
|
getmicrotime(&ifp->if_lastchange);
|
||||||
@ -1088,7 +1134,7 @@ ifioctl(so, cmd, data, td)
|
|||||||
nd6_setmtu(ifp);
|
nd6_setmtu(ifp);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return (error);
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SIOCADDMULTI:
|
case SIOCADDMULTI:
|
||||||
@ -1099,11 +1145,11 @@ ifioctl(so, cmd, data, td)
|
|||||||
|
|
||||||
/* Don't allow group membership on non-multicast interfaces. */
|
/* Don't allow group membership on non-multicast interfaces. */
|
||||||
if ((ifp->if_flags & IFF_MULTICAST) == 0)
|
if ((ifp->if_flags & IFF_MULTICAST) == 0)
|
||||||
return EOPNOTSUPP;
|
return (EOPNOTSUPP);
|
||||||
|
|
||||||
/* Don't let users screw up protocols' entries. */
|
/* Don't let users screw up protocols' entries. */
|
||||||
if (ifr->ifr_addr.sa_family != AF_LINK)
|
if (ifr->ifr_addr.sa_family != AF_LINK)
|
||||||
return EINVAL;
|
return (EINVAL);
|
||||||
|
|
||||||
if (cmd == SIOCADDMULTI) {
|
if (cmd == SIOCADDMULTI) {
|
||||||
struct ifmultiaddr *ifma;
|
struct ifmultiaddr *ifma;
|
||||||
@ -1113,7 +1159,7 @@ ifioctl(so, cmd, data, td)
|
|||||||
}
|
}
|
||||||
if (error == 0)
|
if (error == 0)
|
||||||
getmicrotime(&ifp->if_lastchange);
|
getmicrotime(&ifp->if_lastchange);
|
||||||
return error;
|
break;
|
||||||
|
|
||||||
case SIOCSIFPHYADDR:
|
case SIOCSIFPHYADDR:
|
||||||
case SIOCDIFPHYADDR:
|
case SIOCDIFPHYADDR:
|
||||||
@ -1126,12 +1172,12 @@ ifioctl(so, cmd, data, td)
|
|||||||
error = suser_td(td);
|
error = suser_td(td);
|
||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
if (ifp->if_ioctl == 0)
|
if (ifp->if_ioctl == NULL)
|
||||||
return (EOPNOTSUPP);
|
return (EOPNOTSUPP);
|
||||||
error = (*ifp->if_ioctl)(ifp, cmd, data);
|
error = (*ifp->if_ioctl)(ifp, cmd, data);
|
||||||
if (error == 0)
|
if (error == 0)
|
||||||
getmicrotime(&ifp->if_lastchange);
|
getmicrotime(&ifp->if_lastchange);
|
||||||
return error;
|
break;
|
||||||
|
|
||||||
case SIOCGIFSTATUS:
|
case SIOCGIFSTATUS:
|
||||||
ifs = (struct ifstat *)data;
|
ifs = (struct ifstat *)data;
|
||||||
@ -1144,16 +1190,67 @@ ifioctl(so, cmd, data, td)
|
|||||||
case SIOCGIFGENERIC:
|
case SIOCGIFGENERIC:
|
||||||
if (ifp->if_ioctl == 0)
|
if (ifp->if_ioctl == 0)
|
||||||
return (EOPNOTSUPP);
|
return (EOPNOTSUPP);
|
||||||
return ((*ifp->if_ioctl)(ifp, cmd, data));
|
error = (*ifp->if_ioctl)(ifp, cmd, data);
|
||||||
|
break;
|
||||||
|
|
||||||
case SIOCSIFLLADDR:
|
case SIOCSIFLLADDR:
|
||||||
error = suser_td(td);
|
error = suser_td(td);
|
||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
return if_setlladdr(ifp,
|
error = if_setlladdr(ifp,
|
||||||
ifr->ifr_addr.sa_data, ifr->ifr_addr.sa_len);
|
ifr->ifr_addr.sa_data, ifr->ifr_addr.sa_len);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
error = ENOIOCTL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Interface ioctls.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ifioctl(so, cmd, data, td)
|
||||||
|
struct socket *so;
|
||||||
|
u_long cmd;
|
||||||
|
caddr_t data;
|
||||||
|
struct thread *td;
|
||||||
|
{
|
||||||
|
struct ifnet *ifp;
|
||||||
|
struct ifreq *ifr;
|
||||||
|
int error;
|
||||||
|
short oif_flags;
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case SIOCGIFCONF:
|
||||||
|
case OSIOCGIFCONF:
|
||||||
|
return (ifconf(cmd, data));
|
||||||
|
}
|
||||||
|
ifr = (struct ifreq *)data;
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case SIOCIFCREATE:
|
||||||
|
case SIOCIFDESTROY:
|
||||||
|
if ((error = suser_td(td)) != 0)
|
||||||
|
return (error);
|
||||||
|
return ((cmd == SIOCIFCREATE) ?
|
||||||
|
if_clone_create(ifr->ifr_name, sizeof(ifr->ifr_name)) :
|
||||||
|
if_clone_destroy(ifr->ifr_name));
|
||||||
|
|
||||||
|
case SIOCIFGCLONERS:
|
||||||
|
return (if_clone_list((struct if_clonereq *)data));
|
||||||
|
}
|
||||||
|
|
||||||
|
ifp = ifunit(ifr->ifr_name);
|
||||||
|
if (ifp == 0)
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
error = ifhwioctl(cmd, ifp, data, td);
|
||||||
|
if (error != ENOIOCTL)
|
||||||
|
return (error);
|
||||||
|
|
||||||
oif_flags = ifp->if_flags;
|
oif_flags = ifp->if_flags;
|
||||||
if (so->so_proto == 0)
|
if (so->so_proto == 0)
|
||||||
return (EOPNOTSUPP);
|
return (EOPNOTSUPP);
|
||||||
@ -1225,9 +1322,6 @@ ifioctl(so, cmd, data, td)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
}
|
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user