summaryrefslogtreecommitdiff
path: root/source4/lib/socket
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/socket')
-rw-r--r--source4/lib/socket/config.m445
-rw-r--r--source4/lib/socket/config.mk4
-rw-r--r--source4/lib/socket/connect.c11
-rw-r--r--source4/lib/socket/connect_multi.c15
-rw-r--r--source4/lib/socket/interface.c114
-rw-r--r--source4/lib/socket/netif.c334
-rw-r--r--source4/lib/socket/netif.h2
-rw-r--r--source4/lib/socket/socket.h9
-rw-r--r--source4/lib/socket/socket_ip.c4
-rw-r--r--source4/lib/socket/testsuite.c20
10 files changed, 113 insertions, 445 deletions
diff --git a/source4/lib/socket/config.m4 b/source4/lib/socket/config.m4
index 3296730c82..a713090c6d 100644
--- a/source4/lib/socket/config.m4
+++ b/source4/lib/socket/config.m4
@@ -97,50 +97,5 @@ dnl don't build ipv6 by default, unless the above test enables it, or
dnl the configure uses --with-static-modules=socket_ipv6
-##################
-# look for a method of finding the list of network interfaces
-#
-# This tests need LIBS="$NSL_LIBS $SOCKET_LIBS"
-#
-old_CFLAGS=$CFLAGS
-old_LIBS=$LIBS
-LIBS="$NSL_LIBS $SOCKET_LIBS"
-CFLAGS="$CFLAGS -Ilib/replace"
-iface=no;
-AC_CACHE_CHECK([for iface AIX],samba_cv_HAVE_IFACE_AIX,[
-AC_TRY_RUN([
-#define HAVE_IFACE_AIX 1
-#define AUTOCONF_TEST 1
-#undef _XOPEN_SOURCE_EXTENDED
-#include "${srcdir-.}/lib/socket/netif.c"],
- samba_cv_HAVE_IFACE_AIX=yes,samba_cv_HAVE_IFACE_AIX=no,samba_cv_HAVE_IFACE_AIX=cross)])
-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 ifconf],samba_cv_HAVE_IFACE_IFCONF,[
-AC_TRY_RUN([
-#define HAVE_IFACE_IFCONF 1
-#define AUTOCONF_TEST 1
-#include "${srcdir-.}/lib/socket/netif.c"],
- samba_cv_HAVE_IFACE_IFCONF=yes,samba_cv_HAVE_IFACE_IFCONF=no,samba_cv_HAVE_IFACE_IFCONF=cross)])
-if test x"$samba_cv_HAVE_IFACE_IFCONF" = x"yes"; then
- iface=yes;AC_DEFINE(HAVE_IFACE_IFCONF,1,[Whether iface ifconf is available])
-fi
-fi
-if test $iface = no; then
-AC_CACHE_CHECK([for iface ifreq],samba_cv_HAVE_IFACE_IFREQ,[
-AC_TRY_RUN([
-#define HAVE_IFACE_IFREQ 1
-#define AUTOCONF_TEST 1
-#include "${srcdir-.}/lib/socket/netif.c"],
- samba_cv_HAVE_IFACE_IFREQ=yes,samba_cv_HAVE_IFACE_IFREQ=no,samba_cv_HAVE_IFACE_IFREQ=cross)])
-if test x"$samba_cv_HAVE_IFACE_IFREQ" = x"yes"; then
- iface=yes;AC_DEFINE(HAVE_IFACE_IFREQ,1,[Whether iface ifreq is available])
-fi
-fi
-CFLAGS=$old_CFLAGS
-LIBS=$old_LIBS
diff --git a/source4/lib/socket/config.mk b/source4/lib/socket/config.mk
index d1e0bcfef5..fe64c90b81 100644
--- a/source4/lib/socket/config.mk
+++ b/source4/lib/socket/config.mk
@@ -39,9 +39,7 @@ OBJ_FILES = \
access.o \
connect_multi.o \
connect.o
-LDFLAGS = $(SUBSYSTEM_LIBCLI_RESOLVE_OUTPUT) $(SUBSYSTEM_LIBCLI_NBT_OUTPUT) $(SUBSYSTEM_NDR_NBT_OUTPUT) $(LIBRARY_NDR_SVCCTL_OUTPUT)
PUBLIC_DEPENDENCIES = LIBTALLOC
-PRIVATE_DEPENDENCIES = SOCKET_WRAPPER LIBCLI_COMPOSITE
-#LIBCLI_RESOLVE
+PRIVATE_DEPENDENCIES = SOCKET_WRAPPER LIBCLI_COMPOSITE LIBCLI_RESOLVE
# End SUBSYSTEM SOCKET
################################################
diff --git a/source4/lib/socket/connect.c b/source4/lib/socket/connect.c
index cad8967dab..773bf41873 100644
--- a/source4/lib/socket/connect.c
+++ b/source4/lib/socket/connect.c
@@ -85,7 +85,7 @@ struct composite_context *socket_connect_send(struct socket_context *sock,
struct socket_address *my_address,
struct socket_address *server_address,
uint32_t flags,
- const char **name_resolve_order,
+ struct resolve_context *resolve_ctx,
struct event_context *event_ctx)
{
struct composite_context *result;
@@ -123,12 +123,11 @@ struct composite_context *socket_connect_send(struct socket_context *sock,
set_blocking(socket_get_fd(sock), false);
- if (server_address->addr && strcmp(sock->backend_name, "ipv4") == 0) {
+ if (resolve_ctx != NULL && server_address->addr && strcmp(sock->backend_name, "ipv4") == 0) {
struct nbt_name name;
struct composite_context *creq;
make_nbt_name_client(&name, server_address->addr);
- creq = resolve_name_send(&name, result->event_ctx,
- lp_name_resolve_order(global_loadparm));
+ creq = resolve_name_send(resolve_ctx, &name, result->event_ctx);
if (composite_nomem(creq, result)) return result;
composite_continue(result, creq, continue_resolve_name, result);
return result;
@@ -207,11 +206,11 @@ NTSTATUS socket_connect_recv(struct composite_context *result)
NTSTATUS socket_connect_ev(struct socket_context *sock,
struct socket_address *my_address,
struct socket_address *server_address,
- uint32_t flags, const char **name_resolve_order,
+ uint32_t flags, struct resolve_context *resolve_ctx,
struct event_context *ev)
{
struct composite_context *ctx;
ctx = socket_connect_send(sock, my_address,
- server_address, flags, name_resolve_order, ev);
+ server_address, flags, resolve_ctx, ev);
return socket_connect_recv(ctx);
}
diff --git a/source4/lib/socket/connect_multi.c b/source4/lib/socket/connect_multi.c
index 58ab673965..2f736a4b05 100644
--- a/source4/lib/socket/connect_multi.c
+++ b/source4/lib/socket/connect_multi.c
@@ -38,7 +38,7 @@ struct connect_multi_state {
int num_ports;
uint16_t *ports;
- const char **name_resolve_order;
+ struct resolve_context *resolve_ctx;
struct socket_context *sock;
uint16_t result_port;
@@ -70,7 +70,7 @@ _PUBLIC_ struct composite_context *socket_connect_multi_send(
const char *server_address,
int num_server_ports,
uint16_t *server_ports,
- const char **name_resolve_order,
+ struct resolve_context *resolve_ctx,
struct event_context *event_ctx)
{
struct composite_context *result;
@@ -90,7 +90,7 @@ _PUBLIC_ struct composite_context *socket_connect_multi_send(
if (composite_nomem(multi->server_address, result)) goto failed;
multi->num_ports = num_server_ports;
- multi->name_resolve_order = str_list_copy(multi, name_resolve_order);
+ multi->resolve_ctx = talloc_reference(multi, resolve_ctx);
multi->ports = talloc_array(multi, uint16_t, multi->num_ports);
if (composite_nomem(multi->ports, result)) goto failed;
@@ -107,8 +107,7 @@ _PUBLIC_ struct composite_context *socket_connect_multi_send(
struct nbt_name name;
struct composite_context *creq;
make_nbt_name_client(&name, server_address);
- creq = resolve_name_send(&name, result->event_ctx,
- name_resolve_order);
+ creq = resolve_name_send(resolve_ctx, &name, result->event_ctx);
if (composite_nomem(creq, result)) goto failed;
composite_continue(result, creq, continue_resolve_name, result);
return result;
@@ -161,7 +160,7 @@ static void connect_multi_next_socket(struct composite_context *result)
talloc_steal(state, state->sock);
creq = socket_connect_send(state->sock, NULL,
- state->addr, 0, multi->name_resolve_order,
+ state->addr, 0, multi->resolve_ctx,
result->event_ctx);
if (composite_nomem(creq, result)) return;
talloc_steal(state, creq);
@@ -269,7 +268,7 @@ _PUBLIC_ NTSTATUS socket_connect_multi_recv(struct composite_context *ctx,
NTSTATUS socket_connect_multi(TALLOC_CTX *mem_ctx,
const char *server_address,
int num_server_ports, uint16_t *server_ports,
- const char **name_resolve_order,
+ struct resolve_context *resolve_ctx,
struct event_context *event_ctx,
struct socket_context **result,
uint16_t *result_port)
@@ -277,7 +276,7 @@ NTSTATUS socket_connect_multi(TALLOC_CTX *mem_ctx,
struct composite_context *ctx =
socket_connect_multi_send(mem_ctx, server_address,
num_server_ports, server_ports,
- name_resolve_order,
+ resolve_ctx,
event_ctx);
return socket_connect_multi_recv(ctx, mem_ctx, result, result_port);
}
diff --git a/source4/lib/socket/interface.c b/source4/lib/socket/interface.c
index 79c5673022..c327f02bbd 100644
--- a/source4/lib/socket/interface.c
+++ b/source4/lib/socket/interface.c
@@ -35,8 +35,6 @@ struct interface {
const char *nmask_s;
};
-static struct interface *local_interfaces;
-
#define ALLONES ((uint32_t)0xFFFFFFFF)
/*
address construction based on a patch from fred@datalync.com
@@ -47,12 +45,13 @@ static struct interface *local_interfaces;
/****************************************************************************
Try and find an interface that matches an ip. If we cannot, return NULL
**************************************************************************/
-static struct interface *iface_find(struct in_addr ip, bool CheckMask)
+static struct interface *iface_find(struct interface *interfaces,
+ struct in_addr ip, bool CheckMask)
{
struct interface *i;
- if (is_zero_ip(ip)) return local_interfaces;
+ if (is_zero_ip(ip)) return interfaces;
- for (i=local_interfaces;i;i=i->next)
+ for (i=interfaces;i;i=i->next)
if (CheckMask) {
if (same_net(i->ip,ip,i->nmask)) return i;
} else if (i->ip.s_addr == ip.s_addr) return i;
@@ -64,18 +63,19 @@ static struct interface *iface_find(struct in_addr ip, bool CheckMask)
/****************************************************************************
add an interface to the linked list of interfaces
****************************************************************************/
-static void add_interface(struct in_addr ip, struct in_addr nmask)
+static void add_interface(TALLOC_CTX *mem_ctx, struct in_addr ip, struct in_addr nmask, struct interface **interfaces)
{
struct interface *iface;
struct in_addr bcast;
- if (iface_find(ip, false)) {
+ if (iface_find(*interfaces, ip, false)) {
DEBUG(3,("not adding duplicate interface %s\n",inet_ntoa(ip)));
return;
}
- iface = talloc(local_interfaces == NULL ? talloc_autofree_context() : local_interfaces, struct interface);
- if (!iface) return;
+ iface = talloc(*interfaces == NULL ? mem_ctx : *interfaces, struct interface);
+ if (iface == NULL)
+ return;
ZERO_STRUCTPN(iface);
@@ -92,7 +92,7 @@ static void add_interface(struct in_addr ip, struct in_addr nmask)
iface->bcast_s = talloc_strdup(iface, inet_ntoa(bcast));
}
- DLIST_ADD_END(local_interfaces, iface, struct interface *);
+ DLIST_ADD_END(*interfaces, iface, struct interface *);
DEBUG(2,("added interface ip=%s nmask=%s\n", iface->ip_s, iface->nmask_s));
}
@@ -110,12 +110,15 @@ This handles the following different forms:
4) ip/mask
5) bcast/mask
**/
-static void interpret_interface(const char *token,
+static void interpret_interface(TALLOC_CTX *mem_ctx,
+ const char *token,
struct iface_struct *probed_ifaces,
- int total_probed)
+ int total_probed,
+ struct interface **local_interfaces)
{
struct in_addr ip, nmask;
char *p;
+ char *address;
int i, added=0;
ip.s_addr = 0;
@@ -124,8 +127,9 @@ static void interpret_interface(const 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(mem_ctx, probed_ifaces[i].ip,
+ probed_ifaces[i].netmask,
+ local_interfaces);
added = 1;
}
}
@@ -141,8 +145,9 @@ static void interpret_interface(const char *token,
ip.s_addr = interpret_addr2(token).s_addr;
for (i=0;i<total_probed;i++) {
if (ip.s_addr == probed_ifaces[i].ip.s_addr) {
- add_interface(probed_ifaces[i].ip,
- probed_ifaces[i].netmask);
+ add_interface(mem_ctx, probed_ifaces[i].ip,
+ probed_ifaces[i].netmask,
+ local_interfaces);
return;
}
}
@@ -150,10 +155,13 @@ static void interpret_interface(const char *token,
return;
}
+ address = talloc_strdup(mem_ctx, token);
+ p = strchr_m(address,'/');
+
/* parse it into an IP address/netmasklength pair */
*p++ = 0;
- ip.s_addr = interpret_addr2(token).s_addr;
+ ip.s_addr = interpret_addr2(address).s_addr;
if (strlen(p) > 2) {
nmask.s_addr = interpret_addr2(p).s_addr;
@@ -166,22 +174,26 @@ static void interpret_interface(const char *token,
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);
+ add_interface(mem_ctx, probed_ifaces[i].ip, nmask,
+ local_interfaces);
+ talloc_free(address);
return;
}
}
- DEBUG(2,("Can't determine ip for broadcast address %s\n", token));
+ DEBUG(2,("Can't determine ip for broadcast address %s\n", address));
+ talloc_free(address);
return;
}
- add_interface(ip, nmask);
+ add_interface(mem_ctx, ip, nmask, local_interfaces);
+ talloc_free(address);
}
/**
load the list of network interfaces
**/
-static void load_interfaces(const char **interfaces)
+void load_interfaces(TALLOC_CTX *mem_ctx, const char **interfaces, struct interface **local_interfaces)
{
const char **ptr = interfaces;
int i;
@@ -189,9 +201,7 @@ static void load_interfaces(const char **interfaces)
struct in_addr loopback_ip;
int total_probed;
- if (local_interfaces != NULL) {
- return;
- }
+ *local_interfaces = NULL;
loopback_ip = interpret_addr2("127.0.0.1");
@@ -206,43 +216,31 @@ static void load_interfaces(const char **interfaces)
}
for (i=0;i<total_probed;i++) {
if (ifaces[i].ip.s_addr != loopback_ip.s_addr) {
- add_interface(ifaces[i].ip,
- ifaces[i].netmask);
+ add_interface(mem_ctx, ifaces[i].ip,
+ ifaces[i].netmask, local_interfaces);
}
}
}
while (ptr && *ptr) {
- interpret_interface(*ptr, ifaces, total_probed);
+ interpret_interface(mem_ctx, *ptr, ifaces, total_probed, local_interfaces);
ptr++;
}
- if (!local_interfaces) {
+ if (!*local_interfaces) {
DEBUG(0,("WARNING: no network interfaces found\n"));
}
}
-
-/**
- unload the interfaces list, so it can be reloaded when needed
-*/
-void unload_interfaces(void)
-{
- talloc_free(local_interfaces);
- local_interfaces = NULL;
-}
-
/**
how many interfaces do we have
**/
-int iface_count(struct loadparm_context *lp_ctx)
+int iface_count(struct interface *ifaces)
{
int ret = 0;
struct interface *i;
- load_interfaces(lp_interfaces(lp_ctx));
-
- for (i=local_interfaces;i;i=i->next)
+ for (i=ifaces;i;i=i->next)
ret++;
return ret;
}
@@ -250,13 +248,11 @@ int iface_count(struct loadparm_context *lp_ctx)
/**
return IP of the Nth interface
**/
-const char *iface_n_ip(struct loadparm_context *lp_ctx, int n)
+const char *iface_n_ip(struct interface *ifaces, int n)
{
struct interface *i;
- load_interfaces(lp_interfaces(lp_ctx));
-
- for (i=local_interfaces;i && n;i=i->next)
+ for (i=ifaces;i && n;i=i->next)
n--;
if (i) {
@@ -268,13 +264,11 @@ const char *iface_n_ip(struct loadparm_context *lp_ctx, int n)
/**
return bcast of the Nth interface
**/
-const char *iface_n_bcast(struct loadparm_context *lp_ctx, int n)
+const char *iface_n_bcast(struct interface *ifaces, int n)
{
struct interface *i;
- load_interfaces(lp_interfaces(lp_ctx));
-
- for (i=local_interfaces;i && n;i=i->next)
+ for (i=ifaces;i && n;i=i->next)
n--;
if (i) {
@@ -286,13 +280,11 @@ const char *iface_n_bcast(struct loadparm_context *lp_ctx, int n)
/**
return netmask of the Nth interface
**/
-const char *iface_n_netmask(struct loadparm_context *lp_ctx, int n)
+const char *iface_n_netmask(struct interface *ifaces, int n)
{
struct interface *i;
- load_interfaces(lp_interfaces(lp_ctx));
-
- for (i=local_interfaces;i && n;i=i->next)
+ for (i=ifaces;i && n;i=i->next)
n--;
if (i) {
@@ -305,32 +297,28 @@ const char *iface_n_netmask(struct loadparm_context *lp_ctx, int n)
return the local IP address that best matches a destination IP, or
our first interface if none match
*/
-const char *iface_best_ip(struct loadparm_context *lp_ctx, const char *dest)
+const char *iface_best_ip(struct interface *ifaces, const char *dest)
{
struct interface *iface;
struct in_addr ip;
- load_interfaces(lp_interfaces(lp_ctx));
-
ip.s_addr = interpret_addr(dest);
- iface = iface_find(ip, true);
+ iface = iface_find(ifaces, ip, true);
if (iface) {
return iface->ip_s;
}
- return iface_n_ip(lp_ctx, 0);
+ return iface_n_ip(ifaces, 0);
}
/**
return true if an IP is one one of our local networks
*/
-bool iface_is_local(struct loadparm_context *lp_ctx, const char *dest)
+bool iface_is_local(struct interface *ifaces, const char *dest)
{
struct in_addr ip;
- load_interfaces(lp_interfaces(lp_ctx));
-
ip.s_addr = interpret_addr(dest);
- if (iface_find(ip, true)) {
+ if (iface_find(ifaces, ip, true)) {
return true;
}
return false;
diff --git a/source4/lib/socket/netif.c b/source4/lib/socket/netif.c
index c9f43e811a..bf410af441 100644
--- a/source4/lib/socket/netif.c
+++ b/source4/lib/socket/netif.c
@@ -2,6 +2,8 @@
Unix SMB/CIFS implementation.
return a list of network interfaces
Copyright (C) Andrew Tridgell 1998
+ Copyright (C) Jeremy Allison 2007
+ Copyright (C) Jelmer Vernooij 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
@@ -29,327 +31,63 @@
*/
-#ifndef AUTOCONF_TEST
#include "includes.h"
-#endif
-
-#include <unistd.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <netdb.h>
-#include <sys/ioctl.h>
-#include <netdb.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#ifndef SIOCGIFCONF
-#ifdef HAVE_SYS_SOCKIO_H
-#include <sys/sockio.h>
-#endif
-#endif
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-
-#ifdef __COMPAR_FN_T
-#define QSORT_CAST (__compar_fn_t)
-#endif
-
-#ifndef QSORT_CAST
-#define QSORT_CAST (int (*)(const void *, const void *))
-#endif
-
-#ifdef HAVE_NET_IF_H
-#include <net/if.h>
-#endif
-
+#include "system/network.h"
#include "netif.h"
-#if HAVE_IFACE_IFCONF
-
-/* this works for Linux 2.2, Solaris 2.5, SunOS4, HPUX 10.20, OSF1
- V4.0, Ultrix 4.4, SCO Unix 3.2, IRIX 6.4 and FreeBSD 3.2.
-
- It probably also works on any BSD style system. */
-
/****************************************************************************
- get the netmask address for a local interface
+ Try the "standard" getifaddrs/freeifaddrs interfaces.
+ Also gets IPv6 interfaces.
****************************************************************************/
-static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
-{
- struct ifconf ifc;
- char buff[8192];
- int fd, i, n;
- struct ifreq *ifr=NULL;
- int total = 0;
- struct in_addr ipaddr;
- struct in_addr nmask;
- char *iname;
-
- 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 */
- for (i=n-1;i>=0 && total < max_interfaces;i--) {
- if (ioctl(fd, SIOCGIFADDR, &ifr[i]) != 0) {
- continue;
- }
-
- iname = ifr[i].ifr_name;
- ipaddr = (*(struct sockaddr_in *)&ifr[i].ifr_addr).sin_addr;
-
- if (ioctl(fd, SIOCGIFFLAGS, &ifr[i]) != 0) {
- continue;
- }
-
- if (!(ifr[i].ifr_flags & IFF_UP)) {
- continue;
- }
-
- 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;
- total++;
- }
-
- close(fd);
-
- return total;
-}
-
-#define _FOUND_IFACE_ANY
-#endif /* HAVE_IFACE_IFCONF */
-#ifdef HAVE_IFACE_IFREQ
-
-#ifndef I_STR
-#include <sys/stropts.h>
-#endif
/****************************************************************************
-this should cover most of the streams based systems
-Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code
+ Get the netmask address for a local interface.
****************************************************************************/
+
static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
{
- struct ifreq ifreq;
- struct strioctl strioctl;
- char buff[8192];
- int fd, i, n;
- struct ifreq *ifr=NULL;
+ struct ifaddrs *iflist = NULL;
+ struct ifaddrs *ifptr = NULL;
int total = 0;
- struct in_addr ipaddr;
- struct in_addr nmask;
- char *iname;
- if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
+ if (getifaddrs(&iflist) < 0) {
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 */
- n = strioctl.ic_len / sizeof(struct ifreq);
- /* we will assume that the kernel returns the length as an int
- 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));
- } else {
- ifr = (struct ifreq *)buff;
- }
+ /* Loop through interfaces, looking for given IP address */
+ for (ifptr = iflist, total = 0;
+ ifptr != NULL && total < max_interfaces;
+ ifptr = ifptr->ifa_next) {
- /* Loop through interfaces */
+ memset(&ifaces[total], '\0', sizeof(ifaces[total]));
- 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)) {
+ if (!ifptr->ifa_addr || !ifptr->ifa_netmask) {
continue;
}
- strioctl.ic_cmd = SIOCGIFADDR;
- strioctl.ic_dp = (char *)&ifreq;
- strioctl.ic_len = sizeof(struct ifreq);
- if (ioctl(fd, I_STR, &strioctl) != 0) {
+ /* Check the interface is up. */
+ if (!(ifptr->ifa_flags & IFF_UP)) {
continue;
}
- ipaddr = (*(struct sockaddr_in *) &ifreq.ifr_addr).sin_addr;
- iname = ifreq.ifr_name;
-
- strioctl.ic_cmd = SIOCGIFNETMASK;
- strioctl.ic_dp = (char *)&ifreq;
- strioctl.ic_len = sizeof(struct ifreq);
- if (ioctl(fd, I_STR, &strioctl) != 0) {
+ /* We don't support IPv6 *yet* */
+ if (ifptr->ifa_addr->sa_family != AF_INET) {
continue;
}
- nmask = ((struct sockaddr_in *)&ifreq.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].ip = ((struct sockaddr_in *)ifptr->ifa_addr)->sin_addr;
+ ifaces[total].netmask = ((struct sockaddr_in *)ifptr->ifa_netmask)->sin_addr;
+ strlcpy(ifaces[total].name, ifptr->ifa_name,
+ sizeof(ifaces[total].name));
total++;
}
- close(fd);
+ freeifaddrs(iflist);
return total;
}
-#define _FOUND_IFACE_ANY
-#endif /* HAVE_IFACE_IFREQ */
-#ifdef HAVE_IFACE_AIX
-
-/****************************************************************************
-this one is for AIX (tested on 4.2)
-****************************************************************************/
-static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
-{
- char buff[8192];
- int fd, i;
- struct ifconf ifc;
- struct ifreq *ifr=NULL;
- struct in_addr ipaddr;
- struct in_addr nmask;
- char *iname;
- int total = 0;
-
- 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;
-
- /* Loop through interfaces */
- i = ifc.ifc_len;
-
- while (i > 0 && total < max_interfaces) {
- uint_t inc;
-
- inc = ifr->ifr_addr.sa_len;
-
- if (ioctl(fd, SIOCGIFADDR, ifr) != 0) {
- goto next;
- }
-
- ipaddr = (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr;
- iname = ifr->ifr_name;
-
- if (ioctl(fd, SIOCGIFFLAGS, ifr) != 0) {
- goto next;
- }
-
- if (!(ifr->ifr_flags & IFF_UP)) {
- goto next;
- }
-
- if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) {
- goto next;
- }
-
- nmask = ((struct sockaddr_in *)&ifr->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;
-
- total++;
-
- next:
- /*
- * Patch from Archie Cobbs (archie@whistle.com). The
- * addresses in the SIOCGIFCONF interface list have a
- * minimum size. Usually this doesn't matter, but if
- * your machine has tunnel interfaces, etc. that have
- * a zero length "link address", this does matter. */
-
- if (inc < sizeof(ifr->ifr_addr))
- inc = sizeof(ifr->ifr_addr);
- inc += IFNAMSIZ;
-
- ifr = (struct ifreq*) (((char*) ifr) + inc);
- i -= inc;
- }
-
-
- close(fd);
- return total;
-}
-
-#define _FOUND_IFACE_ANY
-#endif /* HAVE_IFACE_AIX */
-#ifndef _FOUND_IFACE_ANY
-static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
-{
- return -1;
-}
-#endif
-
-
static int iface_comp(struct iface_struct *i1, struct iface_struct *i2)
{
int r;
@@ -386,25 +124,3 @@ int get_interfaces(struct iface_struct *ifaces, int max_interfaces)
return total;
}
-
-
-#ifdef AUTOCONF_TEST
-/* this is the autoconf driver to test get_interfaces() */
-
- int main()
-{
- struct iface_struct ifaces[MAX_INTERFACES];
- int total = get_interfaces(ifaces, MAX_INTERFACES);
- int i;
-
- printf("got %d interfaces:\n", total);
- if (total <= 0) exit(1);
-
- for (i=0;i<total;i++) {
- printf("%-10s ", ifaces[i].name);
- printf("IP=%s ", inet_ntoa(ifaces[i].ip));
- printf("NETMASK=%s\n", inet_ntoa(ifaces[i].netmask));
- }
- return 0;
-}
-#endif
diff --git a/source4/lib/socket/netif.h b/source4/lib/socket/netif.h
index 4855f4bd73..417c6e074f 100644
--- a/source4/lib/socket/netif.h
+++ b/source4/lib/socket/netif.h
@@ -27,6 +27,8 @@ struct iface_struct {
struct in_addr netmask;
};
+struct interface;
+
#define MAX_INTERFACES 128
#ifndef AUTOCONF_TEST
diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h
index 24bc5f1aac..4baa0cfbb1 100644
--- a/source4/lib/socket/socket.h
+++ b/source4/lib/socket/socket.h
@@ -126,6 +126,7 @@ struct socket_context {
int family;
};
+struct resolve_context;
/* prototypes */
NTSTATUS socket_create_with_ops(TALLOC_CTX *mem_ctx, const struct socket_ops *ops,
@@ -178,21 +179,21 @@ struct composite_context *socket_connect_send(struct socket_context *sock,
struct socket_address *my_address,
struct socket_address *server_address,
uint32_t flags,
- const char **name_resolve_order,
+ struct resolve_context *resolve_ctx,
struct event_context *event_ctx);
NTSTATUS socket_connect_recv(struct composite_context *ctx);
NTSTATUS socket_connect_ev(struct socket_context *sock,
struct socket_address *my_address,
struct socket_address *server_address,
uint32_t flags,
- const char **name_resolve_order,
+ struct resolve_context *resolve_ctx,
struct event_context *ev);
struct composite_context *socket_connect_multi_send(TALLOC_CTX *mem_ctx,
const char *server_address,
int num_server_ports,
uint16_t *server_ports,
- const char **name_resolve_order,
+ struct resolve_context *resolve_ctx,
struct event_context *event_ctx);
NTSTATUS socket_connect_multi_recv(struct composite_context *ctx,
TALLOC_CTX *mem_ctx,
@@ -200,7 +201,7 @@ NTSTATUS socket_connect_multi_recv(struct composite_context *ctx,
uint16_t *port);
NTSTATUS socket_connect_multi(TALLOC_CTX *mem_ctx, const char *server_address,
int num_server_ports, uint16_t *server_ports,
- const char **name_resolve_order,
+ struct resolve_context *resolve_ctx,
struct event_context *event_ctx,
struct socket_context **result,
uint16_t *port);
diff --git a/source4/lib/socket/socket_ip.c b/source4/lib/socket/socket_ip.c
index e3676ad71a..e61b6d82fc 100644
--- a/source4/lib/socket/socket_ip.c
+++ b/source4/lib/socket/socket_ip.c
@@ -130,6 +130,8 @@ static NTSTATUS ipv4_connect(struct socket_context *sock,
if (!srv_ip.s_addr) {
return NT_STATUS_BAD_NETWORK_NAME;
}
+
+ SMB_ASSERT(srv_address->port != 0);
ZERO_STRUCT(srv_addr);
#ifdef HAVE_SOCK_SIN_LEN
@@ -356,6 +358,8 @@ static NTSTATUS ipv4_sendto(struct socket_context *sock,
} else {
struct sockaddr_in srv_addr;
struct in_addr addr;
+
+ SMB_ASSERT(dest_addr->port != 0);
ZERO_STRUCT(srv_addr);
#ifdef HAVE_SOCK_SIN_LEN
diff --git a/source4/lib/socket/testsuite.c b/source4/lib/socket/testsuite.c
index dea740dbc8..6d4d81a884 100644
--- a/source4/lib/socket/testsuite.c
+++ b/source4/lib/socket/testsuite.c
@@ -26,8 +26,9 @@
#include "lib/socket/netif.h"
#include "torture/torture.h"
#include "param/param.h"
+#include "libcli/resolve/resolve.h"
-/*
+/**
basic testing of udp routines
*/
static bool test_udp(struct torture_context *tctx)
@@ -39,6 +40,9 @@ static bool test_udp(struct torture_context *tctx)
DATA_BLOB blob, blob2;
size_t sent, nread;
TALLOC_CTX *mem_ctx = tctx;
+ struct interface *ifaces;
+
+ load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces);
status = socket_create("ip", SOCKET_TYPE_DGRAM, &sock1, 0);
torture_assert_ntstatus_ok(tctx, status, "creating DGRAM IP socket 1");
@@ -49,7 +53,7 @@ static bool test_udp(struct torture_context *tctx)
talloc_steal(mem_ctx, sock2);
localhost = socket_address_from_strings(sock1, sock1->backend_name,
- iface_best_ip(tctx->lp_ctx, "127.0.0.1"), 0);
+ iface_best_ip(ifaces, "127.0.0.1"), 0);
torture_assert(tctx, localhost, "Localhost not found");
@@ -58,10 +62,10 @@ static bool test_udp(struct torture_context *tctx)
srv_addr = socket_get_my_addr(sock1, mem_ctx);
torture_assert(tctx, srv_addr != NULL &&
- strcmp(srv_addr->addr, iface_best_ip(tctx->lp_ctx, "127.0.0.1")) == 0,
+ strcmp(srv_addr->addr, iface_best_ip(ifaces, "127.0.0.1")) == 0,
talloc_asprintf(tctx,
"Expected server address of %s but got %s",
- iface_best_ip(tctx->lp_ctx, "127.0.0.1"), srv_addr ? srv_addr->addr : NULL));
+ iface_best_ip(ifaces, "127.0.0.1"), srv_addr ? srv_addr->addr : NULL));
torture_comment(tctx, "server port is %d\n", srv_addr->port);
@@ -121,6 +125,7 @@ static bool test_tcp(struct torture_context *tctx)
size_t sent, nread;
TALLOC_CTX *mem_ctx = tctx;
struct event_context *ev = event_context_init(mem_ctx);
+ struct interface *ifaces;
status = socket_create("ip", SOCKET_TYPE_STREAM, &sock1, 0);
torture_assert_ntstatus_ok(tctx, status, "creating IP stream socket 1");
@@ -130,8 +135,9 @@ static bool test_tcp(struct torture_context *tctx)
torture_assert_ntstatus_ok(tctx, status, "creating IP stream socket 1");
talloc_steal(mem_ctx, sock2);
+ load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces);
localhost = socket_address_from_strings(sock1, sock1->backend_name,
- iface_best_ip(tctx->lp_ctx, "127.0.0.1"), 0);
+ iface_best_ip(ifaces, "127.0.0.1"), 0);
torture_assert(tctx, localhost, "Localhost not found");
status = socket_listen(sock1, localhost, 0, 0);
@@ -141,12 +147,12 @@ static bool test_tcp(struct torture_context *tctx)
torture_assert(tctx, srv_addr && srv_addr->addr,
"Unexpected socket_get_my_addr NULL\n");
- torture_assert_str_equal(tctx, srv_addr->addr, iface_best_ip(tctx->lp_ctx, "127.0.0.1"),
+ torture_assert_str_equal(tctx, srv_addr->addr, iface_best_ip(ifaces, "127.0.0.1"),
"Unexpected server address");
torture_comment(tctx, "server port is %d\n", srv_addr->port);
- status = socket_connect_ev(sock2, NULL, srv_addr, 0, lp_name_resolve_order(tctx->lp_ctx), ev);
+ status = socket_connect_ev(sock2, NULL, srv_addr, 0, NULL, ev);
torture_assert_ntstatus_ok(tctx, status, "connect() on socket 2");
status = socket_accept(sock1, &sock3);