if_vlan support
authorchris <chris@openbsd.org>
Wed, 26 Apr 2000 19:03:46 +0000 (19:03 +0000)
committerchris <chris@openbsd.org>
Wed, 26 Apr 2000 19:03:46 +0000 (19:03 +0000)
sbin/ifconfig/ifconfig.8
sbin/ifconfig/ifconfig.c

index 5226ee2..0c5e302 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: ifconfig.8,v 1.42 2000/04/12 21:47:58 aaron Exp $
+.\"    $OpenBSD: ifconfig.8,v 1.43 2000/04/26 19:03:46 chris Exp $
 .\"    $NetBSD: ifconfig.8,v 1.11 1996/01/04 21:27:29 pk Exp $
 .\"     $FreeBSD: ifconfig.8,v 1.16 1998/02/01 07:03:29 steve Exp $
 .\"
 .Cm giftunnel
 .Ar src_address dest_address
 .Nm ifconfig
+.Ar vlan-interface
+.Cm vlan
+.Ar vlan-tag
+.Cm vlandev
+.Ar parent-interface
+.Nm ifconfig
 .Ar interface
 .Op Ar address_family
 .Nm ifconfig
@@ -310,6 +316,48 @@ This is useful for devices which have multiple physical layer interfaces
 Setting the instance on such devices may not be strictly required
 by the network interface driver as the driver may take care of this
 automatically; see the driver's manual page for more information.
+.It Cm vlan Ar vlan_tag
+If the interface is a vlan pseudo interface, set the vlan tag value
+to
+.Ar vlan_tag .
+This value is a 16-bit number which is used to create an 802.1Q
+vlan header for packets sent from the vlan interface. Note that
+.Cm vlan
+and
+.Cm vlandev
+must both be set at the same time.
+.It Cm vlandev Ar iface
+If the interface is a vlan pseudo device, associate physical interface
+.Ar iface
+with it. Packets transmitted through the vlan interface will be
+diverted to the specified physical interface
+.Ar iface
+with 802.1Q vlan encapsulation. Packets with 802.1Q encapsulation received
+by the parent interface with the correct vlan tag will be diverted to
+the associated vlan pseudo-interface. The vlan interface is assigned a
+copy of the parent interface's flags and the parent's ethernet address.
+The
+.Cm vlandev
+and
+.Cm vlan
+must both be set at the same time. If the vlan interface already has
+a physical interface associated with it, this command will fail. To
+change the association to another physical interface, the existing
+association must be cleared first.
+.Pp
+Note: if the
+.Ar link0
+flag is set on the vlan interface, the vlan pseudo
+interface's behavior changes: the
+.Ar link0
+tells the vlan interface that the
+parent interface supports insertion and extraction of vlan tags on its
+own (usually in firmware) and that it should pass packets to and from
+the parent unaltered.
+.It Fl vlandev
+If the driver is a vlan pseudo device, disassociate the physical interface
+from it. This breaks the link between the vlan interface and its parent,
+clears its vlan tag, flags and its link address and shuts the interface down.
 .It Cm metric Ar n
 Set the routing metric of the interface to
 .Ar n ,
@@ -498,6 +546,10 @@ Configure the xl0 interface to use 10baseT.
 .Pp
 .It Cm ifconfig xl0 media 100baseTX mediaopt full-duplex
 Configure the xl0 interface to use 100baseTX, full duplex.
+.Pp
+.It Cm ifconfig vlan0 192.168.254.1 vlan 4 vlandev fxp0
+Configure the vlan0 interface for IP address 192.168.254.1, vlan tag 4,
+and vlan parent device fxp0.
 .El
 .Sh DIAGNOSTICS
 Messages indicating the specified interface does not exist, the
index 976123d..342aa35 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ifconfig.c,v 1.34 2000/04/14 02:40:01 itojun Exp $    */
+/*     $OpenBSD: ifconfig.c,v 1.35 2000/04/26 19:03:46 chris Exp $     */
 /*      $NetBSD: ifconfig.c,v 1.40 1997/10/01 02:19:43 enami Exp $      */
 
 /*
@@ -81,7 +81,7 @@ static char copyright[] =
 #if 0
 static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94";
 #else
-static char rcsid[] = "$OpenBSD: ifconfig.c,v 1.34 2000/04/14 02:40:01 itojun Exp $";
+static char rcsid[] = "$OpenBSD: ifconfig.c,v 1.35 2000/04/26 19:03:46 chris Exp $";
 #endif
 #endif /* not lint */
 
@@ -118,6 +118,10 @@ static char rcsid[] = "$OpenBSD: ifconfig.c,v 1.34 2000/04/14 02:40:01 itojun Ex
 #include <netiso/iso_var.h>
 #include <sys/protosw.h>
 
+#ifndef INET_ONLY
+#include <net/if_vlan_var.h>
+#endif
+
 #include <ctype.h>
 #include <err.h>
 #include <errno.h>
@@ -187,6 +191,10 @@ void       setmedia __P((char *, int));
 void   setmediaopt __P((char *, int));
 void   unsetmediaopt __P((char *, int));
 void   setmediainst __P((char *, int));
+void   setvlantag __P((char *, int));
+void   setvlandev __P((char *, int));
+void   unsetvlandev __P((char *, int));
+void   vlan_status ();
 void   fixnsel __P((struct sockaddr_iso *));
 int    main __P((int, char *[]));
 
@@ -259,6 +267,9 @@ const struct        cmd {
        { "802.3",      ETHERTYPE_8023, 0,              setipxframetype },
        { "snap",       ETHERTYPE_SNAP, 0,              setipxframetype },
        { "EtherII",    ETHERTYPE_II,   0,              setipxframetype },
+       { "vlan",       NEXTARG,        0,              setvlantag },
+       { "vlandev",    NEXTARG,        0,              setvlandev },
+       { "-vlandev",   1,              0,              unsetvlandev },
 #endif /* INET_ONLY */
        { "giftunnel",  NEXTARG2,       0,              gifsettunnel } ,
        { "dstsa",      NEXTARG,        0,              dstsa } ,
@@ -965,23 +976,32 @@ setifdstaddr(addr, param)
        (*afp->af_getaddr)(addr, DSTADDR);
 }
 
+/*
+ * Note: doing an SIOCIGIFFLAGS scribbles on the union portion
+ * of the ifreq structure, which may confuse other parts of ifconfig.
+ * Make a private copy so we can avoid that.
+ */
 void
 setifflags(vname, value)
        char *vname;
        int value;
 {
-       if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0)
+       struct ifreq my_ifr;
+
+       bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq));
+
+       if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0)
                err(1, "SIOCGIFFLAGS");
-       strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
-       flags = ifr.ifr_flags;
+       strncpy(my_ifr.ifr_name, name, sizeof (my_ifr.ifr_name));
+       flags = my_ifr.ifr_flags;
 
        if (value < 0) {
                value = -value;
                flags &= ~value;
        } else
                flags |= value;
-       ifr.ifr_flags = flags;
-       if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
+       my_ifr.ifr_flags = flags;
+       if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0)
                err(1, "SIOCSIFFLAGS");
 }
 
@@ -1453,6 +1473,9 @@ status(link)
                printf(" mtu %d", mtu);
        putchar('\n');
 
+#ifndef        INET_ONLY
+       vlan_status();
+#endif
        ieee80211_status();
 
        (void) memset(&ifmr, 0, sizeof(ifmr));
@@ -2299,6 +2322,100 @@ usage()
        exit(1);
 }
 
+#ifndef INET_ONLY
+
+static int __tag = 0;
+static int __have_tag = 0;
+
+void vlan_status()
+{
+       struct vlanreq vreq;
+
+       bzero((char *)&vreq, sizeof(struct vlanreq));
+       ifr.ifr_data = (caddr_t)&vreq;
+
+       if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1)
+               return;
+
+       if (vreq.vlr_tag || (vreq.vlr_parent[0] != '\0'))
+               printf("\tvlan: %d parent interface: %s\n",
+                      vreq.vlr_tag, vreq.vlr_parent[0] == '\0' ?
+                      "<none>" : vreq.vlr_parent);
+
+       return;
+}
+
+void setvlantag(val, d)
+       char *val;
+       int d;
+{
+       u_int16_t tag;
+       struct vlanreq vreq;
+
+       __tag = tag = atoi(val);
+       __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");
+
+       return;
+}
+
+void setvlandev(val, d)
+       char *val;
+       int 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;
+}
+
+void unsetvlandev(val, d)
+       char *val;
+       int 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");
+
+       return;
+}
+
+#endif /* INET_ONLY */
+
 #ifdef INET6
 char *
 sec2str(total)