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

📄 if_sl.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	sc = &sl_softc[ifp->if_unit];	if (sc->sc_ttyp == NULL) {		m_freem(m);		return (ENETDOWN);	/* sort of */	}	if ((sc->sc_ttyp->t_state & TS_CARR_ON) == 0) {		m_freem(m);		return (EHOSTUNREACH);	}		ifq = &ifp->if_snd;	if ((ip = mtod(m, struct ip *))->ip_p == IPPROTO_TCP) {		register int p = -1;		if (m->m_len > sizeof(struct ip))			p = ((int *)ip)[ip->ip_hl];		if (INTERACTIVE(p & 0xffff) || INTERACTIVE(p >> 16)) {			ifq = &sc->sc_fastq;			p = 1;		} else			p = 0;		if (sc->sc_if.if_flags & IFF_D1) {			/*			 * The last parameter turns off connection id			 * compression for background traffic:  Since			 * fastq traffic can jump ahead of the background			 * traffic, we don't know what order packets will			 * go on the line.			 */		  			p = sl_compress_tcp(m, ip, &sc->sc_comp, p);			*mtod(m, u_char *) |= p;		}	} else if ((sc->sc_if.if_flags & IFF_D3) && ip->ip_p == IPPROTO_ICMP) {		m_freem(m);		return (0);	}	s = splimp();	if (IF_QFULL(ifq)) {		IF_DROP(ifq);		m_freem(m);		splx(s);		sc->sc_if.if_oerrors++;		return (ENOBUFS);	}	IF_ENQUEUE(ifq, m);	if (sc->sc_ttyp->t_outq.c_cc == 0) {	  splx(s);	  slstart(sc->sc_ttyp);	} else	    splx(s);	return (0);}/* * Start output on interface.  Get another datagram * to send from the interface queue and map it to * the interface before starting output. */slstart(tp)	register struct tty *tp;{	register struct sl_softc *sc = (struct sl_softc *)tp->t_sc;	register struct mbuf *m;	register u_char *cp;	int s;	struct mbuf *m2;#if !defined(ultrix) || defined(ULTRIX_3)	extern int cfreecount;#endif		for (;;) {		/*		 * If there is more in the output queue, just send it now.		 * We are being called in lieu of ttstart and must do what		 * it would.		 */#ifdef vax	  s=splimp();#else#ifdef mips	  s=spltty();  /* Mips requires higher IPL than Vax */#endif mips#endif vax		if (tp->t_outq.c_cc != 0) {		  (*tp->t_oproc)(tp);		  if (tp->t_outq.c_cc > SLIP_HIWAT) {		    splx(s);		    return;		  }		}	  		/*		 * This happens briefly when the line shuts down.		 */	  if (sc == NULL) {	    splx(s);	    return;	  }	  		/*		 * Get a packet and send it to the interface.		 */		IF_DEQUEUE(&sc->sc_fastq, m);		if (m == NULL)			IF_DEQUEUE(&sc->sc_if.if_snd, m);#if defined(SL_NIT) && defined(NIT)		if (m && sl_donit && nitcb.ncb_next != &nitcb) {			/* do nit processing if there's anyone listening */			static struct ether_header oheader = { { 1 }, { 2 } };			struct nit_ii nii;			int len = 0;			m2 = m;			do {				len += m2->m_len;			} while (m2 = m2->m_next);			oheader.ether_type = *mtod(m, u_char *);			nii.nii_header = (caddr_t)&oheader;			nii.nii_hdrlen = sizeof(oheader);			nii.nii_type = oheader.ether_type;			nii.nii_datalen = len;			nii.nii_promisc = 0;			nit_tap(&sc->sc_if, m, &nii);		}#endif		splx(s);		if (m == NULL)			return;		/*		 * If system is getting low on clists, just flush our		 * output queue (if the stuff was important, it'll get		 * retransmitted).		 */#if !defined(ultrix) || defined(ULTIX_3)		if (cfreecount < CLISTRESERVE + SLMTU) {			m_freem(m);			sc->sc_if.if_collisions++;			continue;		}#endif		/*		 * 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_bytessent;			(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_bytessent += 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_bytessent += 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_bytessent;			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 u_char *cp;	register struct mbuf *m;	MGET(m, M_DONTWAIT, MT_DATA);	if (m == NULL)		return (NULL);	/*	 * If we have more than MLEN 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 + ifp will fit in a cluster and	 * initial setup left room for interface pointer.	 */	cp = sc->sc_buf;#if BSD==43	if (len >= MLEN - sizeof(struct ifnet *)) {		MCLGET(m);		if (m->m_len != MCLBYTES) {			/* we couldn't get a cluster - if memory's this			 * low, it's time to start dropping packets. */			m_freem(m);			return (NULL);		}		sc->sc_ep = mtod(m, u_char *) + (BUFOFFSET + SLMAX);		m->m_off = (int)cp - (int)m - sizeof(struct ifnet *);	} else {		bcopy((caddr_t)cp, mtod(m, caddr_t) + sizeof(struct ifnet *),			len);	}	m->m_len = len + sizeof(struct ifnet *);	*mtod(m, struct ifnet **) = &sc->sc_if;#else#ifdef ultrix	if (len >= MLEN) {		struct mbuf *p;		MCLGET(m,p);		if (m->m_len != MCLBYTES) {			/* we couldn't get a cluster - if memory's this			 * low, it's time to start dropping packets. */			m_freem(m);			return (NULL);		}		m->m_clptr = (caddr_t)(sc->sc_ep - (SLMAX + BUFOFFSET));		sc->sc_ep = mtod(m, u_char *) + (BUFOFFSET + SLMAX);		m->m_off = (int)cp;	} else {		bcopy((caddr_t)cp, mtod(m, caddr_t), len);	}	m->m_len = len;#ifdef ULTRIX_3	m->ifnetptr= (char *) &sc->sc_if;#else	m->m_ifp = &sc->sc_if;#endif ULTRIX_3#else	if (len >= MLEN) {		MCLGET(m);		if (m->m_len != MCLBYTES) {			/* we couldn't get a cluster - if memory's this			 * low, it's time to start dropping packets. */			m_freem(m);			return (NULL);		}		sc->sc_ep = mtod(m, u_char *) + (BUFOFFSET + SLMAX);		m->m_off = (int)cp - (int)m;	} else {		bcopy((caddr_t)cp, mtod(m, caddr_t), len);	}	m->m_len = len;#endif#endif	return (m);}/* * tty interface receiver interrupt. */slinput(c, tp)	register int c;	register struct tty *tp;{	register struct sl_softc *sc;	register struct mbuf *m;	register int len;	int s;#if defined(ultrix) && defined(ULTRIX_4)		  struct ifqueue *inq;#endif	tk_nin++;	sc = (struct sl_softc *)tp->t_sc;	if (sc == NULL)		return;	++sc->sc_bytesrcvd;	c &= 0xff;	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:		len = sc->sc_mp - sc->sc_buf;		if (len < 3)			/* less than min length packet - ignore */			goto newpack;#if defined(SL_NIT) && defined(NIT)		if (sl_donit && nitcb.ncb_next != &nitcb) {			/* do nit processing if there's anyone listening */			static struct ether_header iheader = { { 2 }, { 1 } };			static struct mbuf mb;			struct nit_ii nii;			m = &mb;			m->m_len = len;			m->m_off = (int)sc->sc_buf - (int)m;			iheader.ether_type = *sc->sc_buf;			nii.nii_header = (caddr_t)&iheader;			nii.nii_hdrlen = sizeof(iheader);			nii.nii_type = iheader.ether_type;			nii.nii_datalen = len;			nii.nii_promisc = 0;			nit_tap(&sc->sc_if, m, &nii);		}#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;			/*			 * we've got something that's not an IP packet.			 * If compression is enabled, try to uncompress it.			 * Otherwise, if `auto-enable' compression is on and			 * it's a reasonable packet, uncompress it then			 * enable compression.  Otherwise, drop it.			 */			if (sc->sc_if.if_flags & IFF_D1) {				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 & IFF_D2) &&				   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 |= IFF_D1;			} else				goto error;		}		m = sl_btom(sc, len);		if (m == NULL)			goto error;		sc->sc_if.if_ipackets++;		s = splimp();#if defined(ultrix) && defined(ULTRIX_4)		  inq = &ipintrq;		  smp_lock(&inq->lk_ifqueue, LK_RETRY);#endif		if (IF_QFULL(&ipintrq)) {			IF_DROP(&ipintrq);			sc->sc_if.if_ierrors++;			m_freem(m);		} else {			IF_ENQUEUE(&ipintrq, m);			schednetisr(NETISR_IP);		}#if defined(ultrix) && defined(ULTRIX_4)		  smp_unlock(&inq->lk_ifqueue);#endif		  splx(s);		  goto newpack;	}	if (sc->sc_mp < sc->sc_ep) {		*sc->sc_mp++ = c;		sc->sc_escape = 0;		return;	}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. */slioctl(ifp, cmd, data)	register struct ifnet *ifp;	int cmd;	caddr_t data;{	int s = splimp(), error = 0;#ifndef sun	register struct ifaddr *ifa = (struct ifaddr *)data;	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;	default:		error = EINVAL;	}#else	switch (cmd) {	case SIOCSIFADDR:		if_rtdelete(ifp);		ifp->if_addr = *(struct sockaddr *)data;		ifp->if_net = in_netof(((struct sockaddr_in *)data)->sin_addr);		ifp->if_flags |= IFF_UP|IFF_RUNNING;		ifp->if_flags &=~ IFF_BROADCAST;		/* set up routing table entry */		error = rtinit(&ifp->if_dstaddr, &ifp->if_addr,				RTF_HOST|RTF_UP);		ifp->if_flags |= IFF_ROUTE;		break;	case SIOCSIFDSTADDR:		/* all the real work is done for us in ../net/if.c */		break;	default:		error = EINVAL;	}#endif	splx(s);	return (error);}#endif

⌨️ 快捷键说明

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