aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee802154
diff options
context:
space:
mode:
authorWerner Almesberger <werner@almesberger.net>2013-04-04 02:32:35 -0400
committerDavid S. Miller <davem@davemloft.net>2013-04-08 12:00:16 -0400
commit56aa091d60a63fee83d2c894edb69b7c159966c7 (patch)
treedc831be70fe1bbb665da2c97ba57d6e5ce509e84 /net/ieee802154
parentd87c8c6d1562f12df101c5b9857170d110e7353a (diff)
ieee802154/nl-mac.c: make some MLME operations optional
Check for NULL before calling the following operations from "struct ieee802154_mlme_ops": assoc_req, assoc_resp, disassoc_req, start_req, and scan_req. This fixes a current oops where those functions are called but not implemented. It also updates the documentation to clarify that they are now optional by design. If a call to an unimplemented function is attempted, the kernel returns EOPNOTSUPP via netlink. The following operations are still required: get_phy, get_pan_id, get_short_addr, and get_dsn. Note that the places where this patch changes the initialization of "ret" should not affect the rest of the code since "ret" was always set (again) before returning its value. Signed-off-by: Werner Almesberger <werner@almesberger.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ieee802154')
-rw-r--r--net/ieee802154/nl-mac.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c
index 96bb08abece2..b0bdd8c51e9c 100644
--- a/net/ieee802154/nl-mac.c
+++ b/net/ieee802154/nl-mac.c
@@ -315,7 +315,7 @@ static int ieee802154_associate_req(struct sk_buff *skb,
315 struct net_device *dev; 315 struct net_device *dev;
316 struct ieee802154_addr addr; 316 struct ieee802154_addr addr;
317 u8 page; 317 u8 page;
318 int ret = -EINVAL; 318 int ret = -EOPNOTSUPP;
319 319
320 if (!info->attrs[IEEE802154_ATTR_CHANNEL] || 320 if (!info->attrs[IEEE802154_ATTR_CHANNEL] ||
321 !info->attrs[IEEE802154_ATTR_COORD_PAN_ID] || 321 !info->attrs[IEEE802154_ATTR_COORD_PAN_ID] ||
@@ -327,6 +327,8 @@ static int ieee802154_associate_req(struct sk_buff *skb,
327 dev = ieee802154_nl_get_dev(info); 327 dev = ieee802154_nl_get_dev(info);
328 if (!dev) 328 if (!dev)
329 return -ENODEV; 329 return -ENODEV;
330 if (!ieee802154_mlme_ops(dev)->assoc_req)
331 goto out;
330 332
331 if (info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]) { 333 if (info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]) {
332 addr.addr_type = IEEE802154_ADDR_LONG; 334 addr.addr_type = IEEE802154_ADDR_LONG;
@@ -350,6 +352,7 @@ static int ieee802154_associate_req(struct sk_buff *skb,
350 page, 352 page,
351 nla_get_u8(info->attrs[IEEE802154_ATTR_CAPABILITY])); 353 nla_get_u8(info->attrs[IEEE802154_ATTR_CAPABILITY]));
352 354
355out:
353 dev_put(dev); 356 dev_put(dev);
354 return ret; 357 return ret;
355} 358}
@@ -359,7 +362,7 @@ static int ieee802154_associate_resp(struct sk_buff *skb,
359{ 362{
360 struct net_device *dev; 363 struct net_device *dev;
361 struct ieee802154_addr addr; 364 struct ieee802154_addr addr;
362 int ret = -EINVAL; 365 int ret = -EOPNOTSUPP;
363 366
364 if (!info->attrs[IEEE802154_ATTR_STATUS] || 367 if (!info->attrs[IEEE802154_ATTR_STATUS] ||
365 !info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] || 368 !info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] ||
@@ -369,6 +372,8 @@ static int ieee802154_associate_resp(struct sk_buff *skb,
369 dev = ieee802154_nl_get_dev(info); 372 dev = ieee802154_nl_get_dev(info);
370 if (!dev) 373 if (!dev)
371 return -ENODEV; 374 return -ENODEV;
375 if (!ieee802154_mlme_ops(dev)->assoc_resp)
376 goto out;
372 377
373 addr.addr_type = IEEE802154_ADDR_LONG; 378 addr.addr_type = IEEE802154_ADDR_LONG;
374 nla_memcpy(addr.hwaddr, info->attrs[IEEE802154_ATTR_DEST_HW_ADDR], 379 nla_memcpy(addr.hwaddr, info->attrs[IEEE802154_ATTR_DEST_HW_ADDR],
@@ -380,6 +385,7 @@ static int ieee802154_associate_resp(struct sk_buff *skb,
380 nla_get_u16(info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]), 385 nla_get_u16(info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]),
381 nla_get_u8(info->attrs[IEEE802154_ATTR_STATUS])); 386 nla_get_u8(info->attrs[IEEE802154_ATTR_STATUS]));
382 387
388out:
383 dev_put(dev); 389 dev_put(dev);
384 return ret; 390 return ret;
385} 391}
@@ -389,7 +395,7 @@ static int ieee802154_disassociate_req(struct sk_buff *skb,
389{ 395{
390 struct net_device *dev; 396 struct net_device *dev;
391 struct ieee802154_addr addr; 397 struct ieee802154_addr addr;
392 int ret = -EINVAL; 398 int ret = -EOPNOTSUPP;
393 399
394 if ((!info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] && 400 if ((!info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] &&
395 !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]) || 401 !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]) ||
@@ -399,6 +405,8 @@ static int ieee802154_disassociate_req(struct sk_buff *skb,
399 dev = ieee802154_nl_get_dev(info); 405 dev = ieee802154_nl_get_dev(info);
400 if (!dev) 406 if (!dev)
401 return -ENODEV; 407 return -ENODEV;
408 if (!ieee802154_mlme_ops(dev)->disassoc_req)
409 goto out;
402 410
403 if (info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]) { 411 if (info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]) {
404 addr.addr_type = IEEE802154_ADDR_LONG; 412 addr.addr_type = IEEE802154_ADDR_LONG;
@@ -415,6 +423,7 @@ static int ieee802154_disassociate_req(struct sk_buff *skb,
415 ret = ieee802154_mlme_ops(dev)->disassoc_req(dev, &addr, 423 ret = ieee802154_mlme_ops(dev)->disassoc_req(dev, &addr,
416 nla_get_u8(info->attrs[IEEE802154_ATTR_REASON])); 424 nla_get_u8(info->attrs[IEEE802154_ATTR_REASON]));
417 425
426out:
418 dev_put(dev); 427 dev_put(dev);
419 return ret; 428 return ret;
420} 429}
@@ -432,7 +441,7 @@ static int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info)
432 u8 channel, bcn_ord, sf_ord; 441 u8 channel, bcn_ord, sf_ord;
433 u8 page; 442 u8 page;
434 int pan_coord, blx, coord_realign; 443 int pan_coord, blx, coord_realign;
435 int ret; 444 int ret = -EOPNOTSUPP;
436 445
437 if (!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] || 446 if (!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] ||
438 !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR] || 447 !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR] ||
@@ -448,6 +457,8 @@ static int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info)
448 dev = ieee802154_nl_get_dev(info); 457 dev = ieee802154_nl_get_dev(info);
449 if (!dev) 458 if (!dev)
450 return -ENODEV; 459 return -ENODEV;
460 if (!ieee802154_mlme_ops(dev)->start_req)
461 goto out;
451 462
452 addr.addr_type = IEEE802154_ADDR_SHORT; 463 addr.addr_type = IEEE802154_ADDR_SHORT;
453 addr.short_addr = nla_get_u16( 464 addr.short_addr = nla_get_u16(
@@ -476,6 +487,7 @@ static int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info)
476 ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, page, 487 ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, page,
477 bcn_ord, sf_ord, pan_coord, blx, coord_realign); 488 bcn_ord, sf_ord, pan_coord, blx, coord_realign);
478 489
490out:
479 dev_put(dev); 491 dev_put(dev);
480 return ret; 492 return ret;
481} 493}
@@ -483,7 +495,7 @@ static int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info)
483static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info) 495static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info)
484{ 496{
485 struct net_device *dev; 497 struct net_device *dev;
486 int ret; 498 int ret = -EOPNOTSUPP;
487 u8 type; 499 u8 type;
488 u32 channels; 500 u32 channels;
489 u8 duration; 501 u8 duration;
@@ -497,6 +509,8 @@ static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info)
497 dev = ieee802154_nl_get_dev(info); 509 dev = ieee802154_nl_get_dev(info);
498 if (!dev) 510 if (!dev)
499 return -ENODEV; 511 return -ENODEV;
512 if (!ieee802154_mlme_ops(dev)->scan_req)
513 goto out;
500 514
501 type = nla_get_u8(info->attrs[IEEE802154_ATTR_SCAN_TYPE]); 515 type = nla_get_u8(info->attrs[IEEE802154_ATTR_SCAN_TYPE]);
502 channels = nla_get_u32(info->attrs[IEEE802154_ATTR_CHANNELS]); 516 channels = nla_get_u32(info->attrs[IEEE802154_ATTR_CHANNELS]);
@@ -511,6 +525,7 @@ static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info)
511 ret = ieee802154_mlme_ops(dev)->scan_req(dev, type, channels, page, 525 ret = ieee802154_mlme_ops(dev)->scan_req(dev, type, channels, page,
512 duration); 526 duration);
513 527
528out:
514 dev_put(dev); 529 dev_put(dev);
515 return ret; 530 return ret;
516} 531}