00001
00017 #include <stdlib.h>
00018 #include <stdio.h>
00019 #include <unistd.h>
00020 #include <string.h>
00021 #include <sys/ioctl.h>
00022 #include <errno.h>
00023
00024 #include "wireless_copy.h"
00025 #include "common.h"
00026 #include "driver.h"
00027 #include "driver_wext.h"
00028 #include "driver_hostap.h"
00029 #include "l2_packet.h"
00030 #include "wpa_supplicant.h"
00031
00032 struct wpa_driver_prism54_data {
00033 void *wext;
00034 void *ctx;
00035 char ifname[IFNAMSIZ + 1];
00036 int sock;
00037 };
00038
00039 #define PRISM54_SET_WPA SIOCIWFIRSTPRIV+12
00040 #define PRISM54_HOSTAPD SIOCIWFIRSTPRIV+25
00041 #define PRISM54_DROP_UNENCRYPTED SIOCIWFIRSTPRIV+26
00042
00043 static void show_set_key_error(struct prism2_hostapd_param *);
00044
00045 static int hostapd_ioctl_prism54(struct wpa_driver_prism54_data *drv,
00046 struct prism2_hostapd_param *param,
00047 int len, int show_err)
00048 {
00049 struct iwreq iwr;
00050
00051 memset(&iwr, 0, sizeof(iwr));
00052 strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
00053 iwr.u.data.pointer = (caddr_t) param;
00054 iwr.u.data.length = len;
00055
00056 if (ioctl(drv->sock, PRISM54_HOSTAPD, &iwr) < 0) {
00057 int ret = errno;
00058 if (show_err)
00059 perror("ioctl[PRISM54_HOSTAPD]");
00060 return ret;
00061 }
00062
00063 return 0;
00064 }
00065
00066
00067 static int wpa_driver_prism54_set_wpa_ie(struct wpa_driver_prism54_data *drv,
00068 const u8 *wpa_ie,
00069 size_t wpa_ie_len)
00070 {
00071 struct prism2_hostapd_param *param;
00072 int res;
00073 size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + wpa_ie_len;
00074 if (blen < sizeof(*param))
00075 blen = sizeof(*param);
00076
00077 param = (struct prism2_hostapd_param *) malloc(blen);
00078 if (param == NULL)
00079 return -1;
00080
00081 memset(param, 0, blen);
00082 param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT;
00083 param->u.generic_elem.len = wpa_ie_len;
00084 memcpy(param->u.generic_elem.data, wpa_ie, wpa_ie_len);
00085 res = hostapd_ioctl_prism54(drv, param, blen, 1);
00086
00087 free(param);
00088
00089 return res;
00090 }
00091
00092
00093
00094 static int wpa_driver_prism54_set_wpa(void *priv, int enabled)
00095 {
00096 struct wpa_driver_prism54_data *drv = priv;
00097 struct prism2_hostapd_param *param;
00098 int res;
00099 size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN;
00100 if (blen < sizeof(*param))
00101 blen = sizeof(*param);
00102
00103 param = (struct prism2_hostapd_param *) malloc(blen);
00104 if (param == NULL)
00105 return -1;
00106
00107 memset(param, 0, blen);
00108 param->cmd = PRISM54_SET_WPA;
00109 param->u.generic_elem.len = 0;
00110 res = hostapd_ioctl_prism54(drv, param, blen, 1);
00111
00112 free(param);
00113
00114 return res;
00115 }
00116
00117
00118 static int wpa_driver_prism54_set_key(void *priv, wpa_alg alg,
00119 const u8 *addr, int key_idx, int set_tx,
00120 const u8 *seq, size_t seq_len,
00121 const u8 *key, size_t key_len)
00122 {
00123 struct wpa_driver_prism54_data *drv = priv;
00124 struct prism2_hostapd_param *param;
00125 u8 *buf;
00126 size_t blen;
00127 int ret = 0;
00128 char *alg_name;
00129
00130 switch (alg) {
00131 case WPA_ALG_NONE:
00132 alg_name = "none";
00133 return -1;
00134 break;
00135 case WPA_ALG_WEP:
00136 alg_name = "WEP";
00137 return -1;
00138 break;
00139 case WPA_ALG_TKIP:
00140 alg_name = "TKIP";
00141 break;
00142 case WPA_ALG_CCMP:
00143 alg_name = "CCMP";
00144 return -1;
00145 break;
00146 default:
00147 return -1;
00148 }
00149
00150 wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu "
00151 "key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx,
00152 (unsigned long) seq_len, (unsigned long) key_len);
00153
00154 if (seq_len > 8)
00155 return -2;
00156
00157 blen = sizeof(*param) + key_len;
00158 buf = malloc(blen);
00159 if (buf == NULL)
00160 return -1;
00161 memset(buf, 0, blen);
00162
00163 param = (struct prism2_hostapd_param *) buf;
00164 param->cmd = PRISM2_SET_ENCRYPTION;
00165
00166
00167
00168
00169
00170
00171
00172 #if 0
00173 if (addr == NULL)
00174 memset(param->sta_addr, 0xff, ETH_ALEN);
00175 else
00176 memcpy(param->sta_addr, addr, ETH_ALEN);
00177 #else
00178 memset(param->sta_addr, 0xff, ETH_ALEN);
00179 #endif
00180 strncpy((char *) param->u.crypt.alg, alg_name,
00181 HOSTAP_CRYPT_ALG_NAME_LEN);
00182 param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
00183 param->u.crypt.idx = key_idx;
00184 memcpy(param->u.crypt.seq, seq, seq_len);
00185 param->u.crypt.key_len = key_len;
00186 memcpy((u8 *) (param + 1), key, key_len);
00187
00188 if (hostapd_ioctl_prism54(drv, param, blen, 1)) {
00189 wpa_printf(MSG_WARNING, "Failed to set encryption.");
00190 show_set_key_error(param);
00191 ret = -1;
00192 }
00193 free(buf);
00194
00195 return ret;
00196 }
00197
00198
00199 static int wpa_driver_prism54_set_countermeasures(void *priv,
00200 int enabled)
00201 {
00202
00203 printf("wpa_driver_prism54_set_countermeasures - not yet "
00204 "implemented\n");
00205 return 0;
00206 }
00207
00208
00209 static int wpa_driver_prism54_set_drop_unencrypted(void *priv,
00210 int enabled)
00211 {
00212 struct wpa_driver_prism54_data *drv = priv;
00213 struct prism2_hostapd_param *param;
00214 int res;
00215 size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN;
00216 if (blen < sizeof(*param))
00217 blen = sizeof(*param);
00218
00219 param = (struct prism2_hostapd_param *) malloc(blen);
00220 if (param == NULL)
00221 return -1;
00222
00223 memset(param, 0, blen);
00224 param->cmd = PRISM54_DROP_UNENCRYPTED;
00225 param->u.generic_elem.len = 0;
00226 res = hostapd_ioctl_prism54(drv, param, blen, 1);
00227
00228 free(param);
00229
00230 return res;
00231 }
00232
00233
00234 static int wpa_driver_prism54_deauthenticate(void *priv, const u8 *addr,
00235 int reason_code)
00236 {
00237
00238 printf("wpa_driver_prism54_deauthenticate - not yet implemented\n");
00239 return 0;
00240 }
00241
00242
00243 static int wpa_driver_prism54_disassociate(void *priv, const u8 *addr,
00244 int reason_code)
00245 {
00246
00247 printf("wpa_driver_prism54_disassociate - not yet implemented\n");
00248 return 0;
00249 }
00250
00251
00252 static int
00253 wpa_driver_prism54_associate(void *priv,
00254 struct wpa_driver_associate_params *params)
00255 {
00256 struct wpa_driver_prism54_data *drv = priv;
00257 int ret = 0;
00258
00259 if (wpa_driver_prism54_set_wpa_ie(drv, params->wpa_ie,
00260 params->wpa_ie_len) < 0)
00261 ret = -1;
00262 if (wpa_driver_wext_set_freq(drv->wext, params->freq) < 0)
00263 ret = -1;
00264 if (wpa_driver_wext_set_ssid(drv->wext, params->ssid,
00265 params->ssid_len) < 0)
00266 ret = -1;
00267 if (wpa_driver_wext_set_bssid(drv->wext, params->bssid) < 0)
00268 ret = -1;
00269
00270 return ret;
00271 }
00272
00273 static void show_set_key_error(struct prism2_hostapd_param *param)
00274 {
00275 switch (param->u.crypt.err) {
00276 case HOSTAP_CRYPT_ERR_UNKNOWN_ALG:
00277 wpa_printf(MSG_INFO, "Unknown algorithm '%s'.",
00278 param->u.crypt.alg);
00279 wpa_printf(MSG_INFO, "You may need to load kernel module to "
00280 "register that algorithm.");
00281 wpa_printf(MSG_INFO, "E.g., 'modprobe hostap_crypt_wep' for "
00282 "WEP.");
00283 break;
00284 case HOSTAP_CRYPT_ERR_UNKNOWN_ADDR:
00285 wpa_printf(MSG_INFO, "Unknown address " MACSTR ".",
00286 MAC2STR(param->sta_addr));
00287 break;
00288 case HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED:
00289 wpa_printf(MSG_INFO, "Crypt algorithm initialization failed.");
00290 break;
00291 case HOSTAP_CRYPT_ERR_KEY_SET_FAILED:
00292 wpa_printf(MSG_INFO, "Key setting failed.");
00293 break;
00294 case HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED:
00295 wpa_printf(MSG_INFO, "TX key index setting failed.");
00296 break;
00297 case HOSTAP_CRYPT_ERR_CARD_CONF_FAILED:
00298 wpa_printf(MSG_INFO, "Card configuration failed.");
00299 break;
00300 }
00301 }
00302
00303
00304 static int wpa_driver_prism54_get_bssid(void *priv, u8 *bssid)
00305 {
00306 struct wpa_driver_prism54_data *drv = priv;
00307 return wpa_driver_wext_get_bssid(drv->wext, bssid);
00308 }
00309
00310
00311 static int wpa_driver_prism54_get_ssid(void *priv, u8 *ssid)
00312 {
00313 struct wpa_driver_prism54_data *drv = priv;
00314 return wpa_driver_wext_get_ssid(drv->wext, ssid);
00315 }
00316
00317
00318 static int wpa_driver_prism54_scan(void *priv, const u8 *ssid, size_t ssid_len)
00319 {
00320 struct wpa_driver_prism54_data *drv = priv;
00321 return wpa_driver_wext_scan(drv->wext, ssid, ssid_len);
00322 }
00323
00324
00325 static int wpa_driver_prism54_get_scan_results(void *priv,
00326 struct wpa_scan_result *results,
00327 size_t max_size)
00328 {
00329 struct wpa_driver_prism54_data *drv = priv;
00330 return wpa_driver_wext_get_scan_results(drv->wext, results, max_size);
00331 }
00332
00333
00334 static void * wpa_driver_prism54_init(void *ctx, const char *ifname)
00335 {
00336 struct wpa_driver_prism54_data *drv;
00337
00338 drv = malloc(sizeof(*drv));
00339 if (drv == NULL)
00340 return NULL;
00341 memset(drv, 0, sizeof(*drv));
00342 drv->wext = wpa_driver_wext_init(ctx, ifname);
00343 if (drv->wext == NULL) {
00344 free(drv);
00345 return NULL;
00346 }
00347
00348 drv->ctx = ctx;
00349 strncpy(drv->ifname, ifname, sizeof(drv->ifname));
00350 drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
00351 if (drv->sock < 0) {
00352 wpa_driver_wext_deinit(drv->wext);
00353 free(drv);
00354 return NULL;
00355 }
00356
00357 return drv;
00358 }
00359
00360
00361 static void wpa_driver_prism54_deinit(void *priv)
00362 {
00363 struct wpa_driver_prism54_data *drv = priv;
00364 wpa_driver_wext_deinit(drv->wext);
00365 close(drv->sock);
00366 free(drv);
00367 }
00368
00369
00370 const struct wpa_driver_ops wpa_driver_prism54_ops = {
00371 .name = "prism54",
00372 .desc = "Prism54.org driver (Intersil Prism GT/Duette/Indigo)",
00373 .get_bssid = wpa_driver_prism54_get_bssid,
00374 .get_ssid = wpa_driver_prism54_get_ssid,
00375 .set_wpa = wpa_driver_prism54_set_wpa,
00376 .set_key = wpa_driver_prism54_set_key,
00377 .set_countermeasures = wpa_driver_prism54_set_countermeasures,
00378 .set_drop_unencrypted = wpa_driver_prism54_set_drop_unencrypted,
00379 .scan = wpa_driver_prism54_scan,
00380 .get_scan_results = wpa_driver_prism54_get_scan_results,
00381 .deauthenticate = wpa_driver_prism54_deauthenticate,
00382 .disassociate = wpa_driver_prism54_disassociate,
00383 .associate = wpa_driver_prism54_associate,
00384 .init = wpa_driver_prism54_init,
00385 .deinit = wpa_driver_prism54_deinit,
00386 };
00387