aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-07-08 07:29:08 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-24 15:05:09 -0400
commitb9454e83cac42fcdc90bfbfba479132bd6629455 (patch)
tree4f63180e1406f8b799ee6b2fca2efe4a656c2905 /net/wireless
parent10c836d7896e9d7b683a76f3cac3c289d8da72ef (diff)
nl80211: introduce new key attributes
We will soon want to nest key attributes into some new attribute for configuring static WEP keys at connect() and ibss_join() time, so we need nested attributes for that. However, key attributes right now are 'global'. This patch thus introduces new nested attributes for the key settings and functions for parsing them. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/nl80211.c203
1 files changed, 156 insertions, 47 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index a00fd644370b..50cf59316292 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -73,6 +73,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
73 [NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN }, 73 [NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN },
74 [NL80211_ATTR_PREV_BSSID] = { .type = NLA_BINARY, .len = ETH_ALEN }, 74 [NL80211_ATTR_PREV_BSSID] = { .type = NLA_BINARY, .len = ETH_ALEN },
75 75
76 [NL80211_ATTR_KEY] = { .type = NLA_NESTED, },
76 [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY, 77 [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
77 .len = WLAN_MAX_KEY_LEN }, 78 .len = WLAN_MAX_KEY_LEN },
78 [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 }, 79 [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 },
@@ -134,6 +135,18 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
134 [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, 135 [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
135}; 136};
136 137
138/* policy for the attributes */
139static struct nla_policy
140nl80211_key_policy[NL80211_KEY_MAX + 1] __read_mostly = {
141 [NL80211_KEY_DATA] = { .type = NLA_BINARY,
142 .len = WLAN_MAX_KEY_LEN },
143 [NL80211_KEY_IDX] = { .type = NLA_U8 },
144 [NL80211_KEY_CIPHER] = { .type = NLA_U32 },
145 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 },
146 [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
147 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
148};
149
137/* IE validation */ 150/* IE validation */
138static bool is_valid_ie_attr(const struct nlattr *attr) 151static bool is_valid_ie_attr(const struct nlattr *attr)
139{ 152{
@@ -198,6 +211,100 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
198 211
199/* netlink command implementations */ 212/* netlink command implementations */
200 213
214struct key_parse {
215 struct key_params p;
216 int idx;
217 bool def, defmgmt;
218};
219
220static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k)
221{
222 struct nlattr *tb[NL80211_KEY_MAX + 1];
223 int err = nla_parse_nested(tb, NL80211_KEY_MAX, key,
224 nl80211_key_policy);
225 if (err)
226 return err;
227
228 k->def = !!tb[NL80211_KEY_DEFAULT];
229 k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT];
230
231 if (tb[NL80211_KEY_IDX])
232 k->idx = nla_get_u8(tb[NL80211_KEY_IDX]);
233
234 if (tb[NL80211_KEY_DATA]) {
235 k->p.key = nla_data(tb[NL80211_KEY_DATA]);
236 k->p.key_len = nla_len(tb[NL80211_KEY_DATA]);
237 }
238
239 if (tb[NL80211_KEY_SEQ]) {
240 k->p.seq = nla_data(tb[NL80211_KEY_SEQ]);
241 k->p.seq_len = nla_len(tb[NL80211_KEY_SEQ]);
242 }
243
244 if (tb[NL80211_KEY_CIPHER])
245 k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]);
246
247 return 0;
248}
249
250static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k)
251{
252 if (info->attrs[NL80211_ATTR_KEY_DATA]) {
253 k->p.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
254 k->p.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
255 }
256
257 if (info->attrs[NL80211_ATTR_KEY_SEQ]) {
258 k->p.seq = nla_data(info->attrs[NL80211_ATTR_KEY_SEQ]);
259 k->p.seq_len = nla_len(info->attrs[NL80211_ATTR_KEY_SEQ]);
260 }
261
262 if (info->attrs[NL80211_ATTR_KEY_IDX])
263 k->idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
264
265 if (info->attrs[NL80211_ATTR_KEY_CIPHER])
266 k->p.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
267
268 k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT];
269 k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT];
270
271 return 0;
272}
273
274static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
275{
276 int err;
277
278 memset(k, 0, sizeof(*k));
279 k->idx = -1;
280
281 if (info->attrs[NL80211_ATTR_KEY])
282 err = nl80211_parse_key_new(info->attrs[NL80211_ATTR_KEY], k);
283 else
284 err = nl80211_parse_key_old(info, k);
285
286 if (err)
287 return err;
288
289 if (k->def && k->defmgmt)
290 return -EINVAL;
291
292 if (k->idx != -1) {
293 if (k->defmgmt) {
294 if (k->idx < 4 || k->idx > 5)
295 return -EINVAL;
296 } else if (k->def) {
297 if (k->idx < 0 || k->idx > 3)
298 return -EINVAL;
299 } else {
300 if (k->idx < 0 || k->idx > 5)
301 return -EINVAL;
302 }
303 }
304
305 return 0;
306}
307
201static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, 308static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
202 struct cfg80211_registered_device *dev) 309 struct cfg80211_registered_device *dev)
203{ 310{
@@ -943,10 +1050,12 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
943struct get_key_cookie { 1050struct get_key_cookie {
944 struct sk_buff *msg; 1051 struct sk_buff *msg;
945 int error; 1052 int error;
1053 int idx;
946}; 1054};
947 1055
948static void get_key_callback(void *c, struct key_params *params) 1056static void get_key_callback(void *c, struct key_params *params)
949{ 1057{
1058 struct nlattr *key;
950 struct get_key_cookie *cookie = c; 1059 struct get_key_cookie *cookie = c;
951 1060
952 if (params->key) 1061 if (params->key)
@@ -961,6 +1070,26 @@ static void get_key_callback(void *c, struct key_params *params)
961 NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER, 1070 NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
962 params->cipher); 1071 params->cipher);
963 1072
1073 key = nla_nest_start(cookie->msg, NL80211_ATTR_KEY);
1074 if (!key)
1075 goto nla_put_failure;
1076
1077 if (params->key)
1078 NLA_PUT(cookie->msg, NL80211_KEY_DATA,
1079 params->key_len, params->key);
1080
1081 if (params->seq)
1082 NLA_PUT(cookie->msg, NL80211_KEY_SEQ,
1083 params->seq_len, params->seq);
1084
1085 if (params->cipher)
1086 NLA_PUT_U32(cookie->msg, NL80211_KEY_CIPHER,
1087 params->cipher);
1088
1089 NLA_PUT_U8(cookie->msg, NL80211_ATTR_KEY_IDX, cookie->idx);
1090
1091 nla_nest_end(cookie->msg, key);
1092
964 return; 1093 return;
965 nla_put_failure: 1094 nla_put_failure:
966 cookie->error = 1; 1095 cookie->error = 1;
@@ -1014,6 +1143,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
1014 } 1143 }
1015 1144
1016 cookie.msg = msg; 1145 cookie.msg = msg;
1146 cookie.idx = key_idx;
1017 1147
1018 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); 1148 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
1019 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx); 1149 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
@@ -1049,26 +1179,21 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
1049static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) 1179static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
1050{ 1180{
1051 struct cfg80211_registered_device *rdev; 1181 struct cfg80211_registered_device *rdev;
1182 struct key_parse key;
1052 int err; 1183 int err;
1053 struct net_device *dev; 1184 struct net_device *dev;
1054 u8 key_idx;
1055 int (*func)(struct wiphy *wiphy, struct net_device *netdev, 1185 int (*func)(struct wiphy *wiphy, struct net_device *netdev,
1056 u8 key_index); 1186 u8 key_index);
1057 1187
1058 if (!info->attrs[NL80211_ATTR_KEY_IDX]) 1188 err = nl80211_parse_key(info, &key);
1059 return -EINVAL; 1189 if (err)
1060 1190 return err;
1061 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
1062 1191
1063 if (info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]) { 1192 if (key.idx < 0)
1064 if (key_idx < 4 || key_idx > 5)
1065 return -EINVAL;
1066 } else if (key_idx > 3)
1067 return -EINVAL; 1193 return -EINVAL;
1068 1194
1069 /* currently only support setting default key */ 1195 /* only support setting default key */
1070 if (!info->attrs[NL80211_ATTR_KEY_DEFAULT] && 1196 if (!key.def && !key.defmgmt)
1071 !info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT])
1072 return -EINVAL; 1197 return -EINVAL;
1073 1198
1074 rtnl_lock(); 1199 rtnl_lock();
@@ -1077,7 +1202,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
1077 if (err) 1202 if (err)
1078 goto unlock_rtnl; 1203 goto unlock_rtnl;
1079 1204
1080 if (info->attrs[NL80211_ATTR_KEY_DEFAULT]) 1205 if (key.def)
1081 func = rdev->ops->set_default_key; 1206 func = rdev->ops->set_default_key;
1082 else 1207 else
1083 func = rdev->ops->set_default_mgmt_key; 1208 func = rdev->ops->set_default_mgmt_key;
@@ -1087,13 +1212,13 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
1087 goto out; 1212 goto out;
1088 } 1213 }
1089 1214
1090 err = func(&rdev->wiphy, dev, key_idx); 1215 err = func(&rdev->wiphy, dev, key.idx);
1091#ifdef CONFIG_WIRELESS_EXT 1216#ifdef CONFIG_WIRELESS_EXT
1092 if (!err) { 1217 if (!err) {
1093 if (func == rdev->ops->set_default_key) 1218 if (func == rdev->ops->set_default_key)
1094 dev->ieee80211_ptr->wext.default_key = key_idx; 1219 dev->ieee80211_ptr->wext.default_key = key.idx;
1095 else 1220 else
1096 dev->ieee80211_ptr->wext.default_mgmt_key = key_idx; 1221 dev->ieee80211_ptr->wext.default_mgmt_key = key.idx;
1097 } 1222 }
1098#endif 1223#endif
1099 1224
@@ -1112,34 +1237,20 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
1112 struct cfg80211_registered_device *rdev; 1237 struct cfg80211_registered_device *rdev;
1113 int err, i; 1238 int err, i;
1114 struct net_device *dev; 1239 struct net_device *dev;
1115 struct key_params params; 1240 struct key_parse key;
1116 u8 key_idx = 0;
1117 u8 *mac_addr = NULL; 1241 u8 *mac_addr = NULL;
1118 1242
1119 memset(&params, 0, sizeof(params)); 1243 err = nl80211_parse_key(info, &key);
1244 if (err)
1245 return err;
1120 1246
1121 if (!info->attrs[NL80211_ATTR_KEY_CIPHER]) 1247 if (!key.p.key)
1122 return -EINVAL; 1248 return -EINVAL;
1123 1249
1124 if (info->attrs[NL80211_ATTR_KEY_DATA]) {
1125 params.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
1126 params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
1127 }
1128
1129 if (info->attrs[NL80211_ATTR_KEY_SEQ]) {
1130 params.seq = nla_data(info->attrs[NL80211_ATTR_KEY_SEQ]);
1131 params.seq_len = nla_len(info->attrs[NL80211_ATTR_KEY_SEQ]);
1132 }
1133
1134 if (info->attrs[NL80211_ATTR_KEY_IDX])
1135 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
1136
1137 params.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
1138
1139 if (info->attrs[NL80211_ATTR_MAC]) 1250 if (info->attrs[NL80211_ATTR_MAC])
1140 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1251 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1141 1252
1142 if (cfg80211_validate_key_settings(&params, key_idx, mac_addr)) 1253 if (cfg80211_validate_key_settings(&key.p, key.idx, mac_addr))
1143 return -EINVAL; 1254 return -EINVAL;
1144 1255
1145 rtnl_lock(); 1256 rtnl_lock();
@@ -1149,7 +1260,7 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
1149 goto unlock_rtnl; 1260 goto unlock_rtnl;
1150 1261
1151 for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) 1262 for (i = 0; i < rdev->wiphy.n_cipher_suites; i++)
1152 if (params.cipher == rdev->wiphy.cipher_suites[i]) 1263 if (key.p.cipher == rdev->wiphy.cipher_suites[i])
1153 break; 1264 break;
1154 if (i == rdev->wiphy.n_cipher_suites) { 1265 if (i == rdev->wiphy.n_cipher_suites) {
1155 err = -EINVAL; 1266 err = -EINVAL;
@@ -1161,7 +1272,7 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
1161 goto out; 1272 goto out;
1162 } 1273 }
1163 1274
1164 err = rdev->ops->add_key(&rdev->wiphy, dev, key_idx, mac_addr, &params); 1275 err = rdev->ops->add_key(&rdev->wiphy, dev, key.idx, mac_addr, &key.p);
1165 1276
1166 out: 1277 out:
1167 cfg80211_unlock_rdev(rdev); 1278 cfg80211_unlock_rdev(rdev);
@@ -1177,14 +1288,12 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
1177 struct cfg80211_registered_device *rdev; 1288 struct cfg80211_registered_device *rdev;
1178 int err; 1289 int err;
1179 struct net_device *dev; 1290 struct net_device *dev;
1180 u8 key_idx = 0;
1181 u8 *mac_addr = NULL; 1291 u8 *mac_addr = NULL;
1292 struct key_parse key;
1182 1293
1183 if (info->attrs[NL80211_ATTR_KEY_IDX]) 1294 err = nl80211_parse_key(info, &key);
1184 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); 1295 if (err)
1185 1296 return err;
1186 if (key_idx > 5)
1187 return -EINVAL;
1188 1297
1189 if (info->attrs[NL80211_ATTR_MAC]) 1298 if (info->attrs[NL80211_ATTR_MAC])
1190 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1299 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
@@ -1200,13 +1309,13 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
1200 goto out; 1309 goto out;
1201 } 1310 }
1202 1311
1203 err = rdev->ops->del_key(&rdev->wiphy, dev, key_idx, mac_addr); 1312 err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, mac_addr);
1204 1313
1205#ifdef CONFIG_WIRELESS_EXT 1314#ifdef CONFIG_WIRELESS_EXT
1206 if (!err) { 1315 if (!err) {
1207 if (key_idx == dev->ieee80211_ptr->wext.default_key) 1316 if (key.idx == dev->ieee80211_ptr->wext.default_key)
1208 dev->ieee80211_ptr->wext.default_key = -1; 1317 dev->ieee80211_ptr->wext.default_key = -1;
1209 else if (key_idx == dev->ieee80211_ptr->wext.default_mgmt_key) 1318 else if (key.idx == dev->ieee80211_ptr->wext.default_mgmt_key)
1210 dev->ieee80211_ptr->wext.default_mgmt_key = -1; 1319 dev->ieee80211_ptr->wext.default_mgmt_key = -1;
1211 } 1320 }
1212#endif 1321#endif