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