tipc: add media set to new netlink api
[cascardo/linux.git] / net / tipc / bearer.c
1 /*
2  * net/tipc/bearer.c: TIPC bearer code
3  *
4  * Copyright (c) 1996-2006, 2013-2014, Ericsson AB
5  * Copyright (c) 2004-2006, 2010-2013, Wind River Systems
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the names of the copyright holders nor the names of its
17  *    contributors may be used to endorse or promote products derived from
18  *    this software without specific prior written permission.
19  *
20  * Alternatively, this software may be distributed under the terms of the
21  * GNU General Public License ("GPL") version 2 as published by the Free
22  * Software Foundation.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  */
36
37 #include "core.h"
38 #include "config.h"
39 #include "bearer.h"
40 #include "link.h"
41 #include "discover.h"
42
43 #define MAX_ADDR_STR 60
44
45 static struct tipc_media * const media_info_array[] = {
46         &eth_media_info,
47 #ifdef CONFIG_TIPC_MEDIA_IB
48         &ib_media_info,
49 #endif
50         NULL
51 };
52
53 static const struct nla_policy
54 tipc_nl_bearer_policy[TIPC_NLA_BEARER_MAX + 1]  = {
55         [TIPC_NLA_BEARER_UNSPEC]                = { .type = NLA_UNSPEC },
56         [TIPC_NLA_BEARER_NAME] = {
57                 .type = NLA_STRING,
58                 .len = TIPC_MAX_BEARER_NAME
59         },
60         [TIPC_NLA_BEARER_PROP]                  = { .type = NLA_NESTED },
61         [TIPC_NLA_BEARER_DOMAIN]                = { .type = NLA_U32 }
62 };
63
64 static const struct nla_policy tipc_nl_media_policy[TIPC_NLA_MEDIA_MAX + 1] = {
65         [TIPC_NLA_MEDIA_UNSPEC]         = { .type = NLA_UNSPEC },
66         [TIPC_NLA_MEDIA_NAME]           = { .type = NLA_STRING },
67         [TIPC_NLA_MEDIA_PROP]           = { .type = NLA_NESTED }
68 };
69
70 struct tipc_bearer __rcu *bearer_list[MAX_BEARERS + 1];
71
72 static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down);
73
74 /**
75  * tipc_media_find - locates specified media object by name
76  */
77 struct tipc_media *tipc_media_find(const char *name)
78 {
79         u32 i;
80
81         for (i = 0; media_info_array[i] != NULL; i++) {
82                 if (!strcmp(media_info_array[i]->name, name))
83                         break;
84         }
85         return media_info_array[i];
86 }
87
88 /**
89  * media_find_id - locates specified media object by type identifier
90  */
91 static struct tipc_media *media_find_id(u8 type)
92 {
93         u32 i;
94
95         for (i = 0; media_info_array[i] != NULL; i++) {
96                 if (media_info_array[i]->type_id == type)
97                         break;
98         }
99         return media_info_array[i];
100 }
101
102 /**
103  * tipc_media_addr_printf - record media address in print buffer
104  */
105 void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a)
106 {
107         char addr_str[MAX_ADDR_STR];
108         struct tipc_media *m_ptr;
109         int ret;
110
111         m_ptr = media_find_id(a->media_id);
112
113         if (m_ptr && !m_ptr->addr2str(a, addr_str, sizeof(addr_str)))
114                 ret = tipc_snprintf(buf, len, "%s(%s)", m_ptr->name, addr_str);
115         else {
116                 u32 i;
117
118                 ret = tipc_snprintf(buf, len, "UNKNOWN(%u)", a->media_id);
119                 for (i = 0; i < sizeof(a->value); i++)
120                         ret += tipc_snprintf(buf - ret, len + ret,
121                                             "-%02x", a->value[i]);
122         }
123 }
124
125 /**
126  * tipc_media_get_names - record names of registered media in buffer
127  */
128 struct sk_buff *tipc_media_get_names(void)
129 {
130         struct sk_buff *buf;
131         int i;
132
133         buf = tipc_cfg_reply_alloc(MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME));
134         if (!buf)
135                 return NULL;
136
137         for (i = 0; media_info_array[i] != NULL; i++) {
138                 tipc_cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME,
139                                     media_info_array[i]->name,
140                                     strlen(media_info_array[i]->name) + 1);
141         }
142         return buf;
143 }
144
145 /**
146  * bearer_name_validate - validate & (optionally) deconstruct bearer name
147  * @name: ptr to bearer name string
148  * @name_parts: ptr to area for bearer name components (or NULL if not needed)
149  *
150  * Returns 1 if bearer name is valid, otherwise 0.
151  */
152 static int bearer_name_validate(const char *name,
153                                 struct tipc_bearer_names *name_parts)
154 {
155         char name_copy[TIPC_MAX_BEARER_NAME];
156         char *media_name;
157         char *if_name;
158         u32 media_len;
159         u32 if_len;
160
161         /* copy bearer name & ensure length is OK */
162         name_copy[TIPC_MAX_BEARER_NAME - 1] = 0;
163         /* need above in case non-Posix strncpy() doesn't pad with nulls */
164         strncpy(name_copy, name, TIPC_MAX_BEARER_NAME);
165         if (name_copy[TIPC_MAX_BEARER_NAME - 1] != 0)
166                 return 0;
167
168         /* ensure all component parts of bearer name are present */
169         media_name = name_copy;
170         if_name = strchr(media_name, ':');
171         if (if_name == NULL)
172                 return 0;
173         *(if_name++) = 0;
174         media_len = if_name - media_name;
175         if_len = strlen(if_name) + 1;
176
177         /* validate component parts of bearer name */
178         if ((media_len <= 1) || (media_len > TIPC_MAX_MEDIA_NAME) ||
179             (if_len <= 1) || (if_len > TIPC_MAX_IF_NAME))
180                 return 0;
181
182         /* return bearer name components, if necessary */
183         if (name_parts) {
184                 strcpy(name_parts->media_name, media_name);
185                 strcpy(name_parts->if_name, if_name);
186         }
187         return 1;
188 }
189
190 /**
191  * tipc_bearer_find - locates bearer object with matching bearer name
192  */
193 struct tipc_bearer *tipc_bearer_find(const char *name)
194 {
195         struct tipc_bearer *b_ptr;
196         u32 i;
197
198         for (i = 0; i < MAX_BEARERS; i++) {
199                 b_ptr = rtnl_dereference(bearer_list[i]);
200                 if (b_ptr && (!strcmp(b_ptr->name, name)))
201                         return b_ptr;
202         }
203         return NULL;
204 }
205
206 /**
207  * tipc_bearer_get_names - record names of bearers in buffer
208  */
209 struct sk_buff *tipc_bearer_get_names(void)
210 {
211         struct sk_buff *buf;
212         struct tipc_bearer *b;
213         int i, j;
214
215         buf = tipc_cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME));
216         if (!buf)
217                 return NULL;
218
219         for (i = 0; media_info_array[i] != NULL; i++) {
220                 for (j = 0; j < MAX_BEARERS; j++) {
221                         b = rtnl_dereference(bearer_list[j]);
222                         if (!b)
223                                 continue;
224                         if (b->media == media_info_array[i]) {
225                                 tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME,
226                                                     b->name,
227                                                     strlen(b->name) + 1);
228                         }
229                 }
230         }
231         return buf;
232 }
233
234 void tipc_bearer_add_dest(u32 bearer_id, u32 dest)
235 {
236         struct tipc_bearer *b_ptr;
237
238         rcu_read_lock();
239         b_ptr = rcu_dereference_rtnl(bearer_list[bearer_id]);
240         if (b_ptr) {
241                 tipc_bcbearer_sort(&b_ptr->nodes, dest, true);
242                 tipc_disc_add_dest(b_ptr->link_req);
243         }
244         rcu_read_unlock();
245 }
246
247 void tipc_bearer_remove_dest(u32 bearer_id, u32 dest)
248 {
249         struct tipc_bearer *b_ptr;
250
251         rcu_read_lock();
252         b_ptr = rcu_dereference_rtnl(bearer_list[bearer_id]);
253         if (b_ptr) {
254                 tipc_bcbearer_sort(&b_ptr->nodes, dest, false);
255                 tipc_disc_remove_dest(b_ptr->link_req);
256         }
257         rcu_read_unlock();
258 }
259
260 /**
261  * tipc_enable_bearer - enable bearer with the given name
262  */
263 int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
264 {
265         struct tipc_bearer *b_ptr;
266         struct tipc_media *m_ptr;
267         struct tipc_bearer_names b_names;
268         char addr_string[16];
269         u32 bearer_id;
270         u32 with_this_prio;
271         u32 i;
272         int res = -EINVAL;
273
274         if (!tipc_own_addr) {
275                 pr_warn("Bearer <%s> rejected, not supported in standalone mode\n",
276                         name);
277                 return -ENOPROTOOPT;
278         }
279         if (!bearer_name_validate(name, &b_names)) {
280                 pr_warn("Bearer <%s> rejected, illegal name\n", name);
281                 return -EINVAL;
282         }
283         if (tipc_addr_domain_valid(disc_domain) &&
284             (disc_domain != tipc_own_addr)) {
285                 if (tipc_in_scope(disc_domain, tipc_own_addr)) {
286                         disc_domain = tipc_own_addr & TIPC_CLUSTER_MASK;
287                         res = 0;   /* accept any node in own cluster */
288                 } else if (in_own_cluster_exact(disc_domain))
289                         res = 0;   /* accept specified node in own cluster */
290         }
291         if (res) {
292                 pr_warn("Bearer <%s> rejected, illegal discovery domain\n",
293                         name);
294                 return -EINVAL;
295         }
296         if ((priority > TIPC_MAX_LINK_PRI) &&
297             (priority != TIPC_MEDIA_LINK_PRI)) {
298                 pr_warn("Bearer <%s> rejected, illegal priority\n", name);
299                 return -EINVAL;
300         }
301
302         m_ptr = tipc_media_find(b_names.media_name);
303         if (!m_ptr) {
304                 pr_warn("Bearer <%s> rejected, media <%s> not registered\n",
305                         name, b_names.media_name);
306                 return -EINVAL;
307         }
308
309         if (priority == TIPC_MEDIA_LINK_PRI)
310                 priority = m_ptr->priority;
311
312 restart:
313         bearer_id = MAX_BEARERS;
314         with_this_prio = 1;
315         for (i = MAX_BEARERS; i-- != 0; ) {
316                 b_ptr = rtnl_dereference(bearer_list[i]);
317                 if (!b_ptr) {
318                         bearer_id = i;
319                         continue;
320                 }
321                 if (!strcmp(name, b_ptr->name)) {
322                         pr_warn("Bearer <%s> rejected, already enabled\n",
323                                 name);
324                         return -EINVAL;
325                 }
326                 if ((b_ptr->priority == priority) &&
327                     (++with_this_prio > 2)) {
328                         if (priority-- == 0) {
329                                 pr_warn("Bearer <%s> rejected, duplicate priority\n",
330                                         name);
331                                 return -EINVAL;
332                         }
333                         pr_warn("Bearer <%s> priority adjustment required %u->%u\n",
334                                 name, priority + 1, priority);
335                         goto restart;
336                 }
337         }
338         if (bearer_id >= MAX_BEARERS) {
339                 pr_warn("Bearer <%s> rejected, bearer limit reached (%u)\n",
340                         name, MAX_BEARERS);
341                 return -EINVAL;
342         }
343
344         b_ptr = kzalloc(sizeof(*b_ptr), GFP_ATOMIC);
345         if (!b_ptr)
346                 return -ENOMEM;
347
348         strcpy(b_ptr->name, name);
349         b_ptr->media = m_ptr;
350         res = m_ptr->enable_media(b_ptr);
351         if (res) {
352                 pr_warn("Bearer <%s> rejected, enable failure (%d)\n",
353                         name, -res);
354                 return -EINVAL;
355         }
356
357         b_ptr->identity = bearer_id;
358         b_ptr->tolerance = m_ptr->tolerance;
359         b_ptr->window = m_ptr->window;
360         b_ptr->domain = disc_domain;
361         b_ptr->net_plane = bearer_id + 'A';
362         b_ptr->priority = priority;
363
364         res = tipc_disc_create(b_ptr, &b_ptr->bcast_addr);
365         if (res) {
366                 bearer_disable(b_ptr, false);
367                 pr_warn("Bearer <%s> rejected, discovery object creation failed\n",
368                         name);
369                 return -EINVAL;
370         }
371
372         rcu_assign_pointer(bearer_list[bearer_id], b_ptr);
373
374         pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n",
375                 name,
376                 tipc_addr_string_fill(addr_string, disc_domain), priority);
377         return res;
378 }
379
380 /**
381  * tipc_reset_bearer - Reset all links established over this bearer
382  */
383 static int tipc_reset_bearer(struct tipc_bearer *b_ptr)
384 {
385         pr_info("Resetting bearer <%s>\n", b_ptr->name);
386         tipc_link_reset_list(b_ptr->identity);
387         tipc_disc_reset(b_ptr);
388         return 0;
389 }
390
391 /**
392  * bearer_disable
393  *
394  * Note: This routine assumes caller holds RTNL lock.
395  */
396 static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down)
397 {
398         u32 i;
399
400         pr_info("Disabling bearer <%s>\n", b_ptr->name);
401         b_ptr->media->disable_media(b_ptr);
402
403         tipc_link_delete_list(b_ptr->identity, shutting_down);
404         if (b_ptr->link_req)
405                 tipc_disc_delete(b_ptr->link_req);
406
407         for (i = 0; i < MAX_BEARERS; i++) {
408                 if (b_ptr == rtnl_dereference(bearer_list[i])) {
409                         RCU_INIT_POINTER(bearer_list[i], NULL);
410                         break;
411                 }
412         }
413         kfree_rcu(b_ptr, rcu);
414 }
415
416 int tipc_disable_bearer(const char *name)
417 {
418         struct tipc_bearer *b_ptr;
419         int res;
420
421         b_ptr = tipc_bearer_find(name);
422         if (b_ptr == NULL) {
423                 pr_warn("Attempt to disable unknown bearer <%s>\n", name);
424                 res = -EINVAL;
425         } else {
426                 bearer_disable(b_ptr, false);
427                 res = 0;
428         }
429         return res;
430 }
431
432 int tipc_enable_l2_media(struct tipc_bearer *b)
433 {
434         struct net_device *dev;
435         char *driver_name = strchr((const char *)b->name, ':') + 1;
436
437         /* Find device with specified name */
438         dev = dev_get_by_name(&init_net, driver_name);
439         if (!dev)
440                 return -ENODEV;
441
442         /* Associate TIPC bearer with L2 bearer */
443         rcu_assign_pointer(b->media_ptr, dev);
444         memset(&b->bcast_addr, 0, sizeof(b->bcast_addr));
445         memcpy(b->bcast_addr.value, dev->broadcast, b->media->hwaddr_len);
446         b->bcast_addr.media_id = b->media->type_id;
447         b->bcast_addr.broadcast = 1;
448         b->mtu = dev->mtu;
449         b->media->raw2addr(b, &b->addr, (char *)dev->dev_addr);
450         rcu_assign_pointer(dev->tipc_ptr, b);
451         return 0;
452 }
453
454 /* tipc_disable_l2_media - detach TIPC bearer from an L2 interface
455  *
456  * Mark L2 bearer as inactive so that incoming buffers are thrown away,
457  * then get worker thread to complete bearer cleanup.  (Can't do cleanup
458  * here because cleanup code needs to sleep and caller holds spinlocks.)
459  */
460 void tipc_disable_l2_media(struct tipc_bearer *b)
461 {
462         struct net_device *dev;
463
464         dev = (struct net_device *)rtnl_dereference(b->media_ptr);
465         RCU_INIT_POINTER(b->media_ptr, NULL);
466         RCU_INIT_POINTER(dev->tipc_ptr, NULL);
467         synchronize_net();
468         dev_put(dev);
469 }
470
471 /**
472  * tipc_l2_send_msg - send a TIPC packet out over an L2 interface
473  * @buf: the packet to be sent
474  * @b_ptr: the bearer through which the packet is to be sent
475  * @dest: peer destination address
476  */
477 int tipc_l2_send_msg(struct sk_buff *buf, struct tipc_bearer *b,
478                      struct tipc_media_addr *dest)
479 {
480         struct sk_buff *clone;
481         struct net_device *dev;
482         int delta;
483
484         dev = (struct net_device *)rcu_dereference_rtnl(b->media_ptr);
485         if (!dev)
486                 return 0;
487
488         clone = skb_clone(buf, GFP_ATOMIC);
489         if (!clone)
490                 return 0;
491
492         delta = dev->hard_header_len - skb_headroom(buf);
493         if ((delta > 0) &&
494             pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) {
495                 kfree_skb(clone);
496                 return 0;
497         }
498
499         skb_reset_network_header(clone);
500         clone->dev = dev;
501         clone->protocol = htons(ETH_P_TIPC);
502         dev_hard_header(clone, dev, ETH_P_TIPC, dest->value,
503                         dev->dev_addr, clone->len);
504         dev_queue_xmit(clone);
505         return 0;
506 }
507
508 /* tipc_bearer_send- sends buffer to destination over bearer
509  *
510  * IMPORTANT:
511  * The media send routine must not alter the buffer being passed in
512  * as it may be needed for later retransmission!
513  */
514 void tipc_bearer_send(u32 bearer_id, struct sk_buff *buf,
515                       struct tipc_media_addr *dest)
516 {
517         struct tipc_bearer *b_ptr;
518
519         rcu_read_lock();
520         b_ptr = rcu_dereference_rtnl(bearer_list[bearer_id]);
521         if (likely(b_ptr))
522                 b_ptr->media->send_msg(buf, b_ptr, dest);
523         rcu_read_unlock();
524 }
525
526 /**
527  * tipc_l2_rcv_msg - handle incoming TIPC message from an interface
528  * @buf: the received packet
529  * @dev: the net device that the packet was received on
530  * @pt: the packet_type structure which was used to register this handler
531  * @orig_dev: the original receive net device in case the device is a bond
532  *
533  * Accept only packets explicitly sent to this node, or broadcast packets;
534  * ignores packets sent using interface multicast, and traffic sent to other
535  * nodes (which can happen if interface is running in promiscuous mode).
536  */
537 static int tipc_l2_rcv_msg(struct sk_buff *buf, struct net_device *dev,
538                            struct packet_type *pt, struct net_device *orig_dev)
539 {
540         struct tipc_bearer *b_ptr;
541
542         if (!net_eq(dev_net(dev), &init_net)) {
543                 kfree_skb(buf);
544                 return NET_RX_DROP;
545         }
546
547         rcu_read_lock();
548         b_ptr = rcu_dereference_rtnl(dev->tipc_ptr);
549         if (likely(b_ptr)) {
550                 if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
551                         buf->next = NULL;
552                         tipc_rcv(buf, b_ptr);
553                         rcu_read_unlock();
554                         return NET_RX_SUCCESS;
555                 }
556         }
557         rcu_read_unlock();
558
559         kfree_skb(buf);
560         return NET_RX_DROP;
561 }
562
563 /**
564  * tipc_l2_device_event - handle device events from network device
565  * @nb: the context of the notification
566  * @evt: the type of event
567  * @ptr: the net device that the event was on
568  *
569  * This function is called by the Ethernet driver in case of link
570  * change event.
571  */
572 static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
573                                 void *ptr)
574 {
575         struct tipc_bearer *b_ptr;
576         struct net_device *dev = netdev_notifier_info_to_dev(ptr);
577
578         if (!net_eq(dev_net(dev), &init_net))
579                 return NOTIFY_DONE;
580
581         b_ptr = rtnl_dereference(dev->tipc_ptr);
582         if (!b_ptr)
583                 return NOTIFY_DONE;
584
585         b_ptr->mtu = dev->mtu;
586
587         switch (evt) {
588         case NETDEV_CHANGE:
589                 if (netif_carrier_ok(dev))
590                         break;
591         case NETDEV_DOWN:
592         case NETDEV_CHANGEMTU:
593                 tipc_reset_bearer(b_ptr);
594                 break;
595         case NETDEV_CHANGEADDR:
596                 b_ptr->media->raw2addr(b_ptr, &b_ptr->addr,
597                                        (char *)dev->dev_addr);
598                 tipc_reset_bearer(b_ptr);
599                 break;
600         case NETDEV_UNREGISTER:
601         case NETDEV_CHANGENAME:
602                 bearer_disable(b_ptr, false);
603                 break;
604         }
605         return NOTIFY_OK;
606 }
607
608 static struct packet_type tipc_packet_type __read_mostly = {
609         .type = htons(ETH_P_TIPC),
610         .func = tipc_l2_rcv_msg,
611 };
612
613 static struct notifier_block notifier = {
614         .notifier_call  = tipc_l2_device_event,
615         .priority       = 0,
616 };
617
618 int tipc_bearer_setup(void)
619 {
620         int err;
621
622         err = register_netdevice_notifier(&notifier);
623         if (err)
624                 return err;
625         dev_add_pack(&tipc_packet_type);
626         return 0;
627 }
628
629 void tipc_bearer_cleanup(void)
630 {
631         unregister_netdevice_notifier(&notifier);
632         dev_remove_pack(&tipc_packet_type);
633 }
634
635 void tipc_bearer_stop(void)
636 {
637         struct tipc_bearer *b_ptr;
638         u32 i;
639
640         for (i = 0; i < MAX_BEARERS; i++) {
641                 b_ptr = rtnl_dereference(bearer_list[i]);
642                 if (b_ptr) {
643                         bearer_disable(b_ptr, true);
644                         bearer_list[i] = NULL;
645                 }
646         }
647 }
648
649 /* Caller should hold rtnl_lock to protect the bearer */
650 int __tipc_nl_add_bearer(struct tipc_nl_msg *msg, struct tipc_bearer *bearer)
651 {
652         void *hdr;
653         struct nlattr *attrs;
654         struct nlattr *prop;
655
656         hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_v2_family,
657                           NLM_F_MULTI, TIPC_NL_BEARER_GET);
658         if (!hdr)
659                 return -EMSGSIZE;
660
661         attrs = nla_nest_start(msg->skb, TIPC_NLA_BEARER);
662         if (!attrs)
663                 goto msg_full;
664
665         if (nla_put_string(msg->skb, TIPC_NLA_BEARER_NAME, bearer->name))
666                 goto attr_msg_full;
667
668         prop = nla_nest_start(msg->skb, TIPC_NLA_BEARER_PROP);
669         if (!prop)
670                 goto prop_msg_full;
671         if (nla_put_u32(msg->skb, TIPC_NLA_PROP_PRIO, bearer->priority))
672                 goto prop_msg_full;
673         if (nla_put_u32(msg->skb, TIPC_NLA_PROP_TOL, bearer->tolerance))
674                 goto prop_msg_full;
675         if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, bearer->window))
676                 goto prop_msg_full;
677
678         nla_nest_end(msg->skb, prop);
679         nla_nest_end(msg->skb, attrs);
680         genlmsg_end(msg->skb, hdr);
681
682         return 0;
683
684 prop_msg_full:
685         nla_nest_cancel(msg->skb, prop);
686 attr_msg_full:
687         nla_nest_cancel(msg->skb, attrs);
688 msg_full:
689         genlmsg_cancel(msg->skb, hdr);
690
691         return -EMSGSIZE;
692 }
693
694 int tipc_nl_bearer_dump(struct sk_buff *skb, struct netlink_callback *cb)
695 {
696         int err;
697         int i = cb->args[0];
698         struct tipc_bearer *bearer;
699         struct tipc_nl_msg msg;
700
701         if (i == MAX_BEARERS)
702                 return 0;
703
704         msg.skb = skb;
705         msg.portid = NETLINK_CB(cb->skb).portid;
706         msg.seq = cb->nlh->nlmsg_seq;
707
708         rtnl_lock();
709         for (i = 0; i < MAX_BEARERS; i++) {
710                 bearer = rtnl_dereference(bearer_list[i]);
711                 if (!bearer)
712                         continue;
713
714                 err = __tipc_nl_add_bearer(&msg, bearer);
715                 if (err)
716                         break;
717         }
718         rtnl_unlock();
719
720         cb->args[0] = i;
721         return skb->len;
722 }
723
724 int tipc_nl_bearer_get(struct sk_buff *skb, struct genl_info *info)
725 {
726         int err;
727         char *name;
728         struct sk_buff *rep;
729         struct tipc_bearer *bearer;
730         struct tipc_nl_msg msg;
731         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
732
733         if (!info->attrs[TIPC_NLA_BEARER])
734                 return -EINVAL;
735
736         err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
737                                info->attrs[TIPC_NLA_BEARER],
738                                tipc_nl_bearer_policy);
739         if (err)
740                 return err;
741
742         if (!attrs[TIPC_NLA_BEARER_NAME])
743                 return -EINVAL;
744         name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
745
746         rep = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
747         if (!rep)
748                 return -ENOMEM;
749
750         msg.skb = rep;
751         msg.portid = info->snd_portid;
752         msg.seq = info->snd_seq;
753
754         rtnl_lock();
755         bearer = tipc_bearer_find(name);
756         if (!bearer) {
757                 err = -EINVAL;
758                 goto err_out;
759         }
760
761         err = __tipc_nl_add_bearer(&msg, bearer);
762         if (err)
763                 goto err_out;
764         rtnl_unlock();
765
766         return genlmsg_reply(rep, info);
767 err_out:
768         rtnl_unlock();
769         nlmsg_free(rep);
770
771         return err;
772 }
773
774 int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info)
775 {
776         int err;
777         char *name;
778         struct tipc_bearer *bearer;
779         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
780
781         if (!info->attrs[TIPC_NLA_BEARER])
782                 return -EINVAL;
783
784         err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
785                                info->attrs[TIPC_NLA_BEARER],
786                                tipc_nl_bearer_policy);
787         if (err)
788                 return err;
789
790         if (!attrs[TIPC_NLA_BEARER_NAME])
791                 return -EINVAL;
792
793         name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
794
795         rtnl_lock();
796         bearer = tipc_bearer_find(name);
797         if (!bearer) {
798                 rtnl_unlock();
799                 return -EINVAL;
800         }
801
802         bearer_disable(bearer, false);
803         rtnl_unlock();
804
805         return 0;
806 }
807
808 int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info)
809 {
810         int err;
811         char *bearer;
812         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
813         u32 domain;
814         u32 prio;
815
816         prio = TIPC_MEDIA_LINK_PRI;
817         domain = tipc_own_addr & TIPC_CLUSTER_MASK;
818
819         if (!info->attrs[TIPC_NLA_BEARER])
820                 return -EINVAL;
821
822         err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
823                                info->attrs[TIPC_NLA_BEARER],
824                                tipc_nl_bearer_policy);
825         if (err)
826                 return err;
827
828         if (!attrs[TIPC_NLA_BEARER_NAME])
829                 return -EINVAL;
830
831         bearer = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
832
833         if (attrs[TIPC_NLA_BEARER_DOMAIN])
834                 domain = nla_get_u32(attrs[TIPC_NLA_BEARER_DOMAIN]);
835
836         if (attrs[TIPC_NLA_BEARER_PROP]) {
837                 struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
838
839                 err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_BEARER_PROP],
840                                               props);
841                 if (err)
842                         return err;
843
844                 if (props[TIPC_NLA_PROP_PRIO])
845                         prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
846         }
847
848         rtnl_lock();
849         err = tipc_enable_bearer(bearer, domain, prio);
850         if (err) {
851                 rtnl_unlock();
852                 return err;
853         }
854         rtnl_unlock();
855
856         return 0;
857 }
858
859 int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info)
860 {
861         int err;
862         char *name;
863         struct tipc_bearer *b;
864         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
865
866         if (!info->attrs[TIPC_NLA_BEARER])
867                 return -EINVAL;
868
869         err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
870                                info->attrs[TIPC_NLA_BEARER],
871                                tipc_nl_bearer_policy);
872         if (err)
873                 return err;
874
875         if (!attrs[TIPC_NLA_BEARER_NAME])
876                 return -EINVAL;
877         name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
878
879         rtnl_lock();
880         b = tipc_bearer_find(name);
881         if (!b) {
882                 rtnl_unlock();
883                 return -EINVAL;
884         }
885
886         if (attrs[TIPC_NLA_BEARER_PROP]) {
887                 struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
888
889                 err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_BEARER_PROP],
890                                               props);
891                 if (err) {
892                         rtnl_unlock();
893                         return err;
894                 }
895
896                 if (props[TIPC_NLA_PROP_TOL])
897                         b->tolerance = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
898                 if (props[TIPC_NLA_PROP_PRIO])
899                         b->priority = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
900                 if (props[TIPC_NLA_PROP_WIN])
901                         b->window = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
902         }
903         rtnl_unlock();
904
905         return 0;
906 }
907
908 int __tipc_nl_add_media(struct tipc_nl_msg *msg, struct tipc_media *media)
909 {
910         void *hdr;
911         struct nlattr *attrs;
912         struct nlattr *prop;
913
914         hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_v2_family,
915                           NLM_F_MULTI, TIPC_NL_MEDIA_GET);
916         if (!hdr)
917                 return -EMSGSIZE;
918
919         attrs = nla_nest_start(msg->skb, TIPC_NLA_MEDIA);
920         if (!attrs)
921                 goto msg_full;
922
923         if (nla_put_string(msg->skb, TIPC_NLA_MEDIA_NAME, media->name))
924                 goto attr_msg_full;
925
926         prop = nla_nest_start(msg->skb, TIPC_NLA_MEDIA_PROP);
927         if (!prop)
928                 goto prop_msg_full;
929         if (nla_put_u32(msg->skb, TIPC_NLA_PROP_PRIO, media->priority))
930                 goto prop_msg_full;
931         if (nla_put_u32(msg->skb, TIPC_NLA_PROP_TOL, media->tolerance))
932                 goto prop_msg_full;
933         if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, media->window))
934                 goto prop_msg_full;
935
936         nla_nest_end(msg->skb, prop);
937         nla_nest_end(msg->skb, attrs);
938         genlmsg_end(msg->skb, hdr);
939
940         return 0;
941
942 prop_msg_full:
943         nla_nest_cancel(msg->skb, prop);
944 attr_msg_full:
945         nla_nest_cancel(msg->skb, attrs);
946 msg_full:
947         genlmsg_cancel(msg->skb, hdr);
948
949         return -EMSGSIZE;
950 }
951
952 int tipc_nl_media_dump(struct sk_buff *skb, struct netlink_callback *cb)
953 {
954         int err;
955         int i = cb->args[0];
956         struct tipc_nl_msg msg;
957
958         if (i == MAX_MEDIA)
959                 return 0;
960
961         msg.skb = skb;
962         msg.portid = NETLINK_CB(cb->skb).portid;
963         msg.seq = cb->nlh->nlmsg_seq;
964
965         rtnl_lock();
966         for (; media_info_array[i] != NULL; i++) {
967                 err = __tipc_nl_add_media(&msg, media_info_array[i]);
968                 if (err)
969                         break;
970         }
971         rtnl_unlock();
972
973         cb->args[0] = i;
974         return skb->len;
975 }
976
977 int tipc_nl_media_get(struct sk_buff *skb, struct genl_info *info)
978 {
979         int err;
980         char *name;
981         struct tipc_nl_msg msg;
982         struct tipc_media *media;
983         struct sk_buff *rep;
984         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
985
986         if (!info->attrs[TIPC_NLA_MEDIA])
987                 return -EINVAL;
988
989         err = nla_parse_nested(attrs, TIPC_NLA_MEDIA_MAX,
990                                info->attrs[TIPC_NLA_MEDIA],
991                                tipc_nl_media_policy);
992         if (err)
993                 return err;
994
995         if (!attrs[TIPC_NLA_MEDIA_NAME])
996                 return -EINVAL;
997         name = nla_data(attrs[TIPC_NLA_MEDIA_NAME]);
998
999         rep = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1000         if (!rep)
1001                 return -ENOMEM;
1002
1003         msg.skb = rep;
1004         msg.portid = info->snd_portid;
1005         msg.seq = info->snd_seq;
1006
1007         rtnl_lock();
1008         media = tipc_media_find(name);
1009         if (!media) {
1010                 err = -EINVAL;
1011                 goto err_out;
1012         }
1013
1014         err = __tipc_nl_add_media(&msg, media);
1015         if (err)
1016                 goto err_out;
1017         rtnl_unlock();
1018
1019         return genlmsg_reply(rep, info);
1020 err_out:
1021         rtnl_unlock();
1022         nlmsg_free(rep);
1023
1024         return err;
1025 }
1026
1027 int tipc_nl_media_set(struct sk_buff *skb, struct genl_info *info)
1028 {
1029         int err;
1030         char *name;
1031         struct tipc_media *m;
1032         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
1033
1034         if (!info->attrs[TIPC_NLA_MEDIA])
1035                 return -EINVAL;
1036
1037         err = nla_parse_nested(attrs, TIPC_NLA_MEDIA_MAX,
1038                                info->attrs[TIPC_NLA_MEDIA],
1039                                tipc_nl_media_policy);
1040
1041         if (!attrs[TIPC_NLA_MEDIA_NAME])
1042                 return -EINVAL;
1043         name = nla_data(attrs[TIPC_NLA_MEDIA_NAME]);
1044
1045         rtnl_lock();
1046         m = tipc_media_find(name);
1047         if (!m) {
1048                 rtnl_unlock();
1049                 return -EINVAL;
1050         }
1051
1052         if (attrs[TIPC_NLA_MEDIA_PROP]) {
1053                 struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
1054
1055                 err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_MEDIA_PROP],
1056                                               props);
1057                 if (err) {
1058                         rtnl_unlock();
1059                         return err;
1060                 }
1061
1062                 if (props[TIPC_NLA_PROP_TOL])
1063                         m->tolerance = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
1064                 if (props[TIPC_NLA_PROP_PRIO])
1065                         m->priority = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
1066                 if (props[TIPC_NLA_PROP_WIN])
1067                         m->window = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
1068         }
1069         rtnl_unlock();
1070
1071         return 0;
1072 }