diff options
author | colin@cozybit.com <colin@cozybit.com> | 2008-10-21 15:03:48 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-10-31 19:00:39 -0400 |
commit | 93da9cc17c5ae8a751886fd4732db89ad5e9bdb9 (patch) | |
tree | 5c8c16eaeca4c6e4555682a4ab1b448cdbe21595 | |
parent | 4a68ec535ef1043319928f601d633f78e650a16f (diff) |
Add nl80211 commands to get and set o11s mesh networking parameters
The two new commands are NL80211_CMD_GET_MESH_PARAMS and
NL80211_CMD_SET_MESH_PARAMS. There is a new attribute enum,
NL80211_ATTR_MESH_PARAMS, which enumerates the various mesh configuration
parameters.
Moved struct mesh_config from mac80211/ieee80211_i.h to net/cfg80211.h.
nl80211_get_mesh_params and nl80211_set_mesh_params unpack the netlink messages
and ask the driver to get or set the configuration. This is done via two new
function stubs, get_mesh_params and set_mesh_params, in struct cfg80211_ops.
Signed-off-by: Colin McCabe <colin@cozybit.com>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | include/linux/nl80211.h | 86 | ||||
-rw-r--r-- | include/net/cfg80211.h | 32 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 68 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 21 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 191 |
5 files changed, 377 insertions, 21 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 41720d47d618..e4cc7869b22f 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -106,6 +106,12 @@ | |||
106 | * to the the specified ISO/IEC 3166-1 alpha2 country code. The core will | 106 | * to the the specified ISO/IEC 3166-1 alpha2 country code. The core will |
107 | * store this as a valid request and then query userspace for it. | 107 | * store this as a valid request and then query userspace for it. |
108 | * | 108 | * |
109 | * @NL80211_CMD_GET_MESH_PARAMS: Get mesh networking properties for the | ||
110 | * interface identified by %NL80211_ATTR_IFINDEX | ||
111 | * | ||
112 | * @NL80211_CMD_SET_MESH_PARAMS: Set mesh networking properties for the | ||
113 | * interface identified by %NL80211_ATTR_IFINDEX | ||
114 | * | ||
109 | * @NL80211_CMD_MAX: highest used command number | 115 | * @NL80211_CMD_MAX: highest used command number |
110 | * @__NL80211_CMD_AFTER_LAST: internal use | 116 | * @__NL80211_CMD_AFTER_LAST: internal use |
111 | */ | 117 | */ |
@@ -148,6 +154,9 @@ enum nl80211_commands { | |||
148 | NL80211_CMD_SET_REG, | 154 | NL80211_CMD_SET_REG, |
149 | NL80211_CMD_REQ_SET_REG, | 155 | NL80211_CMD_REQ_SET_REG, |
150 | 156 | ||
157 | NL80211_CMD_GET_MESH_PARAMS, | ||
158 | NL80211_CMD_SET_MESH_PARAMS, | ||
159 | |||
151 | /* add new commands above here */ | 160 | /* add new commands above here */ |
152 | 161 | ||
153 | /* used to define NL80211_CMD_MAX below */ | 162 | /* used to define NL80211_CMD_MAX below */ |
@@ -296,6 +305,8 @@ enum nl80211_attrs { | |||
296 | NL80211_ATTR_REG_ALPHA2, | 305 | NL80211_ATTR_REG_ALPHA2, |
297 | NL80211_ATTR_REG_RULES, | 306 | NL80211_ATTR_REG_RULES, |
298 | 307 | ||
308 | NL80211_ATTR_MESH_PARAMS, | ||
309 | |||
299 | /* add attributes here, update the policy in nl80211.c */ | 310 | /* add attributes here, update the policy in nl80211.c */ |
300 | 311 | ||
301 | __NL80211_ATTR_AFTER_LAST, | 312 | __NL80211_ATTR_AFTER_LAST, |
@@ -606,4 +617,79 @@ enum nl80211_mntr_flags { | |||
606 | NL80211_MNTR_FLAG_MAX = __NL80211_MNTR_FLAG_AFTER_LAST - 1 | 617 | NL80211_MNTR_FLAG_MAX = __NL80211_MNTR_FLAG_AFTER_LAST - 1 |
607 | }; | 618 | }; |
608 | 619 | ||
620 | /** | ||
621 | * enum nl80211_meshconf_params - mesh configuration parameters | ||
622 | * | ||
623 | * Mesh configuration parameters | ||
624 | * | ||
625 | * @__NL80211_MESHCONF_INVALID: internal use | ||
626 | * | ||
627 | * @NL80211_MESHCONF_RETRY_TIMEOUT: specifies the initial retry timeout in | ||
628 | * millisecond units, used by the Peer Link Open message | ||
629 | * | ||
630 | * @NL80211_MESHCONF_CONFIRM_TIMEOUT: specifies the inital confirm timeout, in | ||
631 | * millisecond units, used by the peer link management to close a peer link | ||
632 | * | ||
633 | * @NL80211_MESHCONF_HOLDING_TIMEOUT: specifies the holding timeout, in | ||
634 | * millisecond units | ||
635 | * | ||
636 | * @NL80211_MESHCONF_MAX_PEER_LINKS: maximum number of peer links allowed | ||
637 | * on this mesh interface | ||
638 | * | ||
639 | * @NL80211_MESHCONF_MAX_RETRIES: specifies the maximum number of peer link | ||
640 | * open retries that can be sent to establish a new peer link instance in a | ||
641 | * mesh | ||
642 | * | ||
643 | * @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh | ||
644 | * point. | ||
645 | * | ||
646 | * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically | ||
647 | * open peer links when we detect compatible mesh peers. | ||
648 | * | ||
649 | * @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames | ||
650 | * containing a PREQ that an MP can send to a particular destination (path | ||
651 | * target) | ||
652 | * | ||
653 | * @NL80211_MESHCONF_PATH_REFRESH_TIME: how frequently to refresh mesh paths | ||
654 | * (in milliseconds) | ||
655 | * | ||
656 | * @NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT: minimum length of time to wait | ||
657 | * until giving up on a path discovery (in milliseconds) | ||
658 | * | ||
659 | * @NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT: The time (in TUs) for which mesh | ||
660 | * points receiving a PREQ shall consider the forwarding information from the | ||
661 | * root to be valid. (TU = time unit) | ||
662 | * | ||
663 | * @NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL: The minimum interval of time (in | ||
664 | * TUs) during which an MP can send only one action frame containing a PREQ | ||
665 | * reference element | ||
666 | * | ||
667 | * @NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME: The interval of time (in TUs) | ||
668 | * that it takes for an HWMP information element to propagate across the mesh | ||
669 | * | ||
670 | * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute | ||
671 | * | ||
672 | * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use | ||
673 | */ | ||
674 | enum nl80211_meshconf_params { | ||
675 | __NL80211_MESHCONF_INVALID, | ||
676 | NL80211_MESHCONF_RETRY_TIMEOUT, | ||
677 | NL80211_MESHCONF_CONFIRM_TIMEOUT, | ||
678 | NL80211_MESHCONF_HOLDING_TIMEOUT, | ||
679 | NL80211_MESHCONF_MAX_PEER_LINKS, | ||
680 | NL80211_MESHCONF_MAX_RETRIES, | ||
681 | NL80211_MESHCONF_TTL, | ||
682 | NL80211_MESHCONF_AUTO_OPEN_PLINKS, | ||
683 | NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, | ||
684 | NL80211_MESHCONF_PATH_REFRESH_TIME, | ||
685 | NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, | ||
686 | NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, | ||
687 | NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, | ||
688 | NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, | ||
689 | |||
690 | /* keep last */ | ||
691 | __NL80211_MESHCONF_ATTR_AFTER_LAST, | ||
692 | NL80211_MESHCONF_ATTR_MAX = __NL80211_MESHCONF_ATTR_AFTER_LAST - 1 | ||
693 | }; | ||
694 | |||
609 | #endif /* __LINUX_NL80211_H */ | 695 | #endif /* __LINUX_NL80211_H */ |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 0e85ec39b638..03e1e88c6a09 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -347,6 +347,25 @@ struct ieee80211_regdomain { | |||
347 | .flags = reg_flags, \ | 347 | .flags = reg_flags, \ |
348 | } | 348 | } |
349 | 349 | ||
350 | struct mesh_config { | ||
351 | /* Timeouts in ms */ | ||
352 | /* Mesh plink management parameters */ | ||
353 | u16 dot11MeshRetryTimeout; | ||
354 | u16 dot11MeshConfirmTimeout; | ||
355 | u16 dot11MeshHoldingTimeout; | ||
356 | u16 dot11MeshMaxPeerLinks; | ||
357 | u8 dot11MeshMaxRetries; | ||
358 | u8 dot11MeshTTL; | ||
359 | bool auto_open_plinks; | ||
360 | /* HWMP parameters */ | ||
361 | u8 dot11MeshHWMPmaxPREQretries; | ||
362 | u32 path_refresh_time; | ||
363 | u16 min_discovery_timeout; | ||
364 | u32 dot11MeshHWMPactivePathTimeout; | ||
365 | u16 dot11MeshHWMPpreqMinInterval; | ||
366 | u16 dot11MeshHWMPnetDiameterTraversalTime; | ||
367 | }; | ||
368 | |||
350 | /* from net/wireless.h */ | 369 | /* from net/wireless.h */ |
351 | struct wiphy; | 370 | struct wiphy; |
352 | 371 | ||
@@ -397,6 +416,12 @@ struct wiphy; | |||
397 | * | 416 | * |
398 | * @change_station: Modify a given station. | 417 | * @change_station: Modify a given station. |
399 | * | 418 | * |
419 | * @get_mesh_params: Put the current mesh parameters into *params | ||
420 | * | ||
421 | * @set_mesh_params: Set mesh parameters. | ||
422 | * The mask is a bitfield which tells us which parameters to | ||
423 | * set, and which to leave alone. | ||
424 | * | ||
400 | * @set_mesh_cfg: set mesh parameters (by now, just mesh id) | 425 | * @set_mesh_cfg: set mesh parameters (by now, just mesh id) |
401 | * | 426 | * |
402 | * @change_bss: Modify parameters for a given BSS. | 427 | * @change_bss: Modify parameters for a given BSS. |
@@ -452,7 +477,12 @@ struct cfg80211_ops { | |||
452 | int (*dump_mpath)(struct wiphy *wiphy, struct net_device *dev, | 477 | int (*dump_mpath)(struct wiphy *wiphy, struct net_device *dev, |
453 | int idx, u8 *dst, u8 *next_hop, | 478 | int idx, u8 *dst, u8 *next_hop, |
454 | struct mpath_info *pinfo); | 479 | struct mpath_info *pinfo); |
455 | 480 | int (*get_mesh_params)(struct wiphy *wiphy, | |
481 | struct net_device *dev, | ||
482 | struct mesh_config *conf); | ||
483 | int (*set_mesh_params)(struct wiphy *wiphy, | ||
484 | struct net_device *dev, | ||
485 | const struct mesh_config *nconf, u32 mask); | ||
456 | int (*change_bss)(struct wiphy *wiphy, struct net_device *dev, | 486 | int (*change_bss)(struct wiphy *wiphy, struct net_device *dev, |
457 | struct bss_parameters *params); | 487 | struct bss_parameters *params); |
458 | }; | 488 | }; |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 55e3a26510ed..91f56a48e2b4 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -951,6 +951,72 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
951 | rcu_read_unlock(); | 951 | rcu_read_unlock(); |
952 | return 0; | 952 | return 0; |
953 | } | 953 | } |
954 | |||
955 | static int ieee80211_get_mesh_params(struct wiphy *wiphy, | ||
956 | struct net_device *dev, | ||
957 | struct mesh_config *conf) | ||
958 | { | ||
959 | struct ieee80211_sub_if_data *sdata; | ||
960 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
961 | |||
962 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | ||
963 | return -ENOTSUPP; | ||
964 | memcpy(conf, &(sdata->u.mesh.mshcfg), sizeof(struct mesh_config)); | ||
965 | return 0; | ||
966 | } | ||
967 | |||
968 | static inline bool _chg_mesh_attr(enum nl80211_meshconf_params parm, u32 mask) | ||
969 | { | ||
970 | return (mask >> (parm-1)) & 0x1; | ||
971 | } | ||
972 | |||
973 | static int ieee80211_set_mesh_params(struct wiphy *wiphy, | ||
974 | struct net_device *dev, | ||
975 | const struct mesh_config *nconf, u32 mask) | ||
976 | { | ||
977 | struct mesh_config *conf; | ||
978 | struct ieee80211_sub_if_data *sdata; | ||
979 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
980 | |||
981 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | ||
982 | return -ENOTSUPP; | ||
983 | |||
984 | /* Set the config options which we are interested in setting */ | ||
985 | conf = &(sdata->u.mesh.mshcfg); | ||
986 | if (_chg_mesh_attr(NL80211_MESHCONF_RETRY_TIMEOUT, mask)) | ||
987 | conf->dot11MeshRetryTimeout = nconf->dot11MeshRetryTimeout; | ||
988 | if (_chg_mesh_attr(NL80211_MESHCONF_CONFIRM_TIMEOUT, mask)) | ||
989 | conf->dot11MeshConfirmTimeout = nconf->dot11MeshConfirmTimeout; | ||
990 | if (_chg_mesh_attr(NL80211_MESHCONF_HOLDING_TIMEOUT, mask)) | ||
991 | conf->dot11MeshHoldingTimeout = nconf->dot11MeshHoldingTimeout; | ||
992 | if (_chg_mesh_attr(NL80211_MESHCONF_MAX_PEER_LINKS, mask)) | ||
993 | conf->dot11MeshMaxPeerLinks = nconf->dot11MeshMaxPeerLinks; | ||
994 | if (_chg_mesh_attr(NL80211_MESHCONF_MAX_RETRIES, mask)) | ||
995 | conf->dot11MeshMaxRetries = nconf->dot11MeshMaxRetries; | ||
996 | if (_chg_mesh_attr(NL80211_MESHCONF_TTL, mask)) | ||
997 | conf->dot11MeshTTL = nconf->dot11MeshTTL; | ||
998 | if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) | ||
999 | conf->auto_open_plinks = nconf->auto_open_plinks; | ||
1000 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, mask)) | ||
1001 | conf->dot11MeshHWMPmaxPREQretries = | ||
1002 | nconf->dot11MeshHWMPmaxPREQretries; | ||
1003 | if (_chg_mesh_attr(NL80211_MESHCONF_PATH_REFRESH_TIME, mask)) | ||
1004 | conf->path_refresh_time = nconf->path_refresh_time; | ||
1005 | if (_chg_mesh_attr(NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, mask)) | ||
1006 | conf->min_discovery_timeout = nconf->min_discovery_timeout; | ||
1007 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, mask)) | ||
1008 | conf->dot11MeshHWMPactivePathTimeout = | ||
1009 | nconf->dot11MeshHWMPactivePathTimeout; | ||
1010 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, mask)) | ||
1011 | conf->dot11MeshHWMPpreqMinInterval = | ||
1012 | nconf->dot11MeshHWMPpreqMinInterval; | ||
1013 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, | ||
1014 | mask)) | ||
1015 | conf->dot11MeshHWMPnetDiameterTraversalTime = | ||
1016 | nconf->dot11MeshHWMPnetDiameterTraversalTime; | ||
1017 | return 0; | ||
1018 | } | ||
1019 | |||
954 | #endif | 1020 | #endif |
955 | 1021 | ||
956 | static int ieee80211_change_bss(struct wiphy *wiphy, | 1022 | static int ieee80211_change_bss(struct wiphy *wiphy, |
@@ -1007,6 +1073,8 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1007 | .change_mpath = ieee80211_change_mpath, | 1073 | .change_mpath = ieee80211_change_mpath, |
1008 | .get_mpath = ieee80211_get_mpath, | 1074 | .get_mpath = ieee80211_get_mpath, |
1009 | .dump_mpath = ieee80211_dump_mpath, | 1075 | .dump_mpath = ieee80211_dump_mpath, |
1076 | .set_mesh_params = ieee80211_set_mesh_params, | ||
1077 | .get_mesh_params = ieee80211_get_mesh_params, | ||
1010 | #endif | 1078 | #endif |
1011 | .change_bss = ieee80211_change_bss, | 1079 | .change_bss = ieee80211_change_bss, |
1012 | }; | 1080 | }; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index fe4efdd4253d..2c91108e3901 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
25 | #include <linux/etherdevice.h> | 25 | #include <linux/etherdevice.h> |
26 | #include <net/cfg80211.h> | ||
26 | #include <net/wireless.h> | 27 | #include <net/wireless.h> |
27 | #include <net/iw_handler.h> | 28 | #include <net/iw_handler.h> |
28 | #include <net/mac80211.h> | 29 | #include <net/mac80211.h> |
@@ -247,26 +248,6 @@ struct mesh_preq_queue { | |||
247 | u8 flags; | 248 | u8 flags; |
248 | }; | 249 | }; |
249 | 250 | ||
250 | struct mesh_config { | ||
251 | /* Timeouts in ms */ | ||
252 | /* Mesh plink management parameters */ | ||
253 | u16 dot11MeshRetryTimeout; | ||
254 | u16 dot11MeshConfirmTimeout; | ||
255 | u16 dot11MeshHoldingTimeout; | ||
256 | u16 dot11MeshMaxPeerLinks; | ||
257 | u8 dot11MeshMaxRetries; | ||
258 | u8 dot11MeshTTL; | ||
259 | bool auto_open_plinks; | ||
260 | /* HWMP parameters */ | ||
261 | u8 dot11MeshHWMPmaxPREQretries; | ||
262 | u32 path_refresh_time; | ||
263 | u16 min_discovery_timeout; | ||
264 | u32 dot11MeshHWMPactivePathTimeout; | ||
265 | u16 dot11MeshHWMPpreqMinInterval; | ||
266 | u16 dot11MeshHWMPnetDiameterTraversalTime; | ||
267 | }; | ||
268 | |||
269 | |||
270 | /* flags used in struct ieee80211_if_sta.flags */ | 251 | /* flags used in struct ieee80211_if_sta.flags */ |
271 | #define IEEE80211_STA_SSID_SET BIT(0) | 252 | #define IEEE80211_STA_SSID_SET BIT(0) |
272 | #define IEEE80211_STA_BSSID_SET BIT(1) | 253 | #define IEEE80211_STA_BSSID_SET BIT(1) |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 2b87aec231ea..9a16e9e6c5ca 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -96,6 +96,8 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { | |||
96 | [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 }, | 96 | [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 }, |
97 | [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 }, | 97 | [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 }, |
98 | 98 | ||
99 | [NL80211_ATTR_MESH_PARAMS] = { .type = NLA_NESTED }, | ||
100 | |||
99 | [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, | 101 | [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, |
100 | .len = NL80211_HT_CAPABILITY_LEN }, | 102 | .len = NL80211_HT_CAPABILITY_LEN }, |
101 | }; | 103 | }; |
@@ -1698,6 +1700,183 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
1698 | return r; | 1700 | return r; |
1699 | } | 1701 | } |
1700 | 1702 | ||
1703 | static int nl80211_get_mesh_params(struct sk_buff *skb, | ||
1704 | struct genl_info *info) | ||
1705 | { | ||
1706 | struct cfg80211_registered_device *drv; | ||
1707 | struct mesh_config cur_params; | ||
1708 | int err; | ||
1709 | struct net_device *dev; | ||
1710 | void *hdr; | ||
1711 | struct nlattr *pinfoattr; | ||
1712 | struct sk_buff *msg; | ||
1713 | |||
1714 | /* Look up our device */ | ||
1715 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | ||
1716 | if (err) | ||
1717 | return err; | ||
1718 | |||
1719 | /* Get the mesh params */ | ||
1720 | rtnl_lock(); | ||
1721 | err = drv->ops->get_mesh_params(&drv->wiphy, dev, &cur_params); | ||
1722 | rtnl_unlock(); | ||
1723 | if (err) | ||
1724 | goto out; | ||
1725 | |||
1726 | /* Draw up a netlink message to send back */ | ||
1727 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
1728 | if (!msg) { | ||
1729 | err = -ENOBUFS; | ||
1730 | goto out; | ||
1731 | } | ||
1732 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | ||
1733 | NL80211_CMD_GET_MESH_PARAMS); | ||
1734 | if (!hdr) | ||
1735 | goto nla_put_failure; | ||
1736 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_MESH_PARAMS); | ||
1737 | if (!pinfoattr) | ||
1738 | goto nla_put_failure; | ||
1739 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); | ||
1740 | NLA_PUT_U16(msg, NL80211_MESHCONF_RETRY_TIMEOUT, | ||
1741 | cur_params.dot11MeshRetryTimeout); | ||
1742 | NLA_PUT_U16(msg, NL80211_MESHCONF_CONFIRM_TIMEOUT, | ||
1743 | cur_params.dot11MeshConfirmTimeout); | ||
1744 | NLA_PUT_U16(msg, NL80211_MESHCONF_HOLDING_TIMEOUT, | ||
1745 | cur_params.dot11MeshHoldingTimeout); | ||
1746 | NLA_PUT_U16(msg, NL80211_MESHCONF_MAX_PEER_LINKS, | ||
1747 | cur_params.dot11MeshMaxPeerLinks); | ||
1748 | NLA_PUT_U8(msg, NL80211_MESHCONF_MAX_RETRIES, | ||
1749 | cur_params.dot11MeshMaxRetries); | ||
1750 | NLA_PUT_U8(msg, NL80211_MESHCONF_TTL, | ||
1751 | cur_params.dot11MeshTTL); | ||
1752 | NLA_PUT_U8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS, | ||
1753 | cur_params.auto_open_plinks); | ||
1754 | NLA_PUT_U8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, | ||
1755 | cur_params.dot11MeshHWMPmaxPREQretries); | ||
1756 | NLA_PUT_U32(msg, NL80211_MESHCONF_PATH_REFRESH_TIME, | ||
1757 | cur_params.path_refresh_time); | ||
1758 | NLA_PUT_U16(msg, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, | ||
1759 | cur_params.min_discovery_timeout); | ||
1760 | NLA_PUT_U32(msg, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, | ||
1761 | cur_params.dot11MeshHWMPactivePathTimeout); | ||
1762 | NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, | ||
1763 | cur_params.dot11MeshHWMPpreqMinInterval); | ||
1764 | NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, | ||
1765 | cur_params.dot11MeshHWMPnetDiameterTraversalTime); | ||
1766 | nla_nest_end(msg, pinfoattr); | ||
1767 | genlmsg_end(msg, hdr); | ||
1768 | err = genlmsg_unicast(msg, info->snd_pid); | ||
1769 | goto out; | ||
1770 | |||
1771 | nla_put_failure: | ||
1772 | genlmsg_cancel(msg, hdr); | ||
1773 | err = -EMSGSIZE; | ||
1774 | out: | ||
1775 | /* Cleanup */ | ||
1776 | cfg80211_put_dev(drv); | ||
1777 | dev_put(dev); | ||
1778 | return err; | ||
1779 | } | ||
1780 | |||
1781 | #define FILL_IN_MESH_PARAM_IF_SET(table, cfg, param, mask, attr_num, nla_fn) \ | ||
1782 | do {\ | ||
1783 | if (table[attr_num]) {\ | ||
1784 | cfg.param = nla_fn(table[attr_num]); \ | ||
1785 | mask |= (1 << (attr_num - 1)); \ | ||
1786 | } \ | ||
1787 | } while (0);\ | ||
1788 | |||
1789 | static struct nla_policy | ||
1790 | nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] __read_mostly = { | ||
1791 | [NL80211_MESHCONF_RETRY_TIMEOUT] = { .type = NLA_U16 }, | ||
1792 | [NL80211_MESHCONF_CONFIRM_TIMEOUT] = { .type = NLA_U16 }, | ||
1793 | [NL80211_MESHCONF_HOLDING_TIMEOUT] = { .type = NLA_U16 }, | ||
1794 | [NL80211_MESHCONF_MAX_PEER_LINKS] = { .type = NLA_U16 }, | ||
1795 | [NL80211_MESHCONF_MAX_RETRIES] = { .type = NLA_U8 }, | ||
1796 | [NL80211_MESHCONF_TTL] = { .type = NLA_U8 }, | ||
1797 | [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = { .type = NLA_U8 }, | ||
1798 | |||
1799 | [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 }, | ||
1800 | [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 }, | ||
1801 | [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = { .type = NLA_U16 }, | ||
1802 | [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 }, | ||
1803 | [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 }, | ||
1804 | [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 }, | ||
1805 | }; | ||
1806 | |||
1807 | static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info) | ||
1808 | { | ||
1809 | int err; | ||
1810 | u32 mask; | ||
1811 | struct cfg80211_registered_device *drv; | ||
1812 | struct net_device *dev; | ||
1813 | struct mesh_config cfg; | ||
1814 | struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1]; | ||
1815 | struct nlattr *parent_attr; | ||
1816 | |||
1817 | parent_attr = info->attrs[NL80211_ATTR_MESH_PARAMS]; | ||
1818 | if (!parent_attr) | ||
1819 | return -EINVAL; | ||
1820 | if (nla_parse_nested(tb, NL80211_MESHCONF_ATTR_MAX, | ||
1821 | parent_attr, nl80211_meshconf_params_policy)) | ||
1822 | return -EINVAL; | ||
1823 | |||
1824 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | ||
1825 | if (err) | ||
1826 | return err; | ||
1827 | |||
1828 | /* This makes sure that there aren't more than 32 mesh config | ||
1829 | * parameters (otherwise our bitfield scheme would not work.) */ | ||
1830 | BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32); | ||
1831 | |||
1832 | /* Fill in the params struct */ | ||
1833 | mask = 0; | ||
1834 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, | ||
1835 | mask, NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16); | ||
1836 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, | ||
1837 | mask, NL80211_MESHCONF_CONFIRM_TIMEOUT, nla_get_u16); | ||
1838 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, | ||
1839 | mask, NL80211_MESHCONF_HOLDING_TIMEOUT, nla_get_u16); | ||
1840 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, | ||
1841 | mask, NL80211_MESHCONF_MAX_PEER_LINKS, nla_get_u16); | ||
1842 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, | ||
1843 | mask, NL80211_MESHCONF_MAX_RETRIES, nla_get_u8); | ||
1844 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, | ||
1845 | mask, NL80211_MESHCONF_TTL, nla_get_u8); | ||
1846 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, | ||
1847 | mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS, nla_get_u8); | ||
1848 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, | ||
1849 | mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, | ||
1850 | nla_get_u8); | ||
1851 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, | ||
1852 | mask, NL80211_MESHCONF_PATH_REFRESH_TIME, nla_get_u32); | ||
1853 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, | ||
1854 | mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, | ||
1855 | nla_get_u16); | ||
1856 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout, | ||
1857 | mask, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, | ||
1858 | nla_get_u32); | ||
1859 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, | ||
1860 | mask, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, | ||
1861 | nla_get_u16); | ||
1862 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, | ||
1863 | dot11MeshHWMPnetDiameterTraversalTime, | ||
1864 | mask, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, | ||
1865 | nla_get_u16); | ||
1866 | |||
1867 | /* Apply changes */ | ||
1868 | rtnl_lock(); | ||
1869 | err = drv->ops->set_mesh_params(&drv->wiphy, dev, &cfg, mask); | ||
1870 | rtnl_unlock(); | ||
1871 | |||
1872 | /* cleanup */ | ||
1873 | cfg80211_put_dev(drv); | ||
1874 | dev_put(dev); | ||
1875 | return err; | ||
1876 | } | ||
1877 | |||
1878 | #undef FILL_IN_MESH_PARAM_IF_SET | ||
1879 | |||
1701 | static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | 1880 | static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) |
1702 | { | 1881 | { |
1703 | struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1]; | 1882 | struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1]; |
@@ -1915,6 +2094,18 @@ static struct genl_ops nl80211_ops[] = { | |||
1915 | .policy = nl80211_policy, | 2094 | .policy = nl80211_policy, |
1916 | .flags = GENL_ADMIN_PERM, | 2095 | .flags = GENL_ADMIN_PERM, |
1917 | }, | 2096 | }, |
2097 | { | ||
2098 | .cmd = NL80211_CMD_GET_MESH_PARAMS, | ||
2099 | .doit = nl80211_get_mesh_params, | ||
2100 | .policy = nl80211_policy, | ||
2101 | /* can be retrieved by unprivileged users */ | ||
2102 | }, | ||
2103 | { | ||
2104 | .cmd = NL80211_CMD_SET_MESH_PARAMS, | ||
2105 | .doit = nl80211_set_mesh_params, | ||
2106 | .policy = nl80211_policy, | ||
2107 | .flags = GENL_ADMIN_PERM, | ||
2108 | }, | ||
1918 | }; | 2109 | }; |
1919 | 2110 | ||
1920 | /* multicast groups */ | 2111 | /* multicast groups */ |