Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
Portions of this file are based on the WEP enablement code provided by the Host AP project hostap-drivers v0.1.3 Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen <j@w1.fi> Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
Contact Information: Intel Linux Wireless <ilw@linux.intel.com> Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
/* Add basic and extended rates */ /* Rate : stuffing multiple values in a single event require a bit
* more of magic - Jean II */
current_val = start + iwe_stream_lcp_len(info);
iwe.cmd = SIOCGIWRATE; /* Those two flags are ignored... */
iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
for (i = 0, j = 0; i < network->rates_len;) { if (j < network->rates_ex_len &&
((network->rates_ex[j] & 0x7F) <
(network->rates[i] & 0x7F)))
rate = network->rates_ex[j++] & 0x7F; else
rate = network->rates[i++] & 0x7F; /* Bit rate given in 500 kb/s units (+ 0x80) */
iwe.u.bitrate.value = ((rate & 0x7f) * 500000); /* Add new value to event */
current_val = iwe_stream_add_value(info, start, current_val,
stop, &iwe, IW_EV_PARAM_LEN);
} for (; j < network->rates_ex_len; j++) {
rate = network->rates_ex[j] & 0x7F; /* Bit rate given in 500 kb/s units (+ 0x80) */
iwe.u.bitrate.value = ((rate & 0x7f) * 500000); /* Add new value to event */
current_val = iwe_stream_add_value(info, start, current_val,
stop, &iwe, IW_EV_PARAM_LEN);
} /* Check if we added any rate */ if ((current_val - start) > iwe_stream_lcp_len(info))
start = current_val;
/* Add EXTRA: Age to display seconds since last beacon/probe response
* for given network. */
iwe.cmd = IWEVCUSTOM;
p = custom;
p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom), " Last beacon: %ums ago",
elapsed_jiffies_msecs(network->last_scanned));
iwe.u.data.length = p - custom; if (iwe.u.data.length)
start = iwe_stream_add_point(info, start, stop, &iwe, custom);
/* Add spectrum management information */
iwe.cmd = -1;
p = custom;
p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom), " Channel flags: ");
if (libipw_get_channel_flags(ieee, network->channel) &
LIBIPW_CH_INVALID) {
iwe.cmd = IWEVCUSTOM;
p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom), "INVALID ");
}
if (libipw_get_channel_flags(ieee, network->channel) &
LIBIPW_CH_RADAR_DETECT) {
iwe.cmd = IWEVCUSTOM;
p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom), "DFS ");
}
if (iwe.cmd == IWEVCUSTOM) {
iwe.u.data.length = p - custom;
start = iwe_stream_add_point(info, start, stop, &iwe, custom);
}
return start;
}
#define SCAN_ITEM_SIZE 128
int libipw_wx_get_scan(struct libipw_device *ieee, struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{ struct libipw_network *network; unsignedlong flags; int err = 0;
char *ev = extra; char *stop = ev + wrqu->data.length; int i = 0;
LIBIPW_DEBUG_WX("Getting scan\n");
spin_lock_irqsave(&ieee->lock, flags);
list_for_each_entry(network, &ieee->network_list, list) {
i++; if (stop - ev < SCAN_ITEM_SIZE) {
err = -E2BIG; break;
}
if (ieee->scan_age == 0 ||
time_after(network->last_scanned + ieee->scan_age, jiffies))
ev = libipw_translate_scan(ieee, ev, stop, network,
info); else {
LIBIPW_DEBUG_SCAN("Not showing network '%*pE (%pM)' due to age (%ums).\n",
network->ssid_len, network->ssid,
network->bssid,
elapsed_jiffies_msecs(
network->last_scanned));
}
}
spin_unlock_irqrestore(&ieee->lock, flags);
wrqu->data.length = ev - extra;
wrqu->data.flags = 0;
if (erq->flags & IW_ENCODE_DISABLED) { if (key_provided && *crypt) {
LIBIPW_DEBUG_WX("Disabling encryption on key %d.\n",
key);
libipw_crypt_delayed_deinit(&ieee->crypt_info, crypt);
} else
LIBIPW_DEBUG_WX("Disabling encryption.\n");
/* Check all the keys to see if any are still configured,
* and if no key index was provided, de-init them all */ for (i = 0; i < WEP_KEYS; i++) { if (ieee->crypt_info.crypt[i] != NULL) { if (key_provided) break;
libipw_crypt_delayed_deinit(&ieee->crypt_info,
&ieee->crypt_info.crypt[i]);
}
}
if (*crypt != NULL && (*crypt)->ops != NULL &&
strcmp((*crypt)->ops->name, "WEP") != 0) { /* changing to use WEP; deinit previously used algorithm
* on this key */
libipw_crypt_delayed_deinit(&ieee->crypt_info, crypt);
}
if (*crypt == NULL && host_crypto) { struct libipw_crypt_data *new_crypt;
/* take WEP into use */
new_crypt = kzalloc(sizeof(struct libipw_crypt_data),
GFP_KERNEL); if (new_crypt == NULL) return -ENOMEM;
new_crypt->ops = libipw_get_crypto_ops("WEP"); if (!new_crypt->ops) {
request_module("libipw_crypt_wep");
new_crypt->ops = libipw_get_crypto_ops("WEP");
}
if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
new_crypt->priv = new_crypt->ops->init(key);
if (!new_crypt->ops || !new_crypt->priv) {
kfree(new_crypt);
new_crypt = NULL;
printk(KERN_WARNING "%s: could not initialize WEP: " "load module libipw_crypt_wep\n", dev->name); return -EOPNOTSUPP;
}
*crypt = new_crypt;
}
/* If a new key was provided, set it up */ if (erq->length > 0) {
len = erq->length <= 5 ? 5 : 13;
memcpy(sec.keys[key], keybuf, erq->length); if (len > erq->length)
memset(sec.keys[key] + erq->length, 0,
len - erq->length);
LIBIPW_DEBUG_WX("Setting key %d to '%*pE' (%d:%d bytes)\n",
key, len, sec.keys[key],
erq->length, len);
sec.key_sizes[key] = len; if (*crypt)
(*crypt)->ops->set_key(sec.keys[key], len, NULL,
(*crypt)->priv);
sec.flags |= (1 << key); /* This ensures a key will be activated if no key is
* explicitly set */ if (key == sec.active_key)
sec.flags |= SEC_ACTIVE_KEY;
} else { if (host_crypto) {
len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
NULL, (*crypt)->priv); if (len == 0) { /* Set a default key of all 0 */
LIBIPW_DEBUG_WX("Setting key %d to all " "zero.\n", key);
memset(sec.keys[key], 0, 13);
(*crypt)->ops->set_key(sec.keys[key], 13, NULL,
(*crypt)->priv);
sec.key_sizes[key] = 13;
sec.flags |= (1 << key);
}
} /* No key data - just set the default TX key index */ if (key_provided) {
LIBIPW_DEBUG_WX("Setting key %d to default Tx " "key.\n", key);
ieee->crypt_info.tx_keyidx = key;
sec.active_key = key;
sec.flags |= SEC_ACTIVE_KEY;
}
} if (erq->flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED)) {
ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
WLAN_AUTH_SHARED_KEY;
sec.flags |= SEC_AUTH_MODE;
LIBIPW_DEBUG_WX("Auth: %s\n",
sec.auth_mode == WLAN_AUTH_OPEN ? "OPEN" : "SHARED KEY");
}
/* For now we just support WEP, so only set that security level...
* TODO: When WPA is added this is one place that needs to change */
sec.flags |= SEC_LEVEL;
sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
sec.encode_alg[key] = SEC_ALG_WEP;
done: if (ieee->set_security)
ieee->set_security(dev, &sec);
return 0;
}
int libipw_wx_get_encode(struct libipw_device *ieee, struct iw_request_info *info, union iwreq_data *wrqu, char *keybuf)
{ struct iw_point *erq = &(wrqu->encoding); int len, key; struct libipw_security *sec = &ieee->sec;
LIBIPW_DEBUG_WX("GET_ENCODE\n");
key = erq->flags & IW_ENCODE_INDEX; if (key) { if (key > WEP_KEYS) return -EINVAL;
key--;
} else
key = ieee->crypt_info.tx_keyidx;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.