drivers: wifi: simplelink: reimplement getaddrinfo

Reimplement getaddrinfo to call SlNetUtil_getAddrInfo from the TI HAL
for a more robust implementation that supports both client and server
modes, and performs better error-checking.

Fixes #11890

Signed-off-by: Vincent Wan <vwan@ti.com>
This commit is contained in:
Vincent Wan 2020-08-12 15:00:39 -07:00 committed by Jukka Rissanen
commit 23b54832f8
2 changed files with 145 additions and 76 deletions

View file

@ -18,6 +18,8 @@ LOG_MODULE_DECLARE(LOG_MODULE_NAME);
#include <errno.h>
#include <ti/drivers/net/wifi/simplelink.h>
#include <ti/drivers/net/wifi/source/driver.h>
#include <ti/net/slnetutils.h>
#include <ti/net/slnetif.h>
#include "simplelink_support.h"
#include "sockets_internal.h"
@ -37,9 +39,6 @@ LOG_MODULE_DECLARE(LOG_MODULE_NAME);
#define SD_TO_OBJ(sd) ((void *)(sd + 1))
#define OBJ_TO_SD(obj) (((int)obj) - 1)
/* Mutex for getaddrinfo() calls: */
K_MUTEX_DEFINE(ga_mutex);
static int simplelink_socket_accept(void *obj, struct sockaddr *addr,
socklen_t *addrlen);
@ -974,64 +973,15 @@ static ssize_t simplelink_sendmsg(void *obj, const struct msghdr *msg,
return -1;
}
/*
* Later SimpleLink SDK versions implement the full getaddrinfo semantics,
* returning potentially multiple IP addresses.
* This version implements a simple gethostbyname() API for client only.
*/
static int simplelink_getaddrinfo(const char *node, const char *service,
const struct zsock_addrinfo *hints,
struct zsock_addrinfo **res)
/* Adds address info entry to a list */
static int set_addr_info(const struct SlNetUtil_addrInfo_t *sl_ai,
struct zsock_addrinfo **res)
{
_u8 sl_family = SL_AF_INET;
unsigned long port = 0;
int socktype = SOCK_STREAM;
int proto = IPPROTO_TCP;
struct zsock_addrinfo *ai;
struct sockaddr *ai_addr;
_i16 retval;
_u32 ipaddr[4];
int retval = 0;
/* Check args: */
if (!node) {
retval = DNS_EAI_NONAME;
goto exit;
}
if (service) {
port = strtol(service, NULL, 10);
if (port < 1 || port > USHRT_MAX) {
retval = DNS_EAI_SERVICE;
goto exit;
}
}
if (!res) {
retval = DNS_EAI_NONAME;
goto exit;
}
/* See if any hints for family; otherwise, default to AF_INET. */
if (hints) {
/* Note: SimpleLink SDK doesn't support AF_UNSPEC: */
sl_family = (hints->ai_family == AF_INET6 ?
SL_AF_INET6 : SL_AF_INET);
}
/* Now, try to resolve host name: */
k_mutex_lock(&ga_mutex, K_FOREVER);
retval = sl_NetAppDnsGetHostByName((signed char *)node, strlen(node),
ipaddr, sl_family);
k_mutex_unlock(&ga_mutex);
if (retval < 0) {
LOG_ERR("Could not resolve name: %s, retval: %d",
node, retval);
retval = DNS_EAI_NONAME;
goto exit;
}
/* Allocate out res (addrinfo) struct. Just one. */
*res = calloc(1, sizeof(struct zsock_addrinfo));
ai = *res;
ai = calloc(1, sizeof(struct zsock_addrinfo));
if (!ai) {
retval = DNS_EAI_MEMORY;
goto exit;
@ -1040,44 +990,127 @@ static int simplelink_getaddrinfo(const char *node, const char *service,
ai_addr = calloc(1, sizeof(struct sockaddr));
if (!ai_addr) {
retval = DNS_EAI_MEMORY;
free(*res);
free(ai);
goto exit;
}
}
/* Now, fill in the fields of res (addrinfo struct): */
ai->ai_family = (sl_family == SL_AF_INET6 ? AF_INET6 : AF_INET);
if (hints) {
socktype = hints->ai_socktype;
}
ai->ai_socktype = socktype;
if (socktype == SOCK_DGRAM) {
proto = IPPROTO_UDP;
}
ai->ai_protocol = proto;
ai->ai_family = (sl_ai->ai_family == SL_AF_INET6 ? AF_INET6 : AF_INET);
ai->ai_socktype = (sl_ai->ai_socktype == SLNETSOCK_SOCK_DGRAM ?
SOCK_DGRAM : SOCK_STREAM);
ai->ai_protocol = (sl_ai->ai_protocol == SLNETSOCK_PROTO_UDP ?
IPPROTO_UDP : IPPROTO_TCP);
/* Fill sockaddr struct fields based on family: */
if (ai->ai_family == AF_INET) {
SlNetSock_AddrIn_t *sl_addr =
(SlNetSock_AddrIn_t *)sl_ai->ai_addr;
net_sin(ai_addr)->sin_family = ai->ai_family;
net_sin(ai_addr)->sin_addr.s_addr = htonl(ipaddr[0]);
net_sin(ai_addr)->sin_port = htons(port);
net_sin(ai_addr)->sin_addr.s_addr = sl_addr->sin_addr.s_addr;
net_sin(ai_addr)->sin_port = sl_addr->sin_port;
ai->ai_addrlen = sizeof(struct sockaddr_in);
} else {
SlNetSock_AddrIn6_t *sl_addr =
(SlNetSock_AddrIn6_t *)sl_ai->ai_addr;
net_sin6(ai_addr)->sin6_family = ai->ai_family;
net_sin6(ai_addr)->sin6_addr.s6_addr32[0] = htonl(ipaddr[0]);
net_sin6(ai_addr)->sin6_addr.s6_addr32[1] = htonl(ipaddr[1]);
net_sin6(ai_addr)->sin6_addr.s6_addr32[2] = htonl(ipaddr[2]);
net_sin6(ai_addr)->sin6_addr.s6_addr32[3] = htonl(ipaddr[3]);
net_sin6(ai_addr)->sin6_port = htons(port);
net_sin6(ai_addr)->sin6_addr.s6_addr32[0] =
sl_addr->sin6_addr._S6_un._S6_u32[0];
net_sin6(ai_addr)->sin6_addr.s6_addr32[1] =
sl_addr->sin6_addr._S6_un._S6_u32[1];
net_sin6(ai_addr)->sin6_addr.s6_addr32[2] =
sl_addr->sin6_addr._S6_un._S6_u32[2];
net_sin6(ai_addr)->sin6_addr.s6_addr32[3] =
sl_addr->sin6_addr._S6_un._S6_u32[3];
net_sin6(ai_addr)->sin6_port = sl_addr->sin6_port;
ai->ai_addrlen = sizeof(struct sockaddr_in6);
}
ai->ai_addr = ai_addr;
ai->ai_next = *res;
*res = ai;
exit:
return retval;
}
static int simplelink_getaddrinfo(const char *node, const char *service,
const struct zsock_addrinfo *hints,
struct zsock_addrinfo **res)
{
int32_t retval;
struct SlNetUtil_addrInfo_t sl_hints;
struct SlNetUtil_addrInfo_t *sl_res, *sl_ai;
/* Initialize sl_hints to the defaults */
memset(&sl_hints, 0, sizeof(sl_hints));
/* Check args: */
if (!res) {
retval = DNS_EAI_NONAME;
goto exit;
}
if (hints) {
/*
* SlNetUtil only supports AI_NUMERICHOST and AI_PASSIVE, so
* the rest are ignored.
*/
sl_hints.ai_flags |= ((hints->ai_flags & AI_PASSIVE) ?
SLNETUTIL_AI_PASSIVE : 0);
sl_hints.ai_flags |= ((hints->ai_flags & AI_NUMERICHOST) ?
SLNETUTIL_AI_NUMERICHOST : 0);
if (hints->ai_family == AF_UNSPEC) {
sl_hints.ai_family = SLNETSOCK_AF_UNSPEC;
} else {
sl_hints.ai_family = (hints->ai_family == AF_INET6 ?
SLNETSOCK_AF_INET6 : SLNETSOCK_AF_INET);
}
if (hints->ai_socktype == 0) {
sl_hints.ai_socktype = 0;
} else {
sl_hints.ai_socktype =
(hints->ai_socktype == SOCK_DGRAM ?
SLNETSOCK_SOCK_DGRAM : SLNETSOCK_SOCK_STREAM);
}
if (hints->ai_protocol == 0) {
sl_hints.ai_protocol = 0;
} else {
sl_hints.ai_protocol =
(hints->ai_protocol == IPPROTO_UDP ?
SLNETSOCK_PROTO_UDP : SLNETSOCK_PROTO_TCP);
}
}
/* Now, try to resolve host name: */
retval = SlNetUtil_getAddrInfo(SLNETIF_ID_1, node,
service, &sl_hints, &sl_res);
if (retval < 0) {
LOG_ERR("Could not resolve name: %s, retval: %d",
node, retval);
retval = DNS_EAI_NONAME;
goto exit;
}
sl_ai = sl_res;
*res = NULL;
while (sl_ai != NULL) {
retval = set_addr_info(sl_ai, res);
if (retval < 0) {
LOG_ERR("Unable to set address info, retval: %d",
retval);
goto exit;
}
sl_ai = sl_ai->ai_next;
}
SlNetUtil_freeAddrInfo(sl_res);
exit:
return retval;
}
static void simplelink_freeaddrinfo(struct zsock_addrinfo *res)
{
__ASSERT_NO_MSG(res);
@ -1243,7 +1276,6 @@ NET_SOCKET_REGISTER(simplelink, AF_UNSPEC, simplelink_is_supported,
void simplelink_sockets_init(void)
{
k_mutex_init(&ga_mutex);
}
const struct socket_dns_offload simplelink_dns_ops = {

View file

@ -15,6 +15,9 @@ LOG_MODULE_DECLARE(LOG_MODULE_NAME);
#include <stdint.h>
#include <ti/drivers/net/wifi/simplelink.h>
#include <ti/net/slnetif.h>
#include <ti/net/slnetutils.h>
#include <ti/drivers/net/wifi/slnetifwifi.h>
#include <CC3220SF_LAUNCHXL.h>
#include "simplelink_support.h"
@ -34,6 +37,9 @@ LOG_MODULE_DECLARE(LOG_MODULE_NAME);
#define CHANNEL_MASK_ALL (0x1FFF)
#define RSSI_TH_MAX (-95)
#define SLNET_IF_WIFI_PRIO (5)
#define SLNET_IF_WIFI_NAME "CC32xx"
enum status_bits {
/* Network Processor is powered up */
STATUS_BIT_NWP_INIT = 0,
@ -65,6 +71,20 @@ struct sl_connect_state sl_conn;
/* Network Coprocessor state, including role and connection state: */
static struct nwp_status nwp;
/* Minimal configuration of SlNetIfWifi for Zephyr */
static SlNetIf_Config_t slnetifwifi_config_zephyr = {
.sockCreate = SlNetIfWifi_socket,
.sockClose = SlNetIfWifi_close,
.sockSelect = SlNetIfWifi_select,
.sockSetOpt = SlNetIfWifi_setSockOpt,
.sockGetOpt = SlNetIfWifi_getSockOpt,
.sockRecvFrom = SlNetIfWifi_recvFrom,
.sockSendTo = SlNetIfWifi_sendTo,
.utilGetHostByName = SlNetIfWifi_getHostByName,
.ifGetIPAddr = SlNetIfWifi_getIPAddr,
.ifGetConnectionStatus = SlNetIfWifi_getConnectionStatus
};
/* Configure the device to a default state, resetting previous parameters .*/
static int32_t configure_simplelink(void)
{
@ -442,6 +462,23 @@ void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *netapp_event)
netapp_event->Id);
break;
}
if ((netapp_event->Id == SL_NETAPP_EVENT_IPV4_ACQUIRED) ||
(netapp_event->Id == SL_NETAPP_EVENT_IPV6_ACQUIRED)) {
/* Initialize SlNetSock layer for getaddrinfo */
SlNetIf_init(0);
/*
* We are only using SlNetSock to support getaddrinfo()
* for the WiFi interface, so hardcoding the interface
* id to 1 here.
*/
SlNetIf_add(SLNETIF_ID_1, SLNET_IF_WIFI_NAME,
(const SlNetIf_Config_t *)&slnetifwifi_config_zephyr,
SLNET_IF_WIFI_PRIO);
SlNetSock_init(0);
SlNetUtil_init(0);
}
}
/**