📄 hostap_ioctl.c
字号:
} data->length = val; memcpy(essid, ssid + 2, IW_ESSID_MAX_SIZE); } return 0;}static int prism2_ioctl_giwrange(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra){ struct hostap_interface *iface = dev->priv; local_info_t *local = iface->local; struct iw_range *range = (struct iw_range *) extra; u8 rates[10]; u16 val; int i, len, over2; data->length = sizeof(struct iw_range); memset(range, 0, sizeof(struct iw_range)); /* TODO: could fill num_txpower and txpower array with * something; however, there are 128 different values.. */ range->txpower_capa = IW_TXPOW_DBM; if (local->iw_mode == IW_MODE_INFRA || local->iw_mode == IW_MODE_ADHOC) { range->min_pmp = 1 * 1024; range->max_pmp = 65535 * 1024; range->min_pmt = 1 * 1024; range->max_pmt = 1000 * 1024; range->pmp_flags = IW_POWER_PERIOD; range->pmt_flags = IW_POWER_TIMEOUT; range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R | IW_POWER_ALL_R; } range->we_version_compiled = WIRELESS_EXT; range->we_version_source = 18; range->retry_capa = IW_RETRY_LIMIT; range->retry_flags = IW_RETRY_LIMIT; range->min_retry = 0; range->max_retry = 255; range->num_channels = FREQ_COUNT; val = 0; for (i = 0; i < FREQ_COUNT; i++) { if (local->channel_mask & (1 << i)) { range->freq[val].i = i + 1; range->freq[val].m = freq_list[i] * 100000; range->freq[val].e = 1; val++; } if (val == IW_MAX_FREQUENCIES) break; } range->num_frequency = val; if (local->sta_fw_ver >= PRISM2_FW_VER(1,3,1)) { range->max_qual.qual = 70; /* what is correct max? This was not * documented exactly. At least * 69 has been observed. */ range->max_qual.level = 0; /* dB */ range->max_qual.noise = 0; /* dB */ /* What would be suitable values for "average/typical" qual? */ range->avg_qual.qual = 20; range->avg_qual.level = -60; range->avg_qual.noise = -95; } else { range->max_qual.qual = 92; /* 0 .. 92 */ range->max_qual.level = 154; /* 27 .. 154 */ range->max_qual.noise = 154; /* 27 .. 154 */ } range->sensitivity = 3; range->max_encoding_tokens = WEP_KEYS; range->num_encoding_sizes = 2; range->encoding_size[0] = 5; range->encoding_size[1] = 13; over2 = 0; len = prism2_get_datarates(dev, rates); range->num_bitrates = 0; for (i = 0; i < len; i++) { if (range->num_bitrates < IW_MAX_BITRATES) { range->bitrate[range->num_bitrates] = rates[i] * 500000; range->num_bitrates++; } if (rates[i] == 0x0b || rates[i] == 0x16) over2 = 1; } /* estimated maximum TCP throughput values (bps) */ range->throughput = over2 ? 5500000 : 1500000; range->min_rts = 0; range->max_rts = 2347; range->min_frag = 256; range->max_frag = 2346;#if WIRELESS_EXT > 16 /* Event capability (kernel + driver) */ range->event_capa[0] = (IW_EVENT_CAPA_K_0 | IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) | IW_EVENT_CAPA_MASK(SIOCGIWAP) | IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); range->event_capa[1] = IW_EVENT_CAPA_K_1; range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVTXDROP) | IW_EVENT_CAPA_MASK(IWEVCUSTOM) | IW_EVENT_CAPA_MASK(IWEVREGISTERED) | IW_EVENT_CAPA_MASK(IWEVEXPIRED));#endif /* WIRELESS_EXT > 16 */#if WIRELESS_EXT > 17 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;#endif /* WIRELESS_EXT > 17 */ return 0;}static int hostap_monitor_mode_enable(local_info_t *local){ struct net_device *dev = local->dev; printk(KERN_DEBUG "Enabling monitor mode\n"); hostap_monitor_set_type(local); if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, HFA384X_PORTTYPE_PSEUDO_IBSS)) { printk(KERN_DEBUG "Port type setting for monitor mode " "failed\n"); return -EOPNOTSUPP; } /* Host decrypt is needed to get the IV and ICV fields; * however, monitor mode seems to remove WEP flag from frame * control field */ if (hostap_set_word(dev, HFA384X_RID_CNFWEPFLAGS, HFA384X_WEPFLAGS_HOSTENCRYPT | HFA384X_WEPFLAGS_HOSTDECRYPT)) { printk(KERN_DEBUG "WEP flags setting failed\n"); return -EOPNOTSUPP; } if (local->func->reset_port(dev) || local->func->cmd(dev, HFA384X_CMDCODE_TEST | (HFA384X_TEST_MONITOR << 8), 0, NULL, NULL)) { printk(KERN_DEBUG "Setting monitor mode failed\n"); return -EOPNOTSUPP; } return 0;}static int hostap_monitor_mode_disable(local_info_t *local){ struct net_device *dev = local->ddev; if (dev == NULL) return -1; printk(KERN_DEBUG "%s: Disabling monitor mode\n", dev->name); dev->type = ARPHRD_ETHER; dev->hard_header_parse = local->saved_eth_header_parse; if (local->func->cmd(dev, HFA384X_CMDCODE_TEST | (HFA384X_TEST_STOP << 8), 0, NULL, NULL)) return -1; return hostap_set_encryption(local);}static int prism2_ioctl_siwmode(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra){ struct hostap_interface *iface = dev->priv; local_info_t *local = iface->local; int double_reset = 0; if (*mode != IW_MODE_ADHOC && *mode != IW_MODE_INFRA && *mode != IW_MODE_MASTER && *mode != IW_MODE_REPEAT && *mode != IW_MODE_MONITOR) return -EOPNOTSUPP;#ifdef PRISM2_NO_STATION_MODES if (*mode == IW_MODE_ADHOC || *mode == IW_MODE_INFRA) return -EOPNOTSUPP;#endif /* PRISM2_NO_STATION_MODES */ if (*mode == local->iw_mode) return 0; if (*mode == IW_MODE_MASTER && local->essid[0] == '\0') { printk(KERN_WARNING "%s: empty SSID not allowed in Master " "mode\n", dev->name); return -EINVAL; } if (local->iw_mode == IW_MODE_MONITOR) hostap_monitor_mode_disable(local); if ((local->iw_mode == IW_MODE_ADHOC || local->iw_mode == IW_MODE_MONITOR) && *mode == IW_MODE_MASTER) { /* There seems to be a firmware bug in at least STA f/w v1.5.6 * that leaves beacon frames to use IBSS type when moving from * IBSS to Host AP mode. Doing double Port0 reset seems to be * enough to workaround this. */ double_reset = 1; } printk(KERN_DEBUG "prism2: %s: operating mode changed " "%d -> %d\n", dev->name, local->iw_mode, *mode); local->iw_mode = *mode; if (local->iw_mode == IW_MODE_MONITOR) hostap_monitor_mode_enable(local); else if (local->iw_mode == IW_MODE_MASTER && !local->host_encrypt && !local->fw_encrypt_ok) { printk(KERN_DEBUG "%s: defaulting to host-based encryption as " "a workaround for firmware bug in Host AP mode WEP\n", dev->name); local->host_encrypt = 1; } if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, hostap_get_porttype(local))) return -EOPNOTSUPP; if (local->func->reset_port(dev)) return -EINVAL; if (double_reset && local->func->reset_port(dev)) return -EINVAL; if (local->iw_mode != IW_MODE_INFRA && local->iw_mode != IW_MODE_ADHOC) { /* netif_carrier is used only in client modes for now, so make * sure carrier is on when moving to non-client modes. */ netif_carrier_on(local->dev); netif_carrier_on(local->ddev); } return 0;}static int prism2_ioctl_giwmode(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra){ struct hostap_interface *iface = dev->priv; local_info_t *local = iface->local; switch (iface->type) { case HOSTAP_INTERFACE_STA: *mode = IW_MODE_INFRA; break; case HOSTAP_INTERFACE_WDS: *mode = IW_MODE_REPEAT; break; default: *mode = local->iw_mode; break; } return 0;}static int prism2_ioctl_siwpower(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra){#ifdef PRISM2_NO_STATION_MODES return -EOPNOTSUPP;#else /* PRISM2_NO_STATION_MODES */ int ret = 0; if (wrq->disabled) return hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 0); switch (wrq->flags & IW_POWER_MODE) { case IW_POWER_UNICAST_R: ret = hostap_set_word(dev, HFA384X_RID_CNFMULTICASTRECEIVE, 0); if (ret) return ret; ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1); if (ret) return ret; break; case IW_POWER_ALL_R: ret = hostap_set_word(dev, HFA384X_RID_CNFMULTICASTRECEIVE, 1); if (ret) return ret; ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1); if (ret) return ret; break; case IW_POWER_ON: break; default: return -EINVAL; } if (wrq->flags & IW_POWER_TIMEOUT) { ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1); if (ret) return ret; ret = hostap_set_word(dev, HFA384X_RID_CNFPMHOLDOVERDURATION, wrq->value / 1024); if (ret) return ret; } if (wrq->flags & IW_POWER_PERIOD) { ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1); if (ret) return ret; ret = hostap_set_word(dev, HFA384X_RID_CNFMAXSLEEPDURATION, wrq->value / 1024); if (ret) return ret; } return ret;#endif /* PRISM2_NO_STATION_MODES */}static int prism2_ioctl_giwpower(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra){#ifdef PRISM2_NO_STATION_MODES return -EOPNOTSUPP;#else /* PRISM2_NO_STATION_MODES */ struct hostap_interface *iface = dev->priv; local_info_t *local = iface->local; u16 enable, mcast; if (local->func->get_rid(dev, HFA384X_RID_CNFPMENABLED, &enable, 2, 1) < 0) return -EINVAL; if (!__le16_to_cpu(enable)) { rrq->disabled = 1; return 0; } rrq->disabled = 0; if ((rrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { u16 timeout; if (local->func->get_rid(dev, HFA384X_RID_CNFPMHOLDOVERDURATION, &timeout, 2, 1) < 0) return -EINVAL; rrq->flags = IW_POWER_TIMEOUT; rrq->value = __le16_to_cpu(timeout) * 1024; } else { u16 period; if (local->func->get_rid(dev, HFA384X_RID_CNFMAXSLEEPDURATION, &period, 2, 1) < 0) return -EINVAL; rrq->flags = IW_POWER_PERIOD; rrq->value = __le16_to_cpu(period) * 1024; } if (local->func->get_rid(dev, HFA384X_RID_CNFMULTICASTRECEIVE, &mcast, 2, 1) < 0) return -EINVAL; if (__le16_to_cpu(mcast)) rrq->flags |= IW_POWER_ALL_R; else rrq->flags |= IW_POWER_UNICAST_R; return 0;#endif /* PRISM2_NO_STATION_MODES */}static int prism2_ioctl_siwretry(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra){ struct hostap_interface *iface = dev->priv; local_info_t *local = iface->local; if (rrq->disabled) return -EINVAL; /* setting retry limits is not supported with the current station * firmware code; simulate this with alternative retry count for now */ if (rrq->flags == IW_RETRY_LIMIT) { if (rrq->value < 0) { /* disable manual retry count setting and use firmware * defaults */ local->manual_retry_count = -1; local->tx_control &= ~HFA384X_TX_CTRL_ALT_RTRY; } else { if (hostap_set_word(dev, HFA384X_RID_CNFALTRETRYCOUNT, rrq->value)) { printk(KERN_DEBUG "%s: Alternate retry count " "setting to %d failed\n", dev->name, rrq->value); return -EOPNOTSUPP; } local->manual_retry_count = rrq->value; local->tx_control |= HFA384X_TX_CTRL_ALT_RTRY; } return 0; } return -EOPNOTSUPP;#if 0 /* what could be done, if firmware would support this.. */ if (rrq->flags & IW_RETRY_LIMIT) { if (rrq->flags & IW_RETRY_MAX) HFA384X_RID_LONGRETRYLIMIT = rrq->value; else if (rrq->flags & IW_RETRY_MIN) HFA384X_RID_SHORTRETRYLIMIT = rrq->value; else { HFA384X_RID_LONGRETRYLIMIT = rrq->value; HFA384X_RID_SHORTRETRYLIMIT = rrq->value; } } if (rrq->flags & IW_RETRY_LIFETIME) { HFA384X_RID_MAXTRANSMITLIFETIME = rrq->value / 1024; } return 0;#endif /* 0 */}static int prism2_ioctl_giwretry(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra){ struct hostap_interface *iface = dev->priv; local_info_t *local = iface->local; u16 shortretry, longretry, lifetime, altretry; if (local->func->get_rid(dev, HFA384X_RID_SHORTRETRYLIMIT, &shortretry, 2, 1) < 0 || local->func->get_rid(dev, HFA384X_RID_LONGRETRYLIMIT, &longretry, 2, 1) < 0 || local->func->get_rid(dev, HFA384X_RID_MAXTRANSMITLIFETIME, &lifetime, 2, 1) < 0) return -EINVAL; le16_to_cpus(&shortretry); le16_to_cpus(&longretry); le16_to_cpus(&lifetime);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -