Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 7 Feb 2005 17:40:49 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 70523 for review
Message-ID:  <200502071740.j17Henbj028221@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=70523

Change 70523 by sam@sam_ebb on 2005/02/07 17:40:26

	revise cloning support to take an optional device-specific
	parameter block

Affected files ...

.. //depot/projects/vap/sys/net/if.c#2 edit
.. //depot/projects/vap/sys/net/if_clone.c#2 edit
.. //depot/projects/vap/sys/net/if_clone.h#2 edit
.. //depot/projects/vap/sys/net/if_disc.c#2 edit
.. //depot/projects/vap/sys/net/if_faith.c#2 edit
.. //depot/projects/vap/sys/net/if_gif.c#2 edit
.. //depot/projects/vap/sys/net/if_gre.c#2 edit
.. //depot/projects/vap/sys/net/if_loop.c#2 edit
.. //depot/projects/vap/sys/net/if_ppp.c#2 edit
.. //depot/projects/vap/sys/net/if_stf.c#2 edit
.. //depot/projects/vap/sys/net/if_vlan.c#2 edit
.. //depot/projects/wifi/sbin/ifconfig/ifclone.c#6 edit
.. //depot/projects/wifi/sbin/ifconfig/ifconfig.c#11 edit
.. //depot/projects/wifi/sbin/ifconfig/ifconfig.h#9 edit
.. //depot/projects/wifi/sbin/ifconfig/ifieee80211.c#37 edit
.. //depot/projects/wifi/sbin/ifconfig/ifvlan.c#8 edit

Differences ...

==== //depot/projects/vap/sys/net/if.c#2 (text+ko) ====

@@ -1381,7 +1381,7 @@
 		if ((error = suser(td)) != 0)
 			return (error);
 		return ((cmd == SIOCIFCREATE) ?
-			if_clone_create(ifr->ifr_name, sizeof(ifr->ifr_name)) :
+			if_clone_create(ifr->ifr_name, sizeof(ifr->ifr_name), ifr->ifr_data) :
 			if_clone_destroy(ifr->ifr_name));
 
 	case SIOCIFGCLONERS:

==== //depot/projects/vap/sys/net/if_clone.c#2 (text+ko) ====

@@ -112,7 +112,7 @@
  * Create a clone network interface.
  */
 int
-if_clone_create(char *name, size_t len)
+if_clone_create(char *name, size_t len, caddr_t params)
 {
 	int err;
 	struct if_clone *ifc;
@@ -133,7 +133,7 @@
 	if (ifc == NULL)
 		return (EINVAL);
 
-	err = (*ifc->ifc_create)(ifc, name, len);
+	err = (*ifc->ifc_create)(ifc, name, len, params);
 	IF_CLONE_REMREF(ifc);
 	return (err);
 }
@@ -396,7 +396,7 @@
 
 	for (unit = 0; unit < ifcs->ifcs_minifs; unit++) {
 		snprintf(name, IFNAMSIZ, "%s%d", ifc->ifc_name, unit);
-		err = (*ifc->ifc_create)(ifc, name, IFNAMSIZ);
+		err = (*ifc->ifc_create)(ifc, name, IFNAMSIZ, (caddr_t) 0);
 		KASSERT(err == 0,
 		    ("%s: failed to create required interface %s",
 		    __func__, name));
@@ -425,7 +425,7 @@
 }
 
 int
-ifc_simple_create(struct if_clone *ifc, char *name, size_t len)
+ifc_simple_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
 {
 	char *dp;
 	int wildcard;
@@ -443,7 +443,7 @@
 	if (err != 0)
 		return (err);
 
-	err = ifcs->ifcs_create(ifc, unit);
+	err = ifcs->ifcs_create(ifc, unit, params);
 	if (err != 0) {
 		ifc_free_unit(ifc, unit);
 		return (err);

==== //depot/projects/vap/sys/net/if_clone.h#2 (text+ko) ====

@@ -61,7 +61,7 @@
 	/* (c) Driver specific cloning functions.  Called with no locks held. */
 	void	(*ifc_attach)(struct if_clone *);
 	int	(*ifc_match)(struct if_clone *, const char *);
-	int	(*ifc_create)(struct if_clone *, char *, size_t);
+	int	(*ifc_create)(struct if_clone *, char *, size_t, caddr_t);
 	int	(*ifc_destroy)(struct if_clone *, struct ifnet *);
 
 	long ifc_refcnt;		/* (i) Refrence count. */
@@ -72,7 +72,7 @@
 void	if_clone_attach(struct if_clone *);
 void	if_clone_detach(struct if_clone *);
 
-int	if_clone_create(char *, size_t);
+int	if_clone_create(char *, size_t, caddr_t);
 int	if_clone_destroy(const char *);
 int	if_clone_list(struct if_clonereq *);
 
@@ -88,7 +88,7 @@
 struct ifc_simple_data {
 	int ifcs_minifs;		/* minimum number of interfaces */
 
-	int	(*ifcs_create)(struct if_clone *, int);
+	int	(*ifcs_create)(struct if_clone *, int, caddr_t);
 	void	(*ifcs_destroy)(struct ifnet *);
 };
 
@@ -105,7 +105,7 @@
 
 void	ifc_simple_attach(struct if_clone *);
 int	ifc_simple_match(struct if_clone *, const char *);
-int	ifc_simple_create(struct if_clone *, char *, size_t);
+int	ifc_simple_create(struct if_clone *, char *, size_t, caddr_t);
 int	ifc_simple_destroy(struct if_clone *, struct ifnet *);
 
 #endif /* _KERNEL */

==== //depot/projects/vap/sys/net/if_disc.c#2 (text+ko) ====

@@ -70,7 +70,7 @@
 		    struct sockaddr *, struct rtentry *);
 static void	discrtrequest(int, struct rtentry *, struct rt_addrinfo *);
 static int	discioctl(struct ifnet *, u_long, caddr_t);
-static int	disc_clone_create(struct if_clone *, int);
+static int	disc_clone_create(struct if_clone *, int, caddr_t);
 static void	disc_clone_destroy(struct ifnet *);
 
 static struct mtx disc_mtx;
@@ -80,7 +80,7 @@
 IFC_SIMPLE_DECLARE(disc, 0);
 
 static int
-disc_clone_create(struct if_clone *ifc, int unit)
+disc_clone_create(struct if_clone *ifc, int unit, caddr_t params)
 {
 	struct ifnet		*ifp;
 	struct disc_softc	*sc;

==== //depot/projects/vap/sys/net/if_faith.c#2 (text+ko) ====

@@ -101,7 +101,7 @@
 static MALLOC_DEFINE(M_FAITH, FAITHNAME, "Firewall Assisted Tunnel Interface");
 static LIST_HEAD(, faith_softc) faith_softc_list;
 
-static int	faith_clone_create(struct if_clone *, int);
+static int	faith_clone_create(struct if_clone *, int, caddr_t);
 static void	faith_clone_destroy(struct ifnet *);
 static void	faith_destroy(struct faith_softc *);
 
@@ -161,9 +161,10 @@
 MODULE_VERSION(if_faith, 1);
 
 static int
-faith_clone_create(ifc, unit)
+faith_clone_create(ifc, unit, params)
 	struct if_clone *ifc;
 	int unit;
+	caddr_t params;
 {
 	struct faith_softc *sc;
 

==== //depot/projects/vap/sys/net/if_gif.c#2 (text+ko) ====

@@ -98,7 +98,7 @@
 void	(*ng_gif_attach_p)(struct ifnet *ifp);
 void	(*ng_gif_detach_p)(struct ifnet *ifp);
 
-static int	gif_clone_create(struct if_clone *, int);
+static int	gif_clone_create(struct if_clone *, int, caddr_t);
 static void	gif_clone_destroy(struct ifnet *);
 
 IFC_SIMPLE_DECLARE(gif, 0);
@@ -137,9 +137,10 @@
     &parallel_tunnels, 0, "Allow parallel tunnels?");
 
 static int
-gif_clone_create(ifc, unit)
+gif_clone_create(ifc, unit, params)
 	struct if_clone *ifc;
 	int unit;
+	caddr_t params;
 {
 	struct gif_softc *sc;
 

==== //depot/projects/vap/sys/net/if_gre.c#2 (text+ko) ====

@@ -102,7 +102,7 @@
 
 struct gre_softc_head gre_softc_list;
 
-static int	gre_clone_create(struct if_clone *, int);
+static int	gre_clone_create(struct if_clone *, int, caddr_t);
 static void	gre_clone_destroy(struct ifnet *);
 static int	gre_ioctl(struct ifnet *, u_long, caddr_t);
 static int	gre_output(struct ifnet *, struct mbuf *, struct sockaddr *,
@@ -161,9 +161,10 @@
 }
 
 static int
-gre_clone_create(ifc, unit)
+gre_clone_create(ifc, unit, params)
 	struct if_clone *ifc;
 	int unit;
+	caddr_t params;
 {
 	struct gre_softc *sc;
 

==== //depot/projects/vap/sys/net/if_loop.c#2 (text+ko) ====

@@ -101,7 +101,7 @@
 static void	lortrequest(int, struct rtentry *, struct rt_addrinfo *);
 int		looutput(struct ifnet *ifp, struct mbuf *m,
 		    struct sockaddr *dst, struct rtentry *rt);
-static int	lo_clone_create(struct if_clone *, int);
+static int	lo_clone_create(struct if_clone *, int, caddr_t);
 static void	lo_clone_destroy(struct ifnet *);
 
 struct ifnet *loif = NULL;			/* Used externally */
@@ -133,9 +133,10 @@
 }
 
 static int
-lo_clone_create(ifc, unit)
+lo_clone_create(ifc, unit, params)
 	struct if_clone *ifc;
 	int unit;
+	caddr_t params;
 {
 	struct lo_softc *sc;
 

==== //depot/projects/vap/sys/net/if_ppp.c#2 (text+ko) ====

@@ -157,7 +157,7 @@
 static void	ppp_ccp_closed(struct ppp_softc *);
 static void	ppp_inproc(struct ppp_softc *, struct mbuf *);
 static void	pppdumpm(struct mbuf *m0);
-static int	ppp_clone_create(struct if_clone *, int);
+static int	ppp_clone_create(struct if_clone *, int, caddr_t);
 static void	ppp_clone_destroy(struct ifnet *);
 
 struct ppp_softc *
@@ -221,7 +221,7 @@
 #endif /* PPP_COMPRESS */
 
 static int
-ppp_clone_create(struct if_clone *ifc, int unit)
+ppp_clone_create(struct if_clone *ifc, int unit, caddr_t params)
 {
 	struct ppp_softc	*sc;
 
@@ -354,7 +354,7 @@
     /* Try to clone an interface if we don't have a free one */
     if (sc == NULL) {
 	strcpy(tmpname, PPPNAME);
-	if (if_clone_create(tmpname, sizeof(tmpname)) != 0)
+	if (if_clone_create(tmpname, sizeof(tmpname), (caddr_t) 0) != 0)
 	    return NULL;
 	ifp = ifunit(tmpname);
 	if (ifp == NULL)

==== //depot/projects/vap/sys/net/if_stf.c#2 (text+ko) ====

@@ -178,7 +178,7 @@
 static int stf_ioctl(struct ifnet *, u_long, caddr_t);
 
 static int stf_clone_match(struct if_clone *, const char *);
-static int stf_clone_create(struct if_clone *, char *, size_t);
+static int stf_clone_create(struct if_clone *, char *, size_t, caddr_t);
 static int stf_clone_destroy(struct if_clone *, struct ifnet *);
 struct if_clone stf_cloner = IFC_CLONE_INITIALIZER(STFNAME, NULL, 0,
     NULL, stf_clone_match, stf_clone_create, stf_clone_destroy);
@@ -197,7 +197,7 @@
 }
 
 static int
-stf_clone_create(struct if_clone *ifc, char *name, size_t len)
+stf_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
 {
 	int err, unit;
 	struct stf_softc *sc;

==== //depot/projects/vap/sys/net/if_vlan.c#2 (text+ko) ====

@@ -131,7 +131,7 @@
 static	struct ifnet *vlan_clone_match_ethertag(struct if_clone *,
     const char *, int *);
 static	int vlan_clone_match(struct if_clone *, const char *);
-static	int vlan_clone_create(struct if_clone *, char *, size_t);
+static	int vlan_clone_create(struct if_clone *, char *, size_t, caddr_t);
 static	int vlan_clone_destroy(struct if_clone *, struct ifnet *);
 
 struct if_clone vlan_cloner = IFC_CLONE_INITIALIZER(VLANNAME, NULL, IF_MAXUNIT,
@@ -313,7 +313,7 @@
 }
 
 static int
-vlan_clone_create(struct if_clone *ifc, char *name, size_t len)
+vlan_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
 {
 	char *dp;
 	int wildcard;
@@ -324,8 +324,37 @@
 	struct ifvlan *ifv;
 	struct ifnet *ifp;
 	struct ifnet *p;
+	struct vlanreq vlr;
 
-	if ((p = vlan_clone_match_ethertag(ifc, name, &tag)) != NULL) {
+	/*
+	 * There are 3 (ugh) ways to specify the cloned device:
+	 * o pass a parameter block with the clone request.
+	 * o specify parameters in the text of the clone device name
+	 * o specify no parameters and get an unattached device that
+	 *   must be configured separately.
+	 * The first technique is preferred; the latter two are
+	 * supported for backwards compatibilty.
+	 */
+	if (params) {
+		error = copyin(params, &vlr, sizeof(vlr));
+		if (error)
+			return error;
+		p = ifunit(vlr.vlr_parent);
+		if (p == NULL)
+			return ENXIO;
+		/*
+		 * Don't let the caller set up a VLAN tag with
+		 * anything except VLID bits.
+		 */
+		if (vlr.vlr_tag & ~EVL_VLID_MASK)
+			return (EINVAL);
+		error = ifc_name2unit(name, &unit);
+		if (error != 0)
+			return (error);
+
+		tag = vlr.vlr_tag;
+		wildcard = (unit < 0);
+	} else if ((p = vlan_clone_match_ethertag(ifc, name, &tag)) != NULL) {
 		ethertag = 1;
 		unit = -1;
 		wildcard = 0;

==== //depot/projects/wifi/sbin/ifconfig/ifclone.c#6 (text+ko) ====

@@ -88,48 +88,62 @@
 	free(buf);
 }
 
+static clone_callback_func *clone_cb = NULL;
+
 void
-clone_create(void)
+clone_setcallback(clone_callback_func *p)
 {
-	int s;
+	if (clone_cb != NULL && clone_cb != p)
+		errx(1, "conflicting device create parameters");
+	clone_cb = p;
+}
 
-	s = socket(AF_INET, SOCK_DGRAM, 0);
-	if (s == -1)
-		err(1, "socket(AF_INET,SOCK_DGRAM)");
+/*
+ * 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));
 	(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
-	if (ioctl(s, SIOCIFCREATE, &ifr) < 0)
-		err(1, "SIOCIFCREATE");
+	if (clone_cb == NULL) {
+		/* NB: no parameters */
+		if (ioctl(s, SIOCIFCREATE, &ifr) < 0)
+			err(1, "SIOCIFCREATE");
+	} 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 intrest 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
+DECL_CMD_FUNC(clone_create, arg, d)
+{
+	callback_register(ifclonecreate, NULL);
 }
 
-static void
-clone_destroy(const char *val, int d, int s, const struct afswtch *rafp)
+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_CMD("create",	0,	clone_create),
 	DEF_CMD("destroy",	0,	clone_destroy),
 	DEF_CMD("unplumb",	0,	clone_destroy),
 };

==== //depot/projects/wifi/sbin/ifconfig/ifconfig.c#11 (text+ko) ====

@@ -91,7 +91,6 @@
 int	verbose;
 
 int	supmedia = 0;
-int	printname = 0;		/* Print the name of the created interface. */
 
 static	int ifconfig(int argc, char *const *argv, const struct afswtch *afp);
 static	void status(const struct afswtch *afp, int addrcount,
@@ -233,16 +232,14 @@
 		ifindex = if_nametoindex(name);
 		if (ifindex == 0) {
 			/*
-			 * NOTE:  We must special-case the `create' command right
-			 * here as we would otherwise fail when trying to find
-			 * the interface.
+			 * 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;
+				ifconfig(argc, argv, NULL);
+				exit(0);
 			}
 			errx(1, "interface %s does not exist", name);
 		}
@@ -353,9 +350,6 @@
 
 	if (namesonly && need_nl > 0)
 		putchar('\n');
-end:
-	if (printname)
-		printf("%s\n", name);
 
 	exit (0);
 }
@@ -780,12 +774,6 @@
 	}
 	strlcpy(name, newname, sizeof(name));
 	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;
 }
 
 /*

==== //depot/projects/wifi/sbin/ifconfig/ifconfig.h#9 (text+ko) ====

@@ -126,7 +126,6 @@
 extern	char name[IFNAMSIZ];	/* name of interface */
 extern	int allmedia;
 extern	int supmedia;
-extern	int printname;
 extern	int flags;
 extern	int newaddr;
 extern	int verbose;
@@ -139,4 +138,5 @@
 
 void	ifmaybeload(char *name);
 
-void	clone_create(void);
+typedef void clone_callback_func(int, struct ifreq *);
+void	clone_setcallback(clone_callback_func *);

==== //depot/projects/wifi/sbin/ifconfig/ifieee80211.c#37 (text+ko) ====

@@ -1120,56 +1120,49 @@
 #undef iseq
 }
 
+static 	struct ieee80211_clone_params params = {
+	.icp_opmode	= IEEE80211_M_STA,	/* default to station mode */
+};
+
+static void
+wlan_create(int s, struct ifreq *ifr)
+{
+	if (params.icp_parent[0] == '\0')
+		errx(1, "must specify a parent when creating a wlan device");
+	ifr->ifr_data = (caddr_t) &params;
+	if (ioctl(s, SIOCIFCREATE, ifr) < 0)
+		err(1, "SIOCIFCREATE");
+}
+
 static
-DECL_CMD_FUNC(set80211create, arg, d)
+DECL_CMD_FUNC(set80211wlandev, arg, d)
+{
+	strlcpy(params.icp_parent, arg, IFNAMSIZ);
+	clone_setcallback(wlan_create);
+}
+
+static
+DECL_CMD_FUNC(set80211wlantype, arg, d)
 {
 #define	iseq(a,b)	(strncasecmp(a,b,sizeof(b)-1) == 0)
-	struct ifreq ifr;
-	int opmode;
-
 	if (iseq(arg, "sta"))
-		opmode = IEEE80211_M_STA;
+		params.icp_opmode = IEEE80211_M_STA;
 	else if (iseq(arg, "ahdemo") || iseq(arg, "adhoc-demo"))
-		opmode = IEEE80211_M_AHDEMO;
+		params.icp_opmode = IEEE80211_M_AHDEMO;
 	else if (iseq(arg, "ibss") || iseq(arg, "adhoc"))
-		opmode = IEEE80211_M_IBSS;
+		params.icp_opmode = IEEE80211_M_IBSS;
 	else if (iseq(arg, "ap") || iseq(arg, "hostap"))
-		opmode = IEEE80211_M_HOSTAP;
+		params.icp_opmode = IEEE80211_M_HOSTAP;
 	else if (iseq(arg, "wds"))
-		opmode = IEEE80211_M_WDS;
+		params.icp_opmode = IEEE80211_M_WDS;
 	else if (iseq(arg, "monitor"))
-		opmode = IEEE80211_M_MONITOR;
+		params.icp_opmode = IEEE80211_M_MONITOR;
 	else
 		errx(1, "Don't know how to create %s for %s", arg, name);
-
-	(void) memset(&ifr, 0, sizeof(ifr));
-	(void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
-	ifr.ifr_flags = opmode;
-	if (ioctl(s, SIOC80211IFCREATE, &ifr) < 0)
-		err(1, "SIOC80211IFCREATE");
-	/*
-	 * 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 (strcmp(name, ifr.ifr_name) != 0) {
-		printname = 1;
-		strlcpy(name, ifr.ifr_name, sizeof(name));
-	}
+	clone_setcallback(wlan_create);
 #undef iseq
 }
 
-static
-DECL_CMD_FUNC(set80211destroy, arg, d)
-{
-	struct ifreq req;
-
-	(void) memset(&req, 0, sizeof(req));
-	(void) strncpy(req.ifr_name, name, sizeof(req.ifr_name));
-	if (ioctl(s, SIOC80211IFDESTROY, &req) < 0)
-		err(1, "SIOC80211IFDESTROY");
-}
-
 static enum ieee80211_opmode
 get80211opmode(int s)
 {
@@ -1870,8 +1863,8 @@
 	DEF_CMD("-ff",		0,	set80211fastframes),
 	DEF_CMD("turbo",	1,	set80211turbo),
 	DEF_CMD("-turbo",	0,	set80211turbo),
-	DEF_CMD_ARG("create",		set80211create),
-	DEF_CMD("kill",		0,	set80211destroy),	/*XXX*/
+	DEF_CMD_ARG("wlandev",		set80211wlandev),
+	DEF_CMD_ARG("wlantype",		set80211wlantype),
 };
 static struct afswtch af_ieee80211 = {
 	.af_name	= "af_ieee80211",

==== //depot/projects/wifi/sbin/ifconfig/ifvlan.c#8 (text+ko) ====

@@ -58,8 +58,12 @@
 static const char rcsid[] =
   "$FreeBSD: src/sbin/ifconfig/ifvlan.c,v 1.7 2004/12/31 19:46:27 sam Exp $";
 #endif
-static int			__tag = 0;
-static int			__have_tag = 0;
+
+#define	NOTAG	((u_short) -1)
+
+static 	struct vlanreq params = {
+	.vlr_tag	= NOTAG,
+};
 
 static void
 vlan_status(int s)
@@ -75,58 +79,66 @@
 	printf("\tvlan: %d parent interface: %s\n",
 	    vreq.vlr_tag, vreq.vlr_parent[0] == '\0' ?
 	    "<none>" : vreq.vlr_parent);
+}
 
-	return;
+static void
+vlan_create(int s, struct ifreq *ifr)
+{
+	if (params.vlr_tag != NOTAG || params.vlr_parent[0] != '\0') {
+		/*
+		 * One or both parameters were specified, make sure both.
+		 */
+		if (params.vlr_tag == NOTAG)
+			errx(1, "must specify a tag for vlan create");
+		if (params.vlr_parent[0] == '\0')
+			errx(1, "must specify a parent device for vlan create");
+		ifr->ifr_data = (caddr_t) &params;
+	}
+	if (ioctl(s, SIOCIFCREATE, ifr) < 0)
+		err(1, "SIOCIFCREATE");
 }
 
-static void
-setvlantag(const char *val, int d, int s, const struct afswtch	*afp)
+static
+DECL_CMD_FUNC(setvlantag, val, d)
 {
 	u_int16_t		tag;
 	struct vlanreq		vreq;
 
-	__tag = tag = atoi(val);
-	__have_tag = 1;
+	tag = (u_int16_t) atoi(val);
 
 	bzero((char *)&vreq, sizeof(struct vlanreq));
 	ifr.ifr_data = (caddr_t)&vreq;
 
-	if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1)
-		err(1, "SIOCGETVLAN");
-
-	vreq.vlr_tag = tag;
-
-	if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1)
-		err(1, "SIOCSETVLAN");
-
-	return;
+	if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) != -1) {
+		vreq.vlr_tag = tag;
+		if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1)
+			err(1, "SIOCSETVLAN");
+	} else {
+		params.vlr_tag = tag;
+		clone_setcallback(vlan_create);
+	}
 }
 
-static void
-setvlandev(const char *val, int d, int s, const struct afswtch	*afp)
+static
+DECL_CMD_FUNC(setvlandev, val, d)
 {
 	struct vlanreq		vreq;
 
-	if (!__have_tag)
-		errx(1, "must specify both vlan tag and device");
-
 	bzero((char *)&vreq, sizeof(struct vlanreq));
 	ifr.ifr_data = (caddr_t)&vreq;
 
-	if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1)
-		err(1, "SIOCGETVLAN");
-
-	strncpy(vreq.vlr_parent, val, sizeof(vreq.vlr_parent));
-	vreq.vlr_tag = __tag;
-
-	if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1)
-		err(1, "SIOCSETVLAN");
-
-	return;
+	if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) != -1) {
+		strncpy(vreq.vlr_parent, val, sizeof(vreq.vlr_parent));
+		if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1)
+			err(1, "SIOCSETVLAN");
+	} else {
+		strlcpy(params.vlr_parent, val, sizeof(params.vlr_parent));
+		clone_setcallback(vlan_create);
+	}
 }
 
-static void
-unsetvlandev(const char *val, int d, int s, const struct afswtch *afp)
+static
+DECL_CMD_FUNC(unsetvlandev, val, d)
 {
 	struct vlanreq		vreq;
 
@@ -141,8 +153,6 @@
 
 	if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1)
 		err(1, "SIOCSETVLAN");
-
-	return;
 }
 
 static struct cmd vlan_cmds[] = {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200502071740.j17Henbj028221>