📄 isl_ioctl.c
字号:
union oid_res_t r; int rvalue = 0; vwrq->disabled = 0; /* It cannot be disabled */ if ((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { /* we are asked for the life time */ rvalue = mgt_get_request(priv, DOT11_OID_MAXTXLIFETIME, 0, NULL, &r); vwrq->value = r.u * 1024; vwrq->flags = IW_RETRY_LIFETIME; } else if ((vwrq->flags & IW_RETRY_MAX)) { /* we are asked for the long retry limit */ rvalue |= mgt_get_request(priv, DOT11_OID_LONGRETRIES, 0, NULL, &r); vwrq->value = r.u; vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX; } else { /* default. get the short retry limit */ rvalue |= mgt_get_request(priv, DOT11_OID_SHORTRETRIES, 0, NULL, &r); vwrq->value = r.u; vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MIN; } return rvalue;}static intprism54_set_encode(struct net_device *ndev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ islpci_private *priv = netdev_priv(ndev); int rvalue = 0, force = 0; int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0; union oid_res_t r; /* with the new API, it's impossible to get a NULL pointer. * New version of iwconfig set the IW_ENCODE_NOKEY flag * when no key is given, but older versions don't. */ if (dwrq->length > 0) { /* we have a key to set */ int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; int current_index; struct obj_key key = { DOT11_PRIV_WEP, 0, "" }; /* get the current key index */ rvalue = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); current_index = r.u; /* Verify that the key is not marked as invalid */ if (!(dwrq->flags & IW_ENCODE_NOKEY)) { key.length = dwrq->length > sizeof (key.key) ? sizeof (key.key) : dwrq->length; memcpy(key.key, extra, key.length); if (key.length == 32) /* we want WPA-PSK */ key.type = DOT11_PRIV_TKIP; if ((index < 0) || (index > 3)) /* no index provided use the current one */ index = current_index; /* now send the key to the card */ rvalue |= mgt_set_request(priv, DOT11_OID_DEFKEYX, index, &key); } /* * 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 = (dwrq->flags & IW_ENCODE_INDEX) - 1; if ((index >= 0) && (index <= 3)) { /* we want to set the key index */ rvalue |= mgt_set_request(priv, DOT11_OID_DEFKEYID, 0, &index); } else { if (!dwrq->flags & IW_ENCODE_MODE) { /* we cannot do anything. Complain. */ return -EINVAL; } } } /* now read the flags */ if (dwrq->flags & IW_ENCODE_DISABLED) { /* Encoding disabled, * authen = DOT11_AUTH_OS; * invoke = 0; * exunencrypt = 0; */ } if (dwrq->flags & IW_ENCODE_OPEN) /* Encode but accept non-encoded packets. No auth */ invoke = 1; if ((dwrq->flags & IW_ENCODE_RESTRICTED) || force) { /* Refuse non-encoded packets. Auth */ authen = DOT11_AUTH_BOTH; invoke = 1; exunencrypt = 1; } /* do the change if requested */ if ((dwrq->flags & IW_ENCODE_MODE) || force) { rvalue |= mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen); rvalue |= mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &invoke); rvalue |= mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, &exunencrypt); } return rvalue;}static intprism54_get_encode(struct net_device *ndev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ islpci_private *priv = netdev_priv(ndev); struct obj_key *key; u32 devindex, index = (dwrq->flags & IW_ENCODE_INDEX) - 1; u32 authen = 0, invoke = 0, exunencrypt = 0; int rvalue; union oid_res_t r; /* first get the flags */ rvalue = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r); authen = r.u; rvalue |= mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r); invoke = r.u; rvalue |= mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r); exunencrypt = r.u; if (invoke && (authen == DOT11_AUTH_BOTH) && exunencrypt) dwrq->flags = IW_ENCODE_RESTRICTED; else if ((authen == DOT11_AUTH_OS) && !exunencrypt) { if (invoke) dwrq->flags = IW_ENCODE_OPEN; else dwrq->flags = IW_ENCODE_DISABLED; } else /* The card should not work in this state */ dwrq->flags = 0; /* get the current device key index */ rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); devindex = r.u; /* Now get the key, return it */ if ((index < 0) || (index > 3)) /* no index provided, use the current one */ index = devindex; rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYX, index, NULL, &r); key = r.ptr; dwrq->length = key->length; memcpy(extra, key->key, dwrq->length); kfree(key); /* return the used key index */ dwrq->flags |= devindex + 1; return rvalue;}static intprism54_get_txpower(struct net_device *ndev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ islpci_private *priv = netdev_priv(ndev); union oid_res_t r; int rvalue; rvalue = mgt_get_request(priv, OID_INL_OUTPUTPOWER, 0, NULL, &r); /* intersil firmware operates in 0.25 dBm (1/4 dBm) */ vwrq->value = (s32) r.u / 4; vwrq->fixed = 1; /* radio is not turned of * btw: how is possible to turn off only the radio */ vwrq->disabled = 0; return rvalue;}static intprism54_set_txpower(struct net_device *ndev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ islpci_private *priv = netdev_priv(ndev); s32 u = vwrq->value; /* intersil firmware operates in 0.25 dBm (1/4) */ u *= 4; if (vwrq->disabled) { /* don't know how to disable radio */ printk(KERN_DEBUG "%s: %s() disabling radio is not yet supported.\n", priv->ndev->name, __FUNCTION__); return -ENOTSUPP; } else if (vwrq->fixed) /* currently only fixed value is supported */ return mgt_set_request(priv, OID_INL_OUTPUTPOWER, 0, &u); else { printk(KERN_DEBUG "%s: %s() auto power will be implemented later.\n", priv->ndev->name, __FUNCTION__); return -ENOTSUPP; }}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((islpci_private *) ndev->priv, 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((islpci_private *) ndev->priv, 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((islpci_private *) ndev->priv, 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 list_head *ptr; struct sockaddr *addr = (struct sockaddr *) extra; if (addr->sa_family != ARPHRD_ETHER) return -EOPNOTSUPP; if (down_interruptible(&acl->sem)) return -ERESTARTSYS; for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) { entry = list_entry(ptr, struct mac_entry, _list); if (memcmp(entry->addr, addr->sa_data, ETH_ALEN) == 0) { list_del(ptr); 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 list_head *ptr; struct sockaddr *dst = (struct sockaddr *) extra; dwrq->length = 0; if (down_interruptible(&acl->sem)) return -ERESTARTSYS; for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) { entry = list_entry(ptr, struct mac_entry, _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 list_head *ptr; 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; } for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) { entry = list_entry(ptr, struct mac_entry, _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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -