home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Meeting Pearls 3
/
Meeting_Pearls_III.iso
/
Pearls
/
tcp
/
Networking
/
TCP
/
Server
/
named
/
named.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-12-14
|
5KB
|
254 lines
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/syslog.h>
#include <sys/errno.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <proto/exec.h>
char VersionTag[]="\0$VER: JoranNameserver 0.3 (14.12.93)";
struct hostinfo {
struct MinNode Node;
char name[MAXDNAME];
LONG netnumber;
};
struct MinList hostlist;
char Line[1024];
char hostname[MAXHOSTNAMELEN];
char *curnet="";
void readnamedhosts(void)
{
FILE *f;
f=fopen("AmiTCP:db/named.hosts","r");
if(!f)
{
perror("AmiTCP:db/named.hosts");
exit(1);
}
NewList((struct List *)&hostlist);
while(fgets(Line,sizeof(Line),f))
{
char *p,*a[6];
char curdname[MAXDNAME];
LONG netnumber;
int i;
if(p=strchr(Line,';')) *p='\0'; // Verwijderen commentaar
a[0]=strtok(Line,"\t\n ");
for(i=1;i<6;i++) a[i]=strtok(NULL,"\t\n ");
netnumber=-1;
for(i=0;i<6;i++) if(!a[i] || !strcmp(a[i],"IN")) break;
if(i>0) strcpy(curdname,a[0]);
if(i<4 && a[i+1] && !strcmp(a[i+1],"A")) netnumber=inet_addr(a[i+2]);
if(netnumber!=-1)
{
struct hostinfo *hi;
if(hi=malloc(sizeof(struct hostinfo)))
{
strcpy(hi->name,curdname);
if(hi->name[strlen(hi->name)-1]!='.') strcat(hi->name,curnet);
else hi->name[strlen(hi->name)-1]='\0';
hi->netnumber=netnumber;
#ifdef DEBUG
printf("add: %s(%s)\n",hi->name,Inet_NtoA(hi->netnumber));
#endif
AddTail((struct List *)&hostlist,(struct Node *)hi);
}
}
}
fclose(f);
}
void send_err(int s,char *msg,int msglen,struct sockaddr_in *to,LONG tolen,short rcode)
{
HEADER *h;
h=(HEADER *)msg+sizeof(HEADER);
h->qr=1;
h->rcode=rcode;
sendto(s,msg,msglen,0,(struct sockaddr *)to,tolen);
#ifdef DEBUG
switch(rcode)
{
case FORMERR: puts("FORMERR send");break;
case SERVFAIL: puts("FORMFAIL send");break;
case NXDOMAIN: puts("NXDOMAIN send");break;
default: puts("UNKNOWN ERROR send");break;
}
#endif
}
main()
{
struct servent *sp;
struct sockaddr_in sin;
struct sockaddr_in from;
struct hostinfo *hp,*hi;
LONG fromlen;
char msg[PACKETSZ];
char *lmsg;
char dnbuf[MAXDNAME];
char *cp,*eom;
int msglen;
int s,n;
short type,class;
sp=getservbyname("domain","udp");
if(!sp)
{
fprintf(stderr,"nameserver: tcp/nameserver: unknown service\n");
exit(1);
}
s=socket(AF_INET,SOCK_DGRAM,0);
if(s==-1)
{
perror("nameserver: create socket");
exit(1);
}
bzero(&sin,sizeof(sin));
sin.sin_port=sp->s_port;
if(bind(s,(struct sockaddr *)&sin,sizeof(sin))==-1)
{
perror("nameserver: bind");
exit(1);
}
if(gethostname(hostname,sizeof(hostname))==-1)
{
perror("nameserver: gethostname");
exit(1);
}
if(cp=strchr(hostname,'.')) curnet=cp;
readnamedhosts();
#ifdef DEBUG
printf("nameserver started\n");
#endif
for(;;)
{
fromlen=sizeof(from);
if((msglen=recvfrom(s,msg,sizeof(msg),0,(struct sockaddr *)&from,&fromlen))==-1)
{
perror("nameserver: recvfrom");
}
else
{
HEADER *h;
h=(HEADER *)msg;
cp=msg+sizeof(HEADER);
eom=msg+msglen;
#ifdef DEBUG
printf( "datagram received:\n"
" from : %s\n"
" opcode : %d\n"
" qdqount: %d\n"
,inet_ntoa(from.sin_addr)
,h->opcode
,h->qdcount
);
#endif
switch(h->opcode)
{
case QUERY:
if(h->qdcount!=1 || h->ancount || h->nscount || h->arcount)
{
h->qdcount=0;
h->ancount=0;
h->nscount=0;
h->arcount=0;
send_err(s,msg,msglen,&from,fromlen,FORMERR);
continue;
}
if((n=dn_expand(msg,eom,cp,dnbuf,sizeof(dnbuf)))<0)
{
send_err(s,msg,msglen,&from,fromlen,FORMERR);
continue;
}
cp+=n;
GETSHORT(type, cp);
GETSHORT(class, cp);
if(cp>eom)
{
send_err(s,msg,msglen,&from,fromlen,FORMERR);
continue;
}
#ifdef DEBUG
printf(" host : %s\n",dnbuf);
printf(" type : %d\n",type);
printf(" class : %d\n",class);
#endif
if(type!=T_A || class!=C_IN)
{
send_err(s,msg,msglen,&from,fromlen,NOTIMP);
continue;
}
hp=NULL;
for(hi=(struct hostinfo *)hostlist.mlh_Head;hi!=(struct hostinfo *)&hostlist.mlh_Tail;hi=(struct hostinfo *)hi->Node.mln_Succ)
{
if(!strcmp(hi->name,dnbuf))
{
hp=hi;
break;
}
}
if(!hp)
{
send_err(s,msg,msglen,&from,fromlen,NXDOMAIN);
continue;
}
lmsg=msg+sizeof(msg);
if((n=dn_comp(dnbuf,cp,lmsg-cp,NULL,NULL))<0)
{
send_err(s,msg,msglen,&from,fromlen,SERVFAIL);
continue;
}
cp+=n;
if(cp+14>lmsg)
{
send_err(s,msg,msglen,&from,fromlen,SERVFAIL);
continue;
}
PUTSHORT(type, cp);
PUTSHORT(class, cp);
PUTLONG(100000,cp);
PUTSHORT(sizeof(LONG),cp);
PUTLONG(hi->netnumber,cp);
h->qr=1;
h->rcode=NOERROR;
h->ancount=1;
sendto(s,msg,cp-msg,0,(struct sockaddr *)&from,fromlen);
#ifdef DEBUG
printf("answer: %s(%s) send\n",dnbuf,Inet_NtoA(hi->netnumber));
#endif
break;
default:
send_err(s,msg,msglen,&from,fromlen,NOTIMP);
}
}
}
}