Add the notion of "cloning" of network pseudo-interface (e.g. `gif').
This allows them to be created and destroyed on the fly via ifconfig(8), rather than specifying the count in the kernel configuration file.
This commit is contained in:
parent
87ca5edd6f
commit
1e58f22342
120
sys/net/if.c
120
sys/net/if.c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: if.c,v 1.62 2000/04/26 13:38:13 bouyer Exp $ */
|
||||
/* $NetBSD: if.c,v 1.63 2000/07/02 00:20:48 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
|
||||
@ -147,6 +147,10 @@ extern void nd6_setmtu __P((struct ifnet *));
|
||||
|
||||
int if_rt_walktree __P((struct radix_node *, void *));
|
||||
|
||||
struct if_clone *if_clone_lookup __P((const char *, int *));
|
||||
|
||||
LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
|
||||
|
||||
/*
|
||||
* Network interface utility routines.
|
||||
*
|
||||
@ -479,6 +483,112 @@ if_rt_walktree(rn, v)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a clone network interface.
|
||||
*/
|
||||
int
|
||||
if_clone_create(name)
|
||||
const char *name;
|
||||
{
|
||||
struct if_clone *ifc;
|
||||
int unit;
|
||||
|
||||
ifc = if_clone_lookup(name, &unit);
|
||||
if (ifc == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
if (ifunit(name) != NULL)
|
||||
return (EEXIST);
|
||||
|
||||
return ((*ifc->ifc_create)(ifc, unit));
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy a clone network interface.
|
||||
*/
|
||||
int
|
||||
if_clone_destroy(name)
|
||||
const char *name;
|
||||
{
|
||||
struct if_clone *ifc;
|
||||
struct ifnet *ifp;
|
||||
|
||||
ifc = if_clone_lookup(name, NULL);
|
||||
if (ifc == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
ifp = ifunit(name);
|
||||
if (ifp == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
if (ifc->ifc_destroy == NULL)
|
||||
return (EOPNOTSUPP);
|
||||
|
||||
(*ifc->ifc_destroy)(ifp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up a network interface cloner.
|
||||
*/
|
||||
struct if_clone *
|
||||
if_clone_lookup(name, unitp)
|
||||
const char *name;
|
||||
int *unitp;
|
||||
{
|
||||
struct if_clone *ifc;
|
||||
const char *cp;
|
||||
int i;
|
||||
|
||||
for (ifc = LIST_FIRST(&if_cloners); ifc != NULL;) {
|
||||
for (cp = name, i = 0; i < ifc->ifc_namelen; i++, cp++) {
|
||||
if (ifc->ifc_name[i] != *cp)
|
||||
goto next_ifc;
|
||||
}
|
||||
goto found_name;
|
||||
next_ifc:
|
||||
ifc = LIST_NEXT(ifc, ifc_list);
|
||||
}
|
||||
|
||||
/* No match. */
|
||||
return (NULL);
|
||||
|
||||
found_name:
|
||||
for (i = 0; *cp != '\0'; cp++) {
|
||||
if (*cp < '0' || *cp > '9') {
|
||||
/* Bogus unit number. */
|
||||
return (NULL);
|
||||
}
|
||||
i = (i * 10) + (*cp - '0');
|
||||
}
|
||||
|
||||
if (unitp != NULL)
|
||||
*unitp = i;
|
||||
return (ifc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Register a network interface cloner.
|
||||
*/
|
||||
void
|
||||
if_clone_attach(ifc)
|
||||
struct if_clone *ifc;
|
||||
{
|
||||
|
||||
LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unregister a network interface cloner.
|
||||
*/
|
||||
void
|
||||
if_clone_detach(ifc)
|
||||
struct if_clone *ifc;
|
||||
{
|
||||
|
||||
LIST_REMOVE(ifc, ifc_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* Locate an interface based on a complete address.
|
||||
*/
|
||||
@ -860,6 +970,14 @@ ifioctl(so, cmd, data, p)
|
||||
return (ifconf(cmd, data));
|
||||
}
|
||||
ifr = (struct ifreq *)data;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCIFCREATE:
|
||||
return (if_clone_create(ifr->ifr_name));
|
||||
case SIOCIFDESTROY:
|
||||
return (if_clone_destroy(ifr->ifr_name));
|
||||
}
|
||||
|
||||
ifp = ifunit(ifr->ifr_name);
|
||||
if (ifp == 0)
|
||||
return (ENXIO);
|
||||
|
24
sys/net/if.h
24
sys/net/if.h
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: if.h,v 1.50 2000/05/15 16:59:37 itojun Exp $ */
|
||||
/* $NetBSD: if.h,v 1.51 2000/07/02 00:20:49 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
|
||||
@ -114,6 +114,22 @@ struct proc;
|
||||
struct rtentry;
|
||||
struct socket;
|
||||
struct ether_header;
|
||||
struct ifnet;
|
||||
|
||||
/*
|
||||
* Structure describing a `cloning' interface.
|
||||
*/
|
||||
struct if_clone {
|
||||
LIST_ENTRY(if_clone) ifc_list; /* on list of cloners */
|
||||
const char *ifc_name; /* name of device, e.g. `gif' */
|
||||
size_t ifc_namelen; /* length of name */
|
||||
|
||||
int (*ifc_create)(struct if_clone *, int);
|
||||
void (*ifc_destroy)(struct ifnet *);
|
||||
};
|
||||
|
||||
#define IF_CLONE_INITIALIZER(name, create, destroy) \
|
||||
{ { 0 }, name, sizeof(name) - 1, create, destroy }
|
||||
|
||||
/*
|
||||
* Structure defining statistics and other data kept regarding a network
|
||||
@ -582,6 +598,12 @@ struct ifaddr *ifaof_ifpforaddr __P((struct sockaddr *, struct ifnet *));
|
||||
void ifafree __P((struct ifaddr *));
|
||||
void link_rtrequest __P((int, struct rtentry *, struct sockaddr *));
|
||||
|
||||
void if_clone_attach __P((struct if_clone *));
|
||||
void if_clone_detach __P((struct if_clone *));
|
||||
|
||||
int if_clone_create __P((const char *));
|
||||
int if_clone_destroy __P((const char *));
|
||||
|
||||
int loioctl __P((struct ifnet *, u_long, caddr_t));
|
||||
void loopattach __P((int));
|
||||
int looutput __P((struct ifnet *,
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: sockio.h,v 1.11 2000/05/13 07:55:05 itojun Exp $ */
|
||||
/* $NetBSD: sockio.h,v 1.12 2000/07/02 00:20:49 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1990, 1993, 1994
|
||||
@ -99,4 +99,7 @@
|
||||
parameters */
|
||||
#define SIOCGDRVSPEC _IOWR('i', 123, struct ifdrv) /* get driver-specific
|
||||
parameters */
|
||||
#define SIOCIFCREATE _IOW('i', 122, struct ifreq) /* create clone if */
|
||||
#define SIOCIFDESTROY _IOW('i', 121, struct ifreq) /* destroy clone if */
|
||||
|
||||
#endif /* !_SYS_SOCKIO_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user