Viewing file:
rfc1035search.c (4.95 KB) -rw-rw-rw-Select action/file-type:

(
+) |

(
+) |

(
+) |
Code (
+) |
Session (
+) |

(
+) |
SDB (
+) |

(
+) |

(
+) |

(
+) |

(
+) |

(
+) |
/*
** Copyright 1998 - 2002 Double Precision, Inc.
** See COPYING for distribution information.
*/
#include "rfc1035.h"
#include "rfc1035_res.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, int flags, 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, flags,
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, flags,
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);
}
}