X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=source3%2Fnsswitch%2Fwins.c;h=7d42381986df537ab9f22fd1ea14c642ea9d8087;hb=2ed60a4f6a6e7533648a588fa3c5d98f37529229;hp=9bb2d6755cb576682d3a926988e35360daaed650;hpb=0df1e25542cfddbb383955e6f541207e38acf654;p=ira%2Fwip.git diff --git a/source3/nsswitch/wins.c b/source3/nsswitch/wins.c index 9bb2d6755cb..7d42381986d 100644 --- a/source3/nsswitch/wins.c +++ b/source3/nsswitch/wins.c @@ -5,7 +5,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -14,13 +14,10 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with this program. If not, see . */ -#define NO_SYSLOG - #include "includes.h" #ifdef HAVE_NS_API_H #undef VOLATILE @@ -34,7 +31,12 @@ static int initialised; -extern BOOL AllowDebugChange; +extern bool AllowDebugChange; + +NSS_STATUS _nss_wins_gethostbyname_r(const char *hostname, struct hostent *he, + char *buffer, size_t buflen, int *h_errnop); +NSS_STATUS _nss_wins_gethostbyname2_r(const char *name, int af, struct hostent *he, + char *buffer, size_t buflen, int *h_errnop); /* Use our own create socket code so we don't recurse.... */ @@ -56,9 +58,15 @@ static int wins_lookup_open_socket_in(void) if (res == -1) return -1; - setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val)); + if (setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val)) != 0) { + close(res); + return -1; + } #ifdef SO_REUSEPORT - setsockopt(res,SOL_SOCKET,SO_REUSEPORT,(char *)&val,sizeof(val)); + if (setsockopt(res,SOL_SOCKET,SO_REUSEPORT,(char *)&val,sizeof(val)) != 0) { + close(res); + return -1; + } #endif /* SO_REUSEPORT */ /* now we've got a socket - we need to bind it */ @@ -82,38 +90,16 @@ static void nss_wins_init(void) TimeInit(); setup_logging("nss_wins",False); - lp_load(dyn_CONFIGFILE,True,False,False); + load_case_tables(); + lp_load(get_dyn_CONFIGFILE(),True,False,False,True); load_interfaces(); } -static struct node_status *lookup_byaddr_backend(char *addr, int *count) -{ - int fd; - struct in_addr ip; - struct nmb_name nname; - struct node_status *status; - - if (!initialised) { - nss_wins_init(); - } - - fd = wins_lookup_open_socket_in(); - if (fd == -1) - return NULL; - - make_nmb_name(&nname, "*", 0); - ip = *interpret_addr2(addr); - status = node_status_query(fd,&nname,ip, count); - - close(fd); - return status; -} - static struct in_addr *lookup_byname_backend(const char *name, int *count) { int fd = -1; + struct ip_service *address = NULL; struct in_addr *ret = NULL; - struct in_addr p; int j, flags = 0; if (!initialised) { @@ -123,7 +109,18 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count) *count = 0; /* always try with wins first */ - if (resolve_wins(name,0x20,&ret,count)) { + if (NT_STATUS_IS_OK(resolve_wins(name,0x00,&address,count))) { + if ( (ret = SMB_MALLOC_P(struct in_addr)) == NULL ) { + free( address ); + return NULL; + } + if (address[0].ss.ss_family != AF_INET) { + free(address); + free(ret); + return NULL; + } + *ret = ((struct sockaddr_in *)&address[0].ss)->sin_addr; + free( address ); return ret; } @@ -134,18 +131,54 @@ 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); - ret = name_query(fd,name,0x20,True,True,*bcast,count, &flags, NULL); - if (ret) break; + const struct in_addr *bcast = iface_n_bcast_v4(j); + struct sockaddr_storage ss; + struct sockaddr_storage *pss; + if (!bcast) { + continue; + } + in_addr_to_sockaddr_storage(&ss, *bcast); + pss = name_query(fd,name,0x00,True,True,&ss,count, &flags, NULL); + if (pss) { + if ((ret = SMB_MALLOC_P(struct in_addr)) == NULL) { + return NULL; + } + *ret = ((struct sockaddr_in *)pss)->sin_addr; + break; + } } -out: close(fd); return ret; } - #ifdef HAVE_NS_API_H + +static NODE_STATUS_STRUCT *lookup_byaddr_backend(char *addr, int *count) +{ + int fd; + struct sockaddr_storage ss; + struct nmb_name nname; + NODE_STATUS_STRUCT *status; + + if (!initialised) { + nss_wins_init(); + } + + fd = wins_lookup_open_socket_in(); + if (fd == -1) + return NULL; + + make_nmb_name(&nname, "*", 0); + if (!interpret_string_addr(&ss, addr, AI_NUMERICHOST)) { + return NULL; + } + status = node_status_query(fd, &nname, &ss, count, NULL); + + close(fd); + return status; +} + /* IRIX version */ int init(void) @@ -161,10 +194,10 @@ int lookup(nsd_file_t *rq) char *key; char *addr; struct in_addr *ip_list; - struct node_status *status; + NODE_STATUS_STRUCT *status; int i, count, len, size; char response[1024]; - BOOL found = False; + bool found = False; nsd_logprintf(NSD_LOG_MIN, "entering lookup (wins)\n"); if (! rq) @@ -189,7 +222,7 @@ int lookup(nsd_file_t *rq) * response needs to be a string of the following format * ip_address[ ip_address]*\tname[ alias]* */ - if (strcasecmp(map,"hosts.byaddr") == 0) { + if (StrCaseCmp(map,"hosts.byaddr") == 0) { if ( status = lookup_byaddr_backend(key, &count)) { size = strlen(key) + 1; if (size > len) { @@ -217,7 +250,7 @@ int lookup(nsd_file_t *rq) response[strlen(response)-1] = '\n'; free(status); } - } else if (strcasecmp(map,"hosts.byname") == 0) { + } else if (StrCaseCmp(map,"hosts.byname") == 0) { if (ip_list = lookup_byname_backend(key, &count)) { for (i = count; i ; i--) { addr = inet_ntoa(ip_list[i-1]); @@ -255,54 +288,112 @@ int lookup(nsd_file_t *rq) } #else + +/* Allocate some space from the nss static buffer. The buffer and buflen + are the pointers passed in by the C library to the _nss_*_* + functions. */ + +static char *get_static(char **buffer, size_t *buflen, int len) +{ + char *result; + + /* Error check. We return false if things aren't set up right, or + there isn't enough buffer space left. */ + + if ((buffer == NULL) || (buflen == NULL) || (*buflen < len)) { + return NULL; + } + + /* Return an index into the static buffer */ + + result = *buffer; + *buffer += len; + *buflen -= len; + + return result; +} + /**************************************************************************** gethostbyname() - we ignore any domain portion of the name and only handle names that are at most 15 characters long **************************************************************************/ NSS_STATUS -_nss_wins_gethostbyname_r(const char *name, struct hostent *he, - char *buffer, size_t buflen, int *errnop, - int *h_errnop) +_nss_wins_gethostbyname_r(const char *hostname, struct hostent *he, + char *buffer, size_t buflen, int *h_errnop) { - char **host_addresses; struct in_addr *ip_list; int i, count; - size_t namelen = strlen(name) + 1; + fstring name; + size_t namelen; memset(he, '\0', sizeof(*he)); + fstrcpy(name, hostname); + + /* Do lookup */ ip_list = lookup_byname_backend(name, &count); - if (!ip_list) { + + if (!ip_list) return NSS_STATUS_NOTFOUND; + + /* Copy h_name */ + + namelen = strlen(name) + 1; + + if ((he->h_name = get_static(&buffer, &buflen, namelen)) == NULL) { + free(ip_list); + return NSS_STATUS_TRYAGAIN; } - if (buflen < namelen + (2*count+1)*INADDRSZ) { - /* no ENOMEM error type?! */ - return NSS_STATUS_NOTFOUND; + memcpy(he->h_name, name, namelen); + + /* Copy h_addr_list, align to pointer boundary first */ + + if ((i = (unsigned long)(buffer) % sizeof(char*)) != 0) + i = sizeof(char*) - i; + + if (get_static(&buffer, &buflen, i) == NULL) { + free(ip_list); + return NSS_STATUS_TRYAGAIN; + } + + if ((he->h_addr_list = (char **)get_static( + &buffer, &buflen, (count + 1) * sizeof(char *))) == NULL) { + free(ip_list); + return NSS_STATUS_TRYAGAIN; + } + + for (i = 0; i < count; i++) { + if ((he->h_addr_list[i] = get_static(&buffer, &buflen, + INADDRSZ)) == NULL) { + free(ip_list); + return NSS_STATUS_TRYAGAIN; + } + memcpy(he->h_addr_list[i], &ip_list[i], INADDRSZ); } + he->h_addr_list[count] = NULL; + + free(ip_list); + + /* Set h_addr_type and h_length */ - host_addresses = (char **)buffer; - he->h_addr_list = host_addresses; - host_addresses[count] = NULL; - buffer += (count + 1) * INADDRSZ; - buflen += (count + 1) * INADDRSZ; he->h_addrtype = AF_INET; he->h_length = INADDRSZ; - for (i=0;ih_aliases = (char **)get_static( + &buffer, &buflen, sizeof(char *))) == NULL) + return NSS_STATUS_TRYAGAIN; - memcpy(buffer, name, namelen); - he->h_name = buffer; + he->h_aliases[0] = NULL; return NSS_STATUS_SUCCESS; } @@ -310,15 +401,14 @@ _nss_wins_gethostbyname_r(const char *name, struct hostent *he, NSS_STATUS _nss_wins_gethostbyname2_r(const char *name, int af, struct hostent *he, - char *buffer, size_t buflen, int *errnop, - int *h_errnop) + char *buffer, size_t buflen, int *h_errnop) { if(af!=AF_INET) { *h_errnop = NO_DATA; - *errnop = EAFNOSUPPORT; return NSS_STATUS_UNAVAIL; } - return _nss_wins_gethostbyname_r(name,he,buffer,buflen,errnop,h_errnop); + return _nss_wins_gethostbyname_r( + name, he, buffer, buflen, h_errnop); } #endif