ProjetoBB

Dependencies:   F7_Ethernet WebSocketClient mbed mcp3008

Fork of Nucleo_F746ZG_Ethernet by Dieter Graef

Committer:
DieterGraef
Date:
Sat Jun 18 10:49:12 2016 +0000
Revision:
0:f9b6112278fe
Ethernet for the NUCLEO STM32F746 Board Testprogram uses DHCP and NTP to set the clock

Who changed what in which revision?

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