]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - net/tipc/bearer.c
tipc: involve namespace infrastructure
[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 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(struct net *net, const char *name, u32 disc_domain,
264                        u32 priority)
265 {
266         struct tipc_bearer *b_ptr;
267         struct tipc_media *m_ptr;
268         struct tipc_bearer_names b_names;
269         char addr_string[16];
270         u32 bearer_id;
271         u32 with_this_prio;
272         u32 i;
273         int res = -EINVAL;
274
275         if (!tipc_own_addr) {
276                 pr_warn("Bearer <%s> rejected, not supported in standalone mode\n",
277                         name);
278                 return -ENOPROTOOPT;
279         }
280         if (!bearer_name_validate(name, &b_names)) {
281                 pr_warn("Bearer <%s> rejected, illegal name\n", name);
282                 return -EINVAL;
283         }
284         if (tipc_addr_domain_valid(disc_domain) &&
285             (disc_domain != tipc_own_addr)) {
286                 if (tipc_in_scope(disc_domain, tipc_own_addr)) {
287                         disc_domain = tipc_own_addr & TIPC_CLUSTER_MASK;
288                         res = 0;   /* accept any node in own cluster */
289                 } else if (in_own_cluster_exact(disc_domain))
290                         res = 0;   /* accept specified node in own cluster */
291         }
292         if (res) {
293                 pr_warn("Bearer <%s> rejected, illegal discovery domain\n",
294                         name);
295                 return -EINVAL;
296         }
297         if ((priority > TIPC_MAX_LINK_PRI) &&
298             (priority != TIPC_MEDIA_LINK_PRI)) {
299                 pr_warn("Bearer <%s> rejected, illegal priority\n", name);
300                 return -EINVAL;
301         }
302
303         m_ptr = tipc_media_find(b_names.media_name);
304         if (!m_ptr) {
305                 pr_warn("Bearer <%s> rejected, media <%s> not registered\n",
306                         name, b_names.media_name);
307                 return -EINVAL;
308         }
309
310         if (priority == TIPC_MEDIA_LINK_PRI)
311                 priority = m_ptr->priority;
312
313 restart:
314         bearer_id = MAX_BEARERS;
315         with_this_prio = 1;
316         for (i = MAX_BEARERS; i-- != 0; ) {
317                 b_ptr = rtnl_dereference(bearer_list[i]);
318                 if (!b_ptr) {
319                         bearer_id = i;
320                         continue;
321                 }
322                 if (!strcmp(name, b_ptr->name)) {
323                         pr_warn("Bearer <%s> rejected, already enabled\n",
324                                 name);
325                         return -EINVAL;
326                 }
327                 if ((b_ptr->priority == priority) &&
328                     (++with_this_prio > 2)) {
329                         if (priority-- == 0) {
330                                 pr_warn("Bearer <%s> rejected, duplicate priority\n",
331                                         name);
332                                 return -EINVAL;
333                         }
334                         pr_warn("Bearer <%s> priority adjustment required %u->%u\n",
335                                 name, priority + 1, priority);
336                         goto restart;
337                 }
338         }
339         if (bearer_id >= MAX_BEARERS) {
340                 pr_warn("Bearer <%s> rejected, bearer limit reached (%u)\n",
341                         name, MAX_BEARERS);
342                 return -EINVAL;
343         }
344
345         b_ptr = kzalloc(sizeof(*b_ptr), GFP_ATOMIC);
346         if (!b_ptr)
347                 return -ENOMEM;
348
349         strcpy(b_ptr->name, name);
350         b_ptr->media = m_ptr;
351         res = m_ptr->enable_media(b_ptr);
352         if (res) {
353                 pr_warn("Bearer <%s> rejected, enable failure (%d)\n",
354                         name, -res);
355                 return -EINVAL;
356         }
357
358         b_ptr->identity = bearer_id;
359         b_ptr->tolerance = m_ptr->tolerance;
360         b_ptr->window = m_ptr->window;
361         b_ptr->domain = disc_domain;
362         b_ptr->net_plane = bearer_id + 'A';
363         b_ptr->priority = priority;
364
365         res = tipc_disc_create(net, b_ptr, &b_ptr->bcast_addr);
366         if (res) {
367                 bearer_disable(b_ptr, false);
368                 pr_warn("Bearer <%s> rejected, discovery object creation failed\n",
369                         name);
370                 return -EINVAL;
371         }
372
373         rcu_assign_pointer(bearer_list[bearer_id], b_ptr);
374
375         pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n",
376                 name,
377                 tipc_addr_string_fill(addr_string, disc_domain), priority);
378         return res;
379 }
380
381 /**
382  * tipc_reset_bearer - Reset all links established over this bearer
383  */
384 static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b_ptr)
385 {
386         pr_info("Resetting bearer <%s>\n", b_ptr->name);
387         tipc_link_reset_list(b_ptr->identity);
388         tipc_disc_reset(net, b_ptr);
389         return 0;
390 }
391
392 /**
393  * bearer_disable
394  *
395  * Note: This routine assumes caller holds RTNL lock.
396  */
397 static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down)
398 {
399         u32 i;
400
401         pr_info("Disabling bearer <%s>\n", b_ptr->name);
402         b_ptr->media->disable_media(b_ptr);
403
404         tipc_link_delete_list(b_ptr->identity, shutting_down);
405         if (b_ptr->link_req)
406                 tipc_disc_delete(b_ptr->link_req);
407
408         for (i = 0; i < MAX_BEARERS; i++) {
409                 if (b_ptr == rtnl_dereference(bearer_list[i])) {
410                         RCU_INIT_POINTER(bearer_list[i], NULL);
411                         break;
412                 }
413         }
414         kfree_rcu(b_ptr, rcu);
415 }
416
417 int tipc_disable_bearer(const char *name)
418 {
419         struct tipc_bearer *b_ptr;
420         int res;
421
422         b_ptr = tipc_bearer_find(name);
423         if (b_ptr == NULL) {
424                 pr_warn("Attempt to disable unknown bearer <%s>\n", name);
425                 res = -EINVAL;
426         } else {
427                 bearer_disable(b_ptr, false);
428                 res = 0;
429         }
430         return res;
431 }
432
433 int tipc_enable_l2_media(struct tipc_bearer *b)
434 {
435         struct net_device *dev;
436         char *driver_name = strchr((const char *)b->name, ':') + 1;
437
438         /* Find device with specified name */
439         dev = dev_get_by_name(&init_net, driver_name);
440         if (!dev)
441                 return -ENODEV;
442
443         /* Associate TIPC bearer with L2 bearer */
444         rcu_assign_pointer(b->media_ptr, dev);
445         memset(&b->bcast_addr, 0, sizeof(b->bcast_addr));
446         memcpy(b->bcast_addr.value, dev->broadcast, b->media->hwaddr_len);
447         b->bcast_addr.media_id = b->media->type_id;
448         b->bcast_addr.broadcast = 1;
449         b->mtu = dev->mtu;
450         b->media->raw2addr(b, &b->addr, (char *)dev->dev_addr);
451         rcu_assign_pointer(dev->tipc_ptr, b);
452         return 0;
453 }
454
455 /* tipc_disable_l2_media - detach TIPC bearer from an L2 interface
456  *
457  * Mark L2 bearer as inactive so that incoming buffers are thrown away,
458  * then get worker thread to complete bearer cleanup.  (Can't do cleanup
459  * here because cleanup code needs to sleep and caller holds spinlocks.)
460  */
461 void tipc_disable_l2_media(struct tipc_bearer *b)
462 {
463         struct net_device *dev;
464
465         dev = (struct net_device *)rtnl_dereference(b->media_ptr);
466         RCU_INIT_POINTER(b->media_ptr, NULL);
467         RCU_INIT_POINTER(dev->tipc_ptr, NULL);
468         synchronize_net();
469         dev_put(dev);
470 }
471
472 /**
473  * tipc_l2_send_msg - send a TIPC packet out over an L2 interface
474  * @buf: the packet to be sent
475  * @b_ptr: the bearer through which the packet is to be sent
476  * @dest: peer destination address
477  */
478 int tipc_l2_send_msg(struct sk_buff *buf, struct tipc_bearer *b,
479                      struct tipc_media_addr *dest)
480 {
481         struct sk_buff *clone;
482         struct net_device *dev;
483         int delta;
484
485         dev = (struct net_device *)rcu_dereference_rtnl(b->media_ptr);
486         if (!dev)
487                 return 0;
488
489         clone = skb_clone(buf, GFP_ATOMIC);
490         if (!clone)
491                 return 0;
492
493         delta = dev->hard_header_len - skb_headroom(buf);
494         if ((delta > 0) &&
495             pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) {
496                 kfree_skb(clone);
497                 return 0;
498         }
499
500         skb_reset_network_header(clone);
501         clone->dev = dev;
502         clone->protocol = htons(ETH_P_TIPC);
503         dev_hard_header(clone, dev, ETH_P_TIPC, dest->value,
504                         dev->dev_addr, clone->len);
505         dev_queue_xmit(clone);
506         return 0;
507 }
508
509 /* tipc_bearer_send- sends buffer to destination over bearer
510  *
511  * IMPORTANT:
512  * The media send routine must not alter the buffer being passed in
513  * as it may be needed for later retransmission!
514  */
515 void tipc_bearer_send(u32 bearer_id, struct sk_buff *buf,
516                       struct tipc_media_addr *dest)
517 {
518         struct tipc_bearer *b_ptr;
519
520         rcu_read_lock();
521         b_ptr = rcu_dereference_rtnl(bearer_list[bearer_id]);
522         if (likely(b_ptr))
523                 b_ptr->media->send_msg(buf, b_ptr, dest);
524         rcu_read_unlock();
525 }
526
527 /**
528  * tipc_l2_rcv_msg - handle incoming TIPC message from an interface
529  * @buf: the received packet
530  * @dev: the net device that the packet was received on
531  * @pt: the packet_type structure which was used to register this handler
532  * @orig_dev: the original receive net device in case the device is a bond
533  *
534  * Accept only packets explicitly sent to this node, or broadcast packets;
535  * ignores packets sent using interface multicast, and traffic sent to other
536  * nodes (which can happen if interface is running in promiscuous mode).
537  */
538 static int tipc_l2_rcv_msg(struct sk_buff *buf, struct net_device *dev,
539                            struct packet_type *pt, struct net_device *orig_dev)
540 {
541         struct tipc_bearer *b_ptr;
542
543         rcu_read_lock();
544         b_ptr = rcu_dereference_rtnl(dev->tipc_ptr);
545         if (likely(b_ptr)) {
546                 if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
547                         buf->next = NULL;
548                         tipc_rcv(dev_net(dev), buf, b_ptr);
549                         rcu_read_unlock();
550                         return NET_RX_SUCCESS;
551                 }
552         }
553         rcu_read_unlock();
554
555         kfree_skb(buf);
556         return NET_RX_DROP;
557 }
558
559 /**
560  * tipc_l2_device_event - handle device events from network device
561  * @nb: the context of the notification
562  * @evt: the type of event
563  * @ptr: the net device that the event was on
564  *
565  * This function is called by the Ethernet driver in case of link
566  * change event.
567  */
568 static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
569                                 void *ptr)
570 {
571         struct net_device *dev = netdev_notifier_info_to_dev(ptr);
572         struct net *net = dev_net(dev);
573         struct tipc_bearer *b_ptr;
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(net, 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(net, 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 static int __tipc_nl_add_bearer(struct tipc_nl_msg *msg,
645                                 struct tipc_bearer *bearer)
646 {
647         void *hdr;
648         struct nlattr *attrs;
649         struct nlattr *prop;
650
651         hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_v2_family,
652                           NLM_F_MULTI, TIPC_NL_BEARER_GET);
653         if (!hdr)
654                 return -EMSGSIZE;
655
656         attrs = nla_nest_start(msg->skb, TIPC_NLA_BEARER);
657         if (!attrs)
658                 goto msg_full;
659
660         if (nla_put_string(msg->skb, TIPC_NLA_BEARER_NAME, bearer->name))
661                 goto attr_msg_full;
662
663         prop = nla_nest_start(msg->skb, TIPC_NLA_BEARER_PROP);
664         if (!prop)
665                 goto prop_msg_full;
666         if (nla_put_u32(msg->skb, TIPC_NLA_PROP_PRIO, bearer->priority))
667                 goto prop_msg_full;
668         if (nla_put_u32(msg->skb, TIPC_NLA_PROP_TOL, bearer->tolerance))
669                 goto prop_msg_full;
670         if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, bearer->window))
671                 goto prop_msg_full;
672
673         nla_nest_end(msg->skb, prop);
674         nla_nest_end(msg->skb, attrs);
675         genlmsg_end(msg->skb, hdr);
676
677         return 0;
678
679 prop_msg_full:
680         nla_nest_cancel(msg->skb, prop);
681 attr_msg_full:
682         nla_nest_cancel(msg->skb, attrs);
683 msg_full:
684         genlmsg_cancel(msg->skb, hdr);
685
686         return -EMSGSIZE;
687 }
688
689 int tipc_nl_bearer_dump(struct sk_buff *skb, struct netlink_callback *cb)
690 {
691         int err;
692         int i = cb->args[0];
693         struct tipc_bearer *bearer;
694         struct tipc_nl_msg msg;
695
696         if (i == MAX_BEARERS)
697                 return 0;
698
699         msg.skb = skb;
700         msg.portid = NETLINK_CB(cb->skb).portid;
701         msg.seq = cb->nlh->nlmsg_seq;
702
703         rtnl_lock();
704         for (i = 0; i < MAX_BEARERS; i++) {
705                 bearer = rtnl_dereference(bearer_list[i]);
706                 if (!bearer)
707                         continue;
708
709                 err = __tipc_nl_add_bearer(&msg, bearer);
710                 if (err)
711                         break;
712         }
713         rtnl_unlock();
714
715         cb->args[0] = i;
716         return skb->len;
717 }
718
719 int tipc_nl_bearer_get(struct sk_buff *skb, struct genl_info *info)
720 {
721         int err;
722         char *name;
723         struct sk_buff *rep;
724         struct tipc_bearer *bearer;
725         struct tipc_nl_msg msg;
726         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
727
728         if (!info->attrs[TIPC_NLA_BEARER])
729                 return -EINVAL;
730
731         err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
732                                info->attrs[TIPC_NLA_BEARER],
733                                tipc_nl_bearer_policy);
734         if (err)
735                 return err;
736
737         if (!attrs[TIPC_NLA_BEARER_NAME])
738                 return -EINVAL;
739         name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
740
741         rep = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
742         if (!rep)
743                 return -ENOMEM;
744
745         msg.skb = rep;
746         msg.portid = info->snd_portid;
747         msg.seq = info->snd_seq;
748
749         rtnl_lock();
750         bearer = tipc_bearer_find(name);
751         if (!bearer) {
752                 err = -EINVAL;
753                 goto err_out;
754         }
755
756         err = __tipc_nl_add_bearer(&msg, bearer);
757         if (err)
758                 goto err_out;
759         rtnl_unlock();
760
761         return genlmsg_reply(rep, info);
762 err_out:
763         rtnl_unlock();
764         nlmsg_free(rep);
765
766         return err;
767 }
768
769 int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info)
770 {
771         int err;
772         char *name;
773         struct tipc_bearer *bearer;
774         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
775
776         if (!info->attrs[TIPC_NLA_BEARER])
777                 return -EINVAL;
778
779         err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
780                                info->attrs[TIPC_NLA_BEARER],
781                                tipc_nl_bearer_policy);
782         if (err)
783                 return err;
784
785         if (!attrs[TIPC_NLA_BEARER_NAME])
786                 return -EINVAL;
787
788         name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
789
790         rtnl_lock();
791         bearer = tipc_bearer_find(name);
792         if (!bearer) {
793                 rtnl_unlock();
794                 return -EINVAL;
795         }
796
797         bearer_disable(bearer, false);
798         rtnl_unlock();
799
800         return 0;
801 }
802
803 int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info)
804 {
805         struct net *net = genl_info_net(info);
806         int err;
807         char *bearer;
808         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
809         u32 domain;
810         u32 prio;
811
812         prio = TIPC_MEDIA_LINK_PRI;
813         domain = tipc_own_addr & TIPC_CLUSTER_MASK;
814
815         if (!info->attrs[TIPC_NLA_BEARER])
816                 return -EINVAL;
817
818         err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
819                                info->attrs[TIPC_NLA_BEARER],
820                                tipc_nl_bearer_policy);
821         if (err)
822                 return err;
823
824         if (!attrs[TIPC_NLA_BEARER_NAME])
825                 return -EINVAL;
826
827         bearer = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
828
829         if (attrs[TIPC_NLA_BEARER_DOMAIN])
830                 domain = nla_get_u32(attrs[TIPC_NLA_BEARER_DOMAIN]);
831
832         if (attrs[TIPC_NLA_BEARER_PROP]) {
833                 struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
834
835                 err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_BEARER_PROP],
836                                               props);
837                 if (err)
838                         return err;
839
840                 if (props[TIPC_NLA_PROP_PRIO])
841                         prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
842         }
843
844         rtnl_lock();
845         err = tipc_enable_bearer(net, bearer, domain, prio);
846         if (err) {
847                 rtnl_unlock();
848                 return err;
849         }
850         rtnl_unlock();
851
852         return 0;
853 }
854
855 int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info)
856 {
857         int err;
858         char *name;
859         struct tipc_bearer *b;
860         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
861
862         if (!info->attrs[TIPC_NLA_BEARER])
863                 return -EINVAL;
864
865         err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
866                                info->attrs[TIPC_NLA_BEARER],
867                                tipc_nl_bearer_policy);
868         if (err)
869                 return err;
870
871         if (!attrs[TIPC_NLA_BEARER_NAME])
872                 return -EINVAL;
873         name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
874
875         rtnl_lock();
876         b = tipc_bearer_find(name);
877         if (!b) {
878                 rtnl_unlock();
879                 return -EINVAL;
880         }
881
882         if (attrs[TIPC_NLA_BEARER_PROP]) {
883                 struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
884
885                 err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_BEARER_PROP],
886                                               props);
887                 if (err) {
888                         rtnl_unlock();
889                         return err;
890                 }
891
892                 if (props[TIPC_NLA_PROP_TOL])
893                         b->tolerance = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
894                 if (props[TIPC_NLA_PROP_PRIO])
895                         b->priority = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
896                 if (props[TIPC_NLA_PROP_WIN])
897                         b->window = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
898         }
899         rtnl_unlock();
900
901         return 0;
902 }
903
904 static int __tipc_nl_add_media(struct tipc_nl_msg *msg,
905                                struct tipc_media *media)
906 {
907         void *hdr;
908         struct nlattr *attrs;
909         struct nlattr *prop;
910
911         hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_v2_family,
912                           NLM_F_MULTI, TIPC_NL_MEDIA_GET);
913         if (!hdr)
914                 return -EMSGSIZE;
915
916         attrs = nla_nest_start(msg->skb, TIPC_NLA_MEDIA);
917         if (!attrs)
918                 goto msg_full;
919
920         if (nla_put_string(msg->skb, TIPC_NLA_MEDIA_NAME, media->name))
921                 goto attr_msg_full;
922
923         prop = nla_nest_start(msg->skb, TIPC_NLA_MEDIA_PROP);
924         if (!prop)
925                 goto prop_msg_full;
926         if (nla_put_u32(msg->skb, TIPC_NLA_PROP_PRIO, media->priority))
927                 goto prop_msg_full;
928         if (nla_put_u32(msg->skb, TIPC_NLA_PROP_TOL, media->tolerance))
929                 goto prop_msg_full;
930         if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, media->window))
931                 goto prop_msg_full;
932
933         nla_nest_end(msg->skb, prop);
934         nla_nest_end(msg->skb, attrs);
935         genlmsg_end(msg->skb, hdr);
936
937         return 0;
938
939 prop_msg_full:
940         nla_nest_cancel(msg->skb, prop);
941 attr_msg_full:
942         nla_nest_cancel(msg->skb, attrs);
943 msg_full:
944         genlmsg_cancel(msg->skb, hdr);
945
946         return -EMSGSIZE;
947 }
948
949 int tipc_nl_media_dump(struct sk_buff *skb, struct netlink_callback *cb)
950 {
951         int err;
952         int i = cb->args[0];
953         struct tipc_nl_msg msg;
954
955         if (i == MAX_MEDIA)
956                 return 0;
957
958         msg.skb = skb;
959         msg.portid = NETLINK_CB(cb->skb).portid;
960         msg.seq = cb->nlh->nlmsg_seq;
961
962         rtnl_lock();
963         for (; media_info_array[i] != NULL; i++) {
964                 err = __tipc_nl_add_media(&msg, media_info_array[i]);
965                 if (err)
966                         break;
967         }
968         rtnl_unlock();
969
970         cb->args[0] = i;
971         return skb->len;
972 }
973
974 int tipc_nl_media_get(struct sk_buff *skb, struct genl_info *info)
975 {
976         int err;
977         char *name;
978         struct tipc_nl_msg msg;
979         struct tipc_media *media;
980         struct sk_buff *rep;
981         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
982
983         if (!info->attrs[TIPC_NLA_MEDIA])
984                 return -EINVAL;
985
986         err = nla_parse_nested(attrs, TIPC_NLA_MEDIA_MAX,
987                                info->attrs[TIPC_NLA_MEDIA],
988                                tipc_nl_media_policy);
989         if (err)
990                 return err;
991
992         if (!attrs[TIPC_NLA_MEDIA_NAME])
993                 return -EINVAL;
994         name = nla_data(attrs[TIPC_NLA_MEDIA_NAME]);
995
996         rep = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
997         if (!rep)
998                 return -ENOMEM;
999
1000         msg.skb = rep;
1001         msg.portid = info->snd_portid;
1002         msg.seq = info->snd_seq;
1003
1004         rtnl_lock();
1005         media = tipc_media_find(name);
1006         if (!media) {
1007                 err = -EINVAL;
1008                 goto err_out;
1009         }
1010
1011         err = __tipc_nl_add_media(&msg, media);
1012         if (err)
1013                 goto err_out;
1014         rtnl_unlock();
1015
1016         return genlmsg_reply(rep, info);
1017 err_out:
1018         rtnl_unlock();
1019         nlmsg_free(rep);
1020
1021         return err;
1022 }
1023
1024 int tipc_nl_media_set(struct sk_buff *skb, struct genl_info *info)
1025 {
1026         int err;
1027         char *name;
1028         struct tipc_media *m;
1029         struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
1030
1031         if (!info->attrs[TIPC_NLA_MEDIA])
1032                 return -EINVAL;
1033
1034         err = nla_parse_nested(attrs, TIPC_NLA_MEDIA_MAX,
1035                                info->attrs[TIPC_NLA_MEDIA],
1036                                tipc_nl_media_policy);
1037
1038         if (!attrs[TIPC_NLA_MEDIA_NAME])
1039                 return -EINVAL;
1040         name = nla_data(attrs[TIPC_NLA_MEDIA_NAME]);
1041
1042         rtnl_lock();
1043         m = tipc_media_find(name);
1044         if (!m) {
1045                 rtnl_unlock();
1046                 return -EINVAL;
1047         }
1048
1049         if (attrs[TIPC_NLA_MEDIA_PROP]) {
1050                 struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
1051
1052                 err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_MEDIA_PROP],
1053                                               props);
1054                 if (err) {
1055                         rtnl_unlock();
1056                         return err;
1057                 }
1058
1059                 if (props[TIPC_NLA_PROP_TOL])
1060                         m->tolerance = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
1061                 if (props[TIPC_NLA_PROP_PRIO])
1062                         m->priority = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
1063                 if (props[TIPC_NLA_PROP_WIN])
1064                         m->window = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
1065         }
1066         rtnl_unlock();
1067
1068         return 0;
1069 }