Changeset 068c3ee1 in rtems


Ignore:
Timestamp:
Nov 2, 2006, 9:48:41 PM (14 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.8, 4.9, 5, master
Children:
918b7a9
Parents:
e1d578d8
Message:

2006-11-02 Steven Johnson <sjohnson@…>

  • 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.
Location:
cpukit
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • cpukit/ChangeLog

    re1d578d8 r068c3ee1  
     12006-11-02      Steven Johnson <sjohnson@sakuraindustries.com>
     2
     3        * libnetworking/netdb.h, libnetworking/libc/gethostbyht.c,
     4        libnetworking/libc/gethostnamadr.c: This patch adds a functional
     5        gethostbyname_r to RTEMS. We were having problems with multiple
     6        threads calling gethostbyname, so we decided the best way to deal
     7        with it was to do it properly, rather than kludge up our code to make
     8        gethostbyname safe. We have found several slightly different
     9        parameter lists for this function, it does not seem to be standard.
     10        The one we used has the linux interface. In RTEMS there was an
     11        existing gethostbyname_r inside a #ifdef _THREAD_SAFE which was NOT
     12        Threadsafe, as this just called gethostbyname. So we have placed all
     13        of the additional code inside the #ifdef _THREAD_SAFE.
     14
    1152006-10-30      Joel Sherrill <joel@OARcorp.com>
    216
  • cpukit/libnetworking/libc/gethostbyht.c

    re1d578d8 r068c3ee1  
    6868#include <arpa/nameser.h>       /* XXX */
    6969#include <resolv.h>             /* XXX */
     70#include <sys/fcntl.h>
    7071
    7172#define MAXALIASES      35
     
    7879static char *h_addr_ptrs[2];
    7980static int stayopen = 0;
     81
     82static char* hostmap = NULL;
     83static unsigned int hostlen = 0;
     84static char *cur;
    8085
    8186void
     
    201206        return (p);
    202207}
     208
     209
     210#ifdef _THREAD_SAFE
     211
     212static int isblank ( int ch )
     213{
     214    return ch == ' '  ||  ch == '\t';
     215}
     216
     217struct hostent* gethostent_r(char* buf, int len)
     218{
     219  char  *dest;
     220  struct hostent* pe=(struct hostent*)buf;
     221  char*  last;
     222  char*  max=buf+len;
     223  int    aliasidx;
     224  int    curlen;
     225 
     226   
     227  if (hostf<0) return 0;
     228  fseek(hostf,0,SEEK_END);
     229  curlen=ftell(hostf);
     230  fseek(hostf,0,SEEK_SET);
     231 
     232  if (curlen > hostlen) {
     233    if (hostmap) {
     234      hostmap = realloc(hostmap,curlen);
     235    }
     236    else {
     237      hostmap = malloc(curlen);
     238    }
     239  }
     240  hostlen = curlen;
     241 
     242  if (hostmap) {
     243    if (fread(hostmap,hostlen,1,hostf) != hostlen) {
     244        hostmap=0; goto error;
     245    }
     246    cur=hostmap;
     247  }
     248  last=hostmap+hostlen;
     249again:
     250  if ((size_t)len<sizeof(struct hostent)+11*sizeof(char*)) goto nospace;
     251  dest=buf+sizeof(struct hostent);
     252  pe->h_name=0;
     253  pe->h_aliases=(char**)dest; pe->h_aliases[0]=0; dest+=10*sizeof(char*);
     254  pe->h_addr_list=(char**)dest; dest+=2*sizeof(char**);
     255  if (cur>=last) return 0;
     256  if (*cur=='#' || *cur=='\n') goto parseerror;
     257  /* first, the ip number */
     258  pe->h_name=cur;
     259  while (cur<last && !isspace(*cur)) cur++;
     260  if (cur>=last) return 0;
     261  if (*cur=='\n') goto parseerror;
     262  {
     263    char save=*cur;
     264    *cur=0;
     265    pe->h_addr_list[0]=dest;
     266    pe->h_addr_list[1]=0;
     267    if (max-dest<16) goto nospace;
     268    if (inet_pton(AF_INET6,pe->h_name,dest)>0) {
     269      pe->h_addrtype=AF_INET6;
     270      pe->h_length=16;
     271      dest+=16;
     272    } else if (inet_pton(AF_INET,pe->h_name,dest)>0) {
     273      pe->h_addrtype=AF_INET;
     274      pe->h_length=4;
     275      dest+=4;
     276    } else {
     277      *cur=save;
     278      goto parseerror;
     279    }
     280    *cur=save;
     281  }
     282  ++cur;
     283  /* now the aliases */
     284  for (aliasidx=0;aliasidx<9;++aliasidx) {
     285    while (cur<last && isblank(*cur)) ++cur;
     286    pe->h_aliases[aliasidx]=cur;
     287    while (cur<last && !isspace(*cur)) ++cur;
     288    {
     289      char *from=pe->h_aliases[aliasidx];
     290      int len=cur-from;
     291      if (max-dest<len+2) goto nospace;
     292      pe->h_aliases[aliasidx]=dest;
     293      memmove(dest,from,(size_t)(cur-from));
     294      dest+=len;
     295      *dest=0; ++dest;
     296    }
     297    if (*cur=='\n') { ++cur; ++aliasidx; break; }
     298    if (cur>=last || !isblank(*cur)) break;
     299    cur++;
     300  }
     301  pe->h_aliases[aliasidx]=0;
     302  pe->h_name=pe->h_aliases[0];
     303  pe->h_aliases++;
     304  return pe;
     305parseerror:
     306  while (cur<last && *cur!='\n') cur++;
     307  cur++;
     308  goto again;
     309nospace:
     310  errno=ERANGE;
     311  goto __error;
     312error:
     313  errno=ENOMEM;
     314__error:
     315  if (hostmap!=NULL) free(hostmap);
     316  hostmap=NULL;
     317  return 0;
     318}
     319#endif
  • cpukit/libnetworking/libc/gethostnamadr.c

    re1d578d8 r068c3ee1  
    188188}
    189189
    190 #ifdef _THREAD_SAFE
    191 struct hostent_data;
    192 
    193 /*
    194  * Temporary function (not thread safe)
    195  */
    196 int gethostbyaddr_r(const char *addr, int len, int type,
    197         struct hostent *result, struct hostent_data *buffer)
    198 {
    199         struct hostent *hp;
    200         int ret;
    201         if ((hp = gethostbyaddr(addr, len, type)) == NULL) {
    202                 ret = -1;
    203         } else {
    204                 memcpy(result, hp, sizeof(struct hostent));
    205                 ret = 0;
    206         }
    207         return(ret);
    208 }
    209 #endif
    210 
    211190void
    212191sethostent(stayopen)
     
    223202        _endhostdnsent();
    224203}
     204
     205#ifdef _THREAD_SAFE
     206
     207/* return length of decoded data or -1 */
     208static int __dns_decodename(unsigned char *packet,unsigned int offset,unsigned char *dest,
     209         unsigned int maxlen,unsigned char* behindpacket) {
     210  unsigned char *tmp;
     211  unsigned char *max=dest+maxlen;
     212  unsigned char *after=packet+offset;
     213  int ok=0;
     214  for (tmp=after; maxlen>0&&*tmp; ) {
     215    if (tmp>=behindpacket) return -1;
     216    if ((*tmp>>6)==3) {   /* goofy DNS decompression */
     217      unsigned int ofs=((unsigned int)(*tmp&0x3f)<<8)|*(tmp+1);
     218      if (ofs>=(unsigned int)offset) return -1; /* RFC1035: "pointer to a _prior_ occurrance" */
     219      if (after<tmp+2) after=tmp+2;
     220      tmp=packet+ofs;
     221      ok=0;
     222    } else {
     223      unsigned int duh;
     224      if (dest+*tmp+1>max) return -1;
     225      if (tmp+*tmp+1>=behindpacket) return -1;
     226      for (duh=*tmp; duh>0; --duh)
     227  *dest++=*++tmp;
     228      *dest++='.'; ok=1;
     229      ++tmp;
     230      if (tmp>after) { after=tmp; if (!*tmp) ++after; }
     231    }
     232  }
     233  if (ok) --dest;
     234  *dest=0;
     235  return after-packet;
     236}
     237
     238static int __dns_gethostbyx_r(const char* name, struct hostent* result,
     239      char *buf, size_t buflen,
     240      struct hostent **RESULT, int *h_errnop, int lookfor) {
     241
     242  int names,ips;
     243  unsigned char *cur;
     244  unsigned char *max;
     245  unsigned char inpkg[1500];
     246  char* tmp;
     247  int size;
     248
     249  if (lookfor==1) {
     250    result->h_addrtype=AF_INET;
     251    result->h_length=4;
     252  } else {
     253    result->h_addrtype=AF_INET6;
     254    result->h_length=16;
     255  }
     256  result->h_aliases=(char**)(buf+8*sizeof(char*));
     257  result->h_addr_list=(char**)buf;
     258  result->h_aliases[0]=0;
     259
     260  cur=buf+16*sizeof(char*);
     261  max=buf+buflen;
     262  names=ips=0;
     263
     264  if ((size=res_query(name,C_IN,lookfor,inpkg,512))<0) {
     265invalidpacket:
     266    *h_errnop=HOST_NOT_FOUND;
     267    return -1;
     268  }
     269  {
     270    tmp=inpkg+12;
     271    {
     272      char Name[257];
     273      unsigned short q=((unsigned short)inpkg[4]<<8)+inpkg[5];
     274      while (q>0) {
     275  if (tmp>(char*)inpkg+size) goto invalidpacket;
     276  while (*tmp) { tmp+=*tmp+1; if (tmp>(char*)inpkg+size) goto invalidpacket; }
     277  tmp+=5;
     278  --q;
     279      }
     280      if (tmp>(char*)inpkg+size) goto invalidpacket;
     281      q=((unsigned short)inpkg[6]<<8)+inpkg[7];
     282      if (q<1) goto nodata;
     283      while (q>0) {
     284  int decofs=__dns_decodename(inpkg,(size_t)(tmp-(char*)inpkg),Name,256,inpkg+size);
     285  if (decofs<0) break;
     286  tmp=inpkg+decofs;
     287  --q;
     288  if (tmp[0]!=0 || tmp[1]!=lookfor || /* TYPE != A */
     289      tmp[2]!=0 || tmp[3]!=1) {   /* CLASS != IN */
     290    if (tmp[1]==5) {  /* CNAME */
     291      tmp+=10;
     292      decofs=__dns_decodename(inpkg,(size_t)(tmp-(char*)inpkg),Name,256,inpkg+size);
     293      if (decofs<0) break;
     294      tmp=inpkg+decofs;
     295    } else
     296      break;
     297    continue;
     298  }
     299  tmp+=10;  /* skip type, class, TTL and length */
     300  {
     301    int slen;
     302    if (lookfor==1 || lookfor==28) /* A or AAAA*/ {
     303      slen=strlen(Name);
     304      if (cur+slen+8+(lookfor==28?12:0)>=max) { *h_errnop=NO_RECOVERY; return -1; }
     305    } else if (lookfor==12) /* PTR */ {
     306      decofs=__dns_decodename(inpkg,(size_t)(tmp-(char*)inpkg),Name,256,inpkg+size);
     307      if (decofs<0) break;
     308      tmp=inpkg+decofs;
     309      slen=strlen(Name);
     310    } else
     311      slen=strlen(Name);
     312    strcpy(cur,Name);
     313    if (names==0)
     314      result->h_name=cur;
     315    else
     316      result->h_aliases[names-1]=cur;
     317    result->h_aliases[names]=0;
     318    if (names<8) ++names;
     319/*    cur+=slen+1; */
     320    cur+=(slen|3)+1;
     321    result->h_addr_list[ips++] = cur;
     322    if (lookfor==1) /* A */ {
     323      *(int*)cur=*(int*)tmp;
     324      cur+=4;
     325      result->h_addr_list[ips]=0;
     326    } else if (lookfor==28) /* AAAA */ {
     327      {
     328        int k;
     329        for (k=0; k<16; ++k) cur[k]=tmp[k];
     330      }
     331      cur+=16;
     332      result->h_addr_list[ips]=0;
     333    }
     334  }
     335/*        puts(Name); */
     336      }
     337    }
     338  }
     339  if (!names) {
     340nodata:
     341    *h_errnop=NO_DATA;
     342    return -1;
     343  }
     344  *h_errnop=0;
     345  *RESULT=result;
     346  return 0;
     347}
     348
     349
     350
     351
     352int gethostbyname_r(const char*      name,
     353        struct hostent*  result,
     354        char            *buf,
     355        int              buflen,
     356        struct hostent **RESULT,
     357        int             *h_errnop)
     358{
     359       
     360  size_t L=strlen(name);
     361  result->h_name=buf;
     362  if (buflen<L) { *h_errnop=ERANGE; return 1; }
     363  strcpy(buf,name);
     364
     365  result->h_addr_list=(char**)(buf+strlen(name)+1);
     366  result->h_addr_list+=sizeof(unsigned long)-((unsigned long)(result->h_addr_list)&(sizeof(unsigned long)-1));
     367  result->h_addr_list[0]=(char*)&result->h_addr_list[2];
     368  if (inet_pton(AF_INET,name,result->h_addr_list[0])) {
     369    result->h_addrtype=AF_INET;
     370    result->h_length=4;
     371commonip:
     372    result->h_aliases=result->h_addr_list+2*sizeof(char**);
     373    result->h_aliases[0]=0;
     374    result->h_addr_list[1]=0;
     375    *RESULT=result;
     376    *h_errnop=0;
     377    return 0;
     378  } else if (inet_pton(AF_INET6,name,result->h_addr_list[0])) {
     379    result->h_addrtype=AF_INET6;
     380    result->h_length=16;
     381    goto commonip;
     382  }
     383
     384
     385  {
     386    struct hostent* r;
     387    sethostent(0);
     388    while ((r=gethostent_r(buf,buflen))) {
     389      int i;
     390      if (r->h_addrtype==AF_INET && !strcasecmp(r->h_name,name)) {  /* found it! */
     391found:
     392  memmove(result,r,sizeof(struct hostent));
     393  *RESULT=result;
     394  *h_errnop=0;
     395  endhostent();
     396  return 0;
     397      }
     398      for (i=0; i<16; ++i) {
     399  if (r->h_aliases[i]) {
     400    if (!strcasecmp(r->h_aliases[i],name)) goto found;
     401  } else break;
     402      }
     403    }
     404    endhostent();
     405  }
     406
     407  return __dns_gethostbyx_r(name,result,buf+L,buflen-L,RESULT,h_errnop,1);
     408}
     409
     410#endif
     411
  • cpukit/libnetworking/netdb.h

    re1d578d8 r068c3ee1  
    161161void            setservent(int);
    162162
     163#ifdef _THREAD_SAFE
     164struct hostent* gethostent_r(char* buf, int len);
     165int gethostbyname_r(const char*      name,
     166                    struct hostent*  result,
     167                    char            *buf,
     168                    int              buflen,
     169                    struct hostent **RESULT,
     170                    int             *h_errnop) ;
     171#endif             
     172
    163173/*
    164174 * PRIVATE functions specific to the FreeBSD implementation
Note: See TracChangeset for help on using the changeset viewer.