440 |
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) |
441 |
{ |
{ |
442 |
struct udp_pcb *ipcb; |
struct udp_pcb *ipcb; |
443 |
u8_t rebind = 0; |
u8_t rebind; |
444 |
|
|
445 |
|
rebind = 0; |
446 |
/* Check for double bind and rebind of the same pcb */ |
/* Check for double bind and rebind of the same pcb */ |
447 |
for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { |
for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { |
448 |
/* is this UDP PCB already on active list? */ |
/* is this UDP PCB already on active list? */ |
449 |
if (pcb == ipcb) { |
if (pcb == ipcb) { |
450 |
|
/* TODO: add assert that rebind is 0 here (pcb may |
451 |
|
occur at most once in list) */ |
452 |
rebind = 1; |
rebind = 1; |
453 |
} |
} |
454 |
|
/* this code does not allow upper layer to share a UDP port for |
455 |
|
listening to broadcast or multicast traffic (See SO_REUSE_ADDR and |
456 |
|
SO_REUSE_PORT under *BSD). TODO: See where it fits instead, OR |
457 |
|
combine with implementation of UDP PCB flags. Leon Woestenberg. */ |
458 |
|
#if 0 |
459 |
/* port matches that of PCB in list? */ |
/* port matches that of PCB in list? */ |
460 |
if ((ipcb->local_port == port) && |
else if ((ipcb->local_port == port) && |
461 |
/* IP address matches, or one is IP_ADDR_ANY? */ |
/* IP address matches, or one is IP_ADDR_ANY? */ |
462 |
(ip_addr_isany(&(ipcb->local_ip)) || |
(ip_addr_isany(&(ipcb->local_ip)) || |
463 |
ip_addr_isany(ipaddr) || |
ip_addr_isany(ipaddr) || |
464 |
ip_addr_cmp(&(ipcb->local_ip), ipaddr))) { |
ip_addr_cmp(&(ipcb->local_ip), ipaddr))) { |
465 |
/* other PCB already binds to this local IP and port */ |
/* other PCB already binds to this local IP and port */ |
466 |
|
DEBUGF(UDP_DEBUG, ("udp_bind: local port %u already bound by another pcb\n", port)); |
467 |
return ERR_USE; |
return ERR_USE; |
468 |
} |
} |
469 |
|
#endif |
470 |
} |
} |
471 |
/* bind local address */ |
/* bind local address */ |
472 |
ip_addr_set(&pcb->local_ip, ipaddr); |
ip_addr_set(&pcb->local_ip, ipaddr); |
473 |
if(port == 0) { |
if (port == 0) { |
474 |
#ifndef UDP_LOCAL_PORT_RANGE_START |
#ifndef UDP_LOCAL_PORT_RANGE_START |
475 |
#define UDP_LOCAL_PORT_RANGE_START 4096 |
#define UDP_LOCAL_PORT_RANGE_START 4096 |
476 |
#define UDP_LOCAL_PORT_RANGE_END 0x7fff |
#define UDP_LOCAL_PORT_RANGE_END 0x7fff |
477 |
#endif |
#endif |
478 |
port = UDP_LOCAL_PORT_RANGE_START; |
port = UDP_LOCAL_PORT_RANGE_START; |
479 |
ipcb = udp_pcbs; |
ipcb = udp_pcbs; |
480 |
while((ipcb != NULL) && (port != UDP_LOCAL_PORT_RANGE_END)) { |
while((ipcb != NULL) && (port != UDP_LOCAL_PORT_RANGE_END)) { |
481 |
if(ipcb->local_port == port) { |
if(ipcb->local_port == port) { |
482 |
port++; |
port++; |
483 |
ipcb = udp_pcbs; |
ipcb = udp_pcbs; |
484 |
} else |
} else |
485 |
ipcb = ipcb->next; |
ipcb = ipcb->next; |
486 |
} |
} |
487 |
if(ipcb) /* no more ports available in local range */ |
if(ipcb) /* no more ports available in local range */ |
488 |
return ERR_USE; |
DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n")); |
489 |
|
return ERR_USE; |
490 |
} |
} |
491 |
pcb->local_port = port; |
pcb->local_port = port; |
|
|
|
492 |
/* 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. */ |
493 |
if (rebind == 0) { |
if (rebind == 0) { |
494 |
pcb->next = udp_pcbs; |
pcb->next = udp_pcbs; |
495 |
udp_pcbs = pcb; |
udp_pcbs = pcb; |
496 |
} |
} |
|
|
|
497 |
DEBUGF(UDP_DEBUG, ("udp_bind: bound to port %u\n", port)); |
DEBUGF(UDP_DEBUG, ("udp_bind: bound to port %u\n", port)); |
498 |
return ERR_OK; |
return ERR_OK; |
499 |
} |
} |
500 |
/** |
/** |
501 |
* Connect an UDP PCB. |
* Connect an UDP PCB. |
502 |
* |
* |
503 |
|
* This will associate the UDP PCB with the remote address. |
504 |
|
* |
505 |
* @param pcb UDP PCB to be connected with remote address ipaddr and port. |
* @param pcb UDP PCB to be connected with remote address ipaddr and port. |
506 |
* @param ipaddr remote IP address to connect with. |
* @param ipaddr remote IP address to connect with. |
507 |
* @param port remote UDP port to connect with. |
* @param port remote UDP port to connect with. |
523 |
|
|
524 |
ip_addr_set(&pcb->remote_ip, ipaddr); |
ip_addr_set(&pcb->remote_ip, ipaddr); |
525 |
pcb->remote_port = port; |
pcb->remote_port = port; |
526 |
#if 1 |
#if 0 |
527 |
pcb->flags |= UDP_FLAGS_CONNECTED; |
pcb->flags |= UDP_FLAGS_CONNECTED; |
528 |
/* Nail down local IP for netconn_addr()/getsockname() */ |
/* Nail down local IP for netconn_addr()/getsockname() */ |
529 |
if(ip_addr_isany(&pcb->local_ip) && !ip_addr_isany(&pcb->remote_ip)) { |
if(ip_addr_isany(&pcb->local_ip) && !ip_addr_isany(&pcb->remote_ip)) { |
536 |
#endif /* UDP_STATS */ |
#endif /* UDP_STATS */ |
537 |
return ERR_RTE; |
return ERR_RTE; |
538 |
} |
} |
539 |
|
/** TODO: this will bind the udp pcb locally, to the interface which |
540 |
|
is used to route output packets to the remote address. However, we |
541 |
|
might want to accept incoming packets on any interface! */ |
542 |
pcb->local_ip = netif->ip_addr; |
pcb->local_ip = netif->ip_addr; |
543 |
} else if(ip_addr_isany(&pcb->remote_ip)) { |
} else if(ip_addr_isany(&pcb->remote_ip)) { |
544 |
pcb->local_ip.addr = 0; |
pcb->local_ip.addr = 0; |