1 /*
2  * Copyright (c) 2013-2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  *
8  */
9 
10 #ifndef BGPCOMMON_H_
11 #define BGPCOMMON_H_
12 
13 #include <string>
14 #include <cstdint>
15 #include <sstream>
16 #include <cinttypes>
17 #include <cstring>
18 #include <sys/types.h>
19 
20 namespace bgp {
21     #define BGP_MAX_MSG_SIZE        65535                   // Max payload size - Larger than RFC4271 of 4096
22     #define BGP_MSG_HDR_LEN         19                      // BGP message header size
23     #define BGP_OPEN_MSG_MIN_LEN    29                      // Includes the expected header size
24     #define BGP_VERSION             4
25     #define BGP_CAP_PARAM_TYPE      2
26     #define BGP_AS_TRANS            23456                   // BGP ASN when AS exceeds 16bits
27 
28 
29     /**
30      * defines whether the attribute is optional (if
31      *    set to 1) or well-known (if set to 0)
32      */
33     #define ATTR_FLAG_OPT(flags)        ( flags & 0x80 )
34 
35     /**
36      * defines whether an optional attribute is
37      *    transitive (if set to 1) or non-transitive (if set to 0)
38      */
39     #define ATTR_FLAG_TRANS(flags)      ( flags & 0x40 )
40 
41     /**
42      * defines whether the information contained in the
43      *  (if set to 1) or complete (if set to 0)
44      */
45     #define ATTR_FLAG_PARTIAL(flags)    ( flags & 0x20 )
46 
47     /**
48      * defines whether the Attribute Length is one octet
49      *      (if set to 0) or two octets (if set to 1)
50      *
51      * \details
52      *         If the Extended Length bit of the Attribute Flags octet is set
53      *         to 0, the third octet of the Path Attribute contains the length
54      *         of the attribute data in octets.
55      *
56      *         If the Extended Length bit of the Attribute Flags octet is set
57      *         to 1, the third and fourth octets of the path attribute contain
58      *         the length of the attribute data in octets.
59      */
60      #define ATTR_FLAG_EXTENDED(flags)   ( flags & 0x10 )
61 
62     /**
63      * Defines the BGP address-families (AFI)
64      *      http://www.iana.org/assignments/address-family-numbers/address-family-numbers.xhtml
65      */
66     enum BGP_AFI {
67         BGP_AFI_IPV4=1,
68         BGP_AFI_IPV6=2,
69         BGP_AFI_L2VPN=25,
70         BGP_AFI_BGPLS=16388
71     };
72 
73     /**
74      * Defines the BGP subsequent address-families (SAFI)
75      *      http://www.iana.org/assignments/safi-namespace/safi-namespace.xhtml
76      */
77     enum BGP_SAFI {
78         BGP_SAFI_UNICAST=1,
79         BGP_SAFI_MULTICAST=2,
80 
81         BGP_SAFI_NLRI_LABEL=4,          // RFC3107
82         BGP_SAFI_MCAST_VPN,             // RFC6514
83 
84         BGP_SAFI_VPLS=65,               // RFC4761, RFC6074
85         BGP_SAFI_MDT,                   // RFC6037
86         BGP_SAFI_4over6,                // RFC5747
87         BGP_SAFI_6over4,                // yong cui
88 
89         BGP_SAFI_EVPN=70,               // draft-ietf-l2vpn-evpn
90         BGP_SAFI_BGPLS=71,              // draft-ietf-idr-ls-distribution
91 
92         BGP_SAFI_MPLS=128,              // RFC4364
93         BGP_SAFI_MCAST_MPLS_VPN,        // RFC6513, RFC6514
94 
95         BGP_SAFI_RT_CONSTRAINS=132      // RFC4684
96     };
97 
98     /**
99      * ENUM to define the prefix type used for prefix nlri maps in returned data
100      */
101     enum PREFIX_TYPE {
102                 PREFIX_UNICAST_V4=1,
103                 PREFIX_UNICAST_V6,
104                 PREFIX_LABEL_UNICAST_V4,
105                 PREFIX_LABEL_UNICAST_V6,
106                 PREFIX_VPN_V4,
107                 PREFIX_VPN_v6,
108                 PREFIX_MULTICAST_V4,
109                 // Add BGP-LS types
110     };
111 
112     /**
113       * struct is used for nlri prefixes
114       */
115     struct prefix_tuple {
116         /**
117         * len in bits of the IP address prefix
118         *      length of 0 indicates a prefix that matches all IP addresses
119         */
120         PREFIX_TYPE   type;                 ///< Prefix type - RIB type
121         unsigned char len;                  ///< Length of prefix in bits
122         std::string   prefix;               ///< Printed form of the IP address
123         uint8_t       prefix_bin[16];       ///< Prefix in binary form
124         uint32_t      path_id;              ///< Path ID (add path draft-ietf-idr-add-paths-15)
125         bool          isIPv4;               ///< True if IPv4, false if IPv6
126 
127         std::string   labels;               ///< Labels in the format of label, label, ...
128     };
129 
130     /**
131     * Struct for Route Distinguisher
132     */
133     struct rd_tuple {
134         std::string    rd_administrator_subfield;
135         std::string    rd_assigned_number;
136         uint8_t        rd_type;
137     };
138 
139     /**
140     * struct is used for l3vpn
141     */
142     struct vpn_tuple: prefix_tuple, rd_tuple {
143         // inherits
144     };
145 
146     /**
147     * Struct is used for evpn
148     */
149     struct evpn_tuple: prefix_tuple, rd_tuple {
150         std::string     ethernet_segment_identifier;
151         std::string     ethernet_tag_id_hex;
152         uint8_t         mac_len;
153         std::string     mac;
154         uint8_t         ip_len;
155         std::string     ip;
156         int             mpls_label_1;
157         int             mpls_label_2;
158         uint8_t         originating_router_ip_len;
159         std::string     originating_router_ip;
160     };
161 
162     /*********************************************************************//**
163      * Simple function to swap bytes around from network to host or
164      *  host to networking.  This method will convert any size byte variable,
165      *  unlike ntohs and ntohl.
166      *
167      * @param [in/out] var   Variable containing data to update
168      * @param [in]     size  Size of var - Default is size of var
169      *********************************************************************/
parse_mac(u_char * data_pointer)170     inline std::string parse_mac(u_char *data_pointer) {
171         u_char *pointer = data_pointer;
172 
173         std::ostringstream mac_stringstream;
174 
175         for (int i = 0; i < 6; ++i) {
176             if (i != 0) mac_stringstream << ':';
177             mac_stringstream.width(2);
178             mac_stringstream.fill('0');
179             mac_stringstream << std::hex << (int)(pointer[i]);
180         }
181 
182         return mac_stringstream.str();
183     }
184 
185     /*********************************************************************//**
186      * Simple function to swap bytes around from network to host or
187      *  host to networking.  This method will convert any size byte variable,
188      *  unlike ntohs and ntohl.
189      *
190      * @param [in/out] var   Variable containing data to update
191      * @param [in]     size  Size of var - Default is size of var
192      *********************************************************************/
193     template <typename VarT>
194     void SWAP_BYTES(VarT *var, int size=sizeof(VarT)) {
195         if (size <= 1)
196             return;
197 
198         u_char *v = (u_char *)var;
199 
200         // Allocate a working buffer
201         u_char buf[size];
202 
203         // Make a copy
204         memcpy(buf, var, size);
205 
206         int i2 = 0;
207         for (int i=size-1; i >= 0; i--)
208             v[i2++] = buf[i];
209 
210     }
211 
212     /**
213      * Function to get string representation of AFI code.
214      * @param code AFI http://www.iana.org/assignments/address-family-numbers/address-family-numbers.xhtml
215      * @return string like "IPv6" or "IPv4"
216      */
GET_AFI_STRING_BY_CODE(int code)217     inline std::string GET_AFI_STRING_BY_CODE(int code) {
218         std::string afi_string;
219 
220         switch (code) {
221             case bgp::BGP_AFI_IPV4 :
222                 afi_string = "IPv4";
223                 break;
224 
225             case bgp::BGP_AFI_IPV6 :
226                 afi_string = "IPv6";
227                 break;
228 
229             case bgp::BGP_AFI_BGPLS :
230                 afi_string = "BGP-LS";
231                 break;
232 
233             default:
234                 afi_string = "unknown";
235                 break;
236         }
237         return afi_string;
238     }
239 
240     /**
241      * Function to get string representation of SAFI code.
242      * @param code SAFI http://www.iana.org/assignments/safi-namespace/safi-namespace.xhtml
243      * @return string like "Unicast" or "Multicast"
244      */
GET_SAFI_STRING_BY_CODE(int code)245     inline std::string GET_SAFI_STRING_BY_CODE(int code) {
246         std::string safi_string;
247 
248         switch (code) {
249             case bgp::BGP_SAFI_UNICAST : // Unicast IP forwarding
250                 safi_string = "Unicast";
251                 break;
252 
253             case bgp::BGP_SAFI_MULTICAST : // Multicast IP forwarding
254                 safi_string = "Multicast";
255                 break;
256 
257             case bgp::BGP_SAFI_NLRI_LABEL : // NLRI with MPLS Labels
258                 safi_string = "Labeled Unicast";
259                 break;
260 
261             case bgp::BGP_SAFI_MCAST_VPN : // MCAST VPN
262                 safi_string = "MCAST VPN";
263                 break;
264 
265             case bgp::BGP_SAFI_VPLS : // VPLS
266                 safi_string = "VPLS";
267                 break;
268 
269             case bgp::BGP_SAFI_MDT : // BGP MDT
270                 safi_string = "BGP MDT";
271                 break;
272 
273             case bgp::BGP_SAFI_4over6 : // BGP 4over6
274                 safi_string = "BGP 4over6";
275                 break;
276 
277             case bgp::BGP_SAFI_6over4 : // BGP 6over4
278                 safi_string = "BGP 6over4";
279                 break;
280 
281             case bgp::BGP_SAFI_EVPN : // BGP EVPNs
282                 safi_string = "BGP EVPNs";
283                 break;
284 
285             case bgp::BGP_SAFI_BGPLS : // BGP-LS
286                 safi_string = "BGP-LS";
287                 break;
288 
289             case bgp::BGP_SAFI_MPLS : // MPLS-Labeled VPN
290                 safi_string = "MPLS-Labeled VPN";
291                 break;
292 
293             case bgp::BGP_SAFI_MCAST_MPLS_VPN : // Multicast BGP/MPLS VPN
294                 safi_string = "Multicast BGP/MPLS VPN";
295                 break;
296 
297             case bgp::BGP_SAFI_RT_CONSTRAINS : // Route target constrains
298                 safi_string = "RT constrains";
299                 break;
300 
301         }
302         return safi_string;
303     }
304 
305 }
306 
307 #endif /* BGPCOMMON_H */
308