]> The Tcpdump Group git mirrors - tcpdump/commitdiff
add support for the RPKI/Router Protocol as per draft-ietf-sidr-rpki-rtr-12
authorHannes Gredler <[email protected]>
Thu, 16 Jun 2011 15:17:20 +0000 (17:17 +0200)
committerHannes Gredler <[email protected]>
Thu, 16 Jun 2011 15:17:20 +0000 (17:17 +0200)
Makefile.in
interface.h
netdissect.h
print-rpki-rtr.c [new file with mode: 0644]
print-tcp.c
tcp.h
win32/prj/WinDump.dsp
win32/prj/WinDump.vcproj

index 666420a440962449f50ef602e9a9f8b9f6007633..ae8d17c2846b998ae1a4f992a06dbdeaabca5e02 100644 (file)
@@ -87,7 +87,7 @@ CSRC =        addrtoname.c af.c checksum.c cpack.c gmpls.c oui.c gmt2local.c ipproto.c
        print-nfs.c print-ntp.c print-null.c print-olsr.c print-ospf.c \
        print-pgm.c print-pim.c \
        print-ppi.c print-ppp.c print-pppoe.c print-pptp.c \
-       print-radius.c print-raw.c print-rip.c print-rrcp.c print-rsvp.c \
+       print-radius.c print-raw.c print-rip.c print-rpki-rtr.c print-rrcp.c print-rsvp.c \
        print-rx.c print-sctp.c print-sflow.c print-sip.c print-sl.c print-sll.c \
        print-slow.c print-snmp.c print-stp.c print-sunatm.c print-sunrpc.c \
        print-symantec.c print-syslog.c print-tcp.c print-telnet.c print-tftp.c \
index 4862ff3cb0a904dd8cdf92b0953dc07a80d354d0..9109a4532219fda14836a4fe38cb30527a39f85b 100644 (file)
@@ -223,6 +223,7 @@ extern void cisco_autorp_print(const u_char *, u_int);
 extern void rsvp_print(const u_char *, u_int);
 extern void ldp_print(const u_char *, u_int);
 extern void lldp_print(const u_char *, u_int);
+extern void rpki_rtr_print(const u_char *, u_int);
 extern void lmp_print(const u_char *, u_int);
 extern void lspping_print(const u_char *, u_int);
 extern void lwapp_control_print(const u_char *, u_int, int);
index c459b4c9f0936e647ec29e5bcd8859adf8828846..0c829e62c83ca4113da19092e80865fb17a343c8 100644 (file)
@@ -397,6 +397,7 @@ extern void raw_if_print(u_char *,
                         const struct pcap_pkthdr *, const u_char *);
 
 extern void rip_print(netdissect_options *,const u_char *, u_int);
+extern void rpki_rtr_print(netdissect_options *,const u_char *, u_int);
 
 extern void sctp_print(netdissect_options *ndo,
                       const u_char *bp, const u_char *bp2,       
diff --git a/print-rpki-rtr.c b/print-rpki-rtr.c
new file mode 100644 (file)
index 0000000..d560286
--- /dev/null
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 1998-2011 The TCPDUMP project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code
+ * distributions retain the above copyright notice and this paragraph
+ * in its entirety, and (2) distributions including binary code include
+ * the above copyright notice and this paragraph in its entirety in
+ * the documentation or other materials provided with the distribution.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * support for the The RPKI/Router Protocol Protocol as per draft-ietf-sidr-rpki-rtr-12
+ *
+ * Original code by Hannes Gredler ([email protected])
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+"@(#) $Header: /tcpdump/master/tcpdump/print-rpki_rtr.c,v 1.10 2008-03-20 09:30:56 hannes Exp $";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "interface.h"
+#include "extract.h"
+#include "addrtoname.h"
+
+/*
+ * RPKI/Router PDU header
+ *
+ * Here's what the PDU header looks like.
+ * The length does include the version and length fields.
+ */
+typedef struct rpki_rtr_pdu_ {
+    u_char version;            /* Version number */
+    u_char pdu_type;           /* PDU type */
+    union {
+       u_char cache_nonce[2];  /* Cache Nonce */
+       u_char error_code[2];   /* Error code */
+    };
+    u_char length[4];
+    u_char msg[0];             /* message body */
+} __attribute__((packed)) rpki_rtr_pdu;
+#define RPKI_RTR_PDU_OVERHEAD (offsetof(rpki_rtr_pdu, rpki_rtr_pdu_msg))
+
+/*
+ * IPv4 Prefix PDU.
+ */
+typedef struct rpki_rtr_pdu_ipv4_prefix_ {
+    rpki_rtr_pdu pdu_header;
+    u_char flags;
+    u_char prefix_length;
+    u_char max_length;
+    u_char zero;
+    u_char prefix[4];
+    u_char as[4];
+} __attribute__((packed)) rpki_rtr_pdu_ipv4_prefix;
+
+/*
+ * IPv6 Prefix PDU.
+ */
+typedef struct rpki_rtr_pdu_ipv6_prefix_ {
+    rpki_rtr_pdu pdu_header;
+    u_char flags;
+    u_char prefix_length;
+    u_char max_length;
+    u_char zero;
+    u_char prefix[16];
+    u_char as[4];
+} __attribute__((packed)) rpki_rtr_pdu_ipv6_prefix;
+
+/*
+ * Error report PDU.
+ */
+typedef struct rpki_rtr_pdu_error_report_ {
+    rpki_rtr_pdu pdu_header;
+    u_char encapsulated_pdu_length[4]; /* Encapsulated PDU length */
+    u_char variable[0];
+} __attribute__((packed)) rpki_rtr_pdu_error_report;
+
+/*
+ * PDU type codes
+ */
+#define RPKI_RTR_SERIAL_NOTIFY_PDU     0
+#define RPKI_RTR_SERIAL_QUERY_PDU      1
+#define RPKI_RTR_RESET_QUERY_PDU       2
+#define RPKI_RTR_CACHE_RESPONSE_PDU    3
+#define RPKI_RTR_IPV4_PREFIX_PDU       4
+#define RPKI_RTR_IPV6_PREFIX_PDU       6
+#define RPKI_RTR_END_OF_DATA_PDU       7
+#define RPKI_RTR_CACHE_RESET_PDU       8
+#define RPKI_RTR_ERROR_REPORT_PDU      10
+
+static const struct tok rpki_rtr_pdu_values[] = {
+    { RPKI_RTR_SERIAL_NOTIFY_PDU, "Serial Notify" },
+    { RPKI_RTR_SERIAL_QUERY_PDU, "Serial Query" },
+    { RPKI_RTR_RESET_QUERY_PDU, "Reset Query" },
+    { RPKI_RTR_CACHE_RESPONSE_PDU, "Cache Response" },
+    { RPKI_RTR_IPV4_PREFIX_PDU, "IPV4 Prefix" },
+    { RPKI_RTR_IPV6_PREFIX_PDU, "IPV6 Prefix" },
+    { RPKI_RTR_END_OF_DATA_PDU, "End of Data" },
+    { RPKI_RTR_CACHE_RESET_PDU, "Cache Reset" },
+    { RPKI_RTR_ERROR_REPORT_PDU, "Error Report" },
+    { 0, NULL}
+};
+
+static const struct tok rpki_rtr_error_codes[] = {
+    { 0, "Corrupt Data" },
+    { 1, "Internal Error" },
+    { 2, "No Data Available" },
+    { 3, "Invalid Request" },
+    { 4, "Unsupported Protocol Version" },
+    { 5, "Unsupported PDU Type" },
+    { 6, "Withdrawal of Unknown Record" },
+    { 7, "Duplicate Announcement Received" },
+    { 0, NULL}
+};
+
+/*
+ * Build a identation string for a given identation level.
+ * XXX this should be really in util.c
+ */
+static char *
+indent_string (u_int indent)
+{
+    static char buf[20];
+    u_int idx;
+
+    idx = 0;
+    buf[idx] = '\0';
+
+    /*
+     * Does the static buffer fit ?
+     */
+    if (sizeof(buf) < ((indent/8) + (indent %8) + 2)) {
+       return buf;
+    }
+
+    /*
+     * Heading newline.
+     */
+    buf[idx] = '\n';
+    idx++;
+
+    while (indent >= 8) {
+       buf[idx] = '\t';
+       idx++;
+       indent -= 8;
+    }
+
+    while (indent > 0) {
+       buf[idx] = ' ';
+       idx++;
+       indent--;
+    }
+
+    /*
+     * Trailing zero.
+     */
+    buf[idx] = '\0';
+    
+    return buf;
+}
+
+/*
+ * Print a single PDU.
+ */
+static int
+rpki_rtr_pdu_print (const u_char *tptr, u_int indent)
+{
+    const rpki_rtr_pdu *pdu_header;
+    u_int pdu_type, pdu_len, hexdump;
+
+    pdu_header = (rpki_rtr_pdu *)tptr;
+    pdu_type = pdu_header->pdu_type;
+    pdu_len = pdu_len = EXTRACT_32BITS(pdu_header->length);
+    hexdump = FALSE;
+
+    printf("%sRPKI-RTRv%u, %s PDU (%u), length: %u",
+          indent_string(8),
+          pdu_header->version,
+          tok2str(rpki_rtr_pdu_values, "Unknown", pdu_type),
+          pdu_type, pdu_len);
+
+    switch (pdu_type) {
+
+       /*
+        * The following PDUs share the message format.
+        */
+    case RPKI_RTR_SERIAL_NOTIFY_PDU:
+    case RPKI_RTR_SERIAL_QUERY_PDU:
+    case RPKI_RTR_END_OF_DATA_PDU:
+       printf("%sCache-Nonce: 0x%04x, Serial: %u",
+              indent_string(indent+2),
+              EXTRACT_16BITS(pdu_header->cache_nonce),
+              EXTRACT_32BITS(pdu_header->msg));
+       break;
+
+       /*
+        * The following PDUs share the message format.
+        */
+    case RPKI_RTR_RESET_QUERY_PDU:
+    case RPKI_RTR_CACHE_RESET_PDU:
+
+       /*
+        * Zero payload PDUs.
+        */
+       break;
+
+    case RPKI_RTR_CACHE_RESPONSE_PDU:
+       printf("%sCache-Nonce: 0x%04x",
+              indent_string(indent+2),
+              EXTRACT_16BITS(pdu_header->cache_nonce));
+       break;
+
+    case RPKI_RTR_IPV4_PREFIX_PDU:
+       {
+           rpki_rtr_pdu_ipv4_prefix *pdu;
+
+           pdu = (rpki_rtr_pdu_ipv4_prefix *)tptr;
+           printf("%sIPv4 Prefix %s/%u-%u, origin-as %u, flags 0x%02x",
+                  indent_string(indent+2),
+                  ipaddr_string(pdu->prefix),
+                  pdu->prefix_length, pdu->max_length,
+                  EXTRACT_32BITS(pdu->as), pdu->flags);
+       }
+       break;
+
+#ifdef INET6
+    case RPKI_RTR_IPV6_PREFIX_PDU:
+       {
+           rpki_rtr_pdu_ipv6_prefix *pdu;
+
+           pdu = (rpki_rtr_pdu_ipv6_prefix *)tptr;
+           printf("%sIPv6 Prefix %s/%u-%u, origin-as %u, flags 0x%02x",
+                  indent_string(indent+2),
+                  ip6addr_string(pdu->prefix),
+                  pdu->prefix_length, pdu->max_length,
+                  EXTRACT_32BITS(pdu->as), pdu->flags);
+       }
+       break;
+#endif
+
+    case RPKI_RTR_ERROR_REPORT_PDU:
+       {
+           rpki_rtr_pdu_error_report *pdu;
+           u_int encapsulated_pdu_length, text_length, tlen, error_code;
+           u_char buf[80];
+
+           pdu = (rpki_rtr_pdu_error_report *)tptr;
+           encapsulated_pdu_length = EXTRACT_32BITS(pdu->encapsulated_pdu_length);
+           tlen = pdu_len;
+
+           error_code = EXTRACT_16BITS(pdu->pdu_header.error_code);
+           printf("%sError code: %s (%u), Encapsulated PDU length: %u",
+                  indent_string(indent+2),
+                  tok2str(rpki_rtr_error_codes, "Unknown", error_code),
+                  error_code, encapsulated_pdu_length);
+
+           tptr += sizeof(*pdu);
+           tlen -= sizeof(*pdu);
+
+           /*
+            * Recurse if there is an encapsulated PDU.
+            */
+           if (encapsulated_pdu_length &&
+               (encapsulated_pdu_length <= tlen)) {
+               printf("%s-----encapsulated PDU-----", indent_string(indent+4));
+               rpki_rtr_pdu_print(tptr, indent+2);
+           }
+
+           tptr += encapsulated_pdu_length;
+           tlen -= encapsulated_pdu_length;
+
+           /*
+            * Extract, trail-zero and print the Error message.
+            */ 
+           text_length = 0;
+           if (tlen > 4) {
+               text_length = EXTRACT_32BITS(tptr);
+               tptr += 4;
+               tlen -= 4;
+           }
+           if (text_length && (text_length <= tlen )) {
+               memcpy(buf, tptr, MIN(sizeof(buf)-1, text_length));
+               buf[text_length] = '\0';
+               printf("%sError text: %s", indent_string(indent+2), buf);
+           }
+       }
+       break;
+
+    default:
+
+       /*
+        * Unknown data, please hexdump.
+        */ 
+       hexdump = TRUE;
+    }
+
+    /* do we also want to see a hex dump ? */
+    if (vflag > 1 || (vflag && hexdump)) {
+       print_unknown_data(tptr,"\n\t  ", pdu_len);
+    }
+}
+
+void
+rpki_rtr_print(register const u_char *pptr, register u_int len) {
+
+    u_int tlen, pdu_type, pdu_len;
+    const u_char *tptr;
+    const rpki_rtr_pdu *pdu_header;
+    
+    tptr = pptr;
+    tlen = len;
+
+    if (!vflag) {
+       printf(", RPKI-RTR");
+       return;
+    }
+
+    while (tlen >= sizeof(rpki_rtr_pdu)) {
+
+        TCHECK2(*tptr, sizeof(rpki_rtr_pdu));
+
+       pdu_header = (rpki_rtr_pdu *)tptr;
+        pdu_type = pdu_header->pdu_type;
+        pdu_len = EXTRACT_32BITS(pdu_header->length);
+
+        /* infinite loop check */
+        if (!pdu_type || !pdu_len) {
+            break;
+        }
+
+        TCHECK2(*tptr, pdu_len);
+        if (tlen < pdu_len) {
+            goto trunc;
+        }
+
+       /*
+        * Print the PDU.
+        */
+       rpki_rtr_pdu_print(tptr, 8);
+
+        tlen -= pdu_len;
+        tptr += pdu_len;
+    }
+    return;
+ trunc:
+    printf("\n\t[|RPKI-RTR]");
+}
+
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 4
+ * End:
+ */
index 1381799cd8003b968c20a27f553c549dfd36c9ab..dca5108c2628ab9ef40cab618e9ae8e67e073e25 100644 (file)
@@ -680,6 +680,8 @@ tcp_print(register const u_char *bp, register u_int length,
                 ns_print(bp + 2, length - 2, 0);
         } else if (sport == MSDP_PORT || dport == MSDP_PORT) {
                 msdp_print(bp, length);
+        } else if (sport == RPKI_RTR_PORT || dport == RPKI_RTR_PORT) {
+                rpki_rtr_print(bp, length);
         }
         else if (length > 0 && (sport == LDP_PORT || dport == LDP_PORT)) {
                 ldp_print(bp, length);
diff --git a/tcp.h b/tcp.h
index ac83714fe29e08c050eef8d09906bc5fbd204dc6..45fc21c0d5041fa3b303cf1d81f59504a01cd65f 100644 (file)
--- a/tcp.h
+++ b/tcp.h
@@ -105,6 +105,7 @@ struct tcphdr {
 #define NFS_PORT               2049
 #endif
 #define MSDP_PORT              639
+#define RPKI_RTR_PORT          2222 /* experimental up until sidr-wg registers a well-known port */
 #define LDP_PORT                646
 #ifndef SMB_PORT
 #define SMB_PORT                445
index 2470dd60fddeb2823c3adc80fa2d432af61eced3..f3b35132ffcf577e4f3d5512b86c330927dd9c2c 100644 (file)
@@ -485,6 +485,10 @@ SOURCE="..\..\print-ripng.c"
 # End Source File
 # Begin Source File
 
+SOURCE="..\..\print-rpki-rtr.c"
+# End Source File
+# Begin Source File
+
 SOURCE="..\..\print-rsvp.c"
 # End Source File
 # Begin Source File
index d45544853fd5a37309fe5932b5b060e1b1eee11e..d42d4bc4e1282e7957ed2659f48e7e2ff479c78d 100644 (file)
                                />
                        </FileConfiguration>
                </File>
+               <File
+                       RelativePath="..\..\print-rpki-rtr.c"
+                       >
+                       <FileConfiguration
+                               Name="Debug|Win32"
+                               >
+                               <Tool
+                                       Name="VCCLCompilerTool"
+                                       AdditionalIncludeDirectories=""
+                                       PreprocessorDefinitions=""
+                               />
+                       </FileConfiguration>
+                       <FileConfiguration
+                               Name="Release|Win32"
+                               >
+                               <Tool
+                                       Name="VCCLCompilerTool"
+                                       AdditionalIncludeDirectories=""
+                                       PreprocessorDefinitions=""
+                               />
+                       </FileConfiguration>
+               </File>
                <File
                        RelativePath="..\..\print-rrcp.c"
                        >