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:
Jonathan Lemon 2001-09-29 05:55:04 +00:00
parent a35b06c555
commit f13ad20660
2 changed files with 158 additions and 63 deletions

View File

@ -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

View File

@ -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);
} }
/* /*