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

📄 tcp_ipv4.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (tp->bind_hash)		tcp_put_port(sk);	/*	 * If sendmsg cached page exists, toss it.	 */	if (sk->sk_sndmsg_page) {		__free_page(sk->sk_sndmsg_page);		sk->sk_sndmsg_page = NULL;	}	atomic_dec(&tcp_sockets_allocated);	return 0;}EXPORT_SYMBOL(tcp_v4_destroy_sock);#ifdef CONFIG_PROC_FS/* Proc filesystem TCP sock list dumping. */static inline struct tcp_tw_bucket *tw_head(struct hlist_head *head){	return hlist_empty(head) ? NULL :		list_entry(head->first, struct tcp_tw_bucket, tw_node);}static inline struct tcp_tw_bucket *tw_next(struct tcp_tw_bucket *tw){	return tw->tw_node.next ?		hlist_entry(tw->tw_node.next, typeof(*tw), tw_node) : NULL;}static void *listening_get_next(struct seq_file *seq, void *cur){	struct tcp_opt *tp;	struct hlist_node *node;	struct sock *sk = cur;	struct tcp_iter_state* st = seq->private;	if (!sk) {		st->bucket = 0;		sk = sk_head(&tcp_listening_hash[0]);		goto get_sk;	}	++st->num;	if (st->state == TCP_SEQ_STATE_OPENREQ) {		struct open_request *req = cur;	       	tp = tcp_sk(st->syn_wait_sk);		req = req->dl_next;		while (1) {			while (req) {				if (req->class->family == st->family) {					cur = req;					goto out;				}				req = req->dl_next;			}			if (++st->sbucket >= TCP_SYNQ_HSIZE)				break;get_req:			req = tp->listen_opt->syn_table[st->sbucket];		}		sk	  = sk_next(st->syn_wait_sk);		st->state = TCP_SEQ_STATE_LISTENING;		read_unlock_bh(&tp->syn_wait_lock);	} else {	       	tp = tcp_sk(sk);		read_lock_bh(&tp->syn_wait_lock);		if (tp->listen_opt && tp->listen_opt->qlen)			goto start_req;		read_unlock_bh(&tp->syn_wait_lock);		sk = sk_next(sk);	}get_sk:	sk_for_each_from(sk, node) {		if (sk->sk_family == st->family) {			cur = sk;			goto out;		}	       	tp = tcp_sk(sk);		read_lock_bh(&tp->syn_wait_lock);		if (tp->listen_opt && tp->listen_opt->qlen) {start_req:			st->uid		= sock_i_uid(sk);			st->syn_wait_sk = sk;			st->state	= TCP_SEQ_STATE_OPENREQ;			st->sbucket	= 0;			goto get_req;		}		read_unlock_bh(&tp->syn_wait_lock);	}	if (++st->bucket < TCP_LHTABLE_SIZE) {		sk = sk_head(&tcp_listening_hash[st->bucket]);		goto get_sk;	}	cur = NULL;out:	return cur;}static void *listening_get_idx(struct seq_file *seq, loff_t *pos){	void *rc = listening_get_next(seq, NULL);	while (rc && *pos) {		rc = listening_get_next(seq, rc);		--*pos;	}	return rc;}static void *established_get_first(struct seq_file *seq){	struct tcp_iter_state* st = seq->private;	void *rc = NULL;	for (st->bucket = 0; st->bucket < tcp_ehash_size; ++st->bucket) {		struct sock *sk;		struct hlist_node *node;		struct tcp_tw_bucket *tw;	       		read_lock(&tcp_ehash[st->bucket].lock);		sk_for_each(sk, node, &tcp_ehash[st->bucket].chain) {			if (sk->sk_family != st->family) {				continue;			}			rc = sk;			goto out;		}		st->state = TCP_SEQ_STATE_TIME_WAIT;		tw_for_each(tw, node,			    &tcp_ehash[st->bucket + tcp_ehash_size].chain) {			if (tw->tw_family != st->family) {				continue;			}			rc = tw;			goto out;		}		read_unlock(&tcp_ehash[st->bucket].lock);		st->state = TCP_SEQ_STATE_ESTABLISHED;	}out:	return rc;}static void *established_get_next(struct seq_file *seq, void *cur){	struct sock *sk = cur;	struct tcp_tw_bucket *tw;	struct hlist_node *node;	struct tcp_iter_state* st = seq->private;	++st->num;	if (st->state == TCP_SEQ_STATE_TIME_WAIT) {		tw = cur;		tw = tw_next(tw);get_tw:		while (tw && tw->tw_family != st->family) {			tw = tw_next(tw);		}		if (tw) {			cur = tw;			goto out;		}		read_unlock(&tcp_ehash[st->bucket].lock);		st->state = TCP_SEQ_STATE_ESTABLISHED;		if (++st->bucket < tcp_ehash_size) {			read_lock(&tcp_ehash[st->bucket].lock);			sk = sk_head(&tcp_ehash[st->bucket].chain);		} else {			cur = NULL;			goto out;		}	} else		sk = sk_next(sk);	sk_for_each_from(sk, node) {		if (sk->sk_family == st->family)			goto found;	}	st->state = TCP_SEQ_STATE_TIME_WAIT;	tw = tw_head(&tcp_ehash[st->bucket + tcp_ehash_size].chain);	goto get_tw;found:	cur = sk;out:	return cur;}static void *established_get_idx(struct seq_file *seq, loff_t pos){	void *rc = established_get_first(seq);	while (rc && pos) {		rc = established_get_next(seq, rc);		--pos;	}			return rc;}static void *tcp_get_idx(struct seq_file *seq, loff_t pos){	void *rc;	struct tcp_iter_state* st = seq->private;	tcp_listen_lock();	st->state = TCP_SEQ_STATE_LISTENING;	rc	  = listening_get_idx(seq, &pos);	if (!rc) {		tcp_listen_unlock();		local_bh_disable();		st->state = TCP_SEQ_STATE_ESTABLISHED;		rc	  = established_get_idx(seq, pos);	}	return rc;}static void *tcp_seq_start(struct seq_file *seq, loff_t *pos){	struct tcp_iter_state* st = seq->private;	st->state = TCP_SEQ_STATE_LISTENING;	st->num = 0;	return *pos ? tcp_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;}static void *tcp_seq_next(struct seq_file *seq, void *v, loff_t *pos){	void *rc = NULL;	struct tcp_iter_state* st;	if (v == SEQ_START_TOKEN) {		rc = tcp_get_idx(seq, 0);		goto out;	}	st = seq->private;	switch (st->state) {	case TCP_SEQ_STATE_OPENREQ:	case TCP_SEQ_STATE_LISTENING:		rc = listening_get_next(seq, v);		if (!rc) {			tcp_listen_unlock();			local_bh_disable();			st->state = TCP_SEQ_STATE_ESTABLISHED;			rc	  = established_get_first(seq);		}		break;	case TCP_SEQ_STATE_ESTABLISHED:	case TCP_SEQ_STATE_TIME_WAIT:		rc = established_get_next(seq, v);		break;	}out:	++*pos;	return rc;}static void tcp_seq_stop(struct seq_file *seq, void *v){	struct tcp_iter_state* st = seq->private;	switch (st->state) {	case TCP_SEQ_STATE_OPENREQ:		if (v) {			struct tcp_opt *tp = tcp_sk(st->syn_wait_sk);			read_unlock_bh(&tp->syn_wait_lock);		}	case TCP_SEQ_STATE_LISTENING:		if (v != SEQ_START_TOKEN)			tcp_listen_unlock();		break;	case TCP_SEQ_STATE_TIME_WAIT:	case TCP_SEQ_STATE_ESTABLISHED:		if (v)			read_unlock(&tcp_ehash[st->bucket].lock);		local_bh_enable();		break;	}}static int tcp_seq_open(struct inode *inode, struct file *file){	struct tcp_seq_afinfo *afinfo = PDE(inode)->data;	struct seq_file *seq;	struct tcp_iter_state *s;	int rc;	if (unlikely(afinfo == NULL))		return -EINVAL;	s = kmalloc(sizeof(*s), GFP_KERNEL);	if (!s)		return -ENOMEM;	memset(s, 0, sizeof(*s));	s->family		= afinfo->family;	s->seq_ops.start	= tcp_seq_start;	s->seq_ops.next		= tcp_seq_next;	s->seq_ops.show		= afinfo->seq_show;	s->seq_ops.stop		= tcp_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 tcp_proc_register(struct tcp_seq_afinfo *afinfo){	int rc = 0;	struct proc_dir_entry *p;	if (!afinfo)		return -EINVAL;	afinfo->seq_fops->owner		= afinfo->owner;	afinfo->seq_fops->open		= tcp_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 tcp_proc_unregister(struct tcp_seq_afinfo *afinfo){	if (!afinfo)		return;	proc_net_remove(afinfo->name);	memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops)); }static void get_openreq4(struct sock *sk, struct open_request *req,			 char *tmpbuf, int i, int uid){	int ttd = req->expires - jiffies;	sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %p",		i,		req->af.v4_req.loc_addr,		ntohs(inet_sk(sk)->sport),		req->af.v4_req.rmt_addr,		ntohs(req->rmt_port),		TCP_SYN_RECV,		0, 0, /* could print option size, but that is af dependent. */		1,    /* timers active (only the expire timer) */		jiffies_to_clock_t(ttd),		req->retrans,		uid,		0,  /* non standard timer */		0, /* open_requests have no inode */		atomic_read(&sk->sk_refcnt),		req);}static void get_tcp4_sock(struct sock *sp, char *tmpbuf, int i){	int timer_active;	unsigned long timer_expires;	struct tcp_opt *tp = tcp_sk(sp);	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);	if (tp->pending == TCP_TIME_RETRANS) {		timer_active	= 1;		timer_expires	= tp->timeout;	} else if (tp->pending == TCP_TIME_PROBE0) {		timer_active	= 4;		timer_expires	= tp->timeout;	} else if (timer_pending(&sp->sk_timer)) {		timer_active	= 2;		timer_expires	= sp->sk_timer.expires;	} else {		timer_active	= 0;		timer_expires = jiffies;	}	sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "			"%08X %5d %8d %lu %d %p %u %u %u %u %d",		i, src, srcp, dest, destp, sp->sk_state,		tp->write_seq - tp->snd_una, tp->rcv_nxt - tp->copied_seq,		timer_active,		jiffies_to_clock_t(timer_expires - jiffies),		tp->retransmits,		sock_i_uid(sp),		tp->probes_out,		sock_i_ino(sp),		atomic_read(&sp->sk_refcnt), sp,		tp->rto, tp->ack.ato, (tp->ack.quick << 1) | tp->ack.pingpong,		tp->snd_cwnd,		tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh);}static void get_timewait4_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i){	unsigned int dest, src;	__u16 destp, srcp;	int ttd = tw->tw_ttd - jiffies;	if (ttd < 0)		ttd = 0;	dest  = tw->tw_daddr;	src   = tw->tw_rcv_saddr;	destp = ntohs(tw->tw_dport);	srcp  = ntohs(tw->tw_sport);	sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p",		i, src, srcp, dest, destp, tw->tw_substate, 0, 0,		3, jiffies_to_clock_t(ttd), 0, 0, 0, 0,		atomic_read(&tw->tw_refcnt), tw);}#define TMPSZ 150static int tcp4_seq_show(struct seq_file *seq, void *v){	struct tcp_iter_state* st;	char tmpbuf[TMPSZ + 1];	if (v == SEQ_START_TOKEN) {		seq_printf(seq, "%-*s\n", TMPSZ - 1,			   "  sl  local_address rem_address   st tx_queue "			   "rx_queue tr tm->when retrnsmt   uid  timeout "			   "inode");		goto out;	}	st = seq->private;	switch (st->state) {	case TCP_SEQ_STATE_LISTENING:	case TCP_SEQ_STATE_ESTABLISHED:		get_tcp4_sock(v, tmpbuf, st->num);		break;	case TCP_SEQ_STATE_OPENREQ:		get_openreq4(st->syn_wait_sk, v, tmpbuf, st->num, st->uid);		break;	case TCP_SEQ_STATE_TIME_WAIT:		get_timewait4_sock(v, tmpbuf, st->num);		break;	}	seq_printf(seq, "%-*s\n", TMPSZ - 1, tmpbuf);out:	return 0;}static struct file_operations tcp4_seq_fops;static struct tcp_seq_afinfo tcp4_seq_afinfo = {	.owner		= THIS_MODULE,	.name		= "tcp",	.family		= AF_INET,	.seq_show	= tcp4_seq_show,	.seq_fops	= &tcp4_seq_fops,};int __init tcp4_proc_init(void){	return tcp_proc_register(&tcp4_seq_afinfo);}void tcp4_proc_exit(void){	tcp_proc_unregister(&tcp4_seq_afinfo);}#endif /* CONFIG_PROC_FS */struct proto tcp_prot = {	.name			= "TCP",	.close			= tcp_close,	.connect		= tcp_v4_connect,	.disconnect		= tcp_disconnect,	.accept			= tcp_accept,	.ioctl			= tcp_ioctl,	.init			= tcp_v4_init_sock,	.destroy		= tcp_v4_destroy_sock,	.shutdown		= tcp_shutdown,	.setsockopt		= tcp_setsockopt,	.getsockopt		= tcp_getsockopt,	.sendmsg		= tcp_sendmsg,	.recvmsg		= tcp_recvmsg,	.backlog_rcv		= tcp_v4_do_rcv,	.hash			= tcp_v4_hash,	.unhash			= tcp_unhash,	.get_port		= tcp_v4_get_port,	.enter_memory_pressure	= tcp_enter_memory_pressure,	.sockets_allocated	= &tcp_sockets_allocated,	.memory_allocated	= &tcp_memory_allocated,	.memory_pressure	= &tcp_memory_pressure,	.sysctl_mem		= sysctl_tcp_mem,	.sysctl_wmem		= sysctl_tcp_wmem,	.sysctl_rmem		= sysctl_tcp_rmem,	.max_header		= MAX_TCP_HEADER,	.slab_obj_size		= sizeof(struct tcp_sock),};void __init tcp_v4_init(struct net_proto_family *ops){	int err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_TCP, &tcp_socket);	if (err < 0)		panic("Failed to create the TCP control socket.\n");	tcp_socket->sk->sk_allocation   = GFP_ATOMIC;	inet_sk(tcp_socket->sk)->

⌨️ 快捷键说明

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