--- //depot/vendor/freebsd/src/sbin/ifconfig/ifconfig.8 2007/03/30 04:42:41 +++ //depot/user/bms/netdev/sbin/ifconfig/ifconfig.8 2007/03/30 17:00:03 @@ -28,7 +28,7 @@ .\" From: @(#)ifconfig.8 8.3 (Berkeley) 1/5/94 .\" $FreeBSD: src/sbin/ifconfig/ifconfig.8,v 1.134 2007/03/29 21:30:26 thompsa Exp $ .\" -.Dd February 4, 2007 +.Dd March 28, 2007 .Dt IFCONFIG 8 .Os .Sh NAME @@ -1390,6 +1390,17 @@ .El .Pp The following parameters are specific to +.Xr gre 4 +interfaces: +.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 currently always accept GRE packets with invalid or absent keys. +.El +.Pp +The following parameters are specific to .Xr pfsync 4 interfaces: .Bl -tag -width indent --- //depot/vendor/freebsd/src/sbin/ifconfig/ifconfig.c 2007/03/24 20:40:12 +++ //depot/user/bms/netdev/sbin/ifconfig/ifconfig.c 2007/04/01 18:35:48 @@ -51,6 +51,7 @@ #include #include +#include #include #include #include @@ -717,6 +718,19 @@ } static void +setifgrekey(const char *val, int dummy __unused, int s, + const struct afswtch *afp) +{ + + strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); + + ifr.ifr_data = (caddr_t)atol(val); + 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) { @@ -830,6 +844,10 @@ strncpy(ifs.ifs_name, name, sizeof ifs.ifs_name); if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0) printf("%s", ifs.ascii); + if (ioctl(s, GREGKEY, &ifr) == 0) { + if (ifr.ifr_data != 0) + printf("\tGRE key: %08x\n", (uint32_t)ifr.ifr_data); + } close(s); return; @@ -981,6 +999,7 @@ DEF_CMD("noicmp", IFF_LINK1, setifflags), DEF_CMD_ARG("mtu", setifmtu), DEF_CMD_ARG("name", setifname), + DEF_CMD_ARG("grekey", setifgrekey), }; static __constructor void --- //depot/vendor/freebsd/src/share/man/man4/gre.4 2006/10/19 16:41:25 +++ //depot/user/bms/netdev/share/man/man4/gre.4 2007/03/27 19:08:25 @@ -36,7 +36,7 @@ .\" .\" $FreeBSD: src/share/man/man4/gre.4,v 1.7 2006/10/19 07:41:47 danger Exp $ .\" -.Dd June 9, 2002 +.Dd March 28, 2007 .Dt GRE 4 .Os .Sh NAME @@ -167,6 +167,12 @@ section below. .It Dv GREGPROTO Query operation mode. +.It Dv GRESKEY +Set the GRE key used for this tunnel instance. +A value of 0 disables the use of the key. +.It Dv GREGKEY +Get the GRE key used for this tunnel instance. +A value of 0 means no key is in use. .El .Pp Note that the IP addresses of the tunnel endpoints may be the same as the @@ -332,4 +338,9 @@ .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; +inbound packets with the key option present are treated as belonging +to this interface instance. +.Pp +RFC1701 is not fully supported, however all unsupported features have been +deprecated in RFC2784. --- //depot/vendor/freebsd/src/sys/net/if_gre.c 2006/11/06 13:43:21 +++ //depot/user/bms/netdev/sys/net/if_gre.c 2007/04/01 20:13:43 @@ -78,6 +78,7 @@ #include #include #include +#include #else #error "Huh? if_gre without inet?" #endif @@ -202,6 +203,7 @@ sc->encap = NULL; sc->called = 0; sc->wccp_ver = WCCP_V1; + sc->gre_key = 0; if_attach(GRE2IFP(sc)); bpfattach(GRE2IFP(sc), DLT_NULL, sizeof(u_int32_t)); mtx_lock(&gre_mtx); @@ -242,6 +244,7 @@ struct gre_softc *sc = ifp->if_softc; struct greip *gh; struct ip *ip; + uint16_t *csump; u_short ip_id = 0; uint8_t ip_tos = 0; u_int16_t etype = 0; @@ -270,6 +273,7 @@ gh = NULL; ip = NULL; + csump = NULL; /* BPF writes need to be handled specially. */ if (dst->sa_family == AF_UNSPEC) { @@ -381,7 +385,9 @@ error = EAFNOSUPPORT; goto end; } - M_PREPEND(m, sizeof(struct greip), M_DONTWAIT); + + /* Reserve space for GRE header (and optional headers). */ + M_PREPEND(m, GRE_HDR_SIZE(sc), M_DONTWAIT); } else { _IF_DROP(&ifp->if_snd); m_freem(m); @@ -397,9 +403,32 @@ gh = mtod(m, struct greip *); if (sc->g_proto == IPPROTO_GRE) { - /* we don't have any GRE flags for now */ - memset((void *)gh, 0, sizeof(struct greip)); + uint8_t *bp; + + bp = (uint8_t *)gh + sizeof(struct greip); + csump = (uint16_t *)bp; + + memset(gh, 0, GRE_HDR_SIZE(sc)); gh->gi_ptype = htons(etype); + gh->gi_flags = 0; + + if (sc->gre_opts & GRE_CP) + bp += sizeof(uint32_t); + + if (sc->gre_opts & GRE_KP) { + gh->gi_flags |= htons(GRE_KP); + *(uint32_t *)bp = htonl(sc->gre_key); + bp += sizeof(uint32_t); + } + + if (sc->gre_opts & GRE_SP) { + gh->gi_flags |= htons(GRE_SP); + ++sc->gre_seq; + *(uint32_t *)bp = htonl(sc->gre_seq); + bp += sizeof(uint32_t); + } + + /* XXX routing bit and field is not yet supported. */ } gh->gi_pr = sc->g_proto; @@ -412,6 +441,17 @@ ((struct ip*)gh)->ip_tos = ip_tos; ((struct ip*)gh)->ip_id = ip_id; gh->gi_len = m->m_pkthdr.len; + + /* Compute the checksum after all other GRE header fields. */ + if (sc->gre_opts & GRE_CP) { + uint16_t csum; + + gh->gi_flags |= htons(GRE_CP); + KASSERT(csump != NULL, ("%s: csump == NULL", __func__)); + *csump = 0xffff; + csum = in_cksum(m, gh->gi_len); + *csump = csum; + } } ifp->if_opackets++; @@ -718,6 +758,13 @@ si.sin_addr.s_addr = sc->g_dst.s_addr; bcopy(&si, &ifr->ifr_addr, sizeof(ifr->ifr_addr)); break; + case GRESKEY: + sc->gre_key = (uintptr_t)ifr->ifr_data; + break; + case GREGKEY: + ifr->ifr_data = (caddr_t)(uintptr_t)sc->gre_key; + break; + default: error = EINVAL; break; --- //depot/vendor/freebsd/src/sys/net/if_gre.h 2005/06/10 16:51:34 +++ //depot/user/bms/netdev/sys/net/if_gre.h 2007/04/01 20:13:43 @@ -70,6 +70,9 @@ int called; /* infinite recursion preventer */ wccp_ver_t wccp_ver; /* version of the WCCP */ + uint32_t gre_key; /* key for this GRE instance; 0 to disable. */ + uint32_t gre_seq; /* sequence number */ + uint16_t gre_opts; /* GRE options field */ }; #define GRE2IFP(sc) ((sc)->sc_ifp) @@ -117,6 +120,17 @@ #define GRE_SP 0x1000 /* Sequence Present */ #define GRE_SS 0x0800 /* Strict Source Route */ +#define GRE_OPTMASK 0xF000 /* mask for options field */ + +#define GRE_OPT_SIZE(sc) \ + (((sc)->gre_opts & GRE_CP ? sizeof(uint32_t) : 0) + \ + ((sc)->gre_opts & GRE_KP ? sizeof(uint32_t) : 0) + \ + ((sc)->gre_opts & GRE_SP ? sizeof(uint32_t) : 0) + \ + ((sc)->gre_opts & GRE_RP ? sizeof(uint32_t) : 0)) + +#define GRE_HDR_SIZE(sc) \ + sizeof(struct greip) + GRE_OPT_SIZE((sc)) + /* * CISCO uses special type for GRE tunnel created as part of WCCP * connection, while in fact those packets are just IPv4 encapsulated @@ -174,6 +188,10 @@ #define GREGADDRD _IOWR('i', 104, struct ifreq) #define GRESPROTO _IOW('i' , 105, struct ifreq) #define GREGPROTO _IOWR('i', 106, struct ifreq) +#define GREGOPTS _IOWR('i', 107, struct ifreq) +#define GRESOPTS _IOW('i', 108, struct ifreq) +#define GREGKEY _IOWR('i', 109, struct ifreq) +#define GRESKEY _IOW('i', 110, struct ifreq) #ifdef _KERNEL LIST_HEAD(gre_softc_head, gre_softc); --- //depot/vendor/freebsd/src/sys/netinet/ip_gre.c 2006/06/02 20:01:04 +++ //depot/user/bms/netdev/sys/netinet/ip_gre.c 2007/04/01 20:13:43 @@ -158,13 +158,22 @@ flags = ntohs(gip->gi_flags); /* Checksum & Offset are present */ - if ((flags & GRE_CP) | (flags & GRE_RP)) + if ((flags & GRE_CP) | (flags & GRE_RP)) { + if (sc->gre_opts & GRE_CP) { + /* XXX: compute and verify checksum */ + } hlen += 4; + } + /* We don't support routing fields (variable length) */ if (flags & GRE_RP) return (m); - if (flags & GRE_KP) + if (flags & GRE_KP) { + if (sc->gre_opts & GRE_KP) { + /* XXX: verify key in gre_lookup */ + } hlen += 4; + } if (flags & GRE_SP) hlen += 4; @@ -302,6 +311,8 @@ /* * Find the gre interface associated with our src/dst/proto set. * + * XXX: TODO: look up based on key if present also. + * * XXXRW: Need some sort of drain/refcount mechanism so that the softc * reference remains valid after it's returned from gre_lookup(). Right * now, I'm thinking it should be reference-counted with a gre_dropref()