Merge tag 'platform-drivers-x86-v4.4-1' of git://git.infradead.org/users/dvhart/linux...
[linux-2.6-block.git] / net / mac80211 / debugfs_key.c
index 702ca122c498938691842d95db7732d6d8c6d6bb..7961e7d0b61e1ee48700e9a7ef2db8feec84814f 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright 2003-2005 Devicescape Software, Inc.
  * Copyright (c) 2006  Jiri Benc <jbenc@suse.cz>
  * Copyright 2007      Johannes Berg <johannes@sipsolutions.net>
+ * Copyright (C) 2015  Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -34,6 +35,14 @@ static const struct file_operations key_ ##name## _ops = {           \
        .llseek = generic_file_llseek,                                  \
 }
 
+#define KEY_OPS_W(name)                                                        \
+static const struct file_operations key_ ##name## _ops = {             \
+       .read = key_##name##_read,                                      \
+       .write = key_##name##_write,                                    \
+       .open = simple_open,                                            \
+       .llseek = generic_file_llseek,                                  \
+}
+
 #define KEY_FILE(name, format)                                         \
                 KEY_READ_##format(name)                                \
                 KEY_OPS(name)
@@ -74,6 +83,41 @@ static ssize_t key_algorithm_read(struct file *file,
 }
 KEY_OPS(algorithm);
 
+static ssize_t key_tx_spec_write(struct file *file, const char __user *userbuf,
+                                size_t count, loff_t *ppos)
+{
+       struct ieee80211_key *key = file->private_data;
+       u64 pn;
+       int ret;
+
+       switch (key->conf.cipher) {
+       case WLAN_CIPHER_SUITE_WEP40:
+       case WLAN_CIPHER_SUITE_WEP104:
+               return -EINVAL;
+       case WLAN_CIPHER_SUITE_TKIP:
+               /* not supported yet */
+               return -EOPNOTSUPP;
+       case WLAN_CIPHER_SUITE_CCMP:
+       case WLAN_CIPHER_SUITE_CCMP_256:
+       case WLAN_CIPHER_SUITE_AES_CMAC:
+       case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+       case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+       case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+       case WLAN_CIPHER_SUITE_GCMP:
+       case WLAN_CIPHER_SUITE_GCMP_256:
+               ret = kstrtou64_from_user(userbuf, count, 16, &pn);
+               if (ret)
+                       return ret;
+               /* PN is a 48-bit counter */
+               if (pn >= (1ULL << 48))
+                       return -ERANGE;
+               atomic64_set(&key->conf.tx_pn, pn);
+               return count;
+       default:
+               return 0;
+       }
+}
+
 static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
                                size_t count, loff_t *ppos)
 {
@@ -110,7 +154,7 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
        }
        return simple_read_from_buffer(userbuf, count, ppos, buf, len);
 }
-KEY_OPS(tx_spec);
+KEY_OPS_W(tx_spec);
 
 static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
                                size_t count, loff_t *ppos)
@@ -278,6 +322,9 @@ KEY_OPS(key);
 #define DEBUGFS_ADD(name) \
        debugfs_create_file(#name, 0400, key->debugfs.dir, \
                            key, &key_##name##_ops);
+#define DEBUGFS_ADD_W(name) \
+       debugfs_create_file(#name, 0600, key->debugfs.dir, \
+                           key, &key_##name##_ops);
 
 void ieee80211_debugfs_key_add(struct ieee80211_key *key)
 {
@@ -310,7 +357,7 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key)
        DEBUGFS_ADD(keyidx);
        DEBUGFS_ADD(hw_key_idx);
        DEBUGFS_ADD(algorithm);
-       DEBUGFS_ADD(tx_spec);
+       DEBUGFS_ADD_W(tx_spec);
        DEBUGFS_ADD(rx_spec);
        DEBUGFS_ADD(replays);
        DEBUGFS_ADD(icverrors);