aboutsummaryrefslogtreecommitdiff
path: root/sys/net/if_gif.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net/if_gif.c')
-rw-r--r--sys/net/if_gif.c46
1 files changed, 41 insertions, 5 deletions
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c
index 64057254594f..69e14e9de495 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;