Changeset 54a76f2


Ignore:
Timestamp:
08/14/18 10:59:52 (2 years ago)
Author:
Shane Alcock <salcock@…>
Branches:
cachetimestamps, develop, master, ringdecrementfix, ringperformance
Children:
1f184fd, 6646938
Parents:
30bf197
Message:

Fix broken payload lengths when IP length is not yet set.

Presumably, this can happen when the packet segmentation has
been offloaded to the NIC hardware -- the length is not set
until the packet is about to be sent (i.e. *after* an outgoing
packet is captured), so our calculation ends up producing a
negative number (0 - sizeof(IP) - sizeof(TCP / UDP)).

In this case, we instead have to infer the payload length using
the amount of bytes captured less the difference between the start
of the IP header and the start of the captured frame.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • lib/protocols_transport.c

    r6654714 r54a76f2  
    6262        libtrace_tcp_t *tcp;
    6363        size_t len = 0;
     64        uint8_t iplenzero = 0;
    6465
    6566        /* Just use the cached length if we can */
     
    7879                        if (rem < sizeof(libtrace_ip_t))
    7980                                return 0;
     81                        if (ntohs(ip->ip_len) == 0) {
     82                                iplenzero = 1;
     83                                break;
     84                        }
    8085                        len = ntohs(ip->ip_len) - (4 * ip->ip_hl);
    8186               
     
    9095                                return 0;
    9196                        len = ntohs(ip6->plen);
     97                        if (len == 0) {
     98                                iplenzero = 1;
     99                        }
    92100                        break;
    93101                default:
    94102                        return 0;
    95103        }
     104
     105        if (iplenzero) {
     106                /* deal with cases where IP length is zero due to
     107                 * hardware segmentation offload */
     108                uint8_t *iplayer, *pktstart;
     109                libtrace_linktype_t linktype;
     110                uint32_t rem;
     111
     112                iplayer = (uint8_t *)layer;
     113                pktstart = (uint8_t *)trace_get_packet_buffer(packet, &linktype, &rem);
     114
     115                len = rem - (iplayer - pktstart);
     116                if (ethertype == TRACE_ETHERTYPE_IP) {
     117                        ip = (libtrace_ip_t *)layer;
     118                        len -= (4 * ip->ip_hl);
     119                } else {
     120                        len -= sizeof(libtrace_ip6_t);
     121                }
     122        }
    96123
    97124        layer = trace_get_transport(packet, &proto, &rem);
Note: See TracChangeset for help on using the changeset viewer.