diff --git a/doc/bird.sgml b/doc/bird.sgml index 4024f137..5f478066 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -1653,6 +1653,12 @@ are translated to appropriate system (and OS-specific) route attributes. We support these attributes: + int The source of the imported + kernel route. The value is system-dependent. On Linux, it is + a value of the protocol field of the route. See + /etc/iproute2/rt_protos for common values. On BSD, it is + based on STATIC and PROTOx flags. The attribute is read-only. + ip (Linux) The preferred source address. Used in source address selection for outgoing packets. Have to be one of IP addresses of the router. diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index 4ee5495f..eb92d908 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -255,10 +255,11 @@ krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan) ip_addr idst, igate, imask; void *body = (char *)msg->buf; int new = (msg->rtm.rtm_type == RTM_ADD); - int src; char *errmsg = "KRT: Invalid route received"; int flags = msg->rtm.rtm_flags; int addrs = msg->rtm.rtm_addrs; + int src; + byte src2; if (!(flags & RTF_UP) && scan) SKIP("not up in scan\n"); @@ -302,12 +303,17 @@ krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan) u32 self_mask = RTF_PROTO1; u32 alien_mask = RTF_STATIC | RTF_PROTO1 | RTF_GATEWAY; + src2 = (flags & RTF_STATIC) ? 1 : 0; + src2 |= (flags & RTF_PROTO1) ? 2 : 0; + #ifdef RTF_PROTO2 alien_mask |= RTF_PROTO2; + src2 |= (flags & RTF_PROTO2) ? 4 : 0; #endif #ifdef RTF_PROTO3 alien_mask |= RTF_PROTO3; + src2 |= (flags & RTF_PROTO3) ? 8 : 0; #endif #ifdef RTF_REJECT @@ -397,9 +403,9 @@ krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan) e = rte_get_temp(&a); e->net = net; e->u.krt.src = src; + e->u.krt.proto = src2; /* These are probably too Linux-specific */ - e->u.krt.proto = 0; e->u.krt.type = 0; e->u.krt.metric = 0; diff --git a/sysdep/unix/krt.Y b/sysdep/unix/krt.Y index 18e1e52d..2c45c5fe 100644 --- a/sysdep/unix/krt.Y +++ b/sysdep/unix/krt.Y @@ -17,7 +17,7 @@ CF_DEFINES CF_DECLS -CF_KEYWORDS(KERNEL, PERSIST, SCAN, TIME, LEARN, DEVICE, ROUTES) +CF_KEYWORDS(KERNEL, PERSIST, SCAN, TIME, LEARN, DEVICE, ROUTES, KRT_SOURCE) CF_GRAMMAR @@ -90,6 +90,8 @@ kif_item: } ; +CF_ADDTO(dynamic_attr, KRT_SOURCE { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_SOURCE); }) + CF_CODE CF_END diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index 0fb8c4f9..de1188a1 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -907,12 +907,29 @@ krt_shutdown(struct proto *P) return PS_DOWN; } +struct ea_list * +krt_make_tmp_attrs(struct rte *rt, struct linpool *pool) +{ + struct ea_list *l = lp_alloc(pool, sizeof(struct ea_list) + 1 * sizeof(eattr)); + + l->next = NULL; + l->flags = EALF_SORTED; + l->count = 1; + 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; + + return l; +} + static struct proto * krt_init(struct proto_config *c) { struct krt_proto *p = proto_new(c, sizeof(struct krt_proto)); p->p.accept_ra_types = RA_OPTIMAL; + p->p.make_tmp_attrs = krt_make_tmp_attrs; p->p.import_control = krt_import_control; p->p.rt_notify = krt_notify; @@ -952,12 +969,18 @@ krt_get_attr(eattr * a, byte * buf, int buflen UNUSED) { switch (a->id) { + case EA_KRT_SOURCE: + bsprintf(buf, "source"); + return GA_NAME; + case EA_KRT_PREFSRC: bsprintf(buf, "prefsrc"); return GA_NAME; + case EA_KRT_REALM: bsprintf(buf, "realm"); return GA_NAME; + default: return GA_UNKNOWN; } diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h index b0c4dc5e..aa1eccaa 100644 --- a/sysdep/unix/krt.h +++ b/sysdep/unix/krt.h @@ -28,8 +28,9 @@ struct kif_proto; #define KRF_DELETE 3 /* Should be deleted */ #define KRF_IGNORE 4 /* To be ignored */ -#define EA_KRT_PREFSRC EA_CODE(EAP_KRT, 0) -#define EA_KRT_REALM EA_CODE(EAP_KRT, 1) +#define EA_KRT_SOURCE EA_CODE(EAP_KRT, 0) +#define EA_KRT_PREFSRC EA_CODE(EAP_KRT, 1) +#define EA_KRT_REALM EA_CODE(EAP_KRT, 2) /* Whenever we recognize our own routes, we allow learing of foreign routes */ diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c index a4e80154..9219da9b 100644 --- a/sysdep/unix/main.c +++ b/sysdep/unix/main.c @@ -191,7 +191,7 @@ sysdep_preconfig(struct config *c) init_list(&c->logfiles); #ifdef PATH_IPROUTE_DIR - // read_iproute_table(PATH_IPROUTE_DIR "/rt_protos", "ipp_", 256); + read_iproute_table(PATH_IPROUTE_DIR "/rt_protos", "ipp_", 256); read_iproute_table(PATH_IPROUTE_DIR "/rt_realms", "ipr_", 256); read_iproute_table(PATH_IPROUTE_DIR "/rt_scopes", "ips_", 256); read_iproute_table(PATH_IPROUTE_DIR "/rt_tables", "ipt_", 256);