back to topotato report
topotato coverage report
Current view: top level - zebra - ioctl.c (source / functions) Hit Total Coverage
Test: test_bgp_ecmp_enhe.py::BGP_Unnumbered_ECMP Lines: 0 55 0.0 %
Date: 2023-11-16 17:19:14 Functions: 0 10 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /*
       3             :  * Common ioctl functions.
       4             :  * Copyright (C) 1997, 98 Kunihiro Ishiguro
       5             :  */
       6             : 
       7             : #include <zebra.h>
       8             : 
       9             : #include "linklist.h"
      10             : #include "if.h"
      11             : #include "prefix.h"
      12             : #include "ioctl.h"
      13             : #include "log.h"
      14             : #include "privs.h"
      15             : #include "lib_errors.h"
      16             : 
      17             : #include "vty.h"
      18             : #include "zebra/rib.h"
      19             : #include "zebra/rt.h"
      20             : #include "zebra/interface.h"
      21             : #include "zebra/zebra_errors.h"
      22             : #include "zebra/debug.h"
      23             : 
      24             : #ifdef HAVE_BSD_LINK_DETECT
      25             : #include <net/if_media.h>
      26             : #endif /* HAVE_BSD_LINK_DETECT*/
      27             : 
      28             : extern struct zebra_privs_t zserv_privs;
      29             : 
      30             : /* clear and set interface name string */
      31           0 : void ifreq_set_name(struct ifreq *ifreq, struct interface *ifp)
      32             : {
      33           0 :         strlcpy(ifreq->ifr_name, ifp->name, sizeof(ifreq->ifr_name));
      34           0 : }
      35             : 
      36             : #ifndef HAVE_NETLINK
      37             : /* call ioctl system call */
      38             : int if_ioctl(unsigned long request, caddr_t buffer)
      39             : {
      40             :         int sock;
      41             :         int ret;
      42             :         int err = 0;
      43             : 
      44             :         frr_with_privs(&zserv_privs) {
      45             :                 sock = socket(AF_INET, SOCK_DGRAM, 0);
      46             :                 if (sock < 0) {
      47             :                         zlog_err("Cannot create UDP socket: %s",
      48             :                                  safe_strerror(errno));
      49             :                         exit(1);
      50             :                 }
      51             :                 if ((ret = ioctl(sock, request, buffer)) < 0)
      52             :                         err = errno;
      53             :         }
      54             :         close(sock);
      55             : 
      56             :         if (ret < 0) {
      57             :                 errno = err;
      58             :                 return ret;
      59             :         }
      60             :         return 0;
      61             : }
      62             : #endif
      63             : 
      64             : /* call ioctl system call */
      65           0 : int vrf_if_ioctl(unsigned long request, caddr_t buffer, vrf_id_t vrf_id)
      66             : {
      67           0 :         int sock;
      68           0 :         int ret;
      69           0 :         int err = 0;
      70             : 
      71           0 :         frr_with_privs(&zserv_privs) {
      72           0 :                 sock = vrf_socket(AF_INET, SOCK_DGRAM, 0, vrf_id, NULL);
      73           0 :                 if (sock < 0) {
      74           0 :                         zlog_err("Cannot create UDP socket: %s",
      75             :                                  safe_strerror(errno));
      76           0 :                         exit(1);
      77             :                 }
      78           0 :                 ret = vrf_ioctl(vrf_id, sock, request, buffer);
      79           0 :                 if (ret < 0)
      80           0 :                         err = errno;
      81             :         }
      82           0 :         close(sock);
      83             : 
      84           0 :         if (ret < 0) {
      85           0 :                 errno = err;
      86           0 :                 return ret;
      87             :         }
      88             :         return 0;
      89             : }
      90             : 
      91             : #ifndef HAVE_NETLINK
      92             : static int if_ioctl_ipv6(unsigned long request, caddr_t buffer)
      93             : {
      94             :         int sock;
      95             :         int ret;
      96             :         int err = 0;
      97             : 
      98             :         frr_with_privs(&zserv_privs) {
      99             :                 sock = socket(AF_INET6, SOCK_DGRAM, 0);
     100             :                 if (sock < 0) {
     101             :                         zlog_err("Cannot create IPv6 datagram socket: %s",
     102             :                                  safe_strerror(errno));
     103             :                         exit(1);
     104             :                 }
     105             : 
     106             :                 if ((ret = ioctl(sock, request, buffer)) < 0)
     107             :                         err = errno;
     108             :         }
     109             :         close(sock);
     110             : 
     111             :         if (ret < 0) {
     112             :                 errno = err;
     113             :                 return ret;
     114             :         }
     115             :         return 0;
     116             : }
     117             : 
     118             : /*
     119             :  * get interface metric
     120             :  *   -- if value is not avaliable set -1
     121             :  */
     122             : void if_get_metric(struct interface *ifp)
     123             : {
     124             : #ifdef SIOCGIFMETRIC
     125             :         struct ifreq ifreq = {};
     126             : 
     127             :         ifreq_set_name(&ifreq, ifp);
     128             : 
     129             :         if (vrf_if_ioctl(SIOCGIFMETRIC, (caddr_t)&ifreq, ifp->vrf->vrf_id) < 0)
     130             :                 return;
     131             :         ifp->metric = ifreq.ifr_metric;
     132             :         if (ifp->metric == 0)
     133             :                 ifp->metric = 1;
     134             : #else  /* SIOCGIFMETRIC */
     135             :         ifp->metric = -1;
     136             : #endif /* SIOCGIFMETRIC */
     137             : }
     138             : 
     139             : /* get interface MTU */
     140             : void if_get_mtu(struct interface *ifp)
     141             : {
     142             :         struct ifreq ifreq = {};
     143             : 
     144             :         ifreq_set_name(&ifreq, ifp);
     145             : 
     146             : #if defined(SIOCGIFMTU)
     147             :         if (vrf_if_ioctl(SIOCGIFMTU, (caddr_t)&ifreq, ifp->vrf->vrf_id) < 0) {
     148             :                 zlog_info("Can't lookup mtu by ioctl(SIOCGIFMTU) for %s(%u)",
     149             :                           ifp->name, ifp->vrf->vrf_id);
     150             :                 ifp->mtu6 = ifp->mtu = -1;
     151             :                 return;
     152             :         }
     153             : 
     154             :         ifp->mtu6 = ifp->mtu = ifreq.ifr_mtu;
     155             : 
     156             :         /* propogate */
     157             :         zebra_interface_up_update(ifp);
     158             : 
     159             : #else
     160             :         zlog_info("Can't lookup mtu on this system for %s(%u)", ifp->name,
     161             :                   ifp->vrf->vrf_id);
     162             :         ifp->mtu6 = ifp->mtu = -1;
     163             : #endif
     164             : }
     165             : #endif /* ! HAVE_NETLINK */
     166             : 
     167             : /*
     168             :  * Handler for interface address programming via the zebra dplane,
     169             :  * for non-netlink platforms. This handler dispatches to per-platform
     170             :  * helpers, based on the operation requested.
     171             :  */
     172             : #ifndef HAVE_NETLINK
     173             : 
     174             : /* Prototypes: these are placed in this block so that they're only seen
     175             :  * on non-netlink platforms.
     176             :  */
     177             : static int if_set_prefix_ctx(const struct zebra_dplane_ctx *ctx);
     178             : static int if_unset_prefix_ctx(const struct zebra_dplane_ctx *ctx);
     179             : static int if_set_prefix6_ctx(const struct zebra_dplane_ctx *ctx);
     180             : static int if_unset_prefix6_ctx(const struct zebra_dplane_ctx *ctx);
     181             : 
     182             : enum zebra_dplane_result kernel_address_update_ctx(
     183             :         struct zebra_dplane_ctx *ctx)
     184             : {
     185             :         int ret = -1;
     186             :         const struct prefix *p;
     187             : 
     188             :         p = dplane_ctx_get_intf_addr(ctx);
     189             : 
     190             :         if (dplane_ctx_get_op(ctx) == DPLANE_OP_ADDR_INSTALL) {
     191             :                 if (p->family == AF_INET)
     192             :                         ret = if_set_prefix_ctx(ctx);
     193             :                 else
     194             :                         ret = if_set_prefix6_ctx(ctx);
     195             :         } else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ADDR_UNINSTALL) {
     196             :                 if (p->family == AF_INET)
     197             :                         ret = if_unset_prefix_ctx(ctx);
     198             :                 else
     199             :                         ret = if_unset_prefix6_ctx(ctx);
     200             :         } else {
     201             :                 if (IS_ZEBRA_DEBUG_DPLANE)
     202             :                         zlog_debug("Invalid op in interface-addr install");
     203             :         }
     204             : 
     205             :         return (ret == 0 ?
     206             :                 ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE);
     207             : }
     208             : 
     209             : #ifdef HAVE_STRUCT_IFALIASREQ
     210             : 
     211             : /*
     212             :  * Helper for interface-addr install, non-netlink
     213             :  */
     214             : static int if_set_prefix_ctx(const struct zebra_dplane_ctx *ctx)
     215             : {
     216             :         int ret;
     217             :         struct ifaliasreq addreq;
     218             :         struct sockaddr_in addr, mask, peer;
     219             :         struct prefix_ipv4 *p;
     220             : 
     221             :         p = (struct prefix_ipv4 *)dplane_ctx_get_intf_addr(ctx);
     222             : 
     223             :         memset(&addreq, 0, sizeof(addreq));
     224             :         strlcpy((char *)&addreq.ifra_name, dplane_ctx_get_ifname(ctx),
     225             :                 sizeof(addreq.ifra_name));
     226             : 
     227             :         memset(&addr, 0, sizeof(addr));
     228             :         addr.sin_addr = p->prefix;
     229             :         addr.sin_family = p->family;
     230             : #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
     231             :         addr.sin_len = sizeof(struct sockaddr_in);
     232             : #endif
     233             :         memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in));
     234             : 
     235             :         if (dplane_ctx_intf_is_connected(ctx)) {
     236             :                 p = (struct prefix_ipv4 *)dplane_ctx_get_intf_dest(ctx);
     237             :                 memset(&mask, 0, sizeof(mask));
     238             :                 peer.sin_addr = p->prefix;
     239             :                 peer.sin_family = p->family;
     240             : #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
     241             :                 peer.sin_len = sizeof(struct sockaddr_in);
     242             : #endif
     243             :                 memcpy(&addreq.ifra_broadaddr, &peer,
     244             :                        sizeof(struct sockaddr_in));
     245             :         }
     246             : 
     247             :         memset(&mask, 0, sizeof(mask));
     248             :         masklen2ip(p->prefixlen, &mask.sin_addr);
     249             :         mask.sin_family = p->family;
     250             : #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
     251             :         mask.sin_len = sizeof(struct sockaddr_in);
     252             : #endif
     253             :         memcpy(&addreq.ifra_mask, &mask, sizeof(struct sockaddr_in));
     254             : 
     255             :         ret = if_ioctl(SIOCAIFADDR, (caddr_t)&addreq);
     256             :         if (ret < 0)
     257             :                 return ret;
     258             :         return 0;
     259             : 
     260             : }
     261             : 
     262             : /*
     263             :  * Helper for interface-addr un-install, non-netlink
     264             :  */
     265             : static int if_unset_prefix_ctx(const struct zebra_dplane_ctx *ctx)
     266             : {
     267             :         int ret;
     268             :         struct ifaliasreq addreq;
     269             :         struct sockaddr_in addr, mask, peer;
     270             :         struct prefix_ipv4 *p;
     271             : 
     272             :         p = (struct prefix_ipv4 *)dplane_ctx_get_intf_addr(ctx);
     273             : 
     274             :         memset(&addreq, 0, sizeof(addreq));
     275             :         strlcpy((char *)&addreq.ifra_name, dplane_ctx_get_ifname(ctx),
     276             :                 sizeof(addreq.ifra_name));
     277             : 
     278             :         memset(&addr, 0, sizeof(addr));
     279             :         addr.sin_addr = p->prefix;
     280             :         addr.sin_family = p->family;
     281             : #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
     282             :         addr.sin_len = sizeof(struct sockaddr_in);
     283             : #endif
     284             :         memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in));
     285             : 
     286             :         if (dplane_ctx_intf_is_connected(ctx)) {
     287             :                 p = (struct prefix_ipv4 *)dplane_ctx_get_intf_dest(ctx);
     288             :                 memset(&mask, 0, sizeof(mask));
     289             :                 peer.sin_addr = p->prefix;
     290             :                 peer.sin_family = p->family;
     291             : #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
     292             :                 peer.sin_len = sizeof(struct sockaddr_in);
     293             : #endif
     294             :                 memcpy(&addreq.ifra_broadaddr, &peer,
     295             :                        sizeof(struct sockaddr_in));
     296             :         }
     297             : 
     298             :         memset(&mask, 0, sizeof(mask));
     299             :         masklen2ip(p->prefixlen, &mask.sin_addr);
     300             :         mask.sin_family = p->family;
     301             : #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
     302             :         mask.sin_len = sizeof(struct sockaddr_in);
     303             : #endif
     304             :         memcpy(&addreq.ifra_mask, &mask, sizeof(struct sockaddr_in));
     305             : 
     306             :         ret = if_ioctl(SIOCDIFADDR, (caddr_t)&addreq);
     307             :         if (ret < 0)
     308             :                 return ret;
     309             :         return 0;
     310             : }
     311             : #else
     312             : /* Set up interface's address, netmask (and broadcas? ).  Linux or
     313             :    Solaris uses ifname:number semantics to set IP address aliases. */
     314             : int if_set_prefix_ctx(const struct zebra_dplane_ctx *ctx)
     315             : {
     316             :         int ret;
     317             :         struct ifreq ifreq;
     318             :         struct sockaddr_in addr;
     319             :         struct sockaddr_in broad;
     320             :         struct sockaddr_in mask;
     321             :         struct prefix_ipv4 ifaddr;
     322             :         struct prefix_ipv4 *p;
     323             : 
     324             :         p = (struct prefix_ipv4 *)dplane_ctx_get_intf_addr(ctx);
     325             : 
     326             :         ifaddr = *p;
     327             : 
     328             :         strlcpy(ifreq.ifr_name, dplane_ctx_get_ifname(ctx),
     329             :                 sizeof(ifreq.ifr_name));
     330             : 
     331             :         addr.sin_addr = p->prefix;
     332             :         addr.sin_family = p->family;
     333             :         memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in));
     334             :         ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq);
     335             :         if (ret < 0)
     336             :                 return ret;
     337             : 
     338             :         /* We need mask for make broadcast addr. */
     339             :         masklen2ip(p->prefixlen, &mask.sin_addr);
     340             : 
     341             :         if (dplane_ctx_intf_is_broadcast(ctx)) {
     342             :                 apply_mask_ipv4(&ifaddr);
     343             :                 addr.sin_addr = ifaddr.prefix;
     344             : 
     345             :                 broad.sin_addr.s_addr =
     346             :                         (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr);
     347             :                 broad.sin_family = p->family;
     348             : 
     349             :                 memcpy(&ifreq.ifr_broadaddr, &broad,
     350             :                        sizeof(struct sockaddr_in));
     351             :                 ret = if_ioctl(SIOCSIFBRDADDR, (caddr_t)&ifreq);
     352             :                 if (ret < 0)
     353             :                         return ret;
     354             :         }
     355             : 
     356             :         mask.sin_family = p->family;
     357             :         memcpy(&ifreq.ifr_addr, &mask, sizeof(struct sockaddr_in));
     358             :         ret = if_ioctl(SIOCSIFNETMASK, (caddr_t)&ifreq);
     359             :         if (ret < 0)
     360             :                 return ret;
     361             : 
     362             :         return 0;
     363             : }
     364             : 
     365             : /* Set up interface's address, netmask (and broadcas? ).  Linux or
     366             :    Solaris uses ifname:number semantics to set IP address aliases. */
     367             : int if_unset_prefix_ctx(const struct zebra_dplane_ctx *ctx)
     368             : {
     369             :         int ret;
     370             :         struct ifreq ifreq;
     371             :         struct sockaddr_in addr;
     372             :         struct prefix_ipv4 *p;
     373             : 
     374             :         p = (struct prefix_ipv4 *)dplane_ctx_get_intf_addr(ctx);
     375             : 
     376             :         strlcpy(ifreq.ifr_name, dplane_ctx_get_ifname(ctx),
     377             :                 sizeof(ifreq.ifr_name));
     378             : 
     379             :         memset(&addr, 0, sizeof(addr));
     380             :         addr.sin_family = p->family;
     381             :         memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in));
     382             :         ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq);
     383             :         if (ret < 0)
     384             :                 return ret;
     385             : 
     386             :         return 0;
     387             : }
     388             : #endif /* HAVE_STRUCT_IFALIASREQ */
     389             : #endif /* HAVE_NETLINK */
     390             : 
     391             : /* get interface flags */
     392           0 : void if_get_flags(struct interface *ifp)
     393             : {
     394           0 :         int ret;
     395           0 :         struct ifreq ifreqflags = {};
     396           0 :         struct ifreq ifreqdata = {};
     397             : 
     398           0 :         ifreq_set_name(&ifreqflags, ifp);
     399           0 :         ifreq_set_name(&ifreqdata, ifp);
     400             : 
     401           0 :         ret = vrf_if_ioctl(SIOCGIFFLAGS, (caddr_t)&ifreqflags,
     402           0 :                            ifp->vrf->vrf_id);
     403           0 :         if (ret < 0) {
     404           0 :                 flog_err_sys(EC_LIB_SYSTEM_CALL,
     405             :                              "vrf_if_ioctl(SIOCGIFFLAGS %s) failed: %s",
     406             :                              ifp->name, safe_strerror(errno));
     407           0 :                 return;
     408             :         }
     409             : 
     410           0 :         if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
     411             :                 goto out;
     412             : 
     413             :         /* Per-default, IFF_RUNNING is held high, unless link-detect
     414             :          * says otherwise - we abuse IFF_RUNNING inside zebra as a
     415             :          * link-state flag, following practice on Linux and Solaris
     416             :          * kernels
     417             :          */
     418             : 
     419             : #ifdef SIOCGIFDATA
     420             :         /*
     421             :          * BSD gets link state from ifi_link_link in struct if_data.
     422             :          * All BSD's have this in getifaddrs(3) ifa_data for AF_LINK
     423             :          * addresses. We can also access it via SIOCGIFDATA.
     424             :          */
     425             : 
     426             : #ifdef __NetBSD__
     427             :         struct ifdatareq ifdr = {.ifdr_data.ifi_link_state = 0};
     428             :         struct if_data *ifdata = &ifdr.ifdr_data;
     429             : 
     430             :         strlcpy(ifdr.ifdr_name, ifp->name, sizeof(ifdr.ifdr_name));
     431             :         ret = vrf_if_ioctl(SIOCGIFDATA, (caddr_t)&ifdr, ifp->vrf->vrf_id);
     432             : #else
     433             :         struct if_data ifd = {.ifi_link_state = 0};
     434             :         struct if_data *ifdata = &ifd;
     435             : 
     436             :         ifreqdata.ifr_data = (caddr_t)ifdata;
     437             :         ret = vrf_if_ioctl(SIOCGIFDATA, (caddr_t)&ifreqdata, ifp->vrf->vrf_id);
     438             : #endif
     439             : 
     440             :         if (ret == -1)
     441             :                 /* Very unlikely. Did the interface disappear? */
     442             :                 flog_err_sys(EC_LIB_SYSTEM_CALL,
     443             :                              "if_ioctl(SIOCGIFDATA %s) failed: %s", ifp->name,
     444             :                              safe_strerror(errno));
     445             :         else {
     446             :                 if (ifdata->ifi_link_state >= LINK_STATE_UP)
     447             :                         SET_FLAG(ifreqflags.ifr_flags, IFF_RUNNING);
     448             :                 else if (ifdata->ifi_link_state == LINK_STATE_UNKNOWN)
     449             :                         /* BSD traditionally treats UNKNOWN as UP */
     450             :                         SET_FLAG(ifreqflags.ifr_flags, IFF_RUNNING);
     451             :                 else
     452             :                         UNSET_FLAG(ifreqflags.ifr_flags, IFF_RUNNING);
     453             :         }
     454             : 
     455             : #elif defined(HAVE_BSD_LINK_DETECT)
     456             :         /*
     457             :          * This is only needed for FreeBSD older than FreeBSD-13.
     458             :          * Valid and active media generally means the link state is
     459             :          * up, but this is not always the case.
     460             :          * For example, some BSD's with a net80211 interface in MONITOR
     461             :          * mode will treat the media as valid and active but the
     462             :          * link state is down - because we cannot send anything.
     463             :          * Also, virtual interfaces such as PPP, VLAN, etc generally
     464             :          * don't support media at all, so the ioctl will just fail.
     465             :          */
     466             :         struct ifmediareq ifmr = {.ifm_status = 0};
     467             : 
     468             :         strlcpy(ifmr.ifm_name, ifp->name, sizeof(ifmr.ifm_name));
     469             : 
     470             :         if (if_ioctl(SIOCGIFMEDIA, (caddr_t)&ifmr) == -1) {
     471             :                 if (errno != EINVAL)
     472             :                         flog_err_sys(EC_LIB_SYSTEM_CALL,
     473             :                                      "if_ioctl(SIOCGIFMEDIA %s) failed: %s",
     474             :                                      ifp->name, safe_strerror(errno));
     475             :         } else if (ifmr.ifm_status & IFM_AVALID) { /* media state is valid */
     476             :                 if (ifmr.ifm_status & IFM_ACTIVE)  /* media is active */
     477             :                         SET_FLAG(ifreqflags.ifr_flags, IFF_RUNNING);
     478             :                 else
     479             :                         UNSET_FLAG(ifreqflags.ifr_flags, IFF_RUNNING);
     480             :         }
     481             : #endif /* HAVE_BSD_LINK_DETECT */
     482             : 
     483           0 : out:
     484           0 :         if_flags_update(ifp, (ifreqflags.ifr_flags & 0x0000ffff));
     485             : }
     486             : 
     487             : /* Set interface flags */
     488           0 : int if_set_flags(struct interface *ifp, uint64_t flags)
     489             : {
     490           0 :         int ret;
     491           0 :         struct ifreq ifreq;
     492             : 
     493           0 :         memset(&ifreq, 0, sizeof(ifreq));
     494           0 :         ifreq_set_name(&ifreq, ifp);
     495             : 
     496           0 :         ifreq.ifr_flags = ifp->flags;
     497           0 :         ifreq.ifr_flags |= flags;
     498             : 
     499           0 :         ret = vrf_if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq, ifp->vrf->vrf_id);
     500             : 
     501           0 :         if (ret < 0) {
     502           0 :                 zlog_info("can't set interface %s(%u) flags %" PRIu64,
     503             :                           ifp->name, ifp->vrf->vrf_id, flags);
     504           0 :                 return ret;
     505             :         }
     506             :         return 0;
     507             : }
     508             : 
     509             : /* Unset interface's flag. */
     510           0 : int if_unset_flags(struct interface *ifp, uint64_t flags)
     511             : {
     512           0 :         int ret;
     513           0 :         struct ifreq ifreq;
     514             : 
     515           0 :         memset(&ifreq, 0, sizeof(ifreq));
     516           0 :         ifreq_set_name(&ifreq, ifp);
     517             : 
     518           0 :         ifreq.ifr_flags = ifp->flags;
     519           0 :         ifreq.ifr_flags &= ~flags;
     520             : 
     521           0 :         ret = vrf_if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq, ifp->vrf->vrf_id);
     522             : 
     523           0 :         if (ret < 0) {
     524           0 :                 zlog_warn("can't unset interface %s(%u) flags %" PRIu64,
     525             :                           ifp->name, ifp->vrf->vrf_id, flags);
     526           0 :                 return ret;
     527             :         }
     528             :         return 0;
     529             : }
     530             : 
     531             : #ifndef LINUX_IPV6 /* Netlink has its own code */
     532             : 
     533             : #ifdef HAVE_STRUCT_IN6_ALIASREQ
     534             : #ifndef ND6_INFINITE_LIFETIME
     535             : #define ND6_INFINITE_LIFETIME 0xffffffffL
     536             : #endif /* ND6_INFINITE_LIFETIME */
     537             : 
     538             : /*
     539             :  * Helper for interface-addr install, non-netlink
     540             :  */
     541             : static int if_set_prefix6_ctx(const struct zebra_dplane_ctx *ctx)
     542             : {
     543             :         int ret;
     544             :         struct in6_aliasreq addreq;
     545             :         struct sockaddr_in6 addr;
     546             :         struct sockaddr_in6 mask;
     547             :         struct prefix_ipv6 *p;
     548             : 
     549             :         p = (struct prefix_ipv6 *)dplane_ctx_get_intf_addr(ctx);
     550             : 
     551             :         memset(&addreq, 0, sizeof(addreq));
     552             :         strlcpy((char *)&addreq.ifra_name,
     553             :                 dplane_ctx_get_ifname(ctx), sizeof(addreq.ifra_name));
     554             : 
     555             :         memset(&addr, 0, sizeof(addr));
     556             :         addr.sin6_addr = p->prefix;
     557             :         addr.sin6_family = p->family;
     558             : #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
     559             :         addr.sin6_len = sizeof(struct sockaddr_in6);
     560             : #endif
     561             :         memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in6));
     562             : 
     563             :         memset(&mask, 0, sizeof(mask));
     564             :         masklen2ip6(p->prefixlen, &mask.sin6_addr);
     565             :         mask.sin6_family = p->family;
     566             : #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
     567             :         mask.sin6_len = sizeof(struct sockaddr_in6);
     568             : #endif
     569             :         memcpy(&addreq.ifra_prefixmask, &mask, sizeof(struct sockaddr_in6));
     570             : 
     571             :         addreq.ifra_lifetime.ia6t_vltime = 0xffffffff;
     572             :         addreq.ifra_lifetime.ia6t_pltime = 0xffffffff;
     573             : 
     574             : #ifdef HAVE_STRUCT_IF6_ALIASREQ_IFRA_LIFETIME
     575             :         addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
     576             :         addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
     577             : #endif
     578             : 
     579             :         ret = if_ioctl_ipv6(SIOCAIFADDR_IN6, (caddr_t)&addreq);
     580             :         if (ret < 0)
     581             :                 return ret;
     582             :         return 0;
     583             : }
     584             : 
     585             : /*
     586             :  * Helper for interface-addr un-install, non-netlink
     587             :  */
     588             : static int if_unset_prefix6_ctx(const struct zebra_dplane_ctx *ctx)
     589             : {
     590             :         int ret;
     591             :         struct in6_aliasreq addreq;
     592             :         struct sockaddr_in6 addr;
     593             :         struct sockaddr_in6 mask;
     594             :         struct prefix_ipv6 *p;
     595             : 
     596             :         p = (struct prefix_ipv6 *)dplane_ctx_get_intf_addr(ctx);
     597             : 
     598             :         memset(&addreq, 0, sizeof(addreq));
     599             :         strlcpy((char *)&addreq.ifra_name,
     600             :                 dplane_ctx_get_ifname(ctx), sizeof(addreq.ifra_name));
     601             : 
     602             :         memset(&addr, 0, sizeof(addr));
     603             :         addr.sin6_addr = p->prefix;
     604             :         addr.sin6_family = p->family;
     605             : #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
     606             :         addr.sin6_len = sizeof(struct sockaddr_in6);
     607             : #endif
     608             :         memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in6));
     609             : 
     610             :         memset(&mask, 0, sizeof(mask));
     611             :         masklen2ip6(p->prefixlen, &mask.sin6_addr);
     612             :         mask.sin6_family = p->family;
     613             : #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
     614             :         mask.sin6_len = sizeof(struct sockaddr_in6);
     615             : #endif
     616             :         memcpy(&addreq.ifra_prefixmask, &mask, sizeof(struct sockaddr_in6));
     617             : 
     618             : #ifdef HAVE_STRUCT_IF6_ALIASREQ_IFRA_LIFETIME
     619             :         addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
     620             :         addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
     621             : #endif
     622             : 
     623             :         ret = if_ioctl_ipv6(SIOCDIFADDR_IN6, (caddr_t)&addreq);
     624             :         if (ret < 0)
     625             :                 return ret;
     626             :         return 0;
     627             : }
     628             : #else
     629             : /* The old, pre-dataplane code here just returned, so we're retaining that
     630             :  * choice.
     631             :  */
     632             : static int if_set_prefix6_ctx(const struct zebra_dplane_ctx *ctx)
     633             : {
     634             :         return 0;
     635             : }
     636             : 
     637             : static int if_unset_prefix6_ctx(const struct zebra_dplane_ctx *ctx)
     638             : {
     639             :         return 0;
     640             : }
     641             : #endif /* HAVE_STRUCT_IN6_ALIASREQ */
     642             : 
     643             : #endif /* LINUX_IPV6 */

Generated by: LCOV version v1.16-topotato