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 
13 namespace wpa_supplicant_binder {
14 
15 Supplicant::Supplicant(struct wpa_global *global) : wpa_global_(global) {}
16 
17 android::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 
84 android::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 
102 android::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