Fix handling of create operation together with setting other parameters:

o mark cmds/parameters to indicate they are potential arguments to a clone
  operation (e.g. vlantag)
o when handling a create/clone operation do the callback on seeing the first
  non-clone cmd line argument so the new device is created and can be used;
  and re-setup operating state to reflect the newly created device

Reviewed by:	Eugene Grosbein
MFC after:	2 weeks
This commit is contained in:
Sam Leffler 2008-03-31 15:38:07 +00:00
parent 836d250db3
commit 2fa02c5fb7
4 changed files with 42 additions and 9 deletions

View File

@ -143,9 +143,9 @@ DECL_CMD_FUNC(clone_destroy, arg, d)
} }
static struct cmd clone_cmds[] = { static struct cmd clone_cmds[] = {
DEF_CMD("create", 0, clone_create), DEF_CLONE_CMD("create", 0, clone_create),
DEF_CMD("destroy", 0, clone_destroy), DEF_CMD("destroy", 0, clone_destroy),
DEF_CMD("plumb", 0, clone_create), DEF_CLONE_CMD("plumb", 0, clone_create),
DEF_CMD("unplumb", 0, clone_destroy), DEF_CMD("unplumb", 0, clone_destroy),
}; };

View File

@ -93,7 +93,8 @@ int noload;
int supmedia = 0; int supmedia = 0;
int printkeys = 0; /* Print keying material for interfaces. */ int printkeys = 0; /* Print keying material for interfaces. */
static int ifconfig(int argc, char *const *argv, const struct afswtch *afp); static int ifconfig(int argc, char *const *argv, int iscreate,
const struct afswtch *afp);
static void status(const struct afswtch *afp, const struct sockaddr_dl *sdl, static void status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
struct ifaddrs *ifa); struct ifaddrs *ifa);
static void tunnel_status(int s); static void tunnel_status(int s);
@ -247,7 +248,7 @@ main(int argc, char *argv[])
if (iflen >= sizeof(name)) if (iflen >= sizeof(name))
errx(1, "%s: cloning name too long", errx(1, "%s: cloning name too long",
ifname); ifname);
ifconfig(argc, argv, NULL); ifconfig(argc, argv, 1, NULL);
exit(0); exit(0);
} }
errx(1, "interface %s does not exist", ifname); errx(1, "interface %s does not exist", ifname);
@ -305,7 +306,7 @@ main(int argc, char *argv[])
} }
if (argc > 0) if (argc > 0)
ifconfig(argc, argv, afp); ifconfig(argc, argv, 0, afp);
else else
status(afp, sdl, ifa); status(afp, sdl, ifa);
} }
@ -433,17 +434,19 @@ static const struct cmd setifdstaddr_cmd =
DEF_CMD("ifdstaddr", 0, setifdstaddr); DEF_CMD("ifdstaddr", 0, setifdstaddr);
static int static int
ifconfig(int argc, char *const *argv, const struct afswtch *afp) ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *afp)
{ {
const struct afswtch *nafp;
struct callback *cb; struct callback *cb;
int s; int s;
strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
top:
if (afp == NULL) if (afp == NULL)
afp = af_getbyname("inet"); afp = af_getbyname("inet");
ifr.ifr_addr.sa_family = ifr.ifr_addr.sa_family =
afp->af_af == AF_LINK || afp->af_af == AF_UNSPEC ? afp->af_af == AF_LINK || afp->af_af == AF_UNSPEC ?
AF_INET : afp->af_af; AF_INET : afp->af_af;
strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0)
err(1, "socket(family %u,SOCK_DGRAM", ifr.ifr_addr.sa_family); err(1, "socket(family %u,SOCK_DGRAM", ifr.ifr_addr.sa_family);
@ -460,6 +463,33 @@ ifconfig(int argc, char *const *argv, const struct afswtch *afp)
p = (setaddr ? &setifdstaddr_cmd : &setifaddr_cmd); p = (setaddr ? &setifdstaddr_cmd : &setifaddr_cmd);
} }
if (p->c_u.c_func || p->c_u.c_func2) { if (p->c_u.c_func || p->c_u.c_func2) {
if (iscreate && !p->c_iscloneop) {
/*
* Push the clone create callback so the new
* device is created and can be used for any
* remaining arguments.
*/
cb = callbacks;
if (cb == NULL)
errx(1, "internal error, no callback");
callbacks = cb->cb_next;
cb->cb_func(s, cb->cb_arg);
iscreate = 0;
/*
* Handle any address family spec that
* immediately follows and potentially
* recreate the socket.
*/
nafp = af_getbyname(*argv);
if (nafp != NULL) {
argc--, argv++;
if (nafp != afp) {
close(s);
afp = nafp;
goto top;
}
}
}
if (p->c_parameter == NEXTARG) { if (p->c_parameter == NEXTARG) {
if (argv[1] == NULL) if (argv[1] == NULL)
errx(1, "'%s' requires argument", errx(1, "'%s' requires argument",

View File

@ -52,6 +52,7 @@ struct cmd {
c_func *c_func; c_func *c_func;
c_func2 *c_func2; c_func2 *c_func2;
} c_u; } c_u;
int c_iscloneop;
struct cmd *c_next; struct cmd *c_next;
}; };
void cmd_register(struct cmd *); void cmd_register(struct cmd *);
@ -71,6 +72,8 @@ void callback_register(callback_func *, void *);
#define DEF_CMD_ARG(name, func) { name, NEXTARG, { .c_func = func } } #define DEF_CMD_ARG(name, func) { name, NEXTARG, { .c_func = func } }
#define DEF_CMD_OPTARG(name, func) { name, OPTARG, { .c_func = func } } #define DEF_CMD_OPTARG(name, func) { name, OPTARG, { .c_func = func } }
#define DEF_CMD_ARG2(name, func) { name, NEXTARG2, { .c_func2 = func } } #define DEF_CMD_ARG2(name, func) { name, NEXTARG2, { .c_func2 = func } }
#define DEF_CLONE_CMD(name, param, func) { name, param, { .c_func = func }, 1 }
#define DEF_CLONE_CMD_ARG(name, func) { name, NEXTARG, { .c_func = func }, 1 }
struct ifaddrs; struct ifaddrs;
struct addrinfo; struct addrinfo;

View File

@ -172,8 +172,8 @@ DECL_CMD_FUNC(unsetvlandev, val, d)
} }
static struct cmd vlan_cmds[] = { static struct cmd vlan_cmds[] = {
DEF_CMD_ARG("vlan", setvlantag), DEF_CLONE_CMD_ARG("vlan", setvlantag),
DEF_CMD_ARG("vlandev", setvlandev), DEF_CLONE_CMD_ARG("vlandev", setvlandev),
/* XXX For compatibility. Should become DEF_CMD() some day. */ /* XXX For compatibility. Should become DEF_CMD() some day. */
DEF_CMD_OPTARG("-vlandev", unsetvlandev), DEF_CMD_OPTARG("-vlandev", unsetvlandev),
DEF_CMD("vlanmtu", IFCAP_VLAN_MTU, setifcap), DEF_CMD("vlanmtu", IFCAP_VLAN_MTU, setifcap),