1 /* 2 * Copyright 2007-2012 Siemens AG 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 6 * as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * Written by: 14 * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> 15 * Sergey Lapin <slapin@ossfans.org> 16 * Maxim Gorbachyov <maxim.gorbachev@siemens.com> 17 * Alexander Smirnov <alex.bluesman.smirnov@gmail.com> 18 */ 19 20 #include <linux/if_arp.h> 21 22 #include <net/mac802154.h> 23 #include <net/ieee802154_netdev.h> 24 #include <net/cfg802154.h> 25 26 #include "ieee802154_i.h" 27 28 struct phy_chan_notify_work { 29 struct work_struct work; 30 struct net_device *dev; 31 }; 32 33 struct hw_addr_filt_notify_work { 34 struct work_struct work; 35 struct net_device *dev; 36 unsigned long changed; 37 }; 38 39 static struct ieee802154_local *mac802154_slave_get_priv(struct net_device *dev) 40 { 41 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 42 43 BUG_ON(dev->type != ARPHRD_IEEE802154); 44 45 return sdata->local; 46 } 47 48 static void hw_addr_notify(struct work_struct *work) 49 { 50 struct hw_addr_filt_notify_work *nw = container_of(work, 51 struct hw_addr_filt_notify_work, work); 52 struct ieee802154_local *local = mac802154_slave_get_priv(nw->dev); 53 int res; 54 55 res = local->ops->set_hw_addr_filt(&local->hw, &local->hw.hw_filt, 56 nw->changed); 57 if (res) 58 pr_debug("failed changed mask %lx\n", nw->changed); 59 60 kfree(nw); 61 } 62 63 static void set_hw_addr_filt(struct net_device *dev, unsigned long changed) 64 { 65 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 66 struct hw_addr_filt_notify_work *work; 67 68 work = kzalloc(sizeof(*work), GFP_ATOMIC); 69 if (!work) 70 return; 71 72 INIT_WORK(&work->work, hw_addr_notify); 73 work->dev = dev; 74 work->changed = changed; 75 queue_work(sdata->local->workqueue, &work->work); 76 } 77 78 void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val) 79 { 80 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 81 82 BUG_ON(dev->type != ARPHRD_IEEE802154); 83 84 spin_lock_bh(&sdata->mib_lock); 85 sdata->short_addr = val; 86 spin_unlock_bh(&sdata->mib_lock); 87 88 if ((sdata->local->ops->set_hw_addr_filt) && 89 (sdata->local->hw.hw_filt.short_addr != sdata->short_addr)) { 90 sdata->local->hw.hw_filt.short_addr = sdata->short_addr; 91 set_hw_addr_filt(dev, IEEE802154_AFILT_SADDR_CHANGED); 92 } 93 } 94 95 __le16 mac802154_dev_get_short_addr(const struct net_device *dev) 96 { 97 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 98 __le16 ret; 99 100 BUG_ON(dev->type != ARPHRD_IEEE802154); 101 102 spin_lock_bh(&sdata->mib_lock); 103 ret = sdata->short_addr; 104 spin_unlock_bh(&sdata->mib_lock); 105 106 return ret; 107 } 108 109 void mac802154_dev_set_ieee_addr(struct net_device *dev) 110 { 111 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 112 struct ieee802154_local *local = sdata->local; 113 114 sdata->extended_addr = ieee802154_devaddr_from_raw(dev->dev_addr); 115 116 if (local->ops->set_hw_addr_filt && 117 local->hw.hw_filt.ieee_addr != sdata->extended_addr) { 118 local->hw.hw_filt.ieee_addr = sdata->extended_addr; 119 set_hw_addr_filt(dev, IEEE802154_AFILT_IEEEADDR_CHANGED); 120 } 121 } 122 123 __le16 mac802154_dev_get_pan_id(const struct net_device *dev) 124 { 125 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 126 __le16 ret; 127 128 BUG_ON(dev->type != ARPHRD_IEEE802154); 129 130 spin_lock_bh(&sdata->mib_lock); 131 ret = sdata->pan_id; 132 spin_unlock_bh(&sdata->mib_lock); 133 134 return ret; 135 } 136 137 void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val) 138 { 139 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 140 141 BUG_ON(dev->type != ARPHRD_IEEE802154); 142 143 spin_lock_bh(&sdata->mib_lock); 144 sdata->pan_id = val; 145 spin_unlock_bh(&sdata->mib_lock); 146 147 if ((sdata->local->ops->set_hw_addr_filt) && 148 (sdata->local->hw.hw_filt.pan_id != sdata->pan_id)) { 149 sdata->local->hw.hw_filt.pan_id = sdata->pan_id; 150 set_hw_addr_filt(dev, IEEE802154_AFILT_PANID_CHANGED); 151 } 152 } 153 154 u8 mac802154_dev_get_dsn(const struct net_device *dev) 155 { 156 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 157 158 BUG_ON(dev->type != ARPHRD_IEEE802154); 159 160 return sdata->dsn++; 161 } 162 163 static void phy_chan_notify(struct work_struct *work) 164 { 165 struct phy_chan_notify_work *nw = container_of(work, 166 struct phy_chan_notify_work, work); 167 struct net_device *dev = nw->dev; 168 struct ieee802154_local *local = mac802154_slave_get_priv(dev); 169 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 170 int res; 171 172 mutex_lock(&sdata->local->phy->pib_lock); 173 res = local->ops->set_channel(&local->hw, sdata->page, sdata->chan); 174 if (res) { 175 pr_debug("set_channel failed\n"); 176 } else { 177 sdata->local->phy->current_channel = sdata->chan; 178 sdata->local->phy->current_page = sdata->page; 179 } 180 mutex_unlock(&sdata->local->phy->pib_lock); 181 182 kfree(nw); 183 } 184 185 void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan) 186 { 187 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 188 struct phy_chan_notify_work *work; 189 190 BUG_ON(dev->type != ARPHRD_IEEE802154); 191 192 spin_lock_bh(&sdata->mib_lock); 193 sdata->page = page; 194 sdata->chan = chan; 195 spin_unlock_bh(&sdata->mib_lock); 196 197 mutex_lock(&sdata->local->phy->pib_lock); 198 if (sdata->local->phy->current_channel != sdata->chan || 199 sdata->local->phy->current_page != sdata->page) { 200 mutex_unlock(&sdata->local->phy->pib_lock); 201 202 work = kzalloc(sizeof(*work), GFP_ATOMIC); 203 if (!work) 204 return; 205 206 INIT_WORK(&work->work, phy_chan_notify); 207 work->dev = dev; 208 queue_work(sdata->local->workqueue, &work->work); 209 } else { 210 mutex_unlock(&sdata->local->phy->pib_lock); 211 } 212 } 213 214 215 int mac802154_get_params(struct net_device *dev, 216 struct ieee802154_llsec_params *params) 217 { 218 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 219 int res; 220 221 BUG_ON(dev->type != ARPHRD_IEEE802154); 222 223 mutex_lock(&sdata->sec_mtx); 224 res = mac802154_llsec_get_params(&sdata->sec, params); 225 mutex_unlock(&sdata->sec_mtx); 226 227 return res; 228 } 229 230 int mac802154_set_params(struct net_device *dev, 231 const struct ieee802154_llsec_params *params, 232 int changed) 233 { 234 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 235 int res; 236 237 BUG_ON(dev->type != ARPHRD_IEEE802154); 238 239 mutex_lock(&sdata->sec_mtx); 240 res = mac802154_llsec_set_params(&sdata->sec, params, changed); 241 mutex_unlock(&sdata->sec_mtx); 242 243 return res; 244 } 245 246 247 int mac802154_add_key(struct net_device *dev, 248 const struct ieee802154_llsec_key_id *id, 249 const struct ieee802154_llsec_key *key) 250 { 251 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 252 int res; 253 254 BUG_ON(dev->type != ARPHRD_IEEE802154); 255 256 mutex_lock(&sdata->sec_mtx); 257 res = mac802154_llsec_key_add(&sdata->sec, id, key); 258 mutex_unlock(&sdata->sec_mtx); 259 260 return res; 261 } 262 263 int mac802154_del_key(struct net_device *dev, 264 const struct ieee802154_llsec_key_id *id) 265 { 266 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 267 int res; 268 269 BUG_ON(dev->type != ARPHRD_IEEE802154); 270 271 mutex_lock(&sdata->sec_mtx); 272 res = mac802154_llsec_key_del(&sdata->sec, id); 273 mutex_unlock(&sdata->sec_mtx); 274 275 return res; 276 } 277 278 279 int mac802154_add_dev(struct net_device *dev, 280 const struct ieee802154_llsec_device *llsec_dev) 281 { 282 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 283 int res; 284 285 BUG_ON(dev->type != ARPHRD_IEEE802154); 286 287 mutex_lock(&sdata->sec_mtx); 288 res = mac802154_llsec_dev_add(&sdata->sec, llsec_dev); 289 mutex_unlock(&sdata->sec_mtx); 290 291 return res; 292 } 293 294 int mac802154_del_dev(struct net_device *dev, __le64 dev_addr) 295 { 296 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 297 int res; 298 299 BUG_ON(dev->type != ARPHRD_IEEE802154); 300 301 mutex_lock(&sdata->sec_mtx); 302 res = mac802154_llsec_dev_del(&sdata->sec, dev_addr); 303 mutex_unlock(&sdata->sec_mtx); 304 305 return res; 306 } 307 308 309 int mac802154_add_devkey(struct net_device *dev, 310 __le64 device_addr, 311 const struct ieee802154_llsec_device_key *key) 312 { 313 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 314 int res; 315 316 BUG_ON(dev->type != ARPHRD_IEEE802154); 317 318 mutex_lock(&sdata->sec_mtx); 319 res = mac802154_llsec_devkey_add(&sdata->sec, device_addr, key); 320 mutex_unlock(&sdata->sec_mtx); 321 322 return res; 323 } 324 325 int mac802154_del_devkey(struct net_device *dev, 326 __le64 device_addr, 327 const struct ieee802154_llsec_device_key *key) 328 { 329 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 330 int res; 331 332 BUG_ON(dev->type != ARPHRD_IEEE802154); 333 334 mutex_lock(&sdata->sec_mtx); 335 res = mac802154_llsec_devkey_del(&sdata->sec, device_addr, key); 336 mutex_unlock(&sdata->sec_mtx); 337 338 return res; 339 } 340 341 342 int mac802154_add_seclevel(struct net_device *dev, 343 const struct ieee802154_llsec_seclevel *sl) 344 { 345 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 346 int res; 347 348 BUG_ON(dev->type != ARPHRD_IEEE802154); 349 350 mutex_lock(&sdata->sec_mtx); 351 res = mac802154_llsec_seclevel_add(&sdata->sec, sl); 352 mutex_unlock(&sdata->sec_mtx); 353 354 return res; 355 } 356 357 int mac802154_del_seclevel(struct net_device *dev, 358 const struct ieee802154_llsec_seclevel *sl) 359 { 360 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 361 int res; 362 363 BUG_ON(dev->type != ARPHRD_IEEE802154); 364 365 mutex_lock(&sdata->sec_mtx); 366 res = mac802154_llsec_seclevel_del(&sdata->sec, sl); 367 mutex_unlock(&sdata->sec_mtx); 368 369 return res; 370 } 371 372 373 void mac802154_lock_table(struct net_device *dev) 374 { 375 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 376 377 BUG_ON(dev->type != ARPHRD_IEEE802154); 378 379 mutex_lock(&sdata->sec_mtx); 380 } 381 382 void mac802154_get_table(struct net_device *dev, 383 struct ieee802154_llsec_table **t) 384 { 385 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 386 387 BUG_ON(dev->type != ARPHRD_IEEE802154); 388 389 *t = &sdata->sec.table; 390 } 391 392 void mac802154_unlock_table(struct net_device *dev) 393 { 394 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 395 396 BUG_ON(dev->type != ARPHRD_IEEE802154); 397 398 mutex_unlock(&sdata->sec_mtx); 399 } 400