FreeBSD/sys/netinet/ip_mroute.c
/*
 * Add a vif to the vif table
 */
Add a vif to the vif table
Add a vif to the vif table
static int
add_vif(struct vifctl *vifcp)
{
    struct vif *vifp = V_viftable + vifcp->vifc_vifi;
    struct sockaddr_in sin = {sizeof sin, AF_INET};
    struct ifaddr *ifa;
    struct ifnet *ifp;
    int error;
    VIF_LOCK();
    if (vifcp->vifc_vifi >= MAXVIFS) {
	VIF_UNLOCK();
	return EINVAL;
    }
    if (vifcp->vifc_rate_limit != 0) {
	log(LOG_ERR, "rate limiting is no longer supported\n");
	VIF_UNLOCK();
	return EINVAL;
    }
    if (!in_nullhost(vifp->v_lcl_addr)) {
	VIF_UNLOCK();
	return EADDRINUSE;
    }
    if (in_nullhost(vifcp->vifc_lcl_addr)) {
	VIF_UNLOCK();
	return EADDRNOTAVAIL;
    }
    if (vifcp->vifc_flags & VIFF_REGISTER) {
	ifp = NULL;
    } else {
	sin.sin_addr = vifcp->vifc_lcl_addr;
	ifa = ifa_ifwithaddr((struct sockaddr *)&sin);
	if (ifa == NULL) {
	    VIF_UNLOCK();
	    return EADDRNOTAVAIL;
	}
	ifp = ifa->ifa_ifp;
	ifa_free(ifa);
    }
    if ((vifcp->vifc_flags & VIFF_TUNNEL) != 0) {
	CTR1(KTR_IPMF, "%s: tunnels are no longer supported", __func__);
	VIF_UNLOCK();
	return EOPNOTSUPP;
    } else if (vifcp->vifc_flags & VIFF_REGISTER) {
	ifp = &V_multicast_register_if;
	CTR2(KTR_IPMF, "%s: add register vif for ifp %p", __func__, ifp);
	if (V_reg_vif_num == VIFI_INVALID) {
	    if_initname(&V_multicast_register_if, "register_vif", 0);
	    V_multicast_register_if.if_flags = IFF_LOOPBACK;
	    V_reg_vif_num = vifcp->vifc_vifi;
	}
    } else {		
	if ((ifp->if_flags & IFF_MULTICAST) == 0) {
	    VIF_UNLOCK();
	    return EOPNOTSUPP;
	}
	error = if_allmulti(ifp, 1);
	if (error) {
	    VIF_UNLOCK();
	    return error;
	}
    }
    vifp->v_flags     = vifcp->vifc_flags;
    vifp->v_threshold = vifcp->vifc_threshold;
    vifp->v_lcl_addr  = vifcp->vifc_lcl_addr;
    vifp->v_rmt_addr  = vifcp->vifc_rmt_addr;
    vifp->v_ifp       = ifp;
    vifp->v_pkt_in    = 0;
    vifp->v_pkt_out   = 0;
    vifp->v_bytes_in  = 0;
    vifp->v_bytes_out = 0;
    if (V_numvifs <= vifcp->vifc_vifi)
	V_numvifs = vifcp->vifc_vifi + 1;
    VIF_UNLOCK();
    CTR4(KTR_IPMF, "%s: add vif %d laddr %s thresh %x", __func__,
	(int)vifcp->vifc_vifi, inet_ntoa(vifcp->vifc_lcl_addr),
	(int)vifcp->vifc_threshold);
    return 0;
}
static int add_vif ( struct vifctl * vifcp ) { struct vif * vifp = V_viftable + vifcp -> vifc_vifi ; struct sockaddr_in sin = { sizeof sin , AF_INET } ; struct ifaddr * ifa ; struct ifnet * ifp ; int error ; VIF_LOCK ( ) ; if ( vifcp -> vifc_vifi >= MAXVIFS ) { VIF_UNLOCK ( ) ; return EINVAL ; } if ( vifcp -> vifc_rate_limit != 0 ) { log ( LOG_ERR , " \n " ) ; VIF_UNLOCK ( ) ; return EINVAL ; } if ( ! in_nullhost ( vifp -> v_lcl_addr ) ) { VIF_UNLOCK ( ) ; return EADDRINUSE ; } if ( in_nullhost ( vifcp -> vifc_lcl_addr ) ) { VIF_UNLOCK ( ) ; return EADDRNOTAVAIL ; } if ( vifcp -> vifc_flags & VIFF_REGISTER ) { ifp = NULL ; } else { sin . sin_addr = vifcp -> vifc_lcl_addr ; ifa = ifa_ifwithaddr ( ( struct sockaddr * ) & sin ) ; if ( ifa == NULL ) { VIF_UNLOCK ( ) ; return EADDRNOTAVAIL ; } ifp = ifa -> ifa_ifp ; ifa_free ( ifa ) ; } if ( ( vifcp -> vifc_flags & VIFF_TUNNEL ) != 0 ) { CTR1 ( KTR_IPMF , " " , __func__ ) ; VIF_UNLOCK ( ) ; return EOPNOTSUPP ; } else if ( vifcp -> vifc_flags & VIFF_REGISTER ) { ifp = & V_multicast_register_if ; CTR2 ( KTR_IPMF , " " , __func__ , ifp ) ; if ( V_reg_vif_num == VIFI_INVALID ) { if_initname ( & V_multicast_register_if , " " , 0 ) ; V_multicast_register_if . if_flags = IFF_LOOPBACK ; V_reg_vif_num = vifcp -> vifc_vifi ; } } else { if ( ( ifp -> if_flags & IFF_MULTICAST ) == 0 ) { VIF_UNLOCK ( ) ; return EOPNOTSUPP ; } error = if_allmulti ( ifp , 1 ) ; if ( error ) { VIF_UNLOCK ( ) ; return error ; } } vifp -> v_flags = vifcp -> vifc_flags ; vifp -> v_threshold = vifcp -> vifc_threshold ; vifp -> v_lcl_addr = vifcp -> vifc_lcl_addr ; vifp -> v_rmt_addr = vifcp -> vifc_rmt_addr ; vifp -> v_ifp = ifp ; vifp -> v_pkt_in = 0 ; vifp -> v_pkt_out = 0 ; vifp -> v_bytes_in = 0 ; vifp -> v_bytes_out = 0 ; if ( V_numvifs <= vifcp -> vifc_vifi ) V_numvifs = vifcp -> vifc_vifi + 1 ; VIF_UNLOCK ( ) ; CTR4 ( KTR_IPMF , " " , __func__ , ( int ) vifcp -> vifc_vifi , inet_ntoa ( vifcp -> vifc_lcl_addr ) , ( int ) vifcp -> vifc_threshold ) ; return 0 ; }
Add a vif to the vif table
Add a vif to the vif table
/* rate limiting is no longer supported by this code */ /* Find the interface with an address in AF_INET family */ /*
	 * XXX: Because VIFF_REGISTER does not really need a valid
	 * local interface (e.g. it could be 127.0.0.2), we don't
	 * check its address.
	 */ /* Make sure the interface supports multicast */ /* Enable promiscuous reception of all IP multicasts from the if */ /* initialize per vif pkt counters */ /* Adjust numvifs up if the vifi is higher than numvifs */