SNMP agent attached to SPI slave

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers udp.c Source File

udp.c

Go to the documentation of this file.
00001 /**
00002  * @file
00003  * User Datagram Protocol module
00004  v0.1: Debug statements in udp_connect
00005  *
00006  */
00007 
00008 /*
00009  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
00010  * All rights reserved.
00011  *
00012  * Redistribution and use in source and binary forms, with or without modification,
00013  * are permitted provided that the following conditions are met:
00014  *
00015  * 1. Redistributions of source code must retain the above copyright notice,
00016  *    this list of conditions and the following disclaimer.
00017  * 2. Redistributions in binary form must reproduce the above copyright notice,
00018  *    this list of conditions and the following disclaimer in the documentation
00019  *    and/or other materials provided with the distribution.
00020  * 3. The name of the author may not be used to endorse or promote products
00021  *    derived from this software without specific prior written permission.
00022  *
00023  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
00024  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00025  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
00026  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00027  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00028  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00029  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00030  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00031  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
00032  * OF SUCH DAMAGE.
00033  *
00034  * This file is part of the lwIP TCP/IP stack.
00035  *
00036  * Author: Adam Dunkels <adam@sics.se>
00037  *
00038  */
00039 
00040 
00041 /* udp.c
00042  *
00043  * The code for the User Datagram Protocol UDP & UDPLite (RFC 3828).
00044  *
00045  */
00046 
00047 /* @todo Check the use of '(struct udp_pcb).chksum_len_rx'!
00048  */
00049 
00050 #include "lwip/opt.h"
00051 
00052 #if LWIP_UDP /* don't build if not configured for use in lwipopts.h */
00053 
00054 #include "lwip/udp.h"
00055 #include "lwip/def.h"
00056 #include "lwip/memp.h"
00057 #include "lwip/inet_chksum.h"
00058 #include "lwip/ip_addr.h"
00059 #include "lwip/netif.h"
00060 #include "lwip/icmp.h"
00061 #include "lwip/stats.h"
00062 #include "lwip/snmp.h"
00063 #include "arch/perf.h"
00064 #include "lwip/dhcp.h "
00065 
00066 #include <string.h>
00067 #include <stdio.h>
00068 
00069 /**
00070  * UDP_DEBUG: Enable debugging in UDP.
00071  */
00072 #ifndef UDP_DEBUG
00073 #define UDP_DEBUG                       LWIP_DBG_ON
00074 #endif
00075 
00076 /* The list of UDP PCBs */
00077 /* exported in udp.h (was static) */
00078 struct udp_pcb *udp_pcbs;
00079 
00080 /**
00081  * Process an incoming UDP datagram.
00082  *
00083  * Given an incoming UDP datagram (as a chain of pbufs) this function
00084  * finds a corresponding UDP PCB and hands over the pbuf to the pcbs
00085  * recv function. If no pcb is found or the datagram is incorrect, the
00086  * pbuf is freed.
00087  *
00088  * @param p pbuf to be demultiplexed to a UDP PCB.
00089  * @param inp network interface on which the datagram was received.
00090  *
00091  */
00092 void
00093 udp_input(struct pbuf *p, struct netif *inp)
00094 {
00095   struct udp_hdr *udphdr;
00096   struct udp_pcb *pcb, *prev;
00097   struct udp_pcb *uncon_pcb;
00098   struct ip_hdr *iphdr;
00099   u16_t src, dest;
00100   u8_t local_match;
00101   u8_t broadcast;
00102 
00103   PERF_START;
00104 
00105   UDP_STATS_INC(udp.recv);
00106 
00107   iphdr = (struct ip_hdr *)p->payload;
00108 
00109   /* Check minimum length (IP header + UDP header)
00110    * and move payload pointer to UDP header */
00111   if (p->tot_len < (IPH_HL(iphdr) * 4 + UDP_HLEN) || pbuf_header(p, -(s16_t)(IPH_HL(iphdr) * 4))) {
00112     /* drop short packets */
00113     LWIP_DEBUGF(UDP_DEBUG,
00114                 ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len));
00115     UDP_STATS_INC(udp.lenerr);
00116     UDP_STATS_INC(udp.drop);
00117     snmp_inc_udpinerrors();
00118     pbuf_free(p);
00119     goto end;
00120   }
00121 
00122   udphdr = (struct udp_hdr *)p->payload;
00123 
00124   /* is broadcast packet ? */
00125   broadcast = ip_addr_isbroadcast(&current_iphdr_dest, inp);
00126 
00127   LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len));
00128 //  printf("\r\nUDP_input: received datagram of length %"U16_F"\r\n", p->tot_len);
00129 
00130   /* convert src and dest ports to host byte order */
00131   src = ntohs(udphdr->src);
00132   dest = ntohs(udphdr->dest);
00133 
00134   udp_debug_print(udphdr);
00135 
00136   /* print the UDP source and destination */
00137   LWIP_DEBUGF(UDP_DEBUG,
00138               ("udp (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") <-- "
00139                "(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
00140                ip4_addr1_16(&iphdr->dest), ip4_addr2_16(&iphdr->dest),
00141                ip4_addr3_16(&iphdr->dest), ip4_addr4_16(&iphdr->dest), ntohs(udphdr->dest),
00142                ip4_addr1_16(&iphdr->src), ip4_addr2_16(&iphdr->src),
00143                ip4_addr3_16(&iphdr->src), ip4_addr4_16(&iphdr->src), ntohs(udphdr->src)));
00144 
00145 #if LWIP_DHCP
00146   pcb = NULL;
00147   /* when LWIP_DHCP is active, packets to DHCP_CLIENT_PORT may only be processed by
00148      the dhcp module, no other UDP pcb may use the local UDP port DHCP_CLIENT_PORT */
00149   if (dest == DHCP_CLIENT_PORT) {
00150     /* all packets for DHCP_CLIENT_PORT not coming from DHCP_SERVER_PORT are dropped! */
00151     if (src == DHCP_SERVER_PORT) {
00152       if ((inp->dhcp != NULL) && (inp->dhcp->pcb != NULL)) {
00153         /* accept the packe if 
00154            (- broadcast or directed to us) -> DHCP is link-layer-addressed, local ip is always ANY!
00155            - inp->dhcp->pcb->remote == ANY or iphdr->src */
00156         if ((ip_addr_isany(&inp->dhcp->pcb->remote_ip) ||
00157            ip_addr_cmp(&(inp->dhcp->pcb->remote_ip), &current_iphdr_src))) {
00158           pcb = inp->dhcp->pcb;
00159         }
00160       }
00161     }
00162   } else
00163 #endif /* LWIP_DHCP */
00164   {
00165     prev = NULL;
00166     local_match = 0;
00167     uncon_pcb = NULL;
00168     /* Iterate through the UDP pcb list for a matching pcb.
00169      * 'Perfect match' pcbs (connected to the remote port & ip address) are
00170      * preferred. If no perfect match is found, the first unconnected pcb that
00171      * matches the local port and ip address gets the datagram. */
00172     for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
00173       local_match = 0;
00174       /* print the PCB local and remote address */
00175       LWIP_DEBUGF(UDP_DEBUG,
00176                   ("pcb (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") --- "
00177                    "(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
00178                    ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
00179                    ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip), pcb->local_port,
00180                    ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),
00181                    ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip), pcb->remote_port));
00182 
00183       /* compare PCB local addr+port to UDP destination addr+port */
00184       if ((pcb->local_port == dest) &&
00185           ((!broadcast && ip_addr_isany(&pcb->local_ip)) ||
00186            ip_addr_cmp(&(pcb->local_ip), &current_iphdr_dest) ||
00187 #if LWIP_IGMP
00188            ip_addr_ismulticast(&current_iphdr_dest) ||
00189 #endif /* LWIP_IGMP */
00190 #if IP_SOF_BROADCAST_RECV
00191            (broadcast && (pcb->so_options & SOF_BROADCAST)))) {
00192 #else  /* IP_SOF_BROADCAST_RECV */
00193            (broadcast))) {
00194 #endif /* IP_SOF_BROADCAST_RECV */
00195         local_match = 1;
00196         if ((uncon_pcb == NULL) && 
00197             ((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) {
00198           /* the first unconnected matching PCB */
00199           uncon_pcb = pcb;
00200         }
00201       }
00202       /* compare PCB remote addr+port to UDP source addr+port */
00203       if ((local_match != 0) &&
00204           (pcb->remote_port == src) &&
00205           (ip_addr_isany(&pcb->remote_ip) ||
00206            ip_addr_cmp(&(pcb->remote_ip), &current_iphdr_src))) {
00207         /* the first fully matching PCB */
00208         if (prev != NULL) {
00209           /* move the pcb to the front of udp_pcbs so that is
00210              found faster next time */
00211           prev->next = pcb->next;
00212           pcb->next = udp_pcbs;
00213           udp_pcbs = pcb;
00214         } else {
00215           UDP_STATS_INC(udp.cachehit);
00216         }
00217         break;
00218       }
00219       prev = pcb;
00220     }
00221     /* no fully matching pcb found? then look for an unconnected pcb */
00222     if (pcb == NULL) {
00223       pcb = uncon_pcb;
00224     }
00225   }
00226 
00227   /* Check checksum if this is a match or if it was directed at us. */
00228   if (pcb != NULL || ip_addr_cmp(&inp->ip_addr, &current_iphdr_dest)) {
00229     LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\r\n"));
00230 #if LWIP_UDPLITE
00231     if (IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) {
00232       /* Do the UDP Lite checksum */
00233 #if CHECKSUM_CHECK_UDP
00234       u16_t chklen = ntohs(udphdr->len);
00235       if (chklen < sizeof(struct udp_hdr)) {
00236         if (chklen == 0) {
00237           /* For UDP-Lite, checksum length of 0 means checksum
00238              over the complete packet (See RFC 3828 chap. 3.1) */
00239           chklen = p->tot_len;
00240         } else {
00241           /* At least the UDP-Lite header must be covered by the
00242              checksum! (Again, see RFC 3828 chap. 3.1) */
00243           UDP_STATS_INC(udp.chkerr);
00244           UDP_STATS_INC(udp.drop);
00245           snmp_inc_udpinerrors();
00246           pbuf_free(p);
00247           goto end;
00248         }
00249       }
00250       if (inet_chksum_pseudo_partial(p, &current_iphdr_src, &current_iphdr_dest,
00251                              IP_PROTO_UDPLITE, p->tot_len, chklen) != 0) {
00252        LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00253                    ("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
00254         UDP_STATS_INC(udp.chkerr);
00255         UDP_STATS_INC(udp.drop);
00256         snmp_inc_udpinerrors();
00257         pbuf_free(p);
00258         goto end;
00259       }
00260 #endif /* CHECKSUM_CHECK_UDP */
00261     } else
00262 #endif /* LWIP_UDPLITE */
00263     {
00264 #if CHECKSUM_CHECK_UDP
00265       if (udphdr->chksum != 0) {
00266         if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
00267                                IP_PROTO_UDP, p->tot_len) != 0) {
00268           LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00269                       ("udp_input: UDP datagram discarded due to failing checksum\n"));
00270           UDP_STATS_INC(udp.chkerr);
00271           UDP_STATS_INC(udp.drop);
00272           snmp_inc_udpinerrors();
00273           pbuf_free(p);
00274           goto end;
00275         }
00276       }
00277 #endif /* CHECKSUM_CHECK_UDP */
00278     }
00279     if(pbuf_header(p, -UDP_HLEN)) {
00280       /* Can we cope with this failing? Just assert for now */
00281       LWIP_ASSERT("pbuf_header failed\n", 0);
00282       UDP_STATS_INC(udp.drop);
00283       snmp_inc_udpinerrors();
00284       pbuf_free(p);
00285       goto end;
00286     }
00287     LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: OK 1\r\n"));
00288     if (pcb != NULL) {
00289       snmp_inc_udpindatagrams();
00290 #if SO_REUSE && SO_REUSE_RXTOALL
00291       if ((broadcast || ip_addr_ismulticast(&current_iphdr_dest)) &&
00292           ((pcb->so_options & SOF_REUSEADDR) != 0)) {
00293         /* pass broadcast- or multicast packets to all multicast pcbs
00294            if SOF_REUSEADDR is set on the first match */
00295     LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: OK 2\r\n"));
00296         struct udp_pcb *mpcb;
00297         u8_t p_header_changed = 0;
00298         for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) {
00299           if (mpcb != pcb) {
00300             /* compare PCB local addr+port to UDP destination addr+port */
00301             if ((mpcb->local_port == dest) &&
00302                 ((!broadcast && ip_addr_isany(&mpcb->local_ip)) ||
00303                  ip_addr_cmp(&(mpcb->local_ip), &current_iphdr_dest) ||
00304 #if LWIP_IGMP
00305                  ip_addr_ismulticast(&current_iphdr_dest) ||
00306 #endif /* LWIP_IGMP */
00307 #if IP_SOF_BROADCAST_RECV
00308                  (broadcast && (mpcb->so_options & SOF_BROADCAST)))) {
00309 #else  /* IP_SOF_BROADCAST_RECV */
00310                  (broadcast))) {
00311 #endif /* IP_SOF_BROADCAST_RECV */
00312               /* pass a copy of the packet to all local matches */
00313               if (mpcb->recv != NULL) {
00314     LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: OK 3\r\n"));
00315                 struct pbuf *q;
00316                 /* for that, move payload to IP header again */
00317                 if (p_header_changed == 0) {
00318                   pbuf_header(p, (s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
00319                   p_header_changed = 1;
00320                 }
00321                 q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
00322                 if (q != NULL) {
00323                   err_t err = pbuf_copy(q, p);
00324                   if (err == ERR_OK) {
00325                     /* move payload to UDP data */
00326     LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: OK 4\r\n"));
00327                     pbuf_header(q, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
00328                     mpcb->recv(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src);
00329                   }
00330                 }
00331               }
00332             }
00333           }
00334         }
00335         if (p_header_changed) {
00336           /* and move payload to UDP data again */
00337           pbuf_header(p, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
00338     LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: OK 5\r\n"));
00339         }
00340       }
00341 #endif /* SO_REUSE && SO_REUSE_RXTOALL */
00342       /* callback */
00343       if (pcb->recv != NULL) {
00344         /* now the recv function is responsible for freeing p */
00345     LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: OK 6: src %d\r\n", src));
00346         pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr(), src);
00347     LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: OK 6a\r\n"));
00348       } else {
00349         /* no recv function registered? then we have to free the pbuf! */
00350         pbuf_free(p);
00351         goto end;
00352       }
00353     } else {
00354       LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: not for us.\n"));
00355 
00356 #if LWIP_ICMP
00357       /* No match was found, send ICMP destination port unreachable unless
00358          destination address was broadcast/multicast. */
00359       if (!broadcast &&
00360           !ip_addr_ismulticast(&current_iphdr_dest)) {
00361         /* move payload pointer back to ip header */
00362         pbuf_header(p, (IPH_HL(iphdr) * 4) + UDP_HLEN);
00363         LWIP_ASSERT("p->payload == iphdr", (p->payload == iphdr));
00364         icmp_dest_unreach(p, ICMP_DUR_PORT);
00365       }
00366 #endif /* LWIP_ICMP */
00367     LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: OK 7\r\n"));
00368       UDP_STATS_INC(udp.proterr);
00369       UDP_STATS_INC(udp.drop);
00370       snmp_inc_udpnoports();
00371       pbuf_free(p);
00372     }
00373   } else {
00374     pbuf_free(p);
00375     LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: OK 8\r\n"));
00376   }
00377 end:
00378   PERF_STOP("udp_input");
00379 }
00380 
00381 /**
00382  * Send data using UDP.
00383  *
00384  * @param pcb UDP PCB used to send the data.
00385  * @param p chain of pbuf's to be sent.
00386  *
00387  * The datagram will be sent to the current remote_ip & remote_port
00388  * stored in pcb. If the pcb is not bound to a port, it will
00389  * automatically be bound to a random port.
00390  *
00391  * @return lwIP error code.
00392  * - ERR_OK. Successful. No error occured.
00393  * - ERR_MEM. Out of memory.
00394  * - ERR_RTE. Could not find route to destination address.
00395  * - More errors could be returned by lower protocol layers.
00396  *
00397  * @see udp_disconnect() udp_sendto()
00398  */
00399 err_t
00400 udp_send(struct udp_pcb *pcb, struct pbuf *p)
00401 {
00402   /* send to the packet using remote ip and port stored in the pcb */
00403   return udp_sendto(pcb, p, &pcb->remote_ip, pcb->remote_port);
00404 }
00405 
00406 #if LWIP_CHECKSUM_ON_COPY
00407 /** Same as udp_send() but with checksum
00408  */
00409 err_t
00410 udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p,
00411                 u8_t have_chksum, u16_t chksum)
00412 {
00413   /* send to the packet using remote ip and port stored in the pcb */
00414   return udp_sendto_chksum(pcb, p, &pcb->remote_ip, pcb->remote_port,
00415     have_chksum, chksum);
00416 }
00417 #endif /* LWIP_CHECKSUM_ON_COPY */
00418 
00419 /**
00420  * Send data to a specified address using UDP.
00421  *
00422  * @param pcb UDP PCB used to send the data.
00423  * @param p chain of pbuf's to be sent.
00424  * @param dst_ip Destination IP address.
00425  * @param dst_port Destination UDP port.
00426  *
00427  * dst_ip & dst_port are expected to be in the same byte order as in the pcb.
00428  *
00429  * If the PCB already has a remote address association, it will
00430  * be restored after the data is sent.
00431  * 
00432  * @return lwIP error code (@see udp_send for possible error codes)
00433  *
00434  * @see udp_disconnect() udp_send()
00435  */
00436 err_t
00437 udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
00438   ip_addr_t *dst_ip, u16_t dst_port)
00439 {
00440 #if LWIP_CHECKSUM_ON_COPY
00441   return udp_sendto_chksum(pcb, p, dst_ip, dst_port, 0, 0);
00442 }
00443 
00444 /** Same as udp_sendto(), but with checksum */
00445 err_t
00446 udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
00447                   u16_t dst_port, u8_t have_chksum, u16_t chksum)
00448 {
00449 #endif /* LWIP_CHECKSUM_ON_COPY */
00450   struct netif *netif;
00451 
00452   LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n"));
00453 
00454   /* find the outgoing network interface for this packet */
00455 #if LWIP_IGMP
00456   netif = ip_route((ip_addr_ismulticast(dst_ip))?(&(pcb->multicast_ip)):(dst_ip));
00457 #else
00458   netif = ip_route(dst_ip);
00459 #endif /* LWIP_IGMP */
00460 
00461   /* no outgoing network interface could be found? */
00462   if (netif == NULL) {
00463     LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00464       ip4_addr1_16(dst_ip), ip4_addr2_16(dst_ip), ip4_addr3_16(dst_ip), ip4_addr4_16(dst_ip)));
00465     UDP_STATS_INC(udp.rterr);
00466     return ERR_RTE;
00467   }
00468 #if LWIP_CHECKSUM_ON_COPY
00469   return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum);
00470 #else /* LWIP_CHECKSUM_ON_COPY */
00471   return udp_sendto_if(pcb, p, dst_ip, dst_port, netif);
00472 #endif /* LWIP_CHECKSUM_ON_COPY */
00473 }
00474 
00475 /**
00476  * Send data to a specified address using UDP.
00477  * The netif used for sending can be specified.
00478  *
00479  * This function exists mainly for DHCP, to be able to send UDP packets
00480  * on a netif that is still down.
00481  *
00482  * @param pcb UDP PCB used to send the data.
00483  * @param p chain of pbuf's to be sent.
00484  * @param dst_ip Destination IP address.
00485  * @param dst_port Destination UDP port.
00486  * @param netif the netif used for sending.
00487  *
00488  * dst_ip & dst_port are expected to be in the same byte order as in the pcb.
00489  *
00490  * @return lwIP error code (@see udp_send for possible error codes)
00491  *
00492  * @see udp_disconnect() udp_send()
00493  */
00494 err_t
00495 udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
00496   ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif)
00497 {
00498 #if LWIP_CHECKSUM_ON_COPY
00499   return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0);
00500 }
00501 
00502 /** Same as udp_sendto_if(), but with checksum */
00503 err_t
00504 udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
00505                      u16_t dst_port, struct netif *netif, u8_t have_chksum,
00506                      u16_t chksum)
00507 {
00508 #endif /* LWIP_CHECKSUM_ON_COPY */
00509   struct udp_hdr *udphdr;
00510   ip_addr_t *src_ip;
00511   err_t err;
00512   struct pbuf *q; /* q will be sent down the stack */
00513 
00514 #if IP_SOF_BROADCAST
00515   /* broadcast filter? */
00516   if ( ((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(dst_ip, netif) ) {
00517     LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00518       ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
00519     return ERR_VAL;
00520   }
00521 #endif /* IP_SOF_BROADCAST */
00522 
00523   /* if the PCB is not yet bound to a port, bind it here */
00524   if (pcb->local_port == 0) {
00525     LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send: not yet bound to a port, binding now\n"));
00526     err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
00527 printf("\r\nudp_send: not yet bound to a port, binding to %d\r\n", pcb->local_port);
00528     if (err != ERR_OK) {
00529       LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: forced port bind failed\n"));
00530       return err;
00531     }
00532   }
00533 
00534   /* not enough space to add an UDP header to first pbuf in given p chain? */
00535   if (pbuf_header(p, UDP_HLEN)) {
00536     /* allocate header in a separate new pbuf */
00537     q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM);
00538     /* new header pbuf could not be allocated? */
00539     if (q == NULL) {
00540       LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n"));
00541       return ERR_MEM;
00542     }
00543     /* chain header q in front of given pbuf p */
00544     pbuf_chain(q, p);
00545     /* first pbuf q points to header pbuf */
00546     LWIP_DEBUGF(UDP_DEBUG,
00547                 ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
00548   } else {
00549     /* adding space for header within p succeeded */
00550     /* first pbuf q equals given pbuf */
00551     q = p;
00552     LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p));
00553   }
00554   LWIP_ASSERT("check that first pbuf can hold struct udp_hdr",
00555               (q->len >= sizeof(struct udp_hdr)));
00556   /* q now represents the packet to be sent */
00557   udphdr = (struct udp_hdr *)q->payload;
00558   udphdr->src = htons(pcb->local_port);
00559   udphdr->dest = htons(dst_port);
00560 printf("udp_sendto_if: local %d dst %d q->len %d\r\n", pcb->local_port, dst_port, q->len);
00561   /* in UDP, 0 checksum means 'no checksum' */
00562   udphdr->chksum = 0x0000; 
00563 
00564   /* Multicast Loop? */
00565 #if LWIP_IGMP
00566   if (ip_addr_ismulticast(dst_ip) && ((pcb->flags & UDP_FLAGS_MULTICAST_LOOP) != 0)) {
00567     q->flags |= PBUF_FLAG_MCASTLOOP;
00568   }
00569 #endif /* LWIP_IGMP */
00570 
00571 
00572   /* PCB local address is IP_ANY_ADDR? */
00573   if (ip_addr_isany(&pcb->local_ip)) {
00574     /* use outgoing network interface IP address as source address */
00575     src_ip = &(netif->ip_addr);
00576   } else {
00577     /* check if UDP PCB local IP address is correct
00578      * this could be an old address if netif->ip_addr has changed */
00579     if (!ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {
00580       /* local_ip doesn't match, drop the packet */
00581       if (q != p) {
00582         /* free the header pbuf */
00583         pbuf_free(q);
00584         q = NULL;
00585         /* p is still referenced by the caller, and will live on */
00586       }
00587       return ERR_VAL;
00588     }
00589     /* use UDP PCB local IP address as source address */
00590     src_ip = &(pcb->local_ip);
00591   }
00592 
00593   LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len));
00594 //printf("\r\nudp_sendto_if: sending datagram of length %"U16_F"\r\n", q->tot_len);
00595 
00596 #if LWIP_UDPLITE
00597   /* UDP Lite protocol? */
00598   if (pcb->flags & UDP_FLAGS_UDPLITE) {
00599     u16_t chklen, chklen_hdr;
00600     LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len));
00601     /* set UDP message length in UDP header */
00602     chklen_hdr = chklen = pcb->chksum_len_tx;
00603 printf("\r\nudp_sendto_if: LWIP_UDPLITE chklen %d"\r\n", chklen);
00604     if ((chklen < sizeof(struct udp_hdr)) || (chklen > q->tot_len)) {
00605       if (chklen != 0) {
00606         LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE pcb->chksum_len is illegal: %"U16_F"\n", chklen));
00607       }
00608       /* For UDP-Lite, checksum length of 0 means checksum
00609          over the complete packet. (See RFC 3828 chap. 3.1)
00610          At least the UDP-Lite header must be covered by the
00611          checksum, therefore, if chksum_len has an illegal
00612          value, we generate the checksum over the complete
00613          packet to be safe. */
00614       chklen_hdr = 0;
00615       chklen = q->tot_len;
00616     }
00617     udphdr->len = htons(chklen_hdr);
00618     /* calculate checksum */
00619 #if CHECKSUM_GEN_UDP
00620     udphdr->chksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip,
00621       IP_PROTO_UDPLITE, q->tot_len,
00622 #if !LWIP_CHECKSUM_ON_COPY
00623       chklen);
00624 #else /* !LWIP_CHECKSUM_ON_COPY */
00625       (have_chksum ? UDP_HLEN : chklen));
00626     if (have_chksum) {
00627       u32_t acc;
00628       acc = udphdr->chksum + (u16_t)~(chksum);
00629       udphdr->chksum = FOLD_U32T(acc);
00630     }
00631 #endif /* !LWIP_CHECKSUM_ON_COPY */
00632 
00633     /* chksum zero must become 0xffff, as zero means 'no checksum' */
00634     if (udphdr->chksum == 0x0000) {
00635       udphdr->chksum = 0xffff;
00636     }
00637 #endif /* CHECKSUM_GEN_UDP */
00638     /* output to IP */
00639     LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDPLITE,)\n"));
00640 #if LWIP_NETIF_HWADDRHINT
00641     netif->addr_hint = &(pcb->addr_hint);
00642 #endif /* LWIP_NETIF_HWADDRHINT*/
00643     err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
00644 #if LWIP_NETIF_HWADDRHINT
00645     netif->addr_hint = NULL;
00646 #endif /* LWIP_NETIF_HWADDRHINT*/
00647   } else
00648 #endif /* LWIP_UDPLITE */
00649   {      /* UDP */
00650     LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len));
00651 //printf("\r\nudp_sendto_if: UDP packet length %d\r\n", q->tot_len);
00652     udphdr->len = htons(q->tot_len);
00653     /* calculate checksum */
00654 #if CHECKSUM_GEN_UDP
00655     if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
00656       u16_t udpchksum;
00657 #if LWIP_CHECKSUM_ON_COPY
00658       if (have_chksum) {
00659         u32_t acc;
00660         udpchksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip, IP_PROTO_UDP,
00661           q->tot_len, UDP_HLEN);
00662         acc = udpchksum + (u16_t)~(chksum);
00663         udpchksum = FOLD_U32T(acc);
00664       } else
00665 #endif /* LWIP_CHECKSUM_ON_COPY */
00666       {
00667         udpchksum = inet_chksum_pseudo(q, src_ip, dst_ip, IP_PROTO_UDP, q->tot_len);
00668       }
00669 
00670       /* chksum zero must become 0xffff, as zero means 'no checksum' */
00671       if (udpchksum == 0x0000) {
00672         udpchksum = 0xffff;
00673       }
00674       udphdr->chksum = udpchksum;
00675     }
00676 #endif /* CHECKSUM_GEN_UDP */
00677     LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum));
00678     LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
00679     /* output to IP */
00680 #if LWIP_NETIF_HWADDRHINT
00681     netif->addr_hint = &(pcb->addr_hint);
00682 #endif /* LWIP_NETIF_HWADDRHINT*/
00683     err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
00684 printf("udp_sendto_if: ip_output_if error %d\r\n", err);
00685 #if LWIP_NETIF_HWADDRHINT
00686     netif->addr_hint = NULL;
00687 #endif /* LWIP_NETIF_HWADDRHINT*/
00688   }
00689   /* TODO: must this be increased even if error occured? */
00690   snmp_inc_udpoutdatagrams();
00691 
00692   /* did we chain a separate header pbuf earlier? */
00693   if (q != p) {
00694     /* free the header pbuf */
00695     pbuf_free(q);
00696     q = NULL;
00697     /* p is still referenced by the caller, and will live on */
00698   }
00699 
00700   UDP_STATS_INC(udp.xmit);
00701   return err;
00702 }
00703 
00704 /**
00705  * Bind an UDP PCB.
00706  *
00707  * @param pcb UDP PCB to be bound with a local address ipaddr and port.
00708  * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to
00709  * bind to all local interfaces.
00710  * @param port local UDP port to bind with. Use 0 to automatically bind
00711  * to a random port between UDP_LOCAL_PORT_RANGE_START and
00712  * UDP_LOCAL_PORT_RANGE_END.
00713  *
00714  * ipaddr & port are expected to be in the same byte order as in the pcb.
00715  *
00716  * @return lwIP error code.
00717  * - ERR_OK. Successful. No error occured.
00718  * - ERR_USE. The specified ipaddr and port are already bound to by
00719  * another UDP PCB.
00720  *
00721  * @see udp_disconnect()
00722  */
00723 err_t
00724 udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
00725 {
00726   struct udp_pcb *ipcb;
00727   u8_t rebind;
00728 
00729   LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = "));
00730   ip_addr_debug_print(UDP_DEBUG, ipaddr);
00731   LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port));
00732   printf("\r\nUDP_bind: IP Address %d.%d.%d.%d\r\n", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
00733   printf("\r\nUDP_bind: port %"U16_F"\r\n", port);
00734 
00735   rebind = 0;
00736   /* Check for double bind and rebind of the same pcb */
00737   for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
00738     /* is this UDP PCB already on active list? */
00739     if (pcb == ipcb) {
00740       /* pcb may occur at most once in active list */
00741       LWIP_ASSERT("rebind == 0", rebind == 0);
00742       /* pcb already in list, just rebind */
00743       rebind = 1;
00744     }
00745 
00746     /* By default, we don't allow to bind to a port that any other udp
00747        PCB is alread bound to, unless *all* PCBs with that port have tha
00748        REUSEADDR flag set. */
00749 #if SO_REUSE
00750     else if (((pcb->so_options & SOF_REUSEADDR) == 0) &&
00751              ((ipcb->so_options & SOF_REUSEADDR) == 0)) {
00752 #else /* SO_REUSE */
00753     /* port matches that of PCB in list and REUSEADDR not set -> reject */
00754     else {
00755 #endif /* SO_REUSE */
00756       if ((ipcb->local_port == port) &&
00757           /* IP address matches, or one is IP_ADDR_ANY? */
00758           (ip_addr_isany(&(ipcb->local_ip)) ||
00759            ip_addr_isany(ipaddr) ||
00760            ip_addr_cmp(&(ipcb->local_ip), ipaddr))) {
00761         /* other PCB already binds to this local IP and port */
00762         LWIP_DEBUGF(UDP_DEBUG,
00763                     ("udp_bind: local port %"U16_F" already bound by another pcb\n", port));
00764         return ERR_USE;
00765       }
00766     }
00767   }
00768 
00769   ip_addr_set(&pcb->local_ip, ipaddr);
00770 
00771   /* no port specified? */
00772   if (port == 0) {
00773 #ifndef UDP_LOCAL_PORT_RANGE_START
00774 #define UDP_LOCAL_PORT_RANGE_START 4096
00775 #define UDP_LOCAL_PORT_RANGE_END   0x7fff
00776 #endif
00777     port = UDP_LOCAL_PORT_RANGE_START;
00778     ipcb = udp_pcbs;
00779     while ((ipcb != NULL) && (port != UDP_LOCAL_PORT_RANGE_END)) {
00780       if (ipcb->local_port == port) {
00781         /* port is already used by another udp_pcb */
00782         port++;
00783         /* restart scanning all udp pcbs */
00784         ipcb = udp_pcbs;
00785       } else {
00786         /* go on with next udp pcb */
00787         ipcb = ipcb->next;
00788       }
00789     }
00790     if (ipcb != NULL) {
00791       /* no more ports available in local range */
00792       LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n"));
00793       return ERR_USE;
00794     }
00795   }
00796   pcb->local_port = port;
00797   snmp_insert_udpidx_tree(pcb);
00798   /* pcb not active yet? */
00799   if (rebind == 0) {
00800     /* place the PCB on the active list if not already there */
00801     pcb->next = udp_pcbs;
00802     udp_pcbs = pcb;
00803   }
00804   LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
00805               ("udp_bind: bound to %"U16_F".%"U16_F".%"U16_F".%"U16_F", port %"U16_F"\n",
00806                ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
00807                ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip),
00808                pcb->local_port));
00809   return ERR_OK;
00810 }
00811 /**
00812  * Connect an UDP PCB.
00813  *
00814  * This will associate the UDP PCB with the remote address.
00815  *
00816  * @param pcb UDP PCB to be connected with remote address ipaddr and port.
00817  * @param ipaddr remote IP address to connect with.
00818  * @param port remote UDP port to connect with.
00819  *
00820  * @return lwIP error code
00821  *
00822  * ipaddr & port are expected to be in the same byte order as in the pcb.
00823  *
00824  * The udp pcb is bound to a random local port if not already bound.
00825  *
00826  * @see udp_disconnect()
00827  */
00828 err_t
00829 udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
00830 {
00831   struct udp_pcb *ipcb;
00832 
00833   if (pcb->local_port == 0) {
00834 printf("Bind to local port: %d\r\n", pcb->local_port);  // v0.1 DEBUG
00835     err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
00836     if (err != ERR_OK) {
00837       return err;
00838     }
00839   }
00840 
00841   ip_addr_set(&pcb->remote_ip, ipaddr);
00842   pcb->remote_port = port;
00843   pcb->flags |= UDP_FLAGS_CONNECTED;
00844 printf("Remote port: %d and flags %d\r\n", pcb->remote_port, pcb->flags); // v0.1 DEBUG
00845 /** TODO: this functionality belongs in upper layers */
00846 #ifdef LWIP_UDP_TODO
00847   /* Nail down local IP for netconn_addr()/getsockname() */
00848   if (ip_addr_isany(&pcb->local_ip) && !ip_addr_isany(&pcb->remote_ip)) {
00849     struct netif *netif;
00850 
00851     if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
00852       LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.addr));
00853       UDP_STATS_INC(udp.rterr);
00854       return ERR_RTE;
00855     }
00856     /** TODO: this will bind the udp pcb locally, to the interface which
00857         is used to route output packets to the remote address. However, we
00858         might want to accept incoming packets on any interface! */
00859     pcb->local_ip = netif->ip_addr;
00860   } else if (ip_addr_isany(&pcb->remote_ip)) {
00861     pcb->local_ip.addr = 0;
00862   }
00863 #endif
00864   LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
00865               ("udp_connect: connected to %"U16_F".%"U16_F".%"U16_F".%"U16_F",port %"U16_F"\n",
00866                ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
00867                ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip),
00868                pcb->local_port));
00869 printf("udp_connect: connected to %d.%d.%d.%d, port %d\r\n",
00870                ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
00871                ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip),
00872                pcb->local_port);
00873 
00874   /* Insert UDP PCB into the list of active UDP PCBs. */
00875   for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
00876     if (pcb == ipcb) {
00877       /* already on the list, just return */
00878       return ERR_OK;
00879     }
00880   }
00881   /* PCB not yet on the list, add PCB now */
00882   pcb->next = udp_pcbs;
00883   udp_pcbs = pcb;
00884   return ERR_OK;
00885 }
00886 
00887 /**
00888  * Disconnect a UDP PCB
00889  *
00890  * @param pcb the udp pcb to disconnect.
00891  */
00892 void
00893 udp_disconnect(struct udp_pcb *pcb)
00894 {
00895   /* reset remote address association */
00896   ip_addr_set_any(&pcb->remote_ip);
00897   pcb->remote_port = 0;
00898   /* mark PCB as unconnected */
00899   pcb->flags &= ~UDP_FLAGS_CONNECTED;
00900 }
00901 
00902 /**
00903  * Set a receive callback for a UDP PCB
00904  *
00905  * This callback will be called when receiving a datagram for the pcb.
00906  *
00907  * @param pcb the pcb for wich to set the recv callback
00908  * @param recv function pointer of the callback function
00909  * @param recv_arg additional argument to pass to the callback function
00910  */
00911 void
00912 udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg)
00913 {
00914   /* remember recv() callback and user data */
00915   pcb->recv = recv;
00916   pcb->recv_arg = recv_arg;
00917 }
00918 
00919 /**
00920  * Remove an UDP PCB.
00921  *
00922  * @param pcb UDP PCB to be removed. The PCB is removed from the list of
00923  * UDP PCB's and the data structure is freed from memory.
00924  *
00925  * @see udp_new()
00926  */
00927 void
00928 udp_remove(struct udp_pcb *pcb)
00929 {
00930   struct udp_pcb *pcb2;
00931 
00932   snmp_delete_udpidx_tree(pcb);
00933   /* pcb to be removed is first in list? */
00934   if (udp_pcbs == pcb) {
00935     /* make list start at 2nd pcb */
00936     udp_pcbs = udp_pcbs->next;
00937     /* pcb not 1st in list */
00938   } else {
00939     for (pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
00940       /* find pcb in udp_pcbs list */
00941       if (pcb2->next != NULL && pcb2->next == pcb) {
00942         /* remove pcb from list */
00943         pcb2->next = pcb->next;
00944       }
00945     }
00946   }
00947   memp_free(MEMP_UDP_PCB, pcb);
00948 }
00949 
00950 /**
00951  * Create a UDP PCB.
00952  *
00953  * @return The UDP PCB which was created. NULL if the PCB data structure
00954  * could not be allocated.
00955  *
00956  * @see udp_remove()
00957  */
00958 struct udp_pcb *
00959 udp_new(void)
00960 {
00961   struct udp_pcb *pcb;
00962   pcb = (struct udp_pcb *)memp_malloc(MEMP_UDP_PCB);
00963   /* could allocate UDP PCB? */
00964   if (pcb != NULL) {
00965     /* UDP Lite: by initializing to all zeroes, chksum_len is set to 0
00966      * which means checksum is generated over the whole datagram per default
00967      * (recommended as default by RFC 3828). */
00968     /* initialize PCB to all zeroes */
00969     memset(pcb, 0, sizeof(struct udp_pcb));
00970     pcb->ttl = UDP_TTL;
00971   }
00972   return pcb;
00973 }
00974 
00975 #if UDP_DEBUG
00976 /**
00977  * Print UDP header information for debug purposes.
00978  *
00979  * @param udphdr pointer to the udp header in memory.
00980  */
00981 void
00982 udp_debug_print(struct udp_hdr *udphdr)
00983 {
00984 printf("UDP header:\r\n");
00985   LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n"));
00986   LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
00987   LWIP_DEBUGF(UDP_DEBUG, ("|     %5"U16_F"     |     %5"U16_F"     | (src port, dest port)\n",
00988                           ntohs(udphdr->src), ntohs(udphdr->dest)));
00989   LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
00990   LWIP_DEBUGF(UDP_DEBUG, ("|     %5"U16_F"     |     0x%04"X16_F"    | (len, chksum)\n",
00991                           ntohs(udphdr->len), ntohs(udphdr->chksum)));
00992   LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
00993 }
00994 #endif /* UDP_DEBUG */
00995 
00996 #endif /* LWIP_UDP */