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

📄 ppp.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	__u8 *orig_data, *data;	struct sk_buff *new_skb;	int len, proto;	new_skb = alloc_skb(skb->len, GFP_ATOMIC);	if (new_skb == NULL) {		printk(KERN_ERR "ppp: no memory for vj compression\n");		return skb;	}	orig_data = data = skb->data + PPP_HDRLEN;	len = slhc_compress(ppp->slcomp, data, skb->len - PPP_HDRLEN,			    new_skb->data + PPP_HDRLEN, &data,			    (ppp->flags & SC_NO_TCP_CCID) == 0);	if (data == orig_data) {		/* Couldn't compress the data */		kfree_skb(new_skb);		return skb;	}	/* The data has been changed */	if (data[0] & SL_TYPE_COMPRESSED_TCP) {		proto = PPP_VJC_COMP;		data[0] ^= SL_TYPE_COMPRESSED_TCP;	} else {		if (data[0] >= SL_TYPE_UNCOMPRESSED_TCP)			proto = PPP_VJC_UNCOMP;		else			proto = PPP_IP;		data[0] = orig_data[0];	}	data = skb_put(new_skb, len + PPP_HDRLEN);	data[0] = PPP_ALLSTATIONS;	data[1] = PPP_UI;	data[2] = 0;	data[3] = proto;	kfree_skb(skb);	return new_skb;}static inline voidppp_send_frames(struct ppp *ppp){	struct sk_buff *skb;	while (!test_and_set_bit(0, &ppp->xmit_busy)) {		skb = skb_dequeue(&ppp->xmt_q);		if (skb == NULL) {			ppp->xmit_busy = 0;			break;		}		ppp_send_frame(ppp, skb);	}	if (!ppp->xmit_busy && ppp->dev.tbusy) {		ppp->dev.tbusy = 0;		mark_bh(NET_BH);	}}/* * Called from the hardware (tty) layer when it can accept * another packet. */static voidppp_output_wakeup(struct ppp *ppp){	CHECK_PPP_VOID();	if (!ppp->xmit_busy) {		printk(KERN_ERR "ppp_output_wakeup called but xmit_busy==0\n");		return;	}	ppp->xmit_busy = 0;	ppp_send_frames(ppp);}/* * Send a control frame (from pppd). */static voidppp_send_ctrl(struct ppp *ppp, struct sk_buff *skb){	CHECK_PPP_VOID();	/*	 * Put the packet on the queue, then send as many as we can.	 */	skb_queue_tail(&ppp->xmt_q, skb);	ppp_send_frames(ppp);}/************************************************************* * NETWORK OUTPUT *    This routine accepts requests from the network layer *    and attempts to deliver the packets. *************************************************************//* * Send a frame to the peer. * Returns 1 iff the frame was not accepted. */static intppp_dev_xmit(struct sk_buff *skb, struct device *dev){	struct ppp *ppp = dev2ppp(dev);	struct tty_struct *tty = ppp2tty(ppp);	enum NPmode npmode;	int proto;	unsigned char *hdr;	/* just a little sanity check. */	if (skb == NULL)		return 0;	if (skb->data == NULL) {		kfree_skb(skb);		return 0;	}	/*	 * Avoid timing problem should tty hangup while data is	 * queued to be sent.	 */	if (!ppp->inuse) {		dev_kfree_skb(skb);		return 0;	}	/*	 * Validate the tty interface	 */	if (tty == NULL) {		if (ppp->flags & SC_DEBUG)			printk(KERN_ERR			       "ppp_dev_xmit: %s not connected to a TTY!\n",			       dev->name);		dev_kfree_skb(skb);		return 0;	}	/*	 * Work out the appropriate network-protocol mode for this packet.	 */	npmode = NPMODE_PASS;	/* default */	switch (ntohs(skb->protocol)) {	case ETH_P_IP:		proto = PPP_IP;		npmode = ppp->sc_npmode[NP_IP];		break;	case ETH_P_IPV6:		proto = PPP_IPV6;		npmode = ppp->sc_npmode[NP_IPV6];		break;	case ETH_P_IPX:		proto = PPP_IPX;		npmode = ppp->sc_npmode[NP_IPX];		break;	case ETH_P_PPPTALK:	case ETH_P_ATALK:		proto = PPP_AT;		npmode = ppp->sc_npmode[NP_AT];		break;	default:		if (ppp->flags & SC_DEBUG)			printk(KERN_INFO "%s: packet for unknown proto %x\n",			       ppp->name, ntohs(skb->protocol));		dev_kfree_skb(skb);		return 0;	}	/*	 * Drop, accept or reject the packet depending on the mode.	 */	switch (npmode) {	case NPMODE_PASS:		break;	case NPMODE_QUEUE:		/*		 * We may not send the packet now, so drop it.		 * XXX It would be nice to be able to return it to the		 * network system to be queued and retransmitted later.		 */		if (ppp->flags & SC_DEBUG)			printk(KERN_DEBUG "%s: returning frame\n", ppp->name);		dev_kfree_skb(skb);		return 0;	case NPMODE_ERROR:	case NPMODE_DROP:		if (ppp->flags & SC_DEBUG)			printk(KERN_DEBUG			       "ppp_dev_xmit: dropping (npmode = %d) on %s\n",			       npmode, ppp->name);		dev_kfree_skb(skb);		return 0;	}	/*	 * The dev->tbusy field acts as a lock to allow only	 * one packet to be processed at a time.  If we can't	 * get the lock, try again later.	 * We deliberately queue as little as possible inside	 * the ppp driver in order to minimize the latency	 * for high-priority packets.	 */	if (test_and_set_bit(0, &ppp->xmit_busy)) {		dev->tbusy = 1;	/* can't take it now */		return 1;	}	dev->tbusy = 0;	/*	 * Put the 4-byte PPP header on the packet.	 * If there isn't room for it, we have to copy the packet.	 */	if (skb_headroom(skb) < PPP_HDRLEN) {		struct sk_buff *new_skb;		new_skb = alloc_skb(skb->len + PPP_HDRLEN, GFP_ATOMIC);		if (new_skb == NULL) {			printk(KERN_ERR "%s: skb hdr alloc failed\n",			       ppp->name);			dev_kfree_skb(skb);			ppp->xmit_busy = 0;			ppp_send_frames(ppp);			return 0;		}		skb_reserve(new_skb, PPP_HDRLEN);		memcpy(skb_put(new_skb, skb->len), skb->data, skb->len);		dev_kfree_skb(skb);		skb = new_skb;	}	hdr = skb_push(skb, PPP_HDRLEN);	hdr[0] = PPP_ALLSTATIONS;	hdr[1] = PPP_UI;	hdr[2] = proto >> 8;	hdr[3] = proto;	ppp_send_frame(ppp, skb);	if (!ppp->xmit_busy)		ppp_send_frames(ppp);	return 0;}/* * Generate the statistic information for the /proc/net/dev listing. */static struct net_device_stats *ppp_dev_stats (struct device *dev){	struct ppp *ppp = dev2ppp (dev);	ppp->estats.rx_packets = ppp->stats.ppp_ipackets;	ppp->estats.rx_errors  = ppp->stats.ppp_ierrors;	ppp->estats.tx_packets = ppp->stats.ppp_opackets;	ppp->estats.tx_errors  = ppp->stats.ppp_oerrors;	ppp->estats.rx_bytes   = ppp->stats.ppp_ibytes;	ppp->estats.tx_bytes   = ppp->stats.ppp_obytes;	return &ppp->estats;}/************************************************************* * UTILITIES *    Miscellany called by various functions above. *************************************************************//* Locate the previous instance of the PPP channel */static struct ppp *ppp_find(int pid_value){	struct ppp	*ppp;	/* try to find the device which this pid is already using */	for (ppp = ppp_list; ppp != 0; ppp = ppp->next) {		if (ppp->inuse && ppp->sc_xfer == pid_value) {			ppp->sc_xfer = 0;			break;		}	}	return ppp;}/* allocate or create a PPP channel */static struct ppp *ppp_alloc(void){	int		if_num;	int		status;	struct device	*dev;	struct ppp	*ppp;	/* try to find an free device */	for (ppp = ppp_list; ppp != 0; ppp = ppp->next) {		if (!test_and_set_bit(0, &ppp->inuse)) {			dev = ppp2dev(ppp);			if (dev->flags & IFF_UP) {				clear_bit(0, &ppp->inuse);				continue;			}			/* Reregister device */			unregister_netdev(dev);			if (register_netdev(dev) == 0)				return ppp;			printk(KERN_DEBUG "could not reregister ppp device\n");			/* leave inuse set in this case */		}	}	/*	 * There are no available units, so make a new one.	 */	ppp = (struct ppp *) kmalloc(sizeof(struct ppp), GFP_KERNEL);	if (ppp == 0) {		printk(KERN_ERR "ppp: struct ppp allocation failed\n");		return 0;	}	memset(ppp, 0, sizeof(*ppp));	/* initialize channel control data */	ppp->magic = PPP_MAGIC;	ppp->next = NULL;	ppp->inuse = 1;	ppp->read_wait = NULL;	/*	 * Make up a suitable name for this device	 */	dev = ppp2dev(ppp);	dev->name = ppp->name;	if_num = dev_alloc_name(dev, "ppp%d");	if (if_num < 0) {		printk(KERN_ERR "ppp: dev_alloc_name failed (%d)\n", if_num);		kfree(ppp);		return 0;	}	ppp->line = if_num;	ppp->slcomp = NULL;	dev->next = NULL;	dev->init = ppp_init_dev;	dev->name = ppp->name;	dev->priv = (void *) ppp;	/* register device so that we can be ifconfig'd */	/* ppp_init_dev() will be called as a side-effect */	status = register_netdev (dev);	if (status == 0) {		printk(KERN_INFO "registered device %s\n", dev->name);	} else {		printk(KERN_ERR		       "ppp_alloc - register_netdev(%s) = %d failure.\n",		       dev->name, status);		kfree(ppp);		ppp = NULL;	}	/* link this unit into our list */	if (ppp_list == 0)		ppp_list = ppp;	else		ppp_last->next = ppp;	ppp_last = ppp;	return ppp;}/* * Initialize the generic parts of the ppp structure. */static voidppp_generic_init(struct ppp *ppp){	int indx;	ppp->flags  = 0;	ppp->mtu    = PPP_MTU;	ppp->mru    = PPP_MRU;	skb_queue_head_init(&ppp->xmt_q);	skb_queue_head_init(&ppp->rcv_q);	ppp->last_xmit	= jiffies;	ppp->last_recv  = jiffies;	ppp->xmit_busy  = 0;	/* clear statistics */	memset(&ppp->stats, 0, sizeof (struct pppstat));	memset(&ppp->estats, 0, sizeof(struct net_device_stats));	/* PPP compression data */	ppp->sc_xc_state = NULL;	ppp->sc_rc_state = NULL;	for (indx = 0; indx < NUM_NP; ++indx)		ppp->sc_npmode[indx] = NPMODE_PASS;}/* * Called to clean up the generic parts of the ppp structure. */static voidppp_release(struct ppp *ppp){	struct sk_buff *skb;	CHECK_PPP_MAGIC(ppp);	if (ppp->flags & SC_DEBUG)		printk(KERN_DEBUG "%s released\n", ppp->name);	ppp_ccp_closed(ppp);        /* Ensure that the pppd process is not hanging on select()/poll() */        wake_up_interruptible(&ppp->read_wait);	if (ppp->slcomp) {		slhc_free(ppp->slcomp);		ppp->slcomp = NULL;	}	while ((skb = skb_dequeue(&ppp->rcv_q)) != NULL)		kfree_skb(skb);	while ((skb = skb_dequeue(&ppp->xmt_q)) != NULL)		kfree_skb(skb);	ppp->inuse = 0;	if (ppp->dev.tbusy) {		ppp->dev.tbusy = 0;		mark_bh(NET_BH);	}}/* * Utility procedures to print a buffer in hex/ascii */static voidppp_print_hex (register __u8 * out, const __u8 * in, int count){	register __u8 next_ch;	static char hex[] = "0123456789ABCDEF";	while (count-- > 0) {		next_ch = *in++;		*out++ = hex[(next_ch >> 4) & 0x0F];		*out++ = hex[next_ch & 0x0F];		++out;	}}static voidppp_print_char (register __u8 * out, const __u8 * in, int count){	register __u8 next_ch;	while (count-- > 0) {		next_ch = *in++;		if (next_ch < 0x20 || next_ch > 0x7e)			*out++ = '.';		else {			*out++ = next_ch;			if (next_ch == '%')   /* printk/syslogd has a bug !! */				*out++ = '%';		}	}	*out = '\0';}static voidppp_print_buffer (const char *name, const __u8 *buf, int count){	__u8 line[44];	if (name != NULL)		printk(KERN_DEBUG "ppp: %s, count = %d\n", name, count);	while (count > 8) {		memset (line, 32, 44);		ppp_print_hex (line, buf, 8);		ppp_print_char (&line[8 * 3], buf, 8);		printk(KERN_DEBUG "%s\n", line);		count -= 8;		buf += 8;	}	if (count > 0) {		memset (line, 32, 44);		ppp_print_hex (line, buf, count);		ppp_print_char (&line[8 * 3], buf, count);		printk(KERN_DEBUG "%s\n", line);	}}/************************************************************* * Compressor module interface *************************************************************/struct compressor_link {	struct compressor_link	*next;	struct compressor	*comp;};static struct compressor_link *ppp_compressors = (struct compressor_link *) 0;static struct compressor *find_compressor (int type){	struct compressor_link *lnk;	unsigned long flags;	save_flags(flags);	cli();	lnk = ppp_compressors;	while (lnk != (struct compressor_link *) 0) {		if ((int) (__u8) lnk->comp->compress_proto == type) {			restore_flags(flags);			return lnk->comp;		}		lnk = lnk->next;	}	restore_flags(flags);	return (struct compressor *) 0;}#ifdef CONFIG_MODULESstatic int ppp_register_compressor (struct compressor *cp){	struct compressor_link *new;	unsigned long flags;	new = (struct compressor_link *)		kmalloc (sizeof (struct compressor_link), GFP_KERNEL);	if (new == (struct compressor_link *) 0)		return 1;	save_flags(flags);	cli();	if (find_compressor (cp->compress_proto)) {		restore_flags(flags);		kfree (new);		return 0;	}	new->next	= ppp_compressors;	new->comp	= cp;	ppp_compressors = new;	restore_flags(flags);	return 0;}static void ppp_unregister_compressor (struct compressor *cp){	struct compressor_link *prev = (struct compressor_link *) 0;	struct compressor_lin

⌨️ 快捷键说明

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