2 * Copyright (c) 2016 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Bill Yuan <bycn82@dragonflybsd.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/param.h>
37 #include <sys/socket.h>
38 #include <sys/sockio.h>
39 #include <sys/sysctl.h>
43 #include <arpa/inet.h>
61 #include <netinet/in.h>
62 #include <netinet/in_systm.h>
63 #include <netinet/ip.h>
64 #include <netinet/ip_icmp.h>
65 #include <netinet/tcp.h>
67 #include <net/if_dl.h>
68 #include <net/route.h>
69 #include <net/ethernet.h>
71 #include "../../sys/net/ipfw3/ip_fw3.h"
72 #include "../../sys/net/ipfw3/ip_fw3_table.h"
73 #include "../../sys/net/ipfw3/ip_fw3_sync.h"
74 #include "../../sys/net/dummynet3/ip_dummynet3.h"
75 #include "../../sys/net/libalias/alias.h"
76 #include "../../sys/net/ipfw3_basic/ip_fw3_basic.h"
77 #include "../../sys/net/ipfw3_nat/ip_fw3_nat.h"
87 struct char_int_map nat_params
[] = {
91 { "deny_in", TOK_DENY_INC
},
92 { "same_ports", TOK_SAME_PORTS
},
93 { "unreg_only", TOK_UNREG_ONLY
},
94 { "reset", TOK_RESET_ADDR
},
95 { "reverse", TOK_ALIAS_REV
},
96 { "proxy_only", TOK_PROXY_ONLY
},
97 { "redirect_addr", TOK_REDIR_ADDR
},
98 { "redirect_port", TOK_REDIR_PORT
},
99 { "redirect_proto", TOK_REDIR_PROTO
},
105 nat_config(int ac
, char **av
)
107 struct cfg_nat
*n
; /* Nat instance configuration. */
108 int i
, len
, off
, tok
;
109 char *id
, buf
[NAT_BUF_LEN
]; /* Buffer for serialized data. */
112 /* Offset in buf: save space for n at the beginning. */
113 off
= sizeof(struct cfg_nat
);
114 memset(buf
, 0, sizeof(buf
));
115 n
= (struct cfg_nat
*)buf
;
119 if (ac
&& isdigit(**av
)) {
125 errx(EX_DATAERR
, "missing nat id");
127 errx(EX_DATAERR
, "missing option");
130 tok
= match_token(nat_params
, *av
);
135 errx(EX_DATAERR
, "missing option");
136 if (!inet_aton(av
[0], &(n
->ip
)))
137 errx(EX_DATAERR
, "bad ip addr `%s'", av
[0]);
142 errx(EX_DATAERR
, "missing option");
143 set_addr_dynamic(av
[0], n
);
147 n
->mode
|= PKT_ALIAS_LOG
;
150 n
->mode
|= PKT_ALIAS_DENY_INCOMING
;
153 n
->mode
|= PKT_ALIAS_SAME_PORTS
;
156 n
->mode
|= PKT_ALIAS_UNREGISTERED_ONLY
;
159 n
->mode
|= PKT_ALIAS_RESET_ON_ADDR_CHANGE
;
162 n
->mode
|= PKT_ALIAS_REVERSE
;
165 n
->mode
|= PKT_ALIAS_PROXY_ONLY
;
168 * All the setup_redir_* functions work
169 * directly in the final
170 * buffer, see above for details.
174 case TOK_REDIR_PROTO
:
177 i
= setup_redir_addr(&buf
[off
], len
, &ac
, &av
);
180 i
= setup_redir_port(&buf
[off
], len
, &ac
, &av
);
182 case TOK_REDIR_PROTO
:
183 i
= setup_redir_proto(&buf
[off
], len
, &ac
, &av
);
191 errx(EX_DATAERR
, "unrecognised option ``%s''", av
[-1]);
194 i
= do_set_x(IP_FW_NAT_ADD
, buf
, off
);
196 err(1, "do_set_x(%s)", "IP_FW_NAT_ADD");
199 /* After every modification, we show the resultant rule. */
201 char *_av
[] = {"config", id
};
206 nat_show_config(char *buf
)
212 int i
, cnt
, flag
, off
;
214 n
= (struct cfg_nat
*)buf
;
217 printf("ipfw3 nat %u config", n
->id
);
218 if (strlen(n
->if_name
) != 0)
219 printf(" if %s", n
->if_name
);
220 else if (n
->ip
.s_addr
!= 0)
221 printf(" ip %s", inet_ntoa(n
->ip
));
222 while (n
->mode
!= 0) {
223 if (n
->mode
& PKT_ALIAS_LOG
) {
225 n
->mode
&= ~PKT_ALIAS_LOG
;
226 } else if (n
->mode
& PKT_ALIAS_DENY_INCOMING
) {
228 n
->mode
&= ~PKT_ALIAS_DENY_INCOMING
;
229 } else if (n
->mode
& PKT_ALIAS_SAME_PORTS
) {
230 printf(" same_ports");
231 n
->mode
&= ~PKT_ALIAS_SAME_PORTS
;
232 } else if (n
->mode
& PKT_ALIAS_UNREGISTERED_ONLY
) {
233 printf(" unreg_only");
234 n
->mode
&= ~PKT_ALIAS_UNREGISTERED_ONLY
;
235 } else if (n
->mode
& PKT_ALIAS_RESET_ON_ADDR_CHANGE
) {
237 n
->mode
&= ~PKT_ALIAS_RESET_ON_ADDR_CHANGE
;
238 } else if (n
->mode
& PKT_ALIAS_REVERSE
) {
240 n
->mode
&= ~PKT_ALIAS_REVERSE
;
241 } else if (n
->mode
& PKT_ALIAS_PROXY_ONLY
) {
242 printf(" proxy_only");
243 n
->mode
&= ~PKT_ALIAS_PROXY_ONLY
;
247 /* Print all the redirect's data configuration. */
248 for (cnt
= 0; cnt
< n
->redir_cnt
; cnt
++) {
249 t
= (struct cfg_redir
*)&buf
[off
];
253 printf(" redirect_addr");
254 if (t
->spool_cnt
== 0) {
255 printf(" %s", inet_ntoa(t
->laddr
));
257 for (i
= 0; i
< t
->spool_cnt
; i
++) {
258 s
= (struct cfg_spool
*)&buf
[off
];
263 printf("%s", inet_ntoa(s
->addr
));
267 printf(" %s", inet_ntoa(t
->paddr
));
270 p
= getprotobynumber(t
->proto
);
271 printf(" redirect_port %s ", p
->p_name
);
273 printf("%s:%u", inet_ntoa(t
->laddr
), t
->lport
);
274 if (t
->pport_cnt
> 1) {
275 printf("-%u", t
->lport
+
279 for (i
=0; i
< t
->spool_cnt
; i
++) {
280 s
= (struct cfg_spool
*)&buf
[off
];
284 printf("%s:%u", inet_ntoa(s
->addr
),
290 if (t
->paddr
.s_addr
) {
291 printf("%s:", inet_ntoa(t
->paddr
));
293 printf("%u", t
->pport
);
294 if (!t
->spool_cnt
&& t
->pport_cnt
> 1) {
295 printf("-%u", t
->pport
+ t
->pport_cnt
- 1);
298 if (t
->raddr
.s_addr
) {
299 printf(" %s", inet_ntoa(t
->raddr
));
301 printf(":%u", t
->rport
);
302 if (!t
->spool_cnt
&& t
->rport_cnt
> 1) {
303 printf("-%u", t
->rport
+
310 p
= getprotobynumber(t
->proto
);
311 printf(" redirect_proto %s %s", p
->p_name
,
312 inet_ntoa(t
->laddr
));
313 if (t
->paddr
.s_addr
!= 0) {
314 printf(" %s", inet_ntoa(t
->paddr
));
315 if (t
->raddr
.s_addr
) {
316 printf(" %s", inet_ntoa(t
->raddr
));
321 errx(EX_DATAERR
, "unknown redir mode");
330 nat_show(int ac
, char **av
)
334 int i
, nbytes
, nalloc
, size
;
335 int nat_cnt
, redir_cnt
, nat_id
;
347 nat_id
= strtoul(*av
, NULL
, 10);
350 while (nbytes
>= nalloc
) {
353 if ((data
= realloc(data
, nbytes
)) == NULL
) {
354 err(EX_OSERR
, "realloc");
356 if (do_get_x(IP_FW_NAT_GET
, data
, &nbytes
) < 0) {
357 err(EX_OSERR
, "do_get_x(IP_FW_NAT_GET)");
365 nat_cnt
= *((int *)data
);
366 for (i
= sizeof(nat_cnt
); nat_cnt
; nat_cnt
--) {
367 n
= (struct cfg_nat
*)&data
[i
];
368 if (n
->id
>= 0 && n
->id
<= IPFW_DEFAULT_RULE
) {
369 if (nat_id
== 0 || n
->id
== nat_id
)
370 nat_show_config(&data
[i
]);
372 i
+= sizeof(struct cfg_nat
);
373 for (redir_cnt
= 0; redir_cnt
< n
->redir_cnt
; redir_cnt
++) {
374 e
= (struct cfg_redir
*)&data
[i
];
375 i
+= sizeof(struct cfg_redir
) +
376 e
->spool_cnt
* sizeof(struct cfg_spool
);
382 setup_redir_port(char *spool_buf
, int len
, int *_ac
, char ***_av
)
384 char **av
, *sep
, *protoName
;
385 char tmp_spool_buf
[NAT_BUF_LEN
];
386 int ac
, space
, lsnat
;
388 struct cfg_spool
*tmp
;
389 u_short numLocalPorts
;
390 port_range portRange
;
398 if (len
>= SOF_REDIR
) {
399 r
= (struct cfg_redir
*)spool_buf
;
400 /* Skip cfg_redir at beginning of buf. */
401 spool_buf
= &spool_buf
[SOF_REDIR
];
408 r
->mode
= REDIR_PORT
;
413 errx (EX_DATAERR
, "redirect_port: missing protocol");
415 r
->proto
= str2proto(*av
);
420 * Extract local address.
423 errx (EX_DATAERR
, "redirect_port: missing local address");
425 sep
= strchr(*av
, ',');
426 /* LSNAT redirection syntax. */
428 r
->laddr
.s_addr
= INADDR_NONE
;
431 /* Preserve av, copy spool servers to tmp_spool_buf. */
432 strncpy(tmp_spool_buf
, *av
, strlen(*av
)+1);
435 if (str2addr_portrange (*av
, &r
->laddr
,
436 protoName
, &portRange
) != 0)
437 errx(EX_DATAERR
, "redirect_port:"
438 "invalid local port range");
440 r
->lport
= GETLOPORT(portRange
);
441 numLocalPorts
= GETNUMPORTS(portRange
);
446 * Extract public port and optionally address.
449 errx (EX_DATAERR
, "redirect_port: missing public port");
451 sep
= strchr (*av
, ':');
453 if (str2addr_portrange (*av
, &r
->paddr
, protoName
, &portRange
) != 0)
454 errx(EX_DATAERR
, "redirect_port:"
455 "invalid public port range");
457 r
->paddr
.s_addr
= INADDR_ANY
;
458 if (str2portrange(*av
, protoName
, &portRange
) != 0)
459 errx(EX_DATAERR
, "redirect_port:"
460 "invalid public port range");
463 r
->pport
= GETLOPORT(portRange
);
464 r
->pport_cnt
= GETNUMPORTS(portRange
);
468 * Extract remote address and optionally port.
471 * NB: isalpha(**av) => we've to check that next parameter is really an
472 * option for this redirect entry, else stop here processing arg[cv].
474 if (ac
!= 0 && !isalpha(**av
)) {
475 sep
= strchr (*av
, ':');
477 if (str2addr_portrange (*av
, &r
->raddr
,
478 protoName
, &portRange
) != 0) {
479 errx(EX_DATAERR
, "redirect_port:"
480 "invalid remote port range");
483 SETLOPORT(portRange
, 0);
484 SETNUMPORTS(portRange
, 1);
485 str2addr (*av
, &r
->raddr
);
489 SETLOPORT(portRange
, 0);
490 SETNUMPORTS(portRange
, 1);
491 r
->raddr
.s_addr
= INADDR_ANY
;
493 r
->rport
= GETLOPORT(portRange
);
494 r
->rport_cnt
= GETNUMPORTS(portRange
);
497 * Make sure port ranges match up, then add the redirect ports.
499 if (numLocalPorts
!= r
->pport_cnt
) {
500 errx(EX_DATAERR
, "redirect_port:"
501 "port ranges must be equal in size");
504 /* Remote port range is allowed to be '0' which means all ports. */
505 if (r
->rport_cnt
!= numLocalPorts
&&
506 (r
->rport_cnt
!= 1 || r
->rport
!= 0)) {
507 errx(EX_DATAERR
, "redirect_port: remote port must"
508 "be 0 or equal to local port range in size");
512 * Setup LSNAT server pool.
515 sep
= strtok(tmp_spool_buf
, ", ");
516 while (sep
!= NULL
) {
517 tmp
= (struct cfg_spool
*)spool_buf
;
523 if (str2addr_portrange(sep
,
524 &tmp
->addr
, protoName
, &portRange
) != 0)
525 errx(EX_DATAERR
, "redirect_port:"
526 "invalid local port range");
527 if (GETNUMPORTS(portRange
) != 1)
528 errx(EX_DATAERR
, "redirect_port: local port"
529 "must be single in this context");
530 tmp
->port
= GETLOPORT(portRange
);
532 /* Point to the next possible cfg_spool. */
533 spool_buf
= &spool_buf
[SOF_SPOOL
];
534 sep
= strtok(NULL
, ", ");
540 errx(EX_DATAERR
, "redirect_port: buf is too small\n");
544 setup_redir_proto(char *spool_buf
, int len
, int *_ac
, char ***_av
)
546 struct protoent
*protoent
;
554 if (len
>= SOF_REDIR
) {
555 r
= (struct cfg_redir
*)spool_buf
;
556 /* Skip cfg_redir at beginning of buf. */
557 spool_buf
= &spool_buf
[SOF_REDIR
];
563 r
->mode
= REDIR_PROTO
;
568 errx(EX_DATAERR
, "redirect_proto: missing protocol");
570 protoent
= getprotobyname(*av
);
571 if (protoent
== NULL
)
572 errx(EX_DATAERR
, "redirect_proto: unknown protocol %s", *av
);
574 r
->proto
= protoent
->p_proto
;
579 * Extract local address.
582 errx(EX_DATAERR
, "redirect_proto: missing local address");
584 str2addr(*av
, &r
->laddr
);
588 * Extract optional public address.
591 r
->paddr
.s_addr
= INADDR_ANY
;
592 r
->raddr
.s_addr
= INADDR_ANY
;
594 /* see above in setup_redir_port() */
595 if (!isalpha(**av
)) {
596 str2addr(*av
, &r
->paddr
);
600 * Extract optional remote address.
602 /* see above in setup_redir_port() */
603 if (ac
!= 0 && !isalpha(**av
)) {
604 str2addr(*av
, &r
->raddr
);
612 errx(EX_DATAERR
, "redirect_proto: buf is too small\n");
616 str2proto(const char* str
)
618 if (!strcmp (str
, "tcp"))
620 if (!strcmp (str
, "udp"))
622 errx (EX_DATAERR
, "unknown protocol %s. Expected tcp or udp", str
);
626 str2addr_portrange (const char* str
, struct in_addr
* addr
,
627 char* proto
, port_range
*portRange
)
631 ptr
= strchr (str
, ':');
633 errx (EX_DATAERR
, "%s is missing port number", str
);
638 str2addr (str
, addr
);
639 return str2portrange (ptr
, proto
, portRange
);
643 * Search for interface with name "ifn", and fill n accordingly:
645 * n->ip ip address of interface "ifn"
646 * n->if_name copy of interface name "ifn"
649 set_addr_dynamic(const char *ifn
, struct cfg_nat
*n
)
651 struct if_msghdr
*ifm
;
652 struct ifa_msghdr
*ifam
;
653 struct sockaddr_dl
*sdl
;
654 struct sockaddr_in
*sin
;
655 char *buf
, *lim
, *next
;
664 mib
[4] = NET_RT_IFLIST
;
668 * Get interface data.
670 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) == -1)
671 err(1, "iflist-sysctl-estimate");
672 if ((buf
= malloc(needed
)) == NULL
)
673 errx(1, "malloc failed");
674 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) == -1)
675 err(1, "iflist-sysctl-get");
678 * Loop through interfaces until one with
679 * given name is found. This is done to
680 * find correct interface index for routing
681 * message processing.
686 ifm
= (struct if_msghdr
*)next
;
687 next
+= ifm
->ifm_msglen
;
688 if (ifm
->ifm_version
!= RTM_VERSION
) {
690 warnx("routing message version %d "
691 "not understood", ifm
->ifm_version
);
694 if (ifm
->ifm_type
== RTM_IFINFO
) {
695 sdl
= (struct sockaddr_dl
*)(ifm
+ 1);
696 if (strlen(ifn
) == sdl
->sdl_nlen
&&
697 strncmp(ifn
, sdl
->sdl_data
,
698 sdl
->sdl_nlen
) == 0) {
699 ifIndex
= ifm
->ifm_index
;
700 ifMTU
= ifm
->ifm_data
.ifi_mtu
;
706 errx(1, "unknown interface name %s", ifn
);
708 * Get interface address.
712 ifam
= (struct ifa_msghdr
*)next
;
713 next
+= ifam
->ifam_msglen
;
714 if (ifam
->ifam_version
!= RTM_VERSION
) {
716 warnx("routing message version %d "
717 "not understood", ifam
->ifam_version
);
720 if (ifam
->ifam_type
!= RTM_NEWADDR
)
722 if (ifam
->ifam_addrs
& RTA_IFA
) {
724 char *cp
= (char *)(ifam
+ 1);
726 for (i
= 1; i
< RTA_IFA
; i
<<= 1) {
727 if (ifam
->ifam_addrs
& i
)
728 cp
+= SA_SIZE((struct sockaddr
*)cp
);
730 if (((struct sockaddr
*)cp
)->sa_family
== AF_INET
) {
731 sin
= (struct sockaddr_in
*)cp
;
737 errx(1, "%s: cannot get interface address", ifn
);
739 n
->ip
= sin
->sin_addr
;
740 strncpy(n
->if_name
, ifn
, IF_NAMESIZE
);
746 setup_redir_addr(char *spool_buf
, int len
, int *_ac
, char ***_av
)
749 struct cfg_spool
*tmp
;
751 char tmp_spool_buf
[NAT_BUF_LEN
];
752 int ac
, i
, space
, lsnat
;
759 if (len
>= SOF_REDIR
) {
760 r
= (struct cfg_redir
*)spool_buf
;
761 /* Skip cfg_redir at beginning of buf. */
762 spool_buf
= &spool_buf
[SOF_REDIR
];
769 r
->mode
= REDIR_ADDR
;
770 /* Extract local address. */
772 errx(EX_DATAERR
, "redirect_addr: missing local address");
774 sep
= strchr(*av
, ',');
775 if (sep
) { /* LSNAT redirection syntax. */
776 r
->laddr
.s_addr
= INADDR_NONE
;
777 /* Preserve av, copy spool servers to tmp_spool_buf. */
778 strncpy(tmp_spool_buf
, *av
, strlen(*av
)+1);
781 str2addr(*av
, &r
->laddr
);
785 /* Extract public address. */
787 errx(EX_DATAERR
, "redirect_addr: missing public address");
789 str2addr(*av
, &r
->paddr
);
792 /* Setup LSNAT server pool. */
794 sep
= strtok(tmp_spool_buf
, ", ");
795 while (sep
!= NULL
) {
796 tmp
= (struct cfg_spool
*)spool_buf
;
802 str2addr(sep
, &tmp
->addr
);
805 /* Point to the next possible cfg_spool. */
806 spool_buf
= &spool_buf
[SOF_SPOOL
];
807 sep
= strtok(NULL
, ", ");
813 errx(EX_DATAERR
, "redirect_addr: buf is too small\n");
817 str2addr(const char* str
, struct in_addr
* addr
)
821 if (inet_aton (str
, addr
))
824 hp
= gethostbyname (str
);
826 errx (1, "unknown host %s", str
);
828 memcpy (addr
, hp
->h_addr
, sizeof (struct in_addr
));
832 str2portrange(const char* str
, const char* proto
, port_range
*portRange
)
837 u_short loPort
, hiPort
;
839 /* First see if this is a service, return corresponding port if so. */
840 sp
= getservbyname (str
, proto
);
842 SETLOPORT(*portRange
, ntohs(sp
->s_port
));
843 SETNUMPORTS(*portRange
, 1);
847 /* Not a service, see if it's a single port or port range. */
848 sep
= strchr (str
, '-');
850 SETLOPORT(*portRange
, strtol(str
, &end
, 10));
853 SETNUMPORTS(*portRange
, 1);
857 /* Error in port range field. */
858 errx (EX_DATAERR
, "%s/%s: unknown service", str
, proto
);
861 /* Port range, get the values and sanity check. */
862 sscanf (str
, "%hu-%hu", &loPort
, &hiPort
);
863 SETLOPORT(*portRange
, loPort
);
864 SETNUMPORTS(*portRange
, 0); /* Error by default */
865 if (loPort
<= hiPort
)
866 SETNUMPORTS(*portRange
, hiPort
- loPort
+ 1);
868 if (GETNUMPORTS(*portRange
) == 0)
869 errx (EX_DATAERR
, "invalid port range %s", str
);
875 nat_delete_config(int ac
, char *av
[])
882 if (do_set_x(IP_FW_NAT_DEL
, &i
, sizeof(i
)) == -1)
883 errx(EX_USAGE
, "NAT %d in use or not exists", i
);
887 nat_show_state(int ac
, char **av
)
900 nat_id
= strtoul(*av
, NULL
, 10);
903 while (nbytes
>= nalloc
) {
906 if ((data
= realloc(data
, nbytes
)) == NULL
) {
907 err(EX_OSERR
, "realloc");
909 memcpy(data
, &nat_id
, sizeof(int));
910 if (do_get_x(IP_FW_NAT_GET_RECORD
, data
, &nbytes
) < 0) {
911 err(EX_OSERR
, "do_get_x(IP_FW_NAT_GET_RECORD)");
916 struct ipfw_ioc_nat_state
*nat_state
;
917 nat_state
=(struct ipfw_ioc_nat_state
*)data
;
918 int count
= nbytes
/ sizeof( struct ipfw_ioc_nat_state
);
920 uptime_sec
= get_kern_boottime();
921 for (i
= 0; i
< count
; i
++) {
922 printf("#%d ", nat_state
->cpuid
);
923 printf("%s:%hu => ",inet_ntoa(nat_state
->src_addr
),
924 htons(nat_state
->src_port
));
925 printf("%s:%hu",inet_ntoa(nat_state
->alias_addr
),
926 htons(nat_state
->alias_port
));
927 printf(" -> %s:%hu ",inet_ntoa(nat_state
->dst_addr
),
928 htons(nat_state
->dst_port
));
931 time_t t
= _long_to_time(uptime_sec
+
932 nat_state
->timestamp
);
933 strcpy(timestr
, ctime(&t
));
934 *strchr(timestr
, '\n') = '\0';
935 printf("%s ", timestr
);
936 } else if (do_time
== 2) {
937 printf( "%10u ", uptime_sec
+ nat_state
->timestamp
);
939 struct protoent
*pe
= getprotobynumber(nat_state
->link_type
);
940 printf("%s ", pe
->p_name
);
941 printf(" %s", nat_state
->is_outgoing
? "out": "in");
948 get_kern_boottime(void)
950 struct timeval boottime
;
954 mib
[1] = KERN_BOOTTIME
;
955 size
= sizeof(boottime
);
956 if (sysctl(mib
, 2, &boottime
, &size
, NULL
, 0) != -1 &&
957 boottime
.tv_sec
!= 0) {
958 return boottime
.tv_sec
;
966 int cmd
= IP_FW_NAT_FLUSH
;
970 printf("Are you sure? [yn] ");
973 c
= toupper(getc(stdin
));
974 while (c
!= '\n' && getc(stdin
) != '\n')
976 return; /* and do not flush */
977 } while (c
!= 'Y' && c
!= 'N');
978 if (c
== 'N') /* user said no */
981 if (do_set_x(cmd
, NULL
, 0) < 0 ) {
982 errx(EX_USAGE
, "NAT configuration in use");
985 printf("Flushed all nat configurations");
990 nat_main(int ac
, char **av
)
992 if (!strncmp(*av
, "config", strlen(*av
))) {
994 } else if (!strncmp(*av
, "flush", strlen(*av
))) {
996 } else if (!strncmp(*av
, "show", strlen(*av
)) ||
997 !strncmp(*av
, "list", strlen(*av
))) {
998 if (ac
> 2 && isdigit(*(av
[1]))) {
1004 if (!strncmp(*av
, "config", strlen(*av
))) {
1006 } else if (!strncmp(*av
, "state", strlen(*av
))) {
1007 nat_show_state(ac
,av
);
1010 "bad nat show command `%s'", *av
);
1012 } else if (!strncmp(*av
, "delete", strlen(*av
))) {
1013 nat_delete_config(ac
, av
);
1015 errx(EX_USAGE
, "bad ipfw nat command `%s'", *av
);