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

📄 af_decnet.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	switch(scp->state) {		case DN_DN:			dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC, sk->allocation);			scp->persist_fxn = dn_destroy_timer;			scp->persist = dn_nsp_persist(sk);			break;		case DN_CR:			scp->state = DN_DR;			goto disc_reject;		case DN_RUN:			scp->state = DN_DI;		case DN_DI:		case DN_DR:disc_reject:			dn_nsp_send_disc(sk, NSP_DISCINIT, 0, sk->allocation);		case DN_NC:		case DN_NR:		case DN_RJ:		case DN_DIC:		case DN_CN:		case DN_DRC:		case DN_CI:		case DN_CD:			scp->persist_fxn = dn_destroy_timer;			scp->persist = dn_nsp_persist(sk);			break;		default:			printk(KERN_DEBUG "DECnet: dn_destroy_sock passed socket in invalid state\n");		case DN_O:			dn_stop_fast_timer(sk);			dn_stop_slow_timer(sk);			dn_unhash_sock_bh(sk);			sock_put(sk);			break;	}}char *dn_addr2asc(dn_address addr, char *buf){	unsigned short node, area;	node = addr & 0x03ff;	area = addr >> 10;	sprintf(buf, "%hd.%hd", area, node);	return buf;}static char *dn_state2asc(unsigned char state){	switch(state) {		case DN_O:			return "OPEN";		case DN_CR:			return "  CR";		case DN_DR:			return "  DR";		case DN_DRC:			return " DRC";		case DN_CC:			return "  CC";		case DN_CI:			return "  CI";		case DN_NR:			return "  NR";		case DN_NC:			return "  NC";		case DN_CD:			return "  CD";		case DN_RJ:			return "  RJ";		case DN_RUN:			return " RUN";		case DN_DI:			return "  DI";		case DN_DIC:			return " DIC";		case DN_DN:			return "  DN";		case DN_CL:			return "  CL";		case DN_CN:			return "  CN";	}	return "????";}static int dn_create(struct socket *sock, int protocol){	struct sock *sk;	switch(sock->type) {		case SOCK_SEQPACKET:			if (protocol != DNPROTO_NSP)				return -EPROTONOSUPPORT;			break;		case SOCK_STREAM:			break;		default:			return -ESOCKTNOSUPPORT;	}	if ((sk = dn_alloc_sock(sock, GFP_KERNEL)) == NULL) 		return -ENOBUFS;	sk->protocol = protocol;	return 0;}static intdn_release(struct socket *sock){	struct sock *sk = sock->sk;	if (sk) {		sock_orphan(sk);		sock_hold(sk);		lock_sock(sk);		dn_destroy_sock(sk);		release_sock(sk);		sock_put(sk);	}        return 0;}static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len){	struct sock *sk = sock->sk;	struct dn_scp *scp = &sk->protinfo.dn;	struct sockaddr_dn *saddr = (struct sockaddr_dn *)uaddr;	struct net_device *dev;	int rv;	if (sk->zapped == 0)		return -EINVAL;	if (addr_len != sizeof(struct sockaddr_dn))		return -EINVAL;	if (saddr->sdn_family != AF_DECnet)		return -EINVAL;	if (dn_ntohs(saddr->sdn_nodeaddrl) && (dn_ntohs(saddr->sdn_nodeaddrl) != 2))		return -EINVAL;	if (saddr->sdn_objnum && !capable(CAP_NET_BIND_SERVICE))		return -EPERM;	if (dn_ntohs(saddr->sdn_objnamel) > DN_MAXOBJL)		return -EINVAL;	if (saddr->sdn_flags & ~SDF_WILD)		return -EINVAL;	if (saddr->sdn_flags & SDF_WILD) {		if (!capable(CAP_NET_BIND_SERVICE))			return -EPERM;	} else {		if (dn_ntohs(saddr->sdn_nodeaddrl)) {			read_lock(&dev_base_lock);			for(dev = dev_base; dev; dev = dev->next) {				if (!dev->dn_ptr)					continue;				if (dn_dev_islocal(dev, dn_saddr2dn(saddr)))					break;			}			read_unlock(&dev_base_lock);			if (dev == NULL)				return -EADDRNOTAVAIL;		}	}	memcpy(&scp->addr, saddr, addr_len);	sk->zapped = 0;	if ((rv = dn_hash_sock(sk)) == 0)		goto out;	sk->zapped = 1;out:        return rv;}static int dn_auto_bind(struct socket *sock){	struct sock *sk = sock->sk;	struct dn_scp *scp = &sk->protinfo.dn;	sk->zapped = 0;	scp->addr.sdn_flags  = 0;	scp->addr.sdn_objnum = 0;	/*	 * This stuff is to keep compatibility with Eduardo's	 * patch. I hope I can dispense with it shortly...	 */	if ((scp->accessdata.acc_accl != 0) &&		(scp->accessdata.acc_accl <= 12)) {			scp->addr.sdn_objnamel = dn_htons(scp->accessdata.acc_accl);		memcpy(scp->addr.sdn_objname, scp->accessdata.acc_acc, dn_ntohs(scp->addr.sdn_objnamel));		scp->accessdata.acc_accl = 0;		memset(scp->accessdata.acc_acc, 0, 40);	}	scp->addr.sdn_add.a_len = dn_htons(2);	*(dn_address *)scp->addr.sdn_add.a_addr = decnet_address;	dn_hash_sock(sk);	return 0;}static int dn_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags){	struct sockaddr_dn *addr = (struct sockaddr_dn *)uaddr;	struct sock *sk = sock->sk;	struct dn_scp *scp = &sk->protinfo.dn;	int err = -EISCONN;	lock_sock(sk);	if (sock->state == SS_CONNECTED) 		goto out;	if (sock->state == SS_CONNECTING) {		err = 0;		if (sk->state == TCP_ESTABLISHED)			goto out;		err = -ECONNREFUSED;		if (sk->state == TCP_CLOSE)			goto out;	}	err = -EINVAL;	if (sk->protinfo.dn.state != DN_O)		goto out;	if (addr_len != sizeof(struct sockaddr_dn))		goto out;	if (addr->sdn_family != AF_DECnet)		goto out;	if (addr->sdn_flags & SDF_WILD)		goto out;	err = -EADDRNOTAVAIL;	if (sk->zapped && (err = dn_auto_bind(sock)))		goto out;	memcpy(&scp->peer, addr, addr_len);	err = -EHOSTUNREACH;	if (dn_route_output(&sk->dst_cache, dn_saddr2dn(&scp->peer), dn_saddr2dn(&scp->addr), 0) < 0)		goto out;	sk->state   = TCP_SYN_SENT;	sock->state = SS_CONNECTING;	sk->protinfo.dn.state = DN_CI;	dn_nsp_send_conninit(sk, NSP_CI);	err = -EINPROGRESS;	if ((sk->state == TCP_SYN_SENT) && (flags & O_NONBLOCK))		goto out;	while(sk->state == TCP_SYN_SENT) {		err = -ERESTARTSYS;		if (signal_pending(current))			goto out;		if ((err = sock_error(sk)) != 0) {			sock->state = SS_UNCONNECTED;			goto out;		}		SOCK_SLEEP_PRE(sk);		if (sk->state == TCP_SYN_SENT)			schedule();		SOCK_SLEEP_POST(sk);	}	if (sk->state != TCP_ESTABLISHED) {		sock->state = SS_UNCONNECTED;		err = sock_error(sk);		goto out;	}	err = 0;	sock->state = SS_CONNECTED;out:	release_sock(sk);        return err;}static int dn_access_copy(struct sk_buff *skb, struct accessdata_dn *acc){        unsigned char *ptr = skb->data;        acc->acc_userl = *ptr++;        memcpy(&acc->acc_user, ptr, acc->acc_userl);        ptr += acc->acc_userl;        acc->acc_passl = *ptr++;        memcpy(&acc->acc_pass, ptr, acc->acc_passl);        ptr += acc->acc_passl;        acc->acc_accl = *ptr++;        memcpy(&acc->acc_acc, ptr, acc->acc_accl);        skb_pull(skb, acc->acc_accl + acc->acc_passl + acc->acc_userl + 3);	return 0;}static int dn_user_copy(struct sk_buff *skb, struct optdata_dn *opt){        unsigned char *ptr = skb->data;                opt->opt_optl   = *ptr++;        opt->opt_status = 0;        memcpy(opt->opt_data, ptr, opt->opt_optl);        skb_pull(skb, opt->opt_optl + 1);	return 0;}/* * This is here for use in the sockopt() call as well as * in accept(). Must be called with a locked socket. */static int dn_wait_accept(struct socket *sock, int flags){        struct sock *sk = sock->sk;        while(sk->state == TCP_LISTEN) {                if (flags & O_NONBLOCK) {                        return -EAGAIN;                }		SOCK_SLEEP_PRE(sk)		if (sk->state == TCP_LISTEN)			schedule();		SOCK_SLEEP_POST(sk)                if (signal_pending(current))                        return -ERESTARTSYS; /* But of course you don't! */        }        if ((sk->protinfo.dn.state != DN_RUN) && (sk->protinfo.dn.state != DN_DRC)) {                sock->state = SS_UNCONNECTED;                return sock_error(sk);        }	sock->state = SS_CONNECTED;        return 0;}static int dn_accept(struct socket *sock, struct socket *newsock, int flags){	struct sock *sk = sock->sk, *newsk;	struct sk_buff *skb = NULL;	struct dn_skb_cb *cb;	unsigned char menuver;	int err = 0;	unsigned char type;	lock_sock(sk);        if (sk->state != TCP_LISTEN) {		release_sock(sk);		return -EINVAL;	}	if (sk->protinfo.dn.state != DN_O) {		release_sock(sk);		return -EINVAL;	}        do        {                if ((skb = skb_dequeue(&sk->receive_queue)) == NULL)                {                        if (flags & O_NONBLOCK)                        {                                release_sock(sk);                                return -EAGAIN;                        }			SOCK_SLEEP_PRE(sk);			if (!skb_peek(&sk->receive_queue))				schedule();			SOCK_SLEEP_POST(sk);                        if (signal_pending(current))                        {				release_sock(sk);                                return -ERESTARTSYS;                        }                }        } while (skb == NULL);	cb = (struct dn_skb_cb *)skb->cb;	if ((newsk = dn_alloc_sock(newsock, sk->allocation)) == NULL) {		release_sock(sk);		kfree_skb(skb);		return -ENOBUFS;	}	sk->ack_backlog--;	release_sock(sk);	dst_release(xchg(&newsk->dst_cache, skb->dst));	skb->dst = NULL;        newsk->protinfo.dn.state      = DN_CR;	newsk->protinfo.dn.addrrem    = cb->src_port;	newsk->protinfo.dn.mss        = cb->segsize;	newsk->protinfo.dn.accept_mode = sk->protinfo.dn.accept_mode;		if (newsk->protinfo.dn.mss < 230)		newsk->protinfo.dn.mss = 230;	newsk->state  = TCP_LISTEN;	newsk->zapped = 0;	memcpy(&newsk->protinfo.dn.addr, &sk->protinfo.dn.addr, sizeof(struct sockaddr_dn));	/*	 * If we are listening on a wild socket, we don't want	 * the newly created socket on the wrong hash queue.	 */	newsk->protinfo.dn.addr.sdn_flags &= ~SDF_WILD;	skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &newsk->protinfo.dn.addr, &type));	skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &newsk->protinfo.dn.peer, &type));	*(dn_address *)newsk->protinfo.dn.peer.sdn_add.a_addr = cb->src;	*(dn_address *)newsk->protinfo.dn.addr.sdn_add.a_addr = cb->dst;	menuver = *skb->data;	skb_pull(skb, 1);	if (menuver & DN_MENUVER_ACC)		dn_access_copy(skb, &newsk->protinfo.dn.accessdata);	if (menuver & DN_MENUVER_USR)		dn_user_copy(skb, &newsk->protinfo.dn.conndata_in);	if (menuver & DN_MENUVER_PRX)		newsk->protinfo.dn.peer.sdn_flags |= SDF_PROXY;	if (menuver & DN_MENUVER_UIC)		newsk->protinfo.dn.peer.sdn_flags |= SDF_UICPROXY;	kfree_skb(skb);	memcpy(&newsk->protinfo.dn.conndata_out, &sk->protinfo.dn.conndata_out,		sizeof(struct optdata_dn));	memcpy(&newsk->protinfo.dn.discdata_out, &sk->protinfo.dn.discdata_out,		sizeof(struct optdata_dn));	lock_sock(newsk);	dn_hash_sock(newsk);	dn_send_conn_ack(newsk);	if (newsk->protinfo.dn.accept_mode == ACC_IMMED) {		newsk->protinfo.dn.state = DN_CC;        	dn_send_conn_conf(newsk, newsk->allocation);		err = dn_wait_accept(newsock, flags);	}	release_sock(newsk);        return err;}static int dn_getname(struct socket *sock, struct sockaddr *uaddr,int *uaddr_len,int peer){	struct sockaddr_dn *sa = (struct sockaddr_dn *)uaddr;	struct sock *sk = sock->sk;	struct dn_scp *scp = &sk->protinfo.dn;	*uaddr_len = sizeof(struct sockaddr_dn);	lock_sock(sk);	if (peer) {		if (sock->state != SS_CONNECTED && scp->accept_mode == ACC_IMMED)			return -ENOTCONN;		memcpy(sa, &scp->peer, sizeof(struct sockaddr_dn));	} else {		memcpy(sa, &scp->addr, sizeof(struct sockaddr_dn));	}	release_sock(sk);        return 0;}static unsigned int dn_poll(struct file *file, struct socket *sock, poll_table  *wait){	struct sock *sk = sock->sk;	struct dn_scp *scp = &sk->protinfo.dn;	int mask = datagram_poll(file, sock, wait);	if (skb_queue_len(&scp->other_receive_queue))		mask |= POLLRDBAND;	return mask;}

⌨️ 快捷键说明

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