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

📄 af_wanpipe.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************** af_wanpipe.c	WANPIPE(tm) Secure Socket Layer.** Author:	Nenad Corbic	<ncorbic@sangoma.com>** Copyright:	(c) 2000 Sangoma Technologies Inc.**		This program is free software; you can redistribute it and/or*		modify it under the terms of the GNU General Public License*		as published by the Free Software Foundation; either version*		2 of the License, or (at your option) any later version.* ============================================================================* Due Credit:*               Wanpipe socket layer is based on Packet and *               the X25 socket layers. The above sockets were *               used for the specific use of Sangoma Technoloiges *               API programs. *               Packet socket Authors: Ross Biro, Fred N. van Kempen and *                                      Alan Cox.*               X25 socket Author: Jonathan Naylor.* ============================================================================* Apr 25, 2000  Nenad Corbic     o Added the ability to send zero length packets.* Mar 13, 2000  Nenad Corbic	 o Added a tx buffer check via ioctl call.* Mar 06, 2000  Nenad Corbic     o Fixed the corrupt sock lcn problem.*                                  Server and client applicaton can run*                                  simultaneously without conflicts.* Feb 29, 2000  Nenad Corbic     o Added support for PVC protocols, such as*                                  CHDLC, Frame Relay and HDLC API.* Jan 17, 2000 	Nenad Corbic	 o Initial version, based on AF_PACKET socket.*			           X25API support only. *******************************************************************************/#include <linux/version.h>#include <linux/config.h>#include <linux/types.h>#include <linux/sched.h>#include <linux/mm.h>#include <linux/fcntl.h>#include <linux/socket.h>#include <linux/in.h>#include <linux/inet.h>#include <linux/netdevice.h>#include <linux/poll.h>#include <linux/wireless.h>#include <linux/kmod.h>#include <net/ip.h>#include <net/protocol.h>#include <linux/skbuff.h>#include <net/sock.h>#include <linux/errno.h>#include <linux/timer.h>#include <asm/system.h>#include <asm/uaccess.h>#include <linux/module.h>#include <linux/init.h>#include <linux/wanpipe.h>#include <linux/if_wanpipe.h>#include <linux/pkt_sched.h>#include <linux/tcp.h>#include <linux/if_wanpipe_common.h>#include <linux/sdla_x25.h>#ifdef CONFIG_INET#include <net/inet_common.h>#endif#define SLOW_BACKOFF 0.1*HZ#define FAST_BACKOFF 0.01*HZ//#define PRINT_DEBUG#ifdef PRINT_DEBUG	#define DBG_PRINTK(format, a...) printk(format, ## a)#else	#define DBG_PRINTK(format, a...)#endif      #if defined(LINUX_2_1) #define dev_put(a) #define __sock_put(a) #define sock_hold(a) #define DECLARE_WAITQUEUE(a,b) \		struct wait_queue a = { b, NULL }#endif		/* SECURE SOCKET IMPLEMENTATION  *  *   TRANSMIT: * *      When the user sends a packet via send() system call *      the wanpipe_sendmsg() function is executed.   *       *      Each packet is enqueud into sk->write_queue transmit *      queue. When the packet is enqueued, a delayed transmit *      timer is triggerd which acts as a Bottom Half hander.  * *      wanpipe_delay_transmit() function (BH), dequeues packets *      from the sk->write_queue transmit queue and sends it  *      to the deriver via dev->hard_start_xmit(skb, dev) function.   *      Note, this function is actual a function pointer of if_send() *      routine in the wanpipe driver. * *      X25API GUARANTEED DELIVERY: * *         In order to provide 100% guaranteed packet delivery,  *         an atomic 'packet_sent' counter is implemented.  Counter  *         is incremented for each packet enqueued  *         into sk->write_queue.  Counter is decremented each *         time wanpipe_delayed_transmit() function successfuly  *         passes the packet to the driver. Before each send(), a poll *         routine checks the sock resources The maximum value of *         packet sent counter is 1, thus if one packet is queued, the *         application will block untill that packet is passed to the *         driver. * *   RECEIVE: * *      Wanpipe device drivers call the socket bottom half *      function, wanpipe_rcv() to queue the incoming packets *      into an AF_WANPIPE socket queue.  Based on wanpipe_rcv() *      return code, the driver knows whether the packet was *      sucessfully queued.  If the socket queue is full,  *      protocol flow control is used by the driver, if any,  *      to slow down the traffic untill the sock queue is free. * *      Every time a packet arrives into a socket queue the  *      socket wakes up processes which are waiting to receive *      data. * *      If the socket queue is full, the driver sets a block *      bit which signals the socket to kick the wanpipe driver *      bottom half hander when the socket queue is partialy *      empty. wanpipe_recvmsg() function performs this action. *  *      In case of x25api, packets will never be dropped, since *      flow control is available.  *       *      In case of streaming protocols like CHDLC, packets will  *      be dropped but the statistics will be generated.  *//* The code below is used to test memory leaks. It prints out * a message every time kmalloc and kfree system calls get executed. * If the calls match there is no leak :) *//***********FOR DEBUGGING PURPOSES*********************************************#define KMEM_SAFETYZONE 8static void * dbg_kmalloc(unsigned int size, int prio, int line) {	void * v = kmalloc(size,prio);	printk(KERN_INFO "line %d  kmalloc(%d,%d) = %p\n",line,size,prio,v);	return v;}static void dbg_kfree(void * v, int line) {	printk(KERN_INFO "line %d  kfree(%p)\n",line,v);	kfree(v);}#define kmalloc(x,y) dbg_kmalloc(x,y,__LINE__)#define kfree(x) dbg_kfree(x,__LINE__)******************************************************************************//* List of all wanpipe sockets. */struct sock * wanpipe_sklist = NULL;static rwlock_t wanpipe_sklist_lock = RW_LOCK_UNLOCKED;atomic_t wanpipe_socks_nr;static unsigned long wanpipe_tx_critical=0;#if 0/* Private wanpipe socket structures. */struct wanpipe_opt{	void   *mbox;		/* Mail box  */	void   *card; 		/* Card bouded to */	netdevice_t *dev;	/* Bounded device */	unsigned short lcn;	/* Binded LCN */	unsigned char  svc;	/* 0=pvc, 1=svc */	unsigned char  timer;   /* flag for delayed transmit*/		struct timer_list tx_timer;	unsigned poll_cnt;	unsigned char force;	/* Used to force sock release */	atomic_t packet_sent;   };#endifstatic int sk_count=0;extern struct proto_ops wanpipe_ops;static unsigned long find_free_critical=0;static void wanpipe_unlink_driver (struct sock *);static void wanpipe_link_driver (netdevice_t *,struct sock *sk);static void wanpipe_wakeup_driver(struct sock *sk);static int execute_command(struct sock *, unsigned char, unsigned int);static int check_dev (netdevice_t *, sdla_t *);netdevice_t * wanpipe_find_free_dev (sdla_t *);static void wanpipe_unlink_card (struct sock *);static int wanpipe_link_card (struct sock *);static struct sock *wanpipe_make_new(struct sock *);static struct sock *wanpipe_alloc_socket(void);static inline int get_atomic_device (netdevice_t *);static int wanpipe_exec_cmd(struct sock *, int, unsigned int);static int get_ioctl_cmd (struct sock *, void *);static int set_ioctl_cmd (struct sock *, void *);static void release_device (netdevice_t *);static void wanpipe_kill_sock_timer (unsigned long data);static void wanpipe_kill_sock_irq (struct sock *);static void wanpipe_kill_sock_accept (struct sock *);static int wanpipe_do_bind(struct sock *, netdevice_t *, int);struct sock * get_newsk_from_skb (struct sk_buff *);static int wanpipe_debug (struct sock *, void *);static void wanpipe_delayed_transmit (unsigned long data);static void release_driver(struct sock *);static void start_cleanup_timer (struct sock *);static void check_write_queue(struct sock *);static int check_driver_busy (struct sock *);/*============================================================ * wanpipe_rcv * *	Wanpipe socket bottom half handler.  This function *      is called by the WANPIPE device drivers to queue a *      incomming packet into the socket receive queue.  *      Once the packet is queued, all processes waiting to  *      read are woken up. * *      During socket bind, this function is bounded into *      WANPIPE driver private. *===========================================================*/static int wanpipe_rcv(struct sk_buff *skb, netdevice_t *dev,  struct sock *sk){	struct wan_sockaddr_ll *sll = (struct wan_sockaddr_ll*)skb->cb;	wanpipe_common_t *chan = dev->priv;	/*	 *	When we registered the protocol we saved the socket in the data	 *	field for just this event.	 */	skb->dev = dev;	sll->sll_family = AF_WANPIPE;	sll->sll_hatype = dev->type;	sll->sll_protocol = skb->protocol;	sll->sll_pkttype = skb->pkt_type;	sll->sll_ifindex = dev->ifindex;	sll->sll_halen = 0;	if (dev->hard_header_parse)		sll->sll_halen = dev->hard_header_parse(skb, sll->sll_addr);	/* 	 * WAN_PACKET_DATA : Data which should be passed up the receive queue.         * WAN_PACKET_ASYC : Asynchronous data like place call, which should         *                   be passed up the listening sock.         * WAN_PACKET_ERR  : Asynchronous data like clear call or restart          *                   which should go into an error queue.         */	switch (skb->pkt_type){		case WAN_PACKET_DATA:			if (sock_queue_rcv_skb(sk,skb)<0){				return -ENOMEM;			}			break;		case WAN_PACKET_CMD:			sk->state = chan->state;			/* Bug fix: update Mar6.                          * Do not set the sock lcn number here, since         		 * cmd is not guaranteed to be executed on the                         * board, thus Lcn could be wrong */			sk->data_ready(sk,skb->len);			kfree_skb(skb);			break;		case WAN_PACKET_ERR:			sk->state = chan->state;			if (sock_queue_err_skb(sk,skb)<0){				return -ENOMEM;			}			break;		default:			printk(KERN_INFO "wansock: BH Illegal Packet Type Dropping\n");			kfree_skb(skb); 			break;	}//??????????????????????//	if (sk->state == WANSOCK_DISCONNECTED){//		if (sk->zapped){//			//printk(KERN_INFO "wansock: Disconnected, killing early\n");//			wanpipe_unlink_driver(sk);//			sk->bound_dev_if = 0;//		}//	}	return 0;}/*============================================================ * wanpipe_listen_rcv * *	Wanpipe LISTEN socket bottom half handler.  This function *      is called by the WANPIPE device drivers to queue an *      incomming call into the socket listening queue.  *      Once the packet is queued, the waiting accept() process  *      is woken up. * *      During socket bind, this function is bounded into *      WANPIPE driver private.  *  *      IMPORTANT NOTE: *          The accept call() is waiting for an skb packet *          which contains a pointer to a device structure. * *          When we do a bind to a device structre, we  *          bind a newly created socket into "chan->sk".  Thus,  *          when accept receives the skb packet, it will know  *          from which dev it came form, and in turn it will know *          the address of the new sock. * *  	NOTE: This function gets called from driver ISR. *===========================================================*/static int wanpipe_listen_rcv (struct sk_buff *skb,  struct sock *sk){	struct wan_sockaddr_ll *sll = (struct wan_sockaddr_ll*)skb->cb;	struct sock *newsk;	netdevice_t *dev; 	sdla_t *card;	mbox_cmd_t *mbox_ptr;	wanpipe_common_t *chan;	/* Find a free device, if none found, all svc's are busy          */	card = (sdla_t*)sk->protinfo.af_wanpipe->card;	if (!card){		printk(KERN_INFO "wansock: LISTEN ERROR, No Card\n");		return -ENODEV;	}		dev = wanpipe_find_free_dev(card);	if (!dev){		printk(KERN_INFO "wansock: LISTEN ERROR, No Free Device\n");		return -ENODEV;	}	chan=dev->priv;		chan->state = WANSOCK_CONNECTING;	/* Allocate a new sock, which accept will bind         * and pass up to the user 	 */	if ((newsk = wanpipe_make_new(sk)) == NULL){		release_device(dev);		return -ENOMEM;	}	/* Initialize the new sock structure 	 */	newsk->bound_dev_if = dev->ifindex;	newsk->protinfo.af_wanpipe->card = sk->protinfo.af_wanpipe->card;	/* Insert the sock into the main wanpipe         * sock list.         */	atomic_inc(&wanpipe_socks_nr);	/* Allocate and fill in the new Mail Box. Then         * bind the mail box to the sock. It will be          * used by the ioctl call to read call information         * and to execute commands.          */		if ((mbox_ptr = kmalloc(sizeof(mbox_cmd_t), GFP_ATOMIC)) == NULL) {		wanpipe_kill_sock_irq (newsk);		release_device(dev);				return -ENOMEM;	}	memset(mbox_ptr, 0, sizeof(mbox_cmd_t));	memcpy(mbox_ptr,skb->data,skb->len);	/* Register the lcn on which incoming call came         * from. Thus, if we have to clear it, we know         * whic lcn to clear 	 */ 	newsk->protinfo.af_wanpipe->lcn = mbox_ptr->cmd.lcn;	newsk->protinfo.af_wanpipe->mbox = (void *)mbox_ptr;	DBG_PRINTK(KERN_INFO "NEWSOCK : Device %s, bind to lcn %i\n",			dev->name,mbox_ptr->cmd.lcn);	chan->lcn = mbox_ptr->cmd.lcn;	card->u.x.svc_to_dev_map[(chan->lcn%MAX_X25_LCN)] = dev;	newsk->zapped=0;	newsk->num = htons(X25_PROT);	if (wanpipe_do_bind(newsk,dev,newsk->num)){		wanpipe_kill_sock_irq (newsk);		release_device(dev);		return -EINVAL;	}	newsk->state = WANSOCK_CONNECTING;	/* Fill in the standard sock address info */	sll->sll_family = AF_WANPIPE;	sll->sll_hatype = dev->type;	sll->sll_protocol = skb->protocol;	sll->sll_pkttype = skb->pkt_type;	sll->sll_ifindex = dev->ifindex;	sll->sll_halen = 0;	skb->dev = dev;	sk->ack_backlog++;	/* We must do this manually, since the sock_queue_rcv_skb()	 * function sets the skb->dev to NULL.  However, we use	 * the dev field in the accept function.*/ 	if (atomic_read(&sk->rmem_alloc) + skb->truesize >= 			(unsigned)sk->rcvbuf){         	wanpipe_unlink_driver(newsk);		wanpipe_kill_sock_irq (newsk);		--sk->ack_backlog;		return -ENOMEM;	}		skb_set_owner_r(skb, sk);	skb_queue_tail(&sk->receive_queue, skb);	sk->data_ready(sk,skb->len);		return 0;}/*============================================================ * wanpipe_make_new * *	Create a new sock, and allocate a wanpipe private *      structure to it. Also, copy the important data *      from the original sock to the new sock. * *      This function is used by wanpipe_listen_rcv() listen *      bottom half handler.  A copy of the listening sock *      is created using this function. * *===========================================================*/static struct sock *wanpipe_make_new(struct sock *osk){	struct sock *sk;	if (osk->type != SOCK_RAW)		return NULL;	if ((sk = wanpipe_alloc_socket()) == NULL)		return NULL;	sk->type        = osk->type;	sk->socket      = osk->socket;	sk->priority    = osk->priority;	sk->protocol    = osk->protocol;	sk->num		= osk->num;	sk->rcvbuf      = osk->rcvbuf;	sk->sndbuf      = osk->sndbuf;	sk->debug       = osk->debug;	sk->state       = WANSOCK_CONNECTING;	sk->sleep       = osk->sleep;	return sk;}/*============================================================ * wanpipe_make_new * *	Allocate memory for the a new sock, and sock *      private data.   *	 *	Increment the module use count. *       	 *      This function is used by wanpipe_create() and  *      wanpipe_make_new() functions.  * *===========================================================*/static struct sock *wanpipe_alloc_socket(void){	struct sock *sk;	struct wanpipe_opt *wan_opt;	if ((sk = sk_alloc(PF_WANPIPE, GFP_ATOMIC, 1)) == NULL)		return NULL;	if ((wan_opt = kmalloc(sizeof(struct wanpipe_opt), GFP_ATOMIC)) == NULL) {

⌨️ 快捷键说明

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