Ejemplo n.º 1
0
static cl_com_hostent_t* cl_com_copy_hostent(cl_com_hostent_t* hostent) {
   cl_com_hostent_t* copy = NULL;

   if (hostent == NULL) {
      return NULL;
   }

   copy = (cl_com_hostent_t*)malloc(sizeof(cl_com_hostent_t));
   if (copy != NULL) {
      copy->he = NULL;

      if (hostent->he != NULL) {
         copy->he = sge_copy_hostent(hostent->he);
         if (copy->he == NULL ) {
            CL_LOG(CL_LOG_ERROR,"could not copy hostent structure");
            free(copy);
            return NULL;
         }
      } 
   }
   return copy;
}
Ejemplo n.º 2
0
/****** uti/host/sge_gethostbyaddr() ****************************************
*  NAME
*     sge_gethostbyaddr() -- gethostbyaddr() wrapper
*
*  SYNOPSIS
*     struct hostent *sge_gethostbyaddr(const struct in_addr *addr, int* system_error_retval)
*
*  FUNCTION
*     Wraps gethostbyaddr() function calls, measures time spent
*     in gethostbyaddr() and logs when very much time has passed.
*     On error, return error code in *system_error_retval if that is non-null.
*
*     return value must be released by function caller (don't forget the 
*     char** array lists inside of struct hostent)
*
*     If possible (libcomm linked) use  cl_com_cached_gethostbyaddr() 
*     from libcomm. This will return an sge aliased hostname.
*
*
*  NOTES
*     MT-NOTE: sge_gethostbyaddr() is MT safe
*     MT-NOTE: sge_gethostbyaddr() uses a mutex to guard access to the
*     MT-NOTE: gethostbyaddr() system call on all platforms other than Solaris,
*     MT-NOTE: Linux, and HP-UX.  Therefore, except on the aforementioned
*     MT-NOTE: platforms, MT calls to gethostbyaddr() must go through
*     MT-NOTE: sge_gethostbyaddr() to be MT safe.
*******************************************************************************/
struct hostent *sge_gethostbyaddr(const struct in_addr *addr, int* system_error_retval)
{
   struct hostent *he = NULL;
   time_t now;
   time_t time;
   int l_errno;

   DENTER(TOP_LAYER, "sge_gethostbyaddr");

   /* This method goes to great lengths to slip a reentrant gethostbyaddr into
    * the code without making changes to the rest of the source base.  That
    * basically means that we have to make some redundant copies to
    * return to the caller.  This method doesn't appear to be highly utilized,
    * so that's probably ok.  If it's not ok, the interface can be changed
    * later. */

   gethostbyaddr_calls++;      /* profiling */
   now = (time_t)sge_get_gmt();

#ifdef GETHOSTBYADDR_R8
#define SGE_GETHOSTBYADDR_FOUND
   /* This is for Linux */
   DPRINTF (("Getting host by addr - Linux\n"));
   {
      struct hostent re;
      char buffer[4096];

      /* No need to malloc he because it will end up pointing to re. */
      gethostbyaddr_r ((const char *)addr, 4, AF_INET, &re, buffer, 4096, &he, &l_errno);
      
      /* Since re contains pointers into buffer, and both re and the buffer go
       * away when we exit this code block, we make a deep copy to return. */
      /* Yes, I do mean to check if he is NULL and then copy re!  No, he
       * doesn't need to be freed first. */
      if (he != NULL) {
         he = sge_copy_hostent (&re);
      }
   }
#endif
#ifdef GETHOSTBYADDR_R7
#define SGE_GETHOSTBYADDR_FOUND
   /* This is for Solaris */
   DPRINTF(("Getting host by addr - Solaris\n"));
   {
      char buffer[4096];
      struct hostent *help_he = NULL;
      he = (struct hostent *)malloc(sizeof(struct hostent));
      if (he != NULL) {
         memset(he, 0, sizeof(struct hostent));

         /* On Solaris, this function returns the pointer to my struct on success
          * and NULL on failure. */
         help_he = gethostbyaddr_r((const char *)addr, 4, AF_INET, he, buffer, 4096, &l_errno);
      
         /* Since he contains pointers into buffer, and buffer goes away when we
          * exit this code block, we make a deep copy to return. */
         if (help_he != NULL) {
            struct hostent *new_he = sge_copy_hostent(help_he);
            sge_free(&he);
            he = new_he;
         } else {
            sge_free(&he);
         }
      }
   }
#endif

#ifdef GETHOSTBYADDR_R5
#define SGE_GETHOSTBYADDR_FOUND
   /* This is for HPUX < 11 */
   DPRINTF(("Getting host by addr - 3 arg\n"));
   
   {
      struct hostent_data he_data;
     
      memset(&he_data, 0, sizeof(he_data));
      he = (struct hostent *)malloc (sizeof (struct hostent));
      if (he != NULL) {
         memset(he, 0, sizeof(struct hostent));
         if (gethostbyaddr_r ((const char *)addr, 4, AF_INET, he, &he_data) < 0) {
            /* If this function fails, free he so that we can test if it's NULL
             * later in the code. */
            sge_free(&he);
         }
         /* The location of the error code is actually undefined.  I'm just
          * assuming that it's in h_errno since that's where it is in the unsafe
          * version.
          * h_errno is, of course, not thread safe, but if there's an error we're
          * already screwed, so we won't worry to much about it.
          * An alternative would be to set errno to HOST_NOT_FOUND. */
         l_errno = h_errno;
         
         /* Since he contains pointers into he_data, and he_data goes away when we
          * exit this code block, we make a deep copy to return. */
         if (he != NULL) {
            struct hostent *new_he = sge_copy_hostent (he);
            sge_free(&he);
            he = new_he;
         }
      }
   }
#endif
#ifdef GETHOSTBYADDR
#define SGE_GETHOSTBYADDR_FOUND
   /* This is for HPUX >= 11 */
   DPRINTF(("Getting host by addr - Thread safe\n"));
   he = gethostbyaddr((const char *)addr, 4, AF_INET);
   /*
    * JG: TODO: shouldn't it be 
    * he = gethostbyaddr((const char *)addr, sizeof(struct in_addr), AF_INET);
    */

   /* The location of the error code is actually undefined.  I'm just
    * assuming that it's in h_errno since that's where it is in the unsafe
    * version.
    * h_errno is, of course, not thread safe, but if there's an error we're
    * already screwed, so we won't worry too much about it.
    * An alternative would be to set errno to HOST_NOT_FOUND. */
   l_errno = h_errno;
   if (he != NULL) {
      struct hostent *new_he = sge_copy_hostent(he);
      /* do not free he, there was no malloc() */
      he = new_he;
   }
#endif


#ifdef GETHOSTBYADDR_M
#define SGE_GETHOSTBYADDR_FOUND
   /* This is for everyone else. */
   DPRINTF (("Getting host by addr - Mutex guarded\n"));
   
   sge_mutex_lock("hostbyaddr", SGE_FUNC, __LINE__, &hostbyaddr_mutex);

   /* JG: TODO: shouldn't it always be sizeof(struct in_addr)? */
   he = gethostbyaddr((const char *)addr, 4, AF_INET);

   l_errno = h_errno;
   if (he != NULL) {
      struct hostent *new_he = sge_copy_hostent(he);
      /* do not free he, there was no malloc() */
      he = new_he;
   }
   sge_mutex_unlock("hostbyaddr", SGE_FUNC, __LINE__, &hostbyaddr_mutex);
#endif

#ifndef SGE_GETHOSTBYADDR_FOUND
#error "no sge_gethostbyaddr() definition for this architecture."
#endif
   time = (time_t)sge_get_gmt() - now;
   gethostbyaddr_sec += time;   /* profiling */

   /* warn about blocking gethostbyaddr() calls */
   if (time > MAX_RESOLVER_BLOCKING) {
      WARNING((SGE_EVENT, "gethostbyaddr() took %d seconds and returns %s", (int)time, he?"success":
          (l_errno == HOST_NOT_FOUND)?"HOST_NOT_FOUND":
          (l_errno == TRY_AGAIN)?"TRY_AGAIN":
          (l_errno == NO_RECOVERY)?"NO_RECOVERY":
          (l_errno == NO_DATA)?"NO_DATA":
          (l_errno == NO_ADDRESS)?"NO_ADDRESS":"<unknown error>"));
   }
   if (system_error_retval != NULL) {
      *system_error_retval = l_errno;
   }

   DEXIT;
   return he;
}