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

📄 af_rose.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
	init_timer(&rose->idletimer);	rose->t1   = sysctl_rose_call_request_timeout;	rose->t2   = sysctl_rose_reset_request_timeout;	rose->t3   = sysctl_rose_clear_request_timeout;	rose->hb   = sysctl_rose_ack_hold_back_timeout;	rose->idle = sysctl_rose_no_activity_timeout;	rose->state = ROSE_STATE_0;	return 0;}static struct sock *rose_make_new(struct sock *osk){	struct sock *sk;	rose_cb *rose, *orose;	if (osk->sk_type != SOCK_SEQPACKET)		return NULL;	if ((sk = rose_alloc_sock()) == NULL)		return NULL;	rose = rose_sk(sk);	sock_init_data(NULL, sk);	sk_set_owner(sk, THIS_MODULE);	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_debug    = osk->sk_debug;	sk->sk_state    = TCP_ESTABLISHED;	sk->sk_sleep    = osk->sk_sleep;	sk->sk_zapped   = osk->sk_zapped;	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;	rose_cb *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;	rose_cb *rose = rose_sk(sk);	struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr;	struct net_device *dev;	ax25_address *user, *source;	int n;	if (!sk->sk_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;	if ((user = ax25_findbyuid(current->euid)) == NULL) {		if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE))			return -EACCES;		user = source;	}	rose->source_addr   = addr->srose_addr;	rose->source_call   = *user;	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);	sk->sk_zapped = 0;	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;	rose_cb *rose = rose_sk(sk);	struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr;	unsigned char cause, diagnostic;	ax25_address *user;	struct net_device *dev;	int n;	if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {		sock->state = SS_CONNECTED;		return 0;	/* Connect completed during a ERESTARTSYS event */	}	if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) {		sock->state = SS_UNCONNECTED;		return -ECONNREFUSED;	}	if (sk->sk_state == TCP_ESTABLISHED)		return -EISCONN;	/* No reconnect on a seqpacket socket */	sk->sk_state   = TCP_CLOSE;	sock->state = SS_UNCONNECTED;	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;	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)		return -ENETUNREACH;	if (sk->sk_zapped) {	/* Must bind first - autobinding in this may or may not work */		sk->sk_zapped = 0;		if ((dev = rose_dev_first()) == NULL)			return -ENETUNREACH;		if ((user = ax25_findbyuid(current->euid)) == NULL)			return -EINVAL;		memcpy(&rose->source_addr, dev->dev_addr, ROSE_ADDR_LEN);		rose->source_call = *user;		rose->device      = dev;		rose_insert_socket(sk);		/* Finish the bind */	}	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))		return -EINPROGRESS;	/*	 * A Connect Ack with Choke or timeout or failed routing will go to	 * closed.	 */	if (sk->sk_state == TCP_SYN_SENT) {		struct task_struct *tsk = current;		DECLARE_WAITQUEUE(wait, tsk);		add_wait_queue(sk->sk_sleep, &wait);		for (;;) {			set_current_state(TASK_INTERRUPTIBLE);			if (sk->sk_state != TCP_SYN_SENT)				break;			if (!signal_pending(tsk)) {				schedule();				continue;			}			current->state = TASK_RUNNING;			remove_wait_queue(sk->sk_sleep, &wait);			return -ERESTARTSYS;		}		current->state = TASK_RUNNING;		remove_wait_queue(sk->sk_sleep, &wait);	}	if (sk->sk_state != TCP_ESTABLISHED) {		sock->state = SS_UNCONNECTED;		return sock_error(sk);	/* Always set at this point */	}	sock->state = SS_CONNECTED;	return 0;}static int rose_accept(struct socket *sock, struct socket *newsock, int flags){	struct task_struct *tsk = current;	DECLARE_WAITQUEUE(wait, tsk);	struct sk_buff *skb;	struct sock *newsk;	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;	}	if (sk->sk_state != TCP_LISTEN) {		err = -EINVAL;		goto out;	}	/*	 *	The write queue this time is holding sockets ready to use	 *	hooked into the SABM we saved	 */	add_wait_queue(sk->sk_sleep, &wait);	for (;;) {		skb = skb_dequeue(&sk->sk_receive_queue);		if (skb)			break;		current->state = TASK_INTERRUPTIBLE;		release_sock(sk);		if (flags & O_NONBLOCK) {			current->state = TASK_RUNNING;			remove_wait_queue(sk->sk_sleep, &wait);			return -EWOULDBLOCK;		}		if (!signal_pending(tsk)) {			schedule();			lock_sock(sk);			continue;		}		return -ERESTARTSYS;	}	current->state = TASK_RUNNING;	remove_wait_queue(sk->sk_sleep, &wait);	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_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;	rose_cb *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;	rose_cb *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 || sk->sk_ack_backlog == sk->sk_max_ack_backlog ||	    (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;	rose_cb *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 (sk->sk_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];	}

⌨️ 快捷键说明

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