This patch provides all the #DEFINES necessary for the 802.1q. sf.net tracker: <https://sourceforge.net/tracker/?func=detail&aid=2829878&group_id=48978&atid=45 4721>
Discussed on the IRC meeting March 4, 2010 in #openvpn-discussions. <http://thread.gmane.org/gmane.network.openvpn.devel/3242> This includes an additional length check that was not in the original patch: Currently is_ipv4() only checks whether the frame is large enough for struct openvpn_ethhdr. In case of an 802.1Q packet the function now also checks whether the frame is large enough for struct openvpn_8021qhdr, which is 4 bytes larger than struct openvpn_ethhdr. Patch authored by David Sommerseth <d...@users.sourceforge.net> and Fabian Knittel <fabian.knit...@littink.de>. Co-authored-by: David Sommerseth <d...@users.sourceforge.net> Signed-off-by: Fabian Knittel <fabian.knit...@lettink.de> --- src/openvpn/errlevel.h | 2 ++ src/openvpn/options.h | 15 +++++++++++++++ src/openvpn/proto.c | 19 ++++++++++++++++--- src/openvpn/proto.h | 26 ++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 3 deletions(-) diff --git a/src/openvpn/errlevel.h b/src/openvpn/errlevel.h index da600ab..191c763 100644 --- a/src/openvpn/errlevel.h +++ b/src/openvpn/errlevel.h @@ -148,6 +148,8 @@ #define D_PF_DROPPED_BCAST LOGLEV(7, 71, M_DEBUG) /* packet filter dropped a broadcast packet */ #define D_PF_DEBUG LOGLEV(7, 72, M_DEBUG) /* packet filter debugging, must also define PF_DEBUG in pf.h */ +#define D_VLAN_DEBUG LOGLEV(7, 72, M_DEBUG) /* show VLAN tagging/untagging debug info */ + #define D_HANDSHAKE_VERBOSE LOGLEV(8, 70, M_DEBUG) /* show detailed description of each handshake */ #define D_TLS_DEBUG_MED LOGLEV(8, 70, M_DEBUG) /* limited info from tls_session routines */ #define D_INTERVAL LOGLEV(8, 70, M_DEBUG) /* show interval.h debugging info */ diff --git a/src/openvpn/options.h b/src/openvpn/options.h index 23d3992..72ee702 100644 --- a/src/openvpn/options.h +++ b/src/openvpn/options.h @@ -155,6 +155,15 @@ struct remote_list struct remote_entry *array[CONNECTION_LIST_SIZE]; }; +#ifdef ENABLE_VLAN_TAGGING +enum vlan_acceptable_frames +{ + VAF_ONLY_VLAN_TAGGED, + VAF_ONLY_UNTAGGED_OR_PRIORITY, + VAF_ALL, +}; +#endif + struct remote_host_store { # define RH_HOST_LEN 80 @@ -597,6 +606,12 @@ struct options const char *keying_material_exporter_label; int keying_material_exporter_length; #endif + +#ifdef ENABLE_VLAN_TAGGING + bool vlan_tagging; + enum vlan_acceptable_frames vlan_accept; + uint16_t vlan_pvid; +#endif }; #define streq(x, y) (!strcmp((x), (y))) diff --git a/src/openvpn/proto.c b/src/openvpn/proto.c index 7b58e6a..2921a6e 100644 --- a/src/openvpn/proto.c +++ b/src/openvpn/proto.c @@ -60,9 +60,22 @@ is_ipv_X ( int tunnel_type, struct buffer *buf, int ip_ver ) + sizeof (struct openvpn_iphdr))) return false; eh = (const struct openvpn_ethhdr *) BPTR (buf); - if (ntohs (eh->proto) != (ip_ver == 6 ? OPENVPN_ETH_P_IPV6 : OPENVPN_ETH_P_IPV4)) - return false; - offset = sizeof (struct openvpn_ethhdr); + if (ntohs (eh->proto) == OPENVPN_ETH_P_8021Q) { + const struct openvpn_8021qhdr *evh; + if (BLEN (buf) < (int)(sizeof (struct openvpn_8021qhdr) + + sizeof (struct openvpn_iphdr))) + return false; + evh = (const struct openvpn_8021qhdr *) BPTR (buf); + if (ntohs (evh->proto) != + (ip_ver == 6 ? OPENVPN_ETH_P_IPV6 : OPENVPN_ETH_P_IPV4)) + return false; + else + offset = sizeof (struct openvpn_8021qhdr); + } else if (ntohs (eh->proto) != + (ip_ver == 6 ? OPENVPN_ETH_P_IPV6 : OPENVPN_ETH_P_IPV4)) + return false; + else + offset = sizeof (struct openvpn_ethhdr); } else return false; diff --git a/src/openvpn/proto.h b/src/openvpn/proto.h index f91e787..428d10f 100644 --- a/src/openvpn/proto.h +++ b/src/openvpn/proto.h @@ -61,9 +61,29 @@ struct openvpn_ethhdr # define OPENVPN_ETH_P_IPV4 0x0800 /* IPv4 protocol */ # define OPENVPN_ETH_P_IPV6 0x86DD /* IPv6 protocol */ # define OPENVPN_ETH_P_ARP 0x0806 /* ARP protocol */ +# define OPENVPN_ETH_P_8021Q 0x8100 /* 802.1Q protocol */ uint16_t proto; /* packet type ID field */ }; +struct openvpn_8021qhdr +{ + uint8_t dest[OPENVPN_ETH_ALEN]; /* destination ethernet addr */ + uint8_t source[OPENVPN_ETH_ALEN]; /* source ethernet addr */ + + uint16_t tpid; /* 802.1Q Tag Protocol Identifier */ +# define OPENVPN_8021Q_MASK_VID htons (0x0FFF) /* mask VID out of pcp_cfi_vid */ +# define OPENVPN_8021Q_MASK_PCP htons (0xE000) /* mask PCP out of pcp_cfi_vid */ +# define OPENVPN_8021Q_MASK_CFI htons (0x1000) /* mask CFI out of pcp_cfi_vid */ + uint16_t pcp_cfi_vid; /* bit fields, see IEEE 802.1Q */ + uint16_t proto; /* contained packet type ID field */ +}; + +/* + * Size difference between a regular Ethernet II header and an Ethernet II + * header with additional IEEE 802.1Q tagging. + */ +#define SIZE_ETH_TO_8021Q_HDR (sizeof (struct openvpn_8021qhdr) - sizeof (struct openvpn_ethhdr)) + struct openvpn_arp { # define ARP_MAC_ADDR_TYPE 0x0001 uint16_t mac_addr_type; /* 0x0001 */ @@ -234,4 +254,10 @@ void ipv4_packet_size_verify (const uint8_t *data, counter_type *errors); #endif +#ifdef ENABLE_VLAN_TAGGING +# define OPENVPN_8021Q_MIN_VID 1 +# define OPENVPN_8021Q_MAX_VID 4094 + +#endif + #endif -- 2.7.1