tipc: add bearer set to new netlink api
[firefly-linux-kernel-4.4.55.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 struct tipc_bearer __rcu *bearer_list[MAX_BEARERS + 1];
65
66 static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down);
67
68 /**
69  * tipc_media_find - locates specified media object by name
70  */
71 struct tipc_media *tipc_media_find(const char *name)
72 {
73         u32 i;
74
75         for (i = 0; media_info_array[i] != NULL; i++) {
76                 if (!strcmp(media_info_array[i]->name, name))
77                         break;
78         }
79         return media_info_array[i];
80 }
81
82 /**
83  * media_find_id - locates specified media object by type identifier
84  */
85 static struct tipc_media *media_find_id(u8 type)
86 {
87         u32 i;
88
89         for (i = 0; media_info_array[i] != NULL; i++) {
90                 if (media_info_array[i]->type_id == type)
91                         break;
92         }
93         return media_info_array[i];
94 }
95
96 /**
97  * tipc_media_addr_printf - record media address in print buffer
98  */
99 void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a)
100 {
101         char addr_str[MAX_ADDR_STR];
102         struct tipc_media *m_ptr;
103         int ret;
104
105         m_ptr = media_find_id(a->media_id);
106
107         if (m_ptr && !m_ptr->addr2str(a, addr_str, sizeof(addr_str)))
108                 ret = tipc_snprintf(buf, len, "%s(%s)", m_ptr->name, addr_str);
109         else {
110                 u32 i;
111
112                 ret = tipc_snprintf(buf, len, "UNKNOWN(%u)", a->media_id);
113                 for (i = 0; i < sizeof(a->value); i++)
114                         ret += tipc_snprintf(buf - ret, len + ret,
115                                             "-%02x", a->value[i]);
116         }
117 }
118
119 /**
120  * tipc_media_get_names - record names of registered media in buffer
121  */
122 struct sk_buff *tipc_media_get_names(void)
123 {
124         struct sk_buff *buf;
125         int i;
126
127         buf = tipc_cfg_reply_alloc(MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME));
128         if (!buf)
129                 return NULL;
130
131         for (i = 0; media_info_array[i] != NULL; i++) {
132                 tipc_cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME,
133                                     media_info_array[i]->name,
134                                     strlen(media_info_array[i]->name) + 1);
135         }
136         return buf;
137 }
138
139 /**
140  * bearer_name_validate - validate & (optionally) deconstruct bearer name
141  * @name: ptr to bearer name string
142  * @name_parts: ptr to area for bearer name components (or NULL if not needed)
143  *
144  * Returns 1 if bearer name is valid, otherwise 0.
145  */
146 static int bearer_name_validate(const char *name,
147                                 struct tipc_bearer_names *name_parts)
148 {
149         char name_copy[TIPC_MAX_BEARER_NAME];
150         char *media_name;
151         char *if_name;
152         u32 media_len;
153         u32 if_len;
154
155         /* copy bearer name & ensure length is OK */
156         name_copy[TIPC_MAX_BEARER_NAME - 1] = 0;
157         /* need above in case non-Posix strncpy() doesn't pad with nulls */
158         strncpy(name_copy, name, TIPC_MAX_BEARER_NAME);
159         if (name_copy[TIPC_MAX_BEARER_NAME - 1] != 0)
160                 return 0;
161
162         /* ensure all component parts of bearer name are present */
163         media_name = name_copy;
164         if_name = strchr(media_name, ':');
165         if (if_name == NULL)
166                 return 0;
167         *(if_name++) = 0;
168         media_len = if_name - media_name;
169         if_len = strlen(if_name) + 1;
170
171         /* validate component parts of bearer name */
172         if ((media_len <= 1) || (media_len > TIPC_MAX_MEDIA_NAME) ||
173             (if_len <= 1) || (if_len > TIPC_MAX_IF_NAME))
174                 return 0;
175
176         /* return bearer name components, if necessary */
177         if (name_parts) {
178                 strcpy(name_parts->media_name, media_name);
179                 strcpy(name_parts->if_name, if_name);
180         }
181         return 1;
182 }
183
184 /**
185  * tipc_bearer_find - locates bearer object with matching bearer name
186  */
187 struct tipc_bearer *tipc_bearer_find(const char *name)
188 {
189         struct tipc_bearer *b_ptr;
190         u32 i;
191
192         for (i = 0; i < MAX_BEARERS; i++) {
193                 b_ptr = rtnl_dereference(bearer_list[i]);
194                 if (b_ptr && (!strcmp(b_ptr->name, name)))
195                         return b_ptr;
196         }
197         return NULL;
198 }
199
200 /**
201  * tipc_bearer_get_names - record names of bearers in buffer
202  */
203 struct sk_buff *tipc_bearer_get_names(void)
204 {
205         struct sk_buff *buf;
206         struct tipc_bearer *b;
207         int i, j;
208
209         buf = tipc_cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME));
210         if (!buf)
211                 return NULL;
212
213         for (i = 0; media_info_array[i] != NULL; i++) {
214                 for (j = 0; j < MAX_BEARERS; j++) {
215                         b = rtnl_dereference(bearer_list[j]);
216                         if (!b)
217                                 continue;
218                         if (b->media == media_info_array[i]) {
219                                 tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME,
220                                                     b->name,
221                                                     strlen(b->name) + 1);
222                         }
223                 }
224         }
225         return buf;
226 }
227
228 void tipc_bearer_add_dest(u32 bearer_id, u32 dest)
229 {
230         struct tipc_bearer *b_ptr;
231
232         rcu_read_lock();
233         b_ptr = rcu_dereference_rtnl(bearer_list[bearer_id]);
234         if (b_ptr) {
235                 tipc_bcbearer_sort(&b_ptr->nodes, dest, true);
236                 tipc_disc_add_dest(b_ptr->link_req);
237         }
238         rcu_read_unlock();
239 }
240
241 void tipc_bearer_remove_dest(u32 bearer_id, u32 dest)
242 {
243         struct tipc_bearer *b_ptr;
244
245         rcu_read_lock();
246         b_ptr = rcu_dereference_rtnl(bearer_list[bearer_id]);
247         if (b_ptr) {
248                 tipc_bcbearer_sort(&b_ptr->nodes, dest, false);
249                 tipc_disc_remove_dest(b_ptr->link_req);
250         }
251         rcu_read_unlock();
252 }
253
254 /**
255  * tipc_enable_bearer - enable bearer with the given name
256  */
257 int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
258 {
259         struct tipc_bearer *b_ptr;
260         struct tipc_media *m_ptr;
261         struct tipc_bearer_names b_names;
262         char addr_string[16];
263         u32 bearer_id;
264         u32 with_this_prio;
265         u32 i;
266         int res = -EINVAL;
267
268         if (!tipc_own_addr) {
269                 pr_warn("Bearer <%s> rejected, not supported in standalone mode\n",
270                         name);
271                 return -ENOPROTOOPT;
272         }
273         if (!bearer_name_validate(name, &b_names)) {
274                 pr_warn("Bearer <%s> rejected, illegal name\n", name);
275                 return -EINVAL;
276         }
277         if (tipc_addr_domain_valid(disc_domain) &&
278             (disc_domain != tipc_own_addr)) {
279                 if (tipc_in_scope(disc_domain, tipc_own_addr)) {
280                         disc_domain = tipc_own_addr & TIPC_CLUSTER_MASK;
281                         res = 0;   /* accept any node in own cluster */
282                 } else if (in_own_cluster_exact(disc_domain))
283                         res = 0;   /* accept specified node in own cluster */
284         }
285         if (res) {
286                 pr_warn("Bearer <%s> rejected, illegal discovery domain\n",
287                         name);
288                 return -EINVAL;
289         }
290         if ((priority > TIPC_MAX_LINK_PRI) &&
291             (priority != TIPC_MEDIA_LINK_PRI)) {
292                 pr_warn("Bearer <%s> rejected, illegal priority\n", name);
293                 return -EINVAL;
294         }
295
296         m_ptr = tipc_media_find(b_names.media_name);
297         if (!m_ptr) {
298                 pr_warn("Bearer <%s> rejected, media <%s> not registered\n",
299                         name, b_names.media_name);
300                 return -EINVAL;
301         }
302
303         if (priority == TIPC_MEDIA_LINK_PRI)
304                 priority = m_ptr->priority;
305
306 restart:
307         bearer_id = MAX_BEARERS;
308         with_this_prio = 1;
309         for (i = MAX_BEARERS; i-- != 0; ) {
310                 b_ptr = rtnl_dereference(bearer_list[i]);
311                 if (!b_ptr) {
312                         bearer_id = i;
313                         continue;
314                 }
315                 if (!strcmp(name, b_ptr->name)) {
316                         pr_warn("Bearer <%s> rejected, already enabled\n",
317                                 name);
318                         return -EINVAL;
319                 }
320                 if ((b_ptr->priority == priority) &&
321                     (++with_this_prio > 2)) {
322                         if (priority-- == 0) {
323                                 pr_warn("Bearer <%s> rejected, duplicate priority\n",
324                                         name);
325                                 return -EINVAL;
326                         }
327                         pr_warn("Bearer <%s> priority adjustment required %u->%u\n",
328                                 name, priority + 1, priority);
329                         goto restart;
330                 }
331         }
332         if (bearer_id >= MAX_BEARERS) {
333                 pr_warn("Bearer <%s> rejected, bearer limit reached (%u)\n",
334                         name, MAX_BEARERS);
335                 return -EINVAL;
336         }
337
338         b_ptr = kzalloc(sizeof(*b_ptr), GFP_ATOMIC);
339         if (!b_ptr)
340                 return -ENOMEM;
341
342         strcpy(b_ptr->name, name);
343         b_ptr->media = m_ptr;
344         res = m_ptr->enable_media(b_ptr);
345         if (res) {
346                 pr_warn("Bearer <%s> rejected, enable failure (%d)\n",
347                         name, -res);
348                 return -EINVAL;
349         }
350
351         b_ptr->identity = bearer_id;
352         b_ptr->tolerance = m_ptr->tolerance;
353         b_ptr->window = m_ptr->window;
354         b_ptr->domain = disc_domain;
355         b_ptr->net_plane = bearer_id + 'A';
356         b_ptr->priority = priority;
357
358         res = tipc_disc_create(b_ptr, &b_ptr->bcast_addr);
359         if (res) {
360                 bearer_disable(b_ptr, false);
361                 pr_warn("Bearer <%s> rejected, discovery object creation failed\n",
362                         name);
363                 return -EINVAL;
364         }
365
366         rcu_assign_pointer(bearer_list[bearer_id], b_ptr);
367
368         pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n",
369                 name,
370                 tipc_addr_string_fill(addr_string, disc_domain), priority);
371         return res;
372 }
373
374 /**
375  * tipc_reset_bearer - Reset all links established over this bearer
376  */
377 static int tipc_reset_bearer(struct tipc_bearer *b_ptr)
378 {
379         pr_info("Resetting bearer <%s>\n", b_ptr->name);
380         tipc_link_reset_list(b_ptr->identity);
381         tipc_disc_reset(b_ptr);
382         return 0;
383 }
384
385 /**
386  * bearer_disable
387  *
388  * Note: This routine assumes caller holds RTNL lock.
389  */
390 static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down)
391 {
392         u32 i;
393
394         pr_info("Disabling bearer <%s>\n", b_ptr->name);
395         b_ptr->media->disable_media(b_ptr);
396
397         tipc_link_delete_list(b_ptr->identity, shutting_down);
398         if (b_ptr->link_req)
399                 tipc_disc_delete(b_ptr->link_req);
400
401         for (i = 0; i < MAX_BEARERS; i++) {
402                 if (b_ptr == rtnl_dereference(bearer_list[i])) {
403                         RCU_INIT_POINTER(bearer_list[i], NULL);
404                         break;
405                 }
406         }
407         kfree_rcu(b_ptr, rcu);
408 }
409
410 int tipc_disable_bearer(const char *name)
411 {
412         struct tipc_bearer *b_ptr;
413         int res;
414
415         b_ptr = tipc_bearer_find(name);
416         if (b_ptr == NULL) {
417                 pr_warn("Attempt to disable unknown bearer <%s>\n", name);
418                 res = -EINVAL;
419         } else {
420                 bearer_disable(b_ptr, false);
421                 res = 0;
422         }
423         return res;
424 }
425
426 int tipc_enable_l2_media(struct tipc_bearer *b)
427 {
428         struct net_device *dev;
429         char *driver_name = strchr((const char *)b->name, ':') + 1;
430
431         /* Find device with specified name */
432         dev = dev_get_by_name(&init_net, driver_name);
433         if (!dev)
434                 return -ENODEV;
435
436         /* Associate TIPC bearer with L2 bearer */
437         rcu_assign_pointer(b->media_ptr, dev);
438         memset(&b->bcast_addr, 0, sizeof(b->bcast_addr));
439         memcpy(b->bcast_addr.value, dev->broadcast, b->media->hwaddr_len);
440         b->bcast_addr.media_id = b->media->type_id;
441         b->bcast_addr.broadcast = 1;
442         b->mtu = dev->mtu;
443         b->media->raw2addr(b, &b->addr, (char *)dev->dev_addr);
444         rcu_assign_pointer(dev->tipc_ptr, b);
445         return 0;
446 }
447
448 /* tipc_disable_l2_media - detach TIPC bearer from an L2 interface
449  *
450  * Mark L2 bearer as inactive so that incoming buffers are thrown away,
451  * then get worker thread to complete bearer cleanup.  (Can't do cleanup
452  * here because cleanup code needs to sleep and caller holds spinlocks.)
453  */
454 void tipc_disable_l2_media(struct tipc_bearer *b)
455 {
456         struct net_device *dev;
457
458         dev = (struct net_device *)rtnl_dereference(b->media_ptr);
459         RCU_INIT_POINTER(b->media_ptr, NULL);
460         RCU_INIT_POINTER(dev->tipc_ptr, NULL);
461         synchronize_net();
462         dev_put(dev);
463 }
464
465 /**
466  * tipc_l2_send_msg - send a TIPC packet out over an L2 interface
467  * @buf: the packet to be sent
468  * @b_ptr: the bearer through which the packet is to be sent
469  * @dest: peer destination address
470  */
471 int tipc_l2_send_msg(struct sk_buff *buf, struct tipc_bearer *b,
472                      struct tipc_media_addr *dest)
473 {
474         struct sk_buff *clone;
475         struct net_device *dev;
476         int delta;
477
478         dev = (struct net_device *)rcu_dereference_rtnl(b->media_ptr);
479         if (!dev)
480                 return 0;
481
482         clone = skb_clone(buf, GFP_ATOMIC);
483         if (!clone)
484                 return 0;
485
486         delta = dev->hard_header_len - skb_headroom(buf);
487         if ((delta > 0) &&
488             pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) {
489                 kfree_skb(clone);
490                 return 0;
491         }
492
493         skb_reset_network_header(clone);
494         clone->dev = dev;
495         clone->protocol = htons(ETH_P_TIPC);
496         dev_hard_header(clone, dev, ETH_P_TIPC, dest->value,
497                         dev->dev_addr, clone->len);
498         dev_queue_xmit(clone);
499         return 0;
500 }
501
502 /* tipc_bearer_send- sends buffer to destination over bearer
503  *
504  * IMPORTANT:
505  * The media send routine must not alter the buffer being passed in
506  * as it may be needed for later retransmission!
507  */
508 void tipc_bearer_send(u32 bearer_id, struct sk_buff *buf,
509                       struct tipc_media_addr *dest)
510 {
511         struct tipc_bearer *b_ptr;
512
513         rcu_read_lock();
514         b_ptr = rcu_dereference_rtnl(bearer_list[bearer_id]);
515         if (likely(b_ptr))
516                 b_ptr->media->send_msg(buf, b_ptr, dest);
517         rcu_read_unlock();
518 }
519
520 /**
521  * tipc_l2_rcv_msg - handle incoming TIPC message from an interface
522  * @buf: the received packet
523  * @dev: the net device that the packet was received on
524  * @pt: the packet_type structure which was used to register this handler
525  * @orig_dev: the original receive net device in case the device is a bond
526  *
527  * Accept only packets explicitly sent to this node, or broadcast packets;
528  * ignores packets sent using interface multicast, and traffic sent to other
529  * nodes (which can happen if interface is running in promiscuous mode).
530  */
531 static int tipc_l2_rcv_msg(struct sk_buff *buf, struct net_device *dev,
532                            struct packet_type *pt, struct net_device *orig_dev)
533 {
534         struct tipc_bearer *b_ptr;
535
536         if (!net_eq(dev_net(dev), &init_net)) {
537                 kfree_skb(buf);
538                 return NET_RX_DROP;
539         }
540
541         rcu_read_lock();
542         b_ptr = rcu_dereference_rtnl(dev->tipc_ptr);
543         if (likely(b_ptr)) {
544                 if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
545                         buf->next = NULL;
546                         tipc_rcv(buf, b_ptr);
547                         rcu_read_unlock();
548                         return NET_RX_SUCCESS;
549                 }
550         }
551         rcu_read_unlock();
552
553         kfree_skb(buf);
554         return NET_RX_DROP;
555 }
556
557 /**
558  * tipc_l2_device_event - handle device events from network device
559  * @nb: the context of the notification
560  * @evt: the type of event
561  * @ptr: the net device that the event was on
562  *
563  * This function is called by the Ethernet driver in case of link
564  * change event.
565  */
566 static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
567                                 void *ptr)
568 {
569         struct tipc_bearer *b_ptr;
570         struct net_device *dev = netdev_notifier_info_to_dev(ptr);
571
572         if (!net_eq(dev_net(dev), &init_net))
573                 return NOTIFY_DONE;
574
575         b_ptr = rtnl_dereference(dev->tipc_ptr);
576         if (!b_ptr)
577                 return NOTIFY_DONE;
578
579         b_ptr->mtu = dev->mtu;
580
581         switch (evt) {
582         case NETDEV_CHANGE:
583                 if (netif_carrier_ok(dev))
584                         break;
585         case NETDEV_DOWN:
586         case NETDEV_CHANGEMTU:
587                 tipc_reset_bearer(b_ptr);
588                 break;
589         case NETDEV_CHANGEADDR:
590                 b_ptr->media->raw2addr(b_ptr, &b_ptr->addr,
591                                        (char *)dev->dev_addr);
592                 tipc_reset_bearer(b_ptr);
593                 break;
594         case NETDEV_UNREGISTER:
595         case NETDEV_CHANGENAME:
596                 bearer_disable(b_ptr, false);
597                 break;
598         }
599         return NOTIFY_OK;
600 }
601
602 static struct packet_type tipc_packet_type __read_mostly = {
603         .type = htons(ETH_P_TIPC),
604         .func = tipc_l2_rcv_msg,
605 };
606
607 static struct notifier_block notifier = {
608         .notifier_call  = tipc_l2_device_event,
609         .priority       = 0,
610 };
611
612 int tipc_bearer_setup(void)
613 {
614         int err;
615
616         err = register_netdevice_notifier(&notifier);
617         if (err)
618                 return err;
619         dev_add_pack(&tipc_packet_type);
620         return 0;
621 }
622
623 void tipc_bearer_cleanup(void)
624 {
625         unregister_netdevice_notifier(&notifier);
626         dev_remove_pack(&tipc_packet_type);
627 }
628
629 void tipc_bearer_stop(void)
630 {
631         struct tipc_bearer *b_ptr;
632         u32 i;
633
634         for (i = 0; i < MAX_BEARERS; i++) {
635                 b_ptr = rtnl_dereference(bearer_list[i]);
636                 if (b_ptr) {
637                         bearer_disable(b_ptr, true);
638                         bearer_list[i] = NULL;
639                 }
640         }
641 }
642
643 /* Caller should hold rtnl_lock to protect the bearer */
644 int __tipc_nl_add_bearer(struct tipc_nl_msg *msg, struct tipc_bearer *bearer)
645 {
646         void *hdr;
647         struct nlattr *attrs;
648         struct nlattr *prop;
649
650         hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_v2_family,
651                           NLM_F_MULTI, TIPC_NL_BEARER_GET);
652         if (!hdr)
653                 return -EMSGSIZE;
654
655         attrs = nla_nest_start(msg->skb, TIPC_NLA_BEARER);
656         if (!attrs)
657                 goto msg_full;
658
659         if (nla_put_string(msg->skb, TIPC_NLA_BEARER_NAME, bearer->name))
660                 goto attr_msg_full;
661
662         prop = nla_nest_start(msg->skb, TIPC_NLA_BEARER_PROP);
663         if (!prop)
664                 goto prop_msg_full;
665         if (nla_put_u32(msg->skb, TIPC_NLA_PROP_PRIO, bearer->priority))
666                 goto prop_msg_full;
667         if (nla_put_u32(msg->skb, TIPC_NLA_PROP_TOL, bearer->tolerance))
668                 goto prop_msg_full;
669         if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, bearer->window))
670                 goto prop_msg_full;
671
672         nla_nest_end(msg->skb, prop);
673         nla_nest_end(msg->skb, attrs);
674         genlmsg_end(msg->skb, hdr);
675
676         return 0;
677
678 prop_msg_full:
679         nla_nest_cancel(msg->skb, prop);
680 attr_msg_full:
681         nla_nest_cancel(msg->skb, attrs);
682 msg_full:
683         genlmsg_cancel(msg->skb, hdr);
684
685         return -EMSGSIZE;
686 }
687
688 int tipc_nl_bearer_dump(struct sk_buff *skb, struct netlink_callback *cb)
689 {
690         int err;
691         int i = cb->args[0];
692         struct tipc_bearer *bearer;
693         struct tipc_nl_msg msg;
694
695         if (i == MAX_BEARERS)
696                 return 0;
697
698         msg.skb = skb;
699         msg.portid = NETLINK_CB(cb->skb).portid;
700         msg.seq = cb->nlh->nlmsg_seq;
701
702         rtnl_lock();
703         for (i = 0; i < MAX_BEARERS; i++) {
704                 bearer = rtnl_dereference(bearer_list[i]);
705                 if (!bearer)
706                         continue;
707
708                 err = __tipc_nl_add_bearer(&msg, bearer);
709                 if (err)
710                         break;
711         }
712         rtnl_unlock();
713
714         cb->args[0] = i;
715         return skb->len;
716 }
717
718 int tipc_nl_bearer_get(struct sk_buff *skb, struct genl_info *info)
719 {
720         int err;
721         char *name;
722         struct sk_buff *rep;
723         struct tipc_bearer *bearer;
724         struct tipc_nl_msg msg;
725         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
726
727         if (!info->attrs[TIPC_NLA_BEARER])
728                 return -EINVAL;
729
730         err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
731                                info->attrs[TIPC_NLA_BEARER],
732                                tipc_nl_bearer_policy);
733         if (err)
734                 return err;
735
736         if (!attrs[TIPC_NLA_BEARER_NAME])
737                 return -EINVAL;
738         name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
739
740         rep = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
741         if (!rep)
742                 return -ENOMEM;
743
744         msg.skb = rep;
745         msg.portid = info->snd_portid;
746         msg.seq = info->snd_seq;
747
748         rtnl_lock();
749         bearer = tipc_bearer_find(name);
750         if (!bearer) {
751                 err = -EINVAL;
752                 goto err_out;
753         }
754
755         err = __tipc_nl_add_bearer(&msg, bearer);
756         if (err)
757                 goto err_out;
758         rtnl_unlock();
759
760         return genlmsg_reply(rep, info);
761 err_out:
762         rtnl_unlock();
763         nlmsg_free(rep);
764
765         return err;
766 }
767
768 int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info)
769 {
770         int err;
771         char *name;
772         struct tipc_bearer *bearer;
773         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
774
775         if (!info->attrs[TIPC_NLA_BEARER])
776                 return -EINVAL;
777
778         err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
779                                info->attrs[TIPC_NLA_BEARER],
780                                tipc_nl_bearer_policy);
781         if (err)
782                 return err;
783
784         if (!attrs[TIPC_NLA_BEARER_NAME])
785                 return -EINVAL;
786
787         name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
788
789         rtnl_lock();
790         bearer = tipc_bearer_find(name);
791         if (!bearer) {
792                 rtnl_unlock();
793                 return -EINVAL;
794         }
795
796         bearer_disable(bearer, false);
797         rtnl_unlock();
798
799         return 0;
800 }
801
802 int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info)
803 {
804         int err;
805         char *bearer;
806         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
807         u32 domain;
808         u32 prio;
809
810         prio = TIPC_MEDIA_LINK_PRI;
811         domain = tipc_own_addr & TIPC_CLUSTER_MASK;
812
813         if (!info->attrs[TIPC_NLA_BEARER])
814                 return -EINVAL;
815
816         err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
817                                info->attrs[TIPC_NLA_BEARER],
818                                tipc_nl_bearer_policy);
819         if (err)
820                 return err;
821
822         if (!attrs[TIPC_NLA_BEARER_NAME])
823                 return -EINVAL;
824
825         bearer = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
826
827         if (attrs[TIPC_NLA_BEARER_DOMAIN])
828                 domain = nla_get_u32(attrs[TIPC_NLA_BEARER_DOMAIN]);
829
830         if (attrs[TIPC_NLA_BEARER_PROP]) {
831                 struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
832
833                 err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_BEARER_PROP],
834                                               props);
835                 if (err)
836                         return err;
837
838                 if (props[TIPC_NLA_PROP_PRIO])
839                         prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
840         }
841
842         rtnl_lock();
843         err = tipc_enable_bearer(bearer, domain, prio);
844         if (err) {
845                 rtnl_unlock();
846                 return err;
847         }
848         rtnl_unlock();
849
850         return 0;
851 }
852
853 int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info)
854 {
855         int err;
856         char *name;
857         struct tipc_bearer *b;
858         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
859
860         if (!info->attrs[TIPC_NLA_BEARER])
861                 return -EINVAL;
862
863         err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
864                                info->attrs[TIPC_NLA_BEARER],
865                                tipc_nl_bearer_policy);
866         if (err)
867                 return err;
868
869         if (!attrs[TIPC_NLA_BEARER_NAME])
870                 return -EINVAL;
871         name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
872
873         rtnl_lock();
874         b = tipc_bearer_find(name);
875         if (!b) {
876                 rtnl_unlock();
877                 return -EINVAL;
878         }
879
880         if (attrs[TIPC_NLA_BEARER_PROP]) {
881                 struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
882
883                 err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_BEARER_PROP],
884                                               props);
885                 if (err) {
886                         rtnl_unlock();
887                         return err;
888                 }
889
890                 if (props[TIPC_NLA_PROP_TOL])
891                         b->tolerance = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
892                 if (props[TIPC_NLA_PROP_PRIO])
893                         b->priority = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
894                 if (props[TIPC_NLA_PROP_WIN])
895                         b->window = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
896         }
897         rtnl_unlock();
898
899         return 0;
900 }