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

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

PicoTCP. Copyright (c) 2013 TASS Belgium NV.

Released under the GNU General Public License, version 2.

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

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

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

Development steps:

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

Demo application (measuring TCP sender performance):

Import programlpc1768-picotcp-demo

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

Committer:
tass picotcp@tass.be
Date:
Fri Feb 07 11:21:12 2014 +0100
Revision:
137:a1c8bfa9d691
Parent:
134:cc4e6d2654d9
Child:
138:0a7a449980e6
Update from masterbranch

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