Subject: Disinfectant 3.4 and 1.3

From: Shahrol <[email-masked]>
Date: Tue, 8 Mar 1994 19:39:05 -0800 (PST)

Hi all,

I downloaded a copy of Disinfectant 3.4 and installed it in our Ultrix
4.3 machine runnin Netatalk 1.3.  copying the app from the server and
launching it would cause the mac to crash.  running Disinfectant from
the server would also cause the mac to crash.

the macs we tested this on were running 7.1 and 7Pro, Centris 650 and
IIfx.   

anyone else saw this?  3.4 launches fine from CAP servers...

-shahrol

---

From: [email-masked]
Date: Tue, 15 Mar 1994 16:29:16 -0500

> From:    Shahrol <[email-masked]>
> To:      [email-masked]

> the server would also cause the mac to crash.

Nasty bug, introduced in netatalk 1.3.  Please find enclosed a patch
which will bring netatalk up to 1.3.1.  This patch is also available
via anonymous ftp from terminator.rs.itd.umich.edu in
~ftp/unix/netatalk.

:wes

--- cut ---
This patch upgrades netatalk 1.3 to 1.3.1.  There is at least one
"critical" patch for those using afpd, and several less critical
patches.  See the patched file "CHANGES" for details.  Apply this patch
by changing directories to the root of your netatalk 1.3 distribution,
and running

	patch -p -s < netatalk-1.3-1.3.1.patch

Please report any problems to [email-masked].

:wes

Prereq: 1.3

*** VERSION-	1994/01/18 23:30:12
--- VERSION	1994/03/15 20:49:59
***************
*** 1 ****
! 1.3
--- 1 ----
! 1.3.1
*** CHANGES-	1994/01/19 00:04:34
--- CHANGES	1994/03/15 20:29:45
***************
*** 1,5 ****
! This is the CHANGES file for netatalk-1.3.  Changes from the 1.2.1
! release:
  
      atalkd is completely rewritten for phase 2 support.  atalkd.conf
      from previous version will not work!
--- 1,30 ----
! Changes from the 1.3 release:
! 
!     Fixed a bug in afpd which would cause APPL mappings to contain both
!     mac and unix path names.  The fixed code will handle the old
!     (corrupted) database.
! 
!     Fixed a *very* serious bug which would cause files to be corrupted
!     when copying to afpd.
! 
!     Fixed a bug in afpd which would cause replies to icon writes to
!     contain the written icon.
! 
!     Filled in the function code switch in afpd.  Previously, a hacker
!     could probably have used afpd to get unauthorized access to a
!     machine running afpd.
! 
!     Fixed a bug in the asp portion of libatalk.a which could cause the
!     malloc()/free() database to be corrupted.
! 
!     Fixed a bug in atalkd's zip query code.  With this bug, only the
!     first N % 255 nets get queried.  However, since nets bigger than
!     255 are usually pretty unstable, the unqueried for nets will
!     eventually get done, when N drops by one.
! 
!     Suppressed a spurious error ("route: No such process") in atalkd.
! 
! Changes from the 1.2.1 release:
  
      atalkd is completely rewritten for phase 2 support.  atalkd.conf
      from previous version will not work!
*** etc/afpd/Makefile-	1993/12/23 21:13:45
--- etc/afpd/Makefile	1994/01/28 22:12:56
***************
*** 50,56 ****
  OBJ = ${OSO} main.o switch.o auth.o volume.o directory.o file.o \
  	enumerate.o desktop.o filedir.o fork.o appl.o gettok.o bprint.o
  
! CFLAGS=	${AFSDEFS} ${DEFS} ${OPTOPTS} ${INCPATH} -DPRIMETRASH
  TAGSFILE=	tags
  CC=	cc
  INSTALL=	install
--- 50,56 ----
  OBJ = ${OSO} main.o switch.o auth.o volume.o directory.o file.o \
  	enumerate.o desktop.o filedir.o fork.o appl.o gettok.o bprint.o
  
! CFLAGS=	${AFSDEFS} ${DEFS} ${OPTOPTS} ${INCPATH} -DPRIMETRASH -DAPPLCNAME
  TAGSFILE=	tags
  CC=	cc
  INSTALL=	install
*** etc/afpd/appl.c-	1993/12/23 20:20:01
--- etc/afpd/appl.c	1994/02/02 18:00:04
***************
*** 13,18 ****
--- 13,19 ----
  #include <sys/errno.h>
  #include <atalk/afp.h>
  #include <strings.h>
+ #include <ctype.h>
  
  #include "volume.h"
  #include "globals.h"
***************
*** 112,118 ****
      return( AFP_OK );
  }
  
- 
  afp_rmvappl( ibuf, ibuflen, rbuf, rbuflen )
      char	*ibuf, *rbuf;
      int		ibuflen, *rbuflen;
--- 113,118 ----
***************
*** 184,190 ****
      return( AFP_OK );
  }
  
- 
  afp_getappl( ibuf, ibuflen, rbuf, rbuflen )
      char	*ibuf, *rbuf;
      int		ibuflen, *rbuflen;
--- 184,189 ----
***************
*** 253,258 ****
--- 252,294 ----
  	return( AFPERR_NOITEM );
      }
      sa.sdt_index++;
+ 
+ #ifdef APPLCNAME
+     /*
+      * Check to see if this APPL mapping has an mpath or a upath.  If
+      * there are any ':'s in the name, it is a upath and must be converted
+      * to an mpath.  Hopefully, this code will go away.
+      */
+     {
+ #define hextoint( c )	( isdigit( c ) ? c - '0' : c + 10 - 'a' )
+ #define islxdigit(x)	(!isupper(x)&&isxdigit(x))
+ 
+ 	static char	utomname[ MAXPATHLEN ];
+ 	char		*u, *m;
+ 	int		i, h;
+ 
+ 	u = p;
+ 	m = utomname;
+ 	i = len;
+ 	while ( i ) {
+ 	    if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
+ 		    *(u+2) != '\0' && islxdigit( *(u+2))) {
+ 		++u, --i;
+ 		h = hextoint( *u ) << 4;
+ 		++u, --i;
+ 		h |= hextoint( *u );
+ 		*m++ = h;
+ 	    } else {
+ 		*m++ = *u;
+ 	    }
+ 	    ++u, --i;
+ 	}
+ 
+ 	len = m - utomname;
+ 	p = utomname;
+     }
+ #endif APPLCNAME
+ 
      if (( p = cname( vol, vol->v_dir, &p, len )) == NULL ) {
  	*rbuflen = 0;
  	return( AFPERR_NOITEM );
***************
*** 278,284 ****
      return( AFP_OK );
  }
  
- 
  applopen( vol, creator, flags, mode )
      struct vol	*vol;
      u_char	creator[ 4 ];
--- 314,319 ----
***************
*** 325,331 ****
      return( AFP_OK );
  }
  
! 
  char *
  makemacpath( mpath, mpathlen, dir, path )
      char	*mpath;
--- 360,377 ----
      return( AFP_OK );
  }
  
! /*
!  * build mac. path (backwards) by traversing the directory tree
!  *
!  * The old way: dir and path refer to an app, path is a mac format
!  * pathname.  makemacpath() builds something that looks like a cname,
!  * but uses upaths instead of mac format paths.
!  *
!  * The new way: dir and path refer to an app, path is a mac format
!  * pathname.  makemacpath() builds a cname.
!  *
!  * See afp_getappl() for the backward compatiblity code.
!  */
  char *
  makemacpath( mpath, mpathlen, dir, path )
      char	*mpath;
***************
*** 334,357 ****
      char	*path;
  {
      char	*p, *s;
! /*
!  * build mac. path (backwards) by traversing the directory tree
!  */
      p = mpath + mpathlen;
!     s = mtoupath( path );
!     p -= strlen( s ) + 1;
!     strcpy( p, s );
  
      while ( dir->d_parent != NULL ) {
! 	s = mtoupath( dir->d_name );
! 	p -= strlen( s ) + 1;
! 	strcpy( p, s );
  	dir = dir->d_parent;
      }
      return( p ); 
  }
  
! 
  copyapplfile( sfd, dfd, mpath, mplen )
      int		sfd;
      int		dfd;
--- 380,401 ----
      char	*path;
  {
      char	*p, *s;
! 
      p = mpath + mpathlen;
!     p -= strlen( path ) + 1;
!     strcpy( p, path );
  
      while ( dir->d_parent != NULL ) {
! 	p -= strlen( dir->d_name ) + 1;
! 	strcpy( p, dir->d_name );
  	dir = dir->d_parent;
      }
      return( p ); 
  }
  
! /*
!  * copy appls to new file, deleting any matching (old) appl entries
!  */
  copyapplfile( sfd, dfd, mpath, mplen )
      int		sfd;
      int		dfd;
***************
*** 363,371 ****
      u_short	len;
      u_char	appltag[ 4 ];
      char	buf[ MAXPATHLEN ];
! /*
!  * copy appls to new file, deleting any matching (old) appl entries
! */
      while (( cc = read( sfd, buf, sizeof(appltag) + sizeof( u_short ))) > 0 ) {
  	p = buf + sizeof(appltag);
  	bcopy( p, &len, sizeof( u_short ));
--- 407,413 ----
      u_short	len;
      u_char	appltag[ 4 ];
      char	buf[ MAXPATHLEN ];
! 
      while (( cc = read( sfd, buf, sizeof(appltag) + sizeof( u_short ))) > 0 ) {
  	p = buf + sizeof(appltag);
  	bcopy( p, &len, sizeof( u_short ));
***************
*** 384,390 ****
      }
      return( cc );
  }
- 
  
  pathcmp( p, plen, q, qlen )
      char	*p;
--- 426,431 ----
*** etc/afpd/desktop.c-	1993/12/23 20:20:01
--- etc/afpd/desktop.c	1994/03/09 16:57:21
***************
*** 67,73 ****
      struct vol		*vol;
      struct iovec	iov[ 2 ];
      u_char		fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
!     int			ftype, itype, itag, cc, iovcnt = 0;
      u_short		bsize, rsize, vid;
  
      *rbuflen = 0;
--- 67,73 ----
      struct vol		*vol;
      struct iovec	iov[ 2 ];
      u_char		fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
!     int			ftype, itype, itag, cc, iovcnt = 0, buflen;
      u_short		bsize, rsize, vid;
  
      *rbuflen = 0;
***************
*** 99,105 ****
  	si.sdt_fd = -1;
      }
      if ( iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) != AFP_OK ) {
- 	syslog( LOG_ERR, "afp_addicon: iconopen: no item" );
  	return( AFPERR_NOITEM );
      }
  
--- 99,104 ----
***************
*** 152,159 ****
  	return( AFPERR_PARAM );
      }
  
!     *rbuflen = bsize;
!     if ( asp_wrtcont( asp, rbuf, rbuflen ) < 0 ) {
  	return( AFPERR_PARAM );
      }
  
--- 151,158 ----
  	return( AFPERR_PARAM );
      }
  
!     buflen = bsize;
!     if ( asp_wrtcont( asp, rbuf, &buflen ) < 0 || buflen != bsize ) {
  	return( AFPERR_PARAM );
      }
  
*** etc/afpd/directory.c-	1993/12/23 20:20:01
--- etc/afpd/directory.c	1994/01/28 19:54:17
***************
*** 121,127 ****
  	return( NULL );
      }
  
!     if (( dir = adddir( vol, dir, p, strlen( p ))) == NULL ) {
  	return( NULL );
      }
  
--- 121,127 ----
  	return( NULL );
      }
  
!     if (( dir = adddir( vol, dir, path, strlen( path ))) == NULL ) {
  	return( NULL );
      }
  
*** etc/afpd/fork.c-	1993/12/23 20:20:01
--- etc/afpd/fork.c	1994/03/15 02:30:52
***************
*** 250,257 ****
  	    syslog( LOG_ERR, "afp_setforkparams: ad_dtruncate: %m" );
  	    return( AFPERR_PARAM );
  	}
!     }
!     if ( ad_hfileno( &oforks[ ofrefnum ]->of_ad ) != -1 ) {
  	bcopy( ad_entry( &oforks[ ofrefnum ]->of_ad, ADEID_FILEI ) +
  		FILEIOFF_MODIFY, &intime, sizeof( intime ));
  	ad_refresh( &oforks[ ofrefnum ]->of_ad, ADFLAGS_HF );
--- 250,256 ----
  	    syslog( LOG_ERR, "afp_setforkparams: ad_dtruncate: %m" );
  	    return( AFPERR_PARAM );
  	}
!     } else if ( ad_hfileno( &oforks[ ofrefnum ]->of_ad ) != -1 ) {
  	bcopy( ad_entry( &oforks[ ofrefnum ]->of_ad, ADEID_FILEI ) +
  		FILEIOFF_MODIFY, &intime, sizeof( intime ));
  	ad_refresh( &oforks[ ofrefnum ]->of_ad, ADFLAGS_HF );
*** etc/afpd/main.c-	1993/12/23 21:10:06
--- etc/afpd/main.c	1994/01/26 22:47:00
***************
*** 238,244 ****
  	syslog( LOG_ERR, "Can't register %s:%s@%s", Obj, Type, Zone );
  	exit( 1 );
      }
!     syslog( LOG_INFO, "%s:%s@%s started", Obj, Type, Zone );
  
      sv.sv_handler = afp_goaway;
      sv.sv_mask = 0;
--- 246,255 ----
  	syslog( LOG_ERR, "Can't register %s:%s@%s", Obj, Type, Zone );
  	exit( 1 );
      }
!     syslog( LOG_INFO, "%s:%s@%s started on %u.%u:%u", Obj, Type, Zone,
! 	    ntohs( atp_sockaddr( atp )->sat_addr.s_net ),
! 	    atp_sockaddr( atp )->sat_addr.s_node,
! 	    atp_sockaddr( atp )->sat_port );
  
      sv.sv_handler = afp_goaway;
      sv.sv_mask = 0;
***************
*** 273,278 ****
--- 284,296 ----
  	exit( 1 );
      }
  
+     syslog( LOG_INFO, "session from %u.%u:%u on %u.%u:%u",
+ 	    ntohs( child->asp_sat.sat_addr.s_net ),
+ 	    child->asp_sat.sat_addr.s_node, child->asp_sat.sat_port,
+ 	    ntohs( atp_sockaddr( child->asp_atp )->sat_addr.s_net ),
+ 	    atp_sockaddr( child->asp_atp )->sat_addr.s_node,
+ 	    atp_sockaddr( child->asp_atp )->sat_port );
+ 
      for (;;) {
  	buf = data;
  	buflen = sizeof( data );
***************
*** 280,285 ****
--- 298,306 ----
  	case ASPFUNC_CLOSE :
  	    asp_close( child );
  	    syslog( LOG_INFO, "done" );
+ 	    if ( debug ) {
+ 		printf( "done\n" );
+ 	    }
  	    exit( 0 );
  	    break;
  	case ASPFUNC_CMD :
***************
*** 297,308 ****
  		 */
  		rbuflen = sizeof( replybuf );
  		c = (*afp_switch[ func ])( buf, buflen, replybuf, &rbuflen );
! 		if ( debug ) {
! 		    printf( "reply: %d, %d\n", c, ccnt++ );
! 		    bprint( replybuf, rbuflen );
! 		}
! 		asp_cmdreply( child, htonl( c ), replybuf, rbuflen );
  	    }
  	    break;
  	case ASPFUNC_WRITE :
  	    func = (u_char)buf[ 0 ];
--- 318,333 ----
  		 */
  		rbuflen = sizeof( replybuf );
  		c = (*afp_switch[ func ])( buf, buflen, replybuf, &rbuflen );
! 	    } else {
! 		syslog( LOG_ERR, "bad function %X", func );
! 		rbuflen = 0;
! 		c = AFPERR_NOOP;
  	    }
+ 	    if ( debug ) {
+ 		printf( "reply: %d, %d\n", c, ccnt++ );
+ 		bprint( replybuf, rbuflen );
+ 	    }
+ 	    asp_cmdreply( child, htonl( c ), replybuf, rbuflen );
  	    break;
  	case ASPFUNC_WRITE :
  	    func = (u_char)buf[ 0 ];
***************
*** 314,325 ****
  		rbuflen = sizeof( replybuf );
  		c = (*afp_switch[ func ])( child, buf, buflen, replybuf,
  			    &rbuflen );
! 		if ( debug ) {
! 		    printf( "(write) reply code: %d, %d\n", c, ccnt++ );
! 		    bprint( replybuf, rbuflen );
! 		}
! 		asp_wrtreply( child, htonl( c ), replybuf, rbuflen );
  	    }
  	    break;
  	default:
  	    /*
--- 339,354 ----
  		rbuflen = sizeof( replybuf );
  		c = (*afp_switch[ func ])( child, buf, buflen, replybuf,
  			    &rbuflen );
! 	    } else {
! 		syslog( LOG_ERR, "(write) bad function %X", func );
! 		rbuflen = 0;
! 		c = AFPERR_NOOP;
! 	    }
! 	    if ( debug ) {
! 		printf( "(write) reply code: %d, %d\n", c, ccnt++ );
! 		bprint( replybuf, rbuflen );
  	    }
+ 	    asp_wrtreply( child, htonl( c ), replybuf, rbuflen );
  	    break;
  	default:
  	    /*
*** etc/afpd/switch.c-	1992/01/22 23:13:52
--- etc/afpd/switch.c	1994/01/25 21:25:22
***************
*** 110,115 ****
--- 110,174 ----
      NULL, NULL, NULL, NULL,
      NULL, NULL, NULL, NULL,					/*   8 -  15 */
      NULL, NULL, afp_login, afp_logincont,
+     NULL, NULL, NULL, NULL,					/*  16 -  23 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/*  24 -  31 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/*  32 -  39 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/*  40 -  47 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/*  48 -  55 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/*  56 -  63 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/*  64 -  71 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/*  72 -  79 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/*  80 -  87 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/*  88 -  95 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/*  96 - 103 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 104 - 111 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 112 - 119 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 120 - 127 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 128 - 135 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 136 - 143 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 144 - 151 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 152 - 159 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 160 - 167 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 168 - 175 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 176 - 183 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 184 - 191 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 192 - 199 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 200 - 207 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 208 - 215 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 216 - 223 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 224 - 231 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 232 - 239 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 240 - 247 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 248 - 255 */
  };
  
  int	(**afp_switch)() = preauth_switch;
***************
*** 166,169 ****
--- 225,242 ----
      NULL, NULL, NULL, NULL,					/* 184 - 191 */
      afp_addicon, NULL, NULL, NULL,
      NULL, NULL, NULL, NULL,					/* 192 - 199 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 200 - 207 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 208 - 215 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 216 - 223 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 224 - 231 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 232 - 239 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 240 - 247 */
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,					/* 248 - 255 */
  };
*** libatalk/asp/asp_child.h-	1992/01/22 23:13:52
--- libatalk/asp/asp_child.h	1994/01/31 21:36:35
***************
*** 27,31 ****
      struct sockaddr_at	ac_sat;
  };
  
! #define ACSTATE_OK	0
! #define ACSTATE_BAD	6
--- 27,32 ----
      struct sockaddr_at	ac_sat;
  };
  
! #define ACSTATE_DEAD	0
! #define ACSTATE_OK	1
! #define ACSTATE_BAD	7
*** libatalk/asp/asp_getsess.c-	1993/12/23 22:20:03
--- libatalk/asp/asp_getsess.c	1994/02/04 00:49:48
***************
*** 59,77 ****
      int			sid;
  
      for ( sid = 0; sid < asp_sessions; sid++ ) {
! 	if ( asp_ac[ sid ] == NULL ) {
  	    continue;
  	}
! 	asp_ac[ sid ]->ac_state++;
! 	if ( asp_ac[ sid ]->ac_state >= ACSTATE_BAD ) {
  	    if ( kill( asp_ac[ sid ]->ac_pid, SIGTERM ) < 0 ) {
  		syslog( LOG_ERR, "kill: %m" );
  		/*
! 		 * Child is gone (for some reason), clean
! 		 * up after it.
  		 */
! 		free( asp_ac[ sid ] );
! 		asp_ac[ sid ] = NULL;
  	    }
  	    syslog( LOG_INFO, "asp_alrm: %d timed out",
  		    asp_ac[ sid ]->ac_pid );
--- 59,77 ----
      int			sid;
  
      for ( sid = 0; sid < asp_sessions; sid++ ) {
! 	if ( asp_ac[ sid ] == NULL ||
! 		asp_ac[ sid ]->ac_state == ACSTATE_DEAD ) {
  	    continue;
  	}
! 
! 	if ( ++asp_ac[ sid ]->ac_state >= ACSTATE_BAD ) {
  	    if ( kill( asp_ac[ sid ]->ac_pid, SIGTERM ) < 0 ) {
  		syslog( LOG_ERR, "kill: %m" );
  		/*
! 		 * Child is gone (for some reason), mark it to
! 		 * be clean up.
  		 */
! 		asp_ac[ sid ]->ac_state = ACSTATE_DEAD;
  	    }
  	    syslog( LOG_INFO, "asp_alrm: %d timed out",
  		    asp_ac[ sid ]->ac_pid );
***************
*** 116,121 ****
--- 116,125 ----
  		break;
  	    }
  	}
+ 	if ( sid >= asp_sessions ) {
+ 	    syslog( LOG_INFO, "asp_chld spurious child %d", pid );
+ 	    continue;
+ 	}
  
  	if ( WIFEXITED( status )) {
  	    if ( WEXITSTATUS( status )) {
***************
*** 134,143 ****
  	    }
  	}
  
! 	if ( asp_ac[ sid ] != NULL ) {
! 	    free( asp_ac[ sid ] );
! 	    asp_ac[ sid ] = NULL;
! 	}
      }
      return;
  }
--- 138,144 ----
  	    }
  	}
  
! 	asp_ac[ sid ]->ac_state = ACSTATE_DEAD;
      }
      return;
  }
***************
*** 161,167 ****
      ATP			atp;
      ASP			aspret;
      char		rdata[ ATP_MAXDATA ];
!     int			sid, pid;
      extern int		errno;
  
      if (( asp_ac =
--- 162,169 ----
      ATP			atp;
      ASP			aspret;
      char		rdata[ ATP_MAXDATA ];
!     int			sid, csid, pid;
!     u_short		asperr;
      extern int		errno;
  
      if (( asp_ac =
***************
*** 229,241 ****
  	    }
  	    break;
  	case ASPFUNC_OPEN :
! 	    for ( sid = 0; sid < sessions; sid++ ) {
! 		if ( asp_ac[ sid ] == NULL ) {
  		    break;
  		}
  	    }
! 	    if ( sid == sessions ) {				/* Too many */
! 		*(short *)&rdata[ 2 ] = ASPERR_SERVBUSY;
  	    } else {
  		if (( atp = atp_open( 0 )) == NULL ) {
  		    break;
--- 231,251 ----
  	    }
  	    break;
  	case ASPFUNC_OPEN :
! 	    for ( csid = 0; csid < sessions; csid++ ) {
! 		if ( asp_ac[ csid ] == NULL ) {
! 		    break;
! 		}
! 		/* check for stuff to free */
! 		if ( asp_ac[ csid ]->ac_state == ACSTATE_DEAD ) {
! 		    free( asp_ac[ csid ] );
! 		    asp_ac[ csid ] = NULL;
  		    break;
  		}
  	    }
! 	    if ( csid == sessions ) {				/* Too many */
! 		rdata[ 0 ] = 0;
! 		rdata[ 1 ] = 0;
! 		asperr = ASPERR_SERVBUSY;
  	    } else {
  		if (( atp = atp_open( 0 )) == NULL ) {
  		    break;
***************
*** 242,247 ****
--- 252,262 ----
  		}
  		switch ( pid = fork()) {
  		case 0 :					/* child */
+ 		    for ( sid = 0; sid < sessions; sid++ ) {
+ 			if ( asp_ac[ sid ] != NULL ) {
+ 			    free( asp_ac[ sid ] );
+ 			}
+ 		    }
  		    free( asp_ac );
  		    if ( sigvec( SIGALRM, &oasv, 0 ) < 0 ) {
  			return( NULL );
***************
*** 261,294 ****
  		    aspret->asp_wss = rdata[ 1 ];
  		    aspret->asp_seq = 0;
  		    aspret->asp_flags = ASPFL_SSS;
! 		    aspret->asp_sid = sid;
  		    return( aspret );
  
  		case -1 :					/* error */
! 		    *(short *)&rdata[ 2 ] = ASPERR_SERVBUSY;
  		    break;
  		default :
! 		    if (( asp_ac[ sid ] =
  			(struct asp_child *)malloc( sizeof( struct asp_child )))
  			== NULL ) {
  			break;
  		    }
! 		    asp_ac[ sid ]->ac_pid = pid;
! 		    asp_ac[ sid ]->ac_state = ACSTATE_OK;
! 		    asp_ac[ sid ]->ac_sat = sat;
! 		    asp_ac[ sid ]->ac_sat.sat_port = rdata[ 1 ];
! 		    *(short *)&rdata[ 2 ] = ASPERR_OK;
  		    break;
  		}
  	    }
! 	    rdata[ 0 ] = atp_sockaddr( atp )->sat_port;
! 	    rdata[ 1 ] = sid;
  	    iov[ 0 ].iov_base = rdata;
  	    iov[ 0 ].iov_len = 4;
  	    atpb.atp_sresiov = iov;
  	    atpb.atp_sresiovcnt = 1;
  	    atp_sresp( asp->asp_atp, &atpb );
- 	    atp_close( atp );
  	    break;
  
  	case ASPFUNC_TICKLE :
--- 276,312 ----
  		    aspret->asp_wss = rdata[ 1 ];
  		    aspret->asp_seq = 0;
  		    aspret->asp_flags = ASPFL_SSS;
! 		    aspret->asp_sid = csid;
  		    return( aspret );
  
  		case -1 :					/* error */
! 		    rdata[ 0 ] = 0;
! 		    rdata[ 1 ] = 0;
! 		    asperr = ASPERR_SERVBUSY;
  		    break;
  		default :
! 		    if (( asp_ac[ csid ] =
  			(struct asp_child *)malloc( sizeof( struct asp_child )))
  			== NULL ) {
  			break;
  		    }
! 		    asp_ac[ csid ]->ac_pid = pid;
! 		    asp_ac[ csid ]->ac_state = ACSTATE_OK;
! 		    asp_ac[ csid ]->ac_sat = sat;
! 		    asp_ac[ csid ]->ac_sat.sat_port = rdata[ 1 ];
! 		    rdata[ 0 ] = atp_sockaddr( atp )->sat_port;
! 		    rdata[ 1 ] = csid;
! 		    asperr = ASPERR_OK;
! 		    atp_close( atp );
  		    break;
  		}
  	    }
! 	    bcopy( &asperr, &rdata[ 2 ], sizeof( u_short ));
  	    iov[ 0 ].iov_base = rdata;
  	    iov[ 0 ].iov_len = 4;
  	    atpb.atp_sresiov = iov;
  	    atpb.atp_sresiovcnt = 1;
  	    atp_sresp( asp->asp_atp, &atpb );
  	    break;
  
  	case ASPFUNC_TICKLE :
***************
*** 313,323 ****
      int		sid;
  
      for ( sid = 0; sid < asp_sessions; sid++ ) {
! 	if ( asp_ac[ sid ] != NULL ) {
  	    if ( kill( asp_ac[ sid ]->ac_pid, signal ) < 0 ) {
  		syslog( LOG_ERR, "asp_kill %d: %m", asp_ac[ sid ]->ac_pid );
! 		free( asp_ac[ sid ] );
! 		asp_ac[ sid ] = NULL;
  	    }
  	}
      }
--- 331,341 ----
      int		sid;
  
      for ( sid = 0; sid < asp_sessions; sid++ ) {
! 	if ( asp_ac[ sid ] != NULL &&
! 		asp_ac[ sid ]->ac_state != ACSTATE_DEAD ) {
  	    if ( kill( asp_ac[ sid ]->ac_pid, signal ) < 0 ) {
  		syslog( LOG_ERR, "asp_kill %d: %m", asp_ac[ sid ]->ac_pid );
! 		asp_ac[ sid ]->ac_state = ACSTATE_DEAD;
  	    }
  	}
      }
***************
*** 330,336 ****
      int			sid;
  
      for ( sid = 0; sid < asp_sessions; sid++ ) {
! 	if ( asp_ac[ sid ] == NULL ) {
  	    continue;
  	}
  	if ( asp_attention( code, sid ) < 0 ) {
--- 348,355 ----
      int			sid;
  
      for ( sid = 0; sid < asp_sessions; sid++ ) {
! 	if ( asp_ac[ sid ] == NULL ||
! 		asp_ac[ sid ]->ac_state == ACSTATE_DEAD ) {
  	    continue;
  	}
  	if ( asp_attention( code, sid ) < 0 ) {
***************
*** 340,345 ****
--- 359,367 ----
      return( 0 );
  }
  
+ /*
+  * Note that code is passed in network byte-order (foolishly).
+  */
  asp_attention( code, sid )
      short	code, sid;
  {
***************
*** 348,359 ****
      char		sdata[ 4 ], rdata[ 4 ];
  
      sdata[ 0 ] = ASPFUNC_ATTN;
!     sdata[ 2 ] = ((char *)&code)[ 0 ];
!     sdata[ 3 ] = ((char *)&code)[ 1 ];
      iov[ 0 ].iov_base = rdata;
      iov[ 0 ].iov_len = sizeof( rdata );
  
!     if ( asp_ac[ sid ] == NULL ) {
  	return( -1 );
      }
      sdata[ 1 ] = sid;
--- 370,380 ----
      char		sdata[ 4 ], rdata[ 4 ];
  
      sdata[ 0 ] = ASPFUNC_ATTN;
!     bcopy( &code, &sdata[ 2 ], sizeof( short ));
      iov[ 0 ].iov_base = rdata;
      iov[ 0 ].iov_len = sizeof( rdata );
  
!     if ( asp_ac[ sid ] == NULL || asp_ac[ sid ]->ac_state == ACSTATE_DEAD ) {
  	return( -1 );
      }
      sdata[ 1 ] = sid;
*** etc/atalkd/main.c-	1994/01/03 23:51:16
--- etc/atalkd/main.c	1994/02/04 01:01:39
***************
*** 284,290 ****
  		 */
  		if ( rtmp->rt_iprev &&
  			( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
! 		    if ( data + sizeof( u_short ) > end ) {
  			/* send what we've got */
  			zh.zh_op = ZIPOP_QUERY;
  			zh.zh_count = n;
--- 284,290 ----
  		 */
  		if ( rtmp->rt_iprev &&
  			( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
! 		    if ( data + sizeof( u_short ) > end || n == 255 ) {
  			/* send what we've got */
  			zh.zh_op = ZIPOP_QUERY;
  			zh.zh_count = n;
*** etc/atalkd/rtmp.c-	1993/12/23 21:43:48
--- etc/atalkd/rtmp.c	1994/02/04 01:01:05
***************
*** 312,319 ****
  		    rtmp->rt_next = 0;
  		}
  	    } else if (( rt.rt_dist & 0x7f ) + 1 > RTMPHOPS_MAX ) {
! 		syslog( LOG_INFO, "rtmp_packet bad hop count from %u.%u",
! 			ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
  	    } else {		/* new for router */
  		if (( rtmp = (struct rtmptab *)malloc(sizeof(struct rtmptab)))
  			== 0 ) {
--- 312,320 ----
  		    rtmp->rt_next = 0;
  		}
  	    } else if (( rt.rt_dist & 0x7f ) + 1 > RTMPHOPS_MAX ) {
! 		syslog( LOG_INFO, "rtmp_packet bad hop count from %u.%u for %u",
! 			ntohs( from->sat_addr.s_net ), from->sat_addr.s_node,
! 			ntohs( rt.rt_net ));
  	    } else {		/* new for router */
  		if (( rtmp = (struct rtmptab *)malloc(sizeof(struct rtmptab)))
  			== 0 ) {
***************
*** 547,553 ****
      }
      if ( cmd == RTMP_ADD ) {
  	iface->i_flags |= IFACE_LOOP;
!     } else {
  	iface->i_flags &= ~IFACE_LOOP;
      }
      return( 0 );
--- 548,555 ----
      }
      if ( cmd == RTMP_ADD ) {
  	iface->i_flags |= IFACE_LOOP;
!     }
!     if ( cmd == RTMP_DEL ) {
  	iface->i_flags &= ~IFACE_LOOP;
      }
      return( 0 );
***************
*** 560,565 ****
--- 562,574 ----
      struct sockaddr_at	dst, gate;
      unsigned short	net;
  
+     if ( command == RTMP_DEL && ( rtmp->rt_flags & RTMPTAB_ROUTE ) == 0 ) {
+ 	return( -1 );
+     }
+     if ( command == RTMP_ADD && ( rtmp->rt_flags & RTMPTAB_ROUTE )) {
+ 	return( -1 );
+     }
+ 
      /*
       * Since we will accept routes from gateways who advertise their
       * address as 0.YY, we must munge the gateway address we give to
***************
*** 585,593 ****
  	if ( route( command, &dst, &gate, RTF_UP | RTF_GATEWAY )) {
  	    syslog( LOG_ERR, "route: %u -> %u.%u: %m", net,
  		    ntohs( gate.sat_addr.s_net ), gate.sat_addr.s_node );
! 	    return( -1 );
  	}
      } while ( net++ < ntohs( rtmp->rt_lastnet ));
  
      return( 0 );
  }
--- 594,609 ----
  	if ( route( command, &dst, &gate, RTF_UP | RTF_GATEWAY )) {
  	    syslog( LOG_ERR, "route: %u -> %u.%u: %m", net,
  		    ntohs( gate.sat_addr.s_net ), gate.sat_addr.s_node );
! 	    continue;
  	}
      } while ( net++ < ntohs( rtmp->rt_lastnet ));
+ 
+     if ( command == RTMP_ADD ) {
+ 	rtmp->rt_flags |= RTMPTAB_ROUTE;
+     }
+     if ( command == RTMP_DEL ) {
+ 	rtmp->rt_flags &= ~RTMPTAB_ROUTE;
+     }
  
      return( 0 );
  }
*** etc/atalkd/rtmp.h-	1993/12/23 21:43:48
--- etc/atalkd/rtmp.h	1994/02/04 01:01:05
***************
*** 58,63 ****
--- 58,64 ----
  #define RTMPTAB_ZIPQUERY	0x01
  #define RTMPTAB_HASZONES	0x02
  #define RTMPTAB_EXTENDED	0x04
+ #define RTMPTAB_ROUTE		0x08
  
  #ifndef BSD4_4
  #define RTMP_ADD	SIOCADDRT
--- cut ---