Exemple #1
0
BOOL GetMX (
			char *pszQuery,
			char *pszServer,
			OUT t_Ary_MXHostInfos &Ary_MXHostInfos
			)
{
	SOCKET                  hSocket;
	SOCKADDR_IN             stSockAddr;                     // socket address structures
	int                             nAddrLen = sizeof( SOCKADDR_IN );

	HOSTENT                 *pHostEnt;

	char                            achBufOut[ BUFSIZE ] = { 0 };
	char                            achBufIn[ BUFSIZE ] = { 0 };
	int                             nQueryLen = 0;
	int                             nRC;

	char *p, *np, name[128], *eom;
	int count, j, i, n;

	memset( &stSockAddr, ASCII_NULL, sizeof( stSockAddr ) );

	stSockAddr.sin_family      = AF_INET;
	stSockAddr.sin_port             = htons( 53);
	stSockAddr.sin_addr.s_addr = inet_addr( pszServer );
	if ( stSockAddr.sin_addr.s_addr == INADDR_NONE )
	{
		pHostEnt = gethostbyname( pszServer );
		if ( pHostEnt )
		{
			stSockAddr.sin_addr.s_addr = *((ULONG *)pHostEnt->h_addr_list[0]);
		}
		else
		{
			return FALSE;
		} // end if
	} // end if


	  /*------------------------------------------------------------
	  *  Get a DGRAM socket
	*/

	hSocket = socket( AF_INET, SOCK_DGRAM, 0 );

	if ( hSocket == INVALID_SOCKET )
	{
		return FALSE;
	} // end if

	  /*-----------------------------------------------------------
	  * Format DNS Query
	*/

	pDNShdr = (PDNS_HDR)&( achBufOut[ 0 ] );
	pDNShdr->dns_id         = htons( 0xDEAD );
	pDNShdr->dns_flags      = htons( DNS_FLAG_RD ); // do recurse
	pDNShdr->dns_q_count    = htons( 1 );           // one query
	pDNShdr->dns_rr_count   = 0;                  // none in query
	pDNShdr->dns_auth_count = 0;                  // none in query
	pDNShdr->dns_add_count  = 0;                  // none in query

	nQueryLen = PutQName( pszQuery, &(achBufOut[ DNS_HDR_LEN ] ) );
	nQueryLen += DNS_HDR_LEN;

	achBufOut[ nQueryLen++ ]        = 0;
	achBufOut[ nQueryLen++ ]        = 0;
	achBufOut[ nQueryLen ]          = DNS_RRTYPE_MX;
	achBufOut[ nQueryLen + 1 ]      = 0;
	achBufOut[ nQueryLen + 2 ]      = DNS_RRCLASS_IN;
	achBufOut[ nQueryLen + 3 ]      = 0;

	nQueryLen += 4;

	/*-----------------------------------------------------------
	* Send DNS Query to server
	*/

	nRC = sendto( hSocket,
		achBufOut,
		nQueryLen,
		0,
		(LPSOCKADDR)&stSockAddr,
		sizeof( SOCKADDR_IN ) );

	if ( nRC == SOCKET_ERROR )
	{

		closesocket( hSocket );
		return FALSE;
	}
	else
	{

	}

//	VERIFY ( SetBlockingMode ( hSocket, TRUE ) );

	// 用 select 模型实现连接超时
	struct timeval timeout;
	fd_set r;
	FD_ZERO(&r);
	FD_SET(hSocket, &r);
	timeout.tv_sec = 5; //连接超时秒
	timeout.tv_usec =0;
	int ret = select(0, &r, 0, 0, &timeout);
	if ( ret == SOCKET_ERROR )
	{
		::closesocket(hSocket);
		hSocket = SOCKET_ERROR;
		return FALSE;
	}

	// 得到可读的数据长度
	long cmd = FIONREAD;
	u_long argp = 0;
	BOOL err = ioctlsocket ( hSocket, cmd, (u_long*)&argp );
	if ( err || argp < 1 )
	{
		::closesocket(hSocket);
		hSocket = SOCKET_ERROR;
		return FALSE;
	}

	nRC = recvfrom( hSocket,
		achBufIn,
		BUFSIZE,
		0,
		(LPSOCKADDR)&stSockAddr,
		&nAddrLen );

	if ( nRC == SOCKET_ERROR )
	{
		int nWSAErr = WSAGetLastError();

		if ( nWSAErr != WSAETIMEDOUT )
		{

			closesocket( hSocket );
			return FALSE;
		}
		else
		{

			closesocket( hSocket );
			return FALSE;
		}
	}
	else
	{
		pDNShdr = (PDNS_HDR)&( achBufIn[ 0 ] );
		p = (char *)&pDNShdr[0];
		p+=12;
		count = (int)*p;

		// Parse the Question...
		for (i = 0; i< ntohs(pDNShdr->dns_q_count); i++)
		{
			np = name;
			eom = (char *)pDNShdr+nRC;

			if ( (n = dn_expand((char *)pDNShdr, eom, p, name, 127)) < 0 )
			{
				return FALSE;

			}
			p += n + QFIXEDSZ;
		}

		for (i = 0; i< ntohs(pDNShdr->dns_rr_count); i++)
		{

			// The Question Name appears Again...
			if ((n = dn_expand((char *)pDNShdr, eom, p, name, 127)) < 0)
			{
				return FALSE;
			}
			p+=n;


			j =  _getshort(p);;  //TYPE
			p+=2;
			//printf("%s\tType:%d", name, j);

			j = _getshort(p);  //CLASS
			p+=2;
			//	printf("\tClass:%d", j);

			j = _getlong(p);  //TTL
			p+=4;
			//	printf("\tTTL:%d", j);

			j = _getshort(p);  //RDLENGTH
			p+=2;
			//	printf("\tRDLENGTH:%d", j);

			j = _getshort(p);  //N??
			p+=2;

			// This should be an MX Name...
			if ( (n = dn_expand((char *)pDNShdr, eom, p, name, 127)) < 0 )
			{
				return FALSE;
			}

			t_MXHostInfo tMXHostInfo = {0};
			strncpy ( (char*)tMXHostInfo.szMXHost, name, _countof(tMXHostInfo.szMXHost));
			tMXHostInfo.N = j;
			Ary_MXHostInfos.Add ( tMXHostInfo );
			TRACE ( _T("%s\t%d\r\n"), name, j );
			p += n;
		}
		return TRUE;


	}


	closesocket( hSocket );
	return FALSE;
}
Exemple #2
0
/*
 * Print resource record fields in human readable form.
 */
static char *
p_rr(char *cp, char *msg, FILE *file)
{
int type, class, dlen, n, c;
struct in_addr inaddr;
char *cp1, *cp2;

	if ((cp = p_cdname(cp, msg, file)) == NULL)
		return (NULL);			/* compression error */
	fprintf(file,"\n\ttype = %s", __p_type(type = _getshort(cp)));
	cp += sizeof(u_short);
	fprintf(file,", class = %s", __p_class(class = _getshort(cp)));
	cp += sizeof(u_short);
	fprintf(file,", ttl = %s", __p_time(_getlong(cp)));
	cp += sizeof(u_long);
	fprintf(file,", dlen = %d\n", dlen = _getshort(cp));
	cp += sizeof(u_short);
	cp1 = cp;
	/*
	 * Print type specific data, if appropriate
	 */
	switch (type) {
	case T_A:
		switch (class) {
		case C_IN:
		case C_HS:
			bcopy(cp, (char *)&inaddr, sizeof(inaddr));
			if (dlen == 4) {
				fprintf(file,"\tinternet address = %s\n",
					inet_ntoa(inaddr));
				cp += dlen;
			} else if (dlen == 7) {
				fprintf(file,"\tinternet address = %s",
					inet_ntoa(inaddr));
				fprintf(file,", protocol = %d", cp[4]);
				fprintf(file,", port = %d\n",
					(cp[5] << 8) + cp[6]);
				cp += dlen;
			}
			break;
		default:
			cp += dlen;
		}
		break;
	case T_CNAME:
	case T_MB:
	case T_MG:
	case T_MR:
	case T_NS:
	case T_PTR:
		fprintf(file,"\tdomain name = ");
		cp = p_cdname(cp, msg, file);
		fprintf(file,"\n");
		break;

	case T_HINFO:
		if (n = *cp++) {
			fprintf(file,"\tCPU=%.*s\n", n, cp);
			cp += n;
		}
		if (n = *cp++) {
			fprintf(file,"\tOS=%.*s\n", n, cp);
			cp += n;
		}
		break;

	case T_SOA:
		fprintf(file,"\torigin = ");
		cp = p_cdname(cp, msg, file);
		fprintf(file,"\n\tmail addr = ");
		cp = p_cdname(cp, msg, file);
		fprintf(file,"\n\tserial = %ld", _getlong(cp));
		cp += sizeof(u_long);
		fprintf(file,"\n\trefresh = %s", __p_time(_getlong(cp)));
		cp += sizeof(u_long);
		fprintf(file,"\n\tretry = %s", __p_time(_getlong(cp)));
		cp += sizeof(u_long);
		fprintf(file,"\n\texpire = %s", __p_time(_getlong(cp)));
		cp += sizeof(u_long);
		fprintf(file,"\n\tmin = %s\n", __p_time(_getlong(cp)));
		cp += sizeof(u_long);
		break;

	case T_MX:
		fprintf(file,"\tpreference = %ld,",_getshort(cp));
		cp += sizeof(u_short);
		fprintf(file," name = ");
		cp = p_cdname(cp, msg, file);
		break;

  	case T_TXT:
		(void) fputs("\t\"", file);
		cp2 = cp1 + dlen;
		while (cp < cp2) {
			if (n = (unsigned char) *cp++) {
				for (c = n; c > 0 && cp < cp2; c--)
					if (*cp == '\n') {
					    (void) putc('\\', file);
					    (void) putc(*cp++, file);
					} else
					    (void) putc(*cp++, file);
			}
		}
		(void) fputs("\"\n", file);
  		break;

	case T_MINFO:
		fprintf(file,"\trequests = ");
		cp = p_cdname(cp, msg, file);
		fprintf(file,"\n\terrors = ");
		cp = p_cdname(cp, msg, file);
		break;

	case T_UINFO:
		fprintf(file,"\t%s\n", cp);
		cp += dlen;
		break;

	case T_UID:
	case T_GID:
		if (dlen == 4) {
			fprintf(file,"\t%ld\n", _getlong(cp));
			cp += sizeof(int);
		}
		break;

	case T_WKS:
		if (dlen < sizeof(u_long) + 1)
			break;
		bcopy(cp, (char *)&inaddr, sizeof(inaddr));
		cp += sizeof(u_long);
		fprintf(file,"\tinternet address = %s, protocol = %d\n\t",
			inet_ntoa(inaddr), *cp++);
		n = 0;
		while (cp < cp1 + dlen) {
			c = *cp++;
			do {
 				if (c & 0200)
					fprintf(file," %d", n);
 				c <<= 1;
			} while (++n & 07);
		}
		putc('\n',file);
		break;

#ifdef ALLOW_T_UNSPEC
	case T_UNSPEC:
		{
			int NumBytes = 8;
			char *DataPtr;
			int i;

			if (dlen < NumBytes) NumBytes = dlen;
			fprintf(file, "\tFirst %d bytes of hex data:",
				NumBytes);
			for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
				fprintf(file, " %x", *DataPtr);
			fputs("\n", file);
			cp += dlen;
		}
		break;
#endif /* ALLOW_T_UNSPEC */

	default:
		fprintf(file,"\t???\n");
		cp += dlen;
	}
	if (cp != cp1 + dlen) {
		fprintf(file,"packet size error (%#x != %#x)\n", cp, cp1+dlen);
		cp = NULL;
	}
	fprintf(file,"\n");
	return (cp);
}
Exemple #3
0
        /*
         *  parse_rr:
         *      Extract and parse a resource record
         *
         *  returns a pointer to the RR (or NULL on failure).
         */
s_rr *
parse_rr(
        char    **cpp,
        char    *msg)
{
        s_rr            *ptr;
        int             dlen;
        union u_rdata   *rd;


                /*
                 *  Set up the RR-independent information
                 */
        if ((ptr = (s_rr *)malloc(sizeof(s_rr))) == NULL )
                return(NULL);
        if ((ptr->name = expand_cdname(cpp,msg)) == NULL ) {
                free(ptr);
                return(NULL);
        }
        ptr->type = _getshort(*cpp);
        *cpp += sizeof(u_short);
        ptr->rclass = _getshort(*cpp);
        *cpp += sizeof(u_short);
        ptr->ttl = _getlong(*cpp);
        /* Size on the network is 4 bytes so use u_int not u_long as
         * u_long is architecture dependent (e.g. 8 bytes on 64 bit). */
        *cpp += sizeof(u_int);

        dlen = _getshort(*cpp);
        ptr->dlen = dlen;
        *cpp += sizeof(u_short);

        rd = &ptr->rdata;


                /*
                 *  Handle RR-specifics
                 *
                 *    (No indication of failures here is
                 *      passed back to the calling procedure)
                 */
        switch(ptr->type) {
        case T_A:                               /* Address */
                switch (ptr->rclass) {
                case C_IN:
                        memcpy((void *)&rd->address, (void *)*cpp, sizeof(struct in_addr));
                        *cpp += dlen;
                        break;

                default:
                        /* Can't really handle this - just skip it */
                        *cpp += dlen;
                }
                break;

        case T_NS:                              /* Name Server */
        case T_MD:                              /* Mail Destination (OBS) */
        case T_MF:                              /* Mail Forwarder   (OBS) */
        case T_CNAME:                           /* Canonical Name */
                rd->string = expand_cdname(cpp, msg);
                break;

        case T_SOA:                             /* Start of Authority */
                rd->soa.mname = expand_cdname(cpp, msg);
                rd->soa.rname = expand_cdname(cpp, msg);
                rd->soa.serial = _getlong(*cpp);
                *cpp += sizeof(u_long);
                rd->soa.refresh = _getlong(*cpp);
                *cpp += sizeof(u_long);
                rd->soa.retry = _getlong(*cpp);
                *cpp += sizeof(u_long);
                rd->soa.expire = _getlong(*cpp);
                *cpp += sizeof(u_long);
                rd->soa.minimum = _getlong(*cpp);
                *cpp += sizeof(u_long);
                break;

        case T_MB:                              /* Mail Box  */
        case T_MG:                              /* Mail Group */
        case T_MR:                              /* Mail Rename */
                rd->string = expand_cdname(cpp, msg);
                break;

/* Following modification taken from VxWorks --GAT */
/* 01b,29apr97,jag Changed T_NULL to T_NULL_RR to fix conflict with loadCoffLib.h */
        case T_NULL_RR:                         /* Null RR */
                if ((rd->null.anything = (char *)malloc(dlen)) != NULL )
                        memcpy((void *)rd->null.anything, (void *)*cpp, dlen);
                rd->null.length = dlen;
                *cpp += dlen;
                break;

        case T_WKS:                             /* Well Known Services */
                memcpy((void *)&rd->wks.address, (void *)*cpp, sizeof(struct in_addr));
                *cpp += sizeof(struct in_addr);
                rd->wks.protocol = **cpp;
                (*cpp)++;
                rd->wks.maplength = dlen-(sizeof(struct in_addr) +1);
                if ((rd->wks.bitmap = (char *)malloc(rd->wks.maplength)) != NULL )
                        memcpy((void *)rd->wks.bitmap, (void *)*cpp, rd->wks.maplength);
                *cpp += rd->wks.maplength;
                break;

        case T_PTR:                             /* Domain Name Pointer */
                rd->string = expand_cdname(cpp, msg);
                break;

        case T_HINFO:                           /* Host Info */
                if (( rd->hinfo.cpu = expand_charstring(cpp, msg)) == NULL ) {
                        cpp += dlen;
                        break;
                }
                if (( rd->hinfo.os = expand_charstring(cpp, msg)) == NULL ) {
                        cpp -= (strlen(rd->hinfo.cpu) +1);
                        cpp += dlen;
                        break;
                }
                break;

        case T_MINFO:                           /* Mailbox Info */
                rd->minfo.rmailbx = expand_cdname(cpp, msg);
                rd->minfo.emailbx = expand_cdname(cpp, msg);
                break;

        case T_MX:                              /* Mail Exchanger */
                rd->mx.preference = _getshort(*cpp);
                *cpp += sizeof(u_short);
                rd->mx.exchange = expand_cdname(cpp, msg);
                break;

        case T_SRV:                             /* Service location */
                rd->srv.priority = _getshort(*cpp);
                *cpp += sizeof(u_short);
                rd->srv.weight = _getshort(*cpp);
                *cpp += sizeof(u_short);
                rd->srv.port = _getshort(*cpp);
                *cpp += sizeof(u_short);
                rd->srv.target = expand_cdname(cpp, msg);
                break;

        case T_NAPTR:                           /* Naming authority pointer */
        {
                // This is copied from the other cases, but I think that
                // all cases should be setting *cpp += dlen, not
                // cpp += dlen.
                char **cpp_end = cpp + dlen;
                rd->naptr.order = _getshort(*cpp);
                *cpp += sizeof(u_short);
                rd->naptr.preference = _getshort(*cpp);
                *cpp += sizeof(u_short);
                if (( rd->naptr.flags = expand_charstring(cpp, msg)) == NULL ) {
                        cpp = cpp_end;
                        break;
                }
                if (( rd->naptr.services = expand_charstring(cpp, msg)) == NULL ) {
                        cpp = cpp_end;
                        break;
                }
                if (( rd->naptr.regexp = expand_charstring(cpp, msg)) == NULL ) {
                        cpp = cpp_end;
                        break;
                }
                rd->naptr.replacement = expand_cdname(cpp, msg);
        }
                break;

        case T_TXT:                             /* Text string */
                rd->txt.len = **cpp;
                rd->txt.next = NULL;
                if ((rd->txt.text = expand_charstring(cpp, msg)) == NULL ) {
                        cpp += dlen;
                        break;
                }

                        /*
                         *  Multiple strings
                         *      add onto a linked list
                         */
                if ( rd->txt.len+1 < dlen ) {
                        struct s_TXT    *txtp;
                        char            **cpp2;
                        int             n;

                        n = rd->txt.len+1;
                        txtp = &(rd->txt);
                        cpp2 = cpp;
                        while ( n < dlen ) {
                                if ((txtp->next = (struct s_TXT *)malloc(sizeof(struct s_TXT))) == NULL ) {
                                        cpp += (dlen - rd->txt.len);
                                        break;
                                }
                                txtp = txtp->next;
                                txtp->len = **cpp2;
                                n += txtp->len+1;
                                txtp->next = NULL;
                                if ((txtp->text = expand_charstring(cpp2, msg)) == NULL ) {
                                        cpp += (dlen - rd->txt.len);
                                        break;
                                }
                        }
                }
                break;


                        /*
                         *  RFC 1183  Additional types
                         */
        case T_AFSDB:                           /* AFS Server */
                rd->afsdb.subtype = _getshort(*cpp);
                *cpp += sizeof(u_short);
                rd->afsdb.hostname = expand_cdname(cpp, msg);
                break;


        case T_RP:                              /* Responsible Person */
                rd->rp.mbox_dname = expand_cdname(cpp, msg);
                rd->rp.txt_dname = expand_cdname(cpp, msg);
                break;

        case T_X25:                             /* X25 Address */
                rd->string = expand_charstring(cpp, msg);
                break;

        case T_ISDN:                            /* ISDN Address */
                if ( **cpp == dlen ) {
                        rd->isdn.address = expand_charstring(cpp, msg);
                        rd->isdn.sa = NULL;
                }
                else {
                        rd->isdn.address = expand_charstring(cpp, msg);
                        rd->isdn.sa = expand_charstring(cpp, msg);
                }
                break;

        case T_RT:                              /* Route Through */
                rd->rt.preference = _getshort(*cpp);
                *cpp += sizeof(u_short);
                rd->rt.int_host = expand_cdname(cpp, msg);
                break;

                        /*
                         *  Additional Non-standard types
                         */
        case T_UINFO:                           /* User (finger) info */
                if ((rd->string = (char *)malloc(dlen+1)) != NULL ) {
                        memcpy((void *)rd->string, (void *)*cpp, dlen);
                        rd->string[dlen] = '\0';
                }
                *cpp += dlen;
                break;

        case T_UID:                             /* User ID */
        case T_GID:                             /* Group ID */
                rd->number = _getlong(*cpp);
                *cpp += sizeof(u_long);
                break;

        case T_UNSPEC:                          /* Unspecified info */
        default:                                /* Unrecognised */
                if ((rd->string = (char *)malloc(dlen+1)) != NULL )
                        memcpy((void *)rd->string, (void *)*cpp, dlen);
                *cpp += dlen;
                break;

        }


        return(ptr);
}