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

📄 ppp.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
			ppp->escape = 0;		} else if (chr == PPP_ESCAPE) {			ppp->escape = PPP_TRANS;			continue;		}		/*		 * Allocate an skbuff on the first character received.		 * The 128 is room for VJ header expansion and FCS.		 */		if (skb == NULL) {			skb = dev_alloc_skb(ppp->mru + 128 + PPP_HDRLEN);			if (skb == NULL) {				if (ppp->flags & SC_DEBUG)					printk(KERN_DEBUG "couldn't "					       "alloc skb for recv\n");				ppp->toss = 1;				continue;			}		}		/*		 * Decompress A/C and protocol compression here.		 */		if (skb->len == 0 && chr != PPP_ALLSTATIONS) {			p = skb_put(skb, 2);			p[0] = PPP_ALLSTATIONS;			p[1] = PPP_UI;		}		if (skb->len == 2 && (chr & 1) != 0) {			p = skb_put(skb, 1);			p[0] = 0;		}		/*		 * Check if we've overflowed the MRU		 */		if (skb->len >= ppp->mru + PPP_HDRLEN + 2		    || skb_tailroom(skb) <= 0) {			++ppp->estats.rx_length_errors;			ppp->toss = 0xC0;			if (ppp->flags & SC_DEBUG)				printk(KERN_DEBUG "rcv frame too long: "				       "len=%d mru=%d hroom=%d troom=%d\n",				       skb->len, ppp->mru, skb_headroom(skb),				       skb_tailroom(skb));			continue;		}		/*		 * Store the character and update the FCS.		 */		p = skb_put(skb, 1);		*p = chr;		ppp->rfcs = PPP_FCS(ppp->rfcs, chr);	}	ppp->rpkt = skb;}/************************************************************* * PPP NETWORK INTERFACE SUPPORT *	The following code implements the PPP network *	interface device and handles those parts of *	the PPP processing which are independent of the *	type of hardware link being used, including *	VJ and packet compression. *************************************************************//* * Network device driver callback routines */static int ppp_init_dev(struct device *dev);static int ppp_dev_open(struct device *);static int ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd);static int ppp_dev_close(struct device *);static int ppp_dev_xmit(struct sk_buff *, struct device *);static struct net_device_stats *ppp_dev_stats (struct device *);/* * Information for the protocol decoder */typedef int (*pfn_proto)  (struct ppp *, struct sk_buff *);typedef struct ppp_proto_struct {	int		proto;	pfn_proto	func;} ppp_proto_type;static int rcv_proto_ip		(struct ppp *, struct sk_buff *);static int rcv_proto_ipv6	(struct ppp *, struct sk_buff *);static int rcv_proto_ipx	(struct ppp *, struct sk_buff *);static int rcv_proto_at		(struct ppp *, struct sk_buff *);static int rcv_proto_vjc_comp	(struct ppp *, struct sk_buff *);static int rcv_proto_vjc_uncomp (struct ppp *, struct sk_buff *);static int rcv_proto_ccp	(struct ppp *, struct sk_buff *);static int rcv_proto_unknown	(struct ppp *, struct sk_buff *);staticppp_proto_type proto_list[] = {	{ PPP_IP,	  rcv_proto_ip	       },	{ PPP_IPV6,	  rcv_proto_ipv6       },	{ PPP_IPX,	  rcv_proto_ipx	       },	{ PPP_AT,	  rcv_proto_at	       },	{ PPP_VJC_COMP,	  rcv_proto_vjc_comp   },	{ PPP_VJC_UNCOMP, rcv_proto_vjc_uncomp },	{ PPP_CCP,	  rcv_proto_ccp	       },	{ 0,		  rcv_proto_unknown    }  /* !!! MUST BE LAST !!! */};/* * Called when the PPP network interface device is actually created. */static intppp_init_dev (struct device *dev){	dev->hard_header_len  = PPP_HDRLEN;	/* device INFO */	dev->mtu	      = PPP_MTU;	dev->hard_start_xmit  = ppp_dev_xmit;	dev->open	      = ppp_dev_open;	dev->stop	      = ppp_dev_close;	dev->get_stats	      = ppp_dev_stats;	dev->do_ioctl	      = ppp_dev_ioctl;	dev->addr_len	      = 0;	dev->tx_queue_len     = 10;	dev->type	      = ARPHRD_PPP;	dev_init_buffers(dev);	dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;	return 0;}/* * Callback from the network layer when the device goes up. */static intppp_dev_open (struct device *dev){	struct ppp *ppp = dev2ppp(dev);	if (!ppp->inuse || ppp2tty(ppp) == NULL) {		printk(KERN_ERR "ppp: %s not active\n", dev->name);		return -ENXIO;	}	MOD_INC_USE_COUNT;	return 0;}/* * Callback from the network layer when the ppp device goes down. */static intppp_dev_close (struct device *dev){	struct ppp *ppp = dev2ppp (dev);	CHECK_PPP_MAGIC(ppp);	/* ppp_dev_close may be called with tbusy==1 so we must set it to 0 */	dev->tbusy=0;	MOD_DEC_USE_COUNT;	return 0;}static inline voidget_vj_stats(struct vjstat *vj, struct slcompress *slc){	vj->vjs_packets    = slc->sls_o_compressed + slc->sls_o_uncompressed;	vj->vjs_compressed = slc->sls_o_compressed;	vj->vjs_searches   = slc->sls_o_searches;	vj->vjs_misses     = slc->sls_o_misses;	vj->vjs_errorin    = slc->sls_i_error;	vj->vjs_tossed     = slc->sls_i_tossed;	vj->vjs_uncompressedin = slc->sls_i_uncompressed;	vj->vjs_compressedin   = slc->sls_i_compressed;}/* * Callback from the network layer to process the sockioctl functions. */static intppp_dev_ioctl (struct device *dev, struct ifreq *ifr, int cmd){	struct ppp *ppp = dev2ppp(dev);	int nb;	union {		struct ppp_stats stats;		struct ppp_comp_stats cstats;		char vers[32];	} u;	CHECK_PPP_MAGIC(ppp);	memset(&u, 0, sizeof(u));	switch (cmd) {	case SIOCGPPPSTATS:		u.stats.p = ppp->stats;		if (ppp->slcomp != NULL)			get_vj_stats(&u.stats.vj, ppp->slcomp);		nb = sizeof(u.stats);		break;	case SIOCGPPPCSTATS:		if (ppp->sc_xc_state != NULL)			(*ppp->sc_xcomp->comp_stat)				(ppp->sc_xc_state, &u.cstats.c);		if (ppp->sc_rc_state != NULL)			(*ppp->sc_rcomp->decomp_stat)				(ppp->sc_rc_state, &u.cstats.d);		nb = sizeof(u.cstats);		break;	case SIOCGPPPVER:		strcpy(u.vers, szVersion);		nb = strlen(u.vers) + 1;		break;	default:		return -EINVAL;	}	if (copy_to_user((void *) ifr->ifr_ifru.ifru_data, &u, nb))		return -EFAULT;	return 0;}/* * Process the generic PPP ioctls, i.e. those which are not specific * to any particular type of hardware link. */static intppp_ioctl(struct ppp *ppp, unsigned int param2, unsigned long param3){	register int temp_i = 0, oldflags;	int error = -EFAULT;	unsigned long flags;	struct ppp_idle cur_ddinfo;	struct npioctl npi;	CHECK_PPP(-ENXIO);	/*	 * The user must have an euid of root to do these requests.	 */	if (!capable(CAP_NET_ADMIN))		return -EPERM;	switch (param2) {	case PPPIOCSMRU:		/*		 * Set the MRU value		 */		if (get_user(temp_i, (int *) param3))			break;		if (temp_i < PPP_MRU)			temp_i = PPP_MRU;		ppp->mru = temp_i;		if (ppp->flags & SC_DEBUG)			printk(KERN_INFO			       "ppp_ioctl: set mru to %x\n", temp_i);		error = 0;		break;	case PPPIOCGFLAGS:		/*		 * Fetch the current flags		 */		temp_i = ppp->flags & SC_MASK;#ifndef CHECK_CHARACTERS /* Don't generate errors if we don't check chars. */		temp_i |= SC_RCV_B7_1 | SC_RCV_B7_0 |			  SC_RCV_ODDP | SC_RCV_EVNP;#endif		if (put_user(temp_i, (int *) param3))			break;		error = 0;		break;	case PPPIOCSFLAGS:		/*		 * Set the flags for the various options		 */		if (get_user(temp_i, (int *) param3))			break;		if (ppp->flags & ~temp_i & SC_CCP_OPEN)			ppp_ccp_closed(ppp);		save_flags(flags);		cli();		oldflags = ppp->flags;		temp_i = (temp_i & SC_MASK) | (oldflags & ~SC_MASK);		ppp->flags = temp_i;		restore_flags(flags);		if ((oldflags | temp_i) & SC_DEBUG)			printk(KERN_INFO			       "ppp_ioctl: set flags to %x\n", temp_i);		error = 0;		break;	case PPPIOCSCOMPRESS:		/*		 * Set the compression mode		 */		error = ppp_set_compression			(ppp, (struct ppp_option_data *) param3);		break;	case PPPIOCGUNIT:		/*		 * Obtain the unit number for this device.		 */		if (put_user(ppp->line, (int *) param3))			break;		if (ppp->flags & SC_DEBUG)			printk(KERN_INFO			       "ppp_ioctl: get unit: %d\n", ppp->line);		error = 0;		break;	case PPPIOCSDEBUG:		/*		 * Set the debug level		 */		if (get_user(temp_i, (int *) param3))			break;		temp_i = (temp_i & 0x1F) << 16;		if ((ppp->flags | temp_i) & SC_DEBUG)			printk(KERN_INFO			       "ppp_ioctl: set dbg flags to %x\n", temp_i);		save_flags(flags);		cli();		ppp->flags = (ppp->flags & ~0x1F0000) | temp_i;		restore_flags(flags);		error = 0;		break;	case PPPIOCGDEBUG:		/*		 * Get the debug level		 */		temp_i = (ppp->flags >> 16) & 0x1F;		if (put_user(temp_i, (int *) param3))			break;		error = 0;		break;	case PPPIOCGIDLE:		/*		 * Get the times since the last send/receive frame operation		 */		/* change absolute times to relative times. */		cur_ddinfo.xmit_idle = (jiffies - ppp->last_xmit) / HZ;		cur_ddinfo.recv_idle = (jiffies - ppp->last_recv) / HZ;		if (copy_to_user((void *) param3, &cur_ddinfo,				 sizeof (cur_ddinfo)))			break;		error = 0;		break;	case PPPIOCSMAXCID:		/*		 * Set the maximum VJ header compression slot number.		 */		if (get_user(temp_i, (int *) param3))			break;		error = -EINVAL;		if (temp_i < 2 || temp_i > 255)			break;		++temp_i;		if (ppp->flags & SC_DEBUG)			printk(KERN_INFO "ppp_ioctl: set maxcid to %d\n",			       temp_i);		if (ppp->slcomp != NULL)			slhc_free(ppp->slcomp);		ppp->slcomp = slhc_init(16, temp_i);		error = -ENOMEM;		if (ppp->slcomp == NULL) {			printk(KERN_ERR "ppp: no memory for VJ compression\n");			break;		}		error = 0;		break;	case PPPIOCGNPMODE:	case PPPIOCSNPMODE:		if (copy_from_user(&npi, (void *) param3, sizeof(npi)))			break;		switch (npi.protocol) {		case PPP_IP:			npi.protocol = NP_IP;			break;		case PPP_IPX:			npi.protocol = NP_IPX;			break;		case PPP_AT:			npi.protocol = NP_AT;			break;		default:			if (ppp->flags & SC_DEBUG)				printk(KERN_DEBUG "pppioc[gs]npmode: "				       "invalid proto %d\n", npi.protocol);			error = -EINVAL;			goto out;		}		if (param2 == PPPIOCGNPMODE) {			npi.mode = ppp->sc_npmode[npi.protocol];			if (copy_to_user((void *) param3, &npi, sizeof(npi)))				break;		} else {			ppp->sc_npmode[npi.protocol] = npi.mode;			if (ppp->flags & SC_DEBUG)				printk(KERN_DEBUG "ppp: set np %d to %d\n",				       npi.protocol, npi.mode);			mark_bh(NET_BH);		}		error = 0;		break;	default:		/*		 *  All other ioctl() events will come here.		 */		if (ppp->flags & SC_DEBUG)			printk(KERN_ERR			       "ppp_ioctl: invalid ioctl: %x, addr %lx\n",			       param2, param3);		error = -ENOIOCTLCMD;		break;	}out:	return error;}/* * Process the set-compression ioctl. */static intppp_set_compression (struct ppp *ppp, struct ppp_option_data *odp){	struct compressor *cp;	int error, nb;	unsigned long flags;	__u8 *ptr;	__u8 ccp_option[CCP_MAX_OPTION_LENGTH];	struct ppp_option_data data;	/*	 * Fetch the compression parameters	 */	error = -EFAULT;	if (copy_from_user(&data, odp, sizeof (data)))		goto out;	nb  = data.length;	ptr = data.ptr;	if ((unsigned) nb >= CCP_MAX_OPTION_LENGTH)		nb = CCP_MAX_OPTION_LENGTH;	if (copy_from_user(ccp_option, ptr, nb))		goto out;	error = -EINVAL;	if (ccp_option[1] < 2)	/* preliminary check on the length byte */		goto out;	save_flags(flags);	cli();	ppp->flags &= ~(data.transmit? SC_COMP_RUN: SC_DECOMP_RUN);	restore_flags(flags);	cp = find_compressor (ccp_option[0]);#ifdef CONFIG_KMOD	if (cp == NULL) {		char modname[32];		sprintf(modname, "ppp-compress-%d", ccp_option[0]);		request_module(modname);		cp = find_compressor(ccp_option[0]);	}#endif /* CONFIG_KMOD */	if (cp == NULL) {		if (ppp->flags & SC_DEBUG)			printk(KERN_DEBUG			       "%s: no compressor for [%x %x %x], %x\n",			       ppp->name, ccp_option[0], ccp_option[1],			       ccp_option[2], nb);		goto out;		/* compressor not loaded */	}	/*	 * Found a handler for the protocol - try to allocate	 * a compressor or decompressor.	 */	error = 0;	if (data.transmit) {		if (ppp->sc_xc_state != NULL)			(*ppp->sc_xcomp->comp_free)(ppp->sc_xc_state);		ppp->sc_xc_state = NULL;		ppp->sc_xcomp	 = cp;		ppp->sc_xc_state = cp->comp_alloc(ccp_option, nb);		if (ppp->sc_xc_state == NULL) {			if (ppp->flags & SC_DEBUG)				printk(KERN_DEBUG "%s: comp_alloc failed\n",				       ppp->name);			error = -ENOBUFS;		}	} else {		if (ppp->sc_rc_state != NULL)			(*ppp->sc_rcomp->decomp_free)(ppp->sc_rc_state);		ppp->sc_rc_state = NULL;		ppp->sc_rcomp	 = cp;		ppp->sc_rc_state = cp->decomp_alloc(ccp_option, nb);		if (ppp->sc_rc_state == NULL) {			if (ppp->flags & SC_DEBUG)				printk(KERN_DEBUG "%s: decomp_alloc failed\n",				       ppp->name);			error = -ENOBUFS;		}	}out:	return error;}/* * Handle a CCP packet. * * The CCP packet is passed along to the pppd process just like any * other PPP frame. The difference is that some processing needs to be * immediate or the compressors will become confused on the peer. */static void ppp_proto_ccp(struct ppp *ppp, __u8 *dp, int len, int rcvd){	int slen    = CCP_LENGTH(dp);	__u8 *opt = dp	 + CCP_HDRLEN;	int opt_len = slen - CCP_HDRLEN;	unsigned long flags;	if (slen > len)		return;	if (ppp->flags & SC_DEBUG)		printk(KERN_DEBUG "ppp_proto_ccp rcvd=%d code=%x flags=%x\n",

⌨️ 快捷键说明

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