source: libpacketdump/bitbuffer.c @ 11a7f9c

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 11a7f9c was 11a7f9c, checked in by Perry Lorier <perry@…>, 12 years ago

Constification

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