Commit 56aa091d60a63fee83d2c894edb69b7c159966c7

Authored by Werner Almesberger
Committed by David S. Miller
1 parent d87c8c6d15

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>

Showing 3 changed files with 27 additions and 7 deletions Side-by-side Diff

Documentation/networking/ieee802154.txt
... ... @@ -71,8 +71,9 @@
71 71 store info in the skb->data on your own.
72 72  
73 73 To hook the MLME interface you have to populate the ml_priv field of your
74   -net_device with a pointer to struct ieee802154_mlme_ops instance. All fields are
75   -required.
  74 +net_device with a pointer to struct ieee802154_mlme_ops instance. The fields
  75 +assoc_req, assoc_resp, disassoc_req, start_req, and scan_req are optional.
  76 +All other fields are required.
76 77  
77 78 We provide an example of simple HardMAC driver at drivers/ieee802154/fakehard.c
78 79  
include/net/ieee802154_netdev.h
... ... @@ -85,6 +85,8 @@
85 85 * Use wpan_wpy_put to put that reference.
86 86 */
87 87 struct ieee802154_mlme_ops {
  88 + /* The following fields are optional (can be NULL). */
  89 +
88 90 int (*assoc_req)(struct net_device *dev,
89 91 struct ieee802154_addr *addr,
90 92 u8 channel, u8 page, u8 cap);
... ... @@ -100,6 +102,8 @@
100 102 u8 pan_coord, u8 blx, u8 coord_realign);
101 103 int (*scan_req)(struct net_device *dev,
102 104 u8 type, u32 channels, u8 page, u8 duration);
  105 +
  106 + /* The fields below are required. */
103 107  
104 108 struct wpan_phy *(*get_phy)(const struct net_device *dev);
105 109  
net/ieee802154/nl-mac.c
... ... @@ -315,7 +315,7 @@
315 315 struct net_device *dev;
316 316 struct ieee802154_addr addr;
317 317 u8 page;
318   - int ret = -EINVAL;
  318 + int ret = -EOPNOTSUPP;
319 319  
320 320 if (!info->attrs[IEEE802154_ATTR_CHANNEL] ||
321 321 !info->attrs[IEEE802154_ATTR_COORD_PAN_ID] ||
... ... @@ -327,6 +327,8 @@
327 327 dev = ieee802154_nl_get_dev(info);
328 328 if (!dev)
329 329 return -ENODEV;
  330 + if (!ieee802154_mlme_ops(dev)->assoc_req)
  331 + goto out;
330 332  
331 333 if (info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]) {
332 334 addr.addr_type = IEEE802154_ADDR_LONG;
... ... @@ -350,6 +352,7 @@
350 352 page,
351 353 nla_get_u8(info->attrs[IEEE802154_ATTR_CAPABILITY]));
352 354  
  355 +out:
353 356 dev_put(dev);
354 357 return ret;
355 358 }
... ... @@ -359,7 +362,7 @@
359 362 {
360 363 struct net_device *dev;
361 364 struct ieee802154_addr addr;
362   - int ret = -EINVAL;
  365 + int ret = -EOPNOTSUPP;
363 366  
364 367 if (!info->attrs[IEEE802154_ATTR_STATUS] ||
365 368 !info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] ||
... ... @@ -369,6 +372,8 @@
369 372 dev = ieee802154_nl_get_dev(info);
370 373 if (!dev)
371 374 return -ENODEV;
  375 + if (!ieee802154_mlme_ops(dev)->assoc_resp)
  376 + goto out;
372 377  
373 378 addr.addr_type = IEEE802154_ADDR_LONG;
374 379 nla_memcpy(addr.hwaddr, info->attrs[IEEE802154_ATTR_DEST_HW_ADDR],
... ... @@ -380,6 +385,7 @@
380 385 nla_get_u16(info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]),
381 386 nla_get_u8(info->attrs[IEEE802154_ATTR_STATUS]));
382 387  
  388 +out:
383 389 dev_put(dev);
384 390 return ret;
385 391 }
... ... @@ -389,7 +395,7 @@
389 395 {
390 396 struct net_device *dev;
391 397 struct ieee802154_addr addr;
392   - int ret = -EINVAL;
  398 + int ret = -EOPNOTSUPP;
393 399  
394 400 if ((!info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] &&
395 401 !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]) ||
... ... @@ -399,6 +405,8 @@
399 405 dev = ieee802154_nl_get_dev(info);
400 406 if (!dev)
401 407 return -ENODEV;
  408 + if (!ieee802154_mlme_ops(dev)->disassoc_req)
  409 + goto out;
402 410  
403 411 if (info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]) {
404 412 addr.addr_type = IEEE802154_ADDR_LONG;
... ... @@ -415,6 +423,7 @@
415 423 ret = ieee802154_mlme_ops(dev)->disassoc_req(dev, &addr,
416 424 nla_get_u8(info->attrs[IEEE802154_ATTR_REASON]));
417 425  
  426 +out:
418 427 dev_put(dev);
419 428 return ret;
420 429 }
... ... @@ -432,7 +441,7 @@
432 441 u8 channel, bcn_ord, sf_ord;
433 442 u8 page;
434 443 int pan_coord, blx, coord_realign;
435   - int ret;
  444 + int ret = -EOPNOTSUPP;
436 445  
437 446 if (!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] ||
438 447 !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR] ||
... ... @@ -448,6 +457,8 @@
448 457 dev = ieee802154_nl_get_dev(info);
449 458 if (!dev)
450 459 return -ENODEV;
  460 + if (!ieee802154_mlme_ops(dev)->start_req)
  461 + goto out;
451 462  
452 463 addr.addr_type = IEEE802154_ADDR_SHORT;
453 464 addr.short_addr = nla_get_u16(
... ... @@ -476,6 +487,7 @@
476 487 ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, page,
477 488 bcn_ord, sf_ord, pan_coord, blx, coord_realign);
478 489  
  490 +out:
479 491 dev_put(dev);
480 492 return ret;
481 493 }
... ... @@ -483,7 +495,7 @@
483 495 static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info)
484 496 {
485 497 struct net_device *dev;
486   - int ret;
  498 + int ret = -EOPNOTSUPP;
487 499 u8 type;
488 500 u32 channels;
489 501 u8 duration;
... ... @@ -497,6 +509,8 @@
497 509 dev = ieee802154_nl_get_dev(info);
498 510 if (!dev)
499 511 return -ENODEV;
  512 + if (!ieee802154_mlme_ops(dev)->scan_req)
  513 + goto out;
500 514  
501 515 type = nla_get_u8(info->attrs[IEEE802154_ATTR_SCAN_TYPE]);
502 516 channels = nla_get_u32(info->attrs[IEEE802154_ATTR_CHANNELS]);
... ... @@ -511,6 +525,7 @@
511 525 ret = ieee802154_mlme_ops(dev)->scan_req(dev, type, channels, page,
512 526 duration);
513 527  
  528 +out:
514 529 dev_put(dev);
515 530 return ret;
516 531 }