unsigned nowlen;
static int ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen){    struct rdpkt2_state_tag *st = &ssh->rdpkt2_state;    crBegin(ssh->ssh2_rdpkt_crstate);  next_packet:    ssh->pktin.type = 0;    ssh->pktin.length = 0;    if (ssh->sccipher)	st->cipherblk = ssh->sccipher->blksize;    else	st->cipherblk = 8;    if (st->cipherblk < 8)	st->cipherblk = 8;    if (ssh->pktin.maxlen < st->cipherblk) {	ssh->pktin.maxlen = st->cipherblk;	ssh->pktin.data = srealloc(ssh->pktin.data, st->cipherblk + APIEXTRA);    }    /*     * Acquire and decrypt the first block of the packet. This will     * contain the length and padding details.     */    for (st->i = st->len = 0; st->i < st->cipherblk; st->i++) {	while ((*datalen) == 0)	    crReturn(st->cipherblk - st->i);	ssh->pktin.data[st->i] = *(*data)++;	(*datalen)--;    }    if (ssh->sccipher)	ssh->sccipher->decrypt(ssh->sc_cipher_ctx,			       ssh->pktin.data, st->cipherblk);    /*     * Now get the length and padding figures.     */    st->len = GET_32BIT(ssh->pktin.data);    st->pad = ssh->pktin.data[4];    /*     * _Completely_ silly lengths should be stomped on before they     * do us any more damage.     */    if (st->len < 0 || st->pad < 0 || st->len + st->pad < 0) {	bombout((ssh,"Incoming packet was garbled on decryption"));	crReturn(0);    }    /*     * This enables us to deduce the payload length.     */    st->payload = st->len - st->pad - 1;    ssh->pktin.length = st->payload + 5;    /*     * So now we can work out the total packet length.     */    st->packetlen = st->len + 4;    st->maclen = ssh->scmac ? ssh->scmac->len : 0;    /*     * Adjust memory allocation if packet is too big.     */    if (ssh->pktin.maxlen < st->packetlen + st->maclen) {	ssh->pktin.maxlen = st->packetlen + st->maclen;	ssh->pktin.data = srealloc(ssh->pktin.data,				   ssh->pktin.maxlen + APIEXTRA);    }    /*     * Read and decrypt the remainder of the packet.     */    for (st->i = st->cipherblk; st->i < st->packetlen + st->maclen;	 st->i++) {	while ((*datalen) == 0)	    crReturn(st->packetlen + st->maclen - st->i);	ssh->pktin.data[st->i] = *(*data)++;	(*datalen)--;    }    /* Decrypt everything _except_ the MAC. */    if (ssh->sccipher)	ssh->sccipher->decrypt(ssh->sc_cipher_ctx,			       ssh->pktin.data + st->cipherblk,			       st->packetlen - st->cipherblk);    /*     * Check the MAC.     */    if (ssh->scmac	&& !ssh->scmac->verify(ssh->sc_mac_ctx, ssh->pktin.data, st->len + 4,			       st->incoming_sequence)) {	bombout((ssh,"Incorrect MAC received on packet"));	crReturn(0);    }    st->incoming_sequence++;	       /* whether or not we MACed */    /*     * Decompress packet payload.     */    {	unsigned char *newpayload;	int newlen;	if (ssh->sccomp &&	    ssh->sccomp->decompress(ssh->sc_comp_ctx,				    ssh->pktin.data + 5, ssh->pktin.length - 5,				    &newpayload, &newlen)) {	    if (ssh->pktin.maxlen < newlen + 5) {		ssh->pktin.maxlen = newlen + 5;		ssh->pktin.data = srealloc(ssh->pktin.data,					   ssh->pktin.maxlen + APIEXTRA);	    }	    ssh->pktin.length = 5 + newlen;	    memcpy(ssh->pktin.data + 5, newpayload, newlen);	    sfree(newpayload);	}    }    ssh->pktin.savedpos = 6;    ssh->pktin.type = ssh->pktin.data[5];    if (ssh->logctx)	log_packet(ssh->logctx, PKT_INCOMING, ssh->pktin.type,		   ssh2_pkt_type(ssh->pkt_ctx, ssh->pktin.type),		   ssh->pktin.data+6, ssh->pktin.length-6);    switch (ssh->pktin.type) {        /*         * These packets we must handle instantly.         */      case SSH2_MSG_DISCONNECT:        {            /* log reason code in disconnect message */            char buf[256];            int reason = GET_32BIT(ssh->pktin.data + 6);            unsigned msglen = GET_32BIT(ssh->pktin.data + 10);            unsigned nowlen;            if (reason > 0 && reason < lenof(ssh2_disconnect_reasons)) {                sprintf(buf, "Received disconnect message (%s)",                        ssh2_disconnect_reasons[reason]);            } else {                sprintf(buf, "Received disconnect message (unknown type %d)",                        reason);            }            logevent(buf);            strcpy(buf, "Disconnection message text: ");            nowlen = strlen(buf);            if (msglen > sizeof(buf) - nowlen - 1)                msglen = sizeof(buf) - nowlen - 1;            memcpy(buf + nowlen, ssh->pktin.data + 14, msglen);            buf[nowlen + msglen] = '\0';            logevent(buf);            bombout((ssh,"Server sent disconnect message\ntype %d (%s):\n\"%s\"",                     reason,                     (reason > 0 && reason < lenof(ssh2_disconnect_reasons)) ?                     ssh2_disconnect_reasons[reason] : "unknown",                     buf+nowlen));            crReturn(0);        }        break;      case SSH2_MSG_IGNORE:	goto next_packet;      case SSH2_MSG_DEBUG:	{	    /* log the debug message */	    char buf[512];	    /* int display = ssh->pktin.body[6]; */	    int stringlen = GET_32BIT(ssh->pktin.data+7);	    int prefix;	    strcpy(buf, "Remote debug message: ");	    prefix = strlen(buf);	    if (stringlen > (int)(sizeof(buf)-prefix-1))		stringlen = sizeof(buf)-prefix-1;	    memcpy(buf + prefix, ssh->pktin.data + 11, stringlen);	    buf[prefix + stringlen] = '\0';	    logevent(buf);	}        goto next_packet;              /* FIXME: print the debug message */        /*         * These packets we need do nothing about here.         */      case SSH2_MSG_UNIMPLEMENTED:      case SSH2_MSG_SERVICE_REQUEST:      case SSH2_MSG_SERVICE_ACCEPT:      case SSH2_MSG_KEXINIT:      case SSH2_MSG_NEWKEYS:      case SSH2_MSG_KEXDH_INIT:      case SSH2_MSG_KEXDH_REPLY:      /* case SSH2_MSG_KEX_DH_GEX_REQUEST: duplicate case value */      /* case SSH2_MSG_KEX_DH_GEX_GROUP: duplicate case value */      case SSH2_MSG_KEX_DH_GEX_INIT:      case SSH2_MSG_KEX_DH_GEX_REPLY:      case SSH2_MSG_USERAUTH_REQUEST:      case SSH2_MSG_USERAUTH_FAILURE:      case SSH2_MSG_USERAUTH_SUCCESS:      case SSH2_MSG_USERAUTH_BANNER:      case SSH2_MSG_USERAUTH_PK_OK:      /* case SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ: duplicate case value */      /* case SSH2_MSG_USERAUTH_INFO_REQUEST: duplicate case value */      case SSH2_MSG_USERAUTH_INFO_RESPONSE:      case SSH2_MSG_GLOBAL_REQUEST:      case SSH2_MSG_REQUEST_SUCCESS:      case SSH2_MSG_REQUEST_FAILURE:      case SSH2_MSG_CHANNEL_OPEN:      case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:      case SSH2_MSG_CHANNEL_OPEN_FAILURE:      case SSH2_MSG_CHANNEL_WINDOW_ADJUST:      case SSH2_MSG_CHANNEL_DATA:      case SSH2_MSG_CHANNEL_EXTENDED_DATA:      case SSH2_MSG_CHANNEL_EOF:      case SSH2_MSG_CHANNEL_CLOSE:      case SSH2_MSG_CHANNEL_REQUEST:      case SSH2_MSG_CHANNEL_SUCCESS:      case SSH2_MSG_CHANNEL_FAILURE:        break;        /*         * For anything else we send SSH2_MSG_UNIMPLEMENTED.         */      default:	ssh2_pkt_init(ssh, SSH2_MSG_UNIMPLEMENTED);	ssh2_pkt_adduint32(ssh, st->incoming_sequence - 1);	ssh2_pkt_send(ssh);        break;    }    crFinish(0);}