Support network device cloning via create and destroy options.

Reviewed by:	ru, ume
Obtained from:	NetBSD
MFC after:	1 week
This commit is contained in:
Brooks Davis 2001-07-02 20:52:34 +00:00
parent ad37a95b71
commit 3e61dca08d
2 changed files with 166 additions and 16 deletions

View File

@ -43,6 +43,7 @@
.Op Fl L
.Op Fl m
.Ar interface
.Op Cm create
.Op Ar address_family
.Oo
.Ar address Ns Op Cm / Ns Ar prefixlength
@ -50,6 +51,9 @@
.Oc
.Op Ar parameters
.Nm
.Ar interface
.Cm destroy
.Nm
.Fl a
.Op Fl L
.Op Fl d
@ -66,6 +70,7 @@
.Op Fl d
.Op Fl m
.Op Fl u
.Op Fl C
.Sh DESCRIPTION
.Nm Ifconfig
is used to assign an address
@ -269,6 +274,24 @@ IPv4/IPv6 header.
Unconfigure the physical source and destination address for IP tunnel
interfaces previously configured with
.Cm tunnel .
.It Cm create
Create the specified network pseudo-device.
If the interface is given without a unit number, try to create a new
device with an arbitrary unit number.
If creation of an arbitrary device is sucessful, the new device name is
printed to stdout.
.It Cm destroy
Destroy the specified network pseudo-device.
.It Cm plumb
Another name for the
.Fl create
parameter.
Included for Solaris compatibility.
.It Cm unplumb
Another name for the
.Fl destroy
parameter.
Included for Solaris compatibility.
.It Cm vlan Ar vlan_tag
If the interface is a vlan pseudo interface, set the vlan tag value
to
@ -587,6 +610,12 @@ and
.Fl u
(only list interfaces that are up).
.Pp
The
.Fl C
flag may be used to list all of the interface cloners available on
the system, with no additional information.
Use of this flag is mutually exclusive with all other flags and commands.
.Pp
Only the super-user may modify the configuration of a network interface.
.Sh NOTES
The media selection system is relatively new and only some drivers support

View File

@ -135,6 +135,7 @@ static int ip6lifetime;
struct afswtch;
int supmedia = 0;
int listcloners = 0;
#ifdef INET6
char addr_buf[MAXHOSTNAMELEN *2 + 1]; /*for getnameinfo()*/
@ -144,6 +145,7 @@ void Perror __P((const char *cmd));
void checkatrange __P((struct sockaddr_at *));
int ifconfig __P((int argc, char *const *argv, const struct afswtch *afp));
void notealias __P((const char *, int, int, const struct afswtch *afp));
void list_cloners __P((void));
void printb __P((const char *s, unsigned value, const char *bits));
void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
void status __P((const struct afswtch *afp, int addrcount,
@ -175,6 +177,10 @@ c_func2 setip6lifetime;
#endif
c_func setifipdst;
c_func setifflags, setifmetric, setifmtu, setiflladdr;
c_func clone_destroy;
void clone_create __P((void));
#define NEXTARG 0xffffff
@ -239,6 +245,13 @@ struct cmd {
{ "vlandev", NEXTARG, setvlandev },
{ "-vlandev", NEXTARG, unsetvlandev },
#endif
#if 0
/* XXX `create' special-cased below */
{"create", 0, clone_create },
{"plumb", 0, clone_create },
#endif
{"destroy", 0, clone_destroy },
{"unplumb", 0, clone_destroy },
#ifdef USE_IEEE80211
{ "ssid", NEXTARG, set80211ssid },
{ "nwid", NEXTARG, set80211ssid },
@ -364,16 +377,20 @@ void
usage()
{
#ifndef INET6
fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
"usage: ifconfig interface address_family [address [dest_address]]",
" [parameters]",
" ifconfig -C",
" ifconfig interface create",
" ifconfig -a [-d] [-m] [-u] [address_family]",
" ifconfig -l [-d] [-u] [address_family]",
" ifconfig [-d] [-m] [-u]");
#else
fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
"usage: ifconfig [-L] interface address_family [address [dest_address]]",
" [parameters]",
" ifconfig -C",
" ifconfig interface create",
" ifconfig -a [-L] [-d] [-m] [-u] [address_family]",
" ifconfig -l [-d] [-u] [address_family]",
" ifconfig [-L] [-d] [-m] [-u]");
@ -402,7 +419,7 @@ main(argc, argv)
/* Parse leading line options */
all = downonly = uponly = namesonly = 0;
while ((c = getopt(argc, argv, "adlmu"
while ((c = getopt(argc, argv, "adlmuC"
#ifdef INET6
"L"
#endif
@ -411,23 +428,26 @@ main(argc, argv)
case 'a': /* scan all interfaces */
all++;
break;
case 'd': /* restrict scan to "down" interfaces */
downonly++;
break;
case 'l': /* scan interface names only */
namesonly++;
break;
case 'm': /* show media choices in status */
supmedia = 1;
break;
case 'u': /* restrict scan to "up" interfaces */
uponly++;
break;
case 'C':
listcloners = 1;
break;
#ifdef INET6
case 'L':
ip6lifetime++; /* print IPv6 address lifetime */
break;
#endif
case 'l': /* scan interface names only */
namesonly++;
break;
case 'd': /* restrict scan to "down" interfaces */
downonly++;
break;
case 'u': /* restrict scan to "up" interfaces */
uponly++;
break;
case 'm': /* show media choices in status */
supmedia = 1;
break;
default:
usage();
break;
@ -436,6 +456,16 @@ main(argc, argv)
argc -= optind;
argv += optind;
if (listcloners) {
/* -C must be solitary */
if (all || supmedia || uponly || downonly || namesonly ||
argc > 0)
usage();
list_cloners();
exit(0);
}
/* -l cannot be used with -a or -m */
if (namesonly && (all || supmedia))
usage();
@ -473,6 +503,18 @@ main(argc, argv)
/* check and maybe load support for this interface */
ifmaybeload(name);
/*
* NOTE: We must special-case the `create' command right
* here as we would otherwise fail when trying to find
* the interface.
*/
if (argc > 0 && strcmp(argv[0], "create") == 0) {
clone_create();
argc--, argv++;
if (argc == 0)
exit(0);
}
}
/* Check for address family */
@ -1861,7 +1903,8 @@ ifmaybeload(name)
/* turn interface and unit into module name */
strcpy(ifkind, "if_");
for (cp = name, dp = ifkind + 3; (*cp != 0) && !isdigit(*cp); cp++, dp++)
for (cp = name, dp = ifkind + 3;
(*cp != 0) && !isdigit(*cp); cp++, dp++)
*dp = *cp;
*dp = 0;
@ -1888,3 +1931,81 @@ ifmaybeload(name)
/* not present, we should try to load it */
kldload(ifkind);
}
void
list_cloners(void)
{
struct if_clonereq ifcr;
char *cp, *buf;
int idx;
int s;
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s == -1)
err(1, "socket");
memset(&ifcr, 0, sizeof(ifcr));
if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0)
err(1, "SIOCIFGCLONERS for count");
buf = malloc(ifcr.ifcr_total * IFNAMSIZ);
if (buf == NULL)
err(1, "unable to allocate cloner name buffer");
ifcr.ifcr_count = ifcr.ifcr_total;
ifcr.ifcr_buffer = buf;
if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0)
err(1, "SIOCIFGCLONERS for names");
/*
* In case some disappeared in the mean time, clamp it down.
*/
if (ifcr.ifcr_count > ifcr.ifcr_total)
ifcr.ifcr_count = ifcr.ifcr_total;
for (cp = buf, idx = 0; idx < ifcr.ifcr_count; idx++, cp += IFNAMSIZ) {
if (idx > 0)
putchar(' ');
printf("%s", cp);
}
putchar('\n');
free(buf);
}
void
clone_create()
{
int s;
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s == -1)
err(1, "socket");
memset(&ifr, 0, sizeof(ifr));
(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
if (ioctl(s, SIOCIFCREATE, &ifr) < 0)
err(1, "SIOCIFCREATE");
if (strcmp(name, ifr.ifr_name) != 0) {
printf("%s\n", ifr.ifr_name);
strlcpy(name, ifr.ifr_name, sizeof(name));
}
close(s);
}
void
clone_destroy(val, d, s, rafp)
const char *val;
int d;
int s;
const struct afswtch *rafp;
{
(void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
if (ioctl(s, SIOCIFDESTROY, &ifr) < 0)
err(1, "SIOCIFDESTROY");
}