提交 3d6e0ea3 编写于 作者: Lawlieta's avatar Lawlieta

[net][netdev]add network interface device components, SAL component adaptation netdev change

上级 c8870b42
...@@ -291,97 +291,6 @@ int cmd_echo(int argc, char** argv) ...@@ -291,97 +291,6 @@ int cmd_echo(int argc, char** argv)
FINSH_FUNCTION_EXPORT_ALIAS(cmd_echo, __cmd_echo, echo string to file); FINSH_FUNCTION_EXPORT_ALIAS(cmd_echo, __cmd_echo, echo string to file);
#endif #endif
#ifdef RT_USING_LWIP
int cmd_ifconfig(int argc, char **argv)
{
extern void list_if(void);
extern void set_if(char *netif_name, char *ip_addr, char *gw_addr, char *nm_addr);
if (argc == 1)
{
list_if();
}
else if (argc == 5)
{
rt_kprintf("config : %s\n", argv[1]);
rt_kprintf("IP addr: %s\n", argv[2]);
rt_kprintf("Gateway: %s\n", argv[3]);
rt_kprintf("netmask: %s\n", argv[4]);
set_if(argv[1], argv[2], argv[3], argv[4]);
}
else
{
rt_kprintf("bad parameter! e.g: ifconfig e0 192.168.1.30 192.168.1.1 255.255.255.0\n");
}
return 0;
}
FINSH_FUNCTION_EXPORT_ALIAS(cmd_ifconfig, __cmd_ifconfig, list the information of network interfaces);
#ifdef RT_LWIP_DNS
#include <lwip/api.h>
#include <lwip/dns.h>
#include <lwip/ip_addr.h>
#include <lwip/init.h>
int cmd_dns(int argc, char **argv)
{
extern void set_dns(char* dns_server);
if (argc == 1)
{
int index;
#if (LWIP_VERSION) < 0x02000000U
ip_addr_t ip_addr;
for(index=0; index<DNS_MAX_SERVERS; index++)
{
ip_addr = dns_getserver(index);
rt_kprintf("dns server #%d: %s\n", index, ipaddr_ntoa(&ip_addr));
}
#else
const ip_addr_t *ip_addr;
for(index=0; index<DNS_MAX_SERVERS; index++)
{
ip_addr = dns_getserver(index);
rt_kprintf("dns server #%d: %s\n", index, ipaddr_ntoa(ip_addr));
}
#endif
}
else if (argc == 2)
{
rt_kprintf("dns : %s\n", argv[1]);
set_dns(argv[1]);
}
else
{
rt_kprintf("bad parameter! e.g: dns 114.114.114.114\n");
}
return 0;
}
FINSH_FUNCTION_EXPORT_ALIAS(cmd_dns, __cmd_dns, list the information of dns);
#endif
#if defined (RT_LWIP_TCP) || defined (RT_LWIP_UDP)
int cmd_netstat(int argc, char **argv)
{
extern void list_tcps(void);
extern void list_udps(void);
#ifdef RT_LWIP_TCP
list_tcps();
#endif
#ifdef RT_LWIP_UDP
list_udps();
#endif
return 0;
}
FINSH_FUNCTION_EXPORT_ALIAS(cmd_netstat, __cmd_netstat, list the information of TCP / IP);
#endif
#endif /* RT_USING_LWIP */
int cmd_ps(int argc, char **argv) int cmd_ps(int argc, char **argv)
{ {
extern long list_thread(void); extern long list_thread(void);
......
...@@ -4,6 +4,8 @@ menu "Socket abstraction layer" ...@@ -4,6 +4,8 @@ menu "Socket abstraction layer"
config RT_USING_SAL config RT_USING_SAL
bool "Enable socket abstraction layer" bool "Enable socket abstraction layer"
select RT_USING_NETDEV
select RT_USING_SYSTEM_WORKQUEUE
default n default n
if RT_USING_SAL if RT_USING_SAL
...@@ -46,10 +48,30 @@ config RT_USING_SAL ...@@ -46,10 +48,30 @@ config RT_USING_SAL
default 16 default 16
endif endif
endif
endmenu
menu "Network interface device"
config RT_USING_NETDEV
bool "Enable network interface device"
default n
if RT_USING_NETDEV
config NETDEV_USING_IFCONFIG
bool "Enable ifconfig features"
default y
config NETDEV_USING_PING
bool "Enable ping features"
default y
config SAL_PROTO_FAMILIES_NUM config NETDEV_USING_NETSTAT
int "the maximum number of protocol families" bool "Enable netstat features"
default 4 default y
endif endif
...@@ -79,9 +101,11 @@ config RT_USING_LWIP ...@@ -79,9 +101,11 @@ config RT_USING_LWIP
endchoice endchoice
if (RT_USING_LWIP210 || RT_USING_LWIP202) if (RT_USING_LWIP210 || RT_USING_LWIP202)
config RT_USING_LWIP_IPV6 if (!RT_USING_NETDEV || (RT_USING_NETDEV && NETDEV_IPV6))
bool "IPV6 protocol" config RT_USING_LWIP_IPV6
default n bool "IPV6 protocol"
default n
endif
endif endif
config RT_LWIP_IGMP config RT_LWIP_IGMP
...@@ -229,7 +253,11 @@ config RT_USING_LWIP ...@@ -229,7 +253,11 @@ config RT_USING_LWIP
default n default n
config LWIP_NETIF_STATUS_CALLBACK config LWIP_NETIF_STATUS_CALLBACK
int "netif status callback" int "Enable netif status callback"
default 1
config LWIP_NETIF_LINK_CALLBACK
int "Enable netif link status callback"
default 1 default 1
config SO_REUSE config SO_REUSE
...@@ -264,6 +292,13 @@ config RT_USING_LWIP ...@@ -264,6 +292,13 @@ config RT_USING_LWIP
config RT_LWIP_USING_HW_CHECKSUM config RT_LWIP_USING_HW_CHECKSUM
bool "Enable hardware checksum" bool "Enable hardware checksum"
default n default n
config RT_LWIP_USING_PING
bool "Enable ping features"
default y
select NETDEV_USING_PING
select RT_LWIP_ICMP
select RT_LWIP_RAW
menuconfig RT_LWIP_DEBUG menuconfig RT_LWIP_DEBUG
bool "Enable lwIP Debugging Options" bool "Enable lwIP Debugging Options"
......
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
src = Glob('src/*.c')
CPPPATH = [cwd + '/include']
group = DefineGroup('netdev', src, depend = ['RT_USING_NETDEV'], CPPPATH = CPPPATH)
Return('group')
...@@ -8,9 +8,9 @@ ...@@ -8,9 +8,9 @@
* 2015-02-17 Bernard First version * 2015-02-17 Bernard First version
*/ */
#ifndef INET_H__ #ifndef __INET_H__
#define INET_H__ #define __INET_H__
#include <sal_ipaddr.h> #include <netdev_ipaddr.h>
#endif #endif
/*
* Copyright (c) 2006-2019, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-03-18 ChenYong First version
*/
#ifndef __NETDEV_H__
#define __NETDEV_H__
#include <rtthread.h>
#ifdef __cplusplus
extern "C" {
#endif
/* the maximum of all used hardware address lengths */
#ifndef NETDEV_HWADDR_MAX_LEN
#define NETDEV_HWADDR_MAX_LEN 8U
#endif
/* the maximum of dns server number supported */
#ifndef NETDEV_DNS_SERVERS_NUM
#define NETDEV_DNS_SERVERS_NUM 2U
#endif
/* whether the network interface device is 'up' (set by the network interface driver or application) */
#define NETDEV_FLAG_UP 0x01U
/* if set, the network interface device has broadcast capability, only supported in the 'lwIP' stack */
#define NETDEV_FLAG_BROADCAST 0x02U
/* if set, the network interface device has an active link (set by the network interface driver) */
#define NETDEV_FLAG_LINK_UP 0x04U
/* if set, the network interface device is an ethernet device using ARP, only supported in the 'lwIP' stack */
#define NETDEV_FLAG_ETHARP 0x08U
/* if set, the network interface device is an ethernet device, only supported in the 'lwIP' stack */
#define NETDEV_FLAG_ETHERNET 0x10U
/* if set, the network interface device has IGMP capability, only supported in the 'lwIP' stack */
#define NETDEV_FLAG_IGMP 0x20U
/* if set, the network interface device has MLD6 capability, only supported in the 'lwIP' stack */
#define NETDEV_FLAG_MLD6 0x40U
/* if set, the network interface device connected to internet successfully (set by the network interface driver) */
#define NETDEV_FLAG_INTERNET_UP 0x80U
/* if set, the network interface device has DHCP capability (set by the network interface device driver or application) */
#define NETDEV_FLAG_DHCP 0x100U
enum netdev_cb_type
{
NETDEV_CB_ADDR_IP, /* IP address */
NETDEV_CB_ADDR_NETMASK, /* subnet mask */
NETDEV_CB_ADDR_GATEWAY, /* netmask */
NETDEV_CB_ADDR_DNS_SERVER, /* dns server */
NETDEV_CB_STATUS_UP, /* changed to 'up' */
NETDEV_CB_STATUS_DOWN, /* changed to 'down' */
NETDEV_CB_STATUS_LINK_UP, /* changed to 'link up' */
NETDEV_CB_STATUS_LINK_DOWN, /* changed to 'link down' */
NETDEV_CB_STATUS_INTERNET_UP, /* changed to 'internet up' */
NETDEV_CB_STATUS_INTERNET_DOWN, /* changed to 'internet down' */
NETDEV_CB_STATUS_DHCP_ENABLE, /* enable DHCP capability */
NETDEV_CB_STATUS_DHCP_DISABLE, /* disable DHCP capability */
};
struct netdev;
/* function prototype for network interface device status or address change callback functions */
typedef void (*netdev_callback_fn )(struct netdev *netdev, enum netdev_cb_type type);
struct netdev_ops;
/* network interface device object */
struct netdev
{
rt_slist_t list;
char name[RT_NAME_MAX]; /* network interface device name */
ip_addr_t ip_addr; /* IP address */
ip_addr_t netmask; /* subnet mask */
ip_addr_t gw; /* gateway */
ip_addr_t dns_servers[NETDEV_DNS_SERVERS_NUM]; /* DNS server */
uint8_t hwaddr_len; /* hardware address length */
uint8_t hwaddr[NETDEV_HWADDR_MAX_LEN]; /* hardware address */
uint16_t flags; /* network interface device status flag */
uint16_t mtu; /* maximum transfer unit (in bytes) */
const struct netdev_ops *ops; /* network interface device operations */
netdev_callback_fn status_callback; /* network interface device flags change callback */
netdev_callback_fn addr_callback; /* network interface device address information change callback */
#ifdef RT_USING_SAL
void *sal_user_data; /* user-specific data for SAL */
#endif /* RT_USING_SAL */
void *user_data; /* user-specific data */
};
/* The list of network interface device */
extern struct netdev *netdev_list;
/* The default network interface device */
extern struct netdev *netdev_default;
/* The network interface device ping response object */
struct netdev_ping_resp
{
ip_addr_t ip_addr; /* response IP address */
uint16_t data_len; /* response data length */
uint16_t ttl; /* time to live */
uint32_t ticks; /* response time, unit tick */
void *user_data; /* user-specific data */
};
/* The network interface device operations */
struct netdev_ops
{
/* set network interface device hardware status operations */
int (*set_up)(struct netdev *netdev);
int (*set_down)(struct netdev *netdev);
/* set network interface device address information operations */
int (*set_addr_info)(struct netdev *netdev, ip_addr_t *ip_addr, ip_addr_t *netmask, ip_addr_t *gw);
int (*set_dns_server)(struct netdev *netdev, ip_addr_t *dns_server);
int (*set_dhcp)(struct netdev *netdev, rt_bool_t is_enabled);
/* set network interface device common network interface device operations */
int (*ping)(struct netdev *netdev, const char *host, size_t data_len, uint32_t timeout, struct netdev_ping_resp *ping_resp);
void (*netstat)(struct netdev *netdev);
};
/* The network interface device registered and unregistered*/
int netdev_register(struct netdev *netdev, const char *name, void *user_data);
int netdev_unregister(struct netdev *netdev);
/* Get network interface device object */
struct netdev *netdev_get_first_link_up(void);
struct netdev *netdev_get_by_ipaddr(ip_addr_t *ip_addr);
struct netdev *netdev_get_by_name(const char *name);
#ifdef RT_USING_SAL
struct netdev *netdev_get_by_family(int family);
#endif /* RT_USING_SAL */
/* Set default network interface device in list */
void netdev_set_default(struct netdev *netdev);
/* Set network interface device status */
int netdev_set_up(struct netdev *netdev);
int netdev_set_down(struct netdev *netdev);
int netdev_dhcp_enabled(struct netdev *netdev, rt_bool_t is_enabled);
/* Get network interface device status */
#define netdev_is_up(netdev) (((netdev)->flags & NETDEV_FLAG_UP) ? (uint8_t)1 : (uint8_t)0)
#define netdev_is_link_up(netdev) (((netdev)->flags & NETDEV_FLAG_LINK_UP) ? (uint8_t)1 : (uint8_t)0)
#define netdev_is_internet_up(netdev) (((netdev)->flags & NETDEV_FLAG_INTERNET_UP) ? (uint8_t)1 : (uint8_t)0)
#define netdev_is_dhcp_enabled(netdev) (((netdev)->flags & NETDEV_FLAG_DHCP) ? (uint8_t)1 : (uint8_t)0)
/* Set network interface device address */
int netdev_set_ipaddr(struct netdev *netdev, const ip_addr_t *ipaddr);
int netdev_set_netmask(struct netdev *netdev, const ip_addr_t *netmask);
int netdev_set_gw(struct netdev *netdev, const ip_addr_t *gw);
int netdev_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_t *dns_server);
/* Set network interface device callback, it can be called when the status or address changed */
void netdev_set_status_callback(struct netdev *netdev, netdev_callback_fn status_callback);
/* Set network interface device status and address, this function can only be called in the network interface device driver */
void netdev_low_level_set_ipaddr(struct netdev *netdev, const ip_addr_t *ipaddr);
void netdev_low_level_set_netmask(struct netdev *netdev, const ip_addr_t *netmask);
void netdev_low_level_set_gw(struct netdev *netdev, const ip_addr_t *gw);
void netdev_low_level_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_t *dns_server);
void netdev_low_level_set_status(struct netdev *netdev, rt_bool_t is_up);
void netdev_low_level_set_link_status(struct netdev *netdev, rt_bool_t is_up);
void netdev_low_level_set_dhcp_status(struct netdev *netdev, rt_bool_t is_enable);
#ifdef __cplusplus
}
#endif
#endif /* __NETDEV_H__ */
...@@ -7,21 +7,33 @@ ...@@ -7,21 +7,33 @@
* Date Author Notes * Date Author Notes
* 2018-05-18 ChenYong First version * 2018-05-18 ChenYong First version
*/ */
#ifndef SAL_IPADDR_H__
#define SAL_IPADDR_H__
#include "sal_type.h" #ifndef __NETDEV_IPADDR_H__
#define __NETDEV_IPADDR_H__
#include <stdint.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* Only supports the IPV4 protocol */
#ifndef NETDEV_IPV4
#define NETDEV_IPV4 1
#endif
#ifndef NETDEV_IPV6
#define NETDEV_IPV6 0
#endif
#ifdef NETDEV_IPV4
/** IPv4 only: set the IP address given as an u32_t */ /** IPv4 only: set the IP address given as an u32_t */
#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) #define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32))
/** IPv4 only: get the IP address as an u32_t */ /** IPv4 only: get the IP address as an u32_t */
#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr) #define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr)
#define IP4ADDR_STRLEN_MAX 16 #define IP4ADDR_STRLEN_MAX 16
#endif /* NETIF_IPV4 */
/* These macros should be calculated by the preprocessor and are used /* These macros should be calculated by the preprocessor and are used
with compile-time constants only (so that there is no little-endian with compile-time constants only (so that there is no little-endian
...@@ -34,33 +46,53 @@ extern "C" { ...@@ -34,33 +46,53 @@ extern "C" {
(((x) & 0xff000000UL) >> 24)) (((x) & 0xff000000UL) >> 24))
#define PP_NTOHL(x) PP_HTONL(x) #define PP_NTOHL(x) PP_HTONL(x)
#define htons(x) (u16_t)PP_HTONS(x) #define htons(x) (uint16_t)PP_HTONS(x)
#define ntohs(x) (u16_t)PP_NTOHS(x) #define ntohs(x) (uint16_t)PP_NTOHS(x)
#define htonl(x) (u32_t)PP_HTONL(x) #define htonl(x) (uint32_t)PP_HTONL(x)
#define ntohl(x) (u32_t)PP_NTOHL(x) #define ntohl(x) (uint32_t)PP_NTOHL(x)
/* If your port already typedef's in_addr_t, define IN_ADDR_T_DEFINED /* If your port already typedef's in_addr_t, define IN_ADDR_T_DEFINED
to prevent this code from redefining it. */ to prevent this code from redefining it. */
#if !defined(in_addr_t) && !defined(IN_ADDR_T_DEFINED) #if !defined(in_addr_t) && !defined(IN_ADDR_T_DEFINED)
typedef u32_t in_addr_t; typedef uint32_t in_addr_t;
#endif #endif
#if NETDEV_IPV4
struct in_addr struct in_addr
{ {
in_addr_t s_addr; in_addr_t s_addr;
}; };
typedef struct ip4_addr
{
uint32_t addr;
} ip4_addr_t;
typedef ip4_addr_t ip_addr_t;
#endif /* NETIF_IPV4 */
#if NETDEV_IPV6
struct in6_addr struct in6_addr
{ {
union union
{ {
u32_t u32_addr[4]; uint32_t u32_addr[4];
u8_t u8_addr[16]; uint8_t u8_addr[16];
} un; } un;
#define s6_addr un.u8_addr #define s6_addr un.u8_addr
}; };
enum sal_ip_addr_type typedef struct ip6_addr
{
uint32_t addr[4];
} ip6_addr_t;
typedef ip6_addr ip_addr_t
#endif /* NETIF_IPV6 */
#if NETDEV_IPV4 && NETDEV_IPV6
/* IP address types for use in ip_addr_t.type member */
enum netdev_ip_addr_type
{ {
/** IPv4 */ /** IPv4 */
IPADDR_TYPE_V4 = 0U, IPADDR_TYPE_V4 = 0U,
...@@ -70,16 +102,7 @@ enum sal_ip_addr_type ...@@ -70,16 +102,7 @@ enum sal_ip_addr_type
IPADDR_TYPE_ANY = 46U IPADDR_TYPE_ANY = 46U
}; };
typedef struct ip4_addr /* A union struct for both IP version's addresses */
{
u32_t addr;
} ip4_addr_t;
typedef struct ip6_addr
{
u32_t addr[4];
} ip6_addr_t;
typedef struct _ip_addr typedef struct _ip_addr
{ {
union union
...@@ -87,18 +110,19 @@ typedef struct _ip_addr ...@@ -87,18 +110,19 @@ typedef struct _ip_addr
ip6_addr_t ip6; ip6_addr_t ip6;
ip4_addr_t ip4; ip4_addr_t ip4;
} u_addr; } u_addr;
/** @ref sal_ip_addr_type */ /** @ref netdev_ip_addr_type */
u8_t type; uint8_t type;
} ip_addr_t; } ip_addr_t;
#endif /* NETIF_IPV4 && NETIF_IPV6 */
/** 255.255.255.255 */ /** 255.255.255.255 */
#define IPADDR_NONE ((u32_t)0xffffffffUL) #define IPADDR_NONE ((uint32_t)0xffffffffUL)
/** 127.0.0.1 */ /** 127.0.0.1 */
#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL) #define IPADDR_LOOPBACK ((uint32_t)0x7f000001UL)
/** 0.0.0.0 */ /** 0.0.0.0 */
#define IPADDR_ANY ((u32_t)0x00000000UL) #define IPADDR_ANY ((uint32_t)0x00000000UL)
/** 255.255.255.255 */ /** 255.255.255.255 */
#define IPADDR_BROADCAST ((u32_t)0xffffffffUL) #define IPADDR_BROADCAST ((uint32_t)0xffffffffUL)
/** 255.255.255.255 */ /** 255.255.255.255 */
#define INADDR_NONE IPADDR_NONE #define INADDR_NONE IPADDR_NONE
...@@ -111,18 +135,35 @@ typedef struct _ip_addr ...@@ -111,18 +135,35 @@ typedef struct _ip_addr
#define IPADDR_BROADCAST_STRING "255.255.255.255" #define IPADDR_BROADCAST_STRING "255.255.255.255"
in_addr_t sal_ipaddr_addr(const char *cp); #ifdef NETDEV_IPV4
int sal_ip4addr_aton(const char *cp, ip4_addr_t *addr);
char *sal_ip4addr_ntoa(const ip4_addr_t *addr); /** Copy IP address - faster than ip4_addr_set: no NULL check */
char *sal_ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen); #define ip4_addr_copy(dest, src) ((dest).addr = (src).addr)
#define ip4_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr)
/** Set complete address to zero */
#define ip4_addr_set_zero(ipaddr) ((ipaddr)->addr = 0)
#define ip4_addr_isany_val(ipaddr) ((ipaddr).addr == IPADDR_ANY)
#define ip4_addr_isany(ipaddr) ((ipaddr) == NULL || ip4_addr_isany_val(*(ipaddr)))
#define ip_addr_copy(dest, src) ip4_addr_copy(dest, src)
#define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2)
#define ip_addr_set_zero(ipaddr) ip4_addr_set_zero(ipaddr)
#define ip_addr_isany(ipaddr) ip4_addr_isany(ipaddr)
in_addr_t netdev_ipaddr_addr(const char *cp);
int netdev_ip4addr_aton(const char *cp, ip4_addr_t *addr);
char *netdev_ip4addr_ntoa(const ip4_addr_t *addr);
char *netdev_ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen);
#define inet_addr(cp) netdev_ipaddr_addr(cp)
#define inet_aton(cp, addr) netdev_ip4addr_aton(cp,(ip4_addr_t*)addr)
#define inet_ntoa(addr) netdev_ip4addr_ntoa((const ip4_addr_t*)&(addr))
#define inet_ntoa_r(addr, buf, buflen) netdev_ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen)
#define inet_addr(cp) sal_ipaddr_addr(cp) #endif /* NETDEV_IPV4 */
#define inet_aton(cp,addr) sal_ip4addr_aton(cp,(ip4_addr_t*)addr)
#define inet_ntoa(addr) sal_ip4addr_ntoa((const ip4_addr_t*)&(addr))
#define inet_ntoa_r(addr, buf, buflen) sal_ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen)
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* SAL_IPADDR_H__ */ #endif /* __NETDEV_IPADDR_H__ */
/*
* Copyright (c) 2006-2019, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-03-18 ChenYong First version
*/
#include <stdio.h>
#include <rtthread.h>
#include <rthw.h>
#include <netdev_ipaddr.h>
#include <netdev.h>
#ifdef RT_USING_SAL
#include <sal_netdb.h>
#include <sal.h>
#endif /* RT_USING_SAL */
#define DBG_TAG "netdev"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
/* The list of network interface device */
struct netdev *netdev_list;
/* The default network interface device */
struct netdev *netdev_default;
/**
* This function will register network interface device and
* add it to network interface device list.
*
* @param netdev the network interface device object
* @param name the network interface device name
* @param user_data user-specific data
*
* @return 0: registered successfully
* -1: registered failed
*/
int netdev_register(struct netdev *netdev, const char *name, void *user_data)
{
rt_base_t level;
uint16_t flags_mask;
int index;
RT_ASSERT(netdev);
RT_ASSERT(name);
/* clean network interface device */
flags_mask = NETDEV_FLAG_UP | NETDEV_FLAG_LINK_UP | NETDEV_FLAG_INTERNET_UP | NETDEV_FLAG_DHCP;
netdev->flags &= ~flags_mask;
ip_addr_set_zero(&(netdev->ip_addr));
ip_addr_set_zero(&(netdev->netmask));
ip_addr_set_zero(&(netdev->gw));
for (index = 0; index < NETDEV_DNS_SERVERS_NUM; index++)
{
ip_addr_set_zero(&(netdev->dns_servers[index]));
}
netdev->status_callback = RT_NULL;
netdev->addr_callback = RT_NULL;
/* fill network interface device */
rt_strncpy(netdev->name, name, rt_strlen(name));
netdev->user_data = user_data;
/* initialize current network interface device single list */
rt_slist_init(&(netdev->list));
level = rt_hw_interrupt_disable();
if (netdev_list == RT_NULL)
{
netdev_list = netdev;
netdev_default = netdev;
}
else
{
/* tail insertion */
rt_slist_append(&(netdev_list->list), &(netdev->list));
}
rt_hw_interrupt_enable(level);
return RT_EOK;
}
/**
* This function will unregister network interface device and
* delete it from network interface device list.
*
* @param netdev the network interface device object
*
* @return 0: unregistered successfully
* -1: unregistered failed
*/
int netdev_unregister(struct netdev *netdev)
{
rt_base_t level;
rt_slist_t *node = RT_NULL;
struct netdev *cur_netdev = RT_NULL;
RT_ASSERT(netdev);
if (netdev_list == RT_NULL)
{
return -RT_ERROR;
}
level = rt_hw_interrupt_disable();
for (node = &(netdev_list->list); node; node = rt_slist_next(node))
{
cur_netdev = rt_slist_entry(node, struct netdev, list);
if (cur_netdev && (rt_memcpy(cur_netdev, netdev, sizeof(struct netdev)) == 0))
{
rt_slist_remove(&(netdev_list->list), &(cur_netdev->list));
rt_hw_interrupt_enable(level);
return RT_EOK;
}
}
rt_hw_interrupt_enable(level);
/* not find this network interface device in network interface device list */
return -RT_ERROR;
}
/**
* This function will get the first network interface device
* with the link_up status in network interface device list.
*
* @return != NULL: network interface device object
* NULL: get failed
*/
struct netdev *netdev_get_first_link_up(void)
{
rt_base_t level;
rt_slist_t *node = RT_NULL;
struct netdev *netdev = RT_NULL;
if (netdev_list == RT_NULL)
{
return RT_NULL;
}
level = rt_hw_interrupt_disable();
for (node = &(netdev_list->list); node; node = rt_slist_next(node))
{
netdev = rt_slist_entry(node, struct netdev, list);
if (netdev && netdev_is_up(netdev) && netdev_is_link_up(netdev))
{
rt_hw_interrupt_enable(level);
return netdev;
}
}
rt_hw_interrupt_enable(level);
return RT_NULL;
}
/**
* This function will get the first network interface device
* in network interface device list by IP address.
*
* @param addr the network interface device IP address
*
* @return != NULL: network interface device object
* NULL: get failed
*/
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;
if (netdev_list == RT_NULL)
{
return RT_NULL;
}
level = rt_hw_interrupt_disable();
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_hw_interrupt_enable(level);
return netdev;
}
}
rt_hw_interrupt_enable(level);
return RT_NULL;
}
/**
* This function will get network interface device
* in network interface device list by netdev name.
*
* @param name the network interface device name
*
* @return != NULL: network interface device object
* NULL: get failed
*/
struct netdev *netdev_get_by_name(const char *name)
{
rt_base_t level;
rt_slist_t *node = RT_NULL;
struct netdev *netdev = RT_NULL;
if (netdev_list == RT_NULL)
{
return RT_NULL;
}
level = rt_hw_interrupt_disable();
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(netdev->name)) == 0))
{
rt_hw_interrupt_enable(level);
return netdev;
}
}
rt_hw_interrupt_enable(level);
return RT_NULL;
}
#ifdef RT_USING_SAL
/**
* This function will get the first network interface device
* in network interface device list by protocol family type.
*
* @param family the network interface device protocol family type
*
* @return != NULL: network interface device object
* NULL: get failed
*/
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;
if (netdev_list == RT_NULL)
{
return RT_NULL;
}
level = rt_hw_interrupt_disable();
for (node = &(netdev_list->list); node; node = rt_slist_next(node))
{
netdev = rt_slist_entry(node, struct netdev, list);
pf = (struct sal_proto_family *) netdev->sal_user_data;
if (pf && pf->skt_ops && pf->family == family &&
netdev_is_up(netdev) && netdev_is_link_up(netdev))
{
rt_hw_interrupt_enable(level);
return netdev;
}
}
for (node = &(netdev_list->list); node; node = rt_slist_next(node))
{
netdev = rt_slist_entry(node, struct netdev, list);
pf = (struct sal_proto_family *) netdev->sal_user_data;
if (pf && pf->skt_ops && pf->sec_family == family &&
netdev_is_up(netdev) && netdev_is_link_up(netdev))
{
rt_hw_interrupt_enable(level);
return netdev;
}
}
rt_hw_interrupt_enable(level);
return RT_NULL;
}
#endif /* RT_USING_SAL */
/**
* This function will set default network interface device.
*
* @param netdev the network interface device to change
*/
void netdev_set_default(struct netdev *netdev)
{
if (netdev)
{
netdev_default = netdev;
LOG_D("Setting default network interface device name(%s) successfully.", netdev->name);
}
}
/**
* This function will enable network interface device .
*
* @param netdev the network interface device to change
*
* @return 0: set status successfully
* -1: set status failed
*/
int netdev_set_up(struct netdev *netdev)
{
RT_ASSERT(netdev);
if (!netdev->ops || !netdev->ops->set_up)
{
LOG_E("The network interface device(%s) not support to set status.", netdev->name);
return -RT_ERROR;
}
/* network interface device status flags check */
if (netdev_is_up(netdev))
{
return RT_EOK;
}
/* execute enable network interface device operations by network interface device driver */
return netdev->ops->set_up(netdev);
}
/**
* This function will disable network interface device.
*
* @param netdev the network interface device to change
*
* @return 0: set status successfully
* -1: set sttaus failed
*/
int netdev_set_down(struct netdev *netdev)
{
RT_ASSERT(netdev);
if (!netdev->ops || !netdev->ops->set_down)
{
LOG_E("The network interface device(%s) not support to set status.", netdev->name);
return -RT_ERROR;
}
/* network interface device status flags check */
if (!netdev_is_up(netdev))
{
return RT_EOK;
}
/* execute disable network interface device operations by network interface driver */
return netdev->ops->set_down(netdev);
}
/**
* This function will control network interface device DHCP capability enable or disable.
*
* @param netdev the network interface device device to change
* @param is_enable the new DHCP status
*
* @return 0: set DHCP status successfully
* -1: set DHCP status failed
*/
int netdev_dhcp_enabled(struct netdev *netdev, rt_bool_t is_enabled)
{
RT_ASSERT(netdev);
if (!netdev->ops || !netdev->ops->set_dhcp)
{
LOG_E("The network interface device(%s) not support to set DHCP status.", netdev->name);
return -RT_ERROR;
}
/* network interface device DHCP flags check */
if (netdev_is_dhcp_enabled(netdev) == is_enabled)
{
return RT_EOK;
}
/* execute network interface device DHCP capability control operations */
return netdev->ops->set_dhcp(netdev, is_enabled);
}
/**
* This function will set network interface device IP address.
*
* @param netdev the network interface device to change
* @param ipaddr the new IP address
*
* @return 0: set IP address successfully
* -1: set IP address failed
*/
int netdev_set_ipaddr(struct netdev *netdev, const ip_addr_t *ip_addr)
{
RT_ASSERT(netdev);
RT_ASSERT(ip_addr);
if (!netdev->ops || !netdev->ops->set_addr_info)
{
LOG_E("The network interface device(%s) not support to set IP address.", netdev->name);
return -RT_ERROR;
}
if (netdev_is_dhcp_enabled(netdev))
{
LOG_E("The network interface device(%s) DHCP capability is enable, not support set IP address.", netdev->name);
return -RT_ERROR;
}
/* execute network interface device set IP address operations */
return netdev->ops->set_addr_info(netdev, (ip_addr_t *)ip_addr, RT_NULL, RT_NULL);
}
/**
* This function will set network interface device netmask address.
*
* @param netdev the network interface device to change
* @param netmask the new netmask address
*
* @return 0: set netmask address successfully
* -1: set netmask address failed
*/
int netdev_set_netmask(struct netdev *netdev, const ip_addr_t *netmask)
{
RT_ASSERT(netdev);
RT_ASSERT(netmask);
if (!netdev->ops || !netdev->ops->set_addr_info)
{
LOG_E("The network interface device(%s) not support to set netmask address.", netdev->name);
return -RT_ERROR;
}
if (netdev_is_dhcp_enabled(netdev))
{
LOG_E("The network interface device(%s) DHCP capability is enable, not support set netmask address.", netdev->name);
return -RT_ERROR;
}
/* execute network interface device set netmask address operations */
return netdev->ops->set_addr_info(netdev, RT_NULL, (ip_addr_t *)netmask, RT_NULL);
}
/**
* This function will set network interface device gateway address.
*
* @param netdev the network interface device to change
* @param gateway the new gateway address
*
* @return 0: set gateway address successfully
* -1: set gateway address failed
*/
int netdev_set_gw(struct netdev *netdev, const ip_addr_t *gw)
{
RT_ASSERT(netdev);
RT_ASSERT(gw);
if (!netdev->ops || !netdev->ops->set_addr_info)
{
LOG_E("The network interface device(%s) not support to set gateway address.", netdev->name);
return -RT_ERROR;
}
if (netdev_is_dhcp_enabled(netdev))
{
LOG_E("The network interface device(%s) DHCP capability is enable, not support set gateway address.", netdev->name);
return -RT_ERROR;
}
/* execute network interface device set gateway address operations */
return netdev->ops->set_addr_info(netdev, RT_NULL, RT_NULL, (ip_addr_t *)gw);
}
/**
* This function will set network interface device DNS server address.
*
* @param netdev the network interface device to change
* @param dns_server the new DNS server address
*
* @return 0: set netmask address successfully
* -1: set netmask address failed
*/
int netdev_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_t *dns_server)
{
RT_ASSERT(netdev);
RT_ASSERT(dns_server);
if (dns_num >= NETDEV_DNS_SERVERS_NUM)
{
LOG_E("The number of DNS servers(%d) set exceeds the maximum number(%d).", dns_num + 1, NETDEV_DNS_SERVERS_NUM);
return -RT_ERROR;
}
if (!netdev->ops || !netdev->ops->set_dns_server)
{
LOG_E("The network interface device(%s) not support to set DNS server address.", netdev->name);
return -RT_ERROR;
}
/* execute network interface device set DNS server address operations */
return netdev->ops->set_dns_server(netdev, (ip_addr_t *)dns_server);
}
/**
* This function will set callback to be called when the network interface device status has been changed.
*
* @param netdev the network interface device to change
* @param status_callback the callback be called when the status has been changed.
*/
void netdev_set_status_callback(struct netdev *netdev, netdev_callback_fn status_callback)
{
RT_ASSERT(netdev);
RT_ASSERT(status_callback);
netdev->status_callback = status_callback;
}
/**
* This function will set callback to be called when the network interface device address has been changed.
*
* @param netdev the network interface device to change
* @param addr_callback the callback be called when the address has been changed.
*/
void netdev_set_addr_callback(struct netdev *netdev, netdev_callback_fn addr_callback)
{
RT_ASSERT(netdev);
RT_ASSERT(addr_callback);
netdev->addr_callback = addr_callback;
}
/**
* This function will set network interface device IP address.
* @NOTE it can only be called in the network interface device driver.
*
* @param netdev the network interface device to change
* @param ipaddr the new IP address
*/
void netdev_low_level_set_ipaddr(struct netdev *netdev, const ip_addr_t *ip_addr)
{
RT_ASSERT(ip_addr);
if (netdev && ip_addr_cmp(&(netdev->ip_addr), ip_addr) == 0)
{
ip_addr_copy(netdev->ip_addr, *ip_addr);
#ifdef RT_USING_SAL
/* set network interface device flags to internet up */
if (netdev_is_up(netdev) && netdev_is_link_up(netdev))
{
sal_check_netdev_internet_up(netdev);
}
#endif /* RT_USING_SAL */
/* execute IP address change callback function */
if (netdev->addr_callback)
{
netdev->addr_callback(netdev, NETDEV_CB_ADDR_IP);
}
}
}
/**
* This function will set network interface device netmask address.
* @NOTE it can only be called in the network interface device driver.
*
* @param netdev the network interface device to change
* @param netmask the new netmask address
*/
void netdev_low_level_set_netmask(struct netdev *netdev, const ip_addr_t *netmask)
{
RT_ASSERT(netmask);
if (netdev && ip_addr_cmp(&(netdev->netmask), netmask) == 0)
{
ip_addr_copy(netdev->netmask, *netmask);
#ifdef RT_USING_SAL
/* set network interface device flags to internet up */
if (netdev_is_up(netdev) && netdev_is_link_up(netdev) &&
!ip_addr_isany(&(netdev->ip_addr)))
{
sal_check_netdev_internet_up(netdev);
}
#endif /* RT_USING_SAL */
/* execute netmask address change callback function */
if (netdev->addr_callback)
{
netdev->addr_callback(netdev, NETDEV_CB_ADDR_NETMASK);
}
}
}
/**
* This function will set network interface device gateway address.
* @NOTE it can only be called in the network interface device driver.
*
* @param netdev the network interface device to change
* @param gateway the new gateway address
*/
void netdev_low_level_set_gw(struct netdev *netdev, const ip_addr_t *gw)
{
RT_ASSERT(gw);
if (netdev && ip_addr_cmp(&(netdev->gw), gw) == 0)
{
ip_addr_copy(netdev->gw, *gw);
#ifdef RT_USING_SAL
/* set network interface device flags to internet up */
if (netdev_is_up(netdev) && netdev_is_link_up(netdev) &&
!ip_addr_isany(&(netdev->ip_addr)))
{
sal_check_netdev_internet_up(netdev);
}
#endif /* RT_USING_SAL */
/* execute gateway address change callback function */
if (netdev->addr_callback)
{
netdev->addr_callback(netdev, NETDEV_CB_ADDR_GATEWAY);
}
}
}
/**
* This function will set network interface device DNS server address.
* @NOTE it can only be called in the network interface device driver.
*
* @param netdev the network interface device to change
* @param dns_server the new DNS server address
*
*/
void netdev_low_level_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_t *dns_server)
{
int index;
RT_ASSERT(dns_server);
/* check DNS servers is exist */
for (index = 0; index < NETDEV_DNS_SERVERS_NUM; index++)
{
if (ip_addr_cmp(&(netdev->dns_servers[index]), dns_server))
{
return;
}
}
if (netdev && dns_num < NETDEV_DNS_SERVERS_NUM)
{
ip_addr_copy(netdev->dns_servers[dns_num], *dns_server);
/* execute DNS servers address change callback function */
if (netdev->addr_callback)
{
netdev->addr_callback(netdev, NETDEV_CB_ADDR_DNS_SERVER);
}
}
}
/**
* This function will set network interface device status.
* @NOTE it can only be called in the network interface device driver.
*
* @param netdev the network interface device to change
* @param is_up the new status
*/
void netdev_low_level_set_status(struct netdev *netdev, rt_bool_t is_up)
{
if (netdev && netdev_is_up(netdev) != is_up)
{
if (is_up)
{
netdev->flags |= NETDEV_FLAG_UP;
}
else
{
netdev->flags &= ~NETDEV_FLAG_UP;
}
/* execute network interface device status change callback function */
if (netdev->status_callback)
{
netdev->status_callback(netdev, is_up ? NETDEV_CB_STATUS_UP : NETDEV_CB_STATUS_DOWN);
}
}
}
/**
* This function will set network interface device active link status.
* @NOTE it can only be called in the network interface device driver.
*
* @param netdev the network interface device to change
* @param is_up the new link status
*/
void netdev_low_level_set_link_status(struct netdev *netdev, rt_bool_t is_up)
{
if (netdev && netdev_is_link_up(netdev) != is_up)
{
if (is_up)
{
netdev->flags |= NETDEV_FLAG_LINK_UP;
#ifdef RT_USING_SAL
/* set network interface device flags to internet up */
if (netdev_is_up(netdev) && !ip_addr_isany(&(netdev->ip_addr)))
{
sal_check_netdev_internet_up(netdev);
}
#endif /* RT_USING_SAL */
}
else
{
netdev->flags &= ~NETDEV_FLAG_LINK_UP;
/* set network interface device flags to internet down */
netdev->flags &= ~NETDEV_FLAG_INTERNET_UP;
}
/* execute link status change callback function */
if (netdev->status_callback)
{
netdev->status_callback(netdev, is_up ? NETDEV_CB_STATUS_LINK_UP : NETDEV_CB_STATUS_LINK_DOWN);
}
}
}
/**
* This function will set network interface device DHCP status.
* @NOTE it can only be called in the network interface device driver.
*
* @param netdev the network interface device to change
* @param is_up the new DHCP status
*/
void netdev_low_level_set_dhcp_status(struct netdev *netdev, rt_bool_t is_enable)
{
if (netdev && netdev_is_dhcp_enabled(netdev) != is_enable)
{
if (is_enable)
{
netdev->flags |= NETDEV_FLAG_DHCP;
}
else
{
netdev->flags &= ~NETDEV_FLAG_DHCP;
}
/* execute DHCP status change callback function */
if (netdev->status_callback)
{
netdev->status_callback(netdev, is_enable ? NETDEV_CB_STATUS_DHCP_ENABLE : NETDEV_CB_STATUS_DHCP_DISABLE);
}
}
}
#ifdef FINSH_USING_MSH
#include <finsh.h>
#ifdef NETDEV_USING_IFCONFIG
static void netdev_list_if(void)
{
#define NETDEV_IFCONFIG_MAC_MAX_LEN 6
#define NETDEV_IFCONFIG_IEMI_MAX_LEN 8
rt_ubase_t index;
rt_base_t level;
rt_slist_t *node = RT_NULL;
struct netdev *netdev = RT_NULL;
struct netdev *cur_netdev_list = netdev_list;
if (cur_netdev_list == RT_NULL)
{
rt_kprintf("ifconfig: network interface device list error.\n");
return;
}
level = rt_hw_interrupt_disable();
for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node))
{
netdev = rt_list_entry(node, struct netdev, list);
rt_kprintf("network interface device: %s%s\n",
netdev->name,
(netdev == netdev_default)?" (Default)":"");
rt_kprintf("MTU: %d\n", netdev->mtu);
/* 6 - MAC address, 8 - IEMI */
if (netdev->hwaddr_len == NETDEV_IFCONFIG_MAC_MAX_LEN)
{
rt_kprintf("MAC: ");
for (index = 0; index < netdev->hwaddr_len; index++)
{
rt_kprintf("%02x ", netdev->hwaddr[index]);
}
}
else if (netdev->hwaddr_len == NETDEV_IFCONFIG_IEMI_MAX_LEN)
{
rt_kprintf("IEMI: ");
for (index = 0; index < netdev->hwaddr_len; index++)
{
/* two numbers are displayed at one time*/
if (netdev->hwaddr[index] < 10 && index != netdev->hwaddr_len - 1)
rt_kprintf("0");
rt_kprintf("%d", netdev->hwaddr[index]);
}
}
rt_kprintf("\nFLAGS:");
if (netdev->flags & NETDEV_FLAG_UP) rt_kprintf(" UP");
else rt_kprintf(" DOWN");
if (netdev->flags & NETDEV_FLAG_LINK_UP) rt_kprintf(" LINK_UP");
else rt_kprintf(" LINK_DOWN");
if (netdev->flags & NETDEV_FLAG_INTERNET_UP) rt_kprintf(" INTERNET_UP");
else rt_kprintf(" INTERNET_DOWN");
if (netdev->flags & NETDEV_FLAG_DHCP) rt_kprintf(" DHCP_ENABLE");
else rt_kprintf(" DHCP_DISABLE");
if (netdev->flags & NETDEV_FLAG_ETHARP) rt_kprintf(" ETHARP");
if (netdev->flags & NETDEV_FLAG_BROADCAST) rt_kprintf(" BROADCAST");
if (netdev->flags & NETDEV_FLAG_IGMP) rt_kprintf(" IGMP");
rt_kprintf("\n");
rt_kprintf("ip address: %s\n", inet_ntoa(netdev->ip_addr));
rt_kprintf("gw address: %s\n", inet_ntoa(netdev->gw));
rt_kprintf("net mask : %s\n", inet_ntoa(netdev->netmask));
for (index = 0; index < NETDEV_DNS_SERVERS_NUM; index++)
{
rt_kprintf("dns server #%d: %s\n", index, inet_ntoa(netdev->dns_servers[index]));
}
if (rt_slist_next(node))
{
rt_kprintf("\n");
}
}
rt_hw_interrupt_enable(level);
}
static void netdev_set_if(char* netdev_name, char* ip_addr, char* gw_addr, char* nm_addr)
{
struct netdev *netdev = RT_NULL;
ip_addr_t addr;
netdev = netdev_get_by_name(netdev_name);
if (netdev == RT_NULL)
{
rt_kprintf("bad network interface device name(%s).\n", netdev_name);
return;
}
/* set IP address */
if ((ip_addr != RT_NULL) && inet_aton(ip_addr, &addr))
{
netdev_set_ipaddr(netdev, &addr);
}
/* set gateway address */
if ((gw_addr != RT_NULL) && inet_aton(gw_addr, &addr))
{
netdev_set_gw(netdev, &addr);
}
/* set netmask address */
if ((nm_addr != RT_NULL) && inet_aton(nm_addr, &addr))
{
netdev_set_netmask(netdev, &addr);
}
}
int netdev_ifconfig(int argc, char **argv)
{
if (argc == 1)
{
netdev_list_if();
}
else if (argc == 5)
{
rt_kprintf("config : %s\n", argv[1]);
rt_kprintf("IP addr: %s\n", argv[2]);
rt_kprintf("Gateway: %s\n", argv[3]);
rt_kprintf("netmask: %s\n", argv[4]);
netdev_set_if(argv[1], argv[2], argv[3], argv[4]);
}
else
{
rt_kprintf("bad parameter! e.g: ifconfig e0 192.168.1.30 192.168.1.1 255.255.255.0\n");
}
return 0;
}
FINSH_FUNCTION_EXPORT_ALIAS(netdev_ifconfig, __cmd_ifconfig, list the information of all network interfaces);
#endif /* NETDEV_USING_IFCONFIG */
#ifdef NETDEV_USING_PING
static int netdev_cmd_ping(char* target_name, rt_uint32_t times, rt_size_t size)
{
#define NETDEV_PING_DATA_SIZE 32
/** ping receive timeout - in milliseconds */
#define NETDEV_PING_RECV_TIMEO (2 * RT_TICK_PER_SECOND)
/** ping delay - in milliseconds */
#define NETDEV_PING_DELAY (1 * RT_TICK_PER_SECOND)
/* check netdev ping options */
#define NETDEV_PING_IS_COMMONICABLE(netdev) \
((netdev) && (netdev)->ops && (netdev)->ops->ping && \
netdev_is_up(netdev) && netdev_is_link_up(netdev)) \
struct netdev *netdev = RT_NULL;
struct netdev_ping_resp ping_resp;
int index, ret = 0;
if (size == 0)
{
size = NETDEV_PING_DATA_SIZE;
}
if (NETDEV_PING_IS_COMMONICABLE(netdev_default))
{
/* using default network interface device for ping */
netdev = netdev_default;
}
else
{
/* using first internet up status network interface device */
netdev = netdev_get_first_link_up();
if (netdev == RT_NULL || NETDEV_PING_IS_COMMONICABLE(netdev) == 0)
{
rt_kprintf("ping: network interface device get error.\n");
return -RT_ERROR;
}
}
for (index = 0; index < times; index++)
{
rt_memset(&ping_resp, 0x00, sizeof(struct netdev_ping_resp));
ret = netdev->ops->ping(netdev, (const char *)target_name, size, NETDEV_PING_RECV_TIMEO, &ping_resp);
if (ret == -RT_ETIMEOUT)
{
rt_kprintf("ping: from %s icmp_seq=%d timeout\n",
(ip_addr_isany(&(ping_resp.ip_addr))) ? target_name : inet_ntoa(ping_resp.ip_addr), index);
}
else if (ret == -RT_ERROR)
{
rt_kprintf("ping: unknown %s %s\n",
(ip_addr_isany(&(ping_resp.ip_addr))) ? "host" : "address",
(ip_addr_isany(&(ping_resp.ip_addr))) ? target_name : inet_ntoa(ping_resp.ip_addr));
}
else
{
if (ping_resp.ttl == 0)
{
rt_kprintf("%d bytes from %s icmp_seq=%d time=%d ms\n",
ping_resp.data_len, inet_ntoa(ping_resp.ip_addr), index, ping_resp.ticks);
}
else
{
rt_kprintf("%d bytes from %s icmp_seq=%d ttl=%d time=%d ms\n",
ping_resp.data_len, inet_ntoa(ping_resp.ip_addr), index, ping_resp.ttl, ping_resp.ticks);
}
}
rt_thread_mdelay(NETDEV_PING_DELAY);
}
return RT_EOK;
}
int netdev_ping(int argc, char **argv)
{
if (argc == 1)
{
rt_kprintf("Please input: ping <host address>\n");
}
else
{
netdev_cmd_ping(argv[1], 4, 0);
}
return 0;
}
FINSH_FUNCTION_EXPORT_ALIAS(netdev_ping, __cmd_ping, ping network host);
#endif /* NETDEV_USING_IFCONFIG */
static void netdev_list_dns(void)
{
rt_base_t level;
int index = 0;
struct netdev *netdev = RT_NULL;
rt_slist_t *node = RT_NULL;
level = rt_hw_interrupt_disable();
for (node = &(netdev_list->list); node; node = rt_slist_next(node))
{
netdev = rt_list_entry(node, struct netdev, list);
rt_kprintf("network interface device: %s%s\n",
netdev->name,
(netdev == netdev_default)?" (Default)":"");
for(index = 0; index < NETDEV_DNS_SERVERS_NUM; index++)
{
rt_kprintf("dns server #%d: %s\n", index, inet_ntoa(netdev->dns_servers[index]));
}
if (rt_slist_next(node))
{
rt_kprintf("\n");
}
}
rt_hw_interrupt_enable(level);
}
static void netdev_set_dns(char *netdev_name, char *dns_server)
{
struct netdev *netdev = RT_NULL;
ip_addr_t dns_addr;
netdev = netdev_get_by_name(netdev_name);
if (netdev == RT_NULL)
{
rt_kprintf("bad network interface device name(%s).\n", netdev_name);
return;
}
inet_aton(dns_server, &dns_addr);
netdev_set_dns_server(netdev, 0, &dns_addr);
rt_kprintf("set network interface device(%s) dns server #0: %s\n", netdev_name, dns_server);
}
int netdev_dns(int argc, char **argv)
{
if (argc == 1)
{
netdev_list_dns();
}
else if (argc == 3)
{
netdev_set_dns(argv[1], argv[2]);
}
else
{
rt_kprintf("bad parameter! e.g: dns name 114.114.114.114\n");
}
return 0;
}
FINSH_FUNCTION_EXPORT_ALIAS(netdev_dns, __cmd_dns, list and set the information of dns);
#ifdef NETDEV_USING_NETSTAT
static void netdev_cmd_netstat(void)
{
rt_base_t level;
rt_slist_t *node = RT_NULL;
struct netdev *netdev = RT_NULL;
struct netdev *cur_netdev_list = netdev_list;
if (cur_netdev_list == RT_NULL)
{
rt_kprintf("netstat: network interface device list error.\n");
return;
}
level = rt_hw_interrupt_disable();
for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node))
{
netdev = rt_list_entry(node, struct netdev, list);
if (netdev && netdev->ops && netdev->ops->netstat)
{
break;
}
}
rt_hw_interrupt_enable(level);
netdev->ops->netstat(netdev);
}
int netdev_netstat(int argc, char **argv)
{
if (argc != 1)
{
rt_kprintf("Please input: netstat \n");
}
else
{
netdev_cmd_netstat();
}
return 0;
}
FINSH_FUNCTION_EXPORT_ALIAS(netdev_netstat, __cmd_netstat, list the information of TCP / IP);
#endif /* NETDEV_USING_NETSTAT */
#endif /* FINSH_USING_MSH */
...@@ -8,12 +8,12 @@ ...@@ -8,12 +8,12 @@
* 2018-05-18 ChenYong First version * 2018-05-18 ChenYong First version
*/ */
#include <sal_ipaddr.h>
#include <rtthread.h> #include <rtthread.h>
#include <netdev_ipaddr.h>
/* Here for now until needed in other places in lwIP */ /* Here for now until needed in other places in lwIP */
#ifndef isprint #ifndef isprint
#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) #define in_range(c, lo, up) ((uint8_t)c >= lo && (uint8_t)c <= up)
#define isprint(c) in_range(c, 0x20, 0x7f) #define isprint(c) in_range(c, 0x20, 0x7f)
#define isdigit(c) in_range(c, '0', '9') #define isdigit(c) in_range(c, '0', '9')
#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) #define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
...@@ -33,13 +33,13 @@ ...@@ -33,13 +33,13 @@
* @param addr pointer to which to save the ip address in network order * @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 * @return 1 if cp could be converted to addr, 0 on failure
*/ */
int sal_ip4addr_aton(const char *cp, ip4_addr_t *addr) int netdev_ip4addr_aton(const char *cp, ip4_addr_t *addr)
{ {
u32_t val; uint32_t val;
u8_t base; uint8_t base;
char c; char c;
u32_t parts[4]; uint32_t parts[4];
u32_t *pp = parts; uint32_t *pp = parts;
c = *cp; c = *cp;
for (;;) for (;;)
...@@ -72,12 +72,12 @@ int sal_ip4addr_aton(const char *cp, ip4_addr_t *addr) ...@@ -72,12 +72,12 @@ int sal_ip4addr_aton(const char *cp, ip4_addr_t *addr)
{ {
if (isdigit(c)) if (isdigit(c))
{ {
val = (val * base) + (u32_t) (c - '0'); val = (val * base) + (uint32_t) (c - '0');
c = *++cp; c = *++cp;
} }
else if (base == 16 && isxdigit(c)) else if (base == 16 && isxdigit(c))
{ {
val = (val << 4) | (u32_t) (c + 10 - (islower(c) ? 'a' : 'A')); val = (val << 4) | (uint32_t) (c + 10 - (islower(c) ? 'a' : 'A'));
c = *++cp; c = *++cp;
} }
else else
...@@ -180,28 +180,28 @@ int sal_ip4addr_aton(const char *cp, ip4_addr_t *addr) ...@@ -180,28 +180,28 @@ int sal_ip4addr_aton(const char *cp, ip4_addr_t *addr)
* @return either pointer to buf which now holds the ASCII * @return either pointer to buf which now holds the ASCII
* representation of addr or NULL if buf was too small * representation of addr or NULL if buf was too small
*/ */
char *sal_ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen) char *netdev_ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen)
{ {
u32_t s_addr; uint32_t s_addr;
char inv[3]; char inv[3];
char *rp; char *rp;
u8_t *ap; uint8_t *ap;
u8_t rem; uint8_t rem;
u8_t n; uint8_t n;
u8_t i; uint8_t i;
int len = 0; int len = 0;
s_addr = ip4_addr_get_u32(addr); s_addr = ip4_addr_get_u32(addr);
rp = buf; rp = buf;
ap = (u8_t *) &s_addr; ap = (uint8_t *) &s_addr;
for (n = 0; n < 4; n++) for (n = 0; n < 4; n++)
{ {
i = 0; i = 0;
do do
{ {
rem = *ap % (u8_t) 10; rem = *ap % (uint8_t) 10;
*ap /= (u8_t) 10; *ap /= (uint8_t) 10;
inv[i++] = (char) ('0' + rem); inv[i++] = (char) ('0' + rem);
} while (*ap); } while (*ap);
while (i--) while (i--)
...@@ -232,10 +232,10 @@ char *sal_ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen) ...@@ -232,10 +232,10 @@ char *sal_ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen)
* @return pointer to a global static (!) buffer that holds the ASCII * @return pointer to a global static (!) buffer that holds the ASCII
* representation of addr * representation of addr
*/ */
char *sal_ip4addr_ntoa(const ip4_addr_t *addr) char *netdev_ip4addr_ntoa(const ip4_addr_t *addr)
{ {
static char str[IP4ADDR_STRLEN_MAX]; static char str[IP4ADDR_STRLEN_MAX];
return sal_ip4addr_ntoa_r(addr, str, IP4ADDR_STRLEN_MAX); return netdev_ip4addr_ntoa_r(addr, str, IP4ADDR_STRLEN_MAX);
} }
...@@ -246,11 +246,11 @@ char *sal_ip4addr_ntoa(const ip4_addr_t *addr) ...@@ -246,11 +246,11 @@ char *sal_ip4addr_ntoa(const ip4_addr_t *addr)
* @param cp IP address in ascii representation (e.g. "127.0.0.1") * @param cp IP address in ascii representation (e.g. "127.0.0.1")
* @return ip address in network order * @return ip address in network order
*/ */
in_addr_t sal_ipaddr_addr(const char *cp) in_addr_t netdev_ipaddr_addr(const char *cp)
{ {
ip4_addr_t val; ip4_addr_t val;
if (sal_ip4addr_aton(cp, &val)) { if (netdev_ip4addr_aton(cp, &val)) {
return ip4_addr_get_u32(&val); return ip4_addr_get_u32(&val);
} }
return (IPADDR_NONE); return (IPADDR_NONE);
......
...@@ -18,14 +18,18 @@ extern "C" { ...@@ -18,14 +18,18 @@ extern "C" {
#endif #endif
#ifdef SAL_USING_LWIP #ifdef SAL_USING_LWIP
/* lwIP protocol family register */
int lwip_inet_init(void); /* Set lwIP network interface device protocol family information */
#endif int sal_lwip_netdev_set_pf_info(struct netdev *netdev);
#endif /* SAL_USING_LWIP */
#ifdef SAL_USING_AT #ifdef SAL_USING_AT
/* AT protocol family register */
int at_inet_init(void); /* Set AT network interface device protocol family information */
#endif int sal_at_netdev_set_pf_info(struct netdev *netdev);
#endif /* SAL_USING_AT */
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
#include <at_socket.h> #include <at_socket.h>
#include <af_inet.h> #include <af_inet.h>
#include <netdev.h>
#ifdef SAL_USING_POSIX #ifdef SAL_USING_POSIX
#include <dfs_poll.h> #include <dfs_poll.h>
#endif #endif
...@@ -78,24 +80,12 @@ static const struct sal_socket_ops at_socket_ops = ...@@ -78,24 +80,12 @@ static const struct sal_socket_ops at_socket_ops =
NULL, NULL,
NULL, NULL,
NULL, NULL,
#ifdef SAL_USING_POSIX #ifdef SAL_USING_POSIX
at_poll, at_poll,
#endif /* SAL_USING_POSIX */ #endif /* SAL_USING_POSIX */
}; };
static int at_create(struct sal_socket *socket, int type, int protocol) static const struct sal_netdb_ops at_netdb_ops =
{
RT_ASSERT(socket);
//TODO Check type & protocol
socket->ops = &at_socket_ops;
return 0;
}
static struct sal_proto_ops at_proto_ops =
{ {
at_gethostbyname, at_gethostbyname,
NULL, NULL,
...@@ -107,16 +97,18 @@ static const struct sal_proto_family at_inet_family = ...@@ -107,16 +97,18 @@ static const struct sal_proto_family at_inet_family =
{ {
AF_AT, AF_AT,
AF_INET, AF_INET,
at_create, &at_socket_ops,
&at_proto_ops, &at_netdb_ops,
}; };
int at_inet_init(void)
/* Set AT network interface device protocol family information */
int sal_at_netdev_set_pf_info(struct netdev *netdev)
{ {
sal_proto_family_register(&at_inet_family); RT_ASSERT(netdev);
netdev->sal_user_data = (void *) &at_inet_family;
return 0; return 0;
} }
INIT_COMPONENT_EXPORT(at_inet_init);
#endif /* SAL_USING_AT */ #endif /* SAL_USING_AT */
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <lwip/netdb.h> #include <lwip/netdb.h>
#include <lwip/api.h> #include <lwip/api.h>
#include <lwip/init.h> #include <lwip/init.h>
#include <lwip/netif.h>
#ifdef SAL_USING_POSIX #ifdef SAL_USING_POSIX
#include <dfs_poll.h> #include <dfs_poll.h>
...@@ -22,6 +23,8 @@ ...@@ -22,6 +23,8 @@
#include <sal.h> #include <sal.h>
#include <af_inet.h> #include <af_inet.h>
#include <netdev.h>
#if LWIP_VERSION < 0x2000000 #if LWIP_VERSION < 0x2000000
#define SELWAIT_T int #define SELWAIT_T int
#else #else
...@@ -281,18 +284,7 @@ static const struct sal_socket_ops lwip_socket_ops = ...@@ -281,18 +284,7 @@ static const struct sal_socket_ops lwip_socket_ops =
#endif #endif
}; };
static int inet_create(struct sal_socket *socket, int type, int protocol) static const struct sal_netdb_ops lwip_netdb_ops =
{
RT_ASSERT(socket);
//TODO Check type & protocol
socket->ops = &lwip_socket_ops;
return 0;
}
static struct sal_proto_ops lwip_proto_ops =
{ {
lwip_gethostbyname, lwip_gethostbyname,
lwip_gethostbyname_r, lwip_gethostbyname_r,
...@@ -304,16 +296,17 @@ static const struct sal_proto_family lwip_inet_family = ...@@ -304,16 +296,17 @@ static const struct sal_proto_family lwip_inet_family =
{ {
AF_INET, AF_INET,
AF_INET, AF_INET,
inet_create, &lwip_socket_ops,
&lwip_proto_ops, &lwip_netdb_ops,
}; };
int lwip_inet_init(void) /* Set lwIP network interface device protocol family information */
int sal_lwip_netdev_set_pf_info(struct netdev *netdev)
{ {
sal_proto_family_register(&lwip_inet_family); RT_ASSERT(netdev);
netdev->sal_user_data = (void *) &lwip_inet_family;
return 0; return 0;
} }
INIT_COMPONENT_EXPORT(lwip_inet_init);
#endif /* SAL_USING_LWIP */ #endif /* SAL_USING_LWIP */
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include <netdb.h> #include <netdb.h>
#include <sal.h> #include <sal.h>
#include <netdev.h>
#ifdef SAL_USING_TLS #ifdef SAL_USING_TLS
#if !defined(MBEDTLS_CONFIG_FILE) #if !defined(MBEDTLS_CONFIG_FILE)
...@@ -76,6 +78,7 @@ int mbedtls_net_send_cb(void *ctx, const unsigned char *buf, size_t len) ...@@ -76,6 +78,7 @@ int mbedtls_net_send_cb(void *ctx, const unsigned char *buf, size_t len)
{ {
struct sal_socket *sock; struct sal_socket *sock;
int socket, ret; int socket, ret;
struct sal_proto_family *pf;
RT_ASSERT(ctx); RT_ASSERT(ctx);
RT_ASSERT(buf); RT_ASSERT(buf);
...@@ -86,9 +89,11 @@ int mbedtls_net_send_cb(void *ctx, const unsigned char *buf, size_t len) ...@@ -86,9 +89,11 @@ int mbedtls_net_send_cb(void *ctx, const unsigned char *buf, size_t len)
{ {
return -1; return -1;
} }
pf = (struct sal_proto_family *)sock->netdev->sal_user_data;
/* Register scoket sendto option to TLS send data callback */ /* Register scoket sendto option to TLS send data callback */
ret = sock->ops->sendto((int) sock->user_data, (void *)buf, len, 0, RT_NULL, RT_NULL); ret = pf->skt_ops->sendto((int) sock->user_data, (void *)buf, len, 0, RT_NULL, RT_NULL);
if (ret < 0) if (ret < 0)
{ {
#ifdef RT_USING_DFS #ifdef RT_USING_DFS
...@@ -109,6 +114,7 @@ int mbedtls_net_send_cb(void *ctx, const unsigned char *buf, size_t len) ...@@ -109,6 +114,7 @@ int mbedtls_net_send_cb(void *ctx, const unsigned char *buf, size_t len)
int mbedtls_net_recv_cb( void *ctx, unsigned char *buf, size_t len) int mbedtls_net_recv_cb( void *ctx, unsigned char *buf, size_t len)
{ {
struct sal_socket *sock; struct sal_socket *sock;
struct sal_proto_family *pf;
int socket, ret; int socket, ret;
RT_ASSERT(ctx); RT_ASSERT(ctx);
...@@ -121,8 +127,10 @@ int mbedtls_net_recv_cb( void *ctx, unsigned char *buf, size_t len) ...@@ -121,8 +127,10 @@ int mbedtls_net_recv_cb( void *ctx, unsigned char *buf, size_t len)
return -1; return -1;
} }
pf = (struct sal_proto_family *)sock->netdev->sal_user_data;
/* Register scoket recvfrom option to TLS recv data callback */ /* Register scoket recvfrom option to TLS recv data callback */
ret = sock->ops->recvfrom((int) sock->user_data, (void *)buf, len, 0, RT_NULL, RT_NULL); ret = pf->skt_ops->recvfrom((int) sock->user_data, (void *)buf, len, 0, RT_NULL, RT_NULL);
if (ret < 0) if (ret < 0)
{ {
#ifdef RT_USING_DFS #ifdef RT_USING_DFS
......
...@@ -43,6 +43,24 @@ typedef uint32_t socklen_t; ...@@ -43,6 +43,24 @@ typedef uint32_t socklen_t;
#define SAL_SOCKET_OFFSET 0 #define SAL_SOCKET_OFFSET 0
#endif #endif
struct sal_socket
{
uint32_t magic; /* SAL socket magic word */
int socket; /* SAL socket descriptor */
int domain;
int type;
int protocol;
struct netdev *netdev; /* SAL network interface device */
void *user_data; /* user-specific data */
#ifdef SAL_USING_TLS
void *user_data_tls; /* user-specific TLS data */
#endif
};
/* network interface socket opreations */
struct sal_socket_ops struct sal_socket_ops
{ {
int (*socket) (int domain, int type, int protocol); int (*socket) (int domain, int type, int protocol);
...@@ -64,7 +82,8 @@ struct sal_socket_ops ...@@ -64,7 +82,8 @@ struct sal_socket_ops
#endif #endif
}; };
struct sal_proto_ops /* sal network database name resolving */
struct sal_netdb_ops
{ {
struct hostent* (*gethostbyname) (const char *name); struct hostent* (*gethostbyname) (const char *name);
int (*gethostbyname_r)(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop); int (*gethostbyname_r)(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop);
...@@ -72,42 +91,21 @@ struct sal_proto_ops ...@@ -72,42 +91,21 @@ struct sal_proto_ops
void (*freeaddrinfo) (struct addrinfo *ai); void (*freeaddrinfo) (struct addrinfo *ai);
}; };
struct sal_socket
{
uint32_t magic; /* SAL socket magic word */
int socket; /* SAL socket descriptor */
int domain;
int type;
int protocol;
const struct sal_socket_ops *ops; /* socket options */
void *user_data; /* user-specific data */
#ifdef SAL_USING_TLS
void *user_data_tls; /* user-specific TLS data */
#endif
};
struct sal_proto_family struct sal_proto_family
{ {
int family; /* primary protocol families type */ int family; /* primary protocol families type */
int sec_family; /* secondary protocol families type */ int sec_family; /* secondary protocol families type */
int (*create)(struct sal_socket *sal_socket, int type, int protocol); /* register socket options */ const struct sal_socket_ops *skt_ops; /* socket opreations */
const struct sal_netdb_ops *netdb_ops; /* network database opreations */
struct sal_proto_ops *ops; /* protocol family options */
}; };
/* SAL(Socket Abstraction Layer) initialize */ /* SAL(Socket Abstraction Layer) initialize */
int sal_init(void); int sal_init(void);
/* Get SAL socket object by socket descriptor */
struct sal_socket *sal_get_socket(int sock); struct sal_socket *sal_get_socket(int sock);
/* SAL protocol family register and unregister operate */ /* check SAL socket netweork interface device internet status */
int sal_proto_family_register(const struct sal_proto_family *pf); int sal_check_netdev_internet_up(struct netdev *netdev);
int sal_proto_family_unregister(int family);
rt_bool_t sal_proto_family_is_registered(int family);
struct sal_proto_family *sal_proto_family_find(int family);
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#ifndef SAL_NETDB_H__ #ifndef SAL_NETDB_H__
#define SAL_NETDB_H__ #define SAL_NETDB_H__
#include <sal_socket.h> #include "sal_socket.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#ifndef SAL_SOCKET_H__ #ifndef SAL_SOCKET_H__
#define SAL_SOCKET_H__ #define SAL_SOCKET_H__
#include "sal_ipaddr.h" #include <arpa/inet.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
......
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-05-17 ChenYong First version
*/
#ifndef SAL_TYPE_H__
#define SAL_TYPE_H__
#include <stdlib.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef int8_t err_t;
typedef uint8_t u8_t;
typedef int8_t s8_t;
typedef uint16_t u16_t;
typedef int16_t s16_t;
typedef uint32_t u32_t;
typedef int32_t s32_t;
typedef uintptr_t mem_ptr_t;
#ifdef __cplusplus
}
#endif
#endif /* SAL_TYPE_H__ */
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <rtthread.h> #include <rtthread.h>
#include <rthw.h> #include <rthw.h>
#include <sys/time.h>
#include <sal_socket.h> #include <sal_socket.h>
#include <sal_netdb.h> #include <sal_netdb.h>
...@@ -18,9 +19,17 @@ ...@@ -18,9 +19,17 @@
#include <sal_tls.h> #include <sal_tls.h>
#endif #endif
#include <sal.h> #include <sal.h>
#include <netdev.h>
#define DBG_TAG "SAL_SKT" #include <ipc/workqueue.h>
#define DBG_LVL DBG_INFO
/* 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> #include <rtdbg.h>
#define SOCKET_TABLE_STEP_LEN 4 #define SOCKET_TABLE_STEP_LEN 4
...@@ -37,8 +46,6 @@ struct sal_socket_table ...@@ -37,8 +46,6 @@ struct sal_socket_table
static struct sal_proto_tls *proto_tls; static struct sal_proto_tls *proto_tls;
#endif #endif
/* The global array of available protocol families */
static struct sal_proto_family proto_families[SAL_PROTO_FAMILIES_NUM];
/* The global socket table */ /* The global socket table */
static struct sal_socket_table socket_table; static struct sal_socket_table socket_table;
static struct rt_mutex sal_core_lock; static struct rt_mutex sal_core_lock;
...@@ -49,14 +56,39 @@ static rt_bool_t init_ok = RT_FALSE; ...@@ -49,14 +56,39 @@ 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_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) \ #define SAL_SOCKOPT_PROTO_TLS_EXEC(sock, name, optval, optlen) \
do \ do { \
{ \ if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, name)){ \
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, name)) \
{ \
return proto_tls->ops->name((sock)->user_data_tls, (optval), (optlen)); \ return proto_tls->ops->name((sock)->user_data_tls, (optval), (optlen)); \
} \ } \
}while(0) \ }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_COMMONICABLE(netdev) \
do { \
if (!netdev_is_up(netdev) || !netdev_is_link_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) && netdev_is_link_up(netdev) && \
((pf) = (struct sal_proto_family *) (netdev)->sal_user_data) != RT_NULL && \
(pf)->netdb_ops->ops) \
/** /**
* SAL (Socket Abstraction Layer) initialize. * SAL (Socket Abstraction Layer) initialize.
...@@ -94,153 +126,176 @@ int sal_init(void) ...@@ -94,153 +126,176 @@ int sal_init(void)
} }
INIT_COMPONENT_EXPORT(sal_init); INIT_COMPONENT_EXPORT(sal_init);
/** /* check SAL network interface device internet status */
* This function will register TLS protocol to the global TLS protocol. static void check_netdev_internet_up_work(struct rt_work *work, void *work_data)
*
* @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)
{ {
RT_ASSERT(pt); #define SAL_INTERNET_VERSION 0x00
proto_tls = (struct sal_proto_tls *) pt; #define SAL_INTERNET_BUFF_LEN 12
#define SAL_INTERNET_TIMEOUT (2 * RT_TICK_PER_SECOND)
return 0; #define SAL_INTERNET_HOST "link.rt-thread.org"
} #define SAL_INTERNET_PORT 8101
#endif
/** #define SAL_INTERNET_MONTH_LEN 4
* This function will register protocol family to the global array of protocol families. #define SAL_INTERNET_DATE_LEN 16
*
* @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;
/* disable interrupt */ int index, sockfd = 0, result = 0;
level = rt_hw_interrupt_disable(); 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;
/* check protocol family is already registered */ const char month[][SAL_INTERNET_MONTH_LEN] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
for(idx = 0; idx < SAL_PROTO_FAMILIES_NUM; idx++) 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) rt_free((struct rt_delayed_work *)work);
{
/* enable interrupt */
rt_hw_interrupt_enable(level);
LOG_E("%s protocol family is already registered!", pf->family);
return -1;
}
} }
/* find an empty protocol family entry */ /* get network interface socket operations */
for(idx = 0; idx < SAL_PROTO_FAMILIES_NUM && proto_families[idx].create; idx++); if (pf == RT_NULL || pf->skt_ops == RT_NULL)
/* can't find an empty protocol family entry */
if (idx == SAL_PROTO_FAMILIES_NUM)
{ {
/* enable interrupt */ result = -RT_ERROR;
rt_hw_interrupt_enable(level); goto __exit;
return -1;
} }
proto_families[idx].family = pf->family; host = (struct hostent *) pf->netdb_ops->gethostbyname(SAL_INTERNET_HOST);
proto_families[idx].sec_family = pf->sec_family; if (host == RT_NULL)
proto_families[idx].create = pf->create; {
result = -RT_ERROR;
goto __exit;
}
proto_families[idx].ops = pf->ops; skt_ops = pf->skt_ops;
proto_families[idx].ops->gethostbyname = pf->ops->gethostbyname; if((sockfd = skt_ops->socket(AF_INET, SOCK_DGRAM, 0)) < 0)
proto_families[idx].ops->gethostbyname_r = pf->ops->gethostbyname_r; {
proto_families[idx].ops->freeaddrinfo = pf->ops->freeaddrinfo; result = -RT_ERROR;
proto_families[idx].ops->getaddrinfo = pf->ops->getaddrinfo; goto __exit;
}
/* enable interrupt */ server_addr.sin_family = AF_INET;
rt_hw_interrupt_enable(level); 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));
return 0; timeout.tv_sec = SAL_INTERNET_TIMEOUT;
} timeout.tv_usec = 0;
/** /* set receive and send timeout */
* This function removes a previously registered protocol family object. skt_ops->setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (void *) &timeout, sizeof(timeout));
* skt_ops->setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (void *) &timeout, sizeof(timeout));
* @param pf protocol family object
*
* @return >=0 : unregister protocol family index
* -1 : unregister failed
*/
int sal_proto_family_unregister(int family)
{
int idx = 0;
RT_ASSERT(family > 0 && family < AF_MAX); /* get build moth value*/
rt_memset(date, 0x00, SAL_INTERNET_DATE_LEN);
rt_snprintf(date, SAL_INTERNET_DATE_LEN, "%s", __DATE__);
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)); moth_num = index + 1;
break;
return idx;
} }
} }
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 * @param netdev the network interface device to check
*
* @return 1: protocol family is registered
* 0: protocol family is not registered
*/ */
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) LOG_W("No memory for network interface device(%s) delay work.", netdev->name);
{ return -1;
return RT_TRUE;
}
} }
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(pt);
proto_tls = (struct sal_proto_tls *) pt;
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];
}
}
return RT_NULL; return 0;
} }
#endif
/** /**
* This function will get sal socket object by sal socket descriptor. * This function will get sal socket object by sal socket descriptor.
...@@ -294,36 +349,6 @@ static void sal_unlock(void) ...@@ -294,36 +349,6 @@ static void sal_unlock(void)
rt_mutex_release(&sal_core_lock); rt_mutex_release(&sal_core_lock);
} }
/**
* This function will get protocol family structure by family type
*
* @param family protocol family
*
* @return protocol family structure address
*/
static struct sal_proto_family *get_proto_family(int family)
{
int idx;
for (idx = 0; idx < SAL_PROTO_FAMILIES_NUM; idx++)
{
if (proto_families[idx].family == family && proto_families[idx].create)
{
return &proto_families[idx];
}
}
/* 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)
{
return &proto_families[idx];
}
}
return RT_NULL;
}
/** /**
* This function will initialize sal socket object and set socket options * This function will initialize sal socket object and set socket options
* *
...@@ -335,13 +360,16 @@ static struct sal_proto_family *get_proto_family(int family) ...@@ -335,13 +360,16 @@ static struct sal_proto_family *get_proto_family(int family)
* @return 0 : socket initialize success * @return 0 : socket initialize success
* -1 : input the wrong family * -1 : input the wrong family
* -2 : input the wrong socket type * -2 : input the wrong socket type
* -3 : get protocol family object failed * -3 : get network interface failed
* -4 : set socket options failed
*/ */
static int socket_init(int family, int type, int protocol, struct sal_socket **res) static int socket_init(int family, int type, int protocol, struct sal_socket **res)
{ {
struct sal_socket *sock; struct sal_socket *sock;
struct sal_proto_family *pf; struct sal_proto_family *pf;
struct netdev *netdv_def = netdev_default;
struct netdev *netdev = RT_NULL;
rt_bool_t falgs = RT_FALSE;
if (family < 0 || family > AF_MAX) if (family < 0 || family > AF_MAX)
{ {
...@@ -358,16 +386,37 @@ static int socket_init(int family, int type, int protocol, struct sal_socket **r ...@@ -358,16 +386,37 @@ static int socket_init(int family, int type, int protocol, struct sal_socket **r
sock->type = type; sock->type = type;
sock->protocol = protocol; sock->protocol = protocol;
/* get socket protocol family object */ /* get socket operations from network interface device */
if ((pf = get_proto_family(family)) == RT_NULL) if (netdv_def)
{ {
if (netdev_is_up(netdv_def) && netdev_is_link_up(netdv_def))
{
/* 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;
falgs = RT_TRUE;
}
}
}
else
{
LOG_E("not find default network interface device for socket create.");
return -3; return -3;
} }
/* registered the current socket options */ if (falgs == RT_FALSE)
if (pf->create(sock, type, protocol) != 0)
{ {
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; return 0;
...@@ -380,10 +429,11 @@ static int socket_alloc(struct sal_socket_table *st, int f_socket) ...@@ -380,10 +429,11 @@ static int socket_alloc(struct sal_socket_table *st, int f_socket)
/* find an empty socket entry */ /* find an empty socket entry */
for (idx = f_socket; idx < (int) st->max_socket; idx++) for (idx = f_socket; idx < (int) st->max_socket; idx++)
{ {
if (st->sockets[idx] == RT_NULL) if (st->sockets[idx] == RT_NULL ||
break; st->sockets[idx]->netdev == RT_NULL)
if (st->sockets[idx]->ops == RT_NULL) {
break; break;
}
} }
/* allocate a larger sockte container */ /* allocate a larger sockte container */
...@@ -422,7 +472,6 @@ static int socket_alloc(struct sal_socket_table *st, int f_socket) ...@@ -422,7 +472,6 @@ static int socket_alloc(struct sal_socket_table *st, int f_socket)
__result: __result:
return idx; return idx;
} }
static int socket_new(void) static int socket_new(void)
...@@ -446,7 +495,7 @@ static int socket_new(void) ...@@ -446,7 +495,7 @@ static int socket_new(void)
sock = st->sockets[idx]; sock = st->sockets[idx];
sock->socket = idx + SAL_SOCKET_OFFSET; sock->socket = idx + SAL_SOCKET_OFFSET;
sock->magic = SAL_SOCKET_MAGIC; sock->magic = SAL_SOCKET_MAGIC;
sock->ops = RT_NULL; sock->netdev = RT_NULL;
sock->user_data = RT_NULL; sock->user_data = RT_NULL;
#ifdef SAL_USING_TLS #ifdef SAL_USING_TLS
sock->user_data_tls = RT_NULL; sock->user_data_tls = RT_NULL;
...@@ -461,19 +510,17 @@ int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen) ...@@ -461,19 +510,17 @@ int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen)
{ {
int new_socket; int new_socket;
struct sal_socket *sock; struct sal_socket *sock;
struct sal_proto_family *pf;
sock = sal_get_socket(socket); /* get the socket object by socket descriptor */
if (!sock) SAL_SOCKET_OBJ_GET(sock, socket);
{
return -1;
}
if (sock->ops->accept == RT_NULL) /* check the network interface is commonicable */
{ SAL_NETDEV_IS_COMMONICABLE(sock->netdev);
return -RT_ENOSYS; /* check the network interface socket operations */
} SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, accept);
new_socket = sock->ops->accept((int) sock->user_data, addr, addrlen); new_socket = pf->skt_ops->accept((int) sock->user_data, addr, addrlen);
if (new_socket != -1) if (new_socket != -1)
{ {
int retval; int retval;
...@@ -484,7 +531,7 @@ int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen) ...@@ -484,7 +531,7 @@ int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen)
new_sal_socket = socket_new(); new_sal_socket = socket_new();
if (new_sal_socket < 0) if (new_sal_socket < 0)
{ {
sock->ops->closesocket(new_socket); pf->skt_ops->closesocket(new_socket);
return -1; return -1;
} }
new_sock = sal_get_socket(new_sal_socket); new_sock = sal_get_socket(new_sal_socket);
...@@ -492,13 +539,13 @@ int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen) ...@@ -492,13 +539,13 @@ int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen)
retval = socket_init(sock->domain, sock->type, sock->protocol, &new_sock); retval = socket_init(sock->domain, sock->type, sock->protocol, &new_sock);
if (retval < 0) if (retval < 0)
{ {
sock->ops->closesocket(new_socket); pf->skt_ops->closesocket(new_socket);
rt_memset(new_sock, 0x00, sizeof(struct sal_socket)); rt_memset(new_sock, 0x00, sizeof(struct sal_socket));
LOG_E("New socket registered failed, return error %d.", retval); LOG_E("New socket registered failed, return error %d.", retval);
return -1; 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; new_sock->user_data = (void *) new_socket;
return new_sal_socket; return new_sal_socket;
...@@ -507,40 +554,88 @@ int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen) ...@@ -507,40 +554,88 @@ int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen)
return -1; 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;
#elif NETDEV_IPV4
(*local_ipaddr).addr = svr_addr->sin_addr.s_addr;
#elif NETDEV_IPV6
LOG_E("not support IPV6");
#endif /* SAL_IPV4 && SAL_IPV6*/
}
int sal_bind(int socket, const struct sockaddr *name, socklen_t namelen) int sal_bind(int socket, const struct sockaddr *name, socklen_t namelen)
{ {
struct sal_socket *sock; struct sal_socket *sock;
struct sal_proto_family *pf;
struct netdev *new_netdev;
ip_addr_t local_addr;
sock = sal_get_socket(socket); RT_ASSERT(name);
if (!sock)
/* get the socket object by socket descriptor */
SAL_SOCKET_OBJ_GET(sock, socket);
/* bind network interface by ip address */
sal_sockaddr_to_ipaddr(name, &local_addr);
/* check input ipaddr is default netdev ipaddr */
if (local_addr.addr == INADDR_ANY)
{
SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, bind);
return pf->skt_ops->bind((int) sock->user_data, name, namelen);
}
new_netdev = netdev_get_by_ipaddr(&local_addr);
if (new_netdev == RT_NULL)
{ {
LOG_E("Not find network interface device ipaddr(%s).", inet_ntoa(local_addr));
return -1; return -1;
} }
if (sock->ops->bind == RT_NULL) /* change network interface device parameter in sal socket object */
if (sock->netdev != new_netdev)
{ {
return -RT_ENOSYS; struct sal_proto_family *old_pf, *new_pf;
int new_socket = 0;
/* close old netdev socket */
SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, old_pf, closesocket);
old_pf->skt_ops->closesocket(socket);
/* open new netdev socket */
SAL_NETDEV_SOCKETOPS_VALID(new_netdev, new_pf, socket);
new_socket = new_pf->skt_ops->socket(sock->domain, 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 the network interface socket opreation */
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) int sal_shutdown(int socket, int how)
{ {
struct sal_socket *sock; struct sal_socket *sock;
struct sal_proto_family *pf;
int error = 0;
sock = sal_get_socket(socket); /* get the socket object by socket descriptor */
if (!sock) SAL_SOCKET_OBJ_GET(sock, socket);
{
return -1;
}
if (sock->ops->shutdown == RT_NULL) /* shutdown operation not nead to check network interface status */
{ /* check the network interface socket opreation */
return -RT_ENOSYS; 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 #ifdef SAL_USING_TLS
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, closesocket)) if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, closesocket))
...@@ -551,82 +646,72 @@ int sal_shutdown(int socket, int how) ...@@ -551,82 +646,72 @@ int sal_shutdown(int socket, int how)
} }
} }
#endif #endif
rt_free(sock); error = 0;
socket_table.sockets[socket] = RT_NULL; }
return 0; else
{
error = -1;
} }
return -1; /* free socket */
rt_free(sock);
socket_table.sockets[socket] = RT_NULL;
return error;
} }
int sal_getpeername(int socket, struct sockaddr *name, socklen_t *namelen) int sal_getpeername(int socket, struct sockaddr *name, socklen_t *namelen)
{ {
struct sal_socket *sock; struct sal_socket *sock;
struct sal_proto_family *pf;
sock = sal_get_socket(socket); /* get the socket object by socket descriptor */
if (!sock) SAL_SOCKET_OBJ_GET(sock, socket);
{
return -1;
}
if (sock->ops->getpeername == RT_NULL) /* check the network interface socket opreation */
{ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, getpeername);
return -RT_ENOSYS;
}
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) int sal_getsockname(int socket, struct sockaddr *name, socklen_t *namelen)
{ {
struct sal_socket *sock; struct sal_socket *sock;
struct sal_proto_family *pf;
sock = sal_get_socket(socket); /* get socket object by socket descriptor */
if (!sock) SAL_SOCKET_OBJ_GET(sock, socket);
{
return -1;
}
if (sock->ops->getsockname == RT_NULL) /* check the network interface socket opreation */
{ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, getsockname);
return -RT_ENOSYS;
}
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) int sal_getsockopt(int socket, int level, int optname, void *optval, socklen_t *optlen)
{ {
struct sal_socket *sock; struct sal_socket *sock;
struct sal_proto_family *pf;
sock = sal_get_socket(socket); /* get the socket object by socket descriptor */
if (!sock) SAL_SOCKET_OBJ_GET(sock, socket);
{
return -1;
}
if (sock->ops->getsockopt == RT_NULL) /* check the network interface socket opreation */
{ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, getsockopt);
return -RT_ENOSYS;
}
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) int sal_setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen)
{ {
struct sal_socket *sock; struct sal_socket *sock;
struct sal_proto_family *pf;
sock = sal_get_socket(socket); /* get the socket object by socket descriptor */
if (!sock) SAL_SOCKET_OBJ_GET(sock, socket);
{
return -1;
}
if (sock->ops->setsockopt == RT_NULL) /* check the network interface socket opreation */
{ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, setsockopt);
return -RT_ENOSYS;
}
#ifdef SAL_USING_TLS #ifdef SAL_USING_TLS
if (level == SOL_TLS) if (level == SOL_TLS)
...@@ -657,30 +742,28 @@ int sal_setsockopt(int socket, int level, int optname, const void *optval, sockl ...@@ -657,30 +742,28 @@ int sal_setsockopt(int socket, int level, int optname, const void *optval, sockl
} }
else 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 #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 */ #endif /* SAL_USING_TLS */
} }
int sal_connect(int socket, const struct sockaddr *name, socklen_t namelen) int sal_connect(int socket, const struct sockaddr *name, socklen_t namelen)
{ {
struct sal_socket *sock; struct sal_socket *sock;
struct sal_proto_family *pf;
int ret; int ret;
sock = sal_get_socket(socket); /* get the socket object by socket descriptor */
if (!sock) SAL_SOCKET_OBJ_GET(sock, socket);
{
return -1;
}
if (sock->ops->connect == RT_NULL) /* check the network interface is commonicable */
{ SAL_NETDEV_IS_COMMONICABLE(sock->netdev);
return -RT_ENOSYS; /* 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 #ifdef SAL_USING_TLS
if (ret >= 0 && SAL_SOCKOPS_PROTO_TLS_VALID(sock, connect)) if (ret >= 0 && SAL_SOCKOPS_PROTO_TLS_VALID(sock, connect))
{ {
...@@ -699,36 +782,30 @@ int sal_connect(int socket, const struct sockaddr *name, socklen_t namelen) ...@@ -699,36 +782,30 @@ int sal_connect(int socket, const struct sockaddr *name, socklen_t namelen)
int sal_listen(int socket, int backlog) int sal_listen(int socket, int backlog)
{ {
struct sal_socket *sock; struct sal_socket *sock;
struct sal_proto_family *pf;
sock = sal_get_socket(socket); /* get the socket object by socket descriptor */
if (!sock) SAL_SOCKET_OBJ_GET(sock, socket);
{
return -1;
}
if (sock->ops->listen == RT_NULL) /* check the network interface socket opreation */
{ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, listen);
return -RT_ENOSYS;
}
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, 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_socket *sock;
struct sal_proto_family *pf;
sock = sal_get_socket(socket); /* get the socket object by socket descriptor */
if (!sock) SAL_SOCKET_OBJ_GET(sock, socket);
{
return -1;
}
if (sock->ops->recvfrom == RT_NULL) /* check the network interface is commonicable */
{ SAL_NETDEV_IS_COMMONICABLE(sock->netdev);
return -RT_ENOSYS; /* check the network interface socket opreation */
} SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, recvfrom);
#ifdef SAL_USING_TLS #ifdef SAL_USING_TLS
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, recv)) if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, recv))
...@@ -743,10 +820,10 @@ int sal_recvfrom(int socket, void *mem, size_t len, int flags, ...@@ -743,10 +820,10 @@ int sal_recvfrom(int socket, void *mem, size_t len, int flags,
} }
else 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 #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 #endif
} }
...@@ -754,17 +831,15 @@ int sal_sendto(int socket, const void *dataptr, size_t size, int flags, ...@@ -754,17 +831,15 @@ 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_socket *sock;
struct sal_proto_family *pf;
sock = sal_get_socket(socket); /* get the socket object by socket descriptor */
if (!sock) SAL_SOCKET_OBJ_GET(sock, socket);
{
return -1;
}
if (sock->ops->sendto == RT_NULL) /* check the network interface is commonicable */
{ SAL_NETDEV_IS_COMMONICABLE(sock->netdev);
return -RT_ENOSYS; /* check the network interface socket opreation */
} SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, sendto);
#ifdef SAL_USING_TLS #ifdef SAL_USING_TLS
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, send)) if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, send))
...@@ -779,10 +854,10 @@ int sal_sendto(int socket, const void *dataptr, size_t size, int flags, ...@@ -779,10 +854,10 @@ int sal_sendto(int socket, const void *dataptr, size_t size, int flags,
} }
else 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 #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 #endif
} }
...@@ -791,6 +866,7 @@ int sal_socket(int domain, int type, int protocol) ...@@ -791,6 +866,7 @@ int sal_socket(int domain, int type, int protocol)
int retval; int retval;
int socket, proto_socket; int socket, proto_socket;
struct sal_socket *sock; struct sal_socket *sock;
struct sal_proto_family *pf;
/* allocate a new socket and registered socket options */ /* allocate a new socket and registered socket options */
socket = socket_new(); socket = socket_new();
...@@ -798,8 +874,15 @@ int sal_socket(int domain, int type, int protocol) ...@@ -798,8 +874,15 @@ int sal_socket(int domain, int type, int protocol)
{ {
return -1; return -1;
} }
/* get sal socket object by socket descriptor */
sock = sal_get_socket(socket); sock = sal_get_socket(socket);
if (sock == RT_NULL)
{
return -1;
}
/* Initialize sal socket object */
retval = socket_init(domain, type, protocol, &sock); retval = socket_init(domain, type, protocol, &sock);
if (retval < 0) if (retval < 0)
{ {
...@@ -807,18 +890,16 @@ int sal_socket(int domain, int type, int protocol) ...@@ -807,18 +890,16 @@ int sal_socket(int domain, int type, int protocol)
return -1; return -1;
} }
if (sock->ops->socket == RT_NULL) /* valid the network interface socket opreation */
{ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, socket);
return -RT_ENOSYS;
}
proto_socket = sock->ops->socket(domain, type, protocol); proto_socket = pf->skt_ops->socket(domain, type, protocol);
if (proto_socket >= 0) if (proto_socket >= 0)
{ {
#ifdef SAL_USING_TLS #ifdef SAL_USING_TLS
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, socket)) 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) if (sock->user_data_tls == RT_NULL)
{ {
return -1; return -1;
...@@ -835,19 +916,17 @@ int sal_socket(int domain, int type, int protocol) ...@@ -835,19 +916,17 @@ int sal_socket(int domain, int type, int protocol)
int sal_closesocket(int socket) int sal_closesocket(int socket)
{ {
struct sal_socket *sock; struct sal_socket *sock;
struct sal_proto_family *pf;
int error = 0;
sock = sal_get_socket(socket); /* get the socket object by socket descriptor */
if (!sock) SAL_SOCKET_OBJ_GET(sock, socket);
{
return -1;
}
if (sock->ops->closesocket == RT_NULL) /* clsoesocket operation not nead to vaild network interface status */
{ /* valid the network interface socket opreation */
return -RT_ENOSYS; 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 #ifdef SAL_USING_TLS
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, closesocket)) if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, closesocket))
...@@ -858,67 +937,69 @@ int sal_closesocket(int socket) ...@@ -858,67 +937,69 @@ int sal_closesocket(int socket)
} }
} }
#endif #endif
rt_free(sock); error = 0;
socket_table.sockets[socket] = RT_NULL; }
return 0; else
{
error = -1;
} }
return -1; /* free socket */
rt_free(sock);
socket_table.sockets[socket] = RT_NULL;
return error;
} }
int sal_ioctlsocket(int socket, long cmd, void *arg) int sal_ioctlsocket(int socket, long cmd, void *arg)
{ {
struct sal_socket *sock; struct sal_socket *sock;
struct sal_proto_family *pf;
sock = sal_get_socket(socket); /* get the socket object by socket descriptor */
if (!sock) SAL_SOCKET_OBJ_GET(sock, socket);
{
return -1;
}
if (sock->ops->ioctlsocket == RT_NULL) /* check the network interface socket opreation */
{ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, ioctlsocket);
return -RT_ENOSYS;
}
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 #ifdef SAL_USING_POSIX
int sal_poll(struct dfs_fd *file, struct rt_pollreq *req) int sal_poll(struct dfs_fd *file, struct rt_pollreq *req)
{ {
struct sal_socket *sock; struct sal_socket *sock;
struct sal_proto_family *pf;
int socket = (int) file->data; int socket = (int) file->data;
sock = sal_get_socket(socket); /* get the socket object by socket descriptor */
if (!sock) SAL_SOCKET_OBJ_GET(sock, socket);
{
return -1;
}
if (sock->ops->poll == RT_NULL) /* check the network interface is commonicable */
{ SAL_NETDEV_IS_COMMONICABLE(sock->netdev);
return -RT_ENOSYS; /* 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 #endif
struct hostent *sal_gethostbyname(const char *name) struct hostent *sal_gethostbyname(const char *name)
{ {
int i; struct netdev *netdev = netdev_default;
struct hostent *hst; 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 the link up status */
netdev = netdev_get_first_link_up();
if (SAL_NETDEV_NETDBOPS_VALID(netdev, pf, gethostbyname))
{ {
hst = proto_families[i].ops->gethostbyname(name); return pf->netdb_ops->gethostbyname(name);
if (hst != RT_NULL)
{
return hst;
}
} }
} }
...@@ -928,17 +1009,20 @@ struct hostent *sal_gethostbyname(const char *name) ...@@ -928,17 +1009,20 @@ struct hostent *sal_gethostbyname(const char *name)
int sal_gethostbyname_r(const char *name, struct hostent *ret, char *buf, 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))
{ {
if (proto_families[i].ops && proto_families[i].ops->gethostbyname_r) return pf->netdb_ops->gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
}
else
{
/* get the first network interface device with the link up status */
netdev = netdev_get_first_link_up();
if (SAL_NETDEV_NETDBOPS_VALID(netdev, pf, gethostbyname_r))
{ {
res = proto_families[i].ops->gethostbyname_r(name, ret, buf, buflen, result, h_errnop); return pf->netdb_ops->gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
if (res == 0)
{
return res;
}
} }
} }
...@@ -950,17 +1034,20 @@ int sal_getaddrinfo(const char *nodename, ...@@ -950,17 +1034,20 @@ int sal_getaddrinfo(const char *nodename,
const struct addrinfo *hints, const struct addrinfo *hints,
struct addrinfo **res) 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))
{ {
if (proto_families[i].ops && proto_families[i].ops->getaddrinfo) return pf->netdb_ops->getaddrinfo(nodename, servname, hints, res);
}
else
{
/* get the first network interface device with the link up status */
netdev = netdev_get_first_link_up();
if (SAL_NETDEV_NETDBOPS_VALID(netdev, pf, getaddrinfo))
{ {
ret = proto_families[i].ops->getaddrinfo(nodename, servname, hints, res); return pf->netdb_ops->getaddrinfo(nodename, servname, hints, res);
if (ret == 0)
{
return ret;
}
} }
} }
...@@ -969,14 +1056,21 @@ int sal_getaddrinfo(const char *nodename, ...@@ -969,14 +1056,21 @@ int sal_getaddrinfo(const char *nodename,
void sal_freeaddrinfo(struct addrinfo *ai) 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 the link up status */
netdev = netdev_get_first_link_up();
if (SAL_NETDEV_NETDBOPS_VALID(netdev, pf, freeaddrinfo))
{ {
proto_families[i].ops->freeaddrinfo(ai); pf->netdb_ops->freeaddrinfo(ai);
return;
} }
} }
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册