summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKen Raeburn <raeburn@mit.edu>2000-10-10 15:24:22 +0000
committerKen Raeburn <raeburn@mit.edu>2000-10-10 15:24:22 +0000
commit045fe9bf7263b9ed539e527199db7dd6bc60e3b5 (patch)
tree90b86e257b05fd7399bb6590578534a5e5ee3ed9 /src
parentc7be20a68a11e52e03ff69ef42e0c3a265c8e6f8 (diff)
getifaddrs() support
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@12751 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src')
-rw-r--r--src/lib/krb5/configure.in4
-rw-r--r--src/lib/krb5/os/ChangeLog14
-rw-r--r--src/lib/krb5/os/Makefile.in3
-rw-r--r--src/lib/krb5/os/localaddr.c207
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 <raeburn@mit.edu>
+
+ 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 <epeisach@mit.edu>
* 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 <ifaddrs.h>
+
+#ifdef DEBUG
+#include <netinet/in.h>
+#include <net/if.h>
+
+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 */
/*