print-rpki-rtr.c revision 251158
1241149Sdteske/* 2241149Sdteske * Copyright (c) 1998-2011 The TCPDUMP project 3241149Sdteske * 4241149Sdteske * Redistribution and use in source and binary forms, with or without 5241149Sdteske * modification, are permitted provided that: (1) source code 6241149Sdteske * distributions retain the above copyright notice and this paragraph 7241149Sdteske * in its entirety, and (2) distributions including binary code include 8241149Sdteske * the above copyright notice and this paragraph in its entirety in 9241149Sdteske * the documentation or other materials provided with the distribution. 10241149Sdteske * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 11241149Sdteske * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT 12241149Sdteske * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 13241149Sdteske * FOR A PARTICULAR PURPOSE. 14241149Sdteske * 15241149Sdteske * support for the The RPKI/Router Protocol as RFC6810 16241149Sdteske * 17241149Sdteske * Original code by Hannes Gredler (hannes@juniper.net) 18241149Sdteske */ 19241149Sdteske 20241149Sdteske#ifndef lint 21241149Sdteskestatic const char rcsid[] _U_ = 22241149Sdteske"@(#) $Header: /tcpdump/master/tcpdump/print-rpki_rtr.c,v 1.10 2008-03-20 09:30:56 hannes Exp $"; 23241149Sdteske#endif 24241149Sdteske 25241149Sdteske#ifdef HAVE_CONFIG_H 26241149Sdteske#include "config.h" 27241149Sdteske#endif 28241149Sdteske 29241149Sdteske#include <tcpdump-stdinc.h> 30241149Sdteske 31241149Sdteske#include <stdio.h> 32241149Sdteske#include <stdlib.h> 33241149Sdteske#include <string.h> 34241149Sdteske 35241149Sdteske#include "interface.h" 36241149Sdteske#include "extract.h" 37241149Sdteske#include "addrtoname.h" 38241149Sdteske 39241149Sdteske/* 40241149Sdteske * RPKI/Router PDU header 41241149Sdteske * 42241149Sdteske * Here's what the PDU header looks like. 43241149Sdteske * The length does include the version and length fields. 44241149Sdteske */ 45241149Sdtesketypedef struct rpki_rtr_pdu_ { 46241149Sdteske u_char version; /* Version number */ 47241149Sdteske u_char pdu_type; /* PDU type */ 48241149Sdteske union { 49241149Sdteske u_char session_id[2]; /* Session id */ 50241149Sdteske u_char error_code[2]; /* Error code */ 51241149Sdteske } u; 52241149Sdteske u_char length[4]; 53241149Sdteske} rpki_rtr_pdu; 54241149Sdteske#define RPKI_RTR_PDU_OVERHEAD (offsetof(rpki_rtr_pdu, rpki_rtr_pdu_msg)) 55241149Sdteske 56241149Sdteske/* 57241149Sdteske * IPv4 Prefix PDU. 58241149Sdteske */ 59241149Sdtesketypedef struct rpki_rtr_pdu_ipv4_prefix_ { 60241149Sdteske rpki_rtr_pdu pdu_header; 61241149Sdteske u_char flags; 62241149Sdteske u_char prefix_length; 63241149Sdteske u_char max_length; 64241149Sdteske u_char zero; 65241149Sdteske u_char prefix[4]; 66241149Sdteske u_char as[4]; 67241149Sdteske} rpki_rtr_pdu_ipv4_prefix; 68241149Sdteske 69241149Sdteske/* 70241149Sdteske * IPv6 Prefix PDU. 71241149Sdteske */ 72241149Sdtesketypedef struct rpki_rtr_pdu_ipv6_prefix_ { 73241149Sdteske rpki_rtr_pdu pdu_header; 74241149Sdteske u_char flags; 75241149Sdteske u_char prefix_length; 76241149Sdteske u_char max_length; 77241149Sdteske u_char zero; 78241149Sdteske u_char prefix[16]; 79241149Sdteske u_char as[4]; 80241149Sdteske} rpki_rtr_pdu_ipv6_prefix; 81241149Sdteske 82241149Sdteske/* 83241149Sdteske * Error report PDU. 84241149Sdteske */ 85241149Sdtesketypedef struct rpki_rtr_pdu_error_report_ { 86241149Sdteske rpki_rtr_pdu pdu_header; 87241149Sdteske u_char encapsulated_pdu_length[4]; /* Encapsulated PDU length */ 88241149Sdteske} rpki_rtr_pdu_error_report; 89241149Sdteske 90241149Sdteske/* 91241149Sdteske * PDU type codes 92241149Sdteske */ 93241149Sdteske#define RPKI_RTR_SERIAL_NOTIFY_PDU 0 94241149Sdteske#define RPKI_RTR_SERIAL_QUERY_PDU 1 95241149Sdteske#define RPKI_RTR_RESET_QUERY_PDU 2 96241149Sdteske#define RPKI_RTR_CACHE_RESPONSE_PDU 3 97241149Sdteske#define RPKI_RTR_IPV4_PREFIX_PDU 4 98241149Sdteske#define RPKI_RTR_IPV6_PREFIX_PDU 6 99241149Sdteske#define RPKI_RTR_END_OF_DATA_PDU 7 100241149Sdteske#define RPKI_RTR_CACHE_RESET_PDU 8 101241149Sdteske#define RPKI_RTR_ERROR_REPORT_PDU 10 102241149Sdteske 103241149Sdteskestatic const struct tok rpki_rtr_pdu_values[] = { 104241149Sdteske { RPKI_RTR_SERIAL_NOTIFY_PDU, "Serial Notify" }, 105241149Sdteske { RPKI_RTR_SERIAL_QUERY_PDU, "Serial Query" }, 106241149Sdteske { RPKI_RTR_RESET_QUERY_PDU, "Reset Query" }, 107241149Sdteske { RPKI_RTR_CACHE_RESPONSE_PDU, "Cache Response" }, 108241149Sdteske { RPKI_RTR_IPV4_PREFIX_PDU, "IPV4 Prefix" }, 109241149Sdteske { RPKI_RTR_IPV6_PREFIX_PDU, "IPV6 Prefix" }, 110241149Sdteske { RPKI_RTR_END_OF_DATA_PDU, "End of Data" }, 111241149Sdteske { RPKI_RTR_CACHE_RESET_PDU, "Cache Reset" }, 112241149Sdteske { RPKI_RTR_ERROR_REPORT_PDU, "Error Report" }, 113241149Sdteske { 0, NULL} 114241149Sdteske}; 115241149Sdteske 116241149Sdteskestatic const struct tok rpki_rtr_error_codes[] = { 117241149Sdteske { 0, "Corrupt Data" }, 118241149Sdteske { 1, "Internal Error" }, 119241149Sdteske { 2, "No Data Available" }, 120241149Sdteske { 3, "Invalid Request" }, 121241149Sdteske { 4, "Unsupported Protocol Version" }, 122241149Sdteske { 5, "Unsupported PDU Type" }, 123241149Sdteske { 6, "Withdrawal of Unknown Record" }, 124241149Sdteske { 7, "Duplicate Announcement Received" }, 125241149Sdteske { 0, NULL} 126241149Sdteske}; 127241149Sdteske 128241149Sdteske/* 129241149Sdteske * Build a identation string for a given identation level. 130241149Sdteske * XXX this should be really in util.c 131241149Sdteske */ 132241149Sdteskestatic char * 133241149Sdteskeindent_string (u_int indent) 134241149Sdteske{ 135241149Sdteske static char buf[20]; 136241149Sdteske u_int idx; 137241149Sdteske 138241149Sdteske idx = 0; 139241149Sdteske buf[idx] = '\0'; 140241149Sdteske 141241149Sdteske /* 142241149Sdteske * Does the static buffer fit ? 143241149Sdteske */ 144241149Sdteske if (sizeof(buf) < ((indent/8) + (indent %8) + 2)) { 145241149Sdteske return buf; 146241149Sdteske } 147241149Sdteske 148241149Sdteske /* 149241149Sdteske * Heading newline. 150241149Sdteske */ 151241149Sdteske buf[idx] = '\n'; 152241149Sdteske idx++; 153241149Sdteske 154241149Sdteske while (indent >= 8) { 155241149Sdteske buf[idx] = '\t'; 156241149Sdteske idx++; 157241149Sdteske indent -= 8; 158241149Sdteske } 159241149Sdteske 160241149Sdteske while (indent > 0) { 161241149Sdteske buf[idx] = ' '; 162241149Sdteske idx++; 163241149Sdteske indent--; 164241149Sdteske } 165241149Sdteske 166241149Sdteske /* 167241149Sdteske * Trailing zero. 168241149Sdteske */ 169241149Sdteske buf[idx] = '\0'; 170241149Sdteske 171241149Sdteske return buf; 172241149Sdteske} 173241149Sdteske 174241149Sdteske/* 175241149Sdteske * Print a single PDU. 176241149Sdteske */ 177241149Sdteskestatic void 178241149Sdteskerpki_rtr_pdu_print (const u_char *tptr, u_int indent) 179241149Sdteske{ 180241149Sdteske const rpki_rtr_pdu *pdu_header; 181241149Sdteske u_int pdu_type, pdu_len, hexdump; 182241149Sdteske const u_char *msg; 183241149Sdteske 184241149Sdteske pdu_header = (rpki_rtr_pdu *)tptr; 185241149Sdteske pdu_type = pdu_header->pdu_type; 186241149Sdteske pdu_len = EXTRACT_32BITS(pdu_header->length); 187241149Sdteske hexdump = FALSE; 188241149Sdteske 189241149Sdteske printf("%sRPKI-RTRv%u, %s PDU (%u), length: %u", 190241149Sdteske indent_string(8), 191241149Sdteske pdu_header->version, 192241149Sdteske tok2str(rpki_rtr_pdu_values, "Unknown", pdu_type), 193241149Sdteske pdu_type, pdu_len); 194241149Sdteske 195241149Sdteske switch (pdu_type) { 196241149Sdteske 197241149Sdteske /* 198241149Sdteske * The following PDUs share the message format. 199241149Sdteske */ 200241149Sdteske case RPKI_RTR_SERIAL_NOTIFY_PDU: 201241149Sdteske case RPKI_RTR_SERIAL_QUERY_PDU: 202241149Sdteske case RPKI_RTR_END_OF_DATA_PDU: 203241149Sdteske msg = (const u_char *)(pdu_header + 1); 204241149Sdteske printf("%sSession ID: 0x%04x, Serial: %u", 205241149Sdteske indent_string(indent+2), 206241149Sdteske EXTRACT_16BITS(pdu_header->u.session_id), 207241149Sdteske EXTRACT_32BITS(msg)); 208241149Sdteske break; 209241149Sdteske 210241149Sdteske /* 211241149Sdteske * The following PDUs share the message format. 212241149Sdteske */ 213241149Sdteske case RPKI_RTR_RESET_QUERY_PDU: 214241149Sdteske case RPKI_RTR_CACHE_RESET_PDU: 215241149Sdteske 216241149Sdteske /* 217241149Sdteske * Zero payload PDUs. 218241149Sdteske */ 219241149Sdteske break; 220241149Sdteske 221241149Sdteske case RPKI_RTR_CACHE_RESPONSE_PDU: 222241149Sdteske printf("%sSession ID: 0x%04x", 223241149Sdteske indent_string(indent+2), 224241149Sdteske EXTRACT_16BITS(pdu_header->u.session_id)); 225241149Sdteske break; 226241149Sdteske 227241149Sdteske case RPKI_RTR_IPV4_PREFIX_PDU: 228241149Sdteske { 229241149Sdteske rpki_rtr_pdu_ipv4_prefix *pdu; 230241149Sdteske 231241149Sdteske pdu = (rpki_rtr_pdu_ipv4_prefix *)tptr; 232241149Sdteske printf("%sIPv4 Prefix %s/%u-%u, origin-as %u, flags 0x%02x", 233241149Sdteske indent_string(indent+2), 234241149Sdteske ipaddr_string(pdu->prefix), 235241149Sdteske pdu->prefix_length, pdu->max_length, 236241149Sdteske EXTRACT_32BITS(pdu->as), pdu->flags); 237241149Sdteske } 238241149Sdteske break; 239241149Sdteske 240241149Sdteske#ifdef INET6 241241149Sdteske case RPKI_RTR_IPV6_PREFIX_PDU: 242241149Sdteske { 243241149Sdteske rpki_rtr_pdu_ipv6_prefix *pdu; 244241149Sdteske 245241149Sdteske pdu = (rpki_rtr_pdu_ipv6_prefix *)tptr; 246241149Sdteske printf("%sIPv6 Prefix %s/%u-%u, origin-as %u, flags 0x%02x", 247241149Sdteske indent_string(indent+2), 248241149Sdteske ip6addr_string(pdu->prefix), 249241149Sdteske pdu->prefix_length, pdu->max_length, 250241149Sdteske EXTRACT_32BITS(pdu->as), pdu->flags); 251241149Sdteske } 252241149Sdteske break; 253241149Sdteske#endif 254241565Sdteske 255241149Sdteske case RPKI_RTR_ERROR_REPORT_PDU: 256241149Sdteske { 257241149Sdteske rpki_rtr_pdu_error_report *pdu; 258241149Sdteske u_int encapsulated_pdu_length, text_length, tlen, error_code; 259241149Sdteske u_char buf[80]; 260241149Sdteske 261241149Sdteske pdu = (rpki_rtr_pdu_error_report *)tptr; 262241149Sdteske encapsulated_pdu_length = EXTRACT_32BITS(pdu->encapsulated_pdu_length); 263241149Sdteske tlen = pdu_len; 264241149Sdteske 265241149Sdteske error_code = EXTRACT_16BITS(pdu->pdu_header.u.error_code); 266241149Sdteske printf("%sError code: %s (%u), Encapsulated PDU length: %u", 267241149Sdteske indent_string(indent+2), 268241149Sdteske tok2str(rpki_rtr_error_codes, "Unknown", error_code), 269241149Sdteske error_code, encapsulated_pdu_length); 270241149Sdteske 271241149Sdteske tptr += sizeof(*pdu); 272241149Sdteske tlen -= sizeof(*pdu); 273241149Sdteske 274241149Sdteske /* 275241149Sdteske * Recurse if there is an encapsulated PDU. 276241149Sdteske */ 277241149Sdteske if (encapsulated_pdu_length && 278241149Sdteske (encapsulated_pdu_length <= tlen)) { 279241149Sdteske printf("%s-----encapsulated PDU-----", indent_string(indent+4)); 280241149Sdteske rpki_rtr_pdu_print(tptr, indent+2); 281241149Sdteske } 282241149Sdteske 283241149Sdteske tptr += encapsulated_pdu_length; 284241149Sdteske tlen -= encapsulated_pdu_length; 285241149Sdteske 286241149Sdteske /* 287241149Sdteske * Extract, trail-zero and print the Error message. 288241149Sdteske */ 289241149Sdteske text_length = 0; 290241149Sdteske if (tlen > 4) { 291241149Sdteske text_length = EXTRACT_32BITS(tptr); 292241149Sdteske tptr += 4; 293241149Sdteske tlen -= 4; 294241149Sdteske } 295241149Sdteske if (text_length && (text_length <= tlen )) { 296241149Sdteske memcpy(buf, tptr, MIN(sizeof(buf)-1, text_length)); 297241149Sdteske buf[text_length] = '\0'; 298241149Sdteske printf("%sError text: %s", indent_string(indent+2), buf); 299241149Sdteske } 300241149Sdteske } 301241149Sdteske break; 302241149Sdteske 303241149Sdteske default: 304241149Sdteske 305241149Sdteske /* 306241149Sdteske * Unknown data, please hexdump. 307241149Sdteske */ 308241149Sdteske hexdump = TRUE; 309241149Sdteske } 310241149Sdteske 311241149Sdteske /* do we also want to see a hex dump ? */ 312241149Sdteske if (vflag > 1 || (vflag && hexdump)) { 313241149Sdteske print_unknown_data(tptr,"\n\t ", pdu_len); 314241565Sdteske } 315241149Sdteske} 316241149Sdteske 317241149Sdteskevoid 318241149Sdteskerpki_rtr_print(register const u_char *pptr, register u_int len) { 319241149Sdteske 320241149Sdteske u_int tlen, pdu_type, pdu_len; 321241149Sdteske const u_char *tptr; 322241149Sdteske const rpki_rtr_pdu *pdu_header; 323241149Sdteske 324241149Sdteske tptr = pptr; 325241149Sdteske tlen = len; 326241149Sdteske 327241149Sdteske if (!vflag) { 328241149Sdteske printf(", RPKI-RTR"); 329241149Sdteske return; 330241149Sdteske } 331241149Sdteske 332241149Sdteske while (tlen >= sizeof(rpki_rtr_pdu)) { 333241149Sdteske 334241149Sdteske TCHECK2(*tptr, sizeof(rpki_rtr_pdu)); 335241149Sdteske 336241149Sdteske pdu_header = (rpki_rtr_pdu *)tptr; 337241149Sdteske pdu_type = pdu_header->pdu_type; 338241149Sdteske pdu_len = EXTRACT_32BITS(pdu_header->length); 339241149Sdteske 340241149Sdteske /* infinite loop check */ 341241149Sdteske if (!pdu_type || !pdu_len) { 342241149Sdteske break; 343241149Sdteske } 344241149Sdteske 345241149Sdteske TCHECK2(*tptr, pdu_len); 346241149Sdteske if (tlen < pdu_len) { 347241149Sdteske goto trunc; 348241149Sdteske } 349241149Sdteske 350241149Sdteske /* 351241149Sdteske * Print the PDU. 352241149Sdteske */ 353241149Sdteske rpki_rtr_pdu_print(tptr, 8); 354241149Sdteske 355241149Sdteske tlen -= pdu_len; 356241149Sdteske tptr += pdu_len; 357241149Sdteske } 358241149Sdteske return; 359241149Sdteske trunc: 360241149Sdteske printf("\n\t[|RPKI-RTR]"); 361241149Sdteske} 362241149Sdteske 363241149Sdteske/* 364241149Sdteske * Local Variables: 365241149Sdteske * c-style: whitesmith 366241149Sdteske * c-basic-offset: 4 367241149Sdteske * End: 368241149Sdteske */ 369241149Sdteske