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

📄 ppp.c

📁 unix and linux net driver
💻 C
📖 第 1 页 / 共 5 页
字号:
	dev->rebuild_header   = ppp_dev_rebuild;#endif	/* 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;#if LINUX_VERSION_CODE < VERSION(2,1,20)	{		int    indx;		for (indx = 0; indx < DEV_NUMBUFFS; indx++)			skb_queue_head_init (&dev->buffs[indx]);	}#else	dev_init_buffers(dev);#endif	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);	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 (!SUSER())		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_IPV6:			npi.protocol = NP_IPV6;			break;		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]);#if defined(CONFIG_KMOD) || defined(CONFIG_KERNELD)	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",		       rcvd, CCP_CODE(dp), ppp->flags);	save_flags(flags);	switch (CCP_CODE(dp)) {	case CCP_CONFREQ:	case CCP_TERMREQ:	case CCP_TERMACK:		/*		 * CCP must be going down - disable compression		 */		if (ppp->flags & SC_CCP_UP) {			cli();			ppp->flags &= ~(SC_CCP_UP   |					SC_COMP_RUN |					SC_DECOMP_RUN);		}		break;	case CCP_CONFACK:		if ((ppp->flags & SC_CCP_OPEN) == 0)			break;		if (ppp->flags & SC_CCP_UP)			break;		if (slen < (CCP_HDRLEN + CCP_OPT_MINLEN))			break;		if (slen < (CCP_OPT_LENGTH (opt) + CCP_HDRLEN))			break;		if (!rcvd) {			/*			 * we're agreeing to send compressed packets.			 */			if (ppp->sc_xc_state == NULL)				break;			if ((*ppp->sc_xcomp->comp_init)			    (ppp->sc_xc_state,			     opt, opt_len,			     ppp->line, 0, ppp->flags & SC_DEBUG)) {				if (ppp->flags & SC_DEBUG)					printk(KERN_DEBUG "%s: comp running\n",					       ppp->name);				cli();				ppp->flags |= SC_COMP_RUN;			}			break;		}		/*		 * peer is agreeing to send compressed packets.		 */		if (ppp->sc_rc_state == NULL)			break;		if ((*ppp->sc_rcomp->decomp_init)		    (ppp->sc_rc_state,		     opt, opt_len,		     ppp->line, 0, ppp->mru, ppp->flags & SC_DEBUG)) {			if (ppp->flags & SC_DEBUG)				printk(KERN_DEBUG "%s: decomp running\n",				       ppp->name);			cli();			ppp->flags |= SC_DECOMP_RUN;			ppp->flags &= ~(SC_DC_ERROR | SC_DC_FERROR);		}		break;	case CCP_RESETACK:		/*		 * CCP Reset-ack resets compressors and decompressors		 * as it passes through.		 */		if ((ppp->flags & SC_CCP_UP) == 0)			break;		if (!rcvd) {			if (ppp->sc_xc_state && (ppp->flags & SC_COMP_RUN)) {				(*ppp->sc_xcomp->comp_reset)(ppp->sc_xc_state);				if (ppp->flags & SC_DEBUG)					printk(KERN_DEBUG "%s: comp reset\n",					       ppp->name);			}		} else {			if (ppp->sc_rc_state && (ppp->flags & SC_DECOMP_RUN)) {			      (*ppp->sc_rcomp->decomp_reset)(ppp->sc_rc_state);			      if (ppp->flags & SC_DEBUG)					printk(KERN_DEBUG "%s: decomp reset\n",					       ppp->name);			      cli();			      ppp->flags &= ~SC_DC_ERROR;			}		}		break;	}	restore_flags(flags);}/* * CCP is down; free (de)compressor state if necessary. */static voidppp_ccp_closed(struct ppp *ppp)

⌨️ 快捷键说明

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