source: lib/protocols.c @ e0f9c80

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since e0f9c80 was e0f9c80, checked in by Shane Alcock <salcock@…>, 15 years ago

Fixed build error for the libpacketdump parser which crops up if you specify --with-dag
Might have also added/removed some braces and newlines that I couldn't be bothered reverting before commit :]

  • Property mode set to 100644
File size: 16.8 KB
Line 
1/* This file has the various helper functions used to decode various protocols
2 *
3 * $Id$
4 */ 
5#include "libtrace.h"
6#include "libtrace_int.h"
7#include "wag.h"
8#include <assert.h>
9#include <stdio.h>
10
11#ifndef WIN32
12#include <net/if_arp.h>
13#endif
14
15#ifndef ARPHRD_ETHER
16#define ARPHRD_ETHER    1               /* Ethernet 10/100Mbps.  */
17#endif
18
19#ifndef ARPHRD_PPP
20#define ARPHRD_PPP      512
21#endif
22
23
24/* Returns the payload from 802.3 ethernet.  Type optionally returned in
25 * "type" in host byte order.  This will return a vlan header.
26 */
27static void *trace_get_payload_from_ethernet(void *ethernet, 
28                uint16_t *type,
29                uint32_t *remaining)
30{
31        libtrace_ether_t *eth = (libtrace_ether_t*)ethernet;
32
33        if (remaining) {
34                if (*remaining < sizeof(*eth))
35                        return NULL;
36                *remaining-=sizeof(*eth);
37        }
38
39        if (type)
40                *type = ntohs(eth->ether_type);
41
42        return (void*)((char *)eth + sizeof(*eth));
43}
44
45/* skip any 802.1q headers if necessary
46 * type is input/output
47 */
48static void *trace_get_vlan_payload_from_ethernet_payload(void *ethernet, uint16_t *type,
49                uint32_t *remaining)
50{
51        assert(type && "You must pass a type in!");
52
53        if (*type == 0x8100) {
54                libtrace_8021q_t *vlanhdr = (libtrace_8021q_t *)ethernet;
55
56                if (remaining) {
57                        if (*remaining < sizeof(libtrace_8021q_t))
58                                return NULL;
59
60                        *remaining=*remaining-sizeof(libtrace_8021q_t);
61                }
62
63                *type = ntohs(vlanhdr->vlan_ether_type);
64
65                return (void*)((char *)ethernet + sizeof(*vlanhdr));
66        }
67
68        return ethernet;
69}
70
71static void *trace_get_payload_from_80211(void *link, uint16_t *type, uint32_t *remaining)
72{
73        libtrace_80211_t *wifi;
74        libtrace_802_11_payload_t *eth;
75
76        if (remaining && *remaining < sizeof(libtrace_80211_t))
77                return NULL;
78
79        wifi=(libtrace_80211_t*)link;
80
81        /* Data packet? */
82        if (wifi->type != 2) {
83                return NULL;
84        }
85
86        if (remaining && *remaining < sizeof(*eth))
87                return NULL;
88
89        eth=(libtrace_802_11_payload_t *)((char*)wifi+sizeof(*wifi));
90
91        if (type) *type=ntohs(eth->type);
92
93        return (void*)((char*)eth+sizeof(*eth));
94}
95
96static void *trace_get_payload_from_linux_sll(void *link,
97                uint16_t *type, uint32_t *remaining) 
98{
99        libtrace_sll_header_t *sll;
100        void *ret;
101
102        sll = (libtrace_sll_header_t*) link;
103
104        if (remaining) {
105                if (*remaining < sizeof(*sll))
106                        return NULL;
107                *remaining-=sizeof(*sll);
108        }
109
110        /* What kind of wacked out header, has this in host order?! */
111        if (type) *type = htons(sll->protocol); 
112
113        ret=(void*)((char*)sll+sizeof(*sll));
114
115        switch(sll->hatype) {
116                case ARPHRD_PPP:
117                        break;
118                case ARPHRD_ETHER:
119                        ret=trace_get_payload_from_ethernet(ret,type,remaining);
120                        break;
121                default:
122                        /* Unknown hardware type */
123                        return NULL;
124        }
125
126        return ret;
127}
128
129static void *trace_get_payload_from_atm(void *link,
130                uint16_t *type, uint32_t *remaining)
131{
132        /* 64 byte capture. */
133        libtrace_llcsnap_t *llc = (libtrace_llcsnap_t*)link;
134
135        if (remaining) {
136                if (*remaining < sizeof(libtrace_llcsnap_t)+4)
137                        return NULL;
138                *remaining-=(sizeof(libtrace_llcsnap_t)+4);
139        }
140
141        /* advance the llc ptr +4 into the link layer.
142         * TODO: need to check what is in these 4 bytes.
143         * don't have time!
144         */
145        llc = (libtrace_llcsnap_t*)((char *)llc + 4);
146
147        if (type) *type = ntohs(llc->type);
148
149        return (void*)((char*)llc+sizeof(*llc));
150}
151
152static void *trace_get_payload_from_pos(void *link, 
153                uint16_t *type, uint32_t *remaining)
154{
155        /* 64 byte capture. */
156        libtrace_pos_t *pos = (libtrace_pos_t*)link;
157
158        if (remaining) {
159                if (*remaining < sizeof(libtrace_pos_t))
160                        return NULL;
161                *remaining-=sizeof(libtrace_pos_t);
162        }
163
164        if (type) *type = ntohs(pos->ether_type);
165
166        return (void*)((char *)pos+sizeof(*pos));
167}
168
169static void *trace_get_payload_from_pflog(void *link,
170                uint16_t *type, uint32_t *remaining)
171{
172        libtrace_pflog_header_t *pflog = (libtrace_pflog_header_t*)link;
173        if (remaining) {
174                if (*remaining<sizeof(*pflog)) 
175                        return NULL;
176                *remaining-=sizeof(*pflog);
177        }
178        if (type) {
179                switch(pflog->af) {
180                        case AF_INET6: *type=0x86DD; break;
181                        case AF_INET:  *type=0x0800; break;
182                        default:
183                                      /* Unknown */
184                                      return NULL;
185                }
186        }
187        return (void*)((char*)pflog+ sizeof(*pflog));
188}
189
190void *trace_get_payload_from_link(void *link, libtrace_linktype_t linktype, 
191                uint16_t *type, uint32_t *remaining)
192{
193        switch(linktype) {
194                case TRACE_TYPE_80211_PRISM:
195                        return trace_get_payload_from_80211((char*)link+144,
196                                        type,remaining);
197                case TRACE_TYPE_80211:
198                        return trace_get_payload_from_80211(link,type,remaining);
199                case TRACE_TYPE_ETH:
200                        return trace_get_payload_from_ethernet(link,type,remaining);
201                case TRACE_TYPE_NONE:
202                        if ((*(char*)link&0xF0) == 0x40)
203                                *type=0x0800;
204                        else if ((*(char*)link&0xF0) == 0x60)
205                                *type=0x86DD;
206                        return link; /* I love the simplicity */
207                case TRACE_TYPE_LINUX_SLL:
208                        return trace_get_payload_from_linux_sll(link,type,remaining);
209                case TRACE_TYPE_PFLOG:
210                        return trace_get_payload_from_pflog(link,type,remaining);
211                case TRACE_TYPE_POS:
212                        return trace_get_payload_from_pos(link,type,remaining);
213                case TRACE_TYPE_ATM:
214                        return trace_get_payload_from_atm(link,type,remaining);
215                case TRACE_TYPE_DUCK:
216                        return NULL; /* duck packets have no payload! */
217        }
218        fprintf(stderr,"Don't understand link layer type %i in trace_get_payload_from_link()\n",
219                linktype);
220        return NULL;
221}
222
223libtrace_ip_t *trace_get_ip(libtrace_packet_t *packet) 
224{
225        uint16_t type;
226        void *link = trace_get_link(packet);
227        void *ret;
228
229        if (!link)
230                return NULL;
231       
232        ret=trace_get_payload_from_link(
233                        link,
234                        trace_get_link_type(packet),
235                        &type, NULL);
236
237        if (!ret)
238                return NULL;
239
240        ret=trace_get_vlan_payload_from_ethernet_payload(ret,&type,NULL);
241
242        if (!ret || type!=0x0800)
243                return NULL;
244
245        /* Not an IPv4 packet */
246        if (((libtrace_ip_t*)ret)->ip_v != 4)
247                return NULL;
248
249        return (libtrace_ip_t*)ret;
250}
251
252libtrace_ip6_t *trace_get_ip6(libtrace_packet_t *packet) 
253{
254        uint16_t type;
255        void *link=trace_get_link(packet);
256        void *ret;
257       
258        if (!link)
259                return NULL;
260
261        ret=trace_get_payload_from_link(
262                        link,
263                        trace_get_link_type(packet),
264                        &type,NULL);
265
266        if (!ret)
267                return NULL;
268
269        ret=trace_get_vlan_payload_from_ethernet_payload(ret,&type,NULL);
270
271        if (!ret || type!=0x86DD)
272                return NULL;
273
274        return (libtrace_ip6_t*)ret;
275}
276
277#define SW_IP_OFFMASK 0xff1f
278
279DLLEXPORT void *trace_get_payload_from_ip(libtrace_ip_t *ipptr, uint8_t *prot,
280                uint32_t *remaining) 
281{
282        void *trans_ptr = 0;
283
284        if ((ipptr->ip_off & SW_IP_OFFMASK) != 0) {
285                return NULL;
286        }
287
288        if (remaining) {
289                if (*remaining<(ipptr->ip_hl*4U)) {
290                        return NULL;
291                }
292                *remaining-=(ipptr->ip_hl * 4);
293        }
294
295        trans_ptr = (void *)((char *)ipptr + (ipptr->ip_hl * 4));
296
297        if (prot) *prot = ipptr->ip_p;
298
299        return trans_ptr;
300}
301
302void *trace_get_payload_from_ip6(libtrace_ip6_t *ipptr, uint8_t *prot,
303                uint32_t *remaining) 
304{
305        void *payload = (char*)ipptr+sizeof(libtrace_ip6_t);
306        uint8_t nxt = ipptr->nxt;
307
308        if (remaining) {
309                if (*remaining<sizeof(libtrace_ip6_t))
310                        return NULL;
311                *remaining-=sizeof(libtrace_ip6_t);
312        }
313
314        while(1) {
315                switch (nxt) {
316                        case 0: /* hop by hop options */
317                        case 43: /* routing */
318                        case 44: /* fragment */
319                        case 50: /* ESP */
320                        case 51: /* AH */
321                        case 60: /* Destination options */
322                                {
323                                        uint16_t len=((libtrace_ip6_ext_t*)payload)->len
324                                        +sizeof(libtrace_ip6_ext_t);
325
326                                        if (remaining) {
327                                                if (*remaining < len) {
328                                                        /* Snap too short */
329                                                        return NULL;
330                                                }
331                                                *remaining-=len;
332                                        }
333
334                                        payload=(char*)payload+len;
335                                        nxt=((libtrace_ip6_ext_t*)payload)->nxt;
336                                        continue;
337                                }
338                        default:
339                                if (prot) *prot=nxt;
340                                return payload;
341                }
342        }
343}
344
345DLLEXPORT void *trace_get_transport(libtrace_packet_t *packet, 
346                uint8_t *proto,
347                uint32_t *remaining
348                ) 
349{
350        void *transport;
351        uint8_t dummy_proto;
352        uint16_t ethertype;
353        void *link;
354        uint32_t dummy_remaining;
355
356        if (!proto) proto=&dummy_proto;
357
358        if (!remaining) remaining=&dummy_remaining;
359
360        *remaining = trace_get_capture_length(packet);
361
362        link=trace_get_link(packet);
363
364        if (!link)
365                return NULL;
366
367        transport = trace_get_payload_from_link(
368                        link,
369                        trace_get_link_type(packet),
370                        &ethertype,
371                        remaining);
372
373        if (!transport)
374                return NULL;
375
376        transport = trace_get_vlan_payload_from_ethernet_payload(transport,
377                        &ethertype,
378                        remaining);
379
380        if (!transport)
381                return NULL;
382
383        switch (ethertype) {
384                case 0x0800: /* IPv4 */
385                        transport=trace_get_payload_from_ip(
386                                (libtrace_ip_t*)transport, proto, remaining);
387                        /* IPv6 */
388                        if (transport && *proto == 41) {
389                                transport=trace_get_payload_from_ip6(
390                                 (libtrace_ip6_t*)transport, proto,remaining);
391                        }
392                        return transport;
393                case 0x86DD: /* IPv6 */
394                        return trace_get_payload_from_ip6(
395                                (libtrace_ip6_t*)transport, proto, remaining);
396                       
397                default:
398                        *proto=0;
399                        return NULL;
400        }
401
402}
403
404DLLEXPORT libtrace_tcp_t *trace_get_tcp(libtrace_packet_t *packet) {
405        uint8_t proto;
406        libtrace_tcp_t *tcp;
407
408        tcp=(libtrace_tcp_t*)trace_get_transport(packet,&proto,NULL);
409
410        if (!tcp || proto != 6)
411                return NULL;
412
413        return (libtrace_tcp_t*)tcp;
414}
415
416DLLEXPORT libtrace_tcp_t *trace_get_tcp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
417{
418        libtrace_tcp_t *tcpptr = 0;
419
420        if (ip->ip_p == 6)  {
421                tcpptr = (libtrace_tcp_t *)
422                        trace_get_payload_from_ip(ip, NULL, remaining);
423        }
424
425        return tcpptr;
426}
427
428DLLEXPORT libtrace_udp_t *trace_get_udp(libtrace_packet_t *packet) {
429        uint8_t proto;
430        libtrace_udp_t *udp;
431
432        udp=(libtrace_udp_t*)trace_get_transport(packet,&proto,NULL);
433
434        if (!udp || proto != 17)
435                return NULL;
436
437        return udp;
438}
439
440DLLEXPORT libtrace_udp_t *trace_get_udp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
441{
442        libtrace_udp_t *udpptr = 0;
443
444        if (ip->ip_p == 17) {
445                udpptr = (libtrace_udp_t *)
446                        trace_get_payload_from_ip(ip, NULL, remaining);
447        }
448
449        return udpptr;
450}
451
452DLLEXPORT libtrace_icmp_t *trace_get_icmp(libtrace_packet_t *packet) {
453        uint8_t proto;
454        libtrace_icmp_t *icmp;
455
456        icmp=(libtrace_icmp_t*)trace_get_transport(packet,&proto,NULL);
457
458        if (!icmp || proto != 1)
459                return NULL;
460
461        return icmp;
462}
463
464DLLEXPORT libtrace_icmp_t *trace_get_icmp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
465{
466        libtrace_icmp_t *icmpptr = 0;
467
468        if (ip->ip_p == 1)  {
469                icmpptr = (libtrace_icmp_t *)trace_get_payload_from_ip(ip, 
470                                NULL, remaining);
471        }
472
473        return icmpptr;
474}
475
476DLLEXPORT void *trace_get_payload_from_udp(libtrace_udp_t *udp, uint32_t *remaining)
477{
478        if (remaining) {
479                if (*remaining < sizeof(libtrace_udp_t))
480                        return NULL;
481                *remaining-=sizeof(libtrace_udp_t);
482        }
483        return (void*)((char*)udp+sizeof(libtrace_udp_t));
484}
485
486DLLEXPORT void *trace_get_payload_from_tcp(libtrace_tcp_t *tcp, uint32_t *remaining)
487{
488        unsigned int dlen = tcp->doff*4;
489        if (remaining) {
490                if (*remaining < dlen)
491                        return NULL;
492                *remaining-=dlen;
493        }
494        return (void *)((char *)tcp+dlen);
495}
496
497DLLEXPORT void *trace_get_payload_from_icmp(libtrace_icmp_t *icmp, uint32_t *remaining)
498{
499        if (remaining) {
500                if (*remaining < sizeof(libtrace_icmp_t))
501                        return NULL;
502                *remaining-=sizeof(libtrace_icmp_t);
503        }
504        return (char*)icmp+sizeof(libtrace_icmp_t);
505}
506
507struct ports_t {
508        uint16_t src;
509        uint16_t dst;
510};
511
512/* Return the client port
513 */
514DLLEXPORT uint16_t trace_get_source_port(const libtrace_packet_t *packet)
515{
516        uint32_t remaining;
517        struct ports_t *port = 
518                (struct ports_t*)trace_get_transport((libtrace_packet_t*)packet,
519                        NULL, &remaining);
520
521        /* snapped too early */
522        if (remaining<2)
523                return 0;
524
525        if (port)
526                return ntohs(port->src);
527        else
528                return 0;
529}
530
531/* Same as get_source_port except use the destination port */
532DLLEXPORT uint16_t trace_get_destination_port(const libtrace_packet_t *packet)
533{
534        uint32_t remaining;
535        struct ports_t *port = 
536                (struct ports_t*)trace_get_transport((libtrace_packet_t*)packet,
537                        NULL, &remaining);
538        /* snapped to early */
539        if (remaining<4)
540                return 0;
541
542        if (port)
543                return ntohs(port->dst);
544        else
545                return 0;
546}
547
548
549uint8_t *trace_get_source_mac(libtrace_packet_t *packet) {
550        void *link = trace_get_link(packet);
551        libtrace_80211_t *wifi;
552        libtrace_ether_t *ethptr = (libtrace_ether_t*)link;
553        if (!link)
554                return NULL;
555        switch (trace_get_link_type(packet)) {
556                case TRACE_TYPE_80211:
557                        wifi=(libtrace_80211_t*)link;
558                        return (uint8_t*)&wifi->mac2;
559                case TRACE_TYPE_80211_PRISM:
560                        wifi=(libtrace_80211_t*)((char*)link+144);
561                        return (uint8_t*)&wifi->mac2;
562                case TRACE_TYPE_ETH:
563                        return (uint8_t*)&ethptr->ether_shost;
564                case TRACE_TYPE_POS:
565                case TRACE_TYPE_NONE:
566                case TRACE_TYPE_HDLC_POS:
567                case TRACE_TYPE_LINUX_SLL:
568                case TRACE_TYPE_PFLOG:
569                case TRACE_TYPE_ATM:
570                case TRACE_TYPE_DUCK:
571                        return NULL;
572        }
573        fprintf(stderr,"Not implemented\n");
574        assert(0);
575        return NULL;
576}
577
578DLLEXPORT uint8_t *trace_get_destination_mac(libtrace_packet_t *packet) {
579        void *link = trace_get_link(packet);
580        libtrace_80211_t *wifi;
581        libtrace_ether_t *ethptr = (libtrace_ether_t*)link;
582        if (!link)
583                return NULL;
584        switch (trace_get_link_type(packet)) {
585                case TRACE_TYPE_80211:
586                        wifi=(libtrace_80211_t*)link;
587                        return (uint8_t*)&wifi->mac1;
588                case TRACE_TYPE_80211_PRISM:
589                        wifi=(libtrace_80211_t*)((char*)link+144);
590                        return (uint8_t*)&wifi->mac1;
591                case TRACE_TYPE_ETH:
592                        return (uint8_t*)&ethptr->ether_dhost;
593                case TRACE_TYPE_POS:
594                case TRACE_TYPE_NONE:
595                case TRACE_TYPE_ATM:
596                case TRACE_TYPE_HDLC_POS:
597                case TRACE_TYPE_LINUX_SLL:
598                case TRACE_TYPE_PFLOG:
599                case TRACE_TYPE_DUCK:
600                        /* No MAC address */
601                        return NULL;
602        }
603        fprintf(stderr,"Not implemented\n");
604        assert(0);
605        return NULL;
606}
607
608DLLEXPORT struct sockaddr *trace_get_source_address(const libtrace_packet_t *packet, 
609                struct sockaddr *addr)
610{
611        uint16_t proto;
612        uint32_t remaining;
613        void *l3;
614        struct ports_t *ports;
615        static struct sockaddr_storage dummy;
616
617        if (!addr)
618                addr=(struct sockaddr*)&dummy;
619
620        remaining = trace_get_capture_length(packet);
621
622        l3 = trace_get_payload_from_link(
623                        trace_get_link(packet),
624                        trace_get_link_type(packet),
625                        &proto,
626                        &remaining);
627
628        if (!l3)
629                return false;
630
631        l3 = trace_get_vlan_payload_from_ethernet_payload(l3,
632                        &proto,
633                        &remaining);
634
635        if (!l3)
636                return NULL;
637
638        switch (proto) {
639                case 0x0800: /* IPv4 */
640                {
641                        struct sockaddr_in *addr4=(struct sockaddr_in*)addr;
642                        libtrace_ip_t *ip = (libtrace_ip_t*)l3;
643                        ports = (struct ports_t*)
644                                trace_get_payload_from_ip(ip,NULL,&remaining);
645                        addr4->sin_family=AF_INET;
646                        if (ports && remaining>=sizeof(*ports))
647                                addr4->sin_port=ports->src;
648                        else
649                                addr4->sin_port=0;
650                        addr4->sin_addr=ip->ip_src;
651                        return addr;
652                }
653                case 0x86DD: /* IPv6 */
654                {
655                        struct sockaddr_in6 *addr6=(struct sockaddr_in6*)addr;
656                        libtrace_ip6_t *ip6 = (libtrace_ip6_t*)l3;
657                        ports = (struct ports_t*)
658                                trace_get_payload_from_ip6(ip6,NULL,&remaining);
659                        addr6->sin6_family=AF_INET6;
660                        if (ports && remaining>=sizeof(*ports))
661                                addr6->sin6_port=ports->dst;
662                        else
663                                addr6->sin6_port=0;
664                        addr6->sin6_flowinfo=0;
665                        addr6->sin6_addr=ip6->ip_src;
666                        return addr;
667                }
668                default:
669                        return NULL;
670        }
671}
672
673DLLEXPORT struct sockaddr *trace_get_destination_address(const libtrace_packet_t *packet, 
674                struct sockaddr *addr)
675{
676        uint16_t proto;
677        uint32_t remaining;
678        void *transport;
679        static struct sockaddr_storage dummy;
680
681        if (!addr)
682                addr=(struct sockaddr*)&dummy;
683
684        remaining = trace_get_capture_length(packet);
685
686        transport = trace_get_payload_from_link(
687                        trace_get_link(packet),
688                        trace_get_link_type(packet),
689                        &proto,
690                        &remaining);
691
692        if (!transport)
693                return false;
694
695        transport = trace_get_vlan_payload_from_ethernet_payload(transport,
696                        &proto,
697                        &remaining);
698
699        if (!transport)
700                return false;
701
702        switch (proto) {
703                case 0x0800: /* IPv4 */
704                {
705                        struct sockaddr_in *addr4=(struct sockaddr_in*)addr;
706                        libtrace_ip_t *ip = (libtrace_ip_t*)transport;
707                        addr4->sin_family=AF_INET;
708                        addr4->sin_port=0;
709                        addr4->sin_addr=ip->ip_dst;
710                        return addr;
711                }
712                case 0x86DD: /* IPv6 */
713                {
714                        struct sockaddr_in6 *addr6=(struct sockaddr_in6*)addr;
715                        libtrace_ip6_t *ip6 = (libtrace_ip6_t*)transport;
716                        addr6->sin6_family=AF_INET6;
717                        addr6->sin6_port=0;
718                        addr6->sin6_flowinfo=0;
719                        addr6->sin6_addr=ip6->ip_dst;
720                        return addr;
721                }
722                default:
723                        return NULL;
724        }
725}
726
727/* parse an ip or tcp option
728 * @param[in,out] ptr   the pointer to the current option
729 * @param[in,out] len   the length of the remaining buffer
730 * @param[out] type     the type of the option
731 * @param[out] optlen   the length of the option
732 * @param[out] data     the data of the option
733 *
734 * @returns bool true if there is another option (and the fields are filled in)
735 *               or false if this was the last option.
736 *
737 * This updates ptr to point to the next option after this one, and updates
738 * len to be the number of bytes remaining in the options area.  Type is updated
739 * to be the code of this option, and data points to the data of this option,
740 * with optlen saying how many bytes there are.
741 *
742 * @note Beware of fragmented packets.
743 * @author Perry Lorier
744 */
745DLLEXPORT int trace_get_next_option(unsigned char **ptr,int *len,
746                        unsigned char *type,
747                        unsigned char *optlen,
748                        unsigned char **data)
749{
750        if (*len<=0)
751                return 0;
752        *type=**ptr;
753        switch(*type) {
754                case 0: /* End of options */
755                        return 0;
756                case 1: /* Pad */
757                        (*ptr)++;
758                        (*len)--;
759                        return 1;
760                default:
761                        *optlen = *(*ptr+1);
762                        if (*optlen<2)
763                                return 0; /* I have no idea wtf is going on
764                                           * with these packets
765                                           */
766                        (*len)-=*optlen;
767                        (*data)=(*ptr+2);
768                        (*ptr)+=*optlen;
769                        if (*len<0)
770                                return 0;
771                        return 1;
772        }
773        assert(0);
774}
775
776
Note: See TracBrowser for help on using the repository browser.