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

📄 svc.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	pr_debug("svc_accept %p -> %p\n",old_vcc,new_vcc);	while (1) {		DEFINE_WAIT(wait);		prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);		while (!(skb = skb_dequeue(&sk->sk_receive_queue)) &&		       sigd) {			if (test_bit(ATM_VF_RELEASED,&old_vcc->flags)) break;			if (test_bit(ATM_VF_CLOSE,&old_vcc->flags)) {				error = -sk->sk_err;				break;			}			if (flags & O_NONBLOCK) {				error = -EAGAIN;				break;			}			release_sock(sk);			schedule();			lock_sock(sk);			if (signal_pending(current)) {				error = -ERESTARTSYS;				break;			}			prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);		}		finish_wait(sk->sk_sleep, &wait);		if (error)			goto out;		if (!skb) {			error = -EUNATCH;			goto out;		}		msg = (struct atmsvc_msg *) skb->data;		new_vcc->qos = msg->qos;		set_bit(ATM_VF_HASQOS,&new_vcc->flags);		new_vcc->remote = msg->svc;		new_vcc->local = msg->local;		new_vcc->sap = msg->sap;		error = vcc_connect(newsock, msg->pvc.sap_addr.itf,				    msg->pvc.sap_addr.vpi, msg->pvc.sap_addr.vci);		dev_kfree_skb(skb);		sk->sk_ack_backlog--;		if (error) {			sigd_enq2(NULL,as_reject,old_vcc,NULL,NULL,			    &old_vcc->qos,error);			error = error == -EAGAIN ? -EBUSY : error;			goto out;		}		/* wait should be short, so we ignore the non-blocking flag */		set_bit(ATM_VF_WAITING, &new_vcc->flags);		prepare_to_wait(sk_atm(new_vcc)->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);		sigd_enq(new_vcc,as_accept,old_vcc,NULL,NULL);		while (test_bit(ATM_VF_WAITING, &new_vcc->flags) && sigd) {			release_sock(sk);			schedule();			lock_sock(sk);			prepare_to_wait(sk_atm(new_vcc)->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);		}		finish_wait(sk_atm(new_vcc)->sk_sleep, &wait);		if (!sigd) {			error = -EUNATCH;			goto out;		}		if (!sk_atm(new_vcc)->sk_err)			break;		if (sk_atm(new_vcc)->sk_err != ERESTARTSYS) {			error = -sk_atm(new_vcc)->sk_err;			goto out;		}	}	newsock->state = SS_CONNECTED;out:	release_sock(sk);	return error;}static int svc_getname(struct socket *sock,struct sockaddr *sockaddr,    int *sockaddr_len,int peer){	struct sockaddr_atmsvc *addr;	*sockaddr_len = sizeof(struct sockaddr_atmsvc);	addr = (struct sockaddr_atmsvc *) sockaddr;	memcpy(addr,peer ? &ATM_SD(sock)->remote : &ATM_SD(sock)->local,	    sizeof(struct sockaddr_atmsvc));	return 0;}int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos){	struct sock *sk = sk_atm(vcc);	DEFINE_WAIT(wait);	set_bit(ATM_VF_WAITING, &vcc->flags);	prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);	sigd_enq2(vcc,as_modify,NULL,NULL,&vcc->local,qos,0);	while (test_bit(ATM_VF_WAITING, &vcc->flags) &&	       !test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) {		schedule();		prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);	}	finish_wait(sk->sk_sleep, &wait);	if (!sigd) return -EUNATCH;	return -sk->sk_err;}static int svc_setsockopt(struct socket *sock, int level, int optname,			  char __user *optval, int optlen){	struct sock *sk = sock->sk;	struct atm_vcc *vcc = ATM_SD(sock);	int value, error = 0;	lock_sock(sk);	switch (optname) {		case SO_ATMSAP:			if (level != SOL_ATM || optlen != sizeof(struct atm_sap)) {				error = -EINVAL;				goto out;			}			if (copy_from_user(&vcc->sap, optval, optlen)) {				error = -EFAULT;				goto out;			}			set_bit(ATM_VF_HASSAP, &vcc->flags);			break;		case SO_MULTIPOINT:			if (level != SOL_ATM || optlen != sizeof(int)) {				error = -EINVAL;				goto out;			}			if (get_user(value, (int __user *) optval)) {				error = -EFAULT;				goto out;			}			if (value == 1) {				set_bit(ATM_VF_SESSION, &vcc->flags);			} else if (value == 0) {				clear_bit(ATM_VF_SESSION, &vcc->flags);			} else {				error = -EINVAL;			}			break;		default:			error = vcc_setsockopt(sock, level, optname,					       optval, optlen);	}out:	release_sock(sk);	return error;}static int svc_getsockopt(struct socket *sock,int level,int optname,    char __user *optval,int __user *optlen){	struct sock *sk = sock->sk;	int error = 0, len;	lock_sock(sk);	if (!__SO_LEVEL_MATCH(optname, level) || optname != SO_ATMSAP) {		error = vcc_getsockopt(sock, level, optname, optval, optlen);		goto out;	}	if (get_user(len, optlen)) {		error = -EFAULT;		goto out;	}	if (len != sizeof(struct atm_sap)) {		error = -EINVAL;		goto out;	}	if (copy_to_user(optval, &ATM_SD(sock)->sap, sizeof(struct atm_sap))) {		error = -EFAULT;		goto out;	}out:	release_sock(sk);	return error;}static int svc_addparty(struct socket *sock, struct sockaddr *sockaddr,			int sockaddr_len, int flags){	DEFINE_WAIT(wait);	struct sock *sk = sock->sk;	struct atm_vcc *vcc = ATM_SD(sock);	int error;	lock_sock(sk);	set_bit(ATM_VF_WAITING, &vcc->flags);	prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);	sigd_enq(vcc, as_addparty, NULL, NULL,		 (struct sockaddr_atmsvc *) sockaddr);	if (flags & O_NONBLOCK) {		finish_wait(sk->sk_sleep, &wait);		error = -EINPROGRESS;		goto out;	}	pr_debug("svc_addparty added wait queue\n");	while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {		schedule();		prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);	}	finish_wait(sk->sk_sleep, &wait);	error = xchg(&sk->sk_err_soft, 0);out:	release_sock(sk);	return error;}static int svc_dropparty(struct socket *sock, int ep_ref){	DEFINE_WAIT(wait);	struct sock *sk = sock->sk;	struct atm_vcc *vcc = ATM_SD(sock);	int error;	lock_sock(sk);	set_bit(ATM_VF_WAITING, &vcc->flags);	prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);	sigd_enq2(vcc, as_dropparty, NULL, NULL, NULL, NULL, ep_ref);	while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {		schedule();		prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);	}	finish_wait(sk->sk_sleep, &wait);	if (!sigd) {		error = -EUNATCH;		goto out;	}	error = xchg(&sk->sk_err_soft, 0);out:	release_sock(sk);	return error;}static int svc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg){	int error, ep_ref;	struct sockaddr_atmsvc sa;	struct atm_vcc *vcc = ATM_SD(sock);	switch (cmd) {		case ATM_ADDPARTY:			if (!test_bit(ATM_VF_SESSION, &vcc->flags))				return -EINVAL;			if (copy_from_user(&sa, (void __user *) arg, sizeof(sa)))				return -EFAULT;			error = svc_addparty(sock, (struct sockaddr *) &sa, sizeof(sa), 0);			break;		case ATM_DROPPARTY:			if (!test_bit(ATM_VF_SESSION, &vcc->flags))				return -EINVAL;			if (copy_from_user(&ep_ref, (void __user *) arg, sizeof(int)))				return -EFAULT;			error = svc_dropparty(sock, ep_ref);			break;		default:			error = vcc_ioctl(sock, cmd, arg);	}	return error;}static const struct proto_ops svc_proto_ops = {	.family =	PF_ATMSVC,	.owner =	THIS_MODULE,	.release =	svc_release,	.bind =		svc_bind,	.connect =	svc_connect,	.socketpair =	sock_no_socketpair,	.accept =	svc_accept,	.getname =	svc_getname,	.poll =		vcc_poll,	.ioctl =	svc_ioctl,	.listen =	svc_listen,	.shutdown =	svc_shutdown,	.setsockopt =	svc_setsockopt,	.getsockopt =	svc_getsockopt,	.sendmsg =	vcc_sendmsg,	.recvmsg =	vcc_recvmsg,	.mmap =		sock_no_mmap,	.sendpage =	sock_no_sendpage,};static int svc_create(struct net *net, struct socket *sock,int protocol){	int error;	if (net != &init_net)		return -EAFNOSUPPORT;	sock->ops = &svc_proto_ops;	error = vcc_create(net, sock, protocol, AF_ATMSVC);	if (error) return error;	ATM_SD(sock)->local.sas_family = AF_ATMSVC;	ATM_SD(sock)->remote.sas_family = AF_ATMSVC;	return 0;}static struct net_proto_family svc_family_ops = {	.family = PF_ATMSVC,	.create = svc_create,	.owner = THIS_MODULE,};/* *	Initialize the ATM SVC protocol family */int __init atmsvc_init(void){	return sock_register(&svc_family_ops);}void atmsvc_exit(void){	sock_unregister(PF_ATMSVC);}

⌨️ 快捷键说明

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