ReactOS  0.4.15-dev-5462-g4d0d22a
tcp_in.c
Go to the documentation of this file.
1 
12 /*
13  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
14  * All rights reserved.
15  *
16  * Redistribution and use in source and binary forms, with or without modification,
17  * are permitted provided that the following conditions are met:
18  *
19  * 1. Redistributions of source code must retain the above copyright notice,
20  * this list of conditions and the following disclaimer.
21  * 2. Redistributions in binary form must reproduce the above copyright notice,
22  * this list of conditions and the following disclaimer in the documentation
23  * and/or other materials provided with the distribution.
24  * 3. The name of the author may not be used to endorse or promote products
25  * derived from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
28  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
29  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
30  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
32  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
35  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
36  * OF SUCH DAMAGE.
37  *
38  * This file is part of the lwIP TCP/IP stack.
39  *
40  * Author: Adam Dunkels <adam@sics.se>
41  *
42  */
43 
44 #include "lwip/opt.h"
45 
46 #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
47 
48 #include "lwip/tcp_impl.h"
49 #include "lwip/def.h"
50 #include "lwip/ip_addr.h"
51 #include "lwip/netif.h"
52 #include "lwip/mem.h"
53 #include "lwip/memp.h"
54 #include "lwip/inet_chksum.h"
55 #include "lwip/stats.h"
56 #include "lwip/snmp.h"
57 #include "arch/perf.h"
58 
59 /* These variables are global to all functions involved in the input
60  processing of TCP segments. They are set by the tcp_input()
61  function. */
62 static struct tcp_seg inseg;
63 static struct tcp_hdr *tcphdr;
64 static struct ip_hdr *iphdr;
65 static u32_t seqno, ackno;
66 static u8_t flags;
67 static u16_t tcplen;
68 
69 static u8_t recv_flags;
70 static struct pbuf *recv_data;
71 
72 struct tcp_pcb *tcp_input_pcb;
73 
74 /* Forward declarations. */
75 static err_t tcp_process(struct tcp_pcb *pcb);
76 static void tcp_receive(struct tcp_pcb *pcb);
77 static void tcp_parseopt(struct tcp_pcb *pcb);
78 
79 static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
80 static err_t tcp_timewait_input(struct tcp_pcb *pcb);
81 
91 void
92 tcp_input(struct pbuf *p, struct netif *inp)
93 {
94  struct tcp_pcb *pcb, *prev;
95  struct tcp_pcb_listen *lpcb;
96 #if SO_REUSE
97  struct tcp_pcb *lpcb_prev = NULL;
98  struct tcp_pcb_listen *lpcb_any = NULL;
99 #endif /* SO_REUSE */
100  u8_t hdrlen;
101  err_t err;
102 
103  PERF_START;
104 
105  TCP_STATS_INC(tcp.recv);
107 
108  iphdr = (struct ip_hdr *)p->payload;
109  tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
110 
111 #if TCP_INPUT_DEBUG
112  tcp_debug_print(tcphdr);
113 #endif
114 
115  /* remove header from payload */
116  if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) {
117  /* drop short packets */
118  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len));
119  TCP_STATS_INC(tcp.lenerr);
120  goto dropped;
121  }
122 
123  /* Don't even process incoming broadcasts/multicasts. */
126  TCP_STATS_INC(tcp.proterr);
127  goto dropped;
128  }
129 
130 #if CHECKSUM_CHECK_TCP
131  /* Verify TCP checksum. */
133  IP_PROTO_TCP, p->tot_len) != 0) {
134  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n",
136  IP_PROTO_TCP, p->tot_len)));
137 #if TCP_DEBUG
138  tcp_debug_print(tcphdr);
139 #endif /* TCP_DEBUG */
140  TCP_STATS_INC(tcp.chkerr);
141  goto dropped;
142  }
143 #endif
144 
145  /* Move the payload pointer in the pbuf so that it points to the
146  TCP data instead of the TCP header. */
147  hdrlen = TCPH_HDRLEN(tcphdr);
148  if(pbuf_header(p, -(hdrlen * 4))){
149  /* drop short packets */
150  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n"));
151  TCP_STATS_INC(tcp.lenerr);
152  goto dropped;
153  }
154 
155  /* Convert fields in TCP header to host byte order. */
156  tcphdr->src = ntohs(tcphdr->src);
157  tcphdr->dest = ntohs(tcphdr->dest);
158  seqno = tcphdr->seqno = ntohl(tcphdr->seqno);
159  ackno = tcphdr->ackno = ntohl(tcphdr->ackno);
160  tcphdr->wnd = ntohs(tcphdr->wnd);
161 
162  flags = TCPH_FLAGS(tcphdr);
163  tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0);
164 
165  /* Demultiplex an incoming segment. First, we check if it is destined
166  for an active connection. */
167  prev = NULL;
168 
169 
170  for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
171  LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
172  LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
173  LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
174  if (pcb->remote_port == tcphdr->src &&
175  pcb->local_port == tcphdr->dest &&
176  ip_addr_cmp(&(pcb->remote_ip), &current_iphdr_src) &&
177  ip_addr_cmp(&(pcb->local_ip), &current_iphdr_dest)) {
178 
179  /* Move this PCB to the front of the list so that subsequent
180  lookups will be faster (we exploit locality in TCP segment
181  arrivals). */
182  LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb);
183  if (prev != NULL) {
184  prev->next = pcb->next;
185  pcb->next = tcp_active_pcbs;
186  tcp_active_pcbs = pcb;
187  }
188  LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);
189  break;
190  }
191  prev = pcb;
192  }
193 
194  if (pcb == NULL) {
195  /* If it did not go to an active connection, we check the connections
196  in the TIME-WAIT state. */
197  for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
198  LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
199  if (pcb->remote_port == tcphdr->src &&
200  pcb->local_port == tcphdr->dest &&
201  ip_addr_cmp(&(pcb->remote_ip), &current_iphdr_src) &&
202  ip_addr_cmp(&(pcb->local_ip), &current_iphdr_dest)) {
203  /* We don't really care enough to move this PCB to the front
204  of the list since we are not very likely to receive that
205  many segments for connections in TIME-WAIT. */
206  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n"));
207  tcp_timewait_input(pcb);
208  pbuf_free(p);
209  return;
210  }
211  }
212 
213  /* Finally, if we still did not get a match, we check all PCBs that
214  are LISTENing for incoming connections. */
215  prev = NULL;
216  for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
217  if (lpcb->local_port == tcphdr->dest) {
218 #if SO_REUSE
219  if (ip_addr_cmp(&(lpcb->local_ip), &current_iphdr_dest)) {
220  /* found an exact match */
221  break;
222  } else if(ip_addr_isany(&(lpcb->local_ip))) {
223  /* found an ANY-match */
224  lpcb_any = lpcb;
225  lpcb_prev = prev;
226  }
227 #else /* SO_REUSE */
228  if (ip_addr_cmp(&(lpcb->local_ip), &current_iphdr_dest) ||
229  ip_addr_isany(&(lpcb->local_ip))) {
230  /* found a match */
231  break;
232  }
233 #endif /* SO_REUSE */
234  }
235  prev = (struct tcp_pcb *)lpcb;
236  }
237 #if SO_REUSE
238  /* first try specific local IP */
239  if (lpcb == NULL) {
240  /* only pass to ANY if no specific local IP has been found */
241  lpcb = lpcb_any;
242  prev = lpcb_prev;
243  }
244 #endif /* SO_REUSE */
245  if (lpcb != NULL) {
246  /* Move this PCB to the front of the list so that subsequent
247  lookups will be faster (we exploit locality in TCP segment
248  arrivals). */
249  if (prev != NULL) {
250  ((struct tcp_pcb_listen *)prev)->next = lpcb->next;
251  /* our successor is the remainder of the listening list */
252  lpcb->next = tcp_listen_pcbs.listen_pcbs;
253  /* put this listening pcb at the head of the listening list */
254  tcp_listen_pcbs.listen_pcbs = lpcb;
255  }
256 
257  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
258  tcp_listen_input(lpcb);
259  pbuf_free(p);
260  return;
261  }
262  }
263 
264 #if TCP_INPUT_DEBUG
265  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags "));
266  tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
267  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n"));
268 #endif /* TCP_INPUT_DEBUG */
269 
270 
271  if (pcb != NULL) {
272  /* The incoming segment belongs to a connection. */
273 #if TCP_INPUT_DEBUG
274 #if TCP_DEBUG
275  tcp_debug_print_state(pcb->state);
276 #endif /* TCP_DEBUG */
277 #endif /* TCP_INPUT_DEBUG */
278 
279  /* Set up a tcp_seg structure. */
280  inseg.next = NULL;
281  inseg.len = p->tot_len;
282  inseg.p = p;
283  inseg.tcphdr = tcphdr;
284 
285  recv_data = NULL;
286  recv_flags = 0;
287 
288  if (flags & TCP_PSH) {
289  p->flags |= PBUF_FLAG_PUSH;
290  }
291 
292  /* If there is data which was previously "refused" by upper layer */
293  if (pcb->refused_data != NULL) {
294  if ((tcp_process_refused_data(pcb) == ERR_ABRT) ||
295  ((pcb->refused_data != NULL) && (tcplen > 0))) {
296  /* pcb has been aborted or refused data is still refused and the new
297  segment contains data */
298  TCP_STATS_INC(tcp.drop);
300  goto aborted;
301  }
302  }
303  tcp_input_pcb = pcb;
304  err = tcp_process(pcb);
305  /* A return value of ERR_ABRT means that tcp_abort() was called
306  and that the pcb has been freed. If so, we don't do anything. */
307  if (err != ERR_ABRT) {
308  if (recv_flags & TF_RESET) {
309  /* TF_RESET means that the connection was reset by the other
310  end. We then call the error callback to inform the
311  application that the connection is dead before we
312  deallocate the PCB. */
313  TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST);
314  tcp_pcb_remove(&tcp_active_pcbs, pcb);
315  memp_free(MEMP_TCP_PCB, pcb);
316  } else if (recv_flags & TF_CLOSED) {
317  /* The connection has been closed and we will deallocate the
318  PCB. */
319  if (!(pcb->flags & TF_RXCLOSED)) {
320  /* Connection closed although the application has only shut down the
321  tx side: call the PCB's err callback and indicate the closure to
322  ensure the application doesn't continue using the PCB. */
323  TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_CLSD);
324  }
325  tcp_pcb_remove(&tcp_active_pcbs, pcb);
326  memp_free(MEMP_TCP_PCB, pcb);
327  } else {
328  err = ERR_OK;
329  /* If the application has registered a "sent" function to be
330  called when new send buffer space is available, we call it
331  now. */
332  if (pcb->acked > 0) {
333  TCP_EVENT_SENT(pcb, pcb->acked, err);
334  if (err == ERR_ABRT) {
335  goto aborted;
336  }
337  }
338 
339  if (recv_data != NULL) {
340  LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL);
341  if (pcb->flags & TF_RXCLOSED) {
342  /* received data although already closed -> abort (send RST) to
343  notify the remote host that not all data has been processed */
344  pbuf_free(recv_data);
345  tcp_abort(pcb);
346  goto aborted;
347  }
348 
349  /* Notify application that data has been received. */
350  TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);
351  if (err == ERR_ABRT) {
352  goto aborted;
353  }
354 
355  /* If the upper layer can't receive this data, store it */
356  if (err != ERR_OK) {
357  pcb->refused_data = recv_data;
358  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n"));
359  }
360  }
361 
362  /* If a FIN segment was received, we call the callback
363  function with a NULL buffer to indicate EOF. */
364  if (recv_flags & TF_GOT_FIN) {
365  if (pcb->refused_data != NULL) {
366  /* Delay this if we have refused data. */
367  pcb->refused_data->flags |= PBUF_FLAG_TCP_FIN;
368  } else {
369  /* correct rcv_wnd as the application won't call tcp_recved()
370  for the FIN's seqno */
371  if (pcb->rcv_wnd != TCP_WND) {
372  pcb->rcv_wnd++;
373  }
374  TCP_EVENT_CLOSED(pcb, err);
375  if (err == ERR_ABRT) {
376  goto aborted;
377  }
378  }
379  }
380 
381  tcp_input_pcb = NULL;
382  /* Try to send something out. */
383  tcp_output(pcb);
384 #if TCP_INPUT_DEBUG
385 #if TCP_DEBUG
386  tcp_debug_print_state(pcb->state);
387 #endif /* TCP_DEBUG */
388 #endif /* TCP_INPUT_DEBUG */
389  }
390  }
391  /* Jump target if pcb has been aborted in a callback (by calling tcp_abort()).
392  Below this line, 'pcb' may not be dereferenced! */
393 aborted:
394  tcp_input_pcb = NULL;
395  recv_data = NULL;
396 
397  /* give up our reference to inseg.p */
398  if (inseg.p != NULL)
399  {
400  pbuf_free(inseg.p);
401  inseg.p = NULL;
402  }
403  } else {
404 
405  /* If no matching PCB was found, send a TCP RST (reset) to the
406  sender. */
407  LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
408  if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
409  TCP_STATS_INC(tcp.proterr);
410  TCP_STATS_INC(tcp.drop);
411  tcp_rst(ackno, seqno + tcplen,
413  tcphdr->dest, tcphdr->src);
414  }
415  pbuf_free(p);
416  }
417 
418  LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
419  PERF_STOP("tcp_input");
420  return;
421 dropped:
422  TCP_STATS_INC(tcp.drop);
424  pbuf_free(p);
425 }
426 
439 static err_t
440 tcp_listen_input(struct tcp_pcb_listen *pcb)
441 {
442  struct tcp_pcb *npcb;
443  err_t rc;
444 
445  if (flags & TCP_RST) {
446  /* An incoming RST should be ignored. Return. */
447  return ERR_OK;
448  }
449 
450  /* In the LISTEN state, we check for incoming SYN segments,
451  creates a new PCB, and responds with a SYN|ACK. */
452  if (flags & TCP_ACK) {
453  /* For incoming segments with the ACK flag set, respond with a
454  RST. */
455  LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
456  tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(),
458  } else if (flags & TCP_SYN) {
459  LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
460 #if TCP_LISTEN_BACKLOG
461  if (pcb->accepts_pending >= pcb->backlog) {
462  LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest));
463  return ERR_ABRT;
464  }
465 #endif /* TCP_LISTEN_BACKLOG */
466  npcb = tcp_alloc(pcb->prio);
467  /* If a new PCB could not be created (probably due to lack of memory),
468  we don't do anything, but rely on the sender will retransmit the
469  SYN at a time when we have more memory available. */
470  if (npcb == NULL) {
471  LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
472  TCP_STATS_INC(tcp.memerr);
473  return ERR_MEM;
474  }
475 #if TCP_LISTEN_BACKLOG
476  pcb->accepts_pending++;
477 #endif /* TCP_LISTEN_BACKLOG */
478  /* Set up the new PCB. */
479  ip_addr_copy(npcb->local_ip, current_iphdr_dest);
480  npcb->local_port = pcb->local_port;
481  ip_addr_copy(npcb->remote_ip, current_iphdr_src);
482  npcb->remote_port = tcphdr->src;
483  npcb->state = SYN_RCVD;
484  npcb->rcv_nxt = seqno + 1;
485  npcb->rcv_ann_right_edge = npcb->rcv_nxt;
486  npcb->snd_wnd = tcphdr->wnd;
487  npcb->snd_wnd_max = tcphdr->wnd;
488  npcb->ssthresh = npcb->snd_wnd;
489  npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
490  npcb->callback_arg = pcb->callback_arg;
491 #if LWIP_CALLBACK_API
492  npcb->accept = pcb->accept;
493 #endif /* LWIP_CALLBACK_API */
494  /* inherit socket options */
495  npcb->so_options = pcb->so_options & SOF_INHERITED;
496  /* Register the new PCB so that we can begin receiving segments
497  for it. */
498  TCP_REG_ACTIVE(npcb);
499 
500  /* Parse any options in the SYN. */
501  tcp_parseopt(npcb);
502 #if TCP_CALCULATE_EFF_SEND_MSS
503  npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip));
504 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
505 
507 
508  /* Send a SYN|ACK together with the MSS option. */
509  rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK);
510  if (rc != ERR_OK) {
511  tcp_abandon(npcb, 0);
512  return rc;
513  }
514  return tcp_output(npcb);
515  }
516  return ERR_OK;
517 }
518 
528 static err_t
529 tcp_timewait_input(struct tcp_pcb *pcb)
530 {
531  /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */
532  /* RFC 793 3.9 Event Processing - Segment Arrives:
533  * - first check sequence number - we skip that one in TIME_WAIT (always
534  * acceptable since we only send ACKs)
535  * - second check the RST bit (... return) */
536  if (flags & TCP_RST) {
537  return ERR_OK;
538  }
539  /* - fourth, check the SYN bit, */
540  if (flags & TCP_SYN) {
541  /* If an incoming segment is not acceptable, an acknowledgment
542  should be sent in reply */
543  if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
544  /* If the SYN is in the window it is an error, send a reset */
545  tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
546  tcphdr->dest, tcphdr->src);
547  return ERR_OK;
548  }
549  } else if (flags & TCP_FIN) {
550  /* - eighth, check the FIN bit: Remain in the TIME-WAIT state.
551  Restart the 2 MSL time-wait timeout.*/
552  pcb->tmr = tcp_ticks;
553  }
554 
555  if ((tcplen > 0)) {
556  /* Acknowledge data, FIN or out-of-window SYN */
557  pcb->flags |= TF_ACK_NOW;
558  return tcp_output(pcb);
559  }
560  return ERR_OK;
561 }
562 
574 static err_t
575 tcp_process(struct tcp_pcb *pcb)
576 {
577  struct tcp_seg *rseg;
578  u8_t acceptable = 0;
579  err_t err;
580 
581  err = ERR_OK;
582 
583  /* Process incoming RST segments. */
584  if (flags & TCP_RST) {
585  /* First, determine if the reset is acceptable. */
586  if (pcb->state == SYN_SENT) {
587  if (ackno == pcb->snd_nxt) {
588  acceptable = 1;
589  }
590  } else {
591  if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
592  pcb->rcv_nxt+pcb->rcv_wnd)) {
593  acceptable = 1;
594  }
595  }
596 
597  if (acceptable) {
598  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n"));
599  LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED);
600  recv_flags |= TF_RESET;
601  pcb->flags &= ~TF_ACK_DELAY;
602  return ERR_RST;
603  } else {
604  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
605  seqno, pcb->rcv_nxt));
606  LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
607  seqno, pcb->rcv_nxt));
608  return ERR_OK;
609  }
610  }
611 
612  if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) {
613  /* Cope with new connection attempt after remote end crashed */
614  tcp_ack_now(pcb);
615  return ERR_OK;
616  }
617 
618  if ((pcb->flags & TF_RXCLOSED) == 0) {
619  /* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */
620  pcb->tmr = tcp_ticks;
621  }
622  pcb->keep_cnt_sent = 0;
623 
624  tcp_parseopt(pcb);
625 
626  /* Do different things depending on the TCP state. */
627  switch (pcb->state) {
628  case SYN_SENT:
629  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno,
630  pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));
631  /* received SYN ACK with expected sequence number? */
632  if ((flags & TCP_ACK) && (flags & TCP_SYN)
633  && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
634  pcb->snd_buf++;
635  pcb->rcv_nxt = seqno + 1;
636  pcb->rcv_ann_right_edge = pcb->rcv_nxt;
637  pcb->lastack = ackno;
638  pcb->snd_wnd = tcphdr->wnd;
639  pcb->snd_wnd_max = tcphdr->wnd;
640  pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
641  pcb->state = ESTABLISHED;
642 
643 #if TCP_CALCULATE_EFF_SEND_MSS
644  pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip));
645 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
646 
647  /* Set ssthresh again after changing pcb->mss (already set in tcp_connect
648  * but for the default value of pcb->mss) */
649  pcb->ssthresh = pcb->mss * 10;
650 
651  pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
652  LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0));
653  --pcb->snd_queuelen;
654  LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen));
655  rseg = pcb->unacked;
656  pcb->unacked = rseg->next;
657  tcp_seg_free(rseg);
658 
659  /* If there's nothing left to acknowledge, stop the retransmit
660  timer, otherwise reset it to start again */
661  if(pcb->unacked == NULL)
662  pcb->rtime = -1;
663  else {
664  pcb->rtime = 0;
665  pcb->nrtx = 0;
666  }
667 
668  /* Call the user specified function to call when sucessfully
669  * connected. */
670  TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
671  if (err == ERR_ABRT) {
672  return ERR_ABRT;
673  }
674  tcp_ack_now(pcb);
675  }
676  /* received ACK? possibly a half-open connection */
677  else if (flags & TCP_ACK) {
678  /* send a RST to bring the other side in a non-synchronized state. */
679  tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
680  tcphdr->dest, tcphdr->src);
681  }
682  break;
683  case SYN_RCVD:
684  if (flags & TCP_ACK) {
685  /* expected ACK number? */
686  if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
687  u16_t old_cwnd;
688  pcb->state = ESTABLISHED;
689  LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
690 #if LWIP_CALLBACK_API
691  LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);
692 #endif
693  /* Call the accept function. */
694  TCP_EVENT_ACCEPT(pcb, ERR_OK, err);
695  if (err != ERR_OK) {
696  /* If the accept function returns with an error, we abort
697  * the connection. */
698  /* Already aborted? */
699  if (err != ERR_ABRT) {
700  tcp_abort(pcb);
701  }
702  return ERR_ABRT;
703  }
704  old_cwnd = pcb->cwnd;
705  /* If there was any data contained within this ACK,
706  * we'd better pass it on to the application as well. */
707  tcp_receive(pcb);
708 
709  /* Prevent ACK for SYN to generate a sent event */
710  if (pcb->acked != 0) {
711  pcb->acked--;
712  }
713 
714  pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
715 
716  if (recv_flags & TF_GOT_FIN) {
717  tcp_ack_now(pcb);
718  pcb->state = CLOSE_WAIT;
719  }
720  } else {
721  /* incorrect ACK number, send RST */
722  tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
723  tcphdr->dest, tcphdr->src);
724  }
725  } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
726  /* Looks like another copy of the SYN - retransmit our SYN-ACK */
727  tcp_rexmit(pcb);
728  }
729  break;
730  case CLOSE_WAIT:
731  /* FALLTHROUGH */
732  case ESTABLISHED:
733  tcp_receive(pcb);
734  if (recv_flags & TF_GOT_FIN) { /* passive close */
735  tcp_ack_now(pcb);
736  pcb->state = CLOSE_WAIT;
737  }
738  break;
739  case FIN_WAIT_1:
740  tcp_receive(pcb);
741  if (recv_flags & TF_GOT_FIN) {
742  if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
744  ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
745  tcp_ack_now(pcb);
746  tcp_pcb_purge(pcb);
747  TCP_RMV_ACTIVE(pcb);
748  pcb->state = TIME_WAIT;
749  TCP_REG(&tcp_tw_pcbs, pcb);
750  } else {
751  tcp_ack_now(pcb);
752  pcb->state = CLOSING;
753  }
754  } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
755  pcb->state = FIN_WAIT_2;
756  }
757  break;
758  case FIN_WAIT_2:
759  tcp_receive(pcb);
760  if (recv_flags & TF_GOT_FIN) {
761  LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
762  tcp_ack_now(pcb);
763  tcp_pcb_purge(pcb);
764  TCP_RMV_ACTIVE(pcb);
765  pcb->state = TIME_WAIT;
766  TCP_REG(&tcp_tw_pcbs, pcb);
767  }
768  break;
769  case CLOSING:
770  tcp_receive(pcb);
771  if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
772  LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
773  tcp_pcb_purge(pcb);
774  TCP_RMV_ACTIVE(pcb);
775  pcb->state = TIME_WAIT;
776  TCP_REG(&tcp_tw_pcbs, pcb);
777  }
778  break;
779  case LAST_ACK:
780  tcp_receive(pcb);
781  if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
782  LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
783  /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
784  recv_flags |= TF_CLOSED;
785  }
786  break;
787  default:
788  break;
789  }
790  return ERR_OK;
791 }
792 
793 #if TCP_QUEUE_OOSEQ
794 
799 static void
800 tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next)
801 {
802  struct tcp_seg *old_seg;
803 
804  if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
805  /* received segment overlaps all following segments */
806  tcp_segs_free(next);
807  next = NULL;
808  }
809  else {
810  /* delete some following segments
811  oos queue may have segments with FIN flag */
812  while (next &&
813  TCP_SEQ_GEQ((seqno + cseg->len),
814  (next->tcphdr->seqno + next->len))) {
815  /* cseg with FIN already processed */
816  if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
817  TCPH_SET_FLAG(cseg->tcphdr, TCP_FIN);
818  }
819  old_seg = next;
820  next = next->next;
821  tcp_seg_free(old_seg);
822  }
823  if (next &&
824  TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
825  /* We need to trim the incoming segment. */
826  cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
827  pbuf_realloc(cseg->p, cseg->len);
828  }
829  }
830  cseg->next = next;
831 }
832 #endif /* TCP_QUEUE_OOSEQ */
833 
846 static void
847 tcp_receive(struct tcp_pcb *pcb)
848 {
849  struct tcp_seg *next;
850 #if TCP_QUEUE_OOSEQ
851  struct tcp_seg *prev, *cseg;
852 #endif /* TCP_QUEUE_OOSEQ */
853  struct pbuf *p;
854  s32_t off;
855  s16_t m;
856  u32_t right_wnd_edge;
857  u16_t new_tot_len;
858  int found_dupack = 0;
859 #if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS
860  u32_t ooseq_blen;
861  u16_t ooseq_qlen;
862 #endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */
863 
864  LWIP_ASSERT("tcp_receive: wrong state", pcb->state >= ESTABLISHED);
865 
866  if (flags & TCP_ACK) {
867  right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;
868 
869  /* Update window. */
870  if (TCP_SEQ_LT(pcb->snd_wl1, seqno) ||
871  (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) ||
872  (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) {
873  pcb->snd_wnd = tcphdr->wnd;
874  /* keep track of the biggest window announced by the remote host to calculate
875  the maximum segment size */
876  if (pcb->snd_wnd_max < tcphdr->wnd) {
877  pcb->snd_wnd_max = tcphdr->wnd;
878  }
879  pcb->snd_wl1 = seqno;
880  pcb->snd_wl2 = ackno;
881  if (pcb->snd_wnd == 0) {
882  if (pcb->persist_backoff == 0) {
883  /* start persist timer */
884  pcb->persist_cnt = 0;
885  pcb->persist_backoff = 1;
886  }
887  } else if (pcb->persist_backoff > 0) {
888  /* stop persist timer */
889  pcb->persist_backoff = 0;
890  }
891  LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd));
892 #if TCP_WND_DEBUG
893  } else {
894  if (pcb->snd_wnd != tcphdr->wnd) {
896  ("tcp_receive: no window update lastack %"U32_F" ackno %"
897  U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n",
898  pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2));
899  }
900 #endif /* TCP_WND_DEBUG */
901  }
902 
903  /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a
904  * duplicate ack if:
905  * 1) It doesn't ACK new data
906  * 2) length of received packet is zero (i.e. no payload)
907  * 3) the advertised window hasn't changed
908  * 4) There is outstanding unacknowledged data (retransmission timer running)
909  * 5) The ACK is == biggest ACK sequence number so far seen (snd_una)
910  *
911  * If it passes all five, should process as a dupack:
912  * a) dupacks < 3: do nothing
913  * b) dupacks == 3: fast retransmit
914  * c) dupacks > 3: increase cwnd
915  *
916  * If it only passes 1-3, should reset dupack counter (and add to
917  * stats, which we don't do in lwIP)
918  *
919  * If it only passes 1, should reset dupack counter
920  *
921  */
922 
923  /* Clause 1 */
924  if (TCP_SEQ_LEQ(ackno, pcb->lastack)) {
925  pcb->acked = 0;
926  /* Clause 2 */
927  if (tcplen == 0) {
928  /* Clause 3 */
929  if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){
930  /* Clause 4 */
931  if (pcb->rtime >= 0) {
932  /* Clause 5 */
933  if (pcb->lastack == ackno) {
934  found_dupack = 1;
935  if ((u8_t)(pcb->dupacks + 1) > pcb->dupacks) {
936  ++pcb->dupacks;
937  }
938  if (pcb->dupacks > 3) {
939  /* Inflate the congestion window, but not if it means that
940  the value overflows. */
941  if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
942  pcb->cwnd += pcb->mss;
943  }
944  } else if (pcb->dupacks == 3) {
945  /* Do fast retransmit */
946  tcp_rexmit_fast(pcb);
947  }
948  }
949  }
950  }
951  }
952  /* If Clause (1) or more is true, but not a duplicate ack, reset
953  * count of consecutive duplicate acks */
954  if (!found_dupack) {
955  pcb->dupacks = 0;
956  }
957  } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){
958  /* We come here when the ACK acknowledges new data. */
959 
960  /* Reset the "IN Fast Retransmit" flag, since we are no longer
961  in fast retransmit. Also reset the congestion window to the
962  slow start threshold. */
963  if (pcb->flags & TF_INFR) {
964  pcb->flags &= ~TF_INFR;
965  pcb->cwnd = pcb->ssthresh;
966  }
967 
968  /* Reset the number of retransmissions. */
969  pcb->nrtx = 0;
970 
971  /* Reset the retransmission time-out. */
972  pcb->rto = (pcb->sa >> 3) + pcb->sv;
973 
974  /* Update the send buffer space. Diff between the two can never exceed 64K? */
975  pcb->acked = (u16_t)(ackno - pcb->lastack);
976 
977  pcb->snd_buf += pcb->acked;
978 
979  /* Reset the fast retransmit variables. */
980  pcb->dupacks = 0;
981  pcb->lastack = ackno;
982 
983  /* Update the congestion control variables (cwnd and
984  ssthresh). */
985  if (pcb->state >= ESTABLISHED) {
986  if (pcb->cwnd < pcb->ssthresh) {
987  if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
988  pcb->cwnd += pcb->mss;
989  }
990  LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd));
991  } else {
992  u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);
993  if (new_cwnd > pcb->cwnd) {
994  pcb->cwnd = new_cwnd;
995  }
996  LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd));
997  }
998  }
999  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n",
1000  ackno,
1001  pcb->unacked != NULL?
1002  ntohl(pcb->unacked->tcphdr->seqno): 0,
1003  pcb->unacked != NULL?
1004  ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
1005 
1006  /* Remove segment from the unacknowledged list if the incoming
1007  ACK acknowlegdes them. */
1008  while (pcb->unacked != NULL &&
1009  TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
1010  TCP_TCPLEN(pcb->unacked), ackno)) {
1011  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n",
1012  ntohl(pcb->unacked->tcphdr->seqno),
1013  ntohl(pcb->unacked->tcphdr->seqno) +
1014  TCP_TCPLEN(pcb->unacked)));
1015 
1016  next = pcb->unacked;
1017  pcb->unacked = pcb->unacked->next;
1018 
1019  LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
1020  LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
1021  /* Prevent ACK for FIN to generate a sent event */
1022  if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
1023  pcb->acked--;
1024  }
1025 
1026  pcb->snd_queuelen -= pbuf_clen(next->p);
1027  tcp_seg_free(next);
1028 
1029  LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen));
1030  if (pcb->snd_queuelen != 0) {
1031  LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
1032  pcb->unsent != NULL);
1033  }
1034  }
1035 
1036  /* If there's nothing left to acknowledge, stop the retransmit
1037  timer, otherwise reset it to start again */
1038  if(pcb->unacked == NULL)
1039  pcb->rtime = -1;
1040  else
1041  pcb->rtime = 0;
1042 
1043  pcb->polltmr = 0;
1044  } else {
1045  /* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */
1046  pcb->acked = 0;
1047  }
1048 
1049  /* We go through the ->unsent list to see if any of the segments
1050  on the list are acknowledged by the ACK. This may seem
1051  strange since an "unsent" segment shouldn't be acked. The
1052  rationale is that lwIP puts all outstanding segments on the
1053  ->unsent list after a retransmission, so these segments may
1054  in fact have been sent once. */
1055  while (pcb->unsent != NULL &&
1056  TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) +
1057  TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) {
1058  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n",
1059  ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) +
1060  TCP_TCPLEN(pcb->unsent)));
1061 
1062  next = pcb->unsent;
1063  pcb->unsent = pcb->unsent->next;
1064 #if TCP_OVERSIZE
1065  if (pcb->unsent == NULL) {
1066  pcb->unsent_oversize = 0;
1067  }
1068 #endif /* TCP_OVERSIZE */
1069  LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
1070  LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
1071  /* Prevent ACK for FIN to generate a sent event */
1072  if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
1073  pcb->acked--;
1074  }
1075  pcb->snd_queuelen -= pbuf_clen(next->p);
1076  tcp_seg_free(next);
1077  LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen));
1078  if (pcb->snd_queuelen != 0) {
1079  LWIP_ASSERT("tcp_receive: valid queue length",
1080  pcb->unacked != NULL || pcb->unsent != NULL);
1081  }
1082  }
1083  /* End of ACK for new data processing. */
1084 
1085  LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n",
1086  pcb->rttest, pcb->rtseq, ackno));
1087 
1088  /* RTT estimation calculations. This is done by checking if the
1089  incoming segment acknowledges the segment we use to take a
1090  round-trip time measurement. */
1091  if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {
1092  /* diff between this shouldn't exceed 32K since this are tcp timer ticks
1093  and a round-trip shouldn't be that long... */
1094  m = (s16_t)(tcp_ticks - pcb->rttest);
1095 
1096  LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n",
1097  m, m * TCP_SLOW_INTERVAL));
1098 
1099  /* This is taken directly from VJs original code in his paper */
1100  m = m - (pcb->sa >> 3);
1101  pcb->sa += m;
1102  if (m < 0) {
1103  m = -m;
1104  }
1105  m = m - (pcb->sv >> 2);
1106  pcb->sv += m;
1107  pcb->rto = (pcb->sa >> 3) + pcb->sv;
1108 
1109  LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n",
1110  pcb->rto, pcb->rto * TCP_SLOW_INTERVAL));
1111 
1112  pcb->rttest = 0;
1113  }
1114  }
1115 
1116  /* If the incoming segment contains data, we must process it
1117  further unless the pcb already received a FIN.
1118  (RFC 793, chapeter 3.9, "SEGMENT ARRIVES" in states CLOSE-WAIT, CLOSING,
1119  LAST-ACK and TIME-WAIT: "Ignore the segment text.") */
1120  if ((tcplen > 0) && (pcb->state < CLOSE_WAIT)) {
1121  /* This code basically does three things:
1122 
1123  +) If the incoming segment contains data that is the next
1124  in-sequence data, this data is passed to the application. This
1125  might involve trimming the first edge of the data. The rcv_nxt
1126  variable and the advertised window are adjusted.
1127 
1128  +) If the incoming segment has data that is above the next
1129  sequence number expected (->rcv_nxt), the segment is placed on
1130  the ->ooseq queue. This is done by finding the appropriate
1131  place in the ->ooseq queue (which is ordered by sequence
1132  number) and trim the segment in both ends if needed. An
1133  immediate ACK is sent to indicate that we received an
1134  out-of-sequence segment.
1135 
1136  +) Finally, we check if the first segment on the ->ooseq queue
1137  now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If
1138  rcv_nxt > ooseq->seqno, we must trim the first edge of the
1139  segment on ->ooseq before we adjust rcv_nxt. The data in the
1140  segments that are now on sequence are chained onto the
1141  incoming segment so that we only need to call the application
1142  once.
1143  */
1144 
1145  /* First, we check if we must trim the first edge. We have to do
1146  this if the sequence number of the incoming segment is less
1147  than rcv_nxt, and the sequence number plus the length of the
1148  segment is larger than rcv_nxt. */
1149  /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
1150  if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/
1151  if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)){
1152  /* Trimming the first edge is done by pushing the payload
1153  pointer in the pbuf downwards. This is somewhat tricky since
1154  we do not want to discard the full contents of the pbuf up to
1155  the new starting point of the data since we have to keep the
1156  TCP header which is present in the first pbuf in the chain.
1157 
1158  What is done is really quite a nasty hack: the first pbuf in
1159  the pbuf chain is pointed to by inseg.p. Since we need to be
1160  able to deallocate the whole pbuf, we cannot change this
1161  inseg.p pointer to point to any of the later pbufs in the
1162  chain. Instead, we point the ->payload pointer in the first
1163  pbuf to data in one of the later pbufs. We also set the
1164  inseg.data pointer to point to the right place. This way, the
1165  ->p pointer will still point to the first pbuf, but the
1166  ->p->payload pointer will point to data in another pbuf.
1167 
1168  After we are done with adjusting the pbuf pointers we must
1169  adjust the ->data pointer in the seg and the segment
1170  length.*/
1171 
1172  off = pcb->rcv_nxt - seqno;
1173  p = inseg.p;
1174  LWIP_ASSERT("inseg.p != NULL", inseg.p);
1175  LWIP_ASSERT("insane offset!", (off < 0x7fff));
1176  if (inseg.p->len < off) {
1177  LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off));
1178  new_tot_len = (u16_t)(inseg.p->tot_len - off);
1179  while (p->len < off) {
1180  off -= p->len;
1181  /* KJM following line changed (with addition of new_tot_len var)
1182  to fix bug #9076
1183  inseg.p->tot_len -= p->len; */
1184  p->tot_len = new_tot_len;
1185  p->len = 0;
1186  p = p->next;
1187  }
1188  if(pbuf_header(p, (s16_t)-off)) {
1189  /* Do we need to cope with this failing? Assert for now */
1190  LWIP_ASSERT("pbuf_header failed", 0);
1191  }
1192  } else {
1193  if(pbuf_header(inseg.p, (s16_t)-off)) {
1194  /* Do we need to cope with this failing? Assert for now */
1195  LWIP_ASSERT("pbuf_header failed", 0);
1196  }
1197  }
1198  inseg.len -= (u16_t)(pcb->rcv_nxt - seqno);
1199  inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
1200  }
1201  else {
1202  if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
1203  /* the whole segment is < rcv_nxt */
1204  /* must be a duplicate of a packet that has already been correctly handled */
1205 
1206  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno));
1207  tcp_ack_now(pcb);
1208  }
1209  }
1210 
1211  /* The sequence number must be within the window (above rcv_nxt
1212  and below rcv_nxt + rcv_wnd) in order to be further
1213  processed. */
1214  if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
1215  pcb->rcv_nxt + pcb->rcv_wnd - 1)){
1216  if (pcb->rcv_nxt == seqno) {
1217  /* The incoming segment is the next in sequence. We check if
1218  we have to trim the end of the segment and update rcv_nxt
1219  and pass the data to the application. */
1220  tcplen = TCP_TCPLEN(&inseg);
1221 
1222  if (tcplen > pcb->rcv_wnd) {
1224  ("tcp_receive: other end overran receive window"
1225  "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
1226  seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
1227  if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1228  /* Must remove the FIN from the header as we're trimming
1229  * that byte of sequence-space from the packet */
1230  TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) &~ TCP_FIN);
1231  }
1232  /* Adjust length of segment to fit in the window. */
1233  inseg.len = pcb->rcv_wnd;
1234  if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
1235  inseg.len -= 1;
1236  }
1237  pbuf_realloc(inseg.p, inseg.len);
1238  tcplen = TCP_TCPLEN(&inseg);
1239  LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
1240  (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
1241  }
1242 #if TCP_QUEUE_OOSEQ
1243  /* Received in-sequence data, adjust ooseq data if:
1244  - FIN has been received or
1245  - inseq overlaps with ooseq */
1246  if (pcb->ooseq != NULL) {
1247  if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1249  ("tcp_receive: received in-order FIN, binning ooseq queue\n"));
1250  /* Received in-order FIN means anything that was received
1251  * out of order must now have been received in-order, so
1252  * bin the ooseq queue */
1253  while (pcb->ooseq != NULL) {
1254  struct tcp_seg *old_ooseq = pcb->ooseq;
1255  pcb->ooseq = pcb->ooseq->next;
1256  tcp_seg_free(old_ooseq);
1257  }
1258  } else {
1259  next = pcb->ooseq;
1260  /* Remove all segments on ooseq that are covered by inseg already.
1261  * FIN is copied from ooseq to inseg if present. */
1262  while (next &&
1263  TCP_SEQ_GEQ(seqno + tcplen,
1264  next->tcphdr->seqno + next->len)) {
1265  /* inseg cannot have FIN here (already processed above) */
1266  if (TCPH_FLAGS(next->tcphdr) & TCP_FIN &&
1267  (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) {
1268  TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN);
1269  tcplen = TCP_TCPLEN(&inseg);
1270  }
1271  prev = next;
1272  next = next->next;
1273  tcp_seg_free(prev);
1274  }
1275  /* Now trim right side of inseg if it overlaps with the first
1276  * segment on ooseq */
1277  if (next &&
1278  TCP_SEQ_GT(seqno + tcplen,
1279  next->tcphdr->seqno)) {
1280  /* inseg cannot have FIN here (already processed above) */
1281  inseg.len = (u16_t)(next->tcphdr->seqno - seqno);
1282  if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
1283  inseg.len -= 1;
1284  }
1285  pbuf_realloc(inseg.p, inseg.len);
1286  tcplen = TCP_TCPLEN(&inseg);
1287  LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n",
1288  (seqno + tcplen) == next->tcphdr->seqno);
1289  }
1290  pcb->ooseq = next;
1291  }
1292  }
1293 #endif /* TCP_QUEUE_OOSEQ */
1294 
1295  pcb->rcv_nxt = seqno + tcplen;
1296 
1297  /* Update the receiver's (our) window. */
1298  LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen);
1299  pcb->rcv_wnd -= tcplen;
1300 
1301  tcp_update_rcv_ann_wnd(pcb);
1302 
1303  /* If there is data in the segment, we make preparations to
1304  pass this up to the application. The ->recv_data variable
1305  is used for holding the pbuf that goes to the
1306  application. The code for reassembling out-of-sequence data
1307  chains its data on this pbuf as well.
1308 
1309  If the segment was a FIN, we set the TF_GOT_FIN flag that will
1310  be used to indicate to the application that the remote side has
1311  closed its end of the connection. */
1312  if (inseg.p->tot_len > 0) {
1313  recv_data = inseg.p;
1314  /* Since this pbuf now is the responsibility of the
1315  application, we delete our reference to it so that we won't
1316  (mistakingly) deallocate it. */
1317  inseg.p = NULL;
1318  }
1319  if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1320  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
1321  recv_flags |= TF_GOT_FIN;
1322  }
1323 
1324 #if TCP_QUEUE_OOSEQ
1325  /* We now check if we have segments on the ->ooseq queue that
1326  are now in sequence. */
1327  while (pcb->ooseq != NULL &&
1328  pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
1329 
1330  cseg = pcb->ooseq;
1331  seqno = pcb->ooseq->tcphdr->seqno;
1332 
1333  pcb->rcv_nxt += TCP_TCPLEN(cseg);
1334  LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n",
1335  pcb->rcv_wnd >= TCP_TCPLEN(cseg));
1336  pcb->rcv_wnd -= TCP_TCPLEN(cseg);
1337 
1338  tcp_update_rcv_ann_wnd(pcb);
1339 
1340  if (cseg->p->tot_len > 0) {
1341  /* Chain this pbuf onto the pbuf that we will pass to
1342  the application. */
1343  if (recv_data) {
1344  pbuf_cat(recv_data, cseg->p);
1345  } else {
1346  recv_data = cseg->p;
1347  }
1348  cseg->p = NULL;
1349  }
1350  if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
1351  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
1352  recv_flags |= TF_GOT_FIN;
1353  if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */
1354  pcb->state = CLOSE_WAIT;
1355  }
1356  }
1357 
1358  pcb->ooseq = cseg->next;
1359  tcp_seg_free(cseg);
1360  }
1361 #endif /* TCP_QUEUE_OOSEQ */
1362 
1363 
1364  /* Acknowledge the segment(s). */
1365  tcp_ack(pcb);
1366 
1367  } else {
1368  /* We get here if the incoming segment is out-of-sequence. */
1369  tcp_send_empty_ack(pcb);
1370 #if TCP_QUEUE_OOSEQ
1371  /* We queue the segment on the ->ooseq queue. */
1372  if (pcb->ooseq == NULL) {
1373  pcb->ooseq = tcp_seg_copy(&inseg);
1374  } else {
1375  /* If the queue is not empty, we walk through the queue and
1376  try to find a place where the sequence number of the
1377  incoming segment is between the sequence numbers of the
1378  previous and the next segment on the ->ooseq queue. That is
1379  the place where we put the incoming segment. If needed, we
1380  trim the second edges of the previous and the incoming
1381  segment so that it will fit into the sequence.
1382 
1383  If the incoming segment has the same sequence number as a
1384  segment on the ->ooseq queue, we discard the segment that
1385  contains less data. */
1386 
1387  prev = NULL;
1388  for(next = pcb->ooseq; next != NULL; next = next->next) {
1389  if (seqno == next->tcphdr->seqno) {
1390  /* The sequence number of the incoming segment is the
1391  same as the sequence number of the segment on
1392  ->ooseq. We check the lengths to see which one to
1393  discard. */
1394  if (inseg.len > next->len) {
1395  /* The incoming segment is larger than the old
1396  segment. We replace some segments with the new
1397  one. */
1398  cseg = tcp_seg_copy(&inseg);
1399  if (cseg != NULL) {
1400  if (prev != NULL) {
1401  prev->next = cseg;
1402  } else {
1403  pcb->ooseq = cseg;
1404  }
1405  tcp_oos_insert_segment(cseg, next);
1406  }
1407  break;
1408  } else {
1409  /* Either the lenghts are the same or the incoming
1410  segment was smaller than the old one; in either
1411  case, we ditch the incoming segment. */
1412  break;
1413  }
1414  } else {
1415  if (prev == NULL) {
1416  if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
1417  /* The sequence number of the incoming segment is lower
1418  than the sequence number of the first segment on the
1419  queue. We put the incoming segment first on the
1420  queue. */
1421  cseg = tcp_seg_copy(&inseg);
1422  if (cseg != NULL) {
1423  pcb->ooseq = cseg;
1424  tcp_oos_insert_segment(cseg, next);
1425  }
1426  break;
1427  }
1428  } else {
1429  /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
1430  TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/
1431  if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) {
1432  /* The sequence number of the incoming segment is in
1433  between the sequence numbers of the previous and
1434  the next segment on ->ooseq. We trim trim the previous
1435  segment, delete next segments that included in received segment
1436  and trim received, if needed. */
1437  cseg = tcp_seg_copy(&inseg);
1438  if (cseg != NULL) {
1439  if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
1440  /* We need to trim the prev segment. */
1441  prev->len = (u16_t)(seqno - prev->tcphdr->seqno);
1442  pbuf_realloc(prev->p, prev->len);
1443  }
1444  prev->next = cseg;
1445  tcp_oos_insert_segment(cseg, next);
1446  }
1447  break;
1448  }
1449  }
1450  /* If the "next" segment is the last segment on the
1451  ooseq queue, we add the incoming segment to the end
1452  of the list. */
1453  if (next->next == NULL &&
1454  TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
1455  if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
1456  /* segment "next" already contains all data */
1457  break;
1458  }
1459  next->next = tcp_seg_copy(&inseg);
1460  if (next->next != NULL) {
1461  if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
1462  /* We need to trim the last segment. */
1463  next->len = (u16_t)(seqno - next->tcphdr->seqno);
1464  pbuf_realloc(next->p, next->len);
1465  }
1466  /* check if the remote side overruns our receive window */
1467  if ((u32_t)tcplen + seqno > pcb->rcv_nxt + (u32_t)pcb->rcv_wnd) {
1469  ("tcp_receive: other end overran receive window"
1470  "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
1471  seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
1472  if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) {
1473  /* Must remove the FIN from the header as we're trimming
1474  * that byte of sequence-space from the packet */
1475  TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) &~ TCP_FIN);
1476  }
1477  /* Adjust length of segment to fit in the window. */
1478  next->next->len = pcb->rcv_nxt + pcb->rcv_wnd - seqno;
1479  pbuf_realloc(next->next->p, next->next->len);
1480  tcplen = TCP_TCPLEN(next->next);
1481  LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
1482  (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
1483  }
1484  }
1485  break;
1486  }
1487  }
1488  prev = next;
1489  }
1490  }
1491 #if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS
1492  /* Check that the data on ooseq doesn't exceed one of the limits
1493  and throw away everything above that limit. */
1494  ooseq_blen = 0;
1495  ooseq_qlen = 0;
1496  prev = NULL;
1497  for(next = pcb->ooseq; next != NULL; prev = next, next = next->next) {
1498  struct pbuf *p = next->p;
1499  ooseq_blen += p->tot_len;
1500  ooseq_qlen += pbuf_clen(p);
1501  if ((ooseq_blen > TCP_OOSEQ_MAX_BYTES) ||
1502  (ooseq_qlen > TCP_OOSEQ_MAX_PBUFS)) {
1503  /* too much ooseq data, dump this and everything after it */
1504  tcp_segs_free(next);
1505  if (prev == NULL) {
1506  /* first ooseq segment is too much, dump the whole queue */
1507  pcb->ooseq = NULL;
1508  } else {
1509  /* just dump 'next' and everything after it */
1510  prev->next = NULL;
1511  }
1512  break;
1513  }
1514  }
1515 #endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */
1516 #endif /* TCP_QUEUE_OOSEQ */
1517  }
1518  } else {
1519  /* The incoming segment is not withing the window. */
1520  tcp_send_empty_ack(pcb);
1521  }
1522  } else {
1523  /* Segments with length 0 is taken care of here. Segments that
1524  fall out of the window are ACKed. */
1525  /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
1526  TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
1527  if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){
1528  tcp_ack_now(pcb);
1529  }
1530  }
1531 }
1532 
1541 static void
1542 tcp_parseopt(struct tcp_pcb *pcb)
1543 {
1544  u16_t c, max_c;
1545  u16_t mss;
1546  u8_t *opts, opt;
1547 #if LWIP_TCP_TIMESTAMPS
1548  u32_t tsval;
1549 #endif
1550 
1551  opts = (u8_t *)tcphdr + TCP_HLEN;
1552 
1553  /* Parse the TCP MSS option, if present. */
1554  if(TCPH_HDRLEN(tcphdr) > 0x5) {
1555  max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2;
1556  for (c = 0; c < max_c; ) {
1557  opt = opts[c];
1558  switch (opt) {
1559  case 0x00:
1560  /* End of options. */
1561  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n"));
1562  return;
1563  case 0x01:
1564  /* NOP option. */
1565  ++c;
1566  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n"));
1567  break;
1568  case 0x02:
1569  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n"));
1570  if (opts[c + 1] != 0x04 || c + 0x04 > max_c) {
1571  /* Bad length */
1572  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1573  return;
1574  }
1575  /* An MSS option with the right option length. */
1576  mss = (opts[c + 2] << 8) | opts[c + 3];
1577  /* Limit the mss to the configured TCP_MSS and prevent division by zero */
1578  pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss;
1579  /* Advance to next option */
1580  c += 0x04;
1581  break;
1582 #if LWIP_TCP_TIMESTAMPS
1583  case 0x08:
1584  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n"));
1585  if (opts[c + 1] != 0x0A || c + 0x0A > max_c) {
1586  /* Bad length */
1587  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1588  return;
1589  }
1590  /* TCP timestamp option with valid length */
1591  tsval = (opts[c+2]) | (opts[c+3] << 8) |
1592  (opts[c+4] << 16) | (opts[c+5] << 24);
1593  if (flags & TCP_SYN) {
1594  pcb->ts_recent = ntohl(tsval);
1595  pcb->flags |= TF_TIMESTAMP;
1596  } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) {
1597  pcb->ts_recent = ntohl(tsval);
1598  }
1599  /* Advance to next option */
1600  c += 0x0A;
1601  break;
1602 #endif
1603  default:
1604  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n"));
1605  if (opts[c + 1] == 0) {
1606  LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1607  /* If the length field is zero, the options are malformed
1608  and we don't process them further. */
1609  return;
1610  }
1611  /* All other options have a length field, so that we easily
1612  can skip past them. */
1613  c += opts[c + 1];
1614  }
1615  }
1616  }
1617 }
1618 
1619 #endif /* LWIP_TCP */
#define TCP_INPUT_DEBUG
Definition: opt.h:2017
#define ip_addr_copy(dest, src)
Definition: ip_addr.h:162
#define TCP_QLEN_DEBUG
Definition: opt.h:2067
#define ERR_CLSD
Definition: err.h:67
r dropped
Definition: btrfs.c:3014
#define TCP_OOSEQ_MAX_BYTES
Definition: opt.h:1011
#define TCP_DEBUG
Definition: tcpcore.h:1815
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
Definition: pbuf.c:511
void pbuf_realloc(struct pbuf *p, u16_t new_len)
Definition: pbuf.c:430
#define U32_F
Definition: cc.h:39
u16_t inet_chksum_pseudo(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, u8_t proto, u16_t proto_len)
Definition: inet_chksum.c:272
#define TCP_CWND_DEBUG
Definition: opt.h:2039
#define PBUF_FLAG_PUSH
Definition: pbuf.h:66
#define SOF_INHERITED
Definition: ip.h:109
#define TCP_RTO_DEBUG
Definition: opt.h:2032
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:66
const GLfloat * m
Definition: glext.h:10848
void memp_free(memp_t type, void *mem)
Definition: memp.c:435
#define TCP_OOSEQ_MAX_PBUFS
Definition: opt.h:1019
ip_addr_t current_iphdr_dest
Definition: ip.c:109
#define PERF_START
Definition: perf.h:3
#define ip_addr_isbroadcast(ipaddr, netif)
Definition: ip_addr.h:202
#define TCP_WND_DEBUG
Definition: opt.h:2046
#define ip_current_src_addr()
Definition: ip.h:200
#define TCP_STATS_INC(x)
Definition: stats.h:171
#define IP_PROTO_TCP
Definition: ip.h:56
#define TCP_WND
Definition: opt.h:923
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:618
s8_t err_t
Definition: err.h:47
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:95
#define U16_F
Definition: cc.h:36
#define ERR_OK
Definition: err.h:52
#define snmp_inc_tcppassiveopens()
Definition: snmp.h:312
#define ip_addr_ismulticast(addr1)
Definition: ip_addr.h:208
Definition: pbuf.h:79
unsigned long u32_t
Definition: cc.h:25
const GLubyte * c
Definition: glext.h:8905
#define snmp_inc_tcpinerrs()
Definition: snmp.h:318
#define X16_F
Definition: cc.h:38
Definition: netif.h:136
GLbitfield flags
Definition: glext.h:7161
Definition: tcpdef.h:22
#define ERR_RST
Definition: err.h:66
#define ntohs(x)
Definition: module.h:208
#define err(...)
static unsigned __int64 next
Definition: rand_nt.c:6
#define PBUF_FLAG_TCP_FIN
Definition: pbuf.h:77
#define snmp_inc_tcpinsegs()
Definition: snmp.h:315
u8_t pbuf_clen(struct pbuf *p)
Definition: pbuf.c:704
#define ip_addr_isany(addr1)
Definition: ip_addr.h:200
Definition: ip.h:116
#define ip_addr_cmp(addr1, addr2)
Definition: ip_addr.h:198
#define IPH_HL(hdr)
Definition: ip.h:147
#define ERR_MEM
Definition: fontsub.h:52
struct define * next
Definition: compiler.c:65
void pbuf_cat(struct pbuf *h, struct pbuf *t)
Definition: pbuf.c:745
ip_addr_t current_iphdr_src
Definition: ip.c:107
unsigned char u8_t
Definition: cc.h:23
#define NULL
Definition: types.h:112
#define TCP_MSS
Definition: opt.h:956
#define ntohl(x)
Definition: module.h:203
signed long s32_t
Definition: cc.h:30
#define TCP_RST_DEBUG
Definition: opt.h:2060
#define c
Definition: ke_i.h:80
__u16 dest
Definition: tcpdef.h:24
#define ERR_ABRT
Definition: err.h:65
unsigned short u16_t
Definition: cc.h:24
GLfloat GLfloat p
Definition: glext.h:8902
#define ip_current_dest_addr()
Definition: ip.h:202
signed short s16_t
Definition: cc.h:29