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;