blob: cd4be061ec97e16fb182dd532a644aaad352b0bf [file] [log] [blame]
Dmitry Shmidte4663042016-04-04 10:07:49 -07001/*
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
Roshan Piusd3854452016-07-07 16:46:41 -070010#include "binder_manager.h"
Dmitry Shmidte4663042016-04-04 10:07:49 -070011#include "iface.h"
12
13namespace wpa_supplicant_binder {
14
Roshan Pius8702ba92016-07-25 15:29:39 -070015#define RETURN_IF_IFACE_INVALID(wpa_s) \
16 { \
17 if (!wpa_s) { \
18 return android::binder::Status:: \
19 fromServiceSpecificError( \
20 ERROR_IFACE_INVALID, "wpa_supplicant does " \
21 "not control this " \
22 "interface."); \
23 } \
24 } // #define RETURN_IF_IFACE_INVALID(wpa_s)
25
Roshan Pius54e763a2016-07-06 15:41:53 -070026Iface::Iface(struct wpa_global *wpa_global, const char ifname[])
27 : wpa_global_(wpa_global), ifname_(ifname)
28{
29}
Dmitry Shmidte4663042016-04-04 10:07:49 -070030
Roshan Pius54e763a2016-07-06 15:41:53 -070031android::binder::Status Iface::GetName(std::string *iface_name_out)
32{
33 // We could directly return the name we hold, but let's verify
34 // if the underlying iface still exists.
Roshan Pius8702ba92016-07-25 15:29:39 -070035 RETURN_IF_IFACE_INVALID(retrieveIfacePtr());
Roshan Pius54e763a2016-07-06 15:41:53 -070036 *iface_name_out = ifname_;
37 return android::binder::Status::ok();
38}
39
Roshan Piusd6e37512016-07-07 13:20:46 -070040android::binder::Status Iface::AddNetwork(
41 android::sp<fi::w1::wpa_supplicant::INetwork> *network_object_out)
42{
Roshan Piusd3854452016-07-07 16:46:41 -070043 struct wpa_supplicant *wpa_s = retrieveIfacePtr();
Roshan Pius8702ba92016-07-25 15:29:39 -070044 RETURN_IF_IFACE_INVALID(wpa_s);
Roshan Piusd3854452016-07-07 16:46:41 -070045
Roshan Piusf745df82016-07-14 16:00:23 -070046 struct wpa_ssid *ssid = wpa_supplicant_add_network(wpa_s);
Roshan Piusd3854452016-07-07 16:46:41 -070047 if (!ssid) {
48 return android::binder::Status::fromServiceSpecificError(
49 ERROR_GENERIC, "wpa_supplicant couldn't add this network.");
50 }
51
Roshan Piusd3854452016-07-07 16:46:41 -070052 BinderManager *binder_manager = BinderManager::getInstance();
53 if (!binder_manager ||
54 binder_manager->getNetworkBinderObjectByIfnameAndNetworkId(
55 wpa_s->ifname, ssid->id, network_object_out)) {
56 return android::binder::Status::fromServiceSpecificError(
57 ERROR_GENERIC,
58 "wpa_supplicant encountered a binder error.");
59 }
Roshan Piusd6e37512016-07-07 13:20:46 -070060 return android::binder::Status::ok();
61}
62
63android::binder::Status Iface::RemoveNetwork(int network_id)
64{
Roshan Piusd3854452016-07-07 16:46:41 -070065 struct wpa_supplicant *wpa_s = retrieveIfacePtr();
Roshan Pius8702ba92016-07-25 15:29:39 -070066 RETURN_IF_IFACE_INVALID(wpa_s);
Roshan Piusd3854452016-07-07 16:46:41 -070067
Roshan Piusf745df82016-07-14 16:00:23 -070068 int result = wpa_supplicant_remove_network(wpa_s, network_id);
69 if (result == -1) {
Roshan Piusd3854452016-07-07 16:46:41 -070070 return android::binder::Status::fromServiceSpecificError(
71 ERROR_NETWORK_UNKNOWN,
72 "wpa_supplicant does not control this network.");
73 }
Roshan Piusf745df82016-07-14 16:00:23 -070074
75 if (result == -2) {
Roshan Piusd3854452016-07-07 16:46:41 -070076 return android::binder::Status::fromServiceSpecificError(
77 ERROR_GENERIC,
78 "wpa_supplicant couldn't remove this network.");
79 }
80 return android::binder::Status::ok();
81}
82
83android::binder::Status Iface::GetNetwork(
84 int network_id,
85 android::sp<fi::w1::wpa_supplicant::INetwork> *network_object_out)
86{
87 struct wpa_supplicant *wpa_s = retrieveIfacePtr();
Roshan Pius8702ba92016-07-25 15:29:39 -070088 RETURN_IF_IFACE_INVALID(wpa_s);
Roshan Piusd3854452016-07-07 16:46:41 -070089
90 struct wpa_ssid *ssid = wpa_config_get_network(wpa_s->conf, network_id);
91 if (!ssid) {
92 return android::binder::Status::fromServiceSpecificError(
93 ERROR_NETWORK_UNKNOWN,
94 "wpa_supplicant does not control this network.");
95 }
96
97 BinderManager *binder_manager = BinderManager::getInstance();
98 if (!binder_manager ||
99 binder_manager->getNetworkBinderObjectByIfnameAndNetworkId(
100 wpa_s->ifname, ssid->id, network_object_out)) {
101 return android::binder::Status::fromServiceSpecificError(
102 ERROR_GENERIC,
103 "wpa_supplicant encountered a binder error.");
104 }
Roshan Piusd6e37512016-07-07 13:20:46 -0700105 return android::binder::Status::ok();
106}
107
Roshan Pius0470cc82016-07-14 16:37:07 -0700108android::binder::Status Iface::RegisterCallback(
109 const android::sp<fi::w1::wpa_supplicant::IIfaceCallback> &callback)
110{
111 struct wpa_supplicant *wpa_s = retrieveIfacePtr();
Roshan Pius8702ba92016-07-25 15:29:39 -0700112 RETURN_IF_IFACE_INVALID(wpa_s);
113
Roshan Pius0470cc82016-07-14 16:37:07 -0700114 BinderManager *binder_manager = BinderManager::getInstance();
115 if (!binder_manager ||
116 binder_manager->addIfaceCallbackBinderObject(ifname_, callback)) {
117 return android::binder::Status::fromServiceSpecificError(
118 ERROR_GENERIC,
119 "wpa_supplicant encountered a binder error.");
120 }
121 return android::binder::Status::ok();
122}
123
Roshan Piusf4e46cf2016-08-09 15:42:42 -0700124android::binder::Status Iface::Reassociate()
125{
126 struct wpa_supplicant *wpa_s = retrieveIfacePtr();
127 RETURN_IF_IFACE_INVALID(wpa_s);
128
129 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
130 return android::binder::Status::fromServiceSpecificError(
131 ERROR_IFACE_DISABLED);
132 }
133 wpas_request_connection(wpa_s);
134 return android::binder::Status::ok();
135}
136
137android::binder::Status Iface::Reconnect()
138{
139 struct wpa_supplicant *wpa_s = retrieveIfacePtr();
140 RETURN_IF_IFACE_INVALID(wpa_s);
141
142 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
143 return android::binder::Status::fromServiceSpecificError(
144 ERROR_IFACE_DISABLED);
145 }
146 if (!wpa_s->disconnected) {
147 return android::binder::Status::fromServiceSpecificError(
148 ERROR_IFACE_NOT_DISCONNECTED);
149 }
150 wpas_request_connection(wpa_s);
151 return android::binder::Status::ok();
152}
153
154android::binder::Status Iface::Disconnect()
155{
156 struct wpa_supplicant *wpa_s = retrieveIfacePtr();
157 RETURN_IF_IFACE_INVALID(wpa_s);
158
159 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
160 return android::binder::Status::fromServiceSpecificError(
161 ERROR_IFACE_DISABLED);
162 }
163 wpas_request_disconnection(wpa_s);
164 return android::binder::Status::ok();
165}
166
Roshan Pius54e763a2016-07-06 15:41:53 -0700167/**
168 * Retrieve the underlying |wpa_supplicant| struct pointer for
169 * this iface.
170 * If the underlying iface is removed, then all RPC method calls
171 * on this object will return failure.
172 */
173wpa_supplicant *Iface::retrieveIfacePtr()
174{
175 return wpa_supplicant_get_iface(
176 (struct wpa_global *)wpa_global_, ifname_.c_str());
177}
Roshan Pius54e763a2016-07-06 15:41:53 -0700178} // namespace wpa_supplicant_binder