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

📄 pk_input.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
			m_freem (m);			/*			 * NB.  This is dangerous: sending a RR here can			 * cause sequence number errors if a previous data			 * packet has not yet been passed up to the application			 * (RR's are normally generated via PRU_RCVD).			 */			pk_flowcontrol (lcp, 0, 1);		} else {			sbappendrecord (&so -> so_rcv, m);			sorwakeup (so);		}		break;	/* 	 *  Interrupt packet received.	 */	case INTERRUPT + DATA_TRANSFER: 		if (lcp -> lcd_reset_condition)			break;		lcp -> lcd_intrdata = xp -> packet_data;		lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_INTERRUPT_CONFIRM);		pk_output (lcp);		m -> m_data += PKHEADERLN;		m -> m_len -= PKHEADERLN;		m -> m_pkthdr.len -= PKHEADERLN;		MCHTYPE(m, MT_OOBDATA);		if (so) {			if (so -> so_options & SO_OOBINLINE)				sbinsertoob (&so -> so_rcv, m);			else				m_freem (m);			sohasoutofband (so);		}		break;	/* 	 *  Interrupt confirmation packet received.	 */	case INTERRUPT_CONF + DATA_TRANSFER: 		if (lcp -> lcd_reset_condition)			break;		if (lcp -> lcd_intrconf_pending == TRUE)			lcp -> lcd_intrconf_pending = FALSE;		else			pk_procerror (RESET, lcp, "unexpected packet", 43);		break;	/* 	 *  Receiver ready received. Rotate the output window and output	 *  any data packets waiting transmission.	 */	case RR + DATA_TRANSFER: 		if (lcp -> lcd_reset_condition ||		    pk_ack (lcp, PR(xp)) != PACKET_OK) {			ptype = DELETE_PACKET;			break;		}		if (lcp -> lcd_rnr_condition == TRUE)			lcp -> lcd_rnr_condition = FALSE;		pk_output (lcp);		break;	/* 	 *  Receiver Not Ready received. Packets up to the P(R) can be	 *  be sent. Condition is cleared with a RR.	 */	case RNR + DATA_TRANSFER: 		if (lcp -> lcd_reset_condition ||		    pk_ack (lcp, PR(xp)) != PACKET_OK) {			ptype = DELETE_PACKET;			break;		}		lcp -> lcd_rnr_condition = TRUE;		break;	/* 	 *  Reset packet received. Set state to FLOW_OPEN.  The Input and	 *  Output window edges ar set to zero. Both the send and receive	 *  numbers are reset. A confirmation is returned.	 */	case RESET + DATA_TRANSFER: 		if (lcp -> lcd_reset_condition)			/* Reset collision. Just ignore packet. */			break;		pk_resetcause (pkp, xp);		lcp -> lcd_window_condition = lcp -> lcd_rnr_condition =			lcp -> lcd_intrconf_pending = FALSE;		lcp -> lcd_output_window = lcp -> lcd_input_window =			lcp -> lcd_last_transmitted_pr = 0;		lcp -> lcd_ssn = 0;		lcp -> lcd_rsn = MODULUS - 1;		lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESET_CONFIRM);		pk_output (lcp);		pk_flush (lcp);		if (so == 0)			break;		wakeup ((caddr_t) & so -> so_timeo);		sorwakeup (so);		sowwakeup (so);		break;	/* 	 *  Reset confirmation received.	 */	case RESET_CONF + DATA_TRANSFER: 		if (lcp -> lcd_reset_condition) {			lcp -> lcd_reset_condition = FALSE;			pk_output (lcp);		}		else			pk_procerror (RESET, lcp, "unexpected packet", 32);		break;	case DATA + SENT_CLEAR: 		ptype = DELETE_PACKET;	case RR + SENT_CLEAR: 	case RNR + SENT_CLEAR: 	case INTERRUPT + SENT_CLEAR: 	case INTERRUPT_CONF + SENT_CLEAR: 	case RESET + SENT_CLEAR: 	case RESET_CONF + SENT_CLEAR: 		/* Just ignore p if we have sent a CLEAR already.		   */		break;	/* 	 *  Restart sets all the permanent virtual circuits to the "Data	 *  Transfer" stae and  all the switched virtual circuits to the	 *  "Ready" state.	 */	case RESTART + READY: 		switch (pkp -> pk_state) {		case DTE_SENT_RESTART: 			/* 			 * Restart collision.			 * If case the restart cause is "DTE originated" we			 * have a DTE-DTE situation and are trying to resolve			 * who is going to play DTE/DCE [ISO 8208:4.2-4.5]			 */			if (RESTART_DTE_ORIGINATED(xp)) {				pk_restart (pkp, X25_RESTART_DTE_ORIGINATED);				pk_message (0, pkp -> pk_xcp,					    "RESTART collision");				if ((pkp -> pk_restartcolls++) > MAXRESTARTCOLLISIONS) {					pk_message (0, pkp -> pk_xcp,						    "excessive RESTART collisions");					pkp -> pk_restartcolls = 0;				}				break;			}			pkp -> pk_state = DTE_READY;			pkp -> pk_dxerole |= DTE_PLAYDTE;			pkp -> pk_dxerole &= ~DTE_PLAYDCE;			pk_message (0, pkp -> pk_xcp,				"Packet level operational");			pk_message (0, pkp -> pk_xcp, 				    "Assuming DTE role");			if (pkp -> pk_dxerole & DTE_CONNECTPENDING)				pk_callcomplete (pkp);			break;		default: 			pk_restart (pkp, -1);			pk_restartcause (pkp, xp);			pkp -> pk_chan[0] -> lcd_template = pk_template (0,				X25_RESTART_CONFIRM);			pk_output (pkp -> pk_chan[0]);			pkp -> pk_state = DTE_READY;			pkp -> pk_dxerole |= RESTART_DTE_ORIGINATED(xp) ? DTE_PLAYDCE :				DTE_PLAYDTE;			if (pkp -> pk_dxerole & DTE_PLAYDTE) {				pkp -> pk_dxerole &= ~DTE_PLAYDCE;				pk_message (0, pkp -> pk_xcp, 					    "Assuming DTE role");			} else {				pkp -> pk_dxerole &= ~DTE_PLAYDTE;				pk_message (0, pkp -> pk_xcp, 					 "Assuming DCE role");			}			if (pkp -> pk_dxerole & DTE_CONNECTPENDING)				pk_callcomplete (pkp);		}		break;	/* 	 *  Restart confirmation received. All logical channels are set	 *  to READY. 	 */	case RESTART_CONF + READY: 		switch (pkp -> pk_state) {		case DTE_SENT_RESTART: 			pkp -> pk_state = DTE_READY;			pkp -> pk_dxerole |= DTE_PLAYDTE;			pkp -> pk_dxerole &= ~DTE_PLAYDCE;			pk_message (0, pkp -> pk_xcp,				    "Packet level operational");			pk_message (0, pkp -> pk_xcp,				    "Assuming DTE role");			if (pkp -> pk_dxerole & DTE_CONNECTPENDING)				pk_callcomplete (pkp);			break;		default: 			/* Restart local procedure error. */			pk_restart (pkp, X25_RESTART_LOCAL_PROCEDURE_ERROR);			pkp -> pk_state = DTE_SENT_RESTART;			pkp -> pk_dxerole &= ~(DTE_PLAYDTE | DTE_PLAYDCE);		}		break;	default: 		if (lcp) {			pk_procerror (CLEAR, lcp, "unknown packet error", 33);			pk_message (lcn, pkp -> pk_xcp,				"\"%s\" unexpected in \"%s\" state",				pk_name[ptype/MAXSTATES], pk_state[lcdstate]);		} else			pk_message (lcn, pkp -> pk_xcp,				"packet arrived on unassigned lcn");		break;	}	if (so == 0 && lcp && lcp -> lcd_upper && lcdstate == DATA_TRANSFER) {		if (ptype != DATA && ptype != INTERRUPT)			MCHTYPE(m, MT_CONTROL);		lcp -> lcd_upper (lcp, m);	} else if (ptype != DATA && ptype != INTERRUPT)		m_freem (m);}staticprune_dnic (from, to, dnicname, xcp)char *from, *to, *dnicname;register struct x25config *xcp;{	register char *cp1 = from, *cp2 = from;	if (xcp -> xc_prepnd0 && *cp1 == '0') {		from = ++cp1;		goto copyrest;	}	if (xcp -> xc_nodnic) {		for (cp1 = dnicname; *cp2 = *cp1++;)			cp2++;		cp1 = from;	}copyrest:	for (cp1 = dnicname; *cp2 = *cp1++;)		cp2++;}/* static */pk_simple_bsd (from, to, lower, len)register octet *from, *to;register len, lower;{	register int c;	while (--len >= 0) {		c = *from;		if (lower & 0x01)			*from++;		else			c >>= 4;		c &= 0x0f; c |= 0x30; *to++ = c; lower++;	}	*to = 0;}/*static octet * */pk_from_bcd (a, iscalling, sa, xcp)register struct x25_calladdr *a;register struct sockaddr_x25 *sa;register struct x25config *xcp;{	octet buf[MAXADDRLN+1];	octet *cp;	unsigned count;	bzero ((caddr_t) sa, sizeof (*sa));	sa -> x25_len = sizeof (*sa);	sa -> x25_family = AF_CCITT;	if (iscalling) {		cp = a -> address_field + (X25GBITS(a -> addrlens, called_addrlen) / 2);		count = X25GBITS(a -> addrlens, calling_addrlen);		pk_simple_bsd (cp, buf, X25GBITS(a -> addrlens, called_addrlen), count);	} else {		count = X25GBITS(a -> addrlens, called_addrlen);		pk_simple_bsd (a -> address_field, buf, 0, count);	}	if (xcp -> xc_addr.x25_net && (xcp -> xc_nodnic || xcp -> xc_prepnd0)) {		octet dnicname[sizeof (long) * NBBY/3 + 2];		sprintf ((char *) dnicname, "%d", xcp -> xc_addr.x25_net);		prune_dnic ((char *) buf, sa -> x25_addr, dnicname, xcp);	} else		bcopy ((caddr_t) buf, (caddr_t) sa -> x25_addr, count + 1);}staticsave_extra (m0, fp, so)struct mbuf *m0;octet *fp;struct socket *so;{	register struct mbuf *m;	struct cmsghdr cmsghdr;	if (m = m_copy (m, 0, (int)M_COPYALL)) {		int off = fp - mtod (m0, octet *);		int len = m -> m_pkthdr.len - off + sizeof (cmsghdr);		cmsghdr.cmsg_len = len;		cmsghdr.cmsg_level = AF_CCITT;		cmsghdr.cmsg_type = PK_FACILITIES;		m_adj (m, off);		M_PREPEND (m, sizeof (cmsghdr), M_DONTWAIT);		if (m == 0)			return;		bcopy ((caddr_t)&cmsghdr, mtod (m, caddr_t), sizeof (cmsghdr));		MCHTYPE(m, MT_CONTROL);		sbappendrecord (&so -> so_rcv, m);	}}/*  * This routine handles incoming call packets. It matches the protocol * field on the Call User Data field (usually the first four bytes) with  * sockets awaiting connections. */pk_incoming_call (pkp, m0)struct mbuf *m0;struct pkcb *pkp;{	register struct pklcd *lcp = 0, *l;	register struct sockaddr_x25 *sa;	register struct x25_calladdr *a;	register struct socket *so = 0;	struct	x25_packet *xp = mtod (m0, struct x25_packet *);	struct	mbuf *m;	struct	x25config *xcp = pkp -> pk_xcp;	int len = m0 -> m_pkthdr.len;	unsigned udlen;	char *errstr = "server unavailable";	octet *u, *facp;	int lcn = LCN(xp);	/* First, copy the data from the incoming call packet to a X25 address	   descriptor. It is to be regretted that you have	   to parse the facilities into a sockaddr to determine	   if reverse charging is being requested */	if ((m = m_get (M_DONTWAIT, MT_SONAME)) == 0)		return;	sa = mtod (m, struct sockaddr_x25 *);	a = (struct x25_calladdr *) &xp -> packet_data;	facp = u = (octet *) (a -> address_field +		((X25GBITS(a -> addrlens, called_addrlen) + X25GBITS(a -> addrlens, calling_addrlen) + 1) / 2));	u += *u + 1;	udlen = min (16, ((octet *) xp) + len - u);	if (udlen < 0)		udlen = 0;	pk_from_bcd (a, 1, sa, pkp -> pk_xcp); /* get calling address */	pk_parse_facilities (facp, sa);	bcopy ((caddr_t) u, sa -> x25_udata, udlen);	sa -> x25_udlen = udlen;	/*	 * Now, loop through the listen sockets looking for a match on the	 * PID. That is the first few octets of the user data field.	 * This is the closest thing to a port number for X.25 packets.	 * It does provide a way of multiplexing services at the user level. 	 */	for (l = pk_listenhead; l; l = l -> lcd_listen) {		struct sockaddr_x25 *sxp = l -> lcd_ceaddr;		if (bcmp (sxp -> x25_udata, u, sxp -> x25_udlen))			continue;		if (sxp -> x25_net &&		    sxp -> x25_net != xcp -> xc_addr.x25_net)			continue;		/*		 * don't accept incoming calls with the D-Bit on		 * unless the server agrees		 */		if (X25GBITS(xp -> bits, d_bit) && !(sxp -> x25_opts.op_flags & X25_DBIT)) {			errstr = "incoming D-Bit mismatch";			break;		}		/*		 * don't accept incoming collect calls unless		 * the server sets the reverse charging option.		 */		if ((sxp -> x25_opts.op_flags & (X25_OLDSOCKADDR|X25_REVERSE_CHARGE)) == 0 &&			sa -> x25_opts.op_flags & X25_REVERSE_CHARGE) {			errstr = "incoming collect call refused";			break;		}		if (l -> lcd_so) {			if (so = sonewconn (l -> lcd_so, SS_ISCONNECTED))				    lcp = (struct pklcd *) so -> so_pcb;		} else 			lcp = pk_attach ((struct socket *) 0);		if (lcp == 0) {			/*			 * Insufficient space or too many unaccepted			 * connections.  Just throw the call away.			 */			errstr = "server malfunction";			break;		}		lcp -> lcd_upper = l -> lcd_upper;		lcp -> lcd_upnext = l -> lcd_upnext;		lcp -> lcd_lcn = lcn;		lcp -> lcd_state = RECEIVED_CALL;		sa -> x25_opts.op_flags |= (sxp -> x25_opts.op_flags &			~X25_REVERSE_CHARGE) | l -> lcd_flags;		pk_assoc (pkp, lcp, sa);		lcp -> lcd_faddr = *sa;		lcp -> lcd_laddr.x25_udlen = sxp -> x25_udlen;		lcp -> lcd_craddr = &lcp -> lcd_faddr;		lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL_ACCEPTED);		if (lcp -> lcd_flags & X25_DBIT) {			if (X25GBITS(xp -> bits, d_bit))				X25SBITS(mtod (lcp -> lcd_template,					struct x25_packet *) -> bits, d_bit, 1);			else				lcp -> lcd_flags &= ~X25_DBIT;		}		if (so) {			pk_output (lcp);			soisconnected (so);			if (so -> so_options & SO_OOBINLINE)				save_extra (m0, facp, so);		} else if (lcp -> lcd_upper) {			(*lcp -> lcd_upper) (lcp, m0);		}		(void) m_free (m);		return;	}	/*	 * If the call fails for whatever reason, we still need to build a	 * skeleton LCD in order to be able to properly  receive the CLEAR	 * CONFIRMATION.	 */#ifdef WATERLOO		/* be explicit */	if (l == 0 && bcmp (sa -> x25_udata, "ean", 3) == 0)		pk_message (lcn, pkp -> pk_xcp, "host=%s ean%c: %s",			sa -> x25_addr, sa -> x25_udata[3] & 0xff, errstr);	else if (l == 0 && bcmp (sa -> x25_udata, "\1\0\0\0", 4) == 0)		pk_message (lcn, pkp -> pk_xcp, "host=%s x29d: %s",			sa -> x25_addr, errstr);	else#endif	pk_message (lcn, pkp -> pk_xcp, "host=%s pid=%x %x %x %x: %s",		sa -> x25_addr, sa -> x25_udata[0] & 0xff,		sa -> x25_udata[1] & 0xff, sa -> x25_udata[2] & 0xff,		sa -> x25_udata[3] & 0xff, errstr);	if ((lcp = pk_attach ((struct socket *)0)) == 0) {		(void) m_free (m);		return;	}	lcp -> lcd_lcn = lcn;	lcp -> lcd_state = RECEIVED_CALL;	pk_assoc (pkp, lcp, sa);	(void) m_free (m);	pk_clear (lcp, 0, 1);}pk_call_accepted (lcp, m)struct pklcd *lcp;struct mbuf *m;{	register struct x25_calladdr *ap;	register octet *fcp;	struct x25_packet *xp = mtod (m, struct x25_packet *);	int len = m -> m_len;	lcp -> lcd_state = DATA_TRANSFER;	if (lcp -> lcd_so)		soisconnected (lcp -> lcd_so);	if ((lcp -> lcd_flags & X25_DBIT) && (X25GBITS(xp -> bits, d_bit) == 0))		lcp -> lcd_flags &= ~X25_DBIT;	if (len > 3) {		ap = (struct x25_calladdr *) &xp -> packet_data;		fcp = (octet *) ap -> address_field + (X25GBITS(ap -> addrlens, calling_addrlen) +			X25GBITS(ap -> addrlens, called_addrlen) + 1) / 2;		if (fcp + *fcp <= ((octet *) xp) + len)			pk_parse_facilities (fcp, lcp -> lcd_ceaddr);	}	pk_assoc (lcp -> lcd_pkp, lcp, lcp -> lcd_ceaddr);	if (lcp -> lcd_so == 0 && lcp -> lcd_upper)		lcp -> lcd_upper (lcp, m);}pk_parse_facilities (fcp, sa)register octet *fcp;register struct sockaddr_x25 *sa;{	register octet *maxfcp;	maxfcp = fcp + *fcp;	fcp++;	while (fcp < maxfcp) {		/*		 * Ignore national DCE or DTE facilities		 */		if (*fcp == 0 || *fcp == 0xff)			break;		switch (*fcp) {		case FACILITIES_WINDOWSIZE:			sa -> x25_opts.op_wsize = fcp[1];			fcp += 3;			break;		case FACILITIES_PACKETSIZE:			sa -> x25_opts.op_psize = fcp[1];			fcp += 3;			break;		case FACILITIES_THROUGHPUT:			sa -> x25_opts.op_speed = fcp[1];			fcp += 2;			break;		case FACILITIES_REVERSE_CHARGE:			if (fcp[1] & 01)				sa -> x25_opts.op_flags |= X25_REVERSE_CHARGE;			/*			 * Datapac specific: for a X.25(1976) DTE, bit 2			 * indicates a "hi priority" (eg. international) call.			 */			if (fcp[1] & 02 && sa -> x25_opts.op_psize == 0)				sa -> x25_opts.op_psize = X25_PS128;			fcp += 2;			break;		default:/*printf("unknown facility %x, class=%d\n", *fcp, (*fcp & 0xc0) >> 6);*/			switch ((*fcp & 0xc0) >> 6) {			case 0:			/* class A */				fcp += 2;				break;			case 1:				fcp += 3;				break;			case 2:				fcp += 4;				break;			case 3:				fcp++;				fcp += *fcp;			}		}	}}

⌨️ 快捷键说明

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