1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

Move to protocol independent code in most of lib/util_sock.c

We don't use gethostbyname any more except in one case where
we're looking for host aliases (I don't know how to do that
with getaddrinfo yet). New function should be getaddrinfo().
Next step will be fixing lib/access.c, and then changing
libsmb/namequery.c to cope with IPv6 address returns.
Jeremy.
This commit is contained in:
Jeremy Allison 2007-10-15 16:11:48 -07:00
parent 406737cd9a
commit 4a56b697b6
6 changed files with 313 additions and 239 deletions

View File

@ -461,7 +461,7 @@ static void interpret_interface(char *token)
/* maybe it is a DNS name */
p = strchr_m(token,'/');
if (p == NULL) {
if (!interpret_string_addr(&ss, token)) {
if (!interpret_string_addr(&ss, token, 0)) {
DEBUG(2, ("interpret_interface: Can't find address "
"for %s\n", token));
return;
@ -481,7 +481,7 @@ static void interpret_interface(char *token)
/* parse it into an IP address/netmasklength pair */
*p = 0;
goodaddr = interpret_string_addr(&ss, token);
goodaddr = interpret_string_addr(&ss, token, 0);
*p++ = '/';
if (!goodaddr) {
@ -492,7 +492,7 @@ static void interpret_interface(char *token)
}
if (strlen(p) > 2) {
goodaddr = interpret_string_addr(&ss_mask, p);
goodaddr = interpret_string_addr(&ss_mask, p, 0);
if (!goodaddr) {
DEBUG(2,("interpret_interface: "
"can't determine netmask from %s\n",

View File

@ -682,49 +682,6 @@ int sys_chroot(const char *dname)
#endif
}
/**************************************************************************
A wrapper for gethostbyname() that tries avoids looking up hostnames
in the root domain, which can cause dial-on-demand links to come up for no
apparent reason.
****************************************************************************/
struct hostent *sys_gethostbyname(const char *name)
{
#ifdef REDUCE_ROOT_DNS_LOOKUPS
char query[HOST_NAME_MAX], hostname[HOST_NAME_MAX];
char *domain;
/* Does this name have any dots in it? If so, make no change */
if (strchr_m(name, '.'))
return(gethostbyname(name));
/* Get my hostname, which should have domain name
attached. If not, just do the gethostname on the
original string.
*/
gethostname(hostname, sizeof(hostname) - 1);
hostname[sizeof(hostname) - 1] = 0;
if ((domain = strchr_m(hostname, '.')) == NULL)
return(gethostbyname(name));
/* Attach domain name to query and do modified query.
If names too large, just do gethostname on the
original string.
*/
if((strlen(name) + strlen(domain)) >= sizeof(query))
return(gethostbyname(name));
slprintf(query, sizeof(query)-1, "%s%s", name, domain);
return(gethostbyname(query));
#else /* REDUCE_ROOT_DNS_LOOKUPS */
return(gethostbyname(name));
#endif /* REDUCE_ROOT_DNS_LOOKUPS */
}
#if defined(HAVE_POSIX_CAPABILITIES)
#ifdef HAVE_SYS_CAPABILITY_H

View File

@ -1208,37 +1208,6 @@ BOOL get_myname(char *my_name)
return(True);
}
/****************************************************************************
Get my own canonical name, including domain.
****************************************************************************/
BOOL get_mydnsfullname(fstring my_dnsname)
{
static fstring dnshostname;
struct hostent *hp;
if (!*dnshostname) {
/* get my host name */
if (gethostname(dnshostname, sizeof(dnshostname)) == -1) {
*dnshostname = '\0';
DEBUG(0,("gethostname failed\n"));
return False;
}
/* Ensure null termination. */
dnshostname[sizeof(dnshostname)-1] = '\0';
/* Ensure we get the cannonical name. */
if (!(hp = sys_gethostbyname(dnshostname))) {
*dnshostname = '\0';
return False;
}
fstrcpy(dnshostname, hp->h_name);
}
fstrcpy(my_dnsname, dnshostname);
return True;
}
/****************************************************************************
Get my own domain name.
****************************************************************************/
@ -2742,17 +2711,23 @@ BOOL unix_wild_match(const char *pattern, const char *string)
/**********************************************************************
Converts a name to a fully qualified domain name.
Returns True if lookup succeeded, False if not (then fqdn is set to name)
Returns true if lookup succeeded, false if not (then fqdn is set to name)
Note we deliberately use gethostbyname here, not getaddrinfo as we want
to examine the h_aliases and I don't know how to do that with getaddrinfo.
***********************************************************************/
BOOL name_to_fqdn(fstring fqdn, const char *name)
bool name_to_fqdn(fstring fqdn, const char *name)
{
struct hostent *hp = sys_gethostbyname(name);
if ( hp && hp->h_name && *hp->h_name ) {
char *full = NULL;
struct hostent *hp = gethostbyname(name);
/* find out if the fqdn is returned as an alias
if (!hp || !hp->h_name || !*hp->h_name) {
DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
fstrcpy(fqdn, name);
return false;
}
/* Find out if the fqdn is returned as an alias
* to cope with /etc/hosts files where the first
* name is not the fqdn but the short name */
if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
@ -2771,19 +2746,13 @@ BOOL name_to_fqdn(fstring fqdn, const char *name)
DEBUGADD(1, (" may end up being used instead of the real machine FQDN.\n"));
full = hp->h_name;
}
if (!full) {
full = hp->h_name;
}
DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
fstrcpy(fqdn, full);
return True;
} else {
DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
fstrcpy(fqdn, name);
return False;
}
return true;
}
/**********************************************************************

View File

@ -29,63 +29,133 @@ static int client_fd = -1;
static char client_ip_string[INET6_ADDRSTRLEN];
/****************************************************************************
Return true if a string could be a pure IPv4 address.
Return true if a string could be an IPv4 address.
****************************************************************************/
bool is_ipaddress_v4(const char *str)
{
bool pure_address = true;
int i;
int ret = -1;
struct in_addr dest;
for (i=0; pure_address && str[i]; i++) {
if (!(isdigit((int)str[i]) || str[i] == '.')) {
pure_address = false;
}
ret = inet_pton(AF_INET, str, &dest);
if (ret > 0) {
return true;
}
return false;
}
/* Check that a pure number is not misinterpreted as an IP */
pure_address = pure_address && (strchr_m(str, '.') != NULL);
return pure_address;
/****************************************************************************
Return true if a string could be an IPv4 or IPv6 address.
****************************************************************************/
bool is_ipaddress(const char *str)
{
int ret = -1;
#if defined(AF_INET6)
struct in6_addr dest6;
ret = inet_pton(AF_INET6, str, &dest6);
if (ret > 0) {
return true;
}
#endif
return is_ipaddress_v4(str);
}
/*******************************************************************
Wrap getaddrinfo...
******************************************************************/
static bool interpret_string_addr_internal(struct addrinfo **ppres,
const char *str, int flags)
{
int ret;
struct addrinfo hints;
memset(&hints, '\0', sizeof(hints));
/* By default make sure it supports TCP. */
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = flags;
ret = getaddrinfo(str, NULL,
&hints,
ppres);
if (ret) {
DEBUG(3,("interpret_string_addr_interal: getaddrinfo failed "
"for name %s [%s]\n",
str,
gai_strerror(ret) ));
return false;
}
return true;
}
/****************************************************************************
Interpret an internet address or name into an IP address in 4 byte form.
RETURNS IN NETWORK BYTE ORDER (big endian).
****************************************************************************/
uint32 interpret_addr(const char *str)
{
struct hostent *hp;
uint32 res;
uint32 ret;
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
/* 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);
struct in_addr dest;
if (inet_pton(AF_INET, str, &dest) <= 0) {
/* Error - this shouldn't happen ! */
DEBUG(0,("interpret_addr: inet_pton failed "
"host %s\n",
str));
return 0;
}
ret = dest.s_addr; /* NETWORK BYTE ORDER ! */
} 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));
/* Otherwise assume it's a network name of some sort and use
getadddrinfo. */
struct addrinfo *res = NULL;
struct addrinfo *res_list = NULL;
if (!interpret_string_addr_internal(&res_list,
str,
AI_ADDRCONFIG)) {
DEBUG(3,("interpret_addr: Unknown host. %s\n",str));
return 0;
}
if(hp->h_addr == NULL) {
DEBUG(3,("sys_gethostbyname: host address is "
/* Find the first IPv4 address. */
for (res = res_list; res; res = res->ai_next) {
if (res->ai_family != AF_INET) {
continue;
}
if (res->ai_addr == NULL) {
continue;
}
break;
}
if(res == NULL) {
DEBUG(3,("interpret_addr: host address is "
"invalid for host %s\n",str));
if (res_list) {
freeaddrinfo(res_list);
}
return 0;
}
putip((char *)&res,(char *)hp->h_addr);
putip((char *)&ret,
&((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr);
if (res_list) {
freeaddrinfo(res_list);
}
}
if (res == (uint32)-1)
return(0);
/* This is so bogus - all callers need fixing... JRA. */
if (ret == (uint32)-1) {
return 0;
}
return(res);
return ret;
}
/*******************************************************************
@ -105,31 +175,20 @@ struct in_addr *interpret_addr2(const char *str)
struct sockaddr_storage.
******************************************************************/
bool interpret_string_addr(struct sockaddr_storage *pss, const char *str)
bool interpret_string_addr(struct sockaddr_storage *pss,
const char *str,
int flags)
{
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) ));
if (!interpret_string_addr_internal(&res, str, flags|AI_ADDRCONFIG)) {
return false;
}
if (!res) {
return false;
}
/* Copy the first sockaddr. */
memcpy(pss, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
@ -155,7 +214,8 @@ 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;
struct in6_addr *pin6 =
&((struct sockaddr_in6 *)pss)->sin6_addr;
return IN6_IS_ADDR_LOOPBACK(pin6);
}
#endif
@ -185,7 +245,8 @@ 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;
struct in6_addr *pin6 =
&((struct sockaddr_in6 *)pss)->sin6_addr;
return IN6_IS_ADDR_UNSPECIFIED(pin6);
}
#endif
@ -1215,7 +1276,7 @@ bool send_smb(int fd, char *buffer)
int open_socket_in(int type,
int port,
int dlevel,
uint32 socket_addr,
uint32 socket_addr, /* NETWORK BYTE ORDER */
bool rebind )
{
struct sockaddr_in sock;
@ -1595,22 +1656,14 @@ static bool matchname(const char *remotehost,
const struct sockaddr_storage *pss,
socklen_t len)
{
struct addrinfo hints;
struct addrinfo *res = NULL;
struct addrinfo *ailist = NULL;
char addr_buf[INET6_ADDRSTRLEN];
int ret = -1;
bool ret = interpret_string_addr_internal(&ailist,
remotehost,
AI_ADDRCONFIG|AI_CANONNAME);
memset(&hints,'\0',sizeof(struct addrinfo));
/* By default make sure it supports TCP. */
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_ADDRCONFIG|AI_CANONNAME;
ret = getaddrinfo(remotehost, NULL,
&hints,
&res);
if (ret || res == NULL) {
if (!ret || ailist == NULL) {
DEBUG(3,("matchname: getaddrinfo failed for "
"name %s [%s]\n",
remotehost,
@ -1622,24 +1675,25 @@ static bool matchname(const char *remotehost,
* Make sure that getaddrinfo() returns the "correct" host name.
*/
if (res->ai_canonname == NULL ||
(!strequal(remotehost, res->ai_canonname) &&
if (ailist->ai_canonname == NULL ||
(!strequal(remotehost, ailist->ai_canonname) &&
!strequal(remotehost, "localhost"))) {
DEBUG(0,("matchname: host name/name mismatch: %s != %s\n",
remotehost,
res->ai_canonname ? res->ai_canonname : "(NULL)"));
freeaddrinfo(res);
ailist->ai_canonname ?
ailist->ai_canonname : "(NULL)"));
freeaddrinfo(ailist);
return false;
}
/* Look up the host address in the address list we just got. */
for (ailist = res; ailist; ailist = ailist->ai_next) {
if (!ailist->ai_addr) {
for (res = ailist; res; res = res->ai_next) {
if (!res->ai_addr) {
continue;
}
if (addr_equal((const struct sockaddr_storage *)ailist->ai_addr,
if (addr_equal((const struct sockaddr_storage *)res->ai_addr,
pss)) {
freeaddrinfo(res);
freeaddrinfo(ailist);
return true;
}
}
@ -1655,9 +1709,11 @@ static bool matchname(const char *remotehost,
sizeof(addr_buf),
pss,
len),
res->ai_canonname ? res->ai_canonname : "(NULL)"));
ailist->ai_canonname ? ailist->ai_canonname : "(NULL)"));
freeaddrinfo(res);
if (ailist) {
freeaddrinfo(ailist);
}
return false;
}
@ -1837,8 +1893,62 @@ out_umask:
#endif /* HAVE_UNIXSOCKET */
}
/****************************************************************************
Get my own canonical name, including domain.
****************************************************************************/
bool get_mydnsfullname(fstring my_dnsname)
{
static fstring dnshostname;
if (!*dnshostname) {
struct addrinfo *res = NULL;
bool ret;
/* get my host name */
if (gethostname(dnshostname, sizeof(dnshostname)) == -1) {
*dnshostname = '\0';
DEBUG(0,("get_mydnsfullname: gethostname failed\n"));
return false;
}
/* Ensure null termination. */
dnshostname[sizeof(dnshostname)-1] = '\0';
ret = interpret_string_addr_internal(&res,
dnshostname,
AI_ADDRCONFIG|AI_CANONNAME);
if (!ret || res == NULL) {
DEBUG(3,("get_mydnsfullname: getaddrinfo failed for "
"name %s [%s]\n",
dnshostname,
gai_strerror(ret) ));
return false;
}
/*
* Make sure that getaddrinfo() returns the "correct" host name.
*/
if (res->ai_canonname == NULL) {
DEBUG(3,("get_mydnsfullname: failed to get "
"canonical name for %s\n",
dnshostname));
freeaddrinfo(res);
return false;
}
fstrcpy(dnshostname, res->ai_canonname);
freeaddrinfo(res);
}
fstrcpy(my_dnsname, dnshostname);
return true;
}
/************************************************************
Is this my name ? Needs fixing for IPv6.
Is this my name ?
************************************************************/
bool is_myname_or_ipaddr(const char *s)
@ -1846,83 +1956,82 @@ bool is_myname_or_ipaddr(const char *s)
fstring name, dnsname;
char *servername;
if ( !s ) {
if (!s) {
return false;
}
/* santize the string from '\\name' */
/* Santize the string from '\\name' */
fstrcpy(name, s);
fstrcpy( name, s );
servername = strrchr_m( name, '\\' );
if ( !servername )
servername = strrchr_m(name, '\\' );
if (!servername) {
servername = name;
else
} else {
servername++;
}
/* optimize for the common case */
if (strequal(servername, global_myname()))
/* Optimize for the common case */
if (strequal(servername, global_myname())) {
return true;
}
/* check for an alias */
if (is_myname(servername))
/* Check for an alias */
if (is_myname(servername)) {
return true;
}
/* check for loopback */
if (strequal(servername, "127.0.0.1"))
/* Check for loopback */
if (strequal(servername, "127.0.0.1") ||
strequal(servername, "::1")) {
return true;
}
if (strequal(servername, "localhost"))
if (strequal(servername, "localhost")) {
return true;
}
/* maybe it's my dns name */
if ( get_mydnsfullname( dnsname ) )
if ( strequal( servername, dnsname ) )
/* 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 ) );
/* Handle possible CNAME records - convert to an IP addr. */
if (!is_ipaddress(servername)) {
/* Use DNS to resolve the name, but only the first address */
struct sockaddr_storage ss;
if (interpret_string_addr(&ss, servername,0)) {
print_sockaddr(name,
sizeof(name),
&ss,
sizeof(ss));
servername = name;
}
}
/* maybe its an IP address? */
if (is_ipaddress_v4(servername)) {
/* Maybe its an IP address? */
if (is_ipaddress(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)) {
if (!interpret_string_addr(&ss, servername, AI_NUMERICHOST)) {
return false;
}
in_addr_to_sockaddr_storage(&ss, ip);
if (is_zero_addr(&ss) || is_loopback_addr(&ss)) {
return false;
}
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 */
/* No match */
return false;
}

View File

@ -1028,7 +1028,11 @@ static NTSTATUS resolve_hosts(const char *name, int name_type,
/*
* "host" means do a localhost, or dns lookup.
*/
struct hostent *hp;
struct addrinfo hints;
struct addrinfo *ailist = NULL;
struct addrinfo *res = NULL;
int ret = -1;
int i = 0;
if ( name_type != 0x20 && name_type != 0x0) {
DEBUG(5, ("resolve_hosts: not appropriate for name type <0x%x>\n", name_type));
@ -1040,17 +1044,53 @@ static NTSTATUS resolve_hosts(const char *name, int name_type,
DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x%x>\n", name, name_type));
if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
ZERO_STRUCT(hints);
/* By default make sure it supports TCP. */
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_ADDRCONFIG;
ret = getaddrinfo(name,
NULL,
&hints,
&ailist);
if (ret) {
DEBUG(3,("resolve_hosts: getaddrinfo failed for name %s [%s]\n",
name,
gai_strerror(ret) ));
}
for (res = ailist; res; res = res->ai_next) {
struct in_addr return_ip;
putip((char *)&return_ip,(char *)hp->h_addr);
*return_iplist = SMB_MALLOC_P(struct ip_service);
if(*return_iplist == NULL) {
/* IPv4 only for now until I convert ip_service */
if (res->ai_family != AF_INET) {
continue;
}
if (!res->ai_addr) {
continue;
}
putip((char *)&return_ip,
&((struct sockaddr_in *)res->ai_addr)->sin_addr);
*return_count += 1;
i++;
*return_iplist = SMB_REALLOC_ARRAY(*return_iplist,
struct ip_service,
*return_count);
if (!*return_iplist) {
DEBUG(3,("resolve_hosts: malloc fail !\n"));
freeaddrinfo(ailist);
return NT_STATUS_NO_MEMORY;
}
(*return_iplist)->ip = return_ip;
(*return_iplist)->port = PORT_NONE;
*return_count = 1;
(*return_iplist)[i].ip = return_ip;
(*return_iplist)[i].port = PORT_NONE;
}
if (ailist) {
freeaddrinfo(ailist);
}
if (*return_count) {
return NT_STATUS_OK;
}
return NT_STATUS_UNSUCCESSFUL;

View File

@ -171,7 +171,7 @@ static krb5_error_code smb_krb5_locator_call_cbfunc(const char *name,
int (*cbfunc)(void *, int, struct sockaddr *),
void *cbdata)
{
struct addrinfo *out;
struct addrinfo *out = NULL;
int ret;
int count = 3;
@ -206,7 +206,6 @@ static krb5_error_code smb_krb5_locator_call_cbfunc(const char *name,
#endif
freeaddrinfo(out);
return ret;
}