From e12fe2864a30f4e5b6c77fcf6128be7a6266d73e Mon Sep 17 00:00:00 2001 From: james Date: Thu, 13 Apr 2006 21:09:04 +0000 Subject: Added --lladdr option to specify the link layer (MAC) address 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 | 5 ++++- Makefile.am | 1 + init.c | 7 +++++++ lladdr.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lladdr.h | 8 ++++++++ makefile.w32 | 2 ++ openvpn.8 | 5 +++++ options.c | 11 +++++++++++ options.h | 1 + 9 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 lladdr.c create mode 100644 lladdr.h diff --git a/ChangeLog b/ChangeLog index a83ae01..a4285db 100644 --- 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 diff --git a/Makefile.am b/Makefile.am index 85c0c4f..36e2cf9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 0bc5219..d23272c 100644 --- 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 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 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); diff --git a/makefile.w32 b/makefile.w32 index 22fbc28..bb9af54 100755 --- a/makefile.w32 +++ b/makefile.w32 @@ -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 \ diff --git a/openvpn.8 b/openvpn.8 index 7df156d..1c05fd2 100644 --- 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 diff --git a/options.c b/options.c index effe1b1..8dcc645 100644 --- 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); diff --git a/options.h b/options.h index b9dafe7..99e68a2 100644 --- 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; -- cgit v1.2.3