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

📄 ddp.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
                ((struct net_device_stats *)dev->priv)->rx_bytes += skb->len + 13;                netif_rx(skb);  /* Send the SKB up to a higher place. */                return 0;        }#endif	/*	 * Which socket - atalk_search_socket() looks for a *full match*	 * of the <net,node,port> tuple.	 */	tosat.sat_addr.s_net  = ddp->deh_dnet;	tosat.sat_addr.s_node = ddp->deh_dnode;	tosat.sat_port = ddp->deh_dport;	sock = atalk_search_socket(&tosat, atif);		if (sock == NULL) {		/* But not one of our sockets */		kfree_skb(skb);		return 0;	}	/*	 *	Queue packet (standard)	 */	 	skb->sk = sock;	if (sock_queue_rcv_skb(sock, skb) < 0)		kfree_skb(skb);	return 0;}/* * Receive a LocalTalk frame. We make some demands on the caller here. * Caller must provide enough headroom on the packet to pull the short * header and append a long one. */static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt){	struct ddpehdr *ddp;	struct at_addr *ap;	/*	 * Expand any short form frames.	 */	if (skb->mac.raw[2] == 1) {		/*		 * Find our address.		 */		ap = atalk_find_dev_addr(dev);		if (ap == NULL || skb->len < sizeof(struct ddpshdr)) {			kfree_skb(skb);			return 0;		}		/*		 * The push leaves us with a ddephdr not an shdr, and		 * handily the port bytes in the right place preset.		 */		skb_push(skb, sizeof(*ddp) - 4);		ddp = (struct ddpehdr *)skb->data;		/*		 * Now fill in the long header.		 */	 	/*	 	 * These two first. The mac overlays the new source/dest	 	 * network information so we MUST copy these before	 	 * we write the network numbers !	 	 */		ddp->deh_dnode = skb->mac.raw[0];     /* From physical header */		ddp->deh_snode = skb->mac.raw[1];     /* From physical header */		ddp->deh_dnet  = ap->s_net;	/* Network number */		ddp->deh_snet  = ap->s_net;		ddp->deh_sum   = 0;		/* No checksum */		/*		 * Not sure about this bit...		 */		ddp->deh_len   = skb->len;		ddp->deh_hops  = DDP_MAXHOPS;	/* Non routable, so force a drop						   if we slip up later */		/* Mend the byte order */		*((__u16 *)ddp) = htons(*((__u16 *)ddp));	}	skb->h.raw = skb->data;	return atalk_rcv(skb, dev, pt);}static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm){	struct sock *sk = sock->sk;	struct sockaddr_at *usat = (struct sockaddr_at *)msg->msg_name;	struct sockaddr_at local_satalk, gsat;	struct sk_buff *skb;	struct net_device *dev;	struct ddpehdr *ddp;	int size;	struct atalk_route *rt;	int loopback = 0;	int err;	int flags = msg->msg_flags;	if (flags & ~MSG_DONTWAIT)		return -EINVAL;	if (len > DDP_MAXSZ)		return -EMSGSIZE;	if (usat) {		if(sk->zapped) {			if (atalk_autobind(sk) < 0)				return -EBUSY;		}		if (msg->msg_namelen < sizeof(*usat))			return -EINVAL;		if (usat->sat_family != AF_APPLETALK)			return -EINVAL;		/* netatalk doesn't implement this check */		if (usat->sat_addr.s_node == ATADDR_BCAST && !sk->broadcast) {			printk(KERN_INFO "SO_BROADCAST: Fix your netatalk as it will break before 2.2\n");#if 0			return -EPERM;#endif		}	} else {		if (sk->state != TCP_ESTABLISHED)			return -ENOTCONN;		usat = &local_satalk;		usat->sat_family = AF_APPLETALK;		usat->sat_port   = sk->protinfo.af_at.dest_port;		usat->sat_addr.s_node = sk->protinfo.af_at.dest_node;		usat->sat_addr.s_net  = sk->protinfo.af_at.dest_net;	}	/* Build a packet */	SOCK_DEBUG(sk, "SK %p: Got address.\n", sk);	/* For headers */	size = sizeof(struct ddpehdr) + len + ddp_dl->header_length;	if (usat->sat_addr.s_net != 0 || usat->sat_addr.s_node == ATADDR_ANYNODE) {		rt = atrtr_find(&usat->sat_addr);		if (rt == NULL)			return -ENETUNREACH;		dev = rt->dev;	} else {		struct at_addr at_hint;		at_hint.s_node = 0;		at_hint.s_net  = sk->protinfo.af_at.src_net;		rt = atrtr_find(&at_hint);		if (rt == NULL)			return -ENETUNREACH;		dev = rt->dev;	}	SOCK_DEBUG(sk, "SK %p: Size needed %d, device %s\n", sk, size, dev->name);	size += dev->hard_header_len;	skb = sock_alloc_send_skb(sk, size, 0, (flags & MSG_DONTWAIT), &err);	if (skb == NULL)		return err;		skb->sk = sk;	skb_reserve(skb, ddp_dl->header_length);	skb_reserve(skb, dev->hard_header_len);	skb->dev = dev;	SOCK_DEBUG(sk, "SK %p: Begin build.\n", sk);	ddp = (struct ddpehdr *)skb_put(skb, sizeof(struct ddpehdr));	ddp->deh_pad  = 0;	ddp->deh_hops = 0;	ddp->deh_len  = len + sizeof(*ddp);	/*	 * Fix up the length field [Ok this is horrible but otherwise	 * I end up with unions of bit fields and messy bit field order	 * compiler/endian dependencies..	 */	*((__u16 *)ddp) = ntohs(*((__u16 *)ddp));	ddp->deh_dnet  = usat->sat_addr.s_net;	ddp->deh_snet  = sk->protinfo.af_at.src_net;	ddp->deh_dnode = usat->sat_addr.s_node;	ddp->deh_snode = sk->protinfo.af_at.src_node;	ddp->deh_dport = usat->sat_port;	ddp->deh_sport = sk->protinfo.af_at.src_port;	SOCK_DEBUG(sk, "SK %p: Copy user data (%d bytes).\n", sk, len);	err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);	if (err) {		kfree_skb(skb);		return -EFAULT;	}	if (sk->no_check == 1)		ddp->deh_sum = 0;	else		ddp->deh_sum = atalk_checksum(ddp, len + sizeof(*ddp));	/*	 * Loopback broadcast packets to non gateway targets (ie routes	 * to group we are in)	 */	if (ddp->deh_dnode == ATADDR_BCAST) {		if ((!(rt->flags&RTF_GATEWAY)) && (!(dev->flags&IFF_LOOPBACK))) {			struct sk_buff *skb2 = skb_copy(skb, GFP_KERNEL);			if (skb2) {				loopback = 1;				SOCK_DEBUG(sk, "SK %p: send out(copy).\n", sk);				if (aarp_send_ddp(dev, skb2, &usat->sat_addr, NULL) == -1)					kfree_skb(skb2);				/* else queued/sent above in the aarp queue */			}		}	}	if ((dev->flags & IFF_LOOPBACK) || loopback) {		SOCK_DEBUG(sk, "SK %p: Loop back.\n", sk);		/* loop back */		skb_orphan(skb);		ddp_dl->datalink_header(ddp_dl, skb, dev->dev_addr);		skb->mac.raw = skb->data;		skb->h.raw   = skb->data + ddp_dl->header_length + dev->hard_header_len;		skb_pull(skb,dev->hard_header_len);		skb_pull(skb,ddp_dl->header_length);		atalk_rcv(skb, dev, NULL);	} else {		SOCK_DEBUG(sk, "SK %p: send out.\n", sk);		if (rt->flags & RTF_GATEWAY) {		    gsat.sat_addr = rt->gateway;		    usat = &gsat;		}		if (aarp_send_ddp(dev, skb, &usat->sat_addr, NULL) == -1)			kfree_skb(skb);		/* else queued/sent above in the aarp queue */	}	SOCK_DEBUG(sk, "SK %p: Done write (%d).\n", sk, len);	return len;}static int atalk_recvmsg(struct socket *sock, struct msghdr *msg, int size,			 int flags, struct scm_cookie *scm){	struct sock *sk = sock->sk;	struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name;	struct ddpehdr	*ddp = NULL;        struct ddpebits ddphv;	int copied = 0;	struct sk_buff *skb;	int err = 0;	skb = skb_recv_datagram(sk, (flags & ~MSG_DONTWAIT),				(flags & MSG_DONTWAIT), &err);	if (skb == NULL)		return err;	ddp = (struct ddpehdr *)(skb->h.raw);	*((__u16 *)&ddphv) = ntohs(*((__u16 *)ddp));	if (sk->type == SOCK_RAW) {		copied = ddphv.deh_len;		if (copied > size) {			copied = size;			msg->msg_flags |= MSG_TRUNC;		}		err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);	} else {		copied = ddphv.deh_len - sizeof(*ddp);		if (copied > size) {			copied = size;			msg->msg_flags |= MSG_TRUNC;		}		err = skb_copy_datagram_iovec(skb, sizeof(*ddp), msg->msg_iov, copied);	}	if (!err) {		if (sat) {			sat->sat_family      = AF_APPLETALK;			sat->sat_port        = ddp->deh_sport;			sat->sat_addr.s_node = ddp->deh_snode;			sat->sat_addr.s_net  = ddp->deh_snet;		}		msg->msg_namelen = sizeof(*sat);	}	skb_free_datagram(sk, skb);	/* Free the datagram. */	return err ? err : copied;}/* * AppleTalk ioctl calls. */static int atalk_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg){	long amount=0;	struct sock *sk=sock->sk;	switch(cmd)	{		/*		 *	Protocol layer		 */		case TIOCOUTQ:			amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);			if(amount < 0)				amount = 0;			break;		case TIOCINQ:		{			struct sk_buff *skb;			/* 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-sizeof(struct ddpehdr);			break;		}		case SIOCGSTAMP:			if(sk)			{				if(sk->stamp.tv_sec == 0)					return -ENOENT;				return (copy_to_user((void *)arg,&sk->stamp,sizeof(struct timeval)) ? -EFAULT : 0);			}			return (-EINVAL);		/*		 * Routing		 */		case SIOCADDRT:		case SIOCDELRT:			if(!capable(CAP_NET_ADMIN))				return -EPERM;			return (atrtr_ioctl(cmd,(void *)arg));		/*		 * Interface		 */		case SIOCGIFADDR:		case SIOCSIFADDR:		case SIOCGIFBRDADDR:		case SIOCATALKDIFADDR:		case SIOCDIFADDR:		case SIOCSARP:	/* proxy AARP */		case SIOCDARP:	/* proxy AARP */			return (atif_ioctl(cmd,(void *)arg));		/*		 * Physical layer ioctl calls		 */		case SIOCSIFLINK:		case SIOCGIFHWADDR:		case SIOCSIFHWADDR:		case SIOCGIFFLAGS:		case SIOCSIFFLAGS:		case SIOCGIFMTU:		case SIOCGIFCONF:		case SIOCADDMULTI:		case SIOCDELMULTI:		case SIOCGIFCOUNT:		case SIOCGIFINDEX:		case SIOCGIFNAME:			return ((dev_ioctl(cmd,(void *) arg)));		case SIOCSIFMETRIC:		case SIOCSIFBRDADDR:		case SIOCGIFNETMASK:		case SIOCSIFNETMASK:		case SIOCGIFMEM:		case SIOCSIFMEM:		case SIOCGIFDSTADDR:		case SIOCSIFDSTADDR:			return (-EINVAL);		default:			return (-EINVAL);	}	return (put_user(amount, (int *)arg));}static struct net_proto_family atalk_family_ops={	PF_APPLETALK,	atalk_create};static struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops)={	family:		PF_APPLETALK,	release:	atalk_release,	bind:		atalk_bind,	connect:	atalk_connect,	socketpair:	sock_no_socketpair,	accept:		sock_no_accept,	getname:	atalk_getname,	poll:		datagram_poll,	ioctl:		atalk_ioctl,	listen:		sock_no_listen,	shutdown:	sock_no_shutdown,	setsockopt:	sock_no_setsockopt,	getsockopt:	sock_no_getsockopt,	sendmsg:	atalk_sendmsg,	recvmsg:	atalk_recvmsg,	mmap:		sock_no_mmap,};#include <linux/smp_lock.h>SOCKOPS_WRAP(atalk_dgram, PF_APPLETALK);static struct notifier_block ddp_notifier={	ddp_device_event,	NULL,	0};struct packet_type ltalk_packet_type={	0,	NULL,	ltalk_rcv,	NULL,	NULL};struct packet_type ppptalk_packet_type={	0,	NULL,	atalk_rcv,	NULL,	NULL};static char ddp_snap_id[] = {0x08, 0x00, 0x07, 0x80, 0x9B};/* * Export symbols for use by drivers when AppleTalk is a module. */EXPORT_SYMBOL(aarp_send_ddp);EXPORT_SYMBOL(atrtr_get_dev);EXPORT_SYMBOL(atalk_find_dev_addr);/* Called by proto.c on kernel start up */static int __init atalk_init(void){	(void) sock_register(&atalk_family_ops);	if((ddp_dl = register_snap_client(ddp_snap_id, atalk_rcv)) == NULL)		printk(KERN_CRIT "Unable to register DDP with SNAP.\n");	ltalk_packet_type.type = htons(ETH_P_LOCALTALK);	dev_add_pack(&ltalk_packet_type);	ppptalk_packet_type.type = htons(ETH_P_PPPTALK);	dev_add_pack(&ppptalk_packet_type);	register_netdevice_notifier(&ddp_notifier);	aarp_proto_init();#ifdef CONFIG_PROC_FS	proc_net_create("appletalk", 0, atalk_get_info);	proc_net_create("atalk_route", 0, atalk_rt_get_info);	proc_net_create("atalk_iface", 0, atalk_if_get_info);	aarp_register_proc_fs();#endif /* CONFIG_PROC_FS */#ifdef CONFIG_SYSCTL	atalk_register_sysctl();#endif /* CONFIG_SYSCTL */	printk(KERN_INFO "NET4: AppleTalk 0.18 for Linux NET4.0\n");	return 0;}module_init(atalk_init);#ifdef MODULE/* * Note on MOD_{INC,DEC}_USE_COUNT: * * Use counts are incremented/decremented when * sockets are created/deleted. * * AppleTalk interfaces are not incremented untill atalkd is run * and are only decremented when they are downed. * * Ergo, before the AppleTalk module can be removed, all AppleTalk * sockets be closed from user space. */static void __exit atalk_exit(void){#ifdef CONFIG_SYSCTL	atalk_unregister_sysctl();#endif /* CONFIG_SYSCTL */#ifdef CONFIG_PROC_FS	proc_net_remove("appletalk");	proc_net_remove("atalk_route");	proc_net_remove("atalk_iface");	aarp_unregister_proc_fs();#endif /* CONFIG_PROC_FS */	aarp_cleanup_module();	/* General aarp clean-up. */	unregister_netdevice_notifier(&ddp_notifier);	dev_remove_pack(&ltalk_packet_type);	dev_remove_pack(&ppptalk_packet_type);	unregister_snap_client(ddp_snap_id);	sock_unregister(PF_APPLETALK);	return;}module_exit(atalk_exit);#endif  /* MODULE */#endif  /* CONFIG_ATALK || CONFIG_ATALK_MODULE */

⌨️ 快捷键说明

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