diff --git a/share/man/man4/gre.4 b/share/man/man4/gre.4 index 91c1d25669ef..e8c903b32687 100644 --- a/share/man/man4/gre.4 +++ b/share/man/man4/gre.4 @@ -75,6 +75,16 @@ GRE mode is also the default tunnel mode on Cisco routers. This is also the default mode of operation of the .Nm interfaces. +As part of the GRE mode +.Nm +also supports Cisco WCCP protocol, both version 1 and version 2. +Since there is no reliable way to distinguish between WCCP versions, it +should be configured manually using the +.Cm link2 +flag. +If the +.Cm link2 +flag is not set (default), then WCCP version 1 is selected. .It "MOBILE encapsulation (IP protocol number 55)" Datagrams are encapsulated into IP, but with a shorter encapsulation. diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c index 7eb1732c6494..aab706833353 100644 --- a/sys/net/if_gre.c +++ b/sys/net/if_gre.c @@ -178,6 +178,7 @@ gre_clone_create(ifc, unit) sc->sc_if.if_flags |= IFF_LINK0; sc->encap = NULL; sc->called = 0; + sc->wccp_ver = WCCP_V1; if_attach(&sc->sc_if); bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int32_t)); LIST_INSERT_HEAD(&gre_softc_list, sc, sc_list); @@ -407,6 +408,10 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) sc->g_proto = IPPROTO_GRE; else sc->g_proto = IPPROTO_MOBILE; + if ((ifr->ifr_flags & IFF_LINK2) != 0) + sc->wccp_ver = WCCP_V2; + else + sc->wccp_ver = WCCP_V1; goto recompute; case SIOCSIFMTU: if ((error = suser(curthread)) != 0) diff --git a/sys/net/if_gre.h b/sys/net/if_gre.h index 73fed0b89984..21fab39e6160 100644 --- a/sys/net/if_gre.h +++ b/sys/net/if_gre.h @@ -44,6 +44,16 @@ #ifdef _KERNEL #include +/* + * Version of the WCCP, need to be configured manually since + * header for version 2 is the same but IP payload is prepended + * with additional 4-bytes field. + */ +typedef enum { + WCCP_V1 = 0, + WCCP_V2 +} wccp_ver_t; + struct gre_softc { struct ifnet sc_if; LIST_ENTRY(gre_softc) sc_list; @@ -58,6 +68,8 @@ struct gre_softc { const struct encaptab *encap; /* encapsulation cookie */ int called; /* infinite recursion preventer */ + + wccp_ver_t wccp_ver; /* version of the WCCP */ }; diff --git a/sys/netinet/ip_gre.c b/sys/netinet/ip_gre.c index 1abef1622e63..ad9ed3066b62 100644 --- a/sys/netinet/ip_gre.c +++ b/sys/netinet/ip_gre.c @@ -177,9 +177,12 @@ gre_input2(struct mbuf *m ,int hlen, u_char proto) hlen += 4; switch (ntohs(gip->gi_ptype)) { /* ethertypes */ - case ETHERTYPE_IP: /* shouldn't need a schednetisr(), as */ - case WCCP_PROTOCOL_TYPE: /* we are in ip_input */ - isr = NETISR_IP; + case WCCP_PROTOCOL_TYPE: + if (sc->wccp_ver == WCCP_V2) + hlen += 4; + /* FALLTHROUGH */ + case ETHERTYPE_IP: /* shouldn't need a schednetisr(), */ + isr = NETISR_IP;/* as we are in ip_input */ break; #ifdef NETATALK case ETHERTYPE_ATALK: