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

📄 af_ax25.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 4 页
字号:
	sk->sleep    = osk->sleep;	sk->zapped   = osk->zapped;	ax25->modulus = osk->protinfo.ax25->modulus;	ax25->backoff = osk->protinfo.ax25->backoff;	ax25->pidincl = osk->protinfo.ax25->pidincl;	ax25->iamdigi = osk->protinfo.ax25->iamdigi;	ax25->rtt     = osk->protinfo.ax25->rtt;	ax25->t1      = osk->protinfo.ax25->t1;	ax25->t2      = osk->protinfo.ax25->t2;	ax25->t3      = osk->protinfo.ax25->t3;	ax25->n2      = osk->protinfo.ax25->n2;	ax25->idle    = osk->protinfo.ax25->idle;	ax25->paclen  = osk->protinfo.ax25->paclen;	ax25->window  = osk->protinfo.ax25->window;	ax25->ax25_dev    = ax25_dev;	ax25->source_addr = osk->protinfo.ax25->source_addr;	if (osk->protinfo.ax25->digipeat != NULL) {		if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {			sk_free(sk);			return NULL;		}		memcpy(ax25->digipeat, osk->protinfo.ax25->digipeat, sizeof(ax25_digi));	}	sk->protinfo.ax25 = ax25;	ax25->sk          = sk;	return sk;}static int ax25_release(struct socket *sock){	struct sock *sk = sock->sk;	if (sk == NULL) return 0;	if (sk->type == SOCK_SEQPACKET) {		switch (sk->protinfo.ax25->state) {			case AX25_STATE_0:				ax25_disconnect(sk->protinfo.ax25, 0);				ax25_destroy_socket(sk->protinfo.ax25);				break;			case AX25_STATE_1:			case AX25_STATE_2:				ax25_send_control(sk->protinfo.ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);				ax25_disconnect(sk->protinfo.ax25, 0);				ax25_destroy_socket(sk->protinfo.ax25);				break;			case AX25_STATE_3:			case AX25_STATE_4:				ax25_clear_queues(sk->protinfo.ax25);				sk->protinfo.ax25->n2count = 0;				switch (sk->protinfo.ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {					case AX25_PROTO_STD_SIMPLEX:					case AX25_PROTO_STD_DUPLEX:						ax25_send_control(sk->protinfo.ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);						ax25_stop_t2timer(sk->protinfo.ax25);						ax25_stop_t3timer(sk->protinfo.ax25);						ax25_stop_idletimer(sk->protinfo.ax25);						break;#ifdef CONFIG_AX25_DAMA_SLAVE					case AX25_PROTO_DAMA_SLAVE:						ax25_stop_t3timer(sk->protinfo.ax25);						ax25_stop_idletimer(sk->protinfo.ax25);						break;#endif				}				ax25_calculate_t1(sk->protinfo.ax25);				ax25_start_t1timer(sk->protinfo.ax25);				sk->protinfo.ax25->state = AX25_STATE_2;				sk->state                = TCP_CLOSE;				sk->shutdown            |= SEND_SHUTDOWN;				sk->state_change(sk);				sock_orphan(sk);				sk->destroy              = 1;				break;			default:				break;		}	} else {		sk->state     = TCP_CLOSE;		sk->shutdown |= SEND_SHUTDOWN;		sk->state_change(sk);		sock_orphan(sk);		ax25_destroy_socket(sk->protinfo.ax25);	}	sock->sk   = NULL;		sk->socket = NULL;	/* Not used, but we should do this */	return 0;}/* *	We support a funny extension here so you can (as root) give any callsign *	digipeated via a local address as source. This hack is obsolete now *	that we've implemented support for SO_BINDTODEVICE. It is however small  *	and trivially backward compatible. */static int ax25_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;	ax25_address *call;	ax25_dev *ax25_dev = NULL;	if (sk->zapped == 0)		return -EINVAL;	if (addr_len != sizeof(struct sockaddr_ax25) && 	    addr_len != sizeof(struct full_sockaddr_ax25)) {		/* support for old structure may go away some time */		if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) ||		    (addr_len > sizeof(struct full_sockaddr_ax25)))			return -EINVAL;		printk(KERN_WARNING "ax25_bind(): %s uses old (6 digipeater) socket structure.\n",			current->comm);	}	if (addr->fsa_ax25.sax25_family != AF_AX25)		return -EINVAL;	call = ax25_findbyuid(current->euid);	if (call == NULL && ax25_uid_policy && !capable(CAP_NET_ADMIN))		return -EACCES;	if (call == NULL)		sk->protinfo.ax25->source_addr = addr->fsa_ax25.sax25_call;	else		sk->protinfo.ax25->source_addr = *call;	/*	 * User already set interface with SO_BINDTODEVICE	 */	if (sk->protinfo.ax25->ax25_dev != NULL)		goto done;	if (addr_len > sizeof(struct sockaddr_ax25) && addr->fsa_ax25.sax25_ndigis == 1) {		if (ax25cmp(&addr->fsa_digipeater[0], &null_ax25_address) != 0 &&		    (ax25_dev = ax25_addr_ax25dev(&addr->fsa_digipeater[0])) == NULL)			return -EADDRNOTAVAIL;	}  else {		if ((ax25_dev = ax25_addr_ax25dev(&addr->fsa_ax25.sax25_call)) == NULL)			return -EADDRNOTAVAIL;	}	if (ax25_dev != NULL)		ax25_fillin_cb(sk->protinfo.ax25, ax25_dev);done:	ax25_insert_socket(sk->protinfo.ax25);	sk->zapped = 0;	return 0;}/* *	FIXME: nonblock behaviour looks like it may have a bug. */static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags){	struct sock *sk = sock->sk;	struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)uaddr;	ax25_digi *digi = NULL;	int ct = 0, err;	/* deal with restarts */	if (sock->state == SS_CONNECTING) {		switch (sk->state) {		case TCP_SYN_SENT: /* still trying */			return -EINPROGRESS;		case TCP_ESTABLISHED: /* connection established */			sock->state = SS_CONNECTED;			return 0;		case TCP_CLOSE: /* connection refused */			sock->state = SS_UNCONNECTED;			return -ECONNREFUSED;		}	}	if (sk->state == TCP_ESTABLISHED && sk->type == SOCK_SEQPACKET)		return -EISCONN;	/* No reconnect on a seqpacket socket */	sk->state   = TCP_CLOSE;	sock->state = SS_UNCONNECTED;	/*	 * some sanity checks. code further down depends on this	 */	if (addr_len == sizeof(struct sockaddr_ax25)) {		/* support for this will go away in early 2.5.x */		printk(KERN_WARNING "ax25_connect(): %s uses obsolete socket structure\n",			current->comm);	}	else if (addr_len != sizeof(struct full_sockaddr_ax25)) {		/* support for old structure may go away some time */		if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) ||		    (addr_len > sizeof(struct full_sockaddr_ax25)))			return -EINVAL;		printk(KERN_WARNING "ax25_connect(): %s uses old (6 digipeater) socket structure.\n",			current->comm);	}	if (fsa->fsa_ax25.sax25_family != AF_AX25)		return -EINVAL;	if (sk->protinfo.ax25->digipeat != NULL) {		kfree(sk->protinfo.ax25->digipeat);		sk->protinfo.ax25->digipeat = NULL;	}		/*	 *	Handle digi-peaters to be used.	 */	if (addr_len > sizeof(struct sockaddr_ax25) && fsa->fsa_ax25.sax25_ndigis != 0) {		/* Valid number of digipeaters ? */		if (fsa->fsa_ax25.sax25_ndigis < 1 || fsa->fsa_ax25.sax25_ndigis > AX25_MAX_DIGIS)			return -EINVAL;		if ((digi = kmalloc(sizeof(ax25_digi), GFP_KERNEL)) == NULL)			return -ENOBUFS;		digi->ndigi      = fsa->fsa_ax25.sax25_ndigis;		digi->lastrepeat = -1;		while (ct < fsa->fsa_ax25.sax25_ndigis) {			if ((fsa->fsa_digipeater[ct].ax25_call[6] & AX25_HBIT) && sk->protinfo.ax25->iamdigi) {				digi->repeated[ct] = 1;				digi->lastrepeat   = ct;			} else {				digi->repeated[ct] = 0;			}			digi->calls[ct] = fsa->fsa_digipeater[ct];			ct++;		}	}	/*	 *	Must bind first - autobinding in this may or may not work. If	 *	the socket is already bound, check to see if the device has	 *	been filled in, error if it hasn't.	 */	if (sk->zapped) {		/* check if we can remove this feature. It is broken. */		printk(KERN_WARNING "ax25_connect(): %s uses autobind, please contact jreuter@yaina.de\n",			current->comm);		if ((err = ax25_rt_autobind(sk->protinfo.ax25, &fsa->fsa_ax25.sax25_call)) < 0)			return err;		ax25_fillin_cb(sk->protinfo.ax25, sk->protinfo.ax25->ax25_dev);		ax25_insert_socket(sk->protinfo.ax25);	} else {		if (sk->protinfo.ax25->ax25_dev == NULL)			return -EHOSTUNREACH;	}	if (sk->type == SOCK_SEQPACKET && ax25_find_cb(&sk->protinfo.ax25->source_addr, &fsa->fsa_ax25.sax25_call, digi, sk->protinfo.ax25->ax25_dev->dev) != NULL) {		if (digi != NULL) kfree(digi);		return -EADDRINUSE;			/* Already such a connection */	}	sk->protinfo.ax25->dest_addr = fsa->fsa_ax25.sax25_call;	sk->protinfo.ax25->digipeat  = digi;	/* First the easy one */	if (sk->type != SOCK_SEQPACKET) {		sock->state = SS_CONNECTED;		sk->state   = TCP_ESTABLISHED;		return 0;	}	/* Move to connecting socket, ax.25 lapb WAIT_UA.. */	sock->state        = SS_CONNECTING;	sk->state          = TCP_SYN_SENT;	switch (sk->protinfo.ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {		case AX25_PROTO_STD_SIMPLEX:		case AX25_PROTO_STD_DUPLEX:			ax25_std_establish_data_link(sk->protinfo.ax25);			break;#ifdef CONFIG_AX25_DAMA_SLAVE		case AX25_PROTO_DAMA_SLAVE:			sk->protinfo.ax25->modulus = AX25_MODULUS;			sk->protinfo.ax25->window  = sk->protinfo.ax25->ax25_dev->values[AX25_VALUES_WINDOW];			if (sk->protinfo.ax25->ax25_dev->dama.slave)				ax25_ds_establish_data_link(sk->protinfo.ax25);			else				ax25_std_establish_data_link(sk->protinfo.ax25);			break;#endif	}	sk->protinfo.ax25->state = AX25_STATE_1;	ax25_start_heartbeat(sk->protinfo.ax25);	/* Now the loop */	if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK))		return -EINPROGRESS;	cli();	/* To avoid races on the sleep */	/* A DM or timeout will go to closed, a UA will go to ABM */	while (sk->state == TCP_SYN_SENT) {		interruptible_sleep_on(sk->sleep);		if (signal_pending(current)) {			sti();			return -ERESTARTSYS;		}	}	if (sk->state != TCP_ESTABLISHED) {		/* Not in ABM, not in WAIT_UA -> failed */		sti();		sock->state = SS_UNCONNECTED;		return sock_error(sk);	/* Always set at this point */	}	sock->state = SS_CONNECTED;	sti();	return 0;}static int ax25_accept(struct socket *sock, struct socket *newsock, int flags){	struct sock *sk;	struct sock *newsk;	struct sk_buff *skb;	if (sock->state != SS_UNCONNECTED)		return -EINVAL;	if ((sk = sock->sk) == NULL)		return -EINVAL;	if (sk->type != SOCK_SEQPACKET)		return -EOPNOTSUPP;	if (sk->state != TCP_LISTEN)		return -EINVAL;	/*	 *	The read queue this time is holding sockets ready to use	 *	hooked into the SABM we saved	 */	do {		if ((skb = skb_dequeue(&sk->receive_queue)) == NULL) {			if (flags & O_NONBLOCK)				return -EWOULDBLOCK;			interruptible_sleep_on(sk->sleep);			if (signal_pending(current)) 				return -ERESTARTSYS;		}	} while (skb == NULL);	newsk = skb->sk;	newsk->pair = NULL;	newsk->socket = newsock;	newsk->sleep = &newsock->wait;	/* Now attach up the new socket */	kfree_skb(skb);	sk->ack_backlog--;	newsock->sk    = newsk;	newsock->state = SS_CONNECTED;	return 0;}static int ax25_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer){	struct sock *sk = sock->sk;	struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)uaddr;	unsigned char ndigi, i;	if (peer != 0) {		if (sk->state != TCP_ESTABLISHED)			return -ENOTCONN;		fsa->fsa_ax25.sax25_family = AF_AX25;		fsa->fsa_ax25.sax25_call   = sk->protinfo.ax25->dest_addr;		fsa->fsa_ax25.sax25_ndigis = 0;		if (sk->protinfo.ax25->digipeat != NULL) {			ndigi = sk->protinfo.ax25->digipeat->ndigi;			fsa->fsa_ax25.sax25_ndigis = ndigi;			for (i = 0; i < ndigi; i++)				fsa->fsa_digipeater[i] = sk->protinfo.ax25->digipeat->calls[i];		}	} else {		fsa->fsa_ax25.sax25_family = AF_AX25;		fsa->fsa_ax25.sax25_call   = sk->protinfo.ax25->source_addr;		fsa->fsa_ax25.sax25_ndigis = 1;		if (sk->protinfo.ax25->ax25_dev != NULL) {			memcpy(&fsa->fsa_digipeater[0], sk->protinfo.ax25->ax25_dev->dev->dev_addr, AX25_ADDR_LEN);		} else {			fsa->fsa_digipeater[0] = null_ax25_address;		}	}	*uaddr_len = sizeof (struct full_sockaddr_ax25);	return 0;}static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm){	struct sock *sk = sock->sk;	struct sockaddr_ax25 *usax = (struct sockaddr_ax25 *)msg->msg_name;	int err;	struct sockaddr_ax25 sax;	struct sk_buff *skb;	unsigned char *asmptr;	int size;	ax25_digi *dp;	ax25_digi dtmp;	int lv;	int addr_len = msg->msg_namelen;	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR))		return -EINVAL;	if (sk->zapped)		return -EADDRNOTAVAIL;	if (sk->shutdown & SEND_SHUTDOWN) {		send_sig(SIGPIPE, current, 0);		return -EPIPE;	}	if (sk->protinfo.ax25->ax25_dev == NULL)		return -ENETUNREACH;	if (usax != NULL) {		if (usax->sax25_family != AF_AX25)			return -EINVAL;		if (addr_len == sizeof(struct sockaddr_ax25)) {			printk(KERN_WARNING "ax25_sendmsg(): %s uses obsolete socket structure\n",				current->comm);		}		else if (addr_len != sizeof(struct full_sockaddr_ax25)) {			/* support for old structure may go away some time */			if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) ||		    	    (addr_len > sizeof(struct full_sockaddr_ax25)))		    		return -EINVAL;			printk(KERN_WARNING "ax25_sendmsg(): %s uses old (6 digipeater) socket structure.\n",				current->comm);		}		if (addr_len > sizeof(struct sockaddr_ax25) && usax->sax25_ndigis != 0) {			int ct           = 0;			struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)usax;			/* Valid number of digipeaters ? */			if (usax->sax25_ndigis < 1 || usax->sax25_ndigis > AX25_MAX_DIGIS)

⌨️ 快捷键说明

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