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 Belgium NV
Date:
Mon Dec 16 11:25:54 2013 +0100
Revision:
131:4758606c9316
Parent:
128:ae39e6e81531
Child:
133:5b075f5e141a
Syncronized with 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 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 646 if(s->parent)
TASS Belgium NV 131:4758606c9316 647 s->parent->number_of_pending_conn--;
tass 128:ae39e6e81531 648
TASS Belgium NV 131:4758606c9316 649 #endif
TASS Belgium NV 131:4758606c9316 650
TASS Belgium NV 131:4758606c9316 651 socket_clean_queues(s);
TASS Belgium NV 131:4758606c9316 652 pico_free(s);
tass 68:0847e35d08a6 653 }
tass 68:0847e35d08a6 654
tass 70:cd218dd180e5 655 int8_t pico_socket_del(struct pico_socket *s)
tass 68:0847e35d08a6 656 {
TASS Belgium NV 131:4758606c9316 657 struct pico_sockport *sp = pico_get_sockport(PROTO(s), s->local_port);
tass 68:0847e35d08a6 658
TASS Belgium NV 131:4758606c9316 659 if (!sp) {
TASS Belgium NV 131:4758606c9316 660 pico_err = PICO_ERR_ENXIO;
TASS Belgium NV 131:4758606c9316 661 return -1;
tass 68:0847e35d08a6 662 }
tass 68:0847e35d08a6 663
TASS Belgium NV 131:4758606c9316 664 LOCK(Mutex);
TASS Belgium NV 131:4758606c9316 665 pico_tree_delete(&sp->socks, s);
TASS Belgium NV 131:4758606c9316 666 s->net = NULL;
TASS Belgium NV 131:4758606c9316 667 if(pico_tree_empty(&sp->socks)) {
TASS Belgium NV 131:4758606c9316 668 if (PROTO(s) == PICO_PROTO_UDP)
TASS Belgium NV 131:4758606c9316 669 {
TASS Belgium NV 131:4758606c9316 670 pico_tree_delete(&UDPTable, sp);
TASS Belgium NV 131:4758606c9316 671 }
TASS Belgium NV 131:4758606c9316 672 else if (PROTO(s) == PICO_PROTO_TCP)
TASS Belgium NV 131:4758606c9316 673 {
TASS Belgium NV 131:4758606c9316 674 pico_tree_delete(&TCPTable, sp);
TASS Belgium NV 131:4758606c9316 675 }
tass 68:0847e35d08a6 676
TASS Belgium NV 131:4758606c9316 677 if(sp_tcp == sp) sp_tcp = NULL;
TASS Belgium NV 131:4758606c9316 678
TASS Belgium NV 131:4758606c9316 679 if(sp_udp == sp) sp_udp = NULL;
tass 68:0847e35d08a6 680
TASS Belgium NV 131:4758606c9316 681 pico_free(sp);
TASS Belgium NV 131:4758606c9316 682
TASS Belgium NV 131:4758606c9316 683 }
tass 68:0847e35d08a6 684
tass 68:0847e35d08a6 685 #ifdef PICO_SUPPORT_MCAST
TASS Belgium NV 131:4758606c9316 686 do {
TASS Belgium NV 131:4758606c9316 687 int filter_mode;
TASS Belgium NV 131:4758606c9316 688 struct pico_tree_node *index = NULL, *_tmp = NULL, *index2 = NULL, *_tmp2 = NULL;
TASS Belgium NV 131:4758606c9316 689 struct pico_mcast_listen *listen = NULL;
TASS Belgium NV 131:4758606c9316 690 struct pico_ip4 *source = NULL;
TASS Belgium NV 131:4758606c9316 691 if (s->MCASTListen) {
TASS Belgium NV 131:4758606c9316 692 pico_tree_delete(&MCASTSockets, s);
TASS Belgium NV 131:4758606c9316 693 pico_tree_foreach_safe(index, s->MCASTListen, _tmp)
TASS Belgium NV 131:4758606c9316 694 {
TASS Belgium NV 131:4758606c9316 695 listen = index->keyValue;
TASS Belgium NV 131:4758606c9316 696 pico_tree_foreach_safe(index2, &listen->MCASTSources, _tmp2)
TASS Belgium NV 131:4758606c9316 697 {
TASS Belgium NV 131:4758606c9316 698 source = index->keyValue;
TASS Belgium NV 131:4758606c9316 699 pico_tree_delete(&listen->MCASTSources, source);
TASS Belgium NV 131:4758606c9316 700 pico_free(source);
TASS Belgium NV 131:4758606c9316 701 }
TASS Belgium NV 131:4758606c9316 702 filter_mode = pico_socket_aggregate_mcastfilters(&listen->mcast_link, &listen->mcast_group);
TASS Belgium NV 131:4758606c9316 703 if (filter_mode >= 0)
TASS Belgium NV 131:4758606c9316 704 pico_ipv4_mcast_leave(&listen->mcast_link, &listen->mcast_group, 1, (uint8_t)filter_mode, &MCASTFilter);
TASS Belgium NV 131:4758606c9316 705
TASS Belgium NV 131:4758606c9316 706 pico_tree_delete(s->MCASTListen, listen);
TASS Belgium NV 131:4758606c9316 707 pico_free(listen);
TASS Belgium NV 131:4758606c9316 708 }
TASS Belgium NV 131:4758606c9316 709 pico_free(s->MCASTListen);
tass 68:0847e35d08a6 710 }
TASS Belgium NV 131:4758606c9316 711 } while (0);
tass 68:0847e35d08a6 712 #endif
tass 68:0847e35d08a6 713
TASS Belgium NV 131:4758606c9316 714 s->state = PICO_SOCKET_STATE_CLOSED;
TASS Belgium NV 131:4758606c9316 715 pico_timer_add(3000, socket_garbage_collect, s);
TASS Belgium NV 131:4758606c9316 716 UNLOCK(Mutex);
TASS Belgium NV 131:4758606c9316 717 return 0;
tass 68:0847e35d08a6 718 }
tass 68:0847e35d08a6 719
tass 70:cd218dd180e5 720 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 721 {
TASS Belgium NV 131:4758606c9316 722 struct pico_sockport *sp;
TASS Belgium NV 131:4758606c9316 723 if (more_states & PICO_SOCKET_STATE_BOUND)
TASS Belgium NV 131:4758606c9316 724 return pico_socket_add(s);
tass 68:0847e35d08a6 725
TASS Belgium NV 131:4758606c9316 726 if (less_states & PICO_SOCKET_STATE_BOUND)
TASS Belgium NV 131:4758606c9316 727 return pico_socket_del(s);
tass 68:0847e35d08a6 728
TASS Belgium NV 131:4758606c9316 729 sp = pico_get_sockport(PROTO(s), s->local_port);
TASS Belgium NV 131:4758606c9316 730 if (!sp) {
TASS Belgium NV 131:4758606c9316 731 pico_err = PICO_ERR_ENXIO;
TASS Belgium NV 131:4758606c9316 732 return -1;
TASS Belgium NV 131:4758606c9316 733 }
tass 68:0847e35d08a6 734
TASS Belgium NV 131:4758606c9316 735 s->state |= more_states;
TASS Belgium NV 131:4758606c9316 736 s->state = (uint16_t)(s->state & (~less_states));
TASS Belgium NV 131:4758606c9316 737 if (tcp_state) {
TASS Belgium NV 131:4758606c9316 738 s->state &= 0x00FF;
TASS Belgium NV 131:4758606c9316 739 s->state |= tcp_state;
TASS Belgium NV 131:4758606c9316 740 }
tass 68:0847e35d08a6 741
TASS Belgium NV 131:4758606c9316 742 return 0;
tass 68:0847e35d08a6 743 }
tass 68:0847e35d08a6 744
tass 68:0847e35d08a6 745 static int pico_socket_deliver(struct pico_protocol *p, struct pico_frame *f, uint16_t localport)
tass 68:0847e35d08a6 746 {
TASS Belgium NV 131:4758606c9316 747 struct pico_frame *cpy = NULL;
TASS Belgium NV 131:4758606c9316 748 struct pico_sockport *sp = NULL;
TASS Belgium NV 131:4758606c9316 749 struct pico_socket *s = NULL;
TASS Belgium NV 131:4758606c9316 750 struct pico_tree_node *index = NULL;
TASS Belgium NV 131:4758606c9316 751 struct pico_tree_node *_tmp;
TASS Belgium NV 131:4758606c9316 752 struct pico_trans *tr = (struct pico_trans *) f->transport_hdr;
tass 68:0847e35d08a6 753 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 754 struct pico_ipv4_hdr *ip4hdr;
tass 68:0847e35d08a6 755 #endif
tass 68:0847e35d08a6 756 #ifdef PICO_SUPPORT_IPV6
TASS Belgium NV 131:4758606c9316 757 struct pico_ipv6_hdr *ip6hdr;
tass 68:0847e35d08a6 758 #endif
tass 68:0847e35d08a6 759
tass 125:96003ae6f1d8 760 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 761 struct pico_socket *found = NULL;
tass 125:96003ae6f1d8 762 #endif
tass 125:96003ae6f1d8 763
TASS Belgium NV 131:4758606c9316 764 if (!tr)
TASS Belgium NV 131:4758606c9316 765 return -1;
tass 68:0847e35d08a6 766
TASS Belgium NV 131:4758606c9316 767 sp = pico_get_sockport(p->proto_number, localport);
tass 68:0847e35d08a6 768
TASS Belgium NV 131:4758606c9316 769 if (!sp) {
TASS Belgium NV 131:4758606c9316 770 dbg("No such port %d\n", short_be(localport));
TASS Belgium NV 131:4758606c9316 771 return -1;
TASS Belgium NV 131:4758606c9316 772 }
tass 68:0847e35d08a6 773
tass 68:0847e35d08a6 774 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 775 if (p->proto_number == PICO_PROTO_TCP) {
TASS Belgium NV 131:4758606c9316 776 pico_tree_foreach_safe(index, &sp->socks, _tmp){
TASS Belgium NV 131:4758606c9316 777 s = index->keyValue;
TASS Belgium NV 131:4758606c9316 778 /* 4-tuple identification of socket (port-IP) */
tass 68:0847e35d08a6 779 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 780 if (IS_IPV4(f)) {
TASS Belgium NV 131:4758606c9316 781 struct pico_ip4 s_local, s_remote, p_src, p_dst;
TASS Belgium NV 131:4758606c9316 782 ip4hdr = (struct pico_ipv4_hdr*)(f->net_hdr);
TASS Belgium NV 131:4758606c9316 783 s_local.addr = s->local_addr.ip4.addr;
TASS Belgium NV 131:4758606c9316 784 s_remote.addr = s->remote_addr.ip4.addr;
TASS Belgium NV 131:4758606c9316 785 p_src.addr = ip4hdr->src.addr;
TASS Belgium NV 131:4758606c9316 786 p_dst.addr = ip4hdr->dst.addr;
TASS Belgium NV 131:4758606c9316 787 if ((s->remote_port == tr->sport) && /* remote port check */
TASS Belgium NV 131:4758606c9316 788 (s_remote.addr == p_src.addr) && /* remote addr check */
TASS Belgium NV 131:4758606c9316 789 ((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 790 found = s;
TASS Belgium NV 131:4758606c9316 791 break;
TASS Belgium NV 131:4758606c9316 792 } else if ((s->remote_port == 0) && /* not connected... listening */
TASS Belgium NV 131:4758606c9316 793 ((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 794 /* listen socket */
TASS Belgium NV 131:4758606c9316 795 found = s;
TASS Belgium NV 131:4758606c9316 796 }
TASS Belgium NV 131:4758606c9316 797 }
TASS Belgium NV 131:4758606c9316 798
tass 68:0847e35d08a6 799 #endif
tass 68:0847e35d08a6 800 #ifdef PICO_SUPPORT_IPV6 /* XXX TODO make compare for ipv6 addresses */
TASS Belgium NV 131:4758606c9316 801 if (IS_IPV6(f)) {
TASS Belgium NV 131:4758606c9316 802 ip6hdr = (struct pico_ipv6_hdr*)(f->net_hdr);
TASS Belgium NV 131:4758606c9316 803 if ((s->remote_port == localport)) { /* && (((struct pico_ip6) s->remote_addr.ip6).addr == ((struct pico_ip6)(ip6hdr->src)).addr) ) { */
TASS Belgium NV 131:4758606c9316 804 found = s;
TASS Belgium NV 131:4758606c9316 805 break;
TASS Belgium NV 131:4758606c9316 806 } else if (s->remote_port == 0) {
TASS Belgium NV 131:4758606c9316 807 /* listen socket */
TASS Belgium NV 131:4758606c9316 808 found = s;
TASS Belgium NV 131:4758606c9316 809 }
TASS Belgium NV 131:4758606c9316 810 }
TASS Belgium NV 131:4758606c9316 811
TASS Belgium NV 131:4758606c9316 812 #endif
TASS Belgium NV 131:4758606c9316 813 } /* FOREACH */
TASS Belgium NV 131:4758606c9316 814 if (found != NULL) {
TASS Belgium NV 131:4758606c9316 815 pico_tcp_input(found, f);
TASS Belgium NV 131:4758606c9316 816 if ((found->ev_pending) && found->wakeup) {
TASS Belgium NV 131:4758606c9316 817 found->wakeup(found->ev_pending, found);
TASS Belgium NV 131:4758606c9316 818 if(!found->parent)
TASS Belgium NV 131:4758606c9316 819 found->ev_pending = 0;
TASS Belgium NV 131:4758606c9316 820 }
TASS Belgium NV 131:4758606c9316 821
TASS Belgium NV 131:4758606c9316 822 return 0;
TASS Belgium NV 131:4758606c9316 823 } else {
TASS Belgium NV 131:4758606c9316 824 dbg("SOCKET> mmm something wrong (prob sockport)\n");
TASS Belgium NV 131:4758606c9316 825 return -1;
tass 68:0847e35d08a6 826 }
TASS Belgium NV 131:4758606c9316 827 } /* TCP CASE */
TASS Belgium NV 131:4758606c9316 828
tass 68:0847e35d08a6 829 #endif
tass 68:0847e35d08a6 830
tass 68:0847e35d08a6 831 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 832 if (p->proto_number == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 833 pico_tree_foreach_safe(index, &sp->socks, _tmp){
TASS Belgium NV 131:4758606c9316 834 s = index->keyValue;
TASS Belgium NV 131:4758606c9316 835 if (IS_IPV4(f)) { /* IPV4 */
TASS Belgium NV 131:4758606c9316 836 struct pico_ip4 s_local, p_dst;
TASS Belgium NV 131:4758606c9316 837 ip4hdr = (struct pico_ipv4_hdr*)(f->net_hdr);
TASS Belgium NV 131:4758606c9316 838 s_local.addr = s->local_addr.ip4.addr;
TASS Belgium NV 131:4758606c9316 839 p_dst.addr = ip4hdr->dst.addr;
TASS Belgium NV 131:4758606c9316 840 if ((pico_ipv4_is_broadcast(p_dst.addr)) || pico_ipv4_is_multicast(p_dst.addr)) {
TASS Belgium NV 131:4758606c9316 841 struct pico_device *dev = pico_ipv4_link_find(&s->local_addr.ip4);
TASS Belgium NV 131:4758606c9316 842 if (pico_ipv4_is_multicast(p_dst.addr) && (pico_socket_mcast_filter(s, &ip4hdr->dst, &ip4hdr->src) < 0))
TASS Belgium NV 131:4758606c9316 843 return -1;
TASS Belgium NV 131:4758606c9316 844
TASS Belgium NV 131:4758606c9316 845 if ((s_local.addr == PICO_IPV4_INADDR_ANY) || /* If our local ip is ANY, or.. */
TASS Belgium NV 131:4758606c9316 846 (dev == f->dev)) { /* the source of the bcast packet is a neighbor... */
TASS Belgium NV 131:4758606c9316 847 cpy = pico_frame_copy(f);
TASS Belgium NV 131:4758606c9316 848 if (!cpy)
TASS Belgium NV 131:4758606c9316 849 return -1;
TASS Belgium NV 131:4758606c9316 850
TASS Belgium NV 131:4758606c9316 851 if (pico_enqueue(&s->q_in, cpy) > 0) {
TASS Belgium NV 131:4758606c9316 852 if (s->wakeup)
TASS Belgium NV 131:4758606c9316 853 s->wakeup(PICO_SOCK_EV_RD, s);
TASS Belgium NV 131:4758606c9316 854 }
TASS Belgium NV 131:4758606c9316 855 else
TASS Belgium NV 131:4758606c9316 856 pico_frame_discard(cpy);
tass 110:0ece1bbbd36e 857
TASS Belgium NV 131:4758606c9316 858 }
TASS Belgium NV 131:4758606c9316 859 } else if ((s_local.addr == PICO_IPV4_INADDR_ANY) || (s_local.addr == p_dst.addr))
TASS Belgium NV 131:4758606c9316 860 { /* Either local socket is ANY, or matches dst */
TASS Belgium NV 131:4758606c9316 861 cpy = pico_frame_copy(f);
TASS Belgium NV 131:4758606c9316 862 if (!cpy)
TASS Belgium NV 131:4758606c9316 863 return -1;
TASS Belgium NV 131:4758606c9316 864
TASS Belgium NV 131:4758606c9316 865 if (pico_enqueue(&s->q_in, cpy) > 0) {
TASS Belgium NV 131:4758606c9316 866 if (s->wakeup)
TASS Belgium NV 131:4758606c9316 867 s->wakeup(PICO_SOCK_EV_RD, s);
TASS Belgium NV 131:4758606c9316 868 }
TASS Belgium NV 131:4758606c9316 869 else
TASS Belgium NV 131:4758606c9316 870 pico_frame_discard(cpy);
TASS Belgium NV 131:4758606c9316 871 }
TASS Belgium NV 131:4758606c9316 872 } else {
TASS Belgium NV 131:4758606c9316 873 /*... IPv6 */
TASS Belgium NV 131:4758606c9316 874 }
TASS Belgium NV 131:4758606c9316 875 } /* FOREACH */
TASS Belgium NV 131:4758606c9316 876 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 877 if (s)
TASS Belgium NV 131:4758606c9316 878 return 0;
TASS Belgium NV 131:4758606c9316 879 else
tass 68:0847e35d08a6 880 return -1;
TASS Belgium NV 131:4758606c9316 881 }
TASS Belgium NV 131:4758606c9316 882
tass 68:0847e35d08a6 883 #endif
TASS Belgium NV 131:4758606c9316 884 return -1;
tass 68:0847e35d08a6 885 }
tass 68:0847e35d08a6 886
tass 68:0847e35d08a6 887 struct pico_socket *pico_socket_open(uint16_t net, uint16_t proto, void (*wakeup)(uint16_t ev, struct pico_socket *))
tass 68:0847e35d08a6 888 {
tass 68:0847e35d08a6 889
TASS Belgium NV 131:4758606c9316 890 struct pico_socket *s = NULL;
tass 68:0847e35d08a6 891
tass 68:0847e35d08a6 892 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 893 if (proto == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 894 s = pico_udp_open();
TASS Belgium NV 131:4758606c9316 895 s->proto = &pico_proto_udp;
TASS Belgium NV 131:4758606c9316 896 s->q_in.overhead = s->q_out.overhead = UDP_FRAME_OVERHEAD;
TASS Belgium NV 131:4758606c9316 897 }
TASS Belgium NV 131:4758606c9316 898
tass 68:0847e35d08a6 899 #endif
tass 68:0847e35d08a6 900
tass 68:0847e35d08a6 901 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 902 if (proto == PICO_PROTO_TCP) {
TASS Belgium NV 131:4758606c9316 903 s = pico_tcp_open();
TASS Belgium NV 131:4758606c9316 904 s->proto = &pico_proto_tcp;
TASS Belgium NV 131:4758606c9316 905 /*check if Nagle enabled */
TASS Belgium NV 131:4758606c9316 906 if (!IS_NAGLE_ENABLED(s))
TASS Belgium NV 131:4758606c9316 907 dbg("ERROR Nagle should be enabled here\n\n");
TASS Belgium NV 131:4758606c9316 908 }
TASS Belgium NV 131:4758606c9316 909
tass 68:0847e35d08a6 910 #endif
tass 68:0847e35d08a6 911
TASS Belgium NV 131:4758606c9316 912 if (!s) {
TASS Belgium NV 131:4758606c9316 913 pico_err = PICO_ERR_EPROTONOSUPPORT;
TASS Belgium NV 131:4758606c9316 914 return NULL;
TASS Belgium NV 131:4758606c9316 915 }
tass 68:0847e35d08a6 916
tass 68:0847e35d08a6 917 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 918 if (net == PICO_PROTO_IPV4)
TASS Belgium NV 131:4758606c9316 919 s->net = &pico_proto_ipv4;
TASS Belgium NV 131:4758606c9316 920
tass 68:0847e35d08a6 921 #endif
tass 68:0847e35d08a6 922
tass 68:0847e35d08a6 923 #ifdef PICO_SUPPORT_IPV6
TASS Belgium NV 131:4758606c9316 924 if (net == PICO_PROTO_IPV6)
TASS Belgium NV 131:4758606c9316 925 s->net = &pico_proto_ipv6;
TASS Belgium NV 131:4758606c9316 926
tass 68:0847e35d08a6 927 #endif
tass 68:0847e35d08a6 928
TASS Belgium NV 131:4758606c9316 929 s->q_in.max_size = PICO_DEFAULT_SOCKETQ;
TASS Belgium NV 131:4758606c9316 930 s->q_out.max_size = PICO_DEFAULT_SOCKETQ;
tass 110:0ece1bbbd36e 931
TASS Belgium NV 131:4758606c9316 932 s->wakeup = wakeup;
tass 68:0847e35d08a6 933
TASS Belgium NV 131:4758606c9316 934 if (!s->net) {
TASS Belgium NV 131:4758606c9316 935 pico_free(s);
TASS Belgium NV 131:4758606c9316 936 pico_err = PICO_ERR_ENETUNREACH;
TASS Belgium NV 131:4758606c9316 937 return NULL;
TASS Belgium NV 131:4758606c9316 938 }
TASS Belgium NV 131:4758606c9316 939
TASS Belgium NV 131:4758606c9316 940 return s;
tass 68:0847e35d08a6 941 }
tass 68:0847e35d08a6 942
tass 68:0847e35d08a6 943
tass 68:0847e35d08a6 944 struct pico_socket *pico_socket_clone(struct pico_socket *facsimile)
tass 68:0847e35d08a6 945 {
TASS Belgium NV 131:4758606c9316 946 struct pico_socket *s = NULL;
tass 68:0847e35d08a6 947
tass 68:0847e35d08a6 948 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 949 if (facsimile->proto->proto_number == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 950 s = pico_udp_open();
TASS Belgium NV 131:4758606c9316 951 s->proto = &pico_proto_udp;
TASS Belgium NV 131:4758606c9316 952 s->q_in.overhead = s->q_out.overhead = UDP_FRAME_OVERHEAD;
TASS Belgium NV 131:4758606c9316 953 }
TASS Belgium NV 131:4758606c9316 954
tass 68:0847e35d08a6 955 #endif
tass 68:0847e35d08a6 956
tass 68:0847e35d08a6 957 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 958 if (facsimile->proto->proto_number == PICO_PROTO_TCP) {
TASS Belgium NV 131:4758606c9316 959 s = pico_tcp_open();
TASS Belgium NV 131:4758606c9316 960 s->proto = &pico_proto_tcp;
TASS Belgium NV 131:4758606c9316 961 }
TASS Belgium NV 131:4758606c9316 962
tass 68:0847e35d08a6 963 #endif
tass 68:0847e35d08a6 964
TASS Belgium NV 131:4758606c9316 965 if (!s) {
TASS Belgium NV 131:4758606c9316 966 pico_err = PICO_ERR_EPROTONOSUPPORT;
TASS Belgium NV 131:4758606c9316 967 return NULL;
TASS Belgium NV 131:4758606c9316 968 }
TASS Belgium NV 131:4758606c9316 969
TASS Belgium NV 131:4758606c9316 970 s->local_port = facsimile->local_port;
TASS Belgium NV 131:4758606c9316 971 s->remote_port = facsimile->remote_port;
TASS Belgium NV 131:4758606c9316 972 s->state = facsimile->state;
tass 68:0847e35d08a6 973
tass 68:0847e35d08a6 974 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 975 if (facsimile->net == &pico_proto_ipv4) {
TASS Belgium NV 131:4758606c9316 976 s->net = &pico_proto_ipv4;
TASS Belgium NV 131:4758606c9316 977 memcpy(&s->local_addr, &facsimile->local_addr, sizeof(struct pico_ip4));
TASS Belgium NV 131:4758606c9316 978 memcpy(&s->remote_addr, &facsimile->remote_addr, sizeof(struct pico_ip4));
TASS Belgium NV 131:4758606c9316 979 }
TASS Belgium NV 131:4758606c9316 980
tass 68:0847e35d08a6 981 #endif
tass 68:0847e35d08a6 982
tass 68:0847e35d08a6 983 #ifdef PICO_SUPPORT_IPV6
TASS Belgium NV 131:4758606c9316 984 if (net == &pico_proto_ipv6) {
TASS Belgium NV 131:4758606c9316 985 s->net = &pico_proto_ipv6;
TASS Belgium NV 131:4758606c9316 986 memcpy(&s->local_addr, &facsimile->local_addr, sizeof(struct pico_ip6));
TASS Belgium NV 131:4758606c9316 987 memcpy(&s->remote_addr, &facsimile->remote_addr, sizeof(struct pico_ip6));
TASS Belgium NV 131:4758606c9316 988 }
TASS Belgium NV 131:4758606c9316 989
tass 68:0847e35d08a6 990 #endif
TASS Belgium NV 131:4758606c9316 991 s->q_in.max_size = PICO_DEFAULT_SOCKETQ;
TASS Belgium NV 131:4758606c9316 992 s->q_out.max_size = PICO_DEFAULT_SOCKETQ;
TASS Belgium NV 131:4758606c9316 993 s->wakeup = NULL;
TASS Belgium NV 131:4758606c9316 994 if (!s->net) {
TASS Belgium NV 131:4758606c9316 995 pico_free(s);
TASS Belgium NV 131:4758606c9316 996 pico_err = PICO_ERR_ENETUNREACH;
TASS Belgium NV 131:4758606c9316 997 return NULL;
TASS Belgium NV 131:4758606c9316 998 }
TASS Belgium NV 131:4758606c9316 999
TASS Belgium NV 131:4758606c9316 1000 return s;
tass 68:0847e35d08a6 1001 }
tass 68:0847e35d08a6 1002
tass 68:0847e35d08a6 1003 int pico_socket_read(struct pico_socket *s, void *buf, int len)
tass 68:0847e35d08a6 1004 {
TASS Belgium NV 131:4758606c9316 1005 if (!s || buf == NULL) {
TASS Belgium NV 131:4758606c9316 1006 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1007 return -1;
TASS Belgium NV 131:4758606c9316 1008 } else {
TASS Belgium NV 131:4758606c9316 1009 /* check if exists in tree */
TASS Belgium NV 131:4758606c9316 1010 /* See task #178 */
TASS Belgium NV 131:4758606c9316 1011 if (pico_check_socket(s) != 0) {
TASS Belgium NV 131:4758606c9316 1012 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1013 return -1;
TASS Belgium NV 131:4758606c9316 1014 }
tass 68:0847e35d08a6 1015 }
tass 68:0847e35d08a6 1016
TASS Belgium NV 131:4758606c9316 1017 if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) {
TASS Belgium NV 131:4758606c9316 1018 pico_err = PICO_ERR_EIO;
TASS Belgium NV 131:4758606c9316 1019 return -1;
TASS Belgium NV 131:4758606c9316 1020 }
TASS Belgium NV 131:4758606c9316 1021
TASS Belgium NV 131:4758606c9316 1022 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 1023 if (PROTO(s) == PICO_PROTO_UDP)
TASS Belgium NV 131:4758606c9316 1024 return pico_udp_recv(s, buf, (uint16_t)len, NULL, NULL);
TASS Belgium NV 131:4758606c9316 1025
tass 68:0847e35d08a6 1026 #endif
tass 68:0847e35d08a6 1027
tass 68:0847e35d08a6 1028 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 1029 if (PROTO(s) == PICO_PROTO_TCP) {
TASS Belgium NV 131:4758606c9316 1030 /* check if in shutdown state and if no more data in tcpq_in */
TASS Belgium NV 131:4758606c9316 1031 if ((s->state & PICO_SOCKET_STATE_SHUT_REMOTE) && pico_tcp_queue_in_is_empty(s)) {
TASS Belgium NV 131:4758606c9316 1032 pico_err = PICO_ERR_ESHUTDOWN;
TASS Belgium NV 131:4758606c9316 1033 return -1;
TASS Belgium NV 131:4758606c9316 1034 } else {
TASS Belgium NV 131:4758606c9316 1035 return (int)pico_tcp_read(s, buf, (uint32_t)len);
TASS Belgium NV 131:4758606c9316 1036 }
tass 68:0847e35d08a6 1037 }
TASS Belgium NV 131:4758606c9316 1038
tass 68:0847e35d08a6 1039 #endif
TASS Belgium NV 131:4758606c9316 1040 return 0;
tass 68:0847e35d08a6 1041 }
tass 68:0847e35d08a6 1042
tass 68:0847e35d08a6 1043 int pico_socket_write(struct pico_socket *s, const void *buf, int len)
tass 68:0847e35d08a6 1044 {
TASS Belgium NV 131:4758606c9316 1045 if (!s || buf == NULL) {
TASS Belgium NV 131:4758606c9316 1046 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1047 return -1;
TASS Belgium NV 131:4758606c9316 1048 } else {
TASS Belgium NV 131:4758606c9316 1049 /* check if exists in tree */
TASS Belgium NV 131:4758606c9316 1050 /* See task #178 */
TASS Belgium NV 131:4758606c9316 1051 if (pico_check_socket(s) != 0) {
TASS Belgium NV 131:4758606c9316 1052 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1053 return -1;
TASS Belgium NV 131:4758606c9316 1054 }
tass 68:0847e35d08a6 1055 }
tass 68:0847e35d08a6 1056
TASS Belgium NV 131:4758606c9316 1057 if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) {
TASS Belgium NV 131:4758606c9316 1058 pico_err = PICO_ERR_EIO;
TASS Belgium NV 131:4758606c9316 1059 return -1;
TASS Belgium NV 131:4758606c9316 1060 }
TASS Belgium NV 131:4758606c9316 1061
TASS Belgium NV 131:4758606c9316 1062 if ((s->state & PICO_SOCKET_STATE_CONNECTED) == 0) {
TASS Belgium NV 131:4758606c9316 1063 pico_err = PICO_ERR_ENOTCONN;
TASS Belgium NV 131:4758606c9316 1064 return -1;
TASS Belgium NV 131:4758606c9316 1065 } else if (s->state & PICO_SOCKET_STATE_SHUT_LOCAL) { /* check if in shutdown state */
TASS Belgium NV 131:4758606c9316 1066 pico_err = PICO_ERR_ESHUTDOWN;
TASS Belgium NV 131:4758606c9316 1067 return -1;
TASS Belgium NV 131:4758606c9316 1068 } else {
TASS Belgium NV 131:4758606c9316 1069 return pico_socket_sendto(s, buf, len, &s->remote_addr, s->remote_port);
TASS Belgium NV 131:4758606c9316 1070 }
tass 68:0847e35d08a6 1071 }
tass 68:0847e35d08a6 1072
tass 68:0847e35d08a6 1073 uint16_t pico_socket_high_port(uint16_t proto)
tass 68:0847e35d08a6 1074 {
TASS Belgium NV 131:4758606c9316 1075 uint16_t port;
TASS Belgium NV 131:4758606c9316 1076 if (0 ||
tass 68:0847e35d08a6 1077 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 1078 (proto == PICO_PROTO_TCP) ||
tass 68:0847e35d08a6 1079 #endif
tass 68:0847e35d08a6 1080 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 1081 (proto == PICO_PROTO_UDP) ||
tass 68:0847e35d08a6 1082 #endif
TASS Belgium NV 131:4758606c9316 1083 0) {
TASS Belgium NV 131:4758606c9316 1084 do {
TASS Belgium NV 131:4758606c9316 1085 uint32_t rand = pico_rand();
TASS Belgium NV 131:4758606c9316 1086 port = (uint16_t) (rand & 0xFFFFU);
TASS Belgium NV 131:4758606c9316 1087 port = (uint16_t)((port % (65535 - 1024)) + 1024U);
TASS Belgium NV 131:4758606c9316 1088 if (pico_is_port_free(proto, port, NULL, NULL)) {
TASS Belgium NV 131:4758606c9316 1089 return short_be(port);
TASS Belgium NV 131:4758606c9316 1090 }
TASS Belgium NV 131:4758606c9316 1091 } while(1);
TASS Belgium NV 131:4758606c9316 1092 }
TASS Belgium NV 131:4758606c9316 1093 else return 0U;
tass 68:0847e35d08a6 1094 }
tass 68:0847e35d08a6 1095
tass 68:0847e35d08a6 1096
tass 68:0847e35d08a6 1097 int pico_socket_sendto(struct pico_socket *s, const void *buf, const int len, void *dst, uint16_t remote_port)
tass 68:0847e35d08a6 1098 {
TASS Belgium NV 131:4758606c9316 1099 struct pico_frame *f;
TASS Belgium NV 131:4758606c9316 1100 struct pico_remote_duple *remote_duple = NULL;
TASS Belgium NV 131:4758606c9316 1101 int socket_mtu = PICO_SOCKET4_MTU;
TASS Belgium NV 131:4758606c9316 1102 int header_offset = 0;
TASS Belgium NV 131:4758606c9316 1103 int total_payload_written = 0;
tass 68:0847e35d08a6 1104 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 1105 struct pico_ip4 *src4;
tass 68:0847e35d08a6 1106 #endif
tass 68:0847e35d08a6 1107
tass 68:0847e35d08a6 1108 #ifdef PICO_SUPPORT_IPV6
TASS Belgium NV 131:4758606c9316 1109 struct pico_ip6 *src6;
tass 68:0847e35d08a6 1110 #endif
TASS Belgium NV 131:4758606c9316 1111 if (len == 0) {
TASS Belgium NV 131:4758606c9316 1112 return 0;
TASS Belgium NV 131:4758606c9316 1113 } else if (len < 0) {
TASS Belgium NV 131:4758606c9316 1114 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1115 return -1;
TASS Belgium NV 131:4758606c9316 1116 }
tass 68:0847e35d08a6 1117
TASS Belgium NV 131:4758606c9316 1118 if (buf == NULL || s == NULL) {
TASS Belgium NV 131:4758606c9316 1119 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1120 return -1;
TASS Belgium NV 131:4758606c9316 1121 }
tass 68:0847e35d08a6 1122
TASS Belgium NV 131:4758606c9316 1123 if (!dst || !remote_port) {
TASS Belgium NV 131:4758606c9316 1124 pico_err = PICO_ERR_EADDRNOTAVAIL;
TASS Belgium NV 131:4758606c9316 1125 return -1;
TASS Belgium NV 131:4758606c9316 1126 }
tass 68:0847e35d08a6 1127
TASS Belgium NV 131:4758606c9316 1128 if ((s->state & PICO_SOCKET_STATE_CONNECTED) != 0) {
TASS Belgium NV 131:4758606c9316 1129 if (remote_port != s->remote_port) {
TASS Belgium NV 131:4758606c9316 1130 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1131 return -1;
TASS Belgium NV 131:4758606c9316 1132 }
tass 68:0847e35d08a6 1133 }
tass 68:0847e35d08a6 1134
tass 68:0847e35d08a6 1135 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 1136 if (IS_SOCK_IPV4(s)) {
TASS Belgium NV 131:4758606c9316 1137 socket_mtu = PICO_SOCKET4_MTU;
TASS Belgium NV 131:4758606c9316 1138 if ((s->state & PICO_SOCKET_STATE_CONNECTED)) {
TASS Belgium NV 131:4758606c9316 1139 if (s->remote_addr.ip4.addr != ((struct pico_ip4 *)dst)->addr ) {
TASS Belgium NV 131:4758606c9316 1140 pico_err = PICO_ERR_EADDRNOTAVAIL;
TASS Belgium NV 131:4758606c9316 1141 return -1;
TASS Belgium NV 131:4758606c9316 1142 }
TASS Belgium NV 131:4758606c9316 1143 } else {
TASS Belgium NV 131:4758606c9316 1144 src4 = pico_ipv4_source_find(dst);
TASS Belgium NV 131:4758606c9316 1145 if (!src4) {
TASS Belgium NV 131:4758606c9316 1146 pico_err = PICO_ERR_EHOSTUNREACH;
TASS Belgium NV 131:4758606c9316 1147 return -1;
TASS Belgium NV 131:4758606c9316 1148 }
TASS Belgium NV 131:4758606c9316 1149
TASS Belgium NV 131:4758606c9316 1150 if (src4->addr != PICO_IPV4_INADDR_ANY)
TASS Belgium NV 131:4758606c9316 1151 s->local_addr.ip4.addr = src4->addr;
TASS Belgium NV 131:4758606c9316 1152
tass 68:0847e35d08a6 1153 # ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 1154 /* socket remote info could change in a consecutive call, make persistent */
TASS Belgium NV 131:4758606c9316 1155 if (PROTO(s) == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1156 remote_duple = pico_zalloc(sizeof(struct pico_remote_duple));
TASS Belgium NV 131:4758606c9316 1157 remote_duple->remote_addr.ip4.addr = ((struct pico_ip4 *)dst)->addr;
TASS Belgium NV 131:4758606c9316 1158 remote_duple->remote_port = remote_port;
TASS Belgium NV 131:4758606c9316 1159 }
TASS Belgium NV 131:4758606c9316 1160
tass 68:0847e35d08a6 1161 # endif
TASS Belgium NV 131:4758606c9316 1162 }
TASS Belgium NV 131:4758606c9316 1163
tass 68:0847e35d08a6 1164 #endif
TASS Belgium NV 131:4758606c9316 1165 }
TASS Belgium NV 131:4758606c9316 1166 else if (IS_SOCK_IPV6(s)) {
tass 68:0847e35d08a6 1167 socket_mtu = PICO_SOCKET6_MTU;
tass 68:0847e35d08a6 1168 #ifdef PICO_SUPPORT_IPV6
tass 68:0847e35d08a6 1169 if (s->state & PICO_SOCKET_STATE_CONNECTED) {
TASS Belgium NV 131:4758606c9316 1170 if (memcmp(&s->remote_addr, dst, PICO_SIZE_IP6))
TASS Belgium NV 131:4758606c9316 1171 return -1;
tass 68:0847e35d08a6 1172 } else {
TASS Belgium NV 131:4758606c9316 1173 src6 = pico_ipv6_source_find(dst);
TASS Belgium NV 131:4758606c9316 1174 if (!src6) {
TASS Belgium NV 131:4758606c9316 1175 pico_err = PICO_ERR_EHOSTUNREACH;
TASS Belgium NV 131:4758606c9316 1176 return -1;
TASS Belgium NV 131:4758606c9316 1177 }
TASS Belgium NV 131:4758606c9316 1178
TASS Belgium NV 131:4758606c9316 1179 memcpy(&s->local_addr, src6, PICO_SIZE_IP6);
TASS Belgium NV 131:4758606c9316 1180 memcpy(&s->remote_addr, dst, PICO_SIZE_IP6);
tass 68:0847e35d08a6 1181 # ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 1182 if (PROTO(s) == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1183 remote_duple = pico_zalloc(sizeof(struct pico_remote_duple));
TASS Belgium NV 131:4758606c9316 1184 remote_duple->remote_addr.ip6.addr = ((struct pico_ip6 *)dst)->addr;
TASS Belgium NV 131:4758606c9316 1185 remote_duple->remote_port = remote_port;
TASS Belgium NV 131:4758606c9316 1186 }
TASS Belgium NV 131:4758606c9316 1187
tass 68:0847e35d08a6 1188 # endif
tass 68:0847e35d08a6 1189 }
TASS Belgium NV 131:4758606c9316 1190
tass 68:0847e35d08a6 1191 #endif
TASS Belgium NV 131:4758606c9316 1192 }
tass 68:0847e35d08a6 1193
TASS Belgium NV 131:4758606c9316 1194 if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) {
tass 68:0847e35d08a6 1195 s->local_port = pico_socket_high_port(s->proto->proto_number);
tass 68:0847e35d08a6 1196 if (s->local_port == 0) {
TASS Belgium NV 131:4758606c9316 1197 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1198 return -1;
tass 68:0847e35d08a6 1199 }
TASS Belgium NV 131:4758606c9316 1200 }
TASS Belgium NV 131:4758606c9316 1201
TASS Belgium NV 131:4758606c9316 1202 if ((s->state & PICO_SOCKET_STATE_CONNECTED) == 0) {
tass 68:0847e35d08a6 1203 s->remote_port = remote_port;
TASS Belgium NV 131:4758606c9316 1204 }
tass 68:0847e35d08a6 1205
tass 68:0847e35d08a6 1206 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 1207 if (PROTO(s) == PICO_PROTO_TCP)
tass 68:0847e35d08a6 1208 header_offset = pico_tcp_overhead(s);
TASS Belgium NV 131:4758606c9316 1209
tass 68:0847e35d08a6 1210 #endif
tass 68:0847e35d08a6 1211
tass 68:0847e35d08a6 1212 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 1213 if (PROTO(s) == PICO_PROTO_UDP)
tass 68:0847e35d08a6 1214 header_offset = sizeof(struct pico_udp_hdr);
TASS Belgium NV 131:4758606c9316 1215
tass 68:0847e35d08a6 1216 #endif
tass 68:0847e35d08a6 1217
TASS Belgium NV 131:4758606c9316 1218 while (total_payload_written < len) {
TASS Belgium NV 131:4758606c9316 1219 int transport_len = (len - total_payload_written) + header_offset;
tass 68:0847e35d08a6 1220 if (transport_len > socket_mtu)
TASS Belgium NV 131:4758606c9316 1221 transport_len = socket_mtu;
TASS Belgium NV 131:4758606c9316 1222
tass 68:0847e35d08a6 1223 #ifdef PICO_SUPPORT_IPFRAG
tass 68:0847e35d08a6 1224 else {
TASS Belgium NV 131:4758606c9316 1225 if (total_payload_written)
TASS Belgium NV 131:4758606c9316 1226 transport_len -= header_offset; /* last fragment, do not allocate memory for transport header */
TASS Belgium NV 131:4758606c9316 1227
tass 68:0847e35d08a6 1228 }
tass 68:0847e35d08a6 1229 #endif /* PICO_SUPPORT_IPFRAG */
tass 68:0847e35d08a6 1230
tass 70:cd218dd180e5 1231 f = pico_socket_frame_alloc(s, (uint16_t)transport_len);
tass 68:0847e35d08a6 1232 if (!f) {
TASS Belgium NV 131:4758606c9316 1233 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 1234 return -1;
tass 68:0847e35d08a6 1235 }
TASS Belgium NV 131:4758606c9316 1236
tass 68:0847e35d08a6 1237 f->payload += header_offset;
tass 73:dfb737147f6e 1238 f->payload_len = (uint16_t)(f->payload_len - header_offset);
tass 68:0847e35d08a6 1239 f->sock = s;
TASS Belgium NV 131:4758606c9316 1240 transport_flags_update(f, s);
tass 68:0847e35d08a6 1241 if (remote_duple) {
TASS Belgium NV 131:4758606c9316 1242 f->info = pico_zalloc(sizeof(struct pico_remote_duple));
TASS Belgium NV 131:4758606c9316 1243 memcpy(f->info, remote_duple, sizeof(struct pico_remote_duple));
tass 68:0847e35d08a6 1244 }
tass 68:0847e35d08a6 1245
tass 68:0847e35d08a6 1246 #ifdef PICO_SUPPORT_IPFRAG
tass 68:0847e35d08a6 1247 #ifdef PICO_SUPPORT_UDP
tass 68:0847e35d08a6 1248 if (PROTO(s) == PICO_PROTO_UDP && ((len + header_offset) > socket_mtu)) {
TASS Belgium NV 131:4758606c9316 1249 /* hacking way to identify fragmentation frames: payload != transport_hdr -> first frame */
TASS Belgium NV 131:4758606c9316 1250 if (!total_payload_written) {
TASS Belgium NV 131:4758606c9316 1251 frag_dbg("FRAG: first fragmented frame %p | len = %u offset = 0\n", f, f->payload_len);
TASS Belgium NV 131:4758606c9316 1252 /* transport header length field contains total length + header length */
TASS Belgium NV 131:4758606c9316 1253 f->transport_len = (uint16_t)(len + header_offset);
TASS Belgium NV 131:4758606c9316 1254 f->frag = short_be(PICO_IPV4_MOREFRAG);
tass 68:0847e35d08a6 1255 } else {
TASS Belgium NV 131:4758606c9316 1256 /* no transport header in fragmented IP */
TASS Belgium NV 131:4758606c9316 1257 f->payload = f->transport_hdr;
TASS Belgium NV 131:4758606c9316 1258 f->payload_len = (uint16_t)(f->payload_len + header_offset);
TASS Belgium NV 131:4758606c9316 1259 /* set offset in octets */
TASS Belgium NV 131:4758606c9316 1260 f->frag = short_be((uint16_t)((total_payload_written + header_offset) / 8));
TASS Belgium NV 131:4758606c9316 1261 if (total_payload_written + f->payload_len < len) {
TASS Belgium NV 131:4758606c9316 1262 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 1263 f->frag |= short_be(PICO_IPV4_MOREFRAG);
TASS Belgium NV 131:4758606c9316 1264 } else {
TASS Belgium NV 131:4758606c9316 1265 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 1266 f->frag &= short_be(PICO_IPV4_FRAG_MASK);
TASS Belgium NV 131:4758606c9316 1267 }
tass 68:0847e35d08a6 1268 }
tass 68:0847e35d08a6 1269 } else {
TASS Belgium NV 131:4758606c9316 1270 f->frag = short_be(PICO_IPV4_DONTFRAG);
tass 68:0847e35d08a6 1271 }
TASS Belgium NV 131:4758606c9316 1272
tass 68:0847e35d08a6 1273 # endif /* PICO_SUPPORT_UDP */
tass 68:0847e35d08a6 1274 #endif /* PICO_SUPPORT_IPFRAG */
tass 68:0847e35d08a6 1275
tass 68:0847e35d08a6 1276 if (f->payload_len <= 0) {
TASS Belgium NV 131:4758606c9316 1277 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 1278 if (remote_duple)
TASS Belgium NV 131:4758606c9316 1279 pico_free(remote_duple);
TASS Belgium NV 131:4758606c9316 1280
TASS Belgium NV 131:4758606c9316 1281 return total_payload_written;
tass 68:0847e35d08a6 1282 }
tass 68:0847e35d08a6 1283
tass 68:0847e35d08a6 1284 memcpy(f->payload, buf + total_payload_written, f->payload_len);
TASS Belgium NV 131:4758606c9316 1285 /* dbg("Pushing segment, hdr len: %d, payload_len: %d\n", header_offset, f->payload_len); */
tass 68:0847e35d08a6 1286
tass 68:0847e35d08a6 1287 if (s->proto->push(s->proto, f) > 0) {
TASS Belgium NV 131:4758606c9316 1288 total_payload_written += (int)f->payload_len;
tass 68:0847e35d08a6 1289 } else {
TASS Belgium NV 131:4758606c9316 1290 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 1291 pico_err = PICO_ERR_EAGAIN;
TASS Belgium NV 131:4758606c9316 1292 break;
tass 68:0847e35d08a6 1293 }
TASS Belgium NV 131:4758606c9316 1294 }
TASS Belgium NV 131:4758606c9316 1295 if (remote_duple)
tass 68:0847e35d08a6 1296 pico_free(remote_duple);
TASS Belgium NV 131:4758606c9316 1297
TASS Belgium NV 131:4758606c9316 1298 return total_payload_written;
tass 68:0847e35d08a6 1299 }
tass 68:0847e35d08a6 1300
tass 68:0847e35d08a6 1301 int pico_socket_send(struct pico_socket *s, const void *buf, int len)
tass 68:0847e35d08a6 1302 {
TASS Belgium NV 131:4758606c9316 1303 if (!s || buf == NULL) {
TASS Belgium NV 131:4758606c9316 1304 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1305 return -1;
TASS Belgium NV 131:4758606c9316 1306 } else {
TASS Belgium NV 131:4758606c9316 1307 /* check if exists in tree */
TASS Belgium NV 131:4758606c9316 1308 /* See task #178 */
TASS Belgium NV 131:4758606c9316 1309 if (pico_check_socket(s) != 0) {
TASS Belgium NV 131:4758606c9316 1310 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1311 return -1;
TASS Belgium NV 131:4758606c9316 1312 }
tass 68:0847e35d08a6 1313 }
tass 68:0847e35d08a6 1314
TASS Belgium NV 131:4758606c9316 1315 if ((s->state & PICO_SOCKET_STATE_CONNECTED) == 0) {
TASS Belgium NV 131:4758606c9316 1316 pico_err = PICO_ERR_ENOTCONN;
TASS Belgium NV 131:4758606c9316 1317 return -1;
TASS Belgium NV 131:4758606c9316 1318 }
TASS Belgium NV 131:4758606c9316 1319
TASS Belgium NV 131:4758606c9316 1320 return pico_socket_sendto(s, buf, len, &s->remote_addr, s->remote_port);
tass 68:0847e35d08a6 1321 }
tass 68:0847e35d08a6 1322
tass 68:0847e35d08a6 1323 int pico_socket_recvfrom(struct pico_socket *s, void *buf, int len, void *orig, uint16_t *remote_port)
tass 68:0847e35d08a6 1324 {
TASS Belgium NV 131:4758606c9316 1325 if (!s || buf == NULL) { /* / || orig == NULL || remote_port == NULL) { */
TASS Belgium NV 131:4758606c9316 1326 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1327 return -1;
TASS Belgium NV 131:4758606c9316 1328 } else {
TASS Belgium NV 131:4758606c9316 1329 /* check if exists in tree */
TASS Belgium NV 131:4758606c9316 1330 if (pico_check_socket(s) != 0) {
TASS Belgium NV 131:4758606c9316 1331 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1332 /* See task #178 */
TASS Belgium NV 131:4758606c9316 1333 return -1;
TASS Belgium NV 131:4758606c9316 1334 }
tass 68:0847e35d08a6 1335 }
TASS Belgium NV 131:4758606c9316 1336
TASS Belgium NV 131:4758606c9316 1337 if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) {
TASS Belgium NV 131:4758606c9316 1338 pico_err = PICO_ERR_EADDRNOTAVAIL;
TASS Belgium NV 131:4758606c9316 1339 return -1;
TASS Belgium NV 131:4758606c9316 1340 }
tass 68:0847e35d08a6 1341
TASS Belgium NV 131:4758606c9316 1342 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 1343 if (PROTO(s) == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1344 return pico_udp_recv(s, buf, (uint16_t)len, orig, remote_port);
TASS Belgium NV 131:4758606c9316 1345 }
TASS Belgium NV 131:4758606c9316 1346
tass 68:0847e35d08a6 1347 #endif
tass 68:0847e35d08a6 1348 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 1349 if (PROTO(s) == PICO_PROTO_TCP) {
TASS Belgium NV 131:4758606c9316 1350 /* check if in shutdown state and if tcpq_in empty */
TASS Belgium NV 131:4758606c9316 1351 if ((s->state & PICO_SOCKET_STATE_SHUT_REMOTE) && pico_tcp_queue_in_is_empty(s)) {
TASS Belgium NV 131:4758606c9316 1352 pico_err = PICO_ERR_ESHUTDOWN;
TASS Belgium NV 131:4758606c9316 1353 return -1;
TASS Belgium NV 131:4758606c9316 1354 } else {
TASS Belgium NV 131:4758606c9316 1355 /* dbg("socket tcp recv\n"); */
TASS Belgium NV 131:4758606c9316 1356 return (int)pico_tcp_read(s, buf, (uint32_t)len);
TASS Belgium NV 131:4758606c9316 1357 }
tass 68:0847e35d08a6 1358 }
TASS Belgium NV 131:4758606c9316 1359
tass 68:0847e35d08a6 1360 #endif
TASS Belgium NV 131:4758606c9316 1361 /* dbg("socket return 0\n"); */
TASS Belgium NV 131:4758606c9316 1362 return 0;
tass 68:0847e35d08a6 1363 }
tass 68:0847e35d08a6 1364
tass 68:0847e35d08a6 1365 int pico_socket_recv(struct pico_socket *s, void *buf, int len)
tass 68:0847e35d08a6 1366 {
TASS Belgium NV 131:4758606c9316 1367 return pico_socket_recvfrom(s, buf, len, NULL, NULL);
tass 68:0847e35d08a6 1368 }
tass 68:0847e35d08a6 1369
tass 68:0847e35d08a6 1370
tass 68:0847e35d08a6 1371 int pico_socket_bind(struct pico_socket *s, void *local_addr, uint16_t *port)
tass 68:0847e35d08a6 1372 {
TASS Belgium NV 131:4758606c9316 1373 if (!s || !local_addr || !port) {
tass 68:0847e35d08a6 1374 pico_err = PICO_ERR_EINVAL;
tass 68:0847e35d08a6 1375 return -1;
tass 68:0847e35d08a6 1376 }
TASS Belgium NV 131:4758606c9316 1377
TASS Belgium NV 131:4758606c9316 1378 if (!is_sock_ipv6(s)) {
TASS Belgium NV 131:4758606c9316 1379 struct pico_ip4 *ip = (struct pico_ip4 *)local_addr;
TASS Belgium NV 131:4758606c9316 1380 if (ip->addr != PICO_IPV4_INADDR_ANY) {
TASS Belgium NV 131:4758606c9316 1381 if (!pico_ipv4_link_find(local_addr)) {
TASS Belgium NV 131:4758606c9316 1382 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1383 return -1;
TASS Belgium NV 131:4758606c9316 1384 }
TASS Belgium NV 131:4758606c9316 1385 }
TASS Belgium NV 131:4758606c9316 1386 } else {
TASS Belgium NV 131:4758606c9316 1387 /*... IPv6 */
TASS Belgium NV 131:4758606c9316 1388 }
tass 68:0847e35d08a6 1389
tass 68:0847e35d08a6 1390
TASS Belgium NV 131:4758606c9316 1391 /* When given port = 0, get a random high port to bind to. */
tass 68:0847e35d08a6 1392 if (*port == 0) {
TASS Belgium NV 131:4758606c9316 1393 *port = pico_socket_high_port(PROTO(s));
TASS Belgium NV 131:4758606c9316 1394 if (*port == 0) {
TASS Belgium NV 131:4758606c9316 1395 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1396 return -1;
TASS Belgium NV 131:4758606c9316 1397 }
tass 68:0847e35d08a6 1398 }
tass 68:0847e35d08a6 1399
TASS Belgium NV 131:4758606c9316 1400 if (pico_is_port_free(PROTO(s), *port, local_addr, s->net) == 0) {
TASS Belgium NV 131:4758606c9316 1401 pico_err = PICO_ERR_EADDRINUSE;
TASS Belgium NV 131:4758606c9316 1402 return -1;
TASS Belgium NV 131:4758606c9316 1403 }
TASS Belgium NV 131:4758606c9316 1404
TASS Belgium NV 131:4758606c9316 1405 s->local_port = *port;
tass 68:0847e35d08a6 1406
TASS Belgium NV 131:4758606c9316 1407 if (is_sock_ipv6(s)) {
TASS Belgium NV 131:4758606c9316 1408 struct pico_ip6 *ip = (struct pico_ip6 *) local_addr;
TASS Belgium NV 131:4758606c9316 1409 memcpy(s->local_addr.ip6.addr, ip, PICO_SIZE_IP6);
TASS Belgium NV 131:4758606c9316 1410 /* XXX: port ipv4 functionality to ipv6 */
TASS Belgium NV 131:4758606c9316 1411 /* Check for port already in use */
TASS Belgium NV 131:4758606c9316 1412 if (pico_is_port_free(PROTO(s), *port, &local_addr, s->net)) {
TASS Belgium NV 131:4758606c9316 1413 pico_err = PICO_ERR_EADDRINUSE;
TASS Belgium NV 131:4758606c9316 1414 return -1;
TASS Belgium NV 131:4758606c9316 1415 }
TASS Belgium NV 131:4758606c9316 1416 } else if (is_sock_ipv4(s)) {
TASS Belgium NV 131:4758606c9316 1417 struct pico_ip4 *ip = (struct pico_ip4 *) local_addr;
TASS Belgium NV 131:4758606c9316 1418 s->local_addr.ip4.addr = ip->addr;
tass 68:0847e35d08a6 1419 }
TASS Belgium NV 131:4758606c9316 1420
TASS Belgium NV 131:4758606c9316 1421 return pico_socket_alter_state(s, PICO_SOCKET_STATE_BOUND, 0, 0);
tass 68:0847e35d08a6 1422 }
tass 68:0847e35d08a6 1423
tass 68:0847e35d08a6 1424 int pico_socket_connect(struct pico_socket *s, const void *remote_addr, uint16_t remote_port)
tass 68:0847e35d08a6 1425 {
TASS Belgium NV 131:4758606c9316 1426 int ret = -1;
TASS Belgium NV 131:4758606c9316 1427 pico_err = PICO_ERR_EPROTONOSUPPORT;
TASS Belgium NV 131:4758606c9316 1428 if (!s || remote_addr == NULL || remote_port == 0) {
TASS Belgium NV 131:4758606c9316 1429 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1430 return -1;
TASS Belgium NV 131:4758606c9316 1431 }
tass 68:0847e35d08a6 1432
TASS Belgium NV 131:4758606c9316 1433 s->remote_port = remote_port;
tass 68:0847e35d08a6 1434
TASS Belgium NV 131:4758606c9316 1435 if (s->local_port == 0) {
TASS Belgium NV 131:4758606c9316 1436 s->local_port = pico_socket_high_port(PROTO(s));
TASS Belgium NV 131:4758606c9316 1437 if (!s->local_port) {
TASS Belgium NV 131:4758606c9316 1438 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1439 return -1;
TASS Belgium NV 131:4758606c9316 1440 }
tass 68:0847e35d08a6 1441 }
tass 68:0847e35d08a6 1442
TASS Belgium NV 131:4758606c9316 1443 if (is_sock_ipv6(s)) {
TASS Belgium NV 131:4758606c9316 1444 const struct pico_ip6 *ip = (const struct pico_ip6 *) remote_addr;
TASS Belgium NV 131:4758606c9316 1445 memcpy(s->remote_addr.ip6.addr, ip, PICO_SIZE_IP6);
TASS Belgium NV 131:4758606c9316 1446 } else if (is_sock_ipv4(s)) {
TASS Belgium NV 131:4758606c9316 1447 const struct pico_ip4 *local, *ip = (const struct pico_ip4 *) remote_addr;
TASS Belgium NV 131:4758606c9316 1448 s->remote_addr.ip4.addr = ip->addr;
TASS Belgium NV 131:4758606c9316 1449 local = pico_ipv4_source_find(ip);
TASS Belgium NV 131:4758606c9316 1450 if (local) {
TASS Belgium NV 131:4758606c9316 1451 s->local_addr.ip4.addr = local->addr;
TASS Belgium NV 131:4758606c9316 1452 } else {
TASS Belgium NV 131:4758606c9316 1453 pico_err = PICO_ERR_EHOSTUNREACH;
TASS Belgium NV 131:4758606c9316 1454 return -1;
TASS Belgium NV 131:4758606c9316 1455 }
tass 68:0847e35d08a6 1456 }
tass 68:0847e35d08a6 1457
TASS Belgium NV 131:4758606c9316 1458 pico_socket_alter_state(s, PICO_SOCKET_STATE_BOUND, 0, 0);
tass 68:0847e35d08a6 1459
tass 68:0847e35d08a6 1460 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 1461 if (PROTO(s) == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1462 pico_socket_alter_state(s, PICO_SOCKET_STATE_CONNECTED, 0, 0);
TASS Belgium NV 131:4758606c9316 1463 pico_err = PICO_ERR_NOERR;
TASS Belgium NV 131:4758606c9316 1464 ret = 0;
TASS Belgium NV 131:4758606c9316 1465 }
TASS Belgium NV 131:4758606c9316 1466
tass 68:0847e35d08a6 1467 #endif
tass 68:0847e35d08a6 1468
tass 68:0847e35d08a6 1469 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 1470 if (PROTO(s) == PICO_PROTO_TCP) {
TASS Belgium NV 131:4758606c9316 1471 if (pico_tcp_initconn(s) == 0) {
TASS Belgium NV 131:4758606c9316 1472 pico_socket_alter_state(s, PICO_SOCKET_STATE_CONNECTED | PICO_SOCKET_STATE_TCP_SYN_SENT, 0, 0);
TASS Belgium NV 131:4758606c9316 1473 pico_err = PICO_ERR_NOERR;
TASS Belgium NV 131:4758606c9316 1474 ret = 0;
TASS Belgium NV 131:4758606c9316 1475 } else {
TASS Belgium NV 131:4758606c9316 1476 pico_err = PICO_ERR_EHOSTUNREACH;
TASS Belgium NV 131:4758606c9316 1477 }
tass 68:0847e35d08a6 1478 }
TASS Belgium NV 131:4758606c9316 1479
tass 68:0847e35d08a6 1480 #endif
tass 68:0847e35d08a6 1481
TASS Belgium NV 131:4758606c9316 1482 return ret;
tass 68:0847e35d08a6 1483 }
tass 68:0847e35d08a6 1484
tass 68:0847e35d08a6 1485 #ifdef PICO_SUPPORT_TCP
tass 68:0847e35d08a6 1486
tass 68:0847e35d08a6 1487 int pico_socket_listen(struct pico_socket *s, int backlog)
tass 68:0847e35d08a6 1488 {
TASS Belgium NV 131:4758606c9316 1489 if (!s || backlog < 1) {
TASS Belgium NV 131:4758606c9316 1490 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1491 return -1;
TASS Belgium NV 131:4758606c9316 1492 } else {
TASS Belgium NV 131:4758606c9316 1493 /* check if exists in tree */
TASS Belgium NV 131:4758606c9316 1494 /* See task #178 */
TASS Belgium NV 131:4758606c9316 1495 if (pico_check_socket(s) != 0) {
TASS Belgium NV 131:4758606c9316 1496 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1497 return -1;
TASS Belgium NV 131:4758606c9316 1498 }
tass 68:0847e35d08a6 1499 }
TASS Belgium NV 131:4758606c9316 1500
TASS Belgium NV 131:4758606c9316 1501 if (PROTO(s) == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1502 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1503 return -1;
TASS Belgium NV 131:4758606c9316 1504 }
tass 68:0847e35d08a6 1505
TASS Belgium NV 131:4758606c9316 1506 if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) {
TASS Belgium NV 131:4758606c9316 1507 pico_err = PICO_ERR_EISCONN;
TASS Belgium NV 131:4758606c9316 1508 return -1;
TASS Belgium NV 131:4758606c9316 1509 }
tass 68:0847e35d08a6 1510
TASS Belgium NV 131:4758606c9316 1511 if (backlog < 1) {
TASS Belgium NV 131:4758606c9316 1512 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1513 return -1;
TASS Belgium NV 131:4758606c9316 1514 }
tass 68:0847e35d08a6 1515
TASS Belgium NV 131:4758606c9316 1516 if (PROTO(s) == PICO_PROTO_TCP)
TASS Belgium NV 131:4758606c9316 1517 pico_socket_alter_state(s, PICO_SOCKET_STATE_TCP_SYN_SENT, 0, PICO_SOCKET_STATE_TCP_LISTEN);
tass 68:0847e35d08a6 1518
TASS Belgium NV 131:4758606c9316 1519 s->max_backlog = backlog;
TASS Belgium NV 131:4758606c9316 1520
TASS Belgium NV 131:4758606c9316 1521 return 0;
tass 68:0847e35d08a6 1522 }
tass 68:0847e35d08a6 1523
tass 68:0847e35d08a6 1524 struct pico_socket *pico_socket_accept(struct pico_socket *s, void *orig, uint16_t *port)
tass 68:0847e35d08a6 1525 {
TASS Belgium NV 131:4758606c9316 1526 if (!s || !orig || !port) {
TASS Belgium NV 131:4758606c9316 1527 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1528 return NULL;
TASS Belgium NV 131:4758606c9316 1529 }
TASS Belgium NV 131:4758606c9316 1530
tass 68:0847e35d08a6 1531 pico_err = PICO_ERR_EINVAL;
tass 68:0847e35d08a6 1532
TASS Belgium NV 131:4758606c9316 1533 if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) {
TASS Belgium NV 131:4758606c9316 1534 return NULL;
TASS Belgium NV 131:4758606c9316 1535 }
tass 68:0847e35d08a6 1536
TASS Belgium NV 131:4758606c9316 1537 if (PROTO(s) == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1538 return NULL;
TASS Belgium NV 131:4758606c9316 1539 }
tass 68:0847e35d08a6 1540
TASS Belgium NV 131:4758606c9316 1541 if (TCPSTATE(s) == PICO_SOCKET_STATE_TCP_LISTEN) {
TASS Belgium NV 131:4758606c9316 1542 struct pico_sockport *sp = pico_get_sockport(PICO_PROTO_TCP, s->local_port);
TASS Belgium NV 131:4758606c9316 1543 struct pico_socket *found;
TASS Belgium NV 131:4758606c9316 1544 /* If at this point no incoming connection socket is found,
TASS Belgium NV 131:4758606c9316 1545 * the accept call is valid, but no connection is established yet.
TASS Belgium NV 131:4758606c9316 1546 */
TASS Belgium NV 131:4758606c9316 1547 pico_err = PICO_ERR_EAGAIN;
TASS Belgium NV 131:4758606c9316 1548 if (sp) {
TASS Belgium NV 131:4758606c9316 1549 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 1550 /* RB_FOREACH(found, socket_tree, &sp->socks) { */
TASS Belgium NV 131:4758606c9316 1551 pico_tree_foreach(index, &sp->socks){
TASS Belgium NV 131:4758606c9316 1552 found = index->keyValue;
TASS Belgium NV 131:4758606c9316 1553 if ((s == found->parent) && ((found->state & PICO_SOCKET_STATE_TCP) == PICO_SOCKET_STATE_TCP_ESTABLISHED)) {
TASS Belgium NV 131:4758606c9316 1554 found->parent = NULL;
TASS Belgium NV 131:4758606c9316 1555 pico_err = PICO_ERR_NOERR;
TASS Belgium NV 131:4758606c9316 1556 memcpy(orig, &found->remote_addr, sizeof(struct pico_ip4));
TASS Belgium NV 131:4758606c9316 1557 *port = found->remote_port;
TASS Belgium NV 131:4758606c9316 1558 s->number_of_pending_conn--;
TASS Belgium NV 131:4758606c9316 1559 return found;
TASS Belgium NV 131:4758606c9316 1560 }
TASS Belgium NV 131:4758606c9316 1561 }
tass 68:0847e35d08a6 1562 }
tass 68:0847e35d08a6 1563 }
TASS Belgium NV 131:4758606c9316 1564
TASS Belgium NV 131:4758606c9316 1565 return NULL;
tass 68:0847e35d08a6 1566 }
tass 68:0847e35d08a6 1567
tass 68:0847e35d08a6 1568 #else
tass 68:0847e35d08a6 1569
tass 68:0847e35d08a6 1570 int pico_socket_listen(struct pico_socket *s, int backlog)
tass 68:0847e35d08a6 1571 {
TASS Belgium NV 131:4758606c9316 1572 IGNORE_PARAMETER(s);
TASS Belgium NV 131:4758606c9316 1573 IGNORE_PARAMETER(backlog);
TASS Belgium NV 131:4758606c9316 1574 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1575 return -1;
tass 68:0847e35d08a6 1576 }
tass 68:0847e35d08a6 1577
tass 68:0847e35d08a6 1578 struct pico_socket *pico_socket_accept(struct pico_socket *s, void *orig, uint16_t *local_port)
tass 68:0847e35d08a6 1579 {
TASS Belgium NV 131:4758606c9316 1580 IGNORE_PARAMETER(s);
TASS Belgium NV 131:4758606c9316 1581 IGNORE_PARAMETER(orig);
TASS Belgium NV 131:4758606c9316 1582 IGNORE_PARAMETER(local_port);
TASS Belgium NV 131:4758606c9316 1583 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1584 return NULL;
tass 68:0847e35d08a6 1585 }
tass 68:0847e35d08a6 1586
tass 68:0847e35d08a6 1587 #endif
tass 68:0847e35d08a6 1588
TASS Belgium NV 131:4758606c9316 1589 #define PICO_SOCKET_SETOPT_EN(socket, index) (socket->opt_flags |= (1 << index))
TASS Belgium NV 131:4758606c9316 1590 #define PICO_SOCKET_SETOPT_DIS(socket, index) (socket->opt_flags &= (uint16_t) ~(1 << index))
tass 68:0847e35d08a6 1591
tass 74:c146c4e346c4 1592 #ifdef PICO_SUPPORT_MCAST
tass 74:c146c4e346c4 1593 static struct pico_ipv4_link *setopt_multicast_check(struct pico_socket *s, void *value, int alloc, int bysource)
tass 74:c146c4e346c4 1594 {
tass 74:c146c4e346c4 1595 struct pico_ip_mreq *mreq = NULL;
tass 74:c146c4e346c4 1596 struct pico_ipv4_link *mcast_link = NULL;
tass 74:c146c4e346c4 1597 struct pico_ip_mreq_source *mreq_src = NULL;
tass 74:c146c4e346c4 1598
tass 74:c146c4e346c4 1599 if (!value) {
TASS Belgium NV 131:4758606c9316 1600 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1601 return NULL;
tass 74:c146c4e346c4 1602 }
TASS Belgium NV 131:4758606c9316 1603
tass 74:c146c4e346c4 1604 if (!bysource) {
TASS Belgium NV 131:4758606c9316 1605 mreq = (struct pico_ip_mreq *) value;
TASS Belgium NV 131:4758606c9316 1606 mcast_link = pico_socket_setoption_mcastargs_validation(mreq, NULL);
TASS Belgium NV 131:4758606c9316 1607 if (!mreq->mcast_link_addr.addr)
TASS Belgium NV 131:4758606c9316 1608 mreq->mcast_link_addr.addr = mcast_link->address.addr;
tass 74:c146c4e346c4 1609 } else {
TASS Belgium NV 131:4758606c9316 1610 mreq_src = (struct pico_ip_mreq_source *) value;
TASS Belgium NV 131:4758606c9316 1611 mcast_link = pico_socket_setoption_mcastargs_validation(NULL, mreq_src);
TASS Belgium NV 131:4758606c9316 1612 if (!mreq_src->mcast_link_addr.addr)
TASS Belgium NV 131:4758606c9316 1613 mreq_src->mcast_link_addr.addr = mcast_link->address.addr;
tass 74:c146c4e346c4 1614 }
TASS Belgium NV 131:4758606c9316 1615
tass 74:c146c4e346c4 1616 if (!mcast_link) {
TASS Belgium NV 131:4758606c9316 1617 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1618 return NULL;
tass 74:c146c4e346c4 1619 }
tass 74:c146c4e346c4 1620
tass 74:c146c4e346c4 1621 if (!s->MCASTListen) { /* No RBTree allocated yet */
TASS Belgium NV 131:4758606c9316 1622 if (alloc) {
TASS Belgium NV 131:4758606c9316 1623 s->MCASTListen = pico_zalloc(sizeof(struct pico_tree));
TASS Belgium NV 131:4758606c9316 1624 if (!s->MCASTListen) {
TASS Belgium NV 131:4758606c9316 1625 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 1626 return NULL;
TASS Belgium NV 131:4758606c9316 1627 }
TASS Belgium NV 131:4758606c9316 1628
TASS Belgium NV 131:4758606c9316 1629 s->MCASTListen->root = &LEAF;
TASS Belgium NV 131:4758606c9316 1630 s->MCASTListen->compare = mcast_listen_cmp;
TASS Belgium NV 131:4758606c9316 1631 } else return NULL;
tass 74:c146c4e346c4 1632 }
TASS Belgium NV 131:4758606c9316 1633
tass 74:c146c4e346c4 1634 return mcast_link;
tass 74:c146c4e346c4 1635 }
tass 74:c146c4e346c4 1636 #endif
tass 74:c146c4e346c4 1637
TASS Belgium NV 131:4758606c9316 1638 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 1639 {
TASS Belgium NV 131:4758606c9316 1640 if (s == NULL) {
TASS Belgium NV 131:4758606c9316 1641 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1642 return -1;
TASS Belgium NV 131:4758606c9316 1643 }
tass 68:0847e35d08a6 1644
TASS Belgium NV 131:4758606c9316 1645 pico_err = PICO_ERR_NOERR;
tass 68:0847e35d08a6 1646
TASS Belgium NV 131:4758606c9316 1647 switch (option)
TASS Belgium NV 131:4758606c9316 1648 {
tass 68:0847e35d08a6 1649 #ifdef PICO_SUPPORT_TCP
tass 68:0847e35d08a6 1650 case PICO_TCP_NODELAY:
TASS Belgium NV 131:4758606c9316 1651 if (!value) {
tass 68:0847e35d08a6 1652 pico_err = PICO_ERR_EINVAL;
tass 68:0847e35d08a6 1653 return -1;
TASS Belgium NV 131:4758606c9316 1654 }
TASS Belgium NV 131:4758606c9316 1655
TASS Belgium NV 131:4758606c9316 1656 if (s->proto->proto_number == PICO_PROTO_TCP) {
tass 68:0847e35d08a6 1657 int *val = (int*)value;
tass 68:0847e35d08a6 1658 if (*val > 0) {
TASS Belgium NV 131:4758606c9316 1659 dbg("setsockopt: Nagle algorithm disabled.\n");
TASS Belgium NV 131:4758606c9316 1660 PICO_SOCKET_SETOPT_EN(s, PICO_SOCKET_OPT_TCPNODELAY);
tass 68:0847e35d08a6 1661 } else {
TASS Belgium NV 131:4758606c9316 1662 dbg("setsockopt: Nagle algorithm enabled.\n");
TASS Belgium NV 131:4758606c9316 1663 PICO_SOCKET_SETOPT_DIS(s, PICO_SOCKET_OPT_TCPNODELAY);
tass 68:0847e35d08a6 1664 }
TASS Belgium NV 131:4758606c9316 1665 } else {
tass 68:0847e35d08a6 1666 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1667 }
TASS Belgium NV 131:4758606c9316 1668
TASS Belgium NV 131:4758606c9316 1669 break;
tass 68:0847e35d08a6 1670 #endif
tass 68:0847e35d08a6 1671
tass 68:0847e35d08a6 1672
tass 68:0847e35d08a6 1673 #ifdef PICO_SUPPORT_MCAST
tass 68:0847e35d08a6 1674 case PICO_IP_MULTICAST_IF:
TASS Belgium NV 131:4758606c9316 1675 pico_err = PICO_ERR_EOPNOTSUPP;
TASS Belgium NV 131:4758606c9316 1676 return -1;
TASS Belgium NV 131:4758606c9316 1677 break;
tass 68:0847e35d08a6 1678
tass 68:0847e35d08a6 1679 case PICO_IP_MULTICAST_TTL:
TASS Belgium NV 131:4758606c9316 1680 if (s->proto->proto_number == PICO_PROTO_UDP) {
tass 68:0847e35d08a6 1681 return pico_udp_set_mc_ttl(s, *((uint8_t *) value));
TASS Belgium NV 131:4758606c9316 1682 }
TASS Belgium NV 131:4758606c9316 1683
TASS Belgium NV 131:4758606c9316 1684 break;
tass 68:0847e35d08a6 1685
tass 68:0847e35d08a6 1686 case PICO_IP_MULTICAST_LOOP:
TASS Belgium NV 131:4758606c9316 1687 if (s->proto->proto_number == PICO_PROTO_UDP) {
tass 68:0847e35d08a6 1688 switch (*(uint8_t *) value)
tass 68:0847e35d08a6 1689 {
TASS Belgium NV 131:4758606c9316 1690 case 0:
tass 68:0847e35d08a6 1691 /* do not loop back multicast datagram */
TASS Belgium NV 131:4758606c9316 1692 PICO_SOCKET_SETOPT_DIS(s, PICO_SOCKET_OPT_MULTICAST_LOOP);
tass 68:0847e35d08a6 1693 break;
tass 68:0847e35d08a6 1694
TASS Belgium NV 131:4758606c9316 1695 case 1:
tass 68:0847e35d08a6 1696 /* do loop back multicast datagram */
TASS Belgium NV 131:4758606c9316 1697 PICO_SOCKET_SETOPT_EN(s, PICO_SOCKET_OPT_MULTICAST_LOOP);
TASS Belgium NV 131:4758606c9316 1698 break;
tass 68:0847e35d08a6 1699
TASS Belgium NV 131:4758606c9316 1700 default:
tass 68:0847e35d08a6 1701 pico_err = PICO_ERR_EINVAL;
tass 68:0847e35d08a6 1702 return -1;
TASS Belgium NV 131:4758606c9316 1703 }
TASS Belgium NV 131:4758606c9316 1704 }
TASS Belgium NV 131:4758606c9316 1705
TASS Belgium NV 131:4758606c9316 1706 break;
tass 68:0847e35d08a6 1707
tass 68:0847e35d08a6 1708 case PICO_IP_ADD_MEMBERSHIP:
TASS Belgium NV 131:4758606c9316 1709 /* EXCLUDE mode */
TASS Belgium NV 131:4758606c9316 1710 if (s->proto->proto_number == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1711 int filter_mode;
TASS Belgium NV 131:4758606c9316 1712 struct pico_mcast_listen *listen;
TASS Belgium NV 131:4758606c9316 1713 struct pico_ip_mreq *mreq = (struct pico_ip_mreq *)value;
TASS Belgium NV 131:4758606c9316 1714 struct pico_ipv4_link *mcast_link = setopt_multicast_check(s, value, 1, 0);
TASS Belgium NV 131:4758606c9316 1715 if (!mcast_link)
TASS Belgium NV 131:4758606c9316 1716 return -1;
TASS Belgium NV 131:4758606c9316 1717
TASS Belgium NV 131:4758606c9316 1718 listen = listen_find(s, &mreq->mcast_link_addr, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1719 if (listen) {
TASS Belgium NV 131:4758606c9316 1720 if (listen->filter_mode != PICO_IP_MULTICAST_EXCLUDE) {
TASS Belgium NV 131:4758606c9316 1721 so_mcast_dbg("pico_socket_setoption: ERROR any-source multicast (exclude) on source-specific multicast (include)\n");
TASS Belgium NV 131:4758606c9316 1722 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1723 return -1;
TASS Belgium NV 131:4758606c9316 1724 } else {
TASS Belgium NV 131:4758606c9316 1725 so_mcast_dbg("pico_socket_setoption: ERROR duplicate PICO_IP_ADD_MEMBERSHIP\n");
TASS Belgium NV 131:4758606c9316 1726 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1727 return -1;
TASS Belgium NV 131:4758606c9316 1728 }
TASS Belgium NV 131:4758606c9316 1729 } else {
TASS Belgium NV 131:4758606c9316 1730 listen = pico_zalloc(sizeof(struct pico_mcast_listen));
TASS Belgium NV 131:4758606c9316 1731 if (!listen) {
TASS Belgium NV 131:4758606c9316 1732 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 1733 return -1;
TASS Belgium NV 131:4758606c9316 1734 }
TASS Belgium NV 131:4758606c9316 1735
TASS Belgium NV 131:4758606c9316 1736 listen->filter_mode = PICO_IP_MULTICAST_EXCLUDE;
TASS Belgium NV 131:4758606c9316 1737 listen->mcast_link = mreq->mcast_link_addr;
TASS Belgium NV 131:4758606c9316 1738 listen->mcast_group = mreq->mcast_group_addr;
TASS Belgium NV 131:4758606c9316 1739 listen->MCASTSources.root = &LEAF;
TASS Belgium NV 131:4758606c9316 1740 listen->MCASTSources.compare = mcast_sources_cmp;
TASS Belgium NV 131:4758606c9316 1741 pico_tree_insert(s->MCASTListen, listen);
TASS Belgium NV 131:4758606c9316 1742 }
TASS Belgium NV 131:4758606c9316 1743
TASS Belgium NV 131:4758606c9316 1744 pico_tree_insert(&MCASTSockets, s);
TASS Belgium NV 131:4758606c9316 1745 filter_mode = pico_socket_aggregate_mcastfilters(&mcast_link->address, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1746 if (filter_mode < 0)
TASS Belgium NV 131:4758606c9316 1747 return -1;
TASS Belgium NV 131:4758606c9316 1748
TASS Belgium NV 131:4758606c9316 1749 return pico_ipv4_mcast_join(&mreq->mcast_link_addr, &mreq->mcast_group_addr, 1, (uint8_t)filter_mode, &MCASTFilter);
tass 68:0847e35d08a6 1750 }
tass 68:0847e35d08a6 1751
TASS Belgium NV 131:4758606c9316 1752 break;
tass 68:0847e35d08a6 1753
tass 68:0847e35d08a6 1754 case PICO_IP_DROP_MEMBERSHIP:
TASS Belgium NV 131:4758606c9316 1755 /* EXCLUDE mode */
TASS Belgium NV 131:4758606c9316 1756 if (s->proto->proto_number == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1757 int filter_mode = 0;
TASS Belgium NV 131:4758606c9316 1758 struct pico_mcast_listen *listen;
TASS Belgium NV 131:4758606c9316 1759 struct pico_ip_mreq *mreq = (struct pico_ip_mreq *)value;
TASS Belgium NV 131:4758606c9316 1760 struct pico_ip4 *source = NULL;
TASS Belgium NV 131:4758606c9316 1761 struct pico_tree_node *index, *_tmp;
TASS Belgium NV 131:4758606c9316 1762 struct pico_ipv4_link *mcast_link = setopt_multicast_check(s, value, 0, 0);
TASS Belgium NV 131:4758606c9316 1763 if (!mcast_link)
TASS Belgium NV 131:4758606c9316 1764 return -1;
tass 68:0847e35d08a6 1765
TASS Belgium NV 131:4758606c9316 1766 listen = listen_find(s, &mreq->mcast_link_addr, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1767 if (!listen) {
TASS Belgium NV 131:4758606c9316 1768 so_mcast_dbg("pico_socket_setoption: ERROR PICO_IP_DROP_MEMBERSHIP before PICO_IP_ADD_MEMBERSHIP/SOURCE_MEMBERSHIP\n");
TASS Belgium NV 131:4758606c9316 1769 pico_err = PICO_ERR_EADDRNOTAVAIL;
TASS Belgium NV 131:4758606c9316 1770 return -1;
TASS Belgium NV 131:4758606c9316 1771 } else {
TASS Belgium NV 131:4758606c9316 1772 pico_tree_foreach_safe(index, &listen->MCASTSources, _tmp)
TASS Belgium NV 131:4758606c9316 1773 {
TASS Belgium NV 131:4758606c9316 1774 source = index->keyValue;
TASS Belgium NV 131:4758606c9316 1775 pico_tree_delete(&listen->MCASTSources, source);
TASS Belgium NV 131:4758606c9316 1776 pico_free(source);
TASS Belgium NV 131:4758606c9316 1777 }
TASS Belgium NV 131:4758606c9316 1778 pico_tree_delete(s->MCASTListen, listen);
TASS Belgium NV 131:4758606c9316 1779 pico_free(listen);
TASS Belgium NV 131:4758606c9316 1780 if (pico_tree_empty(s->MCASTListen)) {
TASS Belgium NV 131:4758606c9316 1781 pico_free(s->MCASTListen);
TASS Belgium NV 131:4758606c9316 1782 s->MCASTListen = NULL;
TASS Belgium NV 131:4758606c9316 1783 pico_tree_delete(&MCASTSockets, s);
TASS Belgium NV 131:4758606c9316 1784 }
TASS Belgium NV 131:4758606c9316 1785 }
TASS Belgium NV 131:4758606c9316 1786
TASS Belgium NV 131:4758606c9316 1787 filter_mode = pico_socket_aggregate_mcastfilters(&mcast_link->address, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1788 if (filter_mode < 0)
TASS Belgium NV 131:4758606c9316 1789 return -1;
TASS Belgium NV 131:4758606c9316 1790
TASS Belgium NV 131:4758606c9316 1791 return pico_ipv4_mcast_leave(&mreq->mcast_link_addr, &mreq->mcast_group_addr, 1, (uint8_t)filter_mode, &MCASTFilter);
tass 68:0847e35d08a6 1792 }
tass 68:0847e35d08a6 1793
TASS Belgium NV 131:4758606c9316 1794 break;
tass 68:0847e35d08a6 1795
tass 68:0847e35d08a6 1796 case PICO_IP_UNBLOCK_SOURCE:
TASS Belgium NV 131:4758606c9316 1797 /* EXCLUDE mode */
TASS Belgium NV 131:4758606c9316 1798 if (s->proto->proto_number == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1799 int filter_mode = 0;
TASS Belgium NV 131:4758606c9316 1800 struct pico_ip_mreq_source *mreq = (struct pico_ip_mreq_source *)value;
TASS Belgium NV 131:4758606c9316 1801 struct pico_mcast_listen *listen = NULL;
TASS Belgium NV 131:4758606c9316 1802 struct pico_ip4 *source = NULL, stest = {
TASS Belgium NV 131:4758606c9316 1803 0
TASS Belgium NV 131:4758606c9316 1804 };
TASS Belgium NV 131:4758606c9316 1805 struct pico_ipv4_link *mcast_link = setopt_multicast_check(s, value, 0, 1);
TASS Belgium NV 131:4758606c9316 1806 if (!mcast_link)
TASS Belgium NV 131:4758606c9316 1807 return -1;
TASS Belgium NV 131:4758606c9316 1808
TASS Belgium NV 131:4758606c9316 1809 listen = listen_find(s, &mreq->mcast_link_addr, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1810 if (!listen) {
TASS Belgium NV 131:4758606c9316 1811 so_mcast_dbg("pico_socket_setoption: ERROR PICO_IP_UNBLOCK_SOURCE before PICO_IP_ADD_MEMBERSHIP\n");
TASS Belgium NV 131:4758606c9316 1812 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1813 return -1;
TASS Belgium NV 131:4758606c9316 1814 } else {
TASS Belgium NV 131:4758606c9316 1815 if (listen->filter_mode != PICO_IP_MULTICAST_EXCLUDE) {
TASS Belgium NV 131:4758606c9316 1816 so_mcast_dbg("pico_socket_setoption: ERROR any-source multicast (exclude) on source-specific multicast (include)\n");
TASS Belgium NV 131:4758606c9316 1817 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1818 return -1;
TASS Belgium NV 131:4758606c9316 1819 }
TASS Belgium NV 131:4758606c9316 1820
TASS Belgium NV 131:4758606c9316 1821 stest.addr = mreq->mcast_source_addr.addr;
TASS Belgium NV 131:4758606c9316 1822 source = pico_tree_findKey(&listen->MCASTSources, &stest);
TASS Belgium NV 131:4758606c9316 1823 if (!source) {
TASS Belgium NV 131:4758606c9316 1824 so_mcast_dbg("pico_socket_setoption: ERROR address to unblock not in source list\n");
TASS Belgium NV 131:4758606c9316 1825 pico_err = PICO_ERR_EADDRNOTAVAIL;
TASS Belgium NV 131:4758606c9316 1826 return -1;
TASS Belgium NV 131:4758606c9316 1827 } else {
TASS Belgium NV 131:4758606c9316 1828 pico_tree_delete(&listen->MCASTSources, source);
TASS Belgium NV 131:4758606c9316 1829 pico_free(source);
TASS Belgium NV 131:4758606c9316 1830 }
TASS Belgium NV 131:4758606c9316 1831 }
TASS Belgium NV 131:4758606c9316 1832
TASS Belgium NV 131:4758606c9316 1833 filter_mode = pico_socket_aggregate_mcastfilters(&mcast_link->address, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1834 if (filter_mode < 0)
TASS Belgium NV 131:4758606c9316 1835 return -1;
TASS Belgium NV 131:4758606c9316 1836
TASS Belgium NV 131:4758606c9316 1837 return pico_ipv4_mcast_leave(&mreq->mcast_link_addr, &mreq->mcast_group_addr, 0, (uint8_t)filter_mode, &MCASTFilter);
tass 68:0847e35d08a6 1838 }
tass 68:0847e35d08a6 1839
TASS Belgium NV 131:4758606c9316 1840 break;
tass 68:0847e35d08a6 1841
tass 68:0847e35d08a6 1842 case PICO_IP_BLOCK_SOURCE:
TASS Belgium NV 131:4758606c9316 1843 /* EXCLUDE mode */
TASS Belgium NV 131:4758606c9316 1844 if (s->proto->proto_number == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1845 int filter_mode = 0;
TASS Belgium NV 131:4758606c9316 1846 struct pico_ip_mreq_source *mreq = (struct pico_ip_mreq_source *)value;
TASS Belgium NV 131:4758606c9316 1847 struct pico_mcast_listen *listen = NULL;
TASS Belgium NV 131:4758606c9316 1848 struct pico_ip4 *source = NULL, stest = {
TASS Belgium NV 131:4758606c9316 1849 0
TASS Belgium NV 131:4758606c9316 1850 };
TASS Belgium NV 131:4758606c9316 1851 struct pico_ipv4_link *mcast_link = setopt_multicast_check(s, value, 0, 1);
TASS Belgium NV 131:4758606c9316 1852 if (!mcast_link)
TASS Belgium NV 131:4758606c9316 1853 return -1;
TASS Belgium NV 131:4758606c9316 1854
TASS Belgium NV 131:4758606c9316 1855 listen = listen_find(s, &mreq->mcast_link_addr, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1856 if (!listen) {
TASS Belgium NV 131:4758606c9316 1857 dbg("pico_socket_setoption: ERROR PICO_IP_BLOCK_SOURCE before PICO_IP_ADD_MEMBERSHIP\n");
TASS Belgium NV 131:4758606c9316 1858 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1859 return -1;
TASS Belgium NV 131:4758606c9316 1860 } else {
TASS Belgium NV 131:4758606c9316 1861 if (listen->filter_mode != PICO_IP_MULTICAST_EXCLUDE) {
TASS Belgium NV 131:4758606c9316 1862 so_mcast_dbg("pico_socket_setoption: ERROR any-source multicast (exclude) on source-specific multicast (include)\n");
TASS Belgium NV 131:4758606c9316 1863 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1864 return -1;
TASS Belgium NV 131:4758606c9316 1865 }
TASS Belgium NV 131:4758606c9316 1866
TASS Belgium NV 131:4758606c9316 1867 stest.addr = mreq->mcast_source_addr.addr;
TASS Belgium NV 131:4758606c9316 1868 source = pico_tree_findKey(&listen->MCASTSources, &stest);
TASS Belgium NV 131:4758606c9316 1869 if (source) {
TASS Belgium NV 131:4758606c9316 1870 so_mcast_dbg("pico_socket_setoption: ERROR address to block already in source list\n");
TASS Belgium NV 131:4758606c9316 1871 pico_err = PICO_ERR_EADDRNOTAVAIL;
TASS Belgium NV 131:4758606c9316 1872 return -1;
TASS Belgium NV 131:4758606c9316 1873 } else {
TASS Belgium NV 131:4758606c9316 1874 source = pico_zalloc(sizeof(struct pico_ip4));
TASS Belgium NV 131:4758606c9316 1875 if (!source) {
TASS Belgium NV 131:4758606c9316 1876 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 1877 return -1;
TASS Belgium NV 131:4758606c9316 1878 }
TASS Belgium NV 131:4758606c9316 1879
TASS Belgium NV 131:4758606c9316 1880 source->addr = mreq->mcast_source_addr.addr;
TASS Belgium NV 131:4758606c9316 1881 pico_tree_insert(&listen->MCASTSources, source);
TASS Belgium NV 131:4758606c9316 1882 }
tass 68:0847e35d08a6 1883 }
TASS Belgium NV 131:4758606c9316 1884
TASS Belgium NV 131:4758606c9316 1885 filter_mode = pico_socket_aggregate_mcastfilters(&mcast_link->address, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1886 if (filter_mode < 0)
TASS Belgium NV 131:4758606c9316 1887 return -1;
TASS Belgium NV 131:4758606c9316 1888
TASS Belgium NV 131:4758606c9316 1889 return pico_ipv4_mcast_join(&mreq->mcast_link_addr, &mreq->mcast_group_addr, 0, (uint8_t)filter_mode, &MCASTFilter);
tass 68:0847e35d08a6 1890 }
tass 68:0847e35d08a6 1891
TASS Belgium NV 131:4758606c9316 1892 break;
tass 68:0847e35d08a6 1893
tass 68:0847e35d08a6 1894 case PICO_IP_ADD_SOURCE_MEMBERSHIP:
TASS Belgium NV 131:4758606c9316 1895 /* INCLUDE mode */
TASS Belgium NV 131:4758606c9316 1896 if (s->proto->proto_number == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1897 int filter_mode = 0, reference_count = 0;
TASS Belgium NV 131:4758606c9316 1898 struct pico_ip_mreq_source *mreq = (struct pico_ip_mreq_source *)value;
TASS Belgium NV 131:4758606c9316 1899 struct pico_mcast_listen *listen = NULL;
TASS Belgium NV 131:4758606c9316 1900 struct pico_ip4 *source = NULL, stest = {
TASS Belgium NV 131:4758606c9316 1901 0
TASS Belgium NV 131:4758606c9316 1902 };
TASS Belgium NV 131:4758606c9316 1903 struct pico_ipv4_link *mcast_link = setopt_multicast_check(s, value, 1, 1);
TASS Belgium NV 131:4758606c9316 1904 if (!mcast_link)
TASS Belgium NV 131:4758606c9316 1905 return -1;
TASS Belgium NV 131:4758606c9316 1906
TASS Belgium NV 131:4758606c9316 1907 listen = listen_find(s, &mreq->mcast_link_addr, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1908 if (listen) {
TASS Belgium NV 131:4758606c9316 1909 if (listen->filter_mode != PICO_IP_MULTICAST_INCLUDE) {
TASS Belgium NV 131:4758606c9316 1910 so_mcast_dbg("pico_socket_setoption: ERROR source-specific multicast (include) on any-source multicast (exclude)\n");
TASS Belgium NV 131:4758606c9316 1911 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1912 return -1;
TASS Belgium NV 131:4758606c9316 1913 }
TASS Belgium NV 131:4758606c9316 1914
TASS Belgium NV 131:4758606c9316 1915 stest.addr = mreq->mcast_source_addr.addr;
TASS Belgium NV 131:4758606c9316 1916 source = pico_tree_findKey(&listen->MCASTSources, &stest);
TASS Belgium NV 131:4758606c9316 1917 if (source) {
TASS Belgium NV 131:4758606c9316 1918 so_mcast_dbg("pico_socket_setoption: ERROR source address to allow already in source list\n");
TASS Belgium NV 131:4758606c9316 1919 pico_err = PICO_ERR_EADDRNOTAVAIL;
TASS Belgium NV 131:4758606c9316 1920 return -1;
TASS Belgium NV 131:4758606c9316 1921 } else {
TASS Belgium NV 131:4758606c9316 1922 source = pico_zalloc(sizeof(struct pico_ip4));
TASS Belgium NV 131:4758606c9316 1923 if (!source) {
TASS Belgium NV 131:4758606c9316 1924 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 1925 return -1;
TASS Belgium NV 131:4758606c9316 1926 }
TASS Belgium NV 131:4758606c9316 1927
TASS Belgium NV 131:4758606c9316 1928 source->addr = mreq->mcast_source_addr.addr;
TASS Belgium NV 131:4758606c9316 1929 pico_tree_insert(&listen->MCASTSources, source);
TASS Belgium NV 131:4758606c9316 1930 }
TASS Belgium NV 131:4758606c9316 1931 } else {
TASS Belgium NV 131:4758606c9316 1932 listen = pico_zalloc(sizeof(struct pico_mcast_listen));
TASS Belgium NV 131:4758606c9316 1933 if (!listen) {
TASS Belgium NV 131:4758606c9316 1934 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 1935 return -1;
TASS Belgium NV 131:4758606c9316 1936 }
TASS Belgium NV 131:4758606c9316 1937
TASS Belgium NV 131:4758606c9316 1938 listen->filter_mode = PICO_IP_MULTICAST_INCLUDE;
TASS Belgium NV 131:4758606c9316 1939 listen->mcast_link = mreq->mcast_link_addr;
TASS Belgium NV 131:4758606c9316 1940 listen->mcast_group = mreq->mcast_group_addr;
TASS Belgium NV 131:4758606c9316 1941 listen->MCASTSources.root = &LEAF;
TASS Belgium NV 131:4758606c9316 1942 listen->MCASTSources.compare = mcast_sources_cmp;
TASS Belgium NV 131:4758606c9316 1943 source = pico_zalloc(sizeof(struct pico_ip4));
TASS Belgium NV 131:4758606c9316 1944 if (!source) {
TASS Belgium NV 131:4758606c9316 1945 pico_free(listen);
TASS Belgium NV 131:4758606c9316 1946 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 1947 return -1;
TASS Belgium NV 131:4758606c9316 1948 }
TASS Belgium NV 131:4758606c9316 1949
TASS Belgium NV 131:4758606c9316 1950 source->addr = mreq->mcast_source_addr.addr;
TASS Belgium NV 131:4758606c9316 1951 pico_tree_insert(&listen->MCASTSources, source);
TASS Belgium NV 131:4758606c9316 1952 pico_tree_insert(s->MCASTListen, listen);
TASS Belgium NV 131:4758606c9316 1953 reference_count = 1;
tass 68:0847e35d08a6 1954 }
TASS Belgium NV 131:4758606c9316 1955
TASS Belgium NV 131:4758606c9316 1956 pico_tree_insert(&MCASTSockets, s);
TASS Belgium NV 131:4758606c9316 1957 filter_mode = pico_socket_aggregate_mcastfilters(&mcast_link->address, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1958 if (filter_mode < 0)
TASS Belgium NV 131:4758606c9316 1959 return -1;
TASS Belgium NV 131:4758606c9316 1960
TASS Belgium NV 131:4758606c9316 1961 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 1962 }
tass 68:0847e35d08a6 1963
TASS Belgium NV 131:4758606c9316 1964 break;
tass 68:0847e35d08a6 1965
tass 68:0847e35d08a6 1966 case PICO_IP_DROP_SOURCE_MEMBERSHIP:
TASS Belgium NV 131:4758606c9316 1967 /* INCLUDE mode */
TASS Belgium NV 131:4758606c9316 1968 if (s->proto->proto_number == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1969 int filter_mode = 0, reference_count = 0;
TASS Belgium NV 131:4758606c9316 1970 struct pico_ip_mreq_source *mreq = (struct pico_ip_mreq_source *)value;
TASS Belgium NV 131:4758606c9316 1971 struct pico_mcast_listen *listen = NULL;
TASS Belgium NV 131:4758606c9316 1972 struct pico_ip4 *source = NULL, stest = {
TASS Belgium NV 131:4758606c9316 1973 0
TASS Belgium NV 131:4758606c9316 1974 };
TASS Belgium NV 131:4758606c9316 1975 struct pico_ipv4_link *mcast_link = setopt_multicast_check(s, value, 0, 1);
TASS Belgium NV 131:4758606c9316 1976 if (!mcast_link)
TASS Belgium NV 131:4758606c9316 1977 return -1;
TASS Belgium NV 131:4758606c9316 1978
TASS Belgium NV 131:4758606c9316 1979 listen = listen_find(s, &mreq->mcast_link_addr, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 1980 if (!listen) {
TASS Belgium NV 131:4758606c9316 1981 so_mcast_dbg("pico_socket_setoption: ERROR PICO_IP_DROP_SOURCE_MEMBERSHIP before PICO_IP_ADD_SOURCE_MEMBERSHIP\n");
TASS Belgium NV 131:4758606c9316 1982 pico_err = PICO_ERR_EADDRNOTAVAIL;
TASS Belgium NV 131:4758606c9316 1983 return -1;
TASS Belgium NV 131:4758606c9316 1984 } else {
TASS Belgium NV 131:4758606c9316 1985 if (listen->filter_mode != PICO_IP_MULTICAST_INCLUDE) {
TASS Belgium NV 131:4758606c9316 1986 so_mcast_dbg("pico_socket_setoption: ERROR source-specific multicast (include) on any-source multicast (exclude)\n");
TASS Belgium NV 131:4758606c9316 1987 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1988 return -1;
TASS Belgium NV 131:4758606c9316 1989 }
TASS Belgium NV 131:4758606c9316 1990
TASS Belgium NV 131:4758606c9316 1991 stest.addr = mreq->mcast_source_addr.addr;
TASS Belgium NV 131:4758606c9316 1992 source = pico_tree_findKey(&listen->MCASTSources, &stest);
TASS Belgium NV 131:4758606c9316 1993 if (!source) {
TASS Belgium NV 131:4758606c9316 1994 so_mcast_dbg("pico_socket_setoption: ERROR address to drop not in source list\n");
TASS Belgium NV 131:4758606c9316 1995 pico_err = PICO_ERR_EADDRNOTAVAIL;
TASS Belgium NV 131:4758606c9316 1996 return -1;
TASS Belgium NV 131:4758606c9316 1997 } else {
TASS Belgium NV 131:4758606c9316 1998 pico_tree_delete(&listen->MCASTSources, source);
TASS Belgium NV 131:4758606c9316 1999 pico_free(source);
TASS Belgium NV 131:4758606c9316 2000 if (pico_tree_empty(&listen->MCASTSources)) { /* 1 if empty, 0 otherwise */
TASS Belgium NV 131:4758606c9316 2001 reference_count = 1;
TASS Belgium NV 131:4758606c9316 2002 pico_tree_delete(s->MCASTListen, listen);
TASS Belgium NV 131:4758606c9316 2003 pico_free(listen);
TASS Belgium NV 131:4758606c9316 2004 if (pico_tree_empty(s->MCASTListen)) {
TASS Belgium NV 131:4758606c9316 2005 pico_free(s->MCASTListen);
TASS Belgium NV 131:4758606c9316 2006 s->MCASTListen = NULL;
TASS Belgium NV 131:4758606c9316 2007 pico_tree_delete(&MCASTSockets, s);
TASS Belgium NV 131:4758606c9316 2008 }
TASS Belgium NV 131:4758606c9316 2009 }
TASS Belgium NV 131:4758606c9316 2010 }
tass 68:0847e35d08a6 2011 }
TASS Belgium NV 131:4758606c9316 2012
TASS Belgium NV 131:4758606c9316 2013 filter_mode = pico_socket_aggregate_mcastfilters(&mcast_link->address, &mreq->mcast_group_addr);
TASS Belgium NV 131:4758606c9316 2014 if (filter_mode < 0)
TASS Belgium NV 131:4758606c9316 2015 return -1;
TASS Belgium NV 131:4758606c9316 2016
TASS Belgium NV 131:4758606c9316 2017 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 2018 }
tass 68:0847e35d08a6 2019
TASS Belgium NV 131:4758606c9316 2020 break;
tass 68:0847e35d08a6 2021 #endif /* PICO_SUPPORT_MCAST */
tass 68:0847e35d08a6 2022
tass 68:0847e35d08a6 2023 default:
TASS Belgium NV 131:4758606c9316 2024 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 2025 return -1;
TASS Belgium NV 131:4758606c9316 2026 }
tass 68:0847e35d08a6 2027
TASS Belgium NV 131:4758606c9316 2028 if (pico_err != PICO_ERR_NOERR)
TASS Belgium NV 131:4758606c9316 2029 return -1;
TASS Belgium NV 131:4758606c9316 2030 else
TASS Belgium NV 131:4758606c9316 2031 return 0;
tass 68:0847e35d08a6 2032 }
tass 68:0847e35d08a6 2033
TASS Belgium NV 131:4758606c9316 2034 #define PICO_SOCKET_GETOPT(socket, index) ((socket->opt_flags & (1 << index)) != 0)
tass 68:0847e35d08a6 2035
tass 68:0847e35d08a6 2036 int pico_socket_getoption(struct pico_socket *s, int option, void *value)
TASS Belgium NV 131:4758606c9316 2037 {
TASS Belgium NV 131:4758606c9316 2038 if (!s || !value) {
TASS Belgium NV 131:4758606c9316 2039 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 2040 return -1;
TASS Belgium NV 131:4758606c9316 2041 }
tass 68:0847e35d08a6 2042
TASS Belgium NV 131:4758606c9316 2043 switch (option)
TASS Belgium NV 131:4758606c9316 2044 {
tass 68:0847e35d08a6 2045 #ifdef PICO_SUPPORT_TCP
tass 68:0847e35d08a6 2046 case PICO_TCP_NODELAY:
TASS Belgium NV 131:4758606c9316 2047 if (s->proto->proto_number == PICO_PROTO_TCP)
tass 68:0847e35d08a6 2048 /* state of the NODELAY option */
TASS Belgium NV 131:4758606c9316 2049 *(int *)value = PICO_SOCKET_GETOPT(s, PICO_SOCKET_OPT_TCPNODELAY);
TASS Belgium NV 131:4758606c9316 2050 else
tass 68:0847e35d08a6 2051 *(int *)value = 0;
TASS Belgium NV 131:4758606c9316 2052
TASS Belgium NV 131:4758606c9316 2053 break;
tass 68:0847e35d08a6 2054 #endif
tass 68:0847e35d08a6 2055
tass 68:0847e35d08a6 2056 #ifdef PICO_SUPPORT_MCAST
tass 68:0847e35d08a6 2057 case PICO_IP_MULTICAST_IF:
TASS Belgium NV 131:4758606c9316 2058 pico_err = PICO_ERR_EOPNOTSUPP;
TASS Belgium NV 131:4758606c9316 2059 return -1;
TASS Belgium NV 131:4758606c9316 2060 break;
tass 68:0847e35d08a6 2061
tass 68:0847e35d08a6 2062 case PICO_IP_MULTICAST_TTL:
TASS Belgium NV 131:4758606c9316 2063 if (s->proto->proto_number == PICO_PROTO_UDP) {
tass 68:0847e35d08a6 2064 pico_udp_get_mc_ttl(s, (uint8_t *) value);
TASS Belgium NV 131:4758606c9316 2065 } else {
tass 68:0847e35d08a6 2066 *(uint8_t *)value = 0;
tass 68:0847e35d08a6 2067 pico_err = PICO_ERR_EINVAL;
tass 68:0847e35d08a6 2068 return -1;
TASS Belgium NV 131:4758606c9316 2069 }
TASS Belgium NV 131:4758606c9316 2070
TASS Belgium NV 131:4758606c9316 2071 break;
tass 68:0847e35d08a6 2072
tass 68:0847e35d08a6 2073 case PICO_IP_MULTICAST_LOOP:
TASS Belgium NV 131:4758606c9316 2074 if (s->proto->proto_number == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 2075 *(uint8_t *)value = PICO_SOCKET_GETOPT(s, PICO_SOCKET_OPT_MULTICAST_LOOP);
TASS Belgium NV 131:4758606c9316 2076 } else {
tass 68:0847e35d08a6 2077 *(uint8_t *)value = 0;
tass 68:0847e35d08a6 2078 pico_err = PICO_ERR_EINVAL;
tass 68:0847e35d08a6 2079 return -1;
TASS Belgium NV 131:4758606c9316 2080 }
TASS Belgium NV 131:4758606c9316 2081
TASS Belgium NV 131:4758606c9316 2082 break;
tass 68:0847e35d08a6 2083 #endif /* PICO_SUPPORT_MCAST */
tass 68:0847e35d08a6 2084
tass 68:0847e35d08a6 2085 default:
TASS Belgium NV 131:4758606c9316 2086 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 2087 return -1;
TASS Belgium NV 131:4758606c9316 2088 }
tass 68:0847e35d08a6 2089
TASS Belgium NV 131:4758606c9316 2090 return 0;
tass 68:0847e35d08a6 2091 }
tass 68:0847e35d08a6 2092
tass 68:0847e35d08a6 2093
tass 68:0847e35d08a6 2094 int pico_socket_shutdown(struct pico_socket *s, int mode)
tass 68:0847e35d08a6 2095 {
TASS Belgium NV 131:4758606c9316 2096 if (!s) {
TASS Belgium NV 131:4758606c9316 2097 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 2098 return -1;
TASS Belgium NV 131:4758606c9316 2099 } else {
TASS Belgium NV 131:4758606c9316 2100 /* check if exists in tree */
TASS Belgium NV 131:4758606c9316 2101 /* See task #178 */
TASS Belgium NV 131:4758606c9316 2102 if (pico_check_socket(s) != 0) {
TASS Belgium NV 131:4758606c9316 2103 pico_free(s); /* close socket after bind or connect failed */
TASS Belgium NV 131:4758606c9316 2104 return 0;
TASS Belgium NV 131:4758606c9316 2105 }
tass 68:0847e35d08a6 2106 }
tass 68:0847e35d08a6 2107
tass 68:0847e35d08a6 2108 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 2109 if (PROTO(s) == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 2110 if (mode & PICO_SHUT_RDWR)
TASS Belgium NV 131:4758606c9316 2111 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 2112 else if (mode & PICO_SHUT_RD)
TASS Belgium NV 131:4758606c9316 2113 pico_socket_alter_state(s, 0, PICO_SOCKET_STATE_BOUND, 0);
TASS Belgium NV 131:4758606c9316 2114 }
TASS Belgium NV 131:4758606c9316 2115
tass 68:0847e35d08a6 2116 #endif
tass 68:0847e35d08a6 2117 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 2118 if (PROTO(s) == PICO_PROTO_TCP) {
TASS Belgium NV 131:4758606c9316 2119 if(mode & PICO_SHUT_RDWR)
TASS Belgium NV 131:4758606c9316 2120 {
TASS Belgium NV 131:4758606c9316 2121 pico_socket_alter_state(s, PICO_SOCKET_STATE_SHUT_LOCAL | PICO_SOCKET_STATE_SHUT_REMOTE, 0, 0);
TASS Belgium NV 131:4758606c9316 2122 pico_tcp_notify_closing(s);
TASS Belgium NV 131:4758606c9316 2123 }
TASS Belgium NV 131:4758606c9316 2124 else if (mode & PICO_SHUT_WR)
TASS Belgium NV 131:4758606c9316 2125 pico_socket_alter_state(s, PICO_SOCKET_STATE_SHUT_LOCAL, 0, 0);
TASS Belgium NV 131:4758606c9316 2126 else if (mode & PICO_SHUT_RD)
TASS Belgium NV 131:4758606c9316 2127 pico_socket_alter_state(s, PICO_SOCKET_STATE_SHUT_REMOTE, 0, 0);
tass 68:0847e35d08a6 2128
TASS Belgium NV 131:4758606c9316 2129 }
TASS Belgium NV 131:4758606c9316 2130
tass 68:0847e35d08a6 2131 #endif
TASS Belgium NV 131:4758606c9316 2132 return 0;
tass 68:0847e35d08a6 2133 }
tass 68:0847e35d08a6 2134
tass 68:0847e35d08a6 2135 int pico_socket_close(struct pico_socket *s)
tass 68:0847e35d08a6 2136 {
TASS Belgium NV 131:4758606c9316 2137 return pico_socket_shutdown(s, PICO_SHUT_RDWR);
tass 68:0847e35d08a6 2138 }
tass 68:0847e35d08a6 2139
tass 68:0847e35d08a6 2140 #ifdef PICO_SUPPORT_CRC
tass 68:0847e35d08a6 2141 static inline int pico_transport_crc_check(struct pico_frame *f)
tass 68:0847e35d08a6 2142 {
TASS Belgium NV 131:4758606c9316 2143 struct pico_ipv4_hdr *net_hdr = (struct pico_ipv4_hdr *) f->net_hdr;
TASS Belgium NV 131:4758606c9316 2144 struct pico_udp_hdr *udp_hdr = NULL;
TASS Belgium NV 131:4758606c9316 2145 uint16_t checksum_invalid = 1;
tass 68:0847e35d08a6 2146
TASS Belgium NV 131:4758606c9316 2147 switch (net_hdr->proto)
TASS Belgium NV 131:4758606c9316 2148 {
tass 68:0847e35d08a6 2149 case PICO_PROTO_TCP:
TASS Belgium NV 131:4758606c9316 2150 checksum_invalid = short_be(pico_tcp_checksum_ipv4(f));
TASS Belgium NV 131:4758606c9316 2151 /* dbg("TCP CRC validation == %u\n", checksum_invalid); */
TASS Belgium NV 131:4758606c9316 2152 if (checksum_invalid) {
TASS Belgium NV 131:4758606c9316 2153 /* dbg("TCP CRC: validation failed!\n"); */
TASS Belgium NV 131:4758606c9316 2154 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 2155 return 0;
TASS Belgium NV 131:4758606c9316 2156 }
TASS Belgium NV 131:4758606c9316 2157
TASS Belgium NV 131:4758606c9316 2158 break;
tass 68:0847e35d08a6 2159
tass 68:0847e35d08a6 2160 case PICO_PROTO_UDP:
TASS Belgium NV 131:4758606c9316 2161 udp_hdr = (struct pico_udp_hdr *) f->transport_hdr;
TASS Belgium NV 131:4758606c9316 2162 if (short_be(udp_hdr->crc)) {
TASS Belgium NV 131:4758606c9316 2163 checksum_invalid = short_be(pico_udp_checksum_ipv4(f));
TASS Belgium NV 131:4758606c9316 2164 /* dbg("UDP CRC validation == %u\n", checksum_invalid); */
TASS Belgium NV 131:4758606c9316 2165 if (checksum_invalid) {
TASS Belgium NV 131:4758606c9316 2166 /* dbg("UDP CRC: validation failed!\n"); */
TASS Belgium NV 131:4758606c9316 2167 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 2168 return 0;
TASS Belgium NV 131:4758606c9316 2169 }
tass 68:0847e35d08a6 2170 }
TASS Belgium NV 131:4758606c9316 2171
TASS Belgium NV 131:4758606c9316 2172 break;
tass 68:0847e35d08a6 2173
tass 68:0847e35d08a6 2174 default:
TASS Belgium NV 131:4758606c9316 2175 /* Do nothing */
TASS Belgium NV 131:4758606c9316 2176 break;
TASS Belgium NV 131:4758606c9316 2177 }
TASS Belgium NV 131:4758606c9316 2178 return 1;
tass 68:0847e35d08a6 2179 }
tass 68:0847e35d08a6 2180 #else
tass 68:0847e35d08a6 2181 static inline int pico_transport_crc_check(struct pico_frame *f)
tass 68:0847e35d08a6 2182 {
TASS Belgium NV 131:4758606c9316 2183 IGNORE_PARAMETER(f);
TASS Belgium NV 131:4758606c9316 2184 return 1;
tass 68:0847e35d08a6 2185 }
tass 68:0847e35d08a6 2186 #endif /* PICO_SUPPORT_CRC */
tass 68:0847e35d08a6 2187
tass 68:0847e35d08a6 2188 int pico_transport_process_in(struct pico_protocol *self, struct pico_frame *f)
tass 68:0847e35d08a6 2189 {
TASS Belgium NV 131:4758606c9316 2190 struct pico_trans *hdr = (struct pico_trans *) f->transport_hdr;
TASS Belgium NV 131:4758606c9316 2191 int ret = 0;
tass 68:0847e35d08a6 2192
TASS Belgium NV 131:4758606c9316 2193 if (!hdr) {
TASS Belgium NV 131:4758606c9316 2194 pico_err = PICO_ERR_EFAULT;
TASS Belgium NV 131:4758606c9316 2195 return -1;
TASS Belgium NV 131:4758606c9316 2196 }
tass 68:0847e35d08a6 2197
TASS Belgium NV 131:4758606c9316 2198 ret = pico_transport_crc_check(f);
TASS Belgium NV 131:4758606c9316 2199 if (ret < 1)
TASS Belgium NV 131:4758606c9316 2200 return ret;
TASS Belgium NV 131:4758606c9316 2201 else
TASS Belgium NV 131:4758606c9316 2202 ret = 0;
tass 68:0847e35d08a6 2203
TASS Belgium NV 131:4758606c9316 2204 if ((hdr) && (pico_socket_deliver(self, f, hdr->dport) == 0))
TASS Belgium NV 131:4758606c9316 2205 return ret;
tass 68:0847e35d08a6 2206
TASS Belgium NV 131:4758606c9316 2207 if (!IS_BCAST(f)) {
TASS Belgium NV 131:4758606c9316 2208 dbg("Socket not found... \n");
TASS Belgium NV 131:4758606c9316 2209 pico_notify_socket_unreachable(f);
tass 68:0847e35d08a6 2210 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 2211 /* if tcp protocol send RST segment */
TASS Belgium NV 131:4758606c9316 2212 /* if (self->proto_number == PICO_PROTO_TCP) */
TASS Belgium NV 131:4758606c9316 2213 /* pico_tcp_reply_rst(f); */
tass 68:0847e35d08a6 2214 #endif
TASS Belgium NV 131:4758606c9316 2215 ret = -1;
TASS Belgium NV 131:4758606c9316 2216 pico_err = PICO_ERR_ENOENT;
TASS Belgium NV 131:4758606c9316 2217 }
TASS Belgium NV 131:4758606c9316 2218
TASS Belgium NV 131:4758606c9316 2219 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 2220 return ret;
tass 68:0847e35d08a6 2221 }
tass 68:0847e35d08a6 2222
tass 68:0847e35d08a6 2223 #define SL_LOOP_MIN 1
tass 68:0847e35d08a6 2224
tass 125:96003ae6f1d8 2225 #ifdef PICO_SUPPORT_TCP
tass 95:f4ca916a26fe 2226 static int checkSocketSanity(struct pico_socket *s)
tass 95:f4ca916a26fe 2227 {
tass 95:f4ca916a26fe 2228
TASS Belgium NV 131:4758606c9316 2229 /* checking for pending connections */
TASS Belgium NV 131:4758606c9316 2230 if(TCP_STATE(s) == PICO_SOCKET_STATE_TCP_SYN_RECV)
TASS Belgium NV 131:4758606c9316 2231 if((pico_time)(PICO_TIME_MS() - s->timestamp) >= PICO_SOCKET_BOUND_TIMEOUT) {
TASS Belgium NV 131:4758606c9316 2232 s->parent->number_of_pending_conn--;
TASS Belgium NV 131:4758606c9316 2233 return -1;
TASS Belgium NV 131:4758606c9316 2234 }
TASS Belgium NV 131:4758606c9316 2235
TASS Belgium NV 131:4758606c9316 2236 if((pico_time)(PICO_TIME_MS() - s->timestamp) >= PICO_SOCKET_TIMEOUT) {
TASS Belgium NV 131:4758606c9316 2237 /* checking for hanging sockets */
TASS Belgium NV 131:4758606c9316 2238 if((TCP_STATE(s) != PICO_SOCKET_STATE_TCP_LISTEN) && (TCP_STATE(s) != PICO_SOCKET_STATE_TCP_ESTABLISHED))
TASS Belgium NV 131:4758606c9316 2239 return -1;
TASS Belgium NV 131:4758606c9316 2240
TASS Belgium NV 131:4758606c9316 2241 /* if no activity, force the socket into closing state */
TASS Belgium NV 131:4758606c9316 2242 if( TCP_STATE(s) == PICO_SOCKET_STATE_TCP_ESTABLISHED )
TASS Belgium NV 131:4758606c9316 2243 {
TASS Belgium NV 131:4758606c9316 2244 s->wakeup(PICO_SOCK_EV_CLOSE, s);
TASS Belgium NV 131:4758606c9316 2245 pico_socket_close(s);
TASS Belgium NV 131:4758606c9316 2246 s->timestamp = PICO_TIME_MS();
TASS Belgium NV 131:4758606c9316 2247 }
TASS Belgium NV 131:4758606c9316 2248 }
TASS Belgium NV 131:4758606c9316 2249
TASS Belgium NV 131:4758606c9316 2250 return 0;
tass 95:f4ca916a26fe 2251 }
tass 125:96003ae6f1d8 2252 #endif
tass 95:f4ca916a26fe 2253
tass 68:0847e35d08a6 2254 int pico_sockets_loop(int loop_score)
tass 68:0847e35d08a6 2255 {
tass 125:96003ae6f1d8 2256 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 2257 static struct pico_tree_node *index_udp;
tass 125:96003ae6f1d8 2258 #endif
tass 125:96003ae6f1d8 2259
tass 125:96003ae6f1d8 2260 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 2261 static struct pico_tree_node*index_tcp;
tass 125:96003ae6f1d8 2262 #endif
tass 68:0847e35d08a6 2263
TASS Belgium NV 131:4758606c9316 2264 struct pico_sockport *start;
TASS Belgium NV 131:4758606c9316 2265 struct pico_socket *s;
tass 68:0847e35d08a6 2266
tass 68:0847e35d08a6 2267 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 2268 struct pico_frame *f;
tass 68:0847e35d08a6 2269
tass 68:0847e35d08a6 2270 if (sp_udp == NULL)
tass 68:0847e35d08a6 2271 {
TASS Belgium NV 131:4758606c9316 2272 index_udp = pico_tree_firstNode(UDPTable.root);
TASS Belgium NV 131:4758606c9316 2273 sp_udp = index_udp->keyValue;
tass 68:0847e35d08a6 2274 }
TASS Belgium NV 131:4758606c9316 2275
TASS Belgium NV 131:4758606c9316 2276 /* init start node */
TASS Belgium NV 131:4758606c9316 2277 start = sp_udp;
TASS Belgium NV 131:4758606c9316 2278
TASS Belgium NV 131:4758606c9316 2279 /* round-robin all transport protocols, break if traversed all protocols */
TASS Belgium NV 131:4758606c9316 2280 while (loop_score > SL_LOOP_MIN && sp_udp != NULL) {
TASS Belgium NV 131:4758606c9316 2281 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 2282
TASS Belgium NV 131:4758606c9316 2283 pico_tree_foreach(index, &sp_udp->socks){
TASS Belgium NV 131:4758606c9316 2284 s = index->keyValue;
TASS Belgium NV 131:4758606c9316 2285 f = pico_dequeue(&s->q_out);
TASS Belgium NV 131:4758606c9316 2286 while (f && (loop_score > 0)) {
TASS Belgium NV 131:4758606c9316 2287 pico_proto_udp.push(&pico_proto_udp, f);
TASS Belgium NV 131:4758606c9316 2288 loop_score -= 1;
TASS Belgium NV 131:4758606c9316 2289 f = pico_dequeue(&s->q_out);
TASS Belgium NV 131:4758606c9316 2290 }
TASS Belgium NV 131:4758606c9316 2291 }
TASS Belgium NV 131:4758606c9316 2292
TASS Belgium NV 131:4758606c9316 2293 index_udp = pico_tree_next(index_udp);
TASS Belgium NV 131:4758606c9316 2294 sp_udp = index_udp->keyValue;
TASS Belgium NV 131:4758606c9316 2295
TASS Belgium NV 131:4758606c9316 2296 if (sp_udp == NULL)
TASS Belgium NV 131:4758606c9316 2297 {
TASS Belgium NV 131:4758606c9316 2298 index_udp = pico_tree_firstNode(UDPTable.root);
TASS Belgium NV 131:4758606c9316 2299 sp_udp = index_udp->keyValue;
TASS Belgium NV 131:4758606c9316 2300 }
TASS Belgium NV 131:4758606c9316 2301
TASS Belgium NV 131:4758606c9316 2302 if (sp_udp == start)
TASS Belgium NV 131:4758606c9316 2303 break;
TASS Belgium NV 131:4758606c9316 2304 }
tass 68:0847e35d08a6 2305 #endif
tass 68:0847e35d08a6 2306
tass 68:0847e35d08a6 2307 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 2308 if (sp_tcp == NULL)
TASS Belgium NV 131:4758606c9316 2309 {
TASS Belgium NV 131:4758606c9316 2310 index_tcp = pico_tree_firstNode(TCPTable.root);
TASS Belgium NV 131:4758606c9316 2311 sp_tcp = index_tcp->keyValue;
tass 95:f4ca916a26fe 2312 }
tass 68:0847e35d08a6 2313
TASS Belgium NV 131:4758606c9316 2314 /* init start node */
TASS Belgium NV 131:4758606c9316 2315 start = sp_tcp;
tass 68:0847e35d08a6 2316
TASS Belgium NV 131:4758606c9316 2317 while (loop_score > SL_LOOP_MIN && sp_tcp != NULL) {
TASS Belgium NV 131:4758606c9316 2318 struct pico_tree_node *index = NULL, *safe_index = NULL;
TASS Belgium NV 131:4758606c9316 2319 pico_tree_foreach_safe(index, &sp_tcp->socks, safe_index){
TASS Belgium NV 131:4758606c9316 2320 s = index->keyValue;
TASS Belgium NV 131:4758606c9316 2321 loop_score = pico_tcp_output(s, loop_score);
TASS Belgium NV 131:4758606c9316 2322 if ((s->ev_pending) && s->wakeup) {
TASS Belgium NV 131:4758606c9316 2323 s->wakeup(s->ev_pending, s);
TASS Belgium NV 131:4758606c9316 2324 if(!s->parent)
TASS Belgium NV 131:4758606c9316 2325 s->ev_pending = 0;
TASS Belgium NV 131:4758606c9316 2326 }
TASS Belgium NV 131:4758606c9316 2327
TASS Belgium NV 131:4758606c9316 2328 if (loop_score <= 0) {
TASS Belgium NV 131:4758606c9316 2329 loop_score = 0;
TASS Belgium NV 131:4758606c9316 2330 break;
TASS Belgium NV 131:4758606c9316 2331 }
tass 68:0847e35d08a6 2332
TASS Belgium NV 131:4758606c9316 2333 if(checkSocketSanity(s) < 0)
TASS Belgium NV 131:4758606c9316 2334 {
TASS Belgium NV 131:4758606c9316 2335 pico_socket_del(s);
TASS Belgium NV 131:4758606c9316 2336 index_tcp = NULL; /* forcing the restart of loop */
TASS Belgium NV 131:4758606c9316 2337 sp_tcp = NULL;
TASS Belgium NV 131:4758606c9316 2338 break;
TASS Belgium NV 131:4758606c9316 2339 }
TASS Belgium NV 131:4758606c9316 2340 }
TASS Belgium NV 131:4758606c9316 2341
TASS Belgium NV 131:4758606c9316 2342 /* check if RB_FOREACH ended, if not, break to keep the cur sp_tcp */
TASS Belgium NV 131:4758606c9316 2343 if (!index_tcp || (index && index->keyValue))
TASS Belgium NV 131:4758606c9316 2344 break;
TASS Belgium NV 131:4758606c9316 2345
TASS Belgium NV 131:4758606c9316 2346 index_tcp = pico_tree_next(index_tcp);
TASS Belgium NV 131:4758606c9316 2347 sp_tcp = index_tcp->keyValue;
TASS Belgium NV 131:4758606c9316 2348
TASS Belgium NV 131:4758606c9316 2349 if (sp_tcp == NULL)
TASS Belgium NV 131:4758606c9316 2350 {
TASS Belgium NV 131:4758606c9316 2351 index_tcp = pico_tree_firstNode(TCPTable.root);
TASS Belgium NV 131:4758606c9316 2352 sp_tcp = index_tcp->keyValue;
TASS Belgium NV 131:4758606c9316 2353 }
TASS Belgium NV 131:4758606c9316 2354
TASS Belgium NV 131:4758606c9316 2355 if (sp_tcp == start)
TASS Belgium NV 131:4758606c9316 2356 break;
tass 68:0847e35d08a6 2357 }
tass 68:0847e35d08a6 2358 #endif
tass 68:0847e35d08a6 2359
TASS Belgium NV 131:4758606c9316 2360 return loop_score;
tass 68:0847e35d08a6 2361 }
tass 68:0847e35d08a6 2362
tass 68:0847e35d08a6 2363
tass 70:cd218dd180e5 2364 struct pico_frame *pico_socket_frame_alloc(struct pico_socket *s, uint16_t len)
tass 68:0847e35d08a6 2365 {
TASS Belgium NV 131:4758606c9316 2366 struct pico_frame *f = NULL;
tass 68:0847e35d08a6 2367
tass 68:0847e35d08a6 2368 #ifdef PICO_SUPPORT_IPV6
TASS Belgium NV 131:4758606c9316 2369 if (IS_SOCK_IPV6(s))
TASS Belgium NV 131:4758606c9316 2370 f = pico_proto_ipv6.alloc(&pico_proto_ipv6, len);
TASS Belgium NV 131:4758606c9316 2371
tass 68:0847e35d08a6 2372 #endif
tass 68:0847e35d08a6 2373
tass 68:0847e35d08a6 2374 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 2375 if (IS_SOCK_IPV4(s))
TASS Belgium NV 131:4758606c9316 2376 f = pico_proto_ipv4.alloc(&pico_proto_ipv4, (uint16_t)len);
TASS Belgium NV 131:4758606c9316 2377
tass 68:0847e35d08a6 2378 #endif
TASS Belgium NV 131:4758606c9316 2379 if (!f) {
TASS Belgium NV 131:4758606c9316 2380 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 2381 return f;
TASS Belgium NV 131:4758606c9316 2382 }
TASS Belgium NV 131:4758606c9316 2383
TASS Belgium NV 131:4758606c9316 2384 f->payload = f->transport_hdr;
TASS Belgium NV 131:4758606c9316 2385 f->payload_len = len;
TASS Belgium NV 131:4758606c9316 2386 f->sock = s;
tass 68:0847e35d08a6 2387 return f;
tass 68:0847e35d08a6 2388 }
tass 68:0847e35d08a6 2389
tass 68:0847e35d08a6 2390 int pico_transport_error(struct pico_frame *f, uint8_t proto, int code)
tass 68:0847e35d08a6 2391 {
TASS Belgium NV 131:4758606c9316 2392 int ret = -1;
TASS Belgium NV 131:4758606c9316 2393 struct pico_trans *trans = (struct pico_trans*) f->transport_hdr;
TASS Belgium NV 131:4758606c9316 2394 struct pico_sockport *port = NULL;
TASS Belgium NV 131:4758606c9316 2395 struct pico_socket *s = NULL;
TASS Belgium NV 131:4758606c9316 2396 switch (proto) {
tass 68:0847e35d08a6 2397
tass 68:0847e35d08a6 2398
tass 68:0847e35d08a6 2399 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 2400 case PICO_PROTO_UDP:
TASS Belgium NV 131:4758606c9316 2401 port = pico_get_sockport(proto, trans->sport);
TASS Belgium NV 131:4758606c9316 2402 break;
tass 68:0847e35d08a6 2403 #endif
tass 68:0847e35d08a6 2404
tass 68:0847e35d08a6 2405 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 2406 case PICO_PROTO_TCP:
TASS Belgium NV 131:4758606c9316 2407 port = pico_get_sockport(proto, trans->sport);
TASS Belgium NV 131:4758606c9316 2408 break;
tass 68:0847e35d08a6 2409 #endif
tass 68:0847e35d08a6 2410
TASS Belgium NV 131:4758606c9316 2411 default:
TASS Belgium NV 131:4758606c9316 2412 /* Protocol not available */
TASS Belgium NV 131:4758606c9316 2413 ret = -1;
TASS Belgium NV 131:4758606c9316 2414 }
TASS Belgium NV 131:4758606c9316 2415 if (port) {
TASS Belgium NV 131:4758606c9316 2416 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 2417 ret = 0;
tass 68:0847e35d08a6 2418
TASS Belgium NV 131:4758606c9316 2419 pico_tree_foreach(index, &port->socks) {
TASS Belgium NV 131:4758606c9316 2420 s = index->keyValue;
TASS Belgium NV 131:4758606c9316 2421 if (trans->dport == s->remote_port) {
TASS Belgium NV 131:4758606c9316 2422 if (s->wakeup) {
TASS Belgium NV 131:4758606c9316 2423 /* dbg("SOCKET ERROR FROM ICMP NOTIFICATION. (icmp code= %d)\n\n", code); */
TASS Belgium NV 131:4758606c9316 2424 switch(code) {
TASS Belgium NV 131:4758606c9316 2425 case PICO_ICMP_UNREACH_PROTOCOL:
TASS Belgium NV 131:4758606c9316 2426 pico_err = PICO_ERR_EPROTO;
TASS Belgium NV 131:4758606c9316 2427 break;
TASS Belgium NV 131:4758606c9316 2428
TASS Belgium NV 131:4758606c9316 2429 case PICO_ICMP_UNREACH_PORT:
TASS Belgium NV 131:4758606c9316 2430 pico_err = PICO_ERR_ECONNREFUSED;
TASS Belgium NV 131:4758606c9316 2431 break;
tass 68:0847e35d08a6 2432
TASS Belgium NV 131:4758606c9316 2433 case PICO_ICMP_UNREACH_NET:
TASS Belgium NV 131:4758606c9316 2434 case PICO_ICMP_UNREACH_NET_PROHIB:
TASS Belgium NV 131:4758606c9316 2435 case PICO_ICMP_UNREACH_NET_UNKNOWN:
TASS Belgium NV 131:4758606c9316 2436 pico_err = PICO_ERR_ENETUNREACH;
TASS Belgium NV 131:4758606c9316 2437 break;
tass 68:0847e35d08a6 2438
TASS Belgium NV 131:4758606c9316 2439 default:
TASS Belgium NV 131:4758606c9316 2440 pico_err = PICO_ERR_EHOSTUNREACH;
TASS Belgium NV 131:4758606c9316 2441 }
TASS Belgium NV 131:4758606c9316 2442 s->state |= PICO_SOCKET_STATE_SHUT_REMOTE;
TASS Belgium NV 131:4758606c9316 2443 s->wakeup(PICO_SOCK_EV_ERR, s);
tass 122:5b1e9de8bf7f 2444
TASS Belgium NV 131:4758606c9316 2445 }
TASS Belgium NV 131:4758606c9316 2446
TASS Belgium NV 131:4758606c9316 2447 break;
TASS Belgium NV 131:4758606c9316 2448 }
tass 68:0847e35d08a6 2449 }
tass 68:0847e35d08a6 2450 }
TASS Belgium NV 131:4758606c9316 2451
TASS Belgium NV 131:4758606c9316 2452 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 2453 return ret;
tass 68:0847e35d08a6 2454 }
tass 68:0847e35d08a6 2455 #endif
tass 68:0847e35d08a6 2456 #endif