发新话题
打印

[求助] (1)在线求助下面代码的错误地方求解MX记录(DNS协议的装报和分析回复报)

263shanghai

(1)在线求助下面代码的错误地方求解MX记录(DNS协议的装报和分析回复报)

各位大虾,看看我的代码哪里出错了?
这个代码是按照DNS协议来查找MX记录的,但是在解析DNS数据报时候,发现我的装报是错误的,求各位怎么去装数据报,怎么去解析回复的数据报?

mxrecord.h
/*
** This class is used to parse domain name via email address
** It can get all MX records according to domain name
** It uses dns protocol to handle domain name parsing
** It will be used by us in sending email function
** Note that: this class uses STL
**
** Document:RFC 1034 and RFC 1035
** 0 = 初始化
** 1  = 处理成功
** -1 = 邮件地址没有'@'或者'.'
** -2 = 初始化winsock或者socket失败
** -3 = 发送DNS数据报失败
** -4 = 没有收到DNS数据报
** -5 = 收到DNS数据报不是本机发送的
** -6 = DNS服务器处理该数据报有错误
** -7 = 没有对应的 RR
** -8 = 关闭socket失败
*/
#ifndef DNS_MX
#define DNS_MX
#include<vector>
#include<string>
using namespace std;
struct TaskInformation
{
char *title; //邮件的标题
char *userName; //任务的用户名
char *taskName; //任务名
char *usedPlace; //本次使用的空间
char *leftPlace; //剩余的空间
char *startedTime; //开始的时间
char *endedTime;  //结束的时间
int errorCode; //本次任务的错误码
};

/* 1 = 发送邮件成功
** 2 = 初始化winsock或者socket失败
** 3 = 表示没有mail exchanger
** 4 = 连接mail exchanger 失败
** 5= 接受数据失败
** 6 = 处理ehlo命令失败
** 7 = 处理mail from命令失败
** 8 = 处理rctp to命令失败
** 9 = 处理data命令失败
** 10 = 处理'.'命令失败
** 9 = 处理quit命令失败
** 20 = 初始化
**/
class MXRecord
{
public:
MXRecord( char * );
~MXRecord();
    int getErrorCode() const;
void getResourceRecord();
void divideEmail( char* ); // divide email address into servral section including integer and string section
void display(); // only to test class
vector<string>mailExchanger;
vector<int>preference;
private:
int errorCode;
char *pemailAddress;
vector<unsigned int>sectionLength;
vector<string>sectionString;
char buff[512]; // store information sending
char receiver[ 512 ];
};

[ 本帖最后由 paulmeng 于 2007-1-4 16:01 编辑 ]
mxrecord.cpp
/*
** All functions are displayed to implemented belonging to MXRecord class
*/
#include<iostream>
#include<winsock2.h>
#include"mxrecord.h"
using namespace std;
// MXRecord structor function
MXRecord::MXRecord( char * emailaddress )
{
// allocate buff space
memset( this->buff,'\0',512 );
memset( this->receiver,'\0',512 );
this->errorCode =0; // initialize errorCode
this->pemailAddress = emailaddress;
} //End MXRecord();

//MXRecord destructor function
MXRecord::~MXRecord()
{

} //~MXRecord()

//return errorCode value
//errorCode can describle error information when using class
// sending email class will be used the errorCode
int MXRecord::getErrorCode() const
{
return this->errorCode;
} //End getErrorCode()

//handle sending and receiving dns package
// handle parse response package at the same time
//all the result will be stored in mailExchanger and preference vector
//Warning: pay attention to bit pointer
void MXRecord::getResourceRecord()
{

// get resource record according to this->emailAddress

    this->divideEmail( this->pemailAddress );
//每次进行处理下一个动作之前看前一个动作是否正常完成
if( this->errorCode < 0 )
  return ;
//开始装DNS数据报
char *pbitptr = buff;//使用bitptr指针来指示每一个字节的地址
//装载header
*((unsigned short*)pbitptr) = htons(1000); //ID
    pbitptr += 2;
    *((unsigned short*)pbitptr) = htons(0x0100); //Flag pcode
pbitptr += 2;
    *((unsigned short*)pbitptr) = htons(1); //qdcont
    pbitptr+= 2;
    *((unsigned short*)pbitptr) = htons(0); //ancount
    pbitptr+= 2;
    *((unsigned short*)pbitptr) = htons(0); //nscount
    pbitptr+= 2;
    *((unsigned short*)pbitptr) = htons(0); //arcount
    pbitptr+= 2;
   
register int skipByte = 0;
    //装载查询的部分
    for( int i = 1;i <= this->sectionLength.size(); i++ )
{   
  //装载每一个label的长度
   register unsigned short len = this->sectionLength.at( i-1 );
   skipByte += len;
   *pbitptr = len;
   //装载对应的label
   pbitptr++;
   for( int j = 0; j < len;j++ )
   {
            *pbitptr = this->sectionString.at( i-1 ).at( j );
   pbitptr++;
   } //End for loop
} //End for loop
    //装载最后的0
*pbitptr = 0;
     
    //装载qtype = mx
pbitptr++;
*((unsigned short*)pbitptr) = htons(0x0f);
//装载qclass = in
pbitptr += 2;
*((unsigned short*)pbitptr) = htons(0x01);
    pbitptr += 2;
int totalByte = pbitptr - buff;
//发送socket数据报
WSADATA wsadata;
if( WSAStartup( MAKEWORD( 2, 0),&wsadata ) != 0 )
{
  this->errorCode = -2;
  return ;
}
int sockfd;
if( ( sockfd = socket(AF_INET,SOCK_DGRAM,0 )) == -1 )
{
  this->errorCode = -2;
  return;
}

struct sockaddr_in localDNS;
    struct sockaddr_in dnsserver;
    int sockaddrLen = sizeof( struct sockaddr);
    localDNS.sin_family = AF_INET;
    localDNS.sin_port = htons(53);
    localDNS.sin_addr.s_addr = inet_addr( "202.96.154.15" ); //DNS server ip
// localDNS.sin_addr.s_addr = inet_addr( "202.96.128.68" ); //DNS server ip
if( (sendto(sockfd,buff,totalByte,0,(struct sockaddr*)&localDNS,sizeof( struct sockaddr)))!= totalByte )
{
       this->errorCode = -3;
    return;
}
if( (recvfrom( sockfd,this->receiver,512,0,(struct sockaddr*)&dnsserver,&sockaddrLen)) == 0)
{
  this->errorCode = -4;
     return;
}
   
//检查收到的数据报是否是自己发送的
pbitptr = this->receiver;
if( ntohs( *(unsigned short*)pbitptr) != 1000)
{
  this->errorCode = -5;
  return;
}
    //检查DNS服务器处理的结果
pbitptr += 2;
int rcode = 0xf & ntohs(*(unsigned short*)pbitptr);
if( rcode != 0 )
{
  this->errorCode = -6;
  return;
}


    pbitptr += 2;//qncount;
pbitptr += 2; //ancount
    int answer = ntohs(*((unsigned short*)pbitptr));

    if( answer == 0 )
{
  this->errorCode = -7;
  return;
}
//authorative
pbitptr += 2;
//additional
pbitptr += 2;
    pbitptr += 2;// query section

skipByte += sectionLength.size();
skipByte++;
    pbitptr +=skipByte;
pbitptr += 4; // rr section
   
//处理每一个MX record
register char * ptemparory = pbitptr;
for( int index = 1; index <= answer;index++ )
{   
  pbitptr = ptemparory;
  pbitptr += 2; //skip name offset
  pbitptr += 2; //skip type
  pbitptr += 2; //skip class
  pbitptr += 4; //skip ttl
  register int isizeOfRdata = ntohs(*((unsigned short*)pbitptr));
      
  pbitptr +=2; //skip rdlength
        register int ipreference = ntohs(*((unsigned short*)pbitptr));
  this->preference.push_back( ipreference );
  pbitptr +=2; //skip preference
        register char pMailExchanger[100];
  memset( pMailExchanger,'\0',100 );
  register char*pguard = pMailExchanger;
  for( int bytes = 1; bytes <= isizeOfRdata-2;)
  {
   register int sectionLength = *pbitptr;
   if( sectionLength == 0 )
   {
                pguard --;
    *pguard = '\0';
    bytes+=2;
    //bitptr++;
    this->mailExchanger.push_back( pMailExchanger );
   }
   else
   if( sectionLength == -64 ) //offset
   {
    bytes += 2; //表示现在要去处理便移量
    pbitptr++;
    register int offset = (unsigned short)*pbitptr;
    register char* poff = this->receiver + offset; //找到offset的地址
               
    //在指针的地方不知道有多少个字符,故用while循环
    while( *poff != 0)
    {
     poff++;
     register int partlength = *poff;
     for( int k = 1; k <= partlength; k++ )
     {
      *pguard = *poff;
                        poff++;
      pguard++;
     } //处理每一个label
     *pguard = '.';
                    pguard++;
    } //End while loop
    pguard--;
    *pguard = '\0';
    this->mailExchanger.push_back( pMailExchanger );
   }
   else //一般情况
   {
    for( int i = 1;i <= sectionLength; i++ )
    {
     bytes++;
     pbitptr++;
     *pguard = *pbitptr;
     pguard++;
    } //处理完一个label
                bytes++;
    pbitptr++;
    *pguard = '.';
    pguard++;
   } //结束一般情况
  } //结束一个 mail exchanger
      
   ptemparory += 10;
      ptemparory += isizeOfRdata;
} //End for loop
   if( closesocket( sockfd ) != 0 )
   {
    this->errorCode = -8;
    return;
   }
WSACleanup();
    this->errorCode = 1;
return ;
} //End getResourceRecord()

//根据email地址,把@后面的域名去出来,同时还要分解为数据报的格式
//比如:yahoo.com.cn
//数据报格式为 5yahoo3com2cn0
//处理的结果放置在setionLength 和sectionString 中,分别存储长度和对应的字符
void MXRecord::divideEmail( char *emailaddress )
{
   register string temString = emailaddress;
   
   //检查域名的格式,是否有一个'.'符号
   int location = temString.find_first_of( '@', 0 );
   if( location == -1 )
   {
    this->errorCode = -1;
    return ;
   }
   
   //除去@字符,只保留后面的域名
   temString = temString.substr( location + 1 );
   
   //开始分解域名,把每个'.'分开的label放置到sectionString中,同时把对应的长度放置到sectionLength中
   location = temString.find_first_of( '.' , 0 );
   
   //检查域名的格式,是否有一个'.'符号
   if( location == -1 )
   {
    this->errorCode = -1;
    return ;
   }

   while( location != -1 )
   {
    this->sectionLength.push_back( location );//store length
    this->sectionString.push_back( temString.substr( 0, location ) ); //store characters
   
    temString = temString.substr( location + 1 );
       location = temString.find_first_of( '.' , 0 );
   } //End while loop
   //保存最后的字符数和对应的字符
   sectionLength.push_back( temString.size() );
   sectionString.push_back( temString );
   return;
} //End diviedEmail()

//testing class
void MXRecord::display()
{
getResourceRecord();
int errorcode = this->getErrorCode();
cout <<"Error code = " << errorcode << endl;
cout << "email = " << this->pemailAddress << endl;
   
int sectionlength = this->sectionLength.size();
cout << "section length = " << sectionlength << endl;
int stringlength = this->sectionString.size();
cout << "section string = " <<  stringlength << endl;
for( int i = 0; i< sectionlength; i++)
  cout << this->sectionLength.at(i) << " " ;
cout << endl;
for( int j = 0; j< stringlength; j++ )
  cout << this->sectionString.at(j) << " " ;
int length = this->preference.size();
cout << "preference length " << length << endl;
cout << "preferencer is " <<  this->preference.at(0) << endl;
cout << endl << endl;

} //End display()

//all functions belonging to Email class are displayed as follows

//constructor
Email::Email( char *emailaddress,struct TaskInformation information ):MXRecord( emailaddress )
{
this->pdomainName = emailaddress;
//initialize all memeber of task information
    this->taskInformation.endedTime = information.endedTime;
this->taskInformation.errorCode = information.errorCode;
this->taskInformation.leftPlace = information.leftPlace;
this->taskInformation.startedTime = information.startedTime;
this->taskInformation.taskName = information.taskName;
this->taskInformation.title = information.title;
this->taskInformation.usedPlace = information.usedPlace;
this->taskInformation.userName = information.userName;
this->responseCode = 20 ;
} //Email()

//destructor
Email::~Email()
{
} //End ~Email()

//send email to sender address
void Email::sendEmail()
{
getResourceRecord();
int errorcode = getErrorCode();
if( errorcode != 1 )
{
  this->responseCode = errorcode;
  return;
}
   
WSADATA wsaData;
if(WSAStartup( MAKEWORD( 2, 0 ),&wsaData) != 0)
{
  this->responseCode = 2;
  return;
}
int sock;
if( (sock=socket( AF_INET,SOCK_STREAM,0)) == -1 )
{
  this->responseCode = 2;
  return;
}
sockaddr_in smtpIP;
smtpIP.sin_family = AF_INET;
smtpIP.sin_port = htons( 25 );
// 循环遍历每一个 Mail exchanger,如果有一个发送成功,就终止发送,
int loop = mailExchanger.size();
if( loop == 0 )
{
  this->responseCode = 3;
  return;
}
else
{
  register string domainname = this->getDomainName();
  for( int index = 1 ; index <= loop; index++ )
  {
   register struct hostent *phost = gethostbyname( mailExchanger.at( index-1 ).data() );
   register struct in_addr *paddr = ( struct in_addr *)*phost->h_addr_list;
   smtpIP.sin_addr.s_addr = inet_addr( inet_ntoa(*paddr) );
   char recvbuff[256];
         memset(recvbuff, 0, sizeof(recvbuff));
         char sendbuff[256];
         memset(sendbuff, 0, sizeof(sendbuff));
   register int len;
            register int rval;
   //connect smtp server
         if (connect(sock, (sockaddr*)&smtpIP, sizeof( sockaddr ) ) != 0 )
   {
          this->responseCode = 4; //连接SMTP服务器失败
          return ;
   }
            
            //send email
            strcpy(sendbuff, "EHLO ");
            strcat(sendbuff, domainname.data());
            strcat(sendbuff, "\r\n");
            len = strlen(sendbuff);
            rval = send(sock, sendbuff, len, 0 );
   rval = recv(sock, recvbuff, sizeof(recvbuff), 0); //modified
      rval = recv(sock, recvbuff, sizeof(recvbuff), 0); //modified
   if (rval == -1 )
   {
          this->responseCode = 5; //接收数据失败
             return ;
   }
           if (strstr(recvbuff, "250") == NULL )
     {
       this->responseCode = 6; //SMTP服务器处理此命令失败
       return;
     }
     //send email
           strcpy(sendbuff ,"MAIL FROM:" );
           strcat(sendbuff,"<support@gbvsystem.com>");
           strcat(sendbuff,"\r\n" );
           len = strlen(sendbuff );
           rval = send(sock,sendbuff,len,0 );
           rval = recv(sock,recvbuff,sizeof( recvbuff), 0 );
           if (rval == -1 )
     {
          this->responseCode = 5; //接收数据失败
          return ;
     }
           if (strstr( recvbuff,"250" ) == NULL )
     {
          this->responseCode = 7; //SMTP服务器处理此命令失败
    return;
     }
     // receiver address
           strcpy(sendbuff,"RCPT TO:" );
           strcat(sendbuff,"<" );
           strcat(sendbuff,this->pdomainName );
           strcat(sendbuff,">" );
           strcat(sendbuff,"\r\n" );
           len = strlen(sendbuff );
           rval = send(sock,sendbuff,len ,0 );
           rval = recv( sock,recvbuff ,sizeof( recvbuff) -1 , 0 );
           if (rval == -1 )
     {
             this->responseCode = 5; //接收数据失败
             return ;
     }
           if(strstr(recvbuff,"250" ) == NULL )
     {
             this->responseCode = 8; //SMTP服务器处理此命令失败
       return;
     }
           
     //send data
     strcpy(sendbuff,"DATA" );
           strcat(sendbuff,"\r\n" );
           len = strlen(sendbuff );
           rval = send(sock,sendbuff,len, 0 );
           rval = recv(sock,recvbuff,sizeof(recvbuff), 0 );
           if (rval == -1 )
     {
             this->responseCode = 5; //接收数据失败
             return ;
     }
           if (strstr(recvbuff,"354" ) == NULL )
     {
             this->responseCode = 9;  //SMTP服务器处理此命令失败
       return;
     }
     strcpy(sendbuff,"FROM:<");
           strcat(sendbuff,"support@gbvsystem.com" );
           strcat(sendbuff,">\r\n");
           len = strlen(sendbuff );
           rval = send(sock,sendbuff ,len ,0 );
           strcpy(sendbuff ,"SUBJECT:" );
           strcat(sendbuff,this->taskInformation.title );
           strcat(sendbuff,"\r\n" );
           len = strlen(sendbuff );
           rval = send(sock, sendbuff,len ,0 );
           strcpy(sendbuff,"TO:<" );
           strcat(sendbuff,this->pdomainName );
           strcat(sendbuff,">\r\n" );
           strcpy( sendbuff ,"" );
           strcat( sendbuff ,"\r\n" );
           len = strlen( sendbuff );
           send( sock ,sendbuff,len ,0 );
     strcpy(sendbuff,"Hello ");
        strcat(sendbuff, this->taskInformation.userName );
           len = strlen(sendbuff );
           send(sock,sendbuff,len ,0 );
           strcpy(sendbuff,"" );
           strcat(sendbuff,"\r\n" );
           len = strlen(sendbuff );
           send(sock,sendbuff ,len, 0 );
     strcpy(sendbuff, "TasK Name " );
        strcat(sendbuff, this->taskInformation.taskName );
           len = strlen(sendbuff );
           send(sock,sendbuff ,len ,0 );
           strcpy(sendbuff,"" );
           strcat(sendbuff,"\r\n" );
           len = strlen(sendbuff );
           send(sock,sendbuff,len, 0 );
     if (this->taskInformation.errorCode == 0 )
     {   
         // 3 line for task failed
         strcpy(sendbuff, "Task " );
            strcat(sendbuff, " Failed" );
               len = strlen(sendbuff );
               send(sock,sendbuff,len ,0 );
               strcpy(sendbuff,"" );
               strcat(sendbuff,"\r\n" );
               len = strlen(sendbuff );
               send(sock,sendbuff,len, 0 );
     }
        else
     {   
         // task succeeded
               // 3 line
         strcpy(sendbuff, "Used Place " );
            strcat(sendbuff, this->taskInformation.usedPlace );
               len = strlen(sendbuff );
               send(sock,sendbuff,len ,0 );
               strcpy(sendbuff,"" );
               strcat(sendbuff,"\r\n" );
               len = strlen(sendbuff );
               send(sock,sendbuff ,len, 0 );
         //4 line
               strcpy(sendbuff, "Left Space " );
            strcat(sendbuff, this->taskInformation.leftPlace );
               len = strlen(sendbuff );
               send(sock,sendbuff ,len ,0 );
               strcpy(sendbuff,"" );
               strcat(sendbuff,"\r\n" );
               len = strlen(sendbuff );
               send(sock,sendbuff ,len, 0 );
         //5 line
         strcpy(sendbuff, "Start Time " );
            strcat(sendbuff, this->taskInformation.startedTime );
               len = strlen(sendbuff );
               send(sock,sendbuff,len,0 );
               strcpy(sendbuff,"" );
               strcat(sendbuff,"\r\n" );
               len = strlen(sendbuff );
               send(sock,sendbuff,len, 0 );
         // 6 line
         strcpy(sendbuff, "End Time " );
            strcat(sendbuff, this->taskInformation.endedTime );
               len = strlen(sendbuff );
               send(sock,sendbuff,len,0 );
               strcpy(sendbuff,"" );
               strcat(sendbuff,"\r\n" );
               len = strlen(sendbuff );
               send(sock,sendbuff,len, 0 );
     }
      // last line of email
            strcpy(sendbuff, "Best guard " );
            len = strlen(sendbuff );
            send(sock,sendbuff,len ,0 );
            strcpy(sendbuff,"" );
            strcat(sendbuff,"\r\n" );
            len = strlen(sendbuff );
            send(sock,sendbuff,len, 0 );
        strcpy( sendbuff, "GBV SYSTEM " );
           len = strlen(sendbuff );
           send(sock,sendbuff,len,0 );
           strcpy(sendbuff,"" );
           strcat(sendbuff,"\r\n" );
           len = strlen(sendbuff );
           send(sock,sendbuff,len, 0 );
     strcpy(sendbuff, "\r\n.\r\n" );
           len = strlen(sendbuff );
           rval = send(sock,sendbuff,len, 0 );
           rval = recv(sock,recvbuff,sizeof( recvbuff) ,0 );
           if (rval == -1 )
     {
           this->responseCode = 5; //接收数据失败
           return ;
     }
           if (strstr(recvbuff,"250" ) == NULL )
     {
            this->responseCode = 10; //SMTP服务器处理此命令失败
      return;
     }
     strcpy( sendbuff ,"QUIT\r\n" );
           len = strlen( sendbuff );
           rval = send(sock,sendbuff,len, 0 );
           rval = recv( sock ,recvbuff ,sizeof( recvbuff ),0 );
           if (rval == -1 )
     {
            this->responseCode = 5; //接收数据失败
            return ;
     }
   
           if (strstr( recvbuff ,"221" ) != NULL )
     {
           this->responseCode  = 1; //发送EMAIL成功
           break; ;
     }
           else
     {
           this->responseCode = 11; //SMTP服务器处理此命令失败
     return;
     }

  } //End for loop
} //发送邮件结束
   
return;
} //End sendEmail()
//get domain name via email address
string Email::getDomainName()
{
   register string temString = pdomainName;   
   int location = temString.find_first_of( '@', 0 );
   temString = temString.substr( location + 1 );
   return temString;
}//End getDomainName()
//return response code
int Email::getResponseCode() const
{
return this->responseCode ;
} //End getResponseCode()
//only to test email class
void Email::display()
{   
sendEmail();
int errorcode = getResponseCode();
cout << "Response code = "<<errorcode << endl;
return;
} //End display()
上面的代码可以解析yahoo.com.cn和163.com,但是在解析sina.com时候程序出现异常,我是用VC6.0编译的,各位帮忙一下,看看是不是在分析MX记录的时候出错了,所有的操作是用指针来进行的.
晕, 看不懂程序, 帮你顶一下.
ORF防垃圾邮件系统, 以超低费用享受高质过滤, 让你永离垃圾骚扰!
详情请看: www.assistant-soft.com
没办法,我也不懂,帮你顶一下吧!
Allen chen
:'( :'( :'( ,各位帮帮忙忙吧,求求你们了,我在网上实在找不到对应的资料,5555,现在是不知道怎么解决啊
发新话题
  清除 Cookies - 联系我们 - 邮件技术资讯网 - Archiver - WAP - 繁體中文
当前时区 GMT+8, 现在时间是 2008-9-7 23:29

本论坛为非盈利中立机构,论坛所有言论纯属发表者个人意见,与《 邮件技术资讯网》论坛立场无关。内容所涉及的版权和法律相关事宜请参考各自所有者的条款。
如果认定侵犯了您的权利,请联系我们尽快处理。本论坛原创内容请联系本站后再行转载并务必保留我站信息。此声明修改不再另行通知,本论坛保留最终解释权。
*本论坛QQ群:1#群2233231(已满) 2#群2598254(推荐) 3#群15974064(推荐) 4#群14173252(推荐)*
* 建议使用 1024×768 模式查看本论坛 *
Powered by Discuz! 6.1.0