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

📄 af_wanpipe.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
	mbox_ptr = (mbox_cmd_t*)wp_sk(sk)->mbox;	memset(mbox_ptr, 0, sizeof(mbox_cmd_t));	if (usr_data == NULL){		return 0;	}	if ((err=get_user(mbox_ptr->cmd.qdm, &usr_data->hdr.qdm)))		return err;	if ((err=get_user(mbox_ptr->cmd.cause, &usr_data->hdr.cause)))		return err;	if ((err=get_user(mbox_ptr->cmd.diagn, &usr_data->hdr.diagn)))		return err;	if ((err=get_user(mbox_ptr->cmd.length, &usr_data->hdr.length)))		return err;	if ((err=get_user(mbox_ptr->cmd.result, &usr_data->hdr.result)))		return err;	if (mbox_ptr->cmd.length > 0){		if (mbox_ptr->cmd.length > X25_MAX_DATA)			return -EINVAL;		if (copy_from_user(mbox_ptr->data, usr_data->data, mbox_ptr->cmd.length)){			printk(KERN_INFO "Copy failed\n");			return -EFAULT;		}	}	return 0;}/*====================================================================== * wanpipe_poll * *	Datagram poll: Again totally generic. This also handles *	sequenced packet sockets providing the socket receive queue *	is only ever holding data ready to receive. * *	Note: when you _don't_ use this routine for this protocol, *	and you use a different write policy from sock_writeable() *	then please supply your own write_space callback. *=====================================================================*/unsigned int wanpipe_poll(struct file * file, struct socket *sock, poll_table *wait){	struct sock *sk = sock->sk;	unsigned int mask;	++wp_sk(sk)->poll_cnt;	poll_wait(file, sk->sk_sleep, wait);	mask = 0;	/* exceptional events? */	if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) {		mask |= POLLPRI;		return mask;	}	if (sk->sk_shutdown & RCV_SHUTDOWN)		mask |= POLLHUP;	/* readable? */	if (!skb_queue_empty(&sk->sk_receive_queue)) {		mask |= POLLIN | POLLRDNORM;	}	/* connection hasn't started yet */	if (sk->sk_state == WANSOCK_CONNECTING) {		return mask;	}	if (sk->sk_state == WANSOCK_DISCONNECTED) {		mask = POLLPRI;		return mask;	}	/* This check blocks the user process if there is   	 * a packet already queued in the socket write queue.         * This option is only for X25API protocol, for other         * protocol like chdlc enable streaming mode,          * where multiple packets can be pending in the socket          * transmit queue */	if (wp_sk(sk)->num == htons(X25_PROT)) {		if (atomic_read(&wp_sk(sk)->packet_sent))			return mask;	}	/* writable? */	if (sock_writeable(sk)){		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;	}else{		set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);	}			return mask;}/*====================================================================== * wanpipe_listen * *	X25API Specific function. Set a socket into LISTENING  MODE. *=====================================================================*/static int wanpipe_listen(struct socket *sock, int backlog){	struct sock *sk = sock->sk; 	/* This is x25 specific area if protocol doesn't         * match, return error */	if (wp_sk(sk)->num != htons(X25_PROT))		return -EINVAL;	if (sk->sk_state == WANSOCK_BIND_LISTEN) {		sk->sk_max_ack_backlog = backlog;		sk->sk_state           = WANSOCK_LISTEN;		return 0;	}else{		printk(KERN_INFO "wansock: Listening sock was not binded\n");	}	return -EINVAL;}/*====================================================================== * wanpipe_link_card * *	Connects the listening socket to the driver *=====================================================================*/static int wanpipe_link_card (struct sock *sk){	sdla_t *card = (sdla_t*)wp_sk(sk)->card;	if (!card)		return -ENOMEM;	if ((card->sk != NULL) || (card->func != NULL)){		printk(KERN_INFO "wansock: Listening queue is already established\n");		return -EINVAL;	}	card->sk=sk;	card->func=wanpipe_listen_rcv;	sk->sk_zapped = 1; 	return 0;}/*====================================================================== * wanpipe_listen * *	X25API Specific function. Disconnect listening socket from *      the driver. *=====================================================================*/static void wanpipe_unlink_card (struct sock *sk){	sdla_t *card = (sdla_t*)wp_sk(sk)->card; 	if (card){		card->sk=NULL;		card->func=NULL;	}}/*====================================================================== * wanpipe_exec_cmd * *	Ioctl function calls this function to execute user command. *      Connect() sytem call also calls this function to execute *      place call.  This function blocks until command is executed. *=====================================================================*/static int wanpipe_exec_cmd(struct sock *sk, int cmd, unsigned int flags){	int err = -EINVAL;	wanpipe_opt *wp = wp_sk(sk);	mbox_cmd_t *mbox_ptr = (mbox_cmd_t*)wp->mbox;	if (!mbox_ptr){		printk(KERN_INFO "NO MBOX PTR !!!!!\n");		return -EINVAL;	}		/* This is x25 specific area if protocol doesn't         * match, return error */	if (wp->num != htons(X25_PROT))		return -EINVAL;	switch (cmd){		case SIOC_WANPIPE_ACCEPT_CALL:			if (sk->sk_state != WANSOCK_CONNECTING) {				err = -EHOSTDOWN;				break;			}						err = execute_command(sk,X25_ACCEPT_CALL,0);			if (err < 0)				break;			/* Update. Mar6 2000.                          * Do not set the sock lcn number here, since                         * it is done in wanpipe_listen_rcv().                          */ 		 	if (sk->sk_state == WANSOCK_CONNECTED) {				wp->lcn = ((mbox_cmd_t*)wp->mbox)->cmd.lcn;					DBG_PRINTK(KERN_INFO "\nwansock: Accept OK %i\n",					wp->lcn);				err = 0;			}else{				DBG_PRINTK (KERN_INFO "\nwansock: Accept Failed %i\n",					wp->lcn);				wp->lcn = 0;				err = -ECONNREFUSED;			}			break;		case SIOC_WANPIPE_CLEAR_CALL:			if (sk->sk_state == WANSOCK_DISCONNECTED) {				err = -EINVAL;				break;			}			/* Check if data buffers are pending for transmission,                         * if so, check whether user wants to wait until data                         * is transmitted, or clear a call and drop packets */                          			if (atomic_read(&sk->sk_wmem_alloc) ||			    check_driver_busy(sk)) {			  	mbox_cmd_t *mbox = wp->mbox;				if (mbox->cmd.qdm & 0x80){					mbox->cmd.result = 0x35;					err = -EAGAIN;						break;				}			}			sk->sk_state = WANSOCK_DISCONNECTING;			err = execute_command(sk,X25_CLEAR_CALL,0);			if (err < 0)				break;			err = -ECONNREFUSED;			if (sk->sk_state == WANSOCK_DISCONNECTED) {				DBG_PRINTK(KERN_INFO "\nwansock: CLEAR OK %i\n",					   wp->lcn);				wp->lcn = 0;				err = 0;			}			break;		case SIOC_WANPIPE_RESET_CALL:			if (sk->sk_state != WANSOCK_CONNECTED) {				err = -EINVAL;				break;			}			/* Check if data buffers are pending for transmission,                         * if so, check whether user wants to wait until data                         * is transmitted, or reset a call and drop packets */                          			if (atomic_read(&sk->sk_wmem_alloc) ||			    check_driver_busy(sk)) {			  	mbox_cmd_t *mbox = wp->mbox;				if (mbox->cmd.qdm & 0x80){					mbox->cmd.result = 0x35;					err = -EAGAIN;						break;				}			}			err = execute_command(sk, X25_RESET,0);			if (err < 0)				break;			err = mbox_ptr->cmd.result;			break;		case X25_PLACE_CALL:			err=execute_command(sk,X25_PLACE_CALL,flags);			if (err < 0)				break;			if (sk->sk_state == WANSOCK_CONNECTED) {				wp->lcn = ((mbox_cmd_t*)wp->mbox)->cmd.lcn;					DBG_PRINTK(KERN_INFO "\nwansock: PLACE CALL OK %i\n",					wp->lcn);				err = 0;			} else if (sk->sk_state == WANSOCK_CONNECTING &&				   (flags & O_NONBLOCK)) {				wp->lcn = ((mbox_cmd_t*)wp->mbox)->cmd.lcn;				DBG_PRINTK(KERN_INFO "\nwansock: Place Call OK: Waiting %i\n",					wp->lcn);				err = 0;			}else{				DBG_PRINTK(KERN_INFO "\nwansock: Place call Failed\n");				err = -ECONNREFUSED;			}			break;		default: 			return -EINVAL;	}	return err;}static int check_driver_busy (struct sock *sk){	struct net_device *dev = dev_get_by_index(sk->sk_bound_dev_if);	wanpipe_common_t *chan;	if (!dev)		return 0;	dev_put(dev);	if ((chan=dev->priv) == NULL)		return 0;	return atomic_read(&chan->driver_busy);}/*====================================================================== * wanpipe_accept * *	ACCEPT() System call.	X25API Specific function.  *	For each incoming call, create a new socket and  *      return it to the user.	 *=====================================================================*/static int wanpipe_accept(struct socket *sock, struct socket *newsock, int flags){	struct sock *sk;	struct sock *newsk;	struct sk_buff *skb;	DECLARE_WAITQUEUE(wait, current);	int err=0;	if (newsock->sk != NULL){		wanpipe_kill_sock_accept(newsock->sk);			newsock->sk=NULL;	}		if ((sk = sock->sk) == NULL)		return -EINVAL;	if (sk->sk_type != SOCK_RAW)		return -EOPNOTSUPP;	if (sk->sk_state != WANSOCK_LISTEN)		return -EINVAL;	if (wp_sk(sk)->num != htons(X25_PROT))		return -EINVAL;	add_wait_queue(sk->sk_sleep,&wait);	current->state = TASK_INTERRUPTIBLE;	for (;;){		skb = skb_dequeue(&sk->sk_receive_queue);		if (skb){			err=0;			break;		}		if (signal_pending(current)) {			err = -ERESTARTSYS;			break;		}		schedule();	}	current->state = TASK_RUNNING;	remove_wait_queue(sk->sk_sleep,&wait);		if (err != 0)		return err;		newsk = get_newsk_from_skb(skb);	if (!newsk){		return -EINVAL;	}	set_bit(1,&wanpipe_tx_critical);	write_lock(&wanpipe_sklist_lock);	sk_add_node(newsk, &wanpipe_sklist);	write_unlock(&wanpipe_sklist_lock);	clear_bit(1,&wanpipe_tx_critical);	newsk->sk_socket = newsock;	newsk->sk_sleep = &newsock->wait;	/* Now attach up the new socket */	sk->sk_ack_backlog--;	newsock->sk = newsk;		kfree_skb(skb);	DBG_PRINTK(KERN_INFO "\nwansock: ACCEPT Got LCN %i\n",		   wp_sk(newsk)->lcn);	return 0;}/*====================================================================== *  get_newsk_from_skb * *	Accept() uses this function to get the address of the new *      socket structure. *=====================================================================*/struct sock * get_newsk_from_skb (struct sk_buff *skb){	struct net_device *dev = skb->dev;	wanpipe_common_t *chan;		if (!dev){		return NULL;	}			if ((chan = dev->priv) == NULL){		return NULL;	}			if (!chan->sk){		return NULL;	}	return (struct sock *)chan->sk;}/*====================================================================== *  wanpipe_connect * *  	CONNECT() System Call. X25API specific function * 	Check the state of the sock, and execute PLACE_CALL command. *      Connect can ether block or return without waiting for connection,  *      if specified by user. *=====================================================================*/static int wanpipe_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags){	struct sock *sk = sock->sk;	struct wan_sockaddr_ll *addr = (struct wan_sockaddr_ll*)uaddr;	struct net_device *dev;	int err;	if (wp_sk(sk)->num != htons(X25_PROT))		return -EINVAL;	if (sk->sk_state == WANSOCK_CONNECTED)		return -EISCONN;	/* No reconnect on a seqpacket socket */	if (sk->sk_state != WAN_DISCONNECTED) {		printk(KERN_INFO "wansock: Trying to connect on channel NON DISCONNECT\n");		return -ECONNREFUSED;	}	sk->sk_state = WANSOCK_DISCONNECTED;		sock->state  = SS_UNCONNECTED;	if (addr_len != sizeof(struct wan_sockaddr_ll))		return -EINVAL;	if (addr->sll_family != AF_WANPIPE)		return -EINVAL;	if ((dev = dev_get_by_index(sk->sk_bound_dev_if)) == NULL)		return -ENETUNREACH;	dev_put(dev);		if (!sk->sk_zapped) /* Must bind first - autobinding does not work */		return -EINVAL;	sock->state   = SS_CONNECTING;	sk->sk_state  = WANSOCK_CONNECTING;	if (!wp_sk(sk)->mbox) {		if (wp_sk (sk)->svc)			return -EINVAL;		else {			int err;			if ((err=set_ioctl_cmd(sk,

⌨️ 快捷键说明

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