/*
*
*              Reverse MX Filter for Postfix 2
*                    reject_bad_rmx
*           (c) 2004 Elita rozanski@sergiusz.com
*
*/

/*
MXfilter is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
*/

/*
This file is a modify part of public message:

To: sslug-cprog@sslug.dk 
Subject: Re: [CPROG] DNS query p. MX record. 
From: "Erwin S. Andreasen" <erw@dde.dk.sslug.dk> 
Date: Mon, 25 Oct 1999 11:51:52 +0200 (CEST) 
Delivered-To: mailing list sslug-cprog@sslug.dk 
In-Reply-To: <381364DB.48919E5@risoe.dk> 
Mailing-List: contact sslug-cprog-help@sslug.dk; run by ezmlm 

http://www.sslug.dk/emailarkiv/cprog/1999_10/msg00056.html
*/


#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <unistd.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <ctype.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <arpa/inet.h>

#include "fecyk.h"

struct rrecord {
    int16_t r_type;
    int16_t r_class;
    u_int32_t r_ttl;
    int16_t r_length;
};

/* find txtdomain for domain */
/* return -2 too many answers or no txt or txt but not dmp*/
/* return -1 dns error*/
/* return 0 dmp= */
/* return 1 dmp=allow */
/* return 2 dmp=deny */

int find_dmp(char *domain) {
    static char out[1000];
    unsigned char query[1000];
    HEADER *h;
    unsigned char *p;
    int qcount, acount;
    char buf[1000];
    struct rrecord *r;

    /* ask libc to do the query:
     * look up 'domain'
     * class C_IN (internet)
     * type  T_TXT
     * record results in query, max len 1000
     */
    if (res_search(domain, C_IN, T_TXT, query, 1000) <= 0) {
        if(h_errno == HOST_NOT_FOUND ||
                h_errno == TRY_AGAIN ||
                h_errno == NO_DATA)
            return (-2);
        return -1;
	}

    h = (HEADER *) query;

    /* skip over queries in packet */
    p = query + sizeof(HEADER);
    qcount = ntohs(h->qdcount);	/* # of queries present */
    acount = ntohs(h->ancount);	/* # of answers present */
    
//    printf(">> %d %d\n",qcount,acount);

    if(qcount!=1)return -2; //too many dmp records
    if(acount!=1)return -2; //too many dmp records
    
    /* get past queries */
    while (qcount--) {
	p += dn_expand(query, query + 1000, p, buf, 1000);
	p += 4;			/* qclass, qtype */
    }

    /* now we are in the answers section. Just get the best exchanger,
     * we don't want to spend too much time messing around
     */
    out[0] = 0;
    while (acount--) {
	/* name that this answer refers to */
	p += dn_expand(query, query + 1000, p, buf, 1000);

	r = (struct rrecord *) p;
	if (htons(r->r_type) == T_TXT) {		/* TXT record */
	    char result[1024];
	    unsigned char *p1 = p + 11;
	    snprintf(result,sizeof(result),"%.*s",ntohs(r->r_length)-1,p1);
	    if(strcasecmp(result,"dmp=")==0) {//root domain
		return 0;
		}
	    else
	    if(strcasecmp(result,"dmp=allow")==0) {//allow
		return 1;
		}
	    else
	    if(strncasecmp(result,"dmp=",4)==0) //dmp=deny or dmp=(other)
		return 2;
	    return -2; // txt record but false
	    }
	p = p + 10 + ntohs(r->r_length);	/* skip RR header and data */
    }

return -2;
}
