示例#1
0
/*
 * Initialize the passed vif with all appropriate default values.
 * "t" is true if a tunnel, or false if a phyint.
 */
void zero_vif(struct uvif *v, int t)
{
    v->uv_flags		= 0;
    v->uv_metric	= DEFAULT_METRIC;
    v->uv_admetric	= 0;
    v->uv_threshold	= DEFAULT_THRESHOLD;
    v->uv_rate_limit	= t ? DEFAULT_TUN_RATE_LIMIT : DEFAULT_PHY_RATE_LIMIT;
    v->uv_lcl_addr	= 0;
    v->uv_rmt_addr	= 0;
    v->uv_dst_addr	= t ? 0 : dvmrp_group;
    v->uv_subnet	= 0;
    v->uv_subnetmask	= 0;
    v->uv_subnetbcast	= 0;
    v->uv_name[0]	= '\0';
    v->uv_groups	= NULL;
    v->uv_neighbors	= NULL;
    NBRM_CLRALL(v->uv_nbrmap);
    v->uv_querier	= NULL;
    v->uv_igmpv1_warn	= 0;
    v->uv_prune_lifetime = 0;
    v->uv_leaf_timer	= 0;
    v->uv_acl		= NULL;
    v->uv_addrs		= NULL;
    v->uv_filter	= NULL;
    v->uv_blasterbuf	= NULL;
    v->uv_blastercur	= NULL;
    v->uv_blasterend	= NULL;
    v->uv_blasterlen	= 0;
    v->uv_blastertimer	= 0;
    v->uv_nbrup		= 0;
    v->uv_icmp_warn	= 0;
    v->uv_nroutes	= 0;
}
示例#2
0
/*
 * Query the kernel to find network interfaces that are multicast-capable
 * and install them in the uvifs array.
 */
void 
config_vifs_from_kernel()
{
    register struct uvif *v=NULL;
    register vifi_t vifi;
    struct sockaddr_in6 addr;
    struct in6_addr mask, prefix;
    short flags;
#ifdef HAVE_GETIFADDRS
    struct ifaddrs *ifap=NULL, *ifa=NULL;//init by ziqiang 
#else
    int n;
    int num_ifreq = 64;
    struct ifconf ifc;
    struct ifreq *ifrp=NULL, *ifend=NULL;//init by ziqiang 
#endif 

    total_interfaces = 0; /* The total number of physical interfaces */
    
#ifdef HAVE_GETIFADDRS
    if (getifaddrs(&ifap))
    	{
	syslog(LOG_ERR, "getiaddrs() error  ifap = %p\n",ifap);
	return ;//by ziqiang
    	}

    /*
     * Loop through all of the interfaces.
     */
    for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
	/*
	 * Ignore any interface for an address family other than IPv6.
	 */
	if (ifa->ifa_addr->sa_family != AF_INET6) {
	    total_interfaces++;  /* Eventually may have IPv6 address later */
	    continue;
	}

	memcpy(&addr, ifa->ifa_addr, sizeof(struct sockaddr_in6));
	
	flags = ifa->ifa_flags;
	if ((flags & (IFF_LOOPBACK | IFF_MULTICAST)) != IFF_MULTICAST)
	    continue;

	/*
	 * Get netmask of the address.
	 */
	//memcpy(&mask, &((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr,
	   //    sizeof(mask));
	inet_pton(AF_INET6, "ffff:ffff:ffff:ffff::", &mask);

	if (IN6_IS_ADDR_LINKLOCAL(&addr.sin6_addr)) {
		addr.sin6_scope_id = if_nametoindex(ifa->ifa_name);
#ifdef __KAME__
		/*
		 * Hack for KAME kernel. Set sin6_scope_id field of a
		 * link local address and clear the index embedded in
		 * the address.
		 */
		/* clear interface index */
		addr.sin6_addr.s6_addr[2] = 0;
		addr.sin6_addr.s6_addr[3] = 0;
#endif
	}

	/*
	 * If the address is connected to the same subnet as one already
	 * installed in the uvifs array, just add the address to the list
	 * of addresses of the uvif.
	 */
	for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
	    if (strcmp(v->uv_name, ifa->ifa_name) == 0) {
		    add_phaddr(v, &addr, &mask);
		    break;
	    }
	}
	if (vifi != numvifs)
	    continue;

	/*
	 * If there is room in the uvifs array, install this interface.
	 */
	if (numvifs == MAXMIFS) {
	    syslog(LOG_WARNING, "too many ifs, ignoring %s", ifa->ifa_name);
	    continue;
	}

	/*
	 * Everyone below is a potential vif interface.
	 * We don't care if it has wrong configuration or not configured
	 * at all.
	 */
	total_interfaces++;
	
	v = &uvifs[numvifs];
	v->uv_flags		= 0;
	v->uv_metric		= DEFAULT_METRIC;
	v->uv_admetric		= 0;
	v->uv_rate_limit	= DEFAULT_PHY_RATE_LIMIT;
	v->uv_dst_addr		= allpim6routers_group;
	v->uv_prefix.sin6_addr	= prefix;
	v->uv_subnetmask	= mask;
	strncpy(v->uv_name, ifa->ifa_name, IFNAMSIZ);
	v->uv_ifindex	        = if_nametoindex(v->uv_name);
	v->uv_groups		= (struct listaddr *)NULL;
	v->uv_dvmrp_neighbors   = (struct listaddr *)NULL;
	NBRM_CLRALL(v->uv_nbrmap);
	v->uv_querier           = (struct listaddr *)NULL;
	v->uv_prune_lifetime    = 0;
	v->uv_acl               = (struct vif_acl *)NULL;
	v->uv_leaf_timer        = 0;
	v->uv_addrs		= (struct phaddr *)NULL;
	v->uv_filter		= (struct vif_filter *)NULL;
	v->uv_pim_hello_timer   = 0;
	v->uv_gq_timer          = 0;
	v->uv_pim_neighbors	= (struct pim_nbr_entry *)NULL;
	v->uv_local_pref        = default_source_preference;
	v->uv_local_metric      = default_source_metric;
	add_phaddr(v, &addr, &mask);
	
	if (flags & IFF_POINTOPOINT)
	    v->uv_flags |= (VIFF_REXMIT_PRUNES | VIFF_POINT_TO_POINT);
	syslog(LOG_INFO,
	    "installing %s as if #%u - rate=%d",
	    v->uv_name, numvifs, v->uv_rate_limit);
	++numvifs;

	/*
	 * If the interface is not yet up, set the vifs_down flag to
	 * remind us to check again later.
	 */
	if (!(flags & IFF_UP)) {
	    v->uv_flags |= VIFF_DOWN;
	    vifs_down = TRUE;
	}
    }

    freeifaddrs(ifap);
#else /* !HAVE_GETIFADDRS */

    ifc.ifc_len = num_ifreq * sizeof(struct ifreq);
    ifc.ifc_buf = calloc(ifc.ifc_len, sizeof(char));
    while (ifc.ifc_buf) {
	caddr_t newbuf;

	if (ioctl(udp_socket, SIOCGIFCONF, (char *)&ifc) < 0)
	    syslog(LOG_ERR, "ioctl SIOCGIFCONF");
	
	/*
	 * If the buffer was large enough to hold all the addresses
	 * then break out, otherwise increase the buffer size and
	 * try again.
	 *
	 * The only way to know that we definitely had enough space
	 * is to know that there was enough space for at least one
	 * more struct ifreq. ???
	 */
	if ((num_ifreq * sizeof(struct ifreq)) >=
	    ifc.ifc_len + sizeof(struct ifreq))
	    break;
	
	num_ifreq *= 2;
	ifc.ifc_len = num_ifreq * sizeof(struct ifreq);
	newbuf = realloc(ifc.ifc_buf, ifc.ifc_len);
	if (newbuf == NULL)
	    free(ifc.ifc_buf);
	ifc.ifc_buf = newbuf;
    }
    if (ifc.ifc_buf == NULL)
	syslog(LOG_ERR, "config_vifs_from_kernel: ran out of memory");
    
    ifrp = (struct ifreq *)ifc.ifc_buf;
    ifend = (struct ifreq *)(ifc.ifc_buf + ifc.ifc_len);
    /*
     * Loop through all of the interfaces.
     */
    for (; ifrp < ifend; ifrp = (struct ifreq *)((char *)ifrp + n)) {
	struct ifreq ifr;
	struct in6_ifreq ifr6;
#ifdef HAVE_SA_LEN
	n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
	if (n < sizeof(*ifrp))
	    n = sizeof(*ifrp);
#else
	n = sizeof(*ifrp);
#endif /* HAVE_SA_LEN */
	
	/*
	 * Ignore any interface for an address family other than IPv6.
	 */
	if (ifrp->ifr_addr.sa_family != AF_INET6) {
	    total_interfaces++;  /* Eventually may have IPv6 address later */
	    continue;
	}

	memcpy(&addr, &ifrp->ifr_addr, sizeof(struct sockaddr_in6));
	
	/*
	 * Need a template to preserve address info that is
	 * used below to locate the next entry.  (Otherwise,
	 * SIOCGIFFLAGS stomps over it because the requests
	 * are returned in a union.)
	 */
	memcpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name));
	memcpy(ifr6.ifr_name, ifrp->ifr_name, sizeof(ifr6.ifr_name));

	/*
	 * Ignore loopback interfaces and interfaces that do not
	 * support multicast.
	 */
	if (ioctl(udp_socket, SIOCGIFFLAGS, (char *)&ifr) < 0)
	    syslog(LOG_ERR, "ioctl SIOCGIFFLAGS for %s", ifr.ifr_name);
	flags = ifr.ifr_flags;
	if ((flags & (IFF_LOOPBACK | IFF_MULTICAST)) != IFF_MULTICAST)
	    continue;

	/*
	 * Get netmask of the address.
	 */
	ifr6.ifr_addr = *(struct sockaddr_in6 *)&ifrp->ifr_addr;
	if (ioctl(udp_socket, SIOCGIFNETMASK_IN6, (char *)&ifr6) < 0)
	    syslog(LOG_ERR, "ioctl SIOCGIFNETMASK_IN6 for %s",
		ifr6.ifr_name);
	memcpy(&mask, &ifr6.ifr_addr.sin6_addr, sizeof(mask));

	if (IN6_IS_ADDR_LINKLOCAL(&addr.sin6_addr)) {
		addr.sin6_scope_id = if_nametoindex(ifrp->ifr_name);
#ifdef __KAME__
		/*
		 * Hack for KAME kernel. Set sin6_scope_id field of a
		 * link local address and clear the index embedded in
		 * the address.
		 */
		/* clear interface index */
		addr.sin6_addr.s6_addr[2] = 0;
		addr.sin6_addr.s6_addr[3] = 0;
#endif
	}

	/*
	 * If the address is connected to the same subnet as one already
	 * installed in the uvifs array, just add the address to the list
	 * of addresses of the uvif.
	 */
	for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
	    if (strcmp(v->uv_name, ifr.ifr_name) == 0) {
		    add_phaddr(v, &addr, &mask);
		    break;
	    }
	}
	if (vifi != numvifs)
	    continue;

	/*
	 * If there is room in the uvifs array, install this interface.
	 */
	if (numvifs == MAXMIFS) {
	    syslog(LOG_WARNING, "too many ifs, ignoring %s", ifr.ifr_name);
	    continue;
	}

	/*
	 * Everyone below is a potential vif interface.
	 * We don't care if it has wrong configuration or not configured
	 * at all.
	 */
	total_interfaces++;
	
	v = &uvifs[numvifs];
	v->uv_flags		= 0;
	v->uv_metric		= DEFAULT_METRIC;
	v->uv_admetric		= 0;
	v->uv_rate_limit	= DEFAULT_PHY_RATE_LIMIT;
	v->uv_dst_addr		= allpim6routers_group;
	v->uv_prefix.sin6_addr	= prefix;
	v->uv_subnetmask	= mask;
	strncpy(v->uv_name, ifr.ifr_name, IFNAMSIZ);
	v->uv_ifindex	        = if_nametoindex(v->uv_name);
	v->uv_groups		= (struct listaddr *)NULL;
	v->uv_dvmrp_neighbors   = (struct listaddr *)NULL;
	NBRM_CLRALL(v->uv_nbrmap);
	v->uv_querier           = (struct listaddr *)NULL;
	v->uv_prune_lifetime    = 0;
	v->uv_acl               = (struct vif_acl *)NULL;
	v->uv_leaf_timer        = 0;
	v->uv_addrs		= (struct phaddr *)NULL;
	v->uv_filter		= (struct vif_filter *)NULL;
	v->uv_pim_hello_timer   = 0;
	v->uv_gq_timer          = 0;
	v->uv_pim_neighbors	= (struct pim_nbr_entry *)NULL;
	v->uv_local_pref        = default_source_preference;
	v->uv_local_metric      = default_source_metric;
	add_phaddr(v, &addr, &mask);
	
	if (flags & IFF_POINTOPOINT)
	    v->uv_flags |= (VIFF_REXMIT_PRUNES | VIFF_POINT_TO_POINT);
	syslog(LOG_INFO,
	    "installing %s as if #%u - rate=%d",
	    v->uv_name, numvifs, v->uv_rate_limit);
	++numvifs;
	
	/*
	 * If the interface is not yet up, set the vifs_down flag to
	 * remind us to check again later.
	 */
	if (!(flags & IFF_UP)) {
	    v->uv_flags |= VIFF_DOWN;
	    vifs_down = TRUE;
	}
    }
#endif /* HAVE_GETIFADDRS */
}