#include "log.h"
#include "privs.h"
+#include "vty.h"
#include "zebra/rib.h"
#include "zebra/rt.h"
#include "zebra/interface.h"
+#ifdef HAVE_BSD_LINK_DETECT
+#include <net/if_media.h>
+#endif /* HAVE_BSD_LINK_DETECT*/
+
extern struct zebra_privs_t zserv_privs;
/* clear and set interface name string */
{
int sock;
int ret;
- int err;
+ int err = 0;
if (zserv_privs.change(ZPRIVS_RAISE))
- zlog (NULL, LOG_ERR, "Can't raise privileges");
+ 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 (NULL, LOG_ERR, "Can't lower privileges");
+ 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 (NULL, LOG_ERR, "Can't lower privileges");
+ zlog_err("Can't lower privileges");
close (sock);
if (ret < 0)
return 0;
}
-#ifdef HAVE_IPV6
static int
if_ioctl_ipv6 (u_long request, caddr_t buffer)
{
int sock;
int ret;
- int err;
+ int err = 0;
if (zserv_privs.change(ZPRIVS_RAISE))
- zlog (NULL, LOG_ERR, "Can't raise privileges");
+ 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 (NULL, LOG_ERR, "Can't lower privileges");
+ 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 (NULL, LOG_ERR, "Can't lower privileges");
+ zlog_err("Can't lower privileges");
close (sock);
if (ret < 0)
}
return 0;
}
-#endif /* HAVE_IPV6 */
/*
* get interface metric
ifp->mtu6 = ifp->mtu = ifreq.ifr_mtu;
#endif /* SUNOS_5 */
+ /* propogate */
+ zebra_interface_up_update(ifp);
+
#else
- zlog (NULL, LOG_INFO, "Can't lookup mtu on this system");
+ zlog_info("Can't lookup mtu on this system");
ifp->mtu6 = ifp->mtu = -1;
#endif
}
return kernel_address_delete_ipv4 (ifp, ifc);
}
#else /* ! HAVE_NETLINK */
-#ifdef HAVE_IFALIASREQ
+#ifdef HAVE_STRUCT_IFALIASREQ
/* Set up interface's IP address, netmask (and broadcas? ). *BSD may
has ifaliasreq structure. */
int
struct prefix_ipv4 *p;
p = (struct prefix_ipv4 *) ifc->address;
+ rib_lookup_and_pushup (p, ifp->vrf_id);
memset (&addreq, 0, sizeof addreq);
strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name);
memset (&addr, 0, sizeof (struct sockaddr_in));
addr.sin_addr = p->prefix;
addr.sin_family = p->family;
-#ifdef HAVE_SIN_LEN
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
addr.sin_len = sizeof (struct sockaddr_in);
#endif
memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in));
memset (&mask, 0, sizeof (struct sockaddr_in));
masklen2ip (p->prefixlen, &mask.sin_addr);
mask.sin_family = p->family;
-#ifdef HAVE_SIN_LEN
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
mask.sin_len = sizeof (struct sockaddr_in);
#endif
memcpy (&addreq.ifra_mask, &mask, sizeof (struct sockaddr_in));
memset (&addr, 0, sizeof (struct sockaddr_in));
addr.sin_addr = p->prefix;
addr.sin_family = p->family;
-#ifdef HAVE_SIN_LEN
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
addr.sin_len = sizeof (struct sockaddr_in);
#endif
memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in));
memset (&mask, 0, sizeof (struct sockaddr_in));
masklen2ip (p->prefixlen, &mask.sin_addr);
mask.sin_family = p->family;
-#ifdef HAVE_SIN_LEN
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
mask.sin_len = sizeof (struct sockaddr_in);
#endif
memcpy (&addreq.ifra_mask, &mask, sizeof (struct sockaddr_in));
return 0;
}
-#endif /* HAVE_IFALIASREQ */
+#endif /* HAVE_STRUCT_IFALIASREQ */
#endif /* HAVE_NETLINK */
/* get interface flags */
{
int ret;
struct ifreq ifreq;
+#ifdef HAVE_BSD_LINK_DETECT
+ struct ifmediareq ifmr;
+#endif /* HAVE_BSD_LINK_DETECT */
ifreq_set_name (&ifreq, ifp);
zlog_err("if_ioctl(SIOCGIFFLAGS) failed: %s", safe_strerror(errno));
return;
}
+#ifdef HAVE_BSD_LINK_DETECT /* Detect BSD link-state at start-up */
+
+ /* Per-default, IFF_RUNNING is held high, unless link-detect says
+ * otherwise - we abuse IFF_RUNNING inside zebra as a link-state flag,
+ * following practice on Linux and Solaris kernels
+ */
+ SET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
+
+ if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
+ {
+ (void) memset(&ifmr, 0, sizeof(ifmr));
+ strncpy (ifmr.ifm_name, ifp->name, IFNAMSIZ);
+
+ /* Seems not all interfaces implement this ioctl */
+ if (if_ioctl(SIOCGIFMEDIA, (caddr_t) &ifmr) < 0)
+ zlog_err("if_ioctl(SIOCGIFMEDIA) failed: %s", safe_strerror(errno));
+ else if (ifmr.ifm_status & IFM_AVALID) /* Link state is valid */
+ {
+ if (ifmr.ifm_status & IFM_ACTIVE)
+ SET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
+ else
+ UNSET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
+ }
+ }
+#endif /* HAVE_BSD_LINK_DETECT */
if_flags_update (ifp, (ifreq.ifr_flags & 0x0000ffff));
}
return 0;
}
-#ifdef HAVE_IPV6
-
#ifdef LINUX_IPV6
#ifndef _LINUX_IN6_H
/* linux/include/net/ipv6.h */
return ret;
}
#else /* LINUX_IPV6 */
-#ifdef HAVE_IN6_ALIASREQ
+#ifdef HAVE_STRUCT_IN6_ALIASREQ
#ifndef ND6_INFINITE_LIFETIME
#define ND6_INFINITE_LIFETIME 0xffffffffL
#endif /* ND6_INFINITE_LIFETIME */
memset (&addr, 0, sizeof (struct sockaddr_in6));
addr.sin6_addr = p->prefix;
addr.sin6_family = p->family;
-#ifdef HAVE_SIN_LEN
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
addr.sin6_len = sizeof (struct sockaddr_in6);
#endif
memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in6));
memset (&mask, 0, sizeof (struct sockaddr_in6));
masklen2ip6 (p->prefixlen, &mask.sin6_addr);
mask.sin6_family = p->family;
-#ifdef HAVE_SIN_LEN
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
mask.sin6_len = sizeof (struct sockaddr_in6);
#endif
memcpy (&addreq.ifra_prefixmask, &mask, sizeof (struct sockaddr_in6));
addreq.ifra_lifetime.ia6t_vltime = 0xffffffff;
addreq.ifra_lifetime.ia6t_pltime = 0xffffffff;
-#ifdef HAVE_IFRA_LIFETIME
+#ifdef HAVE_STRUCT_IF6_ALIASREQ_IFRA_LIFETIME
addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
#endif
memset (&addr, 0, sizeof (struct sockaddr_in6));
addr.sin6_addr = p->prefix;
addr.sin6_family = p->family;
-#ifdef HAVE_SIN_LEN
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
addr.sin6_len = sizeof (struct sockaddr_in6);
#endif
memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in6));
memset (&mask, 0, sizeof (struct sockaddr_in6));
masklen2ip6 (p->prefixlen, &mask.sin6_addr);
mask.sin6_family = p->family;
-#ifdef HAVE_SIN_LEN
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
mask.sin6_len = sizeof (struct sockaddr_in6);
#endif
memcpy (&addreq.ifra_prefixmask, &mask, sizeof (struct sockaddr_in6));
-#ifdef HAVE_IFRA_LIFETIME
+#ifdef HAVE_STRUCT_IF6_ALIASREQ_IFRA_LIFETIME
addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
#endif
{
return 0;
}
-#endif /* HAVE_IN6_ALIASREQ */
+#endif /* HAVE_STRUCT_IN6_ALIASREQ */
#endif /* LINUX_IPV6 */
-
-#endif /* HAVE_IPV6 */