#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include"rr.h"
#include"errors.h"

int
dump_raw_rr(int fd, rr_t *rr) {
  write(fd, rr->name, (*rr->name)+1);
  write(fd, &rr->rrtype, 2);
  write(fd, &rr->rrclass, 2);
  write(fd, &rr->ttl, 4);
  write(fd, &rr->rdlength, 2);
  write(fd, rr->rdata, ntohs(rr->rdlength));
  
  return XENONE;
}

int
read_raw_rr(int fd, rr_t *rr) {
  rr->name=malloc(1);
  read(fd, rr->name, 1); rr->name=realloc(rr->name, (*rr->name)+2);
  read(fd, rr->name+1, (*rr->name)); rr->name[(*rr->name)+1]=0;
  read(fd, &rr->rrtype, 2);
  read(fd, &rr->rrclass, 2);
  read(fd, &rr->ttl, 4);
  read(fd, &rr->rdlength, 2);
  rr->rdata=malloc(ntohs(rr->rdlength));
  read(fd, rr->rdata, ntohs(rr->rdlength));
  
  switch (ntohs(rr->rrtype)) {
    case T_MX: rr->e.mx.preference=(int16_t *)rr->rdata;
	       rr->e.mx.exchange=rr->rdata+2;
	       break;
    case T_SOA: rr->e.soa.mname=rr->rdata;
		rr->e.soa.rname=rr->e.soa.mname+*rr->e.soa.mname+1;
		rr->e.soa.serial=(uint32_t *)(rr->e.soa.rname+*rr->e.soa.rname+1);
		rr->e.soa.refresh=(int32_t *)(rr->e.soa.rname+*rr->e.soa.rname+5);
		rr->e.soa.retry=(int32_t *)(rr->e.soa.rname+*rr->e.soa.rname+9);
		rr->e.soa.expire=(int32_t *)(rr->e.soa.rname+*rr->e.soa.rname+13);
		rr->e.soa.minimum=(uint32_t *)(rr->e.soa.rname+*rr->e.soa.rname+17);
		break;
  }
    
  return XENONE;
}

// l has to be malloc()ed for +1
void
domain2labels(char *l) {
  int m, n=*l; char *p=l+1;

  memmove(p+1, p, n); n++;

  for (m=2; m<n+1; m++) {
    if (l[m]=='.') {
      *p=m-(p-l)-1;
      p=l+m;
    }
  }

  if (*p=='.') { *p=0; }
  *l=n;
}

void
labels2domain(char *l) {
  char *p=l+1, *m; int n=*p;

  for (m=p; n; m+=n+1) {
    memmove(m, m+1, n=*m);
    m[n]='.';
  }
  m[-1]=0;
  (*l)--;
}
		   
