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

📄 af_ax25.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
	case AX25_T1:		val = ax25->t1 / HZ;		break;	case AX25_T2:		val = ax25->t2 / HZ;		break;	case AX25_N2:		val = ax25->n2;		break;	case AX25_T3:		val = ax25->t3 / HZ;		break;	case AX25_IDLE:		val = ax25->idle / (60 * HZ);		break;	case AX25_BACKOFF:		val = ax25->backoff;		break;	case AX25_EXTSEQ:		val = (ax25->modulus == AX25_EMODULUS);		break;	case AX25_PIDINCL:		val = ax25->pidincl;		break;	case AX25_IAMDIGI:		val = ax25->iamdigi;		break;	case AX25_PACLEN:		val = ax25->paclen;		break;	case SO_BINDTODEVICE:		ax25_dev = ax25->ax25_dev;		if (ax25_dev != NULL && ax25_dev->dev != NULL) {			strlcpy(devname, ax25_dev->dev->name, sizeof(devname));			length = strlen(devname) + 1;		} else {			*devname = '\0';			length = 1;		}		valptr = (void *) devname;		break;	default:		release_sock(sk);		return -ENOPROTOOPT;	}	release_sock(sk);	if (put_user(length, optlen))		return -EFAULT;	return copy_to_user(optval, valptr, length) ? -EFAULT : 0;}static int ax25_listen(struct socket *sock, int backlog){	struct sock *sk = sock->sk;	int res = 0;	lock_sock(sk);	if (sk->sk_type == SOCK_SEQPACKET && sk->sk_state != TCP_LISTEN) {		sk->sk_max_ack_backlog = backlog;		sk->sk_state           = TCP_LISTEN;		goto out;	}	res = -EOPNOTSUPP;out:	release_sock(sk);	return res;}int ax25_create(struct socket *sock, int protocol){	struct sock *sk;	ax25_cb *ax25;	switch (sock->type) {	case SOCK_DGRAM:		if (protocol == 0 || protocol == PF_AX25)			protocol = AX25_P_TEXT;		break;	case SOCK_SEQPACKET:		switch (protocol) {		case 0:		case PF_AX25:	/* For CLX */			protocol = AX25_P_TEXT;			break;		case AX25_P_SEGMENT:#ifdef CONFIG_INET		case AX25_P_ARP:		case AX25_P_IP:#endif#ifdef CONFIG_NETROM		case AX25_P_NETROM:#endif#ifdef CONFIG_ROSE		case AX25_P_ROSE:#endif			return -ESOCKTNOSUPPORT;#ifdef CONFIG_NETROM_MODULE		case AX25_P_NETROM:			if (ax25_protocol_is_registered(AX25_P_NETROM))				return -ESOCKTNOSUPPORT;#endif#ifdef CONFIG_ROSE_MODULE		case AX25_P_ROSE:			if (ax25_protocol_is_registered(AX25_P_ROSE))				return -ESOCKTNOSUPPORT;#endif		default:			break;		}		break;	case SOCK_RAW:		break;	default:		return -ESOCKTNOSUPPORT;	}	if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, 1, NULL)) == NULL)		return -ENOMEM;	ax25 = sk->sk_protinfo = ax25_create_cb();	if (!ax25) {		sk_free(sk);		return -ENOMEM;	}	sock_init_data(sock, sk);	sk_set_owner(sk, THIS_MODULE);	sk->sk_destruct = ax25_free_sock;	sock->ops    = &ax25_proto_ops;	sk->sk_protocol = protocol;	ax25->sk    = sk;	return 0;}struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev){	struct sock *sk;	ax25_cb *ax25, *oax25;	if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, 1, NULL)) == NULL)		return NULL;	if ((ax25 = ax25_create_cb()) == NULL) {		sk_free(sk);		return NULL;	}	switch (osk->sk_type) {	case SOCK_DGRAM:		break;	case SOCK_SEQPACKET:		break;	default:		sk_free(sk);		ax25_cb_put(ax25);		return NULL;	}	sock_init_data(NULL, sk);	sk_set_owner(sk, THIS_MODULE);	sk->sk_destruct = ax25_free_sock;	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;	oax25 = ax25_sk(osk);	ax25->modulus = oax25->modulus;	ax25->backoff = oax25->backoff;	ax25->pidincl = oax25->pidincl;	ax25->iamdigi = oax25->iamdigi;	ax25->rtt     = oax25->rtt;	ax25->t1      = oax25->t1;	ax25->t2      = oax25->t2;	ax25->t3      = oax25->t3;	ax25->n2      = oax25->n2;	ax25->idle    = oax25->idle;	ax25->paclen  = oax25->paclen;	ax25->window  = oax25->window;	ax25->ax25_dev    = ax25_dev;	ax25->source_addr = oax25->source_addr;	if (oax25->digipeat != NULL) {		if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {			sk_free(sk);			ax25_cb_put(ax25);			return NULL;		}		memcpy(ax25->digipeat, oax25->digipeat, sizeof(ax25_digi));	}	sk->sk_protinfo = ax25;	ax25->sk    = sk;	return sk;}static int ax25_release(struct socket *sock){	struct sock *sk = sock->sk;	ax25_cb *ax25;	if (sk == NULL)		return 0;	sock_hold(sk);	sock_orphan(sk);	lock_sock(sk);	ax25 = ax25_sk(sk);	if (sk->sk_type == SOCK_SEQPACKET) {		switch (ax25->state) {		case AX25_STATE_0:			release_sock(sk);			ax25_disconnect(ax25, 0);			lock_sock(sk);			ax25_destroy_socket(ax25);			break;		case AX25_STATE_1:		case AX25_STATE_2:			ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);			release_sock(sk);			ax25_disconnect(ax25, 0);			lock_sock(sk);			ax25_destroy_socket(ax25);			break;		case AX25_STATE_3:		case AX25_STATE_4:			ax25_clear_queues(ax25);			ax25->n2count = 0;			switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {			case AX25_PROTO_STD_SIMPLEX:			case AX25_PROTO_STD_DUPLEX:				ax25_send_control(ax25,						  AX25_DISC,						  AX25_POLLON,						  AX25_COMMAND);				ax25_stop_t2timer(ax25);				ax25_stop_t3timer(ax25);				ax25_stop_idletimer(ax25);				break;#ifdef CONFIG_AX25_DAMA_SLAVE			case AX25_PROTO_DAMA_SLAVE:				ax25_stop_t3timer(ax25);				ax25_stop_idletimer(ax25);				break;#endif			}			ax25_calculate_t1(ax25);			ax25_start_t1timer(ax25);			ax25->state = AX25_STATE_2;			sk->sk_state                = TCP_CLOSE;			sk->sk_shutdown            |= SEND_SHUTDOWN;			sk->sk_state_change(sk);			sock_set_flag(sk, SOCK_DESTROY);			break;		default:			break;		}	} else {		sk->sk_state     = TCP_CLOSE;		sk->sk_shutdown |= SEND_SHUTDOWN;		sk->sk_state_change(sk);		ax25_destroy_socket(ax25);	}	sock->sk   = NULL;	release_sock(sk);	sock_put(sk);	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_dev *ax25_dev = NULL;	ax25_address *call;	ax25_cb *ax25;	int err = 0;	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;	}	lock_sock(sk);	ax25 = ax25_sk(sk);	if (!sk->sk_zapped) {		err = -EINVAL;		goto out;	}	if (call == NULL)		ax25->source_addr = addr->fsa_ax25.sax25_call;	else		ax25->source_addr = *call;	/*	 * User already set interface with SO_BINDTODEVICE	 */	if (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) {			err = -EADDRNOTAVAIL;			goto out;		}	} else {		if ((ax25_dev = ax25_addr_ax25dev(&addr->fsa_ax25.sax25_call)) == NULL) {			err = -EADDRNOTAVAIL;			goto out;		}	}	if (ax25_dev != NULL)		ax25_fillin_cb(ax25, ax25_dev);done:	ax25_cb_add(ax25);	sk->sk_zapped = 0;out:	release_sock(sk);	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;	ax25_cb *ax25 = ax25_sk(sk), *ax25t;	struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)uaddr;	ax25_digi *digi = NULL;	int ct = 0, err = 0;	/*	 * 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;	lock_sock(sk);	/* deal with restarts */	if (sock->state == SS_CONNECTING) {		switch (sk->sk_state) {		case TCP_SYN_SENT: /* still trying */			err = -EINPROGRESS;			goto out;		case TCP_ESTABLISHED: /* connection established */			sock->state = SS_CONNECTED;			goto out;		case TCP_CLOSE: /* connection refused */			sock->state = SS_UNCONNECTED;			err = -ECONNREFUSED;			goto out;		}	}	if (sk->sk_state == TCP_ESTABLISHED && sk->sk_type == SOCK_SEQPACKET) {		err = -EISCONN;	/* No reconnect on a seqpacket socket */		goto out;	}	sk->sk_state   = TCP_CLOSE;	sock->state = SS_UNCONNECTED;	if (ax25->digipeat != NULL) {		kfree(ax25->digipeat);		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) {			err = -EINVAL;			goto out;		}		if ((digi = kmalloc(sizeof(ax25_digi), GFP_KERNEL)) == NULL) {			err = -ENOBUFS;			goto out;		}		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) && 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->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(ax25, &fsa->fsa_ax25.sax25_call)) < 0) {			kfree(digi);			goto out;		}		ax25_fillin_cb(ax25, ax25->ax25_dev);		ax25_cb_add(ax25);	} else {		if (ax25->ax25_dev == NULL) {			kfree(digi);			err = -EHOSTUNREACH;			goto out;		}	}	if (sk->sk_type == SOCK_SEQPACKET &&	    (ax25t=ax25_find_cb(&ax25->source_addr, &fsa->fsa_ax25.sax25_call, digi,		    	 ax25->ax25_dev->dev))) {		kfree(digi);		err = -EADDRINUSE;		/* Already such a connection */		ax25_cb_put(ax25t);		goto out;	}	ax25->dest_addr = fsa->fsa_ax25.sax25_call;	ax25->digipeat  = digi;	/* First the easy one */	if (sk->sk_type != SOCK_SEQPACKET) {		sock->state = SS_CONNECTED;		sk->sk_state   = TCP_ESTABLISHED;		goto out;	}	/* Move to connecting socket, ax.25 lapb WAIT_UA.. */	sock->state        = SS_CONNECTING;	sk->sk_state          = TCP_SYN_SENT;	switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {	case AX25_PROTO_STD_SIMPLEX:	case AX25_PROTO_STD_DUPLEX:		ax25_std_establish_data_link(ax25);		break;#ifdef CONFIG_AX25_DAMA_SLAVE	case AX25_PROTO_DAMA_SLAVE:		ax25->modulus = AX25_MODULUS;		ax25->window  = ax25->ax25_dev->values[AX25_VALUES_WINDOW];		if (ax25->ax25_dev->dama.slave)			ax25_ds_establish_data_link(ax25);		else			ax25_std_establish_data_link(ax25);		break;#endif	}	ax25->state = AX25_STATE_1;	ax25_start_heartbeat(ax25);	/* Now the loop */	if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) {		err = -EINPROGRESS;		goto out;	}	if (sk->sk_state == TCP_SYN_SENT) {		struct task_struct *tsk = current;		DECLARE_WAITQUEUE(wait, tsk);		add_wait_queue(sk->sk_sleep, &wait);		for (;;) {			if (sk->sk_state != TCP_SYN_SENT)				break;			set_current_state(TASK_INTERRUPTIBLE);			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) {		/* Not in ABM, not in WAIT_UA -> failed */		sock->state = SS_UNCONNECTED;		err = sock_error(sk);	/* Always set at this point */		goto out;	}	sock->state = SS_CONNECTED;	err=0;out:	release_sock(sk);	return err;}static int ax25_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 (sock->state != SS_UNCONNECTED)		return -EINVAL;	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 read 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;		release_sock(sk);		current->state = TASK_INTERRUPTIBLE;		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;	newsock->state = SS_CONNECTED;out:	release_sock(sk);	return err;}static int ax25_getname(struct socket *sock, struct sockaddr *uaddr,	int *uaddr_len, int peer){

⌨️ 快捷键说明

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