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

📄 if_spppsubr.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Synchronous PPP/Cisco link level subroutines. * Keepalive protocol implemented in both Cisco and PPP modes. * * Copyright (C) 1994-1996 Cronyx Engineering Ltd. * Author: Serge Vakulenko, <vak@cronyx.ru> * * Heavily revamped to conform to RFC 1661. * Copyright (C) 1997, Joerg Wunsch. * * 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. * * From: Version 2.4, Thu Apr 30 17:17:21 MSD 1997 * * $Id: if_spppsubr.c,v 1.52 1998/12/27 21:30:44 phk Exp $ */#include <sys/param.h>#if defined(__FreeBSD__) && __FreeBSD__ >= 3#include "opt_inet.h"#include "opt_ipx.h"#endif#ifdef NetBSD1_3#  if NetBSD1_3 > 6#      include "opt_inet.h"#      include "opt_iso.h"#  endif#endif#include <sys/systm.h>#include <sys/kernel.h>#include <sys/sockio.h>#include <sys/socket.h>#include <sys/syslog.h>#if defined(__FreeBSD__) && __FreeBSD__ >= 3#include <machine/random.h>#endif#include <sys/malloc.h>#include <sys/mbuf.h>#if defined (__OpenBSD__)#include <sys/md5k.h>#else#include <sys/md5.h>#endif#include <net/if.h>#include <net/netisr.h>#include <net/if_types.h>#include <net/route.h>#if defined(__FreeBSD__) && __FreeBSD__ >= 3#include <machine/random.h>#endif#if defined (__NetBSD__) || defined (__OpenBSD__)#include <machine/cpu.h> /* XXX for softnet */#endif#include <machine/stdarg.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># if defined (__FreeBSD__) || defined (__OpenBSD__)#  include <netinet/if_ether.h># else#  include <net/ethertypes.h># endif#else# error Huh? sppp without INET?#endif#ifdef IPX#include <netipx/ipx.h>#include <netipx/ipx_if.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>#if defined(__FreeBSD__) && __FreeBSD__ >= 3# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg, handle)# define TIMEOUT(fun, arg1, arg2, handle) handle = timeout(fun, arg1, arg2)# define IOCTL_CMD_T	u_long#else# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg)# define TIMEOUT(fun, arg1, arg2, handle) timeout(fun, arg1, arg2)# define IOCTL_CMD_T	int#endif#define MAXALIVECNT     3               /* max. alive packets *//* * Interface flags that can be set in an ifconfig command. * * Setting link0 will make the link passive, i.e. it will be marked * as being administrative openable, but won't be opened to begin * with.  Incoming calls will be answered, or subsequent calls with * -link1 will cause the administrative open of the LCP layer. * * Setting link1 will cause the link to auto-dial only as packets * arrive to be sent. * * Setting IFF_DEBUG will syslog the option negotiation and state * transitions at level kern.debug.  Note: all logs consistently look * like * *   <if-name><unit>: <proto-name> <additional info...> * * with <if-name><unit> being something like "bppp0", and <proto-name> * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc. */#define IFF_PASSIVE	IFF_LINK0	/* wait passively for connection */#define IFF_AUTO	IFF_LINK1	/* auto-dial on output */#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_IPX		0x002b		/* Novell IPX Protocol */#define PPP_LCP		0xc021		/* Link Control Protocol */#define PPP_PAP		0xc023		/* Password Authentication Protocol */#define PPP_CHAP	0xc223		/* Challenge-Handshake Auth Protocol */#define PPP_IPCP	0x8021		/* Internet Protocol Control Protocol */#define CONF_REQ	1		/* PPP configure request */#define CONF_ACK	2		/* PPP configure acknowledge */#define CONF_NAK	3		/* PPP configure negative ack */#define CONF_REJ	4		/* PPP configure reject */#define TERM_REQ	5		/* PPP terminate request */#define TERM_ACK	6		/* PPP terminate acknowledge */#define CODE_REJ	7		/* PPP code reject */#define PROTO_REJ	8		/* PPP protocol reject */#define ECHO_REQ	9		/* PPP echo request */#define ECHO_REPLY	10		/* PPP echo reply */#define DISC_REQ	11		/* PPP 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_OPT_ADDRESSES	1	/* both IP addresses; deprecated */#define IPCP_OPT_COMPRESSION	2	/* IP compression protocol (VJ) */#define IPCP_OPT_ADDRESS	3	/* local IP address */#define PAP_REQ			1	/* PAP name/password request */#define PAP_ACK			2	/* PAP acknowledge */#define PAP_NAK			3	/* PAP fail */#define CHAP_CHALLENGE		1	/* CHAP challenge request */#define CHAP_RESPONSE		2	/* CHAP challenge response */#define CHAP_SUCCESS		3	/* CHAP response ok */#define CHAP_FAILURE		4	/* CHAP response failed */#define CHAP_MD5		5	/* hash algorithm - MD5 */#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 *//* states are named and numbered according to RFC 1661 */#define STATE_INITIAL	0#define STATE_STARTING	1#define STATE_CLOSED	2#define STATE_STOPPED	3#define STATE_CLOSING	4#define STATE_STOPPING	5#define STATE_REQ_SENT	6#define STATE_ACK_RCVD	7#define STATE_ACK_SENT	8#define STATE_OPENED	9struct 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 18/* * We follow the spelling and capitalization of RFC 1661 here, to make * it easier comparing with the standard.  Please refer to this RFC in * case you can't make sense out of these abbreviation; it will also * explain the semantics related to the various events and actions. */struct cp {	u_short	proto;		/* PPP control protocol number */	u_char protoidx;	/* index into state table in struct sppp */	u_char flags;#define CP_LCP		0x01	/* this is the LCP */#define CP_AUTH		0x02	/* this is an authentication protocol */#define CP_NCP		0x04	/* this is a NCP */#define CP_QUAL		0x08	/* this is a quality reporting protocol */	const char *name;	/* name of this control protocol */	/* event handlers */	void	(*Up)(struct sppp *sp);	void	(*Down)(struct sppp *sp);	void	(*Open)(struct sppp *sp);	void	(*Close)(struct sppp *sp);	void	(*TO)(void *sp);	int	(*RCR)(struct sppp *sp, struct lcp_header *h, int len);	void	(*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len);	void	(*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len);	/* actions */	void	(*tlu)(struct sppp *sp);	void	(*tld)(struct sppp *sp);	void	(*tls)(struct sppp *sp);	void	(*tlf)(struct sppp *sp);	void	(*scr)(struct sppp *sp);};static struct sppp *spppq;#if defined(__FreeBSD__) && __FreeBSD__ >= 3static struct callout_handle keepalive_ch;#endif#if defined(__FreeBSD__) && __FreeBSD__ >= 3#define	SPP_FMT		"%s%d: "#define	SPP_ARGS(ifp)	(ifp)->if_name, (ifp)->if_unit#else#define	SPP_FMT		"%s: "#define	SPP_ARGS(ifp)	(ifp)->if_xname#endif/* * 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. * * XXX is this really still necessary?  - joerg - */static u_short interactive_ports[8] = {	0,	513,	0,	0,	0,	21,	0,	23,};#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p))/* almost every function needs these */#define STDDCL							\	struct ifnet *ifp = &sp->pp_if;				\	int debug = ifp->if_flags & IFF_DEBUGstatic int sppp_output(struct ifnet *ifp, struct mbuf *m,		       struct sockaddr *dst, struct rtentry *rt);static void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2);static void sppp_cisco_input(struct sppp *sp, struct mbuf *m);static void sppp_cp_input(const struct cp *cp, struct sppp *sp,			  struct mbuf *m);static void sppp_cp_send(struct sppp *sp, u_short proto, u_char type,			 u_char ident, u_short len, void *data);/* static void sppp_cp_timeout(void *arg); */static void sppp_cp_change_state(const struct cp *cp, struct sppp *sp,				 int newstate);static void sppp_auth_send(const struct cp *cp,			   struct sppp *sp, unsigned int type, unsigned int id,			   ...);static void sppp_up_event(const struct cp *cp, struct sppp *sp);static void sppp_down_event(const struct cp *cp, struct sppp *sp);static void sppp_open_event(const struct cp *cp, struct sppp *sp);static void sppp_close_event(const struct cp *cp, struct sppp *sp);static void sppp_to_event(const struct cp *cp, struct sppp *sp);static void sppp_null(struct sppp *sp);static void sppp_lcp_init(struct sppp *sp);static void sppp_lcp_up(struct sppp *sp);static void sppp_lcp_down(struct sppp *sp);static void sppp_lcp_open(struct sppp *sp);static void sppp_lcp_close(struct sppp *sp);static void sppp_lcp_TO(void *sp);static int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len);static void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len);static void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len);static void sppp_lcp_tlu(struct sppp *sp);static void sppp_lcp_tld(struct sppp *sp);static void sppp_lcp_tls(struct sppp *sp);static void sppp_lcp_tlf(struct sppp *sp);static void sppp_lcp_scr(struct sppp *sp);static void sppp_lcp_check_and_close(struct sppp *sp);static int sppp_ncp_check(struct sppp *sp);static void sppp_ipcp_init(struct sppp *sp);static void sppp_ipcp_up(struct sppp *sp);static void sppp_ipcp_down(struct sppp *sp);static void sppp_ipcp_open(struct sppp *sp);static void sppp_ipcp_close(struct sppp *sp);static void sppp_ipcp_TO(void *sp);static int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len);static void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len);static void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len);static void sppp_ipcp_tlu(struct sppp *sp);static void sppp_ipcp_tld(struct sppp *sp);static void sppp_ipcp_tls(struct sppp *sp);static void sppp_ipcp_tlf(struct sppp *sp);static void sppp_ipcp_scr(struct sppp *sp);static void sppp_pap_input(struct sppp *sp, struct mbuf *m);static void sppp_pap_init(struct sppp *sp);static void sppp_pap_open(struct sppp *sp);static void sppp_pap_close(struct sppp *sp);static void sppp_pap_TO(void *sp);static void sppp_pap_my_TO(void *sp);static void sppp_pap_tlu(struct sppp *sp);static void sppp_pap_tld(struct sppp *sp);static void sppp_pap_scr(struct sppp *sp);static void sppp_chap_input(struct sppp *sp, struct mbuf *m);static void sppp_chap_init(struct sppp *sp);static void sppp_chap_open(struct sppp *sp);static void sppp_chap_close(struct sppp *sp);static void sppp_chap_TO(void *sp);static void sppp_chap_tlu(struct sppp *sp);static void sppp_chap_tld(struct sppp *sp);static void sppp_chap_scr(struct sppp *sp);static const char *sppp_auth_type_name(u_short proto, u_char type);static const char *sppp_cp_type_name(u_char type);static const char *sppp_dotted_quad(u_long addr);static const char *sppp_ipcp_opt_name(u_char opt);static const char *sppp_lcp_opt_name(u_char opt);static const char *sppp_phase_name(enum ppp_phase phase);static const char *sppp_proto_name(u_short proto);static const char *sppp_state_name(int state);static int sppp_params(struct sppp *sp, u_long cmd, void *data);static int sppp_strnlen(u_char *p, int max);static void sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst,			      u_long *srcmask);static void sppp_keepalive(void *dummy);static void sppp_phase_network(struct sppp *sp);static void sppp_print_bytes(const u_char *p, u_short len);static void sppp_print_string(const char *p, u_short len);static void sppp_qflush(struct ifqueue *ifq);static void sppp_set_ip_addr(struct sppp *sp, u_long src);/* our control protocol descriptors */static const struct cp lcp = {	PPP_LCP, IDX_LCP, CP_LCP, "lcp",	sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close,	sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak,	sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf,	sppp_lcp_scr};static const struct cp ipcp = {	PPP_IPCP, IDX_IPCP, CP_NCP, "ipcp",	sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close,	sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak,	sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf,	sppp_ipcp_scr};static const struct cp pap = {	PPP_PAP, IDX_PAP, CP_AUTH, "pap",	sppp_null, sppp_null, sppp_pap_open, sppp_pap_close,	sppp_pap_TO, 0, 0, 0,	sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null,	sppp_pap_scr};static const struct cp chap = {	PPP_CHAP, IDX_CHAP, CP_AUTH, "chap",	sppp_null, sppp_null, sppp_chap_open, sppp_chap_close,	sppp_chap_TO, 0, 0, 0,	sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null,	sppp_chap_scr};static const struct cp *cps[IDX_COUNT] = {	&lcp,			/* IDX_LCP */	&ipcp,			/* IDX_IPCP */	&pap,			/* IDX_PAP */	&chap,			/* IDX_CHAP */};/* * Exported functions, comprising our interface to the lower layer. *//* * Process the received packet. */voidsppp_input(struct ifnet *ifp, struct mbuf *m){	struct ppp_header *h;	struct ifqueue *inq = 0;	int s;	struct sppp *sp = (struct sppp *)ifp;	int debug = ifp->if_flags & IFF_DEBUG;	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 (debug)			log(LOG_DEBUG,			    SPP_FMT "input packet is too small, %d bytes\n",			    SPP_ARGS(ifp), m->m_pkthdr.len);	  drop:		++ifp->if_ierrors;		++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) {	case PPP_ALLSTATIONS:		if (h->control != PPP_UI)			goto invalid;		if (sp->pp_flags & PP_CISCO) {			if (debug)				log(LOG_DEBUG,				    SPP_FMT "PPP packet in Cisco 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:			if (sp->state[IDX_LCP] == STATE_OPENED)				sppp_cp_send (sp, PPP_LCP, PROTO_REJ,					++sp->pp_seq, m->m_pkthdr.len + 2,					&h->protocol);			if (debug)				log(LOG_DEBUG,				    SPP_FMT "invalid input protocol "				    "<addr=0x%x ctrl=0x%x proto=0x%x>\n",				    SPP_ARGS(ifp),				    h->address, h->control, ntohs(h->protocol));			++ifp->if_noproto;			goto drop;		case PPP_LCP:			sppp_cp_input(&lcp, sp, m);			m_freem (m);			return;		case PPP_PAP:			if (sp->pp_phase >= PHASE_AUTHENTICATE)				sppp_pap_input(sp, m);			m_freem (m);			return;		case PPP_CHAP:			if (sp->pp_phase >= PHASE_AUTHENTICATE)				sppp_chap_input(sp, m);			m_freem (m);			return;#ifdef INET		case PPP_IPCP:			if (sp->pp_phase == PHASE_NETWORK)				sppp_cp_input(&ipcp, sp, m);			m_freem (m);			return;		case PPP_IP:			if (sp->state[IDX_IPCP] == STATE_OPENED) {				schednetisr (NETISR_IP);				inq = &ipintrq;			}			break;#endif#ifdef IPX		case PPP_IPX:			/* IPX IPXCP not implemented yet */			if (sp->pp_phase == PHASE_NETWORK) {				schednetisr (NETISR_IPX);				inq = &ipxintrq;			}			break;

⌨️ 快捷键说明

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