[6419] in Kerberos
Re: Kerberos 5-B4-pl3 bug report (lib/krb5/os/localaddr.c)
daemon@ATHENA.MIT.EDU (Craig Leres)
Tue Jan 2 01:24:38 1996
To: kerberos@MIT.EDU
Date: 2 Jan 1996 06:12:13 GMT
From: leres@ell.ee.lbl.gov (Craig Leres)
------- Forwarded Message
Date: Mon, 01 Jan 96 22:08:57 PST
From: Craig Leres <leres>
Subject: Kerberos 5-B4-pl3 bug report (lib/krb5/os/localaddr.c)
To: krb5-bugs@athena.mit.edu
The routine krb5_os_localaddr() returns only one address when running
under 4.4 BSD or BSDI; if the first interface is not configured, it
return no addresses. I ran into the latter case which caused k5init to
fail with "Incorrect net address while getting initial credentials."
I imported some code from our libpcap package that works under BSDI 2
and SunOS 4. It behaves the same as the old code for most systems but
handles the variable length addresses found in newer 4 BSD based systems.
The new localaddr.c source is appended.
Craig
------
/*
* lib/krb5/os/localaddr.c
*
* Copyright 1990,1991 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
* require a specific license from the United States Government.
* It is the responsibility of any person or organization contemplating
* export to obtain such a license before exporting.
*
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
* distribute this software and its documentation for any purpose and
* without fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation, and that
* the name of M.I.T. not be used in advertising or publicity pertaining
* to distribution of the software without specific, written prior
* permission. M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is" without express
* or implied warranty.
*
*
* Return the protocol addresses supported by this host.
*
* XNS support is untested, but "Should just work".
*/
#include <krb5/krb5.h>
#include <krb5/osconf.h>
#include <krb5/ext-proto.h>
/* needed for solaris, harmless elsewhere... */
#define BSD_COMP
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <net/route.h>
#ifndef SOLARIS
#include <sys/mbuf.h>
#endif
#include <net/if.h>
#include <errno.h>
/*
* The SIOCGIF* ioctls require a socket.
* It doesn't matter *what* kind of socket they use, but it has to be
* a socket.
*
* Of course, you can't just ask the kernel for a socket of arbitrary
* type; you have to ask for one with a valid type.
*
*/
#ifdef KRB5_USE_INET
#include <netinet/in.h>
#ifndef USE_AF
#define USE_AF AF_INET
#define USE_TYPE SOCK_DGRAM
#define USE_PROTO 0
#endif
#endif
#ifdef KRB5_USE_NS
#include <netns/ns.h>
#ifndef USE_AF
#define USE_AF AF_NS
#define USE_TYPE SOCK_DGRAM
#define USE_PROTO 0 /* guess */
#endif
#endif
/*
* Add more address families here.
*/
extern int errno;
/*
* Return all the protocol addresses of this host.
*
* We could kludge up something to return all addresses, assuming that
* they're valid kerberos protocol addresses, but we wouldn't know the
* real size of the sockaddr or know which part of it was actually the
* host part.
*
* This uses the SIOCGIFCONF, SIOCGIFFLAGS, and SIOCGIFADDR ioctl's.
*/
krb5_error_code krb5_os_localaddr(addr)
krb5_address ***addr;
{
register struct ifreq *ifr, *ifend, *ifnext;
struct ifconf ifc;
int s, code, n, i;
char buf[1024];
krb5_address *addr_temp[sizeof(buf) / sizeof(struct ifreq)];
int n_found;
int mem_err = 0;
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
s = socket (USE_AF, USE_TYPE, USE_PROTO);
if (s < 0)
return errno;
code = ioctl (s, SIOCGIFCONF, (char *)&ifc);
if (code < 0) {
int retval = errno;
close(s);
return retval;
}
ifr = (struct ifreq *)buf;
ifend = (struct ifreq *)(buf + ifc.ifc_len);
for (n_found=0; ifr < ifend && !mem_err; ifr = ifnext) {
krb5_address *address;
#if BSD - 0 >= 199006
n = ifr->ifr_addr.sa_len + sizeof(ifr->ifr_name);
if (n < sizeof(*ifr))
ifnext = ifr + 1;
else
ifnext = (struct ifreq *)((char *)ifr + n);
#else
ifnext = ifr + 1;
#endif
if (ioctl (s, SIOCGIFFLAGS, (char *)ifr) < 0)
continue;
#ifdef IFF_LOOPBACK
if (ifr->ifr_flags & IFF_LOOPBACK)
continue;
#endif
if (!(ifr->ifr_flags & IFF_UP))
/* interface is down; skip */
continue;
if (ioctl (s, SIOCGIFADDR, (char *)ifr) < 0)
/* can't get address */
continue;
/* ifr->ifr_addr has what we want! */
switch (ifr->ifr_addr.sa_family) {
#ifdef KRB5_USE_INET
case AF_INET:
{
struct sockaddr_in *in =
(struct sockaddr_in *)&ifr->ifr_addr;
address = (krb5_address *)
malloc (sizeof(krb5_address));
if (address) {
address->addrtype = ADDRTYPE_INET;
address->length = sizeof(struct in_addr);
address->contents = (unsigned char *)malloc(address->length
);
if (!address->contents) {
krb5_xfree(address);
address = 0;
mem_err++;
} else {
memcpy ((char *)address->contents,
(char *)&in->sin_addr,
address->length);
break;
}
} else mem_err++;
}
#endif
#ifdef KRB5_USE_NS
case AF_XNS:
{
struct sockaddr_ns *ns =
(struct sockaddr_ns *)&ifr->ifr_addr;
address = (krb5_address *)
malloc (sizeof (krb5_address) + sizeof (struct ns_addr));
if (address) {
address->addrtype = ADDRTYPE_XNS;
/* XXX should we perhaps use ns_host instead? */
address->length = sizeof(struct ns_addr);
address->contents = (unsigned char *)malloc(address->length
);
if (!address->contents) {
krb5_xfree(address);
address = 0;
mem_err++;
} else {
memcpy ((char *)address->contents,
(char *)&ns->sns_addr,
address->length);
break;
}
} else mem_err++;
break;
}
#endif
/*
* Add more address families here..
*/
default:
continue;
}
if (address)
addr_temp[n_found++] = address;
address = 0;
}
close(s);
*addr = (krb5_address **)malloc (sizeof (krb5_address *) * (n_found+1));
if (*addr == 0)
mem_err++;
if (mem_err) {
for (i=0; i<n_found; i++) {
krb5_xfree(addr_temp[i]);
addr_temp[i] = 0;
}
return ENOMEM;
}
for (i=0; i<n_found; i++) {
(*addr)[i] = addr_temp[i];
}
(*addr)[n_found] = 0;
return 0;
}
------- End of Forwarded Message