[Openvpn-devel] [PATCH 2/9] vlan: Add global --vlan-tagging option

2010-03-31 Thread Fabian Knittel
This patch adds the new "--vlan-tagging" boolean option.  The option is valid
in server mode.  It is off by default.

The flag indicates whether openvpn should assume the tap device
to be in tagged mode, i.e. packets coming in on the device are tagged via
IEEE 802.1Q and packets going out through the device should be tagged likewise.

The option has no immediate effect yet, but will be used by later patches.
---
 options.c |   13 +
 options.h |2 ++
 2 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/options.c b/options.c
index 36b9913..506fb49 100644
--- a/options.c
+++ b/options.c
@@ -651,6 +651,8 @@ static const char usage_message[] =
   "--show-pkcs11-ids provider [cert_private] : Show PKCS#11 available ids.\n" 
   "--verb option can be added 
*BEFORE* this.\n"
 #endif /* ENABLE_PKCS11 */
+  "\n"
+  "--vlan-tagging  : Enable VLAN tagging/untagging to/from TAP device.\n"
  ;

 #endif /* !ENABLE_SMALL */
@@ -1175,6 +1177,8 @@ show_settings (const struct options *o)
   SHOW_BOOL (ifconfig_noexec);
   SHOW_BOOL (ifconfig_nowarn);

+  SHOW_BOOL (vlan_tagging);
+
 #ifdef HAVE_GETTIMEOFDAY
   SHOW_INT (shaper);
 #endif
@@ -1742,6 +1746,8 @@ options_postprocess_verify_ce (const struct options 
*options, const struct conne

if ((options->ssl_flags & SSLF_NO_NAME_REMAPPING) && script_method == 
SM_SYSTEM)
  msg (M_USAGE, "--script-security method='system' cannot be combined 
with --no-name-remapping");
+  if (options->vlan_tagging && dev != DEV_TYPE_TAP)
+   msg (M_USAGE, "--vlan-tagging only works with --dev tap");
 }
   else
 {
@@ -1788,6 +1794,8 @@ options_postprocess_verify_ce (const struct options 
*options, const struct conne
   if (options->port_share_host || options->port_share_port)
msg (M_USAGE, "--port-share requires TCP server mode (--mode server 
--proto tcp-server)");
 #endif
+  if (options->vlan_tagging)
+   msg (M_USAGE, "--vlan-tagging requires --mode server");

 }
 #endif /* P2MP_SERVER */
@@ -5730,6 +5738,11 @@ add_option (struct options *options,
   options->persist_mode = 1;
 }
 #endif
+  else if (streq (p[0], "vlan-tagging"))
+{
+  VERIFY_PERMISSION (OPT_P_GENERAL);
+  options->vlan_tagging = true;
+}
   else
 {
   if (file)
diff --git a/options.h b/options.h
index 740e18e..49fa596 100644
--- a/options.h
+++ b/options.h
@@ -509,6 +509,8 @@ struct options
   bool show_net_up;
   int route_method;
 #endif
+
+  bool vlan_tagging;
 };

 #define streq(x, y) (!strcmp((x), (y)))
-- 
1.7.0




[Openvpn-devel] [PATCH 3/9] vlan: Add per-client --vlan-tag option

2010-03-31 Thread Fabian Knittel
This patch adds the new "--vlan-tag" integer option.  The option is valid
in server mode and can be set in a client context (e.g. from the client-connect
hook).  It defaults to 0.

The value indicates which VID (VLAN identifier) to associate with a client.
The client will only receive packets which belong to the same VLAN.  Packets
going out via the tap devie will be marked as belonging to the indicated VID.

The option has no immediate effect yet, but will be used by later patches.
---
 options.c |   25 +++--
 options.h |1 +
 proto.h   |4 
 3 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/options.c b/options.c
index 506fb49..aaf92f0 100644
--- a/options.c
+++ b/options.c
@@ -1178,6 +1178,7 @@ show_settings (const struct options *o)
   SHOW_BOOL (ifconfig_nowarn);

   SHOW_BOOL (vlan_tagging);
+  SHOW_INT (vlan_tag);

 #ifdef HAVE_GETTIMEOFDAY
   SHOW_INT (shaper);
@@ -1748,6 +1749,8 @@ options_postprocess_verify_ce (const struct options 
*options, const struct conne
  msg (M_USAGE, "--script-security method='system' cannot be combined 
with --no-name-remapping");
   if (options->vlan_tagging && dev != DEV_TYPE_TAP)
msg (M_USAGE, "--vlan-tagging only works with --dev tap");
+  if (!options->vlan_tagging && options->vlan_tag)
+   msg (M_USAGE, "--vlan-tag must be used with activated --vlan-tagging");
 }
   else
 {
@@ -1794,8 +1797,8 @@ options_postprocess_verify_ce (const struct options 
*options, const struct conne
   if (options->port_share_host || options->port_share_port)
msg (M_USAGE, "--port-share requires TCP server mode (--mode server 
--proto tcp-server)");
 #endif
-  if (options->vlan_tagging)
-   msg (M_USAGE, "--vlan-tagging requires --mode server");
+  if (options->vlan_tagging || options->vlan_tag)
+   msg (M_USAGE, "--vlan-tagging/--vlan-tag requires --mode server");

 }
 #endif /* P2MP_SERVER */
@@ -5743,6 +5746,24 @@ add_option (struct options *options,
   VERIFY_PERMISSION (OPT_P_GENERAL);
   options->vlan_tagging = true;
 }
+  else if (streq (p[0], "vlan-tag"))
+{
+  VERIFY_PERMISSION (OPT_P_INSTANCE);
+  if (p[1])
+   {
+ options->vlan_tag = positive_atoi (p[1]);
+ if (options->vlan_tag < OPENVPN_8021Q_MIN_VID || options->vlan_tag > 
OPENVPN_8021Q_MAX_VID)
+   {
+ msg (msglevel, "the parameter of --vlan-tag parameters must be >= 
%d and <= %d", OPENVPN_8021Q_MIN_VID, OPENVPN_8021Q_MAX_VID);
+ goto err;
+   }
+   }
+  else
+   {
+ msg (msglevel, "error parsing --vlan-tag parameters");
+ goto err;
+   }
+}
   else
 {
   if (file)
diff --git a/options.h b/options.h
index 49fa596..f4ca502 100644
--- a/options.h
+++ b/options.h
@@ -511,6 +511,7 @@ struct options
 #endif

   bool vlan_tagging;
+  int vlan_tag;
 };

 #define streq(x, y) (!strcmp((x), (y)))
diff --git a/proto.h b/proto.h
index 628e991..f26cbc0 100644
--- a/proto.h
+++ b/proto.h
@@ -211,4 +211,8 @@ void ipv4_packet_size_verify (const uint8_t *data,
  counter_type *errors);
 #endif

+
+#define OPENVPN_8021Q_MIN_VID 1
+#define OPENVPN_8021Q_MAX_VID 0xFFFE
+
 #endif
-- 
1.7.0




[Openvpn-devel] [PATCH 4/9] vlan: Prepend and remove VLAN identifiers on outgoing and incoming frames

2010-03-31 Thread Fabian Knittel
This patch adds parsing of the IEEE 802.1Q headers for incoming and outgoing
ethernet frames.

For frames coming in from the tap interface, the 802.1Q header is parsed and
translated into a regular Ethernet II header.  Note that the Priority Code
Point (PCP) and Canonical Format Indicator (CFI) fields contained within the
802.1Q header are ignored.  Only the VLAN Identifier (VID) is used.

For frames going out over the tap interface, the Ethernet II header is
replaced with a 802.1Q-based header.  PCP and CFI are permanently set to 0.
The VID is set according to the instance's vlan_tag value (also see patch
adding the "--vlan-tag" option).
---
 multi.c |   73 +++
 multi.h |5 
 proto.h |   34 +
 3 files changed, 107 insertions(+), 5 deletions(-)

diff --git a/multi.c b/multi.c
index 342871a..c2563a0 100644
--- a/multi.c
+++ b/multi.c
@@ -2117,6 +2117,73 @@ multi_process_incoming_link (struct multi_context *m, 
struct multi_instance *ins
 }

 /*
+ * Removes the VLAN tagging of a frame and returns the frame's VID.  Frames
+ * without tagging are dropped.
+ */
+static int16_t
+remove_vlan_identifier (struct buffer *buf)
+{
+  struct openvpn_ethhdr eth;
+  struct openvpn_8021qhdr vlanhdr;
+  int16_t vid;
+
+  if (BLEN (buf) < (sizeof (struct openvpn_8021qhdr)))
+goto err;
+
+  vlanhdr = *(const struct openvpn_8021qhdr *) BPTR (buf);
+
+  if (ntohs (vlanhdr.tpid) != OPENVPN_ETH_P_8021Q)
+{
+  /* Drop untagged frames */
+  goto err;
+}
+
+  /* Ethernet II frame with 802.1Q */
+  vid = ntohs (vlan_get_vid ());
+  memcpy (, , sizeof (eth));
+  eth.proto = vlanhdr.proto;
+
+  buf_advance (buf, SIZE_ETH_TO_8021Q_HDR);
+  memcpy (BPTR (buf), , sizeof eth);
+
+  return vid;
+err:
+  /* Drop the frame. */
+  buf->len = 0;
+  return -1;
+}
+
+/*
+ * Adds VLAN tagging to a frame.  Short frames that can't be tagged are
+ * dropped.
+ */
+void
+multi_prepend_vlan_identifier (struct multi_instance *mi, struct buffer *buf)
+{
+  struct openvpn_ethhdr eth;
+  struct openvpn_8021qhdr vlanhdr;
+  uint8_t *p;
+
+  /* Frame too small or not enough head room for VLAN tag? */
+  if ((BLEN (buf) < (int) sizeof (struct openvpn_ethhdr)) ||
+  (buf_reverse_capacity (buf) < SIZE_ETH_TO_8021Q_HDR))
+{
+  /* Drop the frame. */
+  buf->len = 0;
+  return;
+}
+
+  eth = *(const struct openvpn_ethhdr *) BPTR (buf);
+  memcpy (, , sizeof eth);
+  vlanhdr.tpid = htons (OPENVPN_ETH_P_8021Q);
+  vlanhdr.proto = eth.proto;
+  vlan_set_vid (, htons (mi->context.options.vlan_tag));
+
+  ASSERT (p = buf_prepend (buf, SIZE_ETH_TO_8021Q_HDR));
+  memcpy (p, , sizeof vlanhdr);
+}
+
+/*
  * Process packets in the TUN/TAP interface -> TCP/UDP socket direction,
  * i.e. server -> client direction.
  */
@@ -2158,6 +2225,12 @@ multi_process_incoming_tun (struct multi_context *m, 
const unsigned int mpp_flag
* the appropriate multi_instance object.
*/

+  if (dev_type == DEV_TYPE_TAP && m->top.options.vlan_tagging)
+{
+ if (remove_vlan_identifier (>top.c2.buf) == -1)
+   return false;
+}
+
   mroute_flags = mroute_extract_addr_from_packet (,
  ,
 #ifdef ENABLE_PF
diff --git a/multi.h b/multi.h
index ad26c12..26b3e1a 100644
--- a/multi.h
+++ b/multi.h
@@ -405,6 +405,7 @@ multi_get_timeout (struct multi_context *m, struct timeval 
*dest)
 static inline bool
 multi_process_outgoing_tun (struct multi_context *m, const unsigned int 
mpp_flags)
 {
+  void multi_prepend_vlan_identifier (struct multi_instance *mi, struct buffer 
*buf);
   struct multi_instance *mi = m->pending;
   bool ret = true;

@@ -415,6 +416,10 @@ multi_process_outgoing_tun (struct multi_context *m, const 
unsigned int mpp_flag
  mi->context.c2.to_tun.len);
 #endif
   set_prefix (mi);
+  if (mi->context.options.vlan_tag)
+{
+  multi_prepend_vlan_identifier (mi, >context.c2.to_tun);
+}
   process_outgoing_tun (>context);
   ret = multi_process_post (m, mi, mpp_flags);
   clear_prefix ();
diff --git a/proto.h b/proto.h
index f26cbc0..671331f 100644
--- a/proto.h
+++ b/proto.h
@@ -61,20 +61,26 @@ struct openvpn_ethhdr
 # define OPENVPN_ETH_P_IPV4   0x0800  /* IPv4 protocol */
 # define OPENVPN_ETH_P_IPV6   0x86DD  /* IPv6 protocol */
 # define OPENVPN_ETH_P_ARP0x0806  /* ARP protocol */
+# define OPENVPN_ETH_P_8021Q  0x8100  /* 802.1Q protocol */
   uint16_t proto; /* packet type ID field */
 };

-# define OPENVPN_ETH_P_8021Q  0x8100  /* 802.1Q protocol */
-
 struct openvpn_8021qhdr
 {
   uint8_t dest[OPENVPN_ETH_ALEN]; /* destination ethernet addr */
   uint8_t source[OPENVPN_ETH_ALEN];   /* source ethernet addr  */

-  uint32_t tag;   /* packet 802.1Q Vlan Tag */
-  uint16_t proto; /* packet type ID field */
+  uint16_t tpid;  /* 802.1Q Tag 

[Openvpn-devel] [PATCH 8/9] vlan: add debug logging to tagging / untagging

2010-03-31 Thread Fabian Knittel
---
 multi.c |6 ++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/multi.c b/multi.c
index 822ae29..661fd98 100644
--- a/multi.c
+++ b/multi.c
@@ -2143,11 +2143,15 @@ remove_vlan_identifier (struct buffer *buf)
   if (ntohs (vlanhdr.tpid) != OPENVPN_ETH_P_8021Q)
 {
   /* Drop untagged frames */
+  msg (M_INFO, "dropping untagged ethernet frame (proto/len 0x%04x)",
+  ntohs (vlanhdr.tpid));
   goto err;
 }

   /* Ethernet II frame with 802.1Q */
   vid = ntohs (vlan_get_vid ());
+  msg (M_INFO, "untagging ethernet frame: vid: %u, wrapped proto/len: 0x%04x",
+   vid, ntohs (vlanhdr.proto));
   memcpy (, , sizeof (eth));
   eth.proto = vlanhdr.proto;

@@ -2189,6 +2193,8 @@ multi_prepend_vlan_identifier (struct multi_instance *mi, 
struct buffer *buf)

   ASSERT (p = buf_prepend (buf, SIZE_ETH_TO_8021Q_HDR));
   memcpy (p, , sizeof vlanhdr);
+
+  msg (M_INFO, "tagging frame with vid %u, type is %04x", 
mi->context.options.vlan_tag, vlanhdr.proto);
 }

 /*
-- 
1.7.0




[Openvpn-devel] [PATCH 7/9] vlan: Slightly enhance PF's protocol inspection of 802.1Q packets

2010-03-31 Thread Fabian Knittel
To allow openvpn's PF code to inspect IP packets contained within 802.1Q
packets, this patch enhances mroute_extract_addr_ether() to properly
skip over the 802.1Q header.
---
 mroute.c |   10 +-
 1 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/mroute.c b/mroute.c
index 1040b8f..4aa7bb4 100644
--- a/mroute.c
+++ b/mroute.c
@@ -205,7 +205,15 @@ mroute_extract_addr_ether (struct mroute_addr *src,
  struct buffer b = *buf;
  if (buf_advance (, sizeof (struct openvpn_ethhdr)))
{
- switch (ntohs (eth->proto))
+ uint16_t proto = ntohs (eth->proto);
+ if (proto == OPENVPN_ETH_P_8021Q)
+   {
+ const struct openvpn_8021qhdr *tag = (const struct 
openvpn_8021qhdr *) BPTR (buf);
+ proto = ntohs (tag->proto);
+ buf_advance (, SIZE_ETH_TO_8021Q_HDR);
+   }
+
+ switch (proto)
{
case OPENVPN_ETH_P_IPV4:
  ret |= (mroute_extract_addr_ipv4 (esrc, edest, ) << 
MROUTE_SEC_SHIFT);
-- 
1.7.0




[Openvpn-devel] [PATCH 6/9] vlan: Restrict broadcasts to the sender's VLAN.

2010-03-31 Thread Fabian Knittel
This patch enhances openvpn's internal packet routing to restrict broadcast
packets to destinations with a matching VID.

I.e. broadcasts from client to client or from tap interface to clients are now
filtered based on whether the client belongs to the correct VLAN id.
---
 multi.c |   15 +--
 1 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/multi.c b/multi.c
index 96644e5..822ae29 100644
--- a/multi.c
+++ b/multi.c
@@ -1759,7 +1759,8 @@ static void
 multi_bcast (struct multi_context *m,
 const struct buffer *buf,
 const struct multi_instance *sender_instance,
-const struct mroute_addr *sender_addr)
+const struct mroute_addr *sender_addr,
+int16_t vid)
 {
   struct hash_iterator hi;
   struct hash_element *he;
@@ -1804,6 +1805,8 @@ multi_bcast (struct multi_context *m,
}
}
 #endif
+ if (vid != 0 && vid != mi->context.options.vlan_tag)
+   continue;
  multi_add_mbuf (m, mi, mb);
}
}
@@ -1997,7 +2000,7 @@ multi_process_incoming_link (struct multi_context *m, 
struct multi_instance *ins
  if (mroute_flags & MROUTE_EXTRACT_MCAST)
{
  /* for now, treat multicast as broadcast */
- multi_bcast (m, >c2.to_tun, m->pending, NULL);
+ multi_bcast (m, >c2.to_tun, m->pending, NULL, 0);
}
  else /* possible client to client routing */
{
@@ -2063,7 +2066,7 @@ multi_process_incoming_link (struct multi_context *m, 
struct multi_instance *ins
{
  if (mroute_flags & 
(MROUTE_EXTRACT_BCAST|MROUTE_EXTRACT_MCAST))
{
- multi_bcast (m, >c2.to_tun, m->pending, NULL);
+ multi_bcast (m, >c2.to_tun, m->pending, NULL, 
vid);
}
  else /* try client-to-client routing */
{
@@ -2258,9 +2261,9 @@ multi_process_incoming_tun (struct multi_context *m, 
const unsigned int mpp_flag
{
  /* for now, treat multicast as broadcast */
 #ifdef ENABLE_PF
- multi_bcast (m, >top.c2.buf, NULL, e2);
+ multi_bcast (m, >top.c2.buf, NULL, e2, vid);
 #else
- multi_bcast (m, >top.c2.buf, NULL, NULL);
+ multi_bcast (m, >top.c2.buf, NULL, NULL, vid);
 #endif
}
  else
@@ -2429,7 +2432,7 @@ gremlin_flood_clients (struct multi_context *m)
ASSERT (buf_write_u8 (, get_random () & 0xFF));

   for (i = 0; i < parm.n_packets; ++i)
-   multi_bcast (m, , NULL, NULL);
+   multi_bcast (m, , NULL, NULL, 0);

   gc_free ();
 }
-- 
1.7.0




[Openvpn-devel] [PATCH 9/9] vlan: add debug logging to broadcast filter

2010-03-31 Thread Fabian Knittel
---
 multi.c |   16 +++-
 1 files changed, 15 insertions(+), 1 deletions(-)

diff --git a/multi.c b/multi.c
index 661fd98..641d464 100644
--- a/multi.c
+++ b/multi.c
@@ -1806,7 +1806,21 @@ multi_bcast (struct multi_context *m,
}
 #endif
  if (vid != 0 && vid != mi->context.options.vlan_tag)
-   continue;
+   {
+ struct gc_arena gc = gc_new ();
+ msg (M_INFO, "VLAN: addr[%s]@%d -> client[%s]@%d packet 
dropped by BCAST VLAN filter",
+ mroute_addr_print_ex (sender_addr, MAPF_SHOW_ARP, ),
+ vid, mi_prefix (mi), mi->context.options.vlan_tag);
+ gc_free ();
+ continue;
+   }
+   {
+ struct gc_arena gc = gc_new ();
+ msg (M_INFO, "BCAST: addr[%s]@%d -> client[%s]@%d",
+ mroute_addr_print_ex (sender_addr, MAPF_SHOW_ARP, ),
+ vid, mi_prefix (mi), mi->context.options.vlan_tag);
+ gc_free ();
+   }
  multi_add_mbuf (m, mi, mb);
}
}
-- 
1.7.0




[Openvpn-devel] [PATCH 5/9] vlan: Add VLAN identifier to mroute_addr for ethernet addresses

2010-03-31 Thread Fabian Knittel
This patch appends the VID to the ethernet address in mroute_addr.

By including the VID in mroute_addr, the routing space is divided by VLAN.
This means:
 - duplicate MAC addresses on different VLANs no longer conflict and
 - all unicast-traffic is constrained to whatever VLAN the traffic came
   from (i.e. cross-VLAN unicast routing is no longer possible).

(This patch doesn't take care of broadcast traffic.  Broadcast traffic across
VLANs is still be possible at this point.)
---
 mroute.c |   10 +++---
 mroute.h |8 +---
 multi.c  |   15 +++
 3 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/mroute.c b/mroute.c
index 9d8fa66..1040b8f 100644
--- a/mroute.c
+++ b/mroute.c
@@ -169,7 +169,8 @@ mroute_extract_addr_ether (struct mroute_addr *src,
   struct mroute_addr *dest,
   struct mroute_addr *esrc,
   struct mroute_addr *edest,
-  const struct buffer *buf)
+  const struct buffer *buf,
+  int16_t vid)
 {
   unsigned int ret = 0;
   if (BLEN (buf) >= (int) sizeof (struct openvpn_ethhdr))
@@ -179,15 +180,17 @@ mroute_extract_addr_ether (struct mroute_addr *src,
{
  src->type = MR_ADDR_ETHER;
  src->netbits = 0;
- src->len = 6;
+ src->len = 8;
  memcpy (src->addr, eth->source, 6);
+ memcpy (src->addr + 6, , 2);
}
   if (dest)
{
  dest->type = MR_ADDR_ETHER;
  dest->netbits = 0;
- dest->len = 6;
+ dest->len = 8;
  memcpy (dest->addr, eth->dest, 6);
+ memcpy (dest->addr + 6, , 2);

  /* ethernet broadcast/multicast packet? */
  if (is_mac_mcast_addr (eth->dest))
@@ -303,6 +306,7 @@ mroute_addr_print_ex (const struct mroute_addr *ma,
{
case MR_ADDR_ETHER:
  buf_printf (, "%s", format_hex_ex (ma->addr, 6, 0, 1, ":", gc)); 
+ buf_printf (, "@%d", *(int16_t*)(ma->addr + 6));
  break;
case MR_ADDR_IPV4:
  {
diff --git a/mroute.h b/mroute.h
index 9b9087d..ccf79ec 100644
--- a/mroute.h
+++ b/mroute.h
@@ -139,7 +139,8 @@ mroute_extract_addr_from_packet (struct mroute_addr *src,
 struct mroute_addr *esrc,
 struct mroute_addr *edest,
 const struct buffer *buf,
-int tunnel_type)
+int tunnel_type,
+int16_t bcast_domain)
 {
   unsigned int mroute_extract_addr_ipv4 (struct mroute_addr *src,
 struct mroute_addr *dest,
@@ -149,13 +150,14 @@ mroute_extract_addr_from_packet (struct mroute_addr *src,
  struct mroute_addr *dest,
  struct mroute_addr *esrc,
  struct mroute_addr *edest,
- const struct buffer *buf);
+ const struct buffer *buf,
+ int16_t vid);
   unsigned int ret = 0;
   verify_align_4 (buf);
   if (tunnel_type == DEV_TYPE_TUN)
 ret = mroute_extract_addr_ipv4 (src, dest, buf);
   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, buf, 
bcast_domain);
   return ret;
 }

diff --git a/multi.c b/multi.c
index c2563a0..96644e5 100644
--- a/multi.c
+++ b/multi.c
@@ -1975,7 +1975,8 @@ multi_process_incoming_link (struct multi_context *m, 
struct multi_instance *ins
  NULL,
  NULL,
  >c2.to_tun,
- DEV_TYPE_TUN);
+ DEV_TYPE_TUN,
+ 0);

  /* drop packet if extract failed */
  if (!(mroute_flags & MROUTE_EXTRACT_SUCCEEDED))
@@ -2033,10 +2034,13 @@ multi_process_incoming_link (struct multi_context *m, 
struct multi_instance *ins
}
  else if (TUNNEL_TYPE (m->top.c1.tuntap) == DEV_TYPE_TAP)
{
+ int16_t vid = 0;
 #ifdef ENABLE_PF
  struct mroute_addr edest;
  mroute_addr_reset ();
 #endif
+ if (m->top.options.vlan_tagging)
+   vid = c->options.vlan_tag;
  /* extract packet source and dest addresses */
  mroute_flags = mroute_extract_addr_from_packet (,
  ,
@@ -2047,7 +2051,8 @@ multi_process_incoming_link (struct multi_context 

[Openvpn-devel] [PATCH 1/9] is_ipv4(): add packet length check for 802.1Q packets

2010-03-31 Thread Fabian Knittel
This patch adds an additional length check to is_ipv4().

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.
---
 proto.c |3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/proto.c b/proto.c
index 1f582ce..64486de 100644
--- a/proto.c
+++ b/proto.c
@@ -54,6 +54,9 @@ is_ipv4 (int tunnel_type, struct buffer *buf)
return false;
   eh = (const struct openvpn_ethhdr *) BPTR (buf);
   if (ntohs (eh->proto) == OPENVPN_ETH_P_8021Q) {
+if (BLEN (buf) < (int)(sizeof (struct openvpn_8021qhdr)
+   + sizeof (struct openvpn_iphdr)))
+ return false;
 const struct openvpn_8021qhdr *evh;
 evh = (const struct openvpn_8021qhdr *) BPTR (buf);
 if (ntohs (evh->proto) != OPENVPN_ETH_P_IPV4)
-- 
1.7.0