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

📄 af_wanpipe.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 5 页
字号:
}/*============================================================ * get_atomic_device *	 *	Sets a bit atomically which indicates that  *      the interface is taken. This avoids race conditions. *===========================================================*/static inline int get_atomic_device (netdevice_t *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 (netdevice_t *dev, sdla_t *card){	netdevice_t* tmp_dev;	for (tmp_dev = card->wandev.dev; tmp_dev; tmp_dev=*((netdevice_t**)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. *===========================================================*/netdevice_t * wanpipe_find_free_dev (sdla_t *card){	netdevice_t* 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=*((netdevice_t**)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;	sk->reuse = 1;	sock->ops = &wanpipe_ops;	sock_init_data(sock,sk);	sk->zapped=0;	sk->family = PF_WANPIPE;	sk->num = protocol;	sk->state = WANSOCK_DISCONNECTED;	sk->ack_backlog = 0;	sk->bound_dev_if=0;	atomic_inc(&wanpipe_socks_nr);		/* We must disable interrupts because the ISR	 * can also change the list */	set_bit(1,&wanpipe_tx_critical);	write_lock(&wanpipe_sklist_lock);	sk->next = wanpipe_sklist;	wanpipe_sklist = sk;	sock_hold(sk);	write_unlock(&wanpipe_sklist_lock);	clear_bit(1,&wanpipe_tx_critical);	return(0);}/*============================================================ *  wanpipe_recvmsg *	 *	Pull a packet from our receive queue and hand it  *      to the user. If necessary we block. *===========================================================*/static int wanpipe_recvmsg(struct socket *sock, struct msghdr *msg, int len,			  int flags, struct scm_cookie *scm){	struct sock *sk = sock->sk;	struct sk_buff *skb;	int copied, err=-ENOBUFS;	/*	 *	If the address length field is there to be filled in, we fill	 *	it in now.	 */	msg->msg_namelen = sizeof(struct wan_sockaddr_ll);	/*	 *	Call the generic datagram receiver. This handles all sorts	 *	of horrible races and re-entrancy so we can forget about it	 *	in the protocol layers.	 *	 *	Now it will return ENETDOWN, if device have just gone down,	 *	but then it will block.	 */	if (flags & MSG_OOB){			skb=skb_dequeue(&sk->error_queue);	}else{		skb=skb_recv_datagram(sk,flags,1,&err);	}	/*	 *	An error occurred so return it. Because skb_recv_datagram() 	 *	handles the blocking we don't see and worry about blocking	 *	retries.	 */	if(skb==NULL)		goto out;	/*	 *	You lose any data beyond the buffer you gave. If it worries a	 *	user program they can ask the device for its MTU anyway.	 */	copied = skb->len;	if (copied > len)	{		copied=len;		msg->msg_flags|=MSG_TRUNC;	}	wanpipe_wakeup_driver(sk);	/* We can't use skb_copy_datagram here */	err = memcpy_toiovec(msg->msg_iov, skb->data, copied);	if (err)		goto out_free;	#ifdef LINUX_2_1	sk->stamp=skb->stamp;#else	sock_recv_timestamp(msg, sk, skb);#endif		if (msg->msg_name)		memcpy(msg->msg_name, skb->cb, msg->msg_namelen);	/*	 *	Free or return the buffer as appropriate. Again this	 *	hides all the races and re-entrancy issues from us.	 */	err = (flags&MSG_TRUNC) ? skb->len : copied;out_free:	skb_free_datagram(sk, skb);out:	return err;}/*============================================================ *  wanpipe_wakeup_driver *	 * 	If socket receive buffer is full and driver cannot *      pass data up the sock, it sets a packet_block flag. *      This function check that flag and if sock receive  *      queue has room it kicks the driver BH handler.  * * 	This way, driver doesn't have to poll the sock  *      receive queue. *===========================================================*/static void wanpipe_wakeup_driver(struct sock *sk){	netdevice_t *dev=NULL;	wanpipe_common_t *chan=NULL;	dev = dev_get_by_index(sk->bound_dev_if);	if (!dev)		return;	dev_put(dev);	if ((chan = dev->priv) == NULL)		return;		if (atomic_read(&chan->receive_block)){  		if (atomic_read(&sk->rmem_alloc) < ((unsigned)sk->rcvbuf*0.9) ){			printk(KERN_INFO "wansock: Queuing task for wanpipe\n");			atomic_set(&chan->receive_block,0);			wanpipe_queue_tq(&chan->wanpipe_task);			wanpipe_mark_bh();		}	}	}	/*============================================================ *  wanpipe_getname *	 * 	I don't know what to do with this yet.  *      User can use this function to get sock address *      information. Not very useful for Sangoma's purposes. *===========================================================*/static int wanpipe_getname(struct socket *sock, struct sockaddr *uaddr,			  int *uaddr_len, int peer){	netdevice_t *dev;	struct sock *sk = sock->sk;	struct wan_sockaddr_ll *sll = (struct wan_sockaddr_ll*)uaddr;	sll->sll_family = AF_WANPIPE;	sll->sll_ifindex = sk->bound_dev_if;	sll->sll_protocol = sk->num;	dev = dev_get_by_index(sk->bound_dev_if);	if (dev) {		sll->sll_hatype = dev->type;		sll->sll_halen = dev->addr_len;		memcpy(sll->sll_addr, dev->dev_addr, dev->addr_len);	} else {		sll->sll_hatype = 0;	/* Bad: we have no ARPHRD_UNSPEC */		sll->sll_halen = 0;	}	*uaddr_len = sizeof(*sll);		dev_put(dev);		return 0;}/*============================================================ *  wanpipe_notifier *	 *	If driver turns off network interface, this function *      will be envoked. Currently I treate it as a  *      call disconnect. More thought should go into this *      function. * * FIXME: More thought should go into this function. * *===========================================================*/static int wanpipe_notifier(struct notifier_block *this, unsigned long msg, void *data){	struct sock *sk;	netdevice_t *dev = (netdevice_t*)data;	struct wanpipe_opt *po;	for (sk = wanpipe_sklist; sk; sk = sk->next) {		if ((po = sk->protinfo.af_wanpipe)==NULL)			continue;		if (dev == NULL)			continue;				switch (msg) {		case NETDEV_DOWN:		case NETDEV_UNREGISTER:			if (dev->ifindex == sk->bound_dev_if) {				printk(KERN_INFO "wansock: Device down %s\n",dev->name);				if (sk->zapped){					wanpipe_unlink_driver(sk);					sk->err = ENETDOWN;					sk->error_report(sk);				}				if (msg == NETDEV_UNREGISTER) {					printk(KERN_INFO "wansock: Unregistering Device: %s\n",						 	  dev->name);					wanpipe_unlink_driver(sk);					sk->bound_dev_if = 0;				}			}			break;		case NETDEV_UP:			if (dev->ifindex == sk->bound_dev_if && sk->num && !sk->zapped) {				printk(KERN_INFO "wansock: Registering Device: %s\n",						dev->name);				wanpipe_link_driver(dev,sk);			}			break;		}	}	return NOTIFY_DONE;}/*============================================================ *  wanpipe_ioctl *	 * 	Execute a user commands, and set socket options. * * FIXME: More thought should go into this function. * *===========================================================*/static int wanpipe_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg){	struct sock *sk = sock->sk;	int err;	int pid;	switch(cmd) 	{		case FIOSETOWN:		case SIOCSPGRP:			err = get_user(pid, (int *) arg);			if (err)				return err; 			if (current->pid != pid && current->pgrp != -pid && 			    !capable(CAP_NET_ADMIN))				return -EPERM;			sk->proc = pid;			return(0);		case FIOGETOWN:		case SIOCGPGRP:			return put_user(sk->proc, (int *)arg);		case SIOCGSTAMP:			if(sk->stamp.tv_sec==0)				return -ENOENT;			err = -EFAULT;			if (!copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)))				err = 0;			return err;		case SIOC_WANPIPE_CHECK_TX:			return atomic_read(&sk->wmem_alloc);		case SIOC_WANPIPE_SOCK_STATE:			if (sk->state == WANSOCK_CONNECTED)				return 0;						return 1;		case SIOC_WANPIPE_GET_CALL_DATA:			return get_ioctl_cmd (sk,(void*)arg);		case SIOC_WANPIPE_SET_CALL_DATA:			return set_ioctl_cmd (sk,(void*)arg);		case SIOC_WANPIPE_ACCEPT_CALL:		case SIOC_WANPIPE_CLEAR_CALL:		case SIOC_WANPIPE_RESET_CALL:			if ((err=set_ioctl_cmd(sk,(void*)arg)) < 0)				return err;			err=wanpipe_exec_cmd(sk,cmd,0);			get_ioctl_cmd(sk,(void*)arg);			return err;		case SIOC_WANPIPE_DEBUG:			return wanpipe_debug(sk,(void*)arg);			case SIOC_WANPIPE_SET_NONBLOCK:			if (sk->state != WANSOCK_DISCONNECTED)				return -EINVAL;			sock->file->f_flags |= O_NONBLOCK;			return 0;			case SIOCGIFFLAGS:#ifndef CONFIG_INET		case SIOCSIFFLAGS:#endif		case SIOCGIFCONF:		case SIOCGIFMETRIC:		case SIOCSIFMETRIC:		case SIOCGIFMEM:		case SIOCSIFMEM:		case SIOCGIFMTU:		case SIOCSIFMTU:		case SIOCSIFLINK:		case SIOCGIFHWADDR:		case SIOCSIFHWADDR:		case SIOCSIFMAP:		case SIOCGIFMAP:		case SIOCSIFSLAVE:		case SIOCGIFSLAVE:		case SIOCGIFINDEX:		case SIOCGIFNAME:		case SIOCGIFCOUNT:		case SIOCSIFHWBROADCAST:			return(dev_ioctl(cmd,(void *) arg));#ifdef CONFIG_INET		case SIOCADDRT:		case SIOCDELRT:		case SIOCDARP:		case SIOCGARP:		case SIOCSARP:		case SIOCDRARP:		case SIOCGRARP:		case SIOCSRARP:		case SIOCGIFADDR:		case SIOCSIFADDR:		case SIOCGIFBRDADDR:		case SIOCSIFBRDADDR:		case SIOCGIFNETMASK:		case SIOCSIFNETMASK:		case SIOCGIFDSTADDR:		case SIOCSIFDSTADDR:		case SIOCSIFFLAGS:		case SIOCADDDLCI:		case SIOCDELDLCI:			return inet_dgram_ops.ioctl(sock, cmd, arg);#endif		default:			if ((cmd >= SIOCDEVPRIVATE) &&			    (cmd <= (SIOCDEVPRIVATE + 15)))				return(dev_ioctl(cmd,(void *) arg));#ifdef CONFIG_NET_RADIO			if((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST))				return(dev_ioctl(cmd,(void *) arg));#endif			return -EOPNOTSUPP;	}	/*NOTREACHED*/}/*============================================================ *  wanpipe_debug *	 *	This function will pass up information about all *      active sockets. * * FIXME: More thought should go into this function. * *===========================================================*/static int wanpipe_debug (struct sock *origsk, void *arg){	struct sock *sk=NULL;	netdevice_t *dev=NULL;	wanpipe_common_t *chan=NULL;	int cnt=0, err=0;	wan_debug_t *dbg_data = (wan_debug_t *)arg;	for (sk = wanpipe_sklist; sk; sk = sk->next){		if (sk == origsk){			continue;		}

⌨️ 快捷键说明

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