⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pk_subr.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
				pkp -> pk_chan[ni] -> lcd_lcn = ni;			}	}	for (i = 1; i <= pkp -> pk_maxlcn; ++i)		if ((lcp = pkp -> pk_chan[i]) != NULL) {			/* if (lcp -> lcd_so)				soisconnecting (lcp -> lcd_so); */			lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL);			pk_callrequest (lcp, lcp -> lcd_ceaddr, pkp -> pk_xcp);			(*pkp -> pk_ia -> ia_start) (lcp);		}}struct bcdinfo {	octet *cp;	unsigned posn;};/*  *  Build the rest of the CALL REQUEST packet. Fill in calling *  address, facilities fields and the user data field. */pk_callrequest (lcp, sa, xcp)struct pklcd *lcp;register struct sockaddr_x25 *sa;register struct x25config *xcp;{	register struct x25_calladdr *a;	register struct mbuf *m = lcp -> lcd_template;	register struct x25_packet *xp = mtod (m, struct x25_packet *);	struct bcdinfo b;	if (lcp -> lcd_flags & X25_DBIT)		X25SBITS(xp -> bits, d_bit, 1);	a = (struct x25_calladdr *) &xp -> packet_data;	b.cp = (octet *) a -> address_field;	b.posn = 0;	X25SBITS(a -> addrlens, called_addrlen, to_bcd (&b, sa, xcp));	X25SBITS(a -> addrlens, calling_addrlen, to_bcd (&b, &xcp -> xc_addr, xcp));	if (b.posn & 0x01)		*b.cp++ &= 0xf0;	m -> m_pkthdr.len = m -> m_len += b.cp - (octet *) a;	if (lcp -> lcd_facilities) {		m -> m_pkthdr.len += 			(m -> m_next = lcp -> lcd_facilities) -> m_pkthdr.len;		lcp -> lcd_facilities = 0;	} else		pk_build_facilities (m, sa, (int)xcp -> xc_type);	m_copyback (m, m -> m_pkthdr.len, sa -> x25_udlen, sa -> x25_udata);}pk_build_facilities (m, sa, type)register struct mbuf *m;struct sockaddr_x25 *sa;{	register octet *cp;	register octet *fcp;	register int revcharge;	cp = mtod (m, octet *) + m -> m_len;	fcp = cp + 1;	revcharge = sa -> x25_opts.op_flags & X25_REVERSE_CHARGE ? 1 : 0;	/*	 * This is specific to Datapac X.25(1976) DTEs.  International	 * calls must have the "hi priority" bit on.	 */	if (type == X25_1976 && sa -> x25_opts.op_psize == X25_PS128)		revcharge |= 02;	if (revcharge) {		*fcp++ = FACILITIES_REVERSE_CHARGE;		*fcp++ = revcharge;	}	switch (type) {	case X25_1980:	case X25_1984:		*fcp++ = FACILITIES_PACKETSIZE;		*fcp++ = sa -> x25_opts.op_psize;		*fcp++ = sa -> x25_opts.op_psize;		*fcp++ = FACILITIES_WINDOWSIZE;		*fcp++ = sa -> x25_opts.op_wsize;		*fcp++ = sa -> x25_opts.op_wsize;	}	*cp = fcp - cp - 1;	m -> m_pkthdr.len = (m -> m_len += *cp + 1);}to_bcd (b, sa, xcp)register struct bcdinfo *b;struct sockaddr_x25 *sa;register struct x25config *xcp;{	register char *x = sa -> x25_addr;	unsigned start = b -> posn;	/*	 * The nodnic and prepnd0 stuff looks tedious,	 * but it does allow full X.121 addresses to be used,	 * which is handy for routing info (& OSI type 37 addresses).	 */	if (xcp -> xc_addr.x25_net && (xcp -> xc_nodnic || xcp -> xc_prepnd0)) {		char dnicname[sizeof (long) * NBBY/3 + 2];		register char *p = dnicname;		sprintf (p, "%d", xcp -> xc_addr.x25_net & 0x7fff);		for (; *p; p++) /* *p == 0 means dnic matched */			if ((*p ^ *x++) & 0x0f)				break;		if (*p || xcp -> xc_nodnic == 0)			x = sa -> x25_addr;		if (*p && xcp -> xc_prepnd0) {			if ((b -> posn)++ & 0x01)				*(b -> cp)++;			else				*(b -> cp) = 0;		}	}	while (*x)		if ((b -> posn)++ & 0x01)			*(b -> cp)++ |= *x++ & 0x0F;		else			*(b -> cp) = *x++ << 4;	return ((b -> posn) - start);}/*  *  This routine gets the  first available logical channel number.  The *  search is  *  		- from the highest number to lowest number if playing DTE, and *		- from lowest to highest number if playing DCE. */pk_getlcn (pkp)register struct pkcb *pkp;{	register int i;	if (pkp -> pk_chan == 0)		return (0);	if ( pkp -> pk_dxerole & DTE_PLAYDCE ) {		for (i = 1; i <= pkp -> pk_maxlcn; ++i)			if (pkp -> pk_chan[i] == NULL)				break;	} else { 		for (i = pkp -> pk_maxlcn; i > 0; --i)			if (pkp -> pk_chan[i] == NULL)				break;	}	i = ( i > pkp -> pk_maxlcn ? 0 : i );	return (i);}/*  *  This procedure sends a CLEAR request packet. The lc state is *  set to "SENT_CLEAR".  */pk_clear (lcp, diagnostic, abortive)register struct pklcd *lcp;{	register struct mbuf *m = pk_template (lcp -> lcd_lcn, X25_CLEAR);	m -> m_len += 2;	m -> m_pkthdr.len += 2;	mtod (m, struct x25_packet *) -> packet_data = 0;	mtod (m, octet *)[4] = diagnostic;	if (lcp -> lcd_facilities) {		m -> m_next = lcp -> lcd_facilities;		m -> m_pkthdr.len += m -> m_next -> m_len;		lcp -> lcd_facilities = 0;	}	if (abortive)		lcp -> lcd_template = m;	else {		struct socket *so = lcp -> lcd_so;		struct sockbuf *sb = so ? & so -> so_snd : & lcp -> lcd_sb;		sbappendrecord (sb, m);	}	pk_output (lcp);}/* * This procedure generates RNR's or RR's to inhibit or enable * inward data flow, if the current state changes (blocked ==> open or * vice versa), or if forced to generate one.  One forces RNR's to ack data.   */pk_flowcontrol (lcp, inhibit, forced)register struct pklcd *lcp;{	inhibit = (inhibit != 0);	if (lcp == 0 || lcp -> lcd_state != DATA_TRANSFER ||	    (forced == 0 && lcp -> lcd_rxrnr_condition == inhibit))		return;	lcp -> lcd_rxrnr_condition = inhibit;	lcp -> lcd_template =		pk_template (lcp -> lcd_lcn, inhibit ? X25_RNR : X25_RR);	pk_output (lcp);}/*  *  This procedure sends a RESET request packet. It re-intializes *  virtual circuit. */staticpk_reset (lcp, diagnostic)register struct pklcd *lcp;{	register struct mbuf *m;	register struct socket *so = lcp -> lcd_so;	if (lcp -> lcd_state != DATA_TRANSFER)		return;	if (so)		so -> so_error = ECONNRESET;	lcp -> lcd_reset_condition = TRUE;	/* Reset all the control variables for the channel. */	pk_flush (lcp);	lcp -> lcd_window_condition = lcp -> lcd_rnr_condition =		lcp -> lcd_intrconf_pending = FALSE;	lcp -> lcd_rsn = MODULUS - 1;	lcp -> lcd_ssn = 0;	lcp -> lcd_output_window = lcp -> lcd_input_window =		lcp -> lcd_last_transmitted_pr = 0;	m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESET);	m -> m_pkthdr.len = m -> m_len += 2;	mtod (m, struct x25_packet *) -> packet_data = 0;	mtod (m, octet *)[4] = diagnostic;	pk_output (lcp);}/* * This procedure frees all data queued for output or delivery on a *  virtual circuit. */pk_flush (lcp)register struct pklcd *lcp;{	register struct socket *so;	if (lcp -> lcd_template)		m_freem (lcp -> lcd_template);	if (lcp -> lcd_cps) {		m_freem (lcp -> lcd_cps);		lcp -> lcd_cps = 0;	}	if (lcp -> lcd_facilities) {		m_freem (lcp -> lcd_facilities);		lcp -> lcd_facilities = 0;	}	if (so = lcp -> lcd_so) 		sbflush (&so -> so_snd);	else 		sbflush (&lcp -> lcd_sb);}/*  *  This procedure handles all local protocol procedure errors. */pk_procerror (error, lcp, errstr, diagnostic)register struct pklcd *lcp;char *errstr;{	pk_message (lcp -> lcd_lcn, lcp -> lcd_pkp -> pk_xcp, errstr);	switch (error) {	case CLEAR: 		if (lcp -> lcd_so) {			lcp -> lcd_so -> so_error = ECONNABORTED;			soisdisconnecting (lcp -> lcd_so);		}		pk_clear (lcp, diagnostic, 1);		break;	case RESET: 		pk_reset (lcp, diagnostic);	}}/*  *  This procedure is called during the DATA TRANSFER state to check  *  and  process  the P(R) values  received  in the DATA,  RR OR RNR *  packets. */pk_ack (lcp, pr)struct pklcd *lcp;unsigned pr;{	register struct socket *so = lcp -> lcd_so;	if (lcp -> lcd_output_window == pr)		return (PACKET_OK);	if (lcp -> lcd_output_window < lcp -> lcd_ssn) {		if (pr < lcp -> lcd_output_window || pr > lcp -> lcd_ssn) {			pk_procerror (RESET, lcp,				"p(r) flow control error", 2);			return (ERROR_PACKET);		}	}	else {		if (pr < lcp -> lcd_output_window && pr > lcp -> lcd_ssn) {			pk_procerror (RESET, lcp,				"p(r) flow control error #2", 2);			return (ERROR_PACKET);		}	}	lcp -> lcd_output_window = pr;		/* Rotate window. */	if (lcp -> lcd_window_condition == TRUE)		lcp -> lcd_window_condition = FALSE;	if (so && ((so -> so_snd.sb_flags & SB_WAIT) || 		   (so -> so_snd.sb_flags & SB_NOTIFY)))		sowwakeup (so);	return (PACKET_OK);}/*  *  This procedure decodes the X.25 level 3 packet returning a  *  code to be used in switchs or arrays. */pk_decode (xp)register struct x25_packet *xp;{	register int type;	if (X25GBITS(xp -> bits, fmt_identifier) != 1)		return (INVALID_PACKET);#ifdef ancient_history	/* 	 *  Make sure that the logical channel group number is 0.	 *  This restriction may be removed at some later date.	 */	if (xp -> lc_group_number != 0)		return (INVALID_PACKET);#endif	/* 	 *  Test for data packet first.	 */	if (!(xp -> packet_type & DATA_PACKET_DESIGNATOR))		return (DATA);	/* 	 *  Test if flow control packet (RR or RNR).	 */	if (!(xp -> packet_type & RR_OR_RNR_PACKET_DESIGNATOR))		switch (xp -> packet_type & 0x1f) {		case X25_RR:			return (RR);		case X25_RNR:			return (RNR);		case X25_REJECT:			return (REJECT);		}	/* 	 *  Determine the rest of the packet types.	 */	switch (xp -> packet_type) {	case X25_CALL: 		type = CALL;		break;	case X25_CALL_ACCEPTED: 		type = CALL_ACCEPTED;		break;	case X25_CLEAR: 		type = CLEAR;		break;	case X25_CLEAR_CONFIRM: 		type = CLEAR_CONF;		break;	case X25_INTERRUPT: 		type = INTERRUPT;		break;	case X25_INTERRUPT_CONFIRM: 		type = INTERRUPT_CONF;		break;	case X25_RESET: 		type = RESET;		break;	case X25_RESET_CONFIRM: 		type = RESET_CONF;		break;	case X25_RESTART: 		type = RESTART;		break;	case X25_RESTART_CONFIRM: 		type = RESTART_CONF;		break;	case X25_DIAGNOSTIC:		type = DIAG_TYPE;		break;	default: 		type = INVALID_PACKET;	}	return (type);}/*  *  A restart packet has been received. Print out the reason *  for the restart. */pk_restartcause (pkp, xp)struct pkcb *pkp;register struct x25_packet *xp;{	register struct x25config *xcp = pkp -> pk_xcp;	register int lcn = LCN(xp);	switch (xp -> packet_data) {	case X25_RESTART_LOCAL_PROCEDURE_ERROR: 		pk_message (lcn, xcp, "restart: local procedure error");		break;	case X25_RESTART_NETWORK_CONGESTION: 		pk_message (lcn, xcp, "restart: network congestion");		break;	case X25_RESTART_NETWORK_OPERATIONAL: 		pk_message (lcn, xcp, "restart: network operational");		break;	default: 		pk_message (lcn, xcp, "restart: unknown cause");	}}#define MAXRESETCAUSE	7int     Reset_cause[] = {	EXRESET, EXROUT, 0, EXRRPE, 0, EXRLPE, 0, EXRNCG};/*  *  A reset packet has arrived. Return the cause to the user. */pk_resetcause (pkp, xp)struct pkcb *pkp;register struct x25_packet *xp;{	register struct pklcd *lcp =				pkp -> pk_chan[LCN(xp)];	register int code = xp -> packet_data;	if (code > MAXRESETCAUSE)		code = 7;	/* EXRNCG */	pk_message (LCN(xp), lcp -> lcd_pkp, "reset code 0x%x, diagnostic 0x%x",			xp -> packet_data, 4[(u_char *)xp]);				if (lcp -> lcd_so)		lcp -> lcd_so -> so_error = Reset_cause[code];}#define MAXCLEARCAUSE	25int     Clear_cause[] = {	EXCLEAR, EXCBUSY, 0, EXCINV, 0, EXCNCG, 0,	0, 0, EXCOUT, 0, EXCAB, 0, EXCNOB, 0, 0, 0, EXCRPE,	0, EXCLPE, 0, 0, 0, 0, 0, EXCRRC};/*  *  A clear packet has arrived. Return the cause to the user. */pk_clearcause (pkp, xp)struct pkcb *pkp;register struct x25_packet *xp;{	register struct pklcd *lcp =		pkp -> pk_chan[LCN(xp)];	register int code = xp -> packet_data;	if (code > MAXCLEARCAUSE)		code = 5;	/* EXRNCG */	if (lcp -> lcd_so)		lcp -> lcd_so -> so_error = Clear_cause[code];}char *format_ntn (xcp)register struct x25config *xcp;{	return (xcp -> xc_addr.x25_addr);}/* VARARGS1 */pk_message (lcn, xcp, fmt, a1, a2, a3, a4, a5, a6)struct x25config *xcp;char *fmt;{	if (lcn)		if (!PQEMPTY)			printf ("X.25(%s): lcn %d: ", format_ntn (xcp), lcn);		else			printf ("X.25: lcn %d: ", lcn);	else		if (!PQEMPTY)			printf ("X.25(%s): ", format_ntn (xcp));		else			printf ("X.25: ");	printf (fmt, a1, a2, a3, a4, a5, a6);	printf ("\n");}pk_fragment (lcp, m0, qbit, mbit, wait)struct mbuf *m0;register struct pklcd *lcp;{	register struct mbuf *m = m0;	register struct x25_packet *xp;	register struct sockbuf *sb;	struct mbuf *head = 0, *next, **mp = &head, *m_split ();	int totlen, psize = 1 << (lcp -> lcd_packetsize);	if (m == 0)		return 0;	if (m -> m_flags & M_PKTHDR == 0)		panic ("pk_fragment");	totlen = m -> m_pkthdr.len;	m -> m_act = 0;	sb = lcp -> lcd_so ? &lcp -> lcd_so -> so_snd : & lcp -> lcd_sb;	do {		if (totlen > psize) {			if ((next = m_split (m, psize, wait)) == 0)				goto abort;			totlen -= psize;		} else			next = 0;		M_PREPEND(m, PKHEADERLN, wait);		if (m == 0)			goto abort;		*mp = m;		mp = & m -> m_act;		*mp = 0;		xp = mtod (m, struct x25_packet *);		0[(char *)xp] = 0;		if (qbit)			X25SBITS(xp -> bits, q_bit, 1);		if (lcp -> lcd_flags & X25_DBIT)			X25SBITS(xp -> bits, d_bit, 1);		X25SBITS(xp -> bits, fmt_identifier, 1);		xp -> packet_type = X25_DATA;		SET_LCN(xp, lcp -> lcd_lcn);		if (next || (mbit && (totlen == psize ||				      (lcp -> lcd_flags & X25_DBIT))))			SMBIT(xp, 1);	} while (m = next);	for (m = head; m; m = next) {		next = m -> m_act;		m -> m_act = 0;		sbappendrecord (sb, m);	}	return 0;abort:	if (wait)		panic ("pk_fragment null mbuf after wait");	if (next)		m_freem (next);	for (m = head; m; m = next) {		next = m -> m_act;		m_freem (m);	}	return ENOBUFS;}

⌨️ 快捷键说明

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