Esempio n. 1
0
/*
 * Update the register vif in the multicast routing daemon and the
 * kernel because the interface used initially to get its local address
 * is DOWN. register_vifi is the index to the Register vif which needs
 * to be updated. As a result the Register vif has a new uv_lcl_addr and
 * is UP (virtually :))
 */
int
update_reg_vif( mifi_t register_vifi )
{
    register struct uvif *v;
    register mifi_t vifi;

    /* Find the first useable vif with solid physical background */
    for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
	if (v->uv_flags & (VIFF_DISABLED | VIFF_DOWN | MIFF_REGISTER))
	    continue;
        /* Found. Stop the bogus Register vif first */
	stop_vif(register_vifi);
	add_phaddr(v, &uvifs[vifi].uv_linklocal->pa_addr,
		   &uvifs[vifi].uv_linklocal->pa_subnetmask,
		   &uvifs[vifi].uv_linklocal->pa_prefix); 
	start_vif(register_vifi);
	IF_DEBUG(DEBUG_PIM_REGISTER | DEBUG_IF)
	    log_msg(LOG_NOTICE, 0, "%s has come up; vif #%u now in service",
		uvifs[register_vifi].uv_name, register_vifi);
	return 0;
    }
    vifs_down = TRUE;
    log_msg(LOG_WARNING, 0, "Cannot start Register vif: %s",
	uvifs[vifi].uv_name);
    return(-1);
}
Esempio n. 2
0
int init_reg_vif()
{
	struct uvif *v;
	mifi_t i;

	v = &uvifs[numvifs];
	if ((numvifs + 1) == MAXMIFS) {
	     /* Exit the program! The PIM router must have a Register vif */
	    log_msg(LOG_ERR, 0,
		"cannot install the Register vif: too many interfaces");
	    /* To make lint happy */
	    return (FALSE);
	}

	/*
	 * So far in PIM we need only one register vif and we save its number in
	 * the global reg_vif_num.
	 */


	reg_vif_num = numvifs;


	/* 
	 * copy the address of the first available physical interface to
	 * create the register vif.
	 */
	for (i =0 ; i < numvifs ; i++) {
		if (uvifs[i].uv_flags & (VIFF_DOWN | VIFF_DISABLED | MIFF_REGISTER))
			continue;
		break;
	}
	if (i >= numvifs) {
		log_msg(LOG_ERR, 0, "No physical interface enabled");
		return -1;
	}
	
	add_phaddr(v, &uvifs[i].uv_linklocal->pa_addr,
		   &uvifs[i].uv_linklocal->pa_subnetmask,
		   &uvifs[i].uv_linklocal->pa_prefix); 
	v->uv_ifindex = uvifs[i].uv_ifindex;
#ifdef HAVE_STRLCPY
	strlcpy(v->uv_name, "register_mif0", IFNAMSIZ);
#elif HAVE_STRNCPY
	strncpy(v->uv_name, "register_mif0", IFNAMSIZ);
#else
	strcpy(v->uv_name, "register_mif0");
#endif
	v->uv_flags = MIFF_REGISTER;
	v->uv_mld_version = MLDv1;

#ifdef PIM_EXPERIMENTAL
	v->uv_flags |= MIFF_REGISTER_KERNEL_ENCAP;
#endif

	IF_DEBUG(DEBUG_IF)
		log_msg(LOG_DEBUG, 0,
		    "Interface %s (subnet %s), installed on vif #%u - rate = %d",
		    v->uv_name,
		    net6name(&v->uv_prefix.sin6_addr,&v->uv_subnetmask),
		    reg_vif_num,
		    v->uv_rate_limit);

	numvifs++;
	total_interfaces++;
	return 0;	
}
Esempio n. 3
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 */
}