1326 lines
36 KiB
C
1326 lines
36 KiB
C
|
/****************************************************************************
|
||
|
* drivers/modem/alt1250/altcom_hdlr_socket.c
|
||
|
*
|
||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||
|
* contributor license agreements. See the NOTICE file distributed with
|
||
|
* this work for additional information regarding copyright ownership. The
|
||
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||
|
* "License"); you may not use this file except in compliance with the
|
||
|
* License. You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||
|
* License for the specific language governing permissions and limitations
|
||
|
* under the License.
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
|
||
|
/****************************************************************************
|
||
|
* Included Files
|
||
|
****************************************************************************/
|
||
|
|
||
|
#include <nuttx/config.h>
|
||
|
|
||
|
#include <stdint.h>
|
||
|
#include <stddef.h>
|
||
|
#include <string.h>
|
||
|
#include <errno.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/socket.h>
|
||
|
#include <netinet/in.h>
|
||
|
#include <netinet/tcp.h>
|
||
|
#include <nuttx/modem/alt1250.h>
|
||
|
|
||
|
#include "altcom_cmd_sock.h"
|
||
|
#include "altcom_errno.h"
|
||
|
|
||
|
/****************************************************************************
|
||
|
* Pre-processor Definitions
|
||
|
****************************************************************************/
|
||
|
|
||
|
#define READSET_BIT (1 << 0)
|
||
|
#define WRITESET_BIT (1 << 1)
|
||
|
#define EXCEPTSET_BIT (1 << 2)
|
||
|
|
||
|
#define ALTCOM_SO_SETMODE_8BIT (1)
|
||
|
#define ALTCOM_SO_SETMODE_32BIT (2)
|
||
|
#define ALTCOM_SO_SETMODE_LINGER (3)
|
||
|
#define ALTCOM_SO_SETMODE_INADDR (4)
|
||
|
#define ALTCOM_SO_SETMODE_IPMREQ (5)
|
||
|
|
||
|
/****************************************************************************
|
||
|
* Private Functions
|
||
|
****************************************************************************/
|
||
|
|
||
|
static void sockaddr2altstorage(FAR const struct sockaddr *from,
|
||
|
FAR struct altcom_sockaddr_storage *to)
|
||
|
{
|
||
|
FAR struct sockaddr_in *inaddr_from;
|
||
|
FAR struct sockaddr_in6 *in6addr_from;
|
||
|
FAR struct altcom_sockaddr_in *inaddr_to;
|
||
|
FAR struct altcom_sockaddr_in6 *in6addr_to;
|
||
|
|
||
|
if (from->sa_family == AF_INET)
|
||
|
{
|
||
|
inaddr_from = (FAR struct sockaddr_in *)from;
|
||
|
inaddr_to = (FAR struct altcom_sockaddr_in *)to;
|
||
|
|
||
|
inaddr_to->sin_len = sizeof(struct altcom_sockaddr_in);
|
||
|
inaddr_to->sin_family = ALTCOM_AF_INET;
|
||
|
inaddr_to->sin_port = inaddr_from->sin_port;
|
||
|
memcpy(&inaddr_to->sin_addr, &inaddr_from->sin_addr,
|
||
|
sizeof(struct altcom_in_addr));
|
||
|
}
|
||
|
else if (from->sa_family == AF_INET6)
|
||
|
{
|
||
|
in6addr_from = (FAR struct sockaddr_in6 *)from;
|
||
|
in6addr_to = (FAR struct altcom_sockaddr_in6 *)to;
|
||
|
|
||
|
in6addr_to->sin6_len = sizeof(struct altcom_sockaddr_in6);
|
||
|
in6addr_to->sin6_family = ALTCOM_AF_INET6;
|
||
|
in6addr_to->sin6_port = in6addr_from->sin6_port;
|
||
|
memcpy(&in6addr_to->sin6_addr, &in6addr_from->sin6_addr,
|
||
|
sizeof(struct altcom_in6_addr));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void altstorage2sockaddr(
|
||
|
FAR const struct altcom_sockaddr_storage *from, FAR struct sockaddr *to)
|
||
|
{
|
||
|
FAR struct altcom_sockaddr_in *inaddr_from;
|
||
|
FAR struct altcom_sockaddr_in6 *in6addr_from;
|
||
|
FAR struct sockaddr_in *inaddr_to;
|
||
|
FAR struct sockaddr_in6 *in6addr_to;
|
||
|
|
||
|
if (from->ss_family == ALTCOM_AF_INET)
|
||
|
{
|
||
|
inaddr_from = (FAR struct altcom_sockaddr_in *)from;
|
||
|
inaddr_to = (FAR struct sockaddr_in *)to;
|
||
|
|
||
|
inaddr_to->sin_family = AF_INET;
|
||
|
inaddr_to->sin_port = inaddr_from->sin_port;
|
||
|
memcpy(&inaddr_to->sin_addr, &inaddr_from->sin_addr,
|
||
|
sizeof(struct in_addr));
|
||
|
|
||
|
/* LwIP does not use this member, so it should be set to 0 */
|
||
|
|
||
|
memset(inaddr_to->sin_zero, 0, sizeof(inaddr_to->sin_zero));
|
||
|
}
|
||
|
else if (from->ss_family == ALTCOM_AF_INET6)
|
||
|
{
|
||
|
in6addr_from = (FAR struct altcom_sockaddr_in6 *)from;
|
||
|
in6addr_to = (FAR struct sockaddr_in6 *)to;
|
||
|
|
||
|
in6addr_to->sin6_family = AF_INET6;
|
||
|
in6addr_to->sin6_port = in6addr_from->sin6_port;
|
||
|
memcpy(&in6addr_to->sin6_addr, &in6addr_from->sin6_addr,
|
||
|
sizeof(struct in6_addr));
|
||
|
|
||
|
/* LwIP does not use thease members, so it should be set to 0 */
|
||
|
|
||
|
in6addr_to->sin6_flowinfo = 0;
|
||
|
in6addr_to->sin6_scope_id = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int flags2altflags(int32_t flags, FAR int32_t *altflags)
|
||
|
{
|
||
|
if (flags & (MSG_DONTROUTE | MSG_CTRUNC | MSG_PROXY | MSG_TRUNC |
|
||
|
MSG_EOR | MSG_FIN | MSG_SYN | MSG_CONFIRM |
|
||
|
MSG_RST | MSG_ERRQUEUE | MSG_NOSIGNAL))
|
||
|
{
|
||
|
return -ENOPROTOOPT;
|
||
|
}
|
||
|
|
||
|
*altflags = 0;
|
||
|
|
||
|
if (flags & MSG_PEEK)
|
||
|
{
|
||
|
*altflags |= ALTCOM_MSG_PEEK;
|
||
|
}
|
||
|
|
||
|
if (flags & MSG_WAITALL)
|
||
|
{
|
||
|
*altflags |= ALTCOM_MSG_WAITALL;
|
||
|
}
|
||
|
|
||
|
if (flags & MSG_OOB)
|
||
|
{
|
||
|
*altflags |= ALTCOM_MSG_OOB;
|
||
|
}
|
||
|
|
||
|
if (flags & MSG_DONTWAIT)
|
||
|
{
|
||
|
*altflags |= ALTCOM_MSG_DONTWAIT;
|
||
|
}
|
||
|
|
||
|
if (flags & MSG_MORE)
|
||
|
{
|
||
|
*altflags |= ALTCOM_MSG_MORE;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int get_so_setmode(uint16_t level, uint16_t option)
|
||
|
{
|
||
|
int setmode = 0;
|
||
|
|
||
|
switch (level)
|
||
|
{
|
||
|
case SOL_SOCKET:
|
||
|
switch (option)
|
||
|
{
|
||
|
case SO_ACCEPTCONN:
|
||
|
case SO_ERROR:
|
||
|
case SO_BROADCAST:
|
||
|
case SO_KEEPALIVE:
|
||
|
case SO_REUSEADDR:
|
||
|
case SO_TYPE:
|
||
|
case SO_RCVBUF:
|
||
|
setmode = ALTCOM_SO_SETMODE_32BIT;
|
||
|
break;
|
||
|
#ifdef CONFIG_NET_SOLINGER
|
||
|
case SO_LINGER:
|
||
|
setmode = ALTCOM_SO_SETMODE_LINGER;
|
||
|
break;
|
||
|
#endif
|
||
|
default:
|
||
|
m_err("Not support option: %u\n", option);
|
||
|
setmode = -EILSEQ;
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case IPPROTO_IP:
|
||
|
switch (option)
|
||
|
{
|
||
|
case IP_TOS:
|
||
|
case IP_TTL:
|
||
|
setmode = ALTCOM_SO_SETMODE_32BIT;
|
||
|
break;
|
||
|
case IP_MULTICAST_TTL:
|
||
|
case IP_MULTICAST_LOOP:
|
||
|
setmode = ALTCOM_SO_SETMODE_8BIT;
|
||
|
break;
|
||
|
case IP_MULTICAST_IF:
|
||
|
setmode = ALTCOM_SO_SETMODE_INADDR;
|
||
|
break;
|
||
|
case IP_ADD_MEMBERSHIP:
|
||
|
case IP_DROP_MEMBERSHIP:
|
||
|
setmode = ALTCOM_SO_SETMODE_IPMREQ;
|
||
|
break;
|
||
|
default:
|
||
|
m_err("Not support option: %u\n", option);
|
||
|
setmode = -EILSEQ;
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case IPPROTO_TCP:
|
||
|
switch (option)
|
||
|
{
|
||
|
case TCP_NODELAY:
|
||
|
case TCP_KEEPIDLE:
|
||
|
case TCP_KEEPINTVL:
|
||
|
setmode = ALTCOM_SO_SETMODE_32BIT;
|
||
|
break;
|
||
|
default:
|
||
|
m_err("Not support option: %u\n", option);
|
||
|
setmode = -EILSEQ;
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case IPPROTO_IPV6:
|
||
|
switch (option)
|
||
|
{
|
||
|
case IPV6_V6ONLY:
|
||
|
setmode = ALTCOM_SO_SETMODE_32BIT;
|
||
|
break;
|
||
|
default:
|
||
|
m_err("Not support option: %u\n", option);
|
||
|
setmode = -EILSEQ;
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
m_err("Not support level: %u\n", level);
|
||
|
setmode = -EILSEQ;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return setmode;
|
||
|
}
|
||
|
|
||
|
static int32_t sockaddrlen_pkt_compose(FAR void **arg, size_t arglen,
|
||
|
uint8_t altver, FAR uint8_t *pktbuf,
|
||
|
const size_t pktsz)
|
||
|
{
|
||
|
int32_t size = 0;
|
||
|
FAR int16_t *usockid = (FAR int16_t *)arg[0];
|
||
|
FAR int16_t *addrlen = (FAR int16_t *)arg[1];
|
||
|
|
||
|
FAR struct altmdmpkt_sockaddrlen_s *out =
|
||
|
(FAR struct altmdmpkt_sockaddrlen_s *)pktbuf;
|
||
|
|
||
|
out->sockfd = htonl(*usockid);
|
||
|
if (*addrlen == sizeof(struct sockaddr_in))
|
||
|
{
|
||
|
out->addrlen = htonl(sizeof(struct altcom_sockaddr_in));
|
||
|
}
|
||
|
else if (*addrlen == sizeof(struct sockaddr_in6))
|
||
|
{
|
||
|
out->addrlen = htonl(sizeof(struct altcom_sockaddr_in6));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
size = -EINVAL;
|
||
|
}
|
||
|
|
||
|
if (size == 0)
|
||
|
{
|
||
|
size = sizeof(struct altmdmpkt_sockaddrlen_s);
|
||
|
}
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
static int32_t sockaddr_pkt_compose(FAR void **arg, size_t arglen,
|
||
|
uint8_t altver, FAR uint8_t *pktbuf,
|
||
|
const size_t pktsz)
|
||
|
{
|
||
|
int32_t size = 0;
|
||
|
FAR int16_t *usockid = (FAR int16_t *)arg[0];
|
||
|
FAR int16_t *addrlen = (FAR int16_t *)arg[1];
|
||
|
FAR struct sockaddr_storage *sa = (FAR struct sockaddr_storage *)arg[2];
|
||
|
|
||
|
FAR struct altmdmpkt_sockaddr_s *out =
|
||
|
(FAR struct altmdmpkt_sockaddr_s *)pktbuf;
|
||
|
struct altcom_sockaddr_storage altsa;
|
||
|
|
||
|
out->sockfd = htonl(*usockid);
|
||
|
if (*addrlen == sizeof(struct sockaddr_in))
|
||
|
{
|
||
|
out->namelen = htonl(sizeof(struct altcom_sockaddr_in));
|
||
|
}
|
||
|
else if (*addrlen == sizeof(struct sockaddr_in6))
|
||
|
{
|
||
|
out->namelen = htonl(sizeof(struct altcom_sockaddr_in6));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
size = -EINVAL;
|
||
|
}
|
||
|
|
||
|
sockaddr2altstorage((struct sockaddr *)sa, &altsa);
|
||
|
memcpy(&out->name, &altsa, sizeof(struct altcom_sockaddr_storage));
|
||
|
|
||
|
if (size == 0)
|
||
|
{
|
||
|
size = sizeof(struct altmdmpkt_sockaddr_s);
|
||
|
}
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
/****************************************************************************
|
||
|
* Public Functions
|
||
|
****************************************************************************/
|
||
|
|
||
|
int32_t altcom_socket_pkt_compose(FAR void **arg, size_t arglen,
|
||
|
uint8_t altver, FAR uint8_t *pktbuf,
|
||
|
const size_t pktsz, FAR uint16_t *altcid)
|
||
|
{
|
||
|
int32_t size = 0;
|
||
|
FAR int16_t *domain = (FAR int16_t *)arg[0];
|
||
|
FAR int16_t *type = (FAR int16_t *)arg[1];
|
||
|
FAR int16_t *protocol = (FAR int16_t *)arg[2];
|
||
|
|
||
|
FAR struct apicmd_socket_s *out =
|
||
|
(FAR struct apicmd_socket_s *)pktbuf;
|
||
|
|
||
|
/* convert domain */
|
||
|
|
||
|
if (*domain == PF_UNSPEC)
|
||
|
{
|
||
|
out->domain = htonl(ALTCOM_PF_UNSPEC);
|
||
|
}
|
||
|
else if (*domain == PF_INET)
|
||
|
{
|
||
|
out->domain = htonl(ALTCOM_PF_INET);
|
||
|
}
|
||
|
else if (*domain == PF_INET6)
|
||
|
{
|
||
|
out->domain = htonl(ALTCOM_PF_INET6);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
size = -EAFNOSUPPORT;
|
||
|
}
|
||
|
|
||
|
/* convert type */
|
||
|
|
||
|
if (*type == SOCK_STREAM)
|
||
|
{
|
||
|
out->type = htonl(ALTCOM_SOCK_STREAM);
|
||
|
}
|
||
|
else if (*type == SOCK_DGRAM)
|
||
|
{
|
||
|
out->type = htonl(ALTCOM_SOCK_DGRAM);
|
||
|
}
|
||
|
else if (*type == SOCK_RAW)
|
||
|
{
|
||
|
out->type = htonl(ALTCOM_SOCK_RAW);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
size = -EAFNOSUPPORT;
|
||
|
}
|
||
|
|
||
|
/* convert protocol */
|
||
|
|
||
|
if (*protocol == IPPROTO_IP)
|
||
|
{
|
||
|
out->protocol = htonl(ALTCOM_IPPROTO_IP);
|
||
|
}
|
||
|
else if (*protocol == IPPROTO_ICMP)
|
||
|
{
|
||
|
out->protocol = htonl(ALTCOM_IPPROTO_ICMP);
|
||
|
}
|
||
|
else if (*protocol == IPPROTO_TCP)
|
||
|
{
|
||
|
out->protocol = htonl(ALTCOM_IPPROTO_TCP);
|
||
|
}
|
||
|
else if (*protocol == IPPROTO_UDP)
|
||
|
{
|
||
|
out->protocol = htonl(ALTCOM_IPPROTO_UDP);
|
||
|
}
|
||
|
else if (*protocol == IPPROTO_IPV6)
|
||
|
{
|
||
|
out->protocol = htonl(ALTCOM_IPPROTO_IPV6);
|
||
|
}
|
||
|
else if (*protocol == IPPROTO_ICMP6)
|
||
|
{
|
||
|
out->protocol = htonl(ALTCOM_IPPROTO_ICMPV6);
|
||
|
}
|
||
|
else if (*protocol == IPPROTO_UDPLITE)
|
||
|
{
|
||
|
out->protocol = htonl(ALTCOM_IPPROTO_UDPLITE);
|
||
|
}
|
||
|
else if (*protocol == IPPROTO_RAW)
|
||
|
{
|
||
|
out->protocol = htonl(ALTCOM_IPPROTO_RAW);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
size = -EAFNOSUPPORT;
|
||
|
}
|
||
|
|
||
|
if (size == 0)
|
||
|
{
|
||
|
size = sizeof(struct apicmd_socket_s);
|
||
|
}
|
||
|
|
||
|
*altcid = APICMDID_SOCK_SOCKET;
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
int32_t altcom_close_pkt_compose(FAR void **arg, size_t arglen,
|
||
|
uint8_t altver, FAR uint8_t *pktbuf,
|
||
|
const size_t pktsz, FAR uint16_t *altcid)
|
||
|
{
|
||
|
int32_t size = 0;
|
||
|
FAR int16_t *usockid = (FAR int16_t *)arg[0];
|
||
|
|
||
|
FAR struct apicmd_close_s *out =
|
||
|
(FAR struct apicmd_close_s *)pktbuf;
|
||
|
|
||
|
out->sockfd = htonl(*usockid);
|
||
|
|
||
|
size = sizeof(struct apicmd_close_s);
|
||
|
|
||
|
*altcid = APICMDID_SOCK_CLOSE;
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
int32_t altcom_accept_pkt_compose(FAR void **arg, size_t arglen,
|
||
|
uint8_t altver, FAR uint8_t *pktbuf,
|
||
|
const size_t pktsz, FAR uint16_t *altcid)
|
||
|
{
|
||
|
int32_t size = 0;
|
||
|
|
||
|
size = sockaddrlen_pkt_compose(arg, arglen, altver, pktbuf, pktsz);
|
||
|
|
||
|
*altcid = APICMDID_SOCK_ACCEPT;
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
int32_t altcom_bind_pkt_compose(FAR void **arg, size_t arglen,
|
||
|
uint8_t altver, FAR uint8_t *pktbuf,
|
||
|
const size_t pktsz, FAR uint16_t *altcid)
|
||
|
{
|
||
|
int32_t size = 0;
|
||
|
|
||
|
size = sockaddr_pkt_compose(arg, arglen, altver, pktbuf, pktsz);
|
||
|
|
||
|
*altcid = APICMDID_SOCK_BIND;
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
int32_t altcom_connect_pkt_compose(FAR void **arg, size_t arglen,
|
||
|
uint8_t altver, FAR uint8_t *pktbuf,
|
||
|
const size_t pktsz, FAR uint16_t *altcid)
|
||
|
{
|
||
|
int32_t size = 0;
|
||
|
|
||
|
size = sockaddr_pkt_compose(arg, arglen, altver, pktbuf, pktsz);
|
||
|
|
||
|
*altcid = APICMDID_SOCK_CONNECT;
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
int32_t altcom_fcntl_pkt_compose(FAR void **arg, size_t arglen,
|
||
|
uint8_t altver, FAR uint8_t *pktbuf,
|
||
|
const size_t pktsz, FAR uint16_t *altcid)
|
||
|
{
|
||
|
int32_t size = 0;
|
||
|
FAR int32_t *sockfd = (FAR int32_t *)arg[0];
|
||
|
FAR int32_t *cmd = (FAR int32_t *)arg[1];
|
||
|
FAR int32_t *val = (FAR int32_t *)arg[2];
|
||
|
|
||
|
FAR struct apicmd_fcntl_s *out =
|
||
|
(FAR struct apicmd_fcntl_s *)pktbuf;
|
||
|
|
||
|
out->sockfd = htonl(*sockfd);
|
||
|
out->cmd = htonl(*cmd);
|
||
|
out->val = htonl(*val);
|
||
|
|
||
|
if (size == 0)
|
||
|
{
|
||
|
size = sizeof(struct apicmd_fcntl_s);
|
||
|
}
|
||
|
|
||
|
*altcid = APICMDID_SOCK_FCNTL;
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
int32_t altcom_getsockname_pkt_compose(FAR void **arg, size_t arglen,
|
||
|
uint8_t altver, FAR uint8_t *pktbuf,
|
||
|
const size_t pktsz,
|
||
|
FAR uint16_t *altcid)
|
||
|
{
|
||
|
int32_t size = 0;
|
||
|
|
||
|
size = sockaddrlen_pkt_compose(arg, arglen, altver, pktbuf, pktsz);
|
||
|
|
||
|
*altcid = APICMDID_SOCK_GETSOCKNAME;
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
int32_t altcom_getsockopt_pkt_compose(FAR void **arg, size_t arglen,
|
||
|
uint8_t altver, FAR uint8_t *pktbuf,
|
||
|
const size_t pktsz,
|
||
|
FAR uint16_t *altcid)
|
||
|
{
|
||
|
int32_t size = 0;
|
||
|
FAR int32_t *sockfd = (FAR int32_t *)arg[0];
|
||
|
FAR int16_t *level = (FAR int16_t *)arg[1];
|
||
|
FAR int16_t *option = (FAR int16_t *)arg[2];
|
||
|
FAR uint16_t *max_valuelen = (FAR uint16_t *)arg[3];
|
||
|
|
||
|
FAR struct apicmd_getsockopt_s *out =
|
||
|
(FAR struct apicmd_getsockopt_s *)pktbuf;
|
||
|
|
||
|
out->sockfd = htonl(*sockfd);
|
||
|
if (*level == SOL_SOCKET)
|
||
|
{
|
||
|
out->level = htonl(ALTCOM_SOL_SOCKET);
|
||
|
out->optlen = htonl(*max_valuelen);
|
||
|
|
||
|
if (*option == SO_ACCEPTCONN)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_SO_ACCEPTCONN);
|
||
|
}
|
||
|
else if (*option == SO_ERROR)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_SO_ERROR);
|
||
|
}
|
||
|
else if (*option == SO_BROADCAST)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_SO_BROADCAST);
|
||
|
}
|
||
|
else if (*option == SO_KEEPALIVE)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_SO_KEEPALIVE);
|
||
|
}
|
||
|
else if (*option == SO_REUSEADDR)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_SO_REUSEADDR);
|
||
|
}
|
||
|
else if (*option == SO_TYPE)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_SO_TYPE);
|
||
|
}
|
||
|
else if (*option == SO_RCVBUF)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_SO_RCVBUF);
|
||
|
}
|
||
|
#ifdef CONFIG_NET_SOLINGER
|
||
|
else if (*option == SO_LINGER)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_SO_LINGER);
|
||
|
}
|
||
|
#endif
|
||
|
else
|
||
|
{
|
||
|
size = -ENOPROTOOPT;
|
||
|
}
|
||
|
}
|
||
|
else if (*level == IPPROTO_IP)
|
||
|
{
|
||
|
out->level = htonl(ALTCOM_IPPROTO_IP);
|
||
|
out->optlen = htonl(*max_valuelen);
|
||
|
|
||
|
if (*option == IP_TOS)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_IP_TOS);
|
||
|
}
|
||
|
else if (*option == IP_TTL)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_IP_TTL);
|
||
|
}
|
||
|
else if (*option == IP_MULTICAST_TTL)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_IP_MULTICAST_TTL);
|
||
|
}
|
||
|
else if (*option == IP_MULTICAST_LOOP)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_IP_MULTICAST_LOOP);
|
||
|
}
|
||
|
else if (*option == IP_MULTICAST_IF)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_IP_MULTICAST_IF);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
size = -ENOPROTOOPT;
|
||
|
}
|
||
|
}
|
||
|
else if (*level == IPPROTO_TCP)
|
||
|
{
|
||
|
out->level = htonl(ALTCOM_IPPROTO_TCP);
|
||
|
out->optlen = htonl(*max_valuelen);
|
||
|
if (*option == TCP_NODELAY)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_TCP_NODELAY);
|
||
|
}
|
||
|
else if (*option == TCP_KEEPIDLE)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_TCP_KEEPIDLE);
|
||
|
}
|
||
|
else if (*option == TCP_KEEPINTVL)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_TCP_KEEPINTVL);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
size = -ENOPROTOOPT;
|
||
|
}
|
||
|
}
|
||
|
else if (*level == IPPROTO_IPV6)
|
||
|
{
|
||
|
out->level = htonl(ALTCOM_IPPROTO_IPV6);
|
||
|
out->optlen = htonl(*max_valuelen);
|
||
|
if (*option == IPV6_V6ONLY)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_IPV6_V6ONLY);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
size = -ENOPROTOOPT;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
size = -ENOPROTOOPT;
|
||
|
}
|
||
|
|
||
|
if (size == 0)
|
||
|
{
|
||
|
size = sizeof(struct apicmd_getsockopt_s);
|
||
|
}
|
||
|
|
||
|
*altcid = APICMDID_SOCK_GETSOCKOPT;
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
int32_t altcom_listen_pkt_compose(FAR void **arg, size_t arglen,
|
||
|
uint8_t altver, FAR uint8_t *pktbuf,
|
||
|
const size_t pktsz, FAR uint16_t *altcid)
|
||
|
{
|
||
|
int32_t size = 0;
|
||
|
FAR int32_t *sockfd = (FAR int32_t *)arg[0];
|
||
|
FAR uint16_t *backlog = (FAR uint16_t *)arg[1];
|
||
|
|
||
|
FAR struct apicmd_listen_s *out =
|
||
|
(FAR struct apicmd_listen_s *)pktbuf;
|
||
|
|
||
|
out->sockfd = htonl(*sockfd);
|
||
|
out->backlog = htonl(*backlog);
|
||
|
|
||
|
size = sizeof(struct apicmd_listen_s);
|
||
|
|
||
|
*altcid = APICMDID_SOCK_LISTEN;
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
int32_t altcom_recvfrom_pkt_compose(FAR void **arg, size_t arglen,
|
||
|
uint8_t altver, FAR uint8_t *pktbuf,
|
||
|
const size_t pktsz, FAR uint16_t *altcid)
|
||
|
{
|
||
|
int32_t size = 0;
|
||
|
FAR int32_t *sockfd = (FAR int32_t *)arg[0];
|
||
|
FAR int32_t *flags = (FAR int32_t *)arg[1];
|
||
|
FAR uint16_t *max_buflen = (FAR uint16_t *)arg[2];
|
||
|
FAR uint16_t *max_addrlen = (FAR uint16_t *)arg[3];
|
||
|
|
||
|
FAR struct apicmd_recvfrom_s *out =
|
||
|
(FAR struct apicmd_recvfrom_s *)pktbuf;
|
||
|
int32_t flg;
|
||
|
|
||
|
out->sockfd = htonl(*sockfd);
|
||
|
if (*max_buflen > APICMD_DATA_LENGTH)
|
||
|
{
|
||
|
/* Truncate the length to the maximum transfer size */
|
||
|
|
||
|
*max_buflen = APICMD_DATA_LENGTH;
|
||
|
}
|
||
|
|
||
|
out->recvlen = htonl(*max_buflen);
|
||
|
size = flags2altflags(*flags, &flg);
|
||
|
out->flags = htonl(flg);
|
||
|
if (*max_addrlen == sizeof(struct sockaddr_in))
|
||
|
{
|
||
|
out->fromlen = htonl(sizeof(struct altcom_sockaddr_in));
|
||
|
}
|
||
|
else if (*max_addrlen == sizeof(struct sockaddr_in6))
|
||
|
{
|
||
|
out->fromlen = htonl(sizeof(struct altcom_sockaddr_in6));
|
||
|
}
|
||
|
else if (*max_addrlen == 0)
|
||
|
{
|
||
|
out->fromlen = htonl(0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
size = -EINVAL;
|
||
|
}
|
||
|
|
||
|
if (size == 0)
|
||
|
{
|
||
|
size = sizeof(struct apicmd_recvfrom_s);
|
||
|
}
|
||
|
|
||
|
*altcid = APICMDID_SOCK_RECVFROM;
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
int32_t altcom_sendto_pkt_compose(FAR void **arg, size_t arglen,
|
||
|
uint8_t altver, FAR uint8_t *pktbuf,
|
||
|
const size_t pktsz, FAR uint16_t *altcid)
|
||
|
{
|
||
|
int32_t size = 0;
|
||
|
FAR int32_t *sockfd = (FAR int32_t *)arg[0];
|
||
|
FAR int32_t *flags = (FAR int32_t *)arg[1];
|
||
|
FAR uint16_t *addrlen = (FAR uint16_t *)arg[2];
|
||
|
FAR uint16_t *buflen = (FAR uint16_t *)arg[3];
|
||
|
FAR struct sockaddr_storage *sa = (FAR struct sockaddr_storage *)arg[4];
|
||
|
FAR uint8_t *buf = (FAR uint8_t *)arg[5];
|
||
|
|
||
|
FAR struct apicmd_sendto_s *out =
|
||
|
(FAR struct apicmd_sendto_s *)pktbuf;
|
||
|
int32_t flg;
|
||
|
struct altcom_sockaddr_storage altsa;
|
||
|
|
||
|
if (*buflen > APICMD_DATA_LENGTH)
|
||
|
{
|
||
|
/* Truncate the length to the maximum transfer size */
|
||
|
|
||
|
*buflen = APICMD_DATA_LENGTH;
|
||
|
}
|
||
|
else if (*buflen < 0)
|
||
|
{
|
||
|
size = -EINVAL;
|
||
|
goto err_out;
|
||
|
}
|
||
|
|
||
|
if (*buflen > 0 && !buf)
|
||
|
{
|
||
|
size = -EINVAL;
|
||
|
goto err_out;
|
||
|
}
|
||
|
|
||
|
if (sa && !(*addrlen))
|
||
|
{
|
||
|
size = -EINVAL;
|
||
|
goto err_out;
|
||
|
}
|
||
|
|
||
|
out->sockfd = htonl(*sockfd);
|
||
|
size = flags2altflags(*flags, &flg);
|
||
|
if (size != 0)
|
||
|
{
|
||
|
goto err_out;
|
||
|
}
|
||
|
|
||
|
out->flags = htonl(flg);
|
||
|
out->datalen = htonl(*buflen);
|
||
|
if (*addrlen == sizeof(struct sockaddr_in))
|
||
|
{
|
||
|
out->tolen = htonl(sizeof(struct altcom_sockaddr_in));
|
||
|
}
|
||
|
else if (*addrlen == sizeof(struct sockaddr_in6))
|
||
|
{
|
||
|
out->tolen = htonl(sizeof(struct altcom_sockaddr_in6));
|
||
|
}
|
||
|
else if (*addrlen == 0)
|
||
|
{
|
||
|
out->tolen = htonl(0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
size = -EINVAL;
|
||
|
}
|
||
|
|
||
|
if (size == 0)
|
||
|
{
|
||
|
memset(&altsa, 0, sizeof(struct altcom_sockaddr_storage));
|
||
|
sockaddr2altstorage((struct sockaddr *)sa, &altsa);
|
||
|
memcpy(&out->to, &altsa, *addrlen);
|
||
|
memcpy(out->senddata, buf, *buflen);
|
||
|
size = sizeof(struct apicmd_sendto_s) - sizeof(out->senddata) +
|
||
|
*buflen;
|
||
|
}
|
||
|
|
||
|
err_out:
|
||
|
*altcid = APICMDID_SOCK_SENDTO;
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
int32_t altcom_setsockopt_pkt_compose(FAR void **arg, size_t arglen,
|
||
|
uint8_t altver, FAR uint8_t *pktbuf,
|
||
|
const size_t pktsz,
|
||
|
FAR uint16_t *altcid)
|
||
|
{
|
||
|
int32_t size = 0;
|
||
|
FAR int32_t *sockfd = (FAR int32_t *)arg[0];
|
||
|
FAR int16_t *level = (FAR int16_t *)arg[1];
|
||
|
FAR int16_t *option = (FAR int16_t *)arg[2];
|
||
|
FAR uint16_t *valuelen = (FAR uint16_t *)arg[3];
|
||
|
FAR uint8_t *value = (FAR uint8_t *)arg[4];
|
||
|
|
||
|
FAR struct apicmd_setsockopt_s *out =
|
||
|
(FAR struct apicmd_setsockopt_s *)pktbuf;
|
||
|
|
||
|
int setmode = 0;
|
||
|
|
||
|
out->sockfd = htonl(*sockfd);
|
||
|
if (*level == SOL_SOCKET)
|
||
|
{
|
||
|
out->level = htonl(ALTCOM_SOL_SOCKET);
|
||
|
out->optlen = htonl(*valuelen);
|
||
|
|
||
|
if (*option == SO_BROADCAST)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_SO_BROADCAST);
|
||
|
}
|
||
|
else if (*option == SO_REUSEADDR)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_SO_REUSEADDR);
|
||
|
}
|
||
|
else if (*option == SO_KEEPALIVE)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_SO_KEEPALIVE);
|
||
|
}
|
||
|
else if (*option == SO_RCVBUF)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_SO_RCVBUF);
|
||
|
}
|
||
|
#ifdef CONFIG_NET_SOLINGER
|
||
|
else if (*option == SO_LINGER)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_SO_LINGER);
|
||
|
}
|
||
|
#endif
|
||
|
else
|
||
|
{
|
||
|
size = -ENOPROTOOPT;
|
||
|
}
|
||
|
}
|
||
|
else if (*level == IPPROTO_IP)
|
||
|
{
|
||
|
out->level = htonl(ALTCOM_IPPROTO_IP);
|
||
|
out->optlen = htonl(*valuelen);
|
||
|
|
||
|
if (*option == IP_TOS)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_IP_TOS);
|
||
|
}
|
||
|
else if (*option == IP_TTL)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_IP_TTL);
|
||
|
}
|
||
|
else if (*option == IP_MULTICAST_TTL)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_IP_MULTICAST_TTL);
|
||
|
}
|
||
|
else if (*option == IP_MULTICAST_LOOP)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_IP_MULTICAST_LOOP);
|
||
|
}
|
||
|
else if (*option == IP_MULTICAST_IF)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_IP_MULTICAST_IF);
|
||
|
}
|
||
|
else if (*option == IP_ADD_MEMBERSHIP)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_IP_ADD_MEMBERSHIP);
|
||
|
}
|
||
|
else if (*option == IP_DROP_MEMBERSHIP)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_IP_DROP_MEMBERSHIP);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
size = -ENOPROTOOPT;
|
||
|
}
|
||
|
}
|
||
|
else if (*level == IPPROTO_TCP)
|
||
|
{
|
||
|
out->level = htonl(ALTCOM_IPPROTO_TCP);
|
||
|
out->optlen = htonl(*valuelen);
|
||
|
if (*option == TCP_NODELAY)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_TCP_NODELAY);
|
||
|
}
|
||
|
else if (*option == TCP_KEEPIDLE)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_TCP_KEEPIDLE);
|
||
|
}
|
||
|
else if (*option == TCP_KEEPINTVL)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_TCP_KEEPINTVL);
|
||
|
}
|
||
|
else if (*option == TCP_KEEPCNT)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_TCP_KEEPCNT);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
size = -ENOPROTOOPT;
|
||
|
}
|
||
|
}
|
||
|
else if (*level == IPPROTO_IPV6)
|
||
|
{
|
||
|
out->level = htonl(ALTCOM_IPPROTO_IPV6);
|
||
|
out->optlen = htonl(*valuelen);
|
||
|
if (*option == IPV6_V6ONLY)
|
||
|
{
|
||
|
out->optname = htonl(ALTCOM_IPV6_V6ONLY);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
size = -ENOPROTOOPT;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
size = -ENOPROTOOPT;
|
||
|
}
|
||
|
|
||
|
if (size < 0)
|
||
|
{
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
setmode = get_so_setmode(*level, *option);
|
||
|
|
||
|
switch (setmode)
|
||
|
{
|
||
|
case ALTCOM_SO_SETMODE_8BIT:
|
||
|
if (*valuelen < sizeof(int8_t))
|
||
|
{
|
||
|
m_err("Unexpected valuelen: actual=%lu expect=%lu\n",
|
||
|
*valuelen, sizeof(int8_t));
|
||
|
size = -EINVAL;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
*out->optval = value[0];
|
||
|
break;
|
||
|
case ALTCOM_SO_SETMODE_32BIT:
|
||
|
if (*valuelen < sizeof(int32_t))
|
||
|
{
|
||
|
m_err("Unexpected valuelen: actual=%lu expect=%lu\n",
|
||
|
*valuelen, sizeof(int32_t));
|
||
|
size = -EINVAL;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
*((FAR int32_t *)out->optval) =
|
||
|
htonl(*((FAR int32_t *)value));
|
||
|
break;
|
||
|
case ALTCOM_SO_SETMODE_LINGER:
|
||
|
if (*valuelen < sizeof(struct linger))
|
||
|
{
|
||
|
m_err("Unexpected valuelen: actual=%lu expect=%lu\n",
|
||
|
*valuelen, sizeof(struct linger));
|
||
|
size = -EINVAL;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
((FAR struct altcom_linger *)out->optval)->l_onoff =
|
||
|
htonl(((FAR struct linger *)value)->l_onoff);
|
||
|
((FAR struct altcom_linger *)out->optval)->l_linger =
|
||
|
htonl(((FAR struct linger *)value)->l_linger);
|
||
|
break;
|
||
|
case ALTCOM_SO_SETMODE_INADDR:
|
||
|
if (*valuelen < sizeof(struct in_addr))
|
||
|
{
|
||
|
m_err("Unexpected valuelen: actual=%lu expect=%lu\n",
|
||
|
*valuelen, sizeof(struct in_addr));
|
||
|
size = -EINVAL;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
((FAR struct altcom_in_addr *)out->optval)->s_addr =
|
||
|
htonl(((FAR struct in_addr *)value)->s_addr);
|
||
|
break;
|
||
|
case ALTCOM_SO_SETMODE_IPMREQ:
|
||
|
if (*valuelen < sizeof(struct ip_mreq))
|
||
|
{
|
||
|
m_err("Unexpected valuelen: actual=%lu expect=%lu\n",
|
||
|
*valuelen, sizeof(struct ip_mreq));
|
||
|
size = -EINVAL;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
((FAR struct altcom_ip_mreq *)out->optval)->imr_multiaddr.s_addr =
|
||
|
htonl(((FAR struct ip_mreq *)value)->imr_multiaddr.s_addr);
|
||
|
((FAR struct altcom_ip_mreq *)out->optval)->imr_interface.s_addr =
|
||
|
htonl(((FAR struct ip_mreq *)value)->imr_interface.s_addr);
|
||
|
break;
|
||
|
default:
|
||
|
size = -EINVAL;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
exit:
|
||
|
if (size == 0)
|
||
|
{
|
||
|
size = sizeof(struct apicmd_setsockopt_s);
|
||
|
}
|
||
|
|
||
|
*altcid = APICMDID_SOCK_SETSOCKOPT;
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
int32_t altcom_select_pkt_compose(FAR void **arg, size_t arglen,
|
||
|
uint8_t altver, FAR uint8_t *pktbuf,
|
||
|
const size_t pktsz, FAR uint16_t *altcid)
|
||
|
{
|
||
|
int32_t size = 0;
|
||
|
FAR int32_t *request = (FAR int32_t *)arg[0];
|
||
|
FAR int32_t *id = (FAR int32_t *)arg[1];
|
||
|
FAR int32_t *maxfds = (FAR int32_t *)arg[2];
|
||
|
FAR uint16_t *used_setbit = (FAR uint16_t *)arg[3];
|
||
|
FAR altcom_fd_set *readset = (FAR altcom_fd_set *)arg[4];
|
||
|
FAR altcom_fd_set *writeset = (FAR altcom_fd_set *)arg[5];
|
||
|
FAR altcom_fd_set *exceptset = (FAR altcom_fd_set *)arg[6];
|
||
|
|
||
|
FAR struct apicmd_select_s *out =
|
||
|
(FAR struct apicmd_select_s *)pktbuf;
|
||
|
|
||
|
out->request = htonl(*request);
|
||
|
out->id = htonl(*id);
|
||
|
out->maxfds = htonl(*maxfds);
|
||
|
out->used_setbit = htons(*used_setbit);
|
||
|
memcpy(&out->readset, readset, sizeof(altcom_fd_set));
|
||
|
memcpy(&out->writeset, writeset, sizeof(altcom_fd_set));
|
||
|
memcpy(&out->exceptset, exceptset, sizeof(altcom_fd_set));
|
||
|
|
||
|
size = sizeof(struct apicmd_select_s);
|
||
|
|
||
|
*altcid = APICMDID_SOCK_SELECT;
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
int32_t altcom_sockcomm_pkt_parse(FAR struct alt1250_dev_s *dev,
|
||
|
FAR uint8_t *pktbuf, size_t pktsz,
|
||
|
uint8_t altver, FAR void **arg,
|
||
|
size_t arglen, FAR uint64_t *bitmap)
|
||
|
{
|
||
|
FAR int32_t *ret = (FAR int32_t *)arg[0];
|
||
|
FAR int32_t *errcode = (FAR int32_t *)arg[1];
|
||
|
|
||
|
FAR struct altmdmpktr_sockcomm_s *in =
|
||
|
(FAR struct altmdmpktr_sockcomm_s *)pktbuf;
|
||
|
|
||
|
*ret = ntohl(in->ret_code);
|
||
|
*errcode = altcom_errno2nuttx(ntohl(in->err_code));
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int32_t altcom_scokaddr_pkt_parse(FAR struct alt1250_dev_s *dev,
|
||
|
FAR uint8_t *pktbuf, size_t pktsz,
|
||
|
uint8_t altver, FAR void **arg,
|
||
|
size_t arglen, FAR uint64_t *bitmap)
|
||
|
{
|
||
|
int32_t rc = OK;
|
||
|
FAR int32_t *ret = (FAR int32_t *)arg[0];
|
||
|
FAR int32_t *errcode = (FAR int32_t *)arg[1];
|
||
|
FAR uint32_t *addrlen = (FAR uint32_t *)arg[2];
|
||
|
FAR struct sockaddr_storage *sa = (FAR struct sockaddr_storage *)arg[3];
|
||
|
|
||
|
FAR struct altmdmpktr_sockaddr_s *in =
|
||
|
(FAR struct altmdmpktr_sockaddr_s *)pktbuf;
|
||
|
struct altcom_sockaddr_storage altsa;
|
||
|
|
||
|
*ret = ntohl(in->ret_code);
|
||
|
*errcode = altcom_errno2nuttx(ntohl(in->err_code));
|
||
|
|
||
|
if (*ret >= 0)
|
||
|
{
|
||
|
*addrlen = ntohl(in->addrlen);
|
||
|
if (*addrlen == sizeof(struct altcom_sockaddr_in))
|
||
|
{
|
||
|
*addrlen = sizeof(struct sockaddr_in);
|
||
|
}
|
||
|
else if (*addrlen == sizeof(struct altcom_sockaddr_in6))
|
||
|
{
|
||
|
*addrlen = sizeof(struct sockaddr_in6);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
rc = -EILSEQ;
|
||
|
}
|
||
|
|
||
|
memcpy(&altsa, &in->address, sizeof(struct altcom_sockaddr_storage));
|
||
|
altstorage2sockaddr(&altsa, (FAR struct sockaddr *)sa);
|
||
|
}
|
||
|
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
int32_t altcom_getsockopt_pkt_parse(FAR struct alt1250_dev_s *dev,
|
||
|
FAR uint8_t *pktbuf, size_t pktsz,
|
||
|
uint8_t altver, FAR void **arg,
|
||
|
size_t arglen, FAR uint64_t *bitmap)
|
||
|
{
|
||
|
int32_t rc = OK;
|
||
|
FAR int32_t *ret = (FAR int32_t *)arg[0];
|
||
|
FAR int32_t *errcode = (FAR int32_t *)arg[1];
|
||
|
FAR uint32_t *optlen = (FAR uint32_t *)arg[2];
|
||
|
FAR int8_t *optval = (FAR int8_t *)arg[3];
|
||
|
FAR uint16_t *level = (FAR uint16_t *)arg[4];
|
||
|
FAR uint16_t *option = (FAR uint16_t *)arg[5];
|
||
|
|
||
|
FAR struct apicmd_getsockoptres_s *in =
|
||
|
(FAR struct apicmd_getsockoptres_s *)pktbuf;
|
||
|
|
||
|
int setmode = 0;
|
||
|
|
||
|
*ret = ntohl(in->ret_code);
|
||
|
*errcode = altcom_errno2nuttx(ntohl(in->err_code));
|
||
|
|
||
|
if (*ret >= 0)
|
||
|
{
|
||
|
*optlen = ntohl(in->optlen);
|
||
|
if (*optlen > APICMD_OPTVAL_LENGTH)
|
||
|
{
|
||
|
rc = -EILSEQ;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
setmode = get_so_setmode(*level, *option);
|
||
|
|
||
|
switch (setmode)
|
||
|
{
|
||
|
case ALTCOM_SO_SETMODE_8BIT:
|
||
|
if (*optlen < sizeof(int8_t))
|
||
|
{
|
||
|
m_err("Unexpected optlen: actual=%lu expect=%lu\n",
|
||
|
*optlen, sizeof(int8_t));
|
||
|
rc = -EILSEQ;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
*optval = in->optval[0];
|
||
|
break;
|
||
|
case ALTCOM_SO_SETMODE_32BIT:
|
||
|
if (*optlen < sizeof(int32_t))
|
||
|
{
|
||
|
m_err("Unexpected optlen: actual=%lu expect=%lu\n",
|
||
|
*optlen, sizeof(int32_t));
|
||
|
rc = -EILSEQ;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
*((FAR int32_t *)optval) =
|
||
|
ntohl(*((FAR int32_t *)in->optval));
|
||
|
break;
|
||
|
case ALTCOM_SO_SETMODE_LINGER:
|
||
|
if (*optlen < sizeof(struct linger))
|
||
|
{
|
||
|
m_err("Unexpected optlen: actual=%lu expect=%lu\n",
|
||
|
*optlen, sizeof(struct linger));
|
||
|
rc = -EILSEQ;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
FAR struct altcom_linger *plinger;
|
||
|
|
||
|
plinger = (FAR struct altcom_linger *)&in->optval[0];
|
||
|
((FAR struct linger *)optval)->l_onoff =
|
||
|
ntohl(plinger->l_onoff);
|
||
|
((FAR struct linger *)optval)->l_linger =
|
||
|
ntohl(plinger->l_linger);
|
||
|
break;
|
||
|
case ALTCOM_SO_SETMODE_INADDR:
|
||
|
if (*optlen < sizeof(struct in_addr))
|
||
|
{
|
||
|
m_err("Unexpected optlen: actual=%lu expect=%lu\n",
|
||
|
*optlen, sizeof(struct in_addr));
|
||
|
rc = -EILSEQ;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
FAR struct altcom_in_addr *pinaddr;
|
||
|
|
||
|
pinaddr = (FAR struct altcom_in_addr *)&in->optval[0];
|
||
|
((FAR struct in_addr *)optval)->s_addr =
|
||
|
ntohl(pinaddr->s_addr);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
int32_t altcom_recvfrom_pkt_parse(FAR struct alt1250_dev_s *dev,
|
||
|
FAR uint8_t *pktbuf, size_t pktsz,
|
||
|
uint8_t altver, FAR void **arg,
|
||
|
size_t arglen, FAR uint64_t *bitmap)
|
||
|
{
|
||
|
int32_t rc = OK;
|
||
|
FAR int32_t *ret = (FAR int32_t *)arg[0];
|
||
|
FAR int32_t *errcode = (FAR int32_t *)arg[1];
|
||
|
FAR uint32_t *fromlen = (FAR uint32_t *)arg[2];
|
||
|
FAR struct sockaddr_storage *sa = (FAR struct sockaddr_storage *)arg[3];
|
||
|
FAR int8_t *buf = (FAR int8_t *)arg[4];
|
||
|
|
||
|
FAR struct apicmd_recvfromres_s *in =
|
||
|
(FAR struct apicmd_recvfromres_s *)pktbuf;
|
||
|
struct altcom_sockaddr_storage altsa;
|
||
|
|
||
|
*ret = ntohl(in->ret_code);
|
||
|
*errcode = altcom_errno2nuttx(ntohl(in->err_code));
|
||
|
|
||
|
if (*ret >= 0)
|
||
|
{
|
||
|
*fromlen = ntohl(in->fromlen);
|
||
|
if (*fromlen == sizeof(struct altcom_sockaddr_in))
|
||
|
{
|
||
|
*fromlen = sizeof(struct sockaddr_in);
|
||
|
}
|
||
|
else if (*fromlen == sizeof(struct altcom_sockaddr_in6))
|
||
|
{
|
||
|
*fromlen = sizeof(struct sockaddr_in6);
|
||
|
}
|
||
|
else if (*fromlen != 0)
|
||
|
{
|
||
|
rc = -EILSEQ;
|
||
|
}
|
||
|
|
||
|
if ((rc == OK) && (*fromlen != 0))
|
||
|
{
|
||
|
memcpy(&altsa, &in->from, *fromlen);
|
||
|
altstorage2sockaddr(&altsa, (FAR struct sockaddr *)sa);
|
||
|
}
|
||
|
|
||
|
if (*ret > APICMD_DATA_LENGTH)
|
||
|
{
|
||
|
rc = -EILSEQ;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
memcpy(buf, in->recvdata, *ret);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
int32_t altcom_select_pkt_parse(FAR struct alt1250_dev_s *dev,
|
||
|
FAR uint8_t *pktbuf, size_t pktsz,
|
||
|
uint8_t altver, FAR void **arg,
|
||
|
size_t arglen, FAR uint64_t *bitmap)
|
||
|
{
|
||
|
FAR int32_t *ret = (FAR int32_t *)arg[0];
|
||
|
FAR int32_t *errcode = (FAR int32_t *)arg[1];
|
||
|
FAR int32_t *id = (FAR int32_t *)arg[2];
|
||
|
FAR altcom_fd_set *readset = (FAR altcom_fd_set *)arg[3];
|
||
|
FAR altcom_fd_set *writeset = (FAR altcom_fd_set *)arg[4];
|
||
|
FAR altcom_fd_set *exceptset = (FAR altcom_fd_set *)arg[5];
|
||
|
|
||
|
FAR struct apicmd_selectres_s *in =
|
||
|
(FAR struct apicmd_selectres_s *)pktbuf;
|
||
|
uint16_t used_setbit;
|
||
|
|
||
|
*ret = ntohl(in->ret_code);
|
||
|
*errcode = altcom_errno2nuttx(ntohl(in->err_code));
|
||
|
|
||
|
if (*ret >= 0)
|
||
|
{
|
||
|
*id = ntohl(in->id);
|
||
|
used_setbit = ntohs(in->used_setbit);
|
||
|
memset(readset, 0, sizeof(altcom_fd_set));
|
||
|
memset(writeset, 0, sizeof(altcom_fd_set));
|
||
|
memset(exceptset, 0, sizeof(altcom_fd_set));
|
||
|
if (used_setbit & READSET_BIT)
|
||
|
{
|
||
|
memcpy(readset, &in->readset, sizeof(altcom_fd_set));
|
||
|
}
|
||
|
|
||
|
if (used_setbit & WRITESET_BIT)
|
||
|
{
|
||
|
memcpy(writeset, &in->writeset, sizeof(altcom_fd_set));
|
||
|
}
|
||
|
|
||
|
if (used_setbit & EXCEPTSET_BIT)
|
||
|
{
|
||
|
memcpy(exceptset, &in->exceptset, sizeof(altcom_fd_set));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|