📄 ip_vs_ctl.c
字号:
ip_vs_num_services--; ip_vs_kill_estimator(&svc->stats); /* Unbind scheduler */ old_sched = svc->scheduler; ip_vs_unbind_scheduler(svc); if (old_sched) ip_vs_scheduler_put(old_sched); /* Unbind app inc */ if (svc->inc) { ip_vs_app_inc_put(svc->inc); svc->inc = NULL; } /* * Unlink the whole destination list */ list_for_each_entry_safe(dest, nxt, &svc->destinations, n_list) { __ip_vs_unlink_dest(svc, dest, 0); __ip_vs_del_dest(dest); } /* * Update the virtual service counters */ if (svc->port == FTPPORT) atomic_dec(&ip_vs_ftpsvc_counter); else if (svc->port == 0) atomic_dec(&ip_vs_nullsvc_counter); /* * Free the service if nobody refers to it */ if (atomic_read(&svc->refcnt) == 0) kfree(svc); /* decrease the module use count */ ip_vs_use_count_dec();}/* * Delete a service from the service list */static int ip_vs_del_service(struct ip_vs_service *svc){ if (svc == NULL) return -EEXIST; /* * Unhash it from the service table */ write_lock_bh(&__ip_vs_svc_lock); ip_vs_svc_unhash(svc); /* * Wait until all the svc users go away. */ IP_VS_WAIT_WHILE(atomic_read(&svc->usecnt) > 1); __ip_vs_del_service(svc); write_unlock_bh(&__ip_vs_svc_lock); return 0;}/* * Flush all the virtual services */static int ip_vs_flush(void){ int idx; struct ip_vs_service *svc, *nxt; /* * Flush the service table hashed by <protocol,addr,port> */ for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { list_for_each_entry_safe(svc, nxt, &ip_vs_svc_table[idx], s_list) { write_lock_bh(&__ip_vs_svc_lock); ip_vs_svc_unhash(svc); /* * Wait until all the svc users go away. */ IP_VS_WAIT_WHILE(atomic_read(&svc->usecnt) > 0); __ip_vs_del_service(svc); write_unlock_bh(&__ip_vs_svc_lock); } } /* * Flush the service table hashed by fwmark */ for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { list_for_each_entry_safe(svc, nxt, &ip_vs_svc_fwm_table[idx], f_list) { write_lock_bh(&__ip_vs_svc_lock); ip_vs_svc_unhash(svc); /* * Wait until all the svc users go away. */ IP_VS_WAIT_WHILE(atomic_read(&svc->usecnt) > 0); __ip_vs_del_service(svc); write_unlock_bh(&__ip_vs_svc_lock); } } return 0;}/* * Zero counters in a service or all services */static int ip_vs_zero_service(struct ip_vs_service *svc){ struct ip_vs_dest *dest; write_lock_bh(&__ip_vs_svc_lock); list_for_each_entry(dest, &svc->destinations, n_list) { ip_vs_zero_stats(&dest->stats); } ip_vs_zero_stats(&svc->stats); write_unlock_bh(&__ip_vs_svc_lock); return 0;}static int ip_vs_zero_all(void){ int idx; struct ip_vs_service *svc; for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { ip_vs_zero_service(svc); } } for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { ip_vs_zero_service(svc); } } ip_vs_zero_stats(&ip_vs_stats); return 0;}static intproc_do_defense_mode(ctl_table *table, int write, struct file * filp, void __user *buffer, size_t *lenp, loff_t *ppos){ int *valp = table->data; int val = *valp; int rc; rc = proc_dointvec(table, write, filp, buffer, lenp, ppos); if (write && (*valp != val)) { if ((*valp < 0) || (*valp > 3)) { /* Restore the correct value */ *valp = val; } else { update_defense_level(); } } return rc;}static intproc_do_sync_threshold(ctl_table *table, int write, struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos){ int *valp = table->data; int val[2]; int rc; /* backup the value first */ memcpy(val, valp, sizeof(val)); rc = proc_dointvec(table, write, filp, buffer, lenp, ppos); if (write && (valp[0] < 0 || valp[1] < 0 || valp[0] >= valp[1])) { /* Restore the correct value */ memcpy(valp, val, sizeof(val)); } return rc;}/* * IPVS sysctl table (under the /proc/sys/net/ipv4/vs/) */static struct ctl_table vs_vars[] = { { .ctl_name = NET_IPV4_VS_AMEMTHRESH, .procname = "amemthresh", .data = &sysctl_ip_vs_amemthresh, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, },#ifdef CONFIG_IP_VS_DEBUG { .ctl_name = NET_IPV4_VS_DEBUG_LEVEL, .procname = "debug_level", .data = &sysctl_ip_vs_debug_level, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, },#endif { .ctl_name = NET_IPV4_VS_AMDROPRATE, .procname = "am_droprate", .data = &sysctl_ip_vs_am_droprate, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, }, { .ctl_name = NET_IPV4_VS_DROP_ENTRY, .procname = "drop_entry", .data = &sysctl_ip_vs_drop_entry, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_do_defense_mode, }, { .ctl_name = NET_IPV4_VS_DROP_PACKET, .procname = "drop_packet", .data = &sysctl_ip_vs_drop_packet, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_do_defense_mode, }, { .ctl_name = NET_IPV4_VS_SECURE_TCP, .procname = "secure_tcp", .data = &sysctl_ip_vs_secure_tcp, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_do_defense_mode, },#if 0 { .ctl_name = NET_IPV4_VS_TO_ES, .procname = "timeout_established", .data = &vs_timeout_table_dos.timeout[IP_VS_S_ESTABLISHED], .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { .ctl_name = NET_IPV4_VS_TO_SS, .procname = "timeout_synsent", .data = &vs_timeout_table_dos.timeout[IP_VS_S_SYN_SENT], .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { .ctl_name = NET_IPV4_VS_TO_SR, .procname = "timeout_synrecv", .data = &vs_timeout_table_dos.timeout[IP_VS_S_SYN_RECV], .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { .ctl_name = NET_IPV4_VS_TO_FW, .procname = "timeout_finwait", .data = &vs_timeout_table_dos.timeout[IP_VS_S_FIN_WAIT], .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { .ctl_name = NET_IPV4_VS_TO_TW, .procname = "timeout_timewait", .data = &vs_timeout_table_dos.timeout[IP_VS_S_TIME_WAIT], .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { .ctl_name = NET_IPV4_VS_TO_CL, .procname = "timeout_close", .data = &vs_timeout_table_dos.timeout[IP_VS_S_CLOSE], .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { .ctl_name = NET_IPV4_VS_TO_CW, .procname = "timeout_closewait", .data = &vs_timeout_table_dos.timeout[IP_VS_S_CLOSE_WAIT], .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { .ctl_name = NET_IPV4_VS_TO_LA, .procname = "timeout_lastack", .data = &vs_timeout_table_dos.timeout[IP_VS_S_LAST_ACK], .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { .ctl_name = NET_IPV4_VS_TO_LI, .procname = "timeout_listen", .data = &vs_timeout_table_dos.timeout[IP_VS_S_LISTEN], .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { .ctl_name = NET_IPV4_VS_TO_SA, .procname = "timeout_synack", .data = &vs_timeout_table_dos.timeout[IP_VS_S_SYNACK], .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { .ctl_name = NET_IPV4_VS_TO_UDP, .procname = "timeout_udp", .data = &vs_timeout_table_dos.timeout[IP_VS_S_UDP], .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { .ctl_name = NET_IPV4_VS_TO_ICMP, .procname = "timeout_icmp", .data = &vs_timeout_table_dos.timeout[IP_VS_S_ICMP], .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, },#endif { .ctl_name = NET_IPV4_VS_CACHE_BYPASS, .procname = "cache_bypass", .data = &sysctl_ip_vs_cache_bypass, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, }, { .ctl_name = NET_IPV4_VS_EXPIRE_NODEST_CONN, .procname = "expire_nodest_conn", .data = &sysctl_ip_vs_expire_nodest_conn, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, }, { .ctl_name = NET_IPV4_VS_EXPIRE_QUIESCENT_TEMPLATE, .procname = "expire_quiescent_template", .data = &sysctl_ip_vs_expire_quiescent_template, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, }, { .ctl_name = NET_IPV4_VS_SYNC_THRESHOLD, .procname = "sync_threshold", .data = &sysctl_ip_vs_sync_threshold, .maxlen = sizeof(sysctl_ip_vs_sync_threshold), .mode = 0644, .proc_handler = &proc_do_sync_threshold, }, { .ctl_name = NET_IPV4_VS_NAT_ICMP_SEND, .procname = "nat_icmp_send", .data = &sysctl_ip_vs_nat_icmp_send, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, }, { .ctl_name = 0 }};static ctl_table vs_table[] = { { .ctl_name = NET_IPV4_VS, .procname = "vs", .mode = 0555, .child = vs_vars }, { .ctl_name = 0 }};static ctl_table ipvs_ipv4_table[] = { { .ctl_name = NET_IPV4, .procname = "ipv4", .mode = 0555, .child = vs_table, }, { .ctl_name = 0 }};static ctl_table vs_root_table[] = { { .ctl_name = CTL_NET, .procname = "net", .mode = 0555, .child = ipvs_ipv4_table, }, { .ctl_name = 0 }};static struct ctl_table_header * sysctl_header;#ifdef CONFIG_PROC_FSstruct ip_vs_iter { struct list_head *table; int bucket;};/* * Write the contents of the VS rule table to a PROCfs file. * (It is kept just for backward compatibility) */static inline const char *ip_vs_fwd_name(unsigned flags){ switch (flags & IP_VS_CONN_F_FWD_MASK) { case IP_VS_CONN_F_LOCALNODE: return "Local"; case IP_VS_CONN_F_TUNNEL: return "Tunnel"; case IP_VS_CONN_F_DROUTE: return "Route"; default: return "Masq"; }}/* Get the Nth entry in the two lists */static struct ip_vs_service *ip_vs_info_array(struct seq_file *seq, loff_t pos){ struct ip_vs_iter *iter = seq->private; int idx; struct ip_vs_service *svc; /* look in hash by protocol */ for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { if (pos-- == 0){ iter->table = ip_vs_svc_table; iter->bucket = idx; return svc; } } } /* keep looking in fwmark */ for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { if (pos-- == 0) { iter->table = ip_vs_svc_fwm_table; iter->bucket = idx; return svc; } } } return NULL;}static void *ip_vs_info_seq_start(struct seq_file *seq, loff_t *pos){ read_lock_bh(&__ip_vs_svc_lock); return *pos ? ip_vs_info_array(seq, *pos - 1) : SEQ_START_TOKEN;}static void *ip_vs_info_seq_next(struct seq_file *seq, void *v, loff_t *pos){ struct list_head *e; struct ip_vs_iter *iter; struct ip_vs_service *svc; ++*pos; if (v == SEQ_START_TOKEN) return ip_vs_info_array(seq,0); svc = v; iter = seq->private; if (iter->table == ip_vs_svc_table) { /* next service in table hashed by protocol */ if ((e = svc->s_list.next) != &ip_vs_svc_table[iter->bucket]) return list_entry(e, struct ip_vs_service, s_list); while (++iter->bucket < IP_VS_SVC_TAB_SIZE) { list_for_each_entry(svc,&ip_vs_svc_table[iter->bucket], s_list) { return svc; } } iter->table = ip_vs_svc_fwm_table; iter->bucket = -1; goto scan_fwmark; } /* next service in hashed by fwmark */ if ((e = svc->f_list.next) != &ip_vs_svc_fwm_table[iter->bucket]) return list_entry(e, struct ip_vs_service, f_list); scan_fwmark: while (++iter->bucket < IP_VS_SVC_TAB_SIZE) { list_for_each_entry(svc, &ip_vs_svc_fwm_table[iter->bucket], f_list) return svc; } return NULL;}static void ip_vs_info_seq_stop(struct seq_file *seq, void *v){ read_unlock_bh(&__ip_vs_svc_lock);}static int ip_vs_info_seq_show(struct seq_file *seq, void *v){ if (v == SEQ_START_TOKEN) { seq_printf(seq, "IP Virtual Server version %d.%d.%d (size=%d)\n", NVERSION(IP_VS_VERSION_CODE), IP_VS_CONN_TAB_SIZE); seq_puts(seq, "Prot LocalAddress:Port Scheduler Flags\n"); seq_puts(seq, " -> RemoteAddress:Port Forward Weight ActiveConn InActConn\n"); } else { const struct ip_vs_service *svc = v; const struct ip_vs_iter *iter = seq->private; const struct ip_vs_dest *dest; if (iter->table == ip_vs_svc_table) seq_printf(seq, "%s %08X:%04X %s ", ip_vs_proto_name(svc->protocol), ntohl(svc->addr), ntohs(svc->port), svc->scheduler->name); else seq_printf(seq, "FWM %08X %s ", svc->fwmark, svc->scheduler->name); if (svc->flags & IP_VS_SVC_F_PERSISTENT) seq_printf(seq, "persistent %d %08X\n", svc->timeout, ntohl(svc->netmask)); else seq_putc(seq, '\n'); list_for_each_entry(dest, &svc->destinations, n_list) { seq_printf(seq, " -> %08X:%04X %-7s %-6d %-10d %-10d\n", ntohl(dest->addr), ntohs(dest->port), ip_vs_fwd_name(atomic_read(&dest->conn_flags)), atomic_read(&dest->weight), atomic_read(&dest->activeconns), atomic_read(&dest->inactconns)); } } return 0;}static struct seq_operations ip_vs_info_seq_ops = { .start = ip_vs_info_seq_start, .next = ip_vs_info_seq_next, .stop = ip_vs_info_seq_stop, .show = ip_vs_info_seq_show,};static int ip_vs_info_open(struct inode *inode, struct file *file){ struct seq_file *seq; int rc = -ENOMEM; struct ip_vs_iter *s = kmalloc(sizeof(*s), GFP_KERNEL); if (!s) goto out;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -