📄 tcp_ipv4.c
字号:
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 + -