From e260cc6448a8c4d8bb150b46364269d5b76798ec Mon Sep 17 00:00:00 2001 From: edolomb Date: Wed, 11 Apr 2018 16:31:47 +0000 Subject: HTTPS SEC and NSEC demos git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@11881 110e8d01-0319-4d1e-a829-52ad28d1bb01 --- .../proxies/tscommon.h | 91 ++++ .../proxies/tssockstub.c | 548 +++++++++++++++++++++ .../proxies/tssockstub.h | 409 +++++++++++++++ 3 files changed, 1048 insertions(+) create mode 100644 demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-HTTPS-SEC/proxies/tscommon.h create mode 100644 demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-HTTPS-SEC/proxies/tssockstub.c create mode 100644 demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-HTTPS-SEC/proxies/tssockstub.h (limited to 'demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-HTTPS-SEC/proxies') diff --git a/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-HTTPS-SEC/proxies/tscommon.h b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-HTTPS-SEC/proxies/tscommon.h new file mode 100644 index 000000000..f290791bb --- /dev/null +++ b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-HTTPS-SEC/proxies/tscommon.h @@ -0,0 +1,91 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file tscommon.h + * @brief Common, shared defines and macros between secure and non secure + * environment. + * + */ + +#ifndef TSCOMMON_H +#define TSCOMMON_H + +#include "ch.h" +#include "ccportab.h" + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ +#define SKEL_REQ_GETOP 1 +#define SKEL_REQ_CPYPRMS 2 +#define SKEL_REQ_PUTRES 3 +#define SKEL_REQ_READY 4 + +#define STUB_OP_SOCKET 0 +#define STUB_OP_CLOSE 1 +#define STUB_OP_CONNECT 2 +#define STUB_OP_RECV 3 +#define STUB_OP_SEND 4 +#define STUB_OP_SELECT 5 +#define STUB_OP_BIND 6 +#define STUB_OP_LISTEN 7 +#define STUB_OP_WRITE 8 +#define STUB_OP_READ 9 +#define STUB_OP_GETADDRINFO 10 +#define STUB_OP_FREEADDRINFO 11 + +#define EVT_F_SOCK_NEW_OP 1 + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ +#define METHOD_MAX_PARAMS 6 + +#define L_FD_SETSIZE 64 + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ +typedef struct skel_req { + uint32_t req; /* getop, cpyprms, putres */ + uint32_t stub_op; + uint32_t stub_op_code; + uint32_t stub_op_result; + uint32_t stub_op_p_sz[METHOD_MAX_PARAMS]; + uint32_t stub_op_p[METHOD_MAX_PARAMS]; +} skel_req_t; + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +#endif /* TSCOMMON_H */ diff --git a/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-HTTPS-SEC/proxies/tssockstub.c b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-HTTPS-SEC/proxies/tssockstub.c new file mode 100644 index 000000000..358acdf0f --- /dev/null +++ b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-HTTPS-SEC/proxies/tssockstub.c @@ -0,0 +1,548 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed 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. +*/ + +/** + * @file tssockstub.c + * @brief Sockets stub for trusted services. + * + */ + +#include "ch.h" +#include "chobjfifos.h" +#include "chtssi.h" +#include "tssockstub.h" +#include +#include + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +#define METHOD_MAX_PARAMS 6 +#define STUB_MAX_OPS 32 + +#define OP_PRMDIR_NONE 0 +#define OP_PRMDIR_IN 1 +#define OP_PRMDIR_OUT 2 + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ +typedef struct stub_op stub_op_t; +typedef enum {FREE=0, CALLING, PENDING} op_state_t; + +typedef struct stub_param { + uint32_t dir; + uint32_t val; + uint32_t size; +} stub_parm_t; + +typedef struct stub_op { + uint32_t op_code; /* e.g. connect, recv, sendv, close, etc.*/ + op_state_t op_state; /* calling, pending, free.*/ + stub_parm_t op_p[METHOD_MAX_PARAMS]; + thread_reference_t op_wthdp; /* TS internal client thread (the caller).*/ +} stub_op_t; + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +static objects_fifo_t ops_fifo; +static msg_t ops_msgs[STUB_MAX_OPS]; +static struct stub_op ops[STUB_MAX_OPS] = {0}; +static bool tsSkelIsReady = false; + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +static bool isOpValid(stub_op_t *op) +{ + if ((op < &ops[0]) || (op >= &ops[STUB_MAX_OPS])) + return FALSE; + if (((char *)op - (char *)&ops[0]) % sizeof ops[0]) + return FALSE; + return TRUE; +} + +/** + * @brief Implement an a call to a NSEC function. + * @details It activates the channel between the stubs service and + * the skels daemon running in the nsec world. + * To do it, it uses an event to signal the skels + * daemon that a new op request is ready to be executed. + * Behind the scenes, the skels daemon will then gets the op, calling + * the stubs service via smc. The daemon executes it and then calls + * the stubs service again to post the result and to wake up the + * calling thread of this function. + * + * @param[in] op the 'remote' method description. + * + * @return the return value of 'remote' method. + */ +static uint32_t callRemote(stub_op_t *op) { + uint32_t r; + + chSysLock(); + chFifoSendObjectI(&ops_fifo, op); + chEvtBroadcastFlagsI(&tsEventSource, EVT_F_SOCK_NEW_OP); + chThdSuspendS(&op->op_wthdp); + chSysUnlock(); + r = op->op_code; + chFifoReturnObject(&ops_fifo, op); + return r; +} + +static stub_op_t *getNewOp(void) { + stub_op_t *op = chFifoTakeObjectTimeout(&ops_fifo, TIME_INFINITE); + memset(op, 0, sizeof *op); + op->op_state = CALLING; + return op; +} + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * @brief The stubs service. + * @details And this is where the magic happens. + */ +THD_WORKING_AREA(waTsStubsService, 1024); +THD_FUNCTION(TsStubsService, tsstate) { + ts_state_t *svcp = tsstate; + skel_req_t *skrp; + stub_op_t *op; + msg_t r; + int i; + + chFifoObjectInit(&ops_fifo, sizeof (stub_op_t), STUB_MAX_OPS, + sizeof (uint8_t), ops, ops_msgs); + for (;/* ever */;) { + + /* Wait a service request.*/ + (void)tssiWaitRequest(svcp); + skrp = (skel_req_t *)TS_GET_DATA(svcp); + r = SMC_SVC_OK; + + /* Process the request.*/ + if (TS_GET_DATALEN(svcp) != sizeof (skel_req_t)) { + TS_SET_STATUS(svcp, SMC_SVC_INVALID); + continue; + } + + switch (skrp->req) { + case SKEL_REQ_READY: + tsSkelIsReady = true; + break; + + case SKEL_REQ_GETOP: + + /* The nsec skeleton calls us to get a new op ready to be executed.*/ + if (chFifoReceiveObjectTimeout(&ops_fifo, (void **)&op, TIME_IMMEDIATE) == + MSG_TIMEOUT) { + + /* no op ready to be executed.*/ + r = SMC_SVC_NHND; + break; + } + skrp->stub_op = (uint32_t)op; + skrp->stub_op_code = op->op_code; + + /* Pass all the 'by value' arguments from stub to skel.*/ + for (i = 0; i < METHOD_MAX_PARAMS; ++i) { + if (op->op_p[i].dir == OP_PRMDIR_NONE) + skrp->stub_op_p[i] = op->op_p[i].val; + } + op->op_state = PENDING; + break; + + case SKEL_REQ_CPYPRMS: + + /* The nsec skel calls us to get a copy of the 'in' parameters of + the specified op. + An 'in' parameter is an indirect argument, that is an argument + the value of which is a pointer to a memory buffer, that + must be copied in a non secure memory buffer. + It represents data to be consumed by the callee.*/ + op = (stub_op_t *)skrp->stub_op; + if (!isOpValid(op) || op->op_state != PENDING || + op->op_code != skrp->stub_op_code) { + r = SMC_SVC_INVALID; + break; + } + + /* Copy all 'in' parameters. + For each parameter check that the destination memory area + is in the non secure memory arena.*/ + for (i = 0; i < METHOD_MAX_PARAMS; ++i) { + if ((op->op_p[i].dir & OP_PRMDIR_IN) == 0) + continue; + if (!tsIsAddrSpaceValid((void *)skrp->stub_op_p[i], op->op_p[i].size)) { + r = SMC_SVC_INVALID; + break; + } + memcpy((void *)skrp->stub_op_p[i], (void *)op->op_p[i].val, + op->op_p[i].size); + } + break; + + case SKEL_REQ_PUTRES: + + /* The nsec skel calls us to put a copy of the 'out' parameters of + the specified op. + An 'out' parameter is an indirect argument, that is an argument + the value of which is a pointer to a memory buffer, that + must be copied in a secure memory buffer. + It represents data produced by the callee.*/ + op = (stub_op_t *)skrp->stub_op; + if (!isOpValid(op) || op->op_state != PENDING || + op->op_code != skrp->stub_op_code) { + r = SMC_SVC_INVALID; + break; + } + + /* Copy all 'out' parameters. + For each parameter check that the source memory area + is in the non secure memory arena, and that the size returned + fits in the caller buffer size.*/ + for (i = 0; i < METHOD_MAX_PARAMS; ++i) { + if ((op->op_p[i].dir & OP_PRMDIR_OUT) == 0) + continue; + if (!tsIsAddrSpaceValid((void *)skrp->stub_op_p[i], skrp->stub_op_p_sz[i]) + || (skrp->stub_op_p_sz[i] > op->op_p[i].size)) { + r = SMC_SVC_INVALID; + break; + } + memcpy((void *)op->op_p[i].val, (void *)skrp->stub_op_p[i], + skrp->stub_op_p_sz[i]); + } + if (r != SMC_SVC_OK) + break; + + /* Set the return value of the 'remote' callee method, + and wake up the caller.*/ + op->op_code = skrp->stub_op_result; + chThdResume(&op->op_wthdp, MSG_OK); + break; + + default: + r = SMC_SVC_INVALID; + break; + } + + /* Set the response.*/ + TS_SET_STATUS(svcp, r); + } +} +/** + * @brief Is the skeletons daemon ready to operate? + * @details It is used at the startup to synchronize the + * stub service with the skeleton daemon. + */ +void tsWaitStubSkelReady(void) { + while (!tsSkelIsReady) { + chThdSleepMilliseconds(100); + } +} + +/** + * @brief The sockets API. + */ +int socket(int domain, int type, int protocol) { + stub_op_t *op = getNewOp(); + op->op_code = STUB_OP_SOCKET; + op->op_p[0].dir = OP_PRMDIR_NONE; + op->op_p[0].val = (uint32_t)domain; + op->op_p[1].dir = OP_PRMDIR_NONE; + op->op_p[1].val = (uint32_t)type; + op->op_p[2].dir = OP_PRMDIR_NONE; + op->op_p[2].val = (uint32_t)protocol; + return (int)callRemote(op); +} + +int connect(int s, const struct sockaddr *name, socklen_t namelen) { + stub_op_t *op = getNewOp(); + op->op_code = STUB_OP_CONNECT; + op->op_p[0].dir = OP_PRMDIR_NONE; + op->op_p[0].val = (uint32_t)s; + op->op_p[1].dir = OP_PRMDIR_IN; + op->op_p[1].val = (uint32_t)name; + op->op_p[1].size = (uint32_t)namelen; + op->op_p[2].dir = OP_PRMDIR_NONE; + op->op_p[2].val = (uint32_t)namelen; + return (int)callRemote(op); +} + +int close(int s) { + stub_op_t *op = getNewOp(); + op->op_code = STUB_OP_CLOSE; + op->op_p[0].dir = OP_PRMDIR_NONE; + op->op_p[0].val = (uint32_t)s; + return (int)callRemote(op); +} + +int recv(int s, void *mem, size_t len, int flags) { + stub_op_t *op = getNewOp(); + op->op_code = STUB_OP_RECV; + op->op_p[0].dir = OP_PRMDIR_NONE; + op->op_p[0].val = (uint32_t)s; + op->op_p[1].dir = OP_PRMDIR_OUT; + op->op_p[1].val = (uint32_t)mem; + op->op_p[1].size = (uint32_t)len; + op->op_p[2].dir = OP_PRMDIR_NONE; + op->op_p[2].val = (uint32_t)len; + op->op_p[3].dir = OP_PRMDIR_NONE; + op->op_p[3].val = (uint32_t)flags; + return (int)callRemote(op); +} + +int send(int s, const void *dataptr, size_t size, int flags) { + stub_op_t *op = getNewOp(); + op->op_code = STUB_OP_SEND; + op->op_p[0].dir = OP_PRMDIR_NONE; + op->op_p[0].val = (uint32_t)s; + op->op_p[1].dir = OP_PRMDIR_IN; + op->op_p[1].val = (uint32_t)dataptr; + op->op_p[1].size = (uint32_t)size; + op->op_p[2].dir = OP_PRMDIR_NONE; + op->op_p[2].val = (uint32_t)size; + op->op_p[3].dir = OP_PRMDIR_NONE; + op->op_p[3].val = (uint32_t)flags; + return (int)callRemote(op); +} + +#if 0 +int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout) { + stub_op_t *op = getNewOp(); + op->op_code = STUB_OP_SELECT; + op->op_p[0].dir = OP_PRMDIR_NONE; + op->op_p[0].val = (uint32_t)maxfdp1; + op->op_p[1].dir = OP_PRMDIR_IN|OP_PRMDIR_OUT; + op->op_p[1].val = (uint32_t)readset; + op->op_p[1].size = sizeof (fd_set); + op->op_p[2].dir = OP_PRMDIR_IN|OP_PRMDIR_OUT; + op->op_p[2].val = (uint32_t)writeset; + op->op_p[2].size = sizeof (fd_set); + op->op_p[3].dir = OP_PRMDIR_IN|OP_PRMDIR_OUT; + op->op_p[3].val = (uint32_t)exceptset; + op->op_p[3].size = sizeof (fd_set); + op->op_p[4].dir = OP_PRMDIR_IN; + op->op_p[4].val = (uint32_t)timeout; + op->op_p[4].size = sizeof (struct timeval); + return (int)callRemote(op); +} +#endif + +int bind(int s, const struct sockaddr *name, socklen_t namelen) { + stub_op_t *op = getNewOp(); + op->op_code = STUB_OP_BIND; + op->op_p[0].dir = OP_PRMDIR_NONE; + op->op_p[0].val = (uint32_t)s; + op->op_p[1].dir = OP_PRMDIR_IN; + op->op_p[1].val = (uint32_t)name; + op->op_p[1].size = (uint32_t)namelen; + op->op_p[2].dir = OP_PRMDIR_NONE; + op->op_p[2].val = (uint32_t)namelen; + return (int)callRemote(op); +} + +int listen(int s, int backlog) { + stub_op_t *op = getNewOp(); + op->op_code = STUB_OP_LISTEN; + op->op_p[0].dir = OP_PRMDIR_NONE; + op->op_p[0].val = (uint32_t)s; + op->op_p[1].dir = OP_PRMDIR_NONE; + op->op_p[1].val = (uint32_t)backlog; + return (int)callRemote(op); +} + +int write(int s, const void *dataptr, size_t size) { + stub_op_t *op = getNewOp(); + op->op_code = STUB_OP_WRITE; + op->op_p[0].dir = OP_PRMDIR_NONE; + op->op_p[0].val = (uint32_t)s; + op->op_p[1].dir = OP_PRMDIR_IN; + op->op_p[1].val = (uint32_t)dataptr; + op->op_p[2].dir = OP_PRMDIR_NONE; + op->op_p[2].val = (uint32_t)size; + return (int)callRemote(op); +} + +int read(int s, void *mem, size_t len) { + stub_op_t *op = getNewOp(); + op->op_code = STUB_OP_READ; + op->op_p[0].dir = OP_PRMDIR_NONE; + op->op_p[0].val = (uint32_t)s; + op->op_p[1].dir = OP_PRMDIR_OUT; + op->op_p[1].val = (uint32_t)mem; + op->op_p[2].dir = OP_PRMDIR_NONE; + op->op_p[2].val = (uint32_t)len; + return (int)callRemote(op); +} + +/* + * TODO verify parameters + */ +int getaddrinfo(const char *nodename, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) { + stub_op_t *op = getNewOp(); + op->op_code = STUB_OP_GETADDRINFO; + op->op_p[0].dir = OP_PRMDIR_IN; + op->op_p[0].val = (uint32_t)nodename; + op->op_p[1].dir = OP_PRMDIR_IN; + op->op_p[1].val = (uint32_t)servname; + op->op_p[2].dir = OP_PRMDIR_IN; + op->op_p[2].val = (uint32_t)hints; + op->op_p[3].dir = OP_PRMDIR_OUT; + op->op_p[3].val = (uint32_t)res; + return (int)callRemote(op); +} + +int freeaddrinfo(struct addrinfo *ai) { + stub_op_t *op = getNewOp(); + op->op_code = STUB_OP_FREEADDRINFO; + op->op_p[0].dir = OP_PRMDIR_IN; + op->op_p[0].val = (uint32_t)ai; + return (int)callRemote(op); +} + + +#if 0 +int accept(int s, struct sockaddr *addr, socklen_t *addrlen); +int shutdown(int s, int how); +int getpeername (int s, struct sockaddr *name, socklen_t *namelen); +int getsockname (int s, struct sockaddr *name, socklen_t *namelen); +int getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen); +int setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen); +int recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen); +int sendmsg(int s, const struct msghdr *message, int flags); +int sendto(int s, const void *dataptr, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen); +int writev(int s, const struct iovec *iov, int iovcnt); +int ioctl(int s, long cmd, void *argp); +int fcntl(int s, int cmd, int val); +#endif + +/* + * Ascii internet address interpretation routine. + * The value returned is in network order. + */ +in_addr_t inet_addr(const char *cp) { + struct in_addr val; + + if (inet_aton(cp, &val)) + return val.s_addr; + return INADDR_NONE; +} + +/* + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + */ + +int inet_aton(const char *cp, struct in_addr *addr) { + uint32_t val, base, n; + char c; + uint32_t parts[4], *pp = parts; + + for (;;) { + /* + * Collect number up to '.'. + * Values are specified as for C: + * 0x=hex, 0=octal, other=decimal. + */ + val = 0; base = 10; + if (*cp == '0') { + if (*++cp == 'x' || *cp == 'X') + base = 16, cp++; + else + base = 8; + } + while ((c = *cp) != '\0') { + if (isascii(c) && isdigit(c)) { + val = (val * base) + (c - '0'); + cp++; + continue; + } + if (base == 16 && isascii(c) && isxdigit(c)) { + val = (val << 4) + + (c + 10 - (islower(c) ? 'a' : 'A')); + cp++; + continue; + } + break; + } + if (*cp == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16-bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3 || val > 0xff) + return 0; + *pp++ = val, cp++; + } else + break; + } + /* + * Check for trailing characters. + */ + if (*cp && (!isascii(*cp) || !isspace(*cp))) + return 0; + /* + * Make the address according to + * the number of parts specified. + */ + n = pp - parts + 1; + switch (n) { + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffff) + return 0; + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) + return 0; + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) + return 0; + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + if (addr) + addr->s_addr = htonl(val); + return 1; +} diff --git a/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-HTTPS-SEC/proxies/tssockstub.h b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-HTTPS-SEC/proxies/tssockstub.h new file mode 100644 index 000000000..58fbcac67 --- /dev/null +++ b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-HTTPS-SEC/proxies/tssockstub.h @@ -0,0 +1,409 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file tssockstub.h + * @brief Sockets stub module macros and structures. + * + */ + +#ifndef TSSOCKSTUB_H +#define TSSOCKSTUB_H + +#include "ch.h" +#include "ccportab.h" +#include "tscommon.h" +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +typedef uint32_t socklen_t; +typedef uint8_t sa_family_t; +typedef uint16_t in_port_t; +typedef uint32_t in_addr_t; + +struct in_addr { + in_addr_t s_addr; +}; + +#if 0 +typedef struct fd_set +{ + unsigned char fd_bits [(L_FD_SETSIZE+7)/8]; +} fd_set; + +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; +#endif + +struct sockaddr { + uint8_t sa_len; + sa_family_t sa_family; + char sa_data[14]; +}; + +struct addrinfo { + int ai_flags; /* Input flags. */ + int ai_family; /* Address family of socket. */ + int ai_socktype; /* Socket type. */ + int ai_protocol; /* Protocol of socket. */ + socklen_t ai_addrlen; /* Length of socket address. */ + struct sockaddr *ai_addr; /* Socket address of socket. */ + char *ai_canonname; /* Canonical name of service location. */ + struct addrinfo *ai_next; /* Pointer to next in list. */ +}; + +struct sockaddr_in { + uint8_t sin_len; + sa_family_t sin_family; + in_port_t sin_port; + struct in_addr sin_addr; +#define SIN_ZERO_LEN 8 + char sin_zero[SIN_ZERO_LEN]; +}; + +struct sockaddr_storage { + uint8_t s2_len; + sa_family_t ss_family; + char s2_data1[2]; + uint32_t s2_data2[3]; +}; + +struct iovec { + void *iov_base; + size_t iov_len; +}; + +struct msghdr { + void *msg_name; + socklen_t msg_namelen; + struct iovec *msg_iov; + int msg_iovlen; + void *msg_control; + socklen_t msg_controllen; + int msg_flags; +}; + +#define htons(s) ((uint16_t)(((uint16_t)(s) >> 8) | ((uint16_t)(s) << 8))) +#define ntohs(s) htons(s) +#define htonl(l) ((((l) & 0x000000ffUL) << 24) | \ + (((l) & 0x0000ff00UL) << 8) | \ + (((l) & 0x00ff0000UL) >> 8) | \ + (((l) & 0xff000000UL) >> 24)) +#define ntohl(l) htonl(l) + +/** 255.255.255.255 */ +#define IPADDR_NONE ((uint32_t)0xffffffffUL) +/** 127.0.0.1 */ +#define IPADDR_LOOPBACK ((uint32_t)0x7f000001UL) +/** 0.0.0.0 */ +#define IPADDR_ANY ((uint32_t)0x00000000UL) +/** 255.255.255.255 */ +#define IPADDR_BROADCAST ((uint32_t)0xffffffffUL) + +/** 255.255.255.255 */ +#define INADDR_NONE IPADDR_NONE +/** 127.0.0.1 */ +#define INADDR_LOOPBACK IPADDR_LOOPBACK +/** 0.0.0.0 */ +#define INADDR_ANY IPADDR_ANY +/** 255.255.255.255 */ +#define INADDR_BROADCAST IPADDR_BROADCAST + +/* Socket protocol types (TCP/UDP/RAW) */ +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define SOCK_RAW 3 + +/* + * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c) + */ +#define SO_REUSEADDR 0x0004 /* Allow local address reuse */ +#define SO_KEEPALIVE 0x0008 /* keep connections alive */ +#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ + +/* + * Additional options, not kept in so_options. + */ +#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */ +#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ +#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */ +#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ +#define SO_LINGER 0x0080 /* linger on close if data present */ +#define SO_DONTLINGER ((int)(~SO_LINGER)) +#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */ +#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */ +#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */ +#define SO_RCVBUF 0x1002 /* receive buffer size */ +#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */ +#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */ +#define SO_SNDTIMEO 0x1005 /* send timeout */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ +#define SO_ERROR 0x1007 /* get error status and clear */ +#define SO_TYPE 0x1008 /* get socket type */ +#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ +#define SO_NO_CHECK 0x100a /* don't create UDP checksum */ + +/* + * Structure used for manipulating linger option. + */ +struct linger { + int l_onoff; /* option on/off */ + int l_linger; /* linger time in seconds */ +}; + +/* + * Level number for (get/set)sockopt() to apply to socket itself. + */ +#define SOL_SOCKET 0xfff /* options for socket level */ + +#define AF_UNSPEC 0 +#define AF_INET 2 +#define AF_INET6 AF_UNSPEC +#define PF_INET AF_INET +#define PF_INET6 AF_INET6 +#define PF_UNSPEC AF_UNSPEC + +#define IPPROTO_IP 0 +#define IPPROTO_ICMP 1 +#define IPPROTO_TCP 6 +#define IPPROTO_UDP 17 +#define IPPROTO_UDPLITE 136 +#define IPPROTO_RAW 255 + +/* Flags we can use with send and recv. */ +#define MSG_PEEK 0x01 /* Peeks at an incoming message */ +#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */ +#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ +#define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */ +#define MSG_MORE 0x10 /* Sender will send more */ + +/* + * Options for level IPPROTO_IP + */ +#define IP_TOS 1 +#define IP_TTL 2 + +/* + * Options for level IPPROTO_TCP + */ +#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ +#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */ +#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */ +#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */ +#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */ + + +/* + * Options for level IPPROTO_UDPLITE + */ +#define UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */ +#define UDPLITE_RECV_CSCOV 0x02 /* minimal receiver checksum coverage */ + + +/* + * Options and types for UDP multicast traffic handling + */ +#define IP_MULTICAST_TTL 5 +#define IP_MULTICAST_IF 6 +#define IP_MULTICAST_LOOP 7 + +/* + * Options and types related to multicast membership + */ +#define IP_ADD_MEMBERSHIP 3 +#define IP_DROP_MEMBERSHIP 4 + +typedef struct ip_mreq { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_interface; /* local IP address of interface */ +} ip_mreq; + +/* + * The Type of Service provides an indication of the abstract + * parameters of the quality of service desired. These parameters are + * to be used to guide the selection of the actual service parameters + * when transmitting a datagram through a particular network. Several + * networks offer service precedence, which somehow treats high + * precedence traffic as more important than other traffic (generally + * by accepting only traffic above a certain precedence at time of high + * load). The major choice is a three way tradeoff between low-delay, + * high-reliability, and high-throughput. + * The use of the Delay, Throughput, and Reliability indications may + * increase the cost (in some sense) of the service. In many networks + * better performance for one of these parameters is coupled with worse + * performance on another. Except for very unusual cases at most two + * of these three indications should be set. + */ +#define IPTOS_TOS_MASK 0x1E +#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +#define IPTOS_LOWCOST 0x02 +#define IPTOS_MINCOST IPTOS_LOWCOST + +/* + * The Network Control precedence designation is intended to be used + * within a network only. The actual use and control of that + * designation is up to each network. The Internetwork Control + * designation is intended for use by gateway control originators only. + * If the actual use of these precedence designations is of concern to + * a particular network, it is the responsibility of that network to + * control the access to, and use of, those precedence designations. + */ +#define IPTOS_PREC_MASK 0xe0 +#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) +#define IPTOS_PREC_NETCONTROL 0xe0 +#define IPTOS_PREC_INTERNETCONTROL 0xc0 +#define IPTOS_PREC_CRITIC_ECP 0xa0 +#define IPTOS_PREC_FLASHOVERRIDE 0x80 +#define IPTOS_PREC_FLASH 0x60 +#define IPTOS_PREC_IMMEDIATE 0x40 +#define IPTOS_PREC_PRIORITY 0x20 +#define IPTOS_PREC_ROUTINE 0x00 + + +/* + * Commands for ioctlsocket(), taken from the BSD file fcntl.h. + * + * Ioctl's have the command encoded in the lower word, + * and the size of any in or out parameters in the upper + * word. The high 2 bits of the upper word are used + * to encode the in/out status of the parameter; for now + * we restrict parameters to at most 128 bytes. + */ +#if !defined(FIONREAD) || !defined(FIONBIO) +#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ +#define IOC_VOID 0x20000000UL /* no parameters */ +#define IOC_OUT 0x40000000UL /* copy out parameters */ +#define IOC_IN 0x80000000UL /* copy in parameters */ +#define IOC_INOUT (IOC_IN|IOC_OUT) + /* 0x20000000 distinguishes new & + old ioctl's */ +#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) + +#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) + +#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) +#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ + +#ifndef FIONREAD +#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */ +#endif +#ifndef FIONBIO +#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ +#endif + +/* Socket I/O Controls: unimplemented */ +#ifndef SIOCSHIWAT +#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */ +#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */ +#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */ +#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */ +#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */ +#endif + +/* commands for fnctl */ +#ifndef F_GETFL +#define F_GETFL 3 +#endif +#ifndef F_SETFL +#define F_SETFL 4 +#endif + +/* File status flags and file access modes for fnctl, + these are bits in an int. */ +#ifndef O_NONBLOCK +#define O_NONBLOCK 1 /* nonblocking I/O */ +#endif +#ifndef O_NDELAY +#define O_NDELAY 1 /* same as O_NONBLOCK, for compatibility */ +#endif + +#ifndef SHUT_RD + #define SHUT_RD 0 + #define SHUT_WR 1 + #define SHUT_RDWR 2 +#endif + +#define FDSETSAFESET(n, code) do { \ + if (((n) < L_FD_SETSIZE) && (((int)(n)) >= 0)) { \ + code; }} while(0) +#define FDSETSAFEGET(n, code) (((n) < L_FD_SETSIZE) && (((int)(n)) >= 0) ?\ + (code) : 0) +#if 0 +#define FD_SET(n, p) FDSETSAFESET(n, (p)->fd_bits[((n))/8] |= (1 << (((n)) & 7))) +#define FD_CLR(n, p) FDSETSAFESET(n, (p)->fd_bits[((n))/8] &= ~(1 << (((n)) & 7))) +#define FD_ISSET(n,p) FDSETSAFEGET(n, (p)->fd_bits[((n))/8] & (1 << (((n)) & 7))) +#define FD_ZERO(p) memset((void*)(p), 0, sizeof(*(p))) +#endif +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + int socket(int domain, int type, int protocol); + int close(int s); + int connect(int s, const struct sockaddr *name, socklen_t namelen); + int recv(int s, void *mem, size_t len, int flags); + int send(int s, const void *dataptr, size_t size, int flags); + //int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + // struct timeval *timeout); + int bind(int s, const struct sockaddr *name, socklen_t namelen); + int listen(int s, int backlog); + int write(int s, const void *dataptr, size_t size); + int read(int s, void *mem, size_t len); + int getaddrinfo(const char *nodename, const char *servname, + const struct addrinfo *hints, struct addrinfo **res); + int freeaddrinfo(struct addrinfo *ai); + in_addr_t inet_addr(const char *cp); + int inet_aton(const char *cp, struct in_addr *addr); + void tsWaitStubSkelReady(void); + THD_FUNCTION(TsStubsService, tsstate); + extern THD_WORKING_AREA(waTsStubsService, 1024); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +#endif /* TSSOCKSTUB_H */ -- cgit v1.2.3