"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,
- &options->tuntap_options);
+ options->username, options->groupname, &options->tuntap_options);
if (options->persist_mode && options->lladdr)
set_lladdr(options->dev, options->lladdr, NULL);
return true;
#if defined(TARGET_LINUX)
#ifdef CONFIG_FEATURE_IPROUTE
openvpn_snprintf (cmd, sizeof (cmd),
- IPROUTE_PATH " link set addr %s dev %s",
- lladdr, ifname);
+ "%s link set addr %s dev %s",
+ iproute_path, lladdr, ifname);
#else
openvpn_snprintf (cmd, sizeof (cmd),
IFCONFIG_PATH " %s hw ether %s",
#include "memdbg.h"
+#ifdef CONFIG_FEATURE_IPROUTE
+const char *iproute_path = IPROUTE_PATH;
+#endif
+
/* Redefine the top level directory of the filesystem
to restrict access to files for security */
void
void get_user_pass_auto_userid (struct user_pass *up, const char *tag);
#endif
+/*
+ * /sbin/ip path, may be overridden
+ */
+#ifdef CONFIG_FEATURE_IPROUTE
+extern const char *iproute_path;
+#endif
+
#endif
[\ \fB\-\-dev\-type\fR\ \fIdevice\-type\fR\ ]
[\ \fB\-\-dev\-node\fR\ \fInode\fR\ ]
[\ \fB\-\-lladdr\fR\ \fIaddress\fR\ ]
+[\ \fB\-\-user\fR\ \fIuser\fR\ ]
+[\ \fB\-\-group\fR\ \fIgroup\fR\ ]
.in -4
.ti +4
.hy
[\ \fB\-\-inetd\fR\ \fI[wait|nowait]\ [progname]\fR\ ]
[\ \fB\-\-ip\-win32\fR\ \fImethod\fR\ ]
[\ \fB\-\-ipchange\fR\ \fIcmd\fR\ ]
+[\ \fB\-\-iproute\fR\ \fIcmd\fR\ ]
[\ \fB\-\-iroute\fR\ \fInetwork\ [netmask]\fR\ ]
[\ \fB\-\-keepalive\fR\ \fIn\ m\fR\ ]
[\ \fB\-\-key\-method\fR\ \fIm\fR\ ]
Only applied to TAP devices.
.\"*********************************************************
.TP
+.B --iproute cmd
+Set alternate command to execute instead of default iproute2 command.
+May be used in order to execute OpenVPN in unprivileged environment.
+.\"*********************************************************
+.TP
.B --ifconfig l rn
Set TUN/TAP adapter parameters.
.B l
.B --dev tunX | tapX
TUN/TAP device
.\"*********************************************************
+.TP
+.B --user user
+Optional user to be owner of this tunnel.
+.\"*********************************************************
+.TP
+.B --group group
+Optional group to be owner of this tunnel.
+.\"*********************************************************
.SS Windows-Specific Options:
.\"*********************************************************
.TP
"--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"
+#ifdef CONFIG_FEATURE_IPROUTE
+ "--iproute cmd : Use this command instead of default " IPROUTE_PATH ".\n"
+#endif
"--ifconfig l rn : TUN: configure device to use IP address l as a local\n"
" endpoint and rn as a remote endpoint. l & rn should be\n"
" swapped on the other peer. l & rn must be private\n"
"--rmtun : Remove a persistent tunnel.\n"
"--dev tunX|tapX : tun/tap device\n"
"--dev-type dt : Device type. See tunnel options above for details.\n"
+ "--user user : User to set privilege to.\n"
+ "--group group : Group to set privilege to.\n"
#endif
#ifdef ENABLE_PKCS11
"\n"
VERIFY_PERMISSION (OPT_P_UP);
options->tun_ipv6 = true;
}
+#ifdef CONFIG_FEATURE_IPROUTE
+ else if (streq (p[0], "iproute") && p[1])
+ {
+ VERIFY_PERMISSION (OPT_P_UP);
+ iproute_path = p[1];
+ }
+#endif
else if (streq (p[0], "ifconfig") && p[1] && p[2])
{
VERIFY_PERMISSION (OPT_P_UP);
#if defined(TARGET_LINUX)
#ifdef CONFIG_FEATURE_IPROUTE
- buf_printf (&buf, IPROUTE_PATH " route add %s/%d via %s",
+ buf_printf (&buf, "%s route add %s/%d via %s",
+ iproute_path,
network,
count_netmask_bits(netmask),
gateway);
#if defined(TARGET_LINUX)
#ifdef CONFIG_FEATURE_IPROUTE
- buf_printf (&buf, IPROUTE_PATH " route del %s/%d",
+ buf_printf (&buf, "%s route del %s/%d",
+ iproute_path,
network,
count_netmask_bits(netmask));
#else
* Set the MTU for the device
*/
openvpn_snprintf (command_line, sizeof (command_line),
- IPROUTE_PATH " link set dev %s up mtu %d",
+ "%s link set dev %s up mtu %d",
+ iproute_path,
actual,
tun_mtu
);
* Set the address for the device
*/
openvpn_snprintf (command_line, sizeof (command_line),
- IPROUTE_PATH " addr add dev %s local %s peer %s",
+ "%s addr add dev %s local %s peer %s",
+ iproute_path,
actual,
ifconfig_local,
ifconfig_remote_netmask
system_check (command_line, es, S_FATAL, "Linux ip addr add failed");
} else {
openvpn_snprintf (command_line, sizeof (command_line),
- IPROUTE_PATH " addr add dev %s %s/%d broadcast %s",
+ "%s addr add dev %s %s/%d broadcast %s",
+ iproute_path,
actual,
ifconfig_local,
count_netmask_bits(ifconfig_remote_netmask),
#ifdef TUNSETPERSIST
+/*
+ * This can be removed in future
+ * when all systems will use newer
+ * linux-headers
+ */
+#ifndef TUNSETOWNER
+#define TUNSETOWNER _IOW('T', 204, int)
+#endif
+#ifndef TUNSETGROUP
+#define TUNSETGROUP _IOW('T', 206, int)
+#endif
+
void
-tuncfg (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, int persist_mode, const struct tuntap_options *options)
+tuncfg (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, int persist_mode, const char *username, const char *groupname, const struct tuntap_options *options)
{
struct tuntap *tt;
open_tun (dev, dev_type, dev_node, ipv6, tt);
if (ioctl (tt->fd, TUNSETPERSIST, persist_mode) < 0)
msg (M_ERR, "Cannot ioctl TUNSETPERSIST(%d) %s", persist_mode, dev);
+ if (username != NULL)
+ {
+ struct user_state user_state;
+
+ if (!get_user (username, &user_state))
+ msg (M_ERR, "Cannot get user entry for %s", username);
+ else
+ if (ioctl (tt->fd, TUNSETOWNER, user_state.pw->pw_uid) < 0)
+ msg (M_ERR, "Cannot ioctl TUNSETOWNER(%s) %s", username, dev);
+ }
+ if (groupname != NULL)
+ {
+ struct group_state group_state;
+
+ if (!get_group (groupname, &group_state))
+ msg (M_ERR, "Cannot get group entry for %s", groupname);
+ else
+ if (ioctl (tt->fd, TUNSETGROUP, group_state.gr->gr_gid) < 0)
+ msg (M_ERR, "Cannot ioctl TUNSETOWNER(%s) %s", groupname, dev);
+ }
close_tun (tt);
msg (M_INFO, "Persist state set to: %s", (persist_mode ? "ON" : "OFF"));
}
{
if (tt)
{
+#ifdef CONFIG_FEATURE_IPROUTE
+ char command_line[256];
+ /*
+ * Flush IP configuration for the device
+ */
+ openvpn_snprintf (command_line, sizeof (command_line),
+ "%s addr flush dev %s",
+ iproute_path,
+ tt->actual_name
+ );
+ msg (M_INFO, "%s", command_line);
+ system_check (command_line, NULL, S_FATAL, "Linux ip flush failed");
+#endif
close_tun_generic (tt);
free (tt);
}
int read_tun (struct tuntap* tt, uint8_t *buf, int len);
void tuncfg (const char *dev, const char *dev_type, const char *dev_node,
- bool ipv6, int persist_mode, const struct tuntap_options *options);
+ bool ipv6, int persist_mode, const char *username,
+ const char *groupname, const struct tuntap_options *options);
const char *guess_tuntap_dev (const char *dev,
const char *dev_type,