aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index a363ca17bfc5..2d3541c5e058 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -70,6 +70,88 @@ static int get_rdev_dev_by_ifindex(struct net *netns, struct nlattr **attrs,
70 return 0; 70 return 0;
71} 71}
72 72
73static struct cfg80211_registered_device *
74__cfg80211_rdev_from_info(struct genl_info *info)
75{
76 int ifindex;
77 struct cfg80211_registered_device *bywiphyidx = NULL, *byifidx = NULL;
78 struct net_device *dev;
79 int err = -EINVAL;
80
81 assert_cfg80211_lock();
82
83 if (info->attrs[NL80211_ATTR_WIPHY]) {
84 bywiphyidx = cfg80211_rdev_by_wiphy_idx(
85 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY]));
86 err = -ENODEV;
87 }
88
89 if (info->attrs[NL80211_ATTR_IFINDEX]) {
90 ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
91 dev = dev_get_by_index(genl_info_net(info), ifindex);
92 if (dev) {
93 if (dev->ieee80211_ptr)
94 byifidx =
95 wiphy_to_dev(dev->ieee80211_ptr->wiphy);
96 dev_put(dev);
97 }
98 err = -ENODEV;
99 }
100
101 if (bywiphyidx && byifidx) {
102 if (bywiphyidx != byifidx)
103 return ERR_PTR(-EINVAL);
104 else
105 return bywiphyidx; /* == byifidx */
106 }
107 if (bywiphyidx)
108 return bywiphyidx;
109
110 if (byifidx)
111 return byifidx;
112
113 return ERR_PTR(err);
114}
115
116/*
117 * This function returns a pointer to the driver
118 * that the genl_info item that is passed refers to.
119 * If successful, it returns non-NULL and also locks
120 * the driver's mutex!
121 *
122 * This means that you need to call cfg80211_unlock_rdev()
123 * before being allowed to acquire &cfg80211_mutex!
124 *
125 * This is necessary because we need to lock the global
126 * mutex to get an item off the list safely, and then
127 * we lock the rdev mutex so it doesn't go away under us.
128 *
129 * We don't want to keep cfg80211_mutex locked
130 * for all the time in order to allow requests on
131 * other interfaces to go through at the same time.
132 *
133 * The result of this can be a PTR_ERR and hence must
134 * be checked with IS_ERR() for errors.
135 */
136static struct cfg80211_registered_device *
137cfg80211_get_dev_from_info(struct genl_info *info)
138{
139 struct cfg80211_registered_device *rdev;
140
141 mutex_lock(&cfg80211_mutex);
142 rdev = __cfg80211_rdev_from_info(info);
143
144 /* if it is not an error we grab the lock on
145 * it to assure it won't be going away while
146 * we operate on it */
147 if (!IS_ERR(rdev))
148 mutex_lock(&rdev->mtx);
149
150 mutex_unlock(&cfg80211_mutex);
151
152 return rdev;
153}
154
73/* policy for the attributes */ 155/* policy for the attributes */
74static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { 156static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
75 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, 157 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },