diff options
46 files changed, 1363 insertions, 662 deletions
diff --git a/source3/auth/auth_server.c b/source3/auth/auth_server.c index b7669e945c..44f36dc4cf 100644 --- a/source3/auth/auth_server.c +++ b/source3/auth/auth_server.c @@ -59,7 +59,7 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx) continue; } - if (ismyip(dest_ip)) { + if (ismyip_v4(dest_ip)) { DEBUG(1,("Password server loop - disabling password server %s\n",desthost)); continue; } diff --git a/source3/client/client.c b/source3/client/client.c index 171d413b0a..4e916f6372 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -3853,7 +3853,7 @@ static int do_message_op(void) snprintf(name_type_hex, sizeof(name_type_hex), "#%X", name_type); fstrcat(server_name, name_type_hex); - zero_ip(&ip); + zero_ip_v4(&ip); if (have_ip) ip = dest_ip; @@ -3994,7 +3994,7 @@ static int do_message_op(void) case 'I': { dest_ip = *interpret_addr2(poptGetOptArg(pc)); - if (is_zero_ip(dest_ip)) + if (is_zero_ip_v4(dest_ip)) exit(1); have_ip = True; diff --git a/source3/include/interfaces.h b/source3/include/interfaces.h index 371f64292f..66ea151f02 100644 --- a/source3/include/interfaces.h +++ b/source3/include/interfaces.h @@ -1,4 +1,4 @@ -/* +/* This structure is used by lib/interfaces.c to return the list of network interfaces on the machine */ @@ -7,17 +7,8 @@ struct iface_struct { char name[16]; - sa_family_t sa_family; - union { - struct in_addr ip; -#ifdef AF_INET6 - struct in6_addr ip6; -#endif - } iface_addr; - union { - struct in_addr netmask; -#ifdef AF_INET6 - struct in6_addr netmask6; -#endif - } iface_netmask; + int flags; + struct sockaddr_storage ip; + struct sockaddr_storage netmask; + struct sockaddr_storage bcast; }; diff --git a/source3/include/smb.h b/source3/include/smb.h index 75ec4363d0..7386613029 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -726,9 +726,11 @@ struct server_info_struct { /* used for network interfaces */ struct interface { struct interface *next, *prev; - struct in_addr ip; - struct in_addr bcast; - struct in_addr nmask; + char *name; + int flags; + struct sockaddr_storage ip; + struct sockaddr_storage netmask; + struct sockaddr_storage bcast; }; /* Internal message queue for deferred opens. */ 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; } diff --git a/source3/librpc/ndr/ndr_basic.c b/source3/librpc/ndr/ndr_basic.c index 5785e5c1ea..e036eae704 100644 --- a/source3/librpc/ndr/ndr_basic.c +++ b/source3/librpc/ndr/ndr_basic.c @@ -595,7 +595,7 @@ NTSTATUS ndr_pull_ipv4address(struct ndr_pull *ndr, int ndr_flags, const char ** NTSTATUS ndr_push_ipv4address(struct ndr_push *ndr, int ndr_flags, const char *address) { uint32_t addr; - if (!is_ipaddress(address)) { + if (!is_ipaddress_v4(address)) { return ndr_push_error(ndr, NDR_ERR_IPV4ADDRESS, "Invalid IPv4 address: '%s'", address); diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 78cc63de50..16c3bed438 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -1421,7 +1421,7 @@ NTSTATUS cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip *p = 0; } - if (!ip || is_zero_ip(*ip)) { + if (!ip || is_zero_ip_v4(*ip)) { if (!resolve_name(cli->desthost, &cli->dest_ip, name_type)) { return NT_STATUS_BAD_NETWORK_NAME; } @@ -1522,7 +1522,7 @@ again: char *p; DEBUG(1,("session request to %s failed (%s)\n", called.name, cli_errstr(cli))); - if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) { + if ((p=strchr(called.name, '.')) && !is_ipaddress_v4(called.name)) { *p = 0; goto again; } @@ -1650,7 +1650,7 @@ BOOL attempt_netbios_session_request(struct cli_state **ppcli, const char *srcho * then use *SMBSERVER immediately. */ - if(is_ipaddress(desthost)) { + if(is_ipaddress_v4(desthost)) { make_nmb_name(&called, "*SMBSERVER", 0x20); } else { make_nmb_name(&called, desthost, 0x20); @@ -1764,7 +1764,7 @@ struct cli_state *get_ipc_connect(char *server, struct in_addr *server_ip, if (NT_STATUS_IS_OK(nt_status)) { return cli; - } else if (is_ipaddress(server)) { + } else if (is_ipaddress_v4(server)) { /* windows 9* needs a correct NMB name for connections */ fstring remote_name; diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c index d32629b139..db4a9dfbd5 100644 --- a/source3/libsmb/clidfs.c +++ b/source3/libsmb/clidfs.c @@ -83,13 +83,13 @@ static struct cli_state *do_connect( const char *server, const char *share, server_n = server; - zero_ip(&ip); + zero_ip_v4(&ip); make_nmb_name(&calling, global_myname(), 0x0); make_nmb_name(&called , server, name_type); again: - zero_ip(&ip); + zero_ip_v4(&ip); if (have_ip) ip = dest_ip; diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c index 384b9ec48d..89bb65006d 100644 --- a/source3/libsmb/dsgetdcname.c +++ b/source3/libsmb/dsgetdcname.c @@ -650,7 +650,7 @@ static NTSTATUS discover_dc_dns(TALLOC_CTX *mem_ctx, * back to netbios lookups is that our DNS server doesn't know * anything about the DC's -- jerry */ - if (!is_zero_ip(r->ip)) { + if (!is_zero_ip_v4(r->ip)) { (*return_count)++; continue; } diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c index 45226a028c..49384e2728 100644 --- a/source3/libsmb/libsmbclient.c +++ b/source3/libsmb/libsmbclient.c @@ -654,7 +654,7 @@ smbc_server(SMBCCTX *context, const char *username_used; NTSTATUS status; - zero_ip(&ip); + zero_ip_v4(&ip); ZERO_STRUCT(c); if (server[0] == 0) { @@ -742,7 +742,7 @@ smbc_server(SMBCCTX *context, again: slprintf(ipenv,sizeof(ipenv)-1,"HOST_%s", server_n); - zero_ip(&ip); + zero_ip_v4(&ip); /* have to open a new connection */ if ((c = cli_initialise()) == NULL) { @@ -796,7 +796,7 @@ smbc_server(SMBCCTX *context, /* Only try this if server is an IP address ... */ - if (is_ipaddress(server) && !tried_reverse) { + if (is_ipaddress_v4(server) && !tried_reverse) { fstring remote_name; struct in_addr rem_ip; @@ -962,7 +962,7 @@ smbc_attr_server(SMBCCTX *context, flags |= CLI_FULL_CONNECTION_USE_KERBEROS; } - zero_ip(&ip); + zero_ip_v4(&ip); nt_status = cli_full_connection(&ipc_cli, global_myname(), server, &ip, 0, "IPC$", "?????", @@ -2761,7 +2761,7 @@ smbc_opendir_ctx(SMBCCTX *context, * LMB or DMB */ if (!srv && - !is_ipaddress(server) && + !is_ipaddress_v4(server) && (resolve_name(server, &rem_ip, 0x1d) || /* LMB */ resolve_name(server, &rem_ip, 0x1b) )) { /* DMB */ diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c index 49e3375f50..182d3641f7 100644 --- a/source3/libsmb/namequery.c +++ b/source3/libsmb/namequery.c @@ -352,12 +352,18 @@ static int ip_compare(struct in_addr *ip1, struct in_addr *ip2) { int max_bits1=0, max_bits2=0; int num_interfaces = iface_count(); + struct sockaddr_storage ss; int i; for (i=0;i<num_interfaces;i++) { + const struct sockaddr_storage *pss = iface_n_bcast(i); struct in_addr ip; int bits1, bits2; - ip = *iface_n_bcast(i); + + if (pss->ss_family != AF_INET) { + continue; + } + ip = ((const struct sockaddr_in *)pss)->sin_addr; bits1 = matching_quad_bits((uchar *)&ip1->s_addr, (uchar *)&ip.s_addr); bits2 = matching_quad_bits((uchar *)&ip2->s_addr, (uchar *)&ip.s_addr); max_bits1 = MAX(bits1, max_bits1); @@ -365,10 +371,12 @@ static int ip_compare(struct in_addr *ip1, struct in_addr *ip2) } /* bias towards directly reachable IPs */ - if (iface_local(*ip1)) { + in_addr_to_sockaddr_storage(&ss, *ip1); + if (iface_local(&ss)) { max_bits1 += 32; } - if (iface_local(*ip2)) { + in_addr_to_sockaddr_storage(&ss, *ip1); + if (iface_local(&ss)) { max_bits2 += 32; } @@ -431,19 +439,19 @@ static int remove_duplicate_addrs2( struct ip_service *iplist, int count ) /* one loop to remove duplicates */ for ( i=0; i<count; i++ ) { - if ( is_zero_ip(iplist[i].ip) ) + if ( is_zero_ip_v4(iplist[i].ip) ) continue; for ( j=i+1; j<count; j++ ) { if ( ip_service_equal(iplist[i], iplist[j]) ) - zero_ip(&iplist[j].ip); + zero_ip_v4(&iplist[j].ip); } } /* one loop to clean up any holes we left */ /* first ip should never be a zero_ip() */ for (i = 0; i<count; ) { - if ( is_zero_ip(iplist[i].ip) ) { + if ( is_zero_ip_v4(iplist[i].ip) ) { if (i != count-1 ) memmove(&iplist[i], &iplist[i+1], (count - i - 1)*sizeof(iplist[i])); count--; @@ -812,9 +820,14 @@ NTSTATUS name_resolve_bcast(const char *name, int name_type, */ for( i = num_interfaces-1; i >= 0; i--) { struct in_addr sendto_ip; + const struct sockaddr_storage *ss = iface_n_bcast(i); int flags; + /* Done this way to fix compiler error on IRIX 5.x */ - sendto_ip = *iface_n_bcast(i); + if (!ss || ss->ss_family != AF_INET) { + continue; + } + sendto_ip = ((const struct sockaddr_in *)ss)->sin_addr; ip_list = name_query(sock, name, name_type, True, True, sendto_ip, return_count, &flags, NULL); if( ip_list ) @@ -886,7 +899,7 @@ NTSTATUS resolve_wins(const char *name, int name_type, wins_ip = wins_srv_ip_tag(wins_tags[t], src_ip); - if (global_in_nmbd && ismyip(wins_ip)) { + if (global_in_nmbd && ismyip_v4(wins_ip)) { /* yikes! we'll loop forever */ continue; } @@ -1144,7 +1157,7 @@ NTSTATUS resolve_ads(const char *name, int name_type, The standard reason for falling back to netbios lookups is that our DNS server doesn't know anything about the DC's -- jerry */ - if ( ! is_zero_ip(r->ip) ) + if ( ! is_zero_ip_v4(r->ip) ) (*return_count)++; } @@ -1173,7 +1186,7 @@ NTSTATUS internal_resolve_name(const char *name, int name_type, const char *ptr; BOOL allones = (strcmp(name,"255.255.255.255") == 0); BOOL allzeros = (strcmp(name,"0.0.0.0") == 0); - BOOL is_address = is_ipaddress(name); + BOOL is_address = is_ipaddress_v4(name); NTSTATUS status = NT_STATUS_UNSUCCESSFUL; int i; @@ -1347,7 +1360,7 @@ BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type) char *sitename = sitename_fetch(lp_realm()); /* wild guess */ int count = 0; - if (is_ipaddress(name)) { + if (is_ipaddress_v4(name)) { *return_ip = *interpret_addr2(name); SAFE_FREE(sitename); return True; diff --git a/source3/libsmb/namequery_dc.c b/source3/libsmb/namequery_dc.c index bdac833d13..39215aaa8f 100644 --- a/source3/libsmb/namequery_dc.c +++ b/source3/libsmb/namequery_dc.c @@ -155,7 +155,7 @@ static BOOL rpc_dc_name(const char *domain, fstring srv_name, struct in_addr *ip int count, i; NTSTATUS result; - zero_ip(&exclude_ip); + zero_ip_v4(&exclude_ip); /* get a list of all domain controllers */ @@ -168,7 +168,7 @@ static BOOL rpc_dc_name(const char *domain, fstring srv_name, struct in_addr *ip /* Remove the entry we've already failed with (should be the PDC). */ for (i = 0; i < count; i++) { - if (is_zero_ip(ip_list[i].ip)) + if (is_zero_ip_v4(ip_list[i].ip)) continue; if (name_status_find(domain, 0x1c, 0x20, ip_list[i].ip, srv_name)) { @@ -212,7 +212,7 @@ BOOL get_dc_name(const char *domain, const char *realm, fstring srv_name, struct BOOL ret; BOOL our_domain = False; - zero_ip(&dc_ip); + zero_ip_v4(&dc_ip); ret = False; diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c index dc03506194..f0de0b8485 100644 --- a/source3/nmbd/nmbd.c +++ b/source3/nmbd/nmbd.c @@ -27,7 +27,6 @@ int ClientDGRAM = -1; int global_nmb_port = -1; extern BOOL rescan_listen_set; -extern struct in_addr loopback_ip; extern BOOL global_in_nmbd; extern BOOL override_logfile; @@ -192,33 +191,49 @@ static BOOL reload_interfaces(time_t t) /* find any interfaces that need adding */ for (n=iface_count() - 1; n >= 0; n--) { - struct interface *iface = get_interface(n); + char str[INET6_ADDRSTRLEN]; + const struct interface *iface = get_interface(n); + struct in_addr ip, nmask; if (!iface) { DEBUG(2,("reload_interfaces: failed to get interface %d\n", n)); continue; } + /* Ensure we're only dealing with IPv4 here. */ + if (iface->ip.ss_family != AF_INET) { + DEBUG(2,("reload_interfaces: " + "ignoring non IPv4 interface.\n")); + continue; + } + + ip = ((struct sockaddr_in *)&iface->ip)->sin_addr; + nmask = ((struct sockaddr_in *)&iface->netmask)->sin_addr; + /* * We don't want to add a loopback interface, in case * someone has added 127.0.0.1 for smbd, nmbd needs to * ignore it here. JRA. */ - if (ip_equal(iface->ip, loopback_ip)) { - DEBUG(2,("reload_interfaces: Ignoring loopback interface %s\n", inet_ntoa(iface->ip))); + if (is_loopback_addr(&iface->ip)) { + DEBUG(2,("reload_interfaces: Ignoring loopback " + "interface %s\n", + print_sockaddr(str, sizeof(str), + &iface->ip, sizeof(iface->ip)) )); continue; } for (subrec=subnetlist; subrec; subrec=subrec->next) { - if (ip_equal(iface->ip, subrec->myip) && - ip_equal(iface->nmask, subrec->mask_ip)) break; + if (ip_equal(ip, subrec->myip) && + ip_equal(nmask, subrec->mask_ip)) break; } if (!subrec) { /* it wasn't found! add it */ DEBUG(2,("Found new interface %s\n", - inet_ntoa(iface->ip))); + print_sockaddr(str, sizeof(str), + &iface->ip, sizeof(iface->ip)) )); subrec = make_normal_subnet(iface); if (subrec) register_my_workgroup_one_subnet(subrec); @@ -229,8 +244,20 @@ static BOOL reload_interfaces(time_t t) for (subrec=subnetlist; subrec; subrec=subrec->next) { for (n=iface_count() - 1; n >= 0; n--) { struct interface *iface = get_interface(n); - if (ip_equal(iface->ip, subrec->myip) && - ip_equal(iface->nmask, subrec->mask_ip)) break; + struct in_addr ip, nmask; + if (!iface) { + continue; + } + /* Ensure we're only dealing with IPv4 here. */ + if (iface->ip.ss_family != AF_INET) { + DEBUG(2,("reload_interfaces: " + "ignoring non IPv4 interface.\n")); + continue; + } + ip = ((struct sockaddr_in *)&iface->ip)->sin_addr; + nmask = ((struct sockaddr_in *)&iface->netmask)->sin_addr; + if (ip_equal(ip, subrec->myip) && + ip_equal(nmask, subrec->mask_ip)) break; } if (n == -1) { /* oops, an interface has disapeared. This is @@ -322,7 +349,9 @@ static void msg_nmbd_send_packet(struct messaging_context *msg, { struct packet_struct *p = (struct packet_struct *)data->data; struct subnet_record *subrec; - struct in_addr *local_ip; + struct sockaddr_storage ss; + const struct sockaddr_storage *pss; + const struct in_addr *local_ip; DEBUG(10, ("Received send_packet from %d\n", procid_to_pid(&src))); @@ -339,14 +368,16 @@ static void msg_nmbd_send_packet(struct messaging_context *msg, return; } - local_ip = iface_ip(p->ip); + in_addr_to_sockaddr_storage(&ss, p->ip); + pss = iface_ip(&ss); - if (local_ip == NULL) { + if (pss == NULL) { DEBUG(2, ("Could not find ip for packet from %d\n", procid_to_pid(&src))); return; } + local_ip = &((const struct sockaddr_in *)pss)->sin_addr; subrec = FIRST_SUBNET; p->fd = (p->packet_type == NMB_PACKET) ? diff --git a/source3/nmbd/nmbd_become_dmb.c b/source3/nmbd/nmbd_become_dmb.c index a0250f205a..fb87927436 100644 --- a/source3/nmbd/nmbd_become_dmb.c +++ b/source3/nmbd/nmbd_become_dmb.c @@ -22,8 +22,6 @@ #include "includes.h" -extern struct in_addr allones_ip; - extern uint16 samba_nb_type; /* Samba's NetBIOS type. */ static void become_domain_master_browser_bcast(const char *); @@ -119,7 +117,7 @@ in workgroup %s on subnet %s\n", if( subrec == unicast_subnet ) { struct nmb_name nmbname; struct in_addr my_first_ip; - struct in_addr *nip; + const struct in_addr *nip; /* Put our name and first IP address into the workgroup struct as domain master browser. This @@ -129,14 +127,14 @@ in workgroup %s on subnet %s\n", make_nmb_name(&nmbname, global_myname(), 0x20); work->dmb_name = nmbname; - /* Pick the first interface ip address as the domain master browser ip. */ - nip = iface_n_ip(0); + /* Pick the first interface IPv4 address as the domain master browser ip. */ + nip = first_ipv4_iface(); if (!nip) { - DEBUG(0,("become_domain_master_stage2: Error. iface_n_ip returned NULL\n")); + DEBUG(0,("become_domain_master_stage2: " + "Error. get_interface returned NULL\n")); return; } - my_first_ip = *nip; putip((char *)&work->dmb_addr, &my_first_ip); @@ -204,10 +202,12 @@ workgroup %s on subnet %s\n", wg_name, subrec->subnet_name)); static void become_domain_master_query_success(struct subnet_record *subrec, struct userdata_struct *userdata, - struct nmb_name *nmbname, struct in_addr ip, + struct nmb_name *nmbname, struct in_addr ip, struct res_rec *rrec) { unstring name; + struct in_addr allones_ip; + pull_ascii_nstring(name, sizeof(name), nmbname->name); /* If the given ip is not ours, then we can't become a domain @@ -217,7 +217,9 @@ static void become_domain_master_query_success(struct subnet_record *subrec, /* BUG note. Samba 1.9.16p11 servers seem to return the broadcast address or zero ip for this query. Pretend this is ok. */ - if(ismyip(ip) || ip_equal(allones_ip, ip) || is_zero_ip(ip)) { + allones_ip.s_addr = htonl(INADDR_BROADCAST); + + if(ismyip_v4(ip) || ip_equal(allones_ip, ip) || is_zero_ip_v4(ip)) { if( DEBUGLVL( 3 ) ) { dbgtext( "become_domain_master_query_success():\n" ); dbgtext( "Our address (%s) ", inet_ntoa(ip) ); diff --git a/source3/nmbd/nmbd_browsesync.c b/source3/nmbd/nmbd_browsesync.c index 2e12f72b33..e141b3e288 100644 --- a/source3/nmbd/nmbd_browsesync.c +++ b/source3/nmbd/nmbd_browsesync.c @@ -103,7 +103,7 @@ static void announce_local_master_browser_to_domain_master_browser( struct work_ unstring dmb_name; char *p; - if(ismyip(work->dmb_addr)) { + if(ismyip_v4(work->dmb_addr)) { if( DEBUGLVL( 2 ) ) { dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" ); dbgtext( "We are both a domain and a local master browser for " ); @@ -291,7 +291,7 @@ static void find_domain_master_name_query_success(struct subnet_record *subrec, /* First check if we already have a dmb for this workgroup. */ - if(!is_zero_ip(work->dmb_addr) && ip_equal(work->dmb_addr, answer_ip)) { + if(!is_zero_ip_v4(work->dmb_addr) && ip_equal(work->dmb_addr, answer_ip)) { /* Do the local master browser announcement to the domain master browser name and IP. */ announce_local_master_browser_to_domain_master_browser( work ); @@ -300,7 +300,7 @@ static void find_domain_master_name_query_success(struct subnet_record *subrec, sync_with_dmb(work); return; } else { - zero_ip(&work->dmb_addr); + zero_ip_v4(&work->dmb_addr); } /* Now initiate the node status request. */ @@ -526,7 +526,7 @@ static void find_all_domain_master_names_query_success(struct subnet_record *sub * Don't send node status requests to ourself. */ - if(ismyip( send_ip )) { + if(ismyip_v4( send_ip )) { if( DEBUGLVL( 5 ) ) { dbgtext( "find_all_domain_master_names_query_succes:\n" ); dbgtext( "Not sending node status to our own IP " ); diff --git a/source3/nmbd/nmbd_incomingrequests.c b/source3/nmbd/nmbd_incomingrequests.c index 956d0ab1e9..292a580ef9 100644 --- a/source3/nmbd/nmbd_incomingrequests.c +++ b/source3/nmbd/nmbd_incomingrequests.c @@ -88,7 +88,7 @@ subnet %s from owner IP %s\n", subrec->subnet_name, inet_ntoa(owner_ip))); /* If someone is releasing a broadcast group name, just ignore it. */ - if( group && !ismyip(owner_ip) ) + if( group && !ismyip_v4(owner_ip) ) return; /* @@ -98,7 +98,7 @@ subnet %s from owner IP %s\n", */ pull_ascii_nstring(qname, sizeof(qname), question->name); - if( !group && !ismyip(owner_ip) && strequal(qname, lp_workgroup()) && + if( !group && !ismyip_v4(owner_ip) && strequal(qname, lp_workgroup()) && ((question->name_type == 0x0) || (question->name_type == 0x1e))) { DEBUG(6,("process_name_release_request: FTP OnNet bug workaround. Ignoring \ group release name %s from IP %s on subnet %s with no group bit set.\n", @@ -497,7 +497,7 @@ void process_name_query_request(struct subnet_record *subrec, struct packet_stru if (namerec->data.source == WINS_PROXY_NAME) { for( i = 0; i < namerec->data.num_ips; i++) { - if (same_net(namerec->data.ip[i], subrec->myip, subrec->mask_ip)) { + if (same_net_v4(namerec->data.ip[i], subrec->myip, subrec->mask_ip)) { DEBUG(5,("process_name_query_request: name %s is a WINS proxy name and is also on the same subnet (%s) as the requestor. Not replying.\n", nmb_namestr(&namerec->name), subrec->subnet_name )); return; diff --git a/source3/nmbd/nmbd_lmhosts.c b/source3/nmbd/nmbd_lmhosts.c index 4785df6cba..eba7329418 100644 --- a/source3/nmbd/nmbd_lmhosts.c +++ b/source3/nmbd/nmbd_lmhosts.c @@ -48,7 +48,7 @@ void load_lmhosts_file(const char *fname) /* We find a relevent subnet to put this entry on, then add it. */ /* Go through all the broadcast subnets and see if the mask matches. */ for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { - if(same_net(ipaddr, subrec->bcast_ip, subrec->mask_ip)) + if(same_net_v4(ipaddr, subrec->bcast_ip, subrec->mask_ip)) break; } diff --git a/source3/nmbd/nmbd_logonnames.c b/source3/nmbd/nmbd_logonnames.c index 71b69ebd87..f0350af3b8 100644 --- a/source3/nmbd/nmbd_logonnames.c +++ b/source3/nmbd/nmbd_logonnames.c @@ -22,8 +22,6 @@ #include "includes.h" -extern struct in_addr allones_ip; - extern uint16 samba_nb_type; /* Samba's NetBIOS type. */ /**************************************************************************** diff --git a/source3/nmbd/nmbd_namequery.c b/source3/nmbd/nmbd_namequery.c index 4dcae87220..ea170d3aaa 100644 --- a/source3/nmbd/nmbd_namequery.c +++ b/source3/nmbd/nmbd_namequery.c @@ -35,7 +35,7 @@ static void query_name_response( struct subnet_record *subrec, struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name; struct in_addr answer_ip; - zero_ip(&answer_ip); + zero_ip_v4(&answer_ip); /* Ensure we don't retry the query but leave the response record cleanup to the timeout code. We may get more answer responses in which case diff --git a/source3/nmbd/nmbd_packets.c b/source3/nmbd/nmbd_packets.c index 875e13fdc8..cb13febe46 100644 --- a/source3/nmbd/nmbd_packets.c +++ b/source3/nmbd/nmbd_packets.c @@ -28,8 +28,6 @@ extern int global_nmb_port; extern int num_response_packets; -extern struct in_addr loopback_ip; - static void queue_packet(struct packet_struct *packet); BOOL rescan_listen_set = False; @@ -148,7 +146,7 @@ static BOOL send_netbios_packet(struct packet_struct *p) BOOL loopback_this_packet = False; /* Check if we are sending to or from ourselves as a WINS server. */ - if(ismyip(p->ip) && (p->port == global_nmb_port)) + if(ismyip_v4(p->ip) && (p->port == global_nmb_port)) loopback_this_packet = True; if(loopback_this_packet) { @@ -225,12 +223,12 @@ static struct packet_struct *create_and_init_netbios_packet(struct nmb_name *nmb static BOOL create_and_init_additional_record(struct packet_struct *packet, uint16 nb_flags, - struct in_addr *register_ip) + const struct in_addr *register_ip) { struct nmb_packet *nmb = &packet->packet.nmb; if((nmb->additional = SMB_MALLOC_P(struct res_rec)) == NULL) { - DEBUG(0,("initiate_name_register_packet: malloc fail for additional record.\n")); + DEBUG(0,("create_and_init_additional_record: malloc fail for additional record.\n")); return False; } @@ -316,7 +314,7 @@ static BOOL initiate_name_query_packet_from_wins_server( struct packet_struct *p **************************************************************************/ static BOOL initiate_name_register_packet( struct packet_struct *packet, - uint16 nb_flags, struct in_addr *register_ip) + uint16 nb_flags, const struct in_addr *register_ip) { struct nmb_packet *nmb = &packet->packet.nmb; @@ -469,7 +467,8 @@ struct response_record *queue_register_name( struct subnet_record *subrec, { struct packet_struct *p; struct response_record *rrec; - + struct sockaddr_storage ss; + const struct sockaddr_storage *pss = NULL; if(assert_check_subnet(subrec)) return NULL; @@ -478,7 +477,16 @@ struct response_record *queue_register_name( struct subnet_record *subrec, subrec->bcast_ip)) == NULL) return NULL; - if(initiate_name_register_packet( p, nb_flags, iface_ip(subrec->bcast_ip)) == False) { + in_addr_to_sockaddr_storage(&ss, subrec->bcast_ip); + pss = iface_ip(&ss); + if (!pss || pss->ss_family != AF_INET) { + p->locked = False; + free_packet(p); + return NULL; + } + + if(initiate_name_register_packet(p, nb_flags, + &((const struct sockaddr_in *)pss)->sin_addr) == False) { p->locked = False; free_packet(p); return NULL; @@ -698,7 +706,7 @@ struct response_record *queue_query_name( struct subnet_record *subrec, /* queries to the WINS server turn up here as queries to IP 0.0.0.0 These need to be handled a bit differently */ - if (subrec->type == UNICAST_SUBNET && is_zero_ip(to_ip)) { + if (subrec->type == UNICAST_SUBNET && is_zero_ip_v4(to_ip)) { /* What we really need to do is loop over each of our wins * servers and wins server tags here, but that just doesn't * fit our architecture at the moment (userdata may already @@ -724,14 +732,14 @@ struct response_record *queue_query_name( struct subnet_record *subrec, DEBUG(10,("queue_query_name: bind_interfaces_only is set, looking for suitable source IP\n")); for(i = 0; i < iface_count(); i++) { - struct in_addr *ifip = iface_n_ip(i); + const struct in_addr *ifip = iface_n_ip_v4(i); - if(ifip == NULL) { + if (ifip == NULL) { DEBUG(0,("queue_query_name: interface %d has NULL IP address !\n", i)); continue; } - if (ip_equal(*ifip,loopback_ip)) { + if (is_loopback_ip_v4(*ifip)) { DEBUG(5,("queue_query_name: ignoring loopback interface (%d)\n", i)); continue; } @@ -869,7 +877,7 @@ void reply_netbios_packet(struct packet_struct *orig_packet, const char *packet_type = "unknown"; /* Check if we are sending to or from ourselves. */ - if(ismyip(orig_packet->ip) && (orig_packet->port == global_nmb_port)) + if(ismyip_v4(orig_packet->ip) && (orig_packet->port == global_nmb_port)) loopback_this_packet = True; nmb = &packet.packet.nmb; @@ -1020,7 +1028,7 @@ static struct subnet_record *find_subnet_for_dgram_browse_packet(struct packet_s /* Go through all the broadcast subnets and see if the mask matches. */ for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { - if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip)) + if(same_net_v4(p->ip, subrec->bcast_ip, subrec->mask_ip)) return subrec; } @@ -1176,7 +1184,7 @@ static BOOL listening(struct packet_struct *p,struct nmb_name *nbname) struct subnet_record *subrec = NULL; for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { - if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip)) + if(same_net_v4(p->ip, subrec->bcast_ip, subrec->mask_ip)) break; } @@ -1439,7 +1447,7 @@ static struct subnet_record *find_subnet_for_nmb_packet( struct packet_struct *p /* Go through all the broadcast subnets and see if the mask matches. */ for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { - if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip)) + if(same_net_v4(p->ip, subrec->bcast_ip, subrec->mask_ip)) return subrec; } @@ -1814,12 +1822,12 @@ BOOL listen_for_packets(BOOL run_election) * only is set then check it came from one of our local nets. */ if(lp_bind_interfaces_only() && (sock_array[i] == ClientNMB) && - (!is_local_net(packet->ip))) { + (!is_local_net_v4(packet->ip))) { DEBUG(7,("discarding nmb packet sent to broadcast socket from %s:%d\n", inet_ntoa(packet->ip),packet->port)); free_packet(packet); - } else if ((ip_equal(loopback_ip, packet->ip) || - ismyip(packet->ip)) && packet->port == global_nmb_port && + } else if ((is_loopback_ip_v4(packet->ip) || + ismyip_v4(packet->ip)) && packet->port == global_nmb_port && packet->packet.nmb.header.nm_flags.bcast) { DEBUG(7,("discarding own bcast packet from %s:%d\n", inet_ntoa(packet->ip),packet->port)); @@ -1841,12 +1849,12 @@ BOOL listen_for_packets(BOOL run_election) * only is set then check it came from one of our local nets. */ if(lp_bind_interfaces_only() && (sock_array[i] == ClientDGRAM) && - (!is_local_net(packet->ip))) { + (!is_local_net_v4(packet->ip))) { DEBUG(7,("discarding dgram packet sent to broadcast socket from %s:%d\n", inet_ntoa(packet->ip),packet->port)); free_packet(packet); - } else if ((ip_equal(loopback_ip, packet->ip) || - ismyip(packet->ip)) && packet->port == DGRAM_PORT) { + } else if ((is_loopback_ip_v4(packet->ip) || + ismyip_v4(packet->ip)) && packet->port == DGRAM_PORT) { DEBUG(7,("discarding own dgram packet from %s:%d\n", inet_ntoa(packet->ip),packet->port)); free_packet(packet); @@ -1880,7 +1888,7 @@ BOOL send_mailslot(BOOL unique, const char *mailslot,char *buf, size_t len, memset((char *)&p,'\0',sizeof(p)); - if(ismyip(dest_ip) && (dest_port == DGRAM_PORT)) /* Only if to DGRAM_PORT */ + if(ismyip_v4(dest_ip) && (dest_port == DGRAM_PORT)) /* Only if to DGRAM_PORT */ loopback_this_packet = True; /* generate_name_trn_id(); */ /* Not used, so gone, RJS */ diff --git a/source3/nmbd/nmbd_processlogon.c b/source3/nmbd/nmbd_processlogon.c index abac2ac776..4b5fe28d4e 100644 --- a/source3/nmbd/nmbd_processlogon.c +++ b/source3/nmbd/nmbd_processlogon.c @@ -54,6 +54,19 @@ void process_logon_packet(struct packet_struct *p, char *buf,int len, pstring ascuser; char *unicomp; /* Unicode computer name. */ size_t size; + struct sockaddr_storage ss; + const struct sockaddr_storage *pss; + struct in_addr ip; + + in_addr_to_sockaddr_storage(&ss, p->ip); + pss = iface_ip(&ss); + if (!pss) { + DEBUG(5,("process_logon_packet:can't find outgoing interface " + "for packet from IP %s\n", + inet_ntoa(p->ip) )); + return; + } + ip = ((struct sockaddr_in *)pss)->sin_addr; memset(outbuf, 0, sizeof(outbuf)); @@ -127,7 +140,7 @@ logons are not enabled.\n", inet_ntoa(p->ip) )); global_myname(), 0x0, mach_str, dgram->source_name.name_type, - p->ip, *iface_ip(p->ip), p->port); + p->ip, ip, p->port); break; } @@ -258,7 +271,7 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", global_myname(), 0x0, source_name, dgram->source_name.name_type, - p->ip, *iface_ip(p->ip), p->port); + p->ip, ip, p->port); return; } @@ -543,7 +556,7 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", SIVAL(q, 0, 0x00000002); q += 4; /* unknown */ - SIVAL(q, 0, (iface_ip(p->ip))->s_addr); + SIVAL(q, 0, ntohl(ip.s_addr)); q += 4; SIVAL(q, 0, 0x00000000); q += 4; /* unknown */ @@ -573,7 +586,7 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", global_myname(), 0x0, source_name, dgram->source_name.name_type, - p->ip, *iface_ip(p->ip), p->port); + p->ip, ip, p->port); break; } diff --git a/source3/nmbd/nmbd_subnetdb.c b/source3/nmbd/nmbd_subnetdb.c index 690ca5b621..7fd241cf62 100644 --- a/source3/nmbd/nmbd_subnetdb.c +++ b/source3/nmbd/nmbd_subnetdb.c @@ -24,7 +24,6 @@ #include "includes.h" -extern struct in_addr loopback_ip; extern int global_nmb_port; /* This is the broadcast subnets database. */ @@ -169,12 +168,16 @@ static struct subnet_record *make_subnet(const char *name, enum subnet_type type Create a normal subnet **************************************************************************/ -struct subnet_record *make_normal_subnet(struct interface *iface) +struct subnet_record *make_normal_subnet(const struct interface *iface) { + struct subnet_record *subrec; + const struct in_addr *pip = &((const struct sockaddr_in *)&iface->ip)->sin_addr; + const struct in_addr *pbcast = &((const struct sockaddr_in *)&iface->bcast)->sin_addr; + const struct in_addr *pnmask = &((const struct sockaddr_in *)&iface->netmask)->sin_addr; - subrec = make_subnet(inet_ntoa(iface->ip), NORMAL_SUBNET, - iface->ip, iface->bcast, iface->nmask); + subrec = make_subnet(inet_ntoa(*pip), NORMAL_SUBNET, + *pip, *pbcast, *pnmask); if (subrec) { add_subnet(subrec); } @@ -186,8 +189,9 @@ struct subnet_record *make_normal_subnet(struct interface *iface) **************************************************************************/ BOOL create_subnets(void) -{ - int num_interfaces = iface_count(); +{ + /* We only count IPv4 interfaces whilst we're waiting. */ + int num_interfaces = iface_count_v4(); int i; struct in_addr unicast_ip, ipzero; @@ -197,47 +201,59 @@ BOOL create_subnets(void) DEBUG(0,("create_subnets: No local interfaces !\n")); DEBUG(0,("create_subnets: Waiting for an interface to appear ...\n")); - /* + /* * Whilst we're waiting for an interface, allow SIGTERM to * cause us to exit. */ saved_handler = CatchSignal( SIGTERM, SIGNAL_CAST SIG_DFL ); - while (iface_count() == 0) { + /* We only count IPv4 interfaces here. */ + while (iface_count_v4() == 0) { sleep(5); load_interfaces(); } - /* + /* * We got an interface, restore our normal term handler. */ CatchSignal( SIGTERM, SIGNAL_CAST saved_handler ); } + /* + * Here we count v4 and v6 - we know there's at least one + * IPv4 interface and we filter on it below. + */ num_interfaces = iface_count(); - /* + /* * Create subnets from all the local interfaces and thread them onto - * the linked list. + * the linked list. */ for (i = 0 ; i < num_interfaces; i++) { - struct interface *iface = get_interface(i); + const struct interface *iface = get_interface(i); if (!iface) { DEBUG(2,("create_subnets: can't get interface %d.\n", i )); continue; } + /* Ensure we're only dealing with IPv4 here. */ + if (iface->ip.ss_family != AF_INET) { + DEBUG(2,("create_subnets: " + "ignoring non IPv4 interface.\n")); + continue; + } + /* * We don't want to add a loopback interface, in case * someone has added 127.0.0.1 for smbd, nmbd needs to * ignore it here. JRA. */ - if (ip_equal(iface->ip, loopback_ip)) { + if (is_loopback_addr(&iface->ip)) { DEBUG(2,("create_subnets: Ignoring loopback interface.\n" )); continue; } @@ -254,8 +270,8 @@ BOOL create_subnets(void) } if (lp_we_are_a_wins_server()) { - /* Pick the first interface ip address as the WINS server ip. */ - struct in_addr *nip = iface_n_ip(0); + /* Pick the first interface IPv4 address as the WINS server ip. */ + const struct in_addr *nip = first_ipv4_iface(); if (!nip) { return False; @@ -266,7 +282,7 @@ BOOL create_subnets(void) /* note that we do not set the wins server IP here. We just set it at zero and let the wins registration code cope with getting the IPs right for each packet */ - zero_ip(&unicast_ip); + zero_ip_v4(&unicast_ip); } /* @@ -279,7 +295,7 @@ BOOL create_subnets(void) unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET, unicast_ip, unicast_ip, unicast_ip); - zero_ip(&ipzero); + zero_ip_v4(&ipzero); remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET", REMOTE_BROADCAST_SUBNET, diff --git a/source3/nmbd/nmbd_synclists.c b/source3/nmbd/nmbd_synclists.c index 60d1d3fd8d..6b716bdf35 100644 --- a/source3/nmbd/nmbd_synclists.c +++ b/source3/nmbd/nmbd_synclists.c @@ -149,7 +149,7 @@ void sync_browse_lists(struct work_record *work, START_PROFILE(sync_browse_lists); /* Check we're not trying to sync with ourselves. This can happen if we are a domain *and* a local master browser. */ - if (ismyip(ip)) { + if (ismyip_v4(ip)) { done: END_PROFILE(sync_browse_lists); return; diff --git a/source3/nmbd/nmbd_winsproxy.c b/source3/nmbd/nmbd_winsproxy.c index 2c57c4649a..ff80c15fff 100644 --- a/source3/nmbd/nmbd_winsproxy.c +++ b/source3/nmbd/nmbd_winsproxy.c @@ -107,7 +107,7 @@ returned for name %s.\n", nmb_namestr(nmbname) )); if(namerec && original_packet->packet.nmb.header.nm_flags.bcast) { for( i = 0; i < namerec->data.num_ips; i++) { - if( same_net( namerec->data.ip[i], orig_broadcast_subnet->myip, + if( same_net_v4( namerec->data.ip[i], orig_broadcast_subnet->myip, orig_broadcast_subnet->mask_ip ) ) { DEBUG( 5, ( "wins_proxy_name_query_request_success: name %s is a WINS \ proxy name and is also on the same subnet (%s) as the requestor. \ diff --git a/source3/nmbd/nmbd_winsserver.c b/source3/nmbd/nmbd_winsserver.c index cd07549b30..66c060f652 100644 --- a/source3/nmbd/nmbd_winsserver.c +++ b/source3/nmbd/nmbd_winsserver.c @@ -1273,7 +1273,7 @@ already exists in WINS as a GROUP name.\n", nmb_namestr(question) )); if ( namerec != NULL ) { pull_ascii_nstring(name, sizeof(name), namerec->name.name); if( is_myname(name) ) { - if(!ismyip(from_ip)) { + if(!ismyip_v4(from_ip)) { DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) )); send_wins_name_registration_response(RFS_ERR, 0, p); @@ -1595,7 +1595,7 @@ already exists in WINS as a GROUP name.\n", nmb_namestr(question) )); */ if((namerec != NULL) && (is_myname(namerec->name.name)) ) { - if(!ismyip(from_ip)) { + if(!ismyip_v4(from_ip)) { DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) )); send_wins_name_registration_response(RFS_ERR, 0, p); diff --git a/source3/nmbd/nmbd_workgroupdb.c b/source3/nmbd/nmbd_workgroupdb.c index 60194e9915..82c3a31669 100644 --- a/source3/nmbd/nmbd_workgroupdb.c +++ b/source3/nmbd/nmbd_workgroupdb.c @@ -110,7 +110,7 @@ static struct work_record *create_workgroup(const char *name, int ttl) /* No known domain master browser as yet. */ *work->dmb_name.name = '\0'; - zero_ip(&work->dmb_addr); + zero_ip_v4(&work->dmb_addr); /* WfWg uses 01040b01 */ /* Win95 uses 01041501 */ diff --git a/source3/nsswitch/wins.c b/source3/nsswitch/wins.c index 8e4d75e545..9502a5d17e 100644 --- a/source3/nsswitch/wins.c +++ b/source3/nsswitch/wins.c @@ -120,7 +120,10 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count) /* uggh, we have to broadcast to each interface in turn */ for (j=iface_count() - 1;j >= 0;j--) { - struct in_addr *bcast = iface_n_bcast(j); + const struct in_addr *bcast = iface_n_bcast_v4(j); + if (!bcast) { + continue; + } ret = name_query(fd,name,0x00,True,True,*bcast,count, &flags, NULL); if (ret) break; } diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 11827c223b..1bed2bf095 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -2534,13 +2534,13 @@ static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state *the_cli; struct in_addr rm_addr; - if ( is_zero_ip(*client_ip) ) { + if ( is_zero_ip_v4(*client_ip) ) { if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) { DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine)); return False; } - if ( ismyip( rm_addr )) { + if ( ismyip_v4( rm_addr )) { DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine)); return False; } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 0f47a550e9..8c92c91577 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -348,15 +348,24 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ /* Now open a listen socket for each of the interfaces. */ for(i = 0; i < num_interfaces; i++) { - struct in_addr *ifip = iface_n_ip(i); + const struct sockaddr_storage *ifss = + iface_n_sockaddr_storage(i); + const struct in_addr *ifip; fstring tok; const char *ptr; - if(ifip == NULL) { + if (ifss == NULL) { DEBUG(0,("open_sockets_smbd: interface %d has NULL IP address !\n", i)); continue; } + /* For now only deal with IPv4. */ + if (ifss->ss_family != AF_INET) { + continue; + } + + ifip = &((const struct sockaddr_in *)ifss)->sin_addr; + for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { unsigned port = atoi(tok); if (port == 0 || port > 0xffff) { diff --git a/source3/torture/locktest.c b/source3/torture/locktest.c index 9e4b895316..394a237a03 100644 --- a/source3/torture/locktest.c +++ b/source3/torture/locktest.c @@ -174,7 +174,7 @@ static struct cli_state *connect_one(char *share, int snum) server_n = server; - zero_ip(&ip); + zero_ip_v4(&ip); slprintf(myname,sizeof(myname), "lock-%lu-%u", (unsigned long)getpid(), count++); @@ -182,7 +182,7 @@ static struct cli_state *connect_one(char *share, int snum) make_nmb_name(&called , server, 0x20); again: - zero_ip(&ip); + zero_ip_v4(&ip); /* have to open a new connection */ if (!(c=cli_initialise())) { diff --git a/source3/torture/masktest.c b/source3/torture/masktest.c index 4913f60025..bab488f7bb 100644 --- a/source3/torture/masktest.c +++ b/source3/torture/masktest.c @@ -179,13 +179,13 @@ static struct cli_state *connect_one(char *share) server_n = server; - zero_ip(&ip); + zero_ip_v4(&ip); make_nmb_name(&calling, "masktest", 0x0); make_nmb_name(&called , server, 0x20); again: - zero_ip(&ip); + zero_ip_v4(&ip); /* have to open a new connection */ if (!(c=cli_initialise())) { diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 991dadf9e3..a0167e8aab 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -106,7 +106,7 @@ static struct cli_state *open_nbt_connection(void) make_nmb_name(&calling, myname, 0x0); make_nmb_name(&called , host, 0x20); - zero_ip(&ip); + zero_ip_v4(&ip); if (!(c = cli_initialise())) { printf("Failed initialize cli_struct to connect with %s\n", host); diff --git a/source3/utils/net.c b/source3/utils/net.c index 88283ac145..f9af7a41ca 100644 --- a/source3/utils/net.c +++ b/source3/utils/net.c @@ -89,7 +89,6 @@ BOOL opt_testmode = False; BOOL opt_have_ip = False; struct in_addr opt_dest_ip; -extern struct in_addr loopback_ip; extern BOOL AllowDebugChange; uint32 get_sec_channel_type(const char *param) @@ -407,7 +406,7 @@ BOOL net_find_server(const char *domain, unsigned flags, struct in_addr *server_ if (get_pdc_ip(d, &pdc_ip)) { fstring dc_name; - if (is_zero_ip(pdc_ip)) + if (is_zero_ip_v4(pdc_ip)) return False; if ( !name_status_find(d, 0x1b, 0x20, pdc_ip, dc_name) ) @@ -437,7 +436,7 @@ BOOL net_find_server(const char *domain, unsigned flags, struct in_addr *server_ } *server_name = SMB_STRDUP(inet_ntoa(opt_dest_ip)); } else if (!(flags & NET_FLAGS_LOCALHOST_DEFAULT_INSANE)) { - *server_ip = loopback_ip; + (*server_ip).s_addr = htonl(INADDR_LOOPBACK); *server_name = SMB_STRDUP("127.0.0.1"); } @@ -453,7 +452,7 @@ BOOL net_find_server(const char *domain, unsigned flags, struct in_addr *server_ BOOL net_find_pdc(struct in_addr *server_ip, fstring server_name, const char *domain_name) { if (get_pdc_ip(domain_name, server_ip)) { - if (is_zero_ip(*server_ip)) + if (is_zero_ip_v4(*server_ip)) return False; if (!name_status_find(domain_name, 0x1b, 0x20, *server_ip, server_name)) @@ -990,7 +989,7 @@ static struct functable net_func[] = { TALLOC_CTX *frame = talloc_stackframe(); - zero_ip(&opt_dest_ip); + zero_ip_v4(&opt_dest_ip); load_case_tables(); @@ -1009,7 +1008,7 @@ static struct functable net_func[] = { break; case 'I': opt_dest_ip = *interpret_addr2(poptGetOptArg(pc)); - if (is_zero_ip(opt_dest_ip)) + if (is_zero_ip_v4(opt_dest_ip)) d_fprintf(stderr, "\nInvalid ip address specified\n"); else opt_have_ip = True; diff --git a/source3/utils/net_dns.c b/source3/utils/net_dns.c index e1993488f5..716192b057 100644 --- a/source3/utils/net_dns.c +++ b/source3/utils/net_dns.c @@ -145,7 +145,6 @@ int get_my_ip_address( struct in_addr **ips ) { struct iface_struct nics[MAX_INTERFACES]; int i, n; - struct in_addr loopback_ip = *interpret_addr2("127.0.0.1"); struct in_addr *list; int count = 0; @@ -158,7 +157,7 @@ int get_my_ip_address( struct in_addr **ips ) } for ( i=0; i<n; i++ ) { - if ( nics[i].iface_addr.ip.s_addr != loopback_ip.s_addr ) { + if (!is_loopback_ip_v4(nics[i].iface_addr.ip.s_addr)) { memcpy( &list[count++], &nics[i].iface_addr.ip, sizeof( struct in_addr ) ); } } diff --git a/source3/utils/netlookup.c b/source3/utils/netlookup.c index 58c0f01019..998e77c68e 100644 --- a/source3/utils/netlookup.c +++ b/source3/utils/netlookup.c @@ -56,8 +56,9 @@ static int cs_destructor(struct con_struct *p) static struct con_struct *create_cs(TALLOC_CTX *ctx, NTSTATUS *perr) { NTSTATUS nt_status; - struct in_addr loopback_ip = *interpret_addr2("127.0.0.1"); + struct in_addr loopback_ip; + loopback_ip.s_addr = htonl(INADDR_LOOPBACK); *perr = NT_STATUS_OK; if (cs) { diff --git a/source3/utils/nmblookup.c b/source3/utils/nmblookup.c index bf158fe4a0..52d7ad1a3c 100644 --- a/source3/utils/nmblookup.c +++ b/source3/utils/nmblookup.c @@ -141,11 +141,14 @@ static BOOL query_one(const char *lookup, unsigned int lookup_type) use_bcast?True:recursion_desired, bcast_addr,&count, &flags, NULL); } else { - struct in_addr *bcast; + const struct in_addr *bcast; for (j=iface_count() - 1; !ip_list && j >= 0; j--) { - bcast = iface_n_bcast(j); + bcast = iface_n_bcast_v4(j); + if (!bcast) { + continue; + } d_printf("querying %s on %s\n", lookup, inet_ntoa(*bcast)); ip_list = name_query(ServerFD,lookup,lookup_type, diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c index 6324dcc192..dbb067477e 100644 --- a/source3/utils/smbcacls.c +++ b/source3/utils/smbcacls.c @@ -768,7 +768,7 @@ static struct cli_state *connect_one(const char *share) struct cli_state *c; struct in_addr ip; NTSTATUS nt_status; - zero_ip(&ip); + zero_ip_v4(&ip); if (!cmdline_auth_info.got_pass) { char *pass = getpass("Password: "); diff --git a/source3/utils/smbcquotas.c b/source3/utils/smbcquotas.c index 8d954ac20a..1f718b7cef 100644 --- a/source3/utils/smbcquotas.c +++ b/source3/utils/smbcquotas.c @@ -360,7 +360,7 @@ static struct cli_state *connect_one(const char *share) struct cli_state *c; struct in_addr ip; NTSTATUS nt_status; - zero_ip(&ip); + zero_ip_v4(&ip); if (!cmdline_auth_info.got_pass) { char *pass = getpass("Password: "); diff --git a/source3/web/diagnose.c b/source3/web/diagnose.c index 227c68dd6d..9aba27c774 100644 --- a/source3/web/diagnose.c +++ b/source3/web/diagnose.c @@ -20,8 +20,6 @@ #include "includes.h" #include "web/swat_proto.h" -extern struct in_addr loopback_ip; - #ifdef WITH_WINBIND /* check to see if winbind is running by pinging it */ @@ -36,9 +34,12 @@ BOOL winbindd_running(void) response */ BOOL nmbd_running(void) { + struct in_addr loopback_ip; int fd, count, flags; struct in_addr *ip_list; + loopback_ip.s_addr = htonl(INADDR_LOOPBACK); + if ((fd = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr("127.0.0.1"), True)) != -1) { if ((ip_list = name_query(fd, "__SAMBA__", 0, @@ -59,9 +60,12 @@ BOOL nmbd_running(void) then closing it */ BOOL smbd_running(void) { + struct in_addr loopback_ip; NTSTATUS status; struct cli_state *cli; + loopback_ip.s_addr = htonl(INADDR_LOOPBACK); + if ((cli = cli_initialise()) == NULL) return False; diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index e12b13cbbd..4ff9fce96f 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1292,7 +1292,7 @@ static BOOL find_new_dc(TALLOC_CTX *mem_ctx, *addr = addrs[fd_index]; - if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) { + if (*dcnames[fd_index] != '\0' && !is_ipaddress_v4(dcnames[fd_index])) { /* Ok, we've got a name for the DC */ fstrcpy(dcname, dcnames[fd_index]); return True; @@ -1336,7 +1336,7 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, saf_servername, domain->name )); /* convert an ip address to a name */ - if ( is_ipaddress( saf_servername ) ) { + if ( is_ipaddress_v4( saf_servername ) ) { fstring saf_name; struct in_addr ip; diff --git a/source3/winbindd/winbindd_wins.c b/source3/winbindd/winbindd_wins.c index f84dfdf2de..2ee6f69b66 100644 --- a/source3/winbindd/winbindd_wins.c +++ b/source3/winbindd/winbindd_wins.c @@ -118,7 +118,10 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count) for (j=iface_count() - 1; j >= 0; j--) { - struct in_addr *bcast = iface_n_bcast(j); + const struct in_addr *bcast = iface_n_bcast_v4(j); + if (!bcast) { + continue; + } return_ip = name_query(fd,name,0x20,True,True,*bcast,count, &flags, NULL); if (return_ip) { break; |