//------------------------------------------------------------------------------
// Copyright (c) David Welch, 1996
//------------------------------------------------------------------------------

#include <windows.h>
#include "winsock.h"
#include <ctype.h>
#include <mem.h>
#include <stdio.h>
#include <string.h>
#include "reverse.h"

char TitleString[]="DNS";

BOOL CALLBACK _export DialogProc ( HWND, UINT, WPARAM, LPARAM );

char command[7];
char gstring[128];

FILE *fp;
FILE *out;

WORD ancount;
WORD type;

FILE *fp;
FILE *out;
char qname[80];
char aname[80];
char bname[80];
char cname[80];
unsigned char buf[1024];
WORD ra;
WORD rb;
WORD rc;
DWORD la;

char name[80];

WSADATA wsad;
SOCKET dnssock;
SOCKADDR_IN namesock;

BOOL timeout=FALSE;

HINSTANCE mainhinst;
HWND mainhwnd;

int rsize;
BYTE sdata[1024];
BYTE rdata[1024];
BYTE idtag=1;


//-----------------------------------------------------------------------------
int PASCAL WinMain ( HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int cmdshow )
{
    WNDCLASS wndclass;
    MSG msg;
    FARPROC lpfn;

    if(hprev!=NULL)
    {
        MessageBox(NULL,"Application Already Running",TitleString,MB_OK);
        return(FALSE);
    }
    if((cmdline[0]==0)||(lstrlen(cmdline)>7))
    {
        MessageBox(NULL,"What?",TitleString,MB_OK);
        return(FALSE);
    }
    lstrcpy(command,cmdline);
    wsprintf(qname,"%s.zon",command);
    fp=fopen(qname,"rt");
    if(fp==NULL)
    {
        wsprintf(gstring,"Error opening input file [%s]",qname);
        MessageBox(NULL,gstring,TitleString,MB_OK);
        return(FALSE);
    }
    wsprintf(qname,"%s.dns",command);
    out=fopen(qname,"wb");
    if(out==NULL)
    {
        wsprintf(gstring,"Error creating file [%s]",qname);
        MessageBox(NULL,qname,TitleString,MB_OK);
        return(FALSE);
    }
    mainhinst=hinst;
    if(WSAStartup(0x0101,&wsad))
    {
        MessageBox(NULL,"WSAStartup() failed",TitleString,MB_OK);
        return(FALSE);
    }
    dnssock=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
    if(dnssock==INVALID_SOCKET)
    {
        wsprintf(gstring,"socket(dnssock) error %d",WSAGetLastError());
        MessageBox(NULL,gstring,TitleString,MB_OK);
        WSACleanup();
        return(FALSE);
    }
    namesock.sin_family=PF_INET;
    namesock.sin_port=htons(0);
    namesock.sin_addr.s_addr=htonl(INADDR_ANY);
    if(bind(dnssock,(PSOCKADDR)&namesock,sizeof(namesock))==SOCKET_ERROR)
    {
        wsprintf(gstring,"bind(dnssock) error %d",WSAGetLastError());
        MessageBox(NULL,gstring,TitleString,MB_OK);
        closesocket(dnssock);
        WSACleanup();
        return(FALSE);
    }
    namesock.sin_family=AF_INET;
    namesock.sin_port=htons(53);
    namesock.sin_addr.s_addr=inet_addr("204.134.124.2");
    if(connect(dnssock,(PSOCKADDR)&namesock,sizeof(namesock))==SOCKET_ERROR)
    {
        wsprintf(gstring,"connect(dnssock) error %d",WSAGetLastError());
        MessageBox(NULL,gstring,TitleString,MB_OK);
        closesocket(dnssock);
        WSACleanup();
        return(FALSE);
    }
    if(DialogBox(mainhinst,"MainDialog",0,DialogProc)==-1)
    {
        MessageBox(NULL,"Could not create main window",TitleString, MB_OK);
        closesocket(dnssock);
        WSACleanup();
    }
    closesocket(dnssock);
    WSACleanup();
    return(FALSE);
}
//------------------------------------------------------------------------------
void addstring ( char *s )
{
    LRESULT lresult;

    while(1)
    {
        lresult=SendDlgItemMessage(mainhwnd,100,LB_GETCOUNT,0,0);
        if(lresult==LB_ERR) break;
        if(lresult<50) break;
        lresult=SendDlgItemMessage(mainhwnd,100,LB_DELETESTRING,0,0);
        if(lresult==LB_ERR) break;
    }
    lresult=SendDlgItemMessage(mainhwnd,100,LB_ADDSTRING,0,(LPARAM)s);
    if(lresult==LB_ERR) return;
    lresult=SendDlgItemMessage(mainhwnd,100,LB_GETCOUNT,0,0L);
    if(lresult==LB_ERR) return;
    SendDlgItemMessage(mainhwnd,100,LB_SETCURSEL,lresult-1,0L);
}
//-----------------------------------------------------------------------------
unsigned short dnsstring ( unsigned char *d, WORD r, unsigned char *n )
{
    unsigned short ret;
    unsigned short off;

    off=0;
    ret=0;
    while(1)
    {
        if(d[r]==0)
        {
            if(!ret) ret=r+1;
            if(off) off--;
            n[off]=0;
            return(ret);
        }
        if((d[r]&0xC0)==0xC0)
        {
            if(!ret) ret=r+2;
            r=d[r+1];
            continue;
        }
        memcpy(&n[off],&d[r+1],d[r]);
        off+=d[r];
        n[off++]='.';
        r+=d[r]+1;
    }
}
//-----------------------------------------------------------------------------
void parse ( unsigned char *data )
{
    ra=reverseword(*(WORD *)&data[0]);
    if(data[2]&0x02) return;
    if(data[3]&0x0F) return;
    ra=reverseword(*(WORD *)&data[4]);
    if(ra!=1) return;
    ancount=reverseword(*(WORD *)&data[6]);
    if(ancount==0) return;
    rb=dnsstring(data,12,qname);
    for(ra=0;qname[ra];ra++) qname[ra]=toupper(qname[ra]);
    ra=reverseword(*(WORD *)&data[rb]); rb+=2;
    rc=reverseword(*(WORD *)&data[rb]); rb+=2;
    if(ra!=1) return;
    if(rc!=1) return;
    rb=dnsstring(data,rb,aname);
    for(ra=0;aname[ra];ra++) aname[ra]=toupper(aname[ra]);
    type=reverseword(*(WORD *)&data[rb]); rb+=2;
    switch(type)
    {
        case  1:
        case  5:
            break;
        default: return;
    }
    ra=reverseword(*(WORD *)&data[rb]); rb+=2;
    if(ra!=1) return;
    la=reversedword(*(DWORD *)&data[rb]); rb+=4;
    ra=reverseword(*(WORD *)&data[rb]); rb+=2;
    if(strcmp(qname,aname)!=0) return;
    if(type==1)
    {
        if(ra!=4) return;
        wsprintf(gstring,"%s %u.%u.%u.%u",qname,data[rb],data[rb+1],data[rb+2],data[rb+3]);
        fprintf(out,"%s\n",gstring);
        addstring(gstring);
        return;
    }
    if(type==5)
    {
        rb=dnsstring(data,rb,bname);
        for(ra=0;bname[ra];ra++) bname[ra]=toupper(bname[ra]);
        if(ancount==1) return;
        rb=dnsstring(data,rb,cname);
        for(ra=0;cname[ra];ra++) cname[ra]=toupper(cname[ra]);
        if(strcmp(bname,cname)!=0) return;
        type=reverseword(*(WORD *)&data[rb]); rb+=2;
        if(type!=1) return;
        ra=reverseword(*(WORD *)&data[rb]); rb+=2;
        if(ra!=1) return;
        la=reversedword(*(DWORD *)&data[rb]); rb+=4;
        ra=reverseword(*(WORD *)&data[rb]); rb+=2;
        if(ra!=4) return;
        wsprintf(gstring,"%s %u.%u.%u.%u",qname,data[rb],data[rb+1],data[rb+2],data[rb+3]);
        fprintf(out,"%s\n",gstring);
        addstring(gstring);
    }
}
//-----------------------------------------------------------------------------
BOOL CALLBACK _export DialogProc ( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam )
{
    int i;
    WORD ra;
    WORD rb;
    WORD rc;

    mainhwnd=hwnd;
    switch(message)
    {
        case WM_INITDIALOG:
            SetWindowText(hwnd,TitleString);
            SetWindowPos(hwnd,(HWND)NULL,0,0,0,0,SWP_NOSIZE|SWP_NOZORDER);
            wsprintf(gstring,"Winsock Version %u.%u",(wsad.wVersion>>8)&255,wsad.wVersion&255);
            addstring(gstring);
            addstring(wsad.szDescription);
            SetTimer(hwnd,123,250,NULL);
            if(WSAAsyncSelect(dnssock,hwnd,WM_USER+1,FD_READ)==SOCKET_ERROR)
            {
                wsprintf(gstring,"WSAAsyncSelect() error %d",WSAGetLastError());
                MessageBox(hwnd,gstring,TitleString,MB_OK);
                KillTimer(hwnd,123);
                EndDialog(hwnd,TRUE);
                return(TRUE);
            }
            return(TRUE);
        case WM_TIMER:
            switch(wparam)
            {
                case 123:
                    if(timeout) return(TRUE);
                    memset(name,0,sizeof(name));
                    if(fgets(name,sizeof(name),fp)==NULL)
                    {
                        timeout=TRUE;
                        KillTimer(hwnd,123);
                        SetTimer(hwnd,666,60000,NULL);
                        addstring("List Finished");
                        return(TRUE);
                    }
                    ra=lstrlen(name);
                    if(ra<5) return(TRUE);
                    if(name[ra-1]==0x0A) name[ra-1]=0;
                    if(lstrlen(name)==0) return(TRUE);
                    if(lstrlen(name)>64) return(TRUE);
                    addstring(name);
                    for(ra=0;name[ra];ra++)
                    {
                        name[ra]=toupper(name[ra]);
                        if(name[ra]=='.') name[ra]=0;
                    }
                    memset(sdata,0,sizeof(sdata));
                    sdata[1]=idtag++;
                    sdata[2]=1;
                    sdata[5]=1;
                    ra=12;
                    rb=0;
                    while(1)
                    {
                        rc=lstrlen(&name[rb]);
                        if(rc==0) break;
                        sdata[ra++]=rc;
                        lstrcpy(&sdata[ra],&name[rb]);
                        ra+=rc;
                        rb+=rc+1;
                    }
                    sdata[ra+2]=1;
                    sdata[ra+4]=1;
                    ra+=5;
                    if(send(dnssock,sdata,ra,0)==SOCKET_ERROR)
                    {
                        wsprintf(gstring,"send(dnssock) error %d",WSAGetLastError());
                        addstring(gstring);
                    }
                    return(TRUE);
                case 666:
                    KillTimer(hwnd,666);
                    EndDialog(hwnd,TRUE);
                    return(TRUE);
            }
            break;
        case WM_USER+1:
            i=sizeof(namesock);
            if((rsize=recvfrom(dnssock,rdata,sizeof(rdata),0,(LPSOCKADDR)&namesock,&i))==SOCKET_ERROR)
            {
                if(WSAGetLastError()==WSAEWOULDBLOCK) break;
                wsprintf(gstring,"recvfrom() error %d",WSAGetLastError());
                addstring(gstring);
            }
            else
            {
                parse(rdata);
            }
            return(TRUE);
        case WM_COMMAND:
            switch(wparam)
            {
                case IDCANCEL:
                    KillTimer(hwnd,123);
                    KillTimer(hwnd,666);
                    EndDialog(hwnd,TRUE);
                    return(TRUE);
                case 101:
                    SendDlgItemMessage(hwnd,100,LB_RESETCONTENT,0,0L);
                    return(TRUE);
            }
            break;
    }
    return(FALSE);
}
//------------------------------------------------------------------------------
// Copyright (c) David Welch, 1996
//------------------------------------------------------------------------------