back to topotato report
topotato coverage report
Current view: top level - zebra - ioctl.c (source / functions) Hit Total Coverage
Test: test_rip.py::RIPBasic Lines: 0 55 0.0 %
Date: 2023-02-24 18:39:46 Functions: 0 5 0.0 %

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

Generated by: LCOV version v1.16-topotato