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