Page MenuHomeFreeBSD

D29468.1792374813.diff
No OneTemporary

Size
7 KB
Referenced Files
None
Subscribers
None

D29468.1792374813.diff

diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -306,6 +306,7 @@
int type;
int staticport;
struct pf_poolhashkey *key;
+ struct pf_mape_portset mape;
} pool_opts;
@@ -461,7 +462,7 @@
%token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY FAILPOLICY
%token RANDOMID REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
%token ANTISPOOF FOR INCLUDE
-%token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY
+%token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY MAPEPORTSET
%token ALTQ CBQ CODEL PRIQ HFSC FAIRQ BANDWIDTH TBRSIZE LINKSHARE REALTIME
%token UPPERLIMIT QUEUE PRIORITY QLIMIT HOGS BUCKETS RTABLE TARGET INTERVAL
%token LOAD RULESET_OPTIMIZATION PRIO
@@ -4007,6 +4008,36 @@
pool_opts.marker |= POM_STICKYADDRESS;
pool_opts.opts |= PF_POOL_STICKYADDR;
}
+ | MAPEPORTSET number '/' number '/' number {
+ if (pool_opts.mape.offset) {
+ yyerror("map-e-portset cannot be redefined");
+ YYERROR;
+ }
+ if (pool_opts.type) {
+ yyerror("map-e-portset cannot be used with "
+ "address pools");
+ YYERROR;
+ }
+ if ($2 < 0 || $2 >= 16) {
+ yyerror("MAP-E PSID offset must be 1-15");
+ YYERROR;
+ }
+ if ($4 < 0 || $4 >= 16 || $2 + $4 > 16) {
+ yyerror("Invalid MAP-E PSID length");
+ YYERROR;
+ } else if ($4 == 0) {
+ yyerror("PSID Length = 0: this means"
+ " you do not need MAP-E");
+ YYERROR;
+ }
+ if ($6 < 0 || $6 > 65535) {
+ yyerror("Invalid MAP-E PSID");
+ YYERROR;
+ }
+ pool_opts.mape.offset = $2;
+ pool_opts.mape.psidlen = $4;
+ pool_opts.mape.psid = $6;
+ }
;
redirection : /* empty */ { $$ = NULL; }
@@ -4212,6 +4243,29 @@
r.rpool.proxy_port[1] = 0;
}
+ if ($10.mape.offset) {
+ if (r.action != PF_NAT) {
+ yyerror("the 'map-e-portset' option is"
+ " only valid with nat rules");
+ YYERROR;
+ }
+ if ($10.staticport) {
+ yyerror("the 'map-e-portset' option"
+ " can't be used 'static-port'");
+ YYERROR;
+ }
+ if (r.rpool.proxy_port[0] !=
+ PF_NAT_PROXY_PORT_LOW &&
+ r.rpool.proxy_port[1] !=
+ PF_NAT_PROXY_PORT_HIGH) {
+ yyerror("the 'map-e-portset' option"
+ " can't be used when specifying"
+ " a port range");
+ YYERROR;
+ }
+ r.rpool.mape = $10.mape;
+ }
+
expand_rule(&r, $2, $9 == NULL ? NULL : $9->host, $4,
$5.src_os, $5.src.host, $5.src.port, $5.dst.host,
$5.dst.port, 0, 0, 0, "");
@@ -5537,6 +5591,7 @@
{ "load", LOAD},
{ "log", LOG},
{ "loginterface", LOGINTERFACE},
+ { "map-e-portset", MAPEPORTSET},
{ "max", MAXIMUM},
{ "max-mss", MAXMSS},
{ "max-src-conn", MAXSRCCONN},
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -486,6 +486,9 @@
printf(" sticky-address");
if (id == PF_NAT && p1 == 0 && p2 == 0)
printf(" static-port");
+ if (pool->mape.offset > 0)
+ printf(" map-e-portset %u/%u/%u",
+ pool->mape.offset, pool->mape.psidlen, pool->mape.psid);
}
const char * const pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
diff --git a/share/man/man5/pf.conf.5 b/share/man/man5/pf.conf.5
--- a/share/man/man5/pf.conf.5
+++ b/share/man/man5/pf.conf.5
@@ -1997,6 +1997,26 @@
option prevents
.Xr pf 4
from modifying the source port on TCP and UDP packets.
+.It Xo Ar map-e-portset Aq Ar psid-offset
+.No / Aq Ar psid-len
+.No / Aq Ar psid
+.Xc
+With
+.Ar nat
+rules, the
+.Ar map-e-portset
+option enables the MAP-E (RFC 7597) source port translation.
+Setting up tunneling interface and pass rules for encapsulated packets
+are required in addition to the MAP-E nat rule.
+.Pp
+For example:
+.Bd -literal -offset indent
+nat on $gif_mape_if from $int_if:network to any \e
+ -> $ipv4_mape_src map-e-portset 6/8/0x34
+.Ed
+.Pp
+sets PSID offset 6, PSID length 8, PSID 0x34.
+.Ed
.El
.Pp
Additionally, the
@@ -2892,7 +2912,8 @@
[ "on" ifspec ] [ af ]
[ protospec ] hosts [ "tag" string ] [ "tagged" string ]
[ "-\*(Gt" ( redirhost | "{" redirhost-list "}" )
- [ portspec ] [ pooltype ] [ "static-port" ] ]
+ [ portspec ] [ pooltype ] [ "static-port" ]
+ [ "map-e-portset" number "/" number "/" number ] ]
binat-rule = [ "no" ] "binat" [ "pass" [ "log" [ "(" logopts ")" ] ] ]
[ "on" interface-name ] [ af ]
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -308,6 +308,7 @@
struct pf_kpooladdr *cur;
struct pf_poolhashkey key;
struct pf_addr counter;
+ struct pf_mape_portset mape;
int tblidx;
u_int16_t proxy_port[2];
u_int8_t opts;
diff --git a/sys/netpfil/pf/pf.h b/sys/netpfil/pf/pf.h
--- a/sys/netpfil/pf/pf.h
+++ b/sys/netpfil/pf/pf.h
@@ -311,11 +311,18 @@
#define key32 pfk.key32
};
+struct pf_mape_portset {
+ u_int8_t offset;
+ u_int8_t psidlen;
+ u_int16_t psid;
+};
+
struct pf_pool {
struct pf_palist list;
struct pf_pooladdr *cur;
struct pf_poolhashkey key;
struct pf_addr counter;
+ struct pf_mape_portset mape;
int tblidx;
u_int16_t proxy_port[2];
u_int8_t opts;
diff --git a/sys/netpfil/pf/pf_lb.c b/sys/netpfil/pf/pf_lb.c
--- a/sys/netpfil/pf/pf_lb.c
+++ b/sys/netpfil/pf/pf_lb.c
@@ -224,11 +224,6 @@
if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
return (1);
- if (proto == IPPROTO_ICMP) {
- low = 1;
- high = 65535;
- }
-
bzero(&key, sizeof(key));
key.af = af;
key.proto = proto;
@@ -306,6 +301,42 @@
return (1); /* none available */
}
+static int
+pf_get_mape_sport(sa_family_t af, u_int8_t proto, struct pf_krule *r,
+ struct pf_addr *saddr, uint16_t sport, struct pf_addr *daddr,
+ uint16_t dport, struct pf_addr *naddr, uint16_t *nport,
+ struct pf_ksrc_node **sn)
+{
+ uint16_t psmask, low, highmask;
+ uint16_t i, ahigh, cut;
+ int ashift, psidshift;
+
+ ashift = 16 - r->rpool.mape.offset;
+ psidshift = ashift - r->rpool.mape.psidlen;
+ psmask = r->rpool.mape.psid & ((1U << r->rpool.mape.psidlen) - 1);
+ psmask = psmask << psidshift;
+ highmask = (1U << psidshift) - 1;
+
+ ahigh = (1U << r->rpool.mape.offset) - 1;
+ cut = arc4random() & ahigh;
+ if (cut == 0)
+ cut = 1;
+
+ for (i = cut; i < ahigh; i++) {
+ low = (i << ashift) | psmask;
+ if (!pf_get_sport(af, proto, r, saddr, sport, daddr, dport,
+ naddr, nport, low, low | highmask, sn))
+ return (0);
+ }
+ for (i = cut - 1; i > 0; i--) {
+ low = (i << ashift) | psmask;
+ if (!pf_get_sport(af, proto, r, saddr, sport, daddr, dport,
+ naddr, nport, low, low | highmask, sn))
+ return (0);
+ }
+ return (1);
+}
+
int
pf_map_addr(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr,
struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_ksrc_node **sn)
@@ -526,6 +557,7 @@
struct pf_krule *r = NULL;
struct pf_addr *naddr;
uint16_t *nport;
+ uint16_t low, high;
PF_RULES_RASSERT();
KASSERT(*skp == NULL, ("*skp not NULL"));
@@ -573,9 +605,26 @@
switch (r->action) {
case PF_NAT:
- if (pf_get_sport(pd->af, pd->proto, r, saddr, sport, daddr,
- dport, naddr, nport, r->rpool.proxy_port[0],
- r->rpool.proxy_port[1], sn)) {
+ if (pd->proto == IPPROTO_ICMP) {
+ low = 1;
+ high = 65535;
+ } else {
+ low = r->rpool.proxy_port[0];
+ high = r->rpool.proxy_port[1];
+ }
+ if (r->rpool.mape.offset > 0) {
+ if (pf_get_mape_sport(pd->af, pd->proto, r, saddr,
+ sport, daddr, dport, naddr, nport, sn)) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: MAP-E port allocation (%u/%u/%u)"
+ " failed\n",
+ r->rpool.mape.offset,
+ r->rpool.mape.psidlen,
+ r->rpool.mape.psid));
+ goto notrans;
+ }
+ } else if (pf_get_sport(pd->af, pd->proto, r, saddr, sport,
+ daddr, dport, naddr, nport, low, high, sn)) {
DPFPRINTF(PF_DEBUG_MISC,
("pf: NAT proxy port allocation (%u-%u) failed\n",
r->rpool.proxy_port[0], r->rpool.proxy_port[1]));

File Metadata

Mime Type
text/plain
Expires
Mon, Oct 19, 1:53 AM (8 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30504859
Default Alt Text
D29468.1792374813.diff (7 KB)

Event Timeline