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

📄 if_spppsubr.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#endif#ifdef NS		case PPP_XNS:			/* XNS IDPCP not implemented yet */			if (sp->pp_phase == PHASE_NETWORK) {				schednetisr (NETISR_NS);				inq = &nsintrq;			}			break;#endif#ifdef ISO		case PPP_ISO:			/* OSI NLCP not implemented yet */			if (sp->pp_phase == PHASE_NETWORK) {				schednetisr (NETISR_ISO);				inq = &clnlintrq;			}			break;#endif		}		break;	case CISCO_MULTICAST:	case CISCO_UNICAST:		/* Don't check the control field here (RFC 1547). */		if (! (sp->pp_flags & PP_CISCO)) {			if (debug)				log(LOG_DEBUG,				    SPP_FMT "Cisco packet in PPP mode "				    "<addr=0x%x ctrl=0x%x proto=0x%x>\n",				    SPP_ARGS(ifp),				    h->address, h->control, ntohs(h->protocol));			goto drop;		}		switch (ntohs (h->protocol)) {		default:			++ifp->if_noproto;			goto invalid;		case CISCO_KEEPALIVE:			sppp_cisco_input ((struct sppp*) ifp, m);			m_freem (m);			return;#ifdef INET		case ETHERTYPE_IP:			schednetisr (NETISR_IP);			inq = &ipintrq;			break;#endif#ifdef IPX		case ETHERTYPE_IPX:			schednetisr (NETISR_IPX);			inq = &ipxintrq;			break;#endif#ifdef NS		case ETHERTYPE_NS:			schednetisr (NETISR_NS);			inq = &nsintrq;			break;#endif		}		break;	default:        /* Invalid PPP packet. */	  invalid:		if (debug)			log(LOG_DEBUG,			    SPP_FMT "invalid input packet "			    "<addr=0x%x ctrl=0x%x proto=0x%x>\n",			    SPP_ARGS(ifp),			    h->address, h->control, ntohs(h->protocol));		goto drop;	}	if (! (ifp->if_flags & IFF_UP) || ! inq)		goto drop;	/* Check queue. */	s = splimp();	if (IF_QFULL (inq)) {		/* Queue overflow. */		IF_DROP(inq);		splx(s);		if (debug)			log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n",				SPP_ARGS(ifp));		goto drop;	}	IF_ENQUEUE(inq, m);	splx(s);}/* * Enqueue transmit packet. */static intsppp_output(struct ifnet *ifp, struct mbuf *m,	    struct sockaddr *dst, struct rtentry *rt){	struct sppp *sp = (struct sppp*) ifp;	struct ppp_header *h;	struct ifqueue *ifq;	int s, rv = 0;	int debug = ifp->if_flags & IFF_DEBUG;	s = splimp();	if ((ifp->if_flags & IFF_UP) == 0 ||	    (ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == 0) {		m_freem (m);		splx (s);		return (ENETDOWN);	}	if ((ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == IFF_AUTO) {		/*		 * Interface is not yet running, but auto-dial.  Need		 * to start LCP for it.		 */		ifp->if_flags |= IFF_RUNNING;		splx(s);		lcp.Open(sp);		s = splimp();	}	ifq = &ifp->if_snd;#ifdef INET	if (dst->sa_family == AF_INET) {		/* XXX Check mbuf length here? */		struct ip *ip = mtod (m, struct ip*);		struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl);		/*		 * When using dynamic local IP address assignment by using		 * 0.0.0.0 as a local address, the first TCP session will		 * not connect because the local TCP checksum is computed		 * using 0.0.0.0 which will later become our real IP address		 * so the TCP checksum computed at the remote end will		 * become invalid. So we		 * - don't let packets with src ip addr 0 thru		 * - we flag TCP packets with src ip 0 as an error		 */			if(ip->ip_src.s_addr == INADDR_ANY)	/* -hm */		{			m_freem(m);			splx(s);			if(ip->ip_p == IPPROTO_TCP)				return(EADDRNOTAVAIL);			else				return(0);		}				/*		 * Put low delay, telnet, rlogin and ftp control packets		 * in front of the queue.		 */		if (IF_QFULL (&sp->pp_fastq))			;		else if (ip->ip_tos & IPTOS_LOWDELAY)			ifq = &sp->pp_fastq;		else if (m->m_len < sizeof *ip + sizeof *tcp)			;		else if (ip->ip_p != IPPROTO_TCP)			;		else if (INTERACTIVE (ntohs (tcp->th_sport)))			ifq = &sp->pp_fastq;		else if (INTERACTIVE (ntohs (tcp->th_dport)))			ifq = &sp->pp_fastq;	}#endif	/*	 * Prepend general data packet PPP header. For now, IP only.	 */	M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT);	if (! m) {		if (debug)			log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n",				SPP_ARGS(ifp));		++ifp->if_oerrors;		splx (s);		return (ENOBUFS);	}	/*	 * May want to check size of packet	 * (albeit due to the implementation it's always enough)	 */	h = mtod (m, struct ppp_header*);	if (sp->pp_flags & PP_CISCO) {		h->address = CISCO_UNICAST;        /* unicast address */		h->control = 0;	} else {		h->address = PPP_ALLSTATIONS;        /* broadcast address */		h->control = PPP_UI;                 /* Unnumbered Info */	}	switch (dst->sa_family) {#ifdef INET	case AF_INET:   /* Internet Protocol */		if (sp->pp_flags & PP_CISCO)			h->protocol = htons (ETHERTYPE_IP);		else {			/*			 * Don't choke with an ENETDOWN early.  It's			 * possible that we just started dialing out,			 * so don't drop the packet immediately.  If			 * we notice that we run out of buffer space			 * below, we will however remember that we are			 * not ready to carry IP packets, and return			 * ENETDOWN, as opposed to ENOBUFS.			 */			h->protocol = htons(PPP_IP);			if (sp->state[IDX_IPCP] != STATE_OPENED)				rv = ENETDOWN;		}		break;#endif#ifdef NS	case AF_NS:     /* Xerox NS Protocol */		h->protocol = htons ((sp->pp_flags & PP_CISCO) ?			ETHERTYPE_NS : PPP_XNS);		break;#endif#ifdef IPX	case AF_IPX:     /* Novell IPX Protocol */		h->protocol = htons ((sp->pp_flags & PP_CISCO) ?			ETHERTYPE_IPX : PPP_IPX);		break;#endif#ifdef ISO	case AF_ISO:    /* ISO OSI Protocol */		if (sp->pp_flags & PP_CISCO)			goto nosupport;		h->protocol = htons (PPP_ISO);		break;nosupport:#endif	default:		m_freem (m);		++ifp->if_oerrors;		splx (s);		return (EAFNOSUPPORT);	}	/*	 * Queue message on interface, and start output if interface	 * not yet active.	 */	if (IF_QFULL (ifq)) {		IF_DROP (&ifp->if_snd);		m_freem (m);		++ifp->if_oerrors;		splx (s);		return (rv? rv: ENOBUFS);	}	IF_ENQUEUE (ifq, m);	if (! (ifp->if_flags & IFF_OACTIVE))		(*ifp->if_start) (ifp);	/*	 * Count output packets and bytes.	 * The packet length includes header, FCS and 1 flag,	 * according to RFC 1333.	 */	ifp->if_obytes += m->m_pkthdr.len + 3;	splx (s);	return (0);}voidsppp_attach(struct ifnet *ifp){	struct sppp *sp = (struct sppp*) ifp;	/* Initialize keepalive handler. */	if (! spppq)		TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch);	/* Insert new entry into the keepalive list. */	sp->pp_next = spppq;	spppq = sp;	sp->pp_if.if_mtu = PP_MTU;	sp->pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;	sp->pp_if.if_type = IFT_PPP;	sp->pp_if.if_output = sppp_output;#if 0	sp->pp_flags = PP_KEEPALIVE;#endif	sp->pp_fastq.ifq_maxlen = 32;	sp->pp_cpq.ifq_maxlen = 20;	sp->pp_loopcnt = 0;	sp->pp_alivecnt = 0;	sp->pp_seq = 0;	sp->pp_rseq = 0;	sp->pp_phase = PHASE_DEAD;	sp->pp_up = lcp.Up;	sp->pp_down = lcp.Down;	sppp_lcp_init(sp);	sppp_ipcp_init(sp);	sppp_pap_init(sp);	sppp_chap_init(sp);}voidsppp_detach(struct ifnet *ifp){	struct sppp **q, *p, *sp = (struct sppp*) ifp;	int i;	/* Remove the entry from the keepalive list. */	for (q = &spppq; (p = *q); q = &p->pp_next)		if (p == sp) {			*q = p->pp_next;			break;		}	/* Stop keepalive handler. */	if (! spppq)		UNTIMEOUT(sppp_keepalive, 0, keepalive_ch);	for (i = 0; i < IDX_COUNT; i++)		UNTIMEOUT((cps[i])->TO, (void *)sp, sp->ch[i]);	UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch);}/* * Flush the interface output queue. */voidsppp_flush(struct ifnet *ifp){	struct sppp *sp = (struct sppp*) ifp;	sppp_qflush (&sp->pp_if.if_snd);	sppp_qflush (&sp->pp_fastq);	sppp_qflush (&sp->pp_cpq);}/* * Check if the output queue is empty. */intsppp_isempty(struct ifnet *ifp){	struct sppp *sp = (struct sppp*) ifp;	int empty, s;	s = splimp();	empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head &&		!sp->pp_if.if_snd.ifq_head;	splx(s);	return (empty);}/* * Get next packet to send. */struct mbuf *sppp_dequeue(struct ifnet *ifp){	struct sppp *sp = (struct sppp*) ifp;	struct mbuf *m;	int s;	s = splimp();	/*	 * Process only the control protocol queue until we have at	 * least one NCP open.	 *	 * Do always serve all three queues in Cisco mode.	 */	IF_DEQUEUE(&sp->pp_cpq, m);	if (m == NULL &&	    (sppp_ncp_check(sp) || (sp->pp_flags & PP_CISCO) != 0)) {		IF_DEQUEUE(&sp->pp_fastq, m);		if (m == NULL)			IF_DEQUEUE (&sp->pp_if.if_snd, m);	}	splx(s);	return m;}/* * Pick the next packet, do not remove it from the queue. */struct mbuf *sppp_pick(struct ifnet *ifp){	struct sppp *sp = (struct sppp*)ifp;	struct mbuf *m;	int s;	s= splimp ();	m = sp->pp_cpq.ifq_head;	if (m == NULL &&	    (sp->pp_phase == PHASE_NETWORK ||	     (sp->pp_flags & PP_CISCO) != 0))		if ((m = sp->pp_fastq.ifq_head) == NULL)			m = sp->pp_if.if_snd.ifq_head;	splx (s);	return (m);}/* * Process an ioctl request.  Called on low priority level. */intsppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data){	struct ifreq *ifr = (struct ifreq*) data;	struct sppp *sp = (struct sppp*) ifp;	int s, rv, going_up, going_down, newmode;	s = splimp();	rv = 0;	switch (cmd) {	case SIOCAIFADDR:	case SIOCSIFDSTADDR:		break;	case SIOCSIFADDR:		if_up(ifp);		/* fall through... */	case SIOCSIFFLAGS:		going_up = ifp->if_flags & IFF_UP &&			(ifp->if_flags & IFF_RUNNING) == 0;		going_down = (ifp->if_flags & IFF_UP) == 0 &&			ifp->if_flags & IFF_RUNNING;		newmode = ifp->if_flags & (IFF_AUTO | IFF_PASSIVE);		if (newmode == (IFF_AUTO | IFF_PASSIVE)) {			/* sanity */			newmode = IFF_PASSIVE;			ifp->if_flags &= ~IFF_AUTO;		}		if (going_up || going_down)			lcp.Close(sp);		if (going_up && newmode == 0) {			/* neither auto-dial nor passive */			ifp->if_flags |= IFF_RUNNING;			if (!(sp->pp_flags & PP_CISCO))				lcp.Open(sp);		} else if (going_down) {			sppp_flush(ifp);			ifp->if_flags &= ~IFF_RUNNING;		}		break;#ifdef SIOCSIFMTU#ifndef ifr_mtu#define ifr_mtu ifr_metric#endif	case SIOCSIFMTU:		if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru)			return (EINVAL);		ifp->if_mtu = ifr->ifr_mtu;		break;#endif#ifdef SLIOCSETMTU	case SLIOCSETMTU:		if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru)			return (EINVAL);		ifp->if_mtu = *(short*)data;		break;#endif#ifdef SIOCGIFMTU	case SIOCGIFMTU:		ifr->ifr_mtu = ifp->if_mtu;		break;#endif#ifdef SLIOCGETMTU	case SLIOCGETMTU:		*(short*)data = ifp->if_mtu;		break;#endif	case SIOCADDMULTI:	case SIOCDELMULTI:		break;	case SIOCGIFGENERIC:	case SIOCSIFGENERIC:		rv = sppp_params(sp, cmd, data);		break;	default:		rv = ENOTTY;	}	splx(s);	return rv;}/* * Cisco framing implementation. *//* * Handle incoming Cisco keepalive protocol packets. */static voidsppp_cisco_input(struct sppp *sp, struct mbuf *m){	STDDCL;	struct cisco_packet *h;	u_long me, mymask;	if (m->m_pkthdr.len < CISCO_PACKET_LEN) {		if (debug)			log(LOG_DEBUG,			    SPP_FMT "cisco invalid packet length: %d bytes\n",			    SPP_ARGS(ifp), m->m_pkthdr.len);		return;	}	h = mtod (m, struct cisco_packet*);	if (debug)		log(LOG_DEBUG,		    SPP_FMT "cisco input: %d bytes "		    "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n",		    SPP_ARGS(ifp), m->m_pkthdr.len,		    (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel,		    (u_int)h->time0, (u_int)h->time1);	switch (ntohl (h->type)) {

⌨️ 快捷键说明

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