From 4d0268dce4eb5210ee73efdb6c82aa899b27008f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 2 May 2011 16:15:50 +1000 Subject: s4-lib/socket Merge updated set_socket_options from Samba3 -> Samba4 --- source4/lib/socket/socket.c | 124 ++++++++++++++++++++++++++++++++------------ 1 file changed, 90 insertions(+), 34 deletions(-) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index 4b5cecab34..a627fbe2a6 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -569,68 +569,115 @@ _PUBLIC_ const struct socket_ops *socket_getops_byname(const char *family, enum enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON}; -static const struct { +typedef struct smb_socket_option { const char *name; int level; int option; int value; int opttype; -} socket_options[] = { - {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL}, - {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL}, - {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL}, +} smb_socket_option; + +static const smb_socket_option socket_options[] = { + {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL}, + {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL}, + {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL}, #ifdef TCP_NODELAY - {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL}, + {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL}, +#endif +#ifdef TCP_KEEPCNT + {"TCP_KEEPCNT", IPPROTO_TCP, TCP_KEEPCNT, 0, OPT_INT}, +#endif +#ifdef TCP_KEEPIDLE + {"TCP_KEEPIDLE", IPPROTO_TCP, TCP_KEEPIDLE, 0, OPT_INT}, +#endif +#ifdef TCP_KEEPINTVL + {"TCP_KEEPINTVL", IPPROTO_TCP, TCP_KEEPINTVL, 0, OPT_INT}, #endif #ifdef IPTOS_LOWDELAY - {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON}, + {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON}, #endif #ifdef IPTOS_THROUGHPUT - {"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON}, + {"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON}, #endif #ifdef SO_REUSEPORT - {"SO_REUSEPORT", SOL_SOCKET, SO_REUSEPORT, 0, OPT_BOOL}, + {"SO_REUSEPORT", SOL_SOCKET, SO_REUSEPORT, 0, OPT_BOOL}, #endif #ifdef SO_SNDBUF - {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT}, + {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT}, #endif #ifdef SO_RCVBUF - {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT}, + {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT}, #endif #ifdef SO_SNDLOWAT - {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT}, + {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT}, #endif #ifdef SO_RCVLOWAT - {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT}, + {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT}, #endif #ifdef SO_SNDTIMEO - {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT}, + {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT}, #endif #ifdef SO_RCVTIMEO - {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT}, + {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT}, +#endif +#ifdef TCP_FASTACK + {"TCP_FASTACK", IPPROTO_TCP, TCP_FASTACK, 0, OPT_INT}, +#endif +#ifdef TCP_QUICKACK + {"TCP_QUICKACK", IPPROTO_TCP, TCP_QUICKACK, 0, OPT_BOOL}, +#endif +#ifdef TCP_KEEPALIVE_THRESHOLD + {"TCP_KEEPALIVE_THRESHOLD", IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD, 0, OPT_INT}, +#endif +#ifdef TCP_KEEPALIVE_ABORT_THRESHOLD + {"TCP_KEEPALIVE_ABORT_THRESHOLD", IPPROTO_TCP, TCP_KEEPALIVE_ABORT_THRESHOLD, 0, OPT_INT}, #endif {NULL,0,0,0,0}}; +/**************************************************************************** + Print socket options. +****************************************************************************/ -/** - Set user socket options. -**/ -_PUBLIC_ void set_socket_options(int fd, const char *options) +static void print_socket_options(int s) { - const char **options_list = (const char **)str_list_make(NULL, options, " \t,"); - int j; + int value; + socklen_t vlen = 4; + const smb_socket_option *p = &socket_options[0]; + + /* wrapped in if statement to prevent streams + * leak in SCO Openserver 5.0 */ + /* reported on samba-technical --jerry */ + if ( DEBUGLEVEL >= 5 ) { + DEBUG(5,("Socket options:\n")); + for (; p->name != NULL; p++) { + if (getsockopt(s, p->level, p->option, + (void *)&value, &vlen) == -1) { + DEBUGADD(5,("\tCould not test socket option %s.\n", + p->name)); + } else { + DEBUGADD(5,("\t%s = %d\n", + p->name,value)); + } + } + } + } - if (!options_list) - return; +/**************************************************************************** + Set user socket options. +****************************************************************************/ - for (j = 0; options_list[j]; j++) { - const char *tok = options_list[j]; +void set_socket_options(int fd, const char *options) +{ + TALLOC_CTX *ctx = talloc_new(NULL); + char *tok; + + while (next_token_talloc(ctx, &options, &tok," \t,")) { int ret=0,i; int value = 1; char *p; bool got_value = false; - if ((p = strchr(tok,'='))) { + if ((p = strchr_m(tok,'='))) { *p = 0; value = atoi(p+1); got_value = true; @@ -649,26 +696,35 @@ _PUBLIC_ void set_socket_options(int fd, const char *options) case OPT_BOOL: case OPT_INT: ret = setsockopt(fd,socket_options[i].level, - socket_options[i].option,(char *)&value,sizeof(int)); + socket_options[i].option, + (char *)&value,sizeof(int)); break; case OPT_ON: if (got_value) - DEBUG(0,("syntax error - %s does not take a value\n",tok)); + DEBUG(0,("syntax error - %s " + "does not take a value\n",tok)); { int on = socket_options[i].value; ret = setsockopt(fd,socket_options[i].level, - socket_options[i].option,(char *)&on,sizeof(int)); + socket_options[i].option, + (char *)&on,sizeof(int)); } - break; + break; + } + + if (ret != 0) { + /* be aware that some systems like Solaris return + * EINVAL to a setsockopt() call when the client + * sent a RST previously - no need to worry */ + DEBUG(2,("Failed to set socket option %s (Error %s)\n", + tok, strerror(errno) )); } - - if (ret != 0) - DEBUG(0,("Failed to set socket option %s (Error %s)\n",tok, strerror(errno) )); } - talloc_free(options_list); + TALLOC_FREE(ctx); + print_socket_options(fd); } /* -- cgit From eea783e04cca45b1d3d9e5bb10556a2c8dc79b86 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 2 May 2011 16:23:40 +1000 Subject: lib/util Move set_socket_options() into common code. --- source4/lib/socket/socket.c | 160 -------------------------------------------- 1 file changed, 160 deletions(-) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index a627fbe2a6..cecd1026d5 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -567,166 +567,6 @@ _PUBLIC_ const struct socket_ops *socket_getops_byname(const char *family, enum return NULL; } -enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON}; - -typedef struct smb_socket_option { - const char *name; - int level; - int option; - int value; - int opttype; -} smb_socket_option; - -static const smb_socket_option socket_options[] = { - {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL}, - {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL}, - {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL}, -#ifdef TCP_NODELAY - {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL}, -#endif -#ifdef TCP_KEEPCNT - {"TCP_KEEPCNT", IPPROTO_TCP, TCP_KEEPCNT, 0, OPT_INT}, -#endif -#ifdef TCP_KEEPIDLE - {"TCP_KEEPIDLE", IPPROTO_TCP, TCP_KEEPIDLE, 0, OPT_INT}, -#endif -#ifdef TCP_KEEPINTVL - {"TCP_KEEPINTVL", IPPROTO_TCP, TCP_KEEPINTVL, 0, OPT_INT}, -#endif -#ifdef IPTOS_LOWDELAY - {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON}, -#endif -#ifdef IPTOS_THROUGHPUT - {"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON}, -#endif -#ifdef SO_REUSEPORT - {"SO_REUSEPORT", SOL_SOCKET, SO_REUSEPORT, 0, OPT_BOOL}, -#endif -#ifdef SO_SNDBUF - {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT}, -#endif -#ifdef SO_RCVBUF - {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT}, -#endif -#ifdef SO_SNDLOWAT - {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT}, -#endif -#ifdef SO_RCVLOWAT - {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT}, -#endif -#ifdef SO_SNDTIMEO - {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT}, -#endif -#ifdef SO_RCVTIMEO - {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT}, -#endif -#ifdef TCP_FASTACK - {"TCP_FASTACK", IPPROTO_TCP, TCP_FASTACK, 0, OPT_INT}, -#endif -#ifdef TCP_QUICKACK - {"TCP_QUICKACK", IPPROTO_TCP, TCP_QUICKACK, 0, OPT_BOOL}, -#endif -#ifdef TCP_KEEPALIVE_THRESHOLD - {"TCP_KEEPALIVE_THRESHOLD", IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD, 0, OPT_INT}, -#endif -#ifdef TCP_KEEPALIVE_ABORT_THRESHOLD - {"TCP_KEEPALIVE_ABORT_THRESHOLD", IPPROTO_TCP, TCP_KEEPALIVE_ABORT_THRESHOLD, 0, OPT_INT}, -#endif - {NULL,0,0,0,0}}; - -/**************************************************************************** - Print socket options. -****************************************************************************/ - -static void print_socket_options(int s) -{ - int value; - socklen_t vlen = 4; - const smb_socket_option *p = &socket_options[0]; - - /* wrapped in if statement to prevent streams - * leak in SCO Openserver 5.0 */ - /* reported on samba-technical --jerry */ - if ( DEBUGLEVEL >= 5 ) { - DEBUG(5,("Socket options:\n")); - for (; p->name != NULL; p++) { - if (getsockopt(s, p->level, p->option, - (void *)&value, &vlen) == -1) { - DEBUGADD(5,("\tCould not test socket option %s.\n", - p->name)); - } else { - DEBUGADD(5,("\t%s = %d\n", - p->name,value)); - } - } - } - } - -/**************************************************************************** - Set user socket options. -****************************************************************************/ - -void set_socket_options(int fd, const char *options) -{ - TALLOC_CTX *ctx = talloc_new(NULL); - char *tok; - - while (next_token_talloc(ctx, &options, &tok," \t,")) { - int ret=0,i; - int value = 1; - char *p; - bool got_value = false; - - if ((p = strchr_m(tok,'='))) { - *p = 0; - value = atoi(p+1); - got_value = true; - } - - for (i=0;socket_options[i].name;i++) - if (strequal(socket_options[i].name,tok)) - break; - - if (!socket_options[i].name) { - DEBUG(0,("Unknown socket option %s\n",tok)); - continue; - } - - switch (socket_options[i].opttype) { - case OPT_BOOL: - case OPT_INT: - ret = setsockopt(fd,socket_options[i].level, - socket_options[i].option, - (char *)&value,sizeof(int)); - break; - - case OPT_ON: - if (got_value) - DEBUG(0,("syntax error - %s " - "does not take a value\n",tok)); - - { - int on = socket_options[i].value; - ret = setsockopt(fd,socket_options[i].level, - socket_options[i].option, - (char *)&on,sizeof(int)); - } - break; - } - - if (ret != 0) { - /* be aware that some systems like Solaris return - * EINVAL to a setsockopt() call when the client - * sent a RST previously - no need to worry */ - DEBUG(2,("Failed to set socket option %s (Error %s)\n", - tok, strerror(errno) )); - } - } - - TALLOC_FREE(ctx); - print_socket_options(fd); -} - /* set some flags on a socket */ -- cgit From b96389d3e17013fd22a64b6ce54478bd912d06b3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 3 May 2011 09:34:06 +1000 Subject: s4-socket: rename allow_access() to socket_allow_access() this prevents a symbol collision with s3 Pair-Programmed-With: Andrew Bartlett --- source4/lib/socket/access.c | 8 ++++---- source4/lib/socket/socket.h | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/access.c b/source4/lib/socket/access.c index ab39d63ef5..589797763f 100644 --- a/source4/lib/socket/access.c +++ b/source4/lib/socket/access.c @@ -249,9 +249,9 @@ static bool allow_access_internal(TALLOC_CTX *mem_ctx, } /* return true if access should be allowed */ -bool allow_access(TALLOC_CTX *mem_ctx, - const char **deny_list, const char **allow_list, - const char *cname, const char *caddr) +bool socket_allow_access(TALLOC_CTX *mem_ctx, + const char **deny_list, const char **allow_list, + const char *cname, const char *caddr) { bool ret; char *nc_cname = talloc_strdup(mem_ctx, cname); @@ -346,7 +346,7 @@ bool socket_check_access(struct socket_context *sock, return false; } - ret = allow_access(mem_ctx, deny_list, allow_list, name, addr->addr); + ret = socket_allow_access(mem_ctx, deny_list, allow_list, name, addr->addr); if (ret) { DEBUG(2,("socket_check_access: Allowed connection to '%s' from %s (%s)\n", diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h index 4a744797b3..88360ac8f3 100644 --- a/source4/lib/socket/socket.h +++ b/source4/lib/socket/socket.h @@ -179,9 +179,9 @@ _PUBLIC_ void socket_address_set_port(struct socket_address *a, struct socket_address *socket_address_copy(TALLOC_CTX *mem_ctx, const struct socket_address *oaddr); const struct socket_ops *socket_getops_byname(const char *name, enum socket_type type); -bool allow_access(TALLOC_CTX *mem_ctx, - const char **deny_list, const char **allow_list, - const char *cname, const char *caddr); +bool socket_allow_access(TALLOC_CTX *mem_ctx, + const char **deny_list, const char **allow_list, + const char *cname, const char *caddr); bool socket_check_access(struct socket_context *sock, const char *service_name, const char **allow_list, const char **deny_list); -- cgit From 5a8b6ac4c0ea88bdab12349830985560c69cbf8c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 2 May 2011 12:09:19 +1000 Subject: s4-lib merge get_interfaces() from Samba3 to Samba4 --- source4/lib/socket/interface.c | 244 ++++++++++++++++++++++++++++------------- source4/lib/socket/netif.c | 225 +++++++++++++++++++++++++++++++++---- source4/lib/socket/netif.h | 6 +- 3 files changed, 375 insertions(+), 100 deletions(-) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/interface.c b/source4/lib/socket/interface.c index c4411b623c..abeca8ba1e 100644 --- a/source4/lib/socket/interface.c +++ b/source4/lib/socket/interface.c @@ -25,11 +25,14 @@ #include "../lib/util/util_net.h" #include "../lib/util/dlinklist.h" -/** used for network interfaces */ +/* used for network interfaces */ struct interface { struct interface *next, *prev; - struct in_addr ip; - struct in_addr nmask; + char *name; + int flags; + struct sockaddr_storage ip; + struct sockaddr_storage netmask; + struct sockaddr_storage bcast; const char *ip_s; const char *bcast_s; const char *nmask_s; @@ -46,30 +49,45 @@ struct interface { Try and find an interface that matches an ip. If we cannot, return NULL **************************************************************************/ static struct interface *iface_find(struct interface *interfaces, - struct in_addr ip, bool CheckMask) + const struct sockaddr *ip, + bool check_mask) { struct interface *i; - if (is_zero_ip_v4(ip)) return interfaces; - for (i=interfaces;i;i=i->next) - if (CheckMask) { - if (same_net_v4(i->ip,ip,i->nmask)) return i; - } else if (i->ip.s_addr == ip.s_addr) return i; + if (is_address_any(ip)) { + return interfaces; + } + + for (i=interfaces;i;i=i->next) { + if (check_mask) { + if (same_net(ip, (struct sockaddr *)&i->ip, (struct sockaddr *)&i->netmask)) { + return i; + } + } else if (sockaddr_equal((struct sockaddr *)&i->ip, ip)) { + return i; + } + } return NULL; } - /**************************************************************************** add an interface to the linked list of interfaces ****************************************************************************/ -static void add_interface(TALLOC_CTX *mem_ctx, struct in_addr ip, struct in_addr nmask, struct interface **interfaces) +static void add_interface(TALLOC_CTX *mem_ctx, const struct iface_struct *ifs, struct interface **interfaces) { + char addr[INET6_ADDRSTRLEN]; struct interface *iface; - struct in_addr bcast; - if (iface_find(*interfaces, ip, false)) { - DEBUG(3,("not adding duplicate interface %s\n",inet_ntoa(ip))); + if (iface_find(*interfaces, (const struct sockaddr *)&ifs->ip, false)) { + DEBUG(3,("add_interface: not adding duplicate interface %s\n", + print_sockaddr(addr, sizeof(addr), &ifs->ip) )); + return; + } + + if (!(ifs->flags & (IFF_BROADCAST|IFF_LOOPBACK))) { + DEBUG(3,("not adding non-broadcast interface %s\n", + ifs->name )); return; } @@ -79,26 +97,36 @@ static void add_interface(TALLOC_CTX *mem_ctx, struct in_addr ip, struct in_addr ZERO_STRUCTPN(iface); - iface->ip = ip; - iface->nmask = nmask; - bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr); + iface->name = talloc_strdup(iface, ifs->name); + if (!iface->name) { + SAFE_FREE(iface); + return; + } + iface->flags = ifs->flags; + iface->ip = ifs->ip; + iface->netmask = ifs->netmask; + iface->bcast = ifs->bcast; /* keep string versions too, to avoid people tripping over the implied static in inet_ntoa() */ - iface->ip_s = talloc_strdup(iface, inet_ntoa(iface->ip)); - iface->nmask_s = talloc_strdup(iface, inet_ntoa(iface->nmask)); - - if (nmask.s_addr != ~0) { - iface->bcast_s = talloc_strdup(iface, inet_ntoa(bcast)); - } - - DLIST_ADD_END(*interfaces, iface, struct interface *); - - DEBUG(3,("added interface ip=%s nmask=%s\n", iface->ip_s, iface->nmask_s)); + print_sockaddr(addr, sizeof(addr), &iface->ip); + DEBUG(2,("added interface %s ip=%s ", + iface->name, addr)); + iface->ip_s = talloc_strdup(iface, addr); + + print_sockaddr(addr, sizeof(addr), + &iface->bcast); + DEBUG(2,("bcast=%s ", addr)); + iface->bcast_s = talloc_strdup(iface, addr); + + print_sockaddr(addr, sizeof(addr), + &iface->netmask); + DEBUG(2,("netmask=%s\n", addr)); + iface->nmask_s = talloc_strdup(iface, addr); + + DLIST_ADD(*interfaces, iface); } - - /** interpret a single element from a interfaces= config line @@ -116,77 +144,134 @@ static void interpret_interface(TALLOC_CTX *mem_ctx, int total_probed, struct interface **local_interfaces) { - struct in_addr ip, nmask; + struct sockaddr_storage ss; + struct sockaddr_storage ss_mask; + struct sockaddr_storage ss_net; + struct sockaddr_storage ss_bcast; + struct iface_struct ifs; char *p; - char *address; - int i, added=0; + int i; + bool added=false; + bool goodaddr = false; - ip.s_addr = 0; - nmask.s_addr = 0; - /* first check if it is an interface name */ for (i=0;i 2) { - nmask.s_addr = interpret_addr2(p).s_addr; + goodaddr = interpret_string_addr(&ss_mask, p, 0); + if (!goodaddr) { + DEBUG(2,("interpret_interface: " + "can't determine netmask from %s\n", + p)); + return; + } } else { - nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES)); + char *endp = NULL; + unsigned long val = strtoul(p, &endp, 0); + if (p == endp || (endp && *endp != '\0')) { + DEBUG(2,("interpret_interface: " + "can't determine netmask value from %s\n", + p)); + return; + } + if (!make_netmask(&ss_mask, &ss, val)) { + DEBUG(2,("interpret_interface: " + "can't apply netmask value %lu from %s\n", + val, + p)); + return; + } } - /* maybe the first component was a broadcast address */ - if (ip.s_addr == MKBCADDR(ip.s_addr, nmask.s_addr) || - ip.s_addr == MKNETADDR(ip.s_addr, nmask.s_addr)) { + make_bcast(&ss_bcast, &ss, &ss_mask); + make_net(&ss_net, &ss, &ss_mask); + + /* Maybe the first component was a broadcast address. */ + if (sockaddr_equal((struct sockaddr *)&ss_bcast, (struct sockaddr *)&ss) || + sockaddr_equal((struct sockaddr *)&ss_net, (struct sockaddr *)&ss)) { for (i=0;iip_s; } @@ -315,10 +399,12 @@ const char *iface_best_ip(struct interface *ifaces, const char *dest) */ bool iface_is_local(struct interface *ifaces, const char *dest) { - struct in_addr ip; + struct sockaddr_storage ss; - ip.s_addr = interpret_addr(dest); - if (iface_find(ifaces, ip, true)) { + if (!interpret_string_addr(&ss, dest, AI_NUMERICHOST)) { + return false; + } + if (iface_find(ifaces, (const struct sockaddr *)&ss, true)) { return true; } return false; diff --git a/source4/lib/socket/netif.c b/source4/lib/socket/netif.c index e36f268bde..2846813d3f 100644 --- a/source4/lib/socket/netif.c +++ b/source4/lib/socket/netif.c @@ -36,6 +36,101 @@ #include "netif.h" #include "lib/util/tsort.h" +/**************************************************************************** + Create a struct sockaddr_storage with the netmask bits set to 1. +****************************************************************************/ + +bool make_netmask(struct sockaddr_storage *pss_out, + const struct sockaddr_storage *pss_in, + unsigned long masklen) +{ + *pss_out = *pss_in; + /* Now apply masklen bits of mask. */ +#if defined(HAVE_IPV6) + if (pss_in->ss_family == AF_INET6) { + char *p = (char *)&((struct sockaddr_in6 *)pss_out)->sin6_addr; + unsigned int i; + + if (masklen > 128) { + return false; + } + for (i = 0; masklen >= 8; masklen -= 8, i++) { + *p++ = 0xff; + } + /* Deal with the partial byte. */ + *p++ &= (0xff & ~(0xff>>masklen)); + i++; + for (;i < sizeof(struct in6_addr); i++) { + *p++ = '\0'; + } + return true; + } +#endif + if (pss_in->ss_family == AF_INET) { + if (masklen > 32) { + return false; + } + ((struct sockaddr_in *)pss_out)->sin_addr.s_addr = + htonl(((0xFFFFFFFFL >> masklen) ^ 0xFFFFFFFFL)); + return true; + } + return false; +} + +/**************************************************************************** + Create a struct sockaddr_storage set to the broadcast or network adress from + an incoming sockaddr_storage. +****************************************************************************/ + +static void make_bcast_or_net(struct sockaddr_storage *pss_out, + const struct sockaddr_storage *pss_in, + const struct sockaddr_storage *nmask, + bool make_bcast_p) +{ + unsigned int i = 0, len = 0; + char *pmask = NULL; + char *p = NULL; + *pss_out = *pss_in; + + /* Set all zero netmask bits to 1. */ +#if defined(HAVE_IPV6) + if (pss_in->ss_family == AF_INET6) { + p = (char *)&((struct sockaddr_in6 *)pss_out)->sin6_addr; + pmask = discard_const_p(char, &((struct sockaddr_in6 *)nmask)->sin6_addr); + len = 16; + } +#endif + if (pss_in->ss_family == AF_INET) { + p = (char *)&((struct sockaddr_in *)pss_out)->sin_addr; + pmask = discard_const_p(char, &((struct sockaddr_in *)nmask)->sin_addr); + len = 4; + } + + for (i = 0; i < len; i++, p++, pmask++) { + if (make_bcast_p) { + *p = (*p & *pmask) | (*pmask ^ 0xff); + } else { + /* make_net */ + *p = (*p & *pmask); + } + } +} + +void make_bcast(struct sockaddr_storage *pss_out, + const struct sockaddr_storage *pss_in, + const struct sockaddr_storage *nmask) +{ + make_bcast_or_net(pss_out, pss_in, nmask, true); +} + +void make_net(struct sockaddr_storage *pss_out, + const struct sockaddr_storage *pss_in, + const struct sockaddr_storage *nmask) +{ + make_bcast_or_net(pss_out, pss_in, nmask, false); +} + + /**************************************************************************** Try the "standard" getifaddrs/freeifaddrs interfaces. Also gets IPv6 interfaces. @@ -45,22 +140,38 @@ Get the netmask address for a local interface. ****************************************************************************/ -static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) +static int _get_interfaces(TALLOC_CTX *mem_ctx, struct iface_struct **pifaces) { + struct iface_struct *ifaces; struct ifaddrs *iflist = NULL; struct ifaddrs *ifptr = NULL; + int count; int total = 0; + size_t copy_size; if (getifaddrs(&iflist) < 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) { + count = 0; + for (ifptr = iflist; ifptr != NULL; ifptr = ifptr->ifa_next) { + if (!ifptr->ifa_addr || !ifptr->ifa_netmask) { + continue; + } + if (!(ifptr->ifa_flags & IFF_UP)) { + continue; + } + count += 1; + } - memset(&ifaces[total], '\0', sizeof(ifaces[total])); + ifaces = talloc_array(mem_ctx, struct iface_struct, count); + if (ifaces == NULL) { + errno = ENOMEM; + return -1; + } + + /* Loop through interfaces, looking for given IP address */ + for (ifptr = iflist; ifptr != NULL; ifptr = ifptr->ifa_next) { if (!ifptr->ifa_addr || !ifptr->ifa_netmask) { continue; @@ -71,13 +182,33 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) continue; } - /* We don't support IPv6 *yet* */ - if (ifptr->ifa_addr->sa_family != AF_INET) { - continue; + memset(&ifaces[total], '\0', sizeof(ifaces[total])); + + copy_size = sizeof(struct sockaddr_in); + + ifaces[total].flags = ifptr->ifa_flags; + +#if defined(HAVE_IPV6) + if (ifptr->ifa_addr->sa_family == AF_INET6) { + copy_size = sizeof(struct sockaddr_in6); } +#endif + + memcpy(&ifaces[total].ip, ifptr->ifa_addr, copy_size); + memcpy(&ifaces[total].netmask, ifptr->ifa_netmask, copy_size); - ifaces[total].ip = ((struct sockaddr_in *)ifptr->ifa_addr)->sin_addr; - ifaces[total].netmask = ((struct sockaddr_in *)ifptr->ifa_netmask)->sin_addr; + if (ifaces[total].flags & (IFF_BROADCAST|IFF_LOOPBACK)) { + make_bcast(&ifaces[total].bcast, + &ifaces[total].ip, + &ifaces[total].netmask); + } else if ((ifaces[total].flags & IFF_POINTOPOINT) && + ifptr->ifa_dstaddr ) { + memcpy(&ifaces[total].bcast, + ifptr->ifa_dstaddr, + copy_size); + } else { + continue; + } strlcpy(ifaces[total].name, ifptr->ifa_name, sizeof(ifaces[total].name)); @@ -86,27 +217,82 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) freeifaddrs(iflist); + *pifaces = ifaces; return total; } 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); - return r; + +#if defined(HAVE_IPV6) + /* + * If we have IPv6 - sort these interfaces lower + * than any IPv4 ones. + */ + if (i1->ip.ss_family == AF_INET6 && + i2->ip.ss_family == AF_INET) { + return -1; + } else if (i1->ip.ss_family == AF_INET && + i2->ip.ss_family == AF_INET6) { + return 1; + } + + if (i1->ip.ss_family == AF_INET6) { + struct sockaddr_in6 *s1 = (struct sockaddr_in6 *)&i1->ip; + struct sockaddr_in6 *s2 = (struct sockaddr_in6 *)&i2->ip; + + r = memcmp(&s1->sin6_addr, + &s2->sin6_addr, + sizeof(struct in6_addr)); + if (r) { + return r; + } + + s1 = (struct sockaddr_in6 *)&i1->netmask; + s2 = (struct sockaddr_in6 *)&i2->netmask; + + r = memcmp(&s1->sin6_addr, + &s2->sin6_addr, + sizeof(struct in6_addr)); + if (r) { + return r; + } + } +#endif + + /* AIX uses __ss_family instead of ss_family inside of + sockaddr_storage. Instead of trying to figure out which field to + use, we can just cast it to a sockaddr. + */ + + if (((struct sockaddr *)&i1->ip)->sa_family == AF_INET) { + struct sockaddr_in *s1 = (struct sockaddr_in *)&i1->ip; + struct sockaddr_in *s2 = (struct sockaddr_in *)&i2->ip; + + r = ntohl(s1->sin_addr.s_addr) - + ntohl(s2->sin_addr.s_addr); + if (r) { + return r; + } + + s1 = (struct sockaddr_in *)&i1->netmask; + s2 = (struct sockaddr_in *)&i2->netmask; + + return ntohl(s1->sin_addr.s_addr) - + ntohl(s2->sin_addr.s_addr); + } + return 0; } /* this wrapper is used to remove duplicates from the interface list generated above */ -int get_interfaces(struct iface_struct *ifaces, int max_interfaces) +int get_interfaces(TALLOC_CTX *mem_ctx, struct iface_struct **pifaces) { + struct iface_struct *ifaces; int total, i, j; - total = _get_interfaces(ifaces, max_interfaces); + total = _get_interfaces(mem_ctx, &ifaces); if (total <= 0) return total; /* now we need to remove duplicates */ @@ -123,5 +309,6 @@ int get_interfaces(struct iface_struct *ifaces, int max_interfaces) } } + *pifaces = ifaces; return total; } diff --git a/source4/lib/socket/netif.h b/source4/lib/socket/netif.h index 417c6e074f..6a06c4bf15 100644 --- a/source4/lib/socket/netif.h +++ b/source4/lib/socket/netif.h @@ -23,8 +23,10 @@ struct iface_struct { char name[16]; - struct in_addr ip; - struct in_addr netmask; + int flags; + struct sockaddr_storage ip; + struct sockaddr_storage netmask; + struct sockaddr_storage bcast; }; struct interface; -- cgit From 879498b3622102630a5ade8d7d5421720f6fd7c6 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 3 May 2011 19:41:41 +1000 Subject: s4-lib/socket Samba4 is not IPv6 compatible Don't add IPv6 interfaces until we actually support them. I'll soon have IPv6 service at home, and then I'll make it my buisness to sort this out once and for all. Andrew Bartlett --- source4/lib/socket/interface.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/interface.c b/source4/lib/socket/interface.c index abeca8ba1e..69b7ec1d49 100644 --- a/source4/lib/socket/interface.c +++ b/source4/lib/socket/interface.c @@ -91,6 +91,11 @@ static void add_interface(TALLOC_CTX *mem_ctx, const struct iface_struct *ifs, s return; } + if (ifs->ip.ss_family != AF_INET) { + DEBUG(5, ("not adding IPv6 interface %s\n", ifs->name)); + return; + } + iface = talloc(*interfaces == NULL ? mem_ctx : *interfaces, struct interface); if (iface == NULL) return; -- cgit From f346a737855bb5018978f0fcf1dcafbf5dc7e603 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 2 May 2011 13:02:17 +1000 Subject: lib/socket move interfaces code to the top level --- source4/lib/socket/netif.c | 314 --------------------------------------- source4/lib/socket/netif.h | 16 +- source4/lib/socket/wscript_build | 10 +- 3 files changed, 6 insertions(+), 334 deletions(-) delete mode 100644 source4/lib/socket/netif.c (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/netif.c b/source4/lib/socket/netif.c deleted file mode 100644 index 2846813d3f..0000000000 --- a/source4/lib/socket/netif.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - 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 - 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 . -*/ - - -/* working out the interfaces for a OS is an incredibly non-portable - thing. We have several possible implementations below, and autoconf - tries each of them to see what works - - Note that this file does _not_ include includes.h. That is so this code - can be called directly from the autoconf tests. That also means - this code cannot use any of the normal Samba debug stuff or defines. - This is standalone code. - -*/ - -#include "includes.h" -#include "system/network.h" -#include "netif.h" -#include "lib/util/tsort.h" - -/**************************************************************************** - Create a struct sockaddr_storage with the netmask bits set to 1. -****************************************************************************/ - -bool make_netmask(struct sockaddr_storage *pss_out, - const struct sockaddr_storage *pss_in, - unsigned long masklen) -{ - *pss_out = *pss_in; - /* Now apply masklen bits of mask. */ -#if defined(HAVE_IPV6) - if (pss_in->ss_family == AF_INET6) { - char *p = (char *)&((struct sockaddr_in6 *)pss_out)->sin6_addr; - unsigned int i; - - if (masklen > 128) { - return false; - } - for (i = 0; masklen >= 8; masklen -= 8, i++) { - *p++ = 0xff; - } - /* Deal with the partial byte. */ - *p++ &= (0xff & ~(0xff>>masklen)); - i++; - for (;i < sizeof(struct in6_addr); i++) { - *p++ = '\0'; - } - return true; - } -#endif - if (pss_in->ss_family == AF_INET) { - if (masklen > 32) { - return false; - } - ((struct sockaddr_in *)pss_out)->sin_addr.s_addr = - htonl(((0xFFFFFFFFL >> masklen) ^ 0xFFFFFFFFL)); - return true; - } - return false; -} - -/**************************************************************************** - Create a struct sockaddr_storage set to the broadcast or network adress from - an incoming sockaddr_storage. -****************************************************************************/ - -static void make_bcast_or_net(struct sockaddr_storage *pss_out, - const struct sockaddr_storage *pss_in, - const struct sockaddr_storage *nmask, - bool make_bcast_p) -{ - unsigned int i = 0, len = 0; - char *pmask = NULL; - char *p = NULL; - *pss_out = *pss_in; - - /* Set all zero netmask bits to 1. */ -#if defined(HAVE_IPV6) - if (pss_in->ss_family == AF_INET6) { - p = (char *)&((struct sockaddr_in6 *)pss_out)->sin6_addr; - pmask = discard_const_p(char, &((struct sockaddr_in6 *)nmask)->sin6_addr); - len = 16; - } -#endif - if (pss_in->ss_family == AF_INET) { - p = (char *)&((struct sockaddr_in *)pss_out)->sin_addr; - pmask = discard_const_p(char, &((struct sockaddr_in *)nmask)->sin_addr); - len = 4; - } - - for (i = 0; i < len; i++, p++, pmask++) { - if (make_bcast_p) { - *p = (*p & *pmask) | (*pmask ^ 0xff); - } else { - /* make_net */ - *p = (*p & *pmask); - } - } -} - -void make_bcast(struct sockaddr_storage *pss_out, - const struct sockaddr_storage *pss_in, - const struct sockaddr_storage *nmask) -{ - make_bcast_or_net(pss_out, pss_in, nmask, true); -} - -void make_net(struct sockaddr_storage *pss_out, - const struct sockaddr_storage *pss_in, - const struct sockaddr_storage *nmask) -{ - make_bcast_or_net(pss_out, pss_in, nmask, false); -} - - -/**************************************************************************** - Try the "standard" getifaddrs/freeifaddrs interfaces. - Also gets IPv6 interfaces. -****************************************************************************/ - -/**************************************************************************** - Get the netmask address for a local interface. -****************************************************************************/ - -static int _get_interfaces(TALLOC_CTX *mem_ctx, struct iface_struct **pifaces) -{ - struct iface_struct *ifaces; - struct ifaddrs *iflist = NULL; - struct ifaddrs *ifptr = NULL; - int count; - int total = 0; - size_t copy_size; - - if (getifaddrs(&iflist) < 0) { - return -1; - } - - count = 0; - for (ifptr = iflist; ifptr != NULL; ifptr = ifptr->ifa_next) { - if (!ifptr->ifa_addr || !ifptr->ifa_netmask) { - continue; - } - if (!(ifptr->ifa_flags & IFF_UP)) { - continue; - } - count += 1; - } - - ifaces = talloc_array(mem_ctx, struct iface_struct, count); - if (ifaces == NULL) { - errno = ENOMEM; - return -1; - } - - /* Loop through interfaces, looking for given IP address */ - for (ifptr = iflist; ifptr != NULL; ifptr = ifptr->ifa_next) { - - if (!ifptr->ifa_addr || !ifptr->ifa_netmask) { - continue; - } - - /* Check the interface is up. */ - if (!(ifptr->ifa_flags & IFF_UP)) { - continue; - } - - memset(&ifaces[total], '\0', sizeof(ifaces[total])); - - copy_size = sizeof(struct sockaddr_in); - - ifaces[total].flags = ifptr->ifa_flags; - -#if defined(HAVE_IPV6) - if (ifptr->ifa_addr->sa_family == AF_INET6) { - copy_size = sizeof(struct sockaddr_in6); - } -#endif - - memcpy(&ifaces[total].ip, ifptr->ifa_addr, copy_size); - memcpy(&ifaces[total].netmask, ifptr->ifa_netmask, copy_size); - - if (ifaces[total].flags & (IFF_BROADCAST|IFF_LOOPBACK)) { - make_bcast(&ifaces[total].bcast, - &ifaces[total].ip, - &ifaces[total].netmask); - } else if ((ifaces[total].flags & IFF_POINTOPOINT) && - ifptr->ifa_dstaddr ) { - memcpy(&ifaces[total].bcast, - ifptr->ifa_dstaddr, - copy_size); - } else { - continue; - } - - strlcpy(ifaces[total].name, ifptr->ifa_name, - sizeof(ifaces[total].name)); - total++; - } - - freeifaddrs(iflist); - - *pifaces = ifaces; - return total; -} - -static int iface_comp(struct iface_struct *i1, struct iface_struct *i2) -{ - int r; - -#if defined(HAVE_IPV6) - /* - * If we have IPv6 - sort these interfaces lower - * than any IPv4 ones. - */ - if (i1->ip.ss_family == AF_INET6 && - i2->ip.ss_family == AF_INET) { - return -1; - } else if (i1->ip.ss_family == AF_INET && - i2->ip.ss_family == AF_INET6) { - return 1; - } - - if (i1->ip.ss_family == AF_INET6) { - struct sockaddr_in6 *s1 = (struct sockaddr_in6 *)&i1->ip; - struct sockaddr_in6 *s2 = (struct sockaddr_in6 *)&i2->ip; - - r = memcmp(&s1->sin6_addr, - &s2->sin6_addr, - sizeof(struct in6_addr)); - if (r) { - return r; - } - - s1 = (struct sockaddr_in6 *)&i1->netmask; - s2 = (struct sockaddr_in6 *)&i2->netmask; - - r = memcmp(&s1->sin6_addr, - &s2->sin6_addr, - sizeof(struct in6_addr)); - if (r) { - return r; - } - } -#endif - - /* AIX uses __ss_family instead of ss_family inside of - sockaddr_storage. Instead of trying to figure out which field to - use, we can just cast it to a sockaddr. - */ - - if (((struct sockaddr *)&i1->ip)->sa_family == AF_INET) { - struct sockaddr_in *s1 = (struct sockaddr_in *)&i1->ip; - struct sockaddr_in *s2 = (struct sockaddr_in *)&i2->ip; - - r = ntohl(s1->sin_addr.s_addr) - - ntohl(s2->sin_addr.s_addr); - if (r) { - return r; - } - - s1 = (struct sockaddr_in *)&i1->netmask; - s2 = (struct sockaddr_in *)&i2->netmask; - - return ntohl(s1->sin_addr.s_addr) - - ntohl(s2->sin_addr.s_addr); - } - return 0; -} - -/* this wrapper is used to remove duplicates from the interface list generated - above */ -int get_interfaces(TALLOC_CTX *mem_ctx, struct iface_struct **pifaces) -{ - struct iface_struct *ifaces; - int total, i, j; - - total = _get_interfaces(mem_ctx, &ifaces); - if (total <= 0) return total; - - /* now we need to remove duplicates */ - TYPESAFE_QSORT(ifaces, total, iface_comp); - - for (i=1;i Date: Mon, 2 May 2011 15:57:19 +1000 Subject: s4-interfaces Rename interfaces code so not to conflict with source3/ The iface_count, iface_n_bcast, and load_interfaces functions conflicted with functions of the same name in source3, so the source4 functions were renamed. Hopefully we can actually wrap one around the other in future. Andrew Bartlett --- source4/lib/socket/interface.c | 32 ++++++++++++++++---------------- source4/lib/socket/testsuite.c | 14 +++++++------- 2 files changed, 23 insertions(+), 23 deletions(-) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/interface.c b/source4/lib/socket/interface.c index 69b7ec1d49..4eb4f3a517 100644 --- a/source4/lib/socket/interface.c +++ b/source4/lib/socket/interface.c @@ -48,9 +48,9 @@ struct interface { /**************************************************************************** Try and find an interface that matches an ip. If we cannot, return NULL **************************************************************************/ -static struct interface *iface_find(struct interface *interfaces, - const struct sockaddr *ip, - bool check_mask) +static struct interface *iface_list_find(struct interface *interfaces, + const struct sockaddr *ip, + bool check_mask) { struct interface *i; @@ -79,7 +79,7 @@ static void add_interface(TALLOC_CTX *mem_ctx, const struct iface_struct *ifs, s char addr[INET6_ADDRSTRLEN]; struct interface *iface; - if (iface_find(*interfaces, (const struct sockaddr *)&ifs->ip, false)) { + if (iface_list_find(*interfaces, (const struct sockaddr *)&ifs->ip, false)) { DEBUG(3,("add_interface: not adding duplicate interface %s\n", print_sockaddr(addr, sizeof(addr), &ifs->ip) )); return; @@ -283,7 +283,7 @@ static void interpret_interface(TALLOC_CTX *mem_ctx, /** load the list of network interfaces **/ -void load_interfaces(TALLOC_CTX *mem_ctx, const char **interfaces, struct interface **local_interfaces) +void load_interface_list(TALLOC_CTX *mem_ctx, const char **interfaces, struct interface **local_interfaces) { const char **ptr = interfaces; int i; @@ -322,7 +322,7 @@ void load_interfaces(TALLOC_CTX *mem_ctx, const char **interfaces, struct interf /** how many interfaces do we have **/ -int iface_count(struct interface *ifaces) +int iface_list_count(struct interface *ifaces) { int ret = 0; struct interface *i; @@ -335,7 +335,7 @@ int iface_count(struct interface *ifaces) /** return IP of the Nth interface **/ -const char *iface_n_ip(struct interface *ifaces, int n) +const char *iface_list_n_ip(struct interface *ifaces, int n) { struct interface *i; @@ -351,7 +351,7 @@ const char *iface_n_ip(struct interface *ifaces, int n) /** return bcast of the Nth interface **/ -const char *iface_n_bcast(struct interface *ifaces, int n) +const char *iface_list_n_bcast(struct interface *ifaces, int n) { struct interface *i; @@ -367,7 +367,7 @@ const char *iface_n_bcast(struct interface *ifaces, int n) /** return netmask of the Nth interface **/ -const char *iface_n_netmask(struct interface *ifaces, int n) +const char *iface_list_n_netmask(struct interface *ifaces, int n) { struct interface *i; @@ -384,32 +384,32 @@ const char *iface_n_netmask(struct interface *ifaces, 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 interface *ifaces, const char *dest) +const char *iface_list_best_ip(struct interface *ifaces, const char *dest) { struct interface *iface; struct sockaddr_storage ss; if (!interpret_string_addr(&ss, dest, AI_NUMERICHOST)) { - return iface_n_ip(ifaces, 0); + return iface_list_n_ip(ifaces, 0); } - iface = iface_find(ifaces, (const struct sockaddr *)&ss, true); + iface = iface_list_find(ifaces, (const struct sockaddr *)&ss, true); if (iface) { return iface->ip_s; } - return iface_n_ip(ifaces, 0); + return iface_list_n_ip(ifaces, 0); } /** return true if an IP is one one of our local networks */ -bool iface_is_local(struct interface *ifaces, const char *dest) +bool iface_list_is_local(struct interface *ifaces, const char *dest) { struct sockaddr_storage ss; if (!interpret_string_addr(&ss, dest, AI_NUMERICHOST)) { return false; } - if (iface_find(ifaces, (const struct sockaddr *)&ss, true)) { + if (iface_list_find(ifaces, (const struct sockaddr *)&ss, true)) { return true; } return false; @@ -418,7 +418,7 @@ bool iface_is_local(struct interface *ifaces, const char *dest) /** return true if a IP matches a IP/netmask pair */ -bool iface_same_net(const char *ip1, const char *ip2, const char *netmask) +bool iface_list_same_net(const char *ip1, const char *ip2, const char *netmask) { return same_net_v4(interpret_addr2(ip1), interpret_addr2(ip2), diff --git a/source4/lib/socket/testsuite.c b/source4/lib/socket/testsuite.c index 2489277433..518bc72501 100644 --- a/source4/lib/socket/testsuite.c +++ b/source4/lib/socket/testsuite.c @@ -42,7 +42,7 @@ static bool test_udp(struct torture_context *tctx) TALLOC_CTX *mem_ctx = tctx; struct interface *ifaces; - load_interfaces(tctx, lpcfg_interfaces(tctx->lp_ctx), &ifaces); + load_interface_list(tctx, lpcfg_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"); @@ -53,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(ifaces, "127.0.0.1"), 0); + iface_list_best_ip(ifaces, "127.0.0.1"), 0); torture_assert(tctx, localhost, "Localhost not found"); @@ -62,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(ifaces, "127.0.0.1")) == 0, + strcmp(srv_addr->addr, iface_list_best_ip(ifaces, "127.0.0.1")) == 0, talloc_asprintf(tctx, "Expected server address of %s but got %s", - iface_best_ip(ifaces, "127.0.0.1"), srv_addr ? srv_addr->addr : NULL)); + iface_list_best_ip(ifaces, "127.0.0.1"), srv_addr ? srv_addr->addr : NULL)); torture_comment(tctx, "server port is %d\n", srv_addr->port); @@ -135,9 +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, lpcfg_interfaces(tctx->lp_ctx), &ifaces); + load_interface_list(tctx, lpcfg_interfaces(tctx->lp_ctx), &ifaces); localhost = socket_address_from_strings(sock1, sock1->backend_name, - iface_best_ip(ifaces, "127.0.0.1"), 0); + iface_list_best_ip(ifaces, "127.0.0.1"), 0); torture_assert(tctx, localhost, "Localhost not found"); status = socket_listen(sock1, localhost, 0, 0); @@ -147,7 +147,7 @@ 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(ifaces, "127.0.0.1"), + torture_assert_str_equal(tctx, srv_addr->addr, iface_list_best_ip(ifaces, "127.0.0.1"), "Unexpected server address"); torture_comment(tctx, "server port is %d\n", srv_addr->port); -- cgit From c596d85afd41c2512ef77a10a9d6b40f4836c386 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 8 May 2011 12:55:41 +0200 Subject: s4-interfaces: keep interfaces in the order they were declared the spoolss notify test depends on the interfaces order Pair-Programmed-With: Andrew Bartlett Autobuild-User: Andrew Tridgell Autobuild-Date: Sun May 8 13:57:58 CEST 2011 on sn-devel-104 --- source4/lib/socket/interface.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/interface.c b/source4/lib/socket/interface.c index 4eb4f3a517..b762f5573a 100644 --- a/source4/lib/socket/interface.c +++ b/source4/lib/socket/interface.c @@ -129,7 +129,11 @@ static void add_interface(TALLOC_CTX *mem_ctx, const struct iface_struct *ifs, s DEBUG(2,("netmask=%s\n", addr)); iface->nmask_s = talloc_strdup(iface, addr); - DLIST_ADD(*interfaces, iface); + /* + this needs to be a ADD_END, as some tests (such as the + spoolss notify test) depend on the interfaces ordering + */ + DLIST_ADD_END(*interfaces, iface, NULL); } /** -- cgit From 0204ae6229bae3573b3194c3f657c8f385c0b940 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 1 Jun 2011 11:24:51 +0930 Subject: lib/util/time.c: timeval_current_ofs_usec Several places want "microseconds from current time", and several were simply handing "usecs" values which could be over a million. Using a helper to do this is safer and more readable. I didn't replace any obviously correct callers (ie. constants). I also renamed wait_nsec in source3/lib/util_sock.c; it's actually microseconds not nanoseconds (introduced with this code in Volker's 19b783cc Async wrapper for open_socket_out_send/recv). Signed-off-by: Rusty Russell --- source4/lib/socket/connect_multi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/connect_multi.c b/source4/lib/socket/connect_multi.c index 300e5fb1e5..e3b58456c4 100644 --- a/source4/lib/socket/connect_multi.c +++ b/source4/lib/socket/connect_multi.c @@ -162,7 +162,7 @@ static void connect_multi_next_socket(struct composite_context *result) connect attempt state, so it will go away when this request completes */ event_add_timed(result->event_ctx, state, - timeval_current_ofs(0, MULTI_PORT_DELAY), + timeval_current_ofs_usec(MULTI_PORT_DELAY), connect_multi_timer, result); } } -- cgit From 2fc11518b7573bce3cdf2f2acf7dec024f22e9c6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 12 May 2011 12:23:35 +0200 Subject: s4-ipv6: added iface_list_wildcard() this returns a list of wildcard address to listen on, when we don't have 'bind interfaces only' set. It is a list, not a single address, we need to listen separately for the IPv6 "::" address from the IPv4 0.0.0.0 address. This also takes account of the loadparm "socket address" option --- source4/lib/socket/interface.c | 28 ++++++++++++++++++++++++++++ source4/lib/socket/wscript_build | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/interface.c b/source4/lib/socket/interface.c index b762f5573a..83d8e4c129 100644 --- a/source4/lib/socket/interface.c +++ b/source4/lib/socket/interface.c @@ -21,6 +21,7 @@ #include "includes.h" #include "system/network.h" +#include "param/param.h" #include "lib/socket/netif.h" #include "../lib/util/util_net.h" #include "../lib/util/dlinklist.h" @@ -428,3 +429,30 @@ bool iface_list_same_net(const char *ip1, const char *ip2, const char *netmask) interpret_addr2(ip2), interpret_addr2(netmask)); } + +/** + return the list of wildcard interfaces + this will include the IPv4 0.0.0.0, and may include IPv6 :: + it is overridden by the 'socket address' option in smb.conf +*/ +const char **iface_list_wildcard(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx) +{ + const char **ret; + const char *socket_address; + + /* the user may have configured a specific address */ + socket_address = lpcfg_socket_address(lp_ctx); + if (strcmp(socket_address, "") != 0) { + ret = (const char **)str_list_make(mem_ctx, socket_address, NULL); + return ret; + } + + ret = (const char **)str_list_make(mem_ctx, "0.0.0.0", NULL); + if (ret == NULL) return NULL; + +#ifdef HAVE_IPV6 + return str_list_add(ret, "::"); +#endif + + return ret; +} diff --git a/source4/lib/socket/wscript_build b/source4/lib/socket/wscript_build index fa497335fb..c10970d17a 100644 --- a/source4/lib/socket/wscript_build +++ b/source4/lib/socket/wscript_build @@ -2,7 +2,7 @@ bld.SAMBA_LIBRARY('netif', source='interface.c', - deps='samba-util interfaces', + deps='samba-util interfaces samba-hostconfig', private_library=True, autoproto='netif_proto.h' ) -- cgit From 62af4a3798995b0368625c0322bc9d5373bb0348 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 12 May 2011 12:26:18 +0200 Subject: s4-ipv6: allow IPv6 addresses in our interfaces list --- source4/lib/socket/interface.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/interface.c b/source4/lib/socket/interface.c index 83d8e4c129..9ae658da3e 100644 --- a/source4/lib/socket/interface.c +++ b/source4/lib/socket/interface.c @@ -92,11 +92,6 @@ static void add_interface(TALLOC_CTX *mem_ctx, const struct iface_struct *ifs, s return; } - if (ifs->ip.ss_family != AF_INET) { - DEBUG(5, ("not adding IPv6 interface %s\n", ifs->name)); - return; - } - iface = talloc(*interfaces == NULL ? mem_ctx : *interfaces, struct interface); if (iface == NULL) return; -- cgit From a527b96c968037db2d699493a9017709d053f95a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 12 May 2011 12:27:01 +0200 Subject: s4-ipv6: fixed a warning --- source4/lib/socket/interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/interface.c b/source4/lib/socket/interface.c index 9ae658da3e..0de44c1517 100644 --- a/source4/lib/socket/interface.c +++ b/source4/lib/socket/interface.c @@ -302,7 +302,7 @@ void load_interface_list(TALLOC_CTX *mem_ctx, const char **interfaces, struct in DEBUG(0,("ERROR: Could not determine network interfaces, you must use a interfaces config line\n")); } for (i=0;i Date: Thu, 12 May 2011 12:27:37 +0200 Subject: s4-ipv6: added ipv4 functions to interface code this adds iface_list_first_v4() and iface_list_n_is_v4(). The NBT server will use these to allow it to listen only for IPv4 addresses. --- source4/lib/socket/interface.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/interface.c b/source4/lib/socket/interface.c index 0de44c1517..3737f57f9b 100644 --- a/source4/lib/socket/interface.c +++ b/source4/lib/socket/interface.c @@ -348,6 +348,38 @@ const char *iface_list_n_ip(struct interface *ifaces, int n) return NULL; } + +/** + return the first IPv4 interface address we have registered + **/ +const char *iface_list_first_v4(struct interface *ifaces) +{ + struct interface *i; + + for (i=ifaces; i; i=i->next) { + if (i->ip.ss_family == AF_INET) { + return i->ip_s; + } + } + return NULL; +} + +/** + check if an interface is IPv4 + **/ +bool iface_list_n_is_v4(struct interface *ifaces, int n) +{ + struct interface *i; + + for (i=ifaces;i && n;i=i->next) + n--; + + if (i) { + return i->ip.ss_family == AF_INET; + } + return false; +} + /** return bcast of the Nth interface **/ -- cgit From 244137b10d511dedb1798b90aa2f4c354c50a44e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 12 May 2011 12:29:21 +0200 Subject: s4-ipv6: added socket_address_from_sockaddr_storage() this converts a struct sockaddr_storage to a struct socket_address --- source4/lib/socket/socket.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ source4/lib/socket/socket.h | 4 ++++ 2 files changed, 48 insertions(+) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index cecd1026d5..41638b3d72 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -510,6 +510,50 @@ _PUBLIC_ struct socket_address *socket_address_from_sockaddr(TALLOC_CTX *mem_ctx return addr; } + +/* + Create a new socket_address from sockaddr_storage + */ +_PUBLIC_ struct socket_address *socket_address_from_sockaddr_storage(TALLOC_CTX *mem_ctx, + const struct sockaddr_storage *sockaddr, + uint16_t port) +{ + struct socket_address *addr = talloc_zero(mem_ctx, struct socket_address); + char addr_str[INET6_ADDRSTRLEN+1]; + const char *str; + + if (!addr) { + return NULL; + } + addr->port = port; + switch (sockaddr->ss_family) { + case AF_INET: + addr->family = "ipv4"; + break; +#ifdef HAVE_IPV6 + case AF_INET6: + addr->family = "ipv6"; + break; +#endif + default: + talloc_free(addr); + return NULL; + } + + str = print_sockaddr(addr_str, sizeof(addr_str), sockaddr); + if (str == NULL) { + talloc_free(addr); + return NULL; + } + addr->addr = talloc_strdup(addr, str); + if (addr->addr == NULL) { + talloc_free(addr); + return NULL; + } + + return addr; +} + /* Copy a socket_address structure */ struct socket_address *socket_address_copy(TALLOC_CTX *mem_ctx, const struct socket_address *oaddr) diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h index 88360ac8f3..e00b61ba6c 100644 --- a/source4/lib/socket/socket.h +++ b/source4/lib/socket/socket.h @@ -174,6 +174,10 @@ struct socket_address *socket_address_from_strings(TALLOC_CTX *mem_ctx, struct socket_address *socket_address_from_sockaddr(TALLOC_CTX *mem_ctx, struct sockaddr *sockaddr, size_t addrlen); +struct sockaddr_storage; +struct socket_address *socket_address_from_sockaddr_storage(TALLOC_CTX *mem_ctx, + const struct sockaddr_storage *sockaddr, + uint16_t port); _PUBLIC_ void socket_address_set_port(struct socket_address *a, uint16_t port); struct socket_address *socket_address_copy(TALLOC_CTX *mem_ctx, -- cgit From df632483f18923430a6da595d07c9f241438e766 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 12 May 2011 12:30:16 +0200 Subject: s4-ipv6: fixed ipv6_listen() to use IPV6_V6ONLY this changes ipv6_listen() to use IPV6_V6ONLY, and to setup the right scope id for link local IPv6 addresses --- source4/lib/socket/socket_ip.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/socket_ip.c b/source4/lib/socket/socket_ip.c index 4e66653252..bf0aff74ec 100644 --- a/source4/lib/socket/socket_ip.c +++ b/source4/lib/socket/socket_ip.c @@ -667,9 +667,22 @@ static NTSTATUS ipv6_tcp_connect(struct socket_context *sock, return ip_connect_complete(sock, flags); } +/* + fix the sin6_scope_id based on the address interface + */ +static void fix_scope_id(struct sockaddr_in6 *in6, + const char *address) +{ + const char *p = strchr(address, '%'); + if (p != NULL) { + in6->sin6_scope_id = if_nametoindex(p+1); + } +} + + static NTSTATUS ipv6_listen(struct socket_context *sock, - const struct socket_address *my_address, - int queue_size, uint32_t flags) + const struct socket_address *my_address, + int queue_size, uint32_t flags) { struct sockaddr_in6 my_addr; struct in6_addr ip_addr; @@ -680,14 +693,21 @@ static NTSTATUS ipv6_listen(struct socket_context *sock, if (my_address->sockaddr) { ret = bind(sock->fd, my_address->sockaddr, my_address->sockaddrlen); } else { + int one = 1; ip_addr = interpret_addr6(my_address->addr); ZERO_STRUCT(my_addr); my_addr.sin6_addr = ip_addr; my_addr.sin6_port = htons(my_address->port); my_addr.sin6_family = PF_INET6; - - ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr)); + fix_scope_id(&my_addr, my_address->addr); + + /* when binding on ipv6 we always want to only bind on v6 */ + ret = setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, + (const void *)&one, sizeof(one)); + if (ret != -1) { + ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr)); + } } if (ret == -1) { -- cgit From 44d47e85157209f5aec1a6e0cd507c1084716816 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 2 Jun 2011 15:39:54 +1000 Subject: s4-ipv6: allow ipv6 to be enabled/disabled in smb.conf this adds the parametric option ipv6:enable=true/false It defaults to false for now, until the remaining issues with testing of ipv6 are resolved --- source4/lib/socket/interface.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/interface.c b/source4/lib/socket/interface.c index 3737f57f9b..00550a9ed4 100644 --- a/source4/lib/socket/interface.c +++ b/source4/lib/socket/interface.c @@ -75,7 +75,8 @@ static struct interface *iface_list_find(struct interface *interfaces, /**************************************************************************** add an interface to the linked list of interfaces ****************************************************************************/ -static void add_interface(TALLOC_CTX *mem_ctx, const struct iface_struct *ifs, struct interface **interfaces) +static void add_interface(TALLOC_CTX *mem_ctx, const struct iface_struct *ifs, struct interface **interfaces, + bool enable_ipv6) { char addr[INET6_ADDRSTRLEN]; struct interface *iface; @@ -92,6 +93,10 @@ static void add_interface(TALLOC_CTX *mem_ctx, const struct iface_struct *ifs, s return; } + if (!enable_ipv6 && ifs->ip.ss_family != AF_INET) { + return; + } + iface = talloc(*interfaces == NULL ? mem_ctx : *interfaces, struct interface); if (iface == NULL) return; @@ -147,7 +152,8 @@ static void interpret_interface(TALLOC_CTX *mem_ctx, const char *token, struct iface_struct *probed_ifaces, int total_probed, - struct interface **local_interfaces) + struct interface **local_interfaces, + bool enable_ipv6) { struct sockaddr_storage ss; struct sockaddr_storage ss_mask; @@ -163,7 +169,7 @@ static void interpret_interface(TALLOC_CTX *mem_ctx, for (i=0;i Date: Thu, 2 Jun 2011 15:40:28 +1000 Subject: s4-ipv6: update callers to load_interface_list() --- source4/lib/socket/testsuite.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/testsuite.c b/source4/lib/socket/testsuite.c index 518bc72501..357e4ae5df 100644 --- a/source4/lib/socket/testsuite.c +++ b/source4/lib/socket/testsuite.c @@ -42,7 +42,7 @@ static bool test_udp(struct torture_context *tctx) TALLOC_CTX *mem_ctx = tctx; struct interface *ifaces; - load_interface_list(tctx, lpcfg_interfaces(tctx->lp_ctx), &ifaces); + load_interface_list(tctx, tctx->lp_ctx, &ifaces); status = socket_create("ip", SOCKET_TYPE_DGRAM, &sock1, 0); torture_assert_ntstatus_ok(tctx, status, "creating DGRAM IP socket 1"); @@ -135,7 +135,7 @@ 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_interface_list(tctx, lpcfg_interfaces(tctx->lp_ctx), &ifaces); + load_interface_list(tctx, tctx->lp_ctx, &ifaces); localhost = socket_address_from_strings(sock1, sock1->backend_name, iface_list_best_ip(ifaces, "127.0.0.1"), 0); torture_assert(tctx, localhost, "Localhost not found"); -- cgit From dc1e6109c8bcc21831defd443fcf42427706c642 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 4 Jun 2011 07:59:54 +1000 Subject: s4-ipv6: enable IPv6 by default it now passes all tests --- source4/lib/socket/interface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/interface.c b/source4/lib/socket/interface.c index 00550a9ed4..96cee2fbe6 100644 --- a/source4/lib/socket/interface.c +++ b/source4/lib/socket/interface.c @@ -295,7 +295,7 @@ void load_interface_list(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, s int i; struct iface_struct *ifaces; int total_probed; - bool enable_ipv6 = lpcfg_parm_bool(lp_ctx, NULL, "ipv6", "enable", false); + bool enable_ipv6 = lpcfg_parm_bool(lp_ctx, NULL, "ipv6", "enable", true); *local_interfaces = NULL; @@ -485,7 +485,7 @@ const char **iface_list_wildcard(TALLOC_CTX *mem_ctx, struct loadparm_context *l if (ret == NULL) return NULL; #ifdef HAVE_IPV6 - if (lpcfg_parm_bool(lp_ctx, NULL, "ipv6", "enable", false)) { + if (lpcfg_parm_bool(lp_ctx, NULL, "ipv6", "enable", true)) { return str_list_add(ret, "::"); } #endif -- cgit From 3736f29696288f908aac4189aedfc7149c431caa Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 6 Jun 2011 10:11:53 +1000 Subject: s4-ipv6: use the server address family don't force v4 in connect_multi --- source4/lib/socket/connect_multi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/connect_multi.c b/source4/lib/socket/connect_multi.c index e3b58456c4..4ce5115e97 100644 --- a/source4/lib/socket/connect_multi.c +++ b/source4/lib/socket/connect_multi.c @@ -136,7 +136,7 @@ static void connect_multi_next_socket(struct composite_context *result) if (composite_nomem(state, result)) return; state->result = result; - result->status = socket_create("ipv4", SOCKET_TYPE_STREAM, &state->sock, 0); + result->status = socket_create(multi->server_address->family, SOCKET_TYPE_STREAM, &state->sock, 0); if (!composite_is_ok(result)) return; state->addr = socket_address_copy(state, multi->server_address); -- cgit From 25ac58dccef5d1da9946aeb191d6b6c4ee8782cf Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 6 Jun 2011 10:42:28 +1000 Subject: s4-ipv6: fix the address family for IPv6 string addresses --- source4/lib/socket/socket.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index 41638b3d72..369cf5ff36 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -473,6 +473,11 @@ _PUBLIC_ struct socket_address *socket_address_from_strings(TALLOC_CTX *mem_ctx, return NULL; } + if (strcmp(family, "ip") == 0 && is_ipaddress_v6(host)) { + /* leaving as "ip" would force IPv4 */ + family = "ipv6"; + } + addr->family = family; addr->addr = talloc_strdup(addr, host); if (!addr->addr) { -- cgit From d168a5e703288a5fba3f35a6e44d3f5d5733e6c5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 6 Jun 2011 11:31:23 +1000 Subject: s4-ipv6: fill in family when initialising from sockaddr Autobuild-User: Andrew Tridgell Autobuild-Date: Mon Jun 6 05:35:36 CEST 2011 on sn-devel-104 --- source4/lib/socket/socket.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index 369cf5ff36..b16e38c372 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -503,7 +503,19 @@ _PUBLIC_ struct socket_address *socket_address_from_sockaddr(TALLOC_CTX *mem_ctx if (!addr) { return NULL; } - addr->family = NULL; + switch (sockaddr->sa_family) { + case AF_INET: + addr->family = "ipv4"; + break; +#ifdef HAVE_IPV6 + case AF_INET6: + addr->family = "ipv6"; + break; +#endif + case AF_UNIX: + addr->family = "unix"; + break; + } addr->addr = NULL; addr->port = 0; addr->sockaddr = (struct sockaddr *)talloc_memdup(addr, sockaddr, sockaddrlen); -- cgit From 6a6d4d8884788c1e860bda886d168301623e1ea3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 6 Jun 2011 15:18:12 +1000 Subject: s4-ipv6: fix iface_list_best_ip() for IPv6 return an interface with the same address family as the target --- source4/lib/socket/interface.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/interface.c b/source4/lib/socket/interface.c index 96cee2fbe6..1bf1e4f62b 100644 --- a/source4/lib/socket/interface.c +++ b/source4/lib/socket/interface.c @@ -371,6 +371,23 @@ const char *iface_list_first_v4(struct interface *ifaces) return NULL; } +/** + return the first IPv6 interface address we have registered + **/ +static const char *iface_list_first_v6(struct interface *ifaces) +{ + struct interface *i; + +#ifdef HAVE_IPV6 + for (i=ifaces; i; i=i->next) { + if (i->ip.ss_family == AF_INET6) { + return i->ip_s; + } + } +#endif + return NULL; +} + /** check if an interface is IPv4 **/ @@ -435,7 +452,12 @@ const char *iface_list_best_ip(struct interface *ifaces, const char *dest) if (iface) { return iface->ip_s; } - return iface_list_n_ip(ifaces, 0); +#ifdef HAVE_IPV6 + if (ss.ss_family == AF_INET6) { + return iface_list_first_v6(ifaces); + } +#endif + return iface_list_first_v4(ifaces); } /** -- cgit From 3ccb72d7496aadbdf35b0aee3b2384466d9dd3b8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 7 Jun 2011 12:55:09 +1000 Subject: s4-ipv6: fixed iface_list_same_net() for IPv6 --- source4/lib/socket/interface.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/interface.c b/source4/lib/socket/interface.c index 1bf1e4f62b..9cb8f5e611 100644 --- a/source4/lib/socket/interface.c +++ b/source4/lib/socket/interface.c @@ -481,9 +481,21 @@ bool iface_list_is_local(struct interface *ifaces, const char *dest) */ bool iface_list_same_net(const char *ip1, const char *ip2, const char *netmask) { - return same_net_v4(interpret_addr2(ip1), - interpret_addr2(ip2), - interpret_addr2(netmask)); + struct sockaddr_storage ip1_ss, ip2_ss, nm_ss; + + if (!interpret_string_addr(&ip1_ss, ip1, AI_NUMERICHOST)) { + return false; + } + if (!interpret_string_addr(&ip2_ss, ip2, AI_NUMERICHOST)) { + return false; + } + if (!interpret_string_addr(&nm_ss, netmask, AI_NUMERICHOST)) { + return false; + } + + return same_net((struct sockaddr *)&ip1_ss, + (struct sockaddr *)&ip2_ss, + (struct sockaddr *)&nm_ss); } /** -- cgit From 79ef434b900288f23f352dcce083c37308baef2d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 8 Jun 2011 10:41:38 +1000 Subject: s4-interface: raise the debug level for interface discovery --- source4/lib/socket/interface.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/interface.c b/source4/lib/socket/interface.c index 9cb8f5e611..d5b610fea7 100644 --- a/source4/lib/socket/interface.c +++ b/source4/lib/socket/interface.c @@ -116,18 +116,18 @@ static void add_interface(TALLOC_CTX *mem_ctx, const struct iface_struct *ifs, s /* keep string versions too, to avoid people tripping over the implied static in inet_ntoa() */ print_sockaddr(addr, sizeof(addr), &iface->ip); - DEBUG(2,("added interface %s ip=%s ", + DEBUG(4,("added interface %s ip=%s ", iface->name, addr)); iface->ip_s = talloc_strdup(iface, addr); print_sockaddr(addr, sizeof(addr), &iface->bcast); - DEBUG(2,("bcast=%s ", addr)); + DEBUG(4,("bcast=%s ", addr)); iface->bcast_s = talloc_strdup(iface, addr); print_sockaddr(addr, sizeof(addr), &iface->netmask); - DEBUG(2,("netmask=%s\n", addr)); + DEBUG(4,("netmask=%s\n", addr)); iface->nmask_s = talloc_strdup(iface, addr); /* -- cgit From a1f04e8abc761ef1ba211420ff1dbda50fcf527d Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 20 Jun 2011 14:55:32 +1000 Subject: libcli/util Rename common map_nt_error_from_unix to avoid duplicate symbol The two error tables need to be combined, but for now seperate the names. (As the common parts of the tree now use the _common function, errmap_unix.c must be included in the s3 autoconf build). Andrew Bartlett Autobuild-User: Andrew Bartlett Autobuild-Date: Mon Jun 20 08:12:03 CEST 2011 on sn-devel-104 --- source4/lib/socket/socket.c | 2 +- source4/lib/socket/socket_ip.c | 58 ++++++++++++++++++++-------------------- source4/lib/socket/socket_unix.c | 16 +++++------ 3 files changed, 38 insertions(+), 38 deletions(-) (limited to 'source4/lib/socket') diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index b16e38c372..2dbdaad11d 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -451,7 +451,7 @@ _PUBLIC_ NTSTATUS socket_dup(struct socket_context *sock) } fd = dup(sock->fd); if (fd == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } close(sock->fd); sock->fd = fd; diff --git a/source4/lib/socket/socket_ip.c b/source4/lib/socket/socket_ip.c index bf0aff74ec..80f7d333f3 100644 --- a/source4/lib/socket/socket_ip.c +++ b/source4/lib/socket/socket_ip.c @@ -47,7 +47,7 @@ static NTSTATUS ipv4_init(struct socket_context *sock) sock->fd = socket(PF_INET, type, 0); if (sock->fd == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } sock->backend_name = "ipv4"; @@ -70,16 +70,16 @@ static NTSTATUS ip_connect_complete(struct socket_context *sock, uint32_t flags) for non-blocking connect */ ret = getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, &error, &len); if (ret == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } if (error != 0) { - return map_nt_error_from_unix(error); + return map_nt_error_from_unix_common(error); } if (!(flags & SOCKET_FLAG_BLOCK)) { ret = set_blocking(sock->fd, false); if (ret == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } } @@ -102,7 +102,7 @@ static NTSTATUS ipv4_connect(struct socket_context *sock, if (my_address && my_address->sockaddr) { ret = bind(sock->fd, my_address->sockaddr, my_address->sockaddrlen); if (ret == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } } else if (my_address) { my_ip = interpret_addr2(my_address->addr); @@ -119,7 +119,7 @@ static NTSTATUS ipv4_connect(struct socket_context *sock, ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr)); if (ret == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } } } @@ -127,7 +127,7 @@ static NTSTATUS ipv4_connect(struct socket_context *sock, if (srv_address->sockaddr) { ret = connect(sock->fd, srv_address->sockaddr, srv_address->sockaddrlen); if (ret == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } } else { srv_ip = interpret_addr2(srv_address->addr); @@ -147,7 +147,7 @@ static NTSTATUS ipv4_connect(struct socket_context *sock, ret = connect(sock->fd, (const struct sockaddr *)&srv_addr, sizeof(srv_addr)); if (ret == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } } @@ -186,20 +186,20 @@ static NTSTATUS ipv4_listen(struct socket_context *sock, } if (ret == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } if (sock->type == SOCKET_TYPE_STREAM) { ret = listen(sock->fd, queue_size); if (ret == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } } if (!(flags & SOCKET_FLAG_BLOCK)) { ret = set_blocking(sock->fd, false); if (ret == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } } @@ -220,14 +220,14 @@ static NTSTATUS ipv4_accept(struct socket_context *sock, struct socket_context * new_fd = accept(sock->fd, (struct sockaddr *)&cli_addr, &cli_addr_len); if (new_fd == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } if (!(sock->flags & SOCKET_FLAG_BLOCK)) { int ret = set_blocking(new_fd, false); if (ret == -1) { close(new_fd); - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } } @@ -268,7 +268,7 @@ static NTSTATUS ip_recv(struct socket_context *sock, void *buf, if (gotlen == 0) { return NT_STATUS_END_OF_FILE; } else if (gotlen == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } *nread = gotlen; @@ -311,7 +311,7 @@ static NTSTATUS ipv4_recvfrom(struct socket_context *sock, void *buf, return NT_STATUS_END_OF_FILE; } else if (gotlen == -1) { talloc_free(src); - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } src->sockaddrlen = from_len; @@ -342,7 +342,7 @@ static NTSTATUS ip_send(struct socket_context *sock, len = send(sock->fd, blob->data, blob->length, 0); if (len == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } *sendlen = len; @@ -383,7 +383,7 @@ static NTSTATUS ipv4_sendto(struct socket_context *sock, (struct sockaddr *)&srv_addr, sizeof(srv_addr)); } if (len == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } *sendlen = len; @@ -518,7 +518,7 @@ static NTSTATUS ip_pending(struct socket_context *sock, size_t *npending) *npending = value; return NT_STATUS_OK; } - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } static const struct socket_ops ipv4_ops = { @@ -604,7 +604,7 @@ static NTSTATUS ipv6_init(struct socket_context *sock) sock->fd = socket(PF_INET6, type, 0); if (sock->fd == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } sock->backend_name = "ipv6"; @@ -623,7 +623,7 @@ static NTSTATUS ipv6_tcp_connect(struct socket_context *sock, if (my_address && my_address->sockaddr) { ret = bind(sock->fd, my_address->sockaddr, my_address->sockaddrlen); if (ret == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } } else if (my_address) { struct in6_addr my_ip; @@ -638,7 +638,7 @@ static NTSTATUS ipv6_tcp_connect(struct socket_context *sock, ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr)); if (ret == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } } } @@ -661,7 +661,7 @@ static NTSTATUS ipv6_tcp_connect(struct socket_context *sock, ret = connect(sock->fd, (const struct sockaddr *)&srv_addr, sizeof(srv_addr)); } if (ret == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } return ip_connect_complete(sock, flags); @@ -711,20 +711,20 @@ static NTSTATUS ipv6_listen(struct socket_context *sock, } if (ret == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } if (sock->type == SOCKET_TYPE_STREAM) { ret = listen(sock->fd, queue_size); if (ret == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } } if (!(flags & SOCKET_FLAG_BLOCK)) { ret = set_blocking(sock->fd, false); if (ret == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } } @@ -745,14 +745,14 @@ static NTSTATUS ipv6_tcp_accept(struct socket_context *sock, struct socket_conte new_fd = accept(sock->fd, (struct sockaddr *)&cli_addr, &cli_addr_len); if (new_fd == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } if (!(sock->flags & SOCKET_FLAG_BLOCK)) { int ret = set_blocking(new_fd, false); if (ret == -1) { close(new_fd); - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } } @@ -816,7 +816,7 @@ static NTSTATUS ipv6_recvfrom(struct socket_context *sock, void *buf, return NT_STATUS_END_OF_FILE; } else if (gotlen == -1) { talloc_free(src); - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } src->sockaddrlen = from_len; @@ -867,7 +867,7 @@ static NTSTATUS ipv6_sendto(struct socket_context *sock, (struct sockaddr *)&srv_addr, sizeof(srv_addr)); } if (len == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } *sendlen = len; diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index f1fa0a3a30..d492f01268 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -33,7 +33,7 @@ _PUBLIC_ const struct socket_ops *socket_unixdom_ops(enum socket_type type); */ static NTSTATUS unixdom_error(int ernum) { - return map_nt_error_from_unix(ernum); + return map_nt_error_from_unix_common(ernum); } static NTSTATUS unixdom_init(struct socket_context *sock) @@ -53,7 +53,7 @@ static NTSTATUS unixdom_init(struct socket_context *sock) sock->fd = socket(PF_UNIX, type, 0); if (sock->fd == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } sock->private_data = NULL; @@ -76,16 +76,16 @@ static NTSTATUS unixdom_connect_complete(struct socket_context *sock, uint32_t f for non-blocking connect */ ret = getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, &error, &len); if (ret == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } if (error != 0) { - return map_nt_error_from_unix(error); + return map_nt_error_from_unix_common(error); } if (!(flags & SOCKET_FLAG_BLOCK)) { ret = set_blocking(sock->fd, false); if (ret == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } } @@ -194,7 +194,7 @@ static NTSTATUS unixdom_accept(struct socket_context *sock, int ret = set_blocking(new_fd, false); if (ret == -1) { close(new_fd); - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } } @@ -280,7 +280,7 @@ static NTSTATUS unixdom_sendto(struct socket_context *sock, (struct sockaddr *)&srv_addr, sizeof(srv_addr)); } if (len == -1) { - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } *sendlen = len; @@ -390,7 +390,7 @@ static NTSTATUS unixdom_pending(struct socket_context *sock, size_t *npending) *npending = value; return NT_STATUS_OK; } - return map_nt_error_from_unix(errno); + return map_nt_error_from_unix_common(errno); } static const struct socket_ops unixdom_ops = { -- cgit