📄 isl_ioctl.c
字号:
if (islpci_get_state(priv) < PRV_STATE_INIT) return 0; /* Determine and validate the key index */ idx = (encoding->flags & IW_ENCODE_INDEX) - 1; if (idx) { if (idx < 0 || idx > 3) return -EINVAL; } else { ret = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); if (ret < 0) goto out; idx = r.u; } if (encoding->flags & IW_ENCODE_DISABLED) alg = IW_ENCODE_ALG_NONE; if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { /* Only set transmit key index here, actual * key is set below if needed. */ ret = mgt_set_request(priv, DOT11_OID_DEFKEYID, 0, &idx); set_key = ext->key_len > 0 ? 1 : 0; } if (set_key) { struct obj_key key = { DOT11_PRIV_WEP, 0, "" }; switch (alg) { case IW_ENCODE_ALG_NONE: break; case IW_ENCODE_ALG_WEP: if (ext->key_len > KEY_SIZE_WEP104) { ret = -EINVAL; goto out; } if (ext->key_len > KEY_SIZE_WEP40) key.length = KEY_SIZE_WEP104; else key.length = KEY_SIZE_WEP40; break; case IW_ENCODE_ALG_TKIP: if (ext->key_len > KEY_SIZE_TKIP) { ret = -EINVAL; goto out; } key.type = DOT11_PRIV_TKIP; key.length = KEY_SIZE_TKIP; break; default: return -EINVAL; } if (key.length) { memset(key.key, 0, sizeof(key.key)); memcpy(key.key, ext->key, ext->key_len); ret = mgt_set_request(priv, DOT11_OID_DEFKEYX, idx, &key); if (ret < 0) goto out; } } /* Read the flags */ if (encoding->flags & IW_ENCODE_DISABLED) { /* Encoding disabled, * authen = DOT11_AUTH_OS; * invoke = 0; * exunencrypt = 0; */ } if (encoding->flags & IW_ENCODE_OPEN) { /* Encode but accept non-encoded packets. No auth */ invoke = 1; } if (encoding->flags & IW_ENCODE_RESTRICTED) { /* Refuse non-encoded packets. Auth */ authen = DOT11_AUTH_BOTH; invoke = 1; exunencrypt = 1; } /* do the change if requested */ if (encoding->flags & IW_ENCODE_MODE) { ret = mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen); ret = mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &invoke); ret = mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, &exunencrypt); }out: return ret;}static int prism54_get_encodeext(struct net_device *ndev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ islpci_private *priv = netdev_priv(ndev); struct iw_point *encoding = &wrqu->encoding; struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; int idx, max_key_len; union oid_res_t r; int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0, wpa = 0; int ret = 0; if (islpci_get_state(priv) < PRV_STATE_INIT) return 0; /* first get the flags */ ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r); authen = r.u; ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r); invoke = r.u; ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r); exunencrypt = r.u; if (ret < 0) goto out; max_key_len = encoding->length - sizeof(*ext); if (max_key_len < 0) return -EINVAL; idx = (encoding->flags & IW_ENCODE_INDEX) - 1; if (idx) { if (idx < 0 || idx > 3) return -EINVAL; } else { ret = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); if (ret < 0) goto out; idx = r.u; } encoding->flags = idx + 1; memset(ext, 0, sizeof(*ext)); switch (authen) { case DOT11_AUTH_BOTH: case DOT11_AUTH_SK: wrqu->encoding.flags |= IW_ENCODE_RESTRICTED; case DOT11_AUTH_OS: default: wrqu->encoding.flags |= IW_ENCODE_OPEN; break; } down_write(&priv->mib_sem); wpa = priv->wpa; up_write(&priv->mib_sem); if (authen == DOT11_AUTH_OS && !exunencrypt && !invoke && !wpa) { /* No encryption */ ext->alg = IW_ENCODE_ALG_NONE; ext->key_len = 0; wrqu->encoding.flags |= IW_ENCODE_DISABLED; } else { struct obj_key *key; ret = mgt_get_request(priv, DOT11_OID_DEFKEYX, idx, NULL, &r); if (ret < 0) goto out; key = r.ptr; if (max_key_len < key->length) { ret = -E2BIG; goto out; } memcpy(ext->key, key->key, key->length); ext->key_len = key->length; switch (key->type) { case DOT11_PRIV_TKIP: ext->alg = IW_ENCODE_ALG_TKIP; break; default: case DOT11_PRIV_WEP: ext->alg = IW_ENCODE_ALG_WEP; break; } wrqu->encoding.flags |= IW_ENCODE_ENABLED; }out: return ret;}static intprism54_reset(struct net_device *ndev, struct iw_request_info *info, __u32 * uwrq, char *extra){ islpci_reset(netdev_priv(ndev), 0); return 0;}static intprism54_get_oid(struct net_device *ndev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ union oid_res_t r; int rvalue; enum oid_num_t n = dwrq->flags; rvalue = mgt_get_request(netdev_priv(ndev), n, 0, NULL, &r); dwrq->length = mgt_response_to_str(n, &r, extra); if ((isl_oid[n].flags & OID_FLAG_TYPE) != OID_TYPE_U32) kfree(r.ptr); return rvalue;}static intprism54_set_u32(struct net_device *ndev, struct iw_request_info *info, __u32 * uwrq, char *extra){ u32 oid = uwrq[0], u = uwrq[1]; return mgt_set_request(netdev_priv(ndev), oid, 0, &u);}static intprism54_set_raw(struct net_device *ndev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ u32 oid = dwrq->flags; return mgt_set_request(netdev_priv(ndev), oid, 0, extra);}voidprism54_acl_init(struct islpci_acl *acl){ sema_init(&acl->sem, 1); INIT_LIST_HEAD(&acl->mac_list); acl->size = 0; acl->policy = MAC_POLICY_OPEN;}static voidprism54_clear_mac(struct islpci_acl *acl){ struct list_head *ptr, *next; struct mac_entry *entry; if (down_interruptible(&acl->sem)) return; if (acl->size == 0) { up(&acl->sem); return; } for (ptr = acl->mac_list.next, next = ptr->next; ptr != &acl->mac_list; ptr = next, next = ptr->next) { entry = list_entry(ptr, struct mac_entry, _list); list_del(ptr); kfree(entry); } acl->size = 0; up(&acl->sem);}voidprism54_acl_clean(struct islpci_acl *acl){ prism54_clear_mac(acl);}static intprism54_add_mac(struct net_device *ndev, struct iw_request_info *info, struct sockaddr *awrq, char *extra){ islpci_private *priv = netdev_priv(ndev); struct islpci_acl *acl = &priv->acl; struct mac_entry *entry; struct sockaddr *addr = (struct sockaddr *) extra; if (addr->sa_family != ARPHRD_ETHER) return -EOPNOTSUPP; entry = kmalloc(sizeof (struct mac_entry), GFP_KERNEL); if (entry == NULL) return -ENOMEM; memcpy(entry->addr, addr->sa_data, ETH_ALEN); if (down_interruptible(&acl->sem)) { kfree(entry); return -ERESTARTSYS; } list_add_tail(&entry->_list, &acl->mac_list); acl->size++; up(&acl->sem); return 0;}static intprism54_del_mac(struct net_device *ndev, struct iw_request_info *info, struct sockaddr *awrq, char *extra){ islpci_private *priv = netdev_priv(ndev); struct islpci_acl *acl = &priv->acl; struct mac_entry *entry; struct sockaddr *addr = (struct sockaddr *) extra; if (addr->sa_family != ARPHRD_ETHER) return -EOPNOTSUPP; if (down_interruptible(&acl->sem)) return -ERESTARTSYS; list_for_each_entry(entry, &acl->mac_list, _list) { if (memcmp(entry->addr, addr->sa_data, ETH_ALEN) == 0) { list_del(&entry->_list); acl->size--; kfree(entry); up(&acl->sem); return 0; } } up(&acl->sem); return -EINVAL;}static intprism54_get_mac(struct net_device *ndev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ islpci_private *priv = netdev_priv(ndev); struct islpci_acl *acl = &priv->acl; struct mac_entry *entry; struct sockaddr *dst = (struct sockaddr *) extra; dwrq->length = 0; if (down_interruptible(&acl->sem)) return -ERESTARTSYS; list_for_each_entry(entry, &acl->mac_list, _list) { memcpy(dst->sa_data, entry->addr, ETH_ALEN); dst->sa_family = ARPHRD_ETHER; dwrq->length++; dst++; } up(&acl->sem); return 0;}/* Setting policy also clears the MAC acl, even if we don't change the defaut * policy */static intprism54_set_policy(struct net_device *ndev, struct iw_request_info *info, __u32 * uwrq, char *extra){ islpci_private *priv = netdev_priv(ndev); struct islpci_acl *acl = &priv->acl; u32 mlmeautolevel; prism54_clear_mac(acl); if ((*uwrq < MAC_POLICY_OPEN) || (*uwrq > MAC_POLICY_REJECT)) return -EINVAL; down_write(&priv->mib_sem); acl->policy = *uwrq; /* the ACL code needs an intermediate mlmeautolevel */ if ((priv->iw_mode == IW_MODE_MASTER) && (acl->policy != MAC_POLICY_OPEN)) mlmeautolevel = DOT11_MLME_INTERMEDIATE; else mlmeautolevel = CARD_DEFAULT_MLME_MODE; if (priv->wpa) mlmeautolevel = DOT11_MLME_EXTENDED; mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &mlmeautolevel); /* restart the card with our new policy */ if (mgt_commit(priv)) { up_write(&priv->mib_sem); return -EIO; } up_write(&priv->mib_sem); return 0;}static intprism54_get_policy(struct net_device *ndev, struct iw_request_info *info, __u32 * uwrq, char *extra){ islpci_private *priv = netdev_priv(ndev); struct islpci_acl *acl = &priv->acl; *uwrq = acl->policy; return 0;}/* Return 1 only if client should be accepted. */static intprism54_mac_accept(struct islpci_acl *acl, char *mac){ struct mac_entry *entry; int res = 0; if (down_interruptible(&acl->sem)) return -ERESTARTSYS; if (acl->policy == MAC_POLICY_OPEN) { up(&acl->sem); return 1; } list_for_each_entry(entry, &acl->mac_list, _list) { if (memcmp(entry->addr, mac, ETH_ALEN) == 0) { res = 1; break; } } res = (acl->policy == MAC_POLICY_ACCEPT) ? !res : res; up(&acl->sem); return res;}static intprism54_kick_all(struct net_device *ndev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ struct obj_mlme *mlme; int rvalue; mlme = kmalloc(sizeof (struct obj_mlme), GFP_KERNEL); if (mlme == NULL) return -ENOMEM; /* Tell the card to kick every client */ mlme->id = 0; rvalue = mgt_set_request(netdev_priv(ndev), DOT11_OID_DISASSOCIATE, 0, mlme); kfree(mlme); return rvalue;}static intprism54_kick_mac(struct net_device *ndev, struct iw_request_info *info, struct sockaddr *awrq, char *extra){ struct obj_mlme *mlme; struct sockaddr *addr = (struct sockaddr *) extra; int rvalue; if (addr->sa_family != ARPHRD_ETHER) return -EOPNOTSUPP; mlme = kmalloc(sizeof (struct obj_mlme), GFP_KERNEL); if (mlme == NULL) return -ENOMEM; /* Tell the card to only kick the corresponding bastard */ memcpy(mlme->address, addr->sa_data, ETH_ALEN); mlme->id = -1; rvalue = mgt_set_request(netdev_priv(ndev), DOT11_OID_DISASSOCIATE, 0, mlme); kfree(mlme); return rvalue;}/* Translate a TRAP oid into a wireless event. Called in islpci_mgt_receive. */static voidformat_event(islpci_private *priv, char *dest, const char *str, const struct obj_mlme *mlme, u16 *length, int error){ DECLARE_MAC_BUF(mac); int n = snprintf(dest, IW_CUSTOM_MAX, "%s %s %s %s (%2.2X)", str, ((priv->iw_mode == IW_MODE_MASTER) ? "from" : "to"), print_mac(mac, mlme->address), (error ? (mlme->code ? " : REJECTED " : " : ACCEPTED ") : ""), mlme->code); BUG_ON(n > IW_CUSTOM_MAX); *length = n;}static voidsend_formatted_event(islpci_private *priv, const char *str, const struct obj_mlme *mlme, int error){ union iwreq_data wrqu; char *memptr; memptr = kmalloc(IW_CUSTOM_MAX, GFP_KERNEL); if (!memptr) return; wrqu.data.pointer = memptr; wrqu.data.length = 0; format_event(priv, memptr, str, mlme, &wrqu.data.length, error); wireless_send_event(priv->ndev, IWEVCUSTOM, &wrqu, memptr); kfree(memptr);}static voidsend_simple_event(islpci_private *priv, const char *str){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -