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.
lwip_udp.c
00001 /** 00002 * @file 00003 * User Datagram Protocol module\n 00004 * See also @ref udp_raw 00005 */ 00006 00007 /* 00008 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 00009 * All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without modification, 00012 * are permitted provided that the following conditions are met: 00013 * 00014 * 1. Redistributions of source code must retain the above copyright notice, 00015 * this list of conditions and the following disclaimer. 00016 * 2. Redistributions in binary form must reproduce the above copyright notice, 00017 * this list of conditions and the following disclaimer in the documentation 00018 * and/or other materials provided with the distribution. 00019 * 3. The name of the author may not be used to endorse or promote products 00020 * derived from this software without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00023 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00024 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00025 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00026 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00027 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00028 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00029 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00030 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00031 * OF SUCH DAMAGE. 00032 * 00033 * This file is part of the lwIP TCP/IP stack. 00034 * 00035 * Author: Adam Dunkels <adam@sics.se> 00036 * 00037 */ 00038 00039 /** 00040 * @defgroup udp_raw UDP 00041 * @ingroup raw_api 00042 * User Datagram Protocol module\n 00043 * @see @ref raw_api and @ref netconn 00044 */ 00045 00046 /* udp.c 00047 * 00048 * The code for the User Datagram Protocol UDP & UDPLite (RFC 3828). 00049 * 00050 */ 00051 00052 /* @todo Check the use of '(struct udp_pcb).chksum_len_rx'! 00053 */ 00054 00055 #include "lwip/opt.h" 00056 00057 #if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ 00058 00059 #include "lwip/udp.h" 00060 #include "lwip/def.h" 00061 #include "lwip/memp.h" 00062 #include "lwip/inet_chksum.h" 00063 #include "lwip/ip_addr.h" 00064 #include "lwip/ip6.h" 00065 #include "lwip/ip6_addr.h" 00066 #include "lwip/inet_chksum.h" 00067 #include "lwip/netif.h" 00068 #include "lwip/icmp.h" 00069 #include "lwip/icmp6.h" 00070 #include "lwip/stats.h" 00071 #include "lwip/snmp.h" 00072 #include "lwip/dhcp.h" 00073 00074 #include <string.h> 00075 00076 #ifndef UDP_LOCAL_PORT_RANGE_START 00077 /* From http://www.iana.org/assignments/port-numbers: 00078 "The Dynamic and/or Private Ports are those from 49152 through 65535" */ 00079 #define UDP_LOCAL_PORT_RANGE_START 0xc000 00080 #define UDP_LOCAL_PORT_RANGE_END 0xffff 00081 #define UDP_ENSURE_LOCAL_PORT_RANGE(port) ((u16_t)(((port) & ~UDP_LOCAL_PORT_RANGE_START) + UDP_LOCAL_PORT_RANGE_START)) 00082 #endif 00083 00084 /* last local UDP port */ 00085 static u16_t udp_port = UDP_LOCAL_PORT_RANGE_START; 00086 00087 /* The list of UDP PCBs */ 00088 /* exported in udp.h (was static) */ 00089 struct udp_pcb *udp_pcbs; 00090 00091 /** 00092 * Initialize this module. 00093 */ 00094 void 00095 udp_init(void) 00096 { 00097 #if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) 00098 udp_port = UDP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); 00099 #endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ 00100 } 00101 00102 /** 00103 * Allocate a new local UDP port. 00104 * 00105 * @return a new (free) local UDP port number 00106 */ 00107 static u16_t 00108 udp_new_port(void) 00109 { 00110 u16_t n = 0; 00111 struct udp_pcb *pcb; 00112 00113 again: 00114 if (udp_port++ == UDP_LOCAL_PORT_RANGE_END) { 00115 udp_port = UDP_LOCAL_PORT_RANGE_START; 00116 } 00117 /* Check all PCBs. */ 00118 for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { 00119 if (pcb->local_port == udp_port) { 00120 if (++n > (UDP_LOCAL_PORT_RANGE_END - UDP_LOCAL_PORT_RANGE_START)) { 00121 return 0; 00122 } 00123 goto again; 00124 } 00125 } 00126 return udp_port; 00127 #if 0 00128 struct udp_pcb *ipcb = udp_pcbs; 00129 while ((ipcb != NULL) && (udp_port != UDP_LOCAL_PORT_RANGE_END)) { 00130 if (ipcb->local_port == udp_port) { 00131 /* port is already used by another udp_pcb */ 00132 udp_port++; 00133 /* restart scanning all udp pcbs */ 00134 ipcb = udp_pcbs; 00135 } else { 00136 /* go on with next udp pcb */ 00137 ipcb = ipcb->next; 00138 } 00139 } 00140 if (ipcb != NULL) { 00141 return 0; 00142 } 00143 return udp_port; 00144 #endif 00145 } 00146 00147 /** Common code to see if the current input packet matches the pcb 00148 * (current input packet is accessed via ip(4/6)_current_* macros) 00149 * 00150 * @param pcb pcb to check 00151 * @param inp network interface on which the datagram was received (only used for IPv4) 00152 * @param broadcast 1 if his is an IPv4 broadcast (global or subnet-only), 0 otherwise (only used for IPv4) 00153 * @return 1 on match, 0 otherwise 00154 */ 00155 static u8_t 00156 udp_input_local_match(struct udp_pcb *pcb, struct netif *inp, u8_t broadcast) 00157 { 00158 LWIP_UNUSED_ARG(inp); /* in IPv6 only case */ 00159 LWIP_UNUSED_ARG(broadcast); /* in IPv6 only case */ 00160 00161 /* Dual-stack: PCBs listening to any IP type also listen to any IP address */ 00162 if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { 00163 #if LWIP_IPV4 && IP_SOF_BROADCAST_RECV 00164 if ((broadcast != 0) && !ip_get_option(pcb, SOF_BROADCAST)) { 00165 return 0; 00166 } 00167 #endif /* LWIP_IPV4 && IP_SOF_BROADCAST_RECV */ 00168 return 1; 00169 } 00170 00171 /* Only need to check PCB if incoming IP version matches PCB IP version */ 00172 if (IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ip_current_dest_addr())) { 00173 #if LWIP_IPV4 00174 /* Special case: IPv4 broadcast: all or broadcasts in my subnet 00175 * Note: broadcast variable can only be 1 if it is an IPv4 broadcast */ 00176 if (broadcast != 0) { 00177 #if IP_SOF_BROADCAST_RECV 00178 if (ip_get_option(pcb, SOF_BROADCAST)) 00179 #endif /* IP_SOF_BROADCAST_RECV */ 00180 { 00181 if (ip4_addr_isany(ip_2_ip4(&pcb->local_ip)) || 00182 ((ip4_current_dest_addr()->addr == IPADDR_BROADCAST)) || 00183 ip4_addr_netcmp(ip_2_ip4(&pcb->local_ip), ip4_current_dest_addr(), netif_ip4_netmask(inp))) { 00184 return 1; 00185 } 00186 } 00187 } else 00188 #endif /* LWIP_IPV4 */ 00189 /* Handle IPv4 and IPv6: all, multicast or exact match */ 00190 if (ip_addr_isany(&pcb->local_ip) || 00191 #if LWIP_IPV6_MLD 00192 (ip_current_is_v6() && ip6_addr_ismulticast(ip6_current_dest_addr())) || 00193 #endif /* LWIP_IPV6_MLD */ 00194 #if LWIP_IGMP 00195 (!ip_current_is_v6() && ip4_addr_ismulticast(ip4_current_dest_addr())) || 00196 #endif /* LWIP_IGMP */ 00197 ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { 00198 return 1; 00199 } 00200 } 00201 00202 return 0; 00203 } 00204 00205 /** 00206 * Process an incoming UDP datagram. 00207 * 00208 * Given an incoming UDP datagram (as a chain of pbufs) this function 00209 * finds a corresponding UDP PCB and hands over the pbuf to the pcbs 00210 * recv function. If no pcb is found or the datagram is incorrect, the 00211 * pbuf is freed. 00212 * 00213 * @param p pbuf to be demultiplexed to a UDP PCB (p->payload pointing to the UDP header) 00214 * @param inp network interface on which the datagram was received. 00215 * 00216 */ 00217 void 00218 udp_input(struct pbuf *p, struct netif *inp) 00219 { 00220 struct udp_hdr *udphdr; 00221 struct udp_pcb *pcb, *prev; 00222 struct udp_pcb *uncon_pcb; 00223 u16_t src, dest; 00224 u8_t broadcast; 00225 u8_t for_us = 0; 00226 00227 LWIP_UNUSED_ARG(inp); 00228 00229 PERF_START; 00230 00231 UDP_STATS_INC(udp.recv); 00232 00233 /* Check minimum length (UDP header) */ 00234 if (p->len < UDP_HLEN) { 00235 /* drop short packets */ 00236 LWIP_DEBUGF(UDP_DEBUG, 00237 ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len)); 00238 UDP_STATS_INC(udp.lenerr); 00239 UDP_STATS_INC(udp.drop); 00240 MIB2_STATS_INC(mib2.udpinerrors); 00241 pbuf_free(p); 00242 goto end; 00243 } 00244 00245 udphdr = (struct udp_hdr *)p->payload; 00246 00247 /* is broadcast packet ? */ 00248 broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()); 00249 00250 LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len)); 00251 00252 /* convert src and dest ports to host byte order */ 00253 src = ntohs(udphdr->src); 00254 dest = ntohs(udphdr->dest); 00255 00256 udp_debug_print(udphdr); 00257 00258 /* print the UDP source and destination */ 00259 LWIP_DEBUGF(UDP_DEBUG, ("udp (")); 00260 ip_addr_debug_print(UDP_DEBUG, ip_current_dest_addr()); 00261 LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", ntohs(udphdr->dest))); 00262 ip_addr_debug_print(UDP_DEBUG, ip_current_src_addr()); 00263 LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", ntohs(udphdr->src))); 00264 00265 pcb = NULL; 00266 prev = NULL; 00267 uncon_pcb = NULL; 00268 /* Iterate through the UDP pcb list for a matching pcb. 00269 * 'Perfect match' pcbs (connected to the remote port & ip address) are 00270 * preferred. If no perfect match is found, the first unconnected pcb that 00271 * matches the local port and ip address gets the datagram. */ 00272 for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { 00273 /* print the PCB local and remote address */ 00274 LWIP_DEBUGF(UDP_DEBUG, ("pcb (")); 00275 ip_addr_debug_print(UDP_DEBUG, &pcb->local_ip); 00276 LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", pcb->local_port)); 00277 ip_addr_debug_print(UDP_DEBUG, &pcb->remote_ip); 00278 LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", pcb->remote_port)); 00279 00280 /* compare PCB local addr+port to UDP destination addr+port */ 00281 if ((pcb->local_port == dest) && 00282 (udp_input_local_match(pcb, inp, broadcast) != 0)) { 00283 if (((pcb->flags & UDP_FLAGS_CONNECTED) == 0) && 00284 ((uncon_pcb == NULL) 00285 #if SO_REUSE 00286 /* prefer specific IPs over cath-all */ 00287 || !ip_addr_isany(&pcb->local_ip) 00288 #endif /* SO_REUSE */ 00289 )) { 00290 /* the first unconnected matching PCB */ 00291 uncon_pcb = pcb; 00292 } 00293 00294 /* compare PCB remote addr+port to UDP source addr+port */ 00295 if ((pcb->remote_port == src) && 00296 (ip_addr_isany_val(pcb->remote_ip) || 00297 ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()))) { 00298 /* the first fully matching PCB */ 00299 if (prev != NULL) { 00300 /* move the pcb to the front of udp_pcbs so that is 00301 found faster next time */ 00302 prev->next = pcb->next; 00303 pcb->next = udp_pcbs; 00304 udp_pcbs = pcb; 00305 } else { 00306 UDP_STATS_INC(udp.cachehit); 00307 } 00308 break; 00309 } 00310 } 00311 00312 prev = pcb; 00313 } 00314 /* no fully matching pcb found? then look for an unconnected pcb */ 00315 if (pcb == NULL) { 00316 pcb = uncon_pcb; 00317 } 00318 00319 /* Check checksum if this is a match or if it was directed at us. */ 00320 if (pcb != NULL) { 00321 for_us = 1; 00322 } else { 00323 #if LWIP_IPV6 00324 if (ip_current_is_v6()) { 00325 for_us = netif_get_ip6_addr_match(inp, ip6_current_dest_addr()) >= 0; 00326 } 00327 #endif /* LWIP_IPV6 */ 00328 #if LWIP_IPV4 00329 if (!ip_current_is_v6()) { 00330 for_us = ip4_addr_cmp(netif_ip4_addr(inp), ip4_current_dest_addr()); 00331 } 00332 #endif /* LWIP_IPV4 */ 00333 } 00334 00335 if (for_us) { 00336 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n")); 00337 #if CHECKSUM_CHECK_UDP 00338 IF__NETIF_CHECKSUM_ENABLED(inp, CHECKSUM_CHECK_UDP) { 00339 #if LWIP_UDPLITE 00340 if (ip_current_header_proto() == IP_PROTO_UDPLITE) { 00341 /* Do the UDP Lite checksum */ 00342 u16_t chklen = ntohs(udphdr->len); 00343 if (chklen < sizeof(struct udp_hdr)) { 00344 if (chklen == 0) { 00345 /* For UDP-Lite, checksum length of 0 means checksum 00346 over the complete packet (See RFC 3828 chap. 3.1) */ 00347 chklen = p->tot_len; 00348 } else { 00349 /* At least the UDP-Lite header must be covered by the 00350 checksum! (Again, see RFC 3828 chap. 3.1) */ 00351 goto chkerr; 00352 } 00353 } 00354 if (ip_chksum_pseudo_partial(p, IP_PROTO_UDPLITE, 00355 p->tot_len, chklen, 00356 ip_current_src_addr(), ip_current_dest_addr()) != 0) { 00357 goto chkerr; 00358 } 00359 } else 00360 #endif /* LWIP_UDPLITE */ 00361 { 00362 if (udphdr->chksum != 0) { 00363 if (ip_chksum_pseudo(p, IP_PROTO_UDP, p->tot_len, 00364 ip_current_src_addr(), 00365 ip_current_dest_addr()) != 0) { 00366 goto chkerr; 00367 } 00368 } 00369 } 00370 } 00371 #endif /* CHECKSUM_CHECK_UDP */ 00372 if (pbuf_header(p, -UDP_HLEN)) { 00373 /* Can we cope with this failing? Just assert for now */ 00374 LWIP_ASSERT("pbuf_header failed\n", 0); 00375 UDP_STATS_INC(udp.drop); 00376 MIB2_STATS_INC(mib2.udpinerrors); 00377 pbuf_free(p); 00378 goto end; 00379 } 00380 00381 if (pcb != NULL) { 00382 MIB2_STATS_INC(mib2.udpindatagrams); 00383 #if SO_REUSE && SO_REUSE_RXTOALL 00384 if (ip_get_option(pcb, SOF_REUSEADDR) && 00385 (broadcast || ip_addr_ismulticast(ip_current_dest_addr()))) { 00386 /* pass broadcast- or multicast packets to all multicast pcbs 00387 if SOF_REUSEADDR is set on the first match */ 00388 struct udp_pcb *mpcb; 00389 u8_t p_header_changed = 0; 00390 s16_t hdrs_len = (s16_t)(ip_current_header_tot_len() + UDP_HLEN); 00391 for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) { 00392 if (mpcb != pcb) { 00393 /* compare PCB local addr+port to UDP destination addr+port */ 00394 if ((mpcb->local_port == dest) && 00395 (udp_input_local_match(mpcb, inp, broadcast) != 0)) { 00396 /* pass a copy of the packet to all local matches */ 00397 if (mpcb->recv != NULL) { 00398 struct pbuf *q; 00399 /* for that, move payload to IP header again */ 00400 if (p_header_changed == 0) { 00401 pbuf_header_force(p, hdrs_len); 00402 p_header_changed = 1; 00403 } 00404 q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); 00405 if (q != NULL) { 00406 err_t err = pbuf_copy(q, p); 00407 if (err == ERR_OK) { 00408 /* move payload to UDP data */ 00409 pbuf_header(q, -hdrs_len); 00410 mpcb->recv(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src); 00411 } 00412 } 00413 } 00414 } 00415 } 00416 } 00417 if (p_header_changed) { 00418 /* and move payload to UDP data again */ 00419 pbuf_header(p, -hdrs_len); 00420 } 00421 } 00422 #endif /* SO_REUSE && SO_REUSE_RXTOALL */ 00423 /* callback */ 00424 if (pcb->recv != NULL) { 00425 /* now the recv function is responsible for freeing p */ 00426 pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr(), src); 00427 } else { 00428 /* no recv function registered? then we have to free the pbuf! */ 00429 pbuf_free(p); 00430 goto end; 00431 } 00432 } else { 00433 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: not for us.\n")); 00434 00435 #if LWIP_ICMP || LWIP_ICMP6 00436 /* No match was found, send ICMP destination port unreachable unless 00437 destination address was broadcast/multicast. */ 00438 if (!broadcast && !ip_addr_ismulticast(ip_current_dest_addr())) { 00439 /* move payload pointer back to ip header */ 00440 pbuf_header_force(p, ip_current_header_tot_len() + UDP_HLEN); 00441 icmp_port_unreach(ip_current_is_v6(), p); 00442 } 00443 #endif /* LWIP_ICMP || LWIP_ICMP6 */ 00444 UDP_STATS_INC(udp.proterr); 00445 UDP_STATS_INC(udp.drop); 00446 MIB2_STATS_INC(mib2.udpnoports); 00447 pbuf_free(p); 00448 } 00449 } else { 00450 pbuf_free(p); 00451 } 00452 end: 00453 PERF_STOP("udp_input"); 00454 return; 00455 #if CHECKSUM_CHECK_UDP 00456 chkerr: 00457 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 00458 ("udp_input: UDP (or UDP Lite) datagram discarded due to failing checksum\n")); 00459 UDP_STATS_INC(udp.chkerr); 00460 UDP_STATS_INC(udp.drop); 00461 MIB2_STATS_INC(mib2.udpinerrors); 00462 pbuf_free(p); 00463 PERF_STOP("udp_input"); 00464 #endif /* CHECKSUM_CHECK_UDP */ 00465 } 00466 00467 /** 00468 * @ingroup udp_raw 00469 * Send data using UDP. 00470 * 00471 * @param pcb UDP PCB used to send the data. 00472 * @param p chain of pbuf's to be sent. 00473 * 00474 * The datagram will be sent to the current remote_ip & remote_port 00475 * stored in pcb. If the pcb is not bound to a port, it will 00476 * automatically be bound to a random port. 00477 * 00478 * @return lwIP error code. 00479 * - ERR_OK. Successful. No error occurred. 00480 * - ERR_MEM. Out of memory. 00481 * - ERR_RTE. Could not find route to destination address. 00482 * - ERR_VAL. No PCB or PCB is dual-stack 00483 * - More errors could be returned by lower protocol layers. 00484 * 00485 * @see udp_disconnect() udp_sendto() 00486 */ 00487 err_t 00488 udp_send(struct udp_pcb *pcb, struct pbuf *p) 00489 { 00490 if ((pcb == NULL) || IP_IS_ANY_TYPE_VAL(pcb->remote_ip)) { 00491 return ERR_VAL; 00492 } 00493 00494 /* send to the packet using remote ip and port stored in the pcb */ 00495 return udp_sendto(pcb, p, &pcb->remote_ip, pcb->remote_port); 00496 } 00497 00498 #if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP 00499 /** @ingroup udp_raw 00500 * Same as udp_send() but with checksum 00501 */ 00502 err_t 00503 udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, 00504 u8_t have_chksum, u16_t chksum) 00505 { 00506 if ((pcb == NULL) || IP_IS_ANY_TYPE_VAL(pcb->remote_ip)) { 00507 return ERR_VAL; 00508 } 00509 00510 /* send to the packet using remote ip and port stored in the pcb */ 00511 return udp_sendto_chksum(pcb, p, &pcb->remote_ip, pcb->remote_port, 00512 have_chksum, chksum); 00513 } 00514 #endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ 00515 00516 /** 00517 * @ingroup udp_raw 00518 * Send data to a specified address using UDP. 00519 * 00520 * @param pcb UDP PCB used to send the data. 00521 * @param p chain of pbuf's to be sent. 00522 * @param dst_ip Destination IP address. 00523 * @param dst_port Destination UDP port. 00524 * 00525 * dst_ip & dst_port are expected to be in the same byte order as in the pcb. 00526 * 00527 * If the PCB already has a remote address association, it will 00528 * be restored after the data is sent. 00529 * 00530 * @return lwIP error code (@see udp_send for possible error codes) 00531 * 00532 * @see udp_disconnect() udp_send() 00533 */ 00534 err_t 00535 udp_sendto(struct udp_pcb *pcb, struct pbuf *p, 00536 const ip_addr_t *dst_ip, u16_t dst_port) 00537 { 00538 #if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP 00539 return udp_sendto_chksum(pcb, p, dst_ip, dst_port, 0, 0); 00540 } 00541 00542 /** @ingroup udp_raw 00543 * Same as udp_sendto(), but with checksum */ 00544 err_t 00545 udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, 00546 u16_t dst_port, u8_t have_chksum, u16_t chksum) 00547 { 00548 #endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ 00549 struct netif *netif; 00550 const ip_addr_t *dst_ip_route = dst_ip; 00551 00552 if ((pcb == NULL) || (dst_ip == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) { 00553 return ERR_VAL; 00554 } 00555 00556 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n")); 00557 00558 #if LWIP_IPV6 || (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) 00559 if (ip_addr_ismulticast(dst_ip_route)) { 00560 #if LWIP_IPV6 00561 if (IP_IS_V6(dst_ip)) { 00562 /* For multicast, find a netif based on source address. */ 00563 dst_ip_route = &pcb->local_ip; 00564 } else 00565 #endif /* LWIP_IPV6 */ 00566 { 00567 #if LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS 00568 /* IPv4 does not use source-based routing by default, so we use an 00569 administratively selected interface for multicast by default. 00570 However, this can be overridden by setting an interface address 00571 in pcb->multicast_ip that is used for routing. */ 00572 if (!ip_addr_isany_val(pcb->multicast_ip) && 00573 !ip4_addr_cmp(ip_2_ip4(&pcb->multicast_ip), IP4_ADDR_BROADCAST)) { 00574 dst_ip_route = &pcb->multicast_ip; 00575 } 00576 #endif /* LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS */ 00577 } 00578 } 00579 #endif /* LWIP_IPV6 || (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) */ 00580 00581 /* find the outgoing network interface for this packet */ 00582 netif = ip_route(&pcb->local_ip, dst_ip_route); 00583 00584 /* no outgoing network interface could be found? */ 00585 if (netif == NULL) { 00586 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to ")); 00587 ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, dst_ip); 00588 LWIP_DEBUGF(UDP_DEBUG, ("\n")); 00589 UDP_STATS_INC(udp.rterr); 00590 return ERR_RTE; 00591 } 00592 #if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP 00593 return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum); 00594 #else /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ 00595 return udp_sendto_if(pcb, p, dst_ip, dst_port, netif); 00596 #endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ 00597 } 00598 00599 /** 00600 * @ingroup udp_raw 00601 * Send data to a specified address using UDP. 00602 * The netif used for sending can be specified. 00603 * 00604 * This function exists mainly for DHCP, to be able to send UDP packets 00605 * on a netif that is still down. 00606 * 00607 * @param pcb UDP PCB used to send the data. 00608 * @param p chain of pbuf's to be sent. 00609 * @param dst_ip Destination IP address. 00610 * @param dst_port Destination UDP port. 00611 * @param netif the netif used for sending. 00612 * 00613 * dst_ip & dst_port are expected to be in the same byte order as in the pcb. 00614 * 00615 * @return lwIP error code (@see udp_send for possible error codes) 00616 * 00617 * @see udp_disconnect() udp_send() 00618 */ 00619 err_t 00620 udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p, 00621 const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif) 00622 { 00623 #if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP 00624 return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0); 00625 } 00626 00627 /** Same as udp_sendto_if(), but with checksum */ 00628 err_t 00629 udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, 00630 u16_t dst_port, struct netif *netif, u8_t have_chksum, 00631 u16_t chksum) 00632 { 00633 #endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ 00634 const ip_addr_t *src_ip; 00635 00636 if ((pcb == NULL) || (dst_ip == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) { 00637 return ERR_VAL; 00638 } 00639 00640 /* PCB local address is IP_ANY_ADDR? */ 00641 #if LWIP_IPV6 00642 if (IP_IS_V6(dst_ip)) { 00643 if (ip6_addr_isany(ip_2_ip6(&pcb->local_ip))) { 00644 src_ip = ip6_select_source_address(netif, ip_2_ip6(dst_ip)); 00645 if (src_ip == NULL) { 00646 /* No suitable source address was found. */ 00647 return ERR_RTE; 00648 } 00649 } else { 00650 /* use UDP PCB local IPv6 address as source address, if still valid. */ 00651 if (netif_get_ip6_addr_match(netif, ip_2_ip6(&pcb->local_ip)) < 0) { 00652 /* Address isn't valid anymore. */ 00653 return ERR_RTE; 00654 } 00655 src_ip = &pcb->local_ip; 00656 } 00657 } 00658 #endif /* LWIP_IPV6 */ 00659 #if LWIP_IPV4 && LWIP_IPV6 00660 else 00661 #endif /* LWIP_IPV4 && LWIP_IPV6 */ 00662 #if LWIP_IPV4 00663 if (ip4_addr_isany(ip_2_ip4(&pcb->local_ip)) || 00664 ip4_addr_ismulticast(ip_2_ip4(&pcb->local_ip))) { 00665 /* if the local_ip is any or multicast 00666 * use the outgoing network interface IP address as source address */ 00667 src_ip = netif_ip_addr4(netif); 00668 } else { 00669 /* check if UDP PCB local IP address is correct 00670 * this could be an old address if netif->ip_addr has changed */ 00671 if (!ip4_addr_cmp(ip_2_ip4(&(pcb->local_ip)), netif_ip4_addr(netif))) { 00672 /* local_ip doesn't match, drop the packet */ 00673 return ERR_VAL; 00674 } 00675 /* use UDP PCB local IP address as source address */ 00676 src_ip = &pcb->local_ip; 00677 } 00678 #endif /* LWIP_IPV4 */ 00679 #if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP 00680 return udp_sendto_if_src_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum, src_ip); 00681 #else /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ 00682 return udp_sendto_if_src(pcb, p, dst_ip, dst_port, netif, src_ip); 00683 #endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ 00684 } 00685 00686 /** @ingroup udp_raw 00687 * Same as @ref udp_sendto_if, but with source address */ 00688 err_t 00689 udp_sendto_if_src(struct udp_pcb *pcb, struct pbuf *p, 00690 const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif, const ip_addr_t *src_ip) 00691 { 00692 #if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP 00693 return udp_sendto_if_src_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0, src_ip); 00694 } 00695 00696 /** Same as udp_sendto_if_src(), but with checksum */ 00697 err_t 00698 udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, 00699 u16_t dst_port, struct netif *netif, u8_t have_chksum, 00700 u16_t chksum, const ip_addr_t *src_ip) 00701 { 00702 #endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ 00703 struct udp_hdr *udphdr; 00704 err_t err; 00705 struct pbuf *q; /* q will be sent down the stack */ 00706 u8_t ip_proto; 00707 u8_t ttl; 00708 00709 if ((pcb == NULL) || (dst_ip == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, src_ip) || 00710 !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) { 00711 return ERR_VAL; 00712 } 00713 00714 #if LWIP_IPV4 && IP_SOF_BROADCAST 00715 /* broadcast filter? */ 00716 if (!ip_get_option(pcb, SOF_BROADCAST) && 00717 #if LWIP_IPV6 00718 IP_IS_V4(dst_ip) && 00719 #endif /* LWIP_IPV6 */ 00720 ip_addr_isbroadcast(dst_ip, netif)) { 00721 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 00722 ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); 00723 return ERR_VAL; 00724 } 00725 #endif /* LWIP_IPV4 && IP_SOF_BROADCAST */ 00726 00727 /* if the PCB is not yet bound to a port, bind it here */ 00728 if (pcb->local_port == 0) { 00729 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send: not yet bound to a port, binding now\n")); 00730 err = udp_bind(pcb, &pcb->local_ip, pcb->local_port); 00731 if (err != ERR_OK) { 00732 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: forced port bind failed\n")); 00733 return err; 00734 } 00735 } 00736 00737 /* not enough space to add an UDP header to first pbuf in given p chain? */ 00738 if (pbuf_header(p, UDP_HLEN)) { 00739 /* allocate header in a separate new pbuf */ 00740 q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM); 00741 /* new header pbuf could not be allocated? */ 00742 if (q == NULL) { 00743 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n")); 00744 return ERR_MEM; 00745 } 00746 if (p->tot_len != 0) { 00747 /* chain header q in front of given pbuf p (only if p contains data) */ 00748 pbuf_chain(q, p); 00749 } 00750 /* first pbuf q points to header pbuf */ 00751 LWIP_DEBUGF(UDP_DEBUG, 00752 ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); 00753 } else { 00754 /* adding space for header within p succeeded */ 00755 /* first pbuf q equals given pbuf */ 00756 q = p; 00757 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p)); 00758 } 00759 LWIP_ASSERT("check that first pbuf can hold struct udp_hdr", 00760 (q->len >= sizeof(struct udp_hdr))); 00761 /* q now represents the packet to be sent */ 00762 udphdr = (struct udp_hdr *)q->payload; 00763 udphdr->src = htons(pcb->local_port); 00764 udphdr->dest = htons(dst_port); 00765 /* in UDP, 0 checksum means 'no checksum' */ 00766 udphdr->chksum = 0x0000; 00767 00768 /* Multicast Loop? */ 00769 #if (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) || (LWIP_IPV6 && LWIP_IPV6_MLD) 00770 if (((pcb->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) && ip_addr_ismulticast(dst_ip)) { 00771 q->flags |= PBUF_FLAG_MCASTLOOP; 00772 } 00773 #endif /* (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) || (LWIP_IPV6 && LWIP_IPV6_MLD) */ 00774 00775 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len)); 00776 00777 #if LWIP_UDPLITE 00778 /* UDP Lite protocol? */ 00779 if (pcb->flags & UDP_FLAGS_UDPLITE) { 00780 u16_t chklen, chklen_hdr; 00781 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len)); 00782 /* set UDP message length in UDP header */ 00783 chklen_hdr = chklen = pcb->chksum_len_tx; 00784 if ((chklen < sizeof(struct udp_hdr)) || (chklen > q->tot_len)) { 00785 if (chklen != 0) { 00786 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE pcb->chksum_len is illegal: %"U16_F"\n", chklen)); 00787 } 00788 /* For UDP-Lite, checksum length of 0 means checksum 00789 over the complete packet. (See RFC 3828 chap. 3.1) 00790 At least the UDP-Lite header must be covered by the 00791 checksum, therefore, if chksum_len has an illegal 00792 value, we generate the checksum over the complete 00793 packet to be safe. */ 00794 chklen_hdr = 0; 00795 chklen = q->tot_len; 00796 } 00797 udphdr->len = htons(chklen_hdr); 00798 /* calculate checksum */ 00799 #if CHECKSUM_GEN_UDP 00800 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_UDP) { 00801 #if LWIP_CHECKSUM_ON_COPY 00802 if (have_chksum) { 00803 chklen = UDP_HLEN; 00804 } 00805 #endif /* LWIP_CHECKSUM_ON_COPY */ 00806 udphdr->chksum = ip_chksum_pseudo_partial(q, IP_PROTO_UDPLITE, 00807 q->tot_len, chklen, src_ip, dst_ip); 00808 #if LWIP_CHECKSUM_ON_COPY 00809 if (have_chksum) { 00810 u32_t acc; 00811 acc = udphdr->chksum + (u16_t)~(chksum); 00812 udphdr->chksum = FOLD_U32T(acc); 00813 } 00814 #endif /* LWIP_CHECKSUM_ON_COPY */ 00815 00816 /* chksum zero must become 0xffff, as zero means 'no checksum' */ 00817 if (udphdr->chksum == 0x0000) { 00818 udphdr->chksum = 0xffff; 00819 } 00820 } 00821 #endif /* CHECKSUM_GEN_UDP */ 00822 00823 ip_proto = IP_PROTO_UDPLITE; 00824 } else 00825 #endif /* LWIP_UDPLITE */ 00826 { /* UDP */ 00827 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len)); 00828 udphdr->len = htons(q->tot_len); 00829 /* calculate checksum */ 00830 #if CHECKSUM_GEN_UDP 00831 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_UDP) { 00832 /* Checksum is mandatory over IPv6. */ 00833 if (IP_IS_V6(dst_ip) || (pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) { 00834 u16_t udpchksum; 00835 #if LWIP_CHECKSUM_ON_COPY 00836 if (have_chksum) { 00837 u32_t acc; 00838 udpchksum = ip_chksum_pseudo_partial(q, IP_PROTO_UDP, 00839 q->tot_len, UDP_HLEN, src_ip, dst_ip); 00840 acc = udpchksum + (u16_t)~(chksum); 00841 udpchksum = FOLD_U32T(acc); 00842 } else 00843 #endif /* LWIP_CHECKSUM_ON_COPY */ 00844 { 00845 udpchksum = ip_chksum_pseudo(q, IP_PROTO_UDP, q->tot_len, 00846 src_ip, dst_ip); 00847 } 00848 00849 /* chksum zero must become 0xffff, as zero means 'no checksum' */ 00850 if (udpchksum == 0x0000) { 00851 udpchksum = 0xffff; 00852 } 00853 udphdr->chksum = udpchksum; 00854 } 00855 } 00856 #endif /* CHECKSUM_GEN_UDP */ 00857 ip_proto = IP_PROTO_UDP; 00858 } 00859 00860 /* Determine TTL to use */ 00861 #if LWIP_MULTICAST_TX_OPTIONS 00862 ttl = (ip_addr_ismulticast(dst_ip) ? pcb->mcast_ttl : pcb->ttl); 00863 #else /* LWIP_MULTICAST_TX_OPTIONS */ 00864 ttl = pcb->ttl; 00865 #endif /* LWIP_MULTICAST_TX_OPTIONS */ 00866 00867 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum)); 00868 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,0x%02"X16_F",)\n", (u16_t)ip_proto)); 00869 /* output to IP */ 00870 NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); 00871 err = ip_output_if_src(q, src_ip, dst_ip, ttl, pcb->tos, ip_proto, netif); 00872 NETIF_SET_HWADDRHINT(netif, NULL); 00873 00874 /* @todo: must this be increased even if error occurred? */ 00875 MIB2_STATS_INC(mib2.udpoutdatagrams); 00876 00877 /* did we chain a separate header pbuf earlier? */ 00878 if (q != p) { 00879 /* free the header pbuf */ 00880 pbuf_free(q); 00881 q = NULL; 00882 /* p is still referenced by the caller, and will live on */ 00883 } 00884 00885 UDP_STATS_INC(udp.xmit); 00886 return err; 00887 } 00888 00889 /** 00890 * @ingroup udp_raw 00891 * Bind an UDP PCB. 00892 * 00893 * @param pcb UDP PCB to be bound with a local address ipaddr and port. 00894 * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to 00895 * bind to all local interfaces. 00896 * @param port local UDP port to bind with. Use 0 to automatically bind 00897 * to a random port between UDP_LOCAL_PORT_RANGE_START and 00898 * UDP_LOCAL_PORT_RANGE_END. 00899 * 00900 * ipaddr & port are expected to be in the same byte order as in the pcb. 00901 * 00902 * @return lwIP error code. 00903 * - ERR_OK. Successful. No error occurred. 00904 * - ERR_USE. The specified ipaddr and port are already bound to by 00905 * another UDP PCB. 00906 * 00907 * @see udp_disconnect() 00908 */ 00909 err_t 00910 udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) 00911 { 00912 struct udp_pcb *ipcb; 00913 u8_t rebind; 00914 00915 #if LWIP_IPV4 00916 /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ 00917 if (ipaddr == NULL) { 00918 ipaddr = IP_ADDR_ANY; 00919 } 00920 #endif /* LWIP_IPV4 */ 00921 00922 /* still need to check for ipaddr == NULL in IPv6 only case */ 00923 if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) { 00924 return ERR_VAL; 00925 } 00926 00927 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = ")); 00928 ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE, ipaddr); 00929 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port)); 00930 00931 rebind = 0; 00932 /* Check for double bind and rebind of the same pcb */ 00933 for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { 00934 /* is this UDP PCB already on active list? */ 00935 if (pcb == ipcb) { 00936 rebind = 1; 00937 break; 00938 } 00939 } 00940 00941 /* no port specified? */ 00942 if (port == 0) { 00943 port = udp_new_port(); 00944 if (port == 0) { 00945 /* no more ports available in local range */ 00946 LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n")); 00947 return ERR_USE; 00948 } 00949 } else { 00950 for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { 00951 if (pcb != ipcb) { 00952 /* By default, we don't allow to bind to a port that any other udp 00953 PCB is already bound to, unless *all* PCBs with that port have tha 00954 REUSEADDR flag set. */ 00955 #if SO_REUSE 00956 if (!ip_get_option(pcb, SOF_REUSEADDR) || 00957 !ip_get_option(ipcb, SOF_REUSEADDR)) 00958 #endif /* SO_REUSE */ 00959 { 00960 /* port matches that of PCB in list and REUSEADDR not set -> reject */ 00961 if ((ipcb->local_port == port) && 00962 /* IP address matches? */ 00963 ip_addr_cmp(&ipcb->local_ip, ipaddr)) { 00964 /* other PCB already binds to this local IP and port */ 00965 LWIP_DEBUGF(UDP_DEBUG, 00966 ("udp_bind: local port %"U16_F" already bound by another pcb\n", port)); 00967 return ERR_USE; 00968 } 00969 } 00970 } 00971 } 00972 } 00973 00974 ip_addr_set_ipaddr(&pcb->local_ip, ipaddr); 00975 00976 pcb->local_port = port; 00977 mib2_udp_bind(pcb); 00978 /* pcb not active yet? */ 00979 if (rebind == 0) { 00980 /* place the PCB on the active list if not already there */ 00981 pcb->next = udp_pcbs; 00982 udp_pcbs = pcb; 00983 } 00984 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_bind: bound to ")); 00985 ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, &pcb->local_ip); 00986 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->local_port)); 00987 return ERR_OK; 00988 } 00989 00990 /** 00991 * @ingroup udp_raw 00992 * Connect an UDP PCB. 00993 * 00994 * This will associate the UDP PCB with the remote address. 00995 * 00996 * @param pcb UDP PCB to be connected with remote address ipaddr and port. 00997 * @param ipaddr remote IP address to connect with. 00998 * @param port remote UDP port to connect with. 00999 * 01000 * @return lwIP error code 01001 * 01002 * ipaddr & port are expected to be in the same byte order as in the pcb. 01003 * 01004 * The udp pcb is bound to a random local port if not already bound. 01005 * 01006 * @see udp_disconnect() 01007 */ 01008 err_t 01009 udp_connect(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) 01010 { 01011 struct udp_pcb *ipcb; 01012 01013 if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) { 01014 return ERR_VAL; 01015 } 01016 01017 if (pcb->local_port == 0) { 01018 err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port); 01019 if (err != ERR_OK) { 01020 return err; 01021 } 01022 } 01023 01024 ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr); 01025 pcb->remote_port = port; 01026 pcb->flags |= UDP_FLAGS_CONNECTED; 01027 01028 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_connect: connected to ")); 01029 ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, 01030 &pcb->remote_ip); 01031 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->remote_port)); 01032 01033 /* Insert UDP PCB into the list of active UDP PCBs. */ 01034 for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { 01035 if (pcb == ipcb) { 01036 /* already on the list, just return */ 01037 return ERR_OK; 01038 } 01039 } 01040 /* PCB not yet on the list, add PCB now */ 01041 pcb->next = udp_pcbs; 01042 udp_pcbs = pcb; 01043 return ERR_OK; 01044 } 01045 01046 /** 01047 * @ingroup udp_raw 01048 * Disconnect a UDP PCB 01049 * 01050 * @param pcb the udp pcb to disconnect. 01051 */ 01052 void 01053 udp_disconnect(struct udp_pcb *pcb) 01054 { 01055 /* reset remote address association */ 01056 #if LWIP_IPV4 && LWIP_IPV6 01057 if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { 01058 ip_addr_copy(pcb->remote_ip, *IP_ANY_TYPE); 01059 } else { 01060 #endif 01061 ip_addr_set_any(IP_IS_V6_VAL(pcb->remote_ip), &pcb->remote_ip); 01062 #if LWIP_IPV4 && LWIP_IPV6 01063 } 01064 #endif 01065 pcb->remote_port = 0; 01066 /* mark PCB as unconnected */ 01067 pcb->flags &= ~UDP_FLAGS_CONNECTED; 01068 } 01069 01070 /** 01071 * @ingroup udp_raw 01072 * Set a receive callback for a UDP PCB 01073 * 01074 * This callback will be called when receiving a datagram for the pcb. 01075 * 01076 * @param pcb the pcb for which to set the recv callback 01077 * @param recv function pointer of the callback function 01078 * @param recv_arg additional argument to pass to the callback function 01079 */ 01080 void 01081 udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg) 01082 { 01083 /* remember recv() callback and user data */ 01084 pcb->recv = recv; 01085 pcb->recv_arg = recv_arg; 01086 } 01087 01088 /** 01089 * @ingroup udp_raw 01090 * Remove an UDP PCB. 01091 * 01092 * @param pcb UDP PCB to be removed. The PCB is removed from the list of 01093 * UDP PCB's and the data structure is freed from memory. 01094 * 01095 * @see udp_new() 01096 */ 01097 void 01098 udp_remove(struct udp_pcb *pcb) 01099 { 01100 struct udp_pcb *pcb2; 01101 01102 mib2_udp_unbind(pcb); 01103 /* pcb to be removed is first in list? */ 01104 if (udp_pcbs == pcb) { 01105 /* make list start at 2nd pcb */ 01106 udp_pcbs = udp_pcbs->next; 01107 /* pcb not 1st in list */ 01108 } else { 01109 for (pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { 01110 /* find pcb in udp_pcbs list */ 01111 if (pcb2->next != NULL && pcb2->next == pcb) { 01112 /* remove pcb from list */ 01113 pcb2->next = pcb->next; 01114 break; 01115 } 01116 } 01117 } 01118 memp_free(MEMP_UDP_PCB, pcb); 01119 } 01120 01121 /** 01122 * @ingroup udp_raw 01123 * Create a UDP PCB. 01124 * 01125 * @return The UDP PCB which was created. NULL if the PCB data structure 01126 * could not be allocated. 01127 * 01128 * @see udp_remove() 01129 */ 01130 struct udp_pcb * 01131 udp_new(void) 01132 { 01133 struct udp_pcb *pcb; 01134 pcb = (struct udp_pcb *)memp_malloc(MEMP_UDP_PCB); 01135 /* could allocate UDP PCB? */ 01136 if (pcb != NULL) { 01137 /* UDP Lite: by initializing to all zeroes, chksum_len is set to 0 01138 * which means checksum is generated over the whole datagram per default 01139 * (recommended as default by RFC 3828). */ 01140 /* initialize PCB to all zeroes */ 01141 memset(pcb, 0, sizeof(struct udp_pcb)); 01142 pcb->ttl = UDP_TTL; 01143 #if LWIP_MULTICAST_TX_OPTIONS 01144 pcb->mcast_ttl = UDP_TTL; 01145 #endif /* LWIP_MULTICAST_TX_OPTIONS */ 01146 } 01147 return pcb; 01148 } 01149 01150 /** 01151 * @ingroup udp_raw 01152 * Create a UDP PCB for specific IP type. 01153 * 01154 * @param type IP address type, see IPADDR_TYPE_XX definitions. 01155 * @return The UDP PCB which was created. NULL if the PCB data structure 01156 * could not be allocated. 01157 * 01158 * @see udp_remove() 01159 */ 01160 struct udp_pcb * 01161 udp_new_ip_type(u8_t type) 01162 { 01163 struct udp_pcb *pcb; 01164 pcb = udp_new(); 01165 #if LWIP_IPV4 && LWIP_IPV6 01166 if (pcb != NULL) { 01167 IP_SET_TYPE_VAL(pcb->local_ip, type); 01168 IP_SET_TYPE_VAL(pcb->remote_ip, type); 01169 } 01170 #else 01171 LWIP_UNUSED_ARG(type); 01172 #endif /* LWIP_IPV4 && LWIP_IPV6 */ 01173 return pcb; 01174 } 01175 01176 #if LWIP_IPV4 01177 /** This function is called from netif.c when address is changed 01178 * 01179 * @param old_addr IPv4 address of the netif before change 01180 * @param new_addr IPv4 address of the netif after change 01181 */ 01182 void udp_netif_ipv4_addr_changed(const ip4_addr_t* old_addr, const ip4_addr_t* new_addr) 01183 { 01184 struct udp_pcb* upcb; 01185 01186 if (!ip4_addr_isany(new_addr)) { 01187 for (upcb = udp_pcbs; upcb != NULL; upcb = upcb->next) { 01188 /* Is this an IPv4 pcb? */ 01189 if (IP_IS_V4_VAL(upcb->local_ip)) { 01190 /* PCB bound to current local interface address? */ 01191 if (!ip4_addr_isany(ip_2_ip4(&upcb->local_ip)) && 01192 ip4_addr_cmp(ip_2_ip4(&upcb->local_ip), old_addr)) { 01193 /* The PCB is bound to the old ipaddr and 01194 * is set to bound to the new one instead */ 01195 ip_addr_copy_from_ip4(upcb->local_ip, *new_addr); 01196 } 01197 } 01198 } 01199 } 01200 } 01201 #endif /* LWIP_IPV4 */ 01202 01203 #if UDP_DEBUG 01204 /** 01205 * Print UDP header information for debug purposes. 01206 * 01207 * @param udphdr pointer to the udp header in memory. 01208 */ 01209 void 01210 udp_debug_print(struct udp_hdr *udphdr) 01211 { 01212 LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n")); 01213 LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); 01214 LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", 01215 ntohs(udphdr->src), ntohs(udphdr->dest))); 01216 LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); 01217 LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n", 01218 ntohs(udphdr->len), ntohs(udphdr->chksum))); 01219 LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); 01220 } 01221 #endif /* UDP_DEBUG */ 01222 01223 #endif /* LWIP_UDP */
Generated on Tue Jul 12 2022 17:34:47 by
