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.
udp.c
00001 /* 00002 * Copyright (c) 2013-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 #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/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 [%"PRIi16"]: %s%s", 00150 buffer_data_length(buf), 00151 trace_array( 00152 buffer_data_pointer(buf), 00153 (buffer_data_length(buf) > 64 ? 64 : buffer_data_length(buf))), 00154 (buffer_data_length(buf) > 64 ? "..." : "")); 00155 00156 cur = buf->interface ; 00157 00158 if (addr_is_ipv6_multicast(buf->dst_sa .address )) { 00159 const uint8_t *ipv6_ptr; 00160 ipv6_ptr = addr_select_source(cur, buf->dst_sa .address , 0); 00161 if (!ipv6_ptr) { 00162 tr_debug("UDP Echo:No address"); 00163 return buffer_free(buf); 00164 } 00165 memcpy(buf->dst_sa .address , buf->src_sa .address , 16); 00166 memcpy(buf->src_sa .address , ipv6_ptr, 16); 00167 } else { 00168 memswap(buf->dst_sa .address , buf->src_sa .address , 16); 00169 } 00170 buf->dst_sa .port = buf->src_sa .port ; 00171 buf->src_sa .port = UDP_PORT_ECHO; 00172 00173 buf->info = (buffer_info_t)(B_FROM_UDP | B_TO_UDP | B_DIR_DOWN); 00174 buf->options .hop_limit = UNICAST_HOP_LIMIT_DEFAULT; 00175 buf->options .traffic_class = 0; 00176 buf->IPHC_NH = 0; 00177 return buffer_turnaround(buf); 00178 } 00179 00180 if (ip_hdr) { 00181 /* New path generates port unreachable here, using the real IP headers 00182 * that we know the position of thanks to buf->offset. 00183 * 00184 * Old path has socket_up make port unreachable itself, creating a 00185 * fake IP header. 00186 */ 00187 if (!buf->socket ) { 00188 buffer_socket_set(buf, socket_lookup_ipv6(IPV6_NH_UDP, &buf->dst_sa , &buf->src_sa , true)); 00189 } 00190 if (!buf->socket ) { 00191 // Reconstruct original IP packet 00192 buffer_data_pointer_set(buf, udp_hdr); 00193 buffer_data_length_set(buf, ip_len); 00194 buffer_data_pointer_set(buf, ip_hdr); 00195 return icmpv6_error(buf, NULL, ICMPV6_TYPE_ERROR_DESTINATION_UNREACH, ICMPV6_CODE_DST_UNREACH_PORT_UNREACH, 0); 00196 } 00197 } 00198 00199 buf->options .type = (uint8_t) SOCKET_FAMILY_IPV6; 00200 buf->options .code = IPV6_NH_UDP; 00201 buf->info = (buffer_info_t)(B_FROM_UDP | B_TO_APP | B_DIR_UP); 00202 return buf; 00203 }
Generated on Tue Jul 12 2022 14:25:06 by
