diff --git a/source3/include/proto.h b/source3/include/proto.h index 506e2e80fa1..ac7b36f005b 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -680,10 +680,11 @@ bool namecache_store(const char *name, int name_type, int num_names, struct ip_service *ip_list); -bool namecache_fetch(const char *name, +bool namecache_fetch(TALLOC_CTX *ctx, + const char *name, int name_type, - struct ip_service **ip_list, - int *num_names); + struct samba_sockaddr **sa_list, + size_t *num_names); bool namecache_delete(const char *name, int name_type); void namecache_flush(void); bool namecache_status_store(const char *keyname, int keyname_type, diff --git a/source3/libsmb/namecache.c b/source3/libsmb/namecache.c index fb4a4aac8c8..ae22c2fc26a 100644 --- a/source3/libsmb/namecache.c +++ b/source3/libsmb/namecache.c @@ -23,6 +23,7 @@ #include "includes.h" #include "lib/gencache.h" +#include "libsmb/namequery.h" #define IPSTR_LIST_SEP "," #define IPSTR_LIST_CHAR ',' @@ -114,35 +115,47 @@ static char *ipstr_list_make(TALLOC_CTX *ctx, * * @param ipstr ip string list to be parsed * @param ip_list pointer to array of ip addresses which is - * allocated by this function and must be freed by caller + * talloced by this function and must be freed by caller * @return number of successfully parsed addresses **/ -static int ipstr_list_parse(const char *ipstr_list, struct ip_service **ip_list) +static int ipstr_list_parse(TALLOC_CTX *ctx, + const char *ipstr_list, + struct samba_sockaddr **sa_list_out) { - TALLOC_CTX *frame; + TALLOC_CTX *frame = talloc_stackframe(); + struct samba_sockaddr *sa_list = NULL; char *token_str = NULL; size_t i, count; + size_t array_size; - if (!ipstr_list || !ip_list) - return 0; + *sa_list_out = NULL; - count = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1; - if ( (*ip_list = SMB_MALLOC_ARRAY(struct ip_service, count)) == NULL ) { - DBG_ERR("malloc failed for %lu entries\n", - (unsigned long)count); + array_size = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1; + sa_list = talloc_zero_array(frame, + struct samba_sockaddr, + array_size); + if (sa_list == NULL) { + TALLOC_FREE(frame); return 0; } - frame = talloc_stackframe(); - for ( i=0; next_token_talloc(frame, &ipstr_list, &token_str, - IPSTR_LIST_SEP) && i= array_size) { + break; + } if (p) { *p = 0; - (*ip_list)[i].port = atoi(p+1); + /* We now ignore the port. */ } /* convert single token to ip address */ @@ -155,11 +168,19 @@ static int ipstr_list_parse(const char *ipstr_list, struct ip_service **ip_list) } *p = '\0'; } - if (!interpret_string_addr(&(*ip_list)[i].ss, - s, - AI_NUMERICHOST)) { + ok = interpret_string_addr(&ss, s, AI_NUMERICHOST); + if (!ok) { continue; } + ok = sockaddr_storage_to_samba_sockaddr(&sa_list[count], + &ss); + if (!ok) { + continue; + } + count++; + } + if (count > 0) { + *sa_list_out = talloc_move(ctx, &sa_list); } TALLOC_FREE(frame); return count; @@ -266,7 +287,7 @@ bool namecache_store(const char *name, * * @param name netbios name to look up for * @param name_type netbios name type of @param name - * @param ip_list mallocated list of IP addresses if found in the cache, + * @param ip_list talloced list of IP addresses if found in the cache, * NULL otherwise * @param num_names number of entries found * @@ -274,19 +295,15 @@ bool namecache_store(const char *name, * false if name isn't found in the cache or has expired **/ -bool namecache_fetch(const char *name, - int name_type, - struct ip_service **ip_list, - int *num_names) +bool namecache_fetch(TALLOC_CTX *ctx, + const char *name, + int name_type, + struct samba_sockaddr **sa_list, + size_t *num_names) { char *key, *value; time_t timeout; - /* exit now if null pointers were passed as they're required further */ - if (!ip_list || !num_names) { - return false; - } - if (name_type > 255) { return false; /* Don't fetch non-real name types. */ } @@ -312,7 +329,7 @@ bool namecache_fetch(const char *name, /* * Split up the stored value into the list of IP adresses */ - *num_names = ipstr_list_parse(value, ip_list); + *num_names = ipstr_list_parse(ctx, value, sa_list); TALLOC_FREE(key); TALLOC_FREE(value); diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c index ba103f6c7fc..2f7a4e81e64 100644 --- a/source3/libsmb/namequery.c +++ b/source3/libsmb/namequery.c @@ -3186,9 +3186,11 @@ static NTSTATUS _internal_resolve_name(const char *name, { const char *tok; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - int i; + size_t i; + size_t nc_count = 0; bool ok; struct sockaddr_storage *ss_list = NULL; + struct samba_sockaddr *sa_list = NULL; TALLOC_CTX *frame = talloc_stackframe(); *return_iplist = NULL; @@ -3232,17 +3234,50 @@ static NTSTATUS _internal_resolve_name(const char *name, /* Check name cache */ - ok = namecache_fetch(name, name_type, return_iplist, return_count); + ok = namecache_fetch(frame, + name, + name_type, + &sa_list, + &nc_count); if (ok) { - *return_count = remove_duplicate_addrs2(*return_iplist, - *return_count ); - if (*return_count > 0) { + /* + * Create a struct ip_service list from the + * returned samba_sockaddrs. + */ + size_t count = 0; + struct ip_service *iplist = NULL; + + iplist = SMB_MALLOC_ARRAY(struct ip_service, nc_count); + if (iplist == NULL) { TALLOC_FREE(frame); - return NT_STATUS_OK; - } else { + return NT_STATUS_NO_MEMORY; + } + count = 0; + for (i = 0; i < nc_count; i++) { + if (is_zero_addr(&sa_list[i].u.ss)) { + continue; + } + iplist[count].ss = sa_list[i].u.ss; + iplist[count].port = 0; + count++; + } + count = remove_duplicate_addrs2(iplist, count); + if (count == 0) { + SAFE_FREE(iplist); TALLOC_FREE(frame); return NT_STATUS_UNSUCCESSFUL; } + /* Paranoia size_t -> int. */ + if ((int)count < 0) { + SAFE_FREE(iplist); + TALLOC_FREE(frame); + return NT_STATUS_INVALID_PARAMETER; + } + + *return_count = (int)count; + *return_iplist = iplist; + TALLOC_FREE(frame); + return NT_STATUS_OK; } /* set the name resolution order */