Merge "Merge net branch into master"
This commit is contained in:
commit
8ec959a041
53 changed files with 3592 additions and 410 deletions
|
@ -46,7 +46,7 @@ endif
|
|||
config BLUETOOTH_MONITOR_ON_DEV_NAME
|
||||
default UART_QMSI_1_NAME if BLUETOOTH_DEBUG_MONITOR
|
||||
|
||||
if IEEE802154_CC2520_LEGACY || IEEE802154_CC2520 || IEEE802154_CC2520_RAW
|
||||
if IEEE802154_CC2520
|
||||
|
||||
config SPI
|
||||
def_bool y
|
||||
|
@ -85,6 +85,6 @@ config IEEE802154_CC2520_GPIO_1_NAME
|
|||
default GPIO_QMSI_1_NAME
|
||||
endif
|
||||
|
||||
endif # IEEE802154_CC2520_LEGACY || IEEE802154_CC2520 || IEEE802154_CC2520_RAW
|
||||
endif # IEEE802154_CC2520
|
||||
|
||||
endif # BOARD_QUARK_SE_C1000_DEVBOARD
|
||||
|
|
|
@ -10,9 +10,7 @@
|
|||
#include <device.h>
|
||||
#include <init.h>
|
||||
|
||||
#if defined(CONFIG_IEEE802154_CC2520_LEGACY) || \
|
||||
defined(CONFIG_IEEE802154_CC2520) || \
|
||||
defined(CONFIG_IEEE802154_CC2520_RAW)
|
||||
#if defined(CONFIG_IEEE802154_CC2520)
|
||||
|
||||
#include <ieee802154/cc2520.h>
|
||||
#include <gpio.h>
|
||||
|
@ -61,6 +59,4 @@ struct cc2520_gpio_configuration *cc2520_configure_gpios(void)
|
|||
return cc2520_gpios;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IEEE802154_CC2520_LEGACY || CONFIG_IEEE802154_CC2520 ||
|
||||
* CONFIG_IEEE802154_CC2520_RAW
|
||||
*/
|
||||
#endif /* CONFIG_IEEE802154_CC2520 */
|
||||
|
|
|
@ -21,9 +21,7 @@
|
|||
#define LED0_GPIO_PORT CONFIG_GPIO_QMSI_0_NAME
|
||||
#define LED0_GPIO_PIN 25
|
||||
|
||||
#if defined(CONFIG_IEEE802154_CC2520_LEGACY) || \
|
||||
defined(CONFIG_IEEE802154_CC2520) || \
|
||||
defined(CONFIG_IEEE802154_CC2520_RAW)
|
||||
#if defined(CONFIG_IEEE802154_CC2520)
|
||||
|
||||
/* GPIO numbers where the TI cc2520 chip is connected to */
|
||||
#define CC2520_GPIO_VREG_EN 0 /* PIN ?, ATP_AON_INT0 (out) */
|
||||
|
@ -33,9 +31,7 @@
|
|||
#define CC2520_GPIO_CCA 6 /* PIN 6, GPIO6 (in) */
|
||||
#define CC2520_GPIO_SFD 29 /* PIN 33, GPIO29 (in) */
|
||||
|
||||
#endif /* CONFIG_IEEE802154_CC2520_LEGACY || CONFIG_IEEE802154_CC2520 ||
|
||||
* CONFIG_IEEE802154_CC2520_RAW
|
||||
*/
|
||||
#endif /* CONFIG_IEEE802154_CC2520 */
|
||||
|
||||
#if defined(CONFIG_USB)
|
||||
/* GPIO driver name */
|
||||
|
|
|
@ -7,17 +7,7 @@ menuconfig IEEE802154_CC2520
|
|||
select NET_L2_IEEE802154
|
||||
default n
|
||||
|
||||
menuconfig IEEE802154_CC2520_RAW
|
||||
bool "TI CC2520 Driver RAW channel"
|
||||
select NET_L2_RAW_CHANNEL
|
||||
default n
|
||||
help
|
||||
Enable IEEE802154_CC2520 driver with RAW channel
|
||||
|
||||
The CC2520 driver with RAW channel allows to export radio interface
|
||||
over USB making an USB 802.15.4 dongle.
|
||||
|
||||
if IEEE802154_CC2520 || IEEE802154_CC2520_RAW
|
||||
if IEEE802154_CC2520
|
||||
|
||||
config IEEE802154_CC2520_DRV_NAME
|
||||
string "TI CC2520 Driver's name"
|
||||
|
@ -99,6 +89,17 @@ config IEEE802154_CC2520_MAC7
|
|||
range 0 ff
|
||||
help
|
||||
This is the byte 7 of the MAC address.
|
||||
endif
|
||||
|
||||
endif
|
||||
endif # ! IEEE802154_CC2520_RANDOM_MAC
|
||||
|
||||
config IEEE802154_CC2520_RAW
|
||||
bool "TI CC2520 Driver RAW channel"
|
||||
select NET_L2_RAW_CHANNEL
|
||||
default n
|
||||
help
|
||||
Enable IEEE802154_CC2520 driver with RAW channel
|
||||
|
||||
The CC2520 driver with RAW channel allows to export radio interface
|
||||
over USB making an USB 802.15.4 dongle.
|
||||
|
||||
endif # IEEE802154_CC2520
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
obj-$(CONFIG_IEEE802154_CC2520) += ieee802154_cc2520.o
|
||||
obj-$(CONFIG_IEEE802154_CC2520_RAW) += ieee802154_cc2520.o
|
||||
obj-$(CONFIG_IEEE802154_UPIPE) += ieee802154_uart_pipe.o
|
||||
obj-$(CONFIG_IEEE802154_MCR20A) += ieee802154_mcr20a.o
|
||||
obj-$(CONFIG_IEEE802154_MCR20A_RAW) += ieee802154_mcr20a.o
|
||||
|
|
307
include/net/dns_resolve.h
Normal file
307
include/net/dns_resolve.h
Normal file
|
@ -0,0 +1,307 @@
|
|||
/** @file
|
||||
* @brief DNS resolving library
|
||||
*
|
||||
* An API for applications to resolve a DNS name.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _DNS_RESOLVE_H
|
||||
#define _DNS_RESOLVE_H
|
||||
|
||||
#if defined(CONFIG_DNS_RESOLVER)
|
||||
|
||||
#include <net/net_ip.h>
|
||||
#include <net/net_context.h>
|
||||
|
||||
/**
|
||||
* DNS query type enum
|
||||
*/
|
||||
enum dns_query_type {
|
||||
DNS_QUERY_TYPE_A = 1, /* IPv4 */
|
||||
DNS_QUERY_TYPE_AAAA = 28 /* IPv6 */
|
||||
};
|
||||
|
||||
#ifndef DNS_MAX_NAME_SIZE
|
||||
#define DNS_MAX_NAME_SIZE 20
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Address info struct is passed to callback that gets all the results.
|
||||
*/
|
||||
struct dns_addrinfo {
|
||||
struct sockaddr ai_addr;
|
||||
char ai_canonname[DNS_MAX_NAME_SIZE + 1];
|
||||
socklen_t ai_addrlen;
|
||||
uint16_t ai_flags;
|
||||
uint8_t ai_family;
|
||||
uint8_t ai_socktype;
|
||||
uint8_t ai_protocol;
|
||||
};
|
||||
|
||||
/**
|
||||
* Status values for the callback.
|
||||
*/
|
||||
enum dns_resolve_status {
|
||||
DNS_EAI_BADFLAGS = -1, /* Invalid value for `ai_flags' field */
|
||||
DNS_EAI_NONAME = -2, /* NAME or SERVICE is unknown */
|
||||
DNS_EAI_AGAIN = -3, /* Temporary failure in name resolution */
|
||||
DNS_EAI_FAIL = -4, /* Non-recoverable failure in name res */
|
||||
DNS_EAI_NODATA = -5, /* No address associated with NAME */
|
||||
DNS_EAI_FAMILY = -6, /* `ai_family' not supported */
|
||||
DNS_EAI_SOCKTYPE = -7, /* `ai_socktype' not supported */
|
||||
DNS_EAI_SERVICE = -8, /* SRV not supported for `ai_socktype' */
|
||||
DNS_EAI_ADDRFAMILY = -9, /* Address family for NAME not supported */
|
||||
DNS_EAI_MEMORY = -10, /* Memory allocation failure */
|
||||
DNS_EAI_SYSTEM = -11, /* System error returned in `errno' */
|
||||
DNS_EAI_OVERFLOW = -12, /* Argument buffer overflow */
|
||||
DNS_EAI_INPROGRESS = -100, /* Processing request in progress */
|
||||
DNS_EAI_CANCELED = -101, /* Request canceled */
|
||||
DNS_EAI_NOTCANCELED = -102, /* Request not canceled */
|
||||
DNS_EAI_ALLDONE = -103, /* All requests done */
|
||||
DNS_EAI_IDN_ENCODE = -105, /* IDN encoding failed */
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef dns_resolve_cb_t
|
||||
* @brief DNS resolve callback
|
||||
*
|
||||
* @details The DNS resolve callback is called after a successful
|
||||
* DNS resolving. The resolver can call this callback multiple times, one
|
||||
* for each resolved address.
|
||||
*
|
||||
* @param status The status of the query:
|
||||
* DNS_EAI_INPROGRESS returned for each resolved address
|
||||
* DNS_EAI_ALLDONE mark end of the resolving, info is set to NULL in
|
||||
* this case
|
||||
* DNS_EAI_CANCELED if the query was canceled manually or timeout happened
|
||||
* DNS_EAI_FAIL if the name cannot be resolved by the server
|
||||
* DNS_EAI_NODATA if there is no such name
|
||||
* other values means that an error happened.
|
||||
* @param info Query results are stored here.
|
||||
* @param user_data The user data given in dns_resolve_name() call.
|
||||
*/
|
||||
typedef void (*dns_resolve_cb_t)(enum dns_resolve_status status,
|
||||
struct dns_addrinfo *info,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* DNS resolve context structure.
|
||||
*/
|
||||
struct dns_resolve_context {
|
||||
struct {
|
||||
/** DNS server information */
|
||||
struct sockaddr dns_server;
|
||||
|
||||
/** Connection to the DNS server */
|
||||
struct net_context *net_ctx;
|
||||
} servers[CONFIG_DNS_RESOLVER_MAX_SERVERS];
|
||||
|
||||
/** This timeout is also used when a buffer is required from the
|
||||
* buffer pools.
|
||||
*/
|
||||
int32_t buf_timeout;
|
||||
|
||||
/** Result callbacks. We have multiple callbacks here so that it is
|
||||
* possible to do multiple queries at the same time.
|
||||
*/
|
||||
struct dns_pending_query {
|
||||
/** Timeout timer */
|
||||
struct k_delayed_work timer;
|
||||
|
||||
/** Back pointer to ctx, needed in timeout handler */
|
||||
struct dns_resolve_context *ctx;
|
||||
|
||||
/** Result callback */
|
||||
dns_resolve_cb_t cb;
|
||||
|
||||
/** User data */
|
||||
void *user_data;
|
||||
|
||||
/** TX timeout */
|
||||
int32_t timeout;
|
||||
|
||||
/** String containing the thing to resolve like www.example.com
|
||||
*/
|
||||
const char *query;
|
||||
|
||||
/** Query type */
|
||||
enum dns_query_type query_type;
|
||||
|
||||
/** DNS id of this query */
|
||||
uint16_t id;
|
||||
} queries[CONFIG_DNS_NUM_CONCUR_QUERIES];
|
||||
|
||||
/** Is this context in use */
|
||||
bool is_used;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Init DNS resolving context.
|
||||
*
|
||||
* @details This function sets the DNS server address and initializes the
|
||||
* DNS context that is used by the actual resolver.
|
||||
* Note that the recommended way to resolve DNS names is to use
|
||||
* the dns_get_addr_info() API. In that case user does not need to
|
||||
* call dns_resolve_init() as the DNS servers are already setup by the system.
|
||||
*
|
||||
* @param ctx DNS context. If the context variable is allocated from
|
||||
* the stack, then the variable needs to be valid for the whole duration of
|
||||
* the resolving. Caller does not need to fill the variable beforehand or
|
||||
* edit the context afterwards.
|
||||
* @param server_array DNS server addresses. The array is null terminated.
|
||||
* The port number can be given in the string.
|
||||
* Syntax for the server addresses with or without port numbers:
|
||||
* IPv4 : 10.0.9.1
|
||||
* IPv4 + port : 10.0.9.1:5353
|
||||
* IPv6 : 2001:db8::22:42
|
||||
* IPv6 + port : [2001:db8::22:42]:5353
|
||||
*
|
||||
* @return 0 if ok, <0 if error.
|
||||
*/
|
||||
int dns_resolve_init(struct dns_resolve_context *ctx,
|
||||
const char *dns_servers[]);
|
||||
|
||||
/**
|
||||
* @brief Close DNS resolving context.
|
||||
*
|
||||
* @details This releases DNS resolving context and marks the context unusable.
|
||||
* Caller must call the dns_resolve_init() again to make context usable.
|
||||
*
|
||||
* @param ctx DNS context
|
||||
*
|
||||
* @return 0 if ok, <0 if error.
|
||||
*/
|
||||
int dns_resolve_close(struct dns_resolve_context *ctx);
|
||||
|
||||
/**
|
||||
* @brief Cancel a pending DNS query.
|
||||
*
|
||||
* @details This releases DNS resources used by a pending query.
|
||||
*
|
||||
* @param ctx DNS context
|
||||
* @param dns_id DNS id of the pending query
|
||||
*
|
||||
* @return 0 if ok, <0 if error.
|
||||
*/
|
||||
int dns_resolve_cancel(struct dns_resolve_context *ctx,
|
||||
uint16_t dns_id);
|
||||
|
||||
/**
|
||||
* @brief Resolve DNS name.
|
||||
*
|
||||
* @details This function can be used to resolve e.g., IPv4 or IPv6 address.
|
||||
* Note that this is asynchronous call, the function will return immediately
|
||||
* and system will call the callback after resolving has finished or timeout
|
||||
* has occurred.
|
||||
* We might send the query to multiple servers (if there are more than one
|
||||
* server configured), but we only use the result of the first received
|
||||
* response.
|
||||
*
|
||||
* @param ctx DNS context
|
||||
* @param query What the caller wants to resolve.
|
||||
* @param type What kind of data the caller wants to get.
|
||||
* @param dns_id DNS id is returned to the caller. This is needed if one
|
||||
* wishes to cancel the query. This can be set to NULL if there is no need
|
||||
* to cancel the query.
|
||||
* @param cb Callback to call after the resolving has finished or timeout
|
||||
* has happened.
|
||||
* @param user_data The user data.
|
||||
* @param timeout The timeout value for the query. Possible values:
|
||||
* K_FOREVER: the query is tried forever, user needs to cancel it manually
|
||||
* if it takes too long time to finish
|
||||
* >0: start the query and let the system timeout it after specified ms
|
||||
*
|
||||
* @return 0 if resolving was started ok, < 0 otherwise
|
||||
*/
|
||||
int dns_resolve_name(struct dns_resolve_context *ctx,
|
||||
const char *query,
|
||||
enum dns_query_type type,
|
||||
uint16_t *dns_id,
|
||||
dns_resolve_cb_t cb,
|
||||
void *user_data,
|
||||
int32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Get default DNS context.
|
||||
*
|
||||
* @detail The system level DNS context uses DNS servers that are
|
||||
* defined in project config file. If no DNS servers are defined by the
|
||||
* user, then resolving DNS names using default DNS context will do nothing.
|
||||
* The configuration options are described in subsys/net/lib/dns/Kconfig file.
|
||||
*
|
||||
* @return Default DNS context.
|
||||
*/
|
||||
struct dns_resolve_context *dns_resolve_get_default(void);
|
||||
|
||||
/**
|
||||
* @brief Get IP address info from DNS.
|
||||
*
|
||||
* @details This function can be used to resolve e.g., IPv4 or IPv6 address.
|
||||
* Note that this is asynchronous call, the function will return immediately
|
||||
* and system will call the callback after resolving has finished or timeout
|
||||
* has occurred.
|
||||
* We might send the query to multiple servers (if there are more than one
|
||||
* server configured), but we only use the result of the first received
|
||||
* response.
|
||||
* This variant uses system wide DNS servers.
|
||||
*
|
||||
* @param query What the caller wants to resolve.
|
||||
* @param type What kind of data the caller wants to get.
|
||||
* @param dns_id DNS id is returned to the caller. This is needed if one
|
||||
* wishes to cancel the query. This can be set to NULL if there is no need
|
||||
* to cancel the query.
|
||||
* @param cb Callback to call after the resolving has finished or timeout
|
||||
* has happened.
|
||||
* @param user_data The user data.
|
||||
* @param timeout The timeout value for the connection. Possible values:
|
||||
* K_FOREVER: the query is tried forever, user needs to cancel it manually
|
||||
* if it takes too long time to finish
|
||||
* >0: start the query and let the system timeout it after specified ms
|
||||
*
|
||||
* @return 0 if resolving was started ok, < 0 otherwise
|
||||
*/
|
||||
static inline int dns_get_addr_info(const char *query,
|
||||
enum dns_query_type type,
|
||||
uint16_t *dns_id,
|
||||
dns_resolve_cb_t cb,
|
||||
void *user_data,
|
||||
int32_t timeout)
|
||||
{
|
||||
return dns_resolve_name(dns_resolve_get_default(),
|
||||
query,
|
||||
type,
|
||||
dns_id,
|
||||
cb,
|
||||
user_data,
|
||||
timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Cancel a pending DNS query.
|
||||
*
|
||||
* @details This releases DNS resources used by a pending query.
|
||||
*
|
||||
* @param dns_id DNS id of the pending query
|
||||
*
|
||||
* @return 0 if ok, <0 if error.
|
||||
*/
|
||||
static inline int dns_cancel_addr_info(uint16_t dns_id)
|
||||
{
|
||||
return dns_resolve_cancel(dns_resolve_get_default(), dns_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize DNS subsystem.
|
||||
*/
|
||||
void dns_init_resolver(void);
|
||||
|
||||
#else
|
||||
#define dns_init_resolver(...)
|
||||
#endif /* CONFIG_DNS_RESOLVER */
|
||||
|
||||
#endif /* _DNS_RESOLVE_H */
|
|
@ -76,6 +76,10 @@ struct net_nbuf {
|
|||
#if defined(CONFIG_NET_TCP)
|
||||
bool buf_sent; /* Is this net_buf sent or not */
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_ROUTE)
|
||||
bool forwarding; /* Are we forwarding this buf */
|
||||
#endif
|
||||
/* @endcond */
|
||||
};
|
||||
|
||||
|
@ -218,6 +222,23 @@ static inline void net_nbuf_set_buf_sent(struct net_buf *buf, bool sent)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_ROUTE)
|
||||
static inline bool net_nbuf_forwarding(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->forwarding;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_forwarding(struct net_buf *buf, bool forward)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->forwarding = forward;
|
||||
}
|
||||
#else
|
||||
static inline bool net_nbuf_forwarding(struct net_buf *buf)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline uint16_t net_nbuf_get_len(struct net_buf *buf)
|
||||
{
|
||||
return buf->len;
|
||||
|
|
|
@ -48,6 +48,8 @@ enum net_event_ipv6_cmd {
|
|||
NET_EVENT_IPV6_CMD_PREFIX_DEL,
|
||||
NET_EVENT_IPV6_CMD_MCAST_JOIN,
|
||||
NET_EVENT_IPV6_CMD_MCAST_LEAVE,
|
||||
NET_EVENT_IPV6_CMD_ROUTER_ADD,
|
||||
NET_EVENT_IPV6_CMD_ROUTER_DEL,
|
||||
};
|
||||
|
||||
#define NET_EVENT_IPV6_ADDR_ADD \
|
||||
|
@ -74,6 +76,12 @@ enum net_event_ipv6_cmd {
|
|||
#define NET_EVENT_IPV6_MCAST_LEAVE \
|
||||
(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_MCAST_LEAVE)
|
||||
|
||||
#define NET_EVENT_IPV6_ROUTER_ADD \
|
||||
(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ROUTER_ADD)
|
||||
|
||||
#define NET_EVENT_IPV6_ROUTER_DEL \
|
||||
(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ROUTER_DEL)
|
||||
|
||||
/* IPv4 Events*/
|
||||
#define _NET_IPV4_LAYER NET_MGMT_LAYER_L3
|
||||
#define _NET_IPV4_CORE_CODE 0x400
|
||||
|
|
|
@ -162,6 +162,11 @@ enum {
|
|||
NET_IF_NUM_FLAGS
|
||||
};
|
||||
|
||||
#if defined(CONFIG_NET_OFFLOAD)
|
||||
struct net_offload;
|
||||
#endif /* CONFIG_NET_OFFLOAD */
|
||||
|
||||
|
||||
/**
|
||||
* @brief Network Interface structure
|
||||
*
|
||||
|
@ -194,11 +199,14 @@ struct net_if {
|
|||
/** The hardware MTU */
|
||||
uint16_t mtu;
|
||||
|
||||
/** Is the IP stack is offloaded. If set, then the IP stack is located
|
||||
* in the communication chip that is accessed via this network
|
||||
* interface.
|
||||
#if defined(CONFIG_NET_OFFLOAD)
|
||||
/** TCP/IP Offload functions.
|
||||
* If non-NULL, then the TCP/IP stack is located
|
||||
* in the communication chip that is accessed via this
|
||||
* network interface.
|
||||
*/
|
||||
bool offload_ip;
|
||||
struct net_offload *offload;
|
||||
#endif /* CONFIG_NET_OFFLOAD */
|
||||
|
||||
/** Queue for outgoing packets from apps */
|
||||
struct k_fifo tx_queue;
|
||||
|
@ -379,6 +387,7 @@ static inline void net_if_queue_tx(struct net_if *iface, struct net_buf *buf)
|
|||
net_buf_put(&iface->tx_queue, buf);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_OFFLOAD)
|
||||
/**
|
||||
* @brief Return the IP offload status.
|
||||
*
|
||||
|
@ -388,8 +397,9 @@ static inline void net_if_queue_tx(struct net_if *iface, struct net_buf *buf)
|
|||
*/
|
||||
static inline bool net_if_is_ip_offloaded(struct net_if *iface)
|
||||
{
|
||||
return iface->offload_ip;
|
||||
return (iface->offload != NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get an network interface's link address
|
||||
|
|
|
@ -20,10 +20,6 @@ extern "C" {
|
|||
|
||||
struct net_if;
|
||||
|
||||
#if defined(CONFIG_NET_L2_OFFLOAD_IP)
|
||||
struct net_l2_offload_ip;
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
|
||||
struct net_l2 {
|
||||
/**
|
||||
* This function is used by net core to get iface's L2 layer parsing
|
||||
|
@ -50,10 +46,6 @@ struct net_l2 {
|
|||
* interface.
|
||||
*/
|
||||
int (*enable)(struct net_if *iface, bool state);
|
||||
|
||||
#if defined(CONFIG_NET_L2_OFFLOAD_IP)
|
||||
struct net_l2_offload_ip *offload_ip;
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
};
|
||||
|
||||
#define NET_L2_GET_NAME(_name) (__net_l2_##_name)
|
||||
|
@ -87,10 +79,10 @@ NET_L2_DECLARE_PUBLIC(IEEE802154_L2);
|
|||
#define BLUETOOTH_L2_CTX_TYPE void*
|
||||
#endif /* CONFIG_NET_L2_BLUETOOTH */
|
||||
|
||||
#ifdef CONFIG_NET_L2_OFFLOAD_IP
|
||||
#ifdef CONFIG_NET_OFFLOAD
|
||||
#define OFFLOAD_IP_L2 OFFLOAD_IP
|
||||
#define OFFLOAD_IP_L2_CTX_TYPE void*
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
#endif /* CONFIG_NET_OFFLOAD */
|
||||
|
||||
extern struct net_l2 __net_l2_end[];
|
||||
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
* @brief Public API for offloading IP stack
|
||||
*/
|
||||
|
||||
#ifndef __OFFLOAD_IP_H__
|
||||
#define __OFFLOAD_IP_H__
|
||||
#ifndef __NET_OFFLOAD_H__
|
||||
#define __NET_OFFLOAD_H__
|
||||
|
||||
#if defined(CONFIG_NET_L2_OFFLOAD_IP)
|
||||
#if defined(CONFIG_NET_OFFLOAD)
|
||||
|
||||
#include <net/buf.h>
|
||||
#include <net/net_ip.h>
|
||||
|
@ -25,7 +25,7 @@ extern "C" {
|
|||
/** For return parameters and return values of the elements in this
|
||||
* struct, see similarly named functions in net_context.h
|
||||
*/
|
||||
struct net_l2_offload_ip {
|
||||
struct net_offload {
|
||||
/**
|
||||
* This function is called when the socket is to be opened.
|
||||
*/
|
||||
|
@ -119,18 +119,17 @@ struct net_l2_offload_ip {
|
|||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_get(struct net_if *iface,
|
||||
static inline int net_offload_get(struct net_if *iface,
|
||||
sa_family_t family,
|
||||
enum net_sock_type type,
|
||||
enum net_ip_protocol ip_proto,
|
||||
struct net_context **context)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->get);
|
||||
NET_ASSERT(iface->offload);
|
||||
NET_ASSERT(iface->offload->get);
|
||||
|
||||
return iface->l2->offload_ip->get(family, type, ip_proto, context);
|
||||
return iface->offload->get(family, type, ip_proto, context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -146,17 +145,16 @@ static inline int net_l2_offload_ip_get(struct net_if *iface,
|
|||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_bind(struct net_if *iface,
|
||||
static inline int net_offload_bind(struct net_if *iface,
|
||||
struct net_context *context,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->bind);
|
||||
NET_ASSERT(iface->offload);
|
||||
NET_ASSERT(iface->offload->bind);
|
||||
|
||||
return iface->l2->offload_ip->bind(context, addr, addrlen);
|
||||
return iface->offload->bind(context, addr, addrlen);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -171,16 +169,15 @@ static inline int net_l2_offload_ip_bind(struct net_if *iface,
|
|||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_listen(struct net_if *iface,
|
||||
static inline int net_offload_listen(struct net_if *iface,
|
||||
struct net_context *context,
|
||||
int backlog)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->listen);
|
||||
NET_ASSERT(iface->offload);
|
||||
NET_ASSERT(iface->offload->listen);
|
||||
|
||||
return iface->l2->offload_ip->listen(context, backlog);
|
||||
return iface->offload->listen(context, backlog);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -212,7 +209,7 @@ static inline int net_l2_offload_ip_listen(struct net_if *iface,
|
|||
* @return -EINVAL if an invalid parameter is passed as an argument.
|
||||
* @return -ENOTSUP if the operation is not supported or implemented.
|
||||
*/
|
||||
static inline int net_l2_offload_ip_connect(struct net_if *iface,
|
||||
static inline int net_offload_connect(struct net_if *iface,
|
||||
struct net_context *context,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen,
|
||||
|
@ -221,11 +218,10 @@ static inline int net_l2_offload_ip_connect(struct net_if *iface,
|
|||
void *user_data)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->connect);
|
||||
NET_ASSERT(iface->offload);
|
||||
NET_ASSERT(iface->offload->connect);
|
||||
|
||||
return iface->l2->offload_ip->connect(context, addr, addrlen, cb,
|
||||
return iface->offload->connect(context, addr, addrlen, cb,
|
||||
timeout, user_data);
|
||||
}
|
||||
|
||||
|
@ -256,18 +252,17 @@ static inline int net_l2_offload_ip_connect(struct net_if *iface,
|
|||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_accept(struct net_if *iface,
|
||||
static inline int net_offload_accept(struct net_if *iface,
|
||||
struct net_context *context,
|
||||
net_tcp_accept_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *user_data)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->accept);
|
||||
NET_ASSERT(iface->offload);
|
||||
NET_ASSERT(iface->offload->accept);
|
||||
|
||||
return iface->l2->offload_ip->accept(context, cb, timeout, user_data);
|
||||
return iface->offload->accept(context, cb, timeout, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -297,7 +292,7 @@ static inline int net_l2_offload_ip_accept(struct net_if *iface,
|
|||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_send(struct net_if *iface,
|
||||
static inline int net_offload_send(struct net_if *iface,
|
||||
struct net_buf *buf,
|
||||
net_context_send_cb_t cb,
|
||||
int32_t timeout,
|
||||
|
@ -305,11 +300,10 @@ static inline int net_l2_offload_ip_send(struct net_if *iface,
|
|||
void *user_data)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->send);
|
||||
NET_ASSERT(iface->offload);
|
||||
NET_ASSERT(iface->offload->send);
|
||||
|
||||
return iface->l2->offload_ip->send(buf, cb, timeout, token, user_data);
|
||||
return iface->offload->send(buf, cb, timeout, token, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -341,7 +335,7 @@ static inline int net_l2_offload_ip_send(struct net_if *iface,
|
|||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_sendto(struct net_if *iface,
|
||||
static inline int net_offload_sendto(struct net_if *iface,
|
||||
struct net_buf *buf,
|
||||
const struct sockaddr *dst_addr,
|
||||
socklen_t addrlen,
|
||||
|
@ -351,11 +345,10 @@ static inline int net_l2_offload_ip_sendto(struct net_if *iface,
|
|||
void *user_data)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->sendto);
|
||||
NET_ASSERT(iface->offload);
|
||||
NET_ASSERT(iface->offload->sendto);
|
||||
|
||||
return iface->l2->offload_ip->sendto(buf, dst_addr, addrlen, cb,
|
||||
return iface->offload->sendto(buf, dst_addr, addrlen, cb,
|
||||
timeout, token, user_data);
|
||||
}
|
||||
|
||||
|
@ -392,18 +385,17 @@ static inline int net_l2_offload_ip_sendto(struct net_if *iface,
|
|||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_recv(struct net_if *iface,
|
||||
static inline int net_offload_recv(struct net_if *iface,
|
||||
struct net_context *context,
|
||||
net_context_recv_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *user_data)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->recv);
|
||||
NET_ASSERT(iface->offload);
|
||||
NET_ASSERT(iface->offload->recv);
|
||||
|
||||
return iface->l2->offload_ip->recv(context, cb, timeout, user_data);
|
||||
return iface->offload->recv(context, cb, timeout, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -419,21 +411,20 @@ static inline int net_l2_offload_ip_recv(struct net_if *iface,
|
|||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_put(struct net_if *iface,
|
||||
static inline int net_offload_put(struct net_if *iface,
|
||||
struct net_context *context)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->put);
|
||||
NET_ASSERT(iface->offload);
|
||||
NET_ASSERT(iface->offload->put);
|
||||
|
||||
return iface->l2->offload_ip->put(context);
|
||||
return iface->offload->put(context);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
#endif /* CONFIG_NET_OFFLOAD */
|
||||
|
||||
#endif /* __OFFLOAD_IP_H__ */
|
||||
#endif /* __NET_OFFLOAD_H__ */
|
13
samples/net/dns_resolve/Makefile
Normal file
13
samples/net/dns_resolve/Makefile
Normal file
|
@ -0,0 +1,13 @@
|
|||
#
|
||||
# Copyright (c) 2016 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
BOARD ?= qemu_x86
|
||||
CONF_FILE ?= prj_$(BOARD).conf
|
||||
|
||||
include $(ZEPHYR_BASE)/Makefile.inc
|
||||
ifeq ($(BOARD), qemu_x86)
|
||||
include $(ZEPHYR_BASE)/samples/net/common/Makefile.ipstack
|
||||
endif
|
59
samples/net/dns_resolve/prj_qemu_x86.conf
Normal file
59
samples/net/dns_resolve/prj_qemu_x86.conf
Normal file
|
@ -0,0 +1,59 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_RANDOM_GENERATOR=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_NET_SLIP_TAP=y
|
||||
CONFIG_INIT_STACKS=y
|
||||
CONFIG_NET_NBUF_RX_COUNT=4
|
||||
CONFIG_NET_NBUF_TX_COUNT=4
|
||||
CONFIG_NET_NBUF_RX_DATA_COUNT=14
|
||||
CONFIG_NET_NBUF_TX_DATA_COUNT=14
|
||||
|
||||
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3
|
||||
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=5
|
||||
|
||||
CONFIG_NET_LOG=y
|
||||
CONFIG_SYS_LOG=y
|
||||
CONFIG_SYS_LOG_NET_LEVEL=4
|
||||
CONFIG_SYS_LOG_SHOW_COLOR=y
|
||||
#CONFIG_NET_DEBUG_NET_BUF=y
|
||||
CONFIG_NET_DEBUG_DNS_RESOLVE=y
|
||||
#CONFIG_NET_DEBUG_CONTEXT=y
|
||||
#CONFIG_NET_DEBUG_CORE=y
|
||||
#CONFIG_NET_DEBUG_IF=y
|
||||
#CONFIG_NET_DEBUG_IPV4=y
|
||||
#CONFIG_NET_DEBUG_IPV6=y
|
||||
#CONFIG_NET_DEBUG_UDP=y
|
||||
#CONFIG_NET_DEBUG_DHCPV4=y
|
||||
#CONFIG_SLIP_DEBUG=y
|
||||
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_IPV6=y
|
||||
|
||||
# Enable the DNS resolver
|
||||
CONFIG_DNS_RESOLVER=y
|
||||
# Enable additional buffers
|
||||
CONFIG_DNS_RESOLVER_ADDITIONAL_BUF_CTR=2
|
||||
# Enable additional queries
|
||||
CONFIG_DNS_RESOLVER_ADDITIONAL_QUERIES=2
|
||||
|
||||
CONFIG_DNS_RESOLVER_MAX_SERVERS=2
|
||||
CONFIG_DNS_SERVER_IP_ADDRESSES=y
|
||||
CONFIG_DNS_NUM_CONCUR_QUERIES=2
|
||||
|
||||
# Google DNS IPv4 and IPv6 servers
|
||||
CONFIG_DNS_SERVER1="8.8.8.8"
|
||||
CONFIG_DNS_SERVER2="2001:4860:4860::8888"
|
||||
|
||||
CONFIG_NET_DHCPV4=y
|
||||
|
||||
CONFIG_NET_MGMT=y
|
||||
CONFIG_NET_MGMT_EVENT=y
|
||||
|
||||
CONFIG_NET_SHELL=y
|
||||
|
||||
CONFIG_NET_SAMPLES_IP_ADDRESSES=y
|
||||
CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::1"
|
||||
CONFIG_NET_SAMPLES_PEER_IPV6_ADDR="2001:db8::2"
|
||||
CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.0.2.1"
|
||||
CONFIG_NET_SAMPLES_PEER_IPV4_ADDR="192.0.2.2"
|
7
samples/net/dns_resolve/src/Makefile
Normal file
7
samples/net/dns_resolve/src/Makefile
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
# Copyright (c) 2016 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
obj-y += main.o
|
284
samples/net/dns_resolve/src/main.c
Normal file
284
samples/net/dns_resolve/src/main.c
Normal file
|
@ -0,0 +1,284 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#if 1
|
||||
#define SYS_LOG_DOMAIN "dns-res"
|
||||
#define NET_SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG
|
||||
#define NET_LOG_ENABLED 1
|
||||
#endif
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <sections.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <net/net_core.h>
|
||||
#include <net/net_if.h>
|
||||
#include <net/net_mgmt.h>
|
||||
#include <net/dns_resolve.h>
|
||||
|
||||
#define STACKSIZE 2000
|
||||
char __noinit __stack thread_stack[STACKSIZE];
|
||||
|
||||
#define DNS_TIMEOUT 2000 /* ms */
|
||||
|
||||
void dns_result_cb(enum dns_resolve_status status,
|
||||
struct dns_addrinfo *info,
|
||||
void *user_data)
|
||||
{
|
||||
char hr_addr[NET_IPV6_ADDR_LEN];
|
||||
char *hr_family;
|
||||
void *addr;
|
||||
|
||||
switch (status) {
|
||||
case DNS_EAI_CANCELED:
|
||||
NET_INFO("DNS query was canceled");
|
||||
return;
|
||||
case DNS_EAI_FAIL:
|
||||
NET_INFO("DNS resolve failed");
|
||||
return;
|
||||
case DNS_EAI_NODATA:
|
||||
NET_INFO("Cannot resolve address");
|
||||
return;
|
||||
case DNS_EAI_ALLDONE:
|
||||
NET_INFO("DNS resolving finished");
|
||||
return;
|
||||
case DNS_EAI_INPROGRESS:
|
||||
break;
|
||||
default:
|
||||
NET_INFO("DNS resolving error (%d)", status);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->ai_family == AF_INET) {
|
||||
hr_family = "IPv4";
|
||||
addr = &net_sin(&info->ai_addr)->sin_addr;
|
||||
} else if (info->ai_family == AF_INET6) {
|
||||
hr_family = "IPv6";
|
||||
addr = &net_sin6(&info->ai_addr)->sin6_addr;
|
||||
} else {
|
||||
NET_ERR("Invalid IP address family %d", info->ai_family);
|
||||
return;
|
||||
}
|
||||
|
||||
NET_INFO("%s address: %s", hr_family,
|
||||
net_addr_ntop(info->ai_family, addr,
|
||||
hr_addr, sizeof(hr_addr)));
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_DHCPV4)
|
||||
static struct net_mgmt_event_callback mgmt4_cb;
|
||||
static struct k_delayed_work ipv4_timer;
|
||||
|
||||
static void do_ipv4_lookup(struct k_work *work)
|
||||
{
|
||||
uint16_t dns_id;
|
||||
int ret;
|
||||
|
||||
ret = dns_get_addr_info("www.zephyrproject.org",
|
||||
DNS_QUERY_TYPE_A,
|
||||
&dns_id,
|
||||
dns_result_cb,
|
||||
NULL,
|
||||
DNS_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot resolve IPv4 address (%d)", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
NET_DBG("DNS id %u", dns_id);
|
||||
}
|
||||
|
||||
static void ipv4_addr_add_handler(struct net_mgmt_event_callback *cb,
|
||||
uint32_t mgmt_event,
|
||||
struct net_if *iface)
|
||||
{
|
||||
char hr_addr[NET_IPV4_ADDR_LEN];
|
||||
int i;
|
||||
|
||||
if (mgmt_event != NET_EVENT_IPV4_ADDR_ADD) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
|
||||
struct net_if_addr *if_addr = &iface->ipv4.unicast[i];
|
||||
|
||||
if (if_addr->addr_type != NET_ADDR_DHCP || !if_addr->is_used) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NET_INFO("IPv4 address: %s",
|
||||
net_addr_ntop(AF_INET, &if_addr->address.in_addr,
|
||||
hr_addr, NET_IPV4_ADDR_LEN));
|
||||
NET_INFO("Lease time: %u seconds", iface->dhcpv4.lease_time);
|
||||
NET_INFO("Subnet: %s",
|
||||
net_addr_ntop(AF_INET, &iface->ipv4.netmask,
|
||||
hr_addr, NET_IPV4_ADDR_LEN));
|
||||
NET_INFO("Router: %s",
|
||||
net_addr_ntop(AF_INET, &iface->ipv4.gw,
|
||||
hr_addr, NET_IPV4_ADDR_LEN));
|
||||
break;
|
||||
}
|
||||
|
||||
/* We cannot run DNS lookup directly from this thread as the
|
||||
* management event thread stack is very small by default.
|
||||
* So run it from work queue instead.
|
||||
*/
|
||||
k_delayed_work_init(&ipv4_timer, do_ipv4_lookup);
|
||||
k_delayed_work_submit(&ipv4_timer, 0);
|
||||
}
|
||||
|
||||
static void setup_dhcpv4(struct net_if *iface)
|
||||
{
|
||||
NET_INFO("Running dhcpv4 client...");
|
||||
|
||||
net_mgmt_init_event_callback(&mgmt4_cb, ipv4_addr_add_handler,
|
||||
NET_EVENT_IPV4_ADDR_ADD);
|
||||
net_mgmt_add_event_callback(&mgmt4_cb);
|
||||
|
||||
net_dhcpv4_start(iface);
|
||||
}
|
||||
|
||||
#else
|
||||
#define setup_dhcpv4(...)
|
||||
#endif /* CONFIG_NET_DHCPV4 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_DHCPV4)
|
||||
|
||||
#if !defined(CONFIG_NET_SAMPLES_MY_IPV4_ADDR)
|
||||
#error "You need to define an IPv4 address or enable DHCPv4!"
|
||||
#endif
|
||||
|
||||
static void setup_ipv4(struct net_if *iface)
|
||||
{
|
||||
char hr_addr[NET_IPV4_ADDR_LEN];
|
||||
struct in_addr addr;
|
||||
uint16_t dns_id;
|
||||
int ret;
|
||||
|
||||
if (net_addr_pton(AF_INET, CONFIG_NET_SAMPLES_MY_IPV4_ADDR, &addr)) {
|
||||
NET_ERR("Invalid address: %s", CONFIG_NET_SAMPLES_MY_IPV4_ADDR);
|
||||
return;
|
||||
}
|
||||
|
||||
net_if_ipv4_addr_add(iface, &addr, NET_ADDR_MANUAL, 0);
|
||||
|
||||
NET_INFO("IPv4 address: %s",
|
||||
net_addr_ntop(AF_INET, &addr, hr_addr, NET_IPV4_ADDR_LEN));
|
||||
|
||||
ret = dns_get_addr_info("www.zephyrproject.org",
|
||||
DNS_QUERY_TYPE_A,
|
||||
&dns_id,
|
||||
dns_result_cb,
|
||||
NULL,
|
||||
DNS_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot resolve IPv4 address (%d)", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
NET_DBG("DNS id %u", dns_id);
|
||||
}
|
||||
|
||||
#else
|
||||
#define setup_ipv4(...)
|
||||
#endif /* CONFIG_NET_IPV4 && !CONFIG_NET_DHCPV4 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
|
||||
#if !defined(CONFIG_NET_SAMPLES_MY_IPV6_ADDR)
|
||||
#error "You need to define an IPv6 address!"
|
||||
#endif
|
||||
|
||||
static struct net_mgmt_event_callback mgmt6_cb;
|
||||
static struct k_delayed_work ipv6_timer;
|
||||
|
||||
static void do_ipv6_lookup(struct k_work *work)
|
||||
{
|
||||
uint16_t dns_id;
|
||||
int ret;
|
||||
|
||||
ret = dns_get_addr_info("www.zephyrproject.org",
|
||||
DNS_QUERY_TYPE_AAAA,
|
||||
&dns_id,
|
||||
dns_result_cb,
|
||||
NULL,
|
||||
DNS_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot resolve IPv6 address (%d)", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
NET_DBG("DNS id %u", dns_id);
|
||||
}
|
||||
|
||||
/* DNS query will most probably fail if we do not have a default
|
||||
* router configured because typically the DNS server is outside of local
|
||||
* network. So wait for that before continuing.
|
||||
*/
|
||||
static void ipv6_router_add_handler(struct net_mgmt_event_callback *cb,
|
||||
uint32_t mgmt_event,
|
||||
struct net_if *iface)
|
||||
{
|
||||
if (mgmt_event != NET_EVENT_IPV6_ROUTER_ADD) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* We cannot run DNS lookup directly from this thread as the
|
||||
* management event thread stack is very small by default.
|
||||
* So run it from work queue instead.
|
||||
*/
|
||||
k_delayed_work_init(&ipv6_timer, do_ipv6_lookup);
|
||||
k_delayed_work_submit(&ipv6_timer, 0);
|
||||
}
|
||||
|
||||
static void setup_ipv6(struct net_if *iface)
|
||||
{
|
||||
char hr_addr[NET_IPV6_ADDR_LEN];
|
||||
struct in6_addr addr;
|
||||
|
||||
if (net_addr_pton(AF_INET6, CONFIG_NET_SAMPLES_MY_IPV6_ADDR, &addr)) {
|
||||
NET_ERR("Invalid address: %s", CONFIG_NET_SAMPLES_MY_IPV6_ADDR);
|
||||
return;
|
||||
}
|
||||
|
||||
net_mgmt_init_event_callback(&mgmt6_cb, ipv6_router_add_handler,
|
||||
NET_EVENT_IPV6_ROUTER_ADD);
|
||||
net_mgmt_add_event_callback(&mgmt6_cb);
|
||||
|
||||
net_if_ipv6_addr_add(iface, &addr, NET_ADDR_MANUAL, 0);
|
||||
|
||||
NET_INFO("IPv6 address: %s",
|
||||
net_addr_ntop(AF_INET6, &addr, hr_addr, NET_IPV6_ADDR_LEN));
|
||||
}
|
||||
|
||||
#else
|
||||
#define setup_ipv6(...)
|
||||
#endif /* CONFIG_NET_IPV6 */
|
||||
|
||||
static void network_setup(void)
|
||||
{
|
||||
struct net_if *iface = net_if_get_default();
|
||||
|
||||
setup_ipv4(iface);
|
||||
|
||||
setup_dhcpv4(iface);
|
||||
|
||||
setup_ipv6(iface);
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
NET_INFO("Starting DNS resolve sample");
|
||||
|
||||
k_thread_spawn(&thread_stack[0], STACKSIZE,
|
||||
(k_thread_entry_t)network_setup,
|
||||
NULL, NULL, NULL, K_PRIO_COOP(7), 0, 0);
|
||||
}
|
4
samples/net/dns_resolve/testcase.ini
Normal file
4
samples/net/dns_resolve/testcase.ini
Normal file
|
@ -0,0 +1,4 @@
|
|||
[test]
|
||||
tags = net dns
|
||||
build_only = true
|
||||
platform_whitelist = qemu_x86
|
|
@ -26,3 +26,7 @@ CONFIG_ETH_ENC28J60_0_MAC5=0x32
|
|||
|
||||
# Arduino 101
|
||||
CONFIG_SPI=y
|
||||
|
||||
CONFIG_NET_SAMPLES_IP_ADDRESSES=y
|
||||
CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.0.2.2"
|
||||
CONFIG_NET_SAMPLES_PEER_IPV4_ADDR="192.0.2.1"
|
||||
|
|
32
samples/net/echo_client/prj_frdm_k64f.conf
Normal file
32
samples/net/echo_client/prj_frdm_k64f.conf
Normal file
|
@ -0,0 +1,32 @@
|
|||
# For Freedom board with ethernet support
|
||||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_LOG=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_DHCPV4=n
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_TCP=y
|
||||
CONFIG_NET_STATISTICS=y
|
||||
|
||||
CONFIG_NET_NBUF_RX_COUNT=14
|
||||
CONFIG_NET_NBUF_TX_COUNT=14
|
||||
CONFIG_NET_NBUF_RX_DATA_COUNT=30
|
||||
CONFIG_NET_NBUF_TX_DATA_COUNT=30
|
||||
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=5
|
||||
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=5
|
||||
CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=1
|
||||
CONFIG_NET_MAX_CONTEXTS=10
|
||||
|
||||
CONFIG_INIT_STACKS=y
|
||||
CONFIG_SYS_LOG_SHOW_COLOR=y
|
||||
CONFIG_PRINTK=y
|
||||
|
||||
CONFIG_NET_L2_ETHERNET=y
|
||||
|
||||
CONFIG_NET_SHELL=y
|
||||
|
||||
CONFIG_NET_SAMPLES_IP_ADDRESSES=y
|
||||
CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::1"
|
||||
CONFIG_NET_SAMPLES_PEER_IPV6_ADDR="2001:db8::2"
|
||||
CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.0.2.1"
|
||||
CONFIG_NET_SAMPLES_PEER_IPV4_ADDR="192.0.2.2"
|
36
samples/net/echo_client/prj_sam_e70_xplained.conf
Normal file
36
samples/net/echo_client/prj_sam_e70_xplained.conf
Normal file
|
@ -0,0 +1,36 @@
|
|||
# For Atmel SMART SAM E70 Xplained board
|
||||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_LOG=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_DHCPV4=n
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_TCP=y
|
||||
CONFIG_NET_STATISTICS=n
|
||||
|
||||
CONFIG_NET_NBUF_RX_COUNT=14
|
||||
CONFIG_NET_NBUF_TX_COUNT=14
|
||||
CONFIG_NET_NBUF_RX_DATA_COUNT=36
|
||||
CONFIG_NET_NBUF_TX_DATA_COUNT=36
|
||||
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=2
|
||||
CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=1
|
||||
CONFIG_NET_MAX_CONTEXTS=10
|
||||
CONFIG_NET_L2_ETHERNET=y
|
||||
|
||||
CONFIG_INIT_STACKS=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_SYS_LOG_SHOW_COLOR=y
|
||||
CONFIG_PRINTK=y
|
||||
|
||||
CONFIG_ETH_INIT_PRIORITY=95
|
||||
CONFIG_ETH_SAM_GMAC=y
|
||||
CONFIG_ETH_SAM_GMAC_MAC0=10
|
||||
CONFIG_ETH_SAM_GMAC_MAC1=22
|
||||
CONFIG_ETH_SAM_GMAC_MAC2=33
|
||||
CONFIG_ETH_SAM_GMAC_MAC3=44
|
||||
CONFIG_ETH_SAM_GMAC_MAC4=55
|
||||
CONFIG_ETH_SAM_GMAC_MAC5=66
|
||||
|
||||
CONFIG_NET_SAMPLES_IP_ADDRESSES=y
|
||||
CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::1"
|
||||
CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.0.2.1"
|
|
@ -130,10 +130,6 @@ static bool send_tcp_data(struct net_context *ctx,
|
|||
#endif /* CONFIG_NET_TCP */
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
/* admin-local, dynamically allocated multicast address */
|
||||
#define MCAST_IP6ADDR { { { 0xff, 0x84, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0x2 } } }
|
||||
|
||||
/* Define the peer IP address where to send messages */
|
||||
#define PEER_IP6ADDR { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0x2 } } }
|
||||
|
@ -148,8 +144,6 @@ static struct in6_addr in6addr_my = MY_IP6ADDR;
|
|||
static struct in6_addr in6addr_peer = PEER_IP6ADDR;
|
||||
#endif
|
||||
|
||||
static struct in6_addr in6addr_mcast = MCAST_IP6ADDR;
|
||||
|
||||
static struct sockaddr_in6 my_addr6 = {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_port = htons(MY_PORT),
|
||||
|
@ -160,11 +154,6 @@ static struct sockaddr_in6 peer_addr6 = {
|
|||
.sin6_port = htons(PEER_PORT),
|
||||
};
|
||||
|
||||
static struct sockaddr_in6 mcast_addr6 = {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_port = htons(PEER_PORT),
|
||||
};
|
||||
|
||||
#if defined(CONFIG_NET_UDP)
|
||||
static char __noinit __stack ipv6_udp_stack[STACKSIZE];
|
||||
#endif
|
||||
|
@ -176,9 +165,6 @@ static char __noinit __stack ipv6_tcp_stack[STACKSIZE];
|
|||
#endif /* CONFIG_NET_IPV6 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
/* Organization-local 239.192.0.0/14 */
|
||||
#define MCAST_IP4ADDR { { { 239, 192, 0, 2 } } }
|
||||
|
||||
#define MY_IP4ADDR { { { 192, 0, 2, 1 } } }
|
||||
#define PEER_IP4ADDR { { { 192, 0, 2, 2 } } }
|
||||
|
||||
|
@ -248,9 +234,6 @@ static inline void init_app(void)
|
|||
NET_ADDR_MANUAL, 0);
|
||||
} while (0);
|
||||
|
||||
net_ipaddr_copy(&mcast_addr6.sin6_addr, &in6addr_mcast);
|
||||
net_if_ipv6_maddr_add(net_if_get_default(), &in6addr_mcast);
|
||||
|
||||
#if defined(CONFIG_NET_UDP)
|
||||
k_sem_init(&conf.recv_ipv6, 0, UINT_MAX);
|
||||
#endif
|
||||
|
@ -295,8 +278,7 @@ static inline void init_app(void)
|
|||
static inline bool get_context(struct net_context **udp_recv4,
|
||||
struct net_context **udp_recv6,
|
||||
struct net_context **tcp_recv4,
|
||||
struct net_context **tcp_recv6,
|
||||
struct net_context **mcast_recv6)
|
||||
struct net_context **tcp_recv6)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -317,22 +299,6 @@ static inline bool get_context(struct net_context **udp_recv4,
|
|||
ntohs(my_addr6.sin6_port), ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, mcast_recv6);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get receiving IPv6 mcast "
|
||||
"network context (%d)", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
net_context_setup_pools(*mcast_recv6, tx_udp_pool, data_udp_pool);
|
||||
|
||||
ret = net_context_bind(*mcast_recv6, (struct sockaddr *)&mcast_addr6,
|
||||
sizeof(struct sockaddr_in6));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv6 mcast (%d)", ret);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_UDP)
|
||||
|
@ -889,13 +855,11 @@ static void event_iface_up(struct net_mgmt_event_callback *cb,
|
|||
struct net_context *udp_send6 = { 0 };
|
||||
struct net_context *tcp_send4 = { 0 };
|
||||
struct net_context *tcp_send6 = { 0 };
|
||||
struct net_context *mcast_send6 = { 0 };
|
||||
|
||||
ipsum_len = strlen(lorem_ipsum);
|
||||
|
||||
if (!get_context(&udp_send4, &udp_send6,
|
||||
&tcp_send4, &tcp_send6,
|
||||
&mcast_send6)) {
|
||||
&tcp_send4, &tcp_send6)) {
|
||||
NET_ERR("Cannot get network contexts");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -26,3 +26,7 @@ CONFIG_ETH_ENC28J60_0_MAC5=0x36
|
|||
|
||||
# Arduino 101
|
||||
CONFIG_SPI=y
|
||||
|
||||
CONFIG_NET_SAMPLES_IP_ADDRESSES=y
|
||||
CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.0.2.1"
|
||||
CONFIG_NET_SAMPLES_PEER_IPV4_ADDR="192.0.2.2"
|
||||
|
|
|
@ -30,12 +30,6 @@
|
|||
#define NET_BIND_ANY_ADDR 1
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
/* admin-local, dynamically allocated multicast address */
|
||||
#define MCAST_IP6ADDR { { { 0xff, 0x84, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0x2 } } }
|
||||
|
||||
struct in6_addr in6addr_mcast = MCAST_IP6ADDR;
|
||||
|
||||
/* Define my IP address where to expect messages */
|
||||
#define MY_IP6ADDR { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0x1 } } }
|
||||
|
@ -45,9 +39,6 @@ static struct in6_addr in6addr_my = MY_IP6ADDR;
|
|||
#endif /* IPv6 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
/* Organization-local 239.192.0.0/14 */
|
||||
#define MCAST_IP4ADDR { { { 239, 192, 0, 2 } } }
|
||||
|
||||
/* The 192.0.2.0/24 is the private address space for documentation RFC 5737 */
|
||||
#define MY_IP4ADDR { { { 192, 0, 2, 1 } } }
|
||||
|
||||
|
@ -127,8 +118,6 @@ static inline void init_app(void)
|
|||
ifaddr = net_if_ipv6_addr_add(net_if_get_default(),
|
||||
&in6addr_my, NET_ADDR_MANUAL, 0);
|
||||
} while (0);
|
||||
|
||||
net_if_ipv6_maddr_add(net_if_get_default(), &in6addr_mcast);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
|
@ -153,13 +142,11 @@ static inline void init_app(void)
|
|||
static inline bool get_context(struct net_context **udp_recv4,
|
||||
struct net_context **udp_recv6,
|
||||
struct net_context **tcp_recv4,
|
||||
struct net_context **tcp_recv6,
|
||||
struct net_context **mcast_recv6)
|
||||
struct net_context **tcp_recv6)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
struct sockaddr_in6 mcast_addr6 = { 0 };
|
||||
struct sockaddr_in6 my_addr6 = { 0 };
|
||||
#endif
|
||||
|
||||
|
@ -168,9 +155,6 @@ static inline bool get_context(struct net_context **udp_recv4,
|
|||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
net_ipaddr_copy(&mcast_addr6.sin6_addr, &in6addr_mcast);
|
||||
mcast_addr6.sin6_family = AF_INET6;
|
||||
|
||||
#if !NET_BIND_ANY_ADDR
|
||||
net_ipaddr_copy(&my_addr6.sin6_addr, &in6addr_my);
|
||||
#endif
|
||||
|
@ -205,20 +189,6 @@ static inline bool get_context(struct net_context **udp_recv4,
|
|||
ntohs(my_addr6.sin6_port), ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, mcast_recv6);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get receiving IPv6 mcast "
|
||||
"network context (%d)", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = net_context_bind(*mcast_recv6, (struct sockaddr *)&mcast_addr6,
|
||||
sizeof(struct sockaddr_in6));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv6 mcast (%d)", ret);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_UDP)
|
||||
|
@ -549,11 +519,9 @@ void receive(void)
|
|||
struct net_context *udp_recv6 = { 0 };
|
||||
struct net_context *tcp_recv4 = { 0 };
|
||||
struct net_context *tcp_recv6 = { 0 };
|
||||
struct net_context *mcast_recv6 = { 0 };
|
||||
|
||||
if (!get_context(&udp_recv4, &udp_recv6,
|
||||
&tcp_recv4, &tcp_recv6,
|
||||
&mcast_recv6)) {
|
||||
&tcp_recv4, &tcp_recv6)) {
|
||||
NET_ERR("Cannot get network contexts");
|
||||
return;
|
||||
}
|
||||
|
@ -574,7 +542,6 @@ void receive(void)
|
|||
|
||||
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_UDP)
|
||||
net_context_put(udp_recv6);
|
||||
net_context_put(mcast_recv6);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_UDP)
|
||||
|
|
|
@ -10,6 +10,7 @@ CONFIG_SERIAL=y
|
|||
CONFIG_UART_INTERRUPT_DRIVEN=y
|
||||
CONFIG_UART_LINE_CTRL=y
|
||||
|
||||
CONFIG_IEEE802154_CC2520=y
|
||||
CONFIG_IEEE802154_CC2520_RAW=y
|
||||
CONFIG_NET_BUF=y
|
||||
CONFIG_NETWORKING=y
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include <net/buf.h>
|
||||
|
||||
#define SYS_LOG_DOMAIN "main"
|
||||
#define SYS_LOG_DOMAIN "wpan_serial"
|
||||
#include <logging/sys_log.h>
|
||||
|
||||
#include <net_private.h>
|
||||
|
|
|
@ -15,7 +15,7 @@ CONFIG_NET_NBUF_DATA_SIZE=128
|
|||
|
||||
CONFIG_NET_L2_IEEE802154=y
|
||||
|
||||
#CONFIG_IEEE802154_CC2520=y
|
||||
CONFIG_IEEE802154_CC2520=y
|
||||
CONFIG_IEEE802154_CC2520_RAW=y
|
||||
|
||||
CONFIG_SYS_LOG=y
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
ccflags-y += -I${ZEPHYR_BASE}/usb/include -I${ZEPHYR_BASE}/include/drivers/usb -I${ZEPHYR_BASE}/include/usb/
|
||||
|
||||
ccflags-$(CONFIG_IEEE802154_CC2520_LEGACY) += -I${ZEPHYR_BASE}/net/ip/contiki/os
|
||||
ccflags-$(CONFIG_IEEE802154_CC2520_LEGACY) += -I${ZEPHYR_BASE}/net/ip/contiki
|
||||
ccflags-$(CONFIG_IEEE802154_CC2520_LEGACY) += -I${ZEPHYR_BASE}/net/ip
|
||||
|
||||
ccflags-$(CONFIG_IEEE802154_CC2520_RAW) += -I${ZEPHYR_BASE}/subsys/net/ip
|
||||
|
||||
obj-y += wpanusb.o
|
||||
|
|
|
@ -387,7 +387,7 @@ static int wpanusb_vendor_handler(struct usb_setup_packet *setup,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
buf = net_nbuf_get_frag(buf, K_NO_WAIT);
|
||||
buf = net_nbuf_get_frag(pkt, K_NO_WAIT);
|
||||
if (!buf) {
|
||||
net_nbuf_unref(pkt);
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -53,11 +53,13 @@ config NET_MAX_ROUTERS
|
|||
help
|
||||
The value depends on your network needs.
|
||||
|
||||
# Normally the route support is enabled by RPL or similar technology
|
||||
# that needs to use the routing infrastructure.
|
||||
config NET_ROUTE
|
||||
bool
|
||||
depends on NET_IPV6
|
||||
depends on NET_IPV6_NBR_CACHE
|
||||
default n
|
||||
default y if NET_IPV6
|
||||
default y if NET_IPV6_NBR_CACHE
|
||||
|
||||
config NET_MAX_ROUTES
|
||||
int "Max number of routing entries stored."
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
menuconfig NET_RPL
|
||||
bool "Enable RPL (Ripple) support"
|
||||
default n
|
||||
select NET_IPV6_ND
|
||||
select NET_IPV6
|
||||
select NET_IPV6_NBR_CACHE
|
||||
select NET_ROUTE
|
||||
help
|
||||
See RFC 6550 and RFC 6551 for details. Enable this if required by
|
||||
|
@ -177,6 +178,14 @@ config NET_RPL_DAO_TIMER
|
|||
help
|
||||
How many seconds to wait before sending DAO.
|
||||
|
||||
config NET_RPL_DAO_ACK
|
||||
bool "Node expecting DAO ACK"
|
||||
depends on NET_RPL
|
||||
default n
|
||||
help
|
||||
Node expecting DAO ACK for DAO message. Enable if interested
|
||||
in status of DAO message.
|
||||
|
||||
config NET_RPL_PREFERENCE
|
||||
int "DAG preference field default value"
|
||||
depends on NET_RPL
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
#define BUF_WAIT_TIME K_SECONDS(1)
|
||||
|
||||
static sys_slist_t handlers;
|
||||
|
||||
static inline enum net_verdict handle_echo_request(struct net_buf *buf)
|
||||
{
|
||||
/* Note that we send the same data buffers back and just swap
|
||||
|
@ -161,24 +163,6 @@ int net_icmpv4_send_echo_request(struct net_if *iface,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
enum net_verdict net_icmpv4_input(struct net_buf *buf, uint16_t len,
|
||||
uint8_t type, uint8_t code)
|
||||
{
|
||||
ARG_UNUSED(code);
|
||||
ARG_UNUSED(len);
|
||||
|
||||
net_stats_update_icmp_recv();
|
||||
|
||||
switch (type) {
|
||||
case NET_ICMPV4_ECHO_REQUEST:
|
||||
return handle_echo_request(buf);
|
||||
}
|
||||
|
||||
net_stats_update_icmp_drop();
|
||||
|
||||
return NET_DROP;
|
||||
}
|
||||
|
||||
int net_icmpv4_send_error(struct net_buf *orig, uint8_t type, uint8_t code)
|
||||
{
|
||||
struct net_buf *buf, *frag;
|
||||
|
@ -283,3 +267,42 @@ drop_no_buf:
|
|||
|
||||
return err;
|
||||
}
|
||||
|
||||
void net_icmpv4_register_handler(struct net_icmpv4_handler *handler)
|
||||
{
|
||||
sys_slist_prepend(&handlers, &handler->node);
|
||||
}
|
||||
|
||||
void net_icmpv4_unregister_handler(struct net_icmpv4_handler *handler)
|
||||
{
|
||||
sys_slist_find_and_remove(&handlers, &handler->node);
|
||||
}
|
||||
|
||||
enum net_verdict net_icmpv4_input(struct net_buf *buf,
|
||||
uint8_t type, uint8_t code)
|
||||
{
|
||||
struct net_icmpv4_handler *cb;
|
||||
|
||||
net_stats_update_icmp_recv();
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER(&handlers, cb, node) {
|
||||
if (cb->type == type && (cb->code == code || cb->code == 0)) {
|
||||
return cb->handler(buf);
|
||||
}
|
||||
}
|
||||
|
||||
net_stats_update_icmp_drop();
|
||||
|
||||
return NET_DROP;
|
||||
}
|
||||
|
||||
static struct net_icmpv4_handler echo_request_handler = {
|
||||
.type = NET_ICMPV4_ECHO_REQUEST,
|
||||
.code = 0,
|
||||
.handler = handle_echo_request,
|
||||
};
|
||||
|
||||
void net_icmpv4_init(void)
|
||||
{
|
||||
net_icmpv4_register_handler(&echo_request_handler);
|
||||
}
|
||||
|
|
|
@ -34,6 +34,15 @@ struct net_icmpv4_echo_req {
|
|||
((struct net_icmpv4_echo_req *)(net_nbuf_icmp_data(buf) + \
|
||||
sizeof(struct net_icmp_hdr)))
|
||||
|
||||
typedef enum net_verdict (*icmpv4_callback_handler_t)(struct net_buf *buf);
|
||||
|
||||
struct net_icmpv4_handler {
|
||||
sys_snode_t node;
|
||||
uint8_t type;
|
||||
uint8_t code;
|
||||
icmpv4_callback_handler_t handler;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Send ICMPv4 error message.
|
||||
* @param buf Network buffer that this error is related to.
|
||||
|
@ -60,7 +69,17 @@ int net_icmpv4_send_echo_request(struct net_if *iface,
|
|||
uint16_t identifier,
|
||||
uint16_t sequence);
|
||||
|
||||
enum net_verdict net_icmpv4_input(struct net_buf *buf, uint16_t len,
|
||||
void net_icmpv4_register_handler(struct net_icmpv4_handler *handler);
|
||||
|
||||
void net_icmpv4_unregister_handler(struct net_icmpv4_handler *handler);
|
||||
|
||||
enum net_verdict net_icmpv4_input(struct net_buf *buf,
|
||||
uint8_t type, uint8_t code);
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
void net_icmpv4_init(void);
|
||||
#else
|
||||
#define net_icmpv4_init(...)
|
||||
#endif
|
||||
|
||||
#endif /* __ICMPV4_H */
|
||||
|
|
|
@ -58,33 +58,34 @@ NET_NBR_TABLE_INIT(NET_NBR_GLOBAL,
|
|||
net_neighbor_pool,
|
||||
net_neighbor_table_clear);
|
||||
|
||||
const char *net_nbr_state2str(enum net_nbr_state state)
|
||||
const char *net_ipv6_nbr_state2str(enum net_ipv6_nbr_state state)
|
||||
{
|
||||
switch (state) {
|
||||
case NET_NBR_INCOMPLETE:
|
||||
case NET_IPV6_NBR_STATE_INCOMPLETE:
|
||||
return "incomplete";
|
||||
case NET_NBR_REACHABLE:
|
||||
case NET_IPV6_NBR_STATE_REACHABLE:
|
||||
return "reachable";
|
||||
case NET_NBR_STALE:
|
||||
case NET_IPV6_NBR_STATE_STALE:
|
||||
return "stale";
|
||||
case NET_NBR_DELAY:
|
||||
case NET_IPV6_NBR_STATE_DELAY:
|
||||
return "delay";
|
||||
case NET_NBR_PROBE:
|
||||
case NET_IPV6_NBR_STATE_PROBE:
|
||||
return "probe";
|
||||
}
|
||||
|
||||
return "<invalid state>";
|
||||
}
|
||||
|
||||
static void nbr_set_state(struct net_nbr *nbr, enum net_nbr_state new_state)
|
||||
static void ipv6_nbr_set_state(struct net_nbr *nbr,
|
||||
enum net_ipv6_nbr_state new_state)
|
||||
{
|
||||
if (new_state == net_ipv6_nbr_data(nbr)->state) {
|
||||
return;
|
||||
}
|
||||
|
||||
NET_DBG("nbr %p %s -> %s", nbr,
|
||||
net_nbr_state2str(net_ipv6_nbr_data(nbr)->state),
|
||||
net_nbr_state2str(new_state));
|
||||
net_ipv6_nbr_state2str(net_ipv6_nbr_data(nbr)->state),
|
||||
net_ipv6_nbr_state2str(new_state));
|
||||
|
||||
net_ipv6_nbr_data(nbr)->state = new_state;
|
||||
}
|
||||
|
@ -245,7 +246,7 @@ struct net_nbr *net_ipv6_nbr_add(struct net_if *iface,
|
|||
struct in6_addr *addr,
|
||||
struct net_linkaddr *lladdr,
|
||||
bool is_router,
|
||||
enum net_nbr_state state)
|
||||
enum net_ipv6_nbr_state state)
|
||||
{
|
||||
struct net_nbr *nbr = net_nbr_get(&net_neighbor.table);
|
||||
|
||||
|
@ -259,7 +260,7 @@ struct net_nbr *net_ipv6_nbr_add(struct net_if *iface,
|
|||
}
|
||||
|
||||
net_ipaddr_copy(&net_ipv6_nbr_data(nbr)->addr, addr);
|
||||
nbr_set_state(nbr, state);
|
||||
ipv6_nbr_set_state(nbr, state);
|
||||
net_ipv6_nbr_data(nbr)->is_router = is_router;
|
||||
|
||||
NET_DBG("[%d] nbr %p state %d router %d IPv6 %s ll %s",
|
||||
|
@ -274,7 +275,7 @@ static inline struct net_nbr *nbr_add(struct net_buf *buf,
|
|||
struct in6_addr *addr,
|
||||
struct net_linkaddr *lladdr,
|
||||
bool is_router,
|
||||
enum net_nbr_state state)
|
||||
enum net_ipv6_nbr_state state)
|
||||
{
|
||||
return net_ipv6_nbr_add(net_nbuf_iface(buf), addr, lladdr,
|
||||
is_router, state);
|
||||
|
@ -319,7 +320,7 @@ static void ns_reply_timeout(struct k_work *work)
|
|||
|
||||
static struct net_nbr *nbr_new(struct net_if *iface,
|
||||
struct in6_addr *addr,
|
||||
enum net_nbr_state state)
|
||||
enum net_ipv6_nbr_state state)
|
||||
{
|
||||
struct net_nbr *nbr = net_nbr_get(&net_neighbor.table);
|
||||
|
||||
|
@ -331,7 +332,7 @@ static struct net_nbr *nbr_new(struct net_if *iface,
|
|||
nbr->iface = iface;
|
||||
|
||||
net_ipaddr_copy(&net_ipv6_nbr_data(nbr)->addr, addr);
|
||||
nbr_set_state(nbr, state);
|
||||
ipv6_nbr_set_state(nbr, state);
|
||||
net_ipv6_nbr_data(nbr)->pending = NULL;
|
||||
|
||||
#if defined(CONFIG_NET_IPV6_ND)
|
||||
|
@ -550,12 +551,7 @@ static inline void dbg_update_neighbor_lladdr_raw(uint8_t *new_lladdr,
|
|||
|
||||
dbg_update_neighbor_lladdr(&lladdr, old_lladdr, addr);
|
||||
}
|
||||
#else
|
||||
#define dbg_update_neighbor_lladdr(...)
|
||||
#define dbg_update_neighbor_lladdr_raw(...)
|
||||
#endif /* CONFIG_NET_DEBUG_IPV6 */
|
||||
|
||||
#if defined(CONFIG_NET_DEBUG_IPV6)
|
||||
#define dbg_addr(action, pkt_str, src, dst) \
|
||||
do { \
|
||||
char out[NET_IPV6_ADDR_LEN]; \
|
||||
|
@ -595,6 +591,8 @@ static inline void dbg_update_neighbor_lladdr_raw(uint8_t *new_lladdr,
|
|||
#define dbg_addr_sent_tgt(pkt_str, src, dst, tgt) \
|
||||
dbg_addr_with_tgt("Sent", pkt_str, src, dst, tgt)
|
||||
#else
|
||||
#define dbg_update_neighbor_lladdr(...)
|
||||
#define dbg_update_neighbor_lladdr_raw(...)
|
||||
#define dbg_addr(...)
|
||||
#define dbg_addr_recv(...)
|
||||
#define dbg_addr_sent(...)
|
||||
|
@ -621,6 +619,14 @@ static struct net_buf *update_ll_reserve(struct net_buf *buf,
|
|||
uint16_t reserve, room_len, copy_len, pos;
|
||||
struct net_buf *orig_frag, *frag;
|
||||
|
||||
/* No need to do anything if we are forwarding the packet
|
||||
* as we already know everything about the destination of
|
||||
* the packet.
|
||||
*/
|
||||
if (net_nbuf_forwarding(buf)) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
reserve = net_if_get_ll_reserve(net_nbuf_iface(buf), addr);
|
||||
if (reserve == net_nbuf_ll_reserve(buf)) {
|
||||
return buf;
|
||||
|
@ -774,7 +780,8 @@ try_send:
|
|||
nbr ? nbr->idx : NET_NBR_LLADDR_UNKNOWN,
|
||||
net_nbuf_iface(buf),
|
||||
net_sprint_ipv6_addr(nexthop),
|
||||
net_nbr_state2str(net_ipv6_nbr_data(nbr)->state));
|
||||
nbr ? net_ipv6_nbr_state2str(net_ipv6_nbr_data(nbr)->state) :
|
||||
"-");
|
||||
|
||||
if (nbr && nbr->idx != NET_NBR_LLADDR_UNKNOWN) {
|
||||
struct net_linkaddr_storage *lladdr;
|
||||
|
@ -791,8 +798,8 @@ try_send:
|
|||
* See RFC 4861 ch 7.3.3 for details.
|
||||
*/
|
||||
#if defined(CONFIG_NET_IPV6_ND)
|
||||
if (net_ipv6_nbr_data(nbr)->state == NET_NBR_STALE) {
|
||||
nbr_set_state(nbr, NET_NBR_DELAY);
|
||||
if (net_ipv6_nbr_data(nbr)->state == NET_IPV6_NBR_STATE_STALE) {
|
||||
ipv6_nbr_set_state(nbr, NET_IPV6_NBR_STATE_DELAY);
|
||||
|
||||
k_delayed_work_submit(
|
||||
&net_ipv6_nbr_data(nbr)->reachable,
|
||||
|
@ -931,7 +938,8 @@ static inline void handle_ns_neighbor(struct net_buf *buf,
|
|||
nbr_print();
|
||||
|
||||
nbr = nbr_new(net_nbuf_iface(buf),
|
||||
&NET_IPV6_BUF(buf)->src, NET_NBR_INCOMPLETE);
|
||||
&NET_IPV6_BUF(buf)->src,
|
||||
NET_IPV6_NBR_STATE_INCOMPLETE);
|
||||
if (nbr) {
|
||||
NET_DBG("Added %s to nbr cache",
|
||||
net_sprint_ipv6_addr(&NET_IPV6_BUF(buf)->src));
|
||||
|
@ -964,11 +972,12 @@ static inline void handle_ns_neighbor(struct net_buf *buf,
|
|||
net_linkaddr_set(cached_lladdr, lladdr.addr,
|
||||
lladdr.len);
|
||||
|
||||
nbr_set_state(nbr, NET_NBR_STALE);
|
||||
ipv6_nbr_set_state(nbr, NET_IPV6_NBR_STATE_STALE);
|
||||
} else {
|
||||
if (net_ipv6_nbr_data(nbr)->state ==
|
||||
NET_NBR_INCOMPLETE) {
|
||||
nbr_set_state(nbr, NET_NBR_STALE);
|
||||
NET_IPV6_NBR_STATE_INCOMPLETE) {
|
||||
ipv6_nbr_set_state(nbr,
|
||||
NET_IPV6_NBR_STATE_STALE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1235,7 +1244,7 @@ static void nd_reachable_timeout(struct k_work *work)
|
|||
|
||||
switch (data->state) {
|
||||
|
||||
case NET_NBR_INCOMPLETE:
|
||||
case NET_IPV6_NBR_STATE_INCOMPLETE:
|
||||
if (data->ns_count >= MAX_MULTICAST_SOLICIT) {
|
||||
nbr_free(nbr);
|
||||
} else {
|
||||
|
@ -1249,21 +1258,21 @@ static void nd_reachable_timeout(struct k_work *work)
|
|||
}
|
||||
break;
|
||||
|
||||
case NET_NBR_REACHABLE:
|
||||
data->state = NET_NBR_STALE;
|
||||
case NET_IPV6_NBR_STATE_REACHABLE:
|
||||
data->state = NET_IPV6_NBR_STATE_STALE;
|
||||
|
||||
NET_DBG("nbr %p moving %s state to STALE (%d)",
|
||||
nbr, net_sprint_ipv6_addr(&data->addr), data->state);
|
||||
break;
|
||||
|
||||
case NET_NBR_STALE:
|
||||
case NET_IPV6_NBR_STATE_STALE:
|
||||
NET_DBG("nbr %p removing stale address %s",
|
||||
nbr, net_sprint_ipv6_addr(&data->addr));
|
||||
nbr_free(nbr);
|
||||
break;
|
||||
|
||||
case NET_NBR_DELAY:
|
||||
data->state = NET_NBR_PROBE;
|
||||
case NET_IPV6_NBR_STATE_DELAY:
|
||||
data->state = NET_IPV6_NBR_STATE_PROBE;
|
||||
data->ns_count = 0;
|
||||
|
||||
NET_DBG("nbr %p moving %s state to PROBE (%d)",
|
||||
|
@ -1271,7 +1280,7 @@ static void nd_reachable_timeout(struct k_work *work)
|
|||
|
||||
/* Intentionally continuing to probe state */
|
||||
|
||||
case NET_NBR_PROBE:
|
||||
case NET_IPV6_NBR_STATE_PROBE:
|
||||
if (data->ns_count >= MAX_UNICAST_SOLICIT) {
|
||||
struct net_if_router *router;
|
||||
|
||||
|
@ -1378,7 +1387,7 @@ static inline bool handle_na_neighbor(struct net_buf *buf,
|
|||
}
|
||||
|
||||
/* Update the cached address if we do not yet known it */
|
||||
if (net_ipv6_nbr_data(nbr)->state == NET_NBR_INCOMPLETE) {
|
||||
if (net_ipv6_nbr_data(nbr)->state == NET_IPV6_NBR_STATE_INCOMPLETE) {
|
||||
if (!tllao) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1395,7 +1404,7 @@ static inline bool handle_na_neighbor(struct net_buf *buf,
|
|||
}
|
||||
|
||||
if (net_is_solicited(buf)) {
|
||||
nbr_set_state(nbr, NET_NBR_REACHABLE);
|
||||
ipv6_nbr_set_state(nbr, NET_IPV6_NBR_STATE_REACHABLE);
|
||||
net_ipv6_nbr_data(nbr)->ns_count = 0;
|
||||
|
||||
/* We might have active timer from PROBE */
|
||||
|
@ -1405,7 +1414,7 @@ static inline bool handle_na_neighbor(struct net_buf *buf,
|
|||
net_ipv6_nbr_set_reachable_timer(net_nbuf_iface(buf),
|
||||
nbr);
|
||||
} else {
|
||||
nbr_set_state(nbr, NET_NBR_STALE);
|
||||
ipv6_nbr_set_state(nbr, NET_IPV6_NBR_STATE_STALE);
|
||||
}
|
||||
|
||||
net_ipv6_nbr_data(nbr)->is_router = net_is_router(buf);
|
||||
|
@ -1417,8 +1426,9 @@ static inline bool handle_na_neighbor(struct net_buf *buf,
|
|||
* and we have a valid address in the cache.
|
||||
*/
|
||||
if (!net_is_override(buf) && lladdr_changed) {
|
||||
if (net_ipv6_nbr_data(nbr)->state == NET_NBR_REACHABLE) {
|
||||
nbr_set_state(nbr, NET_NBR_STALE);
|
||||
if (net_ipv6_nbr_data(nbr)->state ==
|
||||
NET_IPV6_NBR_STATE_REACHABLE) {
|
||||
ipv6_nbr_set_state(nbr, NET_IPV6_NBR_STATE_STALE);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -1439,7 +1449,7 @@ static inline bool handle_na_neighbor(struct net_buf *buf,
|
|||
}
|
||||
|
||||
if (net_is_solicited(buf)) {
|
||||
nbr_set_state(nbr, NET_NBR_REACHABLE);
|
||||
ipv6_nbr_set_state(nbr, NET_IPV6_NBR_STATE_REACHABLE);
|
||||
|
||||
/* We might have active timer from PROBE */
|
||||
k_delayed_work_cancel(
|
||||
|
@ -1449,7 +1459,8 @@ static inline bool handle_na_neighbor(struct net_buf *buf,
|
|||
nbr);
|
||||
} else {
|
||||
if (lladdr_changed) {
|
||||
nbr_set_state(nbr, NET_NBR_STALE);
|
||||
ipv6_nbr_set_state(nbr,
|
||||
NET_IPV6_NBR_STATE_STALE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1682,7 +1693,7 @@ int net_ipv6_send_ns(struct net_if *iface,
|
|||
|
||||
nbr = nbr_new(net_nbuf_iface(buf),
|
||||
&NET_ICMPV6_NS_BUF(buf)->tgt,
|
||||
NET_NBR_INCOMPLETE);
|
||||
NET_IPV6_NBR_STATE_INCOMPLETE);
|
||||
if (!nbr) {
|
||||
NET_DBG("Could not create new neighbor %s",
|
||||
net_sprint_ipv6_addr(
|
||||
|
@ -1859,7 +1870,7 @@ static inline struct net_buf *handle_ra_neighbor(struct net_buf *buf,
|
|||
nbr_print();
|
||||
|
||||
*nbr = nbr_add(buf, &NET_IPV6_BUF(buf)->src, &lladdr,
|
||||
true, NET_NBR_STALE);
|
||||
true, NET_IPV6_NBR_STATE_STALE);
|
||||
if (!*nbr) {
|
||||
NET_ERR("Could not add router neighbor %s [%s]",
|
||||
net_sprint_ipv6_addr(&NET_IPV6_BUF(buf)->src),
|
||||
|
@ -1883,11 +1894,12 @@ static inline struct net_buf *handle_ra_neighbor(struct net_buf *buf,
|
|||
net_linkaddr_set(cached_lladdr, lladdr.addr,
|
||||
lladdr.len);
|
||||
|
||||
nbr_set_state(*nbr, NET_NBR_STALE);
|
||||
ipv6_nbr_set_state(*nbr, NET_IPV6_NBR_STATE_STALE);
|
||||
} else {
|
||||
if (net_ipv6_nbr_data(*nbr)->state ==
|
||||
NET_NBR_INCOMPLETE) {
|
||||
nbr_set_state(*nbr, NET_NBR_STALE);
|
||||
NET_IPV6_NBR_STATE_INCOMPLETE) {
|
||||
ipv6_nbr_set_state(*nbr,
|
||||
NET_IPV6_NBR_STATE_STALE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,15 +64,15 @@
|
|||
#define NET_IPV6_MLDv2_BLOCK_OLD_SOURCES 6
|
||||
|
||||
/* State of the neighbor */
|
||||
enum net_nbr_state {
|
||||
NET_NBR_INCOMPLETE,
|
||||
NET_NBR_REACHABLE,
|
||||
NET_NBR_STALE,
|
||||
NET_NBR_DELAY,
|
||||
NET_NBR_PROBE,
|
||||
enum net_ipv6_nbr_state {
|
||||
NET_IPV6_NBR_STATE_INCOMPLETE,
|
||||
NET_IPV6_NBR_STATE_REACHABLE,
|
||||
NET_IPV6_NBR_STATE_STALE,
|
||||
NET_IPV6_NBR_STATE_DELAY,
|
||||
NET_IPV6_NBR_STATE_PROBE,
|
||||
};
|
||||
|
||||
const char *net_nbr_state2str(enum net_nbr_state state);
|
||||
const char *net_ipv6_nbr_state2str(enum net_ipv6_nbr_state state);
|
||||
|
||||
/**
|
||||
* @brief IPv6 neighbor information.
|
||||
|
@ -91,7 +91,7 @@ struct net_ipv6_nbr_data {
|
|||
struct k_delayed_work send_ns;
|
||||
|
||||
/** State of the neighbor discovery */
|
||||
enum net_nbr_state state;
|
||||
enum net_ipv6_nbr_state state;
|
||||
|
||||
/** Link metric for the neighbor */
|
||||
uint16_t link_metric;
|
||||
|
@ -289,7 +289,7 @@ struct net_nbr *net_ipv6_nbr_add(struct net_if *iface,
|
|||
struct in6_addr *addr,
|
||||
struct net_linkaddr *lladdr,
|
||||
bool is_router,
|
||||
enum net_nbr_state state);
|
||||
enum net_ipv6_nbr_state state);
|
||||
|
||||
/**
|
||||
* @brief Remove a neighbour from neighbor cache.
|
||||
|
@ -332,7 +332,7 @@ static inline struct net_nbr *net_ipv6_nbr_add(struct net_if *iface,
|
|||
struct in6_addr *addr,
|
||||
struct net_linkaddr *lladdr,
|
||||
bool is_router,
|
||||
enum net_nbr_state state)
|
||||
enum net_ipv6_nbr_state state)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -29,19 +29,19 @@ config NET_DEBUG_L2_ETHERNET
|
|||
help
|
||||
Enables Ethernet L2 output debug messages
|
||||
|
||||
config NET_L2_OFFLOAD_IP
|
||||
config NET_OFFLOAD
|
||||
bool "Offload IP stack [EXPERIMENTAL]"
|
||||
default n
|
||||
help
|
||||
Enables IP stack to be offload to a co-processor.
|
||||
Enables TCP/IP stack to be offload to a co-processor.
|
||||
|
||||
config NET_DEBUG_L2_OFFLOAD
|
||||
bool "Debug IP Offload L2 layer"
|
||||
config NET_DEBUG_NET_OFFLOAD
|
||||
bool "Debug Net Offload Layer"
|
||||
default n
|
||||
depends on NET_LOG
|
||||
depends on NET_L2_OFFLOAD
|
||||
depends on NET_OFFLOAD
|
||||
help
|
||||
Enables offload IP stack L2 output debug messages.
|
||||
Enables offload TCP/IP stack output debug messages.
|
||||
|
||||
config NET_L2_BLUETOOTH
|
||||
bool "Enable Bluetooth support"
|
||||
|
|
|
@ -144,7 +144,8 @@ static void ipsp_connected(struct bt_l2cap_chan *chan)
|
|||
* A Bluetooth LE 6LN MUST NOT register its link-local address.
|
||||
*/
|
||||
net_ipv6_addr_create_iid(&in6, &ll);
|
||||
net_ipv6_nbr_add(ctxt->iface, &in6, &ll, false, NET_NBR_REACHABLE);
|
||||
net_ipv6_nbr_add(ctxt->iface, &in6, &ll, false,
|
||||
NET_IPV6_NBR_STATE_REACHABLE);
|
||||
|
||||
/* Set iface up */
|
||||
net_if_up(ctxt->iface);
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include <net/nbuf.h>
|
||||
#include <net/net_ip.h>
|
||||
#include <net/net_context.h>
|
||||
#include <net/offload_ip.h>
|
||||
#include <net/net_offload.h>
|
||||
|
||||
#include "connection.h"
|
||||
#include "net_private.h"
|
||||
|
@ -319,16 +319,16 @@ int net_context_get(sa_family_t family,
|
|||
|
||||
k_sem_give(&contexts_lock);
|
||||
|
||||
#if defined(CONFIG_NET_L2_OFFLOAD_IP)
|
||||
#if defined(CONFIG_NET_OFFLOAD)
|
||||
/* FIXME - Figure out a way to get the correct network interface
|
||||
* as it is not known at this point yet.
|
||||
*/
|
||||
if (!ret && net_if_is_ip_offloaded(net_if_get_default())) {
|
||||
ret = net_l2_offload_ip_get(net_if_get_default(),
|
||||
family,
|
||||
type,
|
||||
ip_proto,
|
||||
context);
|
||||
ret = net_offload_get(net_if_get_default(),
|
||||
family,
|
||||
type,
|
||||
ip_proto,
|
||||
context);
|
||||
if (ret < 0) {
|
||||
(*context)->flags &= ~NET_CONTEXT_IN_USE;
|
||||
*context = NULL;
|
||||
|
@ -336,7 +336,7 @@ int net_context_get(sa_family_t family,
|
|||
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
#endif /* CONFIG_NET_OFFLOAD */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -405,14 +405,14 @@ int net_context_put(struct net_context *context)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_L2_OFFLOAD_IP)
|
||||
#if defined(CONFIG_NET_OFFLOAD)
|
||||
if (net_if_is_ip_offloaded(net_context_get_iface(context))) {
|
||||
k_sem_take(&contexts_lock, K_FOREVER);
|
||||
context->flags &= ~NET_CONTEXT_IN_USE;
|
||||
return net_l2_offload_ip_put(
|
||||
return net_offload_put(
|
||||
net_context_get_iface(context), context);
|
||||
}
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
#endif /* CONFIG_NET_OFFLOAD */
|
||||
|
||||
context->connect_cb = NULL;
|
||||
context->recv_cb = NULL;
|
||||
|
@ -496,16 +496,16 @@ int net_context_bind(struct net_context *context, const struct sockaddr *addr,
|
|||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_L2_OFFLOAD_IP)
|
||||
#if defined(CONFIG_NET_OFFLOAD)
|
||||
if (net_if_is_ip_offloaded(iface)) {
|
||||
net_context_set_iface(context, iface);
|
||||
|
||||
return net_l2_offload_ip_bind(iface,
|
||||
context,
|
||||
addr,
|
||||
addrlen);
|
||||
return net_offload_bind(iface,
|
||||
context,
|
||||
addr,
|
||||
addrlen);
|
||||
}
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
#endif /* CONFIG_NET_OFFLOAD */
|
||||
|
||||
net_context_set_iface(context, iface);
|
||||
|
||||
|
@ -522,6 +522,9 @@ int net_context_bind(struct net_context *context, const struct sockaddr *addr,
|
|||
ntohs(addr6->sin6_port));
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
addr6->sin6_port =
|
||||
net_sin6_ptr(&context->local)->sin6_port;
|
||||
}
|
||||
|
||||
NET_DBG("Context %p binding to %s [%s]:%d iface %p",
|
||||
|
@ -567,16 +570,16 @@ int net_context_bind(struct net_context *context, const struct sockaddr *addr,
|
|||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_L2_OFFLOAD_IP)
|
||||
#if defined(CONFIG_NET_OFFLOAD)
|
||||
if (net_if_is_ip_offloaded(iface)) {
|
||||
net_context_set_iface(context, iface);
|
||||
|
||||
return net_l2_offload_ip_bind(iface,
|
||||
context,
|
||||
addr,
|
||||
addrlen);
|
||||
return net_offload_bind(iface,
|
||||
context,
|
||||
addr,
|
||||
addrlen);
|
||||
}
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
#endif /* CONFIG_NET_OFFLOAD */
|
||||
|
||||
net_context_set_iface(context, iface);
|
||||
|
||||
|
@ -593,6 +596,9 @@ int net_context_bind(struct net_context *context, const struct sockaddr *addr,
|
|||
ntohs(addr4->sin_port));
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
addr4->sin_port =
|
||||
net_sin_ptr(&context->local)->sin_port;
|
||||
}
|
||||
|
||||
NET_DBG("Context %p binding to %s %s:%d iface %p",
|
||||
|
@ -635,12 +641,12 @@ int net_context_listen(struct net_context *context, int backlog)
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_L2_OFFLOAD_IP)
|
||||
#if defined(CONFIG_NET_OFFLOAD)
|
||||
if (net_if_is_ip_offloaded(net_context_get_iface(context))) {
|
||||
return net_l2_offload_ip_listen(
|
||||
return net_offload_listen(
|
||||
net_context_get_iface(context), context, backlog);
|
||||
}
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
#endif /* CONFIG_NET_OFFLOAD */
|
||||
|
||||
#if defined(CONFIG_NET_TCP)
|
||||
if (net_context_get_ip_proto(context) == IPPROTO_TCP) {
|
||||
|
@ -827,7 +833,10 @@ NET_CONN_CB(tcp_established)
|
|||
* LAST_ACK state
|
||||
*/
|
||||
context->tcp->fin_rcvd = 1;
|
||||
net_tcp_change_state(context->tcp, NET_TCP_CLOSE_WAIT);
|
||||
|
||||
if (net_tcp_get_state(context->tcp) == NET_TCP_ESTABLISHED) {
|
||||
net_tcp_change_state(context->tcp, NET_TCP_CLOSE_WAIT);
|
||||
}
|
||||
|
||||
context->tcp->send_ack += 1;
|
||||
|
||||
|
@ -1005,9 +1014,9 @@ int net_context_connect(struct net_context *context,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_L2_OFFLOAD_IP)
|
||||
#if defined(CONFIG_NET_OFFLOAD)
|
||||
if (net_if_is_ip_offloaded(net_context_get_iface(context))) {
|
||||
return net_l2_offload_ip_connect(
|
||||
return net_offload_connect(
|
||||
net_context_get_iface(context),
|
||||
context,
|
||||
addr,
|
||||
|
@ -1016,7 +1025,7 @@ int net_context_connect(struct net_context *context,
|
|||
timeout,
|
||||
user_data);
|
||||
}
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
#endif /* CONFIG_NET_OFFLOAD */
|
||||
|
||||
if (net_context_get_state(context) == NET_CONTEXT_LISTENING) {
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -1469,16 +1478,16 @@ int net_context_accept(struct net_context *context,
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_L2_OFFLOAD_IP)
|
||||
#if defined(CONFIG_NET_OFFLOAD)
|
||||
if (net_if_is_ip_offloaded(net_context_get_iface(context))) {
|
||||
return net_l2_offload_ip_accept(
|
||||
return net_offload_accept(
|
||||
net_context_get_iface(context),
|
||||
context,
|
||||
cb,
|
||||
timeout,
|
||||
user_data);
|
||||
}
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
#endif /* CONFIG_NET_OFFLOAD */
|
||||
|
||||
if ((net_context_get_state(context) != NET_CONTEXT_LISTENING) &&
|
||||
(net_context_get_type(context) != SOCK_STREAM)) {
|
||||
|
@ -1656,14 +1665,14 @@ static int sendto(struct net_buf *buf,
|
|||
return -EDESTADDRREQ;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_L2_OFFLOAD_IP)
|
||||
#if defined(CONFIG_NET_OFFLOAD)
|
||||
if (net_if_is_ip_offloaded(net_nbuf_iface(buf))) {
|
||||
return net_l2_offload_ip_sendto(
|
||||
return net_offload_sendto(
|
||||
net_nbuf_iface(buf),
|
||||
buf, dst_addr, addrlen,
|
||||
cb, timeout, token, user_data);
|
||||
}
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
#endif /* CONFIG_NET_OFFLOAD */
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
if (net_nbuf_family(buf) == AF_INET6) {
|
||||
|
@ -1733,14 +1742,14 @@ int net_context_send(struct net_buf *buf,
|
|||
|
||||
NET_ASSERT(PART_OF_ARRAY(contexts, context));
|
||||
|
||||
#if defined(CONFIG_NET_L2_OFFLOAD_IP)
|
||||
#if defined(CONFIG_NET_OFFLOAD)
|
||||
if (net_if_is_ip_offloaded(net_nbuf_iface(buf))) {
|
||||
return net_l2_offload_ip_send(
|
||||
return net_offload_send(
|
||||
net_nbuf_iface(buf),
|
||||
buf, cb, timeout,
|
||||
token, user_data);
|
||||
}
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
#endif /* CONFIG_NET_OFFLOAD */
|
||||
|
||||
if (!(context->flags & NET_CONTEXT_REMOTE_ADDR_SET) ||
|
||||
!net_sin(&context->remote)->sin_port) {
|
||||
|
@ -1939,13 +1948,13 @@ int net_context_recv(struct net_context *context,
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_L2_OFFLOAD_IP)
|
||||
#if defined(CONFIG_NET_OFFLOAD)
|
||||
if (net_if_is_ip_offloaded(net_context_get_iface(context))) {
|
||||
return net_l2_offload_ip_recv(
|
||||
return net_offload_recv(
|
||||
net_context_get_iface(context),
|
||||
context, cb, timeout, user_data);
|
||||
}
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
#endif /* CONFIG_NET_OFFLOAD */
|
||||
|
||||
#if defined(CONFIG_NET_UDP)
|
||||
if (net_context_get_ip_proto(context) == IPPROTO_UDP) {
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <net/arp.h>
|
||||
#include <net/nbuf.h>
|
||||
#include <net/net_core.h>
|
||||
#include <net/dns_resolve.h>
|
||||
|
||||
#include "net_private.h"
|
||||
#include "net_shell.h"
|
||||
|
@ -35,9 +36,7 @@
|
|||
#include "icmpv6.h"
|
||||
#include "ipv6.h"
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
#include "icmpv4.h"
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_DHCPV4)
|
||||
#include "dhcpv4.h"
|
||||
|
@ -258,7 +257,29 @@ static inline enum net_verdict process_ipv6_pkt(struct net_buf *buf)
|
|||
!net_is_my_ipv6_maddr(&hdr->dst) &&
|
||||
!net_is_ipv6_addr_mcast(&hdr->dst) &&
|
||||
!net_is_ipv6_addr_loopback(&hdr->dst)) {
|
||||
NET_DBG("IPv6 packet in buf %p not for me", buf);
|
||||
#if defined(CONFIG_NET_ROUTE)
|
||||
struct net_route_entry *route;
|
||||
struct in6_addr *nexthop;
|
||||
|
||||
/* Check if the packet can be routed */
|
||||
if (net_route_get_info(&hdr->dst, &route, &nexthop)) {
|
||||
int ret;
|
||||
|
||||
ret = net_route_packet(buf, route, nexthop);
|
||||
if (ret < 0) {
|
||||
NET_DBG("Cannot re-route buf %p via %s (%d)",
|
||||
buf, net_sprint_ipv6_addr(nexthop),
|
||||
ret);
|
||||
} else {
|
||||
return NET_OK;
|
||||
}
|
||||
} else
|
||||
#endif /* CONFIG_NET_ROUTE */
|
||||
|
||||
{
|
||||
NET_DBG("IPv6 packet in buf %p not for me", buf);
|
||||
}
|
||||
|
||||
net_stats_update_ipv6_drop();
|
||||
goto drop;
|
||||
}
|
||||
|
@ -392,12 +413,11 @@ static inline enum net_verdict process_icmpv4_pkt(struct net_buf *buf,
|
|||
struct net_ipv4_hdr *ipv4)
|
||||
{
|
||||
struct net_icmp_hdr *hdr = NET_ICMP_BUF(buf);
|
||||
uint16_t len = (ipv4->len[0] << 8) + ipv4->len[1];
|
||||
|
||||
NET_DBG("ICMPv4 packet received length %d type %d code %d",
|
||||
len, hdr->type, hdr->code);
|
||||
NET_DBG("ICMPv4 packet received type %d code %d",
|
||||
hdr->type, hdr->code);
|
||||
|
||||
return net_icmpv4_input(buf, len, hdr->type, hdr->code);
|
||||
return net_icmpv4_input(buf, hdr->type, hdr->code);
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV4 */
|
||||
|
||||
|
@ -735,6 +755,7 @@ int net_recv_data(struct net_if *iface, struct net_buf *buf)
|
|||
|
||||
static inline void l3_init(void)
|
||||
{
|
||||
net_icmpv4_init();
|
||||
net_icmpv6_init();
|
||||
net_ipv6_init();
|
||||
|
||||
|
@ -746,6 +767,8 @@ static inline void l3_init(void)
|
|||
|
||||
net_route_init();
|
||||
|
||||
dns_init_resolver();
|
||||
|
||||
NET_DBG("Network L3 init done");
|
||||
}
|
||||
|
||||
|
|
|
@ -443,7 +443,11 @@ void net_if_start_dad(struct net_if *iface)
|
|||
}
|
||||
}
|
||||
#else
|
||||
#define net_if_ipv6_start_dad(...)
|
||||
static inline void net_if_ipv6_start_dad(struct net_if *iface,
|
||||
struct net_if_addr *ifaddr)
|
||||
{
|
||||
ifaddr->addr_state = NET_ADDR_PREFERRED;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV6_DAD */
|
||||
|
||||
#if defined(CONFIG_NET_IPV6_ND)
|
||||
|
@ -1043,6 +1047,8 @@ struct net_if_router *net_if_ipv6_router_add(struct net_if *iface,
|
|||
i, iface, net_sprint_ipv6_addr(addr), lifetime,
|
||||
routers[i].is_default);
|
||||
|
||||
net_mgmt_event_notify(NET_EVENT_IPV6_ROUTER_ADD, iface);
|
||||
|
||||
return &routers[i];
|
||||
}
|
||||
|
||||
|
@ -1066,6 +1072,9 @@ bool net_if_ipv6_router_rm(struct net_if_router *router)
|
|||
|
||||
routers[i].is_used = false;
|
||||
|
||||
net_mgmt_event_notify(NET_EVENT_IPV6_ROUTER_DEL,
|
||||
routers[i].iface);
|
||||
|
||||
NET_DBG("[%d] router %s removed",
|
||||
i, net_sprint_ipv6_addr(&routers[i].address.in6_addr));
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <shell/shell.h>
|
||||
|
||||
#include <net/net_if.h>
|
||||
#include <net/dns_resolve.h>
|
||||
#include <misc/printk.h>
|
||||
|
||||
#include "route.h"
|
||||
|
@ -568,6 +569,198 @@ static int shell_cmd_conn(int argc, char *argv[])
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DNS_RESOLVER)
|
||||
static void dns_result_cb(enum dns_resolve_status status,
|
||||
struct dns_addrinfo *info,
|
||||
void *user_data)
|
||||
{
|
||||
bool *first = user_data;
|
||||
|
||||
if (status == DNS_EAI_CANCELED) {
|
||||
printk("\nTimeout while resolving name.\n");
|
||||
*first = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == DNS_EAI_INPROGRESS && info) {
|
||||
char addr[NET_IPV6_ADDR_LEN];
|
||||
|
||||
if (*first) {
|
||||
printk("\n");
|
||||
*first = false;
|
||||
}
|
||||
|
||||
if (info->ai_family == AF_INET) {
|
||||
net_addr_ntop(AF_INET,
|
||||
&net_sin(&info->ai_addr)->sin_addr,
|
||||
addr, NET_IPV4_ADDR_LEN);
|
||||
} else if (info->ai_family == AF_INET6) {
|
||||
net_addr_ntop(AF_INET6,
|
||||
&net_sin6(&info->ai_addr)->sin6_addr,
|
||||
addr, NET_IPV6_ADDR_LEN);
|
||||
} else {
|
||||
strncpy(addr, "Invalid protocol family",
|
||||
sizeof(addr));
|
||||
}
|
||||
|
||||
printk("\t%s\n", addr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == DNS_EAI_ALLDONE) {
|
||||
printk("All results received\n");
|
||||
*first = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == DNS_EAI_FAIL) {
|
||||
printk("No such name found.\n");
|
||||
*first = false;
|
||||
return;
|
||||
}
|
||||
|
||||
printk("Unhandled status %d received\n", status);
|
||||
}
|
||||
|
||||
static void print_dns_info(struct dns_resolve_context *ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
printk("DNS servers:\n");
|
||||
|
||||
for (i = 0; i < CONFIG_DNS_RESOLVER_MAX_SERVERS; i++) {
|
||||
if (ctx->servers[i].dns_server.family == AF_INET) {
|
||||
printk("\t%s:%u\n",
|
||||
net_sprint_ipv4_addr(
|
||||
&net_sin(&ctx->servers[i].dns_server)->
|
||||
sin_addr),
|
||||
ntohs(net_sin(&ctx->servers[i].
|
||||
dns_server)->sin_port));
|
||||
} else if (ctx->servers[i].dns_server.family == AF_INET6) {
|
||||
printk("\t[%s]:%u\n",
|
||||
net_sprint_ipv6_addr(
|
||||
&net_sin6(&ctx->servers[i].dns_server)->
|
||||
sin6_addr),
|
||||
ntohs(net_sin6(&ctx->servers[i].
|
||||
dns_server)->sin6_port));
|
||||
}
|
||||
}
|
||||
|
||||
printk("Pending queries:\n");
|
||||
|
||||
for (i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) {
|
||||
int32_t remaining;
|
||||
|
||||
if (!ctx->queries[i].cb) {
|
||||
continue;
|
||||
}
|
||||
|
||||
remaining =
|
||||
k_delayed_work_remaining_get(&ctx->queries[i].timer);
|
||||
|
||||
if (ctx->queries[i].query_type == DNS_QUERY_TYPE_A) {
|
||||
printk("\tIPv4[%u]: %s remaining %d\n",
|
||||
ctx->queries[i].id,
|
||||
ctx->queries[i].query,
|
||||
remaining);
|
||||
} else if (ctx->queries[i].query_type == DNS_QUERY_TYPE_AAAA) {
|
||||
printk("\tIPv6[%u]: %s remaining %d\n",
|
||||
ctx->queries[i].id,
|
||||
ctx->queries[i].query,
|
||||
remaining);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int shell_cmd_dns(int argc, char *argv[])
|
||||
{
|
||||
#if defined(CONFIG_DNS_RESOLVER)
|
||||
#define DNS_TIMEOUT 2000 /* ms */
|
||||
|
||||
struct dns_resolve_context *ctx;
|
||||
enum dns_query_type qtype = DNS_QUERY_TYPE_A;
|
||||
char *host, *type = NULL;
|
||||
bool first = true;
|
||||
int arg = 1;
|
||||
int ret, i;
|
||||
|
||||
if (strcmp(argv[0], "dns")) {
|
||||
arg++;
|
||||
}
|
||||
|
||||
if (!argv[arg]) {
|
||||
/* DNS status */
|
||||
ctx = dns_resolve_get_default();
|
||||
if (!ctx) {
|
||||
printk("No default DNS context found.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
print_dns_info(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(argv[arg], "cancel") == 0) {
|
||||
ctx = dns_resolve_get_default();
|
||||
if (!ctx) {
|
||||
printk("No default DNS context found.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (ret = 0, i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) {
|
||||
if (!ctx->queries[i].cb) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!dns_resolve_cancel(ctx, ctx->queries[i].id)) {
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
printk("Cancelled %d pending requests.\n", ret);
|
||||
} else {
|
||||
printk("No pending DNS requests.\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
host = argv[arg++];
|
||||
|
||||
if (argv[arg]) {
|
||||
type = argv[arg];
|
||||
}
|
||||
|
||||
if (type) {
|
||||
if (strcmp(type, "A") == 0) {
|
||||
qtype = DNS_QUERY_TYPE_A;
|
||||
printk("IPv4 address type\n");
|
||||
} else if (strcmp(type, "AAAA") == 0) {
|
||||
qtype = DNS_QUERY_TYPE_AAAA;
|
||||
printk("IPv6 address type\n");
|
||||
} else {
|
||||
printk("Unknown query type, specify either "
|
||||
"A or AAAA\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ret = dns_get_addr_info(host, qtype, NULL, dns_result_cb, &first,
|
||||
DNS_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
printk("Cannot resolve '%s' (%d)\n", host, ret);
|
||||
} else {
|
||||
printk("Query for '%s' sent.\n", host);
|
||||
}
|
||||
|
||||
#else
|
||||
printk("DNS resolver not supported.\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shell_cmd_iface(int argc, char *argv[])
|
||||
{
|
||||
ARG_UNUSED(argc);
|
||||
|
@ -721,7 +914,7 @@ static void nbr_cb(struct net_nbr *nbr, void *user_data)
|
|||
net_ipv6_nbr_data(nbr)->is_router,
|
||||
net_ipv6_nbr_data(nbr)->link_metric,
|
||||
nbr->iface,
|
||||
net_nbr_state2str(net_ipv6_nbr_data(nbr)->state),
|
||||
net_ipv6_nbr_state2str(net_ipv6_nbr_data(nbr)->state),
|
||||
k_delayed_work_remaining_get(
|
||||
&net_ipv6_nbr_data(nbr)->reachable),
|
||||
nbr->idx == NET_NBR_LLADDR_UNKNOWN ? "?" :
|
||||
|
@ -783,14 +976,131 @@ static int shell_cmd_nbr(int argc, char *argv[])
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) || defined(CONFIG_NET_IPV4)
|
||||
|
||||
K_SEM_DEFINE(ping_timeout, 0, 1);
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
|
||||
static enum net_verdict _handle_ipv6_echo_reply(struct net_buf *buf);
|
||||
|
||||
static struct net_icmpv6_handler ping6_handler = {
|
||||
.type = NET_ICMPV6_ECHO_REPLY,
|
||||
.code = 0,
|
||||
.handler = _handle_ipv6_echo_reply,
|
||||
};
|
||||
|
||||
static inline void _remove_ipv6_ping_handler(void)
|
||||
{
|
||||
net_icmpv6_unregister_handler(&ping6_handler);
|
||||
}
|
||||
|
||||
static enum net_verdict _handle_ipv6_echo_reply(struct net_buf *buf)
|
||||
{
|
||||
char addr[NET_IPV6_ADDR_LEN];
|
||||
|
||||
snprintk(addr, sizeof(addr), "%s",
|
||||
net_sprint_ipv6_addr(&NET_IPV6_BUF(buf)->dst));
|
||||
|
||||
printk("Received echo reply from %s to %s\n",
|
||||
net_sprint_ipv6_addr(&NET_IPV6_BUF(buf)->src), addr);
|
||||
|
||||
k_sem_give(&ping_timeout);
|
||||
_remove_ipv6_ping_handler();
|
||||
|
||||
return NET_OK;
|
||||
}
|
||||
|
||||
static int _ping_ipv6(char *host)
|
||||
{
|
||||
struct in6_addr ipv6_target;
|
||||
int ret;
|
||||
|
||||
if (net_addr_pton(AF_INET6, host, &ipv6_target) < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
net_icmpv6_register_handler(&ping6_handler);
|
||||
|
||||
ret = net_icmpv6_send_echo_request(net_if_get_default(),
|
||||
&ipv6_target,
|
||||
sys_rand32_get(),
|
||||
sys_rand32_get());
|
||||
if (ret) {
|
||||
_remove_ipv6_ping_handler();
|
||||
} else {
|
||||
printk("Sent a ping to %s\n", host);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
#define _ping_ipv6(...) -EINVAL
|
||||
#define _remove_ipv6_ping_handler()
|
||||
#endif /* CONFIG_NET_IPV6 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
|
||||
static enum net_verdict _handle_ipv4_echo_reply(struct net_buf *buf);
|
||||
|
||||
static struct net_icmpv4_handler ping4_handler = {
|
||||
.type = NET_ICMPV4_ECHO_REPLY,
|
||||
.code = 0,
|
||||
.handler = _handle_ipv4_echo_reply,
|
||||
};
|
||||
|
||||
static inline void _remove_ipv4_ping_handler(void)
|
||||
{
|
||||
net_icmpv4_unregister_handler(&ping4_handler);
|
||||
}
|
||||
|
||||
static enum net_verdict _handle_ipv4_echo_reply(struct net_buf *buf)
|
||||
{
|
||||
char addr[NET_IPV4_ADDR_LEN];
|
||||
|
||||
snprintk(addr, sizeof(addr), "%s",
|
||||
net_sprint_ipv4_addr(&NET_IPV4_BUF(buf)->dst));
|
||||
|
||||
printk("Received echo reply from %s to %s\n",
|
||||
net_sprint_ipv4_addr(&NET_IPV4_BUF(buf)->src), addr);
|
||||
|
||||
k_sem_give(&ping_timeout);
|
||||
_remove_ipv4_ping_handler();
|
||||
|
||||
return NET_OK;
|
||||
}
|
||||
|
||||
static int _ping_ipv4(char *host)
|
||||
{
|
||||
struct in_addr ipv4_target;
|
||||
int ret;
|
||||
|
||||
if (net_addr_pton(AF_INET, host, &ipv4_target) < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
net_icmpv4_register_handler(&ping4_handler);
|
||||
|
||||
ret = net_icmpv4_send_echo_request(net_if_get_default(),
|
||||
&ipv4_target,
|
||||
sys_rand32_get(),
|
||||
sys_rand32_get());
|
||||
if (ret) {
|
||||
_remove_ipv4_ping_handler();
|
||||
} else {
|
||||
printk("Sent a ping to %s\n", host);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
#define _ping_ipv4(...) -EINVAL
|
||||
#define _remove_ipv4_ping_handler()
|
||||
#endif /* CONFIG_NET_IPV4 */
|
||||
#endif /* CONFIG_NET_IPV6 || CONFIG_NET_IPV4 */
|
||||
|
||||
static int shell_cmd_ping(int argc, char *argv[])
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
struct in6_addr ipv6_target;
|
||||
#endif
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
struct in_addr ipv4_target;
|
||||
#endif
|
||||
char *host;
|
||||
int ret;
|
||||
|
||||
|
@ -802,66 +1112,32 @@ static int shell_cmd_ping(int argc, char *argv[])
|
|||
host = argv[2];
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4)
|
||||
ret = net_addr_pton(AF_INET6, host, &ipv6_target);
|
||||
if (ret < 0) {
|
||||
printk("Invalid IPv6 address\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = net_icmpv6_send_echo_request(net_if_get_default(),
|
||||
&ipv6_target,
|
||||
sys_rand32_get(),
|
||||
sys_rand32_get());
|
||||
if (ret < 0) {
|
||||
ret = _ping_ipv6(host);
|
||||
if (!ret) {
|
||||
goto wait_reply;
|
||||
} else if (ret == -EIO) {
|
||||
printk("Cannot send IPv6 ping\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
|
||||
ret = net_addr_pton(AF_INET, host, &ipv4_target);
|
||||
if (ret < 0) {
|
||||
printk("Invalid IPv4 address\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = net_icmpv4_send_echo_request(net_if_get_default(),
|
||||
&ipv4_target,
|
||||
sys_rand32_get(),
|
||||
sys_rand32_get());
|
||||
if (ret < 0) {
|
||||
printk("Cannot send IPv4 ping\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_IPV4)
|
||||
ret = net_addr_pton(AF_INET6, host, &ipv6_target);
|
||||
if (ret < 0) {
|
||||
ret = net_addr_pton(AF_INET, host, &ipv4_target);
|
||||
if (ret < 0) {
|
||||
printk("Invalid IP address\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = net_icmpv4_send_echo_request(net_if_get_default(),
|
||||
&ipv4_target,
|
||||
sys_rand32_get(),
|
||||
sys_rand32_get());
|
||||
if (ret < 0) {
|
||||
ret = _ping_ipv4(host);
|
||||
if (ret) {
|
||||
if (ret == -EIO) {
|
||||
printk("Cannot send IPv4 ping\n");
|
||||
} else if (ret == -EINVAL) {
|
||||
printk("Invalid IP address\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
ret = net_icmpv6_send_echo_request(net_if_get_default(),
|
||||
&ipv6_target,
|
||||
sys_rand32_get(),
|
||||
sys_rand32_get());
|
||||
if (ret < 0) {
|
||||
printk("Cannot send IPv6 ping\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
wait_reply:
|
||||
ret = k_sem_take(&ping_timeout, K_SECONDS(2));
|
||||
if (ret == -EAGAIN) {
|
||||
printk("Ping timeout\n");
|
||||
_remove_ipv6_ping_handler();
|
||||
_remove_ipv4_ping_handler();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -950,6 +1226,288 @@ static int shell_cmd_stats(int argc, char *argv[])
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_TCP)
|
||||
static struct net_context *tcp_ctx;
|
||||
|
||||
#define TCP_CONNECT_TIMEOUT K_SECONDS(5) /* ms */
|
||||
#define TCP_TIMEOUT K_SECONDS(2) /* ms */
|
||||
|
||||
static void tcp_connected(struct net_context *context,
|
||||
int status,
|
||||
void *user_data)
|
||||
{
|
||||
if (status < 0) {
|
||||
printk("TCP connection failed (%d)\n", status);
|
||||
|
||||
net_context_put(context);
|
||||
|
||||
tcp_ctx = NULL;
|
||||
} else {
|
||||
printk("TCP connected\n");
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
static void get_my_ipv6_addr(struct net_if *iface,
|
||||
struct sockaddr *myaddr)
|
||||
{
|
||||
const struct in6_addr *my6addr;
|
||||
|
||||
my6addr = net_if_ipv6_select_src_addr(net_if_get_default(),
|
||||
&net_sin6(myaddr)->sin6_addr);
|
||||
|
||||
memcpy(&net_sin6(myaddr)->sin6_addr, my6addr, sizeof(struct in6_addr));
|
||||
|
||||
net_sin6(myaddr)->sin6_port = 0; /* let the IP stack to select */
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
static void get_my_ipv4_addr(struct net_if *iface,
|
||||
struct sockaddr *myaddr)
|
||||
{
|
||||
/* Just take the first IPv4 address of an interface. */
|
||||
memcpy(&net_sin(myaddr)->sin_addr,
|
||||
&iface->ipv4.unicast[0].address.in_addr,
|
||||
sizeof(struct in_addr));
|
||||
|
||||
net_sin(myaddr)->sin_port = 0; /* let the IP stack to select */
|
||||
}
|
||||
#endif
|
||||
|
||||
static void print_connect_info(int family,
|
||||
struct sockaddr *myaddr,
|
||||
struct sockaddr *addr)
|
||||
{
|
||||
switch (family) {
|
||||
case AF_INET:
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
printk("Connecting from %s:%u ",
|
||||
net_sprint_ipv4_addr(&net_sin(myaddr)->sin_addr),
|
||||
ntohs(net_sin(myaddr)->sin_port));
|
||||
printk("to %s:%u\n",
|
||||
net_sprint_ipv4_addr(&net_sin(addr)->sin_addr),
|
||||
ntohs(net_sin(addr)->sin_port));
|
||||
#else
|
||||
printk("IPv4 not supported\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
printk("Connecting from [%s]:%u ",
|
||||
net_sprint_ipv6_addr(&net_sin6(myaddr)->sin6_addr),
|
||||
ntohs(net_sin6(myaddr)->sin6_port));
|
||||
printk("to [%s]:%u\n",
|
||||
net_sprint_ipv6_addr(&net_sin6(addr)->sin6_addr),
|
||||
ntohs(net_sin6(addr)->sin6_port));
|
||||
#else
|
||||
printk("IPv6 not supported\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("Unknown protocol family (%d)\n", family);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int tcp_connect(char *host, uint16_t port, struct net_context **ctx)
|
||||
{
|
||||
struct sockaddr addr;
|
||||
struct sockaddr myaddr;
|
||||
int addrlen;
|
||||
int family;
|
||||
int ret;
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4)
|
||||
ret = net_addr_pton(AF_INET6, host, &net_sin6(&addr)->sin6_addr);
|
||||
if (ret < 0) {
|
||||
printk("Invalid IPv6 address\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
net_sin6(&addr)->sin6_port = htons(port);
|
||||
addrlen = sizeof(struct sockaddr_in6);
|
||||
get_my_ipv6_addr(net_if_get_default(), &myaddr);
|
||||
family = addr.family = myaddr.family = AF_INET6;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
|
||||
ret = net_addr_pton(AF_INET, host, &net_sin(&addr)->sin_addr);
|
||||
if (ret < 0) {
|
||||
printk("Invalid IPv4 address\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
get_my_ipv4_addr(net_if_get_default(), &myaddr);
|
||||
net_sin(&addr)->sin_port = htons(port);
|
||||
addrlen = sizeof(struct sockaddr_in);
|
||||
family = addr.family = myaddr.family = AF_INET;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_IPV4)
|
||||
ret = net_addr_pton(AF_INET6, host, &net_sin6(&addr)->sin6_addr);
|
||||
if (ret < 0) {
|
||||
ret = net_addr_pton(AF_INET, host, &net_sin(&addr)->sin_addr);
|
||||
if (ret < 0) {
|
||||
printk("Invalid IP address\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
net_sin(&addr)->sin_port = htons(port);
|
||||
addrlen = sizeof(struct sockaddr_in);
|
||||
get_my_ipv4_addr(net_if_get_default(), &myaddr);
|
||||
family = addr.family = myaddr.family = AF_INET;
|
||||
} else {
|
||||
net_sin6(&addr)->sin6_port = htons(port);
|
||||
addrlen = sizeof(struct sockaddr_in6);
|
||||
get_my_ipv6_addr(net_if_get_default(), &myaddr);
|
||||
family = addr.family = myaddr.family = AF_INET6;
|
||||
}
|
||||
#endif
|
||||
|
||||
print_connect_info(family, &myaddr, &addr);
|
||||
|
||||
ret = net_context_get(family, SOCK_STREAM, IPPROTO_TCP, ctx);
|
||||
if (ret < 0) {
|
||||
printk("Cannot get TCP context (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = net_context_bind(*ctx, &myaddr, addrlen);
|
||||
if (ret < 0) {
|
||||
printk("Cannot bind TCP (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return net_context_connect(*ctx, &addr, addrlen, tcp_connected,
|
||||
K_NO_WAIT, NULL);
|
||||
}
|
||||
|
||||
static void tcp_sent_cb(struct net_context *context,
|
||||
int status,
|
||||
void *token,
|
||||
void *user_data)
|
||||
{
|
||||
printk("Message sent\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
static int shell_cmd_tcp(int argc, char *argv[])
|
||||
{
|
||||
#if defined(CONFIG_NET_TCP)
|
||||
int arg = 1;
|
||||
int ret;
|
||||
|
||||
if (strcmp(argv[0], "tcp")) {
|
||||
arg++;
|
||||
}
|
||||
|
||||
if (argv[arg]) {
|
||||
if (!strcmp(argv[arg], "connect")) {
|
||||
/* tcp connect <ip> port */
|
||||
char *ip;
|
||||
uint16_t port;
|
||||
|
||||
if (tcp_ctx && net_context_is_used(tcp_ctx)) {
|
||||
printk("Already connected\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!argv[++arg]) {
|
||||
printk("Peer IP address missing.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ip = argv[arg];
|
||||
|
||||
if (!argv[++arg]) {
|
||||
printk("Peer port missing.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
port = strtol(argv[arg], NULL, 10);
|
||||
|
||||
return tcp_connect(ip, port, &tcp_ctx);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[arg], "send")) {
|
||||
/* tcp send <data> */
|
||||
struct net_buf *buf;
|
||||
|
||||
if (!tcp_ctx || !net_context_is_used(tcp_ctx)) {
|
||||
printk("Not connected\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!argv[++arg]) {
|
||||
printk("No data to send.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf = net_nbuf_get_tx(tcp_ctx, TCP_TIMEOUT);
|
||||
if (!buf) {
|
||||
printk("Out of bufs, msg cannot be sent.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = net_nbuf_append(buf, strlen(argv[arg]),
|
||||
argv[arg], TCP_TIMEOUT);
|
||||
if (!ret) {
|
||||
printk("Cannot build msg (out of bufs)\n");
|
||||
net_nbuf_unref(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = net_context_send(buf, tcp_sent_cb, TCP_TIMEOUT,
|
||||
NULL, NULL);
|
||||
if (ret < 0) {
|
||||
printk("Cannot send msg (%d)\n", ret);
|
||||
net_nbuf_unref(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[arg], "close")) {
|
||||
/* tcp close */
|
||||
if (!tcp_ctx || !net_context_is_used(tcp_ctx)) {
|
||||
printk("Not connected\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = net_context_put(tcp_ctx);
|
||||
if (ret < 0) {
|
||||
printk("Cannot close the connection (%d)\n",
|
||||
ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printk("Connection closed.\n");
|
||||
tcp_ctx = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
printk("Unknown command '%s'\n", argv[arg]);
|
||||
goto usage;
|
||||
} else {
|
||||
printk("Invalid command.\n");
|
||||
usage:
|
||||
printk("Usage:\n");
|
||||
printk("\ttcp connect <ipaddr> port\n");
|
||||
printk("\ttcp send <data>\n");
|
||||
printk("\ttcp close\n");
|
||||
}
|
||||
#else
|
||||
printk("TCP not enabled.\n");
|
||||
#endif /* CONFIG_NET_TCP */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shell_cmd_help(int argc, char *argv[])
|
||||
{
|
||||
ARG_UNUSED(argc);
|
||||
|
@ -958,6 +1516,10 @@ static int shell_cmd_help(int argc, char *argv[])
|
|||
/* Keep the commands in alphabetical order */
|
||||
printk("net allocs\n\tPrint network buffer allocations\n");
|
||||
printk("net conn\n\tPrint information about network connections\n");
|
||||
printk("net dns\n\tShow how DNS is configured\n");
|
||||
printk("net dns cancel\n\tCancel all pending requests\n");
|
||||
printk("net dns <hostname> [A or AAAA]\n\tQuery IPv4 address (default)"
|
||||
" or IPv6 address for a host name\n");
|
||||
printk("net iface\n\tPrint information about network interfaces\n");
|
||||
printk("net mem\n\tPrint network buffer information\n");
|
||||
printk("net nbr\n\tPrint neighbor information\n");
|
||||
|
@ -966,6 +1528,9 @@ static int shell_cmd_help(int argc, char *argv[])
|
|||
printk("net route\n\tShow network routes\n");
|
||||
printk("net stacks\n\tShow network stacks information\n");
|
||||
printk("net stats\n\tShow network statistics\n");
|
||||
printk("net tcp connect <ip> port\n\tConnect to TCP peer\n");
|
||||
printk("net tcp send <data>\n\tSend data to peer using TCP\n");
|
||||
printk("net tcp close\n\tClose TCP connection\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -973,6 +1538,7 @@ static struct shell_cmd net_commands[] = {
|
|||
/* Keep the commands in alphabetical order */
|
||||
{ "allocs", shell_cmd_allocs, NULL },
|
||||
{ "conn", shell_cmd_conn, NULL },
|
||||
{ "dns", shell_cmd_dns, NULL },
|
||||
{ "help", shell_cmd_help, NULL },
|
||||
{ "iface", shell_cmd_iface, NULL },
|
||||
{ "mem", shell_cmd_mem, NULL },
|
||||
|
@ -981,6 +1547,7 @@ static struct shell_cmd net_commands[] = {
|
|||
{ "route", shell_cmd_route, NULL },
|
||||
{ "stacks", shell_cmd_stacks, NULL },
|
||||
{ "stats", shell_cmd_stats, NULL },
|
||||
{ "tcp", shell_cmd_tcp, NULL },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -671,6 +671,77 @@ net_route_mcast_lookup(struct in6_addr *group)
|
|||
}
|
||||
#endif /* CONFIG_NET_ROUTE_MCAST */
|
||||
|
||||
bool net_route_get_info(struct in6_addr *dst,
|
||||
struct net_route_entry **route,
|
||||
struct in6_addr **nexthop)
|
||||
{
|
||||
struct net_if_router *router;
|
||||
|
||||
*route = net_route_lookup(NULL, dst);
|
||||
if (*route) {
|
||||
*nexthop = net_route_get_nexthop(*route);
|
||||
if (!*nexthop) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
/* No specific route to this host, use the default
|
||||
* route instead.
|
||||
*/
|
||||
router = net_if_ipv6_router_find_default(NULL, dst);
|
||||
if (!router) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*nexthop = &router->address.in6_addr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int net_route_packet(struct net_buf *buf, struct net_route_entry *route,
|
||||
struct in6_addr *nexthop)
|
||||
{
|
||||
struct net_linkaddr_storage *lladdr;
|
||||
struct net_nbr *nbr;
|
||||
|
||||
if (route) {
|
||||
net_nbuf_set_iface(buf, route->iface);
|
||||
}
|
||||
|
||||
nbr = net_ipv6_nbr_lookup(net_nbuf_iface(buf), nexthop);
|
||||
if (!nbr) {
|
||||
NET_DBG("Cannot find %s neighbor.",
|
||||
net_sprint_ipv6_addr(nexthop));
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
lladdr = net_nbr_get_lladdr(nbr->idx);
|
||||
if (!lladdr) {
|
||||
NET_DBG("Cannot find %s neighbor link layer address.",
|
||||
net_sprint_ipv6_addr(nexthop));
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
net_nbuf_set_forwarding(buf, true);
|
||||
|
||||
/* Set the destination and source ll address in the packet.
|
||||
* We set the destination address to be the nexthop recipient.
|
||||
*/
|
||||
net_nbuf_ll_src(buf)->addr = net_nbuf_ll_if(buf)->addr;
|
||||
net_nbuf_ll_src(buf)->type = net_nbuf_ll_if(buf)->type;
|
||||
net_nbuf_ll_src(buf)->len = net_nbuf_ll_if(buf)->len;
|
||||
|
||||
net_nbuf_ll_dst(buf)->addr = lladdr->addr;
|
||||
net_nbuf_ll_dst(buf)->type = lladdr->type;
|
||||
net_nbuf_ll_dst(buf)->len = lladdr->len;
|
||||
|
||||
return net_send_data(buf);
|
||||
}
|
||||
|
||||
void net_route_init(void)
|
||||
{
|
||||
NET_DBG("Allocated %d routing entries (%zu bytes)",
|
||||
|
|
|
@ -233,6 +233,31 @@ net_route_mcast_lookup(struct in6_addr *group);
|
|||
|
||||
#endif /* CONFIG_NET_ROUTE_MCAST */
|
||||
|
||||
/**
|
||||
* @brief Return a route to destination via some intermediate host.
|
||||
*
|
||||
* @param dst Destination IPv6 address
|
||||
* @param route Route entry to destination is returned.
|
||||
* @param nexthop Next hop neighbor IPv6 address is returned.
|
||||
*
|
||||
* @return True if there is a route to the destination, False otherwise
|
||||
*/
|
||||
bool net_route_get_info(struct in6_addr *dst,
|
||||
struct net_route_entry **route,
|
||||
struct in6_addr **nexthop);
|
||||
|
||||
/**
|
||||
* @brief Send the network packet to network via some intermediate host.
|
||||
*
|
||||
* @param buf Network buffer to send.
|
||||
* @param route Route entry to destination.
|
||||
* @param nexthop Next hop neighbor IPv6 address.
|
||||
*
|
||||
* @return 0 if there was no error, <0 if the packet could not be sent.
|
||||
*/
|
||||
int net_route_packet(struct net_buf *buf, struct net_route_entry *route,
|
||||
struct in6_addr *nexthop);
|
||||
|
||||
#else /* CONFIG_NET_ROUTE */
|
||||
#define net_route_init(...)
|
||||
#endif /* CONFIG_NET_ROUTE */
|
||||
|
|
|
@ -2700,7 +2700,7 @@ static enum net_verdict handle_dio(struct net_buf *buf)
|
|||
&NET_IPV6_BUF(buf)->src,
|
||||
net_nbuf_ll_src(buf),
|
||||
0,
|
||||
NET_NBR_REACHABLE);
|
||||
NET_IPV6_NBR_STATE_REACHABLE);
|
||||
if (!nbr) {
|
||||
NET_DBG("Cannot add neighbor by DIO");
|
||||
goto out;
|
||||
|
@ -2719,7 +2719,7 @@ static enum net_verdict handle_dio(struct net_buf *buf)
|
|||
frag = net_nbuf_read_u8(frag, pos, &pos, &dio.version);
|
||||
frag = net_nbuf_read_be16(frag, pos, &pos, &dio.rank);
|
||||
|
||||
NET_DBG("Incoming DIO len %d id %d ver %d rank %d",
|
||||
NET_DBG("Incoming DIO len %zu id %d ver %d rank %d",
|
||||
net_buf_frags_len(buf) - offset,
|
||||
dio.instance_id, dio.version, dio.rank);
|
||||
|
||||
|
@ -3080,8 +3080,13 @@ static inline int dao_forward(struct net_if *iface,
|
|||
|
||||
net_ipaddr_copy(&NET_IPV6_BUF(buf)->dst, dst);
|
||||
|
||||
net_nbuf_set_ip_hdr_len(buf, sizeof(struct net_ipv6_hdr));
|
||||
net_nbuf_set_family(buf, AF_INET6);
|
||||
net_nbuf_set_iface(buf, iface);
|
||||
|
||||
NET_ICMP_BUF(buf)->chksum = 0;
|
||||
NET_ICMP_BUF(buf)->chksum = ~net_calc_chksum_icmpv6(buf);
|
||||
|
||||
ret = net_send_data(buf);
|
||||
if (ret >= 0) {
|
||||
net_stats_update_icmp_sent();
|
||||
|
@ -3093,13 +3098,12 @@ static inline int dao_forward(struct net_if *iface,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int dao_ack_send(struct net_buf *orig,
|
||||
struct net_rpl_instance *instance,
|
||||
static int dao_ack_send(struct in6_addr *src,
|
||||
struct in6_addr *dst,
|
||||
struct net_if *iface,
|
||||
struct net_rpl_instance *instance,
|
||||
uint8_t sequence)
|
||||
{
|
||||
struct in6_addr *src = &NET_IPV6_BUF(orig)->dst;
|
||||
struct net_if *iface = net_nbuf_iface(orig);
|
||||
struct net_buf *buf;
|
||||
int ret;
|
||||
|
||||
|
@ -3143,27 +3147,38 @@ static int dao_ack_send(struct net_buf *orig,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void forwarding_dao(struct net_rpl_instance *instance,
|
||||
struct net_rpl_dag *dag,
|
||||
struct in6_addr *dao_sender,
|
||||
struct net_buf *buf,
|
||||
uint8_t sequence,
|
||||
uint8_t flags,
|
||||
char *str)
|
||||
static int forwarding_dao(struct net_rpl_instance *instance,
|
||||
struct net_rpl_dag *dag,
|
||||
struct net_buf *buf,
|
||||
uint8_t sequence,
|
||||
uint8_t flags,
|
||||
char *str)
|
||||
{
|
||||
struct in6_addr *paddr;
|
||||
struct in6_addr src;
|
||||
struct in6_addr dst;
|
||||
int r = -EINVAL;
|
||||
|
||||
paddr = net_rpl_get_parent_addr(instance->iface,
|
||||
dag->preferred_parent);
|
||||
if (paddr) {
|
||||
NET_DBG("%s %s", str, net_sprint_ipv6_addr(paddr));
|
||||
|
||||
dao_forward(dag->instance->iface, buf, paddr);
|
||||
net_ipaddr_copy(&src, &NET_IPV6_BUF(buf)->src);
|
||||
net_ipaddr_copy(&dst, &NET_IPV6_BUF(buf)->dst);
|
||||
|
||||
r = dao_forward(dag->instance->iface, buf, paddr);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
if (flags & NET_RPL_DAO_K_FLAG) {
|
||||
dao_ack_send(buf, instance, dao_sender, sequence);
|
||||
r = dao_ack_send(&dst, &src, net_nbuf_iface(buf),
|
||||
instance, sequence);
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static enum net_verdict handle_dao(struct net_buf *buf)
|
||||
|
@ -3187,6 +3202,7 @@ static enum net_verdict handle_dao(struct net_buf *buf)
|
|||
uint8_t flags;
|
||||
uint8_t subopt_type;
|
||||
int len;
|
||||
int r = -EINVAL;
|
||||
|
||||
net_rpl_info(buf, "Destination Advertisement Object");
|
||||
|
||||
|
@ -3300,8 +3316,8 @@ static enum net_verdict handle_dao(struct net_buf *buf)
|
|||
addr.s6_addr);
|
||||
break;
|
||||
case NET_RPL_OPTION_TRANSIT:
|
||||
/* The path sequence and control are ignored. */
|
||||
frag = net_nbuf_skip(frag, pos, &pos, 2);
|
||||
/* The flags, path sequence and control are ignored. */
|
||||
frag = net_nbuf_skip(frag, pos, &pos, 3);
|
||||
frag = net_nbuf_read_u8(frag, pos, &pos, &lifetime);
|
||||
break;
|
||||
}
|
||||
|
@ -3350,15 +3366,19 @@ static enum net_verdict handle_dao(struct net_buf *buf)
|
|||
* if we have one.
|
||||
*/
|
||||
if (dag->preferred_parent) {
|
||||
forwarding_dao(instance, dag, dao_sender,
|
||||
buf, sequence, flags,
|
||||
r = forwarding_dao(instance, dag,
|
||||
buf, sequence, flags,
|
||||
#if defined(CONFIG_NET_DEBUG_RPL)
|
||||
"Forwarding no-path DAO to "
|
||||
"parent"
|
||||
"Forwarding no-path DAO to "
|
||||
"parent"
|
||||
#else
|
||||
""
|
||||
""
|
||||
#endif
|
||||
);
|
||||
);
|
||||
if (r >= 0) {
|
||||
net_nbuf_unref(buf);
|
||||
return NET_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3371,7 +3391,7 @@ static enum net_verdict handle_dao(struct net_buf *buf)
|
|||
if (!nbr) {
|
||||
nbr = net_ipv6_nbr_add(net_nbuf_iface(buf), dao_sender,
|
||||
net_nbuf_ll_src(buf), false,
|
||||
NET_NBR_REACHABLE);
|
||||
NET_IPV6_NBR_STATE_REACHABLE);
|
||||
if (nbr) {
|
||||
/* Set reachable timer */
|
||||
net_ipv6_nbr_set_reachable_timer(net_nbuf_iface(buf),
|
||||
|
@ -3416,15 +3436,18 @@ fwd_dao:
|
|||
|
||||
if (learned_from == NET_RPL_ROUTE_UNICAST_DAO) {
|
||||
if (dag->preferred_parent) {
|
||||
forwarding_dao(instance, dag,
|
||||
dao_sender, buf,
|
||||
sequence, flags,
|
||||
r = forwarding_dao(instance, dag,
|
||||
buf, sequence, flags,
|
||||
#if defined(CONFIG_NET_DEBUG_RPL)
|
||||
"Forwarding DAO to parent"
|
||||
"Forwarding DAO to parent"
|
||||
#else
|
||||
""
|
||||
""
|
||||
#endif
|
||||
);
|
||||
);
|
||||
if (r >= 0) {
|
||||
net_nbuf_unref(buf);
|
||||
return NET_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3436,9 +3459,12 @@ static enum net_verdict handle_dao_ack(struct net_buf *buf)
|
|||
{
|
||||
net_rpl_info(buf, "Destination Advertisement Object Ack");
|
||||
|
||||
/* TODO: Handle DAO ACK properly */
|
||||
net_stats_update_rpl_dao_ack_recv();
|
||||
|
||||
return NET_DROP;
|
||||
net_nbuf_unref(buf);
|
||||
|
||||
return NET_OK;
|
||||
}
|
||||
|
||||
static struct net_icmpv6_handler dodag_info_solicitation_handler = {
|
||||
|
@ -3992,7 +4018,7 @@ void net_rpl_init(void)
|
|||
static struct net_if_link_cb link_cb;
|
||||
struct in6_addr addr;
|
||||
|
||||
NET_DBG("Allocated %d routing entries (%d bytes)",
|
||||
NET_DBG("Allocated %d routing entries (%zu bytes)",
|
||||
CONFIG_NET_IPV6_MAX_NEIGHBORS,
|
||||
sizeof(net_rpl_neighbor_pool));
|
||||
|
||||
|
|
|
@ -71,13 +71,14 @@ static char upper_if_set(char chr, bool set)
|
|||
static void net_tcp_trace(struct net_buf *buf, struct net_tcp *tcp)
|
||||
{
|
||||
uint8_t flags = NET_TCP_FLAGS(buf);
|
||||
uint32_t rel_ack;
|
||||
uint32_t rel_ack, ack;
|
||||
|
||||
ack = sys_get_be32(NET_TCP_BUF(buf)->ack);
|
||||
|
||||
if (!tcp->sent_ack) {
|
||||
rel_ack = 0;
|
||||
} else {
|
||||
rel_ack = sys_get_be32(NET_TCP_BUF(buf)->ack) ?
|
||||
sys_get_be32(NET_TCP_BUF(buf)->ack) - tcp->sent_ack : 0;
|
||||
rel_ack = ack ? ack - tcp->sent_ack : 0;
|
||||
}
|
||||
|
||||
NET_DBG("buf %p src %u dst %u seq 0x%04x ack 0x%04x (%u) "
|
||||
|
@ -86,7 +87,7 @@ static void net_tcp_trace(struct net_buf *buf, struct net_tcp *tcp)
|
|||
ntohs(NET_TCP_BUF(buf)->src_port),
|
||||
ntohs(NET_TCP_BUF(buf)->dst_port),
|
||||
sys_get_be32(NET_TCP_BUF(buf)->seq),
|
||||
sys_get_be32(NET_TCP_BUF(buf)->ack),
|
||||
ack,
|
||||
/* This tells how many bytes we are acking now */
|
||||
rel_ack,
|
||||
upper_if_set('u', flags & NET_TCP_URG),
|
||||
|
|
|
@ -11,10 +11,11 @@ config DNS_RESOLVER
|
|||
help
|
||||
This option enables the DNS client side support for Zephyr
|
||||
|
||||
if DNS_RESOLVER
|
||||
|
||||
config DNS_RESOLVER_ADDITIONAL_BUF_CTR
|
||||
int
|
||||
prompt "Additional DNS buffers"
|
||||
depends on DNS_RESOLVER
|
||||
default 0
|
||||
help
|
||||
Number of additional buffers available for the DNS resolver.
|
||||
|
@ -25,7 +26,6 @@ config DNS_RESOLVER_ADDITIONAL_BUF_CTR
|
|||
config DNS_RESOLVER_ADDITIONAL_QUERIES
|
||||
int
|
||||
prompt "Additional DNS queries"
|
||||
depends on DNS_RESOLVER
|
||||
range 0 2
|
||||
default 1
|
||||
help
|
||||
|
@ -33,3 +33,79 @@ config DNS_RESOLVER_ADDITIONAL_QUERIES
|
|||
generate when the RR ANSWER only contains CNAME(s).
|
||||
The maximum value of this variable is constrained to avoid
|
||||
'alias loops'.
|
||||
|
||||
config DNS_RESOLVER_MAX_SERVERS
|
||||
int "Number of DNS server addresses"
|
||||
range 1 NET_MAX_CONTEXTS
|
||||
default 1
|
||||
help
|
||||
Max number of DNS servers that we can connect to. Normally one
|
||||
DNS server is enough. Each connection to DNS server will use one
|
||||
network context.
|
||||
|
||||
menuconfig DNS_SERVER_IP_ADDRESSES
|
||||
bool "Set DNS server IP addresses"
|
||||
default n
|
||||
help
|
||||
Allow DNS IP addresses to be set in config file for
|
||||
networking applications.
|
||||
|
||||
if DNS_SERVER_IP_ADDRESSES
|
||||
|
||||
config DNS_SERVER1
|
||||
string "DNS server 1"
|
||||
default ""
|
||||
help
|
||||
DNS server IP address 1. The address can be either IPv4 or IPv6
|
||||
address. An optional port number can be given.
|
||||
Following syntax is supported:
|
||||
192.0.2.1
|
||||
192.0.2.1:5353
|
||||
2001:db8::1
|
||||
[2001:db8::1]:5353
|
||||
It is not mandatory to use this Kconfig option at all.
|
||||
The one calling dns_resolve_init() can use this option or not
|
||||
to populate the server list. If the DNS server addresses are
|
||||
set here, then we automatically create default DNS context
|
||||
for the user.
|
||||
|
||||
config DNS_SERVER2
|
||||
string "DNS server 2"
|
||||
default ""
|
||||
help
|
||||
See help in "DNS server 1" option.
|
||||
|
||||
config DNS_SERVER3
|
||||
string "DNS server 3"
|
||||
default ""
|
||||
help
|
||||
See help in "DNS server 1" option.
|
||||
|
||||
config DNS_SERVER4
|
||||
string "DNS server 4"
|
||||
default ""
|
||||
help
|
||||
See help in "DNS server 1" option.
|
||||
|
||||
config DNS_SERVER5
|
||||
string "DNS server 5"
|
||||
default ""
|
||||
help
|
||||
See help in "DNS server 1" option.
|
||||
|
||||
endif # DNS_SERVER_IP_ADDRESSES
|
||||
|
||||
config DNS_NUM_CONCUR_QUERIES
|
||||
int "Number of simultaneous DNS queries per one DNS context"
|
||||
default 1
|
||||
help
|
||||
This defines how many concurrent DNS queries can be generated using
|
||||
same DNS context. Normally 1 is a good default value.
|
||||
|
||||
config NET_DEBUG_DNS_RESOLVE
|
||||
bool "Debug DNS resolver"
|
||||
default n
|
||||
help
|
||||
Enables DNS resolver code to output debug messages
|
||||
|
||||
endif # DNS_RESOLVER
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
ccflags-y += -I$(srctree)/subsys/net/lib/dns
|
||||
|
||||
obj-y := dns_pack.o
|
||||
obj-y += dns_client.o
|
||||
|
||||
obj-$(CONFIG_DNS_RESOLVER) += dns_client.o
|
||||
obj-$(CONFIG_DNS_RESOLVER) += resolve.o
|
||||
|
|
907
subsys/net/lib/dns/resolve.c
Normal file
907
subsys/net/lib/dns/resolve.c
Normal file
|
@ -0,0 +1,907 @@
|
|||
/** @file
|
||||
* @brief DNS resolve API
|
||||
*
|
||||
* An API for applications to do DNS query.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_NET_DEBUG_DNS_RESOLVE)
|
||||
#define SYS_LOG_DOMAIN "dns/resolve"
|
||||
#define NET_LOG_ENABLED 1
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <net/net_ip.h>
|
||||
#include <net/nbuf.h>
|
||||
#include <net/dns_resolve.h>
|
||||
#include "dns_pack.h"
|
||||
|
||||
static int dns_write(struct dns_resolve_context *ctx,
|
||||
int server_idx,
|
||||
int query_idx,
|
||||
struct net_buf *dns_data,
|
||||
struct net_buf *dns_qname);
|
||||
|
||||
#define DNS_BUF_TIMEOUT 500 /* ms */
|
||||
|
||||
/* RFC 1035, 3.1. Name space definitions
|
||||
* To simplify implementations, the total length of a domain name (i.e.,
|
||||
* label octets and label length octets) is restricted to 255 octets or
|
||||
* less.
|
||||
*/
|
||||
#define DNS_MAX_NAME_LEN 255
|
||||
|
||||
#define DNS_QUERY_MAX_SIZE (DNS_MSG_HEADER_SIZE + DNS_MAX_NAME_LEN + \
|
||||
DNS_QTYPE_LEN + DNS_QCLASS_LEN)
|
||||
|
||||
/* This value is recommended by RFC 1035 */
|
||||
#define DNS_RESOLVER_MAX_BUF_SIZE 512
|
||||
#define DNS_RESOLVER_MIN_BUF 1
|
||||
#define DNS_RESOLVER_BUF_CTR (DNS_RESOLVER_MIN_BUF + \
|
||||
CONFIG_DNS_RESOLVER_ADDITIONAL_BUF_CTR)
|
||||
|
||||
/* Compressed RR uses a pointer to another RR. So, min size is 12 bytes without
|
||||
* considering RR payload.
|
||||
* See https://tools.ietf.org/html/rfc1035#section-4.1.4
|
||||
*/
|
||||
#define DNS_ANSWER_PTR_LEN 12
|
||||
|
||||
/* See dns_unpack_answer, and also see:
|
||||
* https://tools.ietf.org/html/rfc1035#section-4.1.2
|
||||
*/
|
||||
#define DNS_QUERY_POS 0x0c
|
||||
|
||||
#define DNS_IPV4_LEN sizeof(struct in_addr)
|
||||
#define DNS_IPV6_LEN sizeof(struct in6_addr)
|
||||
|
||||
NET_BUF_POOL_DEFINE(dns_msg_pool, DNS_RESOLVER_BUF_CTR,
|
||||
DNS_RESOLVER_MAX_BUF_SIZE, 0, NULL);
|
||||
|
||||
NET_BUF_POOL_DEFINE(dns_qname_pool, DNS_RESOLVER_BUF_CTR, DNS_MAX_NAME_LEN,
|
||||
0, NULL);
|
||||
|
||||
static struct dns_resolve_context dns_default_ctx;
|
||||
|
||||
int dns_resolve_init(struct dns_resolve_context *ctx, const char *servers[])
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
struct sockaddr_in6 local_addr6 = {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_port = 0,
|
||||
};
|
||||
#endif
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
struct sockaddr_in local_addr4 = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = 0,
|
||||
};
|
||||
#endif
|
||||
struct sockaddr *local_addr = NULL;
|
||||
socklen_t addr_len = 0;
|
||||
int i = 0, idx = 0;
|
||||
uint16_t port = 0;
|
||||
int ret, count;
|
||||
|
||||
if (!ctx) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (!servers || !*servers) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (ctx->is_used) {
|
||||
return -ENOTEMPTY;
|
||||
}
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
for (i = 0; i < CONFIG_DNS_RESOLVER_MAX_SERVERS && servers[i]; i++) {
|
||||
int j;
|
||||
char *ptr;
|
||||
|
||||
if (*servers[i] == '[') {
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
/* IPv6 address with port number */
|
||||
struct in6_addr *addr;
|
||||
char server[INET6_ADDRSTRLEN + 1];
|
||||
int end;
|
||||
|
||||
ptr = strstr(servers[i], "]:");
|
||||
if (!ptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
end = min(INET6_ADDRSTRLEN, ptr - (servers[i] + 1));
|
||||
memcpy(server, servers[i] + 1, end);
|
||||
server[end] = '\0';
|
||||
|
||||
addr = &net_sin6(&ctx->servers[idx].dns_server)->
|
||||
sin6_addr;
|
||||
|
||||
ret = net_addr_pton(AF_INET6, server, addr);
|
||||
if (ret < 0 && ret != -EINVAL) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret == -EINVAL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
port = strtol(ptr + 2, NULL, 10);
|
||||
|
||||
net_sin6(&ctx->servers[idx].dns_server)->sin6_port =
|
||||
htons(port);
|
||||
|
||||
ctx->servers[idx++].dns_server.family = AF_INET6;
|
||||
#endif /* CONFIG_NET_IPV6 */
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
count = j = 0;
|
||||
while (servers[i][j]) {
|
||||
if (servers[i][j] == ':') {
|
||||
count++;
|
||||
}
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
if (count == 1) {
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
/* IPv4 address with port number */
|
||||
char server[NET_IPV4_ADDR_LEN + 1];
|
||||
struct in_addr *addr;
|
||||
int end;
|
||||
|
||||
ptr = strstr(servers[i], ":");
|
||||
if (!ptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
end = min(NET_IPV4_ADDR_LEN, ptr - servers[i]);
|
||||
memcpy(server, servers[i], end);
|
||||
server[end] = '\0';
|
||||
|
||||
addr = &net_sin(&ctx->servers[idx].dns_server)->
|
||||
sin_addr;
|
||||
ret = net_addr_pton(AF_INET, server, addr);
|
||||
if (ret < 0 && ret != -EINVAL) {
|
||||
NET_ERR("Cannot set DNS server %s", server);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret == -EINVAL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
port = strtol(ptr + 1, NULL, 10);
|
||||
|
||||
net_sin(&ctx->servers[idx].dns_server)->sin_port =
|
||||
htons(port);
|
||||
|
||||
ctx->servers[idx++].dns_server.family = AF_INET;
|
||||
#endif /* CONFIG_NET_IPV4 */
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_IPV6)
|
||||
/* First try IPv4 address */
|
||||
ret = net_addr_pton(AF_INET, servers[i],
|
||||
&net_sin(&ctx->servers[idx].dns_server)->
|
||||
sin_addr);
|
||||
if (ret < 0 && ret != -EINVAL) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
net_sin(&ctx->servers[idx].dns_server)->sin_port =
|
||||
htons(53);
|
||||
|
||||
ctx->servers[idx++].dns_server.family = AF_INET;
|
||||
|
||||
} else if (ret == -EINVAL) {
|
||||
/* Then the address must be IPv6 based */
|
||||
ret = net_addr_pton(AF_INET6, servers[i],
|
||||
&net_sin6(&ctx->servers[idx].dns_server)->
|
||||
sin6_addr);
|
||||
if (ret < 0 && ret != -EINVAL) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret == -EINVAL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
net_sin6(&ctx->servers[idx].dns_server)->sin6_port =
|
||||
htons(53);
|
||||
|
||||
ctx->servers[idx++].dns_server.family = AF_INET6;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
|
||||
ret = net_addr_pton(AF_INET, servers[i],
|
||||
&net_sin(&ctx->servers[idx].dns_server)->
|
||||
sin_addr);
|
||||
if (ret < 0 && ret != -EINVAL) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret == -EINVAL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
net_sin(&ctx->servers[idx].dns_server)->sin_port = htons(53);
|
||||
ctx->servers[idx++].dns_server.family = AF_INET;
|
||||
#endif /* IPv4 && !IPv6 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4)
|
||||
ret = net_addr_pton(AF_INET6, servers[i],
|
||||
&net_sin6(&ctx->servers[idx].dns_server)->sin6_addr);
|
||||
if (ret < 0 && ret != -EINVAL) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret == -EINVAL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
net_sin6(&ctx->servers[idx].dns_server)->sin6_port = htons(53);
|
||||
ctx->servers[idx++].dns_server.family = AF_INET6;
|
||||
#endif /* IPv6 && !IPv4 */
|
||||
}
|
||||
|
||||
for (i = 0, count = 0; i < CONFIG_DNS_RESOLVER_MAX_SERVERS &&
|
||||
ctx->servers[i].dns_server.family; i++) {
|
||||
|
||||
if (ctx->servers[i].dns_server.family == AF_INET6) {
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
local_addr = (struct sockaddr *)&local_addr6;
|
||||
addr_len = sizeof(struct sockaddr_in6);
|
||||
#else
|
||||
continue;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ctx->servers[i].dns_server.family == AF_INET) {
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
local_addr = (struct sockaddr *)&local_addr4;
|
||||
addr_len = sizeof(struct sockaddr_in);
|
||||
#else
|
||||
continue;
|
||||
#endif
|
||||
}
|
||||
|
||||
ret = net_context_get(ctx->servers[i].dns_server.family,
|
||||
SOCK_DGRAM, IPPROTO_UDP,
|
||||
&ctx->servers[i].net_ctx);
|
||||
if (ret < 0) {
|
||||
NET_DBG("Cannot get net_context (%d)", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = net_context_bind(ctx->servers[i].net_ctx,
|
||||
local_addr, addr_len);
|
||||
if (ret < 0) {
|
||||
NET_DBG("Cannot bind DNS context (%d)", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
/* No servers defined */
|
||||
NET_DBG("No DNS servers defined.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ctx->is_used = true;
|
||||
ctx->buf_timeout = DNS_BUF_TIMEOUT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int get_cb_slot(struct dns_resolve_context *ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) {
|
||||
if (!ctx->queries[i].cb) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int get_slot_by_id(struct dns_resolve_context *ctx,
|
||||
uint16_t dns_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) {
|
||||
if (ctx->queries[i].cb && ctx->queries[i].id == dns_id) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int dns_read(struct dns_resolve_context *ctx,
|
||||
struct net_buf *buf,
|
||||
struct net_buf *dns_data,
|
||||
uint16_t *dns_id,
|
||||
struct net_buf *dns_cname,
|
||||
struct dns_addrinfo *info)
|
||||
{
|
||||
/* Helper struct to track the dns msg received from the server */
|
||||
struct dns_msg_t dns_msg;
|
||||
uint32_t ttl; /* RR ttl, so far it is not passed to caller */
|
||||
uint8_t *src, *addr;
|
||||
int address_size;
|
||||
/* index that points to the current answer being analyzed */
|
||||
int answer_ptr;
|
||||
int data_len;
|
||||
int offset;
|
||||
int items;
|
||||
int ret;
|
||||
int server_idx, query_idx;
|
||||
|
||||
data_len = min(net_nbuf_appdatalen(buf), DNS_RESOLVER_MAX_BUF_SIZE);
|
||||
offset = net_buf_frags_len(buf) - data_len;
|
||||
|
||||
/* TODO: Instead of this temporary copy, just use the net_buf directly.
|
||||
*/
|
||||
ret = net_nbuf_linear_copy(dns_data, buf, offset, data_len);
|
||||
if (ret < 0) {
|
||||
ret = DNS_EAI_MEMORY;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
dns_msg.msg = dns_data->data;
|
||||
dns_msg.msg_size = data_len;
|
||||
|
||||
/* The dns_unpack_response_header() has design flaw as it expects
|
||||
* dns id to be given instead of returning the id to the caller.
|
||||
* In our case we would like to get it returned instead so that we
|
||||
* can match the DNS query that we sent. When dns_read() is called,
|
||||
* we do not know what the DNS id is yet.
|
||||
*/
|
||||
*dns_id = dns_unpack_header_id(dns_msg.msg);
|
||||
|
||||
query_idx = get_slot_by_id(ctx, *dns_id);
|
||||
if (query_idx < 0) {
|
||||
ret = DNS_EAI_SYSTEM;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
if (dns_header_rcode(dns_msg.msg) == DNS_HEADER_REFUSED) {
|
||||
ret = DNS_EAI_FAIL;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
ret = dns_unpack_response_header(&dns_msg, *dns_id);
|
||||
if (ret < 0) {
|
||||
ret = DNS_EAI_FAIL;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
if (dns_header_qdcount(dns_msg.msg) != 1) {
|
||||
ret = DNS_EAI_FAIL;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
ret = dns_unpack_response_query(&dns_msg);
|
||||
if (ret < 0) {
|
||||
ret = DNS_EAI_FAIL;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
if (ctx->queries[query_idx].query_type == DNS_QUERY_TYPE_A) {
|
||||
address_size = DNS_IPV4_LEN;
|
||||
addr = (uint8_t *)&net_sin(&info->ai_addr)->sin_addr;
|
||||
info->ai_family = AF_INET;
|
||||
} else if (ctx->queries[query_idx].query_type == DNS_QUERY_TYPE_AAAA) {
|
||||
address_size = DNS_IPV6_LEN;
|
||||
addr = (uint8_t *)&net_sin6(&info->ai_addr)->sin6_addr;
|
||||
info->ai_family = AF_INET6;
|
||||
} else {
|
||||
ret = DNS_EAI_FAMILY;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
/* while loop to traverse the response */
|
||||
answer_ptr = DNS_QUERY_POS;
|
||||
items = 0;
|
||||
server_idx = 0;
|
||||
while (server_idx < dns_header_ancount(dns_msg.msg)) {
|
||||
ret = dns_unpack_answer(&dns_msg, answer_ptr, &ttl);
|
||||
if (ret < 0) {
|
||||
ret = DNS_EAI_FAIL;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
switch (dns_msg.response_type) {
|
||||
case DNS_RESPONSE_IP:
|
||||
if (dns_msg.response_length < address_size) {
|
||||
/* it seems this is a malformed message */
|
||||
ret = DNS_EAI_FAIL;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
src = dns_msg.msg + dns_msg.response_position;
|
||||
|
||||
memcpy(addr, src, address_size);
|
||||
info->ai_addrlen = address_size;
|
||||
|
||||
ctx->queries[query_idx].cb(DNS_EAI_INPROGRESS, info,
|
||||
ctx->queries[query_idx].user_data);
|
||||
items++;
|
||||
break;
|
||||
|
||||
case DNS_RESPONSE_CNAME_NO_IP:
|
||||
/* Instead of using the QNAME at DNS_QUERY_POS,
|
||||
* we will use this CNAME
|
||||
*/
|
||||
answer_ptr = dns_msg.response_position;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = DNS_EAI_FAIL;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
/* Update the answer offset to point to the next RR (answer) */
|
||||
dns_msg.answer_offset += DNS_ANSWER_PTR_LEN;
|
||||
dns_msg.answer_offset += dns_msg.response_length;
|
||||
|
||||
server_idx++;
|
||||
}
|
||||
|
||||
/* No IP addresses were found, so we take the last CNAME to generate
|
||||
* another query. Number of additional queries is controlled via Kconfig
|
||||
*/
|
||||
if (items == 0) {
|
||||
if (dns_msg.response_type == DNS_RESPONSE_CNAME_NO_IP) {
|
||||
uint16_t pos = dns_msg.response_position;
|
||||
|
||||
ret = dns_copy_qname(dns_cname->data, &dns_cname->len,
|
||||
dns_cname->size, &dns_msg, pos);
|
||||
if (ret < 0) {
|
||||
ret = DNS_EAI_SYSTEM;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
ret = DNS_EAI_AGAIN;
|
||||
goto finished;
|
||||
}
|
||||
}
|
||||
|
||||
if (items == 0) {
|
||||
ret = DNS_EAI_NODATA;
|
||||
} else {
|
||||
ret = DNS_EAI_ALLDONE;
|
||||
}
|
||||
|
||||
/* Marks the end of the results */
|
||||
ctx->queries[query_idx].cb(ret, NULL,
|
||||
ctx->queries[query_idx].user_data);
|
||||
|
||||
if (k_delayed_work_remaining_get(&ctx->queries[query_idx].timer) > 0) {
|
||||
k_delayed_work_cancel(&ctx->queries[query_idx].timer);
|
||||
}
|
||||
|
||||
ctx->queries[query_idx].cb = NULL;
|
||||
|
||||
net_nbuf_unref(buf);
|
||||
|
||||
return 0;
|
||||
|
||||
finished:
|
||||
dns_resolve_cancel(ctx, *dns_id);
|
||||
|
||||
quit:
|
||||
net_nbuf_unref(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cb_recv(struct net_context *net_ctx,
|
||||
struct net_buf *buf,
|
||||
int status,
|
||||
void *user_data)
|
||||
{
|
||||
struct dns_resolve_context *ctx = user_data;
|
||||
struct dns_addrinfo info = { 0 };
|
||||
struct net_buf *dns_cname = NULL;
|
||||
struct net_buf *dns_data = NULL;
|
||||
uint16_t dns_id = 0;
|
||||
int ret, i;
|
||||
|
||||
ARG_UNUSED(net_ctx);
|
||||
|
||||
if (status) {
|
||||
ret = DNS_EAI_SYSTEM;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
dns_data = net_buf_alloc(&dns_msg_pool, ctx->buf_timeout);
|
||||
if (!dns_data) {
|
||||
ret = DNS_EAI_MEMORY;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
dns_cname = net_buf_alloc(&dns_qname_pool, ctx->buf_timeout);
|
||||
if (!dns_cname) {
|
||||
ret = DNS_EAI_MEMORY;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
ret = dns_read(ctx, buf, dns_data, &dns_id, dns_cname, &info);
|
||||
if (!ret) {
|
||||
/* We called the callback already in dns_read() if there
|
||||
* was no errors.
|
||||
*/
|
||||
goto free_buf;
|
||||
}
|
||||
|
||||
/* Query again if we got CNAME */
|
||||
if (ret == DNS_EAI_AGAIN) {
|
||||
int failure = 0;
|
||||
int j;
|
||||
|
||||
i = get_slot_by_id(ctx, dns_id);
|
||||
if (i < 0) {
|
||||
goto cancel;
|
||||
}
|
||||
|
||||
for (j = 0; j < CONFIG_DNS_RESOLVER_MAX_SERVERS; j++) {
|
||||
if (!ctx->servers[j].net_ctx) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = dns_write(ctx, j, i, dns_data, dns_cname);
|
||||
if (ret < 0) {
|
||||
failure++;
|
||||
}
|
||||
}
|
||||
|
||||
if (failure) {
|
||||
NET_DBG("DNS cname query failed %d times", failure);
|
||||
|
||||
if (failure == j) {
|
||||
ret = DNS_EAI_SYSTEM;
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
|
||||
goto free_buf;
|
||||
}
|
||||
|
||||
quit:
|
||||
i = get_slot_by_id(ctx, dns_id);
|
||||
if (i < 0) {
|
||||
goto free_buf;
|
||||
}
|
||||
|
||||
cancel:
|
||||
if (k_delayed_work_remaining_get(&ctx->queries[i].timer) > 0) {
|
||||
k_delayed_work_cancel(&ctx->queries[i].timer);
|
||||
}
|
||||
|
||||
ctx->queries[i].cb(ret, &info, ctx->queries[i].user_data);
|
||||
ctx->queries[i].cb = NULL;
|
||||
|
||||
free_buf:
|
||||
if (dns_data) {
|
||||
net_buf_unref(dns_data);
|
||||
}
|
||||
|
||||
if (dns_cname) {
|
||||
net_buf_unref(dns_cname);
|
||||
}
|
||||
}
|
||||
|
||||
static int dns_write(struct dns_resolve_context *ctx,
|
||||
int server_idx,
|
||||
int query_idx,
|
||||
struct net_buf *dns_data,
|
||||
struct net_buf *dns_qname)
|
||||
{
|
||||
enum dns_query_type query_type;
|
||||
struct net_context *net_ctx;
|
||||
struct sockaddr *server;
|
||||
struct net_buf *buf;
|
||||
int server_addr_len;
|
||||
uint16_t dns_id;
|
||||
int ret;
|
||||
|
||||
net_ctx = ctx->servers[server_idx].net_ctx;
|
||||
server = &ctx->servers[server_idx].dns_server;
|
||||
dns_id = ctx->queries[query_idx].id;
|
||||
query_type = ctx->queries[query_idx].query_type;
|
||||
|
||||
ret = dns_msg_pack_query(dns_data->data, &dns_data->len, dns_data->size,
|
||||
dns_qname->data, dns_qname->len, dns_id,
|
||||
(enum dns_rr_type)query_type);
|
||||
if (ret < 0) {
|
||||
ret = -EINVAL;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
buf = net_nbuf_get_tx(net_ctx, ctx->buf_timeout);
|
||||
if (!buf) {
|
||||
ret = -ENOMEM;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
ret = net_nbuf_append(buf, dns_data->len, dns_data->data,
|
||||
ctx->buf_timeout);
|
||||
if (ret < 0) {
|
||||
ret = -ENOMEM;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
if (server->family == AF_INET) {
|
||||
server_addr_len = sizeof(struct sockaddr_in);
|
||||
} else {
|
||||
server_addr_len = sizeof(struct sockaddr_in6);
|
||||
}
|
||||
|
||||
net_context_recv(net_ctx, cb_recv, K_NO_WAIT, ctx);
|
||||
|
||||
ret = net_context_sendto(buf, server, server_addr_len, NULL,
|
||||
K_NO_WAIT, NULL, NULL);
|
||||
if (ret < 0) {
|
||||
NET_DBG("Cannot send query (%d)", ret);
|
||||
net_nbuf_unref(buf);
|
||||
goto quit;
|
||||
}
|
||||
|
||||
ret = k_delayed_work_submit(&ctx->queries[query_idx].timer,
|
||||
ctx->queries[query_idx].timeout);
|
||||
if (ret < 0) {
|
||||
NET_DBG("[%u] cannot submit work to server idx %d for id %u "
|
||||
"timeout %u ret %d",
|
||||
query_idx, server_idx, dns_id,
|
||||
ctx->queries[query_idx].timeout, ret);
|
||||
goto quit;
|
||||
} else {
|
||||
NET_DBG("[%u] submitting work to server idx %d for id %u "
|
||||
"timeout %u",
|
||||
query_idx, server_idx, dns_id,
|
||||
ctx->queries[query_idx].timeout);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
quit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dns_resolve_cancel(struct dns_resolve_context *ctx, uint16_t dns_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = get_slot_by_id(ctx, dns_id);
|
||||
if (i < 0) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
NET_DBG("Cancelling DNS req %u", dns_id);
|
||||
|
||||
if (k_delayed_work_remaining_get(&ctx->queries[i].timer) > 0) {
|
||||
k_delayed_work_cancel(&ctx->queries[i].timer);
|
||||
}
|
||||
|
||||
ctx->queries[i].cb(DNS_EAI_CANCELED, NULL, ctx->queries[i].user_data);
|
||||
ctx->queries[i].cb = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void query_timeout(struct k_work *work)
|
||||
{
|
||||
struct dns_pending_query *pending_query =
|
||||
CONTAINER_OF(work, struct dns_pending_query, timer);
|
||||
|
||||
NET_DBG("Query timeout DNS req %u", pending_query->id);
|
||||
|
||||
dns_resolve_cancel(pending_query->ctx, pending_query->id);
|
||||
}
|
||||
|
||||
int dns_resolve_name(struct dns_resolve_context *ctx,
|
||||
const char *query,
|
||||
enum dns_query_type type,
|
||||
uint16_t *dns_id,
|
||||
dns_resolve_cb_t cb,
|
||||
void *user_data,
|
||||
int32_t timeout)
|
||||
{
|
||||
struct net_buf *dns_data;
|
||||
struct net_buf *dns_qname = NULL;
|
||||
int ret, i, j = 0;
|
||||
int failure = 0;
|
||||
|
||||
if (!ctx || !ctx->is_used || !query || !cb) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Timeout cannot be 0 as we cannot resolve name that fast.
|
||||
*/
|
||||
if (timeout == K_NO_WAIT) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
i = get_cb_slot(ctx);
|
||||
if (i < 0) {
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
ctx->queries[i].cb = cb;
|
||||
ctx->queries[i].timeout = timeout;
|
||||
ctx->queries[i].query = query;
|
||||
ctx->queries[i].query_type = type;
|
||||
ctx->queries[i].user_data = user_data;
|
||||
ctx->queries[i].ctx = ctx;
|
||||
|
||||
k_delayed_work_init(&ctx->queries[i].timer, query_timeout);
|
||||
|
||||
dns_data = net_buf_alloc(&dns_msg_pool, ctx->buf_timeout);
|
||||
if (!dns_data) {
|
||||
ret = -ENOMEM;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
dns_qname = net_buf_alloc(&dns_qname_pool, ctx->buf_timeout);
|
||||
if (!dns_qname) {
|
||||
ret = -ENOMEM;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
ret = dns_msg_pack_qname(&dns_qname->len, dns_qname->data,
|
||||
DNS_MAX_NAME_LEN, ctx->queries[i].query);
|
||||
if (ret < 0) {
|
||||
goto quit;
|
||||
}
|
||||
|
||||
ctx->queries[i].id = sys_rand32_get();
|
||||
|
||||
/* Do this immediately after calculating the Id so that the unit
|
||||
* test will work properly.
|
||||
*/
|
||||
if (dns_id) {
|
||||
*dns_id = ctx->queries[i].id;
|
||||
|
||||
NET_DBG("DNS id will be %u", *dns_id);
|
||||
}
|
||||
|
||||
|
||||
for (j = 0; j < CONFIG_DNS_RESOLVER_MAX_SERVERS; j++) {
|
||||
if (!ctx->servers[j].net_ctx) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = dns_write(ctx, j, i, dns_data, dns_qname);
|
||||
if (ret < 0) {
|
||||
failure++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Do one concurrent query only for each name resolve.
|
||||
* TODO: Change the i (query index) to do multiple concurrent
|
||||
* to each server.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
if (failure) {
|
||||
NET_DBG("DNS query failed %d times", failure);
|
||||
|
||||
if (failure == j) {
|
||||
ret = -ENOENT;
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
quit:
|
||||
if (ret < 0) {
|
||||
if (k_delayed_work_remaining_get(&ctx->queries[i].timer) > 0) {
|
||||
k_delayed_work_cancel(&ctx->queries[i].timer);
|
||||
}
|
||||
|
||||
ctx->queries[i].cb = NULL;
|
||||
|
||||
if (dns_id) {
|
||||
*dns_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (dns_data) {
|
||||
net_buf_unref(dns_data);
|
||||
}
|
||||
|
||||
if (dns_qname) {
|
||||
net_buf_unref(dns_qname);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dns_resolve_close(struct dns_resolve_context *ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!ctx->is_used) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
for (i = 0; i < CONFIG_DNS_RESOLVER_MAX_SERVERS; i++) {
|
||||
if (ctx->servers[i].net_ctx) {
|
||||
net_context_put(ctx->servers[i].net_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dns_resolve_context *dns_resolve_get_default(void)
|
||||
{
|
||||
return &dns_default_ctx;
|
||||
}
|
||||
|
||||
void dns_init_resolver(void)
|
||||
{
|
||||
#if defined(CONFIG_DNS_SERVER_IP_ADDRESSES)
|
||||
static const char *dns_servers[CONFIG_DNS_RESOLVER_MAX_SERVERS + 1];
|
||||
int count = CONFIG_DNS_RESOLVER_MAX_SERVERS;
|
||||
int ret;
|
||||
|
||||
if (count > 5) {
|
||||
count = 5;
|
||||
}
|
||||
|
||||
switch (count) {
|
||||
case 5:
|
||||
dns_servers[4] = CONFIG_DNS_SERVER5;
|
||||
/* fallthrough */
|
||||
case 4:
|
||||
dns_servers[3] = CONFIG_DNS_SERVER4;
|
||||
/* fallthrough */
|
||||
case 3:
|
||||
dns_servers[2] = CONFIG_DNS_SERVER3;
|
||||
/* fallthrough */
|
||||
case 2:
|
||||
dns_servers[1] = CONFIG_DNS_SERVER2;
|
||||
/* fallthrough */
|
||||
case 1:
|
||||
dns_servers[0] = CONFIG_DNS_SERVER1;
|
||||
/* fallthrough */
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
|
||||
dns_servers[CONFIG_DNS_RESOLVER_MAX_SERVERS] = NULL;
|
||||
|
||||
ret = dns_resolve_init(dns_resolve_get_default(), dns_servers);
|
||||
if (ret < 0) {
|
||||
NET_WARN("Cannot initialize DNS resolver (%d)", ret);
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -275,6 +275,7 @@ int _zoap_well_known_core_get(struct zoap_resource *resource,
|
|||
r = zoap_add_option(&response, ZOAP_OPTION_CONTENT_FORMAT,
|
||||
&format, sizeof(format));
|
||||
if (r < 0) {
|
||||
net_nbuf_unref(buf);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -298,6 +299,11 @@ done:
|
|||
zoap_header_set_code(&response, ZOAP_RESPONSE_CODE_BAD_REQUEST);
|
||||
}
|
||||
|
||||
return net_context_sendto(buf, from, sizeof(struct sockaddr_in6),
|
||||
NULL, 0, NULL, NULL);
|
||||
r = net_context_sendto(buf, from, sizeof(struct sockaddr_in6),
|
||||
NULL, 0, NULL, NULL);
|
||||
if (r < 0) {
|
||||
net_nbuf_unref(buf);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
4
tests/net/lib/dns_resolve/Makefile
Normal file
4
tests/net/lib/dns_resolve/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
|||
BOARD ?= qemu_x86
|
||||
CONF_FILE ?= prj.conf
|
||||
|
||||
include $(ZEPHYR_BASE)/Makefile.test
|
31
tests/net/lib/dns_resolve/prj.conf
Normal file
31
tests/net/lib/dns_resolve/prj.conf
Normal file
|
@ -0,0 +1,31 @@
|
|||
CONFIG_NETWORKING=y
|
||||
|
||||
CONFIG_RANDOM_GENERATOR=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
|
||||
CONFIG_NET_L2_DUMMY=y
|
||||
|
||||
CONFIG_DNS_RESOLVER=y
|
||||
CONFIG_DNS_RESOLVER_MAX_SERVERS=4
|
||||
CONFIG_DNS_NUM_OF_CONCUR_QUERIES=1
|
||||
|
||||
CONFIG_DNS_SERVER_IP_ADDRESSES=y
|
||||
CONFIG_DNS_SERVER1="192.0.2.2"
|
||||
CONFIG_DNS_SERVER2="2001:db8::2"
|
||||
CONFIG_DNS_SERVER3="192.0.2.2:5353"
|
||||
CONFIG_DNS_SERVER4="[2001:db8::2]:5353"
|
||||
|
||||
CONFIG_NET_LOG=y
|
||||
CONFIG_SYS_LOG_NET_LEVEL=4
|
||||
CONFIG_SYS_LOG_SHOW_COLOR=y
|
||||
#CONFIG_NET_DEBUG_DNS_RESOLVE=y
|
||||
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_IPV6_DAD=n
|
||||
CONFIG_NET_IPV6_MLD=n
|
||||
CONFIG_NET_IPV6_ND=n
|
||||
CONFIG_NET_ARP=n
|
||||
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_ZTEST=y
|
7
tests/net/lib/dns_resolve/src/Makefile
Normal file
7
tests/net/lib/dns_resolve/src/Makefile
Normal file
|
@ -0,0 +1,7 @@
|
|||
ccflags-y += -I$(ZEPHYR_BASE)/subsys/net/lib/dns
|
||||
ccflags-y += -I${ZEPHYR_BASE}/subsys/net/ip
|
||||
ccflags-y += -I${ZEPHYR_BASE}/tests/include
|
||||
|
||||
include $(ZEPHYR_BASE)/tests/Makefile.test
|
||||
|
||||
obj-y = main.o
|
656
tests/net/lib/dns_resolve/src/main.c
Normal file
656
tests/net/lib/dns_resolve/src/main.c
Normal file
|
@ -0,0 +1,656 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <misc/printk.h>
|
||||
|
||||
#include <ztest.h>
|
||||
|
||||
#include <net/ethernet.h>
|
||||
#include <net/buf.h>
|
||||
#include <net/net_ip.h>
|
||||
#include <net/net_if.h>
|
||||
#include <net/dns_resolve.h>
|
||||
|
||||
#define NET_LOG_ENABLED 1
|
||||
#include "net_private.h"
|
||||
|
||||
#if defined(CONFIG_NET_DEBUG_DNS_RESOLVE)
|
||||
#define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define DBG(fmt, ...)
|
||||
#endif
|
||||
|
||||
#define NAME4 "4.zephyr.test"
|
||||
#define NAME6 "6.zephyr.test"
|
||||
|
||||
#define DNS_TIMEOUT 500 /* ms */
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
/* Interface 1 addresses */
|
||||
static struct in6_addr my_addr1 = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0x1 } } };
|
||||
|
||||
/* Extra address is assigned to ll_addr */
|
||||
static struct in6_addr ll_addr = { { { 0xfe, 0x80, 0x43, 0xb8, 0, 0, 0, 0,
|
||||
0, 0, 0, 0xf2, 0xaa, 0x29, 0x02,
|
||||
0x04 } } };
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
/* Interface 1 addresses */
|
||||
static struct in_addr my_addr2 = { { { 192, 0, 2, 1 } } };
|
||||
#endif
|
||||
|
||||
static struct net_if *iface1;
|
||||
|
||||
static bool test_failed;
|
||||
static bool test_started;
|
||||
static bool timeout_query;
|
||||
static struct k_sem wait_data;
|
||||
static struct k_sem wait_data2;
|
||||
static uint16_t current_dns_id;
|
||||
static struct dns_addrinfo addrinfo;
|
||||
|
||||
/* this must be higher that the DNS_TIMEOUT */
|
||||
#define WAIT_TIME (DNS_TIMEOUT + 300)
|
||||
|
||||
struct net_if_test {
|
||||
uint8_t idx;
|
||||
uint8_t mac_addr[sizeof(struct net_eth_addr)];
|
||||
struct net_linkaddr ll_addr;
|
||||
};
|
||||
|
||||
static int net_iface_dev_init(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t *net_iface_get_mac(struct device *dev)
|
||||
{
|
||||
struct net_if_test *data = dev->driver_data;
|
||||
|
||||
if (data->mac_addr[2] == 0x00) {
|
||||
/* 00-00-5E-00-53-xx Documentation RFC 7042 */
|
||||
data->mac_addr[0] = 0x00;
|
||||
data->mac_addr[1] = 0x00;
|
||||
data->mac_addr[2] = 0x5E;
|
||||
data->mac_addr[3] = 0x00;
|
||||
data->mac_addr[4] = 0x53;
|
||||
data->mac_addr[5] = sys_rand32_get();
|
||||
}
|
||||
|
||||
data->ll_addr.addr = data->mac_addr;
|
||||
data->ll_addr.len = 6;
|
||||
|
||||
return data->mac_addr;
|
||||
}
|
||||
|
||||
static void net_iface_init(struct net_if *iface)
|
||||
{
|
||||
uint8_t *mac = net_iface_get_mac(net_if_get_device(iface));
|
||||
|
||||
net_if_set_link_addr(iface, mac, sizeof(struct net_eth_addr),
|
||||
NET_LINK_ETHERNET);
|
||||
}
|
||||
|
||||
static inline int get_slot_by_id(struct dns_resolve_context *ctx,
|
||||
uint16_t dns_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) {
|
||||
if (ctx->queries[i].cb && ctx->queries[i].id == dns_id) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int sender_iface(struct net_if *iface, struct net_buf *buf)
|
||||
{
|
||||
if (!buf->frags) {
|
||||
DBG("No data to send!\n");
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
if (!timeout_query) {
|
||||
struct net_if_test *data = iface->dev->driver_data;
|
||||
struct dns_resolve_context *ctx;
|
||||
int slot;
|
||||
|
||||
DBG("Sending at iface %d %p\n", net_if_get_by_iface(iface),
|
||||
iface);
|
||||
|
||||
if (net_nbuf_iface(buf) != iface) {
|
||||
DBG("Invalid interface %p, expecting %p\n",
|
||||
net_nbuf_iface(buf), iface);
|
||||
test_failed = true;
|
||||
}
|
||||
|
||||
if (net_if_get_by_iface(iface) != data->idx) {
|
||||
DBG("Invalid interface %d index, expecting %d\n",
|
||||
data->idx, net_if_get_by_iface(iface));
|
||||
test_failed = true;
|
||||
}
|
||||
|
||||
ctx = dns_resolve_get_default();
|
||||
|
||||
slot = get_slot_by_id(ctx, current_dns_id);
|
||||
if (slot < 0) {
|
||||
DBG("Skipping this query dns id %u\n", current_dns_id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* We need to cancel the query manually so that we
|
||||
* will not get a timeout.
|
||||
*/
|
||||
k_delayed_work_cancel(&ctx->queries[slot].timer);
|
||||
|
||||
DBG("Calling cb %p with user data %p\n",
|
||||
ctx->queries[slot].cb,
|
||||
ctx->queries[slot].user_data);
|
||||
|
||||
ctx->queries[slot].cb(DNS_EAI_INPROGRESS,
|
||||
&addrinfo,
|
||||
ctx->queries[slot].user_data);
|
||||
ctx->queries[slot].cb(DNS_EAI_ALLDONE,
|
||||
NULL,
|
||||
ctx->queries[slot].user_data);
|
||||
|
||||
ctx->queries[slot].cb = NULL;
|
||||
}
|
||||
|
||||
out:
|
||||
net_nbuf_unref(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct net_if_test net_iface1_data;
|
||||
|
||||
static struct net_if_api net_iface_api = {
|
||||
.init = net_iface_init,
|
||||
.send = sender_iface,
|
||||
};
|
||||
|
||||
#define _ETH_L2_LAYER DUMMY_L2
|
||||
#define _ETH_L2_CTX_TYPE NET_L2_GET_CTX_TYPE(DUMMY_L2)
|
||||
|
||||
NET_DEVICE_INIT_INSTANCE(net_iface1_test,
|
||||
"iface1",
|
||||
iface1,
|
||||
net_iface_dev_init,
|
||||
&net_iface1_data,
|
||||
NULL,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&net_iface_api,
|
||||
_ETH_L2_LAYER,
|
||||
_ETH_L2_CTX_TYPE,
|
||||
127);
|
||||
|
||||
static void test_init(void)
|
||||
{
|
||||
struct net_if_addr *ifaddr;
|
||||
|
||||
/* The semaphore is there to wait the data to be received. */
|
||||
k_sem_init(&wait_data, 0, UINT_MAX);
|
||||
k_sem_init(&wait_data2, 0, UINT_MAX);
|
||||
|
||||
iface1 = net_if_get_by_index(0);
|
||||
|
||||
((struct net_if_test *)iface1->dev->driver_data)->idx = 0;
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
ifaddr = net_if_ipv6_addr_add(iface1, &my_addr1,
|
||||
NET_ADDR_MANUAL, 0);
|
||||
if (!ifaddr) {
|
||||
DBG("Cannot add IPv6 address %s\n",
|
||||
net_sprint_ipv6_addr(&my_addr1));
|
||||
assert_not_null(ifaddr, "addr1");
|
||||
}
|
||||
|
||||
/* For testing purposes we need to set the adddresses preferred */
|
||||
ifaddr->addr_state = NET_ADDR_PREFERRED;
|
||||
|
||||
ifaddr = net_if_ipv6_addr_add(iface1, &ll_addr,
|
||||
NET_ADDR_MANUAL, 0);
|
||||
if (!ifaddr) {
|
||||
DBG("Cannot add IPv6 address %s\n",
|
||||
net_sprint_ipv6_addr(&ll_addr));
|
||||
assert_not_null(ifaddr, "ll_addr");
|
||||
}
|
||||
|
||||
ifaddr->addr_state = NET_ADDR_PREFERRED;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
ifaddr = net_if_ipv4_addr_add(iface1, &my_addr2,
|
||||
NET_ADDR_MANUAL, 0);
|
||||
if (!ifaddr) {
|
||||
DBG("Cannot add IPv4 address %s\n",
|
||||
net_sprint_ipv4_addr(&my_addr2));
|
||||
assert_not_null(ifaddr, "addr2");
|
||||
}
|
||||
|
||||
ifaddr->addr_state = NET_ADDR_PREFERRED;
|
||||
#endif
|
||||
|
||||
net_if_up(iface1);
|
||||
|
||||
/* The interface might receive data which might fail the checks
|
||||
* in the iface sending function, so we need to reset the failure
|
||||
* flag.
|
||||
*/
|
||||
test_failed = false;
|
||||
|
||||
test_started = true;
|
||||
}
|
||||
|
||||
void dns_result_cb_dummy(enum dns_resolve_status status,
|
||||
struct dns_addrinfo *info,
|
||||
void *user_data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void dns_query_invalid_timeout(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dns_get_addr_info(NAME6,
|
||||
DNS_QUERY_TYPE_AAAA,
|
||||
NULL,
|
||||
dns_result_cb_dummy,
|
||||
NULL,
|
||||
K_NO_WAIT);
|
||||
assert_equal(ret, -EINVAL, "Wrong return code for timeout");
|
||||
}
|
||||
|
||||
static void dns_query_invalid_context(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dns_resolve_name(NULL,
|
||||
NAME6,
|
||||
DNS_QUERY_TYPE_AAAA,
|
||||
NULL,
|
||||
dns_result_cb_dummy,
|
||||
NULL,
|
||||
DNS_TIMEOUT);
|
||||
assert_equal(ret, -EINVAL, "Wrong return code for context");
|
||||
}
|
||||
|
||||
static void dns_query_invalid_callback(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dns_get_addr_info(NAME6,
|
||||
DNS_QUERY_TYPE_AAAA,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
DNS_TIMEOUT);
|
||||
assert_equal(ret, -EINVAL, "Wrong return code for callback");
|
||||
}
|
||||
|
||||
static void dns_query_invalid_query(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dns_get_addr_info(NULL,
|
||||
DNS_QUERY_TYPE_AAAA,
|
||||
NULL,
|
||||
dns_result_cb_dummy,
|
||||
NULL,
|
||||
DNS_TIMEOUT);
|
||||
assert_equal(ret, -EINVAL, "Wrong return code for query");
|
||||
}
|
||||
|
||||
void dns_result_cb_timeout(enum dns_resolve_status status,
|
||||
struct dns_addrinfo *info,
|
||||
void *user_data)
|
||||
{
|
||||
int expected_status = POINTER_TO_INT(user_data);
|
||||
|
||||
if (expected_status != status) {
|
||||
DBG("Result status %d\n", status);
|
||||
DBG("Expected status %d\n", expected_status);
|
||||
|
||||
assert_equal(expected_status, status, "Invalid status");
|
||||
}
|
||||
|
||||
k_sem_give(&wait_data);
|
||||
}
|
||||
|
||||
static void dns_query_server_count(void)
|
||||
{
|
||||
struct dns_resolve_context *ctx = dns_resolve_get_default();
|
||||
int i, count = 0;
|
||||
|
||||
for (i = 0; i < CONFIG_DNS_RESOLVER_MAX_SERVERS; i++) {
|
||||
if (!ctx->is_used) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ctx->servers[i].net_ctx) {
|
||||
continue;
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
assert_equal(count, CONFIG_DNS_RESOLVER_MAX_SERVERS,
|
||||
"Invalid number of servers");
|
||||
}
|
||||
|
||||
static void dns_query_ipv4_server_count(void)
|
||||
{
|
||||
struct dns_resolve_context *ctx = dns_resolve_get_default();
|
||||
int i, count = 0, port = 0;
|
||||
|
||||
for (i = 0; i < CONFIG_DNS_RESOLVER_MAX_SERVERS; i++) {
|
||||
if (!ctx->is_used) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ctx->servers[i].net_ctx) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx->servers[i].dns_server.family == AF_INET) {
|
||||
count++;
|
||||
}
|
||||
|
||||
if (net_sin(&ctx->servers[i].dns_server)->sin_port ==
|
||||
ntohs(53)) {
|
||||
port++;
|
||||
}
|
||||
}
|
||||
|
||||
assert_equal(count, 2, "Invalid number of IPv4 servers");
|
||||
assert_equal(port, 2, "Invalid number of IPv4 servers with port 53");
|
||||
}
|
||||
|
||||
static void dns_query_ipv6_server_count(void)
|
||||
{
|
||||
struct dns_resolve_context *ctx = dns_resolve_get_default();
|
||||
int i, count = 0, port = 0;
|
||||
|
||||
for (i = 0; i < CONFIG_DNS_RESOLVER_MAX_SERVERS; i++) {
|
||||
if (!ctx->is_used) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ctx->servers[i].net_ctx) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx->servers[i].dns_server.family == AF_INET6) {
|
||||
count++;
|
||||
}
|
||||
|
||||
if (net_sin6(&ctx->servers[i].dns_server)->sin6_port ==
|
||||
ntohs(53)) {
|
||||
port++;
|
||||
}
|
||||
}
|
||||
|
||||
assert_equal(count, 2, "Invalid number of IPv6 servers");
|
||||
assert_equal(port, 2, "Invalid number of IPv6 servers with port 53");
|
||||
}
|
||||
|
||||
static void dns_query_too_many(void)
|
||||
{
|
||||
int expected_status = DNS_EAI_CANCELED;
|
||||
int ret;
|
||||
|
||||
timeout_query = true;
|
||||
|
||||
ret = dns_get_addr_info(NAME4,
|
||||
DNS_QUERY_TYPE_A,
|
||||
NULL,
|
||||
dns_result_cb_timeout,
|
||||
INT_TO_POINTER(expected_status),
|
||||
DNS_TIMEOUT);
|
||||
assert_equal(ret, 0, "Cannot create IPv4 query");
|
||||
|
||||
ret = dns_get_addr_info(NAME4,
|
||||
DNS_QUERY_TYPE_A,
|
||||
NULL,
|
||||
dns_result_cb_dummy,
|
||||
INT_TO_POINTER(expected_status),
|
||||
DNS_TIMEOUT);
|
||||
assert_equal(ret, -EAGAIN, "Should have run out of space");
|
||||
|
||||
if (k_sem_take(&wait_data, WAIT_TIME)) {
|
||||
assert_true(false, "Timeout while waiting data");
|
||||
}
|
||||
|
||||
timeout_query = false;
|
||||
}
|
||||
|
||||
static void dns_query_ipv4_timeout(void)
|
||||
{
|
||||
int expected_status = DNS_EAI_CANCELED;
|
||||
int ret;
|
||||
|
||||
timeout_query = true;
|
||||
|
||||
ret = dns_get_addr_info(NAME4,
|
||||
DNS_QUERY_TYPE_A,
|
||||
NULL,
|
||||
dns_result_cb_timeout,
|
||||
INT_TO_POINTER(expected_status),
|
||||
DNS_TIMEOUT);
|
||||
assert_equal(ret, 0, "Cannot create IPv4 query");
|
||||
|
||||
if (k_sem_take(&wait_data, WAIT_TIME)) {
|
||||
assert_true(false, "Timeout while waiting data");
|
||||
}
|
||||
|
||||
timeout_query = false;
|
||||
}
|
||||
|
||||
static void dns_query_ipv6_timeout(void)
|
||||
{
|
||||
int expected_status = DNS_EAI_CANCELED;
|
||||
int ret;
|
||||
|
||||
timeout_query = true;
|
||||
|
||||
ret = dns_get_addr_info(NAME6,
|
||||
DNS_QUERY_TYPE_AAAA,
|
||||
NULL,
|
||||
dns_result_cb_timeout,
|
||||
INT_TO_POINTER(expected_status),
|
||||
DNS_TIMEOUT);
|
||||
assert_equal(ret, 0, "Cannot create IPv6 query");
|
||||
|
||||
if (k_sem_take(&wait_data, WAIT_TIME)) {
|
||||
assert_true(false, "Timeout while waiting data");
|
||||
}
|
||||
|
||||
timeout_query = false;
|
||||
}
|
||||
|
||||
static void verify_cancelled(void)
|
||||
{
|
||||
struct dns_resolve_context *ctx = dns_resolve_get_default();
|
||||
int i, count = 0, timer_not_stopped = 0;
|
||||
|
||||
for (i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) {
|
||||
if (ctx->queries[i].cb) {
|
||||
count++;
|
||||
}
|
||||
|
||||
if (k_delayed_work_remaining_get(&ctx->queries[i].timer) > 0) {
|
||||
timer_not_stopped++;
|
||||
}
|
||||
}
|
||||
|
||||
assert_equal(count, 0, "Not all pending queries vere cancelled");
|
||||
assert_equal(timer_not_stopped, 0, "Not all timers vere cancelled");
|
||||
}
|
||||
|
||||
static void dns_query_ipv4_cancel(void)
|
||||
{
|
||||
int expected_status = DNS_EAI_CANCELED;
|
||||
uint16_t dns_id;
|
||||
int ret;
|
||||
|
||||
timeout_query = true;
|
||||
|
||||
ret = dns_get_addr_info(NAME4,
|
||||
DNS_QUERY_TYPE_A,
|
||||
&dns_id,
|
||||
dns_result_cb_timeout,
|
||||
INT_TO_POINTER(expected_status),
|
||||
DNS_TIMEOUT);
|
||||
assert_equal(ret, 0, "Cannot create IPv4 query");
|
||||
|
||||
ret = dns_cancel_addr_info(dns_id);
|
||||
assert_equal(ret, 0, "Cannot cancel IPv4 query");
|
||||
|
||||
if (k_sem_take(&wait_data, WAIT_TIME)) {
|
||||
assert_true(false, "Timeout while waiting data");
|
||||
}
|
||||
|
||||
verify_cancelled();
|
||||
}
|
||||
|
||||
static void dns_query_ipv6_cancel(void)
|
||||
{
|
||||
int expected_status = DNS_EAI_CANCELED;
|
||||
uint16_t dns_id;
|
||||
int ret;
|
||||
|
||||
timeout_query = true;
|
||||
|
||||
ret = dns_get_addr_info(NAME6,
|
||||
DNS_QUERY_TYPE_AAAA,
|
||||
&dns_id,
|
||||
dns_result_cb_timeout,
|
||||
INT_TO_POINTER(expected_status),
|
||||
DNS_TIMEOUT);
|
||||
assert_equal(ret, 0, "Cannot create IPv6 query");
|
||||
|
||||
ret = dns_cancel_addr_info(dns_id);
|
||||
assert_equal(ret, 0, "Cannot cancel IPv6 query");
|
||||
|
||||
if (k_sem_take(&wait_data, WAIT_TIME)) {
|
||||
assert_true(false, "Timeout while waiting data");
|
||||
}
|
||||
|
||||
verify_cancelled();
|
||||
}
|
||||
|
||||
struct expected_status {
|
||||
int status1;
|
||||
int status2;
|
||||
const char *caller;
|
||||
};
|
||||
|
||||
void dns_result_cb(enum dns_resolve_status status,
|
||||
struct dns_addrinfo *info,
|
||||
void *user_data)
|
||||
{
|
||||
struct expected_status *expected = user_data;
|
||||
|
||||
if (status != expected->status1 && status != expected->status2) {
|
||||
DBG("Result status %d\n", status);
|
||||
DBG("Expected status1 %d\n", expected->status1);
|
||||
DBG("Expected status2 %d\n", expected->status2);
|
||||
DBG("Caller %s\n", expected->caller);
|
||||
|
||||
assert_true(false, "Invalid status");
|
||||
}
|
||||
|
||||
k_sem_give(&wait_data2);
|
||||
}
|
||||
|
||||
static void dns_query_ipv4(void)
|
||||
{
|
||||
struct expected_status status = {
|
||||
.status1 = DNS_EAI_INPROGRESS,
|
||||
.status2 = DNS_EAI_ALLDONE,
|
||||
.caller = __func__,
|
||||
};
|
||||
int ret;
|
||||
|
||||
timeout_query = false;
|
||||
|
||||
ret = dns_get_addr_info(NAME4,
|
||||
DNS_QUERY_TYPE_A,
|
||||
¤t_dns_id,
|
||||
dns_result_cb,
|
||||
&status,
|
||||
DNS_TIMEOUT);
|
||||
assert_equal(ret, 0, "Cannot create IPv4 query");
|
||||
|
||||
DBG("Query id %u\n", current_dns_id);
|
||||
|
||||
k_yield(); /* mandatory so that net_if send func gets to run */
|
||||
|
||||
if (k_sem_take(&wait_data2, WAIT_TIME)) {
|
||||
assert_true(false, "Timeout while waiting data");
|
||||
}
|
||||
}
|
||||
|
||||
static void dns_query_ipv6(void)
|
||||
{
|
||||
struct expected_status status = {
|
||||
.status1 = DNS_EAI_INPROGRESS,
|
||||
.status2 = DNS_EAI_ALLDONE,
|
||||
.caller = __func__,
|
||||
};
|
||||
int ret;
|
||||
|
||||
timeout_query = false;
|
||||
|
||||
ret = dns_get_addr_info(NAME6,
|
||||
DNS_QUERY_TYPE_AAAA,
|
||||
¤t_dns_id,
|
||||
dns_result_cb,
|
||||
&status,
|
||||
DNS_TIMEOUT);
|
||||
assert_equal(ret, 0, "Cannot create IPv6 query");
|
||||
|
||||
DBG("Query id %u\n", current_dns_id);
|
||||
|
||||
k_yield(); /* mandatory so that net_if send func gets to run */
|
||||
|
||||
if (k_sem_take(&wait_data2, WAIT_TIME)) {
|
||||
assert_true(false, "Timeout while waiting data");
|
||||
}
|
||||
}
|
||||
|
||||
void test_main(void)
|
||||
{
|
||||
ztest_test_suite(dns_tests,
|
||||
ztest_unit_test(test_init),
|
||||
ztest_unit_test(dns_query_invalid_timeout),
|
||||
ztest_unit_test(dns_query_invalid_context),
|
||||
ztest_unit_test(dns_query_invalid_callback),
|
||||
ztest_unit_test(dns_query_invalid_query),
|
||||
ztest_unit_test(dns_query_too_many),
|
||||
ztest_unit_test(dns_query_server_count),
|
||||
ztest_unit_test(dns_query_ipv4_server_count),
|
||||
ztest_unit_test(dns_query_ipv6_server_count),
|
||||
ztest_unit_test(dns_query_ipv4_timeout),
|
||||
ztest_unit_test(dns_query_ipv6_timeout),
|
||||
ztest_unit_test(dns_query_ipv4_cancel),
|
||||
ztest_unit_test(dns_query_ipv6_cancel),
|
||||
ztest_unit_test(dns_query_ipv4),
|
||||
ztest_unit_test(dns_query_ipv6));
|
||||
|
||||
ztest_run_test_suite(dns_tests);
|
||||
}
|
6
tests/net/lib/dns_resolve/testcase.ini
Normal file
6
tests/net/lib/dns_resolve/testcase.ini
Normal file
|
@ -0,0 +1,6 @@
|
|||
[test]
|
||||
tags = dns net
|
||||
build_only = false
|
||||
platform_whitelist = qemu_x86
|
||||
timeout = 10800
|
||||
slow = True
|
|
@ -440,7 +440,7 @@ static bool net_test_send_ns(void)
|
|||
&in6addr_my,
|
||||
&iface->link_addr,
|
||||
false,
|
||||
NET_NBR_REACHABLE);
|
||||
NET_IPV6_NBR_STATE_REACHABLE);
|
||||
if (!nbr) {
|
||||
TC_ERROR("Cannot add to neighbor cache\n");
|
||||
return false;
|
||||
|
@ -484,7 +484,7 @@ static bool net_test_nbr_lookup_ok(void)
|
|||
net_sprint_ipv6_addr(&peer_addr),
|
||||
net_sprint_ll_addr(llstorage->addr, llstorage->len));
|
||||
|
||||
net_ipv6_nbr_data(nbr)->state = NET_NBR_REACHABLE;
|
||||
net_ipv6_nbr_data(nbr)->state = NET_IPV6_NBR_STATE_REACHABLE;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue