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

📄 af_x25.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	 */	SOCK_DEBUG(sk, "x25_sendmsg: Copying user data\n");	asmptr = skb->h.raw = skb_put(skb, len);	memcpy_fromiovec(asmptr, msg->msg_iov, len);	/*	 *	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 (sk->protinfo.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 (sk->protinfo.x25->neighbour->extended) {			asmptr    = skb_push(skb, X25_STD_MIN_LEN);			*asmptr++ = ((sk->protinfo.x25->lci >> 8) & 0x0F) | X25_GFI_EXTSEQ;			*asmptr++ = (sk->protinfo.x25->lci >> 0) & 0xFF;			*asmptr++ = X25_INTERRUPT;		} else {			asmptr    = skb_push(skb, X25_STD_MIN_LEN);			*asmptr++ = ((sk->protinfo.x25->lci >> 8) & 0x0F) | X25_GFI_STDSEQ;			*asmptr++ = (sk->protinfo.x25->lci >> 0) & 0xFF;			*asmptr++ = X25_INTERRUPT;		}	} else {		if (sk->protinfo.x25->neighbour->extended) {			/* Build an Extended X.25 header */			asmptr    = skb_push(skb, X25_EXT_MIN_LEN);			*asmptr++ = ((sk->protinfo.x25->lci >> 8) & 0x0F) | X25_GFI_EXTSEQ;			*asmptr++ = (sk->protinfo.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++ = ((sk->protinfo.x25->lci >> 8) & 0x0F) | X25_GFI_STDSEQ;			*asmptr++ = (sk->protinfo.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");	if (sk->state != TCP_ESTABLISHED) {		kfree_skb(skb);		return -ENOTCONN;	}	if (msg->msg_flags & MSG_OOB) {		skb_queue_tail(&sk->protinfo.x25->interrupt_out_queue, skb);	} else {	        len = x25_output(sk, skb);		if(len<0){			kfree_skb(skb);		} else {			if(sk->protinfo.x25->qbitincl) len++;		}	}	/*	 * lock_sock() is currently only used to serialize this x25_kick()	 * against input-driven x25_kick() calls. It currently only blocks	 * incoming packets for this socket and does not protect against	 * any other socket state changes and is not called from anywhere	 * else. As x25_kick() cannot block and as long as all socket	 * operations are BKL-wrapped, we don't need take to care about	 * purging the backlog queue in x25_release().	 *	 * Using lock_sock() to protect all socket operations entirely	 * (and making the whole x25 stack SMP aware) unfortunately would	 * require major changes to {send,recv}msg and skb allocation methods.	 * -> 2.5 ;)	 */	lock_sock(sk);	x25_kick(sk);	release_sock(sk);	return len;}static int x25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags, struct scm_cookie *scm){	struct sock *sk = sock->sk;	struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)msg->msg_name;	int copied, qbit;	struct sk_buff *skb;	unsigned char *asmptr;	int er;	/*	 * This works for seqpacket too. The receiver has ordered the queue for	 * us! We do one quick check first though	 */	if (sk->state != TCP_ESTABLISHED)		return -ENOTCONN;	if (flags & MSG_OOB) {		if (sk->urginline || skb_peek(&sk->protinfo.x25->interrupt_in_queue) == NULL)			return -EINVAL;		skb = skb_dequeue(&sk->protinfo.x25->interrupt_in_queue);		skb_pull(skb, X25_STD_MIN_LEN);		/*		 *	No Q bit information on Interrupt data.		 */		if (sk->protinfo.x25->qbitincl) {			asmptr  = skb_push(skb, 1);			*asmptr = 0x00;		}		msg->msg_flags |= MSG_OOB;	} else {		/* Now we can treat all alike */		if ((skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &er)) == NULL)			return er;		qbit = (skb->data[0] & X25_Q_BIT) == X25_Q_BIT;		skb_pull(skb, (sk->protinfo.x25->neighbour->extended) ? X25_EXT_MIN_LEN : X25_STD_MIN_LEN);		if (sk->protinfo.x25->qbitincl) {			asmptr  = skb_push(skb, 1);			*asmptr = qbit;		}	}	skb->h.raw = skb->data;	copied = skb->len;	if (copied > size) {		copied = size;		msg->msg_flags |= MSG_TRUNC;	}	/* Currently, each datagram always contains a complete record */ 	msg->msg_flags |= MSG_EOR;	skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);	if (sx25 != NULL) {		sx25->sx25_family = AF_X25;		sx25->sx25_addr   = sk->protinfo.x25->dest_addr;	}	msg->msg_namelen = sizeof(struct sockaddr_x25);	skb_free_datagram(sk, skb);	return copied;}static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg){	struct sock *sk = sock->sk;	switch (cmd) {		case TIOCOUTQ: {			int amount;			amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);			if (amount < 0)				amount = 0;			return put_user(amount, (unsigned int *)arg);		}		case TIOCINQ: {			struct sk_buff *skb;			int amount = 0;			/* These two are safe on a single CPU system as only user tasks fiddle here */			if ((skb = skb_peek(&sk->receive_queue)) != NULL)				amount = skb->len;			return put_user(amount, (unsigned int *)arg);		}		case SIOCGSTAMP:			if (sk != NULL) {				if (sk->stamp.tv_sec == 0)					return -ENOENT;				return copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)) ? -EFAULT : 0;			}			return -EINVAL;		case SIOCGIFADDR:		case SIOCSIFADDR:		case SIOCGIFDSTADDR:		case SIOCSIFDSTADDR:		case SIOCGIFBRDADDR:		case SIOCSIFBRDADDR:		case SIOCGIFNETMASK:		case SIOCSIFNETMASK:		case SIOCGIFMETRIC:		case SIOCSIFMETRIC:			return -EINVAL;		case SIOCADDRT:		case SIOCDELRT:			if (!capable(CAP_NET_ADMIN)) return -EPERM;			return x25_route_ioctl(cmd, (void *)arg);		case SIOCX25GSUBSCRIP:			return x25_subscr_ioctl(cmd, (void *)arg);		case SIOCX25SSUBSCRIP:			if (!capable(CAP_NET_ADMIN)) return -EPERM;			return x25_subscr_ioctl(cmd, (void *)arg);		case SIOCX25GFACILITIES: {			struct x25_facilities facilities;			facilities = sk->protinfo.x25->facilities;			return copy_to_user((void *)arg, &facilities, sizeof(facilities)) ? -EFAULT : 0;		}		case SIOCX25SFACILITIES: {			struct x25_facilities facilities;			if (copy_from_user(&facilities, (void *)arg, sizeof(facilities)))				return -EFAULT;			if (sk->state != TCP_LISTEN && sk->state != TCP_CLOSE)				return -EINVAL;			if (facilities.pacsize_in < X25_PS16 || facilities.pacsize_in > X25_PS4096)				return -EINVAL;			if (facilities.pacsize_out < X25_PS16 || facilities.pacsize_out > X25_PS4096)				return -EINVAL;			if (facilities.winsize_in < 1 || facilities.winsize_in > 127)				return -EINVAL;			if (facilities.throughput < 0x03 || facilities.throughput > 0xDD)				return -EINVAL;			if (facilities.reverse != 0 && facilities.reverse != 1)				return -EINVAL;			sk->protinfo.x25->facilities = facilities;			return 0;		}		case SIOCX25GCALLUSERDATA: {			struct x25_calluserdata calluserdata;			calluserdata = sk->protinfo.x25->calluserdata;			return copy_to_user((void *)arg, &calluserdata, sizeof(calluserdata)) ? -EFAULT : 0;		}		case SIOCX25SCALLUSERDATA: {			struct x25_calluserdata calluserdata;			if (copy_from_user(&calluserdata, (void *)arg, sizeof(calluserdata)))				return -EFAULT;			if (calluserdata.cudlength > X25_MAX_CUD_LEN)				return -EINVAL;			sk->protinfo.x25->calluserdata = calluserdata;			return 0;		}		case SIOCX25GCAUSEDIAG: {			struct x25_causediag causediag;			causediag = sk->protinfo.x25->causediag;			return copy_to_user((void *)arg, &causediag, sizeof(causediag)) ? -EFAULT : 0;		} 		default:			return dev_ioctl(cmd, (void *)arg);	}	/*NOTREACHED*/	return 0;}static int x25_get_info(char *buffer, char **start, off_t offset, int length){	struct sock *s;	struct net_device *dev;	const char *devname;	int len = 0;	off_t pos = 0;	off_t begin = 0;	cli();	len += sprintf(buffer, "dest_addr  src_addr   dev   lci st vs vr va   t  t2 t21 t22 t23 Snd-Q Rcv-Q inode\n");	for (s = x25_list; s != NULL; s = s->next) {		if (s->protinfo.x25->neighbour == NULL || (dev = s->protinfo.x25->neighbour->dev) == NULL)			devname = "???";		else			devname = s->protinfo.x25->neighbour->dev->name;		len += sprintf(buffer + len, "%-10s %-10s %-5s %3.3X  %d  %d  %d  %d %3lu %3lu %3lu %3lu %3lu %5d %5d %ld\n",			(s->protinfo.x25->dest_addr.x25_addr[0] == '\0')   ? "*" : s->protinfo.x25->dest_addr.x25_addr,			(s->protinfo.x25->source_addr.x25_addr[0] == '\0') ? "*" : s->protinfo.x25->source_addr.x25_addr,			devname, 			s->protinfo.x25->lci & 0x0FFF,			s->protinfo.x25->state,			s->protinfo.x25->vs,			s->protinfo.x25->vr,			s->protinfo.x25->va,			x25_display_timer(s) / HZ,			s->protinfo.x25->t2  / HZ,			s->protinfo.x25->t21 / HZ,			s->protinfo.x25->t22 / HZ,			s->protinfo.x25->t23 / HZ,			atomic_read(&s->wmem_alloc),			atomic_read(&s->rmem_alloc),			s->socket != NULL ? s->socket->inode->i_ino : 0L);		pos = begin + len;		if (pos < offset) {			len   = 0;			begin = pos;		}		if (pos > offset + length)			break;	}	sti();	*start = buffer + (offset - begin);	len   -= (offset - begin);	if (len > length) len = length;	return(len);} struct net_proto_family x25_family_ops = {	AF_X25,	x25_create};static struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {	family:		AF_X25,	release:	x25_release,	bind:		x25_bind,	connect:	x25_connect,	socketpair:	sock_no_socketpair,	accept:		x25_accept,	getname:	x25_getname,	poll:		datagram_poll,	ioctl:		x25_ioctl,	listen:		x25_listen,	shutdown:	sock_no_shutdown,	setsockopt:	x25_setsockopt,	getsockopt:	x25_getsockopt,	sendmsg:	x25_sendmsg,	recvmsg:	x25_recvmsg,	mmap:		sock_no_mmap,};#include <linux/smp_lock.h>SOCKOPS_WRAP(x25_proto, AF_X25);static struct packet_type x25_packet_type ={	0,		/* MUTTER ntohs(ETH_P_X25),*/	0,		/* copy */	x25_lapb_receive_frame,	NULL,	NULL,};struct notifier_block x25_dev_notifier = {	x25_device_event,	0};void x25_kill_by_neigh(struct x25_neigh *neigh){	struct sock *s;	for( s=x25_list; s != NULL; s=s->next){		if( s->protinfo.x25->neighbour == neigh )			x25_disconnect(s, ENETUNREACH, 0, 0);	} }static int __init x25_init(void){#ifdef MODULE	struct net_device *dev;#endif /* MODULE */	sock_register(&x25_family_ops);	x25_packet_type.type = htons(ETH_P_X25);	dev_add_pack(&x25_packet_type);	register_netdevice_notifier(&x25_dev_notifier);	printk(KERN_INFO "X.25 for Linux. Version 0.2 for Linux 2.1.15\n");#ifdef CONFIG_SYSCTL	x25_register_sysctl();#endif	proc_net_create("x25", 0, x25_get_info);	proc_net_create("x25_routes", 0, x25_routes_get_info);#ifdef MODULE	/*	 *	Register any pre existing devices.	 */	read_lock(&dev_base_lock);	for (dev = dev_base; dev != NULL; dev = dev->next) {		if ((dev->flags & IFF_UP) && (dev->type == ARPHRD_X25#if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)					   || dev->type == ARPHRD_ETHER#endif			))			x25_link_device_up(dev);	}	read_unlock(&dev_base_lock);#endif /* MODULE */	return 0;}module_init(x25_init);EXPORT_NO_SYMBOLS;MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");MODULE_DESCRIPTION("The X.25 Packet Layer network layer protocol");static void __exit x25_exit(void){	proc_net_remove("x25");	proc_net_remove("x25_routes");	x25_link_free();	x25_route_free();#ifdef CONFIG_SYSCTL	x25_unregister_sysctl();#endif	unregister_netdevice_notifier(&x25_dev_notifier);	dev_remove_pack(&x25_packet_type);	sock_unregister(AF_X25);}module_exit(x25_exit);

⌨️ 快捷键说明

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