Used in Live Traffic Update Nokia LCD Display Project

Fork of NetServices by Segundo Equipo

Committer:
rrajan8
Date:
Wed Mar 06 19:07:23 2013 +0000
Revision:
8:92b57208ab99
Parent:
0:ac1725ba162c
This project utilizes mbed's networking features to display live traffic updates on the Nokia LCD using the MapQuest API's Traffic Web Service.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
segundo 0:ac1725ba162c 1 /**
segundo 0:ac1725ba162c 2 * @file
segundo 0:ac1725ba162c 3 * User Datagram Protocol module
segundo 0:ac1725ba162c 4 *
segundo 0:ac1725ba162c 5 */
segundo 0:ac1725ba162c 6
segundo 0:ac1725ba162c 7 /*
segundo 0:ac1725ba162c 8 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
segundo 0:ac1725ba162c 9 * All rights reserved.
segundo 0:ac1725ba162c 10 *
segundo 0:ac1725ba162c 11 * Redistribution and use in source and binary forms, with or without modification,
segundo 0:ac1725ba162c 12 * are permitted provided that the following conditions are met:
segundo 0:ac1725ba162c 13 *
segundo 0:ac1725ba162c 14 * 1. Redistributions of source code must retain the above copyright notice,
segundo 0:ac1725ba162c 15 * this list of conditions and the following disclaimer.
segundo 0:ac1725ba162c 16 * 2. Redistributions in binary form must reproduce the above copyright notice,
segundo 0:ac1725ba162c 17 * this list of conditions and the following disclaimer in the documentation
segundo 0:ac1725ba162c 18 * and/or other materials provided with the distribution.
segundo 0:ac1725ba162c 19 * 3. The name of the author may not be used to endorse or promote products
segundo 0:ac1725ba162c 20 * derived from this software without specific prior written permission.
segundo 0:ac1725ba162c 21 *
segundo 0:ac1725ba162c 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
segundo 0:ac1725ba162c 23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
segundo 0:ac1725ba162c 24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
segundo 0:ac1725ba162c 25 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
segundo 0:ac1725ba162c 26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
segundo 0:ac1725ba162c 27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
segundo 0:ac1725ba162c 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
segundo 0:ac1725ba162c 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
segundo 0:ac1725ba162c 30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
segundo 0:ac1725ba162c 31 * OF SUCH DAMAGE.
segundo 0:ac1725ba162c 32 *
segundo 0:ac1725ba162c 33 * This file is part of the lwIP TCP/IP stack.
segundo 0:ac1725ba162c 34 *
segundo 0:ac1725ba162c 35 * Author: Adam Dunkels <adam@sics.se>
segundo 0:ac1725ba162c 36 *
segundo 0:ac1725ba162c 37 */
segundo 0:ac1725ba162c 38
segundo 0:ac1725ba162c 39
segundo 0:ac1725ba162c 40 /* udp.c
segundo 0:ac1725ba162c 41 *
segundo 0:ac1725ba162c 42 * The code for the User Datagram Protocol UDP & UDPLite (RFC 3828).
segundo 0:ac1725ba162c 43 *
segundo 0:ac1725ba162c 44 */
segundo 0:ac1725ba162c 45
segundo 0:ac1725ba162c 46 /* @todo Check the use of '(struct udp_pcb).chksum_len_rx'!
segundo 0:ac1725ba162c 47 */
segundo 0:ac1725ba162c 48
segundo 0:ac1725ba162c 49 #include "lwip/opt.h"
segundo 0:ac1725ba162c 50
segundo 0:ac1725ba162c 51 #if LWIP_UDP /* don't build if not configured for use in lwipopts.h */
segundo 0:ac1725ba162c 52
segundo 0:ac1725ba162c 53 #include "lwip/udp.h"
segundo 0:ac1725ba162c 54 #include "lwip/def.h"
segundo 0:ac1725ba162c 55 #include "lwip/memp.h"
segundo 0:ac1725ba162c 56 #include "lwip/inet_chksum.h"
segundo 0:ac1725ba162c 57 #include "lwip/ip_addr.h"
segundo 0:ac1725ba162c 58 #include "lwip/netif.h"
segundo 0:ac1725ba162c 59 #include "lwip/icmp.h"
segundo 0:ac1725ba162c 60 #include "lwip/stats.h"
segundo 0:ac1725ba162c 61 #include "lwip/snmp.h"
segundo 0:ac1725ba162c 62 #include "arch/perf.h"
segundo 0:ac1725ba162c 63 #include "lwip/dhcp.h"
segundo 0:ac1725ba162c 64
segundo 0:ac1725ba162c 65 #include <string.h>
segundo 0:ac1725ba162c 66
segundo 0:ac1725ba162c 67 /* The list of UDP PCBs */
segundo 0:ac1725ba162c 68 /* exported in udp.h (was static) */
segundo 0:ac1725ba162c 69 struct udp_pcb *udp_pcbs;
segundo 0:ac1725ba162c 70
segundo 0:ac1725ba162c 71 /**
segundo 0:ac1725ba162c 72 * Process an incoming UDP datagram.
segundo 0:ac1725ba162c 73 *
segundo 0:ac1725ba162c 74 * Given an incoming UDP datagram (as a chain of pbufs) this function
segundo 0:ac1725ba162c 75 * finds a corresponding UDP PCB and hands over the pbuf to the pcbs
segundo 0:ac1725ba162c 76 * recv function. If no pcb is found or the datagram is incorrect, the
segundo 0:ac1725ba162c 77 * pbuf is freed.
segundo 0:ac1725ba162c 78 *
segundo 0:ac1725ba162c 79 * @param p pbuf to be demultiplexed to a UDP PCB.
segundo 0:ac1725ba162c 80 * @param inp network interface on which the datagram was received.
segundo 0:ac1725ba162c 81 *
segundo 0:ac1725ba162c 82 */
segundo 0:ac1725ba162c 83 void
segundo 0:ac1725ba162c 84 udp_input(struct pbuf *p, struct netif *inp)
segundo 0:ac1725ba162c 85 {
segundo 0:ac1725ba162c 86 struct udp_hdr *udphdr;
segundo 0:ac1725ba162c 87 struct udp_pcb *pcb, *prev;
segundo 0:ac1725ba162c 88 struct udp_pcb *uncon_pcb;
segundo 0:ac1725ba162c 89 struct ip_hdr *iphdr;
segundo 0:ac1725ba162c 90 u16_t src, dest;
segundo 0:ac1725ba162c 91 u8_t local_match;
segundo 0:ac1725ba162c 92 u8_t broadcast;
segundo 0:ac1725ba162c 93
segundo 0:ac1725ba162c 94 PERF_START;
segundo 0:ac1725ba162c 95
segundo 0:ac1725ba162c 96 UDP_STATS_INC(udp.recv);
segundo 0:ac1725ba162c 97
segundo 0:ac1725ba162c 98 iphdr = (struct ip_hdr *)p->payload;
segundo 0:ac1725ba162c 99
segundo 0:ac1725ba162c 100 /* Check minimum length (IP header + UDP header)
segundo 0:ac1725ba162c 101 * and move payload pointer to UDP header */
segundo 0:ac1725ba162c 102 if (p->tot_len < (IPH_HL(iphdr) * 4 + UDP_HLEN) || pbuf_header(p, -(s16_t)(IPH_HL(iphdr) * 4))) {
segundo 0:ac1725ba162c 103 /* drop short packets */
segundo 0:ac1725ba162c 104 LWIP_DEBUGF(UDP_DEBUG,
segundo 0:ac1725ba162c 105 ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len));
segundo 0:ac1725ba162c 106 UDP_STATS_INC(udp.lenerr);
segundo 0:ac1725ba162c 107 UDP_STATS_INC(udp.drop);
segundo 0:ac1725ba162c 108 snmp_inc_udpinerrors();
segundo 0:ac1725ba162c 109 pbuf_free(p);
segundo 0:ac1725ba162c 110 goto end;
segundo 0:ac1725ba162c 111 }
segundo 0:ac1725ba162c 112
segundo 0:ac1725ba162c 113 udphdr = (struct udp_hdr *)p->payload;
segundo 0:ac1725ba162c 114
segundo 0:ac1725ba162c 115 /* is broadcast packet ? */
segundo 0:ac1725ba162c 116 broadcast = ip_addr_isbroadcast(&current_iphdr_dest, inp);
segundo 0:ac1725ba162c 117
segundo 0:ac1725ba162c 118 LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len));
segundo 0:ac1725ba162c 119
segundo 0:ac1725ba162c 120 /* convert src and dest ports to host byte order */
segundo 0:ac1725ba162c 121 src = ntohs(udphdr->src);
segundo 0:ac1725ba162c 122 dest = ntohs(udphdr->dest);
segundo 0:ac1725ba162c 123
segundo 0:ac1725ba162c 124 udp_debug_print(udphdr);
segundo 0:ac1725ba162c 125
segundo 0:ac1725ba162c 126 /* print the UDP source and destination */
segundo 0:ac1725ba162c 127 LWIP_DEBUGF(UDP_DEBUG,
segundo 0:ac1725ba162c 128 ("udp (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") <-- "
segundo 0:ac1725ba162c 129 "(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
segundo 0:ac1725ba162c 130 ip4_addr1_16(&iphdr->dest), ip4_addr2_16(&iphdr->dest),
segundo 0:ac1725ba162c 131 ip4_addr3_16(&iphdr->dest), ip4_addr4_16(&iphdr->dest), ntohs(udphdr->dest),
segundo 0:ac1725ba162c 132 ip4_addr1_16(&iphdr->src), ip4_addr2_16(&iphdr->src),
segundo 0:ac1725ba162c 133 ip4_addr3_16(&iphdr->src), ip4_addr4_16(&iphdr->src), ntohs(udphdr->src)));
segundo 0:ac1725ba162c 134
segundo 0:ac1725ba162c 135 #if LWIP_DHCP
segundo 0:ac1725ba162c 136 pcb = NULL;
segundo 0:ac1725ba162c 137 /* when LWIP_DHCP is active, packets to DHCP_CLIENT_PORT may only be processed by
segundo 0:ac1725ba162c 138 the dhcp module, no other UDP pcb may use the local UDP port DHCP_CLIENT_PORT */
segundo 0:ac1725ba162c 139 if (dest == DHCP_CLIENT_PORT) {
segundo 0:ac1725ba162c 140 /* all packets for DHCP_CLIENT_PORT not coming from DHCP_SERVER_PORT are dropped! */
segundo 0:ac1725ba162c 141 if (src == DHCP_SERVER_PORT) {
segundo 0:ac1725ba162c 142 if ((inp->dhcp != NULL) && (inp->dhcp->pcb != NULL)) {
segundo 0:ac1725ba162c 143 /* accept the packe if
segundo 0:ac1725ba162c 144 (- broadcast or directed to us) -> DHCP is link-layer-addressed, local ip is always ANY!
segundo 0:ac1725ba162c 145 - inp->dhcp->pcb->remote == ANY or iphdr->src */
segundo 0:ac1725ba162c 146 if ((ip_addr_isany(&inp->dhcp->pcb->remote_ip) ||
segundo 0:ac1725ba162c 147 ip_addr_cmp(&(inp->dhcp->pcb->remote_ip), &current_iphdr_src))) {
segundo 0:ac1725ba162c 148 pcb = inp->dhcp->pcb;
segundo 0:ac1725ba162c 149 }
segundo 0:ac1725ba162c 150 }
segundo 0:ac1725ba162c 151 }
segundo 0:ac1725ba162c 152 } else
segundo 0:ac1725ba162c 153 #endif /* LWIP_DHCP */
segundo 0:ac1725ba162c 154 {
segundo 0:ac1725ba162c 155 prev = NULL;
segundo 0:ac1725ba162c 156 local_match = 0;
segundo 0:ac1725ba162c 157 uncon_pcb = NULL;
segundo 0:ac1725ba162c 158 /* Iterate through the UDP pcb list for a matching pcb.
segundo 0:ac1725ba162c 159 * 'Perfect match' pcbs (connected to the remote port & ip address) are
segundo 0:ac1725ba162c 160 * preferred. If no perfect match is found, the first unconnected pcb that
segundo 0:ac1725ba162c 161 * matches the local port and ip address gets the datagram. */
segundo 0:ac1725ba162c 162 for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
segundo 0:ac1725ba162c 163 local_match = 0;
segundo 0:ac1725ba162c 164 /* print the PCB local and remote address */
segundo 0:ac1725ba162c 165 LWIP_DEBUGF(UDP_DEBUG,
segundo 0:ac1725ba162c 166 ("pcb (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") --- "
segundo 0:ac1725ba162c 167 "(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
segundo 0:ac1725ba162c 168 ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
segundo 0:ac1725ba162c 169 ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip), pcb->local_port,
segundo 0:ac1725ba162c 170 ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),
segundo 0:ac1725ba162c 171 ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip), pcb->remote_port));
segundo 0:ac1725ba162c 172
segundo 0:ac1725ba162c 173 /* compare PCB local addr+port to UDP destination addr+port */
segundo 0:ac1725ba162c 174 if ((pcb->local_port == dest) &&
segundo 0:ac1725ba162c 175 ((!broadcast && ip_addr_isany(&pcb->local_ip)) ||
segundo 0:ac1725ba162c 176 ip_addr_cmp(&(pcb->local_ip), &current_iphdr_dest) ||
segundo 0:ac1725ba162c 177 #if LWIP_IGMP
segundo 0:ac1725ba162c 178 ip_addr_ismulticast(&current_iphdr_dest) ||
segundo 0:ac1725ba162c 179 #endif /* LWIP_IGMP */
segundo 0:ac1725ba162c 180 #if IP_SOF_BROADCAST_RECV
segundo 0:ac1725ba162c 181 (broadcast && (pcb->so_options & SOF_BROADCAST)))) {
segundo 0:ac1725ba162c 182 #else /* IP_SOF_BROADCAST_RECV */
segundo 0:ac1725ba162c 183 (broadcast))) {
segundo 0:ac1725ba162c 184 #endif /* IP_SOF_BROADCAST_RECV */
segundo 0:ac1725ba162c 185 local_match = 1;
segundo 0:ac1725ba162c 186 if ((uncon_pcb == NULL) &&
segundo 0:ac1725ba162c 187 ((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) {
segundo 0:ac1725ba162c 188 /* the first unconnected matching PCB */
segundo 0:ac1725ba162c 189 uncon_pcb = pcb;
segundo 0:ac1725ba162c 190 }
segundo 0:ac1725ba162c 191 }
segundo 0:ac1725ba162c 192 /* compare PCB remote addr+port to UDP source addr+port */
segundo 0:ac1725ba162c 193 if ((local_match != 0) &&
segundo 0:ac1725ba162c 194 (pcb->remote_port == src) &&
segundo 0:ac1725ba162c 195 (ip_addr_isany(&pcb->remote_ip) ||
segundo 0:ac1725ba162c 196 ip_addr_cmp(&(pcb->remote_ip), &current_iphdr_src))) {
segundo 0:ac1725ba162c 197 /* the first fully matching PCB */
segundo 0:ac1725ba162c 198 if (prev != NULL) {
segundo 0:ac1725ba162c 199 /* move the pcb to the front of udp_pcbs so that is
segundo 0:ac1725ba162c 200 found faster next time */
segundo 0:ac1725ba162c 201 prev->next = pcb->next;
segundo 0:ac1725ba162c 202 pcb->next = udp_pcbs;
segundo 0:ac1725ba162c 203 udp_pcbs = pcb;
segundo 0:ac1725ba162c 204 } else {
segundo 0:ac1725ba162c 205 UDP_STATS_INC(udp.cachehit);
segundo 0:ac1725ba162c 206 }
segundo 0:ac1725ba162c 207 break;
segundo 0:ac1725ba162c 208 }
segundo 0:ac1725ba162c 209 prev = pcb;
segundo 0:ac1725ba162c 210 }
segundo 0:ac1725ba162c 211 /* no fully matching pcb found? then look for an unconnected pcb */
segundo 0:ac1725ba162c 212 if (pcb == NULL) {
segundo 0:ac1725ba162c 213 pcb = uncon_pcb;
segundo 0:ac1725ba162c 214 }
segundo 0:ac1725ba162c 215 }
segundo 0:ac1725ba162c 216
segundo 0:ac1725ba162c 217 /* Check checksum if this is a match or if it was directed at us. */
segundo 0:ac1725ba162c 218 if (pcb != NULL || ip_addr_cmp(&inp->ip_addr, &current_iphdr_dest)) {
segundo 0:ac1725ba162c 219 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n"));
segundo 0:ac1725ba162c 220 #if LWIP_UDPLITE
segundo 0:ac1725ba162c 221 if (IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) {
segundo 0:ac1725ba162c 222 /* Do the UDP Lite checksum */
segundo 0:ac1725ba162c 223 #if CHECKSUM_CHECK_UDP
segundo 0:ac1725ba162c 224 u16_t chklen = ntohs(udphdr->len);
segundo 0:ac1725ba162c 225 if (chklen < sizeof(struct udp_hdr)) {
segundo 0:ac1725ba162c 226 if (chklen == 0) {
segundo 0:ac1725ba162c 227 /* For UDP-Lite, checksum length of 0 means checksum
segundo 0:ac1725ba162c 228 over the complete packet (See RFC 3828 chap. 3.1) */
segundo 0:ac1725ba162c 229 chklen = p->tot_len;
segundo 0:ac1725ba162c 230 } else {
segundo 0:ac1725ba162c 231 /* At least the UDP-Lite header must be covered by the
segundo 0:ac1725ba162c 232 checksum! (Again, see RFC 3828 chap. 3.1) */
segundo 0:ac1725ba162c 233 UDP_STATS_INC(udp.chkerr);
segundo 0:ac1725ba162c 234 UDP_STATS_INC(udp.drop);
segundo 0:ac1725ba162c 235 snmp_inc_udpinerrors();
segundo 0:ac1725ba162c 236 pbuf_free(p);
segundo 0:ac1725ba162c 237 goto end;
segundo 0:ac1725ba162c 238 }
segundo 0:ac1725ba162c 239 }
segundo 0:ac1725ba162c 240 if (inet_chksum_pseudo_partial(p, &current_iphdr_src, &current_iphdr_dest,
segundo 0:ac1725ba162c 241 IP_PROTO_UDPLITE, p->tot_len, chklen) != 0) {
segundo 0:ac1725ba162c 242 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
segundo 0:ac1725ba162c 243 ("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
segundo 0:ac1725ba162c 244 UDP_STATS_INC(udp.chkerr);
segundo 0:ac1725ba162c 245 UDP_STATS_INC(udp.drop);
segundo 0:ac1725ba162c 246 snmp_inc_udpinerrors();
segundo 0:ac1725ba162c 247 pbuf_free(p);
segundo 0:ac1725ba162c 248 goto end;
segundo 0:ac1725ba162c 249 }
segundo 0:ac1725ba162c 250 #endif /* CHECKSUM_CHECK_UDP */
segundo 0:ac1725ba162c 251 } else
segundo 0:ac1725ba162c 252 #endif /* LWIP_UDPLITE */
segundo 0:ac1725ba162c 253 {
segundo 0:ac1725ba162c 254 #if CHECKSUM_CHECK_UDP
segundo 0:ac1725ba162c 255 if (udphdr->chksum != 0) {
segundo 0:ac1725ba162c 256 if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
segundo 0:ac1725ba162c 257 IP_PROTO_UDP, p->tot_len) != 0) {
segundo 0:ac1725ba162c 258 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
segundo 0:ac1725ba162c 259 ("udp_input: UDP datagram discarded due to failing checksum\n"));
segundo 0:ac1725ba162c 260 UDP_STATS_INC(udp.chkerr);
segundo 0:ac1725ba162c 261 UDP_STATS_INC(udp.drop);
segundo 0:ac1725ba162c 262 snmp_inc_udpinerrors();
segundo 0:ac1725ba162c 263 pbuf_free(p);
segundo 0:ac1725ba162c 264 goto end;
segundo 0:ac1725ba162c 265 }
segundo 0:ac1725ba162c 266 }
segundo 0:ac1725ba162c 267 #endif /* CHECKSUM_CHECK_UDP */
segundo 0:ac1725ba162c 268 }
segundo 0:ac1725ba162c 269 if(pbuf_header(p, -UDP_HLEN)) {
segundo 0:ac1725ba162c 270 /* Can we cope with this failing? Just assert for now */
segundo 0:ac1725ba162c 271 LWIP_ASSERT("pbuf_header failed\n", 0);
segundo 0:ac1725ba162c 272 UDP_STATS_INC(udp.drop);
segundo 0:ac1725ba162c 273 snmp_inc_udpinerrors();
segundo 0:ac1725ba162c 274 pbuf_free(p);
segundo 0:ac1725ba162c 275 goto end;
segundo 0:ac1725ba162c 276 }
segundo 0:ac1725ba162c 277 if (pcb != NULL) {
segundo 0:ac1725ba162c 278 snmp_inc_udpindatagrams();
segundo 0:ac1725ba162c 279 #if SO_REUSE && SO_REUSE_RXTOALL
segundo 0:ac1725ba162c 280 if ((broadcast || ip_addr_ismulticast(&current_iphdr_dest)) &&
segundo 0:ac1725ba162c 281 ((pcb->so_options & SOF_REUSEADDR) != 0)) {
segundo 0:ac1725ba162c 282 /* pass broadcast- or multicast packets to all multicast pcbs
segundo 0:ac1725ba162c 283 if SOF_REUSEADDR is set on the first match */
segundo 0:ac1725ba162c 284 struct udp_pcb *mpcb;
segundo 0:ac1725ba162c 285 u8_t p_header_changed = 0;
segundo 0:ac1725ba162c 286 for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) {
segundo 0:ac1725ba162c 287 if (mpcb != pcb) {
segundo 0:ac1725ba162c 288 /* compare PCB local addr+port to UDP destination addr+port */
segundo 0:ac1725ba162c 289 if ((mpcb->local_port == dest) &&
segundo 0:ac1725ba162c 290 ((!broadcast && ip_addr_isany(&mpcb->local_ip)) ||
segundo 0:ac1725ba162c 291 ip_addr_cmp(&(mpcb->local_ip), &current_iphdr_dest) ||
segundo 0:ac1725ba162c 292 #if LWIP_IGMP
segundo 0:ac1725ba162c 293 ip_addr_ismulticast(&current_iphdr_dest) ||
segundo 0:ac1725ba162c 294 #endif /* LWIP_IGMP */
segundo 0:ac1725ba162c 295 #if IP_SOF_BROADCAST_RECV
segundo 0:ac1725ba162c 296 (broadcast && (mpcb->so_options & SOF_BROADCAST)))) {
segundo 0:ac1725ba162c 297 #else /* IP_SOF_BROADCAST_RECV */
segundo 0:ac1725ba162c 298 (broadcast))) {
segundo 0:ac1725ba162c 299 #endif /* IP_SOF_BROADCAST_RECV */
segundo 0:ac1725ba162c 300 /* pass a copy of the packet to all local matches */
segundo 0:ac1725ba162c 301 if (mpcb->recv != NULL) {
segundo 0:ac1725ba162c 302 struct pbuf *q;
segundo 0:ac1725ba162c 303 /* for that, move payload to IP header again */
segundo 0:ac1725ba162c 304 if (p_header_changed == 0) {
segundo 0:ac1725ba162c 305 pbuf_header(p, (s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
segundo 0:ac1725ba162c 306 p_header_changed = 1;
segundo 0:ac1725ba162c 307 }
segundo 0:ac1725ba162c 308 q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
segundo 0:ac1725ba162c 309 if (q != NULL) {
segundo 0:ac1725ba162c 310 err_t err = pbuf_copy(q, p);
segundo 0:ac1725ba162c 311 if (err == ERR_OK) {
segundo 0:ac1725ba162c 312 /* move payload to UDP data */
segundo 0:ac1725ba162c 313 pbuf_header(q, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
segundo 0:ac1725ba162c 314 mpcb->recv(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src);
segundo 0:ac1725ba162c 315 }
segundo 0:ac1725ba162c 316 }
segundo 0:ac1725ba162c 317 }
segundo 0:ac1725ba162c 318 }
segundo 0:ac1725ba162c 319 }
segundo 0:ac1725ba162c 320 }
segundo 0:ac1725ba162c 321 if (p_header_changed) {
segundo 0:ac1725ba162c 322 /* and move payload to UDP data again */
segundo 0:ac1725ba162c 323 pbuf_header(p, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
segundo 0:ac1725ba162c 324 }
segundo 0:ac1725ba162c 325 }
segundo 0:ac1725ba162c 326 #endif /* SO_REUSE && SO_REUSE_RXTOALL */
segundo 0:ac1725ba162c 327 /* callback */
segundo 0:ac1725ba162c 328 if (pcb->recv != NULL) {
segundo 0:ac1725ba162c 329 /* now the recv function is responsible for freeing p */
segundo 0:ac1725ba162c 330 pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr(), src);
segundo 0:ac1725ba162c 331 } else {
segundo 0:ac1725ba162c 332 /* no recv function registered? then we have to free the pbuf! */
segundo 0:ac1725ba162c 333 pbuf_free(p);
segundo 0:ac1725ba162c 334 goto end;
segundo 0:ac1725ba162c 335 }
segundo 0:ac1725ba162c 336 } else {
segundo 0:ac1725ba162c 337 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: not for us.\n"));
segundo 0:ac1725ba162c 338
segundo 0:ac1725ba162c 339 #if LWIP_ICMP
segundo 0:ac1725ba162c 340 /* No match was found, send ICMP destination port unreachable unless
segundo 0:ac1725ba162c 341 destination address was broadcast/multicast. */
segundo 0:ac1725ba162c 342 if (!broadcast &&
segundo 0:ac1725ba162c 343 !ip_addr_ismulticast(&current_iphdr_dest)) {
segundo 0:ac1725ba162c 344 /* move payload pointer back to ip header */
segundo 0:ac1725ba162c 345 pbuf_header(p, (IPH_HL(iphdr) * 4) + UDP_HLEN);
segundo 0:ac1725ba162c 346 LWIP_ASSERT("p->payload == iphdr", (p->payload == iphdr));
segundo 0:ac1725ba162c 347 icmp_dest_unreach(p, ICMP_DUR_PORT);
segundo 0:ac1725ba162c 348 }
segundo 0:ac1725ba162c 349 #endif /* LWIP_ICMP */
segundo 0:ac1725ba162c 350 UDP_STATS_INC(udp.proterr);
segundo 0:ac1725ba162c 351 UDP_STATS_INC(udp.drop);
segundo 0:ac1725ba162c 352 snmp_inc_udpnoports();
segundo 0:ac1725ba162c 353 pbuf_free(p);
segundo 0:ac1725ba162c 354 }
segundo 0:ac1725ba162c 355 } else {
segundo 0:ac1725ba162c 356 pbuf_free(p);
segundo 0:ac1725ba162c 357 }
segundo 0:ac1725ba162c 358 end:
segundo 0:ac1725ba162c 359 PERF_STOP("udp_input");
segundo 0:ac1725ba162c 360 }
segundo 0:ac1725ba162c 361
segundo 0:ac1725ba162c 362 /**
segundo 0:ac1725ba162c 363 * Send data using UDP.
segundo 0:ac1725ba162c 364 *
segundo 0:ac1725ba162c 365 * @param pcb UDP PCB used to send the data.
segundo 0:ac1725ba162c 366 * @param p chain of pbuf's to be sent.
segundo 0:ac1725ba162c 367 *
segundo 0:ac1725ba162c 368 * The datagram will be sent to the current remote_ip & remote_port
segundo 0:ac1725ba162c 369 * stored in pcb. If the pcb is not bound to a port, it will
segundo 0:ac1725ba162c 370 * automatically be bound to a random port.
segundo 0:ac1725ba162c 371 *
segundo 0:ac1725ba162c 372 * @return lwIP error code.
segundo 0:ac1725ba162c 373 * - ERR_OK. Successful. No error occured.
segundo 0:ac1725ba162c 374 * - ERR_MEM. Out of memory.
segundo 0:ac1725ba162c 375 * - ERR_RTE. Could not find route to destination address.
segundo 0:ac1725ba162c 376 * - More errors could be returned by lower protocol layers.
segundo 0:ac1725ba162c 377 *
segundo 0:ac1725ba162c 378 * @see udp_disconnect() udp_sendto()
segundo 0:ac1725ba162c 379 */
segundo 0:ac1725ba162c 380 err_t
segundo 0:ac1725ba162c 381 udp_send(struct udp_pcb *pcb, struct pbuf *p)
segundo 0:ac1725ba162c 382 {
segundo 0:ac1725ba162c 383 /* send to the packet using remote ip and port stored in the pcb */
segundo 0:ac1725ba162c 384 return udp_sendto(pcb, p, &pcb->remote_ip, pcb->remote_port);
segundo 0:ac1725ba162c 385 }
segundo 0:ac1725ba162c 386
segundo 0:ac1725ba162c 387 #if LWIP_CHECKSUM_ON_COPY
segundo 0:ac1725ba162c 388 /** Same as udp_send() but with checksum
segundo 0:ac1725ba162c 389 */
segundo 0:ac1725ba162c 390 err_t
segundo 0:ac1725ba162c 391 udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p,
segundo 0:ac1725ba162c 392 u8_t have_chksum, u16_t chksum)
segundo 0:ac1725ba162c 393 {
segundo 0:ac1725ba162c 394 /* send to the packet using remote ip and port stored in the pcb */
segundo 0:ac1725ba162c 395 return udp_sendto_chksum(pcb, p, &pcb->remote_ip, pcb->remote_port,
segundo 0:ac1725ba162c 396 have_chksum, chksum);
segundo 0:ac1725ba162c 397 }
segundo 0:ac1725ba162c 398 #endif /* LWIP_CHECKSUM_ON_COPY */
segundo 0:ac1725ba162c 399
segundo 0:ac1725ba162c 400 /**
segundo 0:ac1725ba162c 401 * Send data to a specified address using UDP.
segundo 0:ac1725ba162c 402 *
segundo 0:ac1725ba162c 403 * @param pcb UDP PCB used to send the data.
segundo 0:ac1725ba162c 404 * @param p chain of pbuf's to be sent.
segundo 0:ac1725ba162c 405 * @param dst_ip Destination IP address.
segundo 0:ac1725ba162c 406 * @param dst_port Destination UDP port.
segundo 0:ac1725ba162c 407 *
segundo 0:ac1725ba162c 408 * dst_ip & dst_port are expected to be in the same byte order as in the pcb.
segundo 0:ac1725ba162c 409 *
segundo 0:ac1725ba162c 410 * If the PCB already has a remote address association, it will
segundo 0:ac1725ba162c 411 * be restored after the data is sent.
segundo 0:ac1725ba162c 412 *
segundo 0:ac1725ba162c 413 * @return lwIP error code (@see udp_send for possible error codes)
segundo 0:ac1725ba162c 414 *
segundo 0:ac1725ba162c 415 * @see udp_disconnect() udp_send()
segundo 0:ac1725ba162c 416 */
segundo 0:ac1725ba162c 417 err_t
segundo 0:ac1725ba162c 418 udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
segundo 0:ac1725ba162c 419 ip_addr_t *dst_ip, u16_t dst_port)
segundo 0:ac1725ba162c 420 {
segundo 0:ac1725ba162c 421 #if LWIP_CHECKSUM_ON_COPY
segundo 0:ac1725ba162c 422 return udp_sendto_chksum(pcb, p, dst_ip, dst_port, 0, 0);
segundo 0:ac1725ba162c 423 }
segundo 0:ac1725ba162c 424
segundo 0:ac1725ba162c 425 /** Same as udp_sendto(), but with checksum */
segundo 0:ac1725ba162c 426 err_t
segundo 0:ac1725ba162c 427 udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
segundo 0:ac1725ba162c 428 u16_t dst_port, u8_t have_chksum, u16_t chksum)
segundo 0:ac1725ba162c 429 {
segundo 0:ac1725ba162c 430 #endif /* LWIP_CHECKSUM_ON_COPY */
segundo 0:ac1725ba162c 431 struct netif *netif;
segundo 0:ac1725ba162c 432
segundo 0:ac1725ba162c 433 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n"));
segundo 0:ac1725ba162c 434
segundo 0:ac1725ba162c 435 /* find the outgoing network interface for this packet */
segundo 0:ac1725ba162c 436 #if LWIP_IGMP
segundo 0:ac1725ba162c 437 netif = ip_route((ip_addr_ismulticast(dst_ip))?(&(pcb->multicast_ip)):(dst_ip));
segundo 0:ac1725ba162c 438 #else
segundo 0:ac1725ba162c 439 netif = ip_route(dst_ip);
segundo 0:ac1725ba162c 440 #endif /* LWIP_IGMP */
segundo 0:ac1725ba162c 441
segundo 0:ac1725ba162c 442 /* no outgoing network interface could be found? */
segundo 0:ac1725ba162c 443 if (netif == NULL) {
segundo 0:ac1725ba162c 444 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
segundo 0:ac1725ba162c 445 ip4_addr1_16(dst_ip), ip4_addr2_16(dst_ip), ip4_addr3_16(dst_ip), ip4_addr4_16(dst_ip)));
segundo 0:ac1725ba162c 446 UDP_STATS_INC(udp.rterr);
segundo 0:ac1725ba162c 447 return ERR_RTE;
segundo 0:ac1725ba162c 448 }
segundo 0:ac1725ba162c 449 #if LWIP_CHECKSUM_ON_COPY
segundo 0:ac1725ba162c 450 return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum);
segundo 0:ac1725ba162c 451 #else /* LWIP_CHECKSUM_ON_COPY */
segundo 0:ac1725ba162c 452 return udp_sendto_if(pcb, p, dst_ip, dst_port, netif);
segundo 0:ac1725ba162c 453 #endif /* LWIP_CHECKSUM_ON_COPY */
segundo 0:ac1725ba162c 454 }
segundo 0:ac1725ba162c 455
segundo 0:ac1725ba162c 456 /**
segundo 0:ac1725ba162c 457 * Send data to a specified address using UDP.
segundo 0:ac1725ba162c 458 * The netif used for sending can be specified.
segundo 0:ac1725ba162c 459 *
segundo 0:ac1725ba162c 460 * This function exists mainly for DHCP, to be able to send UDP packets
segundo 0:ac1725ba162c 461 * on a netif that is still down.
segundo 0:ac1725ba162c 462 *
segundo 0:ac1725ba162c 463 * @param pcb UDP PCB used to send the data.
segundo 0:ac1725ba162c 464 * @param p chain of pbuf's to be sent.
segundo 0:ac1725ba162c 465 * @param dst_ip Destination IP address.
segundo 0:ac1725ba162c 466 * @param dst_port Destination UDP port.
segundo 0:ac1725ba162c 467 * @param netif the netif used for sending.
segundo 0:ac1725ba162c 468 *
segundo 0:ac1725ba162c 469 * dst_ip & dst_port are expected to be in the same byte order as in the pcb.
segundo 0:ac1725ba162c 470 *
segundo 0:ac1725ba162c 471 * @return lwIP error code (@see udp_send for possible error codes)
segundo 0:ac1725ba162c 472 *
segundo 0:ac1725ba162c 473 * @see udp_disconnect() udp_send()
segundo 0:ac1725ba162c 474 */
segundo 0:ac1725ba162c 475 err_t
segundo 0:ac1725ba162c 476 udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
segundo 0:ac1725ba162c 477 ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif)
segundo 0:ac1725ba162c 478 {
segundo 0:ac1725ba162c 479 #if LWIP_CHECKSUM_ON_COPY
segundo 0:ac1725ba162c 480 return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0);
segundo 0:ac1725ba162c 481 }
segundo 0:ac1725ba162c 482
segundo 0:ac1725ba162c 483 /** Same as udp_sendto_if(), but with checksum */
segundo 0:ac1725ba162c 484 err_t
segundo 0:ac1725ba162c 485 udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
segundo 0:ac1725ba162c 486 u16_t dst_port, struct netif *netif, u8_t have_chksum,
segundo 0:ac1725ba162c 487 u16_t chksum)
segundo 0:ac1725ba162c 488 {
segundo 0:ac1725ba162c 489 #endif /* LWIP_CHECKSUM_ON_COPY */
segundo 0:ac1725ba162c 490 struct udp_hdr *udphdr;
segundo 0:ac1725ba162c 491 ip_addr_t *src_ip;
segundo 0:ac1725ba162c 492 err_t err;
segundo 0:ac1725ba162c 493 struct pbuf *q; /* q will be sent down the stack */
segundo 0:ac1725ba162c 494
segundo 0:ac1725ba162c 495 #if IP_SOF_BROADCAST
segundo 0:ac1725ba162c 496 /* broadcast filter? */
segundo 0:ac1725ba162c 497 if ( ((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(dst_ip, netif) ) {
segundo 0:ac1725ba162c 498 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
segundo 0:ac1725ba162c 499 ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
segundo 0:ac1725ba162c 500 return ERR_VAL;
segundo 0:ac1725ba162c 501 }
segundo 0:ac1725ba162c 502 #endif /* IP_SOF_BROADCAST */
segundo 0:ac1725ba162c 503
segundo 0:ac1725ba162c 504 /* if the PCB is not yet bound to a port, bind it here */
segundo 0:ac1725ba162c 505 if (pcb->local_port == 0) {
segundo 0:ac1725ba162c 506 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send: not yet bound to a port, binding now\n"));
segundo 0:ac1725ba162c 507 err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
segundo 0:ac1725ba162c 508 if (err != ERR_OK) {
segundo 0:ac1725ba162c 509 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: forced port bind failed\n"));
segundo 0:ac1725ba162c 510 return err;
segundo 0:ac1725ba162c 511 }
segundo 0:ac1725ba162c 512 }
segundo 0:ac1725ba162c 513
segundo 0:ac1725ba162c 514 /* not enough space to add an UDP header to first pbuf in given p chain? */
segundo 0:ac1725ba162c 515 if (pbuf_header(p, UDP_HLEN)) {
segundo 0:ac1725ba162c 516 /* allocate header in a separate new pbuf */
segundo 0:ac1725ba162c 517 q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM);
segundo 0:ac1725ba162c 518 /* new header pbuf could not be allocated? */
segundo 0:ac1725ba162c 519 if (q == NULL) {
segundo 0:ac1725ba162c 520 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n"));
segundo 0:ac1725ba162c 521 return ERR_MEM;
segundo 0:ac1725ba162c 522 }
segundo 0:ac1725ba162c 523 /* chain header q in front of given pbuf p */
segundo 0:ac1725ba162c 524 pbuf_chain(q, p);
segundo 0:ac1725ba162c 525 /* first pbuf q points to header pbuf */
segundo 0:ac1725ba162c 526 LWIP_DEBUGF(UDP_DEBUG,
segundo 0:ac1725ba162c 527 ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
segundo 0:ac1725ba162c 528 } else {
segundo 0:ac1725ba162c 529 /* adding space for header within p succeeded */
segundo 0:ac1725ba162c 530 /* first pbuf q equals given pbuf */
segundo 0:ac1725ba162c 531 q = p;
segundo 0:ac1725ba162c 532 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p));
segundo 0:ac1725ba162c 533 }
segundo 0:ac1725ba162c 534 LWIP_ASSERT("check that first pbuf can hold struct udp_hdr",
segundo 0:ac1725ba162c 535 (q->len >= sizeof(struct udp_hdr)));
segundo 0:ac1725ba162c 536 /* q now represents the packet to be sent */
segundo 0:ac1725ba162c 537 udphdr = (struct udp_hdr *)q->payload;
segundo 0:ac1725ba162c 538 udphdr->src = htons(pcb->local_port);
segundo 0:ac1725ba162c 539 udphdr->dest = htons(dst_port);
segundo 0:ac1725ba162c 540 /* in UDP, 0 checksum means 'no checksum' */
segundo 0:ac1725ba162c 541 udphdr->chksum = 0x0000;
segundo 0:ac1725ba162c 542
segundo 0:ac1725ba162c 543 /* Multicast Loop? */
segundo 0:ac1725ba162c 544 #if LWIP_IGMP
segundo 0:ac1725ba162c 545 if (ip_addr_ismulticast(dst_ip) && ((pcb->flags & UDP_FLAGS_MULTICAST_LOOP) != 0)) {
segundo 0:ac1725ba162c 546 q->flags |= PBUF_FLAG_MCASTLOOP;
segundo 0:ac1725ba162c 547 }
segundo 0:ac1725ba162c 548 #endif /* LWIP_IGMP */
segundo 0:ac1725ba162c 549
segundo 0:ac1725ba162c 550
segundo 0:ac1725ba162c 551 /* PCB local address is IP_ANY_ADDR? */
segundo 0:ac1725ba162c 552 if (ip_addr_isany(&pcb->local_ip)) {
segundo 0:ac1725ba162c 553 /* use outgoing network interface IP address as source address */
segundo 0:ac1725ba162c 554 src_ip = &(netif->ip_addr);
segundo 0:ac1725ba162c 555 } else {
segundo 0:ac1725ba162c 556 /* check if UDP PCB local IP address is correct
segundo 0:ac1725ba162c 557 * this could be an old address if netif->ip_addr has changed */
segundo 0:ac1725ba162c 558 if (!ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {
segundo 0:ac1725ba162c 559 /* local_ip doesn't match, drop the packet */
segundo 0:ac1725ba162c 560 if (q != p) {
segundo 0:ac1725ba162c 561 /* free the header pbuf */
segundo 0:ac1725ba162c 562 pbuf_free(q);
segundo 0:ac1725ba162c 563 q = NULL;
segundo 0:ac1725ba162c 564 /* p is still referenced by the caller, and will live on */
segundo 0:ac1725ba162c 565 }
segundo 0:ac1725ba162c 566 return ERR_VAL;
segundo 0:ac1725ba162c 567 }
segundo 0:ac1725ba162c 568 /* use UDP PCB local IP address as source address */
segundo 0:ac1725ba162c 569 src_ip = &(pcb->local_ip);
segundo 0:ac1725ba162c 570 }
segundo 0:ac1725ba162c 571
segundo 0:ac1725ba162c 572 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len));
segundo 0:ac1725ba162c 573
segundo 0:ac1725ba162c 574 #if LWIP_UDPLITE
segundo 0:ac1725ba162c 575 /* UDP Lite protocol? */
segundo 0:ac1725ba162c 576 if (pcb->flags & UDP_FLAGS_UDPLITE) {
segundo 0:ac1725ba162c 577 u16_t chklen, chklen_hdr;
segundo 0:ac1725ba162c 578 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len));
segundo 0:ac1725ba162c 579 /* set UDP message length in UDP header */
segundo 0:ac1725ba162c 580 chklen_hdr = chklen = pcb->chksum_len_tx;
segundo 0:ac1725ba162c 581 if ((chklen < sizeof(struct udp_hdr)) || (chklen > q->tot_len)) {
segundo 0:ac1725ba162c 582 if (chklen != 0) {
segundo 0:ac1725ba162c 583 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE pcb->chksum_len is illegal: %"U16_F"\n", chklen));
segundo 0:ac1725ba162c 584 }
segundo 0:ac1725ba162c 585 /* For UDP-Lite, checksum length of 0 means checksum
segundo 0:ac1725ba162c 586 over the complete packet. (See RFC 3828 chap. 3.1)
segundo 0:ac1725ba162c 587 At least the UDP-Lite header must be covered by the
segundo 0:ac1725ba162c 588 checksum, therefore, if chksum_len has an illegal
segundo 0:ac1725ba162c 589 value, we generate the checksum over the complete
segundo 0:ac1725ba162c 590 packet to be safe. */
segundo 0:ac1725ba162c 591 chklen_hdr = 0;
segundo 0:ac1725ba162c 592 chklen = q->tot_len;
segundo 0:ac1725ba162c 593 }
segundo 0:ac1725ba162c 594 udphdr->len = htons(chklen_hdr);
segundo 0:ac1725ba162c 595 /* calculate checksum */
segundo 0:ac1725ba162c 596 #if CHECKSUM_GEN_UDP
segundo 0:ac1725ba162c 597 udphdr->chksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip,
segundo 0:ac1725ba162c 598 IP_PROTO_UDPLITE, q->tot_len,
segundo 0:ac1725ba162c 599 #if !LWIP_CHECKSUM_ON_COPY
segundo 0:ac1725ba162c 600 chklen);
segundo 0:ac1725ba162c 601 #else /* !LWIP_CHECKSUM_ON_COPY */
segundo 0:ac1725ba162c 602 (have_chksum ? UDP_HLEN : chklen));
segundo 0:ac1725ba162c 603 if (have_chksum) {
segundo 0:ac1725ba162c 604 u32_t acc;
segundo 0:ac1725ba162c 605 acc = udphdr->chksum + (u16_t)~(chksum);
segundo 0:ac1725ba162c 606 udphdr->chksum = FOLD_U32T(acc);
segundo 0:ac1725ba162c 607 }
segundo 0:ac1725ba162c 608 #endif /* !LWIP_CHECKSUM_ON_COPY */
segundo 0:ac1725ba162c 609
segundo 0:ac1725ba162c 610 /* chksum zero must become 0xffff, as zero means 'no checksum' */
segundo 0:ac1725ba162c 611 if (udphdr->chksum == 0x0000) {
segundo 0:ac1725ba162c 612 udphdr->chksum = 0xffff;
segundo 0:ac1725ba162c 613 }
segundo 0:ac1725ba162c 614 #endif /* CHECKSUM_GEN_UDP */
segundo 0:ac1725ba162c 615 /* output to IP */
segundo 0:ac1725ba162c 616 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDPLITE,)\n"));
segundo 0:ac1725ba162c 617 #if LWIP_NETIF_HWADDRHINT
segundo 0:ac1725ba162c 618 netif->addr_hint = &(pcb->addr_hint);
segundo 0:ac1725ba162c 619 #endif /* LWIP_NETIF_HWADDRHINT*/
segundo 0:ac1725ba162c 620 err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
segundo 0:ac1725ba162c 621 #if LWIP_NETIF_HWADDRHINT
segundo 0:ac1725ba162c 622 netif->addr_hint = NULL;
segundo 0:ac1725ba162c 623 #endif /* LWIP_NETIF_HWADDRHINT*/
segundo 0:ac1725ba162c 624 } else
segundo 0:ac1725ba162c 625 #endif /* LWIP_UDPLITE */
segundo 0:ac1725ba162c 626 { /* UDP */
segundo 0:ac1725ba162c 627 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len));
segundo 0:ac1725ba162c 628 udphdr->len = htons(q->tot_len);
segundo 0:ac1725ba162c 629 /* calculate checksum */
segundo 0:ac1725ba162c 630 #if CHECKSUM_GEN_UDP
segundo 0:ac1725ba162c 631 if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
segundo 0:ac1725ba162c 632 u16_t udpchksum;
segundo 0:ac1725ba162c 633 #if LWIP_CHECKSUM_ON_COPY
segundo 0:ac1725ba162c 634 if (have_chksum) {
segundo 0:ac1725ba162c 635 u32_t acc;
segundo 0:ac1725ba162c 636 udpchksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip, IP_PROTO_UDP,
segundo 0:ac1725ba162c 637 q->tot_len, UDP_HLEN);
segundo 0:ac1725ba162c 638 acc = udpchksum + (u16_t)~(chksum);
segundo 0:ac1725ba162c 639 udpchksum = FOLD_U32T(acc);
segundo 0:ac1725ba162c 640 } else
segundo 0:ac1725ba162c 641 #endif /* LWIP_CHECKSUM_ON_COPY */
segundo 0:ac1725ba162c 642 {
segundo 0:ac1725ba162c 643 udpchksum = inet_chksum_pseudo(q, src_ip, dst_ip, IP_PROTO_UDP, q->tot_len);
segundo 0:ac1725ba162c 644 }
segundo 0:ac1725ba162c 645
segundo 0:ac1725ba162c 646 /* chksum zero must become 0xffff, as zero means 'no checksum' */
segundo 0:ac1725ba162c 647 if (udpchksum == 0x0000) {
segundo 0:ac1725ba162c 648 udpchksum = 0xffff;
segundo 0:ac1725ba162c 649 }
segundo 0:ac1725ba162c 650 udphdr->chksum = udpchksum;
segundo 0:ac1725ba162c 651 }
segundo 0:ac1725ba162c 652 #endif /* CHECKSUM_GEN_UDP */
segundo 0:ac1725ba162c 653 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum));
segundo 0:ac1725ba162c 654 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
segundo 0:ac1725ba162c 655 /* output to IP */
segundo 0:ac1725ba162c 656 #if LWIP_NETIF_HWADDRHINT
segundo 0:ac1725ba162c 657 netif->addr_hint = &(pcb->addr_hint);
segundo 0:ac1725ba162c 658 #endif /* LWIP_NETIF_HWADDRHINT*/
segundo 0:ac1725ba162c 659 err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
segundo 0:ac1725ba162c 660 #if LWIP_NETIF_HWADDRHINT
segundo 0:ac1725ba162c 661 netif->addr_hint = NULL;
segundo 0:ac1725ba162c 662 #endif /* LWIP_NETIF_HWADDRHINT*/
segundo 0:ac1725ba162c 663 }
segundo 0:ac1725ba162c 664 /* TODO: must this be increased even if error occured? */
segundo 0:ac1725ba162c 665 snmp_inc_udpoutdatagrams();
segundo 0:ac1725ba162c 666
segundo 0:ac1725ba162c 667 /* did we chain a separate header pbuf earlier? */
segundo 0:ac1725ba162c 668 if (q != p) {
segundo 0:ac1725ba162c 669 /* free the header pbuf */
segundo 0:ac1725ba162c 670 pbuf_free(q);
segundo 0:ac1725ba162c 671 q = NULL;
segundo 0:ac1725ba162c 672 /* p is still referenced by the caller, and will live on */
segundo 0:ac1725ba162c 673 }
segundo 0:ac1725ba162c 674
segundo 0:ac1725ba162c 675 UDP_STATS_INC(udp.xmit);
segundo 0:ac1725ba162c 676 return err;
segundo 0:ac1725ba162c 677 }
segundo 0:ac1725ba162c 678
segundo 0:ac1725ba162c 679 /**
segundo 0:ac1725ba162c 680 * Bind an UDP PCB.
segundo 0:ac1725ba162c 681 *
segundo 0:ac1725ba162c 682 * @param pcb UDP PCB to be bound with a local address ipaddr and port.
segundo 0:ac1725ba162c 683 * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to
segundo 0:ac1725ba162c 684 * bind to all local interfaces.
segundo 0:ac1725ba162c 685 * @param port local UDP port to bind with. Use 0 to automatically bind
segundo 0:ac1725ba162c 686 * to a random port between UDP_LOCAL_PORT_RANGE_START and
segundo 0:ac1725ba162c 687 * UDP_LOCAL_PORT_RANGE_END.
segundo 0:ac1725ba162c 688 *
segundo 0:ac1725ba162c 689 * ipaddr & port are expected to be in the same byte order as in the pcb.
segundo 0:ac1725ba162c 690 *
segundo 0:ac1725ba162c 691 * @return lwIP error code.
segundo 0:ac1725ba162c 692 * - ERR_OK. Successful. No error occured.
segundo 0:ac1725ba162c 693 * - ERR_USE. The specified ipaddr and port are already bound to by
segundo 0:ac1725ba162c 694 * another UDP PCB.
segundo 0:ac1725ba162c 695 *
segundo 0:ac1725ba162c 696 * @see udp_disconnect()
segundo 0:ac1725ba162c 697 */
segundo 0:ac1725ba162c 698 err_t
segundo 0:ac1725ba162c 699 udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
segundo 0:ac1725ba162c 700 {
segundo 0:ac1725ba162c 701 struct udp_pcb *ipcb;
segundo 0:ac1725ba162c 702 u8_t rebind;
segundo 0:ac1725ba162c 703
segundo 0:ac1725ba162c 704 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = "));
segundo 0:ac1725ba162c 705 ip_addr_debug_print(UDP_DEBUG, ipaddr);
segundo 0:ac1725ba162c 706 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port));
segundo 0:ac1725ba162c 707
segundo 0:ac1725ba162c 708 rebind = 0;
segundo 0:ac1725ba162c 709 /* Check for double bind and rebind of the same pcb */
segundo 0:ac1725ba162c 710 for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
segundo 0:ac1725ba162c 711 /* is this UDP PCB already on active list? */
segundo 0:ac1725ba162c 712 if (pcb == ipcb) {
segundo 0:ac1725ba162c 713 /* pcb may occur at most once in active list */
segundo 0:ac1725ba162c 714 LWIP_ASSERT("rebind == 0", rebind == 0);
segundo 0:ac1725ba162c 715 /* pcb already in list, just rebind */
segundo 0:ac1725ba162c 716 rebind = 1;
segundo 0:ac1725ba162c 717 }
segundo 0:ac1725ba162c 718
segundo 0:ac1725ba162c 719 /* By default, we don't allow to bind to a port that any other udp
segundo 0:ac1725ba162c 720 PCB is alread bound to, unless *all* PCBs with that port have tha
segundo 0:ac1725ba162c 721 REUSEADDR flag set. */
segundo 0:ac1725ba162c 722 #if SO_REUSE
segundo 0:ac1725ba162c 723 else if (((pcb->so_options & SOF_REUSEADDR) == 0) &&
segundo 0:ac1725ba162c 724 ((ipcb->so_options & SOF_REUSEADDR) == 0)) {
segundo 0:ac1725ba162c 725 #else /* SO_REUSE */
segundo 0:ac1725ba162c 726 /* port matches that of PCB in list and REUSEADDR not set -> reject */
segundo 0:ac1725ba162c 727 else {
segundo 0:ac1725ba162c 728 #endif /* SO_REUSE */
segundo 0:ac1725ba162c 729 if ((ipcb->local_port == port) &&
segundo 0:ac1725ba162c 730 /* IP address matches, or one is IP_ADDR_ANY? */
segundo 0:ac1725ba162c 731 (ip_addr_isany(&(ipcb->local_ip)) ||
segundo 0:ac1725ba162c 732 ip_addr_isany(ipaddr) ||
segundo 0:ac1725ba162c 733 ip_addr_cmp(&(ipcb->local_ip), ipaddr))) {
segundo 0:ac1725ba162c 734 /* other PCB already binds to this local IP and port */
segundo 0:ac1725ba162c 735 LWIP_DEBUGF(UDP_DEBUG,
segundo 0:ac1725ba162c 736 ("udp_bind: local port %"U16_F" already bound by another pcb\n", port));
segundo 0:ac1725ba162c 737 return ERR_USE;
segundo 0:ac1725ba162c 738 }
segundo 0:ac1725ba162c 739 }
segundo 0:ac1725ba162c 740 }
segundo 0:ac1725ba162c 741
segundo 0:ac1725ba162c 742 ip_addr_set(&pcb->local_ip, ipaddr);
segundo 0:ac1725ba162c 743
segundo 0:ac1725ba162c 744 /* no port specified? */
segundo 0:ac1725ba162c 745 if (port == 0) {
segundo 0:ac1725ba162c 746 #ifndef UDP_LOCAL_PORT_RANGE_START
segundo 0:ac1725ba162c 747 #define UDP_LOCAL_PORT_RANGE_START 4096
segundo 0:ac1725ba162c 748 #define UDP_LOCAL_PORT_RANGE_END 0x7fff
segundo 0:ac1725ba162c 749 #endif
segundo 0:ac1725ba162c 750 port = UDP_LOCAL_PORT_RANGE_START;
segundo 0:ac1725ba162c 751 ipcb = udp_pcbs;
segundo 0:ac1725ba162c 752 while ((ipcb != NULL) && (port != UDP_LOCAL_PORT_RANGE_END)) {
segundo 0:ac1725ba162c 753 if (ipcb->local_port == port) {
segundo 0:ac1725ba162c 754 /* port is already used by another udp_pcb */
segundo 0:ac1725ba162c 755 port++;
segundo 0:ac1725ba162c 756 /* restart scanning all udp pcbs */
segundo 0:ac1725ba162c 757 ipcb = udp_pcbs;
segundo 0:ac1725ba162c 758 } else {
segundo 0:ac1725ba162c 759 /* go on with next udp pcb */
segundo 0:ac1725ba162c 760 ipcb = ipcb->next;
segundo 0:ac1725ba162c 761 }
segundo 0:ac1725ba162c 762 }
segundo 0:ac1725ba162c 763 if (ipcb != NULL) {
segundo 0:ac1725ba162c 764 /* no more ports available in local range */
segundo 0:ac1725ba162c 765 LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n"));
segundo 0:ac1725ba162c 766 return ERR_USE;
segundo 0:ac1725ba162c 767 }
segundo 0:ac1725ba162c 768 }
segundo 0:ac1725ba162c 769 pcb->local_port = port;
segundo 0:ac1725ba162c 770 snmp_insert_udpidx_tree(pcb);
segundo 0:ac1725ba162c 771 /* pcb not active yet? */
segundo 0:ac1725ba162c 772 if (rebind == 0) {
segundo 0:ac1725ba162c 773 /* place the PCB on the active list if not already there */
segundo 0:ac1725ba162c 774 pcb->next = udp_pcbs;
segundo 0:ac1725ba162c 775 udp_pcbs = pcb;
segundo 0:ac1725ba162c 776 }
segundo 0:ac1725ba162c 777 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
segundo 0:ac1725ba162c 778 ("udp_bind: bound to %"U16_F".%"U16_F".%"U16_F".%"U16_F", port %"U16_F"\n",
segundo 0:ac1725ba162c 779 ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
segundo 0:ac1725ba162c 780 ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip),
segundo 0:ac1725ba162c 781 pcb->local_port));
segundo 0:ac1725ba162c 782 return ERR_OK;
segundo 0:ac1725ba162c 783 }
segundo 0:ac1725ba162c 784 /**
segundo 0:ac1725ba162c 785 * Connect an UDP PCB.
segundo 0:ac1725ba162c 786 *
segundo 0:ac1725ba162c 787 * This will associate the UDP PCB with the remote address.
segundo 0:ac1725ba162c 788 *
segundo 0:ac1725ba162c 789 * @param pcb UDP PCB to be connected with remote address ipaddr and port.
segundo 0:ac1725ba162c 790 * @param ipaddr remote IP address to connect with.
segundo 0:ac1725ba162c 791 * @param port remote UDP port to connect with.
segundo 0:ac1725ba162c 792 *
segundo 0:ac1725ba162c 793 * @return lwIP error code
segundo 0:ac1725ba162c 794 *
segundo 0:ac1725ba162c 795 * ipaddr & port are expected to be in the same byte order as in the pcb.
segundo 0:ac1725ba162c 796 *
segundo 0:ac1725ba162c 797 * The udp pcb is bound to a random local port if not already bound.
segundo 0:ac1725ba162c 798 *
segundo 0:ac1725ba162c 799 * @see udp_disconnect()
segundo 0:ac1725ba162c 800 */
segundo 0:ac1725ba162c 801 err_t
segundo 0:ac1725ba162c 802 udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
segundo 0:ac1725ba162c 803 {
segundo 0:ac1725ba162c 804 struct udp_pcb *ipcb;
segundo 0:ac1725ba162c 805
segundo 0:ac1725ba162c 806 if (pcb->local_port == 0) {
segundo 0:ac1725ba162c 807 err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
segundo 0:ac1725ba162c 808 if (err != ERR_OK) {
segundo 0:ac1725ba162c 809 return err;
segundo 0:ac1725ba162c 810 }
segundo 0:ac1725ba162c 811 }
segundo 0:ac1725ba162c 812
segundo 0:ac1725ba162c 813 ip_addr_set(&pcb->remote_ip, ipaddr);
segundo 0:ac1725ba162c 814 pcb->remote_port = port;
segundo 0:ac1725ba162c 815 pcb->flags |= UDP_FLAGS_CONNECTED;
segundo 0:ac1725ba162c 816 /** TODO: this functionality belongs in upper layers */
segundo 0:ac1725ba162c 817 #ifdef LWIP_UDP_TODO
segundo 0:ac1725ba162c 818 /* Nail down local IP for netconn_addr()/getsockname() */
segundo 0:ac1725ba162c 819 if (ip_addr_isany(&pcb->local_ip) && !ip_addr_isany(&pcb->remote_ip)) {
segundo 0:ac1725ba162c 820 struct netif *netif;
segundo 0:ac1725ba162c 821
segundo 0:ac1725ba162c 822 if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
segundo 0:ac1725ba162c 823 LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.addr));
segundo 0:ac1725ba162c 824 UDP_STATS_INC(udp.rterr);
segundo 0:ac1725ba162c 825 return ERR_RTE;
segundo 0:ac1725ba162c 826 }
segundo 0:ac1725ba162c 827 /** TODO: this will bind the udp pcb locally, to the interface which
segundo 0:ac1725ba162c 828 is used to route output packets to the remote address. However, we
segundo 0:ac1725ba162c 829 might want to accept incoming packets on any interface! */
segundo 0:ac1725ba162c 830 pcb->local_ip = netif->ip_addr;
segundo 0:ac1725ba162c 831 } else if (ip_addr_isany(&pcb->remote_ip)) {
segundo 0:ac1725ba162c 832 pcb->local_ip.addr = 0;
segundo 0:ac1725ba162c 833 }
segundo 0:ac1725ba162c 834 #endif
segundo 0:ac1725ba162c 835 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
segundo 0:ac1725ba162c 836 ("udp_connect: connected to %"U16_F".%"U16_F".%"U16_F".%"U16_F",port %"U16_F"\n",
segundo 0:ac1725ba162c 837 ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
segundo 0:ac1725ba162c 838 ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip),
segundo 0:ac1725ba162c 839 pcb->local_port));
segundo 0:ac1725ba162c 840
segundo 0:ac1725ba162c 841 /* Insert UDP PCB into the list of active UDP PCBs. */
segundo 0:ac1725ba162c 842 for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
segundo 0:ac1725ba162c 843 if (pcb == ipcb) {
segundo 0:ac1725ba162c 844 /* already on the list, just return */
segundo 0:ac1725ba162c 845 return ERR_OK;
segundo 0:ac1725ba162c 846 }
segundo 0:ac1725ba162c 847 }
segundo 0:ac1725ba162c 848 /* PCB not yet on the list, add PCB now */
segundo 0:ac1725ba162c 849 pcb->next = udp_pcbs;
segundo 0:ac1725ba162c 850 udp_pcbs = pcb;
segundo 0:ac1725ba162c 851 return ERR_OK;
segundo 0:ac1725ba162c 852 }
segundo 0:ac1725ba162c 853
segundo 0:ac1725ba162c 854 /**
segundo 0:ac1725ba162c 855 * Disconnect a UDP PCB
segundo 0:ac1725ba162c 856 *
segundo 0:ac1725ba162c 857 * @param pcb the udp pcb to disconnect.
segundo 0:ac1725ba162c 858 */
segundo 0:ac1725ba162c 859 void
segundo 0:ac1725ba162c 860 udp_disconnect(struct udp_pcb *pcb)
segundo 0:ac1725ba162c 861 {
segundo 0:ac1725ba162c 862 /* reset remote address association */
segundo 0:ac1725ba162c 863 ip_addr_set_any(&pcb->remote_ip);
segundo 0:ac1725ba162c 864 pcb->remote_port = 0;
segundo 0:ac1725ba162c 865 /* mark PCB as unconnected */
segundo 0:ac1725ba162c 866 pcb->flags &= ~UDP_FLAGS_CONNECTED;
segundo 0:ac1725ba162c 867 }
segundo 0:ac1725ba162c 868
segundo 0:ac1725ba162c 869 /**
segundo 0:ac1725ba162c 870 * Set a receive callback for a UDP PCB
segundo 0:ac1725ba162c 871 *
segundo 0:ac1725ba162c 872 * This callback will be called when receiving a datagram for the pcb.
segundo 0:ac1725ba162c 873 *
segundo 0:ac1725ba162c 874 * @param pcb the pcb for wich to set the recv callback
segundo 0:ac1725ba162c 875 * @param recv function pointer of the callback function
segundo 0:ac1725ba162c 876 * @param recv_arg additional argument to pass to the callback function
segundo 0:ac1725ba162c 877 */
segundo 0:ac1725ba162c 878 void
segundo 0:ac1725ba162c 879 udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg)
segundo 0:ac1725ba162c 880 {
segundo 0:ac1725ba162c 881 /* remember recv() callback and user data */
segundo 0:ac1725ba162c 882 pcb->recv = recv;
segundo 0:ac1725ba162c 883 pcb->recv_arg = recv_arg;
segundo 0:ac1725ba162c 884 }
segundo 0:ac1725ba162c 885
segundo 0:ac1725ba162c 886 /**
segundo 0:ac1725ba162c 887 * Remove an UDP PCB.
segundo 0:ac1725ba162c 888 *
segundo 0:ac1725ba162c 889 * @param pcb UDP PCB to be removed. The PCB is removed from the list of
segundo 0:ac1725ba162c 890 * UDP PCB's and the data structure is freed from memory.
segundo 0:ac1725ba162c 891 *
segundo 0:ac1725ba162c 892 * @see udp_new()
segundo 0:ac1725ba162c 893 */
segundo 0:ac1725ba162c 894 void
segundo 0:ac1725ba162c 895 udp_remove(struct udp_pcb *pcb)
segundo 0:ac1725ba162c 896 {
segundo 0:ac1725ba162c 897 struct udp_pcb *pcb2;
segundo 0:ac1725ba162c 898
segundo 0:ac1725ba162c 899 snmp_delete_udpidx_tree(pcb);
segundo 0:ac1725ba162c 900 /* pcb to be removed is first in list? */
segundo 0:ac1725ba162c 901 if (udp_pcbs == pcb) {
segundo 0:ac1725ba162c 902 /* make list start at 2nd pcb */
segundo 0:ac1725ba162c 903 udp_pcbs = udp_pcbs->next;
segundo 0:ac1725ba162c 904 /* pcb not 1st in list */
segundo 0:ac1725ba162c 905 } else {
segundo 0:ac1725ba162c 906 for (pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
segundo 0:ac1725ba162c 907 /* find pcb in udp_pcbs list */
segundo 0:ac1725ba162c 908 if (pcb2->next != NULL && pcb2->next == pcb) {
segundo 0:ac1725ba162c 909 /* remove pcb from list */
segundo 0:ac1725ba162c 910 pcb2->next = pcb->next;
segundo 0:ac1725ba162c 911 }
segundo 0:ac1725ba162c 912 }
segundo 0:ac1725ba162c 913 }
segundo 0:ac1725ba162c 914 memp_free(MEMP_UDP_PCB, pcb);
segundo 0:ac1725ba162c 915 }
segundo 0:ac1725ba162c 916
segundo 0:ac1725ba162c 917 /**
segundo 0:ac1725ba162c 918 * Create a UDP PCB.
segundo 0:ac1725ba162c 919 *
segundo 0:ac1725ba162c 920 * @return The UDP PCB which was created. NULL if the PCB data structure
segundo 0:ac1725ba162c 921 * could not be allocated.
segundo 0:ac1725ba162c 922 *
segundo 0:ac1725ba162c 923 * @see udp_remove()
segundo 0:ac1725ba162c 924 */
segundo 0:ac1725ba162c 925 struct udp_pcb *
segundo 0:ac1725ba162c 926 udp_new(void)
segundo 0:ac1725ba162c 927 {
segundo 0:ac1725ba162c 928 struct udp_pcb *pcb;
segundo 0:ac1725ba162c 929 pcb = (struct udp_pcb *)memp_malloc(MEMP_UDP_PCB);
segundo 0:ac1725ba162c 930 /* could allocate UDP PCB? */
segundo 0:ac1725ba162c 931 if (pcb != NULL) {
segundo 0:ac1725ba162c 932 /* UDP Lite: by initializing to all zeroes, chksum_len is set to 0
segundo 0:ac1725ba162c 933 * which means checksum is generated over the whole datagram per default
segundo 0:ac1725ba162c 934 * (recommended as default by RFC 3828). */
segundo 0:ac1725ba162c 935 /* initialize PCB to all zeroes */
segundo 0:ac1725ba162c 936 memset(pcb, 0, sizeof(struct udp_pcb));
segundo 0:ac1725ba162c 937 pcb->ttl = UDP_TTL;
segundo 0:ac1725ba162c 938 }
segundo 0:ac1725ba162c 939 return pcb;
segundo 0:ac1725ba162c 940 }
segundo 0:ac1725ba162c 941
segundo 0:ac1725ba162c 942 #if UDP_DEBUG
segundo 0:ac1725ba162c 943 /**
segundo 0:ac1725ba162c 944 * Print UDP header information for debug purposes.
segundo 0:ac1725ba162c 945 *
segundo 0:ac1725ba162c 946 * @param udphdr pointer to the udp header in memory.
segundo 0:ac1725ba162c 947 */
segundo 0:ac1725ba162c 948 void
segundo 0:ac1725ba162c 949 udp_debug_print(struct udp_hdr *udphdr)
segundo 0:ac1725ba162c 950 {
segundo 0:ac1725ba162c 951 LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n"));
segundo 0:ac1725ba162c 952 LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
segundo 0:ac1725ba162c 953 LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n",
segundo 0:ac1725ba162c 954 ntohs(udphdr->src), ntohs(udphdr->dest)));
segundo 0:ac1725ba162c 955 LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
segundo 0:ac1725ba162c 956 LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n",
segundo 0:ac1725ba162c 957 ntohs(udphdr->len), ntohs(udphdr->chksum)));
segundo 0:ac1725ba162c 958 LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
segundo 0:ac1725ba162c 959 }
segundo 0:ac1725ba162c 960 #endif /* UDP_DEBUG */
segundo 0:ac1725ba162c 961
segundo 0:ac1725ba162c 962 #endif /* LWIP_UDP */