back to topotato report
topotato coverage report
Current view: top level - bgpd - bgp_encap_tlv.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 0 518 0.0 %
Date: 2023-02-24 14:41:08 Functions: 0 42 0.0 %

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

Generated by: LCOV version v1.16-topotato