wpa: Import wpa 2.10 (second part)
WPA is in fact two distfiles. Import the second distfile.
This commit is contained in:
parent
03f33dd077
commit
df0c787c3e
81
hs20/client/Android.mk
Normal file
81
hs20/client/Android.mk
Normal file
@ -0,0 +1,81 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
INCLUDES = $(LOCAL_PATH)
|
||||
INCLUDES += $(LOCAL_PATH)/../../src/utils
|
||||
INCLUDES += $(LOCAL_PATH)/../../src/common
|
||||
INCLUDES += $(LOCAL_PATH)/../../src
|
||||
INCLUDES += external/libxml2/include
|
||||
INCLUDES += external/curl/include
|
||||
INCLUDES += external/webkit/Source/WebKit/gtk
|
||||
|
||||
# We try to keep this compiling against older platform versions.
|
||||
# The new icu location (external/icu) exports its own headers, but
|
||||
# the older versions in external/icu4c don't, and we need to add those
|
||||
# headers to the include path by hand.
|
||||
ifeq ($(wildcard external/icu),)
|
||||
INCLUDES += external/icu4c/common
|
||||
else
|
||||
# The LOCAL_EXPORT_C_INCLUDE_DIRS from ICU did not seem to fully resolve the
|
||||
# build (e.g., "mm -B" failed to build, but following that with "mm" allowed
|
||||
# the build to complete). For now, add the include directory manually here for
|
||||
# Android 5.0.
|
||||
ver = $(filter 5.0%,$(PLATFORM_VERSION))
|
||||
ifneq (,$(strip $(ver)))
|
||||
INCLUDES += external/icu/icu4c/source/common
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
L_CFLAGS += -DCONFIG_CTRL_IFACE
|
||||
L_CFLAGS += -DCONFIG_CTRL_IFACE_UNIX
|
||||
L_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/misc/wifi/sockets\"
|
||||
|
||||
OBJS = spp_client.c
|
||||
OBJS += oma_dm_client.c
|
||||
OBJS += osu_client.c
|
||||
OBJS += est.c
|
||||
OBJS += ../../src/common/wpa_ctrl.c
|
||||
OBJS += ../../src/common/wpa_helpers.c
|
||||
OBJS += ../../src/utils/xml-utils.c
|
||||
#OBJS += ../../src/utils/browser-android.c
|
||||
OBJS += ../../src/utils/browser-wpadebug.c
|
||||
OBJS += ../../src/utils/wpabuf.c
|
||||
OBJS += ../../src/utils/eloop.c
|
||||
OBJS += ../../src/wps/httpread.c
|
||||
OBJS += ../../src/wps/http_server.c
|
||||
OBJS += ../../src/utils/xml_libxml2.c
|
||||
OBJS += ../../src/utils/http_curl.c
|
||||
OBJS += ../../src/utils/base64.c
|
||||
OBJS += ../../src/utils/os_unix.c
|
||||
L_CFLAGS += -DCONFIG_DEBUG_FILE
|
||||
OBJS += ../../src/utils/wpa_debug.c
|
||||
OBJS += ../../src/utils/common.c
|
||||
OBJS += ../../src/crypto/crypto_internal.c
|
||||
OBJS += ../../src/crypto/md5-internal.c
|
||||
OBJS += ../../src/crypto/sha1-internal.c
|
||||
OBJS += ../../src/crypto/sha256-internal.c
|
||||
OBJS += ../../src/crypto/tls_openssl_ocsp.c
|
||||
|
||||
L_CFLAGS += -DEAP_TLS_OPENSSL
|
||||
|
||||
L_CFLAGS += -Wno-unused-parameter
|
||||
|
||||
|
||||
########################
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := hs20-osu-client
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := libc libcutils
|
||||
LOCAL_SHARED_LIBRARIES += libcrypto libssl
|
||||
#LOCAL_SHARED_LIBRARIES += libxml2
|
||||
LOCAL_STATIC_LIBRARIES += libxml2
|
||||
LOCAL_SHARED_LIBRARIES += libicuuc
|
||||
LOCAL_SHARED_LIBRARIES += libcurl
|
||||
|
||||
LOCAL_CFLAGS := $(L_CFLAGS)
|
||||
LOCAL_SRC_FILES := $(OBJS)
|
||||
LOCAL_C_INCLUDES := $(INCLUDES)
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
########################
|
81
hs20/client/Makefile
Normal file
81
hs20/client/Makefile
Normal file
@ -0,0 +1,81 @@
|
||||
ALL=hs20-osu-client
|
||||
|
||||
include ../../src/build.rules
|
||||
|
||||
CFLAGS += -I../../src/utils
|
||||
CFLAGS += -I../../src/common
|
||||
CFLAGS += -I../../src
|
||||
|
||||
ifndef CONFIG_NO_BROWSER
|
||||
ifndef CONFIG_BROWSER_SYSTEM
|
||||
TEST_WK := $(shell pkg-config --silence-errors --cflags webkitgtk-3.0)
|
||||
ifeq ($(TEST_WK),)
|
||||
# Try webkit2
|
||||
GTKCFLAGS := $(shell pkg-config --cflags gtk+-3.0 webkit2gtk-4.0)
|
||||
GTKLIBS := $(shell pkg-config --libs gtk+-3.0 webkit2gtk-4.0)
|
||||
CFLAGS += -DUSE_WEBKIT2
|
||||
else
|
||||
GTKCFLAGS := $(shell pkg-config --cflags gtk+-3.0 webkitgtk-3.0)
|
||||
GTKLIBS := $(shell pkg-config --libs gtk+-3.0 webkitgtk-3.0)
|
||||
endif
|
||||
|
||||
CFLAGS += $(GTKCFLAGS)
|
||||
LIBS += $(GTKLIBS)
|
||||
endif
|
||||
endif
|
||||
|
||||
OBJS=spp_client.o
|
||||
OBJS += oma_dm_client.o
|
||||
OBJS += osu_client.o
|
||||
OBJS += est.o
|
||||
OBJS += ../../src/utils/xml-utils.o
|
||||
CFLAGS += -DCONFIG_CTRL_IFACE
|
||||
CFLAGS += -DCONFIG_CTRL_IFACE_UNIX
|
||||
OBJS += ../../src/common/wpa_ctrl.o ../../src/common/wpa_helpers.o
|
||||
ifdef CONFIG_NO_BROWSER
|
||||
CFLAGS += -DCONFIG_NO_BROWSER
|
||||
else
|
||||
ifdef CONFIG_BROWSER_SYSTEM
|
||||
OBJS += ../../src/utils/eloop.o
|
||||
OBJS += ../../src/utils/wpabuf.o
|
||||
OBJS += ../../src/wps/httpread.o
|
||||
OBJS += ../../src/wps/http_server.o
|
||||
OBJS += ../../src/utils/browser-system.o
|
||||
else
|
||||
OBJS += ../../src/utils/browser.o
|
||||
endif
|
||||
endif
|
||||
OBJS += ../../src/utils/xml_libxml2.o
|
||||
OBJS += ../../src/utils/http_curl.o
|
||||
OBJS += ../../src/utils/base64.o
|
||||
OBJS += ../../src/utils/os_unix.o
|
||||
CFLAGS += -DCONFIG_DEBUG_FILE
|
||||
OBJS += ../../src/utils/wpa_debug.o
|
||||
OBJS += ../../src/utils/common.o
|
||||
OBJS += ../../src/crypto/crypto_internal.o
|
||||
OBJS += ../../src/crypto/md5-internal.o
|
||||
OBJS += ../../src/crypto/sha1-internal.o
|
||||
OBJS += ../../src/crypto/sha256-internal.o
|
||||
|
||||
CFLAGS += $(shell xml2-config --cflags)
|
||||
LIBS += $(shell xml2-config --libs)
|
||||
|
||||
# Allow static/custom linking of libcurl.
|
||||
ifdef CUST_CURL_LINKAGE
|
||||
LIBS += ${CUST_CURL_LINKAGE}
|
||||
else
|
||||
LIBS += -lcurl
|
||||
endif
|
||||
|
||||
CFLAGS += -DEAP_TLS_OPENSSL
|
||||
OBJS += ../../src/crypto/tls_openssl_ocsp.o
|
||||
LIBS += -lssl -lcrypto
|
||||
|
||||
_OBJS_VAR := OBJS
|
||||
include ../../src/objs.mk
|
||||
hs20-osu-client: $(OBJS)
|
||||
$(Q)$(LDO) $(LDFLAGS) -o hs20-osu-client $(OBJS) $(LIBS)
|
||||
@$(E) " LD " $@
|
||||
|
||||
clean: common-clean
|
||||
rm -f core *~
|
47
hs20/client/devdetail.xml
Normal file
47
hs20/client/devdetail.xml
Normal file
@ -0,0 +1,47 @@
|
||||
<DevDetail xmlns="urn:oma:mo:oma-dm-devdetail:1.0">
|
||||
<Ext>
|
||||
<org.wi-fi>
|
||||
<Wi-Fi>
|
||||
<EAPMethodList>
|
||||
<EAPMethod1>
|
||||
<EAPType>13</EAPType>
|
||||
</EAPMethod1>
|
||||
<EAPMethod2>
|
||||
<EAPType>21</EAPType>
|
||||
<InnerMethod>MS-CHAP-V2</InnerMethod>
|
||||
</EAPMethod2>
|
||||
<EAPMethod3>
|
||||
<EAPType>18</EAPType>
|
||||
</EAPMethod3>
|
||||
<EAPMethod4>
|
||||
<EAPType>23</EAPType>
|
||||
</EAPMethod4>
|
||||
<EAPMethod5>
|
||||
<EAPType>50</EAPType>
|
||||
</EAPMethod5>
|
||||
</EAPMethodList>
|
||||
<ManufacturingCertificate>false</ManufacturingCertificate>
|
||||
<Wi-FiMACAddress>020102030405</Wi-FiMACAddress>
|
||||
<IMSI>310026000000000</IMSI>
|
||||
<IMEI_MEID>imei:490123456789012</IMEI_MEID>
|
||||
<ClientTriggerRedirectURI>http://localhost:12345/</ClientTriggerRedirectURI>
|
||||
<Ops>
|
||||
<launchBrowserToURI></launchBrowserToURI>
|
||||
<negotiateClientCertTLS></negotiateClientCertTLS>
|
||||
<getCertificate></getCertificate>
|
||||
</Ops>
|
||||
</Wi-Fi>
|
||||
</org.wi-fi>
|
||||
</Ext>
|
||||
<URI>
|
||||
<MaxDepth>0</MaxDepth>
|
||||
<MaxTotLen>0</MaxTotLen>
|
||||
<MaxSegLen>0</MaxSegLen>
|
||||
</URI>
|
||||
<DevType>MobilePhone</DevType>
|
||||
<OEM>Manufacturer</OEM>
|
||||
<FwV>1.0</FwV>
|
||||
<SwV>1.0</SwV>
|
||||
<HwV>1.0</HwV>
|
||||
<LrgObj>false</LrgObj>
|
||||
</DevDetail>
|
7
hs20/client/devinfo.xml
Normal file
7
hs20/client/devinfo.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<DevInfo xmlns="urn:oma:mo:oma-dm-devinfo:1.0">
|
||||
<DevId>urn:Example:HS20-station:123456</DevId>
|
||||
<Man>Manufacturer</Man>
|
||||
<Mod>HS20-station</Mod>
|
||||
<DmV>1.2</DmV>
|
||||
<Lang>en</Lang>
|
||||
</DevInfo>
|
769
hs20/client/est.c
Normal file
769
hs20/client/est.c
Normal file
@ -0,0 +1,769 @@
|
||||
/*
|
||||
* Hotspot 2.0 OSU client - EST client
|
||||
* Copyright (c) 2012-2014, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/pkcs7.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/opensslv.h>
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
#include <openssl/buf.h>
|
||||
#endif /* OPENSSL_IS_BORINGSSL */
|
||||
|
||||
#include "common.h"
|
||||
#include "utils/base64.h"
|
||||
#include "utils/xml-utils.h"
|
||||
#include "utils/http-utils.h"
|
||||
#include "osu_client.h"
|
||||
|
||||
|
||||
static int pkcs7_to_cert(struct hs20_osu_client *ctx, const u8 *pkcs7,
|
||||
size_t len, char *pem_file, char *der_file)
|
||||
{
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
CBS pkcs7_cbs;
|
||||
#else /* OPENSSL_IS_BORINGSSL */
|
||||
PKCS7 *p7 = NULL;
|
||||
const unsigned char *p = pkcs7;
|
||||
#endif /* OPENSSL_IS_BORINGSSL */
|
||||
STACK_OF(X509) *certs;
|
||||
int i, num, ret = -1;
|
||||
BIO *out = NULL;
|
||||
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
certs = sk_X509_new_null();
|
||||
if (!certs)
|
||||
goto fail;
|
||||
CBS_init(&pkcs7_cbs, pkcs7, len);
|
||||
if (!PKCS7_get_certificates(certs, &pkcs7_cbs)) {
|
||||
wpa_printf(MSG_INFO, "Could not parse PKCS#7 object: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
write_result(ctx, "Could not parse PKCS#7 object from EST");
|
||||
goto fail;
|
||||
}
|
||||
#else /* OPENSSL_IS_BORINGSSL */
|
||||
p7 = d2i_PKCS7(NULL, &p, len);
|
||||
if (p7 == NULL) {
|
||||
wpa_printf(MSG_INFO, "Could not parse PKCS#7 object: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
write_result(ctx, "Could not parse PKCS#7 object from EST");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
switch (OBJ_obj2nid(p7->type)) {
|
||||
case NID_pkcs7_signed:
|
||||
certs = p7->d.sign->cert;
|
||||
break;
|
||||
case NID_pkcs7_signedAndEnveloped:
|
||||
certs = p7->d.signed_and_enveloped->cert;
|
||||
break;
|
||||
default:
|
||||
certs = NULL;
|
||||
break;
|
||||
}
|
||||
#endif /* OPENSSL_IS_BORINGSSL */
|
||||
|
||||
if (!certs || ((num = sk_X509_num(certs)) == 0)) {
|
||||
wpa_printf(MSG_INFO, "No certificates found in PKCS#7 object");
|
||||
write_result(ctx, "No certificates found in PKCS#7 object");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (der_file) {
|
||||
FILE *f = fopen(der_file, "wb");
|
||||
if (f == NULL)
|
||||
goto fail;
|
||||
i2d_X509_fp(f, sk_X509_value(certs, 0));
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
if (pem_file) {
|
||||
out = BIO_new(BIO_s_file());
|
||||
if (out == NULL ||
|
||||
BIO_write_filename(out, pem_file) <= 0)
|
||||
goto fail;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
X509 *cert = sk_X509_value(certs, i);
|
||||
X509_print(out, cert);
|
||||
PEM_write_bio_X509(out, cert);
|
||||
BIO_puts(out, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
fail:
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
if (certs)
|
||||
sk_X509_pop_free(certs, X509_free);
|
||||
#else /* OPENSSL_IS_BORINGSSL */
|
||||
PKCS7_free(p7);
|
||||
#endif /* OPENSSL_IS_BORINGSSL */
|
||||
if (out)
|
||||
BIO_free_all(out);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int est_load_cacerts(struct hs20_osu_client *ctx, const char *url)
|
||||
{
|
||||
char *buf, *resp;
|
||||
size_t buflen;
|
||||
unsigned char *pkcs7;
|
||||
size_t pkcs7_len, resp_len;
|
||||
int res;
|
||||
|
||||
buflen = os_strlen(url) + 100;
|
||||
buf = os_malloc(buflen);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
os_snprintf(buf, buflen, "%s/cacerts", url);
|
||||
wpa_printf(MSG_INFO, "Download EST cacerts from %s", buf);
|
||||
write_summary(ctx, "Download EST cacerts from %s", buf);
|
||||
ctx->no_osu_cert_validation = 1;
|
||||
http_ocsp_set(ctx->http, 1);
|
||||
res = http_download_file(ctx->http, buf, "Cert/est-cacerts.txt",
|
||||
ctx->ca_fname);
|
||||
http_ocsp_set(ctx->http,
|
||||
(ctx->workarounds & WORKAROUND_OCSP_OPTIONAL) ? 1 : 2);
|
||||
ctx->no_osu_cert_validation = 0;
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_INFO, "Failed to download EST cacerts from %s",
|
||||
buf);
|
||||
write_result(ctx, "Failed to download EST cacerts from %s",
|
||||
buf);
|
||||
os_free(buf);
|
||||
return -1;
|
||||
}
|
||||
os_free(buf);
|
||||
|
||||
resp = os_readfile("Cert/est-cacerts.txt", &resp_len);
|
||||
if (resp == NULL) {
|
||||
wpa_printf(MSG_INFO, "Could not read Cert/est-cacerts.txt");
|
||||
write_result(ctx, "Could not read EST cacerts");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pkcs7 = base64_decode(resp, resp_len, &pkcs7_len);
|
||||
if (pkcs7 && pkcs7_len < resp_len / 2) {
|
||||
wpa_printf(MSG_INFO, "Too short base64 decode (%u bytes; downloaded %u bytes) - assume this was binary",
|
||||
(unsigned int) pkcs7_len, (unsigned int) resp_len);
|
||||
os_free(pkcs7);
|
||||
pkcs7 = NULL;
|
||||
}
|
||||
if (pkcs7 == NULL) {
|
||||
wpa_printf(MSG_INFO, "EST workaround - Could not decode base64, assume this is DER encoded PKCS7");
|
||||
pkcs7 = os_malloc(resp_len);
|
||||
if (pkcs7) {
|
||||
os_memcpy(pkcs7, resp, resp_len);
|
||||
pkcs7_len = resp_len;
|
||||
}
|
||||
}
|
||||
os_free(resp);
|
||||
|
||||
if (pkcs7 == NULL) {
|
||||
wpa_printf(MSG_INFO, "Could not fetch PKCS7 cacerts");
|
||||
write_result(ctx, "Could not fetch EST PKCS#7 cacerts");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = pkcs7_to_cert(ctx, pkcs7, pkcs7_len, "Cert/est-cacerts.pem",
|
||||
NULL);
|
||||
os_free(pkcs7);
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_INFO, "Could not parse CA certs from PKCS#7 cacerts response");
|
||||
write_result(ctx, "Could not parse CA certs from EST PKCS#7 cacerts response");
|
||||
return -1;
|
||||
}
|
||||
unlink("Cert/est-cacerts.txt");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CsrAttrs ::= SEQUENCE SIZE (0..MAX) OF AttrOrOID
|
||||
*
|
||||
* AttrOrOID ::= CHOICE {
|
||||
* oid OBJECT IDENTIFIER,
|
||||
* attribute Attribute }
|
||||
*
|
||||
* Attribute ::= SEQUENCE {
|
||||
* type OBJECT IDENTIFIER,
|
||||
* values SET SIZE(1..MAX) OF OBJECT IDENTIFIER }
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
ASN1_OBJECT *type;
|
||||
STACK_OF(ASN1_OBJECT) *values;
|
||||
} Attribute;
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
union {
|
||||
ASN1_OBJECT *oid;
|
||||
Attribute *attribute;
|
||||
} d;
|
||||
} AttrOrOID;
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_IS_BORINGSSL)
|
||||
DEFINE_STACK_OF(AttrOrOID)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
STACK_OF(AttrOrOID) *attrs;
|
||||
} CsrAttrs;
|
||||
|
||||
ASN1_SEQUENCE(Attribute) = {
|
||||
ASN1_SIMPLE(Attribute, type, ASN1_OBJECT),
|
||||
ASN1_SET_OF(Attribute, values, ASN1_OBJECT)
|
||||
} ASN1_SEQUENCE_END(Attribute);
|
||||
|
||||
ASN1_CHOICE(AttrOrOID) = {
|
||||
ASN1_SIMPLE(AttrOrOID, d.oid, ASN1_OBJECT),
|
||||
ASN1_SIMPLE(AttrOrOID, d.attribute, Attribute)
|
||||
} ASN1_CHOICE_END(AttrOrOID);
|
||||
|
||||
ASN1_CHOICE(CsrAttrs) = {
|
||||
ASN1_SEQUENCE_OF(CsrAttrs, attrs, AttrOrOID)
|
||||
} ASN1_CHOICE_END(CsrAttrs);
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(CsrAttrs);
|
||||
|
||||
|
||||
static void add_csrattrs_oid(struct hs20_osu_client *ctx, ASN1_OBJECT *oid,
|
||||
STACK_OF(X509_EXTENSION) *exts)
|
||||
{
|
||||
char txt[100];
|
||||
int res;
|
||||
|
||||
if (!oid)
|
||||
return;
|
||||
|
||||
res = OBJ_obj2txt(txt, sizeof(txt), oid, 1);
|
||||
if (res < 0 || res >= (int) sizeof(txt))
|
||||
return;
|
||||
|
||||
if (os_strcmp(txt, "1.2.840.113549.1.9.7") == 0) {
|
||||
wpa_printf(MSG_INFO, "TODO: csrattr challengePassword");
|
||||
} else if (os_strcmp(txt, "1.2.840.113549.1.1.11") == 0) {
|
||||
wpa_printf(MSG_INFO, "csrattr sha256WithRSAEncryption");
|
||||
} else {
|
||||
wpa_printf(MSG_INFO, "Ignore unsupported csrattr oid %s", txt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void add_csrattrs_ext_req(struct hs20_osu_client *ctx,
|
||||
STACK_OF(ASN1_OBJECT) *values,
|
||||
STACK_OF(X509_EXTENSION) *exts)
|
||||
{
|
||||
char txt[100];
|
||||
int i, num, res;
|
||||
|
||||
num = sk_ASN1_OBJECT_num(values);
|
||||
for (i = 0; i < num; i++) {
|
||||
ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(values, i);
|
||||
|
||||
res = OBJ_obj2txt(txt, sizeof(txt), oid, 1);
|
||||
if (res < 0 || res >= (int) sizeof(txt))
|
||||
continue;
|
||||
|
||||
if (os_strcmp(txt, "1.3.6.1.1.1.1.22") == 0) {
|
||||
wpa_printf(MSG_INFO, "TODO: extReq macAddress");
|
||||
} else if (os_strcmp(txt, "1.3.6.1.4.1.40808.1.1.3") == 0) {
|
||||
wpa_printf(MSG_INFO, "TODO: extReq imei");
|
||||
} else if (os_strcmp(txt, "1.3.6.1.4.1.40808.1.1.4") == 0) {
|
||||
wpa_printf(MSG_INFO, "TODO: extReq meid");
|
||||
} else if (os_strcmp(txt, "1.3.6.1.4.1.40808.1.1.5") == 0) {
|
||||
wpa_printf(MSG_INFO, "TODO: extReq DevId");
|
||||
} else {
|
||||
wpa_printf(MSG_INFO, "Ignore unsupported cstattr extensionsRequest %s",
|
||||
txt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void add_csrattrs_attr(struct hs20_osu_client *ctx, Attribute *attr,
|
||||
STACK_OF(X509_EXTENSION) *exts)
|
||||
{
|
||||
char txt[100], txt2[100];
|
||||
int i, num, res;
|
||||
|
||||
if (!attr || !attr->type || !attr->values)
|
||||
return;
|
||||
|
||||
res = OBJ_obj2txt(txt, sizeof(txt), attr->type, 1);
|
||||
if (res < 0 || res >= (int) sizeof(txt))
|
||||
return;
|
||||
|
||||
if (os_strcmp(txt, "1.2.840.113549.1.9.14") == 0) {
|
||||
add_csrattrs_ext_req(ctx, attr->values, exts);
|
||||
return;
|
||||
}
|
||||
|
||||
num = sk_ASN1_OBJECT_num(attr->values);
|
||||
for (i = 0; i < num; i++) {
|
||||
ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(attr->values, i);
|
||||
|
||||
res = OBJ_obj2txt(txt2, sizeof(txt2), oid, 1);
|
||||
if (res < 0 || res >= (int) sizeof(txt2))
|
||||
continue;
|
||||
|
||||
wpa_printf(MSG_INFO, "Ignore unsupported cstattr::attr %s oid %s",
|
||||
txt, txt2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void add_csrattrs(struct hs20_osu_client *ctx, CsrAttrs *csrattrs,
|
||||
STACK_OF(X509_EXTENSION) *exts)
|
||||
{
|
||||
int i, num;
|
||||
|
||||
if (!csrattrs || ! csrattrs->attrs)
|
||||
return;
|
||||
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
num = sk_num(CHECKED_CAST(_STACK *, STACK_OF(AttrOrOID) *,
|
||||
csrattrs->attrs));
|
||||
for (i = 0; i < num; i++) {
|
||||
AttrOrOID *ao = sk_value(
|
||||
CHECKED_CAST(_STACK *, const STACK_OF(AttrOrOID) *,
|
||||
csrattrs->attrs), i);
|
||||
switch (ao->type) {
|
||||
case 0:
|
||||
add_csrattrs_oid(ctx, ao->d.oid, exts);
|
||||
break;
|
||||
case 1:
|
||||
add_csrattrs_attr(ctx, ao->d.attribute, exts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else /* OPENSSL_IS_BORINGSSL */
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_IS_BORINGSSL)
|
||||
num = sk_AttrOrOID_num(csrattrs->attrs);
|
||||
#else
|
||||
num = SKM_sk_num(AttrOrOID, csrattrs->attrs);
|
||||
#endif
|
||||
for (i = 0; i < num; i++) {
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_IS_BORINGSSL)
|
||||
AttrOrOID *ao = sk_AttrOrOID_value(csrattrs->attrs, i);
|
||||
#else
|
||||
AttrOrOID *ao = SKM_sk_value(AttrOrOID, csrattrs->attrs, i);
|
||||
#endif
|
||||
switch (ao->type) {
|
||||
case 0:
|
||||
add_csrattrs_oid(ctx, ao->d.oid, exts);
|
||||
break;
|
||||
case 1:
|
||||
add_csrattrs_attr(ctx, ao->d.attribute, exts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* OPENSSL_IS_BORINGSSL */
|
||||
}
|
||||
|
||||
|
||||
static int generate_csr(struct hs20_osu_client *ctx, char *key_pem,
|
||||
char *csr_pem, char *est_req, char *old_cert,
|
||||
CsrAttrs *csrattrs)
|
||||
{
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
RSA *rsa;
|
||||
X509_REQ *req = NULL;
|
||||
int ret = -1;
|
||||
unsigned int val;
|
||||
X509_NAME *subj = NULL;
|
||||
char name[100];
|
||||
STACK_OF(X509_EXTENSION) *exts = NULL;
|
||||
X509_EXTENSION *ex;
|
||||
BIO *out;
|
||||
CONF *ctmp = NULL;
|
||||
|
||||
wpa_printf(MSG_INFO, "Generate RSA private key");
|
||||
write_summary(ctx, "Generate RSA private key");
|
||||
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
|
||||
if (!pctx)
|
||||
return -1;
|
||||
|
||||
if (EVP_PKEY_keygen_init(pctx) <= 0)
|
||||
goto fail;
|
||||
|
||||
if (EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, 2048) <= 0)
|
||||
goto fail;
|
||||
|
||||
if (EVP_PKEY_keygen(pctx, &pkey) <= 0)
|
||||
goto fail;
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
pctx = NULL;
|
||||
|
||||
rsa = EVP_PKEY_get1_RSA(pkey);
|
||||
if (rsa == NULL)
|
||||
goto fail;
|
||||
|
||||
if (key_pem) {
|
||||
FILE *f = fopen(key_pem, "wb");
|
||||
if (f == NULL)
|
||||
goto fail;
|
||||
if (!PEM_write_RSAPrivateKey(f, rsa, NULL, NULL, 0, NULL,
|
||||
NULL)) {
|
||||
wpa_printf(MSG_INFO, "Could not write private key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
fclose(f);
|
||||
goto fail;
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
wpa_printf(MSG_INFO, "Generate CSR");
|
||||
write_summary(ctx, "Generate CSR");
|
||||
req = X509_REQ_new();
|
||||
if (req == NULL)
|
||||
goto fail;
|
||||
|
||||
if (old_cert) {
|
||||
FILE *f;
|
||||
X509 *cert;
|
||||
int res;
|
||||
|
||||
f = fopen(old_cert, "r");
|
||||
if (f == NULL)
|
||||
goto fail;
|
||||
cert = PEM_read_X509(f, NULL, NULL, NULL);
|
||||
fclose(f);
|
||||
|
||||
if (cert == NULL)
|
||||
goto fail;
|
||||
res = X509_REQ_set_subject_name(req,
|
||||
X509_get_subject_name(cert));
|
||||
X509_free(cert);
|
||||
if (!res)
|
||||
goto fail;
|
||||
} else {
|
||||
os_get_random((u8 *) &val, sizeof(val));
|
||||
os_snprintf(name, sizeof(name), "cert-user-%u", val);
|
||||
subj = X509_NAME_new();
|
||||
if (subj == NULL ||
|
||||
!X509_NAME_add_entry_by_txt(subj, "CN", MBSTRING_ASC,
|
||||
(unsigned char *) name,
|
||||
-1, -1, 0) ||
|
||||
!X509_REQ_set_subject_name(req, subj))
|
||||
goto fail;
|
||||
X509_NAME_free(subj);
|
||||
subj = NULL;
|
||||
}
|
||||
|
||||
if (!X509_REQ_set_pubkey(req, pkey))
|
||||
goto fail;
|
||||
|
||||
exts = sk_X509_EXTENSION_new_null();
|
||||
if (!exts)
|
||||
goto fail;
|
||||
|
||||
ex = X509V3_EXT_nconf_nid(ctmp, NULL, NID_basic_constraints,
|
||||
"CA:FALSE");
|
||||
if (ex == NULL ||
|
||||
!sk_X509_EXTENSION_push(exts, ex))
|
||||
goto fail;
|
||||
|
||||
ex = X509V3_EXT_nconf_nid(ctmp, NULL, NID_key_usage,
|
||||
"nonRepudiation,digitalSignature,keyEncipherment");
|
||||
if (ex == NULL ||
|
||||
!sk_X509_EXTENSION_push(exts, ex))
|
||||
goto fail;
|
||||
|
||||
ex = X509V3_EXT_nconf_nid(ctmp, NULL, NID_ext_key_usage,
|
||||
"1.3.6.1.4.1.40808.1.1.2");
|
||||
if (ex == NULL ||
|
||||
!sk_X509_EXTENSION_push(exts, ex))
|
||||
goto fail;
|
||||
|
||||
add_csrattrs(ctx, csrattrs, exts);
|
||||
|
||||
if (!X509_REQ_add_extensions(req, exts))
|
||||
goto fail;
|
||||
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
|
||||
exts = NULL;
|
||||
|
||||
if (!X509_REQ_sign(req, pkey, EVP_sha256()))
|
||||
goto fail;
|
||||
|
||||
out = BIO_new(BIO_s_mem());
|
||||
if (out) {
|
||||
char *txt;
|
||||
size_t rlen;
|
||||
|
||||
#if !defined(ANDROID) || !defined(OPENSSL_IS_BORINGSSL)
|
||||
X509_REQ_print(out, req);
|
||||
#endif
|
||||
rlen = BIO_ctrl_pending(out);
|
||||
txt = os_malloc(rlen + 1);
|
||||
if (txt) {
|
||||
int res = BIO_read(out, txt, rlen);
|
||||
if (res > 0) {
|
||||
txt[res] = '\0';
|
||||
wpa_printf(MSG_MSGDUMP, "OpenSSL: Certificate request:\n%s",
|
||||
txt);
|
||||
}
|
||||
os_free(txt);
|
||||
}
|
||||
BIO_free(out);
|
||||
}
|
||||
|
||||
if (csr_pem) {
|
||||
FILE *f = fopen(csr_pem, "w");
|
||||
if (f == NULL)
|
||||
goto fail;
|
||||
#if !defined(ANDROID) || !defined(OPENSSL_IS_BORINGSSL)
|
||||
X509_REQ_print_fp(f, req);
|
||||
#endif
|
||||
if (!PEM_write_X509_REQ(f, req)) {
|
||||
fclose(f);
|
||||
goto fail;
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
if (est_req) {
|
||||
BIO *mem = BIO_new(BIO_s_mem());
|
||||
BUF_MEM *ptr;
|
||||
char *pos, *end, *buf_end;
|
||||
FILE *f;
|
||||
|
||||
if (mem == NULL)
|
||||
goto fail;
|
||||
if (!PEM_write_bio_X509_REQ(mem, req)) {
|
||||
BIO_free(mem);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
BIO_get_mem_ptr(mem, &ptr);
|
||||
pos = ptr->data;
|
||||
buf_end = pos + ptr->length;
|
||||
|
||||
/* Remove START/END lines */
|
||||
while (pos < buf_end && *pos != '\n')
|
||||
pos++;
|
||||
if (pos == buf_end) {
|
||||
BIO_free(mem);
|
||||
goto fail;
|
||||
}
|
||||
pos++;
|
||||
|
||||
end = pos;
|
||||
while (end < buf_end && *end != '-')
|
||||
end++;
|
||||
|
||||
f = fopen(est_req, "w");
|
||||
if (f == NULL) {
|
||||
BIO_free(mem);
|
||||
goto fail;
|
||||
}
|
||||
fwrite(pos, end - pos, 1, f);
|
||||
fclose(f);
|
||||
|
||||
BIO_free(mem);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
if (exts)
|
||||
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
|
||||
if (subj)
|
||||
X509_NAME_free(subj);
|
||||
if (req)
|
||||
X509_REQ_free(req);
|
||||
if (pkey)
|
||||
EVP_PKEY_free(pkey);
|
||||
if (pctx)
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int est_build_csr(struct hs20_osu_client *ctx, const char *url)
|
||||
{
|
||||
char *buf;
|
||||
size_t buflen;
|
||||
int res;
|
||||
char old_cert_buf[200];
|
||||
char *old_cert = NULL;
|
||||
CsrAttrs *csrattrs = NULL;
|
||||
|
||||
buflen = os_strlen(url) + 100;
|
||||
buf = os_malloc(buflen);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
os_snprintf(buf, buflen, "%s/csrattrs", url);
|
||||
wpa_printf(MSG_INFO, "Download csrattrs from %s", buf);
|
||||
write_summary(ctx, "Download EST csrattrs from %s", buf);
|
||||
ctx->no_osu_cert_validation = 1;
|
||||
http_ocsp_set(ctx->http, 1);
|
||||
res = http_download_file(ctx->http, buf, "Cert/est-csrattrs.txt",
|
||||
ctx->ca_fname);
|
||||
http_ocsp_set(ctx->http,
|
||||
(ctx->workarounds & WORKAROUND_OCSP_OPTIONAL) ? 1 : 2);
|
||||
ctx->no_osu_cert_validation = 0;
|
||||
os_free(buf);
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_INFO, "Failed to download EST csrattrs - assume no extra attributes are needed");
|
||||
} else {
|
||||
size_t resp_len;
|
||||
char *resp;
|
||||
unsigned char *attrs;
|
||||
const unsigned char *pos;
|
||||
size_t attrs_len;
|
||||
|
||||
resp = os_readfile("Cert/est-csrattrs.txt", &resp_len);
|
||||
if (resp == NULL) {
|
||||
wpa_printf(MSG_INFO, "Could not read csrattrs");
|
||||
return -1;
|
||||
}
|
||||
|
||||
attrs = base64_decode(resp, resp_len, &attrs_len);
|
||||
os_free(resp);
|
||||
|
||||
if (attrs == NULL) {
|
||||
wpa_printf(MSG_INFO, "Could not base64 decode csrattrs");
|
||||
return -1;
|
||||
}
|
||||
unlink("Cert/est-csrattrs.txt");
|
||||
|
||||
pos = attrs;
|
||||
csrattrs = d2i_CsrAttrs(NULL, &pos, attrs_len);
|
||||
os_free(attrs);
|
||||
if (csrattrs == NULL) {
|
||||
wpa_printf(MSG_INFO, "Failed to parse csrattrs ASN.1");
|
||||
/* Continue assuming no additional requirements */
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->client_cert_present) {
|
||||
os_snprintf(old_cert_buf, sizeof(old_cert_buf),
|
||||
"SP/%s/client-cert.pem", ctx->fqdn);
|
||||
old_cert = old_cert_buf;
|
||||
}
|
||||
|
||||
res = generate_csr(ctx, "Cert/privkey-plain.pem", "Cert/est-req.pem",
|
||||
"Cert/est-req.b64", old_cert, csrattrs);
|
||||
if (csrattrs)
|
||||
CsrAttrs_free(csrattrs);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int est_simple_enroll(struct hs20_osu_client *ctx, const char *url,
|
||||
const char *user, const char *pw)
|
||||
{
|
||||
char *buf, *resp, *req, *req2;
|
||||
size_t buflen, resp_len, len, pkcs7_len;
|
||||
unsigned char *pkcs7;
|
||||
char client_cert_buf[200];
|
||||
char client_key_buf[200];
|
||||
const char *client_cert = NULL, *client_key = NULL;
|
||||
int res;
|
||||
|
||||
req = os_readfile("Cert/est-req.b64", &len);
|
||||
if (req == NULL) {
|
||||
wpa_printf(MSG_INFO, "Could not read Cert/req.b64");
|
||||
return -1;
|
||||
}
|
||||
req2 = os_realloc(req, len + 1);
|
||||
if (req2 == NULL) {
|
||||
os_free(req);
|
||||
return -1;
|
||||
}
|
||||
req2[len] = '\0';
|
||||
req = req2;
|
||||
wpa_printf(MSG_DEBUG, "EST simpleenroll request: %s", req);
|
||||
|
||||
buflen = os_strlen(url) + 100;
|
||||
buf = os_malloc(buflen);
|
||||
if (buf == NULL) {
|
||||
os_free(req);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ctx->client_cert_present) {
|
||||
os_snprintf(buf, buflen, "%s/simplereenroll", url);
|
||||
os_snprintf(client_cert_buf, sizeof(client_cert_buf),
|
||||
"SP/%s/client-cert.pem", ctx->fqdn);
|
||||
client_cert = client_cert_buf;
|
||||
os_snprintf(client_key_buf, sizeof(client_key_buf),
|
||||
"SP/%s/client-key.pem", ctx->fqdn);
|
||||
client_key = client_key_buf;
|
||||
} else
|
||||
os_snprintf(buf, buflen, "%s/simpleenroll", url);
|
||||
wpa_printf(MSG_INFO, "EST simpleenroll URL: %s", buf);
|
||||
write_summary(ctx, "EST simpleenroll URL: %s", buf);
|
||||
ctx->no_osu_cert_validation = 1;
|
||||
http_ocsp_set(ctx->http, 1);
|
||||
resp = http_post(ctx->http, buf, req, "application/pkcs10",
|
||||
"Content-Transfer-Encoding: base64",
|
||||
ctx->ca_fname, user, pw, client_cert, client_key,
|
||||
&resp_len);
|
||||
http_ocsp_set(ctx->http,
|
||||
(ctx->workarounds & WORKAROUND_OCSP_OPTIONAL) ? 1 : 2);
|
||||
ctx->no_osu_cert_validation = 0;
|
||||
os_free(buf);
|
||||
if (resp == NULL) {
|
||||
wpa_printf(MSG_INFO, "EST certificate enrollment failed");
|
||||
write_result(ctx, "EST certificate enrollment failed");
|
||||
return -1;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "EST simpleenroll response: %s", resp);
|
||||
|
||||
pkcs7 = base64_decode(resp, resp_len, &pkcs7_len);
|
||||
if (pkcs7 == NULL) {
|
||||
wpa_printf(MSG_INFO, "EST workaround - Could not decode base64, assume this is DER encoded PKCS7");
|
||||
pkcs7 = os_malloc(resp_len);
|
||||
if (pkcs7) {
|
||||
os_memcpy(pkcs7, resp, resp_len);
|
||||
pkcs7_len = resp_len;
|
||||
}
|
||||
}
|
||||
os_free(resp);
|
||||
|
||||
if (pkcs7 == NULL) {
|
||||
wpa_printf(MSG_INFO, "Failed to parse simpleenroll base64 response");
|
||||
write_result(ctx, "Failed to parse EST simpleenroll base64 response");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = pkcs7_to_cert(ctx, pkcs7, pkcs7_len, "Cert/est_cert.pem",
|
||||
"Cert/est_cert.der");
|
||||
os_free(pkcs7);
|
||||
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_INFO, "EST: Failed to extract certificate from PKCS7 file");
|
||||
write_result(ctx, "EST: Failed to extract certificate from EST PKCS7 file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_INFO, "EST simple%senroll completed successfully",
|
||||
ctx->client_cert_present ? "re" : "");
|
||||
write_summary(ctx, "EST simple%senroll completed successfully",
|
||||
ctx->client_cert_present ? "re" : "");
|
||||
|
||||
return 0;
|
||||
}
|
1398
hs20/client/oma_dm_client.c
Normal file
1398
hs20/client/oma_dm_client.c
Normal file
File diff suppressed because it is too large
Load Diff
3431
hs20/client/osu_client.c
Normal file
3431
hs20/client/osu_client.c
Normal file
File diff suppressed because it is too large
Load Diff
121
hs20/client/osu_client.h
Normal file
121
hs20/client/osu_client.h
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Hotspot 2.0 - OSU client
|
||||
* Copyright (c) 2013-2014, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSU_CLIENT_H
|
||||
#define OSU_CLIENT_H
|
||||
|
||||
#define SPP_NS_URI "http://www.wi-fi.org/specifications/hotspot2dot0/v1.0/spp"
|
||||
|
||||
#define URN_OMA_DM_DEVINFO "urn:oma:mo:oma-dm-devinfo:1.0"
|
||||
#define URN_OMA_DM_DEVDETAIL "urn:oma:mo:oma-dm-devdetail:1.0"
|
||||
#define URN_HS20_DEVDETAIL_EXT "urn:wfa:mo-ext:hotspot2dot0-devdetail-ext:1.0"
|
||||
#define URN_HS20_PPS "urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0"
|
||||
|
||||
|
||||
#define MAX_OSU_VALS 10
|
||||
|
||||
struct osu_lang_text {
|
||||
char lang[4];
|
||||
char text[253];
|
||||
};
|
||||
|
||||
struct hs20_osu_client {
|
||||
struct xml_node_ctx *xml;
|
||||
struct http_ctx *http;
|
||||
int no_reconnect;
|
||||
char pps_fname[300];
|
||||
char *devid;
|
||||
const char *result_file;
|
||||
const char *summary_file;
|
||||
const char *ifname;
|
||||
const char *ca_fname;
|
||||
int no_osu_cert_validation; /* for EST operations */
|
||||
char *fqdn;
|
||||
char *server_url;
|
||||
struct osu_lang_text friendly_name[MAX_OSU_VALS];
|
||||
size_t friendly_name_count;
|
||||
size_t icon_count;
|
||||
char icon_filename[MAX_OSU_VALS][256];
|
||||
u8 icon_hash[MAX_OSU_VALS][32];
|
||||
int pps_cred_set;
|
||||
int pps_updated;
|
||||
int client_cert_present;
|
||||
char **server_dnsname;
|
||||
size_t server_dnsname_count;
|
||||
const char *osu_ssid; /* Enforced OSU_SSID for testing purposes */
|
||||
#define WORKAROUND_OCSP_OPTIONAL 0x00000001
|
||||
unsigned long int workarounds;
|
||||
int ignore_tls; /* whether to ignore TLS validation issues with HTTPS
|
||||
* server certificate */
|
||||
};
|
||||
|
||||
|
||||
/* osu_client.c */
|
||||
|
||||
void write_result(struct hs20_osu_client *ctx, const char *fmt, ...)
|
||||
__attribute__ ((format (printf, 2, 3)));
|
||||
void write_summary(struct hs20_osu_client *ctx, const char *fmt, ...)
|
||||
__attribute__ ((format (printf, 2, 3)));
|
||||
|
||||
void debug_dump_node(struct hs20_osu_client *ctx, const char *title,
|
||||
xml_node_t *node);
|
||||
int osu_get_certificate(struct hs20_osu_client *ctx, xml_node_t *getcert);
|
||||
int hs20_add_pps_mo(struct hs20_osu_client *ctx, const char *uri,
|
||||
xml_node_t *add_mo, char *fname, size_t fname_len);
|
||||
void get_user_pw(struct hs20_osu_client *ctx, xml_node_t *pps,
|
||||
const char *alt_loc, char **user, char **pw);
|
||||
int update_pps_file(struct hs20_osu_client *ctx, const char *pps_fname,
|
||||
xml_node_t *pps);
|
||||
void cmd_set_pps(struct hs20_osu_client *ctx, const char *pps_fname);
|
||||
|
||||
|
||||
/* spp_client.c */
|
||||
|
||||
void spp_sub_rem(struct hs20_osu_client *ctx, const char *address,
|
||||
const char *pps_fname,
|
||||
const char *client_cert, const char *client_key,
|
||||
const char *cred_username, const char *cred_password,
|
||||
xml_node_t *pps);
|
||||
void spp_pol_upd(struct hs20_osu_client *ctx, const char *address,
|
||||
const char *pps_fname,
|
||||
const char *client_cert, const char *client_key,
|
||||
const char *cred_username, const char *cred_password,
|
||||
xml_node_t *pps);
|
||||
int cmd_prov(struct hs20_osu_client *ctx, const char *url);
|
||||
int cmd_sim_prov(struct hs20_osu_client *ctx, const char *url);
|
||||
|
||||
|
||||
/* oma_dm_client.c */
|
||||
|
||||
int cmd_oma_dm_prov(struct hs20_osu_client *ctx, const char *url);
|
||||
int cmd_oma_dm_sim_prov(struct hs20_osu_client *ctx, const char *url);
|
||||
void oma_dm_sub_rem(struct hs20_osu_client *ctx, const char *address,
|
||||
const char *pps_fname,
|
||||
const char *client_cert, const char *client_key,
|
||||
const char *cred_username, const char *cred_password,
|
||||
xml_node_t *pps);
|
||||
void oma_dm_pol_upd(struct hs20_osu_client *ctx, const char *address,
|
||||
const char *pps_fname,
|
||||
const char *client_cert, const char *client_key,
|
||||
const char *cred_username, const char *cred_password,
|
||||
xml_node_t *pps);
|
||||
void cmd_oma_dm_sub_rem(struct hs20_osu_client *ctx, const char *address,
|
||||
const char *pps_fname);
|
||||
void cmd_oma_dm_add(struct hs20_osu_client *ctx, const char *pps_fname,
|
||||
const char *add_fname);
|
||||
void cmd_oma_dm_replace(struct hs20_osu_client *ctx, const char *pps_fname,
|
||||
const char *replace_fname);
|
||||
|
||||
/* est.c */
|
||||
|
||||
int est_load_cacerts(struct hs20_osu_client *ctx, const char *url);
|
||||
int est_build_csr(struct hs20_osu_client *ctx, const char *url);
|
||||
int est_simple_enroll(struct hs20_osu_client *ctx, const char *url,
|
||||
const char *user, const char *pw);
|
||||
|
||||
#endif /* OSU_CLIENT_H */
|
1004
hs20/client/spp_client.c
Normal file
1004
hs20/client/spp_client.c
Normal file
File diff suppressed because it is too large
Load Diff
1827
wpa_supplicant/Android.mk
Normal file
1827
wpa_supplicant/Android.mk
Normal file
File diff suppressed because it is too large
Load Diff
2500
wpa_supplicant/ChangeLog
Normal file
2500
wpa_supplicant/ChangeLog
Normal file
File diff suppressed because it is too large
Load Diff
2074
wpa_supplicant/Makefile
Normal file
2074
wpa_supplicant/Makefile
Normal file
File diff suppressed because it is too large
Load Diff
1163
wpa_supplicant/README
Normal file
1163
wpa_supplicant/README
Normal file
File diff suppressed because it is too large
Load Diff
204
wpa_supplicant/README-DPP
Normal file
204
wpa_supplicant/README-DPP
Normal file
@ -0,0 +1,204 @@
|
||||
Device Provisioning Protocol (DPP)
|
||||
==================================
|
||||
|
||||
This document describes how the Device Provisioning Protocol (DPP)
|
||||
implementation in wpa_supplicant and hostapd can be configured and how
|
||||
the STA device and AP can be configured to connect each other using DPP
|
||||
Connector mechanism.
|
||||
|
||||
Introduction to DPP
|
||||
-------------------
|
||||
|
||||
Device Provisioning Protocol (also known as Wi-Fi Easy Connect) allows
|
||||
enrolling of interface-less devices in a secure Wi-Fi network using many
|
||||
methods like QR code based authentication (detailed below), PKEX based
|
||||
authentication (password with in-band provisioning), etc. In DPP a
|
||||
Configurator is used to provide network credentials to the devices. The
|
||||
three phases of DPP connection are authentication, configuration and
|
||||
network introduction.
|
||||
|
||||
More information about Wi-Fi Easy Connect is available from this Wi-Fi
|
||||
Alliance web page:
|
||||
https://www.wi-fi.org/discover-wi-fi/wi-fi-easy-connect
|
||||
|
||||
Build config setup
|
||||
------------------
|
||||
|
||||
The following parameters must be included in the config file used to
|
||||
compile hostapd and wpa_supplicant.
|
||||
|
||||
wpa_supplicant build config
|
||||
---------------------------
|
||||
|
||||
Enable DPP in wpa_supplicant build config file
|
||||
|
||||
CONFIG_DPP=y
|
||||
|
||||
hostapd build config
|
||||
--------------------
|
||||
|
||||
Enable DPP in hostapd build config file
|
||||
|
||||
CONFIG_DPP=y
|
||||
|
||||
Configurator build config
|
||||
-------------------------
|
||||
|
||||
Any STA or AP device can act as a Configurator. Enable DPP in build
|
||||
config. For an AP to act as a Configurator, Interworking needs to be
|
||||
enabled for GAS. For wpa_supplicant it is not required.
|
||||
|
||||
CONFIG_INTERWORKING=y
|
||||
|
||||
|
||||
Sample supplicant config file before provisioning
|
||||
-------------------------------------------------
|
||||
|
||||
ctrl_interface=DIR=/var/run/wpa_supplicant
|
||||
ctrl_interface_group=0
|
||||
update_config=1
|
||||
pmf=2
|
||||
dpp_config_processing=2
|
||||
|
||||
Sample hostapd config file before provisioning
|
||||
----------------------------------------------
|
||||
|
||||
interface=wlan0
|
||||
driver=nl80211
|
||||
ctrl_interface=/var/run/hostapd
|
||||
ssid=test
|
||||
channel=1
|
||||
wpa=2
|
||||
wpa_key_mgmt=DPP
|
||||
ieee80211w=1
|
||||
wpa_pairwise=CCMP
|
||||
rsn_pairwise=CCMP
|
||||
|
||||
|
||||
Pre-requisites
|
||||
--------------
|
||||
|
||||
It is assumed that an AP and client station are up by running hostapd
|
||||
and wpa_supplicant using respective config files.
|
||||
|
||||
|
||||
Creating Configurator
|
||||
---------------------
|
||||
|
||||
Add a Configurator over the control interface (wpa_cli/hostapd_cli)
|
||||
|
||||
> dpp_configurator_add
|
||||
(returns id)
|
||||
|
||||
To get key of Configurator
|
||||
> dpp_configurator_get_key <id>
|
||||
|
||||
|
||||
How to configure an Enrollee using Configurator
|
||||
-----------------------------------------------
|
||||
|
||||
On Enrollee side:
|
||||
|
||||
Generate QR code for the device. Store the QR code id returned by the
|
||||
command.
|
||||
|
||||
> dpp_bootstrap_gen type=qrcode mac=<mac-address-of-device> chan=<operating-class/channel> key=<key of the device>
|
||||
(Returns bootstrapping info id. If the key parameter is not included, a new key
|
||||
is generated automatically. The MAC address is specified without octet
|
||||
separating colons. The channel list includes the possible channels on which the
|
||||
device is waiting. This uses global operating classes; e.g., 81/1 is the 2.4
|
||||
GHz channel 1 on 2412 MHz.)
|
||||
|
||||
Get URI for the QR Code of device using the bootstrap info id.
|
||||
> dpp_bootstrap_get_uri <bootstrap-id>
|
||||
|
||||
Make device listen to DPP request. The central frequency of the 2.4 GHz
|
||||
band channel 1 is 2412 MHz) in case the Enrollee is a client device. An
|
||||
AP as an Enrollee is listening on its operating channel.
|
||||
|
||||
> dpp_listen <frequency>
|
||||
|
||||
On Configurator side:
|
||||
|
||||
Enter the QR Code in the Configurator.
|
||||
> dpp_qr_code "<URI-from-QR-Code-read-from-enrollee>"
|
||||
|
||||
On successfully adding QR Code, a bootstrapping info id is returned.
|
||||
|
||||
Send provisioning request to Enrollee. (conf is ap-dpp if Enrollee is an
|
||||
AP. conf is sta-dpp if Enrollee is a client)
|
||||
> dpp_auth_init peer=<qr-code-id> conf=<ap-dpp|sta-dpp> ssid=<SSID hexdump> configurator=<configurator-id>
|
||||
or for legacy (PSK/SAE) provisioning for a station Enrollee:
|
||||
> dpp_auth_init peer=<qr-code-id> conf=sta-psk ssid=<SSID hexdump> pass=<passphrase hexdump>
|
||||
|
||||
The DPP values will be printed in the console. Save these values into the
|
||||
config file. If the Enrollee is an AP, we need to manually write these
|
||||
values to the hostapd config file. If the Enrollee is a client device,
|
||||
these details can be automatically saved to config file using the
|
||||
following command.
|
||||
|
||||
> save_config
|
||||
|
||||
To set values in runtime for AP enrollees
|
||||
|
||||
> set dpp_connector <Connector-value-printed-on-console>
|
||||
> set dpp_csign <csign-value-on-console>
|
||||
> set dpp_netaccesskey <netaccess-value-on-console>
|
||||
|
||||
To set values in runtime for client enrollees, set dpp_config_processing
|
||||
to 2 in wpa_supplicant conf file.
|
||||
|
||||
Once the values are set in run-time (if not set in run-time, but saved
|
||||
in config files, they are taken up in next restart), the client device
|
||||
will automatically connect to the already provisioned AP and connection
|
||||
will be established.
|
||||
|
||||
|
||||
Self-configuring a device
|
||||
-------------------------
|
||||
|
||||
It is possible for a device to configure itself if it is the
|
||||
Configurator for the network.
|
||||
|
||||
Create a Configurator in the device and use the dpp_configurator_sign
|
||||
command to get DPP credentials.
|
||||
|
||||
> dpp_configurator_add
|
||||
(returns configurator id)
|
||||
> dpp_configurator_sign conf=<ap-dpp|sta-dpp> configurator=<configurator-id> ssid=<SSID hexdump>
|
||||
|
||||
|
||||
Sample AP configuration files after provisioning
|
||||
------------------------------------------------
|
||||
|
||||
interface=wlan0
|
||||
driver=nl80211
|
||||
ctrl_interface=/var/run/hostapd
|
||||
ssid=test
|
||||
channel=1
|
||||
wpa=2
|
||||
wpa_key_mgmt=DPP
|
||||
ieee80211w=1
|
||||
wpa_pairwise=CCMP
|
||||
rsn_pairwise=CCMP
|
||||
dpp_connector=<Connector value provided by Configurator>
|
||||
dpp_csign=<C-Sign-Key value provided by Configurator>
|
||||
dpp_netaccesskey=<Net access key provided by Configurator>
|
||||
|
||||
|
||||
Sample station configuration file after provisioning
|
||||
----------------------------------------------------
|
||||
|
||||
ctrl_interface=DIR=/var/run/wpa_supplicant
|
||||
ctrl_interface_group=0
|
||||
update_config=1
|
||||
pmf=2
|
||||
dpp_config_processing=2
|
||||
network={
|
||||
ssid="test"
|
||||
key_mgmt=DPP
|
||||
ieee80211w=2
|
||||
dpp_connector="<Connector value provided by Configurator>"
|
||||
dpp_netaccesskey=<Net access key provided by Configurator>
|
||||
dpp_csign=<C-sign-key value provided by Configurator>
|
||||
}
|
654
wpa_supplicant/README-HS20
Normal file
654
wpa_supplicant/README-HS20
Normal file
@ -0,0 +1,654 @@
|
||||
wpa_supplicant and Hotspot 2.0
|
||||
==============================
|
||||
|
||||
This document describe how the IEEE 802.11u Interworking and Wi-Fi
|
||||
Hotspot 2.0 (Release 1) implementation in wpa_supplicant can be
|
||||
configured and how an external component on the client e.g., management
|
||||
GUI or Wi-Fi framework) is used to manage this functionality.
|
||||
|
||||
|
||||
Introduction to Wi-Fi Hotspot 2.0
|
||||
---------------------------------
|
||||
|
||||
Hotspot 2.0 is the name of the Wi-Fi Alliance specification that is used
|
||||
in the Wi-Fi CERTIFIED Passpoint<TM> program. More information about
|
||||
this is available in this white paper:
|
||||
|
||||
http://www.wi-fi.org/knowledge-center/white-papers/wi-fi-certified-passpoint%E2%84%A2-new-program-wi-fi-alliance%C2%AE-enable-seamless
|
||||
|
||||
The Hotspot 2.0 specification is also available from WFA:
|
||||
https://www.wi-fi.org/knowledge-center/published-specifications
|
||||
|
||||
The core Interworking functionality (network selection, GAS/ANQP) were
|
||||
standardized in IEEE Std 802.11u-2011 which is now part of the IEEE Std
|
||||
802.11-2012.
|
||||
|
||||
|
||||
wpa_supplicant network selection
|
||||
--------------------------------
|
||||
|
||||
Interworking support added option for configuring credentials that can
|
||||
work with multiple networks as an alternative to configuration of
|
||||
network blocks (e.g., per-SSID parameters). When requested to perform
|
||||
network selection, wpa_supplicant picks the highest priority enabled
|
||||
network block or credential. If a credential is picked (based on ANQP
|
||||
information from APs), a temporary network block is created
|
||||
automatically for the matching network. This temporary network block is
|
||||
used similarly to the network blocks that can be configured by the user,
|
||||
but it is not stored into the configuration file and is meant to be used
|
||||
only for temporary period of time since a new one can be created
|
||||
whenever needed based on ANQP information and the credential.
|
||||
|
||||
By default, wpa_supplicant is not using automatic network selection
|
||||
unless requested explicitly with the interworking_select command. This
|
||||
can be changed with the auto_interworking=1 parameter to perform network
|
||||
selection automatically whenever trying to find a network for connection
|
||||
and none of the enabled network blocks match with the scan results. This
|
||||
case works similarly to "interworking_select auto", i.e., wpa_supplicant
|
||||
will internally determine which network or credential is going to be
|
||||
used based on configured priorities, scan results, and ANQP information.
|
||||
|
||||
|
||||
wpa_supplicant configuration
|
||||
----------------------------
|
||||
|
||||
Interworking and Hotspot 2.0 functionality are optional components that
|
||||
need to be enabled in the wpa_supplicant build configuration
|
||||
(.config). This is done by adding following parameters into that file:
|
||||
|
||||
CONFIG_INTERWORKING=y
|
||||
CONFIG_HS20=y
|
||||
|
||||
It should be noted that this functionality requires a driver that
|
||||
supports GAS/ANQP operations. This uses the same design as P2P, i.e.,
|
||||
Action frame processing and building in user space within
|
||||
wpa_supplicant. The Linux nl80211 driver interface provides the needed
|
||||
functionality for this.
|
||||
|
||||
|
||||
There are number of run-time configuration parameters (e.g., in
|
||||
wpa_supplicant.conf when using the configuration file) that can be used
|
||||
to control Hotspot 2.0 operations.
|
||||
|
||||
# Enable Interworking
|
||||
interworking=1
|
||||
|
||||
# Enable Hotspot 2.0
|
||||
hs20=1
|
||||
|
||||
# Parameters for controlling scanning
|
||||
|
||||
# Homogeneous ESS identifier
|
||||
# If this is set, scans will be used to request response only from BSSes
|
||||
# belonging to the specified Homogeneous ESS. This is used only if interworking
|
||||
# is enabled.
|
||||
#hessid=00:11:22:33:44:55
|
||||
|
||||
# Access Network Type
|
||||
# When Interworking is enabled, scans can be limited to APs that advertise the
|
||||
# specified Access Network Type (0..15; with 15 indicating wildcard match).
|
||||
# This value controls the Access Network Type value in Probe Request frames.
|
||||
#access_network_type=15
|
||||
|
||||
# Automatic network selection behavior
|
||||
# 0 = do not automatically go through Interworking network selection
|
||||
# (i.e., require explicit interworking_select command for this; default)
|
||||
# 1 = perform Interworking network selection if one or more
|
||||
# credentials have been configured and scan did not find a
|
||||
# matching network block
|
||||
#auto_interworking=0
|
||||
|
||||
|
||||
Credentials can be pre-configured for automatic network selection:
|
||||
|
||||
# credential block
|
||||
#
|
||||
# Each credential used for automatic network selection is configured as a set
|
||||
# of parameters that are compared to the information advertised by the APs when
|
||||
# interworking_select and interworking_connect commands are used.
|
||||
#
|
||||
# credential fields:
|
||||
#
|
||||
# temporary: Whether this credential is temporary and not to be saved
|
||||
#
|
||||
# priority: Priority group
|
||||
# By default, all networks and credentials get the same priority group
|
||||
# (0). This field can be used to give higher priority for credentials
|
||||
# (and similarly in struct wpa_ssid for network blocks) to change the
|
||||
# Interworking automatic networking selection behavior. The matching
|
||||
# network (based on either an enabled network block or a credential)
|
||||
# with the highest priority value will be selected.
|
||||
#
|
||||
# pcsc: Use PC/SC and SIM/USIM card
|
||||
#
|
||||
# realm: Home Realm for Interworking
|
||||
#
|
||||
# username: Username for Interworking network selection
|
||||
#
|
||||
# password: Password for Interworking network selection
|
||||
#
|
||||
# ca_cert: CA certificate for Interworking network selection
|
||||
#
|
||||
# client_cert: File path to client certificate file (PEM/DER)
|
||||
# This field is used with Interworking networking selection for a case
|
||||
# where client certificate/private key is used for authentication
|
||||
# (EAP-TLS). Full path to the file should be used since working
|
||||
# directory may change when wpa_supplicant is run in the background.
|
||||
#
|
||||
# Alternatively, a named configuration blob can be used by setting
|
||||
# this to blob://blob_name.
|
||||
#
|
||||
# private_key: File path to client private key file (PEM/DER/PFX)
|
||||
# When PKCS#12/PFX file (.p12/.pfx) is used, client_cert should be
|
||||
# commented out. Both the private key and certificate will be read
|
||||
# from the PKCS#12 file in this case. Full path to the file should be
|
||||
# used since working directory may change when wpa_supplicant is run
|
||||
# in the background.
|
||||
#
|
||||
# Windows certificate store can be used by leaving client_cert out and
|
||||
# configuring private_key in one of the following formats:
|
||||
#
|
||||
# cert://substring_to_match
|
||||
#
|
||||
# hash://certificate_thumbprint_in_hex
|
||||
#
|
||||
# For example: private_key="hash://63093aa9c47f56ae88334c7b65a4"
|
||||
#
|
||||
# Note that when running wpa_supplicant as an application, the user
|
||||
# certificate store (My user account) is used, whereas computer store
|
||||
# (Computer account) is used when running wpasvc as a service.
|
||||
#
|
||||
# Alternatively, a named configuration blob can be used by setting
|
||||
# this to blob://blob_name.
|
||||
#
|
||||
# private_key_passwd: Password for private key file
|
||||
#
|
||||
# imsi: IMSI in <MCC> | <MNC> | '-' | <MSIN> format
|
||||
#
|
||||
# milenage: Milenage parameters for SIM/USIM simulator in <Ki>:<OPc>:<SQN>
|
||||
# format
|
||||
#
|
||||
# domain_suffix_match: Constraint for server domain name
|
||||
# If set, this FQDN is used as a suffix match requirement for the AAA
|
||||
# server certificate in SubjectAltName dNSName element(s). If a
|
||||
# matching dNSName is found, this constraint is met. If no dNSName
|
||||
# values are present, this constraint is matched against SubjectName CN
|
||||
# using same suffix match comparison. Suffix match here means that the
|
||||
# host/domain name is compared one label at a time starting from the
|
||||
# top-level domain and all the labels in @domain_suffix_match shall be
|
||||
# included in the certificate. The certificate may include additional
|
||||
# sub-level labels in addition to the required labels.
|
||||
#
|
||||
# For example, domain_suffix_match=example.com would match
|
||||
# test.example.com but would not match test-example.com.
|
||||
#
|
||||
# domain: Home service provider FQDN(s)
|
||||
# This is used to compare against the Domain Name List to figure out
|
||||
# whether the AP is operated by the Home SP. Multiple domain entries can
|
||||
# be used to configure alternative FQDNs that will be considered home
|
||||
# networks.
|
||||
#
|
||||
# roaming_consortium: Roaming Consortium OI
|
||||
# If roaming_consortium_len is non-zero, this field contains the
|
||||
# Roaming Consortium OI that can be used to determine which access
|
||||
# points support authentication with this credential. This is an
|
||||
# alternative to the use of the realm parameter. When using Roaming
|
||||
# Consortium to match the network, the EAP parameters need to be
|
||||
# pre-configured with the credential since the NAI Realm information
|
||||
# may not be available or fetched.
|
||||
#
|
||||
# required_roaming_consortium: Required Roaming Consortium OI
|
||||
# If required_roaming_consortium_len is non-zero, this field contains the
|
||||
# Roaming Consortium OI that is required to be advertised by the AP for
|
||||
# the credential to be considered matching.
|
||||
#
|
||||
# roaming_consortiums: Roaming Consortium OI(s) memberships
|
||||
# This string field contains one or more comma delimited OIs (hexdump)
|
||||
# identifying the roaming consortiums of which the provider is a member.
|
||||
# The list is sorted from the most preferred one to the least preferred
|
||||
# one. A match between the Roaming Consortium OIs advertised by an AP and
|
||||
# the OIs in this list indicates that successful authentication is
|
||||
# possible.
|
||||
# (Hotspot 2.0 PerProviderSubscription/<X+>/HomeSP/RoamingConsortiumOI)
|
||||
#
|
||||
# eap: Pre-configured EAP method
|
||||
# This optional field can be used to specify which EAP method will be
|
||||
# used with this credential. If not set, the EAP method is selected
|
||||
# automatically based on ANQP information (e.g., NAI Realm).
|
||||
#
|
||||
# phase1: Pre-configure Phase 1 (outer authentication) parameters
|
||||
# This optional field is used with like the 'eap' parameter.
|
||||
#
|
||||
# phase2: Pre-configure Phase 2 (inner authentication) parameters
|
||||
# This optional field is used with like the 'eap' parameter.
|
||||
#
|
||||
# excluded_ssid: Excluded SSID
|
||||
# This optional field can be used to excluded specific SSID(s) from
|
||||
# matching with the network. Multiple entries can be used to specify more
|
||||
# than one SSID.
|
||||
#
|
||||
# roaming_partner: Roaming partner information
|
||||
# This optional field can be used to configure preferences between roaming
|
||||
# partners. The field is a string in following format:
|
||||
# <FQDN>,<0/1 exact match>,<priority>,<* or country code>
|
||||
# (non-exact match means any subdomain matches the entry; priority is in
|
||||
# 0..255 range with 0 being the highest priority)
|
||||
#
|
||||
# update_identifier: PPS MO ID
|
||||
# (Hotspot 2.0 PerProviderSubscription/UpdateIdentifier)
|
||||
#
|
||||
# provisioning_sp: FQDN of the SP that provisioned the credential
|
||||
# This optional field can be used to keep track of the SP that provisioned
|
||||
# the credential to find the PPS MO (./Wi-Fi/<provisioning_sp>).
|
||||
#
|
||||
# sp_priority: Credential priority within a provisioning SP
|
||||
# This is the priority of the credential among all credentials
|
||||
# provisioned by the same SP (i.e., for entries that have identical
|
||||
# provisioning_sp value). The range of this priority is 0-255 with 0
|
||||
# being the highest and 255 the lower priority.
|
||||
#
|
||||
# Minimum backhaul threshold (PPS/<X+>/Policy/MinBackhauldThreshold/*)
|
||||
# These fields can be used to specify minimum download/upload backhaul
|
||||
# bandwidth that is preferred for the credential. This constraint is
|
||||
# ignored if the AP does not advertise WAN Metrics information or if the
|
||||
# limit would prevent any connection. Values are in kilobits per second.
|
||||
# min_dl_bandwidth_home
|
||||
# min_ul_bandwidth_home
|
||||
# min_dl_bandwidth_roaming
|
||||
# min_ul_bandwidth_roaming
|
||||
#
|
||||
# max_bss_load: Maximum BSS Load Channel Utilization (1..255)
|
||||
# (PPS/<X+>/Policy/MaximumBSSLoadValue)
|
||||
# This value is used as the maximum channel utilization for network
|
||||
# selection purposes for home networks. If the AP does not advertise
|
||||
# BSS Load or if the limit would prevent any connection, this constraint
|
||||
# will be ignored.
|
||||
#
|
||||
# req_conn_capab: Required connection capability
|
||||
# (PPS/<X+>/Policy/RequiredProtoPortTuple)
|
||||
# This value is used to configure set of required protocol/port pairs that
|
||||
# a roaming network shall support (include explicitly in Connection
|
||||
# Capability ANQP element). This constraint is ignored if the AP does not
|
||||
# advertise Connection Capability or if this constraint would prevent any
|
||||
# network connection. This policy is not used in home networks.
|
||||
# Format: <protocol>[:<comma-separated list of ports]
|
||||
# Multiple entries can be used to list multiple requirements.
|
||||
# For example, number of common TCP protocols:
|
||||
# req_conn_capab=6:22,80,443
|
||||
# For example, IPSec/IKE:
|
||||
# req_conn_capab=17:500
|
||||
# req_conn_capab=50
|
||||
#
|
||||
# ocsp: Whether to use/require OCSP to check server certificate
|
||||
# 0 = do not use OCSP stapling (TLS certificate status extension)
|
||||
# 1 = try to use OCSP stapling, but not require response
|
||||
# 2 = require valid OCSP stapling response
|
||||
#
|
||||
# sim_num: Identifier for which SIM to use in multi-SIM devices
|
||||
#
|
||||
# engine: Whether to use an engine for private key operations (0/1)
|
||||
# engine_id: String identifying the engine to use
|
||||
# ca_cert_id: The CA certificate identifier when using an engine
|
||||
# cert_id: The certificate identifier when using an engine
|
||||
# key_id: The private key identifier when using an engine
|
||||
#
|
||||
# for example:
|
||||
#
|
||||
#cred={
|
||||
# realm="example.com"
|
||||
# username="user@example.com"
|
||||
# password="password"
|
||||
# ca_cert="/etc/wpa_supplicant/ca.pem"
|
||||
# domain="example.com"
|
||||
# domain_suffix_match="example.com"
|
||||
#}
|
||||
#
|
||||
#cred={
|
||||
# imsi="310026-000000000"
|
||||
# milenage="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82"
|
||||
#}
|
||||
#
|
||||
#cred={
|
||||
# realm="example.com"
|
||||
# username="user"
|
||||
# password="password"
|
||||
# ca_cert="/etc/wpa_supplicant/ca.pem"
|
||||
# domain="example.com"
|
||||
# roaming_consortium=223344
|
||||
# roaming_consortiums="112233,4455667788,aabbcc"
|
||||
# eap=TTLS
|
||||
# phase2="auth=MSCHAPV2"
|
||||
#}
|
||||
|
||||
|
||||
Control interface
|
||||
-----------------
|
||||
|
||||
wpa_supplicant provides a control interface that can be used from
|
||||
external programs to manage various operations. The included command
|
||||
line tool, wpa_cli, can be used for manual testing with this interface.
|
||||
|
||||
Following wpa_cli interactive mode commands show some examples of manual
|
||||
operations related to Hotspot 2.0:
|
||||
|
||||
Remove configured networks and credentials:
|
||||
|
||||
> remove_network all
|
||||
OK
|
||||
> remove_cred all
|
||||
OK
|
||||
|
||||
|
||||
Add a username/password credential:
|
||||
|
||||
> add_cred
|
||||
0
|
||||
> set_cred 0 realm "mail.example.com"
|
||||
OK
|
||||
> set_cred 0 username "username"
|
||||
OK
|
||||
> set_cred 0 password "password"
|
||||
OK
|
||||
> set_cred 0 priority 1
|
||||
OK
|
||||
> set_cred 0 temporary 1
|
||||
OK
|
||||
|
||||
Add a SIM credential using a simulated SIM/USIM card for testing:
|
||||
|
||||
> add_cred
|
||||
1
|
||||
> set_cred 1 imsi "23456-0000000000"
|
||||
OK
|
||||
> set_cred 1 milenage "90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123"
|
||||
OK
|
||||
> set_cred 1 priority 1
|
||||
OK
|
||||
|
||||
Note: the return value of add_cred is used as the first argument to
|
||||
the following set_cred commands.
|
||||
|
||||
Add a SIM credential using a external SIM/USIM processing:
|
||||
|
||||
> set external_sim 1
|
||||
OK
|
||||
> add_cred
|
||||
1
|
||||
> set_cred 1 imsi "23456-0000000000"
|
||||
OK
|
||||
> set_cred 1 eap SIM
|
||||
OK
|
||||
|
||||
|
||||
Add a WPA2-Enterprise network:
|
||||
|
||||
> add_network
|
||||
0
|
||||
> set_network 0 key_mgmt WPA-EAP
|
||||
OK
|
||||
> set_network 0 ssid "enterprise"
|
||||
OK
|
||||
> set_network 0 eap TTLS
|
||||
OK
|
||||
> set_network 0 anonymous_identity "anonymous"
|
||||
OK
|
||||
> set_network 0 identity "user"
|
||||
OK
|
||||
> set_network 0 password "password"
|
||||
OK
|
||||
> set_network 0 priority 0
|
||||
OK
|
||||
> enable_network 0 no-connect
|
||||
OK
|
||||
|
||||
|
||||
Add an open network:
|
||||
|
||||
> add_network
|
||||
3
|
||||
> set_network 3 key_mgmt NONE
|
||||
OK
|
||||
> set_network 3 ssid "coffee-shop"
|
||||
OK
|
||||
> select_network 3
|
||||
OK
|
||||
|
||||
Note: the return value of add_network is used as the first argument to
|
||||
the following set_network commands.
|
||||
|
||||
The preferred credentials/networks can be indicated with the priority
|
||||
parameter (1 is higher priority than 0).
|
||||
|
||||
|
||||
Interworking network selection can be started with interworking_select
|
||||
command. This instructs wpa_supplicant to run a network scan and iterate
|
||||
through the discovered APs to request ANQP information from the APs that
|
||||
advertise support for Interworking/Hotspot 2.0:
|
||||
|
||||
> interworking_select
|
||||
OK
|
||||
<3>Starting ANQP fetch for 02:00:00:00:01:00
|
||||
<3>RX-ANQP 02:00:00:00:01:00 ANQP Capability list
|
||||
<3>RX-ANQP 02:00:00:00:01:00 Roaming Consortium list
|
||||
<3>RX-HS20-ANQP 02:00:00:00:01:00 HS Capability List
|
||||
<3>ANQP fetch completed
|
||||
<3>INTERWORKING-AP 02:00:00:00:01:00 type=unknown
|
||||
|
||||
|
||||
INTERWORKING-AP event messages indicate the APs that support network
|
||||
selection and for which there is a matching
|
||||
credential. interworking_connect command can be used to select a network
|
||||
to connect with:
|
||||
|
||||
|
||||
> interworking_connect 02:00:00:00:01:00
|
||||
OK
|
||||
<3>CTRL-EVENT-SCAN-RESULTS
|
||||
<3>SME: Trying to authenticate with 02:00:00:00:01:00 (SSID='Example Network' freq=2412 MHz)
|
||||
<3>Trying to associate with 02:00:00:00:01:00 (SSID='Example Network' freq=2412 MHz)
|
||||
<3>Associated with 02:00:00:00:01:00
|
||||
<3>CTRL-EVENT-EAP-STARTED EAP authentication started
|
||||
<3>CTRL-EVENT-EAP-PROPOSED-METHOD vendor=0 method=21
|
||||
<3>CTRL-EVENT-EAP-METHOD EAP vendor 0 method 21 (TTLS) selected
|
||||
<3>CTRL-EVENT-EAP-SUCCESS EAP authentication completed successfully
|
||||
<3>WPA: Key negotiation completed with 02:00:00:00:01:00 [PTK=CCMP GTK=CCMP]
|
||||
<3>CTRL-EVENT-CONNECTED - Connection to 02:00:00:00:01:00 completed (auth) [id=0 id_str=]
|
||||
|
||||
|
||||
wpa_supplicant creates a temporary network block for the selected
|
||||
network based on the configured credential and ANQP information from the
|
||||
AP:
|
||||
|
||||
> list_networks
|
||||
network id / ssid / bssid / flags
|
||||
0 Example Network any [CURRENT]
|
||||
> get_network 0 key_mgmt
|
||||
WPA-EAP
|
||||
> get_network 0 eap
|
||||
TTLS
|
||||
|
||||
|
||||
Alternatively to using an external program to select the network,
|
||||
"interworking_select auto" command can be used to request wpa_supplicant
|
||||
to select which network to use based on configured priorities:
|
||||
|
||||
|
||||
> remove_network all
|
||||
OK
|
||||
<3>CTRL-EVENT-DISCONNECTED bssid=02:00:00:00:01:00 reason=1 locally_generated=1
|
||||
> interworking_select auto
|
||||
OK
|
||||
<3>Starting ANQP fetch for 02:00:00:00:01:00
|
||||
<3>RX-ANQP 02:00:00:00:01:00 ANQP Capability list
|
||||
<3>RX-ANQP 02:00:00:00:01:00 Roaming Consortium list
|
||||
<3>RX-HS20-ANQP 02:00:00:00:01:00 HS Capability List
|
||||
<3>ANQP fetch completed
|
||||
<3>INTERWORKING-AP 02:00:00:00:01:00 type=unknown
|
||||
<3>CTRL-EVENT-SCAN-RESULTS
|
||||
<3>SME: Trying to authenticate with 02:00:00:00:01:00 (SSID='Example Network' freq=2412 MHz)
|
||||
<3>Trying to associate with 02:00:00:00:01:00 (SSID='Example Network' freq=2412 MHz)
|
||||
<3>Associated with 02:00:00:00:01:00
|
||||
<3>CTRL-EVENT-EAP-STARTED EAP authentication started
|
||||
<3>CTRL-EVENT-EAP-PROPOSED-METHOD vendor=0 method=21
|
||||
<3>CTRL-EVENT-EAP-METHOD EAP vendor 0 method 21 (TTLS) selected
|
||||
<3>CTRL-EVENT-EAP-SUCCESS EAP authentication completed successfully
|
||||
<3>WPA: Key negotiation completed with 02:00:00:00:01:00 [PTK=CCMP GTK=CCMP]
|
||||
<3>CTRL-EVENT-CONNECTED - Connection to 02:00:00:00:01:00 completed (reauth) [id=0 id_str=]
|
||||
|
||||
|
||||
The connection status can be shown with the status command:
|
||||
|
||||
> status
|
||||
bssid=02:00:00:00:01:00
|
||||
ssid=Example Network
|
||||
id=0
|
||||
mode=station
|
||||
pairwise_cipher=CCMP <--- link layer security indication
|
||||
group_cipher=CCMP
|
||||
key_mgmt=WPA2/IEEE 802.1X/EAP
|
||||
wpa_state=COMPLETED
|
||||
p2p_device_address=02:00:00:00:00:00
|
||||
address=02:00:00:00:00:00
|
||||
hs20=1 <--- HS 2.0 indication
|
||||
Supplicant PAE state=AUTHENTICATED
|
||||
suppPortStatus=Authorized
|
||||
EAP state=SUCCESS
|
||||
selectedMethod=21 (EAP-TTLS)
|
||||
EAP TLS cipher=AES-128-SHA
|
||||
EAP-TTLSv0 Phase2 method=PAP
|
||||
|
||||
|
||||
> status
|
||||
bssid=02:00:00:00:02:00
|
||||
ssid=coffee-shop
|
||||
id=3
|
||||
mode=station
|
||||
pairwise_cipher=NONE
|
||||
group_cipher=NONE
|
||||
key_mgmt=NONE
|
||||
wpa_state=COMPLETED
|
||||
p2p_device_address=02:00:00:00:00:00
|
||||
address=02:00:00:00:00:00
|
||||
|
||||
|
||||
Note: The Hotspot 2.0 indication is shown as "hs20=1" in the status
|
||||
command output. Link layer security is indicated with the
|
||||
pairwise_cipher (CCMP = secure, NONE = no encryption used).
|
||||
|
||||
|
||||
Also the scan results include the Hotspot 2.0 indication:
|
||||
|
||||
> scan_results
|
||||
bssid / frequency / signal level / flags / ssid
|
||||
02:00:00:00:01:00 2412 -30 [WPA2-EAP-CCMP][ESS][HS20] Example Network
|
||||
|
||||
|
||||
ANQP information for the BSS can be fetched using the BSS command:
|
||||
|
||||
> bss 02:00:00:00:01:00
|
||||
id=1
|
||||
bssid=02:00:00:00:01:00
|
||||
freq=2412
|
||||
beacon_int=100
|
||||
capabilities=0x0411
|
||||
qual=0
|
||||
noise=-92
|
||||
level=-30
|
||||
tsf=1345573286517276
|
||||
age=105
|
||||
ie=000f4578616d706c65204e6574776f726b010882848b960c1218240301012a010432043048606c30140100000fac040100000fac040100000fac0100007f04000000806b091e07010203040506076c027f006f1001531122331020304050010203040506dd05506f9a1000
|
||||
flags=[WPA2-EAP-CCMP][ESS][HS20]
|
||||
ssid=Example Network
|
||||
anqp_roaming_consortium=031122330510203040500601020304050603fedcba
|
||||
|
||||
|
||||
ANQP queries can also be requested with the anqp_get and hs20_anqp_get
|
||||
commands:
|
||||
|
||||
> anqp_get 02:00:00:00:01:00 261
|
||||
OK
|
||||
<3>RX-ANQP 02:00:00:00:01:00 Roaming Consortium list
|
||||
> hs20_anqp_get 02:00:00:00:01:00 2
|
||||
OK
|
||||
<3>RX-HS20-ANQP 02:00:00:00:01:00 HS Capability List
|
||||
|
||||
In addition, fetch_anqp command can be used to request similar set of
|
||||
ANQP queries to be done as is run as part of interworking_select:
|
||||
|
||||
> scan
|
||||
OK
|
||||
<3>CTRL-EVENT-SCAN-RESULTS
|
||||
> fetch_anqp
|
||||
OK
|
||||
<3>Starting ANQP fetch for 02:00:00:00:01:00
|
||||
<3>RX-ANQP 02:00:00:00:01:00 ANQP Capability list
|
||||
<3>RX-ANQP 02:00:00:00:01:00 Roaming Consortium list
|
||||
<3>RX-HS20-ANQP 02:00:00:00:01:00 HS Capability List
|
||||
<3>ANQP fetch completed
|
||||
|
||||
|
||||
Hotspot 2.0 Rel 2 online signup and OSEN
|
||||
----------------------------------------
|
||||
|
||||
Following parameters can be used to create a network profile for
|
||||
link-layer protected Hotspot 2.0 online signup connection with
|
||||
OSEN. Note that ssid and identify (NAI) values need to be set based on
|
||||
the information for the selected provider in the OSU Providers list
|
||||
ANQP-element.
|
||||
|
||||
network={
|
||||
ssid="HS 2.0 OSU"
|
||||
proto=OSEN
|
||||
key_mgmt=OSEN
|
||||
pairwise=CCMP
|
||||
group=GTK_NOT_USED
|
||||
eap=WFA-UNAUTH-TLS
|
||||
identity="anonymous@example.com"
|
||||
ca_cert="osu-ca.pem"
|
||||
ocsp=2
|
||||
}
|
||||
|
||||
|
||||
Hotspot 2.0 connection with external network selection
|
||||
------------------------------------------------------
|
||||
|
||||
When a component controlling wpa_supplicant takes care of Interworking
|
||||
network selection, following configuration and network profile
|
||||
parameters can be used to configure a temporary network profile for a
|
||||
Hotspot 2.0 connection (e.g., with SET, ADD_NETWORK, SET_NETWORK, and
|
||||
SELECT_NETWORK control interface commands):
|
||||
|
||||
interworking=1
|
||||
hs20=1
|
||||
auto_interworking=0
|
||||
|
||||
network={
|
||||
ssid="test-hs20"
|
||||
proto=RSN
|
||||
key_mgmt=WPA-EAP
|
||||
pairwise=CCMP
|
||||
anonymous_identity="anonymous@example.com"
|
||||
identity="hs20-test@example.com"
|
||||
password="password"
|
||||
ca_cert="ca.pem"
|
||||
eap=TTLS
|
||||
phase2="auth=MSCHAPV2"
|
||||
update_identifier=54321
|
||||
roaming_consortium_selection=112233
|
||||
#ocsp=2
|
||||
}
|
||||
|
||||
|
||||
These parameters are set based on the PPS MO credential and/or NAI Realm
|
||||
list ANQP-element:
|
||||
|
||||
anonymous_identity: Credential/UsernamePassword/Username with username part
|
||||
replaced with "anonymous"
|
||||
identity: Credential/UsernamePassword/Username
|
||||
password: Credential/UsernamePassword/Password
|
||||
update_identifier: PPS/UpdateIdentifier
|
||||
ca_cert: from the downloaded trust root based on PPS information
|
||||
eap: Credential/UsernamePassword/EAPMethod or NAI Realm list
|
||||
phase2: Credential/UsernamePassword/EAPMethod or NAI Realm list
|
||||
roaming_consortium_selection: Matching OI from HomeSP/RoamingConsortiumOI
|
||||
ocsp: Credential/CheckAAAServerCertStatus
|
856
wpa_supplicant/README-P2P
Normal file
856
wpa_supplicant/README-P2P
Normal file
@ -0,0 +1,856 @@
|
||||
wpa_supplicant and Wi-Fi P2P
|
||||
============================
|
||||
|
||||
This document describes how the Wi-Fi P2P implementation in
|
||||
wpa_supplicant can be configured and how an external component on the
|
||||
client (e.g., management GUI) is used to enable WPS enrollment and
|
||||
registrar registration.
|
||||
|
||||
|
||||
Introduction to Wi-Fi P2P
|
||||
-------------------------
|
||||
|
||||
TODO
|
||||
|
||||
More information about Wi-Fi P2P is available from Wi-Fi Alliance:
|
||||
http://www.wi-fi.org/Wi-Fi_Direct.php
|
||||
|
||||
|
||||
wpa_supplicant implementation
|
||||
-----------------------------
|
||||
|
||||
TODO
|
||||
|
||||
|
||||
wpa_supplicant configuration
|
||||
----------------------------
|
||||
|
||||
Wi-Fi P2P is an optional component that needs to be enabled in the
|
||||
wpa_supplicant build configuration (.config). Here is an example
|
||||
configuration that includes Wi-Fi P2P support and Linux nl80211
|
||||
-based driver interface:
|
||||
|
||||
CONFIG_DRIVER_NL80211=y
|
||||
CONFIG_CTRL_IFACE=y
|
||||
CONFIG_P2P=y
|
||||
CONFIG_AP=y
|
||||
CONFIG_WPS=y
|
||||
|
||||
|
||||
In run-time configuration file (wpa_supplicant.conf), some parameters
|
||||
for P2P may be set. In order to make the devices easier to recognize,
|
||||
device_name and device_type should be specified. For example,
|
||||
something like this should be included:
|
||||
|
||||
ctrl_interface=/var/run/wpa_supplicant
|
||||
device_name=My P2P Device
|
||||
device_type=1-0050F204-1
|
||||
|
||||
|
||||
wpa_cli
|
||||
-------
|
||||
|
||||
Actual Wi-Fi P2P operations are requested during runtime. These can be
|
||||
done for example using wpa_cli (which is described below) or a GUI
|
||||
like wpa_gui-qt4.
|
||||
|
||||
|
||||
wpa_cli starts in interactive mode if no command string is included on
|
||||
the command line. By default, it will select the first network interface
|
||||
that it can find (and that wpa_supplicant controls). If more than one
|
||||
interface is in use, it may be necessary to select one of the explicitly
|
||||
by adding -i argument on the command line (e.g., 'wpa_cli -i wlan1').
|
||||
|
||||
Most of the P2P operations are done on the main interface (e.g., the
|
||||
interface that is automatically added when the driver is loaded, e.g.,
|
||||
wlan0). When using a separate virtual interface for group operations
|
||||
(e.g., wlan1), the control interface for that group interface may need
|
||||
to be used for some operations (mainly WPS activation in GO). This may
|
||||
change in the future so that all the needed operations could be done
|
||||
over the main control interface.
|
||||
|
||||
Device Discovery
|
||||
|
||||
p2p_find [timeout in seconds] [type=<social|progressive>] \
|
||||
[dev_id=<addr>] [dev_type=<device type>] \
|
||||
[delay=<search delay in ms>] [seek=<service name>] [freq=<MHz>]
|
||||
|
||||
The default behavior is to run a single full scan in the beginning and
|
||||
then scan only social channels. type=social will scan only social
|
||||
channels, i.e., it skips the initial full scan. type=progressive is
|
||||
like the default behavior, but it will scan through all the channels
|
||||
progressively one channel at the time in the Search state rounds. This
|
||||
will help in finding new groups or groups missed during the initial
|
||||
full scan. When the type parameter is not included (i.e., full scan), the
|
||||
optional freq parameter can be used to override the first scan to use only
|
||||
the specified channel after which only social channels are scanned.
|
||||
|
||||
The optional dev_id option can be used to specify a single P2P peer to
|
||||
search for. The optional delay parameter can be used to request an extra
|
||||
delay to be used between search iterations (e.g., to free up radio
|
||||
resources for concurrent operations).
|
||||
|
||||
The optional dev_type option can be used to specify a single device type
|
||||
(primary or secondary) to search for, e.g.,
|
||||
"p2p_find dev_type=1-0050F204-1".
|
||||
|
||||
|
||||
With one or more seek arguments, the command sends Probe Request frames
|
||||
for a P2PS service. For example,
|
||||
p2p_find 5 dev_id=11:22:33:44:55:66 seek=alt.example.chat seek=alt.example.video
|
||||
|
||||
Parameters description:
|
||||
Timeout - Optional ASCII base-10-encoded u16. If missing, request will not
|
||||
time out and must be canceled manually
|
||||
dev_id - Optional to request responses from a single known remote device
|
||||
Service Name - Mandatory UTF-8 string for ASP seeks
|
||||
Service name must match the remote service being advertised exactly
|
||||
(no prefix matching).
|
||||
Service name may be empty, in which case all ASP services will be
|
||||
returned, and may be filtered with p2p_serv_disc_req settings, and
|
||||
p2p_serv_asp_resp results.
|
||||
Multiple service names may be requested, but if it exceeds internal
|
||||
limit, it will automatically revert to requesting all ASP services.
|
||||
|
||||
p2p_listen [timeout in seconds]
|
||||
|
||||
Start Listen-only state (become discoverable without searching for
|
||||
other devices). Optional parameter can be used to specify the duration
|
||||
for the Listen operation in seconds. This command may not be of that
|
||||
much use during normal operations and is mainly designed for
|
||||
testing. It can also be used to keep the device discoverable without
|
||||
having to maintain a group.
|
||||
|
||||
p2p_stop_find
|
||||
|
||||
Stop ongoing P2P device discovery or other operation (connect, listen
|
||||
mode).
|
||||
|
||||
p2p_flush
|
||||
|
||||
Flush P2P peer table and state.
|
||||
|
||||
Group Formation
|
||||
|
||||
p2p_prov_disc <peer device address> <display|keypad|pbc> [join|auto]
|
||||
|
||||
Send P2P provision discovery request to the specified peer. The
|
||||
parameters for this command are the P2P device address of the peer and
|
||||
the desired configuration method. For example, "p2p_prov_disc
|
||||
02:01:02:03:04:05 display" would request the peer to display a PIN for
|
||||
us and "p2p_prov_disc 02:01:02:03:04:05 keypad" would request the peer
|
||||
to enter a PIN that we display.
|
||||
|
||||
The optional "join" parameter can be used to indicate that this command
|
||||
is requesting an already running GO to prepare for a new client. This is
|
||||
mainly used with "display" to request it to display a PIN. The "auto"
|
||||
parameter can be used to request wpa_supplicant to automatically figure
|
||||
out whether the peer device is operating as a GO and if so, use
|
||||
join-a-group style PD instead of GO Negotiation style PD.
|
||||
|
||||
p2p_connect <peer device address> <pbc|pin|PIN#|p2ps> [display|keypad|p2ps]
|
||||
[persistent|persistent=<network id>] [join|auth]
|
||||
[go_intent=<0..15>] [freq=<in MHz>] [ht40] [vht] [he] [provdisc] [auto]
|
||||
[ssid=<hexdump>]
|
||||
|
||||
Start P2P group formation with a discovered P2P peer. This includes
|
||||
optional group owner negotiation, group interface setup, provisioning,
|
||||
and establishing data connection.
|
||||
|
||||
The <pbc|pin|PIN#> parameter specifies the WPS provisioning
|
||||
method. "pbc" string starts pushbutton method, "pin" string start PIN
|
||||
method using an automatically generated PIN (which will be returned as
|
||||
the command return code), PIN# means that a pre-selected PIN can be
|
||||
used (e.g., 12345670). [display|keypad] is used with PIN method
|
||||
to specify which PIN is used (display=dynamically generated random PIN
|
||||
from local display, keypad=PIN entered from peer display). "persistent"
|
||||
parameter can be used to request a persistent group to be formed. The
|
||||
"persistent=<network id>" alternative can be used to pre-populate
|
||||
SSID/passphrase configuration based on a previously used persistent
|
||||
group where this device was the GO. The previously used parameters will
|
||||
then be used if the local end becomes the GO in GO Negotiation (which
|
||||
can be forced with go_intent=15).
|
||||
|
||||
"join" indicates that this is a command to join an existing group as a
|
||||
client. It skips the GO Negotiation part. This will send a Provision
|
||||
Discovery Request message to the target GO before associating for WPS
|
||||
provisioning.
|
||||
|
||||
"auth" indicates that the WPS parameters are authorized for the peer
|
||||
device without actually starting GO Negotiation (i.e., the peer is
|
||||
expected to initiate GO Negotiation). This is mainly for testing
|
||||
purposes.
|
||||
|
||||
"go_intent" can be used to override the default GO Intent for this GO
|
||||
Negotiation.
|
||||
|
||||
"freq" can be used to set a forced operating channel (e.g., freq=2412
|
||||
to select 2.4 GHz channel 1).
|
||||
|
||||
"provdisc" can be used to request a Provision Discovery exchange to be
|
||||
used prior to starting GO Negotiation as a workaround with some deployed
|
||||
P2P implementations that require this to allow the user to accept the
|
||||
connection.
|
||||
|
||||
"auto" can be used to request wpa_supplicant to automatically figure
|
||||
out whether the peer device is operating as a GO and if so, use
|
||||
join-a-group operation rather than GO Negotiation.
|
||||
|
||||
"ssid=<hexdump>" can be used to specify the Group SSID for join
|
||||
operations. This allows the P2P Client interface to filter scan results
|
||||
based on SSID to avoid selecting an incorrect BSS entry in case the same
|
||||
P2P Device or Interface address have been used in multiple groups
|
||||
recently.
|
||||
|
||||
P2PS attribute changes to p2p_connect command:
|
||||
|
||||
P2PS supports two WPS provisioning methods namely PIN method and P2PS default.
|
||||
The remaining parameters hold same role as in legacy P2P. In case of P2PS
|
||||
default config method "p2ps" keyword is added in p2p_connect command.
|
||||
|
||||
For example:
|
||||
p2p_connect 02:0a:f5:85:11:00 12345670 p2ps persistent join
|
||||
(WPS Method = P2PS default)
|
||||
|
||||
p2p_connect 02:0a:f5:85:11:00 45629034 keypad persistent
|
||||
(WPS Method = PIN)
|
||||
|
||||
p2p_asp_provision <peer MAC address> <adv_id=peer adv id>
|
||||
<adv_mac=peer MAC address> [role=2|4|1] <session=session id>
|
||||
<session_mac=initiator mac address>
|
||||
[info='service info'] <method=Default|keypad|Display>
|
||||
|
||||
This command starts provision discovery with the P2PS enabled peer device.
|
||||
|
||||
For example,
|
||||
p2p_asp_provision 00:11:22:33:44:55 adv_id=4d6fc7 adv_mac=00:55:44:33:22:11 role=1 session=12ab34 session_mac=00:11:22:33:44:55 info='name=john' method=1000
|
||||
|
||||
Parameter description:
|
||||
MAC address - Mandatory
|
||||
adv_id - Mandatory remote Advertising ID of service connection is being
|
||||
established for
|
||||
adv_mac - Mandatory MAC address that owns/registered the service
|
||||
role - Optional
|
||||
2 (group client only) or 4 (group owner only)
|
||||
if not present (or 1) role is negotiated by the two peers.
|
||||
session - Mandatory Session ID of the first session to be established
|
||||
session_mac - Mandatory MAC address that owns/initiated the session
|
||||
method - Optional method to request for provisioning (1000 - P2PS Default,
|
||||
100 - Keypad(PIN), 8 - Display(PIN))
|
||||
info - Optional UTF-8 string. Hint for service to indicate possible usage
|
||||
parameters - Escape single quote & backslash:
|
||||
with a backslash 0x27 == ' == \', and 0x5c == \ == \\
|
||||
|
||||
p2p_asp_provision_resp <peer mac address> <adv_id= local adv id>
|
||||
<adv_mac=local MAC address> <role=1|2|4> <status=0>
|
||||
<session=session id> <session_mac=peer MAC address>
|
||||
|
||||
This command sends a provision discovery response from responder side.
|
||||
|
||||
For example,
|
||||
p2p_asp_provision_resp 00:55:44:33:22:11 adv_id=4d6fc7 adv_mac=00:55:44:33:22:11 role=1 status=0 session=12ab34 session_mac=00:11:22:33:44:55
|
||||
|
||||
Parameters definition:
|
||||
MAC address - Mandatory
|
||||
adv_id - Mandatory local Advertising ID of service connection is being
|
||||
established for
|
||||
adv_mac - Mandatory MAC address that owns/registered the service
|
||||
role - Optional 2 (group client only) or 4 (group owner only)
|
||||
if not present (or 1) role is negotiated by the two peers.
|
||||
status - Mandatory Acceptance/Rejection code of Provisioning
|
||||
session - Mandatory Session ID of the first session to be established
|
||||
session_mac - Mandatory MAC address that owns/initiated the session
|
||||
|
||||
p2p_group_add [persistent|persistent=<network id>] [freq=<freq in MHz>]
|
||||
[ht40] [vht] [he]
|
||||
|
||||
Set up a P2P group owner manually (i.e., without group owner
|
||||
negotiation with a specific peer). This is also known as autonomous
|
||||
GO. Optional persistent=<network id> can be used to specify restart of
|
||||
a persistent group. Optional freq=<freq in MHz> can be used to force
|
||||
the GO to be started on a specific frequency. Special freq=2 or freq=5
|
||||
options can be used to request the best 2.4 GHz or 5 GHz band channel
|
||||
to be selected automatically.
|
||||
|
||||
p2p_reject <peer device address>
|
||||
|
||||
Reject connection attempt from a peer (specified with a device
|
||||
address). This is a mechanism to reject a pending GO Negotiation with
|
||||
a peer and request to automatically block any further connection or
|
||||
discovery of the peer.
|
||||
|
||||
p2p_group_remove <group interface>
|
||||
|
||||
Terminate a P2P group. If a new virtual network interface was used for
|
||||
the group, it will also be removed. The network interface name of the
|
||||
group interface is used as a parameter for this command.
|
||||
|
||||
p2p_cancel
|
||||
|
||||
Cancel an ongoing P2P group formation and joining-a-group related
|
||||
operation. This operation unauthorizes the specific peer device (if any
|
||||
had been authorized to start group formation), stops P2P find (if in
|
||||
progress), stops pending operations for join-a-group, and removes the
|
||||
P2P group interface (if one was used) that is in the WPS provisioning
|
||||
step. If the WPS provisioning step has been completed, the group is not
|
||||
terminated.
|
||||
|
||||
p2p_remove_client <peer's P2P Device Address|iface=<interface address>>
|
||||
|
||||
This command can be used to remove the specified client from all groups
|
||||
(operating and persistent) from the local GO. Note that the peer device
|
||||
can rejoin the group if it is in possession of a valid key. See p2p_set
|
||||
per_sta_psk command below for more details on how the peer can be
|
||||
removed securely.
|
||||
|
||||
Service Discovery
|
||||
|
||||
p2p_service_add asp <auto accept> <adv id> <status 0/1> <Config Methods>
|
||||
<Service name> [Service Information] [Response Info]
|
||||
|
||||
This command can be used to search for a P2PS service which includes
|
||||
Play, Send, Display, and Print service. The parameters for this command
|
||||
are "asp" to identify the command as P2PS one, auto accept value,
|
||||
advertisement id which uniquely identifies the service requests, state
|
||||
of the service whether the service is available or not, config methods
|
||||
which can be either P2PS method or PIN method, service name followed by
|
||||
two optional parameters service information, and response info.
|
||||
|
||||
For example,
|
||||
p2p_service_add asp 1 4d6fc7 0 1108 alt.example.chat svc_info='name=john' rsp_info='enter PIN 1234'
|
||||
|
||||
Parameters definition:
|
||||
asp - Mandatory for ASP service registration
|
||||
auto accept - Mandatory ASCII hex-encoded boolean (0 == no auto-accept,
|
||||
1 == auto-accept ANY role, 2 == auto-accept CLIENT role,
|
||||
4 == auto-accept GO role)
|
||||
Advertisement ID - Mandatory non-zero ASCII hex-encoded u32
|
||||
(Must be unique/not yet exist in svc db)
|
||||
State - Mandatory ASCII hex-encoded u8 (0 -- Svc not available,
|
||||
1 -- Svc available, 2-0xff Application defined)
|
||||
Config Methods - Mandatory ASCII hex-encoded u16 (bitmask of WSC config
|
||||
methods)
|
||||
Service Name - Mandatory UTF-8 string
|
||||
Service Information - Optional UTF-8 string
|
||||
Escape single quote & backslash with a backslash:
|
||||
0x27 == ' == \', and 0x5c == \ == \\
|
||||
Session response information - Optional (used only if auto accept is TRUE)
|
||||
UTF-8 string
|
||||
Escape single quote & backslash with a backslash:
|
||||
0x27 == ' == \', and 0x5c == \ == \\
|
||||
|
||||
p2p_service_rep asp <auto accept> <adv id> <status 0/1> <Config Methods>
|
||||
<Service name> [Service Information] [Response Info]
|
||||
|
||||
This command can be used to replace the existing service request
|
||||
attributes from the initiator side. The replacement is only allowed if
|
||||
the advertisement id issued in the command matches with any one entry in
|
||||
the list of existing SD queries. If advertisement id doesn't match the
|
||||
command returns a failure.
|
||||
|
||||
For example,
|
||||
p2p_service_rep asp 1 4d6fc7 1 1108 alt.example.chat svc_info='name=john' rsp_info='enter PIN 1234'
|
||||
|
||||
Parameters definition:
|
||||
asp - Mandatory for ASP service registration
|
||||
auto accept - Mandatory ASCII hex-encoded boolean (1 == true, 0 == false)
|
||||
Advertisement ID - Mandatory non-zero ASCII hex-encoded u32
|
||||
(Must already exist in svc db)
|
||||
State - Mandatory ASCII hex-encoded u8 (can be used to indicate svc
|
||||
available or not available for instance)
|
||||
Config Methods - Mandatory ASCII hex-encoded u16 (bitmask of WSC config
|
||||
methods)
|
||||
Service Name - Mandatory UTF-8 string (Must match existing string in svc db)
|
||||
Service Information - Optional UTF-8 string
|
||||
Escape single quote & backslash with a backslash:
|
||||
0x27 == ' == \', and 0x5c == \ == \\
|
||||
Session response information - Optional (used only if auto accept is TRUE)
|
||||
UTF-8 string
|
||||
Escape single quote & backslash with a backslash:
|
||||
0x27 == ' == \', and 0x5c == \ == \\
|
||||
|
||||
p2p_serv_disc_req
|
||||
|
||||
Schedule a P2P service discovery request. The parameters for this
|
||||
command are the device address of the peer device (or 00:00:00:00:00:00
|
||||
for wildcard query that is sent to every discovered P2P peer that
|
||||
supports service discovery) and P2P Service Query TLV(s) as hexdump. For
|
||||
example,
|
||||
|
||||
p2p_serv_disc_req 00:00:00:00:00:00 02000001
|
||||
|
||||
schedules a request for listing all available services of all service
|
||||
discovery protocols and requests this to be sent to all discovered
|
||||
peers (note: this can result in long response frames). The pending
|
||||
requests are sent during device discovery (see p2p_find).
|
||||
|
||||
There can be multiple pending peer device specific queries (each will be
|
||||
sent in sequence whenever the peer is found).
|
||||
|
||||
This command returns an identifier for the pending query (e.g.,
|
||||
"1f77628") that can be used to cancel the request. Directed requests
|
||||
will be automatically removed when the specified peer has replied to
|
||||
it.
|
||||
|
||||
Service Query TLV has following format:
|
||||
Length (2 octets, little endian) - length of following data
|
||||
Service Protocol Type (1 octet) - see the table below
|
||||
Service Transaction ID (1 octet) - nonzero identifier for the TLV
|
||||
Query Data (Length - 2 octets of data) - service protocol specific data
|
||||
|
||||
Service Protocol Types:
|
||||
0 = All service protocols
|
||||
1 = Bonjour
|
||||
2 = UPnP
|
||||
3 = WS-Discovery
|
||||
4 = Wi-Fi Display
|
||||
|
||||
For UPnP, an alternative command format can be used to specify a
|
||||
single query TLV (i.e., a service discovery for a specific UPnP
|
||||
service):
|
||||
|
||||
p2p_serv_disc_req 00:00:00:00:00:00 upnp <version hex> <ST: from M-SEARCH>
|
||||
|
||||
For example:
|
||||
|
||||
p2p_serv_disc_req 00:00:00:00:00:00 upnp 10 urn:schemas-upnp-org:device:InternetGatewayDevice:1
|
||||
|
||||
Additional examples for queries:
|
||||
|
||||
# list of all Bonjour services
|
||||
p2p_serv_disc_req 00:00:00:00:00:00 02000101
|
||||
|
||||
# list of all UPnP services
|
||||
p2p_serv_disc_req 00:00:00:00:00:00 02000201
|
||||
|
||||
# list of all WS-Discovery services
|
||||
p2p_serv_disc_req 00:00:00:00:00:00 02000301
|
||||
|
||||
# list of all Bonjour and UPnP services
|
||||
p2p_serv_disc_req 00:00:00:00:00:00 0200010102000202
|
||||
|
||||
# Apple File Sharing over TCP
|
||||
p2p_serv_disc_req 00:00:00:00:00:00 130001010b5f6166706f766572746370c00c000c01
|
||||
|
||||
# Bonjour SSTH (supported service type hash)
|
||||
p2p_serv_disc_req 00:00:00:00:00:00 05000101000000
|
||||
|
||||
# UPnP examples
|
||||
p2p_serv_disc_req 00:00:00:00:00:00 upnp 10 ssdp:all
|
||||
p2p_serv_disc_req 00:00:00:00:00:00 upnp 10 upnp:rootdevice
|
||||
p2p_serv_disc_req 00:00:00:00:00:00 upnp 10 urn:schemas-upnp-org:service:ContentDirectory:2
|
||||
p2p_serv_disc_req 00:00:00:00:00:00 upnp 10 uuid:6859dede-8574-59ab-9332-123456789012
|
||||
p2p_serv_disc_req 00:00:00:00:00:00 upnp 10 urn:schemas-upnp-org:device:InternetGatewayDevice:1
|
||||
|
||||
# Wi-Fi Display examples
|
||||
# format: wifi-display <list of roles> <list of subelements>
|
||||
p2p_serv_disc_req 00:00:00:00:00:00 wifi-display [source] 2,3,4,5
|
||||
p2p_serv_disc_req 02:01:02:03:04:05 wifi-display [pri-sink] 3
|
||||
p2p_serv_disc_req 00:00:00:00:00:00 wifi-display [sec-source] 2
|
||||
p2p_serv_disc_req 00:00:00:00:00:00 wifi-display [source+sink] 2,3,4,5
|
||||
p2p_serv_disc_req 00:00:00:00:00:00 wifi-display [source][pri-sink] 2,3,4,5
|
||||
|
||||
p2p_serv_disc_req <Unicast|Broadcast mac address> asp <Transaction ID>
|
||||
<Service Name> [Service Information]
|
||||
|
||||
The command can be used for service discovery for P2PS enabled devices.
|
||||
|
||||
For example: p2p_serv_disc_req 00:00:00:00:00:00 asp a1 alt.example 'john'
|
||||
|
||||
Parameters definition:
|
||||
MAC address - Mandatory Existing
|
||||
asp - Mandatory for ASP queries
|
||||
Transaction ID - Mandatory non-zero ASCII hex-encoded u8 for GAS
|
||||
Service Name Prefix - Mandatory UTF-8 string.
|
||||
Will match from beginning of remote Service Name
|
||||
Service Information Substring - Optional UTF-8 string
|
||||
If Service Information Substring is not included, all services matching
|
||||
Service Name Prefix will be returned.
|
||||
If Service Information Substring is included, both the Substring and the
|
||||
Service Name Prefix must match for service to be returned.
|
||||
If remote service has no Service Information, all Substring searches
|
||||
will fail.
|
||||
|
||||
p2p_serv_disc_cancel_req <query identifier>
|
||||
|
||||
Cancel a pending P2P service discovery request. This command takes a
|
||||
single parameter: identifier for the pending query (the value returned
|
||||
by p2p_serv_disc_req, e.g., "p2p_serv_disc_cancel_req 1f77628".
|
||||
|
||||
p2p_serv_disc_resp
|
||||
|
||||
Reply to a service discovery query. This command takes following
|
||||
parameters: frequency in MHz, destination address, dialog token,
|
||||
response TLV(s). The first three parameters are copied from the
|
||||
request event. For example, "p2p_serv_disc_resp 2437 02:40:61:c2:f3:b7
|
||||
1 0300000101". This command is used only if external program is used
|
||||
to process the request (see p2p_serv_disc_external).
|
||||
|
||||
p2p_service_update
|
||||
|
||||
Indicate that local services have changed. This is used to increment
|
||||
the P2P service indicator value so that peers know when previously
|
||||
cached information may have changed. This is only needed when external
|
||||
service discovery processing is enabled since the commands to
|
||||
pre-configure services for internal processing will increment the
|
||||
indicator automatically.
|
||||
|
||||
p2p_serv_disc_external <0|1>
|
||||
|
||||
Configure external processing of P2P service requests: 0 (default) =
|
||||
no external processing of requests (i.e., internal code will process
|
||||
each request based on pre-configured services), 1 = external
|
||||
processing of requests (external program is responsible for replying
|
||||
to service discovery requests with p2p_serv_disc_resp). Please note
|
||||
that there is quite strict limit on how quickly the response needs to
|
||||
be transmitted, so use of the internal processing is strongly
|
||||
recommended.
|
||||
|
||||
p2p_service_add bonjour <query hexdump> <RDATA hexdump>
|
||||
|
||||
Add a local Bonjour service for internal SD query processing.
|
||||
|
||||
Examples:
|
||||
|
||||
# AFP Over TCP (PTR)
|
||||
p2p_service_add bonjour 0b5f6166706f766572746370c00c000c01 074578616d706c65c027
|
||||
# AFP Over TCP (TXT) (RDATA=null)
|
||||
p2p_service_add bonjour 076578616d706c650b5f6166706f766572746370c00c001001 00
|
||||
|
||||
# IP Printing over TCP (PTR) (RDATA=MyPrinter._ipp._tcp.local.)
|
||||
p2p_service_add bonjour 045f697070c00c000c01 094d795072696e746572c027
|
||||
# IP Printing over TCP (TXT) (RDATA=txtvers=1,pdl=application/postscript)
|
||||
p2p_service_add bonjour 096d797072696e746572045f697070c00c001001 09747874766572733d311a70646c3d6170706c69636174696f6e2f706f7374736372797074
|
||||
|
||||
# Supported Service Type Hash (SSTH)
|
||||
p2p_service_add bonjour 000000 <32-byte bitfield as hexdump>
|
||||
(note: see P2P spec Annex E.4 for information on how to construct the bitfield)
|
||||
|
||||
p2p_service_del bonjour <query hexdump>
|
||||
|
||||
Remove a local Bonjour service from internal SD query processing.
|
||||
|
||||
p2p_service_add upnp <version hex> <service>
|
||||
|
||||
Add a local UPnP service for internal SD query processing.
|
||||
|
||||
Examples:
|
||||
|
||||
p2p_service_add upnp 10 uuid:6859dede-8574-59ab-9332-123456789012::upnp:rootdevice
|
||||
p2p_service_add upnp 10 uuid:5566d33e-9774-09ab-4822-333456785632::upnp:rootdevice
|
||||
p2p_service_add upnp 10 uuid:1122de4e-8574-59ab-9322-333456789044::urn:schemas-upnp-org:service:ContentDirectory:2
|
||||
p2p_service_add upnp 10 uuid:5566d33e-9774-09ab-4822-333456785632::urn:schemas-upnp-org:service:ContentDirectory:2
|
||||
p2p_service_add upnp 10 uuid:6859dede-8574-59ab-9332-123456789012::urn:schemas-upnp-org:device:InternetGatewayDevice:1
|
||||
|
||||
p2p_service_del upnp <version hex> <service>
|
||||
|
||||
Remove a local UPnP service from internal SD query processing.
|
||||
|
||||
p2p_service_del asp <adv id>
|
||||
|
||||
Removes the local asp service from internal SD query list.
|
||||
For example: p2p_service_del asp 4d6fc7
|
||||
|
||||
p2p_service_flush
|
||||
|
||||
Remove all local services from internal SD query processing.
|
||||
|
||||
Invitation
|
||||
|
||||
p2p_invite [persistent=<network id>|group=<group ifname>] [peer=address]
|
||||
[go_dev_addr=address] [freq=<freq in MHz>] [ht40] [vht] [he]
|
||||
[pref=<MHz>]
|
||||
|
||||
Invite a peer to join a group (e.g., group=wlan1) or to reinvoke a
|
||||
persistent group (e.g., persistent=4). If the peer device is the GO of
|
||||
the persistent group, the peer parameter is not needed. Otherwise it is
|
||||
used to specify which device to invite. go_dev_addr parameter can be
|
||||
used to override the GO device address for Invitation Request should
|
||||
it be not known for some reason (this should not be needed in most
|
||||
cases). When reinvoking a persistent group, the GO device can specify
|
||||
the frequency for the group with the freq parameter. When reinvoking a
|
||||
persistent group, the P2P client device can use freq parameter to force
|
||||
a specific operating channel (or invitation failure if GO rejects that)
|
||||
or pref parameter to request a specific channel (while allowing GO to
|
||||
select to use another channel, if needed).
|
||||
|
||||
Group Operations
|
||||
|
||||
(These are used on the group interface.)
|
||||
|
||||
wps_pin <any|address> <PIN>
|
||||
|
||||
Start WPS PIN method. This allows a single WPS Enrollee to connect to
|
||||
the AP/GO. This is used on the GO when a P2P client joins an existing
|
||||
group. The second parameter is the address of the Enrollee or a string
|
||||
"any" to allow any station to use the entered PIN (which will restrict
|
||||
the PIN for one-time-use). PIN is the Enrollee PIN read either from a
|
||||
label or display on the P2P Client/WPS Enrollee.
|
||||
|
||||
wps_pbc
|
||||
|
||||
Start WPS PBC method (i.e., push the button). This allows a single WPS
|
||||
Enrollee to connect to the AP/GO. This is used on the GO when a P2P
|
||||
client joins an existing group.
|
||||
|
||||
p2p_get_passphrase
|
||||
|
||||
Get the passphrase for a group (only available when acting as a GO).
|
||||
|
||||
p2p_presence_req [<duration> <interval>] [<duration> <interval>]
|
||||
|
||||
Send a P2P Presence Request to the GO (this is only available when
|
||||
acting as a P2P client). If no duration/interval pairs are given, the
|
||||
request indicates that this client has no special needs for GO
|
||||
presence. The first parameter pair gives the preferred duration and
|
||||
interval values in microseconds. If the second pair is included, that
|
||||
indicates which value would be acceptable. This command returns OK
|
||||
immediately and the response from the GO is indicated in a
|
||||
P2P-PRESENCE-RESPONSE event message.
|
||||
|
||||
Parameters
|
||||
|
||||
p2p_ext_listen [<period> <interval>]
|
||||
|
||||
Configure Extended Listen Timing. If the parameters are omitted, this
|
||||
feature is disabled. If the parameters are included, Listen State will
|
||||
be entered every interval msec for at least period msec. Both values
|
||||
have acceptable range of 1-65535 (with interval obviously having to be
|
||||
larger than or equal to duration). If the P2P module is not idle at
|
||||
the time the Extended Listen Timing timeout occurs, the Listen State
|
||||
operation will be skipped.
|
||||
|
||||
The configured values will also be advertised to other P2P Devices. The
|
||||
received values are available in the p2p_peer command output:
|
||||
|
||||
ext_listen_period=100 ext_listen_interval=5000
|
||||
|
||||
p2p_set <field> <value>
|
||||
|
||||
Change dynamic P2P parameters
|
||||
|
||||
p2p_set discoverability <0/1>
|
||||
|
||||
Disable/enable advertisement of client discoverability. This is
|
||||
enabled by default and this parameter is mainly used to allow testing
|
||||
of device discoverability.
|
||||
|
||||
p2p_set managed <0/1>
|
||||
|
||||
Disable/enable managed P2P Device operations. This is disabled by
|
||||
default.
|
||||
|
||||
p2p_set listen_channel <channel> [<op_class>]
|
||||
|
||||
Set P2P Listen channel. This is mainly meant for testing purposes and
|
||||
changing the Listen channel during normal operations can result in
|
||||
protocol failures.
|
||||
|
||||
When specifying a social channel on the 2.4 GHz band (1/6/11) there is
|
||||
no need to specify the operating class since it defaults to 81. When
|
||||
specifying a social channel on the 60 GHz band (2), specify the 60 GHz
|
||||
operating class (180).
|
||||
|
||||
p2p_set ssid_postfix <postfix>
|
||||
|
||||
Set postfix string to be added to the automatically generated P2P SSID
|
||||
(DIRECT-<two random characters>). For example, postfix of "-testing"
|
||||
could result in the SSID becoming DIRECT-ab-testing.
|
||||
|
||||
p2p_set per_sta_psk <0/1>
|
||||
|
||||
Disabled(default)/enables use of per-client PSK in the P2P groups. This
|
||||
can be used to request GO to assign a unique PSK for each client during
|
||||
WPS provisioning. When enabled, this allow clients to be removed from
|
||||
the group securely with p2p_remove_client command since that client's
|
||||
PSK is removed at the same time to prevent it from connecting back using
|
||||
the old PSK. When per-client PSK is not used, the client can still be
|
||||
disconnected, but it will be able to re-join the group since the PSK it
|
||||
learned previously is still valid. It should be noted that the default
|
||||
passphrase on the GO that is normally used to allow legacy stations to
|
||||
connect through manual configuration does not change here, so if that is
|
||||
shared, devices with knowledge of that passphrase can still connect.
|
||||
|
||||
set <field> <value>
|
||||
|
||||
Set global configuration parameters which may also affect P2P
|
||||
operations. The format on these parameters is same as is used in
|
||||
wpa_supplicant.conf. Only the parameters listen here should be
|
||||
changed. Modifying other parameters may result in incorrect behavior
|
||||
since not all existing users of the parameters are updated.
|
||||
|
||||
set uuid <UUID>
|
||||
|
||||
Set WPS UUID (by default, this is generated based on the MAC address).
|
||||
|
||||
set device_name <device name>
|
||||
|
||||
Set WPS Device Name (also included in some P2P messages).
|
||||
|
||||
set manufacturer <manufacturer>
|
||||
|
||||
Set WPS Manufacturer.
|
||||
|
||||
set model_name <model name>
|
||||
|
||||
Set WPS Model Name.
|
||||
|
||||
set model_number <model number>
|
||||
|
||||
Set WPS Model Number.
|
||||
|
||||
set serial_number <serial number>
|
||||
|
||||
Set WPS Serial Number.
|
||||
|
||||
set device_type <device type>
|
||||
|
||||
Set WPS Device Type.
|
||||
|
||||
set os_version <OS version>
|
||||
|
||||
Set WPS OS Version.
|
||||
|
||||
set config_methods <config methods>
|
||||
|
||||
Set WPS Configuration Methods.
|
||||
|
||||
set sec_device_type <device type>
|
||||
|
||||
Add a new Secondary Device Type.
|
||||
|
||||
set p2p_go_intent <GO intent>
|
||||
|
||||
Set the default P2P GO Intent. Note: This value can be overridden in
|
||||
p2p_connect command and as such, there should be no need to change the
|
||||
default value here during normal operations.
|
||||
|
||||
set p2p_ssid_postfix <P2P SSID postfix>
|
||||
|
||||
Set P2P SSID postfix.
|
||||
|
||||
set persistent_reconnect <0/1>
|
||||
|
||||
Disable/enabled persistent reconnect for reinvocation of persistent
|
||||
groups. If enabled, invitations to reinvoke a persistent group will be
|
||||
accepted without separate authorization (e.g., user interaction).
|
||||
|
||||
set country <two character country code>
|
||||
|
||||
Set country code (this is included in some P2P messages).
|
||||
|
||||
set p2p_search_delay <delay>
|
||||
|
||||
Set p2p_search_delay which adds extra delay in milliseconds between
|
||||
concurrent search iterations to make p2p_find friendlier to concurrent
|
||||
operations by avoiding it from taking 100% of radio resources. The
|
||||
default value is 500 ms.
|
||||
|
||||
Status
|
||||
|
||||
p2p_peers [discovered]
|
||||
|
||||
List P2P Device Addresses of all the P2P peers we know. The optional
|
||||
"discovered" parameter filters out the peers that we have not fully
|
||||
discovered, i.e., which we have only seen in a received Probe Request
|
||||
frame.
|
||||
|
||||
p2p_peer <P2P Device Address>
|
||||
|
||||
Fetch information about a known P2P peer.
|
||||
|
||||
Group Status
|
||||
|
||||
(These are used on the group interface.)
|
||||
|
||||
status
|
||||
|
||||
Show status information (connection state, role, use encryption
|
||||
parameters, IP address, etc.).
|
||||
|
||||
sta
|
||||
|
||||
Show information about an associated station (when acting in AP/GO role).
|
||||
|
||||
all_sta
|
||||
|
||||
Lists the currently associated stations.
|
||||
|
||||
Configuration data
|
||||
|
||||
list_networks
|
||||
|
||||
Lists the configured networks, including stored information for
|
||||
persistent groups. The identifier in this list is used with
|
||||
p2p_group_add and p2p_invite to indicate which persistent group is to
|
||||
be reinvoked.
|
||||
|
||||
remove_network <network id>
|
||||
|
||||
Remove a network entry from configuration.
|
||||
|
||||
|
||||
P2PS Events/Responses:
|
||||
|
||||
P2PS-PROV-START: This events gets triggered when provisioning is issued for
|
||||
either seeker or advertiser.
|
||||
|
||||
For example,
|
||||
P2PS-PROV-START 00:55:44:33:22:11 adv_id=111 adv_mac=00:55:44:33:22:11 conncap=1 session=1234567 session_mac=00:11:22:33:44:55 info='xxxx'
|
||||
|
||||
Parameters definition:
|
||||
MAC address - always
|
||||
adv_id - always ASCII hex-encoded u32
|
||||
adv_mac - always MAC address that owns/registered the service
|
||||
conncap - always mask of 0x01 (new), 0x02 (group client), 0x04 (group owner)
|
||||
bits
|
||||
session - always Session ID of the first session to be established
|
||||
session_mac - always MAC address that owns/initiated the session
|
||||
info - if available, UTF-8 string
|
||||
Escaped single quote & backslash with a backslash:
|
||||
\' == 0x27 == ', and \\ == 0x5c == \
|
||||
|
||||
P2PS-PROV-DONE: When provisioning is completed then this event gets triggered.
|
||||
|
||||
For example,
|
||||
P2PS-PROV-DONE 00:11:22:33:44:55 status=0 adv_id=111 adv_mac=00:55:44:33:22:11 conncap=1 session=1234567 session_mac=00:11:22:33:44:55 [dev_passwd_id=8 | go=p2p-wlan0-0 | join=11:22:33:44:55:66 | persist=0]
|
||||
|
||||
Parameters definition:
|
||||
MAC address - always main device address of peer. May be different from MAC
|
||||
ultimately connected to.
|
||||
status - always ascii hex-encoded u8 (0 == success, 12 == deferred success)
|
||||
adv_id - always ascii hex-encoded u32
|
||||
adv_mac - always MAC address that owns/registered the service
|
||||
conncap - always One of: 1 (new), 2 (group client), 4 (group owner) bits
|
||||
session - always Session ID of the first session to be established
|
||||
session_mac - always MAC address that owns/initiated the session
|
||||
dev_passwd_id - only if conncap value == 1 (New GO negotiation)
|
||||
8 - "p2ps" password must be passed in p2p_connect command
|
||||
1 - "display" password must be passed in p2p_connect command
|
||||
5 - "keypad" password must be passed in p2p_connect command
|
||||
join only - if conncap value == 2 (Client Only). Display password and "join"
|
||||
must be passed in p2p_connect and address must be the MAC specified
|
||||
go only - if conncap value == 4 (GO Only). Interface name must be set with a
|
||||
password
|
||||
persist - only if previous persistent group existed between peers and shall
|
||||
be re-used. Group is restarted by sending "p2p_group_add persistent=0"
|
||||
where value is taken from P2P-PROV-DONE
|
||||
|
||||
Extended Events/Response
|
||||
|
||||
P2P-DEVICE-FOUND 00:11:22:33:44:55 p2p_dev_addr=00:11:22:33:44:55 pri_dev_type=0-00000000-0 name='' config_methods=0x108 dev_capab=0x21 group_capab=0x0 adv_id=111 asp_svc=alt.example.chat
|
||||
|
||||
Parameters definition:
|
||||
adv_id - if ASP ASCII hex-encoded u32. If it is reporting the
|
||||
"wildcard service", this value will be 0
|
||||
asp_svc - if ASP this is the service string. If it is reporting the
|
||||
"wildcard service", this value will be org.wi-fi.wfds
|
||||
|
||||
|
||||
wpa_cli action script
|
||||
---------------------
|
||||
|
||||
See examples/p2p-action.sh
|
||||
|
||||
TODO: describe DHCP/DNS setup
|
||||
TODO: cross-connection
|
399
wpa_supplicant/README-WPS
Normal file
399
wpa_supplicant/README-WPS
Normal file
@ -0,0 +1,399 @@
|
||||
wpa_supplicant and Wi-Fi Protected Setup (WPS)
|
||||
==============================================
|
||||
|
||||
This document describes how the WPS implementation in wpa_supplicant
|
||||
can be configured and how an external component on the client (e.g.,
|
||||
management GUI) is used to enable WPS enrollment and registrar
|
||||
registration.
|
||||
|
||||
|
||||
Introduction to WPS
|
||||
-------------------
|
||||
|
||||
Wi-Fi Protected Setup (WPS) is a mechanism for easy configuration of a
|
||||
wireless network. It allows automated generation of random keys (WPA
|
||||
passphrase/PSK) and configuration of an access point and client
|
||||
devices. WPS includes number of methods for setting up connections
|
||||
with PIN method and push-button configuration (PBC) being the most
|
||||
commonly deployed options.
|
||||
|
||||
While WPS can enable more home networks to use encryption in the
|
||||
wireless network, it should be noted that the use of the PIN and
|
||||
especially PBC mechanisms for authenticating the initial key setup is
|
||||
not very secure. As such, use of WPS may not be suitable for
|
||||
environments that require secure network access without chance for
|
||||
allowing outsiders to gain access during the setup phase.
|
||||
|
||||
WPS uses following terms to describe the entities participating in the
|
||||
network setup:
|
||||
- access point: the WLAN access point
|
||||
- Registrar: a device that control a network and can authorize
|
||||
addition of new devices); this may be either in the AP ("internal
|
||||
Registrar") or in an external device, e.g., a laptop, ("external
|
||||
Registrar")
|
||||
- Enrollee: a device that is being authorized to use the network
|
||||
|
||||
It should also be noted that the AP and a client device may change
|
||||
roles (i.e., AP acts as an Enrollee and client device as a Registrar)
|
||||
when WPS is used to configure the access point.
|
||||
|
||||
|
||||
More information about WPS is available from Wi-Fi Alliance:
|
||||
http://www.wi-fi.org/wifi-protected-setup
|
||||
|
||||
|
||||
wpa_supplicant implementation
|
||||
-----------------------------
|
||||
|
||||
wpa_supplicant includes an optional WPS component that can be used as
|
||||
an Enrollee to enroll new network credential or as a Registrar to
|
||||
configure an AP.
|
||||
|
||||
|
||||
wpa_supplicant configuration
|
||||
----------------------------
|
||||
|
||||
WPS is an optional component that needs to be enabled in
|
||||
wpa_supplicant build configuration (.config). Here is an example
|
||||
configuration that includes WPS support and Linux nl80211 -based
|
||||
driver interface:
|
||||
|
||||
CONFIG_DRIVER_NL80211=y
|
||||
CONFIG_WPS=y
|
||||
|
||||
If you want to enable WPS external registrar (ER) functionality, you
|
||||
will also need to add following line:
|
||||
|
||||
CONFIG_WPS_ER=y
|
||||
|
||||
Following parameter can be used to enable support for NFC config method:
|
||||
|
||||
CONFIG_WPS_NFC=y
|
||||
|
||||
|
||||
WPS needs the Universally Unique IDentifier (UUID; see RFC 4122) for
|
||||
the device. This is configured in the runtime configuration for
|
||||
wpa_supplicant (if not set, UUID will be generated based on local MAC
|
||||
address):
|
||||
|
||||
# example UUID for WPS
|
||||
uuid=12345678-9abc-def0-1234-56789abcdef0
|
||||
|
||||
The network configuration blocks needed for WPS are added
|
||||
automatically based on control interface commands, so they do not need
|
||||
to be added explicitly in the configuration file.
|
||||
|
||||
WPS registration will generate new network blocks for the acquired
|
||||
credentials. If these are to be stored for future use (after
|
||||
restarting wpa_supplicant), wpa_supplicant will need to be configured
|
||||
to allow configuration file updates:
|
||||
|
||||
update_config=1
|
||||
|
||||
|
||||
|
||||
External operations
|
||||
-------------------
|
||||
|
||||
WPS requires either a device PIN code (usually, 8-digit number) or a
|
||||
pushbutton event (for PBC) to allow a new WPS Enrollee to join the
|
||||
network. wpa_supplicant uses the control interface as an input channel
|
||||
for these events.
|
||||
|
||||
The PIN value used in the commands must be processed by an UI to
|
||||
remove non-digit characters and potentially, to verify the checksum
|
||||
digit. "wpa_cli wps_check_pin <PIN>" can be used to do such processing.
|
||||
It returns FAIL if the PIN is invalid, or FAIL-CHECKSUM if the checksum
|
||||
digit is incorrect, or the processed PIN (non-digit characters removed)
|
||||
if the PIN is valid.
|
||||
|
||||
If the client device has a display, a random PIN has to be generated
|
||||
for each WPS registration session. wpa_supplicant can do this with a
|
||||
control interface request, e.g., by calling wpa_cli:
|
||||
|
||||
wpa_cli wps_pin any
|
||||
|
||||
This will return the generated 8-digit PIN which will then need to be
|
||||
entered at the Registrar to complete WPS registration. At that point,
|
||||
the client will be enrolled with credentials needed to connect to the
|
||||
AP to access the network.
|
||||
|
||||
|
||||
If the client device does not have a display that could show the
|
||||
random PIN, a hardcoded PIN that is printed on a label can be
|
||||
used. wpa_supplicant is notified this with a control interface
|
||||
request, e.g., by calling wpa_cli:
|
||||
|
||||
wpa_cli wps_pin any 12345670
|
||||
|
||||
This starts the WPS negotiation in the same way as above with the
|
||||
generated PIN.
|
||||
|
||||
When the wps_pin command is issued for an AP (including P2P GO) mode
|
||||
interface, an optional timeout parameter can be used to specify
|
||||
expiration timeout for the PIN in seconds. For example:
|
||||
|
||||
wpa_cli wps_pin any 12345670 300
|
||||
|
||||
|
||||
If a random PIN is needed for a user interface, "wpa_cli wps_pin get"
|
||||
can be used to generate a new PIN without starting WPS negotiation.
|
||||
This random PIN can then be passed as an argument to another wps_pin
|
||||
call when the actual operation should be started.
|
||||
|
||||
If the client design wants to support optional WPS PBC mode, this can
|
||||
be enabled by either a physical button in the client device or a
|
||||
virtual button in the user interface. The PBC operation requires that
|
||||
a button is also pressed at the AP/Registrar at about the same time (2
|
||||
minute window). wpa_supplicant is notified of the local button event
|
||||
over the control interface, e.g., by calling wpa_cli:
|
||||
|
||||
wpa_cli wps_pbc
|
||||
|
||||
At this point, the AP/Registrar has two minutes to complete WPS
|
||||
negotiation which will generate a new WPA PSK in the same way as the
|
||||
PIN method described above.
|
||||
|
||||
|
||||
If the client wants to operate in the Registrar role to learn the
|
||||
current AP configuration and optionally, to configure an AP,
|
||||
wpa_supplicant is notified over the control interface, e.g., with
|
||||
wpa_cli:
|
||||
|
||||
wpa_cli wps_reg <AP BSSID> <AP PIN>
|
||||
(example: wpa_cli wps_reg 02:34:56:78:9a:bc 12345670)
|
||||
|
||||
This is used to fetch the current AP settings instead of actually
|
||||
changing them. The main difference with the wps_pin command is that
|
||||
wps_reg uses the AP PIN (e.g., from a label on the AP) instead of a
|
||||
PIN generated at the client.
|
||||
|
||||
In order to change the AP configuration, the new configuration
|
||||
parameters are given to the wps_reg command:
|
||||
|
||||
wpa_cli wps_reg <AP BSSID> <AP PIN> <new SSID> <auth> <encr> <new key>
|
||||
examples:
|
||||
wpa_cli wps_reg 02:34:56:78:9a:bc 12345670 testing WPA2PSK CCMP 12345678
|
||||
wpa_cli wps_reg 02:34:56:78:9a:bc 12345670 clear OPEN NONE ""
|
||||
|
||||
<auth> must be one of the following: OPEN WPAPSK WPA2PSK
|
||||
<encr> must be one of the following: NONE WEP TKIP CCMP
|
||||
|
||||
|
||||
Scanning
|
||||
--------
|
||||
|
||||
Scan results ('wpa_cli scan_results' or 'wpa_cli bss <idx>') include a
|
||||
flags field that is used to indicate whether the BSS support WPS. If
|
||||
the AP support WPS, but has not recently activated a Registrar, [WPS]
|
||||
flag will be included. If PIN method has been recently selected,
|
||||
[WPS-PIN] is shown instead. Similarly, [WPS-PBC] is shown if PBC mode
|
||||
is in progress. GUI programs can use these as triggers for suggesting
|
||||
a guided WPS configuration to the user. In addition, control interface
|
||||
monitor events WPS-AP-AVAILABLE{,-PBC,-PIN} can be used to find out if
|
||||
there are WPS enabled APs in scan results without having to go through
|
||||
all the details in the GUI. These notification could be used, e.g., to
|
||||
suggest possible WPS connection to the user.
|
||||
|
||||
|
||||
wpa_gui
|
||||
-------
|
||||
|
||||
wpa_gui-qt4 directory contains a sample GUI that shows an example of
|
||||
how WPS support can be integrated into the GUI. Its main window has a
|
||||
WPS tab that guides user through WPS registration with automatic AP
|
||||
selection. In addition, it shows how WPS can be started manually by
|
||||
selecting an AP from scan results.
|
||||
|
||||
|
||||
Credential processing
|
||||
---------------------
|
||||
|
||||
By default, wpa_supplicant processes received credentials and updates
|
||||
its configuration internally. However, it is possible to
|
||||
control these operations from external programs, if desired.
|
||||
|
||||
This internal processing can be disabled with wps_cred_processing=1
|
||||
option. When this is used, an external program is responsible for
|
||||
processing the credential attributes and updating wpa_supplicant
|
||||
configuration based on them.
|
||||
|
||||
Following control interface messages are sent out for external programs:
|
||||
|
||||
WPS-CRED-RECEIVED <hexdump of Credential attribute(s)>
|
||||
For example:
|
||||
<2>WPS-CRED-RECEIVED 100e006f10260001011045000c6a6b6d2d7770732d74657374100300020020100f000200081027004030653462303435366332363666653064333961643135353461316634626637313234333761636664623766333939653534663166316230323061643434386235102000060266a0ee1727
|
||||
|
||||
|
||||
wpa_supplicant as WPS External Registrar (ER)
|
||||
---------------------------------------------
|
||||
|
||||
wpa_supplicant can be used as a WPS ER to configure an AP or enroll
|
||||
new Enrollee to join the network. This functionality uses UPnP and
|
||||
requires that a working IP connectivity is available with the AP (this
|
||||
can be either over a wired or wireless connection).
|
||||
|
||||
Separate wpa_supplicant process can be started for WPS ER
|
||||
operations. A special "none" driver can be used in such a case to
|
||||
indicate that no local network interface is actually controlled. For
|
||||
example, following command could be used to start the ER:
|
||||
|
||||
wpa_supplicant -Dnone -c er.conf -ieth0
|
||||
|
||||
Sample er.conf:
|
||||
|
||||
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=admin
|
||||
device_name=WPS External Registrar
|
||||
|
||||
|
||||
wpa_cli commands for ER functionality:
|
||||
|
||||
wps_er_start [IP address]
|
||||
- start WPS ER functionality
|
||||
- the optional IP address parameter can be used to filter operations only
|
||||
to include a single AP
|
||||
- if run again while ER is active, the stored information (discovered APs
|
||||
and Enrollees) are shown again
|
||||
|
||||
wps_er_stop
|
||||
- stop WPS ER functionality
|
||||
|
||||
wps_er_learn <UUID|BSSID> <AP PIN>
|
||||
- learn AP configuration
|
||||
|
||||
wps_er_set_config <UUID|BSSID> <network id>
|
||||
- use AP configuration from a locally configured network (e.g., from
|
||||
wps_reg command); this does not change the AP's configuration, but
|
||||
only prepares a configuration to be used when enrolling a new device
|
||||
to the AP
|
||||
|
||||
wps_er_config <UUID|BSSID> <AP PIN> <new SSID> <auth> <encr> <new key>
|
||||
- examples:
|
||||
wps_er_config 87654321-9abc-def0-1234-56789abc0002 12345670 testing WPA2PSK CCMP 12345678
|
||||
wpa_er_config 87654321-9abc-def0-1234-56789abc0002 12345670 clear OPEN NONE ""
|
||||
|
||||
<auth> must be one of the following: OPEN WPAPSK WPA2PSK
|
||||
<encr> must be one of the following: NONE WEP TKIP CCMP
|
||||
|
||||
|
||||
wps_er_pbc <Enrollee UUID|MAC address>
|
||||
- accept an Enrollee PBC using External Registrar
|
||||
|
||||
wps_er_pin <Enrollee UUID|"any"|MAC address> <PIN> [Enrollee MAC address]
|
||||
- add an Enrollee PIN to External Registrar
|
||||
- if Enrollee UUID is not known, "any" can be used to add a wildcard PIN
|
||||
- if the MAC address of the enrollee is known, it should be configured
|
||||
to allow the AP to advertise list of authorized enrollees
|
||||
|
||||
|
||||
WPS ER events:
|
||||
|
||||
WPS_EVENT_ER_AP_ADD
|
||||
- WPS ER discovered an AP
|
||||
|
||||
WPS-ER-AP-ADD 87654321-9abc-def0-1234-56789abc0002 02:11:22:33:44:55 pri_dev_type=6-0050F204-1 wps_state=1 |Very friendly name|Company|Long description of the model|WAP|http://w1.fi/|http://w1.fi/hostapd/
|
||||
|
||||
WPS_EVENT_ER_AP_REMOVE
|
||||
- WPS ER removed an AP entry
|
||||
|
||||
WPS-ER-AP-REMOVE 87654321-9abc-def0-1234-56789abc0002
|
||||
|
||||
WPS_EVENT_ER_ENROLLEE_ADD
|
||||
- WPS ER discovered a new Enrollee
|
||||
|
||||
WPS-ER-ENROLLEE-ADD 2b7093f1-d6fb-5108-adbb-bea66bb87333 02:66:a0:ee:17:27 M1=1 config_methods=0x14d dev_passwd_id=0 pri_dev_type=1-0050F204-1 |Wireless Client|Company|cmodel|123|12345|
|
||||
|
||||
WPS_EVENT_ER_ENROLLEE_REMOVE
|
||||
- WPS ER removed an Enrollee entry
|
||||
|
||||
WPS-ER-ENROLLEE-REMOVE 2b7093f1-d6fb-5108-adbb-bea66bb87333 02:66:a0:ee:17:27
|
||||
|
||||
WPS-ER-AP-SETTINGS
|
||||
- WPS ER learned AP settings
|
||||
|
||||
WPS-ER-AP-SETTINGS uuid=fd91b4ec-e3fa-5891-a57d-8c59efeed1d2 ssid=test-wps auth_type=0x0020 encr_type=0x0008 key=12345678
|
||||
|
||||
|
||||
WPS with NFC
|
||||
------------
|
||||
|
||||
WPS can be used with NFC-based configuration method. An NFC tag
|
||||
containing a password token from the Enrollee can be used to
|
||||
authenticate the connection instead of the PIN. In addition, an NFC tag
|
||||
with a configuration token can be used to transfer AP settings without
|
||||
going through the WPS protocol.
|
||||
|
||||
When the station acts as an Enrollee, a local NFC tag with a password
|
||||
token can be used by touching the NFC interface of a Registrar.
|
||||
|
||||
"wps_nfc [BSSID]" command starts WPS protocol run with the local end as
|
||||
the Enrollee using the NFC password token that is either pre-configured
|
||||
in the configuration file (wps_nfc_dev_pw_id, wps_nfc_dh_pubkey,
|
||||
wps_nfc_dh_privkey, wps_nfc_dev_pw) or generated dynamically with
|
||||
"wps_nfc_token <WPS|NDEF>" command. The included nfc_pw_token tool
|
||||
(build with "make nfc_pw_token") can be used to generate NFC password
|
||||
tokens during manufacturing (each station needs to have its own random
|
||||
keys).
|
||||
|
||||
The "wps_nfc_config_token <WPS/NDEF>" command can be used to build an
|
||||
NFC configuration token when wpa_supplicant is controlling an AP
|
||||
interface (AP or P2P GO). The output value from this command is a
|
||||
hexdump of the current AP configuration (WPS parameter requests this to
|
||||
include only the WPS attributes; NDEF parameter requests additional NDEF
|
||||
encapsulation to be included). This data needs to be written to an NFC
|
||||
tag with an external program. Once written, the NFC configuration token
|
||||
can be used to touch an NFC interface on a station to provision the
|
||||
credentials needed to access the network.
|
||||
|
||||
The "wps_nfc_config_token <WPS/NDEF> <network id>" command can be used
|
||||
to build an NFC configuration token based on a locally configured
|
||||
network.
|
||||
|
||||
If the station includes NFC interface and reads an NFC tag with a MIME
|
||||
media type "application/vnd.wfa.wsc", the NDEF message payload (with or
|
||||
without NDEF encapsulation) can be delivered to wpa_supplicant using the
|
||||
following wpa_cli command:
|
||||
|
||||
wps_nfc_tag_read <hexdump of payload>
|
||||
|
||||
If the NFC tag contains a configuration token, the network is added to
|
||||
wpa_supplicant configuration. If the NFC tag contains a password token,
|
||||
the token is added to the WPS Registrar component. This information can
|
||||
then be used with wps_reg command (when the NFC password token was from
|
||||
an AP) using a special value "nfc-pw" in place of the PIN parameter. If
|
||||
the ER functionality has been started (wps_er_start), the NFC password
|
||||
token is used to enable enrollment of a new station (that was the source
|
||||
of the NFC password token).
|
||||
|
||||
"nfc_get_handover_req <NDEF> <WPS-CR>" command can be used to build the
|
||||
WPS carrier record for a Handover Request Message for connection
|
||||
handover. The first argument selects the format of the output data and
|
||||
the second argument selects which type of connection handover is
|
||||
requested (WPS-CR = Wi-Fi handover as specified in WSC 2.0).
|
||||
|
||||
"nfc_get_handover_sel <NDEF> <WPS> [UUID|BSSID]" command can be used to
|
||||
build the contents of a Handover Select Message for connection handover
|
||||
when this does not depend on the contents of the Handover Request
|
||||
Message. The first argument selects the format of the output data and
|
||||
the second argument selects which type of connection handover is
|
||||
requested (WPS = Wi-Fi handover as specified in WSC 2.0). If the options
|
||||
UUID|BSSID argument is included, this is a request to build the handover
|
||||
message for the specified AP when wpa_supplicant is operating as a WPS
|
||||
ER.
|
||||
|
||||
"nfc_report_handover <INIT/RESP> WPS <carrier from handover request>
|
||||
<carrier from handover select>" can be used as an alternative way for
|
||||
reporting completed NFC connection handover. The first parameter
|
||||
indicates whether the local device initiated or responded to the
|
||||
connection handover and the carrier records are the selected carrier
|
||||
from the handover request and select messages as a hexdump.
|
||||
|
||||
The "wps_er_nfc_config_token <WPS/NDEF> <UUID|BSSID>" command can be
|
||||
used to build an NFC configuration token for the specified AP when
|
||||
wpa_supplicant is operating as a WPS ER. The output value from this
|
||||
command is a hexdump of the selected AP configuration (WPS parameter
|
||||
requests this to include only the WPS attributes; NDEF parameter
|
||||
requests additional NDEF encapsulation to be included). This data needs
|
||||
to be written to an NFC tag with an external program. Once written, the
|
||||
NFC configuration token can be used to touch an NFC interface on a
|
||||
station to provision the credentials needed to access the network.
|
299
wpa_supplicant/README-Windows.txt
Normal file
299
wpa_supplicant/README-Windows.txt
Normal file
@ -0,0 +1,299 @@
|
||||
wpa_supplicant for Windows
|
||||
==========================
|
||||
|
||||
Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi> and contributors
|
||||
All Rights Reserved.
|
||||
|
||||
This program is licensed under the BSD license (the one with
|
||||
advertisement clause removed).
|
||||
|
||||
|
||||
wpa_supplicant has support for being used as a WPA/WPA2/IEEE 802.1X
|
||||
Supplicant on Windows. The current port requires that WinPcap
|
||||
(http://winpcap.polito.it/) is installed for accessing packets and the
|
||||
driver interface. Both release versions 3.0 and 3.1 are supported.
|
||||
|
||||
The current port is still somewhat experimental. It has been tested
|
||||
mainly on Windows XP (SP2) with limited set of NDIS drivers. In
|
||||
addition, the current version has been reported to work with Windows
|
||||
2000.
|
||||
|
||||
All security modes have been verified to work (at least complete
|
||||
authentication and successfully ping a wired host):
|
||||
- plaintext
|
||||
- static WEP / open system authentication
|
||||
- static WEP / shared key authentication
|
||||
- IEEE 802.1X with dynamic WEP keys
|
||||
- WPA-PSK, TKIP, CCMP, TKIP+CCMP
|
||||
- WPA-EAP, TKIP, CCMP, TKIP+CCMP
|
||||
- WPA2-PSK, TKIP, CCMP, TKIP+CCMP
|
||||
- WPA2-EAP, TKIP, CCMP, TKIP+CCMP
|
||||
|
||||
|
||||
Building wpa_supplicant with mingw
|
||||
----------------------------------
|
||||
|
||||
The default build setup for wpa_supplicant is to use MinGW and
|
||||
cross-compiling from Linux to MinGW/Windows. It should also be
|
||||
possible to build this under Windows using the MinGW tools, but that
|
||||
is not tested nor supported and is likely to require some changes to
|
||||
the Makefile unless cygwin is used.
|
||||
|
||||
|
||||
Building wpa_supplicant with MSVC
|
||||
---------------------------------
|
||||
|
||||
wpa_supplicant can be built with Microsoft Visual C++ compiler. This
|
||||
has been tested with Microsoft Visual C++ Toolkit 2003 and Visual
|
||||
Studio 2005 using the included nmake.mak as a Makefile for nmake. IDE
|
||||
can also be used by creating a project that includes the files and
|
||||
defines mentioned in nmake.mak. Example VS2005 solution and project
|
||||
files are included in vs2005 subdirectory. This can be used as a
|
||||
starting point for building the programs with VS2005 IDE. Visual Studio
|
||||
2008 Express Edition is also able to use these project files.
|
||||
|
||||
WinPcap development package is needed for the build and this can be
|
||||
downloaded from http://www.winpcap.org/install/bin/WpdPack_4_0_2.zip. The
|
||||
default nmake.mak expects this to be unpacked into C:\dev\WpdPack so
|
||||
that Include and Lib directories are in this directory. The files can be
|
||||
stored elsewhere as long as the WINPCAPDIR in nmake.mak is updated to
|
||||
match with the selected directory. In case a project file in the IDE is
|
||||
used, these Include and Lib directories need to be added to project
|
||||
properties as additional include/library directories.
|
||||
|
||||
OpenSSL source package can be downloaded from
|
||||
http://www.openssl.org/source/openssl-0.9.8i.tar.gz and built and
|
||||
installed following instructions in INSTALL.W32. Note that if EAP-FAST
|
||||
support will be included in the wpa_supplicant, OpenSSL needs to be
|
||||
patched to# support it openssl-0.9.8i-tls-extensions.patch. The example
|
||||
nmake.mak file expects OpenSSL to be installed into C:\dev\openssl, but
|
||||
this directory can be modified by changing OPENSSLDIR variable in
|
||||
nmake.mak.
|
||||
|
||||
If you do not need EAP-FAST support, you may also be able to use Win32
|
||||
binary installation package of OpenSSL from
|
||||
http://www.slproweb.com/products/Win32OpenSSL.html instead of building
|
||||
the library yourself. In this case, you will need to copy Include and
|
||||
Lib directories in suitable directory, e.g., C:\dev\openssl for the
|
||||
default nmake.mak. Copy {Win32OpenSSLRoot}\include into
|
||||
C:\dev\openssl\include and make C:\dev\openssl\lib subdirectory with
|
||||
files from {Win32OpenSSLRoot}\VC (i.e., libeay*.lib and ssleay*.lib).
|
||||
This will end up using dynamically linked OpenSSL (i.e., .dll files are
|
||||
needed) for it. Alternative, you can copy files from
|
||||
{Win32OpenSSLRoot}\VC\static to create a static build (no OpenSSL .dll
|
||||
files needed).
|
||||
|
||||
|
||||
Building wpa_supplicant for cygwin
|
||||
----------------------------------
|
||||
|
||||
wpa_supplicant can be built for cygwin by installing the needed
|
||||
development packages for cygwin. This includes things like compiler,
|
||||
make, openssl development package, etc. In addition, developer's pack
|
||||
for WinPcap (WPdpack.zip) from
|
||||
http://winpcap.polito.it/install/default.htm is needed.
|
||||
|
||||
.config file should enable only one driver interface,
|
||||
CONFIG_DRIVER_NDIS. In addition, include directories may need to be
|
||||
added to match the system. An example configuration is available in
|
||||
defconfig. The library and include files for WinPcap will either need
|
||||
to be installed in compiler/linker default directories or their
|
||||
location will need to be adding to .config when building
|
||||
wpa_supplicant.
|
||||
|
||||
Othen than this, the build should be more or less identical to Linux
|
||||
version, i.e., just run make after having created .config file. An
|
||||
additional tool, win_if_list.exe, can be built by running "make
|
||||
win_if_list".
|
||||
|
||||
|
||||
Building wpa_gui
|
||||
----------------
|
||||
|
||||
wpa_gui uses Qt application framework from Trolltech. It can be built
|
||||
with the open source version of Qt4 and MinGW. Following commands can
|
||||
be used to build the binary in the Qt 4 Command Prompt:
|
||||
|
||||
# go to the root directory of wpa_supplicant source code
|
||||
cd wpa_gui-qt4
|
||||
qmake -o Makefile wpa_gui.pro
|
||||
make
|
||||
# the wpa_gui.exe binary is created into 'release' subdirectory
|
||||
|
||||
|
||||
Using wpa_supplicant for Windows
|
||||
--------------------------------
|
||||
|
||||
wpa_supplicant, wpa_cli, and wpa_gui behave more or less identically to
|
||||
Linux version, so instructions in README and example wpa_supplicant.conf
|
||||
should be applicable for most parts. In addition, there is another
|
||||
version of wpa_supplicant, wpasvc.exe, which can be used as a Windows
|
||||
service and which reads its configuration from registry instead of
|
||||
text file.
|
||||
|
||||
When using access points in "hidden SSID" mode, ap_scan=2 mode need to
|
||||
be used (see wpa_supplicant.conf for more information).
|
||||
|
||||
Windows NDIS/WinPcap uses quite long interface names, so some care
|
||||
will be needed when starting wpa_supplicant. Alternatively, the
|
||||
adapter description can be used as the interface name which may be
|
||||
easier since it is usually in more human-readable
|
||||
format. win_if_list.exe can be used to find out the proper interface
|
||||
name.
|
||||
|
||||
Example steps in starting up wpa_supplicant:
|
||||
|
||||
# win_if_list.exe
|
||||
ifname: \Device\NPF_GenericNdisWanAdapter
|
||||
description: Generic NdisWan adapter
|
||||
|
||||
ifname: \Device\NPF_{769E012B-FD17-4935-A5E3-8090C38E25D2}
|
||||
description: Atheros Wireless Network Adapter (Microsoft's Packet Scheduler)
|
||||
|
||||
ifname: \Device\NPF_{732546E7-E26C-48E3-9871-7537B020A211}
|
||||
description: Intel 8255x-based Integrated Fast Ethernet (Microsoft's Packet Scheduler)
|
||||
|
||||
|
||||
Since the example configuration used Atheros WLAN card, the middle one
|
||||
is the correct interface in this case. The interface name for -i
|
||||
command line option is the full string following "ifname:" (the
|
||||
"\Device\NPF_" prefix can be removed). In other words, wpa_supplicant
|
||||
would be started with the following command:
|
||||
|
||||
# wpa_supplicant.exe -i'{769E012B-FD17-4935-A5E3-8090C38E25D2}' -c wpa_supplicant.conf -d
|
||||
|
||||
-d optional enables some more debugging (use -dd for even more, if
|
||||
needed). It can be left out if debugging information is not needed.
|
||||
|
||||
With the alternative mechanism for selecting the interface, this
|
||||
command has identical results in this case:
|
||||
|
||||
# wpa_supplicant.exe -iAtheros -c wpa_supplicant.conf -d
|
||||
|
||||
|
||||
Simple configuration example for WPA-PSK:
|
||||
|
||||
#ap_scan=2
|
||||
ctrl_interface=
|
||||
network={
|
||||
ssid="test"
|
||||
key_mgmt=WPA-PSK
|
||||
proto=WPA
|
||||
pairwise=TKIP
|
||||
psk="secret passphrase"
|
||||
}
|
||||
|
||||
(remove '#' from the comment out ap_scan line to enable mode in which
|
||||
wpa_supplicant tries to associate with the SSID without doing
|
||||
scanning; this allows APs with hidden SSIDs to be used)
|
||||
|
||||
|
||||
wpa_cli.exe and wpa_gui.exe can be used to interact with the
|
||||
wpa_supplicant.exe program in the same way as with Linux. Note that
|
||||
ctrl_interface is using UNIX domain sockets when built for cygwin, but
|
||||
the native build for Windows uses named pipes and the contents of the
|
||||
ctrl_interface configuration item is used to control access to the
|
||||
interface. Anyway, this variable has to be included in the configuration
|
||||
to enable the control interface.
|
||||
|
||||
|
||||
Example SDDL string formats:
|
||||
|
||||
(local admins group has permission, but nobody else):
|
||||
|
||||
ctrl_interface=SDDL=D:(A;;GA;;;BA)
|
||||
|
||||
("A" == "access allowed", "GA" == GENERIC_ALL == all permissions, and
|
||||
"BA" == "builtin administrators" == the local admins. The empty fields
|
||||
are for flags and object GUIDs, none of which should be required in this
|
||||
case.)
|
||||
|
||||
(local admins and the local "power users" group have permissions,
|
||||
but nobody else):
|
||||
|
||||
ctrl_interface=SDDL=D:(A;;GA;;;BA)(A;;GA;;;PU)
|
||||
|
||||
(One ACCESS_ALLOWED ACE for GENERIC_ALL for builtin administrators, and
|
||||
one ACCESS_ALLOWED ACE for GENERIC_ALL for power users.)
|
||||
|
||||
(close to wide open, but you have to be a valid user on
|
||||
the machine):
|
||||
|
||||
ctrl_interface=SDDL=D:(A;;GA;;;AU)
|
||||
|
||||
(One ACCESS_ALLOWED ACE for GENERIC_ALL for the "authenticated users"
|
||||
group.)
|
||||
|
||||
This one would allow absolutely everyone (including anonymous
|
||||
users) -- this is *not* recommended, since named pipes can be attached
|
||||
to from anywhere on the network (i.e. there's no "this machine only"
|
||||
like there is with 127.0.0.1 sockets):
|
||||
|
||||
ctrl_interface=SDDL=D:(A;;GA;;;BU)(A;;GA;;;AN)
|
||||
|
||||
(BU == "builtin users", "AN" == "anonymous")
|
||||
|
||||
See also [1] for the format of ACEs, and [2] for the possible strings
|
||||
that can be used for principal names.
|
||||
|
||||
[1]
|
||||
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthz/security/ace_strings.asp
|
||||
[2]
|
||||
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthz/security/sid_strings.asp
|
||||
|
||||
|
||||
Starting wpa_supplicant as a Windows service (wpasvc.exe)
|
||||
---------------------------------------------------------
|
||||
|
||||
wpa_supplicant can be started as a Windows service by using wpasvc.exe
|
||||
program that is alternative build of wpa_supplicant.exe. Most of the
|
||||
core functionality of wpasvc.exe is identical to wpa_supplicant.exe,
|
||||
but it is using Windows registry for configuration information instead
|
||||
of a text file and command line parameters. In addition, it can be
|
||||
registered as a service that can be started automatically or manually
|
||||
like any other Windows service.
|
||||
|
||||
The root of wpa_supplicant configuration in registry is
|
||||
HKEY_LOCAL_MACHINE\SOFTWARE\wpa_supplicant. This level includes global
|
||||
parameters and a 'interfaces' subkey with all the interface configuration
|
||||
(adapter to confname mapping). Each such mapping is a subkey that has
|
||||
'adapter', 'config', and 'ctrl_interface' values.
|
||||
|
||||
This program can be run either as a normal command line application,
|
||||
e.g., for debugging, with 'wpasvc.exe app' or as a Windows service.
|
||||
Service need to be registered with 'wpasvc.exe reg <full path to
|
||||
wpasvc.exe>'. Alternatively, 'wpasvc.exe reg' can be used to register
|
||||
the service with the current location of wpasvc.exe. After this, wpasvc
|
||||
can be started like any other Windows service (e.g., 'net start wpasvc')
|
||||
or it can be configured to start automatically through the Services tool
|
||||
in administrative tasks. The service can be unregistered with
|
||||
'wpasvc.exe unreg'.
|
||||
|
||||
If the service is set to start during system bootup to make the
|
||||
network connection available before any user has logged in, there may
|
||||
be a long (half a minute or so) delay in starting up wpa_supplicant
|
||||
due to WinPcap needing a driver called "Network Monitor Driver" which
|
||||
is started by default on demand.
|
||||
|
||||
To speed up wpa_supplicant start during system bootup, "Network
|
||||
Monitor Driver" can be configured to be started sooner by setting its
|
||||
startup type to System instead of the default Demand. To do this, open
|
||||
up Device Manager, select Show Hidden Devices, expand the "Non
|
||||
Plug-and-Play devices" branch, double click "Network Monitor Driver",
|
||||
go to the Driver tab, and change the Demand setting to System instead.
|
||||
|
||||
Configuration data is in HKEY_LOCAL_MACHINE\SOFTWARE\wpa_supplicant\configs
|
||||
key. Each configuration profile has its own key under this. In terms of text
|
||||
files, each profile would map to a separate text file with possibly multiple
|
||||
networks. Under each profile, there is a networks key that lists all
|
||||
networks as a subkey. Each network has set of values in the same way as
|
||||
network block in the configuration file. In addition, blobs subkey has
|
||||
possible blobs as values.
|
||||
|
||||
HKEY_LOCAL_MACHINE\SOFTWARE\wpa_supplicant\configs\test\networks\0000
|
||||
ssid="example"
|
||||
key_mgmt=WPA-PSK
|
||||
|
||||
See win_example.reg for an example on how to setup wpasvc.exe
|
||||
parameters in registry. It can also be imported to registry as a
|
||||
starting point for the configuration.
|
545
wpa_supplicant/android.config
Normal file
545
wpa_supplicant/android.config
Normal file
@ -0,0 +1,545 @@
|
||||
# Example wpa_supplicant build time configuration
|
||||
#
|
||||
# This file lists the configuration options that are used when building the
|
||||
# wpa_supplicant binary. All lines starting with # are ignored. Configuration
|
||||
# option lines must be commented out complete, if they are not to be included,
|
||||
# i.e., just setting VARIABLE=n is not disabling that variable.
|
||||
#
|
||||
# This file is included in Makefile, so variables like CFLAGS and LIBS can also
|
||||
# be modified from here. In most cases, these lines should use += in order not
|
||||
# to override previous values of the variables.
|
||||
|
||||
|
||||
# Uncomment following two lines and fix the paths if you have installed OpenSSL
|
||||
# or GnuTLS in non-default location
|
||||
#CFLAGS += -I/usr/local/openssl/include
|
||||
#LIBS += -L/usr/local/openssl/lib
|
||||
|
||||
# Some Red Hat versions seem to include kerberos header files from OpenSSL, but
|
||||
# the kerberos files are not in the default include path. Following line can be
|
||||
# used to fix build issues on such systems (krb5.h not found).
|
||||
#CFLAGS += -I/usr/include/kerberos
|
||||
|
||||
# Driver interface for generic Linux wireless extensions
|
||||
# Note: WEXT is deprecated in the current Linux kernel version and no new
|
||||
# functionality is added to it. nl80211-based interface is the new
|
||||
# replacement for WEXT and its use allows wpa_supplicant to properly control
|
||||
# the driver to improve existing functionality like roaming and to support new
|
||||
# functionality.
|
||||
#CONFIG_DRIVER_WEXT=y
|
||||
|
||||
# Driver interface for Linux drivers using the nl80211 kernel interface
|
||||
#CONFIG_DRIVER_NL80211=y
|
||||
CONFIG_LIBNL20=y
|
||||
|
||||
# QCA vendor extensions to nl80211
|
||||
CONFIG_DRIVER_NL80211_QCA=y
|
||||
|
||||
# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
|
||||
#CONFIG_DRIVER_BSD=y
|
||||
#CFLAGS += -I/usr/local/include
|
||||
#LIBS += -L/usr/local/lib
|
||||
#LIBS_p += -L/usr/local/lib
|
||||
#LIBS_c += -L/usr/local/lib
|
||||
|
||||
# Driver interface for Windows NDIS
|
||||
#CONFIG_DRIVER_NDIS=y
|
||||
#CFLAGS += -I/usr/include/w32api/ddk
|
||||
#LIBS += -L/usr/local/lib
|
||||
# For native build using mingw
|
||||
#CONFIG_NATIVE_WINDOWS=y
|
||||
# Additional directories for cross-compilation on Linux host for mingw target
|
||||
#CFLAGS += -I/opt/mingw/mingw32/include/ddk
|
||||
#LIBS += -L/opt/mingw/mingw32/lib
|
||||
#CC=mingw32-gcc
|
||||
# By default, driver_ndis uses WinPcap for low-level operations. This can be
|
||||
# replaced with the following option which replaces WinPcap calls with NDISUIO.
|
||||
# However, this requires that WZC is disabled (net stop wzcsvc) before starting
|
||||
# wpa_supplicant.
|
||||
# CONFIG_USE_NDISUIO=y
|
||||
|
||||
# Driver interface for wired Ethernet drivers
|
||||
#CONFIG_DRIVER_WIRED=y
|
||||
|
||||
# Driver interface for the Broadcom RoboSwitch family
|
||||
#CONFIG_DRIVER_ROBOSWITCH=y
|
||||
|
||||
# Driver interface for no driver (e.g., WPS ER only)
|
||||
#CONFIG_DRIVER_NONE=y
|
||||
|
||||
# Solaris libraries
|
||||
#LIBS += -lsocket -ldlpi -lnsl
|
||||
#LIBS_c += -lsocket
|
||||
|
||||
# Enable IEEE 802.1X Supplicant (automatically included if any EAP method is
|
||||
# included)
|
||||
CONFIG_IEEE8021X_EAPOL=y
|
||||
|
||||
# EAP-MD5
|
||||
CONFIG_EAP_MD5=y
|
||||
|
||||
# EAP-MSCHAPv2
|
||||
CONFIG_EAP_MSCHAPV2=y
|
||||
|
||||
# EAP-TLS
|
||||
CONFIG_EAP_TLS=y
|
||||
|
||||
# EAL-PEAP
|
||||
CONFIG_EAP_PEAP=y
|
||||
|
||||
# EAP-TTLS
|
||||
CONFIG_EAP_TTLS=y
|
||||
|
||||
# EAP-FAST
|
||||
#CONFIG_EAP_FAST=y
|
||||
|
||||
# EAP-GTC
|
||||
CONFIG_EAP_GTC=y
|
||||
|
||||
# EAP-OTP
|
||||
CONFIG_EAP_OTP=y
|
||||
|
||||
# EAP-SIM (enable CONFIG_PCSC, if EAP-SIM is used)
|
||||
CONFIG_EAP_SIM=y
|
||||
|
||||
# EAP-PSK (experimental; this is _not_ needed for WPA-PSK)
|
||||
#CONFIG_EAP_PSK=y
|
||||
|
||||
# EAP-pwd (secure authentication using only a password)
|
||||
CONFIG_EAP_PWD=y
|
||||
|
||||
# EAP-PAX
|
||||
#CONFIG_EAP_PAX=y
|
||||
|
||||
# LEAP
|
||||
CONFIG_EAP_LEAP=y
|
||||
|
||||
# EAP-AKA (enable CONFIG_PCSC, if EAP-AKA is used)
|
||||
CONFIG_EAP_AKA=y
|
||||
|
||||
# EAP-AKA' (enable CONFIG_PCSC, if EAP-AKA' is used).
|
||||
# This requires CONFIG_EAP_AKA to be enabled, too.
|
||||
CONFIG_EAP_AKA_PRIME=y
|
||||
|
||||
# Enable USIM simulator (Milenage) for EAP-AKA
|
||||
#CONFIG_USIM_SIMULATOR=y
|
||||
|
||||
# EAP-SAKE
|
||||
#CONFIG_EAP_SAKE=y
|
||||
|
||||
# EAP-GPSK
|
||||
#CONFIG_EAP_GPSK=y
|
||||
# Include support for optional SHA256 cipher suite in EAP-GPSK
|
||||
#CONFIG_EAP_GPSK_SHA256=y
|
||||
|
||||
# EAP-TNC and related Trusted Network Connect support (experimental)
|
||||
#CONFIG_EAP_TNC=y
|
||||
|
||||
# Wi-Fi Protected Setup (WPS)
|
||||
CONFIG_WPS=y
|
||||
# Enable WPS external registrar functionality
|
||||
CONFIG_WPS_ER=y
|
||||
# Disable credentials for an open network by default when acting as a WPS
|
||||
# registrar.
|
||||
#CONFIG_WPS_REG_DISABLE_OPEN=y
|
||||
# Enable WPS support with NFC config method
|
||||
CONFIG_WPS_NFC=y
|
||||
|
||||
# EAP-IKEv2
|
||||
#CONFIG_EAP_IKEV2=y
|
||||
|
||||
# EAP-EKE
|
||||
#CONFIG_EAP_EKE=y
|
||||
|
||||
# PKCS#12 (PFX) support (used to read private key and certificate file from
|
||||
# a file that usually has extension .p12 or .pfx)
|
||||
CONFIG_PKCS12=y
|
||||
|
||||
# Smartcard support (i.e., private key on a smartcard), e.g., with openssl
|
||||
# engine.
|
||||
CONFIG_SMARTCARD=y
|
||||
|
||||
# PC/SC interface for smartcards (USIM, GSM SIM)
|
||||
# Enable this if EAP-SIM or EAP-AKA is included
|
||||
#CONFIG_PCSC=y
|
||||
|
||||
# Support HT overrides (disable HT/HT40, mask MCS rates, etc.)
|
||||
#CONFIG_HT_OVERRIDES=y
|
||||
|
||||
# Support VHT overrides (disable VHT, mask MCS rates, etc.)
|
||||
#CONFIG_VHT_OVERRIDES=y
|
||||
|
||||
# Development testing
|
||||
#CONFIG_EAPOL_TEST=y
|
||||
|
||||
# Select control interface backend for external programs, e.g, wpa_cli:
|
||||
# unix = UNIX domain sockets (default for Linux/*BSD)
|
||||
# udp = UDP sockets using localhost (127.0.0.1)
|
||||
# udp6 = UDP IPv6 sockets using localhost (::1)
|
||||
# named_pipe = Windows Named Pipe (default for Windows)
|
||||
# udp-remote = UDP sockets with remote access (only for tests systems/purpose)
|
||||
# udp6-remote = UDP IPv6 sockets with remote access (only for tests purpose)
|
||||
# y = use default (backwards compatibility)
|
||||
# If this option is commented out, control interface is not included in the
|
||||
# build.
|
||||
CONFIG_CTRL_IFACE=y
|
||||
|
||||
# Include support for GNU Readline and History Libraries in wpa_cli.
|
||||
# When building a wpa_cli binary for distribution, please note that these
|
||||
# libraries are licensed under GPL and as such, BSD license may not apply for
|
||||
# the resulting binary.
|
||||
#CONFIG_READLINE=y
|
||||
|
||||
# Include internal line edit mode in wpa_cli. This can be used as a replacement
|
||||
# for GNU Readline to provide limited command line editing and history support.
|
||||
CONFIG_WPA_CLI_EDIT=y
|
||||
|
||||
# Remove debugging code that is printing out debug message to stdout.
|
||||
# This can be used to reduce the size of the wpa_supplicant considerably
|
||||
# if debugging code is not needed. The size reduction can be around 35%
|
||||
# (e.g., 90 kB).
|
||||
#CONFIG_NO_STDOUT_DEBUG=y
|
||||
|
||||
# Remove WPA support, e.g., for wired-only IEEE 802.1X supplicant, to save
|
||||
# 35-50 kB in code size.
|
||||
#CONFIG_NO_WPA=y
|
||||
|
||||
# Remove IEEE 802.11i/WPA-Personal ASCII passphrase support
|
||||
# This option can be used to reduce code size by removing support for
|
||||
# converting ASCII passphrases into PSK. If this functionality is removed, the
|
||||
# PSK can only be configured as the 64-octet hexstring (e.g., from
|
||||
# wpa_passphrase). This saves about 0.5 kB in code size.
|
||||
#CONFIG_NO_WPA_PASSPHRASE=y
|
||||
|
||||
# Disable scan result processing (ap_mode=1) to save code size by about 1 kB.
|
||||
# This can be used if ap_scan=1 mode is never enabled.
|
||||
#CONFIG_NO_SCAN_PROCESSING=y
|
||||
|
||||
# Select configuration backend:
|
||||
# file = text file (e.g., wpa_supplicant.conf; note: the configuration file
|
||||
# path is given on command line, not here; this option is just used to
|
||||
# select the backend that allows configuration files to be used)
|
||||
# winreg = Windows registry (see win_example.reg for an example)
|
||||
CONFIG_BACKEND=file
|
||||
|
||||
# Remove configuration write functionality (i.e., to allow the configuration
|
||||
# file to be updated based on runtime configuration changes). The runtime
|
||||
# configuration can still be changed, the changes are just not going to be
|
||||
# persistent over restarts. This option can be used to reduce code size by
|
||||
# about 3.5 kB.
|
||||
#CONFIG_NO_CONFIG_WRITE=y
|
||||
|
||||
# Remove support for configuration blobs to reduce code size by about 1.5 kB.
|
||||
#CONFIG_NO_CONFIG_BLOBS=y
|
||||
|
||||
# Select program entry point implementation:
|
||||
# main = UNIX/POSIX like main() function (default)
|
||||
# main_winsvc = Windows service (read parameters from registry)
|
||||
# main_none = Very basic example (development use only)
|
||||
#CONFIG_MAIN=main
|
||||
|
||||
# Select wrapper for operating system and C library specific functions
|
||||
# unix = UNIX/POSIX like systems (default)
|
||||
# win32 = Windows systems
|
||||
# none = Empty template
|
||||
CONFIG_OS=unix
|
||||
|
||||
# Select event loop implementation
|
||||
# eloop = select() loop (default)
|
||||
# eloop_win = Windows events and WaitForMultipleObject() loop
|
||||
CONFIG_ELOOP=eloop
|
||||
|
||||
# Should we use poll instead of select? Select is used by default.
|
||||
#CONFIG_ELOOP_POLL=y
|
||||
|
||||
# Should we use epoll instead of select? Select is used by default.
|
||||
#CONFIG_ELOOP_EPOLL=y
|
||||
|
||||
# Should we use kqueue instead of select? Select is used by default.
|
||||
#CONFIG_ELOOP_KQUEUE=y
|
||||
|
||||
# Select layer 2 packet implementation
|
||||
# linux = Linux packet socket (default)
|
||||
# pcap = libpcap/libdnet/WinPcap
|
||||
# freebsd = FreeBSD libpcap
|
||||
# winpcap = WinPcap with receive thread
|
||||
# ndis = Windows NDISUIO (note: requires CONFIG_USE_NDISUIO=y)
|
||||
# none = Empty template
|
||||
CONFIG_L2_PACKET=linux
|
||||
|
||||
# Disable Linux packet socket workaround applicable for station interface
|
||||
# in a bridge for EAPOL frames. This should be uncommented only if the kernel
|
||||
# is known to not have the regression issue in packet socket behavior with
|
||||
# bridge interfaces (commit 'bridge: respect RFC2863 operational state')').
|
||||
#CONFIG_NO_LINUX_PACKET_SOCKET_WAR=y
|
||||
|
||||
# Support Operating Channel Validation
|
||||
#CONFIG_OCV=y
|
||||
|
||||
# Select TLS implementation
|
||||
# openssl = OpenSSL (default)
|
||||
# gnutls = GnuTLS
|
||||
# internal = Internal TLSv1 implementation (experimental)
|
||||
# none = Empty template
|
||||
#CONFIG_TLS=openssl
|
||||
|
||||
# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
|
||||
# can be enabled to get a stronger construction of messages when block ciphers
|
||||
# are used. It should be noted that some existing TLS v1.0 -based
|
||||
# implementation may not be compatible with TLS v1.1 message (ClientHello is
|
||||
# sent prior to negotiating which version will be used)
|
||||
#CONFIG_TLSV11=y
|
||||
|
||||
# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2)
|
||||
# can be enabled to enable use of stronger crypto algorithms. It should be
|
||||
# noted that some existing TLS v1.0 -based implementation may not be compatible
|
||||
# with TLS v1.2 message (ClientHello is sent prior to negotiating which version
|
||||
# will be used)
|
||||
#CONFIG_TLSV12=y
|
||||
|
||||
# Select which ciphers to use by default with OpenSSL if the user does not
|
||||
# specify them.
|
||||
#CONFIG_TLS_DEFAULT_CIPHERS="DEFAULT:!EXP:!LOW"
|
||||
|
||||
# If CONFIG_TLS=internal is used, additional library and include paths are
|
||||
# needed for LibTomMath. Alternatively, an integrated, minimal version of
|
||||
# LibTomMath can be used. See beginning of libtommath.c for details on benefits
|
||||
# and drawbacks of this option.
|
||||
#CONFIG_INTERNAL_LIBTOMMATH=y
|
||||
#ifndef CONFIG_INTERNAL_LIBTOMMATH
|
||||
#LTM_PATH=/usr/src/libtommath-0.39
|
||||
#CFLAGS += -I$(LTM_PATH)
|
||||
#LIBS += -L$(LTM_PATH)
|
||||
#LIBS_p += -L$(LTM_PATH)
|
||||
#endif
|
||||
# At the cost of about 4 kB of additional binary size, the internal LibTomMath
|
||||
# can be configured to include faster routines for exptmod, sqr, and div to
|
||||
# speed up DH and RSA calculation considerably
|
||||
#CONFIG_INTERNAL_LIBTOMMATH_FAST=y
|
||||
|
||||
# Include NDIS event processing through WMI into wpa_supplicant/wpasvc.
|
||||
# This is only for Windows builds and requires WMI-related header files and
|
||||
# WbemUuid.Lib from Platform SDK even when building with MinGW.
|
||||
#CONFIG_NDIS_EVENTS_INTEGRATED=y
|
||||
#PLATFORMSDKLIB="/opt/Program Files/Microsoft Platform SDK/Lib"
|
||||
|
||||
# Add support for new DBus control interface
|
||||
# (fi.w1.hostap.wpa_supplicant1)
|
||||
#CONFIG_CTRL_IFACE_DBUS_NEW=y
|
||||
|
||||
# Add introspection support for new DBus control interface
|
||||
#CONFIG_CTRL_IFACE_DBUS_INTRO=y
|
||||
|
||||
# Add support for Binder control interface
|
||||
# Only applicable for Android platforms.
|
||||
#CONFIG_CTRL_IFACE_BINDER=y
|
||||
|
||||
# Add support for loading EAP methods dynamically as shared libraries.
|
||||
# When this option is enabled, each EAP method can be either included
|
||||
# statically (CONFIG_EAP_<method>=y) or dynamically (CONFIG_EAP_<method>=dyn).
|
||||
# Dynamic EAP methods are build as shared objects (eap_*.so) and they need to
|
||||
# be loaded in the beginning of the wpa_supplicant configuration file
|
||||
# (see load_dynamic_eap parameter in the example file) before being used in
|
||||
# the network blocks.
|
||||
#
|
||||
# Note that some shared parts of EAP methods are included in the main program
|
||||
# and in order to be able to use dynamic EAP methods using these parts, the
|
||||
# main program must have been build with the EAP method enabled (=y or =dyn).
|
||||
# This means that EAP-TLS/PEAP/TTLS/FAST cannot be added as dynamic libraries
|
||||
# unless at least one of them was included in the main build to force inclusion
|
||||
# of the shared code. Similarly, at least one of EAP-SIM/AKA must be included
|
||||
# in the main build to be able to load these methods dynamically.
|
||||
#
|
||||
# Please also note that using dynamic libraries will increase the total binary
|
||||
# size. Thus, it may not be the best option for targets that have limited
|
||||
# amount of memory/flash.
|
||||
#CONFIG_DYNAMIC_EAP_METHODS=y
|
||||
|
||||
# IEEE Std 802.11r-2008 (Fast BSS Transition) for station mode
|
||||
CONFIG_IEEE80211R=y
|
||||
|
||||
# Add support for writing debug log to a file (/tmp/wpa_supplicant-log-#.txt)
|
||||
#CONFIG_DEBUG_FILE=y
|
||||
|
||||
# Send debug messages to syslog instead of stdout
|
||||
#CONFIG_DEBUG_SYSLOG=y
|
||||
# Set syslog facility for debug messages
|
||||
#CONFIG_DEBUG_SYSLOG_FACILITY=LOG_DAEMON
|
||||
|
||||
# Add support for sending all debug messages (regardless of debug verbosity)
|
||||
# to the Linux kernel tracing facility. This helps debug the entire stack by
|
||||
# making it easy to record everything happening from the driver up into the
|
||||
# same file, e.g., using trace-cmd.
|
||||
#CONFIG_DEBUG_LINUX_TRACING=y
|
||||
|
||||
# Add support for writing debug log to Android logcat instead of standard
|
||||
# output
|
||||
CONFIG_ANDROID_LOG=y
|
||||
|
||||
# Enable privilege separation (see README 'Privilege separation' for details)
|
||||
#CONFIG_PRIVSEP=y
|
||||
|
||||
# Enable mitigation against certain attacks against TKIP by delaying Michael
|
||||
# MIC error reports by a random amount of time between 0 and 60 seconds
|
||||
#CONFIG_DELAYED_MIC_ERROR_REPORT=y
|
||||
|
||||
# Enable tracing code for developer debugging
|
||||
# This tracks use of memory allocations and other registrations and reports
|
||||
# incorrect use with a backtrace of call (or allocation) location.
|
||||
#CONFIG_WPA_TRACE=y
|
||||
# For BSD, uncomment these.
|
||||
#LIBS += -lexecinfo
|
||||
#LIBS_p += -lexecinfo
|
||||
#LIBS_c += -lexecinfo
|
||||
|
||||
# Use libbfd to get more details for developer debugging
|
||||
# This enables use of libbfd to get more detailed symbols for the backtraces
|
||||
# generated by CONFIG_WPA_TRACE=y.
|
||||
#CONFIG_WPA_TRACE_BFD=y
|
||||
# For BSD, uncomment these.
|
||||
#LIBS += -lbfd -liberty -lz
|
||||
#LIBS_p += -lbfd -liberty -lz
|
||||
#LIBS_c += -lbfd -liberty -lz
|
||||
|
||||
# wpa_supplicant depends on strong random number generation being available
|
||||
# from the operating system. os_get_random() function is used to fetch random
|
||||
# data when needed, e.g., for key generation. On Linux and BSD systems, this
|
||||
# works by reading /dev/urandom. It should be noted that the OS entropy pool
|
||||
# needs to be properly initialized before wpa_supplicant is started. This is
|
||||
# important especially on embedded devices that do not have a hardware random
|
||||
# number generator and may by default start up with minimal entropy available
|
||||
# for random number generation.
|
||||
#
|
||||
# As a safety net, wpa_supplicant is by default trying to internally collect
|
||||
# additional entropy for generating random data to mix in with the data fetched
|
||||
# from the OS. This by itself is not considered to be very strong, but it may
|
||||
# help in cases where the system pool is not initialized properly. However, it
|
||||
# is very strongly recommended that the system pool is initialized with enough
|
||||
# entropy either by using hardware assisted random number generator or by
|
||||
# storing state over device reboots.
|
||||
#
|
||||
# wpa_supplicant can be configured to maintain its own entropy store over
|
||||
# restarts to enhance random number generation. This is not perfect, but it is
|
||||
# much more secure than using the same sequence of random numbers after every
|
||||
# reboot. This can be enabled with -e<entropy file> command line option. The
|
||||
# specified file needs to be readable and writable by wpa_supplicant.
|
||||
#
|
||||
# If the os_get_random() is known to provide strong random data (e.g., on
|
||||
# Linux/BSD, the board in question is known to have reliable source of random
|
||||
# data from /dev/urandom), the internal wpa_supplicant random pool can be
|
||||
# disabled. This will save some in binary size and CPU use. However, this
|
||||
# should only be considered for builds that are known to be used on devices
|
||||
# that meet the requirements described above.
|
||||
|
||||
# Wpa_supplicant's random pool is not necessary on Android. Randomness is
|
||||
# already provided by the entropymixer service which ensures sufficient
|
||||
# entropy is maintained across reboots. Commit b410eb1913 'Initialize
|
||||
# /dev/urandom earlier in boot' seeds /dev/urandom with that entropy before
|
||||
# either wpa_supplicant or hostapd are run.
|
||||
CONFIG_NO_RANDOM_POOL=y
|
||||
|
||||
# IEEE 802.11ac (Very High Throughput) support (mainly for AP mode)
|
||||
#CONFIG_IEEE80211AC=y
|
||||
|
||||
# Wireless Network Management (IEEE Std 802.11v-2011)
|
||||
# Note: This is experimental and not complete implementation.
|
||||
CONFIG_WNM=y
|
||||
|
||||
# Interworking (IEEE 802.11u)
|
||||
# This can be used to enable functionality to improve interworking with
|
||||
# external networks (GAS/ANQP to learn more about the networks and network
|
||||
# selection based on available credentials).
|
||||
CONFIG_INTERWORKING=y
|
||||
|
||||
# Hotspot 2.0
|
||||
CONFIG_HS20=y
|
||||
|
||||
# Enable interface matching in wpa_supplicant
|
||||
#CONFIG_MATCH_IFACE=y
|
||||
|
||||
# Disable roaming in wpa_supplicant
|
||||
CONFIG_NO_ROAMING=y
|
||||
|
||||
# AP mode operations with wpa_supplicant
|
||||
# This can be used for controlling AP mode operations with wpa_supplicant. It
|
||||
# should be noted that this is mainly aimed at simple cases like
|
||||
# WPA2-Personal while more complex configurations like WPA2-Enterprise with an
|
||||
# external RADIUS server can be supported with hostapd.
|
||||
CONFIG_AP=y
|
||||
|
||||
# P2P (Wi-Fi Direct)
|
||||
# This can be used to enable P2P support in wpa_supplicant. See README-P2P for
|
||||
# more information on P2P operations.
|
||||
CONFIG_P2P=y
|
||||
|
||||
# Enable TDLS support
|
||||
CONFIG_TDLS=y
|
||||
|
||||
# Wi-Fi Display
|
||||
# This can be used to enable Wi-Fi Display extensions for P2P using an external
|
||||
# program to control the additional information exchanges in the messages.
|
||||
CONFIG_WIFI_DISPLAY=y
|
||||
|
||||
# Autoscan
|
||||
# This can be used to enable automatic scan support in wpa_supplicant.
|
||||
# See wpa_supplicant.conf for more information on autoscan usage.
|
||||
#
|
||||
# Enabling directly a module will enable autoscan support.
|
||||
# For exponential module:
|
||||
#CONFIG_AUTOSCAN_EXPONENTIAL=y
|
||||
# For periodic module:
|
||||
#CONFIG_AUTOSCAN_PERIODIC=y
|
||||
|
||||
# Password (and passphrase, etc.) backend for external storage
|
||||
# These optional mechanisms can be used to add support for storing passwords
|
||||
# and other secrets in external (to wpa_supplicant) location. This allows, for
|
||||
# example, operating system specific key storage to be used
|
||||
#
|
||||
# External password backend for testing purposes (developer use)
|
||||
#CONFIG_EXT_PASSWORD_TEST=y
|
||||
|
||||
# Enable Fast Session Transfer (FST)
|
||||
#CONFIG_FST=y
|
||||
|
||||
# Support Multi Band Operation
|
||||
#CONFIG_MBO=y
|
||||
|
||||
# Fast Initial Link Setup (FILS) (IEEE 802.11ai)
|
||||
#CONFIG_FILS=y
|
||||
|
||||
# Support RSN on IBSS networks
|
||||
# This is needed to be able to use mode=1 network profile with proto=RSN and
|
||||
# key_mgmt=WPA-PSK (i.e., full key management instead of WPA-None).
|
||||
#CONFIG_IBSS_RSN=y
|
||||
|
||||
# External PMKSA cache control
|
||||
# This can be used to enable control interface commands that allow the current
|
||||
# PMKSA cache entries to be fetched and new entries to be added.
|
||||
#CONFIG_PMKSA_CACHE_EXTERNAL=y
|
||||
|
||||
# Mesh Networking (IEEE 802.11s)
|
||||
#CONFIG_MESH=y
|
||||
|
||||
# Background scanning modules
|
||||
# These can be used to request wpa_supplicant to perform background scanning
|
||||
# operations for roaming within an ESS (same SSID). See the bgscan parameter in
|
||||
# the wpa_supplicant.conf file for more details.
|
||||
# Periodic background scans based on signal strength
|
||||
#CONFIG_BGSCAN_SIMPLE=y
|
||||
# Learn channels used by the network and try to avoid bgscans on other
|
||||
# channels (experimental)
|
||||
#CONFIG_BGSCAN_LEARN=y
|
||||
|
||||
# Opportunistic Wireless Encryption (OWE)
|
||||
# Experimental implementation of draft-harkins-owe-07.txt
|
||||
#CONFIG_OWE=y
|
||||
|
||||
# Wired equivalent privacy (WEP)
|
||||
# WEP is an obsolete cryptographic data confidentiality algorithm that is not
|
||||
# considered secure. It should not be used for anything anymore. The
|
||||
# functionality needed to use WEP is available in the current wpa_supplicant
|
||||
# release under this optional build parameter. This functionality is subject to
|
||||
# be completely removed in a future release.
|
||||
CONFIG_WEP=y
|
||||
|
||||
include $(wildcard $(LOCAL_PATH)/android_config_*.inc)
|
1945
wpa_supplicant/ap.c
Normal file
1945
wpa_supplicant/ap.c
Normal file
File diff suppressed because it is too large
Load Diff
106
wpa_supplicant/ap.h
Normal file
106
wpa_supplicant/ap.h
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* WPA Supplicant - Basic AP mode support routines
|
||||
* Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2009, Atheros Communications
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef AP_H
|
||||
#define AP_H
|
||||
|
||||
int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid);
|
||||
void wpa_supplicant_ap_deinit(struct wpa_supplicant *wpa_s);
|
||||
void wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s,
|
||||
const u8 *src_addr, const u8 *buf, size_t len);
|
||||
int wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||
const u8 *p2p_dev_addr);
|
||||
int wpa_supplicant_ap_wps_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||
const char *pin, char *buf, size_t buflen,
|
||||
int timeout);
|
||||
int wpa_supplicant_ap_wps_cancel(struct wpa_supplicant *wpa_s);
|
||||
void wpas_wps_ap_pin_disable(struct wpa_supplicant *wpa_s);
|
||||
const char * wpas_wps_ap_pin_random(struct wpa_supplicant *wpa_s, int timeout);
|
||||
const char * wpas_wps_ap_pin_get(struct wpa_supplicant *wpa_s);
|
||||
int wpas_wps_ap_pin_set(struct wpa_supplicant *wpa_s, const char *pin,
|
||||
int timeout);
|
||||
int ap_ctrl_iface_sta_first(struct wpa_supplicant *wpa_s,
|
||||
char *buf, size_t buflen);
|
||||
int ap_ctrl_iface_sta(struct wpa_supplicant *wpa_s, const char *txtaddr,
|
||||
char *buf, size_t buflen);
|
||||
int ap_ctrl_iface_sta_next(struct wpa_supplicant *wpa_s, const char *txtaddr,
|
||||
char *buf, size_t buflen);
|
||||
int ap_ctrl_iface_sta_deauthenticate(struct wpa_supplicant *wpa_s,
|
||||
const char *txtaddr);
|
||||
int ap_ctrl_iface_sta_disassociate(struct wpa_supplicant *wpa_s,
|
||||
const char *txtaddr);
|
||||
int ap_ctrl_iface_wpa_get_status(struct wpa_supplicant *wpa_s, char *buf,
|
||||
size_t buflen, int verbose);
|
||||
void ap_tx_status(void *ctx, const u8 *addr,
|
||||
const u8 *buf, size_t len, int ack);
|
||||
void ap_eapol_tx_status(void *ctx, const u8 *dst,
|
||||
const u8 *data, size_t len, int ack);
|
||||
void ap_client_poll_ok(void *ctx, const u8 *addr);
|
||||
void ap_rx_from_unknown_sta(void *ctx, const u8 *addr, int wds);
|
||||
void ap_mgmt_rx(void *ctx, struct rx_mgmt *rx_mgmt);
|
||||
void ap_mgmt_tx_cb(void *ctx, const u8 *buf, size_t len, u16 stype, int ok);
|
||||
int wpa_supplicant_ap_update_beacon(struct wpa_supplicant *wpa_s);
|
||||
int wpa_supplicant_ap_mac_addr_filter(struct wpa_supplicant *wpa_s,
|
||||
const u8 *addr);
|
||||
void wpa_supplicant_ap_pwd_auth_fail(struct wpa_supplicant *wpa_s);
|
||||
int ap_switch_channel(struct wpa_supplicant *wpa_s,
|
||||
struct csa_settings *settings);
|
||||
int ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *txtaddr);
|
||||
void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht,
|
||||
int offset, int width, int cf1, int cf2, int finished);
|
||||
struct wpabuf * wpas_ap_wps_nfc_config_token(struct wpa_supplicant *wpa_s,
|
||||
int ndef);
|
||||
#ifdef CONFIG_AP
|
||||
struct wpabuf * wpas_ap_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
|
||||
int ndef);
|
||||
#else /* CONFIG_AP */
|
||||
static inline struct wpabuf *
|
||||
wpas_ap_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
|
||||
int ndef)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_AP */
|
||||
|
||||
int wpas_ap_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
|
||||
const struct wpabuf *req,
|
||||
const struct wpabuf *sel);
|
||||
int wpas_ap_wps_add_nfc_pw(struct wpa_supplicant *wpa_s, u16 pw_id,
|
||||
const struct wpabuf *pw, const u8 *pubkey_hash);
|
||||
|
||||
struct hostapd_config;
|
||||
int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid,
|
||||
struct hostapd_config *conf);
|
||||
|
||||
int wpas_ap_stop_ap(struct wpa_supplicant *wpa_s);
|
||||
|
||||
int wpas_ap_pmksa_cache_list(struct wpa_supplicant *wpa_s, char *buf,
|
||||
size_t len);
|
||||
void wpas_ap_pmksa_cache_flush(struct wpa_supplicant *wpa_s);
|
||||
int wpas_ap_pmksa_cache_list_mesh(struct wpa_supplicant *wpa_s, const u8 *addr,
|
||||
char *buf, size_t len);
|
||||
int wpas_ap_pmksa_cache_add_external(struct wpa_supplicant *wpa_s, char *cmd);
|
||||
int wpas_ap_update_beacon(struct wpa_supplicant *wpa_s);
|
||||
|
||||
void wpas_ap_event_dfs_radar_detected(struct wpa_supplicant *wpa_s,
|
||||
struct dfs_event *radar);
|
||||
void wpas_ap_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
|
||||
struct dfs_event *radar);
|
||||
void wpas_ap_event_dfs_cac_finished(struct wpa_supplicant *wpa_s,
|
||||
struct dfs_event *radar);
|
||||
void wpas_ap_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s,
|
||||
struct dfs_event *radar);
|
||||
void wpas_ap_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s,
|
||||
struct dfs_event *radar);
|
||||
|
||||
void ap_periodic(struct wpa_supplicant *wpa_s);
|
||||
|
||||
#endif /* AP_H */
|
162
wpa_supplicant/autoscan.c
Normal file
162
wpa_supplicant/autoscan.c
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* WPA Supplicant - auto scan
|
||||
* Copyright (c) 2012, Intel Corporation. All rights reserved.
|
||||
* Copyright 2015 Intel Deutschland GmbH
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "config.h"
|
||||
#include "wpa_supplicant_i.h"
|
||||
#include "bss.h"
|
||||
#include "scan.h"
|
||||
#include "autoscan.h"
|
||||
|
||||
|
||||
static const struct autoscan_ops * autoscan_modules[] = {
|
||||
#ifdef CONFIG_AUTOSCAN_EXPONENTIAL
|
||||
&autoscan_exponential_ops,
|
||||
#endif /* CONFIG_AUTOSCAN_EXPONENTIAL */
|
||||
#ifdef CONFIG_AUTOSCAN_PERIODIC
|
||||
&autoscan_periodic_ops,
|
||||
#endif /* CONFIG_AUTOSCAN_PERIODIC */
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
static void request_scan(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
wpa_s->scan_req = MANUAL_SCAN_REQ;
|
||||
|
||||
if (wpa_supplicant_req_sched_scan(wpa_s))
|
||||
wpa_supplicant_req_scan(wpa_s, wpa_s->scan_interval, 0);
|
||||
}
|
||||
|
||||
|
||||
int autoscan_init(struct wpa_supplicant *wpa_s, int req_scan)
|
||||
{
|
||||
const char *name = wpa_s->conf->autoscan;
|
||||
const char *params;
|
||||
size_t nlen;
|
||||
int i;
|
||||
const struct autoscan_ops *ops = NULL;
|
||||
struct sched_scan_plan *scan_plans;
|
||||
|
||||
/* Give preference to scheduled scan plans if supported/configured */
|
||||
if (wpa_s->sched_scan_plans) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"autoscan: sched_scan_plans set - use it instead");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (wpa_s->autoscan && wpa_s->autoscan_priv) {
|
||||
wpa_printf(MSG_DEBUG, "autoscan: Already initialized");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (name == NULL)
|
||||
return 0;
|
||||
|
||||
params = os_strchr(name, ':');
|
||||
if (params == NULL) {
|
||||
params = "";
|
||||
nlen = os_strlen(name);
|
||||
} else {
|
||||
nlen = params - name;
|
||||
params++;
|
||||
}
|
||||
|
||||
for (i = 0; autoscan_modules[i]; i++) {
|
||||
if (os_strncmp(name, autoscan_modules[i]->name, nlen) == 0) {
|
||||
ops = autoscan_modules[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ops == NULL) {
|
||||
wpa_printf(MSG_ERROR, "autoscan: Could not find module "
|
||||
"matching the parameter '%s'", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
scan_plans = os_malloc(sizeof(*wpa_s->sched_scan_plans));
|
||||
if (!scan_plans)
|
||||
return -1;
|
||||
|
||||
wpa_s->autoscan_params = NULL;
|
||||
|
||||
wpa_s->autoscan_priv = ops->init(wpa_s, params);
|
||||
if (!wpa_s->autoscan_priv) {
|
||||
os_free(scan_plans);
|
||||
return -1;
|
||||
}
|
||||
|
||||
scan_plans[0].interval = 5;
|
||||
scan_plans[0].iterations = 0;
|
||||
os_free(wpa_s->sched_scan_plans);
|
||||
wpa_s->sched_scan_plans = scan_plans;
|
||||
wpa_s->sched_scan_plans_num = 1;
|
||||
wpa_s->autoscan = ops;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "autoscan: Initialized module '%s' with "
|
||||
"parameters '%s'", ops->name, params);
|
||||
if (!req_scan)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Cancelling existing scan requests, if any.
|
||||
*/
|
||||
wpa_supplicant_cancel_sched_scan(wpa_s);
|
||||
wpa_supplicant_cancel_scan(wpa_s);
|
||||
|
||||
/*
|
||||
* Firing first scan, which will lead to call autoscan_notify_scan.
|
||||
*/
|
||||
request_scan(wpa_s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void autoscan_deinit(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
if (wpa_s->autoscan && wpa_s->autoscan_priv) {
|
||||
wpa_printf(MSG_DEBUG, "autoscan: Deinitializing module '%s'",
|
||||
wpa_s->autoscan->name);
|
||||
wpa_s->autoscan->deinit(wpa_s->autoscan_priv);
|
||||
wpa_s->autoscan = NULL;
|
||||
wpa_s->autoscan_priv = NULL;
|
||||
|
||||
wpa_s->scan_interval = 5;
|
||||
|
||||
os_free(wpa_s->sched_scan_plans);
|
||||
wpa_s->sched_scan_plans = NULL;
|
||||
wpa_s->sched_scan_plans_num = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int autoscan_notify_scan(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_scan_results *scan_res)
|
||||
{
|
||||
int interval;
|
||||
|
||||
if (wpa_s->autoscan && wpa_s->autoscan_priv) {
|
||||
interval = wpa_s->autoscan->notify_scan(wpa_s->autoscan_priv,
|
||||
scan_res);
|
||||
|
||||
if (interval <= 0)
|
||||
return -1;
|
||||
|
||||
wpa_s->scan_interval = interval;
|
||||
wpa_s->sched_scan_plans[0].interval = interval;
|
||||
|
||||
request_scan(wpa_s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
59
wpa_supplicant/autoscan.h
Normal file
59
wpa_supplicant/autoscan.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* WPA Supplicant - auto scan
|
||||
* Copyright (c) 2012, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef AUTOSCAN_H
|
||||
#define AUTOSCAN_H
|
||||
|
||||
struct wpa_supplicant;
|
||||
|
||||
struct autoscan_ops {
|
||||
const char *name;
|
||||
|
||||
void * (*init)(struct wpa_supplicant *wpa_s, const char *params);
|
||||
void (*deinit)(void *priv);
|
||||
|
||||
int (*notify_scan)(void *priv, struct wpa_scan_results *scan_res);
|
||||
};
|
||||
|
||||
#ifdef CONFIG_AUTOSCAN
|
||||
|
||||
int autoscan_init(struct wpa_supplicant *wpa_s, int req_scan);
|
||||
void autoscan_deinit(struct wpa_supplicant *wpa_s);
|
||||
int autoscan_notify_scan(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_scan_results *scan_res);
|
||||
|
||||
/* Available autoscan modules */
|
||||
|
||||
#ifdef CONFIG_AUTOSCAN_EXPONENTIAL
|
||||
extern const struct autoscan_ops autoscan_exponential_ops;
|
||||
#endif /* CONFIG_AUTOSCAN_EXPONENTIAL */
|
||||
|
||||
#ifdef CONFIG_AUTOSCAN_PERIODIC
|
||||
extern const struct autoscan_ops autoscan_periodic_ops;
|
||||
#endif /* CONFIG_AUTOSCAN_PERIODIC */
|
||||
|
||||
#else /* CONFIG_AUTOSCAN */
|
||||
|
||||
static inline int autoscan_init(struct wpa_supplicant *wpa_s, int req_scan)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void autoscan_deinit(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int autoscan_notify_scan(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_scan_results *scan_res)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_AUTOSCAN */
|
||||
|
||||
#endif /* AUTOSCAN_H */
|
104
wpa_supplicant/autoscan_exponential.c
Normal file
104
wpa_supplicant/autoscan_exponential.c
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* WPA Supplicant - auto scan exponential module
|
||||
* Copyright (c) 2012, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "wpa_supplicant_i.h"
|
||||
#include "autoscan.h"
|
||||
|
||||
struct autoscan_exponential_data {
|
||||
struct wpa_supplicant *wpa_s;
|
||||
int base;
|
||||
int limit;
|
||||
int interval;
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
autoscan_exponential_get_params(struct autoscan_exponential_data *data,
|
||||
const char *params)
|
||||
{
|
||||
const char *pos;
|
||||
|
||||
if (params == NULL)
|
||||
return -1;
|
||||
|
||||
data->base = atoi(params);
|
||||
|
||||
pos = os_strchr(params, ':');
|
||||
if (pos == NULL)
|
||||
return -1;
|
||||
|
||||
pos++;
|
||||
data->limit = atoi(pos);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void * autoscan_exponential_init(struct wpa_supplicant *wpa_s,
|
||||
const char *params)
|
||||
{
|
||||
struct autoscan_exponential_data *data;
|
||||
|
||||
data = os_zalloc(sizeof(struct autoscan_exponential_data));
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
|
||||
if (autoscan_exponential_get_params(data, params) < 0) {
|
||||
os_free(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "autoscan exponential: base exponential is %d "
|
||||
"and limit is %d", data->base, data->limit);
|
||||
|
||||
data->wpa_s = wpa_s;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
static void autoscan_exponential_deinit(void *priv)
|
||||
{
|
||||
struct autoscan_exponential_data *data = priv;
|
||||
|
||||
os_free(data);
|
||||
}
|
||||
|
||||
|
||||
static int autoscan_exponential_notify_scan(void *priv,
|
||||
struct wpa_scan_results *scan_res)
|
||||
{
|
||||
struct autoscan_exponential_data *data = priv;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "autoscan exponential: scan result "
|
||||
"notification");
|
||||
|
||||
if (data->interval >= data->limit)
|
||||
return data->limit;
|
||||
|
||||
if (data->interval <= 0)
|
||||
data->interval = data->base;
|
||||
else {
|
||||
data->interval = data->interval * data->base;
|
||||
if (data->interval > data->limit)
|
||||
return data->limit;
|
||||
}
|
||||
|
||||
return data->interval;
|
||||
}
|
||||
|
||||
|
||||
const struct autoscan_ops autoscan_exponential_ops = {
|
||||
.name = "exponential",
|
||||
.init = autoscan_exponential_init,
|
||||
.deinit = autoscan_exponential_deinit,
|
||||
.notify_scan = autoscan_exponential_notify_scan,
|
||||
};
|
85
wpa_supplicant/autoscan_periodic.c
Normal file
85
wpa_supplicant/autoscan_periodic.c
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* WPA Supplicant - auto scan periodic module
|
||||
* Copyright (c) 2012, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "wpa_supplicant_i.h"
|
||||
#include "autoscan.h"
|
||||
|
||||
|
||||
struct autoscan_periodic_data {
|
||||
int periodic_interval;
|
||||
};
|
||||
|
||||
|
||||
static int autoscan_periodic_get_params(struct autoscan_periodic_data *data,
|
||||
const char *params)
|
||||
{
|
||||
int interval;
|
||||
|
||||
if (params == NULL)
|
||||
return -1;
|
||||
|
||||
interval = atoi(params);
|
||||
|
||||
if (interval < 0)
|
||||
return -1;
|
||||
|
||||
data->periodic_interval = interval;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void * autoscan_periodic_init(struct wpa_supplicant *wpa_s,
|
||||
const char *params)
|
||||
{
|
||||
struct autoscan_periodic_data *data;
|
||||
|
||||
data = os_zalloc(sizeof(struct autoscan_periodic_data));
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
|
||||
if (autoscan_periodic_get_params(data, params) < 0) {
|
||||
os_free(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "autoscan periodic: interval is %d",
|
||||
data->periodic_interval);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
static void autoscan_periodic_deinit(void *priv)
|
||||
{
|
||||
struct autoscan_periodic_data *data = priv;
|
||||
|
||||
os_free(data);
|
||||
}
|
||||
|
||||
|
||||
static int autoscan_periodic_notify_scan(void *priv,
|
||||
struct wpa_scan_results *scan_res)
|
||||
{
|
||||
struct autoscan_periodic_data *data = priv;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "autoscan periodic: scan result notification");
|
||||
|
||||
return data->periodic_interval;
|
||||
}
|
||||
|
||||
|
||||
const struct autoscan_ops autoscan_periodic_ops = {
|
||||
.name = "periodic",
|
||||
.init = autoscan_periodic_init,
|
||||
.deinit = autoscan_periodic_deinit,
|
||||
.notify_scan = autoscan_periodic_notify_scan,
|
||||
};
|
109
wpa_supplicant/bgscan.c
Normal file
109
wpa_supplicant/bgscan.c
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* WPA Supplicant - background scan and roaming interface
|
||||
* Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "wpa_supplicant_i.h"
|
||||
#include "config_ssid.h"
|
||||
#include "bgscan.h"
|
||||
|
||||
|
||||
static const struct bgscan_ops * bgscan_modules[] = {
|
||||
#ifdef CONFIG_BGSCAN_SIMPLE
|
||||
&bgscan_simple_ops,
|
||||
#endif /* CONFIG_BGSCAN_SIMPLE */
|
||||
#ifdef CONFIG_BGSCAN_LEARN
|
||||
&bgscan_learn_ops,
|
||||
#endif /* CONFIG_BGSCAN_LEARN */
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
int bgscan_init(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
|
||||
const char *name)
|
||||
{
|
||||
const char *params;
|
||||
size_t nlen;
|
||||
int i;
|
||||
const struct bgscan_ops *ops = NULL;
|
||||
|
||||
bgscan_deinit(wpa_s);
|
||||
|
||||
params = os_strchr(name, ':');
|
||||
if (params == NULL) {
|
||||
params = "";
|
||||
nlen = os_strlen(name);
|
||||
} else {
|
||||
nlen = params - name;
|
||||
params++;
|
||||
}
|
||||
|
||||
for (i = 0; bgscan_modules[i]; i++) {
|
||||
if (os_strncmp(name, bgscan_modules[i]->name, nlen) == 0) {
|
||||
ops = bgscan_modules[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ops == NULL) {
|
||||
wpa_printf(MSG_ERROR, "bgscan: Could not find module "
|
||||
"matching the parameter '%s'", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_s->bgscan_priv = ops->init(wpa_s, params, ssid);
|
||||
if (wpa_s->bgscan_priv == NULL)
|
||||
return -1;
|
||||
wpa_s->bgscan = ops;
|
||||
wpa_printf(MSG_DEBUG, "bgscan: Initialized module '%s' with "
|
||||
"parameters '%s'", ops->name, params);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void bgscan_deinit(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
if (wpa_s->bgscan && wpa_s->bgscan_priv) {
|
||||
wpa_printf(MSG_DEBUG, "bgscan: Deinitializing module '%s'",
|
||||
wpa_s->bgscan->name);
|
||||
wpa_s->bgscan->deinit(wpa_s->bgscan_priv);
|
||||
wpa_s->bgscan = NULL;
|
||||
wpa_s->bgscan_priv = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int bgscan_notify_scan(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_scan_results *scan_res)
|
||||
{
|
||||
if (wpa_s->bgscan && wpa_s->bgscan_priv)
|
||||
return wpa_s->bgscan->notify_scan(wpa_s->bgscan_priv,
|
||||
scan_res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void bgscan_notify_beacon_loss(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
if (wpa_s->bgscan && wpa_s->bgscan_priv)
|
||||
wpa_s->bgscan->notify_beacon_loss(wpa_s->bgscan_priv);
|
||||
}
|
||||
|
||||
|
||||
void bgscan_notify_signal_change(struct wpa_supplicant *wpa_s, int above,
|
||||
int current_signal, int current_noise,
|
||||
int current_txrate)
|
||||
{
|
||||
if (wpa_s->bgscan && wpa_s->bgscan_priv)
|
||||
wpa_s->bgscan->notify_signal_change(wpa_s->bgscan_priv, above,
|
||||
current_signal,
|
||||
current_noise,
|
||||
current_txrate);
|
||||
}
|
82
wpa_supplicant/bgscan.h
Normal file
82
wpa_supplicant/bgscan.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* WPA Supplicant - background scan and roaming interface
|
||||
* Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef BGSCAN_H
|
||||
#define BGSCAN_H
|
||||
|
||||
struct wpa_supplicant;
|
||||
struct wpa_ssid;
|
||||
|
||||
struct bgscan_ops {
|
||||
const char *name;
|
||||
|
||||
void * (*init)(struct wpa_supplicant *wpa_s, const char *params,
|
||||
const struct wpa_ssid *ssid);
|
||||
void (*deinit)(void *priv);
|
||||
|
||||
int (*notify_scan)(void *priv, struct wpa_scan_results *scan_res);
|
||||
void (*notify_beacon_loss)(void *priv);
|
||||
void (*notify_signal_change)(void *priv, int above,
|
||||
int current_signal,
|
||||
int current_noise,
|
||||
int current_txrate);
|
||||
};
|
||||
|
||||
#ifdef CONFIG_BGSCAN
|
||||
|
||||
int bgscan_init(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
|
||||
const char *name);
|
||||
void bgscan_deinit(struct wpa_supplicant *wpa_s);
|
||||
int bgscan_notify_scan(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_scan_results *scan_res);
|
||||
void bgscan_notify_beacon_loss(struct wpa_supplicant *wpa_s);
|
||||
void bgscan_notify_signal_change(struct wpa_supplicant *wpa_s, int above,
|
||||
int current_signal, int current_noise,
|
||||
int current_txrate);
|
||||
|
||||
/* Available bgscan modules */
|
||||
|
||||
#ifdef CONFIG_BGSCAN_SIMPLE
|
||||
extern const struct bgscan_ops bgscan_simple_ops;
|
||||
#endif /* CONFIG_BGSCAN_SIMPLE */
|
||||
#ifdef CONFIG_BGSCAN_LEARN
|
||||
extern const struct bgscan_ops bgscan_learn_ops;
|
||||
#endif /* CONFIG_BGSCAN_LEARN */
|
||||
|
||||
#else /* CONFIG_BGSCAN */
|
||||
|
||||
static inline int bgscan_init(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid, const char name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void bgscan_deinit(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int bgscan_notify_scan(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_scan_results *scan_res)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void bgscan_notify_beacon_loss(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void bgscan_notify_signal_change(struct wpa_supplicant *wpa_s,
|
||||
int above, int current_signal,
|
||||
int current_noise,
|
||||
int current_txrate)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BGSCAN */
|
||||
|
||||
#endif /* BGSCAN_H */
|
614
wpa_supplicant/bgscan_learn.c
Normal file
614
wpa_supplicant/bgscan_learn.c
Normal file
@ -0,0 +1,614 @@
|
||||
/*
|
||||
* WPA Supplicant - background scan and roaming module: learn
|
||||
* Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "eloop.h"
|
||||
#include "list.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "config_ssid.h"
|
||||
#include "wpa_supplicant_i.h"
|
||||
#include "driver_i.h"
|
||||
#include "scan.h"
|
||||
#include "bgscan.h"
|
||||
|
||||
struct bgscan_learn_bss {
|
||||
struct dl_list list;
|
||||
u8 bssid[ETH_ALEN];
|
||||
int freq;
|
||||
u8 *neigh; /* num_neigh * ETH_ALEN buffer */
|
||||
size_t num_neigh;
|
||||
};
|
||||
|
||||
struct bgscan_learn_data {
|
||||
struct wpa_supplicant *wpa_s;
|
||||
const struct wpa_ssid *ssid;
|
||||
int scan_interval;
|
||||
int signal_threshold;
|
||||
int short_interval; /* use if signal < threshold */
|
||||
int long_interval; /* use if signal > threshold */
|
||||
struct os_reltime last_bgscan;
|
||||
char *fname;
|
||||
struct dl_list bss;
|
||||
int *supp_freqs;
|
||||
int probe_idx;
|
||||
};
|
||||
|
||||
|
||||
static void bss_free(struct bgscan_learn_bss *bss)
|
||||
{
|
||||
os_free(bss->neigh);
|
||||
os_free(bss);
|
||||
}
|
||||
|
||||
|
||||
static int bssid_in_array(u8 *array, size_t array_len, const u8 *bssid)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (array == NULL || array_len == 0)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < array_len; i++) {
|
||||
if (os_memcmp(array + i * ETH_ALEN, bssid, ETH_ALEN) == 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void bgscan_learn_add_neighbor(struct bgscan_learn_bss *bss,
|
||||
const u8 *bssid)
|
||||
{
|
||||
u8 *n;
|
||||
|
||||
if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
|
||||
return;
|
||||
if (bssid_in_array(bss->neigh, bss->num_neigh, bssid))
|
||||
return;
|
||||
|
||||
n = os_realloc_array(bss->neigh, bss->num_neigh + 1, ETH_ALEN);
|
||||
if (n == NULL)
|
||||
return;
|
||||
|
||||
os_memcpy(n + bss->num_neigh * ETH_ALEN, bssid, ETH_ALEN);
|
||||
bss->neigh = n;
|
||||
bss->num_neigh++;
|
||||
}
|
||||
|
||||
|
||||
static struct bgscan_learn_bss * bgscan_learn_get_bss(
|
||||
struct bgscan_learn_data *data, const u8 *bssid)
|
||||
{
|
||||
struct bgscan_learn_bss *bss;
|
||||
|
||||
dl_list_for_each(bss, &data->bss, struct bgscan_learn_bss, list) {
|
||||
if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
|
||||
return bss;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int bgscan_learn_load(struct bgscan_learn_data *data)
|
||||
{
|
||||
FILE *f;
|
||||
char buf[128];
|
||||
struct bgscan_learn_bss *bss;
|
||||
|
||||
if (data->fname == NULL)
|
||||
return 0;
|
||||
|
||||
f = fopen(data->fname, "r");
|
||||
if (f == NULL)
|
||||
return 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "bgscan learn: Loading data from %s",
|
||||
data->fname);
|
||||
|
||||
if (fgets(buf, sizeof(buf), f) == NULL ||
|
||||
os_strncmp(buf, "wpa_supplicant-bgscan-learn\n", 28) != 0) {
|
||||
wpa_printf(MSG_INFO, "bgscan learn: Invalid data file %s",
|
||||
data->fname);
|
||||
fclose(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (fgets(buf, sizeof(buf), f)) {
|
||||
if (os_strncmp(buf, "BSS ", 4) == 0) {
|
||||
bss = os_zalloc(sizeof(*bss));
|
||||
if (!bss)
|
||||
continue;
|
||||
if (hwaddr_aton(buf + 4, bss->bssid) < 0) {
|
||||
bss_free(bss);
|
||||
continue;
|
||||
}
|
||||
bss->freq = atoi(buf + 4 + 18);
|
||||
dl_list_add(&data->bss, &bss->list);
|
||||
wpa_printf(MSG_DEBUG, "bgscan learn: Loaded BSS "
|
||||
"entry: " MACSTR " freq=%d",
|
||||
MAC2STR(bss->bssid), bss->freq);
|
||||
}
|
||||
|
||||
if (os_strncmp(buf, "NEIGHBOR ", 9) == 0) {
|
||||
u8 addr[ETH_ALEN];
|
||||
|
||||
if (hwaddr_aton(buf + 9, addr) < 0)
|
||||
continue;
|
||||
bss = bgscan_learn_get_bss(data, addr);
|
||||
if (bss == NULL)
|
||||
continue;
|
||||
if (hwaddr_aton(buf + 9 + 18, addr) < 0)
|
||||
continue;
|
||||
|
||||
bgscan_learn_add_neighbor(bss, addr);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void bgscan_learn_save(struct bgscan_learn_data *data)
|
||||
{
|
||||
FILE *f;
|
||||
struct bgscan_learn_bss *bss;
|
||||
|
||||
if (data->fname == NULL)
|
||||
return;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "bgscan learn: Saving data to %s",
|
||||
data->fname);
|
||||
|
||||
f = fopen(data->fname, "w");
|
||||
if (f == NULL)
|
||||
return;
|
||||
fprintf(f, "wpa_supplicant-bgscan-learn\n");
|
||||
|
||||
dl_list_for_each(bss, &data->bss, struct bgscan_learn_bss, list) {
|
||||
fprintf(f, "BSS " MACSTR " %d\n",
|
||||
MAC2STR(bss->bssid), bss->freq);
|
||||
}
|
||||
|
||||
dl_list_for_each(bss, &data->bss, struct bgscan_learn_bss, list) {
|
||||
size_t i;
|
||||
for (i = 0; i < bss->num_neigh; i++) {
|
||||
fprintf(f, "NEIGHBOR " MACSTR " " MACSTR "\n",
|
||||
MAC2STR(bss->bssid),
|
||||
MAC2STR(bss->neigh + i * ETH_ALEN));
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
|
||||
static int in_array(int *array, int val)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (array == NULL)
|
||||
return 0;
|
||||
|
||||
for (i = 0; array[i]; i++) {
|
||||
if (array[i] == val)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int * bgscan_learn_get_freqs(struct bgscan_learn_data *data,
|
||||
size_t *count)
|
||||
{
|
||||
struct bgscan_learn_bss *bss;
|
||||
int *freqs = NULL, *n;
|
||||
|
||||
*count = 0;
|
||||
|
||||
dl_list_for_each(bss, &data->bss, struct bgscan_learn_bss, list) {
|
||||
if (in_array(freqs, bss->freq))
|
||||
continue;
|
||||
n = os_realloc_array(freqs, *count + 2, sizeof(int));
|
||||
if (n == NULL)
|
||||
return freqs;
|
||||
freqs = n;
|
||||
freqs[*count] = bss->freq;
|
||||
(*count)++;
|
||||
freqs[*count] = 0;
|
||||
}
|
||||
|
||||
return freqs;
|
||||
}
|
||||
|
||||
|
||||
static int * bgscan_learn_get_probe_freq(struct bgscan_learn_data *data,
|
||||
int *freqs, size_t count)
|
||||
{
|
||||
int idx, *n;
|
||||
|
||||
if (data->supp_freqs == NULL)
|
||||
return freqs;
|
||||
|
||||
idx = data->probe_idx;
|
||||
do {
|
||||
if (!in_array(freqs, data->supp_freqs[idx])) {
|
||||
wpa_printf(MSG_DEBUG, "bgscan learn: Probe new freq "
|
||||
"%u", data->supp_freqs[idx]);
|
||||
data->probe_idx = idx + 1;
|
||||
if (data->supp_freqs[data->probe_idx] == 0)
|
||||
data->probe_idx = 0;
|
||||
n = os_realloc_array(freqs, count + 2, sizeof(int));
|
||||
if (n == NULL)
|
||||
return freqs;
|
||||
freqs = n;
|
||||
freqs[count] = data->supp_freqs[idx];
|
||||
count++;
|
||||
freqs[count] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
idx++;
|
||||
if (data->supp_freqs[idx] == 0)
|
||||
idx = 0;
|
||||
} while (idx != data->probe_idx);
|
||||
|
||||
return freqs;
|
||||
}
|
||||
|
||||
|
||||
static void bgscan_learn_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct bgscan_learn_data *data = eloop_ctx;
|
||||
struct wpa_supplicant *wpa_s = data->wpa_s;
|
||||
struct wpa_driver_scan_params params;
|
||||
int *freqs = NULL;
|
||||
size_t count, i;
|
||||
char msg[100], *pos;
|
||||
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
params.num_ssids = 1;
|
||||
params.ssids[0].ssid = data->ssid->ssid;
|
||||
params.ssids[0].ssid_len = data->ssid->ssid_len;
|
||||
if (data->ssid->scan_freq)
|
||||
params.freqs = data->ssid->scan_freq;
|
||||
else {
|
||||
freqs = bgscan_learn_get_freqs(data, &count);
|
||||
wpa_printf(MSG_DEBUG, "bgscan learn: BSSes in this ESS have "
|
||||
"been seen on %u channels", (unsigned int) count);
|
||||
freqs = bgscan_learn_get_probe_freq(data, freqs, count);
|
||||
|
||||
msg[0] = '\0';
|
||||
pos = msg;
|
||||
for (i = 0; freqs && freqs[i]; i++) {
|
||||
int ret;
|
||||
ret = os_snprintf(pos, msg + sizeof(msg) - pos, " %d",
|
||||
freqs[i]);
|
||||
if (os_snprintf_error(msg + sizeof(msg) - pos, ret))
|
||||
break;
|
||||
pos += ret;
|
||||
}
|
||||
pos[0] = '\0';
|
||||
wpa_printf(MSG_DEBUG, "bgscan learn: Scanning frequencies:%s",
|
||||
msg);
|
||||
params.freqs = freqs;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "bgscan learn: Request a background scan");
|
||||
if (wpa_supplicant_trigger_scan(wpa_s, ¶ms)) {
|
||||
wpa_printf(MSG_DEBUG, "bgscan learn: Failed to trigger scan");
|
||||
eloop_register_timeout(data->scan_interval, 0,
|
||||
bgscan_learn_timeout, data, NULL);
|
||||
} else
|
||||
os_get_reltime(&data->last_bgscan);
|
||||
os_free(freqs);
|
||||
}
|
||||
|
||||
|
||||
static int bgscan_learn_get_params(struct bgscan_learn_data *data,
|
||||
const char *params)
|
||||
{
|
||||
const char *pos;
|
||||
|
||||
data->short_interval = atoi(params);
|
||||
|
||||
pos = os_strchr(params, ':');
|
||||
if (pos == NULL)
|
||||
return 0;
|
||||
pos++;
|
||||
data->signal_threshold = atoi(pos);
|
||||
pos = os_strchr(pos, ':');
|
||||
if (pos == NULL) {
|
||||
wpa_printf(MSG_ERROR, "bgscan learn: Missing scan interval "
|
||||
"for high signal");
|
||||
return -1;
|
||||
}
|
||||
pos++;
|
||||
data->long_interval = atoi(pos);
|
||||
pos = os_strchr(pos, ':');
|
||||
if (pos) {
|
||||
pos++;
|
||||
data->fname = os_strdup(pos);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int * bgscan_learn_get_supp_freqs(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
struct hostapd_hw_modes *modes;
|
||||
int i, j, *freqs = NULL, *n;
|
||||
size_t count = 0;
|
||||
|
||||
modes = wpa_s->hw.modes;
|
||||
if (modes == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < wpa_s->hw.num_modes; i++) {
|
||||
for (j = 0; j < modes[i].num_channels; j++) {
|
||||
if (modes[i].channels[j].flag & HOSTAPD_CHAN_DISABLED)
|
||||
continue;
|
||||
/* some hw modes (e.g. 11b & 11g) contain same freqs */
|
||||
if (in_array(freqs, modes[i].channels[j].freq))
|
||||
continue;
|
||||
n = os_realloc_array(freqs, count + 2, sizeof(int));
|
||||
if (n == NULL)
|
||||
continue;
|
||||
|
||||
freqs = n;
|
||||
freqs[count] = modes[i].channels[j].freq;
|
||||
count++;
|
||||
freqs[count] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return freqs;
|
||||
}
|
||||
|
||||
|
||||
static void * bgscan_learn_init(struct wpa_supplicant *wpa_s,
|
||||
const char *params,
|
||||
const struct wpa_ssid *ssid)
|
||||
{
|
||||
struct bgscan_learn_data *data;
|
||||
|
||||
data = os_zalloc(sizeof(*data));
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
dl_list_init(&data->bss);
|
||||
data->wpa_s = wpa_s;
|
||||
data->ssid = ssid;
|
||||
if (bgscan_learn_get_params(data, params) < 0) {
|
||||
os_free(data->fname);
|
||||
os_free(data);
|
||||
return NULL;
|
||||
}
|
||||
if (data->short_interval <= 0)
|
||||
data->short_interval = 30;
|
||||
if (data->long_interval <= 0)
|
||||
data->long_interval = 30;
|
||||
|
||||
if (bgscan_learn_load(data) < 0) {
|
||||
os_free(data->fname);
|
||||
os_free(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "bgscan learn: Signal strength threshold %d "
|
||||
"Short bgscan interval %d Long bgscan interval %d",
|
||||
data->signal_threshold, data->short_interval,
|
||||
data->long_interval);
|
||||
|
||||
if (data->signal_threshold &&
|
||||
wpa_drv_signal_monitor(wpa_s, data->signal_threshold, 4) < 0) {
|
||||
wpa_printf(MSG_ERROR, "bgscan learn: Failed to enable "
|
||||
"signal strength monitoring");
|
||||
}
|
||||
|
||||
data->supp_freqs = bgscan_learn_get_supp_freqs(wpa_s);
|
||||
data->scan_interval = data->short_interval;
|
||||
if (data->signal_threshold) {
|
||||
/* Poll for signal info to set initial scan interval */
|
||||
struct wpa_signal_info siginfo;
|
||||
if (wpa_drv_signal_poll(wpa_s, &siginfo) == 0 &&
|
||||
siginfo.current_signal >= data->signal_threshold)
|
||||
data->scan_interval = data->long_interval;
|
||||
}
|
||||
|
||||
eloop_register_timeout(data->scan_interval, 0, bgscan_learn_timeout,
|
||||
data, NULL);
|
||||
|
||||
/*
|
||||
* This function is called immediately after an association, so it is
|
||||
* reasonable to assume that a scan was completed recently. This makes
|
||||
* us skip an immediate new scan in cases where the current signal
|
||||
* level is below the bgscan threshold.
|
||||
*/
|
||||
os_get_reltime(&data->last_bgscan);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
static void bgscan_learn_deinit(void *priv)
|
||||
{
|
||||
struct bgscan_learn_data *data = priv;
|
||||
struct bgscan_learn_bss *bss, *n;
|
||||
|
||||
bgscan_learn_save(data);
|
||||
eloop_cancel_timeout(bgscan_learn_timeout, data, NULL);
|
||||
if (data->signal_threshold)
|
||||
wpa_drv_signal_monitor(data->wpa_s, 0, 0);
|
||||
os_free(data->fname);
|
||||
dl_list_for_each_safe(bss, n, &data->bss, struct bgscan_learn_bss,
|
||||
list) {
|
||||
dl_list_del(&bss->list);
|
||||
bss_free(bss);
|
||||
}
|
||||
os_free(data->supp_freqs);
|
||||
os_free(data);
|
||||
}
|
||||
|
||||
|
||||
static int bgscan_learn_bss_match(struct bgscan_learn_data *data,
|
||||
struct wpa_scan_res *bss)
|
||||
{
|
||||
const u8 *ie;
|
||||
|
||||
ie = wpa_scan_get_ie(bss, WLAN_EID_SSID);
|
||||
if (ie == NULL)
|
||||
return 0;
|
||||
|
||||
if (data->ssid->ssid_len != ie[1] ||
|
||||
os_memcmp(data->ssid->ssid, ie + 2, ie[1]) != 0)
|
||||
return 0; /* SSID mismatch */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int bgscan_learn_notify_scan(void *priv,
|
||||
struct wpa_scan_results *scan_res)
|
||||
{
|
||||
struct bgscan_learn_data *data = priv;
|
||||
size_t i, j;
|
||||
#define MAX_BSS 50
|
||||
u8 bssid[MAX_BSS * ETH_ALEN];
|
||||
size_t num_bssid = 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "bgscan learn: scan result notification");
|
||||
|
||||
eloop_cancel_timeout(bgscan_learn_timeout, data, NULL);
|
||||
eloop_register_timeout(data->scan_interval, 0, bgscan_learn_timeout,
|
||||
data, NULL);
|
||||
|
||||
for (i = 0; i < scan_res->num; i++) {
|
||||
struct wpa_scan_res *res = scan_res->res[i];
|
||||
if (!bgscan_learn_bss_match(data, res))
|
||||
continue;
|
||||
|
||||
if (num_bssid < MAX_BSS) {
|
||||
os_memcpy(bssid + num_bssid * ETH_ALEN, res->bssid,
|
||||
ETH_ALEN);
|
||||
num_bssid++;
|
||||
}
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "bgscan learn: %u matching BSSes in scan "
|
||||
"results", (unsigned int) num_bssid);
|
||||
|
||||
for (i = 0; i < scan_res->num; i++) {
|
||||
struct wpa_scan_res *res = scan_res->res[i];
|
||||
struct bgscan_learn_bss *bss;
|
||||
|
||||
if (!bgscan_learn_bss_match(data, res))
|
||||
continue;
|
||||
|
||||
bss = bgscan_learn_get_bss(data, res->bssid);
|
||||
if (bss && bss->freq != res->freq) {
|
||||
wpa_printf(MSG_DEBUG, "bgscan learn: Update BSS "
|
||||
MACSTR " freq %d -> %d",
|
||||
MAC2STR(res->bssid), bss->freq, res->freq);
|
||||
bss->freq = res->freq;
|
||||
} else if (!bss) {
|
||||
wpa_printf(MSG_DEBUG, "bgscan learn: Add BSS " MACSTR
|
||||
" freq=%d", MAC2STR(res->bssid), res->freq);
|
||||
bss = os_zalloc(sizeof(*bss));
|
||||
if (!bss)
|
||||
continue;
|
||||
os_memcpy(bss->bssid, res->bssid, ETH_ALEN);
|
||||
bss->freq = res->freq;
|
||||
dl_list_add(&data->bss, &bss->list);
|
||||
}
|
||||
|
||||
for (j = 0; j < num_bssid; j++) {
|
||||
u8 *addr = bssid + j * ETH_ALEN;
|
||||
bgscan_learn_add_neighbor(bss, addr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A more advanced bgscan could process scan results internally, select
|
||||
* the BSS and request roam if needed. This sample uses the existing
|
||||
* BSS/ESS selection routine. Change this to return 1 if selection is
|
||||
* done inside the bgscan module.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void bgscan_learn_notify_beacon_loss(void *priv)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "bgscan learn: beacon loss");
|
||||
/* TODO: speed up background scanning */
|
||||
}
|
||||
|
||||
|
||||
static void bgscan_learn_notify_signal_change(void *priv, int above,
|
||||
int current_signal,
|
||||
int current_noise,
|
||||
int current_txrate)
|
||||
{
|
||||
struct bgscan_learn_data *data = priv;
|
||||
int scan = 0;
|
||||
struct os_reltime now;
|
||||
|
||||
if (data->short_interval == data->long_interval ||
|
||||
data->signal_threshold == 0)
|
||||
return;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "bgscan learn: signal level changed "
|
||||
"(above=%d current_signal=%d current_noise=%d "
|
||||
"current_txrate=%d)", above, current_signal,
|
||||
current_noise, current_txrate);
|
||||
if (data->scan_interval == data->long_interval && !above) {
|
||||
wpa_printf(MSG_DEBUG, "bgscan learn: Start using short bgscan "
|
||||
"interval");
|
||||
data->scan_interval = data->short_interval;
|
||||
os_get_reltime(&now);
|
||||
if (now.sec > data->last_bgscan.sec + 1)
|
||||
scan = 1;
|
||||
} else if (data->scan_interval == data->short_interval && above) {
|
||||
wpa_printf(MSG_DEBUG, "bgscan learn: Start using long bgscan "
|
||||
"interval");
|
||||
data->scan_interval = data->long_interval;
|
||||
eloop_cancel_timeout(bgscan_learn_timeout, data, NULL);
|
||||
eloop_register_timeout(data->scan_interval, 0,
|
||||
bgscan_learn_timeout, data, NULL);
|
||||
} else if (!above) {
|
||||
/*
|
||||
* Signal dropped further 4 dB. Request a new scan if we have
|
||||
* not yet scanned in a while.
|
||||
*/
|
||||
os_get_reltime(&now);
|
||||
if (now.sec > data->last_bgscan.sec + 10)
|
||||
scan = 1;
|
||||
}
|
||||
|
||||
if (scan) {
|
||||
wpa_printf(MSG_DEBUG, "bgscan learn: Trigger immediate scan");
|
||||
eloop_cancel_timeout(bgscan_learn_timeout, data, NULL);
|
||||
eloop_register_timeout(0, 0, bgscan_learn_timeout, data, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const struct bgscan_ops bgscan_learn_ops = {
|
||||
.name = "learn",
|
||||
.init = bgscan_learn_init,
|
||||
.deinit = bgscan_learn_deinit,
|
||||
.notify_scan = bgscan_learn_notify_scan,
|
||||
.notify_beacon_loss = bgscan_learn_notify_beacon_loss,
|
||||
.notify_signal_change = bgscan_learn_notify_signal_change,
|
||||
};
|
275
wpa_supplicant/bgscan_simple.c
Normal file
275
wpa_supplicant/bgscan_simple.c
Normal file
@ -0,0 +1,275 @@
|
||||
/*
|
||||
* WPA Supplicant - background scan and roaming module: simple
|
||||
* Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "eloop.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "config_ssid.h"
|
||||
#include "wpa_supplicant_i.h"
|
||||
#include "driver_i.h"
|
||||
#include "scan.h"
|
||||
#include "bgscan.h"
|
||||
|
||||
struct bgscan_simple_data {
|
||||
struct wpa_supplicant *wpa_s;
|
||||
const struct wpa_ssid *ssid;
|
||||
int scan_interval;
|
||||
int signal_threshold;
|
||||
int short_scan_count; /* counter for scans using short scan interval */
|
||||
int max_short_scans; /* maximum times we short-scan before back-off */
|
||||
int short_interval; /* use if signal < threshold */
|
||||
int long_interval; /* use if signal > threshold */
|
||||
struct os_reltime last_bgscan;
|
||||
};
|
||||
|
||||
|
||||
static void bgscan_simple_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct bgscan_simple_data *data = eloop_ctx;
|
||||
struct wpa_supplicant *wpa_s = data->wpa_s;
|
||||
struct wpa_driver_scan_params params;
|
||||
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
params.num_ssids = 1;
|
||||
params.ssids[0].ssid = data->ssid->ssid;
|
||||
params.ssids[0].ssid_len = data->ssid->ssid_len;
|
||||
params.freqs = data->ssid->scan_freq;
|
||||
|
||||
/*
|
||||
* A more advanced bgscan module would learn about most like channels
|
||||
* over time and request scans only for some channels (probing others
|
||||
* every now and then) to reduce effect on the data connection.
|
||||
*/
|
||||
|
||||
wpa_printf(MSG_DEBUG, "bgscan simple: Request a background scan");
|
||||
if (wpa_supplicant_trigger_scan(wpa_s, ¶ms)) {
|
||||
wpa_printf(MSG_DEBUG, "bgscan simple: Failed to trigger scan");
|
||||
eloop_register_timeout(data->scan_interval, 0,
|
||||
bgscan_simple_timeout, data, NULL);
|
||||
} else {
|
||||
if (data->scan_interval == data->short_interval) {
|
||||
data->short_scan_count++;
|
||||
if (data->short_scan_count >= data->max_short_scans) {
|
||||
data->scan_interval = data->long_interval;
|
||||
wpa_printf(MSG_DEBUG, "bgscan simple: Backing "
|
||||
"off to long scan interval");
|
||||
}
|
||||
} else if (data->short_scan_count > 0) {
|
||||
/*
|
||||
* If we lasted a long scan interval without any
|
||||
* CQM triggers, decrease the short-scan count,
|
||||
* which allows 1 more short-scan interval to
|
||||
* occur in the future when CQM triggers.
|
||||
*/
|
||||
data->short_scan_count--;
|
||||
}
|
||||
os_get_reltime(&data->last_bgscan);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int bgscan_simple_get_params(struct bgscan_simple_data *data,
|
||||
const char *params)
|
||||
{
|
||||
const char *pos;
|
||||
|
||||
data->short_interval = atoi(params);
|
||||
|
||||
pos = os_strchr(params, ':');
|
||||
if (pos == NULL)
|
||||
return 0;
|
||||
pos++;
|
||||
data->signal_threshold = atoi(pos);
|
||||
pos = os_strchr(pos, ':');
|
||||
if (pos == NULL) {
|
||||
wpa_printf(MSG_ERROR, "bgscan simple: Missing scan interval "
|
||||
"for high signal");
|
||||
return -1;
|
||||
}
|
||||
pos++;
|
||||
data->long_interval = atoi(pos);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void * bgscan_simple_init(struct wpa_supplicant *wpa_s,
|
||||
const char *params,
|
||||
const struct wpa_ssid *ssid)
|
||||
{
|
||||
struct bgscan_simple_data *data;
|
||||
|
||||
data = os_zalloc(sizeof(*data));
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
data->wpa_s = wpa_s;
|
||||
data->ssid = ssid;
|
||||
if (bgscan_simple_get_params(data, params) < 0) {
|
||||
os_free(data);
|
||||
return NULL;
|
||||
}
|
||||
if (data->short_interval <= 0)
|
||||
data->short_interval = 30;
|
||||
if (data->long_interval <= 0)
|
||||
data->long_interval = 30;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "bgscan simple: Signal strength threshold %d "
|
||||
"Short bgscan interval %d Long bgscan interval %d",
|
||||
data->signal_threshold, data->short_interval,
|
||||
data->long_interval);
|
||||
|
||||
if (data->signal_threshold &&
|
||||
wpa_drv_signal_monitor(wpa_s, data->signal_threshold, 4) < 0) {
|
||||
wpa_printf(MSG_ERROR, "bgscan simple: Failed to enable "
|
||||
"signal strength monitoring");
|
||||
}
|
||||
|
||||
data->scan_interval = data->short_interval;
|
||||
data->max_short_scans = data->long_interval / data->short_interval + 1;
|
||||
if (data->signal_threshold) {
|
||||
/* Poll for signal info to set initial scan interval */
|
||||
struct wpa_signal_info siginfo;
|
||||
if (wpa_drv_signal_poll(wpa_s, &siginfo) == 0 &&
|
||||
siginfo.current_signal >= data->signal_threshold)
|
||||
data->scan_interval = data->long_interval;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "bgscan simple: Init scan interval: %d",
|
||||
data->scan_interval);
|
||||
eloop_register_timeout(data->scan_interval, 0, bgscan_simple_timeout,
|
||||
data, NULL);
|
||||
|
||||
/*
|
||||
* This function is called immediately after an association, so it is
|
||||
* reasonable to assume that a scan was completed recently. This makes
|
||||
* us skip an immediate new scan in cases where the current signal
|
||||
* level is below the bgscan threshold.
|
||||
*/
|
||||
os_get_reltime(&data->last_bgscan);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
static void bgscan_simple_deinit(void *priv)
|
||||
{
|
||||
struct bgscan_simple_data *data = priv;
|
||||
eloop_cancel_timeout(bgscan_simple_timeout, data, NULL);
|
||||
if (data->signal_threshold)
|
||||
wpa_drv_signal_monitor(data->wpa_s, 0, 0);
|
||||
os_free(data);
|
||||
}
|
||||
|
||||
|
||||
static int bgscan_simple_notify_scan(void *priv,
|
||||
struct wpa_scan_results *scan_res)
|
||||
{
|
||||
struct bgscan_simple_data *data = priv;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "bgscan simple: scan result notification");
|
||||
|
||||
eloop_cancel_timeout(bgscan_simple_timeout, data, NULL);
|
||||
eloop_register_timeout(data->scan_interval, 0, bgscan_simple_timeout,
|
||||
data, NULL);
|
||||
|
||||
/*
|
||||
* A more advanced bgscan could process scan results internally, select
|
||||
* the BSS and request roam if needed. This sample uses the existing
|
||||
* BSS/ESS selection routine. Change this to return 1 if selection is
|
||||
* done inside the bgscan module.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void bgscan_simple_notify_beacon_loss(void *priv)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "bgscan simple: beacon loss");
|
||||
/* TODO: speed up background scanning */
|
||||
}
|
||||
|
||||
|
||||
static void bgscan_simple_notify_signal_change(void *priv, int above,
|
||||
int current_signal,
|
||||
int current_noise,
|
||||
int current_txrate)
|
||||
{
|
||||
struct bgscan_simple_data *data = priv;
|
||||
int scan = 0;
|
||||
struct os_reltime now;
|
||||
|
||||
if (data->short_interval == data->long_interval ||
|
||||
data->signal_threshold == 0)
|
||||
return;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "bgscan simple: signal level changed "
|
||||
"(above=%d current_signal=%d current_noise=%d "
|
||||
"current_txrate=%d))", above, current_signal,
|
||||
current_noise, current_txrate);
|
||||
if (data->scan_interval == data->long_interval && !above) {
|
||||
wpa_printf(MSG_DEBUG, "bgscan simple: Start using short "
|
||||
"bgscan interval");
|
||||
data->scan_interval = data->short_interval;
|
||||
os_get_reltime(&now);
|
||||
if (now.sec > data->last_bgscan.sec + 1 &&
|
||||
data->short_scan_count <= data->max_short_scans)
|
||||
/*
|
||||
* If we haven't just previously (<1 second ago)
|
||||
* performed a scan, and we haven't depleted our
|
||||
* budget for short-scans, perform a scan
|
||||
* immediately.
|
||||
*/
|
||||
scan = 1;
|
||||
else if (data->last_bgscan.sec + data->long_interval >
|
||||
now.sec + data->scan_interval) {
|
||||
/*
|
||||
* Restart scan interval timer if currently scheduled
|
||||
* scan is too far in the future.
|
||||
*/
|
||||
eloop_cancel_timeout(bgscan_simple_timeout, data,
|
||||
NULL);
|
||||
eloop_register_timeout(data->scan_interval, 0,
|
||||
bgscan_simple_timeout, data,
|
||||
NULL);
|
||||
}
|
||||
} else if (data->scan_interval == data->short_interval && above) {
|
||||
wpa_printf(MSG_DEBUG, "bgscan simple: Start using long bgscan "
|
||||
"interval");
|
||||
data->scan_interval = data->long_interval;
|
||||
eloop_cancel_timeout(bgscan_simple_timeout, data, NULL);
|
||||
eloop_register_timeout(data->scan_interval, 0,
|
||||
bgscan_simple_timeout, data, NULL);
|
||||
} else if (!above) {
|
||||
/*
|
||||
* Signal dropped further 4 dB. Request a new scan if we have
|
||||
* not yet scanned in a while.
|
||||
*/
|
||||
os_get_reltime(&now);
|
||||
if (now.sec > data->last_bgscan.sec + 10)
|
||||
scan = 1;
|
||||
}
|
||||
|
||||
if (scan) {
|
||||
wpa_printf(MSG_DEBUG, "bgscan simple: Trigger immediate scan");
|
||||
eloop_cancel_timeout(bgscan_simple_timeout, data, NULL);
|
||||
eloop_register_timeout(0, 0, bgscan_simple_timeout, data,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const struct bgscan_ops bgscan_simple_ops = {
|
||||
.name = "simple",
|
||||
.init = bgscan_simple_init,
|
||||
.deinit = bgscan_simple_deinit,
|
||||
.notify_scan = bgscan_simple_notify_scan,
|
||||
.notify_beacon_loss = bgscan_simple_notify_beacon_loss,
|
||||
.notify_signal_change = bgscan_simple_notify_signal_change,
|
||||
};
|
9
wpa_supplicant/binder/.clang-format
Normal file
9
wpa_supplicant/binder/.clang-format
Normal file
@ -0,0 +1,9 @@
|
||||
BasedOnStyle: LLVM
|
||||
IndentWidth: 8
|
||||
UseTab: Always
|
||||
BreakBeforeBraces: Mozilla
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
IndentCaseLabels: false
|
||||
AccessModifierOffset: -8
|
||||
AlignAfterOpenBracket: AlwaysBreak
|
||||
SortIncludes: false
|
104
wpa_supplicant/binder/binder.cpp
Normal file
104
wpa_supplicant/binder/binder.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* binder interface for wpa_supplicant daemon
|
||||
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include <binder/IPCThreadState.h>
|
||||
#include <binder/IServiceManager.h>
|
||||
#include <binder/ProcessState.h>
|
||||
|
||||
#include "binder_manager.h"
|
||||
|
||||
extern "C" {
|
||||
#include "binder.h"
|
||||
#include "binder_i.h"
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "utils/includes.h"
|
||||
}
|
||||
|
||||
void wpas_binder_sock_handler(int sock, void *eloop_ctx, void *sock_ctx)
|
||||
{
|
||||
struct wpa_global *global = (wpa_global *)eloop_ctx;
|
||||
struct wpas_binder_priv *priv = (wpas_binder_priv *)sock_ctx;
|
||||
|
||||
wpa_printf(
|
||||
MSG_DEBUG, "Processing binder events on FD %d", priv->binder_fd);
|
||||
android::IPCThreadState::self()->handlePolledCommands();
|
||||
}
|
||||
|
||||
struct wpas_binder_priv *wpas_binder_init(struct wpa_global *global)
|
||||
{
|
||||
struct wpas_binder_priv *priv;
|
||||
wpa_supplicant_binder::BinderManager *binder_manager;
|
||||
|
||||
priv = (wpas_binder_priv *)os_zalloc(sizeof(*priv));
|
||||
if (!priv)
|
||||
return NULL;
|
||||
priv->global = global;
|
||||
|
||||
android::ProcessState::self()->setThreadPoolMaxThreadCount(0);
|
||||
android::IPCThreadState::self()->disableBackgroundScheduling(true);
|
||||
android::IPCThreadState::self()->setupPolling(&priv->binder_fd);
|
||||
wpa_printf(MSG_INFO, "Process binder events on FD %d", priv->binder_fd);
|
||||
if (priv->binder_fd < 0)
|
||||
goto err;
|
||||
/* Look for read events from the binder socket in the eloop. */
|
||||
if (eloop_register_read_sock(
|
||||
priv->binder_fd, wpas_binder_sock_handler, global, priv) < 0)
|
||||
goto err;
|
||||
|
||||
binder_manager = wpa_supplicant_binder::BinderManager::getInstance();
|
||||
if (!binder_manager)
|
||||
goto err;
|
||||
binder_manager->registerBinderService(global);
|
||||
/* We may not need to store this binder manager reference in the
|
||||
* global data strucure because we've made it a singleton class. */
|
||||
priv->binder_manager = (void *)binder_manager;
|
||||
|
||||
return priv;
|
||||
|
||||
err:
|
||||
wpas_binder_deinit(priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void wpas_binder_deinit(struct wpas_binder_priv *priv)
|
||||
{
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
wpa_supplicant_binder::BinderManager::destroyInstance();
|
||||
eloop_unregister_read_sock(priv->binder_fd);
|
||||
android::IPCThreadState::shutdown();
|
||||
}
|
||||
|
||||
int wpas_binder_register_interface(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
if (!wpa_s->global->binder)
|
||||
return 1;
|
||||
|
||||
wpa_supplicant_binder::BinderManager *binder_manager =
|
||||
wpa_supplicant_binder::BinderManager::getInstance();
|
||||
if (!binder_manager)
|
||||
return 1;
|
||||
|
||||
return binder_manager->registerInterface(wpa_s);
|
||||
}
|
||||
|
||||
int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
if (!wpa_s->global->binder)
|
||||
return 1;
|
||||
|
||||
wpa_supplicant_binder::BinderManager *binder_manager =
|
||||
wpa_supplicant_binder::BinderManager::getInstance();
|
||||
if (!binder_manager)
|
||||
return 1;
|
||||
|
||||
return binder_manager->unregisterInterface(wpa_s);
|
||||
}
|
46
wpa_supplicant/binder/binder.h
Normal file
46
wpa_supplicant/binder/binder.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* binder interface for wpa_supplicant daemon
|
||||
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPA_SUPPLICANT_BINDER_BINDER_H
|
||||
#define WPA_SUPPLICANT_BINDER_BINDER_H
|
||||
|
||||
#ifdef _cplusplus
|
||||
extern "C" {
|
||||
#endif /* _cplusplus */
|
||||
|
||||
/**
|
||||
* This is the binder RPC interface entry point to the wpa_supplicant core.
|
||||
* This initializes the binder driver & BinderManager instance and then forwards
|
||||
* all the notifications from the supplicant core to the BinderManager.
|
||||
*/
|
||||
struct wpas_binder_priv;
|
||||
struct wpa_global;
|
||||
|
||||
struct wpas_binder_priv *wpas_binder_init(struct wpa_global *global);
|
||||
void wpas_binder_deinit(struct wpas_binder_priv *priv);
|
||||
|
||||
#ifdef CONFIG_CTRL_IFACE_BINDER
|
||||
int wpas_binder_register_interface(struct wpa_supplicant *wpa_s);
|
||||
int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s);
|
||||
#else /* CONFIG_CTRL_IFACE_BINDER */
|
||||
static inline int wpas_binder_register_interface(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_CTRL_IFACE_BINDER */
|
||||
|
||||
#ifdef _cplusplus
|
||||
}
|
||||
#endif /* _cplusplus */
|
||||
|
||||
#endif /* WPA_SUPPLICANT_BINDER_BINDER_H */
|
18
wpa_supplicant/binder/binder_constants.cpp
Normal file
18
wpa_supplicant/binder/binder_constants.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* binder interface for wpa_supplicant daemon
|
||||
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "binder_constants.h"
|
||||
|
||||
namespace wpa_supplicant_binder {
|
||||
namespace binder_constants {
|
||||
|
||||
const char kServiceName[] = "wpa_supplicant";
|
||||
|
||||
} /* namespace binder_constants */
|
||||
} /* namespace wpa_supplicant_binder */
|
21
wpa_supplicant/binder/binder_constants.h
Normal file
21
wpa_supplicant/binder/binder_constants.h
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* binder interface for wpa_supplicant daemon
|
||||
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPA_SUPPLICANT_BINDER_BINDER_CONSTANTS_H
|
||||
#define WPA_SUPPLICANT_BINDER_BINDER_CONSTANTS_H
|
||||
|
||||
namespace wpa_supplicant_binder {
|
||||
namespace binder_constants {
|
||||
|
||||
extern const char kServiceName[];
|
||||
|
||||
} /* namespace binder_constants */
|
||||
} /* namespace wpa_supplicant_binder */
|
||||
|
||||
#endif /* WPA_SUPPLICANT_BINDER_BINDER_CONSTANTS_H */
|
28
wpa_supplicant/binder/binder_i.h
Normal file
28
wpa_supplicant/binder/binder_i.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* binder interface for wpa_supplicant daemon
|
||||
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef BINDER_I_H
|
||||
#define BINDER_I_H
|
||||
|
||||
#ifdef _cplusplus
|
||||
extern "C" {
|
||||
#endif // _cplusplus
|
||||
|
||||
struct wpas_binder_priv
|
||||
{
|
||||
int binder_fd;
|
||||
struct wpa_global *global;
|
||||
void *binder_manager;
|
||||
};
|
||||
|
||||
#ifdef _cplusplus
|
||||
}
|
||||
#endif /* _cplusplus */
|
||||
|
||||
#endif /* BINDER_I_H */
|
100
wpa_supplicant/binder/binder_manager.cpp
Normal file
100
wpa_supplicant/binder/binder_manager.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* binder interface for wpa_supplicant daemon
|
||||
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include <binder/IServiceManager.h>
|
||||
|
||||
#include "binder_constants.h"
|
||||
#include "binder_manager.h"
|
||||
|
||||
extern "C" {
|
||||
#include "utils/common.h"
|
||||
#include "utils/includes.h"
|
||||
}
|
||||
|
||||
namespace wpa_supplicant_binder {
|
||||
|
||||
BinderManager *BinderManager::instance_ = NULL;
|
||||
|
||||
BinderManager *BinderManager::getInstance()
|
||||
{
|
||||
if (!instance_)
|
||||
instance_ = new BinderManager();
|
||||
return instance_;
|
||||
}
|
||||
|
||||
void BinderManager::destroyInstance()
|
||||
{
|
||||
if (instance_)
|
||||
delete instance_;
|
||||
instance_ = NULL;
|
||||
}
|
||||
|
||||
int BinderManager::registerBinderService(struct wpa_global *global)
|
||||
{
|
||||
/* Create the main binder service object and register with
|
||||
* system service manager. */
|
||||
supplicant_object_ = new Supplicant(global);
|
||||
android::String16 service_name(binder_constants::kServiceName);
|
||||
android::defaultServiceManager()->addService(
|
||||
service_name, android::IInterface::asBinder(supplicant_object_));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BinderManager::registerInterface(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
if (!wpa_s)
|
||||
return 1;
|
||||
|
||||
/* Using the corresponding wpa_supplicant pointer as key to our
|
||||
* object map. */
|
||||
const void *iface_key = wpa_s;
|
||||
|
||||
/* Return failure if we already have an object for that iface_key. */
|
||||
if (iface_object_map_.find(iface_key) != iface_object_map_.end())
|
||||
return 1;
|
||||
|
||||
iface_object_map_[iface_key] = new Iface(wpa_s);
|
||||
if (!iface_object_map_[iface_key].get())
|
||||
return 1;
|
||||
|
||||
wpa_s->binder_object_key = iface_key;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BinderManager::unregisterInterface(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
if (!wpa_s || !wpa_s->binder_object_key)
|
||||
return 1;
|
||||
|
||||
const void *iface_key = wpa_s;
|
||||
if (iface_object_map_.find(iface_key) == iface_object_map_.end())
|
||||
return 1;
|
||||
|
||||
/* Delete the corresponding iface object from our map. */
|
||||
iface_object_map_.erase(iface_key);
|
||||
wpa_s->binder_object_key = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BinderManager::getIfaceBinderObjectByKey(
|
||||
const void *iface_object_key,
|
||||
android::sp<fi::w1::wpa_supplicant::IIface> *iface_object)
|
||||
{
|
||||
if (!iface_object_key || !iface_object)
|
||||
return 1;
|
||||
|
||||
if (iface_object_map_.find(iface_object_key) == iface_object_map_.end())
|
||||
return 1;
|
||||
|
||||
*iface_object = iface_object_map_[iface_object_key];
|
||||
return 0;
|
||||
}
|
||||
|
||||
} /* namespace wpa_supplicant_binder */
|
58
wpa_supplicant/binder/binder_manager.h
Normal file
58
wpa_supplicant/binder/binder_manager.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* binder interface for wpa_supplicant daemon
|
||||
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPA_SUPPLICANT_BINDER_BINDER_MANAGER_H
|
||||
#define WPA_SUPPLICANT_BINDER_BINDER_MANAGER_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "iface.h"
|
||||
#include "supplicant.h"
|
||||
|
||||
struct wpa_global;
|
||||
struct wpa_supplicant;
|
||||
|
||||
namespace wpa_supplicant_binder {
|
||||
|
||||
/**
|
||||
* BinderManager is responsible for managing the lifetime of all
|
||||
* binder objects created by wpa_supplicant. This is a singleton
|
||||
* class which is created by the supplicant core and can be used
|
||||
* to get references to the binder objects.
|
||||
*/
|
||||
class BinderManager
|
||||
{
|
||||
public:
|
||||
static BinderManager *getInstance();
|
||||
static void destroyInstance();
|
||||
int registerBinderService(struct wpa_global *global);
|
||||
int registerInterface(struct wpa_supplicant *wpa_s);
|
||||
int unregisterInterface(struct wpa_supplicant *wpa_s);
|
||||
int getIfaceBinderObjectByKey(
|
||||
const void *iface_object_key,
|
||||
android::sp<fi::w1::wpa_supplicant::IIface> *iface_object);
|
||||
|
||||
private:
|
||||
BinderManager() = default;
|
||||
~BinderManager() = default;
|
||||
|
||||
/* Singleton instance of this class. */
|
||||
static BinderManager *instance_;
|
||||
/* The main binder service object. */
|
||||
android::sp<Supplicant> supplicant_object_;
|
||||
/* Map of all the interface specific binder objects controlled by
|
||||
* wpa_supplicant. This map is keyed in by the corresponding
|
||||
* wpa_supplicant structure pointer. */
|
||||
std::map<const void *, android::sp<Iface>> iface_object_map_;
|
||||
};
|
||||
|
||||
} /* namespace wpa_supplicant_binder */
|
||||
|
||||
#endif /* WPA_SUPPLICANT_BINDER_BINDER_MANAGER_H */
|
16
wpa_supplicant/binder/iface.cpp
Normal file
16
wpa_supplicant/binder/iface.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* binder interface for wpa_supplicant daemon
|
||||
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "iface.h"
|
||||
|
||||
namespace wpa_supplicant_binder {
|
||||
|
||||
Iface::Iface(struct wpa_supplicant *wpa_s) : wpa_s_(wpa_s) {}
|
||||
|
||||
} /* namespace wpa_supplicant_binder */
|
42
wpa_supplicant/binder/iface.h
Normal file
42
wpa_supplicant/binder/iface.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* binder interface for wpa_supplicant daemon
|
||||
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPA_SUPPLICANT_BINDER_IFACE_H
|
||||
#define WPA_SUPPLICANT_BINDER_IFACE_H
|
||||
|
||||
#include "fi/w1/wpa_supplicant/BnIface.h"
|
||||
|
||||
extern "C" {
|
||||
#include "utils/common.h"
|
||||
#include "utils/includes.h"
|
||||
#include "../wpa_supplicant_i.h"
|
||||
}
|
||||
|
||||
namespace wpa_supplicant_binder {
|
||||
|
||||
/**
|
||||
* Implementation of Iface binder object. Each unique binder
|
||||
* object is used for control operations on a specific interface
|
||||
* controlled by wpa_supplicant.
|
||||
*/
|
||||
class Iface : public fi::w1::wpa_supplicant::BnIface
|
||||
{
|
||||
public:
|
||||
Iface(struct wpa_supplicant *wpa_s);
|
||||
virtual ~Iface() = default;
|
||||
|
||||
private:
|
||||
/* Raw pointer to the structure maintained by the core for this
|
||||
* interface. */
|
||||
struct wpa_supplicant *wpa_s_;
|
||||
};
|
||||
|
||||
} /* namespace wpa_supplicant_binder */
|
||||
|
||||
#endif /* WPA_SUPPLICANT_BINDER_IFACE_H */
|
127
wpa_supplicant/binder/supplicant.cpp
Normal file
127
wpa_supplicant/binder/supplicant.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* binder interface for wpa_supplicant daemon
|
||||
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "supplicant.h"
|
||||
#include "binder_manager.h"
|
||||
|
||||
namespace wpa_supplicant_binder {
|
||||
|
||||
Supplicant::Supplicant(struct wpa_global *global) : wpa_global_(global) {}
|
||||
|
||||
android::binder::Status Supplicant::CreateInterface(
|
||||
const android::os::PersistableBundle ¶ms,
|
||||
android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
|
||||
{
|
||||
android::String16 driver, ifname, confname, bridge_ifname;
|
||||
|
||||
/* Check if required Ifname argument is missing */
|
||||
if (!params.getString(android::String16("Ifname"), &ifname))
|
||||
return android::binder::Status::fromServiceSpecificError(
|
||||
ERROR_INVALID_ARGS,
|
||||
android::String8("Ifname missing in params."));
|
||||
/* Retrieve the remaining params from the dictionary */
|
||||
params.getString(android::String16("Driver"), &driver);
|
||||
params.getString(android::String16("ConfigFile"), &confname);
|
||||
params.getString(android::String16("BridgeIfname"), &bridge_ifname);
|
||||
|
||||
/*
|
||||
* Try to get the wpa_supplicant record for this iface, return
|
||||
* an error if we already control it.
|
||||
*/
|
||||
if (wpa_supplicant_get_iface(
|
||||
wpa_global_, android::String8(ifname).string()) != NULL)
|
||||
return android::binder::Status::fromServiceSpecificError(
|
||||
ERROR_IFACE_EXISTS,
|
||||
android::String8("wpa_supplicant already controls this "
|
||||
"interface."));
|
||||
|
||||
android::binder::Status status;
|
||||
struct wpa_supplicant *wpa_s = NULL;
|
||||
struct wpa_interface iface;
|
||||
|
||||
os_memset(&iface, 0, sizeof(iface));
|
||||
iface.driver = os_strdup(android::String8(driver).string());
|
||||
iface.ifname = os_strdup(android::String8(ifname).string());
|
||||
iface.confname = os_strdup(android::String8(confname).string());
|
||||
iface.bridge_ifname =
|
||||
os_strdup(android::String8(bridge_ifname).string());
|
||||
/* Otherwise, have wpa_supplicant attach to it. */
|
||||
wpa_s = wpa_supplicant_add_iface(wpa_global_, &iface, NULL);
|
||||
/* The supplicant core creates a corresponding binder object via
|
||||
* BinderManager when |wpa_supplicant_add_iface| is called. */
|
||||
if (!wpa_s || !wpa_s->binder_object_key) {
|
||||
status = android::binder::Status::fromServiceSpecificError(
|
||||
ERROR_UNKNOWN,
|
||||
android::String8(
|
||||
"wpa_supplicant couldn't grab this interface."));
|
||||
} else {
|
||||
BinderManager *binder_manager = BinderManager::getInstance();
|
||||
|
||||
if (!binder_manager ||
|
||||
binder_manager->getIfaceBinderObjectByKey(
|
||||
wpa_s->binder_object_key, aidl_return))
|
||||
status =
|
||||
android::binder::Status::fromServiceSpecificError(
|
||||
ERROR_UNKNOWN,
|
||||
android::String8("wpa_supplicant encountered a "
|
||||
"binder error."));
|
||||
else
|
||||
status = android::binder::Status::ok();
|
||||
}
|
||||
os_free((void *)iface.driver);
|
||||
os_free((void *)iface.ifname);
|
||||
os_free((void *)iface.confname);
|
||||
os_free((void *)iface.bridge_ifname);
|
||||
return status;
|
||||
}
|
||||
|
||||
android::binder::Status Supplicant::RemoveInterface(const std::string &ifname)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s;
|
||||
|
||||
wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str());
|
||||
if (!wpa_s || !wpa_s->binder_object_key)
|
||||
return android::binder::Status::fromServiceSpecificError(
|
||||
ERROR_IFACE_UNKNOWN,
|
||||
android::String8("wpa_supplicant does not control this "
|
||||
"interface."));
|
||||
if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0))
|
||||
return android::binder::Status::fromServiceSpecificError(
|
||||
ERROR_UNKNOWN,
|
||||
android::String8(
|
||||
"wpa_supplicant couldn't remove this interface."));
|
||||
return android::binder::Status::ok();
|
||||
}
|
||||
|
||||
android::binder::Status Supplicant::GetInterface(
|
||||
const std::string &ifname,
|
||||
android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s;
|
||||
|
||||
wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str());
|
||||
if (!wpa_s || !wpa_s->binder_object_key)
|
||||
return android::binder::Status::fromServiceSpecificError(
|
||||
ERROR_IFACE_UNKNOWN,
|
||||
android::String8(
|
||||
"wpa_supplicant does not control this interface."));
|
||||
|
||||
BinderManager *binder_manager = BinderManager::getInstance();
|
||||
if (!binder_manager ||
|
||||
binder_manager->getIfaceBinderObjectByKey(
|
||||
wpa_s->binder_object_key, aidl_return))
|
||||
return android::binder::Status::fromServiceSpecificError(
|
||||
ERROR_UNKNOWN,
|
||||
android::String8(
|
||||
"wpa_supplicant encountered a binder error."));
|
||||
|
||||
return android::binder::Status::ok();
|
||||
}
|
||||
|
||||
} /* namespace wpa_supplicant_binder */
|
55
wpa_supplicant/binder/supplicant.h
Normal file
55
wpa_supplicant/binder/supplicant.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* binder interface for wpa_supplicant daemon
|
||||
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPA_SUPPLICANT_BINDER_SUPPLICANT_H
|
||||
#define WPA_SUPPLICANT_BINDER_SUPPLICANT_H
|
||||
|
||||
#include "fi/w1/wpa_supplicant/BnSupplicant.h"
|
||||
#include "fi/w1/wpa_supplicant/IIface.h"
|
||||
#include "fi/w1/wpa_supplicant/ISupplicantCallbacks.h"
|
||||
|
||||
extern "C" {
|
||||
#include "utils/common.h"
|
||||
#include "utils/includes.h"
|
||||
#include "../wpa_supplicant_i.h"
|
||||
}
|
||||
|
||||
namespace wpa_supplicant_binder {
|
||||
|
||||
/**
|
||||
* Implementation of the supplicant binder object. This binder
|
||||
* object is used core for global control operations on
|
||||
* wpa_supplicant.
|
||||
*/
|
||||
class Supplicant : public fi::w1::wpa_supplicant::BnSupplicant
|
||||
{
|
||||
public:
|
||||
Supplicant(struct wpa_global *global);
|
||||
virtual ~Supplicant() = default;
|
||||
|
||||
android::binder::Status CreateInterface(
|
||||
const android::os::PersistableBundle ¶ms,
|
||||
android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return) override;
|
||||
android::binder::Status
|
||||
RemoveInterface(const std::string &ifname) override;
|
||||
android::binder::Status GetInterface(
|
||||
const std::string &ifname,
|
||||
android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return) override;
|
||||
|
||||
private:
|
||||
/* Raw pointer to the global structure maintained by the core. */
|
||||
struct wpa_global *wpa_global_;
|
||||
/* All the callback objects registered by the clients. */
|
||||
std::vector<android::sp<fi::w1::wpa_supplicant::ISupplicantCallbacks>>
|
||||
callbacks_;
|
||||
};
|
||||
|
||||
} /* namespace wpa_supplicant_binder */
|
||||
|
||||
#endif /* WPA_SUPPLICANT_BINDER_SUPPLICANT_H */
|
1385
wpa_supplicant/bss.c
Normal file
1385
wpa_supplicant/bss.c
Normal file
File diff suppressed because it is too large
Load Diff
200
wpa_supplicant/bss.h
Normal file
200
wpa_supplicant/bss.h
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* BSS table
|
||||
* Copyright (c) 2009-2019, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef BSS_H
|
||||
#define BSS_H
|
||||
|
||||
struct wpa_scan_res;
|
||||
|
||||
#define WPA_BSS_QUAL_INVALID BIT(0)
|
||||
#define WPA_BSS_NOISE_INVALID BIT(1)
|
||||
#define WPA_BSS_LEVEL_INVALID BIT(2)
|
||||
#define WPA_BSS_LEVEL_DBM BIT(3)
|
||||
#define WPA_BSS_AUTHENTICATED BIT(4)
|
||||
#define WPA_BSS_ASSOCIATED BIT(5)
|
||||
#define WPA_BSS_ANQP_FETCH_TRIED BIT(6)
|
||||
#define WPA_BSS_OWE_TRANSITION BIT(7)
|
||||
|
||||
#define WPA_BSS_FREQ_CHANGED_FLAG BIT(0)
|
||||
#define WPA_BSS_SIGNAL_CHANGED_FLAG BIT(1)
|
||||
#define WPA_BSS_PRIVACY_CHANGED_FLAG BIT(2)
|
||||
#define WPA_BSS_MODE_CHANGED_FLAG BIT(3)
|
||||
#define WPA_BSS_WPAIE_CHANGED_FLAG BIT(4)
|
||||
#define WPA_BSS_RSNIE_CHANGED_FLAG BIT(5)
|
||||
#define WPA_BSS_WPS_CHANGED_FLAG BIT(6)
|
||||
#define WPA_BSS_RATES_CHANGED_FLAG BIT(7)
|
||||
#define WPA_BSS_IES_CHANGED_FLAG BIT(8)
|
||||
|
||||
struct wpa_bss_anqp_elem {
|
||||
struct dl_list list;
|
||||
u16 infoid;
|
||||
bool protected_response; /* received in a protected GAS response */
|
||||
struct wpabuf *payload;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wpa_bss_anqp - ANQP data for a BSS entry (struct wpa_bss)
|
||||
*/
|
||||
struct wpa_bss_anqp {
|
||||
/** Number of BSS entries referring to this ANQP data instance */
|
||||
unsigned int users;
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
struct wpabuf *capability_list;
|
||||
struct wpabuf *venue_name;
|
||||
struct wpabuf *network_auth_type;
|
||||
struct wpabuf *roaming_consortium;
|
||||
struct wpabuf *ip_addr_type_availability;
|
||||
struct wpabuf *nai_realm;
|
||||
struct wpabuf *anqp_3gpp;
|
||||
struct wpabuf *domain_name;
|
||||
struct wpabuf *fils_realm_info;
|
||||
struct dl_list anqp_elems; /* list of struct wpa_bss_anqp_elem */
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
#ifdef CONFIG_HS20
|
||||
struct wpabuf *hs20_capability_list;
|
||||
struct wpabuf *hs20_operator_friendly_name;
|
||||
struct wpabuf *hs20_wan_metrics;
|
||||
struct wpabuf *hs20_connection_capability;
|
||||
struct wpabuf *hs20_operating_class;
|
||||
struct wpabuf *hs20_osu_providers_list;
|
||||
struct wpabuf *hs20_operator_icon_metadata;
|
||||
struct wpabuf *hs20_osu_providers_nai_list;
|
||||
#endif /* CONFIG_HS20 */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wpa_bss - BSS table
|
||||
*
|
||||
* This structure is used to store information about neighboring BSSes in
|
||||
* generic format. It is mainly updated based on scan results from the driver.
|
||||
*/
|
||||
struct wpa_bss {
|
||||
/** List entry for struct wpa_supplicant::bss */
|
||||
struct dl_list list;
|
||||
/** List entry for struct wpa_supplicant::bss_id */
|
||||
struct dl_list list_id;
|
||||
/** Unique identifier for this BSS entry */
|
||||
unsigned int id;
|
||||
/** Number of counts without seeing this BSS */
|
||||
unsigned int scan_miss_count;
|
||||
/** Index of the last scan update */
|
||||
unsigned int last_update_idx;
|
||||
/** Information flags about the BSS/IBSS (WPA_BSS_*) */
|
||||
unsigned int flags;
|
||||
/** BSSID */
|
||||
u8 bssid[ETH_ALEN];
|
||||
/** HESSID */
|
||||
u8 hessid[ETH_ALEN];
|
||||
/** SSID */
|
||||
u8 ssid[SSID_MAX_LEN];
|
||||
/** Length of SSID */
|
||||
size_t ssid_len;
|
||||
/** Frequency of the channel in MHz (e.g., 2412 = channel 1) */
|
||||
int freq;
|
||||
/** Beacon interval in TUs (host byte order) */
|
||||
u16 beacon_int;
|
||||
/** Capability information field in host byte order */
|
||||
u16 caps;
|
||||
/** Signal quality */
|
||||
int qual;
|
||||
/** Noise level */
|
||||
int noise;
|
||||
/** Signal level */
|
||||
int level;
|
||||
/** Timestamp of last Beacon/Probe Response frame */
|
||||
u64 tsf;
|
||||
/** Time of the last update (i.e., Beacon or Probe Response RX) */
|
||||
struct os_reltime last_update;
|
||||
/** Estimated throughput in kbps */
|
||||
unsigned int est_throughput;
|
||||
/** Signal-to-noise ratio in dB */
|
||||
int snr;
|
||||
/** ANQP data */
|
||||
struct wpa_bss_anqp *anqp;
|
||||
/** Length of the following IE field in octets (from Probe Response) */
|
||||
size_t ie_len;
|
||||
/** Length of the following Beacon IE field in octets */
|
||||
size_t beacon_ie_len;
|
||||
/* followed by ie_len octets of IEs */
|
||||
/* followed by beacon_ie_len octets of IEs */
|
||||
u8 ies[];
|
||||
};
|
||||
|
||||
static inline const u8 * wpa_bss_ie_ptr(const struct wpa_bss *bss)
|
||||
{
|
||||
return bss->ies;
|
||||
}
|
||||
|
||||
void notify_bss_changes(struct wpa_supplicant *wpa_s, u32 changes,
|
||||
const struct wpa_bss *bss);
|
||||
void wpa_bss_update_start(struct wpa_supplicant *wpa_s);
|
||||
void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_scan_res *res,
|
||||
struct os_reltime *fetch_time);
|
||||
void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
|
||||
const char *reason);
|
||||
void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info,
|
||||
int new_scan);
|
||||
int wpa_bss_init(struct wpa_supplicant *wpa_s);
|
||||
void wpa_bss_deinit(struct wpa_supplicant *wpa_s);
|
||||
void wpa_bss_flush(struct wpa_supplicant *wpa_s);
|
||||
void wpa_bss_flush_by_age(struct wpa_supplicant *wpa_s, int age);
|
||||
struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||
const u8 *ssid, size_t ssid_len);
|
||||
struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s,
|
||||
const u8 *bssid);
|
||||
struct wpa_bss * wpa_bss_get_bssid_latest(struct wpa_supplicant *wpa_s,
|
||||
const u8 *bssid);
|
||||
struct wpa_bss * wpa_bss_get_p2p_dev_addr(struct wpa_supplicant *wpa_s,
|
||||
const u8 *dev_addr);
|
||||
struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id);
|
||||
struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s,
|
||||
unsigned int idf, unsigned int idl);
|
||||
const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie);
|
||||
const u8 * wpa_bss_get_ie_ext(const struct wpa_bss *bss, u8 ext);
|
||||
const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type);
|
||||
const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss,
|
||||
u32 vendor_type);
|
||||
struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss,
|
||||
u32 vendor_type);
|
||||
struct wpabuf * wpa_bss_get_vendor_ie_multi_beacon(const struct wpa_bss *bss,
|
||||
u32 vendor_type);
|
||||
int wpa_bss_get_max_rate(const struct wpa_bss *bss);
|
||||
int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates);
|
||||
struct wpa_bss_anqp * wpa_bss_anqp_alloc(void);
|
||||
int wpa_bss_anqp_unshare_alloc(struct wpa_bss *bss);
|
||||
const u8 * wpa_bss_get_fils_cache_id(const struct wpa_bss *bss);
|
||||
int wpa_bss_ext_capab(const struct wpa_bss *bss, unsigned int capab);
|
||||
|
||||
static inline int bss_is_dmg(const struct wpa_bss *bss)
|
||||
{
|
||||
return bss->freq > 45000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether a BSS is a PBSS.
|
||||
* This checks whether a BSS is a DMG-band PBSS. PBSS is used for P2P DMG
|
||||
* network.
|
||||
*/
|
||||
static inline int bss_is_pbss(struct wpa_bss *bss)
|
||||
{
|
||||
return bss_is_dmg(bss) &&
|
||||
(bss->caps & IEEE80211_CAP_DMG_MASK) == IEEE80211_CAP_DMG_PBSS;
|
||||
}
|
||||
|
||||
static inline void wpa_bss_update_level(struct wpa_bss *bss, int new_level)
|
||||
{
|
||||
if (bss != NULL && new_level > -WPA_INVALID_NOISE && new_level < 0)
|
||||
bss->level = new_level;
|
||||
}
|
||||
|
||||
void calculate_update_time(const struct os_reltime *fetch_time,
|
||||
unsigned int age_ms,
|
||||
struct os_reltime *update_time);
|
||||
|
||||
#endif /* BSS_H */
|
221
wpa_supplicant/bssid_ignore.c
Normal file
221
wpa_supplicant/bssid_ignore.c
Normal file
@ -0,0 +1,221 @@
|
||||
/*
|
||||
* wpa_supplicant - List of temporarily ignored BSSIDs
|
||||
* Copyright (c) 2003-2021, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "wpa_supplicant_i.h"
|
||||
#include "bssid_ignore.h"
|
||||
|
||||
/**
|
||||
* wpa_bssid_ignore_get - Get the ignore list entry for a BSSID
|
||||
* @wpa_s: Pointer to wpa_supplicant data
|
||||
* @bssid: BSSID
|
||||
* Returns: Matching entry for the BSSID or %NULL if not found
|
||||
*/
|
||||
struct wpa_bssid_ignore * wpa_bssid_ignore_get(struct wpa_supplicant *wpa_s,
|
||||
const u8 *bssid)
|
||||
{
|
||||
struct wpa_bssid_ignore *e;
|
||||
|
||||
if (wpa_s == NULL || bssid == NULL)
|
||||
return NULL;
|
||||
|
||||
if (wpa_s->current_ssid &&
|
||||
wpa_s->current_ssid->was_recently_reconfigured) {
|
||||
wpa_bssid_ignore_clear(wpa_s);
|
||||
wpa_s->current_ssid->was_recently_reconfigured = false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wpa_bssid_ignore_update(wpa_s);
|
||||
|
||||
e = wpa_s->bssid_ignore;
|
||||
while (e) {
|
||||
if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0)
|
||||
return e;
|
||||
e = e->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_bssid_ignore_add - Add an BSSID to the ignore list
|
||||
* @wpa_s: Pointer to wpa_supplicant data
|
||||
* @bssid: BSSID to be added to the ignore list
|
||||
* Returns: Current ignore list count on success, -1 on failure
|
||||
*
|
||||
* This function adds the specified BSSID to the ignore list or increases the
|
||||
* ignore count if the BSSID was already listed. It should be called when
|
||||
* an association attempt fails either due to the selected BSS rejecting
|
||||
* association or due to timeout.
|
||||
*
|
||||
* This ignore list is used to force %wpa_supplicant to go through all available
|
||||
* BSSes before retrying to associate with an BSS that rejected or timed out
|
||||
* association. It does not prevent the listed BSS from being used; it only
|
||||
* changes the order in which they are tried.
|
||||
*/
|
||||
int wpa_bssid_ignore_add(struct wpa_supplicant *wpa_s, const u8 *bssid)
|
||||
{
|
||||
struct wpa_bssid_ignore *e;
|
||||
struct os_reltime now;
|
||||
|
||||
if (wpa_s == NULL || bssid == NULL)
|
||||
return -1;
|
||||
|
||||
e = wpa_bssid_ignore_get(wpa_s, bssid);
|
||||
os_get_reltime(&now);
|
||||
if (e) {
|
||||
e->start = now;
|
||||
e->count++;
|
||||
if (e->count > 5)
|
||||
e->timeout_secs = 1800;
|
||||
else if (e->count == 5)
|
||||
e->timeout_secs = 600;
|
||||
else if (e->count == 4)
|
||||
e->timeout_secs = 120;
|
||||
else if (e->count == 3)
|
||||
e->timeout_secs = 60;
|
||||
else
|
||||
e->timeout_secs = 10;
|
||||
wpa_printf(MSG_INFO, "BSSID " MACSTR
|
||||
" ignore list count incremented to %d, ignoring for %d seconds",
|
||||
MAC2STR(bssid), e->count, e->timeout_secs);
|
||||
return e->count;
|
||||
}
|
||||
|
||||
e = os_zalloc(sizeof(*e));
|
||||
if (e == NULL)
|
||||
return -1;
|
||||
os_memcpy(e->bssid, bssid, ETH_ALEN);
|
||||
e->count = 1;
|
||||
e->timeout_secs = 10;
|
||||
e->start = now;
|
||||
e->next = wpa_s->bssid_ignore;
|
||||
wpa_s->bssid_ignore = e;
|
||||
wpa_printf(MSG_DEBUG, "Added BSSID " MACSTR
|
||||
" into ignore list, ignoring for %d seconds",
|
||||
MAC2STR(bssid), e->timeout_secs);
|
||||
|
||||
return e->count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_bssid_ignore_del - Remove an BSSID from the ignore list
|
||||
* @wpa_s: Pointer to wpa_supplicant data
|
||||
* @bssid: BSSID to be removed from the ignore list
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int wpa_bssid_ignore_del(struct wpa_supplicant *wpa_s, const u8 *bssid)
|
||||
{
|
||||
struct wpa_bssid_ignore *e, *prev = NULL;
|
||||
|
||||
if (wpa_s == NULL || bssid == NULL)
|
||||
return -1;
|
||||
|
||||
e = wpa_s->bssid_ignore;
|
||||
while (e) {
|
||||
if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0) {
|
||||
if (prev == NULL) {
|
||||
wpa_s->bssid_ignore = e->next;
|
||||
} else {
|
||||
prev->next = e->next;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR
|
||||
" from ignore list", MAC2STR(bssid));
|
||||
os_free(e);
|
||||
return 0;
|
||||
}
|
||||
prev = e;
|
||||
e = e->next;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_bssid_ignore_is_listed - Check whether a BSSID is ignored temporarily
|
||||
* @wpa_s: Pointer to wpa_supplicant data
|
||||
* @bssid: BSSID to be checked
|
||||
* Returns: count if BSS is currently considered to be ignored, 0 otherwise
|
||||
*/
|
||||
int wpa_bssid_ignore_is_listed(struct wpa_supplicant *wpa_s, const u8 *bssid)
|
||||
{
|
||||
struct wpa_bssid_ignore *e;
|
||||
struct os_reltime now;
|
||||
|
||||
e = wpa_bssid_ignore_get(wpa_s, bssid);
|
||||
if (!e)
|
||||
return 0;
|
||||
os_get_reltime(&now);
|
||||
if (os_reltime_expired(&now, &e->start, e->timeout_secs))
|
||||
return 0;
|
||||
return e->count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_bssid_ignore_clear - Clear the ignore list of all entries
|
||||
* @wpa_s: Pointer to wpa_supplicant data
|
||||
*/
|
||||
void wpa_bssid_ignore_clear(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
struct wpa_bssid_ignore *e, *prev;
|
||||
|
||||
e = wpa_s->bssid_ignore;
|
||||
wpa_s->bssid_ignore = NULL;
|
||||
while (e) {
|
||||
prev = e;
|
||||
e = e->next;
|
||||
wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR
|
||||
" from ignore list (clear)", MAC2STR(prev->bssid));
|
||||
os_free(prev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_bssid_ignore_update - Update the entries in the ignore list,
|
||||
* deleting entries that have been expired for over an hour.
|
||||
* @wpa_s: Pointer to wpa_supplicant data
|
||||
*/
|
||||
void wpa_bssid_ignore_update(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
struct wpa_bssid_ignore *e, *prev = NULL;
|
||||
struct os_reltime now;
|
||||
|
||||
if (!wpa_s)
|
||||
return;
|
||||
|
||||
e = wpa_s->bssid_ignore;
|
||||
os_get_reltime(&now);
|
||||
while (e) {
|
||||
if (os_reltime_expired(&now, &e->start,
|
||||
e->timeout_secs + 3600)) {
|
||||
struct wpa_bssid_ignore *to_delete = e;
|
||||
|
||||
if (prev) {
|
||||
prev->next = e->next;
|
||||
e = prev->next;
|
||||
} else {
|
||||
wpa_s->bssid_ignore = e->next;
|
||||
e = wpa_s->bssid_ignore;
|
||||
}
|
||||
wpa_printf(MSG_INFO, "Removed BSSID " MACSTR
|
||||
" from ignore list (expired)",
|
||||
MAC2STR(to_delete->bssid));
|
||||
os_free(to_delete);
|
||||
} else {
|
||||
prev = e;
|
||||
e = e->next;
|
||||
}
|
||||
}
|
||||
}
|
33
wpa_supplicant/bssid_ignore.h
Normal file
33
wpa_supplicant/bssid_ignore.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* wpa_supplicant - List of temporarily ignored BSSIDs
|
||||
* Copyright (c) 2003-2021, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef BSSID_IGNORE_H
|
||||
#define BSSID_IGNORE_H
|
||||
|
||||
struct wpa_bssid_ignore {
|
||||
struct wpa_bssid_ignore *next;
|
||||
u8 bssid[ETH_ALEN];
|
||||
int count;
|
||||
/* Time of the most recent trigger to ignore this BSSID. */
|
||||
struct os_reltime start;
|
||||
/*
|
||||
* Number of seconds after start that the entey will be considered
|
||||
* valid.
|
||||
*/
|
||||
int timeout_secs;
|
||||
};
|
||||
|
||||
struct wpa_bssid_ignore * wpa_bssid_ignore_get(struct wpa_supplicant *wpa_s,
|
||||
const u8 *bssid);
|
||||
int wpa_bssid_ignore_add(struct wpa_supplicant *wpa_s, const u8 *bssid);
|
||||
int wpa_bssid_ignore_del(struct wpa_supplicant *wpa_s, const u8 *bssid);
|
||||
int wpa_bssid_ignore_is_listed(struct wpa_supplicant *wpa_s, const u8 *bssid);
|
||||
void wpa_bssid_ignore_clear(struct wpa_supplicant *wpa_s);
|
||||
void wpa_bssid_ignore_update(struct wpa_supplicant *wpa_s);
|
||||
|
||||
#endif /* BSSID_IGNORE_H */
|
5429
wpa_supplicant/config.c
Normal file
5429
wpa_supplicant/config.c
Normal file
File diff suppressed because it is too large
Load Diff
1797
wpa_supplicant/config.h
Normal file
1797
wpa_supplicant/config.h
Normal file
File diff suppressed because it is too large
Load Diff
1656
wpa_supplicant/config_file.c
Normal file
1656
wpa_supplicant/config_file.c
Normal file
File diff suppressed because it is too large
Load Diff
56
wpa_supplicant/config_none.c
Normal file
56
wpa_supplicant/config_none.c
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* WPA Supplicant / Configuration backend: empty starting point
|
||||
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*
|
||||
* This file implements stub example of a configuration backend. None of the
|
||||
* functions are actually implemented so this can be used as a simple
|
||||
* compilation test or a starting point for a new configuration backend.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "config.h"
|
||||
#include "base64.h"
|
||||
|
||||
|
||||
struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp)
|
||||
{
|
||||
struct wpa_config *config;
|
||||
|
||||
if (name == NULL)
|
||||
return NULL;
|
||||
if (cfgp)
|
||||
config = cfgp;
|
||||
else
|
||||
config = wpa_config_alloc_empty(NULL, NULL);
|
||||
if (config == NULL)
|
||||
return NULL;
|
||||
/* TODO: fill in configuration data */
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
int wpa_config_write(const char *name, struct wpa_config *config)
|
||||
{
|
||||
struct wpa_ssid *ssid;
|
||||
struct wpa_config_blob *blob;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name);
|
||||
|
||||
/* TODO: write global config parameters */
|
||||
|
||||
|
||||
for (ssid = config->ssid; ssid; ssid = ssid->next) {
|
||||
/* TODO: write networks */
|
||||
}
|
||||
|
||||
for (blob = config->blobs; blob; blob = blob->next) {
|
||||
/* TODO: write blobs */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
1182
wpa_supplicant/config_ssid.h
Normal file
1182
wpa_supplicant/config_ssid.h
Normal file
File diff suppressed because it is too large
Load Diff
1061
wpa_supplicant/config_winreg.c
Normal file
1061
wpa_supplicant/config_winreg.c
Normal file
File diff suppressed because it is too large
Load Diff
13103
wpa_supplicant/ctrl_iface.c
Normal file
13103
wpa_supplicant/ctrl_iface.c
Normal file
File diff suppressed because it is too large
Load Diff
167
wpa_supplicant/ctrl_iface.h
Normal file
167
wpa_supplicant/ctrl_iface.h
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* WPA Supplicant / UNIX domain socket -based control interface
|
||||
* Copyright (c) 2004-2020, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef CTRL_IFACE_H
|
||||
#define CTRL_IFACE_H
|
||||
|
||||
#ifdef CONFIG_CTRL_IFACE
|
||||
|
||||
#ifndef CTRL_IFACE_MAX_LEN
|
||||
#define CTRL_IFACE_MAX_LEN 8192
|
||||
#endif /* CTRL_IFACE_MAX_LEN */
|
||||
|
||||
/* Shared functions from ctrl_iface.c; to be called by ctrl_iface backends */
|
||||
|
||||
/**
|
||||
* wpa_supplicant_ctrl_iface_process - Process ctrl_iface command
|
||||
* @wpa_s: Pointer to wpa_supplicant data
|
||||
* @buf: Received command buffer (nul terminated string)
|
||||
* @resp_len: Variable to be set to the response length
|
||||
* Returns: Response (*resp_len bytes) or %NULL on failure
|
||||
*
|
||||
* Control interface backends call this function when receiving a message that
|
||||
* they do not process internally, i.e., anything else than ATTACH, DETACH,
|
||||
* and LEVEL. The return response value is then sent to the external program
|
||||
* that sent the command. Caller is responsible for freeing the buffer after
|
||||
* this. If %NULL is returned, *resp_len can be set to two special values:
|
||||
* 1 = send "FAIL\n" response, 2 = send "OK\n" response. If *resp_len has any
|
||||
* other value, no response is sent.
|
||||
*/
|
||||
char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
||||
char *buf, size_t *resp_len);
|
||||
|
||||
/**
|
||||
* wpa_supplicant_global_ctrl_iface_process - Process global ctrl_iface command
|
||||
* @global: Pointer to global data from wpa_supplicant_init()
|
||||
* @buf: Received command buffer (nul terminated string)
|
||||
* @resp_len: Variable to be set to the response length
|
||||
* Returns: Response (*resp_len bytes) or %NULL on failure
|
||||
*
|
||||
* Control interface backends call this function when receiving a message from
|
||||
* the global ctrl_iface connection. The return response value is then sent to
|
||||
* the external program that sent the command. Caller is responsible for
|
||||
* freeing the buffer after this. If %NULL is returned, *resp_len can be set to
|
||||
* two special values: 1 = send "FAIL\n" response, 2 = send "OK\n" response. If
|
||||
* *resp_len has any other value, no response is sent.
|
||||
*/
|
||||
char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
|
||||
char *buf, size_t *resp_len);
|
||||
|
||||
|
||||
/* Functions that each ctrl_iface backend must implement */
|
||||
|
||||
/**
|
||||
* wpa_supplicant_ctrl_iface_init - Initialize control interface
|
||||
* @wpa_s: Pointer to wpa_supplicant data
|
||||
* Returns: Pointer to private data on success, %NULL on failure
|
||||
*
|
||||
* Initialize the control interface and start receiving commands from external
|
||||
* programs.
|
||||
*
|
||||
* Required to be implemented in each control interface backend.
|
||||
*/
|
||||
struct ctrl_iface_priv *
|
||||
wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s);
|
||||
|
||||
/**
|
||||
* wpa_supplicant_ctrl_iface_deinit - Deinitialize control interface
|
||||
* @wpa_s: Pointer to wpa_supplicant data
|
||||
* @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init()
|
||||
*
|
||||
* Deinitialize the control interface that was initialized with
|
||||
* wpa_supplicant_ctrl_iface_init() and any data related to the wpa_s instance.
|
||||
* @priv may be %NULL if the control interface has not yet been initialized.
|
||||
*
|
||||
* Required to be implemented in each control interface backend.
|
||||
*/
|
||||
void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
|
||||
struct ctrl_iface_priv *priv);
|
||||
|
||||
/**
|
||||
* wpa_supplicant_ctrl_iface_wait - Wait for ctrl_iface monitor
|
||||
* @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init()
|
||||
*
|
||||
* Wait until the first message from an external program using the control
|
||||
* interface is received. This function can be used to delay normal startup
|
||||
* processing to allow control interface programs to attach with
|
||||
* %wpa_supplicant before normal operations are started.
|
||||
*
|
||||
* Required to be implemented in each control interface backend.
|
||||
*/
|
||||
void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv);
|
||||
|
||||
/**
|
||||
* wpa_supplicant_global_ctrl_iface_init - Initialize global control interface
|
||||
* @global: Pointer to global data from wpa_supplicant_init()
|
||||
* Returns: Pointer to private data on success, %NULL on failure
|
||||
*
|
||||
* Initialize the global control interface and start receiving commands from
|
||||
* external programs.
|
||||
*
|
||||
* Required to be implemented in each control interface backend.
|
||||
*/
|
||||
struct ctrl_iface_global_priv *
|
||||
wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global);
|
||||
|
||||
/**
|
||||
* wpa_supplicant_global_ctrl_iface_deinit - Deinitialize global ctrl interface
|
||||
* @priv: Pointer to private data from wpa_supplicant_global_ctrl_iface_init()
|
||||
*
|
||||
* Deinitialize the global control interface that was initialized with
|
||||
* wpa_supplicant_global_ctrl_iface_init().
|
||||
*
|
||||
* Required to be implemented in each control interface backend.
|
||||
*/
|
||||
void wpa_supplicant_global_ctrl_iface_deinit(
|
||||
struct ctrl_iface_global_priv *priv);
|
||||
|
||||
void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s);
|
||||
|
||||
#else /* CONFIG_CTRL_IFACE */
|
||||
|
||||
static inline struct ctrl_iface_priv *
|
||||
wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
return (void *) -1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
|
||||
struct ctrl_iface_priv *priv)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, int level,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv)
|
||||
{
|
||||
}
|
||||
|
||||
static inline struct ctrl_iface_global_priv *
|
||||
wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
|
||||
{
|
||||
return (void *) 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_CTRL_IFACE */
|
||||
|
||||
#endif /* CTRL_IFACE_H */
|
831
wpa_supplicant/ctrl_iface_named_pipe.c
Normal file
831
wpa_supplicant/ctrl_iface_named_pipe.c
Normal file
@ -0,0 +1,831 @@
|
||||
/*
|
||||
* WPA Supplicant / Windows Named Pipe -based control interface
|
||||
* Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "eloop.h"
|
||||
#include "config.h"
|
||||
#include "eapol_supp/eapol_supp_sm.h"
|
||||
#include "wpa_supplicant_i.h"
|
||||
#include "ctrl_iface.h"
|
||||
#include "common/wpa_ctrl.h"
|
||||
|
||||
#ifdef __MINGW32_VERSION
|
||||
/* mingw-w32api v3.1 does not yet include sddl.h, so define needed parts here
|
||||
*/
|
||||
#define SDDL_REVISION_1 1
|
||||
BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
|
||||
LPCSTR, DWORD, PSECURITY_DESCRIPTOR *, PULONG);
|
||||
BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW(
|
||||
LPCWSTR, DWORD, PSECURITY_DESCRIPTOR *, PULONG);
|
||||
#ifdef UNICODE
|
||||
#define ConvertStringSecurityDescriptorToSecurityDescriptor \
|
||||
ConvertStringSecurityDescriptorToSecurityDescriptorW
|
||||
#else
|
||||
#define ConvertStringSecurityDescriptorToSecurityDescriptor \
|
||||
ConvertStringSecurityDescriptorToSecurityDescriptorA
|
||||
#endif
|
||||
#else /* __MINGW32_VERSION */
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0500
|
||||
#endif
|
||||
#include <sddl.h>
|
||||
#endif /* __MINGW32_VERSION */
|
||||
|
||||
#ifndef WPA_SUPPLICANT_NAMED_PIPE
|
||||
#define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant"
|
||||
#endif
|
||||
#define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE)
|
||||
|
||||
/* Per-interface ctrl_iface */
|
||||
|
||||
#define REQUEST_BUFSIZE CTRL_IFACE_MAX_LEN
|
||||
#define REPLY_BUFSIZE 4096
|
||||
|
||||
struct ctrl_iface_priv;
|
||||
|
||||
/**
|
||||
* struct wpa_ctrl_dst - Internal data structure of control interface clients
|
||||
*
|
||||
* This structure is used to store information about registered control
|
||||
* interface monitors into struct wpa_supplicant. This data is private to
|
||||
* ctrl_iface_named_pipe.c and should not be touched directly from other files.
|
||||
*/
|
||||
struct wpa_ctrl_dst {
|
||||
/* Note: OVERLAPPED must be the first member of struct wpa_ctrl_dst */
|
||||
OVERLAPPED overlap;
|
||||
struct wpa_ctrl_dst *next, *prev;
|
||||
struct ctrl_iface_priv *priv;
|
||||
HANDLE pipe;
|
||||
int attached;
|
||||
int debug_level;
|
||||
int errors;
|
||||
char req_buf[REQUEST_BUFSIZE];
|
||||
char *rsp_buf;
|
||||
int used;
|
||||
};
|
||||
|
||||
|
||||
struct ctrl_iface_priv {
|
||||
struct wpa_supplicant *wpa_s;
|
||||
struct wpa_ctrl_dst *ctrl_dst;
|
||||
SECURITY_ATTRIBUTES attr;
|
||||
int sec_attr_set;
|
||||
};
|
||||
|
||||
|
||||
static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
|
||||
int level, const char *buf,
|
||||
size_t len);
|
||||
|
||||
static void ctrl_close_pipe(struct wpa_ctrl_dst *dst);
|
||||
static void wpa_supplicant_ctrl_iface_receive(void *, void *);
|
||||
static VOID WINAPI ctrl_iface_read_completed(DWORD err, DWORD bytes,
|
||||
LPOVERLAPPED overlap);
|
||||
|
||||
struct wpa_global_dst;
|
||||
static void global_close_pipe(struct wpa_global_dst *dst);
|
||||
static void wpa_supplicant_global_iface_receive(void *eloop_data,
|
||||
void *user_ctx);
|
||||
static VOID WINAPI global_iface_read_completed(DWORD err, DWORD bytes,
|
||||
LPOVERLAPPED overlap);
|
||||
|
||||
|
||||
static int ctrl_broken_pipe(HANDLE pipe, int used)
|
||||
{
|
||||
DWORD err;
|
||||
|
||||
if (PeekNamedPipe(pipe, NULL, 0, NULL, NULL, NULL))
|
||||
return 0;
|
||||
|
||||
err = GetLastError();
|
||||
if (err == ERROR_BROKEN_PIPE || (err == ERROR_BAD_PIPE && used))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void ctrl_flush_broken_pipes(struct ctrl_iface_priv *priv)
|
||||
{
|
||||
struct wpa_ctrl_dst *dst, *next;
|
||||
|
||||
dst = priv->ctrl_dst;
|
||||
|
||||
while (dst) {
|
||||
next = dst->next;
|
||||
if (ctrl_broken_pipe(dst->pipe, dst->used)) {
|
||||
wpa_printf(MSG_DEBUG, "CTRL: closing broken pipe %p",
|
||||
dst);
|
||||
ctrl_close_pipe(dst);
|
||||
}
|
||||
dst = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int ctrl_open_pipe(struct ctrl_iface_priv *priv)
|
||||
{
|
||||
struct wpa_ctrl_dst *dst;
|
||||
DWORD err;
|
||||
TCHAR name[256];
|
||||
|
||||
dst = os_zalloc(sizeof(*dst));
|
||||
if (dst == NULL)
|
||||
return -1;
|
||||
wpa_printf(MSG_DEBUG, "CTRL: Open pipe %p", dst);
|
||||
|
||||
dst->priv = priv;
|
||||
dst->debug_level = MSG_INFO;
|
||||
dst->pipe = INVALID_HANDLE_VALUE;
|
||||
|
||||
dst->overlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
|
||||
if (dst->overlap.hEvent == NULL) {
|
||||
wpa_printf(MSG_ERROR, "CTRL: CreateEvent failed: %d",
|
||||
(int) GetLastError());
|
||||
goto fail;
|
||||
}
|
||||
|
||||
eloop_register_event(dst->overlap.hEvent,
|
||||
sizeof(dst->overlap.hEvent),
|
||||
wpa_supplicant_ctrl_iface_receive, dst, NULL);
|
||||
|
||||
#ifdef UNICODE
|
||||
_snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"),
|
||||
priv->wpa_s->ifname);
|
||||
#else /* UNICODE */
|
||||
os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s",
|
||||
priv->wpa_s->ifname);
|
||||
#endif /* UNICODE */
|
||||
|
||||
/* TODO: add support for configuring access list for the pipe */
|
||||
dst->pipe = CreateNamedPipe(name,
|
||||
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
|
||||
PIPE_TYPE_MESSAGE |
|
||||
PIPE_READMODE_MESSAGE |
|
||||
PIPE_WAIT,
|
||||
15, REPLY_BUFSIZE, REQUEST_BUFSIZE,
|
||||
1000,
|
||||
priv->sec_attr_set ? &priv->attr : NULL);
|
||||
if (dst->pipe == INVALID_HANDLE_VALUE) {
|
||||
wpa_printf(MSG_ERROR, "CTRL: CreateNamedPipe failed: %d",
|
||||
(int) GetLastError());
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (ConnectNamedPipe(dst->pipe, &dst->overlap)) {
|
||||
wpa_printf(MSG_ERROR, "CTRL: ConnectNamedPipe failed: %d",
|
||||
(int) GetLastError());
|
||||
CloseHandle(dst->pipe);
|
||||
os_free(dst);
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = GetLastError();
|
||||
switch (err) {
|
||||
case ERROR_IO_PENDING:
|
||||
wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe: connection in "
|
||||
"progress");
|
||||
break;
|
||||
case ERROR_PIPE_CONNECTED:
|
||||
wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe: already "
|
||||
"connected");
|
||||
if (SetEvent(dst->overlap.hEvent))
|
||||
break;
|
||||
/* fall through */
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe error: %d",
|
||||
(int) err);
|
||||
CloseHandle(dst->pipe);
|
||||
os_free(dst);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dst->next = priv->ctrl_dst;
|
||||
if (dst->next)
|
||||
dst->next->prev = dst;
|
||||
priv->ctrl_dst = dst;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
ctrl_close_pipe(dst);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static void ctrl_close_pipe(struct wpa_ctrl_dst *dst)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "CTRL: close pipe %p", dst);
|
||||
|
||||
if (dst->overlap.hEvent) {
|
||||
eloop_unregister_event(dst->overlap.hEvent,
|
||||
sizeof(dst->overlap.hEvent));
|
||||
CloseHandle(dst->overlap.hEvent);
|
||||
}
|
||||
|
||||
if (dst->pipe != INVALID_HANDLE_VALUE) {
|
||||
/*
|
||||
* Could use FlushFileBuffers() here to guarantee that all data
|
||||
* gets delivered to the client, but that can block, so let's
|
||||
* not do this for now.
|
||||
* FlushFileBuffers(dst->pipe);
|
||||
*/
|
||||
CloseHandle(dst->pipe);
|
||||
}
|
||||
|
||||
if (dst->prev)
|
||||
dst->prev->next = dst->next;
|
||||
else
|
||||
dst->priv->ctrl_dst = dst->next;
|
||||
if (dst->next)
|
||||
dst->next->prev = dst->prev;
|
||||
|
||||
os_free(dst->rsp_buf);
|
||||
os_free(dst);
|
||||
}
|
||||
|
||||
|
||||
static VOID WINAPI ctrl_iface_write_completed(DWORD err, DWORD bytes,
|
||||
LPOVERLAPPED overlap)
|
||||
{
|
||||
struct wpa_ctrl_dst *dst = (struct wpa_ctrl_dst *) overlap;
|
||||
wpa_printf(MSG_DEBUG, "CTRL: Overlapped write completed: dst=%p "
|
||||
"err=%d bytes=%d", dst, (int) err, (int) bytes);
|
||||
if (err) {
|
||||
ctrl_close_pipe(dst);
|
||||
return;
|
||||
}
|
||||
|
||||
os_free(dst->rsp_buf);
|
||||
dst->rsp_buf = NULL;
|
||||
|
||||
if (!ReadFileEx(dst->pipe, dst->req_buf, sizeof(dst->req_buf),
|
||||
&dst->overlap, ctrl_iface_read_completed)) {
|
||||
wpa_printf(MSG_DEBUG, "CTRL: ReadFileEx failed: %d",
|
||||
(int) GetLastError());
|
||||
ctrl_close_pipe(dst);
|
||||
return;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "CTRL: Overlapped read started for %p", dst);
|
||||
}
|
||||
|
||||
|
||||
static void wpa_supplicant_ctrl_iface_rx(struct wpa_ctrl_dst *dst, size_t len)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = dst->priv->wpa_s;
|
||||
char *reply = NULL, *send_buf;
|
||||
size_t reply_len = 0, send_len;
|
||||
int new_attached = 0;
|
||||
char *buf = dst->req_buf;
|
||||
|
||||
dst->used = 1;
|
||||
if (len >= REQUEST_BUFSIZE)
|
||||
len = REQUEST_BUFSIZE - 1;
|
||||
buf[len] = '\0';
|
||||
|
||||
if (os_strcmp(buf, "ATTACH") == 0) {
|
||||
dst->attached = 1;
|
||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached");
|
||||
new_attached = 1;
|
||||
reply_len = 2;
|
||||
} else if (os_strcmp(buf, "DETACH") == 0) {
|
||||
dst->attached = 0;
|
||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached");
|
||||
reply_len = 2;
|
||||
} else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
|
||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", buf + 6);
|
||||
dst->debug_level = atoi(buf + 6);
|
||||
reply_len = 2;
|
||||
} else {
|
||||
reply = wpa_supplicant_ctrl_iface_process(wpa_s, buf,
|
||||
&reply_len);
|
||||
}
|
||||
|
||||
if (reply) {
|
||||
send_buf = reply;
|
||||
send_len = reply_len;
|
||||
} else if (reply_len == 2) {
|
||||
send_buf = "OK\n";
|
||||
send_len = 3;
|
||||
} else {
|
||||
send_buf = "FAIL\n";
|
||||
send_len = 5;
|
||||
}
|
||||
|
||||
os_free(dst->rsp_buf);
|
||||
dst->rsp_buf = os_memdup(send_buf, send_len);
|
||||
if (dst->rsp_buf == NULL) {
|
||||
ctrl_close_pipe(dst);
|
||||
os_free(reply);
|
||||
return;
|
||||
}
|
||||
os_free(reply);
|
||||
|
||||
if (!WriteFileEx(dst->pipe, dst->rsp_buf, send_len, &dst->overlap,
|
||||
ctrl_iface_write_completed)) {
|
||||
wpa_printf(MSG_DEBUG, "CTRL: WriteFileEx failed: %d",
|
||||
(int) GetLastError());
|
||||
ctrl_close_pipe(dst);
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "CTRL: Overlapped write started for %p",
|
||||
dst);
|
||||
}
|
||||
|
||||
if (new_attached)
|
||||
eapol_sm_notify_ctrl_attached(wpa_s->eapol);
|
||||
}
|
||||
|
||||
|
||||
static VOID WINAPI ctrl_iface_read_completed(DWORD err, DWORD bytes,
|
||||
LPOVERLAPPED overlap)
|
||||
{
|
||||
struct wpa_ctrl_dst *dst = (struct wpa_ctrl_dst *) overlap;
|
||||
wpa_printf(MSG_DEBUG, "CTRL: Overlapped read completed: dst=%p err=%d "
|
||||
"bytes=%d", dst, (int) err, (int) bytes);
|
||||
if (err == 0 && bytes > 0)
|
||||
wpa_supplicant_ctrl_iface_rx(dst, bytes);
|
||||
}
|
||||
|
||||
|
||||
static void wpa_supplicant_ctrl_iface_receive(void *eloop_data, void *user_ctx)
|
||||
{
|
||||
struct wpa_ctrl_dst *dst = eloop_data;
|
||||
struct ctrl_iface_priv *priv = dst->priv;
|
||||
DWORD bytes;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "CTRL: wpa_supplicant_ctrl_iface_receive");
|
||||
ResetEvent(dst->overlap.hEvent);
|
||||
|
||||
if (!GetOverlappedResult(dst->pipe, &dst->overlap, &bytes, FALSE)) {
|
||||
wpa_printf(MSG_DEBUG, "CTRL: GetOverlappedResult failed: %d",
|
||||
(int) GetLastError());
|
||||
return;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "CTRL: GetOverlappedResult: New client "
|
||||
"connected");
|
||||
|
||||
/* Open a new named pipe for the next client. */
|
||||
ctrl_open_pipe(priv);
|
||||
|
||||
/* Use write completion function to start reading a command */
|
||||
ctrl_iface_write_completed(0, 0, &dst->overlap);
|
||||
|
||||
ctrl_flush_broken_pipes(priv);
|
||||
}
|
||||
|
||||
|
||||
static int ctrl_iface_parse(struct ctrl_iface_priv *priv, const char *params)
|
||||
{
|
||||
const char *sddl = NULL;
|
||||
TCHAR *t_sddl;
|
||||
|
||||
if (os_strncmp(params, "SDDL=", 5) == 0)
|
||||
sddl = params + 5;
|
||||
if (!sddl) {
|
||||
sddl = os_strstr(params, " SDDL=");
|
||||
if (sddl)
|
||||
sddl += 6;
|
||||
}
|
||||
|
||||
if (!sddl)
|
||||
return 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "CTRL: SDDL='%s'", sddl);
|
||||
os_memset(&priv->attr, 0, sizeof(priv->attr));
|
||||
priv->attr.nLength = sizeof(priv->attr);
|
||||
priv->attr.bInheritHandle = FALSE;
|
||||
t_sddl = wpa_strdup_tchar(sddl);
|
||||
if (t_sddl == NULL)
|
||||
return -1;
|
||||
if (!ConvertStringSecurityDescriptorToSecurityDescriptor(
|
||||
t_sddl, SDDL_REVISION_1,
|
||||
(PSECURITY_DESCRIPTOR *) (void *)
|
||||
&priv->attr.lpSecurityDescriptor,
|
||||
NULL)) {
|
||||
os_free(t_sddl);
|
||||
wpa_printf(MSG_ERROR, "CTRL: SDDL='%s' - could not convert to "
|
||||
"security descriptor: %d",
|
||||
sddl, (int) GetLastError());
|
||||
return -1;
|
||||
}
|
||||
os_free(t_sddl);
|
||||
|
||||
priv->sec_attr_set = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
|
||||
enum wpa_msg_type type,
|
||||
const char *txt, size_t len)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = ctx;
|
||||
if (wpa_s == NULL || wpa_s->ctrl_iface == NULL)
|
||||
return;
|
||||
wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len);
|
||||
}
|
||||
|
||||
|
||||
struct ctrl_iface_priv *
|
||||
wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
struct ctrl_iface_priv *priv;
|
||||
|
||||
priv = os_zalloc(sizeof(*priv));
|
||||
if (priv == NULL)
|
||||
return NULL;
|
||||
priv->wpa_s = wpa_s;
|
||||
|
||||
if (wpa_s->conf->ctrl_interface == NULL)
|
||||
return priv;
|
||||
|
||||
if (ctrl_iface_parse(priv, wpa_s->conf->ctrl_interface) < 0) {
|
||||
os_free(priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ctrl_open_pipe(priv) < 0) {
|
||||
os_free(priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
|
||||
|
||||
return priv;
|
||||
}
|
||||
|
||||
|
||||
void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
|
||||
struct ctrl_iface_priv *priv)
|
||||
{
|
||||
if (!priv)
|
||||
return;
|
||||
while (priv->ctrl_dst)
|
||||
ctrl_close_pipe(priv->ctrl_dst);
|
||||
if (priv->sec_attr_set)
|
||||
LocalFree(priv->attr.lpSecurityDescriptor);
|
||||
os_free(priv);
|
||||
}
|
||||
|
||||
|
||||
static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
|
||||
int level, const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct wpa_ctrl_dst *dst, *next;
|
||||
char levelstr[10];
|
||||
int idx;
|
||||
char *sbuf;
|
||||
int llen;
|
||||
DWORD written;
|
||||
|
||||
dst = priv->ctrl_dst;
|
||||
if (dst == NULL)
|
||||
return;
|
||||
|
||||
os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
|
||||
|
||||
llen = os_strlen(levelstr);
|
||||
sbuf = os_malloc(llen + len);
|
||||
if (sbuf == NULL)
|
||||
return;
|
||||
|
||||
os_memcpy(sbuf, levelstr, llen);
|
||||
os_memcpy(sbuf + llen, buf, len);
|
||||
|
||||
idx = 0;
|
||||
while (dst) {
|
||||
next = dst->next;
|
||||
if (dst->attached && level >= dst->debug_level) {
|
||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %p",
|
||||
dst);
|
||||
if (!WriteFile(dst->pipe, sbuf, llen + len, &written,
|
||||
NULL)) {
|
||||
wpa_printf(MSG_DEBUG, "CTRL: WriteFile to dst "
|
||||
"%p failed: %d",
|
||||
dst, (int) GetLastError());
|
||||
dst->errors++;
|
||||
if (dst->errors > 10)
|
||||
ctrl_close_pipe(dst);
|
||||
} else
|
||||
dst->errors = 0;
|
||||
}
|
||||
idx++;
|
||||
dst = next;
|
||||
}
|
||||
os_free(sbuf);
|
||||
}
|
||||
|
||||
|
||||
void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor",
|
||||
priv->wpa_s->ifname);
|
||||
if (priv->ctrl_dst == NULL)
|
||||
return;
|
||||
WaitForSingleObject(priv->ctrl_dst->pipe, INFINITE);
|
||||
}
|
||||
|
||||
|
||||
/* Global ctrl_iface */
|
||||
|
||||
struct ctrl_iface_global_priv;
|
||||
|
||||
struct wpa_global_dst {
|
||||
/* Note: OVERLAPPED must be the first member of struct wpa_global_dst
|
||||
*/
|
||||
OVERLAPPED overlap;
|
||||
struct wpa_global_dst *next, *prev;
|
||||
struct ctrl_iface_global_priv *priv;
|
||||
HANDLE pipe;
|
||||
char req_buf[REQUEST_BUFSIZE];
|
||||
char *rsp_buf;
|
||||
int used;
|
||||
};
|
||||
|
||||
struct ctrl_iface_global_priv {
|
||||
struct wpa_global *global;
|
||||
struct wpa_global_dst *ctrl_dst;
|
||||
};
|
||||
|
||||
|
||||
static void global_flush_broken_pipes(struct ctrl_iface_global_priv *priv)
|
||||
{
|
||||
struct wpa_global_dst *dst, *next;
|
||||
|
||||
dst = priv->ctrl_dst;
|
||||
|
||||
while (dst) {
|
||||
next = dst->next;
|
||||
if (ctrl_broken_pipe(dst->pipe, dst->used)) {
|
||||
wpa_printf(MSG_DEBUG, "CTRL: closing broken pipe %p",
|
||||
dst);
|
||||
global_close_pipe(dst);
|
||||
}
|
||||
dst = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int global_open_pipe(struct ctrl_iface_global_priv *priv)
|
||||
{
|
||||
struct wpa_global_dst *dst;
|
||||
DWORD err;
|
||||
|
||||
dst = os_zalloc(sizeof(*dst));
|
||||
if (dst == NULL)
|
||||
return -1;
|
||||
wpa_printf(MSG_DEBUG, "CTRL: Open pipe %p", dst);
|
||||
|
||||
dst->priv = priv;
|
||||
dst->pipe = INVALID_HANDLE_VALUE;
|
||||
|
||||
dst->overlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
|
||||
if (dst->overlap.hEvent == NULL) {
|
||||
wpa_printf(MSG_ERROR, "CTRL: CreateEvent failed: %d",
|
||||
(int) GetLastError());
|
||||
goto fail;
|
||||
}
|
||||
|
||||
eloop_register_event(dst->overlap.hEvent,
|
||||
sizeof(dst->overlap.hEvent),
|
||||
wpa_supplicant_global_iface_receive, dst, NULL);
|
||||
|
||||
/* TODO: add support for configuring access list for the pipe */
|
||||
dst->pipe = CreateNamedPipe(NAMED_PIPE_PREFIX,
|
||||
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
|
||||
PIPE_TYPE_MESSAGE |
|
||||
PIPE_READMODE_MESSAGE |
|
||||
PIPE_WAIT,
|
||||
10, REPLY_BUFSIZE, REQUEST_BUFSIZE,
|
||||
1000, NULL);
|
||||
if (dst->pipe == INVALID_HANDLE_VALUE) {
|
||||
wpa_printf(MSG_ERROR, "CTRL: CreateNamedPipe failed: %d",
|
||||
(int) GetLastError());
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (ConnectNamedPipe(dst->pipe, &dst->overlap)) {
|
||||
wpa_printf(MSG_ERROR, "CTRL: ConnectNamedPipe failed: %d",
|
||||
(int) GetLastError());
|
||||
CloseHandle(dst->pipe);
|
||||
os_free(dst);
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = GetLastError();
|
||||
switch (err) {
|
||||
case ERROR_IO_PENDING:
|
||||
wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe: connection in "
|
||||
"progress");
|
||||
break;
|
||||
case ERROR_PIPE_CONNECTED:
|
||||
wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe: already "
|
||||
"connected");
|
||||
if (SetEvent(dst->overlap.hEvent))
|
||||
break;
|
||||
/* fall through */
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe error: %d",
|
||||
(int) err);
|
||||
CloseHandle(dst->pipe);
|
||||
os_free(dst);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dst->next = priv->ctrl_dst;
|
||||
if (dst->next)
|
||||
dst->next->prev = dst;
|
||||
priv->ctrl_dst = dst;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
global_close_pipe(dst);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static void global_close_pipe(struct wpa_global_dst *dst)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "CTRL: close pipe %p", dst);
|
||||
|
||||
if (dst->overlap.hEvent) {
|
||||
eloop_unregister_event(dst->overlap.hEvent,
|
||||
sizeof(dst->overlap.hEvent));
|
||||
CloseHandle(dst->overlap.hEvent);
|
||||
}
|
||||
|
||||
if (dst->pipe != INVALID_HANDLE_VALUE) {
|
||||
/*
|
||||
* Could use FlushFileBuffers() here to guarantee that all data
|
||||
* gets delivered to the client, but that can block, so let's
|
||||
* not do this for now.
|
||||
* FlushFileBuffers(dst->pipe);
|
||||
*/
|
||||
CloseHandle(dst->pipe);
|
||||
}
|
||||
|
||||
if (dst->prev)
|
||||
dst->prev->next = dst->next;
|
||||
else
|
||||
dst->priv->ctrl_dst = dst->next;
|
||||
if (dst->next)
|
||||
dst->next->prev = dst->prev;
|
||||
|
||||
os_free(dst->rsp_buf);
|
||||
os_free(dst);
|
||||
}
|
||||
|
||||
|
||||
static VOID WINAPI global_iface_write_completed(DWORD err, DWORD bytes,
|
||||
LPOVERLAPPED overlap)
|
||||
{
|
||||
struct wpa_global_dst *dst = (struct wpa_global_dst *) overlap;
|
||||
wpa_printf(MSG_DEBUG, "CTRL: Overlapped write completed: dst=%p "
|
||||
"err=%d bytes=%d", dst, (int) err, (int) bytes);
|
||||
if (err) {
|
||||
global_close_pipe(dst);
|
||||
return;
|
||||
}
|
||||
|
||||
os_free(dst->rsp_buf);
|
||||
dst->rsp_buf = NULL;
|
||||
|
||||
if (!ReadFileEx(dst->pipe, dst->req_buf, sizeof(dst->req_buf),
|
||||
&dst->overlap, global_iface_read_completed)) {
|
||||
wpa_printf(MSG_DEBUG, "CTRL: ReadFileEx failed: %d",
|
||||
(int) GetLastError());
|
||||
global_close_pipe(dst);
|
||||
/* FIX: if this was the pipe waiting for new global
|
||||
* connections, at this point there are no open global pipes..
|
||||
* Should try to open a new pipe.. */
|
||||
return;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "CTRL: Overlapped read started for %p", dst);
|
||||
}
|
||||
|
||||
|
||||
static void wpa_supplicant_global_iface_rx(struct wpa_global_dst *dst,
|
||||
size_t len)
|
||||
{
|
||||
struct wpa_global *global = dst->priv->global;
|
||||
char *reply = NULL, *send_buf;
|
||||
size_t reply_len = 0, send_len;
|
||||
char *buf = dst->req_buf;
|
||||
|
||||
dst->used = 1;
|
||||
if (len >= REQUEST_BUFSIZE)
|
||||
len = REQUEST_BUFSIZE - 1;
|
||||
buf[len] = '\0';
|
||||
|
||||
reply = wpa_supplicant_global_ctrl_iface_process(global, buf,
|
||||
&reply_len);
|
||||
if (reply) {
|
||||
send_buf = reply;
|
||||
send_len = reply_len;
|
||||
} else if (reply_len) {
|
||||
send_buf = "FAIL\n";
|
||||
send_len = 5;
|
||||
} else {
|
||||
os_free(dst->rsp_buf);
|
||||
dst->rsp_buf = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
os_free(dst->rsp_buf);
|
||||
dst->rsp_buf = os_memdup(send_buf, send_len);
|
||||
if (dst->rsp_buf == NULL) {
|
||||
global_close_pipe(dst);
|
||||
os_free(reply);
|
||||
return;
|
||||
}
|
||||
os_free(reply);
|
||||
|
||||
if (!WriteFileEx(dst->pipe, dst->rsp_buf, send_len, &dst->overlap,
|
||||
global_iface_write_completed)) {
|
||||
wpa_printf(MSG_DEBUG, "CTRL: WriteFileEx failed: %d",
|
||||
(int) GetLastError());
|
||||
global_close_pipe(dst);
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "CTRL: Overlapped write started for %p",
|
||||
dst);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static VOID WINAPI global_iface_read_completed(DWORD err, DWORD bytes,
|
||||
LPOVERLAPPED overlap)
|
||||
{
|
||||
struct wpa_global_dst *dst = (struct wpa_global_dst *) overlap;
|
||||
wpa_printf(MSG_DEBUG, "CTRL: Overlapped read completed: dst=%p err=%d "
|
||||
"bytes=%d", dst, (int) err, (int) bytes);
|
||||
if (err == 0 && bytes > 0)
|
||||
wpa_supplicant_global_iface_rx(dst, bytes);
|
||||
}
|
||||
|
||||
|
||||
static void wpa_supplicant_global_iface_receive(void *eloop_data,
|
||||
void *user_ctx)
|
||||
{
|
||||
struct wpa_global_dst *dst = eloop_data;
|
||||
struct ctrl_iface_global_priv *priv = dst->priv;
|
||||
DWORD bytes;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "CTRL: wpa_supplicant_global_iface_receive");
|
||||
ResetEvent(dst->overlap.hEvent);
|
||||
|
||||
if (!GetOverlappedResult(dst->pipe, &dst->overlap, &bytes, FALSE)) {
|
||||
wpa_printf(MSG_DEBUG, "CTRL: GetOverlappedResult failed: %d",
|
||||
(int) GetLastError());
|
||||
return;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "CTRL: GetOverlappedResult: New client "
|
||||
"connected");
|
||||
|
||||
/* Open a new named pipe for the next client. */
|
||||
if (global_open_pipe(priv) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "CTRL: global_open_pipe failed");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Use write completion function to start reading a command */
|
||||
global_iface_write_completed(0, 0, &dst->overlap);
|
||||
|
||||
global_flush_broken_pipes(priv);
|
||||
}
|
||||
|
||||
|
||||
struct ctrl_iface_global_priv *
|
||||
wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
|
||||
{
|
||||
struct ctrl_iface_global_priv *priv;
|
||||
|
||||
priv = os_zalloc(sizeof(*priv));
|
||||
if (priv == NULL)
|
||||
return NULL;
|
||||
priv->global = global;
|
||||
|
||||
if (global_open_pipe(priv) < 0) {
|
||||
os_free(priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return priv;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
|
||||
{
|
||||
while (priv->ctrl_dst)
|
||||
global_close_pipe(priv->ctrl_dst);
|
||||
os_free(priv);
|
||||
}
|
831
wpa_supplicant/ctrl_iface_udp.c
Normal file
831
wpa_supplicant/ctrl_iface_udp.c
Normal file
@ -0,0 +1,831 @@
|
||||
/*
|
||||
* WPA Supplicant / UDP socket -based control interface
|
||||
* Copyright (c) 2004-2020, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "eloop.h"
|
||||
#include "config.h"
|
||||
#include "eapol_supp/eapol_supp_sm.h"
|
||||
#include "wpa_supplicant_i.h"
|
||||
#include "ctrl_iface.h"
|
||||
#include "common/wpa_ctrl.h"
|
||||
|
||||
|
||||
#define COOKIE_LEN 8
|
||||
|
||||
/* Per-interface ctrl_iface */
|
||||
|
||||
/**
|
||||
* struct wpa_ctrl_dst - Internal data structure of control interface monitors
|
||||
*
|
||||
* This structure is used to store information about registered control
|
||||
* interface monitors into struct wpa_supplicant. This data is private to
|
||||
* ctrl_iface_udp.c and should not be touched directly from other files.
|
||||
*/
|
||||
struct wpa_ctrl_dst {
|
||||
struct wpa_ctrl_dst *next;
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
|
||||
struct sockaddr_in6 addr;
|
||||
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
struct sockaddr_in addr;
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
socklen_t addrlen;
|
||||
int debug_level;
|
||||
int errors;
|
||||
};
|
||||
|
||||
|
||||
struct ctrl_iface_priv {
|
||||
struct wpa_supplicant *wpa_s;
|
||||
int sock;
|
||||
struct wpa_ctrl_dst *ctrl_dst;
|
||||
u8 cookie[COOKIE_LEN];
|
||||
};
|
||||
|
||||
struct ctrl_iface_global_priv {
|
||||
int sock;
|
||||
struct wpa_ctrl_dst *ctrl_dst;
|
||||
u8 cookie[COOKIE_LEN];
|
||||
};
|
||||
|
||||
|
||||
static void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s,
|
||||
const char *ifname, int sock,
|
||||
struct wpa_ctrl_dst **head,
|
||||
int level, const char *buf,
|
||||
size_t len);
|
||||
|
||||
|
||||
static void wpas_ctrl_iface_free_dst(struct wpa_ctrl_dst *dst)
|
||||
{
|
||||
struct wpa_ctrl_dst *prev;
|
||||
|
||||
while (dst) {
|
||||
prev = dst;
|
||||
dst = dst->next;
|
||||
os_free(prev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int wpa_supplicant_ctrl_iface_attach(struct wpa_ctrl_dst **head,
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
|
||||
struct sockaddr_in6 *from,
|
||||
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
struct sockaddr_in *from,
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
socklen_t fromlen)
|
||||
{
|
||||
struct wpa_ctrl_dst *dst;
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
|
||||
char addr[INET6_ADDRSTRLEN];
|
||||
#endif /* CONFIG_UDP_IPV6 */
|
||||
|
||||
dst = os_zalloc(sizeof(*dst));
|
||||
if (dst == NULL)
|
||||
return -1;
|
||||
os_memcpy(&dst->addr, from, sizeof(*from));
|
||||
dst->addrlen = fromlen;
|
||||
dst->debug_level = MSG_INFO;
|
||||
dst->next = *head;
|
||||
*head = dst;
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
|
||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d",
|
||||
inet_ntop(AF_INET6, &from->sin6_addr, addr, sizeof(*from)),
|
||||
ntohs(from->sin6_port));
|
||||
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d",
|
||||
inet_ntoa(from->sin_addr), ntohs(from->sin_port));
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_supplicant_ctrl_iface_detach(struct wpa_ctrl_dst **head,
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
|
||||
struct sockaddr_in6 *from,
|
||||
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
struct sockaddr_in *from,
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
socklen_t fromlen)
|
||||
{
|
||||
struct wpa_ctrl_dst *dst, *prev = NULL;
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
|
||||
char addr[INET6_ADDRSTRLEN];
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
|
||||
dst = *head;
|
||||
while (dst) {
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
|
||||
if (from->sin6_port == dst->addr.sin6_port &&
|
||||
!os_memcmp(&from->sin6_addr, &dst->addr.sin6_addr,
|
||||
sizeof(from->sin6_addr))) {
|
||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached %s:%d",
|
||||
inet_ntop(AF_INET6, &from->sin6_addr, addr,
|
||||
sizeof(*from)),
|
||||
ntohs(from->sin6_port));
|
||||
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr &&
|
||||
from->sin_port == dst->addr.sin_port) {
|
||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached "
|
||||
"%s:%d", inet_ntoa(from->sin_addr),
|
||||
ntohs(from->sin_port));
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
if (prev == NULL)
|
||||
*head = dst->next;
|
||||
else
|
||||
prev->next = dst->next;
|
||||
os_free(dst);
|
||||
return 0;
|
||||
}
|
||||
prev = dst;
|
||||
dst = dst->next;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv,
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
|
||||
struct sockaddr_in6 *from,
|
||||
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
struct sockaddr_in *from,
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
socklen_t fromlen,
|
||||
char *level)
|
||||
{
|
||||
struct wpa_ctrl_dst *dst;
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
|
||||
char addr[INET6_ADDRSTRLEN];
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
|
||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
|
||||
|
||||
dst = priv->ctrl_dst;
|
||||
while (dst) {
|
||||
#if CONFIG_CTRL_IFACE_UDP_IPV6
|
||||
if (from->sin6_port == dst->addr.sin6_port &&
|
||||
!os_memcmp(&from->sin6_addr, &dst->addr.sin6_addr,
|
||||
sizeof(from->sin6_addr))) {
|
||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor level %s:%d",
|
||||
inet_ntop(AF_INET6, &from->sin6_addr, addr,
|
||||
sizeof(*from)),
|
||||
ntohs(from->sin6_port));
|
||||
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr &&
|
||||
from->sin_port == dst->addr.sin_port) {
|
||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor "
|
||||
"level %s:%d", inet_ntoa(from->sin_addr),
|
||||
ntohs(from->sin_port));
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
dst->debug_level = atoi(level);
|
||||
return 0;
|
||||
}
|
||||
dst = dst->next;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
wpa_supplicant_ctrl_iface_get_cookie(struct ctrl_iface_priv *priv,
|
||||
size_t *reply_len)
|
||||
{
|
||||
char *reply;
|
||||
reply = os_malloc(7 + 2 * COOKIE_LEN + 1);
|
||||
if (reply == NULL) {
|
||||
*reply_len = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os_memcpy(reply, "COOKIE=", 7);
|
||||
wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
|
||||
priv->cookie, COOKIE_LEN);
|
||||
|
||||
*reply_len = 7 + 2 * COOKIE_LEN;
|
||||
return reply;
|
||||
}
|
||||
|
||||
|
||||
static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
|
||||
void *sock_ctx)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = eloop_ctx;
|
||||
struct ctrl_iface_priv *priv = sock_ctx;
|
||||
char *buf, *pos;
|
||||
int res;
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
|
||||
struct sockaddr_in6 from;
|
||||
#ifndef CONFIG_CTRL_IFACE_UDP_REMOTE
|
||||
char addr[INET6_ADDRSTRLEN];
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
|
||||
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
struct sockaddr_in from;
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
socklen_t fromlen = sizeof(from);
|
||||
char *reply = NULL;
|
||||
size_t reply_len = 0;
|
||||
int new_attached = 0;
|
||||
u8 cookie[COOKIE_LEN];
|
||||
|
||||
buf = os_malloc(CTRL_IFACE_MAX_LEN + 1);
|
||||
if (!buf)
|
||||
return;
|
||||
res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN, 0,
|
||||
(struct sockaddr *) &from, &fromlen);
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
|
||||
strerror(errno));
|
||||
os_free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_CTRL_IFACE_UDP_REMOTE
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
|
||||
inet_ntop(AF_INET6, &from.sin6_addr, addr, sizeof(from));
|
||||
if (os_strcmp(addr, "::1")) {
|
||||
wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected source %s",
|
||||
addr);
|
||||
os_free(buf);
|
||||
return;
|
||||
}
|
||||
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) {
|
||||
/*
|
||||
* The OS networking stack is expected to drop this kind of
|
||||
* frames since the socket is bound to only localhost address.
|
||||
* Just in case, drop the frame if it is coming from any other
|
||||
* address.
|
||||
*/
|
||||
wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected "
|
||||
"source %s", inet_ntoa(from.sin_addr));
|
||||
os_free(buf);
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
|
||||
|
||||
if ((size_t) res > CTRL_IFACE_MAX_LEN) {
|
||||
wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated");
|
||||
os_free(buf);
|
||||
return;
|
||||
}
|
||||
buf[res] = '\0';
|
||||
|
||||
if (os_strcmp(buf, "GET_COOKIE") == 0) {
|
||||
reply = wpa_supplicant_ctrl_iface_get_cookie(priv, &reply_len);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Require that the client includes a prefix with the 'cookie' value
|
||||
* fetched with GET_COOKIE command. This is used to verify that the
|
||||
* client has access to a bidirectional link over UDP in order to
|
||||
* avoid attacks using forged localhost IP address even if the OS does
|
||||
* not block such frames from remote destinations.
|
||||
*/
|
||||
if (os_strncmp(buf, "COOKIE=", 7) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - "
|
||||
"drop request");
|
||||
os_free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the "
|
||||
"request - drop request");
|
||||
os_free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - "
|
||||
"drop request");
|
||||
os_free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
pos = buf + 7 + 2 * COOKIE_LEN;
|
||||
while (*pos == ' ')
|
||||
pos++;
|
||||
|
||||
if (os_strcmp(pos, "ATTACH") == 0) {
|
||||
if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst,
|
||||
&from, fromlen))
|
||||
reply_len = 1;
|
||||
else {
|
||||
new_attached = 1;
|
||||
reply_len = 2;
|
||||
}
|
||||
} else if (os_strcmp(pos, "DETACH") == 0) {
|
||||
if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst,
|
||||
&from, fromlen))
|
||||
reply_len = 1;
|
||||
else
|
||||
reply_len = 2;
|
||||
} else if (os_strncmp(pos, "LEVEL ", 6) == 0) {
|
||||
if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen,
|
||||
pos + 6))
|
||||
reply_len = 1;
|
||||
else
|
||||
reply_len = 2;
|
||||
} else {
|
||||
reply = wpa_supplicant_ctrl_iface_process(wpa_s, pos,
|
||||
&reply_len);
|
||||
}
|
||||
|
||||
done:
|
||||
if (reply) {
|
||||
sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
|
||||
fromlen);
|
||||
os_free(reply);
|
||||
} else if (reply_len == 1) {
|
||||
sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
|
||||
fromlen);
|
||||
} else if (reply_len == 2) {
|
||||
sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from,
|
||||
fromlen);
|
||||
}
|
||||
|
||||
os_free(buf);
|
||||
|
||||
if (new_attached)
|
||||
eapol_sm_notify_ctrl_attached(wpa_s->eapol);
|
||||
}
|
||||
|
||||
|
||||
static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
|
||||
enum wpa_msg_type type,
|
||||
const char *txt, size_t len)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = ctx;
|
||||
|
||||
if (!wpa_s)
|
||||
return;
|
||||
|
||||
if (type != WPA_MSG_NO_GLOBAL && wpa_s->global->ctrl_iface) {
|
||||
struct ctrl_iface_global_priv *priv = wpa_s->global->ctrl_iface;
|
||||
|
||||
if (priv->ctrl_dst) {
|
||||
wpa_supplicant_ctrl_iface_send(
|
||||
wpa_s,
|
||||
type != WPA_MSG_PER_INTERFACE ?
|
||||
NULL : wpa_s->ifname,
|
||||
priv->sock, &priv->ctrl_dst, level, txt, len);
|
||||
}
|
||||
}
|
||||
|
||||
if (type == WPA_MSG_ONLY_GLOBAL || !wpa_s->ctrl_iface)
|
||||
return;
|
||||
|
||||
wpa_supplicant_ctrl_iface_send(wpa_s, NULL, wpa_s->ctrl_iface->sock,
|
||||
&wpa_s->ctrl_iface->ctrl_dst,
|
||||
level, txt, len);
|
||||
}
|
||||
|
||||
|
||||
struct ctrl_iface_priv *
|
||||
wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
struct ctrl_iface_priv *priv;
|
||||
char port_str[40];
|
||||
int port = WPA_CTRL_IFACE_PORT;
|
||||
char *pos;
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
|
||||
struct sockaddr_in6 addr;
|
||||
int domain = PF_INET6;
|
||||
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
struct sockaddr_in addr;
|
||||
int domain = PF_INET;
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
|
||||
priv = os_zalloc(sizeof(*priv));
|
||||
if (priv == NULL)
|
||||
return NULL;
|
||||
priv->wpa_s = wpa_s;
|
||||
priv->sock = -1;
|
||||
os_get_random(priv->cookie, COOKIE_LEN);
|
||||
|
||||
if (wpa_s->conf->ctrl_interface == NULL)
|
||||
return priv;
|
||||
|
||||
pos = os_strstr(wpa_s->conf->ctrl_interface, "udp:");
|
||||
if (pos) {
|
||||
pos += 4;
|
||||
port = atoi(pos);
|
||||
if (port <= 0) {
|
||||
wpa_printf(MSG_ERROR, "Invalid ctrl_iface UDP port: %s",
|
||||
wpa_s->conf->ctrl_interface);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
priv->sock = socket(domain, SOCK_DGRAM, 0);
|
||||
if (priv->sock < 0) {
|
||||
wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
os_memset(&addr, 0, sizeof(addr));
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
|
||||
addr.sin6_family = AF_INET6;
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
|
||||
addr.sin6_addr = in6addr_any;
|
||||
#else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
|
||||
inet_pton(AF_INET6, "::1", &addr.sin6_addr);
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
|
||||
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
addr.sin_family = AF_INET;
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
#else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
|
||||
addr.sin_addr.s_addr = htonl((127 << 24) | 1);
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
try_again:
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
|
||||
addr.sin6_port = htons(port);
|
||||
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
addr.sin_port = htons(port);
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
port--;
|
||||
if ((WPA_CTRL_IFACE_PORT - port) < WPA_CTRL_IFACE_PORT_LIMIT)
|
||||
goto try_again;
|
||||
wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Update the ctrl_interface value to match the selected port */
|
||||
os_snprintf(port_str, sizeof(port_str), "udp:%d", port);
|
||||
os_free(wpa_s->conf->ctrl_interface);
|
||||
wpa_s->conf->ctrl_interface = os_strdup(port_str);
|
||||
if (!wpa_s->conf->ctrl_interface) {
|
||||
wpa_msg(wpa_s, MSG_ERROR, "Failed to malloc ctrl_interface");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
|
||||
wpa_msg(wpa_s, MSG_DEBUG, "ctrl_iface_init UDP port: %d", port);
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
|
||||
|
||||
eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive,
|
||||
wpa_s, priv);
|
||||
wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
|
||||
|
||||
return priv;
|
||||
|
||||
fail:
|
||||
if (priv->sock >= 0)
|
||||
close(priv->sock);
|
||||
os_free(priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
|
||||
struct ctrl_iface_priv *priv)
|
||||
{
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
if (priv->sock > -1) {
|
||||
eloop_unregister_read_sock(priv->sock);
|
||||
if (priv->ctrl_dst) {
|
||||
/*
|
||||
* Wait before closing the control socket if
|
||||
* there are any attached monitors in order to allow
|
||||
* them to receive any pending messages.
|
||||
*/
|
||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached "
|
||||
"monitors to receive messages");
|
||||
os_sleep(0, 100000);
|
||||
}
|
||||
close(priv->sock);
|
||||
priv->sock = -1;
|
||||
}
|
||||
|
||||
wpas_ctrl_iface_free_dst(priv->ctrl_dst);
|
||||
os_free(priv);
|
||||
}
|
||||
|
||||
|
||||
static void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s,
|
||||
const char *ifname, int sock,
|
||||
struct wpa_ctrl_dst **head,
|
||||
int level, const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct wpa_ctrl_dst *dst, *next;
|
||||
char levelstr[64];
|
||||
int idx;
|
||||
char *sbuf;
|
||||
int llen;
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
|
||||
char addr[INET6_ADDRSTRLEN];
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
|
||||
dst = *head;
|
||||
if (sock < 0 || dst == NULL)
|
||||
return;
|
||||
|
||||
if (ifname)
|
||||
os_snprintf(levelstr, sizeof(levelstr), "IFNAME=%s <%d>",
|
||||
ifname, level);
|
||||
else
|
||||
os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
|
||||
|
||||
llen = os_strlen(levelstr);
|
||||
sbuf = os_malloc(llen + len);
|
||||
if (sbuf == NULL)
|
||||
return;
|
||||
|
||||
os_memcpy(sbuf, levelstr, llen);
|
||||
os_memcpy(sbuf + llen, buf, len);
|
||||
|
||||
idx = 0;
|
||||
while (dst) {
|
||||
next = dst->next;
|
||||
if (level >= dst->debug_level) {
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
|
||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d",
|
||||
inet_ntop(AF_INET6, &dst->addr.sin6_addr,
|
||||
addr, sizeof(dst->addr)),
|
||||
ntohs(dst->addr.sin6_port));
|
||||
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d",
|
||||
inet_ntoa(dst->addr.sin_addr),
|
||||
ntohs(dst->addr.sin_port));
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
if (sendto(sock, sbuf, llen + len, 0,
|
||||
(struct sockaddr *) &dst->addr,
|
||||
sizeof(dst->addr)) < 0) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"sendto(CTRL_IFACE monitor): %s",
|
||||
strerror(errno));
|
||||
dst->errors++;
|
||||
if (dst->errors > 10) {
|
||||
wpa_supplicant_ctrl_iface_detach(
|
||||
head, &dst->addr,
|
||||
dst->addrlen);
|
||||
}
|
||||
} else
|
||||
dst->errors = 0;
|
||||
}
|
||||
idx++;
|
||||
dst = next;
|
||||
}
|
||||
os_free(sbuf);
|
||||
}
|
||||
|
||||
|
||||
void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor",
|
||||
priv->wpa_s->ifname);
|
||||
eloop_wait_for_read_sock(priv->sock);
|
||||
}
|
||||
|
||||
|
||||
/* Global ctrl_iface */
|
||||
|
||||
static char *
|
||||
wpa_supplicant_global_get_cookie(struct ctrl_iface_global_priv *priv,
|
||||
size_t *reply_len)
|
||||
{
|
||||
char *reply;
|
||||
reply = os_malloc(7 + 2 * COOKIE_LEN + 1);
|
||||
if (reply == NULL) {
|
||||
*reply_len = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os_memcpy(reply, "COOKIE=", 7);
|
||||
wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
|
||||
priv->cookie, COOKIE_LEN);
|
||||
|
||||
*reply_len = 7 + 2 * COOKIE_LEN;
|
||||
return reply;
|
||||
}
|
||||
|
||||
|
||||
static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
|
||||
void *sock_ctx)
|
||||
{
|
||||
struct wpa_global *global = eloop_ctx;
|
||||
struct ctrl_iface_global_priv *priv = sock_ctx;
|
||||
char *buf, *pos;
|
||||
int res;
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
|
||||
struct sockaddr_in6 from;
|
||||
#ifndef CONFIG_CTRL_IFACE_UDP_REMOTE
|
||||
char addr[INET6_ADDRSTRLEN];
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
|
||||
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
struct sockaddr_in from;
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
socklen_t fromlen = sizeof(from);
|
||||
char *reply = NULL;
|
||||
size_t reply_len;
|
||||
u8 cookie[COOKIE_LEN];
|
||||
|
||||
buf = os_malloc(CTRL_IFACE_MAX_LEN + 1);
|
||||
if (!buf)
|
||||
return;
|
||||
res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN, 0,
|
||||
(struct sockaddr *) &from, &fromlen);
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
|
||||
strerror(errno));
|
||||
os_free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_CTRL_IFACE_UDP_REMOTE
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
|
||||
inet_ntop(AF_INET6, &from.sin6_addr, addr, sizeof(from));
|
||||
if (os_strcmp(addr, "::1")) {
|
||||
wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected source %s",
|
||||
addr);
|
||||
os_free(buf);
|
||||
return;
|
||||
}
|
||||
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) {
|
||||
/*
|
||||
* The OS networking stack is expected to drop this kind of
|
||||
* frames since the socket is bound to only localhost address.
|
||||
* Just in case, drop the frame if it is coming from any other
|
||||
* address.
|
||||
*/
|
||||
wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected "
|
||||
"source %s", inet_ntoa(from.sin_addr));
|
||||
os_free(buf);
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
|
||||
|
||||
if ((size_t) res > CTRL_IFACE_MAX_LEN) {
|
||||
wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated");
|
||||
os_free(buf);
|
||||
return;
|
||||
}
|
||||
buf[res] = '\0';
|
||||
|
||||
if (os_strcmp(buf, "GET_COOKIE") == 0) {
|
||||
reply = wpa_supplicant_global_get_cookie(priv, &reply_len);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (os_strncmp(buf, "COOKIE=", 7) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - "
|
||||
"drop request");
|
||||
os_free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the "
|
||||
"request - drop request");
|
||||
os_free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - "
|
||||
"drop request");
|
||||
os_free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
pos = buf + 7 + 2 * COOKIE_LEN;
|
||||
while (*pos == ' ')
|
||||
pos++;
|
||||
|
||||
if (os_strcmp(pos, "ATTACH") == 0) {
|
||||
if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst,
|
||||
&from, fromlen))
|
||||
reply_len = 1;
|
||||
else
|
||||
reply_len = 2;
|
||||
} else if (os_strcmp(pos, "DETACH") == 0) {
|
||||
if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst,
|
||||
&from, fromlen))
|
||||
reply_len = 1;
|
||||
else
|
||||
reply_len = 2;
|
||||
} else {
|
||||
reply = wpa_supplicant_global_ctrl_iface_process(global, pos,
|
||||
&reply_len);
|
||||
}
|
||||
|
||||
done:
|
||||
if (reply) {
|
||||
sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
|
||||
fromlen);
|
||||
os_free(reply);
|
||||
} else if (reply_len == 1) {
|
||||
sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
|
||||
fromlen);
|
||||
} else if (reply_len == 2) {
|
||||
sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from,
|
||||
fromlen);
|
||||
}
|
||||
|
||||
os_free(buf);
|
||||
}
|
||||
|
||||
|
||||
struct ctrl_iface_global_priv *
|
||||
wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
|
||||
{
|
||||
struct ctrl_iface_global_priv *priv;
|
||||
struct sockaddr_in addr;
|
||||
char *pos;
|
||||
int port = WPA_GLOBAL_CTRL_IFACE_PORT;
|
||||
|
||||
priv = os_zalloc(sizeof(*priv));
|
||||
if (priv == NULL)
|
||||
return NULL;
|
||||
priv->sock = -1;
|
||||
os_get_random(priv->cookie, COOKIE_LEN);
|
||||
|
||||
if (global->params.ctrl_interface == NULL)
|
||||
return priv;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Global control interface '%s'",
|
||||
global->params.ctrl_interface);
|
||||
|
||||
pos = os_strstr(global->params.ctrl_interface, "udp:");
|
||||
if (pos) {
|
||||
pos += 4;
|
||||
port = atoi(pos);
|
||||
if (port <= 0) {
|
||||
wpa_printf(MSG_ERROR, "Invalid global ctrl UDP port %s",
|
||||
global->params.ctrl_interface);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
priv->sock = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (priv->sock < 0) {
|
||||
wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
os_memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
#else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
|
||||
addr.sin_addr.s_addr = htonl((127 << 24) | 1);
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
|
||||
try_again:
|
||||
addr.sin_port = htons(port);
|
||||
if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
port++;
|
||||
if ((port - WPA_GLOBAL_CTRL_IFACE_PORT) <
|
||||
WPA_GLOBAL_CTRL_IFACE_PORT_LIMIT && !pos)
|
||||
goto try_again;
|
||||
wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
|
||||
wpa_printf(MSG_DEBUG, "global_ctrl_iface_init UDP port: %d", port);
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
|
||||
|
||||
eloop_register_read_sock(priv->sock,
|
||||
wpa_supplicant_global_ctrl_iface_receive,
|
||||
global, priv);
|
||||
wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
|
||||
|
||||
return priv;
|
||||
|
||||
fail:
|
||||
if (priv->sock >= 0)
|
||||
close(priv->sock);
|
||||
os_free(priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
|
||||
{
|
||||
if (priv->sock >= 0) {
|
||||
eloop_unregister_read_sock(priv->sock);
|
||||
close(priv->sock);
|
||||
}
|
||||
|
||||
wpas_ctrl_iface_free_dst(priv->ctrl_dst);
|
||||
os_free(priv);
|
||||
}
|
1431
wpa_supplicant/ctrl_iface_unix.c
Normal file
1431
wpa_supplicant/ctrl_iface_unix.c
Normal file
File diff suppressed because it is too large
Load Diff
69
wpa_supplicant/dbus/Makefile
Normal file
69
wpa_supplicant/dbus/Makefile
Normal file
@ -0,0 +1,69 @@
|
||||
all: libwpadbus.a
|
||||
|
||||
clean:
|
||||
rm -f *~ *.o *.d *.gcno *.gcda *.gcov
|
||||
rm -f libwpadbus.a
|
||||
|
||||
install:
|
||||
@echo Nothing to be made.
|
||||
|
||||
ifndef CC
|
||||
CC=gcc
|
||||
endif
|
||||
|
||||
ifndef CFLAGS
|
||||
CFLAGS = -MMD -O2 -Wall -g
|
||||
endif
|
||||
|
||||
PKG_CONFIG ?= pkg-config
|
||||
CFLAGS += -I../../src -I../../src/utils
|
||||
|
||||
|
||||
Q=@
|
||||
E=echo
|
||||
ifeq ($(V), 1)
|
||||
Q=
|
||||
E=true
|
||||
endif
|
||||
|
||||
%.o: %.c
|
||||
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
|
||||
@$(E) " CC " $<
|
||||
|
||||
|
||||
ifdef CONFIG_WPS
|
||||
CFLAGS += -DCONFIG_WPS
|
||||
endif
|
||||
|
||||
CFLAGS += -DCONFIG_CTRL_IFACE_DBUS_NEW
|
||||
|
||||
ifndef DBUS_LIBS
|
||||
DBUS_LIBS := $(shell $(PKG_CONFIG) --libs dbus-1)
|
||||
endif
|
||||
ifndef DBUS_INCLUDE
|
||||
DBUS_INCLUDE := $(shell $(PKG_CONFIG) --cflags dbus-1)
|
||||
endif
|
||||
ifdef CONFIG_CTRL_IFACE_DBUS_INTRO
|
||||
CFLAGS += -DCONFIG_CTRL_IFACE_DBUS_INTRO
|
||||
DBUS_INCLUDE += $(shell xml2-config --cflags)
|
||||
DBUS_LIBS += $(shell xml2-config --libs)
|
||||
endif
|
||||
|
||||
CFLAGS += $(DBUS_INCLUDE)
|
||||
|
||||
LIB_OBJS= \
|
||||
dbus_common.o \
|
||||
dbus_new.o \
|
||||
dbus_new_handlers.o \
|
||||
dbus_new_helpers.o \
|
||||
dbus_new_introspect.o \
|
||||
dbus_dict_helpers.o
|
||||
|
||||
ifdef CONFIG_WPS
|
||||
LIB_OBJS += dbus_new_handlers_wps.o
|
||||
endif
|
||||
|
||||
libwpadbus.a: $(LIB_OBJS)
|
||||
$(AR) crT $@ $?
|
||||
|
||||
-include $(OBJS:%.o=%.d)
|
17
wpa_supplicant/dbus/dbus-wpa_supplicant.conf
Normal file
17
wpa_supplicant/dbus/dbus-wpa_supplicant.conf
Normal file
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE busconfig PUBLIC
|
||||
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
||||
<busconfig>
|
||||
<policy user="root">
|
||||
<allow own="fi.w1.wpa_supplicant1"/>
|
||||
|
||||
<allow send_destination="fi.w1.wpa_supplicant1"/>
|
||||
<allow send_interface="fi.w1.wpa_supplicant1"/>
|
||||
<allow receive_sender="fi.w1.wpa_supplicant1" receive_type="signal"/>
|
||||
</policy>
|
||||
<policy context="default">
|
||||
<deny own="fi.w1.wpa_supplicant1"/>
|
||||
<deny send_destination="fi.w1.wpa_supplicant1"/>
|
||||
<deny receive_sender="fi.w1.wpa_supplicant1" receive_type="signal"/>
|
||||
</policy>
|
||||
</busconfig>
|
373
wpa_supplicant/dbus/dbus_common.c
Normal file
373
wpa_supplicant/dbus/dbus_common.c
Normal file
@ -0,0 +1,373 @@
|
||||
/*
|
||||
* wpa_supplicant D-Bus control interface - common functionality
|
||||
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
|
||||
* Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
|
||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "dbus_common.h"
|
||||
#include "dbus_common_i.h"
|
||||
#include "dbus_new.h"
|
||||
#include "../wpa_supplicant_i.h"
|
||||
|
||||
|
||||
#ifndef SIGPOLL
|
||||
#ifdef SIGIO
|
||||
/*
|
||||
* If we do not have SIGPOLL, try to use SIGIO instead. This is needed for
|
||||
* FreeBSD.
|
||||
*/
|
||||
#define SIGPOLL SIGIO
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
static void dispatch_data(DBusConnection *con)
|
||||
{
|
||||
while (dbus_connection_get_dispatch_status(con) ==
|
||||
DBUS_DISPATCH_DATA_REMAINS)
|
||||
dbus_connection_dispatch(con);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* dispatch_initial_dbus_messages - Dispatch initial dbus messages after
|
||||
* claiming bus name
|
||||
* @eloop_ctx: the DBusConnection to dispatch on
|
||||
* @timeout_ctx: unused
|
||||
*
|
||||
* If clients are quick to notice that service claimed its bus name,
|
||||
* there may have been messages that came in before initialization was
|
||||
* all finished. Dispatch those here.
|
||||
*/
|
||||
static void dispatch_initial_dbus_messages(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
DBusConnection *con = eloop_ctx;
|
||||
dispatch_data(con);
|
||||
}
|
||||
|
||||
|
||||
static void process_watch(struct wpas_dbus_priv *priv,
|
||||
DBusWatch *watch, eloop_event_type type)
|
||||
{
|
||||
dbus_connection_ref(priv->con);
|
||||
|
||||
priv->should_dispatch = 0;
|
||||
|
||||
if (type == EVENT_TYPE_READ)
|
||||
dbus_watch_handle(watch, DBUS_WATCH_READABLE);
|
||||
else if (type == EVENT_TYPE_WRITE)
|
||||
dbus_watch_handle(watch, DBUS_WATCH_WRITABLE);
|
||||
else if (type == EVENT_TYPE_EXCEPTION)
|
||||
dbus_watch_handle(watch, DBUS_WATCH_ERROR);
|
||||
|
||||
if (priv->should_dispatch) {
|
||||
dispatch_data(priv->con);
|
||||
priv->should_dispatch = 0;
|
||||
}
|
||||
|
||||
dbus_connection_unref(priv->con);
|
||||
}
|
||||
|
||||
|
||||
static void process_watch_exception(int sock, void *eloop_ctx, void *sock_ctx)
|
||||
{
|
||||
process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_EXCEPTION);
|
||||
}
|
||||
|
||||
|
||||
static void process_watch_read(int sock, void *eloop_ctx, void *sock_ctx)
|
||||
{
|
||||
process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_READ);
|
||||
}
|
||||
|
||||
|
||||
static void process_watch_write(int sock, void *eloop_ctx, void *sock_ctx)
|
||||
{
|
||||
process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_WRITE);
|
||||
}
|
||||
|
||||
|
||||
static dbus_bool_t add_watch(DBusWatch *watch, void *data)
|
||||
{
|
||||
struct wpas_dbus_priv *priv = data;
|
||||
unsigned int flags;
|
||||
int fd;
|
||||
|
||||
if (!dbus_watch_get_enabled(watch))
|
||||
return TRUE;
|
||||
|
||||
flags = dbus_watch_get_flags(watch);
|
||||
fd = dbus_watch_get_unix_fd(watch);
|
||||
|
||||
if (eloop_register_sock(fd, EVENT_TYPE_EXCEPTION,
|
||||
process_watch_exception, priv, watch) < 0)
|
||||
return FALSE;
|
||||
|
||||
if ((flags & DBUS_WATCH_READABLE) &&
|
||||
eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read,
|
||||
priv, watch) < 0)
|
||||
return FALSE;
|
||||
if ((flags & DBUS_WATCH_WRITABLE) &&
|
||||
eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write,
|
||||
priv, watch) < 0)
|
||||
return FALSE;
|
||||
|
||||
dbus_watch_set_data(watch, priv, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void remove_watch(DBusWatch *watch, void *data)
|
||||
{
|
||||
unsigned int flags;
|
||||
int fd;
|
||||
|
||||
flags = dbus_watch_get_flags(watch);
|
||||
fd = dbus_watch_get_unix_fd(watch);
|
||||
|
||||
eloop_unregister_sock(fd, EVENT_TYPE_EXCEPTION);
|
||||
|
||||
if (flags & DBUS_WATCH_READABLE)
|
||||
eloop_unregister_sock(fd, EVENT_TYPE_READ);
|
||||
if (flags & DBUS_WATCH_WRITABLE)
|
||||
eloop_unregister_sock(fd, EVENT_TYPE_WRITE);
|
||||
|
||||
dbus_watch_set_data(watch, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void watch_toggled(DBusWatch *watch, void *data)
|
||||
{
|
||||
if (dbus_watch_get_enabled(watch))
|
||||
add_watch(watch, data);
|
||||
else
|
||||
remove_watch(watch, data);
|
||||
}
|
||||
|
||||
|
||||
static void process_timeout(void *eloop_ctx, void *sock_ctx)
|
||||
{
|
||||
DBusTimeout *timeout = sock_ctx;
|
||||
dbus_timeout_handle(timeout);
|
||||
}
|
||||
|
||||
|
||||
static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data)
|
||||
{
|
||||
struct wpas_dbus_priv *priv = data;
|
||||
|
||||
if (!dbus_timeout_get_enabled(timeout))
|
||||
return TRUE;
|
||||
|
||||
eloop_register_timeout(0, dbus_timeout_get_interval(timeout) * 1000,
|
||||
process_timeout, priv, timeout);
|
||||
|
||||
dbus_timeout_set_data(timeout, priv, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void remove_timeout(DBusTimeout *timeout, void *data)
|
||||
{
|
||||
struct wpas_dbus_priv *priv = data;
|
||||
|
||||
eloop_cancel_timeout(process_timeout, priv, timeout);
|
||||
dbus_timeout_set_data(timeout, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void timeout_toggled(DBusTimeout *timeout, void *data)
|
||||
{
|
||||
if (dbus_timeout_get_enabled(timeout))
|
||||
add_timeout(timeout, data);
|
||||
else
|
||||
remove_timeout(timeout, data);
|
||||
}
|
||||
|
||||
|
||||
static void process_wakeup_main(int sig, void *signal_ctx)
|
||||
{
|
||||
struct wpas_dbus_priv *priv = signal_ctx;
|
||||
|
||||
if (sig != SIGPOLL || !priv->con)
|
||||
return;
|
||||
|
||||
if (dbus_connection_get_dispatch_status(priv->con) !=
|
||||
DBUS_DISPATCH_DATA_REMAINS)
|
||||
return;
|
||||
|
||||
/* Only dispatch once - we do not want to starve other events */
|
||||
dbus_connection_ref(priv->con);
|
||||
dbus_connection_dispatch(priv->con);
|
||||
dbus_connection_unref(priv->con);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wakeup_main - Attempt to wake our mainloop up
|
||||
* @data: dbus control interface private data
|
||||
*
|
||||
* Try to wake up the main eloop so it will process
|
||||
* dbus events that may have happened.
|
||||
*/
|
||||
static void wakeup_main(void *data)
|
||||
{
|
||||
struct wpas_dbus_priv *priv = data;
|
||||
|
||||
/* Use SIGPOLL to break out of the eloop select() */
|
||||
raise(SIGPOLL);
|
||||
priv->should_dispatch = 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* integrate_with_eloop - Register our mainloop integration with dbus
|
||||
* @connection: connection to the system message bus
|
||||
* @priv: a dbus control interface data structure
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
static int integrate_with_eloop(struct wpas_dbus_priv *priv)
|
||||
{
|
||||
if (!dbus_connection_set_watch_functions(priv->con, add_watch,
|
||||
remove_watch, watch_toggled,
|
||||
priv, NULL) ||
|
||||
!dbus_connection_set_timeout_functions(priv->con, add_timeout,
|
||||
remove_timeout,
|
||||
timeout_toggled, priv,
|
||||
NULL)) {
|
||||
wpa_printf(MSG_ERROR, "dbus: Failed to set callback functions");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (eloop_register_signal(SIGPOLL, process_wakeup_main, priv))
|
||||
return -1;
|
||||
dbus_connection_set_wakeup_main_function(priv->con, wakeup_main,
|
||||
priv, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static DBusHandlerResult disconnect_filter(DBusConnection *conn,
|
||||
DBusMessage *message, void *data)
|
||||
{
|
||||
struct wpas_dbus_priv *priv = data;
|
||||
|
||||
if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL,
|
||||
"Disconnected")) {
|
||||
wpa_printf(MSG_DEBUG, "dbus: bus disconnected, terminating");
|
||||
dbus_connection_set_exit_on_disconnect(conn, FALSE);
|
||||
wpa_supplicant_terminate_proc(priv->global);
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
} else
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
static int wpas_dbus_init_common(struct wpas_dbus_priv *priv)
|
||||
{
|
||||
DBusError error;
|
||||
int ret = 0;
|
||||
|
||||
/* Get a reference to the system bus */
|
||||
dbus_error_init(&error);
|
||||
priv->con = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
|
||||
if (priv->con) {
|
||||
dbus_connection_add_filter(priv->con, disconnect_filter, priv,
|
||||
NULL);
|
||||
} else {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"dbus: Could not acquire the system bus: %s - %s",
|
||||
error.name, error.message);
|
||||
ret = -1;
|
||||
}
|
||||
dbus_error_free(&error);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int wpas_dbus_init_common_finish(struct wpas_dbus_priv *priv)
|
||||
{
|
||||
/* Tell dbus about our mainloop integration functions */
|
||||
integrate_with_eloop(priv);
|
||||
|
||||
/*
|
||||
* Dispatch initial DBus messages that may have come in since the bus
|
||||
* name was claimed above. Happens when clients are quick to notice the
|
||||
* service.
|
||||
*
|
||||
* FIXME: is there a better solution to this problem?
|
||||
*/
|
||||
eloop_register_timeout(0, 50, dispatch_initial_dbus_messages,
|
||||
priv->con, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void wpas_dbus_deinit_common(struct wpas_dbus_priv *priv)
|
||||
{
|
||||
if (priv->con) {
|
||||
eloop_cancel_timeout(dispatch_initial_dbus_messages,
|
||||
priv->con, NULL);
|
||||
eloop_cancel_timeout(process_timeout, priv, ELOOP_ALL_CTX);
|
||||
|
||||
dbus_connection_set_watch_functions(priv->con, NULL, NULL,
|
||||
NULL, NULL, NULL);
|
||||
dbus_connection_set_timeout_functions(priv->con, NULL, NULL,
|
||||
NULL, NULL, NULL);
|
||||
dbus_connection_remove_filter(priv->con, disconnect_filter,
|
||||
priv);
|
||||
|
||||
dbus_connection_unref(priv->con);
|
||||
}
|
||||
|
||||
os_free(priv);
|
||||
}
|
||||
|
||||
|
||||
struct wpas_dbus_priv * wpas_dbus_init(struct wpa_global *global)
|
||||
{
|
||||
struct wpas_dbus_priv *priv;
|
||||
|
||||
priv = os_zalloc(sizeof(*priv));
|
||||
if (priv == NULL)
|
||||
return NULL;
|
||||
priv->global = global;
|
||||
|
||||
if (wpas_dbus_init_common(priv) < 0 ||
|
||||
#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
|
||||
wpas_dbus_ctrl_iface_init(priv) < 0 ||
|
||||
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
|
||||
wpas_dbus_init_common_finish(priv) < 0) {
|
||||
wpas_dbus_deinit(priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return priv;
|
||||
}
|
||||
|
||||
|
||||
void wpas_dbus_deinit(struct wpas_dbus_priv *priv)
|
||||
{
|
||||
if (priv == NULL)
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
|
||||
wpas_dbus_ctrl_iface_deinit(priv);
|
||||
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
|
||||
|
||||
wpas_dbus_deinit_common(priv);
|
||||
}
|
20
wpa_supplicant/dbus/dbus_common.h
Normal file
20
wpa_supplicant/dbus/dbus_common.h
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* wpa_supplicant D-Bus control interface - common definitions
|
||||
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
|
||||
* Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
|
||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef DBUS_COMMON_H
|
||||
#define DBUS_COMMON_H
|
||||
|
||||
struct wpas_dbus_priv;
|
||||
struct wpa_global;
|
||||
|
||||
struct wpas_dbus_priv * wpas_dbus_init(struct wpa_global *global);
|
||||
void wpas_dbus_deinit(struct wpas_dbus_priv *priv);
|
||||
|
||||
#endif /* DBUS_COMMON_H */
|
34
wpa_supplicant/dbus/dbus_common_i.h
Normal file
34
wpa_supplicant/dbus/dbus_common_i.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* wpa_supplicant D-Bus control interface - internal definitions
|
||||
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
|
||||
* Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
|
||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef DBUS_COMMON_I_H
|
||||
#define DBUS_COMMON_I_H
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
struct wpa_dbus_property_desc;
|
||||
|
||||
struct wpas_dbus_priv {
|
||||
DBusConnection *con;
|
||||
int should_dispatch;
|
||||
struct wpa_global *global;
|
||||
u32 next_objid;
|
||||
int dbus_new_initialized;
|
||||
|
||||
#if defined(CONFIG_CTRL_IFACE_DBUS_NEW)
|
||||
struct wpa_dbus_property_desc *all_interface_properties;
|
||||
int globals_start;
|
||||
#if defined(CONFIG_AP)
|
||||
int dbus_noc_refcnt;
|
||||
#endif /* CONFIG_AP */
|
||||
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
|
||||
};
|
||||
|
||||
#endif /* DBUS_COMMON_I_H */
|
1061
wpa_supplicant/dbus/dbus_dict_helpers.c
Normal file
1061
wpa_supplicant/dbus/dbus_dict_helpers.c
Normal file
File diff suppressed because it is too large
Load Diff
152
wpa_supplicant/dbus/dbus_dict_helpers.h
Normal file
152
wpa_supplicant/dbus/dbus_dict_helpers.h
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* WPA Supplicant / dbus-based control interface
|
||||
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef DBUS_DICT_HELPERS_H
|
||||
#define DBUS_DICT_HELPERS_H
|
||||
|
||||
#include "wpabuf.h"
|
||||
|
||||
/*
|
||||
* Adding a dict to a DBusMessage
|
||||
*/
|
||||
|
||||
dbus_bool_t wpa_dbus_dict_open_write(DBusMessageIter *iter,
|
||||
DBusMessageIter *iter_dict);
|
||||
|
||||
dbus_bool_t wpa_dbus_dict_close_write(DBusMessageIter *iter,
|
||||
DBusMessageIter *iter_dict);
|
||||
|
||||
const char * wpa_dbus_type_as_string(const int type);
|
||||
|
||||
dbus_bool_t wpa_dbus_dict_append_string(DBusMessageIter *iter_dict,
|
||||
const char *key, const char *value);
|
||||
|
||||
dbus_bool_t wpa_dbus_dict_append_bool(DBusMessageIter *iter_dict,
|
||||
const char *key,
|
||||
const dbus_bool_t value);
|
||||
|
||||
dbus_bool_t wpa_dbus_dict_append_int16(DBusMessageIter *iter_dict,
|
||||
const char *key,
|
||||
const dbus_int16_t value);
|
||||
|
||||
dbus_bool_t wpa_dbus_dict_append_uint16(DBusMessageIter *iter_dict,
|
||||
const char *key,
|
||||
const dbus_uint16_t value);
|
||||
|
||||
dbus_bool_t wpa_dbus_dict_append_int32(DBusMessageIter *iter_dict,
|
||||
const char *key,
|
||||
const dbus_int32_t value);
|
||||
|
||||
dbus_bool_t wpa_dbus_dict_append_uint32(DBusMessageIter *iter_dict,
|
||||
const char *key,
|
||||
const dbus_uint32_t value);
|
||||
|
||||
dbus_bool_t wpa_dbus_dict_append_object_path(DBusMessageIter *iter_dict,
|
||||
const char *key,
|
||||
const char *value);
|
||||
|
||||
dbus_bool_t wpa_dbus_dict_append_byte_array(DBusMessageIter *iter_dict,
|
||||
const char *key,
|
||||
const char *value,
|
||||
const dbus_uint32_t value_len);
|
||||
|
||||
/* Manual construction and addition of array elements */
|
||||
dbus_bool_t wpa_dbus_dict_begin_array(DBusMessageIter *iter_dict,
|
||||
const char *key, const char *type,
|
||||
DBusMessageIter *iter_dict_entry,
|
||||
DBusMessageIter *iter_dict_val,
|
||||
DBusMessageIter *iter_array);
|
||||
|
||||
dbus_bool_t wpa_dbus_dict_begin_string_array(DBusMessageIter *iter_dict,
|
||||
const char *key,
|
||||
DBusMessageIter *iter_dict_entry,
|
||||
DBusMessageIter *iter_dict_val,
|
||||
DBusMessageIter *iter_array);
|
||||
|
||||
dbus_bool_t wpa_dbus_dict_string_array_add_element(DBusMessageIter *iter_array,
|
||||
const char *elem);
|
||||
|
||||
dbus_bool_t wpa_dbus_dict_bin_array_add_element(DBusMessageIter *iter_array,
|
||||
const u8 *value,
|
||||
size_t value_len);
|
||||
|
||||
dbus_bool_t wpa_dbus_dict_end_array(DBusMessageIter *iter_dict,
|
||||
DBusMessageIter *iter_dict_entry,
|
||||
DBusMessageIter *iter_dict_val,
|
||||
DBusMessageIter *iter_array);
|
||||
|
||||
static inline dbus_bool_t
|
||||
wpa_dbus_dict_end_string_array(DBusMessageIter *iter_dict,
|
||||
DBusMessageIter *iter_dict_entry,
|
||||
DBusMessageIter *iter_dict_val,
|
||||
DBusMessageIter *iter_array)
|
||||
{
|
||||
return wpa_dbus_dict_end_array(iter_dict, iter_dict_entry,
|
||||
iter_dict_val, iter_array);
|
||||
}
|
||||
|
||||
/* Convenience function to add a whole string list */
|
||||
dbus_bool_t wpa_dbus_dict_append_string_array(DBusMessageIter *iter_dict,
|
||||
const char *key,
|
||||
const char **items,
|
||||
const dbus_uint32_t num_items);
|
||||
|
||||
dbus_bool_t wpa_dbus_dict_append_wpabuf_array(DBusMessageIter *iter_dict,
|
||||
const char *key,
|
||||
const struct wpabuf **items,
|
||||
const dbus_uint32_t num_items);
|
||||
|
||||
/*
|
||||
* Reading a dict from a DBusMessage
|
||||
*/
|
||||
|
||||
/*
|
||||
* Used only in struct wpa_dbus_dict_entry::array_type internally to identify
|
||||
* special binary array case.
|
||||
*/
|
||||
#define WPAS_DBUS_TYPE_BINARRAY ((int) '@')
|
||||
|
||||
struct wpa_dbus_dict_entry {
|
||||
int type; /** the dbus type of the dict entry's value */
|
||||
int array_type; /** the dbus type of the array elements if the dict
|
||||
entry value contains an array, or the special
|
||||
WPAS_DBUS_TYPE_BINARRAY */
|
||||
const char *key; /** key of the dict entry */
|
||||
|
||||
/** Possible values of the property */
|
||||
union {
|
||||
char *str_value;
|
||||
char byte_value;
|
||||
dbus_bool_t bool_value;
|
||||
dbus_int16_t int16_value;
|
||||
dbus_uint16_t uint16_value;
|
||||
dbus_int32_t int32_value;
|
||||
dbus_uint32_t uint32_value;
|
||||
dbus_int64_t int64_value;
|
||||
dbus_uint64_t uint64_value;
|
||||
double double_value;
|
||||
char *bytearray_value;
|
||||
char **strarray_value;
|
||||
struct wpabuf **binarray_value;
|
||||
};
|
||||
dbus_uint32_t array_len; /** length of the array if the dict entry's
|
||||
value contains an array */
|
||||
};
|
||||
|
||||
dbus_bool_t wpa_dbus_dict_open_read(DBusMessageIter *iter,
|
||||
DBusMessageIter *iter_dict,
|
||||
DBusError *error);
|
||||
|
||||
dbus_bool_t wpa_dbus_dict_get_entry(DBusMessageIter *iter_dict,
|
||||
struct wpa_dbus_dict_entry *entry);
|
||||
|
||||
dbus_bool_t wpa_dbus_dict_has_dict_entry(DBusMessageIter *iter_dict);
|
||||
|
||||
void wpa_dbus_dict_entry_clear(struct wpa_dbus_dict_entry *entry);
|
||||
|
||||
#endif /* DBUS_DICT_HELPERS_H */
|
5105
wpa_supplicant/dbus/dbus_new.c
Normal file
5105
wpa_supplicant/dbus/dbus_new.c
Normal file
File diff suppressed because it is too large
Load Diff
648
wpa_supplicant/dbus/dbus_new.h
Normal file
648
wpa_supplicant/dbus/dbus_new.h
Normal file
@ -0,0 +1,648 @@
|
||||
/*
|
||||
* WPA Supplicant / dbus-based control interface
|
||||
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
|
||||
* Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef CTRL_IFACE_DBUS_NEW_H
|
||||
#define CTRL_IFACE_DBUS_NEW_H
|
||||
|
||||
#include "common/defs.h"
|
||||
#include "p2p/p2p.h"
|
||||
|
||||
struct wpa_global;
|
||||
struct wpa_supplicant;
|
||||
struct wpa_ssid;
|
||||
struct wpa_cred;
|
||||
struct wpa_bss;
|
||||
struct wps_event_m2d;
|
||||
struct wps_event_fail;
|
||||
struct wps_credential;
|
||||
|
||||
enum wpas_dbus_prop {
|
||||
WPAS_DBUS_PROP_AP_SCAN,
|
||||
WPAS_DBUS_PROP_SCANNING,
|
||||
WPAS_DBUS_PROP_STATE,
|
||||
WPAS_DBUS_PROP_CURRENT_BSS,
|
||||
WPAS_DBUS_PROP_CURRENT_NETWORK,
|
||||
WPAS_DBUS_PROP_CURRENT_AUTH_MODE,
|
||||
WPAS_DBUS_PROP_BSSS,
|
||||
WPAS_DBUS_PROP_STATIONS,
|
||||
WPAS_DBUS_PROP_DISCONNECT_REASON,
|
||||
WPAS_DBUS_PROP_AUTH_STATUS_CODE,
|
||||
WPAS_DBUS_PROP_ASSOC_STATUS_CODE,
|
||||
WPAS_DBUS_PROP_ROAM_TIME,
|
||||
WPAS_DBUS_PROP_ROAM_COMPLETE,
|
||||
WPAS_DBUS_PROP_SESSION_LENGTH,
|
||||
WPAS_DBUS_PROP_BSS_TM_STATUS,
|
||||
};
|
||||
|
||||
enum wpas_dbus_bss_prop {
|
||||
WPAS_DBUS_BSS_PROP_SIGNAL,
|
||||
WPAS_DBUS_BSS_PROP_FREQ,
|
||||
WPAS_DBUS_BSS_PROP_MODE,
|
||||
WPAS_DBUS_BSS_PROP_PRIVACY,
|
||||
WPAS_DBUS_BSS_PROP_RATES,
|
||||
WPAS_DBUS_BSS_PROP_WPA,
|
||||
WPAS_DBUS_BSS_PROP_RSN,
|
||||
WPAS_DBUS_BSS_PROP_WPS,
|
||||
WPAS_DBUS_BSS_PROP_IES,
|
||||
WPAS_DBUS_BSS_PROP_AGE,
|
||||
};
|
||||
|
||||
enum wpas_dbus_sta_prop {
|
||||
WPAS_DBUS_STA_PROP_ADDRESS,
|
||||
};
|
||||
|
||||
#define WPAS_DBUS_OBJECT_PATH_MAX 150
|
||||
|
||||
#define WPAS_DBUS_NEW_SERVICE "fi.w1.wpa_supplicant1"
|
||||
#define WPAS_DBUS_NEW_PATH "/fi/w1/wpa_supplicant1"
|
||||
#define WPAS_DBUS_NEW_INTERFACE "fi.w1.wpa_supplicant1"
|
||||
|
||||
#define WPAS_DBUS_NEW_PATH_INTERFACES WPAS_DBUS_NEW_PATH "/Interfaces"
|
||||
#define WPAS_DBUS_NEW_IFACE_INTERFACE WPAS_DBUS_NEW_INTERFACE ".Interface"
|
||||
#define WPAS_DBUS_NEW_IFACE_WPS WPAS_DBUS_NEW_IFACE_INTERFACE ".WPS"
|
||||
|
||||
#define WPAS_DBUS_NEW_NETWORKS_PART "Networks"
|
||||
#define WPAS_DBUS_NEW_IFACE_NETWORK WPAS_DBUS_NEW_INTERFACE ".Network"
|
||||
|
||||
#define WPAS_DBUS_NEW_BSSIDS_PART "BSSs"
|
||||
#define WPAS_DBUS_NEW_IFACE_BSS WPAS_DBUS_NEW_INTERFACE ".BSS"
|
||||
|
||||
#define WPAS_DBUS_NEW_STAS_PART "Stations"
|
||||
#define WPAS_DBUS_NEW_IFACE_STA WPAS_DBUS_NEW_INTERFACE ".Station"
|
||||
|
||||
#define WPAS_DBUS_NEW_IFACE_P2PDEVICE \
|
||||
WPAS_DBUS_NEW_IFACE_INTERFACE ".P2PDevice"
|
||||
|
||||
#define WPAS_DBUS_NEW_IFACE_MESH WPAS_DBUS_NEW_IFACE_INTERFACE ".Mesh"
|
||||
|
||||
/*
|
||||
* Groups correspond to P2P groups where this device is a GO (owner)
|
||||
*/
|
||||
#define WPAS_DBUS_NEW_P2P_GROUPS_PART "Groups"
|
||||
#define WPAS_DBUS_NEW_IFACE_P2P_GROUP WPAS_DBUS_NEW_INTERFACE ".Group"
|
||||
|
||||
/*
|
||||
* Different dbus object for persistent groups so they do not get confused
|
||||
* with regular (configured) network objects.
|
||||
*/
|
||||
#define WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "PersistentGroups"
|
||||
#define WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP \
|
||||
WPAS_DBUS_NEW_INTERFACE ".PersistentGroup"
|
||||
|
||||
#define WPAS_DBUS_NEW_P2P_PEERS_PART "Peers"
|
||||
#define WPAS_DBUS_NEW_IFACE_P2P_PEER WPAS_DBUS_NEW_INTERFACE ".Peer"
|
||||
|
||||
#define WPAS_DBUS_NEW_CREDENTIALS_PART "Credentials"
|
||||
#define WPAS_DBUS_NEW_IFACE_CREDENTIAL WPAS_DBUS_NEW_INTERFACE ".Credential"
|
||||
|
||||
/* Top-level Errors */
|
||||
#define WPAS_DBUS_ERROR_UNKNOWN_ERROR \
|
||||
WPAS_DBUS_NEW_INTERFACE ".UnknownError"
|
||||
#define WPAS_DBUS_ERROR_INVALID_ARGS \
|
||||
WPAS_DBUS_NEW_INTERFACE ".InvalidArgs"
|
||||
|
||||
#define WPAS_DBUS_ERROR_IFACE_EXISTS \
|
||||
WPAS_DBUS_NEW_INTERFACE ".InterfaceExists"
|
||||
#define WPAS_DBUS_ERROR_IFACE_DISABLED \
|
||||
WPAS_DBUS_NEW_INTERFACE ".InterfaceDisabled"
|
||||
#define WPAS_DBUS_ERROR_IFACE_UNKNOWN \
|
||||
WPAS_DBUS_NEW_INTERFACE ".InterfaceUnknown"
|
||||
|
||||
#define WPAS_DBUS_ERROR_NOT_CONNECTED \
|
||||
WPAS_DBUS_NEW_INTERFACE ".NotConnected"
|
||||
#define WPAS_DBUS_ERROR_NETWORK_UNKNOWN \
|
||||
WPAS_DBUS_NEW_INTERFACE ".NetworkUnknown"
|
||||
|
||||
#define WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNAVAILABLE \
|
||||
WPAS_DBUS_NEW_INTERFACE ".ConnectChannelUnavailable"
|
||||
#define WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNSUPPORTED \
|
||||
WPAS_DBUS_NEW_INTERFACE ".ConnectChannelUnsupported"
|
||||
#define WPAS_DBUS_ERROR_CONNECT_UNSPECIFIED_ERROR \
|
||||
WPAS_DBUS_NEW_INTERFACE ".ConnectUnspecifiedError"
|
||||
|
||||
#define WPAS_DBUS_ERROR_BLOB_EXISTS \
|
||||
WPAS_DBUS_NEW_INTERFACE ".BlobExists"
|
||||
#define WPAS_DBUS_ERROR_BLOB_UNKNOWN \
|
||||
WPAS_DBUS_NEW_INTERFACE ".BlobUnknown"
|
||||
|
||||
#define WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE \
|
||||
WPAS_DBUS_NEW_INTERFACE ".SubscriptionInUse"
|
||||
#define WPAS_DBUS_ERROR_NO_SUBSCRIPTION \
|
||||
WPAS_DBUS_NEW_INTERFACE ".NoSubscription"
|
||||
#define WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM \
|
||||
WPAS_DBUS_NEW_INTERFACE ".SubscriptionNotYou"
|
||||
|
||||
/* Interface-level errors */
|
||||
#define WPAS_DBUS_ERROR_IFACE_SCAN_ERROR \
|
||||
WPAS_DBUS_NEW_IFACE_INTERFACE ".ScanError"
|
||||
|
||||
void wpas_dbus_subscribe_noc(struct wpas_dbus_priv *priv);
|
||||
void wpas_dbus_unsubscribe_noc(struct wpas_dbus_priv *priv);
|
||||
|
||||
|
||||
#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
|
||||
|
||||
int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv);
|
||||
void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface);
|
||||
|
||||
int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s);
|
||||
int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s);
|
||||
void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
|
||||
enum wpas_dbus_prop property);
|
||||
void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
|
||||
enum wpas_dbus_bss_prop property,
|
||||
unsigned int id);
|
||||
void wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid);
|
||||
void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s, int id);
|
||||
void wpas_dbus_signal_network_request(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid,
|
||||
enum wpa_ctrl_req_type rtype,
|
||||
const char *default_text);
|
||||
void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s, int success);
|
||||
void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
|
||||
const struct wps_credential *cred);
|
||||
void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
|
||||
struct wps_event_m2d *m2d);
|
||||
void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
|
||||
struct wps_event_fail *fail);
|
||||
void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s);
|
||||
void wpas_dbus_signal_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s);
|
||||
int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid);
|
||||
int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid);
|
||||
int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
|
||||
u8 bssid[ETH_ALEN], unsigned int id);
|
||||
int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
|
||||
u8 bssid[ETH_ALEN], unsigned int id);
|
||||
int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s, const u8 *sta);
|
||||
int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s, const u8 *sta);
|
||||
void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
|
||||
const char *name);
|
||||
void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
|
||||
const char *name);
|
||||
void wpas_dbus_signal_debug_level_changed(struct wpa_global *global);
|
||||
void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global);
|
||||
void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global);
|
||||
|
||||
int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr);
|
||||
void wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant *wpa_s);
|
||||
void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
|
||||
const u8 *dev_addr);
|
||||
int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
|
||||
const u8 *dev_addr);
|
||||
void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
|
||||
const u8 *dev_addr);
|
||||
void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
|
||||
const u8 *dev_addr);
|
||||
void wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s,
|
||||
const char *role);
|
||||
void wpas_dbus_signal_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
|
||||
const u8 *dev_addr, int request,
|
||||
enum p2p_prov_disc_status status,
|
||||
u16 config_methods,
|
||||
unsigned int generated_pin);
|
||||
void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
|
||||
const u8 *src, u16 dev_passwd_id,
|
||||
u8 go_intent);
|
||||
void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
|
||||
int client, int persistent,
|
||||
const u8 *ip);
|
||||
void wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant *wpa_s,
|
||||
const char *reason);
|
||||
void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid);
|
||||
void wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s,
|
||||
struct p2p_go_neg_results *res);
|
||||
void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
|
||||
const struct wpa_ssid *ssid);
|
||||
int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid);
|
||||
int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s,
|
||||
int nid);
|
||||
void wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant *wpa_s,
|
||||
int status, const u8 *bssid);
|
||||
void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
|
||||
const u8 *member);
|
||||
void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s,
|
||||
int freq, const u8 *sa, u8 dialog_token,
|
||||
u16 update_indic, const u8 *tlvs,
|
||||
size_t tlvs_len);
|
||||
void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s,
|
||||
const u8 *sa, u16 update_indic,
|
||||
const u8 *tlvs, size_t tlvs_len);
|
||||
void wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
|
||||
const u8 *member);
|
||||
void wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s,
|
||||
struct wps_event_fail *fail);
|
||||
void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
|
||||
int depth, const char *subject,
|
||||
const char *altsubject[],
|
||||
int num_altsubject,
|
||||
const char *cert_hash,
|
||||
const struct wpabuf *cert);
|
||||
void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
|
||||
const u8 *addr, const u8 *dst, const u8 *bssid,
|
||||
const u8 *ie, size_t ie_len, u32 ssi_signal);
|
||||
void wpas_dbus_signal_eap_status(struct wpa_supplicant *wpa_s,
|
||||
const char *status, const char *parameter);
|
||||
void wpas_dbus_signal_sta_authorized(struct wpa_supplicant *wpa_s,
|
||||
const u8 *sta);
|
||||
void wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant *wpa_s,
|
||||
const u8 *sta);
|
||||
void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s,
|
||||
const u8 *sa, const u8 *dev_addr,
|
||||
const u8 *bssid, int id,
|
||||
int op_freq);
|
||||
void wpas_dbus_signal_mesh_group_started(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid);
|
||||
void wpas_dbus_signal_mesh_group_removed(struct wpa_supplicant *wpa_s,
|
||||
const u8 *meshid, u8 meshid_len,
|
||||
int reason);
|
||||
void wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant *wpa_s,
|
||||
const u8 *peer_addr);
|
||||
void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
|
||||
const u8 *peer_addr, int reason);
|
||||
void wpas_dbus_signal_interworking_ap_added(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_bss *bss,
|
||||
struct wpa_cred *cred,
|
||||
const char *type, int excluded,
|
||||
int bh, int bss_load,
|
||||
int conn_capab);
|
||||
void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s);
|
||||
|
||||
#else /* CONFIG_CTRL_IFACE_DBUS_NEW */
|
||||
|
||||
static inline int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define wpas_dbus_signal_state_changed(w, n, o) do { } while (0)
|
||||
|
||||
static inline void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
|
||||
enum wpas_dbus_prop property)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wpas_dbus_bss_signal_prop_changed(
|
||||
struct wpa_supplicant *wpa_s, enum wpas_dbus_bss_prop property,
|
||||
unsigned int id)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wpas_dbus_signal_network_enabled_changed(
|
||||
struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wpas_dbus_signal_network_selected(
|
||||
struct wpa_supplicant *wpa_s, int id)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wpas_dbus_signal_network_request(
|
||||
struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
|
||||
enum wpa_ctrl_req_type rtype, const char *default_txt)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s,
|
||||
int success)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
|
||||
const struct wps_credential *cred)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
|
||||
struct wps_event_m2d *m2d)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wpas_dbus_signal_wps_event_fail(
|
||||
struct wpa_supplicant *wpa_s, struct wps_event_fail *fail)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wpas_dbus_signal_wps_event_success(
|
||||
struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wpas_dbus_signal_wps_event_pbc_overlap(
|
||||
struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s,
|
||||
int nid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
|
||||
u8 bssid[ETH_ALEN], unsigned int id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
|
||||
u8 bssid[ETH_ALEN], unsigned int id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s,
|
||||
const u8 *sta)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s,
|
||||
const u8 *sta)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
|
||||
const char *name)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
|
||||
const char *name)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wpas_dbus_signal_debug_level_changed(
|
||||
struct wpa_global *global)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wpas_dbus_signal_debug_timestamp_changed(
|
||||
struct wpa_global *global)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wpas_dbus_signal_debug_show_keys_changed(
|
||||
struct wpa_global *global)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s,
|
||||
const u8 *dev_addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
|
||||
const u8 *dev_addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
|
||||
const u8 *dev_addr)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s,
|
||||
const char *role)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpas_dbus_signal_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
|
||||
const u8 *dev_addr, int request,
|
||||
enum p2p_prov_disc_status status,
|
||||
u16 config_methods,
|
||||
unsigned int generated_pin)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
|
||||
const u8 *src,
|
||||
u16 dev_passwd_id,
|
||||
u8 go_intent)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
|
||||
int client, int persistent,
|
||||
const u8 *ip)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant *wpa_s,
|
||||
const char *reason)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int wpas_dbus_register_persistent_group(
|
||||
struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int wpas_dbus_unregister_persistent_group(
|
||||
struct wpa_supplicant *wpa_s, int nid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s,
|
||||
struct p2p_go_neg_results *res)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
|
||||
const struct wpa_ssid *ssid)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wpas_dbus_signal_p2p_invitation_result(
|
||||
struct wpa_supplicant *wpa_s, int status,
|
||||
const u8 *bssid)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpas_dbus_register_p2p_groupmember(struct wpa_supplicant *wpa_s,
|
||||
const u8 *p2p_if_addr)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s, int freq,
|
||||
const u8 *sa, u8 dialog_token, u16 update_indic,
|
||||
const u8 *tlvs, size_t tlvs_len)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s,
|
||||
const u8 *sa, u16 update_indic,
|
||||
const u8 *tlvs, size_t tlvs_len)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpas_dbus_unregister_p2p_groupmember(struct wpa_supplicant *wpa_s,
|
||||
const u8 *p2p_if_addr)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
|
||||
const u8 *member)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
|
||||
const u8 *dev_addr)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
|
||||
const u8 *dev_addr)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
|
||||
const u8 *member)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s,
|
||||
struct wps_event_fail *fail)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
|
||||
int depth,
|
||||
const char *subject,
|
||||
const char *altsubject[],
|
||||
int num_altsubject,
|
||||
const char *cert_hash,
|
||||
const struct wpabuf *cert)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
|
||||
const u8 *addr, const u8 *dst,
|
||||
const u8 *bssid,
|
||||
const u8 *ie, size_t ie_len,
|
||||
u32 ssi_signal)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wpas_dbus_signal_eap_status(struct wpa_supplicant *wpa_s,
|
||||
const char *status,
|
||||
const char *parameter)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
void wpas_dbus_signal_sta_authorized(struct wpa_supplicant *wpa_s,
|
||||
const u8 *sta)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
void wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant *wpa_s,
|
||||
const u8 *sta)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s,
|
||||
const u8 *sa, const u8 *dev_addr,
|
||||
const u8 *bssid, int id,
|
||||
int op_freq)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
void wpas_dbus_signal_mesh_group_started(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
void wpas_dbus_signal_mesh_group_removed(struct wpa_supplicant *wpa_s,
|
||||
const u8 *meshid, u8 meshid_len,
|
||||
int reason)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
void wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant *wpa_s,
|
||||
const u8 *peer_addr)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
|
||||
const u8 *peer_addr, int reason)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
void wpas_dbus_signal_interworking_ap_added(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_bss *bss,
|
||||
struct wpa_cred *cred,
|
||||
const char *type, int excluded,
|
||||
int bh, int bss_load,
|
||||
int conn_capab)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
|
||||
|
||||
#endif /* CTRL_IFACE_DBUS_H_NEW */
|
5928
wpa_supplicant/dbus/dbus_new_handlers.c
Normal file
5928
wpa_supplicant/dbus/dbus_new_handlers.c
Normal file
File diff suppressed because it is too large
Load Diff
285
wpa_supplicant/dbus/dbus_new_handlers.h
Normal file
285
wpa_supplicant/dbus/dbus_new_handlers.h
Normal file
@ -0,0 +1,285 @@
|
||||
/*
|
||||
* WPA Supplicant / dbus-based control interface
|
||||
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
|
||||
* Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef CTRL_IFACE_DBUS_NEW_HANDLERS_H
|
||||
#define CTRL_IFACE_DBUS_NEW_HANDLERS_H
|
||||
|
||||
#include "dbus_new_helpers.h"
|
||||
|
||||
struct network_handler_args {
|
||||
struct wpa_supplicant *wpa_s;
|
||||
struct wpa_ssid *ssid;
|
||||
};
|
||||
|
||||
struct bss_handler_args {
|
||||
struct wpa_supplicant *wpa_s;
|
||||
unsigned int id;
|
||||
};
|
||||
|
||||
struct sta_handler_args {
|
||||
struct wpa_supplicant *wpa_s;
|
||||
const u8 *sta;
|
||||
};
|
||||
|
||||
dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter,
|
||||
const int type,
|
||||
const void *val,
|
||||
DBusError *error);
|
||||
|
||||
dbus_bool_t wpas_dbus_simple_property_setter(DBusMessageIter *iter,
|
||||
DBusError *error,
|
||||
const int type, void *val);
|
||||
|
||||
dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter,
|
||||
const int type,
|
||||
const void *array,
|
||||
size_t array_len,
|
||||
DBusError *error);
|
||||
|
||||
dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter,
|
||||
const int type,
|
||||
struct wpabuf **array,
|
||||
size_t array_len,
|
||||
DBusError *error);
|
||||
|
||||
dbus_bool_t wpas_dbus_string_property_getter(DBusMessageIter *iter,
|
||||
const void *val,
|
||||
DBusError *error);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
|
||||
struct wpa_global *global);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
|
||||
struct wpa_global *global);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
|
||||
struct wpa_global *global);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_expect_disconnect(DBusMessage *message,
|
||||
struct wpa_global *global);
|
||||
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_debug_level);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_debug_timestamp);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_debug_show_keys);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_debug_level);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_debug_timestamp);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_debug_show_keys);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_interfaces);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_eap_methods);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_global_capabilities);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_iface_global);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_iface_global);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_abort_scan(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid,
|
||||
DBusMessageIter *iter,
|
||||
DBusError *error);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_reconnect(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_remove_all_networks(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_roam(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_set_pkcs11_engine_and_module_path(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_autoscan(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_add_cred(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_remove_cred(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_remove_all_creds(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage *
|
||||
wpas_dbus_handler_interworking_select(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_capabilities);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_state);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_scanning);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_ap_scan);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_ap_scan);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_fast_reauth);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_fast_reauth);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_disconnect_reason);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_disassociate_reason);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_auth_status_code);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_assoc_status_code);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_roam_time);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_roam_complete);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_session_length);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_bss_tm_status);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_bss_expire_age);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_bss_expire_age);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_bss_expire_count);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_bss_expire_count);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_country);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_country);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_scan_interval);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_scan_interval);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_ifname);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_driver);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_bridge_ifname);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_bridge_ifname);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_config_file);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_current_bss);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_current_network);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_current_auth_mode);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_bsss);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_networks);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_pkcs11_engine_path);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_pkcs11_module_path);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_blobs);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_stas);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_mac_address_randomization_mask);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_mac_address_randomization_mask);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_sta_address);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_sta_aid);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_sta_caps);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_sta_rx_packets);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_sta_tx_packets);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_sta_tx_bytes);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_sta_rx_bytes);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_bss_bssid);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_bss_ssid);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_bss_privacy);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_bss_mode);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_bss_signal);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_bss_frequency);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_bss_rates);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_bss_wpa);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_bss_rsn);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_bss_wps);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_bss_ies);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_bss_age);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_enabled);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_enabled);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_network_properties);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_network_properties);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_wps_start(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_wps_cancel(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_process_credentials);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_process_credentials);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_config_methods);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_config_methods);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_wps_device_name);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_wps_device_name);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_wps_manufacturer);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_wps_manufacturer);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_wps_device_model_name);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_wps_device_model_name);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_wps_device_model_number);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_wps_device_model_number);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_wps_device_serial_number);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_wps_device_serial_number);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_wps_device_device_type);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_wps_device_device_type);
|
||||
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_mesh_peers);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_mesh_group);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
DBusMessage * wpas_dbus_handler_tdls_setup(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
DBusMessage *
|
||||
wpas_dbus_handler_tdls_channel_switch(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
DBusMessage *
|
||||
wpas_dbus_handler_tdls_cancel_channel_switch(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_vendor_elem_add(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
DBusMessage * wpas_dbus_handler_vendor_elem_get(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
DBusMessage * wpas_dbus_handler_vendor_elem_remove(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_save_config(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
|
||||
const char *arg);
|
||||
DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
|
||||
const char *arg);
|
||||
DBusMessage * wpas_dbus_error_no_memory(DBusMessage *message);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_subscribe_preq(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
DBusMessage * wpas_dbus_handler_unsubscribe_preq(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
#endif /* CTRL_IFACE_DBUS_HANDLERS_NEW_H */
|
3107
wpa_supplicant/dbus/dbus_new_handlers_p2p.c
Normal file
3107
wpa_supplicant/dbus/dbus_new_handlers_p2p.c
Normal file
File diff suppressed because it is too large
Load Diff
152
wpa_supplicant/dbus/dbus_new_handlers_p2p.h
Normal file
152
wpa_supplicant/dbus/dbus_new_handlers_p2p.h
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* WPA Supplicant / dbus-based control interface for p2p
|
||||
* Copyright (c) 2011-2012, Intel Corporation
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef DBUS_NEW_HANDLERS_P2P_H
|
||||
#define DBUS_NEW_HANDLERS_P2P_H
|
||||
|
||||
struct peer_handler_args {
|
||||
struct wpa_supplicant *wpa_s;
|
||||
u8 p2p_device_addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
/*
|
||||
* P2P Device methods
|
||||
*/
|
||||
|
||||
DBusMessage *wpas_dbus_handler_p2p_find(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage *wpas_dbus_handler_p2p_stop_find(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage *wpas_dbus_handler_p2p_rejectpeer(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage *wpas_dbus_handler_p2p_listen(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage *wpas_dbus_handler_p2p_extendedlisten(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage *wpas_dbus_handler_p2p_presence_request(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage *wpas_dbus_handler_p2p_prov_disc_req(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage *wpas_dbus_handler_p2p_group_add(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage *wpas_dbus_handler_p2p_connect(
|
||||
DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_p2p_cancel(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage *wpas_dbus_handler_p2p_invite(
|
||||
DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage *wpas_dbus_handler_p2p_disconnect(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_p2p_remove_client(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage *wpas_dbus_handler_p2p_flush(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage *wpas_dbus_handler_p2p_add_service(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage *wpas_dbus_handler_p2p_delete_service(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage *wpas_dbus_handler_p2p_flush_service(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage *wpas_dbus_handler_p2p_service_sd_req(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage *wpas_dbus_handler_p2p_service_sd_res(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage *wpas_dbus_handler_p2p_service_sd_cancel_req(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage *wpas_dbus_handler_p2p_service_update(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage *wpas_dbus_handler_p2p_serv_disc_external(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
/*
|
||||
* P2P Device property accessor methods.
|
||||
*/
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_p2p_device_config);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_device_config);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peers);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_role);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peergo);
|
||||
|
||||
/*
|
||||
* P2P Peer properties.
|
||||
*/
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_device_name);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_manufacturer);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_modelname);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_modelnumber);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_serialnumber);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_primary_device_type);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_config_method);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_level);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_device_capability);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_group_capability);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_secondary_device_types);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_vendor_extension);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_ies);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_device_address);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_groups);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_vsie);
|
||||
|
||||
/*
|
||||
* P2P Group properties
|
||||
*/
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group_members);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group_ssid);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group_bssid);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group_frequency);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group_passphrase);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group_psk);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group_vendor_ext);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_p2p_group_vendor_ext);
|
||||
|
||||
/*
|
||||
* P2P Persistent Groups and properties
|
||||
*/
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_persistent_groups);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_persistent_group_properties);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_persistent_group_properties);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_add_persistent_group(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_remove_persistent_group(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_remove_all_persistent_groups(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
#ifdef CONFIG_WIFI_DISPLAY
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_global_wfd_ies);
|
||||
DECLARE_ACCESSOR(wpas_dbus_setter_global_wfd_ies);
|
||||
#endif /* CONFIG_WIFI_DISPLAY */
|
||||
|
||||
#endif /* DBUS_NEW_HANDLERS_P2P_H */
|
804
wpa_supplicant/dbus/dbus_new_handlers_wps.c
Normal file
804
wpa_supplicant/dbus/dbus_new_handlers_wps.c
Normal file
@ -0,0 +1,804 @@
|
||||
/*
|
||||
* WPA Supplicant / dbus-based control interface (WPS)
|
||||
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
|
||||
* Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "../config.h"
|
||||
#include "../wpa_supplicant_i.h"
|
||||
#include "../wps_supplicant.h"
|
||||
#include "../driver_i.h"
|
||||
#include "../ap.h"
|
||||
#include "dbus_new_helpers.h"
|
||||
#include "dbus_new.h"
|
||||
#include "dbus_new_handlers.h"
|
||||
#include "dbus_dict_helpers.h"
|
||||
|
||||
|
||||
struct wps_start_params {
|
||||
int role; /* 0 - not set, 1 - enrollee, 2 - registrar */
|
||||
int type; /* 0 - not set, 1 - pin, 2 - pbc */
|
||||
u8 *bssid;
|
||||
char *pin;
|
||||
u8 *p2p_dev_addr;
|
||||
};
|
||||
|
||||
|
||||
static int wpas_dbus_handler_wps_role(DBusMessage *message,
|
||||
DBusMessageIter *entry_iter,
|
||||
struct wps_start_params *params,
|
||||
DBusMessage **reply)
|
||||
{
|
||||
DBusMessageIter variant_iter;
|
||||
char *val;
|
||||
|
||||
dbus_message_iter_recurse(entry_iter, &variant_iter);
|
||||
if (dbus_message_iter_get_arg_type(&variant_iter) !=
|
||||
DBUS_TYPE_STRING) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"dbus: WPS.Start - Wrong Role type, string required");
|
||||
*reply = wpas_dbus_error_invalid_args(message,
|
||||
"Role must be a string");
|
||||
return -1;
|
||||
}
|
||||
dbus_message_iter_get_basic(&variant_iter, &val);
|
||||
if (os_strcmp(val, "enrollee") == 0)
|
||||
params->role = 1;
|
||||
else if (os_strcmp(val, "registrar") == 0)
|
||||
params->role = 2;
|
||||
else {
|
||||
wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Unknown role %s", val);
|
||||
*reply = wpas_dbus_error_invalid_args(message, val);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpas_dbus_handler_wps_type(DBusMessage *message,
|
||||
DBusMessageIter *entry_iter,
|
||||
struct wps_start_params *params,
|
||||
DBusMessage **reply)
|
||||
{
|
||||
DBusMessageIter variant_iter;
|
||||
char *val;
|
||||
|
||||
dbus_message_iter_recurse(entry_iter, &variant_iter);
|
||||
if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_STRING) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"dbus: WPS.Start - Wrong Type type, string required");
|
||||
*reply = wpas_dbus_error_invalid_args(message,
|
||||
"Type must be a string");
|
||||
return -1;
|
||||
}
|
||||
dbus_message_iter_get_basic(&variant_iter, &val);
|
||||
if (os_strcmp(val, "pin") == 0)
|
||||
params->type = 1;
|
||||
else if (os_strcmp(val, "pbc") == 0)
|
||||
params->type = 2;
|
||||
else {
|
||||
wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Unknown type %s",
|
||||
val);
|
||||
*reply = wpas_dbus_error_invalid_args(message, val);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpas_dbus_handler_wps_bssid(DBusMessage *message,
|
||||
DBusMessageIter *entry_iter,
|
||||
struct wps_start_params *params,
|
||||
DBusMessage **reply)
|
||||
{
|
||||
DBusMessageIter variant_iter, array_iter;
|
||||
int len;
|
||||
|
||||
dbus_message_iter_recurse(entry_iter, &variant_iter);
|
||||
if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY ||
|
||||
dbus_message_iter_get_element_type(&variant_iter) !=
|
||||
DBUS_TYPE_BYTE) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"dbus: WPS.Start - Wrong Bssid type, byte array required");
|
||||
*reply = wpas_dbus_error_invalid_args(
|
||||
message, "Bssid must be a byte array");
|
||||
return -1;
|
||||
}
|
||||
dbus_message_iter_recurse(&variant_iter, &array_iter);
|
||||
dbus_message_iter_get_fixed_array(&array_iter, ¶ms->bssid, &len);
|
||||
if (len != ETH_ALEN) {
|
||||
wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong Bssid length %d",
|
||||
len);
|
||||
*reply = wpas_dbus_error_invalid_args(message,
|
||||
"Bssid is wrong length");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpas_dbus_handler_wps_pin(DBusMessage *message,
|
||||
DBusMessageIter *entry_iter,
|
||||
struct wps_start_params *params,
|
||||
DBusMessage **reply)
|
||||
{
|
||||
DBusMessageIter variant_iter;
|
||||
|
||||
dbus_message_iter_recurse(entry_iter, &variant_iter);
|
||||
if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_STRING) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"dbus: WPS.Start - Wrong Pin type, string required");
|
||||
*reply = wpas_dbus_error_invalid_args(message,
|
||||
"Pin must be a string");
|
||||
return -1;
|
||||
}
|
||||
dbus_message_iter_get_basic(&variant_iter, ¶ms->pin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
static int wpas_dbus_handler_wps_p2p_dev_addr(DBusMessage *message,
|
||||
DBusMessageIter *entry_iter,
|
||||
struct wps_start_params *params,
|
||||
DBusMessage **reply)
|
||||
{
|
||||
DBusMessageIter variant_iter, array_iter;
|
||||
int len;
|
||||
|
||||
dbus_message_iter_recurse(entry_iter, &variant_iter);
|
||||
if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY ||
|
||||
dbus_message_iter_get_element_type(&variant_iter) !=
|
||||
DBUS_TYPE_BYTE) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"dbus: WPS.Start - Wrong P2PDeviceAddress type, byte array required");
|
||||
*reply = wpas_dbus_error_invalid_args(
|
||||
message, "P2PDeviceAddress must be a byte array");
|
||||
return -1;
|
||||
}
|
||||
dbus_message_iter_recurse(&variant_iter, &array_iter);
|
||||
dbus_message_iter_get_fixed_array(&array_iter, ¶ms->p2p_dev_addr,
|
||||
&len);
|
||||
if (len != ETH_ALEN) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"dbus: WPS.Start - Wrong P2PDeviceAddress length %d",
|
||||
len);
|
||||
*reply = wpas_dbus_error_invalid_args(
|
||||
message, "P2PDeviceAddress has wrong length");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
|
||||
static int wpas_dbus_handler_wps_start_entry(DBusMessage *message, char *key,
|
||||
DBusMessageIter *entry_iter,
|
||||
struct wps_start_params *params,
|
||||
DBusMessage **reply)
|
||||
{
|
||||
if (os_strcmp(key, "Role") == 0)
|
||||
return wpas_dbus_handler_wps_role(message, entry_iter,
|
||||
params, reply);
|
||||
else if (os_strcmp(key, "Type") == 0)
|
||||
return wpas_dbus_handler_wps_type(message, entry_iter,
|
||||
params, reply);
|
||||
else if (os_strcmp(key, "Bssid") == 0)
|
||||
return wpas_dbus_handler_wps_bssid(message, entry_iter,
|
||||
params, reply);
|
||||
else if (os_strcmp(key, "Pin") == 0)
|
||||
return wpas_dbus_handler_wps_pin(message, entry_iter,
|
||||
params, reply);
|
||||
#ifdef CONFIG_P2P
|
||||
else if (os_strcmp(key, "P2PDeviceAddress") == 0)
|
||||
return wpas_dbus_handler_wps_p2p_dev_addr(message, entry_iter,
|
||||
params, reply);
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
wpa_printf(MSG_DEBUG, "dbus: WPS.Start - unknown key %s", key);
|
||||
*reply = wpas_dbus_error_invalid_args(message, key);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_handler_wps_start - Start WPS configuration
|
||||
* @message: Pointer to incoming dbus message
|
||||
* @wpa_s: %wpa_supplicant data structure
|
||||
* Returns: DBus message dictionary on success or DBus error on failure
|
||||
*
|
||||
* Handler for "Start" method call. DBus dictionary argument contains
|
||||
* information about role (enrollee or registrar), authorization method
|
||||
* (pin or push button) and optionally pin and bssid. Returned message
|
||||
* has a dictionary argument which may contain newly generated pin (optional).
|
||||
*/
|
||||
DBusMessage * wpas_dbus_handler_wps_start(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
DBusMessage *reply = NULL;
|
||||
DBusMessageIter iter, dict_iter, entry_iter;
|
||||
struct wps_start_params params;
|
||||
char *key;
|
||||
char npin[9] = { '\0' };
|
||||
int ret;
|
||||
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
dbus_message_iter_init(message, &iter);
|
||||
|
||||
dbus_message_iter_recurse(&iter, &dict_iter);
|
||||
while (dbus_message_iter_get_arg_type(&dict_iter) ==
|
||||
DBUS_TYPE_DICT_ENTRY) {
|
||||
dbus_message_iter_recurse(&dict_iter, &entry_iter);
|
||||
|
||||
dbus_message_iter_get_basic(&entry_iter, &key);
|
||||
dbus_message_iter_next(&entry_iter);
|
||||
|
||||
if (wpas_dbus_handler_wps_start_entry(message, key,
|
||||
&entry_iter,
|
||||
¶ms, &reply))
|
||||
return reply;
|
||||
|
||||
dbus_message_iter_next(&dict_iter);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AP
|
||||
if (wpa_s->ap_iface && params.type == 1) {
|
||||
if (params.pin == NULL) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"dbus: WPS.Start - Pin required for registrar role");
|
||||
return wpas_dbus_error_invalid_args(
|
||||
message, "Pin required for registrar role.");
|
||||
}
|
||||
ret = wpa_supplicant_ap_wps_pin(wpa_s,
|
||||
params.bssid,
|
||||
params.pin,
|
||||
npin, sizeof(npin), 0);
|
||||
} else if (wpa_s->ap_iface) {
|
||||
ret = wpa_supplicant_ap_wps_pbc(wpa_s,
|
||||
params.bssid,
|
||||
params.p2p_dev_addr);
|
||||
} else
|
||||
#endif /* CONFIG_AP */
|
||||
if (params.role == 0) {
|
||||
wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Role not specified");
|
||||
return wpas_dbus_error_invalid_args(message,
|
||||
"Role not specified");
|
||||
} else if (params.role == 2) {
|
||||
if (params.pin == NULL) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"dbus: WPS.Start - Pin required for registrar role");
|
||||
return wpas_dbus_error_invalid_args(
|
||||
message, "Pin required for registrar role.");
|
||||
}
|
||||
ret = wpas_wps_start_reg(wpa_s, params.bssid, params.pin,
|
||||
NULL);
|
||||
} else if (params.type == 0) {
|
||||
wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Type not specified");
|
||||
return wpas_dbus_error_invalid_args(message,
|
||||
"Type not specified");
|
||||
} else if (params.type == 1) {
|
||||
ret = wpas_wps_start_pin(wpa_s, params.bssid,
|
||||
params.pin, 0,
|
||||
DEV_PW_DEFAULT);
|
||||
if (ret > 0) {
|
||||
ret = os_snprintf(npin, sizeof(npin), "%08d", ret);
|
||||
if (os_snprintf_error(sizeof(npin), ret))
|
||||
return wpas_dbus_error_unknown_error(
|
||||
message, "invalid PIN");
|
||||
}
|
||||
} else {
|
||||
ret = wpas_wps_start_pbc(wpa_s, params.bssid, 0, 0);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"dbus: WPS.Start wpas_wps_failed in role %s and key %s",
|
||||
(params.role == 1 ? "enrollee" : "registrar"),
|
||||
(params.type == 0 ? "" :
|
||||
(params.type == 1 ? "pin" : "pbc")));
|
||||
return wpas_dbus_error_unknown_error(message,
|
||||
"WPS start failed");
|
||||
}
|
||||
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
return wpas_dbus_error_no_memory(message);
|
||||
|
||||
dbus_message_iter_init_append(reply, &iter);
|
||||
if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
|
||||
(os_strlen(npin) > 0 &&
|
||||
!wpa_dbus_dict_append_string(&dict_iter, "Pin", npin)) ||
|
||||
!wpa_dbus_dict_close_write(&iter, &dict_iter)) {
|
||||
dbus_message_unref(reply);
|
||||
return wpas_dbus_error_no_memory(message);
|
||||
}
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_handler_wps_cancel - Cancel ongoing WPS configuration
|
||||
* @message: Pointer to incoming dbus message
|
||||
* @wpa_s: %wpa_supplicant data structure
|
||||
* Returns: NULL on success or DBus error on failure
|
||||
*
|
||||
* Handler for "Cancel" method call. Returns NULL if WPS cancel successful
|
||||
* or DBus error on WPS cancel failure
|
||||
*/
|
||||
DBusMessage * wpas_dbus_handler_wps_cancel(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
if (wpas_wps_cancel(wpa_s))
|
||||
return wpas_dbus_error_unknown_error(message,
|
||||
"WPS cancel failed");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_getter_process_credentials - Check if credentials are processed
|
||||
* @message: Pointer to incoming dbus message
|
||||
* @wpa_s: %wpa_supplicant data structure
|
||||
* Returns: TRUE on success, FALSE on failure
|
||||
*
|
||||
* Getter for "ProcessCredentials" property. Returns returned boolean will be
|
||||
* true if wps_cred_processing configuration field is not equal to 1 or false
|
||||
* if otherwise.
|
||||
*/
|
||||
dbus_bool_t wpas_dbus_getter_process_credentials(
|
||||
const struct wpa_dbus_property_desc *property_desc,
|
||||
DBusMessageIter *iter, DBusError *error, void *user_data)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = user_data;
|
||||
dbus_bool_t process = wpa_s->conf->wps_cred_processing != 1;
|
||||
|
||||
return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
|
||||
&process, error);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_setter_process_credentials - Set credentials_processed conf param
|
||||
* @iter: Pointer to incoming dbus message iter
|
||||
* @error: Location to store error on failure
|
||||
* @user_data: Function specific data
|
||||
* Returns: TRUE on success, FALSE on failure
|
||||
*
|
||||
* Setter for "ProcessCredentials" property. Sets credentials_processed on 2
|
||||
* if boolean argument is true or on 1 if otherwise.
|
||||
*/
|
||||
dbus_bool_t wpas_dbus_setter_process_credentials(
|
||||
const struct wpa_dbus_property_desc *property_desc,
|
||||
DBusMessageIter *iter, DBusError *error, void *user_data)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = user_data;
|
||||
dbus_bool_t process_credentials, old_pc;
|
||||
|
||||
if (!wpa_s->dbus_new_path)
|
||||
return FALSE;
|
||||
if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
|
||||
&process_credentials))
|
||||
return FALSE;
|
||||
|
||||
old_pc = wpa_s->conf->wps_cred_processing != 1;
|
||||
wpa_s->conf->wps_cred_processing = (process_credentials ? 2 : 1);
|
||||
|
||||
if ((wpa_s->conf->wps_cred_processing != 1) != old_pc)
|
||||
wpa_dbus_mark_property_changed(wpa_s->global->dbus,
|
||||
wpa_s->dbus_new_path,
|
||||
WPAS_DBUS_NEW_IFACE_WPS,
|
||||
"ProcessCredentials");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_getter_config_methods - Get current WPS configuration methods
|
||||
* @iter: Pointer to incoming dbus message iter
|
||||
* @error: Location to store error on failure
|
||||
* @user_data: Function specific data
|
||||
* Returns: TRUE on success, FALSE on failure
|
||||
*
|
||||
* Getter for "ConfigMethods" property. Returned boolean will be true if
|
||||
* providing the relevant string worked, or false otherwise.
|
||||
*/
|
||||
dbus_bool_t wpas_dbus_getter_config_methods(
|
||||
const struct wpa_dbus_property_desc *property_desc,
|
||||
DBusMessageIter *iter, DBusError *error, void *user_data)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = user_data;
|
||||
|
||||
return wpas_dbus_string_property_getter(iter,
|
||||
wpa_s->conf->config_methods,
|
||||
error);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_setter_config_methods - Set WPS configuration methods
|
||||
* @iter: Pointer to incoming dbus message iter
|
||||
* @error: Location to store error on failure
|
||||
* @user_data: Function specific data
|
||||
* Returns: TRUE on success, FALSE on failure
|
||||
*
|
||||
* Setter for "ConfigMethods" property. Sets the methods string, apply such
|
||||
* change and returns true on success. Returns false otherwise.
|
||||
*/
|
||||
dbus_bool_t wpas_dbus_setter_config_methods(
|
||||
const struct wpa_dbus_property_desc *property_desc,
|
||||
DBusMessageIter *iter, DBusError *error, void *user_data)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = user_data;
|
||||
char *methods, *new_methods;
|
||||
|
||||
if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
|
||||
&methods))
|
||||
return FALSE;
|
||||
|
||||
new_methods = os_strdup(methods);
|
||||
if (!new_methods)
|
||||
return FALSE;
|
||||
|
||||
os_free(wpa_s->conf->config_methods);
|
||||
wpa_s->conf->config_methods = new_methods;
|
||||
|
||||
wpa_s->conf->changed_parameters |= CFG_CHANGED_CONFIG_METHODS;
|
||||
wpa_supplicant_update_config(wpa_s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_getter_wps_device_name - Get current WPS device name
|
||||
* @iter: Pointer to incoming dbus message iter
|
||||
* @error: Location to store error on failure
|
||||
* @user_data: Function specific data
|
||||
* Returns: TRUE on success, FALSE on failure
|
||||
*
|
||||
* Getter for "DeviceName" property.
|
||||
*/
|
||||
dbus_bool_t wpas_dbus_getter_wps_device_name(
|
||||
const struct wpa_dbus_property_desc *property_desc,
|
||||
DBusMessageIter *iter, DBusError *error, void *user_data)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = user_data;
|
||||
|
||||
return wpas_dbus_string_property_getter(iter, wpa_s->conf->device_name,
|
||||
error);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_setter_wps_device_name - Set current WPS device name
|
||||
* @iter: Pointer to incoming dbus message iter
|
||||
* @error: Location to store error on failure
|
||||
* @user_data: Function specific data
|
||||
* Returns: TRUE on success, FALSE on failure
|
||||
*
|
||||
* Setter for "DeviceName" property.
|
||||
*/
|
||||
dbus_bool_t wpas_dbus_setter_wps_device_name(
|
||||
const struct wpa_dbus_property_desc *property_desc,
|
||||
DBusMessageIter *iter, DBusError *error, void *user_data)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = user_data;
|
||||
char *methods, *devname;
|
||||
|
||||
if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
|
||||
&methods))
|
||||
return FALSE;
|
||||
|
||||
if (os_strlen(methods) > WPS_DEV_NAME_MAX_LEN)
|
||||
return FALSE;
|
||||
|
||||
devname = os_strdup(methods);
|
||||
if (!devname)
|
||||
return FALSE;
|
||||
|
||||
os_free(wpa_s->conf->device_name);
|
||||
wpa_s->conf->device_name = devname;
|
||||
wpa_s->conf->changed_parameters |= CFG_CHANGED_DEVICE_NAME;
|
||||
wpa_supplicant_update_config(wpa_s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_getter_wps_manufacturer - Get current manufacturer name
|
||||
* @iter: Pointer to incoming dbus message iter
|
||||
* @error: Location to store error on failure
|
||||
* @user_data: Function specific data
|
||||
* Returns: TRUE on success, FALSE on failure
|
||||
*
|
||||
* Getter for "Manufacturer" property.
|
||||
*/
|
||||
dbus_bool_t wpas_dbus_getter_wps_manufacturer(
|
||||
const struct wpa_dbus_property_desc *property_desc,
|
||||
DBusMessageIter *iter, DBusError *error, void *user_data)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = user_data;
|
||||
|
||||
return wpas_dbus_string_property_getter(iter, wpa_s->conf->manufacturer,
|
||||
error);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_setter_wps_manufacturer - Set current manufacturer name
|
||||
* @iter: Pointer to incoming dbus message iter
|
||||
* @error: Location to store error on failure
|
||||
* @user_data: Function specific data
|
||||
* Returns: TRUE on success, FALSE on failure
|
||||
*
|
||||
* Setter for "Manufacturer" property.
|
||||
*/
|
||||
dbus_bool_t wpas_dbus_setter_wps_manufacturer(
|
||||
const struct wpa_dbus_property_desc *property_desc,
|
||||
DBusMessageIter *iter, DBusError *error, void *user_data)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = user_data;
|
||||
char *methods, *manufacturer;
|
||||
|
||||
if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
|
||||
&methods))
|
||||
return FALSE;
|
||||
|
||||
if (os_strlen(methods) > WPS_MANUFACTURER_MAX_LEN)
|
||||
return FALSE;
|
||||
|
||||
manufacturer = os_strdup(methods);
|
||||
if (!manufacturer)
|
||||
return FALSE;
|
||||
|
||||
os_free(wpa_s->conf->manufacturer);
|
||||
wpa_s->conf->manufacturer = manufacturer;
|
||||
wpa_s->conf->changed_parameters |= CFG_CHANGED_WPS_STRING;
|
||||
wpa_supplicant_update_config(wpa_s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_getter_wps_device_model_name - Get current device model name
|
||||
* @iter: Pointer to incoming dbus message iter
|
||||
* @error: Location to store error on failure
|
||||
* @user_data: Function specific data
|
||||
* Returns: TRUE on success, FALSE on failure
|
||||
*
|
||||
* Getter for "ModelName" property.
|
||||
*/
|
||||
dbus_bool_t wpas_dbus_getter_wps_device_model_name(
|
||||
const struct wpa_dbus_property_desc *property_desc,
|
||||
DBusMessageIter *iter, DBusError *error, void *user_data)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = user_data;
|
||||
|
||||
return wpas_dbus_string_property_getter(iter, wpa_s->conf->model_name,
|
||||
error);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_setter_wps_device_model_name - Set current device model name
|
||||
* @iter: Pointer to incoming dbus message iter
|
||||
* @error: Location to store error on failure
|
||||
* @user_data: Function specific data
|
||||
* Returns: TRUE on success, FALSE on failure
|
||||
*
|
||||
* Setter for "ModelName" property.
|
||||
*/
|
||||
dbus_bool_t wpas_dbus_setter_wps_device_model_name(
|
||||
const struct wpa_dbus_property_desc *property_desc,
|
||||
DBusMessageIter *iter, DBusError *error, void *user_data)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = user_data;
|
||||
char *methods, *model_name;
|
||||
|
||||
if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
|
||||
&methods))
|
||||
return FALSE;
|
||||
|
||||
if (os_strlen(methods) > WPS_MODEL_NAME_MAX_LEN)
|
||||
return FALSE;
|
||||
|
||||
model_name = os_strdup(methods);
|
||||
if (!model_name)
|
||||
return FALSE;
|
||||
os_free(wpa_s->conf->model_name);
|
||||
wpa_s->conf->model_name = model_name;
|
||||
wpa_s->conf->changed_parameters |= CFG_CHANGED_WPS_STRING;
|
||||
wpa_supplicant_update_config(wpa_s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_getter_wps_device_model_number - Get current device model number
|
||||
* @iter: Pointer to incoming dbus message iter
|
||||
* @error: Location to store error on failure
|
||||
* @user_data: Function specific data
|
||||
* Returns: TRUE on success, FALSE on failure
|
||||
*
|
||||
* Getter for "ModelNumber" property.
|
||||
*/
|
||||
dbus_bool_t wpas_dbus_getter_wps_device_model_number(
|
||||
const struct wpa_dbus_property_desc *property_desc,
|
||||
DBusMessageIter *iter, DBusError *error, void *user_data)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = user_data;
|
||||
|
||||
return wpas_dbus_string_property_getter(iter, wpa_s->conf->model_number,
|
||||
error);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_setter_wps_device_model_number - Set current device model number
|
||||
* @iter: Pointer to incoming dbus message iter
|
||||
* @error: Location to store error on failure
|
||||
* @user_data: Function specific data
|
||||
* Returns: TRUE on success, FALSE on failure
|
||||
*
|
||||
* Setter for "ModelNumber" property.
|
||||
*/
|
||||
dbus_bool_t wpas_dbus_setter_wps_device_model_number(
|
||||
const struct wpa_dbus_property_desc *property_desc,
|
||||
DBusMessageIter *iter, DBusError *error, void *user_data)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = user_data;
|
||||
char *methods, *model_number;
|
||||
|
||||
if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
|
||||
&methods))
|
||||
return FALSE;
|
||||
|
||||
if (os_strlen(methods) > WPS_MODEL_NUMBER_MAX_LEN)
|
||||
return FALSE;
|
||||
|
||||
model_number = os_strdup(methods);
|
||||
if (!model_number)
|
||||
return FALSE;
|
||||
|
||||
os_free(wpa_s->conf->model_number);
|
||||
wpa_s->conf->model_number = model_number;
|
||||
wpa_s->conf->changed_parameters |= CFG_CHANGED_WPS_STRING;
|
||||
wpa_supplicant_update_config(wpa_s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_getter_wps_device_serial_number - Get current device serial number
|
||||
* @iter: Pointer to incoming dbus message iter
|
||||
* @error: Location to store error on failure
|
||||
* @user_data: Function specific data
|
||||
* Returns: TRUE on success, FALSE on failure
|
||||
*
|
||||
* Getter for "SerialNumber" property.
|
||||
*/
|
||||
dbus_bool_t wpas_dbus_getter_wps_device_serial_number(
|
||||
const struct wpa_dbus_property_desc *property_desc,
|
||||
DBusMessageIter *iter, DBusError *error, void *user_data)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = user_data;
|
||||
|
||||
return wpas_dbus_string_property_getter(iter,
|
||||
wpa_s->conf->serial_number,
|
||||
error);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_setter_wps_device_serial_number - Set current device serial number
|
||||
* @iter: Pointer to incoming dbus message iter
|
||||
* @error: Location to store error on failure
|
||||
* @user_data: Function specific data
|
||||
* Returns: TRUE on success, FALSE on failure
|
||||
*
|
||||
* Setter for "SerialNumber" property.
|
||||
*/
|
||||
dbus_bool_t wpas_dbus_setter_wps_device_serial_number(
|
||||
const struct wpa_dbus_property_desc *property_desc,
|
||||
DBusMessageIter *iter, DBusError *error, void *user_data)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = user_data;
|
||||
char *methods, *serial_number;
|
||||
|
||||
if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
|
||||
&methods))
|
||||
return FALSE;
|
||||
|
||||
if (os_strlen(methods) > WPS_SERIAL_NUMBER_MAX_LEN)
|
||||
return FALSE;
|
||||
|
||||
serial_number = os_strdup(methods);
|
||||
if (!serial_number)
|
||||
return FALSE;
|
||||
os_free(wpa_s->conf->serial_number);
|
||||
wpa_s->conf->serial_number = serial_number;
|
||||
wpa_s->conf->changed_parameters |= CFG_CHANGED_WPS_STRING;
|
||||
wpa_supplicant_update_config(wpa_s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_getter_wps_device_device_type - Get current device type
|
||||
* @iter: Pointer to incoming dbus message iter
|
||||
* @error: Location to store error on failure
|
||||
* @user_data: Function specific data
|
||||
* Returns: TRUE on success, FALSE on failure
|
||||
*
|
||||
* Getter for "DeviceType" property.
|
||||
*/
|
||||
dbus_bool_t wpas_dbus_getter_wps_device_device_type(
|
||||
const struct wpa_dbus_property_desc *property_desc,
|
||||
DBusMessageIter *iter, DBusError *error, void *user_data)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = user_data;
|
||||
|
||||
if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
|
||||
(char *)
|
||||
wpa_s->conf->device_type,
|
||||
WPS_DEV_TYPE_LEN, error)) {
|
||||
dbus_set_error(error, DBUS_ERROR_FAILED,
|
||||
"%s: error constructing reply", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_setter_wps_device_device_type - Set current device type
|
||||
* @iter: Pointer to incoming dbus message iter
|
||||
* @error: Location to store error on failure
|
||||
* @user_data: Function specific data
|
||||
* Returns: TRUE on success, FALSE on failure
|
||||
*
|
||||
* Setter for "DeviceType" property.
|
||||
*/
|
||||
dbus_bool_t wpas_dbus_setter_wps_device_device_type(
|
||||
const struct wpa_dbus_property_desc *property_desc,
|
||||
DBusMessageIter *iter, DBusError *error, void *user_data)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = user_data;
|
||||
u8 *dev_type;
|
||||
int dev_len;
|
||||
DBusMessageIter variant, array_iter;
|
||||
|
||||
if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
|
||||
return FALSE;
|
||||
|
||||
dbus_message_iter_recurse(iter, &variant);
|
||||
if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY)
|
||||
return FALSE;
|
||||
|
||||
dbus_message_iter_recurse(&variant, &array_iter);
|
||||
dbus_message_iter_get_fixed_array(&array_iter, &dev_type, &dev_len);
|
||||
|
||||
if (dev_len != WPS_DEV_TYPE_LEN)
|
||||
return FALSE;
|
||||
|
||||
os_memcpy(wpa_s->conf->device_type, dev_type, WPS_DEV_TYPE_LEN);
|
||||
wpa_s->conf->changed_parameters |= CFG_CHANGED_DEVICE_TYPE;
|
||||
wpa_supplicant_update_config(wpa_s);
|
||||
|
||||
return TRUE;
|
||||
}
|
1025
wpa_supplicant/dbus/dbus_new_helpers.c
Normal file
1025
wpa_supplicant/dbus/dbus_new_helpers.c
Normal file
File diff suppressed because it is too large
Load Diff
154
wpa_supplicant/dbus/dbus_new_helpers.h
Normal file
154
wpa_supplicant/dbus/dbus_new_helpers.h
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* WPA Supplicant / dbus-based control interface
|
||||
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
|
||||
* Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPA_DBUS_CTRL_H
|
||||
#define WPA_DBUS_CTRL_H
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
typedef DBusMessage * (*WPADBusMethodHandler)(DBusMessage *message,
|
||||
void *user_data);
|
||||
typedef void (*WPADBusArgumentFreeFunction)(void *handler_arg);
|
||||
|
||||
struct wpa_dbus_property_desc;
|
||||
typedef dbus_bool_t (*WPADBusPropertyAccessor)(
|
||||
const struct wpa_dbus_property_desc *property_desc,
|
||||
DBusMessageIter *iter, DBusError *error, void *user_data);
|
||||
#define DECLARE_ACCESSOR(f) \
|
||||
dbus_bool_t f(const struct wpa_dbus_property_desc *property_desc, \
|
||||
DBusMessageIter *iter, DBusError *error, void *user_data)
|
||||
|
||||
struct wpa_dbus_object_desc {
|
||||
DBusConnection *connection;
|
||||
char *path;
|
||||
|
||||
/* list of methods, properties and signals registered with object */
|
||||
const struct wpa_dbus_method_desc *methods;
|
||||
const struct wpa_dbus_signal_desc *signals;
|
||||
const struct wpa_dbus_property_desc *properties;
|
||||
|
||||
/* property changed flags */
|
||||
u8 *prop_changed_flags;
|
||||
|
||||
/* argument for method handlers and properties
|
||||
* getter and setter functions */
|
||||
void *user_data;
|
||||
/* function used to free above argument */
|
||||
WPADBusArgumentFreeFunction user_data_free_func;
|
||||
};
|
||||
|
||||
enum dbus_arg_direction { ARG_IN, ARG_OUT };
|
||||
|
||||
struct wpa_dbus_argument {
|
||||
char *name;
|
||||
char *type;
|
||||
enum dbus_arg_direction dir;
|
||||
};
|
||||
|
||||
#define END_ARGS { NULL, NULL, ARG_IN }
|
||||
|
||||
/**
|
||||
* struct wpa_dbus_method_desc - DBus method description
|
||||
*/
|
||||
struct wpa_dbus_method_desc {
|
||||
/* method name */
|
||||
const char *dbus_method;
|
||||
/* method interface */
|
||||
const char *dbus_interface;
|
||||
/* method handling function */
|
||||
WPADBusMethodHandler method_handler;
|
||||
/* array of arguments */
|
||||
struct wpa_dbus_argument args[4];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wpa_dbus_signal_desc - DBus signal description
|
||||
*/
|
||||
struct wpa_dbus_signal_desc {
|
||||
/* signal name */
|
||||
const char *dbus_signal;
|
||||
/* signal interface */
|
||||
const char *dbus_interface;
|
||||
/* array of arguments */
|
||||
struct wpa_dbus_argument args[4];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wpa_dbus_property_desc - DBus property description
|
||||
*/
|
||||
struct wpa_dbus_property_desc {
|
||||
/* property name */
|
||||
const char *dbus_property;
|
||||
/* property interface */
|
||||
const char *dbus_interface;
|
||||
/* property type signature in DBus type notation */
|
||||
const char *type;
|
||||
/* property getter function */
|
||||
WPADBusPropertyAccessor getter;
|
||||
/* property setter function */
|
||||
WPADBusPropertyAccessor setter;
|
||||
/* other data */
|
||||
const char *data;
|
||||
};
|
||||
|
||||
|
||||
#define WPAS_DBUS_OBJECT_PATH_MAX 150
|
||||
#define WPAS_DBUS_INTERFACE_MAX 150
|
||||
#define WPAS_DBUS_METHOD_SIGNAL_PROP_MAX 50
|
||||
#define WPAS_DBUS_AUTH_MODE_MAX 64
|
||||
|
||||
#define WPA_DBUS_INTROSPECTION_INTERFACE "org.freedesktop.DBus.Introspectable"
|
||||
#define WPA_DBUS_INTROSPECTION_METHOD "Introspect"
|
||||
#define WPA_DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
|
||||
#define WPA_DBUS_PROPERTIES_GET "Get"
|
||||
#define WPA_DBUS_PROPERTIES_SET "Set"
|
||||
#define WPA_DBUS_PROPERTIES_GETALL "GetAll"
|
||||
|
||||
void free_dbus_object_desc(struct wpa_dbus_object_desc *obj_dsc);
|
||||
|
||||
int wpa_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface, char *dbus_path,
|
||||
char *dbus_service,
|
||||
struct wpa_dbus_object_desc *obj_desc);
|
||||
|
||||
int wpa_dbus_register_object_per_iface(
|
||||
struct wpas_dbus_priv *ctrl_iface,
|
||||
const char *path, const char *ifname,
|
||||
struct wpa_dbus_object_desc *obj_desc);
|
||||
|
||||
int wpa_dbus_unregister_object_per_iface(
|
||||
struct wpas_dbus_priv *ctrl_iface,
|
||||
const char *path);
|
||||
|
||||
dbus_bool_t wpa_dbus_get_object_properties(struct wpas_dbus_priv *iface,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
DBusMessageIter *iter);
|
||||
|
||||
|
||||
void wpa_dbus_flush_all_changed_properties(DBusConnection *con);
|
||||
|
||||
void wpa_dbus_flush_object_changed_properties(DBusConnection *con,
|
||||
const char *path);
|
||||
|
||||
void wpa_dbus_mark_property_changed(struct wpas_dbus_priv *iface,
|
||||
const char *path, const char *interface,
|
||||
const char *property);
|
||||
|
||||
DBusMessage * wpa_dbus_introspect(DBusMessage *message,
|
||||
struct wpa_dbus_object_desc *obj_dsc);
|
||||
|
||||
char * wpas_dbus_new_decompose_object_path(const char *path, const char *sep,
|
||||
char **item);
|
||||
|
||||
DBusMessage *wpas_dbus_reply_new_from_error(DBusMessage *message,
|
||||
DBusError *error,
|
||||
const char *fallback_name,
|
||||
const char *fallback_string);
|
||||
|
||||
#endif /* WPA_DBUS_CTRL_H */
|
286
wpa_supplicant/dbus/dbus_new_introspect.c
Normal file
286
wpa_supplicant/dbus/dbus_new_introspect.c
Normal file
@ -0,0 +1,286 @@
|
||||
/*
|
||||
* wpa_supplicant - D-Bus introspection
|
||||
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
|
||||
* Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
|
||||
* Copyright (c) 2010, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/list.h"
|
||||
#include "utils/wpabuf.h"
|
||||
#include "dbus_common_i.h"
|
||||
#include "dbus_new_helpers.h"
|
||||
|
||||
|
||||
struct interfaces {
|
||||
struct dl_list list;
|
||||
char *dbus_interface;
|
||||
struct wpabuf *xml;
|
||||
};
|
||||
|
||||
|
||||
static struct interfaces * add_interface(struct dl_list *list,
|
||||
const char *dbus_interface)
|
||||
{
|
||||
struct interfaces *iface;
|
||||
|
||||
dl_list_for_each(iface, list, struct interfaces, list) {
|
||||
if (os_strcmp(iface->dbus_interface, dbus_interface) == 0)
|
||||
return iface; /* already in the list */
|
||||
}
|
||||
|
||||
iface = os_zalloc(sizeof(struct interfaces));
|
||||
if (!iface)
|
||||
return NULL;
|
||||
iface->dbus_interface = os_strdup(dbus_interface);
|
||||
iface->xml = wpabuf_alloc(15000);
|
||||
if (iface->dbus_interface == NULL || iface->xml == NULL) {
|
||||
os_free(iface->dbus_interface);
|
||||
wpabuf_free(iface->xml);
|
||||
os_free(iface);
|
||||
return NULL;
|
||||
}
|
||||
wpabuf_printf(iface->xml, "<interface name=\"%s\">", dbus_interface);
|
||||
dl_list_add_tail(list, &iface->list);
|
||||
return iface;
|
||||
}
|
||||
|
||||
|
||||
static void add_arg(struct wpabuf *xml, const char *name, const char *type,
|
||||
const char *direction)
|
||||
{
|
||||
wpabuf_printf(xml, "<arg name=\"%s\"", name);
|
||||
if (type)
|
||||
wpabuf_printf(xml, " type=\"%s\"", type);
|
||||
if (direction)
|
||||
wpabuf_printf(xml, " direction=\"%s\"", direction);
|
||||
wpabuf_put_str(xml, "/>");
|
||||
}
|
||||
|
||||
|
||||
static void add_entry(struct wpabuf *xml, const char *type, const char *name,
|
||||
const struct wpa_dbus_argument *args, int include_dir)
|
||||
{
|
||||
const struct wpa_dbus_argument *arg;
|
||||
|
||||
if (args == NULL || args->name == NULL) {
|
||||
wpabuf_printf(xml, "<%s name=\"%s\"/>", type, name);
|
||||
return;
|
||||
}
|
||||
wpabuf_printf(xml, "<%s name=\"%s\">", type, name);
|
||||
for (arg = args; arg && arg->name; arg++) {
|
||||
add_arg(xml, arg->name, arg->type,
|
||||
include_dir ? (arg->dir == ARG_IN ? "in" : "out") :
|
||||
NULL);
|
||||
}
|
||||
wpabuf_printf(xml, "</%s>", type);
|
||||
}
|
||||
|
||||
|
||||
static void add_property(struct wpabuf *xml,
|
||||
const struct wpa_dbus_property_desc *dsc)
|
||||
{
|
||||
wpabuf_printf(xml, "<property name=\"%s\" type=\"%s\" "
|
||||
"access=\"%s%s\"/>",
|
||||
dsc->dbus_property, dsc->type,
|
||||
dsc->getter ? "read" : "",
|
||||
dsc->setter ? "write" : "");
|
||||
}
|
||||
|
||||
|
||||
static void extract_interfaces_methods(
|
||||
struct dl_list *list, const struct wpa_dbus_method_desc *methods)
|
||||
{
|
||||
const struct wpa_dbus_method_desc *dsc;
|
||||
struct interfaces *iface;
|
||||
|
||||
for (dsc = methods; dsc && dsc->dbus_method; dsc++) {
|
||||
iface = add_interface(list, dsc->dbus_interface);
|
||||
if (iface)
|
||||
add_entry(iface->xml, "method", dsc->dbus_method,
|
||||
dsc->args, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void extract_interfaces_signals(
|
||||
struct dl_list *list, const struct wpa_dbus_signal_desc *signals)
|
||||
{
|
||||
const struct wpa_dbus_signal_desc *dsc;
|
||||
struct interfaces *iface;
|
||||
|
||||
for (dsc = signals; dsc && dsc->dbus_signal; dsc++) {
|
||||
iface = add_interface(list, dsc->dbus_interface);
|
||||
if (iface)
|
||||
add_entry(iface->xml, "signal", dsc->dbus_signal,
|
||||
dsc->args, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void extract_interfaces_properties(
|
||||
struct dl_list *list, const struct wpa_dbus_property_desc *properties)
|
||||
{
|
||||
const struct wpa_dbus_property_desc *dsc;
|
||||
struct interfaces *iface;
|
||||
|
||||
for (dsc = properties; dsc && dsc->dbus_property; dsc++) {
|
||||
iface = add_interface(list, dsc->dbus_interface);
|
||||
if (iface)
|
||||
add_property(iface->xml, dsc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* extract_interfaces - Extract interfaces from methods, signals and props
|
||||
* @list: Interface list to be filled
|
||||
* @obj_dsc: Description of object from which interfaces will be extracted
|
||||
*
|
||||
* Iterates over all methods, signals, and properties registered with an
|
||||
* object and collects all declared DBus interfaces and create interfaces'
|
||||
* node in XML root node for each. Returned list elements contain interface
|
||||
* name and XML node of corresponding interface.
|
||||
*/
|
||||
static void extract_interfaces(struct dl_list *list,
|
||||
struct wpa_dbus_object_desc *obj_dsc)
|
||||
{
|
||||
extract_interfaces_methods(list, obj_dsc->methods);
|
||||
extract_interfaces_signals(list, obj_dsc->signals);
|
||||
extract_interfaces_properties(list, obj_dsc->properties);
|
||||
}
|
||||
|
||||
|
||||
static void add_interfaces(struct dl_list *list, struct wpabuf *xml)
|
||||
{
|
||||
struct interfaces *iface, *n;
|
||||
|
||||
dl_list_for_each_safe(iface, n, list, struct interfaces, list) {
|
||||
if (wpabuf_len(iface->xml) + 20 < wpabuf_tailroom(xml)) {
|
||||
wpabuf_put_buf(xml, iface->xml);
|
||||
wpabuf_put_str(xml, "</interface>");
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"dbus: Not enough room for add_interfaces inspect data: tailroom %u, add %u",
|
||||
(unsigned int) wpabuf_tailroom(xml),
|
||||
(unsigned int) wpabuf_len(iface->xml));
|
||||
}
|
||||
dl_list_del(&iface->list);
|
||||
wpabuf_free(iface->xml);
|
||||
os_free(iface->dbus_interface);
|
||||
os_free(iface);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void add_child_nodes(struct wpabuf *xml, DBusConnection *con,
|
||||
const char *path)
|
||||
{
|
||||
char **children;
|
||||
int i;
|
||||
|
||||
/* add child nodes to introspection tree */
|
||||
dbus_connection_list_registered(con, path, &children);
|
||||
for (i = 0; children[i]; i++)
|
||||
wpabuf_printf(xml, "<node name=\"%s\"/>", children[i]);
|
||||
dbus_free_string_array(children);
|
||||
}
|
||||
|
||||
|
||||
static void add_introspectable_interface(struct wpabuf *xml)
|
||||
{
|
||||
wpabuf_printf(xml, "<interface name=\"%s\">"
|
||||
"<method name=\"%s\">"
|
||||
"<arg name=\"data\" type=\"s\" direction=\"out\"/>"
|
||||
"</method>"
|
||||
"</interface>",
|
||||
WPA_DBUS_INTROSPECTION_INTERFACE,
|
||||
WPA_DBUS_INTROSPECTION_METHOD);
|
||||
}
|
||||
|
||||
|
||||
static void add_properties_interface(struct wpabuf *xml)
|
||||
{
|
||||
wpabuf_printf(xml, "<interface name=\"%s\">",
|
||||
WPA_DBUS_PROPERTIES_INTERFACE);
|
||||
|
||||
wpabuf_printf(xml, "<method name=\"%s\">", WPA_DBUS_PROPERTIES_GET);
|
||||
add_arg(xml, "interface", "s", "in");
|
||||
add_arg(xml, "propname", "s", "in");
|
||||
add_arg(xml, "value", "v", "out");
|
||||
wpabuf_put_str(xml, "</method>");
|
||||
|
||||
wpabuf_printf(xml, "<method name=\"%s\">", WPA_DBUS_PROPERTIES_GETALL);
|
||||
add_arg(xml, "interface", "s", "in");
|
||||
add_arg(xml, "props", "a{sv}", "out");
|
||||
wpabuf_put_str(xml, "</method>");
|
||||
|
||||
wpabuf_printf(xml, "<method name=\"%s\">", WPA_DBUS_PROPERTIES_SET);
|
||||
add_arg(xml, "interface", "s", "in");
|
||||
add_arg(xml, "propname", "s", "in");
|
||||
add_arg(xml, "value", "v", "in");
|
||||
wpabuf_put_str(xml, "</method>");
|
||||
|
||||
wpabuf_put_str(xml, "</interface>");
|
||||
}
|
||||
|
||||
|
||||
static void add_wpas_interfaces(struct wpabuf *xml,
|
||||
struct wpa_dbus_object_desc *obj_dsc)
|
||||
{
|
||||
struct dl_list ifaces;
|
||||
|
||||
dl_list_init(&ifaces);
|
||||
extract_interfaces(&ifaces, obj_dsc);
|
||||
add_interfaces(&ifaces, xml);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_dbus_introspect - Responds for Introspect calls on object
|
||||
* @message: Message with Introspect call
|
||||
* @obj_dsc: Object description on which Introspect was called
|
||||
* Returns: Message with introspection result XML string as only argument
|
||||
*
|
||||
* Iterates over all methods, signals and properties registered with
|
||||
* object and generates introspection data for the object as XML string.
|
||||
*/
|
||||
DBusMessage * wpa_dbus_introspect(DBusMessage *message,
|
||||
struct wpa_dbus_object_desc *obj_dsc)
|
||||
{
|
||||
|
||||
DBusMessage *reply;
|
||||
struct wpabuf *xml;
|
||||
|
||||
xml = wpabuf_alloc(30000);
|
||||
if (xml == NULL)
|
||||
return NULL;
|
||||
|
||||
wpabuf_put_str(xml, "<?xml version=\"1.0\"?>\n");
|
||||
wpabuf_put_str(xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
|
||||
wpabuf_put_str(xml, "<node>");
|
||||
|
||||
add_introspectable_interface(xml);
|
||||
add_properties_interface(xml);
|
||||
add_wpas_interfaces(xml, obj_dsc);
|
||||
add_child_nodes(xml, obj_dsc->connection,
|
||||
dbus_message_get_path(message));
|
||||
|
||||
wpabuf_put_str(xml, "</node>\n");
|
||||
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (reply) {
|
||||
const char *intro_str = wpabuf_head(xml);
|
||||
|
||||
dbus_message_append_args(reply, DBUS_TYPE_STRING, &intro_str,
|
||||
DBUS_TYPE_INVALID);
|
||||
}
|
||||
wpabuf_free(xml);
|
||||
|
||||
return reply;
|
||||
}
|
5
wpa_supplicant/dbus/fi.w1.wpa_supplicant1.service.in
Normal file
5
wpa_supplicant/dbus/fi.w1.wpa_supplicant1.service.in
Normal file
@ -0,0 +1,5 @@
|
||||
[D-BUS Service]
|
||||
Name=fi.w1.wpa_supplicant1
|
||||
Exec=@BINDIR@/wpa_supplicant -u
|
||||
User=root
|
||||
SystemdService=wpa_supplicant.service
|
635
wpa_supplicant/defconfig
Normal file
635
wpa_supplicant/defconfig
Normal file
@ -0,0 +1,635 @@
|
||||
# Example wpa_supplicant build time configuration
|
||||
#
|
||||
# This file lists the configuration options that are used when building the
|
||||
# wpa_supplicant binary. All lines starting with # are ignored. Configuration
|
||||
# option lines must be commented out complete, if they are not to be included,
|
||||
# i.e., just setting VARIABLE=n is not disabling that variable.
|
||||
#
|
||||
# This file is included in Makefile, so variables like CFLAGS and LIBS can also
|
||||
# be modified from here. In most cases, these lines should use += in order not
|
||||
# to override previous values of the variables.
|
||||
|
||||
|
||||
# Uncomment following two lines and fix the paths if you have installed OpenSSL
|
||||
# or GnuTLS in non-default location
|
||||
#CFLAGS += -I/usr/local/openssl/include
|
||||
#LIBS += -L/usr/local/openssl/lib
|
||||
|
||||
# Some Red Hat versions seem to include kerberos header files from OpenSSL, but
|
||||
# the kerberos files are not in the default include path. Following line can be
|
||||
# used to fix build issues on such systems (krb5.h not found).
|
||||
#CFLAGS += -I/usr/include/kerberos
|
||||
|
||||
# Driver interface for generic Linux wireless extensions
|
||||
# Note: WEXT is deprecated in the current Linux kernel version and no new
|
||||
# functionality is added to it. nl80211-based interface is the new
|
||||
# replacement for WEXT and its use allows wpa_supplicant to properly control
|
||||
# the driver to improve existing functionality like roaming and to support new
|
||||
# functionality.
|
||||
CONFIG_DRIVER_WEXT=y
|
||||
|
||||
# Driver interface for Linux drivers using the nl80211 kernel interface
|
||||
CONFIG_DRIVER_NL80211=y
|
||||
|
||||
# QCA vendor extensions to nl80211
|
||||
#CONFIG_DRIVER_NL80211_QCA=y
|
||||
|
||||
# driver_nl80211.c requires libnl. If you are compiling it yourself
|
||||
# you may need to point hostapd to your version of libnl.
|
||||
#
|
||||
#CFLAGS += -I$<path to libnl include files>
|
||||
#LIBS += -L$<path to libnl library files>
|
||||
|
||||
# Use libnl v2.0 (or 3.0) libraries.
|
||||
#CONFIG_LIBNL20=y
|
||||
|
||||
# Use libnl 3.2 libraries (if this is selected, CONFIG_LIBNL20 is ignored)
|
||||
CONFIG_LIBNL32=y
|
||||
|
||||
|
||||
# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
|
||||
#CONFIG_DRIVER_BSD=y
|
||||
#CFLAGS += -I/usr/local/include
|
||||
#LIBS += -L/usr/local/lib
|
||||
#LIBS_p += -L/usr/local/lib
|
||||
#LIBS_c += -L/usr/local/lib
|
||||
|
||||
# Driver interface for Windows NDIS
|
||||
#CONFIG_DRIVER_NDIS=y
|
||||
#CFLAGS += -I/usr/include/w32api/ddk
|
||||
#LIBS += -L/usr/local/lib
|
||||
# For native build using mingw
|
||||
#CONFIG_NATIVE_WINDOWS=y
|
||||
# Additional directories for cross-compilation on Linux host for mingw target
|
||||
#CFLAGS += -I/opt/mingw/mingw32/include/ddk
|
||||
#LIBS += -L/opt/mingw/mingw32/lib
|
||||
#CC=mingw32-gcc
|
||||
# By default, driver_ndis uses WinPcap for low-level operations. This can be
|
||||
# replaced with the following option which replaces WinPcap calls with NDISUIO.
|
||||
# However, this requires that WZC is disabled (net stop wzcsvc) before starting
|
||||
# wpa_supplicant.
|
||||
# CONFIG_USE_NDISUIO=y
|
||||
|
||||
# Driver interface for wired Ethernet drivers
|
||||
CONFIG_DRIVER_WIRED=y
|
||||
|
||||
# Driver interface for MACsec capable Qualcomm Atheros drivers
|
||||
#CONFIG_DRIVER_MACSEC_QCA=y
|
||||
|
||||
# Driver interface for Linux MACsec drivers
|
||||
CONFIG_DRIVER_MACSEC_LINUX=y
|
||||
|
||||
# Driver interface for the Broadcom RoboSwitch family
|
||||
#CONFIG_DRIVER_ROBOSWITCH=y
|
||||
|
||||
# Driver interface for no driver (e.g., WPS ER only)
|
||||
#CONFIG_DRIVER_NONE=y
|
||||
|
||||
# Solaris libraries
|
||||
#LIBS += -lsocket -ldlpi -lnsl
|
||||
#LIBS_c += -lsocket
|
||||
|
||||
# Enable IEEE 802.1X Supplicant (automatically included if any EAP method or
|
||||
# MACsec is included)
|
||||
CONFIG_IEEE8021X_EAPOL=y
|
||||
|
||||
# EAP-MD5
|
||||
CONFIG_EAP_MD5=y
|
||||
|
||||
# EAP-MSCHAPv2
|
||||
CONFIG_EAP_MSCHAPV2=y
|
||||
|
||||
# EAP-TLS
|
||||
CONFIG_EAP_TLS=y
|
||||
|
||||
# EAL-PEAP
|
||||
CONFIG_EAP_PEAP=y
|
||||
|
||||
# EAP-TTLS
|
||||
CONFIG_EAP_TTLS=y
|
||||
|
||||
# EAP-FAST
|
||||
CONFIG_EAP_FAST=y
|
||||
|
||||
# EAP-TEAP
|
||||
# Note: The current EAP-TEAP implementation is experimental and should not be
|
||||
# enabled for production use. The IETF RFC 7170 that defines EAP-TEAP has number
|
||||
# of conflicting statements and missing details and the implementation has
|
||||
# vendor specific workarounds for those and as such, may not interoperate with
|
||||
# any other implementation. This should not be used for anything else than
|
||||
# experimentation and interoperability testing until those issues has been
|
||||
# resolved.
|
||||
#CONFIG_EAP_TEAP=y
|
||||
|
||||
# EAP-GTC
|
||||
CONFIG_EAP_GTC=y
|
||||
|
||||
# EAP-OTP
|
||||
CONFIG_EAP_OTP=y
|
||||
|
||||
# EAP-SIM (enable CONFIG_PCSC, if EAP-SIM is used)
|
||||
#CONFIG_EAP_SIM=y
|
||||
|
||||
# Enable SIM simulator (Milenage) for EAP-SIM
|
||||
#CONFIG_SIM_SIMULATOR=y
|
||||
|
||||
# EAP-PSK (experimental; this is _not_ needed for WPA-PSK)
|
||||
#CONFIG_EAP_PSK=y
|
||||
|
||||
# EAP-pwd (secure authentication using only a password)
|
||||
CONFIG_EAP_PWD=y
|
||||
|
||||
# EAP-PAX
|
||||
CONFIG_EAP_PAX=y
|
||||
|
||||
# LEAP
|
||||
CONFIG_EAP_LEAP=y
|
||||
|
||||
# EAP-AKA (enable CONFIG_PCSC, if EAP-AKA is used)
|
||||
#CONFIG_EAP_AKA=y
|
||||
|
||||
# EAP-AKA' (enable CONFIG_PCSC, if EAP-AKA' is used).
|
||||
# This requires CONFIG_EAP_AKA to be enabled, too.
|
||||
#CONFIG_EAP_AKA_PRIME=y
|
||||
|
||||
# Enable USIM simulator (Milenage) for EAP-AKA
|
||||
#CONFIG_USIM_SIMULATOR=y
|
||||
|
||||
# EAP-SAKE
|
||||
CONFIG_EAP_SAKE=y
|
||||
|
||||
# EAP-GPSK
|
||||
CONFIG_EAP_GPSK=y
|
||||
# Include support for optional SHA256 cipher suite in EAP-GPSK
|
||||
CONFIG_EAP_GPSK_SHA256=y
|
||||
|
||||
# EAP-TNC and related Trusted Network Connect support (experimental)
|
||||
CONFIG_EAP_TNC=y
|
||||
|
||||
# Wi-Fi Protected Setup (WPS)
|
||||
CONFIG_WPS=y
|
||||
# Enable WPS external registrar functionality
|
||||
#CONFIG_WPS_ER=y
|
||||
# Disable credentials for an open network by default when acting as a WPS
|
||||
# registrar.
|
||||
#CONFIG_WPS_REG_DISABLE_OPEN=y
|
||||
# Enable WPS support with NFC config method
|
||||
#CONFIG_WPS_NFC=y
|
||||
|
||||
# EAP-IKEv2
|
||||
CONFIG_EAP_IKEV2=y
|
||||
|
||||
# EAP-EKE
|
||||
#CONFIG_EAP_EKE=y
|
||||
|
||||
# MACsec
|
||||
CONFIG_MACSEC=y
|
||||
|
||||
# PKCS#12 (PFX) support (used to read private key and certificate file from
|
||||
# a file that usually has extension .p12 or .pfx)
|
||||
CONFIG_PKCS12=y
|
||||
|
||||
# Smartcard support (i.e., private key on a smartcard), e.g., with openssl
|
||||
# engine.
|
||||
CONFIG_SMARTCARD=y
|
||||
|
||||
# PC/SC interface for smartcards (USIM, GSM SIM)
|
||||
# Enable this if EAP-SIM or EAP-AKA is included
|
||||
#CONFIG_PCSC=y
|
||||
|
||||
# Support HT overrides (disable HT/HT40, mask MCS rates, etc.)
|
||||
#CONFIG_HT_OVERRIDES=y
|
||||
|
||||
# Support VHT overrides (disable VHT, mask MCS rates, etc.)
|
||||
#CONFIG_VHT_OVERRIDES=y
|
||||
|
||||
# Development testing
|
||||
#CONFIG_EAPOL_TEST=y
|
||||
|
||||
# Select control interface backend for external programs, e.g, wpa_cli:
|
||||
# unix = UNIX domain sockets (default for Linux/*BSD)
|
||||
# udp = UDP sockets using localhost (127.0.0.1)
|
||||
# udp6 = UDP IPv6 sockets using localhost (::1)
|
||||
# named_pipe = Windows Named Pipe (default for Windows)
|
||||
# udp-remote = UDP sockets with remote access (only for tests systems/purpose)
|
||||
# udp6-remote = UDP IPv6 sockets with remote access (only for tests purpose)
|
||||
# y = use default (backwards compatibility)
|
||||
# If this option is commented out, control interface is not included in the
|
||||
# build.
|
||||
CONFIG_CTRL_IFACE=y
|
||||
|
||||
# Include support for GNU Readline and History Libraries in wpa_cli.
|
||||
# When building a wpa_cli binary for distribution, please note that these
|
||||
# libraries are licensed under GPL and as such, BSD license may not apply for
|
||||
# the resulting binary.
|
||||
#CONFIG_READLINE=y
|
||||
|
||||
# Include internal line edit mode in wpa_cli. This can be used as a replacement
|
||||
# for GNU Readline to provide limited command line editing and history support.
|
||||
#CONFIG_WPA_CLI_EDIT=y
|
||||
|
||||
# Remove debugging code that is printing out debug message to stdout.
|
||||
# This can be used to reduce the size of the wpa_supplicant considerably
|
||||
# if debugging code is not needed. The size reduction can be around 35%
|
||||
# (e.g., 90 kB).
|
||||
#CONFIG_NO_STDOUT_DEBUG=y
|
||||
|
||||
# Remove WPA support, e.g., for wired-only IEEE 802.1X supplicant, to save
|
||||
# 35-50 kB in code size.
|
||||
#CONFIG_NO_WPA=y
|
||||
|
||||
# Remove IEEE 802.11i/WPA-Personal ASCII passphrase support
|
||||
# This option can be used to reduce code size by removing support for
|
||||
# converting ASCII passphrases into PSK. If this functionality is removed, the
|
||||
# PSK can only be configured as the 64-octet hexstring (e.g., from
|
||||
# wpa_passphrase). This saves about 0.5 kB in code size.
|
||||
#CONFIG_NO_WPA_PASSPHRASE=y
|
||||
|
||||
# Simultaneous Authentication of Equals (SAE), WPA3-Personal
|
||||
CONFIG_SAE=y
|
||||
|
||||
# Disable scan result processing (ap_scan=1) to save code size by about 1 kB.
|
||||
# This can be used if ap_scan=1 mode is never enabled.
|
||||
#CONFIG_NO_SCAN_PROCESSING=y
|
||||
|
||||
# Select configuration backend:
|
||||
# file = text file (e.g., wpa_supplicant.conf; note: the configuration file
|
||||
# path is given on command line, not here; this option is just used to
|
||||
# select the backend that allows configuration files to be used)
|
||||
# winreg = Windows registry (see win_example.reg for an example)
|
||||
CONFIG_BACKEND=file
|
||||
|
||||
# Remove configuration write functionality (i.e., to allow the configuration
|
||||
# file to be updated based on runtime configuration changes). The runtime
|
||||
# configuration can still be changed, the changes are just not going to be
|
||||
# persistent over restarts. This option can be used to reduce code size by
|
||||
# about 3.5 kB.
|
||||
#CONFIG_NO_CONFIG_WRITE=y
|
||||
|
||||
# Remove support for configuration blobs to reduce code size by about 1.5 kB.
|
||||
#CONFIG_NO_CONFIG_BLOBS=y
|
||||
|
||||
# Select program entry point implementation:
|
||||
# main = UNIX/POSIX like main() function (default)
|
||||
# main_winsvc = Windows service (read parameters from registry)
|
||||
# main_none = Very basic example (development use only)
|
||||
#CONFIG_MAIN=main
|
||||
|
||||
# Select wrapper for operating system and C library specific functions
|
||||
# unix = UNIX/POSIX like systems (default)
|
||||
# win32 = Windows systems
|
||||
# none = Empty template
|
||||
#CONFIG_OS=unix
|
||||
|
||||
# Select event loop implementation
|
||||
# eloop = select() loop (default)
|
||||
# eloop_win = Windows events and WaitForMultipleObject() loop
|
||||
#CONFIG_ELOOP=eloop
|
||||
|
||||
# Should we use poll instead of select? Select is used by default.
|
||||
#CONFIG_ELOOP_POLL=y
|
||||
|
||||
# Should we use epoll instead of select? Select is used by default.
|
||||
#CONFIG_ELOOP_EPOLL=y
|
||||
|
||||
# Should we use kqueue instead of select? Select is used by default.
|
||||
#CONFIG_ELOOP_KQUEUE=y
|
||||
|
||||
# Select layer 2 packet implementation
|
||||
# linux = Linux packet socket (default)
|
||||
# pcap = libpcap/libdnet/WinPcap
|
||||
# freebsd = FreeBSD libpcap
|
||||
# winpcap = WinPcap with receive thread
|
||||
# ndis = Windows NDISUIO (note: requires CONFIG_USE_NDISUIO=y)
|
||||
# none = Empty template
|
||||
#CONFIG_L2_PACKET=linux
|
||||
|
||||
# Disable Linux packet socket workaround applicable for station interface
|
||||
# in a bridge for EAPOL frames. This should be uncommented only if the kernel
|
||||
# is known to not have the regression issue in packet socket behavior with
|
||||
# bridge interfaces (commit 'bridge: respect RFC2863 operational state')').
|
||||
#CONFIG_NO_LINUX_PACKET_SOCKET_WAR=y
|
||||
|
||||
# Support Operating Channel Validation
|
||||
#CONFIG_OCV=y
|
||||
|
||||
# Select TLS implementation
|
||||
# openssl = OpenSSL (default)
|
||||
# gnutls = GnuTLS
|
||||
# internal = Internal TLSv1 implementation (experimental)
|
||||
# linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental)
|
||||
# none = Empty template
|
||||
#CONFIG_TLS=openssl
|
||||
|
||||
# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
|
||||
# can be enabled to get a stronger construction of messages when block ciphers
|
||||
# are used. It should be noted that some existing TLS v1.0 -based
|
||||
# implementation may not be compatible with TLS v1.1 message (ClientHello is
|
||||
# sent prior to negotiating which version will be used)
|
||||
#CONFIG_TLSV11=y
|
||||
|
||||
# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2)
|
||||
# can be enabled to enable use of stronger crypto algorithms. It should be
|
||||
# noted that some existing TLS v1.0 -based implementation may not be compatible
|
||||
# with TLS v1.2 message (ClientHello is sent prior to negotiating which version
|
||||
# will be used)
|
||||
#CONFIG_TLSV12=y
|
||||
|
||||
# Select which ciphers to use by default with OpenSSL if the user does not
|
||||
# specify them.
|
||||
#CONFIG_TLS_DEFAULT_CIPHERS="DEFAULT:!EXP:!LOW"
|
||||
|
||||
# If CONFIG_TLS=internal is used, additional library and include paths are
|
||||
# needed for LibTomMath. Alternatively, an integrated, minimal version of
|
||||
# LibTomMath can be used. See beginning of libtommath.c for details on benefits
|
||||
# and drawbacks of this option.
|
||||
#CONFIG_INTERNAL_LIBTOMMATH=y
|
||||
#ifndef CONFIG_INTERNAL_LIBTOMMATH
|
||||
#LTM_PATH=/usr/src/libtommath-0.39
|
||||
#CFLAGS += -I$(LTM_PATH)
|
||||
#LIBS += -L$(LTM_PATH)
|
||||
#LIBS_p += -L$(LTM_PATH)
|
||||
#endif
|
||||
# At the cost of about 4 kB of additional binary size, the internal LibTomMath
|
||||
# can be configured to include faster routines for exptmod, sqr, and div to
|
||||
# speed up DH and RSA calculation considerably
|
||||
#CONFIG_INTERNAL_LIBTOMMATH_FAST=y
|
||||
|
||||
# Include NDIS event processing through WMI into wpa_supplicant/wpasvc.
|
||||
# This is only for Windows builds and requires WMI-related header files and
|
||||
# WbemUuid.Lib from Platform SDK even when building with MinGW.
|
||||
#CONFIG_NDIS_EVENTS_INTEGRATED=y
|
||||
#PLATFORMSDKLIB="/opt/Program Files/Microsoft Platform SDK/Lib"
|
||||
|
||||
# Add support for new DBus control interface
|
||||
# (fi.w1.wpa_supplicant1)
|
||||
CONFIG_CTRL_IFACE_DBUS_NEW=y
|
||||
|
||||
# Add introspection support for new DBus control interface
|
||||
CONFIG_CTRL_IFACE_DBUS_INTRO=y
|
||||
|
||||
# Add support for loading EAP methods dynamically as shared libraries.
|
||||
# When this option is enabled, each EAP method can be either included
|
||||
# statically (CONFIG_EAP_<method>=y) or dynamically (CONFIG_EAP_<method>=dyn).
|
||||
# Dynamic EAP methods are build as shared objects (eap_*.so) and they need to
|
||||
# be loaded in the beginning of the wpa_supplicant configuration file
|
||||
# (see load_dynamic_eap parameter in the example file) before being used in
|
||||
# the network blocks.
|
||||
#
|
||||
# Note that some shared parts of EAP methods are included in the main program
|
||||
# and in order to be able to use dynamic EAP methods using these parts, the
|
||||
# main program must have been build with the EAP method enabled (=y or =dyn).
|
||||
# This means that EAP-TLS/PEAP/TTLS/FAST cannot be added as dynamic libraries
|
||||
# unless at least one of them was included in the main build to force inclusion
|
||||
# of the shared code. Similarly, at least one of EAP-SIM/AKA must be included
|
||||
# in the main build to be able to load these methods dynamically.
|
||||
#
|
||||
# Please also note that using dynamic libraries will increase the total binary
|
||||
# size. Thus, it may not be the best option for targets that have limited
|
||||
# amount of memory/flash.
|
||||
#CONFIG_DYNAMIC_EAP_METHODS=y
|
||||
|
||||
# IEEE Std 802.11r-2008 (Fast BSS Transition) for station mode
|
||||
CONFIG_IEEE80211R=y
|
||||
|
||||
# Add support for writing debug log to a file (/tmp/wpa_supplicant-log-#.txt)
|
||||
CONFIG_DEBUG_FILE=y
|
||||
|
||||
# Send debug messages to syslog instead of stdout
|
||||
CONFIG_DEBUG_SYSLOG=y
|
||||
# Set syslog facility for debug messages
|
||||
#CONFIG_DEBUG_SYSLOG_FACILITY=LOG_DAEMON
|
||||
|
||||
# Add support for sending all debug messages (regardless of debug verbosity)
|
||||
# to the Linux kernel tracing facility. This helps debug the entire stack by
|
||||
# making it easy to record everything happening from the driver up into the
|
||||
# same file, e.g., using trace-cmd.
|
||||
#CONFIG_DEBUG_LINUX_TRACING=y
|
||||
|
||||
# Add support for writing debug log to Android logcat instead of standard
|
||||
# output
|
||||
#CONFIG_ANDROID_LOG=y
|
||||
|
||||
# Enable privilege separation (see README 'Privilege separation' for details)
|
||||
#CONFIG_PRIVSEP=y
|
||||
|
||||
# Enable mitigation against certain attacks against TKIP by delaying Michael
|
||||
# MIC error reports by a random amount of time between 0 and 60 seconds
|
||||
#CONFIG_DELAYED_MIC_ERROR_REPORT=y
|
||||
|
||||
# Enable tracing code for developer debugging
|
||||
# This tracks use of memory allocations and other registrations and reports
|
||||
# incorrect use with a backtrace of call (or allocation) location.
|
||||
#CONFIG_WPA_TRACE=y
|
||||
# For BSD, uncomment these.
|
||||
#LIBS += -lexecinfo
|
||||
#LIBS_p += -lexecinfo
|
||||
#LIBS_c += -lexecinfo
|
||||
|
||||
# Use libbfd to get more details for developer debugging
|
||||
# This enables use of libbfd to get more detailed symbols for the backtraces
|
||||
# generated by CONFIG_WPA_TRACE=y.
|
||||
#CONFIG_WPA_TRACE_BFD=y
|
||||
# For BSD, uncomment these.
|
||||
#LIBS += -lbfd -liberty -lz
|
||||
#LIBS_p += -lbfd -liberty -lz
|
||||
#LIBS_c += -lbfd -liberty -lz
|
||||
|
||||
# wpa_supplicant depends on strong random number generation being available
|
||||
# from the operating system. os_get_random() function is used to fetch random
|
||||
# data when needed, e.g., for key generation. On Linux and BSD systems, this
|
||||
# works by reading /dev/urandom. It should be noted that the OS entropy pool
|
||||
# needs to be properly initialized before wpa_supplicant is started. This is
|
||||
# important especially on embedded devices that do not have a hardware random
|
||||
# number generator and may by default start up with minimal entropy available
|
||||
# for random number generation.
|
||||
#
|
||||
# As a safety net, wpa_supplicant is by default trying to internally collect
|
||||
# additional entropy for generating random data to mix in with the data fetched
|
||||
# from the OS. This by itself is not considered to be very strong, but it may
|
||||
# help in cases where the system pool is not initialized properly. However, it
|
||||
# is very strongly recommended that the system pool is initialized with enough
|
||||
# entropy either by using hardware assisted random number generator or by
|
||||
# storing state over device reboots.
|
||||
#
|
||||
# wpa_supplicant can be configured to maintain its own entropy store over
|
||||
# restarts to enhance random number generation. This is not perfect, but it is
|
||||
# much more secure than using the same sequence of random numbers after every
|
||||
# reboot. This can be enabled with -e<entropy file> command line option. The
|
||||
# specified file needs to be readable and writable by wpa_supplicant.
|
||||
#
|
||||
# If the os_get_random() is known to provide strong random data (e.g., on
|
||||
# Linux/BSD, the board in question is known to have reliable source of random
|
||||
# data from /dev/urandom), the internal wpa_supplicant random pool can be
|
||||
# disabled. This will save some in binary size and CPU use. However, this
|
||||
# should only be considered for builds that are known to be used on devices
|
||||
# that meet the requirements described above.
|
||||
#CONFIG_NO_RANDOM_POOL=y
|
||||
|
||||
# Should we attempt to use the getrandom(2) call that provides more reliable
|
||||
# yet secure randomness source than /dev/random on Linux 3.17 and newer.
|
||||
# Requires glibc 2.25 to build, falls back to /dev/random if unavailable.
|
||||
#CONFIG_GETRANDOM=y
|
||||
|
||||
# IEEE 802.11ac (Very High Throughput) support (mainly for AP mode)
|
||||
CONFIG_IEEE80211AC=y
|
||||
|
||||
# Wireless Network Management (IEEE Std 802.11v-2011)
|
||||
# Note: This is experimental and not complete implementation.
|
||||
#CONFIG_WNM=y
|
||||
|
||||
# Interworking (IEEE 802.11u)
|
||||
# This can be used to enable functionality to improve interworking with
|
||||
# external networks (GAS/ANQP to learn more about the networks and network
|
||||
# selection based on available credentials).
|
||||
CONFIG_INTERWORKING=y
|
||||
|
||||
# Hotspot 2.0
|
||||
CONFIG_HS20=y
|
||||
|
||||
# Enable interface matching in wpa_supplicant
|
||||
#CONFIG_MATCH_IFACE=y
|
||||
|
||||
# Disable roaming in wpa_supplicant
|
||||
#CONFIG_NO_ROAMING=y
|
||||
|
||||
# AP mode operations with wpa_supplicant
|
||||
# This can be used for controlling AP mode operations with wpa_supplicant. It
|
||||
# should be noted that this is mainly aimed at simple cases like
|
||||
# WPA2-Personal while more complex configurations like WPA2-Enterprise with an
|
||||
# external RADIUS server can be supported with hostapd.
|
||||
CONFIG_AP=y
|
||||
|
||||
# P2P (Wi-Fi Direct)
|
||||
# This can be used to enable P2P support in wpa_supplicant. See README-P2P for
|
||||
# more information on P2P operations.
|
||||
CONFIG_P2P=y
|
||||
|
||||
# Enable TDLS support
|
||||
CONFIG_TDLS=y
|
||||
|
||||
# Wi-Fi Display
|
||||
# This can be used to enable Wi-Fi Display extensions for P2P using an external
|
||||
# program to control the additional information exchanges in the messages.
|
||||
CONFIG_WIFI_DISPLAY=y
|
||||
|
||||
# Autoscan
|
||||
# This can be used to enable automatic scan support in wpa_supplicant.
|
||||
# See wpa_supplicant.conf for more information on autoscan usage.
|
||||
#
|
||||
# Enabling directly a module will enable autoscan support.
|
||||
# For exponential module:
|
||||
#CONFIG_AUTOSCAN_EXPONENTIAL=y
|
||||
# For periodic module:
|
||||
#CONFIG_AUTOSCAN_PERIODIC=y
|
||||
|
||||
# Password (and passphrase, etc.) backend for external storage
|
||||
# These optional mechanisms can be used to add support for storing passwords
|
||||
# and other secrets in external (to wpa_supplicant) location. This allows, for
|
||||
# example, operating system specific key storage to be used
|
||||
#
|
||||
# External password backend for testing purposes (developer use)
|
||||
#CONFIG_EXT_PASSWORD_TEST=y
|
||||
# File-based backend to read passwords from an external file.
|
||||
#CONFIG_EXT_PASSWORD_FILE=y
|
||||
|
||||
# Enable Fast Session Transfer (FST)
|
||||
#CONFIG_FST=y
|
||||
|
||||
# Enable CLI commands for FST testing
|
||||
#CONFIG_FST_TEST=y
|
||||
|
||||
# OS X builds. This is only for building eapol_test.
|
||||
#CONFIG_OSX=y
|
||||
|
||||
# Automatic Channel Selection
|
||||
# This will allow wpa_supplicant to pick the channel automatically when channel
|
||||
# is set to "0".
|
||||
#
|
||||
# TODO: Extend parser to be able to parse "channel=acs_survey" as an alternative
|
||||
# to "channel=0". This would enable us to eventually add other ACS algorithms in
|
||||
# similar way.
|
||||
#
|
||||
# Automatic selection is currently only done through initialization, later on
|
||||
# we hope to do background checks to keep us moving to more ideal channels as
|
||||
# time goes by. ACS is currently only supported through the nl80211 driver and
|
||||
# your driver must have survey dump capability that is filled by the driver
|
||||
# during scanning.
|
||||
#
|
||||
# TODO: In analogy to hostapd be able to customize the ACS survey algorithm with
|
||||
# a newly to create wpa_supplicant.conf variable acs_num_scans.
|
||||
#
|
||||
# Supported ACS drivers:
|
||||
# * ath9k
|
||||
# * ath5k
|
||||
# * ath10k
|
||||
#
|
||||
# For more details refer to:
|
||||
# http://wireless.kernel.org/en/users/Documentation/acs
|
||||
#CONFIG_ACS=y
|
||||
|
||||
# Support Multi Band Operation
|
||||
#CONFIG_MBO=y
|
||||
|
||||
# Fast Initial Link Setup (FILS) (IEEE 802.11ai)
|
||||
#CONFIG_FILS=y
|
||||
# FILS shared key authentication with PFS
|
||||
#CONFIG_FILS_SK_PFS=y
|
||||
|
||||
# Support RSN on IBSS networks
|
||||
# This is needed to be able to use mode=1 network profile with proto=RSN and
|
||||
# key_mgmt=WPA-PSK (i.e., full key management instead of WPA-None).
|
||||
CONFIG_IBSS_RSN=y
|
||||
|
||||
# External PMKSA cache control
|
||||
# This can be used to enable control interface commands that allow the current
|
||||
# PMKSA cache entries to be fetched and new entries to be added.
|
||||
#CONFIG_PMKSA_CACHE_EXTERNAL=y
|
||||
|
||||
# Mesh Networking (IEEE 802.11s)
|
||||
#CONFIG_MESH=y
|
||||
|
||||
# Background scanning modules
|
||||
# These can be used to request wpa_supplicant to perform background scanning
|
||||
# operations for roaming within an ESS (same SSID). See the bgscan parameter in
|
||||
# the wpa_supplicant.conf file for more details.
|
||||
# Periodic background scans based on signal strength
|
||||
CONFIG_BGSCAN_SIMPLE=y
|
||||
# Learn channels used by the network and try to avoid bgscans on other
|
||||
# channels (experimental)
|
||||
#CONFIG_BGSCAN_LEARN=y
|
||||
|
||||
# Opportunistic Wireless Encryption (OWE)
|
||||
# Experimental implementation of draft-harkins-owe-07.txt
|
||||
#CONFIG_OWE=y
|
||||
|
||||
# Device Provisioning Protocol (DPP) (also known as Wi-Fi Easy Connect)
|
||||
CONFIG_DPP=y
|
||||
# DPP version 2 support
|
||||
CONFIG_DPP2=y
|
||||
# DPP version 3 support (experimental and still changing; do not enable for
|
||||
# production use)
|
||||
#CONFIG_DPP3=y
|
||||
|
||||
# Wired equivalent privacy (WEP)
|
||||
# WEP is an obsolete cryptographic data confidentiality algorithm that is not
|
||||
# considered secure. It should not be used for anything anymore. The
|
||||
# functionality needed to use WEP is available in the current wpa_supplicant
|
||||
# release under this optional build parameter. This functionality is subject to
|
||||
# be completely removed in a future release.
|
||||
#CONFIG_WEP=y
|
||||
|
||||
# Remove all TKIP functionality
|
||||
# TKIP is an old cryptographic data confidentiality algorithm that is not
|
||||
# considered secure. It should not be used anymore for anything else than a
|
||||
# backwards compatibility option as a group cipher when connecting to APs that
|
||||
# use WPA+WPA2 mixed mode. For now, the default wpa_supplicant build includes
|
||||
# support for this by default, but that functionality is subject to be removed
|
||||
# in the future.
|
||||
#CONFIG_NO_TKIP=y
|
||||
|
||||
# Pre-Association Security Negotiation (PASN)
|
||||
# Experimental implementation based on IEEE P802.11z/D2.6 and the protocol
|
||||
# design is still subject to change. As such, this should not yet be enabled in
|
||||
# production use.
|
||||
#CONFIG_PASN=y
|
28
wpa_supplicant/doc/docbook/Makefile
Normal file
28
wpa_supplicant/doc/docbook/Makefile
Normal file
@ -0,0 +1,28 @@
|
||||
all: man html pdf
|
||||
|
||||
FILES += wpa_background
|
||||
FILES += wpa_cli
|
||||
FILES += wpa_gui
|
||||
FILES += wpa_passphrase
|
||||
FILES += wpa_priv
|
||||
FILES += wpa_supplicant.conf
|
||||
FILES += wpa_supplicant
|
||||
FILES += eapol_test
|
||||
|
||||
man:
|
||||
for i in $(FILES); do docbook2man $$i.sgml; done
|
||||
|
||||
html:
|
||||
for i in $(FILES); do docbook2html $$i.sgml && \
|
||||
mv index.html $$i.html; done
|
||||
|
||||
pdf:
|
||||
for i in $(FILES); do docbook2pdf $$i.sgml; done
|
||||
|
||||
|
||||
clean:
|
||||
rm -f wpa_background.8 wpa_cli.8 wpa_gui.8 wpa_passphrase.8 wpa_priv.8 wpa_supplicant.8 eapol_test.8
|
||||
rm -f wpa_supplicant.conf.5
|
||||
rm -f manpage.links manpage.refs
|
||||
rm -f $(FILES:%=%.pdf)
|
||||
rm -f $(FILES:%=%.html)
|
209
wpa_supplicant/doc/docbook/eapol_test.sgml
Normal file
209
wpa_supplicant/doc/docbook/eapol_test.sgml
Normal file
@ -0,0 +1,209 @@
|
||||
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
|
||||
|
||||
<refentry>
|
||||
<refentryinfo>
|
||||
<date>07 August 2019</date>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>eapol_test</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname>eapol_test</refname>
|
||||
|
||||
<refpurpose>EAP peer and RADIUS client testing</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>eapol_test</command>
|
||||
<arg>-nWS</arg>
|
||||
<arg>-c<replaceable>config file</replaceable></arg>
|
||||
<arg>-a<replaceable>server IP address</replaceable></arg>
|
||||
<arg>-A<replaceable>client IP address</replaceable></arg>
|
||||
<arg>-p<replaceable>UDP port</replaceable></arg>
|
||||
<arg>-s<replaceable>shared secret</replaceable></arg>
|
||||
<arg>-r<replaceable>re-authentications</replaceable></arg>
|
||||
<arg>-t<replaceable>timeout</replaceable></arg>
|
||||
<arg>-C<replaceable>Connect-Info</replaceable></arg>
|
||||
<arg>-M<replaceable>MAC address</replaceable></arg>
|
||||
<arg>-o<replaceable>file</replaceable></arg>
|
||||
<arg>-N<replaceable>attr spec</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>eapol_test scard</command>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>eapol_test sim</command>
|
||||
<arg>PIN</arg>
|
||||
<arg>num triplets</arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Overview</title>
|
||||
|
||||
<para>eapol_test is a program that links together the same EAP
|
||||
peer implementation that wpa_supplicant is using and the RADIUS
|
||||
authentication client code from hostapd. In addition, it has
|
||||
minimal glue code to combine these two components in similar
|
||||
ways to IEEE 802.1X/EAPOL Authenticator state machines. In other
|
||||
words, it integrates IEEE 802.1X Authenticator (normally, an
|
||||
access point) and IEEE 802.1X Supplicant (normally, a wireless
|
||||
client) together to generate a single program that can be used to
|
||||
test EAP methods without having to setup an access point and a
|
||||
wireless client.</para>
|
||||
|
||||
<para>The main uses for eapol_test are in interoperability testing
|
||||
of EAP methods against RADIUS servers and in development testing
|
||||
for new EAP methods. It can be easily used to automate EAP testing
|
||||
for interoperability and regression since the program can be run
|
||||
from shell scripts without require additional test components apart
|
||||
from a RADIUS server. For example, the automated EAP tests described
|
||||
in eap_testing.txt are implemented with eapol_test. Similarly,
|
||||
eapol_test could be used to implement an automated regression
|
||||
test suite for a RADIUS authentication server.</para>
|
||||
|
||||
|
||||
<para>As an example:</para>
|
||||
|
||||
<blockquote><programlisting>
|
||||
eapol_test -ctest.conf -a127.0.0.1 -p1812 -ssecret -r1
|
||||
</programlisting></blockquote>
|
||||
|
||||
<para>tries to complete EAP authentication based on the network
|
||||
configuration from test.conf against the RADIUS server running
|
||||
on the local host. A re-authentication is triggered to test fast
|
||||
re-authentication. The configuration file uses the same format for
|
||||
network blocks as wpa_supplicant.</para>
|
||||
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>Command Arguments</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>-c configuration file path</term>
|
||||
|
||||
<listitem><para>A configuration to use. The configuration should
|
||||
use the same format for network blocks as wpa_supplicant.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-a AS address</term>
|
||||
|
||||
<listitem><para>IP address of the authentication server. The
|
||||
default is '127.0.0.1'.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-A client address</term>
|
||||
|
||||
<listitem><para>IP address of the client. The default is to
|
||||
select an address automatically.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-p AS port</term>
|
||||
|
||||
<listitem><para>UDP port of the authentication server. The
|
||||
default is '1812'.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-s AS secret</term>
|
||||
|
||||
<listitem><para>Shared secret with the authentication server.
|
||||
The default is 'radius'.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-r count</term>
|
||||
|
||||
<listitem><para>Number of reauthentications.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-t timeout</term>
|
||||
|
||||
<listitem><para>Timeout in seconds. The default is 30.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-C info</term>
|
||||
|
||||
<listitem><para>RADIUS Connect-Info. The default is
|
||||
'CONNECT 11Mbps 802.11b'.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry>
|
||||
<term>-M mac address</term>
|
||||
|
||||
<listitem><para>Client MAC address (Calling-Station-Id). The
|
||||
default is '02:00:00:00:00:01'.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-o file</term>
|
||||
|
||||
<listitem><para>Location to write out server certificate.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-N attr spec</term>
|
||||
|
||||
<listitem><para>Send arbitrary attribute specific by
|
||||
attr_id:syntax:value, or attr_id alone. attr_id should be the numeric
|
||||
ID of the attribute, and syntax should be one of 's' (string),
|
||||
'd' (integer), or 'x' (octet string). The value is the attribute value
|
||||
to send. When attr_id is given alone, NULL is used as the attribute
|
||||
value. Multiple attributes can be specified by using the option
|
||||
several times.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-n</term>
|
||||
|
||||
<listitem><para>Indicates that no MPPE keys are expected.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-W</term>
|
||||
|
||||
<listitem><para>Wait for a control interface monitor before starting.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-S</term>
|
||||
|
||||
<listitem><para>Save configuration after authentication.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<para>
|
||||
<citerefentry>
|
||||
<refentrytitle>wpa_supplicant</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>Legal</title>
|
||||
<para>wpa_supplicant is copyright (c) 2003-2022,
|
||||
Jouni Malinen <email>j@w1.fi</email> and
|
||||
contributors.
|
||||
All Rights Reserved.</para>
|
||||
|
||||
<para>This program is licensed under the BSD license (the one with
|
||||
advertisement clause removed).</para>
|
||||
</refsect1>
|
||||
</refentry>
|
105
wpa_supplicant/doc/docbook/wpa_background.sgml
Normal file
105
wpa_supplicant/doc/docbook/wpa_background.sgml
Normal file
@ -0,0 +1,105 @@
|
||||
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
|
||||
|
||||
<refentry>
|
||||
<refentryinfo>
|
||||
<date>07 August 2019</date>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>wpa_background</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname>wpa_background</refname>
|
||||
<refpurpose>Background information on Wi-Fi Protected Access and IEEE 802.11i</refpurpose>
|
||||
</refnamediv>
|
||||
<refsect1>
|
||||
<title>WPA</title>
|
||||
|
||||
<para>The original security mechanism of IEEE 802.11 standard was
|
||||
not designed to be strong and has proven to be insufficient for
|
||||
most networks that require some kind of security. Task group I
|
||||
(Security) of IEEE 802.11 working group
|
||||
(http://www.ieee802.org/11/) has worked to address the flaws of
|
||||
the base standard and has in practice completed its work in May
|
||||
2004. The IEEE 802.11i amendment to the IEEE 802.11 standard was
|
||||
approved in June 2004 and published in July 2004.</para>
|
||||
|
||||
<para>Wi-Fi Alliance (http://www.wi-fi.org/) used a draft version
|
||||
of the IEEE 802.11i work (draft 3.0) to define a subset of the
|
||||
security enhancements that can be implemented with existing wlan
|
||||
hardware. This is called Wi-Fi Protected Access<TM> (WPA). This
|
||||
has now become a mandatory component of interoperability testing
|
||||
and certification done by Wi-Fi Alliance. Wi-Fi provides
|
||||
information about WPA at its web site
|
||||
(http://www.wi-fi.org/OpenSection/protected_access.asp).</para>
|
||||
|
||||
<para>IEEE 802.11 standard defined wired equivalent privacy (WEP)
|
||||
algorithm for protecting wireless networks. WEP uses RC4 with
|
||||
40-bit keys, 24-bit initialization vector (IV), and CRC32 to
|
||||
protect against packet forgery. All these choices have proven to
|
||||
be insufficient: key space is too small against current attacks,
|
||||
RC4 key scheduling is insufficient (beginning of the pseudorandom
|
||||
stream should be skipped), IV space is too small and IV reuse
|
||||
makes attacks easier, there is no replay protection, and non-keyed
|
||||
authentication does not protect against bit flipping packet
|
||||
data.</para>
|
||||
|
||||
<para>WPA is an intermediate solution for the security issues. It
|
||||
uses Temporal Key Integrity Protocol (TKIP) to replace WEP. TKIP
|
||||
is a compromise on strong security and possibility to use existing
|
||||
hardware. It still uses RC4 for the encryption like WEP, but with
|
||||
per-packet RC4 keys. In addition, it implements replay protection,
|
||||
keyed packet authentication mechanism (Michael MIC).</para>
|
||||
|
||||
<para>Keys can be managed using two different mechanisms. WPA can
|
||||
either use an external authentication server (e.g., RADIUS) and
|
||||
EAP just like IEEE 802.1X is using or pre-shared keys without need
|
||||
for additional servers. Wi-Fi calls these "WPA-Enterprise" and
|
||||
"WPA-Personal", respectively. Both mechanisms will generate a
|
||||
master session key for the Authenticator (AP) and Supplicant
|
||||
(client station).</para>
|
||||
|
||||
<para>WPA implements a new key handshake (4-Way Handshake and
|
||||
Group Key Handshake) for generating and exchanging data encryption
|
||||
keys between the Authenticator and Supplicant. This handshake is
|
||||
also used to verify that both Authenticator and Supplicant know
|
||||
the master session key. These handshakes are identical regardless
|
||||
of the selected key management mechanism (only the method for
|
||||
generating master session key changes).</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>IEEE 802.11i / WPA2</title>
|
||||
|
||||
<para>The design for parts of IEEE 802.11i that were not included
|
||||
in WPA has finished (May 2004) and this amendment to IEEE 802.11
|
||||
was approved in June 2004. Wi-Fi Alliance is using the final IEEE
|
||||
802.11i as a new version of WPA called WPA2. This includes, e.g.,
|
||||
support for more robust encryption algorithm (CCMP: AES in Counter
|
||||
mode with CBC-MAC) to replace TKIP and optimizations for handoff
|
||||
(reduced number of messages in initial key handshake,
|
||||
pre-authentication, and PMKSA caching).</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<para>
|
||||
<citerefentry>
|
||||
<refentrytitle>wpa_supplicant</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Legal</title>
|
||||
<para>wpa_supplicant is copyright (c) 2003-2022,
|
||||
Jouni Malinen <email>j@w1.fi</email> and
|
||||
contributors.
|
||||
All Rights Reserved.</para>
|
||||
|
||||
<para>This program is licensed under the BSD license (the one with
|
||||
advertisement clause removed).</para>
|
||||
</refsect1>
|
||||
</refentry>
|
360
wpa_supplicant/doc/docbook/wpa_cli.sgml
Normal file
360
wpa_supplicant/doc/docbook/wpa_cli.sgml
Normal file
@ -0,0 +1,360 @@
|
||||
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
|
||||
|
||||
<refentry>
|
||||
<refentryinfo>
|
||||
<date>07 August 2019</date>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>wpa_cli</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname>wpa_cli</refname>
|
||||
|
||||
<refpurpose>WPA command line client</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>wpa_cli</command>
|
||||
<arg>-p <replaceable>path to ctrl sockets</replaceable></arg>
|
||||
<arg>-g <replaceable>path to global ctrl_interface socket</replaceable></arg>
|
||||
<arg>-i <replaceable>ifname</replaceable></arg>
|
||||
<arg>-hvB</arg>
|
||||
<arg>-a <replaceable>action file</replaceable></arg>
|
||||
<arg>-P <replaceable>pid file</replaceable></arg>
|
||||
<arg>-G <replaceable>ping interval</replaceable></arg>
|
||||
<arg><replaceable>command ...</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Overview</title>
|
||||
|
||||
<para>wpa_cli is a text-based frontend program for interacting
|
||||
with wpa_supplicant. It is used to query current status, change
|
||||
configuration, trigger events, and request interactive user
|
||||
input.</para>
|
||||
|
||||
<para>wpa_cli can show the current authentication status, selected
|
||||
security mode, dot11 and dot1x MIBs, etc. In addition, it can
|
||||
configure some variables like EAPOL state machine parameters and
|
||||
trigger events like reassociation and IEEE 802.1X
|
||||
logoff/logon. wpa_cli provides a user interface to request
|
||||
authentication information, like username and password, if these
|
||||
are not included in the configuration. This can be used to
|
||||
implement, e.g., one-time-passwords or generic token card
|
||||
authentication where the authentication is based on a
|
||||
challenge-response that uses an external device for generating the
|
||||
response.</para>
|
||||
|
||||
<para>The control interface of wpa_supplicant can be configured to
|
||||
allow non-root user access (ctrl_interface GROUP= parameter in the
|
||||
configuration file). This makes it possible to run wpa_cli with a
|
||||
normal user account.</para>
|
||||
|
||||
<para>wpa_cli supports two modes: interactive and command
|
||||
line. Both modes share the same command set and the main
|
||||
difference is in interactive mode providing access to unsolicited
|
||||
messages (event messages, username/password requests).</para>
|
||||
|
||||
<para>Interactive mode is started when wpa_cli is executed without
|
||||
including the command as a command line parameter. Commands are
|
||||
then entered on the wpa_cli prompt. In command line mode, the same
|
||||
commands are entered as command line arguments for wpa_cli.</para>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>Interactive authentication parameters request</title>
|
||||
|
||||
<para>When wpa_supplicant need authentication parameters, like
|
||||
username and password, which are not present in the configuration
|
||||
file, it sends a request message to all attached frontend programs,
|
||||
e.g., wpa_cli in interactive mode. wpa_cli shows these requests
|
||||
with "CTRL-REQ-<type>-<id>:<text>"
|
||||
prefix. <type> is IDENTITY, PASSWORD, or OTP
|
||||
(one-time-password). <id> is a unique identifier for the
|
||||
current network. <text> is description of the request. In
|
||||
case of OTP request, it includes the challenge from the
|
||||
authentication server.</para>
|
||||
|
||||
<para>The reply to these requests can be given with
|
||||
<emphasis>identity</emphasis>, <emphasis>password</emphasis>, and
|
||||
<emphasis>otp</emphasis> commands. <id> needs to be copied from
|
||||
the matching request. <emphasis>password</emphasis> and
|
||||
<emphasis>otp</emphasis> commands can be used regardless of whether
|
||||
the request was for PASSWORD or OTP. The main difference between these
|
||||
two commands is that values given with <emphasis>password</emphasis> are
|
||||
remembered as long as wpa_supplicant is running whereas values given
|
||||
with <emphasis>otp</emphasis> are used only once and then forgotten,
|
||||
i.e., wpa_supplicant will ask frontend for a new value for every use.
|
||||
This can be used to implement one-time-password lists and generic token
|
||||
card -based authentication.</para>
|
||||
|
||||
<para>Example request for password and a matching reply:</para>
|
||||
|
||||
<blockquote><programlisting>
|
||||
CTRL-REQ-PASSWORD-1:Password needed for SSID foobar
|
||||
> password 1 mysecretpassword
|
||||
</programlisting></blockquote>
|
||||
|
||||
<para>Example request for generic token card challenge-response:</para>
|
||||
|
||||
<blockquote><programlisting>
|
||||
CTRL-REQ-OTP-2:Challenge 1235663 needed for SSID foobar
|
||||
> otp 2 9876
|
||||
</programlisting></blockquote>
|
||||
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>Command Arguments</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>-p path</term>
|
||||
|
||||
<listitem><para>Change the path where control sockets should
|
||||
be found.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-g control socket path</term>
|
||||
|
||||
<listitem><para>Connect to the global control socket at the
|
||||
indicated path rather than an interface-specific control
|
||||
socket.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-i ifname</term>
|
||||
|
||||
<listitem><para>Specify the interface that is being
|
||||
configured. By default, choose the first interface found with
|
||||
a control socket in the socket path.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-h</term>
|
||||
<listitem><para>Help. Show a usage message.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry>
|
||||
<term>-v</term>
|
||||
<listitem><para>Show version information.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry>
|
||||
<term>-B</term>
|
||||
<listitem><para>Run as a daemon in the background.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-a file</term>
|
||||
|
||||
<listitem><para>Run in daemon mode executing the action file
|
||||
based on events from wpa_supplicant. The specified file will
|
||||
be executed with the first argument set to interface name and
|
||||
second to "CONNECTED" or "DISCONNECTED" depending on the event.
|
||||
This can be used to execute networking tools required to configure
|
||||
the interface.</para>
|
||||
|
||||
<para>Additionally, three environmental variables are available to
|
||||
the file: WPA_CTRL_DIR, WPA_ID, and WPA_ID_STR. WPA_CTRL_DIR
|
||||
contains the absolute path to the ctrl_interface socket. WPA_ID
|
||||
contains the unique network_id identifier assigned to the active
|
||||
network, and WPA_ID_STR contains the content of the id_str option.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-P file</term>
|
||||
|
||||
<listitem><para>Set the location of the PID
|
||||
file.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-G ping interval</term>
|
||||
|
||||
<listitem><para>Set the interval (in seconds) at which
|
||||
wpa_cli pings the supplicant.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>command</term>
|
||||
|
||||
<listitem><para>Run a command. The available commands are
|
||||
listed in the next section.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>Commands</title>
|
||||
<para>The following commands are available:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>status</term>
|
||||
<listitem>
|
||||
<para>get current WPA/EAPOL/EAP status</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>mib</term>
|
||||
<listitem>
|
||||
<para>get MIB variables (dot1x, dot11)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>help</term>
|
||||
<listitem>
|
||||
<para>show this usage help</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>interface [ifname]</term>
|
||||
<listitem>
|
||||
<para>show interfaces/select interface</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>level <debug level></term>
|
||||
<listitem>
|
||||
<para>change debug level</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>license</term>
|
||||
<listitem>
|
||||
<para>show full wpa_cli license</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>logoff</term>
|
||||
<listitem>
|
||||
<para>IEEE 802.1X EAPOL state machine logoff</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>logon</term>
|
||||
<listitem>
|
||||
<para>IEEE 802.1X EAPOL state machine logon</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>set</term>
|
||||
<listitem>
|
||||
<para>set variables (shows list of variables when run without arguments)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>pmksa</term>
|
||||
<listitem>
|
||||
<para>show PMKSA cache</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>reassociate</term>
|
||||
<listitem>
|
||||
<para>force reassociation</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>reconfigure</term>
|
||||
<listitem>
|
||||
<para>force wpa_supplicant to re-read its configuration file</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>preauthenticate <BSSID></term>
|
||||
<listitem>
|
||||
<para>force preauthentication</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>identity <network id> <identity></term>
|
||||
<listitem>
|
||||
<para>configure identity for an SSID</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>password <network id> <password></term>
|
||||
<listitem>
|
||||
<para>configure password for an SSID</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>pin <network id> <pin></term>
|
||||
<listitem>
|
||||
<para>configure pin for an SSID</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>otp <network id> <password></term>
|
||||
<listitem>
|
||||
<para>configure one-time-password for an SSID</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>bssid <network id> <BSSID></term>
|
||||
<listitem>
|
||||
<para>set preferred BSSID for an SSID</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>list_networks</term>
|
||||
<listitem>
|
||||
<para>list configured networks</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>terminate</term>
|
||||
<listitem>
|
||||
<para>terminate <command>wpa_supplicant</command></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>quit</term>
|
||||
<listitem><para>exit wpa_cli</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<para>
|
||||
<citerefentry>
|
||||
<refentrytitle>wpa_supplicant</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>Legal</title>
|
||||
<para>wpa_supplicant is copyright (c) 2003-2022,
|
||||
Jouni Malinen <email>j@w1.fi</email> and
|
||||
contributors.
|
||||
All Rights Reserved.</para>
|
||||
|
||||
<para>This program is licensed under the BSD license (the one with
|
||||
advertisement clause removed).</para>
|
||||
</refsect1>
|
||||
</refentry>
|
106
wpa_supplicant/doc/docbook/wpa_gui.sgml
Normal file
106
wpa_supplicant/doc/docbook/wpa_gui.sgml
Normal file
@ -0,0 +1,106 @@
|
||||
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
|
||||
|
||||
<refentry>
|
||||
<refentryinfo>
|
||||
<date>07 August 2019</date>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>wpa_gui</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname>wpa_gui</refname>
|
||||
|
||||
<refpurpose>WPA Graphical User Interface</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>wpa_gui</command>
|
||||
<arg>-p <replaceable>path to ctrl sockets</replaceable></arg>
|
||||
<arg>-i <replaceable>ifname</replaceable></arg>
|
||||
<arg>-m <replaceable>seconds</replaceable></arg>
|
||||
<arg>-t</arg>
|
||||
<arg>-q</arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Overview</title>
|
||||
|
||||
<para>wpa_gui is a QT graphical frontend program for interacting
|
||||
with wpa_supplicant. It is used to query current status, change
|
||||
configuration and request interactive user input.</para>
|
||||
|
||||
<para>wpa_gui supports (almost) all of the interactive status and
|
||||
configuration features of the command line client, wpa_cli. Refer
|
||||
to the wpa_cli manpage for a comprehensive list of the
|
||||
interactive mode features.</para>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>Command Arguments</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>-p path</term>
|
||||
|
||||
<listitem><para>Change the path where control sockets should
|
||||
be found.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-i ifname</term>
|
||||
|
||||
<listitem><para>Specify the interface that is being
|
||||
configured. By default, choose the first interface found with
|
||||
a control socket in the socket path.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-m seconds</term>
|
||||
|
||||
<listitem><para>Set the update interval in seconds for the signal
|
||||
strength meter. This value must be a positive integer, otherwise
|
||||
meter is not enabled (default behavior).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-t</term>
|
||||
|
||||
<listitem><para>Start program in the system tray only (if the window
|
||||
manager supports it). By default the main status window is
|
||||
shown.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-q</term>
|
||||
|
||||
<listitem><para>Run program in the quiet mode - do not display tray
|
||||
icon pop-up messages.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<para>
|
||||
<citerefentry>
|
||||
<refentrytitle>wpa_cli</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</citerefentry>
|
||||
<citerefentry>
|
||||
<refentrytitle>wpa_supplicant</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>Legal</title>
|
||||
<para>wpa_supplicant is copyright (c) 2003-2022,
|
||||
Jouni Malinen <email>j@w1.fi</email> and
|
||||
contributors.
|
||||
All Rights Reserved.</para>
|
||||
|
||||
<para>This program is licensed under the BSD license (the one with
|
||||
advertisement clause removed).</para>
|
||||
</refsect1>
|
||||
</refentry>
|
77
wpa_supplicant/doc/docbook/wpa_passphrase.sgml
Normal file
77
wpa_supplicant/doc/docbook/wpa_passphrase.sgml
Normal file
@ -0,0 +1,77 @@
|
||||
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
|
||||
|
||||
<refentry>
|
||||
<refentryinfo>
|
||||
<date>07 August 2019</date>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>wpa_passphrase</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname>wpa_passphrase</refname>
|
||||
<refpurpose>Generate a WPA PSK from an ASCII passphrase for a SSID</refpurpose>
|
||||
</refnamediv>
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>wpa_passphrase</command>
|
||||
<arg><replaceable>ssid</replaceable></arg>
|
||||
<arg><replaceable>passphrase</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Overview</title>
|
||||
|
||||
<para><command>wpa_passphrase</command> pre-computes PSK entries for
|
||||
network configuration blocks of a
|
||||
<filename>wpa_supplicant.conf</filename> file. An ASCII passphrase
|
||||
and SSID are used to generate a 256-bit PSK.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Options</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>ssid</term>
|
||||
<listitem>
|
||||
<para>The SSID whose passphrase should be derived.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>passphrase</term>
|
||||
<listitem>
|
||||
<para>The passphrase to use. If not included on the command line,
|
||||
passphrase will be read from standard input.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<para>
|
||||
<citerefentry>
|
||||
<refentrytitle>wpa_supplicant.conf</refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</citerefentry>
|
||||
<citerefentry>
|
||||
<refentrytitle>wpa_supplicant</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</citerefentry>
|
||||
</para>
|
||||
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>Legal</title>
|
||||
<para>wpa_supplicant is copyright (c) 2003-2022,
|
||||
Jouni Malinen <email>j@w1.fi</email> and
|
||||
contributors.
|
||||
All Rights Reserved.</para>
|
||||
|
||||
<para>This program is licensed under the BSD license (the one with
|
||||
advertisement clause removed).</para>
|
||||
</refsect1>
|
||||
</refentry>
|
152
wpa_supplicant/doc/docbook/wpa_priv.sgml
Normal file
152
wpa_supplicant/doc/docbook/wpa_priv.sgml
Normal file
@ -0,0 +1,152 @@
|
||||
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
|
||||
|
||||
<refentry>
|
||||
<refentryinfo>
|
||||
<date>07 August 2019</date>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>wpa_priv</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname>wpa_priv</refname>
|
||||
|
||||
<refpurpose>wpa_supplicant privilege separation helper</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>wpa_priv</command>
|
||||
<arg>-c <replaceable>ctrl path</replaceable></arg>
|
||||
<arg>-Bdd</arg>
|
||||
<arg>-P <replaceable>pid file</replaceable></arg>
|
||||
<arg>driver:ifname <replaceable>[driver:ifname ...]</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Overview</title>
|
||||
|
||||
<para><command>wpa_priv</command> is a privilege separation helper that
|
||||
minimizes the size of <command>wpa_supplicant</command> code that needs
|
||||
to be run with root privileges.</para>
|
||||
|
||||
<para>If enabled, privileged operations are done in the wpa_priv process
|
||||
while leaving rest of the code (e.g., EAP authentication and WPA
|
||||
handshakes) to operate in an unprivileged process (wpa_supplicant) that
|
||||
can be run as non-root user. Privilege separation restricts the effects
|
||||
of potential software errors by containing the majority of the code in an
|
||||
unprivileged process to avoid the possibility of a full system
|
||||
compromise.</para>
|
||||
|
||||
<para><command>wpa_priv</command> needs to be run with network admin
|
||||
privileges (usually, root user). It opens a UNIX domain socket for each
|
||||
interface that is included on the command line; any other interface will
|
||||
be off limits for <command>wpa_supplicant</command> in this kind of
|
||||
configuration. After this, <command>wpa_supplicant</command> can be run as
|
||||
a non-root user (e.g., all standard users on a laptop or as a special
|
||||
non-privileged user account created just for this purpose to limit access
|
||||
to user files even further).</para>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>Example configuration</title>
|
||||
|
||||
<para>The following steps are an example of how to configure
|
||||
<command>wpa_priv</command> to allow users in the
|
||||
<emphasis>wpapriv</emphasis> group to communicate with
|
||||
<command>wpa_supplicant</command> with privilege separation:</para>
|
||||
|
||||
<para>Create user group (e.g., wpapriv) and assign users that
|
||||
should be able to use wpa_supplicant into that group.</para>
|
||||
|
||||
<para>Create /var/run/wpa_priv directory for UNIX domain sockets and
|
||||
control user access by setting it accessible only for the wpapriv
|
||||
group:</para>
|
||||
|
||||
<blockquote><programlisting>
|
||||
mkdir /var/run/wpa_priv
|
||||
chown root:wpapriv /var/run/wpa_priv
|
||||
chmod 0750 /var/run/wpa_priv
|
||||
</programlisting></blockquote>
|
||||
|
||||
<para>Start <command>wpa_priv</command> as root (e.g., from system
|
||||
startup scripts) with the enabled interfaces configured on the
|
||||
command line:</para>
|
||||
|
||||
<blockquote><programlisting>
|
||||
wpa_priv -B -c /var/run/wpa_priv -P /var/run/wpa_priv.pid wext:wlan0
|
||||
</programlisting></blockquote>
|
||||
|
||||
<para>Run <command>wpa_supplicant</command> as non-root with a user
|
||||
that is in the wpapriv group:</para>
|
||||
|
||||
<blockquote><programlisting>
|
||||
wpa_supplicant -i ath0 -c wpa_supplicant.conf
|
||||
</programlisting></blockquote>
|
||||
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>Command Arguments</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>-c ctrl path</term>
|
||||
|
||||
<listitem><para>Specify the path to wpa_priv control directory
|
||||
(Default: /var/run/wpa_priv/).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-B</term>
|
||||
<listitem><para>Run as a daemon in the background.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-P file</term>
|
||||
|
||||
<listitem><para>Set the location of the PID
|
||||
file.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>driver:ifname [driver:ifname ...]</term>
|
||||
|
||||
<listitem><para>The <driver> string dictates which of the
|
||||
supported <command>wpa_supplicant</command> driver backends is to be
|
||||
used. To get a list of supported driver types see wpa_supplicant help
|
||||
(e.g, wpa_supplicant -h). The driver backend supported by most good
|
||||
drivers is <emphasis>wext</emphasis>.</para>
|
||||
|
||||
<para>The <ifname> string specifies which network
|
||||
interface is to be managed by <command>wpa_supplicant</command>
|
||||
(e.g., wlan0 or ath0).</para>
|
||||
|
||||
<para><command>wpa_priv</command> does not use the network interface
|
||||
before <command>wpa_supplicant</command> is started, so it is fine to
|
||||
include network interfaces that are not available at the time wpa_priv
|
||||
is started. wpa_priv can control multiple interfaces with one process,
|
||||
but it is also possible to run multiple <command>wpa_priv</command>
|
||||
processes at the same time, if desired.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<para>
|
||||
<citerefentry>
|
||||
<refentrytitle>wpa_supplicant</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>Legal</title>
|
||||
<para>wpa_supplicant is copyright (c) 2003-2022,
|
||||
Jouni Malinen <email>j@w1.fi</email> and
|
||||
contributors.
|
||||
All Rights Reserved.</para>
|
||||
|
||||
<para>This program is licensed under the BSD license (the one with
|
||||
advertisement clause removed).</para>
|
||||
</refsect1>
|
||||
</refentry>
|
243
wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml
Normal file
243
wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml
Normal file
@ -0,0 +1,243 @@
|
||||
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
|
||||
<refentry>
|
||||
<refentryinfo>
|
||||
<date>07 August 2019</date>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>wpa_supplicant.conf</refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname>wpa_supplicant.conf</refname>
|
||||
<refpurpose>configuration file for wpa_supplicant</refpurpose>
|
||||
</refnamediv>
|
||||
<refsect1>
|
||||
<title>Overview</title>
|
||||
|
||||
<para><command>wpa_supplicant</command> is configured using a text
|
||||
file that lists all accepted networks and security policies,
|
||||
including pre-shared keys. See the example configuration file,
|
||||
probably in <command>/usr/share/doc/wpa_supplicant/</command>, for
|
||||
detailed information about the configuration format and supported
|
||||
fields.</para>
|
||||
|
||||
<para>All file paths in this configuration file should use full
|
||||
(absolute, not relative to working directory) path in order to allow
|
||||
working directory to be changed. This can happen if wpa_supplicant is
|
||||
run in the background.</para>
|
||||
|
||||
<para>Changes to configuration file can be reloaded be sending
|
||||
SIGHUP signal to <command>wpa_supplicant</command> ('killall -HUP
|
||||
wpa_supplicant'). Similarly, reloading can be triggered with
|
||||
the <emphasis>wpa_cli reconfigure</emphasis> command.</para>
|
||||
|
||||
<para>Configuration file can include one or more network blocks,
|
||||
e.g., one for each used SSID. wpa_supplicant will automatically
|
||||
select the best network based on the order of network blocks in
|
||||
the configuration file, network security level (WPA/WPA2 is
|
||||
preferred), and signal strength.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Quick Examples</title>
|
||||
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
|
||||
<para>WPA-Personal (PSK) as home network and WPA-Enterprise with
|
||||
EAP-TLS as work network.</para>
|
||||
|
||||
<blockquote><programlisting>
|
||||
# allow frontend (e.g., wpa_cli) to be used by all users in 'wheel' group
|
||||
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=wheel
|
||||
#
|
||||
# home network; allow all valid ciphers
|
||||
network={
|
||||
ssid="home"
|
||||
scan_ssid=1
|
||||
key_mgmt=WPA-PSK
|
||||
psk="very secret passphrase"
|
||||
}
|
||||
#
|
||||
# work network; use EAP-TLS with WPA; allow only CCMP and TKIP ciphers
|
||||
network={
|
||||
ssid="work"
|
||||
scan_ssid=1
|
||||
key_mgmt=WPA-EAP
|
||||
pairwise=CCMP TKIP
|
||||
group=CCMP TKIP
|
||||
eap=TLS
|
||||
identity="user@example.com"
|
||||
ca_cert="/etc/cert/ca.pem"
|
||||
client_cert="/etc/cert/user.pem"
|
||||
private_key="/etc/cert/user.prv"
|
||||
private_key_passwd="password"
|
||||
}
|
||||
</programlisting></blockquote>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>WPA-RADIUS/EAP-PEAP/MSCHAPv2 with RADIUS servers that
|
||||
use old peaplabel (e.g., Funk Odyssey and SBR, Meetinghouse
|
||||
Aegis, Interlink RAD-Series)</para>
|
||||
|
||||
<blockquote><programlisting>
|
||||
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=wheel
|
||||
network={
|
||||
ssid="example"
|
||||
scan_ssid=1
|
||||
key_mgmt=WPA-EAP
|
||||
eap=PEAP
|
||||
identity="user@example.com"
|
||||
password="foobar"
|
||||
ca_cert="/etc/cert/ca.pem"
|
||||
phase1="peaplabel=0"
|
||||
phase2="auth=MSCHAPV2"
|
||||
}
|
||||
</programlisting></blockquote>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>EAP-TTLS/EAP-MD5-Challenge configuration with anonymous
|
||||
identity for the unencrypted use. Real identity is sent only
|
||||
within an encrypted TLS tunnel.</para>
|
||||
|
||||
|
||||
<blockquote><programlisting>
|
||||
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=wheel
|
||||
network={
|
||||
ssid="example"
|
||||
scan_ssid=1
|
||||
key_mgmt=WPA-EAP
|
||||
eap=TTLS
|
||||
identity="user@example.com"
|
||||
anonymous_identity="anonymous@example.com"
|
||||
password="foobar"
|
||||
ca_cert="/etc/cert/ca.pem"
|
||||
phase2="auth=MD5"
|
||||
}
|
||||
</programlisting></blockquote>
|
||||
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>IEEE 802.1X (i.e., no WPA) with dynamic WEP keys
|
||||
(require both unicast and broadcast); use EAP-TLS for
|
||||
authentication</para>
|
||||
|
||||
<blockquote><programlisting>
|
||||
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=wheel
|
||||
network={
|
||||
ssid="1x-test"
|
||||
scan_ssid=1
|
||||
key_mgmt=IEEE8021X
|
||||
eap=TLS
|
||||
identity="user@example.com"
|
||||
ca_cert="/etc/cert/ca.pem"
|
||||
client_cert="/etc/cert/user.pem"
|
||||
private_key="/etc/cert/user.prv"
|
||||
private_key_passwd="password"
|
||||
eapol_flags=3
|
||||
}
|
||||
</programlisting></blockquote>
|
||||
</listitem>
|
||||
|
||||
|
||||
<listitem>
|
||||
<para>Catch all example that allows more or less all
|
||||
configuration modes. The configuration options are used based
|
||||
on what security policy is used in the selected SSID. This is
|
||||
mostly for testing and is not recommended for normal
|
||||
use.</para>
|
||||
|
||||
<blockquote><programlisting>
|
||||
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=wheel
|
||||
network={
|
||||
ssid="example"
|
||||
scan_ssid=1
|
||||
key_mgmt=WPA-EAP WPA-PSK IEEE8021X NONE
|
||||
pairwise=CCMP TKIP
|
||||
group=CCMP TKIP WEP104 WEP40
|
||||
psk="very secret passphrase"
|
||||
eap=TTLS PEAP TLS
|
||||
identity="user@example.com"
|
||||
password="foobar"
|
||||
ca_cert="/etc/cert/ca.pem"
|
||||
client_cert="/etc/cert/user.pem"
|
||||
private_key="/etc/cert/user.prv"
|
||||
private_key_passwd="password"
|
||||
phase1="peaplabel=0"
|
||||
ca_cert2="/etc/cert/ca2.pem"
|
||||
client_cert2="/etc/cer/user.pem"
|
||||
private_key2="/etc/cer/user.prv"
|
||||
private_key2_passwd="password"
|
||||
}
|
||||
</programlisting></blockquote>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Authentication for wired Ethernet. This can be used with
|
||||
<emphasis>wired</emphasis> or <emphasis>roboswitch</emphasis> interface
|
||||
(-Dwired or -Droboswitch on command line).</para>
|
||||
|
||||
<blockquote><programlisting>
|
||||
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=wheel
|
||||
ap_scan=0
|
||||
network={
|
||||
key_mgmt=IEEE8021X
|
||||
eap=MD5
|
||||
identity="user"
|
||||
password="password"
|
||||
eapol_flags=0
|
||||
}
|
||||
</programlisting></blockquote>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>Certificates</title>
|
||||
|
||||
<para>Some EAP authentication methods require use of
|
||||
certificates. EAP-TLS uses both server side and client
|
||||
certificates whereas EAP-PEAP and EAP-TTLS only require the server
|
||||
side certificate. When client certificate is used, a matching
|
||||
private key file has to also be included in configuration. If the
|
||||
private key uses a passphrase, this has to be configured in
|
||||
wpa_supplicant.conf ("private_key_passwd").</para>
|
||||
|
||||
<para>wpa_supplicant supports X.509 certificates in PEM and DER
|
||||
formats. User certificate and private key can be included in the
|
||||
same file.</para>
|
||||
|
||||
<para>If the user certificate and private key is received in
|
||||
PKCS#12/PFX format, they need to be converted to suitable PEM/DER
|
||||
format for wpa_supplicant. This can be done, e.g., with following
|
||||
commands:</para>
|
||||
<blockquote><programlisting>
|
||||
# convert client certificate and private key to PEM format
|
||||
openssl pkcs12 -in example.pfx -out user.pem -clcerts
|
||||
# convert CA certificate (if included in PFX file) to PEM format
|
||||
openssl pkcs12 -in example.pfx -out ca.pem -cacerts -nokeys
|
||||
</programlisting></blockquote>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<para>
|
||||
<citerefentry>
|
||||
<refentrytitle>wpa_supplicant</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</citerefentry>
|
||||
<citerefentry>
|
||||
<refentrytitle>openssl</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
</refentry>
|
764
wpa_supplicant/doc/docbook/wpa_supplicant.sgml
Normal file
764
wpa_supplicant/doc/docbook/wpa_supplicant.sgml
Normal file
@ -0,0 +1,764 @@
|
||||
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
|
||||
|
||||
<refentry>
|
||||
<refentryinfo>
|
||||
<date>07 August 2019</date>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>wpa_supplicant</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname>wpa_supplicant</refname>
|
||||
<refpurpose>Wi-Fi Protected Access client and IEEE 802.1X supplicant</refpurpose>
|
||||
</refnamediv>
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>wpa_supplicant</command>
|
||||
<arg>-BddfhKLqqsTtuvW</arg>
|
||||
<arg>-i<replaceable>ifname</replaceable></arg>
|
||||
<arg>-c<replaceable>config file</replaceable></arg>
|
||||
<arg>-D<replaceable>driver</replaceable></arg>
|
||||
<arg>-P<replaceable>PID_file</replaceable></arg>
|
||||
<arg>-f<replaceable>output file</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
<refsect1>
|
||||
<title>Overview</title>
|
||||
|
||||
<para>
|
||||
Wireless networks do not require physical access to the network equipment
|
||||
in the same way as wired networks. This makes it easier for unauthorized
|
||||
users to passively monitor a network and capture all transmitted frames.
|
||||
In addition, unauthorized use of the network is much easier. In many cases,
|
||||
this can happen even without user's explicit knowledge since the wireless
|
||||
LAN adapter may have been configured to automatically join any available
|
||||
network.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Link-layer encryption can be used to provide a layer of security for
|
||||
wireless networks. The original wireless LAN standard, IEEE 802.11,
|
||||
included a simple encryption mechanism, WEP. However, that proved to
|
||||
be flawed in many areas and network protected with WEP cannot be consider
|
||||
secure. IEEE 802.1X authentication and frequently changed dynamic WEP keys
|
||||
can be used to improve the network security, but even that has inherited
|
||||
security issues due to the use of WEP for encryption. Wi-Fi Protected
|
||||
Access and IEEE 802.11i amendment to the wireless LAN standard introduce
|
||||
a much improved mechanism for securing wireless networks. IEEE 802.11i
|
||||
enabled networks that are using CCMP (encryption mechanism based on strong
|
||||
cryptographic algorithm AES) can finally be called secure used for
|
||||
applications which require efficient protection against unauthorized
|
||||
access.
|
||||
</para>
|
||||
|
||||
<para><command>wpa_supplicant</command> is an implementation of
|
||||
the WPA Supplicant component, i.e., the part that runs in the
|
||||
client stations. It implements WPA key negotiation with a WPA
|
||||
Authenticator and EAP authentication with Authentication
|
||||
Server. In addition, it controls the roaming and IEEE 802.11
|
||||
authentication/association of the wireless LAN driver.</para>
|
||||
|
||||
<para><command>wpa_supplicant</command> is designed to be a
|
||||
"daemon" program that runs in the background and acts as the
|
||||
backend component controlling the wireless
|
||||
connection. <command>wpa_supplicant</command> supports separate
|
||||
frontend programs and an example text-based frontend,
|
||||
<command>wpa_cli</command>, is included with
|
||||
wpa_supplicant.</para>
|
||||
|
||||
<para>Before wpa_supplicant can do its work, the network interface
|
||||
must be available. That means that the physical device must be
|
||||
present and enabled, and the driver for the device must be
|
||||
loaded. The daemon will exit immediately if the device is not already
|
||||
available.</para>
|
||||
|
||||
<para>After <command>wpa_supplicant</command> has configured the
|
||||
network device, higher level configuration such as DHCP may
|
||||
proceed. There are a variety of ways to integrate wpa_supplicant
|
||||
into a machine's networking scripts, a few of which are described
|
||||
in sections below.</para>
|
||||
|
||||
<para>The following steps are used when associating with an AP
|
||||
using WPA:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><command>wpa_supplicant</command> requests the kernel
|
||||
driver to scan neighboring BSSes</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><command>wpa_supplicant</command> selects a BSS based on
|
||||
its configuration</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><command>wpa_supplicant</command> requests the kernel
|
||||
driver to associate with the chosen BSS</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>If WPA-EAP: integrated IEEE 802.1X Supplicant
|
||||
completes EAP authentication with the
|
||||
authentication server (proxied by the Authenticator in the
|
||||
AP)</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>If WPA-EAP: master key is received from the IEEE 802.1X
|
||||
Supplicant</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>If WPA-PSK: <command>wpa_supplicant</command> uses PSK
|
||||
as the master session key</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><command>wpa_supplicant</command> completes WPA 4-Way
|
||||
Handshake and Group Key Handshake with the Authenticator
|
||||
(AP)</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><command>wpa_supplicant</command> configures encryption
|
||||
keys for unicast and broadcast</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>normal data packets can be transmitted and received</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Supported Features</title>
|
||||
<para>Supported WPA/IEEE 802.11i features:</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>WPA-PSK ("WPA-Personal")</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>WPA with EAP (e.g., with RADIUS authentication server)
|
||||
("WPA-Enterprise") Following authentication methods are
|
||||
supported with an integrate IEEE 802.1X Supplicant:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>EAP-TLS</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>EAP-PEAP/MSCHAPv2 (both PEAPv0 and PEAPv1)</para>
|
||||
</listitem>
|
||||
|
||||
|
||||
<listitem>
|
||||
<para>EAP-PEAP/TLS (both PEAPv0 and PEAPv1)</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>EAP-PEAP/GTC (both PEAPv0 and PEAPv1)</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>EAP-PEAP/OTP (both PEAPv0 and PEAPv1)</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>EAP-PEAP/MD5-Challenge (both PEAPv0 and PEAPv1)</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>EAP-TTLS/EAP-MD5-Challenge</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>EAP-TTLS/EAP-GTC</para>
|
||||
</listitem>
|
||||
|
||||
<listitem><para>EAP-TTLS/EAP-OTP</para></listitem>
|
||||
|
||||
<listitem><para>EAP-TTLS/EAP-MSCHAPv2</para></listitem>
|
||||
|
||||
<listitem><para>EAP-TTLS/EAP-TLS</para></listitem>
|
||||
|
||||
<listitem><para>EAP-TTLS/MSCHAPv2</para></listitem>
|
||||
|
||||
<listitem><para>EAP-TTLS/MSCHAP</para></listitem>
|
||||
|
||||
<listitem><para>EAP-TTLS/PAP</para></listitem>
|
||||
|
||||
<listitem><para>EAP-TTLS/CHAP</para></listitem>
|
||||
|
||||
<listitem><para>EAP-SIM</para></listitem>
|
||||
|
||||
<listitem><para>EAP-AKA</para></listitem>
|
||||
|
||||
<listitem><para>EAP-PSK</para></listitem>
|
||||
|
||||
<listitem><para>EAP-PAX</para></listitem>
|
||||
|
||||
<listitem><para>LEAP (note: requires special support from
|
||||
the driver for IEEE 802.11 authentication)</para></listitem>
|
||||
|
||||
<listitem><para>(following methods are supported, but since
|
||||
they do not generate keying material, they cannot be used
|
||||
with WPA or IEEE 802.1X WEP keying)</para></listitem>
|
||||
|
||||
<listitem><para>EAP-MD5-Challenge </para></listitem>
|
||||
|
||||
<listitem><para>EAP-MSCHAPv2</para></listitem>
|
||||
|
||||
<listitem><para>EAP-GTC</para></listitem>
|
||||
|
||||
<listitem><para>EAP-OTP</para></listitem>
|
||||
</itemizedlist>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>key management for CCMP, TKIP, WEP104, WEP40</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>RSN/WPA2 (IEEE 802.11i)</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>pre-authentication</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>PMKSA caching</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Available Drivers</title>
|
||||
<para>A summary of available driver backends is below. Support for each
|
||||
of the driver backends is chosen at wpa_supplicant compile time. For a
|
||||
list of supported driver backends that may be used with the -D option on
|
||||
your system, refer to the help output of wpa_supplicant
|
||||
(<emphasis>wpa_supplicant -h</emphasis>).</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>nl80211</term>
|
||||
<listitem>
|
||||
<para>Uses the modern Linux nl80211/cfg80211 netlink-based
|
||||
interface (most new drivers).</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>wext</term>
|
||||
<listitem>
|
||||
<para>Uses the legacy Linux wireless extensions ioctl-based
|
||||
interface (older hardware/drivers).</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>wired</term>
|
||||
<listitem>
|
||||
<para>wpa_supplicant wired Ethernet driver</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>roboswitch</term>
|
||||
<listitem>
|
||||
<para>wpa_supplicant Broadcom switch driver</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>bsd</term>
|
||||
<listitem>
|
||||
<para>BSD 802.11 support (Atheros, etc.).</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>ndis</term>
|
||||
<listitem>
|
||||
<para>Windows NDIS driver.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Command Line Options</title>
|
||||
<para>Most command line options have global scope. Some are given per
|
||||
interface, and are only valid if at least one <option>-i</option> option
|
||||
is specified, otherwise they're ignored. Option groups for different
|
||||
interfaces must be separated by <option>-N</option> option.</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>-b br_ifname</term>
|
||||
<listitem>
|
||||
<para>Optional bridge interface name. (Per interface)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-B</term>
|
||||
<listitem>
|
||||
<para>Run daemon in the background.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-c filename</term>
|
||||
<listitem>
|
||||
<para>Path to configuration file. (Per interface)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-C ctrl_interface</term>
|
||||
<listitem>
|
||||
<para>Path to ctrl_interface socket (Per interface. Only used if
|
||||
<option>-c</option> is not).</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-i ifname</term>
|
||||
<listitem>
|
||||
<para>Interface to listen on. Multiple instances of this option can
|
||||
be present, one per interface, separated by <option>-N</option>
|
||||
option (see below).</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-d</term>
|
||||
<listitem>
|
||||
<para>Increase debugging verbosity (<option>-dd</option> even
|
||||
more).</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-D driver</term>
|
||||
<listitem>
|
||||
<para>Driver to use (can be multiple drivers: nl80211,wext).
|
||||
(Per interface, see the available options below.)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-e entropy file</term>
|
||||
<listitem>
|
||||
<para>File for <command>wpa_supplicant</command> to use to
|
||||
maintain its internal entropy store in over restarts.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-f output file</term>
|
||||
<listitem>
|
||||
<para>Log output to specified file instead of stdout. (This
|
||||
is only available if <command>wpa_supplicant</command> was
|
||||
built with the <literal>CONFIG_DEBUG_FILE</literal>
|
||||
option.)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-g global ctrl_interface</term>
|
||||
<listitem>
|
||||
<para>Path to global ctrl_interface socket. If specified, interface
|
||||
definitions may be omitted.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-K</term>
|
||||
<listitem>
|
||||
<para>Include keys (passwords, etc.) in debug output.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-h</term>
|
||||
<listitem>
|
||||
<para>Help. Show a usage message.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-L</term>
|
||||
<listitem>
|
||||
<para>Show license (BSD).</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-o override driver</term>
|
||||
<listitem>
|
||||
<para>Override the driver parameter for new
|
||||
interfaces.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-O override ctrl_interface</term>
|
||||
<listitem>
|
||||
<para>Override the ctrl_interface parameter for new
|
||||
interfaces.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-p</term>
|
||||
<listitem>
|
||||
<para>Driver parameters. (Per interface)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-P PID_file</term>
|
||||
<listitem>
|
||||
<para>Path to PID file.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-q</term>
|
||||
<listitem>
|
||||
<para>Decrease debugging verbosity (<option>-qq</option> even
|
||||
less).</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-s</term>
|
||||
<listitem>
|
||||
<para>Log output to syslog instead of stdout. (This is only
|
||||
available if <command>wpa_supplicant</command> was built
|
||||
with the <literal>CONFIG_DEBUG_SYSLOG</literal>
|
||||
option.)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-T</term>
|
||||
<listitem>
|
||||
<para>Log output to Linux tracing in addition to any other
|
||||
destinations. (This is only available
|
||||
if <command>wpa_supplicant</command> was built with
|
||||
the <literal>CONFIG_DEBUG_LINUX_TRACING</literal>
|
||||
option.)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-t</term>
|
||||
<listitem>
|
||||
<para>Include timestamp in debug messages.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-u</term>
|
||||
<listitem>
|
||||
<para>Enable DBus control interface. If enabled, interface
|
||||
definitions may be omitted. (This is only available
|
||||
if <command>wpa_supplicant</command> was built with
|
||||
the <literal>CONFIG_CTRL_IFACE_DBUS_NEW</literal> option.)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-v</term>
|
||||
<listitem>
|
||||
<para>Show version.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-W</term>
|
||||
<listitem>
|
||||
<para>Wait for a control interface monitor before starting.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-N</term>
|
||||
<listitem>
|
||||
<para>Start describing new interface.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Examples</title>
|
||||
|
||||
<para>In most common cases, <command>wpa_supplicant</command> is
|
||||
started with:</para>
|
||||
|
||||
<blockquote><programlisting>
|
||||
wpa_supplicant -B -c/etc/wpa_supplicant.conf -iwlan0
|
||||
</programlisting></blockquote>
|
||||
|
||||
<para>This makes the process fork into background.</para>
|
||||
|
||||
<para>The easiest way to debug problems, and to get debug log for
|
||||
bug reports, is to start <command>wpa_supplicant</command> on
|
||||
foreground with debugging enabled:</para>
|
||||
|
||||
<blockquote><programlisting>
|
||||
wpa_supplicant -c/etc/wpa_supplicant.conf -iwlan0 -d
|
||||
</programlisting></blockquote>
|
||||
|
||||
<para>If the specific driver wrapper is not known beforehand, it is
|
||||
possible to specify multiple comma separated driver wrappers on the command
|
||||
line. <command>wpa_supplicant</command> will use the first driver
|
||||
wrapper that is able to initialize the interface.</para>
|
||||
|
||||
<blockquote><programlisting>
|
||||
wpa_supplicant -Dnl80211,wext -c/etc/wpa_supplicant.conf -iwlan0
|
||||
</programlisting></blockquote>
|
||||
|
||||
<para><command>wpa_supplicant</command> can control multiple
|
||||
interfaces (radios) either by running one process for each
|
||||
interface separately or by running just one process and list of
|
||||
options at command line. Each interface is separated with -N
|
||||
argument. As an example, following command would start
|
||||
wpa_supplicant for two interfaces:</para>
|
||||
|
||||
<blockquote><programlisting>
|
||||
wpa_supplicant \
|
||||
-c wpa1.conf -i wlan0 -D nl80211 -N \
|
||||
-c wpa2.conf -i ath0 -D wext
|
||||
</programlisting></blockquote>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>OS Requirements</title>
|
||||
<para>Current hardware/software requirements:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Linux kernel 2.6.30 or higher with
|
||||
nl80211/cfg80211 support</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Linux kernel 2.4.x or higher with Linux Wireless
|
||||
Extensions v15 or newer</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>FreeBSD 6-CURRENT</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Microsoft Windows with WinPcap (at least WinXP, may work
|
||||
with other versions)</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Supported Drivers</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>Linux nl80211/cfg80211</term>
|
||||
<listitem>
|
||||
<para>This is the preferred driver for Linux.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>Linux wireless extensions</term>
|
||||
<listitem>
|
||||
<para>In theory, any driver that supports Linux wireless
|
||||
extensions can be used with IEEE 802.1X (i.e., not WPA) when
|
||||
using ap_scan=0 option in configuration file.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>Wired Ethernet drivers</term>
|
||||
<listitem>
|
||||
<para>Use ap_scan=0.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>BSD net80211 layer (e.g., Atheros driver)</term>
|
||||
<listitem>
|
||||
<para>At the moment, this is for FreeBSD 6-CURRENT branch.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>Windows NDIS</term>
|
||||
<listitem>
|
||||
<para>The current Windows port requires WinPcap
|
||||
(http://winpcap.polito.it/). See README-Windows.txt for more
|
||||
information.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
|
||||
<para>wpa_supplicant was designed to be portable for different
|
||||
drivers and operating systems. Hopefully, support for more wlan
|
||||
cards and OSes will be added in the future. See developer.txt for
|
||||
more information about the design of wpa_supplicant and porting to
|
||||
other drivers. One main goal is to add full WPA/WPA2 support to
|
||||
Linux wireless extensions to allow new drivers to be supported
|
||||
without having to implement new driver-specific interface code in
|
||||
wpa_supplicant.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Architecture</title> <para>The
|
||||
<command>wpa_supplicant</command> system consists of the following
|
||||
components:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><filename>wpa_supplicant.conf</filename> </term>
|
||||
<listitem>
|
||||
<para>the configuration file describing all networks that the
|
||||
user wants the computer to connect to. </para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><command>wpa_supplicant</command></term>
|
||||
<listitem><para>the program that directly interacts with the
|
||||
network interface. </para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><command>wpa_cli</command></term> <listitem><para> the
|
||||
client program that provides a high-level interface to the
|
||||
functionality of the daemon. </para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><command>wpa_passphrase</command></term>
|
||||
<listitem><para>a utility needed to construct
|
||||
<filename>wpa_supplicant.conf</filename> files that include
|
||||
encrypted passwords.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Quick Start</title>
|
||||
|
||||
<para>First, make a configuration file, e.g.
|
||||
<filename>/etc/wpa_supplicant.conf</filename>, that describes the networks
|
||||
you are interested in. See <citerefentry>
|
||||
<refentrytitle>wpa_supplicant.conf</refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</citerefentry>
|
||||
for details.</para>
|
||||
|
||||
<para>Once the configuration is ready, you can test whether the
|
||||
configuration works by running <command>wpa_supplicant</command>
|
||||
with following command to start it on foreground with debugging
|
||||
enabled:</para>
|
||||
|
||||
<blockquote><programlisting>
|
||||
wpa_supplicant -iwlan0 -c/etc/wpa_supplicant.conf -d
|
||||
</programlisting></blockquote>
|
||||
|
||||
<para>Assuming everything goes fine, you can start using following
|
||||
command to start <command>wpa_supplicant</command> on background
|
||||
without debugging:</para>
|
||||
|
||||
<blockquote><programlisting>
|
||||
wpa_supplicant -iwlan0 -c/etc/wpa_supplicant.conf -B
|
||||
</programlisting></blockquote>
|
||||
|
||||
<para>Please note that if you included more than one driver
|
||||
interface in the build time configuration (.config), you may need
|
||||
to specify which interface to use by including -D<driver
|
||||
name> option on the command line.</para>
|
||||
|
||||
<!-- XXX at this point, the page could include a little script
|
||||
based on wpa_cli to wait for a connection and then run
|
||||
dhclient -->
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Interface to pcmcia-cs/cardmrg</title>
|
||||
|
||||
<para>For example, following small changes to pcmcia-cs scripts
|
||||
can be used to enable WPA support:</para>
|
||||
|
||||
<para>Add MODE="Managed" and WPA="y" to the network scheme in
|
||||
<filename>/etc/pcmcia/wireless.opts</filename>.</para>
|
||||
|
||||
<para>Add the following block to the end of <emphasis>start</emphasis>
|
||||
action handler in <filename>/etc/pcmcia/wireless</filename>:</para>
|
||||
|
||||
<blockquote><programlisting>
|
||||
if [ "$WPA" = "y" -a -x /usr/local/bin/wpa_supplicant ]; then
|
||||
/usr/local/bin/wpa_supplicant -B -c/etc/wpa_supplicant.conf -i$DEVICE
|
||||
fi
|
||||
</programlisting></blockquote>
|
||||
|
||||
|
||||
<para>Add the following block to the end of <emphasis>stop</emphasis>
|
||||
action handler (may need to be separated from other actions) in
|
||||
<filename>/etc/pcmcia/wireless</filename>:</para>
|
||||
|
||||
<blockquote><programlisting>
|
||||
if [ "$WPA" = "y" -a -x /usr/local/bin/wpa_supplicant ]; then
|
||||
killall wpa_supplicant
|
||||
fi
|
||||
</programlisting></blockquote>
|
||||
|
||||
<para>This will make <command>cardmgr</command> start
|
||||
<command>wpa_supplicant</command> when the card is plugged
|
||||
in.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<para>
|
||||
<citerefentry>
|
||||
<refentrytitle>wpa_background</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</citerefentry>
|
||||
<citerefentry>
|
||||
<refentrytitle>wpa_supplicant.conf</refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</citerefentry>
|
||||
<citerefentry>
|
||||
<refentrytitle>wpa_cli</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</citerefentry>
|
||||
<citerefentry>
|
||||
<refentrytitle>wpa_passphrase</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>Legal</title>
|
||||
<para>wpa_supplicant is copyright (c) 2003-2022,
|
||||
Jouni Malinen <email>j@w1.fi</email> and
|
||||
contributors.
|
||||
All Rights Reserved.</para>
|
||||
|
||||
<para>This program is licensed under the BSD license (the one with
|
||||
advertisement clause removed).</para>
|
||||
</refsect1>
|
||||
</refentry>
|
3995
wpa_supplicant/dpp_supplicant.c
Normal file
3995
wpa_supplicant/dpp_supplicant.c
Normal file
File diff suppressed because it is too large
Load Diff
45
wpa_supplicant/dpp_supplicant.h
Normal file
45
wpa_supplicant/dpp_supplicant.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* wpa_supplicant - DPP
|
||||
* Copyright (c) 2017, Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018-2020, The Linux Foundation
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef DPP_SUPPLICANT_H
|
||||
#define DPP_SUPPLICANT_H
|
||||
|
||||
enum dpp_status_error;
|
||||
|
||||
int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd);
|
||||
int wpas_dpp_nfc_uri(struct wpa_supplicant *wpa_s, const char *cmd);
|
||||
int wpas_dpp_nfc_handover_req(struct wpa_supplicant *wpa_s, const char *cmd);
|
||||
int wpas_dpp_nfc_handover_sel(struct wpa_supplicant *wpa_s, const char *cmd);
|
||||
int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd);
|
||||
int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd);
|
||||
void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s);
|
||||
void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
|
||||
unsigned int freq, unsigned int duration);
|
||||
void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
|
||||
unsigned int freq);
|
||||
void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
|
||||
const u8 *buf, size_t len, unsigned int freq);
|
||||
int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd);
|
||||
int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd);
|
||||
int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id);
|
||||
void wpas_dpp_stop(struct wpa_supplicant *wpa_s);
|
||||
int wpas_dpp_init(struct wpa_supplicant *wpa_s);
|
||||
void wpas_dpp_deinit(struct wpa_supplicant *wpa_s);
|
||||
int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
|
||||
struct wpa_bss *bss);
|
||||
int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd);
|
||||
void wpas_dpp_connected(struct wpa_supplicant *wpa_s);
|
||||
void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s,
|
||||
enum dpp_status_error result);
|
||||
int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd);
|
||||
void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s);
|
||||
int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd);
|
||||
int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd);
|
||||
|
||||
#endif /* DPP_SUPPLICANT_H */
|
1120
wpa_supplicant/driver_i.h
Normal file
1120
wpa_supplicant/driver_i.h
Normal file
File diff suppressed because it is too large
Load Diff
0
wpa_supplicant/eap_proxy_dummy.mak
Normal file
0
wpa_supplicant/eap_proxy_dummy.mak
Normal file
0
wpa_supplicant/eap_proxy_dummy.mk
Normal file
0
wpa_supplicant/eap_proxy_dummy.mk
Normal file
271
wpa_supplicant/eap_register.c
Normal file
271
wpa_supplicant/eap_register.c
Normal file
@ -0,0 +1,271 @@
|
||||
/*
|
||||
* EAP method registration
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "eap_peer/eap_methods.h"
|
||||
#include "eap_server/eap_methods.h"
|
||||
#include "wpa_supplicant_i.h"
|
||||
|
||||
|
||||
/**
|
||||
* eap_register_methods - Register statically linked EAP methods
|
||||
* Returns: 0 on success, -1 or -2 on failure
|
||||
*
|
||||
* This function is called at program initialization to register all EAP
|
||||
* methods that were linked in statically.
|
||||
*/
|
||||
int eap_register_methods(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifdef EAP_MD5
|
||||
if (ret == 0)
|
||||
ret = eap_peer_md5_register();
|
||||
#endif /* EAP_MD5 */
|
||||
|
||||
#ifdef EAP_TLS
|
||||
if (ret == 0)
|
||||
ret = eap_peer_tls_register();
|
||||
#endif /* EAP_TLS */
|
||||
|
||||
#ifdef EAP_UNAUTH_TLS
|
||||
if (ret == 0)
|
||||
ret = eap_peer_unauth_tls_register();
|
||||
#endif /* EAP_UNAUTH_TLS */
|
||||
|
||||
#ifdef EAP_TLS
|
||||
#ifdef CONFIG_HS20
|
||||
if (ret == 0)
|
||||
ret = eap_peer_wfa_unauth_tls_register();
|
||||
#endif /* CONFIG_HS20 */
|
||||
#endif /* EAP_TLS */
|
||||
|
||||
#ifdef EAP_MSCHAPv2
|
||||
if (ret == 0)
|
||||
ret = eap_peer_mschapv2_register();
|
||||
#endif /* EAP_MSCHAPv2 */
|
||||
|
||||
#ifdef EAP_PEAP
|
||||
if (ret == 0)
|
||||
ret = eap_peer_peap_register();
|
||||
#endif /* EAP_PEAP */
|
||||
|
||||
#ifdef EAP_TTLS
|
||||
if (ret == 0)
|
||||
ret = eap_peer_ttls_register();
|
||||
#endif /* EAP_TTLS */
|
||||
|
||||
#ifdef EAP_GTC
|
||||
if (ret == 0)
|
||||
ret = eap_peer_gtc_register();
|
||||
#endif /* EAP_GTC */
|
||||
|
||||
#ifdef EAP_OTP
|
||||
if (ret == 0)
|
||||
ret = eap_peer_otp_register();
|
||||
#endif /* EAP_OTP */
|
||||
|
||||
#ifdef EAP_SIM
|
||||
if (ret == 0)
|
||||
ret = eap_peer_sim_register();
|
||||
#endif /* EAP_SIM */
|
||||
|
||||
#ifdef EAP_LEAP
|
||||
if (ret == 0)
|
||||
ret = eap_peer_leap_register();
|
||||
#endif /* EAP_LEAP */
|
||||
|
||||
#ifdef EAP_PSK
|
||||
if (ret == 0)
|
||||
ret = eap_peer_psk_register();
|
||||
#endif /* EAP_PSK */
|
||||
|
||||
#ifdef EAP_AKA
|
||||
if (ret == 0)
|
||||
ret = eap_peer_aka_register();
|
||||
#endif /* EAP_AKA */
|
||||
|
||||
#ifdef EAP_AKA_PRIME
|
||||
if (ret == 0)
|
||||
ret = eap_peer_aka_prime_register();
|
||||
#endif /* EAP_AKA_PRIME */
|
||||
|
||||
#ifdef EAP_FAST
|
||||
if (ret == 0)
|
||||
ret = eap_peer_fast_register();
|
||||
#endif /* EAP_FAST */
|
||||
|
||||
#ifdef EAP_TEAP
|
||||
if (ret == 0)
|
||||
ret = eap_peer_teap_register();
|
||||
#endif /* EAP_TEAP */
|
||||
|
||||
#ifdef EAP_PAX
|
||||
if (ret == 0)
|
||||
ret = eap_peer_pax_register();
|
||||
#endif /* EAP_PAX */
|
||||
|
||||
#ifdef EAP_SAKE
|
||||
if (ret == 0)
|
||||
ret = eap_peer_sake_register();
|
||||
#endif /* EAP_SAKE */
|
||||
|
||||
#ifdef EAP_GPSK
|
||||
if (ret == 0)
|
||||
ret = eap_peer_gpsk_register();
|
||||
#endif /* EAP_GPSK */
|
||||
|
||||
#ifdef EAP_WSC
|
||||
if (ret == 0)
|
||||
ret = eap_peer_wsc_register();
|
||||
#endif /* EAP_WSC */
|
||||
|
||||
#ifdef EAP_IKEV2
|
||||
if (ret == 0)
|
||||
ret = eap_peer_ikev2_register();
|
||||
#endif /* EAP_IKEV2 */
|
||||
|
||||
#ifdef EAP_VENDOR_TEST
|
||||
if (ret == 0)
|
||||
ret = eap_peer_vendor_test_register();
|
||||
#endif /* EAP_VENDOR_TEST */
|
||||
|
||||
#ifdef EAP_TNC
|
||||
if (ret == 0)
|
||||
ret = eap_peer_tnc_register();
|
||||
#endif /* EAP_TNC */
|
||||
|
||||
#ifdef EAP_PWD
|
||||
if (ret == 0)
|
||||
ret = eap_peer_pwd_register();
|
||||
#endif /* EAP_PWD */
|
||||
|
||||
#ifdef EAP_EKE
|
||||
if (ret == 0)
|
||||
ret = eap_peer_eke_register();
|
||||
#endif /* EAP_EKE */
|
||||
|
||||
#ifdef EAP_SERVER_IDENTITY
|
||||
if (ret == 0)
|
||||
ret = eap_server_identity_register();
|
||||
#endif /* EAP_SERVER_IDENTITY */
|
||||
|
||||
#ifdef EAP_SERVER_MD5
|
||||
if (ret == 0)
|
||||
ret = eap_server_md5_register();
|
||||
#endif /* EAP_SERVER_MD5 */
|
||||
|
||||
#ifdef EAP_SERVER_TLS
|
||||
if (ret == 0)
|
||||
ret = eap_server_tls_register();
|
||||
#endif /* EAP_SERVER_TLS */
|
||||
|
||||
#ifdef EAP_SERVER_UNAUTH_TLS
|
||||
if (ret == 0)
|
||||
ret = eap_server_unauth_tls_register();
|
||||
#endif /* EAP_SERVER_UNAUTH_TLS */
|
||||
|
||||
#ifdef EAP_SERVER_MSCHAPV2
|
||||
if (ret == 0)
|
||||
ret = eap_server_mschapv2_register();
|
||||
#endif /* EAP_SERVER_MSCHAPV2 */
|
||||
|
||||
#ifdef EAP_SERVER_PEAP
|
||||
if (ret == 0)
|
||||
ret = eap_server_peap_register();
|
||||
#endif /* EAP_SERVER_PEAP */
|
||||
|
||||
#ifdef EAP_SERVER_TLV
|
||||
if (ret == 0)
|
||||
ret = eap_server_tlv_register();
|
||||
#endif /* EAP_SERVER_TLV */
|
||||
|
||||
#ifdef EAP_SERVER_GTC
|
||||
if (ret == 0)
|
||||
ret = eap_server_gtc_register();
|
||||
#endif /* EAP_SERVER_GTC */
|
||||
|
||||
#ifdef EAP_SERVER_TTLS
|
||||
if (ret == 0)
|
||||
ret = eap_server_ttls_register();
|
||||
#endif /* EAP_SERVER_TTLS */
|
||||
|
||||
#ifdef EAP_SERVER_SIM
|
||||
if (ret == 0)
|
||||
ret = eap_server_sim_register();
|
||||
#endif /* EAP_SERVER_SIM */
|
||||
|
||||
#ifdef EAP_SERVER_AKA
|
||||
if (ret == 0)
|
||||
ret = eap_server_aka_register();
|
||||
#endif /* EAP_SERVER_AKA */
|
||||
|
||||
#ifdef EAP_SERVER_AKA_PRIME
|
||||
if (ret == 0)
|
||||
ret = eap_server_aka_prime_register();
|
||||
#endif /* EAP_SERVER_AKA_PRIME */
|
||||
|
||||
#ifdef EAP_SERVER_PAX
|
||||
if (ret == 0)
|
||||
ret = eap_server_pax_register();
|
||||
#endif /* EAP_SERVER_PAX */
|
||||
|
||||
#ifdef EAP_SERVER_PSK
|
||||
if (ret == 0)
|
||||
ret = eap_server_psk_register();
|
||||
#endif /* EAP_SERVER_PSK */
|
||||
|
||||
#ifdef EAP_SERVER_SAKE
|
||||
if (ret == 0)
|
||||
ret = eap_server_sake_register();
|
||||
#endif /* EAP_SERVER_SAKE */
|
||||
|
||||
#ifdef EAP_SERVER_GPSK
|
||||
if (ret == 0)
|
||||
ret = eap_server_gpsk_register();
|
||||
#endif /* EAP_SERVER_GPSK */
|
||||
|
||||
#ifdef EAP_SERVER_VENDOR_TEST
|
||||
if (ret == 0)
|
||||
ret = eap_server_vendor_test_register();
|
||||
#endif /* EAP_SERVER_VENDOR_TEST */
|
||||
|
||||
#ifdef EAP_SERVER_FAST
|
||||
if (ret == 0)
|
||||
ret = eap_server_fast_register();
|
||||
#endif /* EAP_SERVER_FAST */
|
||||
|
||||
#ifdef EAP_SERVER_TEAP
|
||||
if (ret == 0)
|
||||
ret = eap_server_teap_register();
|
||||
#endif /* EAP_SERVER_TEAP */
|
||||
|
||||
#ifdef EAP_SERVER_WSC
|
||||
if (ret == 0)
|
||||
ret = eap_server_wsc_register();
|
||||
#endif /* EAP_SERVER_WSC */
|
||||
|
||||
#ifdef EAP_SERVER_IKEV2
|
||||
if (ret == 0)
|
||||
ret = eap_server_ikev2_register();
|
||||
#endif /* EAP_SERVER_IKEV2 */
|
||||
|
||||
#ifdef EAP_SERVER_TNC
|
||||
if (ret == 0)
|
||||
ret = eap_server_tnc_register();
|
||||
#endif /* EAP_SERVER_TNC */
|
||||
|
||||
#ifdef EAP_SERVER_PWD
|
||||
if (ret == 0)
|
||||
ret = eap_server_pwd_register();
|
||||
#endif /* EAP_SERVER_PWD */
|
||||
|
||||
return ret;
|
||||
}
|
392
wpa_supplicant/eap_testing.txt
Normal file
392
wpa_supplicant/eap_testing.txt
Normal file
@ -0,0 +1,392 @@
|
||||
Automatic regression and interoperability testing of wpa_supplicant's
|
||||
IEEE 802.1X/EAPOL authentication
|
||||
|
||||
Test program:
|
||||
- Linked some parts of IEEE 802.1X Authenticator implementation from
|
||||
hostapd (RADIUS client and RADIUS processing, EAP<->RADIUS
|
||||
encapsulation/decapsulation) into wpa_supplicant.
|
||||
- Replaced wpa_supplicant.c and wpa.c with test code that trigger
|
||||
IEEE 802.1X authentication automatically without need for wireless
|
||||
client card or AP.
|
||||
- For EAP methods that generate keying material, the key derived by the
|
||||
Supplicant is verified to match with the one received by the (now
|
||||
integrated) Authenticator.
|
||||
|
||||
The full automated test suite can now be run in couple of seconds, but
|
||||
I'm more than willing to add new RADIUS authentication servers to make
|
||||
this take a bit more time.. ;-) As an extra bonus, this can also be
|
||||
seen as automatic regression/interoperability testing for the RADIUS
|
||||
server, too.
|
||||
|
||||
In order for me to be able to use a new authentication server, the
|
||||
server need to be available from Internet (at least from one static IP
|
||||
address) and I will need to get suitable user name/password pairs,
|
||||
certificates, and private keys for testing use. Other alternative
|
||||
would be to get an evaluation version of the server so that I can
|
||||
install it on my own test setup. If you are interested in providing
|
||||
either server access or evaluation version, please contact me
|
||||
(j@w1.fi).
|
||||
|
||||
|
||||
Test matrix
|
||||
|
||||
+) tested successfully
|
||||
F) failed
|
||||
-) server did not support
|
||||
?) not tested
|
||||
|
||||
Cisco ACS ----------------------------------------------------------.
|
||||
hostapd --------------------------------------------------------. |
|
||||
Cisco Aironet 1200 AP (local RADIUS server) ----------------. | |
|
||||
Periodik Labs Elektron ---------------------------------. | | |
|
||||
Lucent NavisRadius ---------------------------------. | | | |
|
||||
Interlink RAD-Series ---------------------------. | | | | |
|
||||
Radiator -----------------------------------. | | | | | |
|
||||
Meetinghouse Aegis ---------------------. | | | | | | |
|
||||
Funk Steel-Belted ------------------. | | | | | | | |
|
||||
Funk Odyssey -------------------. | | | | | | | | |
|
||||
Microsoft IAS --------------. | | | | | | | | | |
|
||||
FreeRADIUS -------------. | | | | | | | | | | |
|
||||
| | | | | | | | | | | |
|
||||
|
||||
EAP-MD5 + - - + + + + + - - + +
|
||||
EAP-GTC + - - ? + + + + - - + -
|
||||
EAP-OTP - - - - - + - - - - - -
|
||||
EAP-MSCHAPv2 + - - + + + + + - - + -
|
||||
EAP-TLS + + + + + + + + - - + +
|
||||
EAP-PEAPv0/MSCHAPv2 + + + + + + + + + - + +
|
||||
EAP-PEAPv0/GTC + - + - + + + + - - + +
|
||||
EAP-PEAPv0/OTP - - - - - + - - - - - -
|
||||
EAP-PEAPv0/MD5 + - - + + + + + - - + -
|
||||
EAP-PEAPv0/TLS + + - + + + F + - - + +
|
||||
EAP-PEAPv0/SIM - - - - - - - - - - + -
|
||||
EAP-PEAPv0/AKA - - - - - - - - - - + -
|
||||
EAP-PEAPv0/PSK - - - - - - - - - - + -
|
||||
EAP-PEAPv0/PAX - - - - - - - - - - + -
|
||||
EAP-PEAPv0/SAKE - - - - - - - - - - + -
|
||||
EAP-PEAPv0/GPSK - - - - - - - - - - + -
|
||||
EAP-PEAPv1/MSCHAPv2 - - + + + +1 + +5 +8 - + +
|
||||
EAP-PEAPv1/GTC - - + + + +1 + +5 +8 - + +
|
||||
EAP-PEAPv1/OTP - - - - - +1 - - - - - -
|
||||
EAP-PEAPv1/MD5 - - - + + +1 + +5 - - + -
|
||||
EAP-PEAPv1/TLS - - - + + +1 F +5 - - + +
|
||||
EAP-PEAPv1/SIM - - - - - - - - - - + -
|
||||
EAP-PEAPv1/AKA - - - - - - - - - - + -
|
||||
EAP-PEAPv1/PSK - - - - - - - - - - + -
|
||||
EAP-PEAPv1/PAX - - - - - - - - - - + -
|
||||
EAP-PEAPv1/SAKE - - - - - - - - - - + -
|
||||
EAP-PEAPv1/GPSK - - - - - - - - - - + -
|
||||
EAP-TTLS/CHAP + - +2 + + + + + + - + -
|
||||
EAP-TTLS/MSCHAP + - + + + + + + + - + -
|
||||
EAP-TTLS/MSCHAPv2 + - + + + + + + + - + -
|
||||
EAP-TTLS/PAP + - + + + + + + + - + -
|
||||
EAP-TTLS/EAP-MD5 + - +2 + + + + + + - + -
|
||||
EAP-TTLS/EAP-GTC + - +2 ? + + + + - - + -
|
||||
EAP-TTLS/EAP-OTP - - - - - + - - - - - -
|
||||
EAP-TTLS/EAP-MSCHAPv2 + - +2 + + + + + + - + -
|
||||
EAP-TTLS/EAP-TLS + - +2 + F + + + - - + -
|
||||
EAP-TTLS/EAP-SIM - - - - - - - - - - + -
|
||||
EAP-TTLS/EAP-AKA - - - - - - - - - - + -
|
||||
EAP-TTLS/EAP-PSK - - - - - - - - - - + -
|
||||
EAP-TTLS/EAP-PAX - - - - - - - - - - + -
|
||||
EAP-TTLS/EAP-SAKE - - - - - - - - - - + -
|
||||
EAP-TTLS/EAP-GPSK - - - - - - - - - - + -
|
||||
EAP-TTLS + TNC - - - - - + - - - - + -
|
||||
EAP-SIM + - - ? - + - ? - - + -
|
||||
EAP-AKA - - - - - + - - - - + -
|
||||
EAP-AKA' - - - - - - - - - - + -
|
||||
EAP-PSK +7 - - - - + - - - - + -
|
||||
EAP-PAX - - - - - + - - - - + -
|
||||
EAP-SAKE - - - - - - - - - - + -
|
||||
EAP-GPSK - - - - - - - - - - + -
|
||||
EAP-FAST/MSCHAPv2(prov) - - - + - + - - - + + +
|
||||
EAP-FAST/GTC(auth) - - - + - + - - - + + +
|
||||
EAP-FAST/MSCHAPv2(aprov)- - - - - + - - - - + +
|
||||
EAP-FAST/GTC(aprov) - - - - - + - - - - + +
|
||||
EAP-FAST/MD5(aprov) - - - - - + - - - - + -
|
||||
EAP-FAST/TLS(aprov) - - - - - - - - - - + +
|
||||
EAP-FAST/SIM(aprov) - - - - - - - - - - + -
|
||||
EAP-FAST/AKA(aprov) - - - - - - - - - - + -
|
||||
EAP-FAST/MSCHAPv2(auth) - - - - - + - - - - + +
|
||||
EAP-FAST/MD5(auth) - - - - - + - - - - + -
|
||||
EAP-FAST/TLS(auth) - - - - - - - - - - + +
|
||||
EAP-FAST/SIM(auth) - - - - - - - - - - + -
|
||||
EAP-FAST/AKA(auth) - - - - - - - - - - + -
|
||||
EAP-FAST + TNC - - - - - - - - - - + -
|
||||
LEAP + - + + + + F +6 - + - +
|
||||
EAP-TNC +9 - - - - + - - - - + -
|
||||
EAP-IKEv2 +10 - - - - - - - - - + -
|
||||
|
||||
1) PEAPv1 required new label, "client PEAP encryption" instead of "client EAP
|
||||
encryption", during key derivation (requires phase1="peaplabel=1" in the
|
||||
network configuration in wpa_supplicant.conf)
|
||||
2) used FreeRADIUS as inner auth server
|
||||
5) PEAPv1 required termination of negotiation on tunneled EAP-Success and new
|
||||
label in key deriviation
|
||||
(phase1="peap_outer_success=0 peaplabel=1") (in "IETF Draft 5" mode)
|
||||
6) Authenticator simulator required patching for handling Access-Accept within
|
||||
negotiation (for the first EAP-Success of LEAP)
|
||||
7) tested only with an older (incompatible) draft of EAP-PSK; FreeRADIUS does
|
||||
not support the current EAP-PSK (RFC) specification
|
||||
8) PEAPv1 used non-standard version negotiation (client had to force v1 even
|
||||
though server reported v0 as the highest supported version)
|
||||
9) only EAP-TTLS/EAP-TNC tested, i.e., test did not include proper sequence of
|
||||
client authentication followed by TNC inside the tunnel
|
||||
10) worked only with special compatibility code to match the IKEv2 server
|
||||
implementation
|
||||
|
||||
|
||||
Automated tests:
|
||||
|
||||
FreeRADIUS (2.0-beta/CVS snapshot)
|
||||
- EAP-MD5-Challenge
|
||||
- EAP-GTC
|
||||
- EAP-MSCHAPv2
|
||||
- EAP-TLS
|
||||
- EAP-PEAPv0 / MSCHAPv2
|
||||
- EAP-PEAPv0 / GTC
|
||||
- EAP-PEAPv0 / MD5-Challenge
|
||||
- EAP-PEAPv0 / TLS
|
||||
- EAP-TTLS / EAP-MD5-Challenge
|
||||
- EAP-TTLS / EAP-GTC
|
||||
- EAP-TTLS / EAP-MSCHAPv2
|
||||
- EAP-TTLS / EAP-TLS
|
||||
- EAP-TTLS / CHAP
|
||||
- EAP-TTLS / PAP
|
||||
- EAP-TTLS / MSCHAP
|
||||
- EAP-TTLS / MSCHAPv2
|
||||
- EAP-TTLS / EAP-TNC (partial support; no authentication sequence)
|
||||
- EAP-SIM
|
||||
- LEAP
|
||||
|
||||
Microsoft Windows Server 2003 / IAS
|
||||
- EAP-TLS
|
||||
- EAP-PEAPv0 / MSCHAPv2
|
||||
- EAP-PEAPv0 / TLS
|
||||
- EAP-MD5
|
||||
* IAS does not seem to support other EAP methods
|
||||
|
||||
Funk Odyssey 2.01.00.653
|
||||
- EAP-TLS
|
||||
- EAP-PEAPv0 / MSCHAPv2
|
||||
- EAP-PEAPv0 / GTC
|
||||
- EAP-PEAPv1 / MSCHAPv2
|
||||
- EAP-PEAPv1 / GTC
|
||||
Note: PEAPv1 requires TLS key derivation to use label "client EAP encryption"
|
||||
- EAP-TTLS / CHAP (using FreeRADIUS as inner auth srv)
|
||||
- EAP-TTLS / MSCHAP
|
||||
- EAP-TTLS / MSCHAPv2
|
||||
- EAP-TTLS / PAP
|
||||
- EAP-TTLS / EAP-MD5-Challenge (using FreeRADIUS as inner auth srv)
|
||||
- EAP-TTLS / EAP-GTC (using FreeRADIUS as inner auth srv)
|
||||
- EAP-TTLS / EAP-MSCHAPv2 (using FreeRADIUS as inner auth srv)
|
||||
- EAP-TTLS / EAP-TLS (using FreeRADIUS as inner auth srv)
|
||||
* not supported in Odyssey:
|
||||
- EAP-MD5-Challenge
|
||||
- EAP-GTC
|
||||
- EAP-MSCHAPv2
|
||||
- EAP-PEAP / MD5-Challenge
|
||||
- EAP-PEAP / TLS
|
||||
|
||||
Funk Steel-Belted Radius Enterprise Edition v4.71.739
|
||||
- EAP-MD5-Challenge
|
||||
- EAP-MSCHAPv2
|
||||
- EAP-TLS
|
||||
- EAP-PEAPv0 / MSCHAPv2
|
||||
- EAP-PEAPv0 / MD5
|
||||
- EAP-PEAPv0 / TLS
|
||||
- EAP-PEAPv1 / MSCHAPv2
|
||||
- EAP-PEAPv1 / MD5
|
||||
- EAP-PEAPv1 / GTC
|
||||
- EAP-PEAPv1 / TLS
|
||||
Note: PEAPv1 requires TLS key derivation to use label "client EAP encryption"
|
||||
- EAP-TTLS / CHAP
|
||||
- EAP-TTLS / MSCHAP
|
||||
- EAP-TTLS / MSCHAPv2
|
||||
- EAP-TTLS / PAP
|
||||
- EAP-TTLS / EAP-MD5-Challenge
|
||||
- EAP-TTLS / EAP-MSCHAPv2
|
||||
- EAP-TTLS / EAP-TLS
|
||||
|
||||
Meetinghouse Aegis 1.1.4
|
||||
- EAP-MD5-Challenge
|
||||
- EAP-GTC
|
||||
- EAP-MSCHAPv2
|
||||
- EAP-TLS
|
||||
- EAP-PEAPv0 / MSCHAPv2
|
||||
- EAP-PEAPv0 / TLS
|
||||
- EAP-PEAPv0 / GTC
|
||||
- EAP-PEAPv0 / MD5-Challenge
|
||||
- EAP-PEAPv1 / MSCHAPv2
|
||||
- EAP-PEAPv1 / TLS
|
||||
- EAP-PEAPv1 / GTC
|
||||
- EAP-PEAPv1 / MD5-Challenge
|
||||
Note: PEAPv1 requires TLS key derivation to use label "client EAP encryption"
|
||||
- EAP-TTLS / CHAP
|
||||
- EAP-TTLS / MSCHAP
|
||||
- EAP-TTLS / MSCHAPv2
|
||||
- EAP-TTLS / PAP
|
||||
- EAP-TTLS / EAP-MD5-Challenge
|
||||
- EAP-TTLS / EAP-GTC
|
||||
- EAP-TTLS / EAP-MSCHAPv2
|
||||
* did not work
|
||||
- EAP-TTLS / EAP-TLS
|
||||
(Server rejects authentication without any reason in debug log. It
|
||||
looks like the inner TLS negotiation starts properly and the last
|
||||
packet from Supplicant looks like the one sent in the Phase 1. The
|
||||
server generates a valid looking reply in the same way as in Phase
|
||||
1, but then ends up sending Access-Reject. Maybe an issue with TTLS
|
||||
fragmentation in the Aegis server(?) The packet seems to include
|
||||
1328 bytes of EAP-Message and this may go beyond the fragmentation
|
||||
limit with AVP encapsulation and TLS tunneling. Note: EAP-PEAP/TLS
|
||||
did work, so this issue seems to be with something TTLS specific.)
|
||||
|
||||
Radiator 3.17.1 (eval, with all patches up to and including 2007-05-25)
|
||||
- EAP-MD5-Challenge
|
||||
- EAP-GTC
|
||||
- EAP-OTP
|
||||
- EAP-MSCHAPv2
|
||||
- EAP-TLS
|
||||
- EAP-PEAPv0 / MSCHAPv2
|
||||
- EAP-PEAPv0 / GTC
|
||||
- EAP-PEAPv0 / OTP
|
||||
- EAP-PEAPv0 / MD5-Challenge
|
||||
- EAP-PEAPv0 / TLS
|
||||
Note: Needed to use unknown identity in outer auth and some times the server
|
||||
seems to get confused and fails to send proper Phase 2 data.
|
||||
- EAP-PEAPv1 / MSCHAPv2
|
||||
- EAP-PEAPv1 / GTC
|
||||
- EAP-PEAPv1 / OTP
|
||||
- EAP-PEAPv1 / MD5-Challenge
|
||||
- EAP-PEAPv1 / TLS
|
||||
Note: This has some additional requirements for EAPTLS_MaxFragmentSize.
|
||||
Using 1300 for outer auth and 500 for inner auth seemed to work.
|
||||
Note: Needed to use unknown identity in outer auth and some times the server
|
||||
seems to get confused and fails to send proper Phase 2 data.
|
||||
- EAP-TTLS / CHAP
|
||||
- EAP-TTLS / MSCHAP
|
||||
- EAP-TTLS / MSCHAPv2
|
||||
- EAP-TTLS / PAP
|
||||
- EAP-TTLS / EAP-MD5-Challenge
|
||||
- EAP-TTLS / EAP-GTC
|
||||
- EAP-TTLS / EAP-OTP
|
||||
- EAP-TTLS / EAP-MSCHAPv2
|
||||
- EAP-TTLS / EAP-TLS
|
||||
Note: This has some additional requirements for EAPTLS_MaxFragmentSize.
|
||||
Using 1300 for outer auth and 500 for inner auth seemed to work.
|
||||
- EAP-SIM
|
||||
- EAP-AKA
|
||||
- EAP-PSK
|
||||
- EAP-PAX
|
||||
- EAP-TNC
|
||||
|
||||
Interlink Networks RAD-Series 6.1.2.7
|
||||
- EAP-MD5-Challenge
|
||||
- EAP-GTC
|
||||
- EAP-MSCHAPv2
|
||||
- EAP-TLS
|
||||
- EAP-PEAPv0 / MSCHAPv2
|
||||
- EAP-PEAPv0 / GTC
|
||||
- EAP-PEAPv0 / MD5-Challenge
|
||||
- EAP-PEAPv1 / MSCHAPv2
|
||||
- EAP-PEAPv1 / GTC
|
||||
- EAP-PEAPv1 / MD5-Challenge
|
||||
Note: PEAPv1 requires TLS key derivation to use label "client EAP encryption"
|
||||
- EAP-TTLS / CHAP
|
||||
- EAP-TTLS / MSCHAP
|
||||
- EAP-TTLS / MSCHAPv2
|
||||
- EAP-TTLS / PAP
|
||||
- EAP-TTLS / EAP-MD5-Challenge
|
||||
- EAP-TTLS / EAP-GTC
|
||||
- EAP-TTLS / EAP-MSCHAPv2
|
||||
- EAP-TTLS / EAP-TLS
|
||||
* did not work
|
||||
- EAP-PEAPv0 / TLS
|
||||
- EAP-PEAPv1 / TLS
|
||||
(Failed to decrypt Phase 2 data)
|
||||
|
||||
Lucent NavisRadius 4.4.0
|
||||
- EAP-MD5-Challenge
|
||||
- EAP-GTC
|
||||
- EAP-MSCHAPv2
|
||||
- EAP-TLS
|
||||
- EAP-PEAPv0 / MD5-Challenge
|
||||
- EAP-PEAPv0 / MSCHAPv2
|
||||
- EAP-PEAPv0 / GTC
|
||||
- EAP-PEAPv0 / TLS
|
||||
- EAP-PEAPv1 / MD5-Challenge
|
||||
- EAP-PEAPv1 / MSCHAPv2
|
||||
- EAP-PEAPv1 / GTC
|
||||
- EAP-PEAPv1 / TLS
|
||||
"IETF Draft 5" mode requires phase1="peap_outer_success=0 peaplabel=1"
|
||||
'Cisco ACU 5.05' mode works without phase1 configuration
|
||||
- EAP-TTLS / CHAP
|
||||
- EAP-TTLS / MSCHAP
|
||||
- EAP-TTLS / MSCHAPv2
|
||||
- EAP-TTLS / PAP
|
||||
- EAP-TTLS / EAP-MD5-Challenge
|
||||
- EAP-TTLS / EAP-MSCHAPv2
|
||||
- EAP-TTLS / EAP-GTC
|
||||
- EAP-TTLS / EAP-TLS
|
||||
|
||||
Note: user certificate from NavisRadius had private key in a format
|
||||
that wpa_supplicant could not use. Converting this to PKCS#12 and then
|
||||
back to PEM allowed wpa_supplicant to use the key.
|
||||
|
||||
|
||||
hostapd v0.3.3
|
||||
- EAP-MD5-Challenge
|
||||
- EAP-GTC
|
||||
- EAP-MSCHAPv2
|
||||
- EAP-TLS
|
||||
- EAP-PEAPv0 / MSCHAPv2
|
||||
- EAP-PEAPv0 / GTC
|
||||
- EAP-PEAPv0 / MD5-Challenge
|
||||
- EAP-PEAPv1 / MSCHAPv2
|
||||
- EAP-PEAPv1 / GTC
|
||||
- EAP-PEAPv1 / MD5-Challenge
|
||||
- EAP-TTLS / CHAP
|
||||
- EAP-TTLS / MSCHAP
|
||||
- EAP-TTLS / MSCHAPv2
|
||||
- EAP-TTLS / PAP
|
||||
- EAP-TTLS / EAP-MD5-Challenge
|
||||
- EAP-TTLS / EAP-GTC
|
||||
- EAP-TTLS / EAP-MSCHAPv2
|
||||
- EAP-SIM
|
||||
- EAP-PAX
|
||||
|
||||
PEAPv1:
|
||||
|
||||
Funk Odyssey 2.01.00.653:
|
||||
- uses tunneled EAP-Success, expects reply in tunnel or TLS ACK, sends MPPE
|
||||
keys with outer EAP-Success message after this
|
||||
- uses label "client EAP encryption"
|
||||
- (peap_outer_success 1 and 2 work)
|
||||
|
||||
Funk Steel-Belted Radius Enterprise Edition v4.71.739
|
||||
- uses tunneled EAP-Success, expects reply in tunnel or TLS ACK, sends MPPE
|
||||
keys with outer EAP-Success message after this
|
||||
- uses label "client EAP encryption"
|
||||
- (peap_outer_success 1 and 2 work)
|
||||
|
||||
Radiator 3.9:
|
||||
- uses TLV Success and Reply, sends MPPE keys with outer EAP-Success message
|
||||
after this
|
||||
- uses label "client PEAP encryption"
|
||||
|
||||
Lucent NavisRadius 4.4.0 (in "IETF Draft 5" mode):
|
||||
- sends tunneled EAP-Success with MPPE keys and expects the authentication to
|
||||
terminate at this point (gets somewhat confused with reply to this)
|
||||
- uses label "client PEAP encryption"
|
||||
- phase1="peap_outer_success=0 peaplabel=1"
|
||||
|
||||
Lucent NavisRadius 4.4.0 (in "Cisco ACU 5.05" mode):
|
||||
- sends tunneled EAP-Success with MPPE keys and expects to receive TLS ACK
|
||||
as a reply
|
||||
- uses label "client EAP encryption"
|
||||
|
||||
Meetinghouse Aegis 1.1.4
|
||||
- uses tunneled EAP-Success, expects reply in tunnel or TLS ACK, sends MPPE
|
||||
keys with outer EAP-Success message after this
|
||||
- uses label "client EAP encryption"
|
||||
- peap_outer_success 1 and 2 work
|
1555
wpa_supplicant/eapol_test.c
Normal file
1555
wpa_supplicant/eapol_test.c
Normal file
File diff suppressed because it is too large
Load Diff
159
wpa_supplicant/eapol_test.py
Executable file
159
wpa_supplicant/eapol_test.py
Executable file
@ -0,0 +1,159 @@
|
||||
#!/usr/bin/env python2
|
||||
#
|
||||
# eapol_test controller
|
||||
# Copyright (c) 2015, Jouni Malinen <j@w1.fi>
|
||||
#
|
||||
# This software may be distributed under the terms of the BSD license.
|
||||
# See README for more details.
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import Queue
|
||||
import sys
|
||||
import threading
|
||||
|
||||
logger = logging.getLogger()
|
||||
dir = os.path.dirname(os.path.realpath(sys.modules[__name__].__file__))
|
||||
sys.path.append(os.path.join(dir, '..', 'wpaspy'))
|
||||
import wpaspy
|
||||
wpas_ctrl = '/tmp/eapol_test'
|
||||
|
||||
class eapol_test:
|
||||
def __init__(self, ifname):
|
||||
self.ifname = ifname
|
||||
self.ctrl = wpaspy.Ctrl(os.path.join(wpas_ctrl, ifname))
|
||||
if "PONG" not in self.ctrl.request("PING"):
|
||||
raise Exception("Failed to connect to eapol_test (%s)" % ifname)
|
||||
self.mon = wpaspy.Ctrl(os.path.join(wpas_ctrl, ifname))
|
||||
self.mon.attach()
|
||||
|
||||
def add_network(self):
|
||||
id = self.request("ADD_NETWORK")
|
||||
if "FAIL" in id:
|
||||
raise Exception("ADD_NETWORK failed")
|
||||
return int(id)
|
||||
|
||||
def remove_network(self, id):
|
||||
id = self.request("REMOVE_NETWORK " + str(id))
|
||||
if "FAIL" in id:
|
||||
raise Exception("REMOVE_NETWORK failed")
|
||||
return None
|
||||
|
||||
def set_network(self, id, field, value):
|
||||
res = self.request("SET_NETWORK " + str(id) + " " + field + " " + value)
|
||||
if "FAIL" in res:
|
||||
raise Exception("SET_NETWORK failed")
|
||||
return None
|
||||
|
||||
def set_network_quoted(self, id, field, value):
|
||||
res = self.request("SET_NETWORK " + str(id) + " " + field + ' "' + value + '"')
|
||||
if "FAIL" in res:
|
||||
raise Exception("SET_NETWORK failed")
|
||||
return None
|
||||
|
||||
def request(self, cmd, timeout=10):
|
||||
return self.ctrl.request(cmd, timeout=timeout)
|
||||
|
||||
def wait_event(self, events, timeout=10):
|
||||
start = os.times()[4]
|
||||
while True:
|
||||
while self.mon.pending():
|
||||
ev = self.mon.recv()
|
||||
logger.debug(self.ifname + ": " + ev)
|
||||
for event in events:
|
||||
if event in ev:
|
||||
return ev
|
||||
now = os.times()[4]
|
||||
remaining = start + timeout - now
|
||||
if remaining <= 0:
|
||||
break
|
||||
if not self.mon.pending(timeout=remaining):
|
||||
break
|
||||
return None
|
||||
|
||||
def run(ifname, count, no_fast_reauth, res, conf):
|
||||
et = eapol_test(ifname)
|
||||
|
||||
et.request("AP_SCAN 0")
|
||||
if no_fast_reauth:
|
||||
et.request("SET fast_reauth 0")
|
||||
else:
|
||||
et.request("SET fast_reauth 1")
|
||||
id = et.add_network()
|
||||
|
||||
if len(conf):
|
||||
for item in conf:
|
||||
et.set_network(id, item, conf[item])
|
||||
else:
|
||||
et.set_network(id, "key_mgmt", "IEEE8021X")
|
||||
et.set_network(id, "eapol_flags", "0")
|
||||
et.set_network(id, "eap", "TLS")
|
||||
et.set_network_quoted(id, "identity", "user")
|
||||
et.set_network_quoted(id, "ca_cert", 'ca.pem')
|
||||
et.set_network_quoted(id, "client_cert", 'client.pem')
|
||||
et.set_network_quoted(id, "private_key", 'client.key')
|
||||
et.set_network_quoted(id, "private_key_passwd", 'whatever')
|
||||
|
||||
et.set_network(id, "disabled", "0")
|
||||
|
||||
fail = False
|
||||
for i in range(count):
|
||||
et.request("REASSOCIATE")
|
||||
ev = et.wait_event(["CTRL-EVENT-CONNECTED", "CTRL-EVENT-EAP-FAILURE"])
|
||||
if ev is None or "CTRL-EVENT-CONNECTED" not in ev:
|
||||
fail = True
|
||||
break
|
||||
|
||||
et.remove_network(id)
|
||||
|
||||
if fail:
|
||||
res.put("FAIL (%d OK)" % i)
|
||||
else:
|
||||
res.put("PASS %d" % (i + 1))
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='eapol_test controller')
|
||||
parser.add_argument('--ctrl', help='control interface directory')
|
||||
parser.add_argument('--num', help='number of processes')
|
||||
parser.add_argument('--iter', help='number of iterations')
|
||||
parser.add_argument('--no-fast-reauth', action='store_true',
|
||||
dest='no_fast_reauth',
|
||||
help='disable TLS session resumption')
|
||||
parser.add_argument('--conf', help='file of network conf items')
|
||||
args = parser.parse_args()
|
||||
|
||||
num = int(args.num)
|
||||
iter = int(args.iter)
|
||||
if args.ctrl:
|
||||
global wpas_ctrl
|
||||
wpas_ctrl = args.ctrl
|
||||
|
||||
conf = {}
|
||||
if args.conf:
|
||||
f = open(args.conf, "r")
|
||||
for line in f:
|
||||
confitem = line.split("=")
|
||||
if len(confitem) == 2:
|
||||
conf[confitem[0].strip()] = confitem[1].strip()
|
||||
f.close()
|
||||
|
||||
t = {}
|
||||
res = {}
|
||||
for i in range(num):
|
||||
res[i] = Queue.Queue()
|
||||
t[i] = threading.Thread(target=run, args=(str(i), iter,
|
||||
args.no_fast_reauth, res[i],
|
||||
conf))
|
||||
for i in range(num):
|
||||
t[i].start()
|
||||
for i in range(num):
|
||||
t[i].join()
|
||||
try:
|
||||
results = res[i].get(False)
|
||||
except:
|
||||
results = "N/A"
|
||||
print("%d: %s" % (i, results))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
5783
wpa_supplicant/events.c
Normal file
5783
wpa_supplicant/events.c
Normal file
File diff suppressed because it is too large
Load Diff
19
wpa_supplicant/examples/60_wpa_supplicant
Executable file
19
wpa_supplicant/examples/60_wpa_supplicant
Executable file
@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
|
||||
# /etc/pm/sleep.d/60_wpa_supplicant
|
||||
# Action script to notify wpa_supplicant of pm-action events.
|
||||
|
||||
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
||||
|
||||
WPACLI=wpa_cli
|
||||
|
||||
case "$1" in
|
||||
suspend|hibernate)
|
||||
$WPACLI suspend
|
||||
;;
|
||||
resume|thaw)
|
||||
$WPACLI resume
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
66
wpa_supplicant/examples/dbus-listen-preq.py
Executable file
66
wpa_supplicant/examples/dbus-listen-preq.py
Executable file
@ -0,0 +1,66 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
from __future__ import print_function
|
||||
import dbus
|
||||
import sys
|
||||
import time
|
||||
import gobject
|
||||
from dbus.mainloop.glib import DBusGMainLoop
|
||||
|
||||
WPAS_DBUS_SERVICE = "fi.w1.wpa_supplicant1"
|
||||
WPAS_DBUS_INTERFACE = "fi.w1.wpa_supplicant1"
|
||||
WPAS_DBUS_OPATH = "/fi/w1/wpa_supplicant1"
|
||||
WPAS_DBUS_INTERFACES_INTERFACE = "fi.w1.wpa_supplicant1.Interface"
|
||||
|
||||
def usage():
|
||||
print("Usage: %s <ifname>" % sys.argv[0])
|
||||
print("Press Ctrl-C to stop")
|
||||
|
||||
def ProbeRequest(args):
|
||||
if 'addr' in args:
|
||||
print('%.2x:%.2x:%.2x:%.2x:%.2x:%.2x' % tuple(args['addr']),
|
||||
end=' ')
|
||||
if 'dst' in args:
|
||||
print('-> %.2x:%.2x:%.2x:%.2x:%.2x:%.2x' % tuple(args['dst']),
|
||||
end=' ')
|
||||
if 'bssid' in args:
|
||||
print('(bssid %.2x:%.2x:%.2x:%.2x:%.2x:%.2x)' % tuple(args['dst']),
|
||||
end=' ')
|
||||
if 'signal' in args:
|
||||
print('signal:%d' % args['signal'], end=' ')
|
||||
if 'ies' in args:
|
||||
print('have IEs (%d bytes)' % len(args['ies']), end=' ')
|
||||
print('')
|
||||
|
||||
if __name__ == "__main__":
|
||||
global bus
|
||||
global wpas_obj
|
||||
global if_obj
|
||||
global p2p_iface
|
||||
|
||||
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
|
||||
|
||||
bus = dbus.SystemBus()
|
||||
wpas_obj = bus.get_object(WPAS_DBUS_SERVICE, WPAS_DBUS_OPATH)
|
||||
|
||||
# Print list of i/f if no one is specified
|
||||
if (len(sys.argv) < 2) :
|
||||
usage()
|
||||
sys.exit(0)
|
||||
|
||||
wpas = dbus.Interface(wpas_obj, WPAS_DBUS_INTERFACE)
|
||||
|
||||
ifname = sys.argv[1]
|
||||
|
||||
path = wpas.GetInterface(ifname)
|
||||
|
||||
if_obj = bus.get_object(WPAS_DBUS_SERVICE, path)
|
||||
iface = dbus.Interface(if_obj, WPAS_DBUS_INTERFACES_INTERFACE)
|
||||
|
||||
bus.add_signal_receiver(ProbeRequest,
|
||||
dbus_interface=WPAS_DBUS_INTERFACES_INTERFACE,
|
||||
signal_name="ProbeRequest")
|
||||
|
||||
iface.SubscribeProbeReq()
|
||||
|
||||
gobject.MainLoop().run()
|
1186
wpa_supplicant/examples/dpp-nfc.py
Executable file
1186
wpa_supplicant/examples/dpp-nfc.py
Executable file
File diff suppressed because it is too large
Load Diff
130
wpa_supplicant/examples/dpp-qrcode.py
Executable file
130
wpa_supplicant/examples/dpp-qrcode.py
Executable file
@ -0,0 +1,130 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Example Android logcat to wpa_supplicant wrapper for QR Code scans
|
||||
# Copyright (c) 2017, Qualcomm Atheros, Inc.
|
||||
#
|
||||
# This software may be distributed under the terms of the BSD license.
|
||||
# See README for more details.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
import qrcode
|
||||
|
||||
scriptsdir = os.path.dirname(os.path.realpath(sys.modules[__name__].__file__))
|
||||
sys.path.append(os.path.join(scriptsdir, '..', '..', 'wpaspy'))
|
||||
|
||||
import wpaspy
|
||||
|
||||
wpas_ctrl = '/var/run/wpa_supplicant'
|
||||
|
||||
def wpas_connect():
|
||||
ifaces = []
|
||||
if os.path.isdir(wpas_ctrl):
|
||||
try:
|
||||
ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)]
|
||||
except OSError as error:
|
||||
print("Could not find wpa_supplicant: ", error)
|
||||
return None
|
||||
|
||||
if len(ifaces) < 1:
|
||||
print("No wpa_supplicant control interface found")
|
||||
return None
|
||||
|
||||
for ctrl in ifaces:
|
||||
try:
|
||||
wpas = wpaspy.Ctrl(ctrl)
|
||||
return wpas
|
||||
except Exception as e:
|
||||
pass
|
||||
return None
|
||||
|
||||
def dpp_logcat():
|
||||
for line in iter(sys.stdin.readline, ''):
|
||||
if "ResultHandler: Launching intent: Intent" not in line:
|
||||
continue
|
||||
if "act=android.intent.action.VIEW" not in line:
|
||||
continue
|
||||
uri = None
|
||||
for val in line.split(' '):
|
||||
if val.startswith('dat='):
|
||||
uri = val.split('=', 1)[1]
|
||||
break
|
||||
if not uri:
|
||||
continue
|
||||
if not uri.startswith('DPP:'):
|
||||
continue
|
||||
print("Found DPP bootstrap info URI:")
|
||||
print(uri)
|
||||
wpas = wpas_connect()
|
||||
if not wpas:
|
||||
print("Could not connect to wpa_supplicant")
|
||||
print('')
|
||||
continue
|
||||
res = wpas.request("DPP_QR_CODE " + uri);
|
||||
try:
|
||||
id = int(res)
|
||||
except ValueError:
|
||||
print("QR Code URI rejected")
|
||||
continue
|
||||
print("QR Code URI accepted - ID=%d" % id)
|
||||
print(wpas.request("DPP_BOOTSTRAP_INFO %d" % id))
|
||||
del wpas
|
||||
|
||||
def dpp_display(curve):
|
||||
wpas = wpas_connect()
|
||||
if not wpas:
|
||||
print("Could not connect to wpa_supplicant")
|
||||
return
|
||||
res = wpas.request("STATUS")
|
||||
addr = None
|
||||
for line in res.splitlines():
|
||||
if line.startswith("address="):
|
||||
addr = line.split('=')[1]
|
||||
break
|
||||
cmd = "DPP_BOOTSTRAP_GEN type=qrcode"
|
||||
cmd += " chan=81/1"
|
||||
if addr:
|
||||
cmd += " mac=" + addr.replace(':','')
|
||||
if curve:
|
||||
cmd += " curve=" + curve
|
||||
res = wpas.request(cmd)
|
||||
try:
|
||||
id = int(res)
|
||||
except ValueError:
|
||||
print("Failed to generate bootstrap info URI")
|
||||
return
|
||||
print("Bootstrap information - ID=%d" % id)
|
||||
print(wpas.request("DPP_BOOTSTRAP_INFO %d" % id))
|
||||
uri = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % id)
|
||||
print(uri)
|
||||
print("ID=%d" % id)
|
||||
qr = qrcode.QRCode(error_correction=qrcode.constants.ERROR_CORRECT_M,
|
||||
border=3)
|
||||
qr.add_data(uri, optimize=5)
|
||||
qr.print_ascii(tty=True)
|
||||
print("ID=%d" % id)
|
||||
del wpas
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Android logcat to wpa_supplicant integration for DPP QR Code operations')
|
||||
parser.add_argument('-d', const=logging.DEBUG, default=logging.INFO,
|
||||
action='store_const', dest='loglevel',
|
||||
help='verbose debug output')
|
||||
parser.add_argument('--curve', '-c',
|
||||
help='set a specific curve (P-256, P-384, P-521, BP-256R1, BP-384R1, BP-512R1) for key generation')
|
||||
parser.add_argument('command', choices=['logcat',
|
||||
'display'],
|
||||
nargs='?')
|
||||
args = parser.parse_args()
|
||||
|
||||
logging.basicConfig(level=args.loglevel)
|
||||
|
||||
if args.command == "logcat":
|
||||
dpp_logcat()
|
||||
elif args.command == "display":
|
||||
dpp_display(args.curve)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
13
wpa_supplicant/examples/ieee8021x.conf
Normal file
13
wpa_supplicant/examples/ieee8021x.conf
Normal file
@ -0,0 +1,13 @@
|
||||
# IEEE 802.1X with dynamic WEP keys using EAP-PEAP/MSCHAPv2
|
||||
|
||||
ctrl_interface=/var/run/wpa_supplicant
|
||||
|
||||
network={
|
||||
ssid="example 802.1x network"
|
||||
key_mgmt=IEEE8021X
|
||||
eap=PEAP
|
||||
phase2="auth=MSCHAPV2"
|
||||
identity="user name"
|
||||
password="password"
|
||||
ca_cert="/etc/cert/ca.pem"
|
||||
}
|
41
wpa_supplicant/examples/openCryptoki.conf
Normal file
41
wpa_supplicant/examples/openCryptoki.conf
Normal file
@ -0,0 +1,41 @@
|
||||
# EAP-TLS using private key and certificates via OpenSSL PKCS#11 engine and
|
||||
# openCryptoki (e.g., with TPM token)
|
||||
|
||||
# This example uses following PKCS#11 objects:
|
||||
# $ pkcs11-tool --module /usr/lib/opencryptoki/libopencryptoki.so -O -l
|
||||
# Please enter User PIN:
|
||||
# Private Key Object; RSA
|
||||
# label: rsakey
|
||||
# ID: 04
|
||||
# Usage: decrypt, sign, unwrap
|
||||
# Certificate Object, type = X.509 cert
|
||||
# label: ca
|
||||
# ID: 01
|
||||
# Certificate Object, type = X.509 cert
|
||||
# label: cert
|
||||
# ID: 04
|
||||
|
||||
# Configure OpenSSL to load the PKCS#11 engine and openCryptoki module
|
||||
pkcs11_engine_path=/usr/lib/engines/engine_pkcs11.so
|
||||
pkcs11_module_path=/usr/lib/opencryptoki/libopencryptoki.so
|
||||
|
||||
network={
|
||||
ssid="test network"
|
||||
key_mgmt=WPA-EAP
|
||||
eap=TLS
|
||||
identity="User"
|
||||
|
||||
# use OpenSSL PKCS#11 engine for this network
|
||||
engine=1
|
||||
engine_id="pkcs11"
|
||||
|
||||
# select the private key and certificates based on ID (see pkcs11-tool
|
||||
# output above)
|
||||
key_id="4"
|
||||
cert_id="4"
|
||||
ca_cert_id="1"
|
||||
|
||||
# set the PIN code; leave this out to configure the PIN to be requested
|
||||
# interactively when needed (e.g., via wpa_gui or wpa_cli)
|
||||
pin="123456"
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user