These patches are written by Dark@Igor for Dutch Mountains, in December 1995. They are freely redistributable. diff -u src.ident/comm.c src.hname/comm.c --- src.ident/comm.c Wed Jan 3 22:41:48 1996 +++ src.hname/comm.c Thu Jan 4 19:07:20 1996 @@ -70,8 +70,6 @@ char * const him_her [] = { "it", "him", "her" }; char * const his_her [] = { "its", "his", "her" }; -bool fLookupAddress = TRUE; /* Change here to disable nameserver default */ - /* * Signal handling. * Apollo has a problem with __attribute(atomic) in signal.h, @@ -161,6 +159,10 @@ fd_set *exceptfds, struct timeval *timeout ) ); int socket args( ( int domain, int type, int protocol ) ); int write args( ( int fd, char *buf, int nbyte ) ); +pid_t vfork args( ( void ) ); +int dup2 args( ( int oldfd, int newfd ) ); +int execlp args( ( const char *file, const char *arg, ... ) ); +unsigned long inet_addr args( ( const char *cp ) ); #endif #if defined(macintosh) @@ -283,7 +285,12 @@ long boot_time; /* Time when merc started up */ long current_time; /* Time of this pulse */ int players_max; /* Maximum numbers of players */ - +int hname; /* Connects to hname resolver */ +struct { + long addr; + char *hname; +} hname_table[MAX_HNAME]; /* Caches hostnames */ +int hname_index; /* Cycles through hname_table */ /* * OS-dependent local functions. @@ -297,6 +304,8 @@ #if defined(unix) void game_loop_unix args( ( int control ) ); int init_socket args( ( int port ) ); +void init_hname args( ( char *mainpath ) ); +void get_hname args( ( void ) ); int getrlimit args( ( int resource, struct rlimit *rlp ) ); /* int setrlimit args( ( int resource, struct rlimit *rlp ) ); @@ -421,6 +430,7 @@ #if defined(unix) boot_db( ); + init_hname( argv[0] ); control = init_socket( port ); sprintf( log_buf, "Dutch Mountains ready to rock on port %d.", port ); log_string( log_buf ); @@ -438,6 +448,63 @@ #if defined(unix) +void init_hname( char *mainpath ) +{ + int sockets[2]; + int pid; + static char *hnamepath; + char *p; + + p = strrchr( mainpath, '/' ); + if ( p ) { + /* 7 is length of "hname" plus slash plus terminating 0 */ + hnamepath = alloc_mem( p - mainpath + 7 ); + strncpy( hnamepath, mainpath, p - mainpath + 1 ); + strcat( hnamepath, "hname" ); + } + else + { + hnamepath = str_dup( "hname" ); + } + +#ifndef FNDELAY +#define FNDELAY O_NDELAY +#endif + + if ( socketpair( AF_UNIX, SOCK_STREAM, 0, sockets) >= 0 ) + { + pid = vfork(); + if ( pid > 0 ) + { /* parent */ + hname = sockets[1]; + close( sockets[0] ); + free_string( hnamepath ); + signal(SIGPIPE, SIG_IGN); + if ( fcntl( hname, F_SETFL, FNDELAY) < 0 ) + { + perror("init_hname: fcntl"); + close( hname ); + hname = -1; + } + } + else if ( pid == 0 ) + { /* child */ + close(sockets[1]); + dup2( sockets[0], 0 ); + dup2( sockets[0], 1 ); + execlp( hnamepath, "hname", NULL ); + /* Still here? Then exec failed. */ + exit( 1 ); + } + else + { /* failure */ + close(sockets[0]); + close(sockets[1]); + hname = -1; + } + } +} + int init_socket( int port ) { static struct sockaddr_in sa_zero; @@ -781,6 +848,8 @@ FD_ZERO( &out_set ); FD_ZERO( &exc_set ); FD_SET( control, &in_set ); + if ( hname >= 0 ) + FD_SET( hname, &in_set ); maxdesc = control; for ( d = descriptor_list; d != NULL; d = d->next ) { @@ -812,6 +881,14 @@ new_descriptor( control ); } + /* + * New hostname found? + */ + if ( hname >= 0 && FD_ISSET( hname, &in_set ) ) + { + get_hname(); + } + /* * Kick out the freaky folks. */ @@ -1041,6 +1118,147 @@ return 1; } +#if defined(unix) +void query_hname( DESCRIPTOR_DATA *desc ) +{ + int i; + char buf[20]; + + /* Look in cache */ + for ( i = 0; i < MAX_HNAME; i++ ) + { + if ( desc->hostaddr == hname_table[i].addr ) + { + free_string( desc->host ); + desc->host = str_dup( hname_table[i].hname ); + return; + } + } + + /* + * Would be nice to use inet_ntoa here but it takes a struct arg, + * which ain't very compatible between gcc and system libraries. + */ + sprintf( buf, "%ld.%ld.%ld.%ld", + ( desc->hostaddr >> 24 ) & 0xFF, ( desc->hostaddr >> 16 ) & 0xFF, + ( desc->hostaddr >> 8 ) & 0xFF, ( desc->hostaddr ) & 0xFF + ); + + desc->host = str_dup( buf ); + strcat( buf, "\n" ); + if ( write( hname, buf, strlen( buf ) ) < 0 ) + { + close( hname ); + hname = -1; + } +} +#endif + +#if defined(unix) +static void add_hname( long addr, char *hname ) +{ + char *p; + DESCRIPTOR_DATA *d, *d_next; + BAN_DATA *pban; + bool newchar; + + hname_table[hname_index].addr = addr; + free_string( hname_table[hname_index].hname ); + hname_table[hname_index].hname = hname; + hname_index = ( hname_index + 1 ) % MAX_HNAME; + + for ( d = descriptor_list; d; d = d_next ) + { + d_next = d->next; + if ( d->hostaddr == addr ) { + p = strrchr( d->host, '@' ); + if ( p ) + { + char *hostname; + + hostname = alloc_mem( p - d->host + strlen( hname ) + 2 ); + strncpy( hostname, d->host, p - d->host + 1 ); + strcat( hostname, hname ); + free_string( d->host ); + d->host = hostname; + } + else + { + free_string( d->host ); + d->host = str_dup( hname ); + } + + /* + * We now have a hostname, so check banishment. + */ + + /* + * NOT fully reliable. A fast typist on a fast link may + * get through the character generation process before the + * hostname lookup completes. + */ + newchar = ( d->connected == CON_CONFIRM_NEW_NAME || + d->connected == CON_GET_NEW_PASSWORD || + d->connected == CON_CONFIRM_NEW_PASSWORD || + d->connected == CON_GET_NEW_RACE || + d->connected == CON_GET_NEW_SEX || + d->connected == CON_GET_NEW_CLASS || + d->connected == CON_GET_ALIGNMENT || + d->connected == CON_GET_STATS ); + + for ( pban = ban_list; pban != NULL; pban = pban->next ) + { + if ( !str_suffix( pban->name, d->host ) && + ( newchar || pban->flag ) ) + { + if ( d->character == NULL || d->character->name == NULL ) + sprintf( log_buf, "[%s] has been banned", d->host ); + else + sprintf( log_buf, "%s [%s] has been banned", + d->character->name, d->host ); + log_string( log_buf ); + output_channel( NULL, log_buf, CHA_CONNECT ); + if (pban->flag) + write_to_buffer( d, "Your site has been banned" + " from this Mud.\n\r", 0 ); + else + write_to_buffer( d, "Your site has been banned" + " for new players.\n\r", 0 ); + close_socket( d, FALSE ); + return; + } + } + } + } +} + +void get_hname( void ) +{ + char buf[MAX_STRING_LENGTH + 1]; + char *p, *q, *r; + long addr; + int size; + + size = read( hname, buf, MAX_STRING_LENGTH ); + if ( size < 0 ) + { + close( hname ); + hname = -1; + } + + buf[size] = '\0'; + q = buf; + while ( (p = strchr( q, '\n' )) ) + { + *p = '\0'; + addr = inet_addr( q ); + r = strchr( q, ' ' ); + if ( addr && r ) + add_hname( ntohl( addr ), str_dup( r+1 ) ); + q = p + 1; + } +} +#endif void do_maxusers( CHAR_DATA *ch, char *argument ) @@ -1301,14 +1519,12 @@ void new_descriptor( int control ) { static DESCRIPTOR_DATA d_zero; - char buf[MAX_STRING_LENGTH]; DESCRIPTOR_DATA *dnew; /* BB: Unused DESCRIPTOR_DATA *test_list; */ BAN_DATA *pban; struct sockaddr_in sock; - struct hostent *from; int desc; int size; int iHistory; @@ -1361,32 +1577,12 @@ { perror( "New_descriptor: getpeername" ); dnew->host = str_dup( "(unknown)" ); + dnew->hostaddr = 0; } else { - /* - * Would be nice to use inet_ntoa here but it takes a struct arg, - * which ain't very compatible between gcc and system libraries. - */ - int addr; - - addr = ntohl( sock.sin_addr.s_addr ); - sprintf( buf, "%d.%d.%d.%d", - ( addr >> 24 ) & 0xFF, ( addr >> 16 ) & 0xFF, - ( addr >> 8 ) & 0xFF, ( addr ) & 0xFF - ); - /* - * Next two lines can be disabled to reduce lag. - */ - if ( fLookupAddress ) - { - from = gethostbyaddr( (char *) &sock.sin_addr, - sizeof(sock.sin_addr), AF_INET ); - } - else - from = NULL; - - dnew->host = str_dup( from ? from->h_name : buf ); + dnew->hostaddr = ntohl( sock.sin_addr.s_addr ); + query_hname( dnew ); } dnew->ident = new_ident( dnew ); @@ -1398,6 +1594,11 @@ * using automated 'autodialers' and leaving connections hanging. * * Furey: added suffix check by request of Nickel of HiddenWorlds. + */ + + /* + * At this point, the hostname may or may not be known. + * There is another check in get_hname(). */ for ( pban = ban_list; pban != NULL; pban = pban->next ) Only in src.hname: hname.c diff -u src.ident/makefile src.hname/makefile --- src.ident/makefile Wed Dec 6 15:17:16 1995 +++ src.hname/makefile Wed Jan 3 22:44:10 1996 @@ -10,6 +10,11 @@ interp.o newcommands.o magic.o save.o show.o special.o spells.o \ trap.o update.o +all: merc hname + +hname: hname.c + $(CC) $(D_FLAGS) $< -o hname + merc: $(O_FILES) $(CC) $(D_FLAGS) $(L_FLAGS) -o merc *.o diff -u src.ident/merc.h src.hname/merc.h --- src.ident/merc.h Thu Dec 28 02:30:36 1995 +++ src.hname/merc.h Wed Jan 3 22:50:51 1996 @@ -132,6 +132,7 @@ #define MAX_RACE 5 #define MAX_STAT 6 #define MAX_HISTORY 20 +#define MAX_HNAME 400 #define MAX_LEVEL 46 #define MAX_SKILL 212 #define MAX_SCAN_RANGE 3 @@ -269,6 +270,7 @@ char incomm [MAX_INPUT_LENGTH]; char * history [MAX_HISTORY]; sh_int nhistory; + long hostaddr; char * outbuf; int outsize; int outtop;