From 8e040fac8e31d167998b70dc47c2468c43a4901d Mon Sep 17 00:00:00 2001 From: Bill Yuan Date: Fri, 13 Apr 2018 02:02:48 +0000 Subject: [PATCH] ipfw3nat: show translations same as 'show ip nat translations' --- sbin/ipfw3/ipfw3nat.c | 44 ++++++------ sys/net/ipfw3_nat/ip_fw3_nat.c | 156 ++++++++++++++++++++++++++++++++++++++++- sys/net/ipfw3_nat/ip_fw3_nat.h | 13 ++-- 3 files changed, 181 insertions(+), 32 deletions(-) diff --git a/sbin/ipfw3/ipfw3nat.c b/sbin/ipfw3/ipfw3nat.c index 9cac7fa11c..e69933bb47 100644 --- a/sbin/ipfw3/ipfw3nat.c +++ b/sbin/ipfw3/ipfw3nat.c @@ -268,37 +268,33 @@ nat_show_state(int ac, char **av) } if (nbytes == 0) exit(EX_OK); - struct ipfw_ioc_nat_state *nat_state; - nat_state =(struct ipfw_ioc_nat_state *)data; - int count = nbytes / sizeof( struct ipfw_ioc_nat_state); + + struct ioc_nat_state *ioc; + ioc =(struct ioc_nat_state *)data; + int count = nbytes / LEN_IOC_NAT_STATE; int i, uptime_sec; uptime_sec = get_kern_boottime(); for (i = 0; i < count; i ++) { - printf("#%d ", nat_state->cpuid); - printf("%s:%hu => ",inet_ntoa(nat_state->src_addr), - htons(nat_state->src_port)); - printf("%s:%hu",inet_ntoa(nat_state->alias_addr), - htons(nat_state->alias_port)); - printf(" -> %s:%hu ",inet_ntoa(nat_state->dst_addr), - htons(nat_state->dst_port)); - if (do_time == 1) { - char timestr[30]; - time_t t = _long_to_time(uptime_sec + - nat_state->timestamp); - strcpy(timestr, ctime(&t)); - *strchr(timestr, '\n') = '\0'; - printf("%s ", timestr); - } else if (do_time == 2) { - printf( "%10u ", uptime_sec + nat_state->timestamp); + printf("%d %d", ioc->nat_id, ioc->cpu_id); + if (ioc->proto == IPPROTO_ICMP) { + printf(" icmp"); + } else if (ioc->proto == IPPROTO_TCP) { + printf(" tcp"); + } else if (ioc->proto == IPPROTO_UDP) { + printf(" udp"); } - struct protoent *pe = getprotobynumber(nat_state->link_type); - printf("%s ", pe->p_name); - printf(" %s", nat_state->is_outgoing? "out": "in"); + printf(" %s:%hu",inet_ntoa(ioc->src_addr), + htons(ioc->src_port)); + printf(" %s:%hu",inet_ntoa(ioc->alias_addr), + htons(ioc->alias_port)); + printf(" %s:%hu",inet_ntoa(ioc->dst_addr), + htons(ioc->dst_port)); + printf(" %c", ioc->direction? 'o' : 'i'); + printf(" %lld", (long long)ioc->life); printf("\n"); - nat_state++; + ioc++; } } - int get_kern_boottime(void) { diff --git a/sys/net/ipfw3_nat/ip_fw3_nat.c b/sys/net/ipfw3_nat/ip_fw3_nat.c index 65d2b7d3fc..1b09288417 100644 --- a/sys/net/ipfw3_nat/ip_fw3_nat.c +++ b/sys/net/ipfw3_nat/ip_fw3_nat.c @@ -449,7 +449,161 @@ nospace: int ip_fw3_ctl_nat_get_record(struct sockopt *sopt) { - /* TODO */ + struct ip_fw3_nat_context *nat_ctx; + struct cfg_nat *the; + size_t sopt_size, total_len = 0; + struct ioc_nat_state *ioc; + int ioc_nat_id, n, cpu; + struct nat_state *s, *tmp; + + ioc_nat_id = *((int *)(sopt->sopt_val)); + sopt_size = sopt->sopt_valsize; + ioc = (struct ioc_nat_state *)sopt->sopt_val; + /* icmp states only in CPU 0 */ + cpu = 0; + nat_ctx = ip_fw3_nat_ctx[cpu]; + for (n = 0; n < NAT_ID_MAX; n++) { + if (ioc_nat_id == 0 || ioc_nat_id == n + 1) { + if (nat_ctx->nats[n] == NULL) + break; + the = nat_ctx->nats[n]; + RB_FOREACH_SAFE(s, state_tree, &the->tree_icmp_out, tmp) { + total_len += LEN_IOC_NAT_STATE; + if (total_len > sopt_size) + goto nospace; + ioc->src_addr.s_addr = ntohl(s->saddr); + ioc->dst_addr.s_addr = s->daddr; + ioc->alias_addr.s_addr = s->alias_addr; + ioc->src_port = s->sport; + ioc->dst_port = s->dport; + ioc->alias_port = s->alias_port; + ioc->nat_id = n + 1; + ioc->cpu_id = cpu; + ioc->proto = IPPROTO_ICMP; + ioc->direction = 1; + ioc->life = s->timestamp + + sysctl_var_icmp_timeout - time_uptime; + ioc++; + } + RB_FOREACH_SAFE(s, state_tree, &the->tree_icmp_in, tmp) { + total_len += LEN_IOC_NAT_STATE; + if (total_len > sopt_size) + goto nospace; + ioc->src_addr.s_addr = ntohl(s->saddr); + ioc->dst_addr.s_addr = s->daddr; + ioc->alias_addr.s_addr = s->alias_addr; + ioc->src_port = s->sport; + ioc->dst_port = s->dport; + ioc->alias_port = s->alias_port; + ioc->nat_id = n + 1; + ioc->cpu_id = cpu; + ioc->proto = IPPROTO_ICMP; + ioc->direction = 0; + ioc->life = s->timestamp + + sysctl_var_icmp_timeout - time_uptime; + ioc++; + } + } + } + + /* tcp states */ + for (cpu = 0; cpu < ncpus; cpu++) { + nat_ctx = ip_fw3_nat_ctx[cpu]; + for (n = 0; n < NAT_ID_MAX; n++) { + if (ioc_nat_id == 0 || ioc_nat_id == n + 1) { + if (nat_ctx->nats[n] == NULL) + break; + the = nat_ctx->nats[n]; + RB_FOREACH_SAFE(s, state_tree, &the->tree_tcp_out, tmp) { + total_len += LEN_IOC_NAT_STATE; + if (total_len > sopt_size) + goto nospace; + ioc->src_addr.s_addr = ntohl(s->saddr); + ioc->dst_addr.s_addr = ntohl(s->daddr); + ioc->alias_addr.s_addr = s->alias_addr; + ioc->src_port = ntohs(s->sport); + ioc->dst_port = ntohs(s->dport); + ioc->alias_port = s->alias_port; + ioc->nat_id = n + 1; + ioc->cpu_id = cpu; + ioc->proto = IPPROTO_TCP; + ioc->direction = 1; + ioc->life = s->timestamp + + sysctl_var_tcp_timeout - time_uptime; + ioc++; + } + RB_FOREACH_SAFE(s, state_tree, &the->tree_tcp_in, tmp) { + total_len += LEN_IOC_NAT_STATE; + if (total_len > sopt_size) + goto nospace; + ioc->src_addr.s_addr = ntohl(s->saddr); + ioc->dst_addr.s_addr = s->daddr; + ioc->alias_addr.s_addr = s->alias_addr; + ioc->src_port = ntohs(s->sport); + ioc->dst_port = s->dport; + ioc->alias_port = s->alias_port; + ioc->nat_id = n + 1; + ioc->cpu_id = cpu; + ioc->proto = IPPROTO_TCP; + ioc->direction = 0; + ioc->life = s->timestamp + + sysctl_var_tcp_timeout - time_uptime; + ioc++; + } + } + } + } + + /* udp states */ + for (cpu = 0; cpu < ncpus; cpu++) { + nat_ctx = ip_fw3_nat_ctx[cpu]; + for (n = 0; n < NAT_ID_MAX; n++) { + if (ioc_nat_id == 0 || ioc_nat_id == n + 1) { + if (nat_ctx->nats[n] == NULL) + break; + the = nat_ctx->nats[n]; + RB_FOREACH_SAFE(s, state_tree, &the->tree_udp_out, tmp) { + total_len += LEN_IOC_NAT_STATE; + if (total_len > sopt_size) + goto nospace; + ioc->src_addr.s_addr = ntohl(s->saddr); + ioc->dst_addr.s_addr = s->daddr; + ioc->alias_addr.s_addr = s->alias_addr; + ioc->src_port = s->sport; + ioc->dst_port = s->dport; + ioc->alias_port = s->alias_port; + ioc->nat_id = n + 1; + ioc->cpu_id = cpu; + ioc->proto = IPPROTO_UDP; + ioc->direction = 1; + ioc->life = s->timestamp + + sysctl_var_udp_timeout - time_uptime; + ioc++; + } + RB_FOREACH_SAFE(s, state_tree, &the->tree_udp_in, tmp) { + total_len += LEN_IOC_NAT_STATE; + if (total_len > sopt_size) + goto nospace; + ioc->src_addr.s_addr = ntohl(s->saddr); + ioc->dst_addr.s_addr = s->daddr; + ioc->alias_addr.s_addr = s->alias_addr; + ioc->src_port = s->sport; + ioc->dst_port = s->dport; + ioc->alias_port = s->alias_port; + ioc->nat_id = n + 1; + ioc->cpu_id = cpu; + ioc->proto = IPPROTO_UDP; + ioc->direction = 0; + ioc->life = s->timestamp + + sysctl_var_udp_timeout - time_uptime; + ioc++; + } + } + } + } + sopt->sopt_valsize = total_len; + return 0; +nospace: return 0; } diff --git a/sys/net/ipfw3_nat/ip_fw3_nat.h b/sys/net/ipfw3_nat/ip_fw3_nat.h index f60516c093..e945c7ac59 100644 --- a/sys/net/ipfw3_nat/ip_fw3_nat.h +++ b/sys/net/ipfw3_nat/ip_fw3_nat.h @@ -45,21 +45,20 @@ enum ipfw_nat_opcodes { O_NAT_NAT, }; -struct ipfw_ioc_nat_state { +struct ioc_nat_state { struct in_addr src_addr; struct in_addr dst_addr; struct in_addr alias_addr; u_short src_port; u_short dst_port; u_short alias_port; - - int link_type; - int timestamp; - int expire_time; int nat_id; - int cpuid; - int is_outgoing; + int cpu_id; + int proto; + int direction; + time_t life; }; +#define LEN_IOC_NAT_STATE sizeof(struct ioc_nat_state) struct ioc_nat { int id; -- 2.11.4.GIT