summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sbin/ifconfig/ifconfig.812
-rw-r--r--sbin/ifconfig/ifconfig.c20
-rw-r--r--share/man/man4/gre.416
-rw-r--r--sys/net/if_gre.c47
-rw-r--r--sys/net/if_gre.h7
5 files changed, 96 insertions, 6 deletions
diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8
index 22adfaa..b7302fc 100644
--- a/sbin/ifconfig/ifconfig.8
+++ b/sbin/ifconfig/ifconfig.8
@@ -28,7 +28,7 @@
.\" From: @(#)ifconfig.8 8.3 (Berkeley) 1/5/94
.\" $FreeBSD$
.\"
-.Dd April 11, 2008
+.Dd June 20, 2008
.Dt IFCONFIG 8
.Os
.Sh NAME
@@ -2011,6 +2011,16 @@ Another name for the
parameter.
.El
.Pp
+The following parameters are specific to GRE tunnel interfaces,
+.Xr gre 4 :
+.Bl -tag -width indent
+.It Cm grekey Ar key
+Configure the GRE key to be used for outgoing packets.
+Note that
+.Xr gre 4 will always accept GRE packets with invalid or absent keys.
+This command will result in a four byte MTU reduction on the interface.
+.El
+.Pp
The following parameters are specific to
.Xr pfsync 4
interfaces:
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
index 4819679..6f0dd0e 100644
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -51,6 +51,7 @@ static const char rcsid[] =
#include <net/ethernet.h>
#include <net/if.h>
+#include <net/if_gre.h>
#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/if_types.h>
@@ -749,6 +750,18 @@ setifmtu(const char *val, int dummy __unused, int s,
}
static void
+setifgrekey(const char *val, int dummy __unused, int s,
+ const struct afswtch *afp)
+{
+ uint32_t grekey = atol(val);
+
+ strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
+ ifr.ifr_data = (caddr_t)&grekey;
+ if (ioctl(s, GRESKEY, (caddr_t)&ifr) < 0)
+ warn("ioctl (set grekey)");
+}
+
+static void
setifname(const char *val, int dummy __unused, int s,
const struct afswtch *afp)
{
@@ -863,6 +876,12 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0)
printf("%s", ifs.ascii);
+ int grekey = 0;
+ ifr.ifr_data = (caddr_t)&grekey;
+ if (ioctl(s, GREGKEY, &ifr) == 0)
+ if (grekey != 0)
+ printf("\tgrekey: %d\n", grekey);
+
close(s);
return;
}
@@ -1034,6 +1053,7 @@ static struct cmd basic_cmds[] = {
DEF_CMD("noicmp", IFF_LINK1, setifflags),
DEF_CMD_ARG("mtu", setifmtu),
DEF_CMD_ARG("name", setifname),
+ DEF_CMD_ARG("grekey", setifgrekey),
};
static __constructor void
diff --git a/share/man/man4/gre.4 b/share/man/man4/gre.4
index 76eed1a..9052eea 100644
--- a/share/man/man4/gre.4
+++ b/share/man/man4/gre.4
@@ -36,7 +36,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 9, 2002
+.Dd June 20, 2008
.Dt GRE 4
.Os
.Sh NAME
@@ -167,6 +167,12 @@ internal route search for the remote tunnel endpoint, see the
section below.
.It Dv GREGPROTO
Query operation mode.
+.It Dv GRESKEY
+Set the GRE key used for outgoing packets.
+A value of 0 disables the key option.
+.It Dv GREGKEY
+Get the GRE key currently used for outgoing packets.
+0 means no outgoing key.
.El
.Pp
Note that the IP addresses of the tunnel endpoints may be the same as the
@@ -264,6 +270,7 @@ section below) may (and probably should) be set.
The MTU of
.Nm
interfaces is set to 1476 by default, to match the value used by Cisco routers.
+If grekey is set this is lowered to 1472.
This may not be an optimal value, depending on the link between the two tunnel
endpoints.
It can be adjusted via
@@ -332,4 +339,9 @@ over the
.Nm
interface itself.
.Pp
-The GRE RFCs are not yet fully implemented (no GRE options).
+The current implementation uses the key only for outgoing packets.
+Incomming packets with a different key or without a key will be treated as if they
+would belong to this interface.
+.Pp
+RFC1701 is not fully supported, however all unsupported features have been
+deprecated in RFC2784.
diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c
index 9045f06..ff39b1d 100644
--- a/sys/net/if_gre.c
+++ b/sys/net/if_gre.c
@@ -204,6 +204,7 @@ gre_clone_create(ifc, unit, params)
sc->called = 0;
sc->gre_fibnum = curthread->td_proc->p_fibnum;
sc->wccp_ver = WCCP_V1;
+ sc->key = 0;
if_attach(GRE2IFP(sc));
bpfattach(GRE2IFP(sc), DLT_NULL, sizeof(u_int32_t));
mtx_lock(&gre_mtx);
@@ -383,7 +384,12 @@ gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
error = EAFNOSUPPORT;
goto end;
}
- M_PREPEND(m, sizeof(struct greip), M_DONTWAIT);
+
+ /* Reserve space for GRE header + optional GRE key */
+ int hdrlen = sizeof(struct greip);
+ if (sc->key)
+ hdrlen += sizeof(uint32_t);
+ M_PREPEND(m, hdrlen, M_DONTWAIT);
} else {
_IF_DROP(&ifp->if_snd);
m_freem(m);
@@ -401,9 +407,18 @@ gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
gh = mtod(m, struct greip *);
if (sc->g_proto == IPPROTO_GRE) {
- /* we don't have any GRE flags for now */
+ uint32_t *options = gh->gi_options;
+
memset((void *)gh, 0, sizeof(struct greip));
gh->gi_ptype = htons(etype);
+ gh->gi_flags = 0;
+
+ /* Add key option */
+ if (sc->key)
+ {
+ gh->gi_flags |= htons(GRE_KP);
+ *(options++) = htonl(sc->key);
+ }
}
gh->gi_pr = sc->g_proto;
@@ -444,10 +459,12 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
int s;
struct sockaddr_in si;
struct sockaddr *sa = NULL;
- int error;
+ int error, adj;
struct sockaddr_in sp, sm, dp, dm;
+ uint32_t key;
error = 0;
+ adj = 0;
s = splnet();
switch (cmd) {
@@ -722,6 +739,30 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
si.sin_addr.s_addr = sc->g_dst.s_addr;
bcopy(&si, &ifr->ifr_addr, sizeof(ifr->ifr_addr));
break;
+ case GRESKEY:
+ error = priv_check(curthread, PRIV_NET_GRE);
+ if (error)
+ break;
+ error = copyin(ifr->ifr_data, &key, sizeof(key));
+ if (error)
+ break;
+ /* adjust MTU for option header */
+ if (key == 0 && sc->key != 0) /* clear */
+ adj += sizeof(key);
+ else if (key != 0 && sc->key == 0) /* set */
+ adj -= sizeof(key);
+
+ if (ifp->if_mtu + adj < 576) {
+ error = EINVAL;
+ break;
+ }
+ ifp->if_mtu += adj;
+ sc->key = key;
+ break;
+ case GREGKEY:
+ error = copyout(&sc->key, ifr->ifr_data, sizeof(sc->key));
+ break;
+
default:
error = EINVAL;
break;
diff --git a/sys/net/if_gre.h b/sys/net/if_gre.h
index 3c34bec..186d4cc 100644
--- a/sys/net/if_gre.h
+++ b/sys/net/if_gre.h
@@ -70,6 +70,9 @@ struct gre_softc {
int called; /* infinite recursion preventer */
+ uint32_t key; /* key included in outgoing GRE packets */
+ /* zero means none */
+
wccp_ver_t wccp_ver; /* version of the WCCP */
};
#define GRE2IFP(sc) ((sc)->sc_ifp)
@@ -79,6 +82,7 @@ struct gre_h {
u_int16_t flags; /* GRE flags */
u_int16_t ptype; /* protocol type of payload typically
Ether protocol type*/
+ uint32_t options[0]; /* optional options */
/*
* from here on: fields are optional, presence indicated by flags
*
@@ -111,6 +115,7 @@ struct greip {
#define gi_dst gi_i.ip_dst
#define gi_ptype gi_g.ptype
#define gi_flags gi_g.flags
+#define gi_options gi_g.options
#define GRE_CP 0x8000 /* Checksum Present */
#define GRE_RP 0x4000 /* Routing Present */
@@ -175,6 +180,8 @@ struct mobip_h {
#define GREGADDRD _IOWR('i', 104, struct ifreq)
#define GRESPROTO _IOW('i' , 105, struct ifreq)
#define GREGPROTO _IOWR('i', 106, struct ifreq)
+#define GREGKEY _IOWR('i', 107, struct ifreq)
+#define GRESKEY _IOW('i', 108, struct ifreq)
#ifdef _KERNEL
LIST_HEAD(gre_softc_head, gre_softc);
OpenPOWER on IntegriCloud