Commit 56aa091d authored by Werner Almesberger's avatar Werner Almesberger Committed by David S. Miller

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: default avatarWerner Almesberger <werner@almesberger.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d87c8c6d
...@@ -71,8 +71,9 @@ submits skb to qdisc), so if you need something from that cb later, you should ...@@ -71,8 +71,9 @@ submits skb to qdisc), so if you need something from that cb later, you should
store info in the skb->data on your own. store info in the skb->data on your own.
To hook the MLME interface you have to populate the ml_priv field of your To hook the MLME interface you have to populate the ml_priv field of your
net_device with a pointer to struct ieee802154_mlme_ops instance. All fields are net_device with a pointer to struct ieee802154_mlme_ops instance. The fields
required. assoc_req, assoc_resp, disassoc_req, start_req, and scan_req are optional.
All other fields are required.
We provide an example of simple HardMAC driver at drivers/ieee802154/fakehard.c We provide an example of simple HardMAC driver at drivers/ieee802154/fakehard.c
......
...@@ -85,6 +85,8 @@ struct wpan_phy; ...@@ -85,6 +85,8 @@ struct wpan_phy;
* Use wpan_wpy_put to put that reference. * Use wpan_wpy_put to put that reference.
*/ */
struct ieee802154_mlme_ops { struct ieee802154_mlme_ops {
/* The following fields are optional (can be NULL). */
int (*assoc_req)(struct net_device *dev, int (*assoc_req)(struct net_device *dev,
struct ieee802154_addr *addr, struct ieee802154_addr *addr,
u8 channel, u8 page, u8 cap); u8 channel, u8 page, u8 cap);
...@@ -101,6 +103,8 @@ struct ieee802154_mlme_ops { ...@@ -101,6 +103,8 @@ struct ieee802154_mlme_ops {
int (*scan_req)(struct net_device *dev, int (*scan_req)(struct net_device *dev,
u8 type, u32 channels, u8 page, u8 duration); u8 type, u32 channels, u8 page, u8 duration);
/* The fields below are required. */
struct wpan_phy *(*get_phy)(const struct net_device *dev); struct wpan_phy *(*get_phy)(const struct net_device *dev);
/* /*
......
...@@ -315,7 +315,7 @@ static int ieee802154_associate_req(struct sk_buff *skb, ...@@ -315,7 +315,7 @@ static int ieee802154_associate_req(struct sk_buff *skb,
struct net_device *dev; struct net_device *dev;
struct ieee802154_addr addr; struct ieee802154_addr addr;
u8 page; u8 page;
int ret = -EINVAL; int ret = -EOPNOTSUPP;
if (!info->attrs[IEEE802154_ATTR_CHANNEL] || if (!info->attrs[IEEE802154_ATTR_CHANNEL] ||
!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] || !info->attrs[IEEE802154_ATTR_COORD_PAN_ID] ||
...@@ -327,6 +327,8 @@ static int ieee802154_associate_req(struct sk_buff *skb, ...@@ -327,6 +327,8 @@ static int ieee802154_associate_req(struct sk_buff *skb,
dev = ieee802154_nl_get_dev(info); dev = ieee802154_nl_get_dev(info);
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
if (!ieee802154_mlme_ops(dev)->assoc_req)
goto out;
if (info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]) { if (info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]) {
addr.addr_type = IEEE802154_ADDR_LONG; addr.addr_type = IEEE802154_ADDR_LONG;
...@@ -350,6 +352,7 @@ static int ieee802154_associate_req(struct sk_buff *skb, ...@@ -350,6 +352,7 @@ static int ieee802154_associate_req(struct sk_buff *skb,
page, page,
nla_get_u8(info->attrs[IEEE802154_ATTR_CAPABILITY])); nla_get_u8(info->attrs[IEEE802154_ATTR_CAPABILITY]));
out:
dev_put(dev); dev_put(dev);
return ret; return ret;
} }
...@@ -359,7 +362,7 @@ static int ieee802154_associate_resp(struct sk_buff *skb, ...@@ -359,7 +362,7 @@ static int ieee802154_associate_resp(struct sk_buff *skb,
{ {
struct net_device *dev; struct net_device *dev;
struct ieee802154_addr addr; struct ieee802154_addr addr;
int ret = -EINVAL; int ret = -EOPNOTSUPP;
if (!info->attrs[IEEE802154_ATTR_STATUS] || if (!info->attrs[IEEE802154_ATTR_STATUS] ||
!info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] || !info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] ||
...@@ -369,6 +372,8 @@ static int ieee802154_associate_resp(struct sk_buff *skb, ...@@ -369,6 +372,8 @@ static int ieee802154_associate_resp(struct sk_buff *skb,
dev = ieee802154_nl_get_dev(info); dev = ieee802154_nl_get_dev(info);
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
if (!ieee802154_mlme_ops(dev)->assoc_resp)
goto out;
addr.addr_type = IEEE802154_ADDR_LONG; addr.addr_type = IEEE802154_ADDR_LONG;
nla_memcpy(addr.hwaddr, info->attrs[IEEE802154_ATTR_DEST_HW_ADDR], 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,6 +385,7 @@ static int ieee802154_associate_resp(struct sk_buff *skb,
nla_get_u16(info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]), nla_get_u16(info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]),
nla_get_u8(info->attrs[IEEE802154_ATTR_STATUS])); nla_get_u8(info->attrs[IEEE802154_ATTR_STATUS]));
out:
dev_put(dev); dev_put(dev);
return ret; return ret;
} }
...@@ -389,7 +395,7 @@ static int ieee802154_disassociate_req(struct sk_buff *skb, ...@@ -389,7 +395,7 @@ static int ieee802154_disassociate_req(struct sk_buff *skb,
{ {
struct net_device *dev; struct net_device *dev;
struct ieee802154_addr addr; struct ieee802154_addr addr;
int ret = -EINVAL; int ret = -EOPNOTSUPP;
if ((!info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] && if ((!info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] &&
!info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]) || !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]) ||
...@@ -399,6 +405,8 @@ static int ieee802154_disassociate_req(struct sk_buff *skb, ...@@ -399,6 +405,8 @@ static int ieee802154_disassociate_req(struct sk_buff *skb,
dev = ieee802154_nl_get_dev(info); dev = ieee802154_nl_get_dev(info);
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
if (!ieee802154_mlme_ops(dev)->disassoc_req)
goto out;
if (info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]) { if (info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]) {
addr.addr_type = IEEE802154_ADDR_LONG; addr.addr_type = IEEE802154_ADDR_LONG;
...@@ -415,6 +423,7 @@ static int ieee802154_disassociate_req(struct sk_buff *skb, ...@@ -415,6 +423,7 @@ static int ieee802154_disassociate_req(struct sk_buff *skb,
ret = ieee802154_mlme_ops(dev)->disassoc_req(dev, &addr, ret = ieee802154_mlme_ops(dev)->disassoc_req(dev, &addr,
nla_get_u8(info->attrs[IEEE802154_ATTR_REASON])); nla_get_u8(info->attrs[IEEE802154_ATTR_REASON]));
out:
dev_put(dev); dev_put(dev);
return ret; return ret;
} }
...@@ -432,7 +441,7 @@ static int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) ...@@ -432,7 +441,7 @@ static int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info)
u8 channel, bcn_ord, sf_ord; u8 channel, bcn_ord, sf_ord;
u8 page; u8 page;
int pan_coord, blx, coord_realign; int pan_coord, blx, coord_realign;
int ret; int ret = -EOPNOTSUPP;
if (!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] || if (!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] ||
!info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR] || !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,6 +457,8 @@ static int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info)
dev = ieee802154_nl_get_dev(info); dev = ieee802154_nl_get_dev(info);
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
if (!ieee802154_mlme_ops(dev)->start_req)
goto out;
addr.addr_type = IEEE802154_ADDR_SHORT; addr.addr_type = IEEE802154_ADDR_SHORT;
addr.short_addr = nla_get_u16( addr.short_addr = nla_get_u16(
...@@ -476,6 +487,7 @@ static int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) ...@@ -476,6 +487,7 @@ static int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info)
ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, page, ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, page,
bcn_ord, sf_ord, pan_coord, blx, coord_realign); bcn_ord, sf_ord, pan_coord, blx, coord_realign);
out:
dev_put(dev); dev_put(dev);
return ret; return ret;
} }
...@@ -483,7 +495,7 @@ static int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) ...@@ -483,7 +495,7 @@ static int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info)
static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info) static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info)
{ {
struct net_device *dev; struct net_device *dev;
int ret; int ret = -EOPNOTSUPP;
u8 type; u8 type;
u32 channels; u32 channels;
u8 duration; u8 duration;
...@@ -497,6 +509,8 @@ static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info) ...@@ -497,6 +509,8 @@ static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info)
dev = ieee802154_nl_get_dev(info); dev = ieee802154_nl_get_dev(info);
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
if (!ieee802154_mlme_ops(dev)->scan_req)
goto out;
type = nla_get_u8(info->attrs[IEEE802154_ATTR_SCAN_TYPE]); type = nla_get_u8(info->attrs[IEEE802154_ATTR_SCAN_TYPE]);
channels = nla_get_u32(info->attrs[IEEE802154_ATTR_CHANNELS]); 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,6 +525,7 @@ static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info)
ret = ieee802154_mlme_ops(dev)->scan_req(dev, type, channels, page, ret = ieee802154_mlme_ops(dev)->scan_req(dev, type, channels, page,
duration); duration);
out:
dev_put(dev); dev_put(dev);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment