Add support for the optional key in the GRE header.

PR:		kern/114714
Submitted by:	Cristian KLEIN
This commit is contained in:
Andrew Thompson 2008-06-20 17:26:34 +00:00
parent c14909b6e2
commit 131c55bc5b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=179894
5 changed files with 96 additions and 6 deletions

View File

@ -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:

View File

@ -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>
@ -748,6 +749,18 @@ setifmtu(const char *val, int dummy __unused, int s,
warn("ioctl (set mtu)");
}
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

View File

@ -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.

View File

@ -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;

View File

@ -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);