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