lwip-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lwip-devel] tcp_receive(): Wrong tot_len when trimming first edge


From: Edward Kerekes
Subject: [lwip-devel] tcp_receive(): Wrong tot_len when trimming first edge
Date: Sun, 23 May 2004 11:28:37 -0400

Attention: Leon

Bug in:
  Release:   Stable 0.7.1
  Module:    tcp_in.c
  Function   tcp_receive().

Hello and thanks to all contributors to this project!

The pbuf "tot_len" value is not adjusted correctly when "trimming
the first edge" of the received segment.

Here is the original code:

  off = pcb->rcv_nxt - seqno;
  if (inseg.p->len < off) {
    p = inseg.p;
    while (p->len < off) {
      off -= p->len;
      inseg.p->tot_len -= p->len;  /* <-----this doesn't work... */
      p->len = 0;
      p = p->next;
    }
    pbuf_header(p, -off);
  } else {

\\\\\\\\\\\\\\\\
The original code only works if the "trimming" is contained to the
first pbuf.  If the "trim" extends into the second pbuf two problems
result:

1.  Only the first pbuf has it's tot_len (partially) modified, the
other pbufs are left un-modified (this may or may not cause
problems later on...).

2.  The main issue is that the code doesn't take into account the
call to pbuf_header(p, -off).  The code drops out of the loop
with "inseg.p->tot_len" too big (by the amount remaining in "off").
This is handled fine by the call to pbuf_header() - if it's the
first pbuf in the chain.  Otherwise, the first several totals
are wrong...

In my case the call to lwip_recv() (which called netbuf_copy_partial())
returned without copying the requested number of bytes.  (The return
byte count however indicated all the requested bytes had been delivered.)

\\\\\\\\\\\\\\\\
So I believe this is what was intended:

  off = pcb->rcv_nxt - seqno;
  if (inseg.p->len < off) {
    u16_t new_tot;                    /* temp for new tot_len  */
    p = inseg.p;
    new_tot = inseg.p->tot_len - off; /* calc new tot_len */
    while (p->len < off) {
      off -= p->len;
      p->tot_len = new_tot;             /* each with len=0 has new_tot! */
      p->len = 0;
      p = p->next;
    }
    pbuf_header(p, -off);             /* now this works as intended */
  } else {

\\\\\\\\\\\\\
Here is a printout of the pbuf chain before and after the "trim left"
adjustment (from the fixed code):

tcp_receive: before adjust left: pbuf=1541C, tot_len=512, len=74
tcp_receive: before adjust left: pbuf=154AA, tot_len=438, len=128
tcp_receive: before adjust left: pbuf=15538, tot_len=310, len=128
tcp_receive: before adjust left: pbuf=155C6, tot_len=182, len=128
tcp_receive: before adjust left: pbuf=15654, tot_len=54, len=54

tcp_receive: after adjust left: pbuf=1541C, tot_len=260, len=0
tcp_receive: after adjust left: pbuf=154AA, tot_len=260, len=0
tcp_receive: after adjust left: pbuf=15538, tot_len=260, len=78
tcp_receive: after adjust left: pbuf=155C6, tot_len=182, len=128
tcp_receive: after adjust left: pbuf=15654, tot_len=54, len=54

If there are any questions - feel free to email me...

Thanks again for all who have contributed.

Ed Kerekes






reply via email to

[Prev in Thread] Current Thread [Next in Thread]