Any comments on this? Saves can interfaces users from compiling iproute2 ;-)

Niko

On Tue, 9 Aug 2022, Nikolaus Voss wrote:

This is the minimum needed to set up SocketCAN interfaces.
Setting the bitrate is usually required before upping the device, e.g.

 ip link set can0 type can bitrate 1000000
 ip link set up can0

iproute2 supports more options to "type can" but these are not
mandatory for using the device.

Signed-off-by: Nikolaus Voss <[email protected]>
---
networking/ip.c                    |  2 +-
networking/libiproute/iplink.c     | 57 ++++++++++++++++++++++++++++--
networking/libiproute/libnetlink.c | 14 ++++++++
networking/libiproute/libnetlink.h |  5 +++
4 files changed, 75 insertions(+), 3 deletions(-)

diff --git a/networking/ip.c b/networking/ip.c
index 7c3208699..f0159912a 100644
--- a/networking/ip.c
+++ b/networking/ip.c
@@ -152,7 +152,7 @@
//usage:#define iplink_trivial_usage
//usage:       /*Usage:iplink*/"set IFACE [up|down] [arp on|off] [multicast 
on|off]\n"
//usage:       "   [promisc on|off] [mtu NUM] [name NAME] [qlen NUM] [address 
MAC]\n"
-//usage:       "  [master IFACE | nomaster] [netns PID]"
+//usage:       "  [master IFACE | nomaster] [netns PID] [type can bitrate NUM]"
// * short help shows only "set" command, long help continues (with just one 
"\n")
// * and shows all other commands:
//usage:#define iplink_full_usage "\n"
diff --git a/networking/libiproute/iplink.c b/networking/libiproute/iplink.c
index 68d199044..c751087d8 100644
--- a/networking/libiproute/iplink.c
+++ b/networking/libiproute/iplink.c
@@ -10,6 +10,7 @@
#include <netpacket/packet.h>
#include <netinet/if_ether.h>

+#include <linux/can/netlink.h>
#include <linux/if_vlan.h>
#include "ip_common.h"  /* #include "libbb.h" is inside */
#include "rt_names.h"
@@ -241,6 +242,55 @@ static void die_must_be_on_off(const char *msg)
        bb_error_msg_and_die("argument of \"%s\" must be \"on\" or \"off\"", 
msg);
}

+/* Return value becomes exitcode. It's okay to not return at all */
+static int do_set_type(char **argv, char *dev)
+{
+       struct rtnl_handle rth;
+       struct {
+               struct nlmsghdr  n;
+               struct ifinfomsg i;
+               char             buf[1024];
+       } req;
+       struct rtattr *linkinfo;
+       struct rtattr *data;
+
+       memset(&req, 0, sizeof(req));
+       req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+       req.n.nlmsg_flags = NLM_F_REQUEST;
+       req.n.nlmsg_type = RTM_NEWLINK;
+       req.i.ifi_family = preferred_family;
+
+       xrtnl_open(&rth);
+       req.i.ifi_index = xll_name_to_index(dev);
+       linkinfo = addattr_nest(&req.n, sizeof(req), IFLA_LINKINFO);
+
+       if (!strcmp(*argv, "can")) {
+               struct can_bittiming bt = { 0 };
+
+               addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, *argv,
+                         strlen(*argv));
+               data = addattr_nest(&req.n, sizeof(req), IFLA_INFO_DATA);
+               NEXT_ARG();
+               if (!strcmp(*argv, "bitrate")) {
+                       NEXT_ARG();
+                       bt.bitrate = get_u32(*argv, "bitrate");
+                       addattr_l(&req.n, sizeof(req), IFLA_CAN_BITTIMING, &bt,
+                                 sizeof(bt));
+               } else  {
+                       bb_error_msg_and_die("arg \"%s\" unkown", *argv);
+               }
+               addattr_nest_end(&req.n, data);
+       } else {
+               invarg_1_to_2(*argv, "type");
+       }
+       addattr_nest_end(&req.n, linkinfo);
+
+       if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
+               xfunc_die();
+
+       return 0;
+}
+
/* Return value becomes exitcode. It's okay to not return at all */
static int do_set(char **argv)
{
@@ -260,11 +310,11 @@ static int do_set(char **argv)
        static const char keywords[] ALIGN1 =
                "up\0""down\0""name\0""mtu\0""qlen\0""multicast\0"
                "arp\0""promisc\0""address\0""netns\0"
-               "master\0""nomaster\0"
+               "master\0""nomaster\0" "type\0"
                "dev\0" /* must be last */;
        enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_qlen, ARG_multicast,
                ARG_arp, ARG_promisc, ARG_addr, ARG_netns,
-               ARG_master, ARG_nomaster,
+               ARG_master, ARG_nomaster, ARG_type,
                ARG_dev };
        enum { PARM_on = 0, PARM_off };
        smalluint key;
@@ -304,6 +354,9 @@ static int do_set(char **argv)
                } else if (key == ARG_netns) {
                        NEXT_ARG();
                        netns = get_unsigned(*argv, "netns");
+               } else if (key == ARG_type) {
+                       NEXT_ARG();
+                       return do_set_type(argv, dev);
                } else if (key >= ARG_dev) {
                        /* ^^^^^^ ">=" here results in "dev IFACE" treated as 
default */
                        if (key == ARG_dev) {
diff --git a/networking/libiproute/libnetlink.c 
b/networking/libiproute/libnetlink.c
index 7e3473a1c..5b6273245 100644
--- a/networking/libiproute/libnetlink.c
+++ b/networking/libiproute/libnetlink.c
@@ -390,6 +390,20 @@ int FAST_FUNC addattr_l(struct nlmsghdr *n, int maxlen, 
int type, void *data, in
        return 0;
}

+struct rtattr * FAST_FUNC addattr_nest(struct nlmsghdr *n, int maxlen, int 
type)
+{
+       struct rtattr *nest = NLMSG_TAIL(n);
+
+       addattr_l(n, maxlen, type, NULL, 0);
+       return nest;
+}
+
+int FAST_FUNC addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest)
+{
+       nest->rta_len = (void *)NLMSG_TAIL(n) - (void *)nest;
+       return n->nlmsg_len;
+}
+
int FAST_FUNC rta_addattr32(struct rtattr *rta, int maxlen, int type, uint32_t 
data)
{
        int len = RTA_LENGTH(4);
diff --git a/networking/libiproute/libnetlink.h 
b/networking/libiproute/libnetlink.h
index 1b082e019..b7eefa1e5 100644
--- a/networking/libiproute/libnetlink.h
+++ b/networking/libiproute/libnetlink.h
@@ -54,11 +54,16 @@ static ALWAYS_INLINE void rtnl_send(struct rtnl_handle 
*rth, const void *buf, in

extern int addattr32(struct nlmsghdr *n, int maxlen, int type, uint32_t data) 
FAST_FUNC;
extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int 
alen) FAST_FUNC;
+extern struct rtattr * addattr_nest(struct nlmsghdr *n, int maxlen, int type) 
FAST_FUNC;
+extern int addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest) FAST_FUNC;
extern int rta_addattr32(struct rtattr *rta, int maxlen, int type, uint32_t 
data) FAST_FUNC;
extern int rta_addattr_l(struct rtattr *rta, int maxlen, int type, void *data, 
int alen) FAST_FUNC;

extern void parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int 
len) FAST_FUNC;

+#define NLMSG_TAIL(nmsg) \
+       ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
+
POP_SAVED_FUNCTION_VISIBILITY

#endif

_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to