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

response.c

#include "bin.h"
#include "ldapdns.h"
#include "dns.h"
#include "str.h"
#include "ht.h"

#include <netinet/in.h>
#include <string.h>

int response_rstart(dns_ctx *c, char *dnsenc, char rr[2], unsigned int ttl)
{
      if (!response_addname(c, dnsenc)) return 0;
      if (!response_addbytes(c, rr, 2)) return 0;
      if (!response_addbytes(c, DNS_C_IN, 2)) return 0;
      if (!response_addulong(c, ttl)) return 0;
      if (!response_addbytes(c, "\0\0", 2)) return 0;
      c->response_dpos = clen(c->response);
      return 1;
}
static unsigned long __hash_dns(const void *str, unsigned len)
{
      const char *h;
      unsigned long d;
      unsigned i;

      d = 5431;
      for (i = 0, h = str; i < len; i++) {
            /* Clib */
            d += (d << 5) ^ (tolower((int)h[i]));
      }

      return d;
}
void response_axfr(dns_ctx *c)
{
      c->response->used = 0; /* Internal */
}
int response_axstart(dns_ctx *c, int soa, char *q, char qt[2], char qc[2], unsigned int ttl)
{
      int flushed = 0;
      char buf[10];

      if (c->response->used > 0) {
            tp_write(c);
            flushed = 1;
      }

      c->answers = 0;
      c->response_ls = 0;
      ht_die(&c->response_names);
      c->response->used = 0; /* Internal */

      ht_init(&c->response_names, 7, __hash_dns);

      if (!response_addbytes(c, c->dns_message_id, 2)) return 0;
      memcpy(buf, "\204\000\0\0\0\1\0\0\0\0", 10);
      if (!soa) buf[0] &= ~4;

      if (!flushed) {
            buf[3] = 1;
            if (!response_addbytes(c, buf, 10)) return 0;
            if (!response_addname(c, q)) return 0;
            /* we only support AXFR over internet */
            if (!response_addbytes(c, DNS_T_AXFR, 2)) return 0;
            if (!response_addbytes(c, DNS_C_IN, 2)) return 0;
      } else {
            if (!response_addbytes(c, buf, 10)) return 0;
      }
      if (!response_addname(c, q)) return 0;
      if (!response_addbytes(c, qt, 2)) return 0;
      if (!response_addbytes(c, qc, 2)) return 0;
      if (!response_addulong(c, ttl)) return 0;
      if (!response_addbytes(c, "\0\0", 2)) return 0;
      c->response_dpos = clen(c->response);
      return 1;
}
void response_axfinish(dns_ctx *c)
{
      unsigned short n;

      /* Clib */
      n = htons(clen(c->response) - c->response_dpos);
      memcpy(c->response->buf + (c->response_dpos - 2), &n, 2);
}
int response_query(dns_ctx *c, char *q, char qt[2], char qc[2])
{
      c->answers = 0;
      c->response_ls = 0;
      ht_die(&c->response_names);
      c->response->used = 0; /* Internal */

      ht_init(&c->response_names, 7, __hash_dns);

      if (!response_addbytes(c, "\0\0\201\200\0\1\0\0\0\0\0\0", 12)) return 0;
      if (!response_addname(c, q)) return 0;
      if (!response_addbytes(c, qt, 2)) return 0;
      if (!response_addbytes(c, qc, 2)) return 0;

      c->response_tc = clen(c->response);
      return 1;
}
int response_notify(dns_ctx *c, char *q, char qt[2], char qc[2])
{
      c->response->used = 0; /* Internal */

      if (!response_addbytes(c, "\0\0\204\200\0\1\0\0\0\0\0\0", 12)) return 0;
      if (!response_addname(c, q)) return 0;
      if (!response_addbytes(c, qt, 2)) return 0;
      if (!response_addbytes(c, qc, 2)) return 0;

      return 1;
}

int response_adddns(dns_ctx *c, char *dnsenc)
{
      register int dlen, i;
      unsigned short j;

      /* ALWAYS: convert dnsenc to upper case */
      for (i = 0; dnsenc[i]; i++) {
            dnsenc[i] = tolower(dnsenc[i]);
      }
      dlen = i;

      /* safe IF dnsenc is a valid dns name */
      while (*dnsenc) {
            i = ht_fetchint(&c->response_names, dnsenc, dlen);
            if (i > -1) {
                  return response_addnameptr(c, i);
            }
            if (dlen <= 128) {
                  j = clen(c->response);
                  ht_storeint(&c->response_names, dnsenc, dlen, j);
            }
            i = ((unsigned char) *dnsenc) + 1;
            if (!response_addbytes(c, dnsenc, i))
                  return 0;
            dnsenc += i;
            dlen -= i;
      }
      return response_addbytes(c, "\0", 1);
}
int response_addnetbios(dns_ctx *c, char *dnsenc)
{
      /* translates a name to netbios format */
      char buf[34];
      register int i, j, x;

      /* not a netbios name */
      if (dns_domain_length(dnsenc) > 16)
            return response_adddns(c, dnsenc);

      for (i = 0, j = 1; i < dnsenc[0]; i++) {
            x = toupper((unsigned int)(dnsenc[i+1]));
            buf[j] = (0x41 + ((x & 0xF0) >> 4));
            j++;
            buf[j] = (0x41 + ((x & 0x0F)));
            j++;
      }
      while (j < 31) {
            buf[j] = 0x43; j++; /* ca == whitespace */
            buf[j] = 0x41; j++;
      }
      buf[31] = 0x41; buf[32] = 0x41;
      buf[33] = 0;
      buf[0] = 32;
      return response_adddns(c, buf);
}
int response_addname(dns_ctx *c, char *dnsenc)
{
      if (c->protnum == PROT_NETBIOS)
            return response_addnetbios(c, dnsenc);
      return response_adddns(c, dnsenc);
}

int response_addbytes(dns_ctx *c, unsigned char *b, int l)
{
      bin_cat(c->response, b, l);
      return 1;
}

int response_addulong(dns_ctx *c, unsigned long n)
{
      char buf[4];

      /* Clib */
      n = htonl(n);
      memcpy(buf, &n, 4);
      return response_addbytes(c, buf, 4);
}
int response_addnameptr(dns_ctx *c, unsigned int u)
{
      char buf[2];

      u += 49152;
      buf[1] = u & 255;
      buf[0] = u >> 8;
      return response_addbytes(c, buf, 2);
}
int response_addushort(dns_ctx *c, unsigned short n)
{
      char buf[2];

      /* Clib */
      n = htons(n);
      memcpy(buf, &n, 2);
      return response_addbytes(c, buf, 2);
}

void response_id(dns_ctx *c, const char id[2])
{
      bin_need(c->response, 12);
      c->dns_message_id[0] = c->response->buf[0] = id[0];
      c->dns_message_id[1] = c->response->buf[1] = id[1];
}
void response_rcode(dns_ctx *c, int code)
{
      bin_need(c->response, 12);
      c->response->buf[3] &= ~15;
      c->response->buf[3] |= (code & 15);
}
void response_aa(dns_ctx *c, int setting)
{
      bin_need(c->response, 12);
      if (setting) {
            c->response->buf[2] |= 4;     /* set 'aa' flag */
      } else {
            c->response->buf[2] &= (~4);  /* clear 'aa' flag */
      }
}
void response_tc(dns_ctx *c)
{
      bin_need(c->response, 12);
      c->response->buf[2] |= 2;
      c->response->used = c->response_tc; /* Internal */
}
void response_nxdomain(dns_ctx *c)
{
      bin_need(c->response, 12);
      c->response->buf[3] |= 3;
      c->response->buf[2] |= 4;
}
void response_servfail(dns_ctx *c)
{
      bin_need(c->response, 12);
      c->response->buf[3] |= 2;
}
void response_refuse(dns_ctx *c)
{
      bin_need(c->response, 12);

      if (c->axfr) {
            c->response->buf[2] &= ~4;
            c->response->buf[3] &= ~128;
            c->response->buf[3] &= ~15;
            c->response->buf[3] |= 5;
      } else {
            c->response->buf[2] &= ~4;
            c->response->buf[3] &= ~15;
            c->response->buf[3] |= 5;
      }
}

int response_rfinish(dns_ctx *c, int section)
{
      unsigned short n;

      bin_need(c->response, 12);
      /* increment answers... */

      /* Clib */
      memcpy(&n, c->response->buf + section, 2);

      /* Clib */
      n = htons(ntohs(n) + 1);
      memcpy(c->response->buf + section, &n, 2);

      /* set length of this response (rr) data */
      
      /* Clib */
      n = htons(clen(c->response) - c->response_dpos);
      memcpy(c->response->buf + (c->response_dpos - 2), &n, 2);

      if (c->response_ls != section) {
            /* change of section */
            c->response_tc = clen(c->response);
            c->response_ls = section;
      }
      if (section == RESPONSE_ANSWER)
            c->answers++;

      return 1;
}


Generated by  Doxygen 1.6.0   Back to index