Beispiel #1
0
int
_intf_get_noalias(intf_t *intf, struct intf_entry *entry)
{
	struct lifreq lifr;

	/* Get interface index. */
	entry->intf_index = if_nametoindex(entry->intf_name);
	if (entry->intf_index == 0)
		return (-1);

	strlcpy(lifr.lifr_name, entry->intf_name, sizeof(lifr.lifr_name));

	/* Get interface flags. */
	if (ioctl(intf->fd, SIOCGLIFFLAGS, &lifr) < 0)
		return (-1);
	
	entry->intf_flags = intf_iff_to_flags(lifr.lifr_flags);
	_intf_set_type(entry);
	
	/* Get interface MTU. */
#ifdef SIOCSIFMTU
	if (ioctl(intf->fd, SIOCGLIFMTU, &lifr) < 0)
#endif
		return (-1);
	entry->intf_mtu = lifr.lifr_mtu;

	entry->intf_addr.addr_type = entry->intf_dst_addr.addr_type =
	    entry->intf_link_addr.addr_type = ADDR_TYPE_NONE;
	
	/* Get primary interface address. */
	if (ioctl(intf->fd, SIOCGLIFADDR, &lifr) == 0) {
		addr_ston((struct sockaddr *)&lifr.lifr_addr, &entry->intf_addr);
		if (ioctl(intf->fd, SIOCGLIFNETMASK, &lifr) < 0)
			return (-1);
		addr_stob((struct sockaddr *)&lifr.lifr_addr, &entry->intf_addr.addr_bits);
	}
	/* Get other addresses. */
	if (entry->intf_type == INTF_TYPE_TUN) {
		if (ioctl(intf->fd, SIOCGLIFDSTADDR, &lifr) == 0) {
			if (addr_ston((struct sockaddr *)&lifr.lifr_addr,
			    &entry->intf_dst_addr) < 0)
				return (-1);
		}
	} else if (entry->intf_type == INTF_TYPE_ETH) {
		eth_t *eth;
		
		if ((eth = eth_open(entry->intf_name)) != NULL) {
			if (!eth_get(eth, &entry->intf_link_addr.addr_eth)) {
				entry->intf_link_addr.addr_type =
				    ADDR_TYPE_ETH;
				entry->intf_link_addr.addr_bits =
				    ETH_ADDR_BITS;
			}
			eth_close(eth);
		}
	}
	return (0);
}
Beispiel #2
0
static int
_radix_walk(int fd, struct radix_node *rn, route_handler callback, void *arg)
{
	struct radix_node rnode;
	struct rtentry rt;
	struct sockaddr_in sin;
	struct route_entry entry;
	int ret = 0;
 again:
	_kread(fd, rn, &rnode, sizeof(rnode));
	if (rnode.rn_b < 0) {
		if (!(rnode.rn_flags & RNF_ROOT)) {
			entry.intf_name[0] = '\0';
			_kread(fd, rn, &rt, sizeof(rt));
			_kread(fd, rt_key(&rt), &sin, sizeof(sin));
			addr_ston((struct sockaddr *)&sin, &entry.route_dst);
			if (!(rt.rt_flags & RTF_HOST)) {
				_kread(fd, rt_mask(&rt), &sin, sizeof(sin));
				addr_stob((struct sockaddr *)&sin,
				    &entry.route_dst.addr_bits);
			}
			_kread(fd, rt.rt_gateway, &sin, sizeof(sin));
			addr_ston((struct sockaddr *)&sin, &entry.route_gw);
			entry.metric = 0;
			if ((ret = callback(&entry, arg)) != 0)
				return (ret);
		}
		if ((rn = rnode.rn_dupedkey))
			goto again;
	} else {
		rn = rnode.rn_r;
		if ((ret = _radix_walk(fd, rnode.rn_l, callback, arg)) != 0)
			return (ret);
		if ((ret = _radix_walk(fd, rn, callback, arg)) != 0)
			return (ret);
	}
	return (ret);
}
Beispiel #3
0
static int
_intf_get_aliases(intf_t *intf, struct intf_entry *entry)
{
    struct ifreq *ifr, *lifr;
    struct ifreq tmpifr;
    struct addr *ap, *lap;
    char *p;

    if (intf->ifc.ifc_len < (int)sizeof(*ifr)) {
        errno = EINVAL;
        return (-1);
    }
    entry->intf_alias_num = 0;
    ap = entry->intf_alias_addrs;
    lifr = (struct ifreq *)intf->ifc.ifc_buf +
           (intf->ifc.ifc_len / sizeof(*lifr));
    lap = (struct addr *)((u_char *)entry + entry->intf_len);

    /* Get addresses for this interface. */
    for (ifr = intf->ifc.ifc_req; ifr < lifr && (ap + 1) < lap;
            ifr = NEXTIFR(ifr)) {
        /* XXX - Linux, Solaris ifaliases */
        if ((p = strchr(ifr->ifr_name, ':')) != NULL)
            *p = '\0';

        if (strcmp(ifr->ifr_name, entry->intf_name) != 0) {
            if (p) *p = ':';
            continue;
        }

        if (p) *p = ':'; /* Fix the name back up */
        if (addr_ston(&ifr->ifr_addr, ap) < 0)
            continue;

        /* XXX */
        if (ap->addr_type == ADDR_TYPE_ETH) {
            memcpy(&entry->intf_link_addr, ap, sizeof(*ap));
            continue;
        } else if (ap->addr_type == ADDR_TYPE_IP) {
            if (ap->addr_ip == entry->intf_addr.addr_ip ||
                    ap->addr_ip == entry->intf_dst_addr.addr_ip)
                continue;
            strlcpy(tmpifr.ifr_name, ifr->ifr_name,
                    sizeof(tmpifr.ifr_name));
            if (ioctl(intf->fd, SIOCGIFNETMASK, &tmpifr) == 0)
                addr_stob(&tmpifr.ifr_addr, &ap->addr_bits);

        }
#ifdef SIOCGIFNETMASK_IN6
        else if (ap->addr_type == ADDR_TYPE_IP6 && intf->fd6 != -1) {
            struct in6_ifreq ifr6;

            /* XXX - sizeof(ifr) < sizeof(ifr6) */
            memcpy(&ifr6, ifr, sizeof(ifr6));

            if (ioctl(intf->fd6, SIOCGIFNETMASK_IN6, &ifr6) == 0) {
                addr_stob((struct sockaddr *)&ifr6.ifr_addr,
                          &ap->addr_bits);
            }
            else perror("SIOCGIFNETMASK_IN6");
        }
#endif
        ap++, entry->intf_alias_num++;
    }
    entry->intf_len = (u_char *)ap - (u_char *)entry;

    return (0);
}
Beispiel #4
0
static int
_intf_get_noalias(intf_t *intf, struct intf_entry *entry)
{
    struct ifreq ifr;

    strlcpy(ifr.ifr_name, entry->intf_name, sizeof(ifr.ifr_name));

    /* Get interface flags. */
    if (ioctl(intf->fd, SIOCGIFFLAGS, &ifr) < 0)
        return (-1);

    entry->intf_flags = intf_iff_to_flags(ifr.ifr_flags);
    _intf_set_type(entry);

    /* Get interface MTU. */
#ifdef SIOCGIFMTU
    if (ioctl(intf->fd, SIOCGIFMTU, &ifr) < 0)
#endif
        return (-1);
    entry->intf_mtu = ifr.ifr_mtu;

    entry->intf_addr.addr_type = entry->intf_dst_addr.addr_type =
                                     entry->intf_link_addr.addr_type = ADDR_TYPE_NONE;

    /* Get primary interface address. */
    if (ioctl(intf->fd, SIOCGIFADDR, &ifr) == 0) {
        addr_ston(&ifr.ifr_addr, &entry->intf_addr);
        if (ioctl(intf->fd, SIOCGIFNETMASK, &ifr) < 0)
            return (-1);
        addr_stob(&ifr.ifr_addr, &entry->intf_addr.addr_bits);
    }
    /* Get other addresses. */
    if (entry->intf_type == INTF_TYPE_TUN) {
        if (ioctl(intf->fd, SIOCGIFDSTADDR, &ifr) == 0) {
            if (addr_ston(&ifr.ifr_addr,
                          &entry->intf_dst_addr) < 0)
                return (-1);
        }
    } else if (entry->intf_type == INTF_TYPE_ETH) {
#if defined(SIOCGIFHWADDR)
        if (ioctl(intf->fd, SIOCGIFHWADDR, &ifr) < 0)
            return (-1);
        if (addr_ston(&ifr.ifr_addr, &entry->intf_link_addr) < 0)
            return (-1);
#elif defined(SIOCRPHYSADDR)
        /* Tru64 */
        struct ifdevea *ifd = (struct ifdevea *)&ifr; /* XXX */

        if (ioctl(intf->fd, SIOCRPHYSADDR, ifd) < 0)
            return (-1);
        addr_pack(&entry->intf_link_addr, ADDR_TYPE_ETH, ETH_ADDR_BITS,
                  ifd->current_pa, ETH_ADDR_LEN);
#else
        eth_t *eth;

        if ((eth = eth_open(entry->intf_name)) != NULL) {
            if (!eth_get(eth, &entry->intf_link_addr.addr_eth)) {
                entry->intf_link_addr.addr_type =
                    ADDR_TYPE_ETH;
                entry->intf_link_addr.addr_bits =
                    ETH_ADDR_BITS;
            }
            eth_close(eth);
        }
#endif
    }
    return (0);
}
Beispiel #5
0
int
route_loop(route_t *r, route_handler callback, void *arg)
{
	struct route_entry entry;
	struct strbuf msg;
	struct T_optmgmt_req *tor;
	struct T_optmgmt_ack *toa;
	struct T_error_ack *tea;
	struct opthdr *opt;
	u_char buf[8192];
	int flags, rc, rtable, ret;

	tor = (struct T_optmgmt_req *)buf;
	toa = (struct T_optmgmt_ack *)buf;
	tea = (struct T_error_ack *)buf;

	tor->PRIM_type = T_OPTMGMT_REQ;
	tor->OPT_offset = sizeof(*tor);
	tor->OPT_length = sizeof(*opt);
	tor->MGMT_flags = T_CURRENT;
	
	opt = (struct opthdr *)(tor + 1);
	opt->level = MIB2_IP;
	opt->name = opt->len = 0;
	
	msg.maxlen = sizeof(buf);
	msg.len = sizeof(*tor) + sizeof(*opt);
	msg.buf = buf;
	
	if (putmsg(r->ip_fd, &msg, NULL, 0) < 0)
		return (-1);
	
	opt = (struct opthdr *)(toa + 1);
	msg.maxlen = sizeof(buf);
	
	for (;;) {
		mib2_ipRouteEntry_t *rt, *rtend;

		flags = 0;
		if ((rc = getmsg(r->ip_fd, &msg, NULL, &flags)) < 0)
			return (-1);

		/* See if we're finished. */
		if (rc == 0 &&
		    msg.len >= sizeof(*toa) &&
		    toa->PRIM_type == T_OPTMGMT_ACK &&
		    toa->MGMT_flags == T_SUCCESS && opt->len == 0)
			break;

		if (msg.len >= sizeof(*tea) && tea->PRIM_type == T_ERROR_ACK)
			return (-1);
		
		if (rc != MOREDATA || msg.len < (int)sizeof(*toa) ||
		    toa->PRIM_type != T_OPTMGMT_ACK ||
		    toa->MGMT_flags != T_SUCCESS)
			return (-1);
		
		rtable = (opt->level == MIB2_IP && opt->name == MIB2_IP_21);
		
		msg.maxlen = sizeof(buf) - (sizeof(buf) % sizeof(*rt));
		msg.len = 0;
		flags = 0;
		
		do {
			struct sockaddr_in sin;

			rc = getmsg(r->ip_fd, NULL, &msg, &flags);
			
			if (rc != 0 && rc != MOREDATA)
				return (-1);
			
			if (!rtable)
				continue;
			
			rt = (mib2_ipRouteEntry_t *)msg.buf;
			rtend = (mib2_ipRouteEntry_t *)(msg.buf + msg.len);

			sin.sin_family = AF_INET;

			for ( ; rt < rtend; rt++) {
				if ((rt->ipRouteInfo.re_ire_type &
				    (IRE_BROADCAST|IRE_ROUTE_REDIRECT|
					IRE_LOCAL|IRE_ROUTE)) != 0 ||
				    rt->ipRouteNextHop == IP_ADDR_ANY)
					continue;
				
				sin.sin_addr.s_addr = rt->ipRouteNextHop;
				addr_ston((struct sockaddr *)&sin,
				    &entry.route_gw);
				
				sin.sin_addr.s_addr = rt->ipRouteDest;
				addr_ston((struct sockaddr *)&sin,
				    &entry.route_dst);
				
				sin.sin_addr.s_addr = rt->ipRouteMask;
				addr_stob((struct sockaddr *)&sin,
				    &entry.route_dst.addr_bits);
				
				if ((ret = callback(&entry, arg)) != 0)
					return (ret);
			}
		} while (rc == MOREDATA);
	}

	tor = (struct T_optmgmt_req *)buf;
	toa = (struct T_optmgmt_ack *)buf;
	tea = (struct T_error_ack *)buf;

	tor->PRIM_type = T_OPTMGMT_REQ;
	tor->OPT_offset = sizeof(*tor);
	tor->OPT_length = sizeof(*opt);
	tor->MGMT_flags = T_CURRENT;
	
	opt = (struct opthdr *)(tor + 1);
	opt->level = MIB2_IP6;
	opt->name = opt->len = 0;
	
	msg.maxlen = sizeof(buf);
	msg.len = sizeof(*tor) + sizeof(*opt);
	msg.buf = buf;
	
	if (putmsg(r->ip_fd, &msg, NULL, 0) < 0)
		return (-1);
	
	opt = (struct opthdr *)(toa + 1);
	msg.maxlen = sizeof(buf);
	
	for (;;) {
		mib2_ipv6RouteEntry_t *rt, *rtend;

		flags = 0;
		if ((rc = getmsg(r->ip_fd, &msg, NULL, &flags)) < 0)
			return (-1);

		/* See if we're finished. */
		if (rc == 0 &&
		    msg.len >= sizeof(*toa) &&
		    toa->PRIM_type == T_OPTMGMT_ACK &&
		    toa->MGMT_flags == T_SUCCESS && opt->len == 0)
			break;

		if (msg.len >= sizeof(*tea) && tea->PRIM_type == T_ERROR_ACK)
			return (-1);
		
		if (rc != MOREDATA || msg.len < (int)sizeof(*toa) ||
		    toa->PRIM_type != T_OPTMGMT_ACK ||
		    toa->MGMT_flags != T_SUCCESS)
			return (-1);
		
		rtable = (opt->level == MIB2_IP6 && opt->name == MIB2_IP6_ROUTE);
		
		msg.maxlen = sizeof(buf) - (sizeof(buf) % sizeof(*rt));
		msg.len = 0;
		flags = 0;
		
		do {
			struct sockaddr_in6 sin6;

			rc = getmsg(r->ip_fd, NULL, &msg, &flags);
			
			if (rc != 0 && rc != MOREDATA)
				return (-1);
			
			if (!rtable)
				continue;
			
			rt = (mib2_ipv6RouteEntry_t *)msg.buf;
			rtend = (mib2_ipv6RouteEntry_t *)(msg.buf + msg.len);

			sin6.sin6_family = AF_INET6;

			for ( ; rt < rtend; rt++) {
				if ((rt->ipv6RouteInfo.re_ire_type &
				    (IRE_BROADCAST|IRE_ROUTE_REDIRECT|
					IRE_LOCAL|IRE_ROUTE)) != 0 ||
				    memcmp(&rt->ipv6RouteNextHop, IP6_ADDR_UNSPEC, IP6_ADDR_LEN) == 0)
					continue;
				
				sin6.sin6_addr = rt->ipv6RouteNextHop;
				addr_ston((struct sockaddr *)&sin6,
				    &entry.route_gw);
				
				sin6.sin6_addr = rt->ipv6RouteDest;
				addr_ston((struct sockaddr *)&sin6,
				    &entry.route_dst);
				
				entry.route_dst.addr_bits = rt->ipv6RoutePfxLength;
				
				if ((ret = callback(&entry, arg)) != 0)
					return (ret);
			}
		} while (rc == MOREDATA);
	}
	return (0);
}
Beispiel #6
0
int
route_loop(route_t *r, route_handler callback, void *arg)
{
	struct rt_msghdr *rtm;
	struct route_entry entry;
	struct sockaddr *sa;
	char *buf, *lim, *next;
	int ret;
#ifdef HAVE_SYS_SYSCTL_H
	int mib[6] = { CTL_NET, PF_ROUTE, 0, 0 /* XXX */, NET_RT_DUMP, 0 };
	size_t len;
	
	if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
		return (-1);

	if (len == 0)
		return (0);
	
	if ((buf = malloc(len)) == NULL)
		return (-1);
	
	if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
		free(buf);
		return (-1);
	}
	lim = buf + len;
	next = buf;
#elif defined(HAVE_GETKERNINFO)
	int len = getkerninfo(KINFO_RT_DUMP,0,0,0);

	if (len == 0)
		return (0);

	if ((buf = malloc(len)) == NULL)
		return (-1);

	if (getkerninfo(KINFO_RT_DUMP,buf,&len,0) < 0) {
		free(buf);
		return (-1);
	}
	lim = buf + len;
	next = buf;
#else /* HAVE_STREAMS_ROUTE */
	struct rt_giarg giarg, *gp;

	memset(&giarg, 0, sizeof(giarg));
	giarg.gi_op = KINFO_RT_DUMP;

	if (ioctl(r->fd, RTSTR_GETROUTE, &giarg) < 0)
		return (-1);

	if ((buf = malloc(giarg.gi_size)) == NULL)
		return (-1);

	gp = (struct rt_giarg *)buf;
	gp->gi_size = giarg.gi_size;
	gp->gi_op = KINFO_RT_DUMP;
	gp->gi_where = buf;
	gp->gi_arg = RTF_UP | RTF_GATEWAY;

	if (ioctl(r->fd, RTSTR_GETROUTE, buf) < 0) {
		free(buf);
		return (-1);
	}
	lim = buf + gp->gi_size;
	next = buf + sizeof(giarg);
#endif
	/* This loop assumes that RTA_DST, RTA_GATEWAY, and RTA_NETMASK have the
	 * values, 1, 2, and 4 respectively. Cf. Unix Network Programming,
	 * p. 494, function get_rtaddrs. */
	for (ret = 0; next < lim; next += rtm->rtm_msglen) {
		rtm = (struct rt_msghdr *)next;
		sa = (struct sockaddr *)(rtm + 1);

		if ((rtm->rtm_addrs & RTA_DST) == 0)
			/* Need a destination. */
			continue;
		if (addr_ston(sa, &entry.route_dst) < 0)
			continue;

		if ((rtm->rtm_addrs & RTA_GATEWAY) == 0)
			/* Need a gateway. */
			continue;
		sa = NEXTSA(sa);
		if (addr_ston_gateway(&entry.route_dst, sa, &entry.route_gw) < 0)
			continue;
		
		if (entry.route_dst.addr_type != entry.route_gw.addr_type ||
		    (entry.route_dst.addr_type != ADDR_TYPE_IP &&
			entry.route_dst.addr_type != ADDR_TYPE_IP6))
			continue;

		if (rtm->rtm_addrs & RTA_NETMASK) {
			sa = NEXTSA(sa);
			if (addr_stob(sa, &entry.route_dst.addr_bits) < 0)
				continue;
		}

		if ((ret = callback(&entry, arg)) != 0)
			break;
	}
	free(buf);
	
	return (ret);
}
static Bool
RecordRoutingInfoIPv4(NicInfoV3 *nicInfo)
{
   GPtrArray *routes = NULL;
   guint i;
   Bool ret = FALSE;

   if ((routes = SlashProcNet_GetRoute()) == NULL) {
      return FALSE;
   }

   for (i = 0; i < routes->len; i++) {
      struct rtentry *rtentry;
      struct sockaddr_in *sin_dst;
      struct sockaddr_in *sin_gateway;
      struct sockaddr_in *sin_genmask;
      InetCidrRouteEntry *icre;
      uint32_t ifIndex;

      /* Check to see if we're going above our limit. See bug 605821. */
      if (nicInfo->routes.routes_len == NICINFO_MAX_ROUTES) {
         g_message("%s: route limit (%d) reached, skipping overflow.",
                   __FUNCTION__, NICINFO_MAX_ROUTES);
         break;
      }

      rtentry = g_ptr_array_index(routes, i);

      if ((rtentry->rt_flags & RTF_UP) == 0 ||
          !GuestInfoGetNicInfoIfIndex(nicInfo,
                                      if_nametoindex(rtentry->rt_dev),
                                      &ifIndex)) {
         continue;
      }

      icre = XDRUTIL_ARRAYAPPEND(nicInfo, routes, 1);
      ASSERT_MEM_ALLOC(icre);

      sin_dst = (struct sockaddr_in *)&rtentry->rt_dst;
      sin_gateway = (struct sockaddr_in *)&rtentry->rt_gateway;
      sin_genmask = (struct sockaddr_in *)&rtentry->rt_genmask;

      GuestInfoSockaddrToTypedIpAddress((struct sockaddr *)sin_dst,
                                        &icre->inetCidrRouteDest);

      addr_stob((struct sockaddr *)sin_genmask,
                (uint16_t *)&icre->inetCidrRoutePfxLen);

      /*
       * Gateways are optional (ex: one can bind a route to an interface w/o
       * specifying a next hop address).
       */
      if (rtentry->rt_flags & RTF_GATEWAY) {
         TypedIpAddress *ip = Util_SafeCalloc(1, sizeof *ip);
         GuestInfoSockaddrToTypedIpAddress((struct sockaddr *)sin_gateway, ip);
         icre->inetCidrRouteNextHop = ip;
      }

      /*
       * Interface, metric.
       */
      icre->inetCidrRouteIfIndex = ifIndex;
      icre->inetCidrRouteMetric = rtentry->rt_metric;
   }

   ret = TRUE;

   SlashProcNet_FreeRoute(routes);
   return ret;
}
Beispiel #8
0
static int
_intf_get_aliases(intf_t *intf, struct intf_entry *entry)
{
	struct ifreq *ifr, *lifr;
	struct ifreq tmpifr;
	struct addr *ap, *lap;
	char *p;
	
	if (intf->ifc.ifc_len < (int)sizeof(*ifr)) {
		errno = EINVAL;
		return (-1);
	}
	entry->intf_alias_num = 0;
	ap = entry->intf_alias_addrs;
	lifr = (struct ifreq *)intf->ifc.ifc_buf + 
	    (intf->ifc.ifc_len / sizeof(*lifr));
	lap = (struct addr *)((u_char *)entry + entry->intf_len);
	
	/* Get addresses for this interface. */
	for (ifr = intf->ifc.ifc_req; ifr < lifr && (ap + 1) < lap;
	    ifr = NEXTIFR(ifr)) {
		/* XXX - Linux, Solaris ifaliases */
		if ((p = strchr(ifr->ifr_name, ':')) != NULL)
			*p = '\0';
		
		if (strcmp(ifr->ifr_name, entry->intf_name) != 0) {
			if (p) *p = ':';
			continue;
		}
		
		/* Fix the name back up */
		if (p) *p = ':';

		if (addr_ston(&ifr->ifr_addr, ap) < 0)
			continue;
		
		/* XXX */
		if (ap->addr_type == ADDR_TYPE_ETH) {
			memcpy(&entry->intf_link_addr, ap, sizeof(*ap));
			continue;
		} else if (ap->addr_type == ADDR_TYPE_IP) {
			if (ap->addr_ip == entry->intf_addr.addr_ip ||
			    ap->addr_ip == entry->intf_dst_addr.addr_ip)
				continue;
			strlcpy(tmpifr.ifr_name, ifr->ifr_name, sizeof(tmpifr.ifr_name));
			if (ioctl(intf->fd, SIOCGIFNETMASK, &tmpifr) == 0)
				addr_stob(&tmpifr.ifr_addr, &ap->addr_bits);
		}
#ifdef SIOCGIFNETMASK_IN6
		else if (ap->addr_type == ADDR_TYPE_IP6 && intf->fd6 != -1) {
			struct in6_ifreq ifr6;

			/* XXX - sizeof(ifr) < sizeof(ifr6) */
			memcpy(&ifr6, ifr, sizeof(ifr6));
			
			if (ioctl(intf->fd6, SIOCGIFNETMASK_IN6, &ifr6) == 0) {
				addr_stob((struct sockaddr *)&ifr6.ifr_addr,
				    &ap->addr_bits);
			}
			else perror("SIOCGIFNETMASK_IN6");
		}
#else
#ifdef SIOCGIFNETMASK6
		else if (ap->addr_type == ADDR_TYPE_IP6 && intf->fd6 != -1) {
			struct in6_ifreq ifr6;

			/* XXX - sizeof(ifr) < sizeof(ifr6) */
			memcpy(&ifr6, ifr, sizeof(ifr6));
			
			if (ioctl(intf->fd6, SIOCGIFNETMASK6, &ifr6) == 0) {
				/* For some reason this is 0 after the ioctl. */
				ifr6.ifr_Addr.sin6_family = AF_INET6;
				addr_stob((struct sockaddr *)&ifr6.ifr_Addr,
				    &ap->addr_bits);
			}
			else perror("SIOCGIFNETMASK6");
		}
#endif
#endif
		ap++, entry->intf_alias_num++;
	}
#ifdef HAVE_LINUX_PROCFS
#define PROC_INET6_FILE	"/proc/net/if_inet6"
	{
		FILE *f;
		char buf[256], s[8][5], name[INTF_NAME_LEN];
		u_int idx, bits, scope, flags;
		
		if ((f = fopen(PROC_INET6_FILE, "r")) != NULL) {
			while (ap < lap &&
			       fgets(buf, sizeof(buf), f) != NULL) {
				sscanf(buf, "%04s%04s%04s%04s%04s%04s%04s%04s %x %02x %02x %02x %32s\n",
				    s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7],
				    &idx, &bits, &scope, &flags, name);
				if (strcmp(name, entry->intf_name) == 0) {
					snprintf(buf, sizeof(buf), "%s:%s:%s:%s:%s:%s:%s:%s/%d",
					    s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], bits);
					addr_aton(buf, ap);
					ap++, entry->intf_alias_num++;
				}
			}
			fclose(f);
		}
	}
#endif
	entry->intf_len = (u_char *)ap - (u_char *)entry;
	
	return (0);
}
Beispiel #9
0
int
_intf_get_noalias(intf_t *intf, struct intf_entry *entry)
{
	struct lifreq lifr;
	int fd;

	/* Get interface index. */
	entry->intf_index = if_nametoindex(entry->intf_name);
	if (entry->intf_index == 0)
		return (-1);

	strlcpy(lifr.lifr_name, entry->intf_name, sizeof(lifr.lifr_name));

	/* Get interface flags. Here he also check whether we need to use fd or
	 * fd6 in the rest of the function. Using the wrong address family in
	 * the ioctls gives ENXIO on Solaris. */
	if (ioctl(intf->fd, SIOCGLIFFLAGS, &lifr) >= 0)
		fd = intf->fd;
	else if (intf->fd6 != -1 && ioctl(intf->fd6, SIOCGLIFFLAGS, &lifr) >= 0)
		fd = intf->fd6;
	else
		return (-1);
	
	entry->intf_flags = intf_iff_to_flags(lifr.lifr_flags);
	_intf_set_type(entry);
	
	/* Get interface MTU. */
#ifdef SIOCGLIFMTU
	if (ioctl(fd, SIOCGLIFMTU, &lifr) < 0)
#endif
		return (-1);
	entry->intf_mtu = lifr.lifr_mtu;

	entry->intf_addr.addr_type = entry->intf_dst_addr.addr_type =
	    entry->intf_link_addr.addr_type = ADDR_TYPE_NONE;
	
	/* Get primary interface address. */
	if (ioctl(fd, SIOCGLIFADDR, &lifr) == 0) {
		addr_ston((struct sockaddr *)&lifr.lifr_addr, &entry->intf_addr);
		if (ioctl(fd, SIOCGLIFNETMASK, &lifr) < 0)
			return (-1);
		addr_stob((struct sockaddr *)&lifr.lifr_addr, &entry->intf_addr.addr_bits);
	}
	/* Get other addresses. */
	if (entry->intf_type == INTF_TYPE_TUN) {
		if (ioctl(fd, SIOCGLIFDSTADDR, &lifr) == 0) {
			if (addr_ston((struct sockaddr *)&lifr.lifr_addr,
			    &entry->intf_dst_addr) < 0)
				return (-1);
		}
	} else if (entry->intf_type == INTF_TYPE_ETH) {
		eth_t *eth;
		
		if ((eth = eth_open(entry->intf_name)) != NULL) {
			if (!eth_get(eth, &entry->intf_link_addr.addr_eth)) {
				entry->intf_link_addr.addr_type =
				    ADDR_TYPE_ETH;
				entry->intf_link_addr.addr_bits =
				    ETH_ADDR_BITS;
			}
			eth_close(eth);
		}
	}
	return (0);
}
Beispiel #10
0
static int
_intf_get_noalias(intf_t *intf, struct intf_entry *entry)
{
	struct ifreq ifr;
#ifdef HAVE_GETKERNINFO
  int size;
  struct kinfo_ndd *nddp;
  void *end;
#endif

	/* Get interface index. */
	entry->intf_index = if_nametoindex(entry->intf_name);
	if (entry->intf_index == 0)
		return (-1);

	strlcpy(ifr.ifr_name, entry->intf_name, sizeof(ifr.ifr_name));

	/* Get interface flags. */
	if (ioctl(intf->fd, SIOCGIFFLAGS, &ifr) < 0)
		return (-1);

	entry->intf_flags = intf_iff_to_flags(ifr.ifr_flags);
	_intf_set_type(entry);

	/* Get interface MTU. */
#ifdef SIOCGIFMTU
	if (ioctl(intf->fd, SIOCGIFMTU, &ifr) < 0)
#endif
		return (-1);
	entry->intf_mtu = ifr.ifr_mtu;

	entry->intf_addr.addr_type = entry->intf_dst_addr.addr_type =
	    entry->intf_link_addr.addr_type = ADDR_TYPE_NONE;

	/* Get primary interface address. */
	if (ioctl(intf->fd, SIOCGIFADDR, &ifr) == 0) {
		addr_ston(&ifr.ifr_addr, &entry->intf_addr);
		if (ioctl(intf->fd, SIOCGIFNETMASK, &ifr) < 0)
			return (-1);
		addr_stob(&ifr.ifr_addr, &entry->intf_addr.addr_bits);
	}
	/* Get other addresses. */
	if (entry->intf_type == INTF_TYPE_TUN) {
		if (ioctl(intf->fd, SIOCGIFDSTADDR, &ifr) == 0) {
			if (addr_ston(&ifr.ifr_addr,
			    &entry->intf_dst_addr) < 0)
				return (-1);
		}
	} else if (entry->intf_type == INTF_TYPE_ETH) {
#if defined(HAVE_GETKERNINFO)
	  /* AIX also defines SIOCGIFHWADDR, but it fails silently?
	   * This is the method IBM recommends here:
	   * http://www-01.ibm.com/support/knowledgecenter/ssw_aix_53/com.ibm.aix.progcomm/doc/progcomc/skt_sndother_ex.htm%23ssqinc2joyc?lang=en
	   */
	  /* How many bytes will be returned? */
    size = getkerninfo(KINFO_NDD, 0, 0, 0);
    if (size <= 0) {
      return -1;
    }
    nddp = (struct kinfo_ndd *)malloc(size);

    if (!nddp) {
      return -1;
    }
    /* Get all Network Device Driver (NDD) info */
    if (getkerninfo(KINFO_NDD, nddp, &size, 0) < 0) {
      free(nddp);
      return -1;
    }
    /* Loop over the returned values until we find a match */
    end = (void *)nddp + size;
    while ((void *)nddp < end) {
      if (!strcmp(nddp->ndd_alias, entry->intf_name) ||
          !strcmp(nddp->ndd_name, entry->intf_name)) {
        addr_pack(&entry->intf_link_addr, ADDR_TYPE_ETH, ETH_ADDR_BITS,
            nddp->ndd_addr, ETH_ADDR_LEN);
        break;
      } else
        nddp++;
    }
    free(nddp);
#elif defined(SIOCGIFHWADDR)
		if (ioctl(intf->fd, SIOCGIFHWADDR, &ifr) < 0)
			return (-1);
		if (addr_ston(&ifr.ifr_addr, &entry->intf_link_addr) < 0)
			return (-1);
#elif defined(SIOCRPHYSADDR)
		/* Tru64 */
		struct ifdevea *ifd = (struct ifdevea *)&ifr; /* XXX */

		if (ioctl(intf->fd, SIOCRPHYSADDR, ifd) < 0)
			return (-1);
		addr_pack(&entry->intf_link_addr, ADDR_TYPE_ETH, ETH_ADDR_BITS,
		    ifd->current_pa, ETH_ADDR_LEN);
#else
		eth_t *eth;

		if ((eth = eth_open(entry->intf_name)) != NULL) {
			if (!eth_get(eth, &entry->intf_link_addr.addr_eth)) {
				entry->intf_link_addr.addr_type =
				    ADDR_TYPE_ETH;
				entry->intf_link_addr.addr_bits =
				    ETH_ADDR_BITS;
			}
			eth_close(eth);
		}
#endif
	}
	return (0);
}
Beispiel #11
0
int
route_loop(route_t *r, route_handler callback, void *arg)
{
    struct rt_msghdr *rtm;
    struct route_entry entry;
    struct sockaddr *sa;
    char *buf, *lim, *next;
    int ret;
#ifdef HAVE_SYS_SYSCTL_H
    int mib[6] = { CTL_NET, PF_ROUTE, 0, 0 /* XXX */, NET_RT_DUMP, 0 };
    size_t len;

    if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
        return (-1);

    if (len == 0)
        return (0);

    if ((buf = malloc(len)) == NULL)
        return (-1);

    if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
        free(buf);
        return (-1);
    }
    lim = buf + len;
    next = buf;
#else /* HAVE_STREAMS_ROUTE */
    struct rt_giarg giarg, *gp;

    memset(&giarg, 0, sizeof(giarg));
    giarg.gi_op = KINFO_RT_DUMP;

    if (ioctl(r->fd, RTSTR_GETROUTE, &giarg) < 0)
        return (-1);

    if ((buf = malloc(giarg.gi_size)) == NULL)
        return (-1);

    gp = (struct rt_giarg *)buf;
    gp->gi_size = giarg.gi_size;
    gp->gi_op = KINFO_RT_DUMP;
    gp->gi_where = buf;
    gp->gi_arg = RTF_UP | RTF_GATEWAY;

    if (ioctl(r->fd, RTSTR_GETROUTE, buf) < 0) {
        free(buf);
        return (-1);
    }
    lim = buf + gp->gi_size;
    next = buf + sizeof(giarg);
#endif
    for (ret = 0; next < lim; next += rtm->rtm_msglen) {
        rtm = (struct rt_msghdr *)next;
        sa = (struct sockaddr *)(rtm + 1);

        if (addr_ston(sa, &entry.route_dst) < 0 ||
                (rtm->rtm_addrs & RTA_GATEWAY) == 0)
            continue;

        sa = NEXTSA(sa);

        if (addr_ston(sa, &entry.route_gw) < 0)
            continue;

        if (entry.route_dst.addr_type != entry.route_gw.addr_type ||
                (entry.route_dst.addr_type != ADDR_TYPE_IP &&
                 entry.route_dst.addr_type != ADDR_TYPE_IP6))
            continue;

        if (rtm->rtm_addrs & RTA_NETMASK) {
            sa = NEXTSA(sa);
            if (addr_stob(sa, &entry.route_dst.addr_bits) < 0)
                continue;
        }
        if ((ret = callback(&entry, arg)) != 0)
            break;
    }
    free(buf);

    return (ret);
}