2 * Routines for RPKI-Router Protocol dissection (RFC6810)
3 * Copyright 2013, Alexis La Goutte <alexis.lagoutte at gmail dot com>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 * The information used comes from:
26 * RFC6810: The Resource Public Key Infrastructure (RPKI) to Router Protocol
33 #include <epan/packet.h>
34 #include <epan/prefs.h>
35 #include "packet-tcp.h"
37 void proto_reg_handoff_rpkirtr(void);
39 static int proto_rpkirtr
= -1;
40 static int hf_rpkirtr_version
= -1;
41 static int hf_rpkirtr_pdu_type
= -1;
42 static int hf_rpkirtr_reserved
= -1;
43 static int hf_rpkirtr_session_id
= -1;
44 static int hf_rpkirtr_length
= -1;
45 static int hf_rpkirtr_serial_number
= -1;
46 static int hf_rpkirtr_flags
= -1;
47 static int hf_rpkirtr_flags_aw
= -1;
48 static int hf_rpkirtr_prefix_length
= -1;
49 static int hf_rpkirtr_max_length
= -1;
50 static int hf_rpkirtr_ipv4_prefix
= -1;
51 static int hf_rpkirtr_ipv6_prefix
= -1;
52 static int hf_rpkirtr_as_number
= -1;
53 static int hf_rpkirtr_error_code
= -1;
54 static int hf_rpkirtr_length_pdu
= -1;
55 static int hf_rpkirtr_error_pdu
= -1;
56 static int hf_rpkirtr_length_text
= -1;
57 static int hf_rpkirtr_error_text
= -1;
59 static guint g_port_rpkirtr
= 323;
60 static guint g_port_rpkirtr_tls
= 324;
62 static gint ett_rpkirtr
= -1;
63 static gint ett_flags
= -1;
66 /* http://www.iana.org/assignments/rpki/rpki.xml#rpki-rtr-pdu */
67 #define RPKI_RTR_SERIAL_NOTIFY_PDU 0
68 #define RPKI_RTR_SERIAL_QUERY_PDU 1
69 #define RPKI_RTR_RESET_QUERY_PDU 2
70 #define RPKI_RTR_CACHE_RESPONSE_PDU 3
71 #define RPKI_RTR_IPV4_PREFIX_PDU 4
72 #define RPKI_RTR_IPV6_PREFIX_PDU 6
73 #define RPKI_RTR_END_OF_DATA_PDU 7
74 #define RPKI_RTR_CACHE_RESET_PDU 8
75 #define RPKI_RTR_ERROR_REPORT_PDU 10
77 static const value_string rtr_pdu_type_vals
[] = {
78 { RPKI_RTR_SERIAL_NOTIFY_PDU
, "Serial Notify" },
79 { RPKI_RTR_SERIAL_QUERY_PDU
, "Serial Query" },
80 { RPKI_RTR_RESET_QUERY_PDU
, "Reset Query" },
81 { RPKI_RTR_CACHE_RESPONSE_PDU
, "Cache Response" },
82 { RPKI_RTR_IPV4_PREFIX_PDU
, "IPV4 Prefix" },
83 { RPKI_RTR_IPV6_PREFIX_PDU
, "IPV6 Prefix" },
84 { RPKI_RTR_END_OF_DATA_PDU
, "End of Data" },
85 { RPKI_RTR_CACHE_RESET_PDU
, "Cache Reset" },
86 { RPKI_RTR_ERROR_REPORT_PDU
, "Error Report" },
90 /* http://www.iana.org/assignments/rpki/rpki.xml#rpki-rtr-error */
91 static const value_string rtr_error_code_vals
[] = {
92 { 0, "Corrupt Data" },
93 { 1, "Internal Error" },
94 { 2, "No Data Available" },
95 { 3, "Invalid Request" },
96 { 4, "Unsupported Protocol Version" },
97 { 5, "Unsupported PDU Type" },
98 { 6, "Withdrawal of Unknown Record" },
99 { 7, "Duplicate Announcement Received" },
103 static const true_false_string tfs_flag_type_aw
= {
109 get_rpkirtr_pdu_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
, int offset
)
114 * Get the length of the RPKI-RTR packet.
116 plen
= tvb_get_ntohl(tvb
, offset
+4);
122 static int dissect_rpkirtr_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
125 proto_item
*ti
= NULL
, *ti_flags
;
126 proto_tree
*rpkirtr_tree
= NULL
, *flags_tree
= NULL
;
130 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "RPKI-RTR");
131 col_clear(pinfo
->cinfo
, COL_INFO
);
133 while (tvb_reported_length_remaining(tvb
, offset
) != 0) {
136 ti
= proto_tree_add_item(tree
, proto_rpkirtr
, tvb
, 0, -1, ENC_NA
);
138 rpkirtr_tree
= proto_item_add_subtree(ti
, ett_rpkirtr
);
141 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_version
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
144 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_pdu_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
145 pdu_type
= tvb_get_guint8(tvb
, offset
);
146 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, NULL
, val_to_str(pdu_type
, rtr_pdu_type_vals
, "Unknown %d"));
147 proto_item_append_text(ti
, " (%s)", val_to_str(pdu_type
, rtr_pdu_type_vals
, "Unknown %d"));
151 case RPKI_RTR_SERIAL_NOTIFY_PDU
: /* Serial Notify (0) */
152 case RPKI_RTR_SERIAL_QUERY_PDU
: /* Serial Query (1) */
153 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_session_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
155 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_length
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
156 /* TODO: Add check length ? */
158 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_serial_number
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
161 case RPKI_RTR_RESET_QUERY_PDU
: /* Reset Query (2) */
162 case RPKI_RTR_CACHE_RESET_PDU
: /* Cache Reset (8) */
163 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_reserved
, tvb
, offset
, 2, ENC_NA
);
165 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_length
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
166 /* TODO: Add check length ? */
169 case RPKI_RTR_CACHE_RESPONSE_PDU
: /* Cache Response (3) */
170 case RPKI_RTR_END_OF_DATA_PDU
: /* End Of Data (7) */
171 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_session_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
173 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_length
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
174 /* TODO: Add check length ? */
177 case RPKI_RTR_IPV4_PREFIX_PDU
: /* IPv4 Prefix (4) */
178 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_reserved
, tvb
, offset
, 2, ENC_NA
);
180 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_length
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
181 /* TODO: Add check length ? */
183 ti_flags
= proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_flags
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
184 flags_tree
= proto_item_add_subtree(ti_flags
, ett_flags
);
185 proto_tree_add_item(flags_tree
, hf_rpkirtr_flags_aw
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
187 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_prefix_length
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
189 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_max_length
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
191 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_reserved
, tvb
, offset
, 1, ENC_NA
);
193 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_ipv4_prefix
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
195 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_as_number
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
198 case RPKI_RTR_IPV6_PREFIX_PDU
: /* IPv4 Prefix (6) */
199 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_reserved
, tvb
, offset
, 2, ENC_NA
);
201 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_length
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
202 /* TODO: Add check length ? */
204 ti_flags
= proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_flags
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
205 flags_tree
= proto_item_add_subtree(ti_flags
, ett_flags
);
206 proto_tree_add_item(flags_tree
, hf_rpkirtr_flags_aw
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
208 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_prefix_length
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
210 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_max_length
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
212 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_reserved
, tvb
, offset
, 1, ENC_NA
);
214 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_ipv6_prefix
, tvb
, offset
, 16, ENC_NA
);
216 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_as_number
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
219 case RPKI_RTR_ERROR_REPORT_PDU
: /* Error Report (10) */
221 guint32 len_pdu
, len_text
;
222 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_error_code
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
224 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_length
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
225 /* TODO: Add check length ? */
227 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_length_pdu
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
228 len_pdu
= tvb_get_ntohl(tvb
, offset
);
230 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_error_pdu
, tvb
, offset
, len_pdu
, ENC_NA
);
232 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_length_text
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
233 len_text
= tvb_get_ntohl(tvb
, offset
);
235 proto_tree_add_item(rpkirtr_tree
, hf_rpkirtr_error_text
, tvb
, offset
, len_text
, ENC_ASCII
|ENC_NA
);
244 return tvb_length(tvb
);
248 dissect_rpkirtr(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
250 tcp_dissect_pdus(tvb
, pinfo
, tree
, 1, 8, get_rpkirtr_pdu_len
, dissect_rpkirtr_pdu
, data
);
251 return tvb_length(tvb
);
255 proto_register_rpkirtr(void)
257 module_t
*rpkirtr_module
;
259 static hf_register_info hf
[] = {
260 { &hf_rpkirtr_version
,
261 { "Version", "rpki-rtr.version",
262 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
263 "Denoting the version of this protocol (currently 0)", HFILL
}
265 { &hf_rpkirtr_pdu_type
,
266 { "PDU Type", "rpki-rtr.pdu_type",
267 FT_UINT8
, BASE_DEC
, VALS(rtr_pdu_type_vals
), 0x0,
268 "Denoting the type of the PDU", HFILL
}
270 { &hf_rpkirtr_reserved
,
271 { "Reserved", "rpki-rtr.reserved",
272 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
273 "Must be zero", HFILL
}
275 { &hf_rpkirtr_session_id
,
276 { "Session ID", "rpki-rtr.session_id",
277 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
280 { &hf_rpkirtr_length
,
281 { "Length", "rpki-rtr.length",
282 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
283 "Value the count of the bytes in the entire PDU, including the eight bytes of header that end with the length field", HFILL
}
285 { &hf_rpkirtr_serial_number
,
286 { "Serial Number", "rpki-rtr.serial_number",
287 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
291 { "Flags", "rpki-rtr.flags",
292 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
295 { &hf_rpkirtr_flags_aw
,
296 { "Flag AW", "rpki-rtr.flags.aw",
297 FT_BOOLEAN
, 8, TFS(&tfs_flag_type_aw
), 0x01,
300 { &hf_rpkirtr_prefix_length
,
301 { "Prefix Length", "rpki-rtr.prefix_length",
302 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
303 "Denoting the shortest prefix allowed for the prefix", HFILL
}
305 { &hf_rpkirtr_max_length
,
306 { "Max length", "rpki-rtr.max_length",
307 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
308 "Denoting the longest prefix allowed by the prefix. This MUST NOT be less than the Prefix Length element", HFILL
}
310 { &hf_rpkirtr_ipv4_prefix
,
311 { "IPv4 Prefix", "rpki-rtr.ipv4_prefix",
312 FT_IPv4
, BASE_NONE
, NULL
, 0x0,
313 "The IPv4 prefix of the ROA", HFILL
}
315 { &hf_rpkirtr_ipv6_prefix
,
316 { "IPv6 Prefix", "rpki-rtr.ipv6_prefix",
317 FT_IPv6
, BASE_NONE
, NULL
, 0x0,
318 "The IPv6 prefix of the ROA", HFILL
}
320 { &hf_rpkirtr_as_number
,
321 { "AS Number", "rpki-rtr.as_number",
322 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
323 "Autonomous System Number allowed to announce this prefix", HFILL
}
325 { &hf_rpkirtr_error_code
,
326 { "Error Code", "rpki-rtr.error_code",
327 FT_UINT16
, BASE_DEC
, VALS(rtr_error_code_vals
), 0x0,
330 { &hf_rpkirtr_length_pdu
,
331 { "Length of Encapsulated PDU", "rpki-rtr.length_pdu",
332 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
335 { &hf_rpkirtr_error_pdu
,
336 { "Erroneous PDU", "rpki-rtr.error_pdu",
337 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
340 { &hf_rpkirtr_length_text
,
341 { "Length of text", "rpki-rtr.length_text",
342 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
345 { &hf_rpkirtr_error_text
,
346 { "Erroneous Text", "rpki-rtr.error_text",
347 FT_STRING
, BASE_NONE
, NULL
, 0x0,
352 static gint
*ett
[] = {
357 proto_rpkirtr
= proto_register_protocol("RPKI-Router Protocol",
358 "RPKI-Router Protocol", "rpkirtr");
360 proto_register_field_array(proto_rpkirtr
, hf
, array_length(hf
));
361 proto_register_subtree_array(ett
, array_length(ett
));
363 rpkirtr_module
= prefs_register_protocol(proto_rpkirtr
,
364 proto_reg_handoff_rpkirtr
);
366 prefs_register_uint_preference(rpkirtr_module
, "tcp.rpkirtr.port", "RPKI-RTR TCP Port",
367 "RPKI-Router Protocol TCP port if other than the default",
368 10, &g_port_rpkirtr
);
369 prefs_register_uint_preference(rpkirtr_module
, "tcp.rpkirtr_tls.port", "RPKI-RTR TCP TLS Port",
370 "RPKI-Router Protocol TCP TLS port if other than the default",
371 10, &g_port_rpkirtr_tls
);
376 proto_reg_handoff_rpkirtr(void)
378 static gboolean initialized
= FALSE
;
379 static dissector_handle_t rpkirtr_handle
;
380 static dissector_handle_t ssl_handle
;
381 static int rpki_rtr_port
, rpki_rtr_tls_port
;
385 rpkirtr_handle
= new_create_dissector_handle(dissect_rpkirtr
,
387 ssl_handle
= find_dissector("ssl");
391 dissector_delete_uint("tcp.port", rpki_rtr_port
, rpkirtr_handle
);
392 dissector_delete_uint("tcp.port", rpki_rtr_tls_port
, ssl_handle
);
395 rpki_rtr_port
= g_port_rpkirtr
;
396 rpki_rtr_tls_port
= g_port_rpkirtr_tls
;
398 dissector_add_uint("tcp.port", rpki_rtr_port
, rpkirtr_handle
);
399 dissector_add_uint("tcp.port", rpki_rtr_tls_port
, ssl_handle
);
404 * Editor modelines - http://www.wireshark.org/tools/modelines.html
409 * indent-tabs-mode: nil
412 * vi: set shiftwidth=4 tabstop=8 expandtab:
413 * :indentSize=4:tabSize=8:noTabs=true: