back to topotato report
topotato coverage report
Current view: top level - zebra - connected.c (source / functions) Hit Total Coverage
Test: test_bgp_dont_capability_negotiate.py::BGPDontCapabilityNegotiate Lines: 145 276 52.5 %
Date: 2023-02-24 18:37:16 Functions: 7 14 50.0 %

          Line data    Source code
       1             : /*
       2             :  * Address linked list routine.
       3             :  * Copyright (C) 1997, 98 Kunihiro Ishiguro
       4             :  *
       5             :  * This file is part of GNU Zebra.
       6             :  *
       7             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       8             :  * under the terms of the GNU General Public License as published by the
       9             :  * Free Software Foundation; either version 2, or (at your option) any
      10             :  * later version.
      11             :  *
      12             :  * GNU Zebra is distributed in the hope that it will be useful, but
      13             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License along
      18             :  * with this program; see the file COPYING; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : #include <zebra.h>
      23             : 
      24             : #include "prefix.h"
      25             : #include "linklist.h"
      26             : #include "if.h"
      27             : #include "table.h"
      28             : #include "rib.h"
      29             : #include "table.h"
      30             : #include "log.h"
      31             : #include "memory.h"
      32             : 
      33             : #include "vty.h"
      34             : #include "zebra/debug.h"
      35             : #include "zebra/zserv.h"
      36             : #include "zebra/redistribute.h"
      37             : #include "zebra/interface.h"
      38             : #include "zebra/connected.h"
      39             : #include "zebra/rtadv.h"
      40             : #include "zebra/zebra_mpls.h"
      41             : #include "zebra/zebra_errors.h"
      42             : #include "zebra/zebra_router.h"
      43             : 
      44             : /* communicate the withdrawal of a connected address */
      45           0 : static void connected_withdraw(struct connected *ifc)
      46             : {
      47           0 :         if (!ifc)
      48             :                 return;
      49             : 
      50             :         /* Update interface address information to protocol daemon. */
      51           0 :         if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) {
      52           0 :                 zebra_interface_address_delete_update(ifc->ifp, ifc);
      53             : 
      54           0 :                 if (ifc->address->family == AF_INET)
      55           0 :                         if_subnet_delete(ifc->ifp, ifc);
      56             : 
      57           0 :                 connected_down(ifc->ifp, ifc);
      58             : 
      59           0 :                 UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
      60             :         }
      61             : 
      62             :         /* The address is not in the kernel anymore, so clear the flag */
      63           0 :         UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
      64             : 
      65           0 :         if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) {
      66           0 :                 listnode_delete(ifc->ifp->connected, ifc);
      67           0 :                 connected_free(&ifc);
      68             :         }
      69             : }
      70             : 
      71          10 : static void connected_announce(struct interface *ifp, struct connected *ifc)
      72             : {
      73          10 :         if (!ifc)
      74             :                 return;
      75             : 
      76          10 :         if (!if_is_loopback(ifp) && ifc->address->family == AF_INET) {
      77           2 :                 if (ifc->address->prefixlen == IPV4_MAX_BITLEN)
      78           0 :                         SET_FLAG(ifc->flags, ZEBRA_IFA_UNNUMBERED);
      79             :                 else
      80           2 :                         UNSET_FLAG(ifc->flags, ZEBRA_IFA_UNNUMBERED);
      81             :         }
      82             : 
      83          10 :         listnode_add(ifp->connected, ifc);
      84             : 
      85             :         /* Update interface address information to protocol daemon. */
      86          10 :         if (ifc->address->family == AF_INET)
      87           4 :                 if_subnet_add(ifp, ifc);
      88             : 
      89          10 :         zebra_interface_address_add_update(ifp, ifc);
      90             : 
      91          10 :         if (if_is_operative(ifp)) {
      92          10 :                 connected_up(ifp, ifc);
      93             :         }
      94             : }
      95             : 
      96             : /* If same interface address is already exist... */
      97           0 : struct connected *connected_check(struct interface *ifp,
      98             :                                   union prefixconstptr pu)
      99             : {
     100           0 :         const struct prefix *p = pu.p;
     101           0 :         struct connected *ifc;
     102           0 :         struct listnode *node;
     103             : 
     104           0 :         for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc))
     105           0 :                 if (prefix_same(ifc->address, p))
     106           0 :                         return ifc;
     107             : 
     108             :         return NULL;
     109             : }
     110             : 
     111             : /* same, but with peer address */
     112          13 : struct connected *connected_check_ptp(struct interface *ifp,
     113             :                                       union prefixconstptr pu,
     114             :                                       union prefixconstptr du)
     115             : {
     116          13 :         const struct prefix *p = pu.p;
     117          13 :         const struct prefix *d = du.p;
     118          13 :         struct connected *ifc;
     119          13 :         struct listnode *node;
     120             : 
     121          34 :         for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
     122          11 :                 if (!prefix_same(ifc->address, p))
     123           8 :                         continue;
     124           3 :                 if (!CONNECTED_PEER(ifc) && !d)
     125           3 :                         return ifc;
     126           0 :                 if (CONNECTED_PEER(ifc) && d
     127           0 :                     && prefix_same(ifc->destination, d))
     128           0 :                         return ifc;
     129             :         }
     130             : 
     131             :         return NULL;
     132             : }
     133             : 
     134             : /* Check if two ifc's describe the same address in the same state */
     135           0 : static int connected_same(struct connected *ifc1, struct connected *ifc2)
     136             : {
     137           0 :         if (ifc1->ifp != ifc2->ifp)
     138             :                 return 0;
     139             : 
     140           0 :         if (ifc1->flags != ifc2->flags)
     141             :                 return 0;
     142             : 
     143           0 :         if (ifc1->conf != ifc2->conf)
     144             :                 return 0;
     145             : 
     146           0 :         if (ifc1->destination)
     147           0 :                 if (!ifc2->destination)
     148             :                         return 0;
     149           0 :         if (ifc2->destination)
     150           0 :                 if (!ifc1->destination)
     151             :                         return 0;
     152             : 
     153           0 :         if (ifc1->destination && ifc2->destination)
     154           0 :                 if (!prefix_same(ifc1->destination, ifc2->destination))
     155             :                         return 0;
     156             : 
     157             :         return 1;
     158             : }
     159             : 
     160             : /* Handle changes to addresses and send the neccesary announcements
     161             :  * to clients. */
     162          10 : static void connected_update(struct interface *ifp, struct connected *ifc)
     163             : {
     164          10 :         struct connected *current;
     165             : 
     166             :         /* Check same connected route. */
     167          10 :         current = connected_check_ptp(ifp, ifc->address, ifc->destination);
     168          10 :         if (current) {
     169           0 :                 if (CHECK_FLAG(current->conf, ZEBRA_IFC_CONFIGURED))
     170           0 :                         SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
     171             : 
     172             :                 /* Avoid spurious withdraws, this might be just the kernel
     173             :                  * 'reflecting'
     174             :                  * back an address we have already added.
     175             :                  */
     176           0 :                 if (connected_same(current, ifc)) {
     177             :                         /* nothing to do */
     178           0 :                         connected_free(&ifc);
     179           0 :                         return;
     180             :                 }
     181             : 
     182             :                 /* Clear the configured flag on the old ifc, so it will be freed
     183             :                  * by
     184             :                  * connected withdraw. */
     185           0 :                 UNSET_FLAG(current->conf, ZEBRA_IFC_CONFIGURED);
     186           0 :                 connected_withdraw(
     187             :                         current); /* implicit withdraw - freebsd does this */
     188             :         }
     189             : 
     190             :         /* If the connected is new or has changed, announce it, if it is usable
     191             :          */
     192          10 :         if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
     193          10 :                 connected_announce(ifp, ifc);
     194             : }
     195             : 
     196             : /* Called from if_up(). */
     197          12 : void connected_up(struct interface *ifp, struct connected *ifc)
     198             : {
     199          12 :         afi_t afi;
     200          12 :         struct prefix p;
     201          12 :         struct nexthop nh = {
     202             :                 .type = NEXTHOP_TYPE_IFINDEX,
     203          12 :                 .ifindex = ifp->ifindex,
     204          12 :                 .vrf_id = ifp->vrf->vrf_id,
     205             :         };
     206          12 :         struct zebra_vrf *zvrf;
     207          12 :         uint32_t metric;
     208          12 :         uint32_t flags = 0;
     209          12 :         uint32_t count = 0;
     210          12 :         struct listnode *cnode;
     211          12 :         struct connected *c;
     212             : 
     213          12 :         zvrf = ifp->vrf->info;
     214          12 :         if (!zvrf) {
     215           0 :                 flog_err(
     216             :                         EC_ZEBRA_VRF_NOT_FOUND,
     217             :                         "%s: Received Up for interface but no associated zvrf: %s(%d)",
     218             :                         __func__, ifp->vrf->name, ifp->vrf->vrf_id);
     219           0 :                 return;
     220             :         }
     221          12 :         if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
     222             :                 return;
     223             : 
     224             :         /* Ensure 'down' flag is cleared */
     225          12 :         UNSET_FLAG(ifc->conf, ZEBRA_IFC_DOWN);
     226             : 
     227          12 :         prefix_copy(&p, CONNECTED_PREFIX(ifc));
     228             : 
     229             :         /* Apply mask to the network. */
     230          12 :         apply_mask(&p);
     231             : 
     232          12 :         afi = family2afi(p.family);
     233             : 
     234          12 :         switch (afi) {
     235           5 :         case AFI_IP:
     236             :                 /*
     237             :                  * In case of connected address is 0.0.0.0/0 we treat it tunnel
     238             :                  * address.
     239             :                  */
     240           5 :                 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
     241             :                         return;
     242             :                 break;
     243             :         case AFI_IP6:
     244             : #ifndef GNU_LINUX
     245             :                 /* XXX: It is already done by rib_bogus_ipv6 within rib_add */
     246             :                 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
     247             :                         return;
     248             : #endif
     249             :                 break;
     250           0 :         case AFI_UNSPEC:
     251             :         case AFI_L2VPN:
     252             :         case AFI_MAX:
     253           0 :                 flog_warn(EC_ZEBRA_CONNECTED_AFI_UNKNOWN,
     254             :                           "Received unknown AFI: %s", afi2str(afi));
     255           0 :                 return;
     256          12 :                 break;
     257             :         }
     258             : 
     259          24 :         metric = (ifc->metric < (uint32_t)METRIC_MAX) ?
     260          12 :                                 ifc->metric : ifp->metric;
     261             : 
     262             :         /*
     263             :          * Since we are hand creating the connected routes
     264             :          * in our main routing table, *if* we are working
     265             :          * in an offloaded environment then we need to
     266             :          * pretend like the route is offloaded so everything
     267             :          * else will work
     268             :          */
     269          12 :         if (zrouter.asic_offloaded)
     270           0 :                 flags |= ZEBRA_FLAG_OFFLOADED;
     271             : 
     272             :         /*
     273             :          * It's possible to add the same network and mask
     274             :          * to an interface over and over.  This would
     275             :          * result in an equivalent number of connected
     276             :          * routes.  Just add one connected route in
     277             :          * for all the addresses on an interface that
     278             :          * resolve to the same network and mask
     279             :          */
     280          46 :         for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
     281          22 :                 struct prefix cp;
     282             : 
     283          22 :                 prefix_copy(&cp, CONNECTED_PREFIX(c));
     284          22 :                 apply_mask(&cp);
     285             : 
     286          22 :                 if (prefix_same(&cp, &p) &&
     287          12 :                     !CHECK_FLAG(c->conf, ZEBRA_IFC_DOWN))
     288          12 :                         count++;
     289             : 
     290          22 :                 if (count >= 2)
     291           0 :                         return;
     292             :         }
     293             : 
     294          12 :         rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
     295             :                 flags, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0,
     296             :                 false);
     297             : 
     298          12 :         rib_add(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
     299             :                 flags, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0,
     300             :                 false);
     301             : 
     302             :         /* Schedule LSP forwarding entries for processing, if appropriate. */
     303          12 :         if (zvrf->vrf->vrf_id == VRF_DEFAULT) {
     304          12 :                 if (IS_ZEBRA_DEBUG_MPLS)
     305           0 :                         zlog_debug(
     306             :                                 "%u: IF %s IP %pFX address add/up, scheduling MPLS processing",
     307             :                                 zvrf->vrf->vrf_id, ifp->name, &p);
     308          12 :                 mpls_mark_lsps_for_processing(zvrf, &p);
     309             :         }
     310             : }
     311             : 
     312             : /* Add connected IPv4 route to the interface. */
     313           6 : void connected_add_ipv4(struct interface *ifp, int flags,
     314             :                         const struct in_addr *addr, uint16_t prefixlen,
     315             :                         const struct in_addr *dest, const char *label,
     316             :                         uint32_t metric)
     317             : {
     318           6 :         struct prefix_ipv4 *p;
     319           6 :         struct connected *ifc;
     320             : 
     321           6 :         if (ipv4_martian(addr))
     322             :                 return;
     323             : 
     324             :         /* Make connected structure. */
     325           4 :         ifc = connected_new();
     326           4 :         ifc->ifp = ifp;
     327           4 :         ifc->flags = flags;
     328           4 :         ifc->metric = metric;
     329             :         /* If we get a notification from the kernel,
     330             :          * we can safely assume the address is known to the kernel */
     331           4 :         SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
     332           4 :         if (!if_is_operative(ifp))
     333           0 :                 SET_FLAG(ifc->conf, ZEBRA_IFC_DOWN);
     334             : 
     335             :         /* Allocate new connected address. */
     336           4 :         p = prefix_ipv4_new();
     337           4 :         p->family = AF_INET;
     338           4 :         p->prefix = *addr;
     339           8 :         p->prefixlen =
     340           4 :                 CHECK_FLAG(flags, ZEBRA_IFA_PEER) ? IPV4_MAX_BITLEN : prefixlen;
     341           4 :         ifc->address = (struct prefix *)p;
     342             : 
     343             :         /* If there is a peer address. */
     344           4 :         if (CONNECTED_PEER(ifc)) {
     345             :                 /* validate the destination address */
     346           0 :                 if (dest) {
     347           0 :                         p = prefix_ipv4_new();
     348           0 :                         p->family = AF_INET;
     349           0 :                         p->prefix = *dest;
     350           0 :                         p->prefixlen = prefixlen;
     351           0 :                         ifc->destination = (struct prefix *)p;
     352             : 
     353           0 :                         if (IPV4_ADDR_SAME(addr, dest))
     354           0 :                                 flog_warn(
     355             :                                         EC_ZEBRA_IFACE_SAME_LOCAL_AS_PEER,
     356             :                                         "interface %s has same local and peer address %pI4, routing protocols may malfunction",
     357             :                                         ifp->name, addr);
     358             :                 } else {
     359           0 :                         zlog_debug(
     360             :                                 "%s called for interface %s with peer flag set, but no peer address supplied",
     361             :                                 __func__, ifp->name);
     362           0 :                         UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
     363             :                 }
     364             :         }
     365             : 
     366             :         /* no destination address was supplied */
     367           4 :         if (!dest && (prefixlen == IPV4_MAX_BITLEN) && if_is_pointopoint(ifp))
     368           0 :                 zlog_debug(
     369             :                         "PtP interface %s with addr %pI4/%d needs a peer address",
     370             :                         ifp->name, addr, prefixlen);
     371             : 
     372             :         /* Label of this address. */
     373           4 :         if (label)
     374           0 :                 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
     375             : 
     376             :         /* For all that I know an IPv4 address is always ready when we receive
     377             :          * the notification. So it should be safe to set the REAL flag here. */
     378           4 :         SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
     379             : 
     380           4 :         connected_update(ifp, ifc);
     381             : }
     382             : 
     383           2 : void connected_down(struct interface *ifp, struct connected *ifc)
     384             : {
     385           2 :         afi_t afi;
     386           2 :         struct prefix p;
     387           2 :         struct nexthop nh = {
     388             :                 .type = NEXTHOP_TYPE_IFINDEX,
     389           2 :                 .ifindex = ifp->ifindex,
     390           2 :                 .vrf_id = ifp->vrf->vrf_id,
     391             :         };
     392           2 :         struct zebra_vrf *zvrf;
     393           2 :         uint32_t count = 0;
     394           2 :         struct listnode *cnode;
     395           2 :         struct connected *c;
     396             : 
     397           2 :         zvrf = ifp->vrf->info;
     398           2 :         if (!zvrf) {
     399           0 :                 flog_err(
     400             :                         EC_ZEBRA_VRF_NOT_FOUND,
     401             :                         "%s: Received Down for interface but no associated zvrf: %s(%d)",
     402             :                         __func__, ifp->vrf->name, ifp->vrf->vrf_id);
     403           0 :                 return;
     404             :         }
     405             : 
     406           2 :         if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
     407             :                 return;
     408             : 
     409             :         /* Skip if we've already done this; this can happen if we have a
     410             :          * config change that takes an interface down, then we receive kernel
     411             :          * notifications about the downed interface and its addresses.
     412             :          */
     413           2 :         if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_DOWN)) {
     414           0 :                 if (IS_ZEBRA_DEBUG_RIB)
     415           0 :                         zlog_debug("%s: ifc %p, %pFX already DOWN",
     416             :                                    __func__, ifc, ifc->address);
     417           0 :                 return;
     418             :         }
     419             : 
     420           2 :         prefix_copy(&p, CONNECTED_PREFIX(ifc));
     421             : 
     422             :         /* Apply mask to the network. */
     423           2 :         apply_mask(&p);
     424             : 
     425           2 :         afi = family2afi(p.family);
     426             : 
     427           2 :         switch (afi) {
     428           1 :         case AFI_IP:
     429             :                 /*
     430             :                  * In case of connected address is 0.0.0.0/0 we treat it tunnel
     431             :                  *  address.
     432             :                  */
     433           1 :                 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
     434             :                         return;
     435             :                 break;
     436           1 :         case AFI_IP6:
     437           1 :                 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
     438             :                         return;
     439             :                 break;
     440           0 :         case AFI_UNSPEC:
     441             :         case AFI_L2VPN:
     442             :         case AFI_MAX:
     443           0 :                 zlog_warn("Unknown AFI: %s", afi2str(afi));
     444           0 :                 break;
     445             :         }
     446             : 
     447             :         /* Mark the address as 'down' */
     448           2 :         SET_FLAG(ifc->conf, ZEBRA_IFC_DOWN);
     449             : 
     450             :         /*
     451             :          * It's possible to have X number of addresses
     452             :          * on a interface that all resolve to the same
     453             :          * network and mask.  Find them and just
     454             :          * allow the deletion when are removing the last
     455             :          * one.
     456             :          */
     457           8 :         for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
     458           4 :                 struct prefix cp;
     459             : 
     460           4 :                 prefix_copy(&cp, CONNECTED_PREFIX(c));
     461           4 :                 apply_mask(&cp);
     462             : 
     463           4 :                 if (prefix_same(&p, &cp) &&
     464           2 :                     !CHECK_FLAG(c->conf, ZEBRA_IFC_DOWN))
     465           4 :                         count++;
     466             : 
     467           4 :                 if (count >= 1)
     468           0 :                         return;
     469             :         }
     470             : 
     471             :         /*
     472             :          * Same logic as for connected_up(): push the changes into the
     473             :          * head.
     474             :          */
     475           2 :         rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
     476             :                    0, &p, NULL, &nh, 0, zvrf->table_id, 0, 0, false);
     477             : 
     478           2 :         rib_delete(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT,
     479             :                    0, 0, &p, NULL, &nh, 0, zvrf->table_id, 0, 0, false);
     480             : 
     481             :         /* Schedule LSP forwarding entries for processing, if appropriate. */
     482           2 :         if (zvrf->vrf->vrf_id == VRF_DEFAULT) {
     483           2 :                 if (IS_ZEBRA_DEBUG_MPLS)
     484           0 :                         zlog_debug(
     485             :                                 "%u: IF %s IP %pFX address down, scheduling MPLS processing",
     486             :                                 zvrf->vrf->vrf_id, ifp->name, &p);
     487           2 :                 mpls_mark_lsps_for_processing(zvrf, &p);
     488             :         }
     489             : }
     490             : 
     491           0 : static void connected_delete_helper(struct connected *ifc, struct prefix *p)
     492             : {
     493           0 :         struct interface *ifp;
     494             : 
     495           0 :         if (!ifc)
     496             :                 return;
     497           0 :         ifp = ifc->ifp;
     498             : 
     499           0 :         connected_withdraw(ifc);
     500             : 
     501             :         /* Schedule LSP forwarding entries for processing, if appropriate. */
     502           0 :         if (ifp->vrf->vrf_id == VRF_DEFAULT) {
     503           0 :                 if (IS_ZEBRA_DEBUG_MPLS)
     504           0 :                         zlog_debug(
     505             :                                 "%u: IF %s IP %pFX address delete, scheduling MPLS processing",
     506             :                                 ifp->vrf->vrf_id, ifp->name, p);
     507           0 :                 mpls_mark_lsps_for_processing(ifp->vrf->info, p);
     508             :         }
     509             : }
     510             : 
     511             : /* Delete connected IPv4 route to the interface. */
     512           0 : void connected_delete_ipv4(struct interface *ifp, int flags,
     513             :                            const struct in_addr *addr, uint16_t prefixlen,
     514             :                            const struct in_addr *dest)
     515             : {
     516           0 :         struct prefix p, d;
     517           0 :         struct connected *ifc;
     518             : 
     519           0 :         memset(&p, 0, sizeof(p));
     520           0 :         p.family = AF_INET;
     521           0 :         p.u.prefix4 = *addr;
     522           0 :         p.prefixlen =
     523           0 :                 CHECK_FLAG(flags, ZEBRA_IFA_PEER) ? IPV4_MAX_BITLEN : prefixlen;
     524             : 
     525           0 :         if (dest) {
     526           0 :                 memset(&d, 0, sizeof(d));
     527           0 :                 d.family = AF_INET;
     528           0 :                 d.u.prefix4 = *dest;
     529           0 :                 d.prefixlen = prefixlen;
     530           0 :                 ifc = connected_check_ptp(ifp, &p, &d);
     531             :         } else
     532           0 :                 ifc = connected_check_ptp(ifp, &p, NULL);
     533             : 
     534           0 :         connected_delete_helper(ifc, &p);
     535           0 : }
     536             : 
     537             : /* Add connected IPv6 route to the interface. */
     538           8 : void connected_add_ipv6(struct interface *ifp, int flags,
     539             :                         const struct in6_addr *addr,
     540             :                         const struct in6_addr *dest, uint16_t prefixlen,
     541             :                         const char *label, uint32_t metric)
     542             : {
     543           8 :         struct prefix_ipv6 *p;
     544           8 :         struct connected *ifc;
     545             : 
     546           8 :         if (ipv6_martian(addr))
     547             :                 return;
     548             : 
     549             :         /* Make connected structure. */
     550           6 :         ifc = connected_new();
     551           6 :         ifc->ifp = ifp;
     552           6 :         ifc->flags = flags;
     553           6 :         ifc->metric = metric;
     554             :         /* If we get a notification from the kernel,
     555             :          * we can safely assume the address is known to the kernel */
     556           6 :         SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
     557           6 :         if (!if_is_operative(ifp))
     558           0 :                 SET_FLAG(ifc->conf, ZEBRA_IFC_DOWN);
     559             : 
     560             :         /* Allocate new connected address. */
     561           6 :         p = prefix_ipv6_new();
     562           6 :         p->family = AF_INET6;
     563           6 :         IPV6_ADDR_COPY(&p->prefix, addr);
     564           6 :         p->prefixlen = prefixlen;
     565           6 :         ifc->address = (struct prefix *)p;
     566             : 
     567             :         /* Add global ipv6 address to the RA prefix list */
     568           6 :         if (!IN6_IS_ADDR_LINKLOCAL(&p->prefix))
     569           4 :                 rtadv_add_prefix(ifp->info, p);
     570             : 
     571           6 :         if (dest) {
     572           0 :                 p = prefix_ipv6_new();
     573           0 :                 p->family = AF_INET6;
     574           0 :                 IPV6_ADDR_COPY(&p->prefix, dest);
     575           0 :                 p->prefixlen = prefixlen;
     576           0 :                 ifc->destination = (struct prefix *)p;
     577             :         } else {
     578           6 :                 if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) {
     579           0 :                         zlog_debug(
     580             :                                 "%s called for interface %s with peer flag set, but no peer address supplied",
     581             :                                 __func__, ifp->name);
     582           0 :                         UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
     583             :                 }
     584             :         }
     585             : 
     586             :         /* Label of this address. */
     587           6 :         if (label)
     588           0 :                 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
     589             : 
     590             :         /* On Linux, we only get here when DAD is complete, therefore we can set
     591             :          * ZEBRA_IFC_REAL.
     592             :          *
     593             :          * On BSD, there currently doesn't seem to be a way to check for
     594             :          * completion of
     595             :          * DAD, so we replicate the old behaviour and set ZEBRA_IFC_REAL,
     596             :          * although DAD
     597             :          * might still be running.
     598             :          */
     599           6 :         SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
     600           6 :         connected_update(ifp, ifc);
     601             : }
     602             : 
     603           0 : void connected_delete_ipv6(struct interface *ifp,
     604             :                            const struct in6_addr *address,
     605             :                            const struct in6_addr *dest, uint16_t prefixlen)
     606             : {
     607           0 :         struct prefix p, d;
     608           0 :         struct connected *ifc;
     609             : 
     610           0 :         memset(&p, 0, sizeof(p));
     611           0 :         p.family = AF_INET6;
     612           0 :         memcpy(&p.u.prefix6, address, sizeof(struct in6_addr));
     613           0 :         p.prefixlen = prefixlen;
     614             : 
     615             :         /* Delete global ipv6 address from RA prefix list */
     616           0 :         if (!IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
     617           0 :                 rtadv_delete_prefix(ifp->info, &p);
     618             : 
     619           0 :         if (dest) {
     620           0 :                 memset(&d, 0, sizeof(d));
     621           0 :                 d.family = AF_INET6;
     622           0 :                 IPV6_ADDR_COPY(&d.u.prefix6, dest);
     623           0 :                 d.prefixlen = prefixlen;
     624           0 :                 ifc = connected_check_ptp(ifp, &p, &d);
     625             :         } else
     626           0 :                 ifc = connected_check_ptp(ifp, &p, NULL);
     627             : 
     628           0 :         connected_delete_helper(ifc, &p);
     629           0 : }
     630             : 
     631           0 : int connected_is_unnumbered(struct interface *ifp)
     632             : {
     633           0 :         struct connected *connected;
     634           0 :         struct listnode *node;
     635             : 
     636           0 :         for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
     637           0 :                 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
     638           0 :                     && connected->address->family == AF_INET)
     639           0 :                         return CHECK_FLAG(connected->flags,
     640             :                                           ZEBRA_IFA_UNNUMBERED);
     641             :         }
     642             :         return 0;
     643             : }

Generated by: LCOV version v1.16-topotato