|
|
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.