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

📄 if_sl.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
		/*		 * 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;		/*		 * 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_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		if ((ip = mtod(m, struct 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_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_bpf, bpfbuf, len + SLIP_HDRLEN);		}#endif		sc->sc_if.if_lastchange = time;		/*		 * If system is getting low on clists, just flush our		 * output queue (if the stuff was important, it'll get		 * retransmitted).		 */		if (cfreecount < CLISTRESERVE + SLMTU) {			m_freem(m);			sc->sc_if.if_collisions++;			continue;		}		/*		 * 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++;		}	}}/* * 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)((int)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. */voidslinput(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;	if (c & TTY_ERRORMASK || ((tp->t_state & TS_CARR_ON) == 0 &&	    (tp->t_cflag & CLOCAL) == 0)) {		sc->sc_flags |= SC_ERROR;		return;	}	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.tv_sec >= 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.tv_sec >= sc->sc_lasttime + ABT_IDLE) {				if (++sc->sc_abortcount == 1)					sc->sc_starttime = time.tv_sec;				if (sc->sc_abortcount >= ABT_COUNT) {					slclose(tp);					return;				}			}		} else			sc->sc_abortcount = 0;		sc->sc_lasttime = time.tv_sec;	}	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;	case FRAME_END:		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_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_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_bpf, hp, len + SLIP_HDRLEN);		}#endif		m = sl_btom(sc, len);		if (m == NULL)			goto error;		sc->sc_if.if_ipackets++;		sc->sc_if.if_lastchange = time;		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;	}	/* 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 - SLMAX;	sc->sc_escape = 0;}/* * Process an ioctl request. */intslioctl(ifp, cmd, data)	register struct ifnet *ifp;	int cmd;	caddr_t data;{	register struct ifaddr *ifa = (struct ifaddr *)data;	register struct ifreq *ifr;	register int s = splimp(), error = 0;	switch (cmd) {	case SIOCSIFADDR:		if (ifa->ifa_addr->sa_family == AF_INET)			ifp->if_flags |= IFF_UP;		else			error = EAFNOSUPPORT;		break;	case SIOCSIFDSTADDR:		if (ifa->ifa_addr->sa_family != AF_INET)			error = EAFNOSUPPORT;		break;	case SIOCADDMULTI:	case SIOCDELMULTI:		ifr = (struct ifreq *)data;		if (ifr == 0) {			error = EAFNOSUPPORT;		/* XXX */			break;		}		switch (ifr->ifr_addr.sa_family) {#ifdef INET		case AF_INET:			break;#endif		default:			error = EAFNOSUPPORT;			break;		}		break;	default:		error = EINVAL;	}	splx(s);	return (error);}#endif

⌨️ 快捷键说明

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