/[lwip]/lwip/src/core/udp.c
ViewVC logotype

Diff of /lwip/src/core/udp.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.44.2.3 by kieranm, Thu Aug 21 09:59:21 2003 UTC revision 1.44.2.4 by kieranm, Mon Sep 22 09:38:10 2003 UTC
# Line 163  udp_input(struct pbuf *p, struct netif * Line 163  udp_input(struct pbuf *p, struct netif *
163    struct ip_hdr *iphdr;    struct ip_hdr *iphdr;
164    u16_t src, dest;    u16_t src, dest;
165    
166    #ifdef SO_REUSE
167      struct udp_pcb *pcb_temp;
168      int reuse = 0;
169      int reuse_port_1 = 0;
170      int reuse_port_2 = 0;
171    #endif /* SO_REUSE */
172      
173    PERF_START;    PERF_START;
174    
175  #ifdef UDP_STATS  #ifdef UDP_STATS
# Line 200  udp_input(struct pbuf *p, struct netif * Line 207  udp_input(struct pbuf *p, struct netif *
207      ip4_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), ntohs(udphdr->dest),      ip4_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), ntohs(udphdr->dest),
208      ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src),      ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src),
209      ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src)));      ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src)));
210    
211    #ifdef SO_REUSE
212      pcb_temp = udp_pcbs;
213      
214     again_1:
215      
216      /* Iterate through the UDP pcb list for a fully matching pcb */
217      for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
218    #else  /* SO_REUSE */
219    /* Iterate through the UDP pcb list for a fully matching pcb */    /* Iterate through the UDP pcb list for a fully matching pcb */
220    for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {    for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
221    #endif  /* SO_REUSE */
222      /* print the PCB local and remote address */      /* print the PCB local and remote address */
223      LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",      LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
224        ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),        ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
# Line 221  udp_input(struct pbuf *p, struct netif * Line 238  udp_input(struct pbuf *p, struct netif *
238         (ip_addr_isany(&pcb->local_ip) ||         (ip_addr_isany(&pcb->local_ip) ||
239         /* PCB local IP address matches UDP destination IP address? */         /* PCB local IP address matches UDP destination IP address? */
240          ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {          ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
241    #ifdef SO_REUSE
242          if(pcb->so_options & SOF_REUSEPORT) {
243            if(reuse) {
244              /* We processed one PCB already */
245              LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
246            } else {
247              /* First PCB with this address */
248              LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
249              reuse = 1;
250            }
251            
252            reuse_port_1 = 1;
253            p->ref++;
254            LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
255          } else {
256            if(reuse) {
257              /* We processed one PCB already */
258              LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
259            }
260          }
261    #endif /* SO_REUSE */
262        break;        break;
263      }      }
264    }    }
# Line 228  udp_input(struct pbuf *p, struct netif * Line 266  udp_input(struct pbuf *p, struct netif *
266    if (pcb == NULL) {    if (pcb == NULL) {
267      /* Iterate through the UDP PCB list for a pcb that matches      /* Iterate through the UDP PCB list for a pcb that matches
268         the local address. */         the local address. */
269    
270    #ifdef SO_REUSE
271        pcb_temp = udp_pcbs;
272        
273      again_2:
274    
275        for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
276    #else  /* SO_REUSE */
277      for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {      for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
278    #endif  /* SO_REUSE */
279        LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",        LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
280          ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),          ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
281          ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,          ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
# Line 242  udp_input(struct pbuf *p, struct netif * Line 289  udp_input(struct pbuf *p, struct netif *
289          (ip_addr_isany(&pcb->local_ip) ||          (ip_addr_isany(&pcb->local_ip) ||
290          /* ...matching interface address? */          /* ...matching interface address? */
291          ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {          ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
292           break;  #ifdef SO_REUSE
293            if(pcb->so_options & SOF_REUSEPORT) {
294              if(reuse) {
295                /* We processed one PCB already */
296                LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
297              } else {
298                /* First PCB with this address */
299                LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
300                reuse = 1;
301              }
302              
303              reuse_port_2 = 1;
304              p->ref++;
305              LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
306            } else {
307              if(reuse) {
308                /* We processed one PCB already */
309                LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
310              }
311            }
312    #endif /* SO_REUSE */
313            break;
314        }        }
315      }      }
316    }    }
# Line 291  udp_input(struct pbuf *p, struct netif * Line 359  udp_input(struct pbuf *p, struct netif *
359      if (pcb != NULL) {      if (pcb != NULL) {
360        snmp_inc_udpindatagrams();        snmp_inc_udpindatagrams();
361        pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);        pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
362    #ifdef SO_REUSE
363          /* First socket should receive now */
364          if(reuse_port_1 || reuse_port_2) {
365            /* We want to search on next socket after receiving */
366            pcb_temp = pcb->next;
367            
368            if(reuse_port_1) {
369              /* We are searching connected sockets */
370              reuse_port_1 = 0;
371              reuse_port_2 = 0;
372              goto again_1;
373            } else {
374              /* We are searching unconnected sockets */
375              reuse_port_1 = 0;
376              reuse_port_2 = 0;
377              goto again_2;
378            }
379          }
380    #endif /* SO_REUSE */
381      } else {      } else {
382    #ifdef SO_REUSE
383          if(reuse) {
384            LWIP_DEBUGF(UDP_DEBUG, ("udp_input: freeing PBUF with reference counter set to %i\n", p->ref));
385            pbuf_free(p);
386            goto end;
387          }
388    #endif /* SO_REUSE */
389        LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: not for us.\n"));        LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: not for us.\n"));
390    
391        /* No match was found, send ICMP destination port unreachable unless        /* No match was found, send ICMP destination port unreachable unless
# Line 457  udp_bind(struct udp_pcb *pcb, struct ip_ Line 551  udp_bind(struct udp_pcb *pcb, struct ip_
551  {  {
552    struct udp_pcb *ipcb;    struct udp_pcb *ipcb;
553    u8_t rebind;    u8_t rebind;
554    #ifdef SO_REUSE
555      int reuse_port_all_set = 1;
556    #endif /* SO_REUSE */
557    LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_bind(ipaddr = "));    LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_bind(ipaddr = "));
558    ip_addr_debug_print(UDP_DEBUG, ipaddr);    ip_addr_debug_print(UDP_DEBUG, ipaddr);
559    LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, (", port = %u)\n", port));    LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, (", port = %u)\n", port));
560    
561    rebind = 0;    rebind = 0;
562    /* Check for double bind and rebind of the same pcb */    /* Check for double bind and rebind of the same pcb */
563    for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {    for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
# Line 470  udp_bind(struct udp_pcb *pcb, struct ip_ Line 568  udp_bind(struct udp_pcb *pcb, struct ip_
568        /* pcb already in list, just rebind */        /* pcb already in list, just rebind */
569        rebind = 1;        rebind = 1;
570      }      }
571    
572    #ifndef SO_REUSE
573  /* this code does not allow upper layer to share a UDP port for  /* this code does not allow upper layer to share a UDP port for
574     listening to broadcast or multicast traffic (See SO_REUSE_ADDR and     listening to broadcast or multicast traffic (See SO_REUSE_ADDR and
575     SO_REUSE_PORT under *BSD). TODO: See where it fits instead, OR     SO_REUSE_PORT under *BSD). TODO: See where it fits instead, OR
# Line 486  udp_bind(struct udp_pcb *pcb, struct ip_ Line 586  udp_bind(struct udp_pcb *pcb, struct ip_
586        return ERR_USE;        return ERR_USE;
587      }      }
588  #endif  #endif
589    
590    #else /* SO_REUSE */
591          /* Search through list of PCB's.
592            
593          If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP
594          or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to
595          the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid.
596          But no two PCB's bound to same local port and same local address is valid.
597          
598          If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
599          all PCB's must have the SOF_REUSEPORT option set.
600          
601          When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
602          address is already in use. */
603        else if (ipcb->local_port == port) {
604          if(ip_addr_cmp(&(ipcb->local_ip), ipaddr)) {
605            if(pcb->so_options & SOF_REUSEPORT) {
606              LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT set and same address.\n"));
607              reuse_port_all_set = (reuse_port_all_set && (ipcb->so_options & SOF_REUSEPORT));
608            }
609            else {
610              LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT not set and same address.\n"));
611              return ERR_USE;
612            }
613          }
614          else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(ipcb->local_ip))) ||
615                  (!ip_addr_isany(ipaddr) && ip_addr_isany(&(ipcb->local_ip)))) {
616            if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
617              LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
618              return ERR_USE;
619            }          
620          }
621        }
622    #endif /* SO_REUSE */
623    
624      }
625    
626    #ifdef SO_REUSE
627      /* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then
628         {IP, port} can't be reused. */
629      if(!reuse_port_all_set) {
630        LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: not all sockets have SO_REUSEPORT set.\n"));
631        return ERR_USE;
632    }    }
633    /* bind local address */  #endif /* SO_REUSE */
634    
635    ip_addr_set(&pcb->local_ip, ipaddr);    ip_addr_set(&pcb->local_ip, ipaddr);
636    /* no port specified? */    /* no port specified? */
637    if (port == 0) {    if (port == 0) {

Legend:
Removed from v.1.44.2.3  
changed lines
  Added in v.1.44.2.4

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26