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

📄 tcp_ipv4.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
				break;get_req:			req = icsk->icsk_accept_queue.listen_opt->syn_table[st->sbucket];		}		sk	  = sk_next(st->syn_wait_sk);		st->state = TCP_SEQ_STATE_LISTENING;		read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);	} else {		icsk = inet_csk(sk);		read_lock_bh(&icsk->icsk_accept_queue.syn_wait_lock);		if (reqsk_queue_len(&icsk->icsk_accept_queue))			goto start_req;		read_unlock_bh(&icsk->icsk_accept_queue.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;		}		icsk = inet_csk(sk);		read_lock_bh(&icsk->icsk_accept_queue.syn_wait_lock);		if (reqsk_queue_len(&icsk->icsk_accept_queue)) {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(&icsk->icsk_accept_queue.syn_wait_lock);	}	if (++st->bucket < INET_LHTABLE_SIZE) {		sk = sk_head(&tcp_hashinfo.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_hashinfo.ehash_size; ++st->bucket) {		struct sock *sk;		struct hlist_node *node;		struct inet_timewait_sock *tw;		rwlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, st->bucket);		read_lock_bh(lock);		sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {			if (sk->sk_family != st->family) {				continue;			}			rc = sk;			goto out;		}		st->state = TCP_SEQ_STATE_TIME_WAIT;		inet_twsk_for_each(tw, node,				   &tcp_hashinfo.ehash[st->bucket].twchain) {			if (tw->tw_family != st->family) {				continue;			}			rc = tw;			goto out;		}		read_unlock_bh(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 inet_timewait_sock *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_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));		st->state = TCP_SEQ_STATE_ESTABLISHED;		if (++st->bucket < tcp_hashinfo.ehash_size) {			read_lock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));			sk = sk_head(&tcp_hashinfo.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_hashinfo.ehash[st->bucket].twchain);	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;	inet_listen_lock(&tcp_hashinfo);	st->state = TCP_SEQ_STATE_LISTENING;	rc	  = listening_get_idx(seq, &pos);	if (!rc) {		inet_listen_unlock(&tcp_hashinfo);		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) {			inet_listen_unlock(&tcp_hashinfo);			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 inet_connection_sock *icsk = inet_csk(st->syn_wait_sk);			read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);		}	case TCP_SEQ_STATE_LISTENING:		if (v != SEQ_START_TOKEN)			inet_listen_unlock(&tcp_hashinfo);		break;	case TCP_SEQ_STATE_TIME_WAIT:	case TCP_SEQ_STATE_ESTABLISHED:		if (v)			read_unlock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));		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 = kzalloc(sizeof(*s), GFP_KERNEL);	if (!s)		return -ENOMEM;	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(&init_net, 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(&init_net, afinfo->name);	memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));}static void get_openreq4(struct sock *sk, struct request_sock *req,			 char *tmpbuf, int i, int uid){	const struct inet_request_sock *ireq = inet_rsk(req);	int ttd = req->expires - jiffies;	sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %p",		i,		ireq->loc_addr,		ntohs(inet_sk(sk)->sport),		ireq->rmt_addr,		ntohs(ireq->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 *sk, char *tmpbuf, int i){	int timer_active;	unsigned long timer_expires;	struct tcp_sock *tp = tcp_sk(sk);	const struct inet_connection_sock *icsk = inet_csk(sk);	struct inet_sock *inet = inet_sk(sk);	__be32 dest = inet->daddr;	__be32 src = inet->rcv_saddr;	__u16 destp = ntohs(inet->dport);	__u16 srcp = ntohs(inet->sport);	if (icsk->icsk_pending == ICSK_TIME_RETRANS) {		timer_active	= 1;		timer_expires	= icsk->icsk_timeout;	} else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {		timer_active	= 4;		timer_expires	= icsk->icsk_timeout;	} else if (timer_pending(&sk->sk_timer)) {		timer_active	= 2;		timer_expires	= sk->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, sk->sk_state,		tp->write_seq - tp->snd_una,		sk->sk_state == TCP_LISTEN ? sk->sk_ack_backlog :					     (tp->rcv_nxt - tp->copied_seq),		timer_active,		jiffies_to_clock_t(timer_expires - jiffies),		icsk->icsk_retransmits,		sock_i_uid(sk),		icsk->icsk_probes_out,		sock_i_ino(sk),		atomic_read(&sk->sk_refcnt), sk,		icsk->icsk_rto,		icsk->icsk_ack.ato,		(icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,		tp->snd_cwnd,		tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh);}static void get_timewait4_sock(struct inet_timewait_sock *tw,			       char *tmpbuf, int i){	__be32 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 */DEFINE_PROTO_INUSE(tcp)struct proto tcp_prot = {	.name			= "TCP",	.owner			= THIS_MODULE,	.close			= tcp_close,	.connect		= tcp_v4_connect,	.disconnect		= tcp_disconnect,	.accept			= inet_csk_accept,	.ioctl			= tcp_ioctl,	.init			= tcp_v4_init_sock,	.destroy		= tcp_v4_destroy_sock,	.shutdown		= tcp_shutdown,	.setsockopt		= tcp_setsockopt,	.getsockopt		= tcp_getsockopt,	.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,	.orphan_count		= &tcp_orphan_count,	.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,	.obj_size		= sizeof(struct tcp_sock),	.twsk_prot		= &tcp_timewait_sock_ops,	.rsk_prot		= &tcp_request_sock_ops,#ifdef CONFIG_COMPAT	.compat_setsockopt	= compat_tcp_setsockopt,	.compat_getsockopt	= compat_tcp_getsockopt,#endif	REF_PROTO_INUSE(tcp)};void __init tcp_v4_init(struct net_proto_family *ops){	if (inet_csk_ctl_sock_create(&tcp_socket, PF_INET, SOCK_RAW,				     IPPROTO_TCP) < 0)		panic("Failed to create the TCP control socket.\n");}EXPORT_SYMBOL(ipv4_specific);EXPORT_SYMBOL(tcp_hashinfo);EXPORT_SYMBOL(tcp_prot);EXPORT_SYMBOL(tcp_unhash);EXPORT_SYMBOL(tcp_v4_conn_request);EXPORT_SYMBOL(tcp_v4_connect);EXPORT_SYMBOL(tcp_v4_do_rcv);EXPORT_SYMBOL(tcp_v4_remember_stamp);EXPORT_SYMBOL(tcp_v4_send_check);EXPORT_SYMBOL(tcp_v4_syn_recv_sock);#ifdef CONFIG_PROC_FSEXPORT_SYMBOL(tcp_proc_register);EXPORT_SYMBOL(tcp_proc_unregister);#endifEXPORT_SYMBOL(sysctl_tcp_low_latency);

⌨️ 快捷键说明

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