1/*
2 * binder interface for wpa_supplicant daemon
3 * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
4 * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
5 *
6 * This software may be distributed under the terms of the BSD license.
7 * See README for more details.
8 */
9
10#include "supplicant.h"
11#include "binder_manager.h"
12
13namespace wpa_supplicant_binder {
14
15Supplicant::Supplicant(struct wpa_global *global) : wpa_global_(global) {}
16
17android::binder::Status Supplicant::CreateInterface(
18    const android::os::PersistableBundle &params,
19    android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
20{
21	android::String16 driver, ifname, confname, bridge_ifname;
22
23	/* Check if required Ifname argument is missing */
24	if (!params.getString(android::String16("Ifname"), &ifname))
25		return android::binder::Status::fromServiceSpecificError(
26		    ERROR_INVALID_ARGS,
27		    android::String8("Ifname missing in params."));
28	/* Retrieve the remaining params from the dictionary */
29	params.getString(android::String16("Driver"), &driver);
30	params.getString(android::String16("ConfigFile"), &confname);
31	params.getString(android::String16("BridgeIfname"), &bridge_ifname);
32
33	/*
34	 * Try to get the wpa_supplicant record for this iface, return
35	 * an error if we already control it.
36	 */
37	if (wpa_supplicant_get_iface(
38		wpa_global_, android::String8(ifname).string()) != NULL)
39		return android::binder::Status::fromServiceSpecificError(
40		    ERROR_IFACE_EXISTS,
41		    android::String8("wpa_supplicant already controls this "
42				     "interface."));
43
44	android::binder::Status status;
45	struct wpa_supplicant *wpa_s = NULL;
46	struct wpa_interface iface;
47
48	os_memset(&iface, 0, sizeof(iface));
49	iface.driver = os_strdup(android::String8(driver).string());
50	iface.ifname = os_strdup(android::String8(ifname).string());
51	iface.confname = os_strdup(android::String8(confname).string());
52	iface.bridge_ifname =
53	    os_strdup(android::String8(bridge_ifname).string());
54	/* Otherwise, have wpa_supplicant attach to it. */
55	wpa_s = wpa_supplicant_add_iface(wpa_global_, &iface, NULL);
56	/* The supplicant core creates a corresponding binder object via
57	 * BinderManager when |wpa_supplicant_add_iface| is called. */
58	if (!wpa_s || !wpa_s->binder_object_key) {
59		status = android::binder::Status::fromServiceSpecificError(
60		    ERROR_UNKNOWN,
61		    android::String8(
62			"wpa_supplicant couldn't grab this interface."));
63	} else {
64		BinderManager *binder_manager = BinderManager::getInstance();
65
66		if (!binder_manager ||
67		    binder_manager->getIfaceBinderObjectByKey(
68			wpa_s->binder_object_key, aidl_return))
69			status =
70			    android::binder::Status::fromServiceSpecificError(
71				ERROR_UNKNOWN,
72				android::String8("wpa_supplicant encountered a "
73						 "binder error."));
74		else
75			status = android::binder::Status::ok();
76	}
77	os_free((void *)iface.driver);
78	os_free((void *)iface.ifname);
79	os_free((void *)iface.confname);
80	os_free((void *)iface.bridge_ifname);
81	return status;
82}
83
84android::binder::Status Supplicant::RemoveInterface(const std::string &ifname)
85{
86	struct wpa_supplicant *wpa_s;
87
88	wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str());
89	if (!wpa_s || !wpa_s->binder_object_key)
90		return android::binder::Status::fromServiceSpecificError(
91		    ERROR_IFACE_UNKNOWN,
92		    android::String8("wpa_supplicant does not control this "
93				     "interface."));
94	if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0))
95		return android::binder::Status::fromServiceSpecificError(
96		    ERROR_UNKNOWN,
97		    android::String8(
98			"wpa_supplicant couldn't remove this interface."));
99	return android::binder::Status::ok();
100}
101
102android::binder::Status Supplicant::GetInterface(
103    const std::string &ifname,
104    android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
105{
106	struct wpa_supplicant *wpa_s;
107
108	wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str());
109	if (!wpa_s || !wpa_s->binder_object_key)
110		return android::binder::Status::fromServiceSpecificError(
111		    ERROR_IFACE_UNKNOWN,
112		    android::String8(
113			"wpa_supplicant does not control this interface."));
114
115	BinderManager *binder_manager = BinderManager::getInstance();
116	if (!binder_manager ||
117	    binder_manager->getIfaceBinderObjectByKey(
118		wpa_s->binder_object_key, aidl_return))
119		return android::binder::Status::fromServiceSpecificError(
120		    ERROR_UNKNOWN,
121		    android::String8(
122			"wpa_supplicant encountered a binder error."));
123
124	return android::binder::Status::ok();
125}
126
127} /* namespace wpa_supplicant_binder */
128