111767SAnurag.Maskey@Sun.COM /*
211767SAnurag.Maskey@Sun.COM * CDDL HEADER START
311767SAnurag.Maskey@Sun.COM *
411767SAnurag.Maskey@Sun.COM * The contents of this file are subject to the terms of the
511767SAnurag.Maskey@Sun.COM * Common Development and Distribution License (the "License").
611767SAnurag.Maskey@Sun.COM * You may not use this file except in compliance with the License.
711767SAnurag.Maskey@Sun.COM *
811767SAnurag.Maskey@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
911767SAnurag.Maskey@Sun.COM * or http://www.opensolaris.org/os/licensing.
1011767SAnurag.Maskey@Sun.COM * See the License for the specific language governing permissions
1111767SAnurag.Maskey@Sun.COM * and limitations under the License.
1211767SAnurag.Maskey@Sun.COM *
1311767SAnurag.Maskey@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
1411767SAnurag.Maskey@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1511767SAnurag.Maskey@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
1611767SAnurag.Maskey@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
1711767SAnurag.Maskey@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
1811767SAnurag.Maskey@Sun.COM *
1911767SAnurag.Maskey@Sun.COM * CDDL HEADER END
2011767SAnurag.Maskey@Sun.COM */
2111767SAnurag.Maskey@Sun.COM
2211767SAnurag.Maskey@Sun.COM /*
2312576SAnurag.Maskey@Oracle.COM * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2411767SAnurag.Maskey@Sun.COM */
2511767SAnurag.Maskey@Sun.COM
2611767SAnurag.Maskey@Sun.COM #include <arpa/inet.h>
2711767SAnurag.Maskey@Sun.COM #include <ctype.h>
2811767SAnurag.Maskey@Sun.COM #include <errno.h>
2911767SAnurag.Maskey@Sun.COM #include <inet/ip.h>
3011767SAnurag.Maskey@Sun.COM #include <libdladm.h>
3111767SAnurag.Maskey@Sun.COM #include <libdllink.h>
3211767SAnurag.Maskey@Sun.COM #include <libdlwlan.h>
3311767SAnurag.Maskey@Sun.COM #include <netdb.h>
3411767SAnurag.Maskey@Sun.COM #include <stdio.h>
3511767SAnurag.Maskey@Sun.COM #include <stdlib.h>
3611767SAnurag.Maskey@Sun.COM #include <string.h>
3711767SAnurag.Maskey@Sun.COM
3811767SAnurag.Maskey@Sun.COM #include <libnwam.h>
3911767SAnurag.Maskey@Sun.COM #include "conditions.h"
4011767SAnurag.Maskey@Sun.COM #include "ncu.h"
4111767SAnurag.Maskey@Sun.COM #include "objects.h"
4211767SAnurag.Maskey@Sun.COM #include "util.h"
4311767SAnurag.Maskey@Sun.COM
4411767SAnurag.Maskey@Sun.COM /*
4511767SAnurag.Maskey@Sun.COM * conditions.c - contains routines which check state to see if activation
4611767SAnurag.Maskey@Sun.COM * conditions for NWAM objects are satisfied and rates activation conditions to
4711767SAnurag.Maskey@Sun.COM * help determine which is most specific.
4811767SAnurag.Maskey@Sun.COM *
4911767SAnurag.Maskey@Sun.COM * If the activation-mode is CONDITIONAL_ANY or CONDITIONAL_ALL, the conditions
5011767SAnurag.Maskey@Sun.COM * property is set to a string made up of conditional expressions. Each
5111767SAnurag.Maskey@Sun.COM * expression is made up of a condition that can be assigned a boolean value,
5211767SAnurag.Maskey@Sun.COM * e.g. "system-domain is sun.com" or "ncu ip:bge0 is-not active". If the
5311767SAnurag.Maskey@Sun.COM * activation-mode is CONDITIONAL_ANY, the condition will be satisfied if any
5411767SAnurag.Maskey@Sun.COM * one of the conditions is true; if the activation-mode is CONDITIONAL_ALL,
5511767SAnurag.Maskey@Sun.COM * the condition is satisfied only if all of the conditions are true.
5611767SAnurag.Maskey@Sun.COM */
5711767SAnurag.Maskey@Sun.COM
5811767SAnurag.Maskey@Sun.COM uint64_t condition_check_interval = CONDITION_CHECK_INTERVAL_DEFAULT;
5911767SAnurag.Maskey@Sun.COM
6011767SAnurag.Maskey@Sun.COM extern int getdomainname(char *, int);
6111767SAnurag.Maskey@Sun.COM
6211767SAnurag.Maskey@Sun.COM /* NCP, NCU, ENM and location conditions */
6311767SAnurag.Maskey@Sun.COM static boolean_t test_condition_ncp(nwam_condition_t condition,
6411767SAnurag.Maskey@Sun.COM const char *ncp_name);
6511767SAnurag.Maskey@Sun.COM static boolean_t test_condition_ncu(nwam_condition_t condition,
6611767SAnurag.Maskey@Sun.COM const char *ncu_name);
6711767SAnurag.Maskey@Sun.COM static boolean_t test_condition_enm(nwam_condition_t condition,
6811767SAnurag.Maskey@Sun.COM const char *enm_name);
6911767SAnurag.Maskey@Sun.COM static boolean_t test_condition_loc(nwam_condition_t condition,
7011767SAnurag.Maskey@Sun.COM const char *loc_name);
7111767SAnurag.Maskey@Sun.COM
7211767SAnurag.Maskey@Sun.COM /* IP address conditions */
7311767SAnurag.Maskey@Sun.COM static boolean_t test_condition_ip_address(nwam_condition_t condition,
7411767SAnurag.Maskey@Sun.COM const char *ip_address);
7511767SAnurag.Maskey@Sun.COM
7611767SAnurag.Maskey@Sun.COM /* domainname conditions */
7711767SAnurag.Maskey@Sun.COM static boolean_t test_condition_sys_domain(nwam_condition_t condition,
7811767SAnurag.Maskey@Sun.COM const char *domainname);
7911767SAnurag.Maskey@Sun.COM static boolean_t test_condition_adv_domain(nwam_condition_t condition,
8011767SAnurag.Maskey@Sun.COM const char *domainname);
8111767SAnurag.Maskey@Sun.COM
8211767SAnurag.Maskey@Sun.COM /* WLAN conditions */
8311767SAnurag.Maskey@Sun.COM static boolean_t test_condition_wireless_essid(nwam_condition_t condition,
8411767SAnurag.Maskey@Sun.COM const char *essid);
8511767SAnurag.Maskey@Sun.COM static boolean_t test_condition_wireless_bssid(nwam_condition_t condition,
8611767SAnurag.Maskey@Sun.COM const char *essid);
8711767SAnurag.Maskey@Sun.COM
8811767SAnurag.Maskey@Sun.COM struct nwamd_condition_map {
8911767SAnurag.Maskey@Sun.COM nwam_condition_object_type_t object_type;
9011767SAnurag.Maskey@Sun.COM boolean_t (*condition_func)(nwam_condition_t, const char *);
9111767SAnurag.Maskey@Sun.COM } condition_map[] =
9211767SAnurag.Maskey@Sun.COM {
9311767SAnurag.Maskey@Sun.COM { NWAM_CONDITION_OBJECT_TYPE_NCP, test_condition_ncp },
9411767SAnurag.Maskey@Sun.COM { NWAM_CONDITION_OBJECT_TYPE_NCU, test_condition_ncu },
9511767SAnurag.Maskey@Sun.COM { NWAM_CONDITION_OBJECT_TYPE_ENM, test_condition_enm },
9611767SAnurag.Maskey@Sun.COM { NWAM_CONDITION_OBJECT_TYPE_LOC, test_condition_loc },
9711767SAnurag.Maskey@Sun.COM { NWAM_CONDITION_OBJECT_TYPE_IP_ADDRESS, test_condition_ip_address },
9811767SAnurag.Maskey@Sun.COM { NWAM_CONDITION_OBJECT_TYPE_SYS_DOMAIN, test_condition_sys_domain },
9911767SAnurag.Maskey@Sun.COM { NWAM_CONDITION_OBJECT_TYPE_ADV_DOMAIN, test_condition_adv_domain },
10011767SAnurag.Maskey@Sun.COM { NWAM_CONDITION_OBJECT_TYPE_ESSID, test_condition_wireless_essid },
10111767SAnurag.Maskey@Sun.COM { NWAM_CONDITION_OBJECT_TYPE_BSSID, test_condition_wireless_bssid }
10211767SAnurag.Maskey@Sun.COM };
10311767SAnurag.Maskey@Sun.COM
10411767SAnurag.Maskey@Sun.COM /*
10511767SAnurag.Maskey@Sun.COM * This function takes which kind of conditions (is or is not) we are testing
10611767SAnurag.Maskey@Sun.COM * the object against and an object and applies the conditon to the object.
10711767SAnurag.Maskey@Sun.COM */
10811767SAnurag.Maskey@Sun.COM static boolean_t
test_condition_object_state(nwam_condition_t condition,nwam_object_type_t object_type,const char * object_name)10911767SAnurag.Maskey@Sun.COM test_condition_object_state(nwam_condition_t condition,
11011767SAnurag.Maskey@Sun.COM nwam_object_type_t object_type, const char *object_name)
11111767SAnurag.Maskey@Sun.COM {
11211767SAnurag.Maskey@Sun.COM nwamd_object_t object;
11311767SAnurag.Maskey@Sun.COM nwam_state_t state;
11411767SAnurag.Maskey@Sun.COM
11511767SAnurag.Maskey@Sun.COM object = nwamd_object_find(object_type, object_name);
11611767SAnurag.Maskey@Sun.COM if (object == NULL)
11711767SAnurag.Maskey@Sun.COM return (B_FALSE);
11811767SAnurag.Maskey@Sun.COM
11911767SAnurag.Maskey@Sun.COM state = object->nwamd_object_state;
12011767SAnurag.Maskey@Sun.COM nwamd_object_release(object);
12111767SAnurag.Maskey@Sun.COM
12211767SAnurag.Maskey@Sun.COM switch (condition) {
12311767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_IS:
12411767SAnurag.Maskey@Sun.COM return (state == NWAM_STATE_ONLINE);
12511767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_IS_NOT:
12611767SAnurag.Maskey@Sun.COM return (state != NWAM_STATE_ONLINE);
12711767SAnurag.Maskey@Sun.COM default:
12811767SAnurag.Maskey@Sun.COM return (B_FALSE);
12911767SAnurag.Maskey@Sun.COM }
13011767SAnurag.Maskey@Sun.COM }
13111767SAnurag.Maskey@Sun.COM
13211767SAnurag.Maskey@Sun.COM static boolean_t
test_condition_ncp(nwam_condition_t condition,const char * name)13311767SAnurag.Maskey@Sun.COM test_condition_ncp(nwam_condition_t condition, const char *name)
13411767SAnurag.Maskey@Sun.COM {
13511767SAnurag.Maskey@Sun.COM boolean_t active;
13611767SAnurag.Maskey@Sun.COM
13711767SAnurag.Maskey@Sun.COM (void) pthread_mutex_lock(&active_ncp_mutex);
13811767SAnurag.Maskey@Sun.COM active = (strcasecmp(active_ncp, name) == 0);
13911767SAnurag.Maskey@Sun.COM (void) pthread_mutex_unlock(&active_ncp_mutex);
14011767SAnurag.Maskey@Sun.COM
14111767SAnurag.Maskey@Sun.COM switch (condition) {
14211767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_IS:
14311767SAnurag.Maskey@Sun.COM return (active);
14411767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_IS_NOT:
14511767SAnurag.Maskey@Sun.COM return (active != B_TRUE);
14611767SAnurag.Maskey@Sun.COM default:
14711767SAnurag.Maskey@Sun.COM return (B_FALSE);
14811767SAnurag.Maskey@Sun.COM }
14911767SAnurag.Maskey@Sun.COM }
15011767SAnurag.Maskey@Sun.COM
15111767SAnurag.Maskey@Sun.COM static boolean_t
test_condition_ncu(nwam_condition_t condition,const char * name)15211767SAnurag.Maskey@Sun.COM test_condition_ncu(nwam_condition_t condition, const char *name)
15311767SAnurag.Maskey@Sun.COM {
15411767SAnurag.Maskey@Sun.COM char *real_name, *ncu_name;
15511767SAnurag.Maskey@Sun.COM nwam_ncu_handle_t ncuh;
15611767SAnurag.Maskey@Sun.COM nwam_ncu_type_t ncu_type;
15711767SAnurag.Maskey@Sun.COM boolean_t rv;
15811767SAnurag.Maskey@Sun.COM
15911767SAnurag.Maskey@Sun.COM /* names are case-insensitive, so get real name from libnwam */
16011767SAnurag.Maskey@Sun.COM if (nwam_ncu_read(active_ncph, name, NWAM_NCU_TYPE_INTERFACE, 0, &ncuh)
16111767SAnurag.Maskey@Sun.COM == NWAM_SUCCESS) {
16211767SAnurag.Maskey@Sun.COM ncu_type = NWAM_NCU_TYPE_INTERFACE;
16311767SAnurag.Maskey@Sun.COM } else if (nwam_ncu_read(active_ncph, name, NWAM_NCU_TYPE_LINK, 0,
16411767SAnurag.Maskey@Sun.COM &ncuh) == NWAM_SUCCESS) {
16511767SAnurag.Maskey@Sun.COM ncu_type = NWAM_NCU_TYPE_LINK;
16611767SAnurag.Maskey@Sun.COM } else {
16711767SAnurag.Maskey@Sun.COM return (B_FALSE);
16811767SAnurag.Maskey@Sun.COM }
16911767SAnurag.Maskey@Sun.COM if (nwam_ncu_get_name(ncuh, &real_name) != NWAM_SUCCESS) {
17011767SAnurag.Maskey@Sun.COM nwam_ncu_free(ncuh);
17111767SAnurag.Maskey@Sun.COM return (B_FALSE);
17211767SAnurag.Maskey@Sun.COM }
17311767SAnurag.Maskey@Sun.COM nwam_ncu_free(ncuh);
17411767SAnurag.Maskey@Sun.COM
17511767SAnurag.Maskey@Sun.COM /*
17611767SAnurag.Maskey@Sun.COM * Name may be either unqualified or qualified by NCU type
17711767SAnurag.Maskey@Sun.COM * (interface:/link:). Need to translate unqualified names
17811767SAnurag.Maskey@Sun.COM * to qualified, specifying interface:name if an interface
17911767SAnurag.Maskey@Sun.COM * NCU is present, otherwise link:ncu.
18011767SAnurag.Maskey@Sun.COM */
18111767SAnurag.Maskey@Sun.COM if (nwam_ncu_name_to_typed_name(real_name, ncu_type, &ncu_name)
18211767SAnurag.Maskey@Sun.COM != NWAM_SUCCESS) {
18311767SAnurag.Maskey@Sun.COM free(real_name);
18411767SAnurag.Maskey@Sun.COM return (B_FALSE);
18511767SAnurag.Maskey@Sun.COM }
18611767SAnurag.Maskey@Sun.COM free(real_name);
18711767SAnurag.Maskey@Sun.COM
18811767SAnurag.Maskey@Sun.COM rv = test_condition_object_state(condition, NWAM_OBJECT_TYPE_NCU,
18911767SAnurag.Maskey@Sun.COM ncu_name);
19011767SAnurag.Maskey@Sun.COM free(ncu_name);
19111767SAnurag.Maskey@Sun.COM return (rv);
19211767SAnurag.Maskey@Sun.COM }
19311767SAnurag.Maskey@Sun.COM
19411767SAnurag.Maskey@Sun.COM static boolean_t
test_condition_enm(nwam_condition_t condition,const char * enm_name)19511767SAnurag.Maskey@Sun.COM test_condition_enm(nwam_condition_t condition, const char *enm_name)
19611767SAnurag.Maskey@Sun.COM {
19711767SAnurag.Maskey@Sun.COM nwam_enm_handle_t enmh;
19811767SAnurag.Maskey@Sun.COM char *real_name;
19911767SAnurag.Maskey@Sun.COM boolean_t rv;
20011767SAnurag.Maskey@Sun.COM
20111767SAnurag.Maskey@Sun.COM /* names are case-insensitive, so get real name from libnwam */
20211767SAnurag.Maskey@Sun.COM if (nwam_enm_read(enm_name, 0, &enmh) != NWAM_SUCCESS)
20311767SAnurag.Maskey@Sun.COM return (B_FALSE);
20411767SAnurag.Maskey@Sun.COM if (nwam_enm_get_name(enmh, &real_name) != NWAM_SUCCESS) {
20511767SAnurag.Maskey@Sun.COM nwam_enm_free(enmh);
20611767SAnurag.Maskey@Sun.COM return (B_FALSE);
20711767SAnurag.Maskey@Sun.COM }
20811767SAnurag.Maskey@Sun.COM nwam_enm_free(enmh);
20911767SAnurag.Maskey@Sun.COM
21011767SAnurag.Maskey@Sun.COM rv = test_condition_object_state(condition, NWAM_OBJECT_TYPE_ENM,
21111767SAnurag.Maskey@Sun.COM real_name);
21211767SAnurag.Maskey@Sun.COM free(real_name);
21311767SAnurag.Maskey@Sun.COM return (rv);
21411767SAnurag.Maskey@Sun.COM }
21511767SAnurag.Maskey@Sun.COM
21611767SAnurag.Maskey@Sun.COM static boolean_t
test_condition_loc(nwam_condition_t condition,const char * loc_name)21711767SAnurag.Maskey@Sun.COM test_condition_loc(nwam_condition_t condition, const char *loc_name)
21811767SAnurag.Maskey@Sun.COM {
21911767SAnurag.Maskey@Sun.COM nwam_loc_handle_t loch;
22011767SAnurag.Maskey@Sun.COM char *real_name;
22111767SAnurag.Maskey@Sun.COM boolean_t rv;
22211767SAnurag.Maskey@Sun.COM
22311767SAnurag.Maskey@Sun.COM /* names are case-insensitive, so get real name from libnwam */
22411767SAnurag.Maskey@Sun.COM if (nwam_loc_read(loc_name, 0, &loch) != NWAM_SUCCESS)
22511767SAnurag.Maskey@Sun.COM return (B_FALSE);
22611767SAnurag.Maskey@Sun.COM if (nwam_loc_get_name(loch, &real_name) != NWAM_SUCCESS) {
22711767SAnurag.Maskey@Sun.COM nwam_loc_free(loch);
22811767SAnurag.Maskey@Sun.COM return (B_FALSE);
22911767SAnurag.Maskey@Sun.COM }
23011767SAnurag.Maskey@Sun.COM nwam_loc_free(loch);
23111767SAnurag.Maskey@Sun.COM
23211767SAnurag.Maskey@Sun.COM rv = test_condition_object_state(condition, NWAM_OBJECT_TYPE_LOC,
23311767SAnurag.Maskey@Sun.COM real_name);
23411767SAnurag.Maskey@Sun.COM free(real_name);
23511767SAnurag.Maskey@Sun.COM return (rv);
23611767SAnurag.Maskey@Sun.COM }
23711767SAnurag.Maskey@Sun.COM
23811767SAnurag.Maskey@Sun.COM static boolean_t
test_condition_domain(nwam_condition_t condition,const char * target_domain,const char * found_domain)23911767SAnurag.Maskey@Sun.COM test_condition_domain(nwam_condition_t condition, const char *target_domain,
24011767SAnurag.Maskey@Sun.COM const char *found_domain)
24111767SAnurag.Maskey@Sun.COM {
24211767SAnurag.Maskey@Sun.COM int i, len_t, len_f;
24311767SAnurag.Maskey@Sun.COM char target[MAXHOSTNAMELEN], found[MAXHOSTNAMELEN];
24411767SAnurag.Maskey@Sun.COM
24511767SAnurag.Maskey@Sun.COM len_t = target_domain == NULL ? 0 : strlen(target_domain);
24611767SAnurag.Maskey@Sun.COM len_f = found_domain == NULL ? 0 : strlen(found_domain);
24711767SAnurag.Maskey@Sun.COM
24811767SAnurag.Maskey@Sun.COM /* convert target_domain and found_domain to lowercase for strstr() */
24911767SAnurag.Maskey@Sun.COM for (i = 0; i < len_t; i++)
25011767SAnurag.Maskey@Sun.COM target[i] = tolower(target_domain[i]);
25111767SAnurag.Maskey@Sun.COM target[len_t] = '\0';
25211767SAnurag.Maskey@Sun.COM
25311767SAnurag.Maskey@Sun.COM for (i = 0; i < len_f; i++)
25411767SAnurag.Maskey@Sun.COM found[i] = tolower(found_domain[i]);
25511767SAnurag.Maskey@Sun.COM found[len_f] = '\0';
25611767SAnurag.Maskey@Sun.COM
25711767SAnurag.Maskey@Sun.COM switch (condition) {
25811767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_IS:
25911767SAnurag.Maskey@Sun.COM return (found_domain != NULL && strcmp(found, target) == 0);
26011767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_IS_NOT:
26111767SAnurag.Maskey@Sun.COM return (found_domain == NULL || strcmp(found, target) != 0);
26211767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_CONTAINS:
26311767SAnurag.Maskey@Sun.COM return (found_domain != NULL && strstr(found, target) != NULL);
26411767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_DOES_NOT_CONTAIN:
26511767SAnurag.Maskey@Sun.COM return (found_domain == NULL || strstr(found, target) == NULL);
26611767SAnurag.Maskey@Sun.COM default:
26711767SAnurag.Maskey@Sun.COM return (B_FALSE);
26811767SAnurag.Maskey@Sun.COM }
26911767SAnurag.Maskey@Sun.COM }
27011767SAnurag.Maskey@Sun.COM
27111767SAnurag.Maskey@Sun.COM struct ncu_adv_domains {
27211767SAnurag.Maskey@Sun.COM struct ncu_adv_domains *next;
27311767SAnurag.Maskey@Sun.COM char *dns_domain;
27411767SAnurag.Maskey@Sun.COM char *nis_domain;
27511767SAnurag.Maskey@Sun.COM };
27611767SAnurag.Maskey@Sun.COM
27711767SAnurag.Maskey@Sun.COM static int
get_adv_domains(nwamd_object_t obj,void * arg)27811767SAnurag.Maskey@Sun.COM get_adv_domains(nwamd_object_t obj, void *arg)
27911767SAnurag.Maskey@Sun.COM {
28011767SAnurag.Maskey@Sun.COM nwamd_ncu_t *ncu = (nwamd_ncu_t *)obj->nwamd_object_data;
28111767SAnurag.Maskey@Sun.COM struct ncu_adv_domains **headpp = (struct ncu_adv_domains **)arg;
28211767SAnurag.Maskey@Sun.COM struct ncu_adv_domains *adp;
28311767SAnurag.Maskey@Sun.COM char *dns, *nis;
28411767SAnurag.Maskey@Sun.COM
28511767SAnurag.Maskey@Sun.COM if (ncu->ncu_type != NWAM_NCU_TYPE_INTERFACE)
28611767SAnurag.Maskey@Sun.COM return (0);
28711767SAnurag.Maskey@Sun.COM
28811767SAnurag.Maskey@Sun.COM dns = nwamd_get_dhcpinfo_data("DNSdmain", ncu->ncu_name);
28911767SAnurag.Maskey@Sun.COM nis = nwamd_get_dhcpinfo_data("NISdmain", ncu->ncu_name);
29011767SAnurag.Maskey@Sun.COM
29111767SAnurag.Maskey@Sun.COM if (dns != NULL || nis != NULL) {
29211767SAnurag.Maskey@Sun.COM adp = (struct ncu_adv_domains *)malloc(sizeof (*adp));
29311767SAnurag.Maskey@Sun.COM if (adp == NULL)
29411767SAnurag.Maskey@Sun.COM return (1);
29511767SAnurag.Maskey@Sun.COM adp->dns_domain = dns;
29611767SAnurag.Maskey@Sun.COM adp->nis_domain = nis;
29711767SAnurag.Maskey@Sun.COM adp->next = *headpp;
29811767SAnurag.Maskey@Sun.COM *headpp = adp;
29911767SAnurag.Maskey@Sun.COM }
30011767SAnurag.Maskey@Sun.COM
30111767SAnurag.Maskey@Sun.COM return (0);
30211767SAnurag.Maskey@Sun.COM }
30311767SAnurag.Maskey@Sun.COM
30411767SAnurag.Maskey@Sun.COM static boolean_t
test_condition_sys_domain(nwam_condition_t condition,const char * domainname)30511767SAnurag.Maskey@Sun.COM test_condition_sys_domain(nwam_condition_t condition, const char *domainname)
30611767SAnurag.Maskey@Sun.COM {
30711767SAnurag.Maskey@Sun.COM char cur_domainname[MAXHOSTNAMELEN];
30811767SAnurag.Maskey@Sun.COM
30911767SAnurag.Maskey@Sun.COM if (getdomainname(cur_domainname, MAXHOSTNAMELEN) != 0)
31011767SAnurag.Maskey@Sun.COM return (B_FALSE);
31111767SAnurag.Maskey@Sun.COM
31211767SAnurag.Maskey@Sun.COM return (test_condition_domain(condition, domainname, cur_domainname));
31311767SAnurag.Maskey@Sun.COM }
31411767SAnurag.Maskey@Sun.COM
31511767SAnurag.Maskey@Sun.COM static boolean_t
test_condition_adv_domain(nwam_condition_t condition,const char * domainname)31611767SAnurag.Maskey@Sun.COM test_condition_adv_domain(nwam_condition_t condition, const char *domainname)
31711767SAnurag.Maskey@Sun.COM {
31811767SAnurag.Maskey@Sun.COM struct ncu_adv_domains *adv_domains = NULL;
31911767SAnurag.Maskey@Sun.COM struct ncu_adv_domains *adp, *prev;
32011767SAnurag.Maskey@Sun.COM boolean_t positive, rtn;
32111767SAnurag.Maskey@Sun.COM
32211767SAnurag.Maskey@Sun.COM (void) nwamd_walk_objects(NWAM_OBJECT_TYPE_NCU, get_adv_domains,
32311767SAnurag.Maskey@Sun.COM &adv_domains);
32411767SAnurag.Maskey@Sun.COM
32511767SAnurag.Maskey@Sun.COM positive = (condition == NWAM_CONDITION_IS ||
32611767SAnurag.Maskey@Sun.COM condition == NWAM_CONDITION_CONTAINS);
32711767SAnurag.Maskey@Sun.COM
32811767SAnurag.Maskey@Sun.COM /*
32911767SAnurag.Maskey@Sun.COM * Walk the advertised domain list. Our test function tests one
33011767SAnurag.Maskey@Sun.COM * single domain, but we're dealing with a list: if our condition
33111767SAnurag.Maskey@Sun.COM * is positive ('is' or 'contains'), the test function for each
33211767SAnurag.Maskey@Sun.COM * domain results are or'd together; if our condition is negative
33311767SAnurag.Maskey@Sun.COM * ('is-not' or 'does-not-contain'), the test function results must
33411767SAnurag.Maskey@Sun.COM * be and'd. Thus our short-circuit exit value depends on our
33511767SAnurag.Maskey@Sun.COM * condition: if the test function returns TRUE it implies immediate
33611767SAnurag.Maskey@Sun.COM * success for a positive condition; if it returns FALSE it implies
33711767SAnurag.Maskey@Sun.COM * immediate failure for a negative condition.
33811767SAnurag.Maskey@Sun.COM */
33911767SAnurag.Maskey@Sun.COM adp = adv_domains;
34011767SAnurag.Maskey@Sun.COM while (adp != NULL) {
34111767SAnurag.Maskey@Sun.COM if ((test_condition_domain(condition, domainname,
34211767SAnurag.Maskey@Sun.COM adp->dns_domain) == positive) ||
34311767SAnurag.Maskey@Sun.COM (test_condition_domain(condition, domainname,
34411767SAnurag.Maskey@Sun.COM adp->nis_domain) == positive)) {
34511767SAnurag.Maskey@Sun.COM rtn = positive;
34611767SAnurag.Maskey@Sun.COM break;
34711767SAnurag.Maskey@Sun.COM }
34811767SAnurag.Maskey@Sun.COM adp = adp->next;
34911767SAnurag.Maskey@Sun.COM }
35011767SAnurag.Maskey@Sun.COM if (adp == NULL) {
35111767SAnurag.Maskey@Sun.COM /*
35211767SAnurag.Maskey@Sun.COM * We did not short-circuit; we therefore failed if our
35311767SAnurag.Maskey@Sun.COM * condition was positive, and succeeded if our condition
35411767SAnurag.Maskey@Sun.COM * was negative.
35511767SAnurag.Maskey@Sun.COM */
35611767SAnurag.Maskey@Sun.COM rtn = !positive;
35711767SAnurag.Maskey@Sun.COM }
35811767SAnurag.Maskey@Sun.COM
35911767SAnurag.Maskey@Sun.COM /* now free the domain list */
36011767SAnurag.Maskey@Sun.COM adp = adv_domains;
36111767SAnurag.Maskey@Sun.COM while (adp != NULL) {
36211767SAnurag.Maskey@Sun.COM prev = adp;
36311767SAnurag.Maskey@Sun.COM adp = prev->next;
36411767SAnurag.Maskey@Sun.COM free(prev->dns_domain);
36511767SAnurag.Maskey@Sun.COM free(prev->nis_domain);
36611767SAnurag.Maskey@Sun.COM free(prev);
36711767SAnurag.Maskey@Sun.COM }
36811767SAnurag.Maskey@Sun.COM
36911767SAnurag.Maskey@Sun.COM return (rtn);
37011767SAnurag.Maskey@Sun.COM }
37111767SAnurag.Maskey@Sun.COM
37211767SAnurag.Maskey@Sun.COM /*
37311767SAnurag.Maskey@Sun.COM * Returns true if prefixlen bits of addr1 match prefixlen bits of addr2.
37411767SAnurag.Maskey@Sun.COM */
37511767SAnurag.Maskey@Sun.COM static boolean_t
prefixmatch(uchar_t * addr1,uchar_t * addr2,int prefixlen)37611767SAnurag.Maskey@Sun.COM prefixmatch(uchar_t *addr1, uchar_t *addr2, int prefixlen)
37711767SAnurag.Maskey@Sun.COM {
37811767SAnurag.Maskey@Sun.COM uchar_t mask[IPV6_ABITS/8];
37911767SAnurag.Maskey@Sun.COM int i, j = 0;
38011767SAnurag.Maskey@Sun.COM
38111767SAnurag.Maskey@Sun.COM if (prefixlen == 0)
38211767SAnurag.Maskey@Sun.COM return (B_TRUE);
38311767SAnurag.Maskey@Sun.COM
38411767SAnurag.Maskey@Sun.COM while (prefixlen > 0) {
38511767SAnurag.Maskey@Sun.COM if (prefixlen >= 8) {
38611767SAnurag.Maskey@Sun.COM mask[j++] = 0xFF;
38711767SAnurag.Maskey@Sun.COM prefixlen -= 8;
38811767SAnurag.Maskey@Sun.COM } else {
38911767SAnurag.Maskey@Sun.COM mask[j] |= 1 << (8 - prefixlen);
39011767SAnurag.Maskey@Sun.COM prefixlen--;
39111767SAnurag.Maskey@Sun.COM }
39211767SAnurag.Maskey@Sun.COM }
39311767SAnurag.Maskey@Sun.COM /* Ensure at least one byte is tested */
39411767SAnurag.Maskey@Sun.COM if (j == 0) j++;
39511767SAnurag.Maskey@Sun.COM
39611767SAnurag.Maskey@Sun.COM for (i = 0; i < j; i++) {
39711767SAnurag.Maskey@Sun.COM if ((addr1[i] & mask[i]) != (addr2[i] & mask[i]))
39811767SAnurag.Maskey@Sun.COM return (B_FALSE);
39911767SAnurag.Maskey@Sun.COM }
40011767SAnurag.Maskey@Sun.COM return (B_TRUE);
40111767SAnurag.Maskey@Sun.COM }
40211767SAnurag.Maskey@Sun.COM
40312576SAnurag.Maskey@Oracle.COM /*
40412576SAnurag.Maskey@Oracle.COM * Given a string representation of an IPv4 or IPv6 address returns the
40512576SAnurag.Maskey@Oracle.COM * sockaddr representation. Note that 'sockaddr' should point at the correct
40612576SAnurag.Maskey@Oracle.COM * sockaddr structure for the address family (sockaddr_in for AF_INET or
40712576SAnurag.Maskey@Oracle.COM * sockaddr_in6 for AF_INET6) or alternatively at a sockaddr_storage
40812576SAnurag.Maskey@Oracle.COM * structure.
40912576SAnurag.Maskey@Oracle.COM */
41012576SAnurag.Maskey@Oracle.COM static struct sockaddr_storage *
nwamd_str2sockaddr(sa_family_t af,const char * straddr,struct sockaddr_storage * addr)41112576SAnurag.Maskey@Oracle.COM nwamd_str2sockaddr(sa_family_t af, const char *straddr,
41212576SAnurag.Maskey@Oracle.COM struct sockaddr_storage *addr)
41312576SAnurag.Maskey@Oracle.COM {
41412576SAnurag.Maskey@Oracle.COM struct sockaddr_in *sin;
41512576SAnurag.Maskey@Oracle.COM struct sockaddr_in6 *sin6;
41612576SAnurag.Maskey@Oracle.COM int err;
41712576SAnurag.Maskey@Oracle.COM
41812576SAnurag.Maskey@Oracle.COM if (af == AF_INET) {
41912576SAnurag.Maskey@Oracle.COM sin = (struct sockaddr_in *)addr;
42012576SAnurag.Maskey@Oracle.COM sin->sin_family = AF_INET;
42112576SAnurag.Maskey@Oracle.COM err = inet_pton(AF_INET, straddr, &sin->sin_addr);
42212576SAnurag.Maskey@Oracle.COM } else if (af == AF_INET6) {
42312576SAnurag.Maskey@Oracle.COM sin6 = (struct sockaddr_in6 *)addr;
42412576SAnurag.Maskey@Oracle.COM sin6->sin6_family = AF_INET6;
42512576SAnurag.Maskey@Oracle.COM err = inet_pton(AF_INET6, straddr, &sin6->sin6_addr);
42612576SAnurag.Maskey@Oracle.COM } else {
42712576SAnurag.Maskey@Oracle.COM errno = EINVAL;
42812576SAnurag.Maskey@Oracle.COM return (NULL);
42912576SAnurag.Maskey@Oracle.COM }
43012576SAnurag.Maskey@Oracle.COM return (err == 1 ? addr : NULL);
43112576SAnurag.Maskey@Oracle.COM }
43212576SAnurag.Maskey@Oracle.COM
43311767SAnurag.Maskey@Sun.COM struct nwamd_ipaddr_condition_walk_arg {
43411767SAnurag.Maskey@Sun.COM nwam_condition_t condition;
43511767SAnurag.Maskey@Sun.COM struct sockaddr_storage sockaddr;
43611767SAnurag.Maskey@Sun.COM int prefixlen;
43711767SAnurag.Maskey@Sun.COM boolean_t res;
43811767SAnurag.Maskey@Sun.COM };
43911767SAnurag.Maskey@Sun.COM
44011767SAnurag.Maskey@Sun.COM static int
check_ipaddr(sa_family_t family,struct ifaddrs * ifa,void * arg)44112576SAnurag.Maskey@Oracle.COM check_ipaddr(sa_family_t family, struct ifaddrs *ifa, void *arg)
44211767SAnurag.Maskey@Sun.COM {
44311767SAnurag.Maskey@Sun.COM struct nwamd_ipaddr_condition_walk_arg *wa = arg;
444*12805SDarren.Reed@Oracle.COM struct sockaddr_in6 addr6;
445*12805SDarren.Reed@Oracle.COM struct sockaddr_in addr;
44611767SAnurag.Maskey@Sun.COM boolean_t match = B_FALSE;
44711767SAnurag.Maskey@Sun.COM uchar_t *addr1, *addr2;
44811767SAnurag.Maskey@Sun.COM
44912576SAnurag.Maskey@Oracle.COM if (family == AF_INET) {
450*12805SDarren.Reed@Oracle.COM (void) memcpy(&addr, ifa->ifa_addr, sizeof (addr));
451*12805SDarren.Reed@Oracle.COM addr1 = (uchar_t *)(&addr.sin_addr.s_addr);
45211767SAnurag.Maskey@Sun.COM addr2 = (uchar_t *)&(((struct sockaddr_in *)
45311767SAnurag.Maskey@Sun.COM &(wa->sockaddr))->sin_addr.s_addr);
45411767SAnurag.Maskey@Sun.COM } else {
455*12805SDarren.Reed@Oracle.COM (void) memcpy(&addr6, ifa->ifa_addr, sizeof (addr6));
456*12805SDarren.Reed@Oracle.COM addr1 = (uchar_t *)(&addr6.sin6_addr.s6_addr);
45711767SAnurag.Maskey@Sun.COM addr2 = (uchar_t *)&(((struct sockaddr_in6 *)
45811767SAnurag.Maskey@Sun.COM &(wa->sockaddr))->sin6_addr.s6_addr);
45911767SAnurag.Maskey@Sun.COM }
46011767SAnurag.Maskey@Sun.COM
46111767SAnurag.Maskey@Sun.COM match = prefixmatch(addr1, addr2, wa->prefixlen);
46211767SAnurag.Maskey@Sun.COM
46311767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "check_ipaddr: match %d\n", match);
46411767SAnurag.Maskey@Sun.COM switch (wa->condition) {
46511767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_IS:
46611767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_IS_IN_RANGE:
46711767SAnurag.Maskey@Sun.COM wa->res = match;
46811767SAnurag.Maskey@Sun.COM if (match)
46911767SAnurag.Maskey@Sun.COM return (1);
47011767SAnurag.Maskey@Sun.COM return (0);
47111767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_IS_NOT:
47211767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_IS_NOT_IN_RANGE:
47311767SAnurag.Maskey@Sun.COM wa->res = !match;
47411767SAnurag.Maskey@Sun.COM return (0);
47511767SAnurag.Maskey@Sun.COM default:
47611767SAnurag.Maskey@Sun.COM return (0);
47711767SAnurag.Maskey@Sun.COM }
47811767SAnurag.Maskey@Sun.COM }
47911767SAnurag.Maskey@Sun.COM
48011767SAnurag.Maskey@Sun.COM static boolean_t
test_condition_ip_address(nwam_condition_t condition,const char * ip_address_string)48111767SAnurag.Maskey@Sun.COM test_condition_ip_address(nwam_condition_t condition,
48211767SAnurag.Maskey@Sun.COM const char *ip_address_string)
48311767SAnurag.Maskey@Sun.COM {
48412576SAnurag.Maskey@Oracle.COM sa_family_t family;
48511767SAnurag.Maskey@Sun.COM char *copy, *ip_address, *prefixlen_string, *lasts;
48611767SAnurag.Maskey@Sun.COM struct nwamd_ipaddr_condition_walk_arg wa;
48712576SAnurag.Maskey@Oracle.COM struct ifaddrs *ifap, *ifa;
48811767SAnurag.Maskey@Sun.COM
48911767SAnurag.Maskey@Sun.COM if ((copy = strdup(ip_address_string)) == NULL)
49011767SAnurag.Maskey@Sun.COM return (B_FALSE);
49111767SAnurag.Maskey@Sun.COM
49211767SAnurag.Maskey@Sun.COM if ((ip_address = strtok_r(copy, " \t/", &lasts)) == NULL) {
49311767SAnurag.Maskey@Sun.COM free(copy);
49411767SAnurag.Maskey@Sun.COM return (B_FALSE);
49511767SAnurag.Maskey@Sun.COM }
49611767SAnurag.Maskey@Sun.COM
49711767SAnurag.Maskey@Sun.COM prefixlen_string = strtok_r(NULL, " \t", &lasts);
49811767SAnurag.Maskey@Sun.COM
49912576SAnurag.Maskey@Oracle.COM if (nwamd_str2sockaddr(AF_INET, ip_address, &wa.sockaddr) != NULL) {
50012576SAnurag.Maskey@Oracle.COM family = AF_INET;
50111767SAnurag.Maskey@Sun.COM wa.prefixlen = IP_ABITS;
50212576SAnurag.Maskey@Oracle.COM } else if (nwamd_str2sockaddr(AF_INET6, ip_address, &wa.sockaddr)
50312576SAnurag.Maskey@Oracle.COM != NULL) {
50412576SAnurag.Maskey@Oracle.COM family = AF_INET6;
50511767SAnurag.Maskey@Sun.COM wa.prefixlen = IPV6_ABITS;
50611767SAnurag.Maskey@Sun.COM } else {
50711767SAnurag.Maskey@Sun.COM nlog(LOG_ERR, "test_condition_ip_address: "
50812576SAnurag.Maskey@Oracle.COM "nwamd_str2sockaddr failed for %s: %s", ip_address,
50912576SAnurag.Maskey@Oracle.COM strerror(errno));
51011767SAnurag.Maskey@Sun.COM free(copy);
51111767SAnurag.Maskey@Sun.COM return (B_FALSE);
51211767SAnurag.Maskey@Sun.COM }
51311767SAnurag.Maskey@Sun.COM
51411767SAnurag.Maskey@Sun.COM if (prefixlen_string != NULL)
51511767SAnurag.Maskey@Sun.COM wa.prefixlen = atoi(prefixlen_string);
51611767SAnurag.Maskey@Sun.COM
51711767SAnurag.Maskey@Sun.COM wa.condition = condition;
51811767SAnurag.Maskey@Sun.COM
51911767SAnurag.Maskey@Sun.COM switch (condition) {
52011767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_IS:
52111767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_IS_IN_RANGE:
52211767SAnurag.Maskey@Sun.COM wa.res = B_FALSE;
52311767SAnurag.Maskey@Sun.COM break;
52411767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_IS_NOT:
52511767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_IS_NOT_IN_RANGE:
52611767SAnurag.Maskey@Sun.COM wa.res = B_TRUE;
52711767SAnurag.Maskey@Sun.COM break;
52811767SAnurag.Maskey@Sun.COM default:
52911767SAnurag.Maskey@Sun.COM free(copy);
53011767SAnurag.Maskey@Sun.COM return (B_FALSE);
53111767SAnurag.Maskey@Sun.COM }
53212576SAnurag.Maskey@Oracle.COM free(copy);
53311767SAnurag.Maskey@Sun.COM
53412576SAnurag.Maskey@Oracle.COM if (getifaddrs(&ifa) == -1) {
53512576SAnurag.Maskey@Oracle.COM nlog(LOG_ERR, "test_condition_ip_address: "
53612576SAnurag.Maskey@Oracle.COM "getifaddrs failed: %s", strerror(errno));
53712576SAnurag.Maskey@Oracle.COM return (wa.res);
53812576SAnurag.Maskey@Oracle.COM }
53912576SAnurag.Maskey@Oracle.COM for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) {
540*12805SDarren.Reed@Oracle.COM if (ifap->ifa_addr->sa_family != family)
54112576SAnurag.Maskey@Oracle.COM continue;
54212576SAnurag.Maskey@Oracle.COM if (check_ipaddr(family, ifap, &wa) == 1)
54312576SAnurag.Maskey@Oracle.COM break;
54412576SAnurag.Maskey@Oracle.COM }
54512576SAnurag.Maskey@Oracle.COM freeifaddrs(ifa);
54611767SAnurag.Maskey@Sun.COM
54711767SAnurag.Maskey@Sun.COM return (wa.res);
54811767SAnurag.Maskey@Sun.COM }
54911767SAnurag.Maskey@Sun.COM
55011767SAnurag.Maskey@Sun.COM struct nwamd_wlan_condition_walk_arg {
55111767SAnurag.Maskey@Sun.COM nwam_condition_t condition;
55211767SAnurag.Maskey@Sun.COM const char *exp_essid;
55311767SAnurag.Maskey@Sun.COM const char *exp_bssid;
55411767SAnurag.Maskey@Sun.COM uint_t num_connected;
55511767SAnurag.Maskey@Sun.COM boolean_t res;
55611767SAnurag.Maskey@Sun.COM };
55711767SAnurag.Maskey@Sun.COM
55811767SAnurag.Maskey@Sun.COM static int
check_wlan(const char * linkname,void * arg)55911767SAnurag.Maskey@Sun.COM check_wlan(const char *linkname, void *arg)
56011767SAnurag.Maskey@Sun.COM {
56111767SAnurag.Maskey@Sun.COM struct nwamd_wlan_condition_walk_arg *wa = arg;
56211767SAnurag.Maskey@Sun.COM datalink_id_t linkid;
56311767SAnurag.Maskey@Sun.COM dladm_wlan_linkattr_t attr;
56411767SAnurag.Maskey@Sun.COM dladm_status_t status;
56511767SAnurag.Maskey@Sun.COM char cur_essid[DLADM_STRSIZE];
56611767SAnurag.Maskey@Sun.COM char cur_bssid[DLADM_STRSIZE];
56711767SAnurag.Maskey@Sun.COM char errmsg[DLADM_STRSIZE];
56811767SAnurag.Maskey@Sun.COM
56911767SAnurag.Maskey@Sun.COM if ((status = dladm_name2info(dld_handle, linkname, &linkid, NULL, NULL,
57011767SAnurag.Maskey@Sun.COM NULL)) != DLADM_STATUS_OK) {
57111767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "check_wlan: dladm_name2info() for %s "
57211767SAnurag.Maskey@Sun.COM "failed: %s", linkname,
57311767SAnurag.Maskey@Sun.COM dladm_status2str(status, errmsg));
57411767SAnurag.Maskey@Sun.COM return (DLADM_WALK_CONTINUE);
57511767SAnurag.Maskey@Sun.COM }
57611767SAnurag.Maskey@Sun.COM
57711767SAnurag.Maskey@Sun.COM status = dladm_wlan_get_linkattr(dld_handle, linkid, &attr);
57811767SAnurag.Maskey@Sun.COM if (status != DLADM_STATUS_OK) {
57911767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "check_wlan: dladm_wlan_get_linkattr() for %s "
58011767SAnurag.Maskey@Sun.COM "failed: %s", linkname,
58111767SAnurag.Maskey@Sun.COM dladm_status2str(status, errmsg));
58211767SAnurag.Maskey@Sun.COM return (DLADM_WALK_CONTINUE);
58311767SAnurag.Maskey@Sun.COM }
58411767SAnurag.Maskey@Sun.COM if (attr.la_status == DLADM_WLAN_LINK_DISCONNECTED)
58511767SAnurag.Maskey@Sun.COM return (DLADM_WALK_TERMINATE);
58611767SAnurag.Maskey@Sun.COM
58711767SAnurag.Maskey@Sun.COM wa->num_connected++;
58811767SAnurag.Maskey@Sun.COM
58911767SAnurag.Maskey@Sun.COM if (wa->exp_essid != NULL) {
59011767SAnurag.Maskey@Sun.COM /* Is the NIC associated with the expected access point? */
59111767SAnurag.Maskey@Sun.COM (void) dladm_wlan_essid2str(&attr.la_wlan_attr.wa_essid,
59211767SAnurag.Maskey@Sun.COM cur_essid);
59311767SAnurag.Maskey@Sun.COM switch (wa->condition) {
59411767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_IS:
59511767SAnurag.Maskey@Sun.COM wa->res = strcmp(cur_essid, wa->exp_essid) == 0;
59611767SAnurag.Maskey@Sun.COM if (wa->res)
59711767SAnurag.Maskey@Sun.COM return (DLADM_WALK_TERMINATE);
59811767SAnurag.Maskey@Sun.COM break;
59911767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_IS_NOT:
60011767SAnurag.Maskey@Sun.COM wa->res = strcmp(cur_essid, wa->exp_essid) != 0;
60111767SAnurag.Maskey@Sun.COM if (!wa->res)
60211767SAnurag.Maskey@Sun.COM return (DLADM_WALK_TERMINATE);
60311767SAnurag.Maskey@Sun.COM break;
60411767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_CONTAINS:
60511767SAnurag.Maskey@Sun.COM wa->res = strstr(cur_essid, wa->exp_essid) != NULL;
60611767SAnurag.Maskey@Sun.COM if (wa->res)
60711767SAnurag.Maskey@Sun.COM return (DLADM_WALK_TERMINATE);
60811767SAnurag.Maskey@Sun.COM break;
60911767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_DOES_NOT_CONTAIN:
61011767SAnurag.Maskey@Sun.COM wa->res = strstr(cur_essid, wa->exp_essid) == NULL;
61111767SAnurag.Maskey@Sun.COM if (!wa->res)
61211767SAnurag.Maskey@Sun.COM return (DLADM_WALK_TERMINATE);
61311767SAnurag.Maskey@Sun.COM break;
61411767SAnurag.Maskey@Sun.COM default:
61511767SAnurag.Maskey@Sun.COM return (DLADM_WALK_TERMINATE);
61611767SAnurag.Maskey@Sun.COM }
61711767SAnurag.Maskey@Sun.COM return (DLADM_WALK_CONTINUE);
61811767SAnurag.Maskey@Sun.COM }
61911767SAnurag.Maskey@Sun.COM if (wa->exp_bssid != NULL) {
62011767SAnurag.Maskey@Sun.COM /* Is the NIC associated with the expected access point? */
62111767SAnurag.Maskey@Sun.COM (void) dladm_wlan_bssid2str(&attr.la_wlan_attr.wa_bssid,
62211767SAnurag.Maskey@Sun.COM cur_bssid);
62311767SAnurag.Maskey@Sun.COM switch (wa->condition) {
62411767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_IS:
62511767SAnurag.Maskey@Sun.COM wa->res = strcmp(cur_bssid, wa->exp_bssid) == 0;
62611767SAnurag.Maskey@Sun.COM if (wa->res)
62711767SAnurag.Maskey@Sun.COM return (DLADM_WALK_TERMINATE);
62811767SAnurag.Maskey@Sun.COM break;
62911767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_IS_NOT:
63011767SAnurag.Maskey@Sun.COM wa->res = strcmp(cur_bssid, wa->exp_bssid) != 0;
63111767SAnurag.Maskey@Sun.COM if (!wa->res)
63211767SAnurag.Maskey@Sun.COM return (DLADM_WALK_TERMINATE);
63311767SAnurag.Maskey@Sun.COM break;
63411767SAnurag.Maskey@Sun.COM default:
63511767SAnurag.Maskey@Sun.COM return (DLADM_WALK_TERMINATE);
63611767SAnurag.Maskey@Sun.COM }
63711767SAnurag.Maskey@Sun.COM return (DLADM_WALK_CONTINUE);
63811767SAnurag.Maskey@Sun.COM }
63911767SAnurag.Maskey@Sun.COM /*
64011767SAnurag.Maskey@Sun.COM * Neither an ESSID or BSSID match is required - being connected to a
64111767SAnurag.Maskey@Sun.COM * WLAN is enough.
64211767SAnurag.Maskey@Sun.COM */
64311767SAnurag.Maskey@Sun.COM switch (wa->condition) {
64411767SAnurag.Maskey@Sun.COM case NWAM_CONDITION_IS:
64511767SAnurag.Maskey@Sun.COM wa->res = B_TRUE;
64611767SAnurag.Maskey@Sun.COM return (DLADM_WALK_TERMINATE);
64711767SAnurag.Maskey@Sun.COM default:
64811767SAnurag.Maskey@Sun.COM wa->res = B_FALSE;
64911767SAnurag.Maskey@Sun.COM return (DLADM_WALK_TERMINATE);
65011767SAnurag.Maskey@Sun.COM }
65111767SAnurag.Maskey@Sun.COM /*NOTREACHED*/
65211767SAnurag.Maskey@Sun.COM return (DLADM_WALK_CONTINUE);
65311767SAnurag.Maskey@Sun.COM }
65411767SAnurag.Maskey@Sun.COM
65511767SAnurag.Maskey@Sun.COM static boolean_t
test_condition_wireless_essid(nwam_condition_t condition,const char * essid)65611767SAnurag.Maskey@Sun.COM test_condition_wireless_essid(nwam_condition_t condition,
65711767SAnurag.Maskey@Sun.COM const char *essid)
65811767SAnurag.Maskey@Sun.COM {
65911767SAnurag.Maskey@Sun.COM struct nwamd_wlan_condition_walk_arg wa;
66011767SAnurag.Maskey@Sun.COM
66111767SAnurag.Maskey@Sun.COM wa.condition = condition;
66211767SAnurag.Maskey@Sun.COM wa.exp_essid = essid;
66311767SAnurag.Maskey@Sun.COM wa.exp_bssid = NULL;
66411767SAnurag.Maskey@Sun.COM wa.num_connected = 0;
66511767SAnurag.Maskey@Sun.COM wa.res = B_FALSE;
66611767SAnurag.Maskey@Sun.COM
66711767SAnurag.Maskey@Sun.COM (void) dladm_walk(check_wlan, dld_handle, &wa, DATALINK_CLASS_PHYS,
66811767SAnurag.Maskey@Sun.COM DL_WIFI, DLADM_OPT_ACTIVE);
66911767SAnurag.Maskey@Sun.COM
67011767SAnurag.Maskey@Sun.COM return (wa.num_connected > 0 && wa.res == B_TRUE);
67111767SAnurag.Maskey@Sun.COM }
67211767SAnurag.Maskey@Sun.COM
67311767SAnurag.Maskey@Sun.COM static boolean_t
test_condition_wireless_bssid(nwam_condition_t condition,const char * bssid)67411767SAnurag.Maskey@Sun.COM test_condition_wireless_bssid(nwam_condition_t condition,
67511767SAnurag.Maskey@Sun.COM const char *bssid)
67611767SAnurag.Maskey@Sun.COM {
67711767SAnurag.Maskey@Sun.COM struct nwamd_wlan_condition_walk_arg wa;
67811767SAnurag.Maskey@Sun.COM
67911767SAnurag.Maskey@Sun.COM wa.condition = condition;
68011767SAnurag.Maskey@Sun.COM wa.exp_bssid = bssid;
68111767SAnurag.Maskey@Sun.COM wa.exp_essid = NULL;
68211767SAnurag.Maskey@Sun.COM wa.num_connected = 0;
68311767SAnurag.Maskey@Sun.COM wa.res = B_FALSE;
68411767SAnurag.Maskey@Sun.COM
68511767SAnurag.Maskey@Sun.COM (void) dladm_walk(check_wlan, dld_handle, &wa, DATALINK_CLASS_PHYS,
68611767SAnurag.Maskey@Sun.COM DL_WIFI, DLADM_OPT_ACTIVE);
68711767SAnurag.Maskey@Sun.COM
68811767SAnurag.Maskey@Sun.COM return (wa.num_connected > 0 && wa.res == B_TRUE);
68911767SAnurag.Maskey@Sun.COM }
69011767SAnurag.Maskey@Sun.COM
69111767SAnurag.Maskey@Sun.COM /*
69211767SAnurag.Maskey@Sun.COM * This function takes an activation mode and a string representation of a
69311767SAnurag.Maskey@Sun.COM * condition and evaluates it.
69411767SAnurag.Maskey@Sun.COM */
69511767SAnurag.Maskey@Sun.COM boolean_t
nwamd_check_conditions(nwam_activation_mode_t activation_mode,char ** condition_strings,uint_t num_conditions)69611767SAnurag.Maskey@Sun.COM nwamd_check_conditions(nwam_activation_mode_t activation_mode,
69711767SAnurag.Maskey@Sun.COM char **condition_strings, uint_t num_conditions)
69811767SAnurag.Maskey@Sun.COM {
69911767SAnurag.Maskey@Sun.COM boolean_t ret;
70011767SAnurag.Maskey@Sun.COM nwam_condition_t condition;
70111767SAnurag.Maskey@Sun.COM nwam_condition_object_type_t object_type;
70211767SAnurag.Maskey@Sun.COM char *object_name;
70311767SAnurag.Maskey@Sun.COM int i, j;
70411767SAnurag.Maskey@Sun.COM
70511767SAnurag.Maskey@Sun.COM for (i = 0; i < num_conditions; i++) {
70611767SAnurag.Maskey@Sun.COM
70711767SAnurag.Maskey@Sun.COM if (nwam_condition_string_to_condition(condition_strings[i],
70811767SAnurag.Maskey@Sun.COM &object_type, &condition, &object_name) != NWAM_SUCCESS) {
70911767SAnurag.Maskey@Sun.COM nlog(LOG_ERR, "check_conditions: invalid condition %s",
71011767SAnurag.Maskey@Sun.COM condition_strings[i]);
71111767SAnurag.Maskey@Sun.COM return (B_FALSE);
71211767SAnurag.Maskey@Sun.COM }
71311767SAnurag.Maskey@Sun.COM ret = B_FALSE;
71411767SAnurag.Maskey@Sun.COM
71511767SAnurag.Maskey@Sun.COM for (j = 0; j < (sizeof (condition_map) /
71611767SAnurag.Maskey@Sun.COM sizeof (struct nwamd_condition_map)); j++) {
71711767SAnurag.Maskey@Sun.COM if (condition_map[j].object_type == object_type)
71811767SAnurag.Maskey@Sun.COM ret = condition_map[j].condition_func(condition,
71911767SAnurag.Maskey@Sun.COM object_name);
72011767SAnurag.Maskey@Sun.COM }
72111767SAnurag.Maskey@Sun.COM
72211767SAnurag.Maskey@Sun.COM free(object_name);
72311767SAnurag.Maskey@Sun.COM
72411767SAnurag.Maskey@Sun.COM if (activation_mode == NWAM_ACTIVATION_MODE_CONDITIONAL_ANY &&
72511767SAnurag.Maskey@Sun.COM ret) {
72611767SAnurag.Maskey@Sun.COM return (B_TRUE);
72711767SAnurag.Maskey@Sun.COM }
72811767SAnurag.Maskey@Sun.COM if (activation_mode == NWAM_ACTIVATION_MODE_CONDITIONAL_ALL &&
72911767SAnurag.Maskey@Sun.COM !ret) {
73011767SAnurag.Maskey@Sun.COM return (B_FALSE);
73111767SAnurag.Maskey@Sun.COM }
73211767SAnurag.Maskey@Sun.COM }
73311767SAnurag.Maskey@Sun.COM if (activation_mode == NWAM_ACTIVATION_MODE_CONDITIONAL_ANY && ret)
73411767SAnurag.Maskey@Sun.COM return (B_TRUE);
73511767SAnurag.Maskey@Sun.COM if (activation_mode == NWAM_ACTIVATION_MODE_CONDITIONAL_ALL && ret)
73611767SAnurag.Maskey@Sun.COM return (B_TRUE);
73711767SAnurag.Maskey@Sun.COM
73811767SAnurag.Maskey@Sun.COM return (B_FALSE);
73911767SAnurag.Maskey@Sun.COM }
74011767SAnurag.Maskey@Sun.COM
74111767SAnurag.Maskey@Sun.COM /*
74211767SAnurag.Maskey@Sun.COM * In rating activation conditions, we take the best-rated CONDITIONAL_ANY
74311767SAnurag.Maskey@Sun.COM * condition, or sum all the CONDITIONAL_ALL condition ratings. This allows
74411767SAnurag.Maskey@Sun.COM * us to compare between location activation conditions to pick the best.
74511767SAnurag.Maskey@Sun.COM */
74611767SAnurag.Maskey@Sun.COM uint64_t
nwamd_rate_conditions(nwam_activation_mode_t activation_mode,char ** conditions,uint_t num_conditions)74711767SAnurag.Maskey@Sun.COM nwamd_rate_conditions(nwam_activation_mode_t activation_mode,
74811767SAnurag.Maskey@Sun.COM char **conditions, uint_t num_conditions)
74911767SAnurag.Maskey@Sun.COM {
75011767SAnurag.Maskey@Sun.COM nwam_condition_t condition;
75111767SAnurag.Maskey@Sun.COM nwam_condition_object_type_t object_type;
75211767SAnurag.Maskey@Sun.COM char *object_name;
75311767SAnurag.Maskey@Sun.COM int i;
75411767SAnurag.Maskey@Sun.COM uint64_t rating = 0, total_rating = 0;
75511767SAnurag.Maskey@Sun.COM
75611767SAnurag.Maskey@Sun.COM for (i = 0; i < num_conditions; i++) {
75711767SAnurag.Maskey@Sun.COM
75811767SAnurag.Maskey@Sun.COM object_name = NULL;
75911767SAnurag.Maskey@Sun.COM if (nwam_condition_string_to_condition(conditions[i],
76011767SAnurag.Maskey@Sun.COM &object_type, &condition, &object_name) != NWAM_SUCCESS ||
76111767SAnurag.Maskey@Sun.COM nwam_condition_rate(object_type, condition, &rating)
76211767SAnurag.Maskey@Sun.COM != NWAM_SUCCESS) {
76311767SAnurag.Maskey@Sun.COM nlog(LOG_ERR, "nwamd_rate_conditions: could not rate "
76411767SAnurag.Maskey@Sun.COM "condition");
76511767SAnurag.Maskey@Sun.COM free(object_name);
76611767SAnurag.Maskey@Sun.COM return (0);
76711767SAnurag.Maskey@Sun.COM }
76811767SAnurag.Maskey@Sun.COM free(object_name);
76911767SAnurag.Maskey@Sun.COM
77011767SAnurag.Maskey@Sun.COM if (activation_mode == NWAM_ACTIVATION_MODE_CONDITIONAL_ANY) {
77111767SAnurag.Maskey@Sun.COM if (rating > total_rating)
77211767SAnurag.Maskey@Sun.COM total_rating = rating;
77311767SAnurag.Maskey@Sun.COM } else if (activation_mode ==
77411767SAnurag.Maskey@Sun.COM NWAM_ACTIVATION_MODE_CONDITIONAL_ALL) {
77511767SAnurag.Maskey@Sun.COM total_rating += rating;
77611767SAnurag.Maskey@Sun.COM }
77711767SAnurag.Maskey@Sun.COM }
77811767SAnurag.Maskey@Sun.COM return (total_rating);
77911767SAnurag.Maskey@Sun.COM }
78011767SAnurag.Maskey@Sun.COM
78111767SAnurag.Maskey@Sun.COM /*
78211767SAnurag.Maskey@Sun.COM * Different from nwamd_triggered_check_all_conditions() in that this
78311767SAnurag.Maskey@Sun.COM * function enqueues a timed check event.
78411767SAnurag.Maskey@Sun.COM */
78511767SAnurag.Maskey@Sun.COM void
nwamd_set_timed_check_all_conditions(void)78611767SAnurag.Maskey@Sun.COM nwamd_set_timed_check_all_conditions(void)
78711767SAnurag.Maskey@Sun.COM {
78811767SAnurag.Maskey@Sun.COM nwamd_event_t check_event = nwamd_event_init
78911767SAnurag.Maskey@Sun.COM (NWAM_EVENT_TYPE_TIMED_CHECK_CONDITIONS, NWAM_OBJECT_TYPE_UNKNOWN,
79011767SAnurag.Maskey@Sun.COM 0, NULL);
79111767SAnurag.Maskey@Sun.COM if (check_event != NULL) {
79211767SAnurag.Maskey@Sun.COM /* Add another timed event to recheck conditions */
79311767SAnurag.Maskey@Sun.COM nwamd_event_enqueue_timed(check_event,
79411767SAnurag.Maskey@Sun.COM condition_check_interval > CONDITION_CHECK_INTERVAL_MIN ?
79511767SAnurag.Maskey@Sun.COM condition_check_interval : CONDITION_CHECK_INTERVAL_MIN);
79611767SAnurag.Maskey@Sun.COM }
79711767SAnurag.Maskey@Sun.COM }
79811767SAnurag.Maskey@Sun.COM
79911767SAnurag.Maskey@Sun.COM /*
80011767SAnurag.Maskey@Sun.COM * Does not enqueue another check event.
80111767SAnurag.Maskey@Sun.COM */
80211767SAnurag.Maskey@Sun.COM void
nwamd_check_all_conditions(void)80311767SAnurag.Maskey@Sun.COM nwamd_check_all_conditions(void)
80411767SAnurag.Maskey@Sun.COM {
80511767SAnurag.Maskey@Sun.COM nwamd_enm_check_conditions();
80611767SAnurag.Maskey@Sun.COM nwamd_loc_check_conditions();
80711767SAnurag.Maskey@Sun.COM }
80811767SAnurag.Maskey@Sun.COM
80911767SAnurag.Maskey@Sun.COM void
nwamd_create_timed_condition_check_event(void)81011767SAnurag.Maskey@Sun.COM nwamd_create_timed_condition_check_event(void)
81111767SAnurag.Maskey@Sun.COM {
81211767SAnurag.Maskey@Sun.COM nwamd_event_t check_event = nwamd_event_init
81311767SAnurag.Maskey@Sun.COM (NWAM_EVENT_TYPE_TIMED_CHECK_CONDITIONS, NWAM_OBJECT_TYPE_UNKNOWN,
81411767SAnurag.Maskey@Sun.COM 0, NULL);
81511767SAnurag.Maskey@Sun.COM if (check_event != NULL)
81611767SAnurag.Maskey@Sun.COM nwamd_event_enqueue(check_event);
81711767SAnurag.Maskey@Sun.COM }
81811767SAnurag.Maskey@Sun.COM
81911767SAnurag.Maskey@Sun.COM void
nwamd_create_triggered_condition_check_event(uint32_t when)82011767SAnurag.Maskey@Sun.COM nwamd_create_triggered_condition_check_event(uint32_t when)
82111767SAnurag.Maskey@Sun.COM {
82211767SAnurag.Maskey@Sun.COM nwamd_event_t check_event;
82311767SAnurag.Maskey@Sun.COM
82411767SAnurag.Maskey@Sun.COM if (!nwamd_event_enqueued(NWAM_EVENT_TYPE_TRIGGERED_CHECK_CONDITIONS,
82511767SAnurag.Maskey@Sun.COM NWAM_OBJECT_TYPE_UNKNOWN, NULL)) {
82611767SAnurag.Maskey@Sun.COM check_event = nwamd_event_init
82711767SAnurag.Maskey@Sun.COM (NWAM_EVENT_TYPE_TRIGGERED_CHECK_CONDITIONS,
82811767SAnurag.Maskey@Sun.COM NWAM_OBJECT_TYPE_UNKNOWN, 0, NULL);
82911767SAnurag.Maskey@Sun.COM if (check_event != NULL)
83011767SAnurag.Maskey@Sun.COM nwamd_event_enqueue_timed(check_event, when);
83111767SAnurag.Maskey@Sun.COM }
83211767SAnurag.Maskey@Sun.COM }
833