예제 #1
0
파일: config.c 프로젝트: pickup09/pimd
/**
 * parseBSR - Parse the candidate BSR configured information.
 * @s: String token
 *
 * Syntax:
 * cand_bootstrap_router [address | ifname] [priority <0-255>]
 */
int parseBSR(char *s)
{
    char *w;
    uint32_t local    = INADDR_ANY_N;
    uint32_t priority = PIM_DEFAULT_BSR_PRIORITY;

    cand_bsr_flag = FALSE;
    while (!EQUAL((w = next_word(&s)), "")) {
	if (EQUAL(w, "priority")) {
	    if (EQUAL((w = next_word(&s)), "")) {
		WARN("Missing Cand-BSR priority, defaulting to %u", PIM_DEFAULT_BSR_PRIORITY);
		priority = PIM_DEFAULT_BSR_PRIORITY;
		continue;
	    }

	    if (sscanf(w, "%u", &priority) != 1) {
		WARN("Invalid Cand-BSR priority %s, defaulting to %u", PIM_DEFAULT_BSR_PRIORITY);
		priority = PIM_DEFAULT_BSR_PRIORITY;
		continue;
	    }

	    if (priority > PIM_MAX_CAND_BSR_PRIORITY) {
		WARN("Too high Cand-BSR priority %u, defaulting to %d", priority, PIM_MAX_CAND_BSR_PRIORITY);
		priority = PIM_MAX_CAND_BSR_PRIORITY;
	    }

	    my_bsr_priority = (u_int8)priority;
	    continue;
	}

	/* Cand-BSR interface or address */
	local = ifname2addr(w);
	if (!local)
	    local = inet_parse(w, 4);

	if (!inet_valid_host(local)) {
	    local = max_local_address();
	    WARN("Invalid Cand-BSR address '%s', defaulting to %s", w, inet_fmt(local, s1, sizeof(s1)));
	    continue;
	}

	if (local_address(local) == NO_VIF) {
	    local = max_local_address();
	    WARN("Cand-BSR address '%s' is not local, defaulting to %s", w, inet_fmt(local, s1, sizeof(s1)));
	}
    }

    if (local == INADDR_ANY_N) {
	/* If address not provided, use the max. local */
	local = max_local_address();
    }

    my_bsr_address  = local;
    my_bsr_priority = priority;
    MASKLEN_TO_MASK(RP_DEFAULT_IPV4_HASHMASKLEN, my_bsr_hash_mask);
    cand_bsr_flag   = TRUE;
    logit(LOG_INFO, 0, "Local Cand-BSR address %s, priority %u", inet_fmt(local, s1, sizeof(s1)), priority);

    return TRUE;
}
예제 #2
0
파일: config.c 프로젝트: F0rth/pimd
/*
 * function name: parseBSR
 * input: char *s
 * output: int
 * operation: parse the candidate BSR configured information.
 *	General form:
 *	'cand_bootstrap_router <local-addr> [priority <number>]'.
 */
int parseBSR(char *s)
{
    char *w;
    u_int32 local    = INADDR_ANY_N;
    u_int32 priority = PIM_DEFAULT_BSR_PRIORITY;

    cand_bsr_flag = FALSE;
    while (!EQUAL((w = next_word(&s)), "")) {
        if (EQUAL(w, "priority")) {
            if (EQUAL((w = next_word(&s)), "")) {
                logit(LOG_WARNING, 0,
                      "Missing priority; set to default %u (0 is lowest)\n",
                      PIM_DEFAULT_BSR_PRIORITY);
                priority = PIM_DEFAULT_BSR_PRIORITY;
                continue;
            }
            if (sscanf(w, "%u", &priority) != 1) {
                logit(LOG_WARNING, 0,
                      "invalid priority %s; set to default %u (0 is lowest)",
                      PIM_DEFAULT_BSR_PRIORITY);
                priority = PIM_DEFAULT_BSR_PRIORITY;
                continue;
            }
            if (priority > (my_bsr_priority = ~0))
                priority = my_bsr_priority;
            my_bsr_priority = (u_int8)priority;
            continue;
        }

        /* BSR address */
        local = inet_parse(w, 4);
        if (!inet_valid_host(local)) {
            local = max_local_address();
            logit(LOG_WARNING, 0, "Invalid BSR address provided '%s' in %s. Will use the largest enabled local address.",
                  w, configfilename);
            continue;
        }
        if (local_address(local) == NO_VIF) {
            local = max_local_address();
            logit(LOG_WARNING, 0,
                  "Cand-BSR address is not local '%s' in %s. Will use the largest enabled local address.",
                  w, configfilename);
        }
    }		/* while not empty */

    if (local == INADDR_ANY_N)
        /* If address not provided, use the max. local */
        local = max_local_address();
    my_bsr_address  = local;
    my_bsr_priority = priority;
    MASKLEN_TO_MASK(RP_DEFAULT_IPV4_HASHMASKLEN, my_bsr_hash_mask);
    cand_bsr_flag   = TRUE;
    logit(LOG_INFO, 0, "Local Cand-BSR address is %s", inet_fmt(local, s1, sizeof(s1)));
    logit(LOG_INFO, 0, "Local Cand-BSR priority is %u", priority);

    return TRUE;
}
예제 #3
0
파일: mrt.c 프로젝트: CameronNemo/pimd
srcentry_t *find_source(u_int32 source)
{
    srcentry_t *src;

    if (!inet_valid_host(source))
	return NULL;

    if (search_srclist(source, &src) == TRUE)
	return src;	/* Source found! */

    return NULL;
}
예제 #4
0
파일: mrt.c 프로젝트: CameronNemo/pimd
mrtentry_t *find_route(u_int32 source, u_int32 group, u_int16 flags, char create)
{
    srcentry_t *src	     = NULL;
    grpentry_t *grp	     = NULL;
    mrtentry_t *mrt	     = NULL;
    mrtentry_t *mrt_wc	     = NULL;
    mrtentry_t *mrt_pmbr    = NULL;
    mrtentry_t *mrt2	     = NULL;
    rpentry_t  *rp	     = NULL;
    rp_grp_entry_t *rp_grp = NULL;

    if (flags & (MRTF_SG | MRTF_WC)) {
	if (!IN_MULTICAST(ntohl(group)))
	    return NULL;
    }

    if (flags & MRTF_SG) {
	if (!inet_valid_host(source))
	    return NULL;
    }

    if (create == DONT_CREATE) {
	if (flags & (MRTF_SG | MRTF_WC)) {
	    if (search_grplist(group, &grp) == FALSE) {
		/* Group not found. Return the (*,*,RP) entry */
		if (flags & MRTF_PMBR) {
		    rp = rp_match(group);
		    if (rp)
			return rp->mrtlink;
		}

		return NULL;
	    }

	    /* Search for the source */
	    if (flags & MRTF_SG) {
		if (search_grpmrtlink(grp, source, &mrt) == TRUE) {
		    /* Exact (S,G) entry found */
		    return mrt;
		}
	    }

	    /* No (S,G) entry. Return the (*,G) entry (if exist) */
	    if ((flags & MRTF_WC) && grp->grp_route)
		return grp->grp_route;
	}

	/* Return the (*,*,RP) entry */
	if (flags & MRTF_PMBR) {
	    rp = NULL;
	    if (group != INADDR_ANY_N)
		rp = rp_match(group);
	    else if (source != INADDR_ANY_N)
		rp = rp_find(source);

	    if (rp)
		return rp->mrtlink;
	}

	return NULL;
    }


    /* Creation allowed */

    if (flags & (MRTF_SG | MRTF_WC)) {
	grp = create_grpentry(group);
	if (!grp)
	    return NULL;

	if (!grp->active_rp_grp) {
	    rp_grp = rp_grp_match(group);
	    if (!rp_grp) {
		if (!grp->mrtlink && !grp->grp_route) {
		    /* New created grpentry. Delete it. */
		    delete_grpentry(grp);
		}

		return NULL;
	    }

	    rp = rp_grp->rp->rpentry;
	    grp->active_rp_grp = rp_grp;
	    grp->rpaddr = rp->address;

	    /* Link to the top of the rp_grp_chain */
	    grp->rpnext = rp_grp->grplink;
	    rp_grp->grplink = grp;
	    if (grp->rpnext)
		grp->rpnext->rpprev = grp;
	}
	else {
	    rp = grp->active_rp_grp->rp->rpentry;
	}
    }

    mrt_wc = mrt_pmbr = NULL;

    if (flags & MRTF_WC) {
	/* Setup the (*,G) routing entry */
	mrt_wc = create_mrtentry(NULL, grp, MRTF_WC);
	if (!mrt_wc) {
	    if (!grp->mrtlink) {
		/* New created grpentry. Delete it. */
		delete_grpentry(grp);
	    }

	    return NULL;
	}

	if (mrt_wc->flags & MRTF_NEW) {
	    mrt_pmbr = rp->mrtlink;
	    /* Copy the oif list from the (*,*,RP) entry */
	    if (mrt_pmbr) {
		VOIF_COPY(mrt_pmbr, mrt_wc);
	    }
	    mrt_wc->incoming = rp->incoming;
	    mrt_wc->upstream = rp->upstream;
	    mrt_wc->metric   = rp->metric;
	    mrt_wc->preference = rp->preference;
	    move_kernel_cache(mrt_wc, 0);
#ifdef RSRR
	    rsrr_cache_bring_up(mrt_wc);
#endif /* RSRR */
	}

	if (!(flags & MRTF_SG)) {
	    return mrt_wc;
	}
    }

    if (flags & MRTF_SG) {
	/* Setup the (S,G) routing entry */
	src = create_srcentry(source);
	if (!src) {
	    /* TODO: XXX: The MRTF_NEW flag check may be misleading?? check */
	    if ((!grp->grp_route || (grp->grp_route && (grp->grp_route->flags & MRTF_NEW)))
		&& !grp->mrtlink) {
		/* New created grpentry. Delete it. */
		delete_grpentry(grp);
	    }

	    return NULL;
	}

	mrt = create_mrtentry(src, grp, MRTF_SG);
	if (!mrt) {
	    if ((!grp->grp_route
		 || (grp->grp_route && (grp->grp_route->flags & MRTF_NEW)))
		&& !grp->mrtlink) {
		/* New created grpentry. Delete it. */
		delete_grpentry(grp);
	    }

	    if (!src->mrtlink)
		/* New created srcentry. Delete it. */
		delete_srcentry(src);

	    return NULL;
	}

	if (mrt->flags & MRTF_NEW) {
	    mrt2 = grp->grp_route;
	    if (!mrt2)
		mrt2 = rp->mrtlink;

	    /* Copy the oif list from the existing (*,G) or (*,*,RP) entry */
	    if (mrt2) {
		VOIF_COPY(mrt2, mrt);
		if (flags & MRTF_RP) {
		    /* ~(S,G) prune entry */
		    mrt->incoming    = mrt2->incoming;
		    mrt->upstream    = mrt2->upstream;
		    mrt->metric      = mrt2->metric;
		    mrt->preference  = mrt2->preference;
		    mrt->flags      |= MRTF_RP;
		}
	    }

	    if (!(mrt->flags & MRTF_RP)) {
		mrt->incoming   = src->incoming;
		mrt->upstream   = src->upstream;
		mrt->metric     = src->metric;
		mrt->preference = src->preference;
	    }
	    move_kernel_cache(mrt, 0);
#ifdef RSRR
	    rsrr_cache_bring_up(mrt);
#endif /* RSRR */
	}

	return mrt;
    }

    if (flags & MRTF_PMBR) {
	/* Get/return the (*,*,RP) routing entry */
	if (group != INADDR_ANY_N) {
	    rp = rp_match(group);
	} else if (source != INADDR_ANY_N) {
	    rp = rp_find(source);
	    if (!rp)
		return NULL;
	} else {
	    return NULL; /* source == group == INADDR_ANY */
	}

	if (rp->mrtlink)
	    return rp->mrtlink;

	mrt = create_mrtentry(rp, NULL, MRTF_PMBR);
	if (!mrt)
	    return NULL;

	mrt->incoming = rp->incoming;
	mrt->upstream = rp->upstream;
	mrt->metric   = rp->metric;
	mrt->preference = rp->preference;

	return mrt;
    }

    return NULL;
}
예제 #5
0
파일: config.c 프로젝트: pickup09/pimd
/*
 * Query the kernel to find network interfaces that are multicast-capable
 * and install them in the uvifs array.
 */
void config_vifs_from_kernel(void)
{
    struct ifreq *ifrp, *ifend;
    struct uvif *v;
    vifi_t vifi;
    uint32_t n;
    uint32_t addr, mask, subnet;
    short flags;
    int num_ifreq = 64;
    struct ifconf ifc;
    char *newbuf;

    total_interfaces = 0; /* The total number of physical interfaces */

    ifc.ifc_len = num_ifreq * sizeof(struct ifreq);
    ifc.ifc_buf = calloc(ifc.ifc_len, sizeof(char));
    while (ifc.ifc_buf) {
	if (ioctl(udp_socket, SIOCGIFCONF, (char *)&ifc) < 0)
	    logit(LOG_ERR, errno, "Failed querying kernel network interfaces");

	/*
	 * 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)
	logit(LOG_ERR, 0, "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;

	memset (&ifr, 0, sizeof (ifr));

#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 IP.
	 */
	if (ifrp->ifr_addr.sa_family != AF_INET) {
	    total_interfaces++;  /* Eventually may have IP address later */
	    continue;
	}

	addr = ((struct sockaddr_in *)&ifrp->ifr_addr)->sin_addr.s_addr;

	/*
	 * 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));

	/*
	 * Ignore loopback interfaces and interfaces that do not
	 * support multicast.
	 */
	if (ioctl(udp_socket, SIOCGIFFLAGS, (char *)&ifr) < 0)
	    logit(LOG_ERR, errno, "Failed reading interface flags for phyint %s", ifr.ifr_name);

	flags = ifr.ifr_flags;
	if ((flags & (IFF_LOOPBACK | IFF_MULTICAST)) != IFF_MULTICAST)
	    continue;

	/*
	 * Everyone below is a potential vif interface.
	 * We don't care if it has wrong configuration or not configured
	 * at all.
	 */
	total_interfaces++;

	/*
	 * Ignore any interface whose address and mask do not define a
	 * valid subnet number, or whose address is of the form
	 * {subnet,0} or {subnet,-1}.
	 */
	if (ioctl(udp_socket, SIOCGIFNETMASK, (char *)&ifr) < 0) {
	    if (!(flags & IFF_POINTOPOINT))
		logit(LOG_ERR, errno, "Failed reading interface netmask for phyint %s", ifr.ifr_name);

	    mask = 0xffffffff;
	} else {
	    mask = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
	}

	subnet = addr & mask;
	if ((!inet_valid_subnet(subnet, mask)) || (addr == subnet) || addr == (subnet | ~mask)) {
	    if (!(inet_valid_host(addr) && ((mask == htonl(0xfffffffe)) || (flags & IFF_POINTOPOINT)))) {
		logit(LOG_WARNING, 0, "Ignoring %s, has invalid address %s and/or netmask %s",
		      ifr.ifr_name, inet_fmt(addr, s1, sizeof(s1)), inet_fmt(mask, s2, sizeof(s2)));
		continue;
	    }
	}

	/*
	 * Ignore any interface that is connected to the same subnet as
	 * one already installed in the uvifs array.
	 */
	/*
	 * TODO: XXX: bug or "feature" is to allow only one interface per
	 * subnet?
	 */
	for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
	    if (strcmp(v->uv_name, ifr.ifr_name) == 0) {
		logit(LOG_DEBUG, 0, "Ignoring %s (%s on subnet %s) (alias for vif#%u?)",
		      v->uv_name, inet_fmt(addr, s1, sizeof(s1)), netname(subnet, mask), vifi);
		break;
	    }
	    /* we don't care about point-to-point links in same subnet */
	    if (flags & IFF_POINTOPOINT)
		continue;
	    if (v->uv_flags & VIFF_POINT_TO_POINT)
		continue;
#if 0
	    /*
	     * TODO: to allow different interfaces belong to
	     * overlapping subnet addresses, use this version instead
	     */
	    if (((addr & mask ) == v->uv_subnet) && (v->uv_subnetmask == mask)) {
		logit(LOG_WARNING, 0, "Ignoring %s, same subnet as %s", ifr.ifr_name, v->uv_name);
		break;
	    }
#else
	    if ((addr & v->uv_subnetmask) == v->uv_subnet || (v->uv_subnet & mask) == subnet) {
		logit(LOG_WARNING, 0, "Ignoring %s, same subnet as %s", ifr.ifr_name, v->uv_name);
		break;
	    }
#endif /* 0 */
	}
	if (vifi != numvifs)
	    continue;

	/*
	 * If there is room in the uvifs array, install this interface.
	 */
	if (numvifs == MAXVIFS) {
	    logit(LOG_WARNING, 0, "Too many vifs, ignoring %s", ifr.ifr_name);
	    continue;
	}
	v = &uvifs[numvifs];
	zero_vif(v, FALSE);
	v->uv_lcl_addr		= addr;
	v->uv_subnet		= subnet;
	v->uv_subnetmask	= mask;
	if (mask != htonl(0xfffffffe))
		v->uv_subnetbcast = subnet | ~mask;
	else
		v->uv_subnetbcast = 0xffffffff;

	strlcpy(v->uv_name, ifr.ifr_name, IFNAMSIZ);

	/*
	 * Figure out MTU of interface, needed as a seed value when
	 * fragmenting PIM register messages.  We should really do
	 * a PMTU check on initial PIM register send to a new RP...
	 */
	if (ioctl(udp_socket, SIOCGIFMTU, &ifr) < 0)
	    v->uv_mtu = 1500;
	else
	    v->uv_mtu = ifr.ifr_mtu;

	if (flags & IFF_POINTOPOINT) {
	    v->uv_flags |= (VIFF_REXMIT_PRUNES | VIFF_POINT_TO_POINT);
	    if (ioctl(udp_socket, SIOCGIFDSTADDR, (char *)&ifr) < 0)
		logit(LOG_ERR, errno, "Failed reading point-to-point address for %s", v->uv_name);
	    else
		v->uv_rmt_addr = ((struct sockaddr_in *)(&ifr.ifr_dstaddr))->sin_addr.s_addr;
	} else if (mask == htonl(0xfffffffe)) {
	    /*
	     * Handle RFC 3021 /31 netmasks as point-to-point links
	     */
	    v->uv_flags |= (VIFF_REXMIT_PRUNES | VIFF_POINT_TO_POINT);
	    if (addr == subnet)
		v->uv_rmt_addr = addr + htonl(1);
	    else
		v->uv_rmt_addr = subnet;
	}
#ifdef __linux__
	{
	    struct ifreq ifridx;

	    memset(&ifridx, 0, sizeof(ifridx));
	    strlcpy(ifridx.ifr_name,v->uv_name, IFNAMSIZ);
	    if (ioctl(udp_socket, SIOGIFINDEX, (char *) &ifridx) < 0)
		logit(LOG_ERR, errno, "Failed reading interface index for %s", ifridx.ifr_name);
	    v->uv_ifindex = ifridx.ifr_ifindex;
	}
	if (v->uv_flags & VIFF_POINT_TO_POINT) {
	    logit(LOG_INFO, 0, "Installing %s (%s -> %s) as vif #%u-%d - rate %d",
		  v->uv_name, inet_fmt(addr, s1, sizeof(s1)), inet_fmt(v->uv_rmt_addr, s2, sizeof(s2)),
		  numvifs, v->uv_ifindex, v->uv_rate_limit);
	} else {
	    logit(LOG_INFO, 0, "Installing %s (%s on subnet %s) as vif #%u-%d - rate %d",
		  v->uv_name, inet_fmt(addr, s1, sizeof(s1)), netname(subnet, mask),
		  numvifs, v->uv_ifindex, v->uv_rate_limit);
	}
#else /* !__linux__ */
	if (v->uv_flags & VIFF_POINT_TO_POINT) {
	    logit(LOG_INFO, 0, "Installing %s (%s -> %s) as vif #%u - rate=%d",
		  v->uv_name, inet_fmt(addr, s1, sizeof(s1)), inet_fmt(v->uv_rmt_addr, s2, sizeof(s2)),
		  numvifs, v->uv_rate_limit);
	} else {
	    logit(LOG_INFO, 0, "Installing %s (%s on subnet %s) as vif #%u - rate %d",
		  v->uv_name, inet_fmt(addr, s1, sizeof(s1)), netname(subnet, mask),
		  numvifs, v->uv_rate_limit);
	}
#endif /* __linux__ */

	++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;
	}
    }
}
예제 #6
0
파일: config.c 프로젝트: pickup09/pimd
/**
 * parse_candidateRP - Parse candidate Rendez-Vous Point information.
 * @s: String token
 *
 * Syntax:
 * cand_rp [address | ifname] [priority <0-255>] [time <10-16383>]
 *
 * Returns:
 * %TRUE if the parsing was successful, o.w. %FALSE
 */
int parse_candidateRP(char *s)
{
    u_int time = PIM_DEFAULT_CAND_RP_ADV_PERIOD;
    u_int priority = PIM_DEFAULT_CAND_RP_PRIORITY;
    char *w;
    uint32_t local = INADDR_ANY_N;

    cand_rp_flag = FALSE;
    my_cand_rp_adv_period = PIM_DEFAULT_CAND_RP_ADV_PERIOD;
    while (!EQUAL((w = next_word(&s)), "")) {
	if (EQUAL(w, "priority")) {
	    if (EQUAL((w = next_word(&s)), "")) {
		WARN("Missing priority, defaulting to %u", w, PIM_DEFAULT_CAND_RP_PRIORITY);
		priority = PIM_DEFAULT_CAND_RP_PRIORITY;
		continue;
	    }

	    if (sscanf(w, "%u", &priority) != 1) {
		WARN("Invalid priority %s, defaulting to %u", w, PIM_DEFAULT_CAND_RP_PRIORITY);
		priority = PIM_DEFAULT_CAND_RP_PRIORITY;
	    }

	    if (priority > PIM_MAX_CAND_RP_PRIORITY) {
		WARN("Too high Cand-RP priority %u, defaulting to %d", priority, PIM_MAX_CAND_RP_PRIORITY);
		priority = PIM_MAX_CAND_RP_PRIORITY;
	    }

	    continue;
	}

	if (EQUAL(w, "time")) {
	    if (EQUAL((w = next_word(&s)), "")) {
		WARN("Missing Cand-RP announce interval, defaulting to %u", PIM_DEFAULT_CAND_RP_ADV_PERIOD);
		time = PIM_DEFAULT_CAND_RP_ADV_PERIOD;
		continue;
	    }

	    if (sscanf(w, "%u", &time) != 1) {
		WARN("Invalid Cand-RP announce interval, defaulting to %u", PIM_DEFAULT_CAND_RP_ADV_PERIOD);
		time = PIM_DEFAULT_CAND_RP_ADV_PERIOD;
		continue;
	    }

	    if (time < PIM_MIN_CAND_RP_ADV_PERIOD)
		time = PIM_MIN_CAND_RP_ADV_PERIOD;

	    if (time > PIM_MAX_CAND_RP_ADV_PERIOD)
		time = PIM_MAX_CAND_RP_ADV_PERIOD;

	    my_cand_rp_adv_period = time;
	    continue;
	}

	/* Cand-RP interface or address */
	local = ifname2addr(w);
	if (!local)
	    local = inet_parse(w, 4);

	if (!inet_valid_host(local)) {
	    local = max_local_address();
	    WARN("Invalid Cand-RP address '%s', defaulting to %s", w, inet_fmt(local, s1, sizeof(s1)));
	} else if (local_address(local) == NO_VIF) {
	    local = max_local_address();
	    WARN("Cand-RP address '%s' is not local, defaulting to %s", w, inet_fmt(local, s1, sizeof(s1)));
	}
    }

    if (local == INADDR_ANY_N) {
	/* If address not provided, use the max. local */
	local = max_local_address();
    }

    my_cand_rp_address = local;
    my_cand_rp_priority = priority;
    my_cand_rp_adv_period = time;
    cand_rp_flag = TRUE;

    logit(LOG_INFO, 0, "Local Cand-RP address %s, priority %u, interval %u sec",
	  inet_fmt(local, s1, sizeof(s1)), priority, time);

    return TRUE;
}
예제 #7
0
파일: config.c 프로젝트: pickup09/pimd
/**
 * parse_phyint - Parse physical interface configuration, if any.
 * @s: String token
 *
 * Syntax:
 * phyint <local-addr | ifname> [disable|enable]
 *                              [threshold <t>] [preference <p>] [metric <m>]
 *                              [altnet <net-addr>/<masklen>]
 *                              [altnet <net-addr> masklen <masklen>]
 *                              [scoped <net-addr>/<masklen>]
 *                              [scoped <net-addr> masklen <masklen>]
 *
 * Returns:
 * %TRUE if the parsing was successful, o.w. %FALSE
 */
static int parse_phyint(char *s)
{
    char *w, c;
    uint32_t local, altnet_addr, scoped_addr;
    vifi_t vifi;
    struct uvif *v;
    u_int n, altnet_masklen = 0, scoped_masklen = 0;
    struct phaddr *ph;
    struct vif_acl *v_acl;

    if (EQUAL((w = next_word(&s)), "")) {
	WARN("Missing phyint address");
	return FALSE;
    }

    local = ifname2addr(w);
    if (!local) {
	local = inet_parse(w, 4);
	if (!inet_valid_host(local)) {
	    WARN("Invalid phyint address '%s'", w);
	    return FALSE;
	}
    }

    for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
	if (vifi == numvifs) {
	    WARN("phyint %s is not a valid interface", inet_fmt(local, s1, sizeof(s1)));
	    return FALSE;
	}

	if (local != v->uv_lcl_addr)
	    continue;

	while (!EQUAL((w = next_word(&s)), "")) {
	    if (EQUAL(w, "disable")) {
		v->uv_flags |= VIFF_DISABLED;
		continue;
	    }

	    if (EQUAL(w, "enable")) {
		v->uv_flags &= ~VIFF_DISABLED;
		continue;
	    }

	    if (EQUAL(w, "altnet")) {
		if (EQUAL((w = next_word(&s)), "")) {
		    WARN("Missing ALTNET for phyint %s", inet_fmt(local, s1, sizeof(s1)));
		    continue;
		}

		parse_prefix_len (w, &altnet_masklen);

		altnet_addr = ifname2addr(w);
		if (!altnet_addr) {
		    altnet_addr = inet_parse(w, 4);
		    if (!inet_valid_host(altnet_addr)) {
			WARN("Invalid altnet address '%s'", w);
			return FALSE;
		    }
		}

		if (EQUAL((w = next_word(&s)), "masklen")) {
		    if (EQUAL((w = next_word(&s)), "")) {
			WARN("Missing ALTNET masklen for phyint %s", inet_fmt(local, s1, sizeof (s1)));
			continue;
		    }

		    if (!sscanf(w, "%u", &altnet_masklen)) {
			WARN("Invalid altnet masklen '%s' for phyint %s", w, inet_fmt(local, s1, sizeof(s1)));
			continue;
		    }
		}

		ph = (struct phaddr *)calloc(1, sizeof(struct phaddr));
		if (!ph)
		    return FALSE;

		if (altnet_masklen) {
		    VAL_TO_MASK(ph->pa_subnetmask, altnet_masklen);
		} else {
		    ph->pa_subnetmask = v->uv_subnetmask;
		}

		ph->pa_subnet = altnet_addr & ph->pa_subnetmask;
		ph->pa_subnetbcast = ph->pa_subnet | ~ph->pa_subnetmask;
		if (altnet_addr & ~ph->pa_subnetmask)
		    WARN("Extra subnet %s/%d has host bits set", inet_fmt(altnet_addr, s1, sizeof(s1)), altnet_masklen);

		ph->pa_next = v->uv_addrs;
		v->uv_addrs = ph;
		logit(LOG_DEBUG, 0, "ALTNET: %s/%d", inet_fmt(altnet_addr, s1, sizeof(s1)), altnet_masklen);
	    } /* altnet */

	    /* scoped mcast groups/masklen */
	    if (EQUAL(w, "scoped")) {
		if (EQUAL((w = next_word(&s)), "")) {
		    WARN("Missing SCOPED for phyint %s", inet_fmt(local, s1, sizeof(s1)));
		    continue;
		}

		parse_prefix_len (w, &scoped_masklen);

		scoped_addr = ifname2addr(w);
		if (!scoped_addr) {
		    scoped_addr = inet_parse(w, 4);
		    if (!IN_MULTICAST(ntohl(scoped_addr))) {
			WARN("Invalid scoped address '%s'", w);
			return FALSE;
		    }
		}

		if (EQUAL((w = next_word(&s)), "masklen")) {
		    if (EQUAL((w = next_word(&s)), "")) {
			WARN("Missing SCOPED masklen for phyint %s", inet_fmt(local, s1, sizeof(s1)));
			continue;
		    }
		    if (sscanf(w, "%u", &scoped_masklen) != 1) {
			WARN("Invalid scoped masklen '%s' for phyint %s", w, inet_fmt(local, s1, sizeof(s1)));
			continue;
		    }
		}

		v_acl = (struct vif_acl *)calloc(1, sizeof(struct vif_acl));
		if (!v_acl)
		    return FALSE;

		VAL_TO_MASK(v_acl->acl_mask, scoped_masklen);
		v_acl->acl_addr = scoped_addr & v_acl->acl_mask;
		if (scoped_addr & ~v_acl->acl_mask)
		    WARN("Boundary spec %s/%d has host bits set", inet_fmt(scoped_addr, s1, sizeof(s1)),scoped_masklen);

		v_acl->acl_next = v->uv_acl;
		v->uv_acl = v_acl;
		logit(LOG_DEBUG, 0, "SCOPED %s/%x", inet_fmt(v_acl->acl_addr, s1, sizeof(s1)), v_acl->acl_mask);
	    } /* scoped */

	    if (EQUAL(w, "threshold")) {
		if (EQUAL((w = next_word(&s)), "")) {
		    WARN("Missing threshold for phyint %s", inet_fmt(local, s1, sizeof(s1)));
		    continue;
		}

		if (sscanf(w, "%u%c", &n, &c) != 1 || n < 1 || n > 255 ) {
		    WARN("Invalid threshold '%s' for phyint %s", w, inet_fmt(local, s1, sizeof(s1)));
		    continue;
		}

		v->uv_threshold = n;
		continue;
	    } /* threshold */

	    if (EQUAL(w, "preference")) {
		if (EQUAL((w = next_word(&s)), "")) {
		    WARN("Missing preference for phyint %s", inet_fmt(local, s1, sizeof(s1)));
		    continue;
		}

		if (sscanf(w, "%u%c", &n, &c) != 1 || n < 1 || n > 255 ) {
		    WARN("Invalid preference '%s' for phyint %s", w, inet_fmt(local, s1, sizeof(s1)));
		    continue;
		}

		IF_DEBUG(DEBUG_ASSERT) {
		    logit(LOG_DEBUG, 0, "Config setting default local preference on %s to %d", inet_fmt(local, s1, sizeof(s1)), n);
		}

		v->uv_local_pref = n;
		continue;
	    }
	    if (EQUAL(w, "metric")) {
		if (EQUAL((w = next_word(&s)), "")) {
		    WARN("Missing metric for phyint %s", inet_fmt(local, s1, sizeof(s1)));
		    continue;
		}

		if (sscanf(w, "%u%c", &n, &c) != 1 || n < 1 || n > 1024 ) {
		    WARN("Invalid metric '%s' for phyint %s", w, inet_fmt(local, s1, sizeof(s1)));
		    continue;
		}

		IF_DEBUG(DEBUG_ASSERT) {
		    logit(LOG_DEBUG, 0, "Setting default local metric on %s to %d", inet_fmt(local, s1, sizeof(s1)), n);
		}

		v->uv_local_metric = n;
		continue;
	    }
	} /* if not empty */

	break;
    }

    return TRUE;
}
예제 #8
0
파일: config.c 프로젝트: F0rth/pimd
/*
 * function name: parse_candidateRP
 * input: char *s
 * output: int (TRUE if the parsing was successful, o.w. FALSE)
 * operation: parses the candidate RP information.
 *	The general form is:
 *      'cand_rp <local-addr> [priority <number>] [time <number>]'.
 */
int parse_candidateRP(char *s)
{
    u_int time = PIM_DEFAULT_CAND_RP_ADV_PERIOD;
    u_int priority = PIM_DEFAULT_CAND_RP_PRIORITY;
    char *w;
    u_int32 local = INADDR_ANY_N;

    cand_rp_flag = FALSE;
    my_cand_rp_adv_period = PIM_DEFAULT_CAND_RP_ADV_PERIOD;
    while (!EQUAL((w = next_word(&s)), "")) {
        if (EQUAL(w, "priority")) {
            if (EQUAL((w = next_word(&s)), "")) {
                logit(LOG_WARNING, 0,
                      "Missing priority; set to default %u (0 is highest)",
                      PIM_DEFAULT_CAND_RP_PRIORITY);
                priority = PIM_DEFAULT_CAND_RP_PRIORITY;
                continue;
            }
            if (sscanf(w, "%u", &priority) != 1) {
                logit(LOG_WARNING, 0,
                      "invalid priority %s; set to default %u (0 is highest)",
                      PIM_DEFAULT_CAND_RP_PRIORITY);
                priority = PIM_DEFAULT_CAND_RP_PRIORITY;
            }
            continue;
        }
        if (EQUAL(w, "time")) {
            if (EQUAL((w = next_word(&s)), "")) {
                logit(LOG_WARNING, 0,
                      "Missing cand_rp_adv_period value; set to default %u",
                      PIM_DEFAULT_CAND_RP_ADV_PERIOD);
                time = PIM_DEFAULT_CAND_RP_ADV_PERIOD;
                continue;
            }
            if (sscanf(w, "%u", &time) != 1) {
                logit(LOG_WARNING, 0,
                      "Invalid cand_rp_adv_period value; set to default %u",
                      PIM_DEFAULT_CAND_RP_ADV_PERIOD);
                time = PIM_DEFAULT_CAND_RP_ADV_PERIOD;
                continue;
            }
            if (time > (my_cand_rp_adv_period = ~0))
                time = my_cand_rp_adv_period;
            /* TODO: XXX: cannot be shorter than 10 seconds (not in the spec)*/
            if (time < 10)
                time = 10;
#if 0
            if (time > PIM_DEFAULT_CAND_RP_ADV_PERIOD)
                time = PIM_DEFAULT_CAND_RP_ADV_PERIOD;
#endif /* 0 */
            my_cand_rp_adv_period = time;
            continue;
        }
        /* Cand-RP address */
        local = inet_parse(w, 4);
        if (!inet_valid_host(local)) {
            local = max_local_address();
            logit(LOG_WARNING, 0,
                  "Invalid Cand-RP address provided '%s' in %s. Will use the largest enabled local address.",
                  w, configfilename);
        } else if (local_address(local) == NO_VIF) {
            local = max_local_address();
            logit(LOG_WARNING, 0, "Cand-RP address is not local '%s' in %s. Will use the largest enabled local address.",
                  w, configfilename);
        }
    }           /* while not empty */

    if (local == INADDR_ANY_N) {
        /* If address not provided, use the max. local */
        local = max_local_address();
    }

    my_cand_rp_address = local;
    my_cand_rp_priority = priority;
    my_cand_rp_adv_period = time;
    cand_rp_flag = TRUE;

    logit(LOG_INFO, 0, "Local Cand-RP address is %s", inet_fmt(local, s1, sizeof(s1)));
    logit(LOG_INFO, 0, "Local Cand-RP priority is %u", priority);
    logit(LOG_INFO, 0, "Local Cand-RP advertisement period is %u sec.", time);

    return TRUE;
}
예제 #9
0
void receive_pim_graft_ack(u_int32 src,u_int32 dst,char *data,int length)
{//
	vifi_t vif;
	char *mydata;
	struct pim_join_prune_header *graft_header;
	struct pim_join_prune_group *graft_group_header;
	u_int32 unicast_address;
	struct encode_group_address group_address;
	struct encode_source_address *source_address;
	int num_groups;
	int join_number;
	int i,j;
	struct mrt *mymrt;

	vif=find_vif_direct(src);
	if(vif==0)
	{
		return;
	}
	if(valid_packet(src,data,length)==0)
	{
		return;
	}
	mydata=data+sizeof(struct pim)+sizeof(struct encode_unicast_option);
	graft_header=(struct pim_join_prune_header *)mydata;
	unicast_address=graft_header->upstream;
	num_groups=graft_header->num_groups;
	if(num_groups==0)
	{
		return;
	}

	mydata=mydata+sizeof(struct pim_join_prune_header);
	for(i=0;i<num_groups;i++)
	{
		graft_group_header=(struct pim_join_prune_group *)mydata;
		mydata=mydata+sizeof(struct pim_join_prune_group);
		group_address=graft_group_header->group_address;
		join_number=graft_group_header->join_number;
		if(!IN_MULTICAST(ntohl(group_address.group_address)))
		{
			mydata=mydata+(join_number)*sizeof(struct encode_source_address);
			continue;
		}
		for(j=0;j<join_number;j++)
		{
			source_address=(struct encode_source_address *)mydata;
			if(!inet_valid_host(source_address->source_address))
			{
				mydata=mydata+sizeof(struct encode_source_address);
				continue;
			}
			mymrt=find_sg(source_address->source_address,group_address.group_address);
			if(mymrt==NULL)
			{//没有该组播路由表项,则不处理
				mydata=mydata+sizeof(struct encode_source_address);
				continue;
			}
			if(mymrt->graft_timer_id!=0)
			{
				log(LOG_INFO,"Receive PIM Graft ack from %s to %s,Graft success",inet_fmt(src,s1),inet_fmt(src,s2));
				timer_clearTimer(mymrt->graft_timer_id);
				mymrt->graft_timer_id=0;
			}
		}
	}
}
예제 #10
0
void receive_pim_graft(u_int32 src,u_int32 dst,char *data,int length)
{//
	u_int32 unicast_address;
	struct encode_group_address group_address;
	struct encode_source_address *source_address;
	vifi_t vif;
	struct pim_neighbor neighbor;
	struct pim_join_prune_header *graft_header;
	struct pim_join_prune_group *graft_group_header;
	int i,j;
	int join_number;
	char *mydata,*temp;
	int num_groups;
	struct mrt *mymrt;

	temp=data;

	vif=find_vif_direct(src);
	if(vif==0)
	{
		return;
	}
	if(valid_packet(src,data,length)==0)
	{
		return;
	}
	mydata=data+sizeof(struct pim)+sizeof(struct encode_unicast_option);
	graft_header=(struct pim_join_prune_header *)mydata;
	unicast_address=graft_header->upstream;
	num_groups=graft_header->num_groups;
	if(num_groups==0)
	{
		return;
	}

	mydata=mydata+sizeof(struct pim_join_prune_header);
	for(i=0;i<num_groups;i++)
	{
		graft_group_header=(struct pim_join_prune_group *)mydata;
		mydata=mydata+sizeof(struct pim_join_prune_group);
		group_address=graft_group_header->group_address;
		join_number=ntohs(graft_group_header->join_number);
		if(!IN_MULTICAST(ntohl(group_address.group_address)))
		{
			mydata=mydata+(join_number)*sizeof(struct encode_source_address);
			continue;
		}
		for(j=0;j<join_number;j++)
		{
			source_address=(struct encode_source_address *)mydata;
			if(!inet_valid_host(source_address->source_address))
			{
				mydata=mydata+sizeof(struct encode_source_address);
				continue;
			}
			log(LOG_INFO,"Receive Graft form %s for group %s,Forwarding data in this interface",inet_fmt(source_address->source_address,s1),inet_fmt(group_address.group_address,s2));
			bcopy(temp,pim_send_buf+sizeof(struct ip),length);
			pimdm_output(pim_send_buf,myvifs[vif].address,src,PIM_GRAFT_ACK,length-sizeof(struct pim));
			mymrt=find_sg(source_address->source_address,group_address.group_address);
			if(mymrt==NULL)
			{//没有该组播路由表项,则不处理
				mydata=mydata+sizeof(struct encode_source_address);				
				continue;
			}
			
			if(mymrt->prune_delay_timer_id[vif]!=0)
			{
				timer_clearTimer(mymrt->prune_delay_timer_id[vif]);
				mymrt->prune_delay_timer_id[vif]=0;
			}
			if(mymrt->outvif[vif]==0)
			{
				mymrt->outvif[vif]=1;
				change_mfc(igmpsocket,mymrt->source,mymrt->group,mymrt->incoming);
				//bcopy(data,pim_send_buf+sizeof(struct ip),length);
			}
			//pimdm_output(pim_send_buf,myvifs[vif].address,src,PIM_GRAFT_ACK,length-sizeof(struct pim));
		}
		mydata=mydata+sizeof(struct encode_source_address);
	}
}
예제 #11
0
void receive_join_prune(u_int32 src,u_int32 dst,char *data,int length)
{//收到join或prune
	int unicast_address;
	struct encode_group_address group_address;
	struct encode_source_address *source_address;
	vifi_t vif;
	struct pim_neighbor neighbor;
	struct pim_join_prune_header *jp_header;
	struct pim_join_prune_group *jp_group_header;
	struct mrt *mymrt;
	char *mydata;
	int num_groups;
	int holdtime;
	int join_number;
	int prune_number;
	int i,j,k;

	vif=find_vif_direct(src);
	if(vif==0)
	{
		return;
	}
	if(valid_packet(src,data,length)==0)
	{
		return;
	}
	mydata=data+sizeof(struct pim)+sizeof(struct encode_unicast_option);
	jp_header=(struct pim_join_prune_header *)mydata;
	unicast_address=jp_header->upstream;
	num_groups=jp_header->num_groups;
	holdtime=jp_header->holdtime;
	if(num_groups==0)
	{
		return;
	}

	log(LOG_INFO,"Receive PIM Join/Prune from %s to %s",inet_fmt(src,s1),inet_fmt(dst,s2));
	mydata=mydata+sizeof(struct pim_join_prune_header);
	log(LOG_INFO,"Receive Upstream interface:%s",inet_fmt(unicast_address,s1));
	if((unicast_address!=myvifs[vif].address)&&(unicast_address!=INADDR_ANY_N))
	{
		//我不是这条消息的接收者
		//如果是join,如果此时我有延迟发送join消息的计划,则取消发送join的计划
		//如果是prune,此时我还要接收的话,延迟一段时间后发送join消息
		if(findneighbor(unicast_address,vif)==NULL)
		{//看接收方是不是我的PIM邻居
			return;
		}log(LOG_INFO,"Num of groups:%d",num_groups);
		for(i=0;i<num_groups;i++)
		{
			jp_group_header=(struct pim_join_prune_group *)mydata;
			mydata=mydata+sizeof(struct pim_join_prune_group);
			group_address=jp_group_header->group_address;
			join_number=ntohs(jp_group_header->join_number);
			prune_number=ntohs(jp_group_header->prune_number);
log(LOG_INFO,"Receive Group number:%d Join number:%d Prune number:%d",inet_fmt(group_address.group_address,s1),join_number,prune_number);
			if(!IN_MULTICAST(ntohl(group_address.group_address)))
			{
				mydata=mydata+(join_number+prune_number)*sizeof(struct encode_source_address);
				continue;
			}
			for(j=0;j<join_number;j++)
			{
				source_address=(struct encode_source_address *)mydata;
log(LOG_INFO,"Receive Source_address:%s",inet_fmt(source_address->source_address,s1));
				if(!inet_valid_host(source_address->source_address))
				{
					mydata=mydata+sizeof(struct encode_source_address);
					continue;
				}
				mymrt=find_sg(source_address->source_address,group_address.group_address);
				if(mymrt==NULL)
				{//没有该组播路由表项,则不处理
					mydata=mydata+sizeof(struct encode_source_address);
					continue;
				}
				if(mymrt->join_delay_timer_id!=0)
				{//如果有join延迟的话,取消置为0即可
					log(LOG_INFO,"Join form %s for %s,Canceling delay join",inet_fmt(source_address->source_address,s1),inet_fmt(group_address.group_address,s2));
					timer_clearTimer(mymrt->join_delay_timer_id);
					mymrt->join_delay_timer_id=0;
				}
				mydata=mydata+(join_number+prune_number)*sizeof(struct encode_source_address);
			}
			for(k=0;k<prune_number;k++)
			{
				source_address=(struct encode_source_address *)mydata;
log(LOG_INFO,"Receive Source_address:%s",inet_fmt(source_address->source_address,s1));
				if(!inet_valid_host(source_address->source_address))
				{
					mydata=mydata+sizeof(struct encode_source_address);
					continue;
				}
				mymrt=find_sg(source_address->source_address,group_address.group_address);
				if(mymrt==NULL)
				{//路由表是空的情况下,不处理
					mydata=mydata+sizeof(struct encode_source_address);
					continue;
				}
				if(mymrt->outnumber!=0)
				{
					if(mymrt->upstream!=mymrt->source)
					{
						log(LOG_INFO,"We are receiving Src %s Group %s,Scheduling and send Join",inet_fmt(source_address->source_address,s1),inet_fmt(group_address.group_address,s2));
						schedule_join(mymrt,unicast_address);
					}
					mydata=mydata+sizeof(struct encode_source_address);
					continue;
				}
				mydata=mydata+(join_number+prune_number)*sizeof(struct encode_source_address);
			}
		}
		return;
	}
	else
	{//我是Join/Prune报文的接收方
		//收到Join报文,取消我的延迟剪枝计时器
		//收到Prune报文,回送Prune报文,启动计时器,超时后剪枝
log(LOG_INFO,"Num of groups:%d",num_groups);
		for(i=0;i<num_groups;i++)
		{
			jp_group_header=(struct pim_join_prune_group *)mydata;
			mydata=mydata+sizeof(struct pim_join_prune_group);
			group_address=jp_group_header->group_address;
			join_number=ntohs(jp_group_header->join_number);
			prune_number=ntohs(jp_group_header->prune_number);
log(LOG_INFO,"Receive Group address:%s Join number:%d Prune number:%d",inet_fmt(group_address.group_address,s1),join_number,prune_number);
			if(!IN_MULTICAST(ntohl(group_address.group_address)))
			{
				mydata=mydata+(join_number+prune_number)*sizeof(struct encode_source_address);
				continue;
			}
			for(j=0;j<join_number;j++)
			{
				source_address=(struct encode_source_address *)mydata;
log(LOG_INFO,"Join Message,Receive Source_address:%s",inet_fmt(source_address->source_address,s1));
				if(!inet_valid_host(source_address->source_address))
				{
					mydata=mydata+sizeof(struct encode_source_address);
					continue;
				}
				mymrt=find_sg(source_address->source_address,group_address.group_address);
				if(mymrt==NULL)
				{//没有该组播路由表项,则不处理
					mydata=mydata+sizeof(struct encode_source_address);
					continue;
				}
				if(mymrt->prune_delay_timer_id[vif]!=0)
				{//如果有join延迟的话,取消置为0即可
					log(LOG_INFO,"Join form %s for %s,Canceling delay prune",inet_fmt(source_address->source_address,s1),inet_fmt(group_address.group_address,s2));
					timer_clearTimer(mymrt->prune_delay_timer_id[vif]);
					mymrt->prune_delay_timer_id[vif]=0;
				}
				mydata=mydata+(join_number+prune_number)*sizeof(struct encode_source_address);
			}
			for(k=0;k<prune_number;k++)
			{
				source_address=(struct encode_source_address *)mydata;
log(LOG_INFO,"Prune message,Receive Source_address:%s",inet_fmt(source_address->source_address,s1));
				if(!inet_valid_host(source_address->source_address))
				{
					mydata=mydata+sizeof(struct encode_source_address);
					continue;
				}
				mymrt=find_sg(source_address->source_address,group_address.group_address);
				if(mymrt==NULL)
				{//路由表是空的情况下,不处理
					mydata=mydata+sizeof(struct encode_source_address);
					continue;
				}
				if(mymrt->upstream!=mymrt->source)
				{
					log(LOG_INFO,"We are receiving Src %s Group %s,Scheduling and echo Prune",inet_fmt(source_address->source_address,s1),inet_fmt(group_address.group_address,s2));
					bcopy(data,pim_send_buf+sizeof(struct ip),length);
					if(pimdm_output(pim_send_buf,myvifs[vif].address,allpimrouters,PIM_JOIN_PRUNE,length-sizeof(struct pim))!=1)
					{
						log(LOG_INFO,"Echo Prune Packet error!");
					}
					schedule_prune(mymrt,vif,holdtime);
				}
				mydata=mydata+(join_number+prune_number)*sizeof(struct encode_source_address);
			}
		}
	}
	return;
}
예제 #12
0
파일: mrt.c 프로젝트: wgc1212/pimd
mrtentry_t *find_route(uint32_t source, uint32_t group, uint16_t flags, char create)
{
    srcentry_t *src	   = NULL;
    grpentry_t *grp	   = NULL;
    mrtentry_t *mrt	   = NULL;
    mrtentry_t *mrt_wc	   = NULL;
    mrtentry_t *mrt_pmbr   = NULL;
    mrtentry_t *mrt2	   = NULL;
    rpentry_t  *rp	   = NULL;
    rp_grp_entry_t *rp_grp = NULL;

    if (flags & (MRTF_SG | MRTF_WC)) {
	if (!IN_MULTICAST(ntohl(group))) {
	    logit(LOG_WARNING, 0, "find_route: Not a multicast group address (%s) ...",
		  inet_fmt(group, s1, sizeof(s1)));
	    return NULL;
	}
    }

    if (flags & MRTF_SG) {
	if (!inet_valid_host(source) && !IN_PIM_SSM_RANGE(group)) {
	    logit(LOG_WARNING, 0, "find_route: Not a valid host (%s) ...",
		  inet_fmt(source, s1, sizeof(s1)));
	    return NULL;
	}
    }

    if (create == DONT_CREATE) {
	if (flags & (MRTF_SG | MRTF_WC)) {
	    if (search_grplist(group, &grp) == FALSE) {
		/* Group not found. Return the (*,*,RP) entry */
		if (flags & MRTF_PMBR) {
		    rp = rp_match(group);
		    if (rp) {
			logit(LOG_DEBUG, 0 , "find_route: Group not found. Return the (*,*,RP) entry");
			return rp->mrtlink;
		    }
		}

		logit(LOG_DEBUG, 0 , "find_route: Not PMBR, return NULL");
		return NULL;
	    }

	    /* Search for the source */
	    if (flags & MRTF_SG) {
		if (search_grpmrtlink(grp, source, &mrt) == TRUE) {
		    /* Exact (S,G) entry found */
		    logit(LOG_DEBUG, 0 , "find_route: exact (S,G) entry found");
		    return mrt;
		}

		logit(LOG_DEBUG, 0 , "find_route:(S,G) entry not found");
	    }

	    /* No (S,G) entry. Return the (*,G) entry (if exist) */
	    if ((flags & MRTF_WC) && grp->grp_route) {
		logit(LOG_DEBUG, 0 , "find_route: No (S,G) entry. Return the (*,G) entry");
		return grp->grp_route;
	    }
	}

	/* Return the (*,*,RP) entry */
	if (flags & MRTF_PMBR) {
	    rp = NULL;
	    if (group != INADDR_ANY_N)
		rp = rp_match(group);
	    else if (source != INADDR_ANY_N)
		rp = rp_find(source);

	    if (rp) {
		logit(LOG_DEBUG, 0 , "find_route: Return the (*,*,RP) entry");
		return rp->mrtlink;
	    }
	}

	logit(LOG_DEBUG, 0 , "find_route: No SG|WC, return NULL");
	return NULL;
    }


    /* Creation allowed */

    if (flags & (MRTF_SG | MRTF_WC)) {
	grp = create_grpentry(group);
	if (!grp)
	    return NULL;

	if (IN_PIM_SSM_RANGE(group)) {
	    if (rp_match(group) == (rpentry_t *) NULL) {
		/* For SSM, virtual RP entry has to be created. RP is at local link 169.254.0.1
		   to be sure not to send any register messages outside, although sending them
		   has been disabled for SSM also in PIM protocol.
		   The address does not need to be really configured in any interface.
		   TODO: Avoid need for virtual RP by implementing SSM-specific state structures */
		add_rp_grp_entry(&cand_rp_list, &grp_mask_list, htonl(0xa9fe0001), 20, 90, group,
				 0xffffffff, curr_bsr_hash_mask, curr_bsr_fragment_tag);
	    }
	}

	if (!grp->active_rp_grp) {
	    rp_grp = rp_grp_match(group);
	    if (!rp_grp) {
		if (!grp->mrtlink && !grp->grp_route)
		    /* New created grpentry. Delete it. */
		    delete_grpentry(grp);

		return NULL;
	    }

	    rp = rp_grp->rp->rpentry;
	    grp->active_rp_grp = rp_grp;
	    grp->rpaddr = rp->address;

	    /* Link to the top of the rp_grp_chain */
	    grp->rpnext = rp_grp->grplink;
	    rp_grp->grplink = grp;
	    if (grp->rpnext)
		grp->rpnext->rpprev = grp;
	} else {
	    rp = grp->active_rp_grp->rp->rpentry;
	}
    }

    mrt_wc = mrt_pmbr = NULL;

    if (flags & MRTF_WC) {
	/* Setup the (*,G) routing entry */
	mrt_wc = create_mrtentry(NULL, grp, MRTF_WC);
	if (!mrt_wc) {
	    if (!grp->mrtlink)
		/* New created grpentry. Delete it. */
		delete_grpentry(grp);

	    return NULL;
	}

	if (mrt_wc->flags & MRTF_NEW) {
	    mrt_pmbr = rp->mrtlink;

	    /* Copy the oif list from the (*,*,RP) entry */
	    if (mrt_pmbr)
		VOIF_COPY(mrt_pmbr, mrt_wc);

	    mrt_wc->incoming = rp->incoming;
	    mrt_wc->upstream = rp->upstream;
	    mrt_wc->metric   = rp->metric;
	    mrt_wc->preference = rp->preference;
	    move_kernel_cache(mrt_wc, 0);
#ifdef RSRR
	    rsrr_cache_bring_up(mrt_wc);
#endif /* RSRR */
	}

	if (!(flags & MRTF_SG))
	    return mrt_wc;
    }

    if (flags & MRTF_SG) {
	/* Setup the (S,G) routing entry */
	src = create_srcentry(source);
	if (!src) {
	    /* TODO: XXX: The MRTF_NEW flag check may be misleading?? check */
	    if ((!grp->grp_route || (grp->grp_route && (grp->grp_route->flags & MRTF_NEW)))
		&& !grp->mrtlink) {
		/* New created grpentry. Delete it. */
		delete_grpentry(grp);
	    }

	    return NULL;
	}

	mrt = create_mrtentry(src, grp, MRTF_SG);
	if (!mrt) {
	    if ((!grp->grp_route
		 || (grp->grp_route && (grp->grp_route->flags & MRTF_NEW)))
		&& !grp->mrtlink) {
		/* New created grpentry. Delete it. */
		delete_grpentry(grp);
	    }

	    if (!src->mrtlink)
		/* New created srcentry. Delete it. */
		delete_srcentry(src);

	    return NULL;
	}

	if (mrt->flags & MRTF_NEW) {
	    mrt2 = grp->grp_route;
	    if (!mrt2)
		mrt2 = rp->mrtlink;

	    /* Copy the oif list from the existing (*,G) or (*,*,RP) entry */
	    if (mrt2) {
		VOIF_COPY(mrt2, mrt);
		if (flags & MRTF_RP) {
		    /* ~(S,G) prune entry */
		    mrt->incoming    = mrt2->incoming;
		    mrt->upstream    = mrt2->upstream;
		    mrt->metric      = mrt2->metric;
		    mrt->preference  = mrt2->preference;
		    mrt->flags      |= MRTF_RP;
		}
	    }

	    if (!(mrt->flags & MRTF_RP)) {
		mrt->incoming   = src->incoming;
		mrt->upstream   = src->upstream;
		mrt->metric     = src->metric;
		mrt->preference = src->preference;
	    }
	    move_kernel_cache(mrt, 0);
#ifdef RSRR
	    rsrr_cache_bring_up(mrt);
#endif /* RSRR */
	}

	return mrt;
    }

    if (flags & MRTF_PMBR) {
	/* Get/return the (*,*,RP) routing entry */
	if (group != INADDR_ANY_N)
	    rp = rp_match(group);
	else if (source != INADDR_ANY_N)
	    rp = rp_find(source);
	else
	    return NULL; /* source == group == INADDR_ANY */

	if (!rp)
	    return NULL;

	if (rp->mrtlink)
	    return rp->mrtlink;

	mrt = create_mrtentry(rp, NULL, MRTF_PMBR);
	if (!mrt)
	    return NULL;

	mrt->incoming   = rp->incoming;
	mrt->upstream   = rp->upstream;
	mrt->metric     = rp->metric;
	mrt->preference = rp->preference;

	return mrt;
    }

    return NULL;
}