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