mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 07:28:38 +08:00
netlink: Explicitly set ip address for netlink notify
Prepare for multiple IPv6 addresses per net device, then we can notify add/remove of a single address later. Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
parent
85a375cd7d
commit
c7845f5b25
7 changed files with 134 additions and 36 deletions
|
@ -83,6 +83,7 @@
|
|||
#include "icmpv6/icmpv6.h"
|
||||
#include "route/route.h"
|
||||
#include "netlink/netlink.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -858,7 +859,8 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd,
|
|||
|
||||
case SIOCSIFADDR: /* Set IP address */
|
||||
ioctl_set_ipv4addr(&dev->d_ipaddr, &req->ifr_addr);
|
||||
netlink_device_notify_ipaddr(dev, RTM_NEWADDR, AF_INET);
|
||||
netlink_device_notify_ipaddr(dev, RTM_NEWADDR, AF_INET,
|
||||
&dev->d_ipaddr, net_ipv4_mask2pref(dev->d_netmask));
|
||||
break;
|
||||
|
||||
case SIOCGIFDSTADDR: /* Get P-to-P address */
|
||||
|
@ -899,7 +901,8 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd,
|
|||
{
|
||||
FAR struct lifreq *lreq = (FAR struct lifreq *)req;
|
||||
ioctl_set_ipv6addr(dev->d_ipv6addr, &lreq->lifr_addr);
|
||||
netlink_device_notify_ipaddr(dev, RTM_NEWADDR, AF_INET6);
|
||||
netlink_device_notify_ipaddr(dev, RTM_NEWADDR, AF_INET6,
|
||||
dev->d_ipv6addr, net_ipv6_mask2pref(dev->d_ipv6netmask));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1056,12 +1059,14 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd,
|
|||
|
||||
case SIOCDIFADDR: /* Delete IP address */
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
netlink_device_notify_ipaddr(dev, RTM_DELADDR, AF_INET,
|
||||
&dev->d_ipaddr, net_ipv4_mask2pref(dev->d_netmask));
|
||||
dev->d_ipaddr = 0;
|
||||
netlink_device_notify_ipaddr(dev, RTM_DELADDR, AF_INET);
|
||||
#endif
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
netlink_device_notify_ipaddr(dev, RTM_DELADDR, AF_INET6,
|
||||
dev->d_ipv6addr, net_ipv6_mask2pref(dev->d_ipv6netmask));
|
||||
memset(&dev->d_ipv6addr, 0, sizeof(net_ipv6addr_t));
|
||||
netlink_device_notify_ipaddr(dev, RTM_DELADDR, AF_INET6);
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
#ifndef CONFIG_NETLINK_ROUTE
|
||||
# define netlink_device_notify(dev)
|
||||
# define netlink_device_notify_ipaddr(dev, type, domain)
|
||||
# define netlink_device_notify_ipaddr(dev, type, domain, addr, preflen)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_NETLINK
|
||||
|
@ -502,7 +502,8 @@ void netlink_device_notify(FAR struct net_driver_s *dev);
|
|||
****************************************************************************/
|
||||
|
||||
void netlink_device_notify_ipaddr(FAR struct net_driver_s *dev,
|
||||
int type, int domain);
|
||||
int type, int domain,
|
||||
FAR const void *addr, uint8_t preflen);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nla_next
|
||||
|
|
|
@ -369,16 +369,6 @@ static uint32_t make_mask(int prefixlen)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t mask_len(uint32_t nmask)
|
||||
{
|
||||
uint8_t prefixlen = 0;
|
||||
uint32_t hmask = NTOHL(nmask);
|
||||
|
||||
for (; hmask; ++prefixlen, hmask <<= 1);
|
||||
|
||||
return prefixlen;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -392,6 +382,7 @@ static uint8_t mask_len(uint32_t nmask)
|
|||
#ifndef CONFIG_NETLINK_DISABLE_GETLINK
|
||||
static FAR struct netlink_response_s *
|
||||
netlink_get_ifaddr(FAR struct net_driver_s *dev, int domain, int type,
|
||||
FAR const void *local_addr, uint8_t prefixlen,
|
||||
FAR const struct nlroute_sendto_request_s *req)
|
||||
{
|
||||
FAR struct getaddr_recvfrom_rsplist_s *alloc;
|
||||
|
@ -429,8 +420,8 @@ netlink_get_ifaddr(FAR struct net_driver_s *dev, int domain, int type,
|
|||
if (domain == AF_INET)
|
||||
{
|
||||
resp->attr.rta_len = RTA_LENGTH(sizeof(struct in_addr));
|
||||
memcpy(&resp->local_addr, &dev->d_ipaddr, sizeof(struct in_addr));
|
||||
resp->ifaddr.ifa_prefixlen = mask_len(dev->d_netmask);
|
||||
memcpy(&resp->local_addr, local_addr, sizeof(struct in_addr));
|
||||
resp->ifaddr.ifa_prefixlen = prefixlen;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -438,8 +429,8 @@ netlink_get_ifaddr(FAR struct net_driver_s *dev, int domain, int type,
|
|||
if (domain == AF_INET6)
|
||||
{
|
||||
resp->attr.rta_len = RTA_LENGTH(sizeof(struct in6_addr));
|
||||
memcpy(&resp->local_addr, dev->d_ipv6addr, sizeof(struct in6_addr));
|
||||
resp->ifaddr.ifa_prefixlen = net_ipv6_mask2pref(dev->d_ipv6netmask);
|
||||
memcpy(&resp->local_addr, local_addr, sizeof(struct in6_addr));
|
||||
resp->ifaddr.ifa_prefixlen = prefixlen;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -951,7 +942,8 @@ static int netlink_new_ipv4addr(NETLINK_HANDLE handle,
|
|||
dev->d_ipaddr = nla_get_in_addr(tb[IFA_LOCAL]);
|
||||
dev->d_netmask = make_mask(ifm->ifa_prefixlen);
|
||||
|
||||
netlink_device_notify_ipaddr(dev, RTM_NEWADDR, AF_INET);
|
||||
netlink_device_notify_ipaddr(dev, RTM_NEWADDR, AF_INET, &dev->d_ipaddr,
|
||||
ifm->ifa_prefixlen);
|
||||
net_unlock();
|
||||
|
||||
return OK;
|
||||
|
@ -1000,7 +992,8 @@ static int netlink_new_ipv6addr(NETLINK_HANDLE handle,
|
|||
memcpy(dev->d_ipv6addr, nla_data(tb[IFA_LOCAL]), 16);
|
||||
net_ipv6_pref2mask(ifm->ifa_prefixlen, dev->d_ipv6netmask);
|
||||
|
||||
netlink_device_notify_ipaddr(dev, RTM_NEWADDR, AF_INET6);
|
||||
netlink_device_notify_ipaddr(dev, RTM_NEWADDR, AF_INET6, dev->d_ipv6addr,
|
||||
ifm->ifa_prefixlen);
|
||||
net_unlock();
|
||||
|
||||
return OK;
|
||||
|
@ -1047,9 +1040,10 @@ static int netlink_del_ipv4addr(NETLINK_HANDLE handle,
|
|||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
netlink_device_notify_ipaddr(dev, RTM_DELADDR, AF_INET, &dev->d_ipaddr,
|
||||
net_ipv4_mask2pref(dev->d_netmask));
|
||||
dev->d_ipaddr = 0;
|
||||
|
||||
netlink_device_notify_ipaddr(dev, RTM_DELADDR, AF_INET);
|
||||
net_unlock();
|
||||
|
||||
return OK;
|
||||
|
@ -1090,15 +1084,17 @@ static int netlink_del_ipv6addr(NETLINK_HANDLE handle,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (tb[IFA_LOCAL] && dev->d_ipaddr != nla_get_in_addr(tb[IFA_LOCAL]))
|
||||
if (tb[IFA_LOCAL] && !net_ipv6addr_cmp(dev->d_ipv6addr,
|
||||
nla_data(tb[IFA_LOCAL])))
|
||||
{
|
||||
net_unlock();
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
netlink_device_notify_ipaddr(dev, RTM_DELADDR, AF_INET6, dev->d_ipv6addr,
|
||||
net_ipv6_mask2pref(dev->d_ipv6netmask));
|
||||
memset(&dev->d_ipv6addr, 0, sizeof(net_ipv6addr_t));
|
||||
|
||||
netlink_device_notify_ipaddr(dev, RTM_DELADDR, AF_INET6);
|
||||
net_unlock();
|
||||
|
||||
return OK;
|
||||
|
@ -1114,14 +1110,36 @@ static int netlink_del_ipv6addr(NETLINK_HANDLE handle,
|
|||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NETLINK_DISABLE_GETADDR
|
||||
static int netlink_addr_callback(FAR struct net_driver_s *dev,
|
||||
FAR void *arg)
|
||||
static int netlink_addr_callback(FAR struct net_driver_s *dev, FAR void *arg)
|
||||
{
|
||||
FAR struct nlroute_info_s *info = arg;
|
||||
FAR struct netlink_response_s *resp;
|
||||
FAR void *addr = NULL;
|
||||
uint8_t preflen;
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (info->req->gen.rtgen_family == AF_INET)
|
||||
{
|
||||
addr = &dev->d_ipaddr;
|
||||
preflen = net_ipv4_mask2pref(dev->d_netmask);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (info->req->gen.rtgen_family == AF_INET6)
|
||||
{
|
||||
addr = &dev->d_ipv6addr;
|
||||
preflen = net_ipv6_mask2pref(dev->d_ipv6netmask);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (addr == NULL)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
resp = netlink_get_ifaddr(dev, info->req->gen.rtgen_family, RTM_NEWADDR,
|
||||
info->req);
|
||||
addr, preflen, info->req);
|
||||
if (resp == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
|
@ -1378,14 +1396,15 @@ void netlink_device_notify(FAR struct net_driver_s *dev)
|
|||
!defined(CONFIG_NETLINK_DISABLE_DELADDR) || \
|
||||
!defined(CONFIG_NETLINK_DISABLE_GETADDR)
|
||||
void netlink_device_notify_ipaddr(FAR struct net_driver_s *dev,
|
||||
int type, int domain)
|
||||
int type, int domain,
|
||||
FAR const void *addr, uint8_t preflen)
|
||||
{
|
||||
FAR struct netlink_response_s *resp;
|
||||
int group;
|
||||
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
resp = netlink_get_ifaddr(dev, domain, type, NULL);
|
||||
resp = netlink_get_ifaddr(dev, domain, type, addr, preflen, NULL);
|
||||
if (resp != NULL)
|
||||
{
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
|
|
|
@ -31,12 +31,13 @@ set(SRCS
|
|||
net_snoop.c
|
||||
net_cmsg.c
|
||||
net_iob_concat.c
|
||||
net_getrandom.c)
|
||||
net_getrandom.c
|
||||
net_mask2pref.c)
|
||||
|
||||
# IPv6 utilities
|
||||
|
||||
if(CONFIG_NET_IPv6)
|
||||
list(APPEND SRCS net_ipv6_maskcmp.c net_ipv6_mask2pref.c net_ipv6_pref2mask.c)
|
||||
list(APPEND SRCS net_ipv6_maskcmp.c net_ipv6_pref2mask.c)
|
||||
endif()
|
||||
|
||||
# TCP utilities
|
||||
|
|
|
@ -22,12 +22,12 @@
|
|||
|
||||
NET_CSRCS += net_dsec2tick.c net_dsec2timeval.c net_timeval2dsec.c
|
||||
NET_CSRCS += net_chksum.c net_ipchksum.c net_incr32.c net_lock.c net_snoop.c
|
||||
NET_CSRCS += net_cmsg.c net_iob_concat.c net_getrandom.c
|
||||
NET_CSRCS += net_cmsg.c net_iob_concat.c net_getrandom.c net_mask2pref.c
|
||||
|
||||
# IPv6 utilities
|
||||
|
||||
ifeq ($(CONFIG_NET_IPv6),y)
|
||||
NET_CSRCS += net_ipv6_maskcmp.c net_ipv6_mask2pref.c net_ipv6_pref2mask.c
|
||||
NET_CSRCS += net_ipv6_maskcmp.c net_ipv6_pref2mask.c
|
||||
endif
|
||||
|
||||
# TCP utilities
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* net/utils/net_ipv6_mask2pref.c
|
||||
* net/utils/net_mask2pref.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -26,7 +26,7 @@
|
|||
|
||||
#include "utils/utils.h"
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
#if defined(CONFIG_NET_IPv4) || defined(CONFIG_NET_IPv6)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
|
@ -112,10 +112,52 @@ static inline uint8_t net_msbits16(uint16_t hword)
|
|||
return ones;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_IPv4 || CONFIG_NET_IPv6 */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: net_ipv4_mask2pref
|
||||
*
|
||||
* Description:
|
||||
* Convert a 32-bit netmask to a prefix length. The NuttX IPv4
|
||||
* networking uses 32-bit network masks internally. This function
|
||||
* converts the IPv4 netmask to a prefix length.
|
||||
*
|
||||
* The prefix length is the number of MS '1' bits on in the netmask.
|
||||
* This, of course, assumes that all MS bits are '1' and all LS bits are
|
||||
* '0' with no intermixed 1's and 0's. This function searches from the MS
|
||||
* bit until the first '0' is found (this does not necessary mean that
|
||||
* there might not be additional '1' bits following the firs '0', but that
|
||||
* will be a malformed netmask.
|
||||
*
|
||||
* Input Parameters:
|
||||
* mask An IPv4 netmask in the form of in_addr_t
|
||||
*
|
||||
* Returned Value:
|
||||
* The prefix length, range 0-32 on success; This function will not
|
||||
* fail.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
|
||||
uint8_t net_ipv4_mask2pref(in_addr_t mask)
|
||||
{
|
||||
uint32_t hmask = NTOHL(mask);
|
||||
uint8_t ones = net_msbits16((uint16_t)(hmask >> 16));
|
||||
if (ones == 16)
|
||||
{
|
||||
ones += net_msbits16((uint16_t)(hmask & 0xffff));
|
||||
}
|
||||
|
||||
return ones;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_IPv4 */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: net_ipv6_mask2pref
|
||||
*
|
||||
|
@ -140,6 +182,8 @@ static inline uint8_t net_msbits16(uint16_t hword)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
|
||||
uint8_t net_ipv6_mask2pref(FAR const uint16_t *mask)
|
||||
{
|
||||
uint8_t preflen;
|
|
@ -159,6 +159,34 @@ unsigned int net_timeval2dsec(FAR struct timeval *tv,
|
|||
|
||||
void net_getrandom(FAR void *bytes, size_t nbytes);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: net_ipv4_mask2pref
|
||||
*
|
||||
* Description:
|
||||
* Convert a 32-bit netmask to a prefix length. The NuttX IPv4
|
||||
* networking uses 32-bit network masks internally. This function
|
||||
* converts the IPv4 netmask to a prefix length.
|
||||
*
|
||||
* The prefix length is the number of MS '1' bits on in the netmask.
|
||||
* This, of course, assumes that all MS bits are '1' and all LS bits are
|
||||
* '0' with no intermixed 1's and 0's. This function searches from the MS
|
||||
* bit until the first '0' is found (this does not necessary mean that
|
||||
* there might not be additional '1' bits following the firs '0', but that
|
||||
* will be a malformed netmask.
|
||||
*
|
||||
* Input Parameters:
|
||||
* mask An IPv4 netmask in the form of in_addr_t
|
||||
*
|
||||
* Returned Value:
|
||||
* The prefix length, range 0-32 on success; This function will not
|
||||
* fail.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
uint8_t net_ipv4_mask2pref(in_addr_t mask);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: net_ipv6_mask2pref
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue