driver_prism54.c

Go to the documentation of this file.
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; /* private data for driver_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 /* This is called at wpa_supplicant daemon init time */
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         /* TODO: In theory, STA in client mode can use five keys; four default
00166          * keys for receiving (with keyidx 0..3) and one individual key for
00167          * both transmitting and receiving (keyidx 0) _unicast_ packets. Now,
00168          * keyidx 0 is reserved for this unicast use and default keys can only
00169          * use keyidx 1..3 (i.e., default key with keyidx 0 is not supported).
00170          * This should be fine for more or less all cases, but for completeness
00171          * sake, the driver could be enhanced to support the missing key. */
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         /* FIX */
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         /* FIX */
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         /* FIX */
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 

Generated on Sat May 6 21:13:33 2006 for wpa_supplicant by  doxygen 1.4.2