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

📄 af_x25.c

📁 之前积累的一个X25在LINUX下的协议实现代码,现在估计应该比较少见了,应该是收藏的东西
💻 C
📖 第 1 页 / 共 3 页
字号:
	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_state       = TCP_ESTABLISHED;	sk->sk_sleep       = osk->sk_sleep;	sk->sk_backlog_rcv = osk->sk_backlog_rcv;	sock_copy_flags(sk, osk);	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->dte_facilities = ox25->dte_facilities;	x25->cudmatchlength = ox25->cudmatchlength;	x25->accptapprv = ox25->accptapprv;	x25_init_timers(sk);out:	return sk;}static int x25_release(struct socket *sock){	struct sock *sk = sock->sk;	struct x25_sock *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 (!sock_flag(sk, SOCK_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);	sock_reset_flag(sk, SOCK_ZAPPED);	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_sock *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 (sock_flag(sk, SOCK_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, long 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_sock *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_sock *makex25;	struct x25_address source_addr, dest_addr;	struct x25_facilities facilities;	struct x25_dte_facilities dte_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));	/*	 *	Get the length of the facilities, skip past them for the moment	 *	get the call user data because this is needed to determine	 *	the correct listener	 */	len = skb->data[0] + 1;	skb_pull(skb,len);	/*	 *	Find a listener for the particular address/cud pair.	 */	sk = x25_find_listener(&source_addr,skb);	skb_push(skb,len);	/*	 *	We can't accept the Call Request.	 */	if (sk == NULL || sk_acceptq_is_full(sk))		goto out_clear_request;	/*	 *	Try to reach a compromise on the requested facilities.	 */	len = x25_negotiate_facilities(skb, sk, &facilities, &dte_facilities);	if (len == -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	 */	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->dte_facilities= dte_facilities;	makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask;	/* ensure no reverse facil on accept */	makex25->vc_facil_mask &= ~X25_MASK_REVERSE;	/* ensure no calling address extension on accept */	makex25->vc_facil_mask &= ~X25_MASK_CALLING_AE;	makex25->cudmatchlength = x25_sk(sk)->cudmatchlength;	/* Normally all calls are accepted immediatly */	if(makex25->accptapprv & X25_DENY_ACCPT_APPRV) {		x25_write_internal(make, X25_CALL_ACCEPTED);		makex25->state = X25_STATE_3;	}	/*	 *	Incoming Call User Data.	 */	if (skb->len >= 0) {		memcpy(makex25->calluserdata.cuddata, skb->data, skb->len);		makex25->calluserdata.cudlength = skb->len;	}	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_sock *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 (sock_flag(sk, SOCK_ZAPPED))		goto out;	rc = -EPIPE;	if (sk->sk_shutdown & SEND_SHUTDOWN) {		send_sig(SIGPIPE, current, 0);		goto out;	}	rc = -ENETUNREACH;	if (!x25->neighbour)		goto out;	if (usx25) {		rc = -EINVAL;		if (msg->msg_namelen < sizeof(sx25))			goto out;		memcpy(&sx25, usx25, sizeof(sx25));		rc = -EISCONN;		if (strcmp(x25->dest_addr.x25_addr, sx25.sx25_addr.x25_addr))			goto out;		rc = -EINVAL;		if (sx25.sx25_family != AF_X25)			goto out;	} else {		/*		 *	FIXME 1003.1g - if the socket is like this because		 *	it has become closed (not started closed) we ought		 *	to SIGPIPE, EPIPE;		 */		rc = -ENOTCONN;		if (sk->sk_state != TCP_ESTABLISHED)			goto out;		sx25.sx25_family = AF_X25;		sx25.sx25_addr   = x25->dest_addr;	}	SOCK_DEBUG(sk, "x25_sendmsg: sendto: Addresses built.\n");	/* Build a packet */	SOCK_DEBUG(sk, "x25_sendmsg: sendto: building packet.\n");	if ((msg->msg_flags & MSG_OOB) && len > 32)		len = 32;	size = len + X25_MAX_L2_LEN + X25_EXT_MIN_LEN;	skb = sock_alloc_send_skb(sk, size, noblock, &rc);	if (!skb)		goto out;	X25_SKB_CB(skb)->flags = msg->msg_flags;	skb_reserve(skb, X25_MAX_L2_LEN + X25_EXT_MIN_LEN);	/*	 *	Put the data on the end	 */	SOCK_DEBUG(sk, "x25_sendmsg: Copying user data\n");	asmptr = skb->h.raw = skb_put(skb, len);	rc = memcpy_fromiovec(asmptr, msg->msg_iov, len);	if (rc)		goto out_kfree_skb;	/*	 *	If the Q BIT Include socket option is in force, the first	 *	byte of the user data is the logical value of the Q Bit.	 */	if (x25->qbitincl) {		qbit = skb->data[0];		skb_pull(skb, 1);	}	/*	 *	Push down the X.25 header	 */	SOCK_DEBUG(sk, "x25_sendmsg: Building X.25 Header.\n");	if (msg->msg_flags & MSG_OOB) {		if (x25->neighbour->extended) {			asmptr    = skb_push(skb, X25_STD_MIN_LEN);			*asmptr++ = ((x25->lci >> 8) & 0x0F) | X25_GFI_EXTSEQ;			*asmptr++ = (x25->lci >> 0) & 0xFF;			*asmptr++ = X25_INTERRUPT;		} else {			asmptr    = skb_push(skb, X25_STD_MIN_LEN);			*asmptr++ = ((x25->lci >> 8) & 0x0F) | X25_GFI_STDSEQ;			*asmptr++ = (x25->lci >> 0) & 0xFF;			*asmptr++ = X25_INTERRUPT;		}	} else {		if (x25->neighbour->extended) {			/* Build an Extended X.25 header */			asmptr    = skb_push(skb, X25_EXT_MIN_LEN);			*asmptr++ = ((x25->lci >> 8) & 0x0F) | X25_GFI_EXTSEQ;			*asmptr++ = (x25->lci >> 0) & 0xFF;			*asmptr++ = X25_DATA;			*asmptr++ = X25_DATA;		} else {			/* Build an Standard X.25 header */			asmptr    = skb_push(skb, X25_STD_MIN_LEN);			*asmptr++ = ((x25->lci >> 8) & 0x0F) | X25_GFI_STDSEQ;			*asmptr++ = (x25->lci >> 0) & 0xFF;			*asmptr++ = X25_DATA;		}		if (qbit)			skb->data[0] |= X25_Q_BIT;	}	SOCK_DEBUG(sk, "x25_sendmsg: Built header.\n");	SOCK_DEBUG(sk, "x25_sendmsg: Transmitting buffer\n");	rc = -ENOTCONN;	if (sk->sk_state != TCP_ESTABLISHED)		goto out_kfree_skb;

⌨️ 快捷键说明

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