]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_open.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / bgpd / bgp_open.c
index 3e361fccfd1c36e1f2be219b0e1e2fc71778506f..032767820f5c864212e844dcffe33bc5169fa78c 100644 (file)
@@ -1,21 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /* BGP open message handling
  * Copyright (C) 1998, 1999 Kunihiro Ishiguro
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * GNU Zebra is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 #include <zebra.h>
@@ -59,6 +44,7 @@ static const struct message capcode_str[] = {
        {CAPABILITY_CODE_EXT_MESSAGE, "BGP Extended Message"},
        {CAPABILITY_CODE_LLGR, "Long-lived BGP Graceful Restart"},
        {CAPABILITY_CODE_ROLE, "Role"},
+       {CAPABILITY_CODE_SOFT_VERSION, "Software Version"},
        {0}};
 
 /* Minimum sizes for length field of each cap (so not inc. the header) */
@@ -79,6 +65,7 @@ static const size_t cap_minsizes[] = {
                [CAPABILITY_CODE_EXT_MESSAGE] = CAPABILITY_CODE_EXT_MESSAGE_LEN,
                [CAPABILITY_CODE_LLGR] = CAPABILITY_CODE_LLGR_LEN,
                [CAPABILITY_CODE_ROLE] = CAPABILITY_CODE_ROLE_LEN,
+               [CAPABILITY_CODE_SOFT_VERSION] = CAPABILITY_CODE_SOFT_VERSION_LEN,
 };
 
 /* value the capability must be a multiple of.
@@ -103,6 +90,7 @@ static const size_t cap_modsizes[] = {
                [CAPABILITY_CODE_EXT_MESSAGE] = 1,
                [CAPABILITY_CODE_LLGR] = 1,
                [CAPABILITY_CODE_ROLE] = 1,
+               [CAPABILITY_CODE_SOFT_VERSION] = 1,
 };
 
 /* BGP-4 Multiprotocol Extentions lead us to the complex world. We can
@@ -921,6 +909,41 @@ static int bgp_capability_role(struct peer *peer, struct capability_header *hdr)
        return 0;
 }
 
+static int bgp_capability_software_version(struct peer *peer,
+                                          struct capability_header *hdr)
+{
+       struct stream *s = BGP_INPUT(peer);
+       char str[BGP_MAX_SOFT_VERSION + 1];
+       size_t end = stream_get_getp(s) + hdr->length;
+       uint8_t len;
+
+       SET_FLAG(peer->cap, PEER_CAP_SOFT_VERSION_RCV);
+
+       len = stream_getc(s);
+       if (stream_get_getp(s) + len > end) {
+               flog_warn(
+                       EC_BGP_CAPABILITY_INVALID_DATA,
+                       "%s: Received malformed Software Version capability from peer %s",
+                       __func__, peer->host);
+               return -1;
+       }
+
+       if (len) {
+               stream_get(str, s, len);
+               str[len] = '\0';
+
+               XFREE(MTYPE_BGP_SOFT_VERSION, peer->soft_version);
+
+               peer->soft_version = XSTRDUP(MTYPE_BGP_SOFT_VERSION, str);
+
+               if (bgp_debug_neighbor_events(peer))
+                       zlog_debug("%s sent Software Version: %s", peer->host,
+                                  peer->soft_version);
+       }
+
+       return 0;
+}
+
 /**
  * Parse given capability.
  * XXX: This is reading into a stream, but not using stream API
@@ -989,6 +1012,7 @@ static int bgp_capability_parse(struct peer *peer, size_t length,
                case CAPABILITY_CODE_ENHANCED_RR:
                case CAPABILITY_CODE_EXT_MESSAGE:
                case CAPABILITY_CODE_ROLE:
+               case CAPABILITY_CODE_SOFT_VERSION:
                        /* Check length. */
                        if (caphdr.length < cap_minsizes[caphdr.code]) {
                                zlog_info(
@@ -1089,6 +1113,9 @@ static int bgp_capability_parse(struct peer *peer, size_t length,
                case CAPABILITY_CODE_ROLE:
                        ret = bgp_capability_role(peer, &caphdr);
                        break;
+               case CAPABILITY_CODE_SOFT_VERSION:
+                       ret = bgp_capability_software_version(peer, &caphdr);
+                       break;
                default:
                        if (caphdr.code > 128) {
                                /* We don't send Notification for unknown vendor
@@ -1928,6 +1955,50 @@ uint16_t bgp_open_capability(struct stream *s, struct peer *peer,
        bgp_peer_send_gr_capability(s, peer, ext_opt_params);
        bgp_peer_send_llgr_capability(s, peer, ext_opt_params);
 
+       /* Software Version capability
+        * An implementation is REQUIRED Extended Optional Parameters
+        * Length for BGP OPEN Message support as defined in [RFC9072].
+        * The inclusion of the Software Version Capability is OPTIONAL.
+        * If an implementation supports the inclusion of the capability,
+        * the implementation MUST include a configuration switch to enable
+        * or disable its use, and that switch MUST be off by default.
+        */
+       if (peergroup_flag_check(peer, PEER_FLAG_CAPABILITY_SOFT_VERSION) ||
+           peer->sort == BGP_PEER_IBGP) {
+               SET_FLAG(peer->cap, PEER_CAP_SOFT_VERSION_ADV);
+               stream_putc(s, BGP_OPEN_OPT_CAP);
+               rcapp = stream_get_endp(s);
+               ext_opt_params ? stream_putw(s, 0)
+                              : stream_putc(s, 0); /* Capability Length */
+               stream_putc(s, CAPABILITY_CODE_SOFT_VERSION);
+               capp = stream_get_endp(s);
+               stream_putc(s, 0); /* dummy placeholder len */
+
+               /* The Capability Length SHOULD be no greater than 64.
+                * This is the limit to allow other capabilities as much
+                * space as they require.
+                */
+               len = strlen(cmd_software_version_get());
+               if (len > BGP_MAX_SOFT_VERSION)
+                       len = BGP_MAX_SOFT_VERSION;
+
+               stream_putc(s, len);
+               stream_put(s, cmd_software_version_get(), len);
+
+               /* Software Version capability Len. */
+               len = stream_get_endp(s) - rcapp - 1;
+               ext_opt_params ? stream_putw_at(s, rcapp, len - 1)
+                              : stream_putc_at(s, rcapp, len);
+
+               /* Total Capability Len. */
+               len = stream_get_endp(s) - capp - 1;
+               stream_putc_at(s, capp, len);
+
+               if (bgp_debug_neighbor_events(peer))
+                       zlog_debug("%s Sending Software Version cap, value: %s",
+                                  peer->host, cmd_software_version_get());
+       }
+
        /* Total Opt Parm Len. */
        len = stream_get_endp(s) - cp - 1;