|
|
1.1 root 1: /* mxlookup.c */
2:
3: /* Synchronet DNS MX-record lookup routines */
4:
5: /* $Id: mxlookup.c,v 1.10 2000/11/11 01:07:26 rswindell Exp $ */
6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: /* Platform-specific */
39: #ifdef _WIN32
40: #include <windows.h> /* avoid DWORD conflict */
41: #endif
42:
43: /* ANSI */
44: #include <stdio.h>
45: #include <string.h> /* strchr */
46:
47: /* Synchronet-specific */
48: #include "gen_defs.h"
49: #include "sbbsinet.h"
50: #include "smbdefs.h" /* _PACK */
51:
52: #ifdef _WIN32
53: #pragma pack(push)
54: #pragma pack(1)
55: #endif
56:
57: typedef struct _PACK {
58: WORD length; /* This field included when using TCP only */
59: WORD id;
60: WORD bitfields;
61: WORD qdcount;
62: WORD ancount;
63: WORD nscount;
64: WORD arcount;
65: } dns_msghdr_t;
66:
67: typedef struct _PACK {
68: WORD type;
69: WORD class;
70: } dns_query_t;
71:
72: typedef struct _PACK {
73: WORD type;
74: WORD class;
75: DWORD ttl;
76: WORD length;
77: } dns_rr_t;
78:
79: #ifdef _WIN32
80: #pragma pack(pop) /* original packing */
81: #endif
82:
83: #define DNS_QR (1<<15) // Query/Response (0=Query, 1=Response)
84: #define DNS_AA (1<<10) // Authoritavie Answer
85: #define DNS_TC (1<<9) // Truncation due to length limits
86: #define DNS_RD (1<<8) // Recursion Query desired
87: #define DNS_RA (1<<7) // Recursion Query available
88:
89: #define DNS_RCODE_MASK 0x000f // Response code bit field
90: enum {
91: DNS_RCODE_OK // No error condition
92: ,DNS_RCODE_FMT // Format error
93: ,DNS_RCODE_SERVER // Server Failure
94: ,DNS_RCODE_NAME // Name error
95: ,DNS_RCODE_NI // Not Implemented
96: ,DNS_RCODE_REFUSE // Refused
97: };
98:
99: #define DNS_A 1 // Host address Query Type
100: #define DNS_MX 15 // Mail Exchange Query Type
101: #define DNS_IN 1 // Internet Query Class
102:
103: int mail_open_socket(int type);
104: int mail_close_socket(SOCKET sock);
105:
106: int dns_name(char* name, char* srcbuf, char* p)
107: {
108: char* np=name;
109: int len=0;
110: int plen;
111: WORD offset;
112:
113: while(p && *p) {
114: if(np!=name)
115: *(np++)='.'; // insert between.names
116: if(((*p)&0xC0)==0xC0) { // Compresssed name
117: (*p)&=~0xC0;
118: offset=ntohs(*(WORD*)p);
119: (*p)|=0xC0;
120: dns_name(np, srcbuf,srcbuf+offset);
121: len+=2;
122: return(len); //continue;
123: }
124: plen=(*p);
125: memcpy(np,p+1,plen); // don't copy length byte
126: np+=plen;
127: plen++; // Increment past length byte
128: p+=plen;
129: len+=plen;
130: }
131: *np=0;
132: return(len+1);
133: }
134:
135: int dns_getmx(char* name, char* mx, char* mx2, DWORD intf, DWORD ip_addr, BOOL use_tcp)
136: {
137: char* p;
138: char* tp;
139: char hostname[128];
140: BYTE namelen;
141: WORD pref;
142: WORD highpref=0xffff;
143: int i;
144: int rd;
145: int len;
146: int offset;
147: int result;
148: int answers;
149: SOCKET sock;
150: SOCKADDR_IN addr={0};
151: BYTE msg[512];
152: dns_msghdr_t msghdr;
153: dns_query_t query;
154: dns_rr_t* rr;
155:
156: mx[0]=0;
157: mx2[0]=0;
158:
159: if(use_tcp)
160: sock = mail_open_socket(SOCK_STREAM);
161: else
162: sock = mail_open_socket(SOCK_DGRAM);
163:
164: if (sock == INVALID_SOCKET)
165: return(ERROR_VALUE);
166:
167: addr.sin_addr.s_addr = htonl(intf);
168: addr.sin_family = AF_INET;
169: addr.sin_port = htons (0);
170:
171: result = bind (sock, (struct sockaddr *) &addr,sizeof (addr));
172:
173: if (result != 0) {
174: mail_close_socket(sock);
175: return(ERROR_VALUE);
176: }
177:
178: memset(&addr,0,sizeof(addr));
179: addr.sin_addr.s_addr = ip_addr;
180: addr.sin_family = AF_INET;
181: addr.sin_port = htons(53);
182:
183: if((result=connect(sock, (struct sockaddr *)&addr, sizeof(addr)))!=0) {
184: mail_close_socket(sock);
185: return(ERROR_VALUE);
186: }
187:
188: memset(&msghdr,0,sizeof(msghdr));
189:
190: len=sizeof(msghdr)+strlen(name)+sizeof(query);
191: msghdr.length=htons((WORD)len);
192:
193: msghdr.bitfields=htons(DNS_RD);
194: msghdr.qdcount=htons(1);
195: query.type=htons(DNS_MX);
196: query.class=htons(DNS_IN);
197: /* Build the message */
198: memcpy(msg,&msghdr,sizeof(msghdr));
199: len=sizeof(msghdr);
200: for(p=name;*p;p+=namelen) {
201: if(*p=='.')
202: p++;
203: tp=strchr(p,'.');
204: if(tp)
205: namelen=(BYTE)(tp-p);
206: else
207: namelen=(BYTE)strlen(p);
208: *(msg+len)=namelen;
209: len++;
210: memcpy(msg+len,p,namelen);
211: len+=namelen;
212: }
213: *(msg+len)=0; // terminator
214: len++;
215: memcpy(msg+len,&query,sizeof(query));
216: len+=sizeof(query);
217:
218: if(use_tcp)
219: offset=0;
220: else { /* UDP */
221: offset=sizeof(msghdr.length);
222: len-=sizeof(msghdr.length);
223: }
224:
225: send(sock,msg+offset,len,0);
226: rd=recv(sock,msg,sizeof(msg),0);
227: if(rd>0) {
228:
229: memcpy(&msghdr,msg+offset,sizeof(msghdr)-offset);
230:
231: if(!use_tcp)
232: offset=0;
233: else
234: offset=sizeof(msghdr.length);
235:
236: answers=ntohs(msghdr.ancount);
237: p=msg+len; /* Skip the header and question portion */
238:
239: for(i=0;i<answers;i++) {
240: p+=dns_name(hostname, msg+offset, p);
241:
242: rr=(dns_rr_t*)p;
243: p+=sizeof(dns_rr_t);
244:
245: len=ntohs(rr->length);
246: if(ntohs(rr->type)==DNS_MX) {
247: pref=ntohs(*(WORD*)p);
248: p+=2;
249: p+=dns_name(hostname, msg+offset, p);
250: if(pref<=highpref) {
251: highpref=pref;
252: if(mx[0])
253: strcpy(mx2,mx);
254: strcpy(mx,hostname);
255: } else if(!mx2[0])
256: strcpy(mx2,hostname);
257: }
258: else
259: p+=len;
260: }
261: }
262:
263: if(!mx[0])
264: strcpy(mx,name);
265: mail_close_socket(sock);
266: return(0);
267: }
268:
269: #if 0
270: void main(int argc, char **argv)
271: {
272: char mx[128],mx2[128];
273: int result;
274: WSADATA WSAData;
275:
276: if(argc<3) {
277: printf("usage: mxlookup hostname dns\n");
278: return;
279: }
280:
281:
282: if((result = WSAStartup(MAKEWORD(1,1), &WSAData))!=0) {
283: printf("Error %d in WSAStartup",result);
284: return;
285: }
286:
287: if((result=dns_getmx(argv[1],mx,mx2,0,inet_addr(argv[2])))!=0)
288: printf("Error %d getting mx record\n",result);
289: else {
290: printf("MX1: %s\n",mx);
291: printf("MX2: %s\n",mx2);
292: }
293: getch();
294:
295: WSACleanup();
296: }
297: #endif
298:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.