home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Datafile PD-CD 3
/
PDCD_3.iso
/
internet
/
tcpipsrc
/
DNS
/
c
/
dnscli
< prev
next >
Wrap
Text File
|
1994-09-28
|
6KB
|
259 lines
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "global.h"
#include "mbuf.h"
#include "domain.h"
#include "timer.h"
#include "internet.h"
#include "icmp.h"
#include "netuser.h"
#include "tcp.h"
#include "dns.h"
#include "session.h"
#include "misc.h"
#include "Terminal.h"
#include "flex.h"
#include "vterm.h"
extern char badhost[], hostname[];
extern char *dns_encode_query(vterm vt, char *host, char *type);
extern int dns_decode_answer(vterm vt, char *answer, int lentgh);
extern void dns_test(void);
/* Open up a socket to a remote (or the local) host on its dns port. */
int dodns(int argc, char **argv)
{
struct session *s;
struct tcb *tcb;
struct socket lsocket, fsocket;
struct dns *dns;
if (argc < 3)
{
cwprintf(NULL, "usage: %s <nameserver> <name> [<type>]\r\n", argv[0]);
return(1);
}
if (*argv[1]=='.')
{
dns_test();
return 0;
}
lsocket.address = ip_addr;
lsocket.port = lport++;
if ((dns = alloc_dns()) == NULLDNS)
return(1);
if (argc<4)
dns->user = dns_encode_query(dns->window->vt, argv[2], "");
else
dns->user = dns_encode_query(dns->window->vt, argv[2], argv[3]);
if (dns->user==NULL)
{
cwprintf(NULL, "Bad query\r\n");
free_dns(dns);
return 1;
}
if ((fsocket.address = resolve(argv[1])) == 0)
{
cwprintf(NULL, "%s: ", argv[0]);
cwprintf(NULL, badhost, argv[1]);
free_dns(dns);
return(1);
}
fsocket.port = dns_PORT; /* use dns wnp */
/* Allocate a session descriptor */
if ((s = newsession()) == NULLSESSION)
{
cwprintf(NULL, "Too many sessions\r\n");
free_dns(dns);
return 1;
}
dns->window = Window_Open(s, "DNS Query", term_NO_INPUT);
vterm_resize(dns->window->vt, 80, 200);
vterm_visible(dns->window->vt, 80, 24);
current = s;
s->cb.dns = dns;
dns->session = s;
s->window = dns->window;
s->type = DNSQUERY;
s->parse = NULLVFP;
if ((s->name = malloc(strlen(argv[1])+1)) != NULLCHAR)
strcpy(s->name, argv[1]);
tcb = open_tcp(&lsocket, &fsocket, TCP_ACTIVE, 0,
(void(*)())dnscli_rcv, NULLVFP, (void(*)())d_state, 0, (char *)dns);
dns->tcb = tcb;
tcb->user = (char *) dns;
go(s);
return 0;
}
/* Allocate a dns structure for the new session */
struct dns *alloc_dns(void)
{
struct dns *tmp;
if ((tmp = (struct dns *) malloc(sizeof(struct dns))) == NULLDNS)
return(NULLDNS);
tmp->session = NULLSESSION;
tmp->window = NULL;
tmp->user = (char *) NULL;
tmp->rxdata = (char *) NULL;
tmp->rxcount = 0;
return(tmp);
}
/*
* Free a dns structure
*/
int free_dns(struct dns *dns)
{
if (dns != NULLDNS)
{
if (dns->session != NULLSESSION)
freesession(dns->session);
if (dns->user != (char *) NULL)
free(dns->user);
if (dns->rxdata != (char *) NULL)
flex_free((flex_ptr)&dns->rxdata);
free(dns);
}
return 0;
}
/* dns receiver upcall routine */
void dnscli_rcv(register struct tcb *tcb, int16 cnt)
{
struct dns *dns = (struct dns *)tcb->user;
struct mbuf *bp;
int ok;
/* Make sure it's a valid dns session */
if (dns == NULLDNS)
{
return;
}
if (recv_tcp(tcb, &bp, cnt) > 0)
{
if (dns->rxdata==NULL)
{
ok = flex_alloc((flex_ptr)&dns->rxdata, len_mbuf(bp));
dns->rxcount = 0;
}
else
ok = flex_extend((flex_ptr)&dns->rxdata, dns->rxcount + len_mbuf(bp));
if (!ok)
{
cwprintf(dns->window, "Out of memory in DNS CLI\r\n");
free_p(bp);
return;
}
while (bp != NULLBUF)
{
memcpy(dns->rxdata+dns->rxcount, bp->data, bp->cnt);
dns->rxcount += bp->cnt;
bp = free_mbuf(bp);
}
if ( (dns->rxcount-2) == ((dns->rxdata[0]<<8) | dns->rxdata[1]) )
{
dns_decode_answer(dns->window->vt, dns->rxdata+2, dns->rxcount-2);
close_tcp(tcb);
}
}
}
/* State change upcall routine */
void d_state(register struct tcb *tcb, char old, char new)
{
struct dns *dns;
char notify = 0;
extern char *tcpstates[];
extern char *reasons[];
extern char *unreach[];
extern char *exceed[];
struct mbuf *bp;
old = old;
dns = (struct dns *)tcb->user;
if (dns->window || (current != NULLSESSION && current->type == DNSQUERY))
notify = 1;
switch(new)
{
case CLOSE_WAIT:
if (notify)
cwprintf(dns->window, "%s\r\n", tcpstates[new]);
close_tcp(tcb);
break;
case CLOSED: /* finish up */
if(notify)
{
cwprintf(dns->window, "%s (%s", tcpstates[new], reasons[tcb->reason]);
if (tcb->reason == NETWORK)
{
switch(tcb->type)
{
case DEST_UNREACH:
cwprintf(dns->window, ": %s unreachable", unreach[tcb->code]);
break;
case TIME_EXCEED:
cwprintf(dns->window, ": %s time exceeded", exceed[tcb->code]);
break;
}
}
cwprintf(dns->window, ")\r\n");
cmdmode();
}
if (dns != NULLDNS)
{
if (dns->window)
{
dns->window->Attr = ATTR_REVERSE;
dns->window->Flags.flags.dont_destroy = FALSE;
dns->window->Session = NULL;
Window_CloseDown(dns->window);
}
free_dns(dns);
}
del_tcp(tcb);
break;
case ESTABLISHED:
if (notify)
{
cwprintf(dns->window, "%s\r\n", tcpstates[new]);
}
cwprintf(dns->window, "[%s]\r\n", dns->session->name);
bp = qdata(dns->user, ((dns->user[0]<<8)|dns->user[1])+2);
send_tcp(tcb, bp);
break;
default:
if (notify)
cwprintf(dns->window, "%s\r\n",tcpstates[new]);
break;
}
}