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

📄 af_wanpipe.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
			atomic_read(&sk->sk_rmem_alloc),			atomic_read(&sk->sk_wmem_alloc));		sk->sk_timer.data	= (unsigned long)sk;		sk->sk_timer.expires	= jiffies + HZ;		sk->sk_timer.function	= wanpipe_destroy_timer;		add_timer(&sk->sk_timer);		return 0;	}	kfree(wp);	wp_sk(sk) = NULL;	if (atomic_read(&sk->sk_refcnt) != 1) {		DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i !:release.\n",					atomic_read(&sk->sk_refcnt));		atomic_set(&sk->sk_refcnt, 1);	}	sock_put(sk);	atomic_dec(&wanpipe_socks_nr);	return 0;}/*============================================================ * check_write_queue * *  	During sock shutdown, if the sock state is  *      WANSOCK_CONNECTED and there is transmit data  *      pending. Wait until data is released  *      before proceeding. *===========================================================*/static void check_write_queue(struct sock *sk){	if (sk->sk_state != WANSOCK_CONNECTED)		return;	if (!atomic_read(&sk->sk_wmem_alloc))		return;	printk(KERN_INFO "wansock: MAJOR ERROR, Data lost on sock release !!!\n");}/*============================================================ * release_driver * *	This function is called during sock shutdown, to  *      release any resources and links that bind the sock *      to the driver.  It also changes the state of the *      sock to WANSOCK_DISCONNECTED *===========================================================*/static void release_driver(struct sock *sk){	wanpipe_opt *wp;	struct sk_buff *skb=NULL;	struct sock *deadsk=NULL;	if (sk->sk_state == WANSOCK_LISTEN ||	    sk->sk_state == WANSOCK_BIND_LISTEN) {		while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {			if ((deadsk = get_newsk_from_skb(skb))){				DBG_PRINTK (KERN_INFO "wansock: RELEASE: FOUND DEAD SOCK\n");				sock_set_flag(deadsk, SOCK_DEAD);				start_cleanup_timer(deadsk);			}			kfree_skb(skb);		}		if (sk->sk_zapped)			wanpipe_unlink_card(sk);	}else{		if (sk->sk_zapped)			wanpipe_unlink_driver(sk);	}	sk->sk_state	    = WANSOCK_DISCONNECTED;	sk->sk_bound_dev_if = 0;	sk->sk_zapped	    = 0;	wp = wp_sk(sk);	if (wp && wp->mbox) {		kfree(wp->mbox);		wp->mbox = NULL;	}}/*============================================================ *  start_cleanup_timer * *  	If new incoming call's are pending but the socket *      is being released, start the timer which will  *      envoke the kill routines for pending socks. *===========================================================*/static void start_cleanup_timer (struct sock *sk){	del_timer(&sk->sk_timer);	sk->sk_timer.data	= (unsigned long)sk;	sk->sk_timer.expires	= jiffies + HZ;	sk->sk_timer.function	= wanpipe_kill_sock_timer;	add_timer(&sk->sk_timer);}/*============================================================ *  wanpipe_kill_sock * *	This is a function which performs actual killing *      of the sock.  It releases socket resources, *      and unlinks the sock from the driver.  *===========================================================*/static void wanpipe_kill_sock_timer (unsigned long data){	struct sock *sk = (struct sock *)data;	struct sock **skp;	if (!sk)		return;	/* This function can be called from interrupt. We must use	 * appropriate locks */		if (test_bit(1,&wanpipe_tx_critical)){		sk->sk_timer.expires = jiffies + 10;		add_timer(&sk->sk_timer);		return;	}		write_lock(&wanpipe_sklist_lock);	sk_del_node_init(sk);	write_unlock(&wanpipe_sklist_lock);	if (wp_sk(sk)->num == htons(X25_PROT) &&	    sk->sk_state != WANSOCK_DISCONNECTED) {		struct net_device *dev = dev_get_by_index(sk->sk_bound_dev_if);		wanpipe_common_t *chan;		if (dev){			chan=dev->priv;			atomic_set(&chan->disconnect,1);			dev_put(dev);		}		}	release_driver(sk);	sk->sk_socket = NULL;	/* Purge queues */	skb_queue_purge(&sk->sk_receive_queue);	skb_queue_purge(&sk->sk_write_queue);	skb_queue_purge(&sk->sk_error_queue);		if (atomic_read(&sk->sk_rmem_alloc) ||	    atomic_read(&sk->sk_wmem_alloc)) {		del_timer(&sk->sk_timer);		printk(KERN_INFO "wansock: Killing SOCK in Timer\n");		sk->sk_timer.data	= (unsigned long)sk;		sk->sk_timer.expires	= jiffies + HZ;		sk->sk_timer.function	= wanpipe_destroy_timer;		add_timer(&sk->sk_timer);		return;	}	if (wp_sk(sk)) {		kfree(wp_sk(sk));		wp_sk(sk) = NULL;	}	if (atomic_read(&sk->sk_refcnt) != 1) {		atomic_set(&sk->sk_refcnt, 1);		DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i ! :timer.\n",					atomic_read(&sk->sk_refcnt));	}	sock_put(sk);	atomic_dec(&wanpipe_socks_nr);	return;}static void wanpipe_kill_sock_accept (struct sock *sk){	struct sock **skp;	if (!sk)		return;	/* This function can be called from interrupt. We must use	 * appropriate locks */		write_lock(&wanpipe_sklist_lock);	sk_del_node_init(sk);	write_unlock(&wanpipe_sklist_lock);	sk->sk_socket = NULL;	if (wp_sk(sk)) {		kfree(wp_sk(sk));		wp_sk(sk) = NULL;	}	if (atomic_read(&sk->sk_refcnt) != 1) {		atomic_set(&sk->sk_refcnt, 1);		DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i ! :timer.\n",					atomic_read(&sk->sk_refcnt));	}	sock_put(sk);	atomic_dec(&wanpipe_socks_nr);	return;}static void wanpipe_kill_sock_irq (struct sock *sk){	if (!sk)		return;	sk->sk_socket = NULL;	if (wp_sk(sk)) {		kfree(wp_sk(sk));		wp_sk(sk) = NULL;	}	if (atomic_read(&sk->sk_refcnt) != 1) {		atomic_set(&sk->sk_refcnt, 1);		DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i !:listen.\n",					atomic_read(&sk->sk_refcnt));	}	sock_put(sk);	atomic_dec(&wanpipe_socks_nr);}/*============================================================ *  wanpipe_do_bind * * 	Bottom half of the binding system call. *      Once the wanpipe_bind() function checks  the *      legality of the call, this function binds the *      sock to the driver. *===========================================================*/static int wanpipe_do_bind(struct sock *sk, struct net_device *dev,			   int protocol){	wanpipe_opt *wp = wp_sk(sk);	wanpipe_common_t *chan=NULL;	int err=0;	if (sk->sk_zapped) {		err = -EALREADY;		goto bind_unlock_exit;	}	wp->num = protocol;	if (protocol == 0){		release_device(dev);		err = -EINVAL;		goto bind_unlock_exit;	}	if (dev) {		if (dev->flags&IFF_UP) {			chan=dev->priv;			sk->sk_state = chan->state;			if (wp->num == htons(X25_PROT) && 			    sk->sk_state != WANSOCK_DISCONNECTED && 			    sk->sk_state != WANSOCK_CONNECTING) {				DBG_PRINTK(KERN_INFO 					"wansock: Binding to Device not DISCONNECTED %i\n",						sk->sk_state);				release_device(dev);				err = -EAGAIN;				goto bind_unlock_exit;			}			wanpipe_link_driver(dev,sk);			sk->sk_bound_dev_if = dev->ifindex;			/* X25 Specific option */			if (wp->num == htons(X25_PROT))				wp_sk(sk)->svc = chan->svc;		} else {			sk->sk_err = ENETDOWN;			sk->sk_error_report(sk);			release_device(dev);			err = -EINVAL;		}	} else {		err = -ENODEV;	}bind_unlock_exit:	/* FIXME where is this lock */	return err;}/*============================================================ *  wanpipe_bind * *      BIND() System call, which is bound to the AF_WANPIPE *      operations structure.  It checks for correct wanpipe *      card name, and cross references interface names with *      the card names.  Thus, interface name must belong to *      the actual card. *===========================================================*/static int wanpipe_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len){	struct wan_sockaddr_ll *sll = (struct wan_sockaddr_ll*)uaddr;	struct sock *sk=sock->sk;	wanpipe_opt *wp = wp_sk(sk);	struct net_device *dev = NULL;	sdla_t *card=NULL;	char name[15];	/*	 *	Check legality	 */	 	if (addr_len < sizeof(struct wan_sockaddr_ll)){		printk(KERN_INFO "wansock: Address length error\n");		return -EINVAL;	}	if (sll->sll_family != AF_WANPIPE){		printk(KERN_INFO "wansock: Illegal family name specified.\n");		return -EINVAL;	}	card = wanpipe_find_card (sll->sll_card);	if (!card){		printk(KERN_INFO "wansock: Wanpipe card not found: %s\n",sll->sll_card);		return -ENODEV;	}else{		wp_sk(sk)->card = (void *)card;	}	if (!strcmp(sll->sll_device,"svc_listen")){		/* Bind a sock to a card structure for listening 		 */				int err=0; 		/* This is x25 specific area if protocol doesn't                 * match, return error */		if (sll->sll_protocol != htons(X25_PROT))			return -EINVAL;		err= wanpipe_link_card (sk);		if (err < 0)			return err;		if (sll->sll_protocol)			wp->num = sll->sll_protocol;		sk->sk_state = WANSOCK_BIND_LISTEN;		return 0;	}else if (!strcmp(sll->sll_device,"svc_connect")){ 		/* This is x25 specific area if protocol doesn't                 * match, return error */		if (sll->sll_protocol != htons(X25_PROT))			return -EINVAL;		/* Find a free device 		 */		dev = wanpipe_find_free_dev(card);		if (dev == NULL){			DBG_PRINTK(KERN_INFO "wansock: No free network devices for card %s\n",				card->devname);			return -EINVAL;		}	}else{		/* Bind a socket to a interface name                  * This is used by PVC mostly                 */		strlcpy(name,sll->sll_device,sizeof(name));		dev = dev_get_by_name(name);		if (dev == NULL){			printk(KERN_INFO "wansock: Failed to get Dev from name: %s,\n",					name);			return -ENODEV;		}		dev_put(dev);		if (check_dev(dev, card)){			printk(KERN_INFO "wansock: Device %s, doesn't belong to card %s\n",				dev->name, card->devname);			return -EINVAL;		}		if (get_atomic_device (dev))			return -EINVAL;	}	return wanpipe_do_bind(sk, dev, sll->sll_protocol ? : wp->num);}/*============================================================ * get_atomic_device *	 *	Sets a bit atomically which indicates that  *      the interface is taken. This avoids race conditions. *===========================================================*/static inline int get_atomic_device(struct net_device *dev){	wanpipe_common_t *chan = dev->priv;	if (!test_and_set_bit(0,(void *)&chan->rw_bind)){		return 0;	}	return 1;}/*============================================================ * check_dev *	 *  	Check that device name belongs to a particular card. *===========================================================*/static int check_dev(struct net_device *dev, sdla_t *card){	struct net_device* tmp_dev;	for (tmp_dev = card->wandev.dev; tmp_dev;	     tmp_dev = *((struct net_device **)tmp_dev->priv)) {		if (tmp_dev->ifindex == dev->ifindex){ 			return 0;			}	}	return 1;}/*============================================================ *  wanpipe_find_free_dev *	 *	Find a free network interface. If found set atomic *      bit indicating that the interface is taken. *      X25API Specific. *===========================================================*/struct net_device *wanpipe_find_free_dev(sdla_t *card){	struct net_device* dev;	volatile wanpipe_common_t *chan;	if (test_and_set_bit(0,&find_free_critical)){		printk(KERN_INFO "CRITICAL in Find Free\n");	}		for (dev = card->wandev.dev; dev;	     dev = *((struct net_device **)dev->priv)) {		chan = dev->priv;		if (!chan) 			continue;		if (chan->usedby == API && chan->svc){			if (!get_atomic_device (dev)){				if (chan->state != WANSOCK_DISCONNECTED){					release_device(dev);				}else{					clear_bit(0,&find_free_critical);					return dev;				}			}		}	}	clear_bit(0,&find_free_critical);	return NULL;}/*============================================================ *  wanpipe_create *	 * 	SOCKET() System call.  It allocates a sock structure *      and adds the socket to the wanpipe_sk_list.  *      Crates AF_WANPIPE socket. *===========================================================*/static int wanpipe_create(struct socket *sock, int protocol){	struct sock *sk;		//FIXME: This checks for root user, SECURITY ?	//if (!capable(CAP_NET_RAW))	//	return -EPERM;	if (sock->type != SOCK_DGRAM && sock->type != SOCK_RAW)		return -ESOCKTNOSUPPORT;	sock->state = SS_UNCONNECTED;	if ((sk = wanpipe_alloc_socket()) == NULL)		return -ENOBUFS;

⌨️ 快捷键说明

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