summaryrefslogtreecommitdiff
path: root/components/net/sal_socket/src
diff options
context:
space:
mode:
Diffstat (limited to 'components/net/sal_socket/src')
-rw-r--r--components/net/sal_socket/src/sal_ipaddr.c257
-rw-r--r--components/net/sal_socket/src/sal_socket.c844
2 files changed, 493 insertions, 608 deletions
diff --git a/components/net/sal_socket/src/sal_ipaddr.c b/components/net/sal_socket/src/sal_ipaddr.c
deleted file mode 100644
index 6477a8ad64..0000000000
--- a/components/net/sal_socket/src/sal_ipaddr.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Copyright (c) 2006-2018, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2018-05-18 ChenYong First version
- */
-
-#include <sal_ipaddr.h>
-#include <rtthread.h>
-
-/* Here for now until needed in other places in lwIP */
-#ifndef isprint
-#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
-#define isprint(c) in_range(c, 0x20, 0x7f)
-#define isdigit(c) in_range(c, '0', '9')
-#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
-#define islower(c) in_range(c, 'a', 'z')
-#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
-#endif
-
-
-/**
- * Check whether "cp" is a valid ascii representation
- * of an Internet address and convert to a binary address.
- * Returns 1 if the address is valid, 0 if not.
- * This replaces inet_addr, the return value from which
- * cannot distinguish between failure and a local broadcast address.
- *
- * @param cp IP address in ascii representation (e.g. "127.0.0.1")
- * @param addr pointer to which to save the ip address in network order
- * @return 1 if cp could be converted to addr, 0 on failure
- */
-int sal_ip4addr_aton(const char *cp, ip4_addr_t *addr)
-{
- u32_t val;
- u8_t base;
- char c;
- u32_t parts[4];
- u32_t *pp = parts;
-
- c = *cp;
- for (;;)
- {
- /*
- * Collect number up to ``.''.
- * Values are specified as for C:
- * 0x=hex, 0=octal, 1-9=decimal.
- */
- if (!isdigit(c))
- {
- return 0;
- }
- val = 0;
- base = 10;
- if (c == '0')
- {
- c = *++cp;
- if (c == 'x' || c == 'X')
- {
- base = 16;
- c = *++cp;
- }
- else
- {
- base = 8;
- }
- }
- for (;;)
- {
- if (isdigit(c))
- {
- val = (val * base) + (u32_t) (c - '0');
- c = *++cp;
- }
- else if (base == 16 && isxdigit(c))
- {
- val = (val << 4) | (u32_t) (c + 10 - (islower(c) ? 'a' : 'A'));
- c = *++cp;
- }
- else
- {
- break;
- }
- }
- if (c == '.')
- {
- /*
- * Internet format:
- * a.b.c.d
- * a.b.c (with c treated as 16 bits)
- * a.b (with b treated as 24 bits)
- */
- if (pp >= parts + 3)
- {
- return 0;
- }
- *pp++ = val;
- c = *++cp;
- }
- else
- {
- break;
- }
- }
- /*
- * Check for trailing characters.
- */
- if (c != '\0' && !isspace(c))
- {
- return 0;
- }
- /*
- * Concoct the address according to
- * the number of parts specified.
- */
- switch (pp - parts + 1)
- {
-
- case 0:
- return 0; /* initial nondigit */
-
- case 1: /* a -- 32 bits */
- break;
-
- case 2: /* a.b -- 8.24 bits */
- if (val > 0xffffffUL)
- {
- return 0;
- }
- if (parts[0] > 0xff)
- {
- return 0;
- }
- val |= parts[0] << 24;
- break;
-
- case 3: /* a.b.c -- 8.8.16 bits */
- if (val > 0xffff)
- {
- return 0;
- }
- if ((parts[0] > 0xff) || (parts[1] > 0xff))
- {
- return 0;
- }
- val |= (parts[0] << 24) | (parts[1] << 16);
- break;
-
- case 4: /* a.b.c.d -- 8.8.8.8 bits */
- if (val > 0xff)
- {
- return 0;
- }
- if ((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff))
- {
- return 0;
- }
- val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
- break;
- default:
- RT_ASSERT(0);
- break;
- }
- if (addr)
- {
- ip4_addr_set_u32(addr, htonl(val));
- }
- return 1;
-}
-
-/**
- * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used.
- *
- * @param addr ip address in network order to convert
- * @param buf target buffer where the string is stored
- * @param buflen length of buf
- * @return either pointer to buf which now holds the ASCII
- * representation of addr or NULL if buf was too small
- */
-char *sal_ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen)
-{
- u32_t s_addr;
- char inv[3];
- char *rp;
- u8_t *ap;
- u8_t rem;
- u8_t n;
- u8_t i;
- int len = 0;
-
- s_addr = ip4_addr_get_u32(addr);
-
- rp = buf;
- ap = (u8_t *) &s_addr;
- for (n = 0; n < 4; n++)
- {
- i = 0;
- do
- {
- rem = *ap % (u8_t) 10;
- *ap /= (u8_t) 10;
- inv[i++] = (char) ('0' + rem);
- } while (*ap);
- while (i--)
- {
- if (len++ >= buflen)
- {
- return NULL;
- }
- *rp++ = inv[i];
- }
- if (len++ >= buflen)
- {
- return NULL;
- }
- *rp++ = '.';
- ap++;
- }
- *--rp = 0;
- return buf;
-}
-
-
-/**
- * Convert numeric IP address into decimal dotted ASCII representation.
- * returns ptr to static buffer; not reentrant!
- *
- * @param addr ip address in network order to convert
- * @return pointer to a global static (!) buffer that holds the ASCII
- * representation of addr
- */
-char *sal_ip4addr_ntoa(const ip4_addr_t *addr)
-{
- static char str[IP4ADDR_STRLEN_MAX];
- return sal_ip4addr_ntoa_r(addr, str, IP4ADDR_STRLEN_MAX);
-}
-
-
-/**
- * Ascii internet address interpretation routine.
- * The value returned is in network order.
- *
- * @param cp IP address in ascii representation (e.g. "127.0.0.1")
- * @return ip address in network order
- */
-in_addr_t sal_ipaddr_addr(const char *cp)
-{
- ip4_addr_t val;
-
- if (sal_ip4addr_aton(cp, &val)) {
- return ip4_addr_get_u32(&val);
- }
- return (IPADDR_NONE);
-}
diff --git a/components/net/sal_socket/src/sal_socket.c b/components/net/sal_socket/src/sal_socket.c
index dba8e66254..ec0519df02 100644
--- a/components/net/sal_socket/src/sal_socket.c
+++ b/components/net/sal_socket/src/sal_socket.c
@@ -11,6 +11,7 @@
#include <rtthread.h>
#include <rthw.h>
+#include <sys/time.h>
#include <sal_socket.h>
#include <sal_netdb.h>
@@ -18,11 +19,17 @@
#include <sal_tls.h>
#endif
#include <sal.h>
+#include <netdev.h>
-#define DBG_ENABLE
-#define DBG_SECTION_NAME "SAL_SOC"
-#define DBG_LEVEL DBG_INFO
-#define DBG_COLOR
+#include <ipc/workqueue.h>
+
+/* check system workqueue stack size */
+#if RT_SYSTEM_WORKQUEUE_STACKSIZE < 1536
+#error "The system workqueue stack size must more than 1536 bytes"
+#endif
+
+#define DBG_TAG "sal.skt"
+#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#define SOCKET_TABLE_STEP_LEN 4
@@ -39,8 +46,6 @@ struct sal_socket_table
static struct sal_proto_tls *proto_tls;
#endif
-/* The global array of available protocol families */
-static struct sal_proto_family proto_families[SAL_PROTO_FAMILIES_NUM];
/* The global socket table */
static struct sal_socket_table socket_table;
static struct rt_mutex sal_core_lock;
@@ -51,25 +56,50 @@ static rt_bool_t init_ok = RT_FALSE;
#define SAL_SOCKOPS_PROTO_TLS_VALID(sock, name) (proto_tls && (proto_tls->ops->name) && IS_SOCKET_PROTO_TLS(sock))
#define SAL_SOCKOPT_PROTO_TLS_EXEC(sock, name, optval, optlen) \
-do \
-{ \
- if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, name)) \
- { \
+do { \
+ if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, name)){ \
return proto_tls->ops->name((sock)->user_data_tls, (optval), (optlen)); \
} \
}while(0) \
+#define SAL_SOCKET_OBJ_GET(sock, socket) \
+do { \
+ (sock) = sal_get_socket(socket); \
+ if ((sock) == RT_NULL) { \
+ return -1; \
+ } \
+}while(0) \
+
+#define SAL_NETDEV_IS_UP(netdev) \
+do { \
+ if (!netdev_is_up(netdev)) { \
+ return -1; \
+ } \
+}while(0) \
+
+#define SAL_NETDEV_SOCKETOPS_VALID(netdev, pf, ops) \
+do { \
+ (pf) = (struct sal_proto_family *) netdev->sal_user_data; \
+ if ((pf)->skt_ops->ops == RT_NULL){ \
+ return -1; \
+ } \
+}while(0) \
+
+#define SAL_NETDEV_NETDBOPS_VALID(netdev, pf, ops) \
+ ((netdev) && netdev_is_up(netdev) && \
+ ((pf) = (struct sal_proto_family *) (netdev)->sal_user_data) != RT_NULL && \
+ (pf)->netdb_ops->ops) \
/**
* SAL (Socket Abstraction Layer) initialize.
*
* @return result 0: initialize success
- * -1: initialize failed
+ * -1: initialize failed
*/
int sal_init(void)
{
int cn;
-
+
if (init_ok)
{
LOG_D("Socket Abstraction Layer is already initialized.");
@@ -85,7 +115,7 @@ int sal_init(void)
LOG_E("No memory for socket table.\n");
return -1;
}
-
+
/* create sal socket lock */
rt_mutex_init(&sal_core_lock, "sal_lock", RT_IPC_FLAG_FIFO);
@@ -96,153 +126,177 @@ int sal_init(void)
}
INIT_COMPONENT_EXPORT(sal_init);
-/**
- * This function will register TLS protocol to the global TLS protocol.
- *
- * @param pt TLS protocol object
- *
- * @return 0: TLS protocol object register success
- */
-#ifdef SAL_USING_TLS
-int sal_proto_tls_register(const struct sal_proto_tls *pt)
+/* check SAL network interface device internet status */
+static void check_netdev_internet_up_work(struct rt_work *work, void *work_data)
{
- RT_ASSERT(pt);
- proto_tls = (struct sal_proto_tls *) pt;
+#define SAL_INTERNET_VERSION 0x00
+#define SAL_INTERNET_BUFF_LEN 12
+#define SAL_INTERNET_TIMEOUT (2)
- return 0;
-}
-#endif
+#define SAL_INTERNET_HOST "link.rt-thread.org"
+#define SAL_INTERNET_PORT 8101
-/**
- * This function will register protocol family to the global array of protocol families.
- *
- * @param pf protocol family object
- *
- * @return 0: protocol family object register success
- * -1: the global array of available protocol families is full
- */
-int sal_proto_family_register(const struct sal_proto_family *pf)
-{
- rt_base_t level;
- int idx;
+#define SAL_INTERNET_MONTH_LEN 4
+#define SAL_INTERNET_DATE_LEN 16
- /* disable interrupt */
- level = rt_hw_interrupt_disable();
+ int index, sockfd = -1, result = 0;
+ struct sockaddr_in server_addr;
+ struct hostent *host;
+ struct timeval timeout;
+ struct netdev *netdev = (struct netdev *)work_data;
+ socklen_t addr_len = sizeof(struct sockaddr_in);
+ char send_data[SAL_INTERNET_BUFF_LEN], recv_data = 0;
+ struct rt_delayed_work *delay_work = (struct rt_delayed_work *)work;
- /* check protocol family is already registered */
- for(idx = 0; idx < SAL_PROTO_FAMILIES_NUM; idx++)
+ const char month[][SAL_INTERNET_MONTH_LEN] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+ char date[SAL_INTERNET_DATE_LEN];
+ int moth_num = 0;
+
+ struct sal_proto_family *pf = (struct sal_proto_family *) netdev->sal_user_data;
+ const struct sal_socket_ops *skt_ops;
+
+ if (work)
{
- if (proto_families[idx].family == pf->family && proto_families[idx].create)
- {
- /* enable interrupt */
- rt_hw_interrupt_enable(level);
- LOG_E("%s protocol family is already registered!", pf->family);
- return -1;
- }
+ rt_free(delay_work);
}
- /* find an empty protocol family entry */
- for(idx = 0; idx < SAL_PROTO_FAMILIES_NUM && proto_families[idx].create; idx++);
+ /* get network interface socket operations */
+ if (pf == RT_NULL || pf->skt_ops == RT_NULL)
+ {
+ result = -RT_ERROR;
+ goto __exit;
+ }
- /* can't find an empty protocol family entry */
- if (idx == SAL_PROTO_FAMILIES_NUM)
+ host = (struct hostent *) pf->netdb_ops->gethostbyname(SAL_INTERNET_HOST);
+ if (host == RT_NULL)
{
- /* enable interrupt */
- rt_hw_interrupt_enable(level);
- return -1;
+ result = -RT_ERROR;
+ goto __exit;
}
- proto_families[idx].family = pf->family;
- proto_families[idx].sec_family = pf->sec_family;
- proto_families[idx].create = pf->create;
+ skt_ops = pf->skt_ops;
+ if ((sockfd = skt_ops->socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ {
+ result = -RT_ERROR;
+ goto __exit;
+ }
- proto_families[idx].ops = pf->ops;
- proto_families[idx].ops->gethostbyname = pf->ops->gethostbyname;
- proto_families[idx].ops->gethostbyname_r = pf->ops->gethostbyname_r;
- proto_families[idx].ops->freeaddrinfo = pf->ops->freeaddrinfo;
- proto_families[idx].ops->getaddrinfo = pf->ops->getaddrinfo;
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = htons(SAL_INTERNET_PORT);
+ server_addr.sin_addr = *((struct in_addr *)host->h_addr);
+ rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
- /* enable interrupt */
- rt_hw_interrupt_enable(level);
+ timeout.tv_sec = SAL_INTERNET_TIMEOUT;
+ timeout.tv_usec = 0;
- return 0;
-}
+ /* set receive and send timeout */
+ skt_ops->setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (void *) &timeout, sizeof(timeout));
+ skt_ops->setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (void *) &timeout, sizeof(timeout));
-/**
- * This function removes a previously registered protocol family object.
- *
- * @param pf protocol family object
- *
- * @return >=0 : unregister protocol family index
- * -1 : unregister failed
- */
-int sal_proto_family_unregister(int family)
-{
- int idx = 0;
+ /* get build moth value*/
+ rt_memset(date, 0x00, SAL_INTERNET_DATE_LEN);
+ rt_snprintf(date, SAL_INTERNET_DATE_LEN, "%s", __DATE__);
- RT_ASSERT(family > 0 && family < AF_MAX);
-
- for(idx = 0; idx < SAL_PROTO_FAMILIES_NUM; idx++)
+ for (index = 0; index < sizeof(month) / SAL_INTERNET_MONTH_LEN; index++)
{
- if (proto_families[idx].family == family && proto_families[idx].create)
+ if (rt_memcmp(date, month[index], SAL_INTERNET_MONTH_LEN - 1) == 0)
{
- rt_memset(&proto_families[idx], 0x00, sizeof(struct sal_proto_family));
-
- return idx;
+ moth_num = index + 1;
+ break;
}
}
- return -1;
+ /* not find build month */
+ if (moth_num == 0 || moth_num > sizeof(month) / SAL_INTERNET_MONTH_LEN)
+ {
+ result = -RT_ERROR;
+ goto __exit;
+ }
+
+ rt_memset(send_data, 0x00, SAL_INTERNET_BUFF_LEN);
+ send_data[0] = SAL_INTERNET_VERSION;
+ for (index = 0; index < netdev->hwaddr_len; index++)
+ {
+ send_data[index + 1] = netdev->hwaddr[index] + moth_num;
+ }
+ send_data[9] = RT_VERSION;
+ send_data[10] = RT_SUBVERSION;
+ send_data[11] = RT_REVISION;
+
+ skt_ops->sendto(sockfd, send_data, SAL_INTERNET_BUFF_LEN, 0,
+ (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
+
+ result = skt_ops->recvfrom(sockfd, &recv_data, sizeof(recv_data), 0, (struct sockaddr *)&server_addr, &addr_len);
+ if (result < 0)
+ {
+ goto __exit;
+ }
+
+ if (recv_data == RT_FALSE)
+ {
+ result = -RT_ERROR;
+ goto __exit;
+ }
+
+__exit:
+ if (result > 0)
+ {
+ LOG_D("Set network interface device(%s) internet status up.", netdev->name);
+ netdev->flags |= NETDEV_FLAG_INTERNET_UP;
+ }
+ else
+ {
+ LOG_D("Set network interface device(%s) internet status down.", netdev->name);
+ netdev->flags &= ~NETDEV_FLAG_INTERNET_UP;
+ }
+
+ if (sockfd >= 0)
+ {
+ skt_ops->closesocket(sockfd);
+ }
}
/**
- * This function will judge whether protocol family is registered
+ * This function will check SAL network interface device internet status.
*
- * @param family protocol family number
- *
- * @return 1: protocol family is registered
- * 0: protocol family is not registered
+ * @param netdev the network interface device to check
*/
-rt_bool_t sal_proto_family_is_registered(int family)
+int sal_check_netdev_internet_up(struct netdev *netdev)
{
- int idx = 0;
+ /* workqueue for network connect */
+ struct rt_delayed_work *net_work = RT_NULL;
- RT_ASSERT(family > 0 && family < AF_MAX);
+ RT_ASSERT(netdev);
- for (idx = 0; idx < SAL_PROTO_FAMILIES_NUM; idx++)
+ net_work = (struct rt_delayed_work *)rt_calloc(1, sizeof(struct rt_delayed_work));
+ if (net_work == RT_NULL)
{
- if (proto_families[idx].family == family && proto_families[idx].create)
- {
- return RT_TRUE;
- }
+ LOG_W("No memory for network interface device(%s) delay work.", netdev->name);
+ return -1;
}
- return RT_FALSE;
+ rt_delayed_work_init(net_work, check_netdev_internet_up_work, (void *)netdev);
+ rt_work_submit(&(net_work->work), RT_TICK_PER_SECOND);
+
+ return 0;
}
/**
- * This function will get protocol family object by family number.
+ * This function will register TLS protocol to the global TLS protocol.
*
- * @param family protocol family number
+ * @param pt TLS protocol object
*
- * @return protocol family object
+ * @return 0: TLS protocol object register success
*/
-struct sal_proto_family *sal_proto_family_find(int family)
+#ifdef SAL_USING_TLS
+int sal_proto_tls_register(const struct sal_proto_tls *pt)
{
- int idx = 0;
-
- RT_ASSERT(family > 0 && family < AF_MAX);
-
- for (idx = 0; idx < SAL_PROTO_FAMILIES_NUM; idx++)
- {
- if (proto_families[idx].family == family && proto_families[idx].create)
- {
- return &proto_families[idx];
- }
- }
+ RT_ASSERT(pt);
+ proto_tls = (struct sal_proto_tls *) pt;
- return RT_NULL;
+ return 0;
}
+#endif
/**
* This function will get sal socket object by sal socket descriptor.
@@ -262,10 +316,7 @@ struct sal_socket *sal_get_socket(int socket)
socket = socket - SAL_SOCKET_OFFSET;
/* check socket structure valid or not */
- if (st->sockets[socket]->magic != SAL_SOCKET_MAGIC)
- {
- return RT_NULL;
- }
+ RT_ASSERT(st->sockets[socket]->magic == SAL_SOCKET_MAGIC);
return st->sockets[socket];
}
@@ -297,33 +348,35 @@ static void sal_unlock(void)
}
/**
- * This function will get protocol family structure by family type
- *
- * @param family protocol family
+ * This function will clean the netdev.
*
- * @return protocol family structure address
+ * @note please don't invoke it on ISR.
*/
-static struct sal_proto_family *get_proto_family(int family)
+int sal_netdev_cleanup(struct netdev *netdev)
{
- int idx;
+ int idx = 0, find_dev;
- for (idx = 0; idx < SAL_PROTO_FAMILIES_NUM; idx++)
+ do
{
- if (proto_families[idx].family == family && proto_families[idx].create)
+ find_dev = 0;
+ sal_lock();
+ for (idx = 0; idx < socket_table.max_socket; idx++)
{
- return &proto_families[idx];
+ if (socket_table.sockets[idx] && socket_table.sockets[idx]->netdev == netdev)
+ {
+ find_dev = 1;
+ break;
+ }
}
- }
- /* compare the secondary protocol families when primary protocol families find failed */
- for (idx = 0; idx < SAL_PROTO_FAMILIES_NUM; idx++)
- {
- if (proto_families[idx].sec_family == family && proto_families[idx].create)
+ sal_unlock();
+ if (find_dev)
{
- return &proto_families[idx];
+ rt_thread_mdelay(100);
}
}
+ while (find_dev);
- return RT_NULL;
+ return 0;
}
/**
@@ -337,13 +390,16 @@ static struct sal_proto_family *get_proto_family(int family)
* @return 0 : socket initialize success
* -1 : input the wrong family
* -2 : input the wrong socket type
- * -3 : get protocol family object failed
- * -4 : set socket options failed
+ * -3 : get network interface failed
*/
static int socket_init(int family, int type, int protocol, struct sal_socket **res)
{
+
struct sal_socket *sock;
struct sal_proto_family *pf;
+ struct netdev *netdv_def = netdev_default;
+ struct netdev *netdev = RT_NULL;
+ rt_bool_t flag = RT_FALSE;
if (family < 0 || family > AF_MAX)
{
@@ -360,16 +416,28 @@ static int socket_init(int family, int type, int protocol, struct sal_socket **r
sock->type = type;
sock->protocol = protocol;
- /* get socket protocol family object */
- if ((pf = get_proto_family(family)) == RT_NULL)
+ if (netdv_def && netdev_is_up(netdv_def))
{
- return -3;
+ /* check default network interface device protocol family */
+ pf = (struct sal_proto_family *) netdv_def->sal_user_data;
+ if (pf != RT_NULL && pf->skt_ops && (pf->family == family || pf->sec_family == family))
+ {
+ sock->netdev = netdv_def;
+ flag = RT_TRUE;
+ }
}
- /* registered the current socket options */
- if (pf->create(sock, type, protocol) != 0)
+ if (flag == RT_FALSE)
{
- return -4;
+ /* get network interface device by protocol family */
+ netdev = netdev_get_by_family(family);
+ if (netdev == RT_NULL)
+ {
+ LOG_E("not find network interface device by protocol family(%d).", family);
+ return -3;
+ }
+
+ sock->netdev = netdev;
}
return 0;
@@ -383,9 +451,9 @@ static int socket_alloc(struct sal_socket_table *st, int f_socket)
for (idx = f_socket; idx < (int) st->max_socket; idx++)
{
if (st->sockets[idx] == RT_NULL)
+ {
break;
- if (st->sockets[idx]->ops == RT_NULL)
- break;
+ }
}
/* allocate a larger sockte container */
@@ -424,7 +492,15 @@ static int socket_alloc(struct sal_socket_table *st, int f_socket)
__result:
return idx;
+}
+static void socket_free(struct sal_socket_table *st, int idx)
+{
+ struct sal_socket *sock;
+
+ sock = st->sockets[idx];
+ st->sockets[idx] = RT_NULL;
+ rt_free(sock);
}
static int socket_new(void)
@@ -448,7 +524,7 @@ static int socket_new(void)
sock = st->sockets[idx];
sock->socket = idx + SAL_SOCKET_OFFSET;
sock->magic = SAL_SOCKET_MAGIC;
- sock->ops = RT_NULL;
+ sock->netdev = RT_NULL;
sock->user_data = RT_NULL;
#ifdef SAL_USING_TLS
sock->user_data_tls = RT_NULL;
@@ -459,23 +535,42 @@ __result:
return idx + SAL_SOCKET_OFFSET;
}
-int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen)
+static void socket_delete(int socket)
{
- int new_socket;
struct sal_socket *sock;
+ struct sal_socket_table *st = &socket_table;
+ int idx;
- sock = sal_get_socket(socket);
- if (!sock)
+ idx = socket - SAL_SOCKET_OFFSET;
+ if (idx < 0 || idx >= (int) st->max_socket)
{
- return -1;
+ return;
}
+ sal_lock();
+ sock = sal_get_socket(socket);
+ RT_ASSERT(sock != RT_NULL);
+ sock->magic = 0;
+ sock->netdev = RT_NULL;
+ socket_free(st, idx);
+ sal_unlock();
+}
- if (sock->ops->accept == RT_NULL)
- {
- return -RT_ENOSYS;
- }
+int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen)
+{
+ int new_socket;
+ struct sal_socket *sock;
+ struct sal_proto_family *pf;
+
+ /* get the socket object by socket descriptor */
+ SAL_SOCKET_OBJ_GET(sock, socket);
- new_socket = sock->ops->accept((int) sock->user_data, addr, addrlen);
+ /* check the network interface is up status */
+ SAL_NETDEV_IS_UP(sock->netdev);
+
+ /* check the network interface socket operations */
+ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, accept);
+
+ new_socket = pf->skt_ops->accept((int) sock->user_data, addr, addrlen);
if (new_socket != -1)
{
int retval;
@@ -484,23 +579,25 @@ int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen)
/* allocate a new socket structure and registered socket options */
new_sal_socket = socket_new();
- if (new_sal_socket < 0)
+ new_sock = sal_get_socket(new_sal_socket);
+ if (new_sock == RT_NULL)
{
- sock->ops->closesocket(new_socket);
+ pf->skt_ops->closesocket(new_socket);
return -1;
}
- new_sock = sal_get_socket(new_sal_socket);
retval = socket_init(sock->domain, sock->type, sock->protocol, &new_sock);
if (retval < 0)
{
- sock->ops->closesocket(new_socket);
+ pf->skt_ops->closesocket(new_socket);
rt_memset(new_sock, 0x00, sizeof(struct sal_socket));
+ /* socket init failed, delete socket */
+ socket_delete(new_sal_socket);
LOG_E("New socket registered failed, return error %d.", retval);
return -1;
}
- /* socket struct user_data used to store the acquired new socket */
+ /* socket structure user_data used to store the acquired new socket */
new_sock->user_data = (void *) new_socket;
return new_sal_socket;
@@ -509,40 +606,87 @@ int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen)
return -1;
}
+static void sal_sockaddr_to_ipaddr(const struct sockaddr *name, ip_addr_t *local_ipaddr)
+{
+ const struct sockaddr_in *svr_addr = (const struct sockaddr_in *) name;
+
+#if NETDEV_IPV4 && NETDEV_IPV6
+ local_ipaddr->u_addr.ip4.addr = svr_addr->sin_addr.s_addr;
+ local_ipaddr->type = IPADDR_TYPE_V4;
+#elif NETDEV_IPV4
+ local_ipaddr->addr = svr_addr->sin_addr.s_addr;
+#elif NETDEV_IPV6
+#error "not only support IPV6"
+#endif /* NETDEV_IPV4 && NETDEV_IPV6*/
+}
+
int sal_bind(int socket, const struct sockaddr *name, socklen_t namelen)
{
struct sal_socket *sock;
+ struct sal_proto_family *pf;
+ ip_addr_t input_ipaddr;
- sock = sal_get_socket(socket);
- if (!sock)
- {
- return -1;
- }
+ RT_ASSERT(name);
+
+ /* get the socket object by socket descriptor */
+ SAL_SOCKET_OBJ_GET(sock, socket);
- if (sock->ops->bind == RT_NULL)
+ /* bind network interface by ip address */
+ sal_sockaddr_to_ipaddr(name, &input_ipaddr);
+
+ /* check input ipaddr is default netdev ipaddr */
+ if (!ip_addr_isany_val(input_ipaddr))
{
- return -RT_ENOSYS;
+ struct sal_proto_family *input_pf = RT_NULL, *local_pf = RT_NULL;
+ struct netdev *new_netdev = RT_NULL;
+
+ new_netdev = netdev_get_by_ipaddr(&input_ipaddr);
+ if (new_netdev == RT_NULL)
+ {
+ return -1;
+ }
+
+ /* get input and local ip address proto_family */
+ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, local_pf, bind);
+ SAL_NETDEV_SOCKETOPS_VALID(new_netdev, input_pf, bind);
+
+ /* check the network interface protocol family type */
+ if (input_pf->family != local_pf->family)
+ {
+ int new_socket = -1;
+
+ /* protocol family is different, close old socket and create new socket by input ip address */
+ local_pf->skt_ops->closesocket(socket);
+
+ new_socket = input_pf->skt_ops->socket(input_pf->family, sock->type, sock->protocol);
+ if (new_socket < 0)
+ {
+ return -1;
+ }
+ sock->netdev = new_netdev;
+ sock->user_data = (void *) new_socket;
+ }
}
- return sock->ops->bind((int) sock->user_data, name, namelen);
+ /* check and get protocol families by the network interface device */
+ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, bind);
+ return pf->skt_ops->bind((int) sock->user_data, name, namelen);
}
int sal_shutdown(int socket, int how)
{
struct sal_socket *sock;
+ struct sal_proto_family *pf;
+ int error = 0;
- sock = sal_get_socket(socket);
- if (!sock)
- {
- return -1;
- }
+ /* get the socket object by socket descriptor */
+ SAL_SOCKET_OBJ_GET(sock, socket);
- if (sock->ops->shutdown == RT_NULL)
- {
- return -RT_ENOSYS;
- }
+ /* shutdown operation not need to check network interface status */
+ /* check the network interface socket opreation */
+ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, shutdown);
- if (sock->ops->shutdown((int) sock->user_data, how) == 0)
+ if (pf->skt_ops->shutdown((int) sock->user_data, how) == 0)
{
#ifdef SAL_USING_TLS
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, closesocket))
@@ -553,82 +697,69 @@ int sal_shutdown(int socket, int how)
}
}
#endif
- rt_free(sock);
- socket_table.sockets[socket] = RT_NULL;
- return 0;
+ error = 0;
+ }
+ else
+ {
+ error = -1;
}
- return -1;
+
+ return error;
}
int sal_getpeername(int socket, struct sockaddr *name, socklen_t *namelen)
{
struct sal_socket *sock;
+ struct sal_proto_family *pf;
- sock = sal_get_socket(socket);
- if (!sock)
- {
- return -1;
- }
+ /* get the socket object by socket descriptor */
+ SAL_SOCKET_OBJ_GET(sock, socket);
- if (sock->ops->getpeername == RT_NULL)
- {
- return -RT_ENOSYS;
- }
+ /* check the network interface socket opreation */
+ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, getpeername);
- return sock->ops->getpeername((int) sock->user_data, name, namelen);
+ return pf->skt_ops->getpeername((int) sock->user_data, name, namelen);
}
int sal_getsockname(int socket, struct sockaddr *name, socklen_t *namelen)
{
struct sal_socket *sock;
+ struct sal_proto_family *pf;
- sock = sal_get_socket(socket);
- if (!sock)
- {
- return -1;
- }
+ /* get socket object by socket descriptor */
+ SAL_SOCKET_OBJ_GET(sock, socket);
- if (sock->ops->getsockname == RT_NULL)
- {
- return -RT_ENOSYS;
- }
+ /* check the network interface socket opreation */
+ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, getsockname);
- return sock->ops->getsockname((int) sock->user_data, name, namelen);
+ return pf->skt_ops->getsockname((int) sock->user_data, name, namelen);
}
int sal_getsockopt(int socket, int level, int optname, void *optval, socklen_t *optlen)
{
struct sal_socket *sock;
+ struct sal_proto_family *pf;
- sock = sal_get_socket(socket);
- if (!sock)
- {
- return -1;
- }
+ /* get the socket object by socket descriptor */
+ SAL_SOCKET_OBJ_GET(sock, socket);
- if (sock->ops->getsockopt == RT_NULL)
- {
- return -RT_ENOSYS;
- }
+ /* check the network interface socket opreation */
+ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, getsockopt);
- return sock->ops->getsockopt((int) sock->user_data, level, optname, optval, optlen);
+ return pf->skt_ops->getsockopt((int) sock->user_data, level, optname, optval, optlen);
}
int sal_setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen)
{
struct sal_socket *sock;
+ struct sal_proto_family *pf;
- sock = sal_get_socket(socket);
- if (!sock)
- {
- return -1;
- }
+ /* get the socket object by socket descriptor */
+ SAL_SOCKET_OBJ_GET(sock, socket);
- if (sock->ops->setsockopt == RT_NULL)
- {
- return -RT_ENOSYS;
- }
+ /* check the network interface socket opreation */
+ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, setsockopt);
#ifdef SAL_USING_TLS
if (level == SOL_TLS)
@@ -659,30 +790,28 @@ int sal_setsockopt(int socket, int level, int optname, const void *optval, sockl
}
else
{
- return sock->ops->setsockopt((int) sock->user_data, level, optname, optval, optlen);
+ return pf->skt_ops->setsockopt((int) sock->user_data, level, optname, optval, optlen);
}
#else
- return sock->ops->setsockopt((int) sock->user_data, level, optname, optval, optlen);
+ return pf->skt_ops->setsockopt((int) sock->user_data, level, optname, optval, optlen);
#endif /* SAL_USING_TLS */
}
int sal_connect(int socket, const struct sockaddr *name, socklen_t namelen)
{
struct sal_socket *sock;
+ struct sal_proto_family *pf;
int ret;
- sock = sal_get_socket(socket);
- if (!sock)
- {
- return -1;
- }
+ /* get the socket object by socket descriptor */
+ SAL_SOCKET_OBJ_GET(sock, socket);
- if (sock->ops->connect == RT_NULL)
- {
- return -RT_ENOSYS;
- }
+ /* check the network interface is up status */
+ SAL_NETDEV_IS_UP(sock->netdev);
+ /* check the network interface socket opreation */
+ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, connect);
- ret = sock->ops->connect((int) sock->user_data, name, namelen);
+ ret = pf->skt_ops->connect((int) sock->user_data, name, namelen);
#ifdef SAL_USING_TLS
if (ret >= 0 && SAL_SOCKOPS_PROTO_TLS_VALID(sock, connect))
{
@@ -690,7 +819,7 @@ int sal_connect(int socket, const struct sockaddr *name, socklen_t namelen)
{
return -1;
}
-
+
return ret;
}
#endif
@@ -701,90 +830,82 @@ int sal_connect(int socket, const struct sockaddr *name, socklen_t namelen)
int sal_listen(int socket, int backlog)
{
struct sal_socket *sock;
+ struct sal_proto_family *pf;
- sock = sal_get_socket(socket);
- if (!sock)
- {
- return -1;
- }
+ /* get the socket object by socket descriptor */
+ SAL_SOCKET_OBJ_GET(sock, socket);
- if (sock->ops->listen == RT_NULL)
- {
- return -RT_ENOSYS;
- }
+ /* check the network interface socket opreation */
+ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, listen);
- return sock->ops->listen((int) sock->user_data, backlog);
+ return pf->skt_ops->listen((int) sock->user_data, backlog);
}
int sal_recvfrom(int socket, void *mem, size_t len, int flags,
- struct sockaddr *from, socklen_t *fromlen)
+ struct sockaddr *from, socklen_t *fromlen)
{
struct sal_socket *sock;
+ struct sal_proto_family *pf;
- sock = sal_get_socket(socket);
- if (!sock)
- {
- return -1;
- }
+ /* get the socket object by socket descriptor */
+ SAL_SOCKET_OBJ_GET(sock, socket);
- if (sock->ops->recvfrom == RT_NULL)
- {
- return -RT_ENOSYS;
- }
+ /* check the network interface is up status */
+ SAL_NETDEV_IS_UP(sock->netdev);
+ /* check the network interface socket opreation */
+ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, recvfrom);
#ifdef SAL_USING_TLS
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, recv))
{
int ret;
-
+
if ((ret = proto_tls->ops->recv(sock->user_data_tls, mem, len)) < 0)
{
return -1;
- }
+ }
return ret;
}
else
{
- return sock->ops->recvfrom((int) sock->user_data, mem, len, flags, from, fromlen);
+ return pf->skt_ops->recvfrom((int) sock->user_data, mem, len, flags, from, fromlen);
}
#else
- return sock->ops->recvfrom((int) sock->user_data, mem, len, flags, from, fromlen);
+ return pf->skt_ops->recvfrom((int) sock->user_data, mem, len, flags, from, fromlen);
#endif
}
int sal_sendto(int socket, const void *dataptr, size_t size, int flags,
- const struct sockaddr *to, socklen_t tolen)
+ const struct sockaddr *to, socklen_t tolen)
{
struct sal_socket *sock;
+ struct sal_proto_family *pf;
- sock = sal_get_socket(socket);
- if (!sock)
- {
- return -1;
- }
+ /* get the socket object by socket descriptor */
+ SAL_SOCKET_OBJ_GET(sock, socket);
- if (sock->ops->sendto == RT_NULL)
- {
- return -RT_ENOSYS;
- }
+ /* check the network interface is up status */
+ SAL_NETDEV_IS_UP(sock->netdev);
+ /* check the network interface socket opreation */
+ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, sendto);
#ifdef SAL_USING_TLS
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, send))
{
int ret;
-
+
if ((ret = proto_tls->ops->send(sock->user_data_tls, dataptr, size)) < 0)
{
return -1;
- }
+ }
return ret;
}
else
{
- return sock->ops->sendto((int) sock->user_data, dataptr, size, flags, to, tolen);
+ return pf->skt_ops->sendto((int) sock->user_data, dataptr, size, flags, to, tolen);
}
#else
- return sock->ops->sendto((int) sock->user_data, dataptr, size, flags, to, tolen);
+ return pf->skt_ops->sendto((int) sock->user_data, dataptr, size, flags, to, tolen);
#endif
}
@@ -793,6 +914,7 @@ int sal_socket(int domain, int type, int protocol)
int retval;
int socket, proto_socket;
struct sal_socket *sock;
+ struct sal_proto_family *pf;
/* allocate a new socket and registered socket options */
socket = socket_new();
@@ -800,29 +922,37 @@ int sal_socket(int domain, int type, int protocol)
{
return -1;
}
+
+ /* get sal socket object by socket descriptor */
sock = sal_get_socket(socket);
+ if (sock == RT_NULL)
+ {
+ socket_delete(socket);
+ return -1;
+ }
+ /* Initialize sal socket object */
retval = socket_init(domain, type, protocol, &sock);
if (retval < 0)
{
LOG_E("SAL socket protocol family input failed, return error %d.", retval);
+ socket_delete(socket);
return -1;
}
- if (sock->ops->socket == RT_NULL)
- {
- return -RT_ENOSYS;
- }
+ /* valid the network interface socket opreation */
+ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, socket);
- proto_socket = sock->ops->socket(domain, type, protocol);
+ proto_socket = pf->skt_ops->socket(domain, type, protocol);
if (proto_socket >= 0)
{
#ifdef SAL_USING_TLS
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, socket))
{
- sock->user_data_tls = proto_tls->ops->socket(proto_socket);
+ sock->user_data_tls = proto_tls->ops->socket(socket);
if (sock->user_data_tls == RT_NULL)
{
+ socket_delete(socket);
return -1;
}
}
@@ -830,26 +960,24 @@ int sal_socket(int domain, int type, int protocol)
sock->user_data = (void *) proto_socket;
return sock->socket;
}
-
+ socket_delete(socket);
return -1;
}
int sal_closesocket(int socket)
{
struct sal_socket *sock;
+ struct sal_proto_family *pf;
+ int error = 0;
- sock = sal_get_socket(socket);
- if (!sock)
- {
- return -1;
- }
+ /* get the socket object by socket descriptor */
+ SAL_SOCKET_OBJ_GET(sock, socket);
- if (sock->ops->closesocket == RT_NULL)
- {
- return -RT_ENOSYS;
- }
+ /* clsoesocket operation not need to vaild network interface status */
+ /* valid the network interface socket opreation */
+ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, socket);
- if (sock->ops->closesocket((int) sock->user_data) == 0)
+ if (pf->skt_ops->closesocket((int) sock->user_data) == 0)
{
#ifdef SAL_USING_TLS
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, closesocket))
@@ -860,67 +988,68 @@ int sal_closesocket(int socket)
}
}
#endif
- rt_free(sock);
- socket_table.sockets[socket] = RT_NULL;
- return 0;
+ error = 0;
+ }
+ else
+ {
+ error = -1;
}
- return -1;
+ /* delete socket */
+ socket_delete(socket);
+
+ return error;
}
int sal_ioctlsocket(int socket, long cmd, void *arg)
{
struct sal_socket *sock;
+ struct sal_proto_family *pf;
- sock = sal_get_socket(socket);
- if (!sock)
- {
- return -1;
- }
+ /* get the socket object by socket descriptor */
+ SAL_SOCKET_OBJ_GET(sock, socket);
- if (sock->ops->ioctlsocket == RT_NULL)
- {
- return -RT_ENOSYS;
- }
+ /* check the network interface socket opreation */
+ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, ioctlsocket);
- return sock->ops->ioctlsocket((int) sock->user_data, cmd, arg);
+ return pf->skt_ops->ioctlsocket((int) sock->user_data, cmd, arg);
}
#ifdef SAL_USING_POSIX
int sal_poll(struct dfs_fd *file, struct rt_pollreq *req)
{
struct sal_socket *sock;
+ struct sal_proto_family *pf;
int socket = (int) file->data;
- sock = sal_get_socket(socket);
- if (!sock)
- {
- return -1;
- }
+ /* get the socket object by socket descriptor */
+ SAL_SOCKET_OBJ_GET(sock, socket);
- if (sock->ops->poll == RT_NULL)
- {
- return -RT_ENOSYS;
- }
+ /* check the network interface is up status */
+ SAL_NETDEV_IS_UP(sock->netdev);
+ /* check the network interface socket opreation */
+ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, poll);
- return sock->ops->poll(file, req);
+ return pf->skt_ops->poll(file, req);
}
#endif
struct hostent *sal_gethostbyname(const char *name)
{
- int i;
- struct hostent *hst;
+ struct netdev *netdev = netdev_default;
+ struct sal_proto_family *pf;
- for (i = 0; i < SAL_PROTO_FAMILIES_NUM; ++i)
+ if (SAL_NETDEV_NETDBOPS_VALID(netdev, pf, gethostbyname))
{
- if (proto_families[i].ops && proto_families[i].ops->gethostbyname)
+ return pf->netdb_ops->gethostbyname(name);
+ }
+ else
+ {
+ /* get the first network interface device with up status */
+ netdev = netdev_get_first_by_flags(NETDEV_FLAG_UP);
+ if (SAL_NETDEV_NETDBOPS_VALID(netdev, pf, gethostbyname))
{
- hst = proto_families[i].ops->gethostbyname(name);
- if (hst != RT_NULL)
- {
- return hst;
- }
+ return pf->netdb_ops->gethostbyname(name);
}
}
@@ -928,19 +1057,22 @@ struct hostent *sal_gethostbyname(const char *name)
}
int sal_gethostbyname_r(const char *name, struct hostent *ret, char *buf,
- size_t buflen, struct hostent **result, int *h_errnop)
+ size_t buflen, struct hostent **result, int *h_errnop)
{
- int i, res;
+ struct netdev *netdev = netdev_default;
+ struct sal_proto_family *pf;
- for (i = 0; i < SAL_PROTO_FAMILIES_NUM; ++i)
+ if (SAL_NETDEV_NETDBOPS_VALID(netdev, pf, gethostbyname_r))
+ {
+ return pf->netdb_ops->gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
+ }
+ else
{
- if (proto_families[i].ops && proto_families[i].ops->gethostbyname_r)
+ /* get the first network interface device with up status */
+ netdev = netdev_get_first_by_flags(NETDEV_FLAG_UP);
+ if (SAL_NETDEV_NETDBOPS_VALID(netdev, pf, gethostbyname_r))
{
- res = proto_families[i].ops->gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
- if (res == 0)
- {
- return res;
- }
+ return pf->netdb_ops->gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
}
}
@@ -948,21 +1080,24 @@ int sal_gethostbyname_r(const char *name, struct hostent *ret, char *buf,
}
int sal_getaddrinfo(const char *nodename,
- const char *servname,
- const struct addrinfo *hints,
- struct addrinfo **res)
+ const char *servname,
+ const struct addrinfo *hints,
+ struct addrinfo **res)
{
- int i, ret;
+ struct netdev *netdev = netdev_default;
+ struct sal_proto_family *pf;
- for (i = 0; i < SAL_PROTO_FAMILIES_NUM; ++i)
+ if (SAL_NETDEV_NETDBOPS_VALID(netdev, pf, getaddrinfo))
+ {
+ return pf->netdb_ops->getaddrinfo(nodename, servname, hints, res);
+ }
+ else
{
- if (proto_families[i].ops && proto_families[i].ops->getaddrinfo)
+ /* get the first network interface device with up status */
+ netdev = netdev_get_first_by_flags(NETDEV_FLAG_UP);
+ if (SAL_NETDEV_NETDBOPS_VALID(netdev, pf, getaddrinfo))
{
- ret = proto_families[i].ops->getaddrinfo(nodename, servname, hints, res);
- if (ret == 0)
- {
- return ret;
- }
+ return pf->netdb_ops->getaddrinfo(nodename, servname, hints, res);
}
}
@@ -971,14 +1106,21 @@ int sal_getaddrinfo(const char *nodename,
void sal_freeaddrinfo(struct addrinfo *ai)
{
- int i;
+ struct netdev *netdev = netdev_default;
+ struct sal_proto_family *pf;
- for (i = 0; i < SAL_PROTO_FAMILIES_NUM; ++i)
+ if (SAL_NETDEV_NETDBOPS_VALID(netdev, pf, freeaddrinfo))
{
- if (proto_families[i].ops && proto_families[i].ops->freeaddrinfo)
+ pf->netdb_ops->freeaddrinfo(ai);
+ }
+ else
+ {
+ /* get the first network interface device with up status */
+ netdev = netdev_get_first_by_flags(NETDEV_FLAG_UP);
+ if (SAL_NETDEV_NETDBOPS_VALID(netdev, pf, freeaddrinfo))
{
- proto_families[i].ops->freeaddrinfo(ai);
- return;
+ pf->netdb_ops->freeaddrinfo(ai);
}
}
}
+