Hello all.
This patch allows ipsecctl-like flow grouping along with current
behavior. It allows to write many-to-many policies in a more
compact way, see an example:
ikev2 esp \
from { 1.2.3.4, 5.6.7.8 } to { 3.4.5.6, 4.5.6.7} \
from 7.8.9.0 to { 0.1.2.3, 2.3.4.5 } \
...
will create six flows:
1.2.3.4 -> 3.4.5.6
1.2.3.4 -> 4.5.6.7
5.6.7.8 -> 3.4.5.6
5.6.7.8 -> 4.5.6.7
7.8.9.0 -> 0.1.2.3
7.8.9.0 -> 2.3.4.5
Please note that you're still limited by MAX_IMSGSIZE, which is
about 7 flows, depending on arch. This will be addressed in
another patch.
--
Best wishes,
Vadim Zhukov
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?
Index: iked.conf.5
===================================================================
RCS file: /cvs/src/sbin/iked/iked.conf.5,v
retrieving revision 1.13
diff -u -p -r1.13 iked.conf.5
--- iked.conf.5 21 Jan 2011 12:34:11 -0000 1.13
+++ iked.conf.5 19 May 2011 17:18:54 -0000
@@ -318,6 +318,29 @@ For a list of all port name to number ma
.Xr ipsecctl 8 ,
see the file
.Pa /etc/services .
+.Pp
+Traffic selector can contain more than one address for both
+.Ic from
+and
+.Ic to
+clauses, for example:
+.Bd -literal -offset indent
+ikev2 esp \e
+ from { 172.16.0.0/24, 172.16.4.0/24, 172.16.9.0/24 } \e
+ to { 192.168.0.0/20, 10.0.0.0/8 } \e
+ peer 1.2.3.4 local 5.6.7.8
+.Ed
+.Pp
+In this case, six actual selectors will be created, from each
+address in
+.Ic from
+part to each address in
+.Ic to
+part.
+Commas between addresses are optional.
+.Pp
+You can combine multiple addresses and multiple traffic selectors
+features in one statement.
.It Ic local Ar localip Ic peer Ar remote
The
.Ic local
@@ -821,9 +844,13 @@ and any other connection will be matched
.Sq catch all
policy.
.Bd -literal -offset indent
-ikev2 quick esp from 10.10.10.0/24 to 10.20.20.0/24 \e
+ikev2 quick esp \e
+ from { 10.10.10.0/24, 10.11.10.0/24 } \e
+ to 10.20.20.0/24 \e
peer 192.168.1.34
-ikev2 "catch all" esp from 10.0.1.0/24 to 10.0.2.0/24 \e
+ikev2 "catch all" esp \e
+ from 10.0.1.0/24 to 10.0.2.0/24 \e
+ from 10.0.31.0/24 to 10.0.35.0/24 \e
peer any
ikev2 "subnet" esp from 10.0.3.0/24 to 10.0.4.0/24 \e
peer 192.168.1.0/24
Index: parse.y
===================================================================
RCS file: /cvs/src/sbin/iked/parse.y,v
retrieving revision 1.21
diff -u -p -r1.21 parse.y
--- parse.y 18 Apr 2011 08:45:43 -0000 1.21
+++ parse.y 19 May 2011 17:18:54 -0000
@@ -258,6 +258,8 @@ struct ipsec_hosts {
struct ipsec_addr_wrap *dst;
u_int16_t sport;
u_int16_t dport;
+ struct ipsec_hosts *next;
+ struct ipsec_hosts *tail;
};
struct ipsec_filters {
@@ -293,6 +295,8 @@ int get_id_type(char *);
u_int8_t x2i(unsigned char *);
int parsekey(unsigned char *, size_t, struct iked_auth *);
int parsekeyfile(char *, struct iked_auth *);
+struct ipsec_hosts *expand_hosts(struct ipsec_addr_wrap *, u_int16_t,
+ struct ipsec_addr_wrap *, u_int16_t);
struct ipsec_transforms *ipsec_transforms;
struct ipsec_filters *ipsec_filters;
@@ -345,7 +349,7 @@ typedef struct {
%type <v.number> portval af
%type <v.peers> peers
%type <v.anyhost> anyhost
-%type <v.host> host host_spec
+%type <v.host> host host_list host_spec
%type <v.ids> ids
%type <v.id> id
%type <v.transforms> transforms
@@ -490,51 +494,20 @@ hosts_list : hosts { $$ =
$1; }
else if ($1 == NULL)
$$ = $3;
else {
- $1->src->tail->next = $3->src;
- $1->src->tail = $3->src->tail;
- $1->dst->tail->next = $3->dst;
- $1->dst->tail = $3->dst->tail;
$$ = $1;
+ $$->tail->next = $3;
+ $$->tail = $3;
}
}
;
hosts : FROM host port TO host port {
- struct ipsec_addr_wrap *ipa;
- for (ipa = $5; ipa; ipa = ipa->next) {
- if (ipa->srcnat) {
- yyerror("no flow NAT support for"
- " destination network: %s",
- ipa->name);
- YYERROR;
- }
- }
-
- if (($$ = calloc(1, sizeof(*$$))) == NULL)
- err(1, "hosts: calloc");
-
- $$->src = $2;
- $$->sport = $3;
- $$->dst = $5;
- $$->dport = $6;
+ if(($$ = expand_hosts($2, $3, $5, $6)) == NULL)
+ YYERROR;
}
| TO host port FROM host port {
- struct ipsec_addr_wrap *ipa;
- for (ipa = $2; ipa; ipa = ipa->next) {
- if (ipa->srcnat) {
- yyerror("no flow NAT support for"
- " destination network: %s",
- ipa->name);
- YYERROR;
- }
- }
- if (($$ = calloc(1, sizeof(*$$))) == NULL)
- err(1, "hosts: calloc");
-
- $$->src = $5;
- $$->sport = $6;
- $$->dst = $2;
- $$->dport = $3;
+ if (($$ = expand_hosts($5, $6, $2, $3)) == NULL)
+ YYERROR;
}
;
@@ -589,6 +562,20 @@ anyhost : host_spec { $$ =
$1; }
$$ = host_any();
}
+host_list : host { $$ = $1; }
+ | host_list comma host {
+ if ($3 == NULL)
+ $$ = $1;
+ else if ($1 == NULL)
+ $$ = $3;
+ else {
+ $1->tail->next = $3;
+ $1->tail = $3->tail;
+ $$ = $1;
+ }
+ }
+ ;
+
host_spec : STRING {
if (($$ = host($1)) == NULL) {
free($1);
@@ -622,6 +609,7 @@ host : host_spec { $$ =
$1; }
$$ = $1;
$$->srcnat = $3;
}
+ | '{' host_list '}' { $$ = $2; }
| ANY {
$$ = host_any();
}
@@ -2288,11 +2276,12 @@ create_ike(char *name, int af, u_int8_t
struct ipsec_addr_wrap *ikecfg)
{
struct ipsec_addr_wrap *ipa, *ipb;
+ struct ipsec_hosts *iph;
struct iked_policy pol;
struct iked_proposal prop[2];
u_int j;
struct iked_transform ikexforms[64], espxforms[64];
- struct iked_flow flows[64];
+ struct iked_flow flows[64]; /* XXX */
static u_int policy_id = 0;
struct iked_cfg *cfg;
@@ -2485,28 +2474,32 @@ create_ike(char *name, int af, u_int8_t
}
TAILQ_INSERT_TAIL(&pol.pol_proposals, &prop[1], prop_entry);
- if (hosts == NULL || hosts->src == NULL || hosts->dst == NULL)
- fatalx("create_ike: no traffic selectors/flows");
-
- for (j = 0, ipa = hosts->src, ipb = hosts->dst; ipa && ipb;
- ipa = ipa->next, ipb = ipb->next, j++) {
- memcpy(&flows[j].flow_src.addr, &ipa->address,
- sizeof(ipa->address));
- flows[j].flow_src.addr_af = ipa->af;
- flows[j].flow_src.addr_mask = ipa->mask;
- flows[j].flow_src.addr_net = ipa->netaddress;
- flows[j].flow_src.addr_port = hosts->sport;
-
- memcpy(&flows[j].flow_dst.addr, &ipb->address,
- sizeof(ipb->address));
- flows[j].flow_dst.addr_af = ipb->af;
- flows[j].flow_dst.addr_mask = ipb->mask;
- flows[j].flow_dst.addr_net = ipb->netaddress;
- flows[j].flow_dst.addr_port = hosts->dport;
+ for (j = 0, iph = hosts; iph; iph = iph->next) {
+ for (ipa = iph->src, ipb = iph->dst; ipa && ipb;
+ ipa = ipa->next, ipb = ipb->next, j++) {
+ if (j >= nitems(flows))
+ fatalx("create_ike: flow limit reached");
+
+ memcpy(&flows[j].flow_src.addr, &ipa->address,
+ sizeof(ipa->address));
+ flows[j].flow_src.addr_af = ipa->af;
+ flows[j].flow_src.addr_mask = ipa->mask;
+ flows[j].flow_src.addr_net = ipa->netaddress;
+ flows[j].flow_src.addr_port = hosts->sport;
+
+ memcpy(&flows[j].flow_dst.addr, &ipb->address,
+ sizeof(ipb->address));
+ flows[j].flow_dst.addr_af = ipb->af;
+ flows[j].flow_dst.addr_mask = ipb->mask;
+ flows[j].flow_dst.addr_net = ipb->netaddress;
+ flows[j].flow_dst.addr_port = hosts->dport;
- pol.pol_nflows++;
- RB_INSERT(iked_flows, &pol.pol_flows, &flows[j]);
+ pol.pol_nflows++;
+ RB_INSERT(iked_flows, &pol.pol_flows, &flows[j]);
+ }
}
+ if (j == 0)
+ fatalx("create_ike: no traffic selectors/flows");
for (j = 0, ipa = ikecfg; ipa; ipa = ipa->next, j++) {
if (j >= IKED_CFG_MAX)
@@ -2551,4 +2544,43 @@ create_user(const char *user, const char
rules++;
return (0);
+}
+
+struct ipsec_hosts *
+expand_hosts(struct ipsec_addr_wrap *from, u_int16_t fromport,
+ struct ipsec_addr_wrap *to, u_int16_t toport) {
+ struct ipsec_addr_wrap *ipa, *ipb;
+ struct ipsec_hosts *head, *iph;
+
+ for (ipb = to; ipb; ipb = ipb->next) {
+ if (ipb->srcnat) {
+ yyerror("no flow NAT support for"
+ " destination network: %s",
+ ipb->name);
+ return NULL;
+ }
+ }
+
+ for (head = NULL, ipa = from; ipa; ipa = ipa->next) {
+ for (ipb = to; ipb; ipb = ipb->next) {
+ if (ipa->af != ipb->af &&
+ ipa->af != AF_UNSPEC && ipb->af != AF_UNSPEC)
+ continue;
+
+ if ((iph = calloc(1, sizeof(*iph))) == NULL)
+ err(1, "hosts: calloc");
+ iph->src = ipa;
+ iph->sport = fromport;
+ iph->dst = ipb;
+ iph->dport = toport;
+ iph->tail = iph;
+ if (!head)
+ head = iph;
+ else {
+ head->tail->next = iph;
+ head->tail = iph;
+ }
+ }
+ }
+ return head;
}