| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *	BIRD -- UNIX Kernel Synchronization | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2000-01-16 16:44:50 +00:00
										 |  |  |  *	(c) 1998--2000 Martin Mares <mj@ucw.cz> | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  *	Can be freely distributed and used under the terms of the GNU GPL. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-06-05 12:49:04 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * DOC: Kernel synchronization | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This system dependent module implements the Kernel and Device protocol, | 
					
						
							|  |  |  |  * that is synchronization of interface lists and routing tables with the | 
					
						
							|  |  |  |  * OS kernel. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The whole kernel synchronization is a bit messy and touches some internals | 
					
						
							|  |  |  |  * of the routing table engine, because routing table maintenance is a typical | 
					
						
							|  |  |  |  * example of the proverbial compatibility between different Unices and we want | 
					
						
							| 
									
										
										
										
											2000-06-07 12:29:08 +00:00
										 |  |  |  * to keep the overhead of our KRT business as low as possible and avoid maintaining | 
					
						
							| 
									
										
										
										
											2000-06-05 12:49:04 +00:00
										 |  |  |  * a local routing table copy. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The kernel syncer can work in three different modes (according to system config header): | 
					
						
							| 
									
										
										
										
											2000-06-08 12:37:21 +00:00
										 |  |  |  * Either with a single routing table and single KRT protocol [traditional UNIX] | 
					
						
							| 
									
										
										
										
											2000-06-07 12:29:08 +00:00
										 |  |  |  * or with many routing tables and separate KRT protocols for all of them | 
					
						
							| 
									
										
										
										
											2000-06-05 12:49:04 +00:00
										 |  |  |  * or with many routing tables, but every scan including all tables, so we start | 
					
						
							| 
									
										
										
										
											2012-04-30 22:21:52 +02:00
										 |  |  |  * separate KRT protocols which cooperate with each other [Linux]. | 
					
						
							| 
									
										
										
										
											2000-06-05 12:49:04 +00:00
										 |  |  |  * In this case, we keep only a single scan timer. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2000-06-07 13:25:53 +00:00
										 |  |  |  * We use FIB node flags in the routing table to keep track of route | 
					
						
							|  |  |  |  * synchronization status. We also attach temporary &rte's to the routing table, | 
					
						
							|  |  |  |  * but it cannot do any harm to the rest of BIRD since table synchronization is | 
					
						
							|  |  |  |  * an atomic process. | 
					
						
							| 
									
										
										
										
											2000-06-05 12:49:04 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * When starting up, we cheat by looking if there is another | 
					
						
							|  |  |  |  * KRT instance to be initialized later and performing table scan | 
					
						
							| 
									
										
										
										
											2000-06-08 12:37:21 +00:00
										 |  |  |  * only once for all the instances. | 
					
						
							| 
									
										
										
										
											2012-04-30 22:21:52 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * The code uses OS-dependent parts for kernel updates and scans. These parts are | 
					
						
							|  |  |  |  * in more specific sysdep directories (e.g. sysdep/linux) in functions krt_sys_*  | 
					
						
							| 
									
										
										
										
											2012-04-30 22:34:06 +02:00
										 |  |  |  * and kif_sys_* (and some others like krt_replace_rte()) and krt-sys.h header file. | 
					
						
							| 
									
										
										
										
											2012-04-30 22:21:52 +02:00
										 |  |  |  * This is also used for platform specific protocol options and route attributes. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * There was also an old code that used traditional UNIX ioctls for these tasks. | 
					
						
							|  |  |  |  * It was unmaintained and later removed. For reference, see sysdep/krt-* files | 
					
						
							|  |  |  |  * in commit 396dfa9042305f62da1f56589c4b98fac57fc2f6 | 
					
						
							| 
									
										
										
										
											2000-06-08 12:37:21 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2000-06-05 12:49:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  *  If you are brave enough, continue now.  You cannot say you haven't been warned. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-12 21:54:39 +00:00
										 |  |  | #undef LOCAL_DEBUG
 | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "nest/bird.h"
 | 
					
						
							|  |  |  | #include "nest/iface.h"
 | 
					
						
							|  |  |  | #include "nest/route.h"
 | 
					
						
							|  |  |  | #include "nest/protocol.h"
 | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  | #include "filter/filter.h"
 | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | #include "lib/timer.h"
 | 
					
						
							| 
									
										
										
										
											1999-08-03 19:33:22 +00:00
										 |  |  | #include "conf/conf.h"
 | 
					
						
							| 
									
										
										
										
											2002-11-13 08:47:06 +00:00
										 |  |  | #include "lib/string.h"
 | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "unix.h"
 | 
					
						
							|  |  |  | #include "krt.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-26 21:44:38 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *	Global resources | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-08-03 19:33:22 +00:00
										 |  |  | pool *krt_pool; | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  | static linpool *krt_filter_lp; | 
					
						
							| 
									
										
										
										
											2013-06-29 22:55:41 +02:00
										 |  |  | static list krt_proto_list; | 
					
						
							| 
									
										
										
										
											1999-08-03 19:33:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-26 21:44:38 +00:00
										 |  |  | void | 
					
						
							|  |  |  | krt_io_init(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1999-08-03 19:33:22 +00:00
										 |  |  |   krt_pool = rp_new(&root_pool, "Kernel Syncer"); | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  |   krt_filter_lp = lp_new(krt_pool, 4080); | 
					
						
							| 
									
										
										
										
											2013-06-29 22:55:41 +02:00
										 |  |  |   init_list(&krt_proto_list); | 
					
						
							| 
									
										
										
										
											1999-03-26 21:44:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  *	Interfaces | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  | static struct kif_config *kif_cf; | 
					
						
							| 
									
										
										
										
											1999-03-26 21:44:38 +00:00
										 |  |  | static struct kif_proto *kif_proto; | 
					
						
							|  |  |  | static timer *kif_scan_timer; | 
					
						
							|  |  |  | static bird_clock_t kif_last_shot; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | kif_scan(timer *t) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct kif_proto *p = t->data; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-12 21:54:39 +00:00
										 |  |  |   KRT_TRACE(p, D_EVENTS, "Scanning interfaces"); | 
					
						
							| 
									
										
										
										
											1999-03-26 21:44:38 +00:00
										 |  |  |   kif_last_shot = now; | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  |   kif_do_scan(p); | 
					
						
							| 
									
										
										
										
											1999-03-26 21:44:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | kif_force_scan(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (kif_proto && kif_last_shot + 2 < now) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       kif_scan(kif_scan_timer); | 
					
						
							|  |  |  |       tm_start(kif_scan_timer, ((struct kif_config *) kif_proto->p.cf)->scan_time); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-23 03:15:12 +01:00
										 |  |  | void | 
					
						
							|  |  |  | kif_request_scan(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (kif_proto && kif_scan_timer->expires > now) | 
					
						
							|  |  |  |     tm_start(kif_scan_timer, 1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-29 22:49:30 +02:00
										 |  |  | static inline int | 
					
						
							|  |  |  | prefer_addr(struct ifa *a, struct ifa *b) | 
					
						
							| 
									
										
										
										
											2012-08-29 12:42:49 +02:00
										 |  |  | {  | 
					
						
							|  |  |  |   int sa = a->scope > SCOPE_LINK; | 
					
						
							|  |  |  |   int sb = b->scope > SCOPE_LINK; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (sa < sb) | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  |   else if (sa > sb) | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     return ipa_compare(a->ip, b->ip) < 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-05-29 22:49:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | static inline struct ifa * | 
					
						
							|  |  |  | find_preferred_ifa(struct iface *i, ip_addr prefix, ip_addr mask) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct ifa *a, *b = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   WALK_LIST(a, i->addrs) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (!(a->flags & IA_SECONDARY) && | 
					
						
							|  |  |  | 	  ipa_equal(ipa_and(a->ip, mask), prefix) && | 
					
						
							| 
									
										
										
										
											2012-08-29 12:42:49 +02:00
										 |  |  | 	  (!b || prefer_addr(a, b))) | 
					
						
							| 
									
										
										
										
											2009-05-29 22:49:30 +02:00
										 |  |  | 	b = a; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return b; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct ifa * | 
					
						
							|  |  |  | kif_choose_primary(struct iface *i) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct kif_config *cf = (struct kif_config *) (kif_proto->p.cf); | 
					
						
							|  |  |  |   struct kif_primary_item *it; | 
					
						
							|  |  |  |   struct ifa *a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   WALK_LIST(it, cf->primary) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (!it->pattern || patmatch(it->pattern, i->name)) | 
					
						
							|  |  |  | 	if (a = find_preferred_ifa(i, it->prefix, ipa_mkmask(it->pxlen))) | 
					
						
							|  |  |  | 	  return a; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return find_preferred_ifa(i, IPA_NONE, IPA_NONE); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  | static struct proto * | 
					
						
							|  |  |  | kif_init(struct proto_config *c) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct kif_proto *p = proto_new(c, sizeof(struct kif_proto)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   kif_sys_init(p); | 
					
						
							|  |  |  |   return &p->p; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | kif_start(struct proto *P) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct kif_proto *p = (struct kif_proto *) P; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   kif_proto = p; | 
					
						
							|  |  |  |   kif_sys_start(p); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Start periodic interface scanning */ | 
					
						
							|  |  |  |   kif_scan_timer = tm_new(P->pool); | 
					
						
							|  |  |  |   kif_scan_timer->hook = kif_scan; | 
					
						
							|  |  |  |   kif_scan_timer->data = p; | 
					
						
							|  |  |  |   kif_scan_timer->recurrent = KIF_CF->scan_time; | 
					
						
							|  |  |  |   kif_scan(kif_scan_timer); | 
					
						
							|  |  |  |   tm_start(kif_scan_timer, KIF_CF->scan_time); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return PS_UP; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | kif_shutdown(struct proto *P) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct kif_proto *p = (struct kif_proto *) P; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   tm_stop(kif_scan_timer); | 
					
						
							|  |  |  |   kif_sys_shutdown(p); | 
					
						
							|  |  |  |   kif_proto = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return PS_DOWN; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-01-17 11:17:33 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | kif_reconfigure(struct proto *p, struct proto_config *new) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct kif_config *o = (struct kif_config *) p->cf; | 
					
						
							|  |  |  |   struct kif_config *n = (struct kif_config *) new; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  |   if (!kif_sys_reconfigure((struct kif_proto *) p, n, o)) | 
					
						
							| 
									
										
										
										
											2000-01-17 11:17:33 +00:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2009-05-29 22:49:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-01-17 11:17:33 +00:00
										 |  |  |   if (o->scan_time != n->scan_time) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       tm_stop(kif_scan_timer); | 
					
						
							|  |  |  |       kif_scan_timer->recurrent = n->scan_time; | 
					
						
							|  |  |  |       kif_scan(kif_scan_timer); | 
					
						
							|  |  |  |       tm_start(kif_scan_timer, n->scan_time); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-05-29 22:49:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (!EMPTY_LIST(o->primary) || !EMPTY_LIST(n->primary)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       /* This is hack, we have to update a configuration
 | 
					
						
							|  |  |  |        * to the new value just now, because it is used | 
					
						
							|  |  |  |        * for recalculation of primary addresses. | 
					
						
							|  |  |  |        */ | 
					
						
							|  |  |  |       p->cf = new; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       ifa_recalc_all_primary_addresses(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-01-17 11:17:33 +00:00
										 |  |  |   return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | kif_preconfig(struct protocol *P UNUSED, struct config *c) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   kif_cf = NULL; | 
					
						
							|  |  |  |   kif_sys_preconfig(c); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct proto_config * | 
					
						
							|  |  |  | kif_init_config(int class) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (kif_cf) | 
					
						
							|  |  |  |     cf_error("Kernel device protocol already defined"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   kif_cf = (struct kif_config *) proto_config_new(&proto_unix_iface, sizeof(struct kif_config), class); | 
					
						
							|  |  |  |   kif_cf->scan_time = 60; | 
					
						
							|  |  |  |   init_list(&kif_cf->primary); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   kif_sys_init_config(kif_cf); | 
					
						
							|  |  |  |   return (struct proto_config *) kif_cf; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-07 00:31:23 +01:00
										 |  |  | static void | 
					
						
							|  |  |  | kif_copy_config(struct proto_config *dest, struct proto_config *src) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct kif_config *d = (struct kif_config *) dest; | 
					
						
							|  |  |  |   struct kif_config *s = (struct kif_config *) src; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Shallow copy of everything (just scan_time currently) */ | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  |   proto_copy_rest(dest, src, sizeof(struct kif_config)); | 
					
						
							| 
									
										
										
										
											2011-11-07 00:31:23 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Copy primary addr list */ | 
					
						
							|  |  |  |   cfg_copy_list(&d->primary, &s->primary, sizeof(struct kif_primary_item)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Fix sysdep parts */ | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  |   kif_sys_copy_config(d, s); | 
					
						
							| 
									
										
										
										
											2011-11-07 00:31:23 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-26 21:44:38 +00:00
										 |  |  | struct protocol proto_unix_iface = { | 
					
						
							|  |  |  |   name:		"Device", | 
					
						
							| 
									
										
										
										
											2000-01-17 11:52:50 +00:00
										 |  |  |   template:	"device%d", | 
					
						
							| 
									
										
										
										
											2012-01-24 11:31:00 +01:00
										 |  |  |   preference:	DEF_PREF_DIRECT, | 
					
						
							| 
									
										
										
										
											2000-01-16 16:44:50 +00:00
										 |  |  |   preconfig:	kif_preconfig, | 
					
						
							| 
									
										
										
										
											1999-03-26 21:44:38 +00:00
										 |  |  |   init:		kif_init, | 
					
						
							|  |  |  |   start:	kif_start, | 
					
						
							|  |  |  |   shutdown:	kif_shutdown, | 
					
						
							| 
									
										
										
										
											2000-01-17 11:17:33 +00:00
										 |  |  |   reconfigure:	kif_reconfigure, | 
					
						
							| 
									
										
										
										
											2011-11-07 00:31:23 +01:00
										 |  |  |   copy_config:	kif_copy_config | 
					
						
							| 
									
										
										
										
											1999-03-26 21:44:38 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-12 21:54:39 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *	Tracing of routes | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-26 14:23:54 +01:00
										 |  |  | static inline void | 
					
						
							|  |  |  | krt_trace_in(struct krt_proto *p, rte *e, char *msg) | 
					
						
							| 
									
										
										
										
											2000-03-12 21:54:39 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-26 14:23:54 +01:00
										 |  |  |   if (p->p.debug & D_PACKETS) | 
					
						
							|  |  |  |     log(L_TRACE "%s: %I/%d: %s", p->p.name, e->net->n.prefix, e->net->n.pxlen, msg); | 
					
						
							| 
									
										
										
										
											2000-03-12 21:54:39 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void | 
					
						
							| 
									
										
										
										
											2009-02-26 14:23:54 +01:00
										 |  |  | krt_trace_in_rl(struct rate_limit *rl, struct krt_proto *p, rte *e, char *msg) | 
					
						
							| 
									
										
										
										
											2000-03-12 21:54:39 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   if (p->p.debug & D_PACKETS) | 
					
						
							| 
									
										
										
										
											2009-02-26 14:23:54 +01:00
										 |  |  |     log_rl(rl, L_TRACE "%s: %I/%d: %s", p->p.name, e->net->n.prefix, e->net->n.pxlen, msg); | 
					
						
							| 
									
										
										
										
											2000-03-12 21:54:39 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *	Inherited Routes | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef KRT_ALLOW_LEARN
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-26 14:23:54 +01:00
										 |  |  | static struct rate_limit rl_alien_seen, rl_alien_updated, rl_alien_created, rl_alien_ignored; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * krt_same_key() specifies what (aside from the net) is the key in | 
					
						
							|  |  |  |  * kernel routing tables. It should be OS-dependent, this is for | 
					
						
							|  |  |  |  * Linux. It is important for asynchronous alien updates, because a | 
					
						
							|  |  |  |  * positive update is implicitly a negative one for any old route with | 
					
						
							|  |  |  |  * the same key. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | static inline int | 
					
						
							|  |  |  | krt_same_key(rte *a, rte *b) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  |   return a->u.krt.metric == b->u.krt.metric; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline int | 
					
						
							|  |  |  | krt_uptodate(rte *a, rte *b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (a->attrs != b->attrs) | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (a->u.krt.proto != b->u.krt.proto) | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 1; | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | krt_learn_announce_update(struct krt_proto *p, rte *e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   net *n = e->net; | 
					
						
							|  |  |  |   rta *aa = rta_clone(e->attrs); | 
					
						
							|  |  |  |   rte *ee = rte_get_temp(aa); | 
					
						
							| 
									
										
										
										
											1999-04-12 18:01:07 +00:00
										 |  |  |   net *nn = net_get(p->p.table, n->n.prefix, n->n.pxlen); | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  |   ee->net = nn; | 
					
						
							|  |  |  |   ee->pflags = 0; | 
					
						
							| 
									
										
										
										
											2000-05-08 10:38:51 +00:00
										 |  |  |   ee->pref = p->p.preference; | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  |   ee->u.krt = e->u.krt; | 
					
						
							| 
									
										
										
										
											2009-06-01 14:07:13 +02:00
										 |  |  |   rte_update(p->p.table, nn, &p->p, &p->p, ee); | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | krt_learn_announce_delete(struct krt_proto *p, net *n) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1999-04-12 18:01:07 +00:00
										 |  |  |   n = net_find(p->p.table, n->n.prefix, n->n.pxlen); | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  |   if (n) | 
					
						
							| 
									
										
										
										
											2009-06-01 14:07:13 +02:00
										 |  |  |     rte_update(p->p.table, n, &p->p, &p->p, NULL); | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  | /* Called when alien route is discovered during scan */ | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | krt_learn_scan(struct krt_proto *p, rte *e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   net *n0 = e->net; | 
					
						
							| 
									
										
										
										
											1999-04-12 18:01:07 +00:00
										 |  |  |   net *n = net_get(&p->krt_table, n0->n.prefix, n0->n.pxlen); | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  |   rte *m, **mm; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  |   e->attrs = rta_lookup(e->attrs); | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   for(mm=&n->routes; m = *mm; mm=&m->next) | 
					
						
							|  |  |  |     if (krt_same_key(m, e)) | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |   if (m) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (krt_uptodate(m, e)) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-02-26 14:23:54 +01:00
										 |  |  | 	  krt_trace_in_rl(&rl_alien_seen, p, e, "[alien] seen"); | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | 	  rte_free(e); | 
					
						
							|  |  |  | 	  m->u.krt.seen = 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-02-26 14:23:54 +01:00
										 |  |  | 	  krt_trace_in_rl(&rl_alien_updated, p, e, "[alien] updated"); | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | 	  *mm = m->next; | 
					
						
							|  |  |  | 	  rte_free(m); | 
					
						
							|  |  |  | 	  m = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							| 
									
										
										
										
											2009-02-26 14:23:54 +01:00
										 |  |  |     krt_trace_in_rl(&rl_alien_created, p, e, "[alien] created"); | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  |   if (!m) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       e->next = n->routes; | 
					
						
							|  |  |  |       n->routes = e; | 
					
						
							|  |  |  |       e->u.krt.seen = 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | krt_learn_prune(struct krt_proto *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct fib *fib = &p->krt_table.fib; | 
					
						
							|  |  |  |   struct fib_iterator fit; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-12 21:54:39 +00:00
										 |  |  |   KRT_TRACE(p, D_EVENTS, "Pruning inherited routes"); | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   FIB_ITERATE_INIT(&fit, fib); | 
					
						
							|  |  |  | again: | 
					
						
							|  |  |  |   FIB_ITERATE_START(fib, &fit, f) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       net *n = (net *) f; | 
					
						
							|  |  |  |       rte *e, **ee, *best, **pbest, *old_best; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       old_best = n->routes; | 
					
						
							|  |  |  |       best = NULL; | 
					
						
							|  |  |  |       pbest = NULL; | 
					
						
							|  |  |  |       ee = &n->routes; | 
					
						
							|  |  |  |       while (e = *ee) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  if (!e->u.krt.seen) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      *ee = e->next; | 
					
						
							|  |  |  | 	      rte_free(e); | 
					
						
							|  |  |  | 	      continue; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  if (!best || best->u.krt.metric > e->u.krt.metric) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      best = e; | 
					
						
							|  |  |  | 	      pbest = ee; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  e->u.krt.seen = 0; | 
					
						
							|  |  |  | 	  ee = &e->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       if (!n->routes) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  DBG("%I/%d: deleting\n", n->n.prefix, n->n.pxlen); | 
					
						
							|  |  |  | 	  if (old_best) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      krt_learn_announce_delete(p, n); | 
					
						
							|  |  |  | 	      n->n.flags &= ~KRF_INSTALLED; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  FIB_ITERATE_PUT(&fit, f); | 
					
						
							|  |  |  | 	  fib_delete(fib, f); | 
					
						
							|  |  |  | 	  goto again; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       *pbest = best->next; | 
					
						
							|  |  |  |       best->next = n->routes; | 
					
						
							|  |  |  |       n->routes = best; | 
					
						
							|  |  |  |       if (best != old_best || !(n->n.flags & KRF_INSTALLED)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  DBG("%I/%d: announcing (metric=%d)\n", n->n.prefix, n->n.pxlen, best->u.krt.metric); | 
					
						
							|  |  |  | 	  krt_learn_announce_update(p, best); | 
					
						
							|  |  |  | 	  n->n.flags |= KRF_INSTALLED; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	DBG("%I/%d: uptodate (metric=%d)\n", n->n.prefix, n->n.pxlen, best->u.krt.metric); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   FIB_ITERATE_END(f); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | krt_learn_async(struct krt_proto *p, rte *e, int new) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   net *n0 = e->net; | 
					
						
							| 
									
										
										
										
											1999-04-12 18:01:07 +00:00
										 |  |  |   net *n = net_get(&p->krt_table, n0->n.prefix, n0->n.pxlen); | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  |   rte *g, **gg, *best, **bestp, *old_best; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  |   e->attrs = rta_lookup(e->attrs); | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   old_best = n->routes; | 
					
						
							|  |  |  |   for(gg=&n->routes; g = *gg; gg = &g->next) | 
					
						
							|  |  |  |     if (krt_same_key(g, e)) | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |   if (new) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (g) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  if (krt_uptodate(g, e)) | 
					
						
							|  |  |  | 	    { | 
					
						
							| 
									
										
										
										
											2000-03-12 21:54:39 +00:00
										 |  |  | 	      krt_trace_in(p, e, "[alien async] same"); | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | 	      rte_free(e); | 
					
						
							|  |  |  | 	      return; | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2000-03-12 21:54:39 +00:00
										 |  |  | 	  krt_trace_in(p, e, "[alien async] updated"); | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | 	  *gg = g->next; | 
					
						
							|  |  |  | 	  rte_free(g); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							| 
									
										
										
										
											2000-03-12 21:54:39 +00:00
										 |  |  | 	krt_trace_in(p, e, "[alien async] created"); | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  |       e->next = n->routes; | 
					
						
							|  |  |  |       n->routes = e; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else if (!g) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2000-03-12 21:54:39 +00:00
										 |  |  |       krt_trace_in(p, e, "[alien async] delete failed"); | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  |       rte_free(e); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2000-03-12 21:54:39 +00:00
										 |  |  |       krt_trace_in(p, e, "[alien async] removed"); | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  |       *gg = g->next; | 
					
						
							|  |  |  |       rte_free(e); | 
					
						
							|  |  |  |       rte_free(g); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   best = n->routes; | 
					
						
							|  |  |  |   bestp = &n->routes; | 
					
						
							|  |  |  |   for(gg=&n->routes; g=*gg; gg=&g->next) | 
					
						
							|  |  |  |     if (best->u.krt.metric > g->u.krt.metric) | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  | 	best = g; | 
					
						
							|  |  |  | 	bestp = gg; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |   if (best) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       *bestp = best->next; | 
					
						
							|  |  |  |       best->next = n->routes; | 
					
						
							|  |  |  |       n->routes = best; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   if (best != old_best) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       DBG("krt_learn_async: distributing change\n"); | 
					
						
							|  |  |  |       if (best) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  krt_learn_announce_update(p, best); | 
					
						
							|  |  |  | 	  n->n.flags |= KRF_INSTALLED; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  n->routes = NULL; | 
					
						
							|  |  |  | 	  krt_learn_announce_delete(p, n); | 
					
						
							|  |  |  | 	  n->n.flags &= ~KRF_INSTALLED; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | krt_learn_init(struct krt_proto *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (KRT_CF->learn) | 
					
						
							| 
									
										
										
										
											2000-03-04 22:21:06 +00:00
										 |  |  |     rt_setup(p->p.pool, &p->krt_table, "Inherited", NULL); | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | krt_dump(struct proto *P) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct krt_proto *p = (struct krt_proto *) P; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!KRT_CF->learn) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   debug("KRT: Table of inheritable routes\n"); | 
					
						
							|  |  |  |   rt_dump(&p->krt_table); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | krt_dump_attrs(rte *e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   debug(" [m=%d,p=%d,t=%d]", e->u.krt.metric, e->u.krt.proto, e->u.krt.type); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *	Routes | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | krt_flush_routes(struct krt_proto *p) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1999-05-17 20:16:53 +00:00
										 |  |  |   struct rtable *t = p->p.table; | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-12 21:54:39 +00:00
										 |  |  |   KRT_TRACE(p, D_EVENTS, "Flushing kernel routes"); | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  |   FIB_WALK(&t->fib, f) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       net *n = (net *) f; | 
					
						
							|  |  |  |       rte *e = n->routes; | 
					
						
							| 
									
										
										
										
											2012-11-10 14:26:13 +01:00
										 |  |  |       if (rte_is_valid(e) && (n->n.flags & KRF_INSTALLED)) | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2012-05-03 14:04:56 +02:00
										 |  |  | 	  /* FIXME: this does not work if gw is changed in export filter */ | 
					
						
							|  |  |  | 	  krt_replace_rte(p, e->net, NULL, e, NULL); | 
					
						
							|  |  |  | 	  n->n.flags &= ~KRF_INSTALLED; | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   FIB_WALK_END; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  | krt_same_dest(rte *k, rte *e) | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   rta *ka = k->attrs, *ea = e->attrs; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (ka->dest != ea->dest) | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  |   switch (ka->dest) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     case RTD_ROUTER: | 
					
						
							|  |  |  |       return ipa_equal(ka->gw, ea->gw); | 
					
						
							|  |  |  |     case RTD_DEVICE: | 
					
						
							|  |  |  |       return !strcmp(ka->iface->name, ea->iface->name); | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  |     case RTD_MULTIPATH: | 
					
						
							|  |  |  |       return mpnh_same(ka->nexthops, ea->nexthops); | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  |     default: | 
					
						
							|  |  |  |       return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  *  This gets called back when the low-level scanning code discovers a route. | 
					
						
							|  |  |  |  *  We expect that the route is a temporary rte and its attributes are uncached. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | krt_got_route(struct krt_proto *p, rte *e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   rte *old; | 
					
						
							|  |  |  |   net *net = e->net; | 
					
						
							|  |  |  |   int verdict; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-26 10:55:58 +01:00
										 |  |  | #ifdef KRT_ALLOW_LEARN
 | 
					
						
							|  |  |  |   switch (e->u.krt.src) | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2010-02-26 10:55:58 +01:00
										 |  |  |     case KRT_SRC_KERNEL: | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  |       verdict = KRF_IGNORE; | 
					
						
							|  |  |  |       goto sentenced; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-26 10:55:58 +01:00
										 |  |  |     case KRT_SRC_REDIRECT: | 
					
						
							|  |  |  |       verdict = KRF_DELETE; | 
					
						
							|  |  |  |       goto sentenced; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case  KRT_SRC_ALIEN: | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  |       if (KRT_CF->learn) | 
					
						
							|  |  |  | 	krt_learn_scan(p, e); | 
					
						
							|  |  |  |       else | 
					
						
							| 
									
										
										
										
											2003-08-13 22:07:55 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-02-26 10:55:58 +01:00
										 |  |  | 	  krt_trace_in_rl(&rl_alien_ignored, p, e, "[alien] ignored"); | 
					
						
							| 
									
										
										
										
											2003-08-13 22:07:55 +00:00
										 |  |  | 	  rte_free(e); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-02-26 10:55:58 +01:00
										 |  |  |   /* The rest is for KRT_SRC_BIRD (or KRT_SRC_UNKNOWN) */ | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (net->n.flags & KRF_VERDICT_MASK) | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       /* Route to this destination was already seen. Strange, but it happens... */ | 
					
						
							| 
									
										
										
										
											2000-03-12 21:54:39 +00:00
										 |  |  |       krt_trace_in(p, e, "already seen"); | 
					
						
							| 
									
										
										
										
											2003-08-13 22:07:55 +00:00
										 |  |  |       rte_free(e); | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-03 11:50:51 +01:00
										 |  |  |   old = net->routes; | 
					
						
							| 
									
										
										
										
											2012-11-10 14:26:13 +01:00
										 |  |  |   if ((net->n.flags & KRF_INSTALLED) && rte_is_valid(old)) | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  |       /* There may be changes in route attributes, we ignore that.
 | 
					
						
							|  |  |  |          Also, this does not work well if gw is changed in export filter */ | 
					
						
							|  |  |  |       if ((net->n.flags & KRF_SYNC_ERROR) || ! krt_same_dest(e, old)) | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 	verdict = KRF_UPDATE; | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  |       else | 
					
						
							|  |  |  | 	verdict = KRF_SEEN; | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     verdict = KRF_DELETE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-26 10:55:58 +01:00
										 |  |  |  sentenced: | 
					
						
							| 
									
										
										
										
											2000-03-12 21:54:39 +00:00
										 |  |  |   krt_trace_in(p, e, ((char *[]) { "?", "seen", "will be updated", "will be removed", "ignored" }) [verdict]); | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  |   net->n.flags = (net->n.flags & ~KRF_VERDICT_MASK) | verdict; | 
					
						
							|  |  |  |   if (verdict == KRF_UPDATE || verdict == KRF_DELETE) | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  |       /* Get a cached copy of attributes and temporarily link the route */ | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  |       rta *a = e->attrs; | 
					
						
							|  |  |  |       a->source = RTS_DUMMY; | 
					
						
							|  |  |  |       e->attrs = rta_lookup(a); | 
					
						
							|  |  |  |       e->next = net->routes; | 
					
						
							|  |  |  |       net->routes = e; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     rte_free(e); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  | static inline int | 
					
						
							|  |  |  | krt_export_rte(struct krt_proto *p, rte **new, ea_list **tmpa) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-30 11:04:12 +02:00
										 |  |  |   struct filter *filter = p->p.main_ahook->out_filter; | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (! *new) | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (filter == FILTER_REJECT) | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (filter == FILTER_ACCEPT) | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   struct proto *src = (*new)->attrs->proto; | 
					
						
							|  |  |  |   *tmpa = src->make_tmp_attrs ? src->make_tmp_attrs(*new, krt_filter_lp) : NULL; | 
					
						
							|  |  |  |   return f_run(filter, new, tmpa, krt_filter_lp, FF_FORCE_TMPATTR) <= F_ACCEPT; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | krt_prune(struct krt_proto *p) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1999-05-17 20:16:53 +00:00
										 |  |  |   struct rtable *t = p->p.table; | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-12 21:54:39 +00:00
										 |  |  |   KRT_TRACE(p, D_EVENTS, "Pruning table %s", t->name); | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  |   FIB_WALK(&t->fib, f) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       net *n = (net *) f; | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  |       int verdict = f->flags & KRF_VERDICT_MASK; | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  |       rte *new, *new0, *old; | 
					
						
							|  |  |  |       ea_list *tmpa = NULL; | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  |       if (verdict == KRF_UPDATE || verdict == KRF_DELETE) | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  | 	  /* Get a dummy route from krt_got_route() */ | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 	  old = n->routes; | 
					
						
							|  |  |  | 	  n->routes = old->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	old = NULL; | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       new = new0 = n->routes; | 
					
						
							|  |  |  |       if (verdict == KRF_CREATE || verdict == KRF_UPDATE) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  /* We have to run export filter to get proper 'new' route */ | 
					
						
							|  |  |  | 	  if (! krt_export_rte(p, &new, &tmpa)) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      /* Route rejected, should not happen (KRF_INSTALLED) but to be sure .. */ | 
					
						
							|  |  |  | 	      verdict = (verdict == KRF_CREATE) ? KRF_IGNORE : KRF_DELETE;  | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       switch (verdict) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	case KRF_CREATE: | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | 	  if (new && (f->flags & KRF_INSTALLED)) | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 	    { | 
					
						
							| 
									
										
										
										
											2000-03-12 21:54:39 +00:00
										 |  |  | 	      krt_trace_in(p, new, "reinstalling"); | 
					
						
							| 
									
										
										
										
											2012-04-30 22:34:06 +02:00
										 |  |  | 	      krt_replace_rte(p, n, new, NULL, tmpa); | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 	    } | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	case KRF_SEEN: | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | 	case KRF_IGNORE: | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 	  /* Nothing happens */ | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	case KRF_UPDATE: | 
					
						
							| 
									
										
										
										
											2000-03-12 21:54:39 +00:00
										 |  |  | 	  krt_trace_in(p, new, "updating"); | 
					
						
							| 
									
										
										
										
											2012-04-30 22:34:06 +02:00
										 |  |  | 	  krt_replace_rte(p, n, new, old, tmpa); | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 	  break; | 
					
						
							|  |  |  | 	case KRF_DELETE: | 
					
						
							| 
									
										
										
										
											2000-05-08 10:38:51 +00:00
										 |  |  | 	  krt_trace_in(p, old, "deleting"); | 
					
						
							| 
									
										
										
										
											2012-04-30 22:34:06 +02:00
										 |  |  | 	  krt_replace_rte(p, n, NULL, old, NULL); | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 	  break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 	  bug("krt_prune: invalid route status"); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  |       if (old) | 
					
						
							|  |  |  | 	rte_free(old); | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  |       if (new != new0) | 
					
						
							|  |  |  | 	rte_free(new); | 
					
						
							|  |  |  |       lp_flush(krt_filter_lp); | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  |       f->flags &= ~KRF_VERDICT_MASK; | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   FIB_WALK_END; | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef KRT_ALLOW_LEARN
 | 
					
						
							|  |  |  |   if (KRT_CF->learn) | 
					
						
							|  |  |  |     krt_learn_prune(p); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2000-01-18 10:39:30 +00:00
										 |  |  |   p->initialized = 1; | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-04 18:36:18 +00:00
										 |  |  | void | 
					
						
							| 
									
										
										
										
											2010-02-26 10:55:58 +01:00
										 |  |  | krt_got_route_async(struct krt_proto *p, rte *e, int new) | 
					
						
							| 
									
										
										
										
											1999-03-04 18:36:18 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   net *net = e->net; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-26 10:55:58 +01:00
										 |  |  |   switch (e->u.krt.src) | 
					
						
							| 
									
										
										
										
											1999-03-04 18:36:18 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |     case KRT_SRC_BIRD: | 
					
						
							| 
									
										
										
										
											2000-03-12 21:54:39 +00:00
										 |  |  |       ASSERT(0);			/* Should be filtered by the back end */ | 
					
						
							| 
									
										
										
										
											2010-02-26 10:55:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-04 18:36:18 +00:00
										 |  |  |     case KRT_SRC_REDIRECT: | 
					
						
							| 
									
										
										
										
											2010-02-26 10:55:58 +01:00
										 |  |  |       if (new) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  krt_trace_in(p, e, "[redirect] deleting"); | 
					
						
							| 
									
										
										
										
											2012-04-30 22:34:06 +02:00
										 |  |  | 	  krt_replace_rte(p, net, NULL, e, NULL); | 
					
						
							| 
									
										
										
										
											2010-02-26 10:55:58 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  |       /* If !new, it is probably echo of our deletion */ | 
					
						
							| 
									
										
										
										
											1999-03-04 18:36:18 +00:00
										 |  |  |       break; | 
					
						
							| 
									
										
										
										
											2010-02-26 10:55:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | #ifdef KRT_ALLOW_LEARN
 | 
					
						
							| 
									
										
										
										
											2009-05-04 17:49:56 +02:00
										 |  |  |     case KRT_SRC_ALIEN: | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  |       if (KRT_CF->learn) | 
					
						
							| 
									
										
										
										
											1999-03-04 18:36:18 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | 	  krt_learn_async(p, e, new); | 
					
						
							|  |  |  | 	  return; | 
					
						
							| 
									
										
										
										
											1999-03-04 18:36:18 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1999-03-04 18:36:18 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  |   rte_free(e); | 
					
						
							| 
									
										
										
										
											1999-03-04 18:36:18 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *	Periodic scanning | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-29 22:55:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_ALL_TABLES_AT_ONCE
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static timer *krt_scan_timer; | 
					
						
							|  |  |  | static int krt_scan_count; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | static void | 
					
						
							| 
									
										
										
										
											2004-06-05 09:11:07 +00:00
										 |  |  | krt_scan(timer *t UNUSED) | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											1999-08-03 19:33:22 +00:00
										 |  |  |   struct krt_proto *p; | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-26 21:44:38 +00:00
										 |  |  |   kif_force_scan(); | 
					
						
							| 
									
										
										
										
											2013-06-29 22:55:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* We need some node to decide whether to print the debug messages or not */ | 
					
						
							|  |  |  |   p = SKIP_BACK(struct krt_proto, krt_node, HEAD(krt_proto_list)); | 
					
						
							|  |  |  |   KRT_TRACE(p, D_EVENTS, "Scanning routing table"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   krt_do_scan(NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void *q; | 
					
						
							|  |  |  |   WALK_LIST(q, krt_proto_list) | 
					
						
							| 
									
										
										
										
											1999-08-03 19:33:22 +00:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2013-06-29 22:55:41 +02:00
										 |  |  |     p = SKIP_BACK(struct krt_proto, krt_node, q); | 
					
						
							|  |  |  |     krt_prune(p); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | krt_scan_timer_start(struct krt_proto *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (!krt_scan_count) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     krt_scan_timer = tm_new_set(krt_pool, krt_scan, NULL, 0, KRT_CF->scan_time); | 
					
						
							|  |  |  |     tm_start(krt_scan_timer, 0); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   krt_scan_count++; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | krt_scan_timer_stop(struct krt_proto *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   krt_scan_count--; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!krt_scan_count) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     rfree(krt_scan_timer); | 
					
						
							|  |  |  |     krt_scan_timer = NULL; | 
					
						
							| 
									
										
										
										
											1999-08-03 19:33:22 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-06-29 22:55:41 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-08-03 19:33:22 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2013-06-29 22:55:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | krt_scan(timer *t) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct krt_proto *p = t->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   kif_force_scan(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-12 21:54:39 +00:00
										 |  |  |   KRT_TRACE(p, D_EVENTS, "Scanning routing table"); | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  |   krt_do_scan(p); | 
					
						
							| 
									
										
										
										
											1999-03-26 21:44:38 +00:00
										 |  |  |   krt_prune(p); | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-29 22:55:41 +02:00
										 |  |  | static void | 
					
						
							|  |  |  | krt_scan_timer_start(struct krt_proto *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   p->scan_timer = tm_new_set(p->p.pool, krt_scan, p, 0, KRT_CF->scan_time); | 
					
						
							|  |  |  |   tm_start(p->scan_timer, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | krt_scan_timer_stop(struct krt_proto *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   tm_stop(p->scan_timer); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *	Updates | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | static struct ea_list * | 
					
						
							|  |  |  | krt_make_tmp_attrs(rte *rt, struct linpool *pool) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct ea_list *l = lp_alloc(pool, sizeof(struct ea_list) + 2 * sizeof(eattr)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   l->next = NULL; | 
					
						
							|  |  |  |   l->flags = EALF_SORTED; | 
					
						
							|  |  |  |   l->count = 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   l->attrs[0].id = EA_KRT_SOURCE; | 
					
						
							|  |  |  |   l->attrs[0].flags = 0; | 
					
						
							|  |  |  |   l->attrs[0].type = EAF_TYPE_INT | EAF_TEMP; | 
					
						
							|  |  |  |   l->attrs[0].u.data = rt->u.krt.proto; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   l->attrs[1].id = EA_KRT_METRIC; | 
					
						
							|  |  |  |   l->attrs[1].flags = 0; | 
					
						
							|  |  |  |   l->attrs[1].type = EAF_TYPE_INT | EAF_TEMP; | 
					
						
							|  |  |  |   l->attrs[1].u.data = rt->u.krt.metric; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return l; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | krt_store_tmp_attrs(rte *rt, struct ea_list *attrs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* EA_KRT_SOURCE is read-only */ | 
					
						
							|  |  |  |   rt->u.krt.metric = ea_get_int(attrs, EA_KRT_METRIC, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-04 15:41:31 +02:00
										 |  |  | static int | 
					
						
							|  |  |  | krt_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *pool) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct krt_proto *p = (struct krt_proto *) P; | 
					
						
							|  |  |  |   rte *e = *new; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (e->attrs->proto == P) | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!KRT_CF->devroutes &&  | 
					
						
							|  |  |  |       (e->attrs->dest == RTD_DEVICE) &&  | 
					
						
							|  |  |  |       (e->attrs->source != RTS_STATIC_DEVICE)) | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!krt_capable(e)) | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2010-02-13 12:26:26 +01:00
										 |  |  | krt_notify(struct proto *P, struct rtable *table UNUSED, net *net, | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  | 	   rte *new, rte *old, struct ea_list *eattrs) | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   struct krt_proto *p = (struct krt_proto *) P; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-26 12:40:48 +01:00
										 |  |  |   if (config->shutdown) | 
					
						
							| 
									
										
										
										
											2000-05-16 13:36:38 +00:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  |   if (!(net->n.flags & KRF_INSTALLED)) | 
					
						
							|  |  |  |     old = NULL; | 
					
						
							|  |  |  |   if (new) | 
					
						
							|  |  |  |     net->n.flags |= KRF_INSTALLED; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     net->n.flags &= ~KRF_INSTALLED; | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  |   if (p->initialized)		/* Before first scan we don't touch the routes */ | 
					
						
							| 
									
										
										
										
											2012-04-30 22:34:06 +02:00
										 |  |  |     krt_replace_rte(p, net, new, old, eattrs); | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  | static int | 
					
						
							|  |  |  | krt_rte_same(rte *a, rte *b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* src is always KRT_SRC_ALIEN and type is irrelevant */ | 
					
						
							|  |  |  |   return (a->u.krt.proto == b->u.krt.proto) && (a->u.krt.metric == b->u.krt.metric); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *	Protocol glue | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  | struct krt_config *krt_cf; | 
					
						
							| 
									
										
										
										
											1999-03-26 21:44:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  | static struct proto * | 
					
						
							|  |  |  | krt_init(struct proto_config *c) | 
					
						
							| 
									
										
										
										
											1999-08-03 19:33:22 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  |   struct krt_proto *p = proto_new(c, sizeof(struct krt_proto)); | 
					
						
							| 
									
										
										
										
											1999-08-03 19:33:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  |   p->p.accept_ra_types = RA_OPTIMAL; | 
					
						
							|  |  |  |   p->p.make_tmp_attrs = krt_make_tmp_attrs; | 
					
						
							|  |  |  |   p->p.store_tmp_attrs = krt_store_tmp_attrs; | 
					
						
							|  |  |  |   p->p.import_control = krt_import_control; | 
					
						
							|  |  |  |   p->p.rt_notify = krt_notify; | 
					
						
							|  |  |  |   p->p.rte_same = krt_rte_same; | 
					
						
							| 
									
										
										
										
											1999-08-03 19:33:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  |   krt_sys_init(p); | 
					
						
							|  |  |  |   return &p->p; | 
					
						
							| 
									
										
										
										
											1999-08-03 19:33:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | krt_start(struct proto *P) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct krt_proto *p = (struct krt_proto *) P; | 
					
						
							| 
									
										
										
										
											1999-08-03 19:33:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-29 22:55:41 +02:00
										 |  |  |   add_tail(&krt_proto_list, &p->krt_node); | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | #ifdef KRT_ALLOW_LEARN
 | 
					
						
							|  |  |  |   krt_learn_init(p); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-29 22:55:41 +02:00
										 |  |  |   krt_sys_start(p); | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-29 22:55:41 +02:00
										 |  |  |   krt_scan_timer_start(p); | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return PS_UP; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-08-03 19:33:22 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | krt_shutdown(struct proto *P) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct krt_proto *p = (struct krt_proto *) P; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-29 22:55:41 +02:00
										 |  |  |   krt_scan_timer_stop(p); | 
					
						
							| 
									
										
										
										
											1999-03-26 21:44:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-20 12:58:21 +01:00
										 |  |  |   /* FIXME we should flush routes even when persist during reconfiguration */ | 
					
						
							|  |  |  |   if (p->initialized && !KRT_CF->persist) | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  |     krt_flush_routes(p); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-29 22:55:41 +02:00
										 |  |  |   krt_sys_shutdown(p); | 
					
						
							| 
									
										
										
										
											1999-08-03 19:33:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-29 22:55:41 +02:00
										 |  |  |   rem_node(&p->krt_node); | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return PS_DOWN; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  | static int | 
					
						
							|  |  |  | krt_reconfigure(struct proto *p, struct proto_config *new) | 
					
						
							| 
									
										
										
										
											2012-03-23 00:26:26 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  |   struct krt_config *o = (struct krt_config *) p->cf; | 
					
						
							|  |  |  |   struct krt_config *n = (struct krt_config *) new; | 
					
						
							| 
									
										
										
										
											2012-03-23 00:26:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  |   if (!krt_sys_reconfigure((struct krt_proto *) p, n, o)) | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2012-03-23 01:17:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  |   /* persist needn't be the same */ | 
					
						
							|  |  |  |   return o->scan_time == n->scan_time && o->learn == n->learn && o->devroutes == n->devroutes; | 
					
						
							| 
									
										
										
										
											2012-03-23 00:26:26 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-23 01:17:02 +01:00
										 |  |  | static void | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  | krt_preconfig(struct protocol *P UNUSED, struct config *c) | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  |   krt_cf = NULL; | 
					
						
							|  |  |  |   krt_sys_preconfig(c); | 
					
						
							| 
									
										
										
										
											2012-03-25 19:44:14 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2012-03-23 01:17:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  | static void | 
					
						
							|  |  |  | krt_postconfig(struct proto_config *C) | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  |   struct krt_config *c = (struct krt_config *) C; | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  | #ifdef CONFIG_ALL_TABLES_AT_ONCE
 | 
					
						
							|  |  |  |   if (krt_cf->scan_time != c->scan_time) | 
					
						
							|  |  |  |     cf_error("All kernel syncers must use the same table scan interval"); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-04-13 12:32:27 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  |   if (C->table->krt_attached) | 
					
						
							|  |  |  |     cf_error("Kernel syncer (%s) already attached to table %s", C->table->krt_attached->name, C->table->name); | 
					
						
							|  |  |  |   C->table->krt_attached = C; | 
					
						
							|  |  |  |   krt_sys_postconfig(c); | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  | struct proto_config * | 
					
						
							|  |  |  | krt_init_config(int class) | 
					
						
							| 
									
										
										
										
											2000-01-18 10:39:30 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  | #ifndef CONFIG_MULTIPLE_TABLES
 | 
					
						
							|  |  |  |   if (krt_cf) | 
					
						
							|  |  |  |     cf_error("Kernel protocol already defined"); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   krt_cf = (struct krt_config *) proto_config_new(&proto_unix_kernel, sizeof(struct krt_config), class); | 
					
						
							|  |  |  |   krt_cf->scan_time = 60; | 
					
						
							| 
									
										
										
										
											2000-01-18 10:39:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  |   krt_sys_init_config(krt_cf); | 
					
						
							|  |  |  |   return (struct proto_config *) krt_cf; | 
					
						
							| 
									
										
										
										
											2000-01-18 10:39:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-07 00:31:23 +01:00
										 |  |  | static void | 
					
						
							|  |  |  | krt_copy_config(struct proto_config *dest, struct proto_config *src) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct krt_config *d = (struct krt_config *) dest; | 
					
						
							|  |  |  |   struct krt_config *s = (struct krt_config *) src; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Shallow copy of everything */ | 
					
						
							|  |  |  |   proto_copy_rest(dest, src, sizeof(struct krt_config)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Fix sysdep parts */ | 
					
						
							| 
									
										
										
										
											2012-04-30 15:31:32 +02:00
										 |  |  |   krt_sys_copy_config(d, s); | 
					
						
							| 
									
										
										
										
											2011-11-07 00:31:23 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2011-04-13 12:32:27 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | krt_get_attr(eattr * a, byte * buf, int buflen UNUSED) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   switch (a->id) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2012-03-23 00:26:26 +01:00
										 |  |  |   case EA_KRT_SOURCE: | 
					
						
							|  |  |  |     bsprintf(buf, "source"); | 
					
						
							|  |  |  |     return GA_NAME; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-23 01:17:02 +01:00
										 |  |  |   case EA_KRT_METRIC: | 
					
						
							|  |  |  |     bsprintf(buf, "metric"); | 
					
						
							|  |  |  |     return GA_NAME; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-13 12:32:27 +02:00
										 |  |  |   case EA_KRT_PREFSRC: | 
					
						
							|  |  |  |     bsprintf(buf, "prefsrc"); | 
					
						
							|  |  |  |     return GA_NAME; | 
					
						
							| 
									
										
										
										
											2012-03-23 00:26:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-13 12:32:27 +02:00
										 |  |  |   case EA_KRT_REALM: | 
					
						
							|  |  |  |     bsprintf(buf, "realm"); | 
					
						
							|  |  |  |     return GA_NAME; | 
					
						
							| 
									
										
										
										
											2012-03-23 00:26:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-13 12:32:27 +02:00
										 |  |  |   default: | 
					
						
							|  |  |  |     return GA_UNKNOWN; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | struct protocol proto_unix_kernel = { | 
					
						
							|  |  |  |   name:		"Kernel", | 
					
						
							| 
									
										
										
										
											2000-01-17 11:52:50 +00:00
										 |  |  |   template:	"kernel%d", | 
					
						
							| 
									
										
										
										
											2011-04-13 12:32:27 +02:00
										 |  |  |   attr_class:	EAP_KRT, | 
					
						
							| 
									
										
										
										
											2012-01-24 11:31:00 +01:00
										 |  |  |   preference:	DEF_PREF_INHERITED, | 
					
						
							| 
									
										
										
										
											1999-08-03 19:33:22 +00:00
										 |  |  |   preconfig:	krt_preconfig, | 
					
						
							|  |  |  |   postconfig:	krt_postconfig, | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  |   init:		krt_init, | 
					
						
							|  |  |  |   start:	krt_start, | 
					
						
							|  |  |  |   shutdown:	krt_shutdown, | 
					
						
							| 
									
										
										
										
											2000-01-18 10:39:30 +00:00
										 |  |  |   reconfigure:	krt_reconfigure, | 
					
						
							| 
									
										
										
										
											2011-11-07 00:31:23 +01:00
										 |  |  |   copy_config:	krt_copy_config, | 
					
						
							| 
									
										
										
										
											2011-04-13 12:32:27 +02:00
										 |  |  |   get_attr:	krt_get_attr, | 
					
						
							| 
									
										
										
										
											1999-04-03 13:05:18 +00:00
										 |  |  | #ifdef KRT_ALLOW_LEARN
 | 
					
						
							|  |  |  |   dump:		krt_dump, | 
					
						
							|  |  |  |   dump_attrs:	krt_dump_attrs, | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1999-03-03 19:49:56 +00:00
										 |  |  | }; |