summaryrefslogtreecommitdiff
path: root/source3/lib
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2007-10-02 19:27:25 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:31:06 -0500
commit3fbd1ae54ced2eb889a8fe0a6ea32dfd8175f941 (patch)
treea39948ec0633b6bed73df92ddc0c94dc4c607f12 /source3/lib
parent5c5acae0eee9fb113ac6817eb8a164551a1cb117 (diff)
downloadsamba-3fbd1ae54ced2eb889a8fe0a6ea32dfd8175f941.tar.gz
samba-3fbd1ae54ced2eb889a8fe0a6ea32dfd8175f941.tar.bz2
samba-3fbd1ae54ced2eb889a8fe0a6ea32dfd8175f941.zip
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 327875182c9219aeba687e10aaea93546d9a70ea)
Diffstat (limited to 'source3/lib')
-rw-r--r--source3/lib/interface.c27
-rw-r--r--source3/lib/interfaces.c173
-rw-r--r--source3/lib/replace/replace.h12
-rw-r--r--source3/lib/replace/system/network.h12
-rw-r--r--source3/lib/util.c26
5 files changed, 183 insertions, 67 deletions
diff --git a/source3/lib/interface.c b/source3/lib/interface.c
index 29ed15a0c2..c187583923 100644
--- a/source3/lib/interface.c
+++ b/source3/lib/interface.c
@@ -103,12 +103,12 @@ static void interpret_interface(char *token)
zero_ip(&ip);
zero_ip(&nmask);
-
+
/* 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;
diff --git a/source3/lib/interfaces.c b/source3/lib/interfaces.c
index 2a232226b8..07abf4b1c6 100644
--- a/source3/lib/interfaces.c
+++ b/source3/lib/interfaces.c
@@ -1,18 +1,19 @@
-/*
+/*
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
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -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,10 +148,11 @@
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;
char buff[8192];
int fd, i, n;
@@ -105,17 +165,17 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
return -1;
}
-
+
ifc.ifc_len = sizeof(buff);
ifc.ifc_buf = buff;
if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
close(fd);
return -1;
- }
+ }
ifr = ifc.ifc_req;
-
+
n = ifc.ifc_len / sizeof(struct ifreq);
/* Loop through interfaces, looking for given IP address */
@@ -129,7 +189,7 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
if (ioctl(fd, SIOCGIFFLAGS, &ifr[i]) != 0) {
continue;
- }
+ }
if (!(ifr[i].ifr_flags & IFF_UP)) {
continue;
@@ -137,21 +197,22 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
if (ioctl(fd, SIOCGIFNETMASK, &ifr[i]) != 0) {
continue;
- }
+ }
nmask = ((struct sockaddr_in *)&ifr[i].ifr_addr)->sin_addr;
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++;
}
close(fd);
return total;
-}
+}
#define _FOUND_IFACE_ANY
#endif /* HAVE_IFACE_IFCONF */
@@ -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;
@@ -180,14 +242,14 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
return -1;
}
-
+
strioctl.ic_cmd = SIOCGIFCONF;
strioctl.ic_dp = buff;
strioctl.ic_len = sizeof(buff);
if (ioctl(fd, I_STR, &strioctl) < 0) {
close(fd);
return -1;
- }
+ }
/* we can ignore the possible sizeof(int) here as the resulting
number of interface structures won't change */
@@ -197,23 +259,23 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
at the start of the buffer if the offered size is a
multiple of the structure size plus an int */
if (n*sizeof(struct ifreq) + sizeof(int) == strioctl.ic_len) {
- ifr = (struct ifreq *)(buff + sizeof(int));
+ ifr = (struct ifreq *)(buff + sizeof(int));
} else {
- ifr = (struct ifreq *)buff;
+ ifr = (struct ifreq *)buff;
}
/* Loop through interfaces */
for (i = 0; i<n && total < max_interfaces; i++) {
ifreq = ifr[i];
-
+
strioctl.ic_cmd = SIOCGIFFLAGS;
strioctl.ic_dp = (char *)&ifreq;
strioctl.ic_len = sizeof(struct ifreq);
if (ioctl(fd, I_STR, &strioctl) != 0) {
continue;
}
-
+
if (!(ifreq.ifr_flags & IFF_UP)) {
continue;
}
@@ -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++;
@@ -334,7 +399,6 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
ifr = (struct ifreq*) (((char*) ifr) + inc);
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;
}
diff --git a/source3/lib/replace/replace.h b/source3/lib/replace/replace.h
index 907d9b0086..27265e35c4 100644
--- a/source3/lib/replace/replace.h
+++ b/source3/lib/replace/replace.h
@@ -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
diff --git a/source3/lib/replace/system/network.h b/source3/lib/replace/system/network.h
index 7469040b28..70c3ec711c 100644
--- a/source3/lib/replace/system/network.h
+++ b/source3/lib/replace/system/network.h
@@ -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
diff --git a/source3/lib/util.c b/source3/lib/util.c
index 67c5f8d38f..6c86376e57 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -2138,7 +2138,7 @@ BOOL is_myname_or_ipaddr(const char *s)
/* optimize for the common case */
- if (strequal(servername, global_myname()))
+ if (strequal(servername, global_myname()))
return True;
/* check for an alias */
@@ -2148,10 +2148,10 @@ BOOL is_myname_or_ipaddr(const char *s)
/* check for loopback */
- if (strequal(servername, "127.0.0.1"))
+ if (strequal(servername, "127.0.0.1"))
return True;
- if (strequal(servername, "localhost"))
+ if (strequal(servername, "localhost"))
return True;
/* maybe it's my dns name */
@@ -2159,7 +2159,7 @@ BOOL is_myname_or_ipaddr(const char *s)
if ( get_mydnsfullname( dnsname ) )
if ( strequal( servername, dnsname ) )
return True;
-
+
/* handle possible CNAME records */
if ( !is_ipaddress( servername ) ) {
@@ -2171,25 +2171,25 @@ BOOL is_myname_or_ipaddr(const char *s)
putip( (char*)&return_ip, (char*)hp->h_addr );
fstrcpy( name, inet_ntoa( return_ip ) );
servername = name;
- }
+ }
}
-
+
/* maybe its an IP address? */
if (is_ipaddress(servername)) {
struct iface_struct nics[MAX_INTERFACES];
int i, n;
uint32 ip;
-
+
ip = interpret_addr(servername);
if ((ip==0) || (ip==0xffffffff))
return False;
-
+
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;
}
- }
+ }
/* no match */
return False;
@@ -2217,14 +2217,14 @@ BOOL is_myworkgroup(const char *s)
WinXP => "Windows 2002 5.1"
WinXP 64bit => "Windows XP 5.2"
Win2k => "Windows 2000 5.0"
- NT4 => "Windows NT 4.0"
+ NT4 => "Windows NT 4.0"
Win9x => "Windows 4.0"
- Windows 2003 doesn't set the native lan manager string but
+ Windows 2003 doesn't set the native lan manager string but
they do set the domain to "Windows 2003 5.2" (probably a bug).
********************************************************************/
void ra_lanman_string( const char *native_lanman )
-{
+{
if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
set_remote_arch( RA_WINXP );
else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )