diff options
Diffstat (limited to 'zebra')
| -rw-r--r-- | zebra/ChangeLog | 6 | ||||
| -rw-r--r-- | zebra/if_ioctl_solaris.c | 348 | ||||
| -rw-r--r-- | zebra/ioctl_solaris.c | 421 | 
3 files changed, 774 insertions, 1 deletions
diff --git a/zebra/ChangeLog b/zebra/ChangeLog index 8920b961..053f9e87 100644 --- a/zebra/ChangeLog +++ b/zebra/ChangeLog @@ -12,6 +12,8 @@  	* rt_netlink.c: (netlink_interface) set mtu6 to mtu  	  (netlink_link_change) ditto   	* ipforward_solaris.c: fix typo of ND variable. +	* if_ioctl_solaris.c: Add zprivs support. +	* ioctl_solaris.c: ditto.  2004-05-09 Sowmini Varadhan <sowmini.varadhan@sun.com> @@ -30,7 +32,9 @@  	  and RTM_IFANNOUNCE.  	  (if_flag_dump_vty) Solaris IFF_IPV4 and IFF_IPV6 if flags  	  (if_dump_vty) print mtu6 if not same as mtu	   -	   +	* if_ioctl_solaris.c: New file, Solaris interface ioctl methods. +	* ioctl_solaris.c: New file, Common solaris ioctl methods. +	  2004-04-06  Krzysztof Oledzki <oleq@ans.pl>  	* rt_netlink.c: Do not ignore metric when reading kernel routing diff --git a/zebra/if_ioctl_solaris.c b/zebra/if_ioctl_solaris.c new file mode 100644 index 00000000..b07580c2 --- /dev/null +++ b/zebra/if_ioctl_solaris.c @@ -0,0 +1,348 @@ +/* + * Interface looking up by ioctl () on Solaris. + * Copyright (C) 1997, 98 Kunihiro Ishiguro + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING.  If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA.   + */ + +#include <zebra.h> + +#include "if.h" +#include "sockunion.h" +#include "prefix.h" +#include "ioctl.h" +#include "connected.h" +#include "memory.h" +#include "log.h" + +#include "zebra/interface.h" + +void lifreq_set_name (struct lifreq *, struct interface *); +static int if_get_addr (struct interface *, struct sockaddr *); +static void interface_info_ioctl (struct interface *); + + +int +interface_list_ioctl (int af) +{ +  int ret; +  int sock; +#define IFNUM_BASE 32 +  struct lifnum lifn; +  int ifnum; +  struct lifreq *lifreq; +  struct lifconf lifconf; +  struct interface *ifp; +  int n; +  size_t needed, lastneeded = 0; +  char *buf = NULL; + +  if (zserv_privs.change(ZPRIVS_RAISE)) +    zlog (NULL, LOG_ERR, "Can't raise privileges"); +   +  sock = socket (af, SOCK_DGRAM, 0); +  if (sock < 0) +    { +      zlog_warn ("Can't make %s socket stream: %s", +                 (af == AF_INET ? "AF_INET" : "AF_INET6"), strerror (errno)); +                  +      if (zserv_privs.change(ZPRIVS_LOWER)) +        zlog (NULL, LOG_ERR, "Can't lower privileges"); +         +      return -1; +    } + +calculate_lifc_len:     /* must hold privileges to enter here */ +  lifn.lifn_family = af; +  lifn.lifn_flags = 0; +  ret = ioctl (sock, SIOCGLIFNUM, &lifn); +   +  if (zserv_privs.change(ZPRIVS_LOWER)) +    zlog (NULL, LOG_ERR, "Can't lower privileges"); +  +  if (ret < 0) +    { +      zlog_warn ("interface_list_ioctl: SIOCGLIFNUM failed %s", +                 strerror (errno)); +      close (sock); +      return -1; +    } +  ifnum = lifn.lifn_count; + +  /* +   * When calculating the buffer size needed, add a small number +   * of interfaces to those we counted.  We do this to capture +   * the interface status of potential interfaces which may have +   * been plumbed between the SIOCGLIFNUM and the SIOCGLIFCONF. +   */ +  needed = (ifnum + 4) * sizeof (struct lifreq); +  if (needed > lastneeded || needed < lastneeded / 2) +    { +      if (buf != NULL) +        XFREE (MTYPE_TMP, buf); +      if ((buf = XMALLOC (MTYPE_TMP, needed)) == NULL) +        { +          zlog_warn ("interface_list_ioctl: malloc failed"); +          close (sock); +          return -1; +        } +    } +  lastneeded = needed; + +  lifconf.lifc_family = af; +  lifconf.lifc_flags = 0; +  lifconf.lifc_len = needed; +  lifconf.lifc_buf = buf; + +  if (zserv_privs.change(ZPRIVS_RAISE)) +    zlog (NULL, LOG_ERR, "Can't raise privileges"); +     +  ret = ioctl (sock, SIOCGLIFCONF, &lifconf); + +  if (ret < 0) +    { +      if (errno == EINVAL) +        goto calculate_lifc_len; /* deliberately hold privileges */ + +      zlog_warn ("SIOCGLIFCONF: %s", strerror (errno)); + +      if (zserv_privs.change(ZPRIVS_LOWER)) +        zlog (NULL, LOG_ERR, "Can't lower privileges"); + +      goto end; +    } + +  if (zserv_privs.change(ZPRIVS_LOWER)) +    zlog (NULL, LOG_ERR, "Can't lower privileges"); +     +  /* Allocate interface. */ +  lifreq = lifconf.lifc_req; + +  for (n = 0; n < lifconf.lifc_len; n += sizeof (struct lifreq)) +    { +      ifp = if_get_by_name (lifreq->lifr_name); +      if (lifreq->lifr_addr.ss_family == AF_INET) +        ifp->flags |= IFF_IPV4; +      if (lifreq->lifr_addr.ss_family == AF_INET6) +        ifp->flags |= IFF_IPV6; +      if_add_update (ifp); +      interface_info_ioctl (ifp); +      if_get_addr (ifp, (struct sockaddr *) &lifreq->lifr_addr); +      lifreq++; +    } + +end: +  close (sock); +  XFREE (MTYPE_TMP, lifconf.lifc_buf); +  return ret; +} + +/* Get interface's index by ioctl. */ +int +if_get_index (struct interface *ifp) +{ +  int ret; +  struct lifreq lifreq; + +  lifreq_set_name (&lifreq, ifp); + +  if (zserv_privs.change(ZPRIVS_RAISE)) +    zlog (NULL, LOG_ERR, "Can't raise privileges"); + +  if (ifp->flags & IFF_IPV4) +    ret = AF_IOCTL (AF_INET, SIOCGLIFINDEX, (caddr_t) & lifreq); +  else if (ifp->flags & IFF_IPV6) +    ret = AF_IOCTL (AF_INET6, SIOCGLIFINDEX, (caddr_t) & lifreq); +  else +    ret = -1; + +  if (zserv_privs.change(ZPRIVS_LOWER)) +    zlog (NULL, LOG_ERR, "Can't lower privileges"); + +  if (ret < 0) +    { +      zlog_warn ("SIOCGLIFINDEX(%s) failed", ifp->name); +      return ret; +    } + +  /* OK we got interface index. */ +#ifdef ifr_ifindex +  ifp->ifindex = lifreq.lifr_ifindex; +#else +  ifp->ifindex = lifreq.lifr_index; +#endif +  return ifp->ifindex; + +} + + +/* Interface address lookup by ioctl.  This function only looks up +   IPv4 address. */ +#define ADDRLEN(sa) (((sa)->sa_family == AF_INET ?  \ +                sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6))) + +#define SIN(s) ((struct sockaddr_in *)(s)) +#define SIN6(s) ((struct sockaddr_in6 *)(s)) + +static int +if_get_addr (struct interface *ifp, struct sockaddr *addr) +{ +  int ret; +  struct lifreq lifreq; +  struct sockaddr_storage mask, dest; +  char *dest_pnt = NULL; +  u_char prefixlen = 0; +  afi_t af; + +  /* Interface's name and address family. */ +  strncpy (lifreq.lifr_name, ifp->name, IFNAMSIZ); + +  /* Interface's address. */ +  memcpy (&lifreq.lifr_addr, addr, ADDRLEN (addr)); +  af = addr->sa_family; + +  /* Point to point or broad cast address pointer init. */ +  dest_pnt = NULL; + +  if (ifp->flags & IFF_POINTOPOINT) +    { +      if (zserv_privs.change(ZPRIVS_RAISE)) +        zlog (NULL, LOG_ERR, "Can't raise privileges");       + +      ret = AF_IOCTL (af, SIOCGLIFDSTADDR, (caddr_t) & lifreq); + +      if (zserv_privs.change(ZPRIVS_LOWER)) +        zlog (NULL, LOG_ERR, "Can't lower privileges"); +         +      if (ret < 0) +        { +          zlog_warn ("SIOCGLIFDSTADDR (%s) fail: %s", +                     ifp->name, strerror (errno)); +          return ret; +        } +      memcpy (&dest, &lifreq.lifr_dstaddr, ADDRLEN (addr)); +      if (af == AF_INET) +        dest_pnt = (char *) &(SIN (&dest)->sin_addr); +      else +        dest_pnt = (char *) &(SIN6 (&dest)->sin6_addr); +    } + +  if (af == AF_INET) +    { +      ret = if_ioctl (SIOCGLIFNETMASK, (caddr_t) & lifreq); +       +      if (ret < 0) +        { +          if (errno != EADDRNOTAVAIL) +            { +              zlog_warn ("SIOCGLIFNETMASK (%s) fail: %s", ifp->name, +                         strerror (errno)); +              return ret; +            } +          return 0; +        } +      memcpy (&mask, &lifreq.lifr_addr, ADDRLEN (addr)); + +      prefixlen = ip_masklen (SIN (&mask)->sin_addr); +      if (ifp->flags & IFF_BROADCAST) +        { +          ret = if_ioctl (SIOCGLIFBRDADDR, (caddr_t) & lifreq); +          if (ret < 0) +            { +              if (errno != EADDRNOTAVAIL) +                { +                  zlog_warn ("SIOCGLIFBRDADDR (%s) fail: %s", +                             ifp->name, strerror (errno)); +                  return ret; +                } +              return 0; +            } +          memcpy (&dest, &lifreq.lifr_broadaddr, sizeof (struct sockaddr_in)); +          dest_pnt = (char *) &SIN (&dest)->sin_addr; +        } +    } +  else +    { +      if (ifp->flags & IFF_POINTOPOINT) +        { +          prefixlen = IPV6_MAX_BITLEN; +        } +      else +        { +          ret = if_ioctl_ipv6 (SIOCGLIFSUBNET, (caddr_t) & lifreq); +          if (ret < 0) +            { +              zlog_warn ("SIOCGLIFSUBNET (%s) fail: %s", +                         ifp->name, strerror (errno)); +            } +          else +            { +              prefixlen = lifreq.lifr_addrlen; +            } +        } +    } + + +  /* Set address to the interface. */ +  if (af == AF_INET) +    connected_add_ipv4 (ifp, 0, &SIN (addr)->sin_addr, prefixlen, +                        (struct in_addr *) dest_pnt, NULL); +  else +    connected_add_ipv6 (ifp, &SIN6 (addr)->sin6_addr, prefixlen, +                        (struct in6_addr *) dest_pnt); + +  return 0; +} + +/* Fetch interface information via ioctl(). */ +static void +interface_info_ioctl (struct interface *ifp) +{ +  if_get_index (ifp); +  if_get_flags (ifp); +  if_get_mtu (ifp); +  if_get_metric (ifp); +} + +/* Lookup all interface information. */ +void +interface_list () +{ +  interface_list_ioctl (AF_INET); +  interface_list_ioctl (AF_INET6); +} + +struct connected * +if_lookup_linklocal (struct interface *ifp) +{ +  listnode node; +  struct connected *ifc; + +  if (ifp == NULL) +    return NULL; + +  for (node = listhead (ifp->connected); node; node = nextnode (node)) +    { +      ifc = getdata (node); + +      if ((ifc->address->family == AF_INET6) && +          (IN6_IS_ADDR_LINKLOCAL (&ifc->address->u.prefix6))) +        return ifc; +    } +  return NULL; +} diff --git a/zebra/ioctl_solaris.c b/zebra/ioctl_solaris.c new file mode 100644 index 00000000..2fdffc61 --- /dev/null +++ b/zebra/ioctl_solaris.c @@ -0,0 +1,421 @@ +/* + * Common ioctl functions for Solaris. + * Copyright (C) 1997, 98 Kunihiro Ishiguro + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING.  If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA.   + */ + +#include <zebra.h> + +#include "linklist.h" +#include "if.h" +#include "prefix.h" +#include "ioctl.h" +#include "log.h" + +#include "zebra/rib.h" +#include "zebra/rt.h" + + +/* clear and set interface name string */ +void +lifreq_set_name (struct lifreq *lifreq, struct interface *ifp) +{ +  strncpy (lifreq->lifr_name, ifp->name, IFNAMSIZ); +} + +/* call ioctl system call */ +int +if_ioctl (u_long request, caddr_t buffer) +{ +  int sock; +  int ret = 0; +  int err = 0; + +  if (zserv_privs.change(ZPRIVS_RAISE)) +    zlog (NULL, LOG_ERR, "Can't raise privileges"); +     +  sock = socket (AF_INET, SOCK_DGRAM, 0); +  if (sock < 0) +    { +      if (zserv_privs.change(ZPRIVS_LOWER)) +        zlog (NULL, LOG_ERR, "Can't lower privileges"); +      perror ("socket"); +      exit (1); +    } + +  ret = ioctl (sock, request, buffer); +   +  if (zserv_privs.change(ZPRIVS_LOWER)) +    zlog (NULL, LOG_ERR, "Can't lower privileges"); + +  if (ret < 0) +    { +      err = errno; +    } +  close (sock); + +  if (ret < 0) +    { +      errno = err; +      return ret; +    } +  return 0; +} + +#ifdef HAVE_IPV6 +int +if_ioctl_ipv6 (u_long request, caddr_t buffer) +{ +  int sock; +  int ret = 0; +  int err = 0; + +  if (zserv_privs.change(ZPRIVS_RAISE)) +    zlog (NULL, LOG_ERR, "Can't raise privileges"); + +  sock = socket (AF_INET6, SOCK_DGRAM, 0); +  if (sock < 0) +    { +      if (zserv_privs.change(ZPRIVS_LOWER)) +        zlog (NULL, LOG_ERR, "Can't lower privileges"); +      perror ("socket"); +      exit (1); +    } + +  ret = ioctl (sock, request, buffer); + +  if (zserv_privs.change(ZPRIVS_LOWER)) +    zlog (NULL, LOG_ERR, "Can't lower privileges"); + +  if (ret < 0) +    { +      err = errno; +    } +  close (sock); + +  if (ret < 0) +    { +      errno = err; +      return ret; +    } +  return 0; +} +#endif /* HAVE_IPV6 */ + +/* + * get interface metric + *   -- if value is not avaliable set -1 + */ +void +if_get_metric (struct interface *ifp) +{ +  struct lifreq lifreq; +  int ret; + +  lifreq_set_name (&lifreq, ifp); + +  if (zserv_privs.change(ZPRIVS_RAISE)) +    zlog (NULL, LOG_ERR, "Can't raise privileges"); +     +  if (ifp->flags & IFF_IPV4) +    ret = AF_IOCTL (AF_INET, SIOCGLIFMETRIC, (caddr_t) & lifreq); +  else if (ifp->flags & IFF_IPV6) +    ret = AF_IOCTL (AF_INET6, SIOCGLIFMETRIC, (caddr_t) & lifreq); +  else +    ret = -1; + +  if (zserv_privs.change(ZPRIVS_LOWER)) +    zlog (NULL, LOG_ERR, "Can't lower privileges"); +     +  if (ret < 0) +    return; + +  ifp->metric = lifreq.lifr_metric; + +  if (ifp->metric == 0) +    ifp->metric = 1; +} + +/* get interface MTU */ +void +if_get_mtu (struct interface *ifp) +{ +  struct lifreq lifreq; +  int ret; +   +  if (zserv_privs.change(ZPRIVS_RAISE)) +    zlog (NULL, LOG_ERR, "Can't raise privileges"); +   +  if (ifp->flags & IFF_IPV4) +    { +      lifreq_set_name (&lifreq, ifp); +      ret = AF_IOCTL (AF_INET, SIOCGLIFMTU, (caddr_t) & lifreq); +      if (ret < 0) +        { +          zlog_info ("Can't lookup mtu on %s by ioctl(SIOCGLIFMTU)", +                     ifp->name); +          ifp->mtu = -1; +        } +      else +        { +          ifp->mtu = lifreq.lifr_metric; +        } +    } + + +  if ((ifp->flags & IFF_IPV6) == 0) +    goto out; + +  lifreq_set_name (&lifreq, ifp); +  ret = AF_IOCTL (AF_INET6, SIOCGLIFMTU, (caddr_t) & lifreq); +  if (ret < 0) +    { +      zlog_info ("Can't lookup mtu6 on %s by ioctl(SIOCGIFMTU)", ifp->name); +      ifp->mtu6 = -1; +    } +  else +    { +      ifp->mtu6 = lifreq.lifr_metric; +    } + +out: +   if (zserv_privs.change(ZPRIVS_LOWER)) +     zlog (NULL, LOG_ERR, "Can't lower privileges"); +} + +/* Set up interface's address, netmask (and broadcast? ). +   Solaris uses ifname:number semantics to set IP address aliases. */ +int +if_set_prefix (struct interface *ifp, struct connected *ifc) +{ +  int ret; +  struct ifreq ifreq; +  struct sockaddr_in addr; +  struct sockaddr_in broad; +  struct sockaddr_in mask; +  struct prefix_ipv4 ifaddr; +  struct prefix_ipv4 *p; + +  p = (struct prefix_ipv4 *) ifc->address; + +  ifaddr = *p; + +  strncpy (ifreq.ifr_name, ifp->name, IFNAMSIZ); + +  addr.sin_addr = p->prefix; +  addr.sin_family = p->family; +  memcpy (&ifreq.ifr_addr, &addr, sizeof (struct sockaddr_in)); + +  ret = if_ioctl (SIOCSIFADDR, (caddr_t) & ifreq); + +  if (ret < 0) +    return ret; + +  /* We need mask for make broadcast addr. */ +  masklen2ip (p->prefixlen, &mask.sin_addr); + +  if (if_is_broadcast (ifp)) +    { +      apply_mask_ipv4 (&ifaddr); +      addr.sin_addr = ifaddr.prefix; + +      broad.sin_addr.s_addr = (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr); +      broad.sin_family = p->family; + +      memcpy (&ifreq.ifr_broadaddr, &broad, sizeof (struct sockaddr_in)); +      ret = if_ioctl (SIOCSIFBRDADDR, (caddr_t) & ifreq); +      if (ret < 0) +        goto out; +    } + +  mask.sin_family = p->family; +#ifdef SUNOS_5 +  memcpy (&mask, &ifreq.ifr_addr, sizeof (mask)); +#else +  memcpy (&ifreq.ifr_netmask, &mask, sizeof (struct sockaddr_in)); +#endif /* SUNOS5 */ +  ret = if_ioctl (SIOCSIFNETMASK, (caddr_t) & ifreq); + +  return ((ret < 0) ? ret : 0); +} + +/* Set up interface's address, netmask (and broadcast). +   Solaris uses ifname:number semantics to set IP address aliases. */ +int +if_unset_prefix (struct interface *ifp, struct connected *ifc) +{ +  int ret; +  struct ifreq ifreq; +  struct sockaddr_in addr; +  struct prefix_ipv4 *p; + +  p = (struct prefix_ipv4 *) ifc->address; + +  strncpy (ifreq.ifr_name, ifp->name, IFNAMSIZ); + +  memset (&addr, 0, sizeof (struct sockaddr_in)); +  addr.sin_family = p->family; +  memcpy (&ifreq.ifr_addr, &addr, sizeof (struct sockaddr_in)); + +  ret = if_ioctl (SIOCSIFADDR, (caddr_t) & ifreq); +   +  if (ret < 0) +    return ret; + +  return 0; +} + +/* get interface flags */ +void +if_get_flags (struct interface *ifp) +{ +  int ret; +  struct lifreq lifreq; +  unsigned long flags4 = 0, flags6 = 0; + +  if (ifp->flags & IFF_IPV4) +    { +      lifreq_set_name (&lifreq, ifp); +       +      if (zserv_privs.change(ZPRIVS_RAISE)) +        zlog (NULL, LOG_ERR, "Can't raise privileges"); +       +      ret = AF_IOCTL (AF_INET, SIOCGLIFFLAGS, (caddr_t) & lifreq); +       +      if (zserv_privs.change(ZPRIVS_LOWER)) +        zlog (NULL, LOG_ERR, "Can't lower privileges"); + +      flags4 = (lifreq.lifr_flags & 0xffffffff); +      if (!(flags4 & IFF_UP)) +        flags4 &= ~IFF_IPV4; +    } + +  if (ifp->flags & IFF_IPV6) +    { +      lifreq_set_name (&lifreq, ifp); +       +      if (zserv_privs.change(ZPRIVS_RAISE)) +        zlog (NULL, LOG_ERR, "Can't raise privileges");       +       +      ret = AF_IOCTL (AF_INET6, SIOCGLIFFLAGS, (caddr_t) & lifreq); +       +      if (zserv_privs.change(ZPRIVS_LOWER)) +        zlog (NULL, LOG_ERR, "Can't lower privileges"); +               +      flags6 = (lifreq.lifr_flags & 0xffffffff); +      if (!(flags6 & IFF_UP)) +        flags6 &= ~IFF_IPV6; +    } + +  ifp->flags = (flags4 | flags6); +} + +/* Set interface flags */ +int +if_set_flags (struct interface *ifp, unsigned long flags) +{ +  int ret; +  struct lifreq lifreq; + +  lifreq_set_name (&lifreq, ifp); + +  lifreq.lifr_flags = ifp->flags; +  lifreq.lifr_flags |= flags; + +  if (zserv_privs.change(ZPRIVS_RAISE)) +    zlog (NULL, LOG_ERR, "Can't raise privileges"); + +  if (ifp->flags & IFF_IPV4) +    ret = AF_IOCTL (AF_INET, SIOCSLIFFLAGS, (caddr_t) & lifreq); +  else if (ifp->flags & IFF_IPV6) +    ret = AF_IOCTL (AF_INET6, SIOCSLIFFLAGS, (caddr_t) & lifreq); +  else +    ret = -1; + +  if (ret < 0) +    zlog_info ("can't set interface flags on %s: %s", ifp->name, +               strerror (errno)); +  else +    ret = 0; + +  if (zserv_privs.change(ZPRIVS_LOWER)) +    zlog (NULL, LOG_ERR, "Can't lower privileges"); +} + +/* Unset interface's flag. */ +int +if_unset_flags (struct interface *ifp, unsigned long flags) +{ +  int ret; +  struct lifreq lifreq; + +  lifreq_set_name (&lifreq, ifp); + +  lifreq.lifr_flags = ifp->flags; +  lifreq.lifr_flags &= ~flags; + +  if (zserv_privs.change(ZPRIVS_RAISE)) +    zlog (NULL, LOG_ERR, "Can't raise privileges"); + +  if (ifp->flags & IFF_IPV4) +    ret = AF_IOCTL (AF_INET, SIOCSLIFFLAGS, (caddr_t) & lifreq); +  else if (ifp->flags & IFF_IPV6) +    ret = AF_IOCTL (AF_INET6, SIOCSLIFFLAGS, (caddr_t) & lifreq); +  else +    ret = -1; + +  if (ret < 0) +    zlog_info ("can't unset interface flags"); +  else +    ret = 0; +   +  if (zserv_privs.change(ZPRIVS_LOWER)) +    zlog (NULL, LOG_ERR, "Can't lower privileges"); +} + +#ifdef HAVE_IPV6 + +/* Interface's address add/delete functions. */ +int +if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc) +{ +  char addrbuf[INET_ADDRSTRLEN]; + +  inet_ntop (AF_INET6, &(((struct prefix_ipv6 *) (ifc->address))->prefix), +             addrbuf, sizeof (addrbuf)); +  zlog_warn ("Can't set %s on interface %s", addrbuf, ifp->name); + +  return 0; + +} + +int +if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc) +{ +  char addrbuf[INET_ADDRSTRLEN]; + +  inet_ntop (AF_INET6, &(((struct prefix_ipv6 *) (ifc->address))->prefix), +             addrbuf, sizeof (addrbuf)); +  zlog_warn ("Can't delete %s on interface %s", addrbuf, ifp->name); + +  return 0; + +} + +#endif /* HAVE_IPV6 */  | 
