Back to index

courier  0.68.2
rfc1035search.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 2011 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #include      "rfc1035.h"
00007 #include      <string.h>
00008 #include      <stdlib.h>
00009 
00010 
00011 static int found(const struct rfc1035_reply *r,
00012        const struct rfc1035_rr *rrp, const char *h,
00013        unsigned qclass, unsigned qtype)
00014 {
00015 char   namebuf[RFC1035_MAXNAMESIZE+1];
00016 
00017        if ((rrp->rrtype != qtype &&
00018               rrp->rrtype != RFC1035_TYPE_CNAME) ||
00019                      rrp->rrclass != qclass)     return (0);
00020 
00021        if (rfc1035_replyhostname(r, rrp->rrname, namebuf) == 0)
00022               return (0);
00023 
00024        if (rfc1035_hostnamecmp(namebuf, h) == 0) return (1);
00025        return (0);
00026 }
00027 
00028 int rfc1035_replysearch_an(const struct rfc1035_res *res,
00029                         const struct rfc1035_reply *r, const char *h,
00030                         unsigned qtype, unsigned qclass, int pos)
00031 {
00032        if (res->rfc1035_defaultdomain && strchr(h, '.') == NULL)
00033        {
00034               char *buf;
00035               int rc;
00036 
00037               /* Append default domain */
00038 
00039               if ((buf=malloc(strlen(h)+
00040                             strlen(res->rfc1035_defaultdomain)+2)) == 0)
00041                      return (-1);
00042 
00043               strcat(strcat(strcpy(buf, h), "."),
00044                      res->rfc1035_defaultdomain);
00045 
00046               rc=rfc1035_replysearch_an(res, r, buf, qtype, qclass, pos);
00047               free(buf);
00048               return (rc);
00049        }
00050 
00051        for ( ; pos >= 0 && pos < r->ancount; pos++)
00052               if (found(r, r->anptr+pos, h, qclass, qtype))    return (pos);
00053        return (-1);
00054 }
00055 
00056 int rfc1035_replysearch_ns(const struct rfc1035_res *res,
00057                         const struct rfc1035_reply *r, const char *h,
00058                         unsigned qtype, unsigned qclass, int pos)
00059 {
00060        if (res->rfc1035_defaultdomain && strchr(h, '.') == NULL)
00061        {
00062               char *buf;
00063               int rc;
00064 
00065               /* Append default domain */
00066 
00067               if ((buf=malloc(strlen(h)+
00068                             strlen(res->rfc1035_defaultdomain)+2)) == 0)
00069                      return (-1);
00070 
00071               strcat(strcat(strcpy(buf, h), "."),
00072                      res->rfc1035_defaultdomain);
00073 
00074               rc=rfc1035_replysearch_ns(res, r, buf, qtype, qclass, pos);
00075               free(buf);
00076               return (rc);
00077        }
00078 
00079        for ( ; pos >= 0 && pos < r->nscount; pos++)
00080               if (found(r, r->nsptr+pos, h, qclass, qtype))    return (pos);
00081        return (-1);
00082 }
00083 
00084 int rfc1035_replysearch_ar(const struct rfc1035_res *res,
00085                         const struct rfc1035_reply *r, const char *h,
00086                         unsigned qtype, unsigned qclass, int pos)
00087 {
00088        if (res->rfc1035_defaultdomain && strchr(h, '.') == NULL)
00089        {
00090               char *buf;
00091               int rc;
00092 
00093               /* Append default domain */
00094 
00095               if ((buf=malloc(strlen(h)+
00096                             strlen(res->rfc1035_defaultdomain)+2)) == 0)
00097                      return (-1);
00098 
00099               strcat(strcat(strcpy(buf, h), "."),
00100                      res->rfc1035_defaultdomain);
00101 
00102               rc=rfc1035_replysearch_ar(res, r, buf, qtype, qclass, pos);
00103               free(buf);
00104               return (rc);
00105        }
00106 
00107        for ( ; pos >= 0 && pos < r->arcount; pos++)
00108               if (found(r, r->arptr+pos, h, qclass, qtype))    return (pos);
00109        return (-1);
00110 }
00111 
00112 int rfc1035_replysearch_all(const struct rfc1035_res *res,
00113                         const struct rfc1035_reply *r, const char *h,
00114                          unsigned qtype, unsigned qclass, int pos)
00115 {
00116        unsigned s;
00117 
00118        if (res->rfc1035_defaultdomain && strchr(h, '.') == NULL)
00119        {
00120               char *buf;
00121               int rc;
00122 
00123               /* Append default domain */
00124 
00125               if ((buf=malloc(strlen(h)+
00126                             strlen(res->rfc1035_defaultdomain)+2)) == 0)
00127                      return (-1);
00128 
00129               strcat(strcat(strcpy(buf, h), "."),
00130                      res->rfc1035_defaultdomain);
00131 
00132               rc=rfc1035_replysearch_all(res, r, buf, qtype, qclass, pos);
00133               free(buf);
00134               return (rc);
00135        }
00136 
00137        s=r->ancount+r->nscount+r->arcount;
00138 
00139        for ( ; pos >= 0 && pos < s; pos++)
00140               if (found(r, r->allrrs[pos], h, qclass, qtype))  return (pos);
00141        return (-1);
00142 }
00143 
00144 int rfc1035_resolve_cname(struct rfc1035_res *res, char *namebuf,
00145                        unsigned qtype,
00146                        unsigned qclass,
00147                        struct rfc1035_reply **ptr,
00148                        int x_flags)
00149 {
00150 int    n;
00151 int    recursion_count=10;
00152 
00153        if ( (*ptr=rfc1035_resolve(res, RFC1035_OPCODE_QUERY,
00154                      namebuf, qtype, qclass)) == 0)
00155               return (-1);
00156 
00157        if (x_flags && RFC1035_X_RANDOMIZE &&
00158            (*ptr)->rcode == RFC1035_RCODE_NOERROR)
00159               rfc1035_rr_rand(*ptr);
00160 
00161        if ( (*ptr)->rcode != RFC1035_RCODE_NOERROR ||
00162               (n=rfc1035_replysearch_an( res,
00163                                       *ptr, namebuf, qtype, qclass, 0))<0)
00164               return (-1);
00165 
00166        if ( (*ptr)->anptr[n].rrtype == qtype)    return (n);
00167 
00168        /* Must've gotten back a CNAME when we were looking for something else
00169        */
00170 
00171        for (;;)
00172        {
00173 
00174               if (rfc1035_replyhostname( *ptr, (*ptr)->anptr[n].rr.domainname,
00175                      namebuf) == 0)
00176               {
00177                      rfc1035_replyfree( *ptr );
00178                      *ptr=0;
00179                      return (-1);
00180               }
00181 
00182        /* Let's see if we already have the answer for the canonical name */
00183 
00184               if ( (n=rfc1035_replysearch_all( res, *ptr, namebuf, qtype,
00185                             qclass, 0)) >= 0)
00186               {
00187                      if ( (*ptr)->anptr[n].rrtype == qtype)    return (n);
00188                      if ( --recursion_count > 0)
00189                             continue;
00190 
00191                      rfc1035_replyfree( *ptr );  /* Recursive CNAME */
00192                      *ptr=0;
00193                      return (RFC1035_ERR_CNAME_RECURSIVE);
00194               }
00195 
00196               rfc1035_replyfree( *ptr );
00197               if ( (*ptr=rfc1035_resolve(res, RFC1035_OPCODE_QUERY,
00198                             namebuf, qtype, qclass)) == 0)
00199                      return (-1);
00200 
00201               if ( (*ptr)->rcode == RFC1035_RCODE_NOERROR &&
00202                      (n=rfc1035_replysearch_an( res, *ptr, namebuf,
00203                             qtype, qclass, 0)) >= 0)
00204               {
00205                      if ( (*ptr)->anptr[n].rrtype == qtype)    return (n);
00206                      if ( --recursion_count > 0)
00207                             continue;
00208                      rfc1035_replyfree( *ptr );  /* Recursive CNAME */
00209                      *ptr=0;
00210                      return (RFC1035_ERR_CNAME_RECURSIVE);
00211               }
00212               return (-1);
00213        }
00214 }