HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-bgp.c
blobefe1f4baeaf163b32bc68563d4786c305f768060
1 /* packet-bgp.c
2 * Routines for BGP packet dissection.
3 * Copyright 1999, Jun-ichiro itojun Hagino <itojun@itojun.org>
5 * $Id$
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
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (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
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 /* Supports:
26 * RFC1771 A Border Gateway Protocol 4 (BGP-4)
27 * RFC1965 Autonomous System Confederations for BGP
28 * RFC1997 BGP Communities Attribute
29 * RFC2547 BGP/MPLS VPNs
30 * RFC2796 BGP Route Reflection An alternative to full mesh IBGP
31 * RFC2842 Capabilities Advertisement with BGP-4
32 * RFC2858 Multiprotocol Extensions for BGP-4
33 * RFC2918 Route Refresh Capability for BGP-4
34 * RFC3107 Carrying Label Information in BGP-4
35 * RFC4486 Subcodes for BGP Cease Notification Message
36 * RFC4724 Graceful Restart Mechanism for BGP
37 * RFC5512 BGP Encapsulation SAFI and the BGP Tunnel Encapsulation Attribute
38 * RFC5640 Load-Balancing for Mesh Softwires
39 * RFC6608 Subcodes for BGP Finite State Machine Error
40 * RFC5575 Dissemination of flow specification rules
41 * draft-ietf-idr-as4bytes-06
42 * draft-ietf-idr-dynamic-cap-03
43 * draft-ietf-idr-bgp-enhanced-route-refresh-02
44 * draft-ietf-idr-bgp-ext-communities-05
45 * draft-knoll-idr-qos-attribute-03
46 * draft-nalawade-kapoor-tunnel-safi-05
47 * draft-ietf-idr-add-paths-04 Additional-Path for BGP-4
48 * http://www.iana.org/assignments/bgp-parameters/ (last updated 2012-04-26)
50 * TODO:
51 * Destination Preference Attribute for BGP (work in progress)
52 * RFC1863 A BGP/IDRP Route Server alternative to a full mesh routing
55 #include "config.h"
57 #include <string.h>
59 #include <glib.h>
61 #include <epan/packet.h>
62 #include <epan/exceptions.h>
63 #include <epan/addr_and_mask.h>
64 #include <epan/show_exception.h>
65 #include <epan/afn.h>
66 #include <epan/prefs.h>
67 #include <epan/wmem/wmem.h>
68 #include <epan/expert.h>
69 #include <epan/etypes.h>
70 #include <packet-ip.h>
72 void proto_register_bgp(void);
73 void proto_reg_handoff_bgp(void);
75 /* #define MAX_STR_LEN 256 */
77 /* some handy things to know */
78 #define BGP_MAX_PACKET_SIZE 4096
79 #define BGP_MARKER_SIZE 16 /* size of BGP marker */
80 #define BGP_HEADER_SIZE 19 /* size of BGP header, including marker */
81 #define BGP_MIN_OPEN_MSG_SIZE 29
82 #define BGP_MIN_UPDATE_MSG_SIZE 23
83 #define BGP_MIN_NOTIFICATION_MSG_SIZE 21
84 #define BGP_MIN_KEEPALVE_MSG_SIZE BGP_HEADER_SIZE
85 #define BGP_TCP_PORT 179
86 #define BGP_ROUTE_DISTINGUISHER_SIZE 8
88 /* BGP message types */
89 #define BGP_OPEN 1
90 #define BGP_UPDATE 2
91 #define BGP_NOTIFICATION 3
92 #define BGP_KEEPALIVE 4
93 #define BGP_ROUTE_REFRESH 5
94 #define BGP_CAPABILITY 6
95 #define BGP_ROUTE_REFRESH_CISCO 0x80
97 #define BGP_SIZE_OF_PATH_ATTRIBUTE 2
100 /* attribute flags, from RFC1771 */
101 #define BGP_ATTR_FLAG_OPTIONAL 0x80
102 #define BGP_ATTR_FLAG_TRANSITIVE 0x40
103 #define BGP_ATTR_FLAG_PARTIAL 0x20
104 #define BGP_ATTR_FLAG_EXTENDED_LENGTH 0x10
107 /* SSA flags */
108 #define BGP_SSA_TRANSITIVE 0x8000
109 #define BGP_SSA_TYPE 0x7FFF
111 /* SSA Types */
112 #define BGP_SSA_L2TPv3 1
113 #define BGP_SSA_mGRE 2
114 #define BGP_SSA_IPSec 3
115 #define BGP_SSA_MPLS 4
116 #define BGP_SSA_L2TPv3_IN_IPSec 5
117 #define BGP_SSA_mGRE_IN_IPSec 6
119 /* AS_PATH segment types */
120 #define AS_SET 1 /* RFC1771 */
121 #define AS_SEQUENCE 2 /* RFC1771 */
122 #define AS_CONFED_SET 4 /* RFC1965 has the wrong values, corrected in */
123 #define AS_CONFED_SEQUENCE 3 /* draft-ietf-idr-bgp-confed-rfc1965bis-01.txt */
125 /* OPEN message Optional Parameter types */
126 #define BGP_OPTION_AUTHENTICATION 1 /* RFC1771 */
127 #define BGP_OPTION_CAPABILITY 2 /* RFC2842 */
129 /* BGP capability code */
130 #define BGP_CAPABILITY_RESERVED 0 /* RFC2434 */
131 #define BGP_CAPABILITY_MULTIPROTOCOL 1 /* RFC2858 */
132 #define BGP_CAPABILITY_ROUTE_REFRESH 2 /* RFC2918 */
133 #define BGP_CAPABILITY_COOPERATIVE_ROUTE_FILTERING 3 /* draft-ietf-idr-route-filter-04.txt */
134 #define BGP_CAPABILITY_GRACEFUL_RESTART 0x40 /* draft-ietf-idr-restart-05 */
135 #define BGP_CAPABILITY_4_OCTET_AS_NUMBER 0x41 /* draft-ietf-idr-as4bytes-06 */
136 #define BGP_CAPABILITY_DYNAMIC_CAPABILITY 0x42 /* draft-ietf-idr-dynamic-cap-03 */
137 #define BGP_CAPABILITY_ADDITIONAL_PATHS 0x45 /* draft-ietf-idr-add-paths */
138 #define BGP_CAPABILITY_ENHANCED_ROUTE_REFRESH 0x46 /* draft-ietf-idr-bgp-enhanced-route-refresh-02 */
139 #define BGP_CAPABILITY_ORF_CISCO 0x82 /* Cisco */
140 #define BGP_CAPABILITY_ROUTE_REFRESH_CISCO 0x80 /* Cisco */
142 #define BGP_ORF_PREFIX_CISCO 0x80 /* Cisco */
143 #define BGP_ORF_COMM_CISCO 0x81 /* Cisco */
144 #define BGP_ORF_EXTCOMM_CISCO 0x82 /* Cisco */
145 #define BGP_ORF_ASPATH_CISCO 0x83 /* Cisco */
147 #define BGP_ORF_COMM 0x02 /* draft-ietf-idr-route-filter-06.txt */
148 #define BGP_ORF_EXTCOMM 0x03 /* draft-ietf-idr-route-filter-06.txt */
149 #define BGP_ORF_ASPATH 0x04 /* draft-ietf-idr-aspath-orf-02.txt */
150 /* draft-ietf-idr-route-filter-06.txt */
151 #define BGP_ORF_ACTION 0xc0
152 #define BGP_ORF_ADD 0x00
153 #define BGP_ORF_REMOVE 0x01
154 #define BGP_ORF_REMOVEALL 0x02
156 #define BGP_ORF_MATCH 0x20
157 #define BGP_ORF_PERMIT 0x00
158 #define BGP_ORF_DENY 0x01
160 /* well-known communities, from RFC1997 */
161 #define BGP_COMM_NO_EXPORT 0xFFFFFF01
162 #define BGP_COMM_NO_ADVERTISE 0xFFFFFF02
163 #define BGP_COMM_NO_EXPORT_SUBCONFED 0xFFFFFF03
164 #define FOURHEX0 0x00000000
165 #define FOURHEXF 0xFFFF0000
167 /* attribute types */
168 #define BGPTYPE_ORIGIN 1 /* RFC1771 */
169 #define BGPTYPE_AS_PATH 2 /* RFC1771 */
170 #define BGPTYPE_NEXT_HOP 3 /* RFC1771 */
171 #define BGPTYPE_MULTI_EXIT_DISC 4 /* RFC1771 */
172 #define BGPTYPE_LOCAL_PREF 5 /* RFC1771 */
173 #define BGPTYPE_ATOMIC_AGGREGATE 6 /* RFC1771 */
174 #define BGPTYPE_AGGREGATOR 7 /* RFC1771 */
175 #define BGPTYPE_COMMUNITIES 8 /* RFC1997 */
176 #define BGPTYPE_ORIGINATOR_ID 9 /* RFC2796 */
177 #define BGPTYPE_CLUSTER_LIST 10 /* RFC2796 */
178 #define BGPTYPE_DPA 11 /* work in progress */
179 #define BGPTYPE_ADVERTISER 12 /* RFC1863 */
180 #define BGPTYPE_RCID_PATH 13 /* RFC1863 */
181 #define BGPTYPE_MP_REACH_NLRI 14 /* RFC2858 */
182 #define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC2858 */
183 #define BGPTYPE_EXTENDED_COMMUNITY 16 /* Draft Ramachandra */
184 #define BGPTYPE_NEW_AS_PATH 17 /* draft-ietf-idr-as4bytes */
185 #define BGPTYPE_NEW_AGGREGATOR 18 /* draft-ietf-idr-as4bytes */
186 #define BGPTYPE_SAFI_SPECIFIC_ATTR 19 /* draft-kapoor-nalawade-idr-bgp-ssa-00.txt */
187 #define BGPTYPE_TUNNEL_ENCAPS_ATTR 23 /* RFC5512 */
189 /* NLRI type as define in BGP flow spec RFC */
190 #define BGPNLRI_FSPEC_DST_PFIX 1 /* RFC 5575 */
191 #define BGPNLRI_FSPEC_SRC_PFIX 2 /* RFC 5575 */
192 #define BGPNLRI_FSPEC_IP_PROTO 3 /* RFC 5575 */
193 #define BGPNLRI_FSPEC_PORT 4 /* RFC 5575 */
194 #define BGPNLRI_FSPEC_DST_PORT 5 /* RFC 5575 */
195 #define BGPNLRI_FSPEC_SRC_PORT 6 /* RFC 5575 */
196 #define BGPNLRI_FSPEC_ICMP_TP 7 /* RFC 5575 */
197 #define BGPNLRI_FSPEC_ICMP_CD 8 /* RFC 5575 */
198 #define BGPNLRI_FSPEC_TCP_FLAGS 9 /* RFC 5575 */
199 #define BGPNLRI_FSPEC_PCK_LEN 10 /* RFC 5575 */
200 #define BGPNLRI_FSPEC_DSCP 11 /* RFC 5575 */
201 #define BGPNLRI_FSPEC_FRAGMENT 12 /* RFC 5575 */
203 /* BGP flow spec NLRI operator bitmask */
204 #define BGPNLRI_FSPEC_END_OF_LST 0x80
205 #define BGPNLRI_FSPEC_AND_BIT 0x40
206 #define BGPNLRI_FSPEC_VAL_LEN 0x30
207 #define BGPNLRI_FSPEC_UNUSED_BIT4 0x08
208 #define BGPNLRI_FSPEC_UNUSED_BIT5 0x04
209 #define BGPNLRI_FSPEC_LESS_THAN 0x04
210 #define BGPNLRI_FSPEC_GREATER_THAN 0x02
211 #define BGPNLRI_FSPEC_EQUAL 0x01
212 #define BGPNLRI_FSPEC_TCPF_NOTBIT 0x02
213 #define BGPNLRI_FSPEC_TCPF_MATCHBIT 0x01
214 #define BGPNLRI_FSPEC_DSCP_BITMASK 0xFC
216 /* BGP flow spec specific filter value: TCP flags, Packet fragment ... */
217 #define BGPNLRI_FSPEC_TH_FIN 0x01
218 #define BGPNLRI_FSPEC_TH_SYN 0x02
219 #define BGPNLRI_FSPEC_TH_RST 0x04
220 #define BGPNLRI_FSPEC_TH_PUSH 0x08
221 #define BGPNLRI_FSPEC_TH_ACK 0x10
222 #define BGPNLRI_FSPEC_TH_URG 0x20
223 #define BGPNLRI_FSPEC_TH_ECN 0x40
224 #define BGPNLRI_FSPEC_TH_CWR 0x80
226 #define BGPNLRI_FSPEC_FG_DF 0x01
227 #define BGPNLRI_FSPEC_FG_ISF 0x02
228 #define BGPNLRI_FSPEC_FG_FF 0x04
229 #define BGPNLRI_FSPEC_FG_LF 0x08
231 /* Extended community type */
232 /* according to IANA's number assignment at: http://www.iana.org/assignments/bgp-extended-communities */
233 #define BGP_EXT_COM_QOS_MARK_T 0x04 /* QoS Marking transitive attribute of regular type (8bit) */
234 #define BGP_EXT_COM_QOS_MARK_NT 0x44 /* QoS Marking non-transitive attribute of regular type (8bit) */
235 /* Format Type(1byte):Flags(1byte):QoS Set(1byte):Tec. Type(1byte): */
236 /* Marking O(2bytes):Marking A(1byte):Proc.Cnt(1byte) */
237 #define BGP_EXT_COM_COS_CAP_T 0x05 /* CoS Capability - Format Type(1byte):Flags(1byte):remaining '0..0' */
239 /* draft-ietf-idr-bgp-ext-communities */
240 #define BGP_EXT_COM_RT_0 0x0002 /* Route Target,Format AS(2bytes):AN(4bytes) */
241 #define BGP_EXT_COM_RT_1 0x0102 /* Route Target,Format IP address:AN(2bytes) */
242 #define BGP_EXT_COM_RT_2 0x0202 /* Route Target,Format AS(4bytes):AN(2bytes) */
243 #define BGP_EXT_COM_RO_0 0x0003 /* Route Origin,Format AS(2bytes):AN(4bytes) */
244 #define BGP_EXT_COM_RO_1 0x0103 /* Route Origin,Format IP address:AN(2bytes) */
245 #define BGP_EXT_COM_RO_2 0x0203 /* Route Origin,Format AS(2bytes):AN(4bytes) */
246 #define BGP_EXT_COM_LINKBAND ((BGP_ATTR_FLAG_TRANSITIVE << 8) | 0x0004)
247 /* Link Bandwidth,Format AS(2bytes):
248 * Bandwidth(4bytes) */
249 /* -2 version of the draft */
250 #define BGP_EXT_COM_VPN_ORIGIN 0x0005 /* OSPF Domin ID / VPN of Origin */
251 /* draft-rosen-vpns-ospf-bgp-mpls */
252 #define BGP_EXT_COM_OSPF_RTYPE 0x8000 /* OSPF Route Type,Format Area(4B):RouteType(1B):Options(1B) */
253 #define BGP_EXT_COM_OSPF_RID 0x8001 /* OSPF Router ID,Format RouterID(4B):Unused(2B) */
254 #define BGP_EXT_COM_L2INFO 0x800a /* draft-kompella-ppvpn-l2vpn */
255 #define BGP_EXT_COM_FLOW_RATE 0x8006 /* RFC 5575 flow spec ext com rate limit */
256 #define BGP_EXT_COM_FLOW_ACT 0x8007 /* RFC 5575 flow Spec ext com traffic action */
257 #define BGP_EXT_COM_FLOW_RDIR 0x8008 /* RFC 5575 flow spec ext com redirect action */
258 #define BGP_EXT_COM_FLOW_MARK 0x8009 /* RFC 5575 flow spec ext com mark action */
259 #define BGP_EXT_COM_FLOW_NH 0x0800 /* draft-simpson-redirect-02 */
261 /* extended community option flow flec action bit S and T */
262 #define BGP_EXT_COM_FSPEC_ACT_S 0x02
263 #define BGP_EXT_COM_FSPEC_ACT_T 0x01
265 /* extended community l2vpn flags */
267 #define BGP_EXT_COM_L2_FLAG_D 0x80
268 #define BGP_EXT_COM_L2_FLAG_Z1 0x40
269 #define BGP_EXT_COM_L2_FLAG_F 0x20
270 #define BGP_EXT_COM_L2_FLAG_Z345 0x1c
271 #define BGP_EXT_COM_L2_FLAG_C 0x02
272 #define BGP_EXT_COM_L2_FLAG_S 0x01
274 /* Extended community QoS Marking technology type */
275 #define QOS_TECH_TYPE_DSCP 0x00 /* DiffServ enabled IP (DSCP encoding) */
276 #define QOS_TECH_TYPE_802_1q 0x01 /* Ethernet using 802.1q priority tag */
277 #define QOS_TECH_TYPE_E_LSP 0x02 /* MPLS using E-LSP */
278 #define QOS_TECH_TYPE_VC 0x03 /* Virtual Channel (VC) encoding using separate channels for */
279 /* QoS forwarding / one channel per class (e.g. ATM VCs, FR */
280 /* VCs, MPLS L-LSPs) */
281 #define QOS_TECH_TYPE_GMPLS_TIME 0x04 /* GMPLS - time slot encoding */
282 #define QOS_TECH_TYPE_GMPLS_LAMBDA 0x05 /* GMPLS - lambda encoding */
283 #define QOS_TECH_TYPE_GMPLS_FIBRE 0x06 /* GMPLS - fibre encoding */
285 /* OSPF codes for BGP_EXT_COM_OSPF_RTYPE draft-rosen-vpns-ospf-bgp-mpls */
286 #define BGP_OSPF_RTYPE_RTR 1 /* OSPF Router LSA */
287 #define BGP_OSPF_RTYPE_NET 2 /* OSPF Network LSA */
288 #define BGP_OSPF_RTYPE_SUM 3 /* OSPF Summary LSA */
289 #define BGP_OSPF_RTYPE_EXT 5 /* OSPF External LSA, note that ASBR doesn't apply to MPLS-VPN */
290 #define BGP_OSPF_RTYPE_NSSA 7 /* OSPF NSSA External*/
291 #define BGP_OSPF_RTYPE_SHAM 129 /* OSPF-MPLS-VPN Sham link */
292 #define BGP_OSPF_RTYPE_METRIC_TYPE 0x1 /* LSB of RTYPE Options Field */
294 /* Extended community & Route dinstinguisher formats */
295 #define FORMAT_AS2_LOC 0x00 /* Format AS(2bytes):AN(4bytes) */
296 #define FORMAT_IP_LOC 0x01 /* Format IP address:AN(2bytes) */
297 #define FORMAT_AS4_LOC 0x02 /* Format AS(4bytes):AN(2bytes) */
299 /* RFC 2858 subsequent address family numbers */
300 #define SAFNUM_UNICAST 1
301 #define SAFNUM_MULCAST 2
302 #define SAFNUM_UNIMULC 3
303 #define SAFNUM_MPLS_LABEL 4 /* rfc3107 */
304 #define SAFNUM_MCAST_VPN 5 /* draft-ietf-l3vpn-2547bis-mcast-bgp-08.txt */
305 #define SAFNUM_ENCAPSULATION 7 /* rfc5512 */
306 #define SAFNUM_TUNNEL 64 /* draft-nalawade-kapoor-tunnel-safi-02.txt */
307 #define SAFNUM_VPLS 65
308 #define SAFNUM_MDT 66 /* rfc6037 */
309 #define SAFNUM_LAB_VPNUNICAST 128 /* Draft-rosen-rfc2547bis-03 */
310 #define SAFNUM_LAB_VPNMULCAST 129
311 #define SAFNUM_LAB_VPNUNIMULC 130
312 #define SAFNUM_ROUTE_TARGET 132 /* RFC 4684 Constrained Route Distribution for BGP/MPLS IP VPN */
313 #define SAFNUM_FSPEC_RULE 133 /* RFC 5575 BGP flow spec SAFI */
314 #define SAFNUM_FSPEC_VPN_RULE 134 /* RFC 5575 BGP flow spec SAFI VPN */
317 /* BGP Additional Paths Capability */
318 #define BGP_ADDPATH_RECEIVE 0x01
319 #define BGP_ADDPATH_SEND 0x02
321 /* mcast-vpn route types draft-ietf-l3vpn-2547bis-mcast-bgp-08.txt */
322 #define MCAST_VPN_RTYPE_INTRA_AS_IPMSI_AD 1
323 #define MCAST_VPN_RTYPE_INTER_AS_IPMSI_AD 2
324 #define MCAST_VPN_RTYPE_SPMSI_AD 3
325 #define MCAST_VPN_RTYPE_LEAF_AD 4
326 #define MCAST_VPN_RTYPE_SOURCE_ACTIVE_AD 5
327 #define MCAST_VPN_RTYPE_SHARED_TREE_JOIN 6
328 #define MCAST_VPN_RTYPE_SOURCE_TREE_JOIN 7
330 /* RFC 5512 Tunnel Types */
331 #define TUNNEL_TYPE_L2TP_OVER_IP 1
332 #define TUNNEL_TYPE_GRE 2
333 #define TUNNEL_TYPE_IP_IN_IP 7
335 /* RFC 5512/5640 Sub-TLV Types */
336 #define TUNNEL_SUBTLV_ENCAPSULATION 1
337 #define TUNNEL_SUBTLV_PROTO_TYPE 2
338 #define TUNNEL_SUBTLV_COLOR 4
339 #define TUNNEL_SUBTLV_LOAD_BALANCE 5
341 #ifndef offsetof
342 #define offsetof(type, member) ((size_t)(&((type *)0)->member))
343 #endif
346 static const value_string bgptypevals[] = {
347 { BGP_OPEN, "OPEN Message" },
348 { BGP_UPDATE, "UPDATE Message" },
349 { BGP_NOTIFICATION, "NOTIFICATION Message" },
350 { BGP_KEEPALIVE, "KEEPALIVE Message" },
351 { BGP_ROUTE_REFRESH, "ROUTE-REFRESH Message" },
352 { BGP_CAPABILITY, "CAPABILITY Message" },
353 { BGP_ROUTE_REFRESH_CISCO, "Cisco ROUTE-REFRESH Message" },
354 { 0, NULL }
357 #define BGP_MAJOR_ERROR_MSG_HDR 1
358 #define BGP_MAJOR_ERROR_OPEN_MSG 2
359 #define BGP_MAJOR_ERROR_UPDATE_MSG 3
360 #define BGP_MAJOR_ERROR_HT_EXPIRED 4
361 #define BGP_MAJOR_ERROR_STATE_MACHINE 5
362 #define BGP_MAJOR_ERROR_CEASE 6
363 #define BGP_MAJOR_ERROR_CAP_MSG 7
365 static const value_string bgpnotify_major[] = {
366 { BGP_MAJOR_ERROR_MSG_HDR, "Message Header Error" },
367 { BGP_MAJOR_ERROR_OPEN_MSG, "OPEN Message Error" },
368 { BGP_MAJOR_ERROR_UPDATE_MSG, "UPDATE Message Error" },
369 { BGP_MAJOR_ERROR_HT_EXPIRED, "Hold Timer Expired" },
370 { BGP_MAJOR_ERROR_STATE_MACHINE, "Finite State Machine Error" },
371 { BGP_MAJOR_ERROR_CEASE, "Cease" },
372 { BGP_MAJOR_ERROR_CAP_MSG, "CAPABILITY Message Error" },
373 { 0, NULL }
376 static const value_string bgpnotify_minor_msg_hdr[] = {
377 { 1, "Connection Not Synchronized" },
378 { 2, "Bad Message Length" },
379 { 3, "Bad Message Type" },
380 { 0, NULL }
383 static const value_string bgpnotify_minor_open_msg[] = {
384 { 1, "Unsupported Version Number" },
385 { 2, "Bad Peer AS" },
386 { 3, "Bad BGP Identifier" },
387 { 4, "Unsupported Optional Parameter" },
388 { 5, "Authentication Failure [Deprecated]" },
389 { 6, "Unacceptable Hold Time" },
390 { 7, "Unsupported Capability" },
391 { 0, NULL }
394 static const value_string bgpnotify_minor_update_msg[] = {
395 { 1, "Malformed Attribute List" },
396 { 2, "Unrecognized Well-known Attribute" },
397 { 3, "Missing Well-known Attribute" },
398 { 4, "Attribute Flags Error" },
399 { 5, "Attribute Length Error" },
400 { 6, "Invalid ORIGIN Attribute" },
401 { 7, "AS Routing Loop [Deprecated]" },
402 { 8, "Invalid NEXT_HOP Attribute" },
403 { 9, "Optional Attribute Error" },
404 { 10, "Invalid Network Field" },
405 { 11, "Malformed AS_PATH" },
406 { 0, NULL }
408 /* RFC6608 Subcodes for BGP Finite State Machine Error */
409 static const value_string bgpnotify_minor_state_machine[] = {
410 { 1, "Receive Unexpected Message in OpenSent State" },
411 { 2, "Receive Unexpected Message in OpenConfirm State" },
412 { 3, "Receive Unexpected Message in Established State" },
413 { 0, NULL }
416 /* RFC4486 Subcodes for BGP Cease Notification Message */
417 static const value_string bgpnotify_minor_cease[] = {
418 { 1, "Maximum Number of Prefixes Reached"},
419 { 2, "Administratively Shutdown"},
420 { 3, "Peer De-configured"},
421 { 4, "Administratively Reset"},
422 { 5, "Connection Rejected"},
423 { 6, "Other Configuration Change"},
424 { 7, "Connection Collision Resolution"},
425 { 8, "Out of Resources"},
426 { 0, NULL }
429 static const value_string bgpnotify_minor_cap_msg[] = {
430 { 1, "Invalid Action Value" },
431 { 2, "Invalid Capability Length" },
432 { 3, "Malformed Capability Value" },
433 { 4, "Unsupported Capability Code" },
434 { 0, NULL }
437 static const value_string bgpattr_origin[] = {
438 { 0, "IGP" },
439 { 1, "EGP" },
440 { 2, "INCOMPLETE" },
441 { 0, NULL }
444 static const value_string bgp_open_opt_vals[] = {
445 { BGP_OPTION_AUTHENTICATION, "Authentication" },
446 { BGP_OPTION_CAPABILITY, "Capability" },
447 { 0, NULL }
450 static const value_string as_segment_type[] = {
451 { 1, "AS_SET" },
452 { 2, "AS_SEQUENCE" },
453 /* RFC1965 has the wrong values, corrected in */
454 /* draft-ietf-idr-bgp-confed-rfc1965bis-01.txt */
455 { 4, "AS_CONFED_SET" },
456 { 3, "AS_CONFED_SEQUENCE" },
457 { 0, NULL }
460 static const value_string bgpattr_type[] = {
461 { BGPTYPE_ORIGIN, "ORIGIN" },
462 { BGPTYPE_AS_PATH, "AS_PATH" },
463 { BGPTYPE_NEXT_HOP, "NEXT_HOP" },
464 { BGPTYPE_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
465 { BGPTYPE_LOCAL_PREF, "LOCAL_PREF" },
466 { BGPTYPE_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
467 { BGPTYPE_AGGREGATOR, "AGGREGATOR" },
468 { BGPTYPE_COMMUNITIES, "COMMUNITIES" },
469 { BGPTYPE_ORIGINATOR_ID, "ORIGINATOR_ID" },
470 { BGPTYPE_CLUSTER_LIST, "CLUSTER_LIST" },
471 { BGPTYPE_MP_REACH_NLRI, "MP_REACH_NLRI" },
472 { BGPTYPE_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
473 { BGPTYPE_EXTENDED_COMMUNITY, "EXTENDED_COMMUNITIES" },
474 { BGPTYPE_NEW_AS_PATH, "NEW_AS_PATH" },
475 { BGPTYPE_NEW_AGGREGATOR, "NEW_AGGREGATOR" },
476 { BGPTYPE_SAFI_SPECIFIC_ATTR, "SAFI_SPECIFIC_ATTRIBUTE" },
477 { BGPTYPE_TUNNEL_ENCAPS_ATTR, "TUNNEL_ENCAPSULATION_ATTRIBUTE" },
478 { 0, NULL }
481 static const value_string tunnel_type[] = {
482 { TUNNEL_TYPE_L2TP_OVER_IP, "L2TP_OVER_IP" },
483 { TUNNEL_TYPE_GRE, "GRE" },
484 { TUNNEL_TYPE_IP_IN_IP, "IP_IN_IP" },
485 { 0, NULL }
488 static const value_string subtlv_type[] = {
489 { TUNNEL_SUBTLV_ENCAPSULATION, "ENCAPSULATION" },
490 { TUNNEL_SUBTLV_PROTO_TYPE, "PROTOCOL_TYPE" },
491 { TUNNEL_SUBTLV_COLOR, "COLOR" },
492 { TUNNEL_SUBTLV_LOAD_BALANCE, "LOAD_BALANCE" },
493 { 0, NULL }
496 static const value_string bgpext_com8_type[] = {
497 { BGP_EXT_COM_QOS_MARK_T, "QoS Marking - transitive" },
498 { BGP_EXT_COM_QOS_MARK_NT, "QoS Marking - non-transitive" },
499 { BGP_EXT_COM_COS_CAP_T, "CoS Capability - transitive" },
500 { 0, NULL }
503 static const value_string bgpext_com_type[] = {
504 { BGP_EXT_COM_RT_0, "two-octet AS specific Route Target" },
505 { BGP_EXT_COM_RT_1, "IPv4 address specific Route Target" },
506 { BGP_EXT_COM_RT_2, "four-octet AS specific Route Target" },
507 { BGP_EXT_COM_RO_0, "two-octet AS specific Route Origin" },
508 { BGP_EXT_COM_RO_1, "IPv4 address specific Route Origin" },
509 { BGP_EXT_COM_RO_2, "four-octet AS specific Route Origin" },
510 { BGP_EXT_COM_LINKBAND, "Link Bandwidth" },
511 { BGP_EXT_COM_VPN_ORIGIN, "OSPF Domain" },
512 { BGP_EXT_COM_OSPF_RTYPE, "OSPF Route Type" },
513 { BGP_EXT_COM_OSPF_RID, "OSPF Router ID" },
514 { BGP_EXT_COM_L2INFO, "Layer 2 Information" },
515 { BGP_EXT_COM_FLOW_ACT, "Flow spec traffic action" },
516 { BGP_EXT_COM_FLOW_MARK, "FLow spec traffic marling" },
517 { BGP_EXT_COM_FLOW_RATE, "Flow spec traffic rate" },
518 { BGP_EXT_COM_FLOW_RDIR, "Flow spec traffic redirect" },
519 { 0, NULL }
522 static const value_string flow_spec_op_len_val[] = {
523 { 0, "1 byte: 1 <<" },
524 { 1, "2 bytes: 1 <<" },
525 { 2, "4 bytes: 1 <<" },
526 { 3, "8 bytes: 1 <<" },
527 { 0, NULL }
530 static const value_string qos_tech_type[] = {
531 { QOS_TECH_TYPE_DSCP, "DiffServ enabled IP (DSCP encoding)" },
532 { QOS_TECH_TYPE_802_1q, "Ethernet using 802.1q priority tag" },
533 { QOS_TECH_TYPE_E_LSP, "MPLS using E-LSP" },
534 { QOS_TECH_TYPE_VC, "Virtual Channel (VC) encoding" },
535 { QOS_TECH_TYPE_GMPLS_TIME, "GMPLS - time slot encoding" },
536 { QOS_TECH_TYPE_GMPLS_LAMBDA, "GMPLS - lambda encoding" },
537 { QOS_TECH_TYPE_GMPLS_FIBRE, "GMPLS - fibre encoding" },
538 { 0, NULL }
541 static const value_string bgp_ssa_type[] = {
542 { BGP_SSA_L2TPv3 , "L2TPv3 Tunnel" },
543 { BGP_SSA_mGRE , "mGRE Tunnel" },
544 { BGP_SSA_IPSec , "IPSec Tunnel" },
545 { BGP_SSA_MPLS , "MPLS Tunnel" },
546 { BGP_SSA_L2TPv3_IN_IPSec , "L2TPv3 in IPSec Tunnel" },
547 { BGP_SSA_mGRE_IN_IPSec , "mGRE in IPSec Tunnel" },
548 { 0, NULL }
551 static const value_string bgp_l2vpn_encaps[] = {
552 { 0, "Reserved"},
553 { 1, "Frame Relay"},
554 { 2, "ATM AAL5 SDU VCC transport"},
555 { 3, "ATM transparent cell transport"},
556 { 4, "Ethernet (VLAN) Tagged mode"},
557 { 5, "Ethernet raw mode"},
558 { 6, "Cisco-HDLC"},
559 { 7, "PPP"},
560 { 8, "SONET/SDH CES"},
561 { 9, "ATM n-to-one VCC cell transport"},
562 { 10, "ATM n-to-one VPC cell transport"},
563 { 11, "IP layer 2 transport"},
564 { 15, "Frame relay port mode"},
565 { 17, "Structure agnostic E1 over packet"},
566 { 18, "Structure agnostic T1 over packet"},
567 { 19, "VPLS"},
568 { 20, "Structure agnostic T3 over packet"},
569 { 21, "Nx64kbit/s Basic Service using Structure-aware"},
570 { 25, "Frame Relay DLCI"},
571 { 40, "Structure agnostic E3 over packet"},
572 { 41, "Octet-aligned playload for structure-agnostic DS1 circuits"},
573 { 42, "E1 Nx64kbit/s with CAS using Structure-aware"},
574 { 43, "DS1 (ESF) Nx64kbit/s with CAS using Structure-aware"},
575 { 44, "DS1 (SF) Nx64kbit/s with CAS using Structure-aware"},
576 { 64, "IP-interworking"},
577 { 0, NULL }
580 static const value_string bgpext_ospf_rtype[] = {
581 { BGP_OSPF_RTYPE_RTR, "Router" },
582 { BGP_OSPF_RTYPE_NET, "Network" },
583 { BGP_OSPF_RTYPE_SUM, "Summary" },
584 { BGP_OSPF_RTYPE_EXT, "External" },
585 { BGP_OSPF_RTYPE_NSSA,"NSSA External" },
586 { BGP_OSPF_RTYPE_SHAM,"MPLS-VPN Sham" },
587 { 0, NULL }
590 /* Subsequent address family identifier, RFC2858 */
591 static const value_string bgpattr_nlri_safi[] = {
592 { 0, "Reserved" },
593 { SAFNUM_UNICAST, "Unicast" },
594 { SAFNUM_MULCAST, "Multicast" },
595 { SAFNUM_UNIMULC, "Unicast+Multicast" },
596 { SAFNUM_MPLS_LABEL, "Labeled Unicast"},
597 { SAFNUM_MCAST_VPN, "MCAST-VPN"},
598 { SAFNUM_ENCAPSULATION, "Encapsulation"},
599 { SAFNUM_TUNNEL, "Tunnel"},
600 { SAFNUM_VPLS, "VPLS"},
601 { SAFNUM_LAB_VPNUNICAST, "Labeled VPN Unicast" }, /* draft-rosen-rfc2547bis-03 */
602 { SAFNUM_LAB_VPNMULCAST, "Labeled VPN Multicast" },
603 { SAFNUM_LAB_VPNUNIMULC, "Labeled VPN Unicast+Multicast" },
604 { SAFNUM_ROUTE_TARGET, "Route Target Filter" },
605 { SAFNUM_FSPEC_RULE, "Flow Spec Filter" },
606 { SAFNUM_FSPEC_VPN_RULE, "Flow Spec Filter VPN" },
607 { 0, NULL }
610 /* ORF Type, draft-ietf-idr-route-filter-04.txt */
611 static const value_string orf_type_vals[] = {
612 { 2, "Communities ORF-Type" },
613 { 3, "Extended Communities ORF-Type" },
614 { 128, "Cisco PrefixList ORF-Type" },
615 { 129, "Cisco CommunityList ORF-Type" },
616 { 130, "Cisco Extended CommunityList ORF-Type" },
617 { 131, "Cisco AsPathList ORF-Type" },
618 { 0, NULL }
621 /* ORF Send/Receive, draft-ietf-idr-route-filter-04.txt */
622 static const value_string orf_send_recv_vals[] = {
623 { 1, "Receive" },
624 { 2, "Send" },
625 { 3, "Both" },
626 { 0, NULL }
629 /* ORF Send/Receive, draft-ietf-idr-route-filter-04.txt */
630 static const value_string orf_when_vals[] = {
631 { 1, "Immediate" },
632 { 2, "Defer" },
633 { 0, NULL }
636 static const value_string orf_entry_action_vals[] = {
637 { BGP_ORF_ADD, "Add" },
638 { BGP_ORF_REMOVE, "Remove" },
639 { BGP_ORF_REMOVEALL, "RemoveAll" },
640 { 0, NULL }
643 static const value_string orf_entry_match_vals[] = {
644 { BGP_ORF_PERMIT, "Permit" },
645 { BGP_ORF_DENY, "Deny" },
646 { 0, NULL }
649 static const value_string capability_vals[] = {
650 { BGP_CAPABILITY_RESERVED, "Reserved capability" },
651 { BGP_CAPABILITY_MULTIPROTOCOL, "Multiprotocol extensions capability" },
652 { BGP_CAPABILITY_ROUTE_REFRESH, "Route refresh capability" },
653 { BGP_CAPABILITY_COOPERATIVE_ROUTE_FILTERING, "Cooperative route filtering capability" },
654 { BGP_CAPABILITY_GRACEFUL_RESTART, "Graceful Restart capability" },
655 { BGP_CAPABILITY_4_OCTET_AS_NUMBER, "Support for 4-octet AS number capability" },
656 { BGP_CAPABILITY_DYNAMIC_CAPABILITY, "Support for Dynamic capability" },
657 { BGP_CAPABILITY_ADDITIONAL_PATHS, "Support for Additional Paths" },
658 { BGP_CAPABILITY_ROUTE_REFRESH_CISCO, "Route refresh capability" },
659 { BGP_CAPABILITY_ORF_CISCO, "Cooperative route filtering capability" },
660 { BGP_CAPABILITY_ENHANCED_ROUTE_REFRESH, "Enhanced route refresh capability" },
661 { 0, NULL }
664 /* Capability Message action code */
665 static const value_string bgpcap_action[] = {
666 { 0, "advertising a capability" },
667 { 1, "removing a capability" },
668 { 0, NULL }
671 static const value_string mcast_vpn_route_type[] = {
672 { MCAST_VPN_RTYPE_INTRA_AS_IPMSI_AD, "Intra-AS I-PMSI A-D route" },
673 { MCAST_VPN_RTYPE_INTER_AS_IPMSI_AD, "Inter-AS I-PMSI A-D route" },
674 { MCAST_VPN_RTYPE_SPMSI_AD , "S-PMSI A-D route" },
675 { MCAST_VPN_RTYPE_LEAF_AD , "Leaf A-D route" },
676 { MCAST_VPN_RTYPE_SOURCE_ACTIVE_AD , "Source Active A-D route" },
677 { MCAST_VPN_RTYPE_SHARED_TREE_JOIN , "Shared Tree Join route" },
678 { MCAST_VPN_RTYPE_SOURCE_TREE_JOIN , "Source Tree Join route" },
679 { 0, NULL }
682 /* NLRI type value_string as define in BGP flow spec RFC */
684 static const value_string flowspec_nlri_opvaluepair_type[] = {
685 { BGPNLRI_FSPEC_DST_PFIX, "Destination prefix filter" },
686 { BGPNLRI_FSPEC_SRC_PFIX, "Source prefix filter" },
687 { BGPNLRI_FSPEC_IP_PROTO, "IP protocol filter" },
688 { BGPNLRI_FSPEC_PORT, "Port filter" },
689 { BGPNLRI_FSPEC_DST_PORT, "Destination port filter" },
690 { BGPNLRI_FSPEC_SRC_PORT, "Source port filter" },
691 { BGPNLRI_FSPEC_ICMP_TP, "ICMP type filter" },
692 { BGPNLRI_FSPEC_ICMP_CD, "ICMP code filter" },
693 { BGPNLRI_FSPEC_TCP_FLAGS,"TCP flags filter" },
694 { BGPNLRI_FSPEC_PCK_LEN, "Packet Length filter" },
695 { BGPNLRI_FSPEC_DSCP, "DSCP marking filter" },
696 { BGPNLRI_FSPEC_FRAGMENT, "IP fragment filter" },
697 {0, NULL },
699 #define BGPNLRI_FSPEC_FRAGMENT 12 /* RFC 5575 */
702 /* Subtype Route Refresh, draft-ietf-idr-bgp-enhanced-route-refresh-02 */
703 static const value_string route_refresh_subtype_vals[] = {
704 { 0, "Normal route refresh request [RFC2918] with/without ORF [RFC5291]" },
705 { 1, "Demarcation of the beginning of a route refresh" },
706 { 2, "Demarcation of the ending of a route refresh" },
707 { 0, NULL }
710 static const true_false_string tfs_optional_wellknown = { "Optional", "Well-known" };
711 static const true_false_string tfs_transitive_non_transitive = { "Transitive", "Non-transitive" };
712 static const true_false_string tfs_partial_complete = { "Partial", "Complete" };
713 static const true_false_string tfs_extended_regular_length = { "Extended length", "Regular length" };
715 /* Maximal size of an IP address string */
716 #define MAX_SIZE_OF_IP_ADDR_STRING 16
718 static int proto_bgp = -1;
720 /* BGP header field initialisation */
722 /* global BGP header filed */
724 static int hf_bgp_marker = -1;
725 static int hf_bgp_length = -1;
726 static int hf_bgp_type = -1;
728 /* BGP open message header filed */
730 static int hf_bgp_open_version = -1;
731 static int hf_bgp_open_myas = -1;
732 static int hf_bgp_open_holdtime = -1;
733 static int hf_bgp_open_identifier = -1;
734 static int hf_bgp_open_opt_len = -1;
735 static int hf_bgp_open_opt_params = -1;
736 static int hf_bgp_open_opt_param = -1;
737 static int hf_bgp_open_opt_param_type = -1;
738 static int hf_bgp_open_opt_param_len = -1;
739 static int hf_bgp_open_opt_param_auth = -1;
740 static int hf_bgp_open_opt_param_unknown = -1;
742 /* BGP notify header field */
744 static int hf_bgp_notify_major_error = -1;
745 static int hf_bgp_notify_minor_msg_hdr = -1;
746 static int hf_bgp_notify_minor_open_msg = -1;
747 static int hf_bgp_notify_minor_update_msg = -1;
748 static int hf_bgp_notify_minor_ht_expired = -1;
749 static int hf_bgp_notify_minor_state_machine = -1;
750 static int hf_bgp_notify_minor_cease = -1;
751 static int hf_bgp_notify_minor_cap_msg = -1;
752 static int hf_bgp_notify_minor_unknown = -1;
753 static int hf_bgp_notify_data = -1;
755 /* BGP route refresh header field */
757 static int hf_bgp_route_refresh_afi = -1;
758 static int hf_bgp_route_refresh_subtype = -1;
759 static int hf_bgp_route_refresh_safi = -1;
760 static int hf_bgp_route_refresh_orf = -1;
761 static int hf_bgp_route_refresh_orf_flag = -1;
762 static int hf_bgp_route_refresh_orf_type = -1;
763 static int hf_bgp_route_refresh_orf_length = -1;
764 static int hf_bgp_route_refresh_orf_entry_prefixlist = -1;
765 static int hf_bgp_route_refresh_orf_entry_action = -1;
766 static int hf_bgp_route_refresh_orf_entry_match = -1;
767 static int hf_bgp_route_refresh_orf_entry_sequence = -1;
768 static int hf_bgp_route_refresh_orf_entry_prefixmask_lower = -1;
769 static int hf_bgp_route_refresh_orf_entry_prefixmask_upper = -1;
771 /* BGP capabilities header field */
773 static int hf_bgp_cap = -1;
774 static int hf_bgp_cap_type = -1;
775 static int hf_bgp_cap_length = -1;
776 static int hf_bgp_cap_action = -1;
777 static int hf_bgp_cap_unknown = -1;
778 static int hf_bgp_cap_reserved = -1;
779 static int hf_bgp_cap_mp_afi = -1;
780 static int hf_bgp_cap_mp_safi = -1;
781 static int hf_bgp_cap_gr_timers = -1;
782 static int hf_bgp_cap_gr_timers_restart_flag = -1;
783 static int hf_bgp_cap_gr_timers_restart_time = -1;
784 static int hf_bgp_cap_gr_afi = -1;
785 static int hf_bgp_cap_gr_safi = -1;
786 static int hf_bgp_cap_gr_flag = -1;
787 static int hf_bgp_cap_gr_flag_pfs = -1;
788 static int hf_bgp_cap_4as = -1;
789 static int hf_bgp_cap_dc = -1;
790 static int hf_bgp_cap_ap_afi = -1;
791 static int hf_bgp_cap_ap_safi = -1;
792 static int hf_bgp_cap_ap_sendreceive = -1;
793 static int hf_bgp_cap_orf_afi = -1;
794 static int hf_bgp_cap_orf_safi = -1;
795 static int hf_bgp_cap_orf_number = -1;
796 static int hf_bgp_cap_orf_type = -1;
797 static int hf_bgp_cap_orf_sendreceive = -1;
799 /* BGP update global header field */
800 static int hf_bgp_update_withdrawn_routes_length = -1;
801 static int hf_bgp_update_withdrawn_routes = -1;
803 static int hf_bgp_update_community_as = -1;
806 /* BGP update path attribute header field */
807 static int hf_bgp_update_total_path_attribute_length = -1;
808 static int hf_bgp_update_path_attributes = -1;
810 static int hf_bgp_update_path_attribute = -1;
811 static int hf_bgp_update_path_attribute_flags = -1;
812 static int hf_bgp_update_path_attribute_flags_optional = -1;
813 static int hf_bgp_update_path_attribute_flags_transitive = -1;
814 static int hf_bgp_update_path_attribute_flags_partial = -1;
815 static int hf_bgp_update_path_attribute_flags_extended_length = -1;
816 static int hf_bgp_update_path_attribute_type_code = -1;
817 static int hf_bgp_update_path_attribute_length = -1;
818 static int hf_bgp_update_path_attribute_next_hop = -1;
819 static int hf_bgp_update_path_attribute_as_path = -1;
820 static int hf_bgp_update_path_attribute_community_value = -1;
821 static int hf_bgp_update_path_attribute_origin = -1;
822 static int hf_bgp_update_path_attribute_cluster_list = -1;
823 static int hf_bgp_update_path_attribute_originator_id = -1;
824 static int hf_bgp_update_path_attribute_local_pref = -1;
825 static int hf_bgp_update_path_attribute_multi_exit_disc = -1;
826 static int hf_bgp_update_path_attribute_aggregator_as = -1;
827 static int hf_bgp_update_path_attribute_aggregator_origin = -1;
829 /* BGP update tunnel encaps attribute RFC 5512 */
831 static int hf_bgp_update_encaps_tunnel_tlv_len = -1;
832 static int hf_bgp_update_encaps_tunnel_tlv_type = -1;
833 static int hf_bgp_update_encaps_tunnel_subtlv_len = -1;
834 static int hf_bgp_update_encaps_tunnel_subtlv_type = -1;
837 /* BGP update path attribute SSA SAFI Specific attribute (deprecated should we keep it ?) */
839 static int hf_bgp_ssa_t = -1;
840 static int hf_bgp_ssa_type = -1;
841 static int hf_bgp_ssa_len = -1;
842 static int hf_bgp_ssa_value = -1;
843 static int hf_bgp_ssa_l2tpv3_pref = -1;
844 static int hf_bgp_ssa_l2tpv3_s = -1;
845 static int hf_bgp_ssa_l2tpv3_unused = -1;
846 static int hf_bgp_ssa_l2tpv3_cookie_len = -1;
847 static int hf_bgp_ssa_l2tpv3_session_id = -1;
848 static int hf_bgp_ssa_l2tpv3_cookie = -1;
850 /* BGP NLRI head field */
851 static int hf_bgp_update_nlri = -1;
853 static int hf_bgp_mp_reach_nlri_ipv4_prefix = -1;
854 static int hf_bgp_mp_unreach_nlri_ipv4_prefix = -1;
855 static int hf_bgp_mp_nlri_tnl_id = -1;
856 static int hf_bgp_withdrawn_prefix = -1;
857 static int hf_bgp_nlri_prefix = -1;
858 static int hf_bgp_nlri_path_id = -1;
860 /* BGP mcast IP VPN nlri header field */
862 static int hf_bgp_mcast_vpn_nlri_t = -1;
863 static int hf_bgp_mcast_vpn_nlri_route_type = -1;
864 static int hf_bgp_mcast_vpn_nlri_length = -1;
865 static int hf_bgp_mcast_vpn_nlri_rd = -1;
866 static int hf_bgp_mcast_vpn_nlri_origin_router_ipv4 = -1;
867 static int hf_bgp_mcast_vpn_nlri_origin_router_ipv6 = -1;
868 static int hf_bgp_mcast_vpn_nlri_source_as = -1;
869 static int hf_bgp_mcast_vpn_nlri_source_length = -1;
870 static int hf_bgp_mcast_vpn_nlri_group_length = -1;
871 static int hf_bgp_mcast_vpn_nlri_source_addr_ipv4 = -1;
872 static int hf_bgp_mcast_vpn_nlri_source_addr_ipv6 = -1;
873 static int hf_bgp_mcast_vpn_nlri_group_addr_ipv4 = -1;
874 static int hf_bgp_mcast_vpn_nlri_group_addr_ipv6 = -1;
875 static int hf_bgp_mcast_vpn_nlri_route_key = -1;
877 /* BGP flow spec nlri header field */
879 static int hf_bgp_flowspec_nlri_t = -1;
880 static int hf_bgp_flowspec_nlri_filter = -1;
881 static int hf_bgp_flowspec_nlri_filter_type = -1;
882 static int hf_bgp_flowspec_nlri_length = -1;
883 static int hf_bgp_flowspec_nlri_dst_pref_ipv4 = -1;
884 static int hf_bgp_flowspec_nlri_src_pref_ipv4 = -1;
885 static int hf_bgp_flowspec_nlri_op_flags = -1;
886 static int hf_bgp_flowspec_nlri_op_eol = -1;
887 static int hf_bgp_flowspec_nlri_op_and = -1;
888 static int hf_bgp_flowspec_nlri_op_val_len = -1;
889 static int hf_bgp_flowspec_nlri_op_un_bit4 = -1;
890 static int hf_bgp_flowspec_nlri_op_un_bit5 = -1;
891 static int hf_bgp_flowspec_nlri_op_lt = -1;
892 static int hf_bgp_flowspec_nlri_op_gt = -1;
893 static int hf_bgp_flowspec_nlri_op_eq = -1;
894 static int hf_bgp_flowspec_nlri_dec_val_8 = -1;
895 static int hf_bgp_flowspec_nlri_dec_val_16 = -1;
896 static int hf_bgp_flowspec_nlri_dec_val_32 = -1;
897 static int hf_bgp_flowspec_nlri_dec_val_64 = -1;
898 static int hf_bgp_flowspec_nlri_op_flg_not = -1;
899 static int hf_bgp_flowspec_nlri_op_flg_match = -1;
900 static int hf_bgp_flowspec_nlri_tcp_flags = -1;
901 static int hf_bgp_flowspec_nlri_tcp_flags_cwr = -1;
902 static int hf_bgp_flowspec_nlri_tcp_flags_ecn = -1;
903 static int hf_bgp_flowspec_nlri_tcp_flags_urg = -1;
904 static int hf_bgp_flowspec_nlri_tcp_flags_ack = -1;
905 static int hf_bgp_flowspec_nlri_tcp_flags_push = -1;
906 static int hf_bgp_flowspec_nlri_tcp_flags_reset = -1;
907 static int hf_bgp_flowspec_nlri_tcp_flags_syn = -1;
908 static int hf_bgp_flowspec_nlri_tcp_flags_fin = -1;
909 static int hf_bgp_flowspec_nlri_fflag = -1;
910 static int hf_bgp_flowspec_nlri_fflag_lf = -1;
911 static int hf_bgp_flowspec_nlri_fflag_ff = -1;
912 static int hf_bgp_flowspec_nlri_fflag_isf = -1;
913 static int hf_bgp_flowspec_nlri_fflag_df = -1;
914 static int hf_bgp_flowspec_nlri_dscp = -1;
916 /* BGP update safi ndt nlri draft-nalawade-idr-mdt-safi-03 */
918 static int hf_bgp_mdt_nlri_safi_rd = -1;
919 static int hf_bgp_mdt_nlri_safi_ipv4_addr = -1;
920 static int hf_bgp_mdt_nlri_safi_group_addr = -1;
922 /* BGP update extended community header field */
924 /* BGP QoS propagation draft-knoll-idr-qos-attribute */
926 static int hf_bgp_ext_com_qos_flags = -1;
927 static int hf_bgp_ext_com_qos_flags_remarking = -1;
928 static int hf_bgp_ext_com_qos_flags_ignore_remarking = -1;
929 static int hf_bgp_ext_com_qos_flags_agg_marking = -1;
930 static int hf_bgp_ext_com_cos_flags = -1;
931 static int hf_bgp_ext_com_cos_flags_be = -1;
932 static int hf_bgp_ext_com_cos_flags_ef = -1;
933 static int hf_bgp_ext_com_cos_flags_af = -1;
934 static int hf_bgp_ext_com_cos_flags_le = -1;
935 static int hf_bgp_ext_com_qos_set_number = -1;
936 static int hf_bgp_ext_com_qos_tech_type = -1;
937 static int hf_bgp_ext_com_qos_marking_o = -1;
938 static int hf_bgp_ext_com_qos_marking_a = -1;
939 static int hf_bgp_ext_com_qos_default_to_zero = -1;
941 /* BGP Flow spec extended community RFC 5575 */
943 static int hf_bgp_ext_com_flow_rate_float = -1;
944 static int hf_bgp_ext_com_flow_act_allset = -1;
945 static int hf_bgp_ext_com_flow_act_term_act = -1;
946 static int hf_bgp_ext_com_flow_act_samp_act = -1;
947 static int hf_bgp_ext_com_flow_redir_as = -1;
948 static int hf_bgp_ext_com_flow_redir_an = -1;
949 static int hf_bgp_ext_com_flow_redir = -1;
951 /* BGP L2 extended community RFC 4761, RFC 6624 */
952 /* draft-ietf-l2vpn-vpls-multihoming */
954 static int hf_bgp_ext_com_l2_encaps = -1;
955 static int hf_bgp_ext_com_l2_c_flags = -1;
956 static int hf_bgp_ext_com_l2_mtu = -1;
957 static int hf_bgp_ext_com_l2_flag_d = -1;
958 static int hf_bgp_ext_com_l2_flag_z1 = -1;
959 static int hf_bgp_ext_com_l2_flag_f = -1;
960 static int hf_bgp_ext_com_l2_flag_z345 = -1;
961 static int hf_bgp_ext_com_l2_flag_c = -1;
962 static int hf_bgp_ext_com_l2_flag_s = -1;
964 static gint ett_bgp = -1;
965 static gint ett_bgp_prefix = -1;
966 static gint ett_bgp_unfeas = -1;
967 static gint ett_bgp_attrs = -1;
968 static gint ett_bgp_attr = -1;
969 static gint ett_bgp_attr_flags = -1;
970 static gint ett_bgp_mp_nhna = -1;
971 static gint ett_bgp_mp_reach_nlri = -1;
972 static gint ett_bgp_mp_unreach_nlri = -1;
973 static gint ett_bgp_mp_snpa = -1;
974 static gint ett_bgp_nlri = -1;
975 static gint ett_bgp_open = -1;
976 static gint ett_bgp_update = -1;
977 static gint ett_bgp_notification = -1;
978 static gint ett_bgp_route_refresh = -1; /* ROUTE-REFRESH message tree */
979 static gint ett_bgp_capability = -1;
980 static gint ett_bgp_as_paths = -1;
981 static gint ett_bgp_as_path_segments = -1;
982 static gint ett_bgp_communities = -1;
983 static gint ett_bgp_cluster_list = -1; /* cluster list tree */
984 static gint ett_bgp_options = -1; /* optional parameters tree */
985 static gint ett_bgp_option = -1; /* an optional parameter tree */
986 static gint ett_bgp_cap = -1; /* an cap parameter tree */
987 static gint ett_bgp_extended_communities = -1; /* extended communities list tree */
988 static gint ett_bgp_extended_com_fspec_redir = -1; /* extended communities BGP flow act redirect */
989 static gint ett_bgp_ext_com_flags = -1; /* extended communities flags tree */
990 static gint ett_bgp_ext_com_l2_flags = -1; /* extended commuties tree for l2 services flags */
991 static gint ett_bgp_ssa = -1; /* safi specific attribute */
992 static gint ett_bgp_ssa_subtree = -1; /* safi specific attribute Subtrees */
993 static gint ett_bgp_orf = -1; /* orf (outbound route filter) tree */
994 static gint ett_bgp_orf_entry = -1; /* orf entry tree */
995 static gint ett_bgp_mcast_vpn_nlri = -1;
996 static gint ett_bgp_flow_spec_nlri = -1;
997 static gint ett_bgp_flow_spec_nlri_filter = -1; /* tree decoding multiple op and value pairs */
998 static gint ett_bgp_flow_spec_nlri_op_flags = -1; /* tree decoding each op and val pair within the op and value set */
999 static gint ett_bgp_flow_spec_nlri_tcp = -1;
1000 static gint ett_bgp_flow_spec_nlri_ff = -1;
1001 static gint ett_bgp_tunnel_tlv = -1;
1002 static gint ett_bgp_tunnel_tlv_subtree = -1;
1003 static gint ett_bgp_tunnel_subtlv = -1;
1004 static gint ett_bgp_tunnel_subtlv_subtree = -1;
1006 static expert_field ei_bgp_cap_len_bad = EI_INIT;
1007 static expert_field ei_bgp_cap_gr_helper_mode_only = EI_INIT;
1008 static expert_field ei_bgp_notify_minor_unknown = EI_INIT;
1009 static expert_field ei_bgp_route_refresh_orf_type_unknown = EI_INIT;
1010 static expert_field ei_bgp_length_invalid = EI_INIT;
1011 static expert_field ei_bgp_afi_type_not_supported = EI_INIT;
1013 /* desegmentation */
1014 static gboolean bgp_desegment = TRUE;
1016 static gint bgp_asn_len = 0;
1019 * Detect IPv4 prefixes conform to BGP Additional Path but NOT conform to standard BGP
1021 * A real BGP speaker would rely on the BGP Additional Path in the BGP Open messages.
1022 * But it is not suitable for a packet analyse because the BGP sessions are not supposed to
1023 * restart very often, and Open messages from both sides of the session would be needed
1024 * to determine the result of the capability negociation.
1025 * Code inspired from the decode_prefix4 function
1027 static int
1028 detect_add_path_prefix4(tvbuff_t *tvb, gint offset, gint end) {
1029 guint32 addr_len;
1030 guint8 prefix_len;
1031 gint o;
1032 /* Must be compatible with BGP Additional Path */
1033 for (o = offset + 4; o < end; o += 4) {
1034 prefix_len = tvb_get_guint8(tvb, o);
1035 if( prefix_len > 32) {
1036 return 0; /* invalid prefix length - not BGP add-path */
1038 addr_len = (prefix_len + 7) / 8;
1039 o += 1 + addr_len;
1040 if( o > end ) {
1041 return 0; /* invalid offset - not BGP add-path */
1043 if (prefix_len % 8) {
1044 /* detect bits set after the end of the prefix */
1045 if( tvb_get_guint8(tvb, o - 1 ) & (0xFF >> (prefix_len % 8)) ) {
1046 return 0; /* invalid prefix content - not BGP add-path */
1050 /* Must NOT be compatible with standard BGP */
1051 for (o = offset; o < end; ) {
1052 prefix_len = tvb_get_guint8(tvb, o);
1053 if( prefix_len > 32) {
1054 return 1; /* invalid prefix length - may be BGP add-path */
1056 addr_len = (prefix_len + 7) / 8;
1057 o += 1 + addr_len;
1058 if( o > end ) {
1059 return 1; /* invalid offset - may be BGP add-path */
1061 if (prefix_len % 8) {
1062 /* detect bits set after the end of the prefix */
1063 if( tvb_get_guint8(tvb, o - 1 ) & (0xFF >> (prefix_len % 8)) ) {
1064 return 1; /* invalid prefix content - may be BGP add-path (or a bug) */
1068 return 0; /* valid - do not assume Additional Path */
1071 * Decode an IPv4 prefix with Path Identifier
1072 * Code inspired from the decode_prefix4 function
1074 static int
1075 decode_path_prefix4(proto_tree *tree, int hf_path_id, int hf_addr, tvbuff_t *tvb, gint offset,
1076 const char *tag)
1078 proto_item *ti;
1079 proto_tree *prefix_tree;
1080 union {
1081 guint8 addr_bytes[4];
1082 guint32 addr;
1083 } ip_addr; /* IP address */
1084 guint8 plen; /* prefix length */
1085 int length; /* number of octets needed for prefix */
1086 guint32 path_identifier;
1087 /* snarf path identifier length and prefix */
1088 path_identifier = tvb_get_ntohl(tvb, offset);
1089 plen = tvb_get_guint8(tvb, offset + 4);
1090 length = ipv4_addr_and_mask(tvb, offset + 4 + 1, ip_addr.addr_bytes, plen);
1091 if (length < 0) {
1092 proto_tree_add_text(tree, tvb, offset + 4 , 1, "%s length %u invalid (> 32)",
1093 tag, plen);
1094 return -1;
1096 /* put prefix into protocol tree */
1097 ti = proto_tree_add_text(tree, tvb, offset,
1098 4 + 1 + length, "%s/%u PathId %u ",
1099 ip_to_str(ip_addr.addr_bytes), plen, path_identifier);
1100 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
1101 if (hf_path_id != -1) {
1102 proto_tree_add_uint(prefix_tree, hf_path_id, tvb, offset, 4,
1103 path_identifier);
1104 } else {
1105 proto_tree_add_text(prefix_tree, tvb, offset, 4,
1106 "%s Path Id: %u", tag, path_identifier);
1108 proto_tree_add_text(prefix_tree, tvb, offset + 4, 1, "%s prefix length: %u",
1109 tag, plen);
1110 if (hf_addr != -1) {
1111 proto_tree_add_ipv4(prefix_tree, hf_addr, tvb, offset + 4 + 1, length,
1112 ip_addr.addr);
1113 } else {
1114 proto_tree_add_text(prefix_tree, tvb, offset + 4 + 1, length,
1115 "%s prefix: %s", tag, ip_to_str(ip_addr.addr_bytes));
1117 return(4 + 1 + length);
1121 * Decode an IPv4 prefix.
1123 static int
1124 decode_prefix4(proto_tree *tree, proto_item *parent_item, int hf_addr, tvbuff_t *tvb, gint offset,
1125 guint16 tlen, const char *tag)
1127 proto_item *ti;
1128 proto_tree *prefix_tree;
1129 union {
1130 guint8 addr_bytes[4];
1131 guint32 addr;
1132 } ip_addr; /* IP address */
1133 guint8 plen; /* prefix length */
1134 int length; /* number of octets needed for prefix */
1136 /* snarf length and prefix */
1137 plen = tvb_get_guint8(tvb, offset);
1138 length = ipv4_addr_and_mask(tvb, offset + 1, ip_addr.addr_bytes, plen);
1139 if (length < 0) {
1140 proto_tree_add_text(tree, tvb, offset, 1, "%s length %u invalid (> 32)",
1141 tag, plen);
1142 return -1;
1145 /* put prefix into protocol tree */
1146 ti = proto_tree_add_text(tree, tvb, offset,
1147 tlen != 0 ? tlen : 1 + length, "%s/%u",
1148 ip_to_str(ip_addr.addr_bytes), plen);
1149 /* append parent item if not NULL */
1150 if (parent_item != NULL)
1151 proto_item_append_text(parent_item, " (%s/%u)",
1152 ip_to_str(ip_addr.addr_bytes), plen);
1154 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
1155 proto_tree_add_text(prefix_tree, tvb, offset, 1, "%s prefix length: %u",
1156 tag, plen);
1157 if (hf_addr != -1) {
1158 proto_tree_add_ipv4(prefix_tree, hf_addr, tvb, offset + 1, length,
1159 ip_addr.addr);
1160 } else {
1161 proto_tree_add_text(prefix_tree, tvb, offset + 1, length,
1162 "%s prefix: %s", tag, ip_to_str(ip_addr.addr_bytes));
1164 return(1 + length);
1168 * Decode an IPv6 prefix.
1170 static int
1171 decode_prefix6(proto_tree *tree, int hf_addr, tvbuff_t *tvb, gint offset,
1172 guint16 tlen, const char *tag)
1174 proto_item *ti;
1175 proto_tree *prefix_tree;
1176 struct e_in6_addr addr; /* IPv6 address */
1177 int plen; /* prefix length */
1178 int length; /* number of octets needed for prefix */
1180 /* snarf length and prefix */
1181 plen = tvb_get_guint8(tvb, offset);
1182 length = ipv6_addr_and_mask(tvb, offset + 1, &addr, plen);
1183 if (length < 0) {
1184 proto_tree_add_text(tree, tvb, offset, 1, "%s length %u invalid",
1185 tag, plen);
1186 return -1;
1189 /* put prefix into protocol tree */
1190 ti = proto_tree_add_text(tree, tvb, offset,
1191 tlen != 0 ? tlen : 1 + length, "%s/%u",
1192 ip6_to_str(&addr), plen);
1193 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
1194 proto_tree_add_text(prefix_tree, tvb, offset, 1, "%s prefix length: %u",
1195 tag, plen);
1196 if (hf_addr != -1) {
1197 proto_tree_add_ipv6(prefix_tree, hf_addr, tvb, offset + 1, length,
1198 addr.bytes);
1199 } else {
1200 proto_tree_add_text(prefix_tree, tvb, offset + 1, length,
1201 "%s prefix: %s", tag, ip6_to_str(&addr));
1203 return(1 + length);
1206 static char*
1207 decode_bgp_rd(tvbuff_t *tvb, gint offset)
1209 guint16 rd_type;
1210 wmem_strbuf_t *strbuf;
1212 rd_type = tvb_get_ntohs(tvb,offset);
1213 strbuf = wmem_strbuf_new_label(wmem_packet_scope());
1215 switch (rd_type) {
1216 case FORMAT_AS2_LOC:
1217 wmem_strbuf_append_printf(strbuf, "%u:%u", tvb_get_ntohs(tvb, offset + 2),
1218 tvb_get_ntohl(tvb, offset + 4));
1219 break;
1220 case FORMAT_IP_LOC:
1221 wmem_strbuf_append_printf(strbuf, "%s:%u", tvb_ip_to_str(tvb, offset + 2),
1222 tvb_get_ntohs(tvb, offset + 6));
1223 break ;
1224 case FORMAT_AS4_LOC:
1225 wmem_strbuf_append_printf(strbuf, "%u:%u", tvb_get_ntohl(tvb, offset + 2),
1226 tvb_get_ntohs(tvb, offset + 6));
1227 break ;
1228 default:
1229 wmem_strbuf_append_printf(strbuf, "Unknown (0x%04x) RD type",rd_type);
1230 break;
1231 } /* switch (rd_type) */
1233 return (char*)wmem_strbuf_get_str(strbuf);
1236 static int
1237 decode_mcast_vpn_nlri_addresses(proto_tree *tree, tvbuff_t *tvb,
1238 gint offset)
1240 guint8 addr_len;
1242 /* Multicast Source Address */
1243 proto_tree_add_item(tree, hf_bgp_mcast_vpn_nlri_source_length, tvb, offset,
1244 1, ENC_BIG_ENDIAN);
1245 addr_len = tvb_get_guint8(tvb, offset);
1246 if (addr_len != 32 && addr_len != 128)
1247 return -1;
1248 offset++;
1249 if (addr_len == 32) {
1250 proto_tree_add_item(tree, hf_bgp_mcast_vpn_nlri_source_addr_ipv4, tvb,
1251 offset, 4, ENC_BIG_ENDIAN);
1252 offset += 4;
1253 } else {
1254 proto_tree_add_item(tree, hf_bgp_mcast_vpn_nlri_source_addr_ipv6, tvb,
1255 offset, 16, ENC_NA);
1256 offset += 16;
1259 /* Multicast Group Address */
1260 proto_tree_add_item(tree, hf_bgp_mcast_vpn_nlri_group_length, tvb, offset,
1261 1, ENC_BIG_ENDIAN);
1262 addr_len = tvb_get_guint8(tvb, offset);
1263 if (addr_len != 32 && addr_len != 128)
1264 return -1;
1265 offset++;
1266 if (addr_len == 32) {
1267 proto_tree_add_item(tree, hf_bgp_mcast_vpn_nlri_group_addr_ipv4, tvb,
1268 offset, 4, ENC_BIG_ENDIAN);
1269 offset += 4;
1270 } else {
1271 proto_tree_add_item(tree, hf_bgp_mcast_vpn_nlri_group_addr_ipv6, tvb,
1272 offset, 16, ENC_NA);
1273 offset += 16;
1276 return offset;
1280 * function to decode operator in BGP flow spec NLRI when it address decimal values (TCP ports, UDP ports, ports, ...)
1283 static void
1284 decode_bgp_flow_spec_dec_operator(proto_tree *tree, tvbuff_t *tvb, gint offset)
1287 proto_item *op_item;
1288 proto_tree *op_tree;
1290 op_item = proto_tree_add_item(tree, hf_bgp_flowspec_nlri_op_flags, tvb, offset, 1, ENC_NA);
1291 op_tree = proto_item_add_subtree(op_item, ett_bgp_flow_spec_nlri_op_flags);
1293 proto_tree_add_item(op_tree, hf_bgp_flowspec_nlri_op_eol,tvb,offset,1, ENC_BIG_ENDIAN);
1294 proto_tree_add_item(op_tree, hf_bgp_flowspec_nlri_op_and, tvb,offset,1, ENC_BIG_ENDIAN);
1295 proto_tree_add_item(op_tree, hf_bgp_flowspec_nlri_op_val_len ,tvb, offset, 1, ENC_BIG_ENDIAN);
1296 proto_tree_add_item(op_tree, hf_bgp_flowspec_nlri_op_un_bit4, tvb, offset, 1, ENC_BIG_ENDIAN);
1297 proto_tree_add_item(op_tree, hf_bgp_flowspec_nlri_op_lt, tvb,offset, 1, ENC_BIG_ENDIAN);
1298 proto_tree_add_item(op_tree, hf_bgp_flowspec_nlri_op_gt, tvb,offset, 1, ENC_BIG_ENDIAN);
1299 proto_tree_add_item(op_tree, hf_bgp_flowspec_nlri_op_eq, tvb,offset, 1, ENC_BIG_ENDIAN);
1303 * Decode an operator and decimal values of BGP flow spec NLRI
1305 static int
1306 decode_bgp_nlri_op_dec_value(proto_tree *parent_tree, proto_item *parent_item, tvbuff_t *tvb, gint offset)
1308 guint8 nlri_operator;
1309 guint cursor_op_val=0;
1310 guint8 value_len=0;
1311 guint value=0;
1312 guint8 shift_amount=0;
1313 guint first_loop=0;
1315 proto_item_append_text(parent_item," (");
1317 do {
1318 nlri_operator = tvb_get_guint8(tvb, offset+cursor_op_val);
1319 shift_amount = nlri_operator&0x30;
1320 shift_amount = shift_amount >> 4;
1321 value_len = 1 << shift_amount; /* as written in RFC 5575 section 4 */
1322 /* call to a operator decode function */
1323 decode_bgp_flow_spec_dec_operator(parent_tree, tvb, offset+cursor_op_val);
1324 if (first_loop == 0)
1326 /* If first operator we remoe a white space and or (||) is not relevant */
1327 /* BGP flow spec NLRI operator bitmask */
1328 proto_item_append_text(parent_item,"%s%s%s%s",
1329 ((nlri_operator & BGPNLRI_FSPEC_AND_BIT) == 0) ? "" : "&& ",
1330 ((nlri_operator & BGPNLRI_FSPEC_GREATER_THAN) == 0) ? "" : ">",
1331 ((nlri_operator & BGPNLRI_FSPEC_LESS_THAN) == 0) ? "" : "<",
1332 ((nlri_operator & BGPNLRI_FSPEC_EQUAL) == 0) ? "" : "=");
1333 first_loop = 1;
1335 else
1337 proto_item_append_text(parent_item," %s%s%s%s",
1338 ((nlri_operator & BGPNLRI_FSPEC_AND_BIT) == 0) ? "||" : "&& ",
1339 ((nlri_operator & BGPNLRI_FSPEC_GREATER_THAN) == 0) ? "" : ">",
1340 ((nlri_operator & BGPNLRI_FSPEC_LESS_THAN) == 0) ? "" : "<",
1341 ((nlri_operator & BGPNLRI_FSPEC_EQUAL) == 0) ? "" : "=");
1343 cursor_op_val++; /* we manage this operator we move to the value */
1344 switch (value_len) {
1345 case 1:
1346 proto_tree_add_item(parent_tree, hf_bgp_flowspec_nlri_dec_val_8, tvb, offset+cursor_op_val, 1,ENC_BIG_ENDIAN);
1347 value = tvb_get_guint8(tvb,offset+cursor_op_val);
1348 break;
1349 case 2:
1350 proto_tree_add_item(parent_tree, hf_bgp_flowspec_nlri_dec_val_16, tvb, offset+cursor_op_val, 2,ENC_BIG_ENDIAN);
1351 value = tvb_get_ntohs(tvb,offset+cursor_op_val);
1352 break;
1353 case 3:
1354 proto_tree_add_item(parent_tree, hf_bgp_flowspec_nlri_dec_val_32, tvb, offset+cursor_op_val, 4, ENC_BIG_ENDIAN);
1355 value = tvb_get_ntohl(tvb,offset+cursor_op_val);
1356 break;
1357 case 4:
1358 proto_tree_add_item(parent_tree, hf_bgp_flowspec_nlri_dec_val_64, tvb, offset+cursor_op_val, 8, ENC_BIG_ENDIAN);
1359 break;
1360 default:
1361 return -1;
1363 cursor_op_val = cursor_op_val + value_len;
1364 proto_item_append_text(parent_item,"%u", value);
1365 } while ((nlri_operator&BGPNLRI_FSPEC_END_OF_LST) == 0);
1366 proto_item_append_text(parent_item,")");
1367 return (cursor_op_val);
1372 * function to decode operator in BGP flow spec NLRI when it address a bitmask values (TCP flags, fragmentation flags,...)
1375 static void
1376 decode_bgp_flow_spec_bitmask_operator(proto_tree *tree, tvbuff_t *tvb, gint offset)
1378 proto_item *op_item;
1379 proto_tree *op_tree;
1381 op_item = proto_tree_add_item(tree, hf_bgp_flowspec_nlri_op_flags, tvb, offset, 1, ENC_NA);
1382 op_tree = proto_item_add_subtree(op_item, ett_bgp_flow_spec_nlri_op_flags);
1384 proto_tree_add_item(op_tree, hf_bgp_flowspec_nlri_op_eol,tvb,offset,1, ENC_BIG_ENDIAN);
1385 proto_tree_add_item(op_tree, hf_bgp_flowspec_nlri_op_and, tvb,offset,1, ENC_BIG_ENDIAN);
1386 proto_tree_add_item(op_tree, hf_bgp_flowspec_nlri_op_val_len ,tvb, offset, 1, ENC_BIG_ENDIAN);
1387 proto_tree_add_item(op_tree, hf_bgp_flowspec_nlri_op_un_bit4, tvb, offset, 1, ENC_BIG_ENDIAN);
1388 proto_tree_add_item(op_tree, hf_bgp_flowspec_nlri_op_un_bit5, tvb, offset, 1, ENC_BIG_ENDIAN);
1389 proto_tree_add_item(op_tree, hf_bgp_flowspec_nlri_op_flg_not, tvb,offset, 1,ENC_BIG_ENDIAN);
1390 proto_tree_add_item(op_tree, hf_bgp_flowspec_nlri_op_flg_match, tvb,offset, 1,ENC_BIG_ENDIAN);
1394 * Decode an operator and tcp flags bitmask of BGP flow spec NLRI
1396 static int
1397 decode_bgp_nlri_op_tcpf_value(proto_tree *parent_tree, proto_item *parent_item, tvbuff_t *tvb, gint offset)
1399 guint8 nlri_operator;
1400 guint8 tcp_flags;
1401 guint cursor_op_val=0;
1402 proto_tree *tcp_tree;
1403 proto_item *tcp_item;
1404 guint8 value_len=0;
1405 guint8 shift_amount=0;
1406 guint first_loop=0;
1408 proto_item_append_text(parent_item," (");
1410 do {
1411 nlri_operator = tvb_get_guint8(tvb, offset+cursor_op_val);
1412 shift_amount = nlri_operator&0x30;
1413 shift_amount = shift_amount >> 4;
1414 value_len = 1 << shift_amount; /* as written in RFC 5575 section 4 */
1415 decode_bgp_flow_spec_bitmask_operator(parent_tree, tvb, offset+cursor_op_val); /* call to a operator decode function */
1416 if (first_loop == 0)
1418 /* If first operator we remove a white space and or (||) is not relevant */
1419 proto_item_append_text(parent_item,"%s%s%s%s",
1420 ((nlri_operator & BGPNLRI_FSPEC_AND_BIT) == 0) ? "" : "&& ",
1421 ((nlri_operator & BGPNLRI_FSPEC_GREATER_THAN) == 0) ? "" : ">",
1422 ((nlri_operator & BGPNLRI_FSPEC_LESS_THAN) == 0) ? "" : "<",
1423 ((nlri_operator & BGPNLRI_FSPEC_EQUAL) == 0) ? "" : "=");
1424 first_loop = 1;
1426 else
1428 proto_item_append_text(parent_item," %s%s%s%s",
1429 ((nlri_operator & BGPNLRI_FSPEC_AND_BIT) == 0) ? "||" : "&& ",
1430 ((nlri_operator & BGPNLRI_FSPEC_GREATER_THAN) == 0) ? "" : ">",
1431 ((nlri_operator & BGPNLRI_FSPEC_LESS_THAN) == 0) ? "" : "<",
1432 ((nlri_operator & BGPNLRI_FSPEC_EQUAL) == 0) ? "" : "=");
1434 cursor_op_val++; /* we manage this operator we move to the value */
1435 if (value_len == 2) {
1436 cursor_op_val++; /* tcp flags are coded over 2 bytes only the second one is significant, we move to second byte */
1439 tcp_item = proto_tree_add_item(parent_tree, hf_bgp_flowspec_nlri_tcp_flags, tvb, offset+cursor_op_val, 1, ENC_NA);
1440 tcp_tree = proto_item_add_subtree(tcp_item, ett_bgp_flow_spec_nlri_tcp);
1441 tcp_flags = tvb_get_guint8(tvb,offset+cursor_op_val);
1443 proto_tree_add_item(tcp_tree, hf_bgp_flowspec_nlri_tcp_flags_cwr, tvb, offset+cursor_op_val, 1, ENC_BIG_ENDIAN);
1444 proto_tree_add_item(tcp_tree, hf_bgp_flowspec_nlri_tcp_flags_ecn, tvb, offset+cursor_op_val, 1, ENC_BIG_ENDIAN);
1445 proto_tree_add_item(tcp_tree, hf_bgp_flowspec_nlri_tcp_flags_urg, tvb, offset+cursor_op_val, 1, ENC_BIG_ENDIAN);
1446 proto_tree_add_item(tcp_tree, hf_bgp_flowspec_nlri_tcp_flags_ack, tvb, offset+cursor_op_val, 1, ENC_BIG_ENDIAN);
1447 proto_tree_add_item(tcp_tree, hf_bgp_flowspec_nlri_tcp_flags_push, tvb, offset+cursor_op_val, 1, ENC_BIG_ENDIAN);
1448 proto_tree_add_item(tcp_tree, hf_bgp_flowspec_nlri_tcp_flags_reset, tvb, offset+cursor_op_val, 1, ENC_BIG_ENDIAN);
1449 proto_tree_add_item(tcp_tree, hf_bgp_flowspec_nlri_tcp_flags_syn, tvb, offset+cursor_op_val, 1, ENC_BIG_ENDIAN);
1450 proto_tree_add_item(tcp_tree, hf_bgp_flowspec_nlri_tcp_flags_fin, tvb, offset+cursor_op_val, 1, ENC_BIG_ENDIAN);
1451 proto_item_append_text(parent_item," %s%s%s%s%s%s",
1452 ((tcp_flags & BGPNLRI_FSPEC_TH_URG) == 0) ? "" : "U",
1453 ((tcp_flags & BGPNLRI_FSPEC_TH_ACK) == 0) ? "" : "A",
1454 ((tcp_flags & BGPNLRI_FSPEC_TH_PUSH) == 0) ? "" : "P",
1455 ((tcp_flags & BGPNLRI_FSPEC_TH_RST) == 0) ? "" : "R",
1456 ((tcp_flags & BGPNLRI_FSPEC_TH_SYN) == 0) ? "" : "S",
1457 ((tcp_flags & BGPNLRI_FSPEC_TH_FIN) == 0) ? "" : "F");
1458 cursor_op_val = cursor_op_val + value_len;
1459 } while ((nlri_operator&BGPNLRI_FSPEC_END_OF_LST) == 0);
1460 proto_item_append_text(parent_item,")");
1461 return (cursor_op_val);
1466 * Decode an operator and fragmentation bitmask of BGP flow spec NLRI
1468 static int
1469 decode_bgp_nlri_op_fflag_value(proto_tree *parent_tree, proto_item *parent_item, tvbuff_t *tvb, gint offset)
1471 guint8 nlri_operator;
1472 guint8 fragment_flags;
1473 guint cursor_op_val=0;
1474 proto_tree *ff_tree;
1475 proto_item *ff_item;
1476 guint8 value_len=0;
1477 guint8 shift_amount=0;
1478 guint first_loop=0;
1480 proto_item_append_text(parent_item," (");
1482 do {
1483 nlri_operator = tvb_get_guint8(tvb, offset+cursor_op_val);
1484 shift_amount = nlri_operator&0x30;
1485 shift_amount = shift_amount >> 4;
1486 value_len = 1 << shift_amount; /* as written in RFC 5575 section 4 */
1487 /* call a function to decode operator addressing bitmaks */
1488 decode_bgp_flow_spec_bitmask_operator(parent_tree, tvb, offset+cursor_op_val);
1489 if (first_loop == 0)
1491 /* If first operator we remove a white space and or (||) is not relevant */
1492 proto_item_append_text(parent_item,"%s%s%s%s",
1493 ((nlri_operator & BGPNLRI_FSPEC_AND_BIT) == 0) ? "" : "&& ",
1494 ((nlri_operator & BGPNLRI_FSPEC_GREATER_THAN) == 0) ? "" : ">",
1495 ((nlri_operator & BGPNLRI_FSPEC_LESS_THAN) == 0) ? "" : "<",
1496 ((nlri_operator & BGPNLRI_FSPEC_EQUAL) == 0) ? "" : "=");
1497 first_loop = 1;
1499 else
1501 proto_item_append_text(parent_item," %s%s%s%s",
1502 ((nlri_operator & BGPNLRI_FSPEC_AND_BIT) == 0) ? "||" : "&& ",
1503 ((nlri_operator & BGPNLRI_FSPEC_GREATER_THAN) == 0) ? "" : ">",
1504 ((nlri_operator & BGPNLRI_FSPEC_LESS_THAN) == 0) ? "" : "<",
1505 ((nlri_operator & BGPNLRI_FSPEC_EQUAL) == 0) ? "" : "=");
1507 cursor_op_val++; /* we manage this operator we move to the value */
1508 if (value_len != 1) {
1509 return -1; /* frag flags have to be coded in 1 byte */
1511 fragment_flags = tvb_get_guint8(tvb,offset+cursor_op_val);
1512 ff_item = proto_tree_add_item(parent_tree, hf_bgp_flowspec_nlri_fflag, tvb, offset+cursor_op_val, 1, ENC_NA);
1513 ff_tree = proto_item_add_subtree(ff_item, ett_bgp_flow_spec_nlri_ff);
1514 proto_tree_add_item(ff_tree, hf_bgp_flowspec_nlri_fflag_lf, tvb, offset+cursor_op_val, 1, ENC_BIG_ENDIAN);
1515 proto_tree_add_item(ff_tree, hf_bgp_flowspec_nlri_fflag_ff, tvb, offset+cursor_op_val, 1, ENC_BIG_ENDIAN);
1516 proto_tree_add_item(ff_tree, hf_bgp_flowspec_nlri_fflag_isf, tvb, offset+cursor_op_val, 1, ENC_BIG_ENDIAN);
1517 proto_tree_add_item(ff_tree, hf_bgp_flowspec_nlri_fflag_df, tvb, offset+cursor_op_val, 1, ENC_BIG_ENDIAN);
1518 proto_item_append_text(parent_item," %s%s%s%s",
1519 ((fragment_flags & BGPNLRI_FSPEC_FG_DF) == 0) ? "" : "DF",
1520 ((fragment_flags & BGPNLRI_FSPEC_FG_ISF) == 0) ? "" : "IsF",
1521 ((fragment_flags & BGPNLRI_FSPEC_FG_FF) == 0) ? "" : "FF",
1522 ((fragment_flags & BGPNLRI_FSPEC_FG_LF) == 0) ? "" : "LF");
1523 cursor_op_val = cursor_op_val + value_len;
1524 } while ((nlri_operator&BGPNLRI_FSPEC_END_OF_LST) == 0);
1525 proto_item_append_text(parent_item,")");
1526 return (cursor_op_val);
1530 * Decode an operator and DSCP value of BGP flow spec NLRI
1532 static int
1533 decode_bgp_nlri_op_dscp_value(proto_tree *parent_tree, proto_item *parent_item, tvbuff_t *tvb, gint offset)
1535 guint8 nlri_operator;
1536 guint8 dscp_flags;
1537 guint cursor_op_val=0;
1538 guint8 value_len=0;
1539 guint8 shift_amount=0;
1540 guint first_loop=0;
1542 proto_item_append_text(parent_item," (");
1544 do {
1545 nlri_operator = tvb_get_guint8(tvb, offset+cursor_op_val);
1546 shift_amount = nlri_operator&0x30;
1547 shift_amount = shift_amount >> 4;
1548 value_len = 1 << shift_amount; /* as written in RFC 5575 section 4 */
1549 /* call a function to decode operator addressing bitmaks */
1550 decode_bgp_flow_spec_bitmask_operator(parent_tree, tvb, offset+cursor_op_val);
1551 if (first_loop == 0)
1553 /* If first operator we remove a white space and or (||) is not relevant */
1554 proto_item_append_text(parent_item,"%s%s%s%s",
1555 ((nlri_operator & BGPNLRI_FSPEC_AND_BIT) == 0) ? "" : "&& ",
1556 ((nlri_operator & BGPNLRI_FSPEC_GREATER_THAN) == 0) ? "" : ">",
1557 ((nlri_operator & BGPNLRI_FSPEC_LESS_THAN) == 0) ? "" : "<",
1558 ((nlri_operator & BGPNLRI_FSPEC_EQUAL) == 0) ? "" : "=");
1559 first_loop = 1;
1561 else
1563 proto_item_append_text(parent_item," %s%s%s%s",
1564 ((nlri_operator & BGPNLRI_FSPEC_AND_BIT) == 0) ? "||" : "&& ",
1565 ((nlri_operator & BGPNLRI_FSPEC_GREATER_THAN) == 0) ? "" : ">",
1566 ((nlri_operator & BGPNLRI_FSPEC_LESS_THAN) == 0) ? "" : "<",
1567 ((nlri_operator & BGPNLRI_FSPEC_EQUAL) == 0) ? "" : "=");
1569 cursor_op_val++; /* we manage this operator we move to the value */
1570 if (value_len != 1) {
1571 return -1; /* frag flags have to be coded in 1 byte */
1573 dscp_flags = tvb_get_guint8(tvb,offset+cursor_op_val);
1574 dscp_flags = dscp_flags >> 2;
1575 proto_tree_add_item(parent_tree, hf_bgp_flowspec_nlri_dscp, tvb, offset+cursor_op_val, 1, ENC_BIG_ENDIAN);
1576 proto_item_append_text(parent_item,"%s",val_to_str_ext_const(dscp_flags,&dscp_vals_ext, "Unknown DSCP"));
1577 cursor_op_val = cursor_op_val + value_len;
1578 } while ((nlri_operator&BGPNLRI_FSPEC_END_OF_LST) == 0);
1579 proto_item_append_text(parent_item,")");
1580 return (cursor_op_val);
1586 * Decode an FLOWSPEC nlri as define in RFC 5575
1588 static int
1589 decode_flowspec_nlri(proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 afi, packet_info *pinfo)
1591 guint tot_flow_len; /* total length of the flow spec NLRI */
1592 guint offset_len; /* offset of the flow spec NLRI itself could be 1 or 2 bytes */
1593 guint cursor_fspec; /* cursor to move into flow spec nlri */
1594 gint filter_len;
1595 guint16 len_16;
1596 proto_item *item;
1597 proto_item *filter_item;
1598 proto_tree *nlri_tree;
1599 proto_tree *filter_tree;
1602 if (afi != AFNUM_INET)
1604 expert_add_info(pinfo, NULL, &ei_bgp_afi_type_not_supported);
1605 return(-1);
1608 tot_flow_len = tvb_get_guint8(tvb, offset);
1609 /* if nlri length is greater than 240 bytes, it is encoded over 2 bytes */
1610 /* with most significant nibble all in one. 240 is encoded 0xf0f0, 241 0xf0f1 */
1611 /* max possible value value is 4095 Oxffff */
1613 if (tot_flow_len >= 240)
1615 len_16 = tvb_get_ntohs(tvb, offset);
1616 tot_flow_len = len_16 >> 4; /* move 4 bits to the right to remove first f */
1617 offset_len = 2;
1618 } else {
1619 offset_len = 1;
1622 item = proto_tree_add_item(tree, hf_bgp_flowspec_nlri_t, tvb, offset,
1623 tot_flow_len+offset_len, ENC_NA);
1624 proto_item_set_text(item, "FLOW_SPEC_NLRI (%u byte%s)",
1625 tot_flow_len+offset_len, plurality(tot_flow_len+offset_len, "", "s"));
1627 nlri_tree = proto_item_add_subtree(item, ett_bgp_flow_spec_nlri);
1629 proto_tree_add_uint(nlri_tree, hf_bgp_flowspec_nlri_length, tvb, offset,
1630 offset_len, tot_flow_len);
1632 offset = offset + offset_len;
1633 cursor_fspec = 0;
1635 while (cursor_fspec < tot_flow_len)
1637 filter_item = proto_tree_add_item(nlri_tree, hf_bgp_flowspec_nlri_filter, tvb, offset+cursor_fspec, 1, ENC_NA);
1638 filter_tree = proto_item_add_subtree(filter_item, ett_bgp_flow_spec_nlri_filter);
1639 proto_tree_add_item(filter_tree, hf_bgp_flowspec_nlri_filter_type, tvb, offset+cursor_fspec, 1, ENC_NA);
1640 proto_item_append_text(filter_item, ": %s", val_to_str(tvb_get_guint8(tvb,offset+cursor_fspec), flowspec_nlri_opvaluepair_type, "Unknown filter %d"));
1641 switch (tvb_get_guint8(tvb,offset+cursor_fspec)) {
1642 case BGPNLRI_FSPEC_DST_PFIX:
1643 cursor_fspec++;
1644 filter_len = decode_prefix4(filter_tree, filter_item, hf_bgp_flowspec_nlri_dst_pref_ipv4, tvb, offset+cursor_fspec, 0, "Destination IP filter");
1645 if (filter_len == -1)
1646 cursor_fspec= tot_flow_len;
1647 break;
1648 case BGPNLRI_FSPEC_SRC_PFIX:
1649 cursor_fspec++;
1650 filter_len = decode_prefix4(filter_tree, filter_item, hf_bgp_flowspec_nlri_src_pref_ipv4, tvb, offset+cursor_fspec, 0, "Source IP filter");
1651 if (filter_len == -1)
1652 cursor_fspec= tot_flow_len;
1653 break;
1654 case BGPNLRI_FSPEC_IP_PROTO:
1655 cursor_fspec++;
1656 filter_len = decode_bgp_nlri_op_dec_value(filter_tree, filter_item, tvb, offset+cursor_fspec);
1657 break;
1658 case BGPNLRI_FSPEC_PORT:
1659 cursor_fspec++;
1660 filter_len = decode_bgp_nlri_op_dec_value(filter_tree, filter_item, tvb, offset+cursor_fspec);
1661 break;
1662 case BGPNLRI_FSPEC_DST_PORT:
1663 cursor_fspec++;
1664 filter_len = decode_bgp_nlri_op_dec_value(filter_tree, filter_item, tvb, offset+cursor_fspec);
1665 break;
1666 case BGPNLRI_FSPEC_SRC_PORT:
1667 cursor_fspec++;
1668 filter_len = decode_bgp_nlri_op_dec_value(filter_tree, filter_item, tvb, offset+cursor_fspec);
1669 break;
1670 case BGPNLRI_FSPEC_ICMP_TP:
1671 cursor_fspec++;
1672 filter_len = decode_bgp_nlri_op_dec_value(filter_tree, filter_item, tvb, offset+cursor_fspec);
1673 break;
1674 case BGPNLRI_FSPEC_ICMP_CD:
1675 cursor_fspec++;
1676 filter_len = decode_bgp_nlri_op_dec_value(filter_tree, filter_item, tvb, offset+cursor_fspec);
1677 break;
1678 case BGPNLRI_FSPEC_TCP_FLAGS:
1679 cursor_fspec++;
1680 filter_len = decode_bgp_nlri_op_tcpf_value(filter_tree, filter_item, tvb, offset+cursor_fspec);
1681 break;
1682 case BGPNLRI_FSPEC_PCK_LEN:
1683 cursor_fspec++;
1684 filter_len = decode_bgp_nlri_op_dec_value(filter_tree, filter_item, tvb, offset+cursor_fspec);
1685 break;
1686 case BGPNLRI_FSPEC_DSCP:
1687 cursor_fspec++;
1688 filter_len = decode_bgp_nlri_op_dscp_value(filter_tree, filter_item, tvb, offset+cursor_fspec);
1689 break;
1690 case BGPNLRI_FSPEC_FRAGMENT:
1691 cursor_fspec++;
1692 filter_len = decode_bgp_nlri_op_fflag_value(filter_tree, filter_item, tvb, offset+cursor_fspec);
1693 break;
1694 default:
1695 proto_tree_add_text(filter_tree, tvb, offset+cursor_fspec,1,
1696 "NLRI Type unknown (%u)",tvb_get_guint8(tvb,offset+cursor_fspec));
1697 return -1;
1699 if (filter_len>0)
1700 cursor_fspec += filter_len;
1701 else
1702 break;
1703 proto_item_set_len(filter_item,filter_len+1);
1705 return(tot_flow_len);
1709 * Decode an MCAST-VPN nlri as defined in draft-ietf-l3vpn-2547bis-mcast-bgp-08.txt .
1711 static int
1712 decode_mcast_vpn_nlri(proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 afi)
1714 guint8 route_type, length, ip_length;
1715 proto_item *item;
1716 proto_tree *nlri_tree;
1717 guint32 route_key_length;
1718 int ret;
1720 ip_length = (afi == AFNUM_INET) ? 4 : 16;
1722 route_type = tvb_get_guint8(tvb, offset);
1723 proto_tree_add_item(tree, hf_bgp_mcast_vpn_nlri_route_type, tvb,
1724 offset, 1, ENC_BIG_ENDIAN);
1725 offset++;
1727 length = tvb_get_guint8(tvb, offset);
1728 proto_tree_add_item(tree, hf_bgp_mcast_vpn_nlri_length, tvb, offset,
1729 1, ENC_BIG_ENDIAN);
1730 offset++;
1732 if (length < tvb_reported_length_remaining(tvb, offset))
1733 return -1;
1735 item = proto_tree_add_item(tree, hf_bgp_mcast_vpn_nlri_t, tvb, offset,
1736 length, ENC_NA);
1737 proto_item_set_text(item, "%s (%u byte%s)",
1738 val_to_str_const(route_type, mcast_vpn_route_type, "Unknown"),
1739 length, plurality(length, "", "s"));
1741 nlri_tree = proto_item_add_subtree(item, ett_bgp_mcast_vpn_nlri);
1743 switch (route_type) {
1744 case MCAST_VPN_RTYPE_INTRA_AS_IPMSI_AD:
1745 item = proto_tree_add_item(nlri_tree, hf_bgp_mcast_vpn_nlri_rd, tvb,
1746 offset, BGP_ROUTE_DISTINGUISHER_SIZE,
1747 ENC_NA);
1748 proto_item_set_text(item, "Route Distinguisher: %s",
1749 decode_bgp_rd(tvb, offset));
1750 offset += BGP_ROUTE_DISTINGUISHER_SIZE;
1752 if (afi == AFNUM_INET)
1753 proto_tree_add_item(nlri_tree,
1754 hf_bgp_mcast_vpn_nlri_origin_router_ipv4,
1755 tvb, offset, ip_length, ENC_BIG_ENDIAN);
1756 else
1757 proto_tree_add_item(nlri_tree,
1758 hf_bgp_mcast_vpn_nlri_origin_router_ipv6,
1759 tvb, offset, ip_length, ENC_NA);
1760 break;
1762 case MCAST_VPN_RTYPE_INTER_AS_IPMSI_AD:
1763 item = proto_tree_add_item(nlri_tree, hf_bgp_mcast_vpn_nlri_rd, tvb,
1764 offset, BGP_ROUTE_DISTINGUISHER_SIZE,
1765 ENC_NA);
1766 proto_item_set_text(item, "Route Distinguisher: %s",
1767 decode_bgp_rd(tvb, offset));
1768 offset += BGP_ROUTE_DISTINGUISHER_SIZE;
1770 proto_tree_add_item(nlri_tree, hf_bgp_mcast_vpn_nlri_source_as, tvb,
1771 offset, 4, ENC_BIG_ENDIAN);
1772 break;
1774 case MCAST_VPN_RTYPE_SPMSI_AD:
1775 item = proto_tree_add_item(nlri_tree, hf_bgp_mcast_vpn_nlri_rd, tvb,
1776 offset, BGP_ROUTE_DISTINGUISHER_SIZE,
1777 ENC_NA);
1778 proto_item_set_text(item, "Route Distinguisher: %s",
1779 decode_bgp_rd(tvb, offset));
1780 offset += BGP_ROUTE_DISTINGUISHER_SIZE;
1782 ret = decode_mcast_vpn_nlri_addresses(nlri_tree, tvb, offset);
1783 if (ret < 0)
1784 return -1;
1785 break;
1787 case MCAST_VPN_RTYPE_LEAF_AD:
1788 route_key_length = length - ip_length;
1789 item = proto_tree_add_item(nlri_tree,
1790 hf_bgp_mcast_vpn_nlri_route_key, tvb,
1791 offset, route_key_length, ENC_NA);
1792 proto_item_set_text(item, "Route Key (%u byte%s)", route_key_length,
1793 plurality(route_key_length, "", "s"));
1794 offset += route_key_length;
1796 if (afi == AFNUM_INET)
1797 proto_tree_add_item(nlri_tree,
1798 hf_bgp_mcast_vpn_nlri_origin_router_ipv4,
1799 tvb, offset, ip_length, ENC_BIG_ENDIAN);
1800 else
1801 proto_tree_add_item(nlri_tree,
1802 hf_bgp_mcast_vpn_nlri_origin_router_ipv6,
1803 tvb, offset, ip_length, ENC_NA);
1804 break;
1806 case MCAST_VPN_RTYPE_SOURCE_ACTIVE_AD:
1807 item = proto_tree_add_item(nlri_tree, hf_bgp_mcast_vpn_nlri_rd, tvb,
1808 offset, BGP_ROUTE_DISTINGUISHER_SIZE,
1809 ENC_NA);
1810 proto_item_set_text(item, "Route Distinguisher: %s",
1811 decode_bgp_rd(tvb, offset));
1812 offset += BGP_ROUTE_DISTINGUISHER_SIZE;
1814 ret = decode_mcast_vpn_nlri_addresses(nlri_tree, tvb, offset);
1815 if (ret < 0)
1816 return -1;
1817 break;
1819 case MCAST_VPN_RTYPE_SHARED_TREE_JOIN:
1820 case MCAST_VPN_RTYPE_SOURCE_TREE_JOIN:
1821 item = proto_tree_add_item(nlri_tree, hf_bgp_mcast_vpn_nlri_rd, tvb,
1822 offset, BGP_ROUTE_DISTINGUISHER_SIZE,
1823 ENC_NA);
1824 proto_item_set_text(item, "Route Distinguisher: %s",
1825 decode_bgp_rd(tvb, offset));
1826 offset += BGP_ROUTE_DISTINGUISHER_SIZE;
1828 proto_tree_add_item(nlri_tree, hf_bgp_mcast_vpn_nlri_source_as, tvb,
1829 offset, 4, ENC_NA);
1830 offset += 4;
1832 ret = decode_mcast_vpn_nlri_addresses(nlri_tree, tvb, offset);
1833 if (ret < 0)
1834 return -1;
1835 break;
1838 /* route type field (1 byte) + length field (1 byte) + length */
1839 return 2 + length;
1843 * Decodes an MDT-SAFI message.
1845 static guint
1846 decode_mdt_safi(proto_tree *tree, tvbuff_t *tvb, gint offset)
1848 const guint ip_length = 4;
1849 const guint mdt_safi_nlri_length_bits = 128;
1850 guint length; /* length in bits */
1851 gint orig_offset = offset;
1852 proto_item *item;
1854 length = tvb_get_guint8(tvb, offset);
1855 if (length != mdt_safi_nlri_length_bits)
1856 return -1;
1857 offset++;
1859 item = proto_tree_add_item(tree, hf_bgp_mdt_nlri_safi_rd, tvb,
1860 offset, BGP_ROUTE_DISTINGUISHER_SIZE, ENC_NA);
1861 proto_item_set_text(item, "Route Distinguisher: %s",
1862 decode_bgp_rd(tvb, offset));
1863 offset += BGP_ROUTE_DISTINGUISHER_SIZE;
1865 proto_tree_add_item(tree, hf_bgp_mdt_nlri_safi_ipv4_addr, tvb,
1866 offset, ip_length, ENC_BIG_ENDIAN);
1867 offset += ip_length;
1869 proto_tree_add_item(tree, hf_bgp_mdt_nlri_safi_group_addr, tvb,
1870 offset, ip_length, ENC_BIG_ENDIAN);
1871 offset += ip_length;
1873 return offset - orig_offset;
1877 * Decode an MPLS label stack
1878 * XXX - We should change *buf to **buf, use ep_alloc() and drop the buflen
1879 * argument.
1881 static guint
1882 decode_MPLS_stack(tvbuff_t *tvb, gint offset, wmem_strbuf_t *stack_strbuf)
1884 guint32 label_entry; /* an MPLS label enrty (label + COS field + stack bit */
1885 gint indx; /* index for the label stack */
1887 indx = offset ;
1888 label_entry = 0x000000 ;
1890 wmem_strbuf_truncate(stack_strbuf, 0);
1892 while ((label_entry & 0x000001) == 0) {
1894 label_entry = tvb_get_ntoh24(tvb, indx) ;
1896 /* withdrawn routes may contain 0 or 0x800000 in the first label */
1897 if((indx-offset)==0&&(label_entry==0||label_entry==0x800000)) {
1898 wmem_strbuf_append(stack_strbuf, "0 (withdrawn)");
1899 return (1);
1902 wmem_strbuf_append_printf(stack_strbuf, "%u%s", label_entry >> 4,
1903 ((label_entry & 0x000001) == 0) ? "," : " (bottom)");
1905 indx += 3 ;
1907 if ((label_entry & 0x000001) == 0) {
1908 /* real MPLS multi-label stack in BGP? - maybe later; for now, it must be a bogus packet */
1909 wmem_strbuf_append(stack_strbuf, " (BOGUS: Bottom of Stack NOT set!)");
1910 break;
1914 return((indx - offset) / 3);
1918 * Decode a multiprotocol address
1921 static int
1922 mp_addr_to_str (guint16 afi, guint8 safi, tvbuff_t *tvb, gint offset, wmem_strbuf_t *strbuf, gint nhlen)
1924 int length; /* length of the address in byte */
1925 guint32 ip4addr,ip4addr2; /* IPv4 address */
1926 guint16 rd_type; /* Route Distinguisher type */
1927 struct e_in6_addr ip6addr; /* IPv6 address */
1929 switch (afi) {
1930 case AFNUM_INET:
1931 switch (safi) {
1932 case SAFNUM_UNICAST:
1933 case SAFNUM_MULCAST:
1934 case SAFNUM_UNIMULC:
1935 case SAFNUM_MPLS_LABEL:
1936 case SAFNUM_ENCAPSULATION:
1937 case SAFNUM_ROUTE_TARGET:
1938 /* RTF NHop can be IPv4 or IPv6. They are differentiated by length of the field*/
1939 length = nhlen;
1940 if (nhlen == 4) {
1941 wmem_strbuf_append(strbuf, tvb_ip_to_str(tvb, offset));
1942 } else if (nhlen == 16) {
1943 wmem_strbuf_append(strbuf, tvb_ip6_to_str(tvb, offset));
1944 } else {
1945 wmem_strbuf_append(strbuf, "Unknown address");
1947 break;
1948 case SAFNUM_TUNNEL:
1949 length = 4 ;
1950 ip4addr = tvb_get_ipv4(tvb, offset);
1951 wmem_strbuf_append(strbuf, ip_to_str((guint8 *)&ip4addr));
1952 break;
1953 case SAFNUM_LAB_VPNUNICAST:
1954 case SAFNUM_LAB_VPNMULCAST:
1955 case SAFNUM_LAB_VPNUNIMULC:
1956 rd_type=tvb_get_ntohs(tvb,offset) ;
1957 wmem_strbuf_truncate(strbuf, 0);
1958 switch (rd_type) {
1959 case FORMAT_AS2_LOC:
1960 length = 8 + sizeof(ip4addr);
1961 ip4addr = tvb_get_ipv4(tvb, offset + 8); /* Next Hop */
1962 wmem_strbuf_append_printf(strbuf, "Empty Label Stack RD=%u:%u IPv4=%s",
1963 tvb_get_ntohs(tvb, offset + 2),
1964 tvb_get_ntohl(tvb, offset + 4),
1965 ip_to_str((guint8 *)&ip4addr));
1966 break;
1967 case FORMAT_IP_LOC:
1968 length = 8 + sizeof(ip4addr);
1969 ip4addr = tvb_get_ipv4(tvb, offset + 2); /* IP part of the RD */
1970 ip4addr2 = tvb_get_ipv4(tvb, offset + 8); /* Next Hop */
1971 wmem_strbuf_append_printf(strbuf, "Empty Label Stack RD=%s:%u IPv4=%s",
1972 ip_to_str((guint8 *)&ip4addr),
1973 tvb_get_ntohs(tvb, offset + 6),
1974 ip_to_str((guint8 *)&ip4addr2));
1975 break ;
1976 case FORMAT_AS4_LOC:
1977 length = 8 + sizeof(ip4addr);
1978 ip4addr = tvb_get_ipv4(tvb, offset + 8); /* Next Hop */
1979 wmem_strbuf_append_printf(strbuf, "Empty Label Stack RD=%u.%u:%u IPv4=%s",
1980 tvb_get_ntohs(tvb, offset + 2),
1981 tvb_get_ntohs(tvb, offset + 4),
1982 tvb_get_ntohs(tvb, offset + 6),
1983 ip_to_str((guint8 *)&ip4addr));
1984 break ;
1985 default:
1986 length = 0 ;
1987 wmem_strbuf_append_printf(strbuf, "Unknown (0x%04x) labeled VPN IPv4 address format",rd_type);
1988 break;
1989 } /* switch (rd_type) */
1990 break;
1991 default:
1992 length = 0 ;
1993 wmem_strbuf_truncate(strbuf, 0);
1994 wmem_strbuf_append_printf(strbuf, "Unknown SAFI (%u) for AFI %u", safi, afi);
1995 break;
1996 } /* switch (safi) */
1997 break;
1998 case AFNUM_INET6:
1999 wmem_strbuf_truncate(strbuf, 0);
2000 switch (safi) {
2001 case SAFNUM_UNICAST:
2002 case SAFNUM_MULCAST:
2003 case SAFNUM_UNIMULC:
2004 case SAFNUM_MPLS_LABEL:
2005 case SAFNUM_ENCAPSULATION:
2006 case SAFNUM_TUNNEL:
2007 length = 16 ;
2008 tvb_get_ipv6(tvb, offset, &ip6addr);
2009 wmem_strbuf_append_printf(strbuf, "%s", ip6_to_str(&ip6addr));
2010 break;
2011 case SAFNUM_LAB_VPNUNICAST:
2012 case SAFNUM_LAB_VPNMULCAST:
2013 case SAFNUM_LAB_VPNUNIMULC:
2014 rd_type=tvb_get_ntohs(tvb,offset) ;
2015 switch (rd_type) {
2016 case FORMAT_AS2_LOC:
2017 length = 8 + 16;
2018 tvb_get_ipv6(tvb, offset + 8, &ip6addr); /* Next Hop */
2019 wmem_strbuf_append_printf(strbuf, "Empty Label Stack RD=%u:%u IPv6=%s",
2020 tvb_get_ntohs(tvb, offset + 2),
2021 tvb_get_ntohl(tvb, offset + 4),
2022 ip6_to_str(&ip6addr));
2023 break;
2024 case FORMAT_IP_LOC:
2025 length = 8 + 16;
2026 ip4addr = tvb_get_ipv4(tvb, offset + 2); /* IP part of the RD */
2027 tvb_get_ipv6(tvb, offset + 8, &ip6addr); /* Next Hop */
2028 wmem_strbuf_append_printf(strbuf, "Empty Label Stack RD=%s:%u IPv6=%s",
2029 ip_to_str((guint8 *)&ip4addr),
2030 tvb_get_ntohs(tvb, offset + 6),
2031 ip6_to_str(&ip6addr));
2032 break ;
2033 case FORMAT_AS4_LOC:
2034 length = 8 + 16;
2035 tvb_get_ipv6(tvb, offset + 8, &ip6addr); /* Next Hop */
2036 wmem_strbuf_append_printf(strbuf, "Empty Label Stack RD=%u:%u IPv6=%s",
2037 tvb_get_ntohl(tvb, offset + 2),
2038 tvb_get_ntohs(tvb, offset + 6),
2039 ip6_to_str(&ip6addr));
2040 break ;
2041 default:
2042 length = 0 ;
2043 wmem_strbuf_append_printf(strbuf, "Unknown (0x%04x) labeled VPN IPv6 address format",rd_type);
2044 break;
2045 } /* switch (rd_type) */
2046 break;
2047 default:
2048 length = 0 ;
2049 wmem_strbuf_append_printf(strbuf, "Unknown SAFI (%u) for AFI %u", safi, afi);
2050 break;
2051 } /* switch (safi) */
2052 break;
2053 case AFNUM_L2VPN:
2054 case AFNUM_L2VPN_OLD:
2055 wmem_strbuf_truncate(strbuf, 0);
2056 switch (safi) {
2057 case SAFNUM_LAB_VPNUNICAST: /* only labeles prefixes do make sense */
2058 case SAFNUM_LAB_VPNMULCAST:
2059 case SAFNUM_LAB_VPNUNIMULC:
2060 case SAFNUM_VPLS:
2061 length = 4; /* the next-hop is simply an ipv4 addr */
2062 ip4addr = tvb_get_ipv4(tvb, offset + 0);
2063 wmem_strbuf_append_printf(strbuf, "IPv4=%s",
2064 ip_to_str((guint8 *)&ip4addr));
2065 break;
2066 default:
2067 length = 0 ;
2068 wmem_strbuf_append_printf(strbuf, "Unknown SAFI (%u) for AFI %u", safi, afi);
2069 break;
2070 } /* switch (safi) */
2071 break;
2072 default:
2073 length = 0 ;
2074 wmem_strbuf_truncate(strbuf, 0);
2075 wmem_strbuf_append_printf(strbuf, "Unknown AFI (%u) value", afi);
2076 break;
2077 } /* switch (afi) */
2078 return(length) ;
2082 * Decode a multiprotocol prefix
2084 static int
2085 decode_prefix_MP(proto_tree *tree, int hf_addr4, int hf_addr6,
2086 guint16 afi, guint8 safi, tvbuff_t *tvb, gint offset,
2087 const char *tag, packet_info *pinfo)
2089 int start_offset = offset;
2090 proto_item *ti;
2091 proto_tree *prefix_tree;
2092 int total_length; /* length of the entire item */
2093 int length; /* length of the prefix address, in bytes */
2094 guint plen; /* length of the prefix address, in bits */
2095 guint labnum; /* number of labels */
2096 guint16 tnl_id; /* Tunnel Identifier */
2097 int ce_id,labblk_off,labblk_size;
2098 union {
2099 guint8 addr_bytes[4];
2100 guint32 addr;
2101 } ip4addr, ip4addr2; /* IPv4 address */
2102 struct e_in6_addr ip6addr; /* IPv6 address */
2103 guint16 rd_type; /* Route Distinguisher type */
2104 wmem_strbuf_t *stack_strbuf; /* label stack */
2105 wmem_strbuf_t *comm_strbuf;
2107 switch (afi) {
2109 case AFNUM_INET:
2110 switch (safi) {
2112 case SAFNUM_UNICAST:
2113 case SAFNUM_MULCAST:
2114 case SAFNUM_UNIMULC:
2115 total_length = decode_prefix4(tree, NULL,hf_addr4, tvb, offset, 0, tag);
2116 if (total_length < 0)
2117 return -1;
2118 break;
2120 case SAFNUM_MPLS_LABEL:
2121 plen = tvb_get_guint8(tvb, offset);
2122 stack_strbuf = wmem_strbuf_new_label(wmem_packet_scope());
2123 labnum = decode_MPLS_stack(tvb, offset + 1, stack_strbuf);
2125 offset += (1 + labnum * 3);
2126 if (plen <= (labnum * 3*8)) {
2127 proto_tree_add_text(tree, tvb, start_offset, 1,
2128 "%s Labeled IPv4 prefix length %u invalid",
2129 tag, plen);
2130 return -1;
2132 plen -= (labnum * 3*8);
2133 length = ipv4_addr_and_mask(tvb, offset, ip4addr.addr_bytes, plen);
2134 if (length < 0) {
2135 proto_tree_add_text(tree, tvb, start_offset, 1,
2136 "%s Labeled IPv4 prefix length %u invalid",
2137 tag, plen + (labnum * 3*8));
2138 return -1;
2141 ti = proto_tree_add_text(tree, tvb, start_offset,
2142 (offset + length) - start_offset,
2143 "Label Stack=%s IPv4=%s/%u",
2144 wmem_strbuf_get_str(stack_strbuf),
2145 ip_to_str(ip4addr.addr_bytes), plen);
2146 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
2147 proto_tree_add_text(prefix_tree, tvb, start_offset, 1, "%s Prefix length: %u",
2148 tag, plen + labnum * 3 * 8);
2149 proto_tree_add_text(prefix_tree, tvb, start_offset + 1, 3 * labnum, "%s Label Stack: %s",
2150 tag, wmem_strbuf_get_str(stack_strbuf));
2151 if (hf_addr4 != -1) {
2152 proto_tree_add_ipv4(prefix_tree, hf_addr4, tvb, offset,
2153 length, ip4addr.addr);
2154 } else {
2155 proto_tree_add_text(prefix_tree, tvb, offset, length,
2156 "%s IPv4 prefix: %s",
2157 tag, ip_to_str(ip4addr.addr_bytes));
2159 total_length = (1 + labnum*3) + length;
2160 break;
2161 case SAFNUM_MCAST_VPN:
2162 total_length = decode_mcast_vpn_nlri(tree, tvb, offset, afi);
2163 if (total_length < 0)
2164 return -1;
2165 break;
2166 case SAFNUM_MDT:
2167 total_length = decode_mdt_safi(tree, tvb, offset);
2168 if (total_length < 0)
2169 return -1;
2170 break;
2171 case SAFNUM_ROUTE_TARGET:
2172 plen = tvb_get_guint8(tvb, offset);
2174 if (plen == 0) {
2175 proto_tree_add_text(tree, tvb, offset, 1,
2176 "%s Wildcard route target", tag);
2177 total_length = 1;
2178 break;
2181 if ((plen < 32) || (plen > 96)) {
2182 proto_tree_add_text(tree, tvb, offset, 1,
2183 "%s Route target length %u invalid",
2184 tag, plen);
2185 return -1;
2188 length = (plen + 7)/8;
2189 comm_strbuf = wmem_strbuf_new_label(wmem_packet_scope());
2191 switch (tvb_get_ntohs(tvb, offset + 1 + 4)) {
2192 case BGP_EXT_COM_RT_0:
2193 wmem_strbuf_append_printf(comm_strbuf, "%u:%u",
2194 tvb_get_ntohs(tvb, offset + 1 + 6),
2195 tvb_get_ntohl(tvb, offset + 1 + 8));
2196 break;
2197 case BGP_EXT_COM_RT_1:
2198 wmem_strbuf_append_printf(comm_strbuf, "%s:%u",
2199 tvb_ip_to_str(tvb, offset + 1 + 6),
2200 tvb_get_ntohs(tvb, offset + 1 + 10));
2201 break;
2202 case BGP_EXT_COM_RT_2:
2203 wmem_strbuf_append_printf(comm_strbuf, "%u:%u",
2204 tvb_get_ntohl(tvb, 6),
2205 tvb_get_ntohs(tvb, offset + 1 + 10));
2206 break;
2207 default:
2208 wmem_strbuf_append_printf(comm_strbuf, "Invalid RT type");
2209 break;
2211 ti = proto_tree_add_text(tree, tvb, offset + 1, length, "%s %u:%s/%u",
2212 tag, tvb_get_ntohl(tvb, offset + 1 + 0),
2213 wmem_strbuf_get_str(comm_strbuf),
2214 plen);
2215 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
2216 proto_tree_add_text(prefix_tree, tvb, offset, 1, "%s Prefix length: %u",
2217 tag, plen);
2218 proto_tree_add_text(prefix_tree, tvb, offset + 1, 4, "%s Originating AS: %u",
2219 tag, tvb_get_ntohl(tvb, offset + 1 + 0));
2220 proto_tree_add_text(prefix_tree, tvb, offset + 1 + 4, length - 4, "%s Community prefix: %s",
2221 tag, wmem_strbuf_get_str(comm_strbuf));
2222 total_length = 1 + length;
2223 break;
2224 case SAFNUM_ENCAPSULATION:
2225 plen = tvb_get_guint8(tvb, offset);
2226 if (plen != 32){
2227 proto_tree_add_text(tree, tvb, offset, 1,
2228 "%s IPv4 address length %u invalid",
2229 tag, plen);
2230 return -1;
2232 offset += 1;
2233 ip4addr.addr = tvb_get_ipv4(tvb, offset);
2235 proto_tree_add_text(tree, tvb, offset,
2236 offset + 4,
2237 "Endpoint Address: %s",
2238 ip_to_str((guint8 *)&ip4addr));
2240 total_length = 5; /* length(1 octet) + address(4 octets) */
2241 break;
2242 case SAFNUM_TUNNEL:
2243 plen = tvb_get_guint8(tvb, offset);
2244 if (plen <= 16){
2245 proto_tree_add_text(tree, tvb, start_offset, 1,
2246 "%s Tunnel IPv4 prefix length %u invalid",
2247 tag, plen);
2248 return -1;
2250 tnl_id = tvb_get_ntohs(tvb, offset + 1);
2251 offset += 3; /* Length + Tunnel Id */
2252 plen -= 16; /* 2-octet Identifier */
2253 length = ipv4_addr_and_mask(tvb, offset, ip4addr.addr_bytes, plen);
2254 if (length < 0) {
2255 proto_tree_add_text(tree, tvb, start_offset, 1,
2256 "%s Tunnel IPv4 prefix length %u invalid",
2257 tag, plen + 16);
2258 return -1;
2260 ti = proto_tree_add_text(tree, tvb, start_offset,
2261 (offset + length) - start_offset,
2262 "Tunnel Identifier=0x%x IPv4=%s/%u",
2263 tnl_id, ip_to_str(ip4addr.addr_bytes), plen);
2264 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
2266 proto_tree_add_text(prefix_tree, tvb, start_offset, 1, "%s Prefix length: %u",
2267 tag, plen + 16);
2268 proto_tree_add_item(prefix_tree, hf_bgp_mp_nlri_tnl_id, tvb,
2269 start_offset + 1, 2, ENC_BIG_ENDIAN);
2270 if (hf_addr4 != -1) {
2271 proto_tree_add_ipv4(prefix_tree, hf_addr4, tvb, offset,
2272 length, ip4addr.addr);
2273 } else {
2274 proto_tree_add_text(prefix_tree, tvb, offset, length,
2275 "%s IPv4 prefix: %s",
2276 tag, ip_to_str(ip4addr.addr_bytes));
2278 total_length = 1 + 2 + length; /* length field + Tunnel Id + IPv4 len */
2279 break;
2281 case SAFNUM_LAB_VPNUNICAST:
2282 case SAFNUM_LAB_VPNMULCAST:
2283 case SAFNUM_LAB_VPNUNIMULC:
2284 plen = tvb_get_guint8(tvb, offset);
2285 stack_strbuf = wmem_strbuf_new_label(wmem_packet_scope());
2286 labnum = decode_MPLS_stack(tvb, offset + 1, stack_strbuf);
2288 offset += (1 + labnum * 3);
2289 if (plen <= (labnum * 3*8)) {
2290 proto_tree_add_text(tree, tvb, start_offset, 1,
2291 "%s Labeled VPN IPv4 prefix length %u invalid",
2292 tag, plen);
2293 return -1;
2295 plen -= (labnum * 3*8);
2297 rd_type = tvb_get_ntohs(tvb, offset);
2298 if (plen < 8*8) {
2299 proto_tree_add_text(tree, tvb, start_offset, 1,
2300 "%s Labeled VPN IPv4 prefix length %u invalid",
2301 tag, plen + (labnum * 3*8));
2302 return -1;
2304 plen -= 8*8;
2306 switch (rd_type) {
2308 case FORMAT_AS2_LOC: /* Code borrowed from the decode_prefix4 function */
2309 length = ipv4_addr_and_mask(tvb, offset + 8, ip4addr.addr_bytes, plen);
2310 if (length < 0) {
2311 proto_tree_add_text(tree, tvb, start_offset, 1,
2312 "%s Labeled VPN IPv4 prefix length %u invalid",
2313 tag, plen + (labnum * 3*8) + 8*8);
2314 return -1;
2317 ti = proto_tree_add_text(tree, tvb, start_offset,
2318 (offset + 8 + length) - start_offset,
2319 "Label Stack=%s RD=%u:%u, IPv4=%s/%u",
2320 wmem_strbuf_get_str(stack_strbuf),
2321 tvb_get_ntohs(tvb, offset + 2),
2322 tvb_get_ntohl(tvb, offset + 4),
2323 ip_to_str(ip4addr.addr_bytes), plen);
2324 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
2325 proto_tree_add_text(prefix_tree, tvb, start_offset, 1, "%s Prefix length: %u",
2326 tag, plen + labnum * 3 * 8 + 8 * 8);
2327 proto_tree_add_text(prefix_tree, tvb, start_offset + 1, 3 * labnum,
2328 "%s Label Stack: %s", tag, wmem_strbuf_get_str(stack_strbuf));
2329 proto_tree_add_text(prefix_tree, tvb, start_offset + 1 + 3 * labnum, 8,
2330 "%s Route Distinguisher: %u:%u", tag, tvb_get_ntohs(tvb, offset + 2),
2331 tvb_get_ntohl(tvb, offset + 4));
2332 if (hf_addr4 != -1) {
2333 proto_tree_add_ipv4(prefix_tree, hf_addr4, tvb,
2334 offset + 8, length, ip4addr.addr);
2335 } else {
2336 proto_tree_add_text(prefix_tree, tvb, offset + 8,
2337 length, "%s IPv4 prefix: %s", tag,
2338 ip_to_str(ip4addr.addr_bytes));
2340 total_length = (1 + labnum * 3 + 8) + length;
2341 break;
2343 case FORMAT_IP_LOC: /* Code borrowed from the decode_prefix4 function */
2344 tvb_memcpy(tvb, ip4addr.addr_bytes, offset + 2, 4);
2346 length = ipv4_addr_and_mask(tvb, offset + 8, ip4addr2.addr_bytes, plen);
2347 if (length < 0) {
2348 proto_tree_add_text(tree, tvb, start_offset, 1,
2349 "%s Labeled VPN IPv4 prefix length %u invalid",
2350 tag, plen + (labnum * 3*8) + 8*8);
2351 return -1;
2354 ti = proto_tree_add_text(tree, tvb, start_offset,
2355 (offset + 8 + length) - start_offset,
2356 "Label Stack=%s RD=%s:%u, IPv4=%s/%u",
2357 wmem_strbuf_get_str(stack_strbuf),
2358 ip_to_str(ip4addr.addr_bytes),
2359 tvb_get_ntohs(tvb, offset + 6),
2360 ip_to_str(ip4addr2.addr_bytes),
2361 plen);
2362 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
2363 proto_tree_add_text(prefix_tree, tvb, start_offset, 1, "%s Prefix length: %u",
2364 tag, plen + labnum * 3 * 8 + 8 * 8);
2365 proto_tree_add_text(prefix_tree, tvb, start_offset + 1, 3 * labnum,
2366 "%s Label Stack: %s", tag, wmem_strbuf_get_str(stack_strbuf));
2367 proto_tree_add_text(prefix_tree, tvb, start_offset + 1 + 3 * labnum, 8,
2368 "%s Route Distinguisher: %s:%u", tag, ip_to_str(ip4addr.addr_bytes),
2369 tvb_get_ntohs(tvb, offset + 6));
2370 if (hf_addr4 != -1) {
2371 proto_tree_add_ipv4(prefix_tree, hf_addr4, tvb,
2372 offset + 8, length, ip4addr2.addr);
2373 } else {
2374 proto_tree_add_text(prefix_tree, tvb, offset + 8,
2375 length, "%s IPv4 prefix: %s", tag,
2376 ip_to_str(ip4addr2.addr_bytes));
2378 total_length = (1 + labnum * 3 + 8) + length;
2379 break;
2381 case FORMAT_AS4_LOC: /* Code borrowed from the decode_prefix4 function */
2382 length = ipv4_addr_and_mask(tvb, offset + 8, ip4addr.addr_bytes, plen);
2383 if (length < 0) {
2384 proto_tree_add_text(tree, tvb, start_offset, 1,
2385 "%s Labeled VPN IPv4 prefix length %u invalid",
2386 tag, plen + (labnum * 3*8) + 8*8);
2387 return -1;
2390 ti = proto_tree_add_text(tree, tvb, start_offset,
2391 (offset + 8 + length) - start_offset,
2392 "Label Stack=%s RD=%u.%u:%u, IPv4=%s/%u",
2393 wmem_strbuf_get_str(stack_strbuf),
2394 tvb_get_ntohs(tvb, offset + 2),
2395 tvb_get_ntohs(tvb, offset + 4),
2396 tvb_get_ntohs(tvb, offset + 6),
2397 ip_to_str(ip4addr.addr_bytes), plen);
2398 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
2399 proto_tree_add_text(prefix_tree, tvb, start_offset, 1, "%s Prefix length: %u",
2400 tag, plen + labnum * 3 * 8 + 8 * 8);
2401 proto_tree_add_text(prefix_tree, tvb, start_offset + 1, 3 * labnum,
2402 "%s Label Stack: %s", tag, wmem_strbuf_get_str(stack_strbuf));
2403 proto_tree_add_text(prefix_tree, tvb, start_offset + 1 + 3 * labnum, 8,
2404 "%s Route Distinguisher: %u.%u:%u", tag, tvb_get_ntohs(tvb, offset + 2),
2405 tvb_get_ntohs(tvb, offset + 4), tvb_get_ntohs(tvb, offset + 6));
2406 if (hf_addr4 != -1) {
2407 proto_tree_add_ipv4(prefix_tree, hf_addr4, tvb,
2408 offset + 8, length, ip4addr.addr);
2409 } else {
2410 proto_tree_add_text(prefix_tree, tvb, offset + 8,
2411 length, "%s IPv4 prefix: %s", tag,
2412 ip_to_str(ip4addr.addr_bytes));
2414 total_length = (1 + labnum * 3 + 8) + length;
2415 break;
2417 default:
2418 proto_tree_add_text(tree, tvb, start_offset,
2419 (offset - start_offset) + 2,
2420 "Unknown labeled VPN IPv4 address format %u", rd_type);
2421 return -1;
2422 } /* switch (rd_type) */
2423 break;
2425 case SAFNUM_FSPEC_RULE:
2426 case SAFNUM_FSPEC_VPN_RULE:
2427 total_length = decode_flowspec_nlri(tree, tvb, offset, afi, pinfo);
2428 if(total_length < 0)
2429 return(-1);
2430 total_length++;
2431 break;
2432 default:
2433 proto_tree_add_text(tree, tvb, start_offset, 0,
2434 "Unknown SAFI (%u) for AFI %u", safi, afi);
2435 return -1;
2436 } /* switch (safi) */
2437 break;
2439 case AFNUM_INET6:
2440 switch (safi) {
2442 case SAFNUM_UNICAST:
2443 case SAFNUM_MULCAST:
2444 case SAFNUM_UNIMULC:
2445 total_length = decode_prefix6(tree, hf_addr6, tvb, offset, 0, tag);
2446 if (total_length < 0)
2447 return -1;
2448 break;
2450 case SAFNUM_MPLS_LABEL:
2451 plen = tvb_get_guint8(tvb, offset);
2452 stack_strbuf = wmem_strbuf_new_label(wmem_packet_scope());
2453 labnum = decode_MPLS_stack(tvb, offset + 1, stack_strbuf);
2455 offset += (1 + labnum * 3);
2456 if (plen <= (labnum * 3*8)) {
2457 proto_tree_add_text(tree, tvb, start_offset, 1,
2458 "%s Labeled IPv6 prefix length %u invalid", tag, plen);
2459 return -1;
2461 plen -= (labnum * 3*8);
2463 length = ipv6_addr_and_mask(tvb, offset, &ip6addr, plen);
2464 if (length < 0) {
2465 proto_tree_add_text(tree, tvb, start_offset, 1,
2466 "%s Labeled IPv6 prefix length %u invalid",
2467 tag, plen + (labnum * 3*8));
2468 return -1;
2471 proto_tree_add_text(tree, tvb, start_offset,
2472 (offset + length) - start_offset,
2473 "Label Stack=%s, IPv6=%s/%u",
2474 wmem_strbuf_get_str(stack_strbuf),
2475 ip6_to_str(&ip6addr), plen);
2476 total_length = (1 + labnum * 3) + length;
2477 break;
2478 case SAFNUM_ENCAPSULATION:
2479 plen = tvb_get_guint8(tvb, offset);
2480 if (plen != 128){
2481 proto_tree_add_text(tree, tvb, offset, 1,
2482 "%s IPv6 address length %u invalid",
2483 tag, plen);
2484 return -1;
2486 offset += 1;
2487 tvb_get_ipv6(tvb, offset, &ip6addr);
2489 proto_tree_add_text(tree, tvb, offset,
2490 offset + 16,
2491 "Endpoint Address: %s",
2492 ip6_to_str(&ip6addr));
2494 total_length = 17; /* length(1 octet) + address(16 octets) */
2495 break;
2496 case SAFNUM_TUNNEL:
2497 plen = tvb_get_guint8(tvb, offset);
2498 if (plen <= 16){
2499 proto_tree_add_text(tree, tvb, start_offset, 1,
2500 "%s Tunnel IPv6 prefix length %u invalid",
2501 tag, plen);
2502 return -1;
2504 tnl_id = tvb_get_ntohs(tvb, offset + 1);
2505 offset += 3; /* Length + Tunnel Id */
2506 plen -= 16; /* 2-octet Identifier */
2507 length = ipv6_addr_and_mask(tvb, offset, &ip6addr, plen);
2508 if (length < 0) {
2509 proto_tree_add_text(tree, tvb, start_offset, 1,
2510 "%s Tunnel IPv6 prefix length %u invalid",
2511 tag, plen + 16);
2512 return -1;
2514 proto_tree_add_text(tree, tvb, start_offset,
2515 (offset + length) - start_offset,
2516 "Tunnel Identifier=0x%x IPv6=%s/%u",
2517 tnl_id, ip6_to_str(&ip6addr), plen);
2518 total_length = (1 + 2) + length; /* length field + Tunnel Id + IPv4 len */
2519 break;
2521 case SAFNUM_LAB_VPNUNICAST:
2522 case SAFNUM_LAB_VPNMULCAST:
2523 case SAFNUM_LAB_VPNUNIMULC:
2524 plen = tvb_get_guint8(tvb, offset);
2525 stack_strbuf = wmem_strbuf_new_label(wmem_packet_scope());
2526 labnum = decode_MPLS_stack(tvb, offset + 1, stack_strbuf);
2528 offset += (1 + labnum * 3);
2529 if (plen <= (labnum * 3*8)) {
2530 proto_tree_add_text(tree, tvb, start_offset, 1,
2531 "%s Labeled VPN IPv6 prefix length %u invalid", tag, plen);
2532 return -1;
2534 plen -= (labnum * 3*8);
2536 rd_type = tvb_get_ntohs(tvb,offset);
2537 if (plen < 8*8) {
2538 proto_tree_add_text(tree, tvb, start_offset, 1,
2539 "%s Labeled VPN IPv6 prefix length %u invalid",
2540 tag, plen + (labnum * 3*8));
2541 return -1;
2543 plen -= 8*8;
2545 switch (rd_type) {
2547 case FORMAT_AS2_LOC:
2548 length = ipv6_addr_and_mask(tvb, offset + 8, &ip6addr, plen);
2549 if (length < 0) {
2550 proto_tree_add_text(tree, tvb, start_offset, 1,
2551 "%s Labeled VPN IPv6 prefix length %u invalid",
2552 tag, plen + (labnum * 3*8) + 8*8);
2553 return -1;
2556 proto_tree_add_text(tree, tvb, start_offset,
2557 (offset + 8 + length) - start_offset,
2558 "Label Stack=%s RD=%u:%u, IPv6=%s/%u",
2559 wmem_strbuf_get_str(stack_strbuf),
2560 tvb_get_ntohs(tvb, offset + 2),
2561 tvb_get_ntohl(tvb, offset + 4),
2562 ip6_to_str(&ip6addr), plen);
2563 total_length = (1 + labnum * 3 + 8) + length;
2564 break;
2566 case FORMAT_IP_LOC:
2567 tvb_memcpy(tvb, ip4addr.addr_bytes, offset + 2, 4);
2569 length = ipv6_addr_and_mask(tvb, offset + 8, &ip6addr, plen);
2570 if (length < 0) {
2571 proto_tree_add_text(tree, tvb, start_offset, 1,
2572 "%s Labeled VPN IPv6 prefix length %u invalid",
2573 tag, plen + (labnum * 3*8) + 8*8);
2574 return -1;
2577 proto_tree_add_text(tree, tvb, start_offset,
2578 (offset + 8 + length) - start_offset,
2579 "Label Stack=%s RD=%s:%u, IPv6=%s/%u",
2580 wmem_strbuf_get_str(stack_strbuf),
2581 ip_to_str(ip4addr.addr_bytes),
2582 tvb_get_ntohs(tvb, offset + 6),
2583 ip6_to_str(&ip6addr), plen);
2584 total_length = (1 + labnum * 3 + 8) + length;
2585 break;
2587 case FORMAT_AS4_LOC:
2588 length = ipv6_addr_and_mask(tvb, offset + 8, &ip6addr, plen);
2589 if (length < 0) {
2590 proto_tree_add_text(tree, tvb, start_offset, 1,
2591 "%s Labeled VPN IPv6 prefix length %u invalid",
2592 tag, plen + (labnum * 3*8) + 8*8);
2593 return -1;
2596 proto_tree_add_text(tree, tvb, start_offset,
2597 (offset + 8 + length) - start_offset,
2598 "Label Stack=%s RD=%u.%u:%u, IPv6=%s/%u",
2599 wmem_strbuf_get_str(stack_strbuf),
2600 tvb_get_ntohs(tvb, offset + 2),
2601 tvb_get_ntohs(tvb, offset + 4),
2602 tvb_get_ntohs(tvb, offset + 6),
2603 ip6_to_str(&ip6addr), plen);
2604 total_length = (1 + labnum * 3 + 8) + length;
2605 break;
2606 default:
2607 proto_tree_add_text(tree, tvb, start_offset, 0,
2608 "Unknown labeled VPN IPv6 address format %u", rd_type);
2609 return -1;
2610 } /* switch (rd_type) */
2611 break;
2613 default:
2614 proto_tree_add_text(tree, tvb, start_offset, 0,
2615 "Unknown SAFI (%u) for AFI %u", safi, afi);
2616 return -1;
2617 } /* switch (safi) */
2618 break;
2620 case AFNUM_L2VPN:
2621 case AFNUM_L2VPN_OLD:
2622 switch (safi) {
2624 case SAFNUM_LAB_VPNUNICAST:
2625 case SAFNUM_LAB_VPNMULCAST:
2626 case SAFNUM_LAB_VPNUNIMULC:
2627 case SAFNUM_VPLS:
2628 plen = tvb_get_ntohs(tvb,offset);
2629 rd_type=tvb_get_ntohs(tvb,offset+2);
2631 /* RFC6074 Section 7 BGP-AD and VPLS-BGP Interoperability
2632 Both BGP-AD and VPLS-BGP [RFC4761] use the same AFI/SAFI. In order
2633 for both BGP-AD and VPLS-BGP to co-exist, the NLRI length must be
2634 used as a demultiplexer.
2636 The BGP-AD NLRI has an NLRI length of 12 bytes, containing only an
2637 8-byte RD and a 4-byte VSI-ID. VPLS-BGP [RFC4761] uses a 17-byte
2638 NLRI length. Therefore, implementations of BGP-AD must ignore NLRI
2639 that are greater than 12 bytes.
2641 if(plen == 12) /* BGP-AD */
2643 switch (rd_type) {
2645 case FORMAT_AS2_LOC:
2646 proto_tree_add_text(tree, tvb, start_offset,
2647 (offset + plen + 2) - start_offset,
2648 "RD: %u:%u, PE_addr: %s",
2649 tvb_get_ntohs(tvb, offset + 4),
2650 tvb_get_ntohl(tvb, offset + 6),
2651 tvb_ip_to_str(tvb, offset + 10));
2652 break;
2654 case FORMAT_IP_LOC:
2655 proto_tree_add_text(tree, tvb, offset,
2656 (offset + plen + 2) - start_offset,
2657 "RD: %s:%u, PE_addr: %s",
2658 tvb_ip_to_str(tvb, offset + 10),
2659 tvb_get_ntohs(tvb, offset + 8),
2660 tvb_ip_to_str(tvb, offset + 10));
2661 break;
2662 case FORMAT_AS4_LOC:
2663 proto_tree_add_text(tree, tvb, start_offset,
2664 (offset + plen + 2) - start_offset,
2665 "RD: %u.%u:%u, PE_addr: %s",
2666 tvb_get_ntohs(tvb, offset + 4),
2667 tvb_get_ntohs(tvb, offset + 6),
2668 tvb_get_ntohs(tvb, offset + 8),
2669 tvb_ip_to_str(tvb, offset + 10));
2670 break;
2671 default:
2672 proto_tree_add_text(tree, tvb, start_offset,
2673 (offset - start_offset) + 2,
2674 "Unknown labeled VPN address format %u", rd_type);
2675 return -1;
2676 } /* switch (rd_type) */
2677 }else{ /* VPLS-BGP */
2678 ce_id=tvb_get_ntohs(tvb,offset+10);
2679 labblk_off=tvb_get_ntohs(tvb,offset+12);
2680 labblk_size=tvb_get_ntohs(tvb,offset+14);
2681 stack_strbuf = wmem_strbuf_new_label(wmem_packet_scope());
2682 decode_MPLS_stack(tvb, offset + 16, stack_strbuf);
2683 switch (rd_type) {
2685 case FORMAT_AS2_LOC:
2686 tvb_memcpy(tvb, ip4addr.addr_bytes, offset + 6, 4);
2687 proto_tree_add_text(tree, tvb, start_offset,
2688 (offset + plen + 1) - start_offset,
2689 "RD: %u:%s, CE-ID: %u, Label-Block Offset: %u, "
2690 "Label-Block Size: %u Label Base %s",
2691 tvb_get_ntohs(tvb, offset + 4),
2692 ip_to_str(ip4addr.addr_bytes),
2693 ce_id,
2694 labblk_off,
2695 labblk_size,
2696 wmem_strbuf_get_str(stack_strbuf));
2697 break;
2699 case FORMAT_IP_LOC:
2700 tvb_memcpy(tvb, ip4addr.addr_bytes, offset + 4, 4);
2701 proto_tree_add_text(tree, tvb, offset,
2702 (offset + plen + 1) - start_offset,
2703 "RD: %s:%u, CE-ID: %u, Label-Block Offset: %u, "
2704 "Label-Block Size: %u, Label Base %s",
2705 ip_to_str(ip4addr.addr_bytes),
2706 tvb_get_ntohs(tvb, offset + 8),
2707 ce_id,
2708 labblk_off,
2709 labblk_size,
2710 wmem_strbuf_get_str(stack_strbuf));
2711 break;
2712 case FORMAT_AS4_LOC:
2713 proto_tree_add_text(tree, tvb, offset,
2714 (offset + plen + 1) - start_offset,
2715 "RD: %u.%u:%u, CE-ID: %u, Label-Block Offset: %u, "
2716 "Label-Block Size: %u, Label Base %s",
2717 tvb_get_ntohs(tvb, offset + 4),
2718 tvb_get_ntohs(tvb, offset + 6),
2719 tvb_get_ntohs(tvb, offset + 8),
2720 ce_id,
2721 labblk_off,
2722 labblk_size,
2723 wmem_strbuf_get_str(stack_strbuf));
2724 break;
2725 default:
2726 proto_tree_add_text(tree, tvb, start_offset,
2727 (offset - start_offset) + 2,
2728 "Unknown labeled VPN address format %u", rd_type);
2729 return -1;
2730 } /* switch (rd_type) */
2732 /* FIXME there are subTLVs left to decode ... for now lets omit them */
2733 total_length = plen+2;
2734 break;
2736 default:
2737 proto_tree_add_text(tree, tvb, start_offset, 0,
2738 "Unknown SAFI (%u) for AFI %u", safi, afi);
2739 return -1;
2740 } /* switch (safi) */
2741 break;
2743 default:
2744 proto_tree_add_text(tree, tvb, start_offset, 0,
2745 "Unknown AFI (%u) value", afi);
2746 return -1;
2747 } /* switch (afi) */
2748 return(total_length);
2752 * Dissect a BGP capability.
2754 static int
2755 dissect_bgp_capability_item(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, int offset, gboolean action)
2757 proto_tree *cap_tree;
2758 proto_item *ti;
2759 proto_item *ti_len;
2760 guint8 ctype;
2761 guint8 clen;
2763 ti = proto_tree_add_item(tree, hf_bgp_cap, tvb, offset, -1, ENC_NA);
2764 cap_tree = proto_item_add_subtree(ti, ett_bgp_cap);
2766 proto_tree_add_item(cap_tree, hf_bgp_cap_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2767 ctype = tvb_get_guint8(tvb, offset);
2768 proto_item_append_text(ti, ": %s", val_to_str(ctype, capability_vals, "Unknown capability %d"));
2769 offset += 1;
2771 ti_len = proto_tree_add_item(cap_tree, hf_bgp_cap_length, tvb, offset, 1, ENC_BIG_ENDIAN);
2772 clen = tvb_get_guint8(tvb, offset);
2773 proto_item_set_len(ti, clen+2);
2774 offset += 1;
2776 if(action){
2777 proto_tree_add_item(cap_tree, hf_bgp_cap_action, tvb, offset, 1, ENC_BIG_ENDIAN);
2778 proto_item_set_len(ti, clen+3);
2779 offset += 1;
2782 /* check the capability type */
2783 switch (ctype) {
2784 case BGP_CAPABILITY_RESERVED:
2785 if (clen != 0) {
2786 expert_add_info_format(pinfo, ti_len, &ei_bgp_cap_len_bad, "Capability length %u wrong, must be = 0", clen);
2787 proto_tree_add_item(cap_tree, hf_bgp_cap_unknown, tvb, offset, clen, ENC_NA);
2789 offset += clen;
2790 break;
2791 case BGP_CAPABILITY_MULTIPROTOCOL:
2792 if (clen != 4) {
2793 expert_add_info_format(pinfo, ti_len, &ei_bgp_cap_len_bad, "Capability length %u is wrong, must be = 4", clen);
2794 proto_tree_add_item(cap_tree, hf_bgp_cap_unknown, tvb, offset, clen, ENC_NA);
2795 offset += clen;
2797 else {
2798 /* AFI */
2799 proto_tree_add_item(cap_tree, hf_bgp_cap_mp_afi, tvb, offset, 2, ENC_BIG_ENDIAN);
2800 offset += 2;
2802 /* Reserved */
2803 proto_tree_add_item(cap_tree, hf_bgp_cap_reserved, tvb, offset, 1, ENC_NA);
2804 offset += 1;
2806 /* SAFI */
2807 proto_tree_add_item(cap_tree, hf_bgp_cap_mp_safi, tvb, offset, 1, ENC_NA);
2808 offset += 1;
2811 break;
2812 case BGP_CAPABILITY_GRACEFUL_RESTART:
2813 if ((clen < 6) && (clen != 2)) {
2814 expert_add_info_format(pinfo, ti_len, &ei_bgp_cap_len_bad, "Capability length %u too short, must be greater than 6", clen);
2815 proto_tree_add_item(cap_tree, hf_bgp_cap_unknown, tvb, offset, clen, ENC_NA);
2816 offset += clen;
2818 else {
2819 int eclen = offset + clen;
2820 proto_tree *sub_tree;
2822 if (clen == 2){
2823 expert_add_info(pinfo, ti_len, &ei_bgp_cap_gr_helper_mode_only);
2826 /* Timers */
2827 ti = proto_tree_add_item(cap_tree, hf_bgp_cap_gr_timers, tvb, offset, 2, ENC_NA);
2828 sub_tree = proto_item_add_subtree(ti, ett_bgp_cap);
2829 proto_tree_add_item(sub_tree, hf_bgp_cap_gr_timers_restart_flag, tvb, offset, 2, ENC_BIG_ENDIAN);
2830 proto_tree_add_item(sub_tree, hf_bgp_cap_gr_timers_restart_time, tvb, offset, 2, ENC_BIG_ENDIAN);
2831 offset += 2;
2834 * what follows is alist of AFI/SAFI/flag triplets
2835 * read it until the TLV ends
2837 while (offset < eclen) {
2838 /* AFI */
2839 proto_tree_add_item(cap_tree, hf_bgp_cap_gr_afi, tvb, offset, 2, ENC_BIG_ENDIAN);
2840 offset += 2;
2842 /* SAFI */
2843 proto_tree_add_item(cap_tree, hf_bgp_cap_gr_safi, tvb, offset, 1, ENC_BIG_ENDIAN);
2844 offset += 1;
2846 /* Flags */
2847 ti = proto_tree_add_item(cap_tree, hf_bgp_cap_gr_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
2848 sub_tree = proto_item_add_subtree(ti, ett_bgp_cap);
2849 proto_tree_add_item(sub_tree, hf_bgp_cap_gr_flag_pfs, tvb, offset, 1, ENC_BIG_ENDIAN);
2850 offset += 1;
2853 break;
2854 case BGP_CAPABILITY_4_OCTET_AS_NUMBER:
2855 if (clen != 4) {
2856 expert_add_info_format(pinfo, ti_len, &ei_bgp_cap_len_bad, "Capability length %u is wrong, must be = 4", clen);
2857 proto_tree_add_item(cap_tree, hf_bgp_cap_unknown, tvb, offset, clen, ENC_NA);
2858 offset += clen;
2860 else {
2861 proto_tree_add_item(cap_tree, hf_bgp_cap_4as, tvb, offset, 4, ENC_BIG_ENDIAN);
2862 offset += 4;
2864 break;
2865 case BGP_CAPABILITY_DYNAMIC_CAPABILITY:
2866 if (clen > 0) {
2867 int eclen = offset + clen;
2869 while (offset < eclen) {
2870 proto_tree_add_item(cap_tree, hf_bgp_cap_dc, tvb, offset, 1, ENC_BIG_ENDIAN);
2871 offset += 1;
2874 break;
2875 case BGP_CAPABILITY_ADDITIONAL_PATHS:
2876 if (clen != 4) {
2877 expert_add_info_format(pinfo, ti_len, &ei_bgp_cap_len_bad, "Capability length %u is wrong, must be = 4", clen);
2878 proto_tree_add_item(cap_tree, hf_bgp_cap_unknown, tvb, offset, clen, ENC_NA);
2879 offset += clen;
2881 else { /* AFI SAFI Send-receive*/
2882 /* AFI */
2883 proto_tree_add_item(cap_tree, hf_bgp_cap_ap_afi, tvb, offset, 2, ENC_BIG_ENDIAN);
2884 offset += 2;
2886 /* SAFI */
2887 proto_tree_add_item(cap_tree, hf_bgp_cap_ap_safi, tvb, offset, 1, ENC_BIG_ENDIAN);
2888 offset += 1;
2890 /* Send-Receive */
2891 proto_tree_add_item(cap_tree, hf_bgp_cap_ap_sendreceive, tvb, offset, 1, ENC_BIG_ENDIAN);
2892 offset += 1;
2895 break;
2897 case BGP_CAPABILITY_ENHANCED_ROUTE_REFRESH:
2898 case BGP_CAPABILITY_ROUTE_REFRESH_CISCO:
2899 case BGP_CAPABILITY_ROUTE_REFRESH:
2900 if (clen != 0) {
2901 expert_add_info_format(pinfo, ti_len, &ei_bgp_cap_len_bad, "Capability length %u wrong, must be = 0", clen);
2902 proto_tree_add_item(cap_tree, hf_bgp_cap_unknown, tvb, offset, clen, ENC_NA);
2904 offset += clen;
2905 break;
2906 case BGP_CAPABILITY_ORF_CISCO:
2907 case BGP_CAPABILITY_COOPERATIVE_ROUTE_FILTERING:
2908 if (clen < 6) {
2909 expert_add_info_format(pinfo, ti_len, &ei_bgp_cap_len_bad, "Capability length %u too short, must be greater than 6", clen);
2910 proto_tree_add_item(cap_tree, hf_bgp_cap_unknown, tvb, offset, clen, ENC_NA);
2911 offset += clen;
2913 else {
2914 guint8 orfnum; /* number of ORFs */
2915 int i;
2916 /* AFI */
2917 proto_tree_add_item(cap_tree, hf_bgp_cap_orf_afi, tvb, offset, 2, ENC_BIG_ENDIAN);
2918 offset += 2;
2920 /* Reserved */
2921 proto_tree_add_item(cap_tree, hf_bgp_cap_reserved, tvb, offset, 1, ENC_NA);
2922 offset += 1;
2924 /* SAFI */
2925 proto_tree_add_item(cap_tree, hf_bgp_cap_orf_safi, tvb, offset, 1, ENC_BIG_ENDIAN);
2926 offset += 1;
2928 /* Number of ORFs */
2929 orfnum = tvb_get_guint8(tvb, offset);
2930 proto_tree_add_item(cap_tree, hf_bgp_cap_orf_number, tvb, offset, 1, ENC_BIG_ENDIAN);
2931 offset += 1;
2932 for (i=0; i<orfnum; i++) {
2933 /* ORF Type */
2934 proto_tree_add_item(cap_tree, hf_bgp_cap_orf_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2935 offset += 1;
2937 /* Send/Receive */
2938 proto_tree_add_item(cap_tree, hf_bgp_cap_orf_sendreceive, tvb, offset, 1, ENC_BIG_ENDIAN);
2939 offset += 1;
2943 break;
2944 /* unknown capability */
2945 default:
2946 if (clen != 0) {
2947 proto_tree_add_item(cap_tree, hf_bgp_cap_unknown, tvb, offset, clen, ENC_NA);
2949 offset += clen;
2950 break;
2951 } /* switch (ctype) */
2952 return offset;
2956 * Dissect a BGP OPEN message.
2958 static const value_string community_vals[] = {
2959 { BGP_COMM_NO_EXPORT, "NO_EXPORT" },
2960 { BGP_COMM_NO_ADVERTISE, "NO_ADVERTISE" },
2961 { BGP_COMM_NO_EXPORT_SUBCONFED, "NO_EXPORT_SUBCONFED" },
2962 { 0, NULL }
2965 static void
2966 dissect_bgp_open(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo)
2968 guint8 optlen; /* Option Length */
2969 int ptype; /* parameter type */
2970 int plen; /* parameter length */
2971 int cend; /* capabilities end */
2972 int oend; /* options end */
2973 int offset; /* tvb offset counter */
2974 proto_item *ti; /* tree item */
2975 proto_tree *opt_tree; /* subtree for options */
2976 proto_tree *par_tree; /* subtree for par options */
2978 offset = BGP_MARKER_SIZE + 2 + 1;
2980 proto_tree_add_item(tree, hf_bgp_open_version, tvb, offset, 1, ENC_BIG_ENDIAN);
2981 offset += 1;
2983 proto_tree_add_item(tree, hf_bgp_open_myas, tvb, offset, 2, ENC_BIG_ENDIAN);
2984 offset += 2;
2986 proto_tree_add_item(tree, hf_bgp_open_holdtime, tvb, offset, 2, ENC_BIG_ENDIAN);
2987 offset += 2;
2989 proto_tree_add_item(tree, hf_bgp_open_identifier, tvb, offset, 4, ENC_NA);
2990 offset += 4;
2992 proto_tree_add_item(tree, hf_bgp_open_opt_len, tvb, offset, 1, ENC_BIG_ENDIAN);
2993 optlen = tvb_get_guint8(tvb, offset);
2994 offset += 1;
2996 /* optional parameters */
2997 if (optlen > 0) {
2998 oend = offset + optlen;
3000 /* add a subtree */
3001 ti = proto_tree_add_item(tree, hf_bgp_open_opt_params, tvb, offset, optlen, ENC_NA);
3002 opt_tree = proto_item_add_subtree(ti, ett_bgp_options);
3004 /* step through all of the optional parameters */
3005 while (offset < oend) {
3007 /* add a subtree */
3008 ti = proto_tree_add_item(opt_tree, hf_bgp_open_opt_param, tvb, offset, -1, ENC_NA);
3009 par_tree = proto_item_add_subtree(ti, ett_bgp_options);
3011 /* display and grab the type ... */
3012 proto_tree_add_item(par_tree, hf_bgp_open_opt_param_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3013 ptype = tvb_get_guint8(tvb, offset);
3014 proto_item_append_text(ti, ": %s", val_to_str(ptype, bgp_open_opt_vals, "Unknown Parameter %d"));
3015 offset += 1;
3017 /* ... and length */
3018 proto_tree_add_item(par_tree, hf_bgp_open_opt_param_len, tvb, offset, 1, ENC_BIG_ENDIAN);
3019 plen = tvb_get_guint8(tvb, offset);
3020 proto_item_set_len(ti, plen+2);
3021 offset += 1;
3023 /* check the type */
3024 switch (ptype) {
3025 case BGP_OPTION_AUTHENTICATION:
3026 proto_tree_add_item(par_tree, hf_bgp_open_opt_param_auth, tvb, offset, plen, ENC_NA);
3027 offset += plen;
3028 break;
3029 case BGP_OPTION_CAPABILITY:
3030 /* grab the capability code */
3031 cend = offset + plen;
3033 /* step through all of the capabilities */
3034 while (offset < cend) {
3035 offset = dissect_bgp_capability_item(tvb, par_tree, pinfo, offset, FALSE);
3037 break;
3038 default:
3039 proto_tree_add_item(opt_tree, hf_bgp_open_opt_param_unknown, tvb, offset, plen, ENC_NA);
3040 break;
3041 } /* switch (ptype) */
3047 * Dissect a BGP UPDATE message.
3049 static void
3050 dissect_bgp_update(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo)
3052 guint8 bgpa_flags; /* path attributes */
3053 guint8 bgpa_type;
3054 guint16 hlen; /* message length */
3055 gint o; /* packet offset */
3056 gint q; /* tmp */
3057 gint end; /* message end */
3058 guint16 ext_com; /* EXTENDED COMMUNITY extended length type */
3059 guint8 ext_com8; /* EXTENDED COMMUNITY regular type */
3060 gboolean is_regular_type; /* flag for regular types */
3061 gboolean is_extended_type; /* flag for extended types */
3062 guint16 len; /* tmp */
3063 int advance; /* tmp */
3064 proto_item *ti; /* tree item */
3065 proto_item *sub_ti; /* tree fir sub item */
3066 proto_tree *subtree; /* subtree for attributes */
3067 proto_tree *subtree2; /* subtree for attributes */
3068 proto_tree *subtree3; /* subtree for attributes */
3069 proto_tree *subtree4; /* subtree for attributes */
3070 proto_tree *subtree5; /* subtree for attributes */
3071 proto_tree *subtree6; /* subtree for attributes */
3072 proto_tree *as_paths_tree; /* subtree for AS_PATHs */
3073 proto_tree *as_path_tree; /* subtree for AS_PATH */
3074 proto_tree *as_path_segment_tree; /* subtree for AS_PATH segments */
3075 proto_tree *communities_tree; /* subtree for COMMUNITIES */
3076 proto_tree *community_tree; /* subtree for a community */
3077 proto_tree *cluster_list_tree; /* subtree for CLUSTER_LIST */
3078 int i, j; /* tmp */
3079 guint8 length; /* AS_PATH length */
3080 guint8 type; /* AS_PATH type */
3081 guint32 as_path_item; /* item in AS_PATH segment */
3082 wmem_strbuf_t *as_path_emstr = NULL; /* AS_PATH */
3083 wmem_strbuf_t *communities_emstr = NULL; /* COMMUNITIES */
3084 wmem_strbuf_t *cluster_list_emstr = NULL; /* CLUSTER_LIST */
3085 wmem_strbuf_t *junk_emstr; /* tmp */
3086 guint32 ipaddr; /* IPv4 address */
3087 guint32 aggregator_as;
3088 guint16 ssa_type; /* SSA T + Type */
3089 guint16 ssa_len; /* SSA TLV Length */
3090 guint8 ssa_v3_len; /* SSA L2TPv3 Cookie Length */
3091 gfloat linkband; /* Link bandwidth */
3092 guint16 as_num; /* Autonomous System Number */
3093 guint16 encaps_tunnel_type; /* Encapsulation Tunnel Type */
3094 guint16 encaps_tunnel_len; /* Encapsulation TLV Length */
3095 guint8 encaps_tunnel_subtype; /* Encapsulation Tunnel Sub-TLV Type */
3096 guint8 encaps_tunnel_sublen; /* Encapsulation TLV Sub-TLV Length */
3098 if (!tree)
3099 return;
3101 hlen = tvb_get_ntohs(tvb, BGP_MARKER_SIZE);
3102 o = BGP_HEADER_SIZE;
3103 junk_emstr = wmem_strbuf_new_label(wmem_packet_scope());
3105 /* check for withdrawals */
3106 len = tvb_get_ntohs(tvb, o);
3107 proto_tree_add_item(tree, hf_bgp_update_withdrawn_routes_length, tvb, o, 2, ENC_BIG_ENDIAN);
3108 o += 2;
3110 /* parse unfeasible prefixes */
3111 if (len > 0) {
3112 ti = proto_tree_add_item(tree, hf_bgp_update_withdrawn_routes, tvb, o, len, ENC_NA);
3113 subtree = proto_item_add_subtree(ti, ett_bgp_unfeas);
3114 /* parse each prefix */
3115 end = o + len;
3117 /* Heuristic to detect if IPv4 prefix are using Path Identifiers */
3118 if( detect_add_path_prefix4(tvb, o, end) ) {
3119 /* IPv4 prefixes with Path Id */
3120 while (o < end) {
3121 i = decode_path_prefix4(subtree, hf_bgp_nlri_path_id, hf_bgp_withdrawn_prefix, tvb, o,
3122 "Withdrawn route");
3123 if (i < 0)
3124 return;
3125 o += i;
3127 } else {
3128 while (o < end) {
3129 i = decode_prefix4(subtree, NULL, hf_bgp_withdrawn_prefix, tvb, o, len,
3130 "Withdrawn route");
3131 if (i < 0)
3132 return;
3133 o += i;
3138 /* check for advertisements */
3139 len = tvb_get_ntohs(tvb, o);
3140 proto_tree_add_item(tree, hf_bgp_update_total_path_attribute_length, tvb, o, 2, ENC_BIG_ENDIAN);
3142 /* path attributes */
3143 if (len > 0) {
3144 ti = proto_tree_add_item(tree, hf_bgp_update_path_attributes, tvb, o+2, len, ENC_NA);
3145 subtree = proto_item_add_subtree(ti, ett_bgp_attrs);
3146 i = 2;
3147 while (i < len) {
3148 proto_item *hidden_item;
3149 proto_item *ti_pa, *ti_flags;
3150 proto_tree *flags_tree;
3151 int off;
3152 gint k;
3153 guint16 alen, tlen, aoff, aoff_save;
3154 guint16 af;
3155 guint8 saf, snpa;
3156 guint8 nexthop_len;
3157 guint8 asn_len = 0;
3159 bgpa_flags = tvb_get_guint8(tvb, o + i);
3160 bgpa_type = tvb_get_guint8(tvb, o + i+1);
3162 /* check for the Extended Length bit */
3163 if (bgpa_flags & BGP_ATTR_FLAG_EXTENDED_LENGTH) {
3164 alen = tvb_get_ntohs(tvb, o + i + BGP_SIZE_OF_PATH_ATTRIBUTE);
3165 aoff = BGP_SIZE_OF_PATH_ATTRIBUTE+2;
3166 } else {
3167 alen = tvb_get_guint8(tvb, o + i + BGP_SIZE_OF_PATH_ATTRIBUTE);
3168 aoff = BGP_SIZE_OF_PATH_ATTRIBUTE+1;
3170 tlen = alen;
3173 ti_pa = proto_tree_add_item(subtree, hf_bgp_update_path_attribute, tvb, o + i, tlen + aoff, ENC_NA);
3174 proto_item_append_text(ti_pa, " - %s", val_to_str_const(bgpa_type, bgpattr_type, "Unknown %d"));
3176 subtree2 = proto_item_add_subtree(ti_pa, ett_bgp_attr);
3178 ti_flags = proto_tree_add_item(subtree2, hf_bgp_update_path_attribute_flags, tvb, o + i, 1, ENC_NA);
3179 flags_tree = proto_item_add_subtree(ti_flags, ett_bgp_attr_flags);
3181 /* add flag bitfield subtrees */
3182 proto_tree_add_item(flags_tree, hf_bgp_update_path_attribute_flags_optional, tvb, o + i, 1, ENC_BIG_ENDIAN);
3183 proto_tree_add_item(flags_tree, hf_bgp_update_path_attribute_flags_transitive, tvb, o + i, 1, ENC_BIG_ENDIAN);
3184 proto_tree_add_item(flags_tree, hf_bgp_update_path_attribute_flags_partial, tvb, o + i, 1, ENC_BIG_ENDIAN);
3185 proto_tree_add_item(flags_tree, hf_bgp_update_path_attribute_flags_extended_length, tvb, o + i, 1, ENC_BIG_ENDIAN);
3186 proto_item_append_text(ti_flags,"%s%s%s%s",
3187 ((bgpa_flags & BGP_ATTR_FLAG_OPTIONAL) == 0) ? ": Well-known" : ": Optional",
3188 ((bgpa_flags & BGP_ATTR_FLAG_TRANSITIVE) == 0) ? ", Non-transitive" : ", Transitive",
3189 ((bgpa_flags & BGP_ATTR_FLAG_PARTIAL) == 0) ? ", Complete" : ", Partial",
3190 ((bgpa_flags & BGP_ATTR_FLAG_EXTENDED_LENGTH) == 0) ? "" : ", Extended Length");
3192 proto_tree_add_item(subtree2, hf_bgp_update_path_attribute_type_code, tvb, o + i + 1, 1, ENC_BIG_ENDIAN);
3194 proto_tree_add_item(subtree2, hf_bgp_update_path_attribute_length, tvb, o + i + BGP_SIZE_OF_PATH_ATTRIBUTE, aoff - BGP_SIZE_OF_PATH_ATTRIBUTE, ENC_BIG_ENDIAN);
3196 /* Path Attribute Type */
3197 switch (bgpa_type) {
3198 case BGPTYPE_ORIGIN:
3199 if (tlen != 1) {
3200 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
3201 "Origin (invalid): %u byte%s", tlen,
3202 plurality(tlen, "", "s"));
3203 } else {
3204 proto_tree_add_item(subtree2, hf_bgp_update_path_attribute_origin, tvb,
3205 o + i + aoff, 1, ENC_BIG_ENDIAN);
3206 proto_item_append_text(ti_pa, ": %s", val_to_str_const(tvb_get_guint8(tvb, o + i + aoff), bgpattr_origin, "Unknown"));
3208 break;
3209 case BGPTYPE_AS_PATH:
3210 case BGPTYPE_NEW_AS_PATH:
3211 /* (o + i + aoff) =
3212 (o + current attribute + aoff bytes to first tuple) */
3213 q = o + i + aoff;
3214 end = q + tlen;
3215 /* must be freed by second switch! */
3216 /* "tlen * 11" (10 digits + space) should be a good estimate
3217 of how long the AS path string could be */
3218 if (as_path_emstr == NULL)
3219 as_path_emstr = wmem_strbuf_sized_new(wmem_packet_scope(), (tlen + 1) * 11, 0);
3220 wmem_strbuf_truncate(as_path_emstr, 0);
3222 /* estimate the length of the AS number */
3223 if (bgpa_type == BGPTYPE_NEW_AS_PATH)
3224 asn_len = 4;
3225 else {
3226 if (bgp_asn_len == 0) {
3227 guint unknown_segment_type = 0;
3228 guint asn_is_null = 0;
3229 guint d;
3230 asn_len = 2;
3231 k = q;
3232 while ((k < end) && !unknown_segment_type && !asn_is_null)
3234 type = tvb_get_guint8(tvb, k++);
3236 /* type of segment is unknown */
3237 if (type != AS_SET &&
3238 type != AS_SEQUENCE &&
3239 type != AS_CONFED_SEQUENCE &&
3240 type != AS_CONFED_SEQUENCE)
3241 unknown_segment_type = 1;
3243 length = tvb_get_guint8(tvb, k++);
3245 /* Check for invalid ASN */
3246 for (d = 0; d < length && !unknown_segment_type && !asn_is_null; d++)
3248 if(tvb_get_ntohs(tvb, k) == 0)
3249 asn_is_null = 1;
3250 k += 2;
3253 if(k != end || unknown_segment_type || asn_is_null)
3254 asn_len = 4;
3256 else {
3257 asn_len = bgp_asn_len;
3261 /* snarf each AS path */
3262 while (q < end) {
3263 const gchar *str = wmem_strbuf_get_str(as_path_emstr);
3264 type = tvb_get_guint8(tvb, q++);
3265 if (wmem_strbuf_get_len(as_path_emstr) > 1 &&
3266 str[wmem_strbuf_get_len(as_path_emstr) - 1] != ' ')
3267 wmem_strbuf_append_c(as_path_emstr, ' ');
3268 if (type == AS_SET) {
3269 wmem_strbuf_append_c(as_path_emstr, '{');
3271 else if (type == AS_CONFED_SET) {
3272 wmem_strbuf_append_c(as_path_emstr, '[');
3274 else if (type == AS_CONFED_SEQUENCE) {
3275 wmem_strbuf_append_c(as_path_emstr, '(');
3277 length = tvb_get_guint8(tvb, q++);
3279 /* snarf each value in path */
3280 for (j = 0; j < length; j++) {
3281 wmem_strbuf_append_printf(as_path_emstr, "%u%s",
3282 (asn_len == 2) ?
3283 tvb_get_ntohs(tvb, q) : tvb_get_ntohl(tvb, q),
3284 (type == AS_SET || type == AS_CONFED_SET) ?
3285 ", " : " ");
3286 q += asn_len;
3289 /* cleanup end of string */
3290 if (type == AS_SET) {
3291 wmem_strbuf_truncate(as_path_emstr, wmem_strbuf_get_len(as_path_emstr) - 2);
3292 wmem_strbuf_append_c(as_path_emstr, '}');
3294 else if (type == AS_CONFED_SET) {
3295 wmem_strbuf_truncate(as_path_emstr, wmem_strbuf_get_len(as_path_emstr) - 2);
3296 wmem_strbuf_append_c(as_path_emstr, ']');
3298 else if (type == AS_CONFED_SEQUENCE) {
3299 wmem_strbuf_truncate(as_path_emstr, wmem_strbuf_get_len(as_path_emstr) - 1);
3300 wmem_strbuf_append_c(as_path_emstr, ')');
3302 else {
3303 wmem_strbuf_truncate(as_path_emstr, wmem_strbuf_get_len(as_path_emstr) - 1);
3307 /* check for empty AS_PATH */
3308 if (tlen == 0) {
3309 wmem_strbuf_truncate(as_path_emstr, 0);
3310 wmem_strbuf_append_printf(as_path_emstr, "empty");
3313 proto_item_append_text(ti_pa, ": %s", wmem_strbuf_get_str(as_path_emstr));
3315 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
3316 "AS path: %s", wmem_strbuf_get_str(as_path_emstr));
3317 as_paths_tree = proto_item_add_subtree(ti, ett_bgp_as_paths);
3319 /* (o + i + aoff) =
3320 (o + current attribute + aoff bytes to first tuple) */
3321 q = o + i + aoff;
3322 end = q + tlen;
3324 /* snarf each AS path tuple, we have to step through each one
3325 again to make a separate subtree so we can't just reuse
3326 as_path_gstr from above */
3327 /* XXX - Can we use some g_string*() trickery instead, e.g.
3328 g_string_erase()? */
3329 while (q < end) {
3330 wmem_strbuf_truncate(as_path_emstr, 0);
3331 type = tvb_get_guint8(tvb, q++);
3332 if (type == AS_SET) {
3333 wmem_strbuf_append_c(as_path_emstr, '{');
3335 else if (type == AS_CONFED_SET) {
3336 wmem_strbuf_append_c(as_path_emstr, '[');
3338 else if (type == AS_CONFED_SEQUENCE) {
3339 wmem_strbuf_append_c(as_path_emstr, '(');
3341 length = tvb_get_guint8(tvb, q++);
3343 /* snarf each value in path */
3344 for (j = 0; j < length; j++) {
3345 wmem_strbuf_append_printf(as_path_emstr, "%u%s",
3346 (asn_len == 2) ?
3347 tvb_get_ntohs(tvb, q) : tvb_get_ntohl(tvb, q),
3348 (type == AS_SET || type == AS_CONFED_SET) ? ", " : " ");
3349 q += asn_len;
3352 /* cleanup end of string */
3353 if (type == AS_SET) {
3354 wmem_strbuf_truncate(as_path_emstr, wmem_strbuf_get_len(as_path_emstr) - 2);
3355 wmem_strbuf_append_c(as_path_emstr, '}');
3357 else if (type == AS_CONFED_SET) {
3358 wmem_strbuf_truncate(as_path_emstr, wmem_strbuf_get_len(as_path_emstr) - 2);
3359 wmem_strbuf_append_c(as_path_emstr, ']');
3361 else if (type == AS_CONFED_SEQUENCE) {
3362 wmem_strbuf_truncate(as_path_emstr, wmem_strbuf_get_len(as_path_emstr) - 1);
3363 wmem_strbuf_append_c(as_path_emstr, ')');
3365 else {
3366 wmem_strbuf_truncate(as_path_emstr, wmem_strbuf_get_len(as_path_emstr) - 1);
3369 /* length here means number of ASs, ie length * 2 bytes */
3370 ti = proto_tree_add_text(as_paths_tree, tvb,
3371 q - length * asn_len - 2,
3372 length * asn_len + 2, "AS path segment: %s",
3373 wmem_strbuf_get_str(as_path_emstr));
3374 as_path_tree = proto_item_add_subtree(ti, ett_bgp_as_paths);
3375 proto_tree_add_text(as_path_tree, tvb, q - length * asn_len - 2,
3376 1, "Path segment type: %s (%u)",
3377 val_to_str_const(type, as_segment_type, "Unknown"), type);
3378 proto_tree_add_text(as_path_tree, tvb, q - length * asn_len - 1,
3379 1, "Path segment length: %u AS%s", length,
3380 plurality(length, "", "s"));
3382 /* backup and reprint path segment value(s) only */
3383 q -= asn_len * length;
3384 ti = proto_tree_add_text(as_path_tree, tvb, q,
3385 length * asn_len, "Path segment value:");
3386 as_path_segment_tree = proto_item_add_subtree(ti,
3387 ett_bgp_as_path_segments);
3388 for (j = 0; j < length; j++) {
3389 as_path_item = (asn_len == 2) ?
3390 tvb_get_ntohs(tvb, q) : tvb_get_ntohl(tvb, q);
3391 proto_item_append_text(ti, " %u", as_path_item);
3392 hidden_item = proto_tree_add_uint(as_path_segment_tree, hf_bgp_update_path_attribute_as_path, tvb,
3393 q, asn_len, as_path_item);
3394 PROTO_ITEM_SET_HIDDEN(hidden_item);
3395 q += asn_len;
3399 break;
3400 case BGPTYPE_NEXT_HOP:
3401 if (tlen != 4) {
3402 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
3403 "Next hop (invalid): %u byte%s", tlen,
3404 plurality(tlen, "", "s"));
3405 } else {
3406 proto_tree_add_item(subtree2, hf_bgp_update_path_attribute_next_hop, tvb,
3407 o + i + aoff, 4, ENC_BIG_ENDIAN);
3408 proto_item_append_text(ti_pa, ": %s ", tvb_ip_to_str(tvb, o + i + aoff));
3410 break;
3411 case BGPTYPE_MULTI_EXIT_DISC:
3412 if (tlen != 4) {
3413 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
3414 "Multiple exit discriminator (invalid): %u byte%s",
3415 tlen, plurality(tlen, "", "s"));
3416 } else {
3417 proto_tree_add_item(subtree2, hf_bgp_update_path_attribute_multi_exit_disc, tvb,
3418 o + i + aoff, tlen, ENC_BIG_ENDIAN);
3419 proto_item_append_text(ti_pa,": %u", tvb_get_ntohl(tvb, o + i + aoff));
3421 break;
3422 case BGPTYPE_LOCAL_PREF:
3423 if (tlen != 4) {
3424 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
3425 "Local preference (invalid): %u byte%s", tlen,
3426 plurality(tlen, "", "s"));
3427 } else {
3428 proto_tree_add_item(subtree2, hf_bgp_update_path_attribute_local_pref, tvb,
3429 o + i + aoff, tlen, ENC_BIG_ENDIAN);
3430 proto_item_append_text(ti_pa, ": %u", tvb_get_ntohl(tvb, o + i + aoff));
3432 break;
3433 case BGPTYPE_ATOMIC_AGGREGATE:
3434 if (tlen != 0) {
3435 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
3436 "Atomic aggregate (invalid): %u byte%s", tlen,
3437 plurality(tlen, "", "s"));
3439 break;
3440 case BGPTYPE_AGGREGATOR:
3441 if (tlen != 6 && tlen != 8) {
3442 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
3443 "Aggregator (invalid): %u byte%s", tlen,
3444 plurality(tlen, "", "s"));
3445 break;
3447 case BGPTYPE_NEW_AGGREGATOR:
3448 if (bgpa_type == BGPTYPE_NEW_AGGREGATOR && tlen != 8)
3449 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
3450 "Aggregator (invalid): %u byte%s", tlen,
3451 plurality(tlen, "", "s"));
3452 else {
3454 asn_len = tlen - 4;
3455 aggregator_as = (asn_len == 2) ?
3456 tvb_get_ntohs(tvb, o + i + aoff) :
3457 tvb_get_ntohl(tvb, o + i + aoff);
3458 proto_tree_add_uint(subtree2, hf_bgp_update_path_attribute_aggregator_as, tvb,
3459 o + i + aoff, asn_len, aggregator_as);
3460 proto_tree_add_item(subtree2, hf_bgp_update_path_attribute_aggregator_origin, tvb,
3461 o + i + aoff + asn_len, 4, ENC_BIG_ENDIAN);
3463 proto_item_append_text(ti_pa, ": AS: %u origin: %s", aggregator_as,
3464 tvb_ip_to_str(tvb, o + i + aoff + asn_len));
3466 break;
3467 case BGPTYPE_COMMUNITIES:
3468 if (tlen % 4 != 0) {
3469 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
3470 "Communities (invalid): %u byte%s", tlen,
3471 plurality(tlen, "", "s"));
3472 break;
3475 /* (o + i + aoff) =
3476 (o + current attribute + aoff bytes to first tuple) */
3477 q = o + i + aoff;
3478 end = q + tlen;
3479 /* must be freed by second switch! */
3480 /* "tlen * 12" (5 digits, a :, 5 digits + space ) should be
3481 a good estimate of how long the communities string could
3482 be */
3483 if (communities_emstr == NULL)
3484 communities_emstr = wmem_strbuf_sized_new(wmem_packet_scope(), (tlen + 1) * 12, 0);
3485 wmem_strbuf_truncate(communities_emstr, 0);
3487 /* snarf each community */
3488 while (q < end) {
3489 /* check for well-known communities */
3490 if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_EXPORT)
3491 wmem_strbuf_append(communities_emstr, "NO_EXPORT ");
3492 else if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_ADVERTISE)
3493 wmem_strbuf_append(communities_emstr, "NO_ADVERTISE ");
3494 else if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_EXPORT_SUBCONFED)
3495 wmem_strbuf_append(communities_emstr, "NO_EXPORT_SUBCONFED ");
3496 else {
3497 wmem_strbuf_append_printf(communities_emstr, "%u:%u ",
3498 tvb_get_ntohs(tvb, q),
3499 tvb_get_ntohs(tvb, q + 2));
3501 q += 4;
3503 /* cleanup end of string */
3504 wmem_strbuf_truncate(communities_emstr, wmem_strbuf_get_len(communities_emstr) - 1);
3506 proto_item_append_text(ti_pa,": %s", wmem_strbuf_get_str(communities_emstr));
3508 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
3509 "Communities: %s", communities_emstr ?
3510 wmem_strbuf_get_str(communities_emstr) : "<none>");
3511 communities_tree = proto_item_add_subtree(ti,
3512 ett_bgp_communities);
3514 /* (o + i + aoff) =
3515 (o + current attribute + aoff bytes to first tuple) */
3516 q = o + i + aoff;
3517 end = q + tlen;
3519 /* snarf each community */
3520 while (q < end) {
3521 /* check for reserved values */
3522 guint32 community = tvb_get_ntohl(tvb, q);
3523 if ((community & 0xFFFF0000) == FOURHEX0 ||
3524 (community & 0xFFFF0000) == FOURHEXF) {
3525 proto_tree_add_text(communities_tree, tvb,
3526 q - 3 + aoff, 4,
3527 "Community: %s (0x%08x)",
3528 val_to_str_const(community, community_vals, "(reserved)"),
3529 community);
3531 else {
3532 ti = proto_tree_add_text(communities_tree, tvb,
3533 q - 3 + aoff, 4, "Community: %u:%u",
3534 tvb_get_ntohs(tvb, q), tvb_get_ntohs(tvb, q + 2));
3535 community_tree = proto_item_add_subtree(ti,
3536 ett_bgp_communities);
3537 proto_tree_add_item(community_tree, hf_bgp_update_community_as,
3538 tvb, q - 3 + aoff, 2, ENC_BIG_ENDIAN);
3539 proto_tree_add_item(community_tree, hf_bgp_update_path_attribute_community_value,
3540 tvb, q - 1 + aoff, 2, ENC_BIG_ENDIAN);
3543 q += 4;
3546 break;
3547 case BGPTYPE_ORIGINATOR_ID:
3548 if (tlen != 4) {
3549 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
3550 "Originator identifier (invalid): %u byte%s", tlen,
3551 plurality(tlen, "", "s"));
3552 } else {
3553 proto_tree_add_item(subtree2, hf_bgp_update_path_attribute_originator_id, tvb,
3554 o + i + aoff, tlen, ENC_BIG_ENDIAN);
3555 proto_item_append_text(ti_pa, ": %s ", tvb_ip_to_str(tvb, o + i + aoff));
3557 break;
3558 case BGPTYPE_MP_REACH_NLRI:
3560 * RFC 2545 specifies that there may be more than one
3561 * address in the MP_REACH_NLRI attribute in section
3562 * 3, "Constructing the Next Hop field".
3564 * Yes, RFC 2858 says you can't do that, and, yes, RFC
3565 * 2858 obsoletes RFC 2283, which says you can do that,
3566 * but that doesn't mean we shouldn't dissect packets
3567 * that conform to RFC 2283 but not RFC 2858, as some
3568 * device on the network might implement the 2283-style
3569 * BGP extensions rather than RFC 2858-style extensions.
3571 af = tvb_get_ntohs(tvb, o + i + aoff);
3572 proto_tree_add_text(subtree2, tvb, o + i + aoff, 2,
3573 "Address family: %s (%u)",
3574 val_to_str_const(af, afn_vals, "Unknown"), af);
3575 saf = tvb_get_guint8(tvb, o + i + aoff + 2) ;
3576 proto_tree_add_text(subtree2, tvb, o + i + aoff + 2, 1,
3577 "Subsequent address family identifier: %s (%u)",
3578 val_to_str_const(saf, bgpattr_nlri_safi, saf >= 134 ? "Vendor specific" : "Unknown"),
3579 saf);
3580 nexthop_len = tvb_get_guint8(tvb, o + i + aoff + 3);
3581 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff + 3,
3582 nexthop_len + 1,
3583 "Next hop network address (%d byte%s)",
3584 nexthop_len, plurality(nexthop_len, "", "s"));
3585 subtree3 = proto_item_add_subtree(ti, ett_bgp_mp_nhna);
3588 * The addresses don't contain lengths, so if we
3589 * don't understand the address family type, we
3590 * cannot parse the subsequent addresses as we
3591 * don't know how long they are.
3593 switch (af) {
3594 default:
3595 proto_tree_add_text(subtree3, tvb, o + i + aoff + 4,
3596 nexthop_len, "Unknown Address Family");
3597 break;
3599 case AFNUM_INET:
3600 case AFNUM_INET6:
3601 case AFNUM_L2VPN:
3602 case AFNUM_L2VPN_OLD:
3604 j = 0;
3605 while (j < nexthop_len) {
3606 advance = mp_addr_to_str(af, saf, tvb, o + i + aoff + 4 + j,
3607 junk_emstr, nexthop_len) ;
3608 if (advance == 0) /* catch if this is a unknown AFI type*/
3609 break;
3610 if (j + advance > nexthop_len)
3611 break;
3612 proto_tree_add_text(subtree3, tvb,o + i + aoff + 4 + j,
3613 advance, "Next hop: %s (%u)",
3614 wmem_strbuf_get_str(junk_emstr), advance);
3615 j += advance;
3617 break;
3618 } /* switch (af) */
3620 aoff_save = aoff;
3621 tlen -= nexthop_len + 4;
3622 aoff += nexthop_len + 4 ;
3624 off = 0;
3625 snpa = tvb_get_guint8(tvb, o + i + aoff);
3626 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, 1,
3627 "Subnetwork points of attachment: %u", snpa);
3628 off++;
3629 if (snpa) {
3630 subtree3 = proto_item_add_subtree(ti, ett_bgp_mp_snpa);
3631 for (/*nothing*/; snpa > 0; snpa--) {
3632 proto_tree_add_text(subtree3, tvb, o + i + aoff + off, 1,
3633 "SNPA length: %u", tvb_get_guint8(tvb, o + i + aoff + off));
3634 off++;
3635 proto_tree_add_text(subtree3, tvb, o + i + aoff + off,
3636 tvb_get_guint8(tvb, o + i + aoff + off - 1),
3637 "SNPA (%u byte%s)", tvb_get_guint8(tvb, o + i + aoff + off - 1),
3638 plurality(tvb_get_guint8(tvb, o + i + aoff + off - 1), "", "s"));
3639 off += tvb_get_guint8(tvb, o + i + aoff + off - 1);
3642 tlen -= off;
3643 aoff += off;
3645 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
3646 "Network layer reachability information (%u byte%s)",
3647 tlen, plurality(tlen, "", "s"));
3648 if (tlen) {
3649 subtree3 = proto_item_add_subtree(ti,ett_bgp_mp_reach_nlri);
3650 if (af != AFNUM_INET && af != AFNUM_INET6 && af != AFNUM_L2VPN) {
3651 proto_tree_add_text(subtree3, tvb, o + i + aoff,
3652 tlen, "Unknown Address Family");
3653 } else {
3654 while (tlen > 0) {
3655 advance = decode_prefix_MP(subtree3,
3656 hf_bgp_mp_reach_nlri_ipv4_prefix,
3658 af, saf,
3659 tvb, o + i + aoff, "MP Reach NLRI", pinfo);
3660 if (advance < 0)
3661 break;
3662 tlen -= advance;
3663 aoff += advance;
3667 aoff = aoff_save;
3668 break;
3669 case BGPTYPE_MP_UNREACH_NLRI:
3670 af = tvb_get_ntohs(tvb, o + i + aoff);
3671 proto_tree_add_text(subtree2, tvb, o + i + aoff, 2,
3672 "Address family: %s (%u)",
3673 val_to_str_const(af, afn_vals, "Unknown"), af);
3674 saf = tvb_get_guint8(tvb, o + i + aoff + 2) ;
3675 proto_tree_add_text(subtree2, tvb, o + i + aoff + 2, 1,
3676 "Subsequent address family identifier: %s (%u)",
3677 val_to_str_const(saf, bgpattr_nlri_safi, saf >= 134 ? "Vendor specific" : "Unknown"),
3678 saf);
3679 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff + 3,
3680 tlen - 3, "Withdrawn routes (%u byte%s)", tlen - 3,
3681 plurality(tlen - 3, "", "s"));
3683 aoff_save = aoff;
3684 tlen -= 3;
3685 aoff += 3;
3686 if (tlen > 0) {
3687 subtree3 = proto_item_add_subtree(ti,ett_bgp_mp_unreach_nlri);
3689 while (tlen > 0) {
3690 advance = decode_prefix_MP(subtree3,
3691 hf_bgp_mp_unreach_nlri_ipv4_prefix,
3693 af, saf,
3694 tvb, o + i + aoff, "MP Unreach NLRI", pinfo);
3695 if (advance < 0)
3696 break;
3697 tlen -= advance;
3698 aoff += advance;
3701 aoff = aoff_save;
3702 break;
3703 case BGPTYPE_CLUSTER_LIST:
3704 if (tlen % 4 != 0) {
3705 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
3706 "Cluster list (invalid): %u byte%s", tlen,
3707 plurality(tlen, "", "s"));
3708 break;
3711 /* (o + i + aoff) =
3712 (o + current attribute + aoff bytes to first tuple) */
3713 q = o + i + aoff;
3714 end = q + tlen;
3715 /* must be freed by second switch! */
3716 /* "tlen * 16" (12 digits, 3 dots + space ) should be
3717 a good estimate of how long the cluster_list string could
3718 be */
3719 if (cluster_list_emstr == NULL)
3720 cluster_list_emstr = wmem_strbuf_sized_new(wmem_packet_scope(), (tlen + 1) * 16, 0);
3721 wmem_strbuf_truncate(cluster_list_emstr, 0);
3723 /* snarf each cluster list */
3724 while (q < end) {
3725 wmem_strbuf_append_printf(cluster_list_emstr, "%s ", tvb_ip_to_str(tvb, q));
3726 q += 4;
3728 /* cleanup end of string */
3729 wmem_strbuf_truncate(cluster_list_emstr, wmem_strbuf_get_len(cluster_list_emstr) - 1);
3731 proto_item_append_text(ti_pa, ": %s", wmem_strbuf_get_str(cluster_list_emstr));
3733 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
3734 "Cluster list: %s", cluster_list_emstr ?
3735 wmem_strbuf_get_str(cluster_list_emstr) : "<none>");
3736 cluster_list_tree = proto_item_add_subtree(ti,
3737 ett_bgp_cluster_list);
3739 /* (o + i + aoff) =
3740 (o + current attribute + aoff bytes to first tuple) */
3741 q = o + i + aoff;
3742 end = q + tlen;
3744 /* snarf each cluster identifier */
3745 while (q < end) {
3746 proto_tree_add_item(cluster_list_tree, hf_bgp_update_path_attribute_cluster_list,
3747 tvb, q - 3 + aoff, 4, ENC_NA);
3748 q += 4;
3751 break;
3752 case BGPTYPE_EXTENDED_COMMUNITY:
3753 if (tlen %8 != 0) {
3754 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen, "Extended community (invalid) : %u byte%s", tlen,
3755 plurality(tlen, "", "s"));
3756 } else {
3757 q = o + i + aoff ;
3758 end = o + i + aoff + tlen ;
3759 ti = proto_tree_add_text(subtree2,tvb,q,tlen, "Carried Extended communities");
3760 subtree3 = proto_item_add_subtree(ti,ett_bgp_extended_communities);
3762 while (q < end) {
3763 ext_com8 = tvb_get_guint8(tvb,q); /* handle regular types (8 bit) */
3764 ext_com = tvb_get_ntohs(tvb,q); /* handle extended length types (16 bit) */
3765 wmem_strbuf_truncate(junk_emstr, 0);
3766 wmem_strbuf_append_printf(junk_emstr, "%s", val_to_str(ext_com8,bgpext_com8_type,"Unknown %d"));
3767 is_regular_type = FALSE;
3768 is_extended_type = FALSE;
3769 /* handle regular types (8 bit) */
3770 switch (ext_com8) {
3771 case BGP_EXT_COM_QOS_MARK_T:
3772 case BGP_EXT_COM_QOS_MARK_NT:
3773 is_regular_type = TRUE;
3774 ti = proto_tree_add_text(subtree3,tvb,q,8, "%s", wmem_strbuf_get_str(junk_emstr));
3776 subtree4 = proto_item_add_subtree(ti,ett_bgp_extended_communities);
3777 proto_tree_add_text(subtree4, tvb, q, 1,
3778 "Type: 0x%02x", tvb_get_guint8(tvb,q));
3779 ti = proto_tree_add_item(subtree4, hf_bgp_ext_com_qos_flags, tvb, q+1, 1, ENC_BIG_ENDIAN);
3780 subtree5 = proto_item_add_subtree(ti,ett_bgp_ext_com_flags);
3781 /* add flag bitfield */
3782 proto_tree_add_item(subtree5, hf_bgp_ext_com_qos_flags_remarking, tvb, q+1, 1, ENC_BIG_ENDIAN);
3783 proto_tree_add_item(subtree5, hf_bgp_ext_com_qos_flags_ignore_remarking, tvb, q+1, 1, ENC_BIG_ENDIAN);
3784 proto_tree_add_item(subtree5, hf_bgp_ext_com_qos_flags_agg_marking, tvb, q+1, 1, ENC_BIG_ENDIAN);
3786 proto_tree_add_item(subtree4, hf_bgp_ext_com_qos_set_number, tvb, q+2, 1, ENC_BIG_ENDIAN);
3787 proto_tree_add_item(subtree4, hf_bgp_ext_com_qos_tech_type, tvb, q+3, 1, ENC_BIG_ENDIAN);
3788 proto_tree_add_item(subtree4, hf_bgp_ext_com_qos_marking_o, tvb, q+4, 2, ENC_BIG_ENDIAN);
3789 proto_tree_add_item(subtree4, hf_bgp_ext_com_qos_marking_a, tvb, q+6, 1, ENC_BIG_ENDIAN);
3790 proto_tree_add_item(subtree4, hf_bgp_ext_com_qos_default_to_zero, tvb, q+7, 1, ENC_BIG_ENDIAN);
3791 break;
3792 case BGP_EXT_COM_COS_CAP_T:
3793 is_regular_type = TRUE;
3794 ti = proto_tree_add_text(subtree3,tvb,q,8, "%s", wmem_strbuf_get_str(junk_emstr));
3796 subtree4 = proto_item_add_subtree(ti,ett_bgp_extended_communities);
3797 proto_tree_add_text(subtree4, tvb, q, 1,
3798 "Type: 0x%02x", tvb_get_guint8(tvb,q));
3799 ti = proto_tree_add_item(subtree4, hf_bgp_ext_com_cos_flags, tvb, q+1, 1, ENC_BIG_ENDIAN);
3800 subtree5 = proto_item_add_subtree(ti,ett_bgp_ext_com_flags);
3801 /* add flag bitfield */
3802 proto_tree_add_item(subtree5, hf_bgp_ext_com_cos_flags_be, tvb, q+1, 1, ENC_BIG_ENDIAN);
3803 proto_tree_add_item(subtree5, hf_bgp_ext_com_cos_flags_ef, tvb, q+1, 1, ENC_BIG_ENDIAN);
3804 proto_tree_add_item(subtree5, hf_bgp_ext_com_cos_flags_af, tvb, q+1, 1, ENC_BIG_ENDIAN);
3805 proto_tree_add_item(subtree5, hf_bgp_ext_com_cos_flags_le, tvb, q+1, 1, ENC_BIG_ENDIAN);
3806 proto_tree_add_text(subtree4, tvb, q+2, 1,
3807 "Flags byte 2..7 : 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
3808 tvb_get_guint8(tvb,q+2),tvb_get_guint8(tvb,q+3),tvb_get_guint8(tvb,q+4),
3809 tvb_get_guint8(tvb,q+5),tvb_get_guint8(tvb,q+6),tvb_get_guint8(tvb,q+7));
3810 break;
3811 } /* switch (ext_com8) */
3813 if (!is_regular_type) {
3814 wmem_strbuf_truncate(junk_emstr, 0);
3815 wmem_strbuf_append_printf(junk_emstr, "%s", val_to_str(ext_com,bgpext_com_type,"Unknown %d"));
3817 /* handle extended length types (16 bit) */
3818 switch (ext_com) {
3819 case BGP_EXT_COM_RT_0:
3820 case BGP_EXT_COM_RO_0:
3821 is_extended_type = TRUE;
3822 wmem_strbuf_append_printf(junk_emstr, ": %u%s%d",
3823 tvb_get_ntohs(tvb,q+2),":",tvb_get_ntohl(tvb,q+4));
3824 proto_tree_add_text(subtree3,tvb,q,8, "%s", wmem_strbuf_get_str(junk_emstr));
3825 break ;
3826 case BGP_EXT_COM_RT_1:
3827 case BGP_EXT_COM_RO_1:
3828 is_extended_type = TRUE;
3829 ipaddr = tvb_get_ipv4(tvb,q+2);
3830 wmem_strbuf_append_printf(junk_emstr, ": %s%s%u",
3831 ip_to_str((guint8 *)&ipaddr),":",tvb_get_ntohs(tvb,q+6));
3832 proto_tree_add_text(subtree3,tvb,q,8, "%s", wmem_strbuf_get_str(junk_emstr));
3833 break;
3834 case BGP_EXT_COM_RT_2:
3835 case BGP_EXT_COM_RO_2:
3836 is_extended_type = TRUE;
3837 wmem_strbuf_append_printf(junk_emstr, ": %u.%u:%u",
3838 tvb_get_ntohs(tvb,q+2),tvb_get_ntohs(tvb,q+4) ,tvb_get_ntohs(tvb,q+6));
3839 proto_tree_add_text(subtree3,tvb,q,8, "%s", wmem_strbuf_get_str(junk_emstr));
3840 break;
3841 case BGP_EXT_COM_VPN_ORIGIN:
3842 case BGP_EXT_COM_OSPF_RID:
3843 is_extended_type = TRUE;
3844 ipaddr = tvb_get_ipv4(tvb,q+2);
3845 wmem_strbuf_append_printf(junk_emstr, ": %s", ip_to_str((guint8 *)&ipaddr));
3846 proto_tree_add_text(subtree3,tvb,q,8, "%s", wmem_strbuf_get_str(junk_emstr));
3847 break;
3848 case BGP_EXT_COM_OSPF_RTYPE:
3849 is_extended_type = TRUE;
3850 ipaddr = tvb_get_ipv4(tvb,q+2);
3851 wmem_strbuf_append_printf(junk_emstr, ": Area: %s, Type: %s", ip_to_str((guint8 *)&ipaddr),
3852 val_to_str_const(tvb_get_guint8(tvb,q+6),bgpext_ospf_rtype,"Unknown"));
3853 /* print OSPF Metric type if selected */
3854 /* always print E2 even if not external route -- receiving router should ignore */
3855 if ( (tvb_get_guint8(tvb,q+7)) & BGP_OSPF_RTYPE_METRIC_TYPE ) {
3856 wmem_strbuf_append(junk_emstr, " E2");
3857 } else if ((tvb_get_guint8(tvb,q+6)==BGP_OSPF_RTYPE_EXT) || (tvb_get_guint8(tvb,q+6)==BGP_OSPF_RTYPE_NSSA)) {
3858 wmem_strbuf_append(junk_emstr, " E1");
3859 } else {
3860 wmem_strbuf_append(junk_emstr, ", no options");
3862 proto_tree_add_text(subtree3,tvb,q,8, "%s", wmem_strbuf_get_str(junk_emstr));
3863 break;
3864 case BGP_EXT_COM_LINKBAND:
3865 is_extended_type = TRUE;
3866 as_num = tvb_get_ntohs(tvb,q+2);
3867 linkband = tvb_get_ntohieee_float(tvb,q+4);
3868 wmem_strbuf_append_printf(junk_emstr, ": ASN %u, %.3f Mbps", as_num,linkband*8/1000000);
3869 proto_tree_add_text(subtree3,tvb,q,8, "%s", wmem_strbuf_get_str(junk_emstr));
3870 break;
3871 case BGP_EXT_COM_L2INFO:
3872 is_extended_type = TRUE;
3873 ti = proto_tree_add_text(subtree3,tvb,q,8, "%s", wmem_strbuf_get_str(junk_emstr));
3875 subtree4 = proto_item_add_subtree(ti,ett_bgp_extended_communities);
3876 proto_tree_add_item(subtree4, hf_bgp_ext_com_l2_encaps,tvb,q+2, 1, ENC_BIG_ENDIAN);
3877 sub_ti = proto_tree_add_item(subtree4, hf_bgp_ext_com_l2_c_flags, tvb, q+3, 1, ENC_BIG_ENDIAN);
3878 subtree5 = proto_item_add_subtree(sub_ti, ett_bgp_ext_com_l2_flags);
3879 proto_tree_add_item(subtree5, hf_bgp_ext_com_l2_flag_d, tvb, q+3, 1, ENC_BIG_ENDIAN);
3880 proto_tree_add_item(subtree5, hf_bgp_ext_com_l2_flag_z1, tvb, q+3, 1, ENC_BIG_ENDIAN);
3881 proto_tree_add_item(subtree5, hf_bgp_ext_com_l2_flag_f, tvb, q+3, 1, ENC_BIG_ENDIAN);
3882 proto_tree_add_item(subtree5, hf_bgp_ext_com_l2_flag_z345, tvb, q+3, 1, ENC_BIG_ENDIAN);
3883 proto_tree_add_item(subtree5, hf_bgp_ext_com_l2_flag_c, tvb, q+3, 1, ENC_BIG_ENDIAN);
3884 proto_tree_add_item(subtree5, hf_bgp_ext_com_l2_flag_s, tvb, q+3, 1, ENC_BIG_ENDIAN);
3886 proto_tree_add_item(subtree4, hf_bgp_ext_com_l2_mtu, tvb, q+4, 2, ENC_BIG_ENDIAN);
3887 break;
3888 case BGP_EXT_COM_FLOW_ACT:
3889 is_extended_type = TRUE;
3890 proto_tree_add_text(subtree3,tvb,q,2,"Flow Spec Traffic Action");
3891 proto_tree_add_item(subtree3,hf_bgp_ext_com_flow_act_allset , tvb, q+2, 5, ENC_NA);
3892 proto_tree_add_item(subtree3,hf_bgp_ext_com_flow_act_samp_act,tvb,q+7,1,ENC_BIG_ENDIAN);
3893 proto_tree_add_item(subtree3,hf_bgp_ext_com_flow_act_term_act,tvb,q+7,1,ENC_BIG_ENDIAN);
3894 break;
3895 case BGP_EXT_COM_FLOW_MARK:
3896 is_extended_type = TRUE;
3897 proto_tree_add_text(subtree3,tvb,q,2,"Flow Spec Traffic Mark");
3898 break;
3899 case BGP_EXT_COM_FLOW_RATE:
3900 is_extended_type = TRUE;
3901 proto_tree_add_text(subtree3,tvb,q,2,"Flow Spec Traffic Rate Limit");
3902 /* the 2 first bytes are 2 bytes ASN or 2 least significant bytes of a 4 byte ASN */
3903 proto_tree_add_item(subtree3, hf_bgp_update_community_as,
3904 tvb, q+2, 2, ENC_BIG_ENDIAN);
3905 /* remaining 4 bytes gives traffic rate in IEEE floating point */
3906 proto_tree_add_item(subtree3, hf_bgp_ext_com_flow_rate_float,tvb,q+4,4,ENC_BIG_ENDIAN);
3907 break;
3908 case BGP_EXT_COM_FLOW_RDIR:
3909 is_extended_type = TRUE;
3910 ti = proto_tree_add_item(subtree3,hf_bgp_ext_com_flow_redir,tvb,q,8,ENC_NA);
3911 subtree4 = proto_item_add_subtree(ti, ett_bgp_extended_com_fspec_redir);
3912 proto_tree_add_text(subtree4,tvb,q,2,"Flow Spec Traffic Redirect");
3913 /* flow spec RFC doesn't allow to specify RT format, */
3914 /* decoded by default as (2 bytes):an (4 byes) */
3915 proto_tree_add_item(subtree4,hf_bgp_ext_com_flow_redir_as,tvb,q+2,2,ENC_NA);
3916 proto_tree_add_item(subtree4,hf_bgp_ext_com_flow_redir_an,tvb,q+4,4,ENC_NA);
3917 proto_item_append_text(ti," RT %u:%u",tvb_get_ntohs(tvb,q+2),tvb_get_ntohl(tvb,q+4));
3918 break;
3919 } /* switch (ext_com) */
3921 if (!is_regular_type && !is_extended_type)
3922 proto_tree_add_text(subtree3,tvb,q,8, "%s","Unknown");
3923 q = q + 8;
3926 break;
3927 case BGPTYPE_SAFI_SPECIFIC_ATTR:
3928 q = o + i + aoff;
3929 end = o + i + aoff + tlen ;
3931 while(q < end) {
3932 ssa_type = tvb_get_ntohs(tvb, q) & BGP_SSA_TYPE;
3933 ssa_len = tvb_get_ntohs(tvb, q + 2);
3935 ti = proto_tree_add_text(subtree2, tvb, q, MIN(ssa_len + 4, end - q),
3936 "%s Information",
3937 val_to_str_const(ssa_type, bgp_ssa_type, "Unknown SSA"));
3938 subtree3 = proto_item_add_subtree(ti, ett_bgp_ssa);
3940 proto_tree_add_item(subtree3, hf_bgp_ssa_t, tvb,
3941 q, 1, ENC_BIG_ENDIAN);
3942 hidden_item = proto_tree_add_item(subtree3, hf_bgp_ssa_type, tvb,
3943 q, 2, ENC_BIG_ENDIAN);
3944 PROTO_ITEM_SET_HIDDEN(hidden_item);
3945 proto_tree_add_text(subtree3, tvb, q, 2,
3946 "Type: %s", val_to_str_const(ssa_type, bgp_ssa_type, "Unknown"));
3947 if ((ssa_len == 0) || (q + ssa_len > end)) {
3948 proto_tree_add_text(subtree3, tvb, q + 2, end - q - 2,
3949 "Invalid Length of %u", ssa_len);
3950 break;
3952 proto_tree_add_item(subtree3, hf_bgp_ssa_len, tvb,
3953 q + 2, 2, ENC_BIG_ENDIAN);
3955 switch (ssa_type) {
3956 case BGP_SSA_L2TPv3:
3957 proto_tree_add_item(subtree3, hf_bgp_ssa_l2tpv3_pref, tvb,
3958 q + 4, 2, ENC_BIG_ENDIAN);
3960 ti = proto_tree_add_text(subtree3, tvb, q + 6, 1, "Flags");
3961 subtree4 = proto_item_add_subtree(ti, ett_bgp_ssa_subtree) ;
3962 proto_tree_add_item(subtree4, hf_bgp_ssa_l2tpv3_s, tvb,
3963 q + 6, 1, ENC_BIG_ENDIAN);
3964 proto_tree_add_item(subtree4, hf_bgp_ssa_l2tpv3_unused, tvb,
3965 q + 6, 1, ENC_BIG_ENDIAN);
3967 ssa_v3_len = tvb_get_guint8(tvb, q + 7);
3968 if (ssa_v3_len + 8 == ssa_len){
3969 proto_tree_add_item(subtree3, hf_bgp_ssa_l2tpv3_cookie_len, tvb,
3970 q + 7, 1, ENC_BIG_ENDIAN);
3971 } else {
3972 proto_tree_add_text(subtree3, tvb, q + 7, 1,
3973 "Invalid Cookie Length of %u", ssa_v3_len);
3974 q += ssa_len + 4; /* 4 from type and length */
3975 break;
3977 proto_tree_add_item(subtree3, hf_bgp_ssa_l2tpv3_session_id, tvb,
3978 q + 8, 4, ENC_BIG_ENDIAN);
3979 if (ssa_v3_len)
3980 proto_tree_add_item(subtree3, hf_bgp_ssa_l2tpv3_cookie, tvb,
3981 q + 12, ssa_v3_len, ENC_NA);
3982 q += ssa_len + 4; /* 4 from type and length */
3983 break;
3984 case BGP_SSA_mGRE:
3985 case BGP_SSA_IPSec:
3986 case BGP_SSA_MPLS:
3987 default:
3988 proto_tree_add_item(subtree3, hf_bgp_ssa_value, tvb,
3989 q + 4, ssa_len, ENC_NA);
3990 q += ssa_len + 4; /* 4 from type and length */
3991 break;
3992 case BGP_SSA_L2TPv3_IN_IPSec:
3993 case BGP_SSA_mGRE_IN_IPSec:
3994 /* These contain BGP_SSA_IPSec and BGP_SSA_L2TPv3/BGP_SSA_mGRE */
3995 q += 4; /* 4 from type and length */
3996 break;
3997 } /* switch (bgpa.bgpa_type) */
3999 break;
4000 case BGPTYPE_TUNNEL_ENCAPS_ATTR:
4001 q = o + i + aoff;
4002 end = o + i + aoff + tlen;
4004 ti = proto_tree_add_text(subtree2, tvb, q, tlen, "TLV Encodings");
4005 subtree3 = proto_item_add_subtree(ti, ett_bgp_tunnel_tlv);
4007 while (q < end) {
4008 encaps_tunnel_type = tvb_get_ntohs(tvb, q);
4009 encaps_tunnel_len = tvb_get_ntohs(tvb, q + 2);
4011 ti = proto_tree_add_text(subtree3, tvb, q, encaps_tunnel_len + 4, "%s (%u bytes)", val_to_str_const(encaps_tunnel_type, tunnel_type, "Unknown"), encaps_tunnel_len + 4);
4012 subtree4 = proto_item_add_subtree(ti, ett_bgp_tunnel_tlv_subtree);
4014 proto_tree_add_item(subtree4, hf_bgp_update_encaps_tunnel_tlv_type, tvb, q, 2, ENC_NA);
4015 proto_tree_add_item(subtree4, hf_bgp_update_encaps_tunnel_tlv_len, tvb, q + 2, 2, ENC_NA);
4017 ti = proto_tree_add_text(subtree4, tvb, q + 4, encaps_tunnel_len, "Sub-TLV Encodings");
4018 subtree5 = proto_item_add_subtree(ti, ett_bgp_tunnel_subtlv);
4020 q += 4;
4021 j = q + encaps_tunnel_len;
4022 while ( q < j ) {
4023 encaps_tunnel_subtype = tvb_get_guint8(tvb, q);
4024 encaps_tunnel_sublen = tvb_get_guint8(tvb, q + 1);
4026 ti = proto_tree_add_text(subtree5, tvb, q, encaps_tunnel_sublen + 2, "%s (%u bytes)", val_to_str_const(encaps_tunnel_subtype, subtlv_type, "Unknown"), encaps_tunnel_sublen + 2);
4027 subtree6 = proto_item_add_subtree(ti, ett_bgp_tunnel_tlv_subtree);
4029 proto_tree_add_item(subtree6, hf_bgp_update_encaps_tunnel_subtlv_type, tvb, q, 1, ENC_NA);
4030 proto_tree_add_item(subtree6, hf_bgp_update_encaps_tunnel_subtlv_len, tvb, q + 1, 1, ENC_NA);
4032 switch (encaps_tunnel_subtype) {
4033 case TUNNEL_SUBTLV_ENCAPSULATION:
4034 if (encaps_tunnel_type == TUNNEL_TYPE_L2TP_OVER_IP) {
4035 proto_tree_add_text(subtree6, tvb, q + 2, 4, "Session ID: %u", tvb_get_letohl(tvb, q + 2));
4036 proto_tree_add_text(subtree6, tvb, q + 6, encaps_tunnel_sublen - 4, "Cookie: %s", tvb_bytes_to_str(tvb, q + 6, encaps_tunnel_sublen - 4));
4037 } else if (encaps_tunnel_type == TUNNEL_TYPE_GRE) {
4038 proto_tree_add_text(subtree6, tvb, q + 2, encaps_tunnel_sublen, "GRE key: %x", tvb_get_letohl(tvb, q + 2));
4040 break;
4041 case TUNNEL_SUBTLV_PROTO_TYPE:
4042 proto_tree_add_text(subtree6, tvb, q + 2, encaps_tunnel_sublen, "Protocol type: %s (0x%x)", val_to_str_const(tvb_get_ntohs(tvb, q + 2), etype_vals, "Unknown"), tvb_get_ntohs(tvb, q + 2));
4043 break;
4044 case TUNNEL_SUBTLV_COLOR:
4045 proto_tree_add_text(subtree6, tvb, q + 6, encaps_tunnel_sublen - 4, "Color value: %u", tvb_get_letohl(tvb, q + 6));
4046 break;
4047 case TUNNEL_SUBTLV_LOAD_BALANCE:
4048 if (encaps_tunnel_type == TUNNEL_TYPE_L2TP_OVER_IP || encaps_tunnel_type == TUNNEL_TYPE_GRE) {
4049 proto_tree_add_text(subtree6, tvb, q + 2, encaps_tunnel_sublen, "Load-balancing block length: %u", tvb_get_ntohs(tvb, q + 2));
4051 break;
4052 default:
4053 break;
4054 } /* switch (encaps_tunnel_subtype) */
4056 q += 2 + encaps_tunnel_sublen; /* type and length + length of value */
4061 break;
4063 default:
4064 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
4065 "Unknown (%u byte%s)", tlen, plurality(tlen, "", "s"));
4066 break;
4067 } /* switch (bgpa.bgpa_type) */ /* end of second switch */
4069 i += alen + aoff;
4072 o += 2 + len;
4074 /* NLRI */
4075 len = hlen - o;
4077 /* parse prefixes */
4078 if (len > 0) {
4079 ti = proto_tree_add_item(tree, hf_bgp_update_nlri, tvb, o, len, ENC_NA);
4080 subtree = proto_item_add_subtree(ti, ett_bgp_nlri);
4081 end = o + len;
4082 /* Heuristic to detect if IPv4 prefix are using Path Identifiers */
4083 if( detect_add_path_prefix4(tvb, o, end) ) {
4084 /* IPv4 prefixes with Path Id */
4085 while (o < end) {
4086 i = decode_path_prefix4(subtree, hf_bgp_nlri_path_id, hf_bgp_nlri_prefix, tvb, o,
4087 "NLRI");
4088 if (i < 0)
4089 return;
4090 o += i;
4092 } else {
4093 /* Standard prefixes */
4094 while (o < end) {
4095 i = decode_prefix4(subtree, NULL, hf_bgp_nlri_prefix, tvb, o, 0,
4096 "NLRI");
4097 if (i < 0)
4098 return;
4099 o += i;
4107 * Dissect a BGP NOTIFICATION message.
4109 static void
4110 dissect_bgp_notification(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo)
4112 int hlen; /* message length */
4113 int offset;
4114 guint major_error;
4115 proto_item *ti;
4117 hlen = tvb_get_ntohs(tvb, BGP_MARKER_SIZE);
4118 offset = BGP_MARKER_SIZE + 2 + 1;
4121 /* print error code */
4122 proto_tree_add_item(tree, hf_bgp_notify_major_error, tvb, offset, 1, ENC_NA);
4123 major_error = tvb_get_guint8(tvb, offset);
4124 offset += 1;
4126 switch(major_error){
4127 case BGP_MAJOR_ERROR_MSG_HDR:
4128 proto_tree_add_item(tree, hf_bgp_notify_minor_msg_hdr, tvb, offset, 1, ENC_NA);
4129 break;
4130 case BGP_MAJOR_ERROR_OPEN_MSG:
4131 proto_tree_add_item(tree, hf_bgp_notify_minor_open_msg, tvb, offset, 1, ENC_NA);
4132 break;
4133 case BGP_MAJOR_ERROR_UPDATE_MSG:
4134 proto_tree_add_item(tree,hf_bgp_notify_minor_update_msg, tvb, offset, 1, ENC_NA);
4135 break;
4136 case BGP_MAJOR_ERROR_HT_EXPIRED:
4137 proto_tree_add_item(tree, hf_bgp_notify_minor_ht_expired, tvb, offset, 1, ENC_NA);
4138 break;
4139 case BGP_MAJOR_ERROR_STATE_MACHINE:
4140 proto_tree_add_item(tree, hf_bgp_notify_minor_state_machine, tvb, offset, 1, ENC_NA);
4141 break;
4142 case BGP_MAJOR_ERROR_CEASE:
4143 proto_tree_add_item(tree, hf_bgp_notify_minor_cease, tvb, offset, 1, ENC_NA);
4144 break;
4145 case BGP_MAJOR_ERROR_CAP_MSG:
4146 proto_tree_add_item(tree, hf_bgp_notify_minor_cap_msg, tvb, offset, 1, ENC_NA);
4147 break;
4148 default:
4149 ti = proto_tree_add_item(tree, hf_bgp_notify_minor_unknown, tvb, offset, 1, ENC_NA);
4150 expert_add_info_format(pinfo, ti, &ei_bgp_notify_minor_unknown, "Unknown notification error (%d)",major_error);
4151 break;
4153 offset += 1;
4155 /* only print if there is optional data */
4156 if (hlen > BGP_MIN_NOTIFICATION_MSG_SIZE) {
4157 proto_tree_add_item(tree, hf_bgp_notify_data, tvb, offset, hlen - BGP_MIN_NOTIFICATION_MSG_SIZE, ENC_NA);
4162 * Dissect a BGP ROUTE-REFRESH message.
4164 static void
4165 dissect_bgp_route_refresh(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo)
4167 int p; /* tvb offset counter */
4168 int pend; /* end of list of entries for one orf type */
4169 guint16 hlen; /* tvb RR msg length */
4170 proto_item *ti; /* tree item */
4171 proto_item *ti1; /* tree item */
4172 proto_tree *subtree; /* tree for orf */
4173 proto_tree *subtree1; /* tree for orf entry */
4174 guint8 orftype; /* ORF Type */
4175 guint16 orflen; /* ORF len */
4176 guint8 entryflag; /* ORF Entry flag: action(add,del,delall) match(permit,deny) */
4177 int entrylen; /* ORF Entry length */
4178 int advance; /* tmp */
4182 example 1
4183 00 1c 05 hlen=28
4184 00 01 00 01 afi,safi= ipv4-unicast
4185 02 80 00 01 defer, prefix-orf, len=1
4186 80 removeall
4187 example 2
4188 00 25 05 hlen=37
4189 00 01 00 01 afi,saif= ipv4-unicast
4190 01 80 00 0a immediate, prefix-orf, len=10
4191 00 add
4192 00 00 00 05 seqno = 5
4193 12 ge = 18
4194 18 le = 24
4195 10 07 02 prefix = 7.2.0.0/16
4197 if (!tree)
4198 return;
4200 hlen = tvb_get_ntohs(tvb, BGP_MARKER_SIZE);
4201 p = BGP_HEADER_SIZE;
4203 /* AFI */
4204 proto_tree_add_item(tree, hf_bgp_route_refresh_afi, tvb, p, 2, ENC_BIG_ENDIAN);
4205 p += 2;
4207 /* Subtype in draft-ietf-idr-bgp-enhanced-route-refresh-02 (for Enhanced Route Refresh Capability) before Reserved*/
4208 proto_tree_add_item(tree, hf_bgp_route_refresh_subtype, tvb, p, 1, ENC_BIG_ENDIAN);
4209 p++;
4211 /* SAFI */
4212 proto_tree_add_item(tree, hf_bgp_route_refresh_safi, tvb, p, 1, ENC_BIG_ENDIAN);
4213 p++;
4215 if ( hlen == BGP_HEADER_SIZE + 4 )
4216 return;
4217 while (p < hlen) {
4218 /* ORF type */
4220 ti = proto_tree_add_item(tree, hf_bgp_route_refresh_orf, tvb, p, 4, ENC_NA);
4221 subtree = proto_item_add_subtree(ti, ett_bgp_orf);
4223 proto_tree_add_item(subtree, hf_bgp_route_refresh_orf_flag, tvb, p, 1, ENC_BIG_ENDIAN);
4224 p += 1;
4226 ti1 = proto_tree_add_item(subtree, hf_bgp_route_refresh_orf_type, tvb, p , 1, ENC_BIG_ENDIAN);
4227 orftype = tvb_get_guint8(tvb, p);
4228 p += 1;
4230 proto_tree_add_item(subtree, hf_bgp_route_refresh_orf_length, tvb, p , 2, ENC_BIG_ENDIAN);
4231 orflen = tvb_get_ntohs(tvb, p);
4232 proto_item_set_len(ti, orflen + 4);
4233 p += 2;
4235 if (orftype != BGP_ORF_PREFIX_CISCO) {
4236 expert_add_info_format(pinfo, ti1, &ei_bgp_route_refresh_orf_type_unknown, "ORFEntry-Unknown (type %u)", orftype);
4237 p += orflen;
4238 continue;
4240 pend = p + orflen;
4241 while (p < pend) {
4243 ti1 = proto_tree_add_item(subtree, hf_bgp_route_refresh_orf_entry_prefixlist, tvb, p, 1, ENC_NA);
4244 subtree1 = proto_item_add_subtree(ti1, ett_bgp_orf_entry);
4245 proto_tree_add_item(subtree1, hf_bgp_route_refresh_orf_entry_action, tvb, p, 1, ENC_BIG_ENDIAN);
4246 entryflag = tvb_get_guint8(tvb, p);
4247 if (((entryflag & BGP_ORF_ACTION) >> 6) == BGP_ORF_REMOVEALL) {
4248 p++;
4249 continue;
4251 proto_tree_add_item(subtree1, hf_bgp_route_refresh_orf_entry_match, tvb, p, 1, ENC_BIG_ENDIAN);
4252 p++;
4254 proto_tree_add_item(subtree1, hf_bgp_route_refresh_orf_entry_sequence, tvb, p, 4, ENC_BIG_ENDIAN);
4255 p +=4;
4257 proto_tree_add_item(subtree1, hf_bgp_route_refresh_orf_entry_prefixmask_lower, tvb, p, 1, ENC_BIG_ENDIAN);
4258 p++;
4260 proto_tree_add_item(subtree1, hf_bgp_route_refresh_orf_entry_prefixmask_upper, tvb, p, 1, ENC_BIG_ENDIAN);
4261 p++;
4263 advance = decode_prefix4(subtree1, NULL, -1, tvb, p, 0, "ORF");
4264 if (advance < 0)
4265 break;
4266 entrylen = 7 + 1 + advance;
4268 proto_item_set_len(ti1, entrylen);
4269 p += advance;
4276 * Dissect a BGP CAPABILITY message.
4278 static void
4279 dissect_bgp_capability(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo)
4281 int offset = 0;
4282 int mend;
4284 mend = offset + tvb_get_ntohs(tvb, offset + BGP_MARKER_SIZE);
4285 offset += BGP_HEADER_SIZE;
4286 /* step through all of the capabilities */
4287 while (offset < mend) {
4288 offset = dissect_bgp_capability_item(tvb, tree, pinfo, offset, TRUE);
4292 static void
4293 dissect_bgp_pdu(tvbuff_t *volatile tvb, packet_info *pinfo, proto_tree *tree,
4294 gboolean first)
4296 guint16 bgp_len; /* Message length */
4297 guint8 bgp_type; /* Message type */
4298 const char *typ; /* Message type (string) */
4299 proto_item *ti_len = NULL; /* length item */
4300 proto_tree *bgp_tree = NULL; /* BGP packet tree */
4302 bgp_len = tvb_get_ntohs(tvb, BGP_MARKER_SIZE);
4303 bgp_type = tvb_get_guint8(tvb, BGP_MARKER_SIZE + 2);
4304 typ = val_to_str(bgp_type, bgptypevals, "Unknown message type (0x%02x)");
4306 if (first)
4307 col_add_str(pinfo->cinfo, COL_INFO, typ);
4308 else
4309 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", typ);
4311 if (tree) {
4312 proto_item *ti;
4313 ti = proto_tree_add_item(tree, proto_bgp, tvb, 0, -1, ENC_NA);
4314 proto_item_append_text(ti, " - %s", typ);
4316 /* add a different tree for each message type */
4317 switch (bgp_type) {
4318 case BGP_OPEN:
4319 bgp_tree = proto_item_add_subtree(ti, ett_bgp_open);
4320 break;
4321 case BGP_UPDATE:
4322 bgp_tree = proto_item_add_subtree(ti, ett_bgp_update);
4323 break;
4324 case BGP_NOTIFICATION:
4325 bgp_tree = proto_item_add_subtree(ti, ett_bgp_notification);
4326 break;
4327 case BGP_KEEPALIVE:
4328 bgp_tree = proto_item_add_subtree(ti, ett_bgp);
4329 break;
4330 case BGP_ROUTE_REFRESH_CISCO:
4331 case BGP_ROUTE_REFRESH:
4332 bgp_tree = proto_item_add_subtree(ti, ett_bgp_route_refresh);
4333 break;
4334 case BGP_CAPABILITY:
4335 bgp_tree = proto_item_add_subtree(ti, ett_bgp_capability);
4336 break;
4337 default:
4338 bgp_tree = proto_item_add_subtree(ti, ett_bgp);
4339 break;
4342 proto_tree_add_item(bgp_tree, hf_bgp_marker, tvb, 0, 16, ENC_NA);
4344 ti_len = proto_tree_add_item(bgp_tree, hf_bgp_length, tvb, 16, 2, ENC_BIG_ENDIAN);
4347 if (bgp_len < BGP_HEADER_SIZE || bgp_len > BGP_MAX_PACKET_SIZE) {
4348 expert_add_info_format(pinfo, ti_len, &ei_bgp_length_invalid, "Length is invalid %u", bgp_len);
4349 return;
4352 proto_tree_add_item(bgp_tree, hf_bgp_type, tvb, 16 + 2, 1, ENC_BIG_ENDIAN);
4354 switch (bgp_type) {
4355 case BGP_OPEN:
4356 dissect_bgp_open(tvb, bgp_tree, pinfo);
4357 break;
4358 case BGP_UPDATE:
4359 dissect_bgp_update(tvb, bgp_tree, pinfo);
4360 break;
4361 case BGP_NOTIFICATION:
4362 dissect_bgp_notification(tvb, bgp_tree, pinfo);
4363 break;
4364 case BGP_KEEPALIVE:
4365 /* no data in KEEPALIVE messages */
4366 break;
4367 case BGP_ROUTE_REFRESH_CISCO:
4368 case BGP_ROUTE_REFRESH:
4369 dissect_bgp_route_refresh(tvb, bgp_tree, pinfo);
4370 break;
4371 case BGP_CAPABILITY:
4372 dissect_bgp_capability(tvb, bgp_tree, pinfo);
4373 break;
4374 default:
4375 break;
4380 * Dissect a BGP packet.
4382 static void
4383 dissect_bgp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4385 volatile int offset = 0; /* offset into the tvbuff */
4386 gint reported_length_remaining;
4387 guint8 bgp_marker[BGP_MARKER_SIZE]; /* Marker (should be all ones */
4388 static guchar marker[] = { /* BGP message marker */
4389 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
4390 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
4392 proto_item *ti; /* tree item */
4393 proto_tree *bgp_tree; /* BGP packet tree */
4394 guint16 bgp_len; /* Message length */
4395 int offset_before;
4396 guint length_remaining;
4397 guint length;
4398 volatile gboolean first = TRUE; /* TRUE for the first BGP message in packet */
4399 tvbuff_t *volatile next_tvb;
4400 void *pd_save;
4402 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BGP");
4403 col_clear(pinfo->cinfo, COL_INFO);
4406 * Scan through the TCP payload looking for a BGP marker.
4408 while ((reported_length_remaining = tvb_reported_length_remaining(tvb, offset))
4409 > 0) {
4411 * "reported_length_remaining" is the number of bytes of TCP payload
4412 * remaining. If it's more than the length of a BGP marker,
4413 * we check only the number of bytes in a BGP marker.
4415 if (reported_length_remaining > BGP_MARKER_SIZE)
4416 reported_length_remaining = BGP_MARKER_SIZE;
4419 * OK, is there a BGP marker starting at the specified offset -
4420 * or, at least, the beginning of a BGP marker running to the end
4421 * of the TCP payload?
4423 * This will throw an exception if the frame is short; that's what
4424 * we want.
4426 tvb_memcpy(tvb, bgp_marker, offset, reported_length_remaining);
4427 if (memcmp(bgp_marker, marker, reported_length_remaining) == 0) {
4429 * Yes - stop scanning and start processing BGP packets.
4431 break;
4435 * No - keep scanning through the tvbuff to try to find a marker.
4437 offset++;
4441 * If we skipped any bytes, mark it as a BGP continuation.
4443 if (offset > 0) {
4444 ti = proto_tree_add_item(tree, proto_bgp, tvb, 0, -1, ENC_NA);
4445 bgp_tree = proto_item_add_subtree(ti, ett_bgp);
4447 proto_tree_add_text(bgp_tree, tvb, 0, offset, "Continuation");
4451 * Now process the BGP packets in the TCP payload.
4453 * XXX - perhaps "tcp_dissect_pdus()" should take a starting
4454 * offset, in which case we can replace the loop below with
4455 * a call to "tcp_dissect_pdus()".
4457 while (tvb_reported_length_remaining(tvb, offset) > 0) {
4459 * This will throw an exception if we don't have any data left.
4460 * That's what we want. (See "tcp_dissect_pdus()", which is
4461 * similar.)
4463 length_remaining = tvb_ensure_length_remaining(tvb, offset);
4466 * Can we do reassembly?
4468 if (bgp_desegment && pinfo->can_desegment) {
4470 * Yes - would a BGP header starting at this offset be split
4471 * across segment boundaries?
4473 if (length_remaining < BGP_HEADER_SIZE) {
4475 * Yes. Tell the TCP dissector where the data for this message
4476 * starts in the data it handed us and that we need "some more
4477 * data." Don't tell it exactly how many bytes we need because
4478 * if/when we ask for even more (after the header) that will
4479 * break reassembly.
4481 pinfo->desegment_offset = offset;
4482 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
4483 return;
4488 * Get the length and type from the BGP header.
4490 bgp_len = tvb_get_ntohs(tvb, offset + BGP_MARKER_SIZE);
4491 if (bgp_len < BGP_HEADER_SIZE) {
4493 * The BGP length doesn't include the BGP header; report that
4494 * as an error.
4496 show_reported_bounds_error(tvb, pinfo, tree);
4497 return;
4501 * Can we do reassembly?
4503 if (bgp_desegment && pinfo->can_desegment) {
4505 * Yes - is the PDU split across segment boundaries?
4507 if (length_remaining < bgp_len) {
4509 * Yes. Tell the TCP dissector where the data for this
4510 * message starts in the data it handed us, and how many
4511 * more bytes we need, and return.
4513 pinfo->desegment_offset = offset;
4514 pinfo->desegment_len = bgp_len - length_remaining;
4515 return;
4520 * Construct a tvbuff containing the amount of the payload we have
4521 * available. Make its reported length the amount of data in the PDU.
4523 * XXX - if reassembly isn't enabled. the subdissector will throw a
4524 * BoundsError exception, rather than a ReportedBoundsError exception.
4525 * We really want a tvbuff where the length is "length", the reported
4526 * length is "plen", and the "if the snapshot length were infinite"
4527 * length is the minimum of the reported length of the tvbuff handed
4528 * to us and "plen", with a new type of exception thrown if the offset
4529 * is within the reported length but beyond that third length, with
4530 * that exception getting the "Unreassembled Packet" error.
4532 length = length_remaining;
4533 if (length > bgp_len)
4534 length = bgp_len;
4535 next_tvb = tvb_new_subset(tvb, offset, length, bgp_len);
4538 * Dissect the PDU.
4540 * If it gets an error that means there's no point in
4541 * dissecting any more PDUs, rethrow the exception in
4542 * question.
4544 * If it gets any other error, report it and continue, as that
4545 * means that PDU got an error, but that doesn't mean we should
4546 * stop dissecting PDUs within this frame or chunk of reassembled
4547 * data.
4549 pd_save = pinfo->private_data;
4550 TRY {
4551 dissect_bgp_pdu(next_tvb, pinfo, tree, first);
4553 CATCH_NONFATAL_ERRORS {
4554 /* Restore the private_data structure in case one of the
4555 * called dissectors modified it (and, due to the exception,
4556 * was unable to restore it).
4558 pinfo->private_data = pd_save;
4559 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
4561 ENDTRY;
4563 first = FALSE;
4566 * Step to the next PDU.
4567 * Make sure we don't overflow.
4569 offset_before = offset;
4570 offset += bgp_len;
4571 if (offset <= offset_before)
4572 break;
4577 * Register ourselves.
4579 void
4580 proto_register_bgp(void)
4583 static hf_register_info hf[] = {
4584 /* BGP Header */
4585 { &hf_bgp_marker,
4586 { "Marker", "bgp.marker", FT_BYTES, BASE_NONE,
4587 NULL, 0x0, "Must be set to all ones (16 Bytes)", HFILL }},
4588 { &hf_bgp_length,
4589 { "Length", "bgp.length", FT_UINT16, BASE_DEC,
4590 NULL, 0x0, "The total length of the message, including the header in octets", HFILL }},
4591 { &hf_bgp_type,
4592 { "Type", "bgp.type", FT_UINT8, BASE_DEC,
4593 VALS(bgptypevals), 0x0, "BGP message type", HFILL }},
4594 /* Open Message */
4595 { &hf_bgp_open_version,
4596 { "Version", "bgp.open.version", FT_UINT8, BASE_DEC,
4597 NULL, 0x0, "The protocol version number", HFILL }},
4598 { &hf_bgp_open_myas,
4599 { "My AS", "bgp.open.myas", FT_UINT16, BASE_DEC,
4600 NULL, 0x0, "The Autonomous System number of the sender", HFILL }},
4601 { &hf_bgp_open_holdtime,
4602 { "Hold Time", "bgp.open.holdtime", FT_UINT16, BASE_DEC,
4603 NULL, 0x0, "The number of seconds the sender proposes for Hold Time", HFILL }},
4604 { &hf_bgp_open_identifier,
4605 { "BGP Identifier", "bgp.open.identifier", FT_IPv4, BASE_NONE,
4606 NULL, 0x0, "The BGP Identifier of the sender", HFILL }},
4607 { &hf_bgp_open_opt_len,
4608 { "Optional Parameters Length", "bgp.open.opt.len", FT_UINT8, BASE_DEC,
4609 NULL, 0x0, "The total length of the Optional Parameters field in octets", HFILL }},
4610 { &hf_bgp_open_opt_params,
4611 { "Optional Parameters", "bgp.open.opt", FT_NONE, BASE_NONE,
4612 NULL, 0x0, "List of optional parameters", HFILL }},
4613 { &hf_bgp_open_opt_param,
4614 { "Optional Parameter", "bgp.open.opt.param", FT_NONE, BASE_NONE,
4615 NULL, 0x0, NULL, HFILL }},
4616 { &hf_bgp_open_opt_param_type,
4617 { "Parameter Type", "bgp.open.opt.param.type", FT_UINT8, BASE_DEC,
4618 VALS(bgp_open_opt_vals), 0x0, "Unambiguously identifies individual parameters", HFILL }},
4619 { &hf_bgp_open_opt_param_len,
4620 { "Parameter Length", "bgp.open.opt.param.len", FT_UINT8, BASE_DEC,
4621 NULL, 0x0, "Length of the Parameter Value", HFILL }},
4622 { &hf_bgp_open_opt_param_auth,
4623 { "Authentication Data", "bgp.open.opt.param.auth", FT_BYTES, BASE_NONE,
4624 NULL, 0x0, "Deprecated", HFILL }},
4625 { &hf_bgp_open_opt_param_unknown,
4626 { "Unknown", "bgp.open.opt.param.unknown", FT_BYTES, BASE_NONE,
4627 NULL, 0x0, "Unknown Parameter", HFILL }},
4628 /* Notification error */
4629 { &hf_bgp_notify_major_error,
4630 { "Major error Code", "bgp.notify.major_error", FT_UINT8, BASE_DEC,
4631 VALS(bgpnotify_major), 0x0, NULL, HFILL }},
4632 { &hf_bgp_notify_minor_msg_hdr,
4633 { "Minor error Code (Message Header)", "bgp.notify.minor_error", FT_UINT8, BASE_DEC,
4634 VALS(bgpnotify_minor_msg_hdr), 0x0, NULL, HFILL }},
4635 { &hf_bgp_notify_minor_open_msg,
4636 { "Minor error Code (Open Message)", "bgp.notify.minor_error_open", FT_UINT8, BASE_DEC,
4637 VALS(bgpnotify_minor_open_msg), 0x0, NULL, HFILL }},
4638 { &hf_bgp_notify_minor_update_msg,
4639 { "Minor error Code (Update Message)", "bgp.notify.minor_error_update", FT_UINT8, BASE_DEC,
4640 VALS(bgpnotify_minor_update_msg), 0x0, NULL, HFILL }},
4641 { &hf_bgp_notify_minor_ht_expired,
4642 { "Minor error Code (Hold Timer Expired)", "bgp.notify.minor_error_expired", FT_UINT8, BASE_DEC,
4643 NULL, 0x0, NULL, HFILL }},
4644 { &hf_bgp_notify_minor_state_machine,
4645 { "Minor error Code (State Machine)", "bgp.notify.minor_error_state", FT_UINT8, BASE_DEC,
4646 VALS(bgpnotify_minor_state_machine), 0x0, NULL, HFILL }},
4647 { &hf_bgp_notify_minor_cease,
4648 { "Minor error Code (Cease)", "bgp.notify.minor_error_cease", FT_UINT8, BASE_DEC,
4649 VALS(bgpnotify_minor_cease), 0x0, NULL, HFILL }},
4650 { &hf_bgp_notify_minor_cap_msg,
4651 { "Minor error Code (Capability Message)", "bgp.notify.minor_error_capability", FT_UINT8, BASE_DEC,
4652 VALS(bgpnotify_minor_cap_msg), 0x0, NULL, HFILL }},
4653 { &hf_bgp_notify_minor_unknown,
4654 { "Minor error Code (Unknown)", "bgp.notify.minor_error_unknown", FT_UINT8, BASE_DEC,
4655 NULL, 0x0, NULL, HFILL }},
4656 { &hf_bgp_notify_data,
4657 { "Data", "bgp.notify.minor_data", FT_BYTES, BASE_NONE,
4658 NULL, 0x0, NULL, HFILL }},
4660 /* Route Refresh */
4661 { &hf_bgp_route_refresh_afi,
4662 { "Address family identifier (AFI)", "bgp.route_refresh.afi", FT_UINT16, BASE_DEC,
4663 VALS(afn_vals), 0x0, NULL, HFILL }},
4664 { &hf_bgp_route_refresh_subtype,
4665 { "Subtype", "bgp.route_refresh.subtype", FT_UINT8, BASE_DEC,
4666 VALS(route_refresh_subtype_vals), 0x0, NULL, HFILL }},
4667 { &hf_bgp_route_refresh_safi,
4668 { "Subsequent address family identifier (SAFI)", "bgp.route_refresh.safi", FT_UINT8, BASE_DEC,
4669 VALS(bgpattr_nlri_safi), 0x0, NULL, HFILL }},
4670 { &hf_bgp_route_refresh_orf,
4671 { "ORF information", "bgp.route_refresh.orf", FT_NONE, BASE_NONE,
4672 NULL, 0x0, NULL, HFILL }},
4673 { &hf_bgp_route_refresh_orf_flag,
4674 { "ORF flag", "bgp.route_refresh.orf.flag", FT_UINT8, BASE_DEC,
4675 VALS(orf_when_vals), 0x0, NULL, HFILL }},
4676 { &hf_bgp_route_refresh_orf_type,
4677 { "ORF type", "bgp.route_refresh.orf.type", FT_UINT8, BASE_DEC,
4678 VALS(orf_type_vals), 0x0, NULL, HFILL }},
4679 { &hf_bgp_route_refresh_orf_length,
4680 { "ORF length", "bgp.route_refresh.orf.length", FT_UINT8, BASE_DEC,
4681 NULL, 0x0, NULL, HFILL }},
4682 { &hf_bgp_route_refresh_orf_entry_prefixlist,
4683 { "ORFEntry PrefixList", "bgp.route_refresh.orf.entry", FT_NONE, BASE_NONE,
4684 NULL, 0x0, NULL, HFILL }},
4685 { &hf_bgp_route_refresh_orf_entry_action,
4686 { "ORFEntry Action", "bgp.route_refresh.orf.entry.action", FT_UINT8, BASE_DEC,
4687 VALS(orf_entry_action_vals), BGP_ORF_ACTION, NULL, HFILL }},
4688 { &hf_bgp_route_refresh_orf_entry_match,
4689 { "ORFEntry Match", "bgp.route_refresh.orf.entry.match", FT_UINT8, BASE_DEC,
4690 VALS(orf_entry_match_vals), BGP_ORF_MATCH, NULL, HFILL }},
4691 { &hf_bgp_route_refresh_orf_entry_sequence,
4692 { "ORFEntry Sequence", "bgp.route_refresh.orf.entry.sequence", FT_UINT8, BASE_DEC,
4693 NULL, 0x0, NULL, HFILL }},
4694 { &hf_bgp_route_refresh_orf_entry_prefixmask_lower,
4695 { "ORFEntry PrefixMask length lower bound", "bgp.route_refresh.orf.entry.prefixmask_lower", FT_UINT8, BASE_DEC,
4696 NULL, 0x0, NULL, HFILL }},
4697 { &hf_bgp_route_refresh_orf_entry_prefixmask_upper,
4698 { "ORFEntry PrefixMask length upper bound", "bgp.route_refresh.orf.entry.prefixmask_upper", FT_UINT8, BASE_DEC,
4699 NULL, 0x0, NULL, HFILL }},
4701 /* Capability */
4702 { &hf_bgp_cap,
4703 { "Capability", "bgp.cap", FT_NONE, BASE_NONE,
4704 NULL, 0x0, NULL, HFILL }},
4705 { &hf_bgp_cap_type,
4706 { "Type", "bgp.cap.type", FT_UINT8, BASE_DEC,
4707 VALS(capability_vals), 0x0, NULL, HFILL }},
4708 { &hf_bgp_cap_length,
4709 { "Length", "bgp.cap.length", FT_UINT8, BASE_DEC,
4710 NULL, 0x0, NULL, HFILL }},
4711 { &hf_bgp_cap_action,
4712 { "Action", "bgp.cap.action", FT_UINT8, BASE_DEC,
4713 VALS(bgpcap_action), 0x0, NULL, HFILL }},
4714 { &hf_bgp_cap_unknown,
4715 { "Unknown", "bgp.cap.unknown", FT_BYTES, BASE_NONE,
4716 NULL, 0x0, NULL, HFILL }},
4717 { &hf_bgp_cap_reserved,
4718 { "Reserved", "bgp.cap.reserved", FT_BYTES, BASE_NONE,
4719 NULL, 0x0, "Must be Zero", HFILL }},
4720 { &hf_bgp_cap_mp_afi,
4721 { "AFI", "bgp.cap.mp.afi", FT_UINT16, BASE_DEC,
4722 VALS(afn_vals), 0x0, NULL, HFILL }},
4723 { &hf_bgp_cap_mp_safi,
4724 { "SAFI", "bgp.cap.mp.safi", FT_UINT8, BASE_DEC,
4725 VALS(bgpattr_nlri_safi), 0x0, NULL, HFILL }},
4726 { &hf_bgp_cap_gr_timers,
4727 { "Restart Timers", "bgp.cap.gr.timers", FT_UINT16, BASE_HEX,
4728 NULL, 0x0, NULL, HFILL }},
4729 { &hf_bgp_cap_gr_timers_restart_flag,
4730 { "Restart", "bgp.cap.gr.timers.restart_flag", FT_BOOLEAN, 16,
4731 TFS(&tfs_yes_no), 0x8000, NULL, HFILL }},
4732 { &hf_bgp_cap_gr_timers_restart_time,
4733 { "Time", "bgp.cap.gr.timers.restart_time", FT_UINT16, BASE_DEC,
4734 NULL, 0x0FFF, "in us", HFILL }},
4735 { &hf_bgp_cap_gr_afi,
4736 { "AFI", "bgp.cap.gr.afi", FT_UINT16, BASE_DEC,
4737 VALS(afn_vals), 0x0, NULL, HFILL }},
4738 { &hf_bgp_cap_gr_safi,
4739 { "SAFI", "bgp.cap.gr.safi", FT_UINT8, BASE_DEC,
4740 VALS(bgpattr_nlri_safi), 0x0, NULL, HFILL }},
4741 { &hf_bgp_cap_gr_flag,
4742 { "Flag", "bgp.cap.gr.flag", FT_UINT8, BASE_HEX,
4743 NULL, 0x0, NULL, HFILL }},
4744 { &hf_bgp_cap_gr_flag_pfs,
4745 { "Preserve forwarding state", "bgp.cap.gr.flag.pfs", FT_BOOLEAN, 8,
4746 TFS(&tfs_yes_no), 0x80, NULL, HFILL }},
4747 { &hf_bgp_cap_4as,
4748 { "AS Number", "bgp.cap.4as", FT_UINT32, BASE_DEC,
4749 NULL, 0x0, NULL, HFILL }},
4750 { &hf_bgp_cap_dc,
4751 { "Capability Dynamic", "bgp.cap.dc", FT_UINT8, BASE_DEC,
4752 VALS(capability_vals), 0x0, NULL, HFILL }},
4753 { &hf_bgp_cap_ap_afi,
4754 { "AFI", "bgp.cap.ap.afi", FT_UINT16, BASE_DEC,
4755 VALS(afn_vals), 0x0, NULL, HFILL }},
4756 { &hf_bgp_cap_ap_safi,
4757 { "SAFI", "bgp.cap.ap.safi", FT_UINT8, BASE_DEC,
4758 VALS(bgpattr_nlri_safi), 0x0, NULL, HFILL }},
4759 { &hf_bgp_cap_ap_sendreceive,
4760 { "Send/Receive", "bgp.cap.ap.sendreceive", FT_UINT8, BASE_DEC,
4761 VALS(orf_send_recv_vals), 0x0, NULL, HFILL }},
4762 { &hf_bgp_cap_orf_afi,
4763 { "AFI", "bgp.cap.orf.afi", FT_UINT16, BASE_DEC,
4764 VALS(afn_vals), 0x0, NULL, HFILL }},
4765 { &hf_bgp_cap_orf_safi,
4766 { "SAFI", "bgp.cap.orf.safi", FT_UINT8, BASE_DEC,
4767 VALS(bgpattr_nlri_safi), 0x0, NULL, HFILL }},
4768 { &hf_bgp_cap_orf_number,
4769 { "Number", "bgp.cap.orf.number", FT_UINT8, BASE_DEC,
4770 NULL, 0x0, NULL, HFILL }},
4771 { &hf_bgp_cap_orf_type,
4772 { "Type", "bgp.cap.orf.type", FT_UINT8, BASE_DEC,
4773 VALS(orf_type_vals), 0x0, NULL, HFILL }},
4774 { &hf_bgp_cap_orf_sendreceive,
4775 { "Send Receive", "bgp.cap.orf.sendreceive", FT_UINT8, BASE_DEC,
4776 VALS(orf_send_recv_vals), 0x0, NULL, HFILL }},
4777 /* BGP update */
4779 { &hf_bgp_update_withdrawn_routes_length,
4780 { "Withdrawn Routes Length", "bgp.update.withdrawn_routes.length", FT_UINT16, BASE_DEC,
4781 NULL, 0x0, NULL, HFILL}},
4782 { &hf_bgp_update_withdrawn_routes,
4783 { "Withdrawn Routes", "bgp.update.withdrawn_routes.length", FT_NONE, BASE_NONE,
4784 NULL, 0x0, NULL, HFILL}},
4786 { &hf_bgp_update_path_attribute_aggregator_as,
4787 { "Aggregator AS", "bgp.update.path_attribute.aggregator_as", FT_UINT16, BASE_DEC,
4788 NULL, 0x0, NULL, HFILL}},
4789 /* BGP update path attributes */
4790 { &hf_bgp_update_path_attributes,
4791 { "Path attributes", "bgp.update.path_attributes", FT_NONE, BASE_NONE,
4792 NULL, 0x0, NULL, HFILL}},
4793 { &hf_bgp_update_total_path_attribute_length,
4794 { "Total Path Attribute Length", "bgp.update.path_attributes.length", FT_UINT16, BASE_DEC,
4795 NULL, 0x0, NULL, HFILL}},
4796 { &hf_bgp_update_path_attribute_aggregator_origin,
4797 { "Aggregator origin", "bgp.update.path_attribute.aggregator_origin", FT_IPv4, BASE_NONE,
4798 NULL, 0x0, NULL, HFILL}},
4799 { &hf_bgp_update_path_attribute_as_path,
4800 { "AS Path", "bgp.update.path_attribute.as_path", FT_UINT16, BASE_DEC,
4801 NULL, 0x0, NULL, HFILL}},
4802 { &hf_bgp_update_community_as,
4803 { "Community AS", "bgp.update.path_attribute.community_as", FT_UINT16, BASE_DEC,
4804 NULL, 0x0, NULL, HFILL}},
4805 { &hf_bgp_update_path_attribute_community_value,
4806 { "Community value", "bgp.update.path_attribute.community_value", FT_UINT16, BASE_DEC,
4807 NULL, 0x0, NULL, HFILL}},
4808 { &hf_bgp_update_path_attribute_local_pref,
4809 { "Local preference", "bgp.update.path_attribute.local_pref", FT_UINT32, BASE_DEC,
4810 NULL, 0x0, NULL, HFILL}},
4811 { &hf_bgp_update_path_attribute_multi_exit_disc,
4812 { "Multiple exit discriminator", "bgp.update.path_attribute.multi_exit_disc", FT_UINT32, BASE_DEC,
4813 NULL, 0x0, NULL, HFILL}},
4814 { &hf_bgp_update_path_attribute_next_hop,
4815 { "Next hop", "bgp.update.path_attribute.next_hop", FT_IPv4, BASE_NONE,
4816 NULL, 0x0, NULL, HFILL}},
4817 { &hf_bgp_update_path_attribute_origin,
4818 { "Origin", "bgp.update.path_attribute.origin", FT_UINT8, BASE_DEC,
4819 VALS(bgpattr_origin), 0x0, NULL, HFILL}},
4820 { &hf_bgp_update_path_attribute,
4821 { "Path Attribut", "bgp.update.path_attribute", FT_NONE, BASE_NONE,
4822 NULL, 0x0, NULL, HFILL}},
4823 { &hf_bgp_update_path_attribute_flags,
4824 { "Flags", "bgp.update.path_attribute.flags", FT_UINT8, BASE_HEX,
4825 NULL, 0x0, NULL, HFILL}},
4826 { &hf_bgp_update_path_attribute_flags_optional,
4827 { "Optional", "bgp.update.path_attribute.flags.optional", FT_BOOLEAN, 8,
4828 TFS(&tfs_optional_wellknown), BGP_ATTR_FLAG_OPTIONAL, NULL, HFILL}},
4829 { &hf_bgp_update_path_attribute_flags_transitive,
4830 { "Transitive", "bgp.update.path_attribute.flags.transitive", FT_BOOLEAN, 8,
4831 TFS(&tfs_transitive_non_transitive), BGP_ATTR_FLAG_TRANSITIVE, NULL, HFILL}},
4832 { &hf_bgp_update_path_attribute_flags_partial,
4833 { "Partial", "bgp.update.path_attribute.flags.partial", FT_BOOLEAN, 8,
4834 TFS(&tfs_partial_complete), BGP_ATTR_FLAG_PARTIAL, NULL, HFILL}},
4835 { &hf_bgp_update_path_attribute_flags_extended_length,
4836 { "Length", "bgp.update.path_attribute.flags.extended_length", FT_BOOLEAN, 8,
4837 TFS(&tfs_extended_regular_length), BGP_ATTR_FLAG_EXTENDED_LENGTH, NULL, HFILL}},
4838 { &hf_bgp_update_path_attribute_type_code,
4839 { "Type Code", "bgp.update.path_attribute.type_code", FT_UINT8, BASE_DEC,
4840 VALS(bgpattr_type), 0x0, NULL, HFILL}},
4841 { &hf_bgp_update_path_attribute_length,
4842 { "Length", "bgp.update.path_attribute.length", FT_UINT16, BASE_DEC,
4843 NULL, 0x0, NULL, HFILL}},
4845 /* RFC4456 */
4846 { &hf_bgp_update_path_attribute_originator_id,
4847 { "Originator identifier", "bgp.update.path_attribute.originator_id", FT_IPv4, BASE_NONE,
4848 NULL, 0x0, NULL, HFILL}},
4849 { &hf_bgp_update_path_attribute_cluster_list,
4850 { "Cluster List", "bgp.path_attribute.cluster_list", FT_BYTES, BASE_NONE,
4851 NULL, 0x0, NULL, HFILL}},
4853 /* RFC5512 : BGP Encapsulation SAFI and the BGP Tunnel Encapsulation Attribute */
4854 { &hf_bgp_update_encaps_tunnel_tlv_len,
4855 { "length", "bgp.update.encaps_tunnel_tlv_len", FT_UINT16,
4856 BASE_DEC, NULL, 0x0, NULL, HFILL}},
4857 { &hf_bgp_update_encaps_tunnel_tlv_type,
4858 { "Type code", "bgp.update.encaps_tunnel_tlv_type", FT_UINT16, BASE_DEC,
4859 VALS(tunnel_type), 0x0, NULL, HFILL}},
4860 { &hf_bgp_update_encaps_tunnel_subtlv_len,
4861 { "length", "bgp.update.encaps_tunnel_tlv_sublen", FT_UINT8,
4862 BASE_DEC, NULL, 0x0, NULL, HFILL}},
4863 { &hf_bgp_update_encaps_tunnel_subtlv_type,
4864 { "Type code", "bgp.update.encaps_tunnel_subtlv_type", FT_UINT8, BASE_DEC,
4865 VALS(subtlv_type), 0x0, NULL, HFILL}},
4867 /* BGP update path attribut SSA SAFI (deprecated IETF draft) */
4868 { &hf_bgp_ssa_t,
4869 { "Transitive bit", "bgp.ssa_t", FT_BOOLEAN, 8,
4870 NULL, 0x80, "SSA Transitive bit", HFILL}},
4871 { &hf_bgp_ssa_type,
4872 { "SSA Type", "bgp.ssa_type", FT_UINT16, BASE_DEC,
4873 VALS(bgp_ssa_type), 0x7FFF, NULL, HFILL}},
4874 { &hf_bgp_ssa_len,
4875 { "Length", "bgp.ssa_len", FT_UINT16, BASE_DEC,
4876 NULL, 0x0, "SSA Length", HFILL}},
4877 { &hf_bgp_ssa_value,
4878 { "Value", "bgp.ssa_value", FT_BYTES, BASE_NONE,
4879 NULL, 0x0, "SSA Value", HFILL}},
4880 { &hf_bgp_ssa_l2tpv3_pref,
4881 { "Preference", "bgp.ssa_l2tpv3_pref", FT_UINT16, BASE_DEC,
4882 NULL, 0x0, NULL, HFILL}},
4883 { &hf_bgp_ssa_l2tpv3_s,
4884 { "Sequencing bit", "bgp.ssa_l2tpv3_s", FT_BOOLEAN, 8,
4885 NULL, 0x80, "Sequencing S-bit", HFILL}},
4886 { &hf_bgp_ssa_l2tpv3_unused,
4887 { "Unused", "bgp.ssa_l2tpv3_Unused", FT_BOOLEAN, 8,
4888 NULL, 0x7F, "Unused Flags", HFILL}},
4889 { &hf_bgp_ssa_l2tpv3_cookie_len,
4890 { "Cookie Length", "bgp.ssa_l2tpv3_cookie_len", FT_UINT8, BASE_DEC,
4891 NULL, 0x0, NULL, HFILL}},
4892 { &hf_bgp_ssa_l2tpv3_session_id,
4893 { "Session ID", "bgp.ssa_l2tpv3_session_id", FT_UINT32, BASE_DEC,
4894 NULL, 0x0, NULL, HFILL}},
4895 { &hf_bgp_ssa_l2tpv3_cookie,
4896 { "Cookie", "bgp.ssa_l2tpv3_cookie", FT_BYTES, BASE_NONE,
4897 NULL, 0x0, NULL, HFILL}},
4898 { &hf_bgp_withdrawn_prefix,
4899 { "Withdrawn prefix", "bgp.withdrawn_prefix", FT_IPv4, BASE_NONE,
4900 NULL, 0x0, NULL, HFILL}},
4902 /* NLRI header description */
4903 { &hf_bgp_update_nlri,
4904 { "Network Layer Reachability Information (NLRI)", "bgp.update.nlri", FT_NONE, BASE_NONE,
4905 NULL, 0x0, NULL, HFILL}},
4906 /* Global NLRI description */
4907 { &hf_bgp_mp_reach_nlri_ipv4_prefix,
4908 { "MP Reach NLRI IPv4 prefix", "bgp.mp_reach_nlri_ipv4_prefix", FT_IPv4, BASE_NONE,
4909 NULL, 0x0, NULL, HFILL}},
4910 { &hf_bgp_mp_unreach_nlri_ipv4_prefix,
4911 { "MP Unreach NLRI IPv4 prefix", "bgp.mp_unreach_nlri_ipv4_prefix", FT_IPv4, BASE_NONE,
4912 NULL, 0x0, NULL, HFILL}},
4913 { &hf_bgp_mp_nlri_tnl_id,
4914 { "MP Reach NLRI Tunnel Identifier", "bgp.mp_nlri_tnl_id", FT_UINT16, BASE_HEX,
4915 NULL, 0x0, NULL, HFILL}},
4916 { &hf_bgp_nlri_prefix,
4917 { "NLRI prefix", "bgp.nlri_prefix", FT_IPv4, BASE_NONE,
4918 NULL, 0x0, NULL, HFILL}},
4919 { &hf_bgp_nlri_path_id,
4920 { "NLRI path id", "bgp.nlri_path_id", FT_UINT32, BASE_DEC,
4921 NULL, 0x0, NULL, HFILL}},
4923 /* mcast vpn nlri and capability */
4924 { &hf_bgp_mcast_vpn_nlri_t,
4925 { "MCAST-VPN nlri", "bgp.mcast_vpn_nlri", FT_BYTES, BASE_NONE,
4926 NULL, 0x0, NULL, HFILL}},
4927 { &hf_bgp_mcast_vpn_nlri_route_type,
4928 { "Route Type", "bgp.mcast_vpn_nlri_route_type", FT_UINT8,
4929 BASE_DEC, VALS(mcast_vpn_route_type), 0x0, NULL, HFILL}},
4930 { &hf_bgp_mcast_vpn_nlri_length,
4931 { "Length", "bgp.mcast_vpn_nlri_length", FT_UINT8,
4932 BASE_DEC, NULL, 0x0, NULL, HFILL}},
4933 { &hf_bgp_mcast_vpn_nlri_rd,
4934 { "Route Distinguisher", "bgp.mcast_vpn_nlri_rd", FT_BYTES,
4935 BASE_NONE, NULL, 0x0, NULL, HFILL}},
4936 { &hf_bgp_mcast_vpn_nlri_origin_router_ipv4,
4937 { "Originating Router", "bgp.mcast_vpn_nlri_origin_router_ipv4", FT_IPv4,
4938 BASE_NONE, NULL, 0x0, NULL, HFILL}},
4939 { &hf_bgp_mcast_vpn_nlri_origin_router_ipv6,
4940 { "Originating Router", "bgp.mcast_vpn_nlri_origin_router_ipv6", FT_IPv6,
4941 BASE_NONE, NULL, 0x0, NULL, HFILL}},
4942 { &hf_bgp_mcast_vpn_nlri_source_as,
4943 { "Source AS", "bgp.mcast_vpn_nlri_source_as", FT_UINT16,
4944 BASE_DEC, NULL, 0x0, NULL, HFILL}},
4945 { &hf_bgp_mcast_vpn_nlri_source_length,
4946 { "Multicast Source Length", "bgp.mcast_vpn_nlri_source_length", FT_UINT8,
4947 BASE_DEC, NULL, 0x0, NULL, HFILL}},
4948 { &hf_bgp_mcast_vpn_nlri_group_length,
4949 { "Multicast Group Length", "bgp.mcast_vpn_nlri_group_length", FT_UINT8,
4950 BASE_DEC, NULL, 0x0, NULL, HFILL}},
4951 { &hf_bgp_mcast_vpn_nlri_source_addr_ipv4,
4952 { "Multicast Source Address", "bgp.mcast_vpn_nlri_source_addr_ipv4", FT_IPv4,
4953 BASE_NONE, NULL, 0x0, NULL, HFILL}},
4954 { &hf_bgp_mcast_vpn_nlri_source_addr_ipv6,
4955 { "Multicast Source Address", "bgp.mcast_vpn_nlri_source_addr_ipv6", FT_IPv6,
4956 BASE_NONE, NULL, 0x0, NULL, HFILL}},
4957 { &hf_bgp_mcast_vpn_nlri_group_addr_ipv4,
4958 { "Multicast Group Address", "bgp.mcast_vpn_nlri_group_addr_ipv4", FT_IPv4,
4959 BASE_NONE, NULL, 0x0, NULL, HFILL}},
4960 { &hf_bgp_mcast_vpn_nlri_group_addr_ipv6,
4961 { "Group Address", "bgp.mcast_vpn_nlri_group_addr_ipv6", FT_IPv6,
4962 BASE_NONE, NULL, 0x0, NULL, HFILL}},
4963 { &hf_bgp_mcast_vpn_nlri_route_key,
4964 { "Route Key", "bgp.mcast_vpn_nlri_route_key", FT_BYTES,
4965 BASE_NONE, NULL, 0x0, NULL, HFILL}},
4966 /* Bgp flow spec nlri and capability */
4967 { &hf_bgp_flowspec_nlri_t,
4968 { "FLOW-SPEC nlri", "bgp.flowspec_nlri", FT_BYTES, BASE_NONE,
4969 NULL, 0x0, NULL, HFILL}},
4970 { &hf_bgp_flowspec_nlri_filter,
4971 { "Filter", "bgp.flowspec_nlri.filter", FT_NONE, BASE_NONE,
4972 NULL, 0x0, NULL, HFILL }},
4973 { &hf_bgp_flowspec_nlri_filter_type,
4974 { "Filter type", "bgp.flowspec_nlri.filter_type", FT_UINT8, BASE_DEC,
4975 VALS(flowspec_nlri_opvaluepair_type), 0x0, NULL, HFILL }},
4976 { &hf_bgp_flowspec_nlri_length,
4977 { "NRLI length", "bgp.flowspec_nlri.length", FT_UINT32, BASE_DEC,
4978 NULL, 0x0, NULL, HFILL }},
4979 { &hf_bgp_flowspec_nlri_op_flags,
4980 { "Operator flags", "bgp.flowspec_nlri.opflags", FT_UINT8, BASE_HEX,
4981 NULL, 0x0, NULL, HFILL }},
4982 { &hf_bgp_flowspec_nlri_dst_pref_ipv4,
4983 { "Destination IP filter", "bgp.flowspec_nlri.dst_prefix_filter", FT_IPv4,
4984 BASE_NONE, NULL, 0x0, NULL, HFILL}},
4985 { &hf_bgp_flowspec_nlri_src_pref_ipv4,
4986 { "Source IP filter", "bgp.flowspec_nlri.src_prefix_filter", FT_IPv4,
4987 BASE_NONE, NULL, 0x0, NULL, HFILL}},
4988 { &hf_bgp_flowspec_nlri_op_eol,
4989 { "end-of-list", "bgp.flowspec_nlri.op.eol", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BGPNLRI_FSPEC_END_OF_LST,
4990 NULL, HFILL }},
4991 { &hf_bgp_flowspec_nlri_op_and,
4992 { "and", "bgp.flowspec_nlri.op.and", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BGPNLRI_FSPEC_AND_BIT,
4993 NULL, HFILL }},
4994 { &hf_bgp_flowspec_nlri_op_val_len,
4995 { "Value length", "bgp.flowspec_nlri.op.val_len", FT_UINT8, BASE_DEC, &flow_spec_op_len_val, BGPNLRI_FSPEC_VAL_LEN,
4996 NULL, HFILL }},
4997 { &hf_bgp_flowspec_nlri_op_un_bit4,
4998 { "Reserved", "bgp.flowspec_nlri.op.un_bit4", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BGPNLRI_FSPEC_UNUSED_BIT4,
4999 "Unused (must be zero)",HFILL}},
5000 { &hf_bgp_flowspec_nlri_op_un_bit5,
5001 { "Reserved", "bgp.flowspec_nlri.op.un_bit5", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BGPNLRI_FSPEC_UNUSED_BIT5,
5002 "Unused (must be zero)", HFILL}},
5003 { &hf_bgp_flowspec_nlri_dec_val_8,
5004 { "Decimal value", "bgp.flowspec_nlri.dec_val_8", FT_UINT8, BASE_DEC, NULL, 0X0,
5005 NULL, HFILL }},
5006 { &hf_bgp_flowspec_nlri_dec_val_16,
5007 { "Decimal value", "bgp.flowspec_nlri.dec_val_16", FT_UINT16, BASE_DEC, NULL, 0X0,
5008 NULL, HFILL }},
5009 { &hf_bgp_flowspec_nlri_dec_val_32,
5010 { "Decimal value", "bgp.flowspec_nlri.dec_val_32", FT_UINT32, BASE_DEC, NULL, 0X0,
5011 NULL, HFILL }},
5012 { &hf_bgp_flowspec_nlri_dec_val_64,
5013 { "Decimal value", "bgp.flowspec_nlri.dec_val_64", FT_UINT64, BASE_DEC, NULL, 0X0,
5014 NULL, HFILL }},
5015 { &hf_bgp_flowspec_nlri_op_lt,
5016 { "less than", "bgp.flowspec_nlri.op.lt", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BGPNLRI_FSPEC_LESS_THAN,
5017 NULL, HFILL }},
5018 { &hf_bgp_flowspec_nlri_op_gt,
5019 { "greater than", "bgp.flowspec_nlri.op.gt", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BGPNLRI_FSPEC_GREATER_THAN,
5020 NULL, HFILL }},
5021 { &hf_bgp_flowspec_nlri_op_eq,
5022 { "equal", "bgp.flowspec_nlri.op.equal", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BGPNLRI_FSPEC_EQUAL,
5023 NULL, HFILL }},
5024 { &hf_bgp_flowspec_nlri_op_flg_not,
5025 { "logical negation", "bgp.flowspec_nlri.op.flg_not", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BGPNLRI_FSPEC_TCPF_NOTBIT,
5026 NULL, HFILL }},
5027 { &hf_bgp_flowspec_nlri_op_flg_match,
5028 { "Match bit", "bgp.flowspec_nlri.op.flg_match", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BGPNLRI_FSPEC_TCPF_MATCHBIT,
5029 NULL, HFILL }},
5030 { &hf_bgp_flowspec_nlri_tcp_flags,
5031 { "TCP flags", "bgp.flowspec_nlri.val_tcp.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
5032 NULL, HFILL }},
5033 { &hf_bgp_flowspec_nlri_tcp_flags_cwr,
5034 { "Congestion Window Reduced (CWR)", "bgp.flowspec_nlri.val_tcp.flags.cwr", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BGPNLRI_FSPEC_TH_CWR,
5035 NULL, HFILL }},
5036 { &hf_bgp_flowspec_nlri_tcp_flags_ecn,
5037 { "ECN-Echo", "bgp.flowspec_nlri.val_tcp.flags.ecn", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BGPNLRI_FSPEC_TH_ECN,
5038 NULL, HFILL }},
5039 { &hf_bgp_flowspec_nlri_tcp_flags_urg,
5040 { "Urgent", "bgp.flowspec_nlri.val_tcp.flags.urg", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BGPNLRI_FSPEC_TH_URG,
5041 NULL, HFILL }},
5042 { &hf_bgp_flowspec_nlri_tcp_flags_ack,
5043 { "Acknowledgment", "bgp.flowspec_nlri.val_tcp.flags.ack", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BGPNLRI_FSPEC_TH_ACK,
5044 NULL, HFILL }},
5045 { &hf_bgp_flowspec_nlri_tcp_flags_push,
5046 { "Push", "bgp.flowspec_nlri.val_tcp.flags.push", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BGPNLRI_FSPEC_TH_PUSH,
5047 NULL, HFILL }},
5048 { &hf_bgp_flowspec_nlri_tcp_flags_reset,
5049 { "Reset", "bgp.flowspec_nlri.val_tcp.flags.reset", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BGPNLRI_FSPEC_TH_RST,
5050 NULL, HFILL }},
5051 { &hf_bgp_flowspec_nlri_tcp_flags_syn,
5052 { "Syn", "bgp.flowspec_nlri.val_tcp.flags.syn", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BGPNLRI_FSPEC_TH_SYN,
5053 NULL, HFILL }},
5054 { &hf_bgp_flowspec_nlri_tcp_flags_fin,
5055 { "Fin", "bgp.flowspec_nlri.val_tcp.flags.fin", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BGPNLRI_FSPEC_TH_FIN,
5056 NULL, HFILL }},
5057 { &hf_bgp_flowspec_nlri_fflag,
5058 { "Fragment Flag", "bgp.flowspec_nlri.val_frag", FT_UINT8, BASE_HEX, NULL, 0x0,
5059 NULL, HFILL }},
5060 { &hf_bgp_flowspec_nlri_fflag_lf,
5061 { "Last fragment", "bgp.flowspec_nlri.val_frag_lf", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BGPNLRI_FSPEC_FG_LF,
5062 NULL, HFILL }},
5063 { &hf_bgp_flowspec_nlri_fflag_ff,
5064 { "First fragment", "bgp.flowspec_nlri.val_frag_ff", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BGPNLRI_FSPEC_FG_FF,
5065 NULL, HFILL }},
5066 { &hf_bgp_flowspec_nlri_fflag_isf,
5067 { "Is a fragment", "bgp.flowspec_nlri.val_frag_isf", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BGPNLRI_FSPEC_FG_ISF,
5068 NULL, HFILL }},
5069 { &hf_bgp_flowspec_nlri_fflag_df,
5070 { "Don't fragment", "bgp.flowspec_nlri.val_frag_df", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BGPNLRI_FSPEC_FG_DF,
5071 NULL, HFILL }},
5072 { &hf_bgp_flowspec_nlri_dscp,
5073 { "Differentiated Services Codepoint", "bgp.flowspec_nlri.val_dsfield", FT_UINT8, BASE_HEX | BASE_EXT_STRING,
5074 &dscp_vals_ext, BGPNLRI_FSPEC_DSCP_BITMASK, NULL, HFILL }},
5075 /* end of bgp flow spec */
5076 /* BGP update safi ndt nlri draft-nalawade-idr-mdt-safi-03 */
5077 { &hf_bgp_mdt_nlri_safi_rd,
5078 { "Route Distinguisher", "bgp.mdt_safi_rd", FT_BYTES,
5079 BASE_NONE, NULL, 0x0, NULL, HFILL}},
5080 { &hf_bgp_mdt_nlri_safi_ipv4_addr,
5081 { "IPv4 Address", "bgp.mdt_safi_ipv4_addr", FT_IPv4,
5082 BASE_NONE, NULL, 0x0, NULL, HFILL}},
5083 { &hf_bgp_mdt_nlri_safi_group_addr,
5084 { "Group Address", "bgp.mdt_safi_group_addr", FT_IPv4,
5085 BASE_NONE, NULL, 0x0, NULL, HFILL}},
5086 /* BGP update extended community header field */
5087 /* BGP update extended community flow spec RFC 5575 */
5088 { &hf_bgp_ext_com_flow_act_samp_act,
5089 { "Sample", "bgp.ext_com_flow.sample", FT_BOOLEAN, 8, TFS(&tfs_set_notset),
5090 BGP_EXT_COM_FSPEC_ACT_S, NULL, HFILL}},
5091 { &hf_bgp_ext_com_flow_act_term_act,
5092 { "Terminal action", "bgp.ext_com_flow.traff_act", FT_BOOLEAN, 8, TFS(&tfs_set_notset),BGP_EXT_COM_FSPEC_ACT_T,NULL, HFILL}},
5093 { &hf_bgp_ext_com_flow_rate_float,
5094 { "Rate shaper", "bgp.ext_com_flow.rate_limit", FT_FLOAT, BASE_NONE,
5095 NULL, 0x0, NULL, HFILL}},
5096 { &hf_bgp_ext_com_flow_act_allset,
5097 { "5 Bytes", "bgp.flowspec_ext_com.emptybytes", FT_BYTES, BASE_NONE,
5098 NULL, 0x0, "Must be set to all 0", HFILL }},
5099 { &hf_bgp_ext_com_flow_redir,
5100 { "Action Traffic redirect", "bgp.ext_com_flow.redirect", FT_NONE, BASE_NONE,
5101 NULL, 0x0, NULL, HFILL }},
5102 { &hf_bgp_ext_com_flow_redir_as,
5103 { "AS", "bgp.ext_com_flow.redirect.as16", FT_UINT16, BASE_DEC,
5104 NULL, 0x0, NULL, HFILL }},
5105 { &hf_bgp_ext_com_flow_redir_an,
5106 { "AN", "bgp.ext_com_flow.redirect.an32", FT_UINT32, BASE_DEC,
5107 NULL, 0x0, NULL, HFILL }},
5109 /* BGP QoS propagation draft-knoll-idr-qos-attribute */
5110 { &hf_bgp_ext_com_qos_flags,
5111 { "Flags", "bgp.ext_com_qos.flags", FT_UINT8, BASE_HEX,
5112 NULL, 0, NULL, HFILL}},
5113 { &hf_bgp_ext_com_qos_flags_remarking,
5114 { "Remarking", "bgp.ext_com_qos.flags.remarking", FT_BOOLEAN, 8,
5115 TFS(&tfs_yes_no), 0x10, NULL, HFILL}},
5116 { &hf_bgp_ext_com_qos_flags_ignore_remarking,
5117 { "Ignore remarking", "bgp.ext_com_qos.flags.ignore_remarking", FT_BOOLEAN, 8,
5118 TFS(&tfs_yes_no), 0x08, NULL, HFILL}},
5119 { &hf_bgp_ext_com_qos_flags_agg_marking,
5120 { "Aggegation of markins", "bgp.ext_com_qos.flags.agg_marking", FT_BOOLEAN, 8,
5121 TFS(&tfs_yes_no), 0x04, NULL, HFILL}},
5122 { &hf_bgp_ext_com_cos_flags,
5123 { "Flags byte 1", "bgp.ext_com_cos.flags", FT_UINT8, BASE_HEX,
5124 NULL, 0, NULL, HFILL}},
5125 { &hf_bgp_ext_com_cos_flags_be,
5126 { "BE class", "bgp.ext_com_cos.flags.be", FT_BOOLEAN, 8,
5127 TFS(&tfs_supported_not_supported), 0x80, NULL, HFILL}},
5128 { &hf_bgp_ext_com_cos_flags_ef,
5129 { "EF class", "bgp.ext_com_cos.flags.ef", FT_BOOLEAN, 8,
5130 TFS(&tfs_supported_not_supported), 0x40, NULL, HFILL}},
5131 { &hf_bgp_ext_com_cos_flags_af,
5132 { "AF class", "bgp.ext_com_cos.flags.af", FT_BOOLEAN, 8,
5133 TFS(&tfs_supported_not_supported), 0x20, NULL, HFILL}},
5134 { &hf_bgp_ext_com_cos_flags_le,
5135 { "LE class", "bgp.ext_com_cos.flags.le", FT_BOOLEAN, 8,
5136 TFS(&tfs_supported_not_supported), 0x10, NULL, HFILL}},
5137 { &hf_bgp_ext_com_qos_set_number,
5138 { "QoS Set Number", "bgp.ext_com_qos.set_number", FT_UINT8, BASE_HEX,
5139 NULL, 0, NULL, HFILL}},
5140 { &hf_bgp_ext_com_qos_tech_type,
5141 { "Technology Type", "bgp.ext_com_qos.tech_type", FT_UINT8, BASE_HEX,
5142 VALS(qos_tech_type), 0, NULL, HFILL}},
5143 { &hf_bgp_ext_com_qos_marking_o,
5144 { "QoS Marking O", "bgp.ext_com_qos.marking_o", FT_UINT16, BASE_HEX,
5145 NULL, 0, NULL, HFILL}},
5146 { &hf_bgp_ext_com_qos_marking_a,
5147 { "QoS Marking A", "bgp.ext_com_qos.marking_a", FT_UINT8, BASE_HEX_DEC,
5148 NULL, 0, NULL, HFILL}},
5149 { &hf_bgp_ext_com_qos_default_to_zero,
5150 { "Defaults to zero", "bgp.ext_com_qos.default_to_zero", FT_UINT8, BASE_HEX,
5151 NULL, 0, NULL, HFILL}},
5152 /* BGP L2 extended community RFC 4761, RFC 6624 */
5153 /* draft-ietf-l2vpn-vpls-multihoming */
5154 { &hf_bgp_ext_com_l2_encaps,
5155 { "Encaps Type", "bgp.ext_com_l2.encaps_type", FT_UINT8, BASE_DEC,
5156 VALS(bgp_l2vpn_encaps), 0, NULL, HFILL}},
5157 { &hf_bgp_ext_com_l2_c_flags,
5158 { "Control Flags", "bgp.ext_com_l2.c_flags", FT_UINT8, BASE_HEX,
5159 NULL, 0x0, NULL, HFILL }},
5160 { &hf_bgp_ext_com_l2_flag_d,
5161 { "Down flag", "bgp.ext_com_l2.flag_d",FT_BOOLEAN, 8,
5162 TFS(&tfs_set_notset), BGP_EXT_COM_L2_FLAG_D, NULL, HFILL }},
5163 { &hf_bgp_ext_com_l2_flag_z1,
5164 { "Unassigned", "bgp.ext_com_l2.flag_z1",FT_UINT8, BASE_DEC,
5165 NULL, BGP_EXT_COM_L2_FLAG_Z1, "Must be Zero", HFILL }},
5166 { &hf_bgp_ext_com_l2_flag_f,
5167 { "Flush flag", "bgp.ext_com_l2.flag_f",FT_BOOLEAN, 8,
5168 TFS(&tfs_set_notset), BGP_EXT_COM_L2_FLAG_F, NULL, HFILL }},
5169 { &hf_bgp_ext_com_l2_flag_z345,
5170 { "Unassigned", "bgp.ext_com_l2.flag_z345",FT_UINT8, BASE_DEC,
5171 NULL, BGP_EXT_COM_L2_FLAG_Z345, "Must be Zero", HFILL }},
5172 { &hf_bgp_ext_com_l2_flag_c,
5173 { "C flag", "bgp.ext_com_l2.flag_c",FT_BOOLEAN, 8,
5174 TFS(&tfs_set_notset), BGP_EXT_COM_L2_FLAG_C, NULL, HFILL }},
5175 { &hf_bgp_ext_com_l2_flag_s,
5176 { "S flag", "bgp.ext_com_l2.flag_s",FT_BOOLEAN, 8,
5177 TFS(&tfs_set_notset), BGP_EXT_COM_L2_FLAG_S, NULL, HFILL }},
5178 { &hf_bgp_ext_com_l2_mtu,
5179 { "Layer-2 MTU", "bgp.ext_com_l2.l2_mtu", FT_UINT16, BASE_DEC,
5180 NULL, 0x0, NULL, HFILL}},
5183 static gint *ett[] = {
5184 &ett_bgp,
5185 &ett_bgp_prefix,
5186 &ett_bgp_unfeas,
5187 &ett_bgp_attrs,
5188 &ett_bgp_attr,
5189 &ett_bgp_attr_flags,
5190 &ett_bgp_mp_nhna,
5191 &ett_bgp_mp_reach_nlri,
5192 &ett_bgp_mp_unreach_nlri,
5193 &ett_bgp_mp_snpa,
5194 &ett_bgp_nlri,
5195 &ett_bgp_open,
5196 &ett_bgp_update,
5197 &ett_bgp_notification,
5198 &ett_bgp_route_refresh,
5199 &ett_bgp_capability,
5200 &ett_bgp_as_paths,
5201 &ett_bgp_as_path_segments,
5202 &ett_bgp_communities,
5203 &ett_bgp_cluster_list,
5204 &ett_bgp_options,
5205 &ett_bgp_option,
5206 &ett_bgp_cap,
5207 &ett_bgp_extended_communities,
5208 &ett_bgp_extended_com_fspec_redir,
5209 &ett_bgp_ext_com_flags,
5210 &ett_bgp_ext_com_l2_flags,
5211 &ett_bgp_ssa,
5212 &ett_bgp_ssa_subtree,
5213 &ett_bgp_orf,
5214 &ett_bgp_orf_entry,
5215 &ett_bgp_mcast_vpn_nlri,
5216 &ett_bgp_flow_spec_nlri,
5217 &ett_bgp_flow_spec_nlri_filter,
5218 &ett_bgp_flow_spec_nlri_op_flags,
5219 &ett_bgp_flow_spec_nlri_tcp,
5220 &ett_bgp_flow_spec_nlri_ff,
5221 &ett_bgp_tunnel_tlv,
5222 &ett_bgp_tunnel_tlv_subtree,
5223 &ett_bgp_tunnel_subtlv,
5224 &ett_bgp_tunnel_subtlv_subtree,
5226 static ei_register_info ei[] = {
5227 { &ei_bgp_cap_len_bad, { "bgp.cap.length.bad", PI_MALFORMED, PI_ERROR, "Capability length is wrong", EXPFILL }},
5228 { &ei_bgp_cap_gr_helper_mode_only, { "bgp.cap.gr.helper_mode_only", PI_REQUEST_CODE, PI_CHAT, "Graceful Restart Capability supported in Helper mode only", EXPFILL }},
5229 { &ei_bgp_notify_minor_unknown, { "bgp.notify.minor_error.unknown", PI_UNDECODED, PI_NOTE, "Unknown notification error", EXPFILL }},
5230 { &ei_bgp_route_refresh_orf_type_unknown, { "bgp.route_refresh.orf.type.unknown", PI_CHAT, PI_ERROR, "ORFEntry-Unknown", EXPFILL }},
5231 { &ei_bgp_length_invalid, { "bgp.length.invalid", PI_MALFORMED, PI_ERROR, "Length is invalid", EXPFILL }},
5232 { &ei_bgp_afi_type_not_supported, { "bgp.afi_type_not_supported", PI_PROTOCOL, PI_ERROR, "AFI Type not supported", EXPFILL }},
5235 module_t *bgp_module;
5236 expert_module_t* expert_bgp;
5238 static const enum_val_t asn_len[] = {
5239 {"auto-detect", "Auto-detect", 0},
5240 {"2", "2 octet", 2},
5241 {"4", "4 octet", 4},
5242 {NULL, NULL, -1}
5245 proto_bgp = proto_register_protocol("Border Gateway Protocol",
5246 "BGP", "bgp");
5247 proto_register_field_array(proto_bgp, hf, array_length(hf));
5248 proto_register_subtree_array(ett, array_length(ett));
5249 expert_bgp = expert_register_protocol(proto_bgp);
5250 expert_register_field_array(expert_bgp, ei, array_length(ei));
5252 bgp_module = prefs_register_protocol(proto_bgp, NULL);
5253 prefs_register_bool_preference(bgp_module, "desegment",
5254 "Reassemble BGP messages spanning multiple TCP segments",
5255 "Whether the BGP dissector should reassemble messages spanning multiple TCP segments."
5256 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
5257 &bgp_desegment);
5258 prefs_register_enum_preference(bgp_module, "asn_len",
5259 "Length of the AS number",
5260 "BGP dissector detect the length of the AS number in AS_PATH attributes automatically or manually (NOTE: Automatic detection is not 100% accurate)",
5261 &bgp_asn_len, asn_len, FALSE);
5264 void
5265 proto_reg_handoff_bgp(void)
5267 dissector_handle_t bgp_handle;
5269 bgp_handle = create_dissector_handle(dissect_bgp, proto_bgp);
5270 dissector_add_uint("tcp.port", BGP_TCP_PORT, bgp_handle);
5273 * Editor modelines - http://www.wireshark.org/tools/modelines.html
5275 * Local variables:
5276 * c-basic-offset: 4
5277 * tab-width: 8
5278 * indent-tabs-mode: nil
5279 * End:
5281 * ex: set shiftwidth=4 tabstop=8 expandtab:
5282 * :indentSize=4:tabSize=8:noTabs=true: