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

📄 af_decnet.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg){	struct sock *sk = sock->sk;	struct dn_scp *scp = &sk->protinfo.dn;	int err = -EOPNOTSUPP;	unsigned long amount = 0;	struct sk_buff *skb;#if 0	struct dn_naddr dnaddr;#endif	switch(cmd)	{	case SIOCGIFADDR:	case SIOCSIFADDR:		return dn_dev_ioctl(cmd, (void *)arg);#ifdef CONFIG_DECNET_ROUTER	case SIOCADDRT:	case SIOCDELRT:		return dn_fib_ioctl(sock, cmd, arg);#endif /* CONFIG_DECNET_ROUTER */#if 0	case SIOCSIFADDR:		if (!capable(CAP_NET_ADMIN))    return -EPERM;		if ((err = copy_from_user(devname, ioarg->devname, 5)) != 0)			break;		if ((err = copy_from_user(addr, ioarg->exec_addr, 6)) != 0)			break;		if ((dev = dev_get(devname)) == NULL) {			err = -ENODEV;			break;		}		if (dev->dn_ptr == NULL) {			err = -ENODEV;			break;		}		dn_dev_devices_off();		decnet_default_device = dev;		memcpy(decnet_ether_address, addr, ETH_ALEN);		decnet_address = dn_htons(dn_eth2dn(decnet_ether_address));		dn_dev_devices_on();		break;	case SIOCGIFADDR:		if (decnet_default_device)			strcpy(devname, decnet_default_device->name);		else			memset(devname, 0, 6);		if ((err = copy_to_user(ioarg->devname, devname, 5)) != 0)			break;		if ((err = copy_to_user(ioarg->exec_addr, decnet_ether_address, 6)) != 0)			break;		break;#endif#if 0	case SIOCSNETADDR:		if (!capable(CAP_NET_ADMIN)) {			err = -EPERM;			break;		}		if ((err = copy_from_user(&dnaddr, (void *)arg, sizeof(struct dn_naddr))) != 0)			break;		if (dnaddr.a_len != ETH_ALEN) {			err = -EINVAL;			break;		}		dn_dev_devices_off();		memcpy(decnet_ether_address, dnaddr.a_addr, ETH_ALEN);		decnet_address = dn_htons(dn_eth2dn(decnet_ether_address));		dn_dev_devices_on();		break;	case SIOCGNETADDR:		dnaddr.a_len = ETH_ALEN;		memcpy(dnaddr.a_addr, decnet_ether_address, ETH_ALEN);		if ((err = copy_to_user((void *)arg, &dnaddr, sizeof(struct dn_naddr))) != 0)			break;		break;#endif	case OSIOCSNETADDR:		if (!capable(CAP_NET_ADMIN)) {			err = -EPERM;			break;		}		dn_dev_devices_off();		decnet_address = (unsigned short)arg;		dn_dn2eth(decnet_ether_address, dn_ntohs(decnet_address));		dn_dev_devices_on();		err = 0;		break;	case OSIOCGNETADDR:		err = put_user(decnet_address, (unsigned short *)arg);		break;        case SIOCGIFCONF:        case SIOCGIFFLAGS:        case SIOCGIFBRDADDR:                return dev_ioctl(cmd,(void *)arg);	case TIOCOUTQ:		amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);		if (amount < 0)			amount = 0;		err = put_user(amount, (int *)arg);		break;	case TIOCINQ:		lock_sock(sk);		if ((skb = skb_peek(&scp->other_receive_queue)) != NULL) {			amount = skb->len;		} else {			struct sk_buff *skb = sk->receive_queue.next;			for(;;) {				if (skb == (struct sk_buff *)&sk->receive_queue)					break;				amount += skb->len;				skb = skb->next;			}		}		release_sock(sk);		err = put_user(amount, (int *)arg);		break;	}	return err;}static int dn_listen(struct socket *sock, int backlog){	struct sock *sk = sock->sk;	int err = -EINVAL;	lock_sock(sk);	if (sk->zapped)		goto out;	if ((sk->protinfo.dn.state != DN_O) || (sk->state == TCP_LISTEN))		goto out;	sk->max_ack_backlog = backlog;	sk->ack_backlog     = 0;	sk->state           = TCP_LISTEN;	err                 = 0;out:	release_sock(sk);        return err;}static int dn_shutdown(struct socket *sock, int how){	struct sock *sk = sock->sk;	struct dn_scp *scp = &sk->protinfo.dn;	int err = -ENOTCONN;	lock_sock(sk);	if (sock->state == SS_UNCONNECTED)		goto out;	err = 0;	if (sock->state == SS_DISCONNECTING)		goto out;	err = -EINVAL;	if (scp->state == DN_O)		goto out;	if (how != SHUTDOWN_MASK)		goto out;	sk->shutdown = how;	dn_destroy_sock(sk);	err = 0;out:	release_sock(sk);	return err;}static int dn_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen){	struct sock *sk = sock->sk;	int err;	lock_sock(sk);	err = __dn_setsockopt(sock, level, optname, optval, optlen, 0);	release_sock(sk);	return err;}static int __dn_setsockopt(struct socket *sock, int level,int optname, char *optval, int optlen, int flags) {	struct	sock *sk = sock->sk;	struct dn_scp *scp = &sk->protinfo.dn;	struct optdata_dn opt;	struct accessdata_dn acc;	int err;	if (optlen && !optval)		return -EINVAL;	switch(optname) {		case DSO_CONDATA:			if (sock->state == SS_CONNECTED) 				return -EISCONN;			if ((scp->state != DN_O) && (scp->state != DN_CR))				return -EINVAL;			if (optlen != sizeof(struct optdata_dn))				return -EINVAL;			if (copy_from_user(&opt, optval, optlen))				return -EFAULT;			if (opt.opt_optl > 16)				return -EINVAL;			memcpy(&scp->conndata_out, &opt, sizeof(struct optdata_dn));			break;		case DSO_DISDATA:	   	        if (sock->state != SS_CONNECTED && sk->protinfo.dn.accept_mode == ACC_IMMED)				return -ENOTCONN;			if (optlen != sizeof(struct optdata_dn))				return -EINVAL;			if (copy_from_user(&opt, optval, sizeof(struct optdata_dn)))				return -EFAULT;			if (opt.opt_optl > 16)				return -EINVAL;			memcpy(&scp->discdata_out, &opt, sizeof(struct optdata_dn));			break;		case DSO_CONACCESS:			if (sock->state == SS_CONNECTED) 				return -EISCONN;			if (scp->state != DN_O)				return -EINVAL;			if (optlen != sizeof(struct accessdata_dn))				return -EINVAL;			if (copy_from_user(&acc, optval, sizeof(struct accessdata_dn)))				return -EFAULT;			if ((acc.acc_accl > DN_MAXACCL) ||					(acc.acc_passl > DN_MAXACCL) ||					(acc.acc_userl > DN_MAXACCL))				return -EINVAL;			memcpy(&scp->accessdata, &acc, sizeof(struct accessdata_dn));			break;		case DSO_ACCEPTMODE:			if (sock->state == SS_CONNECTED)				return -EISCONN;			if (scp->state != DN_O)				return -EINVAL;			if (optlen != sizeof(int))				return -EINVAL;			{				int mode;				if (get_user(mode, optval))					return -EFAULT;				if ((mode != ACC_IMMED) && (mode != ACC_DEFER))					return -EINVAL;				scp->accept_mode = (unsigned char)mode;			}			break;		case DSO_CONACCEPT:			if (scp->state != DN_CR)				return -EINVAL;			scp->state = DN_CC;			dn_send_conn_conf(sk, sk->allocation);			err = dn_wait_accept(sock, sock->file->f_flags);			return err;		case DSO_CONREJECT:			if (scp->state != DN_CR)				return -EINVAL;			scp->state = DN_DR;			sk->shutdown = SHUTDOWN_MASK;			dn_nsp_send_disc(sk, 0x38, 0, sk->allocation);			break;		default:#ifdef CONFIG_NETFILTER		return nf_setsockopt(sk, PF_DECnet, optname, optval, optlen);#endif		case DSO_LINKINFO:		case DSO_STREAM:		case DSO_SEQPACKET:			return -ENOPROTOOPT;	}	return 0;}static int dn_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen){	struct sock *sk = sock->sk;	int err;	lock_sock(sk);	err = __dn_getsockopt(sock, level, optname, optval, optlen, 0);	release_sock(sk);	return err;}static int __dn_getsockopt(struct socket *sock, int level,int optname, char *optval,int *optlen, int flags){	struct	sock *sk = sock->sk;	struct dn_scp *scp = &sk->protinfo.dn;	struct linkinfo_dn link;	int mode = scp->accept_mode;	switch(optname) {		case DSO_CONDATA:			if (*optlen != sizeof(struct optdata_dn))				return -EINVAL;			if (copy_to_user(optval, &scp->conndata_in, sizeof(struct optdata_dn)))				return -EFAULT;			break;		case DSO_DISDATA:			if (*optlen != sizeof(struct optdata_dn))				return -EINVAL;			if (copy_to_user(optval, &scp->discdata_in, sizeof(struct optdata_dn)))				return -EFAULT;			break;		case DSO_CONACCESS:			if (*optlen != sizeof(struct accessdata_dn))				return -EINVAL;			if (copy_to_user(optval, &scp->accessdata, sizeof(struct accessdata_dn)))				return -EFAULT;			break;		case DSO_ACCEPTMODE:			if (put_user(mode, optval))				return -EFAULT;			break;		case DSO_LINKINFO:			if (*optlen != sizeof(struct linkinfo_dn))				return -EINVAL;			switch(sock->state) {				case SS_CONNECTING:					link.idn_linkstate = LL_CONNECTING;					break;				case SS_DISCONNECTING:					link.idn_linkstate = LL_DISCONNECTING;					break;				case SS_CONNECTED:					link.idn_linkstate = LL_RUNNING;					break;				default:					link.idn_linkstate = LL_INACTIVE;			}			link.idn_segsize = scp->mss;			if (copy_to_user(optval, &link, sizeof(struct linkinfo_dn)))				return -EFAULT;			break;		default:#ifdef CONFIG_NETFILTER		{			int val, len = *optlen;			val = nf_getsockopt(sk, PF_DECnet, optname, 							optval, &len);			if (val >= 0)				val = put_user(len, optlen);			return val;		}#endif		case DSO_STREAM:		case DSO_SEQPACKET:		case DSO_CONACCEPT:		case DSO_CONREJECT:        		return -ENOPROTOOPT;	}	return 0;}/* * Used by send/recvmsg to wait until the socket is connected * before passing data. */static int dn_wait_run(struct sock *sk, int flags){	struct dn_scp *scp = &sk->protinfo.dn;	int err = 0;	switch(scp->state) {		case DN_RUN:			return 0;		case DN_CR:			scp->state = DN_CC;			dn_send_conn_conf(sk, sk->allocation);			return dn_wait_accept(sk->socket, (flags & MSG_DONTWAIT) ? O_NONBLOCK : 0);		case DN_CI:		case DN_CC:			break;		default:			return -ENOTCONN;	}	if (flags & MSG_DONTWAIT)		return -EWOULDBLOCK;	do {		if ((err = sock_error(sk)) != 0)			break;		if (signal_pending(current)) {			err = -ERESTARTSYS;			break;		}		SOCK_SLEEP_PRE(sk)		if (scp->state != DN_RUN)			schedule();		SOCK_SLEEP_POST(sk)	} while(scp->state != DN_RUN);	return 0;}static int dn_data_ready(struct sock *sk, struct sk_buff_head *q, int flags, int target){	struct sk_buff *skb = q->next;	int len = 0;	if (flags & MSG_OOB)		return skb_queue_len(q) ? 1 : 0;	while(skb != (struct sk_buff *)q) {		struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;		len += skb->len;		if (cb->nsp_flags & 0x40) {			/* SOCK_SEQPACKET reads to EOM */			if (sk->type == SOCK_SEQPACKET)				return 1;			/* so does SOCK_STREAM unless WAITALL is specified */			if (!(flags & MSG_WAITALL))				return 1;		}		/* minimum data length for read exceeded */		if (len >= target)			return 1;		skb = skb->next;	}	return 0;}static int dn_recvmsg(struct socket *sock, struct msghdr *msg, int size,	int flags, struct scm_cookie *scm){	struct sock *sk = sock->sk;	struct dn_scp *scp = &sk->protinfo.dn;	struct sk_buff_head *queue = &sk->receive_queue;	int target = size > 1 ? 1 : 0;	int copied = 0;	int rv = 0;	struct sk_buff *skb, *nskb;	struct dn_skb_cb *cb = NULL;	unsigned char eor = 0;	lock_sock(sk);	if (sk->zapped) {		rv = -EADDRNOTAVAIL;		goto out;	}	if ((rv = dn_wait_run(sk, flags)) != 0)		goto out;

⌨️ 快捷键说明

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