OSDN Git Service

resolved conflicts for merge of 64b816ba to master
[android-x86/system-netd.git] / server / SoftapController.cpp
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdlib.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <string.h>
21
22 #include <sys/socket.h>
23 #include <sys/stat.h>
24 #include <sys/ioctl.h>
25 #include <sys/types.h>
26 #include <sys/wait.h>
27
28 #include <netinet/in.h>
29 #include <arpa/inet.h>
30
31 #include <linux/wireless.h>
32
33 #include <openssl/evp.h>
34 #include <openssl/sha.h>
35
36 #define LOG_TAG "SoftapController"
37 #include <cutils/log.h>
38 #include <netutils/ifc.h>
39 #include <private/android_filesystem_config.h>
40 #include <utils/file.h>
41 #include <utils/stringprintf.h>
42 #include "wifi.h"
43 #include "ResponseCode.h"
44
45 #include "SoftapController.h"
46
47 static const char HOSTAPD_CONF_FILE[]    = "/data/misc/wifi/hostapd.conf";
48 static const char HOSTAPD_BIN_FILE[]    = "/system/bin/hostapd";
49
50 SoftapController::SoftapController()
51     : mPid(0) {}
52
53 SoftapController::~SoftapController() {
54 }
55
56 int SoftapController::startSoftap() {
57     pid_t pid = 1;
58
59     if (mPid) {
60         ALOGE("SoftAP is already running");
61         return ResponseCode::SoftapStatusResult;
62     }
63
64     if (ensure_entropy_file_exists() < 0) {
65         ALOGE("Wi-Fi entropy file was not created");
66     }
67
68     if ((pid = fork()) < 0) {
69         ALOGE("fork failed (%s)", strerror(errno));
70         return ResponseCode::ServiceStartFailed;
71     }
72
73     if (!pid) {
74         ensure_entropy_file_exists();
75         if (execl(HOSTAPD_BIN_FILE, HOSTAPD_BIN_FILE,
76                   "-e", WIFI_ENTROPY_FILE,
77                   HOSTAPD_CONF_FILE, (char *) NULL)) {
78             ALOGE("execl failed (%s)", strerror(errno));
79         }
80         ALOGE("SoftAP failed to start");
81         return ResponseCode::ServiceStartFailed;
82     } else {
83         mPid = pid;
84         ALOGD("SoftAP started successfully");
85         usleep(AP_BSS_START_DELAY);
86     }
87     return ResponseCode::SoftapStatusResult;
88 }
89
90 int SoftapController::stopSoftap() {
91
92     if (mPid == 0) {
93         ALOGE("SoftAP is not running");
94         return ResponseCode::SoftapStatusResult;
95     }
96
97     ALOGD("Stopping the SoftAP service...");
98     kill(mPid, SIGTERM);
99     waitpid(mPid, NULL, 0);
100
101     mPid = 0;
102     ALOGD("SoftAP stopped successfully");
103     usleep(AP_BSS_STOP_DELAY);
104     return ResponseCode::SoftapStatusResult;
105 }
106
107 bool SoftapController::isSoftapStarted() {
108     return (mPid != 0);
109 }
110
111 /*
112  * Arguments:
113  *  argv[2] - wlan interface
114  *  argv[3] - SSID
115  *  argv[4] - Broadcast/Hidden
116  *  argv[5] - Channel
117  *  argv[6] - Security
118  *  argv[7] - Key
119  */
120 int SoftapController::setSoftap(int argc, char *argv[]) {
121     int hidden = 0;
122     int channel = AP_CHANNEL_DEFAULT;
123
124     if (argc < 5) {
125         ALOGE("Softap set is missing arguments. Please use:");
126         ALOGE("softap <wlan iface> <SSID> <hidden/broadcast> <channel> <wpa2?-psk|open> <passphrase>");
127         return ResponseCode::CommandSyntaxError;
128     }
129
130     if (!strcasecmp(argv[4], "hidden"))
131         hidden = 1;
132
133     if (argc >= 5) {
134         channel = atoi(argv[5]);
135         if (channel <= 0)
136             channel = AP_CHANNEL_DEFAULT;
137     }
138
139     std::string wbuf(android::StringPrintf("interface=%s\n"
140             "driver=nl80211\n"
141             "ctrl_interface=/data/misc/wifi/hostapd\n"
142             "ssid=%s\n"
143             "channel=%d\n"
144             "ieee80211n=1\n"
145             "hw_mode=%c\n"
146             "ignore_broadcast_ssid=%d\n"
147             "wowlan_triggers=any\n",
148             argv[2], argv[3], channel, (channel <= 14) ? 'g' : 'a', hidden));
149
150     std::string fbuf;
151     if (argc > 7) {
152         char psk_str[2*SHA256_DIGEST_LENGTH+1];
153         if (!strcmp(argv[6], "wpa-psk")) {
154             generatePsk(argv[3], argv[7], psk_str);
155             fbuf = android::StringPrintf("%swpa=3\nwpa_pairwise=TKIP CCMP\nwpa_psk=%s\n", wbuf.c_str(), psk_str);
156         } else if (!strcmp(argv[6], "wpa2-psk")) {
157             generatePsk(argv[3], argv[7], psk_str);
158             fbuf = android::StringPrintf("%swpa=2\nrsn_pairwise=CCMP\nwpa_psk=%s\n", wbuf.c_str(), psk_str);
159         } else if (!strcmp(argv[6], "open")) {
160             fbuf = wbuf;
161         }
162     } else if (argc > 6) {
163         if (!strcmp(argv[6], "open")) {
164             fbuf = wbuf;
165         }
166     } else {
167         fbuf = wbuf;
168     }
169
170     if (!android::WriteStringToFile(fbuf, HOSTAPD_CONF_FILE, 0660, AID_SYSTEM, AID_WIFI)) {
171         ALOGE("Cannot write to \"%s\": %s", HOSTAPD_CONF_FILE, strerror(errno));
172         return ResponseCode::OperationFailed;
173     }
174     return ResponseCode::SoftapStatusResult;
175 }
176
177 /*
178  * Arguments:
179  *      argv[2] - interface name
180  *      argv[3] - AP or P2P or STA
181  */
182 int SoftapController::fwReloadSoftap(int argc, char *argv[])
183 {
184     char *fwpath = NULL;
185
186     if (argc < 4) {
187         ALOGE("SoftAP fwreload is missing arguments. Please use: softap <wlan iface> <AP|P2P|STA>");
188         return ResponseCode::CommandSyntaxError;
189     }
190
191     if (strcmp(argv[3], "AP") == 0) {
192         fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_AP);
193     } else if (strcmp(argv[3], "P2P") == 0) {
194         fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_P2P);
195     } else if (strcmp(argv[3], "STA") == 0) {
196         fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_STA);
197     }
198     if (!fwpath)
199         return ResponseCode::CommandParameterError;
200     if (wifi_change_fw_path((const char *)fwpath)) {
201         ALOGE("Softap fwReload failed");
202         return ResponseCode::OperationFailed;
203     }
204     else {
205         ALOGD("Softap fwReload - Ok");
206     }
207     return ResponseCode::SoftapStatusResult;
208 }
209
210 void SoftapController::generatePsk(char *ssid, char *passphrase, char *psk_str) {
211     unsigned char psk[SHA256_DIGEST_LENGTH];
212     int j;
213     // Use the PKCS#5 PBKDF2 with 4096 iterations
214     PKCS5_PBKDF2_HMAC_SHA1(passphrase, strlen(passphrase),
215             reinterpret_cast<const unsigned char *>(ssid), strlen(ssid),
216             4096, SHA256_DIGEST_LENGTH, psk);
217     for (j=0; j < SHA256_DIGEST_LENGTH; j++) {
218         sprintf(&psk_str[j*2], "%02x", psk[j]);
219     }
220 }