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

bind.c

/*
 *    Copyright 1988 by Rayan S. Zachariassen, all rights reserved.
 *    This will be free software, but only when it is finished.
 */
/*
 *    Lots of modifications (new guts, more or less..) by
 *    Matti Aarnio <mea@nic.funet.fi>  (copyright) 1992-2003
 */

/* LINTLIBRARY */

#include "mailer.h"
#ifdef      HAVE_RESOLVER

#define     RFC974            /* MX/WKS/A processing according to RFC974 */

#include "zresolv.h"

#include <string.h>
#include "search.h"

#include "libz.h"
#include "libc.h"
#include "libsh.h"
#include "dnsgetrr.h"


/*
 * Query a BIND standard (version 4.7 or later) nameserver.
 */



extern int D_bind, D_resolv;

char *h_errhost = NULL;

#define T_MXWKS    0x00010000
#define T_MXLOCAL  0x00020000

struct qtypes {
      const char *typename;
      int   value;
} qt[] = {
      {     "cname",    T_CNAME           },
      {     "any",            T_ANY       },
      {     "mx",       T_MX        },
      {     "mxwks",    T_MX|T_MXWKS      },
      {     "mxlocal",  T_MX|T_MXLOCAL    },
      {     "a",        T_A         },
      {     "aaaa",           T_AAAA            },
#ifdef      T_MP
      {     "mp",       T_MP        },
#endif      /* T_MP */
#ifdef      T_UNAME
      {     "uname",    T_UNAME           },
#endif      /* T_UNAME */
      {     "txt",            T_TXT       },
      {     "uinfo",    T_UINFO           },
      {     "wks",            T_WKS       },
      {     "ptr",            T_PTR       },
      {     0,          0           }
};

static const char *zh_errlist[] = {
      "Error 0",
      "unknown host/not findable at all", /* 1 - HOST_NOT_FOUND   */
      "host name lookup/try again",       /* 2 - TRY_AGAIN  */
      "unknown server/no recovery",       /* 3 - NO_RECOVERY      */
      "no address associated with name"   /* 4 - NO_ADDRESS */
};

static const char *res_respcodes[] = {
      "NOERROR",
      "FORMERR",
      "SERVFAIL",
      "NXDOMAIN",
      "NOTIMP",
      "REFUSED",
      "Resp6",
      "Resp7",
      "Resp8"
};

static conscell * getmxrr    __((const char *, time_t *, int, int));
static conscell * getcrrtype __((const char *, int, time_t *, int));
static conscell * getrrtypec __((const char *, int, time_t *, int));

extern const char * myhostname;
extern int deferit;
extern int cistrcmp __((const char *, const char *));

#if 0
void
zherror(s)
      char *s;
{
      if (h_errno >= 0 && h_errno < (sizeof zh_errlist/sizeof zh_errlist[0]))
        fprintf(stderr, "%s: resolver error: %s\n",
              s, zh_errlist[h_errno]);
      else
        fprintf(stderr, "%s: resolver error: %d\n", s, h_errno);
}
#endif

conscell *
search_res(sip)
      search_info *sip;
{
      struct qtypes *qtp;
      conscell *rval;
      const char *host;
      char        buf[BUFSIZ];

      h_errno = 0;

      if (!(_res.options & RES_INIT)) {
        if (sip->file != NULL)
          conffile = sip->file;
        if (res_init() < 0) {
          fprintf(stderr,
                "search_res: nameserver initialization failure!\n");
          die(1, "res_init failure");
        }
      }
      if (D_resolv)
        _res.options |= RES_DEBUG;
      else
        _res.options &= ~RES_DEBUG;
      /* [Edwin Allum]
       * Turn down the resolver's retry count.
       * The default (4) will cause the router to fall
       * hopelessly behind in the face of broken DNS data.
       */
      /* _res.retry   = 2; */
      /* Lets not, but lets not use DNS at router, lets use it only
         at SMTP channels */

      if (sip->subtype == NULL || *(sip->subtype) == '\0') {
        fprintf(stderr, "search_res: missing subtype to BIND query!\n");
        return NULL;
      }
      for (qtp = qt; qtp->value != 0; ++qtp)
        if (CISTREQ(qtp->typename, sip->subtype))
          break;
      if (qtp->value == 0) {
        fprintf(stderr,
              "search_res: unknown subtype '%s' to BIND query!\n",
              sip->subtype);
        return NULL;
      }
      h_errno = 0;
      if (h_errhost) free(h_errhost);
      h_errhost = NULL;
      switch (0xFF & qtp->value) {
      case T_MX:
            if (qtp->value & T_MXLOCAL)
              stashmyaddresses(myhostname); /* Need to know my local
                                       interface addresses! */
            rval = getmxrr(sip->key, &sip->ttl, 0, qtp->value);
            break;
      case T_WKS:
      case T_PTR:
      case T_A:
      case T_SA:
#ifdef      T_MP
      case T_MP:
#endif      /* T_MP */
#ifdef      T_UNAME
      case T_UNAME:
#endif      /* T_UNAME */
      case T_TXT:
      case T_UINFO:
            rval = getrrtypec(sip->key, qtp->value,
                          &sip->ttl, 0);
            break;
      case T_ANY:
      case T_CNAME:
            rval = getcrrtype(sip->key, qtp->value,
                          &sip->ttl, 0);
            break;
      default:
            rval = NULL;
      }
      if (h_errno > 0) {
        if (!h_errhost)
          host = sip->key;
        else
          host = h_errhost;

        deferit++;

        if (h_errno >= 0 &&
            h_errno < (sizeof zh_errlist/sizeof zh_errlist[0]))
          fprintf(stderr,
                "search_res: deferred: %s: %s (%s) error; errhost=%s\n",
                host, qtp->typename, zh_errlist[h_errno], h_errhost);
        else
          fprintf(stderr,
                "search_res: deferred: %s: %s (%d) error\n",
                host, qtp->typename, h_errno);

        sprintf(buf, "NS:%.500s/%.20s", host, qtp->typename);
        v_set(DEFER, buf);
      }
      return rval;
}


struct mxdata {
      char *host;
      int   pref;
      time_t      ttl;
};

static conscell *
getmxrr(host, ttlp, depth, flags)
      const char *host;
      time_t *ttlp;
      int depth;
      int flags;
{
      HEADER *hp;
      CUC *eom, *cp;
      querybuf buf, answer;
      int n, qlen, nmx, i, ancount, qdcount, maxpref;
      conscell *lhead, *l;
      struct mxdata mx[20];
      char hbuf[MAXNAME], realname[MAXNAME];
      int type;
      time_t ttl, maxttl;
      GCVARS1;

      h_errno = 0;

      nmx = 0;
      maxttl = ttl = 0;
      maxpref = -1;
      lhead = l = NULL;

      if (depth > 4) {
        fprintf(stderr,
              "search_res: CNAME chain length exceeded (%s)\n",
              host);
        h_errhost = realloc(h_errhost, strlen(host)+1);
        strcpy(h_errhost, host);
        h_errno = TRY_AGAIN;
        return NULL;
      }
      qlen = res_mkquery(QUERY, host, C_IN, T_MX, NULL, 0, NULL,
                     (void *)&buf, sizeof(buf));
      if (qlen < 0) {
            fprintf(stderr, "search_res: res_mkquery (%s) failed\n", host);
            h_errhost = realloc(h_errhost, strlen(host)+1);
            strcpy(h_errhost, host);
            h_errno = NO_RECOVERY;
            return NULL;
      }
      n = res_send((void *)&buf, qlen, (void *)&answer, sizeof(answer));
      if (n < 0) {
        /* Retry it ONCE.. */
        n = res_send((void *)&buf, qlen, (void *)&answer, sizeof(answer));
        if (n < 0) {
          if (D_bind || (_res.options & RES_DEBUG))
            fprintf(stderr,
                  "search_res: res_send (%s) failed\n", host);
          h_errhost = realloc(h_errhost, strlen(host)+1);
          strcpy(h_errhost, host);
          h_errno = TRY_AGAIN;
          return NULL;
        }
      }
      eom = (CUC *)&answer + n;
      /*
       * find first satisfactory answer
       */
      hp = (HEADER *) &answer;
      ancount = ntohs(hp->ancount);
      qdcount = ntohs(hp->qdcount);
      if (hp->rcode != NOERROR || ancount == 0) {
            if (D_bind || _res.options & RES_DEBUG)
                  fprintf(stderr,
                        "search_res: rcode = %d, ancount=%d, aa=%d\n",
                        hp->rcode, ancount, hp->aa);
            switch (hp->rcode) {
                  case NXDOMAIN:
                        h_errno = HOST_NOT_FOUND;
                        return NULL;
                  case SERVFAIL:
                        h_errhost = realloc(h_errhost, strlen(host)+1);
                        strcpy(h_errhost, host);
                        h_errno = TRY_AGAIN;
                        return NULL;
                  case NOERROR:
                        /* if we got this, then ancount == 0! */
                        h_errno = 0;
                        return NULL /*getrrtypec(host, T_A, ttlp)*/;
                  case FORMERR:
                  case NOTIMP:
                  case REFUSED:
                        h_errhost = realloc(h_errhost, strlen(host)+1);
                        strcpy(h_errhost, host);
                        h_errno = NO_RECOVERY;
                        return NULL;
            }
            return NULL;
      }
      cp = (CUC *)&answer + sizeof(HEADER);
      for (; qdcount > 0; --qdcount)
#if   defined(BIND_VER) && (BIND_VER >= 473)
            cp += dn_skipname((CUC*)cp, (CUC*)eom) + QFIXEDSZ;
#else /* !defined(BIND_VER) || (BIND_VER < 473) */
            cp += dn_skip((CUC*)cp) + QFIXEDSZ;
#endif      /* defined(BIND_VER) && (BIND_VER >= 473) */
      realname[0] = '\0';
      while (--ancount >= 0 && cp < eom && nmx < (sizeof mx/sizeof mx[0])) {
            n = dn_expand((CUC*)&answer, (CUC*)eom, (CUC*)cp,
                        (void*)hbuf, sizeof hbuf);
            if (n < 0)
                  break;
            cp += n;

            NS_GET16(type,  cp);          /* type -- short */
            cp += NS_INT16SZ;       /* class -- short */
            NS_GET32(ttl, cp);            /* ttl -- "long" */
            NS_GET16(n, cp);        /* dlen -- short */

            if (type == T_CNAME) {
                  cp += dn_expand((CUC*)&answer, (CUC*)eom, (CUC*)cp,
                              (void*)realname, sizeof realname);
                  continue;
            } else if (type != T_MX)  {
                  if (D_bind || _res.options & RES_DEBUG)
                        fprintf(stderr,
                              "search_res: bad mx query answer type %d, size %d\n",
                              type, n);
                  cp += n;
                  continue;
            }
            mx[nmx].ttl = ttl;

            NS_GET16(mx[nmx].pref, cp);   /* MX preference value */

            n = dn_expand((CUC*)&answer, (CUC*)eom, (CUC*)cp,
                        (void*)hbuf, sizeof hbuf);
            if (n < 0)
                  break;
            cp += n;
            mx[nmx].host = (char *)strdup((char*)hbuf);
            if (myhostname != NULL && CISTREQ(hbuf, myhostname)) {
                if ((maxpref < 0) || (maxpref > (int)mx[nmx].pref))
                  maxpref = mx[nmx].pref;
            } else
              if (flags & T_MXLOCAL) {
                struct addrinfo req, *ai;
                int herr = h_errno;

                memset(&req, 0, sizeof(req));
                req.ai_socktype = SOCK_STREAM;
                req.ai_protocol = IPPROTO_TCP;
                req.ai_flags    = AI_CANONNAME;
                req.ai_family   = AF_INET;
                ai = NULL;
              
#if !defined(GETADDRINFODEBUG)
                i = getaddrinfo((const char*)hbuf, "0", &req, &ai);
#else
                i = _getaddrinfo_((const char*)hbuf,"0",&req,&ai,stderr);
#endif
                if (matchmyaddresses(ai) != 0)
                  if ((maxpref < 0) || (maxpref > (int)mx[nmx].pref))
                  maxpref = mx[nmx].pref;
                if (ai)
                  freeaddrinfo(ai);
#if defined(AF_INET6) && defined(INET6)
                memset(&req, 0, sizeof(req));
                req.ai_socktype = SOCK_STREAM;
                req.ai_protocol = IPPROTO_TCP;
                req.ai_flags    = AI_CANONNAME;
                req.ai_family   = AF_INET6;
                ai = NULL;
              
#if !defined(GETADDRINFODEBUG)
                i = getaddrinfo((const char*)hbuf, "0", &req, &ai);
#else
                i = _getaddrinfo_((const char*)hbuf,"0",&req,&ai,stderr);
#endif
                if (matchmyaddresses(ai) != 0)
                  if ((maxpref < 0) || (maxpref > (int)mx[nmx].pref))
                  maxpref = mx[nmx].pref;
                if (ai)
                  freeaddrinfo(ai);
#endif /* INET6 */
                h_errno = herr;
              }
            ++nmx;
      }
      if (nmx == 0 && realname[0] != '\0' &&
          !CISTREQ(host,(char*)realname)) {
            /* do it recursively for the real name */
            return getmxrr((char *)realname, ttlp, depth+1, flags);
      } else if (nmx == 0)
            return NULL;
      /* discard MX RRs with a value >= that of localdomain */
      if (maxpref >= 0) {
            for (n = 0; n < nmx; ++n) {
                  if (((int)mx[n].pref >= maxpref) && (mx[n].host != NULL)) {
                        free((char *)mx[n].host);
                        mx[n].host = NULL;
                  }
            }
      }
#ifdef      RFC974
      /* discard MX's that do not support SMTP service */
      if (flags & T_MXWKS)
        for (n = 0; n < nmx; ++n) {
          if (mx[n].host == NULL)
            continue;
          strcpy(hbuf, mx[n].host);
          if (!getrrtypec(hbuf, T_WKS, ttlp, 0)) {
            free(mx[n].host);
            mx[n].host = NULL;
          }
        }
#endif      /* RFC974 */
      /* determine how many are left, and their max ttl */
      n = 0;
      GCPRO1(lhead);
      for (i = 0; i < nmx; ++i) {
            int slen;
            char *s;
            if (mx[i].host == NULL)
                  continue;
            ++n; /* found one! */
            if (mx[i].ttl > maxttl && mx[i].ttl < MAXVALIDTTL)
                  maxttl = ttl;
            if (D_bind || _res.options & RES_DEBUG)
                  fprintf(stderr, "search_res: %s: mx[%d] = %s [%d]\n",
                        host, n, mx[i].host, mx[i].pref);
            if (!(flags & T_MXLOCAL)) {
              slen = strlen(mx[i].host);
              s = dupnstr(mx[i].host, slen);
              if (lhead == NULL)
                lhead = l = newstring(s,slen);
              else {
                cdr(l) = newstring(s,slen);
                l = cdr(l);
              }
            }
            if (mx[i].host) free(mx[i].host);
            mx[i].host = NULL;
      }
      if (flags & T_MXLOCAL) {
        /* Did find MXes, and we were the lowest of them all... */
        if (n == 0 && nmx > 0) {
          int slen = strlen(host);
          char  *s = dupnstr(host, slen);
          lhead = newstring(s, slen);
        }
      }
      if (lhead)
            lhead = ncons(lhead);
      UNGCPRO1;

      if (D_bind || _res.options & RES_DEBUG)
            fprintf(stderr, "search_res: %s: %d valid MX%s RR's out of %d\n", host, n, (flags & T_MXLOCAL) ? "(LOCAL)":"", nmx);
      if (maxttl > 0)
            *ttlp = maxttl;
      return lhead;
}

static conscell *
getcrrtype(host, rrtype, ttlp, depth)     /* getrrtypec() with completion */
      const char *host;
      int rrtype;
      time_t *ttlp;
      int depth;
{
      conscell *rval;
      char buf[BUFSIZ];
      char *domain;
      int i;

      if (depth > 4) {
            fprintf(stderr,
                  "search_res: CNAME chain length exceeded (%s)\n",
                  host);
            h_errhost = realloc(h_errhost, strlen(host)+1);
            strcpy(h_errhost, host);      /* use strcat on purpose */
            h_errno = TRY_AGAIN;
            return NULL;
      }

      if (strchr(host, '.') != NULL) {
            rval = getrrtypec(host, rrtype, ttlp, depth+1);
            if (rval != NULL)
                  return rval;
            if (*host != '\0' && *(host+strlen(host)-1) == '.')
                  return NULL;
      }
      for (i = 0, domain = _res.dnsrch[i];
           h_errno == 0 && (domain = _res.dnsrch[i]) != NULL; ++i) {
            sprintf(buf, "%.200s.%.300s", host, domain);
            rval = getrrtypec(buf, rrtype, ttlp, depth+1);
            if (rval != NULL)
                  return rval;
      }
      h_errhost = realloc(h_errhost, strlen(host)+1);
      strcpy(h_errhost, host);
      return NULL;
}

static conscell *
getrrtypec(host, rrtype, ttlp, depth)
      const char *host;
      int rrtype;
      time_t *ttlp;
      int depth;
{
      conscell *lhead, *l;
      char *s;
      HEADER *hp;
      CUC *eom, *cp, *nextcp;
      querybuf buf, answer;
      int qlen, n, ancount, qdcount, ok, first;
      time_t maxttl, ttl;
      int type;
      char nbuf[BUFSIZ];
      char hb[MAXNAME];
      GCVARS1;

      if (depth > 4) {
            fprintf(stderr,
                  "search_res: CNAME chain length exceeded (%s)\n",
                  host);
            h_errhost = realloc(h_errhost, strlen(host)+1);
            strcpy(h_errhost, host);      /* use strcat on purpose */
            h_errno = TRY_AGAIN;
            return NULL;
      }

      qlen = res_mkquery(QUERY, host, C_IN, rrtype, NULL, 0, NULL,
                     (void *)&buf, sizeof(buf));
      if (qlen < 0) {
            if (D_bind || _res.options & RES_DEBUG)
                  fprintf(stderr,
                        "search_res: res_mkquery (%s) failed\n", host);
            h_errhost = realloc(h_errhost, strlen(host)+1);
            strcpy(h_errhost, host);
            h_errno = NO_RECOVERY;
            return NULL;
      }
      n = res_send((void *)&buf, qlen, (void *)&answer, sizeof(answer));
      if (n < 0) {
        /* Retry it ONCE.. */
        n = res_send((void*)&buf, qlen, (void *)&answer, sizeof(answer));
        if (n < 0) {
          if (D_bind || _res.options & RES_DEBUG)
            fprintf(stderr,
                  "search_res: res_send (%s) failed\n", host);
          h_errhost = realloc(h_errhost, strlen(host)+1);
          strcpy(h_errhost, host);
          h_errno = TRY_AGAIN;
          return NULL;
        }
      }
      eom = (CUC *)&answer + n;
      /*
       * find first satisfactory answer
       */
      hp = (HEADER *) &answer;
      ancount = ntohs(hp->ancount);
      qdcount = ntohs(hp->qdcount);
      /*
       * We don't care about errors here, only if we got an answer
       */
      if (ancount == 0) {
            int slen; char *s;
            if (D_bind || _res.options & RES_DEBUG)
                  fprintf(stderr,
                        "search_res: rcode=%s, ancount=%d, rrtype=%d\n",
                        res_respcodes[hp->rcode], ancount, rrtype);
            if (rrtype == T_CNAME && hp->rcode == NOERROR) {
              if (qdcount > 0 && strchr(host, '.') == NULL) {
                cp = (CUC*) &answer + sizeof(HEADER);
                if (dn_expand((CUC*)&answer, (CUC*)eom, (CUC*)cp,
                          (void*)hb, sizeof hb)>=0) {
                  if (hb[0] == '\0') {
                  hb[0] = '.'; hb[1] = '\0';
                  }
                  slen = strlen(hb);
                  s = dupnstr(hb, slen);
                  return newstring(s, slen);
                }
              }
              slen = strlen(host);
              s = dupnstr(host, slen);
              return newstring(s, slen);
            }
            if (rrtype == T_WKS) { /* absence of WKS means YES ... */
              slen = strlen(host);
              s = dupnstr(host, slen);
              return newstring(s, slen);
            }
            return NULL;
      }
      cp = (CUC *)&answer + sizeof(HEADER);
      for (; qdcount > 0; --qdcount)
#if   defined(BIND_VER) && (BIND_VER >= 473)
            cp += dn_skipname((CUC*)cp, (CUC*)eom) + QFIXEDSZ;
#else /* !defined(BIND_VER) || (BIND_VER < 473) */
            cp += dn_skip((CUC*)cp) + QFIXEDSZ;
#endif      /* defined(BIND_VER) && (BIND_VER >= 473) */
      first = 1;
      ok = rrtype != T_WKS;
      maxttl = 0;
      l = NULL;
      lhead = NULL;
      GCPRO1(lhead);
      for (; --ancount >= 0 && cp < eom; cp = nextcp) {
            n = dn_expand((CUC*)&answer, (CUC*)eom, (CUC*)cp,
                        (void*)nbuf, sizeof(nbuf));
            if (n < 0)
                  break;
            if (first) {
                  if (strlen(nbuf) < sizeof hb)
                        strcpy(hb, nbuf);
                  else {
                        strncpy(hb, nbuf, sizeof hb);
                        hb[(sizeof hb) - 1] = '\0';
                  }
                  first = 0;
            }
            cp += n;

            NS_GET16(type,  cp);    /* type  -- short */
            cp += NS_INT16SZ; /* class -- short */
            NS_GET32(ttl, cp);      /* ttl -- "long" */
            NS_GET16(n,   cp);      /* dlen -- short */

            nextcp = cp + n;

            if (rrtype != T_ANY && type != rrtype)
                  continue;
            /*
             * Assume that only one rrtype will be found.  More
             * than one is undefined. T_ANY is a bit special..
             */

            if (ttl > maxttl && ttl < MAXVALIDTTL)
                  maxttl = ttl;
            switch (type) {
            case T_TXT:
            case T_UINFO:
#ifdef      T_UNAME
            case T_UNAME:
#endif      /* T_UNAME */
#ifdef      T_MP
            case T_MP:
#endif      /* T_MP */
                  if (rrtype == T_ANY)
                        continue;   /* Not our time.. */

                  *ttlp = maxttl;
                  n = (*cp) & 0xFF;
                  if (0 < n && n < (int)sizeof(hb)) {
                    int slen; char *s;
                    UNGCPRO1;
                    *(char*)(cp+1+n) = 0;
                    slen = strlen((const char *)(cp+1));
                    s = dupnstr((const char *)(cp+1), slen);
                    return newstring(s, slen);
                  }
                  break;

            case T_WKS:
                  /*
                   * If we have seen a WKS, it had better have SMTP,
                   * however in absence of a WKS, assume SMTP.
                   */
                  if (rrtype != T_WKS)    /* Take it only if it was */
                    continue;       /* explicitely asked for! */

                  if (n < (4/*"long"*/ + 1))
                        continue;
                  ok = 0;
                  cp += 4;          /* skip IP address */
                  if (*cp++ == IPPROTO_TCP) {   /* check protocol */
                    if (cp + (IPPORT_SMTP/8) < nextcp &&
                        *(cp+(IPPORT_SMTP/8)) & (0x80>>IPPORT_SMTP%8)) {
                      int slen = strlen(hb);
                      char *s = dupnstr(hb, slen);
                      *ttlp = maxttl;
                      UNGCPRO1;
                      return newstring(s, slen);
                    }
                  }
                  continue;
            case T_A:
            case T_SA:
            case T_AAAA:
                  *ttlp = maxttl;
                  if (rrtype == T_ANY) {
                    int slen = strlen(host);
                    char *s = dupnstr(host, slen);
                    UNGCPRO1;
                    return newstring(s, slen);
                  } else {
                    char tb[80];
                    const char *ss;
                    int slen;

#if defined(AF_INET6) && defined(INET6)
                    if (type == T_AAAA)
                      ss = inet_ntop(AF_INET6, cp, tb, sizeof(tb));
                    else
#endif
                      ss = inet_ntop(AF_INET, cp, tb, sizeof(tb));
                    slen = strlen(ss);
                    s = dupnstr(ss, slen);
                    if (lhead == NULL)
                      lhead = l = newstring(s, slen);
                    else {
                      cdr(l) = newstring(s, slen);
                      l = cdr(l);
                    }
                  }
                  continue;

            case T_CNAME:
            case T_PTR:
                  if (rrtype == T_ANY && type == T_PTR)
                        /* if asking for something particular,
                           don't yield wrong data. Asking
                           "ANY sara.nl"  yielded following:
                              NS ...
                              NS ...
                              ...
                              MX ...
                              MX ...
                              ...
                              PTR ...
                              PTR ...
                              ...
                              SOA ...
                           which really caused headaches, when
                           the PTR data was taken in as CNAME.. */
                        continue;

                  n = dn_expand((CUC*)&answer, (CUC*)eom, (CUC*)cp,
                              (void*)nbuf, sizeof(nbuf));
                  if (n < 0)
                        break;

                  if (type == T_CNAME && rrtype != T_ANY &&
                      !CISTREQ(nbuf, host))
                        /* chase it down */
                        getrrtypec(nbuf, rrtype, ttlp, depth+1);
                  *ttlp = maxttl;
                  UNGCPRO1;
                  {
                    int slen = strlen(nbuf);
                    char *s = dupnstr(nbuf, slen);
                    return newstring(s, slen);
                  }

            case T_SOA:
            case T_NS:
            case T_RP:
            case T_AFSDB:
            case T_X25:
            case T_ISDN:
            case T_RT:
            case T_NSAP:
            case T_NSAP_PTR:
            case T_HINFO:
            case T_UID:
            case T_GID:
            case T_UNSPEC:
                  continue; /* Just forget it */

            case T_MX:
                  if (rrtype == T_ANY) {
                    int slen = strlen(host);
                    char *s = dupnstr(host, slen);
                    UNGCPRO1;
                    return newstring(s, slen);
                  }
            default:
                  fprintf(stderr,"search_res: getrrtypec: non-processed RR type for host='%s' query=%d, result=%d\n",host,rrtype,type);

                  break;
            }
      }
      if (lhead)
            lhead = ncons(lhead);
      UNGCPRO1;
      if (lhead)
            return lhead;
      if (ok) {
            const char *cs = first ? host : hb;
            int slen = strlen(cs);
            char *s = dupnstr(cs, slen);
            *ttlp = maxttl;
            return newstring(s, slen);
      }
      return NULL;
}
#endif      /* HAVE_RESOLVER */

Generated by  Doxygen 1.6.0   Back to index