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

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

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

revision 1.31.2.4 by kieranm, Thu Aug 21 09:59:21 2003 UTC revision 1.31.2.5 by kieranm, Mon Sep 22 09:38:10 2003 UTC
# Line 247  err_t Line 247  err_t
247  tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)  tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
248  {  {
249    struct tcp_pcb *cpcb;    struct tcp_pcb *cpcb;
250    #ifdef SO_REUSE
251      int reuse_port_all_set = 1;
252    #endif /* SO_REUSE */
253    
254    if (port == 0) {    if (port == 0) {
255      port = tcp_new_port();      port = tcp_new_port();
256    }    }
257    #ifndef SO_REUSE
258    /* Check if the address already is in use. */    /* Check if the address already is in use. */
259    for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs;    for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs;
260        cpcb != NULL; cpcb = cpcb->next) {        cpcb != NULL; cpcb = cpcb->next) {
# Line 273  tcp_bind(struct tcp_pcb *pcb, struct ip_ Line 276  tcp_bind(struct tcp_pcb *pcb, struct ip_
276        }        }
277      }      }
278    }    }
279    #else /* SO_REUSE */
280      /* Search through list of PCB's in LISTEN state.
281        
282      If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP
283      or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to
284      the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid.
285      But no two PCB's bound to same local port and same local address is valid.
286      
287      If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
288      all PCB's must have the SOF_REUSEPORT option set.
289      
290      When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
291      address is already in use. */
292      for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs; cpcb != NULL; cpcb = cpcb->next) {
293        if(cpcb->local_port == port) {
294          if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
295            if(pcb->so_options & SOF_REUSEPORT) {
296              LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT set and same address.\n"));
297              reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
298            }
299            else {
300              LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT not set and same address.\n"));
301              return ERR_USE;
302            }
303          }
304          else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||
305                  (!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {
306            if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
307              LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
308              return ERR_USE;
309            }      
310            else {
311              LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));
312            }    
313          }
314        }
315      }
316    
317      /* Search through list of PCB's in a state in which they can accept or send data. Same decription as for
318         PCB's in state LISTEN applies to this PCB's regarding the options SOF_REUSEADDR and SOF_REUSEPORT. */
319      for(cpcb = tcp_active_pcbs; cpcb != NULL; cpcb = cpcb->next) {
320        if(cpcb->local_port == port) {
321          if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
322            if(pcb->so_options & SOF_REUSEPORT) {
323              LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT set and same address.\n"));
324              reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
325            }
326            else {
327              LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT not set and same address.\n"));
328              return ERR_USE;
329            }
330          }
331          else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||
332                  (!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {
333            if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
334              LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
335              return ERR_USE;
336            }  
337            else {
338              LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));
339            }        
340          }
341        }
342      }
343    
344      /* Search through list of PCB's in TIME_WAIT state. If SO_REUSEADDR is set a bound combination [IP, port}
345         can be rebound. The same applies when SOF_REUSEPORT is set.
346        
347         If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
348         all PCB's must have the SOF_REUSEPORT option set.
349        
350         When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
351         address is already in use. */
352      for(cpcb = tcp_tw_pcbs; cpcb != NULL; cpcb = cpcb->next) {
353        if(cpcb->local_port == port) {
354          if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
355            if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
356              LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT or SO_REUSEADDR not set and same address.\n"));
357              return ERR_USE;
358            }
359            else if(pcb->so_options & SOF_REUSEPORT) {
360              LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT set and same address.\n"));
361              reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
362            }
363          }
364        }
365      }
366    
367      /* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then
368         {IP, port} can't be reused. */
369      if(!reuse_port_all_set) {
370        LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: not all sockets have SO_REUSEPORT set.\n"));
371        return ERR_USE;
372      }
373    #endif /* SO_REUSE */
374    
375    if (!ip_addr_isany(ipaddr)) {    if (!ip_addr_isany(ipaddr)) {
376      pcb->local_ip = *ipaddr;      pcb->local_ip = *ipaddr;
377    }    }

Legend:
Removed from v.1.31.2.4  
changed lines
  Added in v.1.31.2.5

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