hi,

On Sun, Nov 19, 2006 at 01:53:14PM +0500, Anton wrote:
> Here, I think that I achieve evenly distributed bandwidth between
> units. Further, I need to slice traffic in each IPSec tunnel between
> primary gateway and each unit. For msrdp unit's traffic - 30% of this
> unit's tunnel bandwidth, 70% for the rest. Is it useful to altq on
> enc0?
> This is in my mind:
> 

altq is not supported on the virtual enc interface, you have to do the
queueing on the related network interface (fxp0 in your example).

> altq on enc0 cbq bandwidth 230Kb {i_unit_1, i_unit_2, ... i_unit_10}
...

> What bandwidth set to "altq on enc0" (I set here 230Kb as _about_ 30% of 
> 700Kb)?
> 
> Or maybe I need to use altq on fxp0 somehow (if I not understand something)?
> 
> Please, explain for me, how pf.conf should be organized.
> 

it is not possible to do explicit queueing of the ipsec traffic on the
gateway at the moment. you can queue the encapsulated ipsec traffic
(ie. esp) and you can filter by src and dst address (the src is not
very helpful if you have roaming users or clients with dynamic ip
addresses). that's it.

there is a solution...

...during k2k6 (the ipsec hackathon), we started working on a way to
add pf tags to specific ipsec traffic to allow a better filtering and
queueing on the real network interfaces. this is work in progress but
testers are very welcome ;), see the attached ipsec.conf(5) diff for
details.

reyk

Index: sbin/ipsecctl/ipsec.conf.5
===================================================================
RCS file: /cvs/src/sbin/ipsecctl/ipsec.conf.5,v
retrieving revision 1.103
diff -u -p -r1.103 ipsec.conf.5
--- sbin/ipsecctl/ipsec.conf.5  1 Nov 2006 03:10:02 -0000       1.103
+++ sbin/ipsecctl/ipsec.conf.5  9 Nov 2006 16:10:11 -0000
@@ -360,6 +360,41 @@ for authentication.
 If this option is not specified,
 public key authentication is used (see
 .Xr isakmpd 8 ) .
+.It Ic tag Ar string
+Add a
+.Xr pf 4
+tag to all packets of phase 2 SAs created for this connection.
+This will allow matching packets for this connection by defining
+rules in
+.Xr pf.conf 5
+using the
+.Cm tagged
+keyword.
+.Pp
+The following variables can be used in tags to include information
+from the remote peer on runtime:
+.Pp
+.Bl -tag -width $domain -compact -offset indent
+.It Ar $id
+The remote phase 1 ID.
+It will be expanded to
+.Ar id-type/id-value ,
+e.g.\&
+.Ar fqdn/foo.bar.org .
+.It Ar $domain
+Extract the domain from IDs of type FQDN or UFQDN.
+.El
+.Pp
+For example, if the ID is
+.Ar fqdn/foo.bar.org
+or
+.Ar ufqdn/[EMAIL PROTECTED] ,
+.Dq ipsec-$domain
+expands to
+.Dq ipsec-bar.org .
+The variable expansion for the
+.Ar tag
+directive occurs only at runtime, not during configuration file parse time.
 .El
 .Sh PACKET FILTERING
 IPsec traffic appears unencrypted on the
@@ -390,6 +425,10 @@ and incoming traffic after it's been dec
 [tunnel mode only]
 IP-in-IP traffic flowing between gateways
 on the enc0 interface.
+.It tagged ipsec-example.org
+Match traffic of phase 2 SAs using the
+.Ic tag
+keyword.
 .El
 .Pp
 If the filtering rules specify to block everything by default,
@@ -440,6 +479,45 @@ to avoid permitting unencrypted traffic 
 exit.
 Therefore all rules on the enc0 interface should explicitly set
 .Dq keep state (if-bound) .
+.Pp
+.Xr pf 4
+has the ability to filter IPsec-related packets
+based on an arbitrary
+.Em tag
+specified within a ruleset.
+The tag is used as an internal marker
+which can be used to identify the packets later on.
+This could be helpful,
+for example,
+in scenarios where users are connecting in from differing IP addresses,
+or to support queue-based bandwidth control,
+since the enc0 interface does not support it.
+.Pp
+The following
+.Xr pf.conf 5
+fragment uses queues for all IPsec traffic with special
+handling for developers and employees:
+.Bd -literal -offset indent
+altq on sk0 cbq bandwidth 1000Mb \e
+       queue { deflt, developers, employees, ipsec }
+    queue deflt bandwidth 10% priority 0 cbq(default ecn)
+    queue developers bandwidth 75% priority 7 cbq(borrow red)
+    queue employees bandwidth 5% cbq(red)
+    queue ipsec bandwidth 10% cbq(red)
+
+pass out on sk0 proto esp queue ipsec
+
+pass out on sk0 tagged ipsec-developers.bar.org queue developers
+pass out on sk0 tagged ipsec-employees.bar.org queue employees
+.Ed
+.Pp
+The tags will be assigned by the following
+.Nm
+example:
+.Bd -literal -offset indent
+ike esp from 10.1.1.0/24 to 10.1.2.0/24 peer 192.168.3.2 \e
+       tag ipsec-$domain
+.Ed
 .Sh CRYPTO TRANSFORMS
 It is very important that keys are not guessable.
 One practical way of generating keys is to use
Index: sbin/ipsecctl/ike.c
===================================================================
RCS file: /cvs/src/sbin/ipsecctl/ike.c,v
retrieving revision 1.52
diff -u -p -r1.52 ike.c
--- sbin/ipsecctl/ike.c 1 Nov 2006 03:12:14 -0000       1.52
+++ sbin/ipsecctl/ike.c 9 Nov 2006 16:10:11 -0000
@@ -39,7 +39,7 @@ static void   ike_section_ids(struct ipsec
                    FILE *, u_int8_t);
 static int     ike_get_id_type(char *);
 static void    ike_section_ipsec(struct ipsec_addr_wrap *, struct
-                   ipsec_addr_wrap *, struct ipsec_addr_wrap *, FILE *);
+                   ipsec_addr_wrap *, struct ipsec_addr_wrap *, char *, FILE 
*);
 static int     ike_section_p1(struct ipsec_addr_wrap *, struct
                    ipsec_transforms *, FILE *, struct ike_auth *, u_int8_t);
 static int     ike_section_p2(struct ipsec_addr_wrap *, struct
@@ -175,7 +175,7 @@ ike_get_id_type(char *string)
 
 static void
 ike_section_ipsec(struct ipsec_addr_wrap *src, struct ipsec_addr_wrap *dst,
-    struct ipsec_addr_wrap *peer, FILE *fd)
+    struct ipsec_addr_wrap *peer, char *tag, FILE *fd)
 {
        fprintf(fd, SET "[IPsec-%s-%s]:Phase=2 force\n", src->name, dst->name);
 
@@ -193,6 +193,10 @@ ike_section_ipsec(struct ipsec_addr_wrap
            dst->name, src->name);
        fprintf(fd, SET "[IPsec-%s-%s]:Remote-ID=rid-%s force\n", src->name,
            dst->name, dst->name);
+
+       if (tag)
+               fprintf(fd, SET "[IPsec-%s-%s]:PF-Tag=%s force\n",
+                   src->name, dst->name, tag);
 }
 
 static int
@@ -595,7 +599,7 @@ ike_gen_config(struct ipsec_rule *r, FIL
            fd, r->ikeauth, r->p1ie) == -1)
                return (-1);
        ike_section_ids(r->peer, r->auth, fd, r->ikemode);
-       ike_section_ipsec(r->src, r->dst, r->peer, fd);
+       ike_section_ipsec(r->src, r->dst, r->peer, r->tag, fd);
        if (ike_section_p2(r->src, r->dst, r->satype, r->tmode, r->p2xfs,
            fd, r->p2ie) == -1)
                return (-1);
Index: sbin/ipsecctl/ipsecctl.h
===================================================================
RCS file: /cvs/src/sbin/ipsecctl/ipsecctl.h,v
retrieving revision 1.50
diff -u -p -r1.50 ipsecctl.h
--- sbin/ipsecctl/ipsecctl.h    1 Nov 2006 03:10:02 -0000       1.50
+++ sbin/ipsecctl/ipsecctl.h    9 Nov 2006 16:10:11 -0000
@@ -181,6 +181,7 @@ struct ipsec_rule {
        struct ipsec_key  *authkey;
        struct ipsec_key  *enckey;
 
+       char            *tag;           /* pf tag for SAs */
        u_int8_t         satype;        /* encapsulating prococol */
        u_int8_t         proto;         /* encapsulated protocol */
        u_int8_t         proto2;
Index: sbin/ipsecctl/parse.y
===================================================================
RCS file: /cvs/src/sbin/ipsecctl/parse.y,v
retrieving revision 1.110
diff -u -p -r1.110 parse.y
--- sbin/ipsecctl/parse.y       1 Nov 2006 03:10:02 -0000       1.110
+++ sbin/ipsecctl/parse.y       9 Nov 2006 16:10:13 -0000
@@ -154,6 +154,7 @@ struct ipsec_auth   *copyipsecauth(const s
 struct ike_auth                *copyikeauth(const struct ike_auth *);
 struct ipsec_key       *copykey(struct ipsec_key *);
 struct ipsec_addr_wrap *copyhost(const struct ipsec_addr_wrap *);
+char                   *copytag(const char *);
 struct ipsec_rule      *copyrule(struct ipsec_rule *);
 int                     validate_sa(u_int32_t, u_int8_t,
                             struct ipsec_transforms *, struct ipsec_key *,
@@ -175,7 +176,7 @@ struct ipsec_rule   *reverse_rule(struct i
 struct ipsec_rule      *create_ike(u_int8_t, struct ipsec_hosts *,
                             struct ipsec_hosts *, struct ike_mode *,
                             struct ike_mode *, u_int8_t, u_int8_t, u_int8_t,
-                            char *, char *, struct ike_auth *);
+                            char *, char *, struct ike_auth *, char *);
 int                     add_sagroup(struct ipsec_rule *);
 
 struct ipsec_transforms *ipsec_transforms;
@@ -229,7 +230,7 @@ typedef struct {
 %token FLOW FROM ESP AH IN PEER ON OUT TO SRCID DSTID RSA PSK TCPMD5 SPI
 %token AUTHKEY ENCKEY FILENAME AUTHXF ENCXF ERROR IKE MAIN QUICK AGGRESSIVE
 %token PASSIVE ACTIVE ANY IPIP IPCOMP COMPXF TUNNEL TRANSPORT DYNAMIC LIFE
-%token TYPE DENY BYPASS LOCAL PROTO USE ACQUIRE REQUIRE DONTACQ GROUP PORT
+%token TYPE DENY BYPASS LOCAL PROTO USE ACQUIRE REQUIRE DONTACQ GROUP PORT TAG
 %token <v.string>              STRING
 %type  <v.string>              string
 %type  <v.dir>                 dir
@@ -254,6 +255,7 @@ typedef struct {
 %type  <v.type>                type
 %type  <v.life>                life
 %type  <v.mode>                phase1mode phase2mode
+%type  <v.string>              tag
 %%
 
 grammar                : /* empty */
@@ -331,11 +333,11 @@ flowrule  : FLOW satype dir proto hosts p
                ;
 
 ikerule                : IKE ikemode satype tmode proto hosts peers
-                   phase1mode phase2mode ids ikeauth {
+                   phase1mode phase2mode ids ikeauth tag {
                        struct ipsec_rule       *r;
 
                        r = create_ike($5, &$6, &$7, $8, $9, $3, $4, $2,
-                           $10.srcid, $10.dstid, &$11);
+                           $10.srcid, $10.dstid, &$11, $12);
                        if (r == NULL)
                                YYERROR;
                        r->nr = ipsec->rule_nr++;
@@ -787,6 +789,16 @@ ikeauth            : /* empty */                   {
                }
                ;
 
+tag            : /* empty */
+               {
+                       $$ = NULL;
+               }
+               | TAG STRING
+               {
+                       $$ = $2;
+               }
+               ;
+
 string         : string STRING
                {
                        if (asprintf(&$$, "%s %s", $1, $2) == -1)
@@ -879,6 +891,7 @@ lookup(char *s)
                { "rsa",                RSA },
                { "spi",                SPI },
                { "srcid",              SRCID },
+               { "tag",                TAG },
                { "tcpmd5",             TCPMD5 },
                { "to",                 TO },
                { "transport",          TRANSPORT },
@@ -1812,6 +1825,19 @@ copyhost(const struct ipsec_addr_wrap *s
        return dst;
 }
 
+char *
+copytag(const char *src)
+{
+       char *tag;
+
+       if (src == NULL)
+               return (NULL);
+       if ((tag = strdup(src)) == NULL)
+               err(1, "copytag: strdup");
+
+       return (tag);
+}
+
 struct ipsec_rule *
 copyrule(struct ipsec_rule *rule)
 {
@@ -1833,6 +1859,7 @@ copyrule(struct ipsec_rule *rule)
        r->p2life = copylife(rule->p2life);
        r->authkey = copykey(rule->authkey);
        r->enckey = copykey(rule->enckey);
+       r->tag = copytag(rule->tag);
 
        r->p1ie = rule->p1ie;
        r->p2ie = rule->p2ie;
@@ -2245,7 +2272,7 @@ struct ipsec_rule *
 create_ike(u_int8_t proto, struct ipsec_hosts *hosts, struct ipsec_hosts 
*peers,
     struct ike_mode *phase1mode, struct ike_mode *phase2mode, u_int8_t satype,
     u_int8_t tmode, u_int8_t mode, char *srcid, char *dstid,
-    struct ike_auth *authtype)
+    struct ike_auth *authtype, char *tag)
 {
        struct ipsec_rule *r;
 
@@ -2335,6 +2362,7 @@ create_ike(u_int8_t proto, struct ipsec_
                err(1, "create_ike: calloc");
        r->ikeauth->type = authtype->type;
        r->ikeauth->string = authtype->string;
+       r->tag = tag;
 
        return (r);
 }
Index: sbin/ipsecctl/pfkdump.c
===================================================================
RCS file: /cvs/src/sbin/ipsecctl/pfkdump.c,v
retrieving revision 1.22
diff -u -p -r1.22 pfkdump.c
--- sbin/ipsecctl/pfkdump.c     19 Sep 2006 21:29:47 -0000      1.22
+++ sbin/ipsecctl/pfkdump.c     9 Nov 2006 16:10:15 -0000
@@ -55,6 +55,7 @@ static void   print_ident(struct sadb_ext 
 static void    print_auth(struct sadb_ext *, struct sadb_msg *);
 static void    print_cred(struct sadb_ext *, struct sadb_msg *);
 static void    print_udpenc(struct sadb_ext *, struct sadb_msg *);
+static void    print_tag(struct sadb_ext *, struct sadb_msg *);
 
 static struct idname *lookup(struct idname [], u_int8_t);
 static char    *lookup_name(struct idname [], u_int8_t);
@@ -104,6 +105,7 @@ struct idname ext_types[] = {
        { SADB_X_EXT_REMOTE_CREDENTIALS,"remote_cred",          print_cred },
        { SADB_X_EXT_UDPENCAP,          "udpencap",             print_udpenc },
        { SADB_X_EXT_LIFETIME_LASTUSE,  "lifetime_lastuse",     print_life },
+       { SADB_X_EXT_TAG,               "tag",                  print_tag },
        { 0,                            NULL,                   NULL }
 };
 
@@ -372,6 +374,16 @@ print_flow(struct sadb_ext *ext, struct 
        }
        printf("type %s direction %s",
            lookup_name(flow_types, proto->sadb_protocol_proto), dir);
+}
+
+static void
+print_tag(struct sadb_ext *ext, struct sadb_msg *msg)
+{
+       struct sadb_x_tag *stag = (struct sadb_x_tag *)ext;
+       char *p;
+
+       p = (char *)(stag + 1);
+       printf("%s", p);
 }
 
 static char *
Index: sbin/isakmpd/ike_auth.c
===================================================================
RCS file: /cvs/src/sbin/isakmpd/ike_auth.c,v
retrieving revision 1.108
diff -u -p -r1.108 ike_auth.c
--- sbin/isakmpd/ike_auth.c     9 Nov 2006 09:43:35 -0000       1.108
+++ sbin/isakmpd/ike_auth.c     9 Nov 2006 16:10:16 -0000
@@ -910,12 +910,14 @@ rsa_sig_encode_hash(struct message *msg)
                        if (handler->cert_obtain(id, id_len, 0, &data,
                            &datalen) == 0) {
                                LOG_DBG((LOG_MISC, 10, "rsa_sig_encode_hash: "
-                                   "no certificate to send"));
+                                   "no certificate to send for id %s",
+                                   ipsec_id_string(id, id_len)));
                                goto skipcert;
                        }
                } else {
                        LOG_DBG((LOG_MISC, 10,
-                           "rsa_sig_encode_hash: no certificate to send"));
+                           "rsa_sig_encode_hash: no certificate to send"
+                           " for id %s", ipsec_id_string(id, id_len)));
                        goto skipcert;
                }
        }
Index: sbin/isakmpd/ipsec.c
===================================================================
RCS file: /cvs/src/sbin/isakmpd/ipsec.c,v
retrieving revision 1.126
diff -u -p -r1.126 ipsec.c
--- sbin/isakmpd/ipsec.c        10 Jun 2006 20:10:02 -0000      1.126
+++ sbin/isakmpd/ipsec.c        9 Nov 2006 16:10:19 -0000
@@ -39,6 +39,9 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <net/if.h>
+#include <net/pfvar.h>
+
 #include "sysdep.h"
 
 #include "attribute.h"
@@ -129,6 +132,7 @@ static int      ipsec_validate_notificat
 static int      ipsec_validate_proto(u_int8_t);
 static int      ipsec_validate_situation(u_int8_t *, size_t *, size_t);
 static int      ipsec_validate_transform_id(u_int8_t, u_int8_t);
+static int      ipsec_sa_tag(struct exchange *, struct sa *, struct sa *);
 
 static struct doi ipsec_doi = {
        {0}, IPSEC_DOI_IPSEC,
@@ -277,6 +281,90 @@ ipsec_sa_check_flow(struct sa *sa, void 
 }
 
 /*
+ * Construct a PF tag if specified in the configuration.
+ * It is possible to use variables to expand the tag:
+ * $id         The string representation of the remote ID
+ * $domain     The stripped domain part of the ID (for FQDN and UFQDN)
+ */
+static int
+ipsec_sa_tag(struct exchange *exchange, struct sa *sa, struct sa *isakmp_sa)
+{
+       char *format, *section;
+       char *id_string = NULL, *domain = NULL;
+       int error = -1;
+       size_t len;
+
+       sa->tag = NULL;
+
+       if (exchange->name == NULL ||
+           (section = exchange->name) == NULL ||
+           (format = conf_get_str(section, "PF-Tag")) == NULL)
+               return (0);     /* ignore if not present */
+
+       len = PF_TAG_NAME_SIZE;
+       if ((sa->tag = calloc(1, len)) == NULL) {
+               log_error("ipsec_sa_tag: calloc");
+               goto fail;
+       }
+       if (strlcpy(sa->tag, format, len) >= len) {
+               log_print("ipsec_sa_tag: tag too long");
+               goto fail;
+       }
+       if (isakmp_sa->initiator)
+               id_string = ipsec_id_string(isakmp_sa->id_r,
+                   isakmp_sa->id_r_len);
+       else
+               id_string = ipsec_id_string(isakmp_sa->id_i,
+                   isakmp_sa->id_i_len);
+
+       if (strstr(format, "$id") != NULL) {
+               if (id_string == NULL) {
+                       log_print("ipsec_sa_tag: cannot get ID");
+                       goto fail;
+               }
+               if (expand_string(sa->tag, len, "$id", id_string) != 0) {
+                       log_print("ipsec_sa_tag: failed to expand tag");
+                       goto fail;
+               }
+       }
+
+       if (strstr(format, "$domain") != NULL) {
+               if (id_string == NULL) {
+                       log_print("ipsec_sa_tag: cannot get ID");
+                       goto fail;
+               }
+               if (strncmp(id_string, "fqdn/", strlen("fqdn/")) == 0)
+                       domain = strchr(id_string, '.');
+               else if (strncmp(id_string, "ufqdn/", strlen("ufqdn/")) == 0)
+                       domain = strchr(id_string, '@');
+               if (domain == NULL || strlen(domain) < 2) {
+                       log_print("ipsec_sa_tag: no valid domain in ID %s",
+                           id_string);
+                       goto fail;
+               }
+               domain++;
+               if (expand_string(sa->tag, len, "$domain", domain) != 0) {
+                       log_print("ipsec_sa_tag: failed to expand tag");
+                       goto fail;
+               }
+       }
+
+       LOG_DBG((LOG_SA, 10, "ipsec_sa_tag: tag_len %ld tag \"%s\"",
+           strlen(sa->tag), sa->tag));
+
+       error = 0;
+ fail:
+       if (id_string != NULL)
+               free(id_string);
+       if (error != 0 && sa->tag != NULL) {
+               free(sa->tag);
+               sa->tag = NULL;
+       }
+
+       return (error);
+}
+
+/*
  * Do IPsec DOI specific finalizations task for the exchange where MSG was
  * the final message.
  */
@@ -356,6 +444,9 @@ ipsec_finalize_exchange(struct message *
                                                return;
                                        }
                                }
+
+                               if (ipsec_sa_tag(exchange, sa, isakmp_sa) == -1)
+                                       return;
 
                                for (proto = TAILQ_FIRST(&sa->protos),
                                    last_proto = 0; proto;
Index: sbin/isakmpd/isakmpd.conf.5
===================================================================
RCS file: /cvs/src/sbin/isakmpd/isakmpd.conf.5,v
retrieving revision 1.118
diff -u -p -r1.118 isakmpd.conf.5
--- sbin/isakmpd/isakmpd.conf.5 15 Sep 2006 09:49:07 -0000      1.118
+++ sbin/isakmpd/isakmpd.conf.5 9 Nov 2006 16:10:21 -0000
@@ -647,6 +647,41 @@ we are dealing with.
 Look at
 .Aq Sy IPsec-ID
 below.
+.It Em PF-Tag
+Add a
+.Xr pf 4
+tag to all packets of phase 2 SAs created for this connection.
+This will allow matching packets for this connection by defining
+rules in
+.Xr pf.conf 5
+using the
+.Em tagged
+keyword.
+.Pp
+The following variables can be used in tags to include information
+from the remote peer on runtime:
+.Pp
+.Bl -tag -width $domain -compact -offset indent
+.It Ar $id
+The remote phase 1 ID.
+It will be expanded to
+.Ar id-type/id-value ,
+e.g.\&
+.Ar fqdn/foo.bar.org .
+.It Ar $domain
+Extract the domain from IDs of type FQDN or UFQDN.
+.El
+.Pp
+For example, if the ID is
+.Ar fqdn/foo.bar.org
+or
+.Ar ufqdn/[EMAIL PROTECTED] ,
+.Dq PF-Tag=ipsec-$domain
+expands to
+.Dq ipsec-bar.org .
+The variable expansion for the
+.Ar PF-Tag
+directive occurs only at runtime, not during configuration file parse time.
 .El
 .It Aq Sy IPsec-configuration
 Parameters for IPsec configuration
Index: sbin/isakmpd/pf_key_v2.c
===================================================================
RCS file: /cvs/src/sbin/isakmpd/pf_key_v2.c,v
retrieving revision 1.176
diff -u -p -r1.176 pf_key_v2.c
--- sbin/isakmpd/pf_key_v2.c    1 Sep 2006 00:24:06 -0000       1.176
+++ sbin/isakmpd/pf_key_v2.c    9 Nov 2006 16:10:25 -0000
@@ -902,6 +902,7 @@ pf_key_v2_set_spi(struct sa *sa, struct 
 {
        struct sadb_msg msg;
        struct sadb_sa  ssa;
+       struct sadb_x_tag *stag = NULL;
        struct sadb_lifetime *life = 0;
        struct sadb_address *addr = 0;
        struct sadb_key *key = 0;
@@ -917,7 +918,7 @@ pf_key_v2_set_spi(struct sa *sa, struct 
        struct sadb_x_cred *cred;
        struct sadb_protocol flowtype, tprotocol;
        struct sadb_x_udpencap udpencap;
-       char           *addr_str;
+       char           *addr_str, *s;
 
        msg.sadb_msg_type = incoming ? SADB_UPDATE : SADB_ADD;
        switch (proto->proto) {
@@ -1549,14 +1550,31 @@ doneauth:
                goto cleanup;
        addr = 0;
 
+       /* Add a pf tag to matching packets of this SA. */
+       if (sa->tag != NULL) {
+               len = sizeof(*stag) + PF_KEY_V2_ROUND(strlen(sa->tag) + 1);
+               if ((stag = (struct sadb_x_tag *)calloc(1, len)) == NULL)
+                       goto cleanup;
+               stag->sadb_x_tag_exttype = SADB_X_EXT_TAG;
+               stag->sadb_x_tag_len = len / PF_KEY_V2_CHUNK;
+               stag->sadb_x_tag_taglen = strlen(sa->tag) + 1;
+               s = (char *)(stag + 1);
+               strlcpy(s, sa->tag, stag->sadb_x_tag_taglen);
+               if (pf_key_v2_msg_add(update, (struct sadb_ext *)stag,
+                   PF_KEY_V2_NODE_MALLOCED) == -1)
+                       goto cleanup;
+       }
+
        /* XXX Here can sensitivity extensions be setup.  */
 
        if (sockaddr2text(dst, &addr_str, 0))
                addr_str = 0;
 
        LOG_DBG((LOG_SYSDEP, 10, "pf_key_v2_set_spi: "
-           "satype %d dst %s SPI 0x%x", msg.sadb_msg_satype,
-           addr_str ? addr_str : "unknown", ntohl(ssa.sadb_sa_spi)));
+           "satype %d dst %s SPI 0x%x%s%s", msg.sadb_msg_satype,
+           addr_str ? addr_str : "unknown",
+           ntohl(ssa.sadb_sa_spi), sa->tag ? " tag " : "",
+           sa->tag ? sa->tag : ""));
 
        if (addr_str)
                free(addr_str);
Index: sbin/isakmpd/sa.c
===================================================================
RCS file: /cvs/src/sbin/isakmpd/sa.c,v
retrieving revision 1.109
diff -u -p -r1.109 sa.c
--- sbin/isakmpd/sa.c   30 Aug 2006 16:33:31 -0000      1.109
+++ sbin/isakmpd/sa.c   9 Nov 2006 16:10:26 -0000
@@ -868,6 +868,8 @@ sa_release(struct sa *sa)
                timer_remove_event(sa->dpd_event);
        if (sa->transport)
                transport_release(sa->transport);
+       if (sa->tag)
+               free(sa->tag);
        free(sa);
 }
 
Index: sbin/isakmpd/sa.h
===================================================================
RCS file: /cvs/src/sbin/isakmpd/sa.h,v
retrieving revision 1.48
diff -u -p -r1.48 sa.h
--- sbin/isakmpd/sa.h   2 Jun 2006 19:35:55 -0000       1.48
+++ sbin/isakmpd/sa.h   9 Nov 2006 16:10:27 -0000
@@ -209,6 +209,9 @@ struct sa {
        u_int32_t       dpd_failcount;  /* # of subsequent failures */
        u_int32_t       dpd_rdupcount;  /* # of subsequent duplicates */
        struct event   *dpd_event;      /* time of next event */
+
+       /* The add a pf tag to packets matching the established SA. */
+       char           *tag;
 };
 
 /* This SA is alive.  */
Index: sbin/isakmpd/util.c
===================================================================
RCS file: /cvs/src/sbin/isakmpd/util.c,v
retrieving revision 1.62
diff -u -p -r1.62 util.c
--- sbin/isakmpd/util.c 24 Jul 2006 11:45:44 -0000      1.62
+++ sbin/isakmpd/util.c 9 Nov 2006 16:10:27 -0000
@@ -621,3 +621,34 @@ gc_strdup(const char *x)
        return strcpy(y,x);
 }
 #endif
+
+int
+expand_string(char *label, size_t len, const char *srch, const char *repl)
+{
+       char *tmp;
+       char *p, *q;
+
+       if ((tmp = calloc(1, len)) == NULL) {
+               log_error("expand_string: calloc");
+               return (-1);
+       }
+       p = q = label;
+       while ((q = strstr(p, srch)) != NULL) {
+               *q = '\0';
+               if ((strlcat(tmp, p, len) >= len) ||
+                   (strlcat(tmp, repl, len) >= len)) {
+                       log_print("expand_string: string too long");
+                       return (-1);
+               }
+               q += strlen(srch);
+               p = q;
+       }
+       if (strlcat(tmp, p, len) >= len) {
+               log_print("expand_string: string too long");
+               return (-1);
+       }
+       strlcpy(label, tmp, len);       /* always fits */
+       free(tmp);
+
+       return (0);
+}
Index: sbin/isakmpd/util.h
===================================================================
RCS file: /cvs/src/sbin/isakmpd/util.h,v
retrieving revision 1.28
diff -u -p -r1.28 util.h
--- sbin/isakmpd/util.h 28 Dec 2005 10:57:35 -0000      1.28
+++ sbin/isakmpd/util.h 9 Nov 2006 16:10:28 -0000
@@ -63,5 +63,6 @@ extern int      text2sockaddr(char *, ch
 extern void     util_ntoa(char **, int, u_int8_t *);
 extern int      zero_test(const u_int8_t *, size_t);
 extern long    get_timeout(struct timeval *);
+extern int     expand_string(char *, size_t, const char *, const char *);
 
 #endif                         /* _UTIL_H_ */
Index: sys/net/pfkeyv2.c
===================================================================
RCS file: /cvs/src/sys/net/pfkeyv2.c,v
retrieving revision 1.111
diff -u -p -r1.111 pfkeyv2.c
--- sys/net/pfkeyv2.c   16 Jun 2006 16:49:39 -0000      1.111
+++ sys/net/pfkeyv2.c   9 Nov 2006 16:10:30 -0000
@@ -68,6 +68,8 @@
  * SUCH DAMAGE.
  */
 
+#include "pf.h"
+
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/socket.h>
@@ -83,6 +85,11 @@
 #include <netinet/ip_ipcomp.h>
 #include <crypto/blf.h>
 
+#if NPF > 0
+#include <net/if.h>
+#include <net/pfvar.h>
+#endif
+
 #define PFKEYV2_PROTOCOL 2
 #define GETSPI_TRIES 10
 
@@ -552,6 +559,11 @@ pfkeyv2_get(struct tdb *sa, void **heade
        if (sa->tdb_udpencap_port)
                i+= sizeof(struct sadb_x_udpencap);
 
+#if NPF > 0
+       if (sa->tdb_tag)
+               i+= PADUP(PF_TAG_NAME_SIZE) + sizeof(struct sadb_x_tag);
+#endif
+
        if (lenp)
                *lenp = i;
 
@@ -659,6 +671,14 @@ pfkeyv2_get(struct tdb *sa, void **heade
                export_udpencap(&p, sa);
        }
 
+#if NPF > 0
+       /* Export tag information, if present */
+       if (sa->tdb_tag) {
+               headers[SADB_X_EXT_TAG] = p;
+               export_tag(&p, sa);
+       }
+#endif
+
        rval = 0;
 
  ret:
@@ -1005,6 +1025,9 @@ pfkeyv2_send(struct socket *socket, void
                            headers[SADB_X_EXT_PROTOCOL],
                            headers[SADB_X_EXT_FLOW_TYPE]);
                        import_udpencap(newsa, headers[SADB_X_EXT_UDPENCAP]);
+#if NPF > 0
+                       import_tag(newsa, headers[SADB_X_EXT_TAG]);
+#endif
 
                        headers[SADB_EXT_KEY_AUTH] = NULL;
                        headers[SADB_EXT_KEY_ENCRYPT] = NULL;
@@ -1051,6 +1074,9 @@ pfkeyv2_send(struct socket *socket, void
                        import_lifetime(sa2, headers[SADB_EXT_LIFETIME_HARD],
                            PFKEYV2_LIFETIME_HARD);
                        import_udpencap(sa2, headers[SADB_X_EXT_UDPENCAP]);
+#if NPF > 0
+                       import_tag(sa2, headers[SADB_X_EXT_TAG]);
+#endif
                }
 
                splx(s);
@@ -1163,6 +1189,9 @@ pfkeyv2_send(struct socket *socket, void
                            headers[SADB_X_EXT_PROTOCOL],
                            headers[SADB_X_EXT_FLOW_TYPE]);
                        import_udpencap(newsa, headers[SADB_X_EXT_UDPENCAP]);
+#if NPF > 0
+                       import_tag(newsa, headers[SADB_X_EXT_TAG]);
+#endif
 
                        headers[SADB_EXT_KEY_AUTH] = NULL;
                        headers[SADB_EXT_KEY_ENCRYPT] = NULL;
Index: sys/net/pfkeyv2.h
===================================================================
RCS file: /cvs/src/sys/net/pfkeyv2.h,v
retrieving revision 1.55
diff -u -p -r1.55 pfkeyv2.h
--- sys/net/pfkeyv2.h   27 May 2005 15:29:55 -0000      1.55
+++ sys/net/pfkeyv2.h   9 Nov 2006 16:10:31 -0000
@@ -213,6 +213,12 @@ struct sadb_x_udpencap {
        uint16_t sadb_x_udpencap_reserved;
 };
 
+struct sadb_x_tag {
+       uint16_t  sadb_x_tag_len;
+       uint16_t  sadb_x_tag_exttype;
+       u_int32_t sadb_x_tag_taglen;
+};
+
 #ifdef _KERNEL
 #define SADB_X_GETSPROTO(x) \
        ( (x) == SADB_SATYPE_AH ? IPPROTO_AH :\
@@ -254,7 +260,8 @@ struct sadb_x_udpencap {
 #define SADB_X_EXT_SUPPORTED_COMP     30
 #define SADB_X_EXT_UDPENCAP           31
 #define SADB_X_EXT_LIFETIME_LASTUSE   32
-#define SADB_EXT_MAX                  32
+#define SADB_X_EXT_TAG                33
+#define SADB_EXT_MAX                  33
 
 /* Fix pfkeyv2.c struct pfkeyv2_socket if SATYPE_MAX > 31 */
 #define SADB_SATYPE_UNSPEC              0
@@ -445,6 +452,7 @@ void export_flow(void **, u_int8_t, stru
 void export_key(void **, struct tdb *, int);
 void export_auth(void **, struct tdb *, int);
 void export_udpencap(void **, struct tdb *);
+void export_tag(void **, struct tdb *);
 
 void import_auth(struct tdb *, struct sadb_x_cred *, int);
 void import_address(struct sockaddr *, struct sadb_address *);
@@ -457,5 +465,6 @@ void import_flow(struct sockaddr_encap *
     struct sadb_address *, struct sadb_address *, struct sadb_address *,
     struct sadb_address *, struct sadb_protocol *, struct sadb_protocol *);
 void import_udpencap(struct tdb *, struct sadb_x_udpencap *);
+void import_tag(struct tdb *, struct sadb_x_tag *);
 #endif /* _KERNEL */
 #endif /* _NET_PFKEY_V2_H_ */
Index: sys/net/pfkeyv2_convert.c
===================================================================
RCS file: /cvs/src/sys/net/pfkeyv2_convert.c,v
retrieving revision 1.28
diff -u -p -r1.28 pfkeyv2_convert.c
--- sys/net/pfkeyv2_convert.c   1 Jun 2006 07:06:09 -0000       1.28
+++ sys/net/pfkeyv2_convert.c   9 Nov 2006 16:10:32 -0000
@@ -91,6 +91,8 @@
  * SUCH DAMAGE.
  */
 
+#include "pf.h"
+
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -99,6 +101,11 @@
 #include <sys/socket.h>
 #include <net/route.h>
 #include <net/if.h>
+
+#if NPF > 0
+#include <net/pfvar.h>
+#endif
+
 #include <netinet/ip_ipsp.h>
 #ifdef INET6
 #include <netinet6/in6_var.h>
@@ -973,3 +980,31 @@ export_udpencap(void **p, struct tdb *td
            sizeof(struct sadb_x_udpencap) / sizeof(uint64_t);
        *p += sizeof(struct sadb_x_udpencap);
 }
+
+#if NPF > 0
+/* Import PF tag information for SA */
+void
+import_tag(struct tdb *tdb, struct sadb_x_tag *stag)
+{
+       char *s;
+
+       if (stag) {
+               s = (char *)(stag + 1);
+               tdb->tdb_tag = pf_tagname2tag(s);
+       }
+}
+
+/* Export PF tag information for SA */
+void
+export_tag(void **p, struct tdb *tdb)
+{
+       struct sadb_x_tag *stag = (struct sadb_x_tag *)*p;
+       char *s = (char *)(stag + 1);
+
+       pf_tag2tagname(tdb->tdb_tag, s);
+       stag->sadb_x_tag_taglen = strlen(s) + 1;
+       stag->sadb_x_tag_len = (sizeof(struct sadb_x_tag) +
+           PADUP(stag->sadb_x_tag_taglen)) / sizeof(uint64_t);
+       *p += PADUP(stag->sadb_x_tag_taglen) + sizeof(struct sadb_x_tag);
+}
+#endif
Index: sys/net/pfkeyv2_parsemessage.c
===================================================================
RCS file: /cvs/src/sys/net/pfkeyv2_parsemessage.c,v
retrieving revision 1.40
diff -u -p -r1.40 pfkeyv2_parsemessage.c
--- sys/net/pfkeyv2_parsemessage.c      28 May 2005 15:10:07 -0000      1.40
+++ sys/net/pfkeyv2_parsemessage.c      9 Nov 2006 16:10:33 -0000
@@ -68,6 +68,8 @@
  * SUCH DAMAGE.
  */
 
+#include "pf.h"
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/socket.h>
@@ -76,6 +78,11 @@
 #include <netinet/ip_ipsp.h>
 #include <net/pfkeyv2.h>
 
+#if NPF > 0
+#include <net/if.h>
+#include <net/pfvar.h>
+#endif
+
 extern int encdebug;
 
 #ifdef ENCDEBUG
@@ -123,6 +130,7 @@ extern int encdebug;
 #define BITMAP_X_SUPPORTED_COMP        (1LL << SADB_X_EXT_SUPPORTED_COMP)
 #define BITMAP_X_UDPENCAP              (1LL << SADB_X_EXT_UDPENCAP)
 #define BITMAP_X_LIFETIME_LASTUSE      (1LL << SADB_X_EXT_LIFETIME_LASTUSE)
+#define BITMAP_X_TAG                   (1LL << SADB_X_EXT_TAG)
 
 uint64_t sadb_exts_allowed_in[SADB_MAX+1] =
 {
@@ -131,9 +139,9 @@ uint64_t sadb_exts_allowed_in[SADB_MAX+1
        /* GETSPI */
        BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SPIRANGE,
        /* UPDATE */
-       BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | 
BITMAP_IDENTITY | BITMAP_X_CREDENTIALS | BITMAP_X_FLOW | BITMAP_X_UDPENCAP,
+       BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | 
BITMAP_IDENTITY | BITMAP_X_CREDENTIALS | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | 
BITMAP_X_TAG,
        /* ADD */
-       BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | 
BITMAP_IDENTITY | BITMAP_X_CREDENTIALS | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | 
BITMAP_X_LIFETIME_LASTUSE,
+       BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | 
BITMAP_IDENTITY | BITMAP_X_CREDENTIALS | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | 
BITMAP_X_LIFETIME_LASTUSE | BITMAP_X_TAG,
        /* DELETE */
        BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST,
        /* GET */
@@ -203,9 +211,9 @@ uint64_t sadb_exts_allowed_out[SADB_MAX+
        /* GETSPI */
        BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST,
        /* UPDATE */
-       BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY | 
BITMAP_X_CREDENTIALS | BITMAP_X_FLOW | BITMAP_X_UDPENCAP,
+       BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY | 
BITMAP_X_CREDENTIALS | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG,
        /* ADD */
-       BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY | 
BITMAP_X_CREDENTIALS | BITMAP_X_FLOW | BITMAP_X_UDPENCAP,
+       BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY | 
BITMAP_X_CREDENTIALS | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG,
        /* DELETE */
        BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST,
        /* GET */
@@ -933,6 +941,21 @@ pfkeyv2_parsemessage(void *p, int len, v
                                return (EINVAL);
                        }
                        break;
+#if NPF > 0
+               case SADB_X_EXT_TAG:
+                       if (i < sizeof(struct sadb_x_tag)) {
+                               DPRINTF(("pfkeyv2_parsemessage: "
+                                   "TAG extension header too small"));
+                               return (EINVAL);
+                       }
+                       if (i > (sizeof(struct sadb_x_tag) +
+                           PF_TAG_NAME_SIZE)) {
+                               DPRINTF(("pfkeyv2_parsemessage: "
+                                   "TAG extension header too long"));
+                               return (EINVAL);
+                       }
+                       break;
+#endif
                default:
                        DPRINTF(("pfkeyv2_parsemessage: unknown extension "
                            "header type %d\n",
Index: sys/netinet/ipsec_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ipsec_input.c,v
retrieving revision 1.79
diff -u -p -r1.79 ipsec_input.c
--- sys/netinet/ipsec_input.c   25 Mar 2006 22:41:48 -0000      1.79
+++ sys/netinet/ipsec_input.c   9 Nov 2006 16:10:35 -0000
@@ -35,6 +35,8 @@
  * PURPOSE.
  */
 
+#include "pf.h"
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/protosw.h>
@@ -47,6 +49,10 @@
 #include <net/netisr.h>
 #include <net/bpf.h>
 
+#if NPF > 0
+#include <net/pfvar.h>
+#endif
+
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
 #include <netinet/ip.h>
@@ -553,6 +559,12 @@ ipsec_common_input_cb(struct mbuf *m, st
                        m->m_flags |= M_AUTH;
        } else if (sproto == IPPROTO_AH)
                m->m_flags |= M_AUTH | M_AUTH_AH;
+
+#if NPF > 0
+       /* Add pf tag if requested. */
+       if (pf_tag_packet(m, NULL, tdbp->tdb_tag, -1))
+               DPRINTF(("failed to tag ipsec packet\n"));
+#endif
 
        if (tdbp->tdb_flags & TDBF_TUNNELING)
                m->m_flags |= M_TUNNEL;
Index: sys/netinet/ipsec_output.c
===================================================================
RCS file: /cvs/src/sys/netinet/ipsec_output.c,v
retrieving revision 1.33
diff -u -p -r1.33 ipsec_output.c
--- sys/netinet/ipsec_output.c  12 Apr 2005 09:39:54 -0000      1.33
+++ sys/netinet/ipsec_output.c  9 Nov 2006 16:10:35 -0000
@@ -20,6 +20,8 @@
  * PURPOSE.
  */
 
+#include "pf.h"
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/mbuf.h>
@@ -29,6 +31,10 @@
 #include <net/if.h>
 #include <net/route.h>
 
+#if NPF > 0
+#include <net/pfvar.h>
+#endif
+
 #ifdef INET
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
@@ -427,6 +433,12 @@ ipsp_process_done(struct mbuf *m, struct
        if (tdb->tdb_onext)
                return ipsp_process_packet(m, tdb->tdb_onext,
                    tdb->tdb_dst.sa.sa_family, 0);
+
+#if NPF > 0
+       /* Add pf tag if requested. */
+       if (pf_tag_packet(m, NULL, tdb->tdb_tag, -1))
+               DPRINTF(("failed to tag ipsec packet\n"));
+#endif
 
        /*
         * We're done with IPsec processing, transmit the packet using the
Index: sys/netinet/ip_ipsp.h
===================================================================
RCS file: /cvs/src/sys/netinet/ip_ipsp.h,v
retrieving revision 1.134
diff -u -p -r1.134 ip_ipsp.h
--- sys/netinet/ip_ipsp.h       30 Jun 2006 21:41:12 -0000      1.134
+++ sys/netinet/ip_ipsp.h       9 Nov 2006 16:10:36 -0000
@@ -270,7 +270,7 @@ struct tdb {                                /* tunnel 
descriptor blo
         * Each TDB is on three hash tables: one keyed on dst/spi/sproto,
         * one keyed on dst/sproto, and one keyed on src/sproto. The first
         * is used for finding a specific TDB, the second for finding TDBs
-        * TDBs for outgoing policy matching, and the third for incoming
+        * for outgoing policy matching, and the third for incoming
         * policy matching. The following three fields maintain the hash
         * queues in those three tables.
         */
@@ -366,6 +366,8 @@ struct tdb {                                /* tunnel 
descriptor blo
        u_int64_t       tdb_mtutimeout; /* When to ignore this entry */
 
        u_int16_t       tdb_udpencap_port;      /* Peer UDP port */
+
+       u_int16_t       tdb_tag;                /* Packet filter tag */
 
        struct sockaddr_encap   tdb_filter; /* What traffic is acceptable */
        struct sockaddr_encap   tdb_filtermask; /* And the mask */
Index: sys/netinet/ip_ipsp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_ipsp.c,v
retrieving revision 1.165
diff -u -p -r1.165 ip_ipsp.c
--- sys/netinet/ip_ipsp.c       13 Jan 2006 10:11:23 -0000      1.165
+++ sys/netinet/ip_ipsp.c       9 Nov 2006 16:10:38 -0000
@@ -37,6 +37,8 @@
  * PURPOSE.
  */
 
+#include "pf.h"
+
 #include <sys/param.h>
 #include <sys/mbuf.h>
 #include <sys/socket.h>
@@ -46,6 +48,10 @@
 #include <net/if.h>
 #include <net/route.h>
 
+#if NPF > 0
+#include <net/pfvar.h>
+#endif
+
 #ifdef INET
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
@@ -857,6 +863,13 @@ tdb_free(struct tdb *tdbp)
                ipsp_reffree(tdbp->tdb_remote_cred);
                tdbp->tdb_remote_cred = NULL;
        }
+
+#if NPF > 0
+       if (tdbp->tdb_tag) {
+               pf_tag_unref(tdbp->tdb_tag);
+               tdbp->tdb_tag = 0;
+       }
+#endif
 
        if ((tdbp->tdb_onext) && (tdbp->tdb_onext->tdb_inext == tdbp))
                tdbp->tdb_onext->tdb_inext = NULL;

Reply via email to