Commit 56aa091d60a63fee83d2c894edb69b7c159966c7
Committed by
David S. Miller
1 parent
d87c8c6d15
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
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 | } |