back to topotato report
topotato coverage report
Current view: top level - bfdd - config.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 3 312 1.0 %
Date: 2023-02-24 19:38:44 Functions: 3 19 15.8 %

          Line data    Source code
       1             : /*********************************************************************
       2             :  * Copyright 2017-2018 Network Device Education Foundation, Inc. ("NetDEF")
       3             :  *
       4             :  * This program is free software; you can redistribute it and/or modify it
       5             :  * under the terms of the GNU General Public License as published by the Free
       6             :  * Software Foundation; either version 2 of the License, or (at your option)
       7             :  * any later version.
       8             :  *
       9             :  * This program is distributed in the hope that it will be useful, but WITHOUT
      10             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      11             :  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
      12             :  * 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             :  * config.c: implements the BFD daemon configuration handling.
      19             :  *
      20             :  * Authors
      21             :  * -------
      22             :  * Rafael Zalamena <rzalamena@opensourcerouting.org>
      23             :  */
      24             : 
      25             : #include <zebra.h>
      26             : 
      27             : #include <string.h>
      28             : 
      29             : #include "lib/json.h"
      30             : 
      31             : #include "bfd.h"
      32             : 
      33          24 : DEFINE_MTYPE_STATIC(BFDD, BFDD_LABEL, "long-lived label memory");
      34             : 
      35             : /*
      36             :  * Definitions
      37             :  */
      38             : enum peer_list_type {
      39             :         PLT_IPV4,
      40             :         PLT_IPV6,
      41             :         PLT_LABEL,
      42             : };
      43             : 
      44             : 
      45             : /*
      46             :  * Prototypes
      47             :  */
      48             : static int parse_config_json(struct json_object *jo, bpc_handle h, void *arg);
      49             : static int parse_list(struct json_object *jo, enum peer_list_type plt,
      50             :                       bpc_handle h, void *arg);
      51             : static int parse_peer_config(struct json_object *jo, struct bfd_peer_cfg *bpc);
      52             : static int parse_peer_label_config(struct json_object *jo,
      53             :                                    struct bfd_peer_cfg *bpc);
      54             : 
      55             : static int config_add(struct bfd_peer_cfg *bpc, void *arg);
      56             : static int config_del(struct bfd_peer_cfg *bpc, void *arg);
      57             : 
      58             : static int json_object_add_peer(struct json_object *jo, struct bfd_session *bs);
      59             : 
      60             : 
      61             : /*
      62             :  * Implementation
      63             :  */
      64           0 : static int config_add(struct bfd_peer_cfg *bpc,
      65             :                       void *arg __attribute__((unused)))
      66             : {
      67           0 :         return ptm_bfd_sess_new(bpc) == NULL;
      68             : }
      69             : 
      70           0 : static int config_del(struct bfd_peer_cfg *bpc,
      71             :                       void *arg __attribute__((unused)))
      72             : {
      73           0 :         return ptm_bfd_sess_del(bpc) != 0;
      74             : }
      75             : 
      76           0 : static int parse_config_json(struct json_object *jo, bpc_handle h, void *arg)
      77             : {
      78           0 :         const char *key, *sval;
      79           0 :         struct json_object *jo_val;
      80           0 :         struct json_object_iterator joi, join;
      81           0 :         int error = 0;
      82             : 
      83           0 :         JSON_FOREACH (jo, joi, join) {
      84           0 :                 key = json_object_iter_peek_name(&joi);
      85           0 :                 jo_val = json_object_iter_peek_value(&joi);
      86             : 
      87           0 :                 if (strcmp(key, "ipv4") == 0) {
      88           0 :                         error += parse_list(jo_val, PLT_IPV4, h, arg);
      89           0 :                 } else if (strcmp(key, "ipv6") == 0) {
      90           0 :                         error += parse_list(jo_val, PLT_IPV6, h, arg);
      91           0 :                 } else if (strcmp(key, "label") == 0) {
      92           0 :                         error += parse_list(jo_val, PLT_LABEL, h, arg);
      93             :                 } else {
      94           0 :                         sval = json_object_get_string(jo_val);
      95           0 :                         zlog_warn("%s:%d invalid configuration: %s", __func__,
      96             :                                   __LINE__, sval);
      97           0 :                         error++;
      98             :                 }
      99             :         }
     100             : 
     101             :         /*
     102             :          * Our callers never call free() on json_object and only expect
     103             :          * the return value, so lets free() it here.
     104             :          */
     105           0 :         json_object_put(jo);
     106             : 
     107           0 :         return error;
     108             : }
     109             : 
     110           0 : int parse_config(const char *fname)
     111             : {
     112           0 :         struct json_object *jo;
     113             : 
     114           0 :         jo = json_object_from_file(fname);
     115           0 :         if (jo == NULL)
     116             :                 return -1;
     117             : 
     118           0 :         return parse_config_json(jo, config_add, NULL);
     119             : }
     120             : 
     121           0 : static int parse_list(struct json_object *jo, enum peer_list_type plt,
     122             :                       bpc_handle h, void *arg)
     123             : {
     124           0 :         struct json_object *jo_val;
     125           0 :         struct bfd_peer_cfg bpc;
     126           0 :         int allen, idx;
     127           0 :         int error = 0, result;
     128             : 
     129           0 :         allen = json_object_array_length(jo);
     130           0 :         for (idx = 0; idx < allen; idx++) {
     131           0 :                 jo_val = json_object_array_get_idx(jo, idx);
     132             : 
     133             :                 /* Set defaults. */
     134           0 :                 memset(&bpc, 0, sizeof(bpc));
     135           0 :                 bpc.bpc_detectmultiplier = BFD_DEFDETECTMULT;
     136           0 :                 bpc.bpc_recvinterval = BFD_DEFREQUIREDMINRX;
     137           0 :                 bpc.bpc_txinterval = BFD_DEFDESIREDMINTX;
     138           0 :                 bpc.bpc_echorecvinterval = BFD_DEF_REQ_MIN_ECHO_RX;
     139           0 :                 bpc.bpc_echotxinterval = BFD_DEF_DES_MIN_ECHO_TX;
     140             : 
     141           0 :                 switch (plt) {
     142           0 :                 case PLT_IPV4:
     143           0 :                         zlog_debug("ipv4 peers %d:", allen);
     144           0 :                         bpc.bpc_ipv4 = true;
     145           0 :                         break;
     146           0 :                 case PLT_IPV6:
     147           0 :                         zlog_debug("ipv6 peers %d:", allen);
     148           0 :                         bpc.bpc_ipv4 = false;
     149           0 :                         break;
     150           0 :                 case PLT_LABEL:
     151           0 :                         zlog_debug("label peers %d:", allen);
     152           0 :                         if (parse_peer_label_config(jo_val, &bpc) != 0) {
     153           0 :                                 error++;
     154           0 :                                 continue;
     155             :                         }
     156             :                         break;
     157             : 
     158           0 :                 default:
     159           0 :                         error++;
     160           0 :                         zlog_err("%s:%d: unsupported peer type", __func__,
     161             :                                  __LINE__);
     162           0 :                         break;
     163             :                 }
     164             : 
     165           0 :                 result = parse_peer_config(jo_val, &bpc);
     166           0 :                 error += result;
     167           0 :                 if (result == 0)
     168           0 :                         error += (h(&bpc, arg) != 0);
     169             :         }
     170             : 
     171           0 :         return error;
     172             : }
     173             : 
     174           0 : static int parse_peer_config(struct json_object *jo, struct bfd_peer_cfg *bpc)
     175             : {
     176           0 :         const char *key, *sval;
     177           0 :         struct json_object *jo_val;
     178           0 :         struct json_object_iterator joi, join;
     179           0 :         int family_type = (bpc->bpc_ipv4) ? AF_INET : AF_INET6;
     180           0 :         int error = 0;
     181             : 
     182           0 :         zlog_debug("        peer: %s", bpc->bpc_ipv4 ? "ipv4" : "ipv6");
     183             : 
     184           0 :         JSON_FOREACH (jo, joi, join) {
     185           0 :                 key = json_object_iter_peek_name(&joi);
     186           0 :                 jo_val = json_object_iter_peek_value(&joi);
     187             : 
     188           0 :                 if (strcmp(key, "multihop") == 0) {
     189           0 :                         bpc->bpc_mhop = json_object_get_boolean(jo_val);
     190           0 :                         zlog_debug("        multihop: %s",
     191             :                                    bpc->bpc_mhop ? "true" : "false");
     192           0 :                 } else if (strcmp(key, "peer-address") == 0) {
     193           0 :                         sval = json_object_get_string(jo_val);
     194           0 :                         if (strtosa(sval, &bpc->bpc_peer) != 0
     195           0 :                             || bpc->bpc_peer.sa_sin.sin_family != family_type) {
     196           0 :                                 zlog_debug(
     197             :                                         "%s:%d failed to parse peer-address '%s'",
     198             :                                         __func__, __LINE__, sval);
     199           0 :                                 error++;
     200             :                         }
     201           0 :                         zlog_debug("        peer-address: %s", sval);
     202           0 :                 } else if (strcmp(key, "local-address") == 0) {
     203           0 :                         sval = json_object_get_string(jo_val);
     204           0 :                         if (strtosa(sval, &bpc->bpc_local) != 0
     205           0 :                             || bpc->bpc_local.sa_sin.sin_family
     206             :                                        != family_type) {
     207           0 :                                 zlog_debug(
     208             :                                         "%s:%d failed to parse local-address '%s'",
     209             :                                         __func__, __LINE__, sval);
     210           0 :                                 error++;
     211             :                         }
     212           0 :                         zlog_debug("        local-address: %s", sval);
     213           0 :                 } else if (strcmp(key, "local-interface") == 0) {
     214           0 :                         bpc->bpc_has_localif = true;
     215           0 :                         sval = json_object_get_string(jo_val);
     216           0 :                         if (strlcpy(bpc->bpc_localif, sval,
     217             :                                     sizeof(bpc->bpc_localif))
     218             :                             > sizeof(bpc->bpc_localif)) {
     219           0 :                                 zlog_debug(
     220             :                                         "        local-interface: %s (truncated)",
     221             :                                         sval);
     222           0 :                                 error++;
     223             :                         } else {
     224           0 :                                 zlog_debug("        local-interface: %s", sval);
     225             :                         }
     226           0 :                 } else if (strcmp(key, "vrf-name") == 0) {
     227           0 :                         bpc->bpc_has_vrfname = true;
     228           0 :                         sval = json_object_get_string(jo_val);
     229           0 :                         if (strlcpy(bpc->bpc_vrfname, sval,
     230             :                                     sizeof(bpc->bpc_vrfname))
     231             :                             > sizeof(bpc->bpc_vrfname)) {
     232           0 :                                 zlog_debug("        vrf-name: %s (truncated)",
     233             :                                            sval);
     234           0 :                                 error++;
     235             :                         } else {
     236           0 :                                 zlog_debug("        vrf-name: %s", sval);
     237             :                         }
     238           0 :                 } else if (strcmp(key, "detect-multiplier") == 0) {
     239           0 :                         bpc->bpc_detectmultiplier =
     240           0 :                                 json_object_get_int64(jo_val);
     241           0 :                         bpc->bpc_has_detectmultiplier = true;
     242           0 :                         zlog_debug("        detect-multiplier: %u",
     243             :                                    bpc->bpc_detectmultiplier);
     244           0 :                 } else if (strcmp(key, "receive-interval") == 0) {
     245           0 :                         bpc->bpc_recvinterval = json_object_get_int64(jo_val);
     246           0 :                         bpc->bpc_has_recvinterval = true;
     247           0 :                         zlog_debug("        receive-interval: %" PRIu64,
     248             :                                    bpc->bpc_recvinterval);
     249           0 :                 } else if (strcmp(key, "transmit-interval") == 0) {
     250           0 :                         bpc->bpc_txinterval = json_object_get_int64(jo_val);
     251           0 :                         bpc->bpc_has_txinterval = true;
     252           0 :                         zlog_debug("        transmit-interval: %" PRIu64,
     253             :                                    bpc->bpc_txinterval);
     254           0 :                 } else if (strcmp(key, "echo-receive-interval") == 0) {
     255           0 :                         bpc->bpc_echorecvinterval = json_object_get_int64(jo_val);
     256           0 :                         bpc->bpc_has_echorecvinterval = true;
     257           0 :                         zlog_debug("        echo-receive-interval: %" PRIu64,
     258             :                                    bpc->bpc_echorecvinterval);
     259           0 :                 } else if (strcmp(key, "echo-transmit-interval") == 0) {
     260           0 :                         bpc->bpc_echotxinterval = json_object_get_int64(jo_val);
     261           0 :                         bpc->bpc_has_echotxinterval = true;
     262           0 :                         zlog_debug("        echo-transmit-interval: %" PRIu64,
     263             :                                    bpc->bpc_echotxinterval);
     264           0 :                 } else if (strcmp(key, "create-only") == 0) {
     265           0 :                         bpc->bpc_createonly = json_object_get_boolean(jo_val);
     266           0 :                         zlog_debug("        create-only: %s",
     267             :                                    bpc->bpc_createonly ? "true" : "false");
     268           0 :                 } else if (strcmp(key, "shutdown") == 0) {
     269           0 :                         bpc->bpc_shutdown = json_object_get_boolean(jo_val);
     270           0 :                         zlog_debug("        shutdown: %s",
     271             :                                    bpc->bpc_shutdown ? "true" : "false");
     272           0 :                 } else if (strcmp(key, "echo-mode") == 0) {
     273           0 :                         bpc->bpc_echo = json_object_get_boolean(jo_val);
     274           0 :                         zlog_debug("        echo-mode: %s",
     275             :                                    bpc->bpc_echo ? "true" : "false");
     276           0 :                 } else if (strcmp(key, "label") == 0) {
     277           0 :                         bpc->bpc_has_label = true;
     278           0 :                         sval = json_object_get_string(jo_val);
     279           0 :                         if (strlcpy(bpc->bpc_label, sval,
     280             :                                     sizeof(bpc->bpc_label))
     281             :                             > sizeof(bpc->bpc_label)) {
     282           0 :                                 zlog_debug("        label: %s (truncated)",
     283             :                                            sval);
     284           0 :                                 error++;
     285             :                         } else {
     286           0 :                                 zlog_debug("        label: %s", sval);
     287             :                         }
     288             :                 } else {
     289           0 :                         sval = json_object_get_string(jo_val);
     290           0 :                         zlog_warn("%s:%d invalid configuration: '%s: %s'",
     291             :                                   __func__, __LINE__, key, sval);
     292           0 :                         error++;
     293             :                 }
     294             :         }
     295             : 
     296           0 :         if (bpc->bpc_peer.sa_sin.sin_family == 0) {
     297           0 :                 zlog_debug("%s:%d no peer address provided", __func__,
     298             :                            __LINE__);
     299           0 :                 error++;
     300             :         }
     301             : 
     302           0 :         return error;
     303             : }
     304             : 
     305           0 : static int parse_peer_label_config(struct json_object *jo,
     306             :                                    struct bfd_peer_cfg *bpc)
     307             : {
     308           0 :         struct peer_label *pl;
     309           0 :         struct json_object *label;
     310           0 :         const char *sval;
     311             : 
     312             :         /* Get label and translate it to BFD daemon key. */
     313           0 :         if (!json_object_object_get_ex(jo, "label", &label))
     314             :                 return 1;
     315             : 
     316           0 :         sval = json_object_get_string(label);
     317             : 
     318           0 :         pl = pl_find(sval);
     319           0 :         if (pl == NULL)
     320             :                 return 1;
     321             : 
     322           0 :         zlog_debug("        peer-label: %s", sval);
     323             : 
     324             :         /* Translate the label into BFD address keys. */
     325           0 :         bs_to_bpc(pl->pl_bs, bpc);
     326             : 
     327           0 :         return 0;
     328             : }
     329             : 
     330             : 
     331             : /*
     332             :  * Control socket JSON parsing.
     333             :  */
     334           0 : int config_request_add(const char *jsonstr)
     335             : {
     336           0 :         struct json_object *jo;
     337             : 
     338           0 :         jo = json_tokener_parse(jsonstr);
     339           0 :         if (jo == NULL)
     340             :                 return -1;
     341             : 
     342           0 :         return parse_config_json(jo, config_add, NULL);
     343             : }
     344             : 
     345           0 : int config_request_del(const char *jsonstr)
     346             : {
     347           0 :         struct json_object *jo;
     348             : 
     349           0 :         jo = json_tokener_parse(jsonstr);
     350           0 :         if (jo == NULL)
     351             :                 return -1;
     352             : 
     353           0 :         return parse_config_json(jo, config_del, NULL);
     354             : }
     355             : 
     356           0 : char *config_response(const char *status, const char *error)
     357             : {
     358           0 :         struct json_object *resp, *jo;
     359           0 :         char *jsonstr;
     360             : 
     361           0 :         resp = json_object_new_object();
     362           0 :         if (resp == NULL)
     363             :                 return NULL;
     364             : 
     365             :         /* Add 'status' response key. */
     366           0 :         jo = json_object_new_string(status);
     367           0 :         if (jo == NULL) {
     368           0 :                 json_object_put(resp);
     369           0 :                 return NULL;
     370             :         }
     371             : 
     372           0 :         json_object_object_add(resp, "status", jo);
     373             : 
     374             :         /* Add 'error' response key. */
     375           0 :         if (error != NULL) {
     376           0 :                 jo = json_object_new_string(error);
     377           0 :                 if (jo == NULL) {
     378           0 :                         json_object_put(resp);
     379           0 :                         return NULL;
     380             :                 }
     381             : 
     382           0 :                 json_object_object_add(resp, "error", jo);
     383             :         }
     384             : 
     385             :         /* Generate JSON response. */
     386           0 :         jsonstr = XSTRDUP(
     387             :                 MTYPE_BFDD_NOTIFICATION,
     388             :                 json_object_to_json_string_ext(resp, BFDD_JSON_CONV_OPTIONS));
     389           0 :         json_object_put(resp);
     390             : 
     391           0 :         return jsonstr;
     392             : }
     393             : 
     394           0 : char *config_notify(struct bfd_session *bs)
     395             : {
     396           0 :         struct json_object *resp;
     397           0 :         char *jsonstr;
     398           0 :         time_t now;
     399             : 
     400           0 :         resp = json_object_new_object();
     401           0 :         if (resp == NULL)
     402             :                 return NULL;
     403             : 
     404           0 :         json_object_string_add(resp, "op", BCM_NOTIFY_PEER_STATUS);
     405             : 
     406           0 :         json_object_add_peer(resp, bs);
     407             : 
     408             :         /* Add status information */
     409           0 :         json_object_int_add(resp, "id", bs->discrs.my_discr);
     410           0 :         json_object_int_add(resp, "remote-id", bs->discrs.my_discr);
     411             : 
     412           0 :         switch (bs->ses_state) {
     413           0 :         case PTM_BFD_UP:
     414           0 :                 json_object_string_add(resp, "state", "up");
     415             : 
     416           0 :                 now = monotime(NULL);
     417           0 :                 json_object_int_add(resp, "uptime", now - bs->uptime.tv_sec);
     418           0 :                 break;
     419           0 :         case PTM_BFD_ADM_DOWN:
     420           0 :                 json_object_string_add(resp, "state", "adm-down");
     421           0 :                 break;
     422           0 :         case PTM_BFD_DOWN:
     423           0 :                 json_object_string_add(resp, "state", "down");
     424             : 
     425           0 :                 now = monotime(NULL);
     426           0 :                 json_object_int_add(resp, "downtime",
     427           0 :                                     now - bs->downtime.tv_sec);
     428           0 :                 break;
     429           0 :         case PTM_BFD_INIT:
     430           0 :                 json_object_string_add(resp, "state", "init");
     431           0 :                 break;
     432             : 
     433           0 :         default:
     434           0 :                 json_object_string_add(resp, "state", "unknown");
     435           0 :                 break;
     436             :         }
     437             : 
     438           0 :         json_object_int_add(resp, "diagnostics", bs->local_diag);
     439           0 :         json_object_int_add(resp, "remote-diagnostics", bs->remote_diag);
     440             : 
     441             :         /* Generate JSON response. */
     442           0 :         jsonstr = XSTRDUP(
     443             :                 MTYPE_BFDD_NOTIFICATION,
     444             :                 json_object_to_json_string_ext(resp, BFDD_JSON_CONV_OPTIONS));
     445           0 :         json_object_put(resp);
     446             : 
     447           0 :         return jsonstr;
     448             : }
     449             : 
     450           0 : char *config_notify_config(const char *op, struct bfd_session *bs)
     451             : {
     452           0 :         struct json_object *resp;
     453           0 :         char *jsonstr;
     454             : 
     455           0 :         resp = json_object_new_object();
     456           0 :         if (resp == NULL)
     457             :                 return NULL;
     458             : 
     459           0 :         json_object_string_add(resp, "op", op);
     460             : 
     461           0 :         json_object_add_peer(resp, bs);
     462             : 
     463             :         /* On peer deletion we don't need to add any additional information. */
     464           0 :         if (strcmp(op, BCM_NOTIFY_CONFIG_DELETE) == 0)
     465           0 :                 goto skip_config;
     466             : 
     467           0 :         json_object_int_add(resp, "detect-multiplier", bs->detect_mult);
     468           0 :         json_object_int_add(resp, "receive-interval",
     469           0 :                             bs->timers.required_min_rx / 1000);
     470           0 :         json_object_int_add(resp, "transmit-interval",
     471           0 :                             bs->timers.desired_min_tx / 1000);
     472           0 :         json_object_int_add(resp, "echo-receive-interval",
     473           0 :                             bs->timers.required_min_echo_rx / 1000);
     474           0 :         json_object_int_add(resp, "echo-transmit-interval",
     475           0 :                             bs->timers.desired_min_echo_tx / 1000);
     476             : 
     477           0 :         json_object_int_add(resp, "remote-detect-multiplier",
     478           0 :                             bs->remote_detect_mult);
     479           0 :         json_object_int_add(resp, "remote-receive-interval",
     480           0 :                             bs->remote_timers.required_min_rx / 1000);
     481           0 :         json_object_int_add(resp, "remote-transmit-interval",
     482           0 :                             bs->remote_timers.desired_min_tx / 1000);
     483           0 :         json_object_int_add(resp, "remote-echo-receive-interval",
     484           0 :                             bs->remote_timers.required_min_echo / 1000);
     485             : 
     486           0 :         if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO))
     487           0 :                 json_object_boolean_true_add(resp, "echo-mode");
     488             :         else
     489           0 :                 json_object_boolean_false_add(resp, "echo-mode");
     490             : 
     491           0 :         if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN))
     492           0 :                 json_object_boolean_true_add(resp, "shutdown");
     493             :         else
     494           0 :                 json_object_boolean_false_add(resp, "shutdown");
     495             : 
     496           0 : skip_config:
     497             :         /* Generate JSON response. */
     498           0 :         jsonstr = XSTRDUP(
     499             :                 MTYPE_BFDD_NOTIFICATION,
     500             :                 json_object_to_json_string_ext(resp, BFDD_JSON_CONV_OPTIONS));
     501           0 :         json_object_put(resp);
     502             : 
     503           0 :         return jsonstr;
     504             : }
     505             : 
     506           0 : int config_notify_request(struct bfd_control_socket *bcs, const char *jsonstr,
     507             :                           bpc_handle bh)
     508             : {
     509           0 :         struct json_object *jo;
     510             : 
     511           0 :         jo = json_tokener_parse(jsonstr);
     512           0 :         if (jo == NULL)
     513             :                 return -1;
     514             : 
     515           0 :         return parse_config_json(jo, bh, bcs);
     516             : }
     517             : 
     518           0 : static int json_object_add_peer(struct json_object *jo, struct bfd_session *bs)
     519             : {
     520           0 :         char addr_buf[INET6_ADDRSTRLEN];
     521             : 
     522             :         /* Add peer 'key' information. */
     523           0 :         if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_IPV6))
     524           0 :                 json_object_boolean_true_add(jo, "ipv6");
     525             :         else
     526           0 :                 json_object_boolean_false_add(jo, "ipv6");
     527             : 
     528           0 :         if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)) {
     529           0 :                 json_object_boolean_true_add(jo, "multihop");
     530           0 :                 json_object_string_add(jo, "peer-address",
     531           0 :                                        inet_ntop(bs->key.family, &bs->key.peer,
     532             :                                                  addr_buf, sizeof(addr_buf)));
     533           0 :                 json_object_string_add(jo, "local-address",
     534           0 :                                        inet_ntop(bs->key.family, &bs->key.local,
     535             :                                                  addr_buf, sizeof(addr_buf)));
     536           0 :                 if (bs->key.vrfname[0])
     537           0 :                         json_object_string_add(jo, "vrf-name", bs->key.vrfname);
     538             :         } else {
     539           0 :                 json_object_boolean_false_add(jo, "multihop");
     540           0 :                 json_object_string_add(jo, "peer-address",
     541           0 :                                        inet_ntop(bs->key.family, &bs->key.peer,
     542             :                                                  addr_buf, sizeof(addr_buf)));
     543           0 :                 if (memcmp(&bs->key.local, &zero_addr, sizeof(bs->key.local)))
     544           0 :                         json_object_string_add(
     545             :                                 jo, "local-address",
     546           0 :                                 inet_ntop(bs->key.family, &bs->key.local,
     547             :                                           addr_buf, sizeof(addr_buf)));
     548           0 :                 if (bs->key.ifname[0])
     549           0 :                         json_object_string_add(jo, "local-interface",
     550           0 :                                                bs->key.ifname);
     551             :         }
     552             : 
     553           0 :         if (bs->pl)
     554           0 :                 json_object_string_add(jo, "label", bs->pl->pl_label);
     555             : 
     556           0 :         return 0;
     557             : }
     558             : 
     559             : 
     560             : /*
     561             :  * Label handling
     562             :  */
     563           0 : struct peer_label *pl_find(const char *label)
     564             : {
     565           0 :         struct peer_label *pl;
     566             : 
     567           0 :         TAILQ_FOREACH (pl, &bglobal.bg_pllist, pl_entry) {
     568           0 :                 if (strcmp(pl->pl_label, label) != 0)
     569           0 :                         continue;
     570             : 
     571             :                 return pl;
     572             :         }
     573             : 
     574             :         return NULL;
     575             : }
     576             : 
     577           0 : struct peer_label *pl_new(const char *label, struct bfd_session *bs)
     578             : {
     579           0 :         struct peer_label *pl;
     580             : 
     581           0 :         pl = XCALLOC(MTYPE_BFDD_LABEL, sizeof(*pl));
     582             : 
     583           0 :         if (strlcpy(pl->pl_label, label, sizeof(pl->pl_label))
     584             :             > sizeof(pl->pl_label))
     585           0 :                 zlog_warn("%s:%d: label was truncated", __func__, __LINE__);
     586             : 
     587           0 :         pl->pl_bs = bs;
     588           0 :         bs->pl = pl;
     589             : 
     590           0 :         TAILQ_INSERT_HEAD(&bglobal.bg_pllist, pl, pl_entry);
     591             : 
     592           0 :         return pl;
     593             : }
     594             : 
     595          16 : void pl_free(struct peer_label *pl)
     596             : {
     597          16 :         if (pl == NULL)
     598             :                 return;
     599             : 
     600             :         /* Remove the pointer back. */
     601           0 :         pl->pl_bs->pl = NULL;
     602             : 
     603           0 :         TAILQ_REMOVE(&bglobal.bg_pllist, pl, pl_entry);
     604           0 :         XFREE(MTYPE_BFDD_LABEL, pl);
     605             : }

Generated by: LCOV version v1.16-topotato