1
0
mirror of https://github.com/samba-team/samba.git synced 2025-08-03 04:22:09 +03:00

r25472: Fix the interfaces code to detect IPv6 interfaces, using the

new standard getifaddrs() and freeifaddrs() interfaces. Currently
we only return IPv4 af_families. Needs fixing for binds to IPv6
but this has to be careful work.
Jeremy.
(This used to be commit 327875182c)
This commit is contained in:
Jeremy Allison
2007-10-02 19:27:25 +00:00
committed by Gerald (Jerry) Carter
parent 5c5acae0ee
commit 3fbd1ae54c
9 changed files with 255 additions and 72 deletions

View File

@ -995,7 +995,7 @@ AC_CHECK_HEADERS(limits.h float.h pthread.h)
AC_CHECK_HEADERS(rpc/rpc.h rpcsvc/nis.h rpcsvc/ypclnt.h)
AC_CHECK_HEADERS(sys/param.h ctype.h sys/wait.h sys/resource.h sys/ioctl.h sys/ipc.h sys/prctl.h)
AC_CHECK_HEADERS(sys/mman.h sys/filio.h sys/priv.h sys/shm.h string.h strings.h stdlib.h sys/socket.h)
AC_CHECK_HEADERS(sys/un.h)
AC_CHECK_HEADERS(sys/un.h ifaddrs.h)
AC_CHECK_HEADERS(sys/mount.h sys/vfs.h sys/fs/s5param.h sys/filsys.h termios.h termio.h)
AC_CHECK_HEADERS(sys/termio.h sys/statfs.h sys/dustat.h sys/statvfs.h stdarg.h sys/sockio.h)
AC_CHECK_HEADERS(sys/sysmacros.h)
@ -1082,6 +1082,7 @@ AC_CHECK_TYPE(loff_t,off_t)
AC_CHECK_TYPE(offset_t,loff_t)
AC_CHECK_TYPE(ssize_t, int)
AC_CHECK_TYPE(wchar_t, unsigned short)
AC_CHECK_TYPE(socklen_t, int)
AC_CHECK_TYPE(comparison_fn_t,
[AC_DEFINE(HAVE_COMPARISON_FN_T, 1,[Whether or not we have comparison_fn_t])])
@ -3038,6 +3039,42 @@ SMB_CHECK_SYSCONF(_SC_NPROCESSORS_ONLN)
SMB_CHECK_SYSCONF(_SC_PAGESIZE)
AC_CHECK_FUNCS(getpagesize)
dnl test for sa_family_t
AC_CACHE_CHECK([for sa_family_t],samba_cv_HAVE_SA_FAMILY_T,[
AC_TRY_COMPILE([
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
],
[
sa_family_t foo;
],
samba_cv_HAVE_SA_FAMILY_T=yes,samba_cv_HAVE_SA_FAMILY_T=no)])
if test x"$samba_cv_HAVE_SA_FAMILY_T" = x"yes"; then
AC_DEFINE(HAVE_SA_FAMILY_T,1,[Whether the system has sa_family_t])
fi
dnl test for getifaddrs and freeifaddrs
AC_CACHE_CHECK([for getifaddrs and freeifaddrs],samba_cv_HAVE_GETIFADDRS,[
AC_TRY_COMPILE([
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <netdb.h>],
[
struct ifaddrs *ifp = NULL;
int ret = getifaddrs (&ifp);
freeifaddrs(ifp);
],
samba_cv_HAVE_GETIFADDRS=yes,samba_cv_HAVE_GETIFADDRS=no)])
if test x"$samba_cv_HAVE_GETIFADDRS" = x"yes"; then
AC_DEFINE(HAVE_GETIFADDRS,1,[Whether the system has getifaddrs])
AC_DEFINE(HAVE_FREEIFADDRS,1,[Whether the system has freeifaddrs])
fi
##################
# look for a method of finding the list of network interfaces
iface=no;
@ -3055,6 +3092,21 @@ if test x"$samba_cv_HAVE_IFACE_AIX" = x"yes"; then
iface=yes;AC_DEFINE(HAVE_IFACE_AIX,1,[Whether iface AIX is available])
fi
if test $iface = no; then
AC_CACHE_CHECK([for iface getifaddrs],samba_cv_HAVE_GETIFADDRS,[
SAVE_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS ${SAMBA_CONFIGURE_CPPFLAGS}"
AC_TRY_RUN([
#define HAVE_IFACE_GETIFADDRS 1
#define AUTOCONF_TEST 1
#include "${srcdir-.}/lib/interfaces.c"],
samba_cv_HAVE_IFACE_GETIFADDRS=yes,samba_cv_HAVE_IFACE_GETIFADDRS=no,samba_cv_HAVE_IFACE_GETIFADDRS=cross)])
CPPFLAGS="$SAVE_CPPFLAGS"
if test x"$samba_cv_HAVE_IFACE_GETIFADDRS" = x"yes"; then
iface=yes;AC_DEFINE(HAVE_IFACE_GETIFADDRS,1,[Whether iface ifconf is available])
fi
fi
if test $iface = no; then
AC_CACHE_CHECK([for iface ifconf],samba_cv_HAVE_IFACE_IFCONF,[
SAVE_CPPFLAGS="$CPPFLAGS"

View File

@ -1262,4 +1262,8 @@ void exit_server_fault(void) NORETURN_ATTRIBUTE ;
#include "libnscd.h"
#endif
#ifndef HAVE_SA_FAMILY_T
typedef unsigned short int sa_family_t;
#endif
#endif /* _INCLUDES_H */

View File

@ -7,6 +7,17 @@
struct iface_struct {
char name[16];
struct in_addr ip;
struct in_addr netmask;
sa_family_t sa_family;
union {
struct in_addr ip;
#ifdef AF_INET6
struct in6_addr ip6;
#endif
} iface_addr;
union {
struct in_addr netmask;
#ifdef AF_INET6
struct in6_addr netmask6;
#endif
} iface_netmask;
};

View File

@ -107,8 +107,8 @@ static void interpret_interface(char *token)
/* first check if it is an interface name */
for (i=0;i<total_probed;i++) {
if (gen_fnmatch(token, probed_ifaces[i].name) == 0) {
add_interface(probed_ifaces[i].ip,
probed_ifaces[i].netmask);
add_interface(probed_ifaces[i].iface_addr.ip,
probed_ifaces[i].iface_netmask.netmask);
added = 1;
}
}
@ -119,10 +119,11 @@ static void interpret_interface(char *token)
if (!p) {
ip = *interpret_addr2(token);
for (i=0;i<total_probed;i++) {
if (ip.s_addr == probed_ifaces[i].ip.s_addr &&
!ip_equal(allones_ip, probed_ifaces[i].netmask)) {
add_interface(probed_ifaces[i].ip,
probed_ifaces[i].netmask);
if (ip.s_addr == probed_ifaces[i].iface_addr.ip.s_addr &&
!ip_equal(allones_ip,
probed_ifaces[i].iface_netmask.netmask)) {
add_interface(probed_ifaces[i].iface_addr.ip,
probed_ifaces[i].iface_netmask.netmask);
return;
}
}
@ -145,8 +146,8 @@ static void interpret_interface(char *token)
if (ip.s_addr == MKBCADDR(ip.s_addr, nmask.s_addr) ||
ip.s_addr == MKNETADDR(ip.s_addr, nmask.s_addr)) {
for (i=0;i<total_probed;i++) {
if (same_net(ip, probed_ifaces[i].ip, nmask)) {
add_interface(probed_ifaces[i].ip, nmask);
if (same_net(ip, probed_ifaces[i].iface_addr.ip, nmask)) {
add_interface(probed_ifaces[i].iface_addr.ip, nmask);
return;
}
}
@ -203,11 +204,11 @@ void load_interfaces(void)
for (i=0;i<total_probed;i++) {
if (
#if !defined(__s390__)
probed_ifaces[i].netmask.s_addr != allones_ip.s_addr &&
probed_ifaces[i].iface_netmask.netmask.s_addr != allones_ip.s_addr &&
#endif
probed_ifaces[i].ip.s_addr != loopback_ip.s_addr) {
add_interface(probed_ifaces[i].ip,
probed_ifaces[i].netmask);
probed_ifaces[i].iface_addr.ip.s_addr != loopback_ip.s_addr) {
add_interface(probed_ifaces[i].iface_addr.ip,
probed_ifaces[i].iface_netmask.netmask);
}
}
return;

View File

@ -2,6 +2,7 @@
Unix SMB/CIFS implementation.
return a list of network interfaces
Copyright (C) Andrew Tridgell 1998
Copyright (C) Jeremy Allison 2007
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -45,6 +46,10 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#ifdef HAVE_IFADDRS_H
#include <ifaddrs.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
@ -81,6 +86,60 @@
#include "interfaces.h"
/****************************************************************************
Try the "standard" getifaddrs/freeifaddrs interfaces.
Also gets IPv6 interfaces.
****************************************************************************/
#if HAVE_IFACE_GETIFADDRS
/****************************************************************************
Get the netmask address for a local interface.
****************************************************************************/
static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
{
struct ifaddrs *iflist = NULL;
struct ifaddrs *ifptr = NULL;
int total = 0;
if (getifaddrs(&ifp) < 0) {
return -1;
}
/* Loop through interfaces, looking for given IP address */
for (ifptr = iflist, total = 0;
ifptr != NULL && total < max_interfaces;
ifptr = ifptr->ifa_next) {
/* Skip ipv6 for now. */
if (ifptr->ifa_addr->sa_family != AF_INET) {
continue;
}
if (!(ifptr->ifa_flags & IFF_UP)) {
continue;
}
ifaces[total].sa_family = ifptr->ifa_addr->sa_family;
ifaces[total].iface_addr.ip =
((struct sockaddr_in *)ifptr->ifa_addr).sin_addr;
ifaces[total].iface_netmask.netmask =
((struct sockaddr_in *)ifptr->ifa_addr)->sin_addr;
strncpy(ifaces[total].name, ifptr->ifa_name,
sizeof(ifaces[total].name)-1);
ifaces[total].name[sizeof(ifaces[total].name)-1] = 0;
total++;
}
freeifaddrs(iflist);
return total;
}
#define _FOUND_IFACE_ANY
#endif /* HAVE_IFACE_GETIFADDRS */
#if HAVE_IFACE_IFCONF
/* this works for Linux 2.2, Solaris 2.5, SunOS4, HPUX 10.20, OSF1
@ -89,8 +148,9 @@
It probably also works on any BSD style system. */
/****************************************************************************
get the netmask address for a local interface
Get the netmask address for a local interface.
****************************************************************************/
static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
{
struct ifconf ifc;
@ -143,8 +203,9 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
strncpy(ifaces[total].name, iname, sizeof(ifaces[total].name)-1);
ifaces[total].name[sizeof(ifaces[total].name)-1] = 0;
ifaces[total].ip = ipaddr;
ifaces[total].netmask = nmask;
ifaces[total].sa_family = AF_INET;
ifaces[total].iface_addr.ip = ipaddr;
ifaces[total].iface_netmask.netmask = nmask;
total++;
}
@ -162,9 +223,10 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
#endif
/****************************************************************************
this should cover most of the streams based systems
Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code
This should cover most of the streams based systems.
Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code.
****************************************************************************/
static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
{
struct ifreq ifreq;
@ -239,8 +301,9 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
strncpy(ifaces[total].name, iname, sizeof(ifaces[total].name)-1);
ifaces[total].name[sizeof(ifaces[total].name)-1] = 0;
ifaces[total].ip = ipaddr;
ifaces[total].netmask = nmask;
ifaces[total].sa_family = AF_INET;
ifaces[total].iface_addr.ip = ipaddr;
ifaces[total].iface_netmask.netmask = nmask;
total++;
}
@ -255,8 +318,9 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
#ifdef HAVE_IFACE_AIX
/****************************************************************************
this one is for AIX (tested on 4.2)
This one is for AIX (tested on 4.2).
****************************************************************************/
static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
{
char buff[8192];
@ -314,8 +378,9 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
strncpy(ifaces[total].name, iname, sizeof(ifaces[total].name)-1);
ifaces[total].name[sizeof(ifaces[total].name)-1] = 0;
ifaces[total].ip = ipaddr;
ifaces[total].netmask = nmask;
ifaces[total].sa_family = AF_INET;
ifaces[total].iface_addr.ip = ipaddr;
ifaces[total].iface_netmask.netmask = nmask;
total++;
@ -335,7 +400,6 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
i -= inc;
}
close(fd);
return total;
}
@ -354,10 +418,40 @@ static int iface_comp(struct iface_struct *i1, struct iface_struct *i2)
{
int r;
r = strcmp(i1->name, i2->name);
if (r) return r;
r = ntohl(i1->ip.s_addr) - ntohl(i2->ip.s_addr);
if (r) return r;
r = ntohl(i1->netmask.s_addr) - ntohl(i2->netmask.s_addr);
if (r) {
return r;
}
r = i1->sa_family - i2->sa_family;
if (r) {
return r;
}
#ifdef AF_INET6
if (i1->sa_family == AF_INET6) {
r = memcmp(&i1->iface_addr.ip6,
&i2->iface_addr.ip6,
sizeof(struct in6_addr));
if (r) {
return r;
}
r = memcmp(&i1->iface_netmask.netmask6,
&i1->iface_netmask.netmask6,
sizeof(struct in6_addr));
if (r) {
return r;
}
}
#endif
if (i1->sa_family == AF_INET) {
r = ntohl(i1->iface_addr.ip.s_addr) -
ntohl(i2->iface_addr.ip.s_addr);
if (r) {
return r;
}
r = ntohl(i1->iface_netmask.netmask.s_addr) -
ntohl(i2->iface_netmask.netmask.s_addr);
}
return r;
}
@ -399,12 +493,21 @@ int get_interfaces(struct iface_struct *ifaces, int max_interfaces)
int i;
printf("got %d interfaces:\n", total);
if (total <= 0) exit(1);
if (total <= 0) {
exit(1);
}
for (i=0;i<total;i++) {
char addr[INET6_ADDRSTRLEN];
printf("%-10s ", ifaces[i].name);
printf("IP=%s ", inet_ntoa(ifaces[i].ip));
printf("NETMASK=%s\n", inet_ntoa(ifaces[i].netmask));
printf("IP=%s ", inet_ntop(ifaces[i].sa_family,
(const void *)&ifaces[i].iface_addr.ip,
addr,
sizeof(addr)));
printf("NETMASK=%s\n", inet_ntop(ifaces[i].sa_family,
(const void *)&ifaces[i].iface_netmask.netmask,
addr,
sizeof(addr)));
}
return 0;
}

View File

@ -330,18 +330,18 @@ ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset);
ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset);
#endif
#if !defined(HAVE_INET_PTON) || !defined(HAVE_INET_NTOP)
#include "system/network.h"
#endif
#ifndef HAVE_INET_PTON
#define inet_pton rep_inet_pton
int rep_inet_pton(int af, const char *src, void *dst);
#define inet_pton rep_inet_pton
#endif
#ifndef HAVE_INET_NTOP
#define inet_ntop rep_inet_ntop
const char *rep_inet_ntop(int af, const void *src, char *dst, socklen_t size);
#endif
#ifndef EAFNOSUPPORT
#define EAFNOSUPPORT EINVAL
#define inet_ntop rep_inet_ntop
#endif
#ifdef HAVE_LIMITS_H

View File

@ -106,4 +106,16 @@ char *rep_inet_ntoa(struct in_addr ip);
#define INADDR_NONE 0xffffffff
#endif
#ifndef EAFNOSUPPORT
#define EAFNOSUPPORT EINVAL
#endif
#ifndef INET_ADDRSTRLEN
#define INET_ADDRSTRLEN 16
#endif
#ifndef INET6_ADDRSTRLEN
#define INET6_ADDRSTRLEN 46
#endif
#endif

View File

@ -2186,7 +2186,7 @@ BOOL is_myname_or_ipaddr(const char *s)
n = get_interfaces(nics, MAX_INTERFACES);
for (i=0; i<n; i++) {
if (ip == nics[i].ip.s_addr)
if (ip == nics[i].iface_addr.ip.s_addr)
return True;
}
}

View File

@ -158,8 +158,8 @@ int get_my_ip_address( struct in_addr **ips )
}
for ( i=0; i<n; i++ ) {
if ( nics[i].ip.s_addr != loopback_ip.s_addr ) {
memcpy( &list[count++], &nics[i].ip, sizeof( struct in_addr ) );
if ( nics[i].iface_addr.ip.s_addr != loopback_ip.s_addr ) {
memcpy( &list[count++], &nics[i].iface_addr.ip, sizeof( struct in_addr ) );
}
}
*ips = list;