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

📄 if_spppsubr.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Synchronous PPP/Cisco link level subroutines. * Keepalive protocol implemented in both Cisco and PPP modes. * * Copyright (C) 1994 Cronyx Ltd. * Author: Serge Vakulenko, <vak@zebub.msk.su> * * This software is distributed with NO WARRANTIES, not even the implied * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * Authors grant any other persons or organisations permission to use * or modify this software as long as this message is kept with the software, * all derivative works or modified versions. * * Version 1.9, Wed Oct  4 18:58:15 MSK 1995 */#undef DEBUG#include <sys/param.h>#include <sys/systm.h>#include <sys/kernel.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <sys/mbuf.h>#include <net/if.h>#include <net/netisr.h>#include <net/if_types.h>#ifdef INET#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/in_var.h>#include <netinet/ip.h>#include <netinet/tcp.h>#include <netinet/if_ether.h>#endif#ifdef NS#include <netns/ns.h>#include <netns/ns_if.h>#endif#ifdef ISO#include <netiso/argo_debug.h>#include <netiso/iso.h>#include <netiso/iso_var.h>#include <netiso/iso_snpac.h>#endif#include <net/if_sppp.h>#ifdef DEBUG#define print(s)        printf s#else#define print(s)        {/*void*/}#endif#define MAXALIVECNT     3               /* max. alive packets */#define PPP_ALLSTATIONS 0xff            /* All-Stations broadcast address */#define PPP_UI          0x03            /* Unnumbered Information */#define PPP_IP          0x0021          /* Internet Protocol */#define PPP_ISO         0x0023          /* ISO OSI Protocol */#define PPP_XNS         0x0025          /* Xerox NS Protocol */#define PPP_LCP         0xc021          /* Link Control Protocol */#define PPP_IPCP        0x8021          /* Internet Protocol Control Protocol */#define LCP_CONF_REQ    1               /* PPP LCP configure request */#define LCP_CONF_ACK    2               /* PPP LCP configure acknowledge */#define LCP_CONF_NAK    3               /* PPP LCP configure negative ack */#define LCP_CONF_REJ    4               /* PPP LCP configure reject */#define LCP_TERM_REQ    5               /* PPP LCP terminate request */#define LCP_TERM_ACK    6               /* PPP LCP terminate acknowledge */#define LCP_CODE_REJ    7               /* PPP LCP code reject */#define LCP_PROTO_REJ   8               /* PPP LCP protocol reject */#define LCP_ECHO_REQ    9               /* PPP LCP echo request */#define LCP_ECHO_REPLY  10              /* PPP LCP echo reply */#define LCP_DISC_REQ    11              /* PPP LCP discard request */#define LCP_OPT_MRU             1       /* maximum receive unit */#define LCP_OPT_ASYNC_MAP       2       /* async control character map */#define LCP_OPT_AUTH_PROTO      3       /* authentication protocol */#define LCP_OPT_QUAL_PROTO      4       /* quality protocol */#define LCP_OPT_MAGIC           5       /* magic number */#define LCP_OPT_RESERVED        6       /* reserved */#define LCP_OPT_PROTO_COMP      7       /* protocol field compression */#define LCP_OPT_ADDR_COMP       8       /* address/control field compression */#define IPCP_CONF_REQ   LCP_CONF_REQ    /* PPP IPCP configure request */#define IPCP_CONF_ACK   LCP_CONF_ACK    /* PPP IPCP configure acknowledge */#define IPCP_CONF_NAK   LCP_CONF_NAK    /* PPP IPCP configure negative ack */#define IPCP_CONF_REJ   LCP_CONF_REJ    /* PPP IPCP configure reject */#define IPCP_TERM_REQ   LCP_TERM_REQ    /* PPP IPCP terminate request */#define IPCP_TERM_ACK   LCP_TERM_ACK    /* PPP IPCP terminate acknowledge */#define IPCP_CODE_REJ   LCP_CODE_REJ    /* PPP IPCP code reject */#define CISCO_MULTICAST         0x8f    /* Cisco multicast address */#define CISCO_UNICAST           0x0f    /* Cisco unicast address */#define CISCO_KEEPALIVE         0x8035  /* Cisco keepalive protocol */#define CISCO_ADDR_REQ          0       /* Cisco address request */#define CISCO_ADDR_REPLY        1       /* Cisco address reply */#define CISCO_KEEPALIVE_REQ     2       /* Cisco keepalive request */struct ppp_header {	u_char address;	u_char control;	u_short protocol;};#define PPP_HEADER_LEN          sizeof (struct ppp_header)struct lcp_header {	u_char type;	u_char ident;	u_short len;};#define LCP_HEADER_LEN          sizeof (struct lcp_header)struct cisco_packet {	u_long type;	u_long par1;	u_long par2;	u_short rel;	u_short time0;	u_short time1;};#define CISCO_PACKET_LEN 18struct sppp *spppq;/* * The following disgusting hack gets around the problem that IP TOS * can't be set yet.  We want to put "interactive" traffic on a high * priority queue.  To decide if traffic is interactive, we check that * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. */static u_short interactive_ports[8] = {	0,	513,	0,	0,	0,	21,	0,	23,};#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p))/* * Timeout routine activation macros. */#define TIMO(p,s) if (! ((p)->pp_flags & PP_TIMO)) { \			timeout (sppp_cp_timeout, (void*) (p), (s)*hz); \			(p)->pp_flags |= PP_TIMO; }#define UNTIMO(p) if ((p)->pp_flags & PP_TIMO) { \			untimeout (sppp_cp_timeout, (void*) (p)); \			(p)->pp_flags &= ~PP_TIMO; }void sppp_keepalive (void *dummy);void sppp_cp_send (struct sppp *sp, u_short proto, u_char type,	u_char ident, u_short len, void *data);void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2);void sppp_lcp_input (struct sppp *sp, struct mbuf *m);void sppp_cisco_input (struct sppp *sp, struct mbuf *m);void sppp_ipcp_input (struct sppp *sp, struct mbuf *m);void sppp_lcp_open (struct sppp *sp);void sppp_ipcp_open (struct sppp *sp);int sppp_lcp_conf_parse_options (struct sppp *sp, struct lcp_header *h,	int len, u_long *magic);void sppp_cp_timeout (void *arg);char *sppp_lcp_type_name (u_char type);char *sppp_ipcp_type_name (u_char type);void sppp_print_bytes (u_char *p, u_short len);/* * Flush interface queue. */static void qflush (struct ifqueue *ifq){	struct mbuf *m, *n;	n = ifq->ifq_head;	while ((m = n)) {		n = m->m_act;		m_freem (m);	}	ifq->ifq_head = 0;	ifq->ifq_tail = 0;	ifq->ifq_len = 0;}/* * Process the received packet. */void sppp_input (struct ifnet *ifp, struct mbuf *m){	struct ppp_header *h;	struct sppp *sp = (struct sppp*) ifp;	struct ifqueue *inq = 0;	int s;	if (ifp->if_flags & IFF_UP)		/* Count received bytes, add FCS and one flag */		ifp->if_ibytes += m->m_pkthdr.len + 3;	if (m->m_pkthdr.len <= PPP_HEADER_LEN) {		/* Too small packet, drop it. */		if (ifp->if_flags & IFF_DEBUG)			printf ("%s%d: input packet is too small, %d bytes\n",				ifp->if_name, ifp->if_unit, m->m_pkthdr.len);drop:           ++ifp->if_iqdrops;		m_freem (m);		return;	}	/* Get PPP header. */	h = mtod (m, struct ppp_header*);	m_adj (m, PPP_HEADER_LEN);	switch (h->address) {	default:        /* Invalid PPP packet. */invalid:        if (ifp->if_flags & IFF_DEBUG)			printf ("%s%d: invalid input packet <0x%x 0x%x 0x%x>\n",				ifp->if_name, ifp->if_unit,				h->address, h->control, ntohs (h->protocol));		goto drop;	case PPP_ALLSTATIONS:		if (h->control != PPP_UI)			goto invalid;		if (sp->pp_flags & PP_CISCO) {			if (ifp->if_flags & IFF_DEBUG)				printf ("%s%d: PPP packet in Cisco mode <0x%x 0x%x 0x%x>\n",					ifp->if_name, ifp->if_unit,					h->address, h->control, ntohs (h->protocol));			goto drop;		}		switch (ntohs (h->protocol)) {		default:			if (sp->lcp.state == LCP_STATE_OPENED)				sppp_cp_send (sp, PPP_LCP, LCP_PROTO_REJ,					++sp->pp_seq, m->m_pkthdr.len + 2,					&h->protocol);			if (ifp->if_flags & IFF_DEBUG)				printf ("%s%d: invalid input protocol <0x%x 0x%x 0x%x>\n",					ifp->if_name, ifp->if_unit,					h->address, h->control, ntohs (h->protocol));			++ifp->if_noproto;			goto drop;		case PPP_LCP:			sppp_lcp_input ((struct sppp*) ifp, m);			m_freem (m);			return;#ifdef INET		case PPP_IPCP:			if (sp->lcp.state == LCP_STATE_OPENED)				sppp_ipcp_input ((struct sppp*) ifp, m);			m_freem (m);			return;		case PPP_IP:			if (sp->ipcp.state == IPCP_STATE_OPENED) {				schednetisr (NETISR_IP);				inq = &ipintrq;			}			break;#endif#ifdef NS		case PPP_XNS:			/* XNS IDPCP not implemented yet */			if (sp->lcp.state == LCP_STATE_OPENED) {				schednetisr (NETISR_NS);				inq = &nsintrq;			}			break;#endif#ifdef ISO		case PPP_ISO:			/* OSI NLCP not implemented yet */			if (sp->lcp.state == LCP_STATE_OPENED) {				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 (ifp->if_flags & IFF_DEBUG)				printf ("%s%d: Cisco packet in PPP mode <0x%x 0x%x 0x%x>\n",					ifp->if_name, ifp->if_unit,					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 NS		case ETHERTYPE_NS:			schednetisr (NETISR_NS);			inq = &nsintrq;			break;#endif		}		break;	}	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 (ifp->if_flags & IFF_DEBUG)			printf ("%s%d: protocol queue overflow\n",				ifp->if_name, ifp->if_unit);		goto drop;	}	IF_ENQUEUE (inq, m);	splx (s);}/* * Enqueue transmit packet. */int sppp_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 = splimp ();	if (! (ifp->if_flags & IFF_UP) || ! (ifp->if_flags & IFF_RUNNING)) {		m_freem (m);		splx (s);		return (ENETDOWN);	}	ifq = &ifp->if_snd;#ifdef INET	/*	 * Put low delay, telnet, rlogin and ftp control packets	 * in front of the queue.	 */	{	struct ip *ip = mtod (m, struct ip*);	struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl);	if (! IF_QFULL (&sp->pp_fastq) && ((ip->ip_tos & IPTOS_LOWDELAY) ||	    ip->ip_p == IPPROTO_TCP &&	    m->m_len >= sizeof (struct ip) + sizeof (struct tcphdr) &&	    (INTERACTIVE (ntohs (tcp->th_sport)) ||	    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 (ifp->if_flags & IFF_DEBUG)			printf ("%s%d: no memory for transmit header\n",				ifp->if_name, ifp->if_unit);		splx (s);		return (ENOBUFS);	}	h = mtod (m, struct ppp_header*);	if (sp->pp_flags & PP_CISCO) {		h->address = CISCO_MULTICAST;        /* broadcast 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 if (sp->ipcp.state == IPCP_STATE_OPENED)			h->protocol = htons (PPP_IP);		else {			m_freem (m);			splx (s);			return (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 ISO	case AF_ISO:    /* ISO OSI Protocol */		if (sp->pp_flags & PP_CISCO)			goto nosupport;		h->protocol = htons (PPP_ISO);		break;#endifnosupport:	default:		m_freem (m);		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);		splx (s);		return (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);}

⌨️ 快捷键说明

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