Fabian Knittel wrote:
> I've attached a diff containing all changes introduced by the
> current patch-set.

Thanks for doing this. It makes review so much easier.


> +++ b/configure.ac
> @@ -212,6 +212,12 @@ AC_ARG_ENABLE(selinux,
>     [SELINUX="yes"]
>  )
>  
> +AC_ARG_ENABLE(vlan-tagging,
> +   [  --disable-vlan-tagging  Disable support for VLAN tagging/untagging],
> +   [VLAN_TAGGING="$enableval"],
> +   [VLAN_TAGGING="yes"]
> +)

Maybe explicitly mention that it's 802.1Q ?


> +dnl enable --vlan-tagging
> +if test "$VLAN_TAGGING" = "yes"; then
> +   AC_DEFINE(ENABLE_VLAN_TAGGING, 1, [Enable VLAN tagging/untagging])
> +fi

Maybe also here.


> +++ b/mroute.c
> @@ -164,12 +164,28 @@ mroute_extract_addr_ipv4 (struct mroute_addr *src,
>    return ret;
>  }
>  
> +static void mroute_copy_ether_to_addr(struct mroute_addr *maddr,
> +                                   const uint8_t *eth_addr,
> +                                   int16_t vid)
> +{
> +  maddr->type = MR_ADDR_ETHER;
> +  maddr->netbits = 0;
> +  memcpy (maddr->addr, eth_addr, 6);
> +#ifdef ENABLE_VLAN_TAGGING
> +  maddr->len = 8;
> +  memcpy (maddr->addr + 6, &vid, 2);

Does this need to consider htons() ?

Also, I have a weak preference for uint16_t, just to indicate that
negative values are never correct.


> @@ -303,6 +322,9 @@ mroute_addr_print_ex (const struct mroute_addr *ma,
>       {
>       case MR_ADDR_ETHER:
>         buf_printf (&out, "%s", format_hex_ex (ma->addr, 6, 0, 1, ":", gc)); 
> +#ifdef ENABLE_VLAN_TAGGING
> +       buf_printf (&out, "@%d", *(int16_t*)(ma->addr + 6));
> +#endif

Also here, ntohs() ?


> +++ b/multi.c
..
> @@ -1918,6 +1924,28 @@ multi_process_post (struct multi_context *m, struct 
> multi_instance *mi, const un
>    return ret;
>  }
>  
> +#ifdef ENABLE_VLAN_TAGGING
> +bool
> +buf_filter_incoming_vlan_tags (const struct buffer *buf)
> +{
> +  if (BLEN (buf) >= (int) sizeof (struct openvpn_8021qhdr))
> +    {
> +      const struct openvpn_8021qhdr *vlanhdr = (const struct 
> openvpn_8021qhdr *) BPTR (buf);
> +
> +      if (ntohs (vlanhdr->tpid) == OPENVPN_ETH_P_8021Q)
> +        {
> +       const int16_t vid = vlanhdr_get_vid(vlanhdr);
> +       if (vid != 0)
> +         {
> +           msg (D_VLAN_DEBUG, "dropping tagged incoming frame, vid: %d", 
> vid);
> +           return true;
> +         }
> +     }
> +    }
> +  return false;
> +}
> +#endif

What a horrible coding style this is!! But oh well, that's certainly
not your fault. :)

However, I really like code that checks for "break" conditions first,
and returns early, over code that nests multiple levels of
conditions, something like:

{
  struct openvpn_8021qhdr *vlanhdr;
  int16_t vid;
  if (BLEN (buf) < (int) sizeof (struct openvpn_8021qhdr))
    return false;
  vlanhdr = (const struct openvpn_8021qhdr *) BPTR (buf);
  if (ntohs (vlanhdr->tpid) != OPENVPN_ETH_P_8021Q)
    return false;
  vid = vlanhdr_get_vid(vlanhdr);
  if (0 == vid)
    return false;
  msg (D_VLAN_DEBUG, "dropping .. ");
  return true;
}

But don't let this start some kind of argument about coding style. I
have no technical complaints about the hunk above.


> @@ -2033,10 +2062,27 @@ multi_process_incoming_link (struct multi_context *m, 
> struct multi_instance *ins
>           }
>         else if (TUNNEL_TYPE (m->top.c1.tuntap) == DEV_TYPE_TAP)
>           {
> +#ifdef ENABLE_VLAN_TAGGING
> +           int16_t vid = 0;
> +#else
> +           const int16_t vid = 0;
> +#endif

I like how you use const here.


> @@ -2116,6 +2163,159 @@ multi_process_incoming_link (struct multi_context *m, 
> struct multi_instance *ins
>    return ret;
>  }
>  
> +#ifdef ENABLE_VLAN_TAGGING
> +/*
> + * For vlan_accept == VAF_ONLY_UNTAGGED_OR_PRIORITY:
> + *   If a frame is VLAN-tagged, it is dropped.  Otherwise, the global
> + *   vlan_pvid is returned as VID.

This is just a comment in the code, but maybe mention that vid=0 in a
tag does not mean that it's VLAN-tagged. Yes, _OR_PRIORITY indicates
this, but it might be nice to be super consistent also in the text.


> +remove_vlan_tag (const struct context *c, struct buffer *buf)
> +{
..
> +  /* Tagged packet. */
> +
> +  vid = ntohs (vlanhdr_get_vid (&vlanhdr));

Hmm - does ntohs() here mean that it shouldn't be done in mroute.c?


> +multi_prepend_vlan_tag (const struct context *c, struct buffer *buf)
> +{
..
> +  /* Frame too small? */
> +  if (BLEN (buf) < (int) sizeof (struct openvpn_ethhdr))
> +    goto drop;

I like forward goto for error handling very much too!


> +      /* Frame too small for header type? */
> +      if (BLEN (buf) < (int) (sizeof (struct openvpn_8021qhdr)))
> +     goto drop;

This looks like a whitespace oops?


> +      /* Not enough head room for VLAN tag? */
> +      if (buf_reverse_capacity (buf) < SIZE_ETH_TO_8021Q_HDR)
> +     goto drop;

Here too? Hmm. Am I missing something?


> @@ -2158,6 +2363,16 @@ multi_process_incoming_tun (struct multi_context *m, 
> const unsigned int mpp_flag
>         * the appropriate multi_instance object.
>         */
>  
> +#ifdef ENABLE_VLAN_TAGGING
> +      if (dev_type == DEV_TYPE_TAP && m->top.options.vlan_tagging)
> +        {
> +       if ((vid = remove_vlan_tag (&m->top, &m->top.c2.buf)) == -1)
> +         {
> +           return false;
> +         }
> +        }
> +#endif

This indent also looks off - but it may just be me not knowing the
coding style. (I hope not though, this is horrible.)


> @@ -415,6 +418,26 @@ multi_process_outgoing_tun (struct multi_context *m, 
> const unsigned int mpp_flag
..
> +      if (m->top.options.vlan_pvid != mi->context.options.vlan_pvid)
> +     {

Again with the weird indenting.


> +++ b/openvpn.8
..
> +Incoming untagged packets from clients are assigned with the client's Port
> +VLAN Identifier (PVID) as their VID. In
> +.B untagged
> +mode, incoming untagged packets on the tap device are associated with the
> +global
> +.B \-\-vlan\-pvid
> +setting. In
> +.B tagged
> +mode, any incoming untagged packets are dropped.

Would it be desirable to support both tagged and untagged at once?

On Linux maybe there could be a workaround involving a bridge or so.


> +++ b/options.c
> @@ -1742,6 +1774,17 @@ 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");
> +#ifdef ENABLE_VLAN_TAGGING
> +      if (options->vlan_tagging && dev != DEV_TYPE_TAP)
> +     msg (M_USAGE, "--vlan-tagging must be used with --dev tap");
> +      if (!options->vlan_tagging)
> +     {
> +       if (options->vlan_accept != defaults.vlan_accept)
> +         msg (M_USAGE, "--vlan-accept requires --vlan-tagging");
> +       if (options->vlan_pvid != defaults.vlan_pvid)
> +         msg (M_USAGE, "--vlan-pvid requires --vlan-tagging");
> +     }
> +#endif

Funky indent again.


> @@ -1788,7 +1831,10 @@ 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
> -
> +#ifdef ENABLE_VLAN_TAGGING
> +      if (options->vlan_tagging)
> +     msg (M_USAGE, "--vlan-tagging requires --mode server");
> +#endif

Here too.


> @@ -5730,6 +5776,45 @@ add_option (struct options *options,
..
> +  else if (streq (p[0], "vlan-accept") && p[1])
> +    {
> +      VERIFY_PERMISSION (OPT_P_GENERAL);
> +      if (streq (p[1], "tagged"))
> +     {
> +       options->vlan_accept = VAF_ONLY_VLAN_TAGGED;
> +     }
> +      else if (streq (p[1], "untagged"))
> +     {
> +       options->vlan_accept = VAF_ONLY_UNTAGGED_OR_PRIORITY;
> +     }
> +      else if (streq (p[1], "all"))
> +     {
> +       options->vlan_accept = VAF_ALL;
> +     }
> +      else
> +     {
> +       msg (msglevel, "--vlan-accept must be 'tagged', 'untagged' or 'all'");
> +       goto err;
> +     }
> +    }
> +  else if (streq (p[0], "vlan-pvid") && p[1])
> +    {
> +      VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_INSTANCE);
> +      options->vlan_pvid = positive_atoi (p[1]);
> +      if (options->vlan_pvid < OPENVPN_8021Q_MIN_VID ||
> +       options->vlan_pvid > OPENVPN_8021Q_MAX_VID)
> +     {
> +       msg (msglevel, "the parameter of --vlan-pvid parameters must be >= %d 
> and <= %d", OPENVPN_8021Q_MIN_VID, OPENVPN_8021Q_MAX_VID);
> +       goto err;
> +     }
> +    }

This indent stuff is really killing me. I find it extremely hard to
read. :)


> +++ 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)

Indenting here too. And I think the if needs to go after the struct
to compile very broadly, even if C99 permits variables like this.


> +++ b/proto.h
..
> +/*
> + * Retrieve the Priority Code Point (PCP) from the IEEE 802.1Q header.
> + */
> +static inline int
> +vlanhdr_get_pcp (const struct openvpn_8021qhdr *hdr)
> +{
> +  return hdr->pcp_cfi_vid & OPENVPN_8021Q_MASK_PCP;
> +}

What about byte order for these guys? Is it OK to use host byte
order?


Thank you so much for your work on this!


//Peter

Reply via email to