DNS Resolver
------------

DNS Resolver
External resolver ported from Rom.
Internal support code provided by Trax of Forever's End.
DNS Cache sections by Samson.

Terms of Use
------------

1. You may use this snippet in your code provided that any included
comment headers in the code are left intact. You may add your own, but
do not take mine out.

2. This snippet may not be posted for redistribution on any site
without obtaining prior written consent from the Alsherok team.

3. ( optional ) Register with the forums at http://forums.alsherok.net
Registration is not required to make use of the snippet, but since I no
longer provide email support for any of the code I release, forum posts
are your only avenue for direct support. This may seem overly stupid,
but you can blame the continuing abuse I suffer from spammers for this.
Don't post stuff to TMC or TMS asking about my code. I'm highly unlikely
to ever notice it there on the rare ocassions I skim posts in either place.

If forum registration doesn't appeal to you, then you can try to get ahold
of me via IMC on the code channel.

If you can't agree to these terms, don't use this code, and don't expect
me to help if something breaks while installing it. Harsh? Hardly. I'm
tired of people who come crawling to whine and complain when they haven't
bothered to comply with the terms first.

What this code does
-------------------

This provides an external program to handle incoming reverse DNS lookups for
people logging into the mud. Instead of the usual slave process that runs
continuously alongside the mud, this one only runs on demand and communicates
its information back to the mud via the character's own descriptor. Has the
advantage of not causing any lag at all for the lookup process, not even for
the person connecting. It then stores the resolved DNS name in an online cache
for 14 days, after which it is expunged.

Installation Instructions
-------------------------

** Note - if you are using the old slave code, remove it before starting this. **

1. Place the resolver.c, dns.c, and dns.h files in your src directory.

2. Open the Makefile

   Add dns.c and dns.o to the appropriate sections.

   Below your L_FLAGS line, add the following 2 lines:

#D_FLAGS : For the DNS Slave process. No need in linking all the extra libs for this.
D_FLAGS = -g2 -O $(PROF) $(SOLARIS_LINK)

   Then, locate the following:
all:
	$(MAKE) -s smaug

   Below that, add:
	$(MAKE) -s dns

   Then, find the following section:

smaug: $(O_FILES)
	rm -f smaug
	$(CC) $(L_FLAGS) $(USE_IMC) -o smaug $(O_FILES)
	chmod g+w smaug
	chmod a+x smaug
	chmod g+w $(O_FILES)

   Below that, add the following section:

dns: resolver.o
	rm -f resolver
	$(CC) $(D_FLAGS) -o resolver resolver.o
	chmod g+w resolver
	chmod a+x resolver
	chmod g+w resolver.o

3. Open mud.h and find the struct for descriptor_data.

   Add the following 2 lines to the end:

   int ifd;
   pid_t ipid;

   Then find the following section:

/*
 * Structure for extended bitvectors -- Thoric
 */
struct extended_bitvector
{
    unsigned int		bits[XBI]; /* Needs to be unsigned to compile in Redhat 6 - Samson */
};

   Directly below that, add:

#include "dns.h"

4. Open comm.c

   In the includes section, add the following:

#include <sys/wait.h>

   Then locate function new_descriptor.

   In the declarations section, remove: struct hostent *from;

   Then find the following:

   dnew->port		= ntohs( sock.sin_port );
   dnew->user 		= STRALLOC("(unknown)");
   dnew->newstate	= 0;
   dnew->prevcolor	= 0x07;

   Directly below that, add the following:

   dnew->ifd = -1; /* Descriptor pipes, used for DNS resolution and such */
   dnew->ipid = -1;

   Then a few lines below, locate the following:

    strcpy( buf, inet_ntoa( sock.sin_addr ) );
    sprintf( log_buf, "Sock.sinaddr:  %s, port %hd.", buf, dnew->port );
    log_string_plus( log_buf, LOG_COMM, sysdata.log_level );
    if ( sysdata.NO_NAME_RESOLVING )
      dnew->host = STRALLOC( buf );
    else
    {
       from = gethostbyaddr( (char *) &sock.sin_addr, sizeof(sock.sin_addr), AF_INET );
       dnew->host = STRALLOC( (char *)( from ? from->h_name : buf) );
    }

   Change it to read as follows:

   strncpy( log_buf, inet_ntoa( sock.sin_addr ), MAX_STRING_LENGTH );
   dnew->host = STRALLOC( log_buf );
   if( !sysdata.NO_NAME_RESOLVING )
   {
      strncpy( buf, in_dns_cache( log_buf ), MAX_STRING_LENGTH );

      if( buf[0] == '\0' )
         resolve_dns( dnew, sock.sin_addr.s_addr );
      else
      {
         STRFREE( dnew->host );
         dnew->host = STRALLOC( buf );
      }
   }

   Then locate function accept_new and find the following:

	/*
	 * Poll all active descriptors.
	 */
	FD_ZERO( &in_set  );
	FD_ZERO( &out_set );
	FD_ZERO( &exc_set );
	FD_SET( ctrl, &in_set );
	maxdesc	= ctrl;
	newdesc = 0;
	for ( d = first_descriptor; d; d = d->next )
	{
	    maxdesc = UMAX( maxdesc, d->descriptor );
	    FD_SET( d->descriptor, &in_set  );
	    FD_SET( d->descriptor, &out_set );
	    FD_SET( d->descriptor, &exc_set );
	    if ( d == last_descriptor )
	      break;
	}

   Change that to read as follows:

   /*
    * Poll all active descriptors.
    */
   FD_ZERO( &in_set );
   FD_ZERO( &out_set );
   FD_ZERO( &exc_set );
   FD_SET( ctrl, &in_set );
   maxdesc = ctrl;
   newdesc = 0;
   for( d = first_descriptor; d; d = d->next )
   {
      maxdesc = UMAX( maxdesc, d->descriptor );
      FD_SET( d->descriptor, &in_set );
      FD_SET( d->descriptor, &out_set );
      FD_SET( d->descriptor, &exc_set );
      if( d->ifd != -1 && d->ipid != -1 )
      {
         maxdesc = UMAX( maxdesc, d->ifd );
         FD_SET( d->ifd, &in_set );
      }
      if( d == last_descriptor )
         break;
   }

   Then locate function game_loop and find the following:

		if ( d->character && d->character->wait > 0 )
		{
			--d->character->wait;
			continue;
		}

   Directly ABOVE that, add the following:

            /* check for input from the dns */
            if( ( d->connected == CON_PLAYING || d->character != NULL ) && d->ifd != -1 && FD_ISSET( d->ifd, &in_set ) )
               process_dns( d );

   Then locate function close_socket and find the following:

    /* flush outbuf */
    if ( !force && dclose->outtop > 0 )
	flush_buffer( dclose, FALSE );

   Directly ABOVE that, add the following:

   if( dclose->ipid != -1 )
   {
      int status;

      kill( dclose->ipid, SIGKILL );
      waitpid( dclose->ipid, &status, 0 );
   }
   if( dclose->ifd != -1 )
      close( dclose->ifd );

5. Open db.c, and locate the following in boot_db:

   /*
    * Assign gsn's for skills which need them.
    */

   Directly ABOVE that, add:

   log_string( "Loading DNS cache..." ); /* Samson 1-30-02 */
   load_dns();

6. Open update.c, and find the following in update_handler:

    if ( --pulse_second   <= 0 )
    {
	pulse_second	= PULSE_PER_SECOND;
	char_check( );
 	reboot_check(0);
    }

   Change it to read as follows:

   if( --pulse_second <= 0 )
   {
      pulse_second = PULSE_PER_SECOND;
      char_check(  );
      check_dns(  );
      reboot_check( 0 );
   }

7. For users of copyover/hotboot only:

   In copyover_recover/hotboot_recover, locate the following:

      CREATE( d, DESCRIPTOR_DATA, 1 );

      d->next		= NULL;
      d->descriptor	= desc;
      d->connected	= CON_GET_NAME;
      d->outsize		= 2000;
      d->idle		= 0;
      d->lines		= 0;
      d->scrlen		= 24;
      d->newstate		= 0;
      d->prevcolor	= 0x07;

   Directly below that, add the following:

      d->ifd = -1;
      d->ipid = -1;

8. Make clean, recompile.

9. Reboot.

10. Create a "cache" command.

If there are any problems with this installation, feel free to post your
question to the forums at http://forums.alsherok.net

This code has been installed and tested on Smaug 1.6 FUSS, which is a bugfixed
and cleaned up version of the base Smaug 1.4a code. The Smaug FUSS Project is
maintained on servers which run the Redhat and Fedora family of Linux. Limited
testing has also been done on the Cygwin package under WindowsXP SP1 and SP2.
Users of BSD, MSVC, MSVC++, or Macintosh platforms are on their own as The
Smaug FUSS Project does not have access to these development environments for testing.
The Smaug FUSS Project can be found at: http://www.fussproject.org

No guarantees are made that this code will be compatible with your codebase and any
modifications you may have made to it. No warranty of any kind is expressed or implied
by the use of this code, and we are not responsible for any damages which may result
from the application of this snippet to your codebase.

Adventure beckons in the lands of mystique....
Samson, Implementor of Alsherok
http://www.alsherok.net
telnet://alsherok.net:5500

IMC2 contact: Samson@Alsherok