1 /*
2  * Copyright (c) 2007-2011 Grégoire Henry, Juliusz Chroboczek
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  * 3. Neither the name of the project nor the names of its contributors
13  *    may be used to endorse or promote products derived from this software
14  *    without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 
33 #include <tcpdump-stdinc.h>
34 
35 #include <stdio.h>
36 #include <string.h>
37 
38 #include "addrtoname.h"
39 #include "interface.h"
40 #include "extract.h"
41 
42 static void babel_print_v2(const u_char *cp, u_int length);
43 
44 void
babel_print(const u_char * cp,u_int length)45 babel_print(const u_char *cp, u_int length) {
46     printf("babel");
47 
48     TCHECK2(*cp, 4);
49 
50     if(cp[0] != 42) {
51         printf(" malformed header");
52         return;
53     } else {
54         printf(" %d", cp[1]);
55     }
56 
57     switch(cp[1]) {
58     case 2:
59         babel_print_v2(cp,length);
60         break;
61     default:
62         printf(" unknown version");
63         break;
64     }
65 
66     return;
67 
68  trunc:
69     printf(" [|babel]");
70     return;
71 }
72 
73 /* TLVs */
74 #define MESSAGE_PAD1 0
75 #define MESSAGE_PADN 1
76 #define MESSAGE_ACK_REQ 2
77 #define MESSAGE_ACK 3
78 #define MESSAGE_HELLO 4
79 #define MESSAGE_IHU 5
80 #define MESSAGE_ROUTER_ID 6
81 #define MESSAGE_NH 7
82 #define MESSAGE_UPDATE 8
83 #define MESSAGE_REQUEST 9
84 #define MESSAGE_MH_REQUEST 10
85 #define MESSAGE_TSPC 11
86 #define MESSAGE_HMAC 12
87 
88 /* sub-TLVs */
89 #define MESSAGE_SUB_PAD1 0
90 #define MESSAGE_SUB_PADN 1
91 #define MESSAGE_SUB_DIVERSITY 2
92 
93 /* Diversity sub-TLV channel codes */
94 static const struct tok diversity_str[] = {
95     { 0,   "reserved" },
96     { 255, "all"      },
97     { 0, NULL }
98 };
99 
100 static const char *
format_id(const u_char * id)101 format_id(const u_char *id)
102 {
103     static char buf[25];
104     snprintf(buf, 25, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
105              id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7]);
106     buf[24] = '\0';
107     return buf;
108 }
109 
110 static const unsigned char v4prefix[16] =
111     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
112 
113 static const char *
format_prefix(const u_char * prefix,unsigned char plen)114 format_prefix(const u_char *prefix, unsigned char plen)
115 {
116     static char buf[50];
117     if(plen >= 96 && memcmp(prefix, v4prefix, 12) == 0)
118         snprintf(buf, 50, "%s/%u", ipaddr_string(prefix + 12), plen - 96);
119     else
120 #ifdef INET6
121         snprintf(buf, 50, "%s/%u", ip6addr_string(prefix), plen);
122 #else
123         snprintf(buf, 50, "IPv6 addresses not supported");
124 #endif
125     buf[49] = '\0';
126     return buf;
127 }
128 
129 static const char *
format_address(const u_char * prefix)130 format_address(const u_char *prefix)
131 {
132     if(memcmp(prefix, v4prefix, 12) == 0)
133         return ipaddr_string(prefix + 12);
134     else
135 #ifdef INET6
136         return ip6addr_string(prefix);
137 #else
138         return "IPv6 addresses not supported";
139 #endif
140 }
141 
142 static const char *
format_interval(const u_int16_t i)143 format_interval(const u_int16_t i)
144 {
145     static char buf[sizeof("0000.0s")];
146 
147     if (i == 0)
148         return "0.0s (bogus)";
149     snprintf(buf, sizeof(buf), "%u.%us", i / 10, i % 10);
150     return buf;
151 }
152 
153 static const char *
format_interval_update(const u_int16_t i)154 format_interval_update(const u_int16_t i)
155 {
156     return i == 0xFFFF ? "infinity" : format_interval(i);
157 }
158 
159 /* Return number of octets consumed from the input buffer (not the prefix length
160  * in bytes), or -1 for encoding error. */
161 static int
network_prefix(int ae,int plen,unsigned int omitted,const unsigned char * p,const unsigned char * dp,unsigned int len,unsigned char * p_r)162 network_prefix(int ae, int plen, unsigned int omitted,
163                const unsigned char *p, const unsigned char *dp,
164                unsigned int len, unsigned char *p_r)
165 {
166     unsigned pb;
167     unsigned char prefix[16];
168     int consumed = 0;
169 
170     if(plen >= 0)
171         pb = (plen + 7) / 8;
172     else if(ae == 1)
173         pb = 4;
174     else
175         pb = 16;
176 
177     if(pb > 16)
178         return -1;
179 
180     memset(prefix, 0, 16);
181 
182     switch(ae) {
183     case 0: break;
184     case 1:
185         if(omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted))
186             return -1;
187         memcpy(prefix, v4prefix, 12);
188         if(omitted) {
189             if (dp == NULL) return -1;
190             memcpy(prefix, dp, 12 + omitted);
191         }
192         if(pb > omitted) {
193             memcpy(prefix + 12 + omitted, p, pb - omitted);
194             consumed = pb - omitted;
195         }
196         break;
197     case 2:
198         if(omitted > 16 || (pb > omitted && len < pb - omitted))
199             return -1;
200         if(omitted) {
201             if (dp == NULL) return -1;
202             memcpy(prefix, dp, omitted);
203         }
204         if(pb > omitted) {
205             memcpy(prefix + omitted, p, pb - omitted);
206             consumed = pb - omitted;
207         }
208         break;
209     case 3:
210         if(pb > 8 && len < pb - 8) return -1;
211         prefix[0] = 0xfe;
212         prefix[1] = 0x80;
213         if(pb > 8) {
214             memcpy(prefix + 8, p, pb - 8);
215             consumed = pb - 8;
216         }
217         break;
218     default:
219         return -1;
220     }
221 
222     memcpy(p_r, prefix, 16);
223     return consumed;
224 }
225 
226 static int
network_address(int ae,const unsigned char * a,unsigned int len,unsigned char * a_r)227 network_address(int ae, const unsigned char *a, unsigned int len,
228                 unsigned char *a_r)
229 {
230     return network_prefix(ae, -1, 0, a, NULL, len, a_r);
231 }
232 
233 /*
234  * Sub-TLVs consume the "extra data" of Babel TLVs (see Section 4.3 of RFC6126),
235  * their encoding is similar to the encoding of TLVs, but the type namespace is
236  * different:
237  *
238  * o Type 0 stands for Pad1 sub-TLV with the same encoding as the Pad1 TLV.
239  * o Type 1 stands for PadN sub-TLV with the same encoding as the PadN TLV.
240  * o Type 2 stands for Diversity sub-TLV, which propagates diversity routing
241  *   data. Its body is a variable-length sequence of 8-bit unsigned integers,
242  *   each representing per-hop number of interferring radio channel for the
243  *   prefix. Channel 0 is invalid and must not be used in the sub-TLV, channel
244  *   255 interferes with any other channel.
245  *
246  * Sub-TLV types 0 and 1 are valid for any TLV type, whether sub-TLV type 2 is
247  * only valid for TLV type 8 (Update). Note that within an Update TLV a missing
248  * Diversity sub-TLV is not the same as a Diversity sub-TLV with an empty body.
249  * The former would mean a lack of any claims about the interference, and the
250  * latter would state that interference is definitely absent. */
251 static void
subtlvs_print(const u_char * cp,const u_char * ep,const uint8_t tlv_type)252 subtlvs_print(const u_char *cp, const u_char *ep, const uint8_t tlv_type) {
253     uint8_t subtype, sublen;
254     const char *sep;
255 
256     while (cp < ep) {
257         subtype = *cp++;
258         if(subtype == MESSAGE_SUB_PAD1) {
259             printf(" sub-pad1");
260             continue;
261         }
262         if(cp == ep)
263             goto corrupt;
264         sublen = *cp++;
265         if(cp + sublen > ep)
266             goto corrupt;
267 
268         switch(subtype) {
269         case MESSAGE_SUB_PADN:
270             printf(" sub-padn");
271             cp += sublen;
272             break;
273         case MESSAGE_SUB_DIVERSITY:
274             printf(" sub-diversity");
275             if (sublen == 0) {
276                 printf(" empty");
277                 break;
278             }
279             sep = " ";
280             while(sublen--) {
281                 printf("%s%s", sep, tok2str(diversity_str, "%u", *cp++));
282                 sep = "-";
283             }
284             if(tlv_type != MESSAGE_UPDATE)
285                 printf(" (bogus)");
286             break;
287         default:
288             printf(" sub-unknown-0x%02x", subtype);
289             cp += sublen;
290         } /* switch */
291     } /* while */
292     return;
293 
294  corrupt:
295     printf(" (corrupt)");
296 }
297 
298 #define ICHECK(i, l) \
299 	if ((i) + (l) > bodylen || (i) + (l) > length) goto corrupt;
300 
301 static void
babel_print_v2(const u_char * cp,u_int length)302 babel_print_v2(const u_char *cp, u_int length) {
303     u_int i;
304     u_short bodylen;
305     u_char v4_prefix[16] =
306         {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
307     u_char v6_prefix[16] = {0};
308 
309     TCHECK2(*cp, 4);
310     if (length < 4)
311         goto corrupt;
312     bodylen = EXTRACT_16BITS(cp + 2);
313     printf(" (%u)", bodylen);
314 
315     /* Process the TLVs in the body */
316     i = 0;
317     while(i < bodylen) {
318         const u_char *message;
319         u_int type, len;
320 
321         message = cp + 4 + i;
322 
323         TCHECK2(*message, 1);
324         if((type = message[0]) == MESSAGE_PAD1) {
325             printf(vflag ? "\n\tPad 1" : " pad1");
326             i += 1;
327             continue;
328         }
329 
330         TCHECK2(*message, 2);
331         ICHECK(i, 2);
332         len = message[1];
333 
334         TCHECK2(*message, 2 + len);
335         ICHECK(i, 2 + len);
336 
337         switch(type) {
338         case MESSAGE_PADN: {
339             if(!vflag)
340                 printf(" padN");
341             else
342                 printf("\n\tPad %d", len + 2);
343         }
344             break;
345 
346         case MESSAGE_ACK_REQ: {
347             u_short nonce, interval;
348             if(!vflag)
349                 printf(" ack-req");
350             else {
351                 printf("\n\tAcknowledgment Request ");
352                 if(len < 6) goto corrupt;
353                 nonce = EXTRACT_16BITS(message + 4);
354                 interval = EXTRACT_16BITS(message + 6);
355                 printf("%04x %s", nonce, format_interval(interval));
356             }
357         }
358             break;
359 
360         case MESSAGE_ACK: {
361             u_short nonce;
362             if(!vflag)
363                 printf(" ack");
364             else {
365                 printf("\n\tAcknowledgment ");
366                 if(len < 2) goto corrupt;
367                 nonce = EXTRACT_16BITS(message + 2);
368                 printf("%04x", nonce);
369             }
370         }
371             break;
372 
373         case MESSAGE_HELLO:  {
374             u_short seqno, interval;
375             if(!vflag)
376                 printf(" hello");
377             else {
378                 printf("\n\tHello ");
379                 if(len < 6) goto corrupt;
380                 seqno = EXTRACT_16BITS(message + 4);
381                 interval = EXTRACT_16BITS(message + 6);
382                 printf("seqno %u interval %s", seqno, format_interval(interval));
383             }
384         }
385             break;
386 
387         case MESSAGE_IHU: {
388             unsigned short txcost, interval;
389             if(!vflag)
390                 printf(" ihu");
391             else {
392                 u_char address[16];
393                 int rc;
394                 printf("\n\tIHU ");
395                 if(len < 6) goto corrupt;
396                 txcost = EXTRACT_16BITS(message + 4);
397                 interval = EXTRACT_16BITS(message + 6);
398                 rc = network_address(message[2], message + 8, len - 6, address);
399                 if(rc < 0) { printf("[|babel]"); break; }
400                 printf("%s txcost %u interval %s",
401                        format_address(address), txcost, format_interval(interval));
402             }
403         }
404             break;
405 
406         case MESSAGE_ROUTER_ID: {
407             if(!vflag)
408                 printf(" router-id");
409             else {
410                 printf("\n\tRouter Id");
411                 if(len < 10) goto corrupt;
412                 printf(" %s", format_id(message + 4));
413             }
414         }
415             break;
416 
417         case MESSAGE_NH: {
418             if(!vflag)
419                 printf(" nh");
420             else {
421                 int rc;
422                 u_char nh[16];
423                 printf("\n\tNext Hop");
424                 if(len < 2) goto corrupt;
425                 rc = network_address(message[2], message + 4, len - 2, nh);
426                 if(rc < 0) goto corrupt;
427                 printf(" %s", format_address(nh));
428             }
429         }
430             break;
431 
432         case MESSAGE_UPDATE: {
433             if(!vflag) {
434                 printf(" update");
435                 if(len < 1)
436                     printf("/truncated");
437                 else
438                     printf("%s%s%s",
439                            (message[3] & 0x80) ? "/prefix": "",
440                            (message[3] & 0x40) ? "/id" : "",
441                            (message[3] & 0x3f) ? "/unknown" : "");
442             } else {
443                 u_short interval, seqno, metric;
444                 u_char plen;
445                 int rc;
446                 u_char prefix[16];
447                 printf("\n\tUpdate");
448                 if(len < 10) goto corrupt;
449                 plen = message[4] + (message[2] == 1 ? 96 : 0);
450                 rc = network_prefix(message[2], message[4], message[5],
451                                     message + 12,
452                                     message[2] == 1 ? v4_prefix : v6_prefix,
453                                     len - 10, prefix);
454                 if(rc < 0) goto corrupt;
455                 interval = EXTRACT_16BITS(message + 6);
456                 seqno = EXTRACT_16BITS(message + 8);
457                 metric = EXTRACT_16BITS(message + 10);
458                 printf("%s%s%s %s metric %u seqno %u interval %s",
459                        (message[3] & 0x80) ? "/prefix": "",
460                        (message[3] & 0x40) ? "/id" : "",
461                        (message[3] & 0x3f) ? "/unknown" : "",
462                        format_prefix(prefix, plen),
463                        metric, seqno, format_interval_update(interval));
464                 if(message[3] & 0x80) {
465                     if(message[2] == 1)
466                         memcpy(v4_prefix, prefix, 16);
467                     else
468                         memcpy(v6_prefix, prefix, 16);
469                 }
470                 /* extra data? */
471                 if((u_int)rc < len - 10)
472                     subtlvs_print(message + 12 + rc, message + 2 + len, type);
473             }
474         }
475             break;
476 
477         case MESSAGE_REQUEST: {
478             if(!vflag)
479                 printf(" request");
480             else {
481                 int rc;
482                 u_char prefix[16], plen;
483                 printf("\n\tRequest ");
484                 if(len < 2) goto corrupt;
485                 plen = message[3] + (message[2] == 1 ? 96 : 0);
486                 rc = network_prefix(message[2], message[3], 0,
487                                     message + 4, NULL, len - 2, prefix);
488                 if(rc < 0) goto corrupt;
489                 plen = message[3] + (message[2] == 1 ? 96 : 0);
490                 printf("for %s",
491                        message[2] == 0 ? "any" : format_prefix(prefix, plen));
492             }
493         }
494             break;
495 
496         case MESSAGE_MH_REQUEST : {
497             if(!vflag)
498                 printf(" mh-request");
499             else {
500                 int rc;
501                 u_short seqno;
502                 u_char prefix[16], plen;
503                 printf("\n\tMH-Request ");
504                 if(len < 14) goto corrupt;
505                 seqno = EXTRACT_16BITS(message + 4);
506                 rc = network_prefix(message[2], message[3], 0,
507                                     message + 16, NULL, len - 14, prefix);
508                 if(rc < 0) goto corrupt;
509                 plen = message[3] + (message[2] == 1 ? 96 : 0);
510                 printf("(%u hops) for %s seqno %u id %s",
511                        message[6], format_prefix(prefix, plen),
512                        seqno, format_id(message + 8));
513             }
514         }
515             break;
516         case MESSAGE_TSPC :
517             if(!vflag)
518                 printf(" tspc");
519             else {
520                 printf("\n\tTS/PC ");
521                 if(len < 6) goto corrupt;
522                 printf("timestamp %u packetcounter %u", EXTRACT_32BITS (message + 4),
523                        EXTRACT_16BITS(message + 2));
524             }
525             break;
526         case MESSAGE_HMAC : {
527             if(!vflag)
528                 printf(" hmac");
529             else {
530                 unsigned j;
531                 printf("\n\tHMAC ");
532                 if(len < 18) goto corrupt;
533                 printf("key-id %u digest-%u ", EXTRACT_16BITS(message + 2), len - 2);
534                 for (j = 0; j < len - 2; j++)
535                     printf ("%02X", message[4 + j]);
536             }
537         }
538             break;
539         default:
540             if(!vflag)
541                 printf(" unknown");
542             else
543                 printf("\n\tUnknown message type %d", type);
544         }
545         i += len + 2;
546     }
547     return;
548 
549  trunc:
550     printf(" [|babel]");
551     return;
552 
553  corrupt:
554     printf(" (corrupt)");
555     return;
556 }
557