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

📄 af_decnet.c

📁 《嵌入式系统设计与实例开发实验教材二源码》Linux内核移植与编译实验
💻 C
📖 第 1 页 / 共 4 页
字号:
static unsigned int dn_poll(struct file *file, struct socket *sock, poll_table  *wait){	struct sock *sk = sock->sk;	struct dn_scp *scp = DN_SK(sk);	int mask = datagram_poll(file, sock, wait);	if (skb_queue_len(&scp->other_receive_queue))		mask |= POLLRDBAND;	return mask;}static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg){	struct sock *sk = sock->sk;	struct dn_scp *scp = DN_SK(sk);	int err = -EOPNOTSUPP;	unsigned long amount = 0;	struct sk_buff *skb;	int val;	switch(cmd)	{	case SIOCGIFADDR:	case SIOCSIFADDR:		return dn_dev_ioctl(cmd, (void *)arg);	case SIOCATMARK:		lock_sock(sk);		val = (skb_queue_len(&scp->other_receive_queue) != 0);		if (scp->state != DN_RUN)			val = -ENOTCONN;		release_sock(sk);		return val;#ifdef CONFIG_DECNET_ROUTER	case SIOCADDRT:	case SIOCDELRT:		return dn_fib_ioctl(sock, cmd, arg);#endif /* CONFIG_DECNET_ROUTER */	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 ((DN_SK(sk)->state != DN_O) || (sk->state == TCP_LISTEN))		goto out;	sk->max_ack_backlog = backlog;	sk->ack_backlog     = 0;	sk->state           = TCP_LISTEN;	err                 = 0;	dn_rehash_sock(sk);out:	release_sock(sk);        return err;}static int dn_shutdown(struct socket *sock, int how){	struct sock *sk = sock->sk;	struct dn_scp *scp = DN_SK(sk);	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 = DN_SK(sk);	union {		struct optdata_dn opt;		struct accessdata_dn acc;		int mode;		unsigned long win;		int val;		unsigned char services;		unsigned char info;	} u;	int err;	if (optlen && !optval)		return -EINVAL;	if (optlen > sizeof(u))		return -EINVAL;	if (copy_from_user(&u, optval, optlen))		return -EFAULT;	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 (u.opt.opt_optl > 16)				return -EINVAL;			memcpy(&scp->conndata_out, &u.opt, optlen);			break;		case DSO_DISDATA:	   	        if (sock->state != SS_CONNECTED && scp->accept_mode == ACC_IMMED)				return -ENOTCONN;			if (optlen != sizeof(struct optdata_dn))				return -EINVAL;			if (u.opt.opt_optl > 16)				return -EINVAL;			memcpy(&scp->discdata_out, &u.opt, optlen);			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 ((u.acc.acc_accl > DN_MAXACCL) ||					(u.acc.acc_passl > DN_MAXACCL) ||					(u.acc.acc_userl > DN_MAXACCL))				return -EINVAL;			memcpy(&scp->accessdata, &u.acc, optlen);			break;		case DSO_ACCEPTMODE:			if (sock->state == SS_CONNECTED)				return -EISCONN;			if (scp->state != DN_O)				return -EINVAL;			if (optlen != sizeof(int))				return -EINVAL;			if ((u.mode != ACC_IMMED) && (u.mode != ACC_DEFER))				return -EINVAL;			scp->accept_mode = (unsigned char)u.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;		case DSO_MAXWINDOW:			if (optlen != sizeof(unsigned long))				return -EINVAL;			if (u.win > NSP_MAX_WINDOW)				u.win = NSP_MAX_WINDOW;			if (u.win == 0)				return -EINVAL;			scp->max_window = u.win;			if (scp->snd_window > u.win)				scp->snd_window = u.win;			break;		case DSO_NODELAY:			if (optlen != sizeof(int))				return -EINVAL;			if (scp->nonagle == 2)				return -EINVAL;			scp->nonagle = (u.val == 0) ? 0 : 1;			/* if (scp->nonagle == 1) { Push pending frames } */			break;		case DSO_CORK:			if (optlen != sizeof(int))				return -EINVAL;			if (scp->nonagle == 1)				return -EINVAL;			scp->nonagle = (u.val == 0) ? 0 : 2;			/* if (scp->nonagle == 0) { Push pending frames } */			break;		case DSO_SERVICES:			if (optlen != sizeof(unsigned char))				return -EINVAL;			if ((u.services & ~NSP_FC_MASK) != 0x01)				return -EINVAL;			if ((u.services & NSP_FC_MASK) == NSP_FC_MASK)				return -EINVAL;			scp->services_loc = u.services;			break;		case DSO_INFO:			if (optlen != sizeof(unsigned char))				return -EINVAL;			if (u.info & 0xfc)				return -EINVAL;			scp->info_loc = u.info;			break;	}	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 = DN_SK(sk);	struct linkinfo_dn link;	unsigned int r_len;	void *r_data = NULL;	unsigned int val;	if(get_user(r_len , optlen))		return -EFAULT;			switch(optname) {		case DSO_CONDATA:			if (r_len > sizeof(struct optdata_dn))				r_len = sizeof(struct optdata_dn);			r_data = &scp->conndata_in;			break;		case DSO_DISDATA:			if (r_len > sizeof(struct optdata_dn))				r_len = sizeof(struct optdata_dn);			r_data = &scp->discdata_in;			break;		case DSO_CONACCESS:			if (r_len > sizeof(struct accessdata_dn))				r_len = sizeof(struct accessdata_dn);			r_data = &scp->accessdata;			break;		case DSO_ACCEPTMODE:			if (r_len > sizeof(unsigned char))				r_len = sizeof(unsigned char);			r_data = &scp->accept_mode;			break;		case DSO_LINKINFO:			if (r_len > sizeof(struct linkinfo_dn))				r_len = sizeof(struct linkinfo_dn);			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->segsize_rem;			r_data = &link;			break;		default:#ifdef CONFIG_NETFILTER		{			int val, len;						if(get_user(len, optlen))				return -EFAULT;						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;		case DSO_MAXWINDOW:			if (r_len > sizeof(unsigned long))				r_len = sizeof(unsigned long);			r_data = &scp->max_window;			break;		case DSO_NODELAY:			if (r_len > sizeof(int))				r_len = sizeof(int);			val = (scp->nonagle == 1);			r_data = &val;			break;		case DSO_CORK:			if (r_len > sizeof(int))				r_len = sizeof(int);			val = (scp->nonagle == 2);			r_data = &val;			break;		case DSO_SERVICES:			if (r_len > sizeof(unsigned char))				r_len = sizeof(unsigned char);			r_data = &scp->services_rem;			break;		case DSO_INFO:			if (r_len > sizeof(unsigned char))				r_len = sizeof(unsigned char);			r_data = &scp->info_rem;			break;	}	if (r_data) {		if (copy_to_user(optval, r_data, r_len))			return -EFAULT;		if (put_user(r_len, optlen))			return -EFAULT;	}	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 = DN_SK(sk);	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 = DN_SKB_CB(skb);		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 = DN_SK(sk);	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;	if (sk->shutdown & RCV_SHUTDOWN) {		send_sig(SIGPIPE, current, 0);		rv = -EPIPE;		goto out;	}	if (flags & ~(MSG_PEEK|MSG_OOB|MSG_WAITALL|MSG_DONTWAIT)) {		rv = -EOPNOTSUPP;		goto out;	}	if (flags & MSG_OOB)

⌨️ 快捷键说明

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