Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F150428317
D29468.1792374813.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D29468.1792374813.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D29468: pf: Implement the NAT source port selection of MAP-E Customer Edge
Attached
Detach File
Event Timeline
Log In to Comment