/* get interface MTU */ void if_get_mtu(struct interface *ifp) { struct ifreq ifreq; ifreq_set_name(&ifreq, ifp); #if defined(SIOCGIFMTU) if (vrf_if_ioctl(SIOCGIFMTU, (caddr_t)&ifreq, ifp->vrf_id) < 0) { zlog_info("Can't lookup mtu by ioctl(SIOCGIFMTU)"); ifp->mtu6 = ifp->mtu = -1; return; } #ifdef SUNOS_5 ifp->mtu6 = ifp->mtu = ifreq.ifr_metric; #else ifp->mtu6 = ifp->mtu = ifreq.ifr_mtu; #endif /* SUNOS_5 */ /* propogate */ zebra_interface_up_update(ifp); #else zlog_info("Can't lookup mtu on this system"); ifp->mtu6 = ifp->mtu = -1; #endif }
/* get interface MTU */ void if_get_mtu (struct interface *ifp) { struct ifreq ifreq; ifreq_set_name (&ifreq, ifp); #if defined(SIOCGIFMTU) if (if_ioctl (SIOCGIFMTU, (caddr_t) & ifreq) < 0) { zlog_info ("Can't lookup mtu by ioctl(SIOCGIFMTU)"); ifp->mtu = -1; return; } #ifdef SUNOS_5 ifp->mtu = ifreq.ifr_metric; #else ifp->mtu = ifreq.ifr_mtu; #endif /* SUNOS_5 */ #else zlog (NULL, LOG_INFO, "Can't lookup mtu on this system"); ifp->mtu = -1; #endif }
/* Set up interface's address, netmask (and broadcas? ). Linux or 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; ifreq_set_name (&ifreq, ifp); 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) return ret; } 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); if (ret < 0) return ret; return 0; }
/* * get interface metric * -- if value is not avaliable set -1 */ void if_get_metric(struct interface *ifp) { #ifdef SIOCGIFMETRIC struct ifreq ifreq; ifreq_set_name(&ifreq, ifp); if (vrf_if_ioctl(SIOCGIFMETRIC, (caddr_t)&ifreq, ifp->vrf_id) < 0) return; ifp->metric = ifreq.ifr_metric; if (ifp->metric == 0) ifp->metric = 1; #else /* SIOCGIFMETRIC */ ifp->metric = -1; #endif /* SIOCGIFMETRIC */ }
/* get interface flags */ void if_get_flags (struct interface *ifp) { int ret = 0; struct ifreq ifreq; ifreq_set_name (&ifreq, ifp); ret = if_ioctl (SIOCGIFFLAGS, (caddr_t) &ifreq); if (ret < 0) { zlog_err("if_ioctl(SIOCGIFFLAGS) failed: %s", safe_strerror(errno)); return; } if_flags_update (ifp, (ifreq.ifr_flags & 0x0000ffff)); }
/* get interface flags */ void if_get_flags(struct interface *ifp) { int ret; struct ifreq ifreq; #ifdef HAVE_BSD_LINK_DETECT struct ifmediareq ifmr; #endif /* HAVE_BSD_LINK_DETECT */ ifreq_set_name(&ifreq, ifp); ret = vrf_if_ioctl(SIOCGIFFLAGS, (caddr_t)&ifreq, ifp->vrf_id); if (ret < 0) { flog_err_sys(EC_LIB_SYSTEM_CALL, "vrf_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)); strlcpy(ifmr.ifm_name, ifp->name, sizeof(ifmr.ifm_name)); /* Seems not all interfaces implement this ioctl */ if (if_ioctl(SIOCGIFMEDIA, (caddr_t)&ifmr) == -1 && errno != EINVAL) flog_err_sys(EC_LIB_SYSTEM_CALL, "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)); }
/* Get interface's index by ioctl. */ int if_get_index (struct interface_FOO *ifp) { #if defined(HAVE_IF_NAMETOINDEX) /* Modern systems should have if_nametoindex(3). */ ifp->ifindex = if_nametoindex(ifp->name); #elif defined(SIOCGIFINDEX) && !defined(HAVE_BROKEN_ALIASES) /* Fall-back for older linuxes. */ int ret; struct ifreq ifreq; static int if_fake_index; ifreq_set_name (&ifreq, ifp); ret = if_ioctl (SIOCGIFINDEX, (caddr_t) &ifreq); if (ret < 0) { /* Linux 2.0.X does not have interface index. */ ifp->ifindex = if_fake_index++; return ifp->ifindex; } /* OK we got interface index. */ #ifdef ifr_ifindex ifp->ifindex = ifreq.ifr_ifindex; #else ifp->ifindex = ifreq.ifr_index; #endif #else /* Linux 2.2.X does not provide individual interface index for aliases and we know it. For others issue a warning. */ #if !defined(HAVE_BROKEN_ALIASES) #ifndef _MSC_VER #warning "Using if_fake_index. You may want to add appropriate" #endif #ifndef _MSC_VER #warning "mapping from ifname to ifindex for your system..." #endif #endif /* This branch probably won't provide usable results, but anyway... */ static int if_fake_index = 1; ifp->ifindex = if_fake_index++; #endif return ifp->ifindex; }
/* * get interface metric * -- if value is not avaliable set -1 */ void if_get_metric (struct interface *ifp) { struct ifreq ifreq; ifreq_set_name (&ifreq, ifp); if (if_ioctl (SIOCGIFMETRIC, (caddr_t) &ifreq) < 0) { return; } ifp->metric = ifreq.ifr_metric; if (ifp->metric == 0) { ifp->metric = 1; } return; }
/* get interface flags */ void if_get_flags (struct interface *ifp) { int ret; struct ifreq ifreq; ifreq_set_name (&ifreq, ifp); ret = if_ioctl (SIOCGIFFLAGS, (caddr_t) &ifreq); if (ret < 0) { perror ("ioctl"); return; } ifp->flags = ifreq.ifr_flags & 0x0000ffff; }
/* get interface MTU */ void if_get_mtu (struct interface *ifp) { struct ifreq ifreq; ifreq_set_name (&ifreq, ifp); if (if_ioctl (SIOCGIFMTU, (caddr_t) & ifreq) < 0) { zlog_info ("Can't lookup mtu by ioctl(SIOCGIFMTU)"); ifp->mtu6 = ifp->mtu = -1; return; } ifp->mtu6 = ifp->mtu = ifreq.ifr_mtu; /* propogate */ zebra_interface_up_update(ifp); }
/* Unset interface's flag. */ int if_unset_flags(struct interface *ifp, uint64_t flags) { int ret; struct ifreq ifreq; memset(&ifreq, 0, sizeof(struct ifreq)); ifreq_set_name(&ifreq, ifp); ifreq.ifr_flags = ifp->flags; ifreq.ifr_flags &= ~flags; ret = vrf_if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq, ifp->vrf_id); if (ret < 0) { zlog_info("can't unset interface flags"); return ret; } return 0; }
/* Unset interface's flag. */ int if_unset_flags (struct interface *ifp, unsigned long flags) { int ret; struct ifreq ifreq; ifreq_set_name (&ifreq, ifp); ifreq.ifr_flags = ifp->flags; ifreq.ifr_flags &= ~flags; ret = if_ioctl (SIOCSIFFLAGS, (caddr_t) &ifreq); if (ret < 0) { zlog_info ("can't unset interface flags"); return ret; } return 0; }
/* Set up interface's address, netmask (and broadcas? ). Linux or 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; ifreq_set_name (&ifreq, ifp); 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's index by ioctl. */ int if_get_index (struct interface *ifp) { static int if_fake_index = 1; #ifdef HAVE_BROKEN_ALIASES /* Linux 2.2.X does not provide individual interface index for aliases. */ ifp->ifindex = if_fake_index++; return ifp->ifindex; #else #ifdef SIOCGIFINDEX int ret; struct ifreq ifreq; ifreq_set_name (&ifreq, ifp); ret = if_ioctl (SIOCGIFINDEX, (caddr_t) &ifreq); if (ret < 0) { /* Linux 2.0.X does not have interface index. */ ifp->ifindex = if_fake_index++; return ifp->ifindex; } /* OK we got interface index. */ #ifdef ifr_ifindex ifp->ifindex = ifreq.ifr_ifindex; #else ifp->ifindex = ifreq.ifr_index; #endif return ifp->ifindex; #else ifp->ifindex = if_fake_index++; return ifp->ifindex; #endif /* SIOCGIFINDEX */ #endif /* HAVE_BROKEN_ALIASES */ }