Logo Search packages:      
Sourcecode: lfc version File versions  Download package

send2nsd.c

/*
 * Copyright (C) 1993-2008 by CERN/IT/PDP/DM
 * All rights reserved
 */

#ifndef lint
static char sccsid[] = "@(#)$RCSfile: send2nsd.c,v $ $Revision: 1.21 $ $Date: 2009/01/11 00:43:26 $ CERN IT-PDP/DM Jean-Philippe Baud";
#endif /* not lint */

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#if defined(_WIN32)
#include <winsock2.h>
#else
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#endif
#include "Cnetdb.h"
#include "Cns.h"
#include "Cns_api.h"
#ifdef CSEC
#include "Csec_api.h"
#endif
#include "marshall.h"
#include "net.h"
#include "serrno.h"

/* send2nsd - send a request to the name server and wait for the reply */

send2nsdx(socketp, host, reqp, reql, user_repbuf, user_repbuf_len, repbuf2, nbstruct)
int *socketp;
char *host;
char *reqp;
int reql;
char *user_repbuf;
int user_repbuf_len;
void **repbuf2;
int *nbstruct;
{
      int abortconnect;
      int actual_replen = 0;
      struct addrinfo *ai;
      struct addrinfo *aitop;
      int alloced = 0;
      int c;
      char Cnshost[CA_MAXHOSTNAMELEN+1];
#ifdef CSEC
      Csec_context_t ctx;
#endif
      int errflag = 0;
      char func[16];
      char *getconfent();
      char *getenv();
      char groupname[256];
      struct Cns_filestatus *lf;
      char **lg = NULL;
      struct Cns_groupinfo *lgi;
      struct Cns_linkinfo *li;
      struct Cns_filereplica *lp;
#if defined(NSTYPE_LFC)
      struct Cns_filereplicas *lr;
#endif
      int gaierrno;
      struct addrinfo hints;
      int isconnected;
      int *ls;
      struct Cns_userinfo *lui;
      struct Cns_filereplicax *lx;
      int magic;
      int n;
      int nbretry;
      char *neterrstr = NULL;
      char *p;
      char prtbuf[PRTBUFSZ];
      char *q;
      struct Cns_rep_info *ri;
      int rep_type;
      char repbuf[REPBUFSZ];
      int repbuf2sz;
      int retrycnt = 0;
      int retryint;
      int s;
      int save_serrno;
      char se[CA_MAXHOSTNAMELEN+1];
      char sfn[CA_MAXSFNLEN+1];
      char strport[NI_MAXSERV];
      struct Cns_api_thread_info *thip = NULL;
      int timeout;

      strcpy (func, "send2nsd");
      if (socketp && *socketp >= 0) {     /* connection opened by Cns_list... */
            s = *socketp;
      } else if (socketp == NULL && Cns_apiinit (&thip) == 0 && thip->fd >= 0) {
            s = thip->fd;           /* connection opened by Cns_starttrans */
      } else {                /* connection not yet opened */
            if (host && *host)
                  strcpy (Cnshost, host);
            else if ((p = getenv (CNS_HOST_ENV)) || (p = getconfent (CNS_SCE, "HOST", 0)))
                  strcpy (Cnshost, p);
            else {
#if defined(CNS_HOST)
                  strcpy (Cnshost, CNS_HOST);
#else
                  gethostname (Cnshost, sizeof(Cnshost));
#endif
                  serrno = 0;
            }

            if ((p = strrchr (Cnshost, ':'))) {
                  char *p2 = strchr (Cnshost, ':');
                  if (p2 != p && !memchr (p2+1, ']', p-p2-1)) {
                        p = NULL;
                  }
            }
            if (p) {
                  *p = '\0';
                  strncpy (strport, p+1, sizeof(strport));
                  strport[sizeof(strport)-1] = '\0';
            } else {
                  if ((p = getenv (CNS_PORT_ENV)) || (p = getconfent (CNS_SCE, "PORT", 0))) {
                        strncpy (strport, p, sizeof(strport));
                        strport[sizeof(strport)-1] = '\0';
                  } else {
                        snprintf (strport, sizeof(strport), "%u", CNS_PORT);
                        serrno = 0;
                  }
            }

            memset (&hints, 0, sizeof(struct addrinfo));
            hints.ai_family = PF_UNSPEC;
            hints.ai_socktype = SOCK_STREAM;
#ifdef AI_ADDRCONFIG
            hints.ai_flags |= AI_ADDRCONFIG;
#endif

            gaierrno = Cgetaddrinfo (Cnshost, strport, &hints, &aitop);

            if (gaierrno !=0 && serrno == 0)
                  serrno = SENOSHOST;

            if (gaierrno == EAI_NONAME) {
                  Cns_errmsg (func, NS009, "Host unknown:", Cnshost);
                  return (-1);
            } else if (gaierrno != 0) {
                  Cns_errmsg (func, "Error during lookup of %s: %s\n", Cnshost, Cgai_strerror (gaierrno));
                  return (-1);
            }

            /* get retry environment variables */
            if ((p = getenv (CNS_CONNTIMEOUT_ENV)) == NULL) {
                  timeout = DEFAULT_CONNTIMEOUT;
            } else {
                  timeout = atoi (p);
            }

            if ((p = getenv (CNS_CONRETRY_ENV)) == NULL) {
                  nbretry = DEFAULT_RETRYCNT;
            } else {
                  nbretry = atoi(p);
            }

            if ((p = getenv (CNS_CONRETRYINT_ENV)) == NULL) {
                  retryint = RETRYI;
            } else {
                  retryint = atoi(p);
            }

            isconnected = 0;
            abortconnect = 0;
            save_serrno = 0;
            /* retry as much as the user wishes */
              while (retrycnt <= nbretry && !isconnected && !abortconnect) {

                  if (retrycnt>0)
                        sleep (retryint);
                  ++retrycnt;

                  if (neterrstr) {
                        free (neterrstr);
                        neterrstr = NULL;
                  }

                  for (ai = aitop; ai && !isconnected; ai = ai->ai_next) {
                        if (ai->ai_family != PF_INET && ai->ai_family != PF_INET6)
                              continue;
                        if ((s = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol))<0) {
                              continue;
                        }

                        if (netconnect_timeout (s, ai->ai_addr, ai->ai_addrlen,
                              timeout) < 0) {

#if defined(_WIN32)
                              if (WSAGetLastError() == WSAEAFNOSUPPORT) {
#else
                              if (serrno == 0 && errno == EAFNOSUPPORT) {
#endif
                                    (void) netclose (s);
                                    continue;
                              }

                              save_serrno = serrno;
                              p = neterror ();
                              if (neterrstr)
                                    free (neterrstr);
                              neterrstr = strdup (p);
                              
                              if(save_serrno != SETIMEDOUT) {
#if defined(_WIN32)
                                    if (WSAGetLastError() == WSAECONNREFUSED) {
#else
                                    if (save_serrno == ECONNREFUSED) {
#endif
                                          save_serrno = ENSNACT;
                                    } else {
                                          save_serrno = SECOMERR;
                                    }
                              }
                              (void) netclose (s);
                        } else {
                              isconnected = 1;

                        }
                  }

                  if (!isconnected)
                        continue;

                  if (neterrstr) {
                        free (neterrstr);
                        neterrstr = NULL;
                  }
#ifdef CSEC
                  Csec_client_initContext (&ctx, CSEC_SERVICE_TYPE_HOST, NULL);
                  if (Cns_apiinit (&thip) == 0 && thip->use_authorization_id &&
                      *thip->Csec_mech && *thip->Csec_auth_id) {
                        Csec_client_setAuthorizationId (&ctx, thip->Csec_mech,
                            thip->Csec_auth_id);
                        if (thip->voname && thip->fqan)
                              Csec_client_setVOMS_data (&ctx,
                                  thip->voname, thip->fqan, thip->nbfqan);
                  }

                  if (Csec_client_establishContext (&ctx, s) == 0)
                        break;

                  save_serrno = serrno ? serrno : errno;
                  isconnected = 0;
                  switch (save_serrno) {
                        case SETIMEDOUT:
                              Cns_errmsg (func, NS002, "send", "Operation timed out");
                              break;
                        default:
                              Cns_errmsg (func, NS002, "send", Csec_getErrorMessageSummary (PRTBUFSZ-48));
                              abortconnect = 1;
                              break;
                  }

                  (void) netclose (s);
                  Csec_clearContext (&ctx);
#endif
            }

            freeaddrinfo (aitop);
            if (!isconnected) {
                  serrno = (save_serrno) ? save_serrno : SECOMERR;
                  if (!abortconnect) {
                        switch(serrno) {
                              case ENSNACT:
                                    Cns_errmsg (func, NS000, Cnshost);
                                    break;
                              default:
                                    if (neterrstr) {
                                          Cns_errmsg (func, NS002,
                                                "connect", neterrstr);
                                    } else {
                                          Cns_errmsg (func, "Could not create "
                                                      "an outgoing connection\n");
                                    }
                                    break;
                        }
                  }
                  if (neterrstr)
                        free (neterrstr);
                  return (-1);
            }
            if (neterrstr) {
                  free (neterrstr);
                  neterrstr = NULL;
            }
#ifdef CSEC
            Csec_clearContext (&ctx);
#endif
            if (socketp)
                  *socketp = s;
      }

      /* send request to name server */

      if ((n = netwrite (s, reqp, reql)) <= 0) {
            if (n == 0)
                  Cns_errmsg (func, NS002, "send", sys_serrlist[SERRNO]);
            else
                  Cns_errmsg (func, NS002, "send", neterror());
            (void) netclose (s);
            serrno = SECOMERR;
            return (-1);
      }

      /* get reply */

      while (1) {
            if ((n = netread (s, repbuf, 3 * LONGSIZE)) <= 0) {
                  if (n == 0)
                        Cns_errmsg (func, NS002, "recv", sys_serrlist[SERRNO]);
                  else
                        Cns_errmsg (func, NS002, "recv", neterror());
                  (void) netclose (s);
                  serrno = SECOMERR;
                  return (-1);
            }
            p = repbuf;
            unmarshall_LONG (p, magic) ;
            unmarshall_LONG (p, rep_type) ;
            unmarshall_LONG (p, c) ;
            if (rep_type == CNS_RC) {
                  (void) netclose (s);
                  if (thip && s == thip->fd)
                        thip->fd = -1;
            }
            if (rep_type == CNS_RC || rep_type == CNS_IRC) {
                  if (c) {
                        serrno = c;
                        c = -1;
                  }
                  break;
            }
            if (c > REPBUFSZ) {
                  Cns_errmsg (func, "reply too large\n");
                  serrno = SEINTERNAL;
                  return (-1);
            }
            if ((n = netread (s, repbuf, c)) <= 0) {
                  if (n == 0)
                        Cns_errmsg (func, NS002, "recv", sys_serrlist[SERRNO]);
                  else
                        Cns_errmsg (func, NS002, "recv", neterror());
                  (void) netclose (s);
                  serrno = SECOMERR;
                  return (-1);
            }
            p = repbuf;
            if (rep_type == MSG_ERR) {
                  unmarshall_STRING (p, prtbuf);
                  Cns_errmsg (NULL, "%s", prtbuf);
            } else if (rep_type == MSG_LINKS) {
                  if (errflag) continue;
                  if (alloced == 0) {
                        repbuf2sz = 4096;
                        if ((*repbuf2 = malloc (repbuf2sz)) == NULL) {
                              errflag++;
                              continue;
                        }
                        alloced = 1;
                        *nbstruct = 0;
                        li = (struct Cns_linkinfo *) *repbuf2;
                  }
                  while (p < repbuf + c) {
                        if ((char *)li - (char *)(*repbuf2) +
                            sizeof(struct Cns_linkinfo) > repbuf2sz) {
                              repbuf2sz += 4096;
                              if ((q = realloc (*repbuf2, repbuf2sz)) == NULL) {
                                    errflag++;
                                    break;
                              }
                              *repbuf2 = q;
                              li = ((struct Cns_linkinfo *) *repbuf2) + *nbstruct;
                        }
                        unmarshall_STRING (p, li->path);
                        (*nbstruct)++;
                        li++;
                  }
            } else if (rep_type == MSG_REPLIC) {
                  if (errflag) continue;
                  if (alloced == 0) {
                        repbuf2sz = 4096;
                        if ((*repbuf2 = malloc (repbuf2sz)) == NULL) {
                              errflag++;
                              continue;
                        }
                        alloced = 1;
                        *nbstruct = 0;
                        lp = (struct Cns_filereplica *) *repbuf2;
                  }
                  while (p < repbuf + c) {
                        if ((char *)lp - (char *)(*repbuf2) +
                            sizeof(struct Cns_filereplica) > repbuf2sz) {
                              repbuf2sz += 4096;
                              if ((q = realloc (*repbuf2, repbuf2sz)) == NULL) {
                                    errflag++;
                                    break;
                              }
                              *repbuf2 = q;
                              lp = ((struct Cns_filereplica *) *repbuf2) + *nbstruct;
                        }
                        unmarshall_HYPER (p, lp->fileid);
                        unmarshall_HYPER (p, lp->nbaccesses);
                        unmarshall_TIME_T (p, lp->atime);
                        unmarshall_TIME_T (p, lp->ptime);
                        unmarshall_BYTE (p, lp->status);
                        unmarshall_BYTE (p, lp->f_type);
                        unmarshall_STRING (p, lp->poolname);
                        unmarshall_STRING (p, lp->host);
                        unmarshall_STRING (p, lp->fs);
                        unmarshall_STRING (p, lp->sfn);
                        (*nbstruct)++;
                        lp++;
                  }
            } else if (rep_type == MSG_REPLICP) {
                  if (errflag) continue;
                  if (alloced == 0) {
                        repbuf2sz = 4096;
                        if ((*repbuf2 = malloc (repbuf2sz)) == NULL) {
                              errflag++;
                              continue;
                        }
                        alloced = 1;
                        *nbstruct = 0;
                        ri = (struct Cns_rep_info *) *repbuf2;
                  }
                  while (p < repbuf + c) {
                        if ((char *)ri - (char *)(*repbuf2) +
                            sizeof(struct Cns_rep_info) > repbuf2sz) {
                              repbuf2sz += 4096;
                              if ((q = realloc (*repbuf2, repbuf2sz)) == NULL) {
                                    errflag++;
                                    break;
                              }
                              *repbuf2 = q;
                              ri = ((struct Cns_rep_info *) *repbuf2) + *nbstruct;
                        }
                        unmarshall_HYPER (p, ri->fileid);
                        unmarshall_BYTE (p, ri->status);
                        unmarshall_STRING (p, se);
                        if ((ri->host = strdup (se)) == NULL) {
                              errflag++;
                              break;
                        }
                        unmarshall_STRING (p, sfn);
                        if ((ri->sfn = strdup (sfn)) == NULL) {
                              errflag++;
                              break;
                        }
                        (*nbstruct)++;
                        ri++;
                  }
            } else if (rep_type == MSG_REPLICX) {
                  if (errflag) continue;
                  if (alloced == 0) {
                        repbuf2sz = 4096;
                        if ((*repbuf2 = malloc (repbuf2sz)) == NULL) {
                              errflag++;
                              continue;
                        }
                        alloced = 1;
                        *nbstruct = 0;
                        lx = (struct Cns_filereplicax *) *repbuf2;
                  }
                  while (p < repbuf + c) {
                        if ((char *)lx - (char *)(*repbuf2) +
                            sizeof(struct Cns_filereplicax) > repbuf2sz) {
                              repbuf2sz += 4096;
                              if ((q = realloc (*repbuf2, repbuf2sz)) == NULL) {
                                    errflag++;
                                    break;
                              }
                              *repbuf2 = q;
                              lx = ((struct Cns_filereplicax *) *repbuf2) + *nbstruct;
                        }
                        unmarshall_HYPER (p, lx->fileid);
                        unmarshall_HYPER (p, lx->nbaccesses);
                        unmarshall_TIME_T (p, lx->ctime);
                        unmarshall_TIME_T (p, lx->atime);
                        unmarshall_TIME_T (p, lx->ptime);
                        unmarshall_TIME_T (p, lx->ltime);
                        unmarshall_BYTE (p, lx->r_type);
                        unmarshall_BYTE (p, lx->status);
                        unmarshall_BYTE (p, lx->f_type);
                        unmarshall_STRING (p, lx->setname);
                        unmarshall_STRING (p, lx->poolname);
                        unmarshall_STRING (p, lx->host);
                        unmarshall_STRING (p, lx->fs);
                        unmarshall_STRING (p, lx->sfn);
                        (*nbstruct)++;
                        lx++;
                  }
#if defined(NSTYPE_LFC)
            } else if (rep_type == MSG_REPLICS) {
                  if (errflag) continue;
                  if (alloced == 0) {
                        repbuf2sz = 4096;
                        if ((*repbuf2 = malloc (repbuf2sz)) == NULL) {
                              errflag++;
                              continue;
                        }
                        alloced = 1;
                        *nbstruct = 0;
                        lr = (struct Cns_filereplicas *) *repbuf2;
                  }
                  while (p < repbuf + c) {
                        if ((char *)lr - (char *)(*repbuf2) +
                            sizeof(struct Cns_filereplicas) > repbuf2sz) {
                              repbuf2sz += 4096;
                              if ((q = realloc (*repbuf2, repbuf2sz)) == NULL) {
                                    errflag++;
                                    break;
                              }
                              *repbuf2 = q;
                              lr = ((struct Cns_filereplicas *) *repbuf2) + *nbstruct;
                        }
                        unmarshall_STRING (p, lr->guid);
                        unmarshall_LONG (p, lr->errcode);
                        unmarshall_HYPER (p, lr->filesize);
                        unmarshall_TIME_T (p, lr->ctime);
                        unmarshall_STRING (p, lr->csumtype);
                        unmarshall_STRING (p, lr->csumvalue);
                        unmarshall_TIME_T (p, lr->r_ctime);
                        unmarshall_TIME_T (p, lr->r_atime);
                        unmarshall_STRING (p, lr->sfn);
                        (*nbstruct)++;
                        lr++;
                  }
#endif
            } else if (rep_type == MSG_GROUPS) {
                  if (errflag) continue;
                  if (! lg)
                        lg = (char **) repbuf2;
                  while (p < repbuf + c) {
                        unmarshall_STRING (p, groupname);
                        if ((*lg = strdup (groupname)) == NULL) {
                              errflag++;
                              break;
                        }
                        lg++;
                  }
            } else if (rep_type == MSG_STATUSES) {
                  if (errflag) continue;
                  if (alloced == 0) {
                        repbuf2sz = 4096;
                        if ((*repbuf2 = malloc (repbuf2sz)) == NULL) {
                              errflag++;
                              continue;
                        }
                        alloced = 1;
                        *nbstruct = 0;
                        ls = (int *) *repbuf2;
                  }
                  while (p < repbuf + c) {
                        if ((char *)ls - (char *)(*repbuf2) +
                            sizeof(int) > repbuf2sz) {
                              repbuf2sz += 4096;
                              if ((q = realloc (*repbuf2, repbuf2sz)) == NULL) {
                                    errflag++;
                                    break;
                              }
                              *repbuf2 = q;
                              ls = ((int *) *repbuf2) + *nbstruct;
                        }
                        unmarshall_LONG (p, *ls);
                        (*nbstruct)++;
                        ls++;
                  }
#if defined(NSTYPE_LFC)
            } else if (rep_type == MSG_FILEST) {
                  if (errflag) continue;
                  if (alloced == 0) {
                        repbuf2sz = 4096;
                        if ((*repbuf2 = malloc (repbuf2sz)) == NULL) {
                              errflag++;
                              continue;
                        }
                        alloced = 1;
                        *nbstruct = 0;
                        lf = (struct Cns_filestatus *) *repbuf2;
                  }
                  while (p < repbuf + c) {
                        if ((char *)lf - (char *)(*repbuf2) +
                            sizeof(struct Cns_filestatus) > repbuf2sz) {
                              repbuf2sz += 4096;
                              if ((q = realloc (*repbuf2, repbuf2sz)) == NULL) {
                                    errflag++;
                                    break;
                              }
                              *repbuf2 = q;
                              lf = ((struct Cns_filestatus *) *repbuf2) + *nbstruct;
                        }
                        unmarshall_STRING (p, lf->name);
                        unmarshall_LONG (p, lf->errcode);
                        (*nbstruct)++;
                        lf++;
                  }
#endif
            } else if (rep_type == MSG_GRPINFO) {
                  if (errflag) continue;
                  if (alloced == 0) {
                        repbuf2sz = 4096;
                        if ((*repbuf2 = malloc (repbuf2sz)) == NULL) {
                              errflag++;
                              continue;
                        }
                        alloced = 1;
                        *nbstruct = 0;
                        lgi = (struct Cns_groupinfo *) *repbuf2;
                  }
                  while (p < repbuf + c) {
                        if ((char *)lgi - (char *)(*repbuf2) +
                            sizeof(struct Cns_groupinfo) > repbuf2sz) {
                              repbuf2sz += 4096;
                              if ((q = realloc (*repbuf2, repbuf2sz)) == NULL) {
                                    errflag++;
                                    break;
                              }
                              *repbuf2 = q;
                              lgi = ((struct Cns_groupinfo *) *repbuf2) + *nbstruct;
                        }
                        unmarshall_LONG (p, lgi->gid);
                        unmarshall_STRING (p, lgi->groupname);
                        (*nbstruct)++;
                        lgi++;
                  }
            } else if (rep_type == MSG_USRINFO) {
                  if (errflag) continue;
                  if (alloced == 0) {
                        repbuf2sz = 4096;
                        if ((*repbuf2 = malloc (repbuf2sz)) == NULL) {
                              errflag++;
                              continue;
                        }
                        alloced = 1;
                        *nbstruct = 0;
                        lui = (struct Cns_userinfo *) *repbuf2;
                  }
                  while (p < repbuf + c) {
                        if ((char *)lui - (char *)(*repbuf2) +
                            sizeof(struct Cns_userinfo) > repbuf2sz) {
                              repbuf2sz += 4096;
                              if ((q = realloc (*repbuf2, repbuf2sz)) == NULL) {
                                    errflag++;
                                    break;
                              }
                              *repbuf2 = q;
                              lui = ((struct Cns_userinfo *) *repbuf2) + *nbstruct;
                        }
                        unmarshall_LONG (p, lui->userid);
                        unmarshall_STRING (p, lui->username);
                        (*nbstruct)++;
                        lui++;
                  }
            } else if (user_repbuf) {
                  if (actual_replen + c <= user_repbuf_len)
                        n = c;
                  else
                        n = user_repbuf_len - actual_replen;
                  if (n) {
                        memcpy (user_repbuf + actual_replen, repbuf, n);
                        actual_replen += n;
                  }
            }
      }
      return (c);
}

send2nsd(socketp, host, reqp, reql, user_repbuf, user_repbuf_len)
int *socketp;
char *host;
char *reqp;
int reql;
char *user_repbuf;
int user_repbuf_len;
{
      return (send2nsdx (socketp, host, reqp, reql, user_repbuf, user_repbuf_len,
          NULL, NULL));
}

Generated by  Doxygen 1.6.0   Back to index