Skip to content

Commit 917f5f3

Browse files
author
Hannes Gredler
committed
add support for the RPKI/Router Protocol as per draft-ietf-sidr-rpki-rtr-12
1 parent 94a4b46 commit 917f5f3

File tree

8 files changed

+400
-1
lines changed

8 files changed

+400
-1
lines changed

Makefile.in

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ CSRC = addrtoname.c af.c checksum.c cpack.c gmpls.c oui.c gmt2local.c ipproto.c
8787
print-nfs.c print-ntp.c print-null.c print-olsr.c print-ospf.c \
8888
print-pgm.c print-pim.c \
8989
print-ppi.c print-ppp.c print-pppoe.c print-pptp.c \
90-
print-radius.c print-raw.c print-rip.c print-rrcp.c print-rsvp.c \
90+
print-radius.c print-raw.c print-rip.c print-rpki-rtr.c print-rrcp.c print-rsvp.c \
9191
print-rx.c print-sctp.c print-sflow.c print-sip.c print-sl.c print-sll.c \
9292
print-slow.c print-snmp.c print-stp.c print-sunatm.c print-sunrpc.c \
9393
print-symantec.c print-syslog.c print-tcp.c print-telnet.c print-tftp.c \

interface.h

+1
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ extern void cisco_autorp_print(const u_char *, u_int);
223223
extern void rsvp_print(const u_char *, u_int);
224224
extern void ldp_print(const u_char *, u_int);
225225
extern void lldp_print(const u_char *, u_int);
226+
extern void rpki_rtr_print(const u_char *, u_int);
226227
extern void lmp_print(const u_char *, u_int);
227228
extern void lspping_print(const u_char *, u_int);
228229
extern void lwapp_control_print(const u_char *, u_int, int);

netdissect.h

+1
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ extern void raw_if_print(u_char *,
397397
const struct pcap_pkthdr *, const u_char *);
398398

399399
extern void rip_print(netdissect_options *,const u_char *, u_int);
400+
extern void rpki_rtr_print(netdissect_options *,const u_char *, u_int);
400401

401402
extern void sctp_print(netdissect_options *ndo,
402403
const u_char *bp, const u_char *bp2,

print-rpki-rtr.c

+368
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,368 @@
1+
/*
2+
* Copyright (c) 1998-2011 The TCPDUMP project
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that: (1) source code
6+
* distributions retain the above copyright notice and this paragraph
7+
* in its entirety, and (2) distributions including binary code include
8+
* the above copyright notice and this paragraph in its entirety in
9+
* the documentation or other materials provided with the distribution.
10+
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND
11+
* WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
12+
* LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13+
* FOR A PARTICULAR PURPOSE.
14+
*
15+
* support for the The RPKI/Router Protocol Protocol as per draft-ietf-sidr-rpki-rtr-12
16+
*
17+
* Original code by Hannes Gredler ([email protected])
18+
*/
19+
20+
#ifndef lint
21+
static const char rcsid[] _U_ =
22+
"@(#) $Header: /tcpdump/master/tcpdump/print-rpki_rtr.c,v 1.10 2008-03-20 09:30:56 hannes Exp $";
23+
#endif
24+
25+
#ifdef HAVE_CONFIG_H
26+
#include "config.h"
27+
#endif
28+
29+
#include <tcpdump-stdinc.h>
30+
31+
#include <stdio.h>
32+
#include <stdlib.h>
33+
#include <string.h>
34+
35+
#include "interface.h"
36+
#include "extract.h"
37+
#include "addrtoname.h"
38+
39+
/*
40+
* RPKI/Router PDU header
41+
*
42+
* Here's what the PDU header looks like.
43+
* The length does include the version and length fields.
44+
*/
45+
typedef struct rpki_rtr_pdu_ {
46+
u_char version; /* Version number */
47+
u_char pdu_type; /* PDU type */
48+
union {
49+
u_char cache_nonce[2]; /* Cache Nonce */
50+
u_char error_code[2]; /* Error code */
51+
};
52+
u_char length[4];
53+
u_char msg[0]; /* message body */
54+
} __attribute__((packed)) rpki_rtr_pdu;
55+
#define RPKI_RTR_PDU_OVERHEAD (offsetof(rpki_rtr_pdu, rpki_rtr_pdu_msg))
56+
57+
/*
58+
* IPv4 Prefix PDU.
59+
*/
60+
typedef struct rpki_rtr_pdu_ipv4_prefix_ {
61+
rpki_rtr_pdu pdu_header;
62+
u_char flags;
63+
u_char prefix_length;
64+
u_char max_length;
65+
u_char zero;
66+
u_char prefix[4];
67+
u_char as[4];
68+
} __attribute__((packed)) rpki_rtr_pdu_ipv4_prefix;
69+
70+
/*
71+
* IPv6 Prefix PDU.
72+
*/
73+
typedef struct rpki_rtr_pdu_ipv6_prefix_ {
74+
rpki_rtr_pdu pdu_header;
75+
u_char flags;
76+
u_char prefix_length;
77+
u_char max_length;
78+
u_char zero;
79+
u_char prefix[16];
80+
u_char as[4];
81+
} __attribute__((packed)) rpki_rtr_pdu_ipv6_prefix;
82+
83+
/*
84+
* Error report PDU.
85+
*/
86+
typedef struct rpki_rtr_pdu_error_report_ {
87+
rpki_rtr_pdu pdu_header;
88+
u_char encapsulated_pdu_length[4]; /* Encapsulated PDU length */
89+
u_char variable[0];
90+
} __attribute__((packed)) rpki_rtr_pdu_error_report;
91+
92+
/*
93+
* PDU type codes
94+
*/
95+
#define RPKI_RTR_SERIAL_NOTIFY_PDU 0
96+
#define RPKI_RTR_SERIAL_QUERY_PDU 1
97+
#define RPKI_RTR_RESET_QUERY_PDU 2
98+
#define RPKI_RTR_CACHE_RESPONSE_PDU 3
99+
#define RPKI_RTR_IPV4_PREFIX_PDU 4
100+
#define RPKI_RTR_IPV6_PREFIX_PDU 6
101+
#define RPKI_RTR_END_OF_DATA_PDU 7
102+
#define RPKI_RTR_CACHE_RESET_PDU 8
103+
#define RPKI_RTR_ERROR_REPORT_PDU 10
104+
105+
static const struct tok rpki_rtr_pdu_values[] = {
106+
{ RPKI_RTR_SERIAL_NOTIFY_PDU, "Serial Notify" },
107+
{ RPKI_RTR_SERIAL_QUERY_PDU, "Serial Query" },
108+
{ RPKI_RTR_RESET_QUERY_PDU, "Reset Query" },
109+
{ RPKI_RTR_CACHE_RESPONSE_PDU, "Cache Response" },
110+
{ RPKI_RTR_IPV4_PREFIX_PDU, "IPV4 Prefix" },
111+
{ RPKI_RTR_IPV6_PREFIX_PDU, "IPV6 Prefix" },
112+
{ RPKI_RTR_END_OF_DATA_PDU, "End of Data" },
113+
{ RPKI_RTR_CACHE_RESET_PDU, "Cache Reset" },
114+
{ RPKI_RTR_ERROR_REPORT_PDU, "Error Report" },
115+
{ 0, NULL}
116+
};
117+
118+
static const struct tok rpki_rtr_error_codes[] = {
119+
{ 0, "Corrupt Data" },
120+
{ 1, "Internal Error" },
121+
{ 2, "No Data Available" },
122+
{ 3, "Invalid Request" },
123+
{ 4, "Unsupported Protocol Version" },
124+
{ 5, "Unsupported PDU Type" },
125+
{ 6, "Withdrawal of Unknown Record" },
126+
{ 7, "Duplicate Announcement Received" },
127+
{ 0, NULL}
128+
};
129+
130+
/*
131+
* Build a identation string for a given identation level.
132+
* XXX this should be really in util.c
133+
*/
134+
static char *
135+
indent_string (u_int indent)
136+
{
137+
static char buf[20];
138+
u_int idx;
139+
140+
idx = 0;
141+
buf[idx] = '\0';
142+
143+
/*
144+
* Does the static buffer fit ?
145+
*/
146+
if (sizeof(buf) < ((indent/8) + (indent %8) + 2)) {
147+
return buf;
148+
}
149+
150+
/*
151+
* Heading newline.
152+
*/
153+
buf[idx] = '\n';
154+
idx++;
155+
156+
while (indent >= 8) {
157+
buf[idx] = '\t';
158+
idx++;
159+
indent -= 8;
160+
}
161+
162+
while (indent > 0) {
163+
buf[idx] = ' ';
164+
idx++;
165+
indent--;
166+
}
167+
168+
/*
169+
* Trailing zero.
170+
*/
171+
buf[idx] = '\0';
172+
173+
return buf;
174+
}
175+
176+
/*
177+
* Print a single PDU.
178+
*/
179+
static int
180+
rpki_rtr_pdu_print (const u_char *tptr, u_int indent)
181+
{
182+
const rpki_rtr_pdu *pdu_header;
183+
u_int pdu_type, pdu_len, hexdump;
184+
185+
pdu_header = (rpki_rtr_pdu *)tptr;
186+
pdu_type = pdu_header->pdu_type;
187+
pdu_len = pdu_len = EXTRACT_32BITS(pdu_header->length);
188+
hexdump = FALSE;
189+
190+
printf("%sRPKI-RTRv%u, %s PDU (%u), length: %u",
191+
indent_string(8),
192+
pdu_header->version,
193+
tok2str(rpki_rtr_pdu_values, "Unknown", pdu_type),
194+
pdu_type, pdu_len);
195+
196+
switch (pdu_type) {
197+
198+
/*
199+
* The following PDUs share the message format.
200+
*/
201+
case RPKI_RTR_SERIAL_NOTIFY_PDU:
202+
case RPKI_RTR_SERIAL_QUERY_PDU:
203+
case RPKI_RTR_END_OF_DATA_PDU:
204+
printf("%sCache-Nonce: 0x%04x, Serial: %u",
205+
indent_string(indent+2),
206+
EXTRACT_16BITS(pdu_header->cache_nonce),
207+
EXTRACT_32BITS(pdu_header->msg));
208+
break;
209+
210+
/*
211+
* The following PDUs share the message format.
212+
*/
213+
case RPKI_RTR_RESET_QUERY_PDU:
214+
case RPKI_RTR_CACHE_RESET_PDU:
215+
216+
/*
217+
* Zero payload PDUs.
218+
*/
219+
break;
220+
221+
case RPKI_RTR_CACHE_RESPONSE_PDU:
222+
printf("%sCache-Nonce: 0x%04x",
223+
indent_string(indent+2),
224+
EXTRACT_16BITS(pdu_header->cache_nonce));
225+
break;
226+
227+
case RPKI_RTR_IPV4_PREFIX_PDU:
228+
{
229+
rpki_rtr_pdu_ipv4_prefix *pdu;
230+
231+
pdu = (rpki_rtr_pdu_ipv4_prefix *)tptr;
232+
printf("%sIPv4 Prefix %s/%u-%u, origin-as %u, flags 0x%02x",
233+
indent_string(indent+2),
234+
ipaddr_string(pdu->prefix),
235+
pdu->prefix_length, pdu->max_length,
236+
EXTRACT_32BITS(pdu->as), pdu->flags);
237+
}
238+
break;
239+
240+
#ifdef INET6
241+
case RPKI_RTR_IPV6_PREFIX_PDU:
242+
{
243+
rpki_rtr_pdu_ipv6_prefix *pdu;
244+
245+
pdu = (rpki_rtr_pdu_ipv6_prefix *)tptr;
246+
printf("%sIPv6 Prefix %s/%u-%u, origin-as %u, flags 0x%02x",
247+
indent_string(indent+2),
248+
ip6addr_string(pdu->prefix),
249+
pdu->prefix_length, pdu->max_length,
250+
EXTRACT_32BITS(pdu->as), pdu->flags);
251+
}
252+
break;
253+
#endif
254+
255+
case RPKI_RTR_ERROR_REPORT_PDU:
256+
{
257+
rpki_rtr_pdu_error_report *pdu;
258+
u_int encapsulated_pdu_length, text_length, tlen, error_code;
259+
u_char buf[80];
260+
261+
pdu = (rpki_rtr_pdu_error_report *)tptr;
262+
encapsulated_pdu_length = EXTRACT_32BITS(pdu->encapsulated_pdu_length);
263+
tlen = pdu_len;
264+
265+
error_code = EXTRACT_16BITS(pdu->pdu_header.error_code);
266+
printf("%sError code: %s (%u), Encapsulated PDU length: %u",
267+
indent_string(indent+2),
268+
tok2str(rpki_rtr_error_codes, "Unknown", error_code),
269+
error_code, encapsulated_pdu_length);
270+
271+
tptr += sizeof(*pdu);
272+
tlen -= sizeof(*pdu);
273+
274+
/*
275+
* Recurse if there is an encapsulated PDU.
276+
*/
277+
if (encapsulated_pdu_length &&
278+
(encapsulated_pdu_length <= tlen)) {
279+
printf("%s-----encapsulated PDU-----", indent_string(indent+4));
280+
rpki_rtr_pdu_print(tptr, indent+2);
281+
}
282+
283+
tptr += encapsulated_pdu_length;
284+
tlen -= encapsulated_pdu_length;
285+
286+
/*
287+
* Extract, trail-zero and print the Error message.
288+
*/
289+
text_length = 0;
290+
if (tlen > 4) {
291+
text_length = EXTRACT_32BITS(tptr);
292+
tptr += 4;
293+
tlen -= 4;
294+
}
295+
if (text_length && (text_length <= tlen )) {
296+
memcpy(buf, tptr, MIN(sizeof(buf)-1, text_length));
297+
buf[text_length] = '\0';
298+
printf("%sError text: %s", indent_string(indent+2), buf);
299+
}
300+
}
301+
break;
302+
303+
default:
304+
305+
/*
306+
* Unknown data, please hexdump.
307+
*/
308+
hexdump = TRUE;
309+
}
310+
311+
/* do we also want to see a hex dump ? */
312+
if (vflag > 1 || (vflag && hexdump)) {
313+
print_unknown_data(tptr,"\n\t ", pdu_len);
314+
}
315+
}
316+
317+
void
318+
rpki_rtr_print(register const u_char *pptr, register u_int len) {
319+
320+
u_int tlen, pdu_type, pdu_len;
321+
const u_char *tptr;
322+
const rpki_rtr_pdu *pdu_header;
323+
324+
tptr = pptr;
325+
tlen = len;
326+
327+
if (!vflag) {
328+
printf(", RPKI-RTR");
329+
return;
330+
}
331+
332+
while (tlen >= sizeof(rpki_rtr_pdu)) {
333+
334+
TCHECK2(*tptr, sizeof(rpki_rtr_pdu));
335+
336+
pdu_header = (rpki_rtr_pdu *)tptr;
337+
pdu_type = pdu_header->pdu_type;
338+
pdu_len = EXTRACT_32BITS(pdu_header->length);
339+
340+
/* infinite loop check */
341+
if (!pdu_type || !pdu_len) {
342+
break;
343+
}
344+
345+
TCHECK2(*tptr, pdu_len);
346+
if (tlen < pdu_len) {
347+
goto trunc;
348+
}
349+
350+
/*
351+
* Print the PDU.
352+
*/
353+
rpki_rtr_pdu_print(tptr, 8);
354+
355+
tlen -= pdu_len;
356+
tptr += pdu_len;
357+
}
358+
return;
359+
trunc:
360+
printf("\n\t[|RPKI-RTR]");
361+
}
362+
363+
/*
364+
* Local Variables:
365+
* c-style: whitesmith
366+
* c-basic-offset: 4
367+
* End:
368+
*/

0 commit comments

Comments
 (0)