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

📄 af_netrom.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
	nr->device  = onr->device;	nr->bpqext  = onr->bpqext;	return sk;}static int nr_release(struct socket *sock){	struct sock *sk = sock->sk;	nr_cb *nr;	if (sk == NULL) return 0;	sock_hold(sk);	lock_sock(sk);	nr = nr_sk(sk);	switch (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);		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);		nr->state    = NR_STATE_2;		sk->sk_state    = TCP_CLOSE;		sk->sk_shutdown |= SEND_SHUTDOWN;		sk->sk_state_change(sk);		sock_orphan(sk);		sock_set_flag(sk, SOCK_DESTROY);		sk->sk_socket   = NULL;		break;	default:		sk->sk_socket = NULL;		break;	}	sock->sk   = NULL;		release_sock(sk);	sock_put(sk);	return 0;}static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len){	struct sock *sk = sock->sk;	nr_cb *nr = nr_sk(sk);	struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)uaddr;	struct net_device *dev;	ax25_address *user, *source;	lock_sock(sk);	if (!sk->sk_zapped) {		release_sock(sk);		return -EINVAL;	}	if (addr_len < sizeof(struct sockaddr_ax25) || addr_len > sizeof(struct full_sockaddr_ax25)) {		release_sock(sk);		return -EINVAL;	}	if (addr_len < (addr->fsa_ax25.sax25_ndigis * sizeof(ax25_address) + sizeof(struct sockaddr_ax25))) {		release_sock(sk);		return -EINVAL;	}	if (addr->fsa_ax25.sax25_family != AF_NETROM) {		release_sock(sk);		return -EINVAL;	}	if ((dev = nr_dev_get(&addr->fsa_ax25.sax25_call)) == NULL) {		SOCK_DEBUG(sk, "NET/ROM: bind failed: invalid node callsign\n");		release_sock(sk);		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)) {			dev_put(dev);			release_sock(sk);			return -EACCES;		}		nr->user_addr   = addr->fsa_digipeater[0];		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)) {				release_sock(sk);				dev_put(dev);				return -EPERM;			}			user = source;		}		nr->user_addr   = *user;		nr->source_addr = *source;	}	nr->device = dev;	nr_insert_socket(sk);	sk->sk_zapped = 0;	dev_put(dev);	release_sock(sk);	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;	nr_cb *nr = nr_sk(sk);	struct sockaddr_ax25 *addr = (struct sockaddr_ax25 *)uaddr;	ax25_address *user, *source = NULL;	struct net_device *dev;	lock_sock(sk);	if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {		sock->state = SS_CONNECTED;		release_sock(sk);		return 0;	/* Connect completed during a ERESTARTSYS event */	}	if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) {		sock->state = SS_UNCONNECTED;		release_sock(sk);		return -ECONNREFUSED;	}	if (sk->sk_state == TCP_ESTABLISHED) {		release_sock(sk);		return -EISCONN;	/* No reconnect on a seqpacket socket */	}	sk->sk_state   = TCP_CLOSE;		sock->state = SS_UNCONNECTED;	if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25)) {		release_sock(sk);		return -EINVAL;	}	if (addr->sax25_family != AF_NETROM) {		release_sock(sk);		return -EINVAL;	}	if (sk->sk_zapped) {	/* Must bind first - autobinding in this may or may not work */		sk->sk_zapped = 0;		if ((dev = nr_dev_first()) == NULL) {			release_sock(sk);			return -ENETUNREACH;		}		source = (ax25_address *)dev->dev_addr;		if ((user = ax25_findbyuid(current->euid)) == NULL) {			if (ax25_uid_policy && !capable(CAP_NET_ADMIN)) {				dev_put(dev);				release_sock(sk);				return -EPERM;			}			user = source;		}		nr->user_addr   = *user;		nr->source_addr = *source;		nr->device      = dev;		dev_put(dev);		nr_insert_socket(sk);		/* Finish the bind */	}	nr->dest_addr = addr->sax25_call;	release_sock(sk);	circuit = nr_find_next_circuit();	lock_sock(sk);	nr->my_index = circuit / 256;	nr->my_id    = circuit % 256;	circuit++;	/* Move to connecting socket, start sending Connect Requests */	sock->state  = SS_CONNECTING;	sk->sk_state = TCP_SYN_SENT;	nr_establish_data_link(sk);	nr->state = NR_STATE_1;	nr_start_heartbeat(sk);	/* Now the loop */	if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) {		release_sock(sk);		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;			release_sock(sk);			if (!signal_pending(tsk)) {				schedule();				lock_sock(sk);				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;		release_sock(sk);		return sock_error(sk);	/* Always set at this point */	}	sock->state = SS_CONNECTED;	release_sock(sk);	return 0;}static int nr_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;		}		current->state = TASK_RUNNING;		remove_wait_queue(sk->sk_sleep, &wait);		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 */	kfree_skb(skb);	sk->sk_ack_backlog--;	newsock->sk = newsk;out:	release_sock(sk);	return err;}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;	nr_cb *nr = nr_sk(sk);	lock_sock(sk);	if (peer != 0) {		if (sk->sk_state != TCP_ESTABLISHED) {			release_sock(sk);			return -ENOTCONN;		}		sax->fsa_ax25.sax25_family = AF_NETROM;		sax->fsa_ax25.sax25_ndigis = 1;		sax->fsa_ax25.sax25_call   = nr->user_addr;		sax->fsa_digipeater[0]     = 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   = nr->source_addr;		*uaddr_len = sizeof(struct sockaddr_ax25);	}	release_sock(sk);	return 0;}int nr_rx_frame(struct sk_buff *skb, struct net_device *dev){	struct sock *sk;	struct sock *make;		nr_cb *nr_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;	int ret;	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;#ifdef CONFIG_INET	/*	 * Check for an incoming IP over NET/ROM frame.	 */	if (frametype == NR_PROTOEXT && 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	/*	 * 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)			nr_sk(sk)->bpqext = 1;		else			nr_sk(sk)->bpqext = 0;		ret = nr_process_rx_frame(sk, skb);		bh_unlock_sock(sk);		return ret;	}	/*	 * 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		/*		 * Never reply to a CONNACK/CHOKE.		 */		if (frametype != NR_CONNACK || flags != NR_CHOKE_FLAG)			nr_transmit_refusal(skb, 1);#endif		return 0;	}	sk = nr_find_listener(dest);	user = (ax25_address *)(skb->data + 21);	if (!sk || sk->sk_ack_backlog == sk->sk_max_ack_backlog ||	    (make = nr_make_new(sk)) == NULL) {		nr_transmit_refusal(skb, 0);		if (sk)			bh_unlock_sock(sk);		return 0;	}	window = skb->data[20];	skb->sk             = make;	make->sk_state	    = TCP_ESTABLISHED;	/* Fill in his circuit details */	nr_make = nr_sk(make);	nr_make->source_addr = *dest;	nr_make->dest_addr   = *src;	nr_make->user_addr   = *user;	nr_make->your_index  = circuit_index;	nr_make->your_id     = circuit_id;	bh_unlock_sock(sk);	circuit = nr_find_next_circuit();	bh_lock_sock(sk);	nr_make->my_index    = circuit / 256;	nr_make->my_id       = circuit % 256;	circuit++;	/* Window negotiation */	if (window < nr_make->window)		nr_make->window = window;	/* L4 timeout negotiation */	if (skb->len == 37) {		timeout = skb->data[36] * 256 + skb->data[35];		if (timeout * HZ < nr_make->t1)			nr_make->t1 = timeout * HZ;		nr_make->bpqext = 1;	} else {		nr_make->bpqext = 0;	}	nr_write_internal(make, NR_CONNACK);	nr_make->condition = 0x00;	nr_make->vs        = 0;	nr_make->va        = 0;	nr_make->vr        = 0;	nr_make->vl        = 0;	nr_make->state     = NR_STATE_3;	sk->sk_ack_backlog++;

⌨️ 快捷键说明

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