The branch stable/12 has been updated by nc (ports committer):

URL: 
https://cgit.FreeBSD.org/src/commit/?id=ab65c43e2620722bc3232590f74d2e015d8b6e25

commit ab65c43e2620722bc3232590f74d2e015d8b6e25
Author:     Neel Chauhan <n...@freebsd.org>
AuthorDate: 2021-02-02 21:24:17 +0000
Commit:     Neel Chauhan <n...@freebsd.org>
CommitDate: 2021-02-17 18:19:02 +0000

    Allow setting alias port ranges in libalias and ipfw.
    
    This will allow a system to be a true RFC 6598 NAT444 setup, where each
    network segment (e.g. user, subnet) can have their own dedicated port
    aliasing ranges.
    
    Reviewed by:            donner, kp
    Approved by:            0mp (mentor), donner, kp
    Differential Revision:  https://reviews.freebsd.org/D23450
    
    (cherry picked from commit a08cdb6cfb1c84b80b5337d46c574b55d0e15c63)
---
 sbin/ipfw/ipfw.8                   |  3 +++
 sbin/ipfw/ipfw2.h                  |  1 +
 sbin/ipfw/main.c                   |  3 ++-
 sbin/ipfw/nat.c                    | 41 ++++++++++++++++++++++++++++++++++++++
 sys/netinet/ip_fw.h                |  2 ++
 sys/netinet/libalias/alias.h       |  1 +
 sys/netinet/libalias/alias_db.c    | 29 ++++++++++++++++++++++++---
 sys/netinet/libalias/alias_local.h |  4 ++++
 sys/netpfil/ipfw/ip_fw_nat.c       |  7 +++++++
 9 files changed, 87 insertions(+), 4 deletions(-)

diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8
index e77930355094..d2c4885bc119 100644
--- a/sbin/ipfw/ipfw.8
+++ b/sbin/ipfw/ipfw.8
@@ -3271,6 +3271,9 @@ Reverse the way libalias handles aliasing.
 Obey transparent proxy rules only, packet aliasing is not performed.
 .It Cm skip_global
 Skip instance in case of global state lookup (see below).
+.It Cm port_range Ar lower-upper
+Set the aliasing ports between the ranges given. Upper port has to be greater
+than lower.
 .El
 .Pp
 Some specials value can be supplied instead of
diff --git a/sbin/ipfw/ipfw2.h b/sbin/ipfw/ipfw2.h
index 764e5176e8ef..42e4f4777792 100644
--- a/sbin/ipfw/ipfw2.h
+++ b/sbin/ipfw/ipfw2.h
@@ -285,6 +285,7 @@ enum tokens {
        TOK_STATES_CHUNKS,
        TOK_JMAXLEN,
        TOK_PORT_RANGE,
+       TOK_PORT_ALIAS,
        TOK_HOST_DEL_AGE,
        TOK_PG_DEL_AGE,
        TOK_TCP_SYN_AGE,
diff --git a/sbin/ipfw/main.c b/sbin/ipfw/main.c
index dc55d0bfa416..89f21062811c 100644
--- a/sbin/ipfw/main.c
+++ b/sbin/ipfw/main.c
@@ -45,7 +45,8 @@ help(void)
 "[pipe|queue] {zero|delete|show} [N{,N}]\n"
 "nat N config {ip IPADDR|if 
IFNAME|log|deny_in|same_ports|unreg_only|unreg_cgn|\n"
 "              reset|reverse|proxy_only|redirect_addr linkspec|\n"
-"              redirect_port linkspec|redirect_proto linkspec}\n"
+"              redirect_port linkspec|redirect_proto linkspec|\n"
+"              port_range lower-upper}\n"
 "set [disable N... enable N...] | move [rule] X to Y | swap X Y | show\n"
 "set N {show|list|zero|resetlog|delete} [N{,N}] | flush\n"
 "table N {add ip[/bits] [value] | delete ip[/bits] | flush | list}\n"
diff --git a/sbin/ipfw/nat.c b/sbin/ipfw/nat.c
index bbf5be666ea0..1076e1038b8a 100644
--- a/sbin/ipfw/nat.c
+++ b/sbin/ipfw/nat.c
@@ -65,6 +65,7 @@ static struct _s_x nat_params[] = {
        { "reset",              TOK_RESET_ADDR },
        { "reverse",            TOK_ALIAS_REV },
        { "proxy_only",         TOK_PROXY_ONLY },
+       { "port_range",         TOK_PORT_ALIAS },
        { "redirect_addr",      TOK_REDIR_ADDR },
        { "redirect_port",      TOK_REDIR_PORT },
        { "redirect_proto",     TOK_REDIR_PROTO },
@@ -753,12 +754,35 @@ nat_show_cfg(struct nat44_cfg_nat *n, void *arg __unused)
        printf("\n");
 }
 
+static int
+nat_port_alias_parse(char *str, u_short *lpout, u_short *hpout) {
+       long lp, hp;
+       char *ptr;
+       /* Lower port parsing */
+       lp = (long) strtol(str, &ptr, 10);
+       if (lp < 1024 || lp > 65535)
+               return 0;
+       if (!ptr || *ptr != '-')
+               return 0;
+       /* Upper port parsing */
+       hp = (long) strtol(ptr, &ptr, 10);
+       if (hp < 1024 || hp > 65535)
+               return 0;
+       if (ptr)
+               return 0;
+
+       *lpout = (u_short) lp;
+       *hpout = (u_short) hp;
+       return 1;
+}
+
 void
 ipfw_config_nat(int ac, char **av)
 {
        ipfw_obj_header *oh;
        struct nat44_cfg_nat *n;                /* Nat instance configuration. 
*/
        int i, off, tok, ac1;
+       u_short lp, hp;
        char *id, *buf, **av1, *end;
        size_t len;
 
@@ -786,6 +810,7 @@ ipfw_config_nat(int ac, char **av)
                switch (tok) {
                case TOK_IP:
                case TOK_IF:
+               case TOK_PORT_ALIAS:
                        ac1--;
                        av1++;
                        break;
@@ -925,8 +950,24 @@ ipfw_config_nat(int ac, char **av)
                        n->redir_cnt++;
                        off += i;
                        break;
+               case TOK_PORT_ALIAS:
+                       if (ac == 0)
+                               errx(EX_DATAERR, "missing option");
+                       if (!nat_port_alias_parse(av[0], &lp, &hp))
+                               errx(EX_DATAERR,
+                                   "You need a range of port(s) from 1024 <= x 
< 65536");
+                       if (lp >= hp)
+                               errx(EX_DATAERR,
+                                   "Upper port has to be greater than lower 
port");
+                       n->alias_port_lo = lp;
+                       n->alias_port_hi = hp;
+                       ac--;
+                       av++;
+                       break;
                }
        }
+       if (n->mode & PKT_ALIAS_SAME_PORTS && n->alias_port_lo)
+               errx(EX_DATAERR, "same_ports and port_range cannot both be 
selected");
 
        i = do_set3(IP_FW_NAT44_XCONFIG, &oh->opheader, len);
        if (i != 0)
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
index 7a01c82ba58b..8b6055e64a6d 100644
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -550,6 +550,8 @@ struct nat44_cfg_nat {
        struct in_addr  ip;             /* nat IPv4 address */
        uint32_t        mode;           /* aliasing mode */
        uint32_t        redir_cnt;      /* number of entry in spool chain */
+       u_short         alias_port_lo;  /* low range for port aliasing */
+       u_short         alias_port_hi;  /* high range for port aliasing */
 };
 
 /* Nat command. */
diff --git a/sys/netinet/libalias/alias.h b/sys/netinet/libalias/alias.h
index 41cd7b2c23d1..c252c823ced8 100644
--- a/sys/netinet/libalias/alias.h
+++ b/sys/netinet/libalias/alias.h
@@ -86,6 +86,7 @@ struct alias_link;
 /* Initialization and control functions. */
 struct libalias *LibAliasInit(struct libalias *);
 void           LibAliasSetAddress(struct libalias *, struct in_addr _addr);
+void           LibAliasSetAliasPortRange(struct libalias *la, u_short 
port_low, u_short port_hi);
 void           LibAliasSetFWBase(struct libalias *, unsigned int _base, 
unsigned int _num);
 void           LibAliasSetSkinnyPort(struct libalias *, unsigned int _port);
 unsigned int
diff --git a/sys/netinet/libalias/alias_db.c b/sys/netinet/libalias/alias_db.c
index cf85f40161e7..b3792c748c56 100644
--- a/sys/netinet/libalias/alias_db.c
+++ b/sys/netinet/libalias/alias_db.c
@@ -605,6 +605,11 @@ GetNewPort(struct libalias *la, struct alias_link *lnk, 
int alias_port_param)
                         */
                        port_net = lnk->src_port;
                        port_sys = ntohs(port_net);
+               } else if (la->aliasPortLower) {
+                       /* First trial is a random port in the aliasing range. 
*/
+                       port_sys = la->aliasPortLower +
+                           (arc4random() % la->aliasPortLength);
+                       port_net = htons(port_sys);
                } else {
                        /* First trial and all subsequent are random. */
                        port_sys = arc4random() & ALIAS_PORT_MASK;
@@ -658,9 +663,15 @@ GetNewPort(struct libalias *la, struct alias_link *lnk, 
int alias_port_param)
                        }
 #endif
                }
-               port_sys = arc4random() & ALIAS_PORT_MASK;
-               port_sys += ALIAS_PORT_BASE;
-               port_net = htons(port_sys);
+               if (la->aliasPortLower) {
+                       port_sys = la->aliasPortLower +
+                           (arc4random() % la->aliasPortLength);
+                       port_net = htons(port_sys);
+               } else {
+                       port_sys = arc4random() & ALIAS_PORT_MASK;
+                       port_sys += ALIAS_PORT_BASE;
+                       port_net = htons(port_sys);
+               }
        }
 
 #ifdef LIBALIAS_DEBUG
@@ -2447,6 +2458,18 @@ LibAliasSetAddress(struct libalias *la, struct in_addr 
addr)
 }
 
 
+void
+LibAliasSetAliasPortRange(struct libalias *la, u_short port_low,
+    u_short port_high)
+{
+
+       LIBALIAS_LOCK(la);
+       la->aliasPortLower = port_low;
+       /* Add 1 to the aliasPortLength as modulo has range of 1 to n-1 */
+       la->aliasPortLength = port_high - port_low + 1;
+       LIBALIAS_UNLOCK(la);
+}
+
 void
 LibAliasSetTarget(struct libalias *la, struct in_addr target_addr)
 {
diff --git a/sys/netinet/libalias/alias_local.h 
b/sys/netinet/libalias/alias_local.h
index c29294256413..94eb26978658 100644
--- a/sys/netinet/libalias/alias_local.h
+++ b/sys/netinet/libalias/alias_local.h
@@ -163,6 +163,10 @@ struct libalias {
        struct in_addr  true_addr;      /* in network byte order. */
        u_short         true_port;      /* in host byte order. */
 
+       /* Port ranges for aliasing. */
+       u_short         aliasPortLower;
+       u_short         aliasPortLength;
+
        /*
         * sctp code support
         */
diff --git a/sys/netpfil/ipfw/ip_fw_nat.c b/sys/netpfil/ipfw/ip_fw_nat.c
index 1c445f72aee9..9e15e9addbe5 100644
--- a/sys/netpfil/ipfw/ip_fw_nat.c
+++ b/sys/netpfil/ipfw/ip_fw_nat.c
@@ -94,6 +94,8 @@ struct cfg_nat {
        /* chain of redir instances */
        LIST_HEAD(redir_chain, cfg_redir) redir_chain;  
        char                    if_name[IF_NAMESIZE];   /* interface name */
+       u_short                 alias_port_lo;  /* low range for port aliasing 
*/
+       u_short                 alias_port_hi;  /* high range for port aliasing 
*/
 };
 
 static eventhandler_tag ifaddr_event_tag;
@@ -527,9 +529,12 @@ nat44_config(struct ip_fw_chain *chain, struct 
nat44_cfg_nat *ucfg)
        ptr->ip = ucfg->ip;
        ptr->redir_cnt = ucfg->redir_cnt;
        ptr->mode = ucfg->mode;
+       ptr->alias_port_lo = ucfg->alias_port_lo;
+       ptr->alias_port_hi = ucfg->alias_port_hi;
        strlcpy(ptr->if_name, ucfg->if_name, sizeof(ptr->if_name));
        LibAliasSetMode(ptr->lib, ptr->mode, ~0);
        LibAliasSetAddress(ptr->lib, ptr->ip);
+       LibAliasSetAliasPortRange(ptr->lib, ptr->alias_port_lo, 
ptr->alias_port_hi);
 
        /*
         * Redir and LSNAT configuration.
@@ -657,6 +662,8 @@ export_nat_cfg(struct cfg_nat *ptr, struct nat44_cfg_nat 
*ucfg)
        ucfg->ip = ptr->ip;
        ucfg->redir_cnt = ptr->redir_cnt;
        ucfg->mode = ptr->mode;
+       ucfg->alias_port_lo = ptr->alias_port_lo;
+       ucfg->alias_port_hi = ptr->alias_port_hi;
        strlcpy(ucfg->if_name, ptr->if_name, sizeof(ucfg->if_name));
 }
 
_______________________________________________
dev-commits-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "dev-commits-src-all-unsubscr...@freebsd.org"

Reply via email to