Deleted Added
full compact
nat.c (240351) nat.c (272840)
1/*
2 * Copyright (c) 2002-2003 Luigi Rizzo
3 * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
4 * Copyright (c) 1994 Ugen J.S.Antsilevich
5 *
6 * Idea and grammar partially left from:
7 * Copyright (c) 1993 Daniel Boulet
8 *
9 * Redistribution and use in source forms, with and without modification,
10 * are permitted provided that this entire comment appears intact.
11 *
12 * Redistribution in binary form may occur without any restrictions.
13 * Obviously, it would be nice if you gave credit where credit is due
14 * but requiring it would be too onerous.
15 *
16 * This software is provided ``AS IS'' without any warranties of any kind.
17 *
18 * NEW command line interface for IP firewall facility
19 *
1/*
2 * Copyright (c) 2002-2003 Luigi Rizzo
3 * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
4 * Copyright (c) 1994 Ugen J.S.Antsilevich
5 *
6 * Idea and grammar partially left from:
7 * Copyright (c) 1993 Daniel Boulet
8 *
9 * Redistribution and use in source forms, with and without modification,
10 * are permitted provided that this entire comment appears intact.
11 *
12 * Redistribution in binary form may occur without any restrictions.
13 * Obviously, it would be nice if you gave credit where credit is due
14 * but requiring it would be too onerous.
15 *
16 * This software is provided ``AS IS'' without any warranties of any kind.
17 *
18 * NEW command line interface for IP firewall facility
19 *
20 * $FreeBSD: head/sbin/ipfw/nat.c 240351 2012-09-11 07:54:41Z kevlo $
20 * $FreeBSD: head/sbin/ipfw/nat.c 272840 2014-10-09 19:32:35Z melifaro $
21 *
22 * In-kernel nat support
23 */
24
25#include <sys/types.h>
26#include <sys/socket.h>
27#include <sys/sysctl.h>
28
29#include "ipfw2.h"
30
31#include <ctype.h>
32#include <err.h>
21 *
22 * In-kernel nat support
23 */
24
25#include <sys/types.h>
26#include <sys/socket.h>
27#include <sys/sysctl.h>
28
29#include "ipfw2.h"
30
31#include <ctype.h>
32#include <err.h>
33#include <errno.h>
33#include <netdb.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <sysexits.h>
38
34#include <netdb.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include <sysexits.h>
39
39#define IPFW_INTERNAL /* Access to protected structures in ip_fw.h. */
40
41#include <net/if.h>
42#include <net/if_dl.h>
43#include <net/route.h> /* def. of struct route */
44#include <netinet/in.h>
45#include <netinet/ip_fw.h>
46#include <arpa/inet.h>
47#include <alias.h>
48
40#include <net/if.h>
41#include <net/if_dl.h>
42#include <net/route.h> /* def. of struct route */
43#include <netinet/in.h>
44#include <netinet/ip_fw.h>
45#include <arpa/inet.h>
46#include <alias.h>
47
48typedef int (nat_cb_t)(struct nat44_cfg_nat *cfg, void *arg);
49static void nat_show_cfg(struct nat44_cfg_nat *n, void *arg);
50static void nat_show_log(struct nat44_cfg_nat *n, void *arg);
51static int nat_show_data(struct nat44_cfg_nat *cfg, void *arg);
52static int natname_cmp(const void *a, const void *b);
53static int nat_foreach(nat_cb_t *f, void *arg, int sort);
54static int nat_get_cmd(char *name, uint16_t cmd, ipfw_obj_header **ooh);
55
49static struct _s_x nat_params[] = {
50 { "ip", TOK_IP },
51 { "if", TOK_IF },
52 { "log", TOK_ALOG },
53 { "deny_in", TOK_DENY_INC },
54 { "same_ports", TOK_SAME_PORTS },
55 { "unreg_only", TOK_UNREG_ONLY },
56 { "skip_global", TOK_SKIP_GLOBAL },

--- 9 unchanged lines hidden (view full) ---

66
67/*
68 * Search for interface with name "ifn", and fill n accordingly:
69 *
70 * n->ip ip address of interface "ifn"
71 * n->if_name copy of interface name "ifn"
72 */
73static void
56static struct _s_x nat_params[] = {
57 { "ip", TOK_IP },
58 { "if", TOK_IF },
59 { "log", TOK_ALOG },
60 { "deny_in", TOK_DENY_INC },
61 { "same_ports", TOK_SAME_PORTS },
62 { "unreg_only", TOK_UNREG_ONLY },
63 { "skip_global", TOK_SKIP_GLOBAL },

--- 9 unchanged lines hidden (view full) ---

73
74/*
75 * Search for interface with name "ifn", and fill n accordingly:
76 *
77 * n->ip ip address of interface "ifn"
78 * n->if_name copy of interface name "ifn"
79 */
80static void
74set_addr_dynamic(const char *ifn, struct cfg_nat *n)
81set_addr_dynamic(const char *ifn, struct nat44_cfg_nat *n)
75{
76 size_t needed;
77 int mib[6];
78 char *buf, *lim, *next;
79 struct if_msghdr *ifm;
80 struct ifa_msghdr *ifam;
81 struct sockaddr_dl *sdl;
82 struct sockaddr_in *sin;

--- 200 unchanged lines hidden (view full) ---

283/* End of stuff taken from natd.c. */
284
285/*
286 * The next 3 functions add support for the addr, port and proto redirect and
287 * their logic is loosely based on SetupAddressRedirect(), SetupPortRedirect()
288 * and SetupProtoRedirect() from natd.c.
289 *
290 * Every setup_* function fills at least one redirect entry
82{
83 size_t needed;
84 int mib[6];
85 char *buf, *lim, *next;
86 struct if_msghdr *ifm;
87 struct ifa_msghdr *ifam;
88 struct sockaddr_dl *sdl;
89 struct sockaddr_in *sin;

--- 200 unchanged lines hidden (view full) ---

290/* End of stuff taken from natd.c. */
291
292/*
293 * The next 3 functions add support for the addr, port and proto redirect and
294 * their logic is loosely based on SetupAddressRedirect(), SetupPortRedirect()
295 * and SetupProtoRedirect() from natd.c.
296 *
297 * Every setup_* function fills at least one redirect entry
291 * (struct cfg_redir) and zero or more server pool entry (struct cfg_spool)
292 * in buf.
298 * (struct nat44_cfg_redir) and zero or more server pool entry
299 * (struct nat44_cfg_spool) in buf.
293 *
294 * The format of data in buf is:
295 *
300 *
301 * The format of data in buf is:
302 *
296 * cfg_nat cfg_redir cfg_spool ...... cfg_spool
303 * nat44_cfg_nat nat44_cfg_redir nat44_cfg_spool ...... nat44_cfg_spool
297 *
298 * ------------------------------------- ------------
304 *
305 * ------------------------------------- ------------
299 * | | .....X ... | | | | .....
306 * | | .....X ..... | | | | .....
300 * ------------------------------------- ...... ------------
301 * ^
302 * spool_cnt n=0 ...... n=(X-1)
303 *
304 * len points to the amount of available space in buf
305 * space counts the memory consumed by every function
306 *
307 * XXX - Every function get all the argv params so it
308 * has to check, in optional parameters, that the next
309 * args is a valid option for the redir entry and not
310 * another token. Only redir_port and redir_proto are
311 * affected by this.
312 */
313
314static int
315estimate_redir_addr(int *ac, char ***av)
316{
307 * ------------------------------------- ...... ------------
308 * ^
309 * spool_cnt n=0 ...... n=(X-1)
310 *
311 * len points to the amount of available space in buf
312 * space counts the memory consumed by every function
313 *
314 * XXX - Every function get all the argv params so it
315 * has to check, in optional parameters, that the next
316 * args is a valid option for the redir entry and not
317 * another token. Only redir_port and redir_proto are
318 * affected by this.
319 */
320
321static int
322estimate_redir_addr(int *ac, char ***av)
323{
317 size_t space = sizeof(struct cfg_redir);
324 size_t space = sizeof(struct nat44_cfg_redir);
318 char *sep = **av;
319 u_int c = 0;
320
321 (void)ac; /* UNUSED */
322 while ((sep = strchr(sep, ',')) != NULL) {
323 c++;
324 sep++;
325 }
326
327 if (c > 0)
328 c++;
329
325 char *sep = **av;
326 u_int c = 0;
327
328 (void)ac; /* UNUSED */
329 while ((sep = strchr(sep, ',')) != NULL) {
330 c++;
331 sep++;
332 }
333
334 if (c > 0)
335 c++;
336
330 space += c * sizeof(struct cfg_spool);
337 space += c * sizeof(struct nat44_cfg_spool);
331
332 return (space);
333}
334
335static int
336setup_redir_addr(char *buf, int *ac, char ***av)
337{
338
339 return (space);
340}
341
342static int
343setup_redir_addr(char *buf, int *ac, char ***av)
344{
338 struct cfg_redir *r;
345 struct nat44_cfg_redir *r;
339 char *sep;
340 size_t space;
341
346 char *sep;
347 size_t space;
348
342 r = (struct cfg_redir *)buf;
349 r = (struct nat44_cfg_redir *)buf;
343 r->mode = REDIR_ADDR;
350 r->mode = REDIR_ADDR;
344 /* Skip cfg_redir at beginning of buf. */
345 buf = &buf[sizeof(struct cfg_redir)];
346 space = sizeof(struct cfg_redir);
351 /* Skip nat44_cfg_redir at beginning of buf. */
352 buf = &buf[sizeof(struct nat44_cfg_redir)];
353 space = sizeof(struct nat44_cfg_redir);
347
348 /* Extract local address. */
349 if (strchr(**av, ',') != NULL) {
354
355 /* Extract local address. */
356 if (strchr(**av, ',') != NULL) {
350 struct cfg_spool *spool;
357 struct nat44_cfg_spool *spool;
351
352 /* Setup LSNAT server pool. */
353 r->laddr.s_addr = INADDR_NONE;
354 sep = strtok(**av, ",");
355 while (sep != NULL) {
358
359 /* Setup LSNAT server pool. */
360 r->laddr.s_addr = INADDR_NONE;
361 sep = strtok(**av, ",");
362 while (sep != NULL) {
356 spool = (struct cfg_spool *)buf;
357 space += sizeof(struct cfg_spool);
363 spool = (struct nat44_cfg_spool *)buf;
364 space += sizeof(struct nat44_cfg_spool);
358 StrToAddr(sep, &spool->addr);
359 spool->port = ~0;
360 r->spool_cnt++;
365 StrToAddr(sep, &spool->addr);
366 spool->port = ~0;
367 r->spool_cnt++;
361 /* Point to the next possible cfg_spool. */
362 buf = &buf[sizeof(struct cfg_spool)];
368 /* Point to the next possible nat44_cfg_spool. */
369 buf = &buf[sizeof(struct nat44_cfg_spool)];
363 sep = strtok(NULL, ",");
364 }
365 } else
366 StrToAddr(**av, &r->laddr);
367 (*av)++; (*ac)--;
368
369 /* Extract public address. */
370 StrToAddr(**av, &r->paddr);
371 (*av)++; (*ac)--;
372
373 return (space);
374}
375
376static int
377estimate_redir_port(int *ac, char ***av)
378{
370 sep = strtok(NULL, ",");
371 }
372 } else
373 StrToAddr(**av, &r->laddr);
374 (*av)++; (*ac)--;
375
376 /* Extract public address. */
377 StrToAddr(**av, &r->paddr);
378 (*av)++; (*ac)--;
379
380 return (space);
381}
382
383static int
384estimate_redir_port(int *ac, char ***av)
385{
379 size_t space = sizeof(struct cfg_redir);
386 size_t space = sizeof(struct nat44_cfg_redir);
380 char *sep = **av;
381 u_int c = 0;
382
383 (void)ac; /* UNUSED */
384 while ((sep = strchr(sep, ',')) != NULL) {
385 c++;
386 sep++;
387 }
388
389 if (c > 0)
390 c++;
391
387 char *sep = **av;
388 u_int c = 0;
389
390 (void)ac; /* UNUSED */
391 while ((sep = strchr(sep, ',')) != NULL) {
392 c++;
393 sep++;
394 }
395
396 if (c > 0)
397 c++;
398
392 space += c * sizeof(struct cfg_spool);
399 space += c * sizeof(struct nat44_cfg_spool);
393
394 return (space);
395}
396
397static int
398setup_redir_port(char *buf, int *ac, char ***av)
399{
400
401 return (space);
402}
403
404static int
405setup_redir_port(char *buf, int *ac, char ***av)
406{
400 struct cfg_redir *r;
407 struct nat44_cfg_redir *r;
401 char *sep, *protoName, *lsnat = NULL;
402 size_t space;
403 u_short numLocalPorts;
404 port_range portRange;
405
406 numLocalPorts = 0;
407
408 char *sep, *protoName, *lsnat = NULL;
409 size_t space;
410 u_short numLocalPorts;
411 port_range portRange;
412
413 numLocalPorts = 0;
414
408 r = (struct cfg_redir *)buf;
415 r = (struct nat44_cfg_redir *)buf;
409 r->mode = REDIR_PORT;
416 r->mode = REDIR_PORT;
410 /* Skip cfg_redir at beginning of buf. */
411 buf = &buf[sizeof(struct cfg_redir)];
412 space = sizeof(struct cfg_redir);
417 /* Skip nat44_cfg_redir at beginning of buf. */
418 buf = &buf[sizeof(struct nat44_cfg_redir)];
419 space = sizeof(struct nat44_cfg_redir);
413
414 /*
415 * Extract protocol.
416 */
417 r->proto = StrToProto(**av);
418 protoName = **av;
419 (*av)++; (*ac)--;
420

--- 90 unchanged lines hidden (view full) ---

511 /* Remote port range is allowed to be '0' which means all ports. */
512 if (r->rport_cnt != numLocalPorts &&
513 (r->rport_cnt != 1 || r->rport != 0))
514 errx(EX_DATAERR, "redirect_port: remote port must"
515 "be 0 or equal to local port range in size");
516
517 /* Setup LSNAT server pool. */
518 if (lsnat != NULL) {
420
421 /*
422 * Extract protocol.
423 */
424 r->proto = StrToProto(**av);
425 protoName = **av;
426 (*av)++; (*ac)--;
427

--- 90 unchanged lines hidden (view full) ---

518 /* Remote port range is allowed to be '0' which means all ports. */
519 if (r->rport_cnt != numLocalPorts &&
520 (r->rport_cnt != 1 || r->rport != 0))
521 errx(EX_DATAERR, "redirect_port: remote port must"
522 "be 0 or equal to local port range in size");
523
524 /* Setup LSNAT server pool. */
525 if (lsnat != NULL) {
519 struct cfg_spool *spool;
526 struct nat44_cfg_spool *spool;
520
521 sep = strtok(lsnat, ",");
522 while (sep != NULL) {
527
528 sep = strtok(lsnat, ",");
529 while (sep != NULL) {
523 spool = (struct cfg_spool *)buf;
524 space += sizeof(struct cfg_spool);
530 spool = (struct nat44_cfg_spool *)buf;
531 space += sizeof(struct nat44_cfg_spool);
525 /*
526 * The sctp nat does not allow the port numbers to
527 * be mapped to new port numbers. Therefore, no ports
528 * are to be specified in the target port field.
529 */
530 if (r->proto == IPPROTO_SCTP) {
531 if (strchr (sep, ':')) {
532 errx(EX_DATAERR, "redirect_port:"

--- 11 unchanged lines hidden (view full) ---

544 "invalid local port range");
545 if (GETNUMPORTS(portRange) != 1)
546 errx(EX_DATAERR, "redirect_port: "
547 "local port must be single in "
548 "this context");
549 spool->port = GETLOPORT(portRange);
550 }
551 r->spool_cnt++;
532 /*
533 * The sctp nat does not allow the port numbers to
534 * be mapped to new port numbers. Therefore, no ports
535 * are to be specified in the target port field.
536 */
537 if (r->proto == IPPROTO_SCTP) {
538 if (strchr (sep, ':')) {
539 errx(EX_DATAERR, "redirect_port:"

--- 11 unchanged lines hidden (view full) ---

551 "invalid local port range");
552 if (GETNUMPORTS(portRange) != 1)
553 errx(EX_DATAERR, "redirect_port: "
554 "local port must be single in "
555 "this context");
556 spool->port = GETLOPORT(portRange);
557 }
558 r->spool_cnt++;
552 /* Point to the next possible cfg_spool. */
553 buf = &buf[sizeof(struct cfg_spool)];
559 /* Point to the next possible nat44_cfg_spool. */
560 buf = &buf[sizeof(struct nat44_cfg_spool)];
554 sep = strtok(NULL, ",");
555 }
556 }
557
558 return (space);
559}
560
561static int
562setup_redir_proto(char *buf, int *ac, char ***av)
563{
561 sep = strtok(NULL, ",");
562 }
563 }
564
565 return (space);
566}
567
568static int
569setup_redir_proto(char *buf, int *ac, char ***av)
570{
564 struct cfg_redir *r;
571 struct nat44_cfg_redir *r;
565 struct protoent *protoent;
566 size_t space;
567
572 struct protoent *protoent;
573 size_t space;
574
568 r = (struct cfg_redir *)buf;
575 r = (struct nat44_cfg_redir *)buf;
569 r->mode = REDIR_PROTO;
576 r->mode = REDIR_PROTO;
570 /* Skip cfg_redir at beginning of buf. */
571 buf = &buf[sizeof(struct cfg_redir)];
572 space = sizeof(struct cfg_redir);
577 /* Skip nat44_cfg_redir at beginning of buf. */
578 buf = &buf[sizeof(struct nat44_cfg_redir)];
579 space = sizeof(struct nat44_cfg_redir);
573
574 /*
575 * Extract protocol.
576 */
577 protoent = getprotobyname(**av);
578 if (protoent == NULL)
579 errx(EX_DATAERR, "redirect_proto: unknown protocol %s", **av);
580 else

--- 30 unchanged lines hidden (view full) ---

611 }
612 }
613 }
614
615 return (space);
616}
617
618static void
580
581 /*
582 * Extract protocol.
583 */
584 protoent = getprotobyname(**av);
585 if (protoent == NULL)
586 errx(EX_DATAERR, "redirect_proto: unknown protocol %s", **av);
587 else

--- 30 unchanged lines hidden (view full) ---

618 }
619 }
620 }
621
622 return (space);
623}
624
625static void
619print_nat_config(unsigned char *buf)
626nat_show_log(struct nat44_cfg_nat *n, void *arg)
620{
627{
621 struct cfg_nat *n;
628 char *buf;
629
630 buf = (char *)(n + 1);
631 if (buf[0] != '\0')
632 printf("nat %s: %s\n", n->name, buf);
633}
634
635static void
636nat_show_cfg(struct nat44_cfg_nat *n, void *arg)
637{
622 int i, cnt, flag, off;
638 int i, cnt, flag, off;
623 struct cfg_redir *t;
624 struct cfg_spool *s;
639 struct nat44_cfg_redir *t;
640 struct nat44_cfg_spool *s;
641 caddr_t buf;
625 struct protoent *p;
626
642 struct protoent *p;
643
627 n = (struct cfg_nat *)buf;
644 buf = (caddr_t)n;
628 flag = 1;
645 flag = 1;
629 off = sizeof(*n);
630 printf("ipfw nat %u config", n->id);
646 off = sizeof(*n);
647 printf("ipfw nat %s config", n->name);
631 if (strlen(n->if_name) != 0)
632 printf(" if %s", n->if_name);
633 else if (n->ip.s_addr != 0)
634 printf(" ip %s", inet_ntoa(n->ip));
635 while (n->mode != 0) {
636 if (n->mode & PKT_ALIAS_LOG) {
637 printf(" log");
638 n->mode &= ~PKT_ALIAS_LOG;

--- 17 unchanged lines hidden (view full) ---

656 n->mode &= ~PKT_ALIAS_REVERSE;
657 } else if (n->mode & PKT_ALIAS_PROXY_ONLY) {
658 printf(" proxy_only");
659 n->mode &= ~PKT_ALIAS_PROXY_ONLY;
660 }
661 }
662 /* Print all the redirect's data configuration. */
663 for (cnt = 0; cnt < n->redir_cnt; cnt++) {
648 if (strlen(n->if_name) != 0)
649 printf(" if %s", n->if_name);
650 else if (n->ip.s_addr != 0)
651 printf(" ip %s", inet_ntoa(n->ip));
652 while (n->mode != 0) {
653 if (n->mode & PKT_ALIAS_LOG) {
654 printf(" log");
655 n->mode &= ~PKT_ALIAS_LOG;

--- 17 unchanged lines hidden (view full) ---

673 n->mode &= ~PKT_ALIAS_REVERSE;
674 } else if (n->mode & PKT_ALIAS_PROXY_ONLY) {
675 printf(" proxy_only");
676 n->mode &= ~PKT_ALIAS_PROXY_ONLY;
677 }
678 }
679 /* Print all the redirect's data configuration. */
680 for (cnt = 0; cnt < n->redir_cnt; cnt++) {
664 t = (struct cfg_redir *)&buf[off];
665 off += SOF_REDIR;
681 t = (struct nat44_cfg_redir *)&buf[off];
682 off += sizeof(struct nat44_cfg_redir);
666 switch (t->mode) {
667 case REDIR_ADDR:
668 printf(" redirect_addr");
669 if (t->spool_cnt == 0)
670 printf(" %s", inet_ntoa(t->laddr));
671 else
672 for (i = 0; i < t->spool_cnt; i++) {
683 switch (t->mode) {
684 case REDIR_ADDR:
685 printf(" redirect_addr");
686 if (t->spool_cnt == 0)
687 printf(" %s", inet_ntoa(t->laddr));
688 else
689 for (i = 0; i < t->spool_cnt; i++) {
673 s = (struct cfg_spool *)&buf[off];
690 s = (struct nat44_cfg_spool *)&buf[off];
674 if (i)
675 printf(",");
676 else
677 printf(" ");
678 printf("%s", inet_ntoa(s->addr));
691 if (i)
692 printf(",");
693 else
694 printf(" ");
695 printf("%s", inet_ntoa(s->addr));
679 off += SOF_SPOOL;
696 off += sizeof(struct nat44_cfg_spool);
680 }
681 printf(" %s", inet_ntoa(t->paddr));
682 break;
683 case REDIR_PORT:
684 p = getprotobynumber(t->proto);
685 printf(" redirect_port %s ", p->p_name);
686 if (!t->spool_cnt) {
687 printf("%s:%u", inet_ntoa(t->laddr), t->lport);
688 if (t->pport_cnt > 1)
689 printf("-%u", t->lport +
690 t->pport_cnt - 1);
691 } else
692 for (i=0; i < t->spool_cnt; i++) {
697 }
698 printf(" %s", inet_ntoa(t->paddr));
699 break;
700 case REDIR_PORT:
701 p = getprotobynumber(t->proto);
702 printf(" redirect_port %s ", p->p_name);
703 if (!t->spool_cnt) {
704 printf("%s:%u", inet_ntoa(t->laddr), t->lport);
705 if (t->pport_cnt > 1)
706 printf("-%u", t->lport +
707 t->pport_cnt - 1);
708 } else
709 for (i=0; i < t->spool_cnt; i++) {
693 s = (struct cfg_spool *)&buf[off];
710 s = (struct nat44_cfg_spool *)&buf[off];
694 if (i)
695 printf(",");
696 printf("%s:%u", inet_ntoa(s->addr),
697 s->port);
711 if (i)
712 printf(",");
713 printf("%s:%u", inet_ntoa(s->addr),
714 s->port);
698 off += SOF_SPOOL;
715 off += sizeof(struct nat44_cfg_spool);
699 }
700
701 printf(" ");
702 if (t->paddr.s_addr)
703 printf("%s:", inet_ntoa(t->paddr));
704 printf("%u", t->pport);
705 if (!t->spool_cnt && t->pport_cnt > 1)
706 printf("-%u", t->pport + t->pport_cnt - 1);

--- 24 unchanged lines hidden (view full) ---

731 }
732 }
733 printf("\n");
734}
735
736void
737ipfw_config_nat(int ac, char **av)
738{
716 }
717
718 printf(" ");
719 if (t->paddr.s_addr)
720 printf("%s:", inet_ntoa(t->paddr));
721 printf("%u", t->pport);
722 if (!t->spool_cnt && t->pport_cnt > 1)
723 printf("-%u", t->pport + t->pport_cnt - 1);

--- 24 unchanged lines hidden (view full) ---

748 }
749 }
750 printf("\n");
751}
752
753void
754ipfw_config_nat(int ac, char **av)
755{
739 struct cfg_nat *n; /* Nat instance configuration. */
756 ipfw_obj_header *oh;
757 struct nat44_cfg_nat *n; /* Nat instance configuration. */
740 int i, off, tok, ac1;
741 char *id, *buf, **av1, *end;
742 size_t len;
743
744 av++;
745 ac--;
746 /* Nat id. */
747 if (ac == 0)
748 errx(EX_DATAERR, "missing nat id");
749 id = *av;
750 i = (int)strtol(id, &end, 0);
751 if (i <= 0 || *end != '\0')
752 errx(EX_DATAERR, "illegal nat id: %s", id);
753 av++;
754 ac--;
755 if (ac == 0)
756 errx(EX_DATAERR, "missing option");
757
758 int i, off, tok, ac1;
759 char *id, *buf, **av1, *end;
760 size_t len;
761
762 av++;
763 ac--;
764 /* Nat id. */
765 if (ac == 0)
766 errx(EX_DATAERR, "missing nat id");
767 id = *av;
768 i = (int)strtol(id, &end, 0);
769 if (i <= 0 || *end != '\0')
770 errx(EX_DATAERR, "illegal nat id: %s", id);
771 av++;
772 ac--;
773 if (ac == 0)
774 errx(EX_DATAERR, "missing option");
775
758 len = sizeof(struct cfg_nat);
776 len = sizeof(*oh) + sizeof(*n);
759 ac1 = ac;
760 av1 = av;
761 while (ac1 > 0) {
762 tok = match_token(nat_params, *av1);
763 ac1--;
764 av1++;
765 switch (tok) {
766 case TOK_IP:

--- 32 unchanged lines hidden (view full) ---

799 av1++;
800 ac1--;
801 }
802 break;
803 case TOK_REDIR_PROTO:
804 if (ac1 < 2)
805 errx(EX_DATAERR, "redirect_proto: "
806 "not enough arguments");
777 ac1 = ac;
778 av1 = av;
779 while (ac1 > 0) {
780 tok = match_token(nat_params, *av1);
781 ac1--;
782 av1++;
783 switch (tok) {
784 case TOK_IP:

--- 32 unchanged lines hidden (view full) ---

817 av1++;
818 ac1--;
819 }
820 break;
821 case TOK_REDIR_PROTO:
822 if (ac1 < 2)
823 errx(EX_DATAERR, "redirect_proto: "
824 "not enough arguments");
807 len += sizeof(struct cfg_redir);
825 len += sizeof(struct nat44_cfg_redir);
808 av1 += 2;
809 ac1 -= 2;
810 /* Skip optional remoteIP/port */
811 if (ac1 != 0 && isdigit(**av1)) {
812 av1++;
813 ac1--;
814 }
815 if (ac1 != 0 && isdigit(**av1)) {

--- 4 unchanged lines hidden (view full) ---

820 default:
821 errx(EX_DATAERR, "unrecognised option ``%s''", av1[-1]);
822 }
823 }
824
825 if ((buf = malloc(len)) == NULL)
826 errx(EX_OSERR, "malloc failed");
827
826 av1 += 2;
827 ac1 -= 2;
828 /* Skip optional remoteIP/port */
829 if (ac1 != 0 && isdigit(**av1)) {
830 av1++;
831 ac1--;
832 }
833 if (ac1 != 0 && isdigit(**av1)) {

--- 4 unchanged lines hidden (view full) ---

838 default:
839 errx(EX_DATAERR, "unrecognised option ``%s''", av1[-1]);
840 }
841 }
842
843 if ((buf = malloc(len)) == NULL)
844 errx(EX_OSERR, "malloc failed");
845
828 /* Offset in buf: save space for n at the beginning. */
829 off = sizeof(*n);
846 /* Offset in buf: save space for header at the beginning. */
847 off = sizeof(*oh) + sizeof(*n);
830 memset(buf, 0, len);
848 memset(buf, 0, len);
831 n = (struct cfg_nat *)buf;
832 n->id = i;
849 oh = (ipfw_obj_header *)buf;
850 n = (struct nat44_cfg_nat *)(oh + 1);
851 oh->ntlv.head.length = sizeof(oh->ntlv);
852 snprintf(oh->ntlv.name, sizeof(oh->ntlv.name), "%d", i);
853 snprintf(n->name, sizeof(n->name), "%d", i);
833
834 while (ac > 0) {
835 tok = match_token(nat_params, *av);
836 ac--;
837 av++;
838 switch (tok) {
839 case TOK_IP:
840 if (ac == 0)

--- 54 unchanged lines hidden (view full) ---

895 break;
896 }
897 n->redir_cnt++;
898 off += i;
899 break;
900 }
901 }
902
854
855 while (ac > 0) {
856 tok = match_token(nat_params, *av);
857 ac--;
858 av++;
859 switch (tok) {
860 case TOK_IP:
861 if (ac == 0)

--- 54 unchanged lines hidden (view full) ---

916 break;
917 }
918 n->redir_cnt++;
919 off += i;
920 break;
921 }
922 }
923
903 i = do_cmd(IP_FW_NAT_CFG, buf, off);
904 if (i)
905 err(1, "setsockopt(%s)", "IP_FW_NAT_CFG");
924 i = do_set3(IP_FW_NAT44_XCONFIG, &oh->opheader, len);
925 if (i != 0)
926 err(1, "setsockopt(%s)", "IP_FW_NAT44_XCONFIG");
906
907 if (!co.do_quiet) {
908 /* After every modification, we show the resultant rule. */
909 int _ac = 3;
910 const char *_av[] = {"show", "config", id};
911 ipfw_show_nat(_ac, (char **)(void *)_av);
912 }
913}
914
927
928 if (!co.do_quiet) {
929 /* After every modification, we show the resultant rule. */
930 int _ac = 3;
931 const char *_av[] = {"show", "config", id};
932 ipfw_show_nat(_ac, (char **)(void *)_av);
933 }
934}
935
936struct nat_list_arg {
937 uint16_t cmd;
938 int is_all;
939};
915
940
941static int
942nat_show_data(struct nat44_cfg_nat *cfg, void *arg)
943{
944 struct nat_list_arg *nla;
945 ipfw_obj_header *oh;
946
947 nla = (struct nat_list_arg *)arg;
948
949 switch (nla->cmd) {
950 case IP_FW_NAT44_XGETCONFIG:
951 if (nat_get_cmd(cfg->name, nla->cmd, &oh) != 0) {
952 warnx("Error getting nat instance %s info", cfg->name);
953 break;
954 }
955 nat_show_cfg((struct nat44_cfg_nat *)(oh + 1), NULL);
956 free(oh);
957 break;
958 case IP_FW_NAT44_XGETLOG:
959 if (nat_get_cmd(cfg->name, nla->cmd, &oh) == 0) {
960 nat_show_log((struct nat44_cfg_nat *)(oh + 1), NULL);
961 free(oh);
962 break;
963 }
964 /* Handle error */
965 if (nla->is_all != 0 && errno == ENOENT)
966 break;
967 warn("Error getting nat instance %s info", cfg->name);
968 break;
969 }
970
971 return (0);
972}
973
974/*
975 * Compare nat names.
976 * Honor number comparison.
977 */
978static int
979natname_cmp(const void *a, const void *b)
980{
981 struct nat44_cfg_nat *ia, *ib;
982
983 ia = (struct nat44_cfg_nat *)a;
984 ib = (struct nat44_cfg_nat *)b;
985
986 return (stringnum_cmp(ia->name, ib->name));
987}
988
989/*
990 * Retrieves nat list from kernel,
991 * optionally sorts it and calls requested function for each table.
992 * Returns 0 on success.
993 */
994static int
995nat_foreach(nat_cb_t *f, void *arg, int sort)
996{
997 ipfw_obj_lheader *olh;
998 struct nat44_cfg_nat *cfg;
999 size_t sz;
1000 int i, error;
1001
1002 /* Start with reasonable default */
1003 sz = sizeof(*olh) + 16 * sizeof(struct nat44_cfg_nat);
1004
1005 for (;;) {
1006 if ((olh = calloc(1, sz)) == NULL)
1007 return (ENOMEM);
1008
1009 olh->size = sz;
1010 if (do_get3(IP_FW_NAT44_LIST_NAT, &olh->opheader, &sz) != 0) {
1011 free(olh);
1012 if (errno == ENOMEM) {
1013 sz = olh->size;
1014 continue;
1015 }
1016 return (errno);
1017 }
1018
1019 if (sort != 0)
1020 qsort(olh + 1, olh->count, olh->objsize, natname_cmp);
1021
1022 cfg = (struct nat44_cfg_nat*)(olh + 1);
1023 for (i = 0; i < olh->count; i++) {
1024 error = f(cfg, arg); /* Ignore errors for now */
1025 cfg = (struct nat44_cfg_nat *)((caddr_t)cfg +
1026 olh->objsize);
1027 }
1028
1029 free(olh);
1030 break;
1031 }
1032
1033 return (0);
1034}
1035
1036static int
1037nat_get_cmd(char *name, uint16_t cmd, ipfw_obj_header **ooh)
1038{
1039 ipfw_obj_header *oh;
1040 struct nat44_cfg_nat *cfg;
1041 size_t sz;
1042
1043 /* Start with reasonable default */
1044 sz = sizeof(*oh) + sizeof(*cfg) + 128;
1045
1046 for (;;) {
1047 if ((oh = calloc(1, sz)) == NULL)
1048 return (ENOMEM);
1049 cfg = (struct nat44_cfg_nat *)(oh + 1);
1050 oh->ntlv.head.length = sizeof(oh->ntlv);
1051 strlcpy(oh->ntlv.name, name, sizeof(oh->ntlv.name));
1052 strlcpy(cfg->name, name, sizeof(cfg->name));
1053
1054 if (do_get3(cmd, &oh->opheader, &sz) != 0) {
1055 sz = cfg->size;
1056 free(oh);
1057 if (errno == ENOMEM)
1058 continue;
1059 return (errno);
1060 }
1061
1062 *ooh = oh;
1063 break;
1064 }
1065
1066 return (0);
1067}
1068
916void
917ipfw_show_nat(int ac, char **av)
918{
1069void
1070ipfw_show_nat(int ac, char **av)
1071{
919 struct cfg_nat *n;
920 struct cfg_redir *e;
921 int cmd, i, nbytes, do_cfg, do_rule, frule, lrule, nalloc, size;
922 int nat_cnt, redir_cnt, r;
923 uint8_t *data, *p;
924 char *endptr;
1072 ipfw_obj_header *oh;
1073 char *name;
1074 int cmd;
1075 struct nat_list_arg nla;
925
1076
926 do_rule = 0;
927 nalloc = 1024;
928 size = 0;
929 data = NULL;
930 frule = 0;
931 lrule = IPFW_DEFAULT_RULE; /* max ipfw rule number */
932 ac--;
933 av++;
934
935 if (co.test_only)
936 return;
937
938 /* Parse parameters. */
1077 ac--;
1078 av++;
1079
1080 if (co.test_only)
1081 return;
1082
1083 /* Parse parameters. */
939 for (cmd = IP_FW_NAT_GET_LOG, do_cfg = 0; ac != 0; ac--, av++) {
1084 cmd = 0; /* XXX: Change to IP_FW_NAT44_XGETLOG @ MFC */
1085 name = NULL;
1086 for ( ; ac != 0; ac--, av++) {
940 if (!strncmp(av[0], "config", strlen(av[0]))) {
1087 if (!strncmp(av[0], "config", strlen(av[0]))) {
941 cmd = IP_FW_NAT_GET_CONFIG, do_cfg = 1;
1088 cmd = IP_FW_NAT44_XGETCONFIG;
942 continue;
943 }
1089 continue;
1090 }
944 /* Convert command line rule #. */
945 frule = lrule = strtoul(av[0], &endptr, 10);
946 if (*endptr == '-')
947 lrule = strtoul(endptr+1, &endptr, 10);
948 if (lrule == 0)
949 err(EX_USAGE, "invalid rule number: %s", av[0]);
950 do_rule = 1;
1091 if (strcmp(av[0], "log") == 0) {
1092 cmd = IP_FW_NAT44_XGETLOG;
1093 continue;
1094 }
1095 if (name != NULL)
1096 err(EX_USAGE,"only one instance name may be specified");
1097 name = av[0];
951 }
952
1098 }
1099
953 nbytes = nalloc;
954 while (nbytes >= nalloc) {
955 nalloc = nalloc * 2;
956 nbytes = nalloc;
957 data = safe_realloc(data, nbytes);
958 if (do_cmd(cmd, data, (uintptr_t)&nbytes) < 0)
959 err(EX_OSERR, "getsockopt(IP_FW_GET_%s)",
960 (cmd == IP_FW_NAT_GET_LOG) ? "LOG" : "CONFIG");
961 }
962 if (nbytes == 0)
963 exit(0);
964 if (do_cfg) {
965 nat_cnt = *((int *)data);
966 for (i = sizeof(nat_cnt); nat_cnt; nat_cnt--) {
967 n = (struct cfg_nat *)&data[i];
968 if (frule <= n->id && lrule >= n->id)
969 print_nat_config(&data[i]);
970 i += sizeof(struct cfg_nat);
971 for (redir_cnt = 0; redir_cnt < n->redir_cnt; redir_cnt++) {
972 e = (struct cfg_redir *)&data[i];
973 i += sizeof(struct cfg_redir) + e->spool_cnt *
974 sizeof(struct cfg_spool);
975 }
976 }
1100 if (cmd == 0)
1101 errx(EX_USAGE, "Please specify action. Available: config,log");
1102
1103 if (name == NULL) {
1104 memset(&nla, 0, sizeof(nla));
1105 nla.cmd = cmd;
1106 nla.is_all = 1;
1107 nat_foreach(nat_show_data, &nla, 1);
977 } else {
1108 } else {
978 for (i = 0; 1; i += LIBALIAS_BUF_SIZE + sizeof(int)) {
979 p = &data[i];
980 if (p == data + nbytes)
981 break;
982 bcopy(p, &r, sizeof(int));
983 if (do_rule) {
984 if (!(frule <= r && lrule >= r))
985 continue;
986 }
987 printf("nat %u: %s\n", r, p+sizeof(int));
988 }
1109 if (nat_get_cmd(name, cmd, &oh) != 0)
1110 err(EX_OSERR, "Error getting nat %s instance info", name);
1111 nat_show_cfg((struct nat44_cfg_nat *)(oh + 1), NULL);
1112 free(oh);
989 }
990}
1113 }
1114}
1115