xref: /openbmc/linux/net/tipc/bearer.c (revision 8684014d)
1 /*
2  * net/tipc/bearer.c: TIPC bearer code
3  *
4  * Copyright (c) 1996-2006, 2013-2014, Ericsson AB
5  * Copyright (c) 2004-2006, 2010-2013, Wind River Systems
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the names of the copyright holders nor the names of its
17  *    contributors may be used to endorse or promote products derived from
18  *    this software without specific prior written permission.
19  *
20  * Alternatively, this software may be distributed under the terms of the
21  * GNU General Public License ("GPL") version 2 as published by the Free
22  * Software Foundation.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 #include "core.h"
38 #include "config.h"
39 #include "bearer.h"
40 #include "link.h"
41 #include "discover.h"
42 
43 #define MAX_ADDR_STR 60
44 
45 static struct tipc_media * const media_info_array[] = {
46 	&eth_media_info,
47 #ifdef CONFIG_TIPC_MEDIA_IB
48 	&ib_media_info,
49 #endif
50 	NULL
51 };
52 
53 static const struct nla_policy
54 tipc_nl_bearer_policy[TIPC_NLA_BEARER_MAX + 1]	= {
55 	[TIPC_NLA_BEARER_UNSPEC]		= { .type = NLA_UNSPEC },
56 	[TIPC_NLA_BEARER_NAME] = {
57 		.type = NLA_STRING,
58 		.len = TIPC_MAX_BEARER_NAME
59 	},
60 	[TIPC_NLA_BEARER_PROP]			= { .type = NLA_NESTED },
61 	[TIPC_NLA_BEARER_DOMAIN]		= { .type = NLA_U32 }
62 };
63 
64 static const struct nla_policy tipc_nl_media_policy[TIPC_NLA_MEDIA_MAX + 1] = {
65 	[TIPC_NLA_MEDIA_UNSPEC]		= { .type = NLA_UNSPEC },
66 	[TIPC_NLA_MEDIA_NAME]		= { .type = NLA_STRING },
67 	[TIPC_NLA_MEDIA_PROP]		= { .type = NLA_NESTED }
68 };
69 
70 struct tipc_bearer __rcu *bearer_list[MAX_BEARERS + 1];
71 
72 static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down);
73 
74 /**
75  * tipc_media_find - locates specified media object by name
76  */
77 struct tipc_media *tipc_media_find(const char *name)
78 {
79 	u32 i;
80 
81 	for (i = 0; media_info_array[i] != NULL; i++) {
82 		if (!strcmp(media_info_array[i]->name, name))
83 			break;
84 	}
85 	return media_info_array[i];
86 }
87 
88 /**
89  * media_find_id - locates specified media object by type identifier
90  */
91 static struct tipc_media *media_find_id(u8 type)
92 {
93 	u32 i;
94 
95 	for (i = 0; media_info_array[i] != NULL; i++) {
96 		if (media_info_array[i]->type_id == type)
97 			break;
98 	}
99 	return media_info_array[i];
100 }
101 
102 /**
103  * tipc_media_addr_printf - record media address in print buffer
104  */
105 void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a)
106 {
107 	char addr_str[MAX_ADDR_STR];
108 	struct tipc_media *m_ptr;
109 	int ret;
110 
111 	m_ptr = media_find_id(a->media_id);
112 
113 	if (m_ptr && !m_ptr->addr2str(a, addr_str, sizeof(addr_str)))
114 		ret = tipc_snprintf(buf, len, "%s(%s)", m_ptr->name, addr_str);
115 	else {
116 		u32 i;
117 
118 		ret = tipc_snprintf(buf, len, "UNKNOWN(%u)", a->media_id);
119 		for (i = 0; i < sizeof(a->value); i++)
120 			ret += tipc_snprintf(buf - ret, len + ret,
121 					    "-%02x", a->value[i]);
122 	}
123 }
124 
125 /**
126  * tipc_media_get_names - record names of registered media in buffer
127  */
128 struct sk_buff *tipc_media_get_names(void)
129 {
130 	struct sk_buff *buf;
131 	int i;
132 
133 	buf = tipc_cfg_reply_alloc(MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME));
134 	if (!buf)
135 		return NULL;
136 
137 	for (i = 0; media_info_array[i] != NULL; i++) {
138 		tipc_cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME,
139 				    media_info_array[i]->name,
140 				    strlen(media_info_array[i]->name) + 1);
141 	}
142 	return buf;
143 }
144 
145 /**
146  * bearer_name_validate - validate & (optionally) deconstruct bearer name
147  * @name: ptr to bearer name string
148  * @name_parts: ptr to area for bearer name components (or NULL if not needed)
149  *
150  * Returns 1 if bearer name is valid, otherwise 0.
151  */
152 static int bearer_name_validate(const char *name,
153 				struct tipc_bearer_names *name_parts)
154 {
155 	char name_copy[TIPC_MAX_BEARER_NAME];
156 	char *media_name;
157 	char *if_name;
158 	u32 media_len;
159 	u32 if_len;
160 
161 	/* copy bearer name & ensure length is OK */
162 	name_copy[TIPC_MAX_BEARER_NAME - 1] = 0;
163 	/* need above in case non-Posix strncpy() doesn't pad with nulls */
164 	strncpy(name_copy, name, TIPC_MAX_BEARER_NAME);
165 	if (name_copy[TIPC_MAX_BEARER_NAME - 1] != 0)
166 		return 0;
167 
168 	/* ensure all component parts of bearer name are present */
169 	media_name = name_copy;
170 	if_name = strchr(media_name, ':');
171 	if (if_name == NULL)
172 		return 0;
173 	*(if_name++) = 0;
174 	media_len = if_name - media_name;
175 	if_len = strlen(if_name) + 1;
176 
177 	/* validate component parts of bearer name */
178 	if ((media_len <= 1) || (media_len > TIPC_MAX_MEDIA_NAME) ||
179 	    (if_len <= 1) || (if_len > TIPC_MAX_IF_NAME))
180 		return 0;
181 
182 	/* return bearer name components, if necessary */
183 	if (name_parts) {
184 		strcpy(name_parts->media_name, media_name);
185 		strcpy(name_parts->if_name, if_name);
186 	}
187 	return 1;
188 }
189 
190 /**
191  * tipc_bearer_find - locates bearer object with matching bearer name
192  */
193 struct tipc_bearer *tipc_bearer_find(const char *name)
194 {
195 	struct tipc_bearer *b_ptr;
196 	u32 i;
197 
198 	for (i = 0; i < MAX_BEARERS; i++) {
199 		b_ptr = rtnl_dereference(bearer_list[i]);
200 		if (b_ptr && (!strcmp(b_ptr->name, name)))
201 			return b_ptr;
202 	}
203 	return NULL;
204 }
205 
206 /**
207  * tipc_bearer_get_names - record names of bearers in buffer
208  */
209 struct sk_buff *tipc_bearer_get_names(void)
210 {
211 	struct sk_buff *buf;
212 	struct tipc_bearer *b;
213 	int i, j;
214 
215 	buf = tipc_cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME));
216 	if (!buf)
217 		return NULL;
218 
219 	for (i = 0; media_info_array[i] != NULL; i++) {
220 		for (j = 0; j < MAX_BEARERS; j++) {
221 			b = rtnl_dereference(bearer_list[j]);
222 			if (!b)
223 				continue;
224 			if (b->media == media_info_array[i]) {
225 				tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME,
226 						    b->name,
227 						    strlen(b->name) + 1);
228 			}
229 		}
230 	}
231 	return buf;
232 }
233 
234 void tipc_bearer_add_dest(u32 bearer_id, u32 dest)
235 {
236 	struct tipc_bearer *b_ptr;
237 
238 	rcu_read_lock();
239 	b_ptr = rcu_dereference_rtnl(bearer_list[bearer_id]);
240 	if (b_ptr) {
241 		tipc_bcbearer_sort(&b_ptr->nodes, dest, true);
242 		tipc_disc_add_dest(b_ptr->link_req);
243 	}
244 	rcu_read_unlock();
245 }
246 
247 void tipc_bearer_remove_dest(u32 bearer_id, u32 dest)
248 {
249 	struct tipc_bearer *b_ptr;
250 
251 	rcu_read_lock();
252 	b_ptr = rcu_dereference_rtnl(bearer_list[bearer_id]);
253 	if (b_ptr) {
254 		tipc_bcbearer_sort(&b_ptr->nodes, dest, false);
255 		tipc_disc_remove_dest(b_ptr->link_req);
256 	}
257 	rcu_read_unlock();
258 }
259 
260 /**
261  * tipc_enable_bearer - enable bearer with the given name
262  */
263 int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
264 {
265 	struct tipc_bearer *b_ptr;
266 	struct tipc_media *m_ptr;
267 	struct tipc_bearer_names b_names;
268 	char addr_string[16];
269 	u32 bearer_id;
270 	u32 with_this_prio;
271 	u32 i;
272 	int res = -EINVAL;
273 
274 	if (!tipc_own_addr) {
275 		pr_warn("Bearer <%s> rejected, not supported in standalone mode\n",
276 			name);
277 		return -ENOPROTOOPT;
278 	}
279 	if (!bearer_name_validate(name, &b_names)) {
280 		pr_warn("Bearer <%s> rejected, illegal name\n", name);
281 		return -EINVAL;
282 	}
283 	if (tipc_addr_domain_valid(disc_domain) &&
284 	    (disc_domain != tipc_own_addr)) {
285 		if (tipc_in_scope(disc_domain, tipc_own_addr)) {
286 			disc_domain = tipc_own_addr & TIPC_CLUSTER_MASK;
287 			res = 0;   /* accept any node in own cluster */
288 		} else if (in_own_cluster_exact(disc_domain))
289 			res = 0;   /* accept specified node in own cluster */
290 	}
291 	if (res) {
292 		pr_warn("Bearer <%s> rejected, illegal discovery domain\n",
293 			name);
294 		return -EINVAL;
295 	}
296 	if ((priority > TIPC_MAX_LINK_PRI) &&
297 	    (priority != TIPC_MEDIA_LINK_PRI)) {
298 		pr_warn("Bearer <%s> rejected, illegal priority\n", name);
299 		return -EINVAL;
300 	}
301 
302 	m_ptr = tipc_media_find(b_names.media_name);
303 	if (!m_ptr) {
304 		pr_warn("Bearer <%s> rejected, media <%s> not registered\n",
305 			name, b_names.media_name);
306 		return -EINVAL;
307 	}
308 
309 	if (priority == TIPC_MEDIA_LINK_PRI)
310 		priority = m_ptr->priority;
311 
312 restart:
313 	bearer_id = MAX_BEARERS;
314 	with_this_prio = 1;
315 	for (i = MAX_BEARERS; i-- != 0; ) {
316 		b_ptr = rtnl_dereference(bearer_list[i]);
317 		if (!b_ptr) {
318 			bearer_id = i;
319 			continue;
320 		}
321 		if (!strcmp(name, b_ptr->name)) {
322 			pr_warn("Bearer <%s> rejected, already enabled\n",
323 				name);
324 			return -EINVAL;
325 		}
326 		if ((b_ptr->priority == priority) &&
327 		    (++with_this_prio > 2)) {
328 			if (priority-- == 0) {
329 				pr_warn("Bearer <%s> rejected, duplicate priority\n",
330 					name);
331 				return -EINVAL;
332 			}
333 			pr_warn("Bearer <%s> priority adjustment required %u->%u\n",
334 				name, priority + 1, priority);
335 			goto restart;
336 		}
337 	}
338 	if (bearer_id >= MAX_BEARERS) {
339 		pr_warn("Bearer <%s> rejected, bearer limit reached (%u)\n",
340 			name, MAX_BEARERS);
341 		return -EINVAL;
342 	}
343 
344 	b_ptr = kzalloc(sizeof(*b_ptr), GFP_ATOMIC);
345 	if (!b_ptr)
346 		return -ENOMEM;
347 
348 	strcpy(b_ptr->name, name);
349 	b_ptr->media = m_ptr;
350 	res = m_ptr->enable_media(b_ptr);
351 	if (res) {
352 		pr_warn("Bearer <%s> rejected, enable failure (%d)\n",
353 			name, -res);
354 		return -EINVAL;
355 	}
356 
357 	b_ptr->identity = bearer_id;
358 	b_ptr->tolerance = m_ptr->tolerance;
359 	b_ptr->window = m_ptr->window;
360 	b_ptr->domain = disc_domain;
361 	b_ptr->net_plane = bearer_id + 'A';
362 	b_ptr->priority = priority;
363 
364 	res = tipc_disc_create(b_ptr, &b_ptr->bcast_addr);
365 	if (res) {
366 		bearer_disable(b_ptr, false);
367 		pr_warn("Bearer <%s> rejected, discovery object creation failed\n",
368 			name);
369 		return -EINVAL;
370 	}
371 
372 	rcu_assign_pointer(bearer_list[bearer_id], b_ptr);
373 
374 	pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n",
375 		name,
376 		tipc_addr_string_fill(addr_string, disc_domain), priority);
377 	return res;
378 }
379 
380 /**
381  * tipc_reset_bearer - Reset all links established over this bearer
382  */
383 static int tipc_reset_bearer(struct tipc_bearer *b_ptr)
384 {
385 	pr_info("Resetting bearer <%s>\n", b_ptr->name);
386 	tipc_link_reset_list(b_ptr->identity);
387 	tipc_disc_reset(b_ptr);
388 	return 0;
389 }
390 
391 /**
392  * bearer_disable
393  *
394  * Note: This routine assumes caller holds RTNL lock.
395  */
396 static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down)
397 {
398 	u32 i;
399 
400 	pr_info("Disabling bearer <%s>\n", b_ptr->name);
401 	b_ptr->media->disable_media(b_ptr);
402 
403 	tipc_link_delete_list(b_ptr->identity, shutting_down);
404 	if (b_ptr->link_req)
405 		tipc_disc_delete(b_ptr->link_req);
406 
407 	for (i = 0; i < MAX_BEARERS; i++) {
408 		if (b_ptr == rtnl_dereference(bearer_list[i])) {
409 			RCU_INIT_POINTER(bearer_list[i], NULL);
410 			break;
411 		}
412 	}
413 	kfree_rcu(b_ptr, rcu);
414 }
415 
416 int tipc_disable_bearer(const char *name)
417 {
418 	struct tipc_bearer *b_ptr;
419 	int res;
420 
421 	b_ptr = tipc_bearer_find(name);
422 	if (b_ptr == NULL) {
423 		pr_warn("Attempt to disable unknown bearer <%s>\n", name);
424 		res = -EINVAL;
425 	} else {
426 		bearer_disable(b_ptr, false);
427 		res = 0;
428 	}
429 	return res;
430 }
431 
432 int tipc_enable_l2_media(struct tipc_bearer *b)
433 {
434 	struct net_device *dev;
435 	char *driver_name = strchr((const char *)b->name, ':') + 1;
436 
437 	/* Find device with specified name */
438 	dev = dev_get_by_name(&init_net, driver_name);
439 	if (!dev)
440 		return -ENODEV;
441 
442 	/* Associate TIPC bearer with L2 bearer */
443 	rcu_assign_pointer(b->media_ptr, dev);
444 	memset(&b->bcast_addr, 0, sizeof(b->bcast_addr));
445 	memcpy(b->bcast_addr.value, dev->broadcast, b->media->hwaddr_len);
446 	b->bcast_addr.media_id = b->media->type_id;
447 	b->bcast_addr.broadcast = 1;
448 	b->mtu = dev->mtu;
449 	b->media->raw2addr(b, &b->addr, (char *)dev->dev_addr);
450 	rcu_assign_pointer(dev->tipc_ptr, b);
451 	return 0;
452 }
453 
454 /* tipc_disable_l2_media - detach TIPC bearer from an L2 interface
455  *
456  * Mark L2 bearer as inactive so that incoming buffers are thrown away,
457  * then get worker thread to complete bearer cleanup.  (Can't do cleanup
458  * here because cleanup code needs to sleep and caller holds spinlocks.)
459  */
460 void tipc_disable_l2_media(struct tipc_bearer *b)
461 {
462 	struct net_device *dev;
463 
464 	dev = (struct net_device *)rtnl_dereference(b->media_ptr);
465 	RCU_INIT_POINTER(b->media_ptr, NULL);
466 	RCU_INIT_POINTER(dev->tipc_ptr, NULL);
467 	synchronize_net();
468 	dev_put(dev);
469 }
470 
471 /**
472  * tipc_l2_send_msg - send a TIPC packet out over an L2 interface
473  * @buf: the packet to be sent
474  * @b_ptr: the bearer through which the packet is to be sent
475  * @dest: peer destination address
476  */
477 int tipc_l2_send_msg(struct sk_buff *buf, struct tipc_bearer *b,
478 		     struct tipc_media_addr *dest)
479 {
480 	struct sk_buff *clone;
481 	struct net_device *dev;
482 	int delta;
483 
484 	dev = (struct net_device *)rcu_dereference_rtnl(b->media_ptr);
485 	if (!dev)
486 		return 0;
487 
488 	clone = skb_clone(buf, GFP_ATOMIC);
489 	if (!clone)
490 		return 0;
491 
492 	delta = dev->hard_header_len - skb_headroom(buf);
493 	if ((delta > 0) &&
494 	    pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) {
495 		kfree_skb(clone);
496 		return 0;
497 	}
498 
499 	skb_reset_network_header(clone);
500 	clone->dev = dev;
501 	clone->protocol = htons(ETH_P_TIPC);
502 	dev_hard_header(clone, dev, ETH_P_TIPC, dest->value,
503 			dev->dev_addr, clone->len);
504 	dev_queue_xmit(clone);
505 	return 0;
506 }
507 
508 /* tipc_bearer_send- sends buffer to destination over bearer
509  *
510  * IMPORTANT:
511  * The media send routine must not alter the buffer being passed in
512  * as it may be needed for later retransmission!
513  */
514 void tipc_bearer_send(u32 bearer_id, struct sk_buff *buf,
515 		      struct tipc_media_addr *dest)
516 {
517 	struct tipc_bearer *b_ptr;
518 
519 	rcu_read_lock();
520 	b_ptr = rcu_dereference_rtnl(bearer_list[bearer_id]);
521 	if (likely(b_ptr))
522 		b_ptr->media->send_msg(buf, b_ptr, dest);
523 	rcu_read_unlock();
524 }
525 
526 /**
527  * tipc_l2_rcv_msg - handle incoming TIPC message from an interface
528  * @buf: the received packet
529  * @dev: the net device that the packet was received on
530  * @pt: the packet_type structure which was used to register this handler
531  * @orig_dev: the original receive net device in case the device is a bond
532  *
533  * Accept only packets explicitly sent to this node, or broadcast packets;
534  * ignores packets sent using interface multicast, and traffic sent to other
535  * nodes (which can happen if interface is running in promiscuous mode).
536  */
537 static int tipc_l2_rcv_msg(struct sk_buff *buf, struct net_device *dev,
538 			   struct packet_type *pt, struct net_device *orig_dev)
539 {
540 	struct tipc_bearer *b_ptr;
541 
542 	if (!net_eq(dev_net(dev), &init_net)) {
543 		kfree_skb(buf);
544 		return NET_RX_DROP;
545 	}
546 
547 	rcu_read_lock();
548 	b_ptr = rcu_dereference_rtnl(dev->tipc_ptr);
549 	if (likely(b_ptr)) {
550 		if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
551 			buf->next = NULL;
552 			tipc_rcv(buf, b_ptr);
553 			rcu_read_unlock();
554 			return NET_RX_SUCCESS;
555 		}
556 	}
557 	rcu_read_unlock();
558 
559 	kfree_skb(buf);
560 	return NET_RX_DROP;
561 }
562 
563 /**
564  * tipc_l2_device_event - handle device events from network device
565  * @nb: the context of the notification
566  * @evt: the type of event
567  * @ptr: the net device that the event was on
568  *
569  * This function is called by the Ethernet driver in case of link
570  * change event.
571  */
572 static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
573 				void *ptr)
574 {
575 	struct tipc_bearer *b_ptr;
576 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
577 
578 	if (!net_eq(dev_net(dev), &init_net))
579 		return NOTIFY_DONE;
580 
581 	b_ptr = rtnl_dereference(dev->tipc_ptr);
582 	if (!b_ptr)
583 		return NOTIFY_DONE;
584 
585 	b_ptr->mtu = dev->mtu;
586 
587 	switch (evt) {
588 	case NETDEV_CHANGE:
589 		if (netif_carrier_ok(dev))
590 			break;
591 	case NETDEV_DOWN:
592 	case NETDEV_CHANGEMTU:
593 		tipc_reset_bearer(b_ptr);
594 		break;
595 	case NETDEV_CHANGEADDR:
596 		b_ptr->media->raw2addr(b_ptr, &b_ptr->addr,
597 				       (char *)dev->dev_addr);
598 		tipc_reset_bearer(b_ptr);
599 		break;
600 	case NETDEV_UNREGISTER:
601 	case NETDEV_CHANGENAME:
602 		bearer_disable(b_ptr, false);
603 		break;
604 	}
605 	return NOTIFY_OK;
606 }
607 
608 static struct packet_type tipc_packet_type __read_mostly = {
609 	.type = htons(ETH_P_TIPC),
610 	.func = tipc_l2_rcv_msg,
611 };
612 
613 static struct notifier_block notifier = {
614 	.notifier_call  = tipc_l2_device_event,
615 	.priority	= 0,
616 };
617 
618 int tipc_bearer_setup(void)
619 {
620 	int err;
621 
622 	err = register_netdevice_notifier(&notifier);
623 	if (err)
624 		return err;
625 	dev_add_pack(&tipc_packet_type);
626 	return 0;
627 }
628 
629 void tipc_bearer_cleanup(void)
630 {
631 	unregister_netdevice_notifier(&notifier);
632 	dev_remove_pack(&tipc_packet_type);
633 }
634 
635 void tipc_bearer_stop(void)
636 {
637 	struct tipc_bearer *b_ptr;
638 	u32 i;
639 
640 	for (i = 0; i < MAX_BEARERS; i++) {
641 		b_ptr = rtnl_dereference(bearer_list[i]);
642 		if (b_ptr) {
643 			bearer_disable(b_ptr, true);
644 			bearer_list[i] = NULL;
645 		}
646 	}
647 }
648 
649 /* Caller should hold rtnl_lock to protect the bearer */
650 static int __tipc_nl_add_bearer(struct tipc_nl_msg *msg,
651 				struct tipc_bearer *bearer)
652 {
653 	void *hdr;
654 	struct nlattr *attrs;
655 	struct nlattr *prop;
656 
657 	hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_v2_family,
658 			  NLM_F_MULTI, TIPC_NL_BEARER_GET);
659 	if (!hdr)
660 		return -EMSGSIZE;
661 
662 	attrs = nla_nest_start(msg->skb, TIPC_NLA_BEARER);
663 	if (!attrs)
664 		goto msg_full;
665 
666 	if (nla_put_string(msg->skb, TIPC_NLA_BEARER_NAME, bearer->name))
667 		goto attr_msg_full;
668 
669 	prop = nla_nest_start(msg->skb, TIPC_NLA_BEARER_PROP);
670 	if (!prop)
671 		goto prop_msg_full;
672 	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_PRIO, bearer->priority))
673 		goto prop_msg_full;
674 	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_TOL, bearer->tolerance))
675 		goto prop_msg_full;
676 	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, bearer->window))
677 		goto prop_msg_full;
678 
679 	nla_nest_end(msg->skb, prop);
680 	nla_nest_end(msg->skb, attrs);
681 	genlmsg_end(msg->skb, hdr);
682 
683 	return 0;
684 
685 prop_msg_full:
686 	nla_nest_cancel(msg->skb, prop);
687 attr_msg_full:
688 	nla_nest_cancel(msg->skb, attrs);
689 msg_full:
690 	genlmsg_cancel(msg->skb, hdr);
691 
692 	return -EMSGSIZE;
693 }
694 
695 int tipc_nl_bearer_dump(struct sk_buff *skb, struct netlink_callback *cb)
696 {
697 	int err;
698 	int i = cb->args[0];
699 	struct tipc_bearer *bearer;
700 	struct tipc_nl_msg msg;
701 
702 	if (i == MAX_BEARERS)
703 		return 0;
704 
705 	msg.skb = skb;
706 	msg.portid = NETLINK_CB(cb->skb).portid;
707 	msg.seq = cb->nlh->nlmsg_seq;
708 
709 	rtnl_lock();
710 	for (i = 0; i < MAX_BEARERS; i++) {
711 		bearer = rtnl_dereference(bearer_list[i]);
712 		if (!bearer)
713 			continue;
714 
715 		err = __tipc_nl_add_bearer(&msg, bearer);
716 		if (err)
717 			break;
718 	}
719 	rtnl_unlock();
720 
721 	cb->args[0] = i;
722 	return skb->len;
723 }
724 
725 int tipc_nl_bearer_get(struct sk_buff *skb, struct genl_info *info)
726 {
727 	int err;
728 	char *name;
729 	struct sk_buff *rep;
730 	struct tipc_bearer *bearer;
731 	struct tipc_nl_msg msg;
732 	struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
733 
734 	if (!info->attrs[TIPC_NLA_BEARER])
735 		return -EINVAL;
736 
737 	err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
738 			       info->attrs[TIPC_NLA_BEARER],
739 			       tipc_nl_bearer_policy);
740 	if (err)
741 		return err;
742 
743 	if (!attrs[TIPC_NLA_BEARER_NAME])
744 		return -EINVAL;
745 	name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
746 
747 	rep = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
748 	if (!rep)
749 		return -ENOMEM;
750 
751 	msg.skb = rep;
752 	msg.portid = info->snd_portid;
753 	msg.seq = info->snd_seq;
754 
755 	rtnl_lock();
756 	bearer = tipc_bearer_find(name);
757 	if (!bearer) {
758 		err = -EINVAL;
759 		goto err_out;
760 	}
761 
762 	err = __tipc_nl_add_bearer(&msg, bearer);
763 	if (err)
764 		goto err_out;
765 	rtnl_unlock();
766 
767 	return genlmsg_reply(rep, info);
768 err_out:
769 	rtnl_unlock();
770 	nlmsg_free(rep);
771 
772 	return err;
773 }
774 
775 int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info)
776 {
777 	int err;
778 	char *name;
779 	struct tipc_bearer *bearer;
780 	struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
781 
782 	if (!info->attrs[TIPC_NLA_BEARER])
783 		return -EINVAL;
784 
785 	err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
786 			       info->attrs[TIPC_NLA_BEARER],
787 			       tipc_nl_bearer_policy);
788 	if (err)
789 		return err;
790 
791 	if (!attrs[TIPC_NLA_BEARER_NAME])
792 		return -EINVAL;
793 
794 	name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
795 
796 	rtnl_lock();
797 	bearer = tipc_bearer_find(name);
798 	if (!bearer) {
799 		rtnl_unlock();
800 		return -EINVAL;
801 	}
802 
803 	bearer_disable(bearer, false);
804 	rtnl_unlock();
805 
806 	return 0;
807 }
808 
809 int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info)
810 {
811 	int err;
812 	char *bearer;
813 	struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
814 	u32 domain;
815 	u32 prio;
816 
817 	prio = TIPC_MEDIA_LINK_PRI;
818 	domain = tipc_own_addr & TIPC_CLUSTER_MASK;
819 
820 	if (!info->attrs[TIPC_NLA_BEARER])
821 		return -EINVAL;
822 
823 	err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
824 			       info->attrs[TIPC_NLA_BEARER],
825 			       tipc_nl_bearer_policy);
826 	if (err)
827 		return err;
828 
829 	if (!attrs[TIPC_NLA_BEARER_NAME])
830 		return -EINVAL;
831 
832 	bearer = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
833 
834 	if (attrs[TIPC_NLA_BEARER_DOMAIN])
835 		domain = nla_get_u32(attrs[TIPC_NLA_BEARER_DOMAIN]);
836 
837 	if (attrs[TIPC_NLA_BEARER_PROP]) {
838 		struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
839 
840 		err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_BEARER_PROP],
841 					      props);
842 		if (err)
843 			return err;
844 
845 		if (props[TIPC_NLA_PROP_PRIO])
846 			prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
847 	}
848 
849 	rtnl_lock();
850 	err = tipc_enable_bearer(bearer, domain, prio);
851 	if (err) {
852 		rtnl_unlock();
853 		return err;
854 	}
855 	rtnl_unlock();
856 
857 	return 0;
858 }
859 
860 int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info)
861 {
862 	int err;
863 	char *name;
864 	struct tipc_bearer *b;
865 	struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
866 
867 	if (!info->attrs[TIPC_NLA_BEARER])
868 		return -EINVAL;
869 
870 	err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
871 			       info->attrs[TIPC_NLA_BEARER],
872 			       tipc_nl_bearer_policy);
873 	if (err)
874 		return err;
875 
876 	if (!attrs[TIPC_NLA_BEARER_NAME])
877 		return -EINVAL;
878 	name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
879 
880 	rtnl_lock();
881 	b = tipc_bearer_find(name);
882 	if (!b) {
883 		rtnl_unlock();
884 		return -EINVAL;
885 	}
886 
887 	if (attrs[TIPC_NLA_BEARER_PROP]) {
888 		struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
889 
890 		err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_BEARER_PROP],
891 					      props);
892 		if (err) {
893 			rtnl_unlock();
894 			return err;
895 		}
896 
897 		if (props[TIPC_NLA_PROP_TOL])
898 			b->tolerance = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
899 		if (props[TIPC_NLA_PROP_PRIO])
900 			b->priority = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
901 		if (props[TIPC_NLA_PROP_WIN])
902 			b->window = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
903 	}
904 	rtnl_unlock();
905 
906 	return 0;
907 }
908 
909 static int __tipc_nl_add_media(struct tipc_nl_msg *msg,
910 			       struct tipc_media *media)
911 {
912 	void *hdr;
913 	struct nlattr *attrs;
914 	struct nlattr *prop;
915 
916 	hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_v2_family,
917 			  NLM_F_MULTI, TIPC_NL_MEDIA_GET);
918 	if (!hdr)
919 		return -EMSGSIZE;
920 
921 	attrs = nla_nest_start(msg->skb, TIPC_NLA_MEDIA);
922 	if (!attrs)
923 		goto msg_full;
924 
925 	if (nla_put_string(msg->skb, TIPC_NLA_MEDIA_NAME, media->name))
926 		goto attr_msg_full;
927 
928 	prop = nla_nest_start(msg->skb, TIPC_NLA_MEDIA_PROP);
929 	if (!prop)
930 		goto prop_msg_full;
931 	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_PRIO, media->priority))
932 		goto prop_msg_full;
933 	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_TOL, media->tolerance))
934 		goto prop_msg_full;
935 	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, media->window))
936 		goto prop_msg_full;
937 
938 	nla_nest_end(msg->skb, prop);
939 	nla_nest_end(msg->skb, attrs);
940 	genlmsg_end(msg->skb, hdr);
941 
942 	return 0;
943 
944 prop_msg_full:
945 	nla_nest_cancel(msg->skb, prop);
946 attr_msg_full:
947 	nla_nest_cancel(msg->skb, attrs);
948 msg_full:
949 	genlmsg_cancel(msg->skb, hdr);
950 
951 	return -EMSGSIZE;
952 }
953 
954 int tipc_nl_media_dump(struct sk_buff *skb, struct netlink_callback *cb)
955 {
956 	int err;
957 	int i = cb->args[0];
958 	struct tipc_nl_msg msg;
959 
960 	if (i == MAX_MEDIA)
961 		return 0;
962 
963 	msg.skb = skb;
964 	msg.portid = NETLINK_CB(cb->skb).portid;
965 	msg.seq = cb->nlh->nlmsg_seq;
966 
967 	rtnl_lock();
968 	for (; media_info_array[i] != NULL; i++) {
969 		err = __tipc_nl_add_media(&msg, media_info_array[i]);
970 		if (err)
971 			break;
972 	}
973 	rtnl_unlock();
974 
975 	cb->args[0] = i;
976 	return skb->len;
977 }
978 
979 int tipc_nl_media_get(struct sk_buff *skb, struct genl_info *info)
980 {
981 	int err;
982 	char *name;
983 	struct tipc_nl_msg msg;
984 	struct tipc_media *media;
985 	struct sk_buff *rep;
986 	struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
987 
988 	if (!info->attrs[TIPC_NLA_MEDIA])
989 		return -EINVAL;
990 
991 	err = nla_parse_nested(attrs, TIPC_NLA_MEDIA_MAX,
992 			       info->attrs[TIPC_NLA_MEDIA],
993 			       tipc_nl_media_policy);
994 	if (err)
995 		return err;
996 
997 	if (!attrs[TIPC_NLA_MEDIA_NAME])
998 		return -EINVAL;
999 	name = nla_data(attrs[TIPC_NLA_MEDIA_NAME]);
1000 
1001 	rep = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1002 	if (!rep)
1003 		return -ENOMEM;
1004 
1005 	msg.skb = rep;
1006 	msg.portid = info->snd_portid;
1007 	msg.seq = info->snd_seq;
1008 
1009 	rtnl_lock();
1010 	media = tipc_media_find(name);
1011 	if (!media) {
1012 		err = -EINVAL;
1013 		goto err_out;
1014 	}
1015 
1016 	err = __tipc_nl_add_media(&msg, media);
1017 	if (err)
1018 		goto err_out;
1019 	rtnl_unlock();
1020 
1021 	return genlmsg_reply(rep, info);
1022 err_out:
1023 	rtnl_unlock();
1024 	nlmsg_free(rep);
1025 
1026 	return err;
1027 }
1028 
1029 int tipc_nl_media_set(struct sk_buff *skb, struct genl_info *info)
1030 {
1031 	int err;
1032 	char *name;
1033 	struct tipc_media *m;
1034 	struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
1035 
1036 	if (!info->attrs[TIPC_NLA_MEDIA])
1037 		return -EINVAL;
1038 
1039 	err = nla_parse_nested(attrs, TIPC_NLA_MEDIA_MAX,
1040 			       info->attrs[TIPC_NLA_MEDIA],
1041 			       tipc_nl_media_policy);
1042 
1043 	if (!attrs[TIPC_NLA_MEDIA_NAME])
1044 		return -EINVAL;
1045 	name = nla_data(attrs[TIPC_NLA_MEDIA_NAME]);
1046 
1047 	rtnl_lock();
1048 	m = tipc_media_find(name);
1049 	if (!m) {
1050 		rtnl_unlock();
1051 		return -EINVAL;
1052 	}
1053 
1054 	if (attrs[TIPC_NLA_MEDIA_PROP]) {
1055 		struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
1056 
1057 		err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_MEDIA_PROP],
1058 					      props);
1059 		if (err) {
1060 			rtnl_unlock();
1061 			return err;
1062 		}
1063 
1064 		if (props[TIPC_NLA_PROP_TOL])
1065 			m->tolerance = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
1066 		if (props[TIPC_NLA_PROP_PRIO])
1067 			m->priority = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
1068 		if (props[TIPC_NLA_PROP_WIN])
1069 			m->window = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
1070 	}
1071 	rtnl_unlock();
1072 
1073 	return 0;
1074 }
1075