These patches are written by Dark@Igor for Dutch Mountains, in December 1995.
They are freely redistributable.
diff -u src.orig/comm.c src.ident/comm.c
--- src.orig/comm.c Fri Dec 15 16:23:26 1995
+++ src.ident/comm.c Wed Jan 3 22:41:48 1996
@@ -272,6 +272,8 @@
DESCRIPTOR_DATA * descriptor_free; /* Free list for descriptors */
DESCRIPTOR_DATA * descriptor_list; /* All open descriptors */
DESCRIPTOR_DATA * d_next; /* Next descriptor in loop */
+IDENT_DATA * ident_free; /* Free list for ident structs */
+IDENT_DATA * ident_list; /* Ident query structs in use */
FILE * fpReserve; /* Reserved filehandle */
FILE * fpReserveBug; /* Reserved filehandle for bugs */
bool god; /* All new chars are gods! */
@@ -302,6 +304,9 @@
void new_descriptor args( ( int control ) );
bool read_from_descriptor args( ( DESCRIPTOR_DATA *d ) );
bool write_to_descriptor args( ( int desc, char *txt, int length ) );
+void free_ident args( ( IDENT_DATA *id ) );
+IDENT_DATA * new_ident args( ( DESCRIPTOR_DATA *desc ) );
+void parse_ident args( ( IDENT_DATA *id ) );
#endif
@@ -440,7 +445,7 @@
int x = 1;
int fd;
- if ( ( fd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
+ if ( ( fd = socket( PF_INET, SOCK_STREAM, 0 ) ) < 0 )
{
perror( "Init_socket: socket" );
exit( 1 );
@@ -761,6 +766,7 @@
fd_set out_set;
fd_set exc_set;
DESCRIPTOR_DATA *d;
+ IDENT_DATA *id, *id_next;
int maxdesc, tmp;
#if defined(MALLOC_DEBUG)
@@ -780,9 +786,17 @@
{
maxdesc = UMAX( maxdesc, d->descriptor );
FD_SET( d->descriptor, &in_set );
- FD_SET( d->descriptor, &out_set );
FD_SET( d->descriptor, &exc_set );
}
+ for ( id = ident_list; id != NULL; id = id->next )
+ {
+ maxdesc = UMAX( maxdesc, id->descriptor );
+ if (id->connected)
+ FD_SET( id->descriptor, &in_set );
+ else
+ FD_SET( id->descriptor, &out_set );
+ }
+
if ( select( maxdesc+1, &in_set, &out_set, &exc_set, &null_time ) < 0 )
{
@@ -807,7 +821,6 @@
if ( FD_ISSET( d->descriptor, &exc_set ) )
{
FD_CLR( d->descriptor, &in_set );
- FD_CLR( d->descriptor, &out_set );
if ( d->character )
save_char_obj( d->character, TRUE );
d->outtop = 0;
@@ -825,6 +838,73 @@
}
+ /*
+ * Process ident queries.
+ */
+ for ( id = ident_list; id != NULL; id = id_next )
+ {
+ long size;
+ char * p;
+ struct sockaddr sa;
+ int salen = sizeof(sa);
+
+ id_next = id->next;
+ if ( !id->connected && FD_ISSET( id->descriptor, &out_set ) )
+ {
+ if ( getpeername( id->descriptor, &sa, &salen ) < 0 )
+ free_ident ( id );
+ else
+ {
+ char querybuf[20];
+ sprintf( querybuf, "%d,%d\r\n",
+ id->remoteport, id->localport );
+ write( id->descriptor, querybuf, strlen(querybuf) );
+ id->connected = TRUE;
+ id->timeout = current_time + IDENT_TIMEOUT;
+ }
+ }
+ else if ( FD_ISSET( id->descriptor, &in_set ) )
+ {
+ size = read( id->descriptor, id->reply_text + id->reply_pos,
+ IDENT_BUFFER - id->reply_pos );
+ if (size < 0)
+ free_ident( id );
+ else
+ {
+ bool complete = FALSE;
+
+ id->reply_pos += size;
+ if ( id->reply_pos == IDENT_BUFFER )
+ {
+ complete = TRUE;
+ id->reply_text[IDENT_BUFFER-2] = '\r';
+ id->reply_text[IDENT_BUFFER-1] = '\n';
+ }
+ else
+ {
+ for ( p = id->reply_text + id->reply_pos - 2;
+ p >= id->reply_text; p-- )
+ {
+ if ( *p == '\r' && *(p+1) == '\n' )
+ {
+ complete = TRUE;
+ break;
+ }
+ }
+ }
+ if ( complete )
+ {
+ parse_ident( id );
+ free_ident( id );
+ }
+ }
+ }
+ else if ( current_time > id->timeout )
+ {
+ free_ident( id );
+ }
+ }
+
/*
* Process input.
*/
@@ -841,7 +921,6 @@
d->original->timer = 0;
if ( !read_from_descriptor( d ) )
{
- FD_CLR( d->descriptor, &out_set );
if ( d->character != NULL )
save_char_obj( d->character, TRUE );
d->outtop = 0;
@@ -1007,6 +1086,8 @@
free_string( d->host );
free_mem( d->outbuf, d->outsize );
+ if ( d->ident )
+ free_ident ( d->ident );
for ( iHistory = 0; iHistory < MAX_HISTORY; iHistory++ )
free_string( GET_HISTORY(d, iHistory) );
d->next = descriptor_free;
@@ -1038,6 +1119,185 @@
/* END */
#if defined(unix)
+void free_ident( IDENT_DATA *id )
+{
+ if ( id->descriptor > 0 )
+ close( id->descriptor );
+ id->desc->ident = NULL;
+
+ if ( ident_list == id )
+ ident_list = ident_list->next;
+ else
+ {
+ IDENT_DATA *idp;
+
+ for ( idp = ident_list; idp; idp = idp->next )
+ {
+ if ( idp->next == id )
+ {
+ idp->next = id->next;
+ break;
+ }
+ }
+ }
+
+ id->next = ident_free;
+ ident_free = id;
+}
+
+IDENT_DATA *new_ident( DESCRIPTOR_DATA *desc )
+{
+ IDENT_DATA *id;
+ static IDENT_DATA id_zero;
+ sh_int d;
+ int localport, remoteport;
+ struct sockaddr_in sin;
+ size_t len = sizeof(sin);
+
+ if ( getsockname( desc->descriptor, (struct sockaddr *) &sin, &len ) < 0
+ || len < sizeof(sin) )
+ return NULL;
+ localport = ntohs( sin.sin_port );
+
+ /* This will also leave sin.sin_addr useful for connect() below. */
+ if ( getpeername( desc->descriptor, (struct sockaddr *) &sin, &len ) < 0
+ || len < sizeof(sin) )
+ return NULL;
+ remoteport = ntohs( sin.sin_port );
+
+ if ( (d = socket( PF_INET, SOCK_STREAM, 0 )) < 0 )
+ {
+ perror("Ident socket: socket");
+ return NULL;
+ }
+
+#if !defined(FNDELAY)
+#define FNDELAY O_NDELAY
+#endif
+
+ if ( fcntl ( d, F_SETFL, FNDELAY ) == -1 )
+ {
+ perror( "Ident socket: fcntl: FNDELAY" );
+ close( d );
+ return NULL;
+ }
+
+ /* sin.sin_addr was set by getpeername() above. */
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(113);
+ if ( connect( d, (struct sockaddr *) &sin, len ) < 0
+ && errno != EINPROGRESS && errno != EAGAIN )
+ {
+ close ( d );
+ return NULL;
+ }
+
+ if ( ident_free == NULL )
+ {
+ id = alloc_perm( sizeof(*id) );
+ }
+ else
+ {
+ id = ident_free;
+ ident_free = ident_free->next;
+ }
+
+ *id = id_zero;
+ id->desc = desc;
+ id->descriptor = d;
+ id->connected = FALSE;
+ id->timeout = current_time + IDENT_TIMEOUT;
+ id->remoteport = remoteport;
+ id->localport = localport;
+ id->next = ident_list;
+ ident_list = id;
+
+ return id;
+}
+
+void parse_ident( IDENT_DATA *id )
+{
+ char *p;
+ int remoteport, localport;
+ char replytype[40];
+ char foo;
+ int tmp;
+ char *ident;
+ char *hostid;
+ static char tokenchars[] =
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "-, .!@#$%^&*()_=+.,<>/?\"'~`{}[];";
+
+ if ( !(p = strstr( id->reply_text, "\r\n")) )
+ return;
+ *p = 0;
+
+ /*
+ * The extra argument "foo" is used because sscanf doesn't count
+ * a bare %n.
+ */
+ if ( sscanf( id->reply_text, "%d , %d : %39s : %n%c",
+ &remoteport, &localport, replytype, &tmp, &foo ) < 4
+ || remoteport != id->remoteport
+ || localport != id->localport )
+ return;
+
+ p = id->reply_text + tmp;
+
+ if ( strcmp( replytype, "ERROR" ) == 0 )
+ {
+ tmp = strspn( p, tokenchars );
+ if ( p[tmp] )
+ return;
+
+ if ( p[0] == 'X' )
+ ident = p + 1;
+ else if ( strcmp( p, "NO-USER" ) == 0 )
+ ident = "<nobody>";
+ else if ( strcmp( p, "HIDDEN-USER" ) == 0 )
+ ident = "<hidden>";
+ else
+ ident = "<error>";
+ }
+ else if ( strcmp( replytype, "USERID" ) == 0 )
+ {
+ /* Skip straight to the userid field */
+ p = strchr( p, ':' );
+ if ( p == NULL )
+ return;
+ p++;
+ /*
+ * The RFC says not to ignore leading whitespace here.
+ * Unfortunately, some servers get it wrong because of
+ * the example on line 109 of RFC1413.
+ */
+ ident = p + strspn( p, " \t" );
+ for ( p = ident; *p; p++ )
+ {
+ if ( !isprint( *p ) )
+ *p = '?';
+ }
+ }
+ else return;
+
+ if ( id->desc->host )
+ {
+ hostid = alloc_mem( strlen( ident ) + strlen( id->desc->host ) + 2 );
+ sprintf( hostid, "%s@%s", ident, id->desc->host );
+ free_string( id->desc->host );
+ }
+ else
+ {
+ hostid = alloc_mem( strlen( ident ) + 6 );
+ sprintf( hostid, "%s@NULL", ident );
+ }
+ id->desc->host = hostid;
+}
+#endif
+
+
+#if defined(unix)
void new_descriptor( int control )
{
static DESCRIPTOR_DATA d_zero;
@@ -1065,12 +1325,6 @@
#define FNDELAY O_NDELAY
#endif
- if ( fcntl( control, F_SETFL, FNDELAY ) == -1 )
- {
- perror( "New_descriptor: fcntl: FNDELAY" );
- return;
- }
-
if ( fcntl( desc, F_SETFL, FNDELAY ) == -1 )
{
perror( "New_descriptor: fcntl: FNDELAY" );
@@ -1134,6 +1388,8 @@
dnew->host = str_dup( from ? from->h_name : buf );
}
+
+ dnew->ident = new_ident( dnew );
/*
* Swiftest: I added the following to ban sites. I don't
diff -u src.orig/merc.h src.ident/merc.h
--- src.orig/merc.h Tue Dec 12 17:12:05 1995
+++ src.ident/merc.h Thu Dec 28 02:30:36 1995
@@ -82,6 +82,7 @@
typedef struct extra_descr_data EXTRA_DESCR_DATA;
typedef struct trap_data TRAP_DATA;
typedef struct help_data HELP_DATA;
+typedef struct ident_data IDENT_DATA;
typedef struct mob_index_data MOB_INDEX_DATA;
typedef struct name_ban_data NAME_BAN_DATA;
typedef struct note_data NOTE_DATA;
@@ -259,6 +260,7 @@
DESCRIPTOR_DATA * snoop_by;
CHAR_DATA * character;
CHAR_DATA * original;
+ IDENT_DATA * ident;
char * host;
sh_int descriptor;
sh_int connected;
@@ -277,7 +279,24 @@
int showstr_len;
};
+#define IDENT_TIMEOUT 120 /* 2 minutes */
+#define IDENT_BUFFER 1024
+/*
+ * Data for Ident (RFC1413) queries.
+ */
+struct ident_data
+{
+ IDENT_DATA * next;
+ DESCRIPTOR_DATA * desc;
+ sh_int descriptor;
+ bool connected;
+ time_t timeout;
+ sh_int localport;
+ sh_int remoteport;
+ sh_int reply_pos;
+ char reply_text [IDENT_BUFFER];
+};
/*
* Attribute bonus structures.