/[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.14 by likewise, Mon Jan 27 12:35:16 2003 UTC revision 1.15 by likewise, Mon Jan 27 13:58:45 2003 UTC
# Line 91  udp_lookup(struct ip_hdr *iphdr, struct Line 91  udp_lookup(struct ip_hdr *iphdr, struct
91    struct udp_pcb *pcb;    struct udp_pcb *pcb;
92    struct udp_hdr *udphdr;    struct udp_hdr *udphdr;
93    u16_t src, dest;    u16_t src, dest;
94      
95    PERF_START;      PERF_START;
96      
97    udphdr = (struct udp_hdr *)(u8_t *)iphdr + IPH_HL(iphdr) * 4;      udphdr = (struct udp_hdr *)(u8_t *)iphdr + IPH_HL(iphdr) * 4;
98    
99    src = NTOHS(udphdr->src);    src = NTOHS(udphdr->src);
100    dest = NTOHS(udphdr->dest);    dest = NTOHS(udphdr->dest);
101      
102    pcb = pcb_cache;      pcb = pcb_cache;
103    if(pcb != NULL &&    if(pcb != NULL &&
104       pcb->remote_port == src &&      pcb->remote_port == src &&
105       pcb->local_port == dest &&      pcb->local_port == dest &&
106       (ip_addr_isany(&pcb->remote_ip) ||      (ip_addr_isany(&pcb->remote_ip) ||
107        ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&      ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
108       (ip_addr_isany(&pcb->local_ip) ||      (ip_addr_isany(&pcb->local_ip) ||
109        ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {      ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
110      return 1;      return 1;
111    } else {      }
112      else {  
113      for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {      for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
114        if(pcb->remote_port == src &&        if(pcb->remote_port == src &&
115           pcb->local_port == dest &&           pcb->local_port == dest &&
# Line 117  udp_lookup(struct ip_hdr *iphdr, struct Line 118  udp_lookup(struct ip_hdr *iphdr, struct
118           (ip_addr_isany(&pcb->local_ip) ||           (ip_addr_isany(&pcb->local_ip) ||
119            ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {            ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
120          pcb_cache = pcb;          pcb_cache = pcb;
121          break;          break;
122        }          }
123      }      }
124    
125      if(pcb == NULL) {      if(pcb == NULL) {
# Line 130  udp_lookup(struct ip_hdr *iphdr, struct Line 131  udp_lookup(struct ip_hdr *iphdr, struct
131             (ip_addr_isany(&pcb->local_ip) ||             (ip_addr_isany(&pcb->local_ip) ||
132              ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {              ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
133            break;            break;
134          }            }
135        }        }
136      }      }
137    }    }
138    
139    PERF_STOP("udp_lookup");    PERF_STOP("udp_lookup");
140      
141    if(pcb != NULL) {    if(pcb != NULL) {
142      return 1;      return 1;
143    } else {      }
144      else {  
145      return 1;      return 1;
146    }    }
147  }  }
148  #endif /* LWIP_DEBUG */  #endif /* LWIP_DEBUG */
149  /*-----------------------------------------------------------------------------------*/  /**
150     * Process an incoming UDP datagram.
151     *
152     * Given an incoming UDP datagram (as a chain of pbufs) this function
153     * finds a corresponding UDP PCB and
154     *
155     * @param pbuf pbuf to be demultiplexed to a UDP PCB.
156     * @param netif network interface on which the datagram was received.
157     *
158     * @see udp_disconnect()
159     */
160  void  void
161  udp_input(struct pbuf *p, struct netif *inp)  udp_input(struct pbuf *p, struct netif *inp)
162  {  {
# Line 299  udp_input(struct pbuf *p, struct netif * Line 311  udp_input(struct pbuf *p, struct netif *
311            
312    PERF_STOP("udp_input");    PERF_STOP("udp_input");
313  }  }
314  /*-----------------------------------------------------------------------------------*/  /**
315     * Send data using UDP.
316     *
317     * @param pcb UDP PCB used to send the data.
318     * @param pbuf chain of pbuf's to be sent.
319     *
320     * @return lwIP error code.
321     * - ERR_OK. Successful. No error occured.
322     * - ERR_MEM. Out of memory.
323     * - ERR_USE. The specified ipaddr and port are already bound to by
324     * another UDP PCB.
325     *
326     * @see udp_disconnect()
327     */
328  err_t  err_t
329  udp_send(struct udp_pcb *pcb, struct pbuf *p)  udp_send(struct udp_pcb *pcb, struct pbuf *p)
330  {  {
# Line 309  udp_send(struct udp_pcb *pcb, struct pbu Line 334  udp_send(struct udp_pcb *pcb, struct pbu
334    err_t err;    err_t err;
335    struct pbuf *hdr;    struct pbuf *hdr;
336    
   
337    DEBUGF(UDP_DEBUG, ("udp_send"));    DEBUGF(UDP_DEBUG, ("udp_send"));
338    /* hdr will point to the UDP header pbuf if an extra header pbuf has    /* hdr will point to the UDP header pbuf if an extra header pbuf has
339       to be allocated. */       to be allocated. */
340    hdr = NULL;    hdr = NULL;
341        
342      /* succeeding in adding an UDP header to first given pbuf in chain? */
343    if(pbuf_header(p, UDP_HLEN)) {    if(pbuf_header(p, UDP_HLEN)) {
344        /* allocate header in new pbuf */
345      hdr = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM);      hdr = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM);
346        /* new header pbuf could not be allocated? */
347      if(hdr == NULL) {      if(hdr == NULL) {
348        return ERR_MEM;        return ERR_MEM;
349      }      }
350        /* chain header in front of given pbuf */
351      pbuf_chain(hdr, p);      pbuf_chain(hdr, p);
352        /* have p point to header pbuf */
353      p = hdr;      p = hdr;
354    }    }
355    DEBUGF(UDP_DEBUG, ("udp_send: got pbuf"));    DEBUGF(UDP_DEBUG, ("udp_send: got pbuf"));
# Line 337  udp_send(struct udp_pcb *pcb, struct pbu Line 366  udp_send(struct udp_pcb *pcb, struct pbu
366  #endif /* UDP_STATS */  #endif /* UDP_STATS */
367      return ERR_RTE;      return ERR_RTE;
368    }    }
369      /* using IP_ANY_ADDR? */
370    if(ip_addr_isany(&pcb->local_ip)) {    if(ip_addr_isany(&pcb->local_ip)) {
371        /* use network interface IP address as source address */
372      src_ip = &(netif->ip_addr);      src_ip = &(netif->ip_addr);
373    } else {    } else {
374        /* use UDP PCB local IP address as source address */
375      src_ip = &(pcb->local_ip);      src_ip = &(pcb->local_ip);
376    }    }
377        
378    DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %d\n", p->tot_len));    DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %d\n", p->tot_len));
379        
380      /* UDP Lite protocol? */
381    if(pcb->flags & UDP_FLAGS_UDPLITE) {    if(pcb->flags & UDP_FLAGS_UDPLITE) {
382      DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %u", p->tot_len));      DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %u", p->tot_len));
383      /* set UDP message length in UDP header */      /* set UDP message length in UDP header */
# Line 353  udp_send(struct udp_pcb *pcb, struct pbu Line 385  udp_send(struct udp_pcb *pcb, struct pbu
385      /* calculate checksum */      /* calculate checksum */
386      udphdr->chksum = inet_chksum_pseudo(p, src_ip, &(pcb->remote_ip),      udphdr->chksum = inet_chksum_pseudo(p, src_ip, &(pcb->remote_ip),
387                                          IP_PROTO_UDP, pcb->chksum_len);                                          IP_PROTO_UDP, pcb->chksum_len);
388      if(udphdr->chksum == 0x0000) {      /* chksum zero must become 0xffff, as zero means 'no checksum' */
389        udphdr->chksum = 0xffff;      if(udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
390      }      /* output to IP */
391      err = ip_output_if(p, src_ip, &pcb->remote_ip, UDP_TTL, IP_PROTO_UDPLITE, netif);          err = ip_output_if(p, src_ip, &pcb->remote_ip, UDP_TTL, IP_PROTO_UDPLITE, netif);    
392  #if LWIP_SNMP > 0  #if LWIP_SNMP > 0
393      snmp_inc_udpoutdatagrams();      snmp_inc_udpoutdatagrams();
# Line 365  udp_send(struct udp_pcb *pcb, struct pbu Line 397  udp_send(struct udp_pcb *pcb, struct pbu
397      udphdr->len = htons(p->tot_len);      udphdr->len = htons(p->tot_len);
398      /* calculate checksum */      /* calculate checksum */
399      if((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {      if((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
400        udphdr->chksum = inet_chksum_pseudo(p, src_ip, &pcb->remote_ip,        udphdr->chksum = inet_chksum_pseudo(p, src_ip, &pcb->remote_ip, IP_PROTO_UDP, p->tot_len);
401                                            IP_PROTO_UDP, p->tot_len);        /* chksum zero must become 0xffff, as zero means 'no checksum' */
402        if(udphdr->chksum == 0x0000) {        if(udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
         udphdr->chksum = 0xffff;  
       }  
403      }      }
404      DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum %x", udphdr->chksum));      DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum %x", udphdr->chksum));
405  #if LWIP_SNMP > 0  #if LWIP_SNMP > 0
406      snmp_inc_udpoutdatagrams();      snmp_inc_udpoutdatagrams();
407  #endif  #endif
408      DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if(,,,,IP_PROTO_UDP,)"));      DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if(,,,,IP_PROTO_UDP,)"));
409        /* output to IP */
410      err = ip_output_if(p, src_ip, &pcb->remote_ip, UDP_TTL, IP_PROTO_UDP, netif);          err = ip_output_if(p, src_ip, &pcb->remote_ip, UDP_TTL, IP_PROTO_UDP, netif);    
411    }    }
412      /* dechain and free the header pbuf */
413    if(hdr != NULL) {    if(hdr != NULL) {
414      pbuf_dechain(hdr);      pbuf_dechain(hdr);
415      pbuf_free(hdr);      pbuf_free(hdr);
# Line 389  udp_send(struct udp_pcb *pcb, struct pbu Line 420  udp_send(struct udp_pcb *pcb, struct pbu
420  #endif /* UDP_STATS */  #endif /* UDP_STATS */
421    return err;    return err;
422  }  }
423  /*-----------------------------------------------------------------------------------*/  /**
424     * Bind an UDP PCB.
425     *
426     * @param pcb UDP PCB to be bound with a local address ipaddr and port.
427     * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to
428     * bind to all local interfaces.
429     * @param port local UDP port to bind with.
430     *
431     * @return lwIP error code.
432     * - ERR_OK. Successful. No error occured.
433     * - ERR_USE. The specified ipaddr and port are already bound to by
434     * another UDP PCB.
435     *
436     * @see udp_disconnect()
437     */
438  err_t  err_t
439  udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)  udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
440  {  {
441    struct udp_pcb *ipcb;    struct udp_pcb *ipcb;
442    u8_t rebind = 0;    u8_t rebind = 0;
443      
444    /* Check for double bind and rebind of the same pcb */    /* Check for double bind and rebind of the same pcb */
445    for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {    for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
446        /* is this UDP PCB already on active list? */
447      if (pcb == ipcb) {      if (pcb == ipcb) {
448           rebind = 1;              rebind = 1;
449           break;      }
450      }  else            /* port matches that of PCB in list? */
451      if (ipcb->local_port == port) {      if ((ipcb->local_port == port) &&
452        if(ip_addr_isany(&(ipcb->local_ip)) ||         /* IP address matches, or one is IP_ADDR_ANY? */
453           ip_addr_isany(ipaddr) ||        (ip_addr_isany(&(ipcb->local_ip)) ||
454           ip_addr_cmp(&(ipcb->local_ip), ipaddr)) {               ip_addr_isany(ipaddr) ||
455            /* Port/IP pair already bound */               ip_addr_cmp(&(ipcb->local_ip), ipaddr))) {
456            return ERR_USE;                  /* other PCB already binds to this local IP and port */
457        }        return ERR_USE;      
458      }      }
459    }    }
460        /* bind local address */
461    ip_addr_set(&pcb->local_ip, ipaddr);    ip_addr_set(&pcb->local_ip, ipaddr);
462    pcb->local_port = port;    pcb->local_port = port;
463      
464    /* We need to place the PCB on the list if not already there. */    /* We need to place the PCB on the list if not already there. */
465    if (rebind == 0) {    if (rebind == 0) {
466      pcb->next = udp_pcbs;      pcb->next = udp_pcbs;
# Line 424  udp_bind(struct udp_pcb *pcb, struct ip_ Line 470  udp_bind(struct udp_pcb *pcb, struct ip_
470    DEBUGF(UDP_DEBUG, ("udp_bind: bound to port %d\n", port));    DEBUGF(UDP_DEBUG, ("udp_bind: bound to port %d\n", port));
471    return ERR_OK;    return ERR_OK;
472  }  }
473  /*-----------------------------------------------------------------------------------*/  /**
474     * Connect an UDP PCB.
475     *
476     * @param pcb UDP PCB to be connected with remote address ipaddr and port.
477     * @param ipaddr remote IP address to connect with.
478     * @param port remote UDP port to connect with.
479     *
480     * @return lwIP error code
481     *
482     * @see udp_disconnect()
483     */
484  err_t  err_t
485  udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)  udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
486  {  {
# Line 436  udp_connect(struct udp_pcb *pcb, struct Line 492  udp_connect(struct udp_pcb *pcb, struct
492    /* Insert UDP PCB into the list of active UDP PCBs. */    /* Insert UDP PCB into the list of active UDP PCBs. */
493    for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {    for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
494      if(pcb == ipcb) {      if(pcb == ipcb) {
495        /* Already on the list, just return. */        /* already on the list, just return */
496        return ERR_OK;        return ERR_OK;
497      }      }
498    }    }
499    /* We need to place the PCB on the list. */    /* PCB not yet on the list, add PCB now */
500    pcb->next = udp_pcbs;    pcb->next = udp_pcbs;
501    udp_pcbs = pcb;    udp_pcbs = pcb;
502    return ERR_OK;    return ERR_OK;
# Line 458  udp_recv(struct udp_pcb *pcb, Line 514  udp_recv(struct udp_pcb *pcb,
514                         struct ip_addr *addr, u16_t port),                         struct ip_addr *addr, u16_t port),
515           void *recv_arg)           void *recv_arg)
516  {  {
517      /* remember recv() callback and user data */
518    pcb->recv = recv;    pcb->recv = recv;
519    pcb->recv_arg = recv_arg;    pcb->recv_arg = recv_arg;
520  }  }
521  /*-----------------------------------------------------------------------------------*/  /**
522     * Remove an UDP PCB.
523     *
524     * @param pcb UDP PCB to be removed. The PCB is removed from the list of
525     * UDP PCB's and the data structure is freed from memory.
526     *
527     * @see udp_new()
528     */
529  void  void
530  udp_remove(struct udp_pcb *pcb)  udp_remove(struct udp_pcb *pcb)
531  {  {
532    struct udp_pcb *pcb2;    struct udp_pcb *pcb2;
533        /* pcb to be removed is first in list? */
534    if(udp_pcbs == pcb) {    if (udp_pcbs == pcb) {
535        /* make list start at 2nd pcb */
536      udp_pcbs = udp_pcbs->next;      udp_pcbs = udp_pcbs->next;
537      /* pcb not 1st in list */
538    } else for(pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {    } else for(pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
539        /* find pcb in udp_pcbs list */
540      if(pcb2->next != NULL && pcb2->next == pcb) {      if(pcb2->next != NULL && pcb2->next == pcb) {
541          /* remove pcb from list */
542        pcb2->next = pcb->next;        pcb2->next = pcb->next;
543      }      }
544    }    }
   
545    memp_free(MEMP_UDP_PCB, pcb);      memp_free(MEMP_UDP_PCB, pcb);  
546  }  }
547  /*-----------------------------------------------------------------------------------*/  /**
548     * Create a UDP PCB.
549     *
550     * @return The UDP PCB which was created. NULL if the PCB data structure
551     * could not be allocated.
552     *
553     * @see udp_remove()
554     */
555  struct udp_pcb *  struct udp_pcb *
556  udp_new(void) {  udp_new(void) {
557    struct udp_pcb *pcb;    struct udp_pcb *pcb;
558    pcb = memp_malloc(MEMP_UDP_PCB);    pcb = memp_malloc(MEMP_UDP_PCB);
559      /* could allocate UDP PCB? */
560    if(pcb != NULL) {    if(pcb != NULL) {
561      pcb->flags = 0;      /* initialize PCB to all zeroes */
562      memset(pcb, 0, sizeof(struct udp_pcb));      memset(pcb, 0, sizeof(struct udp_pcb));
     return pcb;  
563    }    }
564    return NULL;    return pcb;
   
565  }  }
566  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
567  #if UDP_DEBUG  #if UDP_DEBUG

Legend:
Removed from v.1.14  
changed lines
  Added in v.1.15

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