* libnetworking/netdb.h, libnetworking/libc/gethostbyht.c,
	libnetworking/libc/gethostnamadr.c: This patch adds a functional
	gethostbyname_r to RTEMS. We were having problems with multiple
	threads calling gethostbyname, so we decided the best way to deal
	with it was to do it properly, rather than kludge up our code to make
	gethostbyname safe. We have found several slightly different
	parameter lists for this function, it does not seem to be standard.
	The one we used has the linux interface. In RTEMS there was an
	existing gethostbyname_r inside a #ifdef _THREAD_SAFE which was NOT
	Threadsafe, as this just called gethostbyname. So we have placed all
	of the additional code inside the #ifdef _THREAD_SAFE.
This commit is contained in:
Joel Sherrill committed 2006-11-02 21:48:41 +00:00
1 parent e1d578d8bc
commit 068c3ee1df
4 files changed
+349 -21

No files matched your search

+14
View File
@@ -1,3 +1,17 @@
2006-11-02 Steven Johnson <sjohnson@sakuraindustries.com>
* libnetworking/netdb.h, libnetworking/libc/gethostbyht.c,
libnetworking/libc/gethostnamadr.c: This patch adds a functional
gethostbyname_r to RTEMS. We were having problems with multiple
threads calling gethostbyname, so we decided the best way to deal
with it was to do it properly, rather than kludge up our code to make
gethostbyname safe. We have found several slightly different
parameter lists for this function, it does not seem to be standard.
The one we used has the linux interface. In RTEMS there was an
existing gethostbyname_r inside a #ifdef _THREAD_SAFE which was NOT
Threadsafe, as this just called gethostbyname. So we have placed all
of the additional code inside the #ifdef _THREAD_SAFE.
2006-10-30 Joel Sherrill <joel@OARcorp.com>
PR 841/rtems
+117
View File
@@ -67,6 +67,7 @@ static char rcsid[] = "$Id$";
#include <string.h>
#include <arpa/nameser.h> /* XXX */
#include <resolv.h> /* XXX */
#include <sys/fcntl.h>
#define MAXALIASES 35
@@ -78,6 +79,10 @@ static u_char host_addr[16]; /* IPv4 or IPv6 */
static char *h_addr_ptrs[2];
static int stayopen = 0;
static char* hostmap = NULL;
static unsigned int hostlen = 0;
static char *cur;
void
_sethosthtent(f)
int f;
@@ -200,3 +205,115 @@ _gethostbyhtaddr(addr, len, af)
endhostent();
return (p);
}
#ifdef _THREAD_SAFE
static int isblank ( int ch )
{
return ch == ' ' || ch == '\t';
}
struct hostent* gethostent_r(char* buf, int len)
{
char *dest;
struct hostent* pe=(struct hostent*)buf;
char* last;
char* max=buf+len;
int aliasidx;
int curlen;
if (hostf<0) return 0;
fseek(hostf,0,SEEK_END);
curlen=ftell(hostf);
fseek(hostf,0,SEEK_SET);
if (curlen > hostlen) {
if (hostmap) {
hostmap = realloc(hostmap,curlen);
}
else {
hostmap = malloc(curlen);
}
}
hostlen = curlen;
if (hostmap) {
if (fread(hostmap,hostlen,1,hostf) != hostlen) {
hostmap=0; goto error;
}
cur=hostmap;
}
last=hostmap+hostlen;
again:
if ((size_t)len<sizeof(struct hostent)+11*sizeof(char*)) goto nospace;
dest=buf+sizeof(struct hostent);
pe->h_name=0;
pe->h_aliases=(char**)dest; pe->h_aliases[0]=0; dest+=10*sizeof(char*);
pe->h_addr_list=(char**)dest; dest+=2*sizeof(char**);
if (cur>=last) return 0;
if (*cur=='#' || *cur=='\n') goto parseerror;
/* first, the ip number */
pe->h_name=cur;
while (cur<last && !isspace(*cur)) cur++;
if (cur>=last) return 0;
if (*cur=='\n') goto parseerror;
{
char save=*cur;
*cur=0;
pe->h_addr_list[0]=dest;
pe->h_addr_list[1]=0;
if (max-dest<16) goto nospace;
if (inet_pton(AF_INET6,pe->h_name,dest)>0) {
pe->h_addrtype=AF_INET6;
pe->h_length=16;
dest+=16;
} else if (inet_pton(AF_INET,pe->h_name,dest)>0) {
pe->h_addrtype=AF_INET;
pe->h_length=4;
dest+=4;
} else {
*cur=save;
goto parseerror;
}
*cur=save;
}
++cur;
/* now the aliases */
for (aliasidx=0;aliasidx<9;++aliasidx) {
while (cur<last && isblank(*cur)) ++cur;
pe->h_aliases[aliasidx]=cur;
while (cur<last && !isspace(*cur)) ++cur;
{
char *from=pe->h_aliases[aliasidx];
int len=cur-from;
if (max-dest<len+2) goto nospace;
pe->h_aliases[aliasidx]=dest;
memmove(dest,from,(size_t)(cur-from));
dest+=len;
*dest=0; ++dest;
}
if (*cur=='\n') { ++cur; ++aliasidx; break; }
if (cur>=last || !isblank(*cur)) break;
cur++;
}
pe->h_aliases[aliasidx]=0;
pe->h_name=pe->h_aliases[0];
pe->h_aliases++;
return pe;
parseerror:
while (cur<last && *cur!='\n') cur++;
cur++;
goto again;
nospace:
errno=ERANGE;
goto __error;
error:
errno=ENOMEM;
__error:
if (hostmap!=NULL) free(hostmap);
hostmap=NULL;
return 0;
}
#endif
File diff suppressed because it is too large. Load diff
+10
View File
@@ -160,6 +160,16 @@ void setnetent(int);
void setprotoent(int);
void setservent(int);
#ifdef _THREAD_SAFE
struct hostent* gethostent_r(char* buf, int len);
int gethostbyname_r(const char* name,
struct hostent* result,
char *buf,
int buflen,
struct hostent **RESULT,
int *h_errnop) ;
#endif
/*
* PRIVATE functions specific to the FreeBSD implementation
*/