diff options
Diffstat (limited to 'rfc1035/rfc1035search.c')
| -rw-r--r-- | rfc1035/rfc1035search.c | 214 |
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); + } +} |
