diff options
author | Ondrej Zajicek <santiago@crfreenet.org> | 2013-11-25 01:21:39 +0100 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2013-11-25 01:21:39 +0100 |
commit | e237b28a4d4b17ab50182ac110f28594967e76dc (patch) | |
tree | 6ddd5c6b7138ed0bd60a925859d76005f21447e6 /sysdep | |
parent | 5ebc92935cb58c78286d91f0831de94cd4ae0f9e (diff) |
Changes primary addr selection on BSD to respect SIOCGIFADDR ioctl() result.
Thanks to Alexander V. Chernikov for the original patch.
Diffstat (limited to 'sysdep')
-rw-r--r-- | sysdep/bsd/krt-sock.c | 33 | ||||
-rw-r--r-- | sysdep/linux/krt-sys.h | 2 | ||||
-rw-r--r-- | sysdep/unix/krt.c | 3 | ||||
-rw-r--r-- | sysdep/unix/krt.h | 1 |
4 files changed, 39 insertions, 0 deletions
diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index 0bc29458..84ce9c60 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -1058,3 +1058,36 @@ kif_sys_shutdown(struct kif_proto *p) krt_buffer_release(&p->p); } + +struct ifa * +kif_get_primary_ip(struct iface *i) +{ +#ifndef IPV6 + static int fd = -1; + + if (fd < 0) + fd = socket(AF_INET, SOCK_DGRAM, 0); + + struct ifreq ifr; + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, i->name, IFNAMSIZ); + + 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); + + struct ifa *a; + WALK_LIST(a, i->addrs) + { + if (ipa_equal(a->ip, addr)) + return a; + } +#endif + + return NULL; +} diff --git a/sysdep/linux/krt-sys.h b/sysdep/linux/krt-sys.h index 7b3043a7..7e97968a 100644 --- a/sysdep/linux/krt-sys.h +++ b/sysdep/linux/krt-sys.h @@ -27,6 +27,8 @@ static inline void kif_sys_postconfig(struct kif_config *c UNUSED) { } static inline void kif_sys_init_config(struct kif_config *c UNUSED) { } static inline void kif_sys_copy_config(struct kif_config *d UNUSED, struct kif_config *s UNUSED) { } +static inline struct ifa * kif_get_primary_ip(struct iface *i) { return NULL; } + /* Kernel routes */ diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index 57cfe5a4..8f24cf51 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -159,6 +159,9 @@ kif_choose_primary(struct iface *i) return a; } + if (a = kif_get_primary_ip(i)) + return a; + return find_preferred_ifa(i, IPA_NONE, IPA_NONE); } diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h index 446914d2..99983ccd 100644 --- a/sysdep/unix/krt.h +++ b/sysdep/unix/krt.h @@ -142,5 +142,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); #endif |