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

📄 if_spppsubr.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	struct ppp_header *h;	struct lcp_header *lh;	struct mbuf *m;	struct ifnet *ifp = &sp->pp_if;	if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN)		len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN;	MGETHDR (m, M_DONTWAIT, MT_DATA);	if (! m)		return;	m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len;	m->m_pkthdr.rcvif = 0;	h = mtod (m, struct ppp_header*);	h->address = PPP_ALLSTATIONS;        /* broadcast address */	h->control = PPP_UI;                 /* Unnumbered Info */	h->protocol = htons (proto);         /* Link Control Protocol */	lh = (struct lcp_header*) (h + 1);	lh->type = type;	lh->ident = ident;	lh->len = htons (LCP_HEADER_LEN + len);	if (len)		bcopy (data, lh+1, len);	if (ifp->if_flags & IFF_DEBUG) {		printf ("%s%d: %s output <%s id=%xh len=%xh",			ifp->if_name, ifp->if_unit,			proto==PPP_LCP ? "lcp" : "ipcp",			proto==PPP_LCP ? sppp_lcp_type_name (lh->type) :			sppp_ipcp_type_name (lh->type), lh->ident,			ntohs (lh->len));		if (len)			sppp_print_bytes ((u_char*) (lh+1), len);		printf (">\n");	}	if (IF_QFULL (&sp->pp_fastq)) {		IF_DROP (&ifp->if_snd);		m_freem (m);	} else		IF_ENQUEUE (&sp->pp_fastq, m);	if (! (ifp->if_flags & IFF_OACTIVE))		(*ifp->if_start) (ifp);	ifp->if_obytes += m->m_pkthdr.len + 3;}/* * Send Cisco keepalive packet. */void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2){	struct ppp_header *h;	struct cisco_packet *ch;	struct mbuf *m;	struct ifnet *ifp = &sp->pp_if;	u_long t = (time.tv_sec - boottime.tv_sec) * 1000;	MGETHDR (m, M_DONTWAIT, MT_DATA);	if (! m)		return;	m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN;	m->m_pkthdr.rcvif = 0;	h = mtod (m, struct ppp_header*);	h->address = CISCO_MULTICAST;	h->control = 0;	h->protocol = htons (CISCO_KEEPALIVE);	ch = (struct cisco_packet*) (h + 1);	ch->type = htonl (type);	ch->par1 = htonl (par1);	ch->par2 = htonl (par2);	ch->rel = -1;	ch->time0 = htons ((u_short) (t >> 16));	ch->time1 = htons ((u_short) t);	if (ifp->if_flags & IFF_DEBUG)		printf ("%s%d: cisco output: <%lxh %lxh %lxh %xh %xh-%xh>\n",			ifp->if_name, ifp->if_unit, ntohl (ch->type), ch->par1,			ch->par2, ch->rel, ch->time0, ch->time1);	if (IF_QFULL (&sp->pp_fastq)) {		IF_DROP (&ifp->if_snd);		m_freem (m);	} else		IF_ENQUEUE (&sp->pp_fastq, m);	if (! (ifp->if_flags & IFF_OACTIVE))		(*ifp->if_start) (ifp);	ifp->if_obytes += m->m_pkthdr.len + 3;}/* * Process an ioctl request.  Called on low priority level. */int sppp_ioctl (struct ifnet *ifp, int cmd, void *data){	struct ifreq *ifr = (struct ifreq*) data;	struct sppp *sp = (struct sppp*) ifp;	int s, going_up, going_down;	switch (cmd) {	default:		return (EINVAL);	case SIOCAIFADDR:	case SIOCSIFDSTADDR:		break;	case SIOCSIFADDR:		ifp->if_flags |= IFF_UP;		/* fall through... */	case SIOCSIFFLAGS:		s = splimp ();		going_up   = (ifp->if_flags & IFF_UP) &&			     ! (ifp->if_flags & IFF_RUNNING);		going_down = ! (ifp->if_flags & IFF_UP) &&			      (ifp->if_flags & IFF_RUNNING);		if (going_up || going_down) {			/* Shut down the PPP link. */			ifp->if_flags &= ~IFF_RUNNING;			sp->lcp.state = LCP_STATE_CLOSED;			sp->ipcp.state = IPCP_STATE_CLOSED;			UNTIMO (sp);		}		if (going_up) {			/* Interface is starting -- initiate negotiation. */			ifp->if_flags |= IFF_RUNNING;			if (!(sp->pp_flags & PP_CISCO))				sppp_lcp_open (sp);		}		splx (s);		break;#ifdef SIOCSIFMTU#ifndef ifr_mtu#define ifr_mtu ifr_metric#endif	case SIOCSIFMTU:		if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > PP_MTU)			return (EINVAL);		ifp->if_mtu = ifr->ifr_mtu;		break;#endif#ifdef SLIOCSETMTU	case SLIOCSETMTU:		if (*(short*)data < 128 || *(short*)data > PP_MTU)			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#ifdef MULTICAST	case SIOCADDMULTI:	case SIOCDELMULTI:		break;#endif	}	return (0);}/* * Analyze the LCP Configure-Request options list * for the presence of unknown options. * If the request contains unknown options, build and * send Configure-reject packet, containing only unknown options. */int sppp_lcp_conf_parse_options (struct sppp *sp, struct lcp_header *h,	int len, u_long *magic){	u_char *buf, *r, *p;	int rlen;	len -= 4;	buf = r = malloc (len, M_TEMP, M_NOWAIT);	if (! buf)		return (0);	p = (void*) (h+1);	for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) {		switch (*p) {		case LCP_OPT_MAGIC:			/* Magic number -- extract. */			if (len >= 6 && p[1] == 6) {				*magic = (u_long)p[2] << 24 |					(u_long)p[3] << 16 | p[4] << 8 | p[5];				continue;			}			break;		case LCP_OPT_ASYNC_MAP:			/* Async control character map -- check to be zero. */			if (len >= 6 && p[1] == 6 && ! p[2] && ! p[3] &&			    ! p[4] && ! p[5])				continue;			break;		case LCP_OPT_MRU:			/* Maximum receive unit -- always OK. */			continue;		default:			/* Others not supported. */			break;		}		/* Add the option to rejected list. */			bcopy (p, r, p[1]);			r += p[1];		rlen += p[1];		}	if (rlen)	sppp_cp_send (sp, PPP_LCP, LCP_CONF_REJ, h->ident, rlen, buf);	free (buf, M_TEMP);	return (rlen == 0);}void sppp_ipcp_input (struct sppp *sp, struct mbuf *m){	struct lcp_header *h;	struct ifnet *ifp = &sp->pp_if;	int len = m->m_pkthdr.len;	if (len < 4) {		/* if (ifp->if_flags & IFF_DEBUG) */			printf ("%s%d: invalid ipcp 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) {		printf ("%s%d: ipcp input: %d bytes <%s id=%xh len=%xh",			ifp->if_name, ifp->if_unit, len,			sppp_ipcp_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_IPCP, IPCP_CODE_REJ, ++sp->pp_seq, len, h);		break;	case IPCP_CONF_REQ:		if (len < 4) {			if (ifp->if_flags & IFF_DEBUG)				printf ("%s%d: invalid ipcp configure request packet length: %d bytes\n",					ifp->if_name, ifp->if_unit, len);			return;		}		if (len > 4) {			sppp_cp_send (sp, PPP_IPCP, LCP_CONF_REJ, h->ident,				len-4, h+1);			switch (sp->ipcp.state) {			case IPCP_STATE_OPENED:				/* Initiate renegotiation. */				sppp_ipcp_open (sp);				/* fall through... */			case IPCP_STATE_ACK_SENT:				/* Go to closed state. */				sp->ipcp.state = IPCP_STATE_CLOSED;			}		} else {			/* Send Configure-Ack packet. */			sppp_cp_send (sp, PPP_IPCP, IPCP_CONF_ACK, h->ident,				0, 0);			/* Change the state. */			if (sp->ipcp.state == IPCP_STATE_ACK_RCVD)				sp->ipcp.state = IPCP_STATE_OPENED;			else				sp->ipcp.state = IPCP_STATE_ACK_SENT;		}		break;	case IPCP_CONF_ACK:		if (h->ident != sp->ipcp.confid)			break;		UNTIMO (sp);		switch (sp->ipcp.state) {		case IPCP_STATE_CLOSED:			sp->ipcp.state = IPCP_STATE_ACK_RCVD;			TIMO (sp, 5);			break;		case IPCP_STATE_ACK_SENT:			sp->ipcp.state = IPCP_STATE_OPENED;			break;		}		break;	case IPCP_CONF_NAK:	case IPCP_CONF_REJ:		if (h->ident != sp->ipcp.confid)			break;		UNTIMO (sp);			/* Initiate renegotiation. */			sppp_ipcp_open (sp);		if (sp->ipcp.state != IPCP_STATE_ACK_SENT)			/* Go to closed state. */			sp->ipcp.state = IPCP_STATE_CLOSED;		break;	case IPCP_TERM_REQ:		/* Send Terminate-Ack packet. */		sppp_cp_send (sp, PPP_IPCP, IPCP_TERM_ACK, h->ident, 0, 0);		/* Go to closed state. */		sp->ipcp.state = IPCP_STATE_CLOSED;			/* Initiate renegotiation. */			sppp_ipcp_open (sp);		break;	case IPCP_TERM_ACK:		/* Ignore for now. */	case IPCP_CODE_REJ:		/* Ignore for now. */		break;	}}void sppp_lcp_open (struct sppp *sp){	char opt[6];	if (! sp->lcp.magic)	sp->lcp.magic = time.tv_sec + time.tv_usec;	opt[0] = LCP_OPT_MAGIC;	opt[1] = sizeof (opt);	opt[2] = sp->lcp.magic >> 24;	opt[3] = sp->lcp.magic >> 16;	opt[4] = sp->lcp.magic >> 8;	opt[5] = sp->lcp.magic;	sp->lcp.confid = ++sp->pp_seq;	sppp_cp_send (sp, PPP_LCP, LCP_CONF_REQ, sp->lcp.confid,		sizeof (opt), &opt);	TIMO (sp, 2);}void sppp_ipcp_open (struct sppp *sp){	sp->ipcp.confid = ++sp->pp_seq;	sppp_cp_send (sp, PPP_IPCP, IPCP_CONF_REQ, sp->ipcp.confid, 0, 0);	TIMO (sp, 2);}/* * Process PPP control protocol timeouts. */void sppp_cp_timeout (void *arg){	struct sppp *sp = (struct sppp*) arg;	int s = splimp ();	sp->pp_flags &= ~PP_TIMO;	if (! (sp->pp_if.if_flags & IFF_RUNNING) || (sp->pp_flags & PP_CISCO)) {		splx (s);		return;	}	switch (sp->lcp.state) {	case LCP_STATE_CLOSED:		/* No ACK for Configure-Request, retry. */		sppp_lcp_open (sp);		break;	case LCP_STATE_ACK_RCVD:		/* ACK got, but no Configure-Request for peer, retry. */		sppp_lcp_open (sp);		sp->lcp.state = LCP_STATE_CLOSED;		break;	case LCP_STATE_ACK_SENT:		/* ACK sent but no ACK for Configure-Request, retry. */		sppp_lcp_open (sp);		break;	case LCP_STATE_OPENED:		/* LCP is already OK, try IPCP. */		switch (sp->ipcp.state) {		case IPCP_STATE_CLOSED:			/* No ACK for Configure-Request, retry. */			sppp_ipcp_open (sp);			break;		case IPCP_STATE_ACK_RCVD:			/* ACK got, but no Configure-Request for peer, retry. */			sppp_ipcp_open (sp);			sp->ipcp.state = IPCP_STATE_CLOSED;			break;		case IPCP_STATE_ACK_SENT:			/* ACK sent but no ACK for Configure-Request, retry. */			sppp_ipcp_open (sp);			break;		case IPCP_STATE_OPENED:			/* IPCP is OK. */			break;		}		break;	}	splx (s);}char *sppp_lcp_type_name (u_char type){	static char buf [8];	switch (type) {	case LCP_CONF_REQ:   return ("conf-req");	case LCP_CONF_ACK:   return ("conf-ack");	case LCP_CONF_NAK:   return ("conf-nack");	case LCP_CONF_REJ:   return ("conf-rej");	case LCP_TERM_REQ:   return ("term-req");	case LCP_TERM_ACK:   return ("term-ack");	case LCP_CODE_REJ:   return ("code-rej");	case LCP_PROTO_REJ:  return ("proto-rej");	case LCP_ECHO_REQ:   return ("echo-req");	case LCP_ECHO_REPLY: return ("echo-reply");	case LCP_DISC_REQ:   return ("discard-req");	}	sprintf (buf, "%xh", type);	return (buf);}char *sppp_ipcp_type_name (u_char type){	static char buf [8];	switch (type) {	case IPCP_CONF_REQ:   return ("conf-req");	case IPCP_CONF_ACK:   return ("conf-ack");	case IPCP_CONF_NAK:   return ("conf-nack");	case IPCP_CONF_REJ:   return ("conf-rej");	case IPCP_TERM_REQ:   return ("term-req");	case IPCP_TERM_ACK:   return ("term-ack");	case IPCP_CODE_REJ:   return ("code-rej");	}	sprintf (buf, "%xh", type);	return (buf);}void sppp_print_bytes (u_char *p, u_short len){	printf (" %x", *p++);	while (--len > 0)		printf ("-%x", *p++);}

⌨️ 快捷键说明

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