BA
/
BaBoRo1
Embed:
(wiki syntax)
Show/hide line numbers
ns_socket.c
00001 /* 00002 * Copyright (c) 2008-2015, 2017, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 /** 00018 * \file socket.c 00019 * \brief Socket API 00020 * 00021 * The socket API functions 00022 */ 00023 #include "nsconfig.h" 00024 #include "ns_trace.h" 00025 #include <stdio.h> 00026 #include "string.h" 00027 #include "ns_types.h" 00028 #include "randLIB.h" 00029 #include "eventOS_event.h" 00030 #include "eventOS_scheduler.h" 00031 #include "nsdynmemLIB.h" 00032 #include "Core/include/socket.h" 00033 #include "socket_api.h" 00034 #include "NWK_INTERFACE/Include/protocol.h" 00035 #include "Common_Protocols/tcp.h" 00036 #include "Common_Protocols/ipv6.h" 00037 #include "Common_Protocols/icmpv6.h" 00038 #include "ip6string.h" 00039 #include "common_functions.h" 00040 00041 #define TRACE_GROUP "sck" 00042 00043 #define RANDOM_PORT_NUMBER_START 49152 00044 #define RANDOM_PORT_NUMBER_END 65535 00045 #define RANDOM_PORT_NUMBER_COUNT (RANDOM_PORT_NUMBER_END - RANDOM_PORT_NUMBER_START + 1) 00046 #define RANDOM_PORT_NUMBER_MAX_STEP 500 00047 00048 static uint16_t port_counter; 00049 00050 static socket_t *socket_instance[SOCKETS_MAX]; 00051 00052 typedef struct socket_cb_data_t { 00053 int8_t tasklet; 00054 int8_t net_interface_id; 00055 socket_t *socket; 00056 buffer_t *buf; 00057 } socket_cb_data_t; 00058 00059 00060 typedef struct socket_cb_event_t { 00061 socket_t *socket; 00062 uint8_t socket_event; 00063 int8_t interface_id; 00064 uint16_t length; 00065 void *session_ptr; 00066 } socket_cb_event_t; 00067 00068 socket_list_t socket_list = NS_LIST_INIT(socket_list); 00069 00070 static int8_t socket_event_handler = -1; 00071 static uint8_t last_allocated_socket = SOCKETS_MAX - 1; 00072 00073 /** 00074 * Generate random port number between RANDOM_PORT_NUMBER_START and RANDOM_PORT_NUMBER_END. 00075 * 00076 * \return random port number 00077 */ 00078 uint16_t socket_generate_random_port(uint8_t protocol) 00079 { 00080 uint16_t count = RANDOM_PORT_NUMBER_COUNT; 00081 00082 do { 00083 port_counter += randLIB_get_random_in_range(1, RANDOM_PORT_NUMBER_MAX_STEP); 00084 while (port_counter >= RANDOM_PORT_NUMBER_COUNT) { 00085 port_counter -= RANDOM_PORT_NUMBER_COUNT; 00086 } 00087 uint16_t port = RANDOM_PORT_NUMBER_START + port_counter; 00088 if (socket_port_validate(port, protocol) == eOK) { 00089 return port; 00090 } 00091 } while (--count > 0); 00092 00093 return 0; 00094 } 00095 00096 int8_t socket_event_handler_id_get(void) 00097 { 00098 return socket_event_handler; 00099 } 00100 00101 socket_t *socket_pointer_get(int8_t socket) 00102 { 00103 if (socket < 0 || socket >= SOCKETS_MAX) { 00104 return NULL; 00105 } 00106 if (!socket_instance[socket] || socket_instance[socket]->family == SOCKET_FAMILY_NONE) { 00107 return NULL; 00108 } 00109 00110 return socket_instance[socket]; 00111 00112 } 00113 00114 static void socket_data_event_push(buffer_t *buf) 00115 { 00116 arm_event_s event = { 00117 .receiver = socket_event_handler, 00118 .sender = 0, 00119 .event_type = ARM_SOCKET_DATA_CB, 00120 .data_ptr = buf, 00121 .priority = ARM_LIB_HIGH_PRIORITY_EVENT, 00122 }; 00123 00124 if (eventOS_event_send(&event) != 0) { 00125 buffer_free(buf); 00126 } 00127 } 00128 00129 bool socket_data_queued_event_push(socket_t *socket) 00130 { 00131 arm_event_s event = { 00132 .receiver = socket_event_handler, 00133 .sender = 0, 00134 .event_type = ARM_SOCKET_DATA_QUEUED_CB, 00135 .data_ptr = socket_reference(socket), 00136 .priority = ARM_LIB_HIGH_PRIORITY_EVENT, 00137 }; 00138 00139 if (eventOS_event_send(&event) != 0) { 00140 return false; 00141 } 00142 return true; 00143 } 00144 00145 static void socket_cb_event_run(const socket_cb_event_t *event) 00146 { 00147 if (event->socket->id != -1) { 00148 eventOS_scheduler_set_active_tasklet(event->socket->tasklet); 00149 00150 if (event->socket->flags & SOCKET_BUFFER_CB) { 00151 static socket_buffer_callback_t socket_cb_event_buffer; 00152 socket_cb_event_buffer.session_ptr = event->session_ptr; 00153 socket_cb_event_buffer.event_type = event->socket_event; 00154 socket_cb_event_buffer.socket_id = event->socket->id; 00155 socket_cb_event_buffer.buf = 0; 00156 socket_cb_event_buffer.interface_id = event->interface_id; 00157 event->socket->u.live.fptr(&socket_cb_event_buffer); 00158 socket_cb_event_buffer.session_ptr = 0; 00159 } else { 00160 static socket_callback_t socket_cb_event_stucture; 00161 socket_cb_event_stucture.event_type = event->socket_event; 00162 socket_cb_event_stucture.socket_id = event->socket->id; 00163 socket_cb_event_stucture.d_len = event->length; 00164 socket_cb_event_stucture.interface_id = event->interface_id; 00165 event->socket->u.live.fptr(&socket_cb_event_stucture); 00166 } 00167 } 00168 } 00169 00170 void socket_buffer_cb_run(socket_t *socket, buffer_t *buffer) 00171 { 00172 if (socket->id == -1 || !socket->u.live.fptr) { 00173 buffer_free(buffer); 00174 return; 00175 } 00176 00177 eventOS_scheduler_set_active_tasklet(socket->tasklet ); 00178 00179 static socket_buffer_callback_t socket_cb_buffer; 00180 socket_cb_buffer.event_type = SOCKET_DATA; 00181 socket_cb_buffer.socket_id = socket->id ; 00182 socket_cb_buffer.interface_id = buffer->interface ->id; 00183 socket_cb_buffer.buf = buffer; 00184 socket_cb_buffer.session_ptr = NULL; 00185 00186 socket->u.live.fptr(&socket_cb_buffer); 00187 } 00188 00189 void socket_cb_run(socket_t *socket) 00190 { 00191 if (socket->id == -1 || !socket->u.live.fptr) { 00192 return; 00193 } 00194 00195 buffer_t *buf = ns_list_get_first(&socket->rcvq.bufs); 00196 00197 eventOS_scheduler_set_active_tasklet(socket->tasklet ); 00198 00199 static socket_callback_t socket_cb_structure; 00200 00201 socket_cb_structure.event_type = SOCKET_DATA; 00202 socket_cb_structure.socket_id = socket->id ; 00203 socket_cb_structure.interface_id = buf ? buf->interface ->id : 0; 00204 socket_cb_structure.LINK_LQI = buf ? buf->options .lqi : 0; 00205 socket_cb_structure.d_len = socket->rcvq.data_bytes; 00206 00207 socket->u.live.fptr(&socket_cb_structure); 00208 } 00209 00210 void socket_tasklet_event_handler(arm_event_s *event) 00211 { 00212 switch (event->event_type) { 00213 case ARM_SOCKET_INIT: 00214 tr_debug("Socket Tasklet Generated"); 00215 break; 00216 case ARM_SOCKET_EVENT_CB: { 00217 socket_cb_event_t *cb_event_ptr = event->data_ptr; 00218 socket_cb_event_run(cb_event_ptr); 00219 socket_dereference(cb_event_ptr->socket); 00220 ns_dyn_mem_free(cb_event_ptr); 00221 break; 00222 } 00223 case ARM_SOCKET_DATA_CB: { 00224 buffer_t *buf = event->data_ptr; 00225 /* Reference the socket here*/ 00226 socket_t *socket = socket_reference(buf->socket ); 00227 if (socket->flags & SOCKET_BUFFER_CB) { 00228 // They just take ownership of the buffer. No read calls. 00229 socket_buffer_cb_run(socket, buf); 00230 } else { 00231 // Emulate old one-callback-per-buffer behavior. Make sure 00232 // the recv queue is empty, then put this buffer on it, then 00233 // make the callback. Their read calls then read from the 00234 // recv queue. After the callback, flush the receive queue again. 00235 sockbuf_flush(&socket->rcvq); 00236 sockbuf_append(&socket->rcvq, buf); 00237 socket_cb_run(socket); 00238 sockbuf_flush(&socket->rcvq); 00239 } 00240 /* Dereference the socket here*/ 00241 socket_dereference(socket); 00242 break; 00243 } 00244 case ARM_SOCKET_DATA_QUEUED_CB: { 00245 socket_t *socket = event->data_ptr; 00246 socket_cb_run(socket); 00247 socket_dereference(socket); 00248 break; 00249 } 00250 case ARM_SOCKET_TCP_TIMER_CB: 00251 tcp_handle_time_event((uint16_t)event->event_data); 00252 break; 00253 00254 default: 00255 break; 00256 } 00257 } 00258 /** 00259 * Initialize API 00260 */ 00261 void socket_init(void) 00262 { 00263 if (socket_event_handler == -1) { 00264 socket_event_handler = eventOS_event_handler_create(&socket_tasklet_event_handler, ARM_SOCKET_INIT); 00265 } 00266 00267 port_counter = randLIB_get_random_in_range(0, RANDOM_PORT_NUMBER_COUNT - 1); 00268 } 00269 00270 /** 00271 * Release a socket (detaching from application) 00272 * 00273 * We are either releasing directly from an application close (ID being freed, 00274 * reference being removed from ID table), or indirectly - a pending socket 00275 * attached to a listening socket being closed. 00276 * 00277 * \param socket socket pointer 00278 */ 00279 void socket_release(socket_t *socket) 00280 { 00281 socket->flags |= SOCKET_FLAG_CLOSED | SOCKET_FLAG_SHUT_WR | SOCKET_FLAG_CANT_RECV_MORE; 00282 00283 if (socket_is_ipv6(socket)) { 00284 // Do TCP cleanup first, while we have one reference count of our own, 00285 // so it can't make socket vanish. 00286 // Take care never to put tcp_info in local variable - these calls can delete it 00287 if (tcp_info(socket->inet_pcb )) { 00288 /* This may trigger a reset if pending data. Do it first so you 00289 * get just the reset, rather than a FIN. */ 00290 tcp_session_shutdown_read(tcp_info(socket->inet_pcb )); 00291 /* This can also cause TCP deletion */ 00292 if (tcp_info(socket->inet_pcb )) { 00293 tcp_session_close(tcp_info(socket->inet_pcb )); 00294 } 00295 if (tcp_info(socket->inet_pcb )) { 00296 tcp_socket_released(tcp_info(socket->inet_pcb )); 00297 } 00298 } else { 00299 /* Unbind the internet control block - ensures users are not prevented 00300 * from binding a new socket to the same port if the socket lingers 00301 * on due to pending events/buffers. (And also means the new socket 00302 * gets any such packets, with this getting none). 00303 */ 00304 memcpy(socket->inet_pcb ->local_address , ns_in6addr_any, 16); 00305 memcpy(socket->inet_pcb ->remote_address , ns_in6addr_any, 16); 00306 socket->inet_pcb ->local_port = 0; 00307 socket->inet_pcb ->remote_port = 0; 00308 socket->inet_pcb ->protocol = 0; 00309 } 00310 sockbuf_flush(&socket->rcvq); 00311 } 00312 00313 if (!(socket->flags & SOCKET_FLAG_PENDING)) { 00314 // Release any pending sockets in a listening socket's queue 00315 ns_list_foreach_safe(socket_t, pending, &socket->u.live.queue) { 00316 // Release of a pending socket will make it non-pending and 00317 // hence take it off our queue (see immediately below) making 00318 // this loop work. (And maybe it will free it too). 00319 socket_release(pending); 00320 } 00321 } else { 00322 // This may make socket vanish, as leaving pending decrements count 00323 socket_leave_pending_state(socket, NULL); 00324 } 00325 } 00326 00327 static void socket_free(socket_t *socket) 00328 { 00329 if (socket->refcount != 0) { 00330 tr_err("free refed"); 00331 } 00332 if (socket->flags & SOCKET_FLAG_PENDING) { 00333 tr_err("free pending"); 00334 } 00335 ns_list_remove(&socket_list, socket); 00336 sockbuf_flush(&socket->rcvq); 00337 sockbuf_flush(&socket->sndq); 00338 00339 socket_inet_pcb_free(socket->inet_pcb ); 00340 ns_dyn_mem_free(socket); 00341 } 00342 00343 error_t socket_port_validate(uint16_t port, uint8_t protocol) 00344 { 00345 ns_list_foreach(socket_t, socket, &socket_list) { 00346 if (!socket_is_ipv6(socket)) { 00347 continue; 00348 } 00349 if (socket->inet_pcb ->local_port == port && socket->inet_pcb ->protocol == protocol) { 00350 return eFALSE; 00351 } 00352 } 00353 return eOK; 00354 } 00355 00356 int8_t socket_id_assign_and_attach(socket_t *socket) 00357 { 00358 int pos = last_allocated_socket + 1; 00359 00360 for (int i=0; i < SOCKETS_MAX; i++, pos++) { 00361 if (pos >= SOCKETS_MAX) { 00362 pos = 0; 00363 } 00364 if (socket_instance[pos] == NULL) { 00365 socket->id = pos; 00366 socket_instance[pos] = socket_reference(socket); 00367 last_allocated_socket = pos; 00368 return pos; 00369 } 00370 } 00371 return -1; 00372 } 00373 00374 void socket_id_detach(int8_t sid) 00375 { 00376 socket_t *socket = socket_instance[sid]; 00377 socket->id = -1; 00378 socket_release(socket); 00379 socket_instance[sid] = socket_dereference(socket); 00380 } 00381 00382 inet_pcb_t *socket_inet_pcb_allocate(void) 00383 { 00384 inet_pcb_t *inet_pcb = ns_dyn_mem_alloc(sizeof(inet_pcb_t)); 00385 if (!inet_pcb) { 00386 return NULL; 00387 } 00388 00389 memset(inet_pcb, 0, sizeof(inet_pcb_t)); 00390 #ifndef NO_TCP 00391 inet_pcb->session = NULL; 00392 #endif 00393 inet_pcb->unicast_hop_limit = -1; 00394 inet_pcb->multicast_hop_limit = 1; 00395 inet_pcb->multicast_if = 0; 00396 inet_pcb->multicast_loop = true; 00397 inet_pcb->socket = NULL; 00398 inet_pcb->addr_preferences = 0; 00399 inet_pcb->recvhoplimit = false; 00400 inet_pcb->recvpktinfo = false; 00401 inet_pcb->recvtclass = false; 00402 inet_pcb->link_layer_security = -1; 00403 #ifndef NO_IPV6_PMTUD 00404 inet_pcb->use_min_mtu = -1; 00405 #endif 00406 #ifndef NO_IP_FRAGMENT_TX 00407 inet_pcb->dontfrag = 0; 00408 #endif 00409 inet_pcb->tclass = SOCKET_IPV6_TCLASS_DEFAULT; 00410 inet_pcb->flow_label = IPV6_FLOW_UNSPECIFIED; 00411 ns_list_init(&inet_pcb->mc_groups); 00412 00413 return inet_pcb; 00414 } 00415 00416 inet_pcb_t *socket_inet_pcb_clone(const inet_pcb_t *orig) 00417 { 00418 inet_pcb_t *inet_pcb = ns_dyn_mem_alloc(sizeof(inet_pcb_t)); 00419 if (!inet_pcb) { 00420 return NULL; 00421 } 00422 *inet_pcb = *orig; 00423 inet_pcb->socket = NULL; 00424 #ifndef NO_TCP 00425 inet_pcb->session = NULL; 00426 #endif 00427 return inet_pcb; 00428 } 00429 00430 00431 socket_t *socket_allocate(socket_type_t type) 00432 { 00433 socket_t *socket = ns_dyn_mem_alloc(sizeof(socket_t)); 00434 if (!socket) { 00435 return NULL; 00436 } 00437 memset(socket, 0, sizeof *socket); 00438 socket->id = -1; 00439 socket->type = type; 00440 socket->family = SOCKET_FAMILY_NONE; 00441 sockbuf_init(&socket->rcvq); 00442 sockbuf_init(&socket->sndq); 00443 if (type == SOCKET_TYPE_STREAM) { 00444 socket->sndq.low_water_mark = SOCKET_DEFAULT_STREAM_SNDLOWAT; 00445 sockbuf_reserve(&socket->rcvq, SOCKET_DEFAULT_STREAM_RCVBUF); 00446 sockbuf_reserve(&socket->sndq, SOCKET_DEFAULT_STREAM_SNDBUF); 00447 } 00448 00449 ns_list_add_to_end(&socket_list, socket); 00450 return socket; 00451 } 00452 00453 /* Increase reference counter on socket, returning now-owned pointer */ 00454 socket_t *socket_reference(socket_t *socket_ptr) 00455 { 00456 if (!socket_ptr) { 00457 return NULL; 00458 } 00459 00460 socket_ptr->refcount++; 00461 if (socket_ptr->refcount == 0) { 00462 socket_ptr->refcount--; 00463 tr_error("ref overflow"); 00464 } 00465 00466 return socket_ptr; 00467 } 00468 00469 /* Decrease reference counter on socket, releasing if it hits zero */ 00470 /* Always returns NULL to indicate caller no longer owns it */ 00471 socket_t *socket_dereference(socket_t *socket_ptr) 00472 { 00473 if (!socket_ptr) { 00474 return NULL; 00475 } 00476 00477 if (socket_ptr->refcount == 0) { 00478 tr_error("ref underflow"); 00479 return NULL; 00480 } 00481 if (--socket_ptr->refcount == 0) { 00482 socket_free(socket_ptr); 00483 } 00484 return NULL; 00485 } 00486 00487 00488 /** 00489 * Allocate a socket 00490 * 00491 * \param sid pointer to socket ID which will contain socket ID 00492 * \param port listen port for socket 00493 * 00494 * \return eOK socket opened 00495 * \return eFALSE no free sockets 00496 * \return eBUSY port reserved 00497 */ 00498 error_t socket_create(socket_family_t family, socket_type_t type, uint8_t protocol, int8_t *sid, uint16_t port, void (*passed_fptr)(void *), bool buffer_type) 00499 { 00500 if (sid) { 00501 *sid = -1; 00502 } 00503 00504 if (passed_fptr == 0) { 00505 return eFALSE; 00506 } 00507 00508 /* Note that IPv6 socket lookup implementation assumes we don't have raw 00509 * TCP or UDP sockets, thus we ensure protocol=UDP iff type=DGRAM, 00510 * and protocol=TCP iff type=STREAM. 00511 */ 00512 if (family == SOCKET_FAMILY_IPV6) { 00513 switch (type) { 00514 case SOCKET_TYPE_DGRAM: 00515 protocol = IPV6_NH_UDP; 00516 break; 00517 case SOCKET_TYPE_STREAM: 00518 protocol = IPV6_NH_TCP; 00519 break; 00520 default: 00521 if (protocol == 0 || protocol == IPV6_NH_TCP || protocol == IPV6_NH_UDP) { 00522 return eFALSE; 00523 } 00524 port = 0xFFFF; 00525 break; 00526 } 00527 } else { 00528 /* SOCKET_FAMILY_LOCAL still has inet_pcb - give it 0 protocol */ 00529 protocol = 0; 00530 port = 0xFFFF; 00531 } 00532 00533 if (port != 0 && socket_port_validate(port, protocol) == eFALSE) { 00534 return eBUSY; 00535 } 00536 00537 socket_t *socket = socket_allocate(type); 00538 if (socket == NULL) { 00539 tr_error("Socket allocation fail"); 00540 return eFALSE; 00541 } 00542 inet_pcb_t *inet_pcb = socket_inet_pcb_allocate(); 00543 if (inet_pcb == NULL) { 00544 socket_free(socket); // don't leave half initialized sockets behind 00545 tr_error("inet_pcb allocation fail"); 00546 return eFALSE; 00547 } 00548 socket->inet_pcb = inet_pcb; 00549 00550 *sid = socket_id_assign_and_attach(socket); 00551 if (*sid == -1) { 00552 tr_error("Socket IDs exhausted"); 00553 socket_free(socket); 00554 return eFALSE; 00555 } 00556 00557 00558 socket->flags = 0; 00559 00560 tr_debug("Socket id %d allocated", socket->id ); 00561 socket->tasklet = eventOS_scheduler_get_active_tasklet(); 00562 socket->family = family; 00563 socket->u.live.fptr = passed_fptr; 00564 ns_list_init(&socket->u.live.queue); 00565 socket->default_interface_id = -1; 00566 socket->broadcast_pan = 0; 00567 if (buffer_type) { 00568 socket->flags |= SOCKET_BUFFER_CB; 00569 } 00570 00571 // Fill Internet protocol control block 00572 inet_pcb->protocol = protocol; 00573 inet_pcb->local_port = port; 00574 inet_pcb->socket = socket; 00575 00576 return eOK; 00577 } 00578 00579 socket_t *socket_new_incoming_connection(socket_t *listen_socket) 00580 { 00581 if (!socket_validate_listen_backlog(listen_socket)) { 00582 return NULL; 00583 } 00584 socket_t *new_socket = socket_allocate(listen_socket->type); 00585 if (!new_socket) { 00586 return NULL; 00587 } 00588 inet_pcb_t *inet_pcb = socket_inet_pcb_clone(listen_socket->inet_pcb ); 00589 if (!inet_pcb) { 00590 socket_free(new_socket); 00591 return NULL; 00592 } 00593 inet_pcb->socket = new_socket; 00594 // They can fill this in on return 00595 new_socket->inet_pcb = inet_pcb; 00596 new_socket->flags = SOCKET_FLAG_PENDING | SOCKET_FLAG_CONNECTING; 00597 new_socket->family = listen_socket->family; 00598 new_socket->type = listen_socket->type; 00599 new_socket->default_interface_id = listen_socket->default_interface_id; 00600 new_socket->broadcast_pan = listen_socket->broadcast_pan; 00601 new_socket->tasklet = listen_socket->tasklet ; 00602 new_socket->u.pending.listen_head = listen_socket; 00603 ns_list_add_to_end(&listen_socket->u.live.queue, socket_reference(new_socket)); 00604 00605 return new_socket; 00606 } 00607 00608 /* Connection did not complete or was abandoned - notification from transport */ 00609 void socket_connection_abandoned(socket_t *socket, int8_t interface_id, uint8_t reason) 00610 { 00611 if (!(socket->flags & (SOCKET_FLAG_CONNECTING|SOCKET_FLAG_CONNECTED))) { 00612 tr_err("abandoned: not connecting/connected"); 00613 return; 00614 } 00615 socket->flags &=~ SOCKET_FLAG_CONNECTING; 00616 // leaving CONNECTED flag set prevents weirdness like reconnecting. Good idea? 00617 socket->flags |= SOCKET_FLAG_SHUT_WR | SOCKET_FLAG_CANT_RECV_MORE | SOCKET_FLAG_CONNECTED; 00618 sockbuf_flush(&socket->sndq); 00619 if (socket->flags & SOCKET_FLAG_PENDING) { 00620 // By leaving pending state, without any remaining reference, 00621 // we just let the failed connection go away, without notifying user 00622 socket_leave_pending_state(socket, NULL); 00623 // Hard to say if this is right if it was fully connected, but seems the best 00624 // we can do for the minute - we can't queue up the reset/whatever event. 00625 } else if (reason != 0) { 00626 socket_event_push(reason, socket, interface_id, NULL, 0); 00627 } 00628 } 00629 00630 /* Connection has completed - notification from transport */ 00631 void socket_connection_complete(socket_t *socket, int8_t interface_id) 00632 { 00633 if (!(socket->flags & SOCKET_FLAG_CONNECTING)) { 00634 tr_err("complete: not connecting"); 00635 return; 00636 } 00637 if (socket->flags & SOCKET_FLAG_CONNECTED) { 00638 tr_err("complete: already connected"); 00639 return; 00640 } 00641 socket->flags &=~ SOCKET_FLAG_CONNECTING; 00642 socket->flags |= SOCKET_FLAG_CONNECTED; 00643 if (socket->flags & SOCKET_FLAG_PENDING) { 00644 socket_event_push(SOCKET_INCOMING_CONNECTION, socket->u.pending.listen_head, interface_id, NULL, 0); 00645 } else { 00646 socket_event_push(SOCKET_CONNECT_DONE, socket, interface_id, NULL, 0); 00647 } 00648 } 00649 00650 /* Socket is to leave pending state - either being accepted or released */ 00651 void socket_leave_pending_state(socket_t *socket, void (*fptr)(void *)) 00652 { 00653 if (!(socket->flags & SOCKET_FLAG_PENDING)) { 00654 tr_err("not pending"); 00655 return; 00656 } 00657 ns_list_remove(&socket->u.pending.listen_head->u.live.queue, socket); 00658 socket->flags &= ~SOCKET_FLAG_PENDING; 00659 ns_list_init(&socket->u.live.queue); 00660 socket->u.live.fptr = fptr; 00661 socket_dereference(socket); 00662 } 00663 00664 void socket_cant_recv_more(socket_t *socket, int8_t interface_id) 00665 { 00666 socket->flags |= SOCKET_FLAG_CANT_RECV_MORE; 00667 socket_event_push(SOCKET_DATA, socket, interface_id, 0, 0); 00668 } 00669 00670 socket_t *socket_lookup_ipv6(uint8_t protocol, const sockaddr_t *local_addr, const sockaddr_t *remote_addr, bool allow_wildcards) 00671 { 00672 //tr_debug("socket_lookup() local=%s [%d] remote=%s [%d]", trace_ipv6(local_addr->address), local_addr->port, trace_ipv6(remote_addr->address), remote_addr->port); 00673 ns_list_foreach(socket_t, socket, &socket_list) { 00674 if (!socket_is_ipv6(cur)) { 00675 continue; 00676 } 00677 inet_pcb_t *cur = socket->inet_pcb ; 00678 //tr_debug("cur local=%s [%d] remote=%s [%d]", trace_ipv6(cur->local_address), cur->local_port, trace_ipv6(cur->remote_address), cur->remote_port); 00679 /* Protocol must match */ 00680 if (cur->protocol != protocol) { 00681 continue; 00682 } 00683 00684 /* For TCP and UDP only, ports must match */ 00685 if (protocol == IPV6_NH_UDP || protocol == IPV6_NH_TCP) { 00686 if (cur->local_port == 0 || cur->local_port != local_addr->port ) { 00687 continue; 00688 } 00689 if (!(allow_wildcards && cur->remote_port == 0) && cur->remote_port != remote_addr->port ) { 00690 continue; 00691 } 00692 } 00693 00694 if (!(allow_wildcards && addr_ipv6_equal(cur->local_address , ns_in6addr_any))) { 00695 if (!addr_ipv6_equal(cur->local_address , local_addr->address )) { 00696 continue; 00697 } 00698 } 00699 00700 if (!(allow_wildcards && addr_ipv6_equal(cur->remote_address , ns_in6addr_any))) { 00701 if (!addr_ipv6_equal(cur->remote_address , remote_addr->address )) { 00702 continue; 00703 } 00704 } 00705 00706 return socket; 00707 } 00708 00709 return NULL; 00710 } 00711 00712 /* Write address + port neatly to out, returning characters written */ 00713 /* Maximum output length is 48, including the terminator, assuming ip6tos limited to 39 */ 00714 static int sprint_addr(char *out, const uint8_t addr[static 16], uint16_t port) 00715 { 00716 char *init_out = out; 00717 if (addr_is_ipv6_unspecified(addr)) { 00718 *out++ = '*'; 00719 } else { 00720 *out++ = '['; 00721 out += ip6tos(addr, out); 00722 *out++ = ']'; 00723 } 00724 00725 *out++ = ':'; 00726 if (port == 0) { 00727 *out++ = '*'; 00728 } else { 00729 out += sprintf(out, "%"PRIu16, port); 00730 } 00731 *out = '\0'; 00732 return (int) (out - init_out); 00733 } 00734 00735 static void socket_print(const socket_t *socket, int lwidth, int rwidth, route_print_fn_t *print_fn, char sep) 00736 { 00737 if (!socket_is_ipv6(socket)) { 00738 return; 00739 } 00740 const inet_pcb_t *pcb = socket->inet_pcb ; 00741 char remote_str[48]; 00742 char local_str[48]; 00743 00744 char proto_buf[4]; 00745 const char *proto_str; 00746 switch (pcb->protocol ) { 00747 case IPV6_NH_TCP: 00748 proto_str = "TCP"; 00749 break; 00750 case IPV6_NH_UDP: 00751 proto_str = "UDP"; 00752 break; 00753 case IPV6_NH_ICMPV6: 00754 proto_str = "ICMP6"; 00755 break; 00756 default: 00757 sprintf(proto_buf, "%"PRIu8, pcb->protocol ); 00758 proto_str = proto_buf; 00759 break; 00760 } 00761 sprint_addr(local_str, pcb->local_address , pcb->local_port ); 00762 sprint_addr(remote_str, pcb->remote_address , pcb->remote_port ); 00763 00764 const char *state = ""; 00765 if (pcb->protocol == IPV6_NH_TCP) { 00766 if (tcp_info(pcb)) { 00767 state = tcp_state_name(tcp_info(pcb)); 00768 } else if (socket->flags & SOCKET_LISTEN_STATE) { 00769 state = "LISTEN"; 00770 } else { 00771 state = "CLOSED"; 00772 } 00773 } 00774 print_fn("%3.*"PRId8"%c%3u%c%6"PRId32/*"%c%6"PRId32*/"%c%6"PRId32"%c%-5.5s%c%-*s%c%-*s%c%s", 00775 socket->id >= 0 ? 1 : 0, socket->id >= 0 ? socket->id : 0, sep, 00776 socket->refcount, sep, 00777 socket->rcvq.data_bytes,sep, 00778 /*socket->rcvq.buf_overhead_bytes, sep,*/ 00779 socket->sndq.data_bytes, sep, 00780 proto_str, sep, 00781 lwidth, local_str, sep, 00782 rwidth, remote_str, sep, 00783 state); 00784 } 00785 00786 void socket_list_print(route_print_fn_t *print_fn, char sep) 00787 { 00788 int lwidth = 18, rwidth = 18; 00789 ns_list_foreach(const socket_t, socket, &socket_list) { 00790 if (!socket_is_ipv6(socket)) { 00791 continue; 00792 } 00793 const inet_pcb_t *pcb = socket->inet_pcb ; 00794 char addr[48]; 00795 int len; 00796 len = sprint_addr(addr, pcb->local_address , pcb->local_port ); 00797 if (lwidth < len) { 00798 lwidth = len; 00799 } 00800 len = sprint_addr(addr, pcb->remote_address , pcb->remote_port ); 00801 if (rwidth < len) { 00802 rwidth = len; 00803 } 00804 } 00805 print_fn("Sck%cRef%cRecv-Q%c"/*"Recv-B%c"*/"Send-Q%cProto%c%-*s%c%-*s%c(state)", sep, sep, sep, /*sep,*/ sep, sep, lwidth, "Local Address", sep, rwidth, "Remote Address", sep); 00806 ns_list_foreach(const socket_t, socket, &socket_list) { 00807 socket_print(socket, lwidth, rwidth, print_fn, sep); 00808 } 00809 00810 /* Chuck in a consistency check */ 00811 for (int i = 0; i < SOCKETS_MAX; i++) { 00812 if (socket_instance[i] && socket_instance[i]->id != i) { 00813 tr_err("ID %d points to %p with id %d\n", i, (void *)socket_instance[i], socket_instance[i]->id); 00814 } 00815 } 00816 ns_list_foreach(socket_t, socket, &socket_list) { 00817 if (socket->id != -1 && socket_pointer_get(socket->id ) != socket) { 00818 tr_err("Socket %p has invalid ID %d\n", (void *)socket, socket->id ); 00819 } 00820 sockbuf_check(&socket->rcvq); 00821 sockbuf_check(&socket->sndq); 00822 } 00823 } 00824 00825 socket_t *socket_lookup(socket_family_t family, uint8_t protocol, const sockaddr_t *local_addr, const sockaddr_t *remote_addr) 00826 { 00827 switch (family) { 00828 case SOCKET_FAMILY_IPV6: 00829 return socket_lookup_ipv6(protocol, local_addr, remote_addr, true); 00830 default: 00831 return NULL; 00832 } 00833 } 00834 00835 /** 00836 * Push a buffer to a socket 00837 * 00838 * Used by the protocol core to push buffers to sockets. 00839 * 00840 * To determine the socket to send to, transport layer must ensure either: 00841 * a) buf->socket_id already filled in, or 00842 * b) buf->options.type is socket family (IPv6/Local) 00843 * buf->options.code is protocol (IPv6=NH,Local=n/a) 00844 * 00845 * \param buf buffer to push 00846 * 00847 * \return eOK socket opened 00848 * \return eFALSE no socket found 00849 * \return eBUSY socket full 00850 */ 00851 error_t socket_up(buffer_t *buf) 00852 { 00853 socket_t *socket = buf->socket ; 00854 00855 if (!socket) { 00856 socket = socket_lookup((socket_family_t) buf->options .type , buf->options .code , &buf->dst_sa , &buf->src_sa ); 00857 00858 if (!socket) { 00859 //tr_debug("Socket:Drop"); 00860 goto drop; 00861 } 00862 buffer_socket_set(buf, socket); 00863 } 00864 00865 if ((socket->flags & (SOCKET_FLAG_PENDING|SOCKET_FLAG_CLOSED)) || socket->id == -1) { 00866 goto drop; 00867 } 00868 00869 if (socket->rcvq.data_byte_limit == 0) { 00870 // Old-style one event per buffer 00871 socket_data_event_push(buf); 00872 } else { 00873 // Queuing enabled - new-style events 00874 if (sockbuf_space(&socket->rcvq) < buffer_data_length(buf)) { 00875 tr_debug("Socket %d Recv-Q full", socket->id ); 00876 goto drop; 00877 } 00878 bool pushed = socket_data_queued_event_push(socket); 00879 // if this failed, it means total memory exhaustion - safest to drop the packet 00880 if (!pushed) { 00881 goto drop; 00882 } 00883 sockbuf_append(&socket->rcvq, buf); 00884 } 00885 return eOK; 00886 00887 drop: 00888 buffer_free(buf); 00889 return eFALSE; 00890 } 00891 00892 void socket_event_push(uint8_t sock_event, socket_t *socket, int8_t interface_id, void *session_ptr, uint16_t length) 00893 { 00894 if (socket->flags & (SOCKET_FLAG_PENDING|SOCKET_FLAG_CLOSED)) { 00895 return; 00896 } 00897 00898 socket_cb_event_t *cb_event = ns_dyn_mem_temporary_alloc(sizeof(socket_cb_event_t)); 00899 if (cb_event) { 00900 cb_event->socket = socket_reference(socket); 00901 cb_event->socket_event = sock_event; 00902 cb_event->session_ptr = session_ptr; 00903 cb_event->interface_id = interface_id; 00904 cb_event->length = length; 00905 arm_event_s event = { 00906 .receiver = socket_event_handler, 00907 .sender = 0, 00908 .data_ptr = cb_event, 00909 .event_type = ARM_SOCKET_EVENT_CB, 00910 .priority = ARM_LIB_HIGH_PRIORITY_EVENT, 00911 }; 00912 if (eventOS_event_send(&event) != 0) { 00913 socket_dereference(socket); 00914 ns_dyn_mem_free(cb_event); 00915 } 00916 } 00917 } 00918 00919 00920 /* Fill in a buffer's hop limit, based on the user's socket options */ 00921 void socket_inet_pcb_set_buffer_hop_limit(const inet_pcb_t *inet_pcb, buffer_t *buf, const int16_t *msg_hoplimit) 00922 { 00923 /* If hop limit specified by ancillary data, obey that over socket options */ 00924 if (msg_hoplimit) { 00925 if (*msg_hoplimit != -1) { 00926 /* Use the value they gave for this message */ 00927 buf->options .hop_limit = *msg_hoplimit; 00928 return; 00929 } 00930 /* If -1, we will go with the default, ignoring socket options */ 00931 } else if (addr_is_ipv6_multicast(buf->dst_sa .address )) { 00932 /* Multicasts have a fixed default - multicast_hop_limit will be user-specified, or that default */ 00933 buf->options .hop_limit = inet_pcb->multicast_hop_limit; 00934 return; 00935 } else if (inet_pcb->unicast_hop_limit != -1) { 00936 /* If the user specified a unicast hop limit, use it */ 00937 buf->options .hop_limit = inet_pcb->unicast_hop_limit ; 00938 return; 00939 } 00940 00941 /* User didn't specify a unicast hop limit, get the per-interface default */ 00942 /* At the moment we can only rely on if_index in the down direction, not id */ 00943 protocol_interface_info_entry_t *cur = buf->interface ; 00944 buf->options .hop_limit = cur->cur_hop_limit; 00945 } 00946 00947 /** 00948 * Calculate message payload length and validate message header iov vectors 00949 */ 00950 bool socket_message_validate_iov(const ns_msghdr_t *msg, uint16_t *length_out) 00951 { 00952 if (msg->msg_iovlen != 0 && !msg->msg_iov) { 00953 return false; 00954 } 00955 00956 uint16_t msg_length = 0; 00957 ns_iovec_t *msg_iov = msg->msg_iov; 00958 for (uint_fast16_t i = 0; i < msg->msg_iovlen; i++) { 00959 if (msg_iov->iov_len != 0 && !msg_iov->iov_base) { 00960 return false; 00961 } 00962 msg_length += msg_iov->iov_len; 00963 if (msg_length < msg_iov->iov_len) { 00964 return false; 00965 } 00966 msg_iov++; 00967 } 00968 00969 if (length_out) { 00970 *length_out = msg_length; 00971 } 00972 00973 return true; 00974 } 00975 00976 /** 00977 * Write a data buffer to a socket 00978 * 00979 * Used by the application to send data with meta data from msg 00980 * 00981 * Data will be taken either from buf if non-NULL else from msg->msg_iov. 00982 * 00983 * Using buf is not permitted for stream sockets. 00984 * 00985 * \param sid socket id 00986 * \param buf pointer to buffer is plain buffer with payload only - all metadata ignored 00987 * \param msg pointer to message-specific data message name define destination address and control message define ancillary data 00988 * 00989 * \return 0 Ok done 00990 * \return -1 Unsupported socket or message parameter 00991 * \return -5 Socket not properly connected 00992 * \return -6 Packet too short 00993 */ 00994 int16_t socket_buffer_sendmsg(int8_t sid, buffer_t *buf, const struct ns_msghdr *msg, int flags) 00995 { 00996 int8_t ret_val; 00997 int8_t interface_id = -1; 00998 00999 const int16_t *msg_hoplimit = NULL; 01000 uint16_t payload_length; 01001 01002 //Validate socket id 01003 socket_t *socket_ptr = socket_pointer_get(sid); 01004 01005 if (!socket_ptr || !socket_ptr->inet_pcb ) { 01006 tr_warn("Socket Id %i", sid); 01007 ret_val = -1; 01008 goto fail; 01009 } 01010 inet_pcb_t *inet_pcb = socket_ptr->inet_pcb ; 01011 01012 if (buf) { 01013 payload_length = buffer_data_length(buf); 01014 } else { 01015 if (!socket_message_validate_iov(msg, &payload_length)) { 01016 return -1; 01017 } 01018 } 01019 01020 #ifndef NO_TCP 01021 /* Special handling for stream - basically no advanced features of sendmsg operate. 01022 * Can't set address, can't set ancilliary data. 01023 * Don't want to fill in other sticky options into buffer - TCP must handle this itself, 01024 * as it must do it for all packets, not just those coming from sendmsg. 01025 */ 01026 if (socket_ptr->type == SOCKET_TYPE_STREAM) { 01027 /* Stream sockets must be connected and not shutdown for write */ 01028 if ((socket_ptr->flags & (SOCKET_FLAG_CONNECTED|SOCKET_FLAG_SHUT_WR)) != SOCKET_FLAG_CONNECTED) { 01029 ret_val = -5; 01030 goto fail; 01031 } 01032 01033 /* Stream sockets cannot have address specified (POSIX "EISCONN") */ 01034 if (msg && msg->msg_name && msg->msg_namelen) { 01035 ret_val = -5; 01036 goto fail; 01037 } 01038 01039 if (payload_length == 0) { 01040 goto success; // Sending nothing is a no-op 01041 } 01042 01043 // Figure out how much we can actually take, and reduce 01044 // payload_length if necessary (but if fed a buffer, we always just 01045 // accept the whole thing). 01046 if (!buf) { 01047 int32_t space = sockbuf_space(&socket_ptr->sndq); 01048 if (space < payload_length) { 01049 if (space < (int32_t) socket_ptr->sndq.low_water_mark) { 01050 ret_val = NS_EWOULDBLOCK; 01051 goto fail; 01052 } 01053 if (flags & NS_MSG_LEGACY0) { 01054 // Can't do a partial write, as we can't actually 01055 // indicate that we've done so. For compatibility, 01056 // accept a write of any size if there is some buffer 01057 // space available. This could make us massively go 01058 // over the buffer size limit. 01059 } else { 01060 payload_length = space; 01061 } 01062 } 01063 } 01064 } 01065 #endif // NO_TCP 01066 01067 // Now copy (some of) the data into a buffer 01068 if (!buf) { 01069 buf = buffer_get(payload_length); 01070 if (!buf) { 01071 ret_val = -2; 01072 goto fail; 01073 } 01074 01075 const ns_iovec_t *msg_iov = msg->msg_iov; 01076 uint16_t to_copy = payload_length; 01077 for (uint_fast16_t i = 0; i < msg->msg_iovlen; i++, msg_iov++) { 01078 uint16_t len = msg_iov->iov_len < to_copy ? msg_iov->iov_len : to_copy; 01079 buffer_data_add(buf, msg_iov->iov_base, len); 01080 to_copy -= len; 01081 if (to_copy == 0) { 01082 break; 01083 } 01084 } 01085 } 01086 01087 buf->payload_length = payload_length; 01088 01089 #ifndef NO_TCP 01090 if (socket_ptr->type == SOCKET_TYPE_STREAM) { 01091 tcp_session_t *tcp_info = tcp_info(inet_pcb); 01092 if (!tcp_info) { 01093 tr_warn("No TCP session for cur Socket"); 01094 ret_val = -3; 01095 goto fail; 01096 } 01097 01098 switch (tcp_session_send(tcp_info, buf)) { 01099 case TCP_ERROR_NO_ERROR: 01100 break; 01101 case TCP_ERROR_WRONG_STATE: 01102 default: 01103 ret_val = -3; 01104 goto fail; 01105 } 01106 goto success; 01107 } 01108 // TCP system has taken ownership of buffer, or we've failed 01109 // Everything below this point is non-TCP 01110 #endif //NO_TCP 01111 01112 /** 01113 * Mark Socket id to buffer meta data 01114 */ 01115 buffer_socket_set(buf, socket_ptr); 01116 01117 /** 01118 * Allocate random port if port is not defined. 01119 */ 01120 if (inet_pcb->local_port == 0) { 01121 inet_pcb->local_port = socket_generate_random_port(inet_pcb->protocol ); 01122 if (inet_pcb->local_port == 0) { 01123 ret_val = -2; 01124 goto fail; 01125 } 01126 } 01127 01128 /** 01129 * Set socket configured parameters 01130 */ 01131 buf->options .traffic_class = inet_pcb->tclass; 01132 buf->options .ipv6_use_min_mtu = inet_pcb->use_min_mtu ; 01133 buf->options .ipv6_dontfrag = inet_pcb->dontfrag; 01134 buf->options .multicast_loop = inet_pcb->multicast_loop; 01135 01136 /* Set default remote address from PCB */ 01137 if (inet_pcb->remote_port != 0 && !addr_ipv6_equal(inet_pcb->remote_address , ns_in6addr_any)) { 01138 memcpy(buf->dst_sa .address , inet_pcb->remote_address , 16); 01139 buf->dst_sa .port = inet_pcb->remote_port ; 01140 buf->dst_sa .addr_type = ADDR_IPV6 ; 01141 } else { 01142 buf->dst_sa .addr_type = ADDR_NONE ; 01143 } 01144 01145 /** 01146 * validate Message name and Parse Ancillary Data when Message header is shared. 01147 */ 01148 if (msg) { 01149 /** 01150 * Validate message name (destination) and set address to buffer 01151 */ 01152 if (msg->msg_namelen) { 01153 if (!msg->msg_name || msg->msg_namelen != sizeof(ns_address_t)) { 01154 ret_val = -1; 01155 goto fail; 01156 } 01157 01158 ns_address_t *address = msg->msg_name; 01159 buf->dst_sa .port = address->identifier; 01160 buf->dst_sa .addr_type = ADDR_IPV6 ; 01161 memcpy(buf->dst_sa .address , address->address, 16); 01162 } 01163 01164 ns_cmsghdr_t *cmsg = NS_CMSG_FIRSTHDR(msg); 01165 //Stay at while when full ancillary data is analyzed 01166 while (cmsg) { 01167 if (cmsg->cmsg_level == SOCKET_IPPROTO_IPV6) { 01168 const void *data_ptr = NS_CMSG_DATA(cmsg); 01169 switch (cmsg->cmsg_type) { 01170 case SOCKET_IPV6_PKTINFO: { 01171 if (cmsg->cmsg_len != NS_CMSG_LEN(sizeof(ns_in6_pktinfo_t))) { 01172 ret_val = -1; 01173 goto fail; 01174 } 01175 const ns_in6_pktinfo_t *packetinfo = data_ptr; 01176 memcpy(buf->src_sa .address , packetinfo->ipi6_addr, 16); 01177 buf->src_sa .addr_type = addr_ipv6_equal(packetinfo->ipi6_addr, ns_in6addr_any) ? ADDR_NONE : ADDR_IPV6 ; 01178 /** 01179 * Set interface id when it is configured >0 01180 */ 01181 if (packetinfo->ipi6_ifindex > 0) { 01182 interface_id = packetinfo->ipi6_ifindex; 01183 } 01184 break; 01185 } 01186 01187 case SOCKET_IPV6_HOPLIMIT: 01188 if (cmsg->cmsg_len != NS_CMSG_LEN(sizeof(int16_t))) { 01189 ret_val = -1; 01190 goto fail; 01191 } 01192 msg_hoplimit = data_ptr; 01193 if (*msg_hoplimit < -1 || *msg_hoplimit > 255) { 01194 ret_val = -1; 01195 goto fail; 01196 } 01197 break; 01198 01199 case SOCKET_IPV6_TCLASS: { 01200 if (cmsg->cmsg_len != NS_CMSG_LEN(sizeof(int16_t))) { 01201 ret_val = -1; 01202 goto fail; 01203 } 01204 int16_t tclass = *(const int16_t*)data_ptr; 01205 01206 if (tclass == -1) { 01207 buf->options .traffic_class = SOCKET_IPV6_TCLASS_DEFAULT; 01208 } else if (tclass >= 0 && tclass <= 255) { 01209 buf->options .traffic_class = tclass; 01210 } else { 01211 ret_val = -1; 01212 goto fail; 01213 } 01214 break; 01215 } 01216 #ifndef NO_IPV6_PMTUD 01217 case SOCKET_IPV6_USE_MIN_MTU: { 01218 if (cmsg->cmsg_len != NS_CMSG_LEN(sizeof(int8_t))) { 01219 ret_val = -1; 01220 goto fail; 01221 } 01222 int8_t use_min_mtu = *(const int8_t *) data_ptr; 01223 if (use_min_mtu < -1 || use_min_mtu > 1) { 01224 ret_val = -1; 01225 goto fail; 01226 } 01227 buf->options .ipv6_use_min_mtu = use_min_mtu; 01228 break; 01229 } 01230 #endif 01231 #ifndef NO_IP_FRAGMENT_TX 01232 case SOCKET_IPV6_DONTFRAG: { 01233 if (cmsg->cmsg_len != NS_CMSG_LEN(sizeof(int8_t))) { 01234 ret_val = -1; 01235 goto fail; 01236 } 01237 int8_t dont_frag = *(const int8_t *) data_ptr; 01238 if (dont_frag < 0 || dont_frag > 1) { 01239 ret_val = -1; 01240 goto fail; 01241 } 01242 buf->options .ipv6_dontfrag = dont_frag; 01243 break; 01244 } 01245 #endif 01246 case SOCKET_IPV6_MULTICAST_LOOP: { 01247 if (cmsg->cmsg_len != NS_CMSG_LEN(sizeof(bool))) { 01248 ret_val = -1; 01249 goto fail; 01250 } 01251 buf->options .multicast_loop = *(const bool *) data_ptr; 01252 break; 01253 } 01254 default: 01255 break; 01256 } 01257 } 01258 cmsg = NS_CMSG_NXTHDR(msg, cmsg); 01259 } 01260 } 01261 01262 /* Should have destination address by now */ 01263 if (buf->dst_sa .addr_type == ADDR_NONE ) { 01264 return -5; 01265 } 01266 01267 switch (socket_ptr->type) { 01268 case SOCKET_TYPE_DGRAM: 01269 buf->info = (buffer_info_t)(B_DIR_DOWN + B_FROM_APP + B_TO_UDP); 01270 break; 01271 01272 case SOCKET_TYPE_RAW: 01273 if (inet_pcb->protocol == IPV6_NH_ICMPV6) { 01274 if (buffer_data_length(buf) < 4) { 01275 ret_val = -6; 01276 goto fail; 01277 } 01278 uint8_t *ptr = buffer_data_pointer(buf); 01279 buf->options .type = ptr[0]; 01280 buf->options .code = ptr[1]; 01281 buffer_data_strip_header(buf, 4); 01282 buf->info = (buffer_info_t)(B_DIR_DOWN + B_FROM_APP + B_TO_ICMP); 01283 } else { 01284 buf->options .type = inet_pcb->protocol ; 01285 buf->info = (buffer_info_t)(B_DIR_DOWN + B_FROM_APP + B_TO_IPV6); 01286 } 01287 break; 01288 default: 01289 ret_val = -1; 01290 goto fail; 01291 } 01292 01293 /* If no address in packet info, use bound address, if any. Set before interface selection - 01294 * socket_interface_determine could otherwise auto-select source as a side-effect. */ 01295 if (buf->src_sa .addr_type == ADDR_NONE && !addr_ipv6_equal(inet_pcb->local_address , ns_in6addr_any)) { 01296 memcpy(buf->src_sa .address , inet_pcb->local_address , 16); 01297 buf->src_sa .addr_type = ADDR_IPV6 ; 01298 } 01299 01300 /* If address is specified manually we must validate that the 01301 * address is valid in one of the available interfaces 01302 * */ 01303 if (buf->src_sa .addr_type == ADDR_IPV6 && 01304 protcol_interface_address_compare(NULL, buf->src_sa .address ) != 0) { 01305 tr_warn("Specified source address %s is not valid",trace_ipv6(buf->src_sa .address )); 01306 ret_val = -3; 01307 goto fail; 01308 } 01309 01310 /** 01311 * Select outgoing interface for this message 01312 */ 01313 protocol_interface_info_entry_t *cur_interface; 01314 if (interface_id > 0) { 01315 cur_interface = protocol_stack_interface_info_get_by_id(interface_id); 01316 } else { 01317 cur_interface = socket_interface_determine(socket_ptr, buf); 01318 } 01319 01320 if (!cur_interface) { 01321 tr_warn("sendto:No interface"); 01322 ret_val = -4; 01323 goto fail; 01324 } 01325 01326 buf->interface = cur_interface; 01327 01328 /** 01329 * Link-specific configuration 01330 */ 01331 buf->options .ll_security_bypass_tx = (inet_pcb->link_layer_security == 0); 01332 if (socket_ptr->broadcast_pan > 0) { 01333 buf->link_specific.ieee802_15_4.useDefaultPanId = false; 01334 buf->link_specific.ieee802_15_4.dstPanId = 0xffff; 01335 } 01336 01337 /** 01338 * Set Hop Limit 01339 */ 01340 socket_inet_pcb_set_buffer_hop_limit(inet_pcb, buf, msg_hoplimit); 01341 /** 01342 * Flow label set 01343 */ 01344 buf->options .flow_label = inet_pcb->flow_label; 01345 01346 /** 01347 * Select source address for this message 01348 */ 01349 if (buf->src_sa .addr_type == ADDR_NONE ) { 01350 const uint8_t *ipv6_ptr = addr_select_source(cur_interface, buf->dst_sa .address , inet_pcb->addr_preferences); 01351 if (!ipv6_ptr) { 01352 tr_warn("No address"); 01353 ret_val = -3; 01354 goto fail; 01355 } 01356 01357 memcpy(buf->src_sa .address , ipv6_ptr, 16); 01358 buf->src_sa .addr_type = ADDR_IPV6 ; 01359 } 01360 01361 buf->src_sa .port = inet_pcb->local_port ; 01362 01363 protocol_push(buf); 01364 01365 /* TCP jumps back to here */ 01366 success: 01367 if (flags & NS_MSG_LEGACY0) { 01368 return 0; 01369 } else { 01370 return payload_length; 01371 } 01372 01373 fail: 01374 tr_warn("fail: socket_buffer_sendmsg"); 01375 if (buf) 01376 { 01377 buffer_free(buf); 01378 } 01379 01380 return ret_val; 01381 } 01382 01383 void socket_tx_buffer_event_and_free(buffer_t *buf, uint8_t status) 01384 { 01385 buf = socket_tx_buffer_event(buf, status); 01386 if (buf) { 01387 buffer_free(buf); 01388 } 01389 } 01390 01391 buffer_t *socket_tx_buffer_event(buffer_t *buf, uint8_t status) 01392 { 01393 /* TODO here - if not a locally generated packet, and it's a TX_FAIL 01394 * (when we finally implement it), should probably generate ICMP 01395 * address unreachable. (Kind of needed if address resolution was skipped 01396 * and we mapped straight to MAC address). 01397 */ 01398 01399 /* Suppress events once socket orphaned */ 01400 if (!buf->socket || (buf->socket ->flags & (SOCKET_FLAG_PENDING|SOCKET_FLAG_CLOSED))) { 01401 return buf; 01402 } 01403 01404 protocol_interface_info_entry_t *cur_interface = buf->interface ; 01405 01406 socket_event_push(status, buf->socket , cur_interface ? cur_interface->id : -1, buf->session_ptr, buf->payload_length ); 01407 01408 return buf; 01409 } 01410 01411 static void mc_group_free(inet_pcb_t *inet_pcb, inet_group_t *mc) 01412 { 01413 protocol_interface_info_entry_t *cur_interface = protocol_stack_interface_info_get_by_id(mc->interface_id); 01414 if (cur_interface) { 01415 addr_delete_group(cur_interface, mc->group_addr); 01416 } 01417 01418 ns_list_remove(&inet_pcb->mc_groups, mc); 01419 ns_dyn_mem_free(mc); 01420 } 01421 01422 /* 01423 * validate that socket backlog allows new connection. 01424 * Incoming socket needs to be listening socket. 01425 * 01426 * \return true if incoming connection can proceed 01427 * */ 01428 bool socket_validate_listen_backlog(const socket_t *socket_ptr) 01429 { 01430 if (!(socket_ptr->flags & SOCKET_LISTEN_STATE)) { 01431 return false; 01432 } 01433 01434 return ns_list_count(&socket_ptr->u.live.queue) < socket_ptr->listen_backlog ; 01435 } 01436 01437 inet_pcb_t *socket_inet_pcb_free(inet_pcb_t *inet_pcb) 01438 { 01439 if (inet_pcb) { 01440 ns_list_foreach_safe(inet_group_t, mc, &inet_pcb->mc_groups) { 01441 mc_group_free(inet_pcb, mc); 01442 } 01443 ns_dyn_mem_free(inet_pcb); 01444 } 01445 return NULL; 01446 } 01447 01448 int8_t socket_inet_pcb_join_group(inet_pcb_t *inet_pcb, int8_t interface_id, const uint8_t group[static 16]) 01449 { 01450 ns_list_foreach(inet_group_t, mc, &inet_pcb->mc_groups) { 01451 if ((interface_id == 0 || mc->interface_id == interface_id) && addr_ipv6_equal(mc->group_addr, group)) { 01452 return -3; 01453 } 01454 } 01455 if (interface_id == 0) { 01456 ipv6_route_t *route = ipv6_route_choose_next_hop(group, -1, NULL); 01457 if (!route) { 01458 return -3; 01459 } 01460 interface_id = route->info.interface_id; 01461 } 01462 protocol_interface_info_entry_t *cur_interface = protocol_stack_interface_info_get_by_id(interface_id); 01463 if (!cur_interface) { 01464 return -3; 01465 } 01466 inet_group_t *mc = ns_dyn_mem_alloc(sizeof *mc); 01467 if (!mc) { 01468 return -3; 01469 } 01470 memcpy(mc->group_addr, group, 16); 01471 mc->interface_id = interface_id; 01472 if (!addr_add_group(cur_interface, group)) { 01473 /* This could also happen due to being an implicit group member, eg ff02::1 */ 01474 /* In that case, doesn't seem unreasonable to return the same error as "already a member on this socket" */ 01475 ns_dyn_mem_free(mc); 01476 return -3; 01477 } 01478 01479 ns_list_add_to_end(&inet_pcb->mc_groups, mc); 01480 return 0; 01481 } 01482 01483 int8_t socket_inet_pcb_leave_group(inet_pcb_t *inet_pcb, int8_t interface_id, const uint8_t group[static 16]) 01484 { 01485 inet_group_t *mc = NULL; 01486 ns_list_foreach(inet_group_t, cur, &inet_pcb->mc_groups) { 01487 if ((interface_id == 0 || cur->interface_id == interface_id) && addr_ipv6_equal(cur->group_addr, group)) { 01488 mc = cur; 01489 break; 01490 } 01491 } 01492 if (!mc) { 01493 return -3; 01494 } 01495 01496 mc_group_free(inet_pcb, mc); 01497 01498 return 0; 01499 } 01500 01501 struct protocol_interface_info_entry *socket_interface_determine(const socket_t *socket_ptr, buffer_t *buf) 01502 { 01503 protocol_interface_info_entry_t *cur_interface; 01504 01505 /* Link or realm-local scope uses default interface id if set (as if dest scope id), else multicast if, else choose 6LoWPAN, else IPv6(Ethernet) */ 01506 /* Also for packets addressed to ourself (not needed any more - have loopback routes? */ 01507 if (addr_ipv6_scope(buf->dst_sa .address , NULL) <= IPV6_SCOPE_REALM_LOCAL) { 01508 if (socket_ptr->default_interface_id != -1) { 01509 cur_interface = protocol_stack_interface_info_get_by_id(socket_ptr->default_interface_id); 01510 if (cur_interface) { 01511 return cur_interface; 01512 } 01513 } 01514 } 01515 01516 /* Sockets can specify an interface for multicast packets */ 01517 if (addr_is_ipv6_multicast(buf->dst_sa .address ) && socket_ptr->inet_pcb ->multicast_if > 0) { 01518 cur_interface = protocol_stack_interface_info_get_by_id(socket_ptr->inet_pcb ->multicast_if); 01519 if (cur_interface && ipv6_buffer_route_to(buf, buf->dst_sa .address , cur_interface)) { 01520 return cur_interface; 01521 } else { 01522 return NULL; 01523 } 01524 } 01525 01526 /* Try a routing table entry for greater-than-realm scope */ 01527 if (addr_ipv6_scope(buf->dst_sa .address , NULL) > IPV6_SCOPE_REALM_LOCAL) { 01528 if (ipv6_buffer_route(buf)) { 01529 return buf->interface ; 01530 } 01531 } 01532 01533 /* Realm-local scope or lower now chooses an interface - 6LoWPAN default */ 01534 if (addr_ipv6_scope(buf->dst_sa .address , NULL) <= IPV6_SCOPE_REALM_LOCAL) { 01535 buf->interface = protocol_stack_interface_info_get(IF_6LoWPAN); 01536 if (buf->interface ) { 01537 return buf->interface ; 01538 } 01539 buf->interface = protocol_stack_interface_info_get(IF_IPV6); 01540 if (buf->interface ) { 01541 return buf->interface ; 01542 } 01543 return NULL; 01544 } 01545 01546 return NULL; 01547 }
Generated on Tue Jul 12 2022 12:22:16 by
