Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec...
[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 static int __tipc_nl_add_bearer(struct tipc_nl_msg *msg,
651                                 struct tipc_bearer *bearer)
652 {
653         void *hdr;
654         struct nlattr *attrs;
655         struct nlattr *prop;
656
657         hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_v2_family,
658                           NLM_F_MULTI, TIPC_NL_BEARER_GET);
659         if (!hdr)
660                 return -EMSGSIZE;
661
662         attrs = nla_nest_start(msg->skb, TIPC_NLA_BEARER);
663         if (!attrs)
664                 goto msg_full;
665
666         if (nla_put_string(msg->skb, TIPC_NLA_BEARER_NAME, bearer->name))
667                 goto attr_msg_full;
668
669         prop = nla_nest_start(msg->skb, TIPC_NLA_BEARER_PROP);
670         if (!prop)
671                 goto prop_msg_full;
672         if (nla_put_u32(msg->skb, TIPC_NLA_PROP_PRIO, bearer->priority))
673                 goto prop_msg_full;
674         if (nla_put_u32(msg->skb, TIPC_NLA_PROP_TOL, bearer->tolerance))
675                 goto prop_msg_full;
676         if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, bearer->window))
677                 goto prop_msg_full;
678
679         nla_nest_end(msg->skb, prop);
680         nla_nest_end(msg->skb, attrs);
681         genlmsg_end(msg->skb, hdr);
682
683         return 0;
684
685 prop_msg_full:
686         nla_nest_cancel(msg->skb, prop);
687 attr_msg_full:
688         nla_nest_cancel(msg->skb, attrs);
689 msg_full:
690         genlmsg_cancel(msg->skb, hdr);
691
692         return -EMSGSIZE;
693 }
694
695 int tipc_nl_bearer_dump(struct sk_buff *skb, struct netlink_callback *cb)
696 {
697         int err;
698         int i = cb->args[0];
699         struct tipc_bearer *bearer;
700         struct tipc_nl_msg msg;
701
702         if (i == MAX_BEARERS)
703                 return 0;
704
705         msg.skb = skb;
706         msg.portid = NETLINK_CB(cb->skb).portid;
707         msg.seq = cb->nlh->nlmsg_seq;
708
709         rtnl_lock();
710         for (i = 0; i < MAX_BEARERS; i++) {
711                 bearer = rtnl_dereference(bearer_list[i]);
712                 if (!bearer)
713                         continue;
714
715                 err = __tipc_nl_add_bearer(&msg, bearer);
716                 if (err)
717                         break;
718         }
719         rtnl_unlock();
720
721         cb->args[0] = i;
722         return skb->len;
723 }
724
725 int tipc_nl_bearer_get(struct sk_buff *skb, struct genl_info *info)
726 {
727         int err;
728         char *name;
729         struct sk_buff *rep;
730         struct tipc_bearer *bearer;
731         struct tipc_nl_msg msg;
732         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
733
734         if (!info->attrs[TIPC_NLA_BEARER])
735                 return -EINVAL;
736
737         err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
738                                info->attrs[TIPC_NLA_BEARER],
739                                tipc_nl_bearer_policy);
740         if (err)
741                 return err;
742
743         if (!attrs[TIPC_NLA_BEARER_NAME])
744                 return -EINVAL;
745         name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
746
747         rep = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
748         if (!rep)
749                 return -ENOMEM;
750
751         msg.skb = rep;
752         msg.portid = info->snd_portid;
753         msg.seq = info->snd_seq;
754
755         rtnl_lock();
756         bearer = tipc_bearer_find(name);
757         if (!bearer) {
758                 err = -EINVAL;
759                 goto err_out;
760         }
761
762         err = __tipc_nl_add_bearer(&msg, bearer);
763         if (err)
764                 goto err_out;
765         rtnl_unlock();
766
767         return genlmsg_reply(rep, info);
768 err_out:
769         rtnl_unlock();
770         nlmsg_free(rep);
771
772         return err;
773 }
774
775 int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info)
776 {
777         int err;
778         char *name;
779         struct tipc_bearer *bearer;
780         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
781
782         if (!info->attrs[TIPC_NLA_BEARER])
783                 return -EINVAL;
784
785         err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
786                                info->attrs[TIPC_NLA_BEARER],
787                                tipc_nl_bearer_policy);
788         if (err)
789                 return err;
790
791         if (!attrs[TIPC_NLA_BEARER_NAME])
792                 return -EINVAL;
793
794         name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
795
796         rtnl_lock();
797         bearer = tipc_bearer_find(name);
798         if (!bearer) {
799                 rtnl_unlock();
800                 return -EINVAL;
801         }
802
803         bearer_disable(bearer, false);
804         rtnl_unlock();
805
806         return 0;
807 }
808
809 int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info)
810 {
811         int err;
812         char *bearer;
813         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
814         u32 domain;
815         u32 prio;
816
817         prio = TIPC_MEDIA_LINK_PRI;
818         domain = tipc_own_addr & TIPC_CLUSTER_MASK;
819
820         if (!info->attrs[TIPC_NLA_BEARER])
821                 return -EINVAL;
822
823         err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
824                                info->attrs[TIPC_NLA_BEARER],
825                                tipc_nl_bearer_policy);
826         if (err)
827                 return err;
828
829         if (!attrs[TIPC_NLA_BEARER_NAME])
830                 return -EINVAL;
831
832         bearer = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
833
834         if (attrs[TIPC_NLA_BEARER_DOMAIN])
835                 domain = nla_get_u32(attrs[TIPC_NLA_BEARER_DOMAIN]);
836
837         if (attrs[TIPC_NLA_BEARER_PROP]) {
838                 struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
839
840                 err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_BEARER_PROP],
841                                               props);
842                 if (err)
843                         return err;
844
845                 if (props[TIPC_NLA_PROP_PRIO])
846                         prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
847         }
848
849         rtnl_lock();
850         err = tipc_enable_bearer(bearer, domain, prio);
851         if (err) {
852                 rtnl_unlock();
853                 return err;
854         }
855         rtnl_unlock();
856
857         return 0;
858 }
859
860 int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info)
861 {
862         int err;
863         char *name;
864         struct tipc_bearer *b;
865         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
866
867         if (!info->attrs[TIPC_NLA_BEARER])
868                 return -EINVAL;
869
870         err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
871                                info->attrs[TIPC_NLA_BEARER],
872                                tipc_nl_bearer_policy);
873         if (err)
874                 return err;
875
876         if (!attrs[TIPC_NLA_BEARER_NAME])
877                 return -EINVAL;
878         name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
879
880         rtnl_lock();
881         b = tipc_bearer_find(name);
882         if (!b) {
883                 rtnl_unlock();
884                 return -EINVAL;
885         }
886
887         if (attrs[TIPC_NLA_BEARER_PROP]) {
888                 struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
889
890                 err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_BEARER_PROP],
891                                               props);
892                 if (err) {
893                         rtnl_unlock();
894                         return err;
895                 }
896
897                 if (props[TIPC_NLA_PROP_TOL])
898                         b->tolerance = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
899                 if (props[TIPC_NLA_PROP_PRIO])
900                         b->priority = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
901                 if (props[TIPC_NLA_PROP_WIN])
902                         b->window = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
903         }
904         rtnl_unlock();
905
906         return 0;
907 }
908
909 static int __tipc_nl_add_media(struct tipc_nl_msg *msg,
910                                struct tipc_media *media)
911 {
912         void *hdr;
913         struct nlattr *attrs;
914         struct nlattr *prop;
915
916         hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_v2_family,
917                           NLM_F_MULTI, TIPC_NL_MEDIA_GET);
918         if (!hdr)
919                 return -EMSGSIZE;
920
921         attrs = nla_nest_start(msg->skb, TIPC_NLA_MEDIA);
922         if (!attrs)
923                 goto msg_full;
924
925         if (nla_put_string(msg->skb, TIPC_NLA_MEDIA_NAME, media->name))
926                 goto attr_msg_full;
927
928         prop = nla_nest_start(msg->skb, TIPC_NLA_MEDIA_PROP);
929         if (!prop)
930                 goto prop_msg_full;
931         if (nla_put_u32(msg->skb, TIPC_NLA_PROP_PRIO, media->priority))
932                 goto prop_msg_full;
933         if (nla_put_u32(msg->skb, TIPC_NLA_PROP_TOL, media->tolerance))
934                 goto prop_msg_full;
935         if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, media->window))
936                 goto prop_msg_full;
937
938         nla_nest_end(msg->skb, prop);
939         nla_nest_end(msg->skb, attrs);
940         genlmsg_end(msg->skb, hdr);
941
942         return 0;
943
944 prop_msg_full:
945         nla_nest_cancel(msg->skb, prop);
946 attr_msg_full:
947         nla_nest_cancel(msg->skb, attrs);
948 msg_full:
949         genlmsg_cancel(msg->skb, hdr);
950
951         return -EMSGSIZE;
952 }
953
954 int tipc_nl_media_dump(struct sk_buff *skb, struct netlink_callback *cb)
955 {
956         int err;
957         int i = cb->args[0];
958         struct tipc_nl_msg msg;
959
960         if (i == MAX_MEDIA)
961                 return 0;
962
963         msg.skb = skb;
964         msg.portid = NETLINK_CB(cb->skb).portid;
965         msg.seq = cb->nlh->nlmsg_seq;
966
967         rtnl_lock();
968         for (; media_info_array[i] != NULL; i++) {
969                 err = __tipc_nl_add_media(&msg, media_info_array[i]);
970                 if (err)
971                         break;
972         }
973         rtnl_unlock();
974
975         cb->args[0] = i;
976         return skb->len;
977 }
978
979 int tipc_nl_media_get(struct sk_buff *skb, struct genl_info *info)
980 {
981         int err;
982         char *name;
983         struct tipc_nl_msg msg;
984         struct tipc_media *media;
985         struct sk_buff *rep;
986         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
987
988         if (!info->attrs[TIPC_NLA_MEDIA])
989                 return -EINVAL;
990
991         err = nla_parse_nested(attrs, TIPC_NLA_MEDIA_MAX,
992                                info->attrs[TIPC_NLA_MEDIA],
993                                tipc_nl_media_policy);
994         if (err)
995                 return err;
996
997         if (!attrs[TIPC_NLA_MEDIA_NAME])
998                 return -EINVAL;
999         name = nla_data(attrs[TIPC_NLA_MEDIA_NAME]);
1000
1001         rep = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1002         if (!rep)
1003                 return -ENOMEM;
1004
1005         msg.skb = rep;
1006         msg.portid = info->snd_portid;
1007         msg.seq = info->snd_seq;
1008
1009         rtnl_lock();
1010         media = tipc_media_find(name);
1011         if (!media) {
1012                 err = -EINVAL;
1013                 goto err_out;
1014         }
1015
1016         err = __tipc_nl_add_media(&msg, media);
1017         if (err)
1018                 goto err_out;
1019         rtnl_unlock();
1020
1021         return genlmsg_reply(rep, info);
1022 err_out:
1023         rtnl_unlock();
1024         nlmsg_free(rep);
1025
1026         return err;
1027 }
1028
1029 int tipc_nl_media_set(struct sk_buff *skb, struct genl_info *info)
1030 {
1031         int err;
1032         char *name;
1033         struct tipc_media *m;
1034         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
1035
1036         if (!info->attrs[TIPC_NLA_MEDIA])
1037                 return -EINVAL;
1038
1039         err = nla_parse_nested(attrs, TIPC_NLA_MEDIA_MAX,
1040                                info->attrs[TIPC_NLA_MEDIA],
1041                                tipc_nl_media_policy);
1042
1043         if (!attrs[TIPC_NLA_MEDIA_NAME])
1044                 return -EINVAL;
1045         name = nla_data(attrs[TIPC_NLA_MEDIA_NAME]);
1046
1047         rtnl_lock();
1048         m = tipc_media_find(name);
1049         if (!m) {
1050                 rtnl_unlock();
1051                 return -EINVAL;
1052         }
1053
1054         if (attrs[TIPC_NLA_MEDIA_PROP]) {
1055                 struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
1056
1057                 err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_MEDIA_PROP],
1058                                               props);
1059                 if (err) {
1060                         rtnl_unlock();
1061                         return err;
1062                 }
1063
1064                 if (props[TIPC_NLA_PROP_TOL])
1065                         m->tolerance = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
1066                 if (props[TIPC_NLA_PROP_PRIO])
1067                         m->priority = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
1068                 if (props[TIPC_NLA_PROP_WIN])
1069                         m->window = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
1070         }
1071         rtnl_unlock();
1072
1073         return 0;
1074 }