Esempio n. 1
0
/*
 * Verify that the lifetimes and onlink/auto flags are consistent
 * with our settings.
 */
static void
verify_prefix_opt(struct phyint *pi, uchar_t *opt, char *frombuf)
{
	struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt;
	int plen;
	struct adv_prefix *adv_pr;
	uint32_t validtime, preftime;
	char prefixbuf[INET6_ADDRSTRLEN];
	int pktflag, myflag;

	if (8 * po->nd_opt_pi_len != sizeof (*po)) {
		logmsg(LOG_INFO, "RA prefix option from %s on %s wrong size "
		    "(%d bytes)\n",
		    frombuf, pi->pi_name,
		    8 * (int)po->nd_opt_pi_len);
		return;
	}
	if (IN6_IS_ADDR_LINKLOCAL(&po->nd_opt_pi_prefix)) {
		logmsg(LOG_INFO, "RA from %s on %s contains link-local "
		    "prefix - ignored\n",
		    frombuf, pi->pi_name);
		return;
	}
	plen = po->nd_opt_pi_prefix_len;
	adv_pr = adv_prefix_lookup(pi, po->nd_opt_pi_prefix, plen);
	if (adv_pr == NULL)
		return;

	/* Ignore prefixes which we do not advertise */
	if (!adv_pr->adv_pr_AdvAutonomousFlag && !adv_pr->adv_pr_AdvOnLinkFlag)
		return;
	(void) inet_ntop(AF_INET6, (void *)&adv_pr->adv_pr_prefix,
	    prefixbuf, sizeof (prefixbuf));
	pktflag = ((po->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO) != 0);
	myflag = (adv_pr->adv_pr_AdvAutonomousFlag != 0);
	if (pktflag != myflag) {
		logmsg(LOG_INFO,
		    "RA from %s on %s inconsistent autonomous flag for \n\t"
		    "prefix %s/%u: received %s configuration %s\n",
		    frombuf, pi->pi_name, prefixbuf, adv_pr->adv_pr_prefix_len,
		    (pktflag ? "ON" : "OFF"),
		    (myflag ? "ON" : "OFF"));
	}

	pktflag = ((po->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK) != 0);
	myflag = (adv_pr->adv_pr_AdvOnLinkFlag != 0);
	if (pktflag != myflag) {
		logmsg(LOG_INFO, "RA from %s on %s inconsistent on link flag "
		    "for \n\tprefix %s/%u: received %s configuration %s\n",
		    frombuf, pi->pi_name, prefixbuf, adv_pr->adv_pr_prefix_len,
		    (pktflag ? "ON" : "OFF"),
		    (myflag ? "ON" : "OFF"));
	}
	validtime = ntohl(po->nd_opt_pi_valid_time);
	preftime = ntohl(po->nd_opt_pi_preferred_time);

	/*
	 * Take into account variation for lifetimes decrementing
	 * in real time. Allow +/- 10 percent and +/- 10 seconds.
	 */
#define	LOWER_LIMIT(val)	((val) - (val)/10 - 10)
#define	UPPER_LIMIT(val)	((val) + (val)/10 + 10)
	if (adv_pr->adv_pr_AdvValidRealTime) {
		if (adv_pr->adv_pr_AdvValidExpiration > 0 &&
		    (validtime <
		    LOWER_LIMIT(adv_pr->adv_pr_AdvValidExpiration) ||
		    validtime >
		    UPPER_LIMIT(adv_pr->adv_pr_AdvValidExpiration))) {
			logmsg(LOG_INFO, "RA from %s on %s inconsistent valid "
			    "lifetime for\n\tprefix %s/%u: received %d "
			    "configuration %d\n",
			    frombuf, pi->pi_name, prefixbuf,
			    adv_pr->adv_pr_prefix_len,
			    validtime, adv_pr->adv_pr_AdvValidExpiration);
		}
	} else {
		if (validtime != adv_pr->adv_pr_AdvValidLifetime) {
			logmsg(LOG_INFO, "RA from %s on %s inconsistent valid "
			    "lifetime for\n\tprefix %s/%u: received %d "
			    "configuration %d\n",
			    frombuf, pi->pi_name, prefixbuf,
			    adv_pr->adv_pr_prefix_len,
			    validtime, adv_pr->adv_pr_AdvValidLifetime);
		}
	}

	if (adv_pr->adv_pr_AdvPreferredRealTime) {
		if (adv_pr->adv_pr_AdvPreferredExpiration > 0 &&
		    (preftime <
		    LOWER_LIMIT(adv_pr->adv_pr_AdvPreferredExpiration) ||
		    preftime >
		    UPPER_LIMIT(adv_pr->adv_pr_AdvPreferredExpiration))) {
			logmsg(LOG_INFO, "RA from %s on %s inconsistent "
			    "preferred lifetime for\n\tprefix %s/%u: "
			    "received %d configuration %d\n",
			    frombuf, pi->pi_name, prefixbuf,
			    adv_pr->adv_pr_prefix_len,
			    preftime, adv_pr->adv_pr_AdvPreferredExpiration);
		}
	} else {
		if (preftime != adv_pr->adv_pr_AdvPreferredLifetime) {
			logmsg(LOG_INFO, "RA from %s on %s inconsistent "
			    "preferred lifetime for\n\tprefix %s/%u: "
			    "received %d configuration %d\n",
			    frombuf, pi->pi_name, prefixbuf,
			    adv_pr->adv_pr_prefix_len,
			    preftime, adv_pr->adv_pr_AdvPreferredLifetime);
		}
	}
}
Esempio n. 2
0
static void
parse_prefix(struct configinfo *list, char *argvec[], int argcount)
{
	char *ifname, *prefix;
	struct phyint *pi;
	struct adv_prefix *adv_pr;
	struct in6_addr in6;
	int prefixlen;
	char save[sizeof (adv_pr->adv_pr_config)];

	if (debug & D_CONFIG)
		logmsg(LOG_DEBUG, "parse_prefix: argc %d\n", argcount);

	if (argcount < 2) {
		conferr("Missing prefix and/or interface name\n");
		return;
	}
	prefix = argvec[0];
	ifname = argvec[1];
	argvec += 2;
	argcount -= 2;

	prefixlen = parse_addrprefix(prefix, &in6);
	if (prefixlen == -1) {
		conferr("Bad prefix %s\n", prefix);
		return;
	}

	pi = phyint_lookup(ifname);
	if (pi == NULL) {
		/*
		 * Create the physical interface structure.
		 * Note, phyint_create() sets the interface
		 * defaults in pi_config.
		 */
		pi = phyint_create(ifname);
		if (pi == NULL) {
			conferr("Unable to use interface %s\n", ifname);
			return;
		}
	}
	adv_pr = adv_prefix_lookup(pi, in6, prefixlen);
	if (adv_pr == NULL) {
		int i;

		adv_pr = adv_prefix_create(pi, in6, prefixlen);
		if (adv_pr == NULL) {
			conferr("Unable to create prefix %s\n", prefix);
			return;
		}
		/*
		 * Copy the defaults from the default array.
		 */
		for (i = 0; i < I_PREFIXSIZE; i++) {
			adv_pr->adv_pr_config[i].cf_value =
			    prefixdefaults[i].cf_value;
			adv_pr->adv_pr_config[i].cf_notdefault =
			    prefixdefaults[i].cf_notdefault;
		}
	}

	(void) memcpy(save, adv_pr->adv_pr_config, sizeof (save));
	while (argcount >= 2) {
		parse_var_value(CONFIG_PREFIX, list, argvec[0], argvec[1],
		    adv_pr->adv_pr_config);

		argcount -= 2;
		argvec += 2;
	}
	check_var_consistency(adv_pr->adv_pr_config, save, sizeof (save));
	if (argcount != 0)
		logmsg(LOG_ERR, "Trailing text <%s> ignored\n", argvec[0]);
}