예제 #1
0
파일: config.c 프로젝트: pickup09/pimd
/**
 * parse_rp_address - Parse rp_address config option.
 * @s: String token.
 *
 * This is an extension to the original pimd to add pimd.conf support for static
 * Rendez-Vous Point addresses.
 *
 * The function has been extended by [email protected], of Lintrack, to allow specifying
 * multicast group addresses as well.
 *
 * Syntax:
 * rp_address <ADDRESS> [<GROUP>[</LENGTH> masklen <LENGTH>]
 *
 * Returns:
 * When parsing @s is successful this function returns %TRUE, otherwise %FALSE.
 */
int parse_rp_address(char *s)
{
    char *w;
    uint32_t local = 0xffffff;
    uint32_t group_addr = htonl(INADDR_UNSPEC_GROUP);
    uint32_t masklen = PIM_GROUP_PREFIX_DEFAULT_MASKLEN;
    u_int dummy;
    struct rp_hold *rph;

    /* next is RP addr */
    w = next_word(&s);
    if (EQUAL(w, "")) {
	logit(LOG_WARNING, 0, "Missing rp_address argument");
	return FALSE;
    }

    local = inet_parse(w, 4);
    if (local == 0xffffff) {
	WARN("Invalid rp_address %s", w);
	return FALSE;
    }

    /* next is group addr if exist */
    w = next_word(&s);
    if (!EQUAL(w, "")) {
	parse_prefix_len (w, &masklen);

	group_addr = inet_parse(w, 4);
	if (!IN_MULTICAST(ntohl(group_addr))) {
	    WARN("%s is not a valid multicast address", inet_fmt(group_addr, s1, sizeof(s1)));
	    return FALSE;
	}

	/* next is prefix or priority if exist */
	while (!EQUAL((w = next_word(&s)), "")) {
	    if (EQUAL(w, "masklen")) {
		w = next_word(&s);
		if (!sscanf(w, "%u", &masklen)) {
		    WARN("Invalid masklen %s. Defaulting to %d)", w, PIM_GROUP_PREFIX_DEFAULT_MASKLEN);
		    masklen = PIM_GROUP_PREFIX_DEFAULT_MASKLEN;
		}
	    }

	    /* Unused, but keeping for backwards compatibility for people who
	     * may still have this option in their pimd.conf
	     * The priority of a static RP is hardcoded to always be 1, see Juniper's
	     * configuration or similar sources for reference. */
	    if (EQUAL(w, "priority")) {
		w = next_word(&s);
		sscanf(w, "%u", &dummy);
		WARN("The priority of static RP's is, as of pimd 2.2.0, always 1.");
	    }
	}
    } else {
	group_addr = htonl(INADDR_UNSPEC_GROUP);
	masklen = PIM_GROUP_PREFIX_MIN_MASKLEN;
    }

    validate_prefix_len(&masklen);

    rph = calloc(1, sizeof(*rph));
    if (!rph) {
	logit(LOG_WARNING, 0, "Out of memory when parsing rp-address %s",
	      inet_fmt(local, s1, sizeof(s1)));
	return FALSE;
    }

    rph->address = local;
    rph->group = group_addr;
    VAL_TO_MASK(rph->mask, masklen);

    /* attach at the beginning */
    rph->next = g_rp_hold;
    g_rp_hold = rph;

    logit(LOG_INFO, 0, "Local static RP: %s, group %s/%d",
	  inet_fmt(local, s1, sizeof(s1)), inet_fmt(group_addr, s2, sizeof(s2)), masklen);

    return TRUE;
}
예제 #2
0
파일: config.c 프로젝트: F0rth/pimd
/**
 * parse_rp_address - Parse rp_address config option.
 * @s: String token.
 *
 * This is an extension to the original pimd to add pimd.conf support for static
 * Rendez-Vous Point addresses.
 *
 * The function has been extended by [email protected], of Lintrack, to allow specifying
 * multicast group addresses as well.
 *
 * Format:
 * rp_address <rp-address>
 *
 * Returns:
 * When parsing @s is successful this function returns %TRUE, otherwise %FALSE.
 */
int parse_rp_address(char *s)
{
    char *w;
    u_int32 local = 0xffffff;
    u_int32 group_addr;
    u_int32 masklen;
    struct rp_hold * rph;

    w = next_word(&s);
    if (EQUAL(w, "")) {
        logit(LOG_WARNING, 0, "'rp_address' in %s: no <rp-addr> - ignoring", configfilename);
        return FALSE;
    }

    local = inet_parse(w, 4);
    if (local == 0xffffff) {
        logit(LOG_WARNING, 0, "'rp_address' in %s: invalid <rp-addr> provided: '%s'", configfilename, w);
        return FALSE;
    }

    w = next_word(&s);
    if (!EQUAL(w, "")) {
        group_addr = inet_parse(w, 4);
        if (!IN_MULTICAST(ntohl(group_addr))) {
            logit(LOG_WARNING, 0, "'rp_address' in %s: %s is not a multicast addr", configfilename, inet_fmt(group_addr, s1, sizeof(s1)));
            return FALSE;
        }

        if (EQUAL((w = next_word(&s)), "masklen")) {
            w = next_word(&s);
            if (sscanf(w, "%u", &masklen) == 1) {
                if (masklen > (sizeof(group_addr) * 8))
                    masklen = (sizeof(group_addr) * 8);
                else if (masklen < 4)
                    masklen = 4;
            }
            else
                masklen = PIM_GROUP_PREFIX_DEFAULT_MASKLEN;
        }
        else
            masklen = PIM_GROUP_PREFIX_DEFAULT_MASKLEN;
    }
    else {
        group_addr = htonl(224 << 24);
        masklen = 4;
    }

    /* save */
    rph = malloc(sizeof(*rph));
    rph->address = local;
    rph->group = group_addr;
    VAL_TO_MASK(rph->mask, masklen);

    /* attach at the beginning */
    rph->next = g_rp_hold;
    g_rp_hold = rph;

    logit(LOG_INFO, 0, "Added static RP: %s, group %s/%d", inet_fmt(local, s1, sizeof(s1)), inet_fmt(group_addr, s2, sizeof(s2)), masklen);

    return TRUE;
}
예제 #3
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;
}
예제 #4
0
파일: config.c 프로젝트: michfine/pimd
/**
 * parse_rp_address - Parse rp_address config option.
 * @s: String token.
 *
 * This is an extension to the original pimd to add pimd.conf support for static
 * Rendez-Vous Point addresses.
 *
 * The function has been extended by [email protected], of Lintrack, to allow specifying
 * multicast group addresses as well.
 *
 * Syntax:
 * rp_address <rp-address> [<group-addr>[/masklen>]          [priority <number>]]
 *                         [<group-addr> [masklen <masklen>] [priority <number>]]
 *
 * Returns:
 * When parsing @s is successful this function returns %TRUE, otherwise %FALSE.
 */
int parse_rp_address(char *s)
{
    char *w;
    uint32_t local = 0xffffff;
    uint32_t group_addr = htonl(INADDR_UNSPEC_GROUP);
    uint32_t masklen = PIM_GROUP_PREFIX_DEFAULT_MASKLEN;
    u_int priority = PIM_DEFAULT_CAND_RP_PRIORITY;
    struct rp_hold *rph;

    /* next is RP addr */
    w = next_word(&s);
    if (EQUAL(w, "")) {
	logit(LOG_WARNING, 0, "Missing rp_address argument");
	return FALSE;
    }

    local = inet_parse(w, 4);
    if (local == 0xffffff) {
	WARN("Invalid rp_address %s", w);
	return FALSE;
    }

    /* next is group addr if exist */
    w = next_word(&s);
    if (!EQUAL(w, "")) {
	parse_prefix_len (w, &masklen);

	group_addr = inet_parse(w, 4);
	if (!IN_MULTICAST(ntohl(group_addr))) {
	    WARN("%s is not a valid multicast address", inet_fmt(group_addr, s1, sizeof(s1)));
	    return FALSE;
	}

	/* next is prefix or priority if exist */
	while (!EQUAL((w = next_word(&s)), "")) {
	    if (EQUAL(w, "masklen")) {
		w = next_word(&s);
		if (!sscanf(w, "%u", &masklen)) {
		    WARN("Invalid masklen %s. Defaulting to %d)", w, PIM_GROUP_PREFIX_DEFAULT_MASKLEN);
		    masklen = PIM_GROUP_PREFIX_DEFAULT_MASKLEN;
		}
	    }

	    if (EQUAL(w, "priority")) {
		w = next_word(&s);
		if (sscanf(w, "%u", &priority) == 1) {
		    if (priority > PIM_MAX_CAND_RP_PRIORITY) {
			WARN("Too large priority %s. Defaulting to %d", w, PIM_MAX_CAND_RP_PRIORITY);
			priority = PIM_MAX_CAND_RP_PRIORITY;
		    }
		} else {
		    WARN("Invalid priority %s. Defaulting to %d", w, PIM_DEFAULT_CAND_RP_PRIORITY);
		    priority = PIM_DEFAULT_CAND_RP_PRIORITY;
		}
	    }
	}
    } else {
	group_addr = htonl(INADDR_UNSPEC_GROUP);
	masklen = PIM_GROUP_PREFIX_MIN_MASKLEN;
	priority = 1;
    }

    validate_prefix_len (&masklen);

    rph = calloc(1, sizeof(*rph));
    if (!rph) {
	logit(LOG_WARNING, 0, "Ran out of memory in parse_rp_address()");
	return FALSE;
    }

    rph->address = local;
    rph->group = group_addr;
    VAL_TO_MASK(rph->mask, masklen);
    rph->priority = priority;

    /* attach at the beginning */
    rph->next = g_rp_hold;
    g_rp_hold = rph;

    logit(LOG_INFO, 0, "Added static RP: %s, group %s/%d, priority %d",
	  inet_fmt(local, s1, sizeof(s1)), inet_fmt(group_addr, s2, sizeof(s2)), masklen, priority);

    return TRUE;
}