summaryrefslogtreecommitdiff
path: root/source3/lib
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2007-10-10 18:25:16 -0700
committerJeremy Allison <jra@samba.org>2007-10-10 18:25:16 -0700
commit8e54530b52fd256137740107e9fdf000f00a7a30 (patch)
treef9ca56cc0b2eff78c3550c924c79ee4ca0666fd2 /source3/lib
parent0ec55a246238b6cfb3727942c20cd55a16ab4d4a (diff)
downloadsamba-8e54530b52fd256137740107e9fdf000f00a7a30.tar.gz
samba-8e54530b52fd256137740107e9fdf000f00a7a30.tar.bz2
samba-8e54530b52fd256137740107e9fdf000f00a7a30.zip
Add start of IPv6 implementation. Currently most of this is avoiding
IPv6 in winbindd, but moves most of the socket functions that were wrongly in lib/util.c into lib/util_sock.c and provides generic IPv4/6 independent versions of most things. Still lots of work to do, but now I can see how I'll fix the access check code. Nasty part that remains is the name resolution code which is used to returning arrays of in_addr structs. Jeremy. (This used to be commit 3f6bd0e1ec5cc6670f3d08f76fc2cd94c9cd1a08)
Diffstat (limited to 'source3/lib')
-rw-r--r--source3/lib/access.c2
-rw-r--r--source3/lib/interface.c644
-rw-r--r--source3/lib/interfaces.c258
-rw-r--r--source3/lib/util.c189
-rw-r--r--source3/lib/util_sock.c515
-rw-r--r--source3/lib/wins_srv.c10
6 files changed, 1112 insertions, 506 deletions
diff --git a/source3/lib/access.c b/source3/lib/access.c
index 303e3ed4c4..17f4c367eb 100644
--- a/source3/lib/access.c
+++ b/source3/lib/access.c
@@ -279,7 +279,7 @@ static BOOL only_ipaddrs_in_list(const char** list)
continue;
}
- if (!is_ipaddress(*list)) {
+ if (!is_ipaddress_v4(*list)) {
/*
* if we failed, make sure that it was not because the token
* was a network/netmask pair. Only network/netmask pairs
diff --git a/source3/lib/interface.c b/source3/lib/interface.c
index 5982d82e47..1471a06f46 100644
--- a/source3/lib/interface.c
+++ b/source3/lib/interface.c
@@ -2,6 +2,7 @@
Unix SMB/CIFS implementation.
multiple interface handling
Copyright (C) Andrew Tridgell 1992-1998
+ Copyright (C) Jeremy Allison 2007
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -22,66 +23,404 @@
static struct iface_struct *probed_ifaces;
static int total_probed;
-struct in_addr allones_ip;
-struct in_addr loopback_ip;
-
static struct interface *local_interfaces;
-#define ALLONES ((uint32)0xFFFFFFFF)
-#define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES))
-#define MKNETADDR(_IP, _NM) (_IP & _NM)
+/****************************************************************************
+ Check if an IP is one of mine.
+**************************************************************************/
+
+bool ismyaddr(const struct sockaddr_storage *ip)
+{
+ struct interface *i;
+ for (i=local_interfaces;i;i=i->next) {
+ if (addr_equal(&i->ip,ip)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool ismyip_v4(struct in_addr ip)
+{
+ struct sockaddr_storage ss;
+ in_addr_to_sockaddr_storage(&ss, ip);
+ return ismyaddr(&ss);
+}
/****************************************************************************
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(const struct sockaddr_storage *ip,
+ bool check_mask)
{
struct interface *i;
- if (is_zero_ip(ip)) return local_interfaces;
- for (i=local_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;
+ if (is_address_any(ip)) {
+ return local_interfaces;
+ }
+
+ for (i=local_interfaces;i;i=i->next) {
+ if (check_mask) {
+ if (same_net(ip, &i->ip, &i->netmask)) {
+ return i;
+ }
+ } else if (addr_equal(&i->ip, ip)) {
+ return i;
+ }
+ }
return NULL;
}
/****************************************************************************
+ Check if a packet is from a local (known) net.
+**************************************************************************/
+
+bool is_local_net(const struct sockaddr_storage *from)
+{
+ struct interface *i;
+ for (i=local_interfaces;i;i=i->next) {
+ if (same_net(from, &i->ip, &i->netmask)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/****************************************************************************
+ Check if a packet is from a local (known) net.
+**************************************************************************/
+
+bool is_local_net_v4(struct in_addr from)
+{
+ struct sockaddr_storage ss;
+
+ in_addr_to_sockaddr_storage(&ss, from);
+ return is_local_net(&ss);
+}
+
+/****************************************************************************
+ How many interfaces do we have ?
+**************************************************************************/
+
+int iface_count(void)
+{
+ int ret = 0;
+ struct interface *i;
+
+ for (i=local_interfaces;i;i=i->next) {
+ ret++;
+ }
+ return ret;
+}
+
+/****************************************************************************
+ How many interfaces do we have (v4 only) ?
+**************************************************************************/
+
+int iface_count_v4(void)
+{
+ int ret = 0;
+ struct interface *i;
+
+ for (i=local_interfaces;i;i=i->next) {
+ if (i->ip.ss_family == AF_INET) {
+ ret++;
+ }
+ }
+ return ret;
+}
+
+/****************************************************************************
+ Return a pointer to the in_addr of the first IPv4 interface.
+**************************************************************************/
+
+const struct in_addr *first_ipv4_iface(void)
+{
+ struct interface *i;
+
+ for (i=local_interfaces;i ;i=i->next) {
+ if (i->ip.ss_family == AF_INET) {
+ break;
+ }
+ }
+
+ if (!i) {
+ return NULL;
+ }
+ return &((const struct sockaddr_in *)&i->ip)->sin_addr;
+}
+
+/****************************************************************************
+ Return the Nth interface.
+**************************************************************************/
+
+struct interface *get_interface(int n)
+{
+ struct interface *i;
+
+ for (i=local_interfaces;i && n;i=i->next) {
+ n--;
+ }
+
+ if (i) {
+ return i;
+ }
+ return NULL;
+}
+
+/****************************************************************************
+ Return IP sockaddr_storage of the Nth interface.
+**************************************************************************/
+
+const struct sockaddr_storage *iface_n_sockaddr_storage(int n)
+{
+ struct interface *i;
+
+ for (i=local_interfaces;i && n;i=i->next) {
+ n--;
+ }
+
+ if (i) {
+ return &i->ip;
+ }
+ return NULL;
+}
+
+/****************************************************************************
+ Return IPv4 of the Nth interface (if a v4 address). NULL otherwise.
+**************************************************************************/
+
+const struct in_addr *iface_n_ip_v4(int n)
+{
+ struct interface *i;
+
+ for (i=local_interfaces;i && n;i=i->next) {
+ n--;
+ }
+
+ if (i && i->ip.ss_family == AF_INET) {
+ return &((const struct sockaddr_in *)&i->ip)->sin_addr;
+ }
+ return NULL;
+}
+
+/****************************************************************************
+ Return IPv4 bcast of the Nth interface (if a v4 address). NULL otherwise.
+**************************************************************************/
+
+const struct in_addr *iface_n_bcast_v4(int n)
+{
+ struct interface *i;
+
+ for (i=local_interfaces;i && n;i=i->next) {
+ n--;
+ }
+
+ if (i && i->ip.ss_family == AF_INET) {
+ return &((const struct sockaddr_in *)&i->bcast)->sin_addr;
+ }
+ return NULL;
+}
+
+/****************************************************************************
+ Return bcast of the Nth interface.
+**************************************************************************/
+
+const struct sockaddr_storage *iface_n_bcast(int n)
+{
+ struct interface *i;
+
+ for (i=local_interfaces;i && n;i=i->next) {
+ n--;
+ }
+
+ if (i) {
+ return &i->bcast;
+ }
+ return NULL;
+}
+
+/* these 3 functions return the ip/bcast/nmask for the interface
+ most appropriate for the given ip address. If they can't find
+ an appropriate interface they return the requested field of the
+ first known interface. */
+
+const struct sockaddr_storage *iface_ip(const struct sockaddr_storage *ip)
+{
+ struct interface *i = iface_find(ip, true);
+ if (i) {
+ return &i->ip;
+ }
+
+ /* Search for the first interface with
+ * matching address family. */
+
+ for (i=local_interfaces;i;i=i->next) {
+ if (i->ip.ss_family == ip->ss_family) {
+ return &i->ip;
+ }
+ }
+ return NULL;
+}
+
+/*
+ return True if a IP is directly reachable on one of our interfaces
+*/
+
+bool iface_local(struct sockaddr_storage *ip)
+{
+ return iface_find(ip, True) ? true : false;
+}
+
+/****************************************************************************
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(const struct iface_struct *ifs)
{
+ char addr[INET6_ADDRSTRLEN];
struct interface *iface;
- if (iface_find(ip, False)) {
- DEBUG(3,("not adding duplicate interface %s\n",inet_ntoa(ip)));
+
+ if (iface_find(&ifs->ip, False)) {
+ DEBUG(3,("add_interface: not adding duplicate interface %s\n",
+ print_sockaddr(addr, sizeof(addr),
+ &ifs->ip, sizeof(struct sockaddr_storage)) ));
return;
}
-#if !defined(__s390__)
- if (ip_equal(nmask, allones_ip)) {
+ if (!(ifs->flags & IFF_BROADCAST)) {
DEBUG(3,("not adding non-broadcast interface %s\n",
- inet_ntoa(ip)));
+ ifs->name ));
return;
}
-#endif
iface = SMB_MALLOC_P(struct interface);
- if (!iface) return;
+ if (!iface) {
+ return;
+ }
ZERO_STRUCTPN(iface);
- iface->ip = ip;
- iface->nmask = nmask;
- iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
+ iface->name = SMB_STRDUP(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;
DLIST_ADD(local_interfaces, iface);
- DEBUG(2,("added interface ip=%s ",inet_ntoa(iface->ip)));
- DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
- DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));
+ DEBUG(2,("added interface %s ip=%s ",
+ iface->name,
+ print_sockaddr(addr, sizeof(addr),
+ &iface->ip, sizeof(struct sockaddr_storage)) ));
+ DEBUG(2,("bcast=%s ",
+ print_sockaddr(addr, sizeof(addr),
+ &iface->bcast,
+ sizeof(struct sockaddr_storage)) ));
+ DEBUG(2,("netmask=%s\n",
+ print_sockaddr(addr, sizeof(addr),
+ &iface->netmask,
+ sizeof(struct sockaddr_storage)) ));
+}
+
+/****************************************************************************
+ Create a struct sockaddr_storage with the netmask bits set to 1.
+****************************************************************************/
+
+static 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(AF_INET6)
+ 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)
+{
+ 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(AF_INET6)
+ if (pss_in->ss_family == AF_INET6) {
+ p = (char *)&((struct sockaddr_in6 *)pss_out)->sin6_addr;
+ pmask = (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 = (char *)&((struct sockaddr_in *)nmask)->sin_addr;
+ len = 4;
+ }
+
+ for (i = 0; i < len; i++, p++, pmask++) {
+ if (make_bcast) {
+ *p = (*p & *pmask) | (*pmask ^ 0xff);
+ } else {
+ /* make_net */
+ *p = (*p & *pmask);
+ }
+ }
+}
+
+static 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);
+}
+
+static 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);
}
/****************************************************************************
@@ -98,68 +437,121 @@ static void add_interface(struct in_addr ip, struct in_addr nmask)
static void interpret_interface(char *token)
{
- 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;
- int i, added=0;
-
- zero_ip(&ip);
- zero_ip(&nmask);
+ int i;
+ bool added=false;
+ bool goodaddr = false;
/* 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].iface_addr.ip,
- probed_ifaces[i].iface_netmask.netmask);
- added = 1;
+ add_interface(&probed_ifaces[i]);
+ added = true;
}
}
- if (added) return;
+ if (added) {
+ return;
+ }
/* maybe it is a DNS name */
p = strchr_m(token,'/');
- if (!p) {
- ip = *interpret_addr2(token);
+ if (!p && interpret_string_addr(&ss, token)) {
for (i=0;i<total_probed;i++) {
- if (ip.s_addr == probed_ifaces[i].iface_addr.ip.s_addr
- && !ip_equal(allones_ip,
- probed_ifaces[i].iface_netmask.netmask)) {
- add_interface(probed_ifaces[i].iface_addr.ip,
- probed_ifaces[i].iface_netmask.netmask);
+ if (addr_equal(&ss, &probed_ifaces[i].ip)) {
+ add_interface(&probed_ifaces[i]);
return;
}
}
- DEBUG(2,("can't determine netmask for %s\n", token));
+ DEBUG(2,("interpret_interface: "
+ "can't determine interface for %s\n",
+ token));
return;
}
/* parse it into an IP address/netmasklength pair */
*p = 0;
- ip = *interpret_addr2(token);
+ goodaddr = interpret_string_addr(&ss, token);
*p++ = '/';
+ if (!goodaddr) {
+ DEBUG(2,("interpret_interface: "
+ "can't determine interface for %s\n",
+ token));
+ return;
+ }
+
if (strlen(p) > 2) {
- nmask = *interpret_addr2(p);
+ goodaddr = interpret_string_addr(&ss_mask, p);
+ 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 (addr_equal(&ss_bcast, &ss) || addr_equal(&ss_net, &ss)) {
for (i=0;i<total_probed;i++) {
- if (same_net(ip, probed_ifaces[i].iface_addr.ip,
- nmask)) {
- add_interface(probed_ifaces[i].iface_addr.ip,
- nmask);
+ if (same_net(&ss, &probed_ifaces[i].ip, &ss_mask)) {
+ /* Temporarily replace netmask on
+ * the detected interface - user knows
+ * best.... */
+ struct sockaddr_storage saved_mask =
+ probed_ifaces[i].netmask;
+ probed_ifaces[i].netmask = ss_mask;
+ DEBUG(2,("interpret_interface: "
+ "using netmask value %s from "
+ "config file on interface %s\n",
+ p,
+ probed_ifaces[i].name));
+ add_interface(&probed_ifaces[i]);
+ probed_ifaces[i].netmask = saved_mask;
return;
}
}
- DEBUG(2,("Can't determine ip for broadcast address %s\n",
- token));
+ DEBUG(2,("interpret_interface: Can't determine ip for "
+ "broadcast address %s\n",
+ token));
return;
}
- add_interface(ip, nmask);
+ /* Just fake up the interface definition. User knows best. */
+
+ DEBUG(2,("interpret_interface: Adding interface %s\n",
+ token));
+
+ ZERO_STRUCT(ifs);
+ safe_strcpy(ifs.name, token, sizeof(ifs.name)-1);
+ ifs.flags = IFF_BROADCAST;
+ ifs.ip = ss;
+ ifs.netmask = ss_mask;
+ ifs.bcast = ss_bcast;
+ add_interface(&ifs);
}
/****************************************************************************
@@ -168,14 +560,9 @@ static void interpret_interface(char *token)
void load_interfaces(void)
{
- const char **ptr;
- int i;
struct iface_struct ifaces[MAX_INTERFACES];
-
- ptr = lp_interfaces();
-
- allones_ip = *interpret_addr2("255.255.255.255");
- loopback_ip = *interpret_addr2("127.0.0.1");
+ const char **ptr = lp_interfaces();
+ int i;
SAFE_FREE(probed_ifaces);
@@ -183,11 +570,11 @@ void load_interfaces(void)
while (local_interfaces) {
struct interface *iface = local_interfaces;
DLIST_REMOVE(local_interfaces, local_interfaces);
- ZERO_STRUCTPN(iface);
+ SAFE_FREE(iface->name);
SAFE_FREE(iface);
}
- /* probe the kernel for interfaces */
+ /* Probe the kernel for interfaces */
total_probed = get_interfaces(ifaces, MAX_INTERFACES);
if (total_probed > 0) {
@@ -208,15 +595,8 @@ void load_interfaces(void)
exit(1);
}
for (i=0;i<total_probed;i++) {
- if (
-#if !defined(__s390__)
- probed_ifaces[i].iface_netmask.netmask.s_addr !=
- allones_ip.s_addr &&
-#endif
- probed_ifaces[i].iface_addr.ip.s_addr !=
- loopback_ip.s_addr) {
- add_interface(probed_ifaces[i].iface_addr.ip,
- probed_ifaces[i].iface_netmask.netmask);
+ if (probed_ifaces[i].flags & IFF_BROADCAST) {
+ add_interface(&probed_ifaces[i]);
}
}
return;
@@ -244,7 +624,7 @@ void gfree_interfaces(void)
while (local_interfaces) {
struct interface *iface = local_interfaces;
DLIST_REMOVE(local_interfaces, local_interfaces);
- ZERO_STRUCTPN(iface);
+ SAFE_FREE(iface->name);
SAFE_FREE(iface);
}
@@ -255,7 +635,7 @@ void gfree_interfaces(void)
Return True if the list of probed interfaces has changed.
****************************************************************************/
-BOOL interfaces_changed(void)
+bool interfaces_changed(void)
{
int n;
struct iface_struct ifaces[MAX_INTERFACES];
@@ -263,115 +643,9 @@ BOOL interfaces_changed(void)
n = get_interfaces(ifaces, MAX_INTERFACES);
if ((n > 0 )&& (n != total_probed ||
- memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) {
- return True;
- }
-
- return False;
-}
-
-/****************************************************************************
- Check if an IP is one of mine.
-**************************************************************************/
-
-BOOL ismyip(struct in_addr ip)
-{
- struct interface *i;
- for (i=local_interfaces;i;i=i->next)
- if (ip_equal(i->ip,ip)) return True;
- return False;
-}
-
-/****************************************************************************
- Check if a packet is from a local (known) net.
-**************************************************************************/
-
-BOOL is_local_net(struct in_addr from)
-{
- struct interface *i;
- for (i=local_interfaces;i;i=i->next) {
- if((from.s_addr & i->nmask.s_addr) ==
- (i->ip.s_addr & i->nmask.s_addr))
- return True;
+ memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) {
+ return true;
}
- return False;
-}
-
-/****************************************************************************
- How many interfaces do we have
-**************************************************************************/
-
-int iface_count(void)
-{
- int ret = 0;
- struct interface *i;
-
- for (i=local_interfaces;i;i=i->next)
- ret++;
- return ret;
-}
-
-/****************************************************************************
- Return the Nth interface.
-**************************************************************************/
-
-struct interface *get_interface(int n)
-{
- struct interface *i;
-
- for (i=local_interfaces;i && n;i=i->next)
- n--;
-
- if (i) return i;
- return NULL;
-}
-
-/****************************************************************************
- Return IP of the Nth interface.
-**************************************************************************/
-
-struct in_addr *iface_n_ip(int n)
-{
- struct interface *i;
-
- for (i=local_interfaces;i && n;i=i->next)
- n--;
-
- if (i) return &i->ip;
- return NULL;
-}
-
-/****************************************************************************
- Return bcast of the Nth interface.
-**************************************************************************/
-
-struct in_addr *iface_n_bcast(int n)
-{
- struct interface *i;
-
- for (i=local_interfaces;i && n;i=i->next)
- n--;
-
- if (i) return &i->bcast;
- return NULL;
-}
-/* these 3 functions return the ip/bcast/nmask for the interface
- most appropriate for the given ip address. If they can't find
- an appropriate interface they return the requested field of the
- first known interface. */
-
-struct in_addr *iface_ip(struct in_addr ip)
-{
- struct interface *i = iface_find(ip, True);
- return(i ? &i->ip : &local_interfaces->ip);
-}
-
-/*
- return True if a IP is directly reachable on one of our interfaces
-*/
-
-BOOL iface_local(struct in_addr ip)
-{
- return iface_find(ip, True) ? True : False;
+ return false;
}
diff --git a/source3/lib/interfaces.c b/source3/lib/interfaces.c
index 632b38f2b6..c56155c64e 100644
--- a/source3/lib/interfaces.c
+++ b/source3/lib/interfaces.c
@@ -101,6 +101,7 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
struct ifaddrs *iflist = NULL;
struct ifaddrs *ifptr = NULL;
int total = 0;
+ size_t copy_size;
if (getifaddrs(&iflist) < 0) {
return -1;
@@ -111,25 +112,40 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
ifptr != NULL && total < max_interfaces;
ifptr = ifptr->ifa_next) {
+ memset(&ifaces[total], '\0', sizeof(ifaces[total]));
+
+ copy_size = sizeof(struct sockaddr_in);
+
if (!ifptr->ifa_addr || !ifptr->ifa_netmask) {
continue;
}
- /* Skip ipv6 for now. */
- if (ifptr->ifa_addr->sa_family != AF_INET) {
- continue;
- }
- if (!(ifptr->ifa_flags & IFF_UP)) {
+ ifaces[total].flags = ifptr->ifa_flags;
+
+ /* Check the interface is up. */
+ if (!(ifaces[total].flags & IFF_UP)) {
continue;
}
- ifaces[total].sa_family = ifptr->ifa_addr->sa_family;
-
- ifaces[total].iface_addr.ip =
- ((struct sockaddr_in *)ifptr->ifa_addr)->sin_addr;
+#ifdef AF_INET6
+ if (ifptr->ifa_addr->sa_family == AF_INET6) {
+ copy_size = sizeof(struct sockaddr_in6);
+ }
+#endif
- ifaces[total].iface_netmask.netmask =
- ((struct sockaddr_in *)ifptr->ifa_netmask)->sin_addr;
+ memcpy(&ifaces[total].ip, ifptr->ifa_addr, copy_size);
+ memcpy(&ifaces[total].netmask, ifptr->ifa_netmask, copy_size);
+ if (ifaces[total].flags & IFF_BROADCAST) {
+ memcpy(&ifaces[total].bcast,
+ ifptr->ifa_broadaddr,
+ copy_size);
+ } else if (ifaces[total].flags & IFF_POINTOPOINT) {
+ memcpy(&ifaces[total].bcast,
+ ifptr->ifa_dstaddr,
+ copy_size);
+ } else {
+ continue;
+ }
strncpy(ifaces[total].name, ifptr->ifa_name,
sizeof(ifaces[total].name)-1);
@@ -162,9 +178,6 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
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;
@@ -184,32 +197,54 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
/* 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) {
+
+ memset(&ifaces[total], '\0', sizeof(ifaces[total]));
+
+ /* Check the interface is up. */
+ if (ioctl(fd, SIOCGIFFLAGS, &ifr[i]) != 0) {
continue;
}
- iname = ifr[i].ifr_name;
- ipaddr = (*(struct sockaddr_in *)&ifr[i].ifr_addr).sin_addr;
+ ifaces[total].flags = ifr[i].ifr_flags;
- if (ioctl(fd, SIOCGIFFLAGS, &ifr[i]) != 0) {
+ if (!(flags & IFF_UP)) {
continue;
}
- if (!(ifr[i].ifr_flags & IFF_UP)) {
+ if (ioctl(fd, SIOCGIFADDR, &ifr[i]) != 0) {
continue;
}
+ strncpy(ifaces[total].name, ifr[i].ifr_name,
+ sizeof(ifaces[total].name)-1);
+ ifaces[total].name[sizeof(ifaces[total].name)-1] = 0;
+
+ memcpy(&ifaces[total].ip, &ifr[i].ifr_addr,
+ sizeof(struct sockaddr_in));
+
if (ioctl(fd, SIOCGIFNETMASK, &ifr[i]) != 0) {
continue;
}
- nmask = ((struct sockaddr_in *)&ifr[i].ifr_addr)->sin_addr;
+ memcpy(&ifaces[total].netmask, &ifr[i].ifr_netmask,
+ sizeof(struct sockaddr_in));
+
+ if (ifaces[total].flags & IFF_BROADCAST) {
+ if (ioctl(fd, SIOCGIFBRDADDR, &ifr[i]) != 0) {
+ continue;
+ }
+ memcpy(&ifaces[total].bcast, &ifr[i].ifr_broadaddr,
+ sizeof(struct sockaddr_in));
+ } else if (ifaces[total].flags & IFF_POINTOPOINT) {
+ if (ioctl(fd, SIOCGIFDSTADDR, &ifr[i]) != 0) {
+ continue;
+ }
+ memcpy(&ifaces[total].bcast, &ifr[i].ifr_dstaddr,
+ sizeof(struct sockaddr_in));
+ } else {
+ continue;
+ }
- strncpy(ifaces[total].name, iname, sizeof(ifaces[total].name)-1);
- ifaces[total].name[sizeof(ifaces[total].name)-1] = 0;
- ifaces[total].sa_family = AF_INET;
- ifaces[total].iface_addr.ip = ipaddr;
- ifaces[total].iface_netmask.netmask = nmask;
total++;
}
@@ -239,9 +274,6 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
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;
@@ -271,6 +303,9 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
/* Loop through interfaces */
for (i = 0; i<n && total < max_interfaces; i++) {
+
+ memset(&ifaces[total], '\0', sizeof(ifaces[total]));
+
ifreq = ifr[i];
strioctl.ic_cmd = SIOCGIFFLAGS;
@@ -280,7 +315,9 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
continue;
}
- if (!(ifreq.ifr_flags & IFF_UP)) {
+ ifaces[total].flags = ifreq.ifr_flags;
+
+ if (!(ifaces[total].flags & IFF_UP)) {
continue;
}
@@ -291,8 +328,12 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
continue;
}
- ipaddr = (*(struct sockaddr_in *) &ifreq.ifr_addr).sin_addr;
- iname = ifreq.ifr_name;
+ strncpy(ifaces[total].name, iname,
+ sizeof(ifaces[total].name)-1);
+ ifaces[total].name[sizeof(ifaces[total].name)-1] = 0;
+
+ memcpy(&ifaces[total].ip, &ifreq.ifr_addr,
+ sizeof(struct sockaddr_in));
strioctl.ic_cmd = SIOCGIFNETMASK;
strioctl.ic_dp = (char *)&ifreq;
@@ -301,13 +342,30 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
continue;
}
- nmask = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
+ memcpy(&ifaces[total].netmask, &ifreq.ifr_addr,
+ sizeof(struct sockaddr_in));
- strncpy(ifaces[total].name, iname, sizeof(ifaces[total].name)-1);
- ifaces[total].name[sizeof(ifaces[total].name)-1] = 0;
- ifaces[total].sa_family = AF_INET;
- ifaces[total].iface_addr.ip = ipaddr;
- ifaces[total].iface_netmask.netmask = nmask;
+ if (ifaces[total].flags & IFF_BROADCAST) {
+ strioctl.ic_cmd = SIOCGIFBRDADDR;
+ strioctl.ic_dp = (char *)&ifreq;
+ strioctl.ic_len = sizeof(struct ifreq);
+ if (ioctl(fd, I_STR, &strioctl) != 0) {
+ continue;
+ }
+ memcpy(&ifaces[total].bcast, &ifreq.ifr_broadaddr,
+ sizeof(struct sockaddr_in));
+ } else if (ifaces[total].flags & IFF_POINTOPOINT) {
+ strioctl.ic_cmd = SIOCGIFDSTADDR;
+ strioctl.ic_dp = (char *)&ifreq;
+ strioctl.ic_len = sizeof(struct ifreq);
+ if (ioctl(fd, I_STR, &strioctl) != 0) {
+ continue;
+ }
+ memcpy(&ifaces[total].bcast, &ifreq.ifr_dstaddr,
+ sizeof(struct sockaddr_in));
+ } else {
+ continue;
+ }
total++;
}
@@ -331,9 +389,6 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
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) {
@@ -357,34 +412,54 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
while (i > 0 && total < max_interfaces) {
uint_t inc;
+ memset(&ifaces[total], '\0', sizeof(ifaces[total]));
+
inc = ifr->ifr_addr.sa_len;
- if (ioctl(fd, SIOCGIFADDR, ifr) != 0) {
+ if (ioctl(fd, SIOCGIFFLAGS, ifr) != 0) {
goto next;
}
- ipaddr = (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr;
- iname = ifr->ifr_name;
+ ifaces[total].flags = ifr->ifr_flags;
- if (ioctl(fd, SIOCGIFFLAGS, ifr) != 0) {
+ if (!(ifaces[total].flags & IFF_UP)) {
goto next;
}
- if (!(ifr->ifr_flags & IFF_UP)) {
+ if (ioctl(fd, SIOCGIFADDR, ifr) != 0) {
goto next;
}
+ memcpy(&ifaces[total].ip, &ifr->ifr_addr,
+ sizeof(struct sockaddr_in));
+
+ strncpy(ifaces[total].name, ifr->ifr_name,
+ sizeof(ifaces[total].name)-1);
+ ifaces[total].name[sizeof(ifaces[total].name)-1] = 0;
+
if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) {
goto next;
}
- nmask = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
+ memcpy(&ifaces[total].netmask, &ifr->ifr_addr,
+ sizeof(struct sockaddr_in));
+
+ if (ifaces[total].flags & IFF_BROADCAST) {
+ if (ioctl(fd, SIOCGIFBRDADDR, &ifr[i]) != 0) {
+ continue;
+ }
+ memcpy(&ifaces[total].bcast, &ifr[i].ifr_broadaddr,
+ sizeof(struct sockaddr_in));
+ } else if (ifaces[total].flags & IFF_POINTOPOINT) {
+ if (ioctl(fd, SIOCGIFDSTADDR, &ifr[i]) != 0) {
+ continue;
+ }
+ memcpy(&ifaces[total].bcast, &ifr[i].ifr_dstaddr,
+ sizeof(struct sockaddr_in));
+ } else {
+ continue;
+ }
- strncpy(ifaces[total].name, iname, sizeof(ifaces[total].name)-1);
- ifaces[total].name[sizeof(ifaces[total].name)-1] = 0;
- ifaces[total].sa_family = AF_INET;
- ifaces[total].iface_addr.ip = ipaddr;
- ifaces[total].iface_netmask.netmask = nmask;
total++;
@@ -421,25 +496,36 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
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 = i1->sa_family - i2->sa_family;
- if (r) {
- return r;
- }
#ifdef AF_INET6
- if (i1->sa_family == AF_INET6) {
- r = memcmp(&i1->iface_addr.ip6,
- &i2->iface_addr.ip6,
+ /*
+ * 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;
}
- r = memcmp(&i1->iface_netmask.netmask6,
- &i1->iface_netmask.netmask6,
+
+ 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;
@@ -447,14 +533,21 @@ static int iface_comp(struct iface_struct *i1, struct iface_struct *i2)
}
#endif
- if (i1->sa_family == AF_INET) {
- r = ntohl(i1->iface_addr.ip.s_addr) -
- ntohl(i2->iface_addr.ip.s_addr);
+ if (i1->ip.ss_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;
}
- r = ntohl(i1->iface_netmask.netmask.s_addr) -
- ntohl(i2->iface_netmask.netmask.s_addr);
+
+ s1 = (struct sockaddr_in *)&i1->netmask;
+ s2 = (struct sockaddr_in *)&i2->netmask;
+
+ r = ntohl(s1->sin_addr.s_addr) -
+ ntohl(s2->sin_addr.s_addr);
}
return r;
}
@@ -503,15 +596,26 @@ int get_interfaces(struct iface_struct *ifaces, int max_interfaces)
for (i=0;i<total;i++) {
char addr[INET6_ADDRSTRLEN];
+ int ret;
printf("%-10s ", ifaces[i].name);
- printf("IP=%s ", inet_ntop(ifaces[i].sa_family,
- (const void *)&ifaces[i].iface_addr.ip,
- addr,
- sizeof(addr)));
- printf("NETMASK=%s\n", inet_ntop(ifaces[i].sa_family,
- (const void *)&ifaces[i].iface_netmask.netmask,
- addr,
- sizeof(addr)));
+ addr[0] = '\0';
+ ret = getnameinfo((struct sockaddr *)&ifaces[i].ip,
+ sizeof(ifaces[i].ip),
+ addr, sizeof(addr),
+ NULL, 0, NI_NUMERICHOST);
+ printf("IP=%s ", addr);
+ addr[0] = '\0';
+ ret = getnameinfo((struct sockaddr *)&ifaces[i].netmask,
+ sizeof(ifaces[i].netmask),
+ addr, sizeof(addr),
+ NULL, 0, NI_NUMERICHOST);
+ printf("NETMASK=%s ", addr);
+ addr[0] = '\0';
+ ret = getnameinfo((struct sockaddr *)&ifaces[i].bcast,
+ sizeof(ifaces[i].bcast),
+ addr, sizeof(addr),
+ NULL, 0, NI_NUMERICHOST);
+ printf("BCAST=%s\n", addr);
}
return 0;
}
diff --git a/source3/lib/util.c b/source3/lib/util.c
index adbebb04d4..f457e53c47 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -1286,102 +1286,6 @@ int interpret_protocol(const char *str,int def)
return(def);
}
-/****************************************************************************
- Return true if a string could be a pure IP address.
-****************************************************************************/
-
-BOOL is_ipaddress(const char *str)
-{
- BOOL pure_address = True;
- int i;
-
- for (i=0; pure_address && str[i]; i++)
- if (!(isdigit((int)str[i]) || str[i] == '.'))
- pure_address = False;
-
- /* Check that a pure number is not misinterpreted as an IP */
- pure_address = pure_address && (strchr_m(str, '.') != NULL);
-
- return pure_address;
-}
-
-/****************************************************************************
- Interpret an internet address or name into an IP address in 4 byte form.
-****************************************************************************/
-
-uint32 interpret_addr(const char *str)
-{
- struct hostent *hp;
- uint32 res;
-
- if (strcmp(str,"0.0.0.0") == 0)
- return(0);
- if (strcmp(str,"255.255.255.255") == 0)
- return(0xFFFFFFFF);
-
- /* if it's in the form of an IP address then get the lib to interpret it */
- if (is_ipaddress(str)) {
- res = inet_addr(str);
- } else {
- /* otherwise assume it's a network name of some sort and use
- sys_gethostbyname */
- if ((hp = sys_gethostbyname(str)) == 0) {
- DEBUG(3,("sys_gethostbyname: Unknown host. %s\n",str));
- return 0;
- }
-
- if(hp->h_addr == NULL) {
- DEBUG(3,("sys_gethostbyname: host address is invalid for host %s\n",str));
- return 0;
- }
- putip((char *)&res,(char *)hp->h_addr);
- }
-
- if (res == (uint32)-1)
- return(0);
-
- return(res);
-}
-
-/*******************************************************************
- A convenient addition to interpret_addr().
-******************************************************************/
-
-struct in_addr *interpret_addr2(const char *str)
-{
- static struct in_addr ret;
- uint32 a = interpret_addr(str);
- ret.s_addr = a;
- return(&ret);
-}
-
-/*******************************************************************
- Check if an IP is the 0.0.0.0.
-******************************************************************/
-
-BOOL is_zero_ip(struct in_addr ip)
-{
- uint32 a;
- putip((char *)&a,(char *)&ip);
- return(a == 0);
-}
-
-/*******************************************************************
- Set an IP to 0.0.0.0.
-******************************************************************/
-
-void zero_ip(struct in_addr *ip)
-{
- static BOOL init;
- static struct in_addr ipzero;
-
- if (!init) {
- ipzero = *interpret_addr2("0.0.0.0");
- init = True;
- }
-
- *ip = ipzero;
-}
#if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
/******************************************************************
@@ -1506,22 +1410,6 @@ char *automount_lookup(const char *user_name)
#endif /* WITH_NISPLUS_HOME */
#endif
-/*******************************************************************
- Are two IPs on the same subnet?
-********************************************************************/
-
-BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
-{
- uint32 net1,net2,nmask;
-
- nmask = ntohl(mask.s_addr);
- net1 = ntohl(ip1.s_addr);
- net2 = ntohl(ip2.s_addr);
-
- return((net1 & nmask) == (net2 & nmask));
-}
-
-
/****************************************************************************
Check if a process exists. Does this work on all unixes?
****************************************************************************/
@@ -2097,83 +1985,6 @@ BOOL is_myname(const char *s)
return(ret);
}
-BOOL is_myname_or_ipaddr(const char *s)
-{
- fstring name, dnsname;
- char *servername;
-
- if ( !s )
- return False;
-
- /* santize the string from '\\name' */
-
- fstrcpy( name, s );
-
- servername = strrchr_m( name, '\\' );
- if ( !servername )
- servername = name;
- else
- servername++;
-
- /* optimize for the common case */
-
- if (strequal(servername, global_myname()))
- return True;
-
- /* check for an alias */
-
- if (is_myname(servername))
- return True;
-
- /* check for loopback */
-
- if (strequal(servername, "127.0.0.1"))
- return True;
-
- if (strequal(servername, "localhost"))
- return True;
-
- /* maybe it's my dns name */
-
- if ( get_mydnsfullname( dnsname ) )
- if ( strequal( servername, dnsname ) )
- return True;
-
- /* handle possible CNAME records */
-
- if ( !is_ipaddress( servername ) ) {
- /* use DNS to resolve the name, but only the first address */
- struct hostent *hp;
-
- if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
- struct in_addr return_ip;
- putip( (char*)&return_ip, (char*)hp->h_addr );
- fstrcpy( name, inet_ntoa( return_ip ) );
- servername = name;
- }
- }
-
- /* maybe its an IP address? */
- if (is_ipaddress(servername)) {
- struct iface_struct nics[MAX_INTERFACES];
- int i, n;
- uint32 ip;
-
- ip = interpret_addr(servername);
- if ((ip==0) || (ip==0xffffffff))
- return False;
-
- n = get_interfaces(nics, MAX_INTERFACES);
- for (i=0; i<n; i++) {
- if (ip == nics[i].iface_addr.ip.s_addr)
- return True;
- }
- }
-
- /* no match */
- return False;
-}
-
/*******************************************************************
Is the name specified our workgroup/domain.
Returns true if it is equal, false otherwise.
diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c
index 1508ddfce3..7a1a05ec29 100644
--- a/source3/lib/util_sock.c
+++ b/source3/lib/util_sock.c
@@ -29,33 +29,353 @@ static int client_fd = -1;
static char client_ip_string[INET6_ADDRSTRLEN];
/****************************************************************************
- Pritn out an IPv4 or IPv6 address from a struct sockaddr_storage.
+ Return true if a string could be a pure IPv4 address.
****************************************************************************/
-char *print_sockaddr(char *dest,
- size_t destlen,
- struct sockaddr_storage *psa)
+bool is_ipaddress_v4(const char *str)
{
- if (destlen > 0) {
- dest[0] = '\0';
+ bool pure_address = true;
+ int i;
+
+ for (i=0; pure_address && str[i]; i++) {
+ if (!(isdigit((int)str[i]) || str[i] == '.')) {
+ pure_address = false;
+ }
+ }
+
+ /* Check that a pure number is not misinterpreted as an IP */
+ pure_address = pure_address && (strchr_m(str, '.') != NULL);
+ return pure_address;
+}
+
+/****************************************************************************
+ Interpret an internet address or name into an IP address in 4 byte form.
+****************************************************************************/
+
+uint32 interpret_addr(const char *str)
+{
+ struct hostent *hp;
+ uint32 res;
+
+ if (strcmp(str,"0.0.0.0") == 0)
+ return(0);
+ if (strcmp(str,"255.255.255.255") == 0)
+ return(0xFFFFFFFF);
+
+ /* if it's in the form of an IP address then
+ * get the lib to interpret it */
+ if (is_ipaddress_v4(str)) {
+ res = inet_addr(str);
+ } else {
+ /* otherwise assume it's a network name of some sort and use
+ sys_gethostbyname */
+ if ((hp = sys_gethostbyname(str)) == 0) {
+ DEBUG(3,("sys_gethostbyname: Unknown host. %s\n",str));
+ return 0;
+ }
+
+ if(hp->h_addr == NULL) {
+ DEBUG(3,("sys_gethostbyname: host address is "
+ "invalid for host %s\n",str));
+ return 0;
+ }
+ putip((char *)&res,(char *)hp->h_addr);
+ }
+
+ if (res == (uint32)-1)
+ return(0);
+
+ return(res);
+}
+
+/*******************************************************************
+ A convenient addition to interpret_addr().
+******************************************************************/
+
+struct in_addr *interpret_addr2(const char *str)
+{
+ static struct in_addr ret;
+ uint32 a = interpret_addr(str);
+ ret.s_addr = a;
+ return(&ret);
+}
+
+/*******************************************************************
+ Map a text hostname or IP address (IPv4 or IPv6) into a
+ struct sockaddr_storage.
+******************************************************************/
+
+bool interpret_string_addr(struct sockaddr_storage *pss, const char *str)
+{
+ int ret;
+ struct addrinfo *res = NULL;
+ struct addrinfo hints;
+
+ memset(pss,'\0', sizeof(*pss));
+
+ memset(&hints, '\0', sizeof(hints));
+ /* By default make sure it supports TCP. */
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_ADDRCONFIG;
+
+ ret = getaddrinfo(str, NULL,
+ &hints,
+ &res);
+
+ if (ret) {
+ DEBUG(3,("interpret_string_addr: getaddrinfo failed for "
+ "name %s [%s]\n",
+ str,
+ gai_strerror(ret) ));
+ return false;
+ }
+
+ /* Copy the first sockaddr. */
+ memcpy(pss, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+ return true;
+}
+
+/*******************************************************************
+ Check if an IPv7 is 127.0.0.1
+******************************************************************/
+
+bool is_loopback_ip_v4(struct in_addr ip)
+{
+ struct in_addr a;
+ a.s_addr = htonl(INADDR_LOOPBACK);
+ return(ip.s_addr == a.s_addr);
+}
+
+/*******************************************************************
+ Check if a struct sockaddr_storage is the loopback address.
+******************************************************************/
+
+bool is_loopback_addr(const struct sockaddr_storage *pss)
+{
+#if defined(AF_INET6)
+ if (pss->ss_family == AF_INET) {
+ struct in6_addr *pin6 = &((struct sockaddr_in6 *)pss)->sin6_addr;
+ return IN6_IS_ADDR_LOOPBACK(pin6);
+ }
+#endif
+ if (pss->ss_family == AF_INET) {
+ struct in_addr *pin = &((struct sockaddr_in *)pss)->sin_addr;
+ return is_loopback_ip_v4(*pin);
+ }
+ return false;
+}
+
+/*******************************************************************
+ Check if an IPv4 is 0.0.0.0.
+******************************************************************/
+
+bool is_zero_ip_v4(struct in_addr ip)
+{
+ uint32 a;
+ putip((char *)&a,(char *)&ip);
+ return(a == 0);
+}
+
+/*******************************************************************
+ Check if a struct sockaddr_storage has an unspecified address.
+******************************************************************/
+
+bool is_zero_addr(const struct sockaddr_storage *pss)
+{
+#if defined(AF_INET6)
+ if (pss->ss_family == AF_INET) {
+ struct in6_addr *pin6 = &((struct sockaddr_in6 *)pss)->sin6_addr;
+ return IN6_IS_ADDR_UNSPECIFIED(pin6);
+ }
+#endif
+ if (pss->ss_family == AF_INET) {
+ struct in_addr *pin = &((struct sockaddr_in *)pss)->sin_addr;
+ return is_zero_ip_v4(*pin);
}
+ return false;
+}
+
+/*******************************************************************
+ Set an IP to 0.0.0.0.
+******************************************************************/
+
+void zero_ip_v4(struct in_addr *ip)
+{
+ static bool init;
+ static struct in_addr ipzero;
+
+ if (!init) {
+ ipzero = *interpret_addr2("0.0.0.0");
+ init = true;
+ }
+
+ *ip = ipzero;
+}
+
+/*******************************************************************
+ Are two IPs on the same subnet - IPv4 version ?
+********************************************************************/
+
+bool same_net_v4(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
+{
+ uint32 net1,net2,nmask;
+
+ nmask = ntohl(mask.s_addr);
+ net1 = ntohl(ip1.s_addr);
+ net2 = ntohl(ip2.s_addr);
+
+ return((net1 & nmask) == (net2 & nmask));
+}
+
+/*******************************************************************
+ Convert an IPv4 struct in_addr to a struct sockaddr_storage.
+********************************************************************/
+
+void in_addr_to_sockaddr_storage(struct sockaddr_storage *ss,
+ struct in_addr ip)
+{
+ struct sockaddr_in *sa = (struct sockaddr_in *)ss;
+ memset(ss, '\0', sizeof(*ss));
+ ss->ss_family = AF_INET;
+ sa->sin_addr = ip;
+}
+
+#ifdef AF_INET6
+/*******************************************************************
+ Convert an IPv6 struct in_addr to a struct sockaddr_storage.
+********************************************************************/
+
+void in6_addr_to_sockaddr_storage(struct sockaddr_storage *ss,
+ struct in6_addr ip)
+{
+ struct sockaddr_in6 *sa = (struct sockaddr_in6 *)ss;
+ memset(ss, '\0', sizeof(*ss));
+ ss->ss_family = AF_INET6;
+ sa->sin6_addr = ip;
+}
+#endif
+
+/*******************************************************************
+ Are two IPs on the same subnet?
+********************************************************************/
+
+bool same_net(const struct sockaddr_storage *ip1,
+ const struct sockaddr_storage *ip2,
+ const struct sockaddr_storage *mask)
+{
+ if (ip1->ss_family != ip2->ss_family) {
+ /* Never on the same net. */
+ return false;
+ }
+
+#ifdef AF_INET6
+ if (ip1->ss_family == AF_INET6) {
+ struct sockaddr_in6 ip1_6 = *(struct sockaddr_in6 *)ip1;
+ struct sockaddr_in6 ip2_6 = *(struct sockaddr_in6 *)ip2;
+ struct sockaddr_in6 mask_6 = *(struct sockaddr_in6 *)mask;
+ char *p1 = (char *)&ip1_6.sin6_addr;
+ char *p2 = (char *)&ip2_6.sin6_addr;
+ char *m = (char *)&mask_6.sin6_addr;
+ int i;
+
+ for (i = 0; i < sizeof(struct in6_addr); i++) {
+ *p1++ &= *m;
+ *p2++ &= *m;
+ m++;
+ }
+ return (memcmp(&ip1_6.sin6_addr,
+ &ip2_6.sin6_addr,
+ sizeof(struct in6_addr)) == 0);
+ }
+#endif
+ if (ip1->ss_family == AF_INET) {
+ return same_net_v4(((const struct sockaddr_in *)ip1)->sin_addr,
+ ((const struct sockaddr_in *)ip2)->sin_addr,
+ ((const struct sockaddr_in *)mask)->sin_addr);
+ }
+ return false;
+}
+
+/*******************************************************************
+ Are two sockaddr_storage's the same family and address ? Ignore port etc.
+********************************************************************/
+
+bool addr_equal(const struct sockaddr_storage *ip1,
+ const struct sockaddr_storage *ip2)
+{
+ if (ip1->ss_family != ip2->ss_family) {
+ /* Never the same. */
+ return false;
+ }
+
+#ifdef AF_INET6
+ if (ip1->ss_family == AF_INET6) {
+ return (memcmp(&((const struct sockaddr_in6 *)ip1)->sin6_addr,
+ &((const struct sockaddr_in6 *)ip2)->sin6_addr,
+ sizeof(struct in6_addr)) == 0);
+ }
+#endif
+ if (ip1->ss_family == AF_INET) {
+ return (memcmp(&((const struct sockaddr_in *)ip1)->sin_addr,
+ &((const struct sockaddr_in *)ip2)->sin_addr,
+ sizeof(struct in_addr)) == 0);
+ }
+ return false;
+}
+
+
+/****************************************************************************
+ Is an IP address the INADDR_ANY or in6addr_any value ?
+****************************************************************************/
+
+bool is_address_any(const struct sockaddr_storage *psa)
+{
#ifdef AF_INET6
if (psa->ss_family == AF_INET6) {
- inet_ntop(AF_INET6,
- &((struct sockaddr_in6 *)psa)->sin6_addr,
- dest,
- destlen);
+ struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)psa;
+ if (memcmp(&in6addr_any,
+ &si6->sin6_addr,
+ sizeof(in6addr_any)) == 0) {
+ return true;
+ }
+ return false;
}
#endif
if (psa->ss_family == AF_INET) {
- inet_ntop(AF_INET,
- &((struct sockaddr_in *)psa)->sin_addr,
- dest,
- destlen);
+ struct sockaddr_in *si = (struct sockaddr_in *)psa;
+ if (si->sin_addr.s_addr == INADDR_ANY) {
+ return true;
+ }
+ return false;
}
+ return false;
+}
+
+/****************************************************************************
+ Print out an IPv4 or IPv6 address from a struct sockaddr_storage.
+****************************************************************************/
+
+char *print_sockaddr(char *dest,
+ size_t destlen,
+ const struct sockaddr_storage *psa,
+ socklen_t psalen)
+{
+ if (destlen > 0) {
+ dest[0] = '\0';
+ }
+ (void)getnameinfo((const struct sockaddr *)psa,
+ psalen,
+ dest, destlen,
+ NULL, 0,
+ NI_NUMERICHOST);
return dest;
}
+/****************************************************************************
+ Set the global client_fd variable.
+****************************************************************************/
+
void client_setfd(int fd)
{
client_fd = fd;
@@ -64,6 +384,10 @@ void client_setfd(int fd)
sizeof(client_ip_string)-1);
}
+/****************************************************************************
+ Return a static string of an IP address (IPv4 or IPv6).
+****************************************************************************/
+
static char *get_socket_addr(int fd)
{
struct sockaddr_storage sa;
@@ -87,9 +411,13 @@ static char *get_socket_addr(int fd)
return addr_buf;
}
- return print_sockaddr(addr_buf, sizeof(addr_buf), &sa);
+ return print_sockaddr(addr_buf, sizeof(addr_buf), &sa, length);
}
+/****************************************************************************
+ Return the port number we've bound to on a socket.
+****************************************************************************/
+
static int get_socket_port(int fd)
{
struct sockaddr_storage sa;
@@ -118,7 +446,7 @@ static int get_socket_port(int fd)
char *client_name(void)
{
- return get_peer_name(client_fd,False);
+ return get_peer_name(client_fd,false);
}
char *client_addr(void)
@@ -142,7 +470,7 @@ int smb_read_error = 0;
Determine if a file descriptor is in fact a socket.
****************************************************************************/
-BOOL is_a_socket(int fd)
+bool is_a_socket(int fd)
{
int v;
socklen_t l;
@@ -247,12 +575,12 @@ void set_socket_options(int fd, const char *options)
int ret=0,i;
int value = 1;
char *p;
- BOOL got_value = False;
+ bool got_value = false;
if ((p = strchr_m(tok,'='))) {
*p = 0;
value = atoi(p+1);
- got_value = True;
+ got_value = true;
}
for (i=0;socket_options[i].name;i++)
@@ -559,7 +887,7 @@ ssize_t write_data(int fd, const char *buffer, size_t N)
Send a keepalive packet (rfc1002).
****************************************************************************/
-BOOL send_keepalive(int client)
+bool send_keepalive(int client)
{
unsigned char buf[4];
@@ -583,7 +911,7 @@ static ssize_t read_smb_length_return_keepalive(int fd,
{
ssize_t len=0;
int msg_type;
- BOOL ok = False;
+ bool ok = false;
while (!ok) {
if (timeout > 0) {
@@ -809,23 +1137,23 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, int fd,
Checks the MAC on signed packets.
****************************************************************************/
-BOOL receive_smb(int fd, char *buffer, unsigned int timeout)
+bool receive_smb(int fd, char *buffer, unsigned int timeout)
{
if (receive_smb_raw(fd, buffer, timeout, 0) < 0) {
- return False;
+ return false;
}
/* Check the incoming SMB signature. */
- if (!srv_check_sign_mac(buffer, True)) {
+ if (!srv_check_sign_mac(buffer, true)) {
DEBUG(0, ("receive_smb: SMB Signature verification "
"failed on incoming packet!\n"));
if (smb_read_error == 0) {
smb_read_error = READ_BAD_SIG;
}
- return False;
+ return false;
}
- return True;
+ return true;
}
ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer,
@@ -840,7 +1168,7 @@ ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer,
}
/* Check the incoming SMB signature. */
- if (!srv_check_sign_mac(*buffer, True)) {
+ if (!srv_check_sign_mac(*buffer, true)) {
DEBUG(0, ("receive_smb: SMB Signature verification failed on "
"incoming packet!\n"));
if (smb_read_error == 0) {
@@ -856,7 +1184,7 @@ ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer,
Send an smb to a fd.
****************************************************************************/
-BOOL send_smb(int fd, char *buffer)
+bool send_smb(int fd, char *buffer)
{
size_t len;
size_t nwritten=0;
@@ -872,12 +1200,12 @@ BOOL send_smb(int fd, char *buffer)
if (ret <= 0) {
DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
(int)len,(int)ret, strerror(errno) ));
- return False;
+ return false;
}
nwritten += ret;
}
- return True;
+ return true;
}
/****************************************************************************
@@ -888,7 +1216,7 @@ int open_socket_in(int type,
int port,
int dlevel,
uint32 socket_addr,
- BOOL rebind )
+ bool rebind )
{
struct sockaddr_in sock;
int res;
@@ -919,7 +1247,7 @@ int open_socket_in(int type,
if( DEBUGLVL( dlevel ) ) {
dbgtext( "open_socket_in(): setsockopt: " );
dbgtext( "SO_REUSEADDR = %s ",
- val?"True":"False" );
+ val?"true":"false" );
dbgtext( "on port %d failed ", port );
dbgtext( "with error = %s\n", strerror(errno) );
}
@@ -930,7 +1258,7 @@ int open_socket_in(int type,
if( DEBUGLVL( dlevel ) ) {
dbgtext( "open_socket_in(): setsockopt: ");
dbgtext( "SO_REUSEPORT = %s ",
- val?"True":"False" );
+ val?"true":"false" );
dbgtext( "on port %d failed ", port );
dbgtext( "with error = %s\n", strerror(errno) );
}
@@ -984,7 +1312,7 @@ int open_socket_out(int type, struct in_addr *addr, int port ,int timeout)
sock_out.sin_family = PF_INET;
/* set it non-blocking */
- set_blocking(res,False);
+ set_blocking(res,false);
DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port));
@@ -1029,7 +1357,7 @@ int open_socket_out(int type, struct in_addr *addr, int port ,int timeout)
}
/* set it blocking again */
- set_blocking(res,True);
+ set_blocking(res,true);
return res;
}
@@ -1040,12 +1368,12 @@ int open_socket_out(int type, struct in_addr *addr, int port ,int timeout)
of DC's all of which are equivalent for our purposes.
**************************************************************************/
-BOOL open_any_socket_out(struct sockaddr_in *addrs, int num_addrs,
+bool open_any_socket_out(struct sockaddr_in *addrs, int num_addrs,
int timeout, int *fd_index, int *fd)
{
int i, resulting_index, res;
int *sockets;
- BOOL good_connect;
+ bool good_connect;
fd_set r_fds, wr_fds;
struct timeval tv;
@@ -1058,7 +1386,7 @@ BOOL open_any_socket_out(struct sockaddr_in *addrs, int num_addrs,
sockets = SMB_MALLOC_ARRAY(int, num_addrs);
if (sockets == NULL)
- return False;
+ return false;
resulting_index = -1;
@@ -1069,11 +1397,11 @@ BOOL open_any_socket_out(struct sockaddr_in *addrs, int num_addrs,
sockets[i] = socket(PF_INET, SOCK_STREAM, 0);
if (sockets[i] < 0)
goto done;
- set_blocking(sockets[i], False);
+ set_blocking(sockets[i], false);
}
connect_again:
- good_connect = False;
+ good_connect = false;
for (i=0; i<num_addrs; i++) {
@@ -1095,7 +1423,7 @@ BOOL open_any_socket_out(struct sockaddr_in *addrs, int num_addrs,
errno == EAGAIN || errno == EINTR) {
/* These are the error messages that something is
progressing. */
- good_connect = True;
+ good_connect = true;
} else if (errno != 0) {
/* There was a direct error */
close(sockets[i]);
@@ -1180,7 +1508,7 @@ BOOL open_any_socket_out(struct sockaddr_in *addrs, int num_addrs,
if (resulting_index >= 0) {
*fd_index = resulting_index;
*fd = sockets[*fd_index];
- set_blocking(*fd, True);
+ set_blocking(*fd, true);
}
free(sockets);
@@ -1223,7 +1551,7 @@ int open_udp_socket(const char *host, int port)
confirm a hostname lookup to prevent spoof attacks.
******************************************************************/
-static BOOL matchname(char *remotehost,struct in_addr addr)
+static bool matchname(char *remotehost,struct in_addr addr)
{
struct hostent *hp;
int i;
@@ -1231,7 +1559,7 @@ static BOOL matchname(char *remotehost,struct in_addr addr)
if ((hp = sys_gethostbyname(remotehost)) == 0) {
DEBUG(0,("sys_gethostbyname(%s): lookup failure.\n",
remotehost));
- return False;
+ return false;
}
/*
@@ -1246,13 +1574,13 @@ static BOOL matchname(char *remotehost,struct in_addr addr)
&& !strequal(remotehost, "localhost")) {
DEBUG(0,("host name/name mismatch: %s != %s\n",
remotehost, hp->h_name));
- return False;
+ return false;
}
/* Look up the host address in the address list we just got. */
for (i = 0; hp->h_addr_list[i]; i++) {
if (memcmp(hp->h_addr_list[i], (char *)&addr,sizeof(addr)) == 0)
- return True;
+ return true;
}
/*
@@ -1263,14 +1591,14 @@ static BOOL matchname(char *remotehost,struct in_addr addr)
DEBUG(0,("host name/address mismatch: %s != %s\n",
inet_ntoa(addr), hp->h_name));
- return False;
+ return false;
}
/*******************************************************************
Return the DNS name of the remote end of a socket.
******************************************************************/
-char *get_peer_name(int fd, BOOL force_lookup)
+char *get_peer_name(int fd, bool force_lookup)
{
static pstring name_buf;
pstring tmp_name;
@@ -1283,7 +1611,7 @@ char *get_peer_name(int fd, BOOL force_lookup)
situations won't work because many networks don't link dhcp
with dns. To avoid the delay we avoid the lookup if
possible */
- if (!lp_hostname_lookups() && (force_lookup == False)) {
+ if (!lp_hostname_lookups() && (force_lookup == false)) {
return get_peer_addr(fd);
}
@@ -1450,3 +1778,92 @@ out_umask:
return -1;
#endif /* HAVE_UNIXSOCKET */
}
+
+/************************************************************
+ Is this my name ? Needs fixing for IPv6.
+************************************************************/
+
+bool is_myname_or_ipaddr(const char *s)
+{
+ fstring name, dnsname;
+ char *servername;
+
+ if ( !s )
+ return false;
+
+ /* santize the string from '\\name' */
+
+ fstrcpy( name, s );
+
+ servername = strrchr_m( name, '\\' );
+ if ( !servername )
+ servername = name;
+ else
+ servername++;
+
+ /* optimize for the common case */
+
+ if (strequal(servername, global_myname()))
+ return true;
+
+ /* check for an alias */
+
+ if (is_myname(servername))
+ return true;
+
+ /* check for loopback */
+
+ if (strequal(servername, "127.0.0.1"))
+ return true;
+
+ if (strequal(servername, "localhost"))
+ return true;
+
+ /* maybe it's my dns name */
+
+ if ( get_mydnsfullname( dnsname ) )
+ if ( strequal( servername, dnsname ) )
+ return true;
+
+ /* handle possible CNAME records */
+
+ if ( !is_ipaddress_v4( servername ) ) {
+ /* use DNS to resolve the name, but only the first address */
+ struct hostent *hp;
+
+ if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
+ struct in_addr return_ip;
+ putip( (char*)&return_ip, (char*)hp->h_addr );
+ fstrcpy( name, inet_ntoa( return_ip ) );
+ servername = name;
+ }
+ }
+
+ /* maybe its an IP address? */
+ if (is_ipaddress_v4(servername)) {
+ struct sockaddr_storage ss;
+ struct iface_struct nics[MAX_INTERFACES];
+ int i, n;
+ struct in_addr ip;
+
+ ip = *interpret_addr2(servername);
+ if (is_zero_ip_v4(ip) || is_loopback_ip_v4(ip)) {
+ return false;
+ }
+
+ in_addr_to_sockaddr_storage(&ss, ip);
+
+ n = get_interfaces(nics, MAX_INTERFACES);
+ for (i=0; i<n; i++) {
+ if (nics[i].ip.ss_family != AF_INET) {
+ continue;
+ }
+ if (addr_equal(&nics[i].ip, &ss)) {
+ return true;
+ }
+ }
+ }
+
+ /* no match */
+ return false;
+}
diff --git a/source3/lib/wins_srv.c b/source3/lib/wins_srv.c
index 4faa65c18d..6344568122 100644
--- a/source3/lib/wins_srv.c
+++ b/source3/lib/wins_srv.c
@@ -21,8 +21,6 @@
#include "includes.h"
-extern struct in_addr loopback_ip;
-
/*
This is pretty much a complete rewrite of the earlier code. The main
aim of the rewrite is to add support for having multiple wins server
@@ -134,7 +132,7 @@ void wins_srv_died(struct in_addr wins_ip, struct in_addr src_ip)
{
char *keystr;
- if (is_zero_ip(wins_ip) || wins_srv_is_dead(wins_ip, src_ip))
+ if (is_zero_ip_v4(wins_ip) || wins_srv_is_dead(wins_ip, src_ip))
return;
keystr = wins_srv_keystr(wins_ip, src_ip);
@@ -284,13 +282,15 @@ struct in_addr wins_srv_ip_tag(const char *tag, struct in_addr src_ip)
/* if we are a wins server then we always just talk to ourselves */
if (lp_wins_support()) {
+ struct in_addr loopback_ip;
+ loopback_ip.s_addr = htonl(INADDR_LOOPBACK);
return loopback_ip;
}
list = lp_wins_server_list();
if (!list || !list[0]) {
struct in_addr ip;
- zero_ip(&ip);
+ zero_ip_v4(&ip);
return ip;
}
@@ -322,7 +322,7 @@ struct in_addr wins_srv_ip_tag(const char *tag, struct in_addr src_ip)
}
/* this can't happen?? */
- zero_ip(&t_ip.ip);
+ zero_ip_v4(&t_ip.ip);
return t_ip.ip;
}