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

📄 if_sl.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	register struct tty *tp;{	register struct sl_softc *sc = (struct sl_softc *)tp->t_sc;	register struct mbuf *m;	register u_char *cp;	register struct ip *ip;	int s;	struct mbuf *m2;#if NBPFILTER > 0	u_char bpfbuf[SLTMAX + SLIP_HDRLEN];	register int len = 0;#endif	for (;;) {		/*		 * Call output process whether or not there is more in the		 * output queue.  We are being called in lieu of ttstart		 * and must do what it would.		 */		(*tp->t_oproc)(tp);		if (tp->t_outq.c_cc != 0) {			if (sc != NULL)				sc->sc_flags &= ~SC_OUTWAIT;			if (tp->t_outq.c_cc > SLIP_HIWAT)				return 0;		}		/*		 * This happens briefly when the line shuts down.		 */		if (sc == NULL)			return 0;		/*		 * Get a packet and send it to the interface.		 */		s = splimp();		IF_DEQUEUE(&sc->sc_fastq, m);		if (m)			sc->sc_if.if_omcasts++;		/* XXX */		else			IF_DEQUEUE(&sc->sc_if.if_snd, m);		splx(s);		if (m == NULL)			return 0;		/*		 * We do the header compression here rather than in sloutput		 * because the packets will be out of order if we are using TOS		 * queueing, and the connection id compression will get		 * munged when this happens.		 */#if NBPFILTER > 0		if (sc->sc_if.if_bpf) {			/*			 * We need to save the TCP/IP header before it's			 * compressed.  To avoid complicated code, we just			 * copy the entire packet into a stack buffer (since			 * this is a serial line, packets should be short			 * and/or the copy should be negligible cost compared			 * to the packet transmission time).			 */			register struct mbuf *m1 = m;			register u_char *cp = bpfbuf + SLIP_HDRLEN;			len = 0;			do {				register int mlen = m1->m_len;				bcopy(mtod(m1, caddr_t), cp, mlen);				cp += mlen;				len += mlen;			} while (m1 = m1->m_next);		}#endif		ip = mtod(m, struct ip *);		if (ip->ip_v == IPVERSION && ip->ip_p == IPPROTO_TCP) {			if (sc->sc_if.if_flags & SC_COMPRESS)				*mtod(m, u_char *) |= sl_compress_tcp(m, ip,				    &sc->sc_comp, 1);		}#if NBPFILTER > 0		if (sc->sc_if.if_bpf) {			/*			 * Put the SLIP pseudo-"link header" in place.  The			 * compressed header is now at the beginning of the			 * mbuf.			 */			bpfbuf[SLX_DIR] = SLIPDIR_OUT;			bcopy(mtod(m, caddr_t), &bpfbuf[SLX_CHDR], CHDR_LEN);			bpf_tap(&sc->sc_if, bpfbuf, len + SLIP_HDRLEN);		}#endif		/*		 * If system is getting low on clists, just flush our		 * output queue (if the stuff was important, it'll get		 * retransmitted). Note that SLTMAX is used instead of		 * the current if_mtu setting because connections that		 * have already been established still use the original		 * (possibly larger) mss.		 */		if (cfreecount < CLISTRESERVE + SLTMAX) {			m_freem(m);			sc->sc_if.if_collisions++;			continue;		}		sc->sc_flags &= ~SC_OUTWAIT;		/*		 * The extra FRAME_END will start up a new packet, and thus		 * will flush any accumulated garbage.  We do this whenever		 * the line may have been idle for some time.		 */		if (tp->t_outq.c_cc == 0) {			++sc->sc_if.if_obytes;			(void) putc(FRAME_END, &tp->t_outq);		}		while (m) {			register u_char *ep;			cp = mtod(m, u_char *); ep = cp + m->m_len;			while (cp < ep) {				/*				 * Find out how many bytes in the string we can				 * handle without doing something special.				 */				register u_char *bp = cp;				while (cp < ep) {					switch (*cp++) {					case FRAME_ESCAPE:					case FRAME_END:						--cp;						goto out;					}				}				out:				if (cp > bp) {					/*					 * Put n characters at once					 * into the tty output queue.					 */					if (b_to_q((char *)bp, cp - bp,					    &tp->t_outq))						break;					sc->sc_if.if_obytes += cp - bp;				}				/*				 * If there are characters left in the mbuf,				 * the first one must be special..				 * Put it out in a different form.				 */				if (cp < ep) {					if (putc(FRAME_ESCAPE, &tp->t_outq))						break;					if (putc(*cp++ == FRAME_ESCAPE ?					   TRANS_FRAME_ESCAPE : TRANS_FRAME_END,					   &tp->t_outq)) {						(void) unputc(&tp->t_outq);						break;					}					sc->sc_if.if_obytes += 2;				}			}			MFREE(m, m2);			m = m2;		}		if (putc(FRAME_END, &tp->t_outq)) {			/*			 * Not enough room.  Remove a char to make room			 * and end the packet normally.			 * If you get many collisions (more than one or two			 * a day) you probably do not have enough clists			 * and you should increase "nclist" in param.c.			 */			(void) unputc(&tp->t_outq);			(void) putc(FRAME_END, &tp->t_outq);			sc->sc_if.if_collisions++;		} else {			++sc->sc_if.if_obytes;			sc->sc_if.if_opackets++;		}	}	return 0;}/* * Copy data buffer to mbuf chain; add ifnet pointer. */static struct mbuf *sl_btom(sc, len)	register struct sl_softc *sc;	register int len;{	register struct mbuf *m;	MGETHDR(m, M_DONTWAIT, MT_DATA);	if (m == NULL)		return (NULL);	/*	 * If we have more than MHLEN bytes, it's cheaper to	 * queue the cluster we just filled & allocate a new one	 * for the input buffer.  Otherwise, fill the mbuf we	 * allocated above.  Note that code in the input routine	 * guarantees that packet will fit in a cluster.	 */	if (len >= MHLEN) {		MCLGET(m, M_DONTWAIT);		if ((m->m_flags & M_EXT) == 0) {			/*			 * we couldn't get a cluster - if memory's this			 * low, it's time to start dropping packets.			 */			(void) m_free(m);			return (NULL);		}		sc->sc_ep = mtod(m, u_char *) + SLBUFSIZE;		m->m_data = (caddr_t)sc->sc_buf;		m->m_ext.ext_buf = (caddr_t)((intptr_t)sc->sc_buf &~ MCLOFSET);	} else		bcopy((caddr_t)sc->sc_buf, mtod(m, caddr_t), len);	m->m_len = len;	m->m_pkthdr.len = len;	m->m_pkthdr.rcvif = &sc->sc_if;	return (m);}/* * tty interface receiver interrupt. */static intslinput(c, tp)	register int c;	register struct tty *tp;{	register struct sl_softc *sc;	register struct mbuf *m;	register int len;	int s;#if NBPFILTER > 0	u_char chdr[CHDR_LEN];#endif	tk_nin++;	sc = (struct sl_softc *)tp->t_sc;	if (sc == NULL)		return 0;	if (c & TTY_ERRORMASK || (tp->t_state & TS_CONNECTED) == 0) {		sc->sc_flags |= SC_ERROR;		return 0;	}	c &= TTY_CHARMASK;	++sc->sc_if.if_ibytes;	if (sc->sc_if.if_flags & IFF_DEBUG) {		if (c == ABT_ESC) {			/*			 * If we have a previous abort, see whether			 * this one is within the time limit.			 */			if (sc->sc_abortcount &&			    time_second >= sc->sc_starttime + ABT_WINDOW)				sc->sc_abortcount = 0;			/*			 * If we see an abort after "idle" time, count it;			 * record when the first abort escape arrived.			 */			if (time_second >= sc->sc_lasttime + ABT_IDLE) {				if (++sc->sc_abortcount == 1)					sc->sc_starttime = time_second;				if (sc->sc_abortcount >= ABT_COUNT) {					slclose(tp,0);					return 0;				}			}		} else			sc->sc_abortcount = 0;		sc->sc_lasttime = time_second;	}	switch (c) {	case TRANS_FRAME_ESCAPE:		if (sc->sc_escape)			c = FRAME_ESCAPE;		break;	case TRANS_FRAME_END:		if (sc->sc_escape)			c = FRAME_END;		break;	case FRAME_ESCAPE:		sc->sc_escape = 1;		return 0;	case FRAME_END:		sc->sc_flags &= ~SC_KEEPALIVE;		if(sc->sc_flags & SC_ERROR) {			sc->sc_flags &= ~SC_ERROR;			goto newpack;		}		len = sc->sc_mp - sc->sc_buf;		if (len < 3)			/* less than min length packet - ignore */			goto newpack;#if NBPFILTER > 0		if (sc->sc_if.if_bpf) {			/*			 * Save the compressed header, so we			 * can tack it on later.  Note that we			 * will end up copying garbage in some			 * cases but this is okay.  We remember			 * where the buffer started so we can			 * compute the new header length.			 */			bcopy(sc->sc_buf, chdr, CHDR_LEN);		}#endif		if ((c = (*sc->sc_buf & 0xf0)) != (IPVERSION << 4)) {			if (c & 0x80)				c = TYPE_COMPRESSED_TCP;			else if (c == TYPE_UNCOMPRESSED_TCP)				*sc->sc_buf &= 0x4f; /* XXX */			/*			 * We've got something that's not an IP packet.			 * If compression is enabled, try to decompress it.			 * Otherwise, if `auto-enable' compression is on and			 * it's a reasonable packet, decompress it and then			 * enable compression.  Otherwise, drop it.			 */			if (sc->sc_if.if_flags & SC_COMPRESS) {				len = sl_uncompress_tcp(&sc->sc_buf, len,							(u_int)c, &sc->sc_comp);				if (len <= 0)					goto error;			} else if ((sc->sc_if.if_flags & SC_AUTOCOMP) &&			    c == TYPE_UNCOMPRESSED_TCP && len >= 40) {				len = sl_uncompress_tcp(&sc->sc_buf, len,							(u_int)c, &sc->sc_comp);				if (len <= 0)					goto error;				sc->sc_if.if_flags |= SC_COMPRESS;			} else				goto error;		}#if NBPFILTER > 0		if (sc->sc_if.if_bpf) {			/*			 * Put the SLIP pseudo-"link header" in place.			 * We couldn't do this any earlier since			 * decompression probably moved the buffer			 * pointer.  Then, invoke BPF.			 */			register u_char *hp = sc->sc_buf - SLIP_HDRLEN;			hp[SLX_DIR] = SLIPDIR_IN;			bcopy(chdr, &hp[SLX_CHDR], CHDR_LEN);			bpf_tap(&sc->sc_if, hp, len + SLIP_HDRLEN);		}#endif		m = sl_btom(sc, len);		if (m == NULL)			goto error;		sc->sc_if.if_ipackets++;		if ((sc->sc_if.if_flags & IFF_UP) == 0) {			m_freem(m);			goto newpack;		}		s = splimp();		if (IF_QFULL(&ipintrq)) {			IF_DROP(&ipintrq);			sc->sc_if.if_ierrors++;			sc->sc_if.if_iqdrops++;			m_freem(m);		} else {			IF_ENQUEUE(&ipintrq, m);			schednetisr(NETISR_IP);		}		splx(s);		goto newpack;	}	if (sc->sc_mp < sc->sc_ep) {		*sc->sc_mp++ = c;		sc->sc_escape = 0;		return 0;	}	/* can't put lower; would miss an extra frame */	sc->sc_flags |= SC_ERROR;error:	sc->sc_if.if_ierrors++;newpack:	sc->sc_mp = sc->sc_buf = sc->sc_ep - SLRMAX;	sc->sc_escape = 0;	return 0;}/* * Process an ioctl request. */static intslioctl(ifp, cmd, data)	register struct ifnet *ifp;	u_long cmd;	caddr_t data;{	register struct ifaddr *ifa = (struct ifaddr *)data;	register struct ifreq *ifr = (struct ifreq *)data;	register int s, error = 0;	s = splimp();	switch (cmd) {	case SIOCSIFFLAGS:		/*		 * if.c will set the interface up even if we		 * don't want it to.		 */		if (sl_softc[ifp->if_unit].sc_ttyp == NULL) {			ifp->if_flags &= ~IFF_UP;		}		break;	case SIOCSIFADDR:		/*		 * This is "historical" - set the interface up when		 * setting the address.		 */		if (ifa->ifa_addr->sa_family == AF_INET) {			if (sl_softc[ifp->if_unit].sc_ttyp != NULL)				if_up(ifp);		} else {			error = EAFNOSUPPORT;		}		break;	case SIOCSIFDSTADDR:		if (ifa->ifa_addr->sa_family != AF_INET)			error = EAFNOSUPPORT;		break;	case SIOCADDMULTI:	case SIOCDELMULTI:		break;	case SIOCSIFMTU:		/*		 * Set the interface MTU.		 */		if (ifr->ifr_mtu > SLTMAX)			error = EINVAL;		else {			struct tty *tp;			ifp->if_mtu = ifr->ifr_mtu;			tp = sl_softc[ifp->if_unit].sc_ttyp;			if (tp != NULL)				clist_alloc_cblocks(&tp->t_outq,				    SLIP_HIWAT + 2 * ifp->if_mtu + 1,				    SLIP_HIWAT + 2 * ifp->if_mtu + 1);		}		break;	default:		error = EINVAL;	}	splx(s);	return (error);}static voidsl_keepalive(chan)	void *chan;{	struct sl_softc *sc = chan;	if (sc->sc_keepalive) {		if (sc->sc_flags & SC_KEEPALIVE)			pgsignal (sc->sc_ttyp->t_pgrp, SIGURG, 1);		else			sc->sc_flags |= SC_KEEPALIVE;		sc->sc_kahandle = timeout(sl_keepalive, sc, sc->sc_keepalive);	} else {		sc->sc_flags &= ~SC_KEEPALIVE;	}}static voidsl_outfill(chan)	void *chan;{	struct sl_softc *sc = chan;	register struct tty *tp = sc->sc_ttyp;	int s;	if (sc->sc_outfill && tp != NULL) {		if (sc->sc_flags & SC_OUTWAIT) {			s = splimp ();			++sc->sc_if.if_obytes;			(void) putc(FRAME_END, &tp->t_outq);			(*tp->t_oproc)(tp);			splx (s);		} else			sc->sc_flags |= SC_OUTWAIT;		sc->sc_ofhandle = timeout(sl_outfill, sc, sc->sc_outfill);	} else {		sc->sc_flags &= ~SC_OUTWAIT;	}}#endif

⌨️ 快捷键说明

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