LINUX.ORG.RU

resolving MX


0

0

Как получить MX запись стандартными средствами?
Нашел libdns с чем dig слинкован но хедера от нее нет...

anonymous

Стандартными средствами не знаю.
но у меня есть функция, которая это делает, примерно 180 строк.
взята кажется из sendmail, работает хорошо.

Dead ★★★★
()
Ответ на: комментарий от Murr

>res_query - не из той оперы?

из той, просто определенную сложность представляет распаковка результатов работы этой функции :)

Dead ★★★★
()
Ответ на: комментарий от anonymous

#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <stdio.h>
#include <errno.h>
#include <netdb.h>

#ifndef MAXPACKET      // make sure a maximum packet size is declared by BIND
#define MAXPACKET 8192       // BIND maximum packet size
#endif

#define MAXMXHOSTS 9                // max number of MX records returned
#define MXBUFFERSIZE (128 * MAXMXHOSTS)

#ifndef HFIXEDSZ                              // make sure header size is declared
#define HFIXEDSZ 12
#endif


#define MX_NOBUFFERMEM -1
//#define NO_DATA -2
//#define NO_RECOVERY -3
#define MX_NODATA -4
//#define TRY_AGAIN  -5
#define MX_TEMPFAIL -6
#define MX_UNKNOWNERROR -7
#define MX_QUERROR -8
// definitions of return codes for your function can go in here..
// define custom data types

typedef union{
  HEADER hdr;                      // define a header structure
  u_char qbuf[MAXPACKET];          // define a query buffer
} mxquery;

 
/*******************************************************************************
***********/ 
int GetMXRecord( char *dname, char **mxhosts, u_short *mxprefs, char *mxbuf){
    // a function that queries a DNS server for MX records for the specified host
    // host - string containing host name
    // mxhosts - a pointer to an array of pointers each pointing to an MX record (in the same buffer, for efficiency)
    // mxprefs - a pointer to an array of unsigned shorts that specify the preferances of each MX host
    // mxbuf - a pointer to an allocated buffer that will contain all the host names (each name's pointer is in the mxhosts array)
    u_char *end, *puChar;                 // pointers to end of message, generic u_char pointer.
    int i, j, n, nmx;
    char *pByte;                          // generic char pointer
    HEADER *hp;                           // points to a header struct
    mxquery answer;                       // declare an mxquey buffer
    int answers, questions, buflen;
    u_short pref, type, *pPrefs; 
    struct hostent *h;                    // for the A record, if needed
    // check pointers
    if ( mxprefs == NULL)
	return ( MX_NOBUFFERMEM);
    if ( mxhosts == NULL)
	return ( MX_NOBUFFERMEM);
    if ( mxbuf == NULL)
	return ( MX_NOBUFFERMEM);
  // make query
    errno=0;
    n = res_query( dname, C_IN, T_MX, (u_char *) &answer, sizeof( answer));
    if ( n < 0) {
    // handle error conditions
	switch( errno) {
	    case NO_DATA:
	    case NO_RECOVERY:
		// no MX RRs, try the A record..
        	h = gethostbyname( dname);
        	if ( h != NULL) {
		    // returned a resolved result, store
        	    if ( h->h_name != NULL){
        		if ( strlen( h->h_name) != 0) snprintf( mxbuf, MXBUFFERSIZE-1, h->h_name);
        	    }
        	    else snprintf( mxbuf, MXBUFFERSIZE-1, dname);
        	    // set the arrays
        	    nmx=0;
        	    mxprefs[nmx]=0;
        	    mxhosts[nmx]=mxbuf;
        	    nmx++;
        	    return( nmx);
        	}
        	return( MX_NODATA);
        	break;
    	    case TRY_AGAIN:
    	    case -1:
		// couldn't connect or temp failure
		return( MX_TEMPFAIL);
        	break;
            default:
        	return( MX_UNKNOWNERROR);
//        	break;
	}
      // who knows what happened
	return( MX_UNKNOWNERROR);
    }

    // make sure we don't exceed buffer length
    if ( n > sizeof( answer)) n = sizeof( answer);
    // skip the question portion of the DNS packet
    hp = (HEADER *) &answer;
    puChar = (u_char *) &answer + HFIXEDSZ;                // point after the header
    end = (u_char *) &answer + n;                          // point right after the entire answer
    pPrefs = mxprefs;                                      // initialize the pointer to the array of preferences
    for( questions = ntohs((u_short)hp->qdcount) ; questions > 0 ; questions--, puChar += n+QFIXEDSZ){
	// loop on question count (taken from header), and skip them one by one
        if ( (n = dn_skipname(puChar, end)) < 0){
              // couldn't account for a question portion in the packet.
              return ( MX_QUERROR);
        }
    }
    // initialize and start decompressing the answer
    nmx = 0;
    buflen = MXBUFFERSIZE-1;
    pByte = mxbuf;                                                                   // point to start of mx hosts string buffer
    ZeroMemory( mxbuf, MXBUFFERSIZE);
    ZeroMemory( mxhosts, MAXMXHOSTS * 4);
    ZeroMemory( pPrefs, MAXMXHOSTS * sizeof(u_short));
    answers = ntohs((u_short)hp->ancount);                     // number of answers
    while( (--answers >= 0) && (puChar < end) && (nmx < MAXMXHOSTS-1) ) {
	// puChar constantly changes (moves forward in the answer buffer)
        // pByte points to the mx buffer, moves forward after we stored a host name
        // decompress the domain's default host name into the buffer so we can skip it and check if it's an      
        // MXhost
        if ( (n = dn_expand( (u_char *) &answer, end, puChar, (char *)pByte, buflen)) < 0) break;                                                     // error in answer
	puChar += n;                                                   // skip the name, go to its attributes
	GETSHORT( type, puChar);                         // get the type and move forward
	puChar += INT16SZ + INT32SZ;                 // skip the class and TTL portion of the answer RR
	GETSHORT( n, puChar);                              // get the resource size and move on
        if ( type != T_MX){
            // type of record is somehow NOT an MX record, move on
            puChar += n;
            continue;
        }
	GETSHORT( pref, puChar);                          // get the preference of the RR and move on
        if ( (n = dn_expand( (u_char *) &answer, 
	                      end, 
			      puChar, 
			      (char *)pByte, 
			      buflen)) < 0)  break;  // expand the MXRR
        					     // error in decompression
	puChar += n;
	// store it's attributes
	pPrefs[nmx] = pref;
	mxhosts[nmx] = pByte;
        nmx++;
        n = strlen( pByte);
	pByte += n+1;                                 // make sure it's null terminated, notice the buffer was set to 0 initially
	buflen -= n+1;            
    }
  // in case the records aren't sorted, bubble sort them
    for( i=0 ; i < nmx ; i++)
	for( j=i+1 ; j < nmx ; j++)
    	    if ( pPrefs[i] > pPrefs[j]){
		int temp;
	        char *temp2;
		temp = pPrefs[i];
                pPrefs[i] = pPrefs[j];
                pPrefs[j] = temp;
                temp2 = mxhosts[i];
                mxhosts[i] = mxhosts[j];
                mxhosts[j] = temp2;             
            }
  // remove duplicates
    for( i=0 ; i < nmx-1 ; i++){
	if ( strcasecmp( mxhosts[i], mxhosts[i+1]) != 0) continue;
	else {
	    // found a duplicate
	    for( j=i+1 ; j < nmx ; j++){
        	mxhosts[j] = mxhosts[j+1];
        	pPrefs[j] = pPrefs[j+1];
            }
            nmx--;                                  // 1 less MX record
        }
    }
  // all done, bug out
  return nmx;
}
/*******************************************************************************
***********/
extern int ZeroMemory( void *ptr, int size){
    // zeroes out a memory buffer
    if ( memset( ptr, 0, size) < 0) return -1;
    else return 1;
}
/*******************************************************************************
***********/

//Использовать примерно так

char *server="mail.ru"
char *pmx[10];
u_short mx_prefs[10];
char buf[10*256];
int i;

ret = GetMXRecord( server, pmx, mx_prefs, buf);

if ( ret < 0) {
    printf("MX records are not found\n");
    exit(-1); 
}


for(i = 0; i < ret; i++){
    printf("for server %s MX is %s\n", server, pmx[i]);
}








Dead ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.