📄 hostap_ioctl.c
字号:
current_ev = iwe_stream_add_point( current_ev, end_buf, &iwe, bss->wpa_ie); } if (bss && bss->rsn_ie_len > 0 && bss->rsn_ie_len <= MAX_WPA_IE_LEN) { memset(&iwe, 0, sizeof(iwe)); iwe.cmd = IWEVGENIE; iwe.u.data.length = bss->rsn_ie_len; current_ev = iwe_stream_add_point( current_ev, end_buf, &iwe, bss->rsn_ie); } return current_ev;}/* Translate scan data returned from the card to a card independant * format that the Wireless Tools will understand - Jean II */static inline int prism2_translate_scan(local_info_t *local, char *buffer, int buflen){ struct hfa384x_hostscan_result *scan; int entry, hostscan; char *current_ev = buffer; char *end_buf = buffer + buflen; struct list_head *ptr; spin_lock_bh(&local->lock); list_for_each(ptr, &local->bss_list) { struct hostap_bss_info *bss; bss = list_entry(ptr, struct hostap_bss_info, list); bss->included = 0; } hostscan = local->last_scan_type == PRISM2_HOSTSCAN; for (entry = 0; entry < local->last_scan_results_count; entry++) { int found = 0; scan = &local->last_scan_results[entry]; /* Report every SSID if the AP is using multiple SSIDs. If no * BSS record is found (e.g., when WPA mode is disabled), * report the AP once. */ list_for_each(ptr, &local->bss_list) { struct hostap_bss_info *bss; bss = list_entry(ptr, struct hostap_bss_info, list); if (memcmp(bss->bssid, scan->bssid, ETH_ALEN) == 0) { bss->included = 1; current_ev = __prism2_translate_scan( local, scan, bss, current_ev, end_buf); found++; } } if (!found) { current_ev = __prism2_translate_scan( local, scan, NULL, current_ev, end_buf); } /* Check if there is space for one more entry */ if ((end_buf - current_ev) <= IW_EV_ADDR_LEN) { /* Ask user space to try again with a bigger buffer */ spin_unlock_bh(&local->lock); return -E2BIG; } } /* Prism2 firmware has limits (32 at least in some versions) for number * of BSSes in scan results. Extend this limit by using local BSS list. */ list_for_each(ptr, &local->bss_list) { struct hostap_bss_info *bss; bss = list_entry(ptr, struct hostap_bss_info, list); if (bss->included) continue; current_ev = __prism2_translate_scan(local, NULL, bss, current_ev, end_buf); /* Check if there is space for one more entry */ if ((end_buf - current_ev) <= IW_EV_ADDR_LEN) { /* Ask user space to try again with a bigger buffer */ spin_unlock_bh(&local->lock); return -E2BIG; } } spin_unlock_bh(&local->lock); return current_ev - buffer;}#endif /* PRISM2_NO_STATION_MODES */static inline int prism2_ioctl_giwscan_sta(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra){#ifdef PRISM2_NO_STATION_MODES return -EOPNOTSUPP;#else /* PRISM2_NO_STATION_MODES */ struct hostap_interface *iface; local_info_t *local; int res; iface = netdev_priv(dev); local = iface->local; /* Wait until the scan is finished. We can probably do better * than that - Jean II */ if (local->scan_timestamp && time_before(jiffies, local->scan_timestamp + 3 * HZ)) { /* Important note : we don't want to block the caller * until results are ready for various reasons. * First, managing wait queues is complex and racy * (there may be multiple simultaneous callers). * Second, we grab some rtnetlink lock before comming * here (in dev_ioctl()). * Third, the caller can wait on the Wireless Event * - Jean II */ return -EAGAIN; } local->scan_timestamp = 0; res = prism2_translate_scan(local, extra, data->length); if (res >= 0) { data->length = res; return 0; } else { data->length = 0; return res; }#endif /* PRISM2_NO_STATION_MODES */}static int prism2_ioctl_giwscan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra){ struct hostap_interface *iface; local_info_t *local; int res; iface = netdev_priv(dev); local = iface->local; if (local->iw_mode == IW_MODE_MASTER) { /* In MASTER mode, it doesn't make sense to go around * scanning the frequencies and make the stations we serve * wait when what the user is really interested about is the * list of stations and access points we are talking to. * So, just extract results from our cache... * Jean II */ /* Translate to WE format */ res = prism2_ap_translate_scan(dev, extra); if (res >= 0) { printk(KERN_DEBUG "Scan result translation succeeded " "(length=%d)\n", res); data->length = res; return 0; } else { printk(KERN_DEBUG "Scan result translation failed (res=%d)\n", res); data->length = 0; return res; } } else { /* Station mode */ return prism2_ioctl_giwscan_sta(dev, info, data, extra); }}static const struct iw_priv_args prism2_priv[] = { { PRISM2_IOCTL_MONITOR, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "monitor" }, { PRISM2_IOCTL_READMIF, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "readmif" }, { PRISM2_IOCTL_WRITEMIF, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 2, 0, "writemif" }, { PRISM2_IOCTL_RESET, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "reset" }, { PRISM2_IOCTL_INQUIRE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "inquire" }, { PRISM2_IOCTL_SET_RID_WORD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_rid_word" }, { PRISM2_IOCTL_MACCMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "maccmd" }, { PRISM2_IOCTL_WDS_ADD, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "wds_add" }, { PRISM2_IOCTL_WDS_DEL, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "wds_del" }, { PRISM2_IOCTL_ADDMAC, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "addmac" }, { PRISM2_IOCTL_DELMAC, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "delmac" }, { PRISM2_IOCTL_KICKMAC, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "kickmac" }, /* --- raw access to sub-ioctls --- */ { PRISM2_IOCTL_PRISM2_PARAM, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "prism2_param" }, { PRISM2_IOCTL_GET_PRISM2_PARAM, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getprism2_param" }, /* --- sub-ioctls handlers --- */ { PRISM2_IOCTL_PRISM2_PARAM, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "" }, { PRISM2_IOCTL_GET_PRISM2_PARAM, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "" }, /* --- sub-ioctls definitions --- */ { PRISM2_PARAM_TXRATECTRL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "txratectrl" }, { PRISM2_PARAM_TXRATECTRL, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gettxratectrl" }, { PRISM2_PARAM_BEACON_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "beacon_int" }, { PRISM2_PARAM_BEACON_INT, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbeacon_int" },#ifndef PRISM2_NO_STATION_MODES { PRISM2_PARAM_PSEUDO_IBSS, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "pseudo_ibss" }, { PRISM2_PARAM_PSEUDO_IBSS, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getpseudo_ibss" },#endif /* PRISM2_NO_STATION_MODES */ { PRISM2_PARAM_ALC, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "alc" }, { PRISM2_PARAM_ALC, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getalc" }, { PRISM2_PARAM_DUMP, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dump" }, { PRISM2_PARAM_DUMP, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdump" }, { PRISM2_PARAM_OTHER_AP_POLICY, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "other_ap_policy" }, { PRISM2_PARAM_OTHER_AP_POLICY, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getother_ap_pol" }, { PRISM2_PARAM_AP_MAX_INACTIVITY, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "max_inactivity" }, { PRISM2_PARAM_AP_MAX_INACTIVITY, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmax_inactivi" }, { PRISM2_PARAM_AP_BRIDGE_PACKETS, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bridge_packets" }, { PRISM2_PARAM_AP_BRIDGE_PACKETS, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbridge_packe" }, { PRISM2_PARAM_DTIM_PERIOD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dtim_period" }, { PRISM2_PARAM_DTIM_PERIOD, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdtim_period" }, { PRISM2_PARAM_AP_NULLFUNC_ACK, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "nullfunc_ack" }, { PRISM2_PARAM_AP_NULLFUNC_ACK, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getnullfunc_ack" }, { PRISM2_PARAM_MAX_WDS, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "max_wds" }, { PRISM2_PARAM_MAX_WDS, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmax_wds" }, { PRISM2_PARAM_AP_AUTOM_AP_WDS, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "autom_ap_wds" }, { PRISM2_PARAM_AP_AUTOM_AP_WDS, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getautom_ap_wds" }, { PRISM2_PARAM_AP_AUTH_ALGS, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ap_auth_algs" }, { PRISM2_PARAM_AP_AUTH_ALGS, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getap_auth_algs" }, { PRISM2_PARAM_MONITOR_ALLOW_FCSERR, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "allow_fcserr" }, { PRISM2_PARAM_MONITOR_ALLOW_FCSERR, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getallow_fcserr" }, { PRISM2_PARAM_HOST_ENCRYPT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_encrypt" }, { PRISM2_PARAM_HOST_ENCRYPT, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_encrypt" }, { PRISM2_PARAM_HOST_DECRYPT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_decrypt" }, { PRISM2_PARAM_HOST_DECRYPT, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_decrypt" },#ifndef PRISM2_NO_STATION_MODES { PRISM2_PARAM_HOST_ROAMING, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_roaming" }, { PRISM2_PARAM_HOST_ROAMING, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_roaming" },#endif /* PRISM2_NO_STATION_MODES */ { PRISM2_PARAM_BCRX_STA_KEY, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bcrx_sta_key" }, { PRISM2_PARAM_BCRX_STA_KEY, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbcrx_sta_key" }, { PRISM2_PARAM_IEEE_802_1X, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ieee_802_1x" }, { PRISM2_PARAM_IEEE_802_1X, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getieee_802_1x" }, { PRISM2_PARAM_ANTSEL_TX, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "antsel_tx" }, { PRISM2_PARAM_ANTSEL_TX, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getantsel_tx" }, { PRISM2_PARAM_ANTSEL_RX, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "antsel_rx" }, { PRISM2_PARAM_ANTSEL_RX, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getantsel_rx" }, { PRISM2_PARAM_MONITOR_TYPE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "monitor_type" }, { PRISM2_PARAM_MONITOR_TYPE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmonitor_type" }, { PRISM2_PARAM_WDS_TYPE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wds_type" }, { PRISM2_PARAM_WDS_TYPE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getwds_type" }, { PRISM2_PARAM_HOSTSCAN, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hostscan" }, { PRISM2_PARAM_HOSTSCAN, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostscan" }, { PRISM2_PARAM_AP_SCAN, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ap_scan" }, { PRISM2_PARAM_AP_SCAN, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getap_scan" }, { PRISM2_PARAM_ENH_SEC, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "enh_sec" }, { PRISM2_PARAM_ENH_SEC, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getenh_sec" },#ifdef PRISM2_IO_DEBUG { PRISM2_PARAM_IO_DEBUG, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "io_debug" }, { PRISM2_PARAM_IO_DEBUG, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getio_debug" },#endif /* PRISM2_IO_DEBUG */ { PRISM2_PARAM_BASIC_RATES, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "basic_rates" }, { PRISM2_PARAM_BASIC_RATES, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbasic_rates" }, { PRISM2_PARAM_OPER_RATES, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "oper_rates" }, { PRISM2_PARAM_OPER_RATES, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getoper_rates" }, { PRISM2_PARAM_HOSTAPD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hostapd" }, { PRISM2_PARAM_HOSTAPD, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostapd" }, { PRISM2_PARAM_HOSTAPD_STA, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hostapd_sta" }, { PRISM2_PARAM_HOSTAPD_STA, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostapd_sta" }, { PRISM2_PARAM_WPA, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wpa" }, { PRISM2_PARAM_WPA, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getwpa" }, { PRISM2_PARAM_PRIVACY_INVOKED, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "privacy_invoked" }, { PRISM2_PARAM_PRIVACY_INVOKED, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getprivacy_invo" }, { PRISM2_PARAM_TKIP_COUNTERMEASURES, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "tkip_countermea" }, { PRISM2_PARAM_TKIP_COUNTERMEASURES, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gettkip_counter" }, { PRISM2_PARAM_DROP_UNENCRYPTED, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "drop_unencrypte" }, { PRISM2_PARAM_DROP_UNENCRYPTED, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdrop_unencry" }, { PRISM2_PARAM_SCAN_CHANNEL_MASK, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "scan_channels" }, { PRISM2_PARAM_SCAN_CHANNEL_MASK, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getscan_channel" },};static int prism2_ioctl_priv_inquire(struct net_device *dev, int *i){ struct hostap_interface *iface; local_info_t *local; iface = netdev_priv(dev); local = iface->local; if (local->func->cmd(dev, HFA384X_CMDCODE_INQUIRE, *i, NULL, NULL)) return -EOPNOTSUPP; return 0;}static int prism2_ioctl_priv_prism2_param(struct net_device *dev, struct iw_request_info *info, void *wrqu, char *extra){ struct hostap_interface *iface; local_info_t *local; int *i = (int *) extra; int param = *i; int value = *(i + 1); int ret = 0; u16 val; iface = netdev_priv(dev); local = iface->local; switch (param) { case PRISM2_PARAM_TXRATECTRL: local->fw_tx_rate_control = value; break; case PRISM2_PARAM_BEACON_INT: if (hostap_set_word(dev, HFA384X_RID_CNFBEACONINT, value) || local->func->reset_port(dev)) ret = -EINVAL; else local->beacon_int = value; break;#ifndef PRISM2_NO_STATION_MODES case PRISM2_PARAM_PSEUDO_IBSS: if (value == local->pseudo_adhoc) break; if (value != 0 && value != 1) { ret = -EINVAL; break; } printk(KERN_DEBUG "prism2: %s: pseudo IBSS change %d -> %d\n", dev->name, local->pseudo_adhoc, value); local->pseudo_adhoc = value; if (local->iw_mode != IW_MODE_ADHOC) break; if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, hostap_get_porttype(local))) { ret = -EOPNOTSUPP; break; } if (local->func->reset_port(dev)) ret = -EINVAL; break;#endif /* PRISM2_NO_STATION_MODES */ case PRISM2_PARAM_ALC: printk(KERN_DEBUG "%s: %s ALC\n", dev->name, value == 0 ? "Disabling" : "Enabling"); val = HFA384X_TEST_CFG_BIT_ALC; local->func->cmd(dev, HFA384X_CMDCODE_TEST | (HFA384X_TEST_CFG_BITS << 8), value == 0 ? 0 : 1, &val, NULL); break; case PRISM2_PARAM_DUMP: local->frame_dump = value; break; case PRISM2_PARAM_OTHER_AP_POLICY: if (value < 0 || value > 3) { ret = -EINVAL; break; } if (local->ap != NULL) local->ap->ap_policy = value; break; case PRISM2_PARAM_AP_MAX_INACTIVITY: if (value < 0 || value > 7 * 24 * 60 * 60) { ret = -EINVAL; break; } if (local->ap != NULL) local->ap->max_inactivity = value * HZ; break; case PRISM2_PARAM_AP_BRIDGE_PACKETS: if (local->ap != NULL) local->ap->bridge_packets = value; break; case PRISM2_PARAM_DTIM_PERIOD: if (value < 0 || value > 65535) { ret = -EINVAL; break; } if (hostap_set_word(dev, HFA384X_RID_CNFOWNDTIMPERIOD, value) || local->func->reset_port(dev)) ret = -EINVAL; else local->dtim_period = value; break; case PRISM2_PARAM_AP_NULLFUNC_ACK: if (local->ap != NULL) local->ap->nullfunc_ack = value; bre
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -