]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #4810 from qlyoung/fix-pthread-bad-pointer
authorRuss White <russ@riw.us>
Tue, 17 Sep 2019 11:27:12 +0000 (07:27 -0400)
committerGitHub <noreply@github.com>
Tue, 17 Sep 2019 11:27:12 +0000 (07:27 -0400)
Fix potential frr_pthread.c stale pointer

13 files changed:
README.md
bfdd/bfd.c
bfdd/bfd.h
bfdd/bfdd_vty.c
bfdd/ptm_adapter.c
bgpd/bgp_keepalives.c
bgpd/bgp_main.c
lib/vrf.c
ospfd/ospf_main.c
ospfd/ospfd.c
ripd/ripd.c
ripngd/ripngd.c
zebra/zebra_rib.c

index e8c775684a5b5e86627fe8a5120a6958bac9a25c..bb13481cf29c2897d03e9f24dfd0cca4e206b2cb 100644 (file)
--- a/README.md
+++ b/README.md
@@ -27,14 +27,15 @@ FRR currently supports the following protocols:
 Installation & Use
 ------------------
 
-Packages are available for various distributions on our
+For source tarballs, see the
 [releases page](https://github.com/FRRouting/frr/releases).
 
-Snaps are also available [here](https://snapcraft.io/frr).
+For Debian and its derivatives, use the APT repository at
+[https://deb.frrouting.org/](https://deb.frrouting.org/).
 
 Instructions on building and installing from source for supported platforms may
-be found
-[here](http://docs.frrouting.org/projects/dev-guide/en/latest/building.html).
+be found in the
+[developer docs](http://docs.frrouting.org/projects/dev-guide/en/latest/building.html).
 
 Once installed, please refer to the [user guide](http://docs.frrouting.org/)
 for instructions on use.
index 1f1568f5114399dc439c830781591f4fccfa525e..feb9827ce1ff30093f166ecea7cb1e0a65ea15cc 100644 (file)
@@ -391,10 +391,8 @@ struct bfd_session *ptm_bfd_sess_find(struct bfd_pkt *cp,
 
        /* Search for session without using discriminator. */
        ifp = if_lookup_by_index(ifindex, vrfid);
-       if (vrfid != VRF_DEFAULT)
-               vrf = vrf_lookup_by_id(vrfid);
-       else
-               vrf = NULL;
+
+       vrf = vrf_lookup_by_id(vrfid);
 
        gen_bfd_key(&key, peer, local, is_mhop, ifp ? ifp->name : NULL,
                    vrf ? vrf->name : VRF_DEFAULT_NAME);
@@ -1632,6 +1630,16 @@ static int bfd_vrf_delete(struct vrf *vrf)
        return 0;
 }
 
+static int bfd_vrf_update(struct vrf *vrf)
+{
+       if (!vrf_is_enabled(vrf))
+               return 0;
+       log_debug("VRF update: %s(%u)", vrf->name, vrf->vrf_id);
+       /* a different name is given; update bfd list */
+       bfdd_sessions_enable_vrf(vrf);
+       return 0;
+}
+
 static int bfd_vrf_enable(struct vrf *vrf)
 {
        struct bfd_vrf_global *bvrf;
@@ -1719,7 +1727,7 @@ static int bfd_vrf_disable(struct vrf *vrf)
 void bfd_vrf_init(void)
 {
        vrf_init(bfd_vrf_new, bfd_vrf_enable, bfd_vrf_disable,
-                bfd_vrf_delete, NULL);
+                bfd_vrf_delete, bfd_vrf_update);
 }
 
 void bfd_vrf_terminate(void)
@@ -1743,3 +1751,59 @@ struct bfd_vrf_global *bfd_vrf_look_by_session(struct bfd_session *bfd)
                return NULL;
        return bfd->vrf->info;
 }
+
+void bfd_session_update_vrf_name(struct bfd_session *bs, struct vrf *vrf)
+{
+       if (!vrf || !bs)
+               return;
+       /* update key */
+       hash_release(bfd_key_hash, bs);
+       /*
+        * HACK: Change the BFD VRF in the running configuration directly,
+        * bypassing the northbound layer. This is necessary to avoid deleting
+        * the BFD and readding it in the new VRF, which would have
+        * several implications.
+        */
+       if (yang_module_find("frr-bfdd") && bs->key.vrfname[0]) {
+               struct lyd_node *bfd_dnode;
+               char xpath[XPATH_MAXLEN], xpath_srcaddr[XPATH_MAXLEN + 32];
+               char addr_buf[INET6_ADDRSTRLEN];
+               int slen;
+
+               /* build xpath */
+               if (bs->key.mhop) {
+                       inet_ntop(bs->key.family, &bs->key.local, addr_buf, sizeof(addr_buf));
+                       snprintf(xpath_srcaddr, sizeof(xpath_srcaddr), "[source-addr='%s']",
+                                addr_buf);
+               } else
+                       xpath_srcaddr[0] = 0;
+               inet_ntop(bs->key.family, &bs->key.peer, addr_buf, sizeof(addr_buf));
+               slen = snprintf(xpath, sizeof(xpath),
+                               "/frr-bfdd:bfdd/bfd/sessions/%s%s[dest-addr='%s']",
+                               bs->key.mhop ? "multi-hop" : "single-hop", xpath_srcaddr,
+                               addr_buf);
+               if (bs->key.ifname[0])
+                       slen += snprintf(xpath + slen, sizeof(xpath) - slen,
+                                        "[interface='%s']", bs->key.ifname);
+               else
+                       slen += snprintf(xpath + slen, sizeof(xpath) - slen,
+                                        "[interface='']");
+               snprintf(xpath + slen, sizeof(xpath) - slen, "[vrf='%s']/vrf",
+                        bs->key.vrfname);
+
+               pthread_rwlock_wrlock(&running_config->lock);
+               {
+                       bfd_dnode = yang_dnode_get(
+                                                  running_config->dnode,
+                                                  xpath, bs->key.vrfname);
+                       if (bfd_dnode) {
+                               yang_dnode_change_leaf(bfd_dnode, vrf->name);
+                               running_config->version++;
+                       }
+                       pthread_rwlock_unlock(&running_config->lock);
+               }
+       }
+       memset(bs->key.vrfname, 0, sizeof(bs->key.vrfname));
+       strlcpy(bs->key.vrfname, vrf->name, sizeof(bs->key.vrfname));
+       hash_get(bfd_key_hash, bs, hash_alloc_intern);
+}
index 10aeb3e52c9b6a704be4602764d63ba1738bdae7..cdec78d1226066ceb130c38f3cd5942628fbff20 100644 (file)
@@ -630,6 +630,7 @@ void bfdd_zclient_unregister(vrf_id_t vrf_id);
 void bfdd_zclient_register(vrf_id_t vrf_id);
 void bfdd_sessions_enable_vrf(struct vrf *vrf);
 void bfdd_sessions_disable_vrf(struct vrf *vrf);
+void bfd_session_update_vrf_name(struct bfd_session *bs, struct vrf *vrf);
 
 int ptm_bfd_notify(struct bfd_session *bs);
 
index a211f34219af8ef8a99ef05b5b634b30b20b1675..5663ce54cbc7e4e27d57caabacc27624109a07b3 100644 (file)
@@ -685,6 +685,9 @@ static int bfd_configure_peer(struct bfd_peer_cfg *bpc, bool mhop,
                        snprintf(ebuf, ebuflen, "vrf name too long");
                        return -1;
                }
+       } else {
+               bpc->bpc_has_vrfname = true;
+               strlcpy(bpc->bpc_vrfname, VRF_DEFAULT_NAME, sizeof(bpc->bpc_vrfname));
        }
 
        return 0;
index 3e2ace6ea630a95598150799c158be5e185a4730..ae6d04e77d5e72065a20304847d41b2c5fdf97c2 100644 (file)
@@ -376,6 +376,9 @@ static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id,
                        log_error("ptm-read: vrf id %u could not be identified", vrf_id);
                        return -1;
                }
+       } else {
+               bpc->bpc_has_vrfname = true;
+               strlcpy(bpc->bpc_vrfname, VRF_DEFAULT_NAME, sizeof(bpc->bpc_vrfname));
        }
 
        STREAM_GETC(msg, bpc->bpc_cbit);
@@ -627,6 +630,11 @@ void bfdd_sessions_enable_vrf(struct vrf *vrf)
        /* it may affect configs without interfaces */
        TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) {
                bs = bso->bso_bs;
+               /* update name */
+               if (bs->vrf && bs->vrf == vrf) {
+                       if (!strmatch(bs->key.vrfname, vrf->name))
+                               bfd_session_update_vrf_name(bs, vrf);
+               }
                if (bs->vrf)
                        continue;
                if (bs->key.vrfname[0] &&
index 6de1c216a65b4bc155061ab3978bd4544dfafcdd..3a49e8bc00afe5ba01104394cea2bb34b0f7dd60 100644 (file)
@@ -97,11 +97,18 @@ static void peer_process(struct hash_bucket *hb, void *arg)
 
        static struct timeval tolerance = {0, 100000};
 
+       uint32_t v_ka = atomic_load_explicit(&pkat->peer->v_keepalive,
+                                            memory_order_relaxed);
+
+       /* 0 keepalive timer means no keepalives */
+       if (v_ka == 0)
+               return;
+
        /* calculate elapsed time since last keepalive */
        monotime_since(&pkat->last, &elapsed);
 
        /* calculate difference between elapsed time and configured time */
-       ka.tv_sec = pkat->peer->v_keepalive;
+       ka.tv_sec = v_ka;
        timersub(&ka, &elapsed, &diff);
 
        int send_keepalive =
index abd8586f4c71d73ed392e32a3ba9c1ea17e10cfc..ef73b47ffb9407336403e32722bead0765e9e935 100644 (file)
@@ -269,12 +269,20 @@ static int bgp_vrf_enable(struct vrf *vrf)
                zlog_debug("VRF enable add %s id %u", vrf->name, vrf->vrf_id);
 
        bgp = bgp_lookup_by_name(vrf->name);
-       if (bgp) {
+       if (bgp && bgp->vrf_id != vrf->vrf_id) {
                if (bgp->name && strmatch(vrf->name, VRF_DEFAULT_NAME)) {
                        XFREE(MTYPE_BGP, bgp->name);
                        bgp->name = NULL;
                        XFREE(MTYPE_BGP, bgp->name_pretty);
                        bgp->name_pretty = XSTRDUP(MTYPE_BGP, "VRF default");
+                       bgp->inst_type = BGP_INSTANCE_TYPE_DEFAULT;
+#if ENABLE_BGP_VNC
+                       if (!bgp->rfapi) {
+                               bgp->rfapi = bgp_rfapi_new(bgp);
+                               assert(bgp->rfapi);
+                               assert(bgp->rfapi_cfg);
+                       }
+#endif /* ENABLE_BGP_VNC */
                }
                old_vrf_id = bgp->vrf_id;
                /* We have instance configured, link to VRF and make it "up". */
@@ -343,7 +351,7 @@ static int bgp_vrf_disable(struct vrf *vrf)
 static void bgp_vrf_init(void)
 {
        vrf_init(bgp_vrf_new, bgp_vrf_enable, bgp_vrf_disable,
-                bgp_vrf_delete, NULL);
+                bgp_vrf_delete, bgp_vrf_enable);
 }
 
 static void bgp_vrf_terminate(void)
index 575e96bae4540ca5fd024a3ee323185b461ca41f..4c6df797ad49a87ee1678a7bd004c6e997dc5ae7 100644 (file)
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -199,9 +199,14 @@ struct vrf *vrf_get(vrf_id_t vrf_id, const char *name)
 
        /* Set name */
        if (name && vrf->name[0] != '\0' && strcmp(name, vrf->name)) {
+               /* update the vrf name */
                RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf);
+               strlcpy(vrf->data.l.netns_name,
+                       name, NS_NAMSIZ);
                strlcpy(vrf->name, name, sizeof(vrf->name));
                RB_INSERT(vrf_name_head, &vrfs_by_name, vrf);
+               if (vrf->vrf_id == VRF_DEFAULT)
+                       vrf_set_default_name(vrf->name, false);
        } else if (name && vrf->name[0] == '\0') {
                strlcpy(vrf->name, name, sizeof(vrf->name));
                RB_INSERT(vrf_name_head, &vrfs_by_name, vrf);
@@ -870,7 +875,8 @@ void vrf_set_default_name(const char *default_name, bool force)
                           def_vrf->vrf_id);
                return;
        }
-
+       if (strmatch(vrf_default_name, default_name))
+               return;
        snprintf(vrf_default_name, VRF_NAMSIZ, "%s", default_name);
        if (def_vrf) {
                if (force)
index 36bb8d49b595caefd3c4c3af2fbad29482a7a0c2..bee7bbb21d02de10a4de2b09732534a3c33ab016 100644 (file)
@@ -216,16 +216,6 @@ int main(int argc, char **argv)
        /* OSPF errors init */
        ospf_error_init();
 
-       /* Need to initialize the default ospf structure, so the interface mode
-          commands can be duly processed if they are received before 'router
-          ospf',
-          when quagga(ospfd) is restarted */
-       if (!ospf_get_instance(instance)) {
-               flog_err(EC_OSPF_INIT_FAIL, "OSPF instance init failed: %s",
-                        strerror(errno));
-               exit(1);
-       }
-
        frr_config_fork();
        frr_run(master);
 
index e48a5b4d369bce43d37c8c91756ed6e3420ce655..f4de2558778cd7edd5315a361d803e692670016f 100644 (file)
@@ -2158,7 +2158,7 @@ static int ospf_vrf_disable(struct vrf *vrf)
 void ospf_vrf_init(void)
 {
        vrf_init(ospf_vrf_new, ospf_vrf_enable, ospf_vrf_disable,
-                ospf_vrf_delete, NULL);
+                ospf_vrf_delete, ospf_vrf_enable);
 }
 
 void ospf_vrf_terminate(void)
index ad373aebdfbbf3cfc9af9edb1de934d2705cfdde..cd2ddb1eba778aeb4eb89cbcdee7abc625502658 100644 (file)
@@ -3641,6 +3641,41 @@ static int rip_vrf_enable(struct vrf *vrf)
        int socket;
 
        rip = rip_lookup_by_vrf_name(vrf->name);
+       if (!rip) {
+               char *old_vrf_name = NULL;
+
+               rip = (struct rip *)vrf->info;
+               if (!rip)
+                       return 0;
+               /* update vrf name */
+               if (rip->vrf_name)
+                       old_vrf_name = rip->vrf_name;
+               rip->vrf_name = XSTRDUP(MTYPE_RIP_VRF_NAME, vrf->name);
+               /*
+                * HACK: Change the RIP VRF in the running configuration directly,
+                * bypassing the northbound layer. This is necessary to avoid deleting
+                * the RIP and readding it in the new VRF, which would have
+                * several implications.
+                */
+               if (yang_module_find("frr-ripd") && old_vrf_name) {
+                       struct lyd_node *rip_dnode;
+
+                       pthread_rwlock_wrlock(&running_config->lock);
+                       {
+                               rip_dnode = yang_dnode_get(
+                                                  running_config->dnode,
+                                                  "/frr-ripd:ripd/instance[vrf='%s']/vrf",
+                                                  old_vrf_name);
+                               if (rip_dnode) {
+                                       yang_dnode_change_leaf(rip_dnode, vrf->name);
+                                       running_config->version++;
+                               }
+                       }
+                       pthread_rwlock_unlock(&running_config->lock);
+               }
+               if (old_vrf_name)
+                       XFREE(MTYPE_RIP_VRF_NAME, old_vrf_name);
+       }
        if (!rip || rip->enabled)
                return 0;
 
@@ -3682,7 +3717,7 @@ static int rip_vrf_disable(struct vrf *vrf)
 void rip_vrf_init(void)
 {
        vrf_init(rip_vrf_new, rip_vrf_enable, rip_vrf_disable, rip_vrf_delete,
-                NULL);
+                rip_vrf_enable);
 }
 
 void rip_vrf_terminate(void)
index 49f7dda646a9cac67282986bfab019e1fd7b0451..120f46f0da70a915409f7df8248bbd08f67f2967 100644 (file)
@@ -2776,7 +2776,43 @@ static int ripng_vrf_enable(struct vrf *vrf)
        int socket;
 
        ripng = ripng_lookup_by_vrf_name(vrf->name);
-       if (!ripng || ripng->enabled)
+       if (!ripng) {
+               char *old_vrf_name = NULL;
+
+               ripng = (struct ripng *)vrf->info;
+               if (!ripng)
+                       return 0;
+               /* update vrf name */
+               if (ripng->vrf_name)
+                       old_vrf_name = ripng->vrf_name;
+               ripng->vrf_name = XSTRDUP(MTYPE_RIPNG_VRF_NAME, vrf->name);
+               /*
+                * HACK: Change the RIPng VRF in the running configuration directly,
+                * bypassing the northbound layer. This is necessary to avoid deleting
+                * the RIPng and readding it in the new VRF, which would have
+                * several implications.
+                */
+               if (yang_module_find("frr-ripngd") && old_vrf_name) {
+                       struct lyd_node *ripng_dnode;
+
+                       pthread_rwlock_wrlock(&running_config->lock);
+                       {
+                               ripng_dnode = yang_dnode_get(
+                                                  running_config->dnode,
+                                                  "/frr-ripngd:ripngd/instance[vrf='%s']/vrf",
+                                                  old_vrf_name);
+                               if (ripng_dnode) {
+                                       yang_dnode_change_leaf(ripng_dnode, vrf->name);
+                                       running_config->version++;
+                               }
+                       }
+                       pthread_rwlock_unlock(&running_config->lock);
+               }
+               if (old_vrf_name)
+                       XFREE(MTYPE_RIPNG_VRF_NAME, old_vrf_name);
+       }
+
+       if (ripng->enabled)
                return 0;
 
        if (IS_RIPNG_DEBUG_EVENT)
@@ -2784,13 +2820,11 @@ static int ripng_vrf_enable(struct vrf *vrf)
                           vrf->vrf_id);
 
        /* Activate the VRF RIPng instance. */
-       if (!ripng->enabled) {
-               socket = ripng_make_socket(vrf);
-               if (socket < 0)
-                       return -1;
+       socket = ripng_make_socket(vrf);
+       if (socket < 0)
+               return -1;
 
-               ripng_instance_enable(ripng, vrf, socket);
-       }
+       ripng_instance_enable(ripng, vrf, socket);
 
        return 0;
 }
@@ -2817,7 +2851,7 @@ static int ripng_vrf_disable(struct vrf *vrf)
 void ripng_vrf_init(void)
 {
        vrf_init(ripng_vrf_new, ripng_vrf_enable, ripng_vrf_disable,
-                ripng_vrf_delete, NULL);
+                ripng_vrf_delete, ripng_vrf_enable);
 }
 
 void ripng_vrf_terminate(void)
index 157c67fa62dcb6d6b4f658748af577bf49f77396..d8fb9ae3cf6e00c4bfa20a54794f7122301df816 100644 (file)
@@ -2088,14 +2088,6 @@ static unsigned int process_subq(struct list *subq, uint8_t qindex)
        return 1;
 }
 
-
-/*
- * Perform next-hop tracking processing after RIB updates.
- */
-static void do_nht_processing(void)
-{
-}
-
 /* Dispatch the meta queue by picking, processing and unlocking the next RN from
  * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and
  * data
@@ -3294,9 +3286,6 @@ static int rib_process_dplane_results(struct thread *thread)
 
        } while (1);
 
-       /* Check for nexthop tracking processing after finishing with results */
-       do_nht_processing();
-
        return 0;
 }