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

📄 af_rose.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (osk->sk_type != SOCK_SEQPACKET)		return NULL;	sk = sk_alloc(osk->sk_net, PF_ROSE, GFP_ATOMIC, &rose_proto);	if (sk == NULL)		return NULL;	rose = rose_sk(sk);	sock_init_data(NULL, sk);	skb_queue_head_init(&rose->ack_queue);#ifdef M_BIT	skb_queue_head_init(&rose->frag_queue);	rose->fraglen  = 0;#endif	sk->sk_type     = osk->sk_type;	sk->sk_socket   = osk->sk_socket;	sk->sk_priority = osk->sk_priority;	sk->sk_protocol = osk->sk_protocol;	sk->sk_rcvbuf   = osk->sk_rcvbuf;	sk->sk_sndbuf   = osk->sk_sndbuf;	sk->sk_state    = TCP_ESTABLISHED;	sk->sk_sleep    = osk->sk_sleep;	sock_copy_flags(sk, osk);	init_timer(&rose->timer);	init_timer(&rose->idletimer);	orose		= rose_sk(osk);	rose->t1	= orose->t1;	rose->t2	= orose->t2;	rose->t3	= orose->t3;	rose->hb	= orose->hb;	rose->idle	= orose->idle;	rose->defer	= orose->defer;	rose->device	= orose->device;	rose->qbitincl	= orose->qbitincl;	return sk;}static int rose_release(struct socket *sock){	struct sock *sk = sock->sk;	struct rose_sock *rose;	if (sk == NULL) return 0;	rose = rose_sk(sk);	switch (rose->state) {	case ROSE_STATE_0:		rose_disconnect(sk, 0, -1, -1);		rose_destroy_socket(sk);		break;	case ROSE_STATE_2:		rose->neighbour->use--;		rose_disconnect(sk, 0, -1, -1);		rose_destroy_socket(sk);		break;	case ROSE_STATE_1:	case ROSE_STATE_3:	case ROSE_STATE_4:	case ROSE_STATE_5:		rose_clear_queues(sk);		rose_stop_idletimer(sk);		rose_write_internal(sk, ROSE_CLEAR_REQUEST);		rose_start_t3timer(sk);		rose->state  = ROSE_STATE_2;		sk->sk_state    = TCP_CLOSE;		sk->sk_shutdown |= SEND_SHUTDOWN;		sk->sk_state_change(sk);		sock_set_flag(sk, SOCK_DEAD);		sock_set_flag(sk, SOCK_DESTROY);		break;	default:		break;	}	sock->sk = NULL;	return 0;}static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len){	struct sock *sk = sock->sk;	struct rose_sock *rose = rose_sk(sk);	struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr;	struct net_device *dev;	ax25_address *source;	ax25_uid_assoc *user;	int n;	if (!sock_flag(sk, SOCK_ZAPPED))		return -EINVAL;	if (addr_len != sizeof(struct sockaddr_rose) && addr_len != sizeof(struct full_sockaddr_rose))		return -EINVAL;	if (addr->srose_family != AF_ROSE)		return -EINVAL;	if (addr_len == sizeof(struct sockaddr_rose) && addr->srose_ndigis > 1)		return -EINVAL;	if (addr->srose_ndigis > ROSE_MAX_DIGIS)		return -EINVAL;	if ((dev = rose_dev_get(&addr->srose_addr)) == NULL) {		SOCK_DEBUG(sk, "ROSE: bind failed: invalid address\n");		return -EADDRNOTAVAIL;	}	source = &addr->srose_call;	user = ax25_findbyuid(current->euid);	if (user) {		rose->source_call = user->call;		ax25_uid_put(user);	} else {		if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE))			return -EACCES;		rose->source_call   = *source;	}	rose->source_addr   = addr->srose_addr;	rose->device        = dev;	rose->source_ndigis = addr->srose_ndigis;	if (addr_len == sizeof(struct full_sockaddr_rose)) {		struct full_sockaddr_rose *full_addr = (struct full_sockaddr_rose *)uaddr;		for (n = 0 ; n < addr->srose_ndigis ; n++)			rose->source_digis[n] = full_addr->srose_digis[n];	} else {		if (rose->source_ndigis == 1) {			rose->source_digis[0] = addr->srose_digi;		}	}	rose_insert_socket(sk);	sock_reset_flag(sk, SOCK_ZAPPED);	SOCK_DEBUG(sk, "ROSE: socket is bound\n");	return 0;}static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags){	struct sock *sk = sock->sk;	struct rose_sock *rose = rose_sk(sk);	struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr;	unsigned char cause, diagnostic;	struct net_device *dev;	ax25_uid_assoc *user;	int n, err = 0;	if (addr_len != sizeof(struct sockaddr_rose) && addr_len != sizeof(struct full_sockaddr_rose))		return -EINVAL;	if (addr->srose_family != AF_ROSE)		return -EINVAL;	if (addr_len == sizeof(struct sockaddr_rose) && addr->srose_ndigis > 1)		return -EINVAL;	if (addr->srose_ndigis > ROSE_MAX_DIGIS)		return -EINVAL;	/* Source + Destination digis should not exceed ROSE_MAX_DIGIS */	if ((rose->source_ndigis + addr->srose_ndigis) > ROSE_MAX_DIGIS)		return -EINVAL;	lock_sock(sk);	if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {		/* Connect completed during a ERESTARTSYS event */		sock->state = SS_CONNECTED;		goto out_release;	}	if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) {		sock->state = SS_UNCONNECTED;		err = -ECONNREFUSED;		goto out_release;	}	if (sk->sk_state == TCP_ESTABLISHED) {		/* No reconnect on a seqpacket socket */		err = -EISCONN;		goto out_release;	}	sk->sk_state   = TCP_CLOSE;	sock->state = SS_UNCONNECTED;	rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause,					 &diagnostic);	if (!rose->neighbour)		return -ENETUNREACH;	rose->lci = rose_new_lci(rose->neighbour);	if (!rose->lci) {		err = -ENETUNREACH;		goto out_release;	}	if (sock_flag(sk, SOCK_ZAPPED)) {	/* Must bind first - autobinding in this may or may not work */		sock_reset_flag(sk, SOCK_ZAPPED);		if ((dev = rose_dev_first()) == NULL) {			err = -ENETUNREACH;			goto out_release;		}		user = ax25_findbyuid(current->euid);		if (!user) {			err = -EINVAL;			goto out_release;		}		memcpy(&rose->source_addr, dev->dev_addr, ROSE_ADDR_LEN);		rose->source_call = user->call;		rose->device      = dev;		ax25_uid_put(user);		rose_insert_socket(sk);		/* Finish the bind */	}rose_try_next_neigh:	rose->dest_addr   = addr->srose_addr;	rose->dest_call   = addr->srose_call;	rose->rand        = ((long)rose & 0xFFFF) + rose->lci;	rose->dest_ndigis = addr->srose_ndigis;	if (addr_len == sizeof(struct full_sockaddr_rose)) {		struct full_sockaddr_rose *full_addr = (struct full_sockaddr_rose *)uaddr;		for (n = 0 ; n < addr->srose_ndigis ; n++)			rose->dest_digis[n] = full_addr->srose_digis[n];	} else {		if (rose->dest_ndigis == 1) {			rose->dest_digis[0] = addr->srose_digi;		}	}	/* Move to connecting socket, start sending Connect Requests */	sock->state   = SS_CONNECTING;	sk->sk_state     = TCP_SYN_SENT;	rose->state = ROSE_STATE_1;	rose->neighbour->use++;	rose_write_internal(sk, ROSE_CALL_REQUEST);	rose_start_heartbeat(sk);	rose_start_t1timer(sk);	/* Now the loop */	if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) {		err = -EINPROGRESS;		goto out_release;	}	/*	 * A Connect Ack with Choke or timeout or failed routing will go to	 * closed.	 */	if (sk->sk_state == TCP_SYN_SENT) {		DEFINE_WAIT(wait);		for (;;) {			prepare_to_wait(sk->sk_sleep, &wait,					TASK_INTERRUPTIBLE);			if (sk->sk_state != TCP_SYN_SENT)				break;			if (!signal_pending(current)) {				release_sock(sk);				schedule();				lock_sock(sk);				continue;			}			err = -ERESTARTSYS;			break;		}		finish_wait(sk->sk_sleep, &wait);		if (err)			goto out_release;	}	if (sk->sk_state != TCP_ESTABLISHED) {	/* Try next neighbour */		rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause, &diagnostic);		if (rose->neighbour)			goto rose_try_next_neigh;		/* No more neighbours */		sock->state = SS_UNCONNECTED;		err = sock_error(sk);	/* Always set at this point */		goto out_release;	}	sock->state = SS_CONNECTED;out_release:	release_sock(sk);	return err;}static int rose_accept(struct socket *sock, struct socket *newsock, int flags){	struct sk_buff *skb;	struct sock *newsk;	DEFINE_WAIT(wait);	struct sock *sk;	int err = 0;	if ((sk = sock->sk) == NULL)		return -EINVAL;	lock_sock(sk);	if (sk->sk_type != SOCK_SEQPACKET) {		err = -EOPNOTSUPP;		goto out_release;	}	if (sk->sk_state != TCP_LISTEN) {		err = -EINVAL;		goto out_release;	}	/*	 *	The write queue this time is holding sockets ready to use	 *	hooked into the SABM we saved	 */	for (;;) {		prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);		skb = skb_dequeue(&sk->sk_receive_queue);		if (skb)			break;		if (flags & O_NONBLOCK) {			err = -EWOULDBLOCK;			break;		}		if (!signal_pending(current)) {			release_sock(sk);			schedule();			lock_sock(sk);			continue;		}		err = -ERESTARTSYS;		break;	}	finish_wait(sk->sk_sleep, &wait);	if (err)		goto out_release;	newsk = skb->sk;	newsk->sk_socket = newsock;	newsk->sk_sleep = &newsock->wait;	/* Now attach up the new socket */	skb->sk = NULL;	kfree_skb(skb);	sk->sk_ack_backlog--;	newsock->sk = newsk;out_release:	release_sock(sk);	return err;}static int rose_getname(struct socket *sock, struct sockaddr *uaddr,	int *uaddr_len, int peer){	struct full_sockaddr_rose *srose = (struct full_sockaddr_rose *)uaddr;	struct sock *sk = sock->sk;	struct rose_sock *rose = rose_sk(sk);	int n;	if (peer != 0) {		if (sk->sk_state != TCP_ESTABLISHED)			return -ENOTCONN;		srose->srose_family = AF_ROSE;		srose->srose_addr   = rose->dest_addr;		srose->srose_call   = rose->dest_call;		srose->srose_ndigis = rose->dest_ndigis;		for (n = 0; n < rose->dest_ndigis; n++)			srose->srose_digis[n] = rose->dest_digis[n];	} else {		srose->srose_family = AF_ROSE;		srose->srose_addr   = rose->source_addr;		srose->srose_call   = rose->source_call;		srose->srose_ndigis = rose->source_ndigis;		for (n = 0; n < rose->source_ndigis; n++)			srose->srose_digis[n] = rose->source_digis[n];	}	*uaddr_len = sizeof(struct full_sockaddr_rose);	return 0;}int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct rose_neigh *neigh, unsigned int lci){	struct sock *sk;	struct sock *make;	struct rose_sock *make_rose;	struct rose_facilities_struct facilities;	int n, len;	skb->sk = NULL;		/* Initially we don't know who it's for */	/*	 *	skb->data points to the rose frame start	 */	memset(&facilities, 0x00, sizeof(struct rose_facilities_struct));	len  = (((skb->data[3] >> 4) & 0x0F) + 1) / 2;	len += (((skb->data[3] >> 0) & 0x0F) + 1) / 2;	if (!rose_parse_facilities(skb->data + len + 4, &facilities)) {		rose_transmit_clear_request(neigh, lci, ROSE_INVALID_FACILITY, 76);		return 0;	}	sk = rose_find_listener(&facilities.source_addr, &facilities.source_call);	/*	 * We can't accept the Call Request.	 */	if (sk == NULL || sk_acceptq_is_full(sk) ||	    (make = rose_make_new(sk)) == NULL) {		rose_transmit_clear_request(neigh, lci, ROSE_NETWORK_CONGESTION, 120);		return 0;	}	skb->sk     = make;	make->sk_state = TCP_ESTABLISHED;	make_rose = rose_sk(make);	make_rose->lci           = lci;	make_rose->dest_addr     = facilities.dest_addr;	make_rose->dest_call     = facilities.dest_call;	make_rose->dest_ndigis   = facilities.dest_ndigis;	for (n = 0 ; n < facilities.dest_ndigis ; n++)		make_rose->dest_digis[n] = facilities.dest_digis[n];	make_rose->source_addr   = facilities.source_addr;	make_rose->source_call   = facilities.source_call;	make_rose->source_ndigis = facilities.source_ndigis;	for (n = 0 ; n < facilities.source_ndigis ; n++)		make_rose->source_digis[n]= facilities.source_digis[n];	make_rose->neighbour     = neigh;	make_rose->device        = dev;	make_rose->facilities    = facilities;	make_rose->neighbour->use++;	if (rose_sk(sk)->defer) {		make_rose->state = ROSE_STATE_5;	} else {		rose_write_internal(make, ROSE_CALL_ACCEPTED);		make_rose->state = ROSE_STATE_3;		rose_start_idletimer(make);	}	make_rose->condition = 0x00;	make_rose->vs        = 0;	make_rose->va        = 0;	make_rose->vr        = 0;	make_rose->vl        = 0;	sk->sk_ack_backlog++;	rose_insert_socket(make);	skb_queue_head(&sk->sk_receive_queue, skb);	rose_start_heartbeat(make);	if (!sock_flag(sk, SOCK_DEAD))		sk->sk_data_ready(sk, skb->len);	return 1;}static int rose_sendmsg(struct kiocb *iocb, struct socket *sock,			struct msghdr *msg, size_t len){	struct sock *sk = sock->sk;	struct rose_sock *rose = rose_sk(sk);	struct sockaddr_rose *usrose = (struct sockaddr_rose *)msg->msg_name;	int err;	struct full_sockaddr_rose srose;	struct sk_buff *skb;	unsigned char *asmptr;	int n, size, qbit = 0;	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_CMSG_COMPAT))		return -EINVAL;	if (sock_flag(sk, SOCK_ZAPPED))		return -EADDRNOTAVAIL;	if (sk->sk_shutdown & SEND_SHUTDOWN) {		send_sig(SIGPIPE, current, 0);		return -EPIPE;	}	if (rose->neighbour == NULL || rose->device == NULL)		return -ENETUNREACH;	if (usrose != NULL) {		if (msg->msg_namelen != sizeof(struct sockaddr_rose) && msg->msg_namelen != sizeof(struct full_sockaddr_rose))			return -EINVAL;		memset(&srose, 0, sizeof(struct full_sockaddr_rose));		memcpy(&srose, usrose, msg->msg_namelen);		if (rosecmp(&rose->dest_addr, &srose.srose_addr) != 0 ||		    ax25cmp(&rose->dest_call, &srose.srose_call) != 0)			return -EISCONN;		if (srose.srose_ndigis != rose->dest_ndigis)			return -EISCONN;		if (srose.srose_ndigis == rose->dest_ndigis) {			for (n = 0 ; n < srose.srose_ndigis ; n++)				if (ax25cmp(&rose->dest_digis[n],					    &srose.srose_digis[n]))					return -EISCONN;		}		if (srose.srose_family != AF_ROSE)			return -EINVAL;	} else {		if (sk->sk_state != TCP_ESTABLISHED)			return -ENOTCONN;		srose.srose_family = AF_ROSE;		srose.srose_addr   = rose->dest_addr;		srose.srose_call   = rose->dest_call;		srose.srose_ndigis = rose->dest_ndigis;		for (n = 0 ; n < rose->dest_ndigis ; n++)			srose.srose_digis[n] = rose->dest_digis[n];	}	SOCK_DEBUG(sk, "ROSE: sendto: Addresses built.\n");	/* Build a packet */	SOCK_DEBUG(sk, "ROSE: sendto: building packet.\n");

⌨️ 快捷键说明

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