xref: /openbmc/linux/net/tipc/bearer.c (revision b97bf3fd)
1 /*
2  * net/tipc/bearer.c: TIPC bearer code
3  *
4  * Copyright (c) 2003-2005, Ericsson Research Canada
5  * Copyright (c) 2004-2005, Wind River Systems
6  * Copyright (c) 2005-2006, Ericsson AB
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  * Redistributions of source code must retain the above copyright notice, this
13  * list of conditions and the following disclaimer.
14  * Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  * Neither the names of the copyright holders nor the names of its
18  * contributors may be used to endorse or promote products derived from this
19  * software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "core.h"
35 #include "config.h"
36 #include "dbg.h"
37 #include "bearer.h"
38 #include "link.h"
39 #include "port.h"
40 #include "discover.h"
41 #include "bcast.h"
42 
43 #define MAX_ADDR_STR 32
44 
45 static struct media *media_list = 0;
46 static u32 media_count = 0;
47 
48 struct bearer *bearers = 0;
49 
50 /**
51  * media_name_valid - validate media name
52  *
53  * Returns 1 if media name is valid, otherwise 0.
54  */
55 
56 static int media_name_valid(const char *name)
57 {
58 	u32 len;
59 
60 	len = strlen(name);
61 	if ((len + 1) > TIPC_MAX_MEDIA_NAME)
62 		return 0;
63 	return (strspn(name, tipc_alphabet) == len);
64 }
65 
66 /**
67  * media_find - locates specified media object by name
68  */
69 
70 static struct media *media_find(const char *name)
71 {
72 	struct media *m_ptr;
73 	u32 i;
74 
75 	for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
76 		if (!strcmp(m_ptr->name, name))
77 			return m_ptr;
78 	}
79 	return 0;
80 }
81 
82 /**
83  * tipc_register_media - register a media type
84  *
85  * Bearers for this media type must be activated separately at a later stage.
86  */
87 
88 int  tipc_register_media(u32 media_type,
89 			 char *name,
90 			 int (*enable)(struct tipc_bearer *),
91 			 void (*disable)(struct tipc_bearer *),
92 			 int (*send_msg)(struct sk_buff *,
93 					 struct tipc_bearer *,
94 					 struct tipc_media_addr *),
95 			 char *(*addr2str)(struct tipc_media_addr *a,
96 					   char *str_buf, int str_size),
97 			 struct tipc_media_addr *bcast_addr,
98 			 const u32 bearer_priority,
99 			 const u32 link_tolerance,  /* [ms] */
100 			 const u32 send_window_limit)
101 {
102 	struct media *m_ptr;
103 	u32 media_id;
104 	u32 i;
105 	int res = -EINVAL;
106 
107 	write_lock_bh(&net_lock);
108 	if (!media_list)
109 		goto exit;
110 
111 	if (!media_name_valid(name)) {
112 		warn("Media registration error: illegal name <%s>\n", name);
113 		goto exit;
114 	}
115 	if (!bcast_addr) {
116 		warn("Media registration error: no broadcast address supplied\n");
117 		goto exit;
118 	}
119 	if (bearer_priority >= TIPC_NUM_LINK_PRI) {
120 		warn("Media registration error: priority %u\n", bearer_priority);
121 		goto exit;
122 	}
123 	if ((link_tolerance < TIPC_MIN_LINK_TOL) ||
124 	    (link_tolerance > TIPC_MAX_LINK_TOL)) {
125 		warn("Media registration error: tolerance %u\n", link_tolerance);
126 		goto exit;
127 	}
128 
129 	media_id = media_count++;
130 	if (media_id >= MAX_MEDIA) {
131 		warn("Attempt to register more than %u media\n", MAX_MEDIA);
132 		media_count--;
133 		goto exit;
134 	}
135 	for (i = 0; i < media_id; i++) {
136 		if (media_list[i].type_id == media_type) {
137 			warn("Attempt to register second media with type %u\n",
138 			     media_type);
139 			media_count--;
140 			goto exit;
141 		}
142 		if (!strcmp(name, media_list[i].name)) {
143 			warn("Attempt to re-register media name <%s>\n", name);
144 			media_count--;
145 			goto exit;
146 		}
147 	}
148 
149 	m_ptr = &media_list[media_id];
150 	m_ptr->type_id = media_type;
151 	m_ptr->send_msg = send_msg;
152 	m_ptr->enable_bearer = enable;
153 	m_ptr->disable_bearer = disable;
154 	m_ptr->addr2str = addr2str;
155 	memcpy(&m_ptr->bcast_addr, bcast_addr, sizeof(*bcast_addr));
156 	m_ptr->bcast = 1;
157 	strcpy(m_ptr->name, name);
158 	m_ptr->priority = bearer_priority;
159 	m_ptr->tolerance = link_tolerance;
160 	m_ptr->window = send_window_limit;
161 	dbg("Media <%s> registered\n", name);
162 	res = 0;
163 exit:
164 	write_unlock_bh(&net_lock);
165 	return res;
166 }
167 
168 /**
169  * media_addr_printf - record media address in print buffer
170  */
171 
172 void media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a)
173 {
174 	struct media *m_ptr;
175 	u32 media_type;
176 	u32 i;
177 
178 	media_type = ntohl(a->type);
179 	for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
180 		if (m_ptr->type_id == media_type)
181 			break;
182 	}
183 
184 	if ((i < media_count) && (m_ptr->addr2str != NULL)) {
185 		char addr_str[MAX_ADDR_STR];
186 
187 		tipc_printf(pb, "%s(%s) ", m_ptr->name,
188 			    m_ptr->addr2str(a, addr_str, sizeof(addr_str)));
189 	} else {
190 		unchar *addr = (unchar *)&a->dev_addr;
191 
192 		tipc_printf(pb, "UNKNOWN(%u):", media_type);
193 		for (i = 0; i < (sizeof(*a) - sizeof(a->type)); i++) {
194 			tipc_printf(pb, "%02x ", addr[i]);
195 		}
196 	}
197 }
198 
199 /**
200  * media_get_names - record names of registered media in buffer
201  */
202 
203 struct sk_buff *media_get_names(void)
204 {
205 	struct sk_buff *buf;
206 	struct media *m_ptr;
207 	int i;
208 
209 	buf = cfg_reply_alloc(MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME));
210 	if (!buf)
211 		return NULL;
212 
213 	read_lock_bh(&net_lock);
214 	for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
215 		cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME, m_ptr->name,
216 			       strlen(m_ptr->name) + 1);
217 	}
218 	read_unlock_bh(&net_lock);
219 	return buf;
220 }
221 
222 /**
223  * bearer_name_validate - validate & (optionally) deconstruct bearer name
224  * @name - ptr to bearer name string
225  * @name_parts - ptr to area for bearer name components (or NULL if not needed)
226  *
227  * Returns 1 if bearer name is valid, otherwise 0.
228  */
229 
230 static int bearer_name_validate(const char *name,
231 				struct bearer_name *name_parts)
232 {
233 	char name_copy[TIPC_MAX_BEARER_NAME];
234 	char *media_name;
235 	char *if_name;
236 	u32 media_len;
237 	u32 if_len;
238 
239 	/* copy bearer name & ensure length is OK */
240 
241 	name_copy[TIPC_MAX_BEARER_NAME - 1] = 0;
242 	/* need above in case non-Posix strncpy() doesn't pad with nulls */
243 	strncpy(name_copy, name, TIPC_MAX_BEARER_NAME);
244 	if (name_copy[TIPC_MAX_BEARER_NAME - 1] != 0)
245 		return 0;
246 
247 	/* ensure all component parts of bearer name are present */
248 
249 	media_name = name_copy;
250 	if ((if_name = strchr(media_name, ':')) == NULL)
251 		return 0;
252 	*(if_name++) = 0;
253 	media_len = if_name - media_name;
254 	if_len = strlen(if_name) + 1;
255 
256 	/* validate component parts of bearer name */
257 
258 	if ((media_len <= 1) || (media_len > TIPC_MAX_MEDIA_NAME) ||
259 	    (if_len <= 1) || (if_len > TIPC_MAX_IF_NAME) ||
260 	    (strspn(media_name, tipc_alphabet) != (media_len - 1)) ||
261 	    (strspn(if_name, tipc_alphabet) != (if_len - 1)))
262 		return 0;
263 
264 	/* return bearer name components, if necessary */
265 
266 	if (name_parts) {
267 		strcpy(name_parts->media_name, media_name);
268 		strcpy(name_parts->if_name, if_name);
269 	}
270 	return 1;
271 }
272 
273 /**
274  * bearer_find - locates bearer object with matching bearer name
275  */
276 
277 static struct bearer *bearer_find(const char *name)
278 {
279 	struct bearer *b_ptr;
280 	u32 i;
281 
282 	for (i = 0, b_ptr = bearers; i < MAX_BEARERS; i++, b_ptr++) {
283 		if (b_ptr->active && (!strcmp(b_ptr->publ.name, name)))
284 			return b_ptr;
285 	}
286 	return 0;
287 }
288 
289 /**
290  * bearer_find - locates bearer object with matching interface name
291  */
292 
293 struct bearer *bearer_find_interface(const char *if_name)
294 {
295 	struct bearer *b_ptr;
296 	char *b_if_name;
297 	u32 i;
298 
299 	for (i = 0, b_ptr = bearers; i < MAX_BEARERS; i++, b_ptr++) {
300 		if (!b_ptr->active)
301 			continue;
302 		b_if_name = strchr(b_ptr->publ.name, ':') + 1;
303 		if (!strcmp(b_if_name, if_name))
304 			return b_ptr;
305 	}
306 	return 0;
307 }
308 
309 /**
310  * bearer_get_names - record names of bearers in buffer
311  */
312 
313 struct sk_buff *bearer_get_names(void)
314 {
315 	struct sk_buff *buf;
316 	struct media *m_ptr;
317 	struct bearer *b_ptr;
318 	int i, j;
319 
320 	buf = cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME));
321 	if (!buf)
322 		return NULL;
323 
324 	read_lock_bh(&net_lock);
325 	for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
326 		for (j = 0; j < MAX_BEARERS; j++) {
327 			b_ptr = &bearers[j];
328 			if (b_ptr->active && (b_ptr->media == m_ptr)) {
329 				cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME,
330 					       b_ptr->publ.name,
331 					       strlen(b_ptr->publ.name) + 1);
332 			}
333 		}
334 	}
335 	read_unlock_bh(&net_lock);
336 	return buf;
337 }
338 
339 void bearer_add_dest(struct bearer *b_ptr, u32 dest)
340 {
341 	nmap_add(&b_ptr->nodes, dest);
342 	disc_update_link_req(b_ptr->link_req);
343 	bcbearer_sort();
344 }
345 
346 void bearer_remove_dest(struct bearer *b_ptr, u32 dest)
347 {
348 	nmap_remove(&b_ptr->nodes, dest);
349 	disc_update_link_req(b_ptr->link_req);
350 	bcbearer_sort();
351 }
352 
353 /*
354  * bearer_push(): Resolve bearer congestion. Force the waiting
355  * links to push out their unsent packets, one packet per link
356  * per iteration, until all packets are gone or congestion reoccurs.
357  * 'net_lock' is read_locked when this function is called
358  * bearer.lock must be taken before calling
359  * Returns binary true(1) ore false(0)
360  */
361 static int bearer_push(struct bearer *b_ptr)
362 {
363 	u32 res = TIPC_OK;
364 	struct link *ln, *tln;
365 
366 	if (b_ptr->publ.blocked)
367 		return 0;
368 
369 	while (!list_empty(&b_ptr->cong_links) && (res != PUSH_FAILED)) {
370 		list_for_each_entry_safe(ln, tln, &b_ptr->cong_links, link_list) {
371 			res = link_push_packet(ln);
372 			if (res == PUSH_FAILED)
373 				break;
374 			if (res == PUSH_FINISHED)
375 				list_move_tail(&ln->link_list, &b_ptr->links);
376 		}
377 	}
378 	return list_empty(&b_ptr->cong_links);
379 }
380 
381 void bearer_lock_push(struct bearer *b_ptr)
382 {
383 	int res;
384 
385 	spin_lock_bh(&b_ptr->publ.lock);
386 	res = bearer_push(b_ptr);
387 	spin_unlock_bh(&b_ptr->publ.lock);
388 	if (res)
389 		bcbearer_push();
390 }
391 
392 
393 /*
394  * Interrupt enabling new requests after bearer congestion or blocking:
395  * See bearer_send().
396  */
397 void tipc_continue(struct tipc_bearer *tb_ptr)
398 {
399 	struct bearer *b_ptr = (struct bearer *)tb_ptr;
400 
401 	spin_lock_bh(&b_ptr->publ.lock);
402 	b_ptr->continue_count++;
403 	if (!list_empty(&b_ptr->cong_links))
404 		k_signal((Handler)bearer_lock_push, (unsigned long)b_ptr);
405 	b_ptr->publ.blocked = 0;
406 	spin_unlock_bh(&b_ptr->publ.lock);
407 }
408 
409 /*
410  * Schedule link for sending of messages after the bearer
411  * has been deblocked by 'continue()'. This method is called
412  * when somebody tries to send a message via this link while
413  * the bearer is congested. 'net_lock' is in read_lock here
414  * bearer.lock is busy
415  */
416 
417 static void bearer_schedule_unlocked(struct bearer *b_ptr, struct link *l_ptr)
418 {
419 	list_move_tail(&l_ptr->link_list, &b_ptr->cong_links);
420 }
421 
422 /*
423  * Schedule link for sending of messages after the bearer
424  * has been deblocked by 'continue()'. This method is called
425  * when somebody tries to send a message via this link while
426  * the bearer is congested. 'net_lock' is in read_lock here,
427  * bearer.lock is free
428  */
429 
430 void bearer_schedule(struct bearer *b_ptr, struct link *l_ptr)
431 {
432 	spin_lock_bh(&b_ptr->publ.lock);
433 	bearer_schedule_unlocked(b_ptr, l_ptr);
434 	spin_unlock_bh(&b_ptr->publ.lock);
435 }
436 
437 
438 /*
439  * bearer_resolve_congestion(): Check if there is bearer congestion,
440  * and if there is, try to resolve it before returning.
441  * 'net_lock' is read_locked when this function is called
442  */
443 int bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr)
444 {
445 	int res = 1;
446 
447 	if (list_empty(&b_ptr->cong_links))
448 		return 1;
449 	spin_lock_bh(&b_ptr->publ.lock);
450 	if (!bearer_push(b_ptr)) {
451 		bearer_schedule_unlocked(b_ptr, l_ptr);
452 		res = 0;
453 	}
454 	spin_unlock_bh(&b_ptr->publ.lock);
455 	return res;
456 }
457 
458 
459 /**
460  * tipc_enable_bearer - enable bearer with the given name
461  */
462 
463 int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority)
464 {
465 	struct bearer *b_ptr;
466 	struct media *m_ptr;
467 	struct bearer_name b_name;
468 	char addr_string[16];
469 	u32 bearer_id;
470 	u32 with_this_prio;
471 	u32 i;
472 	int res = -EINVAL;
473 
474 	if (tipc_mode != TIPC_NET_MODE)
475 		return -ENOPROTOOPT;
476 	if (!bearer_name_validate(name, &b_name) ||
477 	    !addr_domain_valid(bcast_scope) ||
478 	    !in_scope(bcast_scope, tipc_own_addr) ||
479 	    (priority > TIPC_NUM_LINK_PRI))
480 		return -EINVAL;
481 
482 	write_lock_bh(&net_lock);
483 	if (!bearers)
484 		goto failed;
485 
486 	m_ptr = media_find(b_name.media_name);
487 	if (!m_ptr) {
488 		warn("No media <%s>\n", b_name.media_name);
489 		goto failed;
490 	}
491 	if (priority == TIPC_NUM_LINK_PRI)
492 		priority = m_ptr->priority;
493 
494 restart:
495 	bearer_id = MAX_BEARERS;
496 	with_this_prio = 1;
497 	for (i = MAX_BEARERS; i-- != 0; ) {
498 		if (!bearers[i].active) {
499 			bearer_id = i;
500 			continue;
501 		}
502 		if (!strcmp(name, bearers[i].publ.name)) {
503 			warn("Bearer <%s> already enabled\n", name);
504 			goto failed;
505 		}
506 		if ((bearers[i].priority == priority) &&
507 		    (++with_this_prio > 2)) {
508 			if (priority-- == 0) {
509 				warn("Third bearer <%s> with priority %u, unable to lower to %u\n",
510 				     name, priority + 1, priority);
511 				goto failed;
512 			}
513 			warn("Third bearer <%s> with priority %u, lowering to %u\n",
514 			     name, priority + 1, priority);
515 			goto restart;
516 		}
517 	}
518 	if (bearer_id >= MAX_BEARERS) {
519 		warn("Attempt to enable more than %d bearers\n", MAX_BEARERS);
520 		goto failed;
521 	}
522 
523 	b_ptr = &bearers[bearer_id];
524 	memset(b_ptr, 0, sizeof(struct bearer));
525 
526 	strcpy(b_ptr->publ.name, name);
527 	res = m_ptr->enable_bearer(&b_ptr->publ);
528 	if (res) {
529 		warn("Failed to enable bearer <%s>\n", name);
530 		goto failed;
531 	}
532 
533 	b_ptr->identity = bearer_id;
534 	b_ptr->media = m_ptr;
535 	b_ptr->net_plane = bearer_id + 'A';
536 	b_ptr->active = 1;
537 	b_ptr->detect_scope = bcast_scope;
538 	b_ptr->priority = priority;
539 	INIT_LIST_HEAD(&b_ptr->cong_links);
540 	INIT_LIST_HEAD(&b_ptr->links);
541 	if (m_ptr->bcast) {
542 		b_ptr->link_req = disc_init_link_req(b_ptr, &m_ptr->bcast_addr,
543 						     bcast_scope, 2);
544 	}
545 	b_ptr->publ.lock = SPIN_LOCK_UNLOCKED;
546 	write_unlock_bh(&net_lock);
547 	info("Enabled bearer <%s>, discovery domain %s\n",
548 	     name, addr_string_fill(addr_string, bcast_scope));
549 	return 0;
550 failed:
551 	write_unlock_bh(&net_lock);
552 	return res;
553 }
554 
555 /**
556  * tipc_block_bearer(): Block the bearer with the given name,
557  *                      and reset all its links
558  */
559 
560 int tipc_block_bearer(const char *name)
561 {
562 	struct bearer *b_ptr = 0;
563 	struct link *l_ptr;
564 	struct link *temp_l_ptr;
565 
566 	if (tipc_mode != TIPC_NET_MODE)
567 		return -ENOPROTOOPT;
568 
569 	read_lock_bh(&net_lock);
570 	b_ptr = bearer_find(name);
571 	if (!b_ptr) {
572 		warn("Attempt to block unknown bearer <%s>\n", name);
573 		read_unlock_bh(&net_lock);
574 		return -EINVAL;
575 	}
576 
577 	spin_lock_bh(&b_ptr->publ.lock);
578 	b_ptr->publ.blocked = 1;
579 	list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
580 		struct node *n_ptr = l_ptr->owner;
581 
582 		spin_lock_bh(&n_ptr->lock);
583 		link_reset(l_ptr);
584 		spin_unlock_bh(&n_ptr->lock);
585 	}
586 	spin_unlock_bh(&b_ptr->publ.lock);
587 	read_unlock_bh(&net_lock);
588 	info("Blocked bearer <%s>\n", name);
589 	return TIPC_OK;
590 }
591 
592 /**
593  * bearer_disable -
594  *
595  * Note: This routine assumes caller holds net_lock.
596  */
597 
598 static int bearer_disable(const char *name)
599 {
600 	struct bearer *b_ptr;
601 	struct link *l_ptr;
602 	struct link *temp_l_ptr;
603 
604 	if (tipc_mode != TIPC_NET_MODE)
605 		return -ENOPROTOOPT;
606 
607 	b_ptr = bearer_find(name);
608 	if (!b_ptr) {
609 		warn("Attempt to disable unknown bearer <%s>\n", name);
610 		return -EINVAL;
611 	}
612 
613 	disc_stop_link_req(b_ptr->link_req);
614 	spin_lock_bh(&b_ptr->publ.lock);
615 	b_ptr->link_req = NULL;
616 	b_ptr->publ.blocked = 1;
617 	if (b_ptr->media->disable_bearer) {
618 		spin_unlock_bh(&b_ptr->publ.lock);
619 		write_unlock_bh(&net_lock);
620 		b_ptr->media->disable_bearer(&b_ptr->publ);
621 		write_lock_bh(&net_lock);
622 		spin_lock_bh(&b_ptr->publ.lock);
623 	}
624 	list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
625 		link_delete(l_ptr);
626 	}
627 	spin_unlock_bh(&b_ptr->publ.lock);
628 	info("Disabled bearer <%s>\n", name);
629 	memset(b_ptr, 0, sizeof(struct bearer));
630 	return TIPC_OK;
631 }
632 
633 int tipc_disable_bearer(const char *name)
634 {
635 	int res;
636 
637 	write_lock_bh(&net_lock);
638 	res = bearer_disable(name);
639 	write_unlock_bh(&net_lock);
640 	return res;
641 }
642 
643 
644 
645 int bearer_init(void)
646 {
647 	int res;
648 
649 	write_lock_bh(&net_lock);
650 	bearers = kmalloc(MAX_BEARERS * sizeof(struct bearer), GFP_ATOMIC);
651 	media_list = kmalloc(MAX_MEDIA * sizeof(struct media), GFP_ATOMIC);
652 	if (bearers && media_list) {
653 		memset(bearers, 0, MAX_BEARERS * sizeof(struct bearer));
654 		memset(media_list, 0, MAX_MEDIA * sizeof(struct media));
655 		res = TIPC_OK;
656 	} else {
657 		kfree(bearers);
658 		kfree(media_list);
659 		bearers = 0;
660 		media_list = 0;
661 		res = -ENOMEM;
662 	}
663 	write_unlock_bh(&net_lock);
664 	return res;
665 }
666 
667 void bearer_stop(void)
668 {
669 	u32 i;
670 
671 	if (!bearers)
672 		return;
673 
674 	for (i = 0; i < MAX_BEARERS; i++) {
675 		if (bearers[i].active)
676 			bearers[i].publ.blocked = 1;
677 	}
678 	for (i = 0; i < MAX_BEARERS; i++) {
679 		if (bearers[i].active)
680 			bearer_disable(bearers[i].publ.name);
681 	}
682 	kfree(bearers);
683 	kfree(media_list);
684 	bearers = 0;
685 	media_list = 0;
686 	media_count = 0;
687 }
688 
689 
690