Bring in new ifconfig(8) from FreeBSD6. It is more modular and flexible with
[dragonfly.git] / sbin / ifconfig / ifvlan.c
index 0d6fcc2..56f9be2 100644 (file)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: src/sbin/ifconfig/ifvlan.c,v 1.2 1999/08/28 00:13:09 peter Exp $
- * $DragonFly: src/sbin/ifconfig/ifvlan.c,v 1.4 2003/09/28 14:39:18 hmp Exp $
- *
- * $FreeBSD: src/sbin/ifconfig/ifvlan.c,v 1.2 1999/08/28 00:13:09 peter Exp $
+ * $FreeBSD: src/sbin/ifconfig/ifvlan.c,v 1.7.2.4 2006/02/09 10:48:43 yar Exp $
+ * $DragonFly: src/sbin/ifconfig/ifvlan.c,v 1.8 2006/04/02 03:33:59 sephe Exp $
  */
 
 #include <sys/param.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
-#include <sys/mbuf.h>
 
 #include <stdlib.h>
 #include <unistd.h>
 
 #include "ifconfig.h"
 
-static int                     __tag = 0;
+static struct vlanreq          __vreq;
+static int                     __have_dev = 0;
 static int                     __have_tag = 0;
 
-void vlan_status(int s, struct rt_addrinfo *info __unused)
+static void
+vlan_status(int s)
 {
        struct vlanreq          vreq;
 
-       bzero((char *)&vreq, sizeof(struct vlanreq));
+       bzero((char *)&vreq, sizeof(vreq));
        ifr.ifr_data = (caddr_t)&vreq;
 
        if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1)
@@ -76,69 +75,93 @@ void vlan_status(int s, struct rt_addrinfo *info __unused)
        printf("\tvlan: %d parent interface: %s\n",
            vreq.vlr_tag, vreq.vlr_parent[0] == '\0' ?
            "<none>" : vreq.vlr_parent);
-
-       return;
 }
 
-void setvlantag(const char *val, int d, int s, const struct afswtch *afp)
+static void
+setvlantag(const char *val, int d, int s, const struct afswtch *afp)
 {
-       u_int16_t               tag;
-       struct vlanreq          vreq;
-
-       __tag = tag = atoi(val);
+       char                    *endp;
+       u_long                  ul;
+
+       ul = strtoul(val, &endp, 0);
+       if (*endp != '\0')
+               errx(1, "invalid value for vlan");
+       __vreq.vlr_tag = ul;
+       /* check if the value can be represented in vlr_tag */
+       if (__vreq.vlr_tag != ul)
+               errx(1, "value for vlan out of range");
+       /* the kernel will do more specific checks on vlr_tag */
        __have_tag = 1;
+}
 
-       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");
+static void
+setvlandev(const char *val, int d, int s, const struct afswtch *afp)
+{
 
-       return;
+       strncpy(__vreq.vlr_parent, val, sizeof(__vreq.vlr_parent));
+       __have_dev = 1;
 }
 
-void setvlandev(const char *val, int d, int s, const struct afswtch *afp)
+static void
+unsetvlandev(const char *val, int d, int s, const struct afswtch *afp)
 {
-       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 (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");
 
-       strncpy(vreq.vlr_parent, val, sizeof(vreq.vlr_parent));
-       vreq.vlr_tag = __tag;
-
+       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");
-
-       return;
+       __have_dev = __have_tag = 0;
 }
 
-void unsetvlandev(const char *val, int d, int s, const struct afswtch *afp)
+static void
+vlan_cb(int s, void *arg)
 {
-       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");
+       if (__have_tag ^ __have_dev)
+               errx(1, "both vlan and vlandev must be specified");
 
-       bzero((char *)&vreq.vlr_parent, sizeof(vreq.vlr_parent));
-       vreq.vlr_tag = 0;
-
-       if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1)
-               err(1, "SIOCSETVLAN");
+       if (__have_tag && __have_dev) {
+               ifr.ifr_data = (caddr_t)&__vreq;
+               if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1)
+                       err(1, "SIOCSETVLAN");
+       }
+}
 
-       return;
+static struct cmd vlan_cmds[] = {
+       DEF_CMD_ARG("vlan",                             setvlantag),
+       DEF_CMD_ARG("vlandev",                          setvlandev),
+       /* XXX For compatibility.  Should become DEF_CMD() some day. */
+       DEF_CMD_OPTARG("-vlandev",                      unsetvlandev),
+       DEF_CMD("vlanmtu",      IFCAP_VLAN_MTU,         setifcap),
+       DEF_CMD("-vlanmtu",     -IFCAP_VLAN_MTU,        setifcap),
+       DEF_CMD("vlanhwtag",    IFCAP_VLAN_HWTAGGING,   setifcap),
+       DEF_CMD("-vlanhwtag",   -IFCAP_VLAN_HWTAGGING,  setifcap),
+};
+static struct afswtch af_vlan = {
+       .af_name        = "af_vlan",
+       .af_af          = AF_UNSPEC,
+       .af_other_status = vlan_status,
+};
+
+static __constructor void
+vlan_ctor(void)
+{
+#define        N(a)    (sizeof(a) / sizeof(a[0]))
+       int i;
+
+       for (i = 0; i < N(vlan_cmds);  i++)
+               cmd_register(&vlan_cmds[i]);
+       af_register(&af_vlan);
+       callback_register(vlan_cb, NULL);
+#undef N
 }