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

📄 if_spppsubr.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
void sppp_attach (struct ifnet *ifp){	struct sppp *sp = (struct sppp*) ifp;	/* Initialize keepalive handler. */	if (! spppq)		timeout (sppp_keepalive, 0, hz * 10);	/* Insert new entry into the keepalive list. */	sp->pp_next = spppq;	spppq = sp;	sp->pp_if.if_type = IFT_PPP;	sp->pp_if.if_output = sppp_output;	sp->pp_fastq.ifq_maxlen = 32;	sp->pp_loopcnt = 0;	sp->pp_alivecnt = 0;	sp->pp_seq = 0;	sp->pp_rseq = 0;	sp->lcp.magic = 0;	sp->lcp.state = LCP_STATE_CLOSED;	sp->ipcp.state = IPCP_STATE_CLOSED;}void sppp_detach (struct ifnet *ifp){	struct sppp **q, *p, *sp = (struct sppp*) ifp;	/* 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);	UNTIMO (sp);}/* * Flush the interface output queue. */void sppp_flush (struct ifnet *ifp){	struct sppp *sp = (struct sppp*) ifp;	qflush (&sp->pp_if.if_snd);	qflush (&sp->pp_fastq);}/* * Check if the output queue is empty. */int sppp_isempty (struct ifnet *ifp){	struct sppp *sp = (struct sppp*) ifp;	int empty, s = splimp ();	empty = !sp->pp_fastq.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 = splimp ();	IF_DEQUEUE (&sp->pp_fastq, m);	if (! m)		IF_DEQUEUE (&sp->pp_if.if_snd, m);	splx (s);	return (m);}/* * Send keepalive packets, every 10 seconds. */void sppp_keepalive (void *dummy){	struct sppp *sp;	int s = splimp ();	for (sp=spppq; sp; sp=sp->pp_next) {		struct ifnet *ifp = &sp->pp_if;		/* Keepalive mode disabled or channel down? */		if (! (sp->pp_flags & PP_KEEPALIVE) ||		    ! (ifp->if_flags & IFF_RUNNING))			continue;		/* No keepalive in PPP mode if LCP not opened yet. */		if (! (sp->pp_flags & PP_CISCO) &&		    sp->lcp.state != LCP_STATE_OPENED)			continue;		if (sp->pp_alivecnt == MAXALIVECNT) {			/* No keepalive packets got.  Stop the interface. */			printf ("%s%d: down\n", ifp->if_name, ifp->if_unit);			if_down (ifp);			qflush (&sp->pp_fastq);			if (! (sp->pp_flags & PP_CISCO)) {				/* Shut down the PPP link. */				sp->lcp.state = LCP_STATE_CLOSED;				sp->ipcp.state = IPCP_STATE_CLOSED;				UNTIMO (sp);				/* Initiate negotiation. */				sppp_lcp_open (sp);			}		}		if (sp->pp_alivecnt <= MAXALIVECNT)			++sp->pp_alivecnt;		if (sp->pp_flags & PP_CISCO)			sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, ++sp->pp_seq,				sp->pp_rseq);		else if (sp->lcp.state == LCP_STATE_OPENED) {			long nmagic = htonl (sp->lcp.magic);			sp->lcp.echoid = ++sp->pp_seq;			sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REQ,				sp->lcp.echoid, 4, &nmagic);		}	}	splx (s);	timeout (sppp_keepalive, 0, hz * 10);}/* * Handle incoming PPP Link Control Protocol packets. */void sppp_lcp_input (struct sppp *sp, struct mbuf *m){	struct lcp_header *h;	struct ifnet *ifp = &sp->pp_if;	int len = m->m_pkthdr.len;	u_char *p, opt[6];	u_long rmagic;	if (len < 4) {		if (ifp->if_flags & IFF_DEBUG)			printf ("%s%d: invalid lcp packet length: %d bytes\n",				ifp->if_name, ifp->if_unit, len);		return;	}	h = mtod (m, struct lcp_header*);	if (ifp->if_flags & IFF_DEBUG) {		char state = '?';		switch (sp->lcp.state) {		case LCP_STATE_CLOSED:   state = 'C'; break;		case LCP_STATE_ACK_RCVD: state = 'R'; break;		case LCP_STATE_ACK_SENT: state = 'S'; break;		case LCP_STATE_OPENED:   state = 'O'; break;		}		printf ("%s%d: lcp input(%c): %d bytes <%s id=%xh len=%xh",			ifp->if_name, ifp->if_unit, state, len,			sppp_lcp_type_name (h->type), h->ident, ntohs (h->len));		if (len > 4)			sppp_print_bytes ((u_char*) (h+1), len-4);		printf (">\n");	}	if (len > ntohs (h->len))		len = ntohs (h->len);	switch (h->type) {	default:		/* Unknown packet type -- send Code-Reject packet. */		sppp_cp_send (sp, PPP_LCP, LCP_CODE_REJ, ++sp->pp_seq,			m->m_pkthdr.len, h);		break;	case LCP_CONF_REQ:		if (len < 4) {			if (ifp->if_flags & IFF_DEBUG)				printf ("%s%d: invalid lcp configure request packet length: %d bytes\n",					ifp->if_name, ifp->if_unit, len);			break;		}		if (len>4 && !sppp_lcp_conf_parse_options (sp, h, len, &rmagic))			goto badreq;		if (rmagic == sp->lcp.magic) {			/* Local and remote magics equal -- loopback? */			if (sp->pp_loopcnt >= MAXALIVECNT*5) {				printf ("%s%d: loopback\n",					ifp->if_name, ifp->if_unit);				sp->pp_loopcnt = 0;				if (ifp->if_flags & IFF_UP) {					if_down (ifp);					qflush (&sp->pp_fastq);				}			} else if (ifp->if_flags & IFF_DEBUG)				printf ("%s%d: conf req: magic glitch\n",					ifp->if_name, ifp->if_unit);			++sp->pp_loopcnt;			/* MUST send Conf-Nack packet. */			rmagic = ~sp->lcp.magic;			opt[0] = LCP_OPT_MAGIC;			opt[1] = sizeof (opt);			opt[2] = rmagic >> 24;			opt[3] = rmagic >> 16;			opt[4] = rmagic >> 8;			opt[5] = rmagic;			sppp_cp_send (sp, PPP_LCP, LCP_CONF_NAK,				h->ident, sizeof (opt), &opt);badreq:			switch (sp->lcp.state) {			case LCP_STATE_OPENED:				/* Initiate renegotiation. */				sppp_lcp_open (sp);				/* fall through... */			case LCP_STATE_ACK_SENT:				/* Go to closed state. */				sp->lcp.state = LCP_STATE_CLOSED;				sp->ipcp.state = IPCP_STATE_CLOSED;			}			break;				}				/* Send Configure-Ack packet. */				sp->pp_loopcnt = 0;				sppp_cp_send (sp, PPP_LCP, LCP_CONF_ACK,					h->ident, len-4, h+1);				/* Change the state. */		switch (sp->lcp.state) {		case LCP_STATE_CLOSED:			sp->lcp.state = LCP_STATE_ACK_SENT;			break;		case LCP_STATE_ACK_RCVD:					sp->lcp.state = LCP_STATE_OPENED;					sppp_ipcp_open (sp);			break;		case LCP_STATE_OPENED:			/* Remote magic changed -- close session. */			sp->lcp.state = LCP_STATE_CLOSED;			sp->ipcp.state = IPCP_STATE_CLOSED;			/* Initiate renegotiation. */			sppp_lcp_open (sp);			/* An ACK has already been sent. */			sp->lcp.state = LCP_STATE_ACK_SENT;			break;		}		break;	case LCP_CONF_ACK:		if (h->ident != sp->lcp.confid)			break;		UNTIMO (sp);		if (! (ifp->if_flags & IFF_UP) &&		    (ifp->if_flags & IFF_RUNNING)) {			/* Coming out of loopback mode. */			ifp->if_flags |= IFF_UP;			printf ("%s%d: up\n", ifp->if_name, ifp->if_unit);		}		switch (sp->lcp.state) {		case LCP_STATE_CLOSED:			sp->lcp.state = LCP_STATE_ACK_RCVD;			TIMO (sp, 5);			break;		case LCP_STATE_ACK_SENT:			sp->lcp.state = LCP_STATE_OPENED;			sppp_ipcp_open (sp);			break;		}		break;	case LCP_CONF_NAK:		if (h->ident != sp->lcp.confid)			break;		p = (u_char*) (h+1);		if (len>=10 && p[0] == LCP_OPT_MAGIC && p[1] >= 4) {			rmagic = (u_long)p[2] << 24 |				(u_long)p[3] << 16 | p[4] << 8 | p[5];			if (rmagic == ~sp->lcp.magic) {				if (ifp->if_flags & IFF_DEBUG)					printf ("%s%d: conf nak: magic glitch\n",						ifp->if_name, ifp->if_unit);				sp->lcp.magic += time.tv_sec + time.tv_usec;			} else				sp->lcp.magic = rmagic;			}		if (sp->lcp.state != LCP_STATE_ACK_SENT) {			/* Go to closed state. */			sp->lcp.state = LCP_STATE_CLOSED;			sp->ipcp.state = IPCP_STATE_CLOSED;		}		/* The link will be renegotiated after timeout,		 * to avoid endless req-nack loop. */		UNTIMO (sp);		TIMO (sp, 2);		break;	case LCP_CONF_REJ:		if (h->ident != sp->lcp.confid)			break;		UNTIMO (sp);		/* Initiate renegotiation. */		sppp_lcp_open (sp);		if (sp->lcp.state != LCP_STATE_ACK_SENT) {			/* Go to closed state. */			sp->lcp.state = LCP_STATE_CLOSED;			sp->ipcp.state = IPCP_STATE_CLOSED;		}		break;	case LCP_TERM_REQ:		UNTIMO (sp);		/* Send Terminate-Ack packet. */		sppp_cp_send (sp, PPP_LCP, LCP_TERM_ACK, h->ident, 0, 0);		/* Go to closed state. */		sp->lcp.state = LCP_STATE_CLOSED;		sp->ipcp.state = IPCP_STATE_CLOSED;			/* Initiate renegotiation. */			sppp_lcp_open (sp);		break;	case LCP_TERM_ACK:	case LCP_CODE_REJ:	case LCP_PROTO_REJ:		/* Ignore for now. */		break;	case LCP_DISC_REQ:		/* Discard the packet. */		break;	case LCP_ECHO_REQ:		if (sp->lcp.state != LCP_STATE_OPENED)			break;		if (len < 8) {			if (ifp->if_flags & IFF_DEBUG)				printf ("%s%d: invalid lcp echo request packet length: %d bytes\n",					ifp->if_name, ifp->if_unit, len);			break;		}		if (ntohl (*(long*)(h+1)) == sp->lcp.magic) {			/* Line loopback mode detected. */			printf ("%s%d: loopback\n", ifp->if_name, ifp->if_unit);			if_down (ifp);			qflush (&sp->pp_fastq);			/* Shut down the PPP link. */			sp->lcp.state = LCP_STATE_CLOSED;			sp->ipcp.state = IPCP_STATE_CLOSED;			UNTIMO (sp);			/* Initiate negotiation. */			sppp_lcp_open (sp);			break;		}		*(long*)(h+1) = htonl (sp->lcp.magic);		sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REPLY, h->ident, len-4, h+1);		break;	case LCP_ECHO_REPLY:		if (h->ident != sp->lcp.echoid)			break;		if (len < 8) {			if (ifp->if_flags & IFF_DEBUG)				printf ("%s%d: invalid lcp echo reply packet length: %d bytes\n",					ifp->if_name, ifp->if_unit, len);			break;		}		if (ntohl (*(long*)(h+1)) != sp->lcp.magic)		sp->pp_alivecnt = 0;		break;	}}/* * Handle incoming Cisco keepalive protocol packets. */void sppp_cisco_input (struct sppp *sp, struct mbuf *m){	struct cisco_packet *h;	struct ifaddr *ifa;	struct ifnet *ifp = &sp->pp_if;	if (m->m_pkthdr.len != CISCO_PACKET_LEN) {		if (ifp->if_flags & IFF_DEBUG)			printf ("%s%d: invalid cisco packet length: %d bytes\n",				ifp->if_name, ifp->if_unit, m->m_pkthdr.len);		return;	}	h = mtod (m, struct cisco_packet*);	if (ifp->if_flags & IFF_DEBUG)		printf ("%s%d: cisco input: %d bytes <%lxh %lxh %lxh %xh %xh-%xh>\n",			ifp->if_name, ifp->if_unit, m->m_pkthdr.len,			ntohl (h->type), h->par1, h->par2, h->rel,			h->time0, h->time1);	switch (ntohl (h->type)) {	default:		if (ifp->if_flags & IFF_DEBUG)			printf ("%s%d: unknown cisco packet type: 0x%lx\n",				ifp->if_name, ifp->if_unit, ntohl (h->type));		break;	case CISCO_ADDR_REPLY:		/* Reply on address request, ignore */		break;	case CISCO_KEEPALIVE_REQ:		sp->pp_alivecnt = 0;		sp->pp_rseq = ntohl (h->par1);		if (sp->pp_seq == sp->pp_rseq) {			/* Local and remote sequence numbers are equal.			 * Probably, the line is in loopback mode. */			if (sp->pp_loopcnt >= MAXALIVECNT) {				printf ("%s%d: loopback\n",					ifp->if_name, ifp->if_unit);				sp->pp_loopcnt = 0;				if (ifp->if_flags & IFF_UP) {					if_down (ifp);					qflush (&sp->pp_fastq);				}			}			++sp->pp_loopcnt;			/* Generate new local sequence number */			sp->pp_seq ^= time.tv_sec ^ time.tv_usec;			break;		}			sp->pp_loopcnt = 0;		if (! (ifp->if_flags & IFF_UP) &&		    (ifp->if_flags & IFF_RUNNING)) {			ifp->if_flags |= IFF_UP;			printf ("%s%d: up\n", ifp->if_name, ifp->if_unit);		}		break;	case CISCO_ADDR_REQ:		for (ifa=ifp->if_addrlist; ifa; ifa=ifa->ifa_next)			if (ifa->ifa_addr->sa_family == AF_INET)				break;		if (! ifa) {			if (ifp->if_flags & IFF_DEBUG)				printf ("%s%d: unknown address for cisco request\n",					ifp->if_name, ifp->if_unit);			return;		}		sppp_cisco_send (sp, CISCO_ADDR_REPLY,			ntohl (((struct sockaddr_in*)ifa->ifa_addr)->sin_addr.s_addr),			ntohl (((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr.s_addr));		break;	}}/* * Send PPP LCP packet. */void sppp_cp_send (struct sppp *sp, u_short proto, u_char type,	u_char ident, u_short len, void *data){

⌨️ 快捷键说明

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