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