tipc: involve namespace infrastructure
[deliverable/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 }
This page took 0.103529 seconds and 5 git commands to generate.