aboutsummaryrefslogtreecommitdiffstats
path: root/wpa_supplicant/binder/supplicant.cpp
blob: 76569b1471fbb27872c75ec5638de93580db7de1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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 &params,
    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 */