Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 7 Sep 2009 10:15:50 +0000 (UTC)
From:      Hajimu UMEMOTO <ume@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org
Subject:   svn commit: r196918 - in stable/7: sbin/ifconfig share/man/man4 sys/net sys/netinet sys/netinet6 sys/sys
Message-ID:  <200909071015.n87AFoDx011798@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ume
Date: Mon Sep  7 10:15:50 2009
New Revision: 196918
URL: http://svn.freebsd.org/changeset/base/196918

Log:
  MFC r193664, r193796, r193815:
  Fix and add a workaround on an issue of EtherIP packet with reversed
  version field sent via gif(4)+if_bridge(4).  The EtherIP
  implementation found on FreeBSD 6.1, 6.2, 6.3, 7.0, 7.1, and 7.2 had
  an interoperability issue because it sent the incorrect EtherIP
  packets and discarded the correct ones.
  
  Approved by:	hrs

Added:
  stable/7/sbin/ifconfig/ifgif.c
     - copied unchanged from r193664, head/sbin/ifconfig/ifgif.c
Modified:
  stable/7/sbin/ifconfig/   (props changed)
  stable/7/sbin/ifconfig/Makefile
  stable/7/share/man/man4/   (props changed)
  stable/7/share/man/man4/gif.4
  stable/7/share/man/man4/if_bridge.4
  stable/7/sys/net/   (props changed)
  stable/7/sys/net/if_gif.c
  stable/7/sys/net/if_gif.h
  stable/7/sys/netinet/in_gif.c
  stable/7/sys/netinet6/in6_gif.c
  stable/7/sys/sys/priv.h

Modified: stable/7/sbin/ifconfig/Makefile
==============================================================================
--- stable/7/sbin/ifconfig/Makefile	Mon Sep  7 09:51:23 2009	(r196917)
+++ stable/7/sbin/ifconfig/Makefile	Mon Sep  7 10:15:50 2009	(r196918)
@@ -25,6 +25,7 @@ SRCS+=	ifmedia.c		# SIOC[GS]IFMEDIA supp
 SRCS+=	ifvlan.c		# SIOC[GS]ETVLAN support
 SRCS+=	ifieee80211.c		# SIOC[GS]IEEE80211 support
 SRCS+=	ifgre.c			# GRE keys etc
+SRCS+=	ifgif.c			# GIF reversed header workaround
 
 SRCS+=	ifcarp.c		# SIOC[GS]VH support
 SRCS+=	ifgroup.c		# ...

Copied: stable/7/sbin/ifconfig/ifgif.c (from r193664, head/sbin/ifconfig/ifgif.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/7/sbin/ifconfig/ifgif.c	Mon Sep  7 10:15:50 2009	(r196918, copy of r193664, head/sbin/ifconfig/ifgif.c)
@@ -0,0 +1,132 @@
+/*-
+ * Copyright (c) 2009 Hiroki Sato.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+  "$FreeBSD$";
+#endif
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_gif.h>
+#include <net/route.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+
+#include "ifconfig.h"
+
+static void	gif_status(int);
+
+static struct {
+	const char	*label;
+	u_int		mask;
+} gif_opts[] = {
+	{ "ACCEPT_REV_ETHIP_VER",	GIF_ACCEPT_REVETHIP	},
+	{ "SEND_REV_ETHIP_VER",		GIF_SEND_REVETHIP	},
+};
+
+static void
+gif_status(int s)
+{
+	int opts;
+	int nopts = 0;
+	int i;
+
+	ifr.ifr_data = (caddr_t)&opts;
+	if (ioctl(s, GIFGOPTS, &ifr) == -1)
+		return;
+
+	printf("\toptions=%d<", opts);
+	for (i=0; i < sizeof(gif_opts)/sizeof(gif_opts[0]); i++) {
+		if (opts & gif_opts[i].mask) {
+			if (nopts++)
+				printf(",");
+			printf("%s", gif_opts[i].label);
+		}
+	}
+	printf(">\n");
+}
+
+static void
+setgifopts(const char *val,
+	int d, int s, const struct afswtch *afp)
+{
+	int opts;
+
+	ifr.ifr_data = (caddr_t)&opts;
+	if (ioctl(s, GIFGOPTS, &ifr) == -1) {
+		warn("ioctl(GIFGOPTS)");
+		return;
+	}
+
+	if (d < 0)
+		opts &= ~(-d);
+	else
+		opts |= d;
+
+	if (ioctl(s, GIFSOPTS, &ifr) == -1) {
+		warn("ioctl(GIFSOPTS)");
+		return;
+	}
+}
+
+static struct cmd gif_cmds[] = {
+	DEF_CMD("accept_rev_ethip_ver",	GIF_ACCEPT_REVETHIP,	setgifopts),
+	DEF_CMD("-accept_rev_ethip_ver",-GIF_ACCEPT_REVETHIP,	setgifopts),
+	DEF_CMD("send_rev_ethip_ver",	GIF_SEND_REVETHIP,	setgifopts),
+	DEF_CMD("-send_rev_ethip_ver",	-GIF_SEND_REVETHIP,	setgifopts),
+};
+
+static struct afswtch af_gif = {
+	.af_name	= "af_gif",
+	.af_af		= AF_UNSPEC,
+	.af_other_status = gif_status,
+};
+
+static __constructor void
+gif_ctor(void)
+{
+#define	N(a)	(sizeof(a) / sizeof(a[0]))
+	int i;
+
+	for (i = 0; i < N(gif_cmds); i++)
+		cmd_register(&gif_cmds[i]);
+	af_register(&af_gif);
+#undef N
+}

Modified: stable/7/share/man/man4/gif.4
==============================================================================
--- stable/7/share/man/man4/gif.4	Mon Sep  7 09:51:23 2009	(r196917)
+++ stable/7/share/man/man4/gif.4	Mon Sep  7 10:15:50 2009	(r196918)
@@ -29,7 +29,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd April 10, 1999
+.Dd June 8, 2009
 .Dt GIF 4
 .Os
 .Sh NAME
@@ -256,3 +256,32 @@ had a multi-destination behavior, config
 .Dv IFF_LINK0
 flag.
 The behavior is obsolete and is no longer supported.
+.Pp
+On
+.Fx
+6.1, 6.2, 6.3, 7.0, 7.1, and 7.2
+the
+.Nm
+sends and receives incorrect EtherIP packets with reversed version
+field when
+.Xr if_bridge 4
+is used together.  As a workaround on this interoperability issue, the
+following two
+.Xr ifconfig 8
+flags can be used:
+.Bl -tag -width "accept_rev_ethip_ver" -offset indent
+.It accept_rev_ethip_ver
+accepts both correct EtherIP packets and ones with reversed version
+field, if enabled.  If disabled, the
+.Nm
+accepts the correct packets only.  This flag is enabled by default.
+.It send_rev_ethip_ver
+sends EtherIP packets with reversed version field intentionally, if
+enabled.  If disabled, the
+.Nm
+sends the correct packets only.  This flag is disabled by default.
+.El
+.Pp
+If interoperability with the older
+.Fx
+machines is needed, both of these two flags must be enabled.

Modified: stable/7/share/man/man4/if_bridge.4
==============================================================================
--- stable/7/share/man/man4/if_bridge.4	Mon Sep  7 09:51:23 2009	(r196917)
+++ stable/7/share/man/man4/if_bridge.4	Mon Sep  7 10:15:50 2009	(r196918)
@@ -35,7 +35,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd September 17, 2007
+.Dd June 8, 2009
 .Dt IF_BRIDGE 4
 .Os
 .Sh NAME
@@ -389,6 +389,12 @@ ifconfig gif0 tunnel 1.2.3.4 5.6.7.8 up
 ifconfig bridge0 create
 ifconfig bridge0 addm fxp0 addm gif0 up
 .Ed
+.Pp
+Note that
+.Fx
+6.1, 6.2, 6.3, 7.0, 7.1, and 7.2 have a bug in the EtherIP protocol.
+For more details and workaround, see
+.Xr gif 4 manual page.
 .Sh SEE ALSO
 .Xr gif 4 ,
 .Xr ipf 4 ,

Modified: stable/7/sys/net/if_gif.c
==============================================================================
--- stable/7/sys/net/if_gif.c	Mon Sep  7 09:51:23 2009	(r196917)
+++ stable/7/sys/net/if_gif.c	Mon Sep  7 10:15:50 2009	(r196918)
@@ -46,6 +46,7 @@
 #include <sys/time.h>
 #include <sys/sysctl.h>
 #include <sys/syslog.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/protosw.h>
 #include <sys/conf.h>
@@ -169,6 +170,7 @@ gif_clone_create(ifc, unit, params)
 	if_initname(GIF2IFP(sc), ifc->ifc_name, unit);
 
 	sc->encap_cookie4 = sc->encap_cookie6 = NULL;
+	sc->gif_options = GIF_ACCEPT_REVETHIP;
 
 	GIF2IFP(sc)->if_addrlen = 0;
 	GIF2IFP(sc)->if_mtu    = GIF_MTU;
@@ -479,6 +481,7 @@ gif_input(m, af, ifp)
 	struct ifnet *ifp;
 {
 	int isr, n;
+	struct gif_softc *sc = ifp->if_softc;
 	struct etherip_header *eip;
 	struct ether_header *eh;
 	struct ifnet *oldifp;
@@ -539,11 +542,25 @@ gif_input(m, af, ifp)
 		}
 
 		eip = mtod(m, struct etherip_header *);
- 		if (eip->eip_ver !=
-		    (ETHERIP_VERSION & ETHERIP_VER_VERS_MASK)) {
-			/* discard unknown versions */
-			m_freem(m);
-			return;
+		/* 
+		 * GIF_ACCEPT_REVETHIP (enabled by default) intentionally
+		 * accepts an EtherIP packet with revered version field in
+		 * the header.  This is a knob for backward compatibility
+		 * with FreeBSD 7.2R or prior.
+		 */
+		if (sc->gif_options & GIF_ACCEPT_REVETHIP) {
+			if (eip->eip_resvl != ETHERIP_VERSION
+			    && eip->eip_ver != ETHERIP_VERSION) {
+				/* discard unknown versions */
+				m_freem(m);
+				return;
+			}
+		} else {
+			if (eip->eip_ver != ETHERIP_VERSION) {
+				/* discard unknown versions */
+				m_freem(m);
+				return;
+			}
 		}
 		m_adj(m, sizeof(struct etherip_header));
 
@@ -598,6 +615,7 @@ gif_ioctl(ifp, cmd, data)
 	struct gif_softc *sc  = ifp->if_softc;
 	struct ifreq     *ifr = (struct ifreq*)data;
 	int error = 0, size;
+	u_int	options;
 	struct sockaddr *dst, *src;
 #ifdef	SIOCSIFMTU /* xxx */
 	u_long mtu;
@@ -832,6 +850,24 @@ gif_ioctl(ifp, cmd, data)
 		/* if_ioctl() takes care of it */
 		break;
 
+	case GIFGOPTS:
+		options = sc->gif_options;
+		error = copyout(&options, ifr->ifr_data,
+				sizeof(options));
+		break;
+
+	case GIFSOPTS:
+		if ((error = priv_check(curthread, PRIV_NET_GIF)) != 0)
+			break;
+		error = copyin(ifr->ifr_data, &options, sizeof(options));
+		if (error)
+			break;
+		if (options & ~GIF_OPTMASK)
+			error = EINVAL;
+		else
+			sc->gif_options = options;
+		break;
+
 	default:
 		error = EINVAL;
 		break;

Modified: stable/7/sys/net/if_gif.h
==============================================================================
--- stable/7/sys/net/if_gif.h	Mon Sep  7 09:51:23 2009	(r196917)
+++ stable/7/sys/net/if_gif.h	Mon Sep  7 10:15:50 2009	(r196918)
@@ -71,6 +71,7 @@ struct gif_softc {
 	const struct encaptab *encap_cookie4;
 	const struct encaptab *encap_cookie6;
 	void		*gif_netgraph;	/* ng_gif(4) netgraph node info */
+	u_int		gif_options;
 	LIST_ENTRY(gif_softc) gif_list; /* all gif's are linked */
 };
 #define	GIF2IFP(sc)	((sc)->gif_ifp)
@@ -94,12 +95,18 @@ struct gif_softc {
 #define	MTAG_GIF_CALLED	0
 
 struct etherip_header {
-	u_int8_t eip_ver;	/* version/reserved */
-	u_int8_t eip_pad;	/* required padding byte */
-};
-#define ETHERIP_VER_VERS_MASK   0x0f
-#define ETHERIP_VER_RSVD_MASK   0xf0
-#define ETHERIP_VERSION         0x03
+#if BYTE_ORDER == LITTLE_ENDIAN
+	u_int	eip_resvl:4,	/* reserved */
+		eip_ver:4;	/* version */
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+	u_int	eip_ver:4,	/* version */
+		eip_resvl:4;	/* reserved */
+#endif
+	u_int8_t eip_resvh;	/* reserved */
+} __packed;
+
+#define ETHERIP_VERSION			0x3
 /* mbuf adjust factor to force 32-bit alignment of IP header */
 #define	ETHERIP_ALIGN		2
 
@@ -114,4 +121,11 @@ int gif_encapcheck(const struct mbuf *, 
 
 #endif /* _KERNEL */
 
+#define GIFGOPTS	_IOWR('i', 150, struct ifreq)
+#define GIFSOPTS	_IOW('i', 151, struct ifreq)
+
+#define	GIF_ACCEPT_REVETHIP	0x0001
+#define	GIF_SEND_REVETHIP	0x0010
+#define	GIF_OPTMASK		(GIF_ACCEPT_REVETHIP|GIF_SEND_REVETHIP)
+
 #endif /* _NET_IF_GIF_H_ */

Modified: stable/7/sys/netinet/in_gif.c
==============================================================================
--- stable/7/sys/netinet/in_gif.c	Mon Sep  7 09:51:23 2009	(r196917)
+++ stable/7/sys/netinet/in_gif.c	Mon Sep  7 10:15:50 2009	(r196918)
@@ -144,8 +144,22 @@ in_gif_output(struct ifnet *ifp, int fam
 #endif /* INET6 */
 	case AF_LINK:
  		proto = IPPROTO_ETHERIP;
- 		eiphdr.eip_ver = ETHERIP_VERSION & ETHERIP_VER_VERS_MASK;
- 		eiphdr.eip_pad = 0;
+
+		/*
+		 * GIF_SEND_REVETHIP (disabled by default) intentionally
+		 * sends an EtherIP packet with revered version field in
+		 * the header.  This is a knob for backward compatibility
+		 * with FreeBSD 7.2R or prior.
+		 */
+		if ((sc->gif_options & GIF_SEND_REVETHIP)) {
+ 			eiphdr.eip_ver = 0;
+ 			eiphdr.eip_resvl = ETHERIP_VERSION;
+ 			eiphdr.eip_resvh = 0;
+		} else {
+ 			eiphdr.eip_ver = ETHERIP_VERSION;
+ 			eiphdr.eip_resvl = 0;
+ 			eiphdr.eip_resvh = 0;
+		}
  		/* prepend Ethernet-in-IP header */
  		M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT);
  		if (m && m->m_len < sizeof(struct etherip_header))

Modified: stable/7/sys/netinet6/in6_gif.c
==============================================================================
--- stable/7/sys/netinet6/in6_gif.c	Mon Sep  7 09:51:23 2009	(r196917)
+++ stable/7/sys/netinet6/in6_gif.c	Mon Sep  7 10:15:50 2009	(r196918)
@@ -142,8 +142,22 @@ in6_gif_output(struct ifnet *ifp,
 #endif
 	case AF_LINK:
 		proto = IPPROTO_ETHERIP;
-		eiphdr.eip_ver = ETHERIP_VERSION & ETHERIP_VER_VERS_MASK;
-		eiphdr.eip_pad = 0;
+
+		/*
+		 * GIF_SEND_REVETHIP (disabled by default) intentionally
+		 * sends an EtherIP packet with revered version field in
+		 * the header.  This is a knob for backward compatibility
+		 * with FreeBSD 7.2R or prior.
+		 */
+		if ((sc->gif_options & GIF_SEND_REVETHIP)) {
+			eiphdr.eip_ver = 0;
+			eiphdr.eip_resvl = ETHERIP_VERSION;
+			eiphdr.eip_resvh = 0;
+		} else {
+			eiphdr.eip_ver = ETHERIP_VERSION;
+			eiphdr.eip_resvl = 0;
+			eiphdr.eip_resvh = 0;
+		}
 		/* prepend Ethernet-in-IP header */
 		M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT);
 		if (m && m->m_len < sizeof(struct etherip_header))

Modified: stable/7/sys/sys/priv.h
==============================================================================
--- stable/7/sys/sys/priv.h	Mon Sep  7 09:51:23 2009	(r196917)
+++ stable/7/sys/sys/priv.h	Mon Sep  7 10:15:50 2009	(r196918)
@@ -327,6 +327,7 @@
 #define	PRIV_NET_ADDIFADDR	413	/* Add protocol addr to interface. */
 #define	PRIV_NET_DELIFADDR	414	/* Delete protocol addr on interface. */
 #define	PRIV_NET_LAGG		415	/* Administer lagg interface. */
+#define	PRIV_NET_GIF		416	/* Administer gif interface. */
 
 /*
  * 802.11-related privileges.



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