summaryrefslogtreecommitdiffstats
path: root/rfc1035/rfc1035search.c
diff options
context:
space:
mode:
authorSam Varshavchik2013-08-19 16:39:41 -0400
committerSam Varshavchik2013-08-25 14:43:51 -0400
commit9c45d9ad13fdf439d44d7443ae75da15ea0223ed (patch)
tree7a81a04cb51efb078ee350859a64be2ebc6b8813 /rfc1035/rfc1035search.c
parenta9520698b770168d1f33d6301463bb70a19655ec (diff)
downloadcourier-libs-9c45d9ad13fdf439d44d7443ae75da15ea0223ed.tar.bz2
Initial checkin
Imported from subversion report, converted to git. Updated all paths in scripts and makefiles, reflecting the new directory hierarchy.
Diffstat (limited to 'rfc1035/rfc1035search.c')
-rw-r--r--rfc1035/rfc1035search.c214
1 files changed, 214 insertions, 0 deletions
diff --git a/rfc1035/rfc1035search.c b/rfc1035/rfc1035search.c
new file mode 100644
index 0000000..8e69ad4
--- /dev/null
+++ b/rfc1035/rfc1035search.c
@@ -0,0 +1,214 @@
+/*
+** Copyright 1998 - 2011 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#include "rfc1035.h"
+#include <string.h>
+#include <stdlib.h>
+
+
+static int found(const struct rfc1035_reply *r,
+ const struct rfc1035_rr *rrp, const char *h,
+ unsigned qclass, unsigned qtype)
+{
+char namebuf[RFC1035_MAXNAMESIZE+1];
+
+ if ((rrp->rrtype != qtype &&
+ rrp->rrtype != RFC1035_TYPE_CNAME) ||
+ rrp->rrclass != qclass) return (0);
+
+ if (rfc1035_replyhostname(r, rrp->rrname, namebuf) == 0)
+ return (0);
+
+ if (rfc1035_hostnamecmp(namebuf, h) == 0) return (1);
+ return (0);
+}
+
+int rfc1035_replysearch_an(const struct rfc1035_res *res,
+ const struct rfc1035_reply *r, const char *h,
+ unsigned qtype, unsigned qclass, int pos)
+{
+ if (res->rfc1035_defaultdomain && strchr(h, '.') == NULL)
+ {
+ char *buf;
+ int rc;
+
+ /* Append default domain */
+
+ if ((buf=malloc(strlen(h)+
+ strlen(res->rfc1035_defaultdomain)+2)) == 0)
+ return (-1);
+
+ strcat(strcat(strcpy(buf, h), "."),
+ res->rfc1035_defaultdomain);
+
+ rc=rfc1035_replysearch_an(res, r, buf, qtype, qclass, pos);
+ free(buf);
+ return (rc);
+ }
+
+ for ( ; pos >= 0 && pos < r->ancount; pos++)
+ if (found(r, r->anptr+pos, h, qclass, qtype)) return (pos);
+ return (-1);
+}
+
+int rfc1035_replysearch_ns(const struct rfc1035_res *res,
+ const struct rfc1035_reply *r, const char *h,
+ unsigned qtype, unsigned qclass, int pos)
+{
+ if (res->rfc1035_defaultdomain && strchr(h, '.') == NULL)
+ {
+ char *buf;
+ int rc;
+
+ /* Append default domain */
+
+ if ((buf=malloc(strlen(h)+
+ strlen(res->rfc1035_defaultdomain)+2)) == 0)
+ return (-1);
+
+ strcat(strcat(strcpy(buf, h), "."),
+ res->rfc1035_defaultdomain);
+
+ rc=rfc1035_replysearch_ns(res, r, buf, qtype, qclass, pos);
+ free(buf);
+ return (rc);
+ }
+
+ for ( ; pos >= 0 && pos < r->nscount; pos++)
+ if (found(r, r->nsptr+pos, h, qclass, qtype)) return (pos);
+ return (-1);
+}
+
+int rfc1035_replysearch_ar(const struct rfc1035_res *res,
+ const struct rfc1035_reply *r, const char *h,
+ unsigned qtype, unsigned qclass, int pos)
+{
+ if (res->rfc1035_defaultdomain && strchr(h, '.') == NULL)
+ {
+ char *buf;
+ int rc;
+
+ /* Append default domain */
+
+ if ((buf=malloc(strlen(h)+
+ strlen(res->rfc1035_defaultdomain)+2)) == 0)
+ return (-1);
+
+ strcat(strcat(strcpy(buf, h), "."),
+ res->rfc1035_defaultdomain);
+
+ rc=rfc1035_replysearch_ar(res, r, buf, qtype, qclass, pos);
+ free(buf);
+ return (rc);
+ }
+
+ for ( ; pos >= 0 && pos < r->arcount; pos++)
+ if (found(r, r->arptr+pos, h, qclass, qtype)) return (pos);
+ return (-1);
+}
+
+int rfc1035_replysearch_all(const struct rfc1035_res *res,
+ const struct rfc1035_reply *r, const char *h,
+ unsigned qtype, unsigned qclass, int pos)
+{
+ unsigned s;
+
+ if (res->rfc1035_defaultdomain && strchr(h, '.') == NULL)
+ {
+ char *buf;
+ int rc;
+
+ /* Append default domain */
+
+ if ((buf=malloc(strlen(h)+
+ strlen(res->rfc1035_defaultdomain)+2)) == 0)
+ return (-1);
+
+ strcat(strcat(strcpy(buf, h), "."),
+ res->rfc1035_defaultdomain);
+
+ rc=rfc1035_replysearch_all(res, r, buf, qtype, qclass, pos);
+ free(buf);
+ return (rc);
+ }
+
+ s=r->ancount+r->nscount+r->arcount;
+
+ for ( ; pos >= 0 && pos < s; pos++)
+ if (found(r, r->allrrs[pos], h, qclass, qtype)) return (pos);
+ return (-1);
+}
+
+int rfc1035_resolve_cname(struct rfc1035_res *res, char *namebuf,
+ unsigned qtype,
+ unsigned qclass,
+ struct rfc1035_reply **ptr,
+ int x_flags)
+{
+int n;
+int recursion_count=10;
+
+ if ( (*ptr=rfc1035_resolve(res, RFC1035_OPCODE_QUERY,
+ namebuf, qtype, qclass)) == 0)
+ return (-1);
+
+ if (x_flags && RFC1035_X_RANDOMIZE &&
+ (*ptr)->rcode == RFC1035_RCODE_NOERROR)
+ rfc1035_rr_rand(*ptr);
+
+ if ( (*ptr)->rcode != RFC1035_RCODE_NOERROR ||
+ (n=rfc1035_replysearch_an( res,
+ *ptr, namebuf, qtype, qclass, 0))<0)
+ return (-1);
+
+ if ( (*ptr)->anptr[n].rrtype == qtype) return (n);
+
+ /* Must've gotten back a CNAME when we were looking for something else
+ */
+
+ for (;;)
+ {
+
+ if (rfc1035_replyhostname( *ptr, (*ptr)->anptr[n].rr.domainname,
+ namebuf) == 0)
+ {
+ rfc1035_replyfree( *ptr );
+ *ptr=0;
+ return (-1);
+ }
+
+ /* Let's see if we already have the answer for the canonical name */
+
+ if ( (n=rfc1035_replysearch_all( res, *ptr, namebuf, qtype,
+ qclass, 0)) >= 0)
+ {
+ if ( (*ptr)->anptr[n].rrtype == qtype) return (n);
+ if ( --recursion_count > 0)
+ continue;
+
+ rfc1035_replyfree( *ptr ); /* Recursive CNAME */
+ *ptr=0;
+ return (RFC1035_ERR_CNAME_RECURSIVE);
+ }
+
+ rfc1035_replyfree( *ptr );
+ if ( (*ptr=rfc1035_resolve(res, RFC1035_OPCODE_QUERY,
+ namebuf, qtype, qclass)) == 0)
+ return (-1);
+
+ if ( (*ptr)->rcode == RFC1035_RCODE_NOERROR &&
+ (n=rfc1035_replysearch_an( res, *ptr, namebuf,
+ qtype, qclass, 0)) >= 0)
+ {
+ if ( (*ptr)->anptr[n].rrtype == qtype) return (n);
+ if ( --recursion_count > 0)
+ continue;
+ rfc1035_replyfree( *ptr ); /* Recursive CNAME */
+ *ptr=0;
+ return (RFC1035_ERR_CNAME_RECURSIVE);
+ }
+ return (-1);
+ }
+}