From: Rasmus 'Con' Ronlev <raro94ab@hp4.econ.cbs.dk>
Subject: dnslookup server

Hi,

Below I've attached a little piece of c-code. It's my own implementation
of a little server application to run along with the mud to handle queries
on a specified port for looking up hostnames. The program reveives the
input that the mud produces in the new_descriptor() function as the:
peer.sin_saddr.s_addr. A network byte ordered long int, that gives the IP
adress of the connectee. It then returns either an IP adress or a hostname
depending on the ability to look up a hostname.

Now, the program seems to work perfectly, listens to the specified socket
awaiting inpus, processes the query for a gethostbyaddr() call and stuff.

If you have comments/sugestions please drop a line :)

------------------------- CODE for DNSLOOKUP below -----------------------

/*
 * ConMUD Copyrgight information.
 *
 * All rights reserved.
 *
 * ConMUD is copyrighted (C) 1995, 96, 97 by Rasmus Ronlev.
 * ConMUD is based on CircleMUD, Copyright (C) 1993, 94 by the Trustees of
 * the Johns Hopkins University.
 * CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.
 *
 * Copying, distribution, use of the whole or parts thereof is illegal
 * unnless written permission has been given by the copyrightholder of
 * ConMUD (Rasmus Ronlev - rr@cbs.dk)
 *
 * file: dnslookup.c
 *
 * This is a utility to supply a dns lookup (gethostbyname()) on a specified
 * port. It was specificaly developed for ConMUD to provide a means of non-
 * blocking hostname lookup.
 *
 * The program should be started with a port number, if none is specified, the
 * port 5151 is used.
 *
 */

#include "../conf.h"
#include "../sysdep.h"
#include <sys/types.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

/* internal procedures */
void nonblock(socket_t s);

RETSIGTYPE sigchld()
{
  struct rusage ru;

  pid_t wait3(int *, int, struct rusage *);

  wait3(NULL, WNOHANG, &ru);
}

void main(int argc, char **argv)
{
  int mother_desc;
  struct sockaddr_in sa;
  struct sockaddr_in sock_in;
  struct hostent *from, *host;
  char buf[256], hostip[20];
  unsigned long addr;
  int port = 5151, pos = 1, length, sock, opt;

  fprintf(stderr, "DNS-lookup, (c)1997 Rasmus 'Con' Ronlev (rr@cbs.dk)\n");

  if (argc > 1) {
    if(!isdigit(*argv[1])) {
      fprintf(stderr, "Usage: %s [port #]\n", argv[0]);
      exit(1);
    }
    else if ((port = atoi(argv[pos])) <= 1024) {
      fprintf(stderr, "Illegal port number.\n");
      exit(1);
    }
  }

  fprintf(stderr, "Opening dns-lookup server on port %d\n", port);
  if ((mother_desc = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
    perror("Error creating socket");
    exit(1);
  }
  sa.sin_family = AF_INET;
  sa.sin_port = htons(port);
  sa.sin_addr.s_addr = htonl(INADDR_ANY);

  opt = 1;
  if (setsockopt(mother_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt)) < 0) {
    perror("setsockopt REUSEADDR");
    exit(1);
  }

  if (bind(mother_desc, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
    perror("bind");
    close(mother_desc);
    exit(1);
  }
  listen(mother_desc, 1);	/* Max. pending requests to que		*/

  fprintf(stderr, "Ready to accept connections\n");

#ifdef SIGCLD  /* only on SYSV */
  signal(SIGCLD,  SIG_IGN);  /* "automagically" delete zombies */
#else
# ifdef SIGCHLD
  signal(SIGCHLD,  sigchld);  /* remove zombies */
# endif /* SIGCHLD */
#endif /* SIGCLD */

  while(1) {
    length = sizeof(sock_in);
    sock = accept(mother_desc, (struct sockaddr *) &sock_in, &length);
    /* Now fork a process to process the socket stuff */
    if (fork())
    {
      close(sock);
    }
    else	/* run child process */
    {
      from = gethostbyaddr((char *) &sock_in.sin_addr, sizeof(sock_in.sin_addr), AF_INET);
      if(strcmp(from->h_name, "localhost")) /* Doesn't match localhost */
      {
        fprintf(stderr, "DNS-Request denied, access unauthorized from %s (%ld)!\n", from->h_name, sock_in.sin_addr.s_addr);
        sprintf(buf, "Access not authorized from %s!!!!\n", from->h_name);
        length = strlen(buf);
        write(sock, buf, length);
        close(sock);
        close(mother_desc);
        exit(1);
      }
      /* read in the string sent to the program */
      *buf = '\0';
      read(sock, buf, sizeof(buf));
      sock_in.sin_addr.s_addr = atol(buf);
      addr = ntohl(sock_in.sin_addr.s_addr);
      sprintf(hostip, "%03u.%03u.%03u.%03u", (int) ((addr & 0xFF000000) >> 24),
             (int) ((addr & 0x00FF0000) >> 16), (int) ((addr & 0x0000FF00) >> 8),
             (int) ((addr & 0x000000FF)));
      if(!(host = gethostbyaddr((char *) &sock_in.sin_addr, sizeof(sock_in.sin_addr), AF_INET))) {
        sprintf(buf, "IP: %s\n", hostip);
        length = strlen(buf);
        write(sock, buf, length);
      fprintf(stderr, "DNS-Request accepted from %s. Couldn't look up %s\n", from->h_name, hostip);
      }
      else {
        sprintf(buf, "HOSTNAME: %s\n", host->h_name);
        length = strlen(buf);
        write(sock, buf, length);
      fprintf(stderr, "DNS-Request accepted from %s. %s resolved as %s\n", from->h_name, hostip, host->h_name);
      }
      close(sock);
      close(mother_desc);
      exit(1);
    }
  }
  close(mother_desc);
}

--------------------------------------------------------------------------
Note that the book "Advanced Programming In The Unix Environment" by
Richard Stevens is _highly_ recomended if you are programing on a unix
machine.

Regards,
Con

d.

