source: libpacketdump/bitbuffer.c

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivendag_formatrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file was ee6e802, checked in by Shane Alcock <salcock@…>, 5 years ago

Updated copyright blurb on all source files

In some cases, this meant adding copyright blurbs to files that
had never had them before.

  • Property mode set to 100644
File size: 8.7 KB
Line 
1/*
2 *
3 * Copyright (c) 2007-2016 The University of Waikato, Hamilton, New Zealand.
4 * All rights reserved.
5 *
6 * This file is part of libtrace.
7 *
8 * This code has been developed by the University of Waikato WAND
9 * research group. For further information please see http://www.wand.net.nz/
10 *
11 * libtrace is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * libtrace is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 *
24 *
25 */
26#include "bitbuffer.h"
27#include <inttypes.h>
28#include "parser.h"
29#include <stdio.h>
30#include <netinet/in.h>
31#include <assert.h>
32#include <stdlib.h>
33#include <arpa/inet.h>
34#include "libpacketdump.h"
35
36uint16_t bits;
37/* "the largest possible type the compiler supports" */
38bitbuffer_t buffer;
39
40static bitbuffer_t getbit(void **packet, int *packlen, uint64_t numbits)
41{
42    bitbuffer_t ret;
43    bitbuffer_t mask;
44   
45    char *pktptr = NULL;
46
47    /* While the buffer is not filled up and there is still
48     * data in the packet to read, read a byte...
49     *
50     * The buffer gets filled from right to left
51     */
52    while(bits < numbits && *packlen > 0)
53    {
54        uint8_t byte;
55        /* read in one byte from the packet */
56        byte=(*((bitbuffer_t*)*packet))&0xff;
57        buffer |= (bitbuffer_t)byte << (sizeof(bitbuffer_t)*8-(bits+sizeof(byte)*8));
58        /* update the position within the packet */
59        pktptr = (char *)*packet;
60        pktptr += 1;
61        *packet = pktptr;
62
63        //*packet = ((char*)*packet) + 1;
64
65        bits += sizeof(byte)*8;
66        *packlen -= 1;
67    }
68
69    /* our return value is the first <numbits> of the buffer */
70    mask = ~((1ULL<<((sizeof(bitbuffer_t)*8-numbits)))-1);
71    ret = buffer & mask;
72    ret >>=(sizeof(bitbuffer_t)*8-numbits);
73   
74    /* remove the bits that are being returned from out buffer */
75    buffer <<= numbits;
76
77    /* and update our position inside this buffer */
78    bits -= numbits;
79
80    return ret;
81}
82
83int yyparse(void);
84
85element_t* parse_protocol_file(char *filename)
86{
87    /* hold onto this so we can put it in any error messages */
88    file = filename;
89
90    /* if the protocol file doesn't exist, we return null and
91     * it will fall back to using the generic_decode function
92     */
93    yyin = fopen(filename, "r");
94    if(!yyin)
95        return NULL;
96
97    el_list = NULL;
98    lines = 1;
99
100    yyparse();
101    fclose(yyin);
102    return el_list;
103}
104
105
106static bitbuffer_t fix_byteorder(bitbuffer_t value,
107                enum byte_order_t order, uint64_t size)
108{
109    bitbuffer_t one = 1;
110    bitbuffer_t lhs;
111    bitbuffer_t rhs;;
112
113    /*
114     * XXX trial and error seems to show these numbers to work.
115     * I've tried fields of length 1,2,3,4,8,13,16,32 and they seem to work.
116     * Others are untested...
117     */
118    switch(order)
119    {
120        case BIGENDIAN:
121            if(size < 16)
122                return value;
123            if(size < 32)
124                return ntohs(value);
125            if(size <= 32)
126                return ntohl(value);
127           
128            lhs = ntohl(value& ((one<<32)-1));
129            rhs = ntohl(value >> 32);
130            return ((lhs<<32) | rhs);
131
132        case LITTLEENDIAN:
133            return value;
134
135    };
136
137    /* should never get here */
138    assert(0);
139    return 0;
140}
141
142
143
144void decode_protocol_file(uint16_t link_type UNUSED,const char *packet,int len,element_t *el)
145{
146    bitbuffer_t result;
147
148    while(el != NULL)
149    {
150        switch(el->type)
151        {
152            case FIELD:
153                if (len*8+bits<el->data->field->size) {
154                        printf(" [Truncated]\n");
155                        return;
156                }
157                result = getbit((void*)&packet, &len, el->data->field->size); 
158
159                switch(el->data->field->display)
160                {
161                    /* integers get byteswapped if needed and displayed */
162                    case DISPLAY_INT:
163                    {
164                        result = fix_byteorder(result, 
165                                el->data->field->order, 
166                                el->data->field->size);
167                               
168                        el->data->field->value = result;
169                        printf(" %s %" PRIi64 "\n", 
170                                el->data->field->identifier,
171                                result);
172                    }
173                    break;
174
175                    /*
176                     * hex numbers get byteswapped if needed and displayed
177                     * without being padded with zeroes
178                     */
179                    case DISPLAY_HEX:
180                    { 
181                        result = fix_byteorder(result, 
182                                el->data->field->order, 
183                                el->data->field->size);
184                       
185                        el->data->field->value = result;
186                        printf(" %s 0x%" PRIx64 "\n", 
187                                el->data->field->identifier,
188                                result);
189                    }
190                    break;
191                   
192                    /*
193                     * ipv4 addresses stay in network byte order and are
194                     * given to inet_ntoa() to deal with
195                     */
196                    case DISPLAY_IPV4:
197                    {
198                        /* assumes all ipv4 addresses are 32bit fields */
199                        struct in_addr address;
200                        address.s_addr = (uint32_t)result;
201                        el->data->field->value = result;
202                   
203                        printf(" %s %s\n", 
204                                el->data->field->identifier,
205                                inet_ntoa(address));
206                    }
207                    break;
208
209                    /*
210                     * mac addresses stay in network byte order and are
211                     * displayed byte by byte with zero padding
212                     */
213                    case DISPLAY_MAC:
214                    {
215                        /* assumes all mac addresses are 48bit fields */
216                        uint8_t *ptr = (uint8_t*)&result;
217                        el->data->field->value = result;
218                        printf(" %s %02x:%02x:%02x:%02x:%02x:%02x\n",
219                                el->data->field->identifier,
220                                ptr[0], ptr[1], ptr[2], 
221                                ptr[3], ptr[4], ptr[5]);
222                    }
223                    break;
224                   
225                    /*
226                     * Flag values are only displayed if their value is true
227                     * otherwise they are ignored
228                     */
229                    case DISPLAY_FLAG:
230                    {
231                        el->data->field->value = result;
232                        if(result)
233                            printf(" %s\n", el->data->field->identifier);
234                    }
235                    break;
236
237                    /*
238                     * Hidden values are not displayed at all. This is useful
239                     * for reserved fields or information that you don't care
240                     * about but need to read in order to get to the rest of
241                     * the header
242                     */
243                    case DISPLAY_NONE:
244                    {
245                        result = fix_byteorder(result, 
246                                el->data->field->order, 
247                                el->data->field->size);
248                        el->data->field->value = result;
249                    }
250                    break;
251                };
252
253                break;
254
255            case NEXTHEADER:
256                /*
257                 * Before we move on to the next header, make sure our packet
258                 * pointer is pointing to the first unused bytes. This may
259                 * mean we have to backtrack to some that were put into the
260                 * buffer but weren't used.
261                 * - This wouldn't be a problem if all future output came
262                 * from this buffer, but there is a good chance we will use
263                 * some code from a shared library to output packet info
264                 * instead, and this doesn't have access to the buffer.
265                 */
266                packet = packet - (bits / 8);
267                len = len + (bits / 8);
268                bits = 0;
269                buffer = 0;
270
271                decode_next(packet, len, el->data->nextheader->prefix, 
272                        ntohs(el->data->nextheader->target->value));
273                break;
274        };
275       
276        el = el->next;
277    }
278    buffer = 0;
279    bits = 0;
280
281}
282
283
284
285
286
287
288
289
290int yyerror(const char *s)
291{
292    element_t *tmp;
293   
294    fprintf(stderr, "XXX %s\n"
295                    "XXX %s on line %d\n"
296                    "XXX Falling back to generic_decode()\n", 
297                    file, s, lines);
298    /*
299     * Clear the list so we don't do partial matching...makes it a bit
300     * more obvious that something is broken perhaps.
301     * XXX Not sure if it is better to parse none of the packet, or part
302     * of the packet in the event of error? Feel free to remove this if
303     * that is desired.
304     */
305
306    while(el_list != NULL)
307    {
308        tmp = el_list;
309        el_list = el_list->next;
310
311        switch(tmp->type)
312        {
313            case FIELD: free(tmp->data->field); break;
314            case NEXTHEADER: free(tmp->data->nextheader); break;
315        }
316        free(tmp->data);       
317        free(tmp);
318        printf("deleting...\n");
319    }
320
321    return 0;
322}
323
324/*
325 * Could be shortcut with a pointer to the tail...
326 */
327element_t* append(element_t *list, element_t *item)
328{
329    if(list == NULL)
330        return item;
331
332    list->next = append(list->next, item);
333    return list;
334}
335/*
336 * Testing...
337 */
338void print_list(element_t *list)
339{
340    if(list == NULL)
341        return;
342       
343    switch(list->type)
344    {
345        case NEXTHEADER: printf("*Nextheader, prefix='%s', target='%s'\n", 
346                            list->data->nextheader->prefix, 
347                            list->data->nextheader->fieldname);
348                            break;
349       
350        case FIELD: printf("*Field, order = '%d', size = '%d', "
351                            "display='%d', name='%s'\n",
352                            list->data->field->order, 
353                            list->data->field->size, 
354                            list->data->field->display,
355                            list->data->field->identifier);
356                            break;
357    };
358    /*printf("%s\n", list->data->identifier); */
359    print_list(list->next);
360}
361#ifdef TEST
362#include <stdio.h>
363int main(void)
364{
365        unsigned char mybuffer[] = { 0x01, 0x82, 0x03, 0x04, 0x05, 0x06 };
366        void *buf = mybuffer;
367        int len=sizeof(buffer);
368        printf("8bits=%"PRIx64"\n",getbit(&buf,&len,8));
369        printf("2bits=%"PRIx64"\n",getbit(&buf,&len,2));
370        return 0;
371}
372#endif
Note: See TracBrowser for help on using the repository browser.