From 045fe9bf7263b9ed539e527199db7dd6bc60e3b5 Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Tue, 10 Oct 2000 15:24:22 +0000 Subject: [PATCH] getifaddrs() support git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@12751 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/krb5/configure.in | 4 +- src/lib/krb5/os/ChangeLog | 14 +++ src/lib/krb5/os/Makefile.in | 3 + src/lib/krb5/os/localaddr.c | 207 ++++++++++++++++++++++++++++++++++-- 4 files changed, 217 insertions(+), 11 deletions(-) diff --git a/src/lib/krb5/configure.in b/src/lib/krb5/configure.in index ce4f84c11..ae8c7f4ff 100644 --- a/src/lib/krb5/configure.in +++ b/src/lib/krb5/configure.in @@ -8,8 +8,8 @@ AC_TYPE_UID_T AC_TYPE_OFF_T HAS_ANSI_VOLATILE AC_HEADER_STDARG -AC_CHECK_HEADERS(unistd.h paths.h regex.h regexp.h regexpr.h fcntl.h memory.h) -AC_CHECK_FUNCS(flock fchmod chmod strftime strptime geteuid setenv unsetenv getenv setsid gethostbyname2) +AC_CHECK_HEADERS(unistd.h paths.h regex.h regexp.h regexpr.h fcntl.h memory.h ifaddrs.h) +AC_CHECK_FUNCS(flock fchmod chmod strftime strptime geteuid setenv unsetenv getenv setsid gethostbyname2 getifaddrs) AC_REPLACE_FUNCS(vfprintf vsprintf strdup strcasecmp strerror memmove daemon getuid sscanf syslog) KRB5_AC_REGEX_FUNCS dnl diff --git a/src/lib/krb5/os/ChangeLog b/src/lib/krb5/os/ChangeLog index 31cf7e25e..6a337cc8f 100644 --- a/src/lib/krb5/os/ChangeLog +++ b/src/lib/krb5/os/ChangeLog @@ -1,3 +1,17 @@ +2000-10-09 Ken Raeburn + + Support for getifaddrs() interface added in BSD. + * localaddr.c (printaddr, printifaddr) [HAVE_IFADDRS_H && DEBUG]: + New functions for debugging new ifaddrs code. + (addr_eq) [HAVE_IFADDRS_H]: New function, for comparing addresses + found with getifaddrs. + (foreach_localaddr) [HAVE_IFADDRS_H]: New implementation, relies + on C library function to retrieve data. + (foreach_localaddr) [!HAVE_IFADDRS_H && TEST]: Print info about + each address and why it might not be used. + (print_addr, main) [TEST]: Print out the local addresses. + * Makefile.in (t_localaddr): New target. + 2000-09-26 Ezra Peisach * an_to_ln.c: Unsigned vs signed int fixes. diff --git a/src/lib/krb5/os/Makefile.in b/src/lib/krb5/os/Makefile.in index 05775c41b..a85047416 100644 --- a/src/lib/krb5/os/Makefile.in +++ b/src/lib/krb5/os/Makefile.in @@ -166,6 +166,9 @@ t_an_to_ln: $(T_AN_TO_LN_OBJS) $(KRB5_BASE_DEPLIBS) t_realm_iter: $(T_REALM_ITER_OBJS) $(KRB5_BASE_DEPLIBS) $(CC_LINK) -o t_realm_iter $(T_REALM_ITER_OBJS) $(KRB5_BASE_LIBS) +t_localaddr: localaddr.c + $(CC) $(ALL_CFLAGS) -DTEST -o t_localaddr $(srcdir)/localaddr.c + check-unix:: $(TEST_PROGS) KRB5_CONFIG=$(srcdir)/td_krb5.conf ; export KRB5_CONFIG ;\ $(KRB5_RUN_ENV) ./t_std_conf -d -s NEW.DEFAULT.REALM -d \ diff --git a/src/lib/krb5/os/localaddr.c b/src/lib/krb5/os/localaddr.c index d5b46b664..170b7f2c2 100644 --- a/src/lib/krb5/os/localaddr.c +++ b/src/lib/krb5/os/localaddr.c @@ -249,13 +249,147 @@ add_addr (void *P_data, struct sockaddr *a) #define ifreq_size(i) sizeof(struct ifreq) #endif /* HAVE_SA_LEN*/ +#ifdef HAVE_IFADDRS_H +#include + +#ifdef DEBUG +#include +#include + +void printaddr (struct sockaddr *sa) +{ + char buf[50]; + printf ("%p ", sa); + switch (sa->sa_family) { + case AF_INET: + inet_ntop (AF_INET, &((struct sockaddr_in *)sa)->sin_addr, + buf, sizeof (buf)); + printf ("inet %s", buf); + break; + case AF_INET6: + inet_ntop (AF_INET6, &((struct sockaddr_in6 *)sa)->sin6_addr, + buf, sizeof (buf)); + printf ("inet6 %s", buf); + break; + default: + printf ("family=%d", sa->sa_family); + break; + } +} + +void printifaddr (struct ifaddrs *ifp) +{ + printf ("%p={\n", ifp); +/* printf ("\tnext=%p\n", ifp->ifa_next); */ + printf ("\tname=%s\n", ifp->ifa_name); + printf ("\tflags="); + { + int ch, flags = ifp->ifa_flags; + printf ("%x", flags); + ch = '<'; +#define X(F) if (flags & IFF_##F) { printf ("%c%s", ch, #F); flags &= ~IFF_##F; ch = ','; } + X (UP); X (BROADCAST); X (DEBUG); X (LOOPBACK); X (POINTOPOINT); + X (NOTRAILERS); X (RUNNING); X (NOARP); X (PROMISC); X (ALLMULTI); + X (OACTIVE); X (SIMPLEX); X (MULTICAST); + printf (">"); +#undef X + } + if (ifp->ifa_addr) + printf ("\n\taddr="), printaddr (ifp->ifa_addr); + if (ifp->ifa_netmask) + printf ("\n\tnetmask="), printaddr (ifp->ifa_netmask); + if (ifp->ifa_broadaddr) + printf ("\n\tbroadaddr="), printaddr (ifp->ifa_broadaddr); + if (ifp->ifa_dstaddr) + printf ("\n\tdstaddr="), printaddr (ifp->ifa_dstaddr); + if (ifp->ifa_data) + printf ("\n\tdata=%p", ifp->ifa_data); + printf ("\n}\n"); +} +#endif /* DEBUG */ + static int -foreach_localaddr (data, pass1fn, betweenfn, pass2fn) - void *data; - int (*pass1fn) (void *, struct sockaddr *); - int (*betweenfn) (void *); - int (*pass2fn) (void *, struct sockaddr *); +addr_eq (const struct sockaddr *s1, const struct sockaddr *s2) { + if (s1->sa_family != s2->sa_family) + return 0; +#ifdef HAVE_SA_LEN + if (s1->sa_len != s2->sa_len) + return 0; + return !memcmp (s1, s2, s1->sa_len); +#else +#define CMPTYPE(T,F) (!memcmp(&((T*)s1)->F,&((T*)s2)->F,sizeof(((T*)s1)->F))) + switch (s1->sa_family) { + case AF_INET: + return CMPTYPE (struct sockaddr_in, sin_addr); + case AF_INET6: + return CMPTYPE (struct sockaddr_in6, sin6_addr); + default: + /* Err on side of duplicate listings. */ + return 0; + } +#endif +} +#endif + +static int +foreach_localaddr (void *data, + int (*pass1fn) (void *, struct sockaddr *), + int (*betweenfn) (void *), + int (*pass2fn) (void *, struct sockaddr *)) +{ +#ifdef HAVE_IFADDRS_H + struct ifaddrs *ifp_head, *ifp, *ifp2; + int match, fail = 0; + + if (getifaddrs (&ifp_head) < 0) + return errno; + for (ifp = ifp_head; ifp; ifp = ifp->ifa_next) { +#ifdef DEBUG + printifaddr (ifp); +#endif + if ((ifp->ifa_flags & IFF_UP) == 0) + continue; + if (ifp->ifa_flags & IFF_LOOPBACK) { + ifp->ifa_flags &= ~IFF_UP; + continue; + } + /* If this address is a duplicate, punt. */ + match = 0; + for (ifp2 = ifp_head; ifp2 && ifp2 != ifp; ifp2 = ifp2->ifa_next) { + if ((ifp2->ifa_flags & IFF_UP) == 0) + continue; + if (ifp2->ifa_flags & IFF_LOOPBACK) + continue; + if (addr_eq (ifp->ifa_addr, ifp2->ifa_addr)) { + match = 1; + ifp->ifa_flags &= ~IFF_UP; + break; + } + } + if (match) + continue; + if ((*pass1fn) (data, ifp->ifa_addr)) { + fail = 1; + goto punt; + } + } + if (betweenfn && (*betweenfn)(data)) { + fail = 1; + goto punt; + } + if (pass2fn) + for (ifp = ifp_head; ifp; ifp = ifp->ifa_next) { + if (ifp->ifa_flags & IFF_UP) + if ((*pass2fn) (data, ifp->ifa_addr)) { + fail = 1; + goto punt; + } + } + punt: + freeifaddrs (ifp_head); + return fail; +#else struct ifreq *ifr, ifreq, *ifr2; struct ifconf ifc; int s, code, n, i, j; @@ -329,22 +463,32 @@ foreach_localaddr (data, pass1fn, betweenfn, pass2fn) ifr = (struct ifreq *)((caddr_t) ifc.ifc_buf+i); strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof (ifreq.ifr_name)); +#ifdef TEST + printf ("interface %s\n", ifreq.ifr_name); +#endif if (ioctl (s, SIOCGIFFLAGS, (char *)&ifreq) < 0) { skip: /* mark for next pass */ ifr->ifr_name[0] = 0; - continue; } #ifdef IFF_LOOPBACK /* None of the current callers want loopback addresses. */ - if (ifreq.ifr_flags & IFF_LOOPBACK) + if (ifreq.ifr_flags & IFF_LOOPBACK) { +#ifdef TEST + printf ("loopback\n"); +#endif goto skip; + } #endif /* Ignore interfaces that are down. */ - if (!(ifreq.ifr_flags & IFF_UP)) + if (!(ifreq.ifr_flags & IFF_UP)) { +#ifdef TEST + printf ("down\n"); +#endif goto skip; + } /* Make sure we didn't process this address already. */ for (j = 0; j < i; j += ifreq_size(*ifr2)) { @@ -359,8 +503,12 @@ foreach_localaddr (data, pass1fn, betweenfn, pass2fn) to do it on a per address family basis. */ && !memcmp (&ifr2->ifr_addr.sa_data, &ifr->ifr_addr.sa_data, (ifreq_size (*ifr) - - offsetof (struct ifreq, ifr_addr.sa_data)))) + - offsetof (struct ifreq, ifr_addr.sa_data)))) { +#ifdef TEST + printf ("duplicate addr\n"); +#endif goto skip; + } } if ((*pass1fn) (data, &ifr->ifr_addr)) { @@ -392,9 +540,48 @@ foreach_localaddr (data, pass1fn, betweenfn, pass2fn) free (buf); return fail; +#endif /* not HAVE_IFADDRS_H */ } +#ifdef TEST +int print_addr (void *dataptr, struct sockaddr *sa) +{ + char buf[50]; + printf ("family %d", sa->sa_family); + switch (sa->sa_family) { + case AF_INET: + printf (" addr %s\n", + inet_ntoa (((struct sockaddr_in *)sa)->sin_addr)); + break; + case AF_INET6: + printf (" addr %s\n", + inet_ntop (sa->sa_family, + &((struct sockaddr_in6 *)sa)->sin6_addr, + buf, sizeof (buf))); + break; +#ifdef AF_LINK + case AF_LINK: + printf (" linkaddr\n"); + break; +#endif + default: + printf (" don't know how to print addr\n"); + break; + } + return 0; +} + +int main () +{ + int r; + + r = foreach_localaddr (0, print_addr, 0, 0); + printf ("return value = %d\n", r); + return 0; +} + +#else /* not TESTing */ KRB5_DLLIMP krb5_error_code KRB5_CALLCONV krb5_os_localaddr(context, addr) @@ -437,6 +624,8 @@ krb5_os_localaddr(context, addr) return 0; } +#endif /* not TESTing */ + #else /* Windows/Mac version */ /* -- 2.26.2