-.\" $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
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 ,
.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
-/* $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 $ */
/*
#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 */
#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>
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 *[]));
{ "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 } ,
(*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");
}
printf(" mtu %d", mtu);
putchar('\n');
+#ifndef INET_ONLY
+ vlan_status();
+#endif
ieee80211_status();
(void) memset(&ifmr, 0, sizeof(ifmr));
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)