net: Implement getifaddrs and freeifaddrs
specify here: https://man7.org/linux/man-pages/man3/getifaddrs.3.html Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
This commit is contained in:
parent
1cd935fece
commit
cc1a1b5781
|
@ -0,0 +1,73 @@
|
|||
/****************************************************************************
|
||||
* include/ifaddrs.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __INCLUDE_IFADDRS_H
|
||||
#define __INCLUDE_IFADDRS_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef ifa_broadaddr
|
||||
#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Type Definitions
|
||||
****************************************************************************/
|
||||
|
||||
struct ifaddrs
|
||||
{
|
||||
FAR struct ifaddrs *ifa_next;
|
||||
FAR char *ifa_name;
|
||||
unsigned int ifa_flags;
|
||||
FAR struct sockaddr *ifa_addr;
|
||||
FAR struct sockaddr *ifa_netmask;
|
||||
FAR struct sockaddr *ifa_dstaddr;
|
||||
FAR void *ifa_data;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
extern int getifaddrs(FAR struct ifaddrs **addrs);
|
||||
extern void freeifaddrs(FAR struct ifaddrs *addrs);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __INCLUDE_IFADDRS_H */
|
|
@ -34,6 +34,7 @@ CSRCS += lib_loopback.c
|
|||
endif
|
||||
|
||||
ifeq ($(CONFIG_NETDEV_IFINDEX),y)
|
||||
CSRCS += lib_getifaddrs.c lib_freeifaddrs.c
|
||||
CSRCS += lib_indextoname.c lib_nametoindex.c
|
||||
CSRCS += lib_nameindex.c lib_freenameindex.c
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/****************************************************************************
|
||||
* libs/libc/net/lib_freeifaddrs.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <ifaddrs.h>
|
||||
|
||||
#include "libc.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: freeifaddrs
|
||||
*
|
||||
* Description:
|
||||
* The freeifaddrs() function frees the data structure returned by
|
||||
* getifaddrs().
|
||||
*
|
||||
* Input Parameters:
|
||||
* addrs - The data structure to free
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void freeifaddrs(FAR struct ifaddrs *addrs)
|
||||
{
|
||||
while (addrs != NULL)
|
||||
{
|
||||
FAR struct ifaddrs *tmp = addrs;
|
||||
addrs = addrs->ifa_next;
|
||||
lib_free(tmp);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,282 @@
|
|||
/****************************************************************************
|
||||
* libs/libc/net/lib_getifaddrs.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <errno.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <nuttx/net/netconfig.h>
|
||||
|
||||
#include "libc.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#undef broadaddr
|
||||
#define broadaddr dstaddr
|
||||
|
||||
/****************************************************************************
|
||||
* Private Type Definitions
|
||||
****************************************************************************/
|
||||
|
||||
struct myifaddrs
|
||||
{
|
||||
struct ifaddrs addrs;
|
||||
char name[IF_NAMESIZE];
|
||||
struct sockaddr_storage addr;
|
||||
struct sockaddr_storage netmask;
|
||||
struct sockaddr_storage dstaddr;
|
||||
struct sockaddr hwaddr;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: getifaddrs
|
||||
*
|
||||
* Description:
|
||||
* The getifaddrs() function returns a linked list of ifaddrs structures,
|
||||
* each containing information about one of the network interfaces on the
|
||||
* local system. The ifaddrs structure contains at least the following
|
||||
* entries:
|
||||
* struct ifaddrs *ifa_next;
|
||||
* char *ifa_name;
|
||||
* unsigned int ifa_flags;
|
||||
* struct sockaddr *ifa_addr;
|
||||
* struct sockaddr *ifa_netmask;
|
||||
* struct sockaddr *ifa_dstaddr;
|
||||
* void *ifa_data;
|
||||
* The ifa_next field contains a pointer to the next structure on
|
||||
* the list, or NULL if this is the last item of the list.
|
||||
*
|
||||
* The ifa_name points to the null-terminated interface name.
|
||||
*
|
||||
* The ifa_flags field contains the interface flags, as returned by
|
||||
* the SIOCGIFFLAGS ioctl(2) operation (see netdevice(7) for a list
|
||||
* of these flags).
|
||||
*
|
||||
* The ifa_addr field points to a structure containing the interface
|
||||
* address. (The sa_family subfield should be consulted to
|
||||
* determine the format of the address structure.) This field may
|
||||
* contain a null pointer.
|
||||
*
|
||||
* The ifa_netmask field points to a structure containing the
|
||||
* netmask associated with ifa_addr, if applicable for the address
|
||||
* family. This field may contain a null pointer.
|
||||
*
|
||||
* Depending on whether the bit IFF_BROADCAST or IFF_POINTOPOINT is
|
||||
* set in ifa_flags (only one can be set at a time), either
|
||||
* ifa_broadaddr will contain the broadcast address associated with
|
||||
* ifa_addr (if applicable for the address family) or ifa_dstaddr
|
||||
* will contain the destination address of the point-to-point
|
||||
* interface.
|
||||
*
|
||||
* The ifa_data field points to a buffer containing address-family-
|
||||
* specific data; this field may be NULL if there is no such data
|
||||
* for this interface.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, getifaddrs() returns pointer to the linked list; on error,
|
||||
* NULL is returned, and errno is set to indicate the error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int getifaddrs(FAR struct ifaddrs **addrs)
|
||||
{
|
||||
FAR struct myifaddrs *myaddrs = NULL;
|
||||
int sockfd;
|
||||
int i;
|
||||
|
||||
if (addrs == NULL)
|
||||
{
|
||||
set_errno(EINVAL);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
sockfd = socket(NET_SOCK_FAMILY, NET_SOCK_TYPE, NET_SOCK_PROTOCOL);
|
||||
if (sockfd < 0)
|
||||
{
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
for (i = 1, *addrs = NULL; i <= MAX_IFINDEX; i++)
|
||||
{
|
||||
unsigned int flags;
|
||||
struct lifreq req;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.lifr_ifindex = i;
|
||||
|
||||
if (ioctl(sockfd, SIOCGIFNAME, (unsigned long)&req) < 0)
|
||||
{
|
||||
continue; /* Empty slot, try next one */
|
||||
}
|
||||
|
||||
if (ioctl(sockfd, SIOCGIFFLAGS, (unsigned long)&req) < 0)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
||||
flags = req.lifr_flags;
|
||||
|
||||
if (myaddrs != NULL)
|
||||
{
|
||||
myaddrs->addrs.ifa_next = lib_zalloc(sizeof(*myaddrs));
|
||||
myaddrs = (FAR struct myifaddrs *)myaddrs->addrs.ifa_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
*addrs = lib_zalloc(sizeof(*myaddrs));
|
||||
myaddrs = (FAR struct myifaddrs *)*addrs;
|
||||
}
|
||||
|
||||
if (myaddrs == NULL)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
||||
myaddrs->addrs.ifa_name = myaddrs->name;
|
||||
strncpy(myaddrs->name, req.lifr_name, IF_NAMESIZE);
|
||||
|
||||
myaddrs->addrs.ifa_flags = flags;
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (ioctl(sockfd, SIOCGIFADDR, (unsigned long)&req) >= 0)
|
||||
{
|
||||
myaddrs->addrs.ifa_addr = (FAR struct sockaddr *)&myaddrs->addr;
|
||||
memcpy(&myaddrs->addr, &req.lifr_addr, sizeof(req.lifr_addr));
|
||||
|
||||
if (ioctl(sockfd, SIOCGIFNETMASK, (unsigned long)&req) >= 0)
|
||||
{
|
||||
myaddrs->addrs.ifa_netmask =
|
||||
(FAR struct sockaddr *)&myaddrs->netmask;
|
||||
memcpy(&myaddrs->netmask,
|
||||
&req.lifr_netmask, sizeof(req.lifr_netmask));
|
||||
}
|
||||
|
||||
if (ioctl(sockfd, SIOCGIFDSTADDR, (unsigned long)&req) >= 0)
|
||||
{
|
||||
myaddrs->addrs.ifa_dstaddr =
|
||||
(FAR struct sockaddr *)&myaddrs->dstaddr;
|
||||
memcpy(&myaddrs->dstaddr,
|
||||
&req.lifr_dstaddr, sizeof(req.lifr_dstaddr));
|
||||
}
|
||||
else if (ioctl(sockfd, SIOCGIFBRDADDR, (unsigned long)&req) >= 0)
|
||||
{
|
||||
myaddrs->addrs.ifa_broadaddr =
|
||||
(FAR struct sockaddr *)&myaddrs->broadaddr;
|
||||
memcpy(&myaddrs->broadaddr,
|
||||
&req.lifr_broadaddr, sizeof(req.lifr_broadaddr));
|
||||
}
|
||||
|
||||
if (ioctl(sockfd, SIOCGIFHWADDR, (unsigned long)&req) >= 0)
|
||||
{
|
||||
myaddrs->addrs.ifa_data = &myaddrs->hwaddr;
|
||||
memcpy(&myaddrs->hwaddr,
|
||||
&req.lifr_hwaddr, sizeof(req.lifr_hwaddr));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (ioctl(sockfd, SIOCGLIFADDR, (unsigned long)&req) >= 0)
|
||||
{
|
||||
/* Has IPv4 entry ? */
|
||||
|
||||
if (myaddrs->addrs.ifa_addr)
|
||||
{
|
||||
/* Yes, allocate the new entry for IPv6 */
|
||||
|
||||
myaddrs->addrs.ifa_next = lib_zalloc(sizeof(*myaddrs));
|
||||
myaddrs = (FAR struct myifaddrs *)myaddrs->addrs.ifa_next;
|
||||
|
||||
if (myaddrs == NULL)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
||||
myaddrs->addrs.ifa_name = myaddrs->name;
|
||||
strncpy(myaddrs->name, req.lifr_name, IF_NAMESIZE);
|
||||
|
||||
myaddrs->addrs.ifa_flags = flags;
|
||||
}
|
||||
|
||||
myaddrs->addrs.ifa_addr = (FAR struct sockaddr *)&myaddrs->addr;
|
||||
memcpy(&myaddrs->addr, &req.lifr_addr, sizeof(req.lifr_addr));
|
||||
|
||||
if (ioctl(sockfd, SIOCGLIFNETMASK, (unsigned long)&req) >= 0)
|
||||
{
|
||||
myaddrs->addrs.ifa_netmask =
|
||||
(FAR struct sockaddr *)&myaddrs->netmask;
|
||||
memcpy(&myaddrs->netmask,
|
||||
&req.lifr_netmask, sizeof(req.lifr_netmask));
|
||||
}
|
||||
|
||||
if (ioctl(sockfd, SIOCGLIFDSTADDR, (unsigned long)&req) >= 0)
|
||||
{
|
||||
myaddrs->addrs.ifa_dstaddr =
|
||||
(FAR struct sockaddr *)&myaddrs->dstaddr;
|
||||
memcpy(&myaddrs->dstaddr,
|
||||
&req.lifr_dstaddr, sizeof(req.lifr_dstaddr));
|
||||
}
|
||||
else if (ioctl(sockfd, SIOCGLIFBRDADDR, (unsigned long)&req) >= 0)
|
||||
{
|
||||
myaddrs->addrs.ifa_broadaddr =
|
||||
(FAR struct sockaddr *)&myaddrs->broadaddr;
|
||||
memcpy(&myaddrs->broadaddr,
|
||||
&req.lifr_broadaddr, sizeof(req.lifr_broadaddr));
|
||||
}
|
||||
|
||||
if (ioctl(sockfd, SIOCGIFHWADDR, (unsigned long)&req) >= 0)
|
||||
{
|
||||
myaddrs->addrs.ifa_data = &myaddrs->hwaddr;
|
||||
memcpy(&myaddrs->hwaddr,
|
||||
&req.lifr_hwaddr, sizeof(req.lifr_hwaddr));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
return OK;
|
||||
|
||||
err:
|
||||
if (*addrs != NULL)
|
||||
{
|
||||
freeifaddrs(*addrs);
|
||||
*addrs = NULL;
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
return ERROR;
|
||||
}
|
Loading…
Reference in New Issue