* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sbin/ifconfig/ifclone.c,v 1.1 2004/12/08 19:18:07 sam Exp $
- * $DragonFly: src/sbin/ifconfig/ifclone.c,v 1.1 2006/04/02 03:33:59 sephe Exp $
+ * $FreeBSD: head/sbin/ifconfig/ifclone.c 194799 2009-06-23 23:49:52Z delphij $
+ * $DragonFly$
*/
+#include <sys/queue.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
free(buf);
}
+struct clone_defcb {
+ char ifprefix[IFNAMSIZ];
+ clone_callback_func *clone_cb;
+ SLIST_ENTRY(clone_defcb) next;
+};
+
+static SLIST_HEAD(, clone_defcb) clone_defcbh =
+ SLIST_HEAD_INITIALIZER(clone_defcbh);
+
void
-clone_create(void)
+clone_setdefcallback(const char *ifprefix, clone_callback_func *p)
{
- int s;
+ struct clone_defcb *dcp;
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s == -1)
- err(1, "socket(AF_INET,SOCK_DGRAM)");
+ dcp = malloc(sizeof(*dcp));
+ strlcpy(dcp->ifprefix, ifprefix, IFNAMSIZ-1);
+ dcp->clone_cb = p;
+ SLIST_INSERT_HEAD(&clone_defcbh, dcp, next);
+}
+
+/*
+ * 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;
+ struct clone_defcb *dcp;
+ clone_callback_func *clone_cb = NULL;
memset(&ifr, 0, sizeof(ifr));
(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- wlan_create(s, &ifr);
-#if 0
- if (ioctl(s, SIOCIFCREATE, &ifr) < 0)
- err(1, "SIOCIFCREATE");
-#endif
+
+ if (clone_cb == NULL) {
+ /* Try to find a default callback */
+ SLIST_FOREACH(dcp, &clone_defcbh, next) {
+ if (strncmp(dcp->ifprefix, ifr.ifr_name,
+ strlen(dcp->ifprefix)) == 0) {
+ clone_cb = dcp->clone_cb;
+ break;
+ }
+ }
+ }
+ if (clone_cb == NULL) {
+ /* NB: no parameters */
+ if (ioctl(s, SIOCIFCREATE2, &ifr) < 0)
+ err(1, "SIOCIFCREATE2");
+ } else {
+ clone_cb(s, &ifr);
+ }
/*
- * If we get a different name back then we put in, we probably
- * want to print it out, but we might change our mind later so
- * we just signal our interest and leave the printout for later.
+ * If we get a different name back than we put in, print it.
*/
- if (strcmp(name, ifr.ifr_name) != 0) {
- printname = 1;
+ if (strncmp(name, ifr.ifr_name, sizeof(name)) != 0) {
strlcpy(name, ifr.ifr_name, sizeof(name));
+ printf("%s\n", name);
}
-
- close(s);
}
-static void
-clone_destroy(const char *val, int d, int s, const struct afswtch *rafp)
+static
+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));
if (ioctl(s, SIOCIFDESTROY, &ifr) < 0)
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[] = {
+ DEF_CLONE_CMD("create", 0, clone_create),
DEF_CMD("destroy", 0, clone_destroy),
+ DEF_CLONE_CMD("plumb", 0, clone_create),
DEF_CMD("unplumb", 0, clone_destroy),
};
list_cloners();
exit(0);
}
-static struct option clone_Copt = { "C", "[-C]", clone_Copt_cb };
+static struct option clone_Copt = { .opt = "C", .opt_usage = "[-C]", .cb = clone_Copt_cb };
static __constructor void
clone_ctor(void)
{
#define N(a) (sizeof(a) / sizeof(a[0]))
- int i;
+ size_t i;
for (i = 0; i < N(clone_cmds); i++)
cmd_register(&clone_cmds[i]);
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, int, const struct afswtch *afp);
static void status(const struct afswtch *afp, int addrcount,
struct sockaddr_dl *sdl, struct if_msghdr *ifm,
struct ifa_msghdr *ifam);
size_t needed;
int mib[6];
char options[1024];
+ const char *ifname;
struct option *p;
+ size_t iflen;
all = downonly = uponly = namesonly = verbose = 0;
if (argc > 1)
usage();
+ ifname = NULL;
ifindex = 0;
if (argc == 1) {
afp = af_getbyname(*argv);
if (argc < 1)
usage();
- strncpy(name, *argv, sizeof(name));
+ ifname = *argv;
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 ||
- strcmp(argv[0], "plumb") == 0)) {
- clone_create();
- argc--, argv++;
- if (argc == 0)
- goto end;
- }
- ifindex = if_nametoindex(name);
- if (ifindex == 0)
+ ifindex = if_nametoindex(ifname);
+ 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)) {
+ iflen = strlcpy(name, ifname, sizeof(name));
+ if (iflen >= sizeof(name))
+ errx(1, "%s: cloning name too long",
+ ifname);
+ ifconfig(argc, argv, 1, NULL);
+ exit(0);
+ }
errx(1, "interface %s does not exist", name);
+ }
}
/* Check for address family */
}
if (argc > 0)
- ifconfig(argc, argv, afp);
+ ifconfig(argc, argv, 0, afp);
else
status(afp, addrcount, sdl, ifm, ifam);
}
}
static const struct cmd *
-cmd_lookup(const char *name)
+cmd_lookup(const char *name, int iscreate)
{
#define N(a) (sizeof(a)/sizeof(a[0]))
const struct cmd *p;
for (p = cmds; p != NULL; p = p->c_next)
if (strcmp(name, p->c_name) == 0)
+ if (iscreate) {
+ if (p->c_iscloneop)
+ return p;
+ } else {
+ if (!p->c_iscloneop)
+ return p;
+ }
return p;
return NULL;
#undef N
DEF_CMD("ifdstaddr", 0, setifdstaddr);
static int
-ifconfig(int argc, char *const *argv, const struct afswtch *afp)
+ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *uafp)
{
+ const struct afswtch *afp, *nafp;
struct callback *cb;
int s;
- if (afp == NULL)
- afp = af_getbyname("inet");
+ strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
+ afp = uafp != NULL ? uafp : af_getbyname("inet");
+top:
ifr.ifr_addr.sa_family =
afp->af_af == AF_LINK || afp->af_af == AF_UNSPEC ?
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)
err(1, "socket(family %u,SOCK_DGRAM", ifr.ifr_addr.sa_family);
while (argc > 0) {
const struct cmd *p;
- p = cmd_lookup(*argv);
+ p = cmd_lookup(*argv, iscreate);
+
+ if (iscreate && p == NULL) {
+ /*
+ * 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;
+ }
+ }
+ /*
+ * Look for a normal parameter.
+ */
+ continue;
+ }
if (p == NULL) {
/*
* Not a recognized command, choose between setting
void ifmaybeload(char *);
-void clone_create(void);
+typedef void clone_callback_func(int, struct ifreq *);
+void clone_setdefcallback(const char *, clone_callback_func *);
/*
* XXX expose this so modules that neeed to know of any pending
* SUCH DAMAGE.
*
* $FreeBSD: head/sbin/ifconfig/ifieee80211.c 203970 2010-02-16 21:39:20Z imp $
+ * $DragonFly$
*/
/*-
memcmp(params.icp_bssid, zerobssid, sizeof(zerobssid)) == 0)
errx(1, "no bssid specified for WDS (use wlanbssid)");
ifr->ifr_data = (caddr_t) ¶ms;
- if (ioctl(s, SIOCIFCREATE, ifr) < 0)
- err(1, "SIOCIFCREATE");
+ if (ioctl(s, SIOCIFCREATE2, ifr) < 0)
+ err(1, "SIOCIFCREATE2");
}
static
for (i = 0; i < N(ieee80211_cmds); i++)
cmd_register(&ieee80211_cmds[i]);
af_register(&af_ieee80211);
- //clone_setdefcallback("wlan", wlan_create);
+ clone_setdefcallback("wlan", wlan_create);
#undef N
}