tsdu2spkt.c

来自「ftam等标准协议服务器和客户端的源代码。」· C语言 代码 · 共 2,171 行 · 第 1/4 页

C
2,171
字号
static u_long str2ssn (s, n)register char  *s;register int	n;{    register u_long u;    for (u = 0L; n > 0; n--)	u = u * 10 + *s++ - '0';    return u;}/*  *//* this is used to pull PCI, not user data... */#define	advance(n) \    if (base >= xbase) { \	if ((base = pullqb (qb, (n))) == NULL) { \	    s -> s_errno = SC_PROTOCOL; \	    break; \	} \	xbase = base + (n); \	nread += (n); \    } \    elsestatic char *pullqb (qb, n)struct qbuf *qb;int	n;{    register int    i;    int	    once;    register char  *cp;    register struct qbuf *qp;    static char *buffer = NULL;    if (n > SEGMENT_MAX)	return NULLCP;    for (once = 1, cp = buffer, qp = NULL; n > 0; once = 0, cp += i, n -= i) {	if (qp == NULL && (qp = qb -> qb_forw) == qb)	    return NULLCP;	i = min (qp -> qb_len, n);	if (once && i == n) {	/* special case */	    cp = qp -> qb_data;	    qp -> qb_data += i, qp -> qb_len -= i;	    return cp;	}	if (buffer == NULL) {	    if ((buffer = malloc ((unsigned) SEGMENT_MAX)) == NULL)		return NULLCP;	    cp = buffer;	}	bcopy (qp -> qb_data, cp, i);	qp -> qb_data += i, qp -> qb_len -= i;	if (qp -> qb_len <= 0) {	    remque (qp);	    free ((char *) qp);	    qp = NULL;	}    }    return buffer;}/*  */struct ssapkt *tsdu2spkt (qb, len, cc)struct qbuf *qb;int	len,       *cc;{    register int    li;    int     cat0,	    nread,	    pktlen,            pgilen,	    pmask,	    xlen;    register char *base;    char   *xbase;    unsigned char   code,                    si;    register struct ssapkt  *s;    if (cc) {	cat0 = *cc;	*cc = 0;    }    else	cat0 = 1;    if ((base = pullqb (qb, nread = 2)) == NULL	    || (s = newspkt ((int) (si = *base++))) == NULL)	return NULLSPKT;    if (*((u_char *) base) == 255) {	if ((base = pullqb (qb, 2)) == NULL) {	    s -> s_errno = SC_PROTOCOL;	    return s;	}	nread += 2;	s -> s_li = 		(*((u_char *) base) << 8) + *((u_char *) (base + 1));    }    else	s -> s_li = *((u_char *) base);    pgilen = pktlen = s -> s_li;    if (cat0)	switch (si) {	    case SPDU_GT:		Set (SMASK_SPDU_GT);		break;#if HULA	    case SPDU_UD:		Set (SMASK_SPDU_UD);#ifdef HULADEBUG	printf ("\n     decoding UNITDATASPDU \n");#endif			break;#endif	    case SPDU_AB:		Set (SMASK_SPDU_AB);		break;	    case SPDU_AA:		Set (SMASK_SPDU_AA);		break;	    default:		break;	}    if ((si >= SI_TABLE_LEN)	    || ((pmask = si_table[si]) == PMASK_NOTSUPPORTED)) {	s -> s_errno = SC_PROTOCOL;	return s;    }    if (len < pktlen + nread) {	s -> s_errno = SC_PROTOCOL;	return s;    }    s -> s_errno = SC_ACCEPT;    xbase = base;    while (pktlen && (s -> s_errno == SC_ACCEPT)) {	advance (2);	code = *base++;	if (*((u_char *) base) == 255) {	    base++;	    advance (2);	    li = (*((u_char *) base) << 8) + *((u_char *) (base + 1));	    xlen = 2;	}	else {	    li = *((u_char *) base);	    xlen = 1;	}	base += xlen;	if (xlen > 1)	    xlen += 2;	else	    xlen++;	switch (code) {	    case PI_UDATA:	        if (!(pmask & PMASK_UDATA))		    s -> s_errno = SC_PROTOCOL;		break;	    case PI_XDATA:	        if (!(pmask & PMASK_XDATA))		    s -> s_errno = SC_PROTOCOL;		break;	    default:		if (code >= PI_TABLE_LEN || !(pmask & pi_table[code]))		    s -> s_errno = SC_PROTOCOL;		break;	}	if (s -> s_errno != SC_ACCEPT)	    break;	if (!pgilen)	    pgilen = pktlen;	pktlen -= (xlen + li);	if (li > (pgilen -= xlen)) {	    s -> s_errno = SC_PROTOCOL;	    break;	}	pgilen -= li;	if (li)	    advance (li);	if (code < PI_TABLE_LEN) {	    if (li) {		if (pi_table[code] & PMASK_VARLEN) {		    if (li > pi_length[code]) {			s -> s_errno = SC_PROTOCOL;			break;		    }		}		else		    if (li != pi_length[code]) {			s -> s_errno = SC_PROTOCOL;			break;		    }	    }	}	switch (code) {	    case PGI_AR_LINK:		Set (SMASK_AR_OID);/* HACK! */		goto do_pgi;	    case PGI_CN_ID: 		Set (SMASK_CN_REF);/* fall */	    case PGI_CN_ITEMS: do_pgi: ;		pktlen += li;		pgilen = li;		li = 0;		break;	    case PI_CALLED_SS: 	    case PI_CALLING_SS: #ifdef	notdef	    case PI_AR_CALLED:	    case PI_AR_CALLING:#endif		switch (si) {		    case SPDU_CN: 		    case SPDU_AC: 			s -> s_cn_reference.sr_ulen = li;			bcopy (base, s -> s_cn_reference.sr_udata, li);			Set (SMASK_CN_REF);			break;		    case SPDU_RF: 			s -> s_rf_reference.sr_ulen = li;			bcopy (base, s -> s_rf_reference.sr_udata, li);			Set (SMASK_RF_REF);			break;		    case SPDU_AR:			switch (code) {			    case PI_AR_CALLED:				s -> s_ar_reference.sr_called_len = li;				bcopy (base, s -> s_ar_reference.sr_called,					li);				Set (SMASK_AR_REF);				break;							    case PI_AR_CALLING:				s -> s_ar_reference.sr_calling_len = li;				bcopy (base, s -> s_ar_reference.sr_calling,					li);				Set (SMASK_AR_REF);				break;			    default:				s -> s_errno = SC_PROTOCOL;				break;			}		        break;		    default: 			s -> s_errno = SC_PROTOCOL;			break;		}		base += li;		break;	    case PI_COMMON_REF: #ifdef	notdef	    case PI_AR_COMMON:#endif		switch (si) {		    case SPDU_CN: 		    case SPDU_AC: 			s -> s_cn_reference.sr_clen = li;			bcopy (base, s -> s_cn_reference.sr_cdata, li);			Set (SMASK_CN_REF);			break;		    case SPDU_RF: 			s -> s_rf_reference.sr_clen = li;			bcopy (base, s -> s_rf_reference.sr_cdata, li);			Set (SMASK_RF_REF);			break;		    case SPDU_AR:			s -> s_ar_reference.sr_clen = li;			bcopy (base, s -> s_ar_reference.sr_cdata, li);			Set (SMASK_AR_REF);			break;		    default: 			s -> s_errno = SC_PROTOCOL;			break;		}		base += li;		break;	    case PI_ADD_INFO: #ifdef	notdef	    case PI_AR_ADDT:#endif		switch (si) {		    case SPDU_CN: 		    case SPDU_AC: 			s -> s_cn_reference.sr_alen = li;			bcopy (base, s -> s_cn_reference.sr_adata, li);			Set (SMASK_CN_REF);			break;		    case SPDU_RF: 			s -> s_rf_reference.sr_alen = li;			bcopy (base, s -> s_rf_reference.sr_adata, li);			Set (SMASK_RF_REF);			break;		    case SPDU_AR:			s -> s_ar_reference.sr_alen = li;			bcopy (base, s -> s_ar_reference.sr_adata, li);			Set (SMASK_AR_REF);			break;		    default: 			s -> s_errno = SC_PROTOCOL;			break;		}		base += li;		break;	    case PI_PROTOCOL_OPT: 		if ((s -> s_options = *base++) & ~CR_OPT_MASK)		    s -> s_errno = SC_PROTOCOL;		else		    Set (SMASK_CN_OPT);		break;	    case PI_TSDU_MAXSIZ: 		{		    u_long tsdu_maxsize;		    bcopy (base, (char *) &tsdu_maxsize,			    pi_length[PI_TSDU_MAXSIZ]);		    tsdu_maxsize = ntohl (tsdu_maxsize);		    s -> s_tsdu_init = (tsdu_maxsize >> 16) & 0xffff;		    s -> s_tsdu_resp = tsdu_maxsize & 0xffff;		    Set (SMASK_CN_TSDU);		}		base += pi_length[PI_TSDU_MAXSIZ];		break;	    case PI_VERSION: 		switch (si) {		    case SPDU_CN: 		    case SPDU_AC: 			s -> s_cn_version = *base++;			Set (SMASK_CN_VRSN);			break;		    case SPDU_RF: 			s -> s_rf_version = *base++;			Set (SMASK_RF_VRSN);			break;		    default: 			s -> s_errno = SC_PROTOCOL;			break;		}		break;	    case PI_SYNC: 		switch (si) {		    case SPDU_MIP: 			if ((s -> s_mip_sync = *base++) & ~MIP_SYNC_MASK)			    s -> s_errno = SC_PROTOCOL;			else			    Set (SMASK_MIP_SYNC);			break;		    case SPDU_MAP: 			if ((s -> s_map_sync = *base++) & ~MAP_SYNC_MASK)			    s -> s_errno = SC_PROTOCOL;			else			    Set (SMASK_MAP_SYNC);			break;		}		break;	    case PI_TOKEN_SET: 		switch (si) {		    case SPDU_CN: 		    case SPDU_AC: 			s -> s_settings = *base++;			Set (SMASK_CN_SET);			break;		    case SPDU_RS:			s -> s_rs_settings = *base++;			Set (SMASK_RS_SET);			break;		    case SPDU_RA:			s -> s_ra_settings = *base++;			Set (SMASK_RA_SET);			break;		    default: 			s -> s_errno = SC_PROTOCOL;			break;		}		break;	    case PI_TOKEN: 		switch (si) {		    case SPDU_AC: 			s -> s_ac_token = *base++;			Set (SMASK_AC_TOKEN);			break;		    case SPDU_GT: 			If_Reset (SMASK_SPDU_GT) {			    s -> s_errno = SC_PROTOCOL;			    break;			}			s -> s_gt_token = *base++;			Set (SMASK_GT_TOKEN);			break;		    case SPDU_PT: 			s -> s_pt_token = *base++;			Set (SMASK_PT_TOKEN);			break;		    default: 			s -> s_errno = SC_PROTOCOL;			break;		}		break;	    case PI_TDISC: 		switch (si) {		    case SPDU_RF: 			if ((s -> s_rf_disconnect = *base++) & ~RF_DISC_MASK)			    s -> s_errno = SC_PROTOCOL;			else			    Set (SMASK_RF_DISC);			break;		    case SPDU_FN: 			if ((s -> s_fn_disconnect = *base++) & ~FN_DISC_MASK)			    s -> s_errno = SC_PROTOCOL;			else			    Set (SMASK_FN_DISC);			break;		    case SPDU_AB: 			If_Reset (SMASK_SPDU_AB) {			    s -> s_errno = SC_PROTOCOL;			    break;			}			if ((s -> s_ab_disconnect = *base++) & ~AB_DISC_MASK)			    s -> s_errno = SC_PROTOCOL;			else			    Set (SMASK_AB_DISC);			break;		    default: 			s -> s_errno = SC_PROTOCOL;			break;		}		break;	    case PI_USER_REQ: 		{		    u_short requirements;		    bcopy (base, (char *) &requirements, 2);		    requirements = ntohs (requirements);		    if (si != SPDU_RF) {			s -> s_cn_require = requirements;			Set (SMASK_CN_REQ);		    }		    else {			s -> s_rf_require = requirements;			Set (SMASK_RF_REQ);		    }		}		base += 2;		break;	    case PI_ISN: 		switch (si) {		    case SPDU_CN: 		    case SPDU_AC: 			s -> s_isn = str2ssn (base, li);			Set (SMASK_CN_ISN);			break;		    default: 			s -> s_errno = SC_PROTOCOL;			break;		}	    case PI_ISN2:	/* not supported yet */		base += li;		break;	    case PI_ENCLOSE:		if ((si == SPDU_DT && (s -> s_mask & SMASK_SPDU_GT))		        || (si == SPDU_AI && !(s -> s_mask & SMASK_SPDU_AB))) {		    s -> s_errno = SC_PROTOCOL;		    break;		}		if ((s -> s_enclose = *base++) & ~ENCL_MASK)		    s -> s_errno = SC_PROTOCOL;		else		    Set (SMASK_ENCLOSE);		break;	    case PI_RESYNC:		s -> s_rs_type = *base++;		if (SYNC_OK (s -> s_rs_type))		    Set (SMASK_RS_TYPE);		else		    s -> s_errno = SC_PROTOCOL;		break;	    case PI_ACT_ID:		switch (si) {		    case SPDU_AS:			s -> s_as_id.sd_len = li;			bcopy (base, s -> s_as_id.sd_data, li);			Set (SMASK_AS_ID);			break;		    case SPDU_AR:			if ((s -> s_mask & SMASK_AR_OID)				&& s -> s_ar_oid.sd_len == 0) {			    s -> s_ar_oid.sd_len = li;			    bcopy (base, s -> s_ar_oid.sd_data, li);			}			else {			    s -> s_ar_id.sd_len = li;			    bcopy (base, s -> s_ar_id.sd_data, li);			    Set (SMASK_AR_ID);			}			break;		    default:			s -> s_errno = SC_PROTOCOL;			break;		}		base += li;		break;	    case PI_SERIAL: 		switch (si) {		    case SPDU_MIP: 			s -> s_mip_serial = str2ssn (base, li);			Set (SMASK_MIP_SERIAL);			break;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?