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

📄 af_x25.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
static int x25_create(struct socket *sock, int protocol){	struct sock *sk;	x25_cb *x25;	if (sock->type != SOCK_SEQPACKET || protocol != 0)		return -ESOCKTNOSUPPORT;	if ((sk = x25_alloc_socket()) == NULL)		return -ENOMEM;	x25 = sk->protinfo.x25;	sock_init_data(sock, sk);	init_timer(&x25->timer);	sock->ops    = &x25_proto_ops;	sk->protocol = protocol;	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;	return 0;}static struct sock *x25_make_new(struct sock *osk){	struct sock *sk;	x25_cb *x25;	if (osk->type != SOCK_SEQPACKET)		return NULL;	if ((sk = x25_alloc_socket()) == NULL)		return NULL;	x25 = sk->protinfo.x25;	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;	sk->backlog_rcv = osk->backlog_rcv;	x25->t21        = osk->protinfo.x25->t21;	x25->t22        = osk->protinfo.x25->t22;	x25->t23        = osk->protinfo.x25->t23;	x25->t2         = osk->protinfo.x25->t2;	x25->facilities = osk->protinfo.x25->facilities;	x25->qbitincl   = osk->protinfo.x25->qbitincl;	init_timer(&x25->timer);	return sk;}static int x25_release(struct socket *sock){	struct sock *sk = sock->sk;	if (sk == NULL) return 0;	switch (sk->protinfo.x25->state) {		case X25_STATE_0:		case X25_STATE_2:			x25_disconnect(sk, 0, 0, 0);			x25_destroy_socket(sk);			break;		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);			sk->protinfo.x25->state = X25_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 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->zapped == 0)		return -EINVAL;	if (addr_len != sizeof(struct sockaddr_x25))		return -EINVAL;	if (addr->sx25_family != AF_X25)		return -EINVAL;	sk->protinfo.x25->source_addr = addr->sx25_addr;	x25_insert_socket(sk);	sk->zapped = 0;	SOCK_DEBUG(sk, "x25_bind: socket is bound\n");	return 0;}static int x25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags){	struct sock *sk = sock->sk;	struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;	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_x25))		return -EINVAL;	if (addr->sx25_family != AF_X25)		return -EINVAL;	if ((dev = x25_get_route(&addr->sx25_addr)) == NULL)		return -ENETUNREACH;	if ((sk->protinfo.x25->neighbour = x25_get_neigh(dev)) == NULL)		return -ENETUNREACH;	x25_limit_facilities(&sk->protinfo.x25->facilities,			     sk->protinfo.x25->neighbour);	if ((sk->protinfo.x25->lci = x25_new_lci(sk->protinfo.x25->neighbour)) == 0)		return -ENETUNREACH;	if (sk->zapped)		/* Must bind first - autobinding does not work */		return -EINVAL;	if (strcmp(sk->protinfo.x25->source_addr.x25_addr, null_x25_address.x25_addr) == 0)		memset(&sk->protinfo.x25->source_addr, '\0', X25_ADDR_LEN);	sk->protinfo.x25->dest_addr = addr->sx25_addr;	/* Move to connecting socket, start sending Connect Requests */	sock->state   = SS_CONNECTING;	sk->state     = TCP_SYN_SENT;	sk->protinfo.x25->state = X25_STATE_1;	x25_write_internal(sk, X25_CALL_REQUEST);	x25_start_heartbeat(sk);	x25_start_t21timer(sk);	/* Now the loop */	if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK))		return -EINPROGRESS;	cli();	/* To avoid races on the sleep */	/*	 * A Clear Request 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 x25_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 CALL INDICATION 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;	newsock->state = SS_CONNECTED;	return 0;}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;	if (peer != 0) {		if (sk->state != TCP_ESTABLISHED)			return -ENOTCONN;		sx25->sx25_addr   = sk->protinfo.x25->dest_addr;	} else {		sx25->sx25_addr   = sk->protinfo.x25->source_addr;	}	sx25->sx25_family = AF_X25;	*uaddr_len = sizeof(struct sockaddr_x25);	return 0;} int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned int lci){	struct sock *sk;	struct sock *make;	x25_address source_addr, dest_addr;	struct x25_facilities facilities;	int len;	/*	 *	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 == NULL || sk->ack_backlog == sk->max_ack_backlog) {		x25_transmit_clear_request(neigh, lci, 0x01);		return 0;	}	/*	 *	Try to reach a compromise on the requested facilities.	 */	if ((len = x25_negotiate_facilities(skb, sk, &facilities)) == -1) {		x25_transmit_clear_request(neigh, lci, 0x01);		return 0;	}	/*	 * current neighbour/link might impose additional limits	 * on certain facilties	 */	x25_limit_facilities(&facilities,neigh);	/*	 *	Try to create a new socket.	 */	if ((make = x25_make_new(sk)) == NULL) {		x25_transmit_clear_request(neigh, lci, 0x01);		return 0;	}	/*	 *	Remove the facilities, leaving any Call User Data.	 */	skb_pull(skb, len);	skb->sk     = make;	make->state = TCP_ESTABLISHED;	make->protinfo.x25->lci           = lci;	make->protinfo.x25->dest_addr     = dest_addr;	make->protinfo.x25->source_addr   = source_addr;	make->protinfo.x25->neighbour     = neigh;	make->protinfo.x25->facilities    = facilities;	make->protinfo.x25->vc_facil_mask = sk->protinfo.x25->vc_facil_mask;	x25_write_internal(make, X25_CALL_ACCEPTED);	/*	 *	Incoming Call User Data.	 */	if (skb->len >= 0) {		memcpy(make->protinfo.x25->calluserdata.cuddata, skb->data, skb->len);		make->protinfo.x25->calluserdata.cudlength = skb->len;	}	make->protinfo.x25->state = X25_STATE_3;	sk->ack_backlog++;	make->pair = sk;	x25_insert_socket(make);	skb_queue_head(&sk->receive_queue, skb);	x25_start_heartbeat(make);	if (!sk->dead)		sk->data_ready(sk, skb->len);	return 1;}static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm){	struct sock *sk = sock->sk;	struct sockaddr_x25 *usx25 = (struct sockaddr_x25 *)msg->msg_name;	int err;	struct sockaddr_x25 sx25;	struct sk_buff *skb;	unsigned char *asmptr;	int size, qbit = 0;	if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_OOB | MSG_EOR))		return -EINVAL;	/* we currently don't support segmented records at the user interface */	if (!(msg->msg_flags & (MSG_EOR|MSG_OOB)))		return -EINVAL;	if (sk->zapped)		return -EADDRNOTAVAIL;	if (sk->shutdown & SEND_SHUTDOWN) {		send_sig(SIGPIPE, current, 0);		return -EPIPE;	}	if (sk->protinfo.x25->neighbour == NULL)		return -ENETUNREACH;	if (usx25 != NULL) {		if (msg->msg_namelen < sizeof(sx25))			return -EINVAL;		sx25 = *usx25;		if (strcmp(sk->protinfo.x25->dest_addr.x25_addr, sx25.sx25_addr.x25_addr) != 0)			return -EISCONN;		if (sx25.sx25_family != AF_X25)			return -EINVAL;	} else {		/*		 *	FIXME 1003.1g - if the socket is like this because		 *	it has become closed (not started closed) we ought		 *	to SIGPIPE, EPIPE;		 */		if (sk->state != TCP_ESTABLISHED)			return -ENOTCONN;		sx25.sx25_family = AF_X25;		sx25.sx25_addr   = sk->protinfo.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;	if ((skb = sock_alloc_send_skb(sk, size, 0, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL)		return err;	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

⌨️ 快捷键说明

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