]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
f4c89855 LB |
2 | /* |
3 | * Copyright 2015, LabN Consulting, L.L.C. | |
f4c89855 LB |
4 | */ |
5 | ||
6 | #include <zebra.h> | |
7 | ||
5bf15956 | 8 | #include "command.h" |
f4c89855 LB |
9 | #include "memory.h" |
10 | #include "prefix.h" | |
f4c89855 | 11 | #include "filter.h" |
937652c6 | 12 | #include "stream.h" |
f4c89855 LB |
13 | |
14 | #include "bgpd.h" | |
15 | #include "bgp_attr.h" | |
16 | ||
17 | #include "bgp_encap_types.h" | |
18 | #include "bgp_encap_tlv.h" | |
19 | ||
20 | /*********************************************************************** | |
21 | * SUBTLV ENCODE | |
22 | ***********************************************************************/ | |
23 | ||
24 | /* rfc5512 4.1 */ | |
d62a17ae | 25 | static struct bgp_attr_encap_subtlv *subtlv_encode_encap_l2tpv3_over_ip( |
26 | struct bgp_tea_subtlv_encap_l2tpv3_over_ip *st) | |
f4c89855 | 27 | { |
d62a17ae | 28 | struct bgp_attr_encap_subtlv *new; |
29 | uint8_t *p; | |
30 | int total = 4 + st->cookie_length; | |
f4c89855 | 31 | |
d62a17ae | 32 | /* sanity check */ |
33 | assert(st->cookie_length <= sizeof(st->cookie)); | |
34 | assert(total <= 0xff); | |
f4c89855 | 35 | |
d62a17ae | 36 | new = XCALLOC(MTYPE_ENCAP_TLV, |
12f70478 | 37 | sizeof(struct bgp_attr_encap_subtlv) + total); |
d62a17ae | 38 | assert(new); |
39 | new->type = BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION; | |
40 | new->length = total; | |
41 | p = new->value; | |
f4c89855 | 42 | |
d62a17ae | 43 | *p++ = (st->sessionid & 0xff000000) >> 24; |
44 | *p++ = (st->sessionid & 0xff0000) >> 16; | |
45 | *p++ = (st->sessionid & 0xff00) >> 8; | |
46 | *p++ = (st->sessionid & 0xff); | |
47 | memcpy(p, st->cookie, st->cookie_length); | |
48 | return new; | |
f4c89855 LB |
49 | } |
50 | ||
51 | /* rfc5512 4.1 */ | |
52 | static struct bgp_attr_encap_subtlv * | |
d62a17ae | 53 | subtlv_encode_encap_gre(struct bgp_tea_subtlv_encap_gre_key *st) |
f4c89855 | 54 | { |
d62a17ae | 55 | struct bgp_attr_encap_subtlv *new; |
56 | uint8_t *p; | |
57 | int total = 4; | |
f4c89855 | 58 | |
d62a17ae | 59 | assert(total <= 0xff); |
f4c89855 | 60 | |
d62a17ae | 61 | new = XCALLOC(MTYPE_ENCAP_TLV, |
12f70478 | 62 | sizeof(struct bgp_attr_encap_subtlv) + total); |
d62a17ae | 63 | assert(new); |
64 | new->type = BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION; | |
65 | new->length = total; | |
66 | p = new->value; | |
f4c89855 | 67 | |
d62a17ae | 68 | *p++ = (st->gre_key & 0xff000000) >> 24; |
69 | *p++ = (st->gre_key & 0xff0000) >> 16; | |
70 | *p++ = (st->gre_key & 0xff00) >> 8; | |
71 | *p++ = (st->gre_key & 0xff); | |
72 | return new; | |
f4c89855 LB |
73 | } |
74 | ||
75 | static struct bgp_attr_encap_subtlv * | |
d62a17ae | 76 | subtlv_encode_encap_pbb(struct bgp_tea_subtlv_encap_pbb *st) |
77 | { | |
78 | struct bgp_attr_encap_subtlv *new; | |
79 | uint8_t *p; | |
80 | int total = 1 + 3 + 6 + 2; /* flags + isid + madaddr + vid */ | |
81 | ||
82 | assert(total <= 0xff); | |
83 | ||
84 | new = XCALLOC(MTYPE_ENCAP_TLV, | |
12f70478 | 85 | sizeof(struct bgp_attr_encap_subtlv) + total); |
d62a17ae | 86 | assert(new); |
87 | new->type = BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION; | |
88 | new->length = total; | |
89 | p = new->value; | |
90 | ||
91 | *p++ = (st->flag_isid ? 0x80 : 0) | (st->flag_vid ? 0x40 : 0) | 0; | |
92 | if (st->flag_isid) { | |
93 | *p = (st->isid & 0xff0000) >> 16; | |
94 | *(p + 1) = (st->isid & 0xff00) >> 8; | |
95 | *(p + 2) = (st->isid & 0xff); | |
96 | } | |
97 | p += 3; | |
98 | memcpy(p, st->macaddr, 6); | |
99 | p += 6; | |
100 | if (st->flag_vid) { | |
101 | *p++ = (st->vid & 0xf00) >> 8; | |
102 | *p++ = st->vid & 0xff; | |
103 | } | |
104 | return new; | |
f4c89855 LB |
105 | } |
106 | ||
107 | /* rfc5512 4.2 */ | |
108 | static struct bgp_attr_encap_subtlv * | |
d62a17ae | 109 | subtlv_encode_proto_type(struct bgp_tea_subtlv_proto_type *st) |
f4c89855 | 110 | { |
d62a17ae | 111 | struct bgp_attr_encap_subtlv *new; |
112 | uint8_t *p; | |
113 | int total = 2; | |
f4c89855 | 114 | |
d62a17ae | 115 | assert(total <= 0xff); |
f4c89855 | 116 | |
d62a17ae | 117 | new = XCALLOC(MTYPE_ENCAP_TLV, |
12f70478 | 118 | sizeof(struct bgp_attr_encap_subtlv) + total); |
d62a17ae | 119 | assert(new); |
120 | new->type = BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE; | |
121 | new->length = total; | |
122 | p = new->value; | |
f4c89855 | 123 | |
d62a17ae | 124 | *p++ = (st->proto & 0xff00) >> 8; |
125 | *p++ = (st->proto & 0xff); | |
126 | return new; | |
f4c89855 LB |
127 | } |
128 | ||
129 | /* rfc5512 4.3 */ | |
130 | static struct bgp_attr_encap_subtlv * | |
d62a17ae | 131 | subtlv_encode_color(struct bgp_tea_subtlv_color *st) |
f4c89855 | 132 | { |
d62a17ae | 133 | struct bgp_attr_encap_subtlv *new; |
134 | uint8_t *p; | |
135 | int total = 8; | |
f4c89855 | 136 | |
d62a17ae | 137 | assert(total <= 0xff); |
f4c89855 | 138 | |
d62a17ae | 139 | new = XCALLOC(MTYPE_ENCAP_TLV, |
12f70478 | 140 | sizeof(struct bgp_attr_encap_subtlv) + total); |
d62a17ae | 141 | assert(new); |
142 | new->type = BGP_ENCAP_SUBTLV_TYPE_COLOR; | |
143 | new->length = total; | |
144 | p = new->value; | |
f4c89855 | 145 | |
d62a17ae | 146 | *p++ = 0x03; /* transitive*/ |
147 | *p++ = 0x0b; | |
148 | *p++ = 0; /* reserved */ | |
149 | *p++ = 0; /* reserved */ | |
f4c89855 | 150 | |
d62a17ae | 151 | *p++ = (st->color & 0xff000000) >> 24; |
152 | *p++ = (st->color & 0xff0000) >> 16; | |
153 | *p++ = (st->color & 0xff00) >> 8; | |
154 | *p++ = (st->color & 0xff); | |
f4c89855 | 155 | |
d62a17ae | 156 | return new; |
f4c89855 LB |
157 | } |
158 | ||
159 | /* rfc 5566 4. */ | |
160 | static struct bgp_attr_encap_subtlv * | |
d62a17ae | 161 | subtlv_encode_ipsec_ta(struct bgp_tea_subtlv_ipsec_ta *st) |
f4c89855 | 162 | { |
d62a17ae | 163 | struct bgp_attr_encap_subtlv *new; |
164 | uint8_t *p; | |
165 | int total = 2 + st->authenticator_length; | |
f4c89855 | 166 | |
d62a17ae | 167 | /* sanity check */ |
168 | assert(st->authenticator_length <= sizeof(st->value)); | |
169 | assert(total <= 0xff); | |
f4c89855 | 170 | |
d62a17ae | 171 | new = XCALLOC(MTYPE_ENCAP_TLV, |
12f70478 | 172 | sizeof(struct bgp_attr_encap_subtlv) + total); |
d62a17ae | 173 | assert(new); |
174 | new->type = BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA; | |
175 | new->length = total; | |
176 | p = new->value; | |
f4c89855 | 177 | |
d62a17ae | 178 | *p++ = (st->authenticator_type & 0xff00) >> 8; |
179 | *p++ = st->authenticator_type & 0xff; | |
180 | memcpy(p, st->value, st->authenticator_length); | |
181 | return new; | |
f4c89855 LB |
182 | } |
183 | ||
587ff0fd LB |
184 | /* draft-rosen-idr-tunnel-encaps 2.1 */ |
185 | static struct bgp_attr_encap_subtlv * | |
d62a17ae | 186 | subtlv_encode_remote_endpoint(struct bgp_tea_subtlv_remote_endpoint *st) |
187 | { | |
188 | struct bgp_attr_encap_subtlv *new; | |
189 | uint8_t *p; | |
190 | ||
191 | int total = (st->family == AF_INET ? 8 : 20); | |
192 | ||
193 | assert(total <= 0xff); | |
194 | ||
195 | new = XCALLOC(MTYPE_ENCAP_TLV, | |
12f70478 | 196 | sizeof(struct bgp_attr_encap_subtlv) + total); |
d62a17ae | 197 | assert(new); |
198 | new->type = BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT; | |
199 | new->length = total; | |
200 | p = new->value; | |
201 | if (st->family == AF_INET) { | |
8643c2e5 DA |
202 | memcpy(p, &(st->ip_address.v4.s_addr), IPV4_MAX_BYTELEN); |
203 | p += IPV4_MAX_BYTELEN; | |
d62a17ae | 204 | } else { |
205 | assert(st->family == AF_INET6); | |
8643c2e5 DA |
206 | memcpy(p, &(st->ip_address.v6.s6_addr), IPV6_MAX_BYTELEN); |
207 | p += IPV6_MAX_BYTELEN; | |
d62a17ae | 208 | } |
209 | memcpy(p, &(st->as4), 4); | |
210 | return new; | |
587ff0fd | 211 | } |
f4c89855 LB |
212 | |
213 | /*********************************************************************** | |
214 | * TUNNEL TYPE-SPECIFIC TLV ENCODE | |
215 | ***********************************************************************/ | |
216 | ||
217 | /* | |
218 | * requires "extra" and "last" to be defined in caller | |
219 | */ | |
d62a17ae | 220 | #define ENC_SUBTLV(flag, function, field) \ |
221 | do { \ | |
222 | struct bgp_attr_encap_subtlv *new; \ | |
223 | if (CHECK_FLAG(bet->valid_subtlvs, (flag))) { \ | |
224 | new = function(&bet->field); \ | |
225 | if (last) { \ | |
226 | last->next = new; \ | |
227 | } else { \ | |
228 | attr->encap_subtlvs = new; \ | |
229 | } \ | |
230 | last = new; \ | |
231 | } \ | |
232 | } while (0) | |
f4c89855 | 233 | |
d62a17ae | 234 | void bgp_encap_type_l2tpv3overip_to_tlv( |
235 | struct bgp_encap_type_l2tpv3_over_ip *bet, /* input structure */ | |
236 | struct attr *attr) | |
f4c89855 | 237 | { |
d62a17ae | 238 | struct bgp_attr_encap_subtlv *last; |
f4c89855 | 239 | |
d62a17ae | 240 | /* advance to last subtlv */ |
241 | for (last = attr->encap_subtlvs; last && last->next; last = last->next) | |
242 | ; | |
f4c89855 | 243 | |
d62a17ae | 244 | attr->encap_tunneltype = BGP_ENCAP_TYPE_L2TPV3_OVER_IP; |
f4c89855 | 245 | |
d62a17ae | 246 | assert(CHECK_FLAG(bet->valid_subtlvs, BGP_TEA_SUBTLV_ENCAP)); |
f4c89855 | 247 | |
d62a17ae | 248 | ENC_SUBTLV(BGP_TEA_SUBTLV_ENCAP, subtlv_encode_encap_l2tpv3_over_ip, |
249 | st_encap); | |
250 | ENC_SUBTLV(BGP_TEA_SUBTLV_PROTO_TYPE, subtlv_encode_proto_type, | |
251 | st_proto); | |
252 | ENC_SUBTLV(BGP_TEA_SUBTLV_COLOR, subtlv_encode_color, st_color); | |
253 | ENC_SUBTLV(BGP_TEA_SUBTLV_REMOTE_ENDPOINT, | |
254 | subtlv_encode_remote_endpoint, st_endpoint); | |
f4c89855 LB |
255 | } |
256 | ||
d62a17ae | 257 | void bgp_encap_type_gre_to_tlv( |
258 | struct bgp_encap_type_gre *bet, /* input structure */ | |
259 | struct attr *attr) | |
f4c89855 | 260 | { |
d62a17ae | 261 | struct bgp_attr_encap_subtlv *last; |
f4c89855 | 262 | |
d62a17ae | 263 | /* advance to last subtlv */ |
264 | for (last = attr->encap_subtlvs; last && last->next; last = last->next) | |
265 | ; | |
f4c89855 | 266 | |
d62a17ae | 267 | attr->encap_tunneltype = BGP_ENCAP_TYPE_GRE; |
f4c89855 | 268 | |
d62a17ae | 269 | ENC_SUBTLV(BGP_TEA_SUBTLV_ENCAP, subtlv_encode_encap_gre, st_encap); |
270 | ENC_SUBTLV(BGP_TEA_SUBTLV_PROTO_TYPE, subtlv_encode_proto_type, | |
271 | st_proto); | |
272 | ENC_SUBTLV(BGP_TEA_SUBTLV_COLOR, subtlv_encode_color, st_color); | |
273 | ENC_SUBTLV(BGP_TEA_SUBTLV_REMOTE_ENDPOINT, | |
274 | subtlv_encode_remote_endpoint, st_endpoint); | |
f4c89855 LB |
275 | } |
276 | ||
d62a17ae | 277 | void bgp_encap_type_ip_in_ip_to_tlv( |
278 | struct bgp_encap_type_ip_in_ip *bet, /* input structure */ | |
279 | struct attr *attr) | |
f4c89855 | 280 | { |
d62a17ae | 281 | struct bgp_attr_encap_subtlv *last; |
f4c89855 | 282 | |
d62a17ae | 283 | /* advance to last subtlv */ |
284 | for (last = attr->encap_subtlvs; last && last->next; last = last->next) | |
285 | ; | |
f4c89855 | 286 | |
d62a17ae | 287 | attr->encap_tunneltype = BGP_ENCAP_TYPE_IP_IN_IP; |
f4c89855 | 288 | |
d62a17ae | 289 | ENC_SUBTLV(BGP_TEA_SUBTLV_PROTO_TYPE, subtlv_encode_proto_type, |
290 | st_proto); | |
291 | ENC_SUBTLV(BGP_TEA_SUBTLV_COLOR, subtlv_encode_color, st_color); | |
292 | ENC_SUBTLV(BGP_TEA_SUBTLV_REMOTE_ENDPOINT, | |
293 | subtlv_encode_remote_endpoint, st_endpoint); | |
f4c89855 LB |
294 | } |
295 | ||
d62a17ae | 296 | void bgp_encap_type_transmit_tunnel_endpoint( |
297 | struct bgp_encap_type_transmit_tunnel_endpoint | |
298 | *bet, /* input structure */ | |
299 | struct attr *attr) | |
f4c89855 | 300 | { |
d62a17ae | 301 | struct bgp_attr_encap_subtlv *last; |
f4c89855 | 302 | |
d62a17ae | 303 | /* advance to last subtlv */ |
304 | for (last = attr->encap_subtlvs; last && last->next; last = last->next) | |
305 | ; | |
f4c89855 | 306 | |
d62a17ae | 307 | attr->encap_tunneltype = BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT; |
f4c89855 | 308 | |
d62a17ae | 309 | /* no subtlvs for this type */ |
f4c89855 LB |
310 | } |
311 | ||
d62a17ae | 312 | void bgp_encap_type_ipsec_in_tunnel_mode_to_tlv( |
313 | struct bgp_encap_type_ipsec_in_tunnel_mode *bet, /* input structure */ | |
314 | struct attr *attr) | |
f4c89855 | 315 | { |
d62a17ae | 316 | struct bgp_attr_encap_subtlv *last; |
f4c89855 | 317 | |
d62a17ae | 318 | /* advance to last subtlv */ |
319 | for (last = attr->encap_subtlvs; last && last->next; last = last->next) | |
320 | ; | |
f4c89855 | 321 | |
d62a17ae | 322 | attr->encap_tunneltype = BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE; |
f4c89855 | 323 | |
d62a17ae | 324 | ENC_SUBTLV(BGP_TEA_SUBTLV_IPSEC_TA, subtlv_encode_ipsec_ta, |
325 | st_ipsec_ta); | |
f4c89855 LB |
326 | } |
327 | ||
d62a17ae | 328 | void bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode_to_tlv( |
329 | struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode | |
330 | *bet, /* input structure */ | |
331 | struct attr *attr) | |
f4c89855 | 332 | { |
d62a17ae | 333 | struct bgp_attr_encap_subtlv *last; |
f4c89855 | 334 | |
d62a17ae | 335 | /* advance to last subtlv */ |
336 | for (last = attr->encap_subtlvs; last && last->next; last = last->next) | |
337 | ; | |
f4c89855 | 338 | |
d62a17ae | 339 | attr->encap_tunneltype = |
340 | BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE; | |
f4c89855 | 341 | |
d62a17ae | 342 | ENC_SUBTLV(BGP_TEA_SUBTLV_IPSEC_TA, subtlv_encode_ipsec_ta, |
343 | st_ipsec_ta); | |
f4c89855 LB |
344 | } |
345 | ||
d62a17ae | 346 | void bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode_to_tlv( |
347 | struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode | |
348 | *bet, /* input structure */ | |
349 | struct attr *attr) | |
f4c89855 | 350 | { |
d62a17ae | 351 | struct bgp_attr_encap_subtlv *last; |
f4c89855 | 352 | |
d62a17ae | 353 | /* advance to last subtlv */ |
354 | for (last = attr->encap_subtlvs; last && last->next; last = last->next) | |
355 | ; | |
f4c89855 | 356 | |
d62a17ae | 357 | attr->encap_tunneltype = |
358 | BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE; | |
f4c89855 | 359 | |
d62a17ae | 360 | ENC_SUBTLV(BGP_TEA_SUBTLV_IPSEC_TA, subtlv_encode_ipsec_ta, |
361 | st_ipsec_ta); | |
f4c89855 LB |
362 | } |
363 | ||
d62a17ae | 364 | void bgp_encap_type_pbb_to_tlv( |
365 | struct bgp_encap_type_pbb *bet, /* input structure */ | |
366 | struct attr *attr) | |
f4c89855 | 367 | { |
d62a17ae | 368 | struct bgp_attr_encap_subtlv *last; |
f4c89855 | 369 | |
d62a17ae | 370 | /* advance to last subtlv */ |
371 | for (last = attr->encap_subtlvs; last && last->next; last = last->next) | |
372 | ; | |
f4c89855 | 373 | |
d62a17ae | 374 | attr->encap_tunneltype = BGP_ENCAP_TYPE_PBB; |
f4c89855 | 375 | |
d62a17ae | 376 | assert(CHECK_FLAG(bet->valid_subtlvs, BGP_TEA_SUBTLV_ENCAP)); |
377 | ENC_SUBTLV(BGP_TEA_SUBTLV_ENCAP, subtlv_encode_encap_pbb, st_encap); | |
f4c89855 LB |
378 | } |
379 | ||
d62a17ae | 380 | void bgp_encap_type_vxlan_to_tlv( |
381 | struct bgp_encap_type_vxlan *bet, /* input structure */ | |
382 | struct attr *attr) | |
f4c89855 | 383 | { |
d62a17ae | 384 | struct bgp_attr_encap_subtlv *tlv; |
385 | uint32_t vnid; | |
f4c89855 | 386 | |
d62a17ae | 387 | attr->encap_tunneltype = BGP_ENCAP_TYPE_VXLAN; |
aee875b5 | 388 | |
d62a17ae | 389 | if (bet == NULL || !bet->vnid) |
390 | return; | |
0a22ddfb | 391 | XFREE(MTYPE_ENCAP_TLV, attr->encap_subtlvs); |
d62a17ae | 392 | tlv = XCALLOC(MTYPE_ENCAP_TLV, |
12f70478 | 393 | sizeof(struct bgp_attr_encap_subtlv) + 12); |
d62a17ae | 394 | tlv->type = 1; /* encapsulation type */ |
395 | tlv->length = 12; | |
396 | if (bet->vnid) { | |
397 | vnid = htonl(bet->vnid | VXLAN_ENCAP_MASK_VNID_VALID); | |
398 | memcpy(&tlv->value, &vnid, 4); | |
399 | } | |
400 | if (bet->mac_address) { | |
401 | char *ptr = (char *)&tlv->value + 4; | |
402 | memcpy(ptr, bet->mac_address, 6); | |
403 | } | |
404 | attr->encap_subtlvs = tlv; | |
405 | return; | |
f4c89855 LB |
406 | } |
407 | ||
d62a17ae | 408 | void bgp_encap_type_nvgre_to_tlv( |
409 | struct bgp_encap_type_nvgre *bet, /* input structure */ | |
410 | struct attr *attr) | |
f4c89855 | 411 | { |
d62a17ae | 412 | attr->encap_tunneltype = BGP_ENCAP_TYPE_NVGRE; |
f4c89855 LB |
413 | } |
414 | ||
d62a17ae | 415 | void bgp_encap_type_mpls_to_tlv( |
416 | struct bgp_encap_type_mpls *bet, /* input structure */ | |
417 | struct attr *attr) | |
f4c89855 | 418 | { |
d62a17ae | 419 | return; /* no encap attribute for MPLS */ |
f4c89855 LB |
420 | } |
421 | ||
d62a17ae | 422 | void bgp_encap_type_mpls_in_gre_to_tlv( |
423 | struct bgp_encap_type_mpls_in_gre *bet, /* input structure */ | |
424 | struct attr *attr) | |
f4c89855 | 425 | { |
d62a17ae | 426 | attr->encap_tunneltype = BGP_ENCAP_TYPE_MPLS_IN_GRE; |
f4c89855 LB |
427 | } |
428 | ||
d62a17ae | 429 | void bgp_encap_type_vxlan_gpe_to_tlv( |
430 | struct bgp_encap_type_vxlan_gpe *bet, /* input structure */ | |
431 | struct attr *attr) | |
f4c89855 | 432 | { |
f4c89855 | 433 | |
d62a17ae | 434 | attr->encap_tunneltype = BGP_ENCAP_TYPE_VXLAN_GPE; |
f4c89855 LB |
435 | } |
436 | ||
d62a17ae | 437 | void bgp_encap_type_mpls_in_udp_to_tlv( |
438 | struct bgp_encap_type_mpls_in_udp *bet, /* input structure */ | |
439 | struct attr *attr) | |
f4c89855 | 440 | { |
f4c89855 | 441 | |
d62a17ae | 442 | attr->encap_tunneltype = BGP_ENCAP_TYPE_MPLS_IN_UDP; |
f4c89855 LB |
443 | } |
444 | ||
445 | ||
446 | /*********************************************************************** | |
447 | * SUBTLV DECODE | |
448 | ***********************************************************************/ | |
449 | /* rfc5512 4.1 */ | |
d62a17ae | 450 | static int subtlv_decode_encap_l2tpv3_over_ip( |
451 | struct bgp_attr_encap_subtlv *subtlv, | |
452 | struct bgp_tea_subtlv_encap_l2tpv3_over_ip *st) | |
453 | { | |
454 | if (subtlv->length < 4) { | |
455 | zlog_debug("%s, subtlv length %d is less than 4", __func__, | |
456 | subtlv->length); | |
457 | return -1; | |
458 | } | |
459 | ||
937652c6 | 460 | ptr_get_be32(subtlv->value, &st->sessionid); |
d62a17ae | 461 | st->cookie_length = subtlv->length - 4; |
462 | if (st->cookie_length > sizeof(st->cookie)) { | |
463 | zlog_debug("%s, subtlv length %d is greater than %d", __func__, | |
464 | st->cookie_length, (int)sizeof(st->cookie)); | |
465 | return -1; | |
466 | } | |
467 | memcpy(st->cookie, subtlv->value + 4, st->cookie_length); | |
468 | return 0; | |
f4c89855 LB |
469 | } |
470 | ||
471 | /* rfc5512 4.1 */ | |
d62a17ae | 472 | static int subtlv_decode_encap_gre(struct bgp_attr_encap_subtlv *subtlv, |
473 | struct bgp_tea_subtlv_encap_gre_key *st) | |
474 | { | |
475 | if (subtlv->length != 4) { | |
476 | zlog_debug("%s, subtlv length %d does not equal 4", __func__, | |
477 | subtlv->length); | |
478 | return -1; | |
479 | } | |
937652c6 | 480 | ptr_get_be32(subtlv->value, &st->gre_key); |
d62a17ae | 481 | return 0; |
f4c89855 LB |
482 | } |
483 | ||
d62a17ae | 484 | static int subtlv_decode_encap_pbb(struct bgp_attr_encap_subtlv *subtlv, |
485 | struct bgp_tea_subtlv_encap_pbb *st) | |
486 | { | |
487 | if (subtlv->length != 1 + 3 + 6 + 2) { | |
488 | zlog_debug("%s, subtlv length %d does not equal %d", __func__, | |
489 | subtlv->length, 1 + 3 + 6 + 2); | |
490 | return -1; | |
491 | } | |
492 | if (subtlv->value[0] & 0x80) { | |
493 | st->flag_isid = 1; | |
494 | st->isid = (subtlv->value[1] << 16) | (subtlv->value[2] << 8) | |
495 | | subtlv->value[3]; | |
496 | } | |
497 | if (subtlv->value[0] & 0x40) { | |
498 | st->flag_vid = 1; | |
499 | st->vid = ((subtlv->value[10] & 0x0f) << 8) | subtlv->value[11]; | |
500 | } | |
501 | memcpy(st->macaddr, subtlv->value + 4, 6); | |
502 | return 0; | |
f4c89855 LB |
503 | } |
504 | ||
505 | /* rfc5512 4.2 */ | |
d62a17ae | 506 | static int subtlv_decode_proto_type(struct bgp_attr_encap_subtlv *subtlv, |
507 | struct bgp_tea_subtlv_proto_type *st) | |
f4c89855 | 508 | { |
d62a17ae | 509 | if (subtlv->length != 2) { |
510 | zlog_debug("%s, subtlv length %d does not equal 2", __func__, | |
511 | subtlv->length); | |
512 | return -1; | |
513 | } | |
514 | st->proto = (subtlv->value[0] << 8) | subtlv->value[1]; | |
515 | return 0; | |
f4c89855 LB |
516 | } |
517 | ||
518 | /* rfc5512 4.3 */ | |
d62a17ae | 519 | static int subtlv_decode_color(struct bgp_attr_encap_subtlv *subtlv, |
520 | struct bgp_tea_subtlv_color *st) | |
521 | { | |
522 | if (subtlv->length != 8) { | |
523 | zlog_debug("%s, subtlv length %d does not equal 8", __func__, | |
524 | subtlv->length); | |
525 | return -1; | |
526 | } | |
527 | if ((subtlv->value[0] != 0x03) || (subtlv->value[1] != 0x0b) | |
528 | || (subtlv->value[2] != 0) || (subtlv->value[3] != 0)) { | |
529 | zlog_debug("%s, subtlv value 1st 4 bytes are not 0x030b0000", | |
530 | __func__); | |
531 | return -1; | |
532 | } | |
937652c6 | 533 | ptr_get_be32(subtlv->value + 4, &st->color); |
d62a17ae | 534 | return 0; |
f4c89855 LB |
535 | } |
536 | ||
537 | /* rfc 5566 4. */ | |
d62a17ae | 538 | static int subtlv_decode_ipsec_ta(struct bgp_attr_encap_subtlv *subtlv, |
539 | struct bgp_tea_subtlv_ipsec_ta *st) | |
540 | { | |
541 | st->authenticator_length = subtlv->length - 2; | |
542 | if (st->authenticator_length > sizeof(st->value)) { | |
543 | zlog_debug( | |
544 | "%s, authenticator length %d exceeds storage maximum %d", | |
545 | __func__, st->authenticator_length, | |
546 | (int)sizeof(st->value)); | |
547 | return -1; | |
548 | } | |
549 | st->authenticator_type = (subtlv->value[0] << 8) | subtlv->value[1]; | |
550 | memcpy(st->value, subtlv->value + 2, st->authenticator_length); | |
551 | return 0; | |
f4c89855 LB |
552 | } |
553 | ||
587ff0fd LB |
554 | /* draft-rosen-idr-tunnel-encaps 2.1 */ |
555 | static int | |
d62a17ae | 556 | subtlv_decode_remote_endpoint(struct bgp_attr_encap_subtlv *subtlv, |
557 | struct bgp_tea_subtlv_remote_endpoint *st) | |
558 | { | |
559 | int i; | |
560 | if (subtlv->length != 8 && subtlv->length != 20) { | |
561 | zlog_debug("%s, subtlv length %d does not equal 8 or 20", | |
562 | __func__, subtlv->length); | |
563 | return -1; | |
564 | } | |
565 | if (subtlv->length == 8) { | |
566 | st->family = AF_INET; | |
8643c2e5 DA |
567 | memcpy(&st->ip_address.v4.s_addr, subtlv->value, |
568 | IPV4_MAX_BYTELEN); | |
d62a17ae | 569 | } else { |
570 | st->family = AF_INET6; | |
8643c2e5 DA |
571 | memcpy(&(st->ip_address.v6.s6_addr), subtlv->value, |
572 | IPV6_MAX_BYTELEN); | |
d62a17ae | 573 | } |
574 | i = subtlv->length - 4; | |
937652c6 | 575 | ptr_get_be32(subtlv->value + i, &st->as4); |
d62a17ae | 576 | return 0; |
587ff0fd LB |
577 | } |
578 | ||
f4c89855 LB |
579 | /*********************************************************************** |
580 | * TUNNEL TYPE-SPECIFIC TLV DECODE | |
581 | ***********************************************************************/ | |
582 | ||
d62a17ae | 583 | int tlv_to_bgp_encap_type_l2tpv3overip( |
584 | struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ | |
585 | struct bgp_encap_type_l2tpv3_over_ip *bet) /* caller-allocated */ | |
586 | { | |
587 | struct bgp_attr_encap_subtlv *st; | |
588 | int rc = 0; | |
589 | ||
590 | for (st = stlv; st; st = st->next) { | |
591 | switch (st->type) { | |
592 | case BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION: | |
593 | rc |= subtlv_decode_encap_l2tpv3_over_ip( | |
594 | st, &bet->st_encap); | |
595 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_ENCAP); | |
596 | break; | |
597 | ||
598 | case BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE: | |
599 | rc |= subtlv_decode_proto_type(st, &bet->st_proto); | |
600 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_PROTO_TYPE); | |
601 | break; | |
602 | ||
603 | case BGP_ENCAP_SUBTLV_TYPE_COLOR: | |
604 | rc |= subtlv_decode_color(st, &bet->st_color); | |
605 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_COLOR); | |
606 | break; | |
607 | ||
608 | case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: | |
609 | rc |= subtlv_decode_remote_endpoint(st, | |
610 | &bet->st_endpoint); | |
611 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); | |
612 | break; | |
613 | ||
614 | default: | |
615 | zlog_debug("%s: unexpected subtlv type %d", __func__, | |
616 | st->type); | |
617 | rc |= -1; | |
618 | break; | |
619 | } | |
f4c89855 | 620 | } |
d62a17ae | 621 | return rc; |
622 | } | |
623 | ||
624 | int tlv_to_bgp_encap_type_gre( | |
625 | struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ | |
626 | struct bgp_encap_type_gre *bet) /* caller-allocated */ | |
627 | { | |
628 | struct bgp_attr_encap_subtlv *st; | |
629 | int rc = 0; | |
630 | ||
631 | for (st = stlv; st; st = st->next) { | |
632 | switch (st->type) { | |
633 | case BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION: | |
634 | rc |= subtlv_decode_encap_gre(st, &bet->st_encap); | |
635 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_ENCAP); | |
636 | break; | |
637 | ||
638 | case BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE: | |
639 | rc |= subtlv_decode_proto_type(st, &bet->st_proto); | |
640 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_PROTO_TYPE); | |
641 | break; | |
642 | ||
643 | case BGP_ENCAP_SUBTLV_TYPE_COLOR: | |
644 | rc |= subtlv_decode_color(st, &bet->st_color); | |
645 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_COLOR); | |
646 | break; | |
647 | ||
648 | case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: | |
649 | rc |= subtlv_decode_remote_endpoint(st, | |
650 | &bet->st_endpoint); | |
651 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); | |
652 | break; | |
653 | ||
654 | default: | |
655 | zlog_debug("%s: unexpected subtlv type %d", __func__, | |
656 | st->type); | |
657 | rc |= -1; | |
658 | break; | |
659 | } | |
f4c89855 | 660 | } |
d62a17ae | 661 | return rc; |
662 | } | |
663 | ||
664 | int tlv_to_bgp_encap_type_ip_in_ip( | |
665 | struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ | |
666 | struct bgp_encap_type_ip_in_ip *bet) /* caller-allocated */ | |
667 | { | |
668 | struct bgp_attr_encap_subtlv *st; | |
669 | int rc = 0; | |
670 | ||
671 | for (st = stlv; st; st = st->next) { | |
672 | switch (st->type) { | |
673 | case BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE: | |
674 | rc |= subtlv_decode_proto_type(st, &bet->st_proto); | |
675 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_PROTO_TYPE); | |
676 | break; | |
677 | ||
678 | case BGP_ENCAP_SUBTLV_TYPE_COLOR: | |
679 | rc |= subtlv_decode_color(st, &bet->st_color); | |
680 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_COLOR); | |
681 | break; | |
682 | ||
683 | case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: | |
684 | rc |= subtlv_decode_remote_endpoint(st, | |
685 | &bet->st_endpoint); | |
686 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); | |
687 | break; | |
688 | ||
689 | default: | |
690 | zlog_debug("%s: unexpected subtlv type %d", __func__, | |
691 | st->type); | |
692 | rc |= -1; | |
693 | break; | |
694 | } | |
f4c89855 | 695 | } |
d62a17ae | 696 | return rc; |
f4c89855 LB |
697 | } |
698 | ||
d62a17ae | 699 | int tlv_to_bgp_encap_type_transmit_tunnel_endpoint( |
700 | struct bgp_attr_encap_subtlv *stlv, | |
701 | struct bgp_encap_type_transmit_tunnel_endpoint *bet) | |
f4c89855 | 702 | { |
d62a17ae | 703 | struct bgp_attr_encap_subtlv *st; |
704 | int rc = 0; | |
f4c89855 | 705 | |
d62a17ae | 706 | for (st = stlv; st; st = st->next) { |
707 | switch (st->type) { | |
587ff0fd | 708 | |
d62a17ae | 709 | case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: |
710 | rc |= subtlv_decode_remote_endpoint(st, | |
711 | &bet->st_endpoint); | |
712 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); | |
713 | break; | |
587ff0fd | 714 | |
d62a17ae | 715 | default: |
716 | zlog_debug("%s: unexpected subtlv type %d", __func__, | |
717 | st->type); | |
718 | rc |= -1; | |
719 | break; | |
720 | } | |
f4c89855 | 721 | } |
d62a17ae | 722 | return rc; |
723 | } | |
724 | ||
725 | int tlv_to_bgp_encap_type_ipsec_in_tunnel_mode( | |
726 | struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ | |
727 | struct bgp_encap_type_ipsec_in_tunnel_mode *bet) /* caller-allocated */ | |
728 | { | |
729 | struct bgp_attr_encap_subtlv *st; | |
730 | int rc = 0; | |
731 | ||
732 | for (st = stlv; st; st = st->next) { | |
733 | switch (st->type) { | |
734 | case BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA: | |
735 | rc |= subtlv_decode_ipsec_ta(st, &bet->st_ipsec_ta); | |
736 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_IPSEC_TA); | |
737 | break; | |
738 | ||
739 | case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: | |
740 | rc |= subtlv_decode_remote_endpoint(st, | |
741 | &bet->st_endpoint); | |
742 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); | |
743 | break; | |
744 | ||
745 | default: | |
746 | zlog_debug("%s: unexpected subtlv type %d", __func__, | |
747 | st->type); | |
748 | rc |= -1; | |
749 | break; | |
750 | } | |
f4c89855 | 751 | } |
d62a17ae | 752 | return rc; |
753 | } | |
754 | ||
755 | int tlv_to_bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode( | |
756 | struct bgp_attr_encap_subtlv *stlv, | |
757 | struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet) | |
758 | { | |
759 | struct bgp_attr_encap_subtlv *st; | |
760 | int rc = 0; | |
761 | ||
762 | for (st = stlv; st; st = st->next) { | |
763 | switch (st->type) { | |
764 | case BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA: | |
765 | rc |= subtlv_decode_ipsec_ta(st, &bet->st_ipsec_ta); | |
766 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_IPSEC_TA); | |
767 | break; | |
768 | ||
769 | case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: | |
770 | rc |= subtlv_decode_remote_endpoint(st, | |
771 | &bet->st_endpoint); | |
772 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); | |
773 | break; | |
774 | ||
775 | default: | |
776 | zlog_debug("%s: unexpected subtlv type %d", __func__, | |
777 | st->type); | |
778 | rc |= -1; | |
779 | break; | |
780 | } | |
f4c89855 | 781 | } |
d62a17ae | 782 | return rc; |
783 | } | |
784 | ||
785 | int tlv_to_bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode( | |
786 | struct bgp_attr_encap_subtlv *stlv, | |
787 | struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet) | |
788 | { | |
789 | struct bgp_attr_encap_subtlv *st; | |
790 | int rc = 0; | |
791 | ||
792 | for (st = stlv; st; st = st->next) { | |
793 | switch (st->type) { | |
794 | case BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA: | |
795 | rc |= subtlv_decode_ipsec_ta(st, &bet->st_ipsec_ta); | |
796 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_IPSEC_TA); | |
797 | break; | |
798 | ||
799 | case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: | |
800 | rc |= subtlv_decode_remote_endpoint(st, | |
801 | &bet->st_endpoint); | |
802 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); | |
803 | break; | |
804 | ||
805 | default: | |
806 | zlog_debug("%s: unexpected subtlv type %d", __func__, | |
807 | st->type); | |
808 | rc |= -1; | |
809 | break; | |
810 | } | |
f4c89855 | 811 | } |
d62a17ae | 812 | return rc; |
f4c89855 LB |
813 | } |
814 | ||
d62a17ae | 815 | int tlv_to_bgp_encap_type_vxlan(struct bgp_attr_encap_subtlv *stlv, |
816 | struct bgp_encap_type_vxlan *bet) | |
f4c89855 | 817 | { |
d62a17ae | 818 | struct bgp_attr_encap_subtlv *st; |
819 | int rc = 0; | |
f4c89855 | 820 | |
d62a17ae | 821 | for (st = stlv; st; st = st->next) { |
822 | switch (st->type) { | |
587ff0fd | 823 | |
d62a17ae | 824 | case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: |
825 | rc |= subtlv_decode_remote_endpoint(st, | |
826 | &bet->st_endpoint); | |
827 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); | |
828 | break; | |
587ff0fd | 829 | |
d62a17ae | 830 | default: |
831 | zlog_debug("%s: unexpected subtlv type %d", __func__, | |
832 | st->type); | |
833 | rc |= -1; | |
834 | break; | |
835 | } | |
f4c89855 | 836 | } |
d62a17ae | 837 | return rc; |
f4c89855 LB |
838 | } |
839 | ||
d62a17ae | 840 | int tlv_to_bgp_encap_type_nvgre(struct bgp_attr_encap_subtlv *stlv, |
841 | struct bgp_encap_type_nvgre *bet) | |
f4c89855 | 842 | { |
d62a17ae | 843 | struct bgp_attr_encap_subtlv *st; |
844 | int rc = 0; | |
f4c89855 | 845 | |
d62a17ae | 846 | for (st = stlv; st; st = st->next) { |
847 | switch (st->type) { | |
587ff0fd | 848 | |
d62a17ae | 849 | case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: |
850 | rc |= subtlv_decode_remote_endpoint(st, | |
851 | &bet->st_endpoint); | |
852 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); | |
853 | break; | |
587ff0fd | 854 | |
d62a17ae | 855 | default: |
856 | zlog_debug("%s: unexpected subtlv type %d", __func__, | |
857 | st->type); | |
858 | rc |= -1; | |
859 | break; | |
860 | } | |
f4c89855 | 861 | } |
d62a17ae | 862 | return rc; |
f4c89855 LB |
863 | } |
864 | ||
d62a17ae | 865 | int tlv_to_bgp_encap_type_mpls(struct bgp_attr_encap_subtlv *stlv, |
866 | struct bgp_encap_type_mpls *bet) | |
f4c89855 | 867 | { |
d62a17ae | 868 | struct bgp_attr_encap_subtlv *st; |
869 | int rc = 0; | |
f4c89855 | 870 | |
d62a17ae | 871 | for (st = stlv; st; st = st->next) { |
872 | switch (st->type) { | |
587ff0fd | 873 | |
d62a17ae | 874 | case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: |
875 | rc |= subtlv_decode_remote_endpoint(st, | |
876 | &bet->st_endpoint); | |
877 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); | |
878 | break; | |
587ff0fd | 879 | |
d62a17ae | 880 | default: |
881 | zlog_debug("%s: unexpected subtlv type %d", __func__, | |
882 | st->type); | |
883 | rc |= -1; | |
884 | break; | |
885 | } | |
f4c89855 | 886 | } |
d62a17ae | 887 | return rc; |
f4c89855 LB |
888 | } |
889 | ||
d62a17ae | 890 | int tlv_to_bgp_encap_type_mpls_in_gre(struct bgp_attr_encap_subtlv *stlv, |
891 | struct bgp_encap_type_mpls_in_gre *bet) | |
f4c89855 | 892 | { |
d62a17ae | 893 | struct bgp_attr_encap_subtlv *st; |
894 | int rc = 0; | |
f4c89855 | 895 | |
d62a17ae | 896 | for (st = stlv; st; st = st->next) { |
897 | switch (st->type) { | |
587ff0fd | 898 | |
d62a17ae | 899 | case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: |
900 | rc |= subtlv_decode_remote_endpoint(st, | |
901 | &bet->st_endpoint); | |
902 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); | |
903 | break; | |
587ff0fd | 904 | |
d62a17ae | 905 | default: |
906 | zlog_debug("%s: unexpected subtlv type %d", __func__, | |
907 | st->type); | |
908 | rc |= -1; | |
909 | break; | |
910 | } | |
f4c89855 | 911 | } |
d62a17ae | 912 | return rc; |
f4c89855 LB |
913 | } |
914 | ||
d62a17ae | 915 | int tlv_to_bgp_encap_type_vxlan_gpe(struct bgp_attr_encap_subtlv *stlv, |
916 | struct bgp_encap_type_vxlan_gpe *bet) | |
f4c89855 | 917 | { |
d62a17ae | 918 | struct bgp_attr_encap_subtlv *st; |
919 | int rc = 0; | |
f4c89855 | 920 | |
d62a17ae | 921 | for (st = stlv; st; st = st->next) { |
922 | switch (st->type) { | |
587ff0fd | 923 | |
d62a17ae | 924 | case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: |
925 | rc |= subtlv_decode_remote_endpoint(st, | |
926 | &bet->st_endpoint); | |
927 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); | |
928 | break; | |
587ff0fd | 929 | |
d62a17ae | 930 | default: |
931 | zlog_debug("%s: unexpected subtlv type %d", __func__, | |
932 | st->type); | |
933 | rc |= -1; | |
934 | break; | |
935 | } | |
f4c89855 | 936 | } |
d62a17ae | 937 | return rc; |
f4c89855 LB |
938 | } |
939 | ||
d62a17ae | 940 | int tlv_to_bgp_encap_type_mpls_in_udp(struct bgp_attr_encap_subtlv *stlv, |
941 | struct bgp_encap_type_mpls_in_udp *bet) | |
f4c89855 | 942 | { |
d62a17ae | 943 | struct bgp_attr_encap_subtlv *st; |
944 | int rc = 0; | |
f4c89855 | 945 | |
d62a17ae | 946 | for (st = stlv; st; st = st->next) { |
947 | switch (st->type) { | |
587ff0fd | 948 | |
d62a17ae | 949 | case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: |
950 | rc |= subtlv_decode_remote_endpoint(st, | |
951 | &bet->st_endpoint); | |
952 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); | |
953 | break; | |
587ff0fd | 954 | |
d62a17ae | 955 | default: |
956 | zlog_debug("%s: unexpected subtlv type %d", __func__, | |
957 | st->type); | |
958 | rc |= -1; | |
959 | break; | |
960 | } | |
f4c89855 | 961 | } |
d62a17ae | 962 | return rc; |
963 | } | |
964 | ||
965 | int tlv_to_bgp_encap_type_pbb( | |
966 | struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ | |
967 | struct bgp_encap_type_pbb *bet) /* caller-allocated */ | |
968 | { | |
969 | struct bgp_attr_encap_subtlv *st; | |
970 | int rc = 0; | |
971 | ||
972 | for (st = stlv; st; st = st->next) { | |
973 | switch (st->type) { | |
974 | case BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION: | |
975 | rc |= subtlv_decode_encap_pbb(st, &bet->st_encap); | |
976 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_ENCAP); | |
977 | break; | |
978 | ||
979 | case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: | |
980 | rc |= subtlv_decode_remote_endpoint(st, | |
981 | &bet->st_endpoint); | |
982 | SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); | |
983 | break; | |
984 | ||
985 | default: | |
986 | zlog_debug("%s: unexpected subtlv type %d", __func__, | |
987 | st->type); | |
988 | rc |= -1; | |
989 | break; | |
990 | } | |
f4c89855 | 991 | } |
d62a17ae | 992 | return rc; |
f4c89855 | 993 | } |