batctl: rtnetlink interface manipulation + userspace icmp
v3 cover batctl: rtnetlink interface manipulation + userspace icmp
Hi,
I had to merge the ICMP and rtnetlink patchset [1] into one single patchset because the two remaining ICMP patches depend on the rtnetlink query functionality. This is already the biggest change to the patchset(s). Other minor things are:
* remove patchset already in master
* rebased patchset(s) on top of current master
* changed __unused to __maybe_unused
Kind regards,
Sven
[1] https://lists.open-mesh.org/pipermail/b.a.t.m.a.n/2016-July/015941.html
[2] https://lists.open-mesh.org/pipermail/b.a.t.m.a.n/2016-July/016046.html
Sven Eckelmann (9):
batctl: Use rtnl to query list of softif devices
batctl: Add command to create/destroy batman-adv interface
batctl: Use rtnl to add/remove interfaces
batctl: Parse interface arguments relative to last parsed option
batctl: Allow to disable automatic interface create/destroy
batctl: Move interface command to extra file
batctl: Move check_mesh_iface* to functions.c
batctl: Add helper to generate instant random bytes
batctl: Implement non-routing batadv_icmp in userspace
Makefile | 2 + functions.c | 248 +++++++++++++++++++++++ functions.h | 12 +- icmp_helper.c | 633 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ icmp_helper.h | 58 ++++++ interface.c | 457 ++++++++++++++++++++++++++++++++++++++++++ interface.h | 29 +++ main.c | 1 + man/batctl.8 | 7 +- netlink.c | 178 ++++++++++++++++- netlink.h | 3 + ping.c | 42 ++-- sys.c | 215 +------------------- sys.h | 3 - traceroute.c | 42 ++-- 15 files changed, 1654 insertions(+), 276 deletions(-)
PATCH v3 1/9 batctl: Use rtnl to query list of softif devices
The normal way of network related programs to query the state of interfaces is to use the rtnetlink. Most of these data can also be queried via sysfs but it is easier to use the same way for both retrieving the list of interfaces and modifying the list of interfaces.
---
v3:
- rebased on current master
v2:
- no change
--- functions.c | 64 +++++++++++++++++++++++++++++++++++ functions.h | 5 ++- sys.c | 111 +++++++++++++++++++++++++++++++++--------------------------- 3 files changed, 129 insertions(+), 51 deletions(-)
functions.c +64 -0
@@ -37,6 +37,7 @@#include <stdint.h> #include <linux/netlink.h> #include <net/ethernet.h> +#include <linux/if_link.h> #include <linux/rtnetlink.h> #include <linux/neighbour.h> #include <errno.h>
@@ -890,3 +891,66 @@ int print_routing_algos(void) err =debug_print_routing_algos ();return err; } + +int query_rtnl_link (int ifindex,nl_recvmsg_msg_cb_t func,void *arg) +{ +struct ifinfomsg rt_hdr = { + .ifi_family =IFLA_UNSPEC , + }; +struct nl_sock *sock; +struct nl_msg *msg; +struct nl_cb *cb; +int err =0 ; +int ret; + + sock =nl_socket_alloc (); +if (!sock) +return -ENOMEM ; + + ret =nl_connect (sock,NETLINK_ROUTE ); +if (ret <0 ) { + err = -ENOMEM ; + goto err_free_sock; + } + + cb =nl_cb_alloc (NL_CB_DEFAULT ); +if (!cb) { + err = -ENOMEM ; + goto err_free_sock; + } + +nl_cb_set (cb,NL_CB_VALID ,NL_CB_CUSTOM , func, arg); + + msg =nlmsg_alloc_simple (RTM_GETLINK ,NLM_F_REQUEST |NLM_F_DUMP ); +if (!msg) { + err = -ENOMEM ; + goto err_free_cb; + } + + ret =nlmsg_append (msg, &rt_hdr,sizeof (rt_hdr),NLMSG_ALIGNTO ); +if (ret <0 ) { + err = -ENOMEM ; + goto err_free_msg; + } + + ret =nla_put_u32 (msg,IFLA_MASTER , ifindex); +if (ret <0 ) { + err = -ENOMEM ; + goto err_free_msg; + } + + ret =nl_send_auto_complete (sock, msg); +if (ret <0 ) + goto err_free_msg; + +nl_recvmsgs (sock, cb); + +err_free_msg: +nlmsg_free (msg); +err_free_cb: +nl_cb_put (cb); +err_free_sock: +nl_socket_free (sock); + +return err; +}
functions.h +4 -1
@@ -23,6 +23,8 @@#define _BATCTL_FUNCTIONS_H#include <net/ethernet.h> +#include <netlink/netlink.h> +#include <netlink/handlers.h> #include <stddef.h>
@@ -43,7 +45,8 @@ int write_file(const char *dir, const char *fname, const char *arg1,struct ether_addr *translate_mac (const char *mesh_iface,const struct ether_addr *mac);struct ether_addr *resolve_mac (const char *asc); -int vlan_get_link (const char *ifname,char **parent); +int vlan_get_link (const char *ifname,char **parent);\ +int query_rtnl_link (int ifindex,nl_recvmsg_msg_cb_t func,void *arg);int print_routing_algos (void );extern char *line_ptr;
sys.c +61 -50
139 lines not on this page · raw message
Signature · 1 line
2.9.3
PATCH v3 2/9 batctl: Add command to create/destroy batman-adv interface
In reply to Sven EckelmannThe command "create" can be used to create a batman-adv interface without any interface attached. This is helpful when the interfaces should be configured independently of the first attached interface.
The command "destroy" can be used to destroy a batman-adv interface without going through all attached interfaces and delete them manually.
---
v3:
- rebased on current master
- changed __unused to __maybe_unused
v2:
- rename "new" command to "create" as requested by Linus Luessing and John Harrison
--- functions.c | 59 ++++++++++++++++++++++++ functions.h | 1 + man/batctl.8 | 3 ++ sys.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 201 insertions(+), 5 deletions(-)
functions.c +59 -0
@@ -954,3 +954,62 @@ err_free_sock:return err; } + +static int ack_errno_handler (struct sockaddr_nl *nla__maybe_unused , +struct nlmsgerr *nlerr, +void *arg) +{ +int *err = arg; + + *err = nlerr->error; + +return NL_STOP ; +} + +static int ack_wait_handler (struct nl_msg *msg__maybe_unused , +void *arg__maybe_unused ) +{ +return NL_STOP ; +} + +int netlink_simple_request (struct nl_msg *msg) +{ +struct nl_sock *sock; +struct nl_cb *cb; +int err =0 ; +int ret; + + sock =nl_socket_alloc (); +if (!sock) +return -ENOMEM ; + + ret =nl_connect (sock,NETLINK_ROUTE ); +if (ret <0 ) { + err = -ENOMEM ; + goto err_free_sock; + } + + cb =nl_cb_alloc (NL_CB_DEFAULT ); +if (!cb) { + err = -ENOMEM ; + goto err_free_sock; + } + +nl_cb_err (cb,NL_CB_CUSTOM , ack_errno_handler, &err); +nl_cb_set (cb,NL_CB_ACK ,NL_CB_CUSTOM , ack_wait_handler,NULL ); + + ret =nl_send_auto_complete (sock, msg); +if (ret <0 ) + goto err_free_cb; + +// ack_errno_handler sets err on errors + err =0 ; +nl_recvmsgs (sock, cb); + +err_free_cb: +nl_cb_put (cb); +err_free_sock: +nl_socket_free (sock); + +return err; +}
functions.h +1 -0
@@ -47,6 +47,7 @@ struct ether_addr *translate_mac(const char *mesh_iface,struct ether_addr *resolve_mac (const char *asc);int vlan_get_link (const char *ifname,char **parent);\int query_rtnl_link (int ifindex,nl_recvmsg_msg_cb_t func,void *arg); +int netlink_simple_request (struct nl_msg *msg);int print_routing_algos (void );extern char *line_ptr;
man/batctl.8 +3 -0
@@ -56,6 +56,9 @@ performances, is also included. If no parameter is given or the first parameter is neither "add" nor "del" the current interface settings are displayed. In order to add or delete interfaces specify "add" or "del" as first argument and append the interface names you wish to add or delete. Multiple interfaces can be specified. +.IP "\fBinterface\fP|\fBif\fP [\fBcreate\fP|\fBdestroy\fP]" +A batman-adv interface without attached interfaces can be created using "create". The parameter "destroy" can be used to +free all attached interfaces and remove batman-adv interface. .br .IP "\fBorig_interval\fP|\fBit\fP [\fBinterval\fP]" If no parameter is given the current originator interval setting is displayed otherwise the parameter is used to set the
sys.c +138 -5
170 lines not on this page · raw message
Signature · 1 line
2.9.3
PATCH v3 3/9 batctl: Use rtnl to add/remove interfaces
In reply to Sven EckelmannThe sysfs interface to add/remove interfaces to/from a batman-adv soft-interface was downgraded in batman-adv master to a second-class citizen. This was done because it has conceptional problems (for example locking of sysfs vs. locking of the network core code). The only direct way to modify network interfaces is rtnetlink. sysfs still exists but has to use workers which delay the actual add/del to a later point.
It is therefore prefered to use the modern rtnetlink. Only batman-adv versions older than v2013.2.0 (Linux 3.10) will not yet support the rtnl_link operations required for it to work.
---
v3:
- rebased on current master
v2:
- rename "new" command to "create" as requested by Linus Luessing and John Harrison
--- sys.c | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 145 insertions(+), 27 deletions(-)
sys.c +145 -27
@@ -199,6 +199,58 @@ static int print_interfaces(char *mesh_iface)return EXIT_SUCCESS ; } +struct count_interfaces_rtnl_arg { +int ifindex; +unsigned int count; +}; + +static int count_interfaces_rtnl_parse (struct nl_msg *msg,void *arg) +{ +struct count_interfaces_rtnl_arg *count_arg = arg; +struct nlattr *attrs[IFLA_MAX +1 ]; +struct ifinfomsg *ifm; +int ret; +int master; + + ifm =nlmsg_data (nlmsg_hdr (msg)); + ret =nlmsg_parse (nlmsg_hdr (msg),sizeof (*ifm), attrs,IFLA_MAX , + link_policy); +if (ret <0 ) + goto err; + +if (!attrs[IFLA_IFNAME ]) + goto err; + +if (!attrs[IFLA_MASTER ]) + goto err; + + master =nla_get_u32 (attrs[IFLA_MASTER ]); + +/* required on older kernels which don't prefilter the results */ +if (master != count_arg->ifindex) + goto err; + + count_arg->count++; + +err: +return NL_OK ; +} + +static unsigned int count_interfaces (char *mesh_iface) +{ +struct count_interfaces_rtnl_arg count_arg; + + count_arg.count =0 ; + count_arg.ifindex =if_nametoindex (mesh_iface); +if (!count_arg.ifindex) +return 0 ; + +query_rtnl_link (count_arg.ifindex, count_interfaces_rtnl_parse, + &count_arg); + +return count_arg.count; +} +static int create_interface (const char *mesh_iface) {struct ifinfomsg rt_hdr = {
@@ -283,11 +335,54 @@ err_free_msg:return err; } +static int set_master_interface (const char *iface,unsigned int ifmaster) +{ +struct ifinfomsg rt_hdr = { + .ifi_family =IFLA_UNSPEC , + }; +struct nl_msg *msg; +int err =0 ; +int ret; + + msg =nlmsg_alloc_simple (RTM_SETLINK ,NLM_F_REQUEST |NLM_F_ACK ); +if (!msg) { +return -ENOMEM ; + } + + ret =nlmsg_append (msg, &rt_hdr,sizeof (rt_hdr),NLMSG_ALIGNTO ); +if (ret <0 ) { + err = -ENOMEM ; + goto err_free_msg; + } + + ret =nla_put_string (msg,IFLA_IFNAME , iface); +if (ret <0 ) { + err = -ENOMEM ; + goto err_free_msg; + } + + ret =nla_put_u32 (msg,IFLA_MASTER , ifmaster); +if (ret <0 ) { + err = -ENOMEM ; + goto err_free_msg; + } + + err =netlink_simple_request (msg); + +err_free_msg: +nlmsg_free (msg); + +return err; +} +int interface (char *mesh_iface,int argc,char **argv) { -char *path_buff; -int i, res, optchar; +int i, optchar;int ret; +unsigned int ifindex; +unsigned int ifmaster; +const char *long_op; +unsigned int cnt;while ((optchar =getopt (argc, argv,"h" )) !=-1 ) {switch (optchar) {
@@ -363,46 +458,69 @@ int interface(char *mesh_iface, int argc, char **argv)break ; } - path_buff =malloc (PATH_BUFF_LEN ); -if (!path_buff) { -fprintf (stderr,"Error - could not allocate path buffer: out of memory ?\n" ); - goto err; - } +/* get index of batman-adv interface - or try to create it */ + ifmaster =if_nametoindex (mesh_iface); +if (!ifmaster && argv[1 ][0 ] =='a' ) { + ret =create_interface (mesh_iface); +if (ret <0 ) { +fprintf (stderr, +"Error - failed to create batman-adv interface: %s\n" , +strerror (-ret)); + goto err; + } -for (i =2 ; i < argc; i++) { -snprintf (path_buff,PATH_BUFF_LEN ,SYS_MESH_IFACE_FMT , argv[i]); + ifmaster =if_nametoindex (mesh_iface); + } -if (!file_exists (path_buff)) { -snprintf (path_buff,PATH_BUFF_LEN ,SYS_IFACE_DIR , argv[i]); +if (!ifmaster) { + ret = -ENODEV ; +fprintf (stderr, +"Error - failed to find batman-adv interface: %s\n" , +strerror (-ret)); + goto err; + } -if (!file_exists (path_buff)) { -fprintf (stderr,"Error - interface does not exist: %s\n" , argv[i]); -continue ; - } +/* make sure that batman-adv is loaded or was loaded by create_interface */ +if (!file_exists (module_ver_path)) { +fprintf (stderr,"Error - batman-adv module has not been loaded\n" ); + goto err; + } -if (!file_exists (module_ver_path)) { -fprintf (stderr,"Error - batman-adv module has not been loaded\n" ); - goto err_buff; - } +for (i =2 ; i < argc; i++) { + ifindex =if_nametoindex (argv[i]); -fprintf (stderr,"Error - interface type not supported by batman-adv: %s\n" , argv[i]); +if (!ifindex) { +fprintf (stderr,"Error - interface does not exist: %s\n" , argv[i]);continue ; }if (argv[1 ][0 ] =='a' ) - res =write_file ("" , path_buff, mesh_iface,NULL ); + ifindex = ifmaster;else - res =write_file ("" , path_buff,"none" ,NULL ); + ifindex =0 ; -if (res !=EXIT_SUCCESS ) - goto err_buff; + ret =set_master_interface (argv[i], ifindex); +if (ret <0 ) { +if (argv[1 ][0 ] =='a' ) + long_op ="add" ; +else + long_op ="delete" ; + +fprintf (stderr,"Error - failed to %s interface %s: %s\n" , + long_op, argv[i],strerror (-ret)); + goto err; + } + } + +/* check if there is no interface left and then destroy mesh_iface */ +if (argv[1 ][0 ] =='d' ) { + cnt =count_interfaces (mesh_iface); +if (cnt ==0 ) +destroy_interface (mesh_iface); } -free (path_buff);return EXIT_SUCCESS ; -err_buff: -free (path_buff); err:return EXIT_FAILURE ; }
Signature · 1 line
2.9.3
PATCH v3 4/9 batctl: Parse interface arguments relative to last parsed option
In reply to Sven EckelmannArguments may be added between "interface" and the subcommands "add" and "del". Thus is should not be hardcoded which positions of argv the subcommands start and instead the information from getopt should be used to calculate the correct position.
---
v3:
- rebased on current master
v2:
- rename "new" command to "create" as requested by Linus Luessing and John Harrison
--- sys.c | 51 ++++++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 23 deletions(-)
sys.c +28 -23
@@ -383,6 +383,8 @@ int interface(char *mesh_iface, int argc, char **argv)unsigned int ifmaster;const char *long_op;unsigned int cnt; +int rest_argc; +char **rest_argv;while ((optchar =getopt (argc, argv,"h" )) !=-1 ) {switch (optchar) {
@@ -395,38 +397,41 @@ int interface(char *mesh_iface, int argc, char **argv) } } -if (argc ==1 ) + rest_argc = argc - optind; + rest_argv = &argv[optind]; + +if (rest_argc ==0 )return print_interfaces (mesh_iface); -if ((strcmp (argv[1 ],"add" ) !=0 ) && (strcmp (argv[1 ],"a" ) !=0 ) && - (strcmp (argv[1 ],"del" ) !=0 ) && (strcmp (argv[1 ],"d" ) !=0 ) && - (strcmp (argv[1 ],"create" ) !=0 ) && (strcmp (argv[1 ],"c" ) !=0 ) && - (strcmp (argv[1 ],"destroy" ) !=0 ) && (strcmp (argv[1 ],"D" ) !=0 )) { -fprintf (stderr,"Error - unknown argument specified: %s\n" , argv[1 ]); +if ((strcmp (rest_argv[0 ],"add" ) !=0 ) && (strcmp (rest_argv[0 ],"a" ) !=0 ) && + (strcmp (rest_argv[0 ],"del" ) !=0 ) && (strcmp (rest_argv[0 ],"d" ) !=0 ) && + (strcmp (rest_argv[0 ],"create" ) !=0 ) && (strcmp (rest_argv[0 ],"c" ) !=0 ) && + (strcmp (rest_argv[0 ],"destroy" ) !=0 ) && (strcmp (rest_argv[0 ],"D" ) !=0 )) { +fprintf (stderr,"Error - unknown argument specified: %s\n" , rest_argv[0 ]);interface_usage (); goto err; } -if (strcmp (argv[1 ],"destroy" ) ==0 ) - argv[1 ][0 ] ='D' ; +if (strcmp (rest_argv[0 ],"destroy" ) ==0 ) + rest_argv[0 ][0 ] ='D' ; -switch (argv[1 ][0 ]) { +switch (rest_argv[0 ][0 ]) {case 'a' :case 'd' : -if (argc ==2 ) { +if (rest_argc ==1 ) {fprintf (stderr,"Error - missing interface name(s) after '%s'\n" , - argv[1 ]); + rest_argv[0 ]);interface_usage (); goto err; }break ;case 'c' :case 'D' : -if (argc !=2 ) { +if (rest_argc !=1 ) {fprintf (stderr,"Error - extra parameter after '%s'\n" , - argv[1 ]); + rest_argv[0 ]);interface_usage (); goto err; }
@@ -435,7 +440,7 @@ int interface(char *mesh_iface, int argc, char **argv)break ; } -switch (argv[1 ][0 ]) { +switch (rest_argv[0 ][0 ]) {case 'c' : ret =create_interface (mesh_iface);if (ret <0 ) {
@@ -460,7 +465,7 @@ int interface(char *mesh_iface, int argc, char **argv)/* get index of batman-adv interface - or try to create it */ ifmaster =if_nametoindex (mesh_iface); -if (!ifmaster && argv[1 ][0 ] =='a' ) { +if (!ifmaster && rest_argv[0 ][0 ] =='a' ) { ret =create_interface (mesh_iface);if (ret <0 ) { fprintf(stderr,
@@ -486,34 +491,34 @@ int interface(char *mesh_iface, int argc, char **argv) goto err; } -for (i =2 ; i < argc; i++) { - ifindex =if_nametoindex (argv[i]); +for (i =1 ; i < rest_argc; i++) { + ifindex =if_nametoindex (rest_argv[i]);if (!ifindex) { -fprintf (stderr,"Error - interface does not exist: %s\n" , argv[i]); +fprintf (stderr,"Error - interface does not exist: %s\n" , rest_argv[i]);continue ; } -if (argv[1 ][0 ] =='a' ) +if (rest_argv[0 ][0 ] =='a' ) ifindex = ifmaster;else ifindex =0 ; - ret =set_master_interface (argv[i], ifindex); + ret =set_master_interface (rest_argv[i], ifindex);if (ret <0 ) { -if (argv[1 ][0 ] =='a' ) +if (rest_argv[0 ][0 ] =='a' ) long_op ="add" ;else long_op ="delete" ;fprintf (stderr,"Error - failed to %s interface %s: %s\n" , - long_op, argv[i],strerror (-ret)); + long_op, rest_argv[i],strerror (-ret)); goto err; } }/* check if there is no interface left and then destroy mesh_iface */ -if (argv[1 ][0 ] =='d' ) { +if (rest_argv[0 ][0 ] =='d' ) { cnt =count_interfaces (mesh_iface);if (cnt ==0 )destroy_interface (mesh_iface);
Signature · 1 line
2.9.3
PATCH v3 5/9 batctl: Allow to disable automatic interface create/destroy
In reply to Sven EckelmannUsers may not want to lose their configured batman-adv soft-interface when they remove a single interface from it. The default configuration may not working well enough in the network setup of the user and thus it should be possible to avoid that it gets reset to it when a new interface is added after the last one was removed.
This can be done by avoiding automatic creation of an interface when the command "add" is used together with the option "-M". The add would fail when the soft-interface disappeared for some reason and thus the soft-interface would not be created again with the default configuration. But more importantly, the "del" command can be informed with the option "-M" to not try to remove the soft-interface in the first place.
---
v3:
- rebased on current master
v2:
- rename "new" command to "create" as requested by Linus Luessing and John Harrison
--- man/batctl.8 | 4 +++- sys.c | 12 +++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-)
man/batctl.8 +3 -1
@@ -52,10 +52,12 @@ performances, is also included. .br .TP .I \fBcommands: -.IP "\fBinterface\fP|\fBif\fP [\fBadd\fP|\fBdel iface(s)\fP]" +.IP "\fBinterface\fP|\fBif\fP [\fB-M\fP] [\fBadd\fP|\fBdel iface(s)\fP]" If no parameter is given or the first parameter is neither "add" nor "del" the current interface settings are displayed. In order to add or delete interfaces specify "add" or "del" as first argument and append the interface names you wish to add or delete. Multiple interfaces can be specified. +The "\-M" option tells batctl to not automatically create the batman-adv interface on "add" or to destroy it when "del" +removed all interfaces which belonged to it. .IP "\fBinterface\fP|\fBif\fP [\fBcreate\fP|\fBdestroy\fP]" A batman-adv interface without attached interfaces can be created using "create". The parameter "destroy" can be used to free all attached interfaces and remove batman-adv interface.
sys.c +9 -3
@@ -22,6 +22,7 @@#include <unistd.h> #include <stdio.h> +#include <stdbool.h> #include <stdlib.h> #include <string.h> #include <errno.h>
@@ -122,6 +123,7 @@ static void interface_usage(void)fprintf (stderr,"Usage: batctl [options] interface [parameters] [add|del iface(s)]\n" );fprintf (stderr," batctl [options] interface [parameters] [create|destroy]\n" );fprintf (stderr,"parameters:\n" ); +fprintf (stderr," \t -M disable automatic creation/removal of batman-adv interface\n" );fprintf (stderr," \t -h print this help\n" ); }
@@ -385,12 +387,16 @@ int interface(char *mesh_iface, int argc, char **argv)unsigned int cnt;int rest_argc;char **rest_argv; +bool manual_mode = false; -while ((optchar =getopt (argc, argv,"h" )) !=-1 ) { +while ((optchar =getopt (argc, argv,"hM" )) !=-1 ) {switch (optchar) {case 'h' :interface_usage ();return EXIT_SUCCESS ; +case 'M' : + manual_mode = true; +break ;default :interface_usage ();return EXIT_FAILURE ;
@@ -465,7 +471,7 @@ int interface(char *mesh_iface, int argc, char **argv)/* get index of batman-adv interface - or try to create it */ ifmaster =if_nametoindex (mesh_iface); -if (!ifmaster && rest_argv[0 ][0 ] =='a' ) { +if (!manual_mode && !ifmaster && rest_argv[0 ][0 ] =='a' ) { ret =create_interface (mesh_iface);if (ret <0 ) { fprintf(stderr,
@@ -518,7 +524,7 @@ int interface(char *mesh_iface, int argc, char **argv) }/* check if there is no interface left and then destroy mesh_iface */ -if (rest_argv[0 ][0 ] =='d' ) { +if (!manual_mode && rest_argv[0 ][0 ] =='d' ) { cnt =count_interfaces (mesh_iface);if (cnt ==0 )destroy_interface (mesh_iface);
Signature · 1 line
2.9.3
PATCH v3 6/9 batctl: Move interface command to extra file
In reply to Sven EckelmannThe interface command has nothing to do anymore more with all the other configuration in sysfs. Thus all the "interface" command functions should be placed in a separate file.
---
v3:
- rebased on current master
v2:
- rename "new" command to "create" as requested by Linus Luessing and John Harrison
--- Makefile | 1 + functions.h | 2 + interface.c | 457 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ interface.h | 29 ++++ main.c | 1 + sys.c | 420 ------------------------------------------------------- sys.h | 1 - 7 files changed, 490 insertions(+), 421 deletions(-) create mode 100644 interface.c create mode 100644 interface.h
Makefile +1 -0
@@ -30,6 +30,7 @@ OBJ += debug.o OBJ += functions.o OBJ += genl.o OBJ += hash.o +OBJ += interface.o OBJ += ioctl.o OBJ += main.o OBJ += netlink.o
functions.h +2 -0
@@ -31,6 +31,8 @@#define ETH_STR_LEN 17#define BATMAN_ADV_TAG "batman-adv:" +#define PATH_BUFF_LEN 200 +/* return time delta from start to end in milliseconds */ void start_timer (void );double end_timer (void );
interface.c new file +457 -0
457 lines not on this page · raw message
interface.h new file +29 -0
@@ -0,0 +1,29 @@ +/* +* Copyright (C) 2009-2016 B.A.T.M.A.N. contributors: +* +* Marek Lindner <[email protected]> +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +* 02110-1301, USA +* +*/ + +#ifndef _BATCTL_INTERFACE_H +#define _BATCTL_INTERFACE_H + +#include "main.h" + +int interface (char *mesh_iface,int argc,char **argv); + +#endif
main.c +1 -0
@@ -29,6 +29,7 @@#include "main.h" #include "sys.h" #include "debug.h" +#include "interface.h" #include "ping.h" #include "translate.h" #include "traceroute.h"
sys.c +0 -420
432 lines not on this page · raw message
sys.h +0 -1
@@ -70,7 +70,6 @@ extern const char *sysfs_param_enable[];extern const char *sysfs_param_server[];extern const struct settings_data batctl_settings[BATCTL_SETTINGS_NUM ]; -int interface (char *mesh_iface,int argc,char **argv);int handle_loglevel (char *mesh_iface,int argc,char **argv);int handle_sys_setting (char *mesh_iface,int setting,int argc,char **argv);int handle_gw_setting (char *mesh_iface,int argc,char **argv);
Signature · 1 line
2.9.3
PATCH v3 7/9 batctl: Move check_mesh_iface* to functions.c
In reply to Sven EckelmannThe check_mesh_iface* functions are not used to modify anything in sysfs. So they are better placed in the common/shared functions file than in sys.c.
---
v3:
- rebased on current master
v2:
- no change
--- functions.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ functions.h | 2 ++ sys.c | 56 -------------------------------------------------------- sys.h | 2 -- 4 files changed, 61 insertions(+), 58 deletions(-)
functions.c +59 -0
@@ -32,6 +32,7 @@#include <string.h> #include <errno.h> #include <fcntl.h> +#include <dirent.h> #include <sys/time.h> #include <netinet/in.h> #include <stdint.h>
@@ -57,6 +58,8 @@#include "debugfs.h" #include "netlink.h" +#define PATH_BUFF_LEN 200 +static struct timespec start_time;static char *host_name;char *line_ptr =NULL ;
@@ -1013,3 +1016,59 @@ err_free_sock:return err; } + +int check_mesh_iface (char *mesh_iface) +{ +char *base_dev =NULL ; +char path_buff[PATH_BUFF_LEN ]; +int ret =-1 , vid; +DIR *dir; + +/* use the parent interface if this is a VLAN */ + vid =vlan_get_link (mesh_iface, &base_dev); +if (vid >=0 ) +snprintf (path_buff,PATH_BUFF_LEN ,SYS_VLAN_PATH , base_dev, vid); +else +snprintf (path_buff,PATH_BUFF_LEN ,SYS_BATIF_PATH_FMT , mesh_iface); + +/* try to open the mesh sys directory */ + dir =opendir (path_buff); +if (!dir) + goto out; + +closedir (dir); + + ret =0 ; +out: +if (base_dev) +free (base_dev); + +return ret; +} + +int check_mesh_iface_ownership (char *mesh_iface,char *hard_iface) +{ +char path_buff[PATH_BUFF_LEN ]; +int res; + +/* check if this device actually belongs to the mesh interface */ +snprintf (path_buff,sizeof (path_buff),SYS_MESH_IFACE_FMT , hard_iface); + res =read_file ("" , path_buff,USE_READ_BUFF |SILENCE_ERRORS ,0 ,0 ,0 ); +if (res !=EXIT_SUCCESS ) { +fprintf (stderr,"Error - the directory '%s' could not be read: %s\n" , + path_buff,strerror (errno)); +fprintf (stderr,"Is the batman-adv module loaded and sysfs mounted ?\n" ); +return EXIT_FAILURE ; + } + +if (line_ptr[strlen (line_ptr) -1 ] =='\n' ) + line_ptr[strlen (line_ptr) -1 ] ='\0' ; + +if (strcmp (line_ptr, mesh_iface) !=0 ) { +fprintf (stderr,"Error - interface %s is part of batman network %s, not %s\n" , + hard_iface, line_ptr, mesh_iface); +return EXIT_FAILURE ; + } + +return EXIT_SUCCESS ; +}
functions.h +2 -0
@@ -50,6 +50,8 @@ struct ether_addr *resolve_mac(const char *asc);int vlan_get_link (const char *ifname,char **parent);\int query_rtnl_link (int ifindex,nl_recvmsg_msg_cb_t func,void *arg);int netlink_simple_request (struct nl_msg *msg); +int check_mesh_iface (char *mesh_iface); +int check_mesh_iface_ownership (char *mesh_iface,char *hard_iface);int print_routing_algos (void );extern char *line_ptr;
sys.c +0 -56
59 lines not on this page · raw message
sys.h +0 -2
@@ -74,7 +74,5 @@ int handle_loglevel(char *mesh_iface, int argc, char **argv);int handle_sys_setting (char *mesh_iface,int setting,int argc,char **argv);int handle_gw_setting (char *mesh_iface,int argc,char **argv);int handle_ra_setting (int argc,char **argv); -int check_mesh_iface (char *mesh_iface); -int check_mesh_iface_ownership (char *mesh_iface,char *hard_iface);#endif
Signature · 1 line
2.9.3
PATCH v3 8/9 batctl: Add helper to generate instant random bytes
In reply to Sven EckelmannLinux provides different ways to get instant random bytes. These are not all supported on all systems and thus a fallback may have to be used. Abstract all this in a single function which can be used from different parts of the code.
The current implementations are
* get random data from urandom pool via SYS_getrandom syscall
* get random data from reading /dev/urandom
* fallback to per-program prng initialized via the current time (seconds + nanoseconds)
All are tried in this order in hope to get a high quality random number source before falling back to some really low quality one.
---
v3:
- rebased on current master
- changed __unused to __maybe_unused
- integrated in rtnl patchset due to dependencies
--- functions.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ functions.h | 2 ++ 2 files changed, 68 insertions(+)
functions.c +66 -0
@@ -41,6 +41,7 @@#include <linux/if_link.h> #include <linux/rtnetlink.h> #include <linux/neighbour.h> +#include <sys/syscall.h> #include <errno.h> #include <net/if.h> #include <netlink/socket.h>
@@ -1072,3 +1073,68 @@ int check_mesh_iface_ownership(char *mesh_iface, char *hard_iface)return EXIT_SUCCESS ; } + +static int get_random_bytes_syscall (void *buf__maybe_unused , +size_t buflen__maybe_unused ) +{ +#ifdef SYS_getrandom +return syscall (SYS_getrandom, buf, buflen,0 ); +#else +return -EOPNOTSUPP ; +#endif +} + +static int get_random_bytes_urandom (void *buf,size_t buflen) +{ +int fd; +ssize_t r; + + fd =open ("/dev/urandom" ,O_RDONLY ); +if (fd <0 ) +return -EOPNOTSUPP ; + + r =read (fd, buf, buflen); +close (fd); +if (r <0 ) +return -EOPNOTSUPP ; + +if ((size_t )r != buflen) +return -EOPNOTSUPP ; + +return 0 ; +} + +static int get_random_bytes_fallback (void *buf,size_t buflen) +{ +struct timespec now; +static int initialized =0 ; +size_t i; +uint8_t *bufc = buf; + +/* this is not a good source for randomness */ +if (!initialized) { +clock_gettime (CLOCK_MONOTONIC , &now); +srand (now.tv_sec ^ now.tv_nsec); + initialized =1 ; + } + +for (i =0 ; i < buflen; i++) + bufc[i] =rand () &0xff ; + +return 0 ; +} + +void get_random_bytes (void *buf,size_t buflen) +{ +int ret; + + ret =get_random_bytes_syscall (buf, buflen); +if (ret != -EOPNOTSUPP ) +return ; + + ret =get_random_bytes_urandom (buf, buflen); +if (ret != -EOPNOTSUPP ) +return ; + +get_random_bytes_fallback (buf, buflen); +}
functions.h +2 -0
@@ -53,6 +53,8 @@ int netlink_simple_request(struct nl_msg *msg);int check_mesh_iface (char *mesh_iface);int check_mesh_iface_ownership (char *mesh_iface,char *hard_iface); +void get_random_bytes (void *buf,size_t buflen); +int print_routing_algos (void );extern char *line_ptr;
Signature · 1 line
2.9.3
PATCH v3 9/9 batctl: Implement non-routing batadv_icmp in userspace
In reply to Sven EckelmannThe current endpoint for batadv_icmp* is implemented in the kernel module and can be accessed via debugfs. But the debugfs cannot be accessed from non-default netns or when debugfs is disabled. Thus it has be possible to use it via the netlink infrastructure to make it compatible with future setups.
The use of the socket file is completely removed and instead raw sockets with BPF filters are used to send/receive batadv_icmp_packet* directly. All information about interfaces and available originators are received via rtnetlink and the batman-adv netlink.
The originators debugfs file is used when the batman-adv netlink commands are not available. The routing of batadv_icmp_packets is still done inside the kernel module.
---
v3:
- rebased on current master
- integrated in rtnl patchset due to dependencies
--- Makefile | 1 + icmp_helper.c | 633 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ icmp_helper.h | 58 ++++++ netlink.c | 178 ++++++++++++++++- netlink.h | 3 + ping.c | 42 ++-- traceroute.c | 42 ++-- 7 files changed, 895 insertions(+), 62 deletions(-) create mode 100644 icmp_helper.c create mode 100644 icmp_helper.h
Makefile +1 -0
@@ -30,6 +30,7 @@ OBJ += debug.o OBJ += functions.o OBJ += genl.o OBJ += hash.o +OBJ += icmp_helper.o OBJ += interface.o OBJ += ioctl.o OBJ += main.o
icmp_helper.c new file +633 -0
633 lines not on this page · raw message
icmp_helper.h new file +58 -0
58 lines not on this page · raw message
netlink.c +175 -3
199 lines not on this page · raw message
netlink.h +3 -0
@@ -47,6 +47,9 @@ int netlink_print_bla_backbone(char *mesh_iface, char *orig_iface, int read_opt,int translate_mac_netlink (const char *mesh_iface,const struct ether_addr *mac,struct ether_addr *mac_out); +int get_nexthop_netlink (const char *mesh_iface,const struct ether_addr *mac, +uint8_t *nexthop,char *ifname); +int get_primarymac_netlink (const char *mesh_iface,uint8_t *primarymac);extern struct nla_policy batadv_netlink_policy[];
ping.c +13 -29
95 lines not on this page · raw message
traceroute.c +12 -30
85 lines not on this page · raw message
Signature · 1 line
2.9.3
Simon Wunderlich
AppliedQuoted 10 lines · CEST Sven Eckelmann
Hi,
I had to merge the ICMP and rtnetlink patchset [1] into one single patchset because the two remaining ICMP patches depend on the rtnetlink query functionality. This is already the biggest change to the patchset(s). Other minor things are:
* remove patchset already in master
* rebased patchset(s) on top of current master
* changed__unusedto__maybe_unused
Applied in 60e519b..4bd751e
Thanks,
Simon