Index: sbin/ipfw/ipfw.8 =================================================================== --- sbin/ipfw/ipfw.8 +++ sbin/ipfw/ipfw.8 @@ -3233,8 +3233,11 @@ Try to leave the alias port numbers unchanged from the actual local port numbers. .It Cm unreg_only -Traffic on the local network not originating from an +Traffic on the local network not originating from a RFC 1918 unregistered address spaces will be ignored. +.It Cm unreg_cgn +Like unreg_only, but includes the RFC 6598 (Carrier Grade NAT) +address range. .It Cm reset Reset table of the packet aliasing engine on address change. .It Cm reverse Index: sbin/ipfw/ipfw2.h =================================================================== --- sbin/ipfw/ipfw2.h +++ sbin/ipfw/ipfw2.h @@ -220,6 +220,7 @@ TOK_DENY_INC, TOK_SAME_PORTS, TOK_UNREG_ONLY, + TOK_UNREG_CGN, TOK_SKIP_GLOBAL, TOK_RESET_ADDR, TOK_ALIAS_REV, Index: sbin/ipfw/main.c =================================================================== --- sbin/ipfw/main.c +++ sbin/ipfw/main.c @@ -43,8 +43,8 @@ "add [num] [set N] [prob x] RULE-BODY\n" "{pipe|queue} N config PIPE-BODY\n" "[pipe|queue] {zero|delete|show} [N{,N}]\n" -"nat N config {ip IPADDR|if IFNAME|log|deny_in|same_ports|unreg_only|reset|\n" -" reverse|proxy_only|redirect_addr linkspec|\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" "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" Index: sbin/ipfw/nat.c =================================================================== --- sbin/ipfw/nat.c +++ sbin/ipfw/nat.c @@ -60,6 +60,7 @@ { "deny_in", TOK_DENY_INC }, { "same_ports", TOK_SAME_PORTS }, { "unreg_only", TOK_UNREG_ONLY }, + { "unreg_cgn", TOK_UNREG_CGN }, { "skip_global", TOK_SKIP_GLOBAL }, { "reset", TOK_RESET_ADDR }, { "reverse", TOK_ALIAS_REV }, @@ -663,6 +664,9 @@ } else if (n->mode & PKT_ALIAS_UNREGISTERED_ONLY) { printf(" unreg_only"); n->mode &= ~PKT_ALIAS_UNREGISTERED_ONLY; + } else if (n->mode & PKT_ALIAS_UNREGISTERED_CGN) { + printf(" unreg_cgn"); + n->mode &= ~PKT_ALIAS_UNREGISTERED_CGN; } else if (n->mode & PKT_ALIAS_RESET_ON_ADDR_CHANGE) { printf(" reset"); n->mode &= ~PKT_ALIAS_RESET_ON_ADDR_CHANGE; Index: sys/netinet/libalias/alias.h =================================================================== --- sys/netinet/libalias/alias.h +++ sys/netinet/libalias/alias.h @@ -228,6 +228,14 @@ */ #define PKT_ALIAS_SKIP_GLOBAL 0x200 +/* + * Like PKT_ALIAS_UNREGISTERED_ONLY, but includes the RFC 6598 + * (Carrier Grade NAT) address range as follows: + * + * 100.64.0.0 -> 100.127.255.255 + */ +#define PKT_ALIAS_UNREGISTERED_CGN 0x400 + /* Function return codes. */ #define PKT_ALIAS_ERROR -1 #define PKT_ALIAS_OK 1 Index: sys/netinet/libalias/alias.c =================================================================== --- sys/netinet/libalias/alias.c +++ sys/netinet/libalias/alias.c @@ -1413,6 +1413,10 @@ #define UNREG_ADDR_C_LOWER 0xc0a80000 #define UNREG_ADDR_C_UPPER 0xc0a8ffff +/* 100.64.0.0 -> 100.127.255.255 (RFC 6598 - Carrier Grade NAT) */ +#define UNREG_ADDR_CGN_LOWER 0x64400000 +#define UNREG_ADDR_CGN_UPPER 0x647fffff + int LibAliasOut(struct libalias *la, char *ptr, int maxpacketsize) { @@ -1464,7 +1468,8 @@ } addr_save = GetDefaultAliasAddress(la); - if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY) { + if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY || + la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN) { u_long addr; int iclass; @@ -1476,6 +1481,9 @@ iclass = 2; else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER) iclass = 1; + else if (addr >= UNREG_ADDR_CGN_LOWER && addr <= UNREG_ADDR_CGN_UPPER && + la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN) + iclass = 4; if (iclass == 0) { SetDefaultAliasAddress(la, pip->ip_src); Index: sys/netinet/libalias/libalias.3 =================================================================== --- sys/netinet/libalias/libalias.3 +++ sys/netinet/libalias/libalias.3 @@ -212,6 +212,11 @@ registered and unregistered subnets on different interfaces. The registered subnet is fully accessible to the outside world, so traffic from it does not need to be passed through the packet aliasing engine. +.It Dv PKT_ALIAS_UNREGISTERED_CGN +Like PKT_ALIAS_UNREGISTERED_ONLY, but includes the RFC 6598 (Carrier Grade +NAT) subnet as follows: +.Pp +100.64.0.0 -> 100.127.255.255 (RFC 6598 subnet) .It Dv PKT_ALIAS_RESET_ON_ADDR_CHANGE When this mode bit is set and .Fn LibAliasSetAddress Index: sys/netpfil/ipfw/ip_fw_sockopt.c =================================================================== --- sys/netpfil/ipfw/ip_fw_sockopt.c +++ sys/netpfil/ipfw/ip_fw_sockopt.c @@ -760,36 +760,36 @@ else if (V_autoinc_step > 1000) V_autoinc_step = 1000; - /* FIXME: Handle count > 1 */ - ci = rci; - krule = ci->krule; - rulenum = krule->rulenum; + for (ci = rci, i = 0; i < count; ci++, i++) { + krule = ci->krule; + rulenum = krule->rulenum; - /* find the insertion point, we will insert before */ - insert_before = rulenum ? rulenum + 1 : IPFW_DEFAULT_RULE; - i = ipfw_find_rule(chain, insert_before, 0); - /* duplicate first part */ - if (i > 0) - bcopy(chain->map, map, i * sizeof(struct ip_fw *)); - map[i] = krule; - /* duplicate remaining part, we always have the default rule */ - bcopy(chain->map + i, map + i + 1, - sizeof(struct ip_fw *) *(chain->n_rules - i)); - if (rulenum == 0) { - /* Compute rule number and write it back */ - rulenum = i > 0 ? map[i-1]->rulenum : 0; - if (rulenum < IPFW_DEFAULT_RULE - V_autoinc_step) - rulenum += V_autoinc_step; - krule->rulenum = rulenum; - /* Save number to userland rule */ - pnum = (uint16_t *)((caddr_t)ci->urule + ci->urule_numoff); - *pnum = rulenum; - } + /* find the insertion point, we will insert before */ + insert_before = rulenum ? rulenum + 1 : IPFW_DEFAULT_RULE; + i = ipfw_find_rule(chain, insert_before, 0); + /* duplicate first part */ + if (i > 0) + bcopy(chain->map, map, i * sizeof(struct ip_fw *)); + map[i] = krule; + /* duplicate remaining part, we always have the default rule */ + bcopy(chain->map + i, map + i + 1, + sizeof(struct ip_fw *) *(chain->n_rules - i)); + if (rulenum == 0) { + /* Compute rule number and write it back */ + rulenum = i > 0 ? map[i-1]->rulenum : 0; + if (rulenum < IPFW_DEFAULT_RULE - V_autoinc_step) + rulenum += V_autoinc_step; + krule->rulenum = rulenum; + /* Save number to userland rule */ + pnum = (uint16_t *)((caddr_t)ci->urule + ci->urule_numoff); + *pnum = rulenum; + } - krule->id = chain->id + 1; - update_skipto_cache(chain, map); - map = swap_map(chain, map, chain->n_rules + 1); - chain->static_len += RULEUSIZE0(krule); + krule->id = chain->id + 1; + update_skipto_cache(chain, map); + map = swap_map(chain, map, chain->n_rules + 1); + chain->static_len += RULEUSIZE0(krule); + } IPFW_UH_WUNLOCK(chain); if (map) free(map, M_IPFW);