Correct .gbs.conf settings
[platform/adaptation/renesas_rcar/renesas_kernel.git] / net / ieee802154 / nl-mac.c
1 /*
2  * Netlink inteface for IEEE 802.15.4 stack
3  *
4  * Copyright 2007, 2008 Siemens AG
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Written by:
20  * Sergey Lapin <slapin@ossfans.org>
21  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
22  * Maxim Osipov <maxim.osipov@siemens.com>
23  */
24
25 #include <linux/gfp.h>
26 #include <linux/kernel.h>
27 #include <linux/if_arp.h>
28 #include <linux/netdevice.h>
29 #include <net/netlink.h>
30 #include <net/genetlink.h>
31 #include <net/sock.h>
32 #include <linux/nl802154.h>
33 #include <linux/export.h>
34 #include <net/af_ieee802154.h>
35 #include <net/nl802154.h>
36 #include <net/ieee802154.h>
37 #include <net/ieee802154_netdev.h>
38 #include <net/wpan-phy.h>
39
40 #include "ieee802154.h"
41
42 int ieee802154_nl_assoc_indic(struct net_device *dev,
43                 struct ieee802154_addr *addr, u8 cap)
44 {
45         struct sk_buff *msg;
46
47         pr_debug("%s\n", __func__);
48
49         if (addr->addr_type != IEEE802154_ADDR_LONG) {
50                 pr_err("%s: received non-long source address!\n", __func__);
51                 return -EINVAL;
52         }
53
54         msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_INDIC);
55         if (!msg)
56                 return -ENOBUFS;
57
58         if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
59             nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
60             nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
61                     dev->dev_addr) ||
62             nla_put(msg, IEEE802154_ATTR_SRC_HW_ADDR, IEEE802154_ADDR_LEN,
63                     addr->hwaddr) ||
64             nla_put_u8(msg, IEEE802154_ATTR_CAPABILITY, cap))
65                 goto nla_put_failure;
66
67         return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
68
69 nla_put_failure:
70         nlmsg_free(msg);
71         return -ENOBUFS;
72 }
73 EXPORT_SYMBOL(ieee802154_nl_assoc_indic);
74
75 int ieee802154_nl_assoc_confirm(struct net_device *dev, u16 short_addr,
76                 u8 status)
77 {
78         struct sk_buff *msg;
79
80         pr_debug("%s\n", __func__);
81
82         msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_CONF);
83         if (!msg)
84                 return -ENOBUFS;
85
86         if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
87             nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
88             nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
89                     dev->dev_addr) ||
90             nla_put_u16(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) ||
91             nla_put_u8(msg, IEEE802154_ATTR_STATUS, status))
92                 goto nla_put_failure;
93         return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
94
95 nla_put_failure:
96         nlmsg_free(msg);
97         return -ENOBUFS;
98 }
99 EXPORT_SYMBOL(ieee802154_nl_assoc_confirm);
100
101 int ieee802154_nl_disassoc_indic(struct net_device *dev,
102                 struct ieee802154_addr *addr, u8 reason)
103 {
104         struct sk_buff *msg;
105
106         pr_debug("%s\n", __func__);
107
108         msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_INDIC);
109         if (!msg)
110                 return -ENOBUFS;
111
112         if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
113             nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
114             nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
115                     dev->dev_addr))
116                 goto nla_put_failure;
117         if (addr->addr_type == IEEE802154_ADDR_LONG) {
118                 if (nla_put(msg, IEEE802154_ATTR_SRC_HW_ADDR, IEEE802154_ADDR_LEN,
119                             addr->hwaddr))
120                         goto nla_put_failure;
121         } else {
122                 if (nla_put_u16(msg, IEEE802154_ATTR_SRC_SHORT_ADDR,
123                                 addr->short_addr))
124                         goto nla_put_failure;
125         }
126         if (nla_put_u8(msg, IEEE802154_ATTR_REASON, reason))
127                 goto nla_put_failure;
128         return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
129
130 nla_put_failure:
131         nlmsg_free(msg);
132         return -ENOBUFS;
133 }
134 EXPORT_SYMBOL(ieee802154_nl_disassoc_indic);
135
136 int ieee802154_nl_disassoc_confirm(struct net_device *dev, u8 status)
137 {
138         struct sk_buff *msg;
139
140         pr_debug("%s\n", __func__);
141
142         msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_CONF);
143         if (!msg)
144                 return -ENOBUFS;
145
146         if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
147             nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
148             nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
149                     dev->dev_addr) ||
150             nla_put_u8(msg, IEEE802154_ATTR_STATUS, status))
151                 goto nla_put_failure;
152         return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
153
154 nla_put_failure:
155         nlmsg_free(msg);
156         return -ENOBUFS;
157 }
158 EXPORT_SYMBOL(ieee802154_nl_disassoc_confirm);
159
160 int ieee802154_nl_beacon_indic(struct net_device *dev,
161                 u16 panid, u16 coord_addr)
162 {
163         struct sk_buff *msg;
164
165         pr_debug("%s\n", __func__);
166
167         msg = ieee802154_nl_create(0, IEEE802154_BEACON_NOTIFY_INDIC);
168         if (!msg)
169                 return -ENOBUFS;
170
171         if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
172             nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
173             nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
174                     dev->dev_addr) ||
175             nla_put_u16(msg, IEEE802154_ATTR_COORD_SHORT_ADDR, coord_addr) ||
176             nla_put_u16(msg, IEEE802154_ATTR_COORD_PAN_ID, panid))
177                 goto nla_put_failure;
178         return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
179
180 nla_put_failure:
181         nlmsg_free(msg);
182         return -ENOBUFS;
183 }
184 EXPORT_SYMBOL(ieee802154_nl_beacon_indic);
185
186 int ieee802154_nl_scan_confirm(struct net_device *dev,
187                 u8 status, u8 scan_type, u32 unscanned, u8 page,
188                 u8 *edl/* , struct list_head *pan_desc_list */)
189 {
190         struct sk_buff *msg;
191
192         pr_debug("%s\n", __func__);
193
194         msg = ieee802154_nl_create(0, IEEE802154_SCAN_CONF);
195         if (!msg)
196                 return -ENOBUFS;
197
198         if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
199             nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
200             nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
201                     dev->dev_addr) ||
202             nla_put_u8(msg, IEEE802154_ATTR_STATUS, status) ||
203             nla_put_u8(msg, IEEE802154_ATTR_SCAN_TYPE, scan_type) ||
204             nla_put_u32(msg, IEEE802154_ATTR_CHANNELS, unscanned) ||
205             nla_put_u8(msg, IEEE802154_ATTR_PAGE, page) ||
206             (edl &&
207              nla_put(msg, IEEE802154_ATTR_ED_LIST, 27, edl)))
208                 goto nla_put_failure;
209         return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
210
211 nla_put_failure:
212         nlmsg_free(msg);
213         return -ENOBUFS;
214 }
215 EXPORT_SYMBOL(ieee802154_nl_scan_confirm);
216
217 int ieee802154_nl_start_confirm(struct net_device *dev, u8 status)
218 {
219         struct sk_buff *msg;
220
221         pr_debug("%s\n", __func__);
222
223         msg = ieee802154_nl_create(0, IEEE802154_START_CONF);
224         if (!msg)
225                 return -ENOBUFS;
226
227         if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
228             nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
229             nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
230                     dev->dev_addr) ||
231             nla_put_u8(msg, IEEE802154_ATTR_STATUS, status))
232                 goto nla_put_failure;
233         return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
234
235 nla_put_failure:
236         nlmsg_free(msg);
237         return -ENOBUFS;
238 }
239 EXPORT_SYMBOL(ieee802154_nl_start_confirm);
240
241 static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid,
242         u32 seq, int flags, struct net_device *dev)
243 {
244         void *hdr;
245         struct wpan_phy *phy;
246
247         pr_debug("%s\n", __func__);
248
249         hdr = genlmsg_put(msg, 0, seq, &nl802154_family, flags,
250                 IEEE802154_LIST_IFACE);
251         if (!hdr)
252                 goto out;
253
254         phy = ieee802154_mlme_ops(dev)->get_phy(dev);
255         BUG_ON(!phy);
256
257         if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
258             nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) ||
259             nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
260             nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
261                     dev->dev_addr) ||
262             nla_put_u16(msg, IEEE802154_ATTR_SHORT_ADDR,
263                         ieee802154_mlme_ops(dev)->get_short_addr(dev)) ||
264             nla_put_u16(msg, IEEE802154_ATTR_PAN_ID,
265                         ieee802154_mlme_ops(dev)->get_pan_id(dev)))
266                 goto nla_put_failure;
267         wpan_phy_put(phy);
268         return genlmsg_end(msg, hdr);
269
270 nla_put_failure:
271         wpan_phy_put(phy);
272         genlmsg_cancel(msg, hdr);
273 out:
274         return -EMSGSIZE;
275 }
276
277 /* Requests from userspace */
278 static struct net_device *ieee802154_nl_get_dev(struct genl_info *info)
279 {
280         struct net_device *dev;
281
282         if (info->attrs[IEEE802154_ATTR_DEV_NAME]) {
283                 char name[IFNAMSIZ + 1];
284                 nla_strlcpy(name, info->attrs[IEEE802154_ATTR_DEV_NAME],
285                                 sizeof(name));
286                 dev = dev_get_by_name(&init_net, name);
287         } else if (info->attrs[IEEE802154_ATTR_DEV_INDEX])
288                 dev = dev_get_by_index(&init_net,
289                         nla_get_u32(info->attrs[IEEE802154_ATTR_DEV_INDEX]));
290         else
291                 return NULL;
292
293         if (!dev)
294                 return NULL;
295
296         if (dev->type != ARPHRD_IEEE802154) {
297                 dev_put(dev);
298                 return NULL;
299         }
300
301         return dev;
302 }
303
304 int ieee802154_associate_req(struct sk_buff *skb, struct genl_info *info)
305 {
306         struct net_device *dev;
307         struct ieee802154_addr addr;
308         u8 page;
309         int ret = -EOPNOTSUPP;
310
311         if (!info->attrs[IEEE802154_ATTR_CHANNEL] ||
312             !info->attrs[IEEE802154_ATTR_COORD_PAN_ID] ||
313             (!info->attrs[IEEE802154_ATTR_COORD_HW_ADDR] &&
314                 !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]) ||
315             !info->attrs[IEEE802154_ATTR_CAPABILITY])
316                 return -EINVAL;
317
318         dev = ieee802154_nl_get_dev(info);
319         if (!dev)
320                 return -ENODEV;
321         if (!ieee802154_mlme_ops(dev)->assoc_req)
322                 goto out;
323
324         if (info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]) {
325                 addr.addr_type = IEEE802154_ADDR_LONG;
326                 nla_memcpy(addr.hwaddr,
327                                 info->attrs[IEEE802154_ATTR_COORD_HW_ADDR],
328                                 IEEE802154_ADDR_LEN);
329         } else {
330                 addr.addr_type = IEEE802154_ADDR_SHORT;
331                 addr.short_addr = nla_get_u16(
332                                 info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]);
333         }
334         addr.pan_id = nla_get_u16(info->attrs[IEEE802154_ATTR_COORD_PAN_ID]);
335
336         if (info->attrs[IEEE802154_ATTR_PAGE])
337                 page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]);
338         else
339                 page = 0;
340
341         ret = ieee802154_mlme_ops(dev)->assoc_req(dev, &addr,
342                         nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]),
343                         page,
344                         nla_get_u8(info->attrs[IEEE802154_ATTR_CAPABILITY]));
345
346 out:
347         dev_put(dev);
348         return ret;
349 }
350
351 int ieee802154_associate_resp(struct sk_buff *skb, struct genl_info *info)
352 {
353         struct net_device *dev;
354         struct ieee802154_addr addr;
355         int ret = -EOPNOTSUPP;
356
357         if (!info->attrs[IEEE802154_ATTR_STATUS] ||
358             !info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] ||
359             !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR])
360                 return -EINVAL;
361
362         dev = ieee802154_nl_get_dev(info);
363         if (!dev)
364                 return -ENODEV;
365         if (!ieee802154_mlme_ops(dev)->assoc_resp)
366                 goto out;
367
368         addr.addr_type = IEEE802154_ADDR_LONG;
369         nla_memcpy(addr.hwaddr, info->attrs[IEEE802154_ATTR_DEST_HW_ADDR],
370                         IEEE802154_ADDR_LEN);
371         addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
372
373
374         ret = ieee802154_mlme_ops(dev)->assoc_resp(dev, &addr,
375                 nla_get_u16(info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]),
376                 nla_get_u8(info->attrs[IEEE802154_ATTR_STATUS]));
377
378 out:
379         dev_put(dev);
380         return ret;
381 }
382
383 int ieee802154_disassociate_req(struct sk_buff *skb, struct genl_info *info)
384 {
385         struct net_device *dev;
386         struct ieee802154_addr addr;
387         int ret = -EOPNOTSUPP;
388
389         if ((!info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] &&
390                 !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]) ||
391             !info->attrs[IEEE802154_ATTR_REASON])
392                 return -EINVAL;
393
394         dev = ieee802154_nl_get_dev(info);
395         if (!dev)
396                 return -ENODEV;
397         if (!ieee802154_mlme_ops(dev)->disassoc_req)
398                 goto out;
399
400         if (info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]) {
401                 addr.addr_type = IEEE802154_ADDR_LONG;
402                 nla_memcpy(addr.hwaddr,
403                                 info->attrs[IEEE802154_ATTR_DEST_HW_ADDR],
404                                 IEEE802154_ADDR_LEN);
405         } else {
406                 addr.addr_type = IEEE802154_ADDR_SHORT;
407                 addr.short_addr = nla_get_u16(
408                                 info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]);
409         }
410         addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
411
412         ret = ieee802154_mlme_ops(dev)->disassoc_req(dev, &addr,
413                         nla_get_u8(info->attrs[IEEE802154_ATTR_REASON]));
414
415 out:
416         dev_put(dev);
417         return ret;
418 }
419
420 /*
421  * PANid, channel, beacon_order = 15, superframe_order = 15,
422  * PAN_coordinator, battery_life_extension = 0,
423  * coord_realignment = 0, security_enable = 0
424 */
425 int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info)
426 {
427         struct net_device *dev;
428         struct ieee802154_addr addr;
429
430         u8 channel, bcn_ord, sf_ord;
431         u8 page;
432         int pan_coord, blx, coord_realign;
433         int ret = -EOPNOTSUPP;
434
435         if (!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] ||
436             !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR] ||
437             !info->attrs[IEEE802154_ATTR_CHANNEL] ||
438             !info->attrs[IEEE802154_ATTR_BCN_ORD] ||
439             !info->attrs[IEEE802154_ATTR_SF_ORD] ||
440             !info->attrs[IEEE802154_ATTR_PAN_COORD] ||
441             !info->attrs[IEEE802154_ATTR_BAT_EXT] ||
442             !info->attrs[IEEE802154_ATTR_COORD_REALIGN]
443          )
444                 return -EINVAL;
445
446         dev = ieee802154_nl_get_dev(info);
447         if (!dev)
448                 return -ENODEV;
449         if (!ieee802154_mlme_ops(dev)->start_req)
450                 goto out;
451
452         addr.addr_type = IEEE802154_ADDR_SHORT;
453         addr.short_addr = nla_get_u16(
454                         info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]);
455         addr.pan_id = nla_get_u16(info->attrs[IEEE802154_ATTR_COORD_PAN_ID]);
456
457         channel = nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]);
458         bcn_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_BCN_ORD]);
459         sf_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_SF_ORD]);
460         pan_coord = nla_get_u8(info->attrs[IEEE802154_ATTR_PAN_COORD]);
461         blx = nla_get_u8(info->attrs[IEEE802154_ATTR_BAT_EXT]);
462         coord_realign = nla_get_u8(info->attrs[IEEE802154_ATTR_COORD_REALIGN]);
463
464         if (info->attrs[IEEE802154_ATTR_PAGE])
465                 page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]);
466         else
467                 page = 0;
468
469
470         if (addr.short_addr == IEEE802154_ADDR_BROADCAST) {
471                 ieee802154_nl_start_confirm(dev, IEEE802154_NO_SHORT_ADDRESS);
472                 dev_put(dev);
473                 return -EINVAL;
474         }
475
476         ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, page,
477                 bcn_ord, sf_ord, pan_coord, blx, coord_realign);
478
479 out:
480         dev_put(dev);
481         return ret;
482 }
483
484 int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info)
485 {
486         struct net_device *dev;
487         int ret = -EOPNOTSUPP;
488         u8 type;
489         u32 channels;
490         u8 duration;
491         u8 page;
492
493         if (!info->attrs[IEEE802154_ATTR_SCAN_TYPE] ||
494             !info->attrs[IEEE802154_ATTR_CHANNELS] ||
495             !info->attrs[IEEE802154_ATTR_DURATION])
496                 return -EINVAL;
497
498         dev = ieee802154_nl_get_dev(info);
499         if (!dev)
500                 return -ENODEV;
501         if (!ieee802154_mlme_ops(dev)->scan_req)
502                 goto out;
503
504         type = nla_get_u8(info->attrs[IEEE802154_ATTR_SCAN_TYPE]);
505         channels = nla_get_u32(info->attrs[IEEE802154_ATTR_CHANNELS]);
506         duration = nla_get_u8(info->attrs[IEEE802154_ATTR_DURATION]);
507
508         if (info->attrs[IEEE802154_ATTR_PAGE])
509                 page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]);
510         else
511                 page = 0;
512
513
514         ret = ieee802154_mlme_ops(dev)->scan_req(dev, type, channels, page,
515                         duration);
516
517 out:
518         dev_put(dev);
519         return ret;
520 }
521
522 int ieee802154_list_iface(struct sk_buff *skb, struct genl_info *info)
523 {
524         /* Request for interface name, index, type, IEEE address,
525            PAN Id, short address */
526         struct sk_buff *msg;
527         struct net_device *dev = NULL;
528         int rc = -ENOBUFS;
529
530         pr_debug("%s\n", __func__);
531
532         dev = ieee802154_nl_get_dev(info);
533         if (!dev)
534                 return -ENODEV;
535
536         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
537         if (!msg)
538                 goto out_dev;
539
540         rc = ieee802154_nl_fill_iface(msg, info->snd_portid, info->snd_seq,
541                         0, dev);
542         if (rc < 0)
543                 goto out_free;
544
545         dev_put(dev);
546
547         return genlmsg_reply(msg, info);
548 out_free:
549         nlmsg_free(msg);
550 out_dev:
551         dev_put(dev);
552         return rc;
553
554 }
555
556 int ieee802154_dump_iface(struct sk_buff *skb, struct netlink_callback *cb)
557 {
558         struct net *net = sock_net(skb->sk);
559         struct net_device *dev;
560         int idx;
561         int s_idx = cb->args[0];
562
563         pr_debug("%s\n", __func__);
564
565         idx = 0;
566         for_each_netdev(net, dev) {
567                 if (idx < s_idx || (dev->type != ARPHRD_IEEE802154))
568                         goto cont;
569
570                 if (ieee802154_nl_fill_iface(skb, NETLINK_CB(cb->skb).portid,
571                         cb->nlh->nlmsg_seq, NLM_F_MULTI, dev) < 0)
572                         break;
573 cont:
574                 idx++;
575         }
576         cb->args[0] = idx;
577
578         return skb->len;
579 }