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

📄 udp.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
			/* process the ESP packet */			ret = xfrm4_rcv_encap(skb, up->encap_type);			UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS);			return -ret;		}		/* FALLTHROUGH -- it's a UDP Packet */	}	if (sk->sk_filter && skb->ip_summed != CHECKSUM_UNNECESSARY) {		if (__udp_checksum_complete(skb)) {			UDP_INC_STATS_BH(UDP_MIB_INERRORS);			kfree_skb(skb);			return -1;		}		skb->ip_summed = CHECKSUM_UNNECESSARY;	}	if (sock_queue_rcv_skb(sk,skb)<0) {		UDP_INC_STATS_BH(UDP_MIB_INERRORS);		kfree_skb(skb);		return -1;	}	UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS);	return 0;}/* *	Multicasts and broadcasts go to each listener. * *	Note: called only from the BH handler context, *	so we don't need to lock the hashes. */static int udp_v4_mcast_deliver(struct sk_buff *skb, struct udphdr *uh,				 u32 saddr, u32 daddr){	struct sock *sk;	int dif;	read_lock(&udp_hash_lock);	sk = sk_head(&udp_hash[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]);	dif = skb->dev->ifindex;	sk = udp_v4_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif);	if (sk) {		struct sock *sknext = NULL;		do {			struct sk_buff *skb1 = skb;			sknext = udp_v4_mcast_next(sk_next(sk), uh->dest, daddr,						   uh->source, saddr, dif);			if(sknext)				skb1 = skb_clone(skb, GFP_ATOMIC);			if(skb1) {				int ret = udp_queue_rcv_skb(sk, skb1);				if (ret > 0)					/* we should probably re-process instead					 * of dropping packets here. */					kfree_skb(skb1);			}			sk = sknext;		} while(sknext);	} else		kfree_skb(skb);	read_unlock(&udp_hash_lock);	return 0;}/* Initialize UDP checksum. If exited with zero value (success), * CHECKSUM_UNNECESSARY means, that no more checks are required. * Otherwise, csum completion requires chacksumming packet body, * including udp header and folding it to skb->csum. */static int udp_checksum_init(struct sk_buff *skb, struct udphdr *uh,			     unsigned short ulen, u32 saddr, u32 daddr){	if (uh->check == 0) {		skb->ip_summed = CHECKSUM_UNNECESSARY;	} else if (skb->ip_summed == CHECKSUM_HW) {		skb->ip_summed = CHECKSUM_UNNECESSARY;		if (!udp_check(uh, ulen, saddr, daddr, skb->csum))			return 0;		NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "udp v4 hw csum failure.\n"));		skb->ip_summed = CHECKSUM_NONE;	}	if (skb->ip_summed != CHECKSUM_UNNECESSARY)		skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);	/* Probably, we should checksum udp header (it should be in cache	 * in any case) and data in tiny packets (< rx copybreak).	 */	return 0;}/* *	All we need to do is get the socket, and then do a checksum.  */ int udp_rcv(struct sk_buff *skb){  	struct sock *sk;  	struct udphdr *uh;	unsigned short ulen;	struct rtable *rt = (struct rtable*)skb->dst;	u32 saddr = skb->nh.iph->saddr;	u32 daddr = skb->nh.iph->daddr;	int len = skb->len;	/*	 *	Validate the packet and the UDP length.	 */	if (!pskb_may_pull(skb, sizeof(struct udphdr)))		goto no_header;	uh = skb->h.uh;	ulen = ntohs(uh->len);	if (ulen > len || ulen < sizeof(*uh))		goto short_packet;	if (pskb_trim(skb, ulen))		goto short_packet;	if (udp_checksum_init(skb, uh, ulen, saddr, daddr) < 0)		goto csum_error;	if(rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))		return udp_v4_mcast_deliver(skb, uh, saddr, daddr);	sk = udp_v4_lookup(saddr, uh->source, daddr, uh->dest, skb->dev->ifindex);	if (sk != NULL) {		int ret = udp_queue_rcv_skb(sk, skb);		sock_put(sk);		/* a return value > 0 means to resubmit the input, but		 * it it wants the return to be -protocol, or 0		 */		if (ret > 0)			return -ret;		return 0;	}	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))		goto drop;	/* No socket. Drop packet silently, if checksum is wrong */	if (udp_checksum_complete(skb))		goto csum_error;	UDP_INC_STATS_BH(UDP_MIB_NOPORTS);	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);	/*	 * Hmm.  We got an UDP packet to a port to which we	 * don't wanna listen.  Ignore it.	 */	kfree_skb(skb);	return(0);short_packet:	NETDEBUG(if (net_ratelimit())		printk(KERN_DEBUG "UDP: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n",			NIPQUAD(saddr),			ntohs(uh->source),			ulen,			len,			NIPQUAD(daddr),			ntohs(uh->dest)));no_header:	UDP_INC_STATS_BH(UDP_MIB_INERRORS);	kfree_skb(skb);	return(0);csum_error:	/* 	 * RFC1122: OK.  Discards the bad packet silently (as far as 	 * the network is concerned, anyway) as per 4.1.3.4 (MUST). 	 */	NETDEBUG(if (net_ratelimit())		 printk(KERN_DEBUG "UDP: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n",			NIPQUAD(saddr),			ntohs(uh->source),			NIPQUAD(daddr),			ntohs(uh->dest),			ulen));drop:	UDP_INC_STATS_BH(UDP_MIB_INERRORS);	kfree_skb(skb);	return(0);}static int udp_destroy_sock(struct sock *sk){	lock_sock(sk);	udp_flush_pending_frames(sk);	release_sock(sk);	return 0;}/* *	Socket option code for UDP */static int udp_setsockopt(struct sock *sk, int level, int optname, 			  char __user *optval, int optlen){	struct udp_opt *up = udp_sk(sk);	int val;	int err = 0;	if (level != SOL_UDP)		return ip_setsockopt(sk, level, optname, optval, optlen);	if(optlen<sizeof(int))		return -EINVAL;	if (get_user(val, (int __user *)optval))		return -EFAULT;	switch(optname) {	case UDP_CORK:		if (val != 0) {			up->corkflag = 1;		} else {			up->corkflag = 0;			lock_sock(sk);			udp_push_pending_frames(sk, up);			release_sock(sk);		}		break;			case UDP_ENCAP:		switch (val) {		case 0:		case UDP_ENCAP_ESPINUDP:		case UDP_ENCAP_ESPINUDP_NON_IKE:			up->encap_type = val;			break;		default:			err = -ENOPROTOOPT;			break;		}		break;	default:		err = -ENOPROTOOPT;		break;	};	return err;}static int udp_getsockopt(struct sock *sk, int level, int optname, 			  char __user *optval, int __user *optlen){	struct udp_opt *up = udp_sk(sk);	int val, len;	if (level != SOL_UDP)		return ip_getsockopt(sk, level, optname, optval, optlen);	if(get_user(len,optlen))		return -EFAULT;	len = min_t(unsigned int, len, sizeof(int));		if(len < 0)		return -EINVAL;	switch(optname) {	case UDP_CORK:		val = up->corkflag;		break;	case UDP_ENCAP:		val = up->encap_type;		break;	default:		return -ENOPROTOOPT;	};  	if(put_user(len, optlen))  		return -EFAULT;	if(copy_to_user(optval, &val,len))		return -EFAULT;  	return 0;}struct proto udp_prot = { 	.name =		"UDP",	.close =	udp_close,	.connect =	ip4_datagram_connect,	.disconnect =	udp_disconnect,	.ioctl =	udp_ioctl,	.destroy =	udp_destroy_sock,	.setsockopt =	udp_setsockopt,	.getsockopt =	udp_getsockopt,	.sendmsg =	udp_sendmsg,	.recvmsg =	udp_recvmsg,	.sendpage =	udp_sendpage,	.backlog_rcv =	udp_queue_rcv_skb,	.hash =		udp_v4_hash,	.unhash =	udp_v4_unhash,	.get_port =	udp_v4_get_port,	.slab_obj_size = sizeof(struct udp_sock),};/* ------------------------------------------------------------------------ */#ifdef CONFIG_PROC_FSstatic struct sock *udp_get_first(struct seq_file *seq){	struct sock *sk;	struct udp_iter_state *state = seq->private;	for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) {		struct hlist_node *node;		sk_for_each(sk, node, &udp_hash[state->bucket]) {			if (sk->sk_family == state->family)				goto found;		}	}	sk = NULL;found:	return sk;}static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk){	struct udp_iter_state *state = seq->private;	do {		sk = sk_next(sk);try_again:		;	} while (sk && sk->sk_family != state->family);	if (!sk && ++state->bucket < UDP_HTABLE_SIZE) {		sk = sk_head(&udp_hash[state->bucket]);		goto try_again;	}	return sk;}static struct sock *udp_get_idx(struct seq_file *seq, loff_t pos){	struct sock *sk = udp_get_first(seq);	if (sk)		while(pos && (sk = udp_get_next(seq, sk)) != NULL)			--pos;	return pos ? NULL : sk;}static void *udp_seq_start(struct seq_file *seq, loff_t *pos){	read_lock(&udp_hash_lock);	return *pos ? udp_get_idx(seq, *pos-1) : (void *)1;}static void *udp_seq_next(struct seq_file *seq, void *v, loff_t *pos){	struct sock *sk;	if (v == (void *)1)		sk = udp_get_idx(seq, 0);	else		sk = udp_get_next(seq, v);	++*pos;	return sk;}static void udp_seq_stop(struct seq_file *seq, void *v){	read_unlock(&udp_hash_lock);}static int udp_seq_open(struct inode *inode, struct file *file){	struct udp_seq_afinfo *afinfo = PDE(inode)->data;	struct seq_file *seq;	int rc = -ENOMEM;	struct udp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);	if (!s)		goto out;	memset(s, 0, sizeof(*s));	s->family		= afinfo->family;	s->seq_ops.start	= udp_seq_start;	s->seq_ops.next		= udp_seq_next;	s->seq_ops.show		= afinfo->seq_show;	s->seq_ops.stop		= udp_seq_stop;	rc = seq_open(file, &s->seq_ops);	if (rc)		goto out_kfree;	seq	     = file->private_data;	seq->private = s;out:	return rc;out_kfree:	kfree(s);	goto out;}/* ------------------------------------------------------------------------ */int udp_proc_register(struct udp_seq_afinfo *afinfo){	struct proc_dir_entry *p;	int rc = 0;	if (!afinfo)		return -EINVAL;	afinfo->seq_fops->owner		= afinfo->owner;	afinfo->seq_fops->open		= udp_seq_open;	afinfo->seq_fops->read		= seq_read;	afinfo->seq_fops->llseek	= seq_lseek;	afinfo->seq_fops->release	= seq_release_private;	p = proc_net_fops_create(afinfo->name, S_IRUGO, afinfo->seq_fops);	if (p)		p->data = afinfo;	else		rc = -ENOMEM;	return rc;}void udp_proc_unregister(struct udp_seq_afinfo *afinfo){	if (!afinfo)		return;	proc_net_remove(afinfo->name);	memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));}/* ------------------------------------------------------------------------ */static void udp4_format_sock(struct sock *sp, char *tmpbuf, int bucket){	struct inet_opt *inet = inet_sk(sp);	unsigned int dest = inet->daddr;	unsigned int src  = inet->rcv_saddr;	__u16 destp	  = ntohs(inet->dport);	__u16 srcp	  = ntohs(inet->sport);	sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p",		bucket, src, srcp, dest, destp, sp->sk_state, 		atomic_read(&sp->sk_wmem_alloc),		atomic_read(&sp->sk_rmem_alloc),		0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),		atomic_read(&sp->sk_refcnt), sp);}static int udp4_seq_show(struct seq_file *seq, void *v){	if (v == SEQ_START_TOKEN)		seq_printf(seq, "%-127s\n",			   "  sl  local_address rem_address   st tx_queue "			   "rx_queue tr tm->when retrnsmt   uid  timeout "			   "inode");	else {		char tmpbuf[129];		struct udp_iter_state *state = seq->private;		udp4_format_sock(v, tmpbuf, state->bucket);		seq_printf(seq, "%-127s\n", tmpbuf);	}	return 0;}/* ------------------------------------------------------------------------ */static struct file_operations udp4_seq_fops;static struct udp_seq_afinfo udp4_seq_afinfo = {	.owner		= THIS_MODULE,	.name		= "udp",	.family		= AF_INET,	.seq_show	= udp4_seq_show,	.seq_fops	= &udp4_seq_fops,};int __init udp4_proc_init(void){	return udp_proc_register(&udp4_seq_afinfo);}void udp4_proc_exit(void){	udp_proc_unregister(&udp4_seq_afinfo);}#endif /* CONFIG_PROC_FS */EXPORT_SYMBOL(udp_disconnect);EXPORT_SYMBOL(udp_hash);EXPORT_SYMBOL(udp_hash_lock);EXPORT_SYMBOL(udp_ioctl);EXPORT_SYMBOL(udp_port_rover);EXPORT_SYMBOL(udp_prot);EXPORT_SYMBOL(udp_sendmsg);#ifdef CONFIG_PROC_FSEXPORT_SYMBOL(udp_proc_register);EXPORT_SYMBOL(udp_proc_unregister);#endif

⌨️ 快捷键说明

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