From patchwork Thu Aug 4 13:09:32 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Aring X-Patchwork-Id: 9263623 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 3266960754 for ; Thu, 4 Aug 2016 13:11:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 24078283E1 for ; Thu, 4 Aug 2016 13:11:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 18D2028409; Thu, 4 Aug 2016 13:11:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A1BEB283E1 for ; Thu, 4 Aug 2016 13:11:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756650AbcHDNLP (ORCPT ); Thu, 4 Aug 2016 09:11:15 -0400 Received: from metis.ext.4.pengutronix.de ([92.198.50.35]:41189 "EHLO metis.ext.4.pengutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758604AbcHDNLO (ORCPT ); Thu, 4 Aug 2016 09:11:14 -0400 Received: from gallifrey.ext.pengutronix.de ([2001:67c:670:201:5054:ff:fe8d:eefb] helo=omega.localdomain) by metis.ext.pengutronix.de with esmtp (Exim 4.80) (envelope-from ) id 1bVIP2-0004dR-Fm; Thu, 04 Aug 2016 15:09:36 +0200 From: Alexander Aring To: linux-wpan@vger.kernel.org Cc: kernel@pengutronix.de, linux-bluetooth@vger.kernel.org, Alexander Aring Subject: [PATCHv2 linux-wpan/radvd for-upstream 2/2] device-linux: get address length via netlink Date: Thu, 4 Aug 2016 15:09:32 +0200 Message-Id: <20160804130932.4429-4-aar@pengutronix.de> X-Mailer: git-send-email 2.9.2 In-Reply-To: <20160804130932.4429-1-aar@pengutronix.de> References: <20160804130932.4429-1-aar@pengutronix.de> X-SA-Exim-Connect-IP: 2001:67c:670:201:5054:ff:fe8d:eefb X-SA-Exim-Mail-From: aar@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-wpan@vger.kernel.org Sender: linux-wpan-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wpan@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds a mechanism to get the device address length via netlink. This is necessary for device type 6LoWPAN which can have different device address lengths. --- device-linux.c | 16 +++++++++++++-- netlink.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ netlink.h | 1 + 3 files changed, 79 insertions(+), 2 deletions(-) diff --git a/device-linux.c b/device-linux.c index 7301927..1ccb207 100644 --- a/device-linux.c +++ b/device-linux.c @@ -17,6 +17,7 @@ #include "radvd.h" #include "defaults.h" #include "pathnames.h" +#include "netlink.h" #ifndef IPV6_ADDR_LINKLOCAL #define IPV6_ADDR_LINKLOCAL 0x0020U @@ -84,8 +85,19 @@ int update_device_info(int sock, struct Interface *iface) break; #endif /* ARPHDR_ARCNET */ case ARPHRD_6LOWPAN: - iface->sllao.if_hwaddr_len = 64; - iface->sllao.if_prefix_len = 64; +#ifdef HAVE_NETLINK + /* hwaddr length differs on some L2 type lets detect them */ + iface->sllao.if_hwaddr_len = netlink_get_device_addr_len(iface); + if (iface->sllao.if_hwaddr_len != -1) { + iface->sllao.if_hwaddr_len *= 8; + iface->sllao.if_prefix_len = 64; + } else { + iface->sllao.if_prefix_len = -1; + } +#else + iface->sllao.if_hwaddr_len = -1; + iface->sllao.if_prefix_len = -1; +#endif break; default: iface->sllao.if_hwaddr_len = -1; diff --git a/netlink.c b/netlink.c index 80d2254..d07a0b8 100644 --- a/netlink.c +++ b/netlink.c @@ -32,6 +32,70 @@ #define SOL_NETLINK 270 #endif +struct iplink_req { + struct nlmsghdr n; + struct ifinfomsg i; + char buf[1024]; +}; + +int netlink_get_device_addr_len(struct Interface *iface) +{ + struct iplink_req req = {}; + struct iovec iov = { &req, sizeof(req) }; + struct sockaddr_nl sa = {}; + struct msghdr msg = { (void *)&sa, sizeof(sa), &iov, 1, NULL, 0, 0 }; + int sock, len, addr_len = -1; + unsigned short type; + char answer[32768]; + struct rtattr *tb; + + /* nl_pid (for linux kernel) and nl_groups (unicast) should be zero */ + sa.nl_family = AF_NETLINK; + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = RTM_GETLINK; + req.i.ifi_index = iface->props.if_index; + + sock = netlink_socket(); + if (sock == -1) + return -1; + + len = sendmsg(sock, &msg, 0); + if (len == -1) { + flog(LOG_ERR, "netlink: sendmsg for addr_len failed: %s", strerror(errno)); + close(sock); + goto out; + } + + iov.iov_base = answer; + iov.iov_len = sizeof(answer); + len = recvmsg(sock, &msg, 0); + if (len == -1) { + flog(LOG_ERR, "netlink: recvmsg for addr_len failed: %s", strerror(errno)); + close(sock); + goto out; + } + + if (len < NLMSG_LENGTH(sizeof(struct ifinfomsg))) + goto out; + len -= NLMSG_LENGTH(sizeof(struct ifinfomsg)); + + tb = (struct rtattr *)(answer + NLMSG_LENGTH(sizeof(struct ifinfomsg))); + while (RTA_OK(tb, len)) { + type = tb->rta_type & ~NLA_F_NESTED; + if (type == IFLA_ADDRESS) { + addr_len = RTA_PAYLOAD(tb); + break; + } + tb = RTA_NEXT(tb, len); + } + +out: + close(sock); + + return addr_len; +} + void process_netlink_msg(int sock, struct Interface * ifaces) { char buf[4096]; diff --git a/netlink.h b/netlink.h index e2b706e..c693a10 100644 --- a/netlink.h +++ b/netlink.h @@ -17,5 +17,6 @@ #include "radvd.h" +int netlink_get_device_addr_len(struct Interface *iface); void process_netlink_msg(int sock, struct Interface * ifaces); int netlink_socket(void);