Free (GPLv2) TCP/IP stack developed by TASS Belgium

Dependents:   lpc1768-picotcp-demo ZeroMQ_PicoTCP_Publisher_demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test ... more

PicoTCP. Copyright (c) 2013 TASS Belgium NV.

Released under the GNU General Public License, version 2.

Different licensing models may exist, at the sole discretion of the Copyright holders.

Official homepage: http://www.picotcp.com

Bug tracker: https://github.com/tass-belgium/picotcp/issues

Development steps:

  • initial integration with mbed RTOS
  • generic mbed Ethernet driver
  • high performance NXP LPC1768 specific Ethernet driver
  • Multi-threading support for mbed RTOS
  • Berkeley sockets and integration with the New Socket API
  • Fork of the apps running on top of the New Socket API
  • Scheduling optimizations
  • Debugging/benchmarking/testing

Demo application (measuring TCP sender performance):

Import programlpc1768-picotcp-demo

A PicoTCP demo app testing the ethernet throughput on the lpc1768 mbed board.

Committer:
tass picotcp@tass.be
Date:
Thu Jan 16 10:13:37 2014 +0100
Revision:
133:5b075f5e141a
Parent:
131:4758606c9316
Child:
134:cc4e6d2654d9
Update from master branch

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tass 68:0847e35d08a6 1 /*********************************************************************
TASS Belgium NV 131:4758606c9316 2 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
TASS Belgium NV 131:4758606c9316 3 See LICENSE and COPYING for usage.
tass 68:0847e35d08a6 4
tass 68:0847e35d08a6 5
TASS Belgium NV 131:4758606c9316 6 Authors: Daniele Lacamera
TASS Belgium NV 131:4758606c9316 7 *********************************************************************/
tass 68:0847e35d08a6 8
tass 68:0847e35d08a6 9
tass 68:0847e35d08a6 10 #include "pico_config.h"
tass 68:0847e35d08a6 11 #include "pico_queue.h"
tass 68:0847e35d08a6 12 #include "pico_socket.h"
tass 68:0847e35d08a6 13 #include "pico_ipv4.h"
tass 68:0847e35d08a6 14 #include "pico_ipv6.h"
tass 68:0847e35d08a6 15 #include "pico_udp.h"
tass 68:0847e35d08a6 16 #include "pico_tcp.h"
tass 68:0847e35d08a6 17 #include "pico_stack.h"
tass 68:0847e35d08a6 18 #include "pico_icmp4.h"
tass 68:0847e35d08a6 19 #include "pico_nat.h"
tass 68:0847e35d08a6 20 #include "pico_tree.h"
tass 68:0847e35d08a6 21 #include "pico_device.h"
tass 68:0847e35d08a6 22
tass 68:0847e35d08a6 23 #if defined (PICO_SUPPORT_IPV4) || defined (PICO_SUPPORT_IPV6)
tass 68:0847e35d08a6 24 #if defined (PICO_SUPPORT_TCP) || defined (PICO_SUPPORT_UDP)
tass 68:0847e35d08a6 25
tass 110:0ece1bbbd36e 26 #define UDP_FRAME_OVERHEAD (sizeof(struct pico_frame))
tass 68:0847e35d08a6 27
tass 68:0847e35d08a6 28 #define PROTO(s) ((s)->proto->proto_number)
tass 68:0847e35d08a6 29 #define PICO_SOCKET4_MTU 1480 /* Ethernet MTU(1500) - IP header size(20) */
tass 68:0847e35d08a6 30 #define PICO_SOCKET6_MTU 1460 /* Ethernet MTU(1500) - IP header size(40) */
tass 68:0847e35d08a6 31 #define TCP_STATE(s) (s->state & PICO_SOCKET_STATE_TCP)
tass 68:0847e35d08a6 32
tass 68:0847e35d08a6 33 #ifdef PICO_SUPPORT_MUTEX
TASS Belgium NV 131:4758606c9316 34 static void *Mutex = NULL;
TASS Belgium NV 131:4758606c9316 35 #define LOCK(x) { \
TASS Belgium NV 131:4758606c9316 36 if (x == NULL) \
TASS Belgium NV 131:4758606c9316 37 x = pico_mutex_init(); \
TASS Belgium NV 131:4758606c9316 38 pico_mutex_lock(x); \
tass 68:0847e35d08a6 39 }
TASS Belgium NV 131:4758606c9316 40 #define UNLOCK(x) pico_mutex_unlock(x)
tass 68:0847e35d08a6 41
tass 68:0847e35d08a6 42 #else
TASS Belgium NV 131:4758606c9316 43 #define LOCK(x) do {} while(0)
TASS Belgium NV 131:4758606c9316 44 #define UNLOCK(x) do {} while(0)
tass 68:0847e35d08a6 45 #endif
tass 68:0847e35d08a6 46
tass 68:0847e35d08a6 47
tass 68:0847e35d08a6 48 #define PROTO(s) ((s)->proto->proto_number)
tass 68:0847e35d08a6 49
tass 68:0847e35d08a6 50 #ifdef PICO_SUPPORT_TCP
tass 68:0847e35d08a6 51 # define IS_NAGLE_ENABLED(s) (!(!(!(s->opt_flags & (1 << PICO_SOCKET_OPT_TCPNODELAY)))))
tass 68:0847e35d08a6 52 #endif
tass 68:0847e35d08a6 53
tass 68:0847e35d08a6 54 #define PICO_SOCKET_MTU 1480 /* Ethernet MTU(1500) - IP header size(20) */
tass 68:0847e35d08a6 55
tass 68:0847e35d08a6 56 #ifdef PICO_SUPPORT_IPV4
tass 68:0847e35d08a6 57 # define IS_SOCK_IPV4(s) ((s->net == &pico_proto_ipv4))
tass 68:0847e35d08a6 58 #else
tass 68:0847e35d08a6 59 # define IS_SOCK_IPV4(s) (0)
tass 68:0847e35d08a6 60 #endif
tass 68:0847e35d08a6 61
tass 68:0847e35d08a6 62 #ifdef PICO_SUPPORT_IPV6
tass 68:0847e35d08a6 63 # define IS_SOCK_IPV6(s) ((s->net == &pico_proto_ipv6))
tass 68:0847e35d08a6 64 #else
tass 68:0847e35d08a6 65 # define IS_SOCK_IPV6(s) (0)
tass 68:0847e35d08a6 66 #endif
tass 68:0847e35d08a6 67
tass 68:0847e35d08a6 68 #ifdef PICO_SUPPORT_IPFRAG
TASS Belgium NV 131:4758606c9316 69 # define frag_dbg(...) do {} while(0)
tass 68:0847e35d08a6 70 #endif
tass 68:0847e35d08a6 71
TASS Belgium NV 131:4758606c9316 72 #ifdef PICO_SUPPORT_MCAST
TASS Belgium NV 131:4758606c9316 73 # define so_mcast_dbg(...) do {} while(0) /* ip_mcast_dbg in pico_ipv4.c */
tass 68:0847e35d08a6 74 #endif
tass 68:0847e35d08a6 75
TASS Belgium NV 131:4758606c9316 76 static struct pico_sockport *sp_udp = NULL, *sp_tcp = NULL;
tass 68:0847e35d08a6 77
tass 70:cd218dd180e5 78 struct pico_frame *pico_socket_frame_alloc(struct pico_socket *s, uint16_t len);
tass 68:0847e35d08a6 79
TASS Belgium NV 131:4758606c9316 80 static int32_t socket_cmp(void *ka, void *kb)
tass 68:0847e35d08a6 81 {
TASS Belgium NV 131:4758606c9316 82 struct pico_socket *a = ka, *b = kb;
TASS Belgium NV 131:4758606c9316 83 uint32_t a_is_ip6 = is_sock_ipv6(a);
TASS Belgium NV 131:4758606c9316 84 uint32_t b_is_ip6 = is_sock_ipv6(b);
tass 68:0847e35d08a6 85
TASS Belgium NV 131:4758606c9316 86 int32_t diff;
tass 68:0847e35d08a6 87
TASS Belgium NV 131:4758606c9316 88 /* First, order by network ver */
TASS Belgium NV 131:4758606c9316 89 if (a_is_ip6 < b_is_ip6)
TASS Belgium NV 131:4758606c9316 90 return -1;
tass 68:0847e35d08a6 91
TASS Belgium NV 131:4758606c9316 92 if (a_is_ip6 > b_is_ip6)
TASS Belgium NV 131:4758606c9316 93 return 1;
tass 68:0847e35d08a6 94
TASS Belgium NV 131:4758606c9316 95 /* If either socket is PICO_IPV4_INADDR_ANY mode, skip local address comparison */
TASS Belgium NV 131:4758606c9316 96
TASS Belgium NV 131:4758606c9316 97 /* At this point, sort by local host */
tass 68:0847e35d08a6 98
TASS Belgium NV 131:4758606c9316 99 if (0) {
tass 68:0847e35d08a6 100 #ifdef PICO_SUPPORT_IPV6
TASS Belgium NV 131:4758606c9316 101 } else if (a_is_ip6) {
TASS Belgium NV 131:4758606c9316 102 if ((memcmp(a->local_addr.ip6.addr, PICO_IP6_ANY, PICO_SIZE_IP6) == 0) || memcmp((b->local_addr.ip6.addr, PICO_IP6_ANY, PICO_SIZE_IP6) == 0))
TASS Belgium NV 131:4758606c9316 103 diff = 0;
TASS Belgium NV 131:4758606c9316 104 else
TASS Belgium NV 131:4758606c9316 105 diff = memcmp(a->local_addr.ip6.addr, b->local_addr.ip6.addr, PICO_SIZE_IP6);
TASS Belgium NV 131:4758606c9316 106
tass 68:0847e35d08a6 107 #endif
TASS Belgium NV 131:4758606c9316 108 } else {
TASS Belgium NV 131:4758606c9316 109 if ((a->local_addr.ip4.addr == PICO_IP4_ANY) || (b->local_addr.ip4.addr == PICO_IP4_ANY))
TASS Belgium NV 131:4758606c9316 110 diff = 0;
TASS Belgium NV 131:4758606c9316 111 else
TASS Belgium NV 131:4758606c9316 112 diff = (int32_t)(a->local_addr.ip4.addr - b->local_addr.ip4.addr);
TASS Belgium NV 131:4758606c9316 113 }
tass 68:0847e35d08a6 114
TASS Belgium NV 131:4758606c9316 115 if (diff)
TASS Belgium NV 131:4758606c9316 116 return diff;
tass 68:0847e35d08a6 117
tass 68:0847e35d08a6 118
TASS Belgium NV 131:4758606c9316 119 /* Sort by remote host */
TASS Belgium NV 131:4758606c9316 120 if (a_is_ip6)
TASS Belgium NV 131:4758606c9316 121 diff = memcmp(a->remote_addr.ip6.addr, b->remote_addr.ip6.addr, PICO_SIZE_IP6);
TASS Belgium NV 131:4758606c9316 122 else
TASS Belgium NV 131:4758606c9316 123 diff = (int32_t)(a->remote_addr.ip4.addr - b->remote_addr.ip4.addr);
tass 68:0847e35d08a6 124
TASS Belgium NV 131:4758606c9316 125 if (diff)
TASS Belgium NV 131:4758606c9316 126 return diff;
tass 68:0847e35d08a6 127
TASS Belgium NV 131:4758606c9316 128 /* And finally by remote port. The two sockets are coincident if the quad is the same. */
TASS Belgium NV 131:4758606c9316 129 return b->remote_port - a->remote_port;
tass 68:0847e35d08a6 130 }
tass 68:0847e35d08a6 131
tass 68:0847e35d08a6 132 struct pico_sockport
tass 68:0847e35d08a6 133 {
TASS Belgium NV 131:4758606c9316 134 struct pico_tree socks; /* how you make the connection ? */
TASS Belgium NV 131:4758606c9316 135 uint16_t number;
TASS Belgium NV 131:4758606c9316 136 uint16_t proto;
tass 68:0847e35d08a6 137 };
tass 68:0847e35d08a6 138
TASS Belgium NV 131:4758606c9316 139 #define INIT_SOCKPORT { {&LEAF, socket_cmp}, 0, 0 }
tass 68:0847e35d08a6 140
TASS Belgium NV 131:4758606c9316 141 int sockport_cmp(void *ka, void *kb)
tass 68:0847e35d08a6 142 {
TASS Belgium NV 131:4758606c9316 143 struct pico_sockport *a = ka, *b = kb;
TASS Belgium NV 131:4758606c9316 144 if (a->number < b->number)
TASS Belgium NV 131:4758606c9316 145 return -1;
TASS Belgium NV 131:4758606c9316 146
TASS Belgium NV 131:4758606c9316 147 if (a->number > b->number)
TASS Belgium NV 131:4758606c9316 148 return 1;
TASS Belgium NV 131:4758606c9316 149
TASS Belgium NV 131:4758606c9316 150 return 0;
tass 68:0847e35d08a6 151 }
tass 68:0847e35d08a6 152
TASS Belgium NV 131:4758606c9316 153 PICO_TREE_DECLARE(UDPTable, sockport_cmp);
TASS Belgium NV 131:4758606c9316 154 PICO_TREE_DECLARE(TCPTable, sockport_cmp);
tass 68:0847e35d08a6 155
tass 68:0847e35d08a6 156 #ifdef PICO_SUPPORT_MCAST
tass 68:0847e35d08a6 157 /* socket
TASS Belgium NV 131:4758606c9316 158 * |
tass 68:0847e35d08a6 159 * MCASTListen
tass 68:0847e35d08a6 160 * | | |
tass 68:0847e35d08a6 161 * ------------ | ------------
tass 68:0847e35d08a6 162 * | | |
TASS Belgium NV 131:4758606c9316 163 * MCASTSources MCASTSources MCASTSources
tass 68:0847e35d08a6 164 * | | | | | | | | | | | |
tass 68:0847e35d08a6 165 * S S S S S S S S S S S S
tass 68:0847e35d08a6 166 *
tass 68:0847e35d08a6 167 * MCASTListen: RBTree(mcast_link, mcast_group)
tass 68:0847e35d08a6 168 * MCASTSources: RBTree(source)
tass 68:0847e35d08a6 169 */
tass 68:0847e35d08a6 170 struct pico_mcast_listen
tass 68:0847e35d08a6 171 {
TASS Belgium NV 131:4758606c9316 172 uint8_t filter_mode;
TASS Belgium NV 131:4758606c9316 173 struct pico_ip4 mcast_link;
TASS Belgium NV 131:4758606c9316 174 struct pico_ip4 mcast_group;
TASS Belgium NV 131:4758606c9316 175 struct pico_tree MCASTSources;
tass 68:0847e35d08a6 176 };
tass 68:0847e35d08a6 177
tass 68:0847e35d08a6 178 static int mcast_listen_cmp(void *ka, void *kb)
tass 68:0847e35d08a6 179 {
TASS Belgium NV 131:4758606c9316 180 struct pico_mcast_listen *a = ka, *b = kb;
TASS Belgium NV 131:4758606c9316 181 if (a->mcast_group.addr < b->mcast_group.addr)
TASS Belgium NV 131:4758606c9316 182 return -1;
TASS Belgium NV 131:4758606c9316 183
TASS Belgium NV 131:4758606c9316 184 if (a->mcast_group.addr > b->mcast_group.addr)
TASS Belgium NV 131:4758606c9316 185 return 1;
tass 68:0847e35d08a6 186
TASS Belgium NV 131:4758606c9316 187 if (a->mcast_link.addr < b->mcast_link.addr)
TASS Belgium NV 131:4758606c9316 188 return -1;
tass 68:0847e35d08a6 189
TASS Belgium NV 131:4758606c9316 190 if (a->mcast_link.addr > b->mcast_link.addr)
TASS Belgium NV 131:4758606c9316 191 return 1;
TASS Belgium NV 131:4758606c9316 192
TASS Belgium NV 131:4758606c9316 193 return 0;
tass 68:0847e35d08a6 194 }
tass 68:0847e35d08a6 195
tass 68:0847e35d08a6 196 static int mcast_sources_cmp(void *ka, void *kb)
tass 68:0847e35d08a6 197 {
TASS Belgium NV 131:4758606c9316 198 struct pico_ip4 *a = ka, *b = kb;
TASS Belgium NV 131:4758606c9316 199 if (a->addr < b->addr)
TASS Belgium NV 131:4758606c9316 200 return -1;
TASS Belgium NV 131:4758606c9316 201
TASS Belgium NV 131:4758606c9316 202 if (a->addr > b->addr)
TASS Belgium NV 131:4758606c9316 203 return 1;
TASS Belgium NV 131:4758606c9316 204
TASS Belgium NV 131:4758606c9316 205 return 0;
tass 68:0847e35d08a6 206 }
tass 68:0847e35d08a6 207
tass 68:0847e35d08a6 208 static int mcast_socket_cmp(void *ka, void *kb)
tass 68:0847e35d08a6 209 {
TASS Belgium NV 131:4758606c9316 210 struct pico_socket *a = ka, *b = kb;
TASS Belgium NV 131:4758606c9316 211 if (a < b)
TASS Belgium NV 131:4758606c9316 212 return -1;
TASS Belgium NV 131:4758606c9316 213
TASS Belgium NV 131:4758606c9316 214 if (a > b)
TASS Belgium NV 131:4758606c9316 215 return 1;
TASS Belgium NV 131:4758606c9316 216
TASS Belgium NV 131:4758606c9316 217 return 0;
tass 68:0847e35d08a6 218 }
tass 68:0847e35d08a6 219 /* gather all multicast sockets to hasten filter aggregation */
tass 68:0847e35d08a6 220 PICO_TREE_DECLARE(MCASTSockets, mcast_socket_cmp);
tass 68:0847e35d08a6 221
tass 68:0847e35d08a6 222 static int mcast_filter_cmp(void *ka, void *kb)
tass 68:0847e35d08a6 223 {
TASS Belgium NV 131:4758606c9316 224 struct pico_ip4 *a = ka, *b = kb;
TASS Belgium NV 131:4758606c9316 225 if (a->addr < b->addr)
TASS Belgium NV 131:4758606c9316 226 return -1;
TASS Belgium NV 131:4758606c9316 227
TASS Belgium NV 131:4758606c9316 228 if (a->addr > b->addr)
TASS Belgium NV 131:4758606c9316 229 return 1;
TASS Belgium NV 131:4758606c9316 230
TASS Belgium NV 131:4758606c9316 231 return 0;
tass 68:0847e35d08a6 232 }
tass 68:0847e35d08a6 233 /* gather sources to be filtered */
tass 68:0847e35d08a6 234 PICO_TREE_DECLARE(MCASTFilter, mcast_filter_cmp);
tass 68:0847e35d08a6 235
tass 74:c146c4e346c4 236 static struct pico_mcast_listen *listen_find(struct pico_socket *s, struct pico_ip4 *lnk, struct pico_ip4 *grp)
tass 74:c146c4e346c4 237 {
TASS Belgium NV 131:4758606c9316 238 struct pico_mcast_listen ltest = {
TASS Belgium NV 131:4758606c9316 239 0
TASS Belgium NV 131:4758606c9316 240 };
TASS Belgium NV 131:4758606c9316 241 ltest.mcast_link.addr = lnk->addr;
TASS Belgium NV 131:4758606c9316 242 ltest.mcast_group.addr = grp->addr;
TASS Belgium NV 131:4758606c9316 243 return pico_tree_findKey(s->MCASTListen, &ltest);
tass 74:c146c4e346c4 244 }
tass 74:c146c4e346c4 245
tass 68:0847e35d08a6 246 /* MCASTFilter will be empty if no socket is listening on mcast_group on mcast_link anymore */
tass 68:0847e35d08a6 247 static int pico_socket_aggregate_mcastfilters(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_group)
tass 68:0847e35d08a6 248 {
TASS Belgium NV 131:4758606c9316 249 uint8_t filter_mode = PICO_IP_MULTICAST_INCLUDE;
TASS Belgium NV 131:4758606c9316 250 struct pico_mcast_listen *listen = NULL;
TASS Belgium NV 131:4758606c9316 251 struct pico_ip4 *source = NULL;
TASS Belgium NV 131:4758606c9316 252 struct pico_socket *mcast_sock = NULL;
TASS Belgium NV 131:4758606c9316 253 struct pico_tree_node *index = NULL, *_tmp = NULL, *index2 = NULL, *_tmp2 = NULL;
tass 68:0847e35d08a6 254
tass 68:0847e35d08a6 255
TASS Belgium NV 131:4758606c9316 256 /* cleanup old filter */
TASS Belgium NV 131:4758606c9316 257 pico_tree_foreach_safe(index, &MCASTFilter, _tmp)
TASS Belgium NV 131:4758606c9316 258 {
TASS Belgium NV 131:4758606c9316 259 pico_tree_delete(&MCASTFilter, index->keyValue);
TASS Belgium NV 131:4758606c9316 260 }
tass 68:0847e35d08a6 261
TASS Belgium NV 131:4758606c9316 262 /* construct new filter */
TASS Belgium NV 131:4758606c9316 263 pico_tree_foreach(index, &MCASTSockets)
TASS Belgium NV 131:4758606c9316 264 {
TASS Belgium NV 131:4758606c9316 265 mcast_sock = index->keyValue;
TASS Belgium NV 131:4758606c9316 266 listen = listen_find(mcast_sock, mcast_link, mcast_group);
TASS Belgium NV 131:4758606c9316 267 if (listen) {
TASS Belgium NV 131:4758606c9316 268 /* aggregate filter */
TASS Belgium NV 131:4758606c9316 269 switch(filter_mode)
TASS Belgium NV 131:4758606c9316 270 {
tass 68:0847e35d08a6 271 case PICO_IP_MULTICAST_INCLUDE:
TASS Belgium NV 131:4758606c9316 272 switch (listen->filter_mode)
TASS Belgium NV 131:4758606c9316 273 {
TASS Belgium NV 131:4758606c9316 274 case PICO_IP_MULTICAST_INCLUDE:
TASS Belgium NV 131:4758606c9316 275 /* filter = summation of INCLUDEs */
TASS Belgium NV 131:4758606c9316 276 /* mode stays INCLUDE, add all sources to filter */
TASS Belgium NV 131:4758606c9316 277 pico_tree_foreach(index2, &listen->MCASTSources)
TASS Belgium NV 131:4758606c9316 278 {
TASS Belgium NV 131:4758606c9316 279 source = index2->keyValue;
TASS Belgium NV 131:4758606c9316 280 pico_tree_insert(&MCASTFilter, source);
TASS Belgium NV 131:4758606c9316 281 }
TASS Belgium NV 131:4758606c9316 282 break;
TASS Belgium NV 131:4758606c9316 283
TASS Belgium NV 131:4758606c9316 284 case PICO_IP_MULTICAST_EXCLUDE:
TASS Belgium NV 131:4758606c9316 285 /* filter = EXCLUDE - INCLUDE */
TASS Belgium NV 131:4758606c9316 286 /* delete from the interface INCLUDE filter any source NOT in the socket EXCLUDE filter */
TASS Belgium NV 131:4758606c9316 287 pico_tree_foreach_safe(index2, &MCASTFilter, _tmp2)
TASS Belgium NV 131:4758606c9316 288 {
TASS Belgium NV 131:4758606c9316 289 source = pico_tree_findKey(&listen->MCASTSources, index2->keyValue);
TASS Belgium NV 131:4758606c9316 290 if (!source)
TASS Belgium NV 131:4758606c9316 291 pico_tree_delete(&MCASTFilter, index2->keyValue);
TASS Belgium NV 131:4758606c9316 292 }
TASS Belgium NV 131:4758606c9316 293 /* any record with filter mode EXCLUDE, causes the interface mode to be EXCLUDE */
TASS Belgium NV 131:4758606c9316 294 filter_mode = PICO_IP_MULTICAST_EXCLUDE;
TASS Belgium NV 131:4758606c9316 295 /* add to the interface EXCLUDE filter any socket source NOT in the former interface INCLUDE filter */
TASS Belgium NV 131:4758606c9316 296 pico_tree_foreach(index2, &listen->MCASTSources)
TASS Belgium NV 131:4758606c9316 297 {
TASS Belgium NV 131:4758606c9316 298 source = pico_tree_insert(&MCASTFilter, index2->keyValue);
TASS Belgium NV 131:4758606c9316 299 if (source)
TASS Belgium NV 131:4758606c9316 300 pico_tree_delete(&MCASTFilter, source);
TASS Belgium NV 131:4758606c9316 301 }
TASS Belgium NV 131:4758606c9316 302 break;
TASS Belgium NV 131:4758606c9316 303
TASS Belgium NV 131:4758606c9316 304 default:
TASS Belgium NV 131:4758606c9316 305 return -1;
TASS Belgium NV 131:4758606c9316 306 }
TASS Belgium NV 131:4758606c9316 307 break;
tass 68:0847e35d08a6 308
tass 68:0847e35d08a6 309 case PICO_IP_MULTICAST_EXCLUDE:
TASS Belgium NV 131:4758606c9316 310 switch (listen->filter_mode)
TASS Belgium NV 131:4758606c9316 311 {
TASS Belgium NV 131:4758606c9316 312 case PICO_IP_MULTICAST_INCLUDE:
TASS Belgium NV 131:4758606c9316 313 /* filter = EXCLUDE - INCLUDE */
TASS Belgium NV 131:4758606c9316 314 /* any record with filter mode EXCLUDE, causes the interface mode to be EXCLUDE */
TASS Belgium NV 131:4758606c9316 315 /* remove from the interface EXCLUDE filter any source in the socket INCLUDE filter */
TASS Belgium NV 131:4758606c9316 316 pico_tree_foreach(index2, &listen->MCASTSources)
TASS Belgium NV 131:4758606c9316 317 {
TASS Belgium NV 131:4758606c9316 318 source = pico_tree_findKey(&MCASTFilter, index2->keyValue);
TASS Belgium NV 131:4758606c9316 319 if (source)
TASS Belgium NV 131:4758606c9316 320 pico_tree_delete(&MCASTFilter, source);
TASS Belgium NV 131:4758606c9316 321 }
TASS Belgium NV 131:4758606c9316 322 break;
TASS Belgium NV 131:4758606c9316 323
TASS Belgium NV 131:4758606c9316 324 case PICO_IP_MULTICAST_EXCLUDE:
TASS Belgium NV 131:4758606c9316 325 /* filter = intersection of EXCLUDEs */
TASS Belgium NV 131:4758606c9316 326 /* any record with filter mode EXCLUDE, causes the interface mode to be EXCLUDE */
TASS Belgium NV 131:4758606c9316 327 /* remove from the interface EXCLUDE filter any source not in the socket EXCLUDE filter */
TASS Belgium NV 131:4758606c9316 328 pico_tree_foreach_safe(index2, &MCASTFilter, _tmp2)
TASS Belgium NV 131:4758606c9316 329 {
TASS Belgium NV 131:4758606c9316 330 source = pico_tree_findKey(&listen->MCASTSources, index2->keyValue);
TASS Belgium NV 131:4758606c9316 331 if (!source)
TASS Belgium NV 131:4758606c9316 332 pico_tree_delete(&MCASTFilter, index2->keyValue);
TASS Belgium NV 131:4758606c9316 333 }
TASS Belgium NV 131:4758606c9316 334 break;
TASS Belgium NV 131:4758606c9316 335
TASS Belgium NV 131:4758606c9316 336 default:
TASS Belgium NV 131:4758606c9316 337 return -1;
TASS Belgium NV 131:4758606c9316 338 }
TASS Belgium NV 131:4758606c9316 339 break;
tass 68:0847e35d08a6 340
tass 68:0847e35d08a6 341 default:
TASS Belgium NV 131:4758606c9316 342 return -1;
TASS Belgium NV 131:4758606c9316 343 }
TASS Belgium NV 131:4758606c9316 344 }
tass 68:0847e35d08a6 345 }
TASS Belgium NV 131:4758606c9316 346 return filter_mode;
tass 68:0847e35d08a6 347 }
tass 68:0847e35d08a6 348
tass 68:0847e35d08a6 349 static int pico_socket_mcast_filter(struct pico_socket *s, struct pico_ip4 *mcast_group, struct pico_ip4 *src)
tass 68:0847e35d08a6 350 {
TASS Belgium NV 131:4758606c9316 351 struct pico_ipv4_link *mcast_link = NULL;
TASS Belgium NV 131:4758606c9316 352 struct pico_mcast_listen *listen = NULL;
TASS Belgium NV 131:4758606c9316 353 struct pico_tree_node *index = NULL;
tass 68:0847e35d08a6 354
TASS Belgium NV 131:4758606c9316 355 /* no multicast enabled on socket */
TASS Belgium NV 131:4758606c9316 356 if (!s->MCASTListen)
TASS Belgium NV 131:4758606c9316 357 return 0;
tass 68:0847e35d08a6 358
TASS Belgium NV 131:4758606c9316 359 mcast_link = pico_ipv4_link_get(&s->local_addr.ip4);
TASS Belgium NV 131:4758606c9316 360 if (!mcast_link)
TASS Belgium NV 131:4758606c9316 361 return -1;
tass 68:0847e35d08a6 362
TASS Belgium NV 131:4758606c9316 363 listen = listen_find(s, &mcast_link->address, mcast_group);
TASS Belgium NV 131:4758606c9316 364 if (!listen)
TASS Belgium NV 131:4758606c9316 365 return -1;
TASS Belgium NV 131:4758606c9316 366
TASS Belgium NV 131:4758606c9316 367 /* perform source filtering */
TASS Belgium NV 131:4758606c9316 368 switch (listen->filter_mode)
TASS Belgium NV 131:4758606c9316 369 {
tass 68:0847e35d08a6 370 case PICO_IP_MULTICAST_INCLUDE:
TASS Belgium NV 131:4758606c9316 371 pico_tree_foreach(index, &listen->MCASTSources)
TASS Belgium NV 131:4758606c9316 372 {
TASS Belgium NV 131:4758606c9316 373 if (src->addr == ((struct pico_ip4 *)index->keyValue)->addr) {
TASS Belgium NV 131:4758606c9316 374 so_mcast_dbg("MCAST: IP %08X in included socket source list\n", src->addr);
TASS Belgium NV 131:4758606c9316 375 return 0;
TASS Belgium NV 131:4758606c9316 376 }
tass 68:0847e35d08a6 377 }
TASS Belgium NV 131:4758606c9316 378 so_mcast_dbg("MCAST: IP %08X NOT in included socket source list\n", src->addr);
TASS Belgium NV 131:4758606c9316 379 return -1;
TASS Belgium NV 131:4758606c9316 380 break;
tass 68:0847e35d08a6 381
tass 68:0847e35d08a6 382 case PICO_IP_MULTICAST_EXCLUDE:
TASS Belgium NV 131:4758606c9316 383 pico_tree_foreach(index, &listen->MCASTSources)
TASS Belgium NV 131:4758606c9316 384 {
TASS Belgium NV 131:4758606c9316 385 if (src->addr == ((struct pico_ip4 *)index->keyValue)->addr) {
TASS Belgium NV 131:4758606c9316 386 so_mcast_dbg("MCAST: IP %08X in excluded socket source list\n", src->addr);
TASS Belgium NV 131:4758606c9316 387 return -1;
TASS Belgium NV 131:4758606c9316 388 }
tass 68:0847e35d08a6 389 }
TASS Belgium NV 131:4758606c9316 390 so_mcast_dbg("MCAST: IP %08X NOT in excluded socket source list\n", src->addr);
TASS Belgium NV 131:4758606c9316 391 return 0;
TASS Belgium NV 131:4758606c9316 392 break;
tass 68:0847e35d08a6 393
tass 68:0847e35d08a6 394 default:
TASS Belgium NV 131:4758606c9316 395 return -1;
TASS Belgium NV 131:4758606c9316 396 break;
TASS Belgium NV 131:4758606c9316 397 }
TASS Belgium NV 131:4758606c9316 398 return -1;
tass 68:0847e35d08a6 399 }
tass 68:0847e35d08a6 400
tass 68:0847e35d08a6 401 static inline struct pico_ipv4_link *pico_socket_setoption_mcastargs_validation(struct pico_ip_mreq *mreq, struct pico_ip_mreq_source *mreq_source)
tass 68:0847e35d08a6 402 {
TASS Belgium NV 131:4758606c9316 403 struct pico_ipv4_link *mcast_link = NULL;
tass 68:0847e35d08a6 404
TASS Belgium NV 131:4758606c9316 405 if (!mreq && !mreq_source)
TASS Belgium NV 131:4758606c9316 406 return NULL;
TASS Belgium NV 131:4758606c9316 407
TASS Belgium NV 131:4758606c9316 408 if (mreq) {
TASS Belgium NV 131:4758606c9316 409 if (!mreq->mcast_group_addr.addr)
TASS Belgium NV 131:4758606c9316 410 return NULL;
tass 68:0847e35d08a6 411
TASS Belgium NV 131:4758606c9316 412 if (pico_ipv4_is_unicast(mreq->mcast_group_addr.addr))
TASS Belgium NV 131:4758606c9316 413 return NULL;
tass 68:0847e35d08a6 414
TASS Belgium NV 131:4758606c9316 415 if (!mreq->mcast_link_addr.addr) {
TASS Belgium NV 131:4758606c9316 416 mcast_link = pico_ipv4_get_default_mcastlink();
TASS Belgium NV 131:4758606c9316 417 if (!mcast_link)
TASS Belgium NV 131:4758606c9316 418 return NULL;
TASS Belgium NV 131:4758606c9316 419 } else {
TASS Belgium NV 131:4758606c9316 420 mcast_link = pico_ipv4_link_get(&mreq->mcast_link_addr);
TASS Belgium NV 131:4758606c9316 421 if (!mcast_link)
TASS Belgium NV 131:4758606c9316 422 return NULL;
TASS Belgium NV 131:4758606c9316 423 }
tass 68:0847e35d08a6 424 }
TASS Belgium NV 131:4758606c9316 425
TASS Belgium NV 131:4758606c9316 426 if (mreq_source) {
TASS Belgium NV 131:4758606c9316 427 if (!mreq_source->mcast_group_addr.addr)
TASS Belgium NV 131:4758606c9316 428 return NULL;
tass 68:0847e35d08a6 429
TASS Belgium NV 131:4758606c9316 430 if (pico_ipv4_is_unicast(mreq_source->mcast_group_addr.addr))
TASS Belgium NV 131:4758606c9316 431 return NULL;
TASS Belgium NV 131:4758606c9316 432
TASS Belgium NV 131:4758606c9316 433 if (!mreq_source->mcast_source_addr.addr)
TASS Belgium NV 131:4758606c9316 434 return NULL;
tass 68:0847e35d08a6 435
TASS Belgium NV 131:4758606c9316 436 if (!pico_ipv4_is_unicast(mreq_source->mcast_source_addr.addr))
TASS Belgium NV 131:4758606c9316 437 return NULL;
TASS Belgium NV 131:4758606c9316 438
TASS Belgium NV 131:4758606c9316 439 if (!mreq_source->mcast_link_addr.addr) {
TASS Belgium NV 131:4758606c9316 440 mcast_link = pico_ipv4_get_default_mcastlink();
TASS Belgium NV 131:4758606c9316 441 if (!mcast_link)
TASS Belgium NV 131:4758606c9316 442 return NULL;
TASS Belgium NV 131:4758606c9316 443 } else {
TASS Belgium NV 131:4758606c9316 444 mcast_link = pico_ipv4_link_get(&mreq_source->mcast_link_addr);
TASS Belgium NV 131:4758606c9316 445 if (!mcast_link)
TASS Belgium NV 131:4758606c9316 446 return NULL;
TASS Belgium NV 131:4758606c9316 447 }
tass 68:0847e35d08a6 448 }
TASS Belgium NV 131:4758606c9316 449
TASS Belgium NV 131:4758606c9316 450 return mcast_link;
tass 68:0847e35d08a6 451 }
tass 68:0847e35d08a6 452 #else
TASS Belgium NV 131:4758606c9316 453 static int pico_socket_mcast_filter(struct pico_socket *s, struct pico_ip4 *mcast_group, struct pico_ip4 *src)
TASS Belgium NV 131:4758606c9316 454 {
TASS Belgium NV 131:4758606c9316 455 return 0;
tass 68:0847e35d08a6 456 }
tass 68:0847e35d08a6 457 #endif /* PICO_SUPPORT_MCAST */
tass 68:0847e35d08a6 458
tass 68:0847e35d08a6 459 static struct pico_sockport *pico_get_sockport(uint16_t proto, uint16_t port)
tass 68:0847e35d08a6 460 {
TASS Belgium NV 131:4758606c9316 461 struct pico_sockport test = INIT_SOCKPORT;
TASS Belgium NV 131:4758606c9316 462 test.number = port;
tass 68:0847e35d08a6 463
TASS Belgium NV 131:4758606c9316 464 if (proto == PICO_PROTO_UDP)
TASS Belgium NV 131:4758606c9316 465 return pico_tree_findKey(&UDPTable, &test);
tass 68:0847e35d08a6 466
TASS Belgium NV 131:4758606c9316 467 else if (proto == PICO_PROTO_TCP)
TASS Belgium NV 131:4758606c9316 468 return pico_tree_findKey(&TCPTable, &test);
tass 68:0847e35d08a6 469
TASS Belgium NV 131:4758606c9316 470 else return NULL;
tass 68:0847e35d08a6 471 }
tass 68:0847e35d08a6 472
tass 68:0847e35d08a6 473 int pico_is_port_free(uint16_t proto, uint16_t port, void *addr, void *net)
tass 68:0847e35d08a6 474 {
TASS Belgium NV 131:4758606c9316 475 struct pico_sockport *sp;
TASS Belgium NV 131:4758606c9316 476 struct pico_ip4 ip;
TASS Belgium NV 131:4758606c9316 477 sp = pico_get_sockport(proto, port);
tass 68:0847e35d08a6 478
TASS Belgium NV 131:4758606c9316 479 if (!net)
TASS Belgium NV 131:4758606c9316 480 net = &pico_proto_ipv4;
tass 68:0847e35d08a6 481
TASS Belgium NV 131:4758606c9316 482 /** IPv6 (wip) ***/
TASS Belgium NV 131:4758606c9316 483 if (net != &pico_proto_ipv4) {
TASS Belgium NV 131:4758606c9316 484 dbg("IPV6!!!!!\n");
TASS Belgium NV 131:4758606c9316 485 return (!sp);
TASS Belgium NV 131:4758606c9316 486 }
tass 68:0847e35d08a6 487
TASS Belgium NV 131:4758606c9316 488 /* IPv4 */
tass 68:0847e35d08a6 489 #ifdef PICO_SUPPORT_NAT
TASS Belgium NV 131:4758606c9316 490 if (pico_ipv4_nat_find(port, NULL, 0, (uint8_t)proto)) {
TASS Belgium NV 131:4758606c9316 491 dbg("In use by nat....\n");
TASS Belgium NV 131:4758606c9316 492 return 0;
TASS Belgium NV 131:4758606c9316 493 }
TASS Belgium NV 131:4758606c9316 494
tass 68:0847e35d08a6 495 #endif
TASS Belgium NV 131:4758606c9316 496 if (addr)
TASS Belgium NV 131:4758606c9316 497 ip.addr = ((struct pico_ip4 *)addr)->addr;
TASS Belgium NV 131:4758606c9316 498 else
TASS Belgium NV 131:4758606c9316 499 ip.addr = PICO_IPV4_INADDR_ANY;
TASS Belgium NV 131:4758606c9316 500
TASS Belgium NV 131:4758606c9316 501 if (ip.addr == PICO_IPV4_INADDR_ANY) {
TASS Belgium NV 131:4758606c9316 502 if (!sp) return 1;
TASS Belgium NV 131:4758606c9316 503 else {
TASS Belgium NV 131:4758606c9316 504 dbg("In use, and asked for ANY\n");
TASS Belgium NV 131:4758606c9316 505 return 0;
TASS Belgium NV 131:4758606c9316 506 }
TASS Belgium NV 131:4758606c9316 507 }
tass 68:0847e35d08a6 508
TASS Belgium NV 131:4758606c9316 509 if (sp) {
TASS Belgium NV 131:4758606c9316 510 struct pico_ip4 *s_local;
TASS Belgium NV 131:4758606c9316 511 struct pico_tree_node *idx;
TASS Belgium NV 131:4758606c9316 512 struct pico_socket *s;
TASS Belgium NV 131:4758606c9316 513 pico_tree_foreach(idx, &sp->socks) {
TASS Belgium NV 131:4758606c9316 514 s = idx->keyValue;
TASS Belgium NV 131:4758606c9316 515 if (s->net == &pico_proto_ipv4) {
TASS Belgium NV 131:4758606c9316 516 s_local = (struct pico_ip4*) &s->local_addr;
TASS Belgium NV 131:4758606c9316 517 if ((s_local->addr == PICO_IPV4_INADDR_ANY) || (s_local->addr == ip.addr))
TASS Belgium NV 131:4758606c9316 518 return 0;
TASS Belgium NV 131:4758606c9316 519 }
TASS Belgium NV 131:4758606c9316 520 }
tass 68:0847e35d08a6 521 }
TASS Belgium NV 131:4758606c9316 522
TASS Belgium NV 131:4758606c9316 523 return 1;
tass 68:0847e35d08a6 524 }
tass 68:0847e35d08a6 525
tass 68:0847e35d08a6 526 static int pico_check_socket(struct pico_socket *s)
tass 68:0847e35d08a6 527 {
TASS Belgium NV 131:4758606c9316 528 struct pico_sockport *test;
TASS Belgium NV 131:4758606c9316 529 struct pico_socket *found;
TASS Belgium NV 131:4758606c9316 530 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 531
TASS Belgium NV 131:4758606c9316 532 test = pico_get_sockport(PROTO(s), s->local_port);
tass 68:0847e35d08a6 533
TASS Belgium NV 131:4758606c9316 534 if (!test) {
TASS Belgium NV 131:4758606c9316 535 return -1;
TASS Belgium NV 131:4758606c9316 536 }
TASS Belgium NV 131:4758606c9316 537
TASS Belgium NV 131:4758606c9316 538 pico_tree_foreach(index, &test->socks){
TASS Belgium NV 131:4758606c9316 539 found = index->keyValue;
TASS Belgium NV 131:4758606c9316 540 if (s == found) {
TASS Belgium NV 131:4758606c9316 541 return 0;
TASS Belgium NV 131:4758606c9316 542 }
TASS Belgium NV 131:4758606c9316 543 }
TASS Belgium NV 131:4758606c9316 544
tass 68:0847e35d08a6 545 return -1;
tass 68:0847e35d08a6 546 }
tass 68:0847e35d08a6 547
TASS Belgium NV 131:4758606c9316 548 struct pico_socket*pico_sockets_find(uint16_t local, uint16_t remote)
tass 68:0847e35d08a6 549 {
TASS Belgium NV 131:4758606c9316 550 struct pico_socket *sock = NULL;
TASS Belgium NV 131:4758606c9316 551 struct pico_tree_node *index = NULL;
TASS Belgium NV 131:4758606c9316 552 struct pico_sockport *sp = NULL;
tass 68:0847e35d08a6 553
TASS Belgium NV 131:4758606c9316 554 sp = pico_get_sockport(PICO_PROTO_TCP, local);
TASS Belgium NV 131:4758606c9316 555 if(sp)
TASS Belgium NV 131:4758606c9316 556 {
TASS Belgium NV 131:4758606c9316 557 pico_tree_foreach(index, &sp->socks)
TASS Belgium NV 131:4758606c9316 558 {
TASS Belgium NV 131:4758606c9316 559 if(((struct pico_socket *)index->keyValue)->remote_port == remote)
TASS Belgium NV 131:4758606c9316 560 {
TASS Belgium NV 131:4758606c9316 561 sock = (struct pico_socket *)index->keyValue;
TASS Belgium NV 131:4758606c9316 562 break;
TASS Belgium NV 131:4758606c9316 563 }
TASS Belgium NV 131:4758606c9316 564 }
TASS Belgium NV 131:4758606c9316 565 }
tass 68:0847e35d08a6 566
TASS Belgium NV 131:4758606c9316 567 return sock;
tass 68:0847e35d08a6 568 }
tass 68:0847e35d08a6 569
tass 68:0847e35d08a6 570
tass 70:cd218dd180e5 571 int8_t pico_socket_add(struct pico_socket *s)
tass 68:0847e35d08a6 572 {
TASS Belgium NV 131:4758606c9316 573 struct pico_sockport *sp = pico_get_sockport(PROTO(s), s->local_port);
TASS Belgium NV 131:4758606c9316 574 LOCK(Mutex);
tass 68:0847e35d08a6 575 if (!sp) {
TASS Belgium NV 131:4758606c9316 576 /* dbg("Creating sockport..%04x\n", s->local_port); / * In comment due to spam during test * / */
TASS Belgium NV 131:4758606c9316 577 sp = pico_zalloc(sizeof(struct pico_sockport));
TASS Belgium NV 131:4758606c9316 578
TASS Belgium NV 131:4758606c9316 579 if (!sp) {
TASS Belgium NV 131:4758606c9316 580 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 581 UNLOCK(Mutex);
TASS Belgium NV 131:4758606c9316 582 return -1;
TASS Belgium NV 131:4758606c9316 583 }
tass 68:0847e35d08a6 584
TASS Belgium NV 131:4758606c9316 585 sp->proto = PROTO(s);
TASS Belgium NV 131:4758606c9316 586 sp->number = s->local_port;
TASS Belgium NV 131:4758606c9316 587 sp->socks.root = &LEAF;
TASS Belgium NV 131:4758606c9316 588 sp->socks.compare = socket_cmp;
tass 68:0847e35d08a6 589
TASS Belgium NV 131:4758606c9316 590 if (PROTO(s) == PICO_PROTO_UDP)
TASS Belgium NV 131:4758606c9316 591 {
TASS Belgium NV 131:4758606c9316 592 pico_tree_insert(&UDPTable, sp);
TASS Belgium NV 131:4758606c9316 593 }
TASS Belgium NV 131:4758606c9316 594 else if (PROTO(s) == PICO_PROTO_TCP)
TASS Belgium NV 131:4758606c9316 595 {
TASS Belgium NV 131:4758606c9316 596 pico_tree_insert(&TCPTable, sp);
TASS Belgium NV 131:4758606c9316 597 }
tass 68:0847e35d08a6 598 }
tass 68:0847e35d08a6 599
TASS Belgium NV 131:4758606c9316 600 pico_tree_insert(&sp->socks, s);
TASS Belgium NV 131:4758606c9316 601 s->state |= PICO_SOCKET_STATE_BOUND;
TASS Belgium NV 131:4758606c9316 602 UNLOCK(Mutex);
TASS Belgium NV 131:4758606c9316 603 #if DEBUG_SOCKET_TREE
TASS Belgium NV 131:4758606c9316 604 {
TASS Belgium NV 131:4758606c9316 605 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 606 /* RB_FOREACH(s, socket_tree, &sp->socks) { */
TASS Belgium NV 131:4758606c9316 607 pico_tree_foreach(index, &sp->socks){
TASS Belgium NV 131:4758606c9316 608 s = index->keyValue;
TASS Belgium NV 131:4758606c9316 609 dbg(">>>> List Socket lc=%hu rm=%hu\n", short_be(s->local_port), short_be(s->remote_port));
TASS Belgium NV 131:4758606c9316 610 }
TASS Belgium NV 131:4758606c9316 611
TASS Belgium NV 131:4758606c9316 612 }
tass 68:0847e35d08a6 613 #endif
TASS Belgium NV 131:4758606c9316 614 return 0;
tass 68:0847e35d08a6 615 }
tass 68:0847e35d08a6 616
tass 68:0847e35d08a6 617 static void socket_clean_queues(struct pico_socket *sock)
tass 68:0847e35d08a6 618 {
TASS Belgium NV 131:4758606c9316 619 struct pico_frame *f_in = pico_dequeue(&sock->q_in);
TASS Belgium NV 131:4758606c9316 620 struct pico_frame *f_out = pico_dequeue(&sock->q_out);
TASS Belgium NV 131:4758606c9316 621 while(f_in || f_out)
tass 68:0847e35d08a6 622 {
TASS Belgium NV 131:4758606c9316 623 if(f_in)
TASS Belgium NV 131:4758606c9316 624 {
TASS Belgium NV 131:4758606c9316 625 pico_frame_discard(f_in);
TASS Belgium NV 131:4758606c9316 626 f_in = pico_dequeue(&sock->q_in);
TASS Belgium NV 131:4758606c9316 627 }
tass 68:0847e35d08a6 628
TASS Belgium NV 131:4758606c9316 629 if(f_out)
TASS Belgium NV 131:4758606c9316 630 {
TASS Belgium NV 131:4758606c9316 631 pico_frame_discard(f_out);
TASS Belgium NV 131:4758606c9316 632 f_out = pico_dequeue(&sock->q_out);
TASS Belgium NV 131:4758606c9316 633 }
tass 68:0847e35d08a6 634 }
TASS Belgium NV 131:4758606c9316 635 /* for tcp sockets go further and clean the sockets inside queue */
TASS Belgium NV 131:4758606c9316 636 if(sock->proto == &pico_proto_tcp)
TASS Belgium NV 131:4758606c9316 637 pico_tcp_cleanup_queues(sock);
tass 68:0847e35d08a6 638 }
tass 68:0847e35d08a6 639
tass 128:ae39e6e81531 640 static void socket_garbage_collect(pico_time now, void *arg)
tass 68:0847e35d08a6 641 {
TASS Belgium NV 131:4758606c9316 642 struct pico_socket *s = (struct pico_socket *) arg;
TASS Belgium NV 131:4758606c9316 643 IGNORE_PARAMETER(now);
tass 128:ae39e6e81531 644
TASS Belgium NV 131:4758606c9316 645 socket_clean_queues(s);
TASS Belgium NV 131:4758606c9316 646 pico_free(s);
tass 68:0847e35d08a6 647 }
tass 68:0847e35d08a6 648
tass 70:cd218dd180e5 649 int8_t pico_socket_del(struct pico_socket *s)
tass 68:0847e35d08a6 650 {
TASS Belgium NV 131:4758606c9316 651 struct pico_sockport *sp = pico_get_sockport(PROTO(s), s->local_port);
tass 68:0847e35d08a6 652
TASS Belgium NV 131:4758606c9316 653 if (!sp) {
TASS Belgium NV 131:4758606c9316 654 pico_err = PICO_ERR_ENXIO;
TASS Belgium NV 131:4758606c9316 655 return -1;
tass 68:0847e35d08a6 656 }
tass 68:0847e35d08a6 657
TASS Belgium NV 131:4758606c9316 658 LOCK(Mutex);
TASS Belgium NV 131:4758606c9316 659 pico_tree_delete(&sp->socks, s);
TASS Belgium NV 131:4758606c9316 660 s->net = NULL;
TASS Belgium NV 131:4758606c9316 661 if(pico_tree_empty(&sp->socks)) {
TASS Belgium NV 131:4758606c9316 662 if (PROTO(s) == PICO_PROTO_UDP)
TASS Belgium NV 131:4758606c9316 663 {
TASS Belgium NV 131:4758606c9316 664 pico_tree_delete(&UDPTable, sp);
TASS Belgium NV 131:4758606c9316 665 }
TASS Belgium NV 131:4758606c9316 666 else if (PROTO(s) == PICO_PROTO_TCP)
TASS Belgium NV 131:4758606c9316 667 {
TASS Belgium NV 131:4758606c9316 668 pico_tree_delete(&TCPTable, sp);
TASS Belgium NV 131:4758606c9316 669 }
tass 68:0847e35d08a6 670
TASS Belgium NV 131:4758606c9316 671 if(sp_tcp == sp) sp_tcp = NULL;
TASS Belgium NV 131:4758606c9316 672
TASS Belgium NV 131:4758606c9316 673 if(sp_udp == sp) sp_udp = NULL;
tass 68:0847e35d08a6 674
TASS Belgium NV 131:4758606c9316 675 pico_free(sp);
TASS Belgium NV 131:4758606c9316 676
TASS Belgium NV 131:4758606c9316 677 }
tass 68:0847e35d08a6 678
tass 68:0847e35d08a6 679 #ifdef PICO_SUPPORT_MCAST
TASS Belgium NV 131:4758606c9316 680 do {
TASS Belgium NV 131:4758606c9316 681 int filter_mode;
TASS Belgium NV 131:4758606c9316 682 struct pico_tree_node *index = NULL, *_tmp = NULL, *index2 = NULL, *_tmp2 = NULL;
TASS Belgium NV 131:4758606c9316 683 struct pico_mcast_listen *listen = NULL;
TASS Belgium NV 131:4758606c9316 684 struct pico_ip4 *source = NULL;
TASS Belgium NV 131:4758606c9316 685 if (s->MCASTListen) {
TASS Belgium NV 131:4758606c9316 686 pico_tree_delete(&MCASTSockets, s);
TASS Belgium NV 131:4758606c9316 687 pico_tree_foreach_safe(index, s->MCASTListen, _tmp)
TASS Belgium NV 131:4758606c9316 688 {
TASS Belgium NV 131:4758606c9316 689 listen = index->keyValue;
TASS Belgium NV 131:4758606c9316 690 pico_tree_foreach_safe(index2, &listen->MCASTSources, _tmp2)
TASS Belgium NV 131:4758606c9316 691 {
TASS Belgium NV 131:4758606c9316 692 source = index->keyValue;
TASS Belgium NV 131:4758606c9316 693 pico_tree_delete(&listen->MCASTSources, source);
TASS Belgium NV 131:4758606c9316 694 pico_free(source);
TASS Belgium NV 131:4758606c9316 695 }
TASS Belgium NV 131:4758606c9316 696 filter_mode = pico_socket_aggregate_mcastfilters(&listen->mcast_link, &listen->mcast_group);
TASS Belgium NV 131:4758606c9316 697 if (filter_mode >= 0)
TASS Belgium NV 131:4758606c9316 698 pico_ipv4_mcast_leave(&listen->mcast_link, &listen->mcast_group, 1, (uint8_t)filter_mode, &MCASTFilter);
TASS Belgium NV 131:4758606c9316 699
TASS Belgium NV 131:4758606c9316 700 pico_tree_delete(s->MCASTListen, listen);
TASS Belgium NV 131:4758606c9316 701 pico_free(listen);
TASS Belgium NV 131:4758606c9316 702 }
TASS Belgium NV 131:4758606c9316 703 pico_free(s->MCASTListen);
tass 68:0847e35d08a6 704 }
TASS Belgium NV 131:4758606c9316 705 } while (0);
tass 68:0847e35d08a6 706 #endif
tass 68:0847e35d08a6 707
tass picotcp@tass.be 133:5b075f5e141a 708 #ifdef PICO_SUPPORT_TCP
tass picotcp@tass.be 133:5b075f5e141a 709 if(s->parent)
tass picotcp@tass.be 133:5b075f5e141a 710 s->parent->number_of_pending_conn--;
tass picotcp@tass.be 133:5b075f5e141a 711 #endif
tass picotcp@tass.be 133:5b075f5e141a 712
TASS Belgium NV 131:4758606c9316 713 s->state = PICO_SOCKET_STATE_CLOSED;
TASS Belgium NV 131:4758606c9316 714 pico_timer_add(3000, socket_garbage_collect, s);
TASS Belgium NV 131:4758606c9316 715 UNLOCK(Mutex);
TASS Belgium NV 131:4758606c9316 716 return 0;
tass 68:0847e35d08a6 717 }
tass 68:0847e35d08a6 718
tass 70:cd218dd180e5 719 static int8_t pico_socket_alter_state(struct pico_socket *s, uint16_t more_states, uint16_t less_states, uint16_t tcp_state)
tass 68:0847e35d08a6 720 {
TASS Belgium NV 131:4758606c9316 721 struct pico_sockport *sp;
TASS Belgium NV 131:4758606c9316 722 if (more_states & PICO_SOCKET_STATE_BOUND)
TASS Belgium NV 131:4758606c9316 723 return pico_socket_add(s);
tass 68:0847e35d08a6 724
TASS Belgium NV 131:4758606c9316 725 if (less_states & PICO_SOCKET_STATE_BOUND)
TASS Belgium NV 131:4758606c9316 726 return pico_socket_del(s);
tass 68:0847e35d08a6 727
TASS Belgium NV 131:4758606c9316 728 sp = pico_get_sockport(PROTO(s), s->local_port);
TASS Belgium NV 131:4758606c9316 729 if (!sp) {
TASS Belgium NV 131:4758606c9316 730 pico_err = PICO_ERR_ENXIO;
TASS Belgium NV 131:4758606c9316 731 return -1;
TASS Belgium NV 131:4758606c9316 732 }
tass 68:0847e35d08a6 733
TASS Belgium NV 131:4758606c9316 734 s->state |= more_states;
TASS Belgium NV 131:4758606c9316 735 s->state = (uint16_t)(s->state & (~less_states));
TASS Belgium NV 131:4758606c9316 736 if (tcp_state) {
TASS Belgium NV 131:4758606c9316 737 s->state &= 0x00FF;
TASS Belgium NV 131:4758606c9316 738 s->state |= tcp_state;
TASS Belgium NV 131:4758606c9316 739 }
tass 68:0847e35d08a6 740
TASS Belgium NV 131:4758606c9316 741 return 0;
tass 68:0847e35d08a6 742 }
tass 68:0847e35d08a6 743
tass 68:0847e35d08a6 744 static int pico_socket_deliver(struct pico_protocol *p, struct pico_frame *f, uint16_t localport)
tass 68:0847e35d08a6 745 {
TASS Belgium NV 131:4758606c9316 746 struct pico_frame *cpy = NULL;
TASS Belgium NV 131:4758606c9316 747 struct pico_sockport *sp = NULL;
TASS Belgium NV 131:4758606c9316 748 struct pico_socket *s = NULL;
TASS Belgium NV 131:4758606c9316 749 struct pico_tree_node *index = NULL;
TASS Belgium NV 131:4758606c9316 750 struct pico_tree_node *_tmp;
TASS Belgium NV 131:4758606c9316 751 struct pico_trans *tr = (struct pico_trans *) f->transport_hdr;
tass 68:0847e35d08a6 752 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 753 struct pico_ipv4_hdr *ip4hdr;
tass 68:0847e35d08a6 754 #endif
tass 68:0847e35d08a6 755 #ifdef PICO_SUPPORT_IPV6
TASS Belgium NV 131:4758606c9316 756 struct pico_ipv6_hdr *ip6hdr;
tass 68:0847e35d08a6 757 #endif
tass 68:0847e35d08a6 758
tass 125:96003ae6f1d8 759 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 760 struct pico_socket *found = NULL;
tass 125:96003ae6f1d8 761 #endif
tass 125:96003ae6f1d8 762
TASS Belgium NV 131:4758606c9316 763 if (!tr)
TASS Belgium NV 131:4758606c9316 764 return -1;
tass 68:0847e35d08a6 765
TASS Belgium NV 131:4758606c9316 766 sp = pico_get_sockport(p->proto_number, localport);
tass 68:0847e35d08a6 767
TASS Belgium NV 131:4758606c9316 768 if (!sp) {
TASS Belgium NV 131:4758606c9316 769 dbg("No such port %d\n", short_be(localport));
TASS Belgium NV 131:4758606c9316 770 return -1;
TASS Belgium NV 131:4758606c9316 771 }
tass 68:0847e35d08a6 772
tass 68:0847e35d08a6 773 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 774 if (p->proto_number == PICO_PROTO_TCP) {
TASS Belgium NV 131:4758606c9316 775 pico_tree_foreach_safe(index, &sp->socks, _tmp){
TASS Belgium NV 131:4758606c9316 776 s = index->keyValue;
TASS Belgium NV 131:4758606c9316 777 /* 4-tuple identification of socket (port-IP) */
tass 68:0847e35d08a6 778 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 779 if (IS_IPV4(f)) {
TASS Belgium NV 131:4758606c9316 780 struct pico_ip4 s_local, s_remote, p_src, p_dst;
TASS Belgium NV 131:4758606c9316 781 ip4hdr = (struct pico_ipv4_hdr*)(f->net_hdr);
TASS Belgium NV 131:4758606c9316 782 s_local.addr = s->local_addr.ip4.addr;
TASS Belgium NV 131:4758606c9316 783 s_remote.addr = s->remote_addr.ip4.addr;
TASS Belgium NV 131:4758606c9316 784 p_src.addr = ip4hdr->src.addr;
TASS Belgium NV 131:4758606c9316 785 p_dst.addr = ip4hdr->dst.addr;
TASS Belgium NV 131:4758606c9316 786 if ((s->remote_port == tr->sport) && /* remote port check */
TASS Belgium NV 131:4758606c9316 787 (s_remote.addr == p_src.addr) && /* remote addr check */
TASS Belgium NV 131:4758606c9316 788 ((s_local.addr == PICO_IPV4_INADDR_ANY) || (s_local.addr == p_dst.addr))) { /* Either local socket is ANY, or matches dst */
TASS Belgium NV 131:4758606c9316 789 found = s;
TASS Belgium NV 131:4758606c9316 790 break;
TASS Belgium NV 131:4758606c9316 791 } else if ((s->remote_port == 0) && /* not connected... listening */
TASS Belgium NV 131:4758606c9316 792 ((s_local.addr == PICO_IPV4_INADDR_ANY) || (s_local.addr == p_dst.addr))) { /* Either local socket is ANY, or matches dst */
TASS Belgium NV 131:4758606c9316 793 /* listen socket */
TASS Belgium NV 131:4758606c9316 794 found = s;
TASS Belgium NV 131:4758606c9316 795 }
TASS Belgium NV 131:4758606c9316 796 }
TASS Belgium NV 131:4758606c9316 797
tass 68:0847e35d08a6 798 #endif
tass 68:0847e35d08a6 799 #ifdef PICO_SUPPORT_IPV6 /* XXX TODO make compare for ipv6 addresses */
TASS Belgium NV 131:4758606c9316 800 if (IS_IPV6(f)) {
TASS Belgium NV 131:4758606c9316 801 ip6hdr = (struct pico_ipv6_hdr*)(f->net_hdr);
TASS Belgium NV 131:4758606c9316 802 if ((s->remote_port == localport)) { /* && (((struct pico_ip6) s->remote_addr.ip6).addr == ((struct pico_ip6)(ip6hdr->src)).addr) ) { */
TASS Belgium NV 131:4758606c9316 803 found = s;
TASS Belgium NV 131:4758606c9316 804 break;
TASS Belgium NV 131:4758606c9316 805 } else if (s->remote_port == 0) {
TASS Belgium NV 131:4758606c9316 806 /* listen socket */
TASS Belgium NV 131:4758606c9316 807 found = s;
TASS Belgium NV 131:4758606c9316 808 }
TASS Belgium NV 131:4758606c9316 809 }
TASS Belgium NV 131:4758606c9316 810
TASS Belgium NV 131:4758606c9316 811 #endif
TASS Belgium NV 131:4758606c9316 812 } /* FOREACH */
TASS Belgium NV 131:4758606c9316 813 if (found != NULL) {
TASS Belgium NV 131:4758606c9316 814 pico_tcp_input(found, f);
TASS Belgium NV 131:4758606c9316 815 if ((found->ev_pending) && found->wakeup) {
TASS Belgium NV 131:4758606c9316 816 found->wakeup(found->ev_pending, found);
TASS Belgium NV 131:4758606c9316 817 if(!found->parent)
TASS Belgium NV 131:4758606c9316 818 found->ev_pending = 0;
TASS Belgium NV 131:4758606c9316 819 }
TASS Belgium NV 131:4758606c9316 820
TASS Belgium NV 131:4758606c9316 821 return 0;
TASS Belgium NV 131:4758606c9316 822 } else {
TASS Belgium NV 131:4758606c9316 823 dbg("SOCKET> mmm something wrong (prob sockport)\n");
TASS Belgium NV 131:4758606c9316 824 return -1;
tass 68:0847e35d08a6 825 }
TASS Belgium NV 131:4758606c9316 826 } /* TCP CASE */
TASS Belgium NV 131:4758606c9316 827
tass 68:0847e35d08a6 828 #endif
tass 68:0847e35d08a6 829
tass 68:0847e35d08a6 830 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 831 if (p->proto_number == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 832 pico_tree_foreach_safe(index, &sp->socks, _tmp){
TASS Belgium NV 131:4758606c9316 833 s = index->keyValue;
TASS Belgium NV 131:4758606c9316 834 if (IS_IPV4(f)) { /* IPV4 */
TASS Belgium NV 131:4758606c9316 835 struct pico_ip4 s_local, p_dst;
TASS Belgium NV 131:4758606c9316 836 ip4hdr = (struct pico_ipv4_hdr*)(f->net_hdr);
TASS Belgium NV 131:4758606c9316 837 s_local.addr = s->local_addr.ip4.addr;
TASS Belgium NV 131:4758606c9316 838 p_dst.addr = ip4hdr->dst.addr;
TASS Belgium NV 131:4758606c9316 839 if ((pico_ipv4_is_broadcast(p_dst.addr)) || pico_ipv4_is_multicast(p_dst.addr)) {
TASS Belgium NV 131:4758606c9316 840 struct pico_device *dev = pico_ipv4_link_find(&s->local_addr.ip4);
TASS Belgium NV 131:4758606c9316 841 if (pico_ipv4_is_multicast(p_dst.addr) && (pico_socket_mcast_filter(s, &ip4hdr->dst, &ip4hdr->src) < 0))
TASS Belgium NV 131:4758606c9316 842 return -1;
TASS Belgium NV 131:4758606c9316 843
TASS Belgium NV 131:4758606c9316 844 if ((s_local.addr == PICO_IPV4_INADDR_ANY) || /* If our local ip is ANY, or.. */
TASS Belgium NV 131:4758606c9316 845 (dev == f->dev)) { /* the source of the bcast packet is a neighbor... */
TASS Belgium NV 131:4758606c9316 846 cpy = pico_frame_copy(f);
TASS Belgium NV 131:4758606c9316 847 if (!cpy)
TASS Belgium NV 131:4758606c9316 848 return -1;
TASS Belgium NV 131:4758606c9316 849
TASS Belgium NV 131:4758606c9316 850 if (pico_enqueue(&s->q_in, cpy) > 0) {
TASS Belgium NV 131:4758606c9316 851 if (s->wakeup)
TASS Belgium NV 131:4758606c9316 852 s->wakeup(PICO_SOCK_EV_RD, s);
TASS Belgium NV 131:4758606c9316 853 }
TASS Belgium NV 131:4758606c9316 854 else
TASS Belgium NV 131:4758606c9316 855 pico_frame_discard(cpy);
tass 110:0ece1bbbd36e 856
TASS Belgium NV 131:4758606c9316 857 }
TASS Belgium NV 131:4758606c9316 858 } else if ((s_local.addr == PICO_IPV4_INADDR_ANY) || (s_local.addr == p_dst.addr))
TASS Belgium NV 131:4758606c9316 859 { /* Either local socket is ANY, or matches dst */
TASS Belgium NV 131:4758606c9316 860 cpy = pico_frame_copy(f);
TASS Belgium NV 131:4758606c9316 861 if (!cpy)
TASS Belgium NV 131:4758606c9316 862 return -1;
TASS Belgium NV 131:4758606c9316 863
TASS Belgium NV 131:4758606c9316 864 if (pico_enqueue(&s->q_in, cpy) > 0) {
TASS Belgium NV 131:4758606c9316 865 if (s->wakeup)
TASS Belgium NV 131:4758606c9316 866 s->wakeup(PICO_SOCK_EV_RD, s);
TASS Belgium NV 131:4758606c9316 867 }
TASS Belgium NV 131:4758606c9316 868 else
TASS Belgium NV 131:4758606c9316 869 pico_frame_discard(cpy);
TASS Belgium NV 131:4758606c9316 870 }
TASS Belgium NV 131:4758606c9316 871 } else {
TASS Belgium NV 131:4758606c9316 872 /*... IPv6 */
TASS Belgium NV 131:4758606c9316 873 }
TASS Belgium NV 131:4758606c9316 874 } /* FOREACH */
TASS Belgium NV 131:4758606c9316 875 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 876 if (s)
TASS Belgium NV 131:4758606c9316 877 return 0;
TASS Belgium NV 131:4758606c9316 878 else
tass 68:0847e35d08a6 879 return -1;
TASS Belgium NV 131:4758606c9316 880 }
TASS Belgium NV 131:4758606c9316 881
tass 68:0847e35d08a6 882 #endif
TASS Belgium NV 131:4758606c9316 883 return -1;
tass 68:0847e35d08a6 884 }
tass 68:0847e35d08a6 885
tass 68:0847e35d08a6 886 struct pico_socket *pico_socket_open(uint16_t net, uint16_t proto, void (*wakeup)(uint16_t ev, struct pico_socket *))
tass 68:0847e35d08a6 887 {
tass 68:0847e35d08a6 888
TASS Belgium NV 131:4758606c9316 889 struct pico_socket *s = NULL;
tass 68:0847e35d08a6 890
tass 68:0847e35d08a6 891 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 892 if (proto == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 893 s = pico_udp_open();
TASS Belgium NV 131:4758606c9316 894 s->proto = &pico_proto_udp;
TASS Belgium NV 131:4758606c9316 895 s->q_in.overhead = s->q_out.overhead = UDP_FRAME_OVERHEAD;
TASS Belgium NV 131:4758606c9316 896 }
TASS Belgium NV 131:4758606c9316 897
tass 68:0847e35d08a6 898 #endif
tass 68:0847e35d08a6 899
tass 68:0847e35d08a6 900 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 901 if (proto == PICO_PROTO_TCP) {
TASS Belgium NV 131:4758606c9316 902 s = pico_tcp_open();
TASS Belgium NV 131:4758606c9316 903 s->proto = &pico_proto_tcp;
TASS Belgium NV 131:4758606c9316 904 /*check if Nagle enabled */
TASS Belgium NV 131:4758606c9316 905 if (!IS_NAGLE_ENABLED(s))
TASS Belgium NV 131:4758606c9316 906 dbg("ERROR Nagle should be enabled here\n\n");
TASS Belgium NV 131:4758606c9316 907 }
TASS Belgium NV 131:4758606c9316 908
tass 68:0847e35d08a6 909 #endif
tass 68:0847e35d08a6 910
TASS Belgium NV 131:4758606c9316 911 if (!s) {
TASS Belgium NV 131:4758606c9316 912 pico_err = PICO_ERR_EPROTONOSUPPORT;
TASS Belgium NV 131:4758606c9316 913 return NULL;
TASS Belgium NV 131:4758606c9316 914 }
tass 68:0847e35d08a6 915
tass 68:0847e35d08a6 916 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 917 if (net == PICO_PROTO_IPV4)
TASS Belgium NV 131:4758606c9316 918 s->net = &pico_proto_ipv4;
TASS Belgium NV 131:4758606c9316 919
tass 68:0847e35d08a6 920 #endif
tass 68:0847e35d08a6 921
tass 68:0847e35d08a6 922 #ifdef PICO_SUPPORT_IPV6
TASS Belgium NV 131:4758606c9316 923 if (net == PICO_PROTO_IPV6)
TASS Belgium NV 131:4758606c9316 924 s->net = &pico_proto_ipv6;
TASS Belgium NV 131:4758606c9316 925
tass 68:0847e35d08a6 926 #endif
tass 68:0847e35d08a6 927
TASS Belgium NV 131:4758606c9316 928 s->q_in.max_size = PICO_DEFAULT_SOCKETQ;
TASS Belgium NV 131:4758606c9316 929 s->q_out.max_size = PICO_DEFAULT_SOCKETQ;
tass 110:0ece1bbbd36e 930
TASS Belgium NV 131:4758606c9316 931 s->wakeup = wakeup;
tass 68:0847e35d08a6 932
TASS Belgium NV 131:4758606c9316 933 if (!s->net) {
TASS Belgium NV 131:4758606c9316 934 pico_free(s);
TASS Belgium NV 131:4758606c9316 935 pico_err = PICO_ERR_ENETUNREACH;
TASS Belgium NV 131:4758606c9316 936 return NULL;
TASS Belgium NV 131:4758606c9316 937 }
TASS Belgium NV 131:4758606c9316 938
TASS Belgium NV 131:4758606c9316 939 return s;
tass 68:0847e35d08a6 940 }
tass 68:0847e35d08a6 941
tass 68:0847e35d08a6 942
tass 68:0847e35d08a6 943 struct pico_socket *pico_socket_clone(struct pico_socket *facsimile)
tass 68:0847e35d08a6 944 {
TASS Belgium NV 131:4758606c9316 945 struct pico_socket *s = NULL;
tass 68:0847e35d08a6 946
tass 68:0847e35d08a6 947 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 948 if (facsimile->proto->proto_number == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 949 s = pico_udp_open();
TASS Belgium NV 131:4758606c9316 950 s->proto = &pico_proto_udp;
TASS Belgium NV 131:4758606c9316 951 s->q_in.overhead = s->q_out.overhead = UDP_FRAME_OVERHEAD;
TASS Belgium NV 131:4758606c9316 952 }
TASS Belgium NV 131:4758606c9316 953
tass 68:0847e35d08a6 954 #endif
tass 68:0847e35d08a6 955
tass 68:0847e35d08a6 956 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 957 if (facsimile->proto->proto_number == PICO_PROTO_TCP) {
TASS Belgium NV 131:4758606c9316 958 s = pico_tcp_open();
TASS Belgium NV 131:4758606c9316 959 s->proto = &pico_proto_tcp;
TASS Belgium NV 131:4758606c9316 960 }
TASS Belgium NV 131:4758606c9316 961
tass 68:0847e35d08a6 962 #endif
tass 68:0847e35d08a6 963
TASS Belgium NV 131:4758606c9316 964 if (!s) {
TASS Belgium NV 131:4758606c9316 965 pico_err = PICO_ERR_EPROTONOSUPPORT;
TASS Belgium NV 131:4758606c9316 966 return NULL;
TASS Belgium NV 131:4758606c9316 967 }
TASS Belgium NV 131:4758606c9316 968
TASS Belgium NV 131:4758606c9316 969 s->local_port = facsimile->local_port;
TASS Belgium NV 131:4758606c9316 970 s->remote_port = facsimile->remote_port;
TASS Belgium NV 131:4758606c9316 971 s->state = facsimile->state;
tass 68:0847e35d08a6 972
tass 68:0847e35d08a6 973 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 974 if (facsimile->net == &pico_proto_ipv4) {
TASS Belgium NV 131:4758606c9316 975 s->net = &pico_proto_ipv4;
TASS Belgium NV 131:4758606c9316 976 memcpy(&s->local_addr, &facsimile->local_addr, sizeof(struct pico_ip4));
TASS Belgium NV 131:4758606c9316 977 memcpy(&s->remote_addr, &facsimile->remote_addr, sizeof(struct pico_ip4));
TASS Belgium NV 131:4758606c9316 978 }
TASS Belgium NV 131:4758606c9316 979
tass 68:0847e35d08a6 980 #endif
tass 68:0847e35d08a6 981
tass 68:0847e35d08a6 982 #ifdef PICO_SUPPORT_IPV6
TASS Belgium NV 131:4758606c9316 983 if (net == &pico_proto_ipv6) {
TASS Belgium NV 131:4758606c9316 984 s->net = &pico_proto_ipv6;
TASS Belgium NV 131:4758606c9316 985 memcpy(&s->local_addr, &facsimile->local_addr, sizeof(struct pico_ip6));
TASS Belgium NV 131:4758606c9316 986 memcpy(&s->remote_addr, &facsimile->remote_addr, sizeof(struct pico_ip6));
TASS Belgium NV 131:4758606c9316 987 }
TASS Belgium NV 131:4758606c9316 988
tass 68:0847e35d08a6 989 #endif
TASS Belgium NV 131:4758606c9316 990 s->q_in.max_size = PICO_DEFAULT_SOCKETQ;
TASS Belgium NV 131:4758606c9316 991 s->q_out.max_size = PICO_DEFAULT_SOCKETQ;
TASS Belgium NV 131:4758606c9316 992 s->wakeup = NULL;
TASS Belgium NV 131:4758606c9316 993 if (!s->net) {
TASS Belgium NV 131:4758606c9316 994 pico_free(s);
TASS Belgium NV 131:4758606c9316 995 pico_err = PICO_ERR_ENETUNREACH;
TASS Belgium NV 131:4758606c9316 996 return NULL;
TASS Belgium NV 131:4758606c9316 997 }
TASS Belgium NV 131:4758606c9316 998
TASS Belgium NV 131:4758606c9316 999 return s;
tass 68:0847e35d08a6 1000 }
tass 68:0847e35d08a6 1001
tass 68:0847e35d08a6 1002 int pico_socket_read(struct pico_socket *s, void *buf, int len)
tass 68:0847e35d08a6 1003 {
TASS Belgium NV 131:4758606c9316 1004 if (!s || buf == NULL) {
TASS Belgium NV 131:4758606c9316 1005 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1006 return -1;
TASS Belgium NV 131:4758606c9316 1007 } else {
TASS Belgium NV 131:4758606c9316 1008 /* check if exists in tree */
TASS Belgium NV 131:4758606c9316 1009 /* See task #178 */
TASS Belgium NV 131:4758606c9316 1010 if (pico_check_socket(s) != 0) {
TASS Belgium NV 131:4758606c9316 1011 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1012 return -1;
TASS Belgium NV 131:4758606c9316 1013 }
tass 68:0847e35d08a6 1014 }
tass 68:0847e35d08a6 1015
TASS Belgium NV 131:4758606c9316 1016 if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) {
TASS Belgium NV 131:4758606c9316 1017 pico_err = PICO_ERR_EIO;
TASS Belgium NV 131:4758606c9316 1018 return -1;
TASS Belgium NV 131:4758606c9316 1019 }
TASS Belgium NV 131:4758606c9316 1020
TASS Belgium NV 131:4758606c9316 1021 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 1022 if (PROTO(s) == PICO_PROTO_UDP)
TASS Belgium NV 131:4758606c9316 1023 return pico_udp_recv(s, buf, (uint16_t)len, NULL, NULL);
TASS Belgium NV 131:4758606c9316 1024
tass 68:0847e35d08a6 1025 #endif
tass 68:0847e35d08a6 1026
tass 68:0847e35d08a6 1027 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 1028 if (PROTO(s) == PICO_PROTO_TCP) {
TASS Belgium NV 131:4758606c9316 1029 /* check if in shutdown state and if no more data in tcpq_in */
TASS Belgium NV 131:4758606c9316 1030 if ((s->state & PICO_SOCKET_STATE_SHUT_REMOTE) && pico_tcp_queue_in_is_empty(s)) {
TASS Belgium NV 131:4758606c9316 1031 pico_err = PICO_ERR_ESHUTDOWN;
TASS Belgium NV 131:4758606c9316 1032 return -1;
TASS Belgium NV 131:4758606c9316 1033 } else {
TASS Belgium NV 131:4758606c9316 1034 return (int)pico_tcp_read(s, buf, (uint32_t)len);
TASS Belgium NV 131:4758606c9316 1035 }
tass 68:0847e35d08a6 1036 }
TASS Belgium NV 131:4758606c9316 1037
tass 68:0847e35d08a6 1038 #endif
TASS Belgium NV 131:4758606c9316 1039 return 0;
tass 68:0847e35d08a6 1040 }
tass 68:0847e35d08a6 1041
tass 68:0847e35d08a6 1042 int pico_socket_write(struct pico_socket *s, const void *buf, int len)
tass 68:0847e35d08a6 1043 {
TASS Belgium NV 131:4758606c9316 1044 if (!s || buf == NULL) {
TASS Belgium NV 131:4758606c9316 1045 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1046 return -1;
TASS Belgium NV 131:4758606c9316 1047 } else {
TASS Belgium NV 131:4758606c9316 1048 /* check if exists in tree */
TASS Belgium NV 131:4758606c9316 1049 /* See task #178 */
TASS Belgium NV 131:4758606c9316 1050 if (pico_check_socket(s) != 0) {
TASS Belgium NV 131:4758606c9316 1051 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1052 return -1;
TASS Belgium NV 131:4758606c9316 1053 }
tass 68:0847e35d08a6 1054 }
tass 68:0847e35d08a6 1055
TASS Belgium NV 131:4758606c9316 1056 if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) {
TASS Belgium NV 131:4758606c9316 1057 pico_err = PICO_ERR_EIO;
TASS Belgium NV 131:4758606c9316 1058 return -1;
TASS Belgium NV 131:4758606c9316 1059 }
TASS Belgium NV 131:4758606c9316 1060
TASS Belgium NV 131:4758606c9316 1061 if ((s->state & PICO_SOCKET_STATE_CONNECTED) == 0) {
TASS Belgium NV 131:4758606c9316 1062 pico_err = PICO_ERR_ENOTCONN;
TASS Belgium NV 131:4758606c9316 1063 return -1;
TASS Belgium NV 131:4758606c9316 1064 } else if (s->state & PICO_SOCKET_STATE_SHUT_LOCAL) { /* check if in shutdown state */
TASS Belgium NV 131:4758606c9316 1065 pico_err = PICO_ERR_ESHUTDOWN;
TASS Belgium NV 131:4758606c9316 1066 return -1;
TASS Belgium NV 131:4758606c9316 1067 } else {
TASS Belgium NV 131:4758606c9316 1068 return pico_socket_sendto(s, buf, len, &s->remote_addr, s->remote_port);
TASS Belgium NV 131:4758606c9316 1069 }
tass 68:0847e35d08a6 1070 }
tass 68:0847e35d08a6 1071
tass 68:0847e35d08a6 1072 uint16_t pico_socket_high_port(uint16_t proto)
tass 68:0847e35d08a6 1073 {
TASS Belgium NV 131:4758606c9316 1074 uint16_t port;
TASS Belgium NV 131:4758606c9316 1075 if (0 ||
tass 68:0847e35d08a6 1076 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 1077 (proto == PICO_PROTO_TCP) ||
tass 68:0847e35d08a6 1078 #endif
tass 68:0847e35d08a6 1079 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 1080 (proto == PICO_PROTO_UDP) ||
tass 68:0847e35d08a6 1081 #endif
TASS Belgium NV 131:4758606c9316 1082 0) {
TASS Belgium NV 131:4758606c9316 1083 do {
TASS Belgium NV 131:4758606c9316 1084 uint32_t rand = pico_rand();
TASS Belgium NV 131:4758606c9316 1085 port = (uint16_t) (rand & 0xFFFFU);
TASS Belgium NV 131:4758606c9316 1086 port = (uint16_t)((port % (65535 - 1024)) + 1024U);
TASS Belgium NV 131:4758606c9316 1087 if (pico_is_port_free(proto, port, NULL, NULL)) {
TASS Belgium NV 131:4758606c9316 1088 return short_be(port);
TASS Belgium NV 131:4758606c9316 1089 }
TASS Belgium NV 131:4758606c9316 1090 } while(1);
TASS Belgium NV 131:4758606c9316 1091 }
TASS Belgium NV 131:4758606c9316 1092 else return 0U;
tass 68:0847e35d08a6 1093 }
tass 68:0847e35d08a6 1094
tass 68:0847e35d08a6 1095
tass 68:0847e35d08a6 1096 int pico_socket_sendto(struct pico_socket *s, const void *buf, const int len, void *dst, uint16_t remote_port)
tass 68:0847e35d08a6 1097 {
TASS Belgium NV 131:4758606c9316 1098 struct pico_frame *f;
TASS Belgium NV 131:4758606c9316 1099 struct pico_remote_duple *remote_duple = NULL;
TASS Belgium NV 131:4758606c9316 1100 int socket_mtu = PICO_SOCKET4_MTU;
TASS Belgium NV 131:4758606c9316 1101 int header_offset = 0;
TASS Belgium NV 131:4758606c9316 1102 int total_payload_written = 0;
tass 68:0847e35d08a6 1103 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 1104 struct pico_ip4 *src4;
tass 68:0847e35d08a6 1105 #endif
tass 68:0847e35d08a6 1106
tass 68:0847e35d08a6 1107 #ifdef PICO_SUPPORT_IPV6
TASS Belgium NV 131:4758606c9316 1108 struct pico_ip6 *src6;
tass 68:0847e35d08a6 1109 #endif
TASS Belgium NV 131:4758606c9316 1110 if (len == 0) {
TASS Belgium NV 131:4758606c9316 1111 return 0;
TASS Belgium NV 131:4758606c9316 1112 } else if (len < 0) {
TASS Belgium NV 131:4758606c9316 1113 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1114 return -1;
TASS Belgium NV 131:4758606c9316 1115 }
tass 68:0847e35d08a6 1116
TASS Belgium NV 131:4758606c9316 1117 if (buf == NULL || s == NULL) {
TASS Belgium NV 131:4758606c9316 1118 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1119 return -1;
TASS Belgium NV 131:4758606c9316 1120 }
tass 68:0847e35d08a6 1121
TASS Belgium NV 131:4758606c9316 1122 if (!dst || !remote_port) {
TASS Belgium NV 131:4758606c9316 1123 pico_err = PICO_ERR_EADDRNOTAVAIL;
TASS Belgium NV 131:4758606c9316 1124 return -1;
TASS Belgium NV 131:4758606c9316 1125 }
tass 68:0847e35d08a6 1126
TASS Belgium NV 131:4758606c9316 1127 if ((s->state & PICO_SOCKET_STATE_CONNECTED) != 0) {
TASS Belgium NV 131:4758606c9316 1128 if (remote_port != s->remote_port) {
TASS Belgium NV 131:4758606c9316 1129 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1130 return -1;
TASS Belgium NV 131:4758606c9316 1131 }
tass 68:0847e35d08a6 1132 }
tass 68:0847e35d08a6 1133
tass 68:0847e35d08a6 1134 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 1135 if (IS_SOCK_IPV4(s)) {
TASS Belgium NV 131:4758606c9316 1136 socket_mtu = PICO_SOCKET4_MTU;
TASS Belgium NV 131:4758606c9316 1137 if ((s->state & PICO_SOCKET_STATE_CONNECTED)) {
TASS Belgium NV 131:4758606c9316 1138 if (s->remote_addr.ip4.addr != ((struct pico_ip4 *)dst)->addr ) {
TASS Belgium NV 131:4758606c9316 1139 pico_err = PICO_ERR_EADDRNOTAVAIL;
TASS Belgium NV 131:4758606c9316 1140 return -1;
TASS Belgium NV 131:4758606c9316 1141 }
TASS Belgium NV 131:4758606c9316 1142 } else {
TASS Belgium NV 131:4758606c9316 1143 src4 = pico_ipv4_source_find(dst);
TASS Belgium NV 131:4758606c9316 1144 if (!src4) {
TASS Belgium NV 131:4758606c9316 1145 pico_err = PICO_ERR_EHOSTUNREACH;
TASS Belgium NV 131:4758606c9316 1146 return -1;
TASS Belgium NV 131:4758606c9316 1147 }
TASS Belgium NV 131:4758606c9316 1148
TASS Belgium NV 131:4758606c9316 1149 if (src4->addr != PICO_IPV4_INADDR_ANY)
TASS Belgium NV 131:4758606c9316 1150 s->local_addr.ip4.addr = src4->addr;
TASS Belgium NV 131:4758606c9316 1151
tass 68:0847e35d08a6 1152 # ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 1153 /* socket remote info could change in a consecutive call, make persistent */
TASS Belgium NV 131:4758606c9316 1154 if (PROTO(s) == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1155 remote_duple = pico_zalloc(sizeof(struct pico_remote_duple));
TASS Belgium NV 131:4758606c9316 1156 remote_duple->remote_addr.ip4.addr = ((struct pico_ip4 *)dst)->addr;
TASS Belgium NV 131:4758606c9316 1157 remote_duple->remote_port = remote_port;
TASS Belgium NV 131:4758606c9316 1158 }
TASS Belgium NV 131:4758606c9316 1159
tass 68:0847e35d08a6 1160 # endif
TASS Belgium NV 131:4758606c9316 1161 }
TASS Belgium NV 131:4758606c9316 1162
tass 68:0847e35d08a6 1163 #endif
TASS Belgium NV 131:4758606c9316 1164 }
TASS Belgium NV 131:4758606c9316 1165 else if (IS_SOCK_IPV6(s)) {
tass 68:0847e35d08a6 1166 socket_mtu = PICO_SOCKET6_MTU;
tass 68:0847e35d08a6 1167 #ifdef PICO_SUPPORT_IPV6
tass 68:0847e35d08a6 1168 if (s->state & PICO_SOCKET_STATE_CONNECTED) {
TASS Belgium NV 131:4758606c9316 1169 if (memcmp(&s->remote_addr, dst, PICO_SIZE_IP6))
TASS Belgium NV 131:4758606c9316 1170 return -1;
tass 68:0847e35d08a6 1171 } else {
TASS Belgium NV 131:4758606c9316 1172 src6 = pico_ipv6_source_find(dst);
TASS Belgium NV 131:4758606c9316 1173 if (!src6) {
TASS Belgium NV 131:4758606c9316 1174 pico_err = PICO_ERR_EHOSTUNREACH;
TASS Belgium NV 131:4758606c9316 1175 return -1;
TASS Belgium NV 131:4758606c9316 1176 }
TASS Belgium NV 131:4758606c9316 1177
TASS Belgium NV 131:4758606c9316 1178 memcpy(&s->local_addr, src6, PICO_SIZE_IP6);
TASS Belgium NV 131:4758606c9316 1179 memcpy(&s->remote_addr, dst, PICO_SIZE_IP6);
tass 68:0847e35d08a6 1180 # ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 1181 if (PROTO(s) == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1182 remote_duple = pico_zalloc(sizeof(struct pico_remote_duple));
TASS Belgium NV 131:4758606c9316 1183 remote_duple->remote_addr.ip6.addr = ((struct pico_ip6 *)dst)->addr;
TASS Belgium NV 131:4758606c9316 1184 remote_duple->remote_port = remote_port;
TASS Belgium NV 131:4758606c9316 1185 }
TASS Belgium NV 131:4758606c9316 1186
tass 68:0847e35d08a6 1187 # endif
tass 68:0847e35d08a6 1188 }
TASS Belgium NV 131:4758606c9316 1189
tass 68:0847e35d08a6 1190 #endif
TASS Belgium NV 131:4758606c9316 1191 }
tass 68:0847e35d08a6 1192
TASS Belgium NV 131:4758606c9316 1193 if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) {
tass 68:0847e35d08a6 1194 s->local_port = pico_socket_high_port(s->proto->proto_number);
tass 68:0847e35d08a6 1195 if (s->local_port == 0) {
TASS Belgium NV 131:4758606c9316 1196 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1197 return -1;
tass 68:0847e35d08a6 1198 }
TASS Belgium NV 131:4758606c9316 1199 }
TASS Belgium NV 131:4758606c9316 1200
TASS Belgium NV 131:4758606c9316 1201 if ((s->state & PICO_SOCKET_STATE_CONNECTED) == 0) {
tass 68:0847e35d08a6 1202 s->remote_port = remote_port;
TASS Belgium NV 131:4758606c9316 1203 }
tass 68:0847e35d08a6 1204
tass 68:0847e35d08a6 1205 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 1206 if (PROTO(s) == PICO_PROTO_TCP)
tass 68:0847e35d08a6 1207 header_offset = pico_tcp_overhead(s);
TASS Belgium NV 131:4758606c9316 1208
tass 68:0847e35d08a6 1209 #endif
tass 68:0847e35d08a6 1210
tass 68:0847e35d08a6 1211 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 1212 if (PROTO(s) == PICO_PROTO_UDP)
tass 68:0847e35d08a6 1213 header_offset = sizeof(struct pico_udp_hdr);
TASS Belgium NV 131:4758606c9316 1214
tass 68:0847e35d08a6 1215 #endif
tass 68:0847e35d08a6 1216
TASS Belgium NV 131:4758606c9316 1217 while (total_payload_written < len) {
TASS Belgium NV 131:4758606c9316 1218 int transport_len = (len - total_payload_written) + header_offset;
tass 68:0847e35d08a6 1219 if (transport_len > socket_mtu)
TASS Belgium NV 131:4758606c9316 1220 transport_len = socket_mtu;
TASS Belgium NV 131:4758606c9316 1221
tass 68:0847e35d08a6 1222 #ifdef PICO_SUPPORT_IPFRAG
tass 68:0847e35d08a6 1223 else {
TASS Belgium NV 131:4758606c9316 1224 if (total_payload_written)
TASS Belgium NV 131:4758606c9316 1225 transport_len -= header_offset; /* last fragment, do not allocate memory for transport header */
TASS Belgium NV 131:4758606c9316 1226
tass 68:0847e35d08a6 1227 }
tass 68:0847e35d08a6 1228 #endif /* PICO_SUPPORT_IPFRAG */
tass 68:0847e35d08a6 1229
tass 70:cd218dd180e5 1230 f = pico_socket_frame_alloc(s, (uint16_t)transport_len);
tass 68:0847e35d08a6 1231 if (!f) {
TASS Belgium NV 131:4758606c9316 1232 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 1233 return -1;
tass 68:0847e35d08a6 1234 }
TASS Belgium NV 131:4758606c9316 1235
tass 68:0847e35d08a6 1236 f->payload += header_offset;
tass 73:dfb737147f6e 1237 f->payload_len = (uint16_t)(f->payload_len - header_offset);
tass 68:0847e35d08a6 1238 f->sock = s;
TASS Belgium NV 131:4758606c9316 1239 transport_flags_update(f, s);
tass 68:0847e35d08a6 1240 if (remote_duple) {
TASS Belgium NV 131:4758606c9316 1241 f->info = pico_zalloc(sizeof(struct pico_remote_duple));
TASS Belgium NV 131:4758606c9316 1242 memcpy(f->info, remote_duple, sizeof(struct pico_remote_duple));
tass 68:0847e35d08a6 1243 }
tass 68:0847e35d08a6 1244
tass 68:0847e35d08a6 1245 #ifdef PICO_SUPPORT_IPFRAG
tass 68:0847e35d08a6 1246 #ifdef PICO_SUPPORT_UDP
tass 68:0847e35d08a6 1247 if (PROTO(s) == PICO_PROTO_UDP && ((len + header_offset) > socket_mtu)) {
TASS Belgium NV 131:4758606c9316 1248 /* hacking way to identify fragmentation frames: payload != transport_hdr -> first frame */
TASS Belgium NV 131:4758606c9316 1249 if (!total_payload_written) {
TASS Belgium NV 131:4758606c9316 1250 frag_dbg("FRAG: first fragmented frame %p | len = %u offset = 0\n", f, f->payload_len);
TASS Belgium NV 131:4758606c9316 1251 /* transport header length field contains total length + header length */
TASS Belgium NV 131:4758606c9316 1252 f->transport_len = (uint16_t)(len + header_offset);
TASS Belgium NV 131:4758606c9316 1253 f->frag = short_be(PICO_IPV4_MOREFRAG);
tass 68:0847e35d08a6 1254 } else {
TASS Belgium NV 131:4758606c9316 1255 /* no transport header in fragmented IP */
TASS Belgium NV 131:4758606c9316 1256 f->payload = f->transport_hdr;
TASS Belgium NV 131:4758606c9316 1257 f->payload_len = (uint16_t)(f->payload_len + header_offset);
TASS Belgium NV 131:4758606c9316 1258 /* set offset in octets */
TASS Belgium NV 131:4758606c9316 1259 f->frag = short_be((uint16_t)((total_payload_written + header_offset) / 8));
TASS Belgium NV 131:4758606c9316 1260 if (total_payload_written + f->payload_len < len) {
TASS Belgium NV 131:4758606c9316 1261 frag_dbg("FRAG: intermediate fragmented frame %p | len = %u offset = %u\n", f, f->payload_len, short_be(f->frag));
TASS Belgium NV 131:4758606c9316 1262 f->frag |= short_be(PICO_IPV4_MOREFRAG);
TASS Belgium NV 131:4758606c9316 1263 } else {
TASS Belgium NV 131:4758606c9316 1264 frag_dbg("FRAG: last fragmented frame %p | len = %u offset = %u\n", f, f->payload_len, short_be(f->frag));
TASS Belgium NV 131:4758606c9316 1265 f->frag &= short_be(PICO_IPV4_FRAG_MASK);
TASS Belgium NV 131:4758606c9316 1266 }
tass 68:0847e35d08a6 1267 }
tass 68:0847e35d08a6 1268 } else {
TASS Belgium NV 131:4758606c9316 1269 f->frag = short_be(PICO_IPV4_DONTFRAG);
tass 68:0847e35d08a6 1270 }
TASS Belgium NV 131:4758606c9316 1271
tass 68:0847e35d08a6 1272 # endif /* PICO_SUPPORT_UDP */
tass 68:0847e35d08a6 1273 #endif /* PICO_SUPPORT_IPFRAG */
tass 68:0847e35d08a6 1274
tass 68:0847e35d08a6 1275 if (f->payload_len <= 0) {
TASS Belgium NV 131:4758606c9316 1276 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 1277 if (remote_duple)
TASS Belgium NV 131:4758606c9316 1278 pico_free(remote_duple);
TASS Belgium NV 131:4758606c9316 1279
TASS Belgium NV 131:4758606c9316 1280 return total_payload_written;
tass 68:0847e35d08a6 1281 }
tass 68:0847e35d08a6 1282
tass 68:0847e35d08a6 1283 memcpy(f->payload, buf + total_payload_written, f->payload_len);
TASS Belgium NV 131:4758606c9316 1284 /* dbg("Pushing segment, hdr len: %d, payload_len: %d\n", header_offset, f->payload_len); */
tass 68:0847e35d08a6 1285
tass 68:0847e35d08a6 1286 if (s->proto->push(s->proto, f) > 0) {
TASS Belgium NV 131:4758606c9316 1287 total_payload_written += (int)f->payload_len;
tass 68:0847e35d08a6 1288 } else {
TASS Belgium NV 131:4758606c9316 1289 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 1290 pico_err = PICO_ERR_EAGAIN;
TASS Belgium NV 131:4758606c9316 1291 break;
tass 68:0847e35d08a6 1292 }
TASS Belgium NV 131:4758606c9316 1293 }
TASS Belgium NV 131:4758606c9316 1294 if (remote_duple)
tass 68:0847e35d08a6 1295 pico_free(remote_duple);
TASS Belgium NV 131:4758606c9316 1296
TASS Belgium NV 131:4758606c9316 1297 return total_payload_written;
tass 68:0847e35d08a6 1298 }
tass 68:0847e35d08a6 1299
tass 68:0847e35d08a6 1300 int pico_socket_send(struct pico_socket *s, const void *buf, int len)
tass 68:0847e35d08a6 1301 {
TASS Belgium NV 131:4758606c9316 1302 if (!s || buf == NULL) {
TASS Belgium NV 131:4758606c9316 1303 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1304 return -1;
TASS Belgium NV 131:4758606c9316 1305 } else {
TASS Belgium NV 131:4758606c9316 1306 /* check if exists in tree */
TASS Belgium NV 131:4758606c9316 1307 /* See task #178 */
TASS Belgium NV 131:4758606c9316 1308 if (pico_check_socket(s) != 0) {
TASS Belgium NV 131:4758606c9316 1309 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1310 return -1;
TASS Belgium NV 131:4758606c9316 1311 }
tass 68:0847e35d08a6 1312 }
tass 68:0847e35d08a6 1313
TASS Belgium NV 131:4758606c9316 1314 if ((s->state & PICO_SOCKET_STATE_CONNECTED) == 0) {
TASS Belgium NV 131:4758606c9316 1315 pico_err = PICO_ERR_ENOTCONN;
TASS Belgium NV 131:4758606c9316 1316 return -1;
TASS Belgium NV 131:4758606c9316 1317 }
TASS Belgium NV 131:4758606c9316 1318
TASS Belgium NV 131:4758606c9316 1319 return pico_socket_sendto(s, buf, len, &s->remote_addr, s->remote_port);
tass 68:0847e35d08a6 1320 }
tass 68:0847e35d08a6 1321
tass 68:0847e35d08a6 1322 int pico_socket_recvfrom(struct pico_socket *s, void *buf, int len, void *orig, uint16_t *remote_port)
tass 68:0847e35d08a6 1323 {
TASS Belgium NV 131:4758606c9316 1324 if (!s || buf == NULL) { /* / || orig == NULL || remote_port == NULL) { */
TASS Belgium NV 131:4758606c9316 1325 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1326 return -1;
TASS Belgium NV 131:4758606c9316 1327 } else {
TASS Belgium NV 131:4758606c9316 1328 /* check if exists in tree */
TASS Belgium NV 131:4758606c9316 1329 if (pico_check_socket(s) != 0) {
TASS Belgium NV 131:4758606c9316 1330 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1331 /* See task #178 */
TASS Belgium NV 131:4758606c9316 1332 return -1;
TASS Belgium NV 131:4758606c9316 1333 }
tass 68:0847e35d08a6 1334 }
TASS Belgium NV 131:4758606c9316 1335
TASS Belgium NV 131:4758606c9316 1336 if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) {
TASS Belgium NV 131:4758606c9316 1337 pico_err = PICO_ERR_EADDRNOTAVAIL;
TASS Belgium NV 131:4758606c9316 1338 return -1;
TASS Belgium NV 131:4758606c9316 1339 }
tass 68:0847e35d08a6 1340
TASS Belgium NV 131:4758606c9316 1341 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 1342 if (PROTO(s) == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1343 return pico_udp_recv(s, buf, (uint16_t)len, orig, remote_port);
TASS Belgium NV 131:4758606c9316 1344 }
TASS Belgium NV 131:4758606c9316 1345
tass 68:0847e35d08a6 1346 #endif
tass 68:0847e35d08a6 1347 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 1348 if (PROTO(s) == PICO_PROTO_TCP) {
TASS Belgium NV 131:4758606c9316 1349 /* check if in shutdown state and if tcpq_in empty */
TASS Belgium NV 131:4758606c9316 1350 if ((s->state & PICO_SOCKET_STATE_SHUT_REMOTE) && pico_tcp_queue_in_is_empty(s)) {
TASS Belgium NV 131:4758606c9316 1351 pico_err = PICO_ERR_ESHUTDOWN;
TASS Belgium NV 131:4758606c9316 1352 return -1;
TASS Belgium NV 131:4758606c9316 1353 } else {
TASS Belgium NV 131:4758606c9316 1354 /* dbg("socket tcp recv\n"); */
TASS Belgium NV 131:4758606c9316 1355 return (int)pico_tcp_read(s, buf, (uint32_t)len);
TASS Belgium NV 131:4758606c9316 1356 }
tass 68:0847e35d08a6 1357 }
TASS Belgium NV 131:4758606c9316 1358
tass 68:0847e35d08a6 1359 #endif
TASS Belgium NV 131:4758606c9316 1360 /* dbg("socket return 0\n"); */
TASS Belgium NV 131:4758606c9316 1361 return 0;
tass 68:0847e35d08a6 1362 }
tass 68:0847e35d08a6 1363
tass 68:0847e35d08a6 1364 int pico_socket_recv(struct pico_socket *s, void *buf, int len)
tass 68:0847e35d08a6 1365 {
TASS Belgium NV 131:4758606c9316 1366 return pico_socket_recvfrom(s, buf, len, NULL, NULL);
tass 68:0847e35d08a6 1367 }
tass 68:0847e35d08a6 1368
tass 68:0847e35d08a6 1369
tass 68:0847e35d08a6 1370 int pico_socket_bind(struct pico_socket *s, void *local_addr, uint16_t *port)
tass 68:0847e35d08a6 1371 {
TASS Belgium NV 131:4758606c9316 1372 if (!s || !local_addr || !port) {
tass 68:0847e35d08a6 1373 pico_err = PICO_ERR_EINVAL;
tass 68:0847e35d08a6 1374 return -1;
tass 68:0847e35d08a6 1375 }
TASS Belgium NV 131:4758606c9316 1376
TASS Belgium NV 131:4758606c9316 1377 if (!is_sock_ipv6(s)) {
TASS Belgium NV 131:4758606c9316 1378 struct pico_ip4 *ip = (struct pico_ip4 *)local_addr;
TASS Belgium NV 131:4758606c9316 1379 if (ip->addr != PICO_IPV4_INADDR_ANY) {
TASS Belgium NV 131:4758606c9316 1380 if (!pico_ipv4_link_find(local_addr)) {
TASS Belgium NV 131:4758606c9316 1381 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1382 return -1;
TASS Belgium NV 131:4758606c9316 1383 }
TASS Belgium NV 131:4758606c9316 1384 }
TASS Belgium NV 131:4758606c9316 1385 } else {
TASS Belgium NV 131:4758606c9316 1386 /*... IPv6 */
TASS Belgium NV 131:4758606c9316 1387 }
tass 68:0847e35d08a6 1388
tass 68:0847e35d08a6 1389
TASS Belgium NV 131:4758606c9316 1390 /* When given port = 0, get a random high port to bind to. */
tass 68:0847e35d08a6 1391 if (*port == 0) {
TASS Belgium NV 131:4758606c9316 1392 *port = pico_socket_high_port(PROTO(s));
TASS Belgium NV 131:4758606c9316 1393 if (*port == 0) {
TASS Belgium NV 131:4758606c9316 1394 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1395 return -1;
TASS Belgium NV 131:4758606c9316 1396 }
tass 68:0847e35d08a6 1397 }
tass 68:0847e35d08a6 1398
TASS Belgium NV 131:4758606c9316 1399 if (pico_is_port_free(PROTO(s), *port, local_addr, s->net) == 0) {
TASS Belgium NV 131:4758606c9316 1400 pico_err = PICO_ERR_EADDRINUSE;
TASS Belgium NV 131:4758606c9316 1401 return -1;
TASS Belgium NV 131:4758606c9316 1402 }
TASS Belgium NV 131:4758606c9316 1403
TASS Belgium NV 131:4758606c9316 1404 s->local_port = *port;
tass 68:0847e35d08a6 1405
TASS Belgium NV 131:4758606c9316 1406 if (is_sock_ipv6(s)) {
TASS Belgium NV 131:4758606c9316 1407 struct pico_ip6 *ip = (struct pico_ip6 *) local_addr;
TASS Belgium NV 131:4758606c9316 1408 memcpy(s->local_addr.ip6.addr, ip, PICO_SIZE_IP6);
TASS Belgium NV 131:4758606c9316 1409 /* XXX: port ipv4 functionality to ipv6 */
TASS Belgium NV 131:4758606c9316 1410 /* Check for port already in use */
TASS Belgium NV 131:4758606c9316 1411 if (pico_is_port_free(PROTO(s), *port, &local_addr, s->net)) {
TASS Belgium NV 131:4758606c9316 1412 pico_err = PICO_ERR_EADDRINUSE;
TASS Belgium NV 131:4758606c9316 1413 return -1;
TASS Belgium NV 131:4758606c9316 1414 }
TASS Belgium NV 131:4758606c9316 1415 } else if (is_sock_ipv4(s)) {
TASS Belgium NV 131:4758606c9316 1416 struct pico_ip4 *ip = (struct pico_ip4 *) local_addr;
TASS Belgium NV 131:4758606c9316 1417 s->local_addr.ip4.addr = ip->addr;
tass 68:0847e35d08a6 1418 }
TASS Belgium NV 131:4758606c9316 1419
TASS Belgium NV 131:4758606c9316 1420 return pico_socket_alter_state(s, PICO_SOCKET_STATE_BOUND, 0, 0);
tass 68:0847e35d08a6 1421 }
tass 68:0847e35d08a6 1422
tass 68:0847e35d08a6 1423 int pico_socket_connect(struct pico_socket *s, const void *remote_addr, uint16_t remote_port)
tass 68:0847e35d08a6 1424 {
TASS Belgium NV 131:4758606c9316 1425 int ret = -1;
TASS Belgium NV 131:4758606c9316 1426 pico_err = PICO_ERR_EPROTONOSUPPORT;
TASS Belgium NV 131:4758606c9316 1427 if (!s || remote_addr == NULL || remote_port == 0) {
TASS Belgium NV 131:4758606c9316 1428 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1429 return -1;
TASS Belgium NV 131:4758606c9316 1430 }
tass 68:0847e35d08a6 1431
TASS Belgium NV 131:4758606c9316 1432 s->remote_port = remote_port;
tass 68:0847e35d08a6 1433
TASS Belgium NV 131:4758606c9316 1434 if (s->local_port == 0) {
TASS Belgium NV 131:4758606c9316 1435 s->local_port = pico_socket_high_port(PROTO(s));
TASS Belgium NV 131:4758606c9316 1436 if (!s->local_port) {
TASS Belgium NV 131:4758606c9316 1437 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1438 return -1;
TASS Belgium NV 131:4758606c9316 1439 }
tass 68:0847e35d08a6 1440 }
tass 68:0847e35d08a6 1441
TASS Belgium NV 131:4758606c9316 1442 if (is_sock_ipv6(s)) {
TASS Belgium NV 131:4758606c9316 1443 const struct pico_ip6 *ip = (const struct pico_ip6 *) remote_addr;
TASS Belgium NV 131:4758606c9316 1444 memcpy(s->remote_addr.ip6.addr, ip, PICO_SIZE_IP6);
TASS Belgium NV 131:4758606c9316 1445 } else if (is_sock_ipv4(s)) {
TASS Belgium NV 131:4758606c9316 1446 const struct pico_ip4 *local, *ip = (const struct pico_ip4 *) remote_addr;
TASS Belgium NV 131:4758606c9316 1447 s->remote_addr.ip4.addr = ip->addr;
TASS Belgium NV 131:4758606c9316 1448 local = pico_ipv4_source_find(ip);
TASS Belgium NV 131:4758606c9316 1449 if (local) {
TASS Belgium NV 131:4758606c9316 1450 s->local_addr.ip4.addr = local->addr;
TASS Belgium NV 131:4758606c9316 1451 } else {
TASS Belgium NV 131:4758606c9316 1452 pico_err = PICO_ERR_EHOSTUNREACH;
TASS Belgium NV 131:4758606c9316 1453 return -1;
TASS Belgium NV 131:4758606c9316 1454 }
tass 68:0847e35d08a6 1455 }
tass 68:0847e35d08a6 1456
TASS Belgium NV 131:4758606c9316 1457 pico_socket_alter_state(s, PICO_SOCKET_STATE_BOUND, 0, 0);
tass 68:0847e35d08a6 1458
tass 68:0847e35d08a6 1459 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 1460 if (PROTO(s) == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1461 pico_socket_alter_state(s, PICO_SOCKET_STATE_CONNECTED, 0, 0);
TASS Belgium NV 131:4758606c9316 1462 pico_err = PICO_ERR_NOERR;
TASS Belgium NV 131:4758606c9316 1463 ret = 0;
TASS Belgium NV 131:4758606c9316 1464 }
TASS Belgium NV 131:4758606c9316 1465
tass 68:0847e35d08a6 1466 #endif
tass 68:0847e35d08a6 1467
tass 68:0847e35d08a6 1468 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 1469 if (PROTO(s) == PICO_PROTO_TCP) {
TASS Belgium NV 131:4758606c9316 1470 if (pico_tcp_initconn(s) == 0) {
TASS Belgium NV 131:4758606c9316 1471 pico_socket_alter_state(s, PICO_SOCKET_STATE_CONNECTED | PICO_SOCKET_STATE_TCP_SYN_SENT, 0, 0);
TASS Belgium NV 131:4758606c9316 1472 pico_err = PICO_ERR_NOERR;
TASS Belgium NV 131:4758606c9316 1473 ret = 0;
TASS Belgium NV 131:4758606c9316 1474 } else {
TASS Belgium NV 131:4758606c9316 1475 pico_err = PICO_ERR_EHOSTUNREACH;
TASS Belgium NV 131:4758606c9316 1476 }
tass 68:0847e35d08a6 1477 }
TASS Belgium NV 131:4758606c9316 1478
tass 68:0847e35d08a6 1479 #endif
tass 68:0847e35d08a6 1480
TASS Belgium NV 131:4758606c9316 1481 return ret;
tass 68:0847e35d08a6 1482 }
tass 68:0847e35d08a6 1483
tass 68:0847e35d08a6 1484 #ifdef PICO_SUPPORT_TCP
tass 68:0847e35d08a6 1485
tass 68:0847e35d08a6 1486 int pico_socket_listen(struct pico_socket *s, int backlog)
tass 68:0847e35d08a6 1487 {
TASS Belgium NV 131:4758606c9316 1488 if (!s || backlog < 1) {
TASS Belgium NV 131:4758606c9316 1489 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1490 return -1;
TASS Belgium NV 131:4758606c9316 1491 } else {
TASS Belgium NV 131:4758606c9316 1492 /* check if exists in tree */
TASS Belgium NV 131:4758606c9316 1493 /* See task #178 */
TASS Belgium NV 131:4758606c9316 1494 if (pico_check_socket(s) != 0) {
TASS Belgium NV 131:4758606c9316 1495 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1496 return -1;
TASS Belgium NV 131:4758606c9316 1497 }
tass 68:0847e35d08a6 1498 }
TASS Belgium NV 131:4758606c9316 1499
TASS Belgium NV 131:4758606c9316 1500 if (PROTO(s) == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1501 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1502 return -1;
TASS Belgium NV 131:4758606c9316 1503 }
tass 68:0847e35d08a6 1504
TASS Belgium NV 131:4758606c9316 1505 if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) {
TASS Belgium NV 131:4758606c9316 1506 pico_err = PICO_ERR_EISCONN;
TASS Belgium NV 131:4758606c9316 1507 return -1;
TASS Belgium NV 131:4758606c9316 1508 }
tass 68:0847e35d08a6 1509
TASS Belgium NV 131:4758606c9316 1510 if (backlog < 1) {
TASS Belgium NV 131:4758606c9316 1511 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1512 return -1;
TASS Belgium NV 131:4758606c9316 1513 }
tass 68:0847e35d08a6 1514
TASS Belgium NV 131:4758606c9316 1515 if (PROTO(s) == PICO_PROTO_TCP)
TASS Belgium NV 131:4758606c9316 1516 pico_socket_alter_state(s, PICO_SOCKET_STATE_TCP_SYN_SENT, 0, PICO_SOCKET_STATE_TCP_LISTEN);
tass 68:0847e35d08a6 1517
TASS Belgium NV 131:4758606c9316 1518 s->max_backlog = backlog;
TASS Belgium NV 131:4758606c9316 1519
TASS Belgium NV 131:4758606c9316 1520 return 0;
tass 68:0847e35d08a6 1521 }
tass 68:0847e35d08a6 1522
tass 68:0847e35d08a6 1523 struct pico_socket *pico_socket_accept(struct pico_socket *s, void *orig, uint16_t *port)
tass 68:0847e35d08a6 1524 {
TASS Belgium NV 131:4758606c9316 1525 if (!s || !orig || !port) {
TASS Belgium NV 131:4758606c9316 1526 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1527 return NULL;
TASS Belgium NV 131:4758606c9316 1528 }
TASS Belgium NV 131:4758606c9316 1529
tass 68:0847e35d08a6 1530 pico_err = PICO_ERR_EINVAL;
tass 68:0847e35d08a6 1531
TASS Belgium NV 131:4758606c9316 1532 if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) {
TASS Belgium NV 131:4758606c9316 1533 return NULL;
TASS Belgium NV 131:4758606c9316 1534 }
tass 68:0847e35d08a6 1535
TASS Belgium NV 131:4758606c9316 1536 if (PROTO(s) == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1537 return NULL;
TASS Belgium NV 131:4758606c9316 1538 }
tass 68:0847e35d08a6 1539
TASS Belgium NV 131:4758606c9316 1540 if (TCPSTATE(s) == PICO_SOCKET_STATE_TCP_LISTEN) {
TASS Belgium NV 131:4758606c9316 1541 struct pico_sockport *sp = pico_get_sockport(PICO_PROTO_TCP, s->local_port);
TASS Belgium NV 131:4758606c9316 1542 struct pico_socket *found;
TASS Belgium NV 131:4758606c9316 1543 /* If at this point no incoming connection socket is found,
TASS Belgium NV 131:4758606c9316 1544 * the accept call is valid, but no connection is established yet.
TASS Belgium NV 131:4758606c9316 1545 */
TASS Belgium NV 131:4758606c9316 1546 pico_err = PICO_ERR_EAGAIN;
TASS Belgium NV 131:4758606c9316 1547 if (sp) {
TASS Belgium NV 131:4758606c9316 1548 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 1549 /* RB_FOREACH(found, socket_tree, &sp->socks) { */
TASS Belgium NV 131:4758606c9316 1550 pico_tree_foreach(index, &sp->socks){
TASS Belgium NV 131:4758606c9316 1551 found = index->keyValue;
TASS Belgium NV 131:4758606c9316 1552 if ((s == found->parent) && ((found->state & PICO_SOCKET_STATE_TCP) == PICO_SOCKET_STATE_TCP_ESTABLISHED)) {
TASS Belgium NV 131:4758606c9316 1553 found->parent = NULL;
TASS Belgium NV 131:4758606c9316 1554 pico_err = PICO_ERR_NOERR;
TASS Belgium NV 131:4758606c9316 1555 memcpy(orig, &found->remote_addr, sizeof(struct pico_ip4));
TASS Belgium NV 131:4758606c9316 1556 *port = found->remote_port;
TASS Belgium NV 131:4758606c9316 1557 s->number_of_pending_conn--;
TASS Belgium NV 131:4758606c9316 1558 return found;
TASS Belgium NV 131:4758606c9316 1559 }
TASS Belgium NV 131:4758606c9316 1560 }
tass 68:0847e35d08a6 1561 }
tass 68:0847e35d08a6 1562 }
TASS Belgium NV 131:4758606c9316 1563
TASS Belgium NV 131:4758606c9316 1564 return NULL;
tass 68:0847e35d08a6 1565 }
tass 68:0847e35d08a6 1566
tass 68:0847e35d08a6 1567 #else
tass 68:0847e35d08a6 1568
tass 68:0847e35d08a6 1569 int pico_socket_listen(struct pico_socket *s, int backlog)
tass 68:0847e35d08a6 1570 {
TASS Belgium NV 131:4758606c9316 1571 IGNORE_PARAMETER(s);
TASS Belgium NV 131:4758606c9316 1572 IGNORE_PARAMETER(backlog);
TASS Belgium NV 131:4758606c9316 1573 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1574 return -1;
tass 68:0847e35d08a6 1575 }
tass 68:0847e35d08a6 1576
tass 68:0847e35d08a6 1577 struct pico_socket *pico_socket_accept(struct pico_socket *s, void *orig, uint16_t *local_port)
tass 68:0847e35d08a6 1578 {
TASS Belgium NV 131:4758606c9316 1579 IGNORE_PARAMETER(s);
TASS Belgium NV 131:4758606c9316 1580 IGNORE_PARAMETER(orig);
TASS Belgium NV 131:4758606c9316 1581 IGNORE_PARAMETER(local_port);
TASS Belgium NV 131:4758606c9316 1582 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1583 return NULL;
tass 68:0847e35d08a6 1584 }
tass 68:0847e35d08a6 1585
tass 68:0847e35d08a6 1586 #endif
tass 68:0847e35d08a6 1587
TASS Belgium NV 131:4758606c9316 1588 #define PICO_SOCKET_SETOPT_EN(socket, index) (socket->opt_flags |= (1 << index))
TASS Belgium NV 131:4758606c9316 1589 #define PICO_SOCKET_SETOPT_DIS(socket, index) (socket->opt_flags &= (uint16_t) ~(1 << index))
tass 68:0847e35d08a6 1590
tass 74:c146c4e346c4 1591 #ifdef PICO_SUPPORT_MCAST
tass 74:c146c4e346c4 1592 static struct pico_ipv4_link *setopt_multicast_check(struct pico_socket *s, void *value, int alloc, int bysource)
tass 74:c146c4e346c4 1593 {
tass 74:c146c4e346c4 1594 struct pico_ip_mreq *mreq = NULL;
tass 74:c146c4e346c4 1595 struct pico_ipv4_link *mcast_link = NULL;
tass 74:c146c4e346c4 1596 struct pico_ip_mreq_source *mreq_src = NULL;
tass 74:c146c4e346c4 1597
tass 74:c146c4e346c4 1598 if (!value) {
TASS Belgium NV 131:4758606c9316 1599 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1600 return NULL;
tass 74:c146c4e346c4 1601 }
TASS Belgium NV 131:4758606c9316 1602
tass 74:c146c4e346c4 1603 if (!bysource) {
TASS Belgium NV 131:4758606c9316 1604 mreq = (struct pico_ip_mreq *) value;
TASS Belgium NV 131:4758606c9316 1605 mcast_link = pico_socket_setoption_mcastargs_validation(mreq, NULL);
TASS Belgium NV 131:4758606c9316 1606 if (!mreq->mcast_link_addr.addr)
TASS Belgium NV 131:4758606c9316 1607 mreq->mcast_link_addr.addr = mcast_link->address.addr;
tass 74:c146c4e346c4 1608 } else {
TASS Belgium NV 131:4758606c9316 1609 mreq_src = (struct pico_ip_mreq_source *) value;
TASS Belgium NV 131:4758606c9316 1610 mcast_link = pico_socket_setoption_mcastargs_validation(NULL, mreq_src);
TASS Belgium NV 131:4758606c9316 1611 if (!mreq_src->mcast_link_addr.addr)
TASS Belgium NV 131:4758606c9316 1612 mreq_src->mcast_link_addr.addr = mcast_link->address.addr;
tass 74:c146c4e346c4 1613 }
TASS Belgium NV 131:4758606c9316 1614
tass 74:c146c4e346c4 1615 if (!mcast_link) {
TASS Belgium NV 131:4758606c9316 1616 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1617 return NULL;
tass 74:c146c4e346c4 1618 }
tass 74:c146c4e346c4 1619
tass 74:c146c4e346c4 1620 if (!s->MCASTListen) { /* No RBTree allocated yet */
TASS Belgium NV 131:4758606c9316 1621 if (alloc) {
TASS Belgium NV 131:4758606c9316 1622 s->MCASTListen = pico_zalloc(sizeof(struct pico_tree));
TASS Belgium NV 131:4758606c9316 1623 if (!s->MCASTListen) {
TASS Belgium NV 131:4758606c9316 1624 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 1625 return NULL;
TASS Belgium NV 131:4758606c9316 1626 }
TASS Belgium NV 131:4758606c9316 1627
TASS Belgium NV 131:4758606c9316 1628 s->MCASTListen->root = &LEAF;
TASS Belgium NV 131:4758606c9316 1629 s->MCASTListen->compare = mcast_listen_cmp;
TASS Belgium NV 131:4758606c9316 1630 } else return NULL;
tass 74:c146c4e346c4 1631 }
TASS Belgium NV 131:4758606c9316 1632
tass 74:c146c4e346c4 1633 return mcast_link;
tass 74:c146c4e346c4 1634 }
tass 74:c146c4e346c4 1635 #endif
tass 74:c146c4e346c4 1636
TASS Belgium NV 131:4758606c9316 1637 int pico_socket_setoption(struct pico_socket *s, int option, void *value) /* XXX no check against proto (vs setsockopt) or implicit by socket? */
tass 68:0847e35d08a6 1638 {
TASS Belgium NV 131:4758606c9316 1639 if (s == NULL) {
TASS Belgium NV 131:4758606c9316 1640 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1641 return -1;
TASS Belgium NV 131:4758606c9316 1642 }
tass 68:0847e35d08a6 1643
TASS Belgium NV 131:4758606c9316 1644 pico_err = PICO_ERR_NOERR;
tass 68:0847e35d08a6 1645
TASS Belgium NV 131:4758606c9316 1646 switch (option)
TASS Belgium NV 131:4758606c9316 1647 {
tass 68:0847e35d08a6 1648 #ifdef PICO_SUPPORT_TCP
tass 68:0847e35d08a6 1649 case PICO_TCP_NODELAY:
TASS Belgium NV 131:4758606c9316 1650 if (!value) {
tass 68:0847e35d08a6 1651 pico_err = PICO_ERR_EINVAL;
tass 68:0847e35d08a6 1652 return -1;
TASS Belgium NV 131:4758606c9316 1653 }
TASS Belgium NV 131:4758606c9316 1654
TASS Belgium NV 131:4758606c9316 1655 if (s->proto->proto_number == PICO_PROTO_TCP) {
tass 68:0847e35d08a6 1656 int *val = (int*)value;
tass 68:0847e35d08a6 1657 if (*val > 0) {
TASS Belgium NV 131:4758606c9316 1658 dbg("setsockopt: Nagle algorithm disabled.\n");
TASS Belgium NV 131:4758606c9316 1659 PICO_SOCKET_SETOPT_EN(s, PICO_SOCKET_OPT_TCPNODELAY);
tass 68:0847e35d08a6 1660 } else {
TASS Belgium NV 131:4758606c9316 1661 dbg("setsockopt: Nagle algorithm enabled.\n");
TASS Belgium NV 131:4758606c9316 1662 PICO_SOCKET_SETOPT_DIS(s, PICO_SOCKET_OPT_TCPNODELAY);
tass 68:0847e35d08a6 1663 }
TASS Belgium NV 131:4758606c9316 1664 } else {
tass 68:0847e35d08a6 1665 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1666 }
TASS Belgium NV 131:4758606c9316 1667
TASS Belgium NV 131:4758606c9316 1668 break;
tass 68:0847e35d08a6 1669 #endif
tass 68:0847e35d08a6 1670
tass 68:0847e35d08a6 1671
tass 68:0847e35d08a6 1672 #ifdef PICO_SUPPORT_MCAST
tass 68:0847e35d08a6 1673 case PICO_IP_MULTICAST_IF:
TASS Belgium NV 131:4758606c9316 1674 pico_err = PICO_ERR_EOPNOTSUPP;
TASS Belgium NV 131:4758606c9316 1675 return -1;
TASS Belgium NV 131:4758606c9316 1676 break;
tass 68:0847e35d08a6 1677
tass 68:0847e35d08a6 1678 case PICO_IP_MULTICAST_TTL:
TASS Belgium NV 131:4758606c9316 1679 if (s->proto->proto_number == PICO_PROTO_UDP) {
tass 68:0847e35d08a6 1680 return pico_udp_set_mc_ttl(s, *((uint8_t *) value));
TASS Belgium NV 131:4758606c9316 1681 }
TASS Belgium NV 131:4758606c9316 1682
TASS Belgium NV 131:4758606c9316 1683 break;
tass 68:0847e35d08a6 1684
tass 68:0847e35d08a6 1685 case PICO_IP_MULTICAST_LOOP:
TASS Belgium NV 131:4758606c9316 1686 if (s->proto->proto_number == PICO_PROTO_UDP) {
tass 68:0847e35d08a6 1687 switch (*(uint8_t *) value)
tass 68:0847e35d08a6 1688 {
TASS Belgium NV 131:4758606c9316 1689 case 0:
tass 68:0847e35d08a6 1690 /* do not loop back multicast datagram */
TASS Belgium NV 131:4758606c9316 1691 PICO_SOCKET_SETOPT_DIS(s, PICO_SOCKET_OPT_MULTICAST_LOOP);
tass 68:0847e35d08a6 1692 break;
tass 68:0847e35d08a6 1693
TASS Belgium NV 131:4758606c9316 1694 case 1:
tass 68:0847e35d08a6 1695 /* do loop back multicast datagram */
TASS Belgium NV 131:4758606c9316 1696 PICO_SOCKET_SETOPT_EN(s, PICO_SOCKET_OPT_MULTICAST_LOOP);
TASS Belgium NV 131:4758606c9316 1697 break;
tass 68:0847e35d08a6 1698
TASS Belgium NV 131:4758606c9316 1699 default:
tass 68:0847e35d08a6 1700 pico_err = PICO_ERR_EINVAL;
tass 68:0847e35d08a6 1701 return -1;
TASS Belgium NV 131:4758606c9316 1702 }
TASS Belgium NV 131:4758606c9316 1703 }
TASS Belgium NV 131:4758606c9316 1704
TASS Belgium NV 131:4758606c9316 1705 break;
tass 68:0847e35d08a6 1706
tass 68:0847e35d08a6 1707 case PICO_IP_ADD_MEMBERSHIP:
TASS Belgium NV 131:4758606c9316 1708 /* EXCLUDE mode */
TASS Belgium NV 131:4758606c9316 1709 if (s->proto->proto_number == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1710 int filter_mode;
TASS Belgium NV 131:4758606c9316 1711 struct pico_mcast_listen *listen;
TASS Belgium NV 131:4758606c9316 1712 struct pico_ip_mreq *mreq = (struct pico_ip_mreq *)value;
TASS Belgium NV 131:4758606c9316 1713 struct pico_ipv4_link *mcast_link = setopt_multicast_check(s, value, 1, 0);
TASS Belgium NV 131:4758606c9316 1714 if (!mcast_link)
TASS Belgium NV 131:4758606c9316 1715 return -1;
TASS Belgium NV 131:4758606c9316 1716
TASS Belgium NV 131:4758606c9316 1717 listen = listen_find(s, &mreq->mcast_link_addr, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1718 if (listen) {
TASS Belgium NV 131:4758606c9316 1719 if (listen->filter_mode != PICO_IP_MULTICAST_EXCLUDE) {
TASS Belgium NV 131:4758606c9316 1720 so_mcast_dbg("pico_socket_setoption: ERROR any-source multicast (exclude) on source-specific multicast (include)\n");
TASS Belgium NV 131:4758606c9316 1721 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1722 return -1;
TASS Belgium NV 131:4758606c9316 1723 } else {
TASS Belgium NV 131:4758606c9316 1724 so_mcast_dbg("pico_socket_setoption: ERROR duplicate PICO_IP_ADD_MEMBERSHIP\n");
TASS Belgium NV 131:4758606c9316 1725 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1726 return -1;
TASS Belgium NV 131:4758606c9316 1727 }
TASS Belgium NV 131:4758606c9316 1728 } else {
TASS Belgium NV 131:4758606c9316 1729 listen = pico_zalloc(sizeof(struct pico_mcast_listen));
TASS Belgium NV 131:4758606c9316 1730 if (!listen) {
TASS Belgium NV 131:4758606c9316 1731 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 1732 return -1;
TASS Belgium NV 131:4758606c9316 1733 }
TASS Belgium NV 131:4758606c9316 1734
TASS Belgium NV 131:4758606c9316 1735 listen->filter_mode = PICO_IP_MULTICAST_EXCLUDE;
TASS Belgium NV 131:4758606c9316 1736 listen->mcast_link = mreq->mcast_link_addr;
TASS Belgium NV 131:4758606c9316 1737 listen->mcast_group = mreq->mcast_group_addr;
TASS Belgium NV 131:4758606c9316 1738 listen->MCASTSources.root = &LEAF;
TASS Belgium NV 131:4758606c9316 1739 listen->MCASTSources.compare = mcast_sources_cmp;
TASS Belgium NV 131:4758606c9316 1740 pico_tree_insert(s->MCASTListen, listen);
TASS Belgium NV 131:4758606c9316 1741 }
TASS Belgium NV 131:4758606c9316 1742
TASS Belgium NV 131:4758606c9316 1743 pico_tree_insert(&MCASTSockets, s);
TASS Belgium NV 131:4758606c9316 1744 filter_mode = pico_socket_aggregate_mcastfilters(&mcast_link->address, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1745 if (filter_mode < 0)
TASS Belgium NV 131:4758606c9316 1746 return -1;
TASS Belgium NV 131:4758606c9316 1747
TASS Belgium NV 131:4758606c9316 1748 return pico_ipv4_mcast_join(&mreq->mcast_link_addr, &mreq->mcast_group_addr, 1, (uint8_t)filter_mode, &MCASTFilter);
tass 68:0847e35d08a6 1749 }
tass 68:0847e35d08a6 1750
TASS Belgium NV 131:4758606c9316 1751 break;
tass 68:0847e35d08a6 1752
tass 68:0847e35d08a6 1753 case PICO_IP_DROP_MEMBERSHIP:
TASS Belgium NV 131:4758606c9316 1754 /* EXCLUDE mode */
TASS Belgium NV 131:4758606c9316 1755 if (s->proto->proto_number == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1756 int filter_mode = 0;
TASS Belgium NV 131:4758606c9316 1757 struct pico_mcast_listen *listen;
TASS Belgium NV 131:4758606c9316 1758 struct pico_ip_mreq *mreq = (struct pico_ip_mreq *)value;
TASS Belgium NV 131:4758606c9316 1759 struct pico_ip4 *source = NULL;
TASS Belgium NV 131:4758606c9316 1760 struct pico_tree_node *index, *_tmp;
TASS Belgium NV 131:4758606c9316 1761 struct pico_ipv4_link *mcast_link = setopt_multicast_check(s, value, 0, 0);
TASS Belgium NV 131:4758606c9316 1762 if (!mcast_link)
TASS Belgium NV 131:4758606c9316 1763 return -1;
tass 68:0847e35d08a6 1764
TASS Belgium NV 131:4758606c9316 1765 listen = listen_find(s, &mreq->mcast_link_addr, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1766 if (!listen) {
TASS Belgium NV 131:4758606c9316 1767 so_mcast_dbg("pico_socket_setoption: ERROR PICO_IP_DROP_MEMBERSHIP before PICO_IP_ADD_MEMBERSHIP/SOURCE_MEMBERSHIP\n");
TASS Belgium NV 131:4758606c9316 1768 pico_err = PICO_ERR_EADDRNOTAVAIL;
TASS Belgium NV 131:4758606c9316 1769 return -1;
TASS Belgium NV 131:4758606c9316 1770 } else {
TASS Belgium NV 131:4758606c9316 1771 pico_tree_foreach_safe(index, &listen->MCASTSources, _tmp)
TASS Belgium NV 131:4758606c9316 1772 {
TASS Belgium NV 131:4758606c9316 1773 source = index->keyValue;
TASS Belgium NV 131:4758606c9316 1774 pico_tree_delete(&listen->MCASTSources, source);
TASS Belgium NV 131:4758606c9316 1775 pico_free(source);
TASS Belgium NV 131:4758606c9316 1776 }
TASS Belgium NV 131:4758606c9316 1777 pico_tree_delete(s->MCASTListen, listen);
TASS Belgium NV 131:4758606c9316 1778 pico_free(listen);
TASS Belgium NV 131:4758606c9316 1779 if (pico_tree_empty(s->MCASTListen)) {
TASS Belgium NV 131:4758606c9316 1780 pico_free(s->MCASTListen);
TASS Belgium NV 131:4758606c9316 1781 s->MCASTListen = NULL;
TASS Belgium NV 131:4758606c9316 1782 pico_tree_delete(&MCASTSockets, s);
TASS Belgium NV 131:4758606c9316 1783 }
TASS Belgium NV 131:4758606c9316 1784 }
TASS Belgium NV 131:4758606c9316 1785
TASS Belgium NV 131:4758606c9316 1786 filter_mode = pico_socket_aggregate_mcastfilters(&mcast_link->address, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1787 if (filter_mode < 0)
TASS Belgium NV 131:4758606c9316 1788 return -1;
TASS Belgium NV 131:4758606c9316 1789
TASS Belgium NV 131:4758606c9316 1790 return pico_ipv4_mcast_leave(&mreq->mcast_link_addr, &mreq->mcast_group_addr, 1, (uint8_t)filter_mode, &MCASTFilter);
tass 68:0847e35d08a6 1791 }
tass 68:0847e35d08a6 1792
TASS Belgium NV 131:4758606c9316 1793 break;
tass 68:0847e35d08a6 1794
tass 68:0847e35d08a6 1795 case PICO_IP_UNBLOCK_SOURCE:
TASS Belgium NV 131:4758606c9316 1796 /* EXCLUDE mode */
TASS Belgium NV 131:4758606c9316 1797 if (s->proto->proto_number == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1798 int filter_mode = 0;
TASS Belgium NV 131:4758606c9316 1799 struct pico_ip_mreq_source *mreq = (struct pico_ip_mreq_source *)value;
TASS Belgium NV 131:4758606c9316 1800 struct pico_mcast_listen *listen = NULL;
TASS Belgium NV 131:4758606c9316 1801 struct pico_ip4 *source = NULL, stest = {
TASS Belgium NV 131:4758606c9316 1802 0
TASS Belgium NV 131:4758606c9316 1803 };
TASS Belgium NV 131:4758606c9316 1804 struct pico_ipv4_link *mcast_link = setopt_multicast_check(s, value, 0, 1);
TASS Belgium NV 131:4758606c9316 1805 if (!mcast_link)
TASS Belgium NV 131:4758606c9316 1806 return -1;
TASS Belgium NV 131:4758606c9316 1807
TASS Belgium NV 131:4758606c9316 1808 listen = listen_find(s, &mreq->mcast_link_addr, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1809 if (!listen) {
TASS Belgium NV 131:4758606c9316 1810 so_mcast_dbg("pico_socket_setoption: ERROR PICO_IP_UNBLOCK_SOURCE before PICO_IP_ADD_MEMBERSHIP\n");
TASS Belgium NV 131:4758606c9316 1811 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1812 return -1;
TASS Belgium NV 131:4758606c9316 1813 } else {
TASS Belgium NV 131:4758606c9316 1814 if (listen->filter_mode != PICO_IP_MULTICAST_EXCLUDE) {
TASS Belgium NV 131:4758606c9316 1815 so_mcast_dbg("pico_socket_setoption: ERROR any-source multicast (exclude) on source-specific multicast (include)\n");
TASS Belgium NV 131:4758606c9316 1816 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1817 return -1;
TASS Belgium NV 131:4758606c9316 1818 }
TASS Belgium NV 131:4758606c9316 1819
TASS Belgium NV 131:4758606c9316 1820 stest.addr = mreq->mcast_source_addr.addr;
TASS Belgium NV 131:4758606c9316 1821 source = pico_tree_findKey(&listen->MCASTSources, &stest);
TASS Belgium NV 131:4758606c9316 1822 if (!source) {
TASS Belgium NV 131:4758606c9316 1823 so_mcast_dbg("pico_socket_setoption: ERROR address to unblock not in source list\n");
TASS Belgium NV 131:4758606c9316 1824 pico_err = PICO_ERR_EADDRNOTAVAIL;
TASS Belgium NV 131:4758606c9316 1825 return -1;
TASS Belgium NV 131:4758606c9316 1826 } else {
TASS Belgium NV 131:4758606c9316 1827 pico_tree_delete(&listen->MCASTSources, source);
TASS Belgium NV 131:4758606c9316 1828 pico_free(source);
TASS Belgium NV 131:4758606c9316 1829 }
TASS Belgium NV 131:4758606c9316 1830 }
TASS Belgium NV 131:4758606c9316 1831
TASS Belgium NV 131:4758606c9316 1832 filter_mode = pico_socket_aggregate_mcastfilters(&mcast_link->address, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1833 if (filter_mode < 0)
TASS Belgium NV 131:4758606c9316 1834 return -1;
TASS Belgium NV 131:4758606c9316 1835
TASS Belgium NV 131:4758606c9316 1836 return pico_ipv4_mcast_leave(&mreq->mcast_link_addr, &mreq->mcast_group_addr, 0, (uint8_t)filter_mode, &MCASTFilter);
tass 68:0847e35d08a6 1837 }
tass 68:0847e35d08a6 1838
TASS Belgium NV 131:4758606c9316 1839 break;
tass 68:0847e35d08a6 1840
tass 68:0847e35d08a6 1841 case PICO_IP_BLOCK_SOURCE:
TASS Belgium NV 131:4758606c9316 1842 /* EXCLUDE mode */
TASS Belgium NV 131:4758606c9316 1843 if (s->proto->proto_number == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1844 int filter_mode = 0;
TASS Belgium NV 131:4758606c9316 1845 struct pico_ip_mreq_source *mreq = (struct pico_ip_mreq_source *)value;
TASS Belgium NV 131:4758606c9316 1846 struct pico_mcast_listen *listen = NULL;
TASS Belgium NV 131:4758606c9316 1847 struct pico_ip4 *source = NULL, stest = {
TASS Belgium NV 131:4758606c9316 1848 0
TASS Belgium NV 131:4758606c9316 1849 };
TASS Belgium NV 131:4758606c9316 1850 struct pico_ipv4_link *mcast_link = setopt_multicast_check(s, value, 0, 1);
TASS Belgium NV 131:4758606c9316 1851 if (!mcast_link)
TASS Belgium NV 131:4758606c9316 1852 return -1;
TASS Belgium NV 131:4758606c9316 1853
TASS Belgium NV 131:4758606c9316 1854 listen = listen_find(s, &mreq->mcast_link_addr, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1855 if (!listen) {
TASS Belgium NV 131:4758606c9316 1856 dbg("pico_socket_setoption: ERROR PICO_IP_BLOCK_SOURCE before PICO_IP_ADD_MEMBERSHIP\n");
TASS Belgium NV 131:4758606c9316 1857 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1858 return -1;
TASS Belgium NV 131:4758606c9316 1859 } else {
TASS Belgium NV 131:4758606c9316 1860 if (listen->filter_mode != PICO_IP_MULTICAST_EXCLUDE) {
TASS Belgium NV 131:4758606c9316 1861 so_mcast_dbg("pico_socket_setoption: ERROR any-source multicast (exclude) on source-specific multicast (include)\n");
TASS Belgium NV 131:4758606c9316 1862 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1863 return -1;
TASS Belgium NV 131:4758606c9316 1864 }
TASS Belgium NV 131:4758606c9316 1865
TASS Belgium NV 131:4758606c9316 1866 stest.addr = mreq->mcast_source_addr.addr;
TASS Belgium NV 131:4758606c9316 1867 source = pico_tree_findKey(&listen->MCASTSources, &stest);
TASS Belgium NV 131:4758606c9316 1868 if (source) {
TASS Belgium NV 131:4758606c9316 1869 so_mcast_dbg("pico_socket_setoption: ERROR address to block already in source list\n");
TASS Belgium NV 131:4758606c9316 1870 pico_err = PICO_ERR_EADDRNOTAVAIL;
TASS Belgium NV 131:4758606c9316 1871 return -1;
TASS Belgium NV 131:4758606c9316 1872 } else {
TASS Belgium NV 131:4758606c9316 1873 source = pico_zalloc(sizeof(struct pico_ip4));
TASS Belgium NV 131:4758606c9316 1874 if (!source) {
TASS Belgium NV 131:4758606c9316 1875 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 1876 return -1;
TASS Belgium NV 131:4758606c9316 1877 }
TASS Belgium NV 131:4758606c9316 1878
TASS Belgium NV 131:4758606c9316 1879 source->addr = mreq->mcast_source_addr.addr;
TASS Belgium NV 131:4758606c9316 1880 pico_tree_insert(&listen->MCASTSources, source);
TASS Belgium NV 131:4758606c9316 1881 }
tass 68:0847e35d08a6 1882 }
TASS Belgium NV 131:4758606c9316 1883
TASS Belgium NV 131:4758606c9316 1884 filter_mode = pico_socket_aggregate_mcastfilters(&mcast_link->address, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1885 if (filter_mode < 0)
TASS Belgium NV 131:4758606c9316 1886 return -1;
TASS Belgium NV 131:4758606c9316 1887
TASS Belgium NV 131:4758606c9316 1888 return pico_ipv4_mcast_join(&mreq->mcast_link_addr, &mreq->mcast_group_addr, 0, (uint8_t)filter_mode, &MCASTFilter);
tass 68:0847e35d08a6 1889 }
tass 68:0847e35d08a6 1890
TASS Belgium NV 131:4758606c9316 1891 break;
tass 68:0847e35d08a6 1892
tass 68:0847e35d08a6 1893 case PICO_IP_ADD_SOURCE_MEMBERSHIP:
TASS Belgium NV 131:4758606c9316 1894 /* INCLUDE mode */
TASS Belgium NV 131:4758606c9316 1895 if (s->proto->proto_number == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1896 int filter_mode = 0, reference_count = 0;
TASS Belgium NV 131:4758606c9316 1897 struct pico_ip_mreq_source *mreq = (struct pico_ip_mreq_source *)value;
TASS Belgium NV 131:4758606c9316 1898 struct pico_mcast_listen *listen = NULL;
TASS Belgium NV 131:4758606c9316 1899 struct pico_ip4 *source = NULL, stest = {
TASS Belgium NV 131:4758606c9316 1900 0
TASS Belgium NV 131:4758606c9316 1901 };
TASS Belgium NV 131:4758606c9316 1902 struct pico_ipv4_link *mcast_link = setopt_multicast_check(s, value, 1, 1);
TASS Belgium NV 131:4758606c9316 1903 if (!mcast_link)
TASS Belgium NV 131:4758606c9316 1904 return -1;
TASS Belgium NV 131:4758606c9316 1905
TASS Belgium NV 131:4758606c9316 1906 listen = listen_find(s, &mreq->mcast_link_addr, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1907 if (listen) {
TASS Belgium NV 131:4758606c9316 1908 if (listen->filter_mode != PICO_IP_MULTICAST_INCLUDE) {
TASS Belgium NV 131:4758606c9316 1909 so_mcast_dbg("pico_socket_setoption: ERROR source-specific multicast (include) on any-source multicast (exclude)\n");
TASS Belgium NV 131:4758606c9316 1910 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1911 return -1;
TASS Belgium NV 131:4758606c9316 1912 }
TASS Belgium NV 131:4758606c9316 1913
TASS Belgium NV 131:4758606c9316 1914 stest.addr = mreq->mcast_source_addr.addr;
TASS Belgium NV 131:4758606c9316 1915 source = pico_tree_findKey(&listen->MCASTSources, &stest);
TASS Belgium NV 131:4758606c9316 1916 if (source) {
TASS Belgium NV 131:4758606c9316 1917 so_mcast_dbg("pico_socket_setoption: ERROR source address to allow already in source list\n");
TASS Belgium NV 131:4758606c9316 1918 pico_err = PICO_ERR_EADDRNOTAVAIL;
TASS Belgium NV 131:4758606c9316 1919 return -1;
TASS Belgium NV 131:4758606c9316 1920 } else {
TASS Belgium NV 131:4758606c9316 1921 source = pico_zalloc(sizeof(struct pico_ip4));
TASS Belgium NV 131:4758606c9316 1922 if (!source) {
TASS Belgium NV 131:4758606c9316 1923 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 1924 return -1;
TASS Belgium NV 131:4758606c9316 1925 }
TASS Belgium NV 131:4758606c9316 1926
TASS Belgium NV 131:4758606c9316 1927 source->addr = mreq->mcast_source_addr.addr;
TASS Belgium NV 131:4758606c9316 1928 pico_tree_insert(&listen->MCASTSources, source);
TASS Belgium NV 131:4758606c9316 1929 }
TASS Belgium NV 131:4758606c9316 1930 } else {
TASS Belgium NV 131:4758606c9316 1931 listen = pico_zalloc(sizeof(struct pico_mcast_listen));
TASS Belgium NV 131:4758606c9316 1932 if (!listen) {
TASS Belgium NV 131:4758606c9316 1933 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 1934 return -1;
TASS Belgium NV 131:4758606c9316 1935 }
TASS Belgium NV 131:4758606c9316 1936
TASS Belgium NV 131:4758606c9316 1937 listen->filter_mode = PICO_IP_MULTICAST_INCLUDE;
TASS Belgium NV 131:4758606c9316 1938 listen->mcast_link = mreq->mcast_link_addr;
TASS Belgium NV 131:4758606c9316 1939 listen->mcast_group = mreq->mcast_group_addr;
TASS Belgium NV 131:4758606c9316 1940 listen->MCASTSources.root = &LEAF;
TASS Belgium NV 131:4758606c9316 1941 listen->MCASTSources.compare = mcast_sources_cmp;
TASS Belgium NV 131:4758606c9316 1942 source = pico_zalloc(sizeof(struct pico_ip4));
TASS Belgium NV 131:4758606c9316 1943 if (!source) {
TASS Belgium NV 131:4758606c9316 1944 pico_free(listen);
TASS Belgium NV 131:4758606c9316 1945 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 1946 return -1;
TASS Belgium NV 131:4758606c9316 1947 }
TASS Belgium NV 131:4758606c9316 1948
TASS Belgium NV 131:4758606c9316 1949 source->addr = mreq->mcast_source_addr.addr;
TASS Belgium NV 131:4758606c9316 1950 pico_tree_insert(&listen->MCASTSources, source);
TASS Belgium NV 131:4758606c9316 1951 pico_tree_insert(s->MCASTListen, listen);
TASS Belgium NV 131:4758606c9316 1952 reference_count = 1;
tass 68:0847e35d08a6 1953 }
TASS Belgium NV 131:4758606c9316 1954
TASS Belgium NV 131:4758606c9316 1955 pico_tree_insert(&MCASTSockets, s);
TASS Belgium NV 131:4758606c9316 1956 filter_mode = pico_socket_aggregate_mcastfilters(&mcast_link->address, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1957 if (filter_mode < 0)
TASS Belgium NV 131:4758606c9316 1958 return -1;
TASS Belgium NV 131:4758606c9316 1959
TASS Belgium NV 131:4758606c9316 1960 return pico_ipv4_mcast_join(&mreq->mcast_link_addr, &mreq->mcast_group_addr, (uint8_t)reference_count, (uint8_t)filter_mode, &MCASTFilter);
tass 68:0847e35d08a6 1961 }
tass 68:0847e35d08a6 1962
TASS Belgium NV 131:4758606c9316 1963 break;
tass 68:0847e35d08a6 1964
tass 68:0847e35d08a6 1965 case PICO_IP_DROP_SOURCE_MEMBERSHIP:
TASS Belgium NV 131:4758606c9316 1966 /* INCLUDE mode */
TASS Belgium NV 131:4758606c9316 1967 if (s->proto->proto_number == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1968 int filter_mode = 0, reference_count = 0;
TASS Belgium NV 131:4758606c9316 1969 struct pico_ip_mreq_source *mreq = (struct pico_ip_mreq_source *)value;
TASS Belgium NV 131:4758606c9316 1970 struct pico_mcast_listen *listen = NULL;
TASS Belgium NV 131:4758606c9316 1971 struct pico_ip4 *source = NULL, stest = {
TASS Belgium NV 131:4758606c9316 1972 0
TASS Belgium NV 131:4758606c9316 1973 };
TASS Belgium NV 131:4758606c9316 1974 struct pico_ipv4_link *mcast_link = setopt_multicast_check(s, value, 0, 1);
TASS Belgium NV 131:4758606c9316 1975 if (!mcast_link)
TASS Belgium NV 131:4758606c9316 1976 return -1;
TASS Belgium NV 131:4758606c9316 1977
TASS Belgium NV 131:4758606c9316 1978 listen = listen_find(s, &mreq->mcast_link_addr, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1979 if (!listen) {
TASS Belgium NV 131:4758606c9316 1980 so_mcast_dbg("pico_socket_setoption: ERROR PICO_IP_DROP_SOURCE_MEMBERSHIP before PICO_IP_ADD_SOURCE_MEMBERSHIP\n");
TASS Belgium NV 131:4758606c9316 1981 pico_err = PICO_ERR_EADDRNOTAVAIL;
TASS Belgium NV 131:4758606c9316 1982 return -1;
TASS Belgium NV 131:4758606c9316 1983 } else {
TASS Belgium NV 131:4758606c9316 1984 if (listen->filter_mode != PICO_IP_MULTICAST_INCLUDE) {
TASS Belgium NV 131:4758606c9316 1985 so_mcast_dbg("pico_socket_setoption: ERROR source-specific multicast (include) on any-source multicast (exclude)\n");
TASS Belgium NV 131:4758606c9316 1986 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1987 return -1;
TASS Belgium NV 131:4758606c9316 1988 }
TASS Belgium NV 131:4758606c9316 1989
TASS Belgium NV 131:4758606c9316 1990 stest.addr = mreq->mcast_source_addr.addr;
TASS Belgium NV 131:4758606c9316 1991 source = pico_tree_findKey(&listen->MCASTSources, &stest);
TASS Belgium NV 131:4758606c9316 1992 if (!source) {
TASS Belgium NV 131:4758606c9316 1993 so_mcast_dbg("pico_socket_setoption: ERROR address to drop not in source list\n");
TASS Belgium NV 131:4758606c9316 1994 pico_err = PICO_ERR_EADDRNOTAVAIL;
TASS Belgium NV 131:4758606c9316 1995 return -1;
TASS Belgium NV 131:4758606c9316 1996 } else {
TASS Belgium NV 131:4758606c9316 1997 pico_tree_delete(&listen->MCASTSources, source);
TASS Belgium NV 131:4758606c9316 1998 pico_free(source);
TASS Belgium NV 131:4758606c9316 1999 if (pico_tree_empty(&listen->MCASTSources)) { /* 1 if empty, 0 otherwise */
TASS Belgium NV 131:4758606c9316 2000 reference_count = 1;
TASS Belgium NV 131:4758606c9316 2001 pico_tree_delete(s->MCASTListen, listen);
TASS Belgium NV 131:4758606c9316 2002 pico_free(listen);
TASS Belgium NV 131:4758606c9316 2003 if (pico_tree_empty(s->MCASTListen)) {
TASS Belgium NV 131:4758606c9316 2004 pico_free(s->MCASTListen);
TASS Belgium NV 131:4758606c9316 2005 s->MCASTListen = NULL;
TASS Belgium NV 131:4758606c9316 2006 pico_tree_delete(&MCASTSockets, s);
TASS Belgium NV 131:4758606c9316 2007 }
TASS Belgium NV 131:4758606c9316 2008 }
TASS Belgium NV 131:4758606c9316 2009 }
tass 68:0847e35d08a6 2010 }
TASS Belgium NV 131:4758606c9316 2011
TASS Belgium NV 131:4758606c9316 2012 filter_mode = pico_socket_aggregate_mcastfilters(&mcast_link->address, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 2013 if (filter_mode < 0)
TASS Belgium NV 131:4758606c9316 2014 return -1;
TASS Belgium NV 131:4758606c9316 2015
TASS Belgium NV 131:4758606c9316 2016 return pico_ipv4_mcast_leave(&mreq->mcast_link_addr, &mreq->mcast_group_addr, (uint8_t)reference_count, (uint8_t)filter_mode, &MCASTFilter);
tass 68:0847e35d08a6 2017 }
tass 68:0847e35d08a6 2018
TASS Belgium NV 131:4758606c9316 2019 break;
tass 68:0847e35d08a6 2020 #endif /* PICO_SUPPORT_MCAST */
tass 68:0847e35d08a6 2021
tass 68:0847e35d08a6 2022 default:
TASS Belgium NV 131:4758606c9316 2023 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 2024 return -1;
TASS Belgium NV 131:4758606c9316 2025 }
tass 68:0847e35d08a6 2026
TASS Belgium NV 131:4758606c9316 2027 if (pico_err != PICO_ERR_NOERR)
TASS Belgium NV 131:4758606c9316 2028 return -1;
TASS Belgium NV 131:4758606c9316 2029 else
TASS Belgium NV 131:4758606c9316 2030 return 0;
tass 68:0847e35d08a6 2031 }
tass 68:0847e35d08a6 2032
TASS Belgium NV 131:4758606c9316 2033 #define PICO_SOCKET_GETOPT(socket, index) ((socket->opt_flags & (1 << index)) != 0)
tass 68:0847e35d08a6 2034
tass 68:0847e35d08a6 2035 int pico_socket_getoption(struct pico_socket *s, int option, void *value)
TASS Belgium NV 131:4758606c9316 2036 {
TASS Belgium NV 131:4758606c9316 2037 if (!s || !value) {
TASS Belgium NV 131:4758606c9316 2038 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 2039 return -1;
TASS Belgium NV 131:4758606c9316 2040 }
tass 68:0847e35d08a6 2041
TASS Belgium NV 131:4758606c9316 2042 switch (option)
TASS Belgium NV 131:4758606c9316 2043 {
tass 68:0847e35d08a6 2044 #ifdef PICO_SUPPORT_TCP
tass 68:0847e35d08a6 2045 case PICO_TCP_NODELAY:
TASS Belgium NV 131:4758606c9316 2046 if (s->proto->proto_number == PICO_PROTO_TCP)
tass 68:0847e35d08a6 2047 /* state of the NODELAY option */
TASS Belgium NV 131:4758606c9316 2048 *(int *)value = PICO_SOCKET_GETOPT(s, PICO_SOCKET_OPT_TCPNODELAY);
TASS Belgium NV 131:4758606c9316 2049 else
tass 68:0847e35d08a6 2050 *(int *)value = 0;
TASS Belgium NV 131:4758606c9316 2051
TASS Belgium NV 131:4758606c9316 2052 break;
tass 68:0847e35d08a6 2053 #endif
tass 68:0847e35d08a6 2054
tass 68:0847e35d08a6 2055 #ifdef PICO_SUPPORT_MCAST
tass 68:0847e35d08a6 2056 case PICO_IP_MULTICAST_IF:
TASS Belgium NV 131:4758606c9316 2057 pico_err = PICO_ERR_EOPNOTSUPP;
TASS Belgium NV 131:4758606c9316 2058 return -1;
TASS Belgium NV 131:4758606c9316 2059 break;
tass 68:0847e35d08a6 2060
tass 68:0847e35d08a6 2061 case PICO_IP_MULTICAST_TTL:
TASS Belgium NV 131:4758606c9316 2062 if (s->proto->proto_number == PICO_PROTO_UDP) {
tass 68:0847e35d08a6 2063 pico_udp_get_mc_ttl(s, (uint8_t *) value);
TASS Belgium NV 131:4758606c9316 2064 } else {
tass 68:0847e35d08a6 2065 *(uint8_t *)value = 0;
tass 68:0847e35d08a6 2066 pico_err = PICO_ERR_EINVAL;
tass 68:0847e35d08a6 2067 return -1;
TASS Belgium NV 131:4758606c9316 2068 }
TASS Belgium NV 131:4758606c9316 2069
TASS Belgium NV 131:4758606c9316 2070 break;
tass 68:0847e35d08a6 2071
tass 68:0847e35d08a6 2072 case PICO_IP_MULTICAST_LOOP:
TASS Belgium NV 131:4758606c9316 2073 if (s->proto->proto_number == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 2074 *(uint8_t *)value = PICO_SOCKET_GETOPT(s, PICO_SOCKET_OPT_MULTICAST_LOOP);
TASS Belgium NV 131:4758606c9316 2075 } else {
tass 68:0847e35d08a6 2076 *(uint8_t *)value = 0;
tass 68:0847e35d08a6 2077 pico_err = PICO_ERR_EINVAL;
tass 68:0847e35d08a6 2078 return -1;
TASS Belgium NV 131:4758606c9316 2079 }
TASS Belgium NV 131:4758606c9316 2080
TASS Belgium NV 131:4758606c9316 2081 break;
tass 68:0847e35d08a6 2082 #endif /* PICO_SUPPORT_MCAST */
tass 68:0847e35d08a6 2083
tass 68:0847e35d08a6 2084 default:
TASS Belgium NV 131:4758606c9316 2085 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 2086 return -1;
TASS Belgium NV 131:4758606c9316 2087 }
tass 68:0847e35d08a6 2088
TASS Belgium NV 131:4758606c9316 2089 return 0;
tass 68:0847e35d08a6 2090 }
tass 68:0847e35d08a6 2091
tass 68:0847e35d08a6 2092
tass 68:0847e35d08a6 2093 int pico_socket_shutdown(struct pico_socket *s, int mode)
tass 68:0847e35d08a6 2094 {
TASS Belgium NV 131:4758606c9316 2095 if (!s) {
TASS Belgium NV 131:4758606c9316 2096 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 2097 return -1;
TASS Belgium NV 131:4758606c9316 2098 } else {
TASS Belgium NV 131:4758606c9316 2099 /* check if exists in tree */
TASS Belgium NV 131:4758606c9316 2100 /* See task #178 */
TASS Belgium NV 131:4758606c9316 2101 if (pico_check_socket(s) != 0) {
TASS Belgium NV 131:4758606c9316 2102 pico_free(s); /* close socket after bind or connect failed */
TASS Belgium NV 131:4758606c9316 2103 return 0;
TASS Belgium NV 131:4758606c9316 2104 }
tass 68:0847e35d08a6 2105 }
tass 68:0847e35d08a6 2106
tass 68:0847e35d08a6 2107 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 2108 if (PROTO(s) == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 2109 if (mode & PICO_SHUT_RDWR)
TASS Belgium NV 131:4758606c9316 2110 pico_socket_alter_state(s, PICO_SOCKET_STATE_CLOSED, PICO_SOCKET_STATE_CLOSING | PICO_SOCKET_STATE_BOUND | PICO_SOCKET_STATE_CONNECTED, 0);
TASS Belgium NV 131:4758606c9316 2111 else if (mode & PICO_SHUT_RD)
TASS Belgium NV 131:4758606c9316 2112 pico_socket_alter_state(s, 0, PICO_SOCKET_STATE_BOUND, 0);
TASS Belgium NV 131:4758606c9316 2113 }
TASS Belgium NV 131:4758606c9316 2114
tass 68:0847e35d08a6 2115 #endif
tass 68:0847e35d08a6 2116 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 2117 if (PROTO(s) == PICO_PROTO_TCP) {
TASS Belgium NV 131:4758606c9316 2118 if(mode & PICO_SHUT_RDWR)
TASS Belgium NV 131:4758606c9316 2119 {
TASS Belgium NV 131:4758606c9316 2120 pico_socket_alter_state(s, PICO_SOCKET_STATE_SHUT_LOCAL | PICO_SOCKET_STATE_SHUT_REMOTE, 0, 0);
TASS Belgium NV 131:4758606c9316 2121 pico_tcp_notify_closing(s);
TASS Belgium NV 131:4758606c9316 2122 }
TASS Belgium NV 131:4758606c9316 2123 else if (mode & PICO_SHUT_WR)
TASS Belgium NV 131:4758606c9316 2124 pico_socket_alter_state(s, PICO_SOCKET_STATE_SHUT_LOCAL, 0, 0);
TASS Belgium NV 131:4758606c9316 2125 else if (mode & PICO_SHUT_RD)
TASS Belgium NV 131:4758606c9316 2126 pico_socket_alter_state(s, PICO_SOCKET_STATE_SHUT_REMOTE, 0, 0);
tass 68:0847e35d08a6 2127
TASS Belgium NV 131:4758606c9316 2128 }
TASS Belgium NV 131:4758606c9316 2129
tass 68:0847e35d08a6 2130 #endif
TASS Belgium NV 131:4758606c9316 2131 return 0;
tass 68:0847e35d08a6 2132 }
tass 68:0847e35d08a6 2133
tass 68:0847e35d08a6 2134 int pico_socket_close(struct pico_socket *s)
tass 68:0847e35d08a6 2135 {
TASS Belgium NV 131:4758606c9316 2136 return pico_socket_shutdown(s, PICO_SHUT_RDWR);
tass 68:0847e35d08a6 2137 }
tass 68:0847e35d08a6 2138
tass 68:0847e35d08a6 2139 #ifdef PICO_SUPPORT_CRC
tass 68:0847e35d08a6 2140 static inline int pico_transport_crc_check(struct pico_frame *f)
tass 68:0847e35d08a6 2141 {
TASS Belgium NV 131:4758606c9316 2142 struct pico_ipv4_hdr *net_hdr = (struct pico_ipv4_hdr *) f->net_hdr;
TASS Belgium NV 131:4758606c9316 2143 struct pico_udp_hdr *udp_hdr = NULL;
TASS Belgium NV 131:4758606c9316 2144 uint16_t checksum_invalid = 1;
tass 68:0847e35d08a6 2145
TASS Belgium NV 131:4758606c9316 2146 switch (net_hdr->proto)
TASS Belgium NV 131:4758606c9316 2147 {
tass 68:0847e35d08a6 2148 case PICO_PROTO_TCP:
TASS Belgium NV 131:4758606c9316 2149 checksum_invalid = short_be(pico_tcp_checksum_ipv4(f));
TASS Belgium NV 131:4758606c9316 2150 /* dbg("TCP CRC validation == %u\n", checksum_invalid); */
TASS Belgium NV 131:4758606c9316 2151 if (checksum_invalid) {
TASS Belgium NV 131:4758606c9316 2152 /* dbg("TCP CRC: validation failed!\n"); */
TASS Belgium NV 131:4758606c9316 2153 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 2154 return 0;
TASS Belgium NV 131:4758606c9316 2155 }
TASS Belgium NV 131:4758606c9316 2156
TASS Belgium NV 131:4758606c9316 2157 break;
tass 68:0847e35d08a6 2158
tass 68:0847e35d08a6 2159 case PICO_PROTO_UDP:
TASS Belgium NV 131:4758606c9316 2160 udp_hdr = (struct pico_udp_hdr *) f->transport_hdr;
TASS Belgium NV 131:4758606c9316 2161 if (short_be(udp_hdr->crc)) {
TASS Belgium NV 131:4758606c9316 2162 checksum_invalid = short_be(pico_udp_checksum_ipv4(f));
TASS Belgium NV 131:4758606c9316 2163 /* dbg("UDP CRC validation == %u\n", checksum_invalid); */
TASS Belgium NV 131:4758606c9316 2164 if (checksum_invalid) {
TASS Belgium NV 131:4758606c9316 2165 /* dbg("UDP CRC: validation failed!\n"); */
TASS Belgium NV 131:4758606c9316 2166 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 2167 return 0;
TASS Belgium NV 131:4758606c9316 2168 }
tass 68:0847e35d08a6 2169 }
TASS Belgium NV 131:4758606c9316 2170
TASS Belgium NV 131:4758606c9316 2171 break;
tass 68:0847e35d08a6 2172
tass 68:0847e35d08a6 2173 default:
TASS Belgium NV 131:4758606c9316 2174 /* Do nothing */
TASS Belgium NV 131:4758606c9316 2175 break;
TASS Belgium NV 131:4758606c9316 2176 }
TASS Belgium NV 131:4758606c9316 2177 return 1;
tass 68:0847e35d08a6 2178 }
tass 68:0847e35d08a6 2179 #else
tass 68:0847e35d08a6 2180 static inline int pico_transport_crc_check(struct pico_frame *f)
tass 68:0847e35d08a6 2181 {
TASS Belgium NV 131:4758606c9316 2182 IGNORE_PARAMETER(f);
TASS Belgium NV 131:4758606c9316 2183 return 1;
tass 68:0847e35d08a6 2184 }
tass 68:0847e35d08a6 2185 #endif /* PICO_SUPPORT_CRC */
tass 68:0847e35d08a6 2186
tass 68:0847e35d08a6 2187 int pico_transport_process_in(struct pico_protocol *self, struct pico_frame *f)
tass 68:0847e35d08a6 2188 {
TASS Belgium NV 131:4758606c9316 2189 struct pico_trans *hdr = (struct pico_trans *) f->transport_hdr;
TASS Belgium NV 131:4758606c9316 2190 int ret = 0;
tass 68:0847e35d08a6 2191
TASS Belgium NV 131:4758606c9316 2192 if (!hdr) {
TASS Belgium NV 131:4758606c9316 2193 pico_err = PICO_ERR_EFAULT;
TASS Belgium NV 131:4758606c9316 2194 return -1;
TASS Belgium NV 131:4758606c9316 2195 }
tass 68:0847e35d08a6 2196
TASS Belgium NV 131:4758606c9316 2197 ret = pico_transport_crc_check(f);
TASS Belgium NV 131:4758606c9316 2198 if (ret < 1)
TASS Belgium NV 131:4758606c9316 2199 return ret;
TASS Belgium NV 131:4758606c9316 2200 else
TASS Belgium NV 131:4758606c9316 2201 ret = 0;
tass 68:0847e35d08a6 2202
TASS Belgium NV 131:4758606c9316 2203 if ((hdr) && (pico_socket_deliver(self, f, hdr->dport) == 0))
TASS Belgium NV 131:4758606c9316 2204 return ret;
tass 68:0847e35d08a6 2205
TASS Belgium NV 131:4758606c9316 2206 if (!IS_BCAST(f)) {
TASS Belgium NV 131:4758606c9316 2207 dbg("Socket not found... \n");
TASS Belgium NV 131:4758606c9316 2208 pico_notify_socket_unreachable(f);
tass 68:0847e35d08a6 2209 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 2210 /* if tcp protocol send RST segment */
TASS Belgium NV 131:4758606c9316 2211 /* if (self->proto_number == PICO_PROTO_TCP) */
TASS Belgium NV 131:4758606c9316 2212 /* pico_tcp_reply_rst(f); */
tass 68:0847e35d08a6 2213 #endif
TASS Belgium NV 131:4758606c9316 2214 ret = -1;
TASS Belgium NV 131:4758606c9316 2215 pico_err = PICO_ERR_ENOENT;
TASS Belgium NV 131:4758606c9316 2216 }
TASS Belgium NV 131:4758606c9316 2217
TASS Belgium NV 131:4758606c9316 2218 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 2219 return ret;
tass 68:0847e35d08a6 2220 }
tass 68:0847e35d08a6 2221
tass 68:0847e35d08a6 2222 #define SL_LOOP_MIN 1
tass 68:0847e35d08a6 2223
tass 125:96003ae6f1d8 2224 #ifdef PICO_SUPPORT_TCP
tass 95:f4ca916a26fe 2225 static int checkSocketSanity(struct pico_socket *s)
tass 95:f4ca916a26fe 2226 {
tass 95:f4ca916a26fe 2227
TASS Belgium NV 131:4758606c9316 2228 /* checking for pending connections */
tass picotcp@tass.be 133:5b075f5e141a 2229 if(TCP_STATE(s) == PICO_SOCKET_STATE_TCP_SYN_RECV) {
tass picotcp@tass.be 133:5b075f5e141a 2230 if((pico_time)(PICO_TIME_MS() - s->timestamp) >= PICO_SOCKET_BOUND_TIMEOUT)
TASS Belgium NV 131:4758606c9316 2231 return -1;
tass picotcp@tass.be 133:5b075f5e141a 2232 }
TASS Belgium NV 131:4758606c9316 2233
TASS Belgium NV 131:4758606c9316 2234 if((pico_time)(PICO_TIME_MS() - s->timestamp) >= PICO_SOCKET_TIMEOUT) {
TASS Belgium NV 131:4758606c9316 2235 /* checking for hanging sockets */
TASS Belgium NV 131:4758606c9316 2236 if((TCP_STATE(s) != PICO_SOCKET_STATE_TCP_LISTEN) && (TCP_STATE(s) != PICO_SOCKET_STATE_TCP_ESTABLISHED))
TASS Belgium NV 131:4758606c9316 2237 return -1;
TASS Belgium NV 131:4758606c9316 2238
TASS Belgium NV 131:4758606c9316 2239 /* if no activity, force the socket into closing state */
TASS Belgium NV 131:4758606c9316 2240 if( TCP_STATE(s) == PICO_SOCKET_STATE_TCP_ESTABLISHED )
TASS Belgium NV 131:4758606c9316 2241 {
TASS Belgium NV 131:4758606c9316 2242 s->wakeup(PICO_SOCK_EV_CLOSE, s);
TASS Belgium NV 131:4758606c9316 2243 pico_socket_close(s);
TASS Belgium NV 131:4758606c9316 2244 s->timestamp = PICO_TIME_MS();
TASS Belgium NV 131:4758606c9316 2245 }
TASS Belgium NV 131:4758606c9316 2246 }
TASS Belgium NV 131:4758606c9316 2247
TASS Belgium NV 131:4758606c9316 2248 return 0;
tass 95:f4ca916a26fe 2249 }
tass 125:96003ae6f1d8 2250 #endif
tass 95:f4ca916a26fe 2251
tass 68:0847e35d08a6 2252 int pico_sockets_loop(int loop_score)
tass 68:0847e35d08a6 2253 {
tass 125:96003ae6f1d8 2254 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 2255 static struct pico_tree_node *index_udp;
tass 125:96003ae6f1d8 2256 #endif
tass 125:96003ae6f1d8 2257
tass 125:96003ae6f1d8 2258 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 2259 static struct pico_tree_node*index_tcp;
tass 125:96003ae6f1d8 2260 #endif
tass 68:0847e35d08a6 2261
TASS Belgium NV 131:4758606c9316 2262 struct pico_sockport *start;
TASS Belgium NV 131:4758606c9316 2263 struct pico_socket *s;
tass 68:0847e35d08a6 2264
tass 68:0847e35d08a6 2265 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 2266 struct pico_frame *f;
tass 68:0847e35d08a6 2267
tass 68:0847e35d08a6 2268 if (sp_udp == NULL)
tass 68:0847e35d08a6 2269 {
TASS Belgium NV 131:4758606c9316 2270 index_udp = pico_tree_firstNode(UDPTable.root);
TASS Belgium NV 131:4758606c9316 2271 sp_udp = index_udp->keyValue;
tass 68:0847e35d08a6 2272 }
TASS Belgium NV 131:4758606c9316 2273
TASS Belgium NV 131:4758606c9316 2274 /* init start node */
TASS Belgium NV 131:4758606c9316 2275 start = sp_udp;
TASS Belgium NV 131:4758606c9316 2276
TASS Belgium NV 131:4758606c9316 2277 /* round-robin all transport protocols, break if traversed all protocols */
TASS Belgium NV 131:4758606c9316 2278 while (loop_score > SL_LOOP_MIN && sp_udp != NULL) {
TASS Belgium NV 131:4758606c9316 2279 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 2280
TASS Belgium NV 131:4758606c9316 2281 pico_tree_foreach(index, &sp_udp->socks){
TASS Belgium NV 131:4758606c9316 2282 s = index->keyValue;
TASS Belgium NV 131:4758606c9316 2283 f = pico_dequeue(&s->q_out);
TASS Belgium NV 131:4758606c9316 2284 while (f && (loop_score > 0)) {
TASS Belgium NV 131:4758606c9316 2285 pico_proto_udp.push(&pico_proto_udp, f);
TASS Belgium NV 131:4758606c9316 2286 loop_score -= 1;
TASS Belgium NV 131:4758606c9316 2287 f = pico_dequeue(&s->q_out);
TASS Belgium NV 131:4758606c9316 2288 }
TASS Belgium NV 131:4758606c9316 2289 }
TASS Belgium NV 131:4758606c9316 2290
TASS Belgium NV 131:4758606c9316 2291 index_udp = pico_tree_next(index_udp);
TASS Belgium NV 131:4758606c9316 2292 sp_udp = index_udp->keyValue;
TASS Belgium NV 131:4758606c9316 2293
TASS Belgium NV 131:4758606c9316 2294 if (sp_udp == NULL)
TASS Belgium NV 131:4758606c9316 2295 {
TASS Belgium NV 131:4758606c9316 2296 index_udp = pico_tree_firstNode(UDPTable.root);
TASS Belgium NV 131:4758606c9316 2297 sp_udp = index_udp->keyValue;
TASS Belgium NV 131:4758606c9316 2298 }
TASS Belgium NV 131:4758606c9316 2299
TASS Belgium NV 131:4758606c9316 2300 if (sp_udp == start)
TASS Belgium NV 131:4758606c9316 2301 break;
TASS Belgium NV 131:4758606c9316 2302 }
tass 68:0847e35d08a6 2303 #endif
tass 68:0847e35d08a6 2304
tass 68:0847e35d08a6 2305 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 2306 if (sp_tcp == NULL)
TASS Belgium NV 131:4758606c9316 2307 {
TASS Belgium NV 131:4758606c9316 2308 index_tcp = pico_tree_firstNode(TCPTable.root);
TASS Belgium NV 131:4758606c9316 2309 sp_tcp = index_tcp->keyValue;
tass 95:f4ca916a26fe 2310 }
tass 68:0847e35d08a6 2311
TASS Belgium NV 131:4758606c9316 2312 /* init start node */
TASS Belgium NV 131:4758606c9316 2313 start = sp_tcp;
tass 68:0847e35d08a6 2314
TASS Belgium NV 131:4758606c9316 2315 while (loop_score > SL_LOOP_MIN && sp_tcp != NULL) {
TASS Belgium NV 131:4758606c9316 2316 struct pico_tree_node *index = NULL, *safe_index = NULL;
TASS Belgium NV 131:4758606c9316 2317 pico_tree_foreach_safe(index, &sp_tcp->socks, safe_index){
TASS Belgium NV 131:4758606c9316 2318 s = index->keyValue;
TASS Belgium NV 131:4758606c9316 2319 loop_score = pico_tcp_output(s, loop_score);
TASS Belgium NV 131:4758606c9316 2320 if ((s->ev_pending) && s->wakeup) {
TASS Belgium NV 131:4758606c9316 2321 s->wakeup(s->ev_pending, s);
TASS Belgium NV 131:4758606c9316 2322 if(!s->parent)
TASS Belgium NV 131:4758606c9316 2323 s->ev_pending = 0;
TASS Belgium NV 131:4758606c9316 2324 }
TASS Belgium NV 131:4758606c9316 2325
TASS Belgium NV 131:4758606c9316 2326 if (loop_score <= 0) {
TASS Belgium NV 131:4758606c9316 2327 loop_score = 0;
TASS Belgium NV 131:4758606c9316 2328 break;
TASS Belgium NV 131:4758606c9316 2329 }
tass 68:0847e35d08a6 2330
TASS Belgium NV 131:4758606c9316 2331 if(checkSocketSanity(s) < 0)
TASS Belgium NV 131:4758606c9316 2332 {
TASS Belgium NV 131:4758606c9316 2333 pico_socket_del(s);
TASS Belgium NV 131:4758606c9316 2334 index_tcp = NULL; /* forcing the restart of loop */
TASS Belgium NV 131:4758606c9316 2335 sp_tcp = NULL;
TASS Belgium NV 131:4758606c9316 2336 break;
TASS Belgium NV 131:4758606c9316 2337 }
TASS Belgium NV 131:4758606c9316 2338 }
TASS Belgium NV 131:4758606c9316 2339
TASS Belgium NV 131:4758606c9316 2340 /* check if RB_FOREACH ended, if not, break to keep the cur sp_tcp */
TASS Belgium NV 131:4758606c9316 2341 if (!index_tcp || (index && index->keyValue))
TASS Belgium NV 131:4758606c9316 2342 break;
TASS Belgium NV 131:4758606c9316 2343
TASS Belgium NV 131:4758606c9316 2344 index_tcp = pico_tree_next(index_tcp);
TASS Belgium NV 131:4758606c9316 2345 sp_tcp = index_tcp->keyValue;
TASS Belgium NV 131:4758606c9316 2346
TASS Belgium NV 131:4758606c9316 2347 if (sp_tcp == NULL)
TASS Belgium NV 131:4758606c9316 2348 {
TASS Belgium NV 131:4758606c9316 2349 index_tcp = pico_tree_firstNode(TCPTable.root);
TASS Belgium NV 131:4758606c9316 2350 sp_tcp = index_tcp->keyValue;
TASS Belgium NV 131:4758606c9316 2351 }
TASS Belgium NV 131:4758606c9316 2352
TASS Belgium NV 131:4758606c9316 2353 if (sp_tcp == start)
TASS Belgium NV 131:4758606c9316 2354 break;
tass 68:0847e35d08a6 2355 }
tass 68:0847e35d08a6 2356 #endif
tass 68:0847e35d08a6 2357
TASS Belgium NV 131:4758606c9316 2358 return loop_score;
tass 68:0847e35d08a6 2359 }
tass 68:0847e35d08a6 2360
tass 68:0847e35d08a6 2361
tass 70:cd218dd180e5 2362 struct pico_frame *pico_socket_frame_alloc(struct pico_socket *s, uint16_t len)
tass 68:0847e35d08a6 2363 {
TASS Belgium NV 131:4758606c9316 2364 struct pico_frame *f = NULL;
tass 68:0847e35d08a6 2365
tass 68:0847e35d08a6 2366 #ifdef PICO_SUPPORT_IPV6
TASS Belgium NV 131:4758606c9316 2367 if (IS_SOCK_IPV6(s))
TASS Belgium NV 131:4758606c9316 2368 f = pico_proto_ipv6.alloc(&pico_proto_ipv6, len);
TASS Belgium NV 131:4758606c9316 2369
tass 68:0847e35d08a6 2370 #endif
tass 68:0847e35d08a6 2371
tass 68:0847e35d08a6 2372 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 2373 if (IS_SOCK_IPV4(s))
TASS Belgium NV 131:4758606c9316 2374 f = pico_proto_ipv4.alloc(&pico_proto_ipv4, (uint16_t)len);
TASS Belgium NV 131:4758606c9316 2375
tass 68:0847e35d08a6 2376 #endif
TASS Belgium NV 131:4758606c9316 2377 if (!f) {
TASS Belgium NV 131:4758606c9316 2378 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 2379 return f;
TASS Belgium NV 131:4758606c9316 2380 }
TASS Belgium NV 131:4758606c9316 2381
TASS Belgium NV 131:4758606c9316 2382 f->payload = f->transport_hdr;
TASS Belgium NV 131:4758606c9316 2383 f->payload_len = len;
TASS Belgium NV 131:4758606c9316 2384 f->sock = s;
tass 68:0847e35d08a6 2385 return f;
tass 68:0847e35d08a6 2386 }
tass 68:0847e35d08a6 2387
tass 68:0847e35d08a6 2388 int pico_transport_error(struct pico_frame *f, uint8_t proto, int code)
tass 68:0847e35d08a6 2389 {
TASS Belgium NV 131:4758606c9316 2390 int ret = -1;
TASS Belgium NV 131:4758606c9316 2391 struct pico_trans *trans = (struct pico_trans*) f->transport_hdr;
TASS Belgium NV 131:4758606c9316 2392 struct pico_sockport *port = NULL;
TASS Belgium NV 131:4758606c9316 2393 struct pico_socket *s = NULL;
TASS Belgium NV 131:4758606c9316 2394 switch (proto) {
tass 68:0847e35d08a6 2395
tass 68:0847e35d08a6 2396
tass 68:0847e35d08a6 2397 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 2398 case PICO_PROTO_UDP:
TASS Belgium NV 131:4758606c9316 2399 port = pico_get_sockport(proto, trans->sport);
TASS Belgium NV 131:4758606c9316 2400 break;
tass 68:0847e35d08a6 2401 #endif
tass 68:0847e35d08a6 2402
tass 68:0847e35d08a6 2403 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 2404 case PICO_PROTO_TCP:
TASS Belgium NV 131:4758606c9316 2405 port = pico_get_sockport(proto, trans->sport);
TASS Belgium NV 131:4758606c9316 2406 break;
tass 68:0847e35d08a6 2407 #endif
tass 68:0847e35d08a6 2408
TASS Belgium NV 131:4758606c9316 2409 default:
TASS Belgium NV 131:4758606c9316 2410 /* Protocol not available */
TASS Belgium NV 131:4758606c9316 2411 ret = -1;
TASS Belgium NV 131:4758606c9316 2412 }
TASS Belgium NV 131:4758606c9316 2413 if (port) {
TASS Belgium NV 131:4758606c9316 2414 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 2415 ret = 0;
tass 68:0847e35d08a6 2416
TASS Belgium NV 131:4758606c9316 2417 pico_tree_foreach(index, &port->socks) {
TASS Belgium NV 131:4758606c9316 2418 s = index->keyValue;
TASS Belgium NV 131:4758606c9316 2419 if (trans->dport == s->remote_port) {
TASS Belgium NV 131:4758606c9316 2420 if (s->wakeup) {
TASS Belgium NV 131:4758606c9316 2421 /* dbg("SOCKET ERROR FROM ICMP NOTIFICATION. (icmp code= %d)\n\n", code); */
TASS Belgium NV 131:4758606c9316 2422 switch(code) {
TASS Belgium NV 131:4758606c9316 2423 case PICO_ICMP_UNREACH_PROTOCOL:
TASS Belgium NV 131:4758606c9316 2424 pico_err = PICO_ERR_EPROTO;
TASS Belgium NV 131:4758606c9316 2425 break;
TASS Belgium NV 131:4758606c9316 2426
TASS Belgium NV 131:4758606c9316 2427 case PICO_ICMP_UNREACH_PORT:
TASS Belgium NV 131:4758606c9316 2428 pico_err = PICO_ERR_ECONNREFUSED;
TASS Belgium NV 131:4758606c9316 2429 break;
tass 68:0847e35d08a6 2430
TASS Belgium NV 131:4758606c9316 2431 case PICO_ICMP_UNREACH_NET:
TASS Belgium NV 131:4758606c9316 2432 case PICO_ICMP_UNREACH_NET_PROHIB:
TASS Belgium NV 131:4758606c9316 2433 case PICO_ICMP_UNREACH_NET_UNKNOWN:
TASS Belgium NV 131:4758606c9316 2434 pico_err = PICO_ERR_ENETUNREACH;
TASS Belgium NV 131:4758606c9316 2435 break;
tass 68:0847e35d08a6 2436
TASS Belgium NV 131:4758606c9316 2437 default:
TASS Belgium NV 131:4758606c9316 2438 pico_err = PICO_ERR_EHOSTUNREACH;
TASS Belgium NV 131:4758606c9316 2439 }
TASS Belgium NV 131:4758606c9316 2440 s->state |= PICO_SOCKET_STATE_SHUT_REMOTE;
TASS Belgium NV 131:4758606c9316 2441 s->wakeup(PICO_SOCK_EV_ERR, s);
tass 122:5b1e9de8bf7f 2442
TASS Belgium NV 131:4758606c9316 2443 }
TASS Belgium NV 131:4758606c9316 2444
TASS Belgium NV 131:4758606c9316 2445 break;
TASS Belgium NV 131:4758606c9316 2446 }
tass 68:0847e35d08a6 2447 }
tass 68:0847e35d08a6 2448 }
TASS Belgium NV 131:4758606c9316 2449
TASS Belgium NV 131:4758606c9316 2450 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 2451 return ret;
tass 68:0847e35d08a6 2452 }
tass 68:0847e35d08a6 2453 #endif
tass 68:0847e35d08a6 2454 #endif