@@ -211,4 +211,11 @@ get_num_elements(const char *string, char delimiter);
struct buffer
prepend_dir(const char *dir, const char *path, struct gc_arena *gc);
+#define _STRINGIFY(S) #S
+#define MAC_FMT _STRINGIFY(%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx)
+#define MAC_PRINT_ARG(_mac) _mac[0], _mac[1], _mac[2], \
+ _mac[3], _mac[4], _mac[5]
+#define MAC_SCAN_ARG(_mac) &_mac[0], &_mac[1], &_mac[2], \
+ &_mac[3], &_mac[4], &_mac[5]
+
#endif /* ifndef MISC_H */
@@ -103,6 +103,18 @@ int net_iface_up(openvpn_net_ctx_t *ctx, const openvpn_net_iface_t *iface,
int net_iface_mtu_set(openvpn_net_ctx_t *ctx,
const openvpn_net_iface_t *iface, uint32_t mtu);
+/**
+ * Set the Link Layer (Ethernet) address of the TAP interface
+ *
+ * @param ctx the implementation specific context
+ * @param iface the interface to modify
+ * @param addr the new address to set (expected ETH_ALEN bytes (6))
+ *
+ * @return 0 on success, a negative error code otherwise
+ */
+int net_addr_ll_set(openvpn_net_ctx_t *ctx, const openvpn_net_iface_t *iface,
+ uint8_t *addr);
+
/**
* Add an IPv4 address to an interface
*
@@ -93,6 +93,29 @@ net_iface_mtu_set(openvpn_net_ctx_t *ctx, const char *iface, uint32_t mtu)
return 0;
}
+int
+net_addr_ll_set(openvpn_net_ctx_t *ctx, const openvpn_net_iface_t *iface,
+ uint8_t *addr)
+{
+ struct argv argv = argv_new();
+ int ret = 0;
+
+ argv_printf(&argv,
+ "%s link set addr " MAC_FMT " dev %s",
+ iproute_path, MAC_PRINT_ARG(addr), iface);
+
+ argv_msg(M_INFO, &argv);
+ if (!openvpn_execve_check(&argv, ctx->es, M_WARN,
+ "Linux ip link set addr failed"))
+ {
+ ret = -1;
+ }
+
+ argv_free(&argv);
+
+ return ret;
+}
+
int
net_addr_v4_add(openvpn_net_ctx_t *ctx, const char *iface,
const in_addr_t *addr, int prefixlen)
@@ -30,6 +30,7 @@
#include "errlevel.h"
#include "buffer.h"
+#include "misc.h"
#include "networking.h"
#include <errno.h>
@@ -723,6 +724,40 @@ err:
return ret;
}
+int
+net_addr_ll_set(openvpn_net_ctx_t *ctx, const openvpn_net_iface_t *iface,
+ uint8_t *addr)
+{
+ struct sitnl_link_req req;
+ int ifindex, ret = -1;
+
+ CLEAR(req);
+
+ ifindex = if_nametoindex(iface);
+ if (ifindex == 0)
+ {
+ msg(M_WARN | M_ERRNO, "%s: rtnl: cannot get ifindex for %s", __func__,
+ iface);
+ return -1;
+ }
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = RTM_NEWLINK;
+
+ req.i.ifi_family = AF_PACKET;
+ req.i.ifi_index = ifindex;
+
+ SITNL_ADDATTR(&req.n, sizeof(req), IFLA_ADDRESS, addr, ETH_ALEN);
+
+ msg(M_INFO, "%s: lladdr " MAC_FMT " for %s", __func__, MAC_PRINT_ARG(addr),
+ iface);
+
+ ret = sitnl_send(&req.n, 0, 0, NULL, NULL);
+err:
+ return ret;
+}
+
static int
sitnl_addr_set(int cmd, uint32_t flags, int ifindex, sa_family_t af_family,
const inet_address_t *local, const inet_address_t *remote,