* [B.A.T.M.A.N.] [PATCHv2 next 1/3] batctl: introduce rtnl_open() helper function
@ 2014-01-05 21:37 Antonio Quartulli
2014-01-05 21:37 ` [B.A.T.M.A.N.] [PATCHv2 next 2/3] batctl: implement vlan-to-link helper functions Antonio Quartulli
2014-01-05 21:37 ` [B.A.T.M.A.N.] [PATCHv2 next 3/3] batctl: add sys framework for VLAN support Antonio Quartulli
0 siblings, 2 replies; 3+ messages in thread
From: Antonio Quartulli @ 2014-01-05 21:37 UTC (permalink / raw)
To: b.a.t.m.a.n; +Cc: Antonio Quartulli
Other part of batctl may require to open and send
a message to RTNL. Extract this code and put it in
a generic helper to simplify future uses.
Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
---
Changes from v1:
- fixed typ0
- removed len argument from rtnl_open() in 1/3
- removed error messages in 2/3
- avoided double free in 2/3
- simplified 3/3
functions.c | 45 +++++++++++++++++++++++++++++----------------
1 file changed, 29 insertions(+), 16 deletions(-)
diff --git a/functions.c b/functions.c
index 13ba190..50bb834 100644
--- a/functions.c
+++ b/functions.c
@@ -497,30 +497,27 @@ static void request_mac_resolve(int ai_family, const void *l3addr)
close(sock);
}
-static int resolve_mac_from_cache_open(int ai_family)
+/**
+ * rtnl_open - open a socket to rtnl and send a request
+ * @nh: the header of the request to send
+ * @protocol: the protocol to use when opening the socket
+ *
+ * Return 0 on success or a negative error code otherwise
+ */
+static int rtnl_open(struct nlmsghdr *nh, int protocol)
{
- int socknl;
- int ret;
- struct {
- struct nlmsghdr hdr;
- struct ndmsg msg;
- } nlreq;
- struct sockaddr_nl addrnl;
static uint32_t nr_call = 0;
uint32_t pid = (++nr_call + getpid()) & 0x3FFFFF;
+ struct sockaddr_nl addrnl;
+ int socknl;
+ int ret;
memset(&addrnl, 0, sizeof(addrnl));
addrnl.nl_family = AF_NETLINK;
addrnl.nl_pid = pid;
addrnl.nl_groups = 0;
- memset(&nlreq, 0, sizeof(nlreq));
- nlreq.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(nlreq.msg));
- nlreq.hdr.nlmsg_type = RTM_GETNEIGH;
- nlreq.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
- nlreq.msg.ndm_family = ai_family;
-
- socknl = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ socknl = socket(AF_NETLINK, SOCK_RAW, protocol);
if (socknl < 0)
goto out;
@@ -528,7 +525,7 @@ static int resolve_mac_from_cache_open(int ai_family)
if (ret < 0)
goto outclose;
- ret = send(socknl, &nlreq, nlreq.hdr.nlmsg_len, 0);
+ ret = send(socknl, nh, nh->nlmsg_len, 0);
if (ret < 0)
goto outclose;
out:
@@ -538,6 +535,22 @@ outclose:
return ret;
}
+static int resolve_mac_from_cache_open(int ai_family)
+{
+ struct {
+ struct nlmsghdr hdr;
+ struct ndmsg msg;
+ } nlreq;
+
+ memset(&nlreq, 0, sizeof(nlreq));
+ nlreq.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(nlreq.msg));
+ nlreq.hdr.nlmsg_type = RTM_GETNEIGH;
+ nlreq.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
+ nlreq.msg.ndm_family = ai_family;
+
+ return rtnl_open(&nlreq.hdr, NETLINK_ROUTE);
+}
+
static ssize_t resolve_mac_from_cache_dump(int sock, void **buf, size_t *buflen)
{
struct iovec iov;
--
1.8.5.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [B.A.T.M.A.N.] [PATCHv2 next 2/3] batctl: implement vlan-to-link helper functions
2014-01-05 21:37 [B.A.T.M.A.N.] [PATCHv2 next 1/3] batctl: introduce rtnl_open() helper function Antonio Quartulli
@ 2014-01-05 21:37 ` Antonio Quartulli
2014-01-05 21:37 ` [B.A.T.M.A.N.] [PATCHv2 next 3/3] batctl: add sys framework for VLAN support Antonio Quartulli
1 sibling, 0 replies; 3+ messages in thread
From: Antonio Quartulli @ 2014-01-05 21:37 UTC (permalink / raw)
To: b.a.t.m.a.n; +Cc: Antonio Quartulli
This functions can be used to convert a vlan interface
into the real one and to extract the vlan identifier.
Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
---
functions.c | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
functions.h | 1 +
2 files changed, 166 insertions(+)
diff --git a/functions.c b/functions.c
index 50bb834..fdae6fa 100644
--- a/functions.c
+++ b/functions.c
@@ -40,6 +40,7 @@
#include <linux/neighbour.h>
#include <sys/uio.h>
#include <errno.h>
+#include <net/if.h>
#include "main.h"
#include "functions.h"
@@ -764,3 +765,167 @@ struct ether_addr *resolve_mac(const char *asc)
out:
return mac_result;
}
+
+/**
+ * vlan_get_link_parse - parse a get_link rtnl message and extract the important
+ * data
+ * @nh: the reply header
+ * @iface: pointer to the buffer where the link interface has to be stored (it
+ * is allocated by this function)
+ *
+ * Return the vid in case of success or -1 otherwise
+ */
+static int vlan_get_link_parse(struct nlmsghdr *nh, char **iface)
+{
+ struct ifinfomsg *ifi = NLMSG_DATA(nh);
+ size_t vlan_len, info_len, len = nh->nlmsg_len;
+ struct rtattr *rta, *info, *vlan;
+ int idx = -1, vid = -1;
+
+ *iface = NULL;
+
+ rta = IFLA_RTA(ifi);
+ while (RTA_OK(rta, len)) {
+ /* check if the interface is a vlan */
+ if (rta->rta_type == IFLA_LINKINFO) {
+ info = RTA_DATA(rta);
+ info_len = RTA_PAYLOAD(rta);
+
+ while (RTA_OK(info, info_len)) {
+ if (info->rta_type == IFLA_INFO_KIND &&
+ strcmp(RTA_DATA(info), "vlan"))
+ goto err;
+
+ if (info->rta_type == IFLA_INFO_DATA) {
+ vlan = RTA_DATA(info);
+ vlan_len = RTA_PAYLOAD(info);
+
+ while (RTA_OK(vlan, vlan_len)) {
+ if (vlan->rta_type == IFLA_VLAN_ID)
+ vid = *(int *)RTA_DATA(vlan);
+ vlan = RTA_NEXT(vlan, vlan_len);
+ }
+ }
+ info = RTA_NEXT(info, info_len);
+ }
+ }
+
+ /* extract the name of the "link" interface */
+ if (rta->rta_type == IFLA_LINK) {
+ idx = *(int *)RTA_DATA(rta);
+
+ *iface = malloc(IFNAMSIZ + 1);
+ if (!if_indextoname(idx, *iface))
+ goto err;
+ }
+ rta = RTA_NEXT(rta, len);
+ }
+
+ if (vid == -1)
+ goto err;
+
+ if (idx <= 0)
+ goto err;
+
+ return vid;
+err:
+ free(*iface);
+ return -1;
+}
+
+/**
+ * vlan_get_link_dump - receive and dump a get_link rtnl reply
+ * @sock: the socket to listen for the reply on
+ * @buf: buffer where the reply has to be dumped to
+ * @buflen: length of the buffer
+ *
+ * Returns the amount of dumped bytes
+ */
+static ssize_t vlan_get_link_dump(int sock, void *buf, size_t buflen)
+{
+ struct sockaddr_nl nladdr;
+ struct msghdr msg;
+ struct iovec iov;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&iov, 0, sizeof(iov));
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_controllen = 0;
+ msg.msg_control = NULL;
+ msg.msg_flags = 0;
+ msg.msg_name = &nladdr;
+ msg.msg_namelen = sizeof(nladdr);
+
+ iov.iov_len = buflen;
+ iov.iov_base = buf;
+
+ return recvmsg(sock, &msg, 0);
+}
+
+/**
+ * vlan_get_link_open - send a get_link request
+ * @ifname: the interface to query
+ *
+ * Returns 0 in case of success or a negative error code otherwise
+ */
+static int vlan_get_link_open(const char *ifname)
+{
+ struct {
+ struct nlmsghdr hdr;
+ struct ifinfomsg ifi;
+ /* attribute has to be NLMSG aligned */
+ struct rtattr rta_ifname __attribute__ ((aligned(NLMSG_ALIGNTO)));
+ char ifname[IFNAMSIZ + 1];
+ } nlreq;
+
+ memset(&nlreq, 0, sizeof(nlreq));
+ nlreq.hdr.nlmsg_len = sizeof(nlreq);
+ nlreq.hdr.nlmsg_type = RTM_GETLINK;
+ nlreq.hdr.nlmsg_flags = NLM_F_REQUEST;
+ nlreq.ifi.ifi_family = AF_UNSPEC;
+
+ nlreq.rta_ifname.rta_type = IFLA_IFNAME;
+ nlreq.rta_ifname.rta_len = IFNAMSIZ + 1;
+ strncpy(nlreq.ifname, ifname, IFNAMSIZ);
+
+ return rtnl_open(&nlreq.hdr, 0);
+}
+
+/**
+ * vlan_get_link - convert a VLAN interface into its parent one
+ * @ifname: the interface to convert
+ * @parent: buffer where the parent interface name will be written (allocated by
+ * this function)
+ *
+ * Returns the vlan identifier on success or -1 on error
+ */
+int vlan_get_link(const char *ifname, char **parent)
+{
+ int vid = -1, socknl;
+ void *buf = NULL;
+ size_t buflen;
+ ssize_t len;
+
+ buflen = 8192;
+ buf = malloc(buflen);
+ if (!buf)
+ goto err;
+
+ socknl = vlan_get_link_open(ifname);
+ if (socknl < 0)
+ goto err;
+
+ len = vlan_get_link_dump(socknl, buf, buflen);
+ if (len < 0)
+ goto err_sock;
+
+ vid = vlan_get_link_parse(buf, parent);
+
+err_sock:
+ close(socknl);
+err:
+ free(buf);
+ return vid;
+}
diff --git a/functions.h b/functions.h
index 522c607..14ba525 100644
--- a/functions.h
+++ b/functions.h
@@ -42,6 +42,7 @@ int write_file(const char *dir, const char *fname, const char *arg1,
const char *arg2);
struct ether_addr *translate_mac(char *mesh_iface, struct ether_addr *mac);
struct ether_addr *resolve_mac(const char *asc);
+int vlan_get_link(const char *ifname, char **parent);
extern char *line_ptr;
--
1.8.5.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [B.A.T.M.A.N.] [PATCHv2 next 3/3] batctl: add sys framework for VLAN support
2014-01-05 21:37 [B.A.T.M.A.N.] [PATCHv2 next 1/3] batctl: introduce rtnl_open() helper function Antonio Quartulli
2014-01-05 21:37 ` [B.A.T.M.A.N.] [PATCHv2 next 2/3] batctl: implement vlan-to-link helper functions Antonio Quartulli
@ 2014-01-05 21:37 ` Antonio Quartulli
1 sibling, 0 replies; 3+ messages in thread
From: Antonio Quartulli @ 2014-01-05 21:37 UTC (permalink / raw)
To: b.a.t.m.a.n; +Cc: Marco Dalla Torre, Antonio Quartulli
From: Marco Dalla Torre <marco.dallato@gmail.com>
Allow the batctl tool to take advantage of changes from commit
e4ff5c153dab054a6cd1c4132f87bc5e77127456 "add sys framework for VLAN"
recently added to batman-adv, so that users can execute commands in
a per VLAN fashion.
If no directory entry corresponding to the user-selected device is found
at the standard location for non VLAN interfaces
(/sys/class/net/${device}/mesh/), 'batctl' now looks into directory:
/sys/class/net/${base_device}/mesh/vlan${vid}
Information on VLAN devices (base device, vid) necessary to construct the
directory path is acquired by querying the netlink kernel module.
Where:
-${base_device}: the batman device on top of which the VLAN is sitting
-${device}: the device interface for the VLAN,
-${vid}: the identifier assigned to the VLAN.
If the user-selected command is not supported by the VLAN, an appropriate
error is shown.
Signed-off-by: Marco Dalla Torre <marco.dallato@gmail.com>
Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
---
main.c | 2 +-
man/batctl.8 | 4 ++--
sys.c | 15 +++++++++++++--
sys.h | 22 ++++++++++++----------
4 files changed, 28 insertions(+), 15 deletions(-)
diff --git a/main.c b/main.c
index aab2e11..a37c0b7 100644
--- a/main.c
+++ b/main.c
@@ -46,7 +46,7 @@ static void print_usage(void)
fprintf(stderr, "Usage: batctl [options] command|debug table [parameters]\n");
fprintf(stderr, "options:\n");
- fprintf(stderr, " \t-m mesh interface (default 'bat0')\n");
+ fprintf(stderr, " \t-m mesh interface or VLAN created on top of a mesh interface (default 'bat0')\n");
fprintf(stderr, " \t-h print this help (or 'batctl <command|debug table> -h' for the parameter help)\n");
fprintf(stderr, " \t-v print version\n");
fprintf(stderr, "\n");
diff --git a/man/batctl.8 b/man/batctl.8
index fafe735..b3b12bd 100644
--- a/man/batctl.8
+++ b/man/batctl.8
@@ -42,7 +42,7 @@ behaviour or using the B.A.T.M.A.N. advanced protocol.
.SH OPTIONS
.TP
.I \fBoptions:
-\-m specify mesh interface (default 'bat0')
+\-m specify mesh interface or VLAN created on top of a mesh interface (default 'bat0')
.br
\-h print general batctl help
.br
@@ -61,7 +61,7 @@ originator interval. The interval is in units of milliseconds.
.br
.IP "\fBap_isolation\fP|\fBap\fP [\fB0\fP|\fB1\fP]"
If no parameter is given the current ap isolation setting is displayed. Otherwise the parameter is used to enable or
-disable ap isolation.
+disable ap isolation. This command can be used in conjunction with "-m" option to target per VLAN configurations.
.br
.IP "\fBbridge_loop_avoidance\fP|\fBbl\fP [\fB0\fP|\fB1\fP]"
If no parameter is given the current bridge loop avoidance setting is displayed. Otherwise the parameter is used to enable
diff --git a/sys.c b/sys.c
index 2a508e2..5cebf52 100644
--- a/sys.c
+++ b/sys.c
@@ -372,8 +372,8 @@ static void settings_usage(int setting)
int handle_sys_setting(char *mesh_iface, int setting, int argc, char **argv)
{
- int optchar, res = EXIT_FAILURE;
- char *path_buff;
+ int vid, optchar, res = EXIT_FAILURE;
+ char *path_buff, *base_dev = NULL;
const char **ptr;
while ((optchar = getopt(argc, argv, "h")) != -1) {
@@ -387,10 +387,20 @@ int handle_sys_setting(char *mesh_iface, int setting, int argc, char **argv)
}
}
+ /* prepare the classic path */
path_buff = malloc(PATH_BUFF_LEN);
snprintf(path_buff, PATH_BUFF_LEN, SYS_BATIF_PATH_FMT, mesh_iface);
path_buff[PATH_BUFF_LEN - 1] = '\0';
+ /* if the specified interface is a VLAN then change the path to point
+ * to the proper "vlan%{vid}" subfolder in the sysfs tree.
+ */
+ vid = vlan_get_link(mesh_iface, &base_dev);
+ if (vid >= 0) {
+ snprintf(path_buff, PATH_BUFF_LEN, SYS_VLAN_PATH, base_dev, vid);
+ path_buff[PATH_BUFF_LEN - 1] = '\0';
+ }
+
if (argc == 1) {
res = read_file(path_buff, (char *)batctl_settings[setting].sysfs_name,
NO_FLAGS, 0, 0, 0);
@@ -425,6 +435,7 @@ write_file:
out:
free(path_buff);
+ free(base_dev);
return res;
}
diff --git a/sys.h b/sys.h
index 8934978..2cbbcfb 100644
--- a/sys.h
+++ b/sys.h
@@ -24,16 +24,18 @@
#include "main.h"
-#define SYS_BATIF_PATH_FMT "/sys/class/net/%s/mesh/"
-#define SYS_LOG_LEVEL "log_level"
-#define SYS_LOG "log"
-#define SYS_GW_MODE "gw_mode"
-#define SYS_GW_SEL "gw_sel_class"
-#define SYS_GW_BW "gw_bandwidth"
-#define SYS_IFACE_PATH "/sys/class/net"
-#define SYS_IFACE_DIR SYS_IFACE_PATH"/%s/"
-#define SYS_MESH_IFACE_FMT SYS_IFACE_PATH"/%s/batman_adv/mesh_iface"
-#define SYS_IFACE_STATUS_FMT SYS_IFACE_PATH"/%s/batman_adv/iface_status"
+#define SYS_BATIF_PATH_FMT "/sys/class/net/%s/mesh/"
+#define SYS_LOG_LEVEL "log_level"
+#define SYS_LOG "log"
+#define SYS_GW_MODE "gw_mode"
+#define SYS_GW_SEL "gw_sel_class"
+#define SYS_GW_BW "gw_bandwidth"
+#define SYS_IFACE_PATH "/sys/class/net"
+#define SYS_IFACE_DIR SYS_IFACE_PATH"/%s/"
+#define SYS_MESH_IFACE_FMT SYS_IFACE_PATH"/%s/batman_adv/mesh_iface"
+#define SYS_IFACE_STATUS_FMT SYS_IFACE_PATH"/%s/batman_adv/iface_status"
+#define SYS_VLAN_PATH SYS_IFACE_PATH"/%s/mesh/vlan%d/"
+#define VLAN_ID_MAX_LEN 4
enum batctl_settings_list {
BATCTL_SETTINGS_ORIG_INTERVAL,
--
1.8.5.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2014-01-05 21:37 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-01-05 21:37 [B.A.T.M.A.N.] [PATCHv2 next 1/3] batctl: introduce rtnl_open() helper function Antonio Quartulli
2014-01-05 21:37 ` [B.A.T.M.A.N.] [PATCHv2 next 2/3] batctl: implement vlan-to-link helper functions Antonio Quartulli
2014-01-05 21:37 ` [B.A.T.M.A.N.] [PATCHv2 next 3/3] batctl: add sys framework for VLAN support Antonio Quartulli
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.