]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Added --lladdr option to specify the link layer (MAC) address
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Thu, 13 Apr 2006 21:09:04 +0000 (21:09 +0000)
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Thu, 13 Apr 2006 21:09:04 +0000 (21:09 +0000)
for the tap interface on non-Windows platforms (Roy Marples).

git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@1012 e7ae566f-a301-0410-adde-c780ea21d3b5

ChangeLog
Makefile.am
init.c
lladdr.c [new file with mode: 0644]
lladdr.h [new file with mode: 0644]
makefile.w32
openvpn.8
options.c
options.h

index a83ae01f33ec49005d12779a093f30592f5a0d35..a4285db39f3958952327e841fdd66b581bf1169c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -15,7 +15,10 @@ $Id$
 
 * Added --route-metric option to set a default route metric
   for --route (Roy Marples).
-       
+
+* Added --lladdr option to specify the link layer (MAC) address
+  for the tap interface on non-Windows platforms (Roy Marples).
+
 2006.04.12 -- Version 2.1-beta13
 
 * Code added in 2.1-beta7 and 2.0.6-rc1 to extend byte counters
index 85c0c4f1c8a737399aa427c2ff8c4a67bd8b542e..36e2cf9a9e6b9e4c70baf87db7afd0b1afb016b7 100644 (file)
@@ -50,6 +50,7 @@ openvpn_SOURCES = \
        fragment.c fragment.h \
        gremlin.c gremlin.h \
        helper.c helper.h \
+       lladdr.c lladdr.h \
        init.c init.h \
        integer.h \
         interval.c interval.h \
diff --git a/init.c b/init.c
index 0bc5219166a4cbc9c2d49b1a48944dfe7c33c062..d23272ca534051b28b1fdf6d6cde2ddd1ccffc2c 100644 (file)
--- a/init.c
+++ b/init.c
@@ -40,6 +40,7 @@
 #include "gremlin.h"
 #include "pkcs11.h"
 #include "ps.h"
+#include "lladdr.h"
 
 #include "memdbg.h"
 
@@ -425,6 +426,8 @@ do_persist_tuntap (const struct options *options)
             "options --mktun or --rmtun should only be used together with --dev");
       tuncfg (options->dev, options->dev_type, options->dev_node,
              options->tun_ipv6, options->persist_mode);
+      if (options->persist_mode && options->lladdr)
+        set_lladdr(options->dev, options->lladdr, NULL);
       return true;
     }
 #endif
@@ -836,6 +839,10 @@ do_open_tun (struct context *c)
       open_tun (c->options.dev, c->options.dev_type, c->options.dev_node,
                c->options.tun_ipv6, c->c1.tuntap);
 
+      /* set the hardware address */
+      if (c->options.lladdr)
+         set_lladdr(c->c1.tuntap->actual_name, c->options.lladdr, c->c2.es);
+
       /* do ifconfig */
       if (!c->options.ifconfig_noexec
          && ifconfig_order () == IFCONFIG_AFTER_TUN_OPEN)
diff --git a/lladdr.c b/lladdr.c
new file mode 100644 (file)
index 0000000..d6fb0a6
--- /dev/null
+++ b/lladdr.c
@@ -0,0 +1,58 @@
+/*
+ * Support routine for configuring link layer address 
+ */
+
+#ifdef WIN32
+#include "config-win32.h"
+#else
+#include "config.h"
+#endif
+
+#include "syshead.h"
+#include "error.h"
+#include "misc.h"
+
+int set_lladdr(const char *ifname, const char *lladdr,
+               const struct env_set *es)
+{
+  char cmd[256];
+
+  if (!ifname || !lladdr)
+    return -1;
+  
+#if defined(TARGET_LINUX)
+#ifdef CONFIG_FEATURE_IPROUTE
+  openvpn_snprintf (cmd, sizeof (cmd),
+                   IPROUTE_PATH " link set addr %s dev %s",
+                   lladdr, ifname);
+#else
+  openvpn_snprintf (cmd, sizeof (cmd),
+                   IFCONFIG_PATH " %s hw ether %s",
+                   ifname, lladdr);
+#endif
+#elif defined(TARGET_SOLARIS)
+  openvpn_snprintf (cmd, sizeof (cmd),
+                   IFCONFIG_PATH " %s ether %s",
+                   ifname, lladdr);
+#elif defined(TARGET_OPENBSD)
+  openvpn_snprintf (cmd, sizeof (cmd),
+                   IFCONFIG_PATH " %s lladdr %s",
+                   ifname, lladdr);
+#elif defined(TARGET_DARWIN)
+  openvpn_snprintf (cmd, sizeof (cmd),
+                   IFCONFIG_PATH " %s lladdr %s",
+                   ifname, lladdr);
+#elif defined(TARGET_FREEBSD)
+  openvpn_snprintf (cmd, sizeof (cmd),
+                   IFCONFIG_PATH " %s ether %s",
+                   ifname, lladdr);
+#else
+      msg (M_WARN, "Sorry, but I don't know how to configure link layer addresses on this operating system.");
+      return -1;
+#endif
+
+  int r = system_check (cmd, es, M_WARN, "ERROR: Unable to set link layer address.");
+  if (r)
+    msg (M_INFO, "TUN/TAP link layer address set to %s", lladdr);
+  return r;
+}
diff --git a/lladdr.h b/lladdr.h
new file mode 100644 (file)
index 0000000..d6c4256
--- /dev/null
+++ b/lladdr.h
@@ -0,0 +1,8 @@
+/*
+ * Support routine for configuring link layer address 
+ */
+
+#include "misc.h"
+
+int set_lladdr(const char *ifname, const char *lladdr,
+               const struct env_set *es);
index 22fbc282932d294ff05f0a784e7267bc4bc09319..bb9af54d8c0d3347405c17c4586fc73e305ba85c 100755 (executable)
@@ -82,6 +82,7 @@ HEADERS = \
        integer.h \
        interval.h \
        list.h \
+       lladdr.h \
        lzo.h \
        manage.h \
        mbuf.h \
@@ -139,6 +140,7 @@ OBJS =  base64.o \
        init.o \
        interval.o \
         list.o \
+       lladdr.o \
        lzo.o \
        manage.o \
        mbuf.o \
index 7df156dbaad5bbead21f4cee4af08297cbed9534..1c05fd213c068138f7090d6d70dfaf80ec0a4efc 100644 (file)
--- a/openvpn.8
+++ b/openvpn.8
@@ -70,6 +70,7 @@ openvpn \- secure IP tunnel daemon.
 [\ \fB\-\-dev\fR\ \fItunX\ |\ tapX\fR\ ]
 [\ \fB\-\-dev\-type\fR\ \fIdevice\-type\fR\ ]
 [\ \fB\-\-dev\-node\fR\ \fInode\fR\ ]
+[\ \fB\-\-lladdr\fR\ \fIaddress\fR\ ]
 .in -4
 .ti +4
 .hy
@@ -918,6 +919,10 @@ to enumerate all available TAP-Win32
 adapters and will show both the network
 connections control panel name and the GUID for
 each TAP-Win32 adapter.
+.TP
+.B --lladdr address
+Specify the link layer address, more commonly known as the MAC address.
+Only applied to TAP devices.
 .\"*********************************************************
 .TP
 .B --ifconfig l rn
index effe1b13f1c15d80330406912b37640ffcb7c094..8dcc6457a1c5cec1ce7d97980fb70a6d518702d1 100644 (file)
--- a/options.c
+++ b/options.c
@@ -147,6 +147,7 @@ static const char usage_message[] =
   "                  does not begin with \"tun\" or \"tap\".\n"
   "--dev-node node : Explicitly set the device node rather than using\n"
   "                  /dev/net/tun, /dev/tun, /dev/tap, etc.\n"
+  "--lladdr hw     : Set the link layer address of the tap device.\n"
   "--topology t    : Set --dev tun topology: 'net30', 'p2p', or 'subnet'.\n"
   "--tun-ipv6      : Build tun link capable of forwarding IPv6 traffic.\n"
   "--ifconfig l rn : TUN: configure device to use IP address l as a local\n"
@@ -1070,6 +1071,7 @@ show_settings (const struct options *o)
   SHOW_STR (dev);
   SHOW_STR (dev_type);
   SHOW_STR (dev_node);
+  SHOW_STR (lladdr);
   SHOW_INT (topology);
   SHOW_BOOL (tun_ipv6);
   SHOW_STR (ifconfig_local);
@@ -1403,6 +1405,10 @@ options_postprocess (struct options *options, bool first_time)
   if (options->inetd == INETD_NOWAIT && dev != DEV_TYPE_TAP)
     msg (M_USAGE, "--inetd nowait only makes sense in --dev tap mode");
 
+
+  if (options->lladdr && dev != DEV_TYPE_TAP)
+    msg (M_USAGE, "--lladdr can only be used in --dev tap mode");
   /*
    * In forking TCP server mode, you don't need to ifconfig
    * the tap device (the assumption is that it will be bridged).
@@ -3217,6 +3223,11 @@ add_option (struct options *options,
       VERIFY_PERMISSION (OPT_P_GENERAL);
       options->dev_node = p[1];
     }
+  else if (streq (p[0], "lladdr") && p[1])
+    {
+      VERIFY_PERMISSION (OPT_P_UP);
+      options->lladdr = p[1];
+    }
   else if (streq (p[0], "topology") && p[1])
     {
       VERIFY_PERMISSION (OPT_P_UP);
index b9dafe7afee69438fcac9ba5cfecc38f04a75ea2..99e68a2d5a2ae285cece02e6e0fc26b5e4cb2c3e 100644 (file)
--- a/options.h
+++ b/options.h
@@ -125,6 +125,7 @@ struct options
   const char *dev;
   const char *dev_type;
   const char *dev_node;
+  const char *lladdr;
   int topology; /* one of the TOP_x values from proto.h */
   const char *ifconfig_local;
   const char *ifconfig_remote_netmask;