📄 wvlan_cs.c
字号:
else wrq->u.mode = IW_MODE_ADHOC; /* Check for compliant 802.11 IBSS Ad-Hoc mode */ if ((local->has_ibssid) && (wvlan_hw_getallowibssflag(&local->ifb) == 1)) wrq->u.mode = IW_MODE_ADHOC; break; // Set the desired Power Management mode case SIOCSIWPOWER: // Disable it ? if(wrq->u.power.disabled) { local->pm_on = 0; local->need_commit = 1; } else { // Check mode switch(wrq->u.power.flags & IW_POWER_MODE) { case IW_POWER_UNICAST_R: local->pm_multi = 0; local->need_commit = 1; break; case IW_POWER_ALL_R: local->pm_multi = 1; local->need_commit = 1; break; case IW_POWER_ON: // None = ok break; default: // Invalid rc = -EINVAL; } // Set period if (wrq->u.power.flags & IW_POWER_PERIOD) { // Activate PM local->pm_on = 1; // Hum: check max/min values ? local->pm_period = wrq->u.power.value/1000; local->need_commit = 1; } if (wrq->u.power.flags & IW_POWER_TIMEOUT) rc = -EINVAL; // Invalid } break; // Get the power management settings case SIOCGIWPOWER: wrq->u.power.disabled = !wvlan_hw_getpower(&local->ifb, CFG_CNF_PM_ENABLED); wrq->u.power.flags = IW_POWER_PERIOD; wrq->u.power.value = wvlan_hw_getpmsleep (&local->ifb) * 1000; if (wvlan_hw_getpower(&local->ifb, CFG_CNF_MCAST_RX)) wrq->u.power.flags |= IW_POWER_ALL_R; else wrq->u.power.flags |= IW_POWER_UNICAST_R; break; // Set WEP keys and mode case SIOCSIWENCODE: // Is it supported? if (!wvlan_hw_getprivacy(&local->ifb)) { rc = -EOPNOTSUPP; break; } // Basic checking: do we have a key to set? if (wrq->u.encoding.pointer != (caddr_t) 0) { int index = (wrq->u.encoding.flags & IW_ENCODE_INDEX) - 1; // Check the size of the key if (wrq->u.encoding.length > MAX_KEY_SIZE) { rc = -EINVAL; break; } // Check the index if ((index < 0) || (index >= MAX_KEYS)) index = local->transmit_key; // Cleanup memset(local->key[index].key, 0, MAX_KEY_SIZE); // Copy the key in the driver wv_driver_unlock(local, &flags); rc = copy_from_user(local->key[index].key, wrq->u.encoding.pointer, wrq->u.encoding.length); wv_driver_lock(local, &flags); if (rc) { rc = -EFAULT; local->key[index].len = 0; break; } // Set the length if (wrq->u.encoding.length > MIN_KEY_SIZE) local->key[index].len = MAX_KEY_SIZE; else if (wrq->u.encoding.length > 0) local->key[index].len = MIN_KEY_SIZE; else local->key[index].len = 0; // Enable WEP (if possible) if ((index == local->transmit_key) && (local->key[local->transmit_key].len > 0)) local->wep_on = 1; } else { int index = (wrq->u.encoding.flags & IW_ENCODE_INDEX) - 1; // Do we want to just set the current transmit key? if ((index >= 0) && (index < MAX_KEYS)) { if (local->key[index].len > 0) { local->transmit_key = index; local->wep_on = 1; } else rc = -EINVAL; } } // Read the flags if (wrq->u.encoding.flags & IW_ENCODE_DISABLED) local->wep_on = 0; // disable encryption if (wrq->u.encoding.flags & IW_ENCODE_RESTRICTED) rc = -EINVAL; // Invalid // Commit the changes if (rc == 0) local->need_commit = 1; break; // Get the WEP keys and mode case SIOCGIWENCODE: // Is it supported? if (!wvlan_hw_getprivacy(&local->ifb)) { rc = -EOPNOTSUPP; break; } // Only super-user can see WEP key if (!capable(CAP_NET_ADMIN)) { rc = -EPERM; break; } // Basic checking... if (wrq->u.encoding.pointer != (caddr_t) 0) { int index = (wrq->u.encoding.flags & IW_ENCODE_INDEX) - 1; // Note: should read from adapter(?), and check if WEP capable // Set the flags wrq->u.encoding.flags = 0; if (local->wep_on == 0) wrq->u.encoding.flags |= IW_ENCODE_DISABLED; // Which key do we want if ((index < 0) || (index >= MAX_KEYS)) index = local->transmit_key; wrq->u.encoding.flags |= index + 1; // Copy the key to the user buffer wrq->u.encoding.length = local->key[index].len; wv_driver_unlock(local, &flags); rc = copy_to_user(wrq->u.encoding.pointer, local->key[index].key, local->key[index].len); wv_driver_lock(local, &flags); if (rc) rc = -EFAULT; } break;#endif /* WIRELESS_EXT > 8 */#if WIRELESS_EXT > 9 // Get the current Tx-Power case SIOCGIWTXPOW: wrq->u.txpower.value = 15; /* 15 dBm */ wrq->u.txpower.fixed = 1; /* No power control */ wrq->u.txpower.disabled = 0; /* Can't turn off */ wrq->u.txpower.flags = IW_TXPOW_DBM; break;#endif /* WIRELESS_EXT > 9 */ // Get range of parameters case SIOCGIWRANGE: if (wrq->u.data.pointer) { struct iw_range range; rc = verify_area(VERIFY_WRITE, wrq->u.data.pointer, sizeof(struct iw_range)); if (rc) break; /* Set the length (very important for * backward compatibility) */ wrq->u.data.length = sizeof(range); /* Set all the info we don't care or * don't know about to zero */ memset(&range, 0, sizeof(range));#if WIRELESS_EXT > 10 /* Set the Wireless Extension versions */ range.we_version_compiled = WIRELESS_EXT; range.we_version_source = 10;#endif /* WIRELESS_EXT > 10 */ // Throughput is no way near 2 Mb/s ! // This value should be : // 1.6 Mb/s for the 2 Mb/s card // ~5 Mb/s for the 11 Mb/s card // Jean II range.throughput = 1.6 * 1024 * 1024; range.min_nwid = 0x0000; range.max_nwid = 0x0000; range.num_channels = 14; range.num_frequency = wvlan_hw_getfrequencylist(&local->ifb, range.freq, IW_MAX_FREQUENCIES); range.sensitivity = 3; if (local->port_type == 3 && local->spy_number == 0) { range.max_qual.qual = 0; range.max_qual.level = 0; range.max_qual.noise = 0; } else { range.max_qual.qual = 0x8b - 0x2f; range.max_qual.level = 0x2f - 0x95 - 1; range.max_qual.noise = 0x2f - 0x95 - 1; }#if WIRELESS_EXT > 7 range.num_bitrates = wvlan_getbitratelist(&local->ifb, range.bitrate, IW_MAX_BITRATES); range.min_rts = 0; range.max_rts = 2347; range.min_frag = 256; range.max_frag = 2346;#endif /* WIRELESS_EXT > 7 */#if WIRELESS_EXT > 8 // Is WEP it supported? if (wvlan_hw_getprivacy(&local->ifb)) { // WEP: RC4 40 bits range.encoding_size[0] = MIN_KEY_SIZE; // RC4 ~128 bits range.encoding_size[1] = MAX_KEY_SIZE; range.num_encoding_sizes = 2; range.max_encoding_tokens = 4; // 4 keys } else { range.num_encoding_sizes = 0; range.max_encoding_tokens = 0; }#endif /* WIRELESS_EXT > 8 */#if WIRELESS_EXT > 9 /* Power Management */ range.min_pmp = 0; /* ??? */ range.max_pmp = 65535000; /* ??? */ range.pmp_flags = IW_POWER_PERIOD; range.pmt_flags = 0; range.pm_capa = IW_POWER_PERIOD | IW_POWER_UNICAST_R; /* Transmit Power */ range.txpower[0] = 15; range.num_txpower = 1; range.txpower_capa = IW_TXPOW_DBM;#endif /* WIRELESS_EXT > 9 */ wv_driver_unlock(local, &flags); rc = copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range)); wv_driver_lock(local, &flags); if (rc) rc = -EFAULT; } break;#ifdef WIRELESS_SPY // Set the spy list case SIOCSIWSPY: if (wrq->u.data.length > IW_MAX_SPY) { rc = -E2BIG; break; } local->spy_number = wrq->u.data.length; if (local->spy_number > 0) { struct sockaddr address[IW_MAX_SPY]; int i; rc = verify_area(VERIFY_READ, wrq->u.data.pointer, sizeof(struct sockaddr) * local->spy_number); if (rc) break; wv_driver_unlock(local, &flags); rc = copy_from_user(address, wrq->u.data.pointer, sizeof(struct sockaddr) * local->spy_number); wv_driver_lock(local, &flags); if (rc) { rc = -EFAULT; break; } for (i=0; i<local->spy_number; i++) memcpy(local->spy_address[i], address[i].sa_data, MAC_ADDR_SIZE); memset(local->spy_stat, 0, sizeof(struct iw_quality) * IW_MAX_SPY); DEBUG(DEBUG_INFO, "%s: New spy list:\n", dev_info); for (i=0; i<wrq->u.data.length; i++) DEBUG(DEBUG_INFO, "%s: %d - %02x:%02x:%02x:%02x:%02x:%02x\n", dev_info, i+1, local->spy_address[i][0], local->spy_address[i][1], local->spy_address[i][2], local->spy_address[i][3], local->spy_address[i][4], local->spy_address[i][5]); } break; // Get the spy list case SIOCGIWSPY: wrq->u.data.length = local->spy_number; if ((local->spy_number > 0) && (wrq->u.data.pointer)) { struct sockaddr address[IW_MAX_SPY]; int i; rc = verify_area(VERIFY_WRITE, wrq->u.data.pointer, (sizeof(struct iw_quality)+sizeof(struct sockaddr)) * IW_MAX_SPY); if (rc) break; for (i=0; i<local->spy_number; i++) { memcpy(address[i].sa_data, local->spy_address[i], MAC_ADDR_SIZE); address[i].sa_family = AF_UNIX; } wv_driver_unlock(local, &flags); rc = copy_to_user(wrq->u.data.pointer, address, sizeof(struct sockaddr) * local->spy_number); rc += copy_to_user(wrq->u.data.pointer + (sizeof(struct sockaddr)*local->spy_number), local->spy_stat, sizeof(struct iw_quality) * local->spy_number); wv_driver_lock(local, &flags); if (rc) rc = -EFAULT; for (i=0; i<local->spy_number; i++) local->spy_stat[i].updated = 0; } break;#endif /* WIRELESS_SPY */#ifdef HISTOGRAM // Set the histogram range case SIOCDEVPRIVATE + 0xd: // Only super-user can set histogram data if (!capable(CAP_NET_ADMIN)) { rc = -EPERM; break; } if (wrq->u.data.length > 16) { rc = -E2BIG; break; } local->his_number = wrq->u.data.length; if (local->his_number > 0) { rc = verify_area(VERIFY_READ, wrq->u.data.pointer, sizeof(char) * local->his_number); if (rc) break; wv_driver_unlock(local, &flags); rc = copy_from_user(local->his_range, wrq->u.data.pointer, sizeof(char) * local->his_number); wv_driver_lock(local, &flags); if (rc) { rc = -EFAULT; break; } memset(local->his_sum, 0, sizeof(long) * 16); } break; // Get the histogram statistic case SIOCDEVPRIVATE + 0xe: wrq->u.data.length = local->his_number; if ((local->his_number > 0) && (wrq->u.data.pointer)) { rc = verify_area(VERIFY_WRITE, wrq->u.data.pointer, sizeof(long) * 16); if (rc) break; wv_driver_unlock(local, &flags); rc = copy_to_user(wrq->u.data.pointer, local->his_sum, sizeof(long) * local->his_number); wv_driver_lock(local, &flags); if (rc) rc = -EFAULT; } break;#endif /* HISTOGRAM */ // Get valid private ioctl calls case SIOCGIWPRIV: if (wrq->u.data.pointer) { struct iw_priv_args priv[] = {#ifdef HISTOGRAM { SIOCDEVPRIVATE + 0xd, IW_PRIV_TYPE_BYTE | 16, 0, "sethisto" }, { SIOCDEVPRIVATE + 0xe, 0, IW_PRIV_TYPE_INT | 16, "gethisto" },#endif#ifdef PCMCIA_DEBUG { SIOCDEVPRIVATE + 0x0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "force_reset" }, { SIOCDEVPRIVATE + 0x1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "debug_getinfo" },#endif }; rc = verify_area(VERIFY_WRITE, wrq->u.data.pointer, sizeof(priv)); if (rc) break; wrq->u.data.length = sizeof(priv) / sizeof(priv[0]); wv_driver_unlock(local, &flags); rc = copy_to_user(wrq->u.data.pointer, priv, sizeof(priv)); wv_driver_lock(local, &flags); if (rc) rc = -EFAULT; } break;#ifdef PCMCIA_DEBUG // Force card reset (debug purpose only) case SIOCDEVPRIVATE + 0x0: // Only super-user can reset the card... if (!capable(CAP_NET_ADMIN)) { rc = -EPERM; break; } if (*((int *) wrq->u.name) > 0) { // 'hard' reset printk(KERN_DEBUG "%s: Forcing hard reset\n", dev_info); /* IRQ already disabled, don't do it again */ wvlan_hw_shutdown(dev); wvlan_hw_config(dev); } else { // 'soft' reset printk(KERN_DEBUG "%s: Forc
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -