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

📄 af_netrom.c

📁 《嵌入式系统设计与实例开发实验教材二源码》Linux内核移植与编译实验
💻 C
📖 第 1 页 / 共 3 页
字号:
}static int nr_create(struct socket *sock, int protocol){	struct sock *sk;	nr_cb *nr;	if (sock->type != SOCK_SEQPACKET || protocol != 0)		return -ESOCKTNOSUPPORT;	if ((sk = nr_alloc_sock()) == NULL)		return -ENOMEM;	nr = sk->protinfo.nr;	sock_init_data(sock, sk);	sock->ops    = &nr_proto_ops;	sk->protocol = protocol;	skb_queue_head_init(&nr->ack_queue);	skb_queue_head_init(&nr->reseq_queue);	skb_queue_head_init(&nr->frag_queue);	init_timer(&nr->t1timer);	init_timer(&nr->t2timer);	init_timer(&nr->t4timer);	init_timer(&nr->idletimer);	nr->t1     = sysctl_netrom_transport_timeout;	nr->t2     = sysctl_netrom_transport_acknowledge_delay;	nr->n2     = sysctl_netrom_transport_maximum_tries;	nr->t4     = sysctl_netrom_transport_busy_delay;	nr->idle   = sysctl_netrom_transport_no_activity_timeout;	nr->window = sysctl_netrom_transport_requested_window_size;	nr->bpqext = 1;	nr->state  = NR_STATE_0;	return 0;}static struct sock *nr_make_new(struct sock *osk){	struct sock *sk;	nr_cb *nr;	if (osk->type != SOCK_SEQPACKET)		return NULL;	if ((sk = nr_alloc_sock()) == NULL)		return NULL;	nr = sk->protinfo.nr;	sock_init_data(NULL, sk);	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;	skb_queue_head_init(&nr->ack_queue);	skb_queue_head_init(&nr->reseq_queue);	skb_queue_head_init(&nr->frag_queue);	init_timer(&nr->t1timer);	init_timer(&nr->t2timer);	init_timer(&nr->t4timer);	init_timer(&nr->idletimer);	nr->t1      = osk->protinfo.nr->t1;	nr->t2      = osk->protinfo.nr->t2;	nr->n2      = osk->protinfo.nr->n2;	nr->t4      = osk->protinfo.nr->t4;	nr->idle    = osk->protinfo.nr->idle;	nr->window  = osk->protinfo.nr->window;	nr->device  = osk->protinfo.nr->device;	nr->bpqext  = osk->protinfo.nr->bpqext;	return sk;}static int nr_release(struct socket *sock){	struct sock *sk = sock->sk;	if (sk == NULL) return 0;	switch (sk->protinfo.nr->state) {		case NR_STATE_0:		case NR_STATE_1:		case NR_STATE_2:			nr_disconnect(sk, 0);			nr_destroy_socket(sk);			break;		case NR_STATE_3:			nr_clear_queues(sk);			sk->protinfo.nr->n2count = 0;			nr_write_internal(sk, NR_DISCREQ);			nr_start_t1timer(sk);			nr_stop_t2timer(sk);			nr_stop_t4timer(sk);			nr_stop_idletimer(sk);			sk->protinfo.nr->state   = NR_STATE_2;			sk->state                = TCP_CLOSE;			sk->shutdown            |= SEND_SHUTDOWN;			sk->state_change(sk);			sock_orphan(sk);			sk->destroy              = 1;			break;		default:			sk->socket = NULL;			break;	}	sock->sk   = NULL;		return 0;}static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len){	struct sock *sk = sock->sk;	struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)uaddr;	struct net_device *dev;	ax25_address *user, *source;	if (sk->zapped == 0)		return -EINVAL;	if (addr_len < sizeof(struct sockaddr_ax25) || addr_len > sizeof(structfull_sockaddr_ax25))		return -EINVAL;	if (addr_len < (addr->fsa_ax25.sax25_ndigis * sizeof(ax25_address) + sizeof(struct sockaddr_ax25)))		return -EINVAL;	if (addr->fsa_ax25.sax25_family != AF_NETROM)		return -EINVAL;	if ((dev = nr_dev_get(&addr->fsa_ax25.sax25_call)) == NULL) {		SOCK_DEBUG(sk, "NET/ROM: bind failed: invalid node callsign\n");		return -EADDRNOTAVAIL;	}	/*	 * Only the super user can set an arbitrary user callsign.	 */	if (addr->fsa_ax25.sax25_ndigis == 1) {		if (!capable(CAP_NET_BIND_SERVICE))			return -EACCES;		sk->protinfo.nr->user_addr   = addr->fsa_digipeater[0];		sk->protinfo.nr->source_addr = addr->fsa_ax25.sax25_call;	} else {		source = &addr->fsa_ax25.sax25_call;		if ((user = ax25_findbyuid(current->euid)) == NULL) {			if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE))				return -EPERM;			user = source;		}		sk->protinfo.nr->user_addr   = *user;		sk->protinfo.nr->source_addr = *source;	}	sk->protinfo.nr->device = dev;	nr_insert_socket(sk);	sk->zapped = 0;	SOCK_DEBUG(sk, "NET/ROM: socket is bound\n");	return 0;}static int nr_connect(struct socket *sock, struct sockaddr *uaddr,	int addr_len, int flags){	struct sock *sk = sock->sk;	struct sockaddr_ax25 *addr = (struct sockaddr_ax25 *)uaddr;	ax25_address *user, *source = NULL;	struct net_device *dev;	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_ax25) && addr_len != sizeof(struct full_sockaddr_ax25))		return -EINVAL;	if (addr->sax25_family != AF_NETROM)		return -EINVAL;	if (sk->zapped) {	/* Must bind first - autobinding in this may or may not work */		sk->zapped = 0;		if ((dev = nr_dev_first()) == NULL)			return -ENETUNREACH;		source = (ax25_address *)dev->dev_addr;		if ((user = ax25_findbyuid(current->euid)) == NULL) {			if (ax25_uid_policy && !capable(CAP_NET_ADMIN))				return -EPERM;			user = source;		}		sk->protinfo.nr->user_addr   = *user;		sk->protinfo.nr->source_addr = *source;		sk->protinfo.nr->device      = dev;		nr_insert_socket(sk);		/* Finish the bind */	}	sk->protinfo.nr->dest_addr = addr->sax25_call;	circuit = nr_find_next_circuit();	sk->protinfo.nr->my_index = circuit / 256;	sk->protinfo.nr->my_id    = circuit % 256;	circuit++;	/* Move to connecting socket, start sending Connect Requests */	sock->state            = SS_CONNECTING;	sk->state              = TCP_SYN_SENT;	nr_establish_data_link(sk);	sk->protinfo.nr->state = NR_STATE_1;	nr_start_heartbeat(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 nr_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 */	kfree_skb(skb);	sk->ack_backlog--;	newsock->sk = newsk;	return 0;}static int nr_getname(struct socket *sock, struct sockaddr *uaddr,	int *uaddr_len, int peer){	struct full_sockaddr_ax25 *sax = (struct full_sockaddr_ax25 *)uaddr;	struct sock *sk = sock->sk;	if (peer != 0) {		if (sk->state != TCP_ESTABLISHED)			return -ENOTCONN;		sax->fsa_ax25.sax25_family = AF_NETROM;		sax->fsa_ax25.sax25_ndigis = 1;		sax->fsa_ax25.sax25_call   = sk->protinfo.nr->user_addr;		sax->fsa_digipeater[0]     = sk->protinfo.nr->dest_addr;		*uaddr_len = sizeof(struct full_sockaddr_ax25);	} else {		sax->fsa_ax25.sax25_family = AF_NETROM;		sax->fsa_ax25.sax25_ndigis = 0;		sax->fsa_ax25.sax25_call   = sk->protinfo.nr->source_addr;		*uaddr_len = sizeof(struct sockaddr_ax25);	}	return 0;}int nr_rx_frame(struct sk_buff *skb, struct net_device *dev){	struct sock *sk;	struct sock *make;		ax25_address *src, *dest, *user;	unsigned short circuit_index, circuit_id;	unsigned short peer_circuit_index, peer_circuit_id;	unsigned short frametype, flags, window, timeout;	skb->sk = NULL;		/* Initially we don't know who it's for */	/*	 *	skb->data points to the netrom frame start	 */	src  = (ax25_address *)(skb->data + 0);	dest = (ax25_address *)(skb->data + 7);	circuit_index      = skb->data[15];	circuit_id         = skb->data[16];	peer_circuit_index = skb->data[17];	peer_circuit_id    = skb->data[18];	frametype          = skb->data[19] & 0x0F;	flags              = skb->data[19] & 0xF0;	switch (frametype) {	case NR_PROTOEXT:#ifdef CONFIG_INET		/*		 * Check for an incoming IP over NET/ROM frame.		 */		if (circuit_index == NR_PROTO_IP && circuit_id == NR_PROTO_IP) {			skb_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN);			skb->h.raw = skb->data;			return nr_rx_ip(skb, dev);		}#endif		return 0;	case NR_CONNREQ:	case NR_CONNACK:	case NR_DISCREQ:	case NR_DISCACK:	case NR_INFO:	case NR_INFOACK:		/*		 * These frame types we understand.		 */		break;	default:		/*		 * Everything else is ignored.		 */		return 0;	}	/*	 * Find an existing socket connection, based on circuit ID, if it's	 * a Connect Request base it on their circuit ID.	 *	 * Circuit ID 0/0 is not valid but it could still be a "reset" for a	 * circuit that no longer exists at the other end ...	 */	sk = NULL;	if (circuit_index == 0 && circuit_id == 0) {		if (frametype == NR_CONNACK && flags == NR_CHOKE_FLAG)			sk = nr_find_peer(peer_circuit_index, peer_circuit_id, src);	} else {		if (frametype == NR_CONNREQ)			sk = nr_find_peer(circuit_index, circuit_id, src);		else			sk = nr_find_socket(circuit_index, circuit_id);	}	if (sk != NULL) {		skb->h.raw = skb->data;		if (frametype == NR_CONNACK && skb->len == 22)			sk->protinfo.nr->bpqext = 1;		else			sk->protinfo.nr->bpqext = 0;		return nr_process_rx_frame(sk, skb);	}	/*	 * Now it should be a CONNREQ.	 */	if (frametype != NR_CONNREQ) {		/*		 * Here it would be nice to be able to send a reset but		 * NET/ROM doesn't have one. The following hack would		 * have been a way to extend the protocol but apparently		 * it kills BPQ boxes... :-(		 */#if 0		/*

⌨️ 快捷键说明

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