diff options
author | hrs <hrs@FreeBSD.org> | 2009-06-07 23:00:40 +0000 |
---|---|---|
committer | hrs <hrs@FreeBSD.org> | 2009-06-07 23:00:40 +0000 |
commit | 9bf362d0cc3f533a0c7e793fd354bfabfce44de6 (patch) | |
tree | 9a067cbb66c280e9da4ac4cea8c84e204039d753 /sys/net | |
parent | 92f847edaf37d804dffd489728e6af48a60a4fbb (diff) | |
download | FreeBSD-src-9bf362d0cc3f533a0c7e793fd354bfabfce44de6.zip FreeBSD-src-9bf362d0cc3f533a0c7e793fd354bfabfce44de6.tar.gz |
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.
This change introduces the following two flags to gif(4):
accept_rev_ethip_ver: accepts both correct EtherIP packets and ones
with reversed version field, if enabled. If disabled, the gif
accepts the correct packets only. This flag is enabled by
default.
send_rev_ethip_ver: sends EtherIP packets with reversed version field
intentionally, if enabled. If disabled, the gif sends the correct
packets only. This flag is disabled by default.
These flags are stored in struct gif_softc and can be set by
ifconfig(8) on per-interface basis.
Note that this is an incompatible change of EtherIP with the older
FreeBSD releases. If you need to interoperate older FreeBSD boxes and
new versions after this commit, setting "send_rev_ethip_ver" is
needed.
Reviewed by: thompsa and rwatson
Spotted by: Shunsuke SHINOMIYA
PR: kern/125003
MFC after: 2 weeks
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/if_gif.c | 46 | ||||
-rw-r--r-- | sys/net/if_gif.h | 26 |
2 files changed, 61 insertions, 11 deletions
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c index 6405725..69e14e9 100644 --- a/sys/net/if_gif.c +++ b/sys/net/if_gif.c @@ -45,6 +45,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> @@ -198,6 +199,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; @@ -534,6 +536,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; @@ -594,11 +597,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)); @@ -653,6 +670,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; @@ -887,6 +905,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; + if ((error = copyin(&options, &sc->gif_options, + sizeof(sc->gif_options)))) { + if ((options | GIF_FULLOPTS) == GIF_FULLOPTS) + ifr->ifr_data = (caddr_t)options; + else + error = EINVAL; + } + break; + default: error = EINVAL; break; diff --git a/sys/net/if_gif.h b/sys/net/if_gif.h index d54180d..bdc9562 100644 --- a/sys/net/if_gif.h +++ b/sys/net/if_gif.h @@ -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 @@ -143,4 +150,11 @@ extern struct vnet_gif vnet_gif_0; #endif /* _KERNEL */ +#define GIFGOPTS _IOR('i', 150, struct ifreq) +#define GIFSOPTS _IOW('i', 151, struct ifreq) + +#define GIF_ACCEPT_REVETHIP 0x0001 +#define GIF_SEND_REVETHIP 0x0010 +#define GIF_FULLOPTS (GIF_ACCEPT_REVETHIP|GIF_SEND_REVETHIP) + #endif /* _NET_IF_GIF_H_ */ |