xref: /freebsd/contrib/tcpdump/print-babel.c (revision d03c0883ad6dcda67e9281df01f1940292dee669)
1cac3dcd5SXin LI /*
2cac3dcd5SXin LI  * Copyright (c) 2007-2011 Grégoire Henry, Juliusz Chroboczek
3cac3dcd5SXin LI  *
4cac3dcd5SXin LI  * Redistribution and use in source and binary forms, with or without
5cac3dcd5SXin LI  * modification, are permitted provided that the following conditions
6cac3dcd5SXin LI  * are met:
7cac3dcd5SXin LI  * 1. Redistributions of source code must retain the above copyright
8cac3dcd5SXin LI  *    notice, this list of conditions and the following disclaimer.
9cac3dcd5SXin LI  * 2. Redistributions in binary form must reproduce the above copyright
10cac3dcd5SXin LI  *    notice, this list of conditions and the following disclaimer in the
11cac3dcd5SXin LI  *    documentation and/or other materials provided with the distribution.
12cac3dcd5SXin LI  * 3. Neither the name of the project nor the names of its contributors
13cac3dcd5SXin LI  *    may be used to endorse or promote products derived from this software
14cac3dcd5SXin LI  *    without specific prior written permission.
15cac3dcd5SXin LI  *
16cac3dcd5SXin LI  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
17cac3dcd5SXin LI  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18cac3dcd5SXin LI  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19cac3dcd5SXin LI  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
20cac3dcd5SXin LI  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21cac3dcd5SXin LI  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22cac3dcd5SXin LI  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23cac3dcd5SXin LI  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24cac3dcd5SXin LI  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25cac3dcd5SXin LI  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26cac3dcd5SXin LI  * SUCH DAMAGE.
27cac3dcd5SXin LI  */
28cac3dcd5SXin LI 
29cac3dcd5SXin LI #ifdef HAVE_CONFIG_H
30cac3dcd5SXin LI #include "config.h"
31cac3dcd5SXin LI #endif
32cac3dcd5SXin LI 
33cac3dcd5SXin LI #include <tcpdump-stdinc.h>
34cac3dcd5SXin LI 
35cac3dcd5SXin LI #include <stdio.h>
36cac3dcd5SXin LI #include <string.h>
37cac3dcd5SXin LI 
38cac3dcd5SXin LI #include "addrtoname.h"
39cac3dcd5SXin LI #include "interface.h"
40cac3dcd5SXin LI #include "extract.h"
41cac3dcd5SXin LI 
42cac3dcd5SXin LI static void babel_print_v2(const u_char *cp, u_int length);
43cac3dcd5SXin LI 
44cac3dcd5SXin LI void
45cac3dcd5SXin LI babel_print(const u_char *cp, u_int length) {
46cac3dcd5SXin LI     printf("babel");
47cac3dcd5SXin LI 
48cac3dcd5SXin LI     TCHECK2(*cp, 4);
49cac3dcd5SXin LI 
50cac3dcd5SXin LI     if(cp[0] != 42) {
51cac3dcd5SXin LI         printf(" malformed header");
52cac3dcd5SXin LI         return;
53cac3dcd5SXin LI     } else {
54cac3dcd5SXin LI         printf(" %d", cp[1]);
55cac3dcd5SXin LI     }
56cac3dcd5SXin LI 
57cac3dcd5SXin LI     switch(cp[1]) {
58cac3dcd5SXin LI     case 2:
59cac3dcd5SXin LI         babel_print_v2(cp,length);
60cac3dcd5SXin LI         break;
61cac3dcd5SXin LI     default:
62cac3dcd5SXin LI         printf(" unknown version");
63cac3dcd5SXin LI         break;
64cac3dcd5SXin LI     }
65cac3dcd5SXin LI 
66cac3dcd5SXin LI     return;
67cac3dcd5SXin LI 
68cac3dcd5SXin LI  trunc:
69cac3dcd5SXin LI     printf(" [|babel]");
70cac3dcd5SXin LI     return;
71cac3dcd5SXin LI }
72cac3dcd5SXin LI 
73cac3dcd5SXin LI #define MESSAGE_PAD1 0
74cac3dcd5SXin LI #define MESSAGE_PADN 1
75cac3dcd5SXin LI #define MESSAGE_ACK_REQ 2
76cac3dcd5SXin LI #define MESSAGE_ACK 3
77cac3dcd5SXin LI #define MESSAGE_HELLO 4
78cac3dcd5SXin LI #define MESSAGE_IHU 5
79cac3dcd5SXin LI #define MESSAGE_ROUTER_ID 6
80cac3dcd5SXin LI #define MESSAGE_NH 7
81cac3dcd5SXin LI #define MESSAGE_UPDATE 8
82cac3dcd5SXin LI #define MESSAGE_REQUEST 9
83cac3dcd5SXin LI #define MESSAGE_MH_REQUEST 10
84*d03c0883SXin LI #define MESSAGE_TSPC 11
85*d03c0883SXin LI #define MESSAGE_HMAC 12
86cac3dcd5SXin LI 
87cac3dcd5SXin LI static const char *
88cac3dcd5SXin LI format_id(const u_char *id)
89cac3dcd5SXin LI {
90cac3dcd5SXin LI     static char buf[25];
91cac3dcd5SXin LI     snprintf(buf, 25, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
92cac3dcd5SXin LI              id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7]);
93cac3dcd5SXin LI     buf[24] = '\0';
94cac3dcd5SXin LI     return buf;
95cac3dcd5SXin LI }
96cac3dcd5SXin LI 
97cac3dcd5SXin LI static const unsigned char v4prefix[16] =
98cac3dcd5SXin LI     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
99cac3dcd5SXin LI 
100cac3dcd5SXin LI static const char *
101cac3dcd5SXin LI format_prefix(const u_char *prefix, unsigned char plen)
102cac3dcd5SXin LI {
103cac3dcd5SXin LI     static char buf[50];
104cac3dcd5SXin LI     if(plen >= 96 && memcmp(prefix, v4prefix, 12) == 0)
105cac3dcd5SXin LI         snprintf(buf, 50, "%s/%u", ipaddr_string(prefix + 12), plen - 96);
106cac3dcd5SXin LI     else
107*d03c0883SXin LI #ifdef INET6
108cac3dcd5SXin LI         snprintf(buf, 50, "%s/%u", ip6addr_string(prefix), plen);
109*d03c0883SXin LI #else
110*d03c0883SXin LI         snprintf(buf, 50, "IPv6 addresses not supported");
111*d03c0883SXin LI #endif
112cac3dcd5SXin LI     buf[49] = '\0';
113cac3dcd5SXin LI     return buf;
114cac3dcd5SXin LI }
115cac3dcd5SXin LI 
116cac3dcd5SXin LI static const char *
117cac3dcd5SXin LI format_address(const u_char *prefix)
118cac3dcd5SXin LI {
119cac3dcd5SXin LI     if(memcmp(prefix, v4prefix, 12) == 0)
120cac3dcd5SXin LI         return ipaddr_string(prefix + 12);
121cac3dcd5SXin LI     else
122*d03c0883SXin LI #ifdef INET6
123cac3dcd5SXin LI         return ip6addr_string(prefix);
124*d03c0883SXin LI #else
125*d03c0883SXin LI         return "IPv6 addresses not supported";
126*d03c0883SXin LI #endif
127cac3dcd5SXin LI }
128cac3dcd5SXin LI 
129cac3dcd5SXin LI static int
130cac3dcd5SXin LI network_prefix(int ae, int plen, unsigned int omitted,
131cac3dcd5SXin LI                const unsigned char *p, const unsigned char *dp,
132cac3dcd5SXin LI                unsigned int len, unsigned char *p_r)
133cac3dcd5SXin LI {
134cac3dcd5SXin LI     unsigned pb;
135cac3dcd5SXin LI     unsigned char prefix[16];
136cac3dcd5SXin LI 
137cac3dcd5SXin LI     if(plen >= 0)
138cac3dcd5SXin LI         pb = (plen + 7) / 8;
139cac3dcd5SXin LI     else if(ae == 1)
140cac3dcd5SXin LI         pb = 4;
141cac3dcd5SXin LI     else
142cac3dcd5SXin LI         pb = 16;
143cac3dcd5SXin LI 
144cac3dcd5SXin LI     if(pb > 16)
145cac3dcd5SXin LI         return -1;
146cac3dcd5SXin LI 
147cac3dcd5SXin LI     memset(prefix, 0, 16);
148cac3dcd5SXin LI 
149cac3dcd5SXin LI     switch(ae) {
150cac3dcd5SXin LI     case 0: break;
151cac3dcd5SXin LI     case 1:
152cac3dcd5SXin LI         if(omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted))
153cac3dcd5SXin LI             return -1;
154cac3dcd5SXin LI         memcpy(prefix, v4prefix, 12);
155cac3dcd5SXin LI         if(omitted) {
156cac3dcd5SXin LI             if (dp == NULL) return -1;
157cac3dcd5SXin LI             memcpy(prefix, dp, 12 + omitted);
158cac3dcd5SXin LI         }
159cac3dcd5SXin LI         if(pb > omitted) memcpy(prefix + 12 + omitted, p, pb - omitted);
160cac3dcd5SXin LI         break;
161cac3dcd5SXin LI     case 2:
162cac3dcd5SXin LI         if(omitted > 16 || (pb > omitted && len < pb - omitted))
163cac3dcd5SXin LI             return -1;
164cac3dcd5SXin LI         if(omitted) {
165cac3dcd5SXin LI             if (dp == NULL) return -1;
166cac3dcd5SXin LI             memcpy(prefix, dp, omitted);
167cac3dcd5SXin LI         }
168cac3dcd5SXin LI         if(pb > omitted) memcpy(prefix + omitted, p, pb - omitted);
169cac3dcd5SXin LI         break;
170cac3dcd5SXin LI     case 3:
171cac3dcd5SXin LI         if(pb > 8 && len < pb - 8) return -1;
172cac3dcd5SXin LI         prefix[0] = 0xfe;
173cac3dcd5SXin LI         prefix[1] = 0x80;
174cac3dcd5SXin LI         if(pb > 8) memcpy(prefix + 8, p, pb - 8);
175cac3dcd5SXin LI         break;
176cac3dcd5SXin LI     default:
177cac3dcd5SXin LI         return -1;
178cac3dcd5SXin LI     }
179cac3dcd5SXin LI 
180cac3dcd5SXin LI     memcpy(p_r, prefix, 16);
181cac3dcd5SXin LI     return 1;
182cac3dcd5SXin LI }
183cac3dcd5SXin LI 
184cac3dcd5SXin LI static int
185cac3dcd5SXin LI network_address(int ae, const unsigned char *a, unsigned int len,
186cac3dcd5SXin LI                 unsigned char *a_r)
187cac3dcd5SXin LI {
188cac3dcd5SXin LI     return network_prefix(ae, -1, 0, a, NULL, len, a_r);
189cac3dcd5SXin LI }
190cac3dcd5SXin LI 
191cac3dcd5SXin LI #define ICHECK(i, l) \
192cac3dcd5SXin LI 	if ((i) + (l) > bodylen || (i) + (l) > length) goto corrupt;
193cac3dcd5SXin LI 
194cac3dcd5SXin LI static void
195cac3dcd5SXin LI babel_print_v2(const u_char *cp, u_int length) {
196cac3dcd5SXin LI     u_int i;
197cac3dcd5SXin LI     u_short bodylen;
198cac3dcd5SXin LI     u_char v4_prefix[16] =
199cac3dcd5SXin LI         {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
200cac3dcd5SXin LI     u_char v6_prefix[16] = {0};
201cac3dcd5SXin LI 
202cac3dcd5SXin LI     TCHECK2(*cp, 4);
203cac3dcd5SXin LI     if (length < 4)
204cac3dcd5SXin LI         goto corrupt;
205cac3dcd5SXin LI     bodylen = EXTRACT_16BITS(cp + 2);
206cac3dcd5SXin LI     printf(" (%u)", bodylen);
207cac3dcd5SXin LI 
208cac3dcd5SXin LI     /* Process the TLVs in the body */
209cac3dcd5SXin LI     i = 0;
210cac3dcd5SXin LI     while(i < bodylen) {
211cac3dcd5SXin LI         const u_char *message;
212*d03c0883SXin LI         u_int type, len;
213cac3dcd5SXin LI 
214cac3dcd5SXin LI         message = cp + 4 + i;
215cac3dcd5SXin LI         TCHECK2(*message, 2);
216cac3dcd5SXin LI         ICHECK(i, 2);
217cac3dcd5SXin LI         type = message[0];
218cac3dcd5SXin LI         len = message[1];
219cac3dcd5SXin LI 
220cac3dcd5SXin LI         TCHECK2(*message, 2 + len);
221cac3dcd5SXin LI         ICHECK(i, 2 + len);
222cac3dcd5SXin LI 
223cac3dcd5SXin LI         switch(type) {
224cac3dcd5SXin LI         case MESSAGE_PAD1: {
225cac3dcd5SXin LI             if(!vflag)
226cac3dcd5SXin LI                 printf(" pad1");
227cac3dcd5SXin LI             else
228cac3dcd5SXin LI                 printf("\n\tPad 1");
229cac3dcd5SXin LI         }
230cac3dcd5SXin LI             break;
231cac3dcd5SXin LI 
232cac3dcd5SXin LI         case MESSAGE_PADN: {
233cac3dcd5SXin LI             if(!vflag)
234cac3dcd5SXin LI                 printf(" padN");
235cac3dcd5SXin LI             else
236cac3dcd5SXin LI                 printf("\n\tPad %d", len + 2);
237cac3dcd5SXin LI         }
238cac3dcd5SXin LI             break;
239cac3dcd5SXin LI 
240cac3dcd5SXin LI         case MESSAGE_ACK_REQ: {
241cac3dcd5SXin LI             u_short nonce, interval;
242cac3dcd5SXin LI             if(!vflag)
243cac3dcd5SXin LI                 printf(" ack-req");
244cac3dcd5SXin LI             else {
245cac3dcd5SXin LI                 printf("\n\tAcknowledgment Request ");
246cac3dcd5SXin LI                 if(len < 6) goto corrupt;
247cac3dcd5SXin LI                 nonce = EXTRACT_16BITS(message + 4);
248cac3dcd5SXin LI                 interval = EXTRACT_16BITS(message + 6);
249cac3dcd5SXin LI                 printf("%04x %d", nonce, interval);
250cac3dcd5SXin LI             }
251cac3dcd5SXin LI         }
252cac3dcd5SXin LI             break;
253cac3dcd5SXin LI 
254cac3dcd5SXin LI         case MESSAGE_ACK: {
255cac3dcd5SXin LI             u_short nonce;
256cac3dcd5SXin LI             if(!vflag)
257cac3dcd5SXin LI                 printf(" ack");
258cac3dcd5SXin LI             else {
259cac3dcd5SXin LI                 printf("\n\tAcknowledgment ");
260cac3dcd5SXin LI                 if(len < 2) goto corrupt;
261cac3dcd5SXin LI                 nonce = EXTRACT_16BITS(message + 2);
262cac3dcd5SXin LI                 printf("%04x", nonce);
263cac3dcd5SXin LI             }
264cac3dcd5SXin LI         }
265cac3dcd5SXin LI             break;
266cac3dcd5SXin LI 
267cac3dcd5SXin LI         case MESSAGE_HELLO:  {
268cac3dcd5SXin LI             u_short seqno, interval;
269cac3dcd5SXin LI             if(!vflag)
270cac3dcd5SXin LI                 printf(" hello");
271cac3dcd5SXin LI             else {
272cac3dcd5SXin LI                 printf("\n\tHello ");
273cac3dcd5SXin LI                 if(len < 6) goto corrupt;
274cac3dcd5SXin LI                 seqno = EXTRACT_16BITS(message + 4);
275cac3dcd5SXin LI                 interval = EXTRACT_16BITS(message + 6);
276cac3dcd5SXin LI                 printf("seqno %u interval %u", seqno, interval);
277cac3dcd5SXin LI             }
278cac3dcd5SXin LI         }
279cac3dcd5SXin LI             break;
280cac3dcd5SXin LI 
281cac3dcd5SXin LI         case MESSAGE_IHU: {
282cac3dcd5SXin LI             unsigned short txcost, interval;
283cac3dcd5SXin LI             if(!vflag)
284cac3dcd5SXin LI                 printf(" ihu");
285cac3dcd5SXin LI             else {
286cac3dcd5SXin LI                 u_char address[16];
287cac3dcd5SXin LI                 int rc;
288cac3dcd5SXin LI                 printf("\n\tIHU ");
289cac3dcd5SXin LI                 if(len < 6) goto corrupt;
290cac3dcd5SXin LI                 txcost = EXTRACT_16BITS(message + 4);
291cac3dcd5SXin LI                 interval = EXTRACT_16BITS(message + 6);
292cac3dcd5SXin LI                 rc = network_address(message[2], message + 8, len - 6, address);
293cac3dcd5SXin LI                 if(rc < 0) { printf("[|babel]"); break; }
294cac3dcd5SXin LI                 printf("%s txcost %u interval %d",
295cac3dcd5SXin LI                        format_address(address), txcost, interval);
296cac3dcd5SXin LI             }
297cac3dcd5SXin LI         }
298cac3dcd5SXin LI             break;
299cac3dcd5SXin LI 
300cac3dcd5SXin LI         case MESSAGE_ROUTER_ID: {
301cac3dcd5SXin LI             if(!vflag)
302cac3dcd5SXin LI                 printf(" router-id");
303cac3dcd5SXin LI             else {
304cac3dcd5SXin LI                 printf("\n\tRouter Id");
305cac3dcd5SXin LI                 if(len < 10) goto corrupt;
306cac3dcd5SXin LI                 printf(" %s", format_id(message + 4));
307cac3dcd5SXin LI             }
308cac3dcd5SXin LI         }
309cac3dcd5SXin LI             break;
310cac3dcd5SXin LI 
311cac3dcd5SXin LI         case MESSAGE_NH: {
312cac3dcd5SXin LI             if(!vflag)
313cac3dcd5SXin LI                 printf(" nh");
314cac3dcd5SXin LI             else {
315cac3dcd5SXin LI                 int rc;
316cac3dcd5SXin LI                 u_char nh[16];
317cac3dcd5SXin LI                 printf("\n\tNext Hop");
318cac3dcd5SXin LI                 if(len < 2) goto corrupt;
319cac3dcd5SXin LI                 rc = network_address(message[2], message + 4, len - 2, nh);
320cac3dcd5SXin LI                 if(rc < 0) goto corrupt;
321cac3dcd5SXin LI                 printf(" %s", format_address(nh));
322cac3dcd5SXin LI             }
323cac3dcd5SXin LI         }
324cac3dcd5SXin LI             break;
325cac3dcd5SXin LI 
326cac3dcd5SXin LI         case MESSAGE_UPDATE: {
327cac3dcd5SXin LI             if(!vflag) {
328cac3dcd5SXin LI                 printf(" update");
329cac3dcd5SXin LI                 if(len < 1)
330cac3dcd5SXin LI                     printf("/truncated");
331cac3dcd5SXin LI                 else
332cac3dcd5SXin LI                     printf("%s%s%s",
333cac3dcd5SXin LI                            (message[3] & 0x80) ? "/prefix": "",
334cac3dcd5SXin LI                            (message[3] & 0x40) ? "/id" : "",
335cac3dcd5SXin LI                            (message[3] & 0x3f) ? "/unknown" : "");
336cac3dcd5SXin LI             } else {
337cac3dcd5SXin LI                 u_short interval, seqno, metric;
338cac3dcd5SXin LI                 u_char plen;
339cac3dcd5SXin LI                 int rc;
340cac3dcd5SXin LI                 u_char prefix[16];
341cac3dcd5SXin LI                 printf("\n\tUpdate");
342cac3dcd5SXin LI                 if(len < 10) goto corrupt;
343cac3dcd5SXin LI                 plen = message[4] + (message[2] == 1 ? 96 : 0);
344cac3dcd5SXin LI                 rc = network_prefix(message[2], message[4], message[5],
345cac3dcd5SXin LI                                     message + 12,
346cac3dcd5SXin LI                                     message[2] == 1 ? v4_prefix : v6_prefix,
347cac3dcd5SXin LI                                     len - 10, prefix);
348cac3dcd5SXin LI                 if(rc < 0) goto corrupt;
349cac3dcd5SXin LI                 interval = EXTRACT_16BITS(message + 6);
350cac3dcd5SXin LI                 seqno = EXTRACT_16BITS(message + 8);
351cac3dcd5SXin LI                 metric = EXTRACT_16BITS(message + 10);
352cac3dcd5SXin LI                 printf("%s%s%s %s metric %u seqno %u interval %u",
353cac3dcd5SXin LI                        (message[3] & 0x80) ? "/prefix": "",
354cac3dcd5SXin LI                        (message[3] & 0x40) ? "/id" : "",
355cac3dcd5SXin LI                        (message[3] & 0x3f) ? "/unknown" : "",
356cac3dcd5SXin LI                        format_prefix(prefix, plen),
357cac3dcd5SXin LI                        metric, seqno, interval);
358cac3dcd5SXin LI                 if(message[3] & 0x80) {
359cac3dcd5SXin LI                     if(message[2] == 1)
360cac3dcd5SXin LI                         memcpy(v4_prefix, prefix, 16);
361cac3dcd5SXin LI                     else
362cac3dcd5SXin LI                         memcpy(v6_prefix, prefix, 16);
363cac3dcd5SXin LI                 }
364cac3dcd5SXin LI             }
365cac3dcd5SXin LI         }
366cac3dcd5SXin LI             break;
367cac3dcd5SXin LI 
368cac3dcd5SXin LI         case MESSAGE_REQUEST: {
369cac3dcd5SXin LI             if(!vflag)
370cac3dcd5SXin LI                 printf(" request");
371cac3dcd5SXin LI             else {
372cac3dcd5SXin LI                 int rc;
373cac3dcd5SXin LI                 u_char prefix[16], plen;
374cac3dcd5SXin LI                 printf("\n\tRequest ");
375cac3dcd5SXin LI                 if(len < 2) goto corrupt;
376cac3dcd5SXin LI                 plen = message[3] + (message[2] == 1 ? 96 : 0);
377cac3dcd5SXin LI                 rc = network_prefix(message[2], message[3], 0,
378cac3dcd5SXin LI                                     message + 4, NULL, len - 2, prefix);
379cac3dcd5SXin LI                 if(rc < 0) goto corrupt;
380cac3dcd5SXin LI                 plen = message[3] + (message[2] == 1 ? 96 : 0);
381cac3dcd5SXin LI                 printf("for %s",
382cac3dcd5SXin LI                        message[2] == 0 ? "any" : format_prefix(prefix, plen));
383cac3dcd5SXin LI             }
384cac3dcd5SXin LI         }
385cac3dcd5SXin LI             break;
386cac3dcd5SXin LI 
387cac3dcd5SXin LI         case MESSAGE_MH_REQUEST : {
388cac3dcd5SXin LI             if(!vflag)
389cac3dcd5SXin LI                 printf(" mh-request");
390cac3dcd5SXin LI             else {
391cac3dcd5SXin LI                 int rc;
392cac3dcd5SXin LI                 u_short seqno;
393cac3dcd5SXin LI                 u_char prefix[16], plen;
394cac3dcd5SXin LI                 printf("\n\tMH-Request ");
395cac3dcd5SXin LI                 if(len < 14) goto corrupt;
396cac3dcd5SXin LI                 seqno = EXTRACT_16BITS(message + 4);
397cac3dcd5SXin LI                 rc = network_prefix(message[2], message[3], 0,
398cac3dcd5SXin LI                                     message + 16, NULL, len - 14, prefix);
399cac3dcd5SXin LI                 if(rc < 0) goto corrupt;
400cac3dcd5SXin LI                 plen = message[3] + (message[2] == 1 ? 96 : 0);
401cac3dcd5SXin LI                 printf("(%u hops) for %s seqno %u id %s",
402cac3dcd5SXin LI                        message[6], format_prefix(prefix, plen),
403cac3dcd5SXin LI                        seqno, format_id(message + 8));
404cac3dcd5SXin LI             }
405cac3dcd5SXin LI         }
406cac3dcd5SXin LI             break;
407*d03c0883SXin LI         case MESSAGE_TSPC :
408*d03c0883SXin LI             if(!vflag)
409*d03c0883SXin LI                 printf(" tspc");
410*d03c0883SXin LI             else {
411*d03c0883SXin LI                 printf("\n\tTS/PC ");
412*d03c0883SXin LI                 if(len < 6) goto corrupt;
413*d03c0883SXin LI                 printf("timestamp %u packetcounter %u", EXTRACT_32BITS (message + 4),
414*d03c0883SXin LI                        EXTRACT_16BITS(message + 2));
415*d03c0883SXin LI             }
416*d03c0883SXin LI             break;
417*d03c0883SXin LI         case MESSAGE_HMAC : {
418*d03c0883SXin LI             if(!vflag)
419*d03c0883SXin LI                 printf(" hmac");
420*d03c0883SXin LI             else {
421*d03c0883SXin LI                 unsigned j;
422*d03c0883SXin LI                 printf("\n\tHMAC ");
423*d03c0883SXin LI                 if(len < 18) goto corrupt;
424*d03c0883SXin LI                 printf("key-id %u digest-%u ", EXTRACT_16BITS(message + 2), len - 2);
425*d03c0883SXin LI                 for (j = 0; j < len - 2; j++)
426*d03c0883SXin LI                     printf ("%02X", message[4 + j]);
427*d03c0883SXin LI             }
428*d03c0883SXin LI         }
429*d03c0883SXin LI             break;
430cac3dcd5SXin LI         default:
431cac3dcd5SXin LI             if(!vflag)
432cac3dcd5SXin LI                 printf(" unknown");
433cac3dcd5SXin LI             else
434cac3dcd5SXin LI                 printf("\n\tUnknown message type %d", type);
435cac3dcd5SXin LI         }
436cac3dcd5SXin LI         i += len + 2;
437cac3dcd5SXin LI     }
438cac3dcd5SXin LI     return;
439cac3dcd5SXin LI 
440cac3dcd5SXin LI  trunc:
441cac3dcd5SXin LI     printf(" [|babel]");
442cac3dcd5SXin LI     return;
443cac3dcd5SXin LI 
444cac3dcd5SXin LI  corrupt:
445cac3dcd5SXin LI     printf(" (corrupt)");
446cac3dcd5SXin LI     return;
447cac3dcd5SXin LI }
448