OSDN Git Service

Fixed Issue #104: Doubleclicking changed submodule dir in Check For Modifications...
[tortoisegit/TortoiseGitJp.git] / src / Utils / dnsmx.cpp
1 #include "stdafx.h"\r
2 #include "dnsmx.h"\r
3 \r
4 #define ASCII_NULL              '\0'\r
5 #define MAXHOSTNAME             256\r
6 #define BUFSIZE                 2048\r
7 \r
8 // #pragma comment ( lib, "ws2_32.lib" )\r
9 \r
10 /* DNS Header Format\r
11 *\r
12 * All DNS Message Formats have basically the same structure\r
13 *   (note that an RR (DNS Resource Record) is described in\r
14 *   the other structures that follow this header description):\r
15 *\r
16 *        +--------------------------------+\r
17 *        | DNS Header: <defined below>    |\r
18 *        +--------------------------------+\r
19 *        | Question:   type of query      |\r
20 *        |   QNAME:    <see below>        |\r
21 *        |   QTYPE:    2-octet RR type    |\r
22 *        |   QCLASS:   2-octet RR class   |\r
23 *        +--------------------------------+\r
24 *        | Answer:     RR answer to query |\r
25 *        +--------------------------------+\r
26 *        | Authority:  RR for name server |\r
27 *        +--------------------------------+\r
28 *        | Additional: RR(s) other info   |\r
29 *        +--------------------------------+\r
30 *\r
31 *  QNAME is a variable length field where each portion of the\r
32 *   "dotted-notation" domain name is replaced by the number of\r
33 *   octets to follow.  So, for example, the domain name\r
34 *   "www.sockets.com" is represented by:\r
35 *\r
36 *         0                   1\r
37 *   octet 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6\r
38 *        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
39 *        |3|w|w|w|7|s|o|c|k|e|t|s|3|c|o|m|0|\r
40 *        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
41 *\r
42 * NOTE: The last section, "Additional," often contains records\r
43 *  for queries the server anticipates will be sent (to reduce\r
44 *  traffic).  For example, a response to an MX query, would\r
45 *  usually have the A record in additional information.\r
46 */\r
47 typedef struct dns_hdr\r
48 {\r
49         USHORT dns_id;          /* client query ID number */\r
50         USHORT dns_flags;       /* qualify contents <see below> */\r
51         USHORT dns_q_count;     /* number of questions */\r
52         USHORT dns_rr_count;    /* number of answer RRs */\r
53         USHORT dns_auth_count;  /* number of authority RRs */\r
54         USHORT dns_add_count;   /* number of additional RRs */\r
55 } DNS_HDR, *PDNS_HDR, FAR *LPDNS_HDR;\r
56 \r
57 #define DNS_HDR_LEN 12\r
58 \r
59 /* DNS Flags field values\r
60 *\r
61 *  bits:  0     1-4     5    6    7    8     9-11    12-15\r
62 *       +----+--------+----+----+----+----+--------+-------+\r
63 *       | QR | opcode | AA | TC | RD | RA | <zero> | rcode |\r
64 *       +----+--------+----+----+----+----+--------+-------+\r
65 *\r
66 *  QR:     0 for query, and 1 for response\r
67 *  opcode: type of query (0: standard, and 1: inverse query)\r
68 *  AA:     set if answer from domain authority\r
69 *  TC:     set if message had to be truncated\r
70 *  RD:     set if recursive query desired\r
71 *  RA:     set if recursion is available from server\r
72 *  <zero>: reserved field\r
73 *  rcode:  resulting error non-zero value from authoritative\r
74 *           server (0: no error, 3: name does not exist)\r
75 */\r
76 #define DNS_FLAG_QR 0x8SpeedPostEmail\r
77 #define DNS_FLAG_AA 0x0400\r
78 #define DNS_FLAG_TC 0x0200\r
79 #define DNS_FLAG_RD 0x0100\r
80 #define DNS_FLAG_RA 0x0080\r
81 #define DNS_RCODE_MASK  0xSpeedPostEmailF\r
82 #define DNS_OPCODE_MASK 0x7800\r
83 \r
84 /* DNS Opcode (type of query) */\r
85 char *DNS_Opcode[] =\r
86 {\r
87         "Standard Query",         /* 0: QUERY  */\r
88         "Inverse Query",          /* 1: IQUERY */\r
89         "Server Status Request",  /* 2: STATUS */\r
90 };\r
91 \r
92 /* DNS Response Codes (error descriptions) */\r
93 char *DNS_RCode[] =\r
94 {\r
95         "No Error",        /* 0: ok */\r
96         "Format Error",    /* 1: bad query */\r
97         "Server Failure",  /* 2: server is hosed */\r
98         "Name Error",      /* 3: name doesn't exist (authoritative) */\r
99         "Not Implemented", /* 4: server doesn't support query */\r
100         "Refused"          /* 5: server refused request */\r
101 };\r
102 \r
103 /* DNS Generic Resource Record format (from RFC 1034 and 1035)\r
104 *\r
105 *  NOTE: The first field in the DNS RR Record header is always\r
106 *   the domain name in QNAME format (see earlier description)\r
107 */\r
108 typedef struct dns_rr_hdr\r
109 {\r
110         USHORT rr_type;                /* RR type code (e.g. A, MX, NS, etc.) */\r
111         USHORT rr_class;               /* RR class code (IN for Internet) */\r
112         ULONG  rr_ttl;         /* Time-to-live for resource */\r
113         USHORT rr_rdlength;    /* length of RDATA field (in octets) */\r
114         USHORT rr_rdata;               /* (fieldname used as a ptr) */\r
115 } DNS_RR_HDR, *PDNS_RR_HDR, FAR *LPDNS_RR_HDR;\r
116 \r
117 #define DNS_RR_HDR_LEN 12\r
118 \r
119 /* DNS Resource Record RDATA Field Descriptions\r
120 *\r
121 *  The RDATA field contains resource record data associated\r
122 *  with the specified domain name\r
123 *\r
124 *  Type Value Description\r
125 *  -------------------------------------------------------------\r
126 *   A     1   IP Address (32-bit IP version 4)\r
127 *   NS    2   Name server QNAME (for referrals & recursive queries)\r
128 *   CNAME 5   Canonical name of an alias (in QNAME format)\r
129 *   SOA   6   Start of Zone Transfer (see definition below)\r
130 *   WKS   11  Well-known services (see definition below)\r
131 *   PTR   12  QNAME pointing to other nodes (e.g. in inverse lookups)\r
132 *   HINFO 13  Host Information (CPU string, then OS string)\r
133 *   MX    15  Mail server preference and QNAME (see below)\r
134 */\r
135 char *DNS_RR_Type [] =\r
136 {\r
137         "<invalid>",\r
138         "A",     // 1:  Host Address\r
139         "NS",    // 2:  Authoritative Name Server\r
140         "MD",    // 3:  <obsolete>\r
141         "MF",    // 4:  <obsolete>\r
142         "CNAME", // 5:  The true, canonical name for an alias\r
143         "SOA",   // 6:  Start-of-Zone of authority record\r
144         "MB",    // 7:  Mailbox   <experimental>\r
145         "MG",    // 8:  Mailgroup <experimental>\r
146         "MR",    // 9:  Mail Rename Domain Name <experimental>\r
147         "NULL",  // 10: NULL Resource Record    <experimental>\r
148         "WKS",   // 11: Well-known service description\r
149         "PTR",   // 12: Domain Name Pointer\r
150         "HINFO", // 13: Host Information\r
151         "MINFO", // 14: Mailbox or Mail List information\r
152         "MX",    // 15: Mail Exchange (from RFC 974)\r
153         "TXT"    // 16: Text String\r
154 };\r
155 \r
156 #define DNS_RRTYPE_A     1\r
157 #define DNS_RRTYPE_NS    2\r
158 #define DNS_RRTYPE_CNAME 5\r
159 #define DNS_RRTYPE_SOA   6\r
160 #define DNS_RRTYPE_WKS   11\r
161 #define DNS_RRTYPE_PTR   12\r
162 #define DNS_RRTYPE_HINFO 13\r
163 #define DNS_RRTYPE_MX    15\r
164 \r
165 /* DNS Resource Record Classes:\r
166 *\r
167 * One almost always uses Internet RR Class (also note: the\r
168 *  class value 255 denotes a wildcard, all classes)\r
169 */\r
170 char *DNS_RR_Class [] =\r
171 {\r
172         "<invalid>",\r
173         "IN",    // 1: Internet - used for most queries!\r
174         "CS",    // 2: CSNET <obsolete>\r
175         "CH",    // 3: CHAOS Net\r
176         "HS"     // 4: Hesiod\r
177 };\r
178 \r
179 #define DNS_RRCLASS_IN  1\r
180 #define DNS_RRCLASS_CS  2\r
181 #define DNS_RRCLASS_CH  3\r
182 #define DNS_RRCLASS_HS  4\r
183 \r
184 /* DNS SOA Resource Data Field\r
185 *\r
186 *  NOTE: First two fields not shown here.  They are:\r
187 *    MNAME: QNAME of primary server for this zone\r
188 *    RNAME: QNAME of mailbox of admin for this zone\r
189 */\r
190 typedef struct dns_rdata_soa\r
191 {\r
192         ULONG soa_serial;  /* data version for this zone */\r
193         ULONG soa_refresh; /* time-to-live for data (in seconds) */\r
194         ULONG soa_retry;   /* time between retrieds (in seconds) */\r
195         ULONG soa_expire;  /* time until zone not auth (in seconds) */\r
196         ULONG soa_minimum; /* default TTL for RRs (in seconds) */\r
197 } DNS_RDATA_SOA, PDNS_RDATA_SOA, FAR *LPDNS_RDATA_SOA;\r
198 \r
199 #define DNS_SOA_LEN 20\r
200 \r
201 /* DNS WKS Resource Data Field (RFC 1035)\r
202 *\r
203 *  NOTE: The bitmap field is variable length, with as many\r
204 *   octets necessary to indicate the bit field for the port\r
205 *   number.\r
206 */\r
207 typedef struct dns_rdata_wks\r
208 {\r
209         ULONG wks_addr;      /* IPv4 address */\r
210         UCHAR wks_protocol;  /* Protocol (e.g. 6=TCP, 17=UDP) */\r
211         UCHAR wks_bitmap;    /* e.g. bit 26 = SMTP (port 25) */\r
212 } DNS_RDATA_WKS, *PDNS_RDATA_WKS, FAR *LPDNS_RDATA_WKS;\r
213 \r
214 #define DNS_WKX_LEN 6\r
215 \r
216 /* DNS MX Resource Data Field\r
217 */\r
218 typedef struct dns_rdata_mx\r
219 {\r
220         USHORT mx_pref;     /* Preference value */\r
221         USHORT mx_xchange;  /* QNAME (field used as ptr) */\r
222 } DNS_RDATA_MX, *PDNS_RDATA_MX, FAR *LPDNS_RDATA_MX;\r
223 \r
224 #define DNS_MX_LEN 4\r
225 \r
226 /* Variables used for DNS Header construction & parsing */\r
227 PDNS_HDR       pDNShdr;\r
228 PDNS_RR_HDR    pDNS_RR;\r
229 PDNS_RDATA_SOA pDNS_SOA;\r
230 PDNS_RDATA_WKS pDNS_WKS;\r
231 PDNS_RDATA_MX  pDNS_MX;\r
232 \r
233 /* For Parsing Names in a Reply */\r
234 #define INDIR_MASK      0xc0\r
235 \r
236 /* Number of bytes of fixed size data in query structure */\r
237 #define QFIXEDSZ        4\r
238 /* number of bytes of fixed size data in resource record */\r
239 #define RRFIXEDSZ       10\r
240 \r
241 /* Processor Types */\r
242 char *aszProcessor[] =\r
243 {\r
244         "",\r
245         "",\r
246         "",\r
247         "Intel 386",\r
248         "Intel 486",\r
249         "Intel Pentium"\r
250 };\r
251 \r
252 \r
253 void GetQName( char FAR *pszHostName, char FAR *pQName );\r
254 void PrintQName( char FAR *pQName );\r
255 int  PutQName( char FAR *pszHostName, char FAR *pQName );\r
256 \r
257 USHORT _getshort(char *msgp)\r
258 {\r
259         register UCHAR *p = (UCHAR *) msgp;\r
260         register USHORT u;\r
261         \r
262         u = *p++ << 8;\r
263         return ((USHORT)(u | *p));\r
264 }\r
265 \r
266 ULONG _getlong(char *msgp)\r
267 {\r
268         register UCHAR *p = (UCHAR *) msgp;\r
269         register ULONG u;\r
270         \r
271         u = *p++; u <<= 8;\r
272         u |= *p++; u <<= 8;\r
273         u |= *p++; u <<= 8;\r
274         return (u | *p);\r
275 }\r
276 \r
277 \r
278 /*\r
279 * Expand compressed domain name 'comp_dn' to full domain name.\r
280 * 'msg' is a pointer to the begining of the message,\r
281 * 'eomorig' points to the first location after the message,\r
282 * 'exp_dn' is a pointer to a buffer of size 'length' for the result.\r
283 * Return size of compressed name or -1 if there was an error.\r
284 */\r
285 int dn_expand(char *msg,char  *eomorig,char *comp_dn,char *exp_dn,int length)\r
286 {\r
287         register char *cp, *dn;\r
288         register int n, c;\r
289         char *eom;\r
290         int len = -1, checked = 0;\r
291         \r
292         dn = exp_dn;\r
293         cp = comp_dn;\r
294         eom = exp_dn + length - 1;\r
295         /*\r
296         * fetch next label in domain name\r
297         */\r
298         while (n = *cp++) {\r
299         /*\r
300         * Check for indirection\r
301                 */\r
302                 switch (n & INDIR_MASK) {\r
303                 case 0:\r
304                         if (dn != exp_dn) {\r
305                                 if (dn >= eom)\r
306                                         return (-1);\r
307                                 *dn++ = '.';\r
308                         }\r
309                         if (dn+n >= eom)\r
310                                 return (-1);\r
311                         checked += n + 1;\r
312                         while (--n >= 0) {\r
313                                 if ((c = *cp++) == '.') {\r
314                                         if (dn+n+1 >= eom)\r
315                                                 return (-1);\r
316                                         *dn++ = '\\';\r
317                                 }\r
318                                 *dn++ = c;\r
319                                 if (cp >= eomorig)      /* out of range */\r
320                                         return(-1);\r
321                         }\r
322                         break;\r
323                         \r
324                 case INDIR_MASK:\r
325                         if (len < 0)\r
326                                 len = cp - comp_dn + 1;\r
327                         cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));\r
328                         if (cp < msg || cp >= eomorig)  /* out of range */\r
329                                 return(-1);\r
330                         checked += 2;\r
331                         /*\r
332                         * Check for loops in the compressed name;\r
333                         * if we've looked at the whole message,\r
334                         * there must be a loop.\r
335                         */\r
336                         if (checked >= eomorig - msg)\r
337                                 return (-1);\r
338                         break;\r
339                         \r
340                 default:\r
341                         return (-1);                    /* flag error */\r
342                 }\r
343         }\r
344         *dn = '\0';\r
345         if (len < 0)\r
346                 len = cp - comp_dn;\r
347         return (len);\r
348 }\r
349 \r
350 /*\r
351 * Skip over a compressed domain name. Return the size or -1.\r
352 */\r
353 int dn_skipname(UCHAR *comp_dn,  UCHAR *eom)\r
354 {\r
355         register UCHAR *cp;\r
356         register int n;\r
357         \r
358         cp = comp_dn;\r
359         while (cp < eom && (n = *cp++)) {\r
360         /*\r
361         * check for indirection\r
362                 */\r
363                 switch (n & INDIR_MASK) {\r
364                 case 0:         /* normal case, n == len */\r
365                         cp += n;\r
366                         continue;\r
367                 default:        /* illegal type */\r
368                         return (-1);\r
369                 case INDIR_MASK:        /* indirection */\r
370                         cp++;\r
371                 }\r
372                 break;\r
373         }\r
374         return (cp - comp_dn);\r
375 }\r
376 \r
377 //\r
378 // ÉèÖÃ×èÈûģʽ\r
379 //\r
380 BOOL SetBlockingMode ( SOCKET hSocket, BOOL bNonblockingEnable )\r
381 {\r
382         if ( hSocket == INVALID_SOCKET || hSocket == 0 )\r
383         {\r
384                 return FALSE;\r
385         }\r
386         \r
387         long cmd = FIONBIO;\r
388         long zero = 0;\r
389         u_long* argp = NULL;\r
390         if ( bNonblockingEnable )\r
391                 argp = (u_long*)&cmd;\r
392         else\r
393                 argp = (u_long*)&zero;\r
394         int err = ioctlsocket ( hSocket, cmd, argp );\r
395         if ( err != 0 )\r
396         {\r
397                 return FALSE;\r
398         }\r
399         \r
400         return TRUE;\r
401 }\r
402 \r
403 \r
404 BOOL GetMX (\r
405                         char *pszQuery,\r
406                         char *pszServer,\r
407                         OUT t_Ary_MXHostInfos &Ary_MXHostInfos\r
408                         )\r
409 {\r
410         SOCKET                  hSocket;\r
411         SOCKADDR_IN             stSockAddr;                     // socket address structures\r
412         int                             nAddrLen = sizeof( SOCKADDR_IN );\r
413         \r
414         HOSTENT                 *pHostEnt;\r
415         \r
416         char                            achBufOut[ BUFSIZE ] = { 0 };\r
417         char                            achBufIn[ BUFSIZE ] = { 0 };\r
418         int                             nQueryLen = 0;\r
419         int                             nRC;\r
420         \r
421         char *p, *np, name[128], *eom;\r
422         int count, j, i, n;\r
423         \r
424         memset( &stSockAddr, ASCII_NULL, sizeof( stSockAddr ) );\r
425         \r
426         stSockAddr.sin_family      = AF_INET;\r
427         stSockAddr.sin_port             = htons( 53);\r
428         stSockAddr.sin_addr.s_addr = inet_addr( pszServer );\r
429         if ( stSockAddr.sin_addr.s_addr == INADDR_NONE )\r
430         {\r
431                 pHostEnt = gethostbyname( pszServer );\r
432                 if ( pHostEnt )\r
433                 {\r
434                         stSockAddr.sin_addr.s_addr = *((ULONG *)pHostEnt->h_addr_list[0]);\r
435                 }\r
436                 else\r
437                 {\r
438                         return FALSE;\r
439                 } // end if\r
440         } // end if\r
441         \r
442         \r
443           /*------------------------------------------------------------\r
444           *  Get a DGRAM socket\r
445         */\r
446         \r
447         hSocket = socket( AF_INET, SOCK_DGRAM, 0 );\r
448         \r
449         if ( hSocket == INVALID_SOCKET )\r
450         {\r
451                 return FALSE;\r
452         } // end if\r
453 \r
454           /*-----------------------------------------------------------\r
455           * Format DNS Query\r
456         */\r
457         \r
458         pDNShdr = (PDNS_HDR)&( achBufOut[ 0 ] );\r
459         pDNShdr->dns_id         = htons( 0xDEAD );\r
460         pDNShdr->dns_flags      = htons( DNS_FLAG_RD ); // do recurse\r
461         pDNShdr->dns_q_count    = htons( 1 );           // one query\r
462         pDNShdr->dns_rr_count   = 0;                  // none in query\r
463         pDNShdr->dns_auth_count = 0;                  // none in query\r
464         pDNShdr->dns_add_count  = 0;                  // none in query\r
465         \r
466         nQueryLen = PutQName( pszQuery, &(achBufOut[ DNS_HDR_LEN ] ) );\r
467         nQueryLen += DNS_HDR_LEN;\r
468         \r
469         achBufOut[ nQueryLen++ ]        = 0;\r
470         achBufOut[ nQueryLen++ ]        = 0;    \r
471         achBufOut[ nQueryLen ]          = DNS_RRTYPE_MX;\r
472         achBufOut[ nQueryLen + 1 ]      = 0;\r
473         achBufOut[ nQueryLen + 2 ]      = DNS_RRCLASS_IN;\r
474         achBufOut[ nQueryLen + 3 ]      = 0;\r
475         \r
476         nQueryLen += 4;\r
477         \r
478         /*-----------------------------------------------------------\r
479         * Send DNS Query to server\r
480         */\r
481         \r
482         nRC = sendto( hSocket,\r
483                 achBufOut,\r
484                 nQueryLen,\r
485                 0,\r
486                 (LPSOCKADDR)&stSockAddr,\r
487                 sizeof( SOCKADDR_IN ) );\r
488         \r
489         if ( nRC == SOCKET_ERROR )\r
490         {\r
491                 \r
492                 closesocket( hSocket );\r
493                 return FALSE;\r
494         }\r
495         else\r
496         {\r
497                 \r
498         }\r
499         \r
500 //      VERIFY ( SetBlockingMode ( hSocket, TRUE ) );\r
501 \r
502         // Óàselect Ä£ÐÍʵÏÖÁ¬½Ó³¬Ê±\r
503         struct timeval timeout;\r
504         fd_set r;\r
505         FD_ZERO(&r);\r
506         FD_SET(hSocket, &r);\r
507         timeout.tv_sec = 5; //Á¬½Ó³¬Ê±Ãë\r
508         timeout.tv_usec =0;\r
509         int ret = select(0, &r, 0, 0, &timeout);\r
510         if ( ret == SOCKET_ERROR )\r
511         {\r
512                 ::closesocket(hSocket);\r
513                 hSocket = SOCKET_ERROR;\r
514                 return FALSE;\r
515         }\r
516 \r
517         // µÃµ½¿É¶ÁµÄÊý¾Ý³¤¶È\r
518         long cmd = FIONREAD;\r
519         u_long argp = 0;\r
520         BOOL err = ioctlsocket ( hSocket, cmd, (u_long*)&argp );\r
521         if ( err || argp < 1 )\r
522         {\r
523                 ::closesocket(hSocket);\r
524                 hSocket = SOCKET_ERROR;\r
525                 return FALSE;\r
526         }\r
527 \r
528         nRC = recvfrom( hSocket,\r
529                 achBufIn,\r
530                 BUFSIZE,\r
531                 0,\r
532                 (LPSOCKADDR)&stSockAddr,\r
533                 &nAddrLen );\r
534         \r
535         if ( nRC == SOCKET_ERROR )\r
536         {\r
537                 int nWSAErr = WSAGetLastError();\r
538                 \r
539                 if ( nWSAErr != WSAETIMEDOUT )\r
540                 {\r
541                         \r
542                         closesocket( hSocket );\r
543                         return FALSE;\r
544                 }\r
545                 else\r
546                 {\r
547                         \r
548                         closesocket( hSocket );\r
549                         return FALSE;\r
550                 }\r
551         }\r
552         else\r
553         {\r
554                 pDNShdr = (PDNS_HDR)&( achBufIn[ 0 ] );\r
555                 p = (char *)&pDNShdr[0];\r
556                 p+=12;\r
557                 count = (int)*p;\r
558                 \r
559                 // Parse the Question...\r
560                 for (i = 0; i< ntohs(pDNShdr->dns_q_count); i++)\r
561                 {\r
562                         np = name;\r
563                         eom = (char *)pDNShdr+nRC;\r
564                         \r
565                         if ( (n = dn_expand((char *)pDNShdr, eom, p, name, 127)) < 0 )\r
566                         {\r
567                                 return FALSE;\r
568                                 \r
569                         }\r
570                         p += n + QFIXEDSZ;\r
571                 }               \r
572                 \r
573                 for (i = 0; i< ntohs(pDNShdr->dns_rr_count); i++)\r
574                 {\r
575                         \r
576                         // The Question Name appears Again...\r
577                         if ((n = dn_expand((char *)pDNShdr, eom, p, name, 127)) < 0)\r
578                         {\r
579                                 return FALSE;\r
580                         }\r
581                         p+=n;\r
582                         \r
583                         \r
584                         j =  _getshort(p);;  //TYPE\r
585                         p+=2;\r
586                         //printf("%s\tType:%d", name, j);\r
587                         \r
588                         j = _getshort(p);  //CLASS\r
589                         p+=2;\r
590                         //      printf("\tClass:%d", j);\r
591                         \r
592                         j = _getlong(p);  //TTL\r
593                         p+=4;\r
594                         //      printf("\tTTL:%d", j);\r
595                         \r
596                         j = _getshort(p);  //RDLENGTH\r
597                         p+=2;\r
598                         //      printf("\tRDLENGTH:%d", j);\r
599                         \r
600                         j = _getshort(p);  //N??\r
601                         p+=2;\r
602                         \r
603                         // This should be an MX Name...\r
604                         if ( (n = dn_expand((char *)pDNShdr, eom, p, name, 127)) < 0 )\r
605                         {\r
606                                 return FALSE;\r
607                         }\r
608 \r
609                         t_MXHostInfo tMXHostInfo = {0};\r
610                         strncpy ( (char*)tMXHostInfo.szMXHost, name, sizeof(tMXHostInfo.szMXHost)/sizeof(tMXHostInfo.szMXHost[0]) );\r
611                         tMXHostInfo.N = j;\r
612                         Ary_MXHostInfos.Add ( tMXHostInfo );\r
613                         TRACE ( _T("%s\t%d\r\n"), name, j );\r
614                         p += n;\r
615                 }\r
616                 return TRUE;\r
617                 \r
618                 \r
619         }\r
620         \r
621         \r
622         closesocket( hSocket );\r
623         return FALSE;\r
624 }\r
625 \r
626 \r
627 void GetQName( char FAR *pszHostName, char FAR *pQName )\r
628 {\r
629         \r
630         int i, j, k;\r
631         \r
632         for ( i = 0; i < BUFSIZE; i++ )\r
633         {\r
634                 j = *pQName;\r
635                 \r
636                 if ( j == 0 )\r
637                         break;\r
638                 \r
639                 for ( k = 1; k <= j; k++ )\r
640                 {\r
641                         *pszHostName++ = *( pQName + i + k );\r
642                 } // end for loop\r
643         } // end for loop\r
644         \r
645         *pszHostName++ = ASCII_NULL;\r
646 } /* end GetQName() */\r
647 \r
648 \r
649 void PrintQName( char FAR *pQName )\r
650 {\r
651         int i, j, k;\r
652         \r
653         for ( i = 0; i < BUFSIZE; i++ )\r
654         {\r
655                 j = *pQName;\r
656                 \r
657                 if ( j == 0 )\r
658                         break;\r
659                 \r
660                 for ( k = 1; k <= j; k++ )\r
661                 {\r
662                         //printf( "%c", *( pQName + i + k ) );\r
663                 } // end for loop\r
664         } // end for loop\r
665 } /* end PrintQName() */\r
666 \r
667 \r
668 int PutQName( char FAR *pszHostName, char FAR *pQName )\r
669 {\r
670         int     i;\r
671         int     j = 0;\r
672         int     k = 0;\r
673         \r
674         \r
675         for ( i = 0; *( pszHostName + i ); i++ )\r
676         {\r
677                 char c = *( pszHostName + i );   /* get next character */\r
678                 \r
679                 \r
680                 if ( c == '.' )\r
681                 {\r
682                         /* dot encountered, fill in previous length */\r
683                         *( pQName + j ) = k;\r
684                         \r
685                         k = 0;      /* reset segment length */\r
686                         j = i + 1;    /* set index to next counter */\r
687                 }\r
688                 else\r
689                 {\r
690                         *( pQName + i + 1 ) = c;  /* assign to QName */\r
691                         k++;                /* inc count of seg chars */\r
692                 } // end if\r
693         } // end for loop\r
694         \r
695         *(pQName + j )                  = k;   /* count for final segment */\r
696         *(pQName + i + 1 )      = 0;   /* count for trailing NULL segment is 0 */\r
697         \r
698         return ( i + 1 );        /* return total length of QName */\r
699 }\r
700 \r
701 //\r
702 // ³¢ÊÔËùÓеÄDNSÀ´²éѯÓʾַþÎñÆ÷µØÖ·\r
703 //\r
704 BOOL GetMX (\r
705                         char *pszQuery,                                                 // Òª²éѯµÄÓòÃû\r
706                         OUT t_Ary_MXHostInfos &Ary_MXHostInfos  // Êä³ö Mail Exchange Ö÷»úÃû\r
707                         )\r
708 {\r
709         CNetAdapterInfo m_NetAdapterInfo;\r
710         m_NetAdapterInfo.Refresh ();\r
711         int nNetAdapterCount = m_NetAdapterInfo.GetNetCardCount();\r
712         for ( int i=0; i<nNetAdapterCount; i++ )\r
713         {\r
714                 COneNetAdapterInfo *pOneNetAdapterInfo = m_NetAdapterInfo.Get_OneNetAdapterInfo ( i );\r
715                 if ( pOneNetAdapterInfo )\r
716                 {\r
717                         int nDNSCount = pOneNetAdapterInfo->Get_DNSCount ();\r
718                         for ( int j=0; j<nDNSCount; j++ )\r
719                         {\r
720                                 CString csDNS = pOneNetAdapterInfo->Get_DNSAddr ( j );\r
721                                 if ( GetMX ( pszQuery, csDNS.GetBuffer(0), Ary_MXHostInfos ) )\r
722                                 {\r
723                                         return TRUE;\r
724                                 }\r
725                         }\r
726                 }\r
727         }\r
728 \r
729         return FALSE;\r
730 }