/*
 *  res_free.c
 *
 *  Free a DNS response tree
 *
 *  v1.0
 *
 *  Dave Shield		January 1994
 *
 *  v1.3	Correct a couple of resource-specific entries
 *		Free individual question structures
 *			July 1997
 */

#include	"rr.h"
#include        "rr-internal.h"
#include        <stdlib.h>


	/*
	 *  free_rr:
	 *	Free an individual Resource Record record
	 */
void
free_rr(s_rr *rrp)
{
		/*
		 *  Free generic RR memory
		 */
	free(rrp->name);

		/*
		 *  Free RR-specific memory
		 */
	switch (rrp->type) {
	case T_NS:
	case T_MD:
	case T_MF:
	case T_CNAME:
		free(rrp->rdata.string);
		break;
	case T_SOA:
		free(rrp->rdata.soa.mname);
		free(rrp->rdata.soa.rname);
		break;
	case T_MB:
	case T_MG:
	case T_MR:
		free(rrp->rdata.string);
		break;
	case T_NULL:
		free(rrp->rdata.null.anything);
		break;
	case T_WKS:
		free(rrp->rdata.wks.bitmap);
		break;
	case T_PTR:
		free(rrp->rdata.string);
		break;
	case T_HINFO:
		free(rrp->rdata.hinfo.cpu);
		free(rrp->rdata.hinfo.os);
		break;
	case T_MINFO:
		free(rrp->rdata.minfo.rmailbx);
		free(rrp->rdata.minfo.emailbx);
		break;
	case T_MX:
		free(rrp->rdata.mx.exchange);
		break;
	case T_SRV:
		free(rrp->rdata.srv.target);
		break;
	case T_TXT:
		free(rrp->rdata.txt.text);
		if (rrp->rdata.txt.next != NULL) {
			struct s_TXT	*txtp;
			struct s_TXT	*txtp2;

			txtp = &(rrp->rdata.txt);
			while ( txtp->next != NULL ) {
				free( txtp->text );
				txtp2 = txtp->next;
				free(txtp);
				txtp = txtp2;
			}
		}
		break;
	case T_AFSDB:
		free(rrp->rdata.afsdb.hostname);
		break;
	case T_RP:
		free(rrp->rdata.rp.mbox_dname);
		free(rrp->rdata.rp.txt_dname);
		break;
	case T_X25:
		free(rrp->rdata.string);
		break;
	case T_ISDN:
		free(rrp->rdata.isdn.address);
		free(rrp->rdata.isdn.sa);
		break;
	case T_RT:
		free(rrp->rdata.rt.int_host);
		break;
	case T_UINFO:
	case T_UNSPEC:
		free(rrp->rdata.string);
		break;
	}    

		/*
		 *  Free RR itself
		 */
	free(rrp);
}



	/*
	 *  free_response:
	 *	Free the contents of a DNS response tree
	 */
void
free_response(res_response *resp)
{
	int	i, n;

	/*
	 *  Free question memory
	 */
	if ((n = resp->header.qdcount) != 0) {
		for ( i=0 ; i<n ; i++ ) {
			free(resp->question[i]->qname);
			resp->question[i]->qname = NULL;
			free(resp->question[i]);
			resp->question[i] = NULL;
		}
		free(resp->question);
		resp->question = NULL;
		resp->header.qdcount=0;
	}

	/*
	 *  Free authoritative answer memory
	 */
	if ((n = resp->header.ancount) != 0) {
		for ( i=0 ; i<n ; i++ ) {
			free_rr(resp->answer[i]);
			resp->answer[i] = NULL;
		}
		free(resp->answer);
		resp->answer = NULL;
		resp->header.ancount=0;
	}

	/*
	 *  Free name server memory
	 */
	if ((n = resp->header.nscount) != 0) {
		for ( i=0 ; i<n ; i++ ) {
			free_rr(resp->authority[i]);
			resp->authority[i] = NULL;
		}
		free(resp->authority);
		resp->authority = NULL;
		resp->header.nscount=0;
	}

	/*
	 *  Free additional memory
	 */
	if ((n = resp->header.arcount) != 0) {
		for ( i=0 ; i<n ; i++ ) {
			free_rr(resp->additional[i]);
			resp->additional[i] = NULL;
		}
		free(resp->additional);
		resp->additional = NULL;
		resp->header.arcount=0;
	}
}



	/*
	 *  res_free:
	 *	Free a DNS response tree
	 */
void
res_free(res_response *resp)
{
	free_response( resp );
	free( resp );
}
