/* * 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->name); 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); #endif /* SOLARIS_IPV6 */ else ret = -1; if (ret < 0) return; ifp->metric = lifreq.lifr_metric; if (ifp->metric == 0) ifp->metric = 1; }
/* Set interface 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; }
/* Get interface's index by ioctl. */ static int if_get_index (struct interface *ifp) { int ret; struct lifreq lifreq; lifreq_set_name (&lifreq, ifp->name); 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 (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; }
/* Unset interface's flag. */ int if_unset_flags (struct interface_FOO *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; }
/* get interface MTU */ 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; } } #ifdef HAVE_IPV6 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; } } #endif /* HAVE_IPV6 */ if (changed) zebra_interface_up_update(ifp); }
/* 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.. */ 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; }
/* Retrieve address information for the given ifp */ static int if_get_addr (struct interface *ifp, struct sockaddr *addr, const char *label) { int ret; struct lifreq lifreq; struct sockaddr_storage mask, dest; char *dest_pnt = NULL; u_char prefixlen = 0; afi_t af; int flags = 0; /* Interface's name and address family. * We need to use the logical interface name / label, if we've been * given one, in order to get the right address */ strncpy (lifreq.lifr_name, (label ? label : 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 (AF_IOCTL (af, SIOCGLIFDSTADDR, (caddr_t) & lifreq) >= 0) { 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); flags = ZEBRA_IFA_PEER; } 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, safe_strerror (errno)); return ret; } return 0; } memcpy (&mask, &lifreq.lifr_addr, ADDRLEN (addr)); prefixlen = ip_masklen (SIN (&mask)->sin_addr); if (!dest_pnt && (if_ioctl (SIOCGLIFBRDADDR, (caddr_t) & lifreq) >= 0)) { memcpy (&dest, &lifreq.lifr_broadaddr, sizeof (struct sockaddr_in)); dest_pnt = (char *) &SIN (&dest)->sin_addr; } } #ifdef HAVE_IPV6 else if (af == AF_INET6) { if (if_ioctl_ipv6 (SIOCGLIFSUBNET, (caddr_t) & lifreq) < 0) { if (ifp->flags & IFF_POINTOPOINT) prefixlen = IPV6_MAX_BITLEN; else zlog_warn ("SIOCGLIFSUBNET (%s) fail: %s", ifp->name, safe_strerror (errno)); } else { prefixlen = lifreq.lifr_addrlen; } } #endif /* HAVE_IPV6 */ /* Set address to the interface. */ if (af == AF_INET) connected_add_ipv4 (ifp, flags, &SIN (addr)->sin_addr, prefixlen, (struct in_addr *) dest_pnt, label); #ifdef HAVE_IPV6 else if (af == AF_INET6) connected_add_ipv6 (ifp, flags, &SIN6 (addr)->sin6_addr, prefixlen, (struct in6_addr *) dest_pnt, label); #endif /* HAVE_IPV6 */ return 0; }