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

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

PicoTCP. Copyright (c) 2013 TASS Belgium NV.

Released under the GNU General Public License, version 2.

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

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

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

Development steps:

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

Demo application (measuring TCP sender performance):

Import programlpc1768-picotcp-demo

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

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