Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
udp.c
00001 /* 00002 * Copyright (c) 2013-2017, 2019, 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 #include "nsconfig.h" 00018 #include "ns_types.h" 00019 #include "string.h" 00020 #include "ns_trace.h" 00021 #include "ip_fsc.h" 00022 #include "NWK_INTERFACE/Include/protocol.h" 00023 #include "NWK_INTERFACE/Include/protocol_stats.h" 00024 #include "6LoWPAN/Bootstraps/network_lib.h" // for nwk_udp_rx_security_check 00025 #include "Common_Protocols/ipv6_constants.h" 00026 #include "Common_Protocols/icmpv6.h" 00027 #include "Common_Protocols/udp.h" 00028 #include "Core/include/ns_socket.h" 00029 #include "common_functions.h" 00030 00031 #define TRACE_GROUP "udp" 00032 00033 static buffer_t *udp_checksum_check(buffer_t *buf) 00034 { 00035 uint8_t *ptr = buffer_data_pointer(buf) + 6; 00036 uint16_t check = common_read_16_bit(ptr); 00037 00038 // We refuse checksum field 0000, as per IPv6 (RFC 2460). Would have 00039 // to accept this if handling IPv4. 00040 if (check == 0 || buffer_ipv6_fcf(buf, IPV6_NH_UDP)) { 00041 tr_err("CKSUM ERROR - src=%s", trace_ipv6(buf->src_sa .address )); 00042 protocol_stats_update(STATS_IP_CKSUM_ERROR, 1); 00043 buf = buffer_free(buf); 00044 } 00045 return buf; 00046 } 00047 00048 void udp_checksum_write(buffer_t *buf) 00049 { 00050 uint8_t *ptr = buffer_data_pointer(buf) + 6; 00051 uint16_t check; 00052 00053 common_write_16_bit(0, ptr); 00054 check = buffer_ipv6_fcf(buf, IPV6_NH_UDP); 00055 if (check == 0) { 00056 check = 0xffff; 00057 } 00058 common_write_16_bit(check, ptr); 00059 } 00060 00061 00062 buffer_t *udp_down(buffer_t *buf) 00063 { 00064 if (buf->src_sa .addr_type != ADDR_IPV6 ) { 00065 //tr_debug("Create Address"); 00066 // if(protocol_stack_interface_get_address_by_prefix(buf->if_index, buf->src_sa.address,buf->dst_sa.address, 0) != 0) 00067 // { 00068 tr_debug("InterFace Address Get Fail--> free Buffer"); 00069 return buffer_free(buf); 00070 // } 00071 // else 00072 // { 00073 // buf->src_sa.addr_type = ADDR_IPV6; 00074 // } 00075 } 00076 00077 buf = buffer_headroom(buf, 8); 00078 if (buf) { 00079 uint8_t *ptr; 00080 buf->buf_ptr -= 8; 00081 00082 ptr = buffer_data_pointer(buf); 00083 ptr = common_write_16_bit(buf->src_sa .port , ptr); 00084 ptr = common_write_16_bit(buf->dst_sa .port , ptr); 00085 ptr = common_write_16_bit(buffer_data_length(buf), ptr); 00086 udp_checksum_write(buf); 00087 buf->IPHC_NH = 0; 00088 buf->info = (buffer_info_t)(B_FROM_UDP | B_TO_IPV6 | B_DIR_DOWN); 00089 buf->options .type = IPV6_NH_UDP; 00090 buf->options .code = 0; 00091 } 00092 return (buf); 00093 } 00094 00095 buffer_t *udp_up(buffer_t *buf) 00096 { 00097 //tr_debug("UDP UP"); 00098 const uint8_t *ip_hdr; 00099 if ((buf->info & B_FROM_MASK) == B_FROM_IPV6_FWD) { 00100 // New paths leave IP header on for us to permit ICMP response; 00101 // note the pointer and strip now. 00102 ip_hdr = buffer_data_pointer(buf); 00103 buffer_data_strip_header(buf, buf->offset ); 00104 buf->offset = 0; 00105 } else { 00106 // We came from cipv6_up (or...?) - we have no real IP headers 00107 ip_hdr = NULL; 00108 } 00109 00110 uint16_t ip_len = buffer_data_length(buf); 00111 if (ip_len < 8) { 00112 return buffer_free(buf); 00113 } 00114 00115 const uint8_t *udp_hdr = buffer_data_pointer(buf); 00116 00117 buf->src_sa .port = common_read_16_bit(udp_hdr + 0); 00118 buf->dst_sa .port = common_read_16_bit(udp_hdr + 2); 00119 uint16_t udp_len = common_read_16_bit(udp_hdr + 4); 00120 00121 buf = nwk_udp_rx_security_check(buf); 00122 if (!buf) { 00123 return NULL; 00124 } 00125 00126 if (udp_len < 8 || udp_len > ip_len) { 00127 return buffer_free(buf); 00128 } 00129 00130 // Set UDP length - may trim the buffer 00131 buffer_data_length_set(buf, udp_len); 00132 00133 buf = udp_checksum_check(buf); 00134 if (!buf) { 00135 return buf; 00136 } 00137 00138 // Remove UDP header 00139 buffer_data_pointer_set(buf, udp_hdr + 8); 00140 00141 if (buf->dst_sa .port == 0) { 00142 tr_err("UDP port 0"); 00143 protocol_stats_update(STATS_IP_RX_DROP, 1); 00144 return buffer_free(buf); 00145 } 00146 00147 if (buf->dst_sa .port == UDP_PORT_ECHO && buf->src_sa .port != UDP_PORT_ECHO) { 00148 protocol_interface_info_entry_t *cur; 00149 tr_debug("UDP echo msg from %s", trace_ipv6(buf->src_sa .address )); 00150 00151 cur = buf->interface ; 00152 00153 if (addr_is_ipv6_multicast(buf->dst_sa .address )) { 00154 const uint8_t *ipv6_ptr; 00155 ipv6_ptr = addr_select_source(cur, buf->dst_sa .address , 0); 00156 if (!ipv6_ptr) { 00157 tr_debug("UDP Echo:No address"); 00158 return buffer_free(buf); 00159 } 00160 memcpy(buf->dst_sa .address , buf->src_sa .address , 16); 00161 memcpy(buf->src_sa .address , ipv6_ptr, 16); 00162 } else { 00163 memswap(buf->dst_sa .address , buf->src_sa .address , 16); 00164 } 00165 buf->dst_sa .port = buf->src_sa .port ; 00166 buf->src_sa .port = UDP_PORT_ECHO; 00167 00168 buf->info = (buffer_info_t)(B_FROM_UDP | B_TO_UDP | B_DIR_DOWN); 00169 buf->options .hop_limit = UNICAST_HOP_LIMIT_DEFAULT; 00170 buf->options .traffic_class = 0; 00171 buf->IPHC_NH = 0; 00172 return buffer_turnaround(buf); 00173 } 00174 00175 if (ip_hdr) { 00176 /* New path generates port unreachable here, using the real IP headers 00177 * that we know the position of thanks to buf->offset. 00178 * 00179 * Old path has socket_up make port unreachable itself, creating a 00180 * fake IP header. 00181 */ 00182 if (!buf->socket ) { 00183 buffer_socket_set(buf, socket_lookup_ipv6(IPV6_NH_UDP, &buf->dst_sa , &buf->src_sa , true)); 00184 } 00185 if (!buf->socket ) { 00186 // Reconstruct original IP packet 00187 buffer_data_pointer_set(buf, udp_hdr); 00188 buffer_data_length_set(buf, ip_len); 00189 buffer_data_pointer_set(buf, ip_hdr); 00190 return icmpv6_error(buf, NULL, ICMPV6_TYPE_ERROR_DESTINATION_UNREACH, ICMPV6_CODE_DST_UNREACH_PORT_UNREACH, 0); 00191 } 00192 } 00193 00194 buf->options .type = (uint8_t) SOCKET_FAMILY_IPV6; 00195 buf->options .code = IPV6_NH_UDP; 00196 buf->info = (buffer_info_t)(B_FROM_UDP | B_TO_APP | B_DIR_UP); 00197 return buf; 00198 }
Generated on Tue Jul 12 2022 13:55:01 by
