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

📄 af_x25.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (sock->type != SOCK_SEQPACKET || protocol)		goto out;	rc = -ENOMEM;	if ((sk = x25_alloc_socket()) == NULL)		goto out;	x25 = x25_sk(sk);	sock_init_data(sock, sk);	sk_set_owner(sk, THIS_MODULE);	x25_init_timers(sk);	sock->ops    = &x25_proto_ops;	sk->sk_protocol = protocol;	sk->sk_backlog_rcv = x25_backlog_rcv;	x25->t21   = sysctl_x25_call_request_timeout;	x25->t22   = sysctl_x25_reset_request_timeout;	x25->t23   = sysctl_x25_clear_request_timeout;	x25->t2    = sysctl_x25_ack_holdback_timeout;	x25->state = X25_STATE_0;	x25->facilities.winsize_in  = X25_DEFAULT_WINDOW_SIZE;	x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE;	x25->facilities.pacsize_in  = X25_DEFAULT_PACKET_SIZE;	x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE;	x25->facilities.throughput  = X25_DEFAULT_THROUGHPUT;	x25->facilities.reverse     = X25_DEFAULT_REVERSE;	rc = 0;out:	return rc;}static struct sock *x25_make_new(struct sock *osk){	struct sock *sk = NULL;	struct x25_opt *x25, *ox25;	if (osk->sk_type != SOCK_SEQPACKET)		goto out;	if ((sk = x25_alloc_socket()) == NULL)		goto out;	x25 = x25_sk(sk);	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;	sk->sk_backlog_rcv = osk->sk_backlog_rcv;	ox25 = x25_sk(osk);	x25->t21        = ox25->t21;	x25->t22        = ox25->t22;	x25->t23        = ox25->t23;	x25->t2         = ox25->t2;	x25->facilities = ox25->facilities;	x25->qbitincl   = ox25->qbitincl;	x25_init_timers(sk);out:	return sk;}static int x25_release(struct socket *sock){	struct sock *sk = sock->sk;	struct x25_opt *x25;	if (!sk)		goto out;	x25 = x25_sk(sk);	switch (x25->state) {		case X25_STATE_0:		case X25_STATE_2:			x25_disconnect(sk, 0, 0, 0);			x25_destroy_socket(sk);			goto out;		case X25_STATE_1:		case X25_STATE_3:		case X25_STATE_4:			x25_clear_queues(sk);			x25_write_internal(sk, X25_CLEAR_REQUEST);			x25_start_t23timer(sk);			x25->state = X25_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;	}	sock->sk	= NULL;		sk->sk_socket	= NULL;	/* Not used, but we should do this */out:	return 0;}static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len){	struct sock *sk = sock->sk;	struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;	if (!sk->sk_zapped ||	    addr_len != sizeof(struct sockaddr_x25) ||	    addr->sx25_family != AF_X25)		return -EINVAL;	x25_sk(sk)->source_addr = addr->sx25_addr;	x25_insert_socket(sk);	sk->sk_zapped = 0;	SOCK_DEBUG(sk, "x25_bind: socket is bound\n");	return 0;}static int x25_wait_for_connection_establishment(struct sock *sk){	DECLARE_WAITQUEUE(wait, current);        int rc;	add_wait_queue_exclusive(sk->sk_sleep, &wait);	for (;;) {		__set_current_state(TASK_INTERRUPTIBLE);		rc = -ERESTARTSYS;		if (signal_pending(current))			break;		rc = sock_error(sk);		if (rc) {			sk->sk_socket->state = SS_UNCONNECTED;			break;		}		rc = 0;		if (sk->sk_state != TCP_ESTABLISHED) {			release_sock(sk);			schedule();			lock_sock(sk);		} else			break;	}	__set_current_state(TASK_RUNNING);	remove_wait_queue(sk->sk_sleep, &wait);	return rc;}static int x25_connect(struct socket *sock, struct sockaddr *uaddr,		       int addr_len, int flags){	struct sock *sk = sock->sk;	struct x25_opt *x25 = x25_sk(sk);	struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;	struct x25_route *rt;	int rc = 0;	lock_sock(sk);	if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {		sock->state = SS_CONNECTED;		goto out; /* Connect completed during a ERESTARTSYS event */	}	rc = -ECONNREFUSED;	if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) {		sock->state = SS_UNCONNECTED;		goto out;	}	rc = -EISCONN;	/* No reconnect on a seqpacket socket */	if (sk->sk_state == TCP_ESTABLISHED)		goto out;	sk->sk_state   = TCP_CLOSE;		sock->state = SS_UNCONNECTED;	rc = -EINVAL;	if (addr_len != sizeof(struct sockaddr_x25) ||	    addr->sx25_family != AF_X25)		goto out;	rc = -ENETUNREACH;	rt = x25_get_route(&addr->sx25_addr);	if (!rt)		goto out;	x25->neighbour = x25_get_neigh(rt->dev);	if (!x25->neighbour)		goto out_put_route;	x25_limit_facilities(&x25->facilities, x25->neighbour);	x25->lci = x25_new_lci(x25->neighbour);	if (!x25->lci)		goto out_put_neigh;	rc = -EINVAL;	if (sk->sk_zapped) /* Must bind first - autobinding does not work */		goto out_put_neigh;	if (!strcmp(x25->source_addr.x25_addr, null_x25_address.x25_addr))		memset(&x25->source_addr, '\0', X25_ADDR_LEN);	x25->dest_addr = addr->sx25_addr;	/* Move to connecting socket, start sending Connect Requests */	sock->state   = SS_CONNECTING;	sk->sk_state  = TCP_SYN_SENT;	x25->state = X25_STATE_1;	x25_write_internal(sk, X25_CALL_REQUEST);	x25_start_heartbeat(sk);	x25_start_t21timer(sk);	/* Now the loop */	rc = -EINPROGRESS;	if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK))		goto out_put_neigh;	rc = x25_wait_for_connection_establishment(sk);	if (rc)		goto out_put_neigh;	sock->state = SS_CONNECTED;	rc = 0;out_put_neigh:	if (rc)		x25_neigh_put(x25->neighbour);out_put_route:	x25_route_put(rt);out:	release_sock(sk);	return rc;}static int x25_wait_for_data(struct sock *sk, int timeout){	DECLARE_WAITQUEUE(wait, current);	int rc = 0;	add_wait_queue_exclusive(sk->sk_sleep, &wait);	for (;;) {		__set_current_state(TASK_INTERRUPTIBLE);		if (sk->sk_shutdown & RCV_SHUTDOWN)			break;		rc = -ERESTARTSYS;		if (signal_pending(current))			break;		rc = -EAGAIN;		if (!timeout)			break;		rc = 0;		if (skb_queue_empty(&sk->sk_receive_queue)) {			release_sock(sk);			timeout = schedule_timeout(timeout);			lock_sock(sk);		} else			break;	}	__set_current_state(TASK_RUNNING);	remove_wait_queue(sk->sk_sleep, &wait);	return rc;}	static int x25_accept(struct socket *sock, struct socket *newsock, int flags){	struct sock *sk = sock->sk;	struct sock *newsk;	struct sk_buff *skb;	int rc = -EINVAL;	if (!sk || sk->sk_state != TCP_LISTEN)		goto out;	rc = -EOPNOTSUPP;	if (sk->sk_type != SOCK_SEQPACKET)		goto out;	lock_sock(sk);	rc = x25_wait_for_data(sk, sk->sk_rcvtimeo);	if (rc)		goto out2;	skb = skb_dequeue(&sk->sk_receive_queue);	rc = -EINVAL;	if (!skb->sk)		goto out2;	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;	newsock->state = SS_CONNECTED;	rc = 0;out2:	release_sock(sk);out:	return rc;}static int x25_getname(struct socket *sock, struct sockaddr *uaddr,		       int *uaddr_len, int peer){	struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)uaddr;	struct sock *sk = sock->sk;	struct x25_opt *x25 = x25_sk(sk);	if (peer) {		if (sk->sk_state != TCP_ESTABLISHED)			return -ENOTCONN;		sx25->sx25_addr = x25->dest_addr;	} else		sx25->sx25_addr = x25->source_addr;	sx25->sx25_family = AF_X25;	*uaddr_len = sizeof(*sx25);	return 0;} int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,			unsigned int lci){	struct sock *sk;	struct sock *make;	struct x25_opt *makex25;	struct x25_address source_addr, dest_addr;	struct x25_facilities facilities;	int len, rc;	/*	 *	Remove the LCI and frame type.	 */	skb_pull(skb, X25_STD_MIN_LEN);	/*	 *	Extract the X.25 addresses and convert them to ASCII strings,	 *	and remove them.	 */	skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr));	/*	 *	Find a listener for the particular address.	 */	sk = x25_find_listener(&source_addr);	/*	 *	We can't accept the Call Request.	 */	if (!sk || sk->sk_ack_backlog == sk->sk_max_ack_backlog)		goto out_clear_request;	/*	 *	Try to reach a compromise on the requested facilities.	 */	if ((len = x25_negotiate_facilities(skb, sk, &facilities)) == -1)		goto out_sock_put;	/*	 * current neighbour/link might impose additional limits	 * on certain facilties	 */	x25_limit_facilities(&facilities, nb);	/*	 *	Try to create a new socket.	 */	make = x25_make_new(sk);	if (!make)		goto out_sock_put;	/*	 *	Remove the facilities, leaving any Call User Data.	 */	skb_pull(skb, len);	skb->sk     = make;	make->sk_state = TCP_ESTABLISHED;	makex25 = x25_sk(make);	makex25->lci           = lci;	makex25->dest_addr     = dest_addr;	makex25->source_addr   = source_addr;	makex25->neighbour     = nb;	makex25->facilities    = facilities;	makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask;	x25_write_internal(make, X25_CALL_ACCEPTED);	/*	 *	Incoming Call User Data.	 */	if (skb->len >= 0) {		memcpy(makex25->calluserdata.cuddata, skb->data, skb->len);		makex25->calluserdata.cudlength = skb->len;	}	makex25->state = X25_STATE_3;	sk->sk_ack_backlog++;	x25_insert_socket(make);	skb_queue_head(&sk->sk_receive_queue, skb);	x25_start_heartbeat(make);	if (!sock_flag(sk, SOCK_DEAD))		sk->sk_data_ready(sk, skb->len);	rc = 1;	sock_put(sk);out:	return rc;out_sock_put:	sock_put(sk);out_clear_request:	rc = 0;	x25_transmit_clear_request(nb, lci, 0x01);	goto out;}static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,		       struct msghdr *msg, size_t len){	struct sock *sk = sock->sk;	struct x25_opt *x25 = x25_sk(sk);	struct sockaddr_x25 *usx25 = (struct sockaddr_x25 *)msg->msg_name;	struct sockaddr_x25 sx25;	struct sk_buff *skb;	unsigned char *asmptr;	int noblock = msg->msg_flags & MSG_DONTWAIT;	size_t size;	int qbit = 0, rc = -EINVAL;	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT))		goto out;	/* we currently don't support segmented records at the user interface */	if (!(msg->msg_flags & (MSG_EOR|MSG_OOB)))		goto out;	rc = -EADDRNOTAVAIL;	if (sk->sk_zapped)		goto out;	rc = -EPIPE;	if (sk->sk_shutdown & SEND_SHUTDOWN) {		send_sig(SIGPIPE, current, 0);		goto out;	}	rc = -ENETUNREACH;

⌨️ 快捷键说明

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