print-rpki-rtr.c revision 235427
11573Srgrimes/* 21573Srgrimes * Copyright (c) 1998-2011 The TCPDUMP project 31573Srgrimes * 41573Srgrimes * Redistribution and use in source and binary forms, with or without 51573Srgrimes * modification, are permitted provided that: (1) source code 61573Srgrimes * distributions retain the above copyright notice and this paragraph 71573Srgrimes * in its entirety, and (2) distributions including binary code include 81573Srgrimes * the above copyright notice and this paragraph in its entirety in 91573Srgrimes * the documentation or other materials provided with the distribution. 101573Srgrimes * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 111573Srgrimes * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT 121573Srgrimes * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 131573Srgrimes * FOR A PARTICULAR PURPOSE. 141573Srgrimes * 151573Srgrimes * support for the The RPKI/Router Protocol Protocol as per draft-ietf-sidr-rpki-rtr-12 161573Srgrimes * 171573Srgrimes * Original code by Hannes Gredler (hannes@juniper.net) 181573Srgrimes */ 191573Srgrimes 201573Srgrimes#ifndef lint 211573Srgrimesstatic const char rcsid[] _U_ = 221573Srgrimes"@(#) $Header: /tcpdump/master/tcpdump/print-rpki_rtr.c,v 1.10 2008-03-20 09:30:56 hannes Exp $"; 231573Srgrimes#endif 241573Srgrimes 251573Srgrimes#ifdef HAVE_CONFIG_H 261573Srgrimes#include "config.h" 271573Srgrimes#endif 281573Srgrimes 291573Srgrimes#include <tcpdump-stdinc.h> 301573Srgrimes 311573Srgrimes#include <stdio.h> 321573Srgrimes#include <stdlib.h> 331573Srgrimes#include <string.h> 341573Srgrimes 351573Srgrimes#include "interface.h" 361573Srgrimes#include "extract.h" 371573Srgrimes#include "addrtoname.h" 3816586Sjraynard 391573Srgrimes/* 4016586Sjraynard * RPKI/Router PDU header 4116586Sjraynard * 4231983Sache * Here's what the PDU header looks like. 431573Srgrimes * The length does include the version and length fields. 441573Srgrimes */ 451573Srgrimestypedef struct rpki_rtr_pdu_ { 461573Srgrimes u_char version; /* Version number */ 471573Srgrimes u_char pdu_type; /* PDU type */ 481573Srgrimes union { 491573Srgrimes u_char cache_nonce[2]; /* Cache Nonce */ 501573Srgrimes u_char error_code[2]; /* Error code */ 511573Srgrimes } u; 521573Srgrimes u_char length[4]; 531573Srgrimes} rpki_rtr_pdu; 541573Srgrimes#define RPKI_RTR_PDU_OVERHEAD (offsetof(rpki_rtr_pdu, rpki_rtr_pdu_msg)) 551573Srgrimes 561573Srgrimes/* 571573Srgrimes * IPv4 Prefix PDU. 581573Srgrimes */ 591573Srgrimestypedef struct rpki_rtr_pdu_ipv4_prefix_ { 601573Srgrimes rpki_rtr_pdu pdu_header; 611573Srgrimes u_char flags; 621573Srgrimes u_char prefix_length; 631573Srgrimes u_char max_length; 641573Srgrimes u_char zero; 651573Srgrimes u_char prefix[4]; 6613545Sjulian u_char as[4]; 6713545Sjulian} rpki_rtr_pdu_ipv4_prefix; 6813545Sjulian 6913545Sjulian/* 701573Srgrimes * IPv6 Prefix PDU. 711573Srgrimes */ 721573Srgrimestypedef struct rpki_rtr_pdu_ipv6_prefix_ { 731573Srgrimes rpki_rtr_pdu pdu_header; 7416586Sjraynard u_char flags; 7516586Sjraynard u_char prefix_length; 7616586Sjraynard u_char max_length; 7716586Sjraynard u_char zero; 7821674Sjkh u_char prefix[16]; 7921674Sjkh u_char as[4]; 8016586Sjraynard} rpki_rtr_pdu_ipv6_prefix; 811573Srgrimes 821573Srgrimes/* 831573Srgrimes * Error report PDU. 841573Srgrimes */ 851573Srgrimestypedef struct rpki_rtr_pdu_error_report_ { 861573Srgrimes rpki_rtr_pdu pdu_header; 871573Srgrimes u_char encapsulated_pdu_length[4]; /* Encapsulated PDU length */ 881573Srgrimes} rpki_rtr_pdu_error_report; 891573Srgrimes 901573Srgrimes/* 911573Srgrimes * PDU type codes 921573Srgrimes */ 931573Srgrimes#define RPKI_RTR_SERIAL_NOTIFY_PDU 0 941573Srgrimes#define RPKI_RTR_SERIAL_QUERY_PDU 1 951573Srgrimes#define RPKI_RTR_RESET_QUERY_PDU 2 961573Srgrimes#define RPKI_RTR_CACHE_RESPONSE_PDU 3 971573Srgrimes#define RPKI_RTR_IPV4_PREFIX_PDU 4 981573Srgrimes#define RPKI_RTR_IPV6_PREFIX_PDU 6 991573Srgrimes#define RPKI_RTR_END_OF_DATA_PDU 7 1001573Srgrimes#define RPKI_RTR_CACHE_RESET_PDU 8 1011573Srgrimes#define RPKI_RTR_ERROR_REPORT_PDU 10 1021573Srgrimes 1031573Srgrimesstatic const struct tok rpki_rtr_pdu_values[] = { 1041573Srgrimes { RPKI_RTR_SERIAL_NOTIFY_PDU, "Serial Notify" }, 1051573Srgrimes { RPKI_RTR_SERIAL_QUERY_PDU, "Serial Query" }, 1061573Srgrimes { RPKI_RTR_RESET_QUERY_PDU, "Reset Query" }, 1071573Srgrimes { RPKI_RTR_CACHE_RESPONSE_PDU, "Cache Response" }, 1081573Srgrimes { RPKI_RTR_IPV4_PREFIX_PDU, "IPV4 Prefix" }, 1091573Srgrimes { RPKI_RTR_IPV6_PREFIX_PDU, "IPV6 Prefix" }, 1101573Srgrimes { RPKI_RTR_END_OF_DATA_PDU, "End of Data" }, 1111573Srgrimes { RPKI_RTR_CACHE_RESET_PDU, "Cache Reset" }, 1121573Srgrimes { RPKI_RTR_ERROR_REPORT_PDU, "Error Report" }, 1131573Srgrimes { 0, NULL} 1141573Srgrimes}; 1151573Srgrimes 1161573Srgrimesstatic const struct tok rpki_rtr_error_codes[] = { 1171573Srgrimes { 0, "Corrupt Data" }, 1181573Srgrimes { 1, "Internal Error" }, 1191573Srgrimes { 2, "No Data Available" }, 1201573Srgrimes { 3, "Invalid Request" }, 1211573Srgrimes { 4, "Unsupported Protocol Version" }, 1221573Srgrimes { 5, "Unsupported PDU Type" }, 1231573Srgrimes { 6, "Withdrawal of Unknown Record" }, 1241573Srgrimes { 7, "Duplicate Announcement Received" }, 1251573Srgrimes { 0, NULL} 1261573Srgrimes}; 1271573Srgrimes 1281573Srgrimes/* 1291573Srgrimes * Build a identation string for a given identation level. 1301573Srgrimes * XXX this should be really in util.c 1311573Srgrimes */ 1321573Srgrimesstatic char * 1331573Srgrimesindent_string (u_int indent) 1341573Srgrimes{ 1351573Srgrimes static char buf[20]; 1361573Srgrimes u_int idx; 1371573Srgrimes 1381573Srgrimes idx = 0; 1391573Srgrimes buf[idx] = '\0'; 1401573Srgrimes 1411573Srgrimes /* 1421573Srgrimes * Does the static buffer fit ? 1431573Srgrimes */ 1441573Srgrimes if (sizeof(buf) < ((indent/8) + (indent %8) + 2)) { 1451573Srgrimes return buf; 1461573Srgrimes } 1471573Srgrimes 1481573Srgrimes /* 1491573Srgrimes * Heading newline. 1501573Srgrimes */ 1511573Srgrimes buf[idx] = '\n'; 1521573Srgrimes idx++; 1531573Srgrimes 1541573Srgrimes while (indent >= 8) { 1551573Srgrimes buf[idx] = '\t'; 1561573Srgrimes idx++; 1571573Srgrimes indent -= 8; 1581573Srgrimes } 1591573Srgrimes 1601573Srgrimes while (indent > 0) { 1611573Srgrimes buf[idx] = ' '; 1621573Srgrimes idx++; 1631573Srgrimes indent--; 1641573Srgrimes } 1651573Srgrimes 1661573Srgrimes /* 1671573Srgrimes * Trailing zero. 1681573Srgrimes */ 1691573Srgrimes buf[idx] = '\0'; 1701573Srgrimes 1711573Srgrimes return buf; 1721573Srgrimes} 1731573Srgrimes 1741573Srgrimes/* 1751573Srgrimes * Print a single PDU. 1761573Srgrimes */ 1771573Srgrimesstatic void 1781573Srgrimesrpki_rtr_pdu_print (const u_char *tptr, u_int indent) 1791573Srgrimes{ 1801573Srgrimes const rpki_rtr_pdu *pdu_header; 1811573Srgrimes u_int pdu_type, pdu_len, hexdump; 1821573Srgrimes const u_char *msg; 1831573Srgrimes 1841573Srgrimes pdu_header = (rpki_rtr_pdu *)tptr; 1851573Srgrimes pdu_type = pdu_header->pdu_type; 1861573Srgrimes pdu_len = EXTRACT_32BITS(pdu_header->length); 1871573Srgrimes hexdump = FALSE; 1881573Srgrimes 1891573Srgrimes printf("%sRPKI-RTRv%u, %s PDU (%u), length: %u", 1901573Srgrimes indent_string(8), 1911573Srgrimes pdu_header->version, 1921573Srgrimes tok2str(rpki_rtr_pdu_values, "Unknown", pdu_type), 1931573Srgrimes pdu_type, pdu_len); 1941573Srgrimes 1951573Srgrimes switch (pdu_type) { 1961573Srgrimes 1971573Srgrimes /* 1981573Srgrimes * The following PDUs share the message format. 1991573Srgrimes */ 2001573Srgrimes case RPKI_RTR_SERIAL_NOTIFY_PDU: 2011573Srgrimes case RPKI_RTR_SERIAL_QUERY_PDU: 2021573Srgrimes case RPKI_RTR_END_OF_DATA_PDU: 2031573Srgrimes msg = (const u_char *)(pdu_header + 1); 2041573Srgrimes printf("%sCache-Nonce: 0x%04x, Serial: %u", 2051573Srgrimes indent_string(indent+2), 2061573Srgrimes EXTRACT_16BITS(pdu_header->u.cache_nonce), 2071573Srgrimes EXTRACT_32BITS(msg)); 2081573Srgrimes break; 2091573Srgrimes 2101573Srgrimes /* 2111573Srgrimes * The following PDUs share the message format. 2121573Srgrimes */ 2131573Srgrimes case RPKI_RTR_RESET_QUERY_PDU: 2141573Srgrimes case RPKI_RTR_CACHE_RESET_PDU: 2151573Srgrimes 2161573Srgrimes /* 2171573Srgrimes * Zero payload PDUs. 2181573Srgrimes */ 2191573Srgrimes break; 2201573Srgrimes 2211573Srgrimes case RPKI_RTR_CACHE_RESPONSE_PDU: 2221573Srgrimes printf("%sCache-Nonce: 0x%04x", 2231573Srgrimes indent_string(indent+2), 2241573Srgrimes EXTRACT_16BITS(pdu_header->u.cache_nonce)); 2251573Srgrimes break; 2261573Srgrimes 2271573Srgrimes case RPKI_RTR_IPV4_PREFIX_PDU: 2281573Srgrimes { 2291573Srgrimes rpki_rtr_pdu_ipv4_prefix *pdu; 2301573Srgrimes 2311573Srgrimes pdu = (rpki_rtr_pdu_ipv4_prefix *)tptr; 2321573Srgrimes printf("%sIPv4 Prefix %s/%u-%u, origin-as %u, flags 0x%02x", 2331573Srgrimes indent_string(indent+2), 2341573Srgrimes ipaddr_string(pdu->prefix), 2351573Srgrimes pdu->prefix_length, pdu->max_length, 2361573Srgrimes EXTRACT_32BITS(pdu->as), pdu->flags); 2371573Srgrimes } 2381573Srgrimes break; 2391573Srgrimes 2401573Srgrimes#ifdef INET6 2411573Srgrimes case RPKI_RTR_IPV6_PREFIX_PDU: 2421573Srgrimes { 2431573Srgrimes rpki_rtr_pdu_ipv6_prefix *pdu; 2441573Srgrimes 2451573Srgrimes pdu = (rpki_rtr_pdu_ipv6_prefix *)tptr; 2461573Srgrimes printf("%sIPv6 Prefix %s/%u-%u, origin-as %u, flags 0x%02x", 2471573Srgrimes indent_string(indent+2), 2481573Srgrimes ip6addr_string(pdu->prefix), 2491573Srgrimes pdu->prefix_length, pdu->max_length, 2501573Srgrimes EXTRACT_32BITS(pdu->as), pdu->flags); 2511573Srgrimes } 2521573Srgrimes break; 2531573Srgrimes#endif 2541573Srgrimes 2551573Srgrimes case RPKI_RTR_ERROR_REPORT_PDU: 2561573Srgrimes { 2571573Srgrimes rpki_rtr_pdu_error_report *pdu; 2581573Srgrimes u_int encapsulated_pdu_length, text_length, tlen, error_code; 2591573Srgrimes u_char buf[80]; 2601573Srgrimes 2611573Srgrimes pdu = (rpki_rtr_pdu_error_report *)tptr; 2621573Srgrimes encapsulated_pdu_length = EXTRACT_32BITS(pdu->encapsulated_pdu_length); 2631573Srgrimes tlen = pdu_len; 2641573Srgrimes 2651573Srgrimes error_code = EXTRACT_16BITS(pdu->pdu_header.u.error_code); 2661573Srgrimes printf("%sError code: %s (%u), Encapsulated PDU length: %u", 2671573Srgrimes indent_string(indent+2), 2681573Srgrimes tok2str(rpki_rtr_error_codes, "Unknown", error_code), 2691573Srgrimes error_code, encapsulated_pdu_length); 2701573Srgrimes 2711573Srgrimes tptr += sizeof(*pdu); 2721573Srgrimes tlen -= sizeof(*pdu); 2731573Srgrimes 2741573Srgrimes /* 2751573Srgrimes * Recurse if there is an encapsulated PDU. 2761573Srgrimes */ 2771573Srgrimes if (encapsulated_pdu_length && 2781573Srgrimes (encapsulated_pdu_length <= tlen)) { 27921674Sjkh printf("%s-----encapsulated PDU-----", indent_string(indent+4)); 2801573Srgrimes rpki_rtr_pdu_print(tptr, indent+2); 2811573Srgrimes } 2821573Srgrimes 2831573Srgrimes tptr += encapsulated_pdu_length; 2841573Srgrimes tlen -= encapsulated_pdu_length; 2851573Srgrimes 2861573Srgrimes /* 28731871Sbde * Extract, trail-zero and print the Error message. 2881573Srgrimes */ 2891573Srgrimes text_length = 0; 2901573Srgrimes if (tlen > 4) { 2911573Srgrimes text_length = EXTRACT_32BITS(tptr); 2921573Srgrimes tptr += 4; 2931573Srgrimes tlen -= 4; 2941573Srgrimes } 2951573Srgrimes if (text_length && (text_length <= tlen )) { 2961573Srgrimes memcpy(buf, tptr, MIN(sizeof(buf)-1, text_length)); 2971573Srgrimes buf[text_length] = '\0'; 2981573Srgrimes printf("%sError text: %s", indent_string(indent+2), buf); 2991573Srgrimes } 3001573Srgrimes } 30121674Sjkh break; 3021573Srgrimes 3031573Srgrimes default: 3041573Srgrimes 3051573Srgrimes /* 3061573Srgrimes * Unknown data, please hexdump. 3071573Srgrimes */ 3081573Srgrimes hexdump = TRUE; 3091573Srgrimes } 3101573Srgrimes 3111573Srgrimes /* do we also want to see a hex dump ? */ 3121573Srgrimes if (vflag > 1 || (vflag && hexdump)) { 3131573Srgrimes print_unknown_data(tptr,"\n\t ", pdu_len); 3141573Srgrimes } 3151573Srgrimes} 3161573Srgrimes 3171573Srgrimesvoid 3181573Srgrimesrpki_rtr_print(register const u_char *pptr, register u_int len) { 3191573Srgrimes 3201573Srgrimes u_int tlen, pdu_type, pdu_len; 32114727Sfenner const u_char *tptr; 3221573Srgrimes const rpki_rtr_pdu *pdu_header; 32331983Sache 3241573Srgrimes tptr = pptr; 3251573Srgrimes tlen = len; 3261573Srgrimes 3271573Srgrimes if (!vflag) { 3281573Srgrimes printf(", RPKI-RTR"); 3291573Srgrimes return; 33021674Sjkh } 33121674Sjkh 33221674Sjkh while (tlen >= sizeof(rpki_rtr_pdu)) { 33321674Sjkh 3341573Srgrimes TCHECK2(*tptr, sizeof(rpki_rtr_pdu)); 3351573Srgrimes 3361573Srgrimes pdu_header = (rpki_rtr_pdu *)tptr; 3371573Srgrimes pdu_type = pdu_header->pdu_type; 3381573Srgrimes pdu_len = EXTRACT_32BITS(pdu_header->length); 3391573Srgrimes 3401573Srgrimes /* infinite loop check */ 3411573Srgrimes if (!pdu_type || !pdu_len) { 3421573Srgrimes break; 3431573Srgrimes } 3441573Srgrimes 3451573Srgrimes TCHECK2(*tptr, pdu_len); 3461573Srgrimes if (tlen < pdu_len) { 3471573Srgrimes goto trunc; 3481573Srgrimes } 3491573Srgrimes 3501573Srgrimes /* 3511573Srgrimes * Print the PDU. 3521573Srgrimes */ 3531573Srgrimes rpki_rtr_pdu_print(tptr, 8); 3541573Srgrimes 3551573Srgrimes tlen -= pdu_len; 3561573Srgrimes tptr += pdu_len; 3571573Srgrimes } 3581573Srgrimes return; 3591573Srgrimes trunc: 3601573Srgrimes printf("\n\t[|RPKI-RTR]"); 3611573Srgrimes} 3621573Srgrimes 3631573Srgrimes/* 3641573Srgrimes * Local Variables: 3651573Srgrimes * c-style: whitesmith 3661573Srgrimes * c-basic-offset: 4 3671573Srgrimes * End: 3681573Srgrimes */ 3691573Srgrimes