]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/ioctl_solaris.c
zebra: Refactor kernel_rtm to be a bit smarter about how it handles options
[mirror_frr.git] / zebra / ioctl_solaris.c
index 4bdbdaa584f4792eaf267c1ffef3f2f1c2729280..fc554219bcf989d68d0d242f42236b7e7f35b591 100644 (file)
@@ -21,6 +21,8 @@
 
 #include <zebra.h>
 
+#ifdef SUNOS_5
+
 #include "linklist.h"
 #include "if.h"
 #include "prefix.h"
 #include "log.h"
 #include "privs.h"
 #include "vty.h"
+#include "vrf.h"
+#include "lib_errors.h"
 
 #include "zebra/rib.h"
 #include "zebra/rt.h"
 #include "zebra/interface.h"
 #include "zebra/ioctl_solaris.h"
+#include "zebra/zebra_errors.h"
 
 extern struct zebra_privs_t zserv_privs;
 
 /* clear and set interface name string */
-void
-lifreq_set_name (struct lifreq *lifreq, const char *ifname)
+void lifreq_set_name(struct lifreq *lifreq, const char *ifname)
+{
+       strncpy(lifreq->lifr_name, ifname, IFNAMSIZ);
+}
+
+int vrf_if_ioctl(unsigned long request, caddr_t buffer, vrf_id_t vrf_id)
 {
-  strncpy (lifreq->lifr_name, ifname, IFNAMSIZ);
+       return if_ioctl(request, buffer);
 }
 
 /* call ioctl system call */
-int
-if_ioctl (u_long request, caddr_t buffer)
+int if_ioctl(unsigned long request, caddr_t buffer)
 {
-  int sock;
-  int ret;
-  int err;
-
-  if (zserv_privs.change(ZPRIVS_RAISE))
-    zlog_err("Can't raise privileges");
-    
-  sock = socket (AF_INET, SOCK_DGRAM, 0);
-  if (sock < 0)
-    {
-      int save_errno = errno;
-      if (zserv_privs.change(ZPRIVS_LOWER))
-        zlog_err("Can't lower privileges");
-      zlog_err("Cannot create UDP socket: %s", safe_strerror(save_errno));
-      exit (1);
-    }
-
-  if ((ret = ioctl (sock, request, buffer)) < 0)
-    err = errno;
-  
-  if (zserv_privs.change(ZPRIVS_LOWER))
-    zlog_err("Can't lower privileges");
-
-  close (sock);
-
-  if (ret < 0)
-    {
-      errno = err;
-      return ret;
-    }
-  return 0;
+       int sock;
+       int ret;
+       int err;
+
+       frr_elevate_privs(&zserv_privs) {
+
+               sock = socket(AF_INET, SOCK_DGRAM, 0);
+               if (sock < 0) {
+                       zlog_err("Cannot create UDP socket: %s",
+                                safe_strerror(errno));
+                       exit(1);
+               }
+
+               if ((ret = ioctl(sock, request, buffer)) < 0)
+                       err = errno;
+
+       }
+
+       close(sock);
+
+       if (ret < 0) {
+               errno = err;
+               return ret;
+       }
+       return 0;
 }
 
 
-int
-if_ioctl_ipv6 (u_long request, caddr_t buffer)
+int if_ioctl_ipv6(unsigned long request, caddr_t buffer)
 {
-  int sock;
-  int ret;
-  int err;
-
-  if (zserv_privs.change(ZPRIVS_RAISE))
-    zlog_err("Can't raise privileges");
-
-  sock = socket (AF_INET6, SOCK_DGRAM, 0);
-  if (sock < 0)
-    {
-      int save_errno = errno;
-      if (zserv_privs.change(ZPRIVS_LOWER))
-        zlog_err("Can't lower privileges");
-      zlog_err("Cannot create IPv6 datagram socket: %s",
-              safe_strerror(save_errno));
-      exit (1);
-    }
-
-  if ((ret = ioctl (sock, request, buffer)) < 0)
-    err = errno;
-
-  if (zserv_privs.change(ZPRIVS_LOWER))
-    zlog_err("Can't lower privileges");
-
-  close (sock);
-
-  if (ret < 0)
-    {
-      errno = err;
-      return ret;
-    }
-
-  return 0;
+       int sock;
+       int ret;
+       int err;
+
+       frr_elevate_privs(&zserv_privs) {
+
+               sock = socket(AF_INET6, SOCK_DGRAM, 0);
+               if (sock < 0) {
+                       zlog_err("Cannot create IPv6 datagram socket: %s",
+                                safe_strerror(errno));
+                       exit(1);
+               }
+
+               if ((ret = ioctl(sock, request, buffer)) < 0)
+                       err = errno;
+
+       }
+
+       close(sock);
+
+       if (ret < 0) {
+               errno = err;
+               return ret;
+       }
+
+       return 0;
 }
 
 /*
  * get interface metric
  *   -- if value is not avaliable set -1
  */
-void
-if_get_metric (struct interface *ifp)
+void if_get_metric(struct interface *ifp)
 {
-  struct lifreq lifreq;
-  int ret;
+       struct lifreq lifreq;
+       int ret;
 
-  lifreq_set_name (&lifreq, ifp->name);
+       lifreq_set_name(&lifreq, ifp->name);
 
-  if (ifp->flags & IFF_IPV4)
-    ret = AF_IOCTL (AF_INET, SIOCGLIFMETRIC, (caddr_t) & lifreq);
+       if (ifp->flags & IFF_IPV4)
+               ret = AF_IOCTL(AF_INET, SIOCGLIFMETRIC, (caddr_t)&lifreq);
 #ifdef SOLARIS_IPV6
-  else if (ifp->flags & IFF_IPV6)
-    ret = AF_IOCTL (AF_INET6, SIOCGLIFMETRIC, (caddr_t) & lifreq);
+       else if (ifp->flags & IFF_IPV6)
+               ret = AF_IOCTL(AF_INET6, SIOCGLIFMETRIC, (caddr_t)&lifreq);
 #endif /* SOLARIS_IPV6 */
-  else
-    ret = -1;
-    
-  if (ret < 0)
-    return;
+       else
+               ret = -1;
 
-  ifp->metric = lifreq.lifr_metric;
+       if (ret < 0)
+               return;
 
-  if (ifp->metric == 0)
-    ifp->metric = 1;
+       ifp->metric = lifreq.lifr_metric;
+
+       if (ifp->metric == 0)
+               ifp->metric = 1;
 }
 
 /* get interface MTU */
-void
-if_get_mtu (struct interface *ifp)
+void if_get_mtu(struct interface *ifp)
 {
-  struct lifreq lifreq;
-  int ret;
-  u_char changed = 0;
-  
-  if (ifp->flags & IFF_IPV4)
-    {
-      lifreq_set_name (&lifreq, ifp->name);
-      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;
-          changed = 1;
-        }
-    }
-
-  if (ifp->flags & IFF_IPV6)
-  {
-    memset(&lifreq, 0, sizeof(lifreq));
-    lifreq_set_name (&lifreq, ifp->name);
-
-    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;
-      changed = 1;
-    }
-  }
-
-  if (changed)
-    zebra_interface_up_update(ifp);
+       struct lifreq lifreq;
+       int ret;
+       uint8_t changed = 0;
+
+       if (ifp->flags & IFF_IPV4) {
+               lifreq_set_name(&lifreq, ifp->name);
+               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;
+                       changed = 1;
+               }
+       }
+
+       if (ifp->flags & IFF_IPV6) {
+               memset(&lifreq, 0, sizeof(lifreq));
+               lifreq_set_name(&lifreq, ifp->name);
+
+               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;
+                       changed = 1;
+               }
+       }
+
+       if (changed)
+               zebra_interface_up_update(ifp);
 }
 
 /* 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 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;
+       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;
+       p = (struct prefix_ipv4 *)ifc->address;
 
-  ifaddr = *p;
+       ifaddr = *p;
 
-  strncpy (ifreq.ifr_name, ifp->name, IFNAMSIZ);
+       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));
+       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);
+       ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq);
 
-  if (ret < 0)
-    return ret;
+       if (ret < 0)
+               return ret;
 
-  /* We need mask for make broadcast addr. */
-  masklen2ip (p->prefixlen, &mask.sin_addr);
+       /* 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;
+       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;
+               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)
-        return ret;
-    }
+               memcpy(&ifreq.ifr_broadaddr, &broad,
+                      sizeof(struct sockaddr_in));
+               ret = if_ioctl(SIOCSIFBRDADDR, (caddr_t)&ifreq);
+               if (ret < 0)
+                       return ret;
+       }
 
-  mask.sin_family = p->family;
+       mask.sin_family = p->family;
 #ifdef SUNOS_5
-  memcpy (&mask, &ifreq.ifr_addr, sizeof (mask));
+       memcpy(&mask, &ifreq.ifr_addr, sizeof(mask));
 #else
-  memcpy (&ifreq.ifr_netmask, &mask, sizeof (struct sockaddr_in));
+       memcpy(&ifreq.ifr_netmask, &mask, sizeof(struct sockaddr_in));
 #endif /* SUNOS_5 */
-  ret = if_ioctl (SIOCSIFNETMASK, (caddr_t) & ifreq);
+       ret = if_ioctl(SIOCSIFNETMASK, (caddr_t)&ifreq);
 
-  return ((ret < 0) ? ret : 0);
+       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 if_unset_prefix(struct interface *ifp, struct connected *ifc)
 {
-  int ret;
-  struct ifreq ifreq;
-  struct sockaddr_in addr;
-  struct prefix_ipv4 *p;
+       int ret;
+       struct ifreq ifreq;
+       struct sockaddr_in addr;
+       struct prefix_ipv4 *p;
+
+       p = (struct prefix_ipv4 *)ifc->address;
 
-  p = (struct prefix_ipv4 *) ifc->address;
+       strncpy(ifreq.ifr_name, ifp->name, IFNAMSIZ);
 
-  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));
 
-  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);
 
-  ret = if_ioctl (SIOCSIFADDR, (caddr_t) & ifreq);
-  
-  if (ret < 0)
-    return ret;
+       if (ret < 0)
+               return ret;
 
-  return 0;
+       return 0;
 }
 
 /* Get just the flags for the given name.
@@ -283,144 +269,134 @@ if_unset_prefix (struct interface *ifp, struct connected *ifc)
  * as the bootup interface-list code, which has to peek at per-address
  * flags in order to figure out which ones should be ignored..
  */
-int
-if_get_flags_direct (const char *ifname, uint64_t *flags, unsigned int af)
+int if_get_flags_direct(const char *ifname, uint64_t *flags, unsigned int af)
 {
-  struct lifreq lifreq;
-  int ret;
-    
-  lifreq_set_name (&lifreq, ifname);
-  
-  ret = AF_IOCTL (af, SIOCGLIFFLAGS, (caddr_t) &lifreq);
-  
-  if (ret)
-    zlog_debug ("%s: ifname %s, error %s (%d)",
-                __func__, ifname, safe_strerror (errno), errno);
-  
-  *flags = lifreq.lifr_flags;
-  
-  return ret;
+       struct lifreq lifreq;
+       int ret;
+
+       lifreq_set_name(&lifreq, ifname);
+
+       ret = AF_IOCTL(af, SIOCGLIFFLAGS, (caddr_t)&lifreq);
+
+       if (ret)
+               zlog_debug("%s: ifname %s, error %s (%d)", __func__, ifname,
+                          safe_strerror(errno), errno);
+
+       *flags = lifreq.lifr_flags;
+
+       return ret;
 }
 
 /* get interface flags */
-void
-if_get_flags (struct interface *ifp)
+void if_get_flags(struct interface *ifp)
 {
-  int ret4 = 0, ret6 = 0;
-  uint64_t newflags = 0;
-  uint64_t tmpflags;
-
-  if (ifp->flags & IFF_IPV4)
-    {
-      ret4 = if_get_flags_direct (ifp->name, &tmpflags, AF_INET);
-      
-      if (!ret4)
-        newflags |= tmpflags;
-      else if (errno == ENXIO)
-        {
-          /* it's gone */
-          UNSET_FLAG (ifp->flags, IFF_UP);
-          if_flags_update (ifp, ifp->flags);
-        }
-    }
-
-  if (ifp->flags & IFF_IPV6)
-    {
-      ret6 = if_get_flags_direct (ifp->name, &tmpflags, AF_INET6);
-      
-      if (!ret6)
-        newflags |= tmpflags;
-      else if (errno == ENXIO)
-        {
-          /* it's gone */
-          UNSET_FLAG (ifp->flags, IFF_UP);
-          if_flags_update (ifp, ifp->flags);
-        }
-    }
-  
-  /* only update flags if one of above succeeded */
-  if ( !(ret4 && ret6) )
-    if_flags_update (ifp, newflags);
+       int ret4 = 0, ret6 = 0;
+       uint64_t newflags = 0;
+       uint64_t tmpflags;
+
+       if (ifp->flags & IFF_IPV4) {
+               ret4 = if_get_flags_direct(ifp->name, &tmpflags, AF_INET);
+
+               if (!ret4)
+                       newflags |= tmpflags;
+               else if (errno == ENXIO) {
+                       /* it's gone */
+                       UNSET_FLAG(ifp->flags, IFF_UP);
+                       if_flags_update(ifp, ifp->flags);
+               }
+       }
+
+       if (ifp->flags & IFF_IPV6) {
+               ret6 = if_get_flags_direct(ifp->name, &tmpflags, AF_INET6);
+
+               if (!ret6)
+                       newflags |= tmpflags;
+               else if (errno == ENXIO) {
+                       /* it's gone */
+                       UNSET_FLAG(ifp->flags, IFF_UP);
+                       if_flags_update(ifp, ifp->flags);
+               }
+       }
+
+       /* only update flags if one of above succeeded */
+       if (!(ret4 && ret6))
+               if_flags_update(ifp, newflags);
 }
 
 /* Set interface flags */
-int
-if_set_flags (struct interface *ifp, uint64_t flags)
+int if_set_flags(struct interface *ifp, uint64_t flags)
 {
-  int ret;
-  struct lifreq lifreq;
-
-  lifreq_set_name (&lifreq, ifp->name);
-
-  lifreq.lifr_flags = ifp->flags;
-  lifreq.lifr_flags |= flags;
-
-  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,
-               safe_strerror (errno));
-  else
-    ret = 0;
-    
-  return ret;
+       int ret;
+       struct lifreq lifreq;
+
+       lifreq_set_name(&lifreq, ifp->name);
+
+       lifreq.lifr_flags = ifp->flags;
+       lifreq.lifr_flags |= flags;
+
+       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,
+                         safe_strerror(errno));
+       else
+               ret = 0;
+
+       return ret;
 }
 
 /* Unset interface's flag. */
-int
-if_unset_flags (struct interface *ifp, uint64_t flags)
+int if_unset_flags(struct interface *ifp, uint64_t flags)
 {
-  int ret;
-  struct lifreq lifreq;
-
-  lifreq_set_name (&lifreq, ifp->name);
-
-  lifreq.lifr_flags = ifp->flags;
-  lifreq.lifr_flags &= ~flags;
-
-  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;
-  
-  return ret;
+       int ret;
+       struct lifreq lifreq;
+
+       lifreq_set_name(&lifreq, ifp->name);
+
+       lifreq.lifr_flags = ifp->flags;
+       lifreq.lifr_flags &= ~flags;
+
+       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;
+
+       return ret;
 }
 
 /* Interface's address add/delete functions. */
-int
-if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc)
+int if_prefix_add_ipv6(struct interface *ifp, struct connected *ifc)
 {
-  char addrbuf[PREFIX_STRLEN];
+       char addrbuf[PREFIX_STRLEN];
 
-  zlog_warn ("Can't set %s on interface %s",
-             prefix2str(ifc->address, addrbuf, sizeof(addrbuf)),
-             ifp->name);
-
-  return 0;
+       flog_warn(EC_LIB_DEVELOPMENT, "Can't set %s on interface %s",
+                 prefix2str(ifc->address, addrbuf, sizeof(addrbuf)),
+                 ifp->name);
 
+       return 0;
 }
 
-int
-if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc)
+int if_prefix_delete_ipv6(struct interface *ifp, struct connected *ifc)
 {
-  char addrbuf[PREFIX_STRLEN];
-
-  zlog_warn ("Can't delete %s on interface %s",
-             prefix2str(ifc->address, addrbuf, sizeof(addrbuf)),
-             ifp->name);
+       char addrbuf[PREFIX_STRLEN];
 
-  return 0;
+       flog_warn(EC_LIB_DEVELOPMENT, "Can't delete %s on interface %s",
+                 prefix2str(ifc->address, addrbuf, sizeof(addrbuf)),
+                 ifp->name);
 
+       return 0;
 }
+
+#endif /* SUNOS_5 */