source: lib/protocols_l3.c @ 0989e3e

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 0989e3e was c909fad, checked in by Shane Alcock <salcock@…>, 9 years ago
  • Added checksumming functions for both the IP and transport layer. The functions will calculate the correct checksum for that packet and also return a pointer to the checksum field in the appropriate header so that the caller can either evaluate whether the checksum is correct, replace the existing checksum, or do whatever they want.
  • Also managed to fix a bunch of broken Revision svn tags
  • Property mode set to 100644
File size: 17.2 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
5 * New Zealand.
6 *
7 * Authors: Daniel Lawson
8 *          Perry Lorier
9 *          Shane Alcock
10 *         
11 * All rights reserved.
12 *
13 * This code has been developed by the University of Waikato WAND
14 * research group. For further information please see http://www.wand.net.nz/
15 *
16 * libtrace is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * libtrace is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with libtrace; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29 *
30 * $Id$
31 *
32 */
33
34
35#include "libtrace_int.h"
36#include "libtrace.h"
37#include "protocols.h"
38#include "checksum.h"
39#include <assert.h>
40#include <stdlib.h>
41#include <arpa/inet.h>
42
43#ifdef HAVE_NETPACKET_PACKET_H
44#include <sys/socket.h>
45#include <netpacket/packet.h>
46#include <net/ethernet.h>
47#include <net/if_arp.h>
48#include <string.h>
49#else
50#include <net/if_dl.h>
51#include <string.h>
52#endif
53
54/* This file contains all the protocol decoding functions for layer 3
55 * (the IP layer) protocols. This includes functions for accessing IP
56 * addresses.
57 *
58 * Supported protocols include:
59 *      IPv4
60 *      IPv6
61 */
62
63/* Gets an IPv4 header */
64libtrace_ip_t *trace_get_ip(libtrace_packet_t *packet) 
65{
66        uint16_t ethertype;
67        void *ret;
68
69        uint32_t remaining = trace_get_capture_length(packet);
70
71        ret = trace_get_layer3(packet,&ethertype,&remaining);
72
73        if (!ret || ethertype!=TRACE_ETHERTYPE_IP)
74                return NULL;
75
76        /* Make sure we have at least a base IPv4 header */
77        if (remaining < sizeof(libtrace_ip_t)) 
78                return NULL;
79       
80        /* Not an IPv4 packet */
81        if (((libtrace_ip_t*)ret)->ip_v != 4)
82                return NULL;
83
84        return (libtrace_ip_t*)ret;
85}
86
87libtrace_ip6_t *trace_get_ip6(libtrace_packet_t *packet) 
88{
89        uint16_t ethertype;
90        void *ret;
91
92        uint32_t remaining = trace_get_capture_length(packet);
93
94        ret = trace_get_layer3(packet,&ethertype,&remaining);
95
96        if (!ret || ethertype!=TRACE_ETHERTYPE_IPV6)
97                return NULL;
98
99        /* Make sure we have at least the base IPv6 header */
100        if (remaining < sizeof(libtrace_ip6_t))
101                return NULL;
102
103        return (libtrace_ip6_t*)ret;
104}
105
106#define SW_IP_OFFMASK 0x1fff
107
108DLLEXPORT void *trace_get_payload_from_ip(libtrace_ip_t *ipptr, uint8_t *prot,
109                uint32_t *remaining) 
110{
111        void *trans_ptr = 0;
112
113        assert(ipptr != NULL);
114       
115        /* Er? IPv5? */
116        if (ipptr->ip_v != 4)
117                return NULL;
118
119        if ((ntohs(ipptr->ip_off) & SW_IP_OFFMASK) != 0) {
120                if (remaining)
121                        *remaining = 0;         
122                return NULL;
123        }
124
125        if (remaining) {
126                if (*remaining<(ipptr->ip_hl*4U)) {
127                        *remaining = 0;
128                        return NULL;
129                }
130                /* If the packet features extra "padding", we probably
131                 * don't want that counting as possible payload, e.g. for
132                 * payload length calculations */
133                //if (*remaining > ntohs(ipptr->ip_len))
134                //      *remaining = ntohs(ipptr->ip_len);
135
136                *remaining-=(ipptr->ip_hl * 4);
137        }
138
139        trans_ptr = (void *)((char *)ipptr + (ipptr->ip_hl * 4));
140
141        if (prot) *prot = ipptr->ip_p;
142
143        return trans_ptr;
144}
145
146void *trace_get_payload_from_ip6(libtrace_ip6_t *ipptr, uint8_t *prot,
147                uint32_t *remaining) 
148{
149        void *payload = (char*)ipptr+sizeof(libtrace_ip6_t);
150        uint8_t nxt;
151        uint16_t len;
152
153        assert (ipptr != NULL);
154        nxt = ipptr->nxt;       
155        if (remaining) {
156                if (*remaining<sizeof(libtrace_ip6_t)) {
157                        *remaining = 0;
158                        return NULL;
159                }
160                *remaining-=sizeof(libtrace_ip6_t);
161        }
162
163        while(1) {
164                switch (nxt) {
165                        case 0: /* hop by hop options */
166                        case TRACE_IPPROTO_ROUTING:
167                        case TRACE_IPPROTO_AH:
168                        case TRACE_IPPROTO_DSTOPTS:
169                        {
170                                /* Length does not include the first 8 bytes */
171                                len=((libtrace_ip6_ext_t*)payload)->len * 8;
172                                len += 8;
173
174
175                                if (remaining) {
176                                        if (*remaining < len) {
177                                                /* Snap too short */
178                                                *remaining = 0;
179                                                return NULL;
180                                        }
181                                        *remaining-=len;
182                                }
183
184                                nxt=((libtrace_ip6_ext_t*)payload)->nxt;
185                                payload=(char*)payload+len;
186                                continue;
187                        }
188                        case TRACE_IPPROTO_ESP:
189                        {
190                                if (prot) *prot=TRACE_IPPROTO_ESP;
191                                return payload;
192                        }
193                        case TRACE_IPPROTO_FRAGMENT:
194                                {
195                                        len = sizeof(libtrace_ip6_frag_t);
196                                        if (remaining) {
197                                                if (*remaining < len) {
198                                                        /* Snap too short */
199                                                        *remaining = 0;
200                                                        return NULL;
201                                                }
202                                                *remaining-=len;
203                                        }
204                                        nxt=((libtrace_ip6_frag_t*)payload)->nxt;
205                                        payload=(char*)payload+len;
206                                        continue;
207                                }
208
209                        default:
210                                if (prot) *prot=nxt;
211                                return payload;
212                }
213        }
214}
215
216DLLEXPORT void *trace_get_layer3(const libtrace_packet_t *packet,
217                uint16_t *ethertype,
218                uint32_t *remaining)
219{
220        void *iphdr;
221        uint16_t dummy_ethertype;
222        void *link;
223        uint32_t dummy_remaining;
224        libtrace_linktype_t linktype;
225
226        if (!ethertype) ethertype=&dummy_ethertype;
227
228        if (!remaining) remaining=&dummy_remaining;
229
230        /* use l3 cache */
231        if (packet->l3_header)
232        {
233                /*
234                link = trace_get_packet_buffer(packet,&linktype,remaining);
235
236                if (!link)
237                        return NULL;
238                */
239
240                *ethertype = packet->l3_ethertype;
241                /* *remaining -= (packet->l3_header - link); */
242                *remaining = packet->l3_remaining;
243
244                return packet->l3_header;
245        }
246
247        link = trace_get_layer2(packet,&linktype,remaining);
248        iphdr = trace_get_payload_from_layer2(
249                        link,
250                        linktype,
251                        ethertype,
252                        remaining);
253
254        for(;;) {
255                if (!iphdr || *remaining == 0)
256                        break;
257                switch(*ethertype) {
258                case TRACE_ETHERTYPE_8021Q: /* VLAN */
259                        iphdr=trace_get_payload_from_vlan(
260                                          iphdr,ethertype,remaining);
261                        continue;
262                case TRACE_ETHERTYPE_MPLS: /* MPLS */
263                        iphdr=trace_get_payload_from_mpls(
264                                          iphdr,ethertype,remaining);
265
266                        if (iphdr && ethertype == 0x0) {
267                                iphdr=trace_get_payload_from_ethernet(
268                                                iphdr,ethertype,remaining);
269                        }
270                        continue;
271                case TRACE_ETHERTYPE_PPP_SES: /* PPPoE */
272                        iphdr = trace_get_payload_from_pppoe(iphdr, ethertype,
273                                        remaining);
274                        continue;
275                default:
276                        break;
277                }
278
279                break;
280        }
281
282        if (!iphdr || *remaining == 0)
283                return NULL;
284
285        /* Store values in the cache for later */
286        /* Cast away constness, nasty, but this is just a cache */
287        ((libtrace_packet_t*)packet)->l3_ethertype = *ethertype;
288        ((libtrace_packet_t*)packet)->l3_header = iphdr;
289        ((libtrace_packet_t*)packet)->l3_remaining = *remaining;
290
291        return iphdr;
292}
293
294/* Parse an ip or tcp option
295 * @param[in,out] ptr   the pointer to the current option
296 * @param[in,out] len   the length of the remaining buffer
297 * @param[out] type     the type of the option
298 * @param[out] optlen   the length of the option
299 * @param[out] data     the data of the option
300 *
301 * @returns bool true if there is another option (and the fields are filled in)
302 *               or false if this was the last option.
303 *
304 * This updates ptr to point to the next option after this one, and updates
305 * len to be the number of bytes remaining in the options area.  Type is updated
306 * to be the code of this option, and data points to the data of this option,
307 * with optlen saying how many bytes there are.
308 *
309 * @note Beware of fragmented packets.
310 * @author Perry Lorier
311 */
312DLLEXPORT int trace_get_next_option(unsigned char **ptr,int *len,
313                        unsigned char *type,
314                        unsigned char *optlen,
315                        unsigned char **data)
316{
317        if (*len<=0)
318                return 0;
319        *type=**ptr;
320        switch(*type) {
321                case 0: /* End of options */
322                        return 0;
323                case 1: /* Pad */
324                        (*ptr)++;
325                        (*len)--;
326                        return 1;
327                default:
328                        *optlen = *(*ptr+1);
329                        if (*optlen<2)
330                                return 0; /* I have no idea wtf is going on
331                                           * with these packets
332                                           */
333
334                        /* Ensure that optlen is not greater than the
335                         * amount of buffer remaining */
336                        if (*optlen > *len) 
337                                return 0;
338                       
339                        (*len)-=*optlen;
340                        (*data)=(*ptr+2);
341                        (*ptr)+=*optlen;
342                        if (*len<0)
343                                return 0;
344                        return 1;
345        }
346        assert(0);
347}
348
349static char *sockaddr_to_string(struct sockaddr *addrptr, char *space,
350                int spacelen) {
351
352        assert(addrptr && space);
353        assert(spacelen > 0);
354       
355        if (addrptr->sa_family == AF_INET) {
356                struct sockaddr_in *v4 = (struct sockaddr_in *)addrptr;
357                inet_ntop(AF_INET, &(v4->sin_addr), space, spacelen);
358        }
359
360        else if (addrptr->sa_family == AF_INET6) {
361                struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addrptr;
362                inet_ntop(AF_INET6, &(v6->sin6_addr), space, spacelen);
363        }
364#ifdef HAVE_NETPACKET_PACKET_H
365        else if (addrptr->sa_family == AF_PACKET) {
366                struct sockaddr_ll *l2addr = (struct sockaddr_ll *)addrptr;
367                uint8_t *macbytes = (uint8_t *)l2addr->sll_addr;
368
369                snprintf(space, spacelen, "%02x:%02x:%02x:%02x:%02x:%02x",
370                                macbytes[0], macbytes[1], macbytes[2],
371                                macbytes[3], macbytes[4], macbytes[5]);
372
373        }
374#else
375        else if (addrptr->sa_family == AF_LINK) {
376                struct sockaddr_dl *l2addr = (struct sockaddr_dl *)addrptr;
377                uint8_t *macbytes = (uint8_t *)l2addr->sdl_data;
378
379                snprintf(space, spacelen, "%02x:%02x:%02x:%02x:%02x:%02x",
380                                macbytes[0], macbytes[1], macbytes[2],
381                                macbytes[3], macbytes[4], macbytes[5]);
382       
383        }
384#endif
385        else {
386                space[0] = '\0';
387                return NULL;
388        }
389
390        return space;
391
392}
393
394/* Extract the source mac address from a frame and bundle it up into a sockaddr */
395static struct sockaddr *get_source_ethernet_address(
396        libtrace_ether_t *ethernet, struct sockaddr *addr)
397{
398        static struct sockaddr_storage dummy;
399#ifdef HAVE_NETPACKET_PACKET_H
400/* Use linux's sockaddr_ll structure */
401        struct sockaddr_ll *l2addr;
402
403        if (addr)
404                l2addr = (struct sockaddr_ll*)addr;
405        else
406                l2addr = (struct sockaddr_ll*)&dummy;
407       
408        l2addr->sll_family = AF_PACKET;
409        l2addr->sll_protocol = ethernet->ether_type;
410        l2addr->sll_ifindex = 0; /* Irrelevant */
411        l2addr->sll_hatype = ARPHRD_ETHER; 
412        l2addr->sll_pkttype = PACKET_OTHERHOST;
413        l2addr->sll_halen = 6;
414        memcpy(l2addr->sll_addr,ethernet->ether_shost, 6);
415
416        return (struct sockaddr*)l2addr;
417#else
418/* Use BSD's sockaddr_dl structure */
419        struct sockaddr_dl *l2addr;
420
421        if (addr)
422                l2addr = (struct sockaddr_dl *)addr;
423        else
424                l2addr = (struct sockaddr_dl *)&dummy;
425       
426        l2addr->sdl_family = AF_LINK;
427#if HAVE_SDL_LEN == 1
428        l2addr->sdl_len = sizeof(struct sockaddr_dl);
429#endif
430        l2addr->sdl_index = 0; /* Unused */
431        l2addr->sdl_alen = 6; /* Address length  */
432        l2addr->sdl_nlen = 0; /* No name in here - this *should* work, right? */
433        l2addr->sdl_slen = 0;   
434        l2addr->sdl_type = 0; /* Hopefully zero is OK for this value too */
435        memcpy(l2addr->sdl_data, ethernet->ether_shost, 6);
436
437        return (struct sockaddr *)l2addr;
438#endif
439}
440
441static struct sockaddr *get_source_l2_address(
442        const libtrace_packet_t *packet, struct sockaddr *addr)
443{
444        static struct sockaddr_storage dummy;
445        void *l2;
446        libtrace_linktype_t linktype;
447        uint32_t remaining;
448
449        if (!addr)
450                addr =(struct sockaddr*)&dummy;
451
452        l2=trace_get_layer2(packet, &linktype, &remaining);
453        if (!l2) {
454                return NULL;
455        }
456
457        switch (linktype) {
458                case TRACE_TYPE_ETH:
459                        return get_source_ethernet_address((libtrace_ether_t*)l2, addr);
460                default:
461                        return NULL;
462        }
463}
464
465DLLEXPORT struct sockaddr *trace_get_source_address(
466                const libtrace_packet_t *packet, struct sockaddr *addr)
467{
468        uint16_t ethertype;
469        uint32_t remaining;
470        void *l3;
471        struct ports_t *ports;
472        static struct sockaddr_storage dummy;
473
474        if (!addr)
475                addr=(struct sockaddr*)&dummy;
476
477        l3 = trace_get_layer3(packet,&ethertype,&remaining);
478
479        if (!l3)
480                return get_source_l2_address(packet,addr);
481
482        switch (ethertype) {
483                case TRACE_ETHERTYPE_IP: /* IPv4 */
484                {
485                        struct sockaddr_in *addr4=(struct sockaddr_in*)addr;
486                        libtrace_ip_t *ip = (libtrace_ip_t*)l3;
487                        ports = (struct ports_t*)
488                                trace_get_payload_from_ip(ip,NULL,&remaining);
489                        addr4->sin_family=AF_INET;
490                        if (ports && remaining>=sizeof(*ports))
491                                addr4->sin_port=ports->src;
492                        else
493                                addr4->sin_port=0;
494                        addr4->sin_addr=ip->ip_src;
495                        return addr;
496                }
497                case TRACE_ETHERTYPE_IPV6: /* IPv6 */
498                {
499                        struct sockaddr_in6 *addr6=(struct sockaddr_in6*)addr;
500                        libtrace_ip6_t *ip6 = (libtrace_ip6_t*)l3;
501                        ports = (struct ports_t*)
502                                trace_get_payload_from_ip6(ip6,NULL,&remaining);
503                        addr6->sin6_family=AF_INET6;
504                        if (ports && remaining>=sizeof(*ports))
505                                addr6->sin6_port=ports->src;
506                        else
507                                addr6->sin6_port=0;
508                        addr6->sin6_flowinfo=0;
509                        addr6->sin6_addr=ip6->ip_src;
510                        return addr;
511                }
512                default:
513                        return get_source_l2_address(packet, addr);
514        }
515}
516
517
518DLLEXPORT char *trace_get_source_address_string(
519                const libtrace_packet_t *packet, char *space, int spacelen) {
520
521        static char staticspace[INET6_ADDRSTRLEN];
522        struct sockaddr_storage addr;
523        struct sockaddr *addrptr;
524       
525
526        if (space == NULL || spacelen == 0) {
527                space = staticspace;
528                spacelen = INET6_ADDRSTRLEN;
529        }
530
531        addrptr = trace_get_source_address(packet, (struct sockaddr *)&addr);
532
533        if (addrptr == NULL)
534                return NULL;
535       
536        return sockaddr_to_string(addrptr, space, spacelen);
537}
538
539static struct sockaddr *get_destination_ethernet_address(
540        libtrace_ether_t *ethernet, struct sockaddr *addr)
541{
542        static struct sockaddr_storage dummy;
543#ifdef HAVE_NETPACKET_PACKET_H
544/* Use linux's sockaddr_ll structure */
545        struct sockaddr_ll *l2addr;
546        if (addr)
547                l2addr = (struct sockaddr_ll*)addr;
548        else
549                l2addr = (struct sockaddr_ll*)&dummy;
550       
551        l2addr->sll_family = AF_PACKET;
552        l2addr->sll_protocol = ethernet->ether_type;
553        l2addr->sll_ifindex = 0; /* Irrelevant */
554        l2addr->sll_hatype = ARPHRD_ETHER; 
555        l2addr->sll_pkttype = PACKET_OTHERHOST;
556        l2addr->sll_halen = 6;
557        memcpy(l2addr->sll_addr,ethernet->ether_dhost, 6);
558
559        return (struct sockaddr*)l2addr;
560#else
561/* Use BSD's sockaddr_dl structure */
562        struct sockaddr_dl *l2addr;
563
564        if (addr)
565                l2addr = (struct sockaddr_dl *)addr;
566        else
567                l2addr = (struct sockaddr_dl *)&dummy;
568       
569        l2addr->sdl_family = AF_LINK;
570#if HAVE_SDL_LEN == 1
571        l2addr->sdl_len = sizeof(struct sockaddr_dl);
572#endif
573        l2addr->sdl_index = 0; /* Unused */
574        l2addr->sdl_alen = 6; /* Address length  */
575        l2addr->sdl_nlen = 0; /* No name in here - this *should* work, right? */
576        l2addr->sdl_slen = 0;   
577        l2addr->sdl_type = 0; /* Hopefully zero is OK for this value too */
578        memcpy(l2addr->sdl_data, ethernet->ether_dhost, 6);
579
580        return (struct sockaddr *)l2addr;
581#endif
582}
583
584static struct sockaddr *get_destination_l2_address(
585        const libtrace_packet_t *packet, struct sockaddr *addr)
586{
587        static struct sockaddr_storage dummy;
588        void *l2;
589        libtrace_linktype_t linktype;
590        uint32_t remaining;
591        if (!addr)
592                addr =(struct sockaddr*)&dummy;
593        l2=trace_get_layer2(packet, &linktype, &remaining);
594        if (!l2)
595                return NULL;
596
597        switch (linktype) {
598                case TRACE_TYPE_ETH:
599                        return get_destination_ethernet_address((libtrace_ether_t*)l2, addr);
600                default:
601                        return NULL;
602        }
603}
604
605DLLEXPORT struct sockaddr *trace_get_destination_address(
606                const libtrace_packet_t *packet, struct sockaddr *addr)
607{
608        uint16_t ethertype;
609        uint32_t remaining;
610        void *l3;
611        struct ports_t *ports;
612        static struct sockaddr_storage dummy;
613
614        if (!addr)
615                addr=(struct sockaddr*)&dummy;
616
617        l3 = trace_get_layer3(packet,&ethertype,&remaining);
618
619        if (!l3)
620                return get_destination_l2_address(packet,addr);
621
622        switch (ethertype) {
623                case TRACE_ETHERTYPE_IP: /* IPv4 */
624                {
625                        struct sockaddr_in *addr4=(struct sockaddr_in*)addr;
626                        libtrace_ip_t *ip = (libtrace_ip_t*)l3;
627                        ports = (struct ports_t*)
628                                trace_get_payload_from_ip(ip,NULL,&remaining);
629                        addr4->sin_family=AF_INET;
630                        if (ports && remaining>=sizeof(*ports))
631                                addr4->sin_port=ports->dst;
632                        else
633                                addr4->sin_port=0;
634                        addr4->sin_addr=ip->ip_dst;
635                        return addr;
636                }
637                case TRACE_ETHERTYPE_IPV6: /* IPv6 */
638                {
639                        struct sockaddr_in6 *addr6=(struct sockaddr_in6*)addr;
640                        libtrace_ip6_t *ip6 = (libtrace_ip6_t*)l3;
641                        ports = (struct ports_t*)
642                                trace_get_payload_from_ip6(ip6,NULL,&remaining);
643                        addr6->sin6_family=AF_INET6;
644                        if (ports && remaining>=sizeof(*ports))
645                                addr6->sin6_port=ports->dst;
646                        else
647                                addr6->sin6_port=0;
648                        addr6->sin6_flowinfo=0;
649                        addr6->sin6_addr=ip6->ip_dst;
650                        return addr;
651                }
652                default:
653                        return get_destination_l2_address(packet, addr);
654        }
655}
656
657DLLEXPORT char *trace_get_destination_address_string(
658                const libtrace_packet_t *packet, char *space, int spacelen) {
659
660        struct sockaddr_storage addr;
661        struct sockaddr *addrptr;
662       
663        static char staticspace[INET6_ADDRSTRLEN];
664
665        if (space == NULL || spacelen == 0) {
666                space = staticspace;
667                spacelen = INET6_ADDRSTRLEN;
668        }
669
670        addrptr = trace_get_destination_address(packet, 
671                        (struct sockaddr *)&addr);
672
673        if (addrptr == NULL)
674                return NULL;
675       
676        return sockaddr_to_string(addrptr, space, spacelen);
677}
678
679DLLEXPORT uint16_t *trace_checksum_layer3(libtrace_packet_t *packet, 
680                uint16_t *csum) {
681
682        void *l3;
683        uint16_t ethertype;
684        uint32_t remaining;
685        uint16_t *csum_ptr;
686
687        uint8_t safety[65536];
688
689        if (csum == NULL)
690                return NULL;
691       
692        l3 = trace_get_layer3(packet, &ethertype, &remaining);
693               
694        if (l3 == NULL)
695                return NULL;
696       
697        if (ethertype == TRACE_ETHERTYPE_IP) {
698                libtrace_ip_t *ip = (libtrace_ip_t *)l3;
699                if (remaining < sizeof(libtrace_ip_t))
700                        return NULL;
701
702                csum_ptr = &ip->ip_sum;
703
704                /* I hate memcpys, but this is the only truly safe way to
705                 * do this without modifying the packet. I'm trying to be
706                 * careful about not creating any more thread-safety issues
707                 * than there already are :) */
708                memcpy(safety, ip, ip->ip_hl * sizeof(uint32_t));
709               
710                /* Set the checksum to zero, so we can do the calculation */
711                ip = (libtrace_ip_t *)safety;
712                ip->ip_sum = 0;
713
714                *csum = checksum_buffer(safety, ip->ip_hl * sizeof(uint32_t));
715               
716                /* Remember to byteswap appropriately */
717                *csum = ntohs(*csum);
718               
719                return csum_ptr;
720        }
721
722        return NULL;
723}
724
Note: See TracBrowser for help on using the repository browser.