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

📄 af_wanpipe.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 5 页
字号:
	set_bit(1,&wanpipe_tx_critical);	write_lock(&wanpipe_sklist_lock);	for (skp = &wanpipe_sklist; *skp; skp = &(*skp)->next) {		if (*skp == sk) {			*skp = sk->next;			__sock_put(sk);			break;		}	}	write_unlock(&wanpipe_sklist_lock);	clear_bit(1,&wanpipe_tx_critical);		release_driver(sk);		/*	 *	Now the socket is dead. No more input will appear.	 */	sk->state_change(sk);	/* It is useless. Just for sanity. */	sock->sk = NULL;	sk->socket = NULL;	sk->dead = 1;	/* Purge queues */#ifdef LINUX_2_4	skb_queue_purge(&sk->receive_queue);	skb_queue_purge(&sk->write_queue);	skb_queue_purge(&sk->error_queue);#else		while ((skb=skb_dequeue(&sk->receive_queue))!=NULL){		kfree_skb(skb);	}	while ((skb=skb_dequeue(&sk->error_queue))!=NULL){		kfree_skb(skb);	}	while ((skb=skb_dequeue(&sk->write_queue))!=NULL){		kfree_skb(skb);	}#endif		if (atomic_read(&sk->rmem_alloc) || atomic_read(&sk->wmem_alloc)) {		del_timer(&sk->timer);		printk(KERN_INFO "wansock: Killing in Timer R %i , W %i\n",			atomic_read(&sk->rmem_alloc),atomic_read(&sk->wmem_alloc));		sk->timer.data=(unsigned long)sk;		sk->timer.expires=jiffies+HZ;		sk->timer.function=wanpipe_destroy_timer;		add_timer(&sk->timer);		return 0;	}	if (sk->protinfo.af_wanpipe){		kfree(sk->protinfo.af_wanpipe);		sk->protinfo.af_wanpipe=NULL;	}      #ifdef LINUX_2_4	if (atomic_read(&sk->refcnt) != 1){		DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i !:release.\n",					atomic_read(&sk->refcnt));		atomic_set(&sk->refcnt,1);	}	sock_put(sk);      #else		sk_free(sk);      #endif	atomic_dec(&wanpipe_socks_nr);	MOD_DEC_USE_COUNT;	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->state != WANSOCK_CONNECTED)		return;	if (!atomic_read(&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){	struct sk_buff *skb=NULL;	struct sock *deadsk=NULL;	if (sk->state == WANSOCK_LISTEN || sk->state == WANSOCK_BIND_LISTEN){		while ((skb=skb_dequeue(&sk->receive_queue))!=NULL){			if ((deadsk = get_newsk_from_skb(skb))){				DBG_PRINTK (KERN_INFO "wansock: RELEASE: FOUND DEAD SOCK\n");				deadsk->dead=1;				start_cleanup_timer(deadsk);			}			kfree_skb(skb);		}		if (sk->zapped)			wanpipe_unlink_card(sk);	}else{		if (sk->zapped)			wanpipe_unlink_driver(sk);	}	sk->state = WANSOCK_DISCONNECTED;	sk->bound_dev_if = 0;	sk->zapped=0;	if (sk->protinfo.af_wanpipe){		if (sk->protinfo.af_wanpipe->mbox){			kfree(sk->protinfo.af_wanpipe->mbox);			sk->protinfo.af_wanpipe->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->timer);	sk->timer.data = (unsigned long)sk;	sk->timer.expires = jiffies + HZ;	sk->timer.function = wanpipe_kill_sock_timer;	add_timer(&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;#ifndef LINUX_2_4	struct sk_buff *skb;#endif	struct sock **skp;	if (!sk)		return;	/* This functin can be called from interrupt. We must use	 * appropriate locks */		if (test_bit(1,&wanpipe_tx_critical)){		sk->timer.expires=jiffies+10;		add_timer(&sk->timer);		return;	}		write_lock(&wanpipe_sklist_lock);	for (skp = &wanpipe_sklist; *skp; skp = &(*skp)->next) {		if (*skp == sk) {			*skp = sk->next;			__sock_put(sk);			break;		}	}	write_unlock(&wanpipe_sklist_lock);	if (sk->num == htons(X25_PROT) && sk->state != WANSOCK_DISCONNECTED){		netdevice_t *dev = dev_get_by_index(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->socket = NULL;	/* Purge queues */#ifdef LINUX_2_4	skb_queue_purge(&sk->receive_queue);	skb_queue_purge(&sk->write_queue);	skb_queue_purge(&sk->error_queue);#else		while ((skb=skb_dequeue(&sk->receive_queue)) != NULL){		kfree_skb(skb);	}	while ((skb=skb_dequeue(&sk->write_queue)) != NULL) {		kfree_skb(skb);	}	while ((skb=skb_dequeue(&sk->error_queue)) != NULL){		kfree_skb(skb);	}#endif		if (atomic_read(&sk->rmem_alloc) || atomic_read(&sk->wmem_alloc)) {		del_timer(&sk->timer);		printk(KERN_INFO "wansock: Killing SOCK in Timer\n");		sk->timer.data=(unsigned long)sk;		sk->timer.expires=jiffies+HZ;		sk->timer.function=wanpipe_destroy_timer;		add_timer(&sk->timer);		return;	}	if (sk->protinfo.af_wanpipe){		kfree(sk->protinfo.af_wanpipe);		sk->protinfo.af_wanpipe=NULL;	}      #ifdef LINUX_2_4	if (atomic_read(&sk->refcnt) != 1){		atomic_set(&sk->refcnt,1);		DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i ! :timer.\n",					atomic_read(&sk->refcnt));	}	sock_put(sk);      #else	sk_free(sk);      #endif	atomic_dec(&wanpipe_socks_nr);	MOD_DEC_USE_COUNT;	return;}static void wanpipe_kill_sock_accept (struct sock *sk){	struct sock **skp;	if (!sk)		return;	/* This functin can be called from interrupt. We must use	 * appropriate locks */		write_lock(&wanpipe_sklist_lock);	for (skp = &wanpipe_sklist; *skp; skp = &(*skp)->next) {		if (*skp == sk) {			*skp = sk->next;			__sock_put(sk);			break;		}	}	write_unlock(&wanpipe_sklist_lock);	sk->socket = NULL;	if (sk->protinfo.af_wanpipe){		kfree(sk->protinfo.af_wanpipe);		sk->protinfo.af_wanpipe=NULL;	}      #ifdef LINUX_2_4	if (atomic_read(&sk->refcnt) != 1){		atomic_set(&sk->refcnt,1);		DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i ! :timer.\n",					atomic_read(&sk->refcnt));	}	sock_put(sk);      #else	sk_free(sk);      #endif	atomic_dec(&wanpipe_socks_nr);	MOD_DEC_USE_COUNT;	return;}static void wanpipe_kill_sock_irq (struct sock *sk){	if (!sk)		return;	sk->socket = NULL;	if (sk->protinfo.af_wanpipe){		kfree(sk->protinfo.af_wanpipe);		sk->protinfo.af_wanpipe=NULL;	}      #ifdef LINUX_2_4	if (atomic_read(&sk->refcnt) != 1){		atomic_set(&sk->refcnt,1);		DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i !:listen.\n",					atomic_read(&sk->refcnt));	}	sock_put(sk);      #else	sk_free(sk);      #endif	atomic_dec(&wanpipe_socks_nr);	MOD_DEC_USE_COUNT;	return;}/*============================================================ *  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, netdevice_t *dev, int protocol){	wanpipe_common_t *chan=NULL;	int err=0;	if (sk->zapped){		err = -EALREADY;		goto bind_unlock_exit;	}	sk->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->state = chan->state;			if (sk->num == htons(X25_PROT) && 			    sk->state != WANSOCK_DISCONNECTED && 			    sk->state != WANSOCK_CONNECTING){				DBG_PRINTK(KERN_INFO 					"wansock: Binding to Device not DISCONNECTED %i\n",						sk->state);				release_device(dev);				err = -EAGAIN;				goto bind_unlock_exit;			}			wanpipe_link_driver(dev,sk);			sk->bound_dev_if = dev->ifindex;			/* X25 Specific option */			if (sk->num == htons(X25_PROT))				sk->protinfo.af_wanpipe->svc = chan->svc;		} else {			sk->err = ENETDOWN;			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;	netdevice_t *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{		sk->protinfo.af_wanpipe->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)			sk->num = sll->sll_protocol;		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                 */		strncpy(name,sll->sll_device,14);		name[14]=0;#ifdef LINUX_2_4		dev = dev_get_by_name(name);#else		dev = dev_get(name);#endif		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 ? : sk->num);

⌨️ 快捷键说明

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