summaryrefslogtreecommitdiff
path: root/sysdep
diff options
context:
space:
mode:
Diffstat (limited to 'sysdep')
-rw-r--r--sysdep/bsd/krt-sock.c41
-rw-r--r--sysdep/bsd/sysio.h4
-rw-r--r--sysdep/linux/netlink.c6
-rw-r--r--sysdep/unix/krt.Y44
-rw-r--r--sysdep/unix/krt.c74
-rw-r--r--sysdep/unix/krt.h20
-rw-r--r--sysdep/unix/unix.h3
7 files changed, 93 insertions, 99 deletions
diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c
index df639816..be8b50d6 100644
--- a/sysdep/bsd/krt-sock.c
+++ b/sysdep/bsd/krt-sock.c
@@ -287,18 +287,21 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
#endif
{
/* Fallback for all other valid cases */
- if (!i->addr)
- {
- log(L_ERR "KRT: interface %s has no IP addess", i->name);
- return -1;
- }
#ifdef RTF_CLONING
if (cmd == RTM_ADD && (i->flags & IF_MULTIACCESS) != IF_MULTIACCESS) /* PTP */
msg.rtm.rtm_flags |= RTF_CLONING;
#endif
- sockaddr_fill(&gate, ipa_is_ip4(i->addr->ip) ? AF_INET : AF_INET6, i->addr->ip, NULL, 0);
+ struct ifa *addr = (net->n.addr->type == NET_IP4) ? i->addr4 : (i->addr6 ?: i->llv6);
+
+ if (!addr)
+ {
+ log(L_ERR "KRT: interface %s has no IP addess", i->name);
+ return -1;
+ }
+
+ sockaddr_fill(&gate, af, addr->ip, i, 0);
msg.rtm.rtm_addrs |= RTA_GATEWAY;
break;
}
@@ -1124,13 +1127,11 @@ kif_sys_shutdown(struct kif_proto *p)
krt_buffer_release(&p->p);
}
-
-struct ifa *
-kif_get_primary_ip(struct iface *i UNUSED)
+int
+kif_update_sysdep_addr(struct iface *i)
{
-#if 0
static int fd = -1;
-
+
if (fd < 0)
fd = socket(AF_INET, SOCK_DGRAM, 0);
@@ -1140,20 +1141,10 @@ kif_get_primary_ip(struct iface *i UNUSED)
int rv = ioctl(fd, SIOCGIFADDR, (char *) &ifr);
if (rv < 0)
- return NULL;
-
- ip_addr addr;
- struct sockaddr_in *sin = (struct sockaddr_in *) &ifr.ifr_addr;
- memcpy(&addr, &sin->sin_addr.s_addr, sizeof(ip_addr));
- ipa_ntoh(addr);
+ return 0;
- struct ifa *a;
- WALK_LIST(a, i->addrs)
- {
- if (ipa_equal(a->ip, addr))
- return a;
- }
-#endif
+ ip4_addr old = i->sysdep;
+ i->sysdep = ip4_from_ipa(ipa_from_sa4(&ifr.ifr_addr);
- return NULL;
+ return !ip4_equal(i->sysdep, addr);
}
diff --git a/sysdep/bsd/sysio.h b/sysdep/bsd/sysio.h
index 0e895e20..68296e65 100644
--- a/sysdep/bsd/sysio.h
+++ b/sysdep/bsd/sysio.h
@@ -38,12 +38,12 @@
*/
#define INIT_MREQ4(maddr,ifa) \
- { .imr_multiaddr = ipa_to_in4(maddr), .imr_interface = ipa_to_in4(ifa->addr->ip) }
+ { .imr_multiaddr = ipa_to_in4(maddr), .imr_interface = ip4_to_in4(ifa->sysdep) }
static inline int
sk_setup_multicast4(sock *s)
{
- struct in_addr ifa = ipa_to_in4(s->iface->addr->ip);
+ struct in_addr ifa = ip4_to_in4(s->iface->sysdep);
u8 ttl = s->ttl;
u8 n = 0;
diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c
index 2b7b13fb..c9d5cdec 100644
--- a/sysdep/linux/netlink.c
+++ b/sysdep/linux/netlink.c
@@ -2030,3 +2030,9 @@ void
kif_sys_shutdown(struct kif_proto *p UNUSED)
{
}
+
+int
+kif_update_sysdep_addr(struct iface *i UNUSED)
+{
+ return 0;
+}
diff --git a/sysdep/unix/krt.Y b/sysdep/unix/krt.Y
index b261c91e..3bf7da65 100644
--- a/sysdep/unix/krt.Y
+++ b/sysdep/unix/krt.Y
@@ -14,6 +14,7 @@ CF_DEFINES
#define THIS_KRT ((struct krt_config *) this_proto)
#define THIS_KIF ((struct kif_config *) this_proto)
+#define KIF_IFACE ((struct kif_iface_config *) this_ipatt)
static void
krt_set_merge_paths(struct channel_config *cc, uint merge, uint limit)
@@ -25,6 +26,17 @@ krt_set_merge_paths(struct channel_config *cc, uint merge, uint limit)
cc->merge_limit = limit;
}
+static void
+kif_set_preferred(ip_addr ip)
+{
+ if (ipa_is_ip4(ip))
+ KIF_IFACE->pref_v4 = ip;
+ else if (!ipa_is_link_local(ip))
+ KIF_IFACE->pref_v6 = ip;
+ else
+ KIF_IFACE->pref_ll = ip;
+}
+
CF_DECLS
CF_KEYWORDS(KERNEL, PERSIST, SCAN, TIME, LEARN, DEVICE, ROUTES, GRACEFUL, RESTART, KRT_SOURCE, KRT_METRIC, MERGE, PATHS)
@@ -88,18 +100,38 @@ CF_ADDTO(kif_proto, kif_proto kif_item ';')
kif_item:
proto_item
+ | INTERFACE kif_iface
| SCAN TIME expr {
/* Scan time of 0 means scan on startup only */
THIS_KIF->scan_time = $3;
}
- | PRIMARY opttext net_or_ipa {
- struct kif_primary_item *kpi = cfg_alloc(sizeof (struct kif_primary_item));
- kpi->pattern = $2;
- kpi->addr = $3;
- add_tail(&THIS_KIF->primary, &kpi->n);
- }
;
+kif_iface_start:
+{
+ this_ipatt = cfg_allocz(sizeof(struct kif_iface_config));
+ add_tail(&THIS_KIF->iface_list, NODE this_ipatt);
+ init_list(&this_ipatt->ipn_list);
+}
+
+kif_iface_item:
+ PREFERRED ipa { kif_set_preferred($2); }
+ ;
+
+kif_iface_opts:
+ /* empty */
+ | kif_iface_opts kif_iface_item ';'
+ ;
+
+kif_iface_opt_list:
+ /* empty */
+ | '{' kif_iface_opts '}'
+ ;
+
+kif_iface:
+ kif_iface_start iface_patt_list_nopx kif_iface_opt_list;
+
+
CF_ADDTO(dynamic_attr, KRT_SOURCE { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_KRT_SOURCE); })
CF_ADDTO(dynamic_attr, KRT_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_KRT_METRIC); })
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index f0241777..0349a09f 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -89,6 +89,16 @@ static struct kif_config *kif_cf;
static timer *kif_scan_timer;
static bird_clock_t kif_last_shot;
+static struct kif_iface_config kif_default_iface = {};
+
+struct kif_iface_config *
+kif_get_iface_config(struct iface *iface)
+{
+ struct kif_config *cf = (void *) (kif_proto->p.cf);
+ struct kif_iface_config *ic = (void *) iface_patt_find(&cf->iface_list, iface, NULL);
+ return ic ?: &kif_default_iface;
+}
+
static void
kif_scan(timer *t)
{
@@ -116,57 +126,6 @@ kif_request_scan(void)
tm_start(kif_scan_timer, 1);
}
-static inline int
-prefer_addr(struct ifa *a, struct ifa *b)
-{
- 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;
-}
-
-static inline struct ifa *
-find_preferred_ifa(struct iface *i, const net_addr *n)
-{
- struct ifa *a, *b = NULL;
-
- WALK_LIST(a, i->addrs)
- {
- if (!(a->flags & IA_SECONDARY) &&
- (!n || ipa_in_netX(a->ip, n)) &&
- (!b || prefer_addr(a, b)))
- 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->addr))
- return a;
- }
-
- if (a = kif_get_primary_ip(i))
- return a;
-
- return find_preferred_ifa(i, NULL);
-}
-
-
static struct proto *
kif_init(struct proto_config *c)
{
@@ -224,15 +183,15 @@ kif_reconfigure(struct proto *p, struct proto_config *new)
tm_start(kif_scan_timer, n->scan_time);
}
- if (!EMPTY_LIST(o->primary) || !EMPTY_LIST(n->primary))
+ if (!EMPTY_LIST(o->iface_list) || !EMPTY_LIST(n->iface_list))
{
/* This is hack, we have to update a configuration
* to the new value just now, because it is used
- * for recalculation of primary addresses.
+ * for recalculation of preferred addresses.
*/
p->cf = new;
- ifa_recalc_all_primary_addresses();
+ if_recalc_all_preferred_addresses();
}
return 1;
@@ -254,7 +213,7 @@ kif_init_config(int class)
kif_cf = (struct kif_config *) proto_config_new(&proto_unix_iface, class);
kif_cf->scan_time = 60;
- init_list(&kif_cf->primary);
+ init_list(&kif_cf->iface_list);
kif_sys_init_config(kif_cf);
return (struct proto_config *) kif_cf;
@@ -266,14 +225,13 @@ 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;
- /* Copy primary addr list */
- cfg_copy_list(&d->primary, &s->primary, sizeof(struct kif_primary_item));
+ /* Copy interface config list */
+ cfg_copy_list(&d->iface_list, &s->iface_list, sizeof(struct kif_iface_config));
/* Fix sysdep parts */
kif_sys_copy_config(d, s);
}
-
struct protocol proto_unix_iface = {
.name = "Device",
.template = "device%d",
diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h
index cb404de3..089c97ad 100644
--- a/sysdep/unix/krt.h
+++ b/sysdep/unix/krt.h
@@ -94,17 +94,20 @@ void krt_got_route_async(struct krt_proto *p, struct rte *e, int new);
extern struct protocol proto_unix_iface;
-struct kif_primary_item {
- node n;
- byte *pattern;
- net_addr addr;
-};
-
struct kif_config {
struct proto_config c;
struct kif_params sys; /* Sysdep params */
+
+ list iface_list; /* List of iface configs (struct kif_iface_config) */
int scan_time; /* How often we re-scan interfaces */
- list primary; /* Preferences for primary addresses (struct kif_primary_item) */
+};
+
+struct kif_iface_config {
+ struct iface_patt i;
+
+ ip_addr pref_v4;
+ ip_addr pref_v6;
+ ip_addr pref_ll;
};
struct kif_proto {
@@ -116,6 +119,7 @@ extern struct kif_proto *kif_proto;
#define KIF_CF ((struct kif_config *)p->p.cf)
+struct kif_iface_config * kif_get_iface_config(struct iface *iface);
struct proto_config * krt_init_config(int class);
@@ -150,6 +154,6 @@ void kif_sys_copy_config(struct kif_config *, struct kif_config *);
void kif_do_scan(struct kif_proto *);
-struct ifa *kif_get_primary_ip(struct iface *i);
+int kif_update_sysdep_addr(struct iface *i);
#endif
diff --git a/sysdep/unix/unix.h b/sysdep/unix/unix.h
index dcaab729..4b0fb005 100644
--- a/sysdep/unix/unix.h
+++ b/sysdep/unix/unix.h
@@ -80,6 +80,9 @@ static inline ip_addr ipa_from_sa(sockaddr *sa)
static inline struct in_addr ipa_to_in4(ip_addr a)
{ return (struct in_addr) { htonl(ipa_to_u32(a)) }; }
+static inline struct in_addr ip4_to_in4(ip4_addr a)
+{ return (struct in_addr) { htonl(ip4_to_u32(a)) }; }
+
static inline struct in6_addr ipa_to_in6(ip_addr a)
{ return (struct in6_addr) { .s6_addr32 = { htonl(_I0(a)), htonl(_I1(a)), htonl(_I2(a)), htonl(_I3(a)) } }; }