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