~ubuntu-branches/ubuntu/precise/tcpdump/precise-updates

« back to all changes in this revision

Viewing changes to print-olsr.c

  • Committer: Bazaar Package Importer
  • Author(s): Romain Francoise
  • Date: 2008-03-08 19:24:02 UTC
  • mfrom: (6.1.3 hardy)
  • Revision ID: james.westby@ubuntu.com-20080308192402-9n7erk2yyyd5mpt3
Tags: 3.9.8-4
debian/control: Build-Depend on libpcap0.8-dev (>= 0.9.3),
not (>= 0.9.3-1).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 1998-2007 The TCPDUMP project
 
3
 *
 
4
 * Redistribution and use in source and binary forms, with or without
 
5
 * modification, are permitted provided that: (1) source code
 
6
 * distributions retain the above copyright notice and this paragraph
 
7
 * in its entirety, and (2) distributions including binary code include
 
8
 * the above copyright notice and this paragraph in its entirety in
 
9
 * the documentation or other materials provided with the distribution.
 
10
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
 
11
 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
 
12
 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 
13
 * FOR A PARTICULAR PURPOSE.
 
14
 *
 
15
 * Optimized Link State Protocl (OLSR) as per rfc3626
 
16
 *
 
17
 * Original code by Hannes Gredler <hannes@juniper.net>
 
18
 */
 
19
 
 
20
#ifdef HAVE_CONFIG_H
 
21
#include "config.h"
 
22
#endif
 
23
 
 
24
#include <tcpdump-stdinc.h>
 
25
 
 
26
#include <stdio.h>
 
27
#include <string.h>
 
28
 
 
29
#include "interface.h"
 
30
#include "addrtoname.h"
 
31
#include "extract.h"            
 
32
#include "ip.h"
 
33
 
 
34
/*
 
35
 * RFC 3626 common header
 
36
 *
 
37
 *  0                   1                   2                   3
 
38
 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 
39
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
40
 * |         Packet Length         |    Packet Sequence Number     |
 
41
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
42
 * |  Message Type |     Vtime     |         Message Size          |
 
43
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
44
 * |                      Originator Address                       |
 
45
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
46
 * |  Time To Live |   Hop Count   |    Message Sequence Number    |
 
47
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
48
 * |                                                               |
 
49
 * :                            MESSAGE                            :
 
50
 * |                                                               |
 
51
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
52
 * |  Message Type |     Vtime     |         Message Size          |
 
53
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
54
 * |                      Originator Address                       |
 
55
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
56
 * |  Time To Live |   Hop Count   |    Message Sequence Number    |
 
57
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
58
 * |                                                               |
 
59
 * :                            MESSAGE                            :
 
60
 * |                                                               |
 
61
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
62
 * :                                                               :
 
63
 */
 
64
 
 
65
struct olsr_common {
 
66
    u_int8_t packet_len[2];
 
67
    u_int8_t packet_seq[2];
 
68
};
 
69
 
 
70
#define OLSR_HELLO_MSG         1 /* rfc3626 */
 
71
#define OLSR_TC_MSG            2 /* rfc3626 */
 
72
#define OLSR_MID_MSG           3 /* rfc3626 */
 
73
#define OLSR_HNA_MSG           4 /* rfc3626 */
 
74
#define OLSR_POWERINFO_MSG   128
 
75
#define OLSR_NAMESERVICE_MSG 130
 
76
#define OLSR_HELLO_LQ_MSG    201 /* LQ extensions olsr.org */
 
77
#define OLSR_TC_LQ_MSG       202 /* LQ extensions olsr.org */
 
78
 
 
79
static struct tok olsr_msg_values[] = {
 
80
    { OLSR_HELLO_MSG, "Hello" },
 
81
    { OLSR_TC_MSG, "TC" },
 
82
    { OLSR_MID_MSG, "MID" },
 
83
    { OLSR_HNA_MSG, "HNA" },
 
84
    { OLSR_POWERINFO_MSG, "Powerinfo" },
 
85
    { OLSR_NAMESERVICE_MSG, "Nameservice" },
 
86
    { OLSR_HELLO_LQ_MSG, "Hello-LQ" },
 
87
    { OLSR_TC_LQ_MSG, "TC-LQ" },
 
88
    { 0, NULL}
 
89
};
 
90
 
 
91
struct olsr_msg {
 
92
    u_int8_t msg_type;
 
93
    u_int8_t vtime;
 
94
    u_int8_t msg_len[2];
 
95
    u_int8_t originator[4];
 
96
    u_int8_t ttl;
 
97
    u_int8_t hopcount;
 
98
    u_int8_t msg_seq[2];
 
99
};
 
100
 
 
101
struct olsr_hello {
 
102
    u_int8_t res[2];
 
103
    u_int8_t htime;
 
104
    u_int8_t will;
 
105
};
 
106
 
 
107
struct olsr_hello_link {
 
108
    u_int8_t link_code;
 
109
    u_int8_t res;
 
110
    u_int8_t len[2];
 
111
};
 
112
 
 
113
struct olsr_tc {
 
114
    u_int8_t ans_seq[2];
 
115
    u_int8_t res[2];
 
116
};
 
117
 
 
118
struct olsr_hna {
 
119
    u_int8_t network[4];
 
120
    u_int8_t mask[4];
 
121
};
 
122
 
 
123
 
 
124
#define OLSR_EXTRACT_LINK_TYPE(link_code) (link_code & 0x3)
 
125
#define OLSR_EXTRACT_NEIGHBOR_TYPE(link_code) (link_code >> 2)
 
126
 
 
127
static struct tok olsr_link_type_values[] = {
 
128
    { 0, "Unspecified" },
 
129
    { 1, "Asymmetric" },
 
130
    { 2, "Symmetric" },
 
131
    { 3, "Lost" },
 
132
    { 0, NULL}
 
133
};
 
134
 
 
135
static struct tok olsr_neighbor_type_values[] = {
 
136
    { 0, "Not-Neighbor" },
 
137
    { 1, "Symmetric" },
 
138
    { 2, "Symmetric-MPR" },
 
139
    { 0, NULL}
 
140
};
 
141
 
 
142
struct olsr_lq_neighbor {
 
143
    u_int8_t neighbor[4];
 
144
    u_int8_t link_quality;
 
145
    u_int8_t neighbor_link_quality;
 
146
    u_int8_t res[2];
 
147
};
 
148
 
 
149
/*
 
150
 * macro to convert the 8-bit mantissa/exponent to a double float
 
151
 * taken from olsr.org.
 
152
 */
 
153
#define VTIME_SCALE_FACTOR    0.0625
 
154
#define ME_TO_DOUBLE(me) \
 
155
  (double)(VTIME_SCALE_FACTOR*(1+(double)(me>>4)/16)*(double)(1<<(me&0x0F)))
 
156
 
 
157
/*
 
158
 * print a neighbor list with LQ extensions.
 
159
 */
 
160
static void
 
161
olsr_print_lq_neighbor (const u_char *msg_data, u_int hello_len)
 
162
{
 
163
    struct olsr_lq_neighbor *lq_neighbor;
 
164
 
 
165
    while (hello_len >= sizeof(struct olsr_lq_neighbor)) {
 
166
 
 
167
        lq_neighbor = (struct olsr_lq_neighbor *)msg_data;
 
168
 
 
169
        printf("\n\t      neighbor %s, link-quality %.2lf%%"
 
170
               ", neighbor-link-quality %.2lf%%",
 
171
               ipaddr_string(lq_neighbor->neighbor),
 
172
               ((double)lq_neighbor->link_quality/2.55),
 
173
               ((double)lq_neighbor->neighbor_link_quality/2.55));
 
174
 
 
175
        msg_data += sizeof(struct olsr_lq_neighbor);
 
176
        hello_len -= sizeof(struct olsr_lq_neighbor);
 
177
    }
 
178
}
 
179
 
 
180
/*
 
181
 * print a neighbor list.
 
182
 */
 
183
static void
 
184
olsr_print_neighbor (const u_char *msg_data, u_int hello_len)
 
185
{
 
186
    int neighbor;
 
187
 
 
188
    printf("\n\t      neighbor\n\t\t");
 
189
    neighbor = 1;
 
190
 
 
191
    while (hello_len >= sizeof(struct in_addr)) {
 
192
 
 
193
        /* print 4 neighbors per line */
 
194
 
 
195
        printf("%s%s", ipaddr_string(msg_data),
 
196
               neighbor % 4 == 0 ? "\n\t\t" : " ");
 
197
 
 
198
        msg_data += sizeof(struct in_addr);
 
199
        hello_len -= sizeof(struct in_addr);
 
200
    }
 
201
}
 
202
 
 
203
 
 
204
void
 
205
olsr_print (const u_char *pptr, u_int length)
 
206
{
 
207
    union {
 
208
        const struct olsr_common *common;
 
209
        const struct olsr_msg *msg;
 
210
        const struct olsr_hello *hello;
 
211
        const struct olsr_hello_link *hello_link;
 
212
        const struct olsr_lq_neighbor *lq_neighbor;
 
213
        const struct olsr_tc *tc;
 
214
        const struct olsr_hna *hna;
 
215
    } ptr;
 
216
 
 
217
    u_int msg_type, msg_len, msg_tlen, hello_len, prefix;
 
218
    u_int8_t link_type, neighbor_type;
 
219
    const u_char *tptr, *msg_data;
 
220
 
 
221
    tptr = pptr; 
 
222
 
 
223
    if (length < sizeof(struct olsr_common)) {
 
224
        goto trunc;
 
225
    }
 
226
 
 
227
    if (!TTEST2(*tptr, sizeof(struct olsr_common))) {
 
228
        goto trunc;
 
229
    }
 
230
 
 
231
    ptr.common = (struct olsr_common *)tptr;
 
232
    length = MIN(length, EXTRACT_16BITS(ptr.common->packet_len));
 
233
 
 
234
    printf("OLSR, seq 0x%04x, length %u",
 
235
           EXTRACT_16BITS(ptr.common->packet_seq),
 
236
           length);
 
237
 
 
238
    tptr += sizeof(struct olsr_common);
 
239
 
 
240
    /*
 
241
     * In non-verbose mode, just print version.
 
242
     */
 
243
    if (vflag < 1) {
 
244
        return;
 
245
    }
 
246
 
 
247
    while (tptr < (pptr+length)) {
 
248
 
 
249
        if (!TTEST2(*tptr, sizeof(struct olsr_msg)))    
 
250
            goto trunc;
 
251
 
 
252
        ptr.msg = (struct olsr_msg *)tptr;
 
253
 
 
254
        msg_type = ptr.msg->msg_type;
 
255
        msg_len = EXTRACT_16BITS(ptr.msg->msg_len);
 
256
 
 
257
        /* infinite loop check */
 
258
        if (msg_type == 0 || msg_len == 0) {
 
259
            return;
 
260
        }
 
261
 
 
262
        printf("\n\t%s Message (%u), originator %s, ttl %u, hop %u"
 
263
               "\n\t  vtime %.3lfs, msg-seq 0x%04x, length %u",
 
264
               tok2str(olsr_msg_values, "Unknown", msg_type),
 
265
               msg_type, ipaddr_string(ptr.msg->originator),
 
266
               ptr.msg->ttl,
 
267
               ptr.msg->hopcount,
 
268
               ME_TO_DOUBLE(ptr.msg->vtime),
 
269
               EXTRACT_16BITS(ptr.msg->msg_seq),
 
270
               msg_len);
 
271
 
 
272
        msg_tlen = msg_len - sizeof(struct olsr_msg);
 
273
        msg_data = tptr + sizeof(struct olsr_msg);
 
274
 
 
275
        switch (msg_type) {
 
276
        case OLSR_HELLO_MSG:
 
277
        case OLSR_HELLO_LQ_MSG:
 
278
            if (!TTEST2(*msg_data, sizeof(struct olsr_hello)))  
 
279
                goto trunc;
 
280
 
 
281
            ptr.hello = (struct olsr_hello *)msg_data;
 
282
            printf("\n\t  hello-time %.3lfs, MPR willingness %u",
 
283
                   ME_TO_DOUBLE(ptr.hello->htime), ptr.hello->will);
 
284
            msg_data += sizeof(struct olsr_hello);
 
285
            msg_tlen -= sizeof(struct olsr_hello);
 
286
 
 
287
            while (msg_tlen >= sizeof(struct olsr_hello_link)) {
 
288
 
 
289
                /*
 
290
                 * link-type.
 
291
                 */
 
292
                if (!TTEST2(*msg_data, sizeof(struct olsr_hello_link))) 
 
293
                    goto trunc;
 
294
 
 
295
                ptr.hello_link = (struct olsr_hello_link *)msg_data;
 
296
 
 
297
                hello_len = EXTRACT_16BITS(ptr.hello_link->len);
 
298
                link_type = OLSR_EXTRACT_LINK_TYPE(ptr.hello_link->link_code);
 
299
                neighbor_type = OLSR_EXTRACT_NEIGHBOR_TYPE(ptr.hello_link->link_code);
 
300
 
 
301
                printf("\n\t    link-type %s, neighbor-type %s, len %u",
 
302
                       tok2str(olsr_link_type_values, "Unknown", link_type),
 
303
                       tok2str(olsr_neighbor_type_values, "Unknown", neighbor_type),
 
304
                       hello_len);
 
305
 
 
306
                msg_data += sizeof(struct olsr_hello_link);
 
307
                msg_tlen -= sizeof(struct olsr_hello_link);
 
308
                hello_len -= sizeof(struct olsr_hello_link);
 
309
 
 
310
                if (msg_type == OLSR_HELLO_MSG) {
 
311
                    olsr_print_neighbor(msg_data, hello_len);
 
312
                } else {
 
313
                    olsr_print_lq_neighbor(msg_data, hello_len);
 
314
                }
 
315
 
 
316
                msg_data += hello_len;
 
317
                msg_tlen -= hello_len;
 
318
            }
 
319
            break;
 
320
 
 
321
        case OLSR_TC_MSG:
 
322
        case OLSR_TC_LQ_MSG:
 
323
            if (!TTEST2(*msg_data, sizeof(struct olsr_tc)))     
 
324
                goto trunc;
 
325
 
 
326
            ptr.tc = (struct olsr_tc *)msg_data;
 
327
            printf("\n\t    advertised neighbor seq 0x%04x",
 
328
                   EXTRACT_16BITS(ptr.tc->ans_seq));
 
329
            msg_data += sizeof(struct olsr_tc);
 
330
            msg_tlen -= sizeof(struct olsr_tc);
 
331
 
 
332
            if (msg_type == OLSR_TC_MSG) {
 
333
                olsr_print_neighbor(msg_data, msg_tlen);
 
334
            } else {
 
335
                olsr_print_lq_neighbor(msg_data, msg_tlen);
 
336
            }
 
337
            break;
 
338
 
 
339
        case OLSR_MID_MSG:
 
340
            if (!TTEST2(*msg_data, sizeof(struct in_addr)))     
 
341
                goto trunc;
 
342
 
 
343
            while (msg_tlen >= sizeof(struct in_addr)) {
 
344
                printf("\n\t  interface address %s", ipaddr_string(msg_data));
 
345
                msg_data += sizeof(struct in_addr);
 
346
                msg_tlen -= sizeof(struct in_addr);
 
347
            }
 
348
            break;
 
349
 
 
350
        case OLSR_HNA_MSG:
 
351
            prefix = 1;
 
352
            printf("\n\t  advertised networks\n\t    ");
 
353
            while (msg_tlen >= sizeof(struct olsr_hna)) {
 
354
                if (!TTEST2(*msg_data, sizeof(struct olsr_hna)))        
 
355
                    goto trunc;
 
356
 
 
357
                ptr.hna = (struct olsr_hna *)msg_data;
 
358
 
 
359
                /* print 4 prefixes per line */
 
360
 
 
361
                printf("%s/%u%s",
 
362
                       ipaddr_string(ptr.hna->network),
 
363
                       mask2plen(EXTRACT_32BITS(ptr.hna->mask)),                       
 
364
                       prefix % 4 == 0 ? "\n\t    " : " ");
 
365
 
 
366
                msg_data += sizeof(struct olsr_hna);
 
367
                msg_tlen -= sizeof(struct olsr_hna);
 
368
                prefix ++;
 
369
            }
 
370
            break;
 
371
 
 
372
            /*
 
373
             * FIXME those are the defined messages that lack a decoder
 
374
             * you are welcome to contribute code ;-)
 
375
             */
 
376
 
 
377
        case OLSR_POWERINFO_MSG:
 
378
        case OLSR_NAMESERVICE_MSG:
 
379
        default:
 
380
            print_unknown_data(msg_data, "\n\t    ", msg_tlen);
 
381
            break;
 
382
        }       
 
383
        tptr += msg_len;
 
384
    }
 
385
 
 
386
    return;
 
387
 
 
388
 trunc:
 
389
    printf("[|olsr]");
 
390
}
 
391
 
 
392
/*
 
393
 * Local Variables:
 
394
 * c-style: whitesmith
 
395
 * c-basic-offset: 4
 
396
 * End:
 
397
 */