6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * CDDL HEADER START
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * The contents of this file are subject to the terms of the
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Common Development and Distribution License (the "License").
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * You may not use this file except in compliance with the License.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * or http://www.opensolaris.org/os/licensing.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * See the License for the specific language governing permissions
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * and limitations under the License.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * When distributing Covered Code, include this CDDL HEADER in each
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * If applicable, add the following below this CDDL HEADER, with the
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * fields enclosed by brackets "[]" replaced with your own identifying
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * information: Portions Copyright [yyyy] [name of copyright owner]
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * CDDL HEADER END
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
83ca9a11d102397d8307c76d5b733133f9841464Anurag S. Maskey * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <assert.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <ctype.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <err.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <errno.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <execinfo.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <kstat.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <libdladm.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <libdllink.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <libdlstat.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <libdlwlan.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <libnwam.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <limits.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <pthread.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <stdio.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <stdlib.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <string.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <strings.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <sys/stat.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <sys/time.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <sys/types.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <unistd.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <libdlpi.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <ucontext.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include "events.h"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include "llp.h"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include "objects.h"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include "ncp.h"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include "ncu.h"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include "known_wlans.h"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include "util.h"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * ncu_phys.c - contains routines that are physical-link specific.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Mostly WiFi code.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Get link state from kstats. Used to determine initial link state for
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * cases where drivers do not support DL_NOTE_LINK_UP/DOWN. If link
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * state is LINK_STATE_UNKNOWN, we assume the link is up and the IP NCU
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * timeout will cause us to move on to other links.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeylink_state_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_get_link_state(const char *name)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey kstat_ctl_t *kcp;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey kstat_t *ksp;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char module[DLPI_LINKNAME_MAX];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uint_t instance;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link_state_t link_state = LINK_STATE_UNKNOWN;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((kcp = kstat_open()) == NULL)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (link_state);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (dlpi_parselink(name, module, &instance) != DLPI_SUCCESS)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto out;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((ksp = kstat_lookup(kcp, module, instance, "mac")) == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * The kstat query could fail if the underlying MAC
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * driver was already detached.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto out;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (kstat_read(kcp, ksp, NULL) == -1)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto out;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) dladm_kstat_value(ksp, "link_state", KSTAT_DATA_UINT32,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey &link_state);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyout:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) kstat_close(kcp);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (link_state);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Set/unset link propeties. At present, these are MAC address, link MTU and
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * autopush modules. We set MAC address last as setting it may cause a chip
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * reset which can prevent other device property setting succeeding.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_set_unset_link_properties(nwamd_ncu_t *ncu, boolean_t set)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey dlpi_handle_t dh = ncu->ncu_link.nwamd_link_dhp;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey char *addr = set ? ncu->ncu_link.nwamd_link_mac_addr : NULL;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey uint64_t mtu = set ? ncu->ncu_link.nwamd_link_mtu : 0;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey char **autopush = set ? ncu->ncu_link.nwamd_link_autopush : NULL;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey uint_t num_autopush = set ? ncu->ncu_link.nwamd_link_num_autopush : 0;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uchar_t *hwaddr = NULL, curraddr[DLPI_PHYSADDR_MAX];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey size_t hwaddrlen = DLPI_PHYSADDR_MAX;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int retval;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_status_t status;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char mtustr[DLADM_PROP_VAL_MAX];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char *cp;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char errmsg[DLADM_STRSIZE];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uint_t cnt = 1;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Set MTU here - either default value (if mtu == 0 indicating it has
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * not been set) or specified value.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (mtu == 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey cp = mtustr;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey status = dladm_get_linkprop(dld_handle,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ncu->ncu_link.nwamd_link_id, DLADM_PROP_VAL_DEFAULT, "mtu",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey &cp, &cnt);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (status != DLADM_STATUS_OK) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_set_unset_link_properties: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "dladm_get_linkprop failed: %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_status2str(status, errmsg));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) snprintf(mtustr, DLADM_PROP_VAL_MAX, "%lld", mtu);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey cp = mtustr;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_set_unset_link_properties: setting MTU of %s "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "for link %s", mtustr, ncu->ncu_name);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey status = dladm_set_linkprop(dld_handle, ncu->ncu_link.nwamd_link_id,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "mtu", &cp, 1, DLADM_OPT_ACTIVE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (status != DLADM_STATUS_OK) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_set_unset_link_properties: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "dladm_set_linkprop failed: %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_status2str(status, errmsg));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_set_unset_link_properties: setting %d "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "autopush module for link %s", num_autopush, ncu->ncu_name);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey status = dladm_set_linkprop(dld_handle, ncu->ncu_link.nwamd_link_id,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "autopush", autopush, num_autopush, DLADM_OPT_ACTIVE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (status != DLADM_STATUS_OK) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_set_unset_link_properties: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "dladm_set_linkprop failed for autopush property: %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_status2str(status, errmsg));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Set physical address - either factory (if link_mac_addr is NULL
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * or we are unsetting properties) or specified MAC address string.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (addr == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((hwaddr = calloc(1, DLPI_PHYSADDR_MAX)) == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "nwamd_set_unset_link_properties: malloc() failed");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((retval = dlpi_get_physaddr(dh, DL_FACT_PHYS_ADDR,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey hwaddr, &hwaddrlen)) != DLPI_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_set_unset_link_properties: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "could not get physical address for %s: %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu->ncu_name, dlpi_strerror(retval));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(hwaddr);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int addrlen = hwaddrlen;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((hwaddr = _link_aton(addr, &addrlen)) == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (addrlen == -1) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "nwamd_set_unset_link_properties: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "%s: bad address for %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey addr, ncu->ncu_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_set_unset_link_properties:"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey " malloc() failed");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey hwaddrlen = addrlen;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Only set physical address if desired address differs from current -
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * this avoids unnecessary chip resets for some drivers.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey retval = dlpi_get_physaddr(dh, DL_CURR_PHYS_ADDR, curraddr,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey &hwaddrlen);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (retval != DLPI_SUCCESS || bcmp(curraddr, hwaddr, hwaddrlen) != 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey retval = dlpi_set_physaddr(dh, DL_CURR_PHYS_ADDR, hwaddr,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey hwaddrlen);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (retval != DLPI_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_set_unset_link_properties:"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "failed setting mac address on %s: %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu->ncu_name, dlpi_strerror(retval));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(hwaddr);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#define WLAN_ENC(sec) \
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ((sec == DLADM_WLAN_SECMODE_WPA ? "WPA" : \
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (sec == DLADM_WLAN_SECMODE_WEP ? "WEP" : "none")))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#define NEED_ENC(sec) \
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (sec == DLADM_WLAN_SECMODE_WPA || sec == DLADM_WLAN_SECMODE_WEP)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#define WIRELESS_LAN_INIT_COUNT 8
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * The variable wireless_scan_level specifies the signal level
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * that we will initiate connections to previously-visited APs
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * at when we are in the connected state.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeydladm_wlan_strength_t wireless_scan_level = DLADM_WLAN_STRENGTH_WEAK;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * The variable wireless_scan_interval specifies how often the periodic
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * scan occurs.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyuint64_t wireless_scan_interval = WIRELESS_SCAN_INTERVAL_DEFAULT;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * The variable wireless_autoconf specifies if we use dladm_wlan_autoconf()
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * to connect.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyboolean_t wireless_autoconf = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * The variable wireless_strict_bssid specifies if we only connect
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * to WLANs with BSSIDs that we previously connected to.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyboolean_t wireless_strict_bssid = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * We need to ensure scan or connect threads do not run concurrently
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * on any links - otherwise we get radio interference. Acquire this
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * lock on entering scan/connect threads to prevent this.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeypthread_mutex_t wireless_mutex = PTHREAD_MUTEX_INITIALIZER;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyscanconnect_entry(void)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_mutex_lock(&wireless_mutex);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyscanconnect_exit(void)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_mutex_unlock(&wireless_mutex);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Below are functions used to handle storage/retrieval of keys
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * for a given WLAN. The keys are stored/retrieved using dladm_set_secobj()
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * and dladm_get_secobj().
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Convert key hexascii string to raw secobj value. This
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * code is very similar to convert_secobj() in dladm.c, it would
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * be good to have a libdladm function to convert values.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic int
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeykey_string_to_secobj_value(char *buf, uint8_t *obj_val, uint_t *obj_lenp,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_secobj_class_t class)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey size_t buf_len = strlen(buf);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "before: key_string_to_secobj_value: buf_len = %d",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey buf_len);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (buf_len == 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* length zero means "delete" */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (0);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (buf[buf_len - 1] == '\n')
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey buf[--buf_len] = '\0';
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "after: key_string_to_secobj_value: buf_len = %d",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey buf_len);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (class == DLADM_SECOBJ_CLASS_WPA) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Per IEEE802.11i spec, the Pre-shared key (PSK) length should
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * be between 8 and 63.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (buf_len < 8 || buf_len > 63) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "key_string_to_secobj_value:"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey " invalid WPA key length: buf_len = %d", buf_len);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (-1);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) memcpy(obj_val, buf, (uint_t)buf_len);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *obj_lenp = buf_len;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (0);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey switch (buf_len) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case 5: /* ASCII key sizes */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case 13:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) memcpy(obj_val, buf, (uint_t)buf_len);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *obj_lenp = (uint_t)buf_len;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case 10:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case 26: /* Hex key sizes, not preceded by 0x */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (hexascii_to_octet(buf, (uint_t)buf_len, obj_val, obj_lenp)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey != 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "key_string_to_secobj_value: invalid WEP key");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (-1);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case 12:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case 28: /* Hex key sizes, preceded by 0x */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (strncmp(buf, "0x", 2) != 0 ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey hexascii_to_octet(buf + 2, (uint_t)buf_len - 2, obj_val,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey obj_lenp) != 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "key_string_to_secobj_value: invalid WEP key");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (-1);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey default:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey syslog(LOG_ERR,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "key_string_to_secobj_value: invalid WEP key length");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (-1);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (0);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
c1976b8365310f23085adaa53cf00b14039014c8enricop/*
c1976b8365310f23085adaa53cf00b14039014c8enricop * Callback used on each known WLAN:
c1976b8365310f23085adaa53cf00b14039014c8enricop * return 1 if a secobj, linked with an existing kwown wlan, has the same name
c1976b8365310f23085adaa53cf00b14039014c8enricop * of the secobj that is being created.
c1976b8365310f23085adaa53cf00b14039014c8enricop */
c1976b8365310f23085adaa53cf00b14039014c8enricop
c1976b8365310f23085adaa53cf00b14039014c8enricopstatic int
c1976b8365310f23085adaa53cf00b14039014c8enricopfind_keyname_cb(nwam_known_wlan_handle_t kwh, void *new_keyname)
c1976b8365310f23085adaa53cf00b14039014c8enricop{
c1976b8365310f23085adaa53cf00b14039014c8enricop nwam_error_t err;
c1976b8365310f23085adaa53cf00b14039014c8enricop nwam_value_t old_key;
c1976b8365310f23085adaa53cf00b14039014c8enricop
c1976b8365310f23085adaa53cf00b14039014c8enricop char **old_keyname;
c1976b8365310f23085adaa53cf00b14039014c8enricop uint_t num_old_keyname, i;
c1976b8365310f23085adaa53cf00b14039014c8enricop
c1976b8365310f23085adaa53cf00b14039014c8enricop if ((err = nwam_known_wlan_get_prop_value(kwh,
c1976b8365310f23085adaa53cf00b14039014c8enricop NWAM_KNOWN_WLAN_PROP_KEYNAME, &old_key)) != NWAM_SUCCESS) {
c1976b8365310f23085adaa53cf00b14039014c8enricop nlog(LOG_ERR, "find_keyname_cb: nwam_known_wlan_get_prop: %s",
c1976b8365310f23085adaa53cf00b14039014c8enricop nwam_strerror(err));
c1976b8365310f23085adaa53cf00b14039014c8enricop return (0);
c1976b8365310f23085adaa53cf00b14039014c8enricop }
c1976b8365310f23085adaa53cf00b14039014c8enricop if ((err = nwam_value_get_string_array(old_key, &old_keyname,
c1976b8365310f23085adaa53cf00b14039014c8enricop &num_old_keyname))
c1976b8365310f23085adaa53cf00b14039014c8enricop != NWAM_SUCCESS) {
c1976b8365310f23085adaa53cf00b14039014c8enricop nlog(LOG_ERR, "find_keyname_cb: nwam_value_get_string: %s",
c1976b8365310f23085adaa53cf00b14039014c8enricop nwam_strerror(err));
c1976b8365310f23085adaa53cf00b14039014c8enricop nwam_value_free(old_key);
c1976b8365310f23085adaa53cf00b14039014c8enricop return (0);
c1976b8365310f23085adaa53cf00b14039014c8enricop }
c1976b8365310f23085adaa53cf00b14039014c8enricop nwam_value_free(old_key);
c1976b8365310f23085adaa53cf00b14039014c8enricop for (i = 0; i < num_old_keyname; i++) {
c1976b8365310f23085adaa53cf00b14039014c8enricop if (strcmp(old_keyname[i], (const char *)new_keyname) == 0)
c1976b8365310f23085adaa53cf00b14039014c8enricop /* Found matching keyname so terminate walk */
c1976b8365310f23085adaa53cf00b14039014c8enricop return (1);
c1976b8365310f23085adaa53cf00b14039014c8enricop }
c1976b8365310f23085adaa53cf00b14039014c8enricop return (0);
c1976b8365310f23085adaa53cf00b14039014c8enricop}
c1976b8365310f23085adaa53cf00b14039014c8enricop
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Print the key name format into the appropriate field, then convert any ":"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * characters to ".", as ":[1-4]" is the slot indicator, which otherwise
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * would trip us up. Invalid characters for secobj names are ignored.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * The fourth parameter is expected to be of size DLADM_SECOBJ_NAME_MAX.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * (Note that much of the system uses DLADM_WLAN_MAX_KEYNAME_LEN, which is 64
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * rather than 32, but that dladm_get_secobj will fail if a length greater than
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * DLD_SECOBJ_NAME_MAX is seen, and that's 32. This is all horribly broken.)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_set_key_name(const char *essid, const char *bssid, char *name, size_t nsz)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int i, j;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char secobj_name[DLADM_WLAN_MAX_KEYNAME_LEN];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* create a concatenated string with essid and bssid */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (bssid == NULL || bssid[0] == '\0') {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) snprintf(secobj_name, sizeof (secobj_name), "nwam-%s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey essid);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) snprintf(secobj_name, sizeof (secobj_name), "nwam-%s-%s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey essid, bssid);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* copy only valid chars to the return string, terminating with \0 */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey i = 0; /* index into secobj_name */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey j = 0; /* index into name */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey while (secobj_name[i] != '\0') {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (j == nsz - 1)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (secobj_name[i] == ':') {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey name[j] = '.';
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey j++;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (isalnum(secobj_name[i]) ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey secobj_name[i] == '.' || secobj_name[i] == '-' ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey secobj_name[i] == '_') {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey name[j] = secobj_name[i];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey j++;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey i++;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey name[j] = '\0';
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwam_error_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_wlan_set_key(const char *linkname, const char *essid, const char *bssid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uint32_t security_mode, uint_t keyslot, char *raw_key)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_t ncu_obj;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_ncu_t *ncu;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_link_t *link;
c1976b8365310f23085adaa53cf00b14039014c8enricop int ret = 0;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uint8_t obj_val[DLADM_SECOBJ_VAL_MAX];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uint_t obj_len = sizeof (obj_val);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char obj_name[DLADM_SECOBJ_NAME_MAX];
c1976b8365310f23085adaa53cf00b14039014c8enricop char obj_tempname[DLADM_SECOBJ_NAME_MAX];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_status_t status;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char errmsg[DLADM_STRSIZE];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_secobj_class_t class;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((ncu_obj = nwamd_ncu_object_find(NWAM_NCU_TYPE_LINK, linkname))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_wlan_set_key: could not find object "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "for link %s", linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NWAM_ENTITY_NOT_FOUND);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu = ncu_obj->nwamd_object_data;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey link = &ncu->ncu_link;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey class = (security_mode == DLADM_WLAN_SECMODE_WEP ?
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey DLADM_SECOBJ_CLASS_WEP : DLADM_SECOBJ_CLASS_WPA);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (key_string_to_secobj_value(raw_key, obj_val, &obj_len,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey class) != 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* above function logs internally on failure */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NWAM_ERROR_INTERNAL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
c1976b8365310f23085adaa53cf00b14039014c8enricop nlog(LOG_DEBUG, "nwamd_wlan_set_key: running for link %s", linkname);
c1976b8365310f23085adaa53cf00b14039014c8enricop /*
c1976b8365310f23085adaa53cf00b14039014c8enricop * Name key object for this WLAN so it can be later retrieved.
c1976b8365310f23085adaa53cf00b14039014c8enricop * (bssid is appended if an object, with the same keyname,
c1976b8365310f23085adaa53cf00b14039014c8enricop * already exists and is associated to a known wlan)
c1976b8365310f23085adaa53cf00b14039014c8enricop */
c1976b8365310f23085adaa53cf00b14039014c8enricop nwamd_set_key_name(essid, NULL, obj_tempname, sizeof (obj_tempname));
c1976b8365310f23085adaa53cf00b14039014c8enricop (void) nwam_walk_known_wlans(find_keyname_cb, obj_tempname, 0, &ret);
c1976b8365310f23085adaa53cf00b14039014c8enricop /*
c1976b8365310f23085adaa53cf00b14039014c8enricop * We also check if the keyval is the same. The user might want
c1976b8365310f23085adaa53cf00b14039014c8enricop * to use the same key for more APs with the same ESSID.
c1976b8365310f23085adaa53cf00b14039014c8enricop * This can result in a known wlan with multiple BSSIDs
c1976b8365310f23085adaa53cf00b14039014c8enricop */
c1976b8365310f23085adaa53cf00b14039014c8enricop if (ret == 1) {
c1976b8365310f23085adaa53cf00b14039014c8enricop dladm_wlan_key_t *old_secobj = nwamd_wlan_get_key_named(
c1976b8365310f23085adaa53cf00b14039014c8enricop obj_tempname, security_mode);
c1976b8365310f23085adaa53cf00b14039014c8enricop nlog(LOG_DEBUG, "found existing obj_name %s", obj_tempname);
c1976b8365310f23085adaa53cf00b14039014c8enricop ret = memcmp((*old_secobj).wk_val, obj_val, obj_len);
c1976b8365310f23085adaa53cf00b14039014c8enricop nwamd_set_key_name(essid, ret ? bssid : NULL, obj_name,
c1976b8365310f23085adaa53cf00b14039014c8enricop sizeof (obj_name));
c1976b8365310f23085adaa53cf00b14039014c8enricop free(old_secobj);
c1976b8365310f23085adaa53cf00b14039014c8enricop } else {
c1976b8365310f23085adaa53cf00b14039014c8enricop nwamd_set_key_name(essid, NULL, obj_name,
c1976b8365310f23085adaa53cf00b14039014c8enricop sizeof (obj_name));
c1976b8365310f23085adaa53cf00b14039014c8enricop }
c1976b8365310f23085adaa53cf00b14039014c8enricop nlog(LOG_DEBUG, "store_key: obj_name is %s", obj_name);
c1976b8365310f23085adaa53cf00b14039014c8enricop
c1976b8365310f23085adaa53cf00b14039014c8enricop /*
c1976b8365310f23085adaa53cf00b14039014c8enricop * We have validated the new key, so remove the old one.
c1976b8365310f23085adaa53cf00b14039014c8enricop * This will actually delete the keyobj only if the user had set
c1976b8365310f23085adaa53cf00b14039014c8enricop * a wrong key and is replacing it with a new one for the same AP.
c1976b8365310f23085adaa53cf00b14039014c8enricop */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey status = dladm_unset_secobj(dld_handle, obj_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (status != DLADM_STATUS_OK && status != DLADM_STATUS_NOTFOUND) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "store_key: could not remove old secure object "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "'%s' for key: %s", obj_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_status2str(status, errmsg));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NWAM_ERROR_INTERNAL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* if we're just deleting the key, then we're done */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (raw_key[0] == '\0') {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NWAM_SUCCESS);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey status = dladm_set_secobj(dld_handle, obj_name, class,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey obj_val, obj_len,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey DLADM_OPT_CREATE | DLADM_OPT_PERSIST | DLADM_OPT_ACTIVE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (status != DLADM_STATUS_OK) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "store_key: could not create secure object "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "'%s' for key: %s", obj_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_status2str(status, errmsg));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NWAM_ERROR_INTERNAL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_key = nwamd_wlan_get_key_named(obj_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey security_mode);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(link->nwamd_link_wifi_keyname, obj_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (link->nwamd_link_wifi_keyname));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_security_mode = security_mode;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (security_mode == DLADM_WLAN_SECMODE_WEP) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_key->wk_idx =
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (keyslot >= 1 && keyslot <= 4) ? keyslot : 1;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* If link NCU is offline* or online, (re)connect. */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey switch (ncu_obj->nwamd_object_state) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case NWAM_STATE_ONLINE:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* if changing the key of the connected WLAN, reconnect */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (strcmp(essid, link->nwamd_link_wifi_essid) == 0)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj->nwamd_object_name, NWAM_STATE_ONLINE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_LINK_WIFI_CONNECTING);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case NWAM_STATE_OFFLINE_TO_ONLINE:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* if we are waiting for the key, connect */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (ncu_obj->nwamd_object_aux_state ==
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_LINK_WIFI_NEED_KEY)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj->nwamd_object_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_STATE_OFFLINE_TO_ONLINE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_LINK_WIFI_CONNECTING);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey default:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NWAM_SUCCESS);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * returns NULL if no key was recovered from libdladm. Passing in
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * security mode of 0 means we don't care what key type it is.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeydladm_wlan_key_t *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_wlan_get_key_named(const char *name, uint32_t security_mode)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_status_t status;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char errmsg[DLADM_STRSIZE];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_wlan_key_t *cooked_key;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_secobj_class_t class;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (security_mode == DLADM_WLAN_SECMODE_NONE)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Newly-allocated key must be freed by caller, or by
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * subsequent call to nwamd_wlan_get_key_named().
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((cooked_key = malloc(sizeof (dladm_wlan_key_t))) == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_wlan_get_key_named: malloc failed");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Set name appropriately to retrieve key for this WLAN. Note that we
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * cannot use the actual wk_name buffer size, as it's two times too
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * large for dladm_get_secobj.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(cooked_key->wk_name, name, DLADM_SECOBJ_NAME_MAX);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_wlan_get_key_named: len = %d, object = %s\n",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey strlen(cooked_key->wk_name), cooked_key->wk_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey cooked_key->wk_len = sizeof (cooked_key->wk_val);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey cooked_key->wk_idx = 1;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Try the kernel first, then fall back to persistent storage. */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey status = dladm_get_secobj(dld_handle, cooked_key->wk_name, &class,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey cooked_key->wk_val, &cooked_key->wk_len,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey DLADM_OPT_ACTIVE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (status != DLADM_STATUS_OK) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_wlan_get_key_named: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "dladm_get_secobj(TEMP) failed: %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_status2str(status, errmsg));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey status = dladm_get_secobj(dld_handle, cooked_key->wk_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey &class, cooked_key->wk_val, &cooked_key->wk_len,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey DLADM_OPT_PERSIST);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey switch (status) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case DLADM_STATUS_OK:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_wlan_get_key_named: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "dladm_get_secobj succeeded: len %d", cooked_key->wk_len);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case DLADM_STATUS_NOTFOUND:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * We do not want an error in the case that the secobj
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * is not found, since we then prompt for it.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(cooked_key);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey default:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_wlan_get_key_named: could not get key "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "from secure object '%s': %s", cooked_key->wk_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_status2str(status, errmsg));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(cooked_key);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (security_mode != 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey switch (class) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case DLADM_SECOBJ_CLASS_WEP:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (security_mode == DLADM_WLAN_SECMODE_WEP)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (cooked_key);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case DLADM_SECOBJ_CLASS_WPA:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (security_mode == DLADM_WLAN_SECMODE_WPA)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (cooked_key);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey default:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* shouldn't happen */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_wlan_get_key: invalid class %d",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey class);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* key type mismatch */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_wlan_get_key: key type mismatch"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey " from secure object '%s'", cooked_key->wk_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(cooked_key);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (cooked_key);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic dladm_wlan_key_t *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_wlan_get_key(const char *essid, const char *bssid, uint32_t security_mode)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char keyname[DLADM_SECOBJ_NAME_MAX];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_set_key_name(essid, bssid, keyname, DLADM_SECOBJ_NAME_MAX);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (nwamd_wlan_get_key_named(keyname, security_mode));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Checks if a wireless network can be selected or not. A wireless network
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * CANNOT be selected if the NCU is DISABLED, or the NCU is OFFLINE or
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * ONLINE* and has lower priority than the currently active priority-group.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Called with object lock held.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic boolean_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeywireless_selection_possible(nwamd_object_t object)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_ncu_t *ncu = object->nwamd_object_data;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (ncu->ncu_link.nwamd_link_media != DL_WIFI)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (object->nwamd_object_state == NWAM_STATE_DISABLED ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ((object->nwamd_object_state == NWAM_STATE_OFFLINE ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey object->nwamd_object_state == NWAM_STATE_ONLINE_TO_OFFLINE) &&
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ncu->ncu_link.nwamd_link_activation_mode ==
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_ACTIVATION_MODE_PRIORITIZED &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (current_ncu_priority_group == INVALID_PRIORITY_GROUP ||
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ncu->ncu_link.nwamd_link_priority_group >
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey current_ncu_priority_group))) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_TRUE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Update the selected and/or connected values for the
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * scan data. If these change, we need to trigger a scan
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * event since the updated values need to be communicated
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * to the GUI.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_set_selected_connected(nwamd_ncu_t *ncu, boolean_t selected,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey boolean_t connected)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwamd_link_t *link = &ncu->ncu_link;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_wifi_scan_t *s = &link->nwamd_link_wifi_scan;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int i;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey boolean_t trigger_scan_event = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey for (i = 0; i < s->nwamd_wifi_scan_curr_num; i++) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (strcmp(s->nwamd_wifi_scan_curr[i].nww_essid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_essid) != 0 ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (link->nwamd_link_wifi_bssid[0] != '\0' &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey strcmp(s->nwamd_wifi_scan_curr[i].nww_bssid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_bssid) != 0))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (selected) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (!s->nwamd_wifi_scan_curr[i].nww_selected)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey trigger_scan_event = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s->nwamd_wifi_scan_curr[i].nww_selected = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (s->nwamd_wifi_scan_curr[i].nww_selected)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey trigger_scan_event = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s->nwamd_wifi_scan_curr[i].nww_selected = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (connected) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (!s->nwamd_wifi_scan_curr[i].nww_connected)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey trigger_scan_event = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s->nwamd_wifi_scan_curr[i].nww_connected = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (s->nwamd_wifi_scan_curr[i].nww_connected)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey trigger_scan_event = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s->nwamd_wifi_scan_curr[i].nww_connected = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (trigger_scan_event || s->nwamd_wifi_scan_changed) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_t scan_event = nwamd_event_init_wlan
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (ncu->ncu_name, NWAM_EVENT_TYPE_WLAN_SCAN_REPORT, connected,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s->nwamd_wifi_scan_curr, s->nwamd_wifi_scan_curr_num);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (scan_event != NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Avoid sending same scan data multiple times */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s->nwamd_wifi_scan_changed = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_enqueue(scan_event);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey/*
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey * Callback used on each known WLAN - if the BSSID is matched, set
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey * the ESSID of the hidden WLAN to the known WLAN name.
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey */
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskeystatic int
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskeyfind_bssid_cb(nwam_known_wlan_handle_t kwh, void *data)
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey{
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey nwamd_link_t *link = data;
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey nwam_error_t err;
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey nwam_value_t bssidval;
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey char **bssids, *name;
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey uint_t num_bssids, i;
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey if ((err = nwam_known_wlan_get_prop_value(kwh,
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey NWAM_KNOWN_WLAN_PROP_BSSIDS, &bssidval)) != NWAM_SUCCESS) {
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey nlog(LOG_ERR, "find_bssid_cb: nwam_known_wlan_get_prop: %s",
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey nwam_strerror(err));
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey return (0);
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey }
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey if ((err = nwam_value_get_string_array(bssidval, &bssids, &num_bssids))
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey != NWAM_SUCCESS) {
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey nlog(LOG_ERR, "find_bssid_cb: nwam_value_get_string_array: %s",
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey nwam_strerror(err));
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey nwam_value_free(bssidval);
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey return (0);
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey }
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey for (i = 0; i < num_bssids; i++) {
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey if (strcmp(bssids[i], link->nwamd_link_wifi_bssid) == 0) {
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey if ((err = nwam_known_wlan_get_name(kwh, &name))
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey != NWAM_SUCCESS) {
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey nlog(LOG_ERR, "find_bssid_cb: "
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey "nwam_known_wlan_get_name: %s",
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey nwam_strerror(err));
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey continue;
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey }
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey (void) strlcpy(link->nwamd_link_wifi_essid, name,
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey sizeof (link->nwamd_link_wifi_essid));
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey free(name);
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey nwam_value_free(bssidval);
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey /* Found ESSID for BSSID so terminate walk */
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey return (1);
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey }
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey }
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey nwam_value_free(bssidval);
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey return (0);
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey}
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey/*
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey * We may have encountered a BSSID for a hidden WLAN before and as a result
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey * may have a known WLAN entry with this BSSID. Walk known WLANs, searching
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey * for a BSSID match. Called with object lock held.
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey */
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskeystatic void
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskeycheck_if_hidden_wlan_was_visited(nwamd_link_t *link)
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey{
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey (void) nwam_walk_known_wlans(find_bssid_cb, link,
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER, NULL);
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey}
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwam_error_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_wlan_select(const char *linkname, const char *essid, const char *bssid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uint32_t security_mode, boolean_t add_to_known_wlans)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_t ncu_obj;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_ncu_t *ncu;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_link_t *link;
c1976b8365310f23085adaa53cf00b14039014c8enricop boolean_t found_key = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((ncu_obj = nwamd_ncu_object_find(NWAM_NCU_TYPE_LINK, linkname))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_wlan_select: could not find object "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "for link %s", linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NWAM_ENTITY_NOT_FOUND);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu = ncu_obj->nwamd_object_data;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey link = &ncu->ncu_link;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * If wireless selection is not possible because of the current
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * state or priority-group, then stop.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (!wireless_selection_possible(ncu_obj)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NWAM_ENTITY_INVALID_STATE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* unset selected, connected flag for previously connected wlan */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_set_selected_connected(ncu, B_FALSE, B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey /* Disconnect to allow new selection to go ahead */
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey (void) dladm_wlan_disconnect(dld_handle, link->nwamd_link_id);
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(link->nwamd_link_wifi_essid, essid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (link->nwamd_link_wifi_essid));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(link->nwamd_link_wifi_bssid, bssid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (link->nwamd_link_wifi_bssid));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_security_mode = security_mode;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_add_to_known_wlans = add_to_known_wlans;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey /* If this is a hidden wlan, then essid is empty */
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey if (link->nwamd_link_wifi_essid[0] == '\0')
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey check_if_hidden_wlan_was_visited(link);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* set selected flag for newly-selected WLAN */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_set_selected_connected(ncu, B_TRUE, B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* does this WLAN require a key? If so go to NEED_KEY */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (NEED_ENC(link->nwamd_link_wifi_security_mode)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
c1976b8365310f23085adaa53cf00b14039014c8enricop * nwam secobjs can have two formats: nwam-ESSID-BSSID and
c1976b8365310f23085adaa53cf00b14039014c8enricop * nwam-ESSID. There is no reason for searching through known
c1976b8365310f23085adaa53cf00b14039014c8enricop * wlan keynames since this is only the selection process.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
c1976b8365310f23085adaa53cf00b14039014c8enricop if ((link->nwamd_link_wifi_key = nwamd_wlan_get_key
c1976b8365310f23085adaa53cf00b14039014c8enricop (link->nwamd_link_wifi_essid, link->nwamd_link_wifi_bssid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_security_mode)) != NULL) {
c1976b8365310f23085adaa53cf00b14039014c8enricop /*
c1976b8365310f23085adaa53cf00b14039014c8enricop * Found old key format,
c1976b8365310f23085adaa53cf00b14039014c8enricop * known wlans with similar names might exist
c1976b8365310f23085adaa53cf00b14039014c8enricop */
c1976b8365310f23085adaa53cf00b14039014c8enricop nwamd_set_key_name(link->nwamd_link_wifi_essid,
c1976b8365310f23085adaa53cf00b14039014c8enricop link->nwamd_link_wifi_bssid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_keyname,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey DLADM_SECOBJ_NAME_MAX);
c1976b8365310f23085adaa53cf00b14039014c8enricop nlog(LOG_DEBUG, "nwamd_wlan_select: got old format "
c1976b8365310f23085adaa53cf00b14039014c8enricop "WLAN key %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_keyname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey found_key = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if ((link->nwamd_link_wifi_key = nwamd_wlan_get_key
c1976b8365310f23085adaa53cf00b14039014c8enricop (link->nwamd_link_wifi_essid, NULL,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_security_mode)) != NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_set_key_name(link->nwamd_link_wifi_essid, NULL,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_keyname,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey DLADM_SECOBJ_NAME_MAX);
c1976b8365310f23085adaa53cf00b14039014c8enricop nlog(LOG_DEBUG, "nwamd_wlan_select: got WLAN key %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_keyname);
c1976b8365310f23085adaa53cf00b14039014c8enricop found_key = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_wlan_select: could not "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "find key for WLAN '%s'",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_essid);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(link->nwamd_link_wifi_key);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_key = NULL;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_keyname[0] = '\0';
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (NEED_ENC(link->nwamd_link_wifi_security_mode) && !found_key) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj->nwamd_object_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_STATE_OFFLINE_TO_ONLINE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_LINK_WIFI_NEED_KEY);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj->nwamd_object_name, NWAM_STATE_OFFLINE_TO_ONLINE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_LINK_WIFI_CONNECTING);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NWAM_SUCCESS);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * See if BSSID is in visited list of BSSIDs for known WLAN. Used for
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * strict BSSID matching (depends on wireless_strict_bssid property value).
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
c1976b8365310f23085adaa53cf00b14039014c8enricopstatic int
c1976b8365310f23085adaa53cf00b14039014c8enricopbssid_match(nwam_known_wlan_handle_t kwh, void *bssid)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_value_t bssidsval;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_error_t err;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char **bssids;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uint_t nelem, i;
c1976b8365310f23085adaa53cf00b14039014c8enricop int found = 0;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((err = nwam_known_wlan_get_prop_value(kwh,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_KNOWN_WLAN_PROP_BSSIDS, &bssidsval)) != NWAM_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "bssid_match: %s", nwam_strerror(err));
c1976b8365310f23085adaa53cf00b14039014c8enricop return (0);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((err = nwam_value_get_string_array(bssidsval, &bssids, &nelem))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey != NWAM_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_value_free(bssidsval);
c1976b8365310f23085adaa53cf00b14039014c8enricop return (0);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey for (i = 0; i < nelem; i++) {
c1976b8365310f23085adaa53cf00b14039014c8enricop if (strcmp((const char *)bssid, bssids[i]) == 0) {
c1976b8365310f23085adaa53cf00b14039014c8enricop found = 1;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_value_free(bssidsval);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (found);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/* Find most prioritized AP with strongest signal in scan data. */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic int
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyfind_best_wlan_cb(nwam_known_wlan_handle_t kwh, void *data)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_ncu_t *ncu = data;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwamd_link_t *link = &ncu->ncu_link;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_wifi_scan_t *s = &link->nwamd_link_wifi_scan;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_error_t err;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char *name = NULL;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int i;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_wlan_strength_t curr_strength = 0;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_wlan_strength_t max_strength = 0;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey boolean_t found = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((err = nwam_known_wlan_get_name(kwh, &name)) != NWAM_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "find_best_wlan_cb: could not look up name: %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_strerror(err));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (0);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (link->nwamd_link_wifi_connected) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) dladm_wlan_str2strength
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (link->nwamd_link_wifi_signal_strength, &curr_strength);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * If we're >= scan level, don't pick another Known WLAN if still
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * connected (even if a Known WLAN with higher priority is available).
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * If the user wants to connect to a different Known WLAN, it can be
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * done from the GUI or select-wifi subcommand of nwamadm(1M).
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (curr_strength >= wireless_scan_level &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_connected) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (1);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey for (i = 0; i < s->nwamd_wifi_scan_curr_num; i++) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_wlan_t *cur_wlan = &(s->nwamd_wifi_scan_curr[i]);
c1976b8365310f23085adaa53cf00b14039014c8enricop int b_match = bssid_match(kwh, cur_wlan->nww_bssid);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * We need to either match the scanned essid, or in the case
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * where the essid was not broadcast, match the scanned bssid.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (strcmp(cur_wlan->nww_essid, name) != 0 &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey !(cur_wlan->nww_essid[0] == '\0' && b_match))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * If wireless_strict_bssid is specified, need to match
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * BSSID too.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (wireless_strict_bssid && !b_match)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Found a match. Since we walk known WLANs in
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * priority order, it's guaranteed to be the
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * most prioritized. It may not be the strongest though -
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * we continue the walk and record the strength along
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * with the ESSID and BSSID, so that if we encounter
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * another AP with the same ESSID but a higher signal strength,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * we will choose it - but only if the currently-connected
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * WLAN is at or below wireless_scan_level.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) dladm_wlan_str2strength
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (cur_wlan->nww_signal_strength, &curr_strength);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (curr_strength > max_strength) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(link->nwamd_link_wifi_essid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey cur_wlan->nww_essid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (link->nwamd_link_wifi_essid));
83ca9a11d102397d8307c76d5b733133f9841464Anurag S. Maskey /*
83ca9a11d102397d8307c76d5b733133f9841464Anurag S. Maskey * Set BSSID if wireless_strict_bssid is specified or
83ca9a11d102397d8307c76d5b733133f9841464Anurag S. Maskey * if this is a hidden WLAN. Store the BSSID here and
83ca9a11d102397d8307c76d5b733133f9841464Anurag S. Maskey * then later determine the hidden WLAN's name in the
83ca9a11d102397d8307c76d5b733133f9841464Anurag S. Maskey * connect thread.
83ca9a11d102397d8307c76d5b733133f9841464Anurag S. Maskey */
83ca9a11d102397d8307c76d5b733133f9841464Anurag S. Maskey if (wireless_strict_bssid ||
83ca9a11d102397d8307c76d5b733133f9841464Anurag S. Maskey cur_wlan->nww_essid[0] == '\0') {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(link->nwamd_link_wifi_bssid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey cur_wlan->nww_bssid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (link->nwamd_link_wifi_bssid));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(link->nwamd_link_wifi_signal_strength,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey cur_wlan->nww_signal_strength,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (link->nwamd_link_wifi_signal_strength));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_security_mode =
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey cur_wlan->nww_security_mode;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey found = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) dladm_wlan_str2strength
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (link->nwamd_link_wifi_signal_strength, &max_strength);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (found ? 1 : 0);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic boolean_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_find_known_wlan(nwamd_object_t ncu_obj)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_ncu_t *ncu = ncu_obj->nwamd_object_data;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int ret;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Walk known WLANs, finding lowest priority (preferred) WLAN
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * in our scan results.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) nwam_walk_known_wlans(find_best_wlan_cb, ncu,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER, &ret);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (ret == 1);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * WLAN scan code for WIFI link NCUs.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/* Create periodic scan event for object. Called with object lock held. */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_ncu_create_periodic_scan_event(nwamd_object_t ncu_obj)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_t scan_event;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (wireless_scan_interval == 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_create_periodic_scan_event: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "wireless_scan_interval set to 0 so no periodic scanning");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey scan_event = nwamd_event_init(NWAM_EVENT_TYPE_PERIODIC_SCAN,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_OBJECT_TYPE_NCU, 0, ncu_obj->nwamd_object_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (scan_event != NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_enqueue_timed(scan_event,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey wireless_scan_interval > WIRELESS_SCAN_INTERVAL_MIN ?
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey wireless_scan_interval : WIRELESS_SCAN_INTERVAL_MIN);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/* Handle periodic scan event (which puts link into WIFI_INIT state */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_ncu_handle_periodic_scan_event(nwamd_event_t event)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_t ncu_obj;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_ncu_t *ncu;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj = nwamd_object_find(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey event->event_object);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (ncu_obj == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_periodic_scan_event: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "no object %s", event->event_object);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu = ncu_obj->nwamd_object_data;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Only rescan if state is offline* or online */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_periodic_scan_event: doing rescan..");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (ncu_obj->nwamd_object_state == NWAM_STATE_OFFLINE_TO_ONLINE ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj->nwamd_object_state == NWAM_STATE_ONLINE) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* rescan, then create periodic scan event */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) nwamd_wlan_scan(ncu->ncu_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_ncu_create_periodic_scan_event(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic boolean_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyget_scan_results(void *arg, dladm_wlan_attr_t *attrp)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_wifi_scan_t *s = arg;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey const char *linkname = s->nwamd_wifi_scan_link;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char essid_name[DLADM_STRSIZE];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char bssid_name[DLADM_STRSIZE];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char strength[DLADM_STRSIZE];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uint_t i, index = 0;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey boolean_t found = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) dladm_wlan_essid2str(&attrp->wa_essid, essid_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) dladm_wlan_bssid2str(&attrp->wa_bssid, bssid_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) dladm_wlan_strength2str(&attrp->wa_strength, strength);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey index = s->nwamd_wifi_scan_curr_num;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (index == NWAMD_MAX_NUM_WLANS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "get_scan_results: truncating WLAN scan results "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "for link %s: ommiting (%s, %s)", linkname, essid_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey bssid_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_TRUE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(s->nwamd_wifi_scan_curr[index].nww_essid, essid_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (s->nwamd_wifi_scan_curr[index].nww_essid));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(s->nwamd_wifi_scan_curr[index].nww_bssid, bssid_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (s->nwamd_wifi_scan_curr[index].nww_bssid));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(s->nwamd_wifi_scan_curr[index].nww_signal_strength,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey strength,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (s->nwamd_wifi_scan_curr[index].nww_signal_strength));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s->nwamd_wifi_scan_curr[index].nww_security_mode = attrp->wa_secmode;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s->nwamd_wifi_scan_curr[index].nww_speed = attrp->wa_speed;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s->nwamd_wifi_scan_curr[index].nww_channel = attrp->wa_channel;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s->nwamd_wifi_scan_curr[index].nww_bsstype = attrp->wa_bsstype;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * We fill in actual values for selected/connected/key later when we
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * reacquire the object lock.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s->nwamd_wifi_scan_curr[index].nww_selected = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s->nwamd_wifi_scan_curr[index].nww_connected = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s->nwamd_wifi_scan_curr[index].nww_have_key = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s->nwamd_wifi_scan_curr[index].nww_keyindex = 1;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s->nwamd_wifi_scan_curr_num++;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Check if this AP was in previous scan results */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey for (i = 0; i < s->nwamd_wifi_scan_last_num; i++) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey found = (strcmp(s->nwamd_wifi_scan_last[i].nww_essid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey essid_name) == 0 &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey strcmp(s->nwamd_wifi_scan_last[i].nww_bssid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey bssid_name) == 0);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (found)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (!found)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s->nwamd_wifi_scan_changed = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "get_scan_results(%s, %d): ESSID %s, BSSID %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey linkname, index, essid_name, bssid_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_TRUE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Check if we're connected to the expected WLAN, or in the case of autoconf
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * record the WLAN we're connected to.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyboolean_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_wlan_connected(nwamd_object_t ncu_obj)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_ncu_t *ncu = ncu_obj->nwamd_object_data;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwamd_link_t *link = &ncu->ncu_link;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_wlan_linkattr_t attr;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char essid[DLADM_STRSIZE];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char bssid[DLADM_STRSIZE];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey boolean_t connected = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int retries = 0;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * This is awful, but some wireless drivers
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * (particularly 'ath') will erroneously report
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * "disconnected" if queried right after a scan. If we
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * see 'down' reported here, we retry a few times to
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * make sure it's really down.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey while (retries++ < 4) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (dladm_wlan_get_linkattr(dld_handle, link->nwamd_link_id,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey &attr) != DLADM_STATUS_OK) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey attr.la_status = DLADM_WLAN_LINK_DISCONNECTED;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (attr.la_status == DLADM_WLAN_LINK_CONNECTED) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (attr.la_status == DLADM_WLAN_LINK_CONNECTED) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) dladm_wlan_essid2str(&attr.la_wlan_attr.wa_essid, essid);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) dladm_wlan_bssid2str(&attr.la_wlan_attr.wa_bssid, bssid);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey connected = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_wlan_connected: %s connected to %s %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu->ncu_name, essid, bssid);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * If we're using autoconf, we have no control over what we connect to,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * so rather than verifying ESSSID, simply record ESSID/BSSID.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (link->nwamd_link_wifi_autoconf) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(link->nwamd_link_wifi_essid, essid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (link->nwamd_link_wifi_essid));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(link->nwamd_link_wifi_bssid, bssid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (link->nwamd_link_wifi_bssid));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Are we connected to expected WLAN? Note:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * we'd like to verify BSSID, but we cannot due to CR 6772510.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (strcmp(essid, link->nwamd_link_wifi_essid) == 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Update connected signal strength */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) dladm_wlan_strength2str(&attr.la_wlan_attr.wa_strength,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_signal_strength);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Store current BSSID */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(link->nwamd_link_wifi_bssid, bssid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (link->nwamd_link_wifi_bssid));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (attr.la_wlan_attr.wa_strength < wireless_scan_level) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * We're connected, but we've dropped below
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * scan threshold. Initiate a scan.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_wlan_connected: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "connected but signal under threshold...");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) nwamd_wlan_scan(ncu->ncu_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (connected);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (strlen(essid) == 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * For hidden WLANs, no ESSID is specified, so we cannot verify
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * WLAN name.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "nwamd_wlan_connected: connected to hidden WLAN, cannot "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "verify connection details");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (connected);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) nlog(LOG_ERR,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "nwamd_wlan_connected: wrong AP on %s; expected %s %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu->ncu_name, link->nwamd_link_wifi_essid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_bssid);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) dladm_wlan_disconnect(dld_handle, link->nwamd_link_id);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_connected = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * WLAN scan thread. Called with the per-link WiFi mutex held.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeywlan_scan_thread(void *arg)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char *linkname = arg;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_t ncu_obj;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_ncu_t *ncu;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_link_t *link;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_status_t status;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char essid[DLADM_STRSIZE];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char bssid[DLADM_STRSIZE];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uint32_t now, link_id;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_wifi_scan_t s;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int i;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((ncu_obj = nwamd_ncu_object_find(NWAM_NCU_TYPE_LINK, linkname))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "wlan_scan_thread: could not find object "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "for link %s", linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu = ncu_obj->nwamd_object_data;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey link = &ncu->ncu_link;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * It is possible multiple scan threads have queued up waiting for the
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * object lock. We try to prevent excessive scanning by limiting the
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * interval between scans to WIRELESS_SCAN_REQUESTED_INTERVAL_MIN sec.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey now = NSEC_TO_SEC(gethrtime());
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((now - link->nwamd_link_wifi_scan.nwamd_wifi_scan_last_time) <
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey WIRELESS_SCAN_REQUESTED_INTERVAL_MIN) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "wlan_scan_thread: last scan for %s "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "was < %d sec ago, ignoring scan request",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey linkname, WIRELESS_SCAN_REQUESTED_INTERVAL_MIN);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Prepare scan data - copy link name and copy previous "current"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * scan results from the nwamd_link_t to the last scan results for
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * the next scan so that we can compare results to find if things
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * have changed since last time.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) bzero(&s, sizeof (nwamd_wifi_scan_t));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(s.nwamd_wifi_scan_link, ncu->ncu_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (s.nwamd_wifi_scan_link));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s.nwamd_wifi_scan_last_num =
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_scan.nwamd_wifi_scan_curr_num;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (s.nwamd_wifi_scan_last_num > 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) memcpy(s.nwamd_wifi_scan_last,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_scan.nwamd_wifi_scan_curr,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s.nwamd_wifi_scan_last_num * sizeof (nwam_wlan_t));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link_id = link->nwamd_link_id;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "wlan_scan_thread: initiating scan on %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s.nwamd_wifi_scan_link);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey scanconnect_entry();
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey status = dladm_wlan_scan(dld_handle, link_id, &s, get_scan_results);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s.nwamd_wifi_scan_last_time = NSEC_TO_SEC(gethrtime());
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (!s.nwamd_wifi_scan_changed) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Scan may have lost WLANs, if so this qualifies as change */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s.nwamd_wifi_scan_changed = (s.nwamd_wifi_scan_curr_num !=
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s.nwamd_wifi_scan_last_num);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey scanconnect_exit();
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (status != DLADM_STATUS_OK) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "wlan_scan_thread: cannot scan link %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s.nwamd_wifi_scan_link);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((ncu_obj = nwamd_ncu_object_find(NWAM_NCU_TYPE_LINK, linkname))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "wlan_scan_thread: could not find object "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "for link %s after doing scan", linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu = ncu_obj->nwamd_object_data;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey link = &ncu->ncu_link;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* For new scan data, add key info from known WLANs */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey for (i = 0; i < s.nwamd_wifi_scan_curr_num; i++) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (NEED_ENC(s.nwamd_wifi_scan_curr[i].nww_security_mode)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char keyname[NWAM_MAX_VALUE_LEN];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_wlan_key_t *key = NULL;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
c1976b8365310f23085adaa53cf00b14039014c8enricop /*
c1976b8365310f23085adaa53cf00b14039014c8enricop * If strict_bssid is true, we start checking for
c1976b8365310f23085adaa53cf00b14039014c8enricop * known wlans with the same BSSID.
c1976b8365310f23085adaa53cf00b14039014c8enricop * This would prevent the selection of secobjs
c1976b8365310f23085adaa53cf00b14039014c8enricop * that actually are referenced by different kwl
c1976b8365310f23085adaa53cf00b14039014c8enricop * with the same ESSID.
c1976b8365310f23085adaa53cf00b14039014c8enricop */
c1976b8365310f23085adaa53cf00b14039014c8enricop if (wireless_strict_bssid) {
c1976b8365310f23085adaa53cf00b14039014c8enricop int b_match = 0;
c1976b8365310f23085adaa53cf00b14039014c8enricop (void) nwam_walk_known_wlans(bssid_match,
c1976b8365310f23085adaa53cf00b14039014c8enricop s.nwamd_wifi_scan_curr[i].nww_bssid, 0,
c1976b8365310f23085adaa53cf00b14039014c8enricop &b_match);
c1976b8365310f23085adaa53cf00b14039014c8enricop if (b_match == 0)
c1976b8365310f23085adaa53cf00b14039014c8enricop continue;
c1976b8365310f23085adaa53cf00b14039014c8enricop }
c1976b8365310f23085adaa53cf00b14039014c8enricop
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (known_wlan_get_keyname
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (s.nwamd_wifi_scan_curr[i].nww_essid, keyname)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey == NWAM_SUCCESS &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (key = nwamd_wlan_get_key_named(keyname,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s.nwamd_wifi_scan_curr[i].nww_security_mode))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey != NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s.nwamd_wifi_scan_curr[i].nww_have_key =
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s.nwamd_wifi_scan_curr[i].nww_keyindex =
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s.nwamd_wifi_scan_curr[i].
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nww_security_mode ==
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey DLADM_WLAN_SECMODE_WEP ?
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey key->wk_idx : 1;
c1976b8365310f23085adaa53cf00b14039014c8enricop nlog(LOG_DEBUG, "found matching keyname for \
c1976b8365310f23085adaa53cf00b14039014c8enricop %s", s.nwamd_wifi_scan_curr[i].nww_bssid);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(key);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Copy scan data into nwamd_link_t */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_scan = s;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Set selected, connected and send scan event if we've got new data */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_set_selected_connected(ncu,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_essid[0] != '\0',
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_connected);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * If wireless selection is not possible because of the current
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * state or priority-group, then this was just a scan request.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Nothing else to do.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (!wireless_selection_possible(ncu_obj)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Check if WLAN is on our known WLAN list. If no
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * previously-visited WLANs are found in scan data, set
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * new state to NEED_SELECTION (provided we're not currently
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * connected, as can be the case during a periodic scan or
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * monitor-triggered scan where the signal strength recovers.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (!nwamd_find_known_wlan(ncu_obj)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (!nwamd_wlan_connected(ncu_obj)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (link->nwamd_link_wifi_connected) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "wlan_scan_thread: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "unexpected disconnect after scan");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj->nwamd_object_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_STATE_ONLINE_TO_OFFLINE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_DOWN);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "wlan_scan_thread: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "no known WLANs - ask user");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj->nwamd_object_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_STATE_OFFLINE_TO_ONLINE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_LINK_WIFI_NEED_SELECTION);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* still connected. if not online, change to online */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "wlan_scan_thread: still connected to "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "%s %s", link->nwamd_link_wifi_essid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_bssid);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (ncu_obj->nwamd_object_state != NWAM_STATE_ONLINE) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj->nwamd_object_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_STATE_OFFLINE_TO_ONLINE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_UP);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "wlan_scan_thread: found known WLAN %s %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_essid, link->nwamd_link_wifi_bssid);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (!nwamd_wlan_connected(ncu_obj)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Copy selected ESSID/BSSID, unlock, call select */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(essid, link->nwamd_link_wifi_essid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (essid));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(bssid, link->nwamd_link_wifi_bssid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (bssid));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) nwamd_wlan_select(linkname, essid, bssid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_security_mode, B_TRUE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* still connected. if not online, change to online */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "wlan_scan_thread: still connected to "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "known WLAN %s %s", link->nwamd_link_wifi_essid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_bssid);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (ncu_obj->nwamd_object_state != NWAM_STATE_ONLINE) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj->nwamd_object_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_STATE_OFFLINE_TO_ONLINE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_UP);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwam_error_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_wlan_scan(const char *linkname)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey pthread_t wifi_thread;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char *link = strdup(linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (link == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_wlan_scan: out of memory");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NWAM_NO_MEMORY);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_wlan_scan: WLAN scan for %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (pthread_create(&wifi_thread, NULL, wlan_scan_thread,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link) != 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_wlan_scan: could not start scan");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(link);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NWAM_ERROR_INTERNAL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* detach thread so that it doesn't become a zombie */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_detach(wifi_thread);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NWAM_SUCCESS);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * WLAN connection code.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic dladm_status_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeydo_connect(uint32_t link_id, dladm_wlan_attr_t *attrp, dladm_wlan_key_t *key,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uint_t keycount, uint_t flags)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_status_t status;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char errmsg[DLADM_STRSIZE];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey scanconnect_entry();
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey status = dladm_wlan_connect(dld_handle, link_id, attrp,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey DLADM_WLAN_CONNECT_TIMEOUT_DEFAULT, key, keycount, flags);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey scanconnect_exit();
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_do_connect: dladm_wlan_connect returned %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_status2str(status, errmsg));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (status);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeywlan_connect_thread(void *arg)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char *linkname = arg;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_t ncu_obj;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_ncu_t *ncu;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_link_t *link;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_error_t err;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uint_t keycount;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uint32_t link_id;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_wlan_key_t *key = NULL;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_wlan_attr_t attr;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dladm_status_t status;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey boolean_t autoconf = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((ncu_obj = nwamd_ncu_object_find(NWAM_NCU_TYPE_LINK, linkname))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "wlan_connect_thread: could not find object "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "for link %s", linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu = ncu_obj->nwamd_object_data;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey link = &ncu->ncu_link;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (!wireless_selection_possible(ncu_obj)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "wlan_connect_thread: %s in invalid state or "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "has lower priority", ncu->ncu_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto done;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* If it is already connected to the required AP, just return. */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (nwamd_wlan_connected(ncu_obj)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj->nwamd_object_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj->nwamd_object_state, NWAM_AUX_STATE_UP);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto done;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
19cbc0aa4cfbb1a88c485c55d4a92c53760c0513Anurag S. Maskey (void) memset(&attr, 0, sizeof (attr));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (dladm_wlan_str2essid(link->nwamd_link_wifi_essid, &attr.wa_essid)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey != DLADM_STATUS_OK) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "wlan_connect_thread: invalid ESSID '%s' "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "for '%s'", link->nwamd_link_wifi_essid, ncu->ncu_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto done;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey attr.wa_valid = DLADM_WLAN_ATTR_ESSID;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* note: bssid logic here is non-functional */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (link->nwamd_link_wifi_bssid[0] != '\0') {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (dladm_wlan_str2bssid(link->nwamd_link_wifi_bssid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey &attr.wa_bssid) != DLADM_STATUS_OK) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "wlan_connect_thread: invalid BSSID '%s'",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "for '%s'", link->nwamd_link_wifi_bssid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu->ncu_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey attr.wa_valid |= DLADM_WLAN_ATTR_BSSID;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* First check for the key */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (NEED_ENC(link->nwamd_link_wifi_security_mode)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (link->nwamd_link_wifi_key == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "wlan_connect_thread: could not find "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "key for WLAN '%s'", link->nwamd_link_wifi_essid);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj->nwamd_object_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_STATE_OFFLINE_TO_ONLINE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_LINK_WIFI_NEED_KEY);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto done;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Make a copy of the key as we need to unlock the object */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((key = calloc(1, sizeof (dladm_wlan_key_t))) == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "wlan_connect_thread: out of memory");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto done;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) memcpy(key, link->nwamd_link_wifi_key,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (dladm_wlan_key_t));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey attr.wa_secmode = link->nwamd_link_wifi_security_mode;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey keycount = 1;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "wlan_connect_thread: retrieved key");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey key = NULL;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey keycount = 0;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Connect; only scan if a bssid was not specified. If it times out,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * try a second time using autoconf. Drop the object lock during the
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * connect attempt since connecting may take some time, and access to
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * the link object during that period would be impossible if we held the
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * lock.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_autoconf = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link_id = link->nwamd_link_id;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey status = do_connect(link_id, &attr, key, keycount,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey DLADM_WLAN_CONNECT_NOSCAN);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (status != DLADM_STATUS_OK) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Connect failed, try autoconf */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (!wireless_autoconf || (status = do_connect(link_id, &attr,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NULL, 0, 0)) != DLADM_STATUS_OK) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "wlan_connect_thread: connect failed for "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "%s", linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto done_unlocked;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (status == DLADM_STATUS_OK)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey autoconf = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Connect succeeded, reacquire object */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((ncu_obj = nwamd_ncu_object_find(NWAM_NCU_TYPE_LINK, linkname))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "wlan_connect_thread: could not find object "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "for link %s", linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto done_unlocked;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu = ncu_obj->nwamd_object_data;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey link = &ncu->ncu_link;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (autoconf)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_autoconf = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * If WLAN is WEP/WPA, we would like to test the connection as the key
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * may be wrong. It is difficult to find a reliable test that works
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * across APs however. Do nothing for now.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_connected = nwamd_wlan_connected(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (link->nwamd_link_wifi_connected) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (link->nwamd_link_wifi_add_to_known_wlans) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* add to known WLANs */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "wlan_connect_thread: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "add '%s' to known WLANs",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_essid);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((err = nwam_known_wlan_add_to_known_wlans
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (link->nwamd_link_wifi_essid,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_bssid[0] != '\0' ?
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_bssid : NULL,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_security_mode,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_security_mode ==
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey DLADM_WLAN_SECMODE_WEP ?
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (uint_t)link->nwamd_link_wifi_key->wk_idx : 1,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NEED_ENC(link->nwamd_link_wifi_security_mode) ?
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_keyname : NULL))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey != NWAM_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "wlan_connect_thread: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "could not add to known WLANs: %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_strerror(err));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_set_selected_connected(ncu, B_TRUE, B_TRUE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "wlan_connect_thread: connect "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "succeeded, setting state online");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj->nwamd_object_name, NWAM_STATE_ONLINE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_UP);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeydone:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeydone_unlocked:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(key);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_wlan_connect(const char *linkname)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey pthread_t wifi_thread;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char *link = strdup(linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (link == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_wlan_connect: out of memory");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_wlan_connect: WLAN connect for %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (pthread_create(&wifi_thread, NULL, wlan_connect_thread, link) != 0)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_wlan_connect: could not start connect");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* detach thread so that it doesn't become a zombie */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_detach(wifi_thread);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Launch signal strength-monitoring thread which periodically
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * checks connection and signal strength. If we become disconnected
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * or signal drops below threshold specified by wireless_scan_level,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * initiate a scan. The scan initiation is taken care of by
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * the call to nwamd_wlan_connected().
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeywlan_monitor_signal_thread(void *arg)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char *linkname = arg;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_t ncu_obj;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_ncu_t *ncu;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_link_t *link;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey boolean_t first_time = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey for (;;) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((ncu_obj = nwamd_ncu_object_find(NWAM_NCU_TYPE_LINK,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey linkname)) == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "wlan_monitor_signal_thread: could "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "not find object for link %s", linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu = ncu_obj->nwamd_object_data;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey link = &ncu->ncu_link;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* If the NCU is DISABLED/OFFLINE, exit the monitoring thread */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (ncu_obj->nwamd_object_state == NWAM_STATE_OFFLINE ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj->nwamd_object_state == NWAM_STATE_DISABLED) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_INFO, "wlan_monitor_signal_thread: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "%s is %s, stopping thread", linkname,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_state_to_string(ncu_obj->nwamd_object_state));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_monitor_thread = 0;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * First time thru loop, we check if there is another
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * link monitoring thread in operation - if so exit this
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * thread.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (first_time) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey first_time = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (link->nwamd_link_wifi_monitor_thread != 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Already have a monitor thread for link? */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_monitor_thread =
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey pthread_self();
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (!nwamd_wlan_connected(ncu_obj)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "wlan_monitor_signal_thread: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "disconnect occured for WLAN on link %s", linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj->nwamd_object_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_STATE_ONLINE_TO_OFFLINE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_DOWN);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_wifi_monitor_thread = 0;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) sleep(WIRELESS_MONITOR_SIGNAL_INTERVAL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_wlan_monitor_signal(const char *linkname)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey pthread_t wifi_thread;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char *link = strdup(linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (link == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_wlan_monitor_signal: out of memory");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_wlan_monitor_signal: WLAN monitor for %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (pthread_create(&wifi_thread, NULL, wlan_monitor_signal_thread,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link) != 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_wlan_monitor_signal: could not monitor "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "link %s", link);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(link);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* detach thread so that it doesn't become a zombie */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_detach(wifi_thread);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_ncu_handle_link_state_event(nwamd_event_t event)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_event_t evm;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_t ncu_obj;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_ncu_t *ncu;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_link_t *link;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, event->event_object);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (ncu_obj == NULL) {
f6904bc3cbac0d84f41b1eb2ed9489a8f221695cRenee Danson Sommerfeld nlog(LOG_INFO, "nwamd_ncu_handle_link_state_event: no object "
f6904bc3cbac0d84f41b1eb2ed9489a8f221695cRenee Danson Sommerfeld "%s", event->event_object);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_do_not_send(event);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu = ncu_obj->nwamd_object_data;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey link = &ncu->ncu_link;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey evm = event->event_msg;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * We ignore link state events for WiFi because it is very flaky.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Instead we use the monitor thread and drive WiFi state changes from
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * there.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (link->nwamd_link_media == DL_WIFI) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * If it's a link up event and we're not disabled, go online.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (evm->nwe_data.nwe_link_state.nwe_link_up &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj->nwamd_object_state != NWAM_STATE_DISABLED) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (link->nwamd_link_activation_mode ==
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_ACTIVATION_MODE_PRIORITIZED) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int64_t priority_group;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey priority_group = current_ncu_priority_group;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* compare priority groups */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (link->nwamd_link_priority_group > priority_group) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "nwamd_ncu_handle_link_state_event: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "got LINK UP event for priority group "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "%lld, less preferred than current %lld, "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "ignoring",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_priority_group,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey priority_group);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (link->nwamd_link_priority_group ==
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey priority_group) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "nwamd_ncu_handle_link_state_event: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "got LINK UP event for priority group "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "%lld, same as current %lld",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_priority_group,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey priority_group);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Change link state to UP. It will be
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * propagated to IP state machine. Only do
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * the NCU check if and when the interface
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * NCU is online.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey event->event_object,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_STATE_OFFLINE_TO_ONLINE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_UP);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "nwamd_ncu_handle_link_state_event: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "got LINK UP event for priority group "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "%lld, more preferred than current %lld",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_priority_group,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey priority_group);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * We need to mark the link as up so that when
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * it is activated we will bring the interface
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * up.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey event->event_object,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_STATE_OFFLINE_TO_ONLINE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_UP);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_ncp_deactivate_priority_group
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (priority_group);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_ncp_activate_priority_group
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (link->nwamd_link_priority_group);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (link->nwamd_link_activation_mode ==
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_ACTIVATION_MODE_MANUAL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_link_state_event: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "got LINK UP event for manual NCU %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj->nwamd_object_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey event->event_object, NWAM_STATE_OFFLINE_TO_ONLINE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_UP);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * If the link is down then start or continue transition down.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (!evm->nwe_data.nwe_link_state.nwe_link_up &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (ncu_obj->nwamd_object_state == NWAM_STATE_ONLINE ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj->nwamd_object_state == NWAM_STATE_OFFLINE_TO_ONLINE)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (link->nwamd_link_activation_mode ==
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_ACTIVATION_MODE_PRIORITIZED) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "nwamd_ncu_handle_link_state_event: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "got LINK DOWN for priority group %lld",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey link->nwamd_link_priority_group);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Moving to offline checks priority group */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_link_state_event: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "got LINK DOWN event for manual NCU %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj->nwamd_object_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey event->event_object, NWAM_STATE_ONLINE_TO_OFFLINE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_DOWN);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}