@@ -58,7 +58,7 @@ static inline bool
is_mac_mcast_maddr(const struct mroute_addr *addr)
{
return (addr->type & MR_ADDR_MASK) == MR_ADDR_ETHER
- && is_mac_mcast_addr(addr->eth_addr);
+ && is_mac_mcast_addr(addr->ether.addr);
}
/*
@@ -249,12 +249,15 @@ mroute_extract_addr_ip(struct mroute_addr *src, struct mroute_addr *dest,
static void
mroute_copy_ether_to_addr(struct mroute_addr *maddr,
- const uint8_t *ether_addr)
+ const uint8_t *ether_addr,
+ uint16_t vid)
{
maddr->type = MR_ADDR_ETHER;
maddr->netbits = 0;
maddr->len = OPENVPN_ETH_ALEN;
- memcpy(maddr->eth_addr, ether_addr, OPENVPN_ETH_ALEN);
+ memcpy(maddr->ether.addr, ether_addr, OPENVPN_ETH_ALEN);
+ maddr->len += sizeof(vid);
+ maddr->ether.vid = vid;
}
unsigned int
@@ -262,6 +265,7 @@ mroute_extract_addr_ether(struct mroute_addr *src,
struct mroute_addr *dest,
struct mroute_addr *esrc,
struct mroute_addr *edest,
+ uint16_t vid,
const struct buffer *buf)
{
unsigned int ret = 0;
@@ -270,11 +274,11 @@ mroute_extract_addr_ether(struct mroute_addr *src,
const struct openvpn_ethhdr *eth = (const struct openvpn_ethhdr *) BPTR(buf);
if (src)
{
- mroute_copy_ether_to_addr(src, eth->source);
+ mroute_copy_ether_to_addr(src, eth->source, vid);
}
if (dest)
{
- mroute_copy_ether_to_addr(dest, eth->dest);
+ mroute_copy_ether_to_addr(dest, eth->dest, vid);
/* ethernet broadcast/multicast packet? */
if (is_mac_mcast_addr(eth->dest))
@@ -289,18 +293,35 @@ mroute_extract_addr_ether(struct mroute_addr *src,
if (esrc || edest)
{
struct buffer b = *buf;
- if (buf_advance(&b, sizeof(struct openvpn_ethhdr)))
+ if (!buf_advance(&b, sizeof(struct openvpn_ethhdr)))
{
- switch (ntohs(eth->proto))
- {
- case OPENVPN_ETH_P_IPV4:
- ret |= (mroute_extract_addr_ip(esrc, edest, &b) << MROUTE_SEC_SHIFT);
- break;
+ return 0;
+ }
- case OPENVPN_ETH_P_ARP:
- ret |= (mroute_extract_addr_arp(esrc, edest, &b) << MROUTE_SEC_SHIFT);
- break;
+ uint16_t proto = eth->proto;
+ if (proto == htons(OPENVPN_ETH_P_8021Q))
+ {
+ if (!buf_advance(&b, SIZE_ETH_TO_8021Q_HDR))
+ {
+ /* It's an 802.1Q packet, but doesn't have a full header,
+ * so something went wrong */
+ return 0;
}
+
+ const struct openvpn_8021qhdr *tag;
+ tag = (const struct openvpn_8021qhdr *)BPTR(buf);
+ proto = tag->proto;
+ }
+
+ switch (ntohs(proto))
+ {
+ case OPENVPN_ETH_P_IPV4:
+ ret |= (mroute_extract_addr_ip(esrc, edest, &b) << MROUTE_SEC_SHIFT);
+ break;
+
+ case OPENVPN_ETH_P_ARP:
+ ret |= (mroute_extract_addr_arp(esrc, edest, &b) << MROUTE_SEC_SHIFT);
+ break;
}
}
#endif
@@ -444,8 +465,9 @@ mroute_addr_print_ex(const struct mroute_addr *ma,
switch (maddr.type & MR_ADDR_MASK)
{
case MR_ADDR_ETHER:
- buf_printf(&out, "%s", format_hex_ex(ma->eth_addr,
- sizeof(ma->eth_addr), 0, 1, ":", gc));
+ buf_printf(&out, "%s", format_hex_ex(ma->ether.addr,
+ sizeof(ma->ether.addr), 0, 1, ":", gc));
+ buf_printf(&out, "@%hu", ma->ether.vid);
break;
case MR_ADDR_IPV4:
@@ -82,7 +82,10 @@ struct mroute_addr {
* valid if MR_WITH_NETBITS is set */
union {
uint8_t raw_addr[MR_MAX_ADDR_LEN]; /* actual address */
- uint8_t eth_addr[OPENVPN_ETH_ALEN];
+ struct {
+ uint8_t addr[OPENVPN_ETH_ALEN];
+ uint16_t vid;
+ } ether;
struct {
in_addr_t addr; /* _network order_ IPv4 address */
in_port_t port; /* _network order_ TCP/UDP port */
@@ -100,7 +103,7 @@ struct mroute_addr {
/* Wrappers to support compilers that do not grok anonymous unions */
mroute_union
#define raw_addr mroute_union.raw_addr
-#define eth_addr mroute_union.eth_addr
+#define ether mroute_union.ether
#define v4 mroute_union.v4
#define v6 mroute_union.v6
#define v4mappedv6 mroute_union.v4mappedv6
@@ -178,6 +181,7 @@ unsigned int mroute_extract_addr_ether(struct mroute_addr *src,
struct mroute_addr *dest,
struct mroute_addr *esrc,
struct mroute_addr *edest,
+ uint16_t vid,
const struct buffer *buf);
/*
@@ -189,6 +193,7 @@ mroute_extract_addr_from_packet(struct mroute_addr *src,
struct mroute_addr *dest,
struct mroute_addr *esrc,
struct mroute_addr *edest,
+ uint16_t vid,
const struct buffer *buf,
int tunnel_type)
{
@@ -200,7 +205,7 @@ mroute_extract_addr_from_packet(struct mroute_addr *src,
}
else if (tunnel_type == DEV_TYPE_TAP)
{
- ret = mroute_extract_addr_ether(src, dest, esrc, edest, buf);
+ ret = mroute_extract_addr_ether(src, dest, esrc, edest, vid, buf);
}
return ret;
}
@@ -2570,6 +2570,7 @@ multi_process_incoming_link(struct multi_context *m, struct multi_instance *inst
&dest,
NULL,
NULL,
+ 0,
&c->c2.to_tun,
DEV_TYPE_TUN);
@@ -2664,6 +2665,7 @@ multi_process_incoming_link(struct multi_context *m, struct multi_instance *inst
#else
NULL,
#endif
+ 0,
&c->c2.to_tun,
DEV_TYPE_TAP);
@@ -2791,6 +2793,7 @@ multi_process_incoming_tun(struct multi_context *m, const unsigned int mpp_flags
NULL,
#endif
NULL,
+ 0,
&m->top.c2.buf,
dev_type);