diff options
Diffstat (limited to 'source4/lib/socket')
-rw-r--r-- | source4/lib/socket/config.m4 | 45 | ||||
-rw-r--r-- | source4/lib/socket/config.mk | 4 | ||||
-rw-r--r-- | source4/lib/socket/connect.c | 11 | ||||
-rw-r--r-- | source4/lib/socket/connect_multi.c | 15 | ||||
-rw-r--r-- | source4/lib/socket/interface.c | 114 | ||||
-rw-r--r-- | source4/lib/socket/netif.c | 334 | ||||
-rw-r--r-- | source4/lib/socket/netif.h | 2 | ||||
-rw-r--r-- | source4/lib/socket/socket.h | 9 | ||||
-rw-r--r-- | source4/lib/socket/socket_ip.c | 4 | ||||
-rw-r--r-- | source4/lib/socket/testsuite.c | 20 |
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); |