rtt更新

This commit is contained in:
2025-01-18 13:25:25 +08:00
parent c6a7554b51
commit d6009a0773
726 changed files with 103376 additions and 6270 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -138,6 +138,8 @@ struct at_socket
uint16_t sendevent;
/* error happened for this socket, set by event_callback() */
uint16_t errevent;
/* Last UDP connect address */
struct sockaddr last_udp_adr;
#ifdef SAL_USING_POSIX
rt_wqueue_t wait_head;
@@ -166,6 +168,7 @@ int at_recv(int socket, void *mem, size_t len, int flags);
int at_getsockopt(int socket, int level, int optname, void *optval, socklen_t *optlen);
int at_setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen);
struct hostent *at_gethostbyname(const char *name);
int at_gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop);
int at_getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res);
void at_freeaddrinfo(struct addrinfo *ai);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2025, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -14,6 +14,7 @@
#include <stddef.h>
#include <rtthread.h>
#include <rtdevice.h>
#ifdef __cplusplus
extern "C" {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
* Copyright (c) 2006-2025, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -10,6 +10,7 @@
* 2018-08-17 chenyong multiple client support
* 2021-03-17 Meco Man fix a buf of leaking memory
* 2021-07-14 Sszl fix a buf of leaking memory
* 2025-01-02 dongly support SERIAL_V2
*/
#include <at.h>
@@ -960,6 +961,10 @@ int at_client_init(const char *dev_name, rt_size_t recv_bufsz, rt_size_t send_bu
RT_ASSERT(client->device->type == RT_Device_Class_Char);
rt_device_set_rx_indicate(client->device, at_client_rx_ind);
#ifdef RT_USING_SERIAL_V2
open_result = rt_device_open(client->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_RX_NON_BLOCKING);
#else
/* using DMA mode first */
open_result = rt_device_open(client->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_DMA_RX);
/* using interrupt mode when DMA mode not supported */
@@ -967,6 +972,7 @@ int at_client_init(const char *dev_name, rt_size_t recv_bufsz, rt_size_t send_bu
{
open_result = rt_device_open(client->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
}
#endif /* RT_USING_SERIAL_V2 */
RT_ASSERT(open_result == RT_EOK);
}
else

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2025, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -7,6 +7,7 @@
* Date Author Notes
* 2018-03-30 chenyong first version
* 2018-04-14 chenyong modify parse arguments
* 2025-01-02 dongly support SERIAL_V2
*/
#include <at.h>
@@ -565,6 +566,10 @@ int at_server_init(void)
RT_ASSERT(at_server_local->device->type == RT_Device_Class_Char);
rt_device_set_rx_indicate(at_server_local->device, at_rx_ind);
#ifdef RT_USING_SERIAL_V2
open_result = rt_device_open(client->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_RX_NON_BLOCKING);
#else
/* using DMA mode first */
open_result = rt_device_open(at_server_local->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_DMA_RX);
/* using interrupt mode when DMA mode not supported */
@@ -572,6 +577,7 @@ int at_server_init(void)
{
open_result = rt_device_open(at_server_local->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
}
#endif /* RT_USING_SERIAL_V2 */
RT_ASSERT(open_result == RT_EOK);
}
else

View File

@@ -736,7 +736,7 @@ void dhcpd_start(const char *netif_name)
DEBUG_PRINTF("ip_start: [%s]\r\n", str_tmp);
sprintf(p, "%d", DHCPD_CLIENT_IP_MAX);
ip4addr_aton(str_tmp, &ip_end);
DEBUG_PRINTF("ip_start: [%s]\r\n", str_tmp);
DEBUG_PRINTF("ip_end: [%s]\r\n", str_tmp);
res = dhcp_server_start(netif, &ip_start, &ip_end);
if (res != 0)

View File

@@ -281,6 +281,10 @@ if RT_USING_LWIP
endif
endif
config RT_LWIP_ENABLE_USER_HOOKS
bool "Enable user-defined LWIP hooks"
default n
menuconfig RT_LWIP_DEBUG
bool "Enable lwIP Debugging Options"
default n

View File

@@ -99,6 +99,10 @@
#include <rtthread.h>
#ifdef RT_USING_NETDEV
#include "netdev.h"
#endif
/** Random generator function to create random TXIDs and source ports for queries */
#ifndef DNS_RAND_TXID
#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_XID) != 0)
@@ -300,7 +304,9 @@ static u8_t dns_last_pcb_idx;
static u8_t dns_seqno;
static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
static struct dns_req_entry dns_requests[DNS_MAX_REQUESTS];
#ifndef RT_USING_NETDEV
static ip_addr_t dns_servers[DNS_MAX_SERVERS];
#endif
#if LWIP_IPV4
const ip_addr_t dns_mquery_v4group = DNS_MQUERY_IPV4_GROUP_INIT;
@@ -364,21 +370,25 @@ dns_setserver(u8_t numdns, const ip_addr_t *dnsserver)
{
if (numdns < DNS_MAX_SERVERS) {
if (dnsserver != NULL) {
dns_servers[numdns] = (*dnsserver);
#ifdef RT_USING_NETDEV
extern struct netif *netif_list;
extern struct netdev *netdev_get_by_name(const char *name);
extern void netdev_low_level_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_t *dns_server);
struct netif *netif = NULL;
/* set network interface device DNS server address */
for (netif = netif_list; netif != NULL; netif = netif->next) {
netdev_low_level_set_dns_server(netdev_get_by_name(netif->name), numdns, dnsserver);
netdev_set_dns_server(netdev_get_by_name(netif->name), numdns, dnsserver);
}
#else
dns_servers[numdns] = (*dnsserver);
#endif /* RT_USING_NETDEV */
} else {
#ifdef RT_USING_NETDEV
struct netif *netif = NULL;
for (netif = netif_list; netif != NULL; netif = netif->next) {
netdev_set_dns_server(netdev_get_by_name(netif->name), numdns, IP_ADDR_ANY);
}
#else
dns_servers[numdns] = *IP_ADDR_ANY;
#endif
}
}
}
@@ -395,7 +405,11 @@ const ip_addr_t *
dns_getserver(u8_t numdns)
{
if (numdns < DNS_MAX_SERVERS) {
#ifdef RT_USING_NETDEV
return &netdev_default->dns_servers[numdns];
#else
return &dns_servers[numdns];
#endif
} else {
return IP_ADDR_ANY;
}
@@ -770,11 +784,19 @@ dns_send(u8_t idx)
u8_t n;
u8_t pcb_idx;
struct dns_table_entry *entry = &dns_table[idx];
const ip_addr_t *dns_addr;
LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
(u16_t)(entry->server_idx), entry->name));
LWIP_ASSERT("dns server out of array", entry->server_idx < DNS_MAX_SERVERS);
if (ip_addr_isany_val(dns_servers[entry->server_idx])
#ifdef RT_USING_NETDEV
dns_addr = &netdev_default->dns_servers[entry->server_idx];
#else
dns_addr = &dns_servers[entry->server_idx];
#endif
if (ip_addr_isany(dns_addr)
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
&& !entry->is_mdns
#endif
@@ -859,7 +881,11 @@ dns_send(u8_t idx)
#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
{
dst_port = DNS_SERVER_PORT;
dst = &dns_servers[entry->server_idx];
dst = dns_addr;
#ifdef RT_USING_NETDEV
/* set netif index for this pcb, specify the network interface corresponding to the DNS server */
dns_pcbs[pcb_idx]->netif_idx = netif_get_index((struct netif *)netdev_default->user_data);
#endif
}
err = udp_sendto(dns_pcbs[pcb_idx], p, dst, dst_port);
@@ -1040,8 +1066,15 @@ dns_backupserver_available(struct dns_table_entry *pentry)
u8_t ret = 0;
if (pentry) {
if ((pentry->server_idx + 1 < DNS_MAX_SERVERS) && !ip_addr_isany_val(dns_servers[pentry->server_idx + 1])) {
ret = 1;
if ((pentry->server_idx + 1 < DNS_MAX_SERVERS)) {
#ifdef RT_USING_NETDEV
const ip_addr_t *dns_addr = &netdev_default->dns_servers[pentry->server_idx + 1];
#else
const ip_addr_t *dns_addr = &dns_servers[pentry->server_idx + 1];
#endif
if (!ip_addr_isany(dns_addr)) {
ret = 1;
}
}
}
@@ -1230,9 +1263,14 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
if (!entry->is_mdns)
#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
{
#ifdef RT_USING_NETDEV
const ip_addr_t *dns_addr = &netdev_default->dns_servers[entry->server_idx];
#else
const ip_addr_t *dns_addr = &dns_servers[entry->server_idx];
#endif
/* Check whether response comes from the same network address to which the
question was sent. (RFC 5452) */
if (!ip_addr_cmp(addr, &dns_servers[entry->server_idx])) {
if (!ip_addr_cmp(addr, dns_addr)) {
goto ignore_packet; /* ignore this packet */
}
}
@@ -1631,8 +1669,13 @@ dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_call
if (!is_mdns)
#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
{
#ifdef RT_USING_NETDEV
const ip_addr_t *dns_addr = &netdev_default->dns_servers[0];
#else
const ip_addr_t *dns_addr = &dns_servers[0];
#endif
/* prevent calling found callback if no server is set, return error instead */
if (ip_addr_isany_val(dns_servers[0])) {
if (ip_addr_isany(dns_addr)) {
return ERR_VAL;
}
}

View File

@@ -673,7 +673,16 @@ dhcp_handle_ack(struct netif *netif, struct dhcp_msg *msg_in)
for (n = 0; (n < LWIP_DHCP_PROVIDE_DNS_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) {
ip_addr_t dns_addr;
ip_addr_set_ip4_u32_val(dns_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n)));
#ifdef RT_USING_NETDEV
extern struct netdev *netdev_get_by_name(const char *name);
extern void netdev_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_t *dns_server);
/* Here we only need to set the dns server of the corresponding network device,
* but do not need to configure all network devices.
*/
netdev_set_dns_server(netdev_get_by_name(netif->name), n, &dns_addr);
#else
dns_setserver(n, &dns_addr);
#endif
}
#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
}

View File

@@ -538,7 +538,16 @@ dhcp6_handle_config_reply(struct netif *netif, struct pbuf *p_msg_in)
}
ip6_addr_assign_zone(dns_addr6, IP6_UNKNOWN, netif);
/* @todo: do we need a different offset than DHCP(v4)? */
#ifdef RT_USING_NETDEV
extern struct netdev *netdev_get_by_name(const char *name);
extern void netdev_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_t *dns_server);
/* Here we only need to set the dns server of the corresponding network device,
* but do not need to configure all network devices.
*/
netdev_set_dns_server(netdev_get_by_name(netif->name), n, &dns_addr);
#else
dns_setserver(n, &dns_addr);
#endif
}
}
/* @ todo: parse and set Domain Search List */

View File

@@ -776,14 +776,32 @@ nd6_input(struct pbuf *p, struct netif *inp)
if (htonl(rdnss_opt->lifetime) > 0) {
/* TODO implement Lifetime > 0 */
#ifdef RT_USING_NETDEV
extern struct netdev *netdev_get_by_name(const char *name);
extern void netdev_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_t *dns_server);
/* Here we only need to set the dns server of the corresponding network device,
* but do not need to configure all network devices.
*/
netdev_set_dns_server(netdev_get_by_name(inp->name), rdnss_server_idx++, &rdnss_address);
#else
dns_setserver(rdnss_server_idx++, &rdnss_address);
#endif
} else {
/* TODO implement DNS removal in dns.c */
u8_t s;
for (s = 0; s < DNS_MAX_SERVERS; s++) {
const ip_addr_t *addr = dns_getserver(s);
if(ip_addr_cmp(addr, &rdnss_address)) {
dns_setserver(s, NULL);
#ifdef RT_USING_NETDEV
extern struct netdev *netdev_get_by_name(const char *name);
extern void netdev_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_t *dns_server);
/* Here we only need to set the dns server of the corresponding network device,
* but do not need to configure all network devices.
*/
netdev_set_dns_server(netdev_get_by_name(inp->name), s, IP_ADDR_ANY);
#else
dns_setserver(s, IP_ADDR_ANY);
#endif
}
}
}

View File

@@ -495,6 +495,18 @@ typedef struct fd_set
/* poll-related defines and types */
/* @todo: find a better way to guard the definition of these defines and types if already defined */
#if !defined(POLLIN) && !defined(POLLOUT)
#ifdef RT_USING_MUSLLIBC
#define POLLIN 0x001 /**< There is data to read. */
#define POLLPRI 0x002 /**< There is urgent data to read. */
#define POLLOUT 0x004 /**< Writing is now possible. */
#define POLLERR 0x008 /**< Error condition. */
#define POLLHUP 0x010 /**< Hang up. */
#define POLLNVAL 0x020 /**< Invalid polling request. */
#define POLLRDNORM 0x040 /**< Normal data may be read. */
#define POLLRDBAND 0x080 /**< Priority data may be read. */
#define POLLWRNORM 0x100 /**< Writing normal data is possible. */
#define POLLWRBAND 0x200 /**< Writing priority data is possible. */
#else
#define POLLIN 0x1
#define POLLOUT 0x2
#define POLLERR 0x4
@@ -506,6 +518,7 @@ typedef struct fd_set
#define POLLWRNORM 0x80
#define POLLWRBAND 0x100
#define POLLHUP 0x200
#endif /* RT_USING_MUSLLIBC */
typedef unsigned int nfds_t;
struct pollfd
{

View File

@@ -24,7 +24,8 @@
*
******************************************************************************
* REVISION HISTORY
*
* 24-09-12 Evlers <1425295900@qq.com>
* add support for independent dns services for multiple network devices
* 03-01-01 Marc Boucher <marc@mbsi.ca>
* Ported to lwIP.
* 97-11-05 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
@@ -134,6 +135,9 @@
#if PPP_IPV6_SUPPORT
#include "netif/ppp/ipv6cp.h"
#endif /* PPP_IPV6_SUPPORT */
#ifdef RT_USING_NETDEV
#include "netdev.h"
#endif /* RT_USING_NETDEV */
/*************************/
/*** LOCAL DEFINITIONS ***/
@@ -1109,9 +1113,20 @@ int sdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) {
LWIP_UNUSED_ARG(pcb);
ip_addr_set_ip4_u32_val(ns, ns1);
#ifdef RT_USING_NETDEV
/* Here we only need to set the dns server of the corresponding network device,
* but do not need to configure all network cards.
*/
netdev_set_dns_server(netdev_get_by_name(pcb->netif->name), 0, &ns);
#else
dns_setserver(0, &ns);
#endif
ip_addr_set_ip4_u32_val(ns, ns2);
#ifdef RT_USING_NETDEV
netdev_set_dns_server(netdev_get_by_name(pcb->netif->name), 1, &ns);
#else
dns_setserver(1, &ns);
#endif
return 1;
}
@@ -1127,12 +1142,20 @@ int cdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) {
nsa = dns_getserver(0);
ip_addr_set_ip4_u32_val(nsb, ns1);
if (ip_addr_cmp(nsa, &nsb)) {
#ifdef RT_USING_NETDEV
netdev_set_dns_server(netdev_get_by_name(pcb->netif->name), 0, IP_ADDR_ANY);
#else
dns_setserver(0, IP_ADDR_ANY);
#endif
}
nsa = dns_getserver(1);
ip_addr_set_ip4_u32_val(nsb, ns2);
if (ip_addr_cmp(nsa, &nsb)) {
#ifdef RT_USING_NETDEV
netdev_set_dns_server(netdev_get_by_name(pcb->netif->name), 1, IP_ADDR_ANY);
#else
dns_setserver(1, IP_ADDR_ANY);
#endif
}
return 1;
}

View File

@@ -15,6 +15,7 @@
* 2018-11-02 MurphyZhao port to lwIP 2.1.0
* 2021-09-07 Grissiom fix eth_tx_msg ack bug
* 2022-02-22 xiangxistu integrate v1.4.1 v2.0.3 and v2.1.2 porting layer
* 2024-09-12 Evlers add support for independent dns services for multiple network devices
*/
/*
@@ -169,8 +170,11 @@ static int lwip_netdev_set_addr_info(struct netdev *netif, ip_addr_t *ip_addr, i
}
#ifdef RT_LWIP_DNS
static int lwip_netdev_set_dns_server(struct netdev *netif, uint8_t dns_num, ip_addr_t *dns_server)
static int lwip_netdev_set_dns_server(struct netdev *netdev, uint8_t dns_num, ip_addr_t *dns_server)
{
#if RT_USING_LWIP_VER_NUM >= 0x20102
netdev_low_level_set_dns_server(netdev, dns_num, dns_server);
#else
#if LWIP_VERSION_MAJOR == 1U /* v1.x */
extern void dns_setserver(u8_t numdns, ip_addr_t *dnsserver);
#else /* >=2.x */
@@ -178,6 +182,7 @@ static int lwip_netdev_set_dns_server(struct netdev *netif, uint8_t dns_num, ip_
#endif /* LWIP_VERSION_MAJOR == 1U */
dns_setserver(dns_num, dns_server);
#endif /* RT_USING_LWIP_VER_NUM >= 0x20102 */
return ERR_OK;
}
#endif /* RT_LWIP_DNS */
@@ -421,6 +426,11 @@ static int netdev_add(struct netif *lwip_netif)
netdev->gw = lwip_netif->gw;
netdev->netmask = lwip_netif->netmask;
#ifdef NETDEV_USING_LINK_STATUS_CALLBACK
extern void netdev_status_change(struct netdev *netdev, enum netdev_cb_type type);
netdev_set_status_callback(netdev, netdev_status_change);
#endif
return result;
}

View File

@@ -654,4 +654,15 @@
#endif
#endif /* RT_USING_LWIP_VER_NUM >= 0x20000 */
#ifdef RT_LWIP_ENABLE_USER_HOOKS
/**
 * This hook provides flexibility for handling unknown Ethernet protocols.
 *
 * For example, you can define how to handle packets of unknown types,
 * such as forwarding them to another interface, discarding them,
 * or passing them to an application for further processing.
 */
#define LWIP_HOOK_UNKNOWN_ETH_PROTOCOL lwip_hook_unknown_eth_protocol
#endif /* RT_LWIP_ENABLE_USER_HOOKS */
#endif /* __LWIPOPTS_H__ */

View File

@@ -19,7 +19,11 @@ if RT_USING_NETDEV
config NETDEV_USING_AUTO_DEFAULT
bool "Enable default netdev automatic change features"
default y
config NETDEV_USING_LINK_STATUS_CALLBACK
bool "Enable netdev callback on link status change"
default n
config NETDEV_USING_IPV6
bool "Enable IPV6 protocol support"
default n

View File

@@ -101,6 +101,8 @@ struct netdev
netdev_callback_fn status_callback; /* network interface device flags change callback */
netdev_callback_fn addr_callback; /* network interface device address information change callback */
int ifindex; /* network interface device ifindex */
#ifdef RT_USING_SAL
void *sal_user_data; /* user-specific data for SAL */
#endif /* RT_USING_SAL */
@@ -111,8 +113,6 @@ struct netdev
extern struct netdev *netdev_list;
/* The default network interface device */
extern struct netdev *netdev_default;
/* The local virtual network device */
extern struct netdev *netdev_lo;
/* The network interface device ping response object */
struct netdev_ping_resp
{
@@ -153,10 +153,14 @@ int netdev_unregister(struct netdev *netdev);
struct netdev *netdev_get_first_by_flags(uint16_t flags);
struct netdev *netdev_get_by_ipaddr(ip_addr_t *ip_addr);
struct netdev *netdev_get_by_name(const char *name);
struct netdev *netdev_get_by_ifindex(int ifindex);
#ifdef RT_USING_SAL
struct netdev *netdev_get_by_family(int family);
int netdev_family_get(struct netdev *netdev);
#endif /* RT_USING_SAL */
#if defined(SAL_USING_AF_NETLINK)
int netdev_getnetdev(struct msg_buf *msg, int (*cb)(struct msg_buf *m_buf, struct netdev *nd, int nd_num, int index, int ipvx));
#endif
/* Set default network interface device in list */
void netdev_set_default(struct netdev *netdev);

View File

@@ -35,12 +35,11 @@
struct netdev *netdev_list = RT_NULL;
/* The default network interface device */
struct netdev *netdev_default = RT_NULL;
/* The local virtual network device */
struct netdev *netdev_lo = RT_NULL;
/* The global network register callback */
static netdev_callback_fn g_netdev_register_callback = RT_NULL;
static netdev_callback_fn g_netdev_default_change_callback = RT_NULL;
static RT_DEFINE_SPINLOCK(_spinlock);
static int netdev_num;
/**
* This function will register network interface device and
@@ -55,7 +54,6 @@ static RT_DEFINE_SPINLOCK(_spinlock);
*/
int netdev_register(struct netdev *netdev, const char *name, void *user_data)
{
rt_base_t level;
rt_uint16_t flags_mask;
rt_uint16_t index;
@@ -103,7 +101,7 @@ int netdev_register(struct netdev *netdev, const char *name, void *user_data)
/* initialize current network interface device single list */
rt_slist_init(&(netdev->list));
level = rt_spin_lock_irqsave(&_spinlock);
rt_spin_lock(&_spinlock);
if (netdev_list == RT_NULL)
{
@@ -115,7 +113,10 @@ int netdev_register(struct netdev *netdev, const char *name, void *user_data)
rt_slist_append(&(netdev_list->list), &(netdev->list));
}
rt_spin_unlock_irqrestore(&_spinlock, level);
netdev_num++;
netdev->ifindex = netdev_num;
rt_spin_unlock(&_spinlock);
if (netdev_default == RT_NULL)
{
@@ -146,7 +147,6 @@ int netdev_register(struct netdev *netdev, const char *name, void *user_data)
*/
int netdev_unregister(struct netdev *netdev)
{
rt_base_t level;
rt_slist_t *node = RT_NULL;
struct netdev *cur_netdev = RT_NULL;
@@ -157,7 +157,7 @@ int netdev_unregister(struct netdev *netdev)
return -RT_ERROR;
}
level = rt_spin_lock_irqsave(&_spinlock);
rt_spin_lock(&_spinlock);
for (node = &(netdev_list->list); node; node = rt_slist_next(node))
{
@@ -188,7 +188,7 @@ int netdev_unregister(struct netdev *netdev)
break;
}
}
rt_spin_unlock_irqrestore(&_spinlock, level);
rt_spin_unlock(&_spinlock);
#if defined(SAL_USING_AF_NETLINK)
rtnl_ip_notify(netdev, RTM_DELLINK);
@@ -233,7 +233,6 @@ void netdev_set_register_callback(netdev_callback_fn register_callback)
*/
struct netdev *netdev_get_first_by_flags(uint16_t flags)
{
rt_base_t level;
rt_slist_t *node = RT_NULL;
struct netdev *netdev = RT_NULL;
@@ -242,19 +241,19 @@ struct netdev *netdev_get_first_by_flags(uint16_t flags)
return RT_NULL;
}
level = rt_spin_lock_irqsave(&_spinlock);
rt_spin_lock(&_spinlock);
for (node = &(netdev_list->list); node; node = rt_slist_next(node))
{
netdev = rt_slist_entry(node, struct netdev, list);
if (netdev && (netdev->flags & flags) != 0)
{
rt_spin_unlock_irqrestore(&_spinlock, level);
rt_spin_unlock(&_spinlock);
return netdev;
}
}
rt_spin_unlock_irqrestore(&_spinlock, level);
rt_spin_unlock(&_spinlock);
return RT_NULL;
}
@@ -270,7 +269,6 @@ struct netdev *netdev_get_first_by_flags(uint16_t flags)
*/
struct netdev *netdev_get_by_ipaddr(ip_addr_t *ip_addr)
{
rt_base_t level;
rt_slist_t *node = RT_NULL;
struct netdev *netdev = RT_NULL;
@@ -279,19 +277,19 @@ struct netdev *netdev_get_by_ipaddr(ip_addr_t *ip_addr)
return RT_NULL;
}
level = rt_spin_lock_irqsave(&_spinlock);
rt_spin_lock(&_spinlock);
for (node = &(netdev_list->list); node; node = rt_slist_next(node))
{
netdev = rt_slist_entry(node, struct netdev, list);
if (netdev && ip_addr_cmp(&(netdev->ip_addr), ip_addr))
{
rt_spin_unlock_irqrestore(&_spinlock, level);
rt_spin_unlock(&_spinlock);
return netdev;
}
}
rt_spin_unlock_irqrestore(&_spinlock, level);
rt_spin_unlock(&_spinlock);
return RT_NULL;
}
@@ -307,7 +305,6 @@ struct netdev *netdev_get_by_ipaddr(ip_addr_t *ip_addr)
*/
struct netdev *netdev_get_by_name(const char *name)
{
rt_base_t level;
rt_slist_t *node = RT_NULL;
struct netdev *netdev = RT_NULL;
@@ -316,19 +313,55 @@ struct netdev *netdev_get_by_name(const char *name)
return RT_NULL;
}
level = rt_spin_lock_irqsave(&_spinlock);
rt_spin_lock(&_spinlock);
for (node = &(netdev_list->list); node; node = rt_slist_next(node))
{
netdev = rt_slist_entry(node, struct netdev, list);
if (netdev && (rt_strncmp(netdev->name, name, rt_strlen(name) < RT_NAME_MAX ? rt_strlen(name) : RT_NAME_MAX) == 0))
{
rt_spin_unlock_irqrestore(&_spinlock, level);
rt_spin_unlock(&_spinlock);
return netdev;
}
}
rt_spin_unlock_irqrestore(&_spinlock, level);
rt_spin_unlock(&_spinlock);
return RT_NULL;
}
/**
* This function will get network interface device
* in network interface device list by netdev ifindex.
*
* @param ifindex the ifindex of network interface device
*
* @return != NULL: network interface device object
* NULL: get failed
*/
struct netdev *netdev_get_by_ifindex(int ifindex)
{
rt_slist_t *node = RT_NULL;
struct netdev *netdev = RT_NULL;
if (netdev_list == RT_NULL)
{
return RT_NULL;
}
rt_spin_lock(&_spinlock);
for (node = &(netdev_list->list); node; node = rt_slist_next(node))
{
netdev = rt_slist_entry(node, struct netdev, list);
if (netdev && (netdev->ifindex == ifindex))
{
rt_spin_unlock(&_spinlock);
return netdev;
}
}
rt_spin_unlock(&_spinlock);
return RT_NULL;
}
@@ -345,7 +378,6 @@ struct netdev *netdev_get_by_name(const char *name)
*/
struct netdev *netdev_get_by_family(int family)
{
rt_base_t level;
rt_slist_t *node = RT_NULL;
struct netdev *netdev = RT_NULL;
struct sal_proto_family *pf = RT_NULL;
@@ -355,7 +387,7 @@ struct netdev *netdev_get_by_family(int family)
return RT_NULL;
}
level = rt_spin_lock_irqsave(&_spinlock);
rt_spin_lock(&_spinlock);
for (node = &(netdev_list->list); node; node = rt_slist_next(node))
{
@@ -363,7 +395,7 @@ struct netdev *netdev_get_by_family(int family)
pf = (struct sal_proto_family *) netdev->sal_user_data;
if (pf && pf->skt_ops && pf->family == family && netdev_is_up(netdev))
{
rt_spin_unlock_irqrestore(&_spinlock, level);
rt_spin_unlock(&_spinlock);
return netdev;
}
}
@@ -374,12 +406,12 @@ struct netdev *netdev_get_by_family(int family)
pf = (struct sal_proto_family *) netdev->sal_user_data;
if (pf && pf->skt_ops && pf->sec_family == family && netdev_is_up(netdev))
{
rt_spin_unlock_irqrestore(&_spinlock, level);
rt_spin_unlock(&_spinlock);
return netdev;
}
}
rt_spin_unlock_irqrestore(&_spinlock, level);
rt_spin_unlock(&_spinlock);
return RT_NULL;
}
@@ -400,6 +432,44 @@ int netdev_family_get(struct netdev *netdev)
#endif /* RT_USING_SAL */
#if defined(SAL_USING_AF_NETLINK)
int netdev_getnetdev(struct msg_buf *msg, int (*cb)(struct msg_buf *m_buf, struct netdev *nd, int nd_num, int index, int ipvx))
{
struct netdev *cur_nd_list = netdev_list;
struct netdev *nd_node;
int nd_num = 0;
int err = 0;
if (cur_nd_list == RT_NULL)
return 0;
rt_spin_lock(&_spinlock);
nd_num = rt_slist_len(&cur_nd_list->list) + 1;
rt_spin_unlock(&_spinlock);
err = cb(msg, cur_nd_list, nd_num, nd.ifindex, ROUTE_IPV4_TRUE);
if (err < 0)
return err;
rt_spin_lock(&_spinlock);
rt_slist_for_each_entry(nd_node, &(cur_nd_list->list), list)
{
rt_spin_unlock(&_spinlock);
err = cb(msg, nd_node, nd_num, nd.ifindex, ROUTE_IPV4_TRUE);
if (err < 0)
{
return err;
}
rt_spin_lock(&_spinlock);
}
rt_spin_unlock(&_spinlock);
return 0;
}
#endif
/**
* This function will set default network interface device.
*

View File

@@ -99,7 +99,7 @@ static const struct sal_socket_ops at_socket_ops =
static const struct sal_netdb_ops at_netdb_ops =
{
at_gethostbyname,
NULL,
at_gethostbyname_r,
at_getaddrinfo,
at_freeaddrinfo,
};

View File

@@ -10,16 +10,16 @@
#include <rtthread.h>
#ifdef SAL_USING_POSIX
#include <poll.h>
#endif
#include <lwip/sockets.h>
#include <lwip/netdb.h>
#include <lwip/api.h>
#include <lwip/init.h>
#include <lwip/netif.h>
#ifdef SAL_USING_POSIX
#include <poll.h>
#endif
#include <sal_low_lvl.h>
#include <af_inet.h>

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -16,6 +16,31 @@
#include <sys/errno.h>
#include <sys/socket.h>
/**
* @brief Accepts an incoming connection on a listening socket.
*
* This function extracts the first connection request from the queue of pending connections for
* the listening socket specified by 's' and creates a new socket for the connection.
*
* @param s The file descriptor of the listening socket. This socket must be created with
* 'socket()', bound with 'bind()', and set to listen with 'listen()'.
* @param addr A pointer to a 'sockaddr' structure that will receive the address of the connecting entity.
* This structure is filled with the address of the client once the connection is accepted.
* Can be 'NULL' if the address is not needed.
* @param addrlen A pointer to a variable containing the size of 'addr'. When the function returns, this
* variable will hold the actual size of the address returned. Can be 'NULL' if 'addr' is 'NULL'.
*
* @return On success, returns a new file descriptor for the accepted connection. On failure, returns '-1'
* and sets errno to indicate the error.
*
* @note The original socket 's' remains open and continues to listen for additional incoming connections.
* The returned file descriptor is used for communication with the connected client.
*
* @see socket() Creates a socket for accepting connections.
* @see bind() Binds the socket to a local address.
* @see listen() Sets the socket to listen for incoming connections.
* @see close()/closesocket() Closes a socket when it is no longer needed.
*/
int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
{
int new_socket = -1;
@@ -71,6 +96,27 @@ int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
}
RTM_EXPORT(accept);
/**
* @brief Binds a socket to a specific local address and port.
*
* This function assigns a local address to a socket, defined by the 'name' parameter.
* The address allows the socket to receive data sent to this address.
*
* @param s The file descriptor of the socket to bind.
* @param name A pointer to a 'sockaddr' structure that specifies the address to bind to.
* The structure varies based on the address family, such as 'sockaddr_in' for IPv4.
* @param namelen The length of the 'sockaddr' structure pointed to by 'name', in bytes.
*
* @return Returns '0' on success. On failure, returns '-1' and sets errno to indicate the error.
*
* @note The socket must be created with 'socket()' before calling 'bind()'.
* Binding is typically used for server sockets, specifying the local IP and port to listen on.
* If the port is set to '0', the system assigns an available port automatically.
*
* @see socket() Creates a socket for binding.
* @see listen() Prepares the socket to listen for incoming connections after binding.
* @see accept() Accepts connections on a bound and listening socket.
*/
int bind(int s, const struct sockaddr *name, socklen_t namelen)
{
int socket = dfs_net_getsocket(s);
@@ -79,6 +125,30 @@ int bind(int s, const struct sockaddr *name, socklen_t namelen)
}
RTM_EXPORT(bind);
/**
* @brief Shuts down part of a full-duplex connection on a socket.
*
* This function disables further sends or receives on the specified socket, depending on the value
* of the 'how' parameter. It does not close the socket, which must still be closed separately using
* 'close()' or 'closesocket()'.
*
* @param s The file descriptor of the socket to shut down.
* @param how Specifies the type of shutdown to perform. The 'how' parameter can be one of the following:
* - 'SHUT_RD': Disables further reading on the socket. The socket will not receive data.
* - 'SHUT_WR': Disables further writing on the socket. The socket will not send data.
* - 'SHUT_RDWR': Disables both reading and writing on the socket. The socket will be fully shut down.
*
* @return Returns '0' on success. On failure, returns '-1' and sets errno to indicate the error.
*
* @note The 'shutdown()' function is used to gracefully close a socket in one or both directions
* (read/write). It is commonly used in scenarios like closing the write side of a TCP connection
* when a server has finished sending data but still expects to receive data.
*
* @see socket() Creates the socket used for communication.
* @see close()/closesocket() Closes the socket after the shutdown is complete.
* @see recv() Receives data on a socket.
* @see send() Sends data on a socket.
*/
int shutdown(int s, int how)
{
int error = 0;
@@ -113,6 +183,28 @@ int shutdown(int s, int how)
}
RTM_EXPORT(shutdown);
/**
* @brief Retrieves the address of the peer connected to a socket.
*
* This function obtains the address of the peer (remote end) connected to the socket 's'.
* It is typically used on connected sockets (e.g., TCP) to retrieve information about the peer.
*
* @param s The file descriptor of the connected socket.
* @param name A pointer to a 'sockaddr' structure that will be filled with the address of the peer.
* The structure type (e.g., 'sockaddr_in' for IPv4) depends on the address family of the socket.
* @param namelen A pointer to a variable that initially specifies the size of the 'name' structure.
* On return, it contains the actual size of the address returned.
*
* @return Returns '0' on success. On failure, returns '-1' and sets errno to indicate the error.
*
* @note The 'getpeername()' function is useful for retrieving information about the remote end of a connection,
* such as the IP address and port of a peer in a TCP connection. This function is only valid for sockets
* that are in a connected state.
*
* @see socket() Creates the socket used for the connection.
* @see connect() Connects the socket to a remote address.
* @see getsockname() Retrieves the local address of a socket.
*/
int getpeername(int s, struct sockaddr *name, socklen_t *namelen)
{
int socket = dfs_net_getsocket(s);
@@ -121,6 +213,29 @@ int getpeername(int s, struct sockaddr *name, socklen_t *namelen)
}
RTM_EXPORT(getpeername);
/**
* @brief Retrieves the local address of a socket.
*
* This function obtains the local address (IP address and port) associated with the socket 's'.
* It is typically used to determine the local address and port of a bound or connected socket.
*
* @param s The file descriptor of the socket.
* @param name A pointer to a 'sockaddr' structure that will be filled with the local address
* of the socket. The structure type (e.g., 'sockaddr_in' for IPv4) depends on the
* address family of the socket.
* @param namelen A pointer to a variable that initially specifies the size of the 'name' structure.
* Upon return, this variable contains the actual size of the address returned.
*
* @return Returns '0' on success. On failure, returns '-1' and sets errno to indicate the error.
*
* @note The 'getsockname()' function is useful for retrieving the local address information of a socket,
* which can be especially useful in cases where the socket was bound with an ephemeral port (port 0),
* allowing you to discover the actual port number assigned by the system.
*
* @see socket() Creates the socket for communication.
* @see bind() Binds the socket to a specific local address.
* @see getpeername() Retrieves the address of the peer connected to a socket.
*/
int getsockname(int s, struct sockaddr *name, socklen_t *namelen)
{
int socket = dfs_net_getsocket(s);
@@ -129,6 +244,34 @@ int getsockname(int s, struct sockaddr *name, socklen_t *namelen)
}
RTM_EXPORT(getsockname);
/**
* @brief Retrieves options for a socket.
*
* This function retrieves the current value for a specified option on a socket, identified
* by the file descriptor 's'. The option is specified by the 'level' and 'optname' parameters.
*
* @param s The file descriptor of the socket from which to retrieve the option.
* @param level The protocol level at which the option resides. Common levels include:
* - 'SOL_SOCKET': To retrieve socket-level options.
* - 'IPPROTO_IP': To retrieve IPv4 options.
* - 'IPPROTO_TCP': To retrieve TCP options.
* @param optname The name of the option to retrieve. Some common options include:
* - 'SO_REUSEADDR': Checks if address reuse is enabled.
* - 'SO_RCVBUF': Retrieves the receive buffer size.
* - 'TCP_NODELAY': Checks if Nagle's algorithm is disabled for TCP sockets.
* @param optval A pointer to a buffer where the value of the option will be stored.
* The buffer must be large enough to hold the option value.
* @param optlen A pointer to a variable that initially specifies the size of 'optval'.
* On return, it contains the actual size of the option value returned.
*
* @return Returns '0' on success. On failure, returns '-1' and sets errno to indicate the error.
*
* @note The 'getsockopt()' function is useful for inspecting socket configuration and current settings.
* It can provide information about options such as buffer sizes, timeouts, and protocol-specific features.
*
* @see socket() Creates the socket to retrieve options from.
* @see setsockopt() Sets options for the socket.
*/
int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
{
int socket = dfs_net_getsocket(s);
@@ -137,6 +280,35 @@ int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
}
RTM_EXPORT(getsockopt);
/**
* @brief Sets options on a socket.
*
* This function sets the specified option for the socket referenced by the file descriptor 's'.
* Socket options affect the behavior of the socket and are specified by the 'level' and 'optname' parameters.
*
* @param s The file descriptor of the socket on which to set the option.
* @param level The protocol level at which the option resides. Common levels include:
* - 'SOL_SOCKET': To configure socket-level options.
* - 'IPPROTO_IP': To configure IPv4 options.
* - 'IPPROTO_TCP': To configure TCP options.
* @param optname The name of the option to set. Some common options include:
* - 'SO_REUSEADDR': Allows reuse of local addresses.
* - 'SO_RCVBUF': Sets the receive buffer size.
* - 'TCP_NODELAY': Disables Nagle's algorithm for TCP sockets.
* @param optval A pointer to the buffer containing the value to set for the specified option.
* The type of data in this buffer depends on the option being set.
* @param optlen The size, in bytes, of the option value pointed to by 'optval'.
*
* @return Returns '0' on success. On failure, returns '-1' and sets errno to indicate the error.
*
* @note The 'setsockopt()' function is useful for configuring various socket behaviors, such as
* setting timeouts, buffer sizes, and enabling or disabling certain protocol features.
* The changes may affect socket performance and resource usage.
*
* @see socket() Creates the socket to configure.
* @see getsockopt() Retrieves options set on the socket.
* @see bind() Binds the socket to a local address.
*/
int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
{
int socket = dfs_net_getsocket(s);
@@ -145,6 +317,29 @@ int setsockopt(int s, int level, int optname, const void *optval, socklen_t optl
}
RTM_EXPORT(setsockopt);
/**
* @brief Initiates a connection on a socket.
*
* This function connects the socket specified by 's' to the server address specified by 'name'.
* The socket must have been created with 'socket()' and, for some types of sockets, may need
* to be bound to a local address with 'bind()' before calling 'connect()'.
*
* @param s The file descriptor of the socket to connect.
* @param name A pointer to a 'sockaddr' structure that specifies the address of the server to connect to.
* The specific structure (e.g., 'sockaddr_in' for IPv4) depends on the address family.
* @param namelen The length, in bytes, of the address structure pointed to by 'name'.
*
* @return Returns '0' on success. On failure, returns '-1' and sets errno to indicate the error.
*
* @note 'connect()' is typically used by client sockets to establish a connection with a server.
* For connection-oriented protocols (e.g., TCP), this initiates the connection handshake.
* For connectionless protocols (e.g., UDP), it defines a fixed peer address.
*
* @see socket() Creates the socket to be connected.
* @see bind() Binds the socket to a local address (optional for client sockets).
* @see accept() Used by server sockets to accept incoming connections.
* @see close()/closesocket() Closes the socket when done.
*/
int connect(int s, const struct sockaddr *name, socklen_t namelen)
{
int socket = dfs_net_getsocket(s);
@@ -152,6 +347,26 @@ int connect(int s, const struct sockaddr *name, socklen_t namelen)
}
RTM_EXPORT(connect);
/**
* @brief Marks a socket as a passive socket, ready to accept incoming connections.
*
* This function prepares a socket to accept incoming connection requests. The socket
* must first be created with 'socket()' and bound to a local address with 'bind()'.
*
* @param s The file descriptor of the socket to set to listening mode.
* @param backlog The maximum number of pending connections that can be queued for acceptance.
* If more incoming connections arrive than the backlog limit, they may be rejected
* or ignored until the server accepts some of the pending connections.
*
* @return Returns '0' on success. On failure, returns '-1' and sets errno to indicate the error.
*
* @note After calling 'listen()', the socket can be used with 'accept()' to handle connection requests.
* The backlog size affects how many connections can wait to be accepted before being rejected.
*
* @see socket() Creates the socket.
* @see bind() Binds the socket to a specific address.
* @see accept() Accepts a pending connection request on the listening socket.
*/
int listen(int s, int backlog)
{
int socket = dfs_net_getsocket(s);
@@ -160,6 +375,31 @@ int listen(int s, int backlog)
}
RTM_EXPORT(listen);
/**
* @brief Receives data from a connected socket.
*
* This function reads data from a connected socket and stores it in the specified buffer.
* It is typically used with connection-oriented protocols (e.g., TCP).
*
* @param s The file descriptor of the connected socket to receive data from.
* @param mem A pointer to the buffer where the received data will be stored.
* @param len The maximum number of bytes to read into the buffer.
* @param flags Specifies the behavior of the receive operation. Common flags include:
* - '0': Default operation.
* - 'MSG_DONTWAIT': Non-blocking operation.
* - 'MSG_PEEK': Peeks at the incoming data without removing it from the queue.
*
* @return Returns the number of bytes received on success. On failure, returns '-1' and sets errno to indicate the error.
* A return value of '0' indicates that the connection has been closed by the remote peer.
*
* @note The 'recv()' function may not receive all the requested bytes in a single call.
* Multiple calls to 'recv()' may be needed to read the complete data.
*
* @see socket() Creates the socket to be used for receiving data.
* @see connect() Connects the socket to a remote address (for connection-oriented protocols).
* @see recvfrom() Receives data from a specific address, typically used with connectionless sockets.
* @see send() Sends data on a connected socket.
*/
int recv(int s, void *mem, size_t len, int flags)
{
int socket = dfs_net_getsocket(s);
@@ -168,6 +408,36 @@ int recv(int s, void *mem, size_t len, int flags)
}
RTM_EXPORT(recv);
/**
* @brief Sends a message on a socket.
*
* The 'sendmsg()' function sends data on the socket 's' using the structured data in the 'msghdr'
* structure. This function is commonly used for sending complex messages with multiple buffers,
* control information, or for working with datagram sockets.
*
* @param s The file descriptor of the socket to send the message on.
* @param message A pointer to an 'msghdr' structure, which contains the data, address, and control information:
* - 'msg_name': Optional destination address (used for connectionless sockets).
* - 'msg_namelen': Size of the destination address.
* - 'msg_iov': An array of 'iovec' structures that point to the data buffers to be sent.
* - 'msg_iovlen': The number of elements in the 'msg_iov' array.
* - 'msg_control': Optional ancillary data, such as file descriptors for UNIX domain sockets.
* - 'msg_controllen': The size of the ancillary data buffer.
* - 'msg_flags': Flags related to the message.
* @param flags Specifies how the message should be sent. Common flags include:
* - 'MSG_DONTWAIT': Sends the message in non-blocking mode.
* - 'MSG_EOR': Indicates the end of a record (for record-oriented sockets).
*
* @return Returns the number of bytes sent on success. On failure, returns '-1' and sets errno to indicate the error.
*
* @note The 'sendmsg()' function is useful for sending messages with multiple buffers or ancillary data,
* allowing flexible communication options such as attaching file descriptors. This function can be
* used with both connection-oriented and connectionless sockets.
*
* @see recvmsg() Receives a message from a socket.
* @see send() Sends data on a socket.
* @see socket() Creates the socket to use with 'sendmsg()'.
*/
int sendmsg(int s, const struct msghdr *message, int flags)
{
int socket = dfs_net_getsocket(s);
@@ -176,6 +446,38 @@ int sendmsg(int s, const struct msghdr *message, int flags)
}
RTM_EXPORT(sendmsg);
/**
* @brief Receives a message from a socket.
*
* The 'recvmsg()' function receives data from the socket 's' into the buffers described by
* the 'msghdr' structure. This function allows for complex data structures, including multiple
* data buffers and optional control information.
*
* @param s The file descriptor of the socket to receive data from.
* @param message A pointer to an 'msghdr' structure, which will be filled with the received data and
* information. The structure contains:
* - 'msg_name': A buffer for the source address (used for connectionless sockets).
* - 'msg_namelen': Specifies the size of the 'msg_name' buffer.
* - 'msg_iov': An array of 'iovec' structures that point to the buffers to store received data.
* - 'msg_iovlen': The number of elements in the 'msg_iov' array.
* - 'msg_control': A buffer for ancillary data, such as received file descriptors.
* - 'msg_controllen': The size of the ancillary data buffer.
* - 'msg_flags': Flags set by the 'recvmsg()' call to indicate the message status.
* @param flags Specifies how the message should be received. Common flags include:
* - 'MSG_DONTWAIT': Receives the message in non-blocking mode.
* - 'MSG_PEEK': Peeks at the incoming message without removing it from the queue.
* - 'MSG_WAITALL': Waits for the full amount of data to be received.
*
* @return Returns the number of bytes received on success. On failure, returns '-1' and sets errno to indicate the error.
*
* @note The 'recvmsg()' function is useful for receiving messages with multiple buffers or ancillary data.
* It can be used with both connection-oriented and connectionless sockets, making it versatile for
* different communication needs.
*
* @see sendmsg() Sends a message on a socket.
* @see recv() Receives data on a socket.
* @see socket() Creates the socket used with 'recvmsg()'.
*/
int recvmsg(int s, struct msghdr *message, int flags)
{
int socket = dfs_net_getsocket(s);
@@ -184,6 +486,36 @@ int recvmsg(int s, struct msghdr *message, int flags)
}
RTM_EXPORT(recvmsg);
/**
* @brief Receives data from a specific address using an unconnected socket.
*
* This function reads data from a socket and stores it in the specified buffer. It is commonly used
* with connectionless protocols (e.g., UDP) to receive data from a specific source address.
*
* @param s The file descriptor of the socket to receive data from.
* @param mem A pointer to the buffer where the received data will be stored.
* @param len The maximum number of bytes to read into the buffer.
* @param flags Specifies the behavior of the receive operation. Common flags include:
* - '0': Default operation.
* - 'MSG_DONTWAIT': Non-blocking operation.
* - 'MSG_PEEK': Peeks at the incoming data without removing it from the queue.
* @param from A pointer to a 'sockaddr' structure that will be filled with the address of the
* sending entity. This is the source address from which the data was received.
* @param fromlen A pointer to a variable that initially contains the size of the 'from' structure.
* Upon return, this variable will hold the actual size of the address returned.
*
* @return Returns the number of bytes received on success. On failure, returns '-1' and sets errno to indicate the error.
* A return value of '0' indicates that the connection has been closed by the remote peer.
*
* @note The 'recvfrom()' function is useful for receiving data from an arbitrary source address,
* which makes it especially suited for connectionless protocols where the peer's address may vary.
* The 'from' parameter is filled with the sender's address, which can be useful for identifying
* the origin of the data.
*
* @see socket() Creates the socket used for receiving data.
* @see sendto() Sends data to a specific address, typically used with connectionless sockets.
* @see recv() Receives data on a connected socket.
*/
int recvfrom(int s, void *mem, size_t len, int flags,
struct sockaddr *from, socklen_t *fromlen)
{
@@ -193,6 +525,32 @@ int recvfrom(int s, void *mem, size_t len, int flags,
}
RTM_EXPORT(recvfrom);
/**
* @brief Sends data on a connected socket.
*
* This function sends data to a connected socket, specified by the file descriptor 's'.
* It is typically used with connection-oriented protocols (e.g., TCP).
*
* @param s The file descriptor of the socket to send data on.
* The socket must be connected to a remote peer.
* @param dataptr A pointer to the buffer containing the data to send.
* @param size The size, in bytes, of the data to be sent from the buffer.
* @param flags Specifies the behavior of the send operation. Common flags include:
* - '0': Default operation.
* - 'MSG_DONTWAIT': Non-blocking operation.
* - 'MSG_NOSIGNAL': Prevents the sending of 'SIGPIPE' on errors.
*
* @return Returns the number of bytes sent on success. On failure, returns '-1' and sets errno to indicate the error.
* If the connection is closed by the remote peer, the return value may be '0'.
*
* @note The 'send()' function does not guarantee that all data will be sent in a single call.
* If fewer bytes are sent than requested, the remaining data should be sent in subsequent calls.
*
* @see socket() Creates the socket to be used for sending data.
* @see connect() Connects the socket to a remote address (for connection-oriented protocols).
* @see sendto() Sends data to a specific address, typically used with connectionless sockets.
* @see recv() Receives data from a connected socket.
*/
int send(int s, const void *dataptr, size_t size, int flags)
{
int socket = dfs_net_getsocket(s);
@@ -201,6 +559,34 @@ int send(int s, const void *dataptr, size_t size, int flags)
}
RTM_EXPORT(send);
/**
* @brief Sends data to a specific address using an unconnected socket.
*
* This function is typically used with connectionless protocols (e.g., UDP) to send data
* to a specific destination address, as specified by 'to'.
*
* @param s The file descriptor of the socket to send data on.
* @param dataptr A pointer to the buffer containing the data to be sent.
* @param size The size, in bytes, of the data to be sent from the buffer.
* @param flags Specifies the behavior of the send operation. Common flags include:
* - '0': Default operation.
* - 'MSG_DONTWAIT': Non-blocking operation.
* - 'MSG_NOSIGNAL': Prevents the sending of 'SIGPIPE' on errors.
* @param to A pointer to a 'sockaddr' structure that specifies the destination address.
* The structure type (e.g., 'sockaddr_in' for IPv4) depends on the address family.
* @param tolen The length, in bytes, of the address structure pointed to by 'to'.
*
* @return Returns the number of bytes sent on success. On failure, returns '-1' and sets errno to indicate the error.
*
* @note Unlike 'send()', 'sendto()' can specify a target address for each message, allowing it to be used
* for both connected and unconnected sockets. In connectionless protocols, 'sendto()' is commonly
* used without prior calls to 'connect()'.
*
* @see socket() Creates the socket used for sending data.
* @see recvfrom() Receives data from a specific address, typically used with connectionless sockets.
* @see connect() Optional for connection-oriented protocols.
* @see send() Sends data on a connected socket.
*/
int sendto(int s, const void *dataptr, size_t size, int flags,
const struct sockaddr *to, socklen_t tolen)
{
@@ -210,6 +596,38 @@ int sendto(int s, const void *dataptr, size_t size, int flags,
}
RTM_EXPORT(sendto);
/**
* @brief Creates a network socket.
*
* This function creates a socket and returns a file descriptor that can be used for network communication.
*
* @param domain The communication protocol family (address family) that defines the socket's protocol.
* Common values include:
* - 'AF_INET': IPv4
* - 'AF_INET6': IPv6
* - 'AF_UNIX': Local communication (inter-process communication on the same machine)
* - 'AF_AT': AT socket
* - 'AF_WIZ': WIZnet
* @param type The type of socket, which determines the characteristics of data transmission.
* Common values include:
* - 'SOCK_STREAM': Connection-oriented byte stream communication (e.g., TCP)
* - 'SOCK_DGRAM': Connectionless datagram communication (e.g., UDP)
* - 'SOCK_RAW': Provides raw network protocol access
* @param protocol Specifies the protocol to be used with the socket. It is usually set to '0',
* which allows the system to choose the default protocol:
* - For 'SOCK_STREAM', the default is TCP.
* - For 'SOCK_DGRAM', the default is UDP.
*
* @return On success, returns a file descriptor (a non-negative integer) representing the socket.
* On failure, returns '-1' and sets errno to indicate the error.
*
* @note The created socket can be used for binding, listening, receiving, and sending data.
*
* @see bind() Used to bind the socket to a local address.
* @see listen() Used to set the socket to listen for incoming connections.
* @see accept() Used to accept incoming connection requests.
* @see connect() Used to connect to a remote host.
*/
int socket(int domain, int type, int protocol)
{
/* create a BSD socket */
@@ -262,6 +680,25 @@ int socket(int domain, int type, int protocol)
}
RTM_EXPORT(socket);
/**
* @brief Closes a socket.
*
* This function closes the socket specified by the file descriptor 's'. Once closed, the socket
* can no longer be used for communication. Any pending data that has not been transmitted may be lost.
*
* @param s The file descriptor of the socket to close.
*
* @return Returns '0' on success. On failure, returns '-1' and sets errno to indicate the error.
*
* @note After calling 'closesocket()', the socket descriptor becomes invalid. The socket cannot
* be used for further communication or operations. It is important to close sockets when they are no longer needed
* to release system resources.
*
* @see socket() Creates a socket.
* @see shutdown() Shuts down the socket for reading and/or writing, without closing it.
* @see recv() Receives data from a socket.
* @see send() Sends data on a socket.
*/
int closesocket(int s)
{
int error = 0;
@@ -305,7 +742,32 @@ int closesocket(int s)
}
RTM_EXPORT(closesocket);
/**
* @brief Creates a pair of connected sockets.
*
* The 'socketpair()' function creates two connected sockets, which can be used for bidirectional
* communication between processes or threads on the same machine. This is commonly used for inter-process
* communication (IPC) in UNIX-like operating systems.
*
* @param domain The communication domain (or protocol family). Typically, 'AF_UNIX' (or 'AF_LOCAL')
* is used to create sockets for local communication.
* @param type The type of socket to be created. Common values include:
* - 'SOCK_STREAM': Provides reliable, connection-oriented communication.
* - 'SOCK_DGRAM': Provides connectionless, unreliable communication.
* @param protocol The protocol to be used with the sockets. Normally set to '0' to use the default protocol
* for the specified 'domain' and 'type'.
* @param fds An array of two integers where the file descriptors for the two connected sockets will be stored.
* After a successful call, 'fds[0]' and 'fds[1]' represent the two ends of the socket pair.
*
* @return Returns '0' on success. On failure, returns '-1' and sets 'errno' to indicate the error.
*
* @note The 'socketpair()' function is commonly used to create a communication channel between two processes
* (parent and child after 'fork()') or two threads. Data written to one socket is available for reading
* from the other. It is primarily supported on UNIX-like systems and may not be available on Windows.
*
* @see socket() Creates a single socket for network communication.
* @see pipe() Creates an unidirectional communication channel between processes.
*/
int socketpair(int domain, int type, int protocol, int *fds)
{
rt_err_t ret = 0;
@@ -342,6 +804,32 @@ int socketpair(int domain, int type, int protocol, int *fds)
}
RTM_EXPORT(socketpair);
/**
* @brief Controls socket I/O modes.
*
* The 'ioctlsocket()' function manipulates the I/O mode of the socket specified by the file descriptor 's'.
* It is primarily used to enable or disable non-blocking mode on a socket or to perform other socket-specific
* operations.
*
* @param s The file descriptor of the socket to control.
* @param cmd The command that specifies the operation to perform. Some common commands include:
* - 'FIONBIO': Enables or disables non-blocking mode. Setting 'arg' to a non-zero value
* enables non-blocking mode; setting it to zero disables it.
* - 'FIONREAD': Retrieves the number of bytes available to read, storing the result in 'arg'.
* @param arg A pointer to an argument for the command. The type and meaning of this argument depend on the
* specified command ('cmd'). For example, in non-blocking mode ('FIONBIO'), it points to a 'long'
* that is either non-zero (to enable) or zero (to disable) non-blocking mode.
*
* @return Returns '0' on success. On failure, returns '-1' and sets errno (or 'WSAGetLastError()' on Windows) to indicate the error.
*
* @note This function is specific to Windows environments and is a part of the Winsock API. It performs
* similar functionality to the 'fcntl()' function on UNIX-like systems.
* The 'ioctlsocket()' function allows for various socket manipulations that affect how the socket
* operates in certain conditions, such as setting it to non-blocking mode.
*
* @see socket() Creates a socket to use with 'ioctlsocket()'.
* @see fcntl() Performs similar operations on UNIX-like systems.
*/
int ioctlsocket(int s, long cmd, void *arg)
{
int socket = dfs_net_getsocket(s);

View File

@@ -444,11 +444,6 @@ static int socket_init(int family, int type, int protocol, struct sal_socket **r
struct netdev *netdev = RT_NULL;
rt_bool_t flag = RT_FALSE;
if (family == AF_UNIX)
{
netdv_def = netdev_lo;
}
if (family < 0 || family > AF_MAX)
{
return -1;
@@ -684,7 +679,8 @@ int sal_bind(int socket, const struct sockaddr *name, socklen_t namelen)
addr_un = (struct sockaddr_un *)name;
if ((addr_un->sa_family != AF_UNIX) && (addr_un->sa_family != AF_NETLINK))
#define IS_INET_ADDR_FAMILY(_af) ((_af) == AF_INET) || ((_af) == AF_INET6)
if (IS_INET_ADDR_FAMILY(name->sa_family))
{
/* bind network interface by ip address */
sal_sockaddr_to_ipaddr(name, &input_ipaddr);
@@ -910,11 +906,11 @@ int sal_sendmsg(int socket, const struct msghdr *message, int flags)
SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, sendmsg);
#ifdef SAL_USING_TLS
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, sendmsg))
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, send))
{
int ret;
if ((ret = proto_tls->ops->sendmsg(sock->user_data_tls, message, flags)) < 0)
if ((ret = proto_tls->ops->send(sock->user_data_tls, message, flags)) < 0)
{
return -1;
}
@@ -943,11 +939,11 @@ int sal_recvmsg(int socket, struct msghdr *message, int flags)
SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, recvmsg);
#ifdef SAL_USING_TLS
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, recvmsg))
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, recv))
{
int ret;
if ((ret = proto_tls->ops->recvmsg(sock->user_data_tls, message, flags)) < 0)
if ((ret = proto_tls->ops->recv(sock->user_data_tls, message, flags)) < 0)
{
return -1;
}
@@ -1171,12 +1167,9 @@ int sal_ioctlsocket(int socket, long cmd, void *arg)
/* get the socket object by socket descriptor */
SAL_SOCKET_OBJ_GET(sock, socket);
/* check the network interface socket opreation */
SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, ioctlsocket);
struct sal_ifreq *ifr = (struct sal_ifreq *)arg;
if((sock->domain == AF_INET)&&(sock->netdev)&&(ifr != RT_NULL))
if (ifr != RT_NULL)
{
switch (cmd)
{
@@ -1474,10 +1467,24 @@ int sal_ioctlsocket(int socket, long cmd, void *arg)
ifconf_tmp->ifc_ifcu.ifcu_buf = ifconf_tmp->ifc_ifcu.ifcu_buf - sizeof(struct sal_ifreq) * count_size;
return 0;
}
case SIOCGIFINDEX:
{
netdev = netdev_get_by_name(ifr->ifr_ifrn.ifrn_name);
if (netdev)
{
ifr->ifr_ifru.ifru_ivalue = netdev->ifindex;
return 0;
}
return -ENODEV;
}
default:
break;
}
}
/* check the network interface socket opreation */
SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, ioctlsocket);
return pf->skt_ops->ioctlsocket((int)(size_t)sock->user_data, cmd, arg);
}