summaryrefslogtreecommitdiff
path: root/zebra/ioctl_solaris.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/ioctl_solaris.c')
-rw-r--r--zebra/ioctl_solaris.c91
1 files changed, 49 insertions, 42 deletions
diff --git a/zebra/ioctl_solaris.c b/zebra/ioctl_solaris.c
index ec1d2c44..2f05bf12 100644
--- a/zebra/ioctl_solaris.c
+++ b/zebra/ioctl_solaris.c
@@ -31,14 +31,15 @@
#include "zebra/rib.h"
#include "zebra/rt.h"
+#include "zebra/interface.h"
extern struct zebra_privs_t zserv_privs;
/* clear and set interface name string */
void
-lifreq_set_name (struct lifreq *lifreq, struct interface *ifp)
+lifreq_set_name (struct lifreq *lifreq, const char *ifname)
{
- strncpy (lifreq->lifr_name, ifp->name, IFNAMSIZ);
+ strncpy (lifreq->lifr_name, ifname, IFNAMSIZ);
}
/* call ioctl system call */
@@ -129,7 +130,7 @@ if_get_metric (struct interface *ifp)
struct lifreq lifreq;
int ret;
- lifreq_set_name (&lifreq, ifp);
+ lifreq_set_name (&lifreq, ifp->name);
if (ifp->flags & IFF_IPV4)
ret = AF_IOCTL (AF_INET, SIOCGLIFMETRIC, (caddr_t) & lifreq);
@@ -158,7 +159,7 @@ if_get_mtu (struct interface *ifp)
if (ifp->flags & IFF_IPV4)
{
- lifreq_set_name (&lifreq, ifp);
+ lifreq_set_name (&lifreq, ifp->name);
ret = AF_IOCTL (AF_INET, SIOCGLIFMTU, (caddr_t) & lifreq);
if (ret < 0)
{
@@ -177,7 +178,7 @@ if_get_mtu (struct interface *ifp)
return;
memset(&lifreq, 0, sizeof(lifreq));
- lifreq_set_name (&lifreq, ifp);
+ lifreq_set_name (&lifreq, ifp->name);
ret = AF_IOCTL (AF_INET6, SIOCGLIFMTU, (caddr_t) & lifreq);
if (ret < 0)
@@ -274,28 +275,28 @@ if_unset_prefix (struct interface *ifp, struct connected *ifc)
return 0;
}
-/* Solaris IFF_UP flag reflects only the primary interface as the
- * routing socket only sends IFINFO for the primary interface. Hence
- * ~IFF_UP does not per se imply all the logical interfaces are also
- * down - which we only know of as addresses. Instead we must determine
- * whether the interface really is up or not according to how many
- * addresses are still attached. (Solaris always sends RTM_DELADDR if
- * an interface, logical or not, goes ~IFF_UP).
- *
- * Ie, we mangle IFF_UP to reflect whether or not there are addresses
- * left in struct connected, not the actual underlying IFF_UP flag
- * (which corresponds to just one address of all the logical interfaces)
- *
- * Setting IFF_UP within zebra to administratively shutdown the
- * interface will affect only the primary interface/address on Solaris.
+/* Get just the flags for the given name.
+ * Used by the normal 'if_get_flags' function, as well
+ * as the bootup interface-list code, which has to peek at per-address
+ * flags in order to figure out which ones should be ignored..
*/
-static inline void
-if_mangle_up (struct interface *ifp)
+int
+if_get_flags_direct (const char *ifname, uint64_t *flags, unsigned int af)
{
- if (listcount(ifp->connected) > 0)
- SET_FLAG (ifp->flags, IFF_UP);
- else
- UNSET_FLAG (ifp->flags, IFF_UP);
+ 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 */
@@ -303,44 +304,50 @@ void
if_get_flags (struct interface *ifp)
{
int ret4, ret6;
- struct lifreq lifreq;
- unsigned long flags4 = 0, flags6 = 0;
+ uint64_t newflags = 0;
+ uint64_t tmpflags;
if (ifp->flags & IFF_IPV4)
{
- lifreq_set_name (&lifreq, ifp);
-
- ret4 = AF_IOCTL (AF_INET, SIOCGLIFFLAGS, (caddr_t) & lifreq);
+ ret4 = if_get_flags_direct (ifp->name, &tmpflags, AF_INET);
if (!ret4)
- flags4 = (lifreq.lifr_flags & 0xffffffff);
+ 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)
{
- lifreq_set_name (&lifreq, ifp);
-
- ret6 = AF_IOCTL (AF_INET6, SIOCGLIFFLAGS, (caddr_t) & lifreq);
+ ret6 = if_get_flags_direct (ifp->name, &tmpflags, AF_INET6);
if (!ret6)
- flags6 = (lifreq.lifr_flags & 0xffffffff);
+ 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) )
- ifp->flags = (flags4 | flags6);
-
- if_mangle_up (ifp);
+ if_flags_update (ifp, newflags);
}
/* Set interface flags */
int
-if_set_flags (struct interface *ifp, unsigned long flags)
+if_set_flags (struct interface *ifp, uint64_t flags)
{
int ret;
struct lifreq lifreq;
- lifreq_set_name (&lifreq, ifp);
+ lifreq_set_name (&lifreq, ifp->name);
lifreq.lifr_flags = ifp->flags;
lifreq.lifr_flags |= flags;
@@ -363,12 +370,12 @@ if_set_flags (struct interface *ifp, unsigned long flags)
/* Unset interface's flag. */
int
-if_unset_flags (struct interface *ifp, unsigned long flags)
+if_unset_flags (struct interface *ifp, uint64_t flags)
{
int ret;
struct lifreq lifreq;
- lifreq_set_name (&lifreq, ifp);
+ lifreq_set_name (&lifreq, ifp->name);
lifreq.lifr_flags = ifp->flags;
lifreq.lifr_flags &= ~flags;