xref: /openbsd-src/sbin/ipsecctl/ike.c (revision 8fd570bd951d6ecffe5c8ff12ca193326762d454)
1*8fd570bdSdlg /*	$OpenBSD: ike.c,v 1.84 2023/08/07 04:10:08 dlg Exp $	*/
290bd57a7Shshoexer /*
390bd57a7Shshoexer  * Copyright (c) 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org>
490bd57a7Shshoexer  *
590bd57a7Shshoexer  * Permission to use, copy, modify, and distribute this software for any
690bd57a7Shshoexer  * purpose with or without fee is hereby granted, provided that the above
790bd57a7Shshoexer  * copyright notice and this permission notice appear in all copies.
890bd57a7Shshoexer  *
990bd57a7Shshoexer  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1090bd57a7Shshoexer  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1190bd57a7Shshoexer  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1290bd57a7Shshoexer  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1390bd57a7Shshoexer  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1490bd57a7Shshoexer  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1590bd57a7Shshoexer  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1690bd57a7Shshoexer  */
1790bd57a7Shshoexer 
1890bd57a7Shshoexer #include <sys/types.h>
1990bd57a7Shshoexer #include <sys/socket.h>
206f0500ebShshoexer #include <sys/stat.h>
2190bd57a7Shshoexer #include <sys/queue.h>
2290bd57a7Shshoexer #include <netinet/in.h>
239a6fa87bStodd #include <netdb.h>
2490bd57a7Shshoexer #include <arpa/inet.h>
2590bd57a7Shshoexer 
2690bd57a7Shshoexer #include <err.h>
2790bd57a7Shshoexer #include <fcntl.h>
2890bd57a7Shshoexer #include <stdio.h>
2990bd57a7Shshoexer #include <stdlib.h>
3090bd57a7Shshoexer #include <string.h>
3190bd57a7Shshoexer #include <unistd.h>
32b9fc9a72Sderaadt #include <limits.h>
3390bd57a7Shshoexer 
3490bd57a7Shshoexer #include "ipsecctl.h"
3590bd57a7Shshoexer 
36101a3da2Sreyk static void	ike_section_general(struct ipsec_rule *, FILE *);
37e973ffa2Smarkus static void	ike_section_peer(struct ipsec_rule *, FILE *);
38e973ffa2Smarkus static void	ike_section_ids(struct ipsec_rule *, FILE *);
39e973ffa2Smarkus static void	ike_section_ipsec(struct ipsec_rule *, FILE *);
40e973ffa2Smarkus static int	ike_section_p1(struct ipsec_rule *, FILE *);
41e973ffa2Smarkus static int	ike_section_p2(struct ipsec_rule *, FILE *);
42e973ffa2Smarkus static void	ike_section_p2ids(struct ipsec_rule *, FILE *);
43e973ffa2Smarkus static int	ike_connect(struct ipsec_rule *, FILE *);
4490bd57a7Shshoexer static int	ike_gen_config(struct ipsec_rule *, FILE *);
4590bd57a7Shshoexer static int	ike_delete_config(struct ipsec_rule *, FILE *);
46e973ffa2Smarkus static void	ike_setup_ids(struct ipsec_rule *);
4790bd57a7Shshoexer 
4890bd57a7Shshoexer int		ike_print_config(struct ipsec_rule *, int);
49f8738d8bShenning int		ike_ipsec_establish(int, struct ipsec_rule *, const char *);
5090bd57a7Shshoexer 
5190bd57a7Shshoexer #define	SET	"C set "
5290bd57a7Shshoexer #define	ADD	"C add "
5390bd57a7Shshoexer #define	DELETE	"C rms "
541d6e9a6eSmarkus #define	RMV	"C rmv "
5590bd57a7Shshoexer 
56101a3da2Sreyk #define CONF_DFLT_DYNAMIC_DPD_CHECK_INTERVAL	5
57101a3da2Sreyk #define CONF_DFLT_DYNAMIC_CHECK_INTERVAL	30
58101a3da2Sreyk 
597d4bf23dSjsing char *ike_id_types[] = {
607d4bf23dSjsing 	"", "", "IPV4_ADDR", "IPV6_ADDR", "FQDN", "USER_FQDN"
617d4bf23dSjsing };
6288635086Smsf 
63101a3da2Sreyk static void
ike_section_general(struct ipsec_rule * r,FILE * fd)64101a3da2Sreyk ike_section_general(struct ipsec_rule *r, FILE *fd)
65101a3da2Sreyk {
66101a3da2Sreyk 	if (r->ikemode == IKE_DYNAMIC) {
67101a3da2Sreyk 		fprintf(fd, SET "[General]:Check-interval=%d force\n",
68101a3da2Sreyk 		    CONF_DFLT_DYNAMIC_CHECK_INTERVAL);
69101a3da2Sreyk 		fprintf(fd, SET "[General]:DPD-check-interval=%d force\n",
70101a3da2Sreyk 		    CONF_DFLT_DYNAMIC_DPD_CHECK_INTERVAL);
71101a3da2Sreyk 	}
72101a3da2Sreyk }
73101a3da2Sreyk 
7490bd57a7Shshoexer static void
ike_section_peer(struct ipsec_rule * r,FILE * fd)75e973ffa2Smarkus ike_section_peer(struct ipsec_rule *r, FILE *fd)
7690bd57a7Shshoexer {
77befd40c8Sbluhm 	if (r->peer)
78befd40c8Sbluhm 		fprintf(fd, SET "[Phase 1]:%s=%s force\n", r->peer->name,
79befd40c8Sbluhm 		    r->p1name);
80befd40c8Sbluhm 	else
81befd40c8Sbluhm 		fprintf(fd, SET "[Phase 1]:Default=%s force\n", r->p1name);
82befd40c8Sbluhm 	fprintf(fd, SET "[%s]:Phase=1 force\n", r->p1name);
83befd40c8Sbluhm 	if (r->peer)
84befd40c8Sbluhm 		fprintf(fd, SET "[%s]:Address=%s force\n", r->p1name,
85e973ffa2Smarkus 		    r->peer->name);
86e973ffa2Smarkus 	if (r->local)
87befd40c8Sbluhm 		fprintf(fd, SET "[%s]:Local-address=%s force\n", r->p1name,
88e973ffa2Smarkus 		    r->local->name);
89e973ffa2Smarkus 	if (r->ikeauth->type == IKE_AUTH_PSK)
90befd40c8Sbluhm 		fprintf(fd, SET "[%s]:Authentication=%s force\n", r->p1name,
91e973ffa2Smarkus 		    r->ikeauth->string);
92e1c67a9eShshoexer }
9390bd57a7Shshoexer 
9490bd57a7Shshoexer static void
ike_section_ids(struct ipsec_rule * r,FILE * fd)95e973ffa2Smarkus ike_section_ids(struct ipsec_rule *r, FILE *fd)
9690bd57a7Shshoexer {
97b9fc9a72Sderaadt 	char myname[HOST_NAME_MAX+1];
98101a3da2Sreyk 
99e973ffa2Smarkus 	if (r->auth == NULL)
10090bd57a7Shshoexer 		return;
10190bd57a7Shshoexer 
102e973ffa2Smarkus 	if (r->ikemode == IKE_DYNAMIC && r->auth->srcid == NULL) {
103101a3da2Sreyk 		if (gethostname(myname, sizeof(myname)) == -1)
104101a3da2Sreyk 			err(1, "ike_section_ids: gethostname");
105e973ffa2Smarkus 		if ((r->auth->srcid = strdup(myname)) == NULL)
106101a3da2Sreyk 			err(1, "ike_section_ids: strdup");
1077e56314dSjsing 		r->auth->srcid_type = ID_FQDN;
108101a3da2Sreyk 	}
109e973ffa2Smarkus 	if (r->auth->srcid) {
110befd40c8Sbluhm 		fprintf(fd, SET "[%s]:ID=id-%s force\n", r->p1name,
111e973ffa2Smarkus 		    r->auth->srcid);
112befd40c8Sbluhm 		fprintf(fd, SET "[id-%s]:ID-type=%s force\n", r->auth->srcid,
1132281ca6dSmarkus 		    ike_id_types[r->auth->srcid_type]);
1147d4bf23dSjsing 		if (r->auth->srcid_type == ID_IPV4 ||
1157d4bf23dSjsing 		    r->auth->srcid_type == ID_IPV6)
1167d4bf23dSjsing 			fprintf(fd, SET "[id-%s]:Address=%s force\n",
1177d4bf23dSjsing 			    r->auth->srcid, r->auth->srcid);
1187d4bf23dSjsing 		else
1197d4bf23dSjsing 			fprintf(fd, SET "[id-%s]:Name=%s force\n",
1207d4bf23dSjsing 			    r->auth->srcid, r->auth->srcid);
12190bd57a7Shshoexer 	}
122e973ffa2Smarkus 	if (r->auth->dstid) {
123befd40c8Sbluhm 		fprintf(fd, SET "[%s]:Remote-ID=id-%s force\n", r->p1name,
124e973ffa2Smarkus 		    r->auth->dstid);
125befd40c8Sbluhm 		fprintf(fd, SET "[id-%s]:ID-type=%s force\n", r->auth->dstid,
1262281ca6dSmarkus 		    ike_id_types[r->auth->dstid_type]);
1277d4bf23dSjsing 		if (r->auth->dstid_type == ID_IPV4 ||
1287d4bf23dSjsing 		    r->auth->dstid_type == ID_IPV6)
1297d4bf23dSjsing 			fprintf(fd, SET "[id-%s]:Address=%s force\n",
1307d4bf23dSjsing 			    r->auth->dstid, r->auth->dstid);
1317d4bf23dSjsing 		else
1327d4bf23dSjsing 			fprintf(fd, SET "[id-%s]:Name=%s force\n",
1337d4bf23dSjsing 			    r->auth->dstid, r->auth->dstid);
1346b1bfcbbShshoexer 	}
13590bd57a7Shshoexer }
13690bd57a7Shshoexer 
13790bd57a7Shshoexer static void
ike_section_ipsec(struct ipsec_rule * r,FILE * fd)138e973ffa2Smarkus ike_section_ipsec(struct ipsec_rule *r, FILE *fd)
13990bd57a7Shshoexer {
140befd40c8Sbluhm 	fprintf(fd, SET "[%s]:Phase=2 force\n", r->p2name);
141befd40c8Sbluhm 	fprintf(fd, SET "[%s]:ISAKMP-peer=%s force\n", r->p2name, r->p1name);
142befd40c8Sbluhm 	fprintf(fd, SET "[%s]:Configuration=phase2-%s force\n", r->p2name,
143e973ffa2Smarkus 	    r->p2name);
144befd40c8Sbluhm 	fprintf(fd, SET "[%s]:Local-ID=%s force\n", r->p2name, r->p2lid);
145c471c043Smpf 	if (r->p2nid)
146c471c043Smpf 		fprintf(fd, SET "[%s]:NAT-ID=%s force\n", r->p2name, r->p2nid);
147befd40c8Sbluhm 	fprintf(fd, SET "[%s]:Remote-ID=%s force\n", r->p2name, r->p2rid);
148aa920ac7Sreyk 
149e973ffa2Smarkus 	if (r->tag)
150befd40c8Sbluhm 		fprintf(fd, SET "[%s]:PF-Tag=%s force\n", r->p2name, r->tag);
151*8fd570bdSdlg 	if (r->flags & IPSEC_RULE_F_IFACE) {
152*8fd570bdSdlg 		fprintf(fd, SET "[%s]:Interface=%u force\n", r->p2name,
153*8fd570bdSdlg 		    r->iface);
154*8fd570bdSdlg 	}
15590bd57a7Shshoexer }
15690bd57a7Shshoexer 
15790bd57a7Shshoexer static int
ike_section_p2(struct ipsec_rule * r,FILE * fd)158e973ffa2Smarkus ike_section_p2(struct ipsec_rule *r, FILE *fd)
15990bd57a7Shshoexer {
1609e3efefdSmarkus 	char	*exchange_type, *key_length, *transform, *p;
1613d13b9d5Smarkus 	char	*enc_alg, *auth_alg, *group_desc, *encap;
162783454c1Smikeb 	int	needauth = 1;
1639e3efefdSmarkus 	int	num_print = 0;
164336f7f89Smcbride 
165e973ffa2Smarkus 	switch (r->p2ie) {
166336f7f89Smcbride 	case IKE_QM:
167336f7f89Smcbride 		exchange_type = "QUICK_MODE";
168336f7f89Smcbride 		break;
169336f7f89Smcbride 	default:
170e973ffa2Smarkus 		warnx("illegal phase 2 ike mode %d", r->p2ie);
171336f7f89Smcbride 		return (-1);
172336f7f89Smcbride 	}
173336f7f89Smcbride 
174befd40c8Sbluhm 	fprintf(fd, SET "[phase2-%s]:EXCHANGE_TYPE=%s force\n", r->p2name,
175e973ffa2Smarkus 	    exchange_type);
17645afb999Smikeb 	fprintf(fd, SET "[phase2-%s]:Suites=phase2-suite-%s force\n", r->p2name,
17745afb999Smikeb 	    r->p2name);
17845afb999Smikeb 
17945afb999Smikeb 	fprintf(fd, SET "[phase2-suite-%s]:Protocols=phase2-protocol-%s "
18045afb999Smikeb 	    "force\n", r->p2name, r->p2name);
18145afb999Smikeb 
18245afb999Smikeb 	fprintf(fd, SET "[phase2-protocol-%s]:PROTOCOL_ID=", r->p2name);
18390bd57a7Shshoexer 
184e973ffa2Smarkus 	switch (r->satype) {
18590bd57a7Shshoexer 	case IPSEC_ESP:
18645afb999Smikeb 		fprintf(fd, "IPSEC_ESP");
18790bd57a7Shshoexer 		break;
18811a1b5c9Snaddy 	case IPSEC_AH:
18945afb999Smikeb 		fprintf(fd, "IPSEC_AH");
19011a1b5c9Snaddy 		break;
19190bd57a7Shshoexer 	default:
192e973ffa2Smarkus 		warnx("illegal satype %d", r->satype);
19390bd57a7Shshoexer 		return (-1);
1947d8a4c88Sderaadt 	}
19545afb999Smikeb 	fprintf(fd, " force\n");
19690bd57a7Shshoexer 
19745afb999Smikeb 	key_length = NULL;
1983d13b9d5Smarkus 	enc_alg = NULL;
199e973ffa2Smarkus 	if (r->p2xfs && r->p2xfs->encxf) {
200e973ffa2Smarkus 		if (r->satype == IPSEC_ESP) {
201e973ffa2Smarkus 			switch (r->p2xfs->encxf->id) {
20290bd57a7Shshoexer 			case ENCXF_3DES_CBC:
2033d13b9d5Smarkus 				enc_alg = "3DES";
20490bd57a7Shshoexer 				break;
20590bd57a7Shshoexer 			case ENCXF_AES:
2063d13b9d5Smarkus 				enc_alg = "AES";
20745afb999Smikeb 				key_length = "128,128:256";
20890bd57a7Shshoexer 				break;
209a407e450Shshoexer 			case ENCXF_AES_128:
2103d13b9d5Smarkus 				enc_alg = "AES";
21145afb999Smikeb 				key_length = "128,128:128";
212a407e450Shshoexer 				break;
213a407e450Shshoexer 			case ENCXF_AES_192:
2143d13b9d5Smarkus 				enc_alg = "AES";
21545afb999Smikeb 				key_length = "192,192:192";
216a407e450Shshoexer 				break;
217a407e450Shshoexer 			case ENCXF_AES_256:
2183d13b9d5Smarkus 				enc_alg = "AES";
21945afb999Smikeb 				key_length = "256,256:256";
220a407e450Shshoexer 				break;
22129dc0946Snaddy 			case ENCXF_AESCTR:
2223d13b9d5Smarkus 				enc_alg = "AES_CTR";
22345afb999Smikeb 				key_length = "128,128:128";
22429dc0946Snaddy 				break;
2255f649d51Snaddy 			case ENCXF_AES_128_CTR:
2263d13b9d5Smarkus 				enc_alg = "AES_CTR";
22745afb999Smikeb 				key_length = "128,128:128";
2285f649d51Snaddy 				break;
2295f649d51Snaddy 			case ENCXF_AES_192_CTR:
2303d13b9d5Smarkus 				enc_alg = "AES_CTR";
23145afb999Smikeb 				key_length = "192,192:192";
2325f649d51Snaddy 				break;
2335f649d51Snaddy 			case ENCXF_AES_256_CTR:
2343d13b9d5Smarkus 				enc_alg = "AES_CTR";
23545afb999Smikeb 				key_length = "256,256:256";
2365f649d51Snaddy 				break;
237783454c1Smikeb 			case ENCXF_AES_128_GCM:
2383d13b9d5Smarkus 				enc_alg = "AES_GCM_16";
23945afb999Smikeb 				key_length = "128,128:128";
240783454c1Smikeb 				needauth = 0;
241783454c1Smikeb 				break;
242783454c1Smikeb 			case ENCXF_AES_192_GCM:
2433d13b9d5Smarkus 				enc_alg = "AES_GCM_16";
24445afb999Smikeb 				key_length = "192,192:192";
245783454c1Smikeb 				needauth = 0;
246783454c1Smikeb 				break;
247783454c1Smikeb 			case ENCXF_AES_256_GCM:
2483d13b9d5Smarkus 				enc_alg = "AES_GCM_16";
24945afb999Smikeb 				key_length = "256,256:256";
250783454c1Smikeb 				needauth = 0;
251783454c1Smikeb 				break;
252783454c1Smikeb 			case ENCXF_AES_128_GMAC:
2533d13b9d5Smarkus 				enc_alg = "AES_GMAC";
25445afb999Smikeb 				key_length = "128,128:128";
255783454c1Smikeb 				needauth = 0;
256783454c1Smikeb 				break;
257783454c1Smikeb 			case ENCXF_AES_192_GMAC:
2583d13b9d5Smarkus 				enc_alg = "AES_GMAC";
25945afb999Smikeb 				key_length = "192,192:192";
260783454c1Smikeb 				needauth = 0;
261783454c1Smikeb 				break;
262783454c1Smikeb 			case ENCXF_AES_256_GMAC:
2633d13b9d5Smarkus 				enc_alg = "AES_GMAC";
26445afb999Smikeb 				key_length = "256,256:256";
265783454c1Smikeb 				needauth = 0;
266783454c1Smikeb 				break;
26790bd57a7Shshoexer 			case ENCXF_BLOWFISH:
2683d13b9d5Smarkus 				enc_alg = "BLOWFISH";
26945afb999Smikeb 				key_length = "128,96:192";
27090bd57a7Shshoexer 				break;
27190bd57a7Shshoexer 			case ENCXF_CAST128:
2723d13b9d5Smarkus 				enc_alg = "CAST";
27390bd57a7Shshoexer 				break;
2741b45164bShshoexer 			case ENCXF_NULL:
2753d13b9d5Smarkus 				enc_alg = "NULL";
276783454c1Smikeb 				needauth = 0;
2771b45164bShshoexer 				break;
27890bd57a7Shshoexer 			default:
27911a1b5c9Snaddy 				warnx("illegal transform %s",
280e973ffa2Smarkus 				    r->p2xfs->encxf->name);
28111a1b5c9Snaddy 				return (-1);
28211a1b5c9Snaddy 			}
28311a1b5c9Snaddy 		} else {
284e973ffa2Smarkus 			warnx("illegal transform %s", r->p2xfs->encxf->name);
28590bd57a7Shshoexer 			return (-1);
2867d8a4c88Sderaadt 		}
28745afb999Smikeb 	} else if (r->satype == IPSEC_ESP) {
2883d13b9d5Smarkus 		enc_alg = "AES";
2893d13b9d5Smarkus 		key_length = "128,128:256";
29045afb999Smikeb 	}
29145afb999Smikeb 
29245afb999Smikeb 	switch (r->tmode) {
29345afb999Smikeb 	case IPSEC_TUNNEL:
2943d13b9d5Smarkus 		encap = "TUNNEL";
29545afb999Smikeb 		break;
29645afb999Smikeb 	case IPSEC_TRANSPORT:
2973d13b9d5Smarkus 		encap = "TRANSPORT";
29845afb999Smikeb 		break;
29945afb999Smikeb 	default:
30045afb999Smikeb 		warnx("illegal encapsulation mode %d", r->tmode);
30145afb999Smikeb 		return (-1);
30245afb999Smikeb 	}
30345afb999Smikeb 
3043d13b9d5Smarkus 	auth_alg = NULL;
305e973ffa2Smarkus 	if (r->p2xfs && r->p2xfs->authxf) {
306e973ffa2Smarkus 		switch (r->p2xfs->authxf->id) {
30790bd57a7Shshoexer 		case AUTHXF_HMAC_MD5:
3083d13b9d5Smarkus 			auth_alg = "MD5";
30990bd57a7Shshoexer 			break;
31090bd57a7Shshoexer 		case AUTHXF_HMAC_SHA1:
3113d13b9d5Smarkus 			auth_alg = "SHA";
31290bd57a7Shshoexer 			break;
31390bd57a7Shshoexer 		case AUTHXF_HMAC_RIPEMD160:
3143d13b9d5Smarkus 			auth_alg = "RIPEMD";
31590bd57a7Shshoexer 			break;
31690bd57a7Shshoexer 		case AUTHXF_HMAC_SHA2_256:
3173d13b9d5Smarkus 			auth_alg = "SHA2_256";
31890bd57a7Shshoexer 			break;
31990bd57a7Shshoexer 		case AUTHXF_HMAC_SHA2_384:
3203d13b9d5Smarkus 			auth_alg = "SHA2_384";
32190bd57a7Shshoexer 			break;
32290bd57a7Shshoexer 		case AUTHXF_HMAC_SHA2_512:
3233d13b9d5Smarkus 			auth_alg = "SHA2_512";
32490bd57a7Shshoexer 			break;
32590bd57a7Shshoexer 		default:
326e973ffa2Smarkus 			warnx("illegal transform %s", r->p2xfs->authxf->name);
32790bd57a7Shshoexer 			return (-1);
3287d8a4c88Sderaadt 		}
3293d13b9d5Smarkus 	} else if (needauth)
3303d13b9d5Smarkus 		auth_alg = "SHA2_256";
331791b89f7Shshoexer 
3323d13b9d5Smarkus 	group_desc = NULL;
333e973ffa2Smarkus 	if (r->p2xfs && r->p2xfs->groupxf) {
334e973ffa2Smarkus 		switch (r->p2xfs->groupxf->id) {
3353d13b9d5Smarkus 		case GROUPXF_NONE:
3363d13b9d5Smarkus 			break;
33726c588ccSmpi 		case GROUPXF_1:
3383d13b9d5Smarkus 			group_desc = "MODP_768";
339791b89f7Shshoexer 			break;
34026c588ccSmpi 		case GROUPXF_2:
3413d13b9d5Smarkus 			group_desc = "MODP_1024";
342791b89f7Shshoexer 			break;
34326c588ccSmpi 		case GROUPXF_5:
3443d13b9d5Smarkus 			group_desc = "MODP_1536";
345791b89f7Shshoexer 			break;
34626c588ccSmpi 		case GROUPXF_14:
3473d13b9d5Smarkus 			group_desc = "MODP_2048";
348791b89f7Shshoexer 			break;
34926c588ccSmpi 		case GROUPXF_15:
3503d13b9d5Smarkus 			group_desc = "MODP_3072";
351791b89f7Shshoexer 			break;
35226c588ccSmpi 		case GROUPXF_16:
3533d13b9d5Smarkus 			group_desc = "MODP_4096";
354791b89f7Shshoexer 			break;
35526c588ccSmpi 		case GROUPXF_17:
3563d13b9d5Smarkus 			group_desc = "MODP_6144";
357791b89f7Shshoexer 			break;
35826c588ccSmpi 		case GROUPXF_18:
3593d13b9d5Smarkus 			group_desc = "MODP_8192";
360791b89f7Shshoexer 			break;
36126c588ccSmpi 		case GROUPXF_19:
36226c588ccSmpi 			group_desc = "ECP_256";
36326c588ccSmpi 			break;
36426c588ccSmpi 		case GROUPXF_20:
36526c588ccSmpi 			group_desc = "ECP_384";
36626c588ccSmpi 			break;
36726c588ccSmpi 		case GROUPXF_21:
36826c588ccSmpi 			group_desc = "ECP_521";
36926c588ccSmpi 			break;
37026c588ccSmpi 		case GROUPXF_25:
37126c588ccSmpi 			group_desc = "ECP_192";
37226c588ccSmpi 			break;
37326c588ccSmpi 		case GROUPXF_26:
37426c588ccSmpi 			group_desc = "ECP_224";
37526c588ccSmpi 			break;
37626c588ccSmpi 		case GROUPXF_27:
37726c588ccSmpi 			group_desc = "BP_224";
37826c588ccSmpi 			break;
37926c588ccSmpi 		case GROUPXF_28:
38026c588ccSmpi 			group_desc = "BP_256";
38126c588ccSmpi 			break;
38226c588ccSmpi 		case GROUPXF_29:
38326c588ccSmpi 			group_desc = "BP_384";
38426c588ccSmpi 			break;
38526c588ccSmpi 		case GROUPXF_30:
38626c588ccSmpi 			group_desc = "BP_512";
38726c588ccSmpi 			break;
388791b89f7Shshoexer 		default:
3893d13b9d5Smarkus 			warnx("illegal group %s", r->p2xfs->groupxf->name);
390791b89f7Shshoexer 			return (-1);
3916fb51547Snaddy 		}
392e28b14aaShshoexer 	} else
393bf14ca98Snaddy 		group_desc = "MODP_3072";
3943d13b9d5Smarkus 
3959e3efefdSmarkus 	/* the transform name must not include "," */
3969e3efefdSmarkus 	if (key_length && (p = strchr(key_length, ',')) != NULL)
3979e3efefdSmarkus 		num_print = p - key_length;
3983d13b9d5Smarkus 	/*
3993d13b9d5Smarkus 	 * create a unique transform name, otherwise we cannot have
4003d13b9d5Smarkus 	 * multiple transforms per p2name.
4013d13b9d5Smarkus 	 */
4029e3efefdSmarkus 	if (asprintf(&transform, "phase2-transform-%s-%s%.*s-%s-%s-%s",
4033d13b9d5Smarkus 	    r->p2name,
4043d13b9d5Smarkus 	    enc_alg ? enc_alg : "NONE",
4059e3efefdSmarkus 	    num_print, key_length ? key_length : "",
4063d13b9d5Smarkus 	    auth_alg ? auth_alg : "NONE",
4073d13b9d5Smarkus 	    group_desc ? group_desc : "NONE",
4083d13b9d5Smarkus 	    encap) == -1)
4093d13b9d5Smarkus 		errx(1, "asprintf phase2-transform");
4103d13b9d5Smarkus 
4113d13b9d5Smarkus 	fprintf(fd, SET "[phase2-protocol-%s]:Transforms=%s force\n",
4123d13b9d5Smarkus 	    r->p2name, transform);
4133d13b9d5Smarkus 
4143d13b9d5Smarkus 	fprintf(fd, SET "[%s]:TRANSFORM_ID=%s force\n", transform,
4153d13b9d5Smarkus 	    r->satype == IPSEC_AH ?  auth_alg : enc_alg);
4163d13b9d5Smarkus 	if (key_length)
4173d13b9d5Smarkus 		fprintf(fd, SET "[%s]:KEY_LENGTH=%s force\n", transform,
4183d13b9d5Smarkus 		    key_length);
4193d13b9d5Smarkus 	fprintf(fd, SET "[%s]:ENCAPSULATION_MODE=%s force\n", transform, encap);
4203d13b9d5Smarkus 	if (auth_alg)
4213d13b9d5Smarkus 		fprintf(fd, SET "[%s]:AUTHENTICATION_ALGORITHM=HMAC_%s force\n",
4223d13b9d5Smarkus 		    transform, auth_alg);
4233d13b9d5Smarkus 	if (group_desc)
4243d13b9d5Smarkus 		fprintf(fd, SET "[%s]:GROUP_DESCRIPTION=%s force\n", transform,
4253d13b9d5Smarkus 		    group_desc);
42645afb999Smikeb 
42745afb999Smikeb 	if (r->p2life && r->p2life->lt_seconds != -1) {
4283d13b9d5Smarkus 		fprintf(fd, SET "[%s]:Life=%s-life force\n",
4293d13b9d5Smarkus 		    transform, transform);
4303d13b9d5Smarkus 		fprintf(fd, SET "[%s-life]:LIFE_TYPE=SECONDS force\n",
4313d13b9d5Smarkus 		    transform);
4323d13b9d5Smarkus 		fprintf(fd, SET "[%s-life]:LIFE_DURATION=%d force\n",
4333d13b9d5Smarkus 		    transform, r->p2life->lt_seconds);
43445afb999Smikeb 	} else
4353d13b9d5Smarkus 		fprintf(fd, SET "[%s]:Life=LIFE_QUICK_MODE force\n",
4363d13b9d5Smarkus 		    transform);
43790bd57a7Shshoexer 
4383d13b9d5Smarkus 	free(transform);
43990bd57a7Shshoexer 	return (0);
44090bd57a7Shshoexer }
44190bd57a7Shshoexer 
44290bd57a7Shshoexer static int
ike_section_p1(struct ipsec_rule * r,FILE * fd)443e973ffa2Smarkus ike_section_p1(struct ipsec_rule *r, FILE *fd)
44490bd57a7Shshoexer {
4459e3efefdSmarkus 	char	*exchange_type, *key_length, *transform, *p;
4463d13b9d5Smarkus 	char	*enc_alg, *auth_alg, *group_desc, *auth_method;
4479e3efefdSmarkus 	int	num_print = 0;
448336f7f89Smcbride 
449e973ffa2Smarkus 	switch (r->p1ie) {
450336f7f89Smcbride 	case IKE_MM:
451336f7f89Smcbride 		exchange_type = "ID_PROT";
452336f7f89Smcbride 		break;
453336f7f89Smcbride 	case IKE_AM:
454336f7f89Smcbride 		exchange_type = "AGGRESSIVE";
455336f7f89Smcbride 		break;
456336f7f89Smcbride 	default:
457e8ddbae1Slteo 		warnx("illegal phase 1 ike mode %d", r->p1ie);
458336f7f89Smcbride 		return (-1);
4597bed6a8bShshoexer 	}
46090bd57a7Shshoexer 
461befd40c8Sbluhm 	fprintf(fd, SET "[%s]:Configuration=phase1-%s force\n", r->p1name,
462befd40c8Sbluhm 	    r->p1name);
463befd40c8Sbluhm 	fprintf(fd, SET "[phase1-%s]:EXCHANGE_TYPE=%s force\n", r->p1name,
464befd40c8Sbluhm 	    exchange_type);
465336f7f89Smcbride 
46645afb999Smikeb 	key_length = NULL;
467e973ffa2Smarkus 	if (r->p1xfs && r->p1xfs->encxf) {
468e973ffa2Smarkus 		switch (r->p1xfs->encxf->id) {
46990bd57a7Shshoexer 		case ENCXF_3DES_CBC:
4703d13b9d5Smarkus 			enc_alg = "3DES";
47190bd57a7Shshoexer 			break;
47290bd57a7Shshoexer 		case ENCXF_AES:
4733d13b9d5Smarkus 			enc_alg = "AES";
47445afb999Smikeb 			key_length = "128,128:256";
47590bd57a7Shshoexer 			break;
476a407e450Shshoexer 		case ENCXF_AES_128:
4773d13b9d5Smarkus 			enc_alg = "AES";
47845afb999Smikeb 			key_length = "128,128:128";
479a407e450Shshoexer 			break;
480a407e450Shshoexer 		case ENCXF_AES_192:
4813d13b9d5Smarkus 			enc_alg = "AES";
48245afb999Smikeb 			key_length = "192,192:192";
483a407e450Shshoexer 			break;
484a407e450Shshoexer 		case ENCXF_AES_256:
4853d13b9d5Smarkus 			enc_alg = "AES";
48645afb999Smikeb 			key_length = "256,256:256";
487a407e450Shshoexer 			break;
48890bd57a7Shshoexer 		case ENCXF_BLOWFISH:
4893d13b9d5Smarkus 			enc_alg = "BLOWFISH";
49045afb999Smikeb 			key_length = "128,96:192";
49190bd57a7Shshoexer 			break;
49290bd57a7Shshoexer 		case ENCXF_CAST128:
4933d13b9d5Smarkus 			enc_alg = "CAST";
49490bd57a7Shshoexer 			break;
49590bd57a7Shshoexer 		default:
496e973ffa2Smarkus 			warnx("illegal transform %s", r->p1xfs->encxf->name);
49790bd57a7Shshoexer 			return (-1);
4987d8a4c88Sderaadt 		}
49945afb999Smikeb 	} else {
5003d13b9d5Smarkus 		enc_alg = "AES";
50145afb999Smikeb 		key_length = "128,128:256";
50245afb999Smikeb 	}
50390bd57a7Shshoexer 
504e973ffa2Smarkus 	if (r->p1xfs && r->p1xfs->authxf) {
505e973ffa2Smarkus 		switch (r->p1xfs->authxf->id) {
50690bd57a7Shshoexer 		case AUTHXF_HMAC_MD5:
5073d13b9d5Smarkus 			auth_alg = "MD5";
50890bd57a7Shshoexer 			break;
50990bd57a7Shshoexer 		case AUTHXF_HMAC_SHA1:
5103d13b9d5Smarkus 			auth_alg = "SHA";
51190bd57a7Shshoexer 			break;
51229dc0946Snaddy 		case AUTHXF_HMAC_SHA2_256:
5133d13b9d5Smarkus 			auth_alg = "SHA2_256";
51429dc0946Snaddy 			break;
51529dc0946Snaddy 		case AUTHXF_HMAC_SHA2_384:
5163d13b9d5Smarkus 			auth_alg = "SHA2_384";
51729dc0946Snaddy 			break;
51829dc0946Snaddy 		case AUTHXF_HMAC_SHA2_512:
5193d13b9d5Smarkus 			auth_alg = "SHA2_512";
52029dc0946Snaddy 			break;
52190bd57a7Shshoexer 		default:
522e973ffa2Smarkus 			warnx("illegal transform %s", r->p1xfs->authxf->name);
52390bd57a7Shshoexer 			return (-1);
5247d8a4c88Sderaadt 		}
52590bd57a7Shshoexer 	} else
5263d13b9d5Smarkus 		auth_alg = "SHA";
527791b89f7Shshoexer 
528e973ffa2Smarkus 	if (r->p1xfs && r->p1xfs->groupxf) {
529e973ffa2Smarkus 		switch (r->p1xfs->groupxf->id) {
53026c588ccSmpi 		case GROUPXF_1:
5313d13b9d5Smarkus 			group_desc = "MODP_768";
532791b89f7Shshoexer 			break;
53326c588ccSmpi 		case GROUPXF_2:
5343d13b9d5Smarkus 			group_desc = "MODP_1024";
535791b89f7Shshoexer 			break;
53626c588ccSmpi 		case GROUPXF_5:
5373d13b9d5Smarkus 			group_desc = "MODP_1536";
538791b89f7Shshoexer 			break;
53926c588ccSmpi 		case GROUPXF_14:
5403d13b9d5Smarkus 			group_desc = "MODP_2048";
541791b89f7Shshoexer 			break;
54226c588ccSmpi 		case GROUPXF_15:
5433d13b9d5Smarkus 			group_desc = "MODP_3072";
544791b89f7Shshoexer 			break;
54526c588ccSmpi 		case GROUPXF_16:
5463d13b9d5Smarkus 			group_desc = "MODP_4096";
547791b89f7Shshoexer 			break;
54826c588ccSmpi 		case GROUPXF_17:
5493d13b9d5Smarkus 			group_desc = "MODP_6144";
550791b89f7Shshoexer 			break;
55126c588ccSmpi 		case GROUPXF_18:
5523d13b9d5Smarkus 			group_desc = "MODP_8192";
553791b89f7Shshoexer 			break;
55426c588ccSmpi 		case GROUPXF_19:
55526c588ccSmpi 			group_desc = "ECP_256";
55626c588ccSmpi 			break;
55726c588ccSmpi 		case GROUPXF_20:
55826c588ccSmpi 			group_desc = "ECP_384";
55926c588ccSmpi 			break;
56026c588ccSmpi 		case GROUPXF_21:
56126c588ccSmpi 			group_desc = "ECP_521";
56226c588ccSmpi 			break;
56326c588ccSmpi 		case GROUPXF_25:
56426c588ccSmpi 			group_desc = "ECP_192";
56526c588ccSmpi 			break;
56626c588ccSmpi 		case GROUPXF_26:
56726c588ccSmpi 			group_desc = "ECP_224";
56826c588ccSmpi 			break;
56926c588ccSmpi 		case GROUPXF_27:
57026c588ccSmpi 			group_desc = "BP_224";
57126c588ccSmpi 			break;
57226c588ccSmpi 		case GROUPXF_28:
57326c588ccSmpi 			group_desc = "BP_256";
57426c588ccSmpi 			break;
57526c588ccSmpi 		case GROUPXF_29:
57626c588ccSmpi 			group_desc = "BP_384";
57726c588ccSmpi 			break;
57826c588ccSmpi 		case GROUPXF_30:
57926c588ccSmpi 			group_desc = "BP_512";
58026c588ccSmpi 			break;
581791b89f7Shshoexer 		default:
582e973ffa2Smarkus 			warnx("illegal group %s", r->p1xfs->groupxf->name);
583791b89f7Shshoexer 			return (-1);
58426c588ccSmpi 		}
58545afb999Smikeb 	} else
586bf14ca98Snaddy 		group_desc = "MODP_3072";
58745afb999Smikeb 
58845afb999Smikeb 	switch (r->ikeauth->type) {
58945afb999Smikeb 	case IKE_AUTH_PSK:
5903d13b9d5Smarkus 		auth_method = "PRE_SHARED";
59145afb999Smikeb 		break;
59245afb999Smikeb 	case IKE_AUTH_RSA:
5933d13b9d5Smarkus 		auth_method = "RSA_SIG";
59445afb999Smikeb 		break;
59545afb999Smikeb 	default:
59645afb999Smikeb 		warnx("illegal authentication method %u", r->ikeauth->type);
59745afb999Smikeb 		return (-1);
59845afb999Smikeb 	}
5993d13b9d5Smarkus 
6009ba86ec5Smikeb 	/* the transform name must not include "," */
6019e3efefdSmarkus 	if (key_length && (p = strchr(key_length, ',')) != NULL)
6029e3efefdSmarkus 		num_print = p - key_length;
6033d13b9d5Smarkus 	/* create unique name for transform, see also ike_section_p2() */
6049e3efefdSmarkus 	if (asprintf(&transform, "phase1-transform-%s-%s-%s-%s%.*s-%s",
6053d13b9d5Smarkus 	    r->p1name, auth_method, auth_alg, enc_alg,
6069e3efefdSmarkus 	    num_print, key_length ? key_length : "",
6073d13b9d5Smarkus 	    group_desc) == -1)
6083d13b9d5Smarkus 		errx(1, "asprintf phase1-transform");
6093d13b9d5Smarkus 
6103d13b9d5Smarkus 	fprintf(fd, ADD "[phase1-%s]:Transforms=%s force\n", r->p1name,
6113d13b9d5Smarkus 	    transform);
6123d13b9d5Smarkus 	fprintf(fd, SET "[%s]:AUTHENTICATION_METHOD=%s force\n", transform,
6133d13b9d5Smarkus 	    auth_method);
6143d13b9d5Smarkus 	fprintf(fd, SET "[%s]:HASH_ALGORITHM=%s force\n", transform, auth_alg);
6153d13b9d5Smarkus 	fprintf(fd, SET "[%s]:ENCRYPTION_ALGORITHM=%s_CBC force\n", transform,
6163d13b9d5Smarkus 	    enc_alg);
6173d13b9d5Smarkus 	if (key_length)
6183d13b9d5Smarkus 		fprintf(fd, SET "[%s]:KEY_LENGTH=%s force\n", transform,
6193d13b9d5Smarkus 		    key_length);
6203d13b9d5Smarkus 	fprintf(fd, SET "[%s]:GROUP_DESCRIPTION=%s force\n", transform,
6213d13b9d5Smarkus 	    group_desc);
62245afb999Smikeb 
62345afb999Smikeb 	if (r->p1life && r->p1life->lt_seconds != -1) {
6243d13b9d5Smarkus 		fprintf(fd, SET "[%s]:Life=%s-life force\n",
6253d13b9d5Smarkus 		    transform, transform);
6263d13b9d5Smarkus 		fprintf(fd, SET "[%s-life]:LIFE_TYPE=SECONDS force\n",
6273d13b9d5Smarkus 		    transform);
6283d13b9d5Smarkus 		fprintf(fd, SET "[%s-life]:LIFE_DURATION=%d force\n",
6293d13b9d5Smarkus 		    transform, r->p1life->lt_seconds);
63045afb999Smikeb 	} else
6313d13b9d5Smarkus 		fprintf(fd, SET "[%s]:Life=LIFE_MAIN_MODE force\n", transform);
63290bd57a7Shshoexer 
6333d13b9d5Smarkus 	free(transform);
63490bd57a7Shshoexer 	return (0);
63590bd57a7Shshoexer }
63690bd57a7Shshoexer 
63790bd57a7Shshoexer static void
ike_section_p2ids_net(struct ipsec_addr * iamask,sa_family_t af,char * name,char * p2xid,FILE * fd)638c471c043Smpf ike_section_p2ids_net(struct ipsec_addr *iamask, sa_family_t af, char *name,
639c471c043Smpf     char *p2xid, FILE *fd)
64090bd57a7Shshoexer {
6419a6fa87bStodd 	char mask[NI_MAXHOST], *network, *p;
642e11b24abStodd 	struct sockaddr_storage sas;
643e11b24abStodd 	struct sockaddr *sa = (struct sockaddr *)&sas;
64490bd57a7Shshoexer 
645e11b24abStodd 	bzero(&sas, sizeof(struct sockaddr_storage));
6469a6fa87bStodd 	bzero(mask, sizeof(mask));
647c471c043Smpf 	sa->sa_family = af;
648c471c043Smpf 	switch (af) {
6499a6fa87bStodd 	case AF_INET:
650e11b24abStodd 		sa->sa_len = sizeof(struct sockaddr_in);
651c471c043Smpf 		bcopy(&iamask->ipa,
652e11b24abStodd 		    &((struct sockaddr_in *)(sa))->sin_addr,
653fd17f7d7Smbuhl 		    sizeof(struct in_addr));
6549a6fa87bStodd 		break;
6559a6fa87bStodd 	case AF_INET6:
656e11b24abStodd 		sa->sa_len = sizeof(struct sockaddr_in6);
657c471c043Smpf 		bcopy(&iamask->ipa,
658e11b24abStodd 		    &((struct sockaddr_in6 *)(sa))->sin6_addr,
6599a6fa87bStodd 		    sizeof(struct in6_addr));
6609a6fa87bStodd 		break;
6619a6fa87bStodd 	}
662e11b24abStodd 	if (getnameinfo(sa, sa->sa_len, mask, sizeof(mask), NULL, 0,
663b0429109Shshoexer 	    NI_NUMERICHOST))
664b0429109Shshoexer 		errx(1, "could not get a numeric mask");
665b0429109Shshoexer 
666c471c043Smpf 	if ((network = strdup(name)) == NULL)
667336f7f89Smcbride 		err(1, "ike_section_p2ids: strdup");
66890bd57a7Shshoexer 	if ((p = strrchr(network, '/')) != NULL)
66990bd57a7Shshoexer 		*p = '\0';
67090bd57a7Shshoexer 
671befd40c8Sbluhm 	fprintf(fd, SET "[%s]:ID-type=IPV%d_ADDR_SUBNET force\n",
672c471c043Smpf 	    p2xid, ((af == AF_INET) ? 4 : 6));
673c471c043Smpf 	fprintf(fd, SET "[%s]:Network=%s force\n", p2xid, network);
674c471c043Smpf 	fprintf(fd, SET "[%s]:Netmask=%s force\n", p2xid, mask);
67590bd57a7Shshoexer 
67690bd57a7Shshoexer 	free(network);
677c471c043Smpf }
678c471c043Smpf 
679c471c043Smpf static void
ike_section_p2ids(struct ipsec_rule * r,FILE * fd)680c471c043Smpf ike_section_p2ids(struct ipsec_rule *r, FILE *fd)
681c471c043Smpf {
682c471c043Smpf 	char *p;
683c471c043Smpf 	struct ipsec_addr_wrap *src = r->src;
684c471c043Smpf 	struct ipsec_addr_wrap *dst = r->dst;
685c471c043Smpf 
686c471c043Smpf 	if (src->netaddress) {
687c471c043Smpf 		ike_section_p2ids_net(&src->mask, src->af, src->name,
688c471c043Smpf 		    r->p2lid, fd);
689c471c043Smpf 	} else {
690c471c043Smpf 		fprintf(fd, SET "[%s]:ID-type=IPV%d_ADDR force\n",
691c471c043Smpf 		    r->p2lid, ((src->af == AF_INET) ? 4 : 6));
692c471c043Smpf 		if ((p = strrchr(src->name, '/')) != NULL)
693c471c043Smpf 			*p = '\0';
694c471c043Smpf 		fprintf(fd, SET "[%s]:Address=%s force\n", r->p2lid,
695c471c043Smpf 		    src->name);
696c471c043Smpf 	}
697c471c043Smpf 
698c471c043Smpf 	if (src->srcnat && src->srcnat->netaddress) {
699c471c043Smpf 		ike_section_p2ids_net(&src->srcnat->mask, src->af, src->srcnat->name,
700c471c043Smpf 		    r->p2nid, fd);
701c471c043Smpf 	} else if (src->srcnat) {
702c471c043Smpf 		fprintf(fd, SET "[%s]:ID-type=IPV%d_ADDR force\n",
703c471c043Smpf 		    r->p2nid, ((src->af == AF_INET) ? 4 : 6));
704c471c043Smpf 		if ((p = strrchr(src->srcnat->name, '/')) != NULL)
705c471c043Smpf 			*p = '\0';
706c471c043Smpf 		fprintf(fd, SET "[%s]:Address=%s force\n", r->p2nid,
707c471c043Smpf 		    src->srcnat->name);
708c471c043Smpf 	}
709c471c043Smpf 
710c471c043Smpf 	if (dst->netaddress) {
711c471c043Smpf 		ike_section_p2ids_net(&dst->mask, dst->af, dst->name,
712c471c043Smpf 		    r->p2rid, fd);
71390bd57a7Shshoexer 	} else {
714befd40c8Sbluhm 		fprintf(fd, SET "[%s]:ID-type=IPV%d_ADDR force\n",
715e973ffa2Smarkus 		    r->p2rid, ((dst->af == AF_INET) ? 4 : 6));
7166377a86fShshoexer 		if ((p = strrchr(dst->name, '/')) != NULL)
7176377a86fShshoexer 			*p = '\0';
718befd40c8Sbluhm 		fprintf(fd, SET "[%s]:Address=%s force\n", r->p2rid,
71990bd57a7Shshoexer 		    dst->name);
72090bd57a7Shshoexer 	}
721e973ffa2Smarkus 	if (r->proto) {
722befd40c8Sbluhm 		fprintf(fd, SET "[%s]:Protocol=%d force\n",
723e973ffa2Smarkus 		    r->p2lid, r->proto);
724befd40c8Sbluhm 		fprintf(fd, SET "[%s]:Protocol=%d force\n",
72533912aa1Smarkus 		    r->p2rid, r->proto);
7264fad32afSmarkus 	}
727e973ffa2Smarkus 	if (r->sport)
728befd40c8Sbluhm 		fprintf(fd, SET "[%s]:Port=%d force\n", r->p2lid,
729e973ffa2Smarkus 		    ntohs(r->sport));
730e973ffa2Smarkus 	if (r->dport)
731befd40c8Sbluhm 		fprintf(fd, SET "[%s]:Port=%d force\n", r->p2rid,
732e973ffa2Smarkus 		    ntohs(r->dport));
73390bd57a7Shshoexer }
73490bd57a7Shshoexer 
73590bd57a7Shshoexer static int
ike_connect(struct ipsec_rule * r,FILE * fd)736e973ffa2Smarkus ike_connect(struct ipsec_rule *r, FILE *fd)
73790bd57a7Shshoexer {
738e973ffa2Smarkus 	switch (r->ikemode) {
73990bd57a7Shshoexer 	case IKE_ACTIVE:
740101a3da2Sreyk 	case IKE_DYNAMIC:
741befd40c8Sbluhm 		fprintf(fd, ADD "[Phase 2]:Connections=%s\n", r->p2name);
74290bd57a7Shshoexer 		break;
74390bd57a7Shshoexer 	case IKE_PASSIVE:
744befd40c8Sbluhm 		fprintf(fd, ADD "[Phase 2]:Passive-Connections=%s\n",
745e973ffa2Smarkus 		    r->p2name);
74690bd57a7Shshoexer 		break;
74790bd57a7Shshoexer 	default:
74890bd57a7Shshoexer 		return (-1);
74990bd57a7Shshoexer 	}
75090bd57a7Shshoexer 	return (0);
75190bd57a7Shshoexer }
75290bd57a7Shshoexer 
75390bd57a7Shshoexer static int
ike_gen_config(struct ipsec_rule * r,FILE * fd)75490bd57a7Shshoexer ike_gen_config(struct ipsec_rule *r, FILE *fd)
75590bd57a7Shshoexer {
7568838d2fdSmsf 	ike_setup_ids(r);
757101a3da2Sreyk 	ike_section_general(r, fd);
758e973ffa2Smarkus 	ike_section_peer(r, fd);
759e973ffa2Smarkus 	if (ike_section_p1(r, fd) == -1) {
76090bd57a7Shshoexer 		return (-1);
761e973ffa2Smarkus 	}
762e973ffa2Smarkus 	ike_section_ids(r, fd);
763e973ffa2Smarkus 	ike_section_ipsec(r, fd);
764e973ffa2Smarkus 	if (ike_section_p2(r, fd) == -1) {
76590bd57a7Shshoexer 		return (-1);
766e973ffa2Smarkus 	}
767e973ffa2Smarkus 	ike_section_p2ids(r, fd);
76890bd57a7Shshoexer 
769e973ffa2Smarkus 	if (ike_connect(r, fd) == -1)
77090bd57a7Shshoexer 		return (-1);
77190bd57a7Shshoexer 	return (0);
77290bd57a7Shshoexer }
77390bd57a7Shshoexer 
77490bd57a7Shshoexer static int
ike_delete_config(struct ipsec_rule * r,FILE * fd)77590bd57a7Shshoexer ike_delete_config(struct ipsec_rule *r, FILE *fd)
77690bd57a7Shshoexer {
7778838d2fdSmsf 	ike_setup_ids(r);
778588332b7Smarkus #if 0
77990bd57a7Shshoexer 	switch (r->ikemode) {
78090bd57a7Shshoexer 	case IKE_ACTIVE:
78115286908Shshoexer 	case IKE_DYNAMIC:
782befd40c8Sbluhm 		fprintf(fd, "t %s\n", r->p2name);
78390bd57a7Shshoexer 		break;
78490bd57a7Shshoexer 	case IKE_PASSIVE:
78590bd57a7Shshoexer 		fprintf(fd, DELETE "[Phase 2]\n");
786befd40c8Sbluhm 		fprintf(fd, "t %s\n", r->p2name);
78790bd57a7Shshoexer 		break;
78890bd57a7Shshoexer 	default:
78990bd57a7Shshoexer 		return (-1);
79090bd57a7Shshoexer 	}
79190bd57a7Shshoexer 
79280b4b8eaShshoexer 	if (r->peer) {
793befd40c8Sbluhm 		fprintf(fd, DELETE "[%s]\n", r->p1name);
794befd40c8Sbluhm 		fprintf(fd, DELETE "[phase1-%s]\n", r->p1name);
79580b4b8eaShshoexer 	}
79690bd57a7Shshoexer 	if (r->auth) {
79790bd57a7Shshoexer 		if (r->auth->srcid)
79890bd57a7Shshoexer 			fprintf(fd, DELETE "[%s-ID]\n", r->auth->srcid);
79990bd57a7Shshoexer 		if (r->auth->dstid)
80090bd57a7Shshoexer 			fprintf(fd, DELETE "[%s-ID]\n", r->auth->dstid);
80190bd57a7Shshoexer 	}
802befd40c8Sbluhm 	fprintf(fd, DELETE "[%s]\n", r->p2name);
803befd40c8Sbluhm 	fprintf(fd, DELETE "[phase2-%s]\n", r->p2name);
804befd40c8Sbluhm 	fprintf(fd, DELETE "[%s]\n", r->p2lid);
805befd40c8Sbluhm 	fprintf(fd, DELETE "[%s]\n", r->p2rid);
806588332b7Smarkus #else
807befd40c8Sbluhm 	fprintf(fd, "t %s\n", r->p2name);
8081d6e9a6eSmarkus 	switch (r->ikemode) {
8091d6e9a6eSmarkus 	case IKE_ACTIVE:
8101d6e9a6eSmarkus 	case IKE_DYNAMIC:
811befd40c8Sbluhm 		fprintf(fd, RMV "[Phase 2]:Connections=%s\n", r->p2name);
8121d6e9a6eSmarkus 		break;
8131d6e9a6eSmarkus 	case IKE_PASSIVE:
814befd40c8Sbluhm 		fprintf(fd, RMV "[Phase 2]:Passive-Connections=%s\n",
8151d6e9a6eSmarkus 		    r->p2name);
8161d6e9a6eSmarkus 		break;
8171d6e9a6eSmarkus 	default:
8181d6e9a6eSmarkus 		return (-1);
8191d6e9a6eSmarkus 	}
820befd40c8Sbluhm 	fprintf(fd, DELETE "[%s]\n", r->p2name);
821befd40c8Sbluhm 	fprintf(fd, DELETE "[phase2-%s]\n", r->p2name);
822588332b7Smarkus #endif
82390bd57a7Shshoexer 
82490bd57a7Shshoexer 	return (0);
82590bd57a7Shshoexer }
82690bd57a7Shshoexer 
827e973ffa2Smarkus static void
ike_setup_ids(struct ipsec_rule * r)828e973ffa2Smarkus ike_setup_ids(struct ipsec_rule *r)
829e973ffa2Smarkus {
830befd40c8Sbluhm 	char sproto[10], ssport[10], sdport[10];
831befd40c8Sbluhm 
832befd40c8Sbluhm 	/* phase 1 name is peer and local address */
833befd40c8Sbluhm 	if (r->peer) {
834befd40c8Sbluhm 		if (r->local) {
835befd40c8Sbluhm 			/* peer-dstaddr-local-srcaddr */
836befd40c8Sbluhm 			if (asprintf(&r->p1name, "peer-%s-local-%s",
837befd40c8Sbluhm 			    r->peer->name, r->local->name) == -1)
838e973ffa2Smarkus 				err(1, "ike_setup_ids");
839befd40c8Sbluhm 		} else
840befd40c8Sbluhm 			/* peer-dstaddr */
841befd40c8Sbluhm 			if (asprintf(&r->p1name, "peer-%s",
842befd40c8Sbluhm 			    r->peer->name) == -1)
843e973ffa2Smarkus 				err(1, "ike_setup_ids");
844befd40c8Sbluhm 	} else
845befd40c8Sbluhm 		if ((r->p1name = strdup("peer-default")) == NULL)
846e973ffa2Smarkus 			err(1, "ike_setup_ids");
847befd40c8Sbluhm 
848befd40c8Sbluhm 	/* Phase 2 name is from and to network, protocol, port*/
849*8fd570bdSdlg 	if (r->flags & IPSEC_RULE_F_IFACE) {
850*8fd570bdSdlg 		if (asprintf(&r->p2lid, "from-sec%u", r->iface) == -1)
851*8fd570bdSdlg 			err(1, "ike_setup_ids");
852*8fd570bdSdlg 		if (asprintf(&r->p2rid, "to-sec%u", r->iface) == -1)
853*8fd570bdSdlg 			err(1, "ike_setup_ids");
854*8fd570bdSdlg 	} else {
855befd40c8Sbluhm 		sproto[0] = ssport[0] = sdport[0] = 0;
856befd40c8Sbluhm 		if (r->proto)
857befd40c8Sbluhm 			snprintf(sproto, sizeof sproto, "=%u", r->proto);
858befd40c8Sbluhm 		if (r->sport)
859befd40c8Sbluhm 			snprintf(ssport, sizeof ssport, ":%u", ntohs(r->sport));
860befd40c8Sbluhm 		if (r->dport)
861befd40c8Sbluhm 			snprintf(sdport, sizeof sdport, ":%u", ntohs(r->dport));
862*8fd570bdSdlg 
863befd40c8Sbluhm 		/* from-network/masklen=proto:port */
864*8fd570bdSdlg 		if (asprintf(&r->p2lid, "from-%s%s%s", r->src->name,
865*8fd570bdSdlg 		    sproto, ssport) == -1)
866e973ffa2Smarkus 			err(1, "ike_setup_ids");
867befd40c8Sbluhm 		/* to-network/masklen=proto:port */
868*8fd570bdSdlg 		if (asprintf(&r->p2rid, "to-%s%s%s", r->dst->name,
869*8fd570bdSdlg 		    sproto, sdport) == -1)
870e973ffa2Smarkus 			err(1, "ike_setup_ids");
871*8fd570bdSdlg 	}
872*8fd570bdSdlg 
873befd40c8Sbluhm 	/* from-network/masklen=proto:port-to-network/masklen=proto:port */
874e973ffa2Smarkus 	if (asprintf(&r->p2name, "%s-%s", r->p2lid , r->p2rid) == -1)
875e973ffa2Smarkus 		err(1, "ike_setup_ids");
876c471c043Smpf 	/* nat-network/masklen=proto:port */
877c471c043Smpf 	if (r->src->srcnat && r->src->srcnat->name) {
878c471c043Smpf 		if (asprintf(&r->p2nid, "nat-%s%s%s", r->src->srcnat->name, sproto,
879c471c043Smpf 		    ssport) == -1)
880c471c043Smpf 			err(1, "ike_setup_ids");
881c471c043Smpf 	}
882e973ffa2Smarkus }
883e973ffa2Smarkus 
88490bd57a7Shshoexer int
ike_print_config(struct ipsec_rule * r,int opts)88590bd57a7Shshoexer ike_print_config(struct ipsec_rule *r, int opts)
88690bd57a7Shshoexer {
88733a3cc99Shshoexer 	if (opts & IPSECCTL_OPT_DELETE)
88833a3cc99Shshoexer 		return (ike_delete_config(r, stdout));
88933a3cc99Shshoexer 	else
89090bd57a7Shshoexer 		return (ike_gen_config(r, stdout));
89190bd57a7Shshoexer }
89290bd57a7Shshoexer 
89390bd57a7Shshoexer int
ike_ipsec_establish(int action,struct ipsec_rule * r,const char * fifo)894f8738d8bShenning ike_ipsec_establish(int action, struct ipsec_rule *r, const char *fifo)
89590bd57a7Shshoexer {
8966f0500ebShshoexer 	struct stat	 sb;
8976f0500ebShshoexer 	FILE		*fdp;
8986f0500ebShshoexer 	int		 fd, ret = 0;
89990bd57a7Shshoexer 
900f8738d8bShenning 	if ((fd = open(fifo, O_WRONLY)) == -1)
901f8738d8bShenning 		err(1, "ike_ipsec_establish: open(%s)", fifo);
9026f0500ebShshoexer 	if (fstat(fd, &sb) == -1)
903f8738d8bShenning 		err(1, "ike_ipsec_establish: fstat(%s)", fifo);
9046f0500ebShshoexer 	if (!S_ISFIFO(sb.st_mode))
905f8738d8bShenning 		errx(1, "ike_ipsec_establish: %s not a fifo", fifo);
9066f0500ebShshoexer 	if ((fdp = fdopen(fd, "w")) == NULL)
907f8738d8bShenning 		err(1, "ike_ipsec_establish: fdopen(%s)", fifo);
90890bd57a7Shshoexer 
90990bd57a7Shshoexer 	switch (action) {
91090bd57a7Shshoexer 	case ACTION_ADD:
9116f0500ebShshoexer 		ret = ike_gen_config(r, fdp);
91290bd57a7Shshoexer 		break;
91390bd57a7Shshoexer 	case ACTION_DELETE:
9146f0500ebShshoexer 		ret = ike_delete_config(r, fdp);
91590bd57a7Shshoexer 		break;
91690bd57a7Shshoexer 	default:
91790bd57a7Shshoexer 		ret = -1;
91890bd57a7Shshoexer 	}
91990bd57a7Shshoexer 
9206f0500ebShshoexer 	fclose(fdp);
92190bd57a7Shshoexer 	return (ret);
92290bd57a7Shshoexer }
923