📄 sm_drv_ioctl_umac.c
字号:
if (ret < 0) return ret; if (psm == DOT11_PSM_ACTIVE) prq->disabled = 1; else prq->disabled = 0; /* Note : by default, display the period */ if ((prq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { prq->flags = IW_POWER_TIMEOUT; prq->value = cam_timeout; } return ret;}#define WLAN_FC_TYPE_MGMT 0#define WLAN_FC_STYPE_ASSOC_REQ 0#define WLAN_FC_STYPE_REASSOC_REQ 2static int sm_drv_set_genie(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ int alen, ret=0, i; struct iw_point *dwrq; struct obj_attachment *attach; dwrq = &wrqu->data; if (dwrq == NULL) return -EINVAL; if (dwrq->length) { DEBUG(DBG_WPA, "IE:\n"); for (i = 0; i < dwrq->length; i++) { DEBUG(DBG_WPA, "0x%02x ", *((char*)(dwrq->pointer) + i)); } DEBUG(DBG_WPA, "\n"); alen = sizeof(struct obj_attachment) + dwrq->length; attach = (struct obj_attachment *)kzalloc(alen, GFP_ATOMIC); if (attach == NULL) return -ENOMEM; memcpy(attach->data, dwrq->pointer, dwrq->length); } else { /* If length is set to 0, we remove the generic element from the frame */ alen = sizeof(struct obj_attachment); attach = (struct obj_attachment *)kmalloc(alen, GFP_ATOMIC); } /* We attach the IE for association and re-association. This is neede for roaming */ attach->type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ASSOC_REQ << 4); attach->id = -1; attach->size = dwrq->length; ret = sm_drv_oid_set(dev, DOT11_OID_ATTACHMENT, (void*)attach, alen); if (ret < 0) return ret; attach->type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_REASSOC_REQ << 4); ret = sm_drv_oid_set(dev, DOT11_OID_ATTACHMENT, (void*)attach, alen); kfree(attach); return ret; }static int sm_drv_set_pmk(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ struct iw_pmksa * pmk; struct obj_stakey key; if (dwrq == NULL) return -EINVAL; if (!dwrq->length) return -EINVAL; pmk = (struct iw_pmksa *)dwrq->pointer; memset(&key, 0, sizeof(struct obj_stakey)); switch (pmk->cmd) { case IW_PMKSA_ADD: key.type = DOT11_PRIV_PMKID; memcpy(key.address, pmk->bssid.sa_data, ETH_ALEN); key.length = IW_PMKID_LEN; memcpy(key.key, pmk->pmkid, IW_PMKID_LEN); break; case IW_PMKSA_REMOVE: key.type = DOT11_PRIV_PMKID; memcpy(key.address, pmk->bssid.sa_data, ETH_ALEN); break; case IW_PMKSA_FLUSH: break; default: DEBUG(DBG_WPA, "Invalid PMK command: %d\n", pmk->cmd); return -EINVAL; } return sm_drv_oid_set(dev, DOT11_OID_STAKEY, (void *)&key, sizeof(struct obj_stakey));}/* Private handlers *//* First private ioctl after the WPA ones */#define SIOCIFWFIRST_SMPRIV SIOCIWFIRSTPRIV + 12/* Preamble settings */#define SM_DRV_SET_PREAMBLE SIOCIFWFIRST_SMPRIV#define SM_DRV_GET_PREAMBLE SIOCIFWFIRST_SMPRIV + 1static int sm_drv_set_preamble(struct net_device *dev, struct iw_request_info *info, __u32 * uwrq, char *extra){ DEBUG(DBG_IOCTL, "SET PREAMBLE\n"); if (uwrq == NULL) return -EINVAL; return sm_drv_oid_set(dev, DOT11_OID_PREAMBLESETTINGS, uwrq, sizeof(uint32_t));}static int sm_drv_get_preamble(struct net_device *dev, struct iw_request_info *info, __u32 * uwrq, char *extra){ uint32_t preamble, ret; DEBUG(DBG_IOCTL, "GET PREAMBLE\n"); /* get the rts threshold */ ret = sm_drv_oid_get(dev, DOT11_OID_PREAMBLESETTINGS, (void *)&preamble, sizeof(uint32_t)); if (ret < 0) return ret; memcpy(extra, &preamble, sizeof(preamble)); return ret;}#define SM_DRV_SET_HIBERNATE SIOCIFWFIRST_SMPRIV + 2static int sm_drv_set_hibernate(struct net_device *dev, struct iw_request_info *info, __u32 * uwrq, char *extra){ DEBUG(DBG_IOCTL, "SET HIBERNATE\n"); if (uwrq == NULL) return -EINVAL; return sm_drv_oid_set(dev, GEN_OID_HIBERNATE, uwrq, sizeof(uint32_t));}#define SM_DRV_SET_BGRSCAN SIOCIFWFIRST_SMPRIV + 4static int sm_drv_set_bgrscan(struct net_device *dev, struct iw_request_info *info, __u32 * uwrq, char *extra){ DEBUG(DBG_IOCTL, "SET BACKGROUND SCANNING\n"); return sm_drv_oid_set(dev, DOT11_OID_AUTOSCANDISABLE, uwrq, sizeof(uint32_t));}#define SM_DRV_SET_BEACONPERIOD SIOCIFWFIRST_SMPRIV + 6#define SM_DRV_GET_BEACONPERIOD SIOCIFWFIRST_SMPRIV + 7static int sm_drv_set_beaconperiod(struct net_device *dev, struct iw_request_info *info, __u32 * uwrq, char *extra){ DEBUG(DBG_IOCTL, "SET BEACON PERIOD\n"); if (uwrq == NULL) return -EINVAL; return sm_drv_oid_set(dev, DOT11_OID_BEACONPERIOD, uwrq, sizeof(uint32_t));}static int sm_drv_get_beaconperiod(struct net_device *dev, struct iw_request_info *info, __u32 * uwrq, char *extra){ uint32_t period, ret; DEBUG(DBG_IOCTL, "GET BEACON PERIOD\n"); ret = sm_drv_oid_get(dev, DOT11_OID_BEACONPERIOD, (void *)&period, sizeof(uint32_t)); if (ret < 0) return ret; memcpy(extra, &period, sizeof(period)); return ret;}/* WPA related handlers */int sm_drv_process_bss_data(struct net_device* dev, u8 *addr, u8 *payload, size_t len, uint32_t event){ struct ieee80211_beacon_phdr *hdr; u8 *pos, *end, *wpa1_ie_pos = NULL; int i; DEBUG(DBG_WPA, "Dumping frame for " MACSTR "\n", MAC2STR(addr)); for (i = 0; i < len; i++) DEBUG(DBG_WPA, "0x%02x ",payload[i]); DEBUG(DBG_WPA, "\n"); hdr = (struct ieee80211_beacon_phdr *) payload; pos = (u8 *) (hdr + 1); end = payload + len; while (pos < end) { /* If we find an RSN IE, we're done, we can send the IE event */ if (pos[0] == WPA2_EID_GENERIC && pos[1] >= 2 && memcmp(pos + 2, wpa2_oid, 2) == 0) { DEBUG(DBG_WPA, "Found WPA2 OID in beacon frame for " MACSTR "\n\n", MAC2STR(addr)); sm_drv_wpa_ie_add(dev, addr, pos, pos[1] + 2, event); return 0; } /* * If we find a WPA IE, we should continue to check if there's no RSN IE. * We just keep track of the WPA1 IE position. */ if (pos[0] == WPA_EID_GENERIC && pos[1] >= 4 && memcmp(pos + 2, wpa_oid, 4) == 0) { DEBUG(DBG_WPA, "Found WPA OID in beacon frame for " MACSTR "\n\n", MAC2STR(addr)); wpa1_ie_pos = pos; } pos++; } if (wpa1_ie_pos != NULL) { sm_drv_wpa_ie_add(dev, addr, wpa1_ie_pos, wpa1_ie_pos[1] + 2, event); return 0; } /* * We didn't find any WPA OID in the beacon, * let's remove the AP from the WPA list, if it's * there. */ sm_drv_wpa_ie_remove(dev, addr); return -1;}static int sm_drv_set_encryption(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ int ret = 0, force = 0, i; int invoke = 0, exunencrypt = 0; struct wlan_crypt * crypt_info; struct net_local *lp = dev->priv; const char multicast_address[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; DEBUG(DBG_WPA, "Calling set_encryption\n"); if (dwrq == NULL) return -EINVAL; if (!dwrq->length) return -EINVAL; crypt_info = (struct wlan_crypt *)dwrq->pointer; DEBUG(DBG_WPA, "Key dumping:\n"); DEBUG(DBG_WPA, " alg: %s\n", crypt_info->alg); DEBUG(DBG_WPA, " flags: 0x%x\n", crypt_info->flags); DEBUG(DBG_WPA, " index: %d\n", crypt_info->idx); DEBUG(DBG_WPA, " key length: %d\n", crypt_info->key_len); DEBUG(DBG_WPA, " key:\n"); for (i = 0; i < crypt_info->key_len; i++) DEBUG(DBG_WPA, " 0x%x\n", *((uint8_t *)crypt_info->key + i)); if (crypt_info->key_len > 0) { int index = crypt_info->idx; int current_index; struct obj_stakey key; /* get the current key index */ ret = sm_drv_oid_get(dev, DOT11_OID_DEFKEYID, (void *)¤t_index, sizeof(uint32_t)); if (ret < 0) return ret; /* Verify that the key is not marked as invalid */ if (!(crypt_info->flags & IW_ENCODE_NOKEY)) { key.length = dwrq->length > sizeof (key.key) ? sizeof (key.key) : dwrq->length; if (crypt_info->flags & IW_ENCODE_TKIP) { DEBUG(DBG_WPA, "TKIP encryption\n"); /* * UMAC expects the key in AP mode: RX mic at the * end, and TX at byte 16. * This is 802.11i AP compliant, but not STA. * Conexant doesn't seem to care. */ memcpy(key.key, crypt_info->key, key.length -16); memcpy(key.key+16, crypt_info->key+24, 8); memcpy(key.key+24, crypt_info->key+16, 8); key.type = DOT11_PRIV_TKIP; invoke = DOT11_PRIV_INV_TKIP; } else if (crypt_info->flags & IW_ENCODE_AES) { DEBUG(DBG_WPA, "AES encryption\n"); memcpy(key.key, crypt_info->key, key.length); key.type = DOT11_PRIV_AES_CCMP; invoke = DOT11_PRIV_INV_AES_CCMP; } if ((index < 0) || (index > 3)) { /* no index provided use the current one */ index = current_index; } /* * We can now send the key to the UMAC. * Flags tell us which key it is. */ if (crypt_info->flags & IW_ENCODE_UNICAST) { DEBUG(DBG_WPA, "Setting key with Mac: " MACSTR "\n", MAC2STR(lp->ap_mac_address)); memcpy(key.address, lp->ap_mac_address, ETH_ALEN); } else if (crypt_info->flags & IW_ENCODE_MULTICAST) memcpy(key.address, multicast_address, ETH_ALEN); key.keyid = index; key.ext = 0; ret = sm_drv_oid_set(dev, DOT11_OID_STAKEY, (void *)&key, sizeof(struct obj_stakey)); if (ret < 0) return ret; } /* * If a valid key is set, encryption should be enabled * (user may turn it off later). * This is also how "iwconfig ethX key on" works */ if ((index == current_index) && (key.length > 0)) force = 1; } else { int index = (crypt_info->flags & IW_ENCODE_INDEX) - 1; if ((index >= 0) && (index <= 3)) { /* we want to set the key index */ ret = sm_drv_oid_set(dev, DOT11_OID_DEFKEYID, (void *)&index, sizeof(uint32_t)); if (ret < 0) return ret; } else { if (!crypt_info->flags & IW_ENCODE_MODE) { /* we cannot do anything. Complain. */ return -EINVAL; } } } /* now read the flags */ if (crypt_info->flags & IW_ENCODE_OPEN) { /* Encode but accept non-encoded packets. No auth */ DEBUG(DBG_WPA, "Encode but accept non-encoded packets\n"); } if ((crypt_info->flags & IW_ENCODE_RESTRICTED) || force) { /* Refuse non-encoded packets. Auth */ DEBUG(DBG_WPA, "Refuse non-encoded packets\n"); exunencrypt = 1; } /* do the change if requested */ if ((crypt_info->flags & IW_ENCODE_MODE) || force) { uint32_t dot1x_enable = 1; DEBUG(DBG_WPA, "PRIVACY INVOKED\n"); ret = sm_drv_oid_set(dev, DOT11_OID_PRIVACYINVOKED, (void *)&invoke, sizeof(uint32_t)); DEBUG(DBG_WPA, "EXUNENCRYPTED\n"); ret |= sm_drv_oid_set(dev, DOT11_OID_EXUNENCRYPTED, (void *)&exunencrypt, sizeof(uint32_t)); DEBUG(DBG_WPA, "Enabling 802.1x\n"); ret |= sm_drv_oid_set(dev, DOT11_OID_DOT1XENABLE, (void *)&dot1x_enable, sizeof(uint32_t)); } return ret;}int sm_drv_set_wpa(struct net_device *dev, struct iw_request_info *info, __u32 * uwrq, char *extra){ struct net_local *lp = dev->priv; int ret = 0; uint32_t filter, dot1x_enable = 1; if (uwrq == NULL) return -EINVAL; DEBUG(DBG_WPA, "Calling set_wpa\n"); filter = 1; /* Filter out all unencrypted frames */ dot1x_enable = 1; lp->wpa = *uwrq; switch (lp->wpa) { case DOT11_PRIV_INV_NONE: /* Clears/disables WPA and friends */ filter = 0; /* Do not filter un-encrypted data */ break; case DOT11_PRIV_INV_WEP: dot1x_enable = 0; break; case DOT11_PRIV_INV_TKIP: break; case DOT11_PRIV_INV_AES_CCMP: break; default: return -EINVAL; } ret = sm_drv_oid_set(dev, DOT11_OID_PRIVACYINVOKED, (void *)&(lp->wpa), sizeof(uint32_t)); ret |= sm_drv_oid_set(dev, DOT11_OID_EXUNENCRYPTED, (void *)&filter, sizeof(uint32_t)); ret |= sm_drv_oid_set(dev, DOT11_OID_DOT1XENABLE, (void *)&dot1x_enable, sizeof(uint32_t)); return ret;}int sm_drv_get_wpa(struct net_device *dev, struct iw_request_info *info, __u32 * uwrq, char *extra){ struct net_local *lp = dev->priv; *uwrq = lp->wpa; return 0;}const iw_handler sm_drv_we_handler[] = { (iw_handler) sm_drv_commit, /* SIOCSIWCOMMIT */ (iw_handler) sm_drv_get_name, /* SIOCGIWNAME */ (iw_handler) NULL, /* SIOCSIWNWID */ (iw_handler) NULL, /* SIOCGIWNWID */ (iw_handler) sm_drv_set_freq, /* SIOCSIWFREQ */ (iw_handler) sm_drv_get_freq, /* SIOCGIWFREQ */ (iw_handler) sm_drv_set_mode, /* SIOCSIWMODE */ (iw_handler) sm_drv_get_mode, /* SIOCGIWMODE */ (iw_handler) sm_drv_set_sens, /* SIOCSIWSENS */ (iw_handler) sm_drv_get_sens, /* SIOCGIWSENS */ (iw_handler) NULL, /* SIOCSIWRANGE */ (iw_handler) sm_drv_get_range, /* SIOCGIWRANGE */ (iw_handler) NULL, /* SIOCSIWPRIV */ (iw_handler) NULL, /* SIOCGIWPRIV */ (iw_handler) NULL, /* SIOCSIWSTATS */ (iw_handler) sm_drv_get_wireless_stats, /* SIOCGIWSTATS */ (iw_handler) NULL, /* SIOCSIWSPY */ iw_handler_get_spy, /* SIOCGIWSPY */ iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ (iw_handler) sm_drv_set_wap, /* SIOCSIWAP */ (iw_handler) sm_drv_get_wap, /* SIOCGIWAP */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) NULL, /* SIOCGIWAPLIST deprecated */ (iw_handler) sm_drv_set_scan, /* SIOCSIWSCAN */ (iw_handler) sm_drv_get_scan, /* SIOCGIWSCAN */ (iw_handler) sm_drv_set_essid, /* SIOCSIWESSID */ (iw_handler) sm_drv_get_essid, /* SIOCGIWESSID */ (iw_handler) NULL, /* SIOCSIWNICKN */ (iw_handler) NULL, /* SIOCGIWNICKN */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) sm_drv_set_rate, /* SIOCSIWRATE */ (iw_handler) sm_drv_get_rate, /* SIOCGIWRATE */ (iw_handler) sm_drv_set_rts, /* SIOCSIWRTS */ (iw_handler) sm_drv_get_rts, /* SIOCGIWRTS */ (iw_handler) sm_drv_set_frag, /* SIOCSIWFRAG */ (iw_handler) sm_drv_get_frag, /* SIOCGIWFRAG */ (iw_handler) sm_drv_set_txpower, /* SIOCSIWTXPOW */ (iw_handler) sm_drv_get_txpower, /* SIOCGIWTXPOW */ (iw_handler) NULL, /* SIOCSIWRETRY */ (iw_handler) NULL, /* SIOCGIWRETRY */ (iw_handler) sm_drv_set_encode, /* SIOCSIWENCODE */ (iw_handler) sm_drv_get_encode, /* SIOCGIWENCODE */ (iw_handler) sm_drv_set_ps, /* SIOCSIWPOWER */ (iw_handler) sm_drv_get_ps, /* SIOCGIWPOWER */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) sm_drv_set_genie, /* SIOCSIWGENIE*/ (iw_handler) NULL, /* SIOCGIWGENIE */ (iw_handler) NULL, /* SIOCSIWAUTH */ (iw_handler) NULL, /* SIOCGIWAUTH */ (iw_handler) NULL, /* SIOCSIWENCODEEXT */ (iw_handler) NULL, /* SIOCGIWENCODEEXT */ (iw_handler) sm_drv_set_pmk, /* SIOCSIWPMKSA */};#define SM_DRV_SET_DEBUG SIOCIWFIRSTPRIVconst struct iw_priv_args sm_drv_we_private_args[] = { {SM_DRV_SET_DEBUG, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_debug"}, {SM_DRV_WPA_SCAN, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, "wpa_scan"}, {SM_DRV_WPA_GEN_ELT, IW_PRIV_TYPE_BYTE | 256, 0, "gen_ie"}, {SM_DRV_SET_PREAMBLE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_preamble"}, {SM_DRV_GET_PREAMBLE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_preamble"}, {SM_DRV_SET_HIBERNATE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_hibernate"}, {SM_DRV_SET_BGRSCAN, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_backscan"}, {SM_DRV_SET_BEACONPERIOD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_bperiod"}, {SM_DRV_GET_BEACONPERIOD, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_bperiod"},};static const iw_handler sm_drv_we_private_handler[] = { (iw_handler) sm_drv_set_debug, (iw_handler) NULL, (iw_handler) sm_drv_set_scan, (iw_handler) NULL, (iw_handler) sm_drv_set_genie, (iw_handler) NULL, (iw_handler) sm_drv_set_wpa, (iw_handler) sm_drv_get_wpa, (iw_handler) sm_drv_set_encryption, (iw_handler) sm_drv_set_encryption, (iw_handler) sm_drv_set_pmk, (iw_handler) NULL, (iw_handler) sm_drv_set_preamble, (iw_handler) sm_drv_get_preamble, (iw_handler) sm_drv_set_hibernate, (iw_handler) NULL, (iw_handler) sm_drv_set_bgrscan, (iw_handler) NULL, (iw_handler) sm_drv_set_beaconperiod, (iw_handler) sm_drv_get_beaconperiod,};const struct iw_handler_def sm_drv_we_handler_def = { .num_standard = sizeof(sm_drv_we_handler) / sizeof(iw_handler), .num_private = sizeof(sm_drv_we_private_handler) / sizeof(iw_handler), .num_private_args = sizeof(sm_drv_we_private_args) / sizeof(struct iw_priv_args), .standard = (iw_handler *) sm_drv_we_handler, .private = (iw_handler *) sm_drv_we_private_handler, .private_args = (struct iw_priv_args *) sm_drv_we_private_args, .get_wireless_stats = sm_drv_get_wireless_stats,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -