237 |
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) |
238 |
{ |
{ |
239 |
struct tcp_pcb *cpcb; |
struct tcp_pcb *cpcb; |
|
#if SO_REUSE |
|
|
int reuse_port_all_set = 1; |
|
|
#endif /* SO_REUSE */ |
|
240 |
|
|
241 |
if (port == 0) { |
if (port == 0) { |
242 |
port = tcp_new_port(); |
port = tcp_new_port(); |
243 |
} |
} |
|
#if SO_REUSE == 0 |
|
244 |
/* Check if the address already is in use. */ |
/* Check if the address already is in use. */ |
245 |
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; |
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; |
246 |
cpcb != NULL; cpcb = cpcb->next) { |
cpcb != NULL; cpcb = cpcb->next) { |
262 |
} |
} |
263 |
} |
} |
264 |
} |
} |
|
#else /* SO_REUSE */ |
|
|
/* Search through list of PCB's in LISTEN state. |
|
|
|
|
|
If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP |
|
|
or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to |
|
|
the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid. |
|
|
But no two PCB's bound to same local port and same local address is valid. |
|
|
|
|
|
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then |
|
|
all PCB's must have the SOF_REUSEPORT option set. |
|
|
|
|
|
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that |
|
|
address is already in use. */ |
|
|
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; cpcb != NULL; cpcb = cpcb->next) { |
|
|
if(cpcb->local_port == port) { |
|
|
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { |
|
|
if(pcb->so_options & SOF_REUSEPORT) { |
|
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT set and same address.\n")); |
|
|
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT)); |
|
|
} |
|
|
else { |
|
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT not set and same address.\n")); |
|
|
return ERR_USE; |
|
|
} |
|
|
} |
|
|
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) || |
|
|
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) { |
|
|
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) { |
|
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n")); |
|
|
return ERR_USE; |
|
|
} |
|
|
else { |
|
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n")); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
/* Search through list of PCB's in a state in which they can accept or send data. Same decription as for |
|
|
PCB's in state LISTEN applies to this PCB's regarding the options SOF_REUSEADDR and SOF_REUSEPORT. */ |
|
|
for(cpcb = tcp_active_pcbs; cpcb != NULL; cpcb = cpcb->next) { |
|
|
if(cpcb->local_port == port) { |
|
|
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { |
|
|
if(pcb->so_options & SOF_REUSEPORT) { |
|
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT set and same address.\n")); |
|
|
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT)); |
|
|
} |
|
|
else { |
|
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT not set and same address.\n")); |
|
|
return ERR_USE; |
|
|
} |
|
|
} |
|
|
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) || |
|
|
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) { |
|
|
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) { |
|
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n")); |
|
|
return ERR_USE; |
|
|
} |
|
|
else { |
|
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n")); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
/* Search through list of PCB's in TIME_WAIT state. If SO_REUSEADDR is set a bound combination [IP, port} |
|
|
can be rebound. The same applies when SOF_REUSEPORT is set. |
|
|
|
|
|
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then |
|
|
all PCB's must have the SOF_REUSEPORT option set. |
|
|
|
|
|
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that |
|
|
address is already in use. */ |
|
|
for(cpcb = tcp_tw_pcbs; cpcb != NULL; cpcb = cpcb->next) { |
|
|
if(cpcb->local_port == port) { |
|
|
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { |
|
|
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) { |
|
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT or SO_REUSEADDR not set and same address.\n")); |
|
|
return ERR_USE; |
|
|
} |
|
|
else if(pcb->so_options & SOF_REUSEPORT) { |
|
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT set and same address.\n")); |
|
|
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT)); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
/* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then |
|
|
{IP, port} can't be reused. */ |
|
|
if(!reuse_port_all_set) { |
|
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: not all sockets have SO_REUSEPORT set.\n")); |
|
|
return ERR_USE; |
|
|
} |
|
|
#endif /* SO_REUSE */ |
|
265 |
|
|
266 |
if (!ip_addr_isany(ipaddr)) { |
if (!ip_addr_isany(ipaddr)) { |
267 |
pcb->local_ip = *ipaddr; |
pcb->local_ip = *ipaddr; |
268 |
} |
} |
269 |
pcb->local_port = port; |
pcb->local_port = port; |
270 |
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %u\n", port)); |
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port)); |
271 |
return ERR_OK; |
return ERR_OK; |
272 |
} |
} |
273 |
#if LWIP_CALLBACK_API |
#if LWIP_CALLBACK_API |
357 |
tcp_ack_now(pcb); |
tcp_ack_now(pcb); |
358 |
} |
} |
359 |
|
|
360 |
LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %u bytes, wnd %u (%u).\n", |
LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n", |
361 |
len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd)); |
len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd)); |
362 |
} |
} |
363 |
|
|
411 |
err_t ret; |
err_t ret; |
412 |
u32_t iss; |
u32_t iss; |
413 |
|
|
414 |
LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %u\n", port)); |
LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port)); |
415 |
if (ipaddr != NULL) { |
if (ipaddr != NULL) { |
416 |
pcb->remote_ip = *ipaddr; |
pcb->remote_ip = *ipaddr; |
417 |
} else { |
} else { |
493 |
if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) { |
if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) { |
494 |
|
|
495 |
/* Time for a retransmission. */ |
/* Time for a retransmission. */ |
496 |
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %u pcb->rto %u\n", |
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"U16_F" pcb->rto %"U16_F"\n", |
497 |
pcb->rtime, pcb->rto)); |
pcb->rtime, pcb->rto)); |
498 |
|
|
499 |
/* Double retransmission time-out unless we are trying to |
/* Double retransmission time-out unless we are trying to |
508 |
pcb->ssthresh = pcb->mss * 2; |
pcb->ssthresh = pcb->mss * 2; |
509 |
} |
} |
510 |
pcb->cwnd = pcb->mss; |
pcb->cwnd = pcb->mss; |
511 |
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %u ssthresh %u\n", |
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F" ssthresh %"U16_F"\n", |
512 |
pcb->cwnd, pcb->ssthresh)); |
pcb->cwnd, pcb->ssthresh)); |
513 |
|
|
514 |
/* The following needs to be called AFTER cwnd is set to one mss - STJ */ |
/* The following needs to be called AFTER cwnd is set to one mss - STJ */ |
527 |
/* Check if KEEPALIVE should be sent */ |
/* Check if KEEPALIVE should be sent */ |
528 |
if((pcb->so_options & SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) { |
if((pcb->so_options & SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) { |
529 |
if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) { |
if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) { |
530 |
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %u.%u.%u.%u.\n", |
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n", |
531 |
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip), |
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip), |
532 |
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip))); |
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip))); |
533 |
|
|
715 |
if (cseg == NULL) { |
if (cseg == NULL) { |
716 |
return NULL; |
return NULL; |
717 |
} |
} |
718 |
memcpy((char *)cseg, (const char *)seg, sizeof(struct tcp_seg)); |
memcpy((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg)); |
719 |
pbuf_ref(cseg->p); |
pbuf_ref(cseg->p); |
720 |
return cseg; |
return cseg; |
721 |
} |
} |
759 |
} |
} |
760 |
} |
} |
761 |
if (inactive != NULL) { |
if (inactive != NULL) { |
762 |
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%ld)\n", |
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n", |
763 |
(void *)inactive, inactivity)); |
(void *)inactive, inactivity)); |
764 |
tcp_abort(inactive); |
tcp_abort(inactive); |
765 |
} |
} |
781 |
} |
} |
782 |
} |
} |
783 |
if (inactive != NULL) { |
if (inactive != NULL) { |
784 |
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%ld)\n", |
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n", |
785 |
(void *)inactive, inactivity)); |
(void *)inactive, inactivity)); |
786 |
tcp_abort(inactive); |
tcp_abort(inactive); |
787 |
} |
} |
1013 |
{ |
{ |
1014 |
LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n")); |
LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n")); |
1015 |
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); |
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); |
1016 |
LWIP_DEBUGF(TCP_DEBUG, ("| %5u | %5u | (src port, dest port)\n", |
LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", |
1017 |
ntohs(tcphdr->src), ntohs(tcphdr->dest))); |
ntohs(tcphdr->src), ntohs(tcphdr->dest))); |
1018 |
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); |
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); |
1019 |
LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (seq no)\n", |
LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n", |
1020 |
ntohl(tcphdr->seqno))); |
ntohl(tcphdr->seqno))); |
1021 |
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); |
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); |
1022 |
LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (ack no)\n", |
LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n", |
1023 |
ntohl(tcphdr->ackno))); |
ntohl(tcphdr->ackno))); |
1024 |
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); |
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); |
1025 |
LWIP_DEBUGF(TCP_DEBUG, ("| %2u | |%u%u%u%u%u%u| %5u | (hdrlen, flags (", |
LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (", |
1026 |
TCPH_HDRLEN(tcphdr), |
TCPH_HDRLEN(tcphdr), |
1027 |
TCPH_FLAGS(tcphdr) >> 5 & 1, |
TCPH_FLAGS(tcphdr) >> 5 & 1, |
1028 |
TCPH_FLAGS(tcphdr) >> 4 & 1, |
TCPH_FLAGS(tcphdr) >> 4 & 1, |
1034 |
tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); |
tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); |
1035 |
LWIP_DEBUGF(TCP_DEBUG, ("), win)\n")); |
LWIP_DEBUGF(TCP_DEBUG, ("), win)\n")); |
1036 |
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); |
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); |
1037 |
LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04x | %5u | (chksum, urgp)\n", |
LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n", |
1038 |
ntohs(tcphdr->chksum), ntohs(tcphdr->urgp))); |
ntohs(tcphdr->chksum), ntohs(tcphdr->urgp))); |
1039 |
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); |
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); |
1040 |
} |
} |
1115 |
struct tcp_pcb *pcb; |
struct tcp_pcb *pcb; |
1116 |
LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n")); |
LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n")); |
1117 |
for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { |
for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { |
1118 |
LWIP_DEBUGF(TCP_DEBUG, ("Local port %u, foreign port %u snd_nxt %lu rcv_nxt %lu ", |
LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", |
1119 |
pcb->local_port, pcb->remote_port, |
pcb->local_port, pcb->remote_port, |
1120 |
pcb->snd_nxt, pcb->rcv_nxt)); |
pcb->snd_nxt, pcb->rcv_nxt)); |
1121 |
tcp_debug_print_state(pcb->state); |
tcp_debug_print_state(pcb->state); |
1122 |
} |
} |
1123 |
LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n")); |
LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n")); |
1124 |
for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) { |
for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) { |
1125 |
LWIP_DEBUGF(TCP_DEBUG, ("Local port %u, foreign port %u snd_nxt %lu rcv_nxt %lu ", |
LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", |
1126 |
pcb->local_port, pcb->remote_port, |
pcb->local_port, pcb->remote_port, |
1127 |
pcb->snd_nxt, pcb->rcv_nxt)); |
pcb->snd_nxt, pcb->rcv_nxt)); |
1128 |
tcp_debug_print_state(pcb->state); |
tcp_debug_print_state(pcb->state); |
1129 |
} |
} |
1130 |
LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n")); |
LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n")); |
1131 |
for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { |
for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { |
1132 |
LWIP_DEBUGF(TCP_DEBUG, ("Local port %u, foreign port %u snd_nxt %lu rcv_nxt %lu ", |
LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", |
1133 |
pcb->local_port, pcb->remote_port, |
pcb->local_port, pcb->remote_port, |
1134 |
pcb->snd_nxt, pcb->rcv_nxt)); |
pcb->snd_nxt, pcb->rcv_nxt)); |
1135 |
tcp_debug_print_state(pcb->state); |
tcp_debug_print_state(pcb->state); |
1136 |
} |
} |
1137 |
} |
} |
1138 |
|
|
1139 |
int |
s16_t |
1140 |
tcp_pcbs_sane(void) |
tcp_pcbs_sane(void) |
1141 |
{ |
{ |
1142 |
struct tcp_pcb *pcb; |
struct tcp_pcb *pcb; |