8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / lib / nwamd / conditions.c
bloba93259fed3e65e62c25a0c986c714574d70ae61f
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <arpa/inet.h>
27 #include <ctype.h>
28 #include <errno.h>
29 #include <inet/ip.h>
30 #include <libdladm.h>
31 #include <libdllink.h>
32 #include <libdlwlan.h>
33 #include <netdb.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
38 #include <libnwam.h>
39 #include "conditions.h"
40 #include "ncu.h"
41 #include "objects.h"
42 #include "util.h"
45 * conditions.c - contains routines which check state to see if activation
46 * conditions for NWAM objects are satisfied and rates activation conditions to
47 * help determine which is most specific.
49 * If the activation-mode is CONDITIONAL_ANY or CONDITIONAL_ALL, the conditions
50 * property is set to a string made up of conditional expressions. Each
51 * expression is made up of a condition that can be assigned a boolean value,
52 * e.g. "system-domain is sun.com" or "ncu ip:bge0 is-not active". If the
53 * activation-mode is CONDITIONAL_ANY, the condition will be satisfied if any
54 * one of the conditions is true; if the activation-mode is CONDITIONAL_ALL,
55 * the condition is satisfied only if all of the conditions are true.
58 uint64_t condition_check_interval = CONDITION_CHECK_INTERVAL_DEFAULT;
60 extern int getdomainname(char *, int);
62 /* NCP, NCU, ENM and location conditions */
63 static boolean_t test_condition_ncp(nwam_condition_t condition,
64 const char *ncp_name);
65 static boolean_t test_condition_ncu(nwam_condition_t condition,
66 const char *ncu_name);
67 static boolean_t test_condition_enm(nwam_condition_t condition,
68 const char *enm_name);
69 static boolean_t test_condition_loc(nwam_condition_t condition,
70 const char *loc_name);
72 /* IP address conditions */
73 static boolean_t test_condition_ip_address(nwam_condition_t condition,
74 const char *ip_address);
76 /* domainname conditions */
77 static boolean_t test_condition_sys_domain(nwam_condition_t condition,
78 const char *domainname);
79 static boolean_t test_condition_adv_domain(nwam_condition_t condition,
80 const char *domainname);
82 /* WLAN conditions */
83 static boolean_t test_condition_wireless_essid(nwam_condition_t condition,
84 const char *essid);
85 static boolean_t test_condition_wireless_bssid(nwam_condition_t condition,
86 const char *essid);
88 struct nwamd_condition_map {
89 nwam_condition_object_type_t object_type;
90 boolean_t (*condition_func)(nwam_condition_t, const char *);
91 } condition_map[] =
93 { NWAM_CONDITION_OBJECT_TYPE_NCP, test_condition_ncp },
94 { NWAM_CONDITION_OBJECT_TYPE_NCU, test_condition_ncu },
95 { NWAM_CONDITION_OBJECT_TYPE_ENM, test_condition_enm },
96 { NWAM_CONDITION_OBJECT_TYPE_LOC, test_condition_loc },
97 { NWAM_CONDITION_OBJECT_TYPE_IP_ADDRESS, test_condition_ip_address },
98 { NWAM_CONDITION_OBJECT_TYPE_SYS_DOMAIN, test_condition_sys_domain },
99 { NWAM_CONDITION_OBJECT_TYPE_ADV_DOMAIN, test_condition_adv_domain },
100 { NWAM_CONDITION_OBJECT_TYPE_ESSID, test_condition_wireless_essid },
101 { NWAM_CONDITION_OBJECT_TYPE_BSSID, test_condition_wireless_bssid }
105 * This function takes which kind of conditions (is or is not) we are testing
106 * the object against and an object and applies the conditon to the object.
108 static boolean_t
109 test_condition_object_state(nwam_condition_t condition,
110 nwam_object_type_t object_type, const char *object_name)
112 nwamd_object_t object;
113 nwam_state_t state;
115 object = nwamd_object_find(object_type, object_name);
116 if (object == NULL)
117 return (B_FALSE);
119 state = object->nwamd_object_state;
120 nwamd_object_release(object);
122 switch (condition) {
123 case NWAM_CONDITION_IS:
124 return (state == NWAM_STATE_ONLINE);
125 case NWAM_CONDITION_IS_NOT:
126 return (state != NWAM_STATE_ONLINE);
127 default:
128 return (B_FALSE);
132 static boolean_t
133 test_condition_ncp(nwam_condition_t condition, const char *name)
135 boolean_t active;
137 (void) pthread_mutex_lock(&active_ncp_mutex);
138 active = (strcasecmp(active_ncp, name) == 0);
139 (void) pthread_mutex_unlock(&active_ncp_mutex);
141 switch (condition) {
142 case NWAM_CONDITION_IS:
143 return (active);
144 case NWAM_CONDITION_IS_NOT:
145 return (active != B_TRUE);
146 default:
147 return (B_FALSE);
151 static boolean_t
152 test_condition_ncu(nwam_condition_t condition, const char *name)
154 char *real_name, *ncu_name;
155 nwam_ncu_handle_t ncuh;
156 nwam_ncu_type_t ncu_type;
157 boolean_t rv;
159 /* names are case-insensitive, so get real name from libnwam */
160 if (nwam_ncu_read(active_ncph, name, NWAM_NCU_TYPE_INTERFACE, 0, &ncuh)
161 == NWAM_SUCCESS) {
162 ncu_type = NWAM_NCU_TYPE_INTERFACE;
163 } else if (nwam_ncu_read(active_ncph, name, NWAM_NCU_TYPE_LINK, 0,
164 &ncuh) == NWAM_SUCCESS) {
165 ncu_type = NWAM_NCU_TYPE_LINK;
166 } else {
167 return (B_FALSE);
169 if (nwam_ncu_get_name(ncuh, &real_name) != NWAM_SUCCESS) {
170 nwam_ncu_free(ncuh);
171 return (B_FALSE);
173 nwam_ncu_free(ncuh);
176 * Name may be either unqualified or qualified by NCU type
177 * (interface:/link:). Need to translate unqualified names
178 * to qualified, specifying interface:name if an interface
179 * NCU is present, otherwise link:ncu.
181 if (nwam_ncu_name_to_typed_name(real_name, ncu_type, &ncu_name)
182 != NWAM_SUCCESS) {
183 free(real_name);
184 return (B_FALSE);
186 free(real_name);
188 rv = test_condition_object_state(condition, NWAM_OBJECT_TYPE_NCU,
189 ncu_name);
190 free(ncu_name);
191 return (rv);
194 static boolean_t
195 test_condition_enm(nwam_condition_t condition, const char *enm_name)
197 nwam_enm_handle_t enmh;
198 char *real_name;
199 boolean_t rv;
201 /* names are case-insensitive, so get real name from libnwam */
202 if (nwam_enm_read(enm_name, 0, &enmh) != NWAM_SUCCESS)
203 return (B_FALSE);
204 if (nwam_enm_get_name(enmh, &real_name) != NWAM_SUCCESS) {
205 nwam_enm_free(enmh);
206 return (B_FALSE);
208 nwam_enm_free(enmh);
210 rv = test_condition_object_state(condition, NWAM_OBJECT_TYPE_ENM,
211 real_name);
212 free(real_name);
213 return (rv);
216 static boolean_t
217 test_condition_loc(nwam_condition_t condition, const char *loc_name)
219 nwam_loc_handle_t loch;
220 char *real_name;
221 boolean_t rv;
223 /* names are case-insensitive, so get real name from libnwam */
224 if (nwam_loc_read(loc_name, 0, &loch) != NWAM_SUCCESS)
225 return (B_FALSE);
226 if (nwam_loc_get_name(loch, &real_name) != NWAM_SUCCESS) {
227 nwam_loc_free(loch);
228 return (B_FALSE);
230 nwam_loc_free(loch);
232 rv = test_condition_object_state(condition, NWAM_OBJECT_TYPE_LOC,
233 real_name);
234 free(real_name);
235 return (rv);
238 static boolean_t
239 test_condition_domain(nwam_condition_t condition, const char *target_domain,
240 const char *found_domain)
242 int i, len_t, len_f;
243 char target[MAXHOSTNAMELEN], found[MAXHOSTNAMELEN];
245 len_t = target_domain == NULL ? 0 : strlen(target_domain);
246 len_f = found_domain == NULL ? 0 : strlen(found_domain);
248 /* convert target_domain and found_domain to lowercase for strstr() */
249 for (i = 0; i < len_t; i++)
250 target[i] = tolower(target_domain[i]);
251 target[len_t] = '\0';
253 for (i = 0; i < len_f; i++)
254 found[i] = tolower(found_domain[i]);
255 found[len_f] = '\0';
257 switch (condition) {
258 case NWAM_CONDITION_IS:
259 return (found_domain != NULL && strcmp(found, target) == 0);
260 case NWAM_CONDITION_IS_NOT:
261 return (found_domain == NULL || strcmp(found, target) != 0);
262 case NWAM_CONDITION_CONTAINS:
263 return (found_domain != NULL && strstr(found, target) != NULL);
264 case NWAM_CONDITION_DOES_NOT_CONTAIN:
265 return (found_domain == NULL || strstr(found, target) == NULL);
266 default:
267 return (B_FALSE);
271 struct ncu_adv_domains {
272 struct ncu_adv_domains *next;
273 char *dns_domain;
274 char *nis_domain;
277 static int
278 get_adv_domains(nwamd_object_t obj, void *arg)
280 nwamd_ncu_t *ncu = (nwamd_ncu_t *)obj->nwamd_object_data;
281 struct ncu_adv_domains **headpp = (struct ncu_adv_domains **)arg;
282 struct ncu_adv_domains *adp;
283 char *dns, *nis;
285 if (ncu->ncu_type != NWAM_NCU_TYPE_INTERFACE)
286 return (0);
288 dns = nwamd_get_dhcpinfo_data("DNSdmain", ncu->ncu_name);
289 nis = nwamd_get_dhcpinfo_data("NISdmain", ncu->ncu_name);
291 if (dns != NULL || nis != NULL) {
292 adp = (struct ncu_adv_domains *)malloc(sizeof (*adp));
293 if (adp == NULL)
294 return (1);
295 adp->dns_domain = dns;
296 adp->nis_domain = nis;
297 adp->next = *headpp;
298 *headpp = adp;
301 return (0);
304 static boolean_t
305 test_condition_sys_domain(nwam_condition_t condition, const char *domainname)
307 char cur_domainname[MAXHOSTNAMELEN];
309 if (getdomainname(cur_domainname, MAXHOSTNAMELEN) != 0)
310 return (B_FALSE);
312 return (test_condition_domain(condition, domainname, cur_domainname));
315 static boolean_t
316 test_condition_adv_domain(nwam_condition_t condition, const char *domainname)
318 struct ncu_adv_domains *adv_domains = NULL;
319 struct ncu_adv_domains *adp, *prev;
320 boolean_t positive, rtn;
322 (void) nwamd_walk_objects(NWAM_OBJECT_TYPE_NCU, get_adv_domains,
323 &adv_domains);
325 positive = (condition == NWAM_CONDITION_IS ||
326 condition == NWAM_CONDITION_CONTAINS);
329 * Walk the advertised domain list. Our test function tests one
330 * single domain, but we're dealing with a list: if our condition
331 * is positive ('is' or 'contains'), the test function for each
332 * domain results are or'd together; if our condition is negative
333 * ('is-not' or 'does-not-contain'), the test function results must
334 * be and'd. Thus our short-circuit exit value depends on our
335 * condition: if the test function returns TRUE it implies immediate
336 * success for a positive condition; if it returns FALSE it implies
337 * immediate failure for a negative condition.
339 adp = adv_domains;
340 while (adp != NULL) {
341 if ((test_condition_domain(condition, domainname,
342 adp->dns_domain) == positive) ||
343 (test_condition_domain(condition, domainname,
344 adp->nis_domain) == positive)) {
345 rtn = positive;
346 break;
348 adp = adp->next;
350 if (adp == NULL) {
352 * We did not short-circuit; we therefore failed if our
353 * condition was positive, and succeeded if our condition
354 * was negative.
356 rtn = !positive;
359 /* now free the domain list */
360 adp = adv_domains;
361 while (adp != NULL) {
362 prev = adp;
363 adp = prev->next;
364 free(prev->dns_domain);
365 free(prev->nis_domain);
366 free(prev);
369 return (rtn);
373 * Returns true if prefixlen bits of addr1 match prefixlen bits of addr2.
375 static boolean_t
376 prefixmatch(uchar_t *addr1, uchar_t *addr2, int prefixlen)
378 uchar_t mask[IPV6_ABITS/8];
379 int i, j = 0;
381 if (prefixlen == 0)
382 return (B_TRUE);
384 while (prefixlen > 0) {
385 if (prefixlen >= 8) {
386 mask[j++] = 0xFF;
387 prefixlen -= 8;
388 } else {
389 mask[j] |= 1 << (8 - prefixlen);
390 prefixlen--;
393 /* Ensure at least one byte is tested */
394 if (j == 0) j++;
396 for (i = 0; i < j; i++) {
397 if ((addr1[i] & mask[i]) != (addr2[i] & mask[i]))
398 return (B_FALSE);
400 return (B_TRUE);
404 * Given a string representation of an IPv4 or IPv6 address returns the
405 * sockaddr representation. Note that 'sockaddr' should point at the correct
406 * sockaddr structure for the address family (sockaddr_in for AF_INET or
407 * sockaddr_in6 for AF_INET6) or alternatively at a sockaddr_storage
408 * structure.
410 static struct sockaddr_storage *
411 nwamd_str2sockaddr(sa_family_t af, const char *straddr,
412 struct sockaddr_storage *addr)
414 struct sockaddr_in *sin;
415 struct sockaddr_in6 *sin6;
416 int err;
418 if (af == AF_INET) {
419 sin = (struct sockaddr_in *)addr;
420 sin->sin_family = AF_INET;
421 err = inet_pton(AF_INET, straddr, &sin->sin_addr);
422 } else if (af == AF_INET6) {
423 sin6 = (struct sockaddr_in6 *)addr;
424 sin6->sin6_family = AF_INET6;
425 err = inet_pton(AF_INET6, straddr, &sin6->sin6_addr);
426 } else {
427 errno = EINVAL;
428 return (NULL);
430 return (err == 1 ? addr : NULL);
433 struct nwamd_ipaddr_condition_walk_arg {
434 nwam_condition_t condition;
435 struct sockaddr_storage sockaddr;
436 int prefixlen;
437 boolean_t res;
440 static int
441 check_ipaddr(sa_family_t family, struct ifaddrs *ifa, void *arg)
443 struct nwamd_ipaddr_condition_walk_arg *wa = arg;
444 struct sockaddr_in6 addr6;
445 struct sockaddr_in addr;
446 boolean_t match = B_FALSE;
447 uchar_t *addr1, *addr2;
449 if (family == AF_INET) {
450 (void) memcpy(&addr, ifa->ifa_addr, sizeof (addr));
451 addr1 = (uchar_t *)(&addr.sin_addr.s_addr);
452 addr2 = (uchar_t *)&(((struct sockaddr_in *)
453 &(wa->sockaddr))->sin_addr.s_addr);
454 } else {
455 (void) memcpy(&addr6, ifa->ifa_addr, sizeof (addr6));
456 addr1 = (uchar_t *)(&addr6.sin6_addr.s6_addr);
457 addr2 = (uchar_t *)&(((struct sockaddr_in6 *)
458 &(wa->sockaddr))->sin6_addr.s6_addr);
461 match = prefixmatch(addr1, addr2, wa->prefixlen);
463 nlog(LOG_DEBUG, "check_ipaddr: match %d\n", match);
464 switch (wa->condition) {
465 case NWAM_CONDITION_IS:
466 case NWAM_CONDITION_IS_IN_RANGE:
467 wa->res = match;
468 if (match)
469 return (1);
470 return (0);
471 case NWAM_CONDITION_IS_NOT:
472 case NWAM_CONDITION_IS_NOT_IN_RANGE:
473 wa->res = !match;
474 return (0);
475 default:
476 return (0);
480 static boolean_t
481 test_condition_ip_address(nwam_condition_t condition,
482 const char *ip_address_string)
484 sa_family_t family;
485 char *copy, *ip_address, *prefixlen_string, *lasts;
486 struct nwamd_ipaddr_condition_walk_arg wa;
487 struct ifaddrs *ifap, *ifa;
489 if ((copy = strdup(ip_address_string)) == NULL)
490 return (B_FALSE);
492 if ((ip_address = strtok_r(copy, " \t/", &lasts)) == NULL) {
493 free(copy);
494 return (B_FALSE);
497 prefixlen_string = strtok_r(NULL, " \t", &lasts);
499 if (nwamd_str2sockaddr(AF_INET, ip_address, &wa.sockaddr) != NULL) {
500 family = AF_INET;
501 wa.prefixlen = IP_ABITS;
502 } else if (nwamd_str2sockaddr(AF_INET6, ip_address, &wa.sockaddr)
503 != NULL) {
504 family = AF_INET6;
505 wa.prefixlen = IPV6_ABITS;
506 } else {
507 nlog(LOG_ERR, "test_condition_ip_address: "
508 "nwamd_str2sockaddr failed for %s: %s", ip_address,
509 strerror(errno));
510 free(copy);
511 return (B_FALSE);
514 if (prefixlen_string != NULL)
515 wa.prefixlen = atoi(prefixlen_string);
517 wa.condition = condition;
519 switch (condition) {
520 case NWAM_CONDITION_IS:
521 case NWAM_CONDITION_IS_IN_RANGE:
522 wa.res = B_FALSE;
523 break;
524 case NWAM_CONDITION_IS_NOT:
525 case NWAM_CONDITION_IS_NOT_IN_RANGE:
526 wa.res = B_TRUE;
527 break;
528 default:
529 free(copy);
530 return (B_FALSE);
532 free(copy);
534 if (getifaddrs(&ifa) == -1) {
535 nlog(LOG_ERR, "test_condition_ip_address: "
536 "getifaddrs failed: %s", strerror(errno));
537 return (wa.res);
539 for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) {
540 if (ifap->ifa_addr->sa_family != family)
541 continue;
542 if (check_ipaddr(family, ifap, &wa) == 1)
543 break;
545 freeifaddrs(ifa);
547 return (wa.res);
550 struct nwamd_wlan_condition_walk_arg {
551 nwam_condition_t condition;
552 const char *exp_essid;
553 const char *exp_bssid;
554 uint_t num_connected;
555 boolean_t res;
558 static int
559 check_wlan(const char *linkname, void *arg)
561 struct nwamd_wlan_condition_walk_arg *wa = arg;
562 datalink_id_t linkid;
563 dladm_wlan_linkattr_t attr;
564 dladm_status_t status;
565 char cur_essid[DLADM_STRSIZE];
566 char cur_bssid[DLADM_STRSIZE];
567 char errmsg[DLADM_STRSIZE];
569 if ((status = dladm_name2info(dld_handle, linkname, &linkid, NULL, NULL,
570 NULL)) != DLADM_STATUS_OK) {
571 nlog(LOG_DEBUG, "check_wlan: dladm_name2info() for %s "
572 "failed: %s", linkname,
573 dladm_status2str(status, errmsg));
574 return (DLADM_WALK_CONTINUE);
577 status = dladm_wlan_get_linkattr(dld_handle, linkid, &attr);
578 if (status != DLADM_STATUS_OK) {
579 nlog(LOG_DEBUG, "check_wlan: dladm_wlan_get_linkattr() for %s "
580 "failed: %s", linkname,
581 dladm_status2str(status, errmsg));
582 return (DLADM_WALK_CONTINUE);
584 if (attr.la_status == DLADM_WLAN_LINK_DISCONNECTED)
585 return (DLADM_WALK_TERMINATE);
587 wa->num_connected++;
589 if (wa->exp_essid != NULL) {
590 /* Is the NIC associated with the expected access point? */
591 (void) dladm_wlan_essid2str(&attr.la_wlan_attr.wa_essid,
592 cur_essid);
593 switch (wa->condition) {
594 case NWAM_CONDITION_IS:
595 wa->res = strcmp(cur_essid, wa->exp_essid) == 0;
596 if (wa->res)
597 return (DLADM_WALK_TERMINATE);
598 break;
599 case NWAM_CONDITION_IS_NOT:
600 wa->res = strcmp(cur_essid, wa->exp_essid) != 0;
601 if (!wa->res)
602 return (DLADM_WALK_TERMINATE);
603 break;
604 case NWAM_CONDITION_CONTAINS:
605 wa->res = strstr(cur_essid, wa->exp_essid) != NULL;
606 if (wa->res)
607 return (DLADM_WALK_TERMINATE);
608 break;
609 case NWAM_CONDITION_DOES_NOT_CONTAIN:
610 wa->res = strstr(cur_essid, wa->exp_essid) == NULL;
611 if (!wa->res)
612 return (DLADM_WALK_TERMINATE);
613 break;
614 default:
615 return (DLADM_WALK_TERMINATE);
617 return (DLADM_WALK_CONTINUE);
619 if (wa->exp_bssid != NULL) {
620 /* Is the NIC associated with the expected access point? */
621 (void) dladm_wlan_bssid2str(&attr.la_wlan_attr.wa_bssid,
622 cur_bssid);
623 switch (wa->condition) {
624 case NWAM_CONDITION_IS:
625 wa->res = strcmp(cur_bssid, wa->exp_bssid) == 0;
626 if (wa->res)
627 return (DLADM_WALK_TERMINATE);
628 break;
629 case NWAM_CONDITION_IS_NOT:
630 wa->res = strcmp(cur_bssid, wa->exp_bssid) != 0;
631 if (!wa->res)
632 return (DLADM_WALK_TERMINATE);
633 break;
634 default:
635 return (DLADM_WALK_TERMINATE);
637 return (DLADM_WALK_CONTINUE);
640 * Neither an ESSID or BSSID match is required - being connected to a
641 * WLAN is enough.
643 switch (wa->condition) {
644 case NWAM_CONDITION_IS:
645 wa->res = B_TRUE;
646 return (DLADM_WALK_TERMINATE);
647 default:
648 wa->res = B_FALSE;
649 return (DLADM_WALK_TERMINATE);
651 /*NOTREACHED*/
652 return (DLADM_WALK_CONTINUE);
655 static boolean_t
656 test_condition_wireless_essid(nwam_condition_t condition,
657 const char *essid)
659 struct nwamd_wlan_condition_walk_arg wa;
661 wa.condition = condition;
662 wa.exp_essid = essid;
663 wa.exp_bssid = NULL;
664 wa.num_connected = 0;
665 wa.res = B_FALSE;
667 (void) dladm_walk(check_wlan, dld_handle, &wa, DATALINK_CLASS_PHYS,
668 DL_WIFI, DLADM_OPT_ACTIVE);
670 return (wa.num_connected > 0 && wa.res == B_TRUE);
673 static boolean_t
674 test_condition_wireless_bssid(nwam_condition_t condition,
675 const char *bssid)
677 struct nwamd_wlan_condition_walk_arg wa;
679 wa.condition = condition;
680 wa.exp_bssid = bssid;
681 wa.exp_essid = NULL;
682 wa.num_connected = 0;
683 wa.res = B_FALSE;
685 (void) dladm_walk(check_wlan, dld_handle, &wa, DATALINK_CLASS_PHYS,
686 DL_WIFI, DLADM_OPT_ACTIVE);
688 return (wa.num_connected > 0 && wa.res == B_TRUE);
692 * This function takes an activation mode and a string representation of a
693 * condition and evaluates it.
695 boolean_t
696 nwamd_check_conditions(nwam_activation_mode_t activation_mode,
697 char **condition_strings, uint_t num_conditions)
699 boolean_t ret;
700 nwam_condition_t condition;
701 nwam_condition_object_type_t object_type;
702 char *object_name;
703 int i, j;
705 for (i = 0; i < num_conditions; i++) {
707 if (nwam_condition_string_to_condition(condition_strings[i],
708 &object_type, &condition, &object_name) != NWAM_SUCCESS) {
709 nlog(LOG_ERR, "check_conditions: invalid condition %s",
710 condition_strings[i]);
711 return (B_FALSE);
713 ret = B_FALSE;
715 for (j = 0; j < (sizeof (condition_map) /
716 sizeof (struct nwamd_condition_map)); j++) {
717 if (condition_map[j].object_type == object_type)
718 ret = condition_map[j].condition_func(condition,
719 object_name);
722 free(object_name);
724 if (activation_mode == NWAM_ACTIVATION_MODE_CONDITIONAL_ANY &&
725 ret) {
726 return (B_TRUE);
728 if (activation_mode == NWAM_ACTIVATION_MODE_CONDITIONAL_ALL &&
729 !ret) {
730 return (B_FALSE);
733 if (activation_mode == NWAM_ACTIVATION_MODE_CONDITIONAL_ANY && ret)
734 return (B_TRUE);
735 if (activation_mode == NWAM_ACTIVATION_MODE_CONDITIONAL_ALL && ret)
736 return (B_TRUE);
738 return (B_FALSE);
742 * In rating activation conditions, we take the best-rated CONDITIONAL_ANY
743 * condition, or sum all the CONDITIONAL_ALL condition ratings. This allows
744 * us to compare between location activation conditions to pick the best.
746 uint64_t
747 nwamd_rate_conditions(nwam_activation_mode_t activation_mode,
748 char **conditions, uint_t num_conditions)
750 nwam_condition_t condition;
751 nwam_condition_object_type_t object_type;
752 char *object_name;
753 int i;
754 uint64_t rating = 0, total_rating = 0;
756 for (i = 0; i < num_conditions; i++) {
758 object_name = NULL;
759 if (nwam_condition_string_to_condition(conditions[i],
760 &object_type, &condition, &object_name) != NWAM_SUCCESS ||
761 nwam_condition_rate(object_type, condition, &rating)
762 != NWAM_SUCCESS) {
763 nlog(LOG_ERR, "nwamd_rate_conditions: could not rate "
764 "condition");
765 free(object_name);
766 return (0);
768 free(object_name);
770 if (activation_mode == NWAM_ACTIVATION_MODE_CONDITIONAL_ANY) {
771 if (rating > total_rating)
772 total_rating = rating;
773 } else if (activation_mode ==
774 NWAM_ACTIVATION_MODE_CONDITIONAL_ALL) {
775 total_rating += rating;
778 return (total_rating);
782 * Different from nwamd_triggered_check_all_conditions() in that this
783 * function enqueues a timed check event.
785 void
786 nwamd_set_timed_check_all_conditions(void)
788 nwamd_event_t check_event = nwamd_event_init
789 (NWAM_EVENT_TYPE_TIMED_CHECK_CONDITIONS, NWAM_OBJECT_TYPE_UNKNOWN,
790 0, NULL);
791 if (check_event != NULL) {
792 /* Add another timed event to recheck conditions */
793 nwamd_event_enqueue_timed(check_event,
794 condition_check_interval > CONDITION_CHECK_INTERVAL_MIN ?
795 condition_check_interval : CONDITION_CHECK_INTERVAL_MIN);
800 * Does not enqueue another check event.
802 void
803 nwamd_check_all_conditions(void)
805 nwamd_enm_check_conditions();
806 nwamd_loc_check_conditions();
809 void
810 nwamd_create_timed_condition_check_event(void)
812 nwamd_event_t check_event = nwamd_event_init
813 (NWAM_EVENT_TYPE_TIMED_CHECK_CONDITIONS, NWAM_OBJECT_TYPE_UNKNOWN,
814 0, NULL);
815 if (check_event != NULL)
816 nwamd_event_enqueue(check_event);
819 void
820 nwamd_create_triggered_condition_check_event(uint32_t when)
822 nwamd_event_t check_event;
824 if (!nwamd_event_enqueued(NWAM_EVENT_TYPE_TRIGGERED_CHECK_CONDITIONS,
825 NWAM_OBJECT_TYPE_UNKNOWN, NULL)) {
826 check_event = nwamd_event_init
827 (NWAM_EVENT_TYPE_TRIGGERED_CHECK_CONDITIONS,
828 NWAM_OBJECT_TYPE_UNKNOWN, 0, NULL);
829 if (check_event != NULL)
830 nwamd_event_enqueue_timed(check_event, when);