o replace special handling of clone operations by a clone callback
mechanism o change vlan cloning to use callback and pass all vlan parameters on create using the new SIOCREATE2 ioctl o update vlan set logic to match existing practice
This commit is contained in:
parent
6b7330e2d4
commit
db82353d87
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=160196
@ -88,48 +88,62 @@ list_cloners(void)
|
|||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static clone_callback_func *clone_cb = NULL;
|
||||||
clone_create(void)
|
|
||||||
{
|
|
||||||
int s;
|
|
||||||
|
|
||||||
s = socket(AF_INET, SOCK_DGRAM, 0);
|
void
|
||||||
if (s == -1)
|
clone_setcallback(clone_callback_func *p)
|
||||||
err(1, "socket(AF_INET,SOCK_DGRAM)");
|
{
|
||||||
|
if (clone_cb != NULL && clone_cb != p)
|
||||||
|
errx(1, "conflicting device create parameters");
|
||||||
|
clone_cb = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do the actual clone operation. Any parameters must have been
|
||||||
|
* setup by now. If a callback has been setup to do the work
|
||||||
|
* then defer to it; otherwise do a simple create operation with
|
||||||
|
* no parameters.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ifclonecreate(int s, void *arg)
|
||||||
|
{
|
||||||
|
struct ifreq ifr;
|
||||||
|
|
||||||
memset(&ifr, 0, sizeof(ifr));
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
|
(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
|
||||||
if (ioctl(s, SIOCIFCREATE, &ifr) < 0)
|
if (clone_cb == NULL) {
|
||||||
err(1, "SIOCIFCREATE");
|
/* NB: no parameters */
|
||||||
|
if (ioctl(s, SIOCIFCREATE2, &ifr) < 0)
|
||||||
/*
|
err(1, "SIOCIFCREATE2");
|
||||||
* If we get a different name back then we put in, we probably
|
} else {
|
||||||
* want to print it out, but we might change our mind later so
|
clone_cb(s, &ifr);
|
||||||
* we just signal our intrest and leave the printout for later.
|
|
||||||
*/
|
|
||||||
if (strcmp(name, ifr.ifr_name) != 0) {
|
|
||||||
printname = 1;
|
|
||||||
strlcpy(name, ifr.ifr_name, sizeof(name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
close(s);
|
/*
|
||||||
|
* If we get a different name back than we put in, print it.
|
||||||
|
*/
|
||||||
|
if (strncmp(name, ifr.ifr_name, sizeof(name)) != 0) {
|
||||||
|
strlcpy(name, ifr.ifr_name, sizeof(name));
|
||||||
|
printf("%s\n", name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static
|
||||||
clone_destroy(const char *val, int d, int s, const struct afswtch *rafp)
|
DECL_CMD_FUNC(clone_create, arg, d)
|
||||||
{
|
{
|
||||||
|
callback_register(ifclonecreate, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
DECL_CMD_FUNC(clone_destroy, arg, d)
|
||||||
|
{
|
||||||
(void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
|
(void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
|
||||||
if (ioctl(s, SIOCIFDESTROY, &ifr) < 0)
|
if (ioctl(s, SIOCIFDESTROY, &ifr) < 0)
|
||||||
err(1, "SIOCIFDESTROY");
|
err(1, "SIOCIFDESTROY");
|
||||||
/*
|
|
||||||
* If we create and destroy an interface in the same command,
|
|
||||||
* there isn't any reason to print it's name.
|
|
||||||
*/
|
|
||||||
printname = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cmd clone_cmds[] = {
|
static struct cmd clone_cmds[] = {
|
||||||
|
DEF_CMD("create", 0, clone_create),
|
||||||
DEF_CMD("destroy", 0, clone_destroy),
|
DEF_CMD("destroy", 0, clone_destroy),
|
||||||
DEF_CMD("unplumb", 0, clone_destroy),
|
DEF_CMD("unplumb", 0, clone_destroy),
|
||||||
};
|
};
|
||||||
|
@ -92,7 +92,6 @@ int verbose;
|
|||||||
|
|
||||||
int supmedia = 0;
|
int supmedia = 0;
|
||||||
int printkeys = 0; /* Print keying material for interfaces. */
|
int printkeys = 0; /* Print keying material for interfaces. */
|
||||||
int printname = 0; /* Print the name of the created interface. */
|
|
||||||
|
|
||||||
static int ifconfig(int argc, char *const *argv, const struct afswtch *afp);
|
static int ifconfig(int argc, char *const *argv, const struct afswtch *afp);
|
||||||
static void status(const struct afswtch *afp, int addrcount,
|
static void status(const struct afswtch *afp, int addrcount,
|
||||||
@ -234,21 +233,20 @@ main(int argc, char *argv[])
|
|||||||
/* check and maybe load support for this interface */
|
/* check and maybe load support for this interface */
|
||||||
ifmaybeload(name);
|
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 ||
|
|
||||||
strcmp(argv[0], "plumb") == 0)) {
|
|
||||||
clone_create();
|
|
||||||
argc--, argv++;
|
|
||||||
if (argc == 0)
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
ifindex = if_nametoindex(name);
|
ifindex = if_nametoindex(name);
|
||||||
if (ifindex == 0)
|
if (ifindex == 0) {
|
||||||
|
/*
|
||||||
|
* 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 ||
|
||||||
|
strcmp(argv[0], "plumb") == 0)) {
|
||||||
|
ifconfig(argc, argv, NULL);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
errx(1, "interface %s does not exist", name);
|
errx(1, "interface %s does not exist", name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for address family */
|
/* Check for address family */
|
||||||
@ -356,9 +354,6 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
if (namesonly && need_nl > 0)
|
if (namesonly && need_nl > 0)
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
end:
|
|
||||||
if (printname)
|
|
||||||
printf("%s\n", name);
|
|
||||||
|
|
||||||
exit (0);
|
exit (0);
|
||||||
}
|
}
|
||||||
@ -782,12 +777,6 @@ setifname(const char *val, int dummy __unused, int s,
|
|||||||
}
|
}
|
||||||
strlcpy(name, newname, sizeof(name));
|
strlcpy(name, newname, sizeof(name));
|
||||||
free(newname);
|
free(newname);
|
||||||
|
|
||||||
/*
|
|
||||||
* Even if we just created the interface, we don't need to print
|
|
||||||
* its name because we just nailed it down separately.
|
|
||||||
*/
|
|
||||||
printname = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -127,7 +127,6 @@ extern char name[IFNAMSIZ]; /* name of interface */
|
|||||||
extern int allmedia;
|
extern int allmedia;
|
||||||
extern int supmedia;
|
extern int supmedia;
|
||||||
extern int printkeys;
|
extern int printkeys;
|
||||||
extern int printname;
|
|
||||||
extern int flags;
|
extern int flags;
|
||||||
extern int newaddr;
|
extern int newaddr;
|
||||||
extern int verbose;
|
extern int verbose;
|
||||||
@ -140,4 +139,5 @@ void printb(const char *s, unsigned value, const char *bits);
|
|||||||
|
|
||||||
void ifmaybeload(char *name);
|
void ifmaybeload(char *name);
|
||||||
|
|
||||||
void clone_create(void);
|
typedef void clone_callback_func(int, struct ifreq *);
|
||||||
|
void clone_setcallback(clone_callback_func *);
|
||||||
|
@ -58,95 +58,119 @@
|
|||||||
static const char rcsid[] =
|
static const char rcsid[] =
|
||||||
"$FreeBSD$";
|
"$FreeBSD$";
|
||||||
#endif
|
#endif
|
||||||
static struct vlanreq __vreq;
|
|
||||||
static int __have_dev = 0;
|
|
||||||
static int __have_tag = 0;
|
|
||||||
|
|
||||||
static void vlan_set(int);
|
#define NOTAG ((u_short) -1)
|
||||||
|
|
||||||
|
static struct vlanreq params = {
|
||||||
|
.vlr_tag = NOTAG,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
getvlan(int s, struct ifreq *ifr, struct vlanreq *vreq)
|
||||||
|
{
|
||||||
|
bzero((char *)vreq, sizeof(*vreq));
|
||||||
|
ifr->ifr_data = (caddr_t)vreq;
|
||||||
|
|
||||||
|
return ioctl(s, SIOCGETVLAN, (caddr_t)ifr);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vlan_status(int s)
|
vlan_status(int s)
|
||||||
{
|
{
|
||||||
struct vlanreq vreq;
|
struct vlanreq vreq;
|
||||||
|
|
||||||
bzero((char *)&vreq, sizeof(vreq));
|
if (getvlan(s, &ifr, &vreq) != -1)
|
||||||
ifr.ifr_data = (caddr_t)&vreq;
|
printf("\tvlan: %d parent interface: %s\n",
|
||||||
|
vreq.vlr_tag, vreq.vlr_parent[0] == '\0' ?
|
||||||
if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1)
|
"<none>" : vreq.vlr_parent);
|
||||||
return;
|
|
||||||
|
|
||||||
printf("\tvlan: %d parent interface: %s\n",
|
|
||||||
vreq.vlr_tag, vreq.vlr_parent[0] == '\0' ?
|
|
||||||
"<none>" : vreq.vlr_parent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
setvlantag(const char *val, int d, int s, const struct afswtch *afp)
|
vlan_create(int s, struct ifreq *ifr)
|
||||||
{
|
{
|
||||||
char *endp;
|
if (params.vlr_tag != NOTAG || params.vlr_parent[0] != '\0') {
|
||||||
u_long ul;
|
/*
|
||||||
|
* One or both parameters were specified, make sure both.
|
||||||
ul = strtoul(val, &endp, 0);
|
*/
|
||||||
if (*endp != '\0')
|
if (params.vlr_tag == NOTAG)
|
||||||
errx(1, "invalid value for vlan");
|
errx(1, "must specify a tag for vlan create");
|
||||||
__vreq.vlr_tag = ul;
|
if (params.vlr_parent[0] == '\0')
|
||||||
/* check if the value can be represented in vlr_tag */
|
errx(1, "must specify a parent device for vlan create");
|
||||||
if (__vreq.vlr_tag != ul)
|
ifr->ifr_data = (caddr_t) ¶ms;
|
||||||
errx(1, "value for vlan out of range");
|
}
|
||||||
/* the kernel will do more specific checks on vlr_tag */
|
if (ioctl(s, SIOCIFCREATE2, ifr) < 0)
|
||||||
__have_tag = 1;
|
err(1, "SIOCIFCREATE2");
|
||||||
vlan_set(s); /* try setting vlan params in kernel */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
setvlandev(const char *val, int d, int s, const struct afswtch *afp)
|
|
||||||
{
|
|
||||||
|
|
||||||
strncpy(__vreq.vlr_parent, val, sizeof(__vreq.vlr_parent));
|
|
||||||
__have_dev = 1;
|
|
||||||
vlan_set(s); /* try setting vlan params in kernel */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
unsetvlandev(const char *val, int d, int s, const struct afswtch *afp)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (val != NULL)
|
|
||||||
warnx("argument to -vlandev is useless and hence deprecated");
|
|
||||||
|
|
||||||
bzero((char *)&__vreq, sizeof(__vreq));
|
|
||||||
ifr.ifr_data = (caddr_t)&__vreq;
|
|
||||||
#if 0 /* this code will be of use when we can alter vlan or vlandev only */
|
|
||||||
if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1)
|
|
||||||
err(1, "SIOCGETVLAN");
|
|
||||||
|
|
||||||
bzero((char *)&__vreq.vlr_parent, sizeof(__vreq.vlr_parent));
|
|
||||||
__vreq.vlr_tag = 0; /* XXX clear parent only (no kernel support now) */
|
|
||||||
#endif
|
|
||||||
if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1)
|
|
||||||
err(1, "SIOCSETVLAN");
|
|
||||||
__have_dev = __have_tag = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vlan_cb(int s, void *arg)
|
vlan_cb(int s, void *arg)
|
||||||
{
|
{
|
||||||
|
if ((params.vlr_tag != NOTAG) ^ (params.vlr_parent[0] != '\0'))
|
||||||
if (__have_tag ^ __have_dev)
|
|
||||||
errx(1, "both vlan and vlandev must be specified");
|
errx(1, "both vlan and vlandev must be specified");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vlan_set(int s)
|
vlan_set(int s, struct ifreq *ifr)
|
||||||
{
|
{
|
||||||
|
if (params.vlr_tag != NOTAG && params.vlr_parent[0] != '\0') {
|
||||||
if (__have_tag && __have_dev) {
|
ifr->ifr_data = (caddr_t) ¶ms;
|
||||||
ifr.ifr_data = (caddr_t)&__vreq;
|
if (ioctl(s, SIOCSETVLAN, (caddr_t)ifr) == -1)
|
||||||
if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1)
|
|
||||||
err(1, "SIOCSETVLAN");
|
err(1, "SIOCSETVLAN");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
DECL_CMD_FUNC(setvlantag, val, d)
|
||||||
|
{
|
||||||
|
struct vlanreq vreq;
|
||||||
|
u_long ul;
|
||||||
|
char *endp;
|
||||||
|
|
||||||
|
ul = strtoul(val, &endp, 0);
|
||||||
|
if (*endp != '\0')
|
||||||
|
errx(1, "invalid value for vlan");
|
||||||
|
params.vlr_tag = ul;
|
||||||
|
/* check if the value can be represented in vlr_tag */
|
||||||
|
if (params.vlr_tag != ul)
|
||||||
|
errx(1, "value for vlan out of range");
|
||||||
|
|
||||||
|
if (getvlan(s, &ifr, &vreq) != -1)
|
||||||
|
vlan_set(s, &ifr);
|
||||||
|
else
|
||||||
|
clone_setcallback(vlan_create);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
DECL_CMD_FUNC(setvlandev, val, d)
|
||||||
|
{
|
||||||
|
struct vlanreq vreq;
|
||||||
|
|
||||||
|
strlcpy(params.vlr_parent, val, sizeof(params.vlr_parent));
|
||||||
|
|
||||||
|
if (getvlan(s, &ifr, &vreq) != -1)
|
||||||
|
vlan_set(s, &ifr);
|
||||||
|
else
|
||||||
|
clone_setcallback(vlan_create);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
DECL_CMD_FUNC(unsetvlandev, val, d)
|
||||||
|
{
|
||||||
|
struct vlanreq vreq;
|
||||||
|
|
||||||
|
bzero((char *)&vreq, sizeof(struct vlanreq));
|
||||||
|
ifr.ifr_data = (caddr_t)&vreq;
|
||||||
|
|
||||||
|
if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1)
|
||||||
|
err(1, "SIOCGETVLAN");
|
||||||
|
|
||||||
|
bzero((char *)&vreq.vlr_parent, sizeof(vreq.vlr_parent));
|
||||||
|
vreq.vlr_tag = 0;
|
||||||
|
|
||||||
|
if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1)
|
||||||
|
err(1, "SIOCSETVLAN");
|
||||||
|
}
|
||||||
|
|
||||||
static struct cmd vlan_cmds[] = {
|
static struct cmd vlan_cmds[] = {
|
||||||
DEF_CMD_ARG("vlan", setvlantag),
|
DEF_CMD_ARG("vlan", setvlantag),
|
||||||
DEF_CMD_ARG("vlandev", setvlandev),
|
DEF_CMD_ARG("vlandev", setvlandev),
|
||||||
|
Loading…
Reference in New Issue
Block a user