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

📄 af_wanpipe.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
	sk->sk_reuse = 1;	sock->ops = &wanpipe_ops;	sock_init_data(sock,sk);	sk->sk_zapped	    = 0;	sk->sk_family	    = PF_WANPIPE;	wp_sk(sk)->num	    = protocol;	sk->sk_state	    = WANSOCK_DISCONNECTED;	sk->sk_ack_backlog  = 0;	sk->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_add_node(sk, &wanpipe_sklist);	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 kiocb *iocb, struct socket *sock,			   struct msghdr *msg, int len, int flags){	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->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;		sock_recv_timestamp(msg, sk, skb);		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){	struct net_device *dev = NULL;	wanpipe_common_t *chan=NULL;	dev = dev_get_by_index(sk->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->sk_rmem_alloc) <		    ((unsigned)sk->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){	struct net_device *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->sk_bound_dev_if;	sll->sll_protocol = wp_sk(sk)->num;	dev = dev_get_by_index(sk->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;	hlist_node *node;	struct net_device *dev = (struct net_device *)data;	sk_for_each(sk, node, &wanpipe_sklist) {		struct wanpipe_opt *po = wp_sk(sk);		if (!po)			continue;		if (dev == NULL)			continue;				switch (msg) {		case NETDEV_DOWN:		case NETDEV_UNREGISTER:			if (dev->ifindex == sk->sk_bound_dev_if) {				printk(KERN_INFO "wansock: Device down %s\n",dev->name);				if (sk->sk_zapped) {					wanpipe_unlink_driver(sk);					sk->sk_err = ENETDOWN;					sk->sk_error_report(sk);				}				if (msg == NETDEV_UNREGISTER) {					printk(KERN_INFO "wansock: Unregistering Device: %s\n",						 	  dev->name);					wanpipe_unlink_driver(sk);					sk->sk_bound_dev_if = 0;				}			}			break;		case NETDEV_UP:			if (dev->ifindex == sk->sk_bound_dev_if &&			    po->num && !sk->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;	switch(cmd) 	{		case SIOCGSTAMP:			return sock_get_timestamp(sk, (struct timeval __user *)arg);		case SIOC_WANPIPE_CHECK_TX:			return atomic_read(&sk->sk_wmem_alloc);		case SIOC_WANPIPE_SOCK_STATE:			if (sk->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->sk_state != WANSOCK_DISCONNECTED)				return -EINVAL;			sock->file->f_flags |= O_NONBLOCK;			return 0;	#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:			return inet_dgram_ops.ioctl(sock, cmd, arg);#endif		default:			return dev_ioctl(cmd,(void __user *) arg);	}	/*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;	struct hlist_node *node;	struct net_device *dev = NULL;	wanpipe_common_t *chan=NULL;	int cnt=0, err=0;	wan_debug_t *dbg_data = (wan_debug_t *)arg;	sk_for_each(sk, node, &wanpipe_sklist) {		wanpipe_opt *wp = wp_sk(sk);		if (sk == origsk){			continue;		}		if ((err=put_user(1, &dbg_data->debug[cnt].free)))			return err;		if ((err = put_user(sk->sk_state,				    &dbg_data->debug[cnt].state_sk)))			return err;		if ((err = put_user(sk->sk_rcvbuf,				    &dbg_data->debug[cnt].rcvbuf)))			return err;		if ((err = put_user(atomic_read(&sk->sk_rmem_alloc),				    &dbg_data->debug[cnt].rmem)))			return err;		if ((err = put_user(atomic_read(&sk->sk_wmem_alloc),				    &dbg_data->debug[cnt].wmem)))			return err;		if ((err = put_user(sk->sk_sndbuf,				    &dbg_data->debug[cnt].sndbuf)))			return err;		if ((err=put_user(sk_count, &dbg_data->debug[cnt].sk_count)))			return err;		if ((err=put_user(wp->poll_cnt, &dbg_data->debug[cnt].poll_cnt)))			return err;		if ((err = put_user(sk->sk_bound_dev_if,				    &dbg_data->debug[cnt].bound)))			return err;		if (sk->sk_bound_dev_if) {			dev = dev_get_by_index(sk->sk_bound_dev_if);			if (!dev)					continue;			chan=dev->priv;			dev_put(dev);				if ((err=put_user(chan->state, &dbg_data->debug[cnt].d_state)))				return err;			if ((err=put_user(chan->svc, &dbg_data->debug[cnt].svc)))				return err;			if ((err=put_user(atomic_read(&chan->command), 						&dbg_data->debug[cnt].command)))				return err;			if (wp){				sdla_t *card = (sdla_t*)wp->card;								if (card){					if ((err=put_user(atomic_read(&card->u.x.command_busy), 								&dbg_data->debug[cnt].cmd_busy)))						return err;				}				if ((err=put_user(wp->lcn, 						  &dbg_data->debug[cnt].lcn)))					return err;								if (wp->mbox) {					if ((err=put_user(1, &dbg_data->debug[cnt].mbox)))						return err;				}			}			if ((err=put_user(atomic_read(&chan->receive_block), 								&dbg_data->debug[cnt].rblock)))				return err;			if (copy_to_user(dbg_data->debug[cnt].name, dev->name, strlen(dev->name)))				return -EFAULT;		}			if (++cnt == MAX_NUM_DEBUG)			break;	}	return 0;}/*============================================================ *  get_ioctl_cmd *	 *	Pass up the contents of socket MBOX to the user. *===========================================================*/static int get_ioctl_cmd (struct sock *sk, void *arg){	x25api_t *usr_data = (x25api_t *)arg;	mbox_cmd_t *mbox_ptr;	int err;	if (usr_data == NULL)		return -EINVAL;	if (!wp_sk(sk)->mbox) {		return -EINVAL;	}	mbox_ptr = (mbox_cmd_t *)wp_sk(sk)->mbox;	if ((err=put_user(mbox_ptr->cmd.qdm, &usr_data->hdr.qdm)))		return err;	if ((err=put_user(mbox_ptr->cmd.cause, &usr_data->hdr.cause)))		return err;	if ((err=put_user(mbox_ptr->cmd.diagn, &usr_data->hdr.diagn)))		return err;	if ((err=put_user(mbox_ptr->cmd.length, &usr_data->hdr.length)))		return err;	if ((err=put_user(mbox_ptr->cmd.result, &usr_data->hdr.result)))		return err;	if ((err=put_user(mbox_ptr->cmd.lcn, &usr_data->hdr.lcn)))		return err;		if (mbox_ptr->cmd.length > 0){		if (mbox_ptr->cmd.length > X25_MAX_DATA)			return -EINVAL;		if (copy_to_user(usr_data->data, mbox_ptr->data, mbox_ptr->cmd.length)){			printk(KERN_INFO "wansock: Copy failed !!!\n");			return -EFAULT;		}	}	return 0;} /*============================================================ *  set_ioctl_cmd *	 *	Before command can be execute, socket MBOX must *      be created, and initialized with user data.	 *===========================================================*/static int set_ioctl_cmd (struct sock *sk, void *arg){	x25api_t *usr_data = (x25api_t *)arg;	mbox_cmd_t *mbox_ptr;	int err;	if (!wp_sk(sk)->mbox) {		void *mbox_ptr;		struct net_device *dev = dev_get_by_index(sk->sk_bound_dev_if);		if (!dev)			return -ENODEV;		dev_put(dev);				if ((mbox_ptr = kmalloc(sizeof(mbox_cmd_t), GFP_ATOMIC)) == NULL)			return -ENOMEM;		memset(mbox_ptr, 0, sizeof(mbox_cmd_t));		wp_sk(sk)->mbox = mbox_ptr;		wanpipe_link_driver(dev,sk);	}

⌨️ 快捷键说明

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