Ignore:
Timestamp:
10/05/12 09:50:51 (9 years ago)
Author:
Shane Alcock <salcock@…>
Branches:
4.0.1-hotfixes, cachetimestamps, develop, dpdk-ndag, etsilive, getfragoff, help, libtrace4, master, ndag_format, pfring, rc-4.0.1, rc-4.0.2, rc-4.0.3, rc-4.0.4, ringdecrementfix, ringperformance, ringtimestampfixes
Children:
d11be03
Parents:
699c4a3
Message:
  • Fixed tracereplay bug where we would try to update the transport checksum for packets that don't have a complete transport header
File:
1 edited

Legend:

Unmodified
Added
Removed
  • tools/tracereplay/tracereplay.c

    rec0f8f1 r1ca17db  
    22/*
    33
    4   Tracereplay is a simple utility that takes a trace and replays it to a
    5   specified interface.
    6   It pads packets with zeroes to reach the original length of the packet
    7   and recalculates checksums in ip/tcp/udp headers.
    8 
    9   Authors: Andreas Loef and Yuwei Wang
     4   Tracereplay is a simple utility that takes a trace and replays it to a
     5   specified interface.
     6   It pads packets with zeroes to reach the original length of the packet
     7   and recalculates checksums in ip/tcp/udp headers.
     8
     9Authors: Andreas Loef and Yuwei Wang
    1010
    1111
     
    3030   RFC 1071 describes the method and provides a code example*/
    3131static uint16_t checksum(void * buffer, uint16_t length) {
    32   uint32_t sum = 0;
    33   uint16_t * buff = (uint16_t *) buffer;
    34   uint16_t count = length;
    35 
    36   while(count > 1 ) {
    37     sum += *buff++;
    38     count = count -2;
    39   }
    40 
    41   if(count > 0) {
    42     sum += *buff;
    43   }
    44  
    45   while (sum>>16)
    46     sum = (sum & 0xffff) + (sum >> 16);
    47 
    48   return ~sum;
     32        uint32_t sum = 0;
     33        uint16_t * buff = (uint16_t *) buffer;
     34        uint16_t count = length;
     35
     36        while(count > 1 ) {
     37                sum += *buff++;
     38                count = count -2;
     39        }
     40
     41        if(count > 0) {
     42                sum += *buff;
     43        }
     44
     45        while (sum>>16)
     46                sum = (sum & 0xffff) + (sum >> 16);
     47
     48        return ~sum;
    4949}
    5050
    5151/*
    52   This function calculates and fills in the correct checksum on
    53   a transport protocol header.
    54   Currently only UDP and TCP are supported.
    55 */
     52   This function calculates and fills in the correct checksum on
     53   a transport protocol header.
     54   Currently only UDP and TCP are supported.
     55 */
    5656
    5757static void udp_tcp_checksum(libtrace_ip_t *ip, uint32_t length) {
    5858
    59   uint32_t sum = 0;
    60   uint16_t protocol = ip->ip_p;
    61   uint16_t temp = 0;
    62   uint16_t * check = NULL;
    63   uint16_t tsum = 0;
    64   void * transportheader = NULL;
    65 
    66   sum += (uint16_t) ~checksum(&ip->ip_src.s_addr,sizeof(uint32_t));
    67   sum += (uint16_t) ~checksum(&ip->ip_dst.s_addr,sizeof(uint32_t));
    68 
    69 
    70   /*this will be in host order whereas everything else is in network order*/
    71   temp = htons(protocol);
    72   sum += (uint16_t) ~checksum(&temp,sizeof(uint16_t));
    73 
    74   /*this will be in host order whereas everything else is in network order*/
    75   temp = htons(length);
    76   sum += (uint16_t) ~checksum(&temp,sizeof(uint16_t));
    77 
    78   transportheader = trace_get_payload_from_ip(ip,NULL,NULL);
    79 
    80   /* UDP */
    81   if(protocol == 17 ) {
    82     libtrace_udp_t * udp_header = transportheader;
    83     check = &udp_header -> check;
    84     *check = 0;
    85     tsum = checksum(transportheader, length);
    86   }
    87   /* TCP */
    88   else if(protocol == 6) {
    89     libtrace_tcp_t * tcp_header = transportheader;
    90     tcp_header -> check = 0;
    91     check = &tcp_header -> check;
    92     *check = 0;
    93     tsum = checksum(transportheader,length);
    94   }
    95 
    96   sum += (uint16_t) ~tsum;
    97 
    98   while (sum>>16)
    99     sum = (sum & 0xffff) + (sum >> 16);
    100 
    101   if(check != NULL) {
    102     *check = (uint16_t)~sum;
    103   }
    104  
     59        uint32_t sum = 0;
     60        uint16_t protocol = ip->ip_p;
     61        uint16_t temp = 0;
     62        uint16_t * check = NULL;
     63        uint16_t tsum = 0;
     64        void * transportheader = NULL;
     65        uint32_t rem;
     66
     67        sum += (uint16_t) ~checksum(&ip->ip_src.s_addr,sizeof(uint32_t));
     68        sum += (uint16_t) ~checksum(&ip->ip_dst.s_addr,sizeof(uint32_t));
     69
     70
     71        /*this will be in host order whereas everything else is in network order*/
     72        temp = htons(protocol);
     73        sum += (uint16_t) ~checksum(&temp,sizeof(uint16_t));
     74
     75        /*this will be in host order whereas everything else is in network order*/
     76        temp = htons(length);
     77        sum += (uint16_t) ~checksum(&temp,sizeof(uint16_t));
     78
     79        transportheader = trace_get_payload_from_ip(ip,NULL,&rem);
     80
     81        if (transportheader == NULL)
     82                return;
     83
     84        /* UDP */
     85        if(protocol == 17 ) {
     86                libtrace_udp_t * udp_header = transportheader;
     87
     88                if (rem < sizeof(libtrace_udp_t))
     89                        return;
     90                check = &udp_header -> check;
     91                *check = 0;
     92                tsum = checksum(transportheader, length);
     93        }
     94        /* TCP */
     95        else if(protocol == 6) {
     96                libtrace_tcp_t * tcp_header = transportheader;
     97
     98                if (rem < sizeof(libtrace_tcp_t))
     99                        return;
     100                tcp_header -> check = 0;
     101                check = &tcp_header -> check;
     102                *check = 0;
     103                tsum = checksum(transportheader,length);
     104        }
     105
     106        sum += (uint16_t) ~tsum;
     107
     108        while (sum>>16)
     109                sum = (sum & 0xffff) + (sum >> 16);
     110
     111        if(check != NULL) {
     112                *check = (uint16_t)~sum;
     113        }
     114
    105115
    106116
     
    108118
    109119/*
    110   Create a copy of the packet that can be written to the output URI.
    111   if the packet is IPv4 the checksum will be recalculated to account for
    112   cryptopan. Same for TCP and UDP. No other protocols are supported at the
    113   moment.
     120   Create a copy of the packet that can be written to the output URI.
     121   if the packet is IPv4 the checksum will be recalculated to account for
     122   cryptopan. Same for TCP and UDP. No other protocols are supported at the
     123   moment.
    114124 */
    115125static libtrace_packet_t * per_packet(libtrace_packet_t *packet) {
    116   uint32_t remaining = 0; 
    117   libtrace_linktype_t linktype = 0;
    118   libtrace_ip_t * header = NULL;
    119   uint16_t sum = 0;
    120   libtrace_packet_t *new_packet;
    121   size_t wire_length;
    122   void * pkt_buffer;
    123   void * l2_header;
    124   libtrace_ether_t * ether_header;
    125   int i;
    126 
    127   pkt_buffer = trace_get_packet_buffer(packet,&linktype,&remaining);
    128   remaining = 0;
    129   new_packet = trace_create_packet();
    130  
    131   wire_length = trace_get_wire_length(packet);
    132 
    133   /* if it's ehternet we don't want to add space for the FCS that will
    134      be appended. */
    135   if(linktype == TRACE_TYPE_ETH || linktype == TRACE_TYPE_80211) {
    136     wire_length -= FCS_SIZE;
    137   }
    138 
    139   trace_construct_packet(new_packet,linktype,pkt_buffer,wire_length);
    140 
    141 
    142   if(broadcast) {
    143     l2_header = trace_get_layer2(new_packet,&linktype,&remaining);
    144     if(linktype == TRACE_TYPE_ETH){
    145       ether_header = (libtrace_ether_t *) l2_header;
    146       for(i = 0; i < 6; i++) {
    147         ether_header -> ether_dhost[i] = 0xFF;
    148       }
    149     }
    150    
    151   }
    152 
    153  
    154  
    155   header = trace_get_ip(new_packet);
    156   if(header != NULL) {
    157     /* update ip checksum */
    158     wire_length -= sizeof(uint32_t)*header->ip_hl;
    159     header -> ip_sum = 0;
    160     sum = checksum(header,header->ip_hl*sizeof(uint32_t));
    161     header -> ip_sum = sum;
    162     /* update transport layer checksums */
    163     udp_tcp_checksum(header,ntohs(header->ip_len)-sizeof(uint32_t)*header->ip_hl);
    164   }
    165 
    166   return new_packet;
    167  
     126        uint32_t remaining = 0; 
     127        libtrace_linktype_t linktype = 0;
     128        libtrace_ip_t * header = NULL;
     129        uint16_t sum = 0;
     130        libtrace_packet_t *new_packet;
     131        size_t wire_length;
     132        void * pkt_buffer;
     133        void * l2_header;
     134        libtrace_ether_t * ether_header;
     135        int i;
     136
     137        pkt_buffer = trace_get_packet_buffer(packet,&linktype,&remaining);
     138        remaining = 0;
     139        new_packet = trace_create_packet();
     140
     141        wire_length = trace_get_wire_length(packet);
     142
     143        /* if it's ehternet we don't want to add space for the FCS that will
     144           be appended. */
     145        if(linktype == TRACE_TYPE_ETH || linktype == TRACE_TYPE_80211) {
     146                wire_length -= FCS_SIZE;
     147        }
     148
     149        trace_construct_packet(new_packet,linktype,pkt_buffer,wire_length);
     150
     151
     152        if(broadcast) {
     153                l2_header = trace_get_layer2(new_packet,&linktype,&remaining);
     154                if(linktype == TRACE_TYPE_ETH){
     155                        ether_header = (libtrace_ether_t *) l2_header;
     156                        for(i = 0; i < 6; i++) {
     157                                ether_header -> ether_dhost[i] = 0xFF;
     158                        }
     159                }
     160
     161        }
     162
     163
     164
     165        header = trace_get_ip(new_packet);
     166        if(header != NULL) {
     167                /* update ip checksum */
     168                wire_length -= sizeof(uint32_t)*header->ip_hl;
     169                header -> ip_sum = 0;
     170                sum = checksum(header,header->ip_hl*sizeof(uint32_t));
     171                header -> ip_sum = sum;
     172                /* update transport layer checksums */
     173                udp_tcp_checksum(header,ntohs(header->ip_len)-sizeof(uint32_t)*header->ip_hl);
     174        }
     175
     176        return new_packet;
     177
    168178}
    169179
     
    175185        fd_set rfds;
    176186        struct timeval sleep_tv;
    177        
     187
    178188        FD_ZERO(&rfds);
    179        
     189
    180190        for (;;) {
    181191                obj = trace_event(trace, packet);
    182192
    183193                switch(obj.type) {
    184                        
     194
    185195                        /* Device has no packets at present - lets wait until
    186196                         * it does get something */
     
    190200                                select(obj.fd + 1, &rfds, NULL, NULL, 0);
    191201                                continue;
    192                                
    193                         /* Replaying a trace in tracetime and the next packet
    194                         * is not due yet */
     202
     203                                /* Replaying a trace in tracetime and the next packet
     204                                * is not due yet */
    195205                        case TRACE_EVENT_SLEEP:
    196206                                /* select offers good precision for sleeping */
     
    199209                                select(0, NULL, NULL, NULL, &sleep_tv);
    200210                                continue;
    201                                
    202                         /* We've got a packet! */
     211
     212                                /* We've got a packet! */
    203213                        case TRACE_EVENT_PACKET:
    204214                                /* Check for error first */
     
    206216                                        return -1;
    207217                                return 1;
    208                                
    209                         /* End of trace has been reached */
     218
     219                                /* End of trace has been reached */
    210220                        case TRACE_EVENT_TERMINATE:
    211221                                return -1;
    212                                
    213                         /* An event we don't know about has occured */
     222
     223                                /* An event we don't know about has occured */
    214224                        default:
    215225                                fprintf(stderr, "Unknown event type occured\n");
     
    234244
    235245int main(int argc, char *argv[]) {
    236        
     246
    237247        libtrace_t *trace;
    238248        libtrace_out_t *output;
     
    243253        libtrace_packet_t * new;
    244254        int snaplen = 0;
    245        
     255
    246256
    247257        while(1) {
     
    262272
    263273                switch (c) {
    264                 case 'f':
    265                   filter = trace_create_filter(optarg);
    266                   break;
    267                 case 's':
    268                   snaplen = atoi(optarg);
    269                   break;
    270 
    271                 case 'b':
    272                   broadcast = 1;
    273                   break;
    274                  
    275                 case 'h':
    276                  
    277                   usage(argv[0]);
    278                   return 1;
    279                 default:
    280                   fprintf(stderr, "Unknown option: %c\n", c);
     274                        case 'f':
     275                                filter = trace_create_filter(optarg);
     276                                break;
     277                        case 's':
     278                                snaplen = atoi(optarg);
     279                                break;
     280
     281                        case 'b':
     282                                broadcast = 1;
     283                                break;
     284
     285                        case 'h':
     286
     287                                usage(argv[0]);
     288                                return 1;
     289                        default:
     290                                fprintf(stderr, "Unknown option: %c\n", c);
    281291                }
    282292        }
     
    304314        /*apply snaplength */
    305315        if(snaplen) {
    306           if(trace_config(trace,TRACE_OPTION_SNAPLEN,&snaplen)) {
    307             trace_perror(trace,"error setting snaplength, proceeding anyway");
    308           }
     316                if(trace_config(trace,TRACE_OPTION_SNAPLEN,&snaplen)) {
     317                        trace_perror(trace,"error setting snaplength, proceeding anyway");
     318                }
    309319        }
    310320
     
    324334        /* Creating output trace */
    325335        output = trace_create_output(argv[optind+1]);
    326        
     336
    327337        if (trace_is_err_output(output)) {
    328338                trace_perror_output(output, "Opening output trace: ");
     
    361371        trace_destroy(trace);
    362372        if(filter != NULL) {
    363           trace_destroy_filter(filter);
     373                trace_destroy_filter(filter);
    364374        }
    365375        trace_destroy_output(output);
Note: See TracChangeset for help on using the changeset viewer.