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