[Openvpn-devel,2/9] VLAN: add basic VLAN tagging support

Message ID 20191009143422.9419-3-a@unstable.cc
State Accepted
Headers show
Series support VLANs in TAP mode | expand

Commit Message

Antonio Quartulli Oct. 9, 2019, 3:34 a.m. UTC
This patch introduces basic support for VLAN tagging on the server side.
The introduced functionality consists in allowing the user to assign
a VID to the server TAP device and a VID to each client port.

Client specific VID are assigned by means of files in CCD (like for
other client specific settings).

Once VIDs have been assigned, everything works as before, except that
communications are allowed only between hosts having the same VID.

With this patch all broadcast and client-to-client traffic is yet
separated by VLAN: only client-to-server unicasts are affected.

Signed-off-by: Fabian Knittel <fabian.knittel@lettink.de>
Signed-off-by: Antonio Quartulli <a@unstable.cc>
---
 src/openvpn/Makefile.am |   1 +
 src/openvpn/errlevel.h  |   2 +
 src/openvpn/multi.c     |  27 +++++++---
 src/openvpn/multi.h     |   2 +
 src/openvpn/options.c   |  54 ++++++++++++++++++++
 src/openvpn/options.h   |   9 ++++
 src/openvpn/proto.h     |  25 +++++++++
 src/openvpn/vlan.c      | 110 ++++++++++++++++++++++++++++++++++++++++
 src/openvpn/vlan.h      |  44 ++++++++++++++++
 9 files changed, 268 insertions(+), 6 deletions(-)
 create mode 100644 src/openvpn/vlan.c
 create mode 100644 src/openvpn/vlan.h

Comments

Gert Doering Nov. 6, 2019, 9:41 a.m. UTC | #1
Acked-by: Gert Doering <gert@greenie.muc.de>

Stared at the code (twice now), run t_client and t_server tests.

This patch does not really *do* much yet, but it lays the groundwork
for future work - the "broadcast only to clients in the same vlan"
part is there, but it's always called with "0" (= all clients).  As
far as I can see, the only notable behavioural change we have so far 
is "if a client is assigned a pvid (!= the global pvid), it will not 
be able to communicate with the TAP interface" (check in vlan.c, 
vlan_process_outgoing_tun()), but client-to-client is still allowed,
and there is no per-vlan MAC learning yet either.

(Most notably, it only adds options and code relevant for TAP mode)

Your patch has been applied to the master branch.

commit 99f28081477ca325a14b13c38abec2c9b619eb01
Author: Antonio Quartulli
Date:   Wed Oct 9 16:34:15 2019 +0200

     VLAN: add basic VLAN tagging support

     Signed-off-by: Fabian Knittel <fabian.knittel@lettink.de>
     Signed-off-by: Antonio Quartulli <a@unstable.cc>
     Acked-by: Gert Doering <gert@greenie.muc.de>
     Message-Id: <20191009143422.9419-3-a@unstable.cc>
     URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg18924.html
     Signed-off-by: Gert Doering <gert@greenie.muc.de>


--
kind regards,

Gert Doering
Lev Stipakov Nov. 7, 2019, 1:18 a.m. UTC | #2
This broke (again) Visual Studio build:

> error LNK2019: unresolved external symbol vlan_process_outgoing_tun
referenced in function multi_process_outgoing_tun

Can we please ack and merge this patch
https://patchwork.openvpn.net/patch/868/ to catch these things earlier?

ke 6. marrask. 2019 klo 22.42 Gert Doering (gert@greenie.muc.de) kirjoitti:

> Acked-by: Gert Doering <gert@greenie.muc.de>
>
> Stared at the code (twice now), run t_client and t_server tests.
>
> This patch does not really *do* much yet, but it lays the groundwork
> for future work - the "broadcast only to clients in the same vlan"
> part is there, but it's always called with "0" (= all clients).  As
> far as I can see, the only notable behavioural change we have so far
> is "if a client is assigned a pvid (!= the global pvid), it will not
> be able to communicate with the TAP interface" (check in vlan.c,
> vlan_process_outgoing_tun()), but client-to-client is still allowed,
> and there is no per-vlan MAC learning yet either.
>
> (Most notably, it only adds options and code relevant for TAP mode)
>
> Your patch has been applied to the master branch.
>
> commit 99f28081477ca325a14b13c38abec2c9b619eb01
> Author: Antonio Quartulli
> Date:   Wed Oct 9 16:34:15 2019 +0200
>
>      VLAN: add basic VLAN tagging support
>
>      Signed-off-by: Fabian Knittel <fabian.knittel@lettink.de>
>      Signed-off-by: Antonio Quartulli <a@unstable.cc>
>      Acked-by: Gert Doering <gert@greenie.muc.de>
>      Message-Id: <20191009143422.9419-3-a@unstable.cc>
>      URL:
> https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg18924.html
>      Signed-off-by: Gert Doering <gert@greenie.muc.de>
>
>
> --
> kind regards,
>
> Gert Doering
>
>
>
> _______________________________________________
> Openvpn-devel mailing list
> Openvpn-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/openvpn-devel
>
Gert Doering Nov. 7, 2019, 1:27 a.m. UTC | #3
Hi,

On Thu, Nov 07, 2019 at 02:18:25PM +0200, Lev Stipakov wrote:
> This broke (again) Visual Studio build:
> 
> > error LNK2019: unresolved external symbol vlan_process_outgoing_tun
> referenced in function multi_process_outgoing_tun

Can you please send a patch that adds vlan.c to the list of source code
modules to be compiled and linked?

> Can we please ack and merge this patch
> https://patchwork.openvpn.net/patch/868/ to catch these things earlier?

I'm a bit unhappy with that one, as it changes behaviour for all non-windows
builds (including all the openssl build output even if it succeeds).

Besides this, we need to fix this whole MSVC mess - all other platforms
are just done with "add new source file to the Makefile.ac" and done
(including mingw builds), and then MSVC is broken again, and this will
happen again and again.  

Is there no reasonable way to build these project files from Makefile.ac?

gert
Lev Stipakov Nov. 7, 2019, 1:42 a.m. UTC | #4
Hi,


> I'm a bit unhappy with that one, as it changes behaviour for all
> non-windows
> builds (including all the openssl build output even if it succeeds).
>

The only place it changes behavior is this

 install:
   - if [ ! -z "${CHOST}" ]; then unset CC; fi
-  - .travis/build-deps.sh > build-deps.log 2>&1 || (cat build-deps.log &&
exit 1)
+  - .travis/build-deps.sh

I don't see it as an issue to print output when building dependencies. The
reason why
it is done is that travis aborts build if there is no output for more than
10 minutes.


> Besides this, we need to fix this whole MSVC mess - all other platforms
> are just done with "add new source file to the Makefile.ac" and done
> (including mingw builds), and then MSVC is broken again, and this will
> happen again and again.


> Is there no reasonable way to build these project files from Makefile.ac?
>

I see no reasonable way. Selva, Simon - opinions?

We could probably have a templatized project file and script which inserts
source files to there
based on content of Makefile.ac, but I don't like it. I consider necessity
of modifying VS project
a lesser evil.

(you open it and it just works)

-Lev
<div dir="ltr"><div dir="ltr">Hi,</div><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I&#39;m a bit unhappy with that one, as it changes behaviour for all non-windows<br>
builds (including all the openssl build output even if it succeeds).<br></blockquote><div><br></div><div>The only place it changes behavior is this</div><div><br></div> install:<br>   - if [ ! -z &quot;${CHOST}&quot; ]; then unset CC; fi<br>-  - .travis/build-deps.sh &gt; build-deps.log 2&gt;&amp;1 || (cat build-deps.log &amp;&amp; exit 1)<br><div>+  - .travis/build-deps.sh</div><div><br></div><div>I don&#39;t see it as an issue to print output when building dependencies. The reason why</div><div>it is done is that travis aborts build if there is no output for more than 10 minutes. </div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Besides this, we need to fix this whole MSVC mess - all other platforms<br>
are just done with &quot;add new source file to the Makefile.ac&quot; and done<br>
(including mingw builds), and then MSVC is broken again, and this will<br>
happen again and again.   </blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
Is there no reasonable way to build these project files from Makefile.ac?<br></blockquote><div><br></div><div>I see no reasonable way. Selva, Simon - opinions?</div><div><br></div><div>We could probably have a templatized project file and script which inserts source files to there</div><div>based on content of Makefile.ac, but I don&#39;t like it. I consider necessity of modifying VS project</div><div>a lesser evil. </div><div><br></div><div>(you open it and it just works)</div><div> </div></div><div dir="ltr" class="gmail_signature">-Lev</div></div>
Gert Doering Nov. 7, 2019, 1:57 a.m. UTC | #5
Hi,

On Thu, Nov 07, 2019 at 02:42:17PM +0200, Lev Stipakov wrote:
> > I'm a bit unhappy with that one, as it changes behaviour for all
> > non-windows
> > builds (including all the openssl build output even if it succeeds).
> 
> The only place it changes behavior is this
> 
>  install:
>    - if [ ! -z "${CHOST}" ]; then unset CC; fi
> -  - .travis/build-deps.sh > build-deps.log 2>&1 || (cat build-deps.log &&
> exit 1)
> +  - .travis/build-deps.sh
> 
> I don't see it as an issue to print output when building dependencies. The
> reason why
> it is done is that travis aborts build if there is no output for more than
> 10 minutes.

It's lots of text that is totally uninteresting if it succeeds, but that
you need to scroll over when looking for the reason why a build fails -
which is the reason why it is the way it is today.

[..]
> We could probably have a templatized project file and script which inserts
> source files to there
> based on content of Makefile.ac, but I don't like it. I consider necessity
> of modifying VS project a lesser evil.
> 
> (you open it and it just works)

I'm not taking responsibility for not breaking MSVC builds.  This is a
world alien to me - if you want me to not break things, it needs to be
"without fiddling XML files".

If you volunteer to update MSVC every time we add or change a source file,
I'm happy to send you a HEADS UP notice.  But I am not doing it, and I will
not request it from any contributor who is not using windows.

gert
Simon Rozman Nov. 7, 2019, 2:05 a.m. UTC | #6
We could introduce a master.c file which would include:



#include "argv.c"

#include "auth_token.c"

#include "base64.c"

#include "block_dns.c"

#include "buffer.c"

.

.

.

#include "status.c"

#include "tls_crypt.c"

#include "tun.c"

#include "win32.c"



And then have Makefile.ac and MSVC project files compile the master.c only.



Best regards,

Simon





Besides this, we need to fix this whole MSVC mess - all other platforms
are just done with "add new source file to the Makefile.ac" and done
(including mingw builds), and then MSVC is broken again, and this will
happen again and again.


Is there no reasonable way to build these project files from Makefile.ac?



I see no reasonable way. Selva, Simon - opinions?



We could probably have a templatized project file and script which inserts 
source files to there

based on content of Makefile.ac, but I don't like it. I consider necessity of 
modifying VS project

a lesser evil.



(you open it and it just works)



-Lev
<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=utf-8"><meta name=Generator content="Microsoft Word 15 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
	{font-family:"Cambria Math";
	panose-1:0 0 0 0 0 0 0 0 0 0;}
@font-face
	{font-family:Calibri;
	panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
	{margin:0cm;
	margin-bottom:.0001pt;
	font-size:12.0pt;
	font-family:"Times New Roman",serif;}
a:link, span.MsoHyperlink
	{mso-style-priority:99;
	color:#0563C1;
	text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
	{mso-style-priority:99;
	color:#954F72;
	text-decoration:underline;}
span.EmailStyle17
	{mso-style-type:personal-reply;
	font-family:"Calibri",sans-serif;
	color:#1F497D;}
.MsoChpDefault
	{mso-style-type:export-only;
	font-family:"Calibri",sans-serif;
	mso-fareast-language:EN-US;}
@page WordSection1
	{size:612.0pt 792.0pt;
	margin:70.85pt 70.85pt 70.85pt 70.85pt;}
div.WordSection1
	{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]--></head><body lang=SL link="#0563C1" vlink="#954F72"><div class=WordSection1><p class=MsoNormal><a name="_MailEndCompose"><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>We could introduce a master.c file which would include:<o:p></o:p></span></a></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'><o:p>&nbsp;</o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>#include &quot;argv.c&quot;<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>#include &quot;auth_token.c&quot;<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>#include &quot;base64.c&quot;<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>#include &quot;block_dns.c&quot;<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>#include &quot;buffer.c&quot;<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>.<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>.<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>.<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>#include &quot;status.c&quot;<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>#include &quot;tls_crypt.c&quot;<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>#include &quot;tun.c&quot;<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>#include &quot;win32.c&quot;<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'><o:p>&nbsp;</o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>And then have Makefile.ac and MSVC project files compile the master.c only.<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'><o:p>&nbsp;</o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D'>Best regards,<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D'>Simon<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'><o:p>&nbsp;</o:p></span></p><div><div><div><p class=MsoNormal><span lang=EN-GB>&nbsp;<o:p></o:p></span></p></div><blockquote style='border:none;border-left:solid #CCCCCC 1.0pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-right:0cm'><p class=MsoNormal><span lang=EN-GB>Besides this, we need to fix this whole MSVC mess - all other platforms<br>are just done with &quot;add new source file to the Makefile.ac&quot; and done<br>(including mingw builds), and then MSVC is broken again, and this will<br>happen again and again.&nbsp; &nbsp;<o:p></o:p></span></p></blockquote><blockquote style='border:none;border-left:solid #CCCCCC 1.0pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-right:0cm'><p class=MsoNormal><span lang=EN-GB><br>Is there no reasonable way to build these project files from Makefile.ac?<o:p></o:p></span></p></blockquote><div><p class=MsoNormal><span lang=EN-GB><o:p>&nbsp;</o:p></span></p></div><div><p class=MsoNormal><span lang=EN-GB>I see no reasonable way. Selva, Simon - opinions?<o:p></o:p></span></p></div><div><p class=MsoNormal><span lang=EN-GB><o:p>&nbsp;</o:p></span></p></div><div><p class=MsoNormal><span lang=EN-GB>We could probably have a templatized project file and script which inserts source files to there<o:p></o:p></span></p></div><div><p class=MsoNormal><span lang=EN-GB>based on content of Makefile.ac, but I don't like it. I consider necessity of modifying VS project<o:p></o:p></span></p></div><div><p class=MsoNormal><span lang=EN-GB>a lesser evil.&nbsp;<o:p></o:p></span></p></div><div><p class=MsoNormal><span lang=EN-GB><o:p>&nbsp;</o:p></span></p></div><div><p class=MsoNormal><span lang=EN-GB>(you open it and it just works)<o:p></o:p></span></p></div><div><p class=MsoNormal><span lang=EN-GB>&nbsp;<o:p></o:p></span></p></div></div><div><p class=MsoNormal><span lang=EN-GB>-Lev<o:p></o:p></span></p></div></div></div></body></html>
tincanteksup Nov. 7, 2019, 2:32 a.m. UTC | #7
Hi,

On 07/11/2019 12:42, Lev Stipakov wrote:
> Hi,
> 
> 
>> I'm a bit unhappy with that one, as it changes behaviour for all
>> non-windows
>> builds (including all the openssl build output even if it succeeds).
>>
> 
> The only place it changes behavior is this
> 
>   install:
>     - if [ ! -z "${CHOST}" ]; then unset CC; fi
> -  - .travis/build-deps.sh > build-deps.log 2>&1 || (cat build-deps.log &&
> exit 1)
> +  - .travis/build-deps.sh
> 
> I don't see it as an issue to print output when building dependencies. The
> reason why
> it is done is that travis aborts build if there is no output for more than
> 10 minutes.
> 

Can travis be instructed to wait longer ?
Simon Rozman Nov. 7, 2019, 2:36 a.m. UTC | #8
I revoke this “master.c” idea. It makes incremental compiling ridiculously slow. It might work for production builds, but definitely not for development.

 

Best regards,

Simon

 

From: Simon Rozman [mailto:simon@rozman.si] 
Sent: Thursday, November 7, 2019 2:06 PM
To: 'Lev Stipakov' <lstipakov@gmail.com>; 'Gert Doering' <gert@greenie.muc.de>
Cc: 'Antonio Quartulli' <a@unstable.cc>; 'openvpn-devel' <openvpn-devel@lists.sourceforge.net>
Subject: Re: [Openvpn-devel] [PATCH applied] Re: VLAN: add basic VLAN tagging support

 

We could introduce a master.c file which would include:

 

#include "argv.c"

#include "auth_token.c"

#include "base64.c"

#include "block_dns.c"

#include "buffer.c"

.

.

.

#include "status.c"

#include "tls_crypt.c"

#include "tun.c"

#include "win32.c"

 

And then have Makefile.ac and MSVC project files compile the master.c only.

 

Best regards,

Simon

 

 

Besides this, we need to fix this whole MSVC mess - all other platforms
are just done with "add new source file to the Makefile.ac" and done
(including mingw builds), and then MSVC is broken again, and this will
happen again and again.   


Is there no reasonable way to build these project files from Makefile.ac?

 

I see no reasonable way. Selva, Simon - opinions?

 

We could probably have a templatized project file and script which inserts source files to there

based on content of Makefile.ac, but I don't like it. I consider necessity of modifying VS project

a lesser evil. 

 

(you open it and it just works)

 

-Lev
<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=utf-8"><meta name=Generator content="Microsoft Word 15 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
	{font-family:"Cambria Math";
	panose-1:0 0 0 0 0 0 0 0 0 0;}
@font-face
	{font-family:Calibri;
	panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
	{margin:0cm;
	margin-bottom:.0001pt;
	font-size:12.0pt;
	font-family:"Times New Roman",serif;}
a:link, span.MsoHyperlink
	{mso-style-priority:99;
	color:#0563C1;
	text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
	{mso-style-priority:99;
	color:#954F72;
	text-decoration:underline;}
span.EmailStyle17
	{mso-style-type:personal;
	font-family:"Calibri",sans-serif;
	color:#1F497D;}
span.EmailStyle18
	{mso-style-type:personal-reply;
	font-family:"Calibri",sans-serif;
	color:#1F497D;}
.MsoChpDefault
	{mso-style-type:export-only;
	font-size:10.0pt;}
@page WordSection1
	{size:612.0pt 792.0pt;
	margin:70.85pt 70.85pt 70.85pt 70.85pt;}
div.WordSection1
	{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]--></head><body lang=SL link="#0563C1" vlink="#954F72"><div class=WordSection1><p class=MsoNormal><a name="_MailEndCompose"><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>I revoke this “master.c” idea. It makes incremental compiling ridiculously slow. It might work for production builds, but definitely not for development.<o:p></o:p></span></a></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'><o:p>&nbsp;</o:p></span></p><div><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D'>Best regards,<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D'>Simon<o:p></o:p></span></p></div><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'><o:p>&nbsp;</o:p></span></p><div><div style='border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0cm 0cm 0cm'><p class=MsoNormal><b><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif'>From:</span></b><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif'> Simon Rozman [mailto:simon@rozman.si] <br><b>Sent:</b> Thursday, November 7, 2019 2:06 PM<br><b>To:</b> 'Lev Stipakov' &lt;lstipakov@gmail.com&gt;; 'Gert Doering' &lt;gert@greenie.muc.de&gt;<br><b>Cc:</b> 'Antonio Quartulli' &lt;a@unstable.cc&gt;; 'openvpn-devel' &lt;openvpn-devel@lists.sourceforge.net&gt;<br><b>Subject:</b> Re: [Openvpn-devel] [PATCH applied] Re: VLAN: add basic VLAN tagging support<o:p></o:p></span></p></div></div><p class=MsoNormal><span lang=EN-GB><o:p>&nbsp;</o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>We could introduce a master.c file which would include:<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'><o:p>&nbsp;</o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>#include &quot;argv.c&quot;<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>#include &quot;auth_token.c&quot;<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>#include &quot;base64.c&quot;<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>#include &quot;block_dns.c&quot;<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>#include &quot;buffer.c&quot;<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>.<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>.<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>.<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>#include &quot;status.c&quot;<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>#include &quot;tls_crypt.c&quot;<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>#include &quot;tun.c&quot;<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>#include &quot;win32.c&quot;<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'><o:p>&nbsp;</o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'>And then have Makefile.ac and MSVC project files compile the master.c only.<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'><o:p>&nbsp;</o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D'>Best regards,<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D'>Simon<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-GB style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US'><o:p>&nbsp;</o:p></span></p><div><div><div><p class=MsoNormal><span lang=EN-GB>&nbsp;<o:p></o:p></span></p></div><blockquote style='border:none;border-left:solid #CCCCCC 1.0pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-top:5.0pt;margin-right:0cm;margin-bottom:5.0pt'><p class=MsoNormal><span lang=EN-GB>Besides this, we need to fix this whole MSVC mess - all other platforms<br>are just done with &quot;add new source file to the Makefile.ac&quot; and done<br>(including mingw builds), and then MSVC is broken again, and this will<br>happen again and again.&nbsp; &nbsp;<o:p></o:p></span></p></blockquote><blockquote style='border:none;border-left:solid #CCCCCC 1.0pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-top:5.0pt;margin-right:0cm;margin-bottom:5.0pt'><p class=MsoNormal><span lang=EN-GB><br>Is there no reasonable way to build these project files from Makefile.ac?<o:p></o:p></span></p></blockquote><div><p class=MsoNormal><span lang=EN-GB><o:p>&nbsp;</o:p></span></p></div><div><p class=MsoNormal><span lang=EN-GB>I see no reasonable way. Selva, Simon - opinions?<o:p></o:p></span></p></div><div><p class=MsoNormal><span lang=EN-GB><o:p>&nbsp;</o:p></span></p></div><div><p class=MsoNormal><span lang=EN-GB>We could probably have a templatized project file and script which inserts source files to there<o:p></o:p></span></p></div><div><p class=MsoNormal><span lang=EN-GB>based on content of Makefile.ac, but I don't like it. I consider necessity of modifying VS project<o:p></o:p></span></p></div><div><p class=MsoNormal><span lang=EN-GB>a lesser evil.&nbsp;<o:p></o:p></span></p></div><div><p class=MsoNormal><span lang=EN-GB><o:p>&nbsp;</o:p></span></p></div><div><p class=MsoNormal><span lang=EN-GB>(you open it and it just works)<o:p></o:p></span></p></div><div><p class=MsoNormal><span lang=EN-GB>&nbsp;<o:p></o:p></span></p></div></div><div><p class=MsoNormal><span lang=EN-GB>-Lev<o:p></o:p></span></p></div></div></div></body></html>
Antonio Quartulli Nov. 7, 2019, 2:38 a.m. UTC | #9
Hi,

On 07/11/2019 14:36, Simon Rozman wrote:
> I revoke this “master.c” idea. It makes incremental compiling ridiculously slow. It might work for production builds, but definitely not for development.

It also breaks scoping of variables/function. So, I am glad you found
your own reason to reject that :-)
Selva Nair Nov. 7, 2019, 4:50 a.m. UTC | #10
Hi

On Thu, Nov 7, 2019 at 7:43 AM Lev Stipakov <lstipakov@gmail.com> wrote:

> Hi,
>
>
>> I'm a bit unhappy with that one, as it changes behaviour for all
>> non-windows
>> builds (including all the openssl build output even if it succeeds).
>>
>
> The only place it changes behavior is this
>
>  install:
>    - if [ ! -z "${CHOST}" ]; then unset CC; fi
> -  - .travis/build-deps.sh > build-deps.log 2>&1 || (cat build-deps.log &&
> exit 1)
> +  - .travis/build-deps.sh
>
> I don't see it as an issue to print output when building dependencies. The
> reason why
> it is done is that travis aborts build if there is no output for more than
> 10 minutes.
>
>
>> Besides this, we need to fix this whole MSVC mess - all other platforms
>> are just done with "add new source file to the Makefile.ac" and done
>> (including mingw builds), and then MSVC is broken again, and this will
>> happen again and again.
>
>
>> Is there no reasonable way to build these project files from Makefile.ac?
>>
>
> I see no reasonable way. Selva, Simon - opinions?
>

Personally, I come from the Unix world, work on Windows only out of
necessity, and either avoid MSVC or leave it to others to figure out as far
as possible. So my opinion may not count for much.

That said, short of moving to a more Windows-friendly build system such as
CMake, I see no good options. But the status quo looks good enough to me --
i.e., just do a patch to fix the project files when you notice a missing
entry.

Selva
<div dir="ltr"><div>Hi<br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Nov 7, 2019 at 7:43 AM Lev Stipakov &lt;<a href="mailto:lstipakov@gmail.com">lstipakov@gmail.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr">Hi,</div><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I&#39;m a bit unhappy with that one, as it changes behaviour for all non-windows<br>
builds (including all the openssl build output even if it succeeds).<br></blockquote><div><br></div><div>The only place it changes behavior is this</div><div><br></div> install:<br>   - if [ ! -z &quot;${CHOST}&quot; ]; then unset CC; fi<br>-  - .travis/build-deps.sh &gt; build-deps.log 2&gt;&amp;1 || (cat build-deps.log &amp;&amp; exit 1)<br><div>+  - .travis/build-deps.sh</div><div><br></div><div>I don&#39;t see it as an issue to print output when building dependencies. The reason why</div><div>it is done is that travis aborts build if there is no output for more than 10 minutes. </div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Besides this, we need to fix this whole MSVC mess - all other platforms<br>
are just done with &quot;add new source file to the Makefile.ac&quot; and done<br>
(including mingw builds), and then MSVC is broken again, and this will<br>
happen again and again.   </blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
Is there no reasonable way to build these project files from Makefile.ac?<br></blockquote><div><br></div><div>I see no reasonable way. Selva, Simon - opinions?<br></div></div></div></blockquote><div><br></div><div>Personally, I come from the Unix world, work on Windows only out of necessity, and either avoid MSVC or leave it to others to figure out as far as possible. So my opinion may not count for much.</div><div><br></div><div>That said, short of moving to a more Windows-friendly build system such as CMake, I see no good options. But the status quo looks good enough to me -- i.e., just do a patch to fix the project files when you notice a missing entry.</div><div><br></div><div>Selva<br></div><div><br></div><div><br></div></div></div>
Lev Stipakov Nov. 7, 2019, 10:45 a.m. UTC | #11
Hi,

It's lots of text that is totally uninteresting if it succeeds, but that
> you need to scroll over when looking for the reason why a build fails -
> which is the reason why it is the way it is today.
>

I have sent v2 which doesn't change the behavior for non-Windows builds.

If you volunteer to update MSVC every time we add or change a source file,
> I'm happy to send you a HEADS UP notice.  But I am not doing it, and I will
> not request it from any contributor who is not using windows.
>

All right, that would work for me. We don't add C files that often, I could
take care
of fixing Visual Studio build after getting a mail from travis / buildbot
(when we'll have MSVC there).

v2: https://patchwork.openvpn.net/patch/886/
happy travis: https://travis-ci.org/lstipakov/openvpn/builds/608949725

Patch

diff --git a/src/openvpn/Makefile.am b/src/openvpn/Makefile.am
index 30caa01f..bc976019 100644
--- a/src/openvpn/Makefile.am
+++ b/src/openvpn/Makefile.am
@@ -123,6 +123,7 @@  openvpn_SOURCES = \
 	syshead.h \
 	tls_crypt.c tls_crypt.h \
 	tun.c tun.h \
+	vlan.c vlan.h \
 	win32.h win32.c \
 	cryptoapi.h cryptoapi.c
 openvpn_LDADD = \
diff --git a/src/openvpn/errlevel.h b/src/openvpn/errlevel.h
index 60896c1f..e448fc37 100644
--- a/src/openvpn/errlevel.h
+++ b/src/openvpn/errlevel.h
@@ -148,6 +148,8 @@ 
 #define D_PF_DEBUG           LOGLEV(7, 72, M_DEBUG)  /* packet filter debugging, must also define PF_DEBUG in pf.h */
 #define D_PUSH_DEBUG         LOGLEV(7, 73, M_DEBUG)  /* show push/pull debugging info */
 
+#define D_VLAN_DEBUG         LOGLEV(7, 74, 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/multi.c b/src/openvpn/multi.c
index d1f9c72e..8caaa868 100644
--- a/src/openvpn/multi.c
+++ b/src/openvpn/multi.c
@@ -45,6 +45,7 @@ 
 #include "gremlin.h"
 #include "mstats.h"
 #include "ssl_verify.h"
+#include "vlan.h"
 #include <inttypes.h>
 
 #include "memdbg.h"
@@ -2208,7 +2209,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,
+            uint16_t vid)
 {
     struct hash_iterator hi;
     struct hash_element *he;
@@ -2258,6 +2260,10 @@  multi_bcast(struct multi_context *m,
                     }
                 }
 #endif /* ifdef ENABLE_PF */
+                if (vid != 0 && vid != mi->context.options.vlan_pvid)
+                {
+                    continue;
+                }
                 multi_add_mbuf(m, mi, mb);
             }
         }
@@ -2595,7 +2601,7 @@  multi_process_incoming_link(struct multi_context *m, struct multi_instance *inst
                     if (mroute_flags & MROUTE_EXTRACT_MCAST)
                     {
                         /* for now, treat multicast as broadcast */
-                        multi_bcast(m, &c->c2.to_tun, m->pending, NULL);
+                        multi_bcast(m, &c->c2.to_tun, m->pending, NULL, 0);
                     }
                     else /* possible client to client routing */
                     {
@@ -2640,6 +2646,15 @@  multi_process_incoming_link(struct multi_context *m, struct multi_instance *inst
                 struct mroute_addr edest;
                 mroute_addr_reset(&edest);
 #endif
+                if (m->top.options.vlan_tagging)
+                {
+                    if (vlan_is_tagged(&c->c2.to_tun))
+                    {
+                        /* Drop VLAN-tagged frame. */
+                        msg(D_VLAN_DEBUG, "dropping incoming VLAN-tagged frame");
+                        c->c2.to_tun.len = 0;
+                    }
+                }
                 /* extract packet source and dest addresses */
                 mroute_flags = mroute_extract_addr_from_packet(&src,
                                                                &dest,
@@ -2661,7 +2676,7 @@  multi_process_incoming_link(struct multi_context *m, struct multi_instance *inst
                         {
                             if (mroute_flags & (MROUTE_EXTRACT_BCAST|MROUTE_EXTRACT_MCAST))
                             {
-                                multi_bcast(m, &c->c2.to_tun, m->pending, NULL);
+                                multi_bcast(m, &c->c2.to_tun, m->pending, NULL, 0);
                             }
                             else /* try client-to-client routing */
                             {
@@ -2788,9 +2803,9 @@  multi_process_incoming_tun(struct multi_context *m, const unsigned int mpp_flags
             {
                 /* for now, treat multicast as broadcast */
 #ifdef ENABLE_PF
-                multi_bcast(m, &m->top.c2.buf, NULL, e2);
+                multi_bcast(m, &m->top.c2.buf, NULL, e2, 0);
 #else
-                multi_bcast(m, &m->top.c2.buf, NULL, NULL);
+                multi_bcast(m, &m->top.c2.buf, NULL, NULL, 0);
 #endif
             }
             else
@@ -2972,7 +2987,7 @@  gremlin_flood_clients(struct multi_context *m)
 
         for (i = 0; i < parm.n_packets; ++i)
         {
-            multi_bcast(m, &buf, NULL, NULL);
+            multi_bcast(m, &buf, NULL, NULL, 0);
         }
 
         gc_free(&gc);
diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h
index d87f21b9..cfd86bbe 100644
--- a/src/openvpn/multi.h
+++ b/src/openvpn/multi.h
@@ -40,6 +40,7 @@ 
 #include "mudp.h"
 #include "mtcp.h"
 #include "perf.h"
+#include "vlan.h"
 
 #define MULTI_PREFIX_MAX_LENGTH 256
 
@@ -620,6 +621,7 @@  multi_process_outgoing_tun(struct multi_context *m, const unsigned int mpp_flags
            mi->context.c2.to_tun.len);
 #endif
     set_prefix(mi);
+    vlan_process_outgoing_tun(m, mi);
     process_outgoing_tun(&mi->context);
     ret = multi_process_post(m, mi, mpp_flags);
     clear_prefix();
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index 2d3865a6..caba6494 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -53,6 +53,7 @@ 
 #include "win32.h"
 #include "push.h"
 #include "pool.h"
+#include "proto.h"
 #include "helper.h"
 #include "manage.h"
 #include "forward.h"
@@ -404,6 +405,8 @@  static const char usage_message[] =
     "--plugin m [str]: Load plug-in module m passing str as an argument\n"
     "                  to its initialization function.\n"
 #endif
+    "--vlan-tagging  : Enable 802.1Q-based VLAN tagging.\n"
+    "--vlan-pvid v   : Sets the Port VLAN Identifier. Defaults to 1.\n"
 #if P2MP
 #if P2MP_SERVER
     "\n"
@@ -849,6 +852,8 @@  init_options(struct options *o, const bool init_gc)
     o->route_method = ROUTE_METHOD_ADAPTIVE;
     o->block_outside_dns = false;
 #endif
+    o->vlan_accept = VLAN_ONLY_UNTAGGED_OR_PRIORITY;
+    o->vlan_pvid = 1;
 #if P2MP_SERVER
     o->real_hash_size = 256;
     o->virtual_hash_size = 256;
@@ -1224,6 +1229,17 @@  dhcp_option_address_parse(const char *name, const char *parm, in_addr_t *array,
 
 #endif /* if defined(_WIN32) || defined(TARGET_ANDROID) */
 
+static const char *
+print_vlan_accept(enum vlan_acceptable_frames mode)
+{
+    switch (mode)
+    {
+        case VLAN_ONLY_UNTAGGED_OR_PRIORITY:
+            return "untagged";
+    }
+    return NULL;
+}
+
 #if P2MP
 
 #ifndef ENABLE_SMALL
@@ -1293,6 +1309,9 @@  show_p2mp_parms(const struct options *o)
     SHOW_STR(port_share_host);
     SHOW_STR(port_share_port);
 #endif
+    SHOW_BOOL(vlan_tagging);
+    msg(D_SHOW_PARMS, "  vlan_accept = %s", print_vlan_accept (o->vlan_accept));
+    SHOW_INT(vlan_pvid);
 #endif /* P2MP_SERVER */
 
     SHOW_BOOL(client);
@@ -2355,6 +2374,18 @@  options_postprocess_verify_ce(const struct options *options, const struct connec
                 msg(M_USAGE, "--auth-user-pass-optional %s", postfix);
             }
         }
+
+        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_pvid != defaults.vlan_pvid)
+            {
+                msg(M_USAGE, "--vlan-pvid requires --vlan-tagging");
+            }
+        }
     }
     else
     {
@@ -2444,6 +2475,11 @@  options_postprocess_verify_ce(const struct options *options, const struct connec
         {
             msg(M_USAGE, "--stale-routes-check requires --mode server");
         }
+
+        if (options->vlan_tagging)
+        {
+            msg(M_USAGE, "--vlan-tagging requires --mode server");
+        }
     }
 #endif /* P2MP_SERVER */
 
@@ -8359,6 +8395,24 @@  add_option(struct options *options,
         VERIFY_PERMISSION(OPT_P_GENERAL);
         options->allow_recursive_routing = true;
     }
+    else if (streq(p[0], "vlan-tagging") && !p[1])
+    {
+        VERIFY_PERMISSION(OPT_P_GENERAL);
+        options->vlan_tagging = true;
+    }
+    else if (streq(p[0], "vlan-pvid") && p[1] && !p[2])
+    {
+        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 >= %u and <= %u",
+                OPENVPN_8021Q_MIN_VID, OPENVPN_8021Q_MAX_VID);
+            goto err;
+        }
+    }
     else
     {
         int i;
diff --git a/src/openvpn/options.h b/src/openvpn/options.h
index 63f0f4cb..3f5c5465 100644
--- a/src/openvpn/options.h
+++ b/src/openvpn/options.h
@@ -169,6 +169,11 @@  struct remote_list
     struct remote_entry *array[CONNECTION_LIST_SIZE];
 };
 
+enum vlan_acceptable_frames
+{
+    VLAN_ONLY_UNTAGGED_OR_PRIORITY,
+};
+
 struct remote_host_store
 {
 #define RH_HOST_LEN 80
@@ -632,6 +637,10 @@  struct options
     int keying_material_exporter_length;
 #endif
 
+    bool vlan_tagging;
+    enum vlan_acceptable_frames vlan_accept;
+    uint16_t vlan_pvid;
+
     struct pull_filter_list *pull_filter_list;
 
     /* Useful when packets sent by openvpn itself are not subject
diff --git a/src/openvpn/proto.h b/src/openvpn/proto.h
index 4ddffc7d..c1ff3e14 100644
--- a/src/openvpn/proto.h
+++ b/src/openvpn/proto.h
@@ -60,9 +60,31 @@  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_PCP htons(0xE000) /* mask PCP out of pcp_cfi_vid */
+#define OPENVPN_8021Q_MASK_CFI htons(0x1000) /* mask CFI out of pcp_cfi_vid */
+#define OPENVPN_8021Q_MASK_VID htons(0x0FFF) /* mask VID 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 */
@@ -311,4 +333,7 @@  void ipv4_packet_size_verify(const uint8_t *data,
 
 #endif
 
+#define OPENVPN_8021Q_MIN_VID 1
+#define OPENVPN_8021Q_MAX_VID 4094
+
 #endif /* ifndef PROTO_H */
diff --git a/src/openvpn/vlan.c b/src/openvpn/vlan.c
new file mode 100644
index 00000000..8e987277
--- /dev/null
+++ b/src/openvpn/vlan.c
@@ -0,0 +1,110 @@ 
+/*
+ *  OpenVPN -- An application to securely tunnel IP networks
+ *             over a single TCP/UDP port, with support for SSL/TLS-based
+ *             session authentication and key exchange,
+ *             packet encryption, packet authentication, and
+ *             packet compression.
+ *
+ *  Copyright (C) 2002-2019 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ *  Copyright (C) 2010      Fabian Knittel <fabian.knittel@lettink.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#elif defined(_MSC_VER)
+#include "config-msvc.h"
+#endif
+
+#include "syshead.h"
+
+#if P2MP_SERVER
+
+#include "multi.h"
+#include "options.h"
+#include "vlan.h"
+
+/*
+ * Retrieve the VLAN Identifier (VID) from the IEEE 802.1Q header.
+ *
+ * @param hdr Pointer to the Ethernet header with IEEE 802.1Q tagging.
+ * @return    Returns the VID in host byte order.
+ */
+static uint16_t
+vlanhdr_get_vid(const struct openvpn_8021qhdr *hdr)
+{
+    return ntohs(hdr->pcp_cfi_vid & OPENVPN_8021Q_MASK_VID);
+}
+
+/*
+ * vlan_is_tagged - check if a packet is VLAN-tagged
+ *
+ * Checks whether ethernet frame is VLAN-tagged.
+ *
+ * @param buf The ethernet frame.
+ * @return    Returns true if the frame is VLAN-tagged, false otherwise.
+ */
+bool
+vlan_is_tagged(const struct buffer *buf)
+{
+    const struct openvpn_8021qhdr *vlanhdr;
+    uint16_t vid;
+
+    if (BLEN(buf) < sizeof(struct openvpn_8021qhdr))
+    {
+        /* frame too small to be VLAN-tagged */
+        return false;
+    }
+
+    vlanhdr = (const struct openvpn_8021qhdr *)BPTR(buf);
+
+    if (ntohs(vlanhdr->tpid) != OPENVPN_ETH_P_8021Q)
+    {
+        /* non tagged frame */
+        return false;
+    }
+
+    vid = vlanhdr_get_vid(vlanhdr);
+    if (vid == 0)
+    {
+        /* no vid: piority tagged only */
+        return false;
+    }
+
+    return true;
+}
+
+void
+vlan_process_outgoing_tun(struct multi_context *m, struct multi_instance *mi)
+{
+    if (!m->top.options.vlan_tagging)
+    {
+        return;
+    }
+
+    if (m->top.options.vlan_accept == VLAN_ONLY_UNTAGGED_OR_PRIORITY)
+    {
+        /* Packets forwarded to the TAP devices aren't VLAN-tagged. Only packets
+         * matching the PVID configured globally are allowed to be received
+         */
+        if (m->top.options.vlan_pvid != mi->context.options.vlan_pvid)
+        {
+            /* Packet is coming from the wrong VID, drop it.  */
+            mi->context.c2.to_tun.len = 0;
+        }
+    }
+}
+
+#endif /* P2MP_SERVER */
diff --git a/src/openvpn/vlan.h b/src/openvpn/vlan.h
new file mode 100644
index 00000000..1ef68813
--- /dev/null
+++ b/src/openvpn/vlan.h
@@ -0,0 +1,44 @@ 
+/*
+ *  OpenVPN -- An application to securely tunnel IP networks
+ *             over a single TCP/UDP port, with support for SSL/TLS-based
+ *             session authentication and key exchange,
+ *             packet encryption, packet authentication, and
+ *             packet compression.
+ *
+ *  Copyright (C) 2002-2019 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ *  Copyright (C) 2010      Fabian Knittel <fabian.knittel@lettink.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef VLAN_H
+#define VLAN_H
+
+#if P2MP_SERVER
+
+#include "buffer.h"
+#include "mroute.h"
+
+struct multi_context;
+struct multi_instance;
+
+bool
+vlan_is_tagged(const struct buffer *buf);
+
+void
+vlan_process_outgoing_tun(struct multi_context *m, struct multi_instance *mi);
+
+#endif /* P2MP_SERVER */
+
+#endif /* VLAN_H */