Exemple #1
0
/*
 * bestmove
 *   resign
 *   win
 *   <move1> [ponder <move2>]
 */
static int
bestmove_parse(Usimsg *msg, const char *s)
{
	const char *p;
	Token token;

	if ((p = token_get(&token, s)) == NULL)
		return -1;

	if (token_equal(&token, "resign"))
		return usimsg_pushnil(msg, USIOBJ_RESIGN);
	if (token_equal(&token, "win"))
		return usimsg_pushnil(msg, USIOBJ_WIN);

	if (usimsg_pushstr(msg, USIOBJ_MOVE, token.s, token.len) != 0)
		return -1;

	if ((p = token_get(&token, p)) == NULL)
		return 0;
	if (!token_equal(&token, "ponder"))
		return 0;
	if ((p = token_get(&token, p)) == NULL)
		return -1;
	if (usimsg_pushstr(msg, USIOBJ_MOVE, token.s, token.len) != 0)
		return -1;

	return 0;
}
Exemple #2
0
/*
 * id
 *   name <program name>
 *   author <program author>
 */
static int
id_parse(Usimsg *msg, const char *s)
{
	const char *p;
	Token token;

	if ((p = token_get(&token, s)) == NULL)
		return -1;

	if (token_equal(&token, "name"))
		return usimsg_pushstr(msg, USIOBJ_PROGNAME, p, strlen(p));

	if (token_equal(&token, "author"))
		return usimsg_pushstr(msg, USIOBJ_AUTHOR, p, strlen(p));

	return -1;
}
Exemple #3
0
/*
 * checkmate
 *   notimplemented
 *   timeout
 *   nomate
 *   <move1> ... <movei>
 */
static int
checkmate_parse(Usimsg *msg, const char *s)
{
	const char *p;
	Token token;

	if ((p = token_get(&token, s)) == NULL)
		return -1;

	if (token_equal(&token, "notimplemented"))
		return usimsg_pushnil(msg, USIOBJ_NOTIMPLEMENTED);
	if (token_equal(&token, "timeout"))
		return usimsg_pushnil(msg, USIOBJ_TIMEOUT);
	if (token_equal(&token, "nomate"))
		return usimsg_pushnil(msg, USIOBJ_NOMATE);

	return usimsg_pushstr(msg, USIOBJ_MOVE, token.s, strlen(token.s));
}
Exemple #4
0
static Tbl *
tbl_find(Tbl *root, Token *token)
{
	Tbl *e;

	for (e = root; e->name != NULL; e++)
		if (token_equal(token, e->name))
			return e;

	return NULL;
}
Exemple #5
0
boolean_t
incoming_prefix_addrconf_process(struct phyint *pi, struct prefix *pr,
    uchar_t *opt, struct sockaddr_in6 *from, boolean_t loopback,
    boolean_t new_prefix)
{
	struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt;
	char abuf[INET6_ADDRSTRLEN];
	char pbuf[INET6_ADDRSTRLEN];
	uint32_t validtime, preftime;	/* In seconds */
	uint32_t recorded_validtime;	/* In seconds */
	int plen;
	struct prefix *other_pr;

	validtime = ntohl(po->nd_opt_pi_valid_time);
	preftime = ntohl(po->nd_opt_pi_preferred_time);
	plen = po->nd_opt_pi_prefix_len;
	if (!new_prefix) {
		/*
		 * Check 2 hour rule on valid lifetime.
		 * Follows: RFC 2462
		 * If we advertised this prefix ourselves we skip
		 * these checks. They are also skipped if we did not
		 * previously do addrconf on this prefix.
		 */
		recorded_validtime = pr->pr_ValidLifetime / MILLISEC;

		if (loopback || !(pr->pr_state & PR_AUTO) ||
		    validtime >= MIN_VALID_LIFETIME ||
		    /* LINTED - statement has no consequent */
		    validtime >= recorded_validtime) {
			/* OK */
		} else if (recorded_validtime < MIN_VALID_LIFETIME &&
		    validtime < recorded_validtime) {
			/* Ignore the prefix */
			(void) inet_ntop(AF_INET6,
			    (void *)&from->sin6_addr,
			    abuf, sizeof (abuf));
			(void) inet_ntop(AF_INET6,
			    (void *)&po->nd_opt_pi_prefix,
			    pbuf, sizeof (pbuf));
			logmsg(LOG_INFO, "prefix option %s/%u from %s on %s: "
			    "too short valid lifetime %u stored %u "
			    "- ignored\n",
			    pbuf, plen, abuf, pi->pi_name,
			    validtime, recorded_validtime);
			return (_B_TRUE);
		} else {
			/*
			 * If the router clock runs slower than the
			 * host by 1 second over 2 hours then this
			 * test will set the lifetime back to 2 hours
			 * once i.e. a lifetime decrementing in
			 * realtime might cause the prefix to live an
			 * extra 2 hours on the host.
			 */
			(void) inet_ntop(AF_INET6,
			    (void *)&from->sin6_addr,
			    abuf, sizeof (abuf));
			(void) inet_ntop(AF_INET6,
			    (void *)&po->nd_opt_pi_prefix,
			    pbuf, sizeof (pbuf));
			logmsg(LOG_INFO, "prefix option %s/%u from %s on %s: "
			    "valid time %u stored %u rounded up "
			    "to %u\n",
			    pbuf, plen, abuf, pi->pi_name,
			    validtime, recorded_validtime,
			    MIN_VALID_LIFETIME);
			validtime = MIN_VALID_LIFETIME;
		}
	}

	/*
	 * For RFC3041 addresses, need to take token lifetime
	 * into account, too.
	 */
	if (pr->pr_flags & IFF_TEMPORARY) {
		uint_t	cur_tpreftime =
		    pi->pi_TmpPreferredLifetime - pi->pi_TmpDesyncFactor;

		if (new_prefix) {
			validtime = MIN(validtime, pi->pi_TmpValidLifetime);
			preftime = MIN(preftime, cur_tpreftime);
		} else {
			uint_t cur_vexp, cur_pexp, curtime;
			curtime = getcurrenttime() / MILLISEC;

			cur_vexp = pr->pr_CreateTime + pi->pi_TmpValidLifetime;
			cur_pexp = pr->pr_CreateTime + cur_tpreftime;
			if (curtime > cur_vexp)
				validtime = 0;
			else if ((curtime + validtime) > cur_vexp)
				validtime = cur_vexp - curtime;
			/*
			 * If this is an existing address which was deprecated
			 * because of a bad token, we don't want to update its
			 * preferred lifetime!
			 */
			if ((pr->pr_PreferredLifetime == 0) &&
			    !token_equal(pr->pr_address, pi->pi_tmp_token,
			    TMP_TOKEN_BITS))
				preftime = 0;
			else if (curtime > cur_pexp)
				preftime = 0;
			else if ((curtime + preftime) > cur_pexp)
				preftime = cur_pexp - curtime;
		}
		if ((preftime != 0) && (preftime <= pi->pi_TmpRegenAdvance)) {
			(void) inet_ntop(AF_INET6,
			    (void *)&from->sin6_addr,
			    abuf, sizeof (abuf));
			(void) inet_ntop(AF_INET6,
			    (void *)&po->nd_opt_pi_prefix,
			    pbuf, sizeof (pbuf));
			logmsg(LOG_WARNING, "prefix opt %s/%u from %s on %s: "
			    "preferred lifetime(%d) <= TmpRegenAdvance(%d)\n",
			    pbuf, plen, abuf, pi->pi_name, preftime,
			    pi->pi_TmpRegenAdvance);
			if (new_prefix) {
				prefix_update_ipadm_addrobj(pr, _B_FALSE);
				prefix_delete(pr);
			}
			return (_B_TRUE);
		}
	}
	if (debug & D_TMP)
		logmsg(LOG_DEBUG, "calculated lifetimes(%s, 0x%llx): v %d, "
		    "p %d\n", pr->pr_name, pr->pr_flags, validtime, preftime);

	if (!(pr->pr_state & PR_AUTO)) {
		int i, tokenlen;
		in6_addr_t *token;
		/*
		 * Form a new local address if the lengths match.
		 */
		if (pr->pr_flags & IFF_TEMPORARY) {
			if (IN6_IS_ADDR_UNSPECIFIED(&pi->pi_tmp_token)) {
				if (!tmptoken_create(pi)) {
					prefix_delete(pr);
					return (_B_TRUE);
				}
			}
			tokenlen = TMP_TOKEN_BITS;
			token = &pi->pi_tmp_token;
		} else {
			tokenlen = pi->pi_token_length;
			token = &pi->pi_token;
		}
		if (pr->pr_prefix_len + tokenlen != IPV6_ABITS) {
			(void) inet_ntop(AF_INET6,
			    (void *)&from->sin6_addr,
			    abuf, sizeof (abuf));
			(void) inet_ntop(AF_INET6,
			    (void *)&po->nd_opt_pi_prefix,
			    pbuf, sizeof (pbuf));
			logmsg(LOG_INFO, "prefix option %s/%u from %s on %s: "
			    "mismatched length %d token length %d\n",
			    pbuf, plen, abuf, pi->pi_name,
			    pr->pr_prefix_len, tokenlen);
			return (_B_TRUE);
		}
		for (i = 0; i < 16; i++) {
			/*
			 * prefix_create ensures that pr_prefix has all-zero
			 * bits after prefixlen.
			 */
			pr->pr_address.s6_addr[i] = pr->pr_prefix.s6_addr[i] |
			    token->s6_addr[i];
		}
		/*
		 * Check if any other physical interface has the same
		 * address configured already
		 */
		if ((other_pr = prefix_lookup_addr_match(pr)) != NULL) {
			/*
			 * Delete this prefix structure as kernel
			 * does not allow duplicated addresses
			 */
			logmsg(LOG_ERR, "incoming_prefix_addrconf_process: "
			    "Duplicate prefix %s received on interface %s\n",
			    inet_ntop(AF_INET6, &po->nd_opt_pi_prefix, abuf,
			    sizeof (abuf)), pi->pi_name);
			logmsg(LOG_ERR, "incoming_prefix_addrconf_process: "
			    "Prefix already exists in interface %s\n",
			    other_pr->pr_physical->pi_name);
			if (new_prefix) {
				prefix_update_ipadm_addrobj(pr, _B_FALSE);
				prefix_delete(pr);
				return (_B_FALSE);
			}
			/* Ignore for addrconf purposes */
			validtime = preftime = 0;
		}
		if ((pr->pr_flags & IFF_TEMPORARY) && new_prefix) {
			pr->pr_CreateTime = getcurrenttime() / MILLISEC;
			if (debug & D_TMP)
				logmsg(LOG_DEBUG,
				    "created tmp addr(%s v %d p %d)\n",
				    pr->pr_name, validtime, preftime);
		}
	}

	if (validtime != 0)
		pr->pr_state |= PR_AUTO;
	else
		pr->pr_state &= ~(PR_AUTO|PR_DEPRECATED);
	if (preftime != 0 || !(pr->pr_state & PR_AUTO))
		pr->pr_state &= ~PR_DEPRECATED;
	else
		pr->pr_state |= PR_DEPRECATED;

	/*
	 * Convert from seconds to milliseconds avoiding overflow.
	 * If the lifetime in the packet is e.g. PREFIX_INFINITY - 1
	 * (4 billion seconds - about 130 years) we will in fact time
	 * out the prefix after 4 billion milliseconds - 46 days).
	 * Thus the longest lifetime (apart from infinity) is 46 days.
	 * Note that this ensures that PREFIX_INFINITY still means "forever".
	 */
	if (validtime >= PREFIX_INFINITY / MILLISEC)
		pr->pr_ValidLifetime = PREFIX_INFINITY - 1;
	else
		pr->pr_ValidLifetime = validtime * MILLISEC;
	if (preftime >= PREFIX_INFINITY / MILLISEC)
		pr->pr_PreferredLifetime = PREFIX_INFINITY - 1;
	else
		pr->pr_PreferredLifetime = preftime * MILLISEC;
	pr->pr_AutonomousFlag = _B_TRUE;

	if (debug & D_PREFIX) {
		logmsg(LOG_DEBUG, "incoming_prefix_addrconf_process(%s, %s/%u) "
		    "valid %u pref %u\n",
		    pr->pr_physical->pi_name,
		    inet_ntop(AF_INET6, (void *)&pr->pr_prefix,
		    abuf, sizeof (abuf)), pr->pr_prefix_len,
		    pr->pr_ValidLifetime, pr->pr_PreferredLifetime);
	}

	if (pr->pr_state & PR_AUTO) {
		/* Take the min of the two timeouts by calling it twice */
		if (pr->pr_ValidLifetime != 0)
			timer_schedule(pr->pr_ValidLifetime);
		if (pr->pr_PreferredLifetime != 0)
			timer_schedule(pr->pr_PreferredLifetime);
	}
	if (pr->pr_kernel_state != pr->pr_state) {
		/* Log a message when an addrconf prefix goes away */
		if ((pr->pr_kernel_state & PR_AUTO) &&
		    !(pr->pr_state & PR_AUTO)) {
			char abuf[INET6_ADDRSTRLEN];

			logmsg(LOG_WARNING, "Address removed due to zero "
			    "valid lifetime %s\n",
			    inet_ntop(AF_INET6, (void *)&pr->pr_address,
			    abuf, sizeof (abuf)));
		}
		prefix_update_k(pr);
	}
	return (_B_TRUE);
}
Exemple #6
0
/*
 * Process prefix options with the autonomous flag set.
 * Returns false if this prefix results in a bad address (duplicate)
 * This function needs to loop to find the same prefix multiple times
 * as if a failover happened earlier, the addresses belonging to
 * a different interface may be found here on this interface.
 */
static boolean_t
incoming_prefix_addrconf(struct phyint *pi, uchar_t *opt,
    struct sockaddr_in6 *from, boolean_t loopback)
{
	struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt;
	int plen;
	struct prefix *pr;
	uint32_t validtime, preftime;	/* In seconds */
	char abuf[INET6_ADDRSTRLEN];
	char pbuf[INET6_ADDRSTRLEN];
	boolean_t found_pub = _B_FALSE;
	boolean_t found_tmp = _B_FALSE;
	boolean_t ret;

	validtime = ntohl(po->nd_opt_pi_valid_time);
	preftime = ntohl(po->nd_opt_pi_preferred_time);
	plen = po->nd_opt_pi_prefix_len;

	/* Sanity checks */
	if (validtime < preftime) {
		(void) inet_ntop(AF_INET6, (void *)&from->sin6_addr,
		    abuf, sizeof (abuf));
		(void) inet_ntop(AF_INET6,
		    (void *)&po->nd_opt_pi_prefix,
		    pbuf, sizeof (pbuf));
		logmsg(LOG_WARNING, "prefix option %s/%u from %s on %s: "
		    "valid %u < pref %u ignored\n",
		    pbuf, plen, abuf, pi->pi_name,
		    validtime, preftime);
		return (_B_FALSE);
	}

	for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) {
		if (pr->pr_prefix_len == plen &&
		    prefix_equal(po->nd_opt_pi_prefix, pr->pr_prefix, plen)) {

			/* Exclude static prefixes and DHCP */
			if ((pr->pr_state & PR_STATIC) ||
			    (pr->pr_flags & IFF_DHCPRUNNING))
				continue;
			if (pr->pr_flags & IFF_TEMPORARY) {
				/*
				 * If this address is deprecated and its token
				 * doesn't match the current tmp token, we want
				 * to create a new address with the current
				 * token.  So don't count this addr as a match.
				 */
				if (!((pr->pr_flags & IFF_DEPRECATED) &&
				    !token_equal(pi->pi_tmp_token,
				    pr->pr_address, TMP_TOKEN_BITS)))
					found_tmp = _B_TRUE;
			} else {
				found_pub = _B_TRUE;
			}
			(void) incoming_prefix_addrconf_process(pi, pr, opt,
			    from, loopback, _B_FALSE);
		}
	}

	/*
	 * If we have found a matching prefix (for public and, if temp addrs
	 * are enabled, for temporary) already or validtime is zero, we have
	 * nothing to do.
	 */
	if (validtime == 0 ||
	    (found_pub && (!pi->pi_TmpAddrsEnabled || found_tmp)))
		return (_B_TRUE);

	if (!found_pub) {
		pr = prefix_create(pi, po->nd_opt_pi_prefix, plen, 0);
		if (pr == NULL)
			return (_B_TRUE);
		ret = incoming_prefix_addrconf_process(pi, pr, opt, from,
		    loopback, _B_TRUE);
	}
	/*
	 * if processing of the public address failed,
	 * don't bother with the temporary address.
	 */
	if (ret == _B_FALSE)
		return (_B_FALSE);

	if (pi->pi_TmpAddrsEnabled && !found_tmp) {
		pr = prefix_create(pi, po->nd_opt_pi_prefix, plen,
		    IFF_TEMPORARY);
		if (pr == NULL)
			return (_B_TRUE);
		ret = incoming_prefix_addrconf_process(pi, pr, opt, from,
		    loopback, _B_TRUE);
	}

	return (ret);
}
Exemple #7
0
/*
 * info
 *   depth <x>
 *   seldepth <x>
 *   time <x>
 *   nodes <x>
 *   pv <move1> ... <movei>
 *   score
 *     cp <x>
 *     mate <y>
 *   currmove <move>
 *   hashfull <x>
 *   nps <x>
 *   string <str>
 */
static int
info_parse(Usimsg *msg, const char *s)
{
	const char *p;
	Token token;
	int type;
	int key;
	int num;

	p = s;
	while ((p = token_get(&token, p)) != NULL) {
		if (token_equal(&token, "depth")) {
			type = USITYPE_NUM;
			key = USIOBJ_DEPTH;
		} else if (token_equal(&token, "seldepth")) {
			type = USITYPE_NUM;
			key = USIOBJ_SELDEPTH;
		} else if (token_equal(&token, "time")) {
			type = USITYPE_NUM;
			key = USIOBJ_TIME;
		} else if (token_equal(&token, "nodes")) {
			type = USITYPE_NUM;
			key = USIOBJ_NODES;
		} else if (token_equal(&token, "pv")) {
			type = USITYPE_OCT;
			key = USIOBJ_PV;
		} else if (token_equal(&token, "score")) {
			if ((p = token_get(&token, p)) == NULL)
				return -1;
			if (token_equal(&token, "cp")) {
				type = USITYPE_NUM;
				key = USIOBJ_SCORE_CP;
			} else if (token_equal(&token, "mate")) {
				type = USITYPE_NUM;
				key = USIOBJ_SCORE_MATE;
			} else {
				/* rollback */
				p = token.s;
				continue;
			}
		} else if (token_equal(&token, "currmove")) {
			type = USITYPE_STR;
			key = USIOBJ_CURRMOVE;
		} else if (token_equal(&token, "hashfull")) {
			type = USITYPE_NUM;
			key = USIOBJ_HASHFULL;
		} else if (token_equal(&token, "nps")) {
			type = USITYPE_NUM;
			key = USIOBJ_NPS;
		} else if (token_equal(&token, "string")) {
			type = USITYPE_STR;
			key = USIOBJ_STRING;
		} else {
			continue;
		}

		switch (type) {
		case USITYPE_NUM:
			if ((p = token_get(&token, p)) == NULL)
				return -1;
			if (*token.s == '-' && token.len == 1)
				num = 1 << 31;
			else
				num = strtol(token.s, NULL, 10);
			if (usimsg_pushnum(msg, key, num) != 0)
				return -1;
			break;
		case USITYPE_STR:
			if ((p = token_get(&token, p)) == NULL)
				return -1;
			if (usimsg_pushstr(msg, key, token.s, token.len) != 0)
				return -1;
			break;
		case USITYPE_OCT:
			if ((p = token_get(&token, p)) == NULL)
				return -1;
			if (usimsg_pushstr(msg, key, token.s,
					strlen(token.s)) != 0)
				return -1;
			break;
		default:
			break;
		}
	}

	return 0;
}
Exemple #8
0
/*
 * option
 *   name <optionname> type <optiontype> <parameter...>
 *   <optiontype> =
 *     check
 *     spin
 *     combo
 *     button
 *     string
 *     filename
 *   <parameter> =
 *     default <x>
 *     min <x>
 *     max <x>
 *     var <x1> var <x2> ...
 */
static int
option_parse(Usimsg *msg, const char *s)
{
	const char *p;
	Token token;
	Tbl *tbl;
	int type;
	int num;

	if ((p = token_get(&token, s)) == NULL)
		return -1;
	if (!token_equal(&token, "name"))
		return -1;

	if ((p = token_get(&token, p)) == NULL)
		return -1;
	if (usimsg_pushstr(msg, USIOBJ_OPTNAME, token.s, token.len) != 0)
		return -1;

	if ((p = token_get(&token, p)) == NULL)
		return -1;
	if (!token_equal(&token, "type"))
		return -1;

	if ((p = token_get(&token, p)) == NULL)
		return -1;
	if ((tbl = tbl_find(tbl_option_type, &token)) == NULL)
		return -1;
	if (usimsg_pushnum(msg, USIOBJ_TYPE, tbl->id) != 0)
		return -1;
	type = tbl->id;

	while ((p = token_get(&token, p)) != NULL) {
		if ((tbl = tbl_find(tbl_option, &token)) == NULL)
			continue;
		switch (tbl->id) {
		case USIOBJ_DEFAULT:
			switch (type) {
			case USIOPT_CHECK:
				if ((p = token_get(&token, p)) == NULL)
					return -1;
				if (token_equal(&token, "true"))
					num = 1;
				else if (token_equal(&token, "false"))
					num = 0;
				else
					return -1;
				if (usimsg_pushnum(msg, tbl->id, num) != 0)
					return -1;
				break;
			case USIOPT_SPIN:
				if ((p = token_get(&token, p)) == NULL)
					return -1;
				num = strtol(token.s, NULL, 10);
				if (usimsg_pushnum(msg, tbl->id, num) != 0)
					return -1;
				break;
			case USIOPT_BUTTON:
				break;
			case USIOPT_COMBO:
			case USIOPT_STRING:
			case USIOPT_FILENAME:
				if ((p = token_get(&token, p)) == NULL)
					return -1;
				if (token_equal(&token, "<empty>"))
					token.len = 0;
				if (usimsg_pushstr(msg, tbl->id,
						token.s, token.len) != 0)
					return -1;
				break;
			default:
				break;
			}
			break;
		case USIOBJ_MIN:
		case USIOBJ_MAX:
			if ((p = token_get(&token, p)) == NULL)
				return -1;
			num = strtol(token.s, NULL, 10);
			if (usimsg_pushnum(msg, tbl->id, num) != 0)
				return -1;
			break;
		case USIOBJ_STRING:
			if ((p = token_get(&token, p)) == NULL)
				return -1;
			if (usimsg_pushstr(msg, tbl->id,
					token.s, strlen(token.s)) != 0)
				return -1;
			break;
		default:
			break;
		}
	}

	return 0;
}