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

📄 af_rose.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	len = min(len, sizeof(int));	if (put_user(len, optlen))		return -EFAULT;	return copy_to_user(optval, &val, len) ? -EFAULT : 0;}static int rose_listen(struct socket *sock, int backlog){	struct sock *sk = sock->sk;	if (sk->state != TCP_LISTEN) {		sk->protinfo.rose->dest_ndigis = 0;		memset(&sk->protinfo.rose->dest_addr, '\0', ROSE_ADDR_LEN);		memset(&sk->protinfo.rose->dest_call, '\0', AX25_ADDR_LEN);		memset(sk->protinfo.rose->dest_digis, '\0', AX25_ADDR_LEN*ROSE_MAX_DIGIS);		sk->max_ack_backlog = backlog;		sk->state           = TCP_LISTEN;		return 0;	}	return -EOPNOTSUPP;}static int rose_create(struct socket *sock, int protocol){	struct sock *sk;	rose_cb *rose;	if (sock->type != SOCK_SEQPACKET || protocol != 0)		return -ESOCKTNOSUPPORT;	if ((sk = rose_alloc_sock()) == NULL)		return -ENOMEM;	rose = sk->protinfo.rose;	sock_init_data(sock, sk);		skb_queue_head_init(&rose->ack_queue);#ifdef M_BIT	skb_queue_head_init(&rose->frag_queue);	rose->fraglen    = 0;#endif	sock->ops    = &rose_proto_ops;	sk->protocol = protocol;	init_timer(&rose->timer);	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;	if (osk->type != SOCK_SEQPACKET)		return NULL;	if ((sk = rose_alloc_sock()) == NULL)		return NULL;	rose = sk->protinfo.rose;	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->type     = osk->type;	sk->socket   = osk->socket;	sk->priority = osk->priority;	sk->protocol = osk->protocol;	sk->rcvbuf   = osk->rcvbuf;	sk->sndbuf   = osk->sndbuf;	sk->debug    = osk->debug;	sk->state    = TCP_ESTABLISHED;	sk->sleep    = osk->sleep;	sk->zapped   = osk->zapped;	init_timer(&rose->timer);	init_timer(&rose->idletimer);	rose->t1      = osk->protinfo.rose->t1;	rose->t2      = osk->protinfo.rose->t2;	rose->t3      = osk->protinfo.rose->t3;	rose->hb      = osk->protinfo.rose->hb;	rose->idle    = osk->protinfo.rose->idle;	rose->defer    = osk->protinfo.rose->defer;	rose->device   = osk->protinfo.rose->device;	rose->qbitincl = osk->protinfo.rose->qbitincl;	return sk;}static int rose_release(struct socket *sock){	struct sock *sk = sock->sk;	if (sk == NULL) return 0;	switch (sk->protinfo.rose->state) {		case ROSE_STATE_0:			rose_disconnect(sk, 0, -1, -1);			rose_destroy_socket(sk);			break;		case ROSE_STATE_2:			sk->protinfo.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);			sk->protinfo.rose->state = ROSE_STATE_2;			sk->state                = TCP_CLOSE;			sk->shutdown            |= SEND_SHUTDOWN;			sk->state_change(sk);			sk->dead                 = 1;			sk->destroy              = 1;			break;		default:			break;	}	sock->sk = NULL;		sk->socket = NULL;	/* Not used, but we should do this. **/	return 0;}static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len){	struct sock *sk = sock->sk;	struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr;	struct net_device *dev;	ax25_address *user, *source;	int n;	if (sk->zapped == 0)		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;	}	sk->protinfo.rose->source_addr   = addr->srose_addr;	sk->protinfo.rose->source_call   = *user;	sk->protinfo.rose->device        = dev;	sk->protinfo.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++)			sk->protinfo.rose->source_digis[n] = full_addr->srose_digis[n];	} else {		if (sk->protinfo.rose->source_ndigis == 1) {			sk->protinfo.rose->source_digis[0] = addr->srose_digi;		}	}	rose_insert_socket(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;	struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr;	unsigned char cause, diagnostic;	ax25_address *user;	struct net_device *dev;	int n;	if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {		sock->state = SS_CONNECTED;		return 0;	/* Connect completed during a ERESTARTSYS event */	}	if (sk->state == TCP_CLOSE && sock->state == SS_CONNECTING) {		sock->state = SS_UNCONNECTED;		return -ECONNREFUSED;	}	if (sk->state == TCP_ESTABLISHED)		return -EISCONN;	/* No reconnect on a seqpacket socket */	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 ((sk->protinfo.rose->source_ndigis + addr->srose_ndigis) > ROSE_MAX_DIGIS)		return -EINVAL;	if ((sk->protinfo.rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause, &diagnostic)) == NULL)		return -ENETUNREACH;	if ((sk->protinfo.rose->lci = rose_new_lci(sk->protinfo.rose->neighbour)) == 0)		return -ENETUNREACH;	if (sk->zapped) {	/* Must bind first - autobinding in this may or may not work */		sk->zapped = 0;		if ((dev = rose_dev_first()) == NULL)			return -ENETUNREACH;		if ((user = ax25_findbyuid(current->euid)) == NULL)			return -EINVAL;		memcpy(&sk->protinfo.rose->source_addr, dev->dev_addr, ROSE_ADDR_LEN);		sk->protinfo.rose->source_call = *user;		sk->protinfo.rose->device      = dev;		rose_insert_socket(sk);		/* Finish the bind */	}	sk->protinfo.rose->dest_addr   = addr->srose_addr;	sk->protinfo.rose->dest_call   = addr->srose_call;	sk->protinfo.rose->rand        = ((int)sk->protinfo.rose & 0xFFFF) + sk->protinfo.rose->lci;	sk->protinfo.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++)			sk->protinfo.rose->dest_digis[n] = full_addr->srose_digis[n];	} else {		if (sk->protinfo.rose->dest_ndigis == 1) {			sk->protinfo.rose->dest_digis[0] = addr->srose_digi;		}	}	/* Move to connecting socket, start sending Connect Requests */	sock->state   = SS_CONNECTING;	sk->state     = TCP_SYN_SENT;	sk->protinfo.rose->state = ROSE_STATE_1;	sk->protinfo.rose->neighbour->use++;	rose_write_internal(sk, ROSE_CALL_REQUEST);	rose_start_heartbeat(sk);	rose_start_t1timer(sk);	/* Now the loop */	if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK))		return -EINPROGRESS;	cli();	/* To avoid races on the sleep */	/*	 * A Connect Ack with Choke or timeout or failed routing will go to closed.	 */	while (sk->state == TCP_SYN_SENT) {		interruptible_sleep_on(sk->sleep);		if (signal_pending(current)) {			sti();			return -ERESTARTSYS;		}	}	if (sk->state != TCP_ESTABLISHED) {		sti();		sock->state = SS_UNCONNECTED;		return sock_error(sk);	/* Always set at this point */	}	sock->state = SS_CONNECTED;	sti();	return 0;}static int rose_accept(struct socket *sock, struct socket *newsock, int flags){	struct sock *sk;	struct sock *newsk;	struct sk_buff *skb;	if ((sk = sock->sk) == NULL)		return -EINVAL;	if (sk->type != SOCK_SEQPACKET)		return -EOPNOTSUPP;	if (sk->state != TCP_LISTEN)		return -EINVAL;	/*	 *	The write queue this time is holding sockets ready to use	 *	hooked into the SABM we saved	 */	do {		cli();		if ((skb = skb_dequeue(&sk->receive_queue)) == NULL) {			if (flags & O_NONBLOCK) {				sti();				return -EWOULDBLOCK;			}			interruptible_sleep_on(sk->sleep);			if (signal_pending(current)) {				sti();				return -ERESTARTSYS;			}		}	} while (skb == NULL);	newsk = skb->sk;	newsk->pair = NULL;	newsk->socket = newsock;	newsk->sleep = &newsock->wait;	sti();	/* Now attach up the new socket */	skb->sk = NULL;	kfree_skb(skb);	sk->ack_backlog--;	newsock->sk = newsk;	return 0;}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;	int n;	if (peer != 0) {		if (sk->state != TCP_ESTABLISHED)			return -ENOTCONN;		srose->srose_family = AF_ROSE;		srose->srose_addr   = sk->protinfo.rose->dest_addr;		srose->srose_call   = sk->protinfo.rose->dest_call;		srose->srose_ndigis = sk->protinfo.rose->dest_ndigis;		for (n = 0 ; n < sk->protinfo.rose->dest_ndigis ; n++)			srose->srose_digis[n] = sk->protinfo.rose->dest_digis[n];	} else {		srose->srose_family = AF_ROSE;		srose->srose_addr   = sk->protinfo.rose->source_addr;		srose->srose_call   = sk->protinfo.rose->source_call;		srose->srose_ndigis = sk->protinfo.rose->source_ndigis;		for (n = 0 ; n < sk->protinfo.rose->source_ndigis ; n++)			srose->srose_digis[n] = sk->protinfo.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_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->ack_backlog == 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->state = TCP_ESTABLISHED;	make->protinfo.rose->lci           = lci;	make->protinfo.rose->dest_addr     = facilities.dest_addr;	make->protinfo.rose->dest_call     = facilities.dest_call;	make->protinfo.rose->dest_ndigis   = facilities.dest_ndigis;	for (n = 0 ; n < facilities.dest_ndigis ; n++)		make->protinfo.rose->dest_digis[n] = facilities.dest_digis[n];	make->protinfo.rose->source_addr   = facilities.source_addr;	make->protinfo.rose->source_call   = facilities.source_call;	make->protinfo.rose->source_ndigis = facilities.source_ndigis;	for (n = 0 ; n < facilities.source_ndigis ; n++)		make->protinfo.rose->source_digis[n]= facilities.source_digis[n];	make->protinfo.rose->neighbour     = neigh;	make->protinfo.rose->device        = dev;	make->protinfo.rose->facilities    = facilities;	make->protinfo.rose->neighbour->use++;	if (sk->protinfo.rose->defer) {		make->protinfo.rose->state = ROSE_STATE_5;	} else {		rose_write_internal(make, ROSE_CALL_ACCEPTED);		make->protinfo.rose->state = ROSE_STATE_3;		rose_start_idletimer(make);	}	make->protinfo.rose->condition = 0x00;	make->protinfo.rose->vs        = 0;	make->protinfo.rose->va        = 0;	make->protinfo.rose->vr        = 0;	make->protinfo.rose->vl        = 0;	sk->ack_backlog++;	make->pair = sk;	rose_insert_socket(make);	skb_queue_head(&sk->receive_queue, skb);	rose_start_heartbeat(make);	if (!sk->dead)		sk->data_ready(sk, skb->len);	return 1;}static int rose_sendmsg(struct socket *sock, struct msghdr *msg, int len, 				struct scm_cookie *scm){	struct sock *sk = sock->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))		return -EINVAL;

⌨️ 快捷键说明

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