diff options
-rw-r--r-- | sbin/ifconfig/ifconfig.8 | 12 | ||||
-rw-r--r-- | sbin/ifconfig/ifconfig.c | 20 | ||||
-rw-r--r-- | share/man/man4/gre.4 | 16 | ||||
-rw-r--r-- | sys/net/if_gre.c | 47 | ||||
-rw-r--r-- | sys/net/if_gre.h | 7 |
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); |