source: libpacketdump/bitbuffer.c @ eade363

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

Tidy up thousands of little warnings

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