| 1 |  |  | /* $OpenBSD: pf_key_v2.c,v 1.197 2015/12/10 17:27:00 mmcc Exp $  */ | 
    
    | 2 |  |  | /* $EOM: pf_key_v2.c,v 1.79 2000/12/12 00:33:19 niklas Exp $	 */ | 
    
    | 3 |  |  |  | 
    
    | 4 |  |  | /* | 
    
    | 5 |  |  |  * Copyright (c) 1999, 2000, 2001 Niklas Hallqvist.  All rights reserved. | 
    
    | 6 |  |  |  * Copyright (c) 1999, 2000, 2001 Angelos D. Keromytis.  All rights reserved. | 
    
    | 7 |  |  |  * Copyright (c) 2001 Håkan Olsson.  All rights reserved. | 
    
    | 8 |  |  |  * | 
    
    | 9 |  |  |  * Redistribution and use in source and binary forms, with or without | 
    
    | 10 |  |  |  * modification, are permitted provided that the following conditions | 
    
    | 11 |  |  |  * are met: | 
    
    | 12 |  |  |  * 1. Redistributions of source code must retain the above copyright | 
    
    | 13 |  |  |  *    notice, this list of conditions and the following disclaimer. | 
    
    | 14 |  |  |  * 2. Redistributions in binary form must reproduce the above copyright | 
    
    | 15 |  |  |  *    notice, this list of conditions and the following disclaimer in the | 
    
    | 16 |  |  |  *    documentation and/or other materials provided with the distribution. | 
    
    | 17 |  |  |  * | 
    
    | 18 |  |  |  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 
    
    | 19 |  |  |  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 
    
    | 20 |  |  |  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 
    
    | 21 |  |  |  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 
    
    | 22 |  |  |  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 
    
    | 23 |  |  |  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
    
    | 24 |  |  |  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
    
    | 25 |  |  |  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
    
    | 26 |  |  |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 
    
    | 27 |  |  |  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
    
    | 28 |  |  |  */ | 
    
    | 29 |  |  |  | 
    
    | 30 |  |  | /* | 
    
    | 31 |  |  |  * This code was written under funding by Ericsson Radio Systems. | 
    
    | 32 |  |  |  */ | 
    
    | 33 |  |  |  | 
    
    | 34 |  |  | #include <sys/types.h> | 
    
    | 35 |  |  | #include <sys/ioctl.h> | 
    
    | 36 |  |  | #include <sys/queue.h> | 
    
    | 37 |  |  | #include <sys/socket.h> | 
    
    | 38 |  |  | #include <sys/time.h> | 
    
    | 39 |  |  | #include <sys/uio.h> | 
    
    | 40 |  |  |  | 
    
    | 41 |  |  | #include <net/pfkeyv2.h> | 
    
    | 42 |  |  | #include <netinet/in.h> | 
    
    | 43 |  |  | #include <netinet/ip_ipsp.h> | 
    
    | 44 |  |  | #include <arpa/inet.h> | 
    
    | 45 |  |  | #include <stdlib.h> | 
    
    | 46 |  |  | #include <poll.h> | 
    
    | 47 |  |  | #include <string.h> | 
    
    | 48 |  |  | #include <unistd.h> | 
    
    | 49 |  |  | #include <pwd.h> | 
    
    | 50 |  |  | #include <errno.h> | 
    
    | 51 |  |  | #include <bitstring.h> | 
    
    | 52 |  |  |  | 
    
    | 53 |  |  | #include "cert.h" | 
    
    | 54 |  |  | #include "conf.h" | 
    
    | 55 |  |  | #include "connection.h" | 
    
    | 56 |  |  | #include "exchange.h" | 
    
    | 57 |  |  | #include "ipsec.h" | 
    
    | 58 |  |  | #include "ipsec_num.h" | 
    
    | 59 |  |  | #include "key.h" | 
    
    | 60 |  |  | #include "log.h" | 
    
    | 61 |  |  | #include "pf_key_v2.h" | 
    
    | 62 |  |  | #include "sa.h" | 
    
    | 63 |  |  | #include "timer.h" | 
    
    | 64 |  |  | #include "transport.h" | 
    
    | 65 |  |  | #include "ui.h" | 
    
    | 66 |  |  | #include "util.h" | 
    
    | 67 |  |  |  | 
    
    | 68 |  |  | #include "policy.h" | 
    
    | 69 |  |  |  | 
    
    | 70 |  |  | #include "udp_encap.h" | 
    
    | 71 |  |  |  | 
    
    | 72 |  |  | #define IN6_IS_ADDR_FULL(a)						\ | 
    
    | 73 |  |  | 	((*(u_int32_t *)(void *)(&(a)->s6_addr[0]) == 0xffffffff) &&	\ | 
    
    | 74 |  |  | 	(*(u_int32_t *)(void *)(&(a)->s6_addr[4]) == 0xffffffff) &&	\ | 
    
    | 75 |  |  | 	(*(u_int32_t *)(void *)(&(a)->s6_addr[8]) == 0xffffffff) &&	\ | 
    
    | 76 |  |  | 	(*(u_int32_t *)(void *)(&(a)->s6_addr[12]) == 0xffffffff)) | 
    
    | 77 |  |  |  | 
    
    | 78 |  |  | #define ADDRESS_MAX sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255" | 
    
    | 79 |  |  |  | 
    
    | 80 |  |  | /* | 
    
    | 81 |  |  |  * PF_KEY v2 always work with 64-bit entities and aligns on 64-bit boundaries. | 
    
    | 82 |  |  |  */ | 
    
    | 83 |  |  | #define PF_KEY_V2_CHUNK 8 | 
    
    | 84 |  |  | #define PF_KEY_V2_ROUND(x)						\ | 
    
    | 85 |  |  | 	(((x) + PF_KEY_V2_CHUNK - 1) & ~(PF_KEY_V2_CHUNK - 1)) | 
    
    | 86 |  |  |  | 
    
    | 87 |  |  | /* How many microseconds we will wait for a reply from the PF_KEY socket.  */ | 
    
    | 88 |  |  | #define PF_KEY_REPLY_TIMEOUT 1000 | 
    
    | 89 |  |  |  | 
    
    | 90 |  |  | struct pf_key_v2_node { | 
    
    | 91 |  |  | 	TAILQ_ENTRY(pf_key_v2_node) link; | 
    
    | 92 |  |  | 	void           *seg; | 
    
    | 93 |  |  | 	size_t		sz; | 
    
    | 94 |  |  | 	int		cnt; | 
    
    | 95 |  |  | 	u_int16_t       type; | 
    
    | 96 |  |  | 	u_int8_t	flags; | 
    
    | 97 |  |  | }; | 
    
    | 98 |  |  |  | 
    
    | 99 |  |  | TAILQ_HEAD(pf_key_v2_msg, pf_key_v2_node); | 
    
    | 100 |  |  |  | 
    
    | 101 |  |  | #define PF_KEY_V2_NODE_MALLOCED 1 | 
    
    | 102 |  |  | #define PF_KEY_V2_NODE_MARK 2 | 
    
    | 103 |  |  |  | 
    
    | 104 |  |  | /* Used to derive "unique" connection identifiers. */ | 
    
    | 105 |  |  | int		connection_seq = 0; | 
    
    | 106 |  |  |  | 
    
    | 107 |  |  | static u_int8_t *pf_key_v2_convert_id(u_int8_t *, int, size_t *, int *); | 
    
    | 108 |  |  | static struct pf_key_v2_msg *pf_key_v2_call(struct pf_key_v2_msg *); | 
    
    | 109 |  |  | static struct pf_key_v2_node *pf_key_v2_find_ext(struct pf_key_v2_msg *, | 
    
    | 110 |  |  | 		    u_int16_t); | 
    
    | 111 |  |  | static void     pf_key_v2_notify(struct pf_key_v2_msg *); | 
    
    | 112 |  |  | static struct pf_key_v2_msg *pf_key_v2_read(u_int32_t); | 
    
    | 113 |  |  | static u_int32_t pf_key_v2_seq(void); | 
    
    | 114 |  |  | static u_int32_t pf_key_v2_write(struct pf_key_v2_msg *); | 
    
    | 115 |  |  | static int      pf_key_v2_remove_conf(char *); | 
    
    | 116 |  |  | static int      pf_key_v2_conf_refhandle(int, char *); | 
    
    | 117 |  |  |  | 
    
    | 118 |  |  | static int      pf_key_v2_conf_refinc(int, char *); | 
    
    | 119 |  |  |  | 
    
    | 120 |  |  | /* The socket to use for PF_KEY interactions.  */ | 
    
    | 121 |  |  | int      pf_key_v2_socket; | 
    
    | 122 |  |  |  | 
    
    | 123 |  |  | static struct pf_key_v2_msg * | 
    
    | 124 |  |  | pf_key_v2_msg_new(struct sadb_msg *msg, int flags) | 
    
    | 125 |  |  | { | 
    
    | 126 |  |  | 	struct pf_key_v2_node *node; | 
    
    | 127 |  |  | 	struct pf_key_v2_msg *ret; | 
    
    | 128 |  |  |  | 
    
    | 129 |  |  | 	node = malloc(sizeof *node); | 
    
    | 130 |  |  | 	if (!node) | 
    
    | 131 |  |  | 		goto cleanup; | 
    
    | 132 |  |  | 	ret = malloc(sizeof *ret); | 
    
    | 133 |  |  | 	if (!ret) | 
    
    | 134 |  |  | 		goto cleanup; | 
    
    | 135 |  |  | 	TAILQ_INIT(ret); | 
    
    | 136 |  |  | 	node->seg = msg; | 
    
    | 137 |  |  | 	node->sz = sizeof *msg; | 
    
    | 138 |  |  | 	node->type = 0; | 
    
    | 139 |  |  | 	node->cnt = 1; | 
    
    | 140 |  |  | 	node->flags = flags; | 
    
    | 141 |  |  | 	TAILQ_INSERT_HEAD(ret, node, link); | 
    
    | 142 |  |  | 	return ret; | 
    
    | 143 |  |  |  | 
    
    | 144 |  |  | cleanup: | 
    
    | 145 |  |  | 	free(node); | 
    
    | 146 |  |  | 	return 0; | 
    
    | 147 |  |  | } | 
    
    | 148 |  |  |  | 
    
    | 149 |  |  | /* Add a SZ sized segment SEG to the PF_KEY message MSG.  */ | 
    
    | 150 |  |  | static int | 
    
    | 151 |  |  | pf_key_v2_msg_add(struct pf_key_v2_msg *msg, struct sadb_ext *ext, int flags) | 
    
    | 152 |  |  | { | 
    
    | 153 |  |  | 	struct pf_key_v2_node *node; | 
    
    | 154 |  |  |  | 
    
    | 155 |  |  | 	node = malloc(sizeof *node); | 
    
    | 156 |  |  | 	if (!node) | 
    
    | 157 |  |  | 		return -1; | 
    
    | 158 |  |  | 	node->seg = ext; | 
    
    | 159 |  |  | 	node->sz = ext->sadb_ext_len * PF_KEY_V2_CHUNK; | 
    
    | 160 |  |  | 	node->type = ext->sadb_ext_type; | 
    
    | 161 |  |  | 	node->flags = flags; | 
    
    | 162 |  |  | 	TAILQ_FIRST(msg)->cnt++; | 
    
    | 163 |  |  | 	TAILQ_INSERT_TAIL(msg, node, link); | 
    
    | 164 |  |  | 	return 0; | 
    
    | 165 |  |  | } | 
    
    | 166 |  |  |  | 
    
    | 167 |  |  | /* Deallocate the PF_KEY message MSG.  */ | 
    
    | 168 |  |  | static void | 
    
    | 169 |  |  | pf_key_v2_msg_free(struct pf_key_v2_msg *msg) | 
    
    | 170 |  |  | { | 
    
    | 171 |  |  | 	struct pf_key_v2_node *np; | 
    
    | 172 |  |  |  | 
    
    | 173 |  |  | 	np = TAILQ_FIRST(msg); | 
    
    | 174 |  |  | 	while (np) { | 
    
    | 175 |  |  | 		TAILQ_REMOVE(msg, np, link); | 
    
    | 176 |  |  | 		if (np->flags & PF_KEY_V2_NODE_MALLOCED) | 
    
    | 177 |  |  | 			free(np->seg); | 
    
    | 178 |  |  | 		free(np); | 
    
    | 179 |  |  | 		np = TAILQ_FIRST(msg); | 
    
    | 180 |  |  | 	} | 
    
    | 181 |  |  | 	free(msg); | 
    
    | 182 |  |  | } | 
    
    | 183 |  |  |  | 
    
    | 184 |  |  | /* Just return a new sequence number.  */ | 
    
    | 185 |  |  | static u_int32_t | 
    
    | 186 |  |  | pf_key_v2_seq(void) | 
    
    | 187 |  |  | { | 
    
    | 188 |  |  | 	static u_int32_t seq = 0; | 
    
    | 189 |  |  |  | 
    
    | 190 |  |  | 	return ++seq; | 
    
    | 191 |  |  | } | 
    
    | 192 |  |  |  | 
    
    | 193 |  |  | /* | 
    
    | 194 |  |  |  * Read a PF_KEY packet with SEQ as the sequence number, looping if necessary. | 
    
    | 195 |  |  |  * If SEQ is zero just read the first message we see, otherwise we queue | 
    
    | 196 |  |  |  * messages up until both the PID and the sequence number match. | 
    
    | 197 |  |  |  */ | 
    
    | 198 |  |  | static struct pf_key_v2_msg * | 
    
    | 199 |  |  | pf_key_v2_read(u_int32_t seq) | 
    
    | 200 |  |  | { | 
    
    | 201 |  |  | 	ssize_t		n; | 
    
    | 202 |  |  | 	u_int8_t       *buf = 0; | 
    
    | 203 |  |  | 	struct pf_key_v2_msg *ret = 0; | 
    
    | 204 |  |  | 	struct sadb_msg *msg; | 
    
    | 205 |  |  | 	struct sadb_msg hdr; | 
    
    | 206 |  |  | 	struct sadb_ext *ext; | 
    
    | 207 |  |  | 	struct timeval	tv; | 
    
    | 208 |  |  | 	struct pollfd	pfd[1]; | 
    
    | 209 |  |  |  | 
    
    | 210 |  |  | 	pfd[0].fd = pf_key_v2_socket; | 
    
    | 211 |  |  | 	pfd[0].events = POLLIN; | 
    
    | 212 |  |  |  | 
    
    | 213 |  |  | 	while (1) { | 
    
    | 214 |  |  | 		/* | 
    
    | 215 |  |  | 		 * If this is a read of a reply we should actually expect the | 
    
    | 216 |  |  | 		 * reply to get lost as PF_KEY is an unreliable service per | 
    
    | 217 |  |  | 		 * the specs. Currently we do this by setting a short timeout, | 
    
    | 218 |  |  | 		 * and if it is not readable in that time, we fail the read. | 
    
    | 219 |  |  | 		 */ | 
    
    | 220 |  |  | 		if (seq) { | 
    
    | 221 |  |  | 			n = poll(pfd, 1, PF_KEY_REPLY_TIMEOUT / 1000); | 
    
    | 222 |  |  | 			if (n == -1) { | 
    
    | 223 |  |  | 				log_error("pf_key_v2_read: poll() failed"); | 
    
    | 224 |  |  | 				goto cleanup; | 
    
    | 225 |  |  | 			} | 
    
    | 226 |  |  | 			if (!n) { | 
    
    | 227 |  |  | 				log_print("pf_key_v2_read: " | 
    
    | 228 |  |  | 				    "no reply from PF_KEY"); | 
    
    | 229 |  |  | 				goto cleanup; | 
    
    | 230 |  |  | 			} | 
    
    | 231 |  |  | 		} | 
    
    | 232 |  |  | 		n = recv(pf_key_v2_socket, &hdr, sizeof hdr, MSG_PEEK); | 
    
    | 233 |  |  | 		if (n == -1) { | 
    
    | 234 |  |  | 			log_error("pf_key_v2_read: recv (%d, ...) failed", | 
    
    | 235 |  |  | 			    pf_key_v2_socket); | 
    
    | 236 |  |  | 			goto cleanup; | 
    
    | 237 |  |  | 		} | 
    
    | 238 |  |  | 		if (n != sizeof hdr) { | 
    
    | 239 |  |  | 			log_error("pf_key_v2_read: recv (%d, ...) " | 
    
    | 240 |  |  | 			    "returned short packet (%lu bytes)", | 
    
    | 241 |  |  | 			    pf_key_v2_socket, (unsigned long) n); | 
    
    | 242 |  |  | 			goto cleanup; | 
    
    | 243 |  |  | 		} | 
    
    | 244 |  |  | 		buf = reallocarray(NULL, hdr.sadb_msg_len, PF_KEY_V2_CHUNK); | 
    
    | 245 |  |  | 		if (!buf) { | 
    
    | 246 |  |  | 			log_error("pf_key_v2_read: reallocarray (%d, %d) failed", | 
    
    | 247 |  |  | 			    hdr.sadb_msg_len, PF_KEY_V2_CHUNK); | 
    
    | 248 |  |  | 			goto cleanup; | 
    
    | 249 |  |  | 		} | 
    
    | 250 |  |  | 		n = hdr.sadb_msg_len * PF_KEY_V2_CHUNK; | 
    
    | 251 |  |  |  | 
    
    | 252 |  |  | 		n = read(pf_key_v2_socket, buf, n); | 
    
    | 253 |  |  | 		if (n == -1) { | 
    
    | 254 |  |  | 			log_error("pf_key_v2_read: read (%d, ...) failed", | 
    
    | 255 |  |  | 				  pf_key_v2_socket); | 
    
    | 256 |  |  | 			goto cleanup; | 
    
    | 257 |  |  | 		} | 
    
    | 258 |  |  | 		if (n != hdr.sadb_msg_len * PF_KEY_V2_CHUNK) { | 
    
    | 259 |  |  | 			log_print("pf_key_v2_read: read (%d, ...) " | 
    
    | 260 |  |  | 			    "returned short packet (%lu bytes)", | 
    
    | 261 |  |  | 			    pf_key_v2_socket, (unsigned long) n); | 
    
    | 262 |  |  | 			goto cleanup; | 
    
    | 263 |  |  | 		} | 
    
    | 264 |  |  | 		LOG_DBG_BUF((LOG_SYSDEP, 80, "pf_key_v2_read: msg", buf, n)); | 
    
    | 265 |  |  |  | 
    
    | 266 |  |  | 		/* We drop all messages that is not what we expect.  */ | 
    
    | 267 |  |  | 		msg = (struct sadb_msg *) buf; | 
    
    | 268 |  |  | 		if (msg->sadb_msg_version != PF_KEY_V2 || | 
    
    | 269 |  |  | 		    (msg->sadb_msg_pid != 0 && | 
    
    | 270 |  |  | 		    msg->sadb_msg_pid != (u_int32_t) getpid())) { | 
    
    | 271 |  |  | 			if (seq) { | 
    
    | 272 |  |  | 				free(buf); | 
    
    | 273 |  |  | 				buf = 0; | 
    
    | 274 |  |  | 				continue; | 
    
    | 275 |  |  | 			} else { | 
    
    | 276 |  |  | 				LOG_DBG((LOG_SYSDEP, 90, "pf_key_v2_read:" | 
    
    | 277 |  |  | 				    "bad version (%d) or PID (%d, mine is " | 
    
    | 278 |  |  | 				    "%ld), ignored", msg->sadb_msg_version, | 
    
    | 279 |  |  | 				    msg->sadb_msg_pid, (long) getpid())); | 
    
    | 280 |  |  | 				goto cleanup; | 
    
    | 281 |  |  | 			} | 
    
    | 282 |  |  | 		} | 
    
    | 283 |  |  | 		/* Parse the message.  */ | 
    
    | 284 |  |  | 		ret = pf_key_v2_msg_new(msg, PF_KEY_V2_NODE_MALLOCED); | 
    
    | 285 |  |  | 		if (!ret) | 
    
    | 286 |  |  | 			goto cleanup; | 
    
    | 287 |  |  | 		buf = 0; | 
    
    | 288 |  |  | 		for (ext = (struct sadb_ext *) (msg + 1); | 
    
    | 289 |  |  | 		    (u_int8_t *) ext - (u_int8_t *) msg < | 
    
    | 290 |  |  | 		    msg->sadb_msg_len * PF_KEY_V2_CHUNK; | 
    
    | 291 |  |  | 		    ext = (struct sadb_ext *) ((u_int8_t *) ext + | 
    
    | 292 |  |  | 		    ext->sadb_ext_len * PF_KEY_V2_CHUNK)) | 
    
    | 293 |  |  | 			pf_key_v2_msg_add(ret, ext, 0); | 
    
    | 294 |  |  |  | 
    
    | 295 |  |  | 		/* | 
    
    | 296 |  |  | 		 * If the message is not the one we are waiting for, queue it | 
    
    | 297 |  |  | 		 * up. | 
    
    | 298 |  |  | 		 */ | 
    
    | 299 |  |  | 		if (seq && (msg->sadb_msg_pid != (u_int32_t) getpid() || | 
    
    | 300 |  |  | 		    msg->sadb_msg_seq != seq)) { | 
    
    | 301 |  |  | 			gettimeofday(&tv, 0); | 
    
    | 302 |  |  | 			timer_add_event("pf_key_v2_notify", | 
    
    | 303 |  |  | 			    (void (*) (void *)) pf_key_v2_notify, ret, &tv); | 
    
    | 304 |  |  | 			ret = 0; | 
    
    | 305 |  |  | 			continue; | 
    
    | 306 |  |  | 		} | 
    
    | 307 |  |  | 		return ret; | 
    
    | 308 |  |  | 	} | 
    
    | 309 |  |  |  | 
    
    | 310 |  |  | cleanup: | 
    
    | 311 |  |  | 	free(buf); | 
    
    | 312 |  |  | 	if (ret) | 
    
    | 313 |  |  | 		pf_key_v2_msg_free(ret); | 
    
    | 314 |  |  | 	return 0; | 
    
    | 315 |  |  | } | 
    
    | 316 |  |  |  | 
    
    | 317 |  |  | /* Write the message in PMSG to the PF_KEY socket.  */ | 
    
    | 318 |  |  | u_int32_t | 
    
    | 319 |  |  | pf_key_v2_write(struct pf_key_v2_msg *pmsg) | 
    
    | 320 |  |  | { | 
    
    | 321 |  |  | 	struct iovec   *iov = 0; | 
    
    | 322 |  |  | 	ssize_t		n; | 
    
    | 323 |  |  | 	size_t		len; | 
    
    | 324 |  |  | 	int		i, cnt = TAILQ_FIRST(pmsg)->cnt; | 
    
    | 325 |  |  | 	char		header[80]; | 
    
    | 326 |  |  | 	struct sadb_msg *msg = TAILQ_FIRST(pmsg)->seg; | 
    
    | 327 |  |  | 	struct pf_key_v2_node *np = TAILQ_FIRST(pmsg); | 
    
    | 328 |  |  |  | 
    
    | 329 |  |  | 	iov = calloc(cnt, sizeof *iov); | 
    
    | 330 |  |  | 	if (!iov) { | 
    
    | 331 |  |  | 		log_error("pf_key_v2_write: malloc (%lu) failed", | 
    
    | 332 |  |  | 		    cnt * (unsigned long) sizeof *iov); | 
    
    | 333 |  |  | 		return 0; | 
    
    | 334 |  |  | 	} | 
    
    | 335 |  |  | 	msg->sadb_msg_version = PF_KEY_V2; | 
    
    | 336 |  |  | 	msg->sadb_msg_errno = 0; | 
    
    | 337 |  |  | 	msg->sadb_msg_reserved = 0; | 
    
    | 338 |  |  | 	msg->sadb_msg_pid = getpid(); | 
    
    | 339 |  |  | 	if (!msg->sadb_msg_seq) | 
    
    | 340 |  |  | 		msg->sadb_msg_seq = pf_key_v2_seq(); | 
    
    | 341 |  |  |  | 
    
    | 342 |  |  | 	/* Compute the iovec segments as well as the message length.  */ | 
    
    | 343 |  |  | 	len = 0; | 
    
    | 344 |  |  | 	for (i = 0; i < cnt; i++) { | 
    
    | 345 |  |  | 		iov[i].iov_base = np->seg; | 
    
    | 346 |  |  | 		len += iov[i].iov_len = np->sz; | 
    
    | 347 |  |  |  | 
    
    | 348 |  |  | 		/* | 
    
    | 349 |  |  | 		 * XXX One can envision setting specific extension fields, | 
    
    | 350 |  |  | 		 * like *_reserved ones here.  For now we require them to be | 
    
    | 351 |  |  | 		 * set by the caller. | 
    
    | 352 |  |  | 		 */ | 
    
    | 353 |  |  |  | 
    
    | 354 |  |  | 		np = TAILQ_NEXT(np, link); | 
    
    | 355 |  |  | 	} | 
    
    | 356 |  |  | 	msg->sadb_msg_len = len / PF_KEY_V2_CHUNK; | 
    
    | 357 |  |  |  | 
    
    | 358 |  |  | 	for (i = 0; i < cnt; i++) { | 
    
    | 359 |  |  | 		snprintf(header, sizeof header, "pf_key_v2_write: iov[%d]", i); | 
    
    | 360 |  |  | 		LOG_DBG_BUF((LOG_SYSDEP, 80, header, | 
    
    | 361 |  |  | 		    (u_int8_t *) iov[i].iov_base, iov[i].iov_len)); | 
    
    | 362 |  |  | 	} | 
    
    | 363 |  |  |  | 
    
    | 364 |  |  | 	do { | 
    
    | 365 |  |  | 		n = writev(pf_key_v2_socket, iov, cnt); | 
    
    | 366 |  |  | 	} while (n == -1 && (errno == EAGAIN || errno == EINTR)); | 
    
    | 367 |  |  | 	if (n == -1) { | 
    
    | 368 |  |  | 		log_error("pf_key_v2_write: writev (%d, %p, %d) failed", | 
    
    | 369 |  |  | 		    pf_key_v2_socket, iov, cnt); | 
    
    | 370 |  |  | 		goto cleanup; | 
    
    | 371 |  |  | 	} | 
    
    | 372 |  |  | 	if ((size_t) n != len) { | 
    
    | 373 |  |  | 		log_error("pf_key_v2_write: " | 
    
    | 374 |  |  | 		    "writev (%d, ...) returned prematurely (%lu)", | 
    
    | 375 |  |  | 		    pf_key_v2_socket, (unsigned long) n); | 
    
    | 376 |  |  | 		goto cleanup; | 
    
    | 377 |  |  | 	} | 
    
    | 378 |  |  | 	free(iov); | 
    
    | 379 |  |  | 	return msg->sadb_msg_seq; | 
    
    | 380 |  |  |  | 
    
    | 381 |  |  | cleanup: | 
    
    | 382 |  |  | 	free(iov); | 
    
    | 383 |  |  | 	return 0; | 
    
    | 384 |  |  | } | 
    
    | 385 |  |  |  | 
    
    | 386 |  |  | /* | 
    
    | 387 |  |  |  * Do a PF_KEY "call", i.e. write a message MSG, read the reply and return | 
    
    | 388 |  |  |  * it to the caller. | 
    
    | 389 |  |  |  */ | 
    
    | 390 |  |  | static struct pf_key_v2_msg * | 
    
    | 391 |  |  | pf_key_v2_call(struct pf_key_v2_msg *msg) | 
    
    | 392 |  |  | { | 
    
    | 393 |  |  | 	u_int32_t       seq; | 
    
    | 394 |  |  |  | 
    
    | 395 |  |  | 	seq = pf_key_v2_write(msg); | 
    
    | 396 |  |  | 	if (!seq) | 
    
    | 397 |  |  | 		return 0; | 
    
    | 398 |  |  | 	return pf_key_v2_read(seq); | 
    
    | 399 |  |  | } | 
    
    | 400 |  |  |  | 
    
    | 401 |  |  | /* Find the TYPE extension in MSG.  Return zero if none found.  */ | 
    
    | 402 |  |  | static struct pf_key_v2_node * | 
    
    | 403 |  |  | pf_key_v2_find_ext(struct pf_key_v2_msg *msg, u_int16_t type) | 
    
    | 404 |  |  | { | 
    
    | 405 |  |  | 	struct pf_key_v2_node *ext; | 
    
    | 406 |  |  |  | 
    
    | 407 |  |  | 	for (ext = TAILQ_NEXT(TAILQ_FIRST(msg), link); ext; | 
    
    | 408 |  |  | 	    ext = TAILQ_NEXT(ext, link)) | 
    
    | 409 |  |  | 		if (ext->type == type) | 
    
    | 410 |  |  | 			return ext; | 
    
    | 411 |  |  | 	return 0; | 
    
    | 412 |  |  | } | 
    
    | 413 |  |  |  | 
    
    | 414 |  |  | /* | 
    
    | 415 |  |  |  * Open the PF_KEYv2 sockets and return the descriptor used for notifies. | 
    
    | 416 |  |  |  * Return -1 for failure and -2 if no notifies will show up. | 
    
    | 417 |  |  |  */ | 
    
    | 418 |  |  | int | 
    
    | 419 |  |  | pf_key_v2_open(void) | 
    
    | 420 |  |  | { | 
    
    | 421 |  |  | 	int		fd = -1, err; | 
    
    | 422 |  |  | 	struct sadb_msg msg; | 
    
    | 423 |  |  | 	struct pf_key_v2_msg *regmsg = 0, *ret = 0; | 
    
    | 424 |  |  |  | 
    
    | 425 |  |  | 	/* Open the socket we use to speak to IPsec. */ | 
    
    | 426 |  |  | 	pf_key_v2_socket = -1; | 
    
    | 427 |  |  | 	fd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); | 
    
    | 428 |  |  | 	if (fd == -1) { | 
    
    | 429 |  |  | 		log_error("pf_key_v2_open: " | 
    
    | 430 |  |  | 		    "socket (PF_KEY, SOCK_RAW, PF_KEY_V2) failed"); | 
    
    | 431 |  |  | 		goto cleanup; | 
    
    | 432 |  |  | 	} | 
    
    | 433 |  |  | 	pf_key_v2_socket = fd; | 
    
    | 434 |  |  |  | 
    
    | 435 |  |  | 	/* Register it to get ESP and AH acquires from the kernel.  */ | 
    
    | 436 |  |  | 	msg.sadb_msg_seq = 0; | 
    
    | 437 |  |  | 	msg.sadb_msg_type = SADB_REGISTER; | 
    
    | 438 |  |  | 	msg.sadb_msg_satype = SADB_SATYPE_ESP; | 
    
    | 439 |  |  | 	regmsg = pf_key_v2_msg_new(&msg, 0); | 
    
    | 440 |  |  | 	if (!regmsg) | 
    
    | 441 |  |  | 		goto cleanup; | 
    
    | 442 |  |  | 	ret = pf_key_v2_call(regmsg); | 
    
    | 443 |  |  | 	pf_key_v2_msg_free(regmsg); | 
    
    | 444 |  |  | 	if (!ret) | 
    
    | 445 |  |  | 		goto cleanup; | 
    
    | 446 |  |  | 	err = ((struct sadb_msg *)TAILQ_FIRST(ret)->seg)->sadb_msg_errno; | 
    
    | 447 |  |  | 	if (err) { | 
    
    | 448 |  |  | 		log_print("pf_key_v2_open: REGISTER: %s", strerror(err)); | 
    
    | 449 |  |  | 		goto cleanup; | 
    
    | 450 |  |  | 	} | 
    
    | 451 |  |  | 	/* XXX Register the accepted transforms.  */ | 
    
    | 452 |  |  |  | 
    
    | 453 |  |  | 	pf_key_v2_msg_free(ret); | 
    
    | 454 |  |  | 	ret = 0; | 
    
    | 455 |  |  |  | 
    
    | 456 |  |  | 	msg.sadb_msg_seq = 0; | 
    
    | 457 |  |  | 	msg.sadb_msg_type = SADB_REGISTER; | 
    
    | 458 |  |  | 	msg.sadb_msg_satype = SADB_SATYPE_AH; | 
    
    | 459 |  |  | 	regmsg = pf_key_v2_msg_new(&msg, 0); | 
    
    | 460 |  |  | 	if (!regmsg) | 
    
    | 461 |  |  | 		goto cleanup; | 
    
    | 462 |  |  | 	ret = pf_key_v2_call(regmsg); | 
    
    | 463 |  |  | 	pf_key_v2_msg_free(regmsg); | 
    
    | 464 |  |  | 	if (!ret) | 
    
    | 465 |  |  | 		goto cleanup; | 
    
    | 466 |  |  | 	err = ((struct sadb_msg *)TAILQ_FIRST(ret)->seg)->sadb_msg_errno; | 
    
    | 467 |  |  | 	if (err) { | 
    
    | 468 |  |  | 		log_print("pf_key_v2_open: REGISTER: %s", strerror(err)); | 
    
    | 469 |  |  | 		goto cleanup; | 
    
    | 470 |  |  | 	} | 
    
    | 471 |  |  | 	/* XXX Register the accepted transforms.  */ | 
    
    | 472 |  |  |  | 
    
    | 473 |  |  | 	pf_key_v2_msg_free(ret); | 
    
    | 474 |  |  | 	ret = 0; | 
    
    | 475 |  |  |  | 
    
    | 476 |  |  | 	msg.sadb_msg_seq = 0; | 
    
    | 477 |  |  | 	msg.sadb_msg_type = SADB_REGISTER; | 
    
    | 478 |  |  | 	msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP; | 
    
    | 479 |  |  | 	regmsg = pf_key_v2_msg_new(&msg, 0); | 
    
    | 480 |  |  | 	if (!regmsg) | 
    
    | 481 |  |  | 		goto cleanup; | 
    
    | 482 |  |  | 	ret = pf_key_v2_call(regmsg); | 
    
    | 483 |  |  | 	pf_key_v2_msg_free(regmsg); | 
    
    | 484 |  |  | 	if (!ret) | 
    
    | 485 |  |  | 		goto cleanup; | 
    
    | 486 |  |  | 	err = ((struct sadb_msg *)TAILQ_FIRST(ret)->seg)->sadb_msg_errno; | 
    
    | 487 |  |  | 	if (err) { | 
    
    | 488 |  |  | 		log_print("pf_key_v2_open: REGISTER: %s", strerror(err)); | 
    
    | 489 |  |  | 		goto cleanup; | 
    
    | 490 |  |  | 	} | 
    
    | 491 |  |  | 	/* XXX Register the accepted transforms.  */ | 
    
    | 492 |  |  |  | 
    
    | 493 |  |  | 	pf_key_v2_msg_free(ret); | 
    
    | 494 |  |  |  | 
    
    | 495 |  |  | 	return fd; | 
    
    | 496 |  |  |  | 
    
    | 497 |  |  | cleanup: | 
    
    | 498 |  |  | 	if (pf_key_v2_socket != -1) { | 
    
    | 499 |  |  | 		close(pf_key_v2_socket); | 
    
    | 500 |  |  | 		pf_key_v2_socket = -1; | 
    
    | 501 |  |  | 	} | 
    
    | 502 |  |  | 	if (ret) | 
    
    | 503 |  |  | 		pf_key_v2_msg_free(ret); | 
    
    | 504 |  |  | 	return -1; | 
    
    | 505 |  |  | } | 
    
    | 506 |  |  |  | 
    
    | 507 |  |  | /* | 
    
    | 508 |  |  |  * Generate a SPI for protocol PROTO and the source/destination pair given by | 
    
    | 509 |  |  |  * SRC, SRCLEN, DST & DSTLEN.  Stash the SPI size in SZ. | 
    
    | 510 |  |  |  */ | 
    
    | 511 |  |  | u_int8_t * | 
    
    | 512 |  |  | pf_key_v2_get_spi(size_t *sz, u_int8_t proto, struct sockaddr *src, | 
    
    | 513 |  |  |     struct sockaddr *dst, u_int32_t seq) | 
    
    | 514 |  |  | { | 
    
    | 515 |  |  | 	struct sadb_msg msg; | 
    
    | 516 |  |  | 	struct sadb_sa *sa; | 
    
    | 517 |  |  | 	struct sadb_address *addr = 0; | 
    
    | 518 |  |  | 	struct sadb_spirange spirange; | 
    
    | 519 |  |  | 	struct pf_key_v2_msg *getspi = 0, *ret = 0; | 
    
    | 520 |  |  | 	struct pf_key_v2_node *ext; | 
    
    | 521 |  |  | 	u_int8_t       *spi = 0; | 
    
    | 522 |  |  | 	int		len, err; | 
    
    | 523 |  |  |  | 
    
    | 524 |  |  | 	msg.sadb_msg_type = SADB_GETSPI; | 
    
    | 525 |  |  | 	switch (proto) { | 
    
    | 526 |  |  | 	case IPSEC_PROTO_IPSEC_ESP: | 
    
    | 527 |  |  | 		msg.sadb_msg_satype = SADB_SATYPE_ESP; | 
    
    | 528 |  |  | 		break; | 
    
    | 529 |  |  | 	case IPSEC_PROTO_IPSEC_AH: | 
    
    | 530 |  |  | 		msg.sadb_msg_satype = SADB_SATYPE_AH; | 
    
    | 531 |  |  | 		break; | 
    
    | 532 |  |  | 	case IPSEC_PROTO_IPCOMP: | 
    
    | 533 |  |  | 		msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP; | 
    
    | 534 |  |  | 		break; | 
    
    | 535 |  |  | 	default: | 
    
    | 536 |  |  | 		log_print("pf_key_v2_get_spi: invalid proto %d", proto); | 
    
    | 537 |  |  | 		goto cleanup; | 
    
    | 538 |  |  | 	} | 
    
    | 539 |  |  |  | 
    
    | 540 |  |  | 	/* Set the sequence number from the ACQUIRE message. */ | 
    
    | 541 |  |  | 	msg.sadb_msg_seq = seq; | 
    
    | 542 |  |  | 	getspi = pf_key_v2_msg_new(&msg, 0); | 
    
    | 543 |  |  | 	if (!getspi) | 
    
    | 544 |  |  | 		goto cleanup; | 
    
    | 545 |  |  |  | 
    
    | 546 |  |  | 	/* Setup the ADDRESS extensions.  */ | 
    
    | 547 |  |  | 	len = | 
    
    | 548 |  |  | 	    sizeof(struct sadb_address) + PF_KEY_V2_ROUND(SA_LEN(src)); | 
    
    | 549 |  |  | 	addr = calloc(1, len); | 
    
    | 550 |  |  | 	if (!addr) | 
    
    | 551 |  |  | 		goto cleanup; | 
    
    | 552 |  |  | 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; | 
    
    | 553 |  |  | 	addr->sadb_address_len = len / PF_KEY_V2_CHUNK; | 
    
    | 554 |  |  | 	addr->sadb_address_reserved = 0; | 
    
    | 555 |  |  | 	memcpy(addr + 1, src, SA_LEN(src)); | 
    
    | 556 |  |  | 	switch (((struct sockaddr *) (addr + 1))->sa_family) { | 
    
    | 557 |  |  | 	case AF_INET: | 
    
    | 558 |  |  | 		((struct sockaddr_in *) (addr + 1))->sin_port = 0; | 
    
    | 559 |  |  | 		break; | 
    
    | 560 |  |  | 	case AF_INET6: | 
    
    | 561 |  |  | 		((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0; | 
    
    | 562 |  |  | 		break; | 
    
    | 563 |  |  | 	} | 
    
    | 564 |  |  | 	if (pf_key_v2_msg_add(getspi, (struct sadb_ext *) addr, | 
    
    | 565 |  |  | 	    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 566 |  |  | 		goto cleanup; | 
    
    | 567 |  |  | 	addr = 0; | 
    
    | 568 |  |  |  | 
    
    | 569 |  |  | 	len = sizeof(struct sadb_address) + PF_KEY_V2_ROUND(SA_LEN(dst)); | 
    
    | 570 |  |  | 	addr = calloc(1, len); | 
    
    | 571 |  |  | 	if (!addr) | 
    
    | 572 |  |  | 		goto cleanup; | 
    
    | 573 |  |  | 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; | 
    
    | 574 |  |  | 	addr->sadb_address_len = len / PF_KEY_V2_CHUNK; | 
    
    | 575 |  |  | 	addr->sadb_address_reserved = 0; | 
    
    | 576 |  |  | 	memcpy(addr + 1, dst, SA_LEN(dst)); | 
    
    | 577 |  |  | 	switch (((struct sockaddr *) (addr + 1))->sa_family) { | 
    
    | 578 |  |  | 	case AF_INET: | 
    
    | 579 |  |  | 		((struct sockaddr_in *) (addr + 1))->sin_port = 0; | 
    
    | 580 |  |  | 		break; | 
    
    | 581 |  |  | 	case AF_INET6: | 
    
    | 582 |  |  | 		((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0; | 
    
    | 583 |  |  | 		break; | 
    
    | 584 |  |  | 	} | 
    
    | 585 |  |  | 	if (pf_key_v2_msg_add(getspi, (struct sadb_ext *) addr, | 
    
    | 586 |  |  | 	    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 587 |  |  | 		goto cleanup; | 
    
    | 588 |  |  | 	addr = 0; | 
    
    | 589 |  |  |  | 
    
    | 590 |  |  | 	/* Setup the SPIRANGE extension.  */ | 
    
    | 591 |  |  | 	spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE; | 
    
    | 592 |  |  | 	spirange.sadb_spirange_len = sizeof spirange / PF_KEY_V2_CHUNK; | 
    
    | 593 |  |  | 	if (proto == IPSEC_PROTO_IPCOMP) { | 
    
    | 594 |  |  | 		spirange.sadb_spirange_min = CPI_RESERVED_MAX + 1; | 
    
    | 595 |  |  | 		spirange.sadb_spirange_max = CPI_PRIVATE_MIN - 1; | 
    
    | 596 |  |  | 	} else { | 
    
    | 597 |  |  | 		spirange.sadb_spirange_min = IPSEC_SPI_LOW; | 
    
    | 598 |  |  | 		spirange.sadb_spirange_max = 0xffffffff; | 
    
    | 599 |  |  | 	} | 
    
    | 600 |  |  | 	spirange.sadb_spirange_reserved = 0; | 
    
    | 601 |  |  | 	if (pf_key_v2_msg_add(getspi, (struct sadb_ext *)&spirange, 0) == -1) | 
    
    | 602 |  |  | 		goto cleanup; | 
    
    | 603 |  |  |  | 
    
    | 604 |  |  | 	ret = pf_key_v2_call(getspi); | 
    
    | 605 |  |  | 	pf_key_v2_msg_free(getspi); | 
    
    | 606 |  |  | 	getspi = 0; | 
    
    | 607 |  |  | 	if (!ret) | 
    
    | 608 |  |  | 		goto cleanup; | 
    
    | 609 |  |  | 	err = ((struct sadb_msg *)TAILQ_FIRST(ret)->seg)->sadb_msg_errno; | 
    
    | 610 |  |  | 	if (err) { | 
    
    | 611 |  |  | 		log_print("pf_key_v2_get_spi: GETSPI: %s", strerror(err)); | 
    
    | 612 |  |  | 		goto cleanup; | 
    
    | 613 |  |  | 	} | 
    
    | 614 |  |  | 	ext = pf_key_v2_find_ext(ret, SADB_EXT_SA); | 
    
    | 615 |  |  | 	if (!ext) { | 
    
    | 616 |  |  | 		log_print("pf_key_v2_get_spi: no SA extension found"); | 
    
    | 617 |  |  | 		goto cleanup; | 
    
    | 618 |  |  | 	} | 
    
    | 619 |  |  | 	sa = ext->seg; | 
    
    | 620 |  |  |  | 
    
    | 621 |  |  | 	/* IPCOMP CPIs are only 16 bits long.  */ | 
    
    | 622 |  |  | 	*sz = (proto == IPSEC_PROTO_IPCOMP) ? sizeof(u_int16_t) | 
    
    | 623 |  |  | 		: sizeof sa->sadb_sa_spi; | 
    
    | 624 |  |  | 	spi = malloc(*sz); | 
    
    | 625 |  |  | 	if (!spi) | 
    
    | 626 |  |  | 		goto cleanup; | 
    
    | 627 |  |  | 	/* XXX This is ugly.  */ | 
    
    | 628 |  |  | 	if (proto == IPSEC_PROTO_IPCOMP) { | 
    
    | 629 |  |  | 		u_int32_t       tspi = ntohl(sa->sadb_sa_spi); | 
    
    | 630 |  |  | 		*(u_int16_t *) spi = htons((u_int16_t) tspi); | 
    
    | 631 |  |  | 	} else | 
    
    | 632 |  |  | 		memcpy(spi, &sa->sadb_sa_spi, *sz); | 
    
    | 633 |  |  |  | 
    
    | 634 |  |  | 	pf_key_v2_msg_free(ret); | 
    
    | 635 |  |  |  | 
    
    | 636 |  |  | 	LOG_DBG_BUF((LOG_SYSDEP, 50, "pf_key_v2_get_spi: spi", spi, *sz)); | 
    
    | 637 |  |  | 	return spi; | 
    
    | 638 |  |  |  | 
    
    | 639 |  |  | cleanup: | 
    
    | 640 |  |  | 	free(spi); | 
    
    | 641 |  |  | 	free(addr); | 
    
    | 642 |  |  | 	if (getspi) | 
    
    | 643 |  |  | 		pf_key_v2_msg_free(getspi); | 
    
    | 644 |  |  | 	if (ret) | 
    
    | 645 |  |  | 		pf_key_v2_msg_free(ret); | 
    
    | 646 |  |  | 	return 0; | 
    
    | 647 |  |  | } | 
    
    | 648 |  |  |  | 
    
    | 649 |  |  | /* Fetch SA information from the kernel. XXX OpenBSD only?  */ | 
    
    | 650 |  |  | struct sa_kinfo * | 
    
    | 651 |  |  | pf_key_v2_get_kernel_sa(u_int8_t *spi, size_t spi_sz, u_int8_t proto, | 
    
    | 652 |  |  |     struct sockaddr *dst) | 
    
    | 653 |  |  | { | 
    
    | 654 |  |  | 	struct sadb_msg msg; | 
    
    | 655 |  |  | 	struct sadb_sa *ssa; | 
    
    | 656 |  |  | 	struct sadb_address *addr = 0; | 
    
    | 657 |  |  | 	struct sockaddr *sa; | 
    
    | 658 |  |  | 	struct sadb_lifetime *life; | 
    
    | 659 |  |  | 	struct pf_key_v2_msg *gettdb = 0, *ret = 0; | 
    
    | 660 |  |  | 	struct pf_key_v2_node *ext; | 
    
    | 661 |  |  | 	static struct sa_kinfo ksa; | 
    
    | 662 |  |  | 	struct sadb_x_udpencap *udpencap; | 
    
    | 663 |  |  | 	int len, err; | 
    
    | 664 |  |  |  | 
    
    | 665 |  |  | 	if (spi_sz != sizeof (ssa->sadb_sa_spi)) | 
    
    | 666 |  |  | 		return 0; | 
    
    | 667 |  |  |  | 
    
    | 668 |  |  | 	msg.sadb_msg_type = SADB_GET; | 
    
    | 669 |  |  | 	switch (proto) { | 
    
    | 670 |  |  | 	case IPSEC_PROTO_IPSEC_ESP: | 
    
    | 671 |  |  | 		msg.sadb_msg_satype = SADB_SATYPE_ESP; | 
    
    | 672 |  |  | 		break; | 
    
    | 673 |  |  | 	case IPSEC_PROTO_IPSEC_AH: | 
    
    | 674 |  |  | 		msg.sadb_msg_satype = SADB_SATYPE_AH; | 
    
    | 675 |  |  | 		break; | 
    
    | 676 |  |  | 	case IPSEC_PROTO_IPCOMP: | 
    
    | 677 |  |  | 		msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP; | 
    
    | 678 |  |  | 		break; | 
    
    | 679 |  |  | 	default: | 
    
    | 680 |  |  | 		log_print("pf_key_v2_get_kernel_sa: invalid proto %d", proto); | 
    
    | 681 |  |  | 		goto cleanup; | 
    
    | 682 |  |  | 	} | 
    
    | 683 |  |  |  | 
    
    | 684 |  |  | 	gettdb = pf_key_v2_msg_new(&msg, 0); | 
    
    | 685 |  |  | 	if (!gettdb) | 
    
    | 686 |  |  | 		goto cleanup; | 
    
    | 687 |  |  |  | 
    
    | 688 |  |  | 	/* SPI */ | 
    
    | 689 |  |  | 	ssa = calloc(1, sizeof *ssa); | 
    
    | 690 |  |  | 	if (!ssa) { | 
    
    | 691 |  |  | 		log_print("pf_key_v2_get_kernel_sa: calloc(1, %lu) failed", | 
    
    | 692 |  |  | 		    (unsigned long)sizeof *ssa); | 
    
    | 693 |  |  | 		goto cleanup; | 
    
    | 694 |  |  | 	} | 
    
    | 695 |  |  |  | 
    
    | 696 |  |  | 	ssa->sadb_sa_exttype = SADB_EXT_SA; | 
    
    | 697 |  |  | 	ssa->sadb_sa_len = sizeof *ssa / PF_KEY_V2_CHUNK; | 
    
    | 698 |  |  | 	memcpy(&ssa->sadb_sa_spi, spi, sizeof ssa->sadb_sa_spi); | 
    
    | 699 |  |  | 	ssa->sadb_sa_state = SADB_SASTATE_MATURE; | 
    
    | 700 |  |  | 	if (pf_key_v2_msg_add(gettdb, (struct sadb_ext *)ssa, | 
    
    | 701 |  |  | 	    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 702 |  |  | 		goto cleanup; | 
    
    | 703 |  |  | 	ssa = 0; | 
    
    | 704 |  |  |  | 
    
    | 705 |  |  | 	/* Address */ | 
    
    | 706 |  |  | 	len = | 
    
    | 707 |  |  | 	    sizeof(struct sadb_address) + PF_KEY_V2_ROUND(SA_LEN(dst)); | 
    
    | 708 |  |  | 	addr = calloc(1, len); | 
    
    | 709 |  |  | 	if (!addr) | 
    
    | 710 |  |  | 		goto cleanup; | 
    
    | 711 |  |  | 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; | 
    
    | 712 |  |  | 	addr->sadb_address_len = len / PF_KEY_V2_CHUNK; | 
    
    | 713 |  |  | 	addr->sadb_address_reserved = 0; | 
    
    | 714 |  |  | 	memcpy(addr + 1, dst, SA_LEN(dst)); | 
    
    | 715 |  |  | 	switch (((struct sockaddr *) (addr + 1))->sa_family) { | 
    
    | 716 |  |  | 	case AF_INET: | 
    
    | 717 |  |  | 		((struct sockaddr_in *) (addr + 1))->sin_port = 0; | 
    
    | 718 |  |  | 		break; | 
    
    | 719 |  |  | 	case AF_INET6: | 
    
    | 720 |  |  | 		((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0; | 
    
    | 721 |  |  | 		break; | 
    
    | 722 |  |  | 	} | 
    
    | 723 |  |  | 	if (pf_key_v2_msg_add(gettdb, (struct sadb_ext *)addr, | 
    
    | 724 |  |  | 	    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 725 |  |  | 		goto cleanup; | 
    
    | 726 |  |  | 	addr = 0; | 
    
    | 727 |  |  |  | 
    
    | 728 |  |  | 	ret = pf_key_v2_call(gettdb); | 
    
    | 729 |  |  | 	pf_key_v2_msg_free(gettdb); | 
    
    | 730 |  |  | 	gettdb = 0; | 
    
    | 731 |  |  | 	if (!ret) | 
    
    | 732 |  |  | 		goto cleanup; | 
    
    | 733 |  |  | 	err = ((struct sadb_msg *)TAILQ_FIRST(ret)->seg)->sadb_msg_errno; | 
    
    | 734 |  |  | 	if (err) { | 
    
    | 735 |  |  | 		log_print("pf_key_v2_get_kernel_sa: SADB_GET: %s", | 
    
    | 736 |  |  | 		    strerror(err)); | 
    
    | 737 |  |  | 		goto cleanup; | 
    
    | 738 |  |  | 	} | 
    
    | 739 |  |  |  | 
    
    | 740 |  |  | 	/* Extract the data.  */ | 
    
    | 741 |  |  | 	bzero(&ksa, sizeof ksa); | 
    
    | 742 |  |  |  | 
    
    | 743 |  |  | 	ext = pf_key_v2_find_ext(ret, SADB_EXT_SA); | 
    
    | 744 |  |  | 	if (!ext) | 
    
    | 745 |  |  | 		goto cleanup; | 
    
    | 746 |  |  |  | 
    
    | 747 |  |  | 	ssa = (struct sadb_sa *)ext; | 
    
    | 748 |  |  | 	ksa.spi = ssa->sadb_sa_spi; | 
    
    | 749 |  |  | 	ksa.wnd = ssa->sadb_sa_replay; | 
    
    | 750 |  |  | 	ksa.flags = ssa->sadb_sa_flags; | 
    
    | 751 |  |  |  | 
    
    | 752 |  |  | 	ext = pf_key_v2_find_ext(ret, SADB_EXT_LIFETIME_CURRENT); | 
    
    | 753 |  |  | 	if (ext) { | 
    
    | 754 |  |  | 		life = (struct sadb_lifetime *)ext->seg; | 
    
    | 755 |  |  | 		ksa.cur_allocations = life->sadb_lifetime_allocations; | 
    
    | 756 |  |  | 		ksa.cur_bytes =	life->sadb_lifetime_bytes; | 
    
    | 757 |  |  | 		ksa.first_use = life->sadb_lifetime_usetime; | 
    
    | 758 |  |  | 		ksa.established = life->sadb_lifetime_addtime; | 
    
    | 759 |  |  | 	} | 
    
    | 760 |  |  |  | 
    
    | 761 |  |  | 	ext = pf_key_v2_find_ext(ret, SADB_EXT_LIFETIME_SOFT); | 
    
    | 762 |  |  | 	if (ext) { | 
    
    | 763 |  |  | 		life = (struct sadb_lifetime *)ext->seg; | 
    
    | 764 |  |  | 		ksa.soft_allocations = life->sadb_lifetime_allocations; | 
    
    | 765 |  |  | 		ksa.soft_bytes = life->sadb_lifetime_bytes; | 
    
    | 766 |  |  | 		ksa.soft_timeout = life->sadb_lifetime_addtime; | 
    
    | 767 |  |  | 		ksa.soft_first_use = life->sadb_lifetime_usetime; | 
    
    | 768 |  |  | 	} | 
    
    | 769 |  |  |  | 
    
    | 770 |  |  | 	ext = pf_key_v2_find_ext(ret, SADB_EXT_LIFETIME_HARD); | 
    
    | 771 |  |  | 	if (ext) { | 
    
    | 772 |  |  | 		life = (struct sadb_lifetime *)ext->seg; | 
    
    | 773 |  |  | 		ksa.exp_allocations = life->sadb_lifetime_allocations; | 
    
    | 774 |  |  | 		ksa.exp_bytes = life->sadb_lifetime_bytes; | 
    
    | 775 |  |  | 		ksa.exp_timeout = life->sadb_lifetime_addtime; | 
    
    | 776 |  |  | 		ksa.exp_first_use = life->sadb_lifetime_usetime; | 
    
    | 777 |  |  | 	} | 
    
    | 778 |  |  |  | 
    
    | 779 |  |  | 	ext = pf_key_v2_find_ext(ret, SADB_X_EXT_LIFETIME_LASTUSE); | 
    
    | 780 |  |  | 	if (ext) { | 
    
    | 781 |  |  | 		life = (struct sadb_lifetime *)ext->seg; | 
    
    | 782 |  |  | 		ksa.last_used = life->sadb_lifetime_usetime; | 
    
    | 783 |  |  | 	} | 
    
    | 784 |  |  |  | 
    
    | 785 |  |  | 	ext = pf_key_v2_find_ext(ret, SADB_EXT_ADDRESS_SRC); | 
    
    | 786 |  |  | 	if (ext) { | 
    
    | 787 |  |  | 		sa = (struct sockaddr *)ext->seg; | 
    
    | 788 |  |  | 		memcpy(&ksa.src, sa, | 
    
    | 789 |  |  | 		    sa->sa_family == AF_INET ? sizeof(struct sockaddr_in) : | 
    
    | 790 |  |  | 		    sizeof(struct sockaddr_in6)); | 
    
    | 791 |  |  | 	} | 
    
    | 792 |  |  |  | 
    
    | 793 |  |  | 	ext = pf_key_v2_find_ext(ret, SADB_EXT_ADDRESS_DST); | 
    
    | 794 |  |  | 	if (ext) { | 
    
    | 795 |  |  | 		sa = (struct sockaddr *)ext->seg; | 
    
    | 796 |  |  | 		memcpy(&ksa.dst, sa, | 
    
    | 797 |  |  | 		    sa->sa_family == AF_INET ? sizeof(struct sockaddr_in) : | 
    
    | 798 |  |  | 		    sizeof(struct sockaddr_in6)); | 
    
    | 799 |  |  | 	} | 
    
    | 800 |  |  |  | 
    
    | 801 |  |  | 	ext = pf_key_v2_find_ext(ret, SADB_X_EXT_UDPENCAP); | 
    
    | 802 |  |  | 	if (ext) { | 
    
    | 803 |  |  | 		udpencap = (struct sadb_x_udpencap *)ext->seg; | 
    
    | 804 |  |  | 		ksa.udpencap_port = udpencap->sadb_x_udpencap_port; | 
    
    | 805 |  |  | 	} | 
    
    | 806 |  |  |  | 
    
    | 807 |  |  | 	pf_key_v2_msg_free(ret); | 
    
    | 808 |  |  |  | 
    
    | 809 |  |  | 	LOG_DBG_BUF((LOG_SYSDEP, 50, "pf_key_v2_get_kernel_sa: spi", spi, | 
    
    | 810 |  |  | 	    spi_sz)); | 
    
    | 811 |  |  |  | 
    
    | 812 |  |  | 	return &ksa; | 
    
    | 813 |  |  |  | 
    
    | 814 |  |  |   cleanup: | 
    
    | 815 |  |  | 	free(addr); | 
    
    | 816 |  |  | 	if (gettdb) | 
    
    | 817 |  |  | 		pf_key_v2_msg_free(gettdb); | 
    
    | 818 |  |  | 	if (ret) | 
    
    | 819 |  |  | 		pf_key_v2_msg_free(ret); | 
    
    | 820 |  |  | 	return 0; | 
    
    | 821 |  |  | } | 
    
    | 822 |  |  |  | 
    
    | 823 |  |  | static void | 
    
    | 824 |  |  | pf_key_v2_setup_sockaddr(void *res, struct sockaddr *src, | 
    
    | 825 |  |  |     struct sockaddr *dst, in_port_t port, int ingress) | 
    
    | 826 |  |  | { | 
    
    | 827 |  |  | 	struct sockaddr_in *ip4_sa; | 
    
    | 828 |  |  | 	struct sockaddr_in6 *ip6_sa; | 
    
    | 829 |  |  | 	u_int8_t       *p; | 
    
    | 830 |  |  |  | 
    
    | 831 |  |  | 	switch (src->sa_family) { | 
    
    | 832 |  |  | 	case AF_INET: | 
    
    | 833 |  |  | 		ip4_sa = (struct sockaddr_in *) res; | 
    
    | 834 |  |  | 		ip4_sa->sin_family = AF_INET; | 
    
    | 835 |  |  | 		ip4_sa->sin_len = sizeof *ip4_sa; | 
    
    | 836 |  |  | 		ip4_sa->sin_port = port; | 
    
    | 837 |  |  | 		if (dst) | 
    
    | 838 |  |  | 			p = (u_int8_t *) (ingress ? | 
    
    | 839 |  |  | 			    &((struct sockaddr_in *)src)->sin_addr.s_addr : | 
    
    | 840 |  |  | 			    &((struct sockaddr_in *)dst)->sin_addr.s_addr); | 
    
    | 841 |  |  | 		else | 
    
    | 842 |  |  | 			p = (u_int8_t *)&((struct sockaddr_in *)src)->sin_addr.s_addr; | 
    
    | 843 |  |  | 		ip4_sa->sin_addr.s_addr = *((in_addr_t *) p); | 
    
    | 844 |  |  | 		break; | 
    
    | 845 |  |  |  | 
    
    | 846 |  |  | 	case AF_INET6: | 
    
    | 847 |  |  | 		ip6_sa = (struct sockaddr_in6 *) res; | 
    
    | 848 |  |  | 		ip6_sa->sin6_family = AF_INET6; | 
    
    | 849 |  |  | 		ip6_sa->sin6_len = sizeof *ip6_sa; | 
    
    | 850 |  |  | 		ip6_sa->sin6_port = port; | 
    
    | 851 |  |  | 		if (dst) | 
    
    | 852 |  |  | 			p = (u_int8_t *) (ingress ? | 
    
    | 853 |  |  | 			    &((struct sockaddr_in6 *)src)->sin6_addr.s6_addr : | 
    
    | 854 |  |  | 			    &((struct sockaddr_in6 *)dst)->sin6_addr.s6_addr); | 
    
    | 855 |  |  | 		else | 
    
    | 856 |  |  | 			p = (u_int8_t *)&((struct sockaddr_in6 *)src)->sin6_addr.s6_addr; | 
    
    | 857 |  |  | 		memcpy(ip6_sa->sin6_addr.s6_addr, p, sizeof(struct in6_addr)); | 
    
    | 858 |  |  | 		break; | 
    
    | 859 |  |  |  | 
    
    | 860 |  |  | 	default: | 
    
    | 861 |  |  | 		log_print("pf_key_v2_setup_sockaddr: unknown family %d\n", | 
    
    | 862 |  |  | 		    src->sa_family); | 
    
    | 863 |  |  | 		break; | 
    
    | 864 |  |  | 	} | 
    
    | 865 |  |  | } | 
    
    | 866 |  |  |  | 
    
    | 867 |  |  | /* | 
    
    | 868 |  |  |  * Store/update a PF_KEY_V2 security association with full information from the | 
    
    | 869 |  |  |  * IKE SA and PROTO into the kernel.  INCOMING is set if we are setting the | 
    
    | 870 |  |  |  * parameters for the incoming SA, and cleared otherwise. | 
    
    | 871 |  |  |  */ | 
    
    | 872 |  |  | int | 
    
    | 873 |  |  | pf_key_v2_set_spi(struct sa *sa, struct proto *proto, int incoming, | 
    
    | 874 |  |  |     struct sa *isakmp_sa) | 
    
    | 875 |  |  | { | 
    
    | 876 |  |  | 	struct sadb_msg msg; | 
    
    | 877 |  |  | 	struct sadb_sa  ssa; | 
    
    | 878 |  |  | 	struct sadb_x_tag *stag = NULL; | 
    
    | 879 |  |  | 	struct sadb_lifetime *life = 0; | 
    
    | 880 |  |  | 	struct sadb_address *addr = 0; | 
    
    | 881 |  |  | 	struct sadb_key *key = 0; | 
    
    | 882 |  |  | 	struct sadb_ident *sid = 0; | 
    
    | 883 |  |  | 	struct sockaddr *src, *dst; | 
    
    | 884 |  |  | 	struct pf_key_v2_msg *update = 0, *ret = 0; | 
    
    | 885 |  |  | 	struct ipsec_proto *iproto = proto->data; | 
    
    | 886 |  |  | 	size_t		len; | 
    
    | 887 |  |  | 	int		keylen, hashlen, err; | 
    
    | 888 |  |  | 	u_int8_t       *pp; | 
    
    | 889 |  |  | 	int		idtype; | 
    
    | 890 |  |  | 	struct ipsec_sa *isa = sa->data; | 
    
    | 891 |  |  | 	struct sadb_protocol flowtype, tprotocol; | 
    
    | 892 |  |  | 	struct sadb_x_udpencap udpencap; | 
    
    | 893 |  |  | 	char           *addr_str, *s; | 
    
    | 894 |  |  |  | 
    
    | 895 |  |  | 	msg.sadb_msg_type = incoming ? SADB_UPDATE : SADB_ADD; | 
    
    | 896 |  |  | 	switch (proto->proto) { | 
    
    | 897 |  |  | 	case IPSEC_PROTO_IPSEC_ESP: | 
    
    | 898 |  |  | 		msg.sadb_msg_satype = SADB_SATYPE_ESP; | 
    
    | 899 |  |  | 		keylen = ipsec_esp_enckeylength(proto); | 
    
    | 900 |  |  | 		hashlen = ipsec_esp_authkeylength(proto); | 
    
    | 901 |  |  |  | 
    
    | 902 |  |  | 		switch (proto->id) { | 
    
    | 903 |  |  | 		case IPSEC_ESP_3DES: | 
    
    | 904 |  |  | 			ssa.sadb_sa_encrypt = SADB_EALG_3DESCBC; | 
    
    | 905 |  |  | 			break; | 
    
    | 906 |  |  |  | 
    
    | 907 |  |  | 		case IPSEC_ESP_AES: | 
    
    | 908 |  |  | 			ssa.sadb_sa_encrypt = SADB_X_EALG_AES; | 
    
    | 909 |  |  | 			break; | 
    
    | 910 |  |  |  | 
    
    | 911 |  |  | 		case IPSEC_ESP_AES_CTR: | 
    
    | 912 |  |  | 			ssa.sadb_sa_encrypt = SADB_X_EALG_AESCTR; | 
    
    | 913 |  |  | 			break; | 
    
    | 914 |  |  |  | 
    
    | 915 |  |  | 		case IPSEC_ESP_AES_GCM_16: | 
    
    | 916 |  |  | 			ssa.sadb_sa_encrypt = SADB_X_EALG_AESGCM16; | 
    
    | 917 |  |  | 			break; | 
    
    | 918 |  |  |  | 
    
    | 919 |  |  | 		case IPSEC_ESP_AES_GMAC: | 
    
    | 920 |  |  | 			ssa.sadb_sa_encrypt = SADB_X_EALG_AESGMAC; | 
    
    | 921 |  |  | 			break; | 
    
    | 922 |  |  |  | 
    
    | 923 |  |  | 		case IPSEC_ESP_CAST: | 
    
    | 924 |  |  | 			ssa.sadb_sa_encrypt = SADB_X_EALG_CAST; | 
    
    | 925 |  |  | 			break; | 
    
    | 926 |  |  |  | 
    
    | 927 |  |  | 		case IPSEC_ESP_BLOWFISH: | 
    
    | 928 |  |  | 			ssa.sadb_sa_encrypt = SADB_X_EALG_BLF; | 
    
    | 929 |  |  | 			break; | 
    
    | 930 |  |  |  | 
    
    | 931 |  |  | 		case IPSEC_ESP_NULL: | 
    
    | 932 |  |  | 			ssa.sadb_sa_encrypt = SADB_EALG_NULL; | 
    
    | 933 |  |  | 			break; | 
    
    | 934 |  |  |  | 
    
    | 935 |  |  | 		default: | 
    
    | 936 |  |  | 			LOG_DBG((LOG_SYSDEP, 50, "pf_key_v2_set_spi: " | 
    
    | 937 |  |  | 			    "unknown encryption algorithm %d", proto->id)); | 
    
    | 938 |  |  | 			return -1; | 
    
    | 939 |  |  | 		} | 
    
    | 940 |  |  |  | 
    
    | 941 |  |  | 		switch (iproto->auth) { | 
    
    | 942 |  |  | 		case IPSEC_AUTH_HMAC_MD5: | 
    
    | 943 |  |  | 			ssa.sadb_sa_auth = SADB_AALG_MD5HMAC; | 
    
    | 944 |  |  | 			break; | 
    
    | 945 |  |  |  | 
    
    | 946 |  |  | 		case IPSEC_AUTH_HMAC_SHA: | 
    
    | 947 |  |  | 			ssa.sadb_sa_auth = SADB_AALG_SHA1HMAC; | 
    
    | 948 |  |  | 			break; | 
    
    | 949 |  |  |  | 
    
    | 950 |  |  | 		case IPSEC_AUTH_HMAC_RIPEMD: | 
    
    | 951 |  |  | 			ssa.sadb_sa_auth = SADB_X_AALG_RIPEMD160HMAC; | 
    
    | 952 |  |  | 			break; | 
    
    | 953 |  |  |  | 
    
    | 954 |  |  | 		case IPSEC_AUTH_HMAC_SHA2_256: | 
    
    | 955 |  |  | 			ssa.sadb_sa_auth = SADB_X_AALG_SHA2_256; | 
    
    | 956 |  |  | 			break; | 
    
    | 957 |  |  |  | 
    
    | 958 |  |  | 		case IPSEC_AUTH_HMAC_SHA2_384: | 
    
    | 959 |  |  | 			ssa.sadb_sa_auth = SADB_X_AALG_SHA2_384; | 
    
    | 960 |  |  | 			break; | 
    
    | 961 |  |  |  | 
    
    | 962 |  |  | 		case IPSEC_AUTH_HMAC_SHA2_512: | 
    
    | 963 |  |  | 			ssa.sadb_sa_auth = SADB_X_AALG_SHA2_512; | 
    
    | 964 |  |  | 			break; | 
    
    | 965 |  |  |  | 
    
    | 966 |  |  | 		case IPSEC_AUTH_DES_MAC: | 
    
    | 967 |  |  | 		case IPSEC_AUTH_KPDK: | 
    
    | 968 |  |  | 			/* XXX We should be supporting KPDK */ | 
    
    | 969 |  |  | 			LOG_DBG((LOG_SYSDEP, 50, "pf_key_v2_set_spi: " | 
    
    | 970 |  |  | 			    "unknown authentication algorithm %d", | 
    
    | 971 |  |  | 			    iproto->auth)); | 
    
    | 972 |  |  | 			return -1; | 
    
    | 973 |  |  |  | 
    
    | 974 |  |  | 		default: | 
    
    | 975 |  |  | 			ssa.sadb_sa_auth = SADB_AALG_NONE; | 
    
    | 976 |  |  | 		} | 
    
    | 977 |  |  | 		break; | 
    
    | 978 |  |  |  | 
    
    | 979 |  |  | 	case IPSEC_PROTO_IPSEC_AH: | 
    
    | 980 |  |  | 		msg.sadb_msg_satype = SADB_SATYPE_AH; | 
    
    | 981 |  |  | 		hashlen = ipsec_ah_keylength(proto); | 
    
    | 982 |  |  | 		keylen = 0; | 
    
    | 983 |  |  |  | 
    
    | 984 |  |  | 		ssa.sadb_sa_encrypt = SADB_EALG_NONE; | 
    
    | 985 |  |  | 		switch (proto->id) { | 
    
    | 986 |  |  | 		case IPSEC_AH_MD5: | 
    
    | 987 |  |  | 			ssa.sadb_sa_auth = SADB_AALG_MD5HMAC; | 
    
    | 988 |  |  | 			break; | 
    
    | 989 |  |  |  | 
    
    | 990 |  |  | 		case IPSEC_AH_SHA: | 
    
    | 991 |  |  | 			ssa.sadb_sa_auth = SADB_AALG_SHA1HMAC; | 
    
    | 992 |  |  | 			break; | 
    
    | 993 |  |  |  | 
    
    | 994 |  |  | 		case IPSEC_AH_RIPEMD: | 
    
    | 995 |  |  | 			ssa.sadb_sa_auth = SADB_X_AALG_RIPEMD160HMAC; | 
    
    | 996 |  |  | 			break; | 
    
    | 997 |  |  |  | 
    
    | 998 |  |  | 		case IPSEC_AH_SHA2_256: | 
    
    | 999 |  |  | 			ssa.sadb_sa_auth = SADB_X_AALG_SHA2_256; | 
    
    | 1000 |  |  | 			break; | 
    
    | 1001 |  |  |  | 
    
    | 1002 |  |  | 		case IPSEC_AH_SHA2_384: | 
    
    | 1003 |  |  | 			ssa.sadb_sa_auth = SADB_X_AALG_SHA2_384; | 
    
    | 1004 |  |  | 			break; | 
    
    | 1005 |  |  |  | 
    
    | 1006 |  |  | 		case IPSEC_AH_SHA2_512: | 
    
    | 1007 |  |  | 			ssa.sadb_sa_auth = SADB_X_AALG_SHA2_512; | 
    
    | 1008 |  |  | 			break; | 
    
    | 1009 |  |  |  | 
    
    | 1010 |  |  | 		default: | 
    
    | 1011 |  |  | 			LOG_DBG((LOG_SYSDEP, 50, "pf_key_v2_set_spi: " | 
    
    | 1012 |  |  | 			    "unknown authentication algorithm %d", proto->id)); | 
    
    | 1013 |  |  | 			goto cleanup; | 
    
    | 1014 |  |  | 		} | 
    
    | 1015 |  |  | 		break; | 
    
    | 1016 |  |  |  | 
    
    | 1017 |  |  | 	case IPSEC_PROTO_IPCOMP: | 
    
    | 1018 |  |  | 		msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP; | 
    
    | 1019 |  |  | 		ssa.sadb_sa_auth = SADB_AALG_NONE; | 
    
    | 1020 |  |  | 		keylen = 0; | 
    
    | 1021 |  |  | 		hashlen = 0; | 
    
    | 1022 |  |  |  | 
    
    | 1023 |  |  | 		/* | 
    
    | 1024 |  |  | 		 * Put compression algorithm type in the sadb_sa_encrypt | 
    
    | 1025 |  |  | 		 * field. | 
    
    | 1026 |  |  | 		 */ | 
    
    | 1027 |  |  | 		switch (proto->id) { | 
    
    | 1028 |  |  | 		case IPSEC_IPCOMP_OUI: | 
    
    | 1029 |  |  | 			ssa.sadb_sa_encrypt = SADB_X_CALG_OUI; | 
    
    | 1030 |  |  | 			break; | 
    
    | 1031 |  |  |  | 
    
    | 1032 |  |  | 		case IPSEC_IPCOMP_DEFLATE: | 
    
    | 1033 |  |  | 			ssa.sadb_sa_encrypt = SADB_X_CALG_DEFLATE; | 
    
    | 1034 |  |  | 			break; | 
    
    | 1035 |  |  |  | 
    
    | 1036 |  |  | 		case IPSEC_IPCOMP_LZS: | 
    
    | 1037 |  |  | 			ssa.sadb_sa_encrypt = SADB_X_CALG_LZS; | 
    
    | 1038 |  |  | 			break; | 
    
    | 1039 |  |  |  | 
    
    | 1040 |  |  | 		default: | 
    
    | 1041 |  |  | 			break; | 
    
    | 1042 |  |  | 		} | 
    
    | 1043 |  |  | 		break; | 
    
    | 1044 |  |  |  | 
    
    | 1045 |  |  | 	default: | 
    
    | 1046 |  |  | 		log_print("pf_key_v2_set_spi: invalid proto %d", proto->proto); | 
    
    | 1047 |  |  | 		goto cleanup; | 
    
    | 1048 |  |  | 	} | 
    
    | 1049 |  |  | 	if (incoming) | 
    
    | 1050 |  |  | 		sa->transport->vtbl->get_src(sa->transport, &dst); | 
    
    | 1051 |  |  | 	else | 
    
    | 1052 |  |  | 		sa->transport->vtbl->get_dst(sa->transport, &dst); | 
    
    | 1053 |  |  | 	msg.sadb_msg_seq = sa->seq; | 
    
    | 1054 |  |  | 	update = pf_key_v2_msg_new(&msg, 0); | 
    
    | 1055 |  |  | 	if (!update) | 
    
    | 1056 |  |  | 		goto cleanup; | 
    
    | 1057 |  |  |  | 
    
    | 1058 |  |  | 	/* Setup the rest of the SA extension.  */ | 
    
    | 1059 |  |  | 	ssa.sadb_sa_exttype = SADB_EXT_SA; | 
    
    | 1060 |  |  | 	ssa.sadb_sa_len = sizeof ssa / PF_KEY_V2_CHUNK; | 
    
    | 1061 |  |  | 	if (proto->spi_sz[incoming] == 2)	/* IPCOMP uses 16bit CPIs.  */ | 
    
    | 1062 |  |  | 		ssa.sadb_sa_spi = htonl(proto->spi[incoming][0] << 8 | | 
    
    | 1063 |  |  | 		    proto->spi[incoming][1]); | 
    
    | 1064 |  |  | 	else | 
    
    | 1065 |  |  | 		memcpy(&ssa.sadb_sa_spi, proto->spi[incoming], | 
    
    | 1066 |  |  | 		    sizeof ssa.sadb_sa_spi); | 
    
    | 1067 |  |  | 	ssa.sadb_sa_replay = conf_get_str("General", "Shared-SADB") ? 0 : | 
    
    | 1068 |  |  | 	    iproto->replay_window; | 
    
    | 1069 |  |  | 	ssa.sadb_sa_state = SADB_SASTATE_MATURE; | 
    
    | 1070 |  |  | 	ssa.sadb_sa_flags = 0; | 
    
    | 1071 |  |  | 	if (iproto->encap_mode == IPSEC_ENCAP_TUNNEL || | 
    
    | 1072 |  |  | 	    iproto->encap_mode == IPSEC_ENCAP_UDP_ENCAP_TUNNEL || | 
    
    | 1073 |  |  | 	    iproto->encap_mode == IPSEC_ENCAP_UDP_ENCAP_TUNNEL_DRAFT) | 
    
    | 1074 |  |  | 		ssa.sadb_sa_flags = SADB_X_SAFLAGS_TUNNEL; | 
    
    | 1075 |  |  |  | 
    
    | 1076 |  |  | 	if (isakmp_sa->flags & SA_FLAG_NAT_T_ENABLE) { | 
    
    | 1077 |  |  | 		bzero(&udpencap, sizeof udpencap); | 
    
    | 1078 |  |  | 		ssa.sadb_sa_flags |= SADB_X_SAFLAGS_UDPENCAP; | 
    
    | 1079 |  |  | 		udpencap.sadb_x_udpencap_exttype = SADB_X_EXT_UDPENCAP; | 
    
    | 1080 |  |  | 		udpencap.sadb_x_udpencap_len = | 
    
    | 1081 |  |  | 		    sizeof udpencap / PF_KEY_V2_CHUNK; | 
    
    | 1082 |  |  | 		udpencap.sadb_x_udpencap_port = sockaddr_port(dst); | 
    
    | 1083 |  |  | 		if (pf_key_v2_msg_add(update, (struct sadb_ext *)&udpencap, 0) | 
    
    | 1084 |  |  | 		    == -1) | 
    
    | 1085 |  |  | 			goto cleanup; | 
    
    | 1086 |  |  | 	} | 
    
    | 1087 |  |  |  | 
    
    | 1088 |  |  | 	if (pf_key_v2_msg_add(update, (struct sadb_ext *)&ssa, 0) == -1) | 
    
    | 1089 |  |  | 		goto cleanup; | 
    
    | 1090 |  |  |  | 
    
    | 1091 |  |  | 	if (sa->seconds || sa->kilobytes) { | 
    
    | 1092 |  |  | 		/* Setup the hard limits.  */ | 
    
    | 1093 |  |  | 		life = malloc(sizeof *life); | 
    
    | 1094 |  |  | 		if (!life) | 
    
    | 1095 |  |  | 			goto cleanup; | 
    
    | 1096 |  |  | 		life->sadb_lifetime_len = sizeof *life / PF_KEY_V2_CHUNK; | 
    
    | 1097 |  |  | 		life->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD; | 
    
    | 1098 |  |  | 		life->sadb_lifetime_allocations = 0; | 
    
    | 1099 |  |  | 		life->sadb_lifetime_bytes = sa->kilobytes * 1024; | 
    
    | 1100 |  |  | 		/* | 
    
    | 1101 |  |  | 		 * XXX I am not sure which one is best in security respect. | 
    
    | 1102 |  |  | 		 * Maybe the RFCs actually mandate what a lifetime really is. | 
    
    | 1103 |  |  | 		 */ | 
    
    | 1104 |  |  | #if 0 | 
    
    | 1105 |  |  | 		life->sadb_lifetime_addtime = 0; | 
    
    | 1106 |  |  | 		life->sadb_lifetime_usetime = sa->seconds; | 
    
    | 1107 |  |  | #else | 
    
    | 1108 |  |  | 		life->sadb_lifetime_addtime = sa->seconds; | 
    
    | 1109 |  |  | 		life->sadb_lifetime_usetime = 0; | 
    
    | 1110 |  |  | #endif | 
    
    | 1111 |  |  | 		if (pf_key_v2_msg_add(update, (struct sadb_ext *) life, | 
    
    | 1112 |  |  | 		    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 1113 |  |  | 			goto cleanup; | 
    
    | 1114 |  |  | 		life = 0; | 
    
    | 1115 |  |  |  | 
    
    | 1116 |  |  | 		/* | 
    
    | 1117 |  |  | 		 * Setup the soft limits, we use 90 % of the hard ones. | 
    
    | 1118 |  |  | 		 * XXX A configurable ratio would be better. | 
    
    | 1119 |  |  | 		 */ | 
    
    | 1120 |  |  | 		life = malloc(sizeof *life); | 
    
    | 1121 |  |  | 		if (!life) | 
    
    | 1122 |  |  | 			goto cleanup; | 
    
    | 1123 |  |  | 		life->sadb_lifetime_len = sizeof *life / PF_KEY_V2_CHUNK; | 
    
    | 1124 |  |  | 		life->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT; | 
    
    | 1125 |  |  | 		life->sadb_lifetime_allocations = 0; | 
    
    | 1126 |  |  | 		life->sadb_lifetime_bytes = sa->kilobytes * 1024 * 9 / 10; | 
    
    | 1127 |  |  | 		/* | 
    
    | 1128 |  |  | 		 * XXX I am not sure which one is best in security respect. | 
    
    | 1129 |  |  | 		 * Maybe the RFCs actually mandate what a lifetime really is. | 
    
    | 1130 |  |  | 		 */ | 
    
    | 1131 |  |  | #if 0 | 
    
    | 1132 |  |  | 		life->sadb_lifetime_addtime = 0; | 
    
    | 1133 |  |  | 		life->sadb_lifetime_usetime = sa->seconds * 9 / 10; | 
    
    | 1134 |  |  | #else | 
    
    | 1135 |  |  | 		life->sadb_lifetime_addtime = sa->seconds * 9 / 10; | 
    
    | 1136 |  |  | 		life->sadb_lifetime_usetime = 0; | 
    
    | 1137 |  |  | #endif | 
    
    | 1138 |  |  | 		if (pf_key_v2_msg_add(update, (struct sadb_ext *) life, | 
    
    | 1139 |  |  | 		    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 1140 |  |  | 			goto cleanup; | 
    
    | 1141 |  |  | 		life = 0; | 
    
    | 1142 |  |  | 	} | 
    
    | 1143 |  |  | 	/* | 
    
    | 1144 |  |  | 	 * Setup the ADDRESS extensions. | 
    
    | 1145 |  |  | 	 */ | 
    
    | 1146 |  |  | 	if (incoming) | 
    
    | 1147 |  |  | 		sa->transport->vtbl->get_dst(sa->transport, &src); | 
    
    | 1148 |  |  | 	else | 
    
    | 1149 |  |  | 		sa->transport->vtbl->get_src(sa->transport, &src); | 
    
    | 1150 |  |  | 	len = sizeof *addr + PF_KEY_V2_ROUND(SA_LEN(src)); | 
    
    | 1151 |  |  | 	addr = calloc(1, len); | 
    
    | 1152 |  |  | 	if (!addr) | 
    
    | 1153 |  |  | 		goto cleanup; | 
    
    | 1154 |  |  | 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; | 
    
    | 1155 |  |  | 	addr->sadb_address_len = len / PF_KEY_V2_CHUNK; | 
    
    | 1156 |  |  | 	addr->sadb_address_reserved = 0; | 
    
    | 1157 |  |  | 	memcpy(addr + 1, src, SA_LEN(src)); | 
    
    | 1158 |  |  | 	switch (((struct sockaddr *) (addr + 1))->sa_family) { | 
    
    | 1159 |  |  | 	case AF_INET: | 
    
    | 1160 |  |  | 		((struct sockaddr_in *) (addr + 1))->sin_port = 0; | 
    
    | 1161 |  |  | 		break; | 
    
    | 1162 |  |  | 	case AF_INET6: | 
    
    | 1163 |  |  | 		((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0; | 
    
    | 1164 |  |  | 		break; | 
    
    | 1165 |  |  | 	} | 
    
    | 1166 |  |  | 	if (pf_key_v2_msg_add(update, (struct sadb_ext *) addr, | 
    
    | 1167 |  |  | 	    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 1168 |  |  | 		goto cleanup; | 
    
    | 1169 |  |  | 	addr = 0; | 
    
    | 1170 |  |  |  | 
    
    | 1171 |  |  | 	len = sizeof *addr + PF_KEY_V2_ROUND(SA_LEN(dst)); | 
    
    | 1172 |  |  | 	addr = calloc(1, len); | 
    
    | 1173 |  |  | 	if (!addr) | 
    
    | 1174 |  |  | 		goto cleanup; | 
    
    | 1175 |  |  | 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; | 
    
    | 1176 |  |  | 	addr->sadb_address_len = len / PF_KEY_V2_CHUNK; | 
    
    | 1177 |  |  | 	addr->sadb_address_reserved = 0; | 
    
    | 1178 |  |  | 	memcpy(addr + 1, dst, SA_LEN(dst)); | 
    
    | 1179 |  |  | 	switch (((struct sockaddr *) (addr + 1))->sa_family) { | 
    
    | 1180 |  |  | 	case AF_INET: | 
    
    | 1181 |  |  | 		((struct sockaddr_in *) (addr + 1))->sin_port = 0; | 
    
    | 1182 |  |  | 		break; | 
    
    | 1183 |  |  | 	case AF_INET6: | 
    
    | 1184 |  |  | 		((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0; | 
    
    | 1185 |  |  | 		break; | 
    
    | 1186 |  |  | 	} | 
    
    | 1187 |  |  | 	if (pf_key_v2_msg_add(update, (struct sadb_ext *) addr, | 
    
    | 1188 |  |  | 	    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 1189 |  |  | 		goto cleanup; | 
    
    | 1190 |  |  | 	addr = 0; | 
    
    | 1191 |  |  |  | 
    
    | 1192 |  |  | 	if (proto->proto != IPSEC_PROTO_IPCOMP) { | 
    
    | 1193 |  |  | 		/* Setup the KEY extensions.  */ | 
    
    | 1194 |  |  | 		if (hashlen) { | 
    
    | 1195 |  |  | 			len = sizeof *key + PF_KEY_V2_ROUND(hashlen); | 
    
    | 1196 |  |  | 			key = malloc(len); | 
    
    | 1197 |  |  | 			if (!key) | 
    
    | 1198 |  |  | 				goto cleanup; | 
    
    | 1199 |  |  | 			key->sadb_key_exttype = SADB_EXT_KEY_AUTH; | 
    
    | 1200 |  |  | 			key->sadb_key_len = len / PF_KEY_V2_CHUNK; | 
    
    | 1201 |  |  | 			key->sadb_key_bits = hashlen * 8; | 
    
    | 1202 |  |  | 			key->sadb_key_reserved = 0; | 
    
    | 1203 |  |  | 			memcpy(key + 1, | 
    
    | 1204 |  |  | 			    iproto->keymat[incoming] + | 
    
    | 1205 |  |  | 			    (proto->proto == | 
    
    | 1206 |  |  | 				IPSEC_PROTO_IPSEC_ESP ? keylen : 0), | 
    
    | 1207 |  |  | 			    hashlen); | 
    
    | 1208 |  |  | 			if (pf_key_v2_msg_add(update, (struct sadb_ext *) key, | 
    
    | 1209 |  |  | 			    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 1210 |  |  | 				goto cleanup; | 
    
    | 1211 |  |  | 			key = 0; | 
    
    | 1212 |  |  | 		} | 
    
    | 1213 |  |  | 		if (keylen) { | 
    
    | 1214 |  |  | 			len = sizeof *key + PF_KEY_V2_ROUND(keylen); | 
    
    | 1215 |  |  | 			key = malloc(len); | 
    
    | 1216 |  |  | 			if (!key) | 
    
    | 1217 |  |  | 				goto cleanup; | 
    
    | 1218 |  |  | 			key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT; | 
    
    | 1219 |  |  | 			key->sadb_key_len = len / PF_KEY_V2_CHUNK; | 
    
    | 1220 |  |  | 			key->sadb_key_bits = keylen * 8; | 
    
    | 1221 |  |  | 			key->sadb_key_reserved = 0; | 
    
    | 1222 |  |  | 			memcpy(key + 1, iproto->keymat[incoming], keylen); | 
    
    | 1223 |  |  | 			if (pf_key_v2_msg_add(update, (struct sadb_ext *) key, | 
    
    | 1224 |  |  | 			    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 1225 |  |  | 				goto cleanup; | 
    
    | 1226 |  |  | 			key = 0; | 
    
    | 1227 |  |  | 		} | 
    
    | 1228 |  |  | 	} | 
    
    | 1229 |  |  | 	/* Setup identity extensions. */ | 
    
    | 1230 |  |  | 	if (isakmp_sa->id_i) { | 
    
    | 1231 |  |  | 		pp = pf_key_v2_convert_id(isakmp_sa->id_i, isakmp_sa->id_i_len, | 
    
    | 1232 |  |  | 		    &len, &idtype); | 
    
    | 1233 |  |  | 		if (!pp) | 
    
    | 1234 |  |  | 			goto nosid; | 
    
    | 1235 |  |  |  | 
    
    | 1236 |  |  | 		sid = calloc(PF_KEY_V2_ROUND(len + 1) + sizeof *sid, | 
    
    | 1237 |  |  | 		    sizeof(u_int8_t)); | 
    
    | 1238 |  |  | 		if (!sid) { | 
    
    | 1239 |  |  | 			free(pp); | 
    
    | 1240 |  |  | 			goto cleanup; | 
    
    | 1241 |  |  | 		} | 
    
    | 1242 |  |  | 		sid->sadb_ident_type = idtype; | 
    
    | 1243 |  |  | 		sid->sadb_ident_len = ((sizeof *sid) / PF_KEY_V2_CHUNK) + | 
    
    | 1244 |  |  | 		    PF_KEY_V2_ROUND(len + 1) / PF_KEY_V2_CHUNK; | 
    
    | 1245 |  |  | 		if ((isakmp_sa->initiator && !incoming) || | 
    
    | 1246 |  |  | 		    (!isakmp_sa->initiator && incoming)) | 
    
    | 1247 |  |  | 			sid->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC; | 
    
    | 1248 |  |  | 		else | 
    
    | 1249 |  |  | 			sid->sadb_ident_exttype = SADB_EXT_IDENTITY_DST; | 
    
    | 1250 |  |  |  | 
    
    | 1251 |  |  | 		memcpy(sid + 1, pp, len); | 
    
    | 1252 |  |  | 		free(pp); | 
    
    | 1253 |  |  |  | 
    
    | 1254 |  |  | 		if (pf_key_v2_msg_add(update, (struct sadb_ext *) sid, | 
    
    | 1255 |  |  | 		    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 1256 |  |  | 			goto cleanup; | 
    
    | 1257 |  |  | 		sid = 0; | 
    
    | 1258 |  |  |  | 
    
    | 1259 |  |  | nosid: | 
    
    | 1260 |  |  | 		free(sid); | 
    
    | 1261 |  |  | 		sid = 0; | 
    
    | 1262 |  |  | 	} | 
    
    | 1263 |  |  | 	if (isakmp_sa->id_r) { | 
    
    | 1264 |  |  | 		pp = pf_key_v2_convert_id(isakmp_sa->id_r, isakmp_sa->id_r_len, | 
    
    | 1265 |  |  | 		    &len, &idtype); | 
    
    | 1266 |  |  | 		if (!pp) | 
    
    | 1267 |  |  | 			goto nodid; | 
    
    | 1268 |  |  |  | 
    
    | 1269 |  |  | 		sid = calloc(PF_KEY_V2_ROUND(len + 1) + sizeof *sid, | 
    
    | 1270 |  |  | 		    sizeof(u_int8_t)); | 
    
    | 1271 |  |  | 		if (!sid) { | 
    
    | 1272 |  |  | 			free(pp); | 
    
    | 1273 |  |  | 			goto cleanup; | 
    
    | 1274 |  |  | 		} | 
    
    | 1275 |  |  | 		sid->sadb_ident_type = idtype; | 
    
    | 1276 |  |  | 		sid->sadb_ident_len = ((sizeof *sid) / PF_KEY_V2_CHUNK) + | 
    
    | 1277 |  |  | 		    PF_KEY_V2_ROUND(len + 1) / PF_KEY_V2_CHUNK; | 
    
    | 1278 |  |  | 		if ((isakmp_sa->initiator && !incoming) || | 
    
    | 1279 |  |  | 		    (!isakmp_sa->initiator && incoming)) | 
    
    | 1280 |  |  | 			sid->sadb_ident_exttype = SADB_EXT_IDENTITY_DST; | 
    
    | 1281 |  |  | 		else | 
    
    | 1282 |  |  | 			sid->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC; | 
    
    | 1283 |  |  |  | 
    
    | 1284 |  |  | 		memcpy(sid + 1, pp, len); | 
    
    | 1285 |  |  | 		free(pp); | 
    
    | 1286 |  |  |  | 
    
    | 1287 |  |  | 		if (pf_key_v2_msg_add(update, (struct sadb_ext *) sid, | 
    
    | 1288 |  |  | 		    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 1289 |  |  | 			goto cleanup; | 
    
    | 1290 |  |  | 		sid = 0; | 
    
    | 1291 |  |  |  | 
    
    | 1292 |  |  | nodid: | 
    
    | 1293 |  |  | 		free(sid); | 
    
    | 1294 |  |  | 		sid = 0; | 
    
    | 1295 |  |  | 	} | 
    
    | 1296 |  |  |  | 
    
    | 1297 |  |  | 	/* Setup the flow type extension.  */ | 
    
    | 1298 |  |  | 	bzero(&flowtype, sizeof flowtype); | 
    
    | 1299 |  |  | 	flowtype.sadb_protocol_exttype = SADB_X_EXT_FLOW_TYPE; | 
    
    | 1300 |  |  | 	flowtype.sadb_protocol_len = sizeof flowtype / PF_KEY_V2_CHUNK; | 
    
    | 1301 |  |  | 	flowtype.sadb_protocol_direction = incoming ? | 
    
    | 1302 |  |  | 	    IPSP_DIRECTION_IN : IPSP_DIRECTION_OUT; | 
    
    | 1303 |  |  |  | 
    
    | 1304 |  |  | 	if (pf_key_v2_msg_add(update, (struct sadb_ext *)&flowtype, 0) == -1) | 
    
    | 1305 |  |  | 		goto cleanup; | 
    
    | 1306 |  |  |  | 
    
    | 1307 |  |  | 	bzero(&tprotocol, sizeof tprotocol); | 
    
    | 1308 |  |  | 	tprotocol.sadb_protocol_exttype = SADB_X_EXT_PROTOCOL; | 
    
    | 1309 |  |  | 	tprotocol.sadb_protocol_len = sizeof tprotocol / PF_KEY_V2_CHUNK; | 
    
    | 1310 |  |  | 	tprotocol.sadb_protocol_proto = isa->tproto; | 
    
    | 1311 |  |  |  | 
    
    | 1312 |  |  | 	if (pf_key_v2_msg_add(update, (struct sadb_ext *)&tprotocol, | 
    
    | 1313 |  |  | 	    0) == -1) | 
    
    | 1314 |  |  | 		goto cleanup; | 
    
    | 1315 |  |  |  | 
    
    | 1316 |  |  | 	len = sizeof *addr + PF_KEY_V2_ROUND(SA_LEN(isa->src_net)); | 
    
    | 1317 |  |  | 	addr = calloc(1, len); | 
    
    | 1318 |  |  | 	if (!addr) | 
    
    | 1319 |  |  | 		goto cleanup; | 
    
    | 1320 |  |  | 	addr->sadb_address_exttype = incoming ? | 
    
    | 1321 |  |  | 	    SADB_X_EXT_DST_FLOW : SADB_X_EXT_SRC_FLOW; | 
    
    | 1322 |  |  | 	addr->sadb_address_len = len / PF_KEY_V2_CHUNK; | 
    
    | 1323 |  |  | 	addr->sadb_address_reserved = 0; | 
    
    | 1324 |  |  | 	pf_key_v2_setup_sockaddr(addr + 1, isa->src_net, 0, isa->sport, 0); | 
    
    | 1325 |  |  | 	if (pf_key_v2_msg_add(update, (struct sadb_ext *) addr, | 
    
    | 1326 |  |  | 	    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 1327 |  |  | 		goto cleanup; | 
    
    | 1328 |  |  | 	addr = 0; | 
    
    | 1329 |  |  |  | 
    
    | 1330 |  |  | 	addr = calloc(1, len); | 
    
    | 1331 |  |  | 	if (!addr) | 
    
    | 1332 |  |  | 		goto cleanup; | 
    
    | 1333 |  |  | 	addr->sadb_address_exttype = | 
    
    | 1334 |  |  | 		incoming ? SADB_X_EXT_DST_MASK : SADB_X_EXT_SRC_MASK; | 
    
    | 1335 |  |  | 	addr->sadb_address_len = len / PF_KEY_V2_CHUNK; | 
    
    | 1336 |  |  | 	addr->sadb_address_reserved = 0; | 
    
    | 1337 |  |  | 	pf_key_v2_setup_sockaddr(addr + 1, isa->src_mask, 0, | 
    
    | 1338 |  |  | 	    isa->sport ? 0xffff : 0, 0); | 
    
    | 1339 |  |  | 	if (pf_key_v2_msg_add(update, (struct sadb_ext *) addr, | 
    
    | 1340 |  |  | 	    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 1341 |  |  | 		goto cleanup; | 
    
    | 1342 |  |  | 	addr = 0; | 
    
    | 1343 |  |  |  | 
    
    | 1344 |  |  | 	addr = calloc(1, len); | 
    
    | 1345 |  |  | 	if (!addr) | 
    
    | 1346 |  |  | 		goto cleanup; | 
    
    | 1347 |  |  | 	addr->sadb_address_exttype = incoming ? | 
    
    | 1348 |  |  | 	    SADB_X_EXT_SRC_FLOW : SADB_X_EXT_DST_FLOW; | 
    
    | 1349 |  |  | 	addr->sadb_address_len = len / PF_KEY_V2_CHUNK; | 
    
    | 1350 |  |  | 	addr->sadb_address_reserved = 0; | 
    
    | 1351 |  |  | 	pf_key_v2_setup_sockaddr(addr + 1, isa->dst_net, 0, isa->dport, 0); | 
    
    | 1352 |  |  | 	if (pf_key_v2_msg_add(update, (struct sadb_ext *) addr, | 
    
    | 1353 |  |  | 	    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 1354 |  |  | 		goto cleanup; | 
    
    | 1355 |  |  | 	addr = 0; | 
    
    | 1356 |  |  |  | 
    
    | 1357 |  |  | 	addr = calloc(1, len); | 
    
    | 1358 |  |  | 	if (!addr) | 
    
    | 1359 |  |  | 		goto cleanup; | 
    
    | 1360 |  |  | 	addr->sadb_address_exttype = | 
    
    | 1361 |  |  | 		incoming ? SADB_X_EXT_SRC_MASK : SADB_X_EXT_DST_MASK; | 
    
    | 1362 |  |  | 	addr->sadb_address_len = len / PF_KEY_V2_CHUNK; | 
    
    | 1363 |  |  | 	addr->sadb_address_reserved = 0; | 
    
    | 1364 |  |  | 	pf_key_v2_setup_sockaddr(addr + 1, isa->dst_mask, 0, | 
    
    | 1365 |  |  | 	    isa->dport ? 0xffff : 0, 0); | 
    
    | 1366 |  |  | 	if (pf_key_v2_msg_add(update, (struct sadb_ext *) addr, | 
    
    | 1367 |  |  | 	    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 1368 |  |  | 		goto cleanup; | 
    
    | 1369 |  |  | 	addr = 0; | 
    
    | 1370 |  |  |  | 
    
    | 1371 |  |  | 	/* Add a pf tag to matching packets of this SA. */ | 
    
    | 1372 |  |  | 	if (sa->tag != NULL) { | 
    
    | 1373 |  |  | 		len = sizeof(*stag) + PF_KEY_V2_ROUND(strlen(sa->tag) + 1); | 
    
    | 1374 |  |  | 		if ((stag = calloc(1, len)) == NULL) | 
    
    | 1375 |  |  | 			goto cleanup; | 
    
    | 1376 |  |  | 		stag->sadb_x_tag_exttype = SADB_X_EXT_TAG; | 
    
    | 1377 |  |  | 		stag->sadb_x_tag_len = len / PF_KEY_V2_CHUNK; | 
    
    | 1378 |  |  | 		stag->sadb_x_tag_taglen = strlen(sa->tag) + 1; | 
    
    | 1379 |  |  | 		s = (char *)(stag + 1); | 
    
    | 1380 |  |  | 		strlcpy(s, sa->tag, stag->sadb_x_tag_taglen); | 
    
    | 1381 |  |  | 		if (pf_key_v2_msg_add(update, (struct sadb_ext *)stag, | 
    
    | 1382 |  |  | 		    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 1383 |  |  | 			goto cleanup; | 
    
    | 1384 |  |  | 	} | 
    
    | 1385 |  |  |  | 
    
    | 1386 |  |  | 	/* XXX Here can sensitivity extensions be setup.  */ | 
    
    | 1387 |  |  |  | 
    
    | 1388 |  |  | 	if (sockaddr2text(dst, &addr_str, 0)) | 
    
    | 1389 |  |  | 		addr_str = 0; | 
    
    | 1390 |  |  |  | 
    
    | 1391 |  |  | 	LOG_DBG((LOG_SYSDEP, 10, "pf_key_v2_set_spi: " | 
    
    | 1392 |  |  | 	    "satype %d dst %s SPI 0x%x%s%s", msg.sadb_msg_satype, | 
    
    | 1393 |  |  | 	    addr_str ? addr_str : "unknown", | 
    
    | 1394 |  |  | 	    ntohl(ssa.sadb_sa_spi), sa->tag ? " tag " : "", | 
    
    | 1395 |  |  | 	    sa->tag ? sa->tag : "")); | 
    
    | 1396 |  |  |  | 
    
    | 1397 |  |  | 	free(addr_str); | 
    
    | 1398 |  |  |  | 
    
    | 1399 |  |  | 	/* | 
    
    | 1400 |  |  | 	 * Although PF_KEY knows about expirations, it is unreliable per the | 
    
    | 1401 |  |  | 	 * specs thus we need to do them inside isakmpd as well. | 
    
    | 1402 |  |  | 	 */ | 
    
    | 1403 |  |  | 	if (sa->seconds) | 
    
    | 1404 |  |  | 		if (sa_setup_expirations(sa)) | 
    
    | 1405 |  |  | 			goto cleanup; | 
    
    | 1406 |  |  |  | 
    
    | 1407 |  |  | 	ret = pf_key_v2_call(update); | 
    
    | 1408 |  |  | 	pf_key_v2_msg_free(update); | 
    
    | 1409 |  |  | 	update = 0; | 
    
    | 1410 |  |  | 	if (!ret) | 
    
    | 1411 |  |  | 		goto cleanup; | 
    
    | 1412 |  |  | 	err = ((struct sadb_msg *)TAILQ_FIRST(ret)->seg)->sadb_msg_errno; | 
    
    | 1413 |  |  | 	pf_key_v2_msg_free(ret); | 
    
    | 1414 |  |  | 	ret = 0; | 
    
    | 1415 |  |  |  | 
    
    | 1416 |  |  | 	/* | 
    
    | 1417 |  |  | 	 * If we are doing an addition into an SADB shared with our peer, | 
    
    | 1418 |  |  | 	 * errors here are to be expected as the peer will already have | 
    
    | 1419 |  |  | 	 * created the SA, and can thus be ignored. | 
    
    | 1420 |  |  | 	 */ | 
    
    | 1421 |  |  | 	if (err && !(msg.sadb_msg_type == SADB_ADD && | 
    
    | 1422 |  |  | 	    conf_get_str("General", "Shared-SADB"))) { | 
    
    | 1423 |  |  | 		log_print("pf_key_v2_set_spi: %s: %s", | 
    
    | 1424 |  |  | 		    msg.sadb_msg_type == SADB_ADD ? "ADD" : "UPDATE", | 
    
    | 1425 |  |  | 		    strerror(err)); | 
    
    | 1426 |  |  | 		goto cleanup; | 
    
    | 1427 |  |  | 	} | 
    
    | 1428 |  |  | 	LOG_DBG((LOG_SYSDEP, 50, "pf_key_v2_set_spi: done")); | 
    
    | 1429 |  |  |  | 
    
    | 1430 |  |  | 	return 0; | 
    
    | 1431 |  |  |  | 
    
    | 1432 |  |  | cleanup: | 
    
    | 1433 |  |  | 	free(sid); | 
    
    | 1434 |  |  | 	free(addr); | 
    
    | 1435 |  |  | 	free(life); | 
    
    | 1436 |  |  | 	free(key); | 
    
    | 1437 |  |  | 	if (update) | 
    
    | 1438 |  |  | 		pf_key_v2_msg_free(update); | 
    
    | 1439 |  |  | 	if (ret) | 
    
    | 1440 |  |  | 		pf_key_v2_msg_free(ret); | 
    
    | 1441 |  |  | 	return -1; | 
    
    | 1442 |  |  | } | 
    
    | 1443 |  |  |  | 
    
    | 1444 |  |  | static __inline__ int | 
    
    | 1445 |  |  | pf_key_v2_mask_to_bits(u_int32_t mask) | 
    
    | 1446 |  |  | { | 
    
    | 1447 |  |  | 	u_int32_t       hmask = ntohl(mask); | 
    
    | 1448 |  |  |  | 
    
    | 1449 |  |  | 	return (33 - ffs(~hmask + 1)) % 33; | 
    
    | 1450 |  |  | } | 
    
    | 1451 |  |  |  | 
    
    | 1452 |  |  | static int | 
    
    | 1453 |  |  | pf_key_v2_mask6_to_bits(u_int8_t *mask) | 
    
    | 1454 |  |  | { | 
    
    | 1455 |  |  | 	int		n; | 
    
    | 1456 |  |  |  | 
    
    | 1457 |  |  | 	bit_ffc(mask, 128, &n); | 
    
    | 1458 |  |  | 	return n == -1 ? 128 : n; | 
    
    | 1459 |  |  | } | 
    
    | 1460 |  |  |  | 
    
    | 1461 |  |  | /* | 
    
    | 1462 |  |  |  * Enable/disable a flow. | 
    
    | 1463 |  |  |  * XXX Assumes OpenBSD {ADD,DEL}FLOW extensions. | 
    
    | 1464 |  |  |  */ | 
    
    | 1465 |  |  | static int | 
    
    | 1466 |  |  | pf_key_v2_flow(struct sockaddr *laddr, struct sockaddr *lmask, | 
    
    | 1467 |  |  |     struct sockaddr *raddr, struct sockaddr *rmask, | 
    
    | 1468 |  |  |     u_int8_t tproto, u_int16_t sport, u_int16_t dport, | 
    
    | 1469 |  |  |     u_int8_t *spi, u_int8_t proto, struct sockaddr *dst, | 
    
    | 1470 |  |  |     struct sockaddr *src, int delete, int ingress, | 
    
    | 1471 |  |  |     u_int8_t srcid_type, u_int8_t *srcid, int srcid_len, | 
    
    | 1472 |  |  |     u_int8_t dstid_type, u_int8_t *dstid, int dstid_len, | 
    
    | 1473 |  |  |     struct ipsec_proto *iproto) | 
    
    | 1474 |  |  | { | 
    
    | 1475 |  |  | 	char           *laddr_str, *lmask_str, *raddr_str, *rmask_str; | 
    
    | 1476 |  |  |  | 
    
    | 1477 |  |  | 	struct sadb_msg msg; | 
    
    | 1478 |  |  | 	struct sadb_protocol flowtype; | 
    
    | 1479 |  |  | 	struct sadb_ident *sid = 0; | 
    
    | 1480 |  |  | 	struct sadb_address *addr = 0; | 
    
    | 1481 |  |  | 	struct sadb_protocol tprotocol; | 
    
    | 1482 |  |  | 	struct pf_key_v2_msg *flow = 0, *ret = 0; | 
    
    | 1483 |  |  | 	size_t		len; | 
    
    | 1484 |  |  | 	int		err; | 
    
    | 1485 |  |  |  | 
    
    | 1486 |  |  | 	msg.sadb_msg_type = delete ? SADB_X_DELFLOW : SADB_X_ADDFLOW; | 
    
    | 1487 |  |  | 	switch (proto) { | 
    
    | 1488 |  |  | 	case IPSEC_PROTO_IPSEC_ESP: | 
    
    | 1489 |  |  | 		msg.sadb_msg_satype = SADB_SATYPE_ESP; | 
    
    | 1490 |  |  | 		break; | 
    
    | 1491 |  |  | 	case IPSEC_PROTO_IPSEC_AH: | 
    
    | 1492 |  |  | 		msg.sadb_msg_satype = SADB_SATYPE_AH; | 
    
    | 1493 |  |  | 		break; | 
    
    | 1494 |  |  | 	case IPSEC_PROTO_IPCOMP: | 
    
    | 1495 |  |  | 		msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP; | 
    
    | 1496 |  |  | 		break; | 
    
    | 1497 |  |  | 	default: | 
    
    | 1498 |  |  | 		log_print("pf_key_v2_flow: invalid proto %d", proto); | 
    
    | 1499 |  |  | 		goto cleanup; | 
    
    | 1500 |  |  | 	} | 
    
    | 1501 |  |  | 	msg.sadb_msg_seq = 0; | 
    
    | 1502 |  |  | 	flow = pf_key_v2_msg_new(&msg, 0); | 
    
    | 1503 |  |  | 	if (!flow) | 
    
    | 1504 |  |  | 		goto cleanup; | 
    
    | 1505 |  |  |  | 
    
    | 1506 |  |  | 	if (!delete) { | 
    
    | 1507 |  |  | 		/* Setup the source ID, if provided. */ | 
    
    | 1508 |  |  | 		if (srcid) { | 
    
    | 1509 |  |  | 			sid = calloc( | 
    
    | 1510 |  |  | 			    PF_KEY_V2_ROUND(srcid_len + 1) + sizeof *sid, | 
    
    | 1511 |  |  | 			    sizeof(u_int8_t)); | 
    
    | 1512 |  |  | 			if (!sid) | 
    
    | 1513 |  |  | 				goto cleanup; | 
    
    | 1514 |  |  |  | 
    
    | 1515 |  |  | 			sid->sadb_ident_len = ((sizeof *sid) / PF_KEY_V2_CHUNK) | 
    
    | 1516 |  |  | 			    + PF_KEY_V2_ROUND(srcid_len + 1) / PF_KEY_V2_CHUNK; | 
    
    | 1517 |  |  | 			sid->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC; | 
    
    | 1518 |  |  | 			sid->sadb_ident_type = srcid_type; | 
    
    | 1519 |  |  |  | 
    
    | 1520 |  |  | 			memcpy(sid + 1, srcid, srcid_len); | 
    
    | 1521 |  |  |  | 
    
    | 1522 |  |  | 			if (pf_key_v2_msg_add(flow, (struct sadb_ext *) sid, | 
    
    | 1523 |  |  | 			    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 1524 |  |  | 				goto cleanup; | 
    
    | 1525 |  |  |  | 
    
    | 1526 |  |  | 			sid = 0; | 
    
    | 1527 |  |  | 		} | 
    
    | 1528 |  |  | 		/* Setup the destination ID, if provided. */ | 
    
    | 1529 |  |  | 		if (dstid) { | 
    
    | 1530 |  |  | 			sid = calloc( | 
    
    | 1531 |  |  | 			    PF_KEY_V2_ROUND(dstid_len + 1) + sizeof *sid, | 
    
    | 1532 |  |  | 			    sizeof(u_int8_t)); | 
    
    | 1533 |  |  | 			if (!sid) | 
    
    | 1534 |  |  | 				goto cleanup; | 
    
    | 1535 |  |  |  | 
    
    | 1536 |  |  | 			sid->sadb_ident_len = ((sizeof *sid) / PF_KEY_V2_CHUNK) | 
    
    | 1537 |  |  | 			    + PF_KEY_V2_ROUND(dstid_len + 1) / PF_KEY_V2_CHUNK; | 
    
    | 1538 |  |  | 			sid->sadb_ident_exttype = SADB_EXT_IDENTITY_DST; | 
    
    | 1539 |  |  | 			sid->sadb_ident_type = dstid_type; | 
    
    | 1540 |  |  |  | 
    
    | 1541 |  |  | 			memcpy(sid + 1, dstid, dstid_len); | 
    
    | 1542 |  |  |  | 
    
    | 1543 |  |  | 			if (pf_key_v2_msg_add(flow, (struct sadb_ext *) sid, | 
    
    | 1544 |  |  | 			    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 1545 |  |  | 				goto cleanup; | 
    
    | 1546 |  |  |  | 
    
    | 1547 |  |  | 			sid = 0; | 
    
    | 1548 |  |  | 		} | 
    
    | 1549 |  |  | 	} | 
    
    | 1550 |  |  | 	/* Setup the flow type extension.  */ | 
    
    | 1551 |  |  | 	bzero(&flowtype, sizeof flowtype); | 
    
    | 1552 |  |  | 	flowtype.sadb_protocol_exttype = SADB_X_EXT_FLOW_TYPE; | 
    
    | 1553 |  |  | 	flowtype.sadb_protocol_len = sizeof flowtype / PF_KEY_V2_CHUNK; | 
    
    | 1554 |  |  | 	flowtype.sadb_protocol_direction = | 
    
    | 1555 |  |  | 	    ingress ? IPSP_DIRECTION_IN : IPSP_DIRECTION_OUT; | 
    
    | 1556 |  |  | 	flowtype.sadb_protocol_proto = | 
    
    | 1557 |  |  | 	    ingress ? SADB_X_FLOW_TYPE_USE : SADB_X_FLOW_TYPE_REQUIRE; | 
    
    | 1558 |  |  |  | 
    
    | 1559 |  |  | 	if (pf_key_v2_msg_add(flow, (struct sadb_ext *)&flowtype, 0) == -1) | 
    
    | 1560 |  |  | 		goto cleanup; | 
    
    | 1561 |  |  |  | 
    
    | 1562 |  |  | 	/* | 
    
    | 1563 |  |  | 	 * Setup the ADDRESS extensions. | 
    
    | 1564 |  |  | 	 */ | 
    
    | 1565 |  |  | 	len = sizeof *addr + PF_KEY_V2_ROUND(SA_LEN(src)); | 
    
    | 1566 |  |  | 	if (!delete) | 
    
    | 1567 |  |  | 	{ | 
    
    | 1568 |  |  | 		addr = calloc(1, len); | 
    
    | 1569 |  |  | 		if (!addr) | 
    
    | 1570 |  |  | 			goto cleanup; | 
    
    | 1571 |  |  | 		addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; | 
    
    | 1572 |  |  | 		addr->sadb_address_len = len / PF_KEY_V2_CHUNK; | 
    
    | 1573 |  |  | 		addr->sadb_address_reserved = 0; | 
    
    | 1574 |  |  | 		pf_key_v2_setup_sockaddr(addr + 1, src, dst, 0, ingress); | 
    
    | 1575 |  |  | 		if (pf_key_v2_msg_add(flow, (struct sadb_ext *) addr, | 
    
    | 1576 |  |  | 		    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 1577 |  |  | 			goto cleanup; | 
    
    | 1578 |  |  | 		addr = 0; | 
    
    | 1579 |  |  | 	} | 
    
    | 1580 |  |  | 	len = sizeof *addr + PF_KEY_V2_ROUND(SA_LEN(laddr)); | 
    
    | 1581 |  |  | 	addr = calloc(1, len); | 
    
    | 1582 |  |  | 	if (!addr) | 
    
    | 1583 |  |  | 		goto cleanup; | 
    
    | 1584 |  |  | 	addr->sadb_address_exttype = SADB_X_EXT_SRC_FLOW; | 
    
    | 1585 |  |  | 	addr->sadb_address_len = len / PF_KEY_V2_CHUNK; | 
    
    | 1586 |  |  | 	addr->sadb_address_reserved = 0; | 
    
    | 1587 |  |  | 	pf_key_v2_setup_sockaddr(addr + 1, laddr, 0, sport, 0); | 
    
    | 1588 |  |  | 	if (pf_key_v2_msg_add(flow, (struct sadb_ext *) addr, | 
    
    | 1589 |  |  | 	    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 1590 |  |  | 		goto cleanup; | 
    
    | 1591 |  |  | 	addr = 0; | 
    
    | 1592 |  |  |  | 
    
    | 1593 |  |  | 	addr = calloc(1, len); | 
    
    | 1594 |  |  | 	if (!addr) | 
    
    | 1595 |  |  | 		goto cleanup; | 
    
    | 1596 |  |  | 	addr->sadb_address_exttype = SADB_X_EXT_SRC_MASK; | 
    
    | 1597 |  |  | 	addr->sadb_address_len = len / PF_KEY_V2_CHUNK; | 
    
    | 1598 |  |  | 	addr->sadb_address_reserved = 0; | 
    
    | 1599 |  |  | 	pf_key_v2_setup_sockaddr(addr + 1, lmask, 0, sport ? 0xffff : 0, 0); | 
    
    | 1600 |  |  | 	if (pf_key_v2_msg_add(flow, (struct sadb_ext *) addr, | 
    
    | 1601 |  |  | 	    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 1602 |  |  | 		goto cleanup; | 
    
    | 1603 |  |  | 	addr = 0; | 
    
    | 1604 |  |  |  | 
    
    | 1605 |  |  | 	addr = calloc(1, len); | 
    
    | 1606 |  |  | 	if (!addr) | 
    
    | 1607 |  |  | 		goto cleanup; | 
    
    | 1608 |  |  | 	addr->sadb_address_exttype = SADB_X_EXT_DST_FLOW; | 
    
    | 1609 |  |  | 	addr->sadb_address_len = len / PF_KEY_V2_CHUNK; | 
    
    | 1610 |  |  | 	addr->sadb_address_reserved = 0; | 
    
    | 1611 |  |  | 	pf_key_v2_setup_sockaddr(addr + 1, raddr, 0, dport, 0); | 
    
    | 1612 |  |  | 	if (pf_key_v2_msg_add(flow, (struct sadb_ext *) addr, | 
    
    | 1613 |  |  | 	    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 1614 |  |  | 		goto cleanup; | 
    
    | 1615 |  |  | 	addr = 0; | 
    
    | 1616 |  |  |  | 
    
    | 1617 |  |  | 	addr = calloc(1, len); | 
    
    | 1618 |  |  | 	if (!addr) | 
    
    | 1619 |  |  | 		goto cleanup; | 
    
    | 1620 |  |  | 	addr->sadb_address_exttype = SADB_X_EXT_DST_MASK; | 
    
    | 1621 |  |  | 	addr->sadb_address_len = len / PF_KEY_V2_CHUNK; | 
    
    | 1622 |  |  | 	addr->sadb_address_reserved = 0; | 
    
    | 1623 |  |  | 	pf_key_v2_setup_sockaddr(addr + 1, rmask, 0, dport ? 0xffff : 0, 0); | 
    
    | 1624 |  |  | 	if (pf_key_v2_msg_add(flow, (struct sadb_ext *) addr, | 
    
    | 1625 |  |  | 	    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 1626 |  |  | 		goto cleanup; | 
    
    | 1627 |  |  | 	addr = 0; | 
    
    | 1628 |  |  |  | 
    
    | 1629 |  |  | 	/* Setup the protocol extension.  */ | 
    
    | 1630 |  |  | 	bzero(&tprotocol, sizeof tprotocol); | 
    
    | 1631 |  |  | 	tprotocol.sadb_protocol_exttype = SADB_X_EXT_PROTOCOL; | 
    
    | 1632 |  |  | 	tprotocol.sadb_protocol_len = sizeof tprotocol / PF_KEY_V2_CHUNK; | 
    
    | 1633 |  |  | 	tprotocol.sadb_protocol_proto = tproto; | 
    
    | 1634 |  |  |  | 
    
    | 1635 |  |  | 	if (pf_key_v2_msg_add(flow, (struct sadb_ext *)&tprotocol, 0) == -1) | 
    
    | 1636 |  |  | 		goto cleanup; | 
    
    | 1637 |  |  |  | 
    
    | 1638 |  |  | 	if (sockaddr2text(laddr, &laddr_str, 0)) | 
    
    | 1639 |  |  | 		laddr_str = 0; | 
    
    | 1640 |  |  | 	if (sockaddr2text(lmask, &lmask_str, 0)) | 
    
    | 1641 |  |  | 		lmask_str = 0; | 
    
    | 1642 |  |  | 	if (sockaddr2text(raddr, &raddr_str, 0)) | 
    
    | 1643 |  |  | 		raddr_str = 0; | 
    
    | 1644 |  |  | 	if (sockaddr2text(rmask, &rmask_str, 0)) | 
    
    | 1645 |  |  | 		rmask_str = 0; | 
    
    | 1646 |  |  |  | 
    
    | 1647 |  |  | 	LOG_DBG((LOG_SYSDEP, 50, | 
    
    | 1648 |  |  | 	   "pf_key_v2_flow: src %s %s dst %s %s proto %u sport %u dport %u", | 
    
    | 1649 |  |  | 	 laddr_str ? laddr_str : "<??\?>", lmask_str ? lmask_str : "<??\?>", | 
    
    | 1650 |  |  | 	 raddr_str ? raddr_str : "<??\?>", rmask_str ? rmask_str : "<??\?>", | 
    
    | 1651 |  |  | 		 tproto, ntohs(sport), ntohs(dport))); | 
    
    | 1652 |  |  |  | 
    
    | 1653 |  |  | 	free(laddr_str); | 
    
    | 1654 |  |  | 	free(lmask_str); | 
    
    | 1655 |  |  | 	free(raddr_str); | 
    
    | 1656 |  |  | 	free(rmask_str); | 
    
    | 1657 |  |  |  | 
    
    | 1658 |  |  | 	ret = pf_key_v2_call(flow); | 
    
    | 1659 |  |  | 	pf_key_v2_msg_free(flow); | 
    
    | 1660 |  |  | 	flow = 0; | 
    
    | 1661 |  |  | 	if (!ret) | 
    
    | 1662 |  |  | 		goto cleanup; | 
    
    | 1663 |  |  | 	err = ((struct sadb_msg *)TAILQ_FIRST(ret)->seg)->sadb_msg_errno; | 
    
    | 1664 |  |  | 	if (err) { | 
    
    | 1665 |  |  | 		if (err == ESRCH)	/* These are common and usually | 
    
    | 1666 |  |  | 					 * harmless.  */ | 
    
    | 1667 |  |  | 			LOG_DBG((LOG_SYSDEP, 10, "pf_key_v2_flow: %sFLOW: %s", | 
    
    | 1668 |  |  | 				 delete ? "DEL" : "ADD", strerror(err))); | 
    
    | 1669 |  |  | 		else | 
    
    | 1670 |  |  | 			log_print("pf_key_v2_flow: %sFLOW: %s", | 
    
    | 1671 |  |  | 			    delete ? "DEL" : "ADD", strerror(err)); | 
    
    | 1672 |  |  | 		goto cleanup; | 
    
    | 1673 |  |  | 	} | 
    
    | 1674 |  |  | 	pf_key_v2_msg_free(ret); | 
    
    | 1675 |  |  |  | 
    
    | 1676 |  |  | 	LOG_DBG((LOG_MISC, 50, "pf_key_v2_flow: %sFLOW: done", | 
    
    | 1677 |  |  | 		 delete ? "DEL" : "ADD")); | 
    
    | 1678 |  |  |  | 
    
    | 1679 |  |  | 	return 0; | 
    
    | 1680 |  |  |  | 
    
    | 1681 |  |  | cleanup: | 
    
    | 1682 |  |  | 	free(sid); | 
    
    | 1683 |  |  | 	free(addr); | 
    
    | 1684 |  |  | 	if (flow) | 
    
    | 1685 |  |  | 		pf_key_v2_msg_free(flow); | 
    
    | 1686 |  |  | 	if (ret) | 
    
    | 1687 |  |  | 		pf_key_v2_msg_free(ret); | 
    
    | 1688 |  |  | 	return -1; | 
    
    | 1689 |  |  | } | 
    
    | 1690 |  |  |  | 
    
    | 1691 |  |  | static u_int8_t * | 
    
    | 1692 |  |  | pf_key_v2_convert_id(u_int8_t *id, int idlen, size_t *reslen, int *idtype) | 
    
    | 1693 |  |  | { | 
    
    | 1694 |  |  | 	u_int8_t       *addr, *res = 0; | 
    
    | 1695 |  |  | 	char		addrbuf[ADDRESS_MAX + 5]; | 
    
    | 1696 |  |  |  | 
    
    | 1697 |  |  | 	switch (id[0]) { | 
    
    | 1698 |  |  | 	case IPSEC_ID_FQDN: | 
    
    | 1699 |  |  | 		res = calloc(idlen - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ, | 
    
    | 1700 |  |  | 		    sizeof(u_int8_t)); | 
    
    | 1701 |  |  | 		if (!res) | 
    
    | 1702 |  |  | 			return 0; | 
    
    | 1703 |  |  |  | 
    
    | 1704 |  |  | 		*reslen = idlen - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ; | 
    
    | 1705 |  |  | 		memcpy(res, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, *reslen); | 
    
    | 1706 |  |  | 		*idtype = SADB_IDENTTYPE_FQDN; | 
    
    | 1707 |  |  | 		LOG_DBG((LOG_SYSDEP, 40, "pf_key_v2_convert_id: FQDN %.*s", | 
    
    | 1708 |  |  | 		    (int) *reslen, res)); | 
    
    | 1709 |  |  | 		return res; | 
    
    | 1710 |  |  |  | 
    
    | 1711 |  |  | 	case IPSEC_ID_USER_FQDN: | 
    
    | 1712 |  |  | 		res = calloc(idlen - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ, | 
    
    | 1713 |  |  | 		    sizeof(u_int8_t)); | 
    
    | 1714 |  |  | 		if (!res) | 
    
    | 1715 |  |  | 			return 0; | 
    
    | 1716 |  |  |  | 
    
    | 1717 |  |  | 		*reslen = idlen - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ; | 
    
    | 1718 |  |  | 		memcpy(res, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, *reslen); | 
    
    | 1719 |  |  | 		*idtype = SADB_IDENTTYPE_USERFQDN; | 
    
    | 1720 |  |  | 		LOG_DBG((LOG_SYSDEP, 40, "pf_key_v2_convert_id: UFQDN %.*s", | 
    
    | 1721 |  |  | 		    (int) *reslen, res)); | 
    
    | 1722 |  |  | 		return res; | 
    
    | 1723 |  |  |  | 
    
    | 1724 |  |  | 	case IPSEC_ID_IPV4_ADDR: | 
    
    | 1725 |  |  | 		if (inet_ntop(AF_INET, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, | 
    
    | 1726 |  |  | 		    addrbuf, ADDRESS_MAX) == NULL) | 
    
    | 1727 |  |  | 			return 0; | 
    
    | 1728 |  |  | 		*reslen = strlen(addrbuf) + 3; | 
    
    | 1729 |  |  | 		strlcat(addrbuf, "/32", ADDRESS_MAX + 5); | 
    
    | 1730 |  |  | 		res = (u_int8_t *) strdup(addrbuf); | 
    
    | 1731 |  |  | 		if (!res) | 
    
    | 1732 |  |  | 			return 0; | 
    
    | 1733 |  |  | 		*idtype = SADB_IDENTTYPE_PREFIX; | 
    
    | 1734 |  |  | 		LOG_DBG((LOG_SYSDEP, 40, "pf_key_v2_convert_id: " | 
    
    | 1735 |  |  | 		    "IPv4 address %s", res)); | 
    
    | 1736 |  |  | 		return res; | 
    
    | 1737 |  |  |  | 
    
    | 1738 |  |  | 	case IPSEC_ID_IPV6_ADDR: | 
    
    | 1739 |  |  | 		if (inet_ntop(AF_INET6, | 
    
    | 1740 |  |  | 		    id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, | 
    
    | 1741 |  |  | 		    addrbuf, ADDRESS_MAX) == NULL) | 
    
    | 1742 |  |  | 			return 0; | 
    
    | 1743 |  |  | 		*reslen = strlen(addrbuf) + 4; | 
    
    | 1744 |  |  | 		strlcat(addrbuf, "/128", ADDRESS_MAX + 5); | 
    
    | 1745 |  |  | 		res = (u_int8_t *) strdup(addrbuf); | 
    
    | 1746 |  |  | 		if (!res) | 
    
    | 1747 |  |  | 			return 0; | 
    
    | 1748 |  |  | 		LOG_DBG((LOG_SYSDEP, 40, "pf_key_v2_convert_id: " | 
    
    | 1749 |  |  | 		    "IPv6 address %s", res)); | 
    
    | 1750 |  |  | 		*idtype = SADB_IDENTTYPE_PREFIX; | 
    
    | 1751 |  |  | 		return res; | 
    
    | 1752 |  |  |  | 
    
    | 1753 |  |  | 	case IPSEC_ID_IPV4_ADDR_SUBNET:	/* XXX PREFIX */ | 
    
    | 1754 |  |  | 		addr = id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; | 
    
    | 1755 |  |  | 		if (inet_ntop(AF_INET, addr, addrbuf, ADDRESS_MAX) == NULL) | 
    
    | 1756 |  |  | 			return 0; | 
    
    | 1757 |  |  | 		snprintf(addrbuf + strlen(addrbuf), | 
    
    | 1758 |  |  | 		    ADDRESS_MAX - strlen(addrbuf), "/%d", | 
    
    | 1759 |  |  | 		    pf_key_v2_mask_to_bits(*(u_int32_t *)(addr + | 
    
    | 1760 |  |  | 			sizeof(struct in_addr)))); | 
    
    | 1761 |  |  | 		*reslen = strlen(addrbuf); | 
    
    | 1762 |  |  | 		res = (u_int8_t *) strdup(addrbuf); | 
    
    | 1763 |  |  | 		if (!res) | 
    
    | 1764 |  |  | 			return 0; | 
    
    | 1765 |  |  | 		*idtype = SADB_IDENTTYPE_PREFIX; | 
    
    | 1766 |  |  | 		LOG_DBG((LOG_SYSDEP, 40, "pf_key_v2_convert_id: " | 
    
    | 1767 |  |  | 		    "IPv4 subnet %s", res)); | 
    
    | 1768 |  |  | 		return res; | 
    
    | 1769 |  |  |  | 
    
    | 1770 |  |  | 	case IPSEC_ID_IPV6_ADDR_SUBNET:	/* XXX PREFIX */ | 
    
    | 1771 |  |  | 		addr = id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; | 
    
    | 1772 |  |  | 		if (inet_ntop(AF_INET6, addr, addrbuf, ADDRESS_MAX) == NULL) | 
    
    | 1773 |  |  | 			return 0; | 
    
    | 1774 |  |  | 		snprintf(addrbuf + strlen(addrbuf), | 
    
    | 1775 |  |  | 		    ADDRESS_MAX - strlen(addrbuf), "/%d", | 
    
    | 1776 |  |  | 		    pf_key_v2_mask6_to_bits(addr + | 
    
    | 1777 |  |  | 			sizeof(struct in6_addr))); | 
    
    | 1778 |  |  | 		*reslen = strlen(addrbuf); | 
    
    | 1779 |  |  | 		res = (u_int8_t *) strdup(addrbuf); | 
    
    | 1780 |  |  | 		if (!res) | 
    
    | 1781 |  |  | 			return 0; | 
    
    | 1782 |  |  | 		LOG_DBG((LOG_SYSDEP, 40, "pf_key_v2_convert_id: " | 
    
    | 1783 |  |  | 		    "IPv6 subnet %s", res)); | 
    
    | 1784 |  |  | 		*idtype = SADB_IDENTTYPE_PREFIX; | 
    
    | 1785 |  |  | 		return res; | 
    
    | 1786 |  |  |  | 
    
    | 1787 |  |  | 	case IPSEC_ID_IPV4_RANGE: | 
    
    | 1788 |  |  | 	case IPSEC_ID_IPV6_RANGE: | 
    
    | 1789 |  |  | 	case IPSEC_ID_DER_ASN1_DN: | 
    
    | 1790 |  |  | 	case IPSEC_ID_DER_ASN1_GN: | 
    
    | 1791 |  |  | 	case IPSEC_ID_KEY_ID: | 
    
    | 1792 |  |  | 		/* XXX Not implemented yet.  */ | 
    
    | 1793 |  |  | 		return 0; | 
    
    | 1794 |  |  | 	} | 
    
    | 1795 |  |  |  | 
    
    | 1796 |  |  | 	return 0; | 
    
    | 1797 |  |  | } | 
    
    | 1798 |  |  |  | 
    
    | 1799 |  |  | /* Enable a flow given an SA.  */ | 
    
    | 1800 |  |  | int | 
    
    | 1801 |  |  | pf_key_v2_enable_sa(struct sa *sa, struct sa *isakmp_sa) | 
    
    | 1802 |  |  | { | 
    
    | 1803 |  |  | 	struct ipsec_sa *isa = sa->data; | 
    
    | 1804 |  |  | 	struct sockaddr *dst, *src; | 
    
    | 1805 |  |  | 	int		error; | 
    
    | 1806 |  |  | 	struct proto   *proto = TAILQ_FIRST(&sa->protos); | 
    
    | 1807 |  |  | 	int		sidtype = 0, didtype = 0; | 
    
    | 1808 |  |  | 	size_t		sidlen = 0, didlen = 0; | 
    
    | 1809 |  |  | 	u_int8_t       *sid = 0, *did = 0; | 
    
    | 1810 |  |  |  | 
    
    | 1811 |  |  | 	sa->transport->vtbl->get_dst(sa->transport, &dst); | 
    
    | 1812 |  |  | 	sa->transport->vtbl->get_src(sa->transport, &src); | 
    
    | 1813 |  |  |  | 
    
    | 1814 |  |  | 	if (isakmp_sa->id_i) { | 
    
    | 1815 |  |  | 		if (isakmp_sa->initiator) | 
    
    | 1816 |  |  | 			sid = pf_key_v2_convert_id(isakmp_sa->id_i, | 
    
    | 1817 |  |  | 			    isakmp_sa->id_i_len, &sidlen, &sidtype); | 
    
    | 1818 |  |  | 		else | 
    
    | 1819 |  |  | 			did = pf_key_v2_convert_id(isakmp_sa->id_i, | 
    
    | 1820 |  |  | 			    isakmp_sa->id_i_len, &didlen, &didtype); | 
    
    | 1821 |  |  | 	} | 
    
    | 1822 |  |  | 	if (isakmp_sa->id_r) { | 
    
    | 1823 |  |  | 		if (isakmp_sa->initiator) | 
    
    | 1824 |  |  | 			did = pf_key_v2_convert_id(isakmp_sa->id_r, | 
    
    | 1825 |  |  | 			    isakmp_sa->id_r_len, &didlen, &didtype); | 
    
    | 1826 |  |  | 		else | 
    
    | 1827 |  |  | 			sid = pf_key_v2_convert_id(isakmp_sa->id_r, | 
    
    | 1828 |  |  | 			    isakmp_sa->id_r_len, &sidlen, &sidtype); | 
    
    | 1829 |  |  | 	} | 
    
    | 1830 |  |  |  | 
    
    | 1831 |  |  | 	error = pf_key_v2_flow(isa->src_net, isa->src_mask, isa->dst_net, | 
    
    | 1832 |  |  | 	    isa->dst_mask, isa->tproto, isa->sport, isa->dport, proto->spi[0], | 
    
    | 1833 |  |  | 	    proto->proto, dst, src, 0, 0, sidtype, sid, sidlen, didtype, did, | 
    
    | 1834 |  |  | 	    didlen, proto->data); | 
    
    | 1835 |  |  | 	if (error) | 
    
    | 1836 |  |  | 		goto cleanup; | 
    
    | 1837 |  |  |  | 
    
    | 1838 |  |  | 	error = pf_key_v2_flow(isa->dst_net, isa->dst_mask, isa->src_net, | 
    
    | 1839 |  |  | 	    isa->src_mask, isa->tproto, isa->dport, isa->sport, proto->spi[1], | 
    
    | 1840 |  |  | 	    proto->proto, src, dst, 0, 1, sidtype, sid, sidlen, didtype, did, | 
    
    | 1841 |  |  | 	    didlen, proto->data); | 
    
    | 1842 |  |  |  | 
    
    | 1843 |  |  | cleanup: | 
    
    | 1844 |  |  | 	free(sid); | 
    
    | 1845 |  |  | 	free(did); | 
    
    | 1846 |  |  |  | 
    
    | 1847 |  |  | 	return error; | 
    
    | 1848 |  |  | } | 
    
    | 1849 |  |  |  | 
    
    | 1850 |  |  | /* Increase reference count of refcounted sections. */ | 
    
    | 1851 |  |  | static int | 
    
    | 1852 |  |  | pf_key_v2_conf_refinc(int af, char *section) | 
    
    | 1853 |  |  | { | 
    
    | 1854 |  |  | 	char		conn[22]; | 
    
    | 1855 |  |  | 	int		num; | 
    
    | 1856 |  |  |  | 
    
    | 1857 |  |  | 	if (!section) | 
    
    | 1858 |  |  | 		return 0; | 
    
    | 1859 |  |  |  | 
    
    | 1860 |  |  | 	num = conf_get_num(section, "Refcount", 0); | 
    
    | 1861 |  |  | 	if (num == 0) | 
    
    | 1862 |  |  | 		return 0; | 
    
    | 1863 |  |  |  | 
    
    | 1864 |  |  | 	snprintf(conn, sizeof conn, "%d", num + 1); | 
    
    | 1865 |  |  | 	conf_set(af, section, "Refcount", conn, 1, 0); | 
    
    | 1866 |  |  | 	return 0; | 
    
    | 1867 |  |  | } | 
    
    | 1868 |  |  |  | 
    
    | 1869 |  |  | /* | 
    
    | 1870 |  |  |  * Return 0 if the section didn't exist or was removed, non-zero otherwise. | 
    
    | 1871 |  |  |  * Don't touch non-refcounted (statically defined) sections. | 
    
    | 1872 |  |  |  */ | 
    
    | 1873 |  |  | static int | 
    
    | 1874 |  |  | pf_key_v2_conf_refhandle(int af, char *section) | 
    
    | 1875 |  |  | { | 
    
    | 1876 |  |  | 	char		conn[22]; | 
    
    | 1877 |  |  | 	int		num; | 
    
    | 1878 |  |  |  | 
    
    | 1879 |  |  | 	if (!section) | 
    
    | 1880 |  |  | 		return 0; | 
    
    | 1881 |  |  |  | 
    
    | 1882 |  |  | 	num = conf_get_num(section, "Refcount", 0); | 
    
    | 1883 |  |  | 	if (num == 1) { | 
    
    | 1884 |  |  | 		conf_remove_section(af, section); | 
    
    | 1885 |  |  | 		num--; | 
    
    | 1886 |  |  | 	} else if (num != 0) { | 
    
    | 1887 |  |  | 		snprintf(conn, sizeof conn, "%d", num - 1); | 
    
    | 1888 |  |  | 		conf_set(af, section, "Refcount", conn, 1, 0); | 
    
    | 1889 |  |  | 	} | 
    
    | 1890 |  |  | 	return num; | 
    
    | 1891 |  |  | } | 
    
    | 1892 |  |  |  | 
    
    | 1893 |  |  | /* Remove all dynamically-established configuration entries.  */ | 
    
    | 1894 |  |  | static int | 
    
    | 1895 |  |  | pf_key_v2_remove_conf(char *section) | 
    
    | 1896 |  |  | { | 
    
    | 1897 |  |  | 	char           *ikepeer, *localid, *remoteid, *configname; | 
    
    | 1898 |  |  | 	struct conf_list_node *attr; | 
    
    | 1899 |  |  | 	struct conf_list *attrs; | 
    
    | 1900 |  |  | 	int		af; | 
    
    | 1901 |  |  |  | 
    
    | 1902 |  |  | 	if (!section) | 
    
    | 1903 |  |  | 		return 0; | 
    
    | 1904 |  |  |  | 
    
    | 1905 |  |  | 	if (!conf_get_str(section, "Phase")) | 
    
    | 1906 |  |  | 		return 0; | 
    
    | 1907 |  |  |  | 
    
    | 1908 |  |  | 	/* Only remove dynamically-established entries. */ | 
    
    | 1909 |  |  | 	attrs = conf_get_list(section, "Flags"); | 
    
    | 1910 |  |  | 	if (attrs) { | 
    
    | 1911 |  |  | 		for (attr = TAILQ_FIRST(&attrs->fields); attr; | 
    
    | 1912 |  |  | 		    attr = TAILQ_NEXT(attr, link)) | 
    
    | 1913 |  |  | 			if (!strcasecmp(attr->field, "__ondemand")) | 
    
    | 1914 |  |  | 				goto passed; | 
    
    | 1915 |  |  |  | 
    
    | 1916 |  |  | 		conf_free_list(attrs); | 
    
    | 1917 |  |  | 	} | 
    
    | 1918 |  |  | 	return 0; | 
    
    | 1919 |  |  |  | 
    
    | 1920 |  |  | passed: | 
    
    | 1921 |  |  | 	conf_free_list(attrs); | 
    
    | 1922 |  |  |  | 
    
    | 1923 |  |  | 	af = conf_begin(); | 
    
    | 1924 |  |  |  | 
    
    | 1925 |  |  | 	configname = conf_get_str(section, "Configuration"); | 
    
    | 1926 |  |  | 	pf_key_v2_conf_refhandle(af, configname); | 
    
    | 1927 |  |  |  | 
    
    | 1928 |  |  | 	/* These are the Phase 2 Local/Remote IDs. */ | 
    
    | 1929 |  |  | 	localid = conf_get_str(section, "Local-ID"); | 
    
    | 1930 |  |  | 	pf_key_v2_conf_refhandle(af, localid); | 
    
    | 1931 |  |  |  | 
    
    | 1932 |  |  | 	remoteid = conf_get_str(section, "Remote-ID"); | 
    
    | 1933 |  |  | 	pf_key_v2_conf_refhandle(af, remoteid); | 
    
    | 1934 |  |  |  | 
    
    | 1935 |  |  | 	ikepeer = conf_get_str(section, "ISAKMP-peer"); | 
    
    | 1936 |  |  |  | 
    
    | 1937 |  |  | 	pf_key_v2_conf_refhandle(af, section); | 
    
    | 1938 |  |  |  | 
    
    | 1939 |  |  | 	if (ikepeer) { | 
    
    | 1940 |  |  | 		remoteid = conf_get_str(ikepeer, "Remote-ID"); | 
    
    | 1941 |  |  | 		localid = conf_get_str(ikepeer, "ID"); | 
    
    | 1942 |  |  | 		configname = conf_get_str(ikepeer, "Configuration"); | 
    
    | 1943 |  |  |  | 
    
    | 1944 |  |  | 		pf_key_v2_conf_refhandle(af, ikepeer); | 
    
    | 1945 |  |  | 		pf_key_v2_conf_refhandle(af, configname); | 
    
    | 1946 |  |  |  | 
    
    | 1947 |  |  | 		/* Phase 1 IDs */ | 
    
    | 1948 |  |  | 		pf_key_v2_conf_refhandle(af, localid); | 
    
    | 1949 |  |  | 		pf_key_v2_conf_refhandle(af, remoteid); | 
    
    | 1950 |  |  | 	} | 
    
    | 1951 |  |  | 	conf_end(af, 1); | 
    
    | 1952 |  |  | 	return 0; | 
    
    | 1953 |  |  | } | 
    
    | 1954 |  |  |  | 
    
    | 1955 |  |  | /* Disable a flow given a SA.  */ | 
    
    | 1956 |  |  | int | 
    
    | 1957 |  |  | pf_key_v2_disable_sa(struct sa *sa, int incoming) | 
    
    | 1958 |  |  | { | 
    
    | 1959 |  |  | 	struct ipsec_sa *isa = sa->data; | 
    
    | 1960 |  |  | 	struct sockaddr *dst, *src; | 
    
    | 1961 |  |  | 	struct proto   *proto = TAILQ_FIRST(&sa->protos); | 
    
    | 1962 |  |  |  | 
    
    | 1963 |  |  | 	sa->transport->vtbl->get_dst(sa->transport, &dst); | 
    
    | 1964 |  |  | 	sa->transport->vtbl->get_src(sa->transport, &src); | 
    
    | 1965 |  |  |  | 
    
    | 1966 |  |  | 	if (!incoming) | 
    
    | 1967 |  |  | 		return pf_key_v2_flow(isa->src_net, isa->src_mask, | 
    
    | 1968 |  |  | 		    isa->dst_net, isa->dst_mask, isa->tproto, isa->sport, | 
    
    | 1969 |  |  | 		    isa->dport, proto->spi[0], proto->proto, src, dst, 1, 0, | 
    
    | 1970 |  |  | 		    0, 0, 0, 0, 0, 0, proto->data); | 
    
    | 1971 |  |  | 	else { | 
    
    | 1972 |  |  | 		return pf_key_v2_flow(isa->dst_net, isa->dst_mask, | 
    
    | 1973 |  |  | 		    isa->src_net, isa->src_mask, isa->tproto, isa->dport, | 
    
    | 1974 |  |  | 		    isa->sport, proto->spi[1], proto->proto, src, dst, 1, 1, | 
    
    | 1975 |  |  | 		    0, 0, 0, 0, 0, 0, proto->data); | 
    
    | 1976 |  |  | 	} | 
    
    | 1977 |  |  | } | 
    
    | 1978 |  |  |  | 
    
    | 1979 |  |  | /* | 
    
    | 1980 |  |  |  * Delete the IPsec SA represented by the INCOMING direction in protocol PROTO | 
    
    | 1981 |  |  |  * of the IKE security association SA.  Also delete potential flows tied to it. | 
    
    | 1982 |  |  |  */ | 
    
    | 1983 |  |  | int | 
    
    | 1984 |  |  | pf_key_v2_delete_spi(struct sa *sa, struct proto *proto, int incoming) | 
    
    | 1985 |  |  | { | 
    
    | 1986 |  |  | 	struct sadb_msg msg; | 
    
    | 1987 |  |  | 	struct sadb_sa  ssa; | 
    
    | 1988 |  |  | 	struct sadb_address *addr = 0; | 
    
    | 1989 |  |  | 	struct sockaddr *saddr; | 
    
    | 1990 |  |  | 	int		len, err; | 
    
    | 1991 |  |  | 	struct pf_key_v2_msg *delete = 0, *ret = 0; | 
    
    | 1992 |  |  |  | 
    
    | 1993 |  |  | 	/* If it's not an established SA, don't proceed. */ | 
    
    | 1994 |  |  | 	if (!(sa->flags & SA_FLAG_READY)) | 
    
    | 1995 |  |  | 		return 0; | 
    
    | 1996 |  |  |  | 
    
    | 1997 |  |  | 	if (sa->name && !(sa->flags & SA_FLAG_REPLACED)) { | 
    
    | 1998 |  |  | 		LOG_DBG((LOG_SYSDEP, 50, | 
    
    | 1999 |  |  | 			 "pf_key_v2_delete_spi: removing configuration %s", | 
    
    | 2000 |  |  | 			 sa->name)); | 
    
    | 2001 |  |  | 		pf_key_v2_remove_conf(sa->name); | 
    
    | 2002 |  |  | 	} | 
    
    | 2003 |  |  | 	msg.sadb_msg_type = SADB_DELETE; | 
    
    | 2004 |  |  | 	switch (proto->proto) { | 
    
    | 2005 |  |  | 	case IPSEC_PROTO_IPSEC_ESP: | 
    
    | 2006 |  |  | 		msg.sadb_msg_satype = SADB_SATYPE_ESP; | 
    
    | 2007 |  |  | 		break; | 
    
    | 2008 |  |  | 	case IPSEC_PROTO_IPSEC_AH: | 
    
    | 2009 |  |  | 		msg.sadb_msg_satype = SADB_SATYPE_AH; | 
    
    | 2010 |  |  | 		break; | 
    
    | 2011 |  |  | 	case IPSEC_PROTO_IPCOMP: | 
    
    | 2012 |  |  | 		msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP; | 
    
    | 2013 |  |  | 		break; | 
    
    | 2014 |  |  | 	default: | 
    
    | 2015 |  |  | 		log_print("pf_key_v2_delete_spi: invalid proto %d", | 
    
    | 2016 |  |  | 		    proto->proto); | 
    
    | 2017 |  |  | 		goto cleanup; | 
    
    | 2018 |  |  | 	} | 
    
    | 2019 |  |  | 	msg.sadb_msg_seq = 0; | 
    
    | 2020 |  |  | 	delete = pf_key_v2_msg_new(&msg, 0); | 
    
    | 2021 |  |  | 	if (!delete) | 
    
    | 2022 |  |  | 		goto cleanup; | 
    
    | 2023 |  |  |  | 
    
    | 2024 |  |  | 	/* Setup the SA extension.  */ | 
    
    | 2025 |  |  | 	ssa.sadb_sa_exttype = SADB_EXT_SA; | 
    
    | 2026 |  |  | 	ssa.sadb_sa_len = sizeof ssa / PF_KEY_V2_CHUNK; | 
    
    | 2027 |  |  | 	memcpy(&ssa.sadb_sa_spi, proto->spi[incoming], sizeof ssa.sadb_sa_spi); | 
    
    | 2028 |  |  | 	ssa.sadb_sa_replay = 0; | 
    
    | 2029 |  |  | 	ssa.sadb_sa_state = 0; | 
    
    | 2030 |  |  | 	ssa.sadb_sa_auth = 0; | 
    
    | 2031 |  |  | 	ssa.sadb_sa_encrypt = 0; | 
    
    | 2032 |  |  | 	ssa.sadb_sa_flags = 0; | 
    
    | 2033 |  |  | 	if (pf_key_v2_msg_add(delete, (struct sadb_ext *)&ssa, 0) == -1) | 
    
    | 2034 |  |  | 		goto cleanup; | 
    
    | 2035 |  |  |  | 
    
    | 2036 |  |  | 	/* | 
    
    | 2037 |  |  | 	 * Setup the ADDRESS extensions. | 
    
    | 2038 |  |  | 	 */ | 
    
    | 2039 |  |  | 	if (incoming) | 
    
    | 2040 |  |  | 		sa->transport->vtbl->get_dst(sa->transport, &saddr); | 
    
    | 2041 |  |  | 	else | 
    
    | 2042 |  |  | 		sa->transport->vtbl->get_src(sa->transport, &saddr); | 
    
    | 2043 |  |  | 	len = sizeof *addr + PF_KEY_V2_ROUND(SA_LEN(saddr)); | 
    
    | 2044 |  |  | 	addr = calloc(1, len); | 
    
    | 2045 |  |  | 	if (!addr) | 
    
    | 2046 |  |  | 		goto cleanup; | 
    
    | 2047 |  |  | 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; | 
    
    | 2048 |  |  | 	addr->sadb_address_len = len / PF_KEY_V2_CHUNK; | 
    
    | 2049 |  |  | 	addr->sadb_address_reserved = 0; | 
    
    | 2050 |  |  | 	memcpy(addr + 1, saddr, SA_LEN(saddr)); | 
    
    | 2051 |  |  | 	switch (saddr->sa_family) { | 
    
    | 2052 |  |  | 	case AF_INET: | 
    
    | 2053 |  |  | 		((struct sockaddr_in *) (addr + 1))->sin_port = 0; | 
    
    | 2054 |  |  | 		break; | 
    
    | 2055 |  |  | 	case AF_INET6: | 
    
    | 2056 |  |  | 		((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0; | 
    
    | 2057 |  |  | 		break; | 
    
    | 2058 |  |  | 	} | 
    
    | 2059 |  |  | 	if (pf_key_v2_msg_add(delete, (struct sadb_ext *) addr, | 
    
    | 2060 |  |  | 	    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 2061 |  |  | 		goto cleanup; | 
    
    | 2062 |  |  | 	addr = 0; | 
    
    | 2063 |  |  |  | 
    
    | 2064 |  |  | 	if (incoming) | 
    
    | 2065 |  |  | 		sa->transport->vtbl->get_src(sa->transport, &saddr); | 
    
    | 2066 |  |  | 	else | 
    
    | 2067 |  |  | 		sa->transport->vtbl->get_dst(sa->transport, &saddr); | 
    
    | 2068 |  |  | 	len = sizeof *addr + PF_KEY_V2_ROUND(SA_LEN(saddr)); | 
    
    | 2069 |  |  | 	addr = calloc(1, len); | 
    
    | 2070 |  |  | 	if (!addr) | 
    
    | 2071 |  |  | 		goto cleanup; | 
    
    | 2072 |  |  | 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; | 
    
    | 2073 |  |  | 	addr->sadb_address_len = len / PF_KEY_V2_CHUNK; | 
    
    | 2074 |  |  | 	addr->sadb_address_reserved = 0; | 
    
    | 2075 |  |  | 	memcpy(addr + 1, saddr, SA_LEN(saddr)); | 
    
    | 2076 |  |  | 	switch (saddr->sa_family) { | 
    
    | 2077 |  |  | 	case AF_INET: | 
    
    | 2078 |  |  | 		((struct sockaddr_in *) (addr + 1))->sin_port = 0; | 
    
    | 2079 |  |  | 		break; | 
    
    | 2080 |  |  | 	case AF_INET6: | 
    
    | 2081 |  |  | 		((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0; | 
    
    | 2082 |  |  | 		break; | 
    
    | 2083 |  |  | 	} | 
    
    | 2084 |  |  | 	if (pf_key_v2_msg_add(delete, (struct sadb_ext *) addr, | 
    
    | 2085 |  |  | 	    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 2086 |  |  | 		goto cleanup; | 
    
    | 2087 |  |  | 	addr = 0; | 
    
    | 2088 |  |  |  | 
    
    | 2089 |  |  | 	ret = pf_key_v2_call(delete); | 
    
    | 2090 |  |  | 	pf_key_v2_msg_free(delete); | 
    
    | 2091 |  |  | 	delete = 0; | 
    
    | 2092 |  |  | 	if (!ret) | 
    
    | 2093 |  |  | 		goto cleanup; | 
    
    | 2094 |  |  | 	err = ((struct sadb_msg *)TAILQ_FIRST(ret)->seg)->sadb_msg_errno; | 
    
    | 2095 |  |  | 	if (err) { | 
    
    | 2096 |  |  | 		LOG_DBG((LOG_SYSDEP, 10, "pf_key_v2_delete_spi: DELETE: %s", | 
    
    | 2097 |  |  | 			 strerror(err))); | 
    
    | 2098 |  |  | 		goto cleanup; | 
    
    | 2099 |  |  | 	} | 
    
    | 2100 |  |  | 	pf_key_v2_msg_free(ret); | 
    
    | 2101 |  |  |  | 
    
    | 2102 |  |  | 	LOG_DBG((LOG_SYSDEP, 50, "pf_key_v2_delete_spi: done")); | 
    
    | 2103 |  |  |  | 
    
    | 2104 |  |  | 	return 0; | 
    
    | 2105 |  |  |  | 
    
    | 2106 |  |  | cleanup: | 
    
    | 2107 |  |  | 	free(addr); | 
    
    | 2108 |  |  | 	if (delete) | 
    
    | 2109 |  |  | 		pf_key_v2_msg_free(delete); | 
    
    | 2110 |  |  | 	if (ret) | 
    
    | 2111 |  |  | 		pf_key_v2_msg_free(ret); | 
    
    | 2112 |  |  | 	return -1; | 
    
    | 2113 |  |  | } | 
    
    | 2114 |  |  |  | 
    
    | 2115 |  |  | static void | 
    
    | 2116 |  |  | pf_key_v2_stayalive(struct exchange *exchange, void *vconn, int fail) | 
    
    | 2117 |  |  | { | 
    
    | 2118 |  |  | 	char           *conn = vconn; | 
    
    | 2119 |  |  | 	struct sa      *sa; | 
    
    | 2120 |  |  |  | 
    
    | 2121 |  |  | 	/* XXX What if it is phase 1 ? */ | 
    
    | 2122 |  |  | 	sa = sa_lookup_by_name(conn, 2); | 
    
    | 2123 |  |  | 	if (sa) | 
    
    | 2124 |  |  | 		sa->flags |= SA_FLAG_STAYALIVE; | 
    
    | 2125 |  |  |  | 
    
    | 2126 |  |  | 	/* | 
    
    | 2127 |  |  | 	 * Remove failed configuration entry -- call twice because it is | 
    
    | 2128 |  |  | 	 * created with a Refcount of 2. | 
    
    | 2129 |  |  | 	 */ | 
    
    | 2130 |  |  | 	if (fail && (!exchange || exchange->name)) { | 
    
    | 2131 |  |  | 		pf_key_v2_remove_conf(conn); | 
    
    | 2132 |  |  | 		pf_key_v2_remove_conf(conn); | 
    
    | 2133 |  |  | 	} | 
    
    | 2134 |  |  | } | 
    
    | 2135 |  |  |  | 
    
    | 2136 |  |  | /* Check if a connection CONN exists, otherwise establish it.  */ | 
    
    | 2137 |  |  | void | 
    
    | 2138 |  |  | pf_key_v2_connection_check(char *conn) | 
    
    | 2139 |  |  | { | 
    
    | 2140 |  |  | 	if (!sa_lookup_by_name(conn, 2)) { | 
    
    | 2141 |  |  | 		LOG_DBG((LOG_SYSDEP, 70, | 
    
    | 2142 |  |  | 		    "pf_key_v2_connection_check: SA for %s missing", conn)); | 
    
    | 2143 |  |  | 		exchange_establish(conn, pf_key_v2_stayalive, conn, 0); | 
    
    | 2144 |  |  | 	} else | 
    
    | 2145 |  |  | 		LOG_DBG((LOG_SYSDEP, 70, "pf_key_v2_connection_check: " | 
    
    | 2146 |  |  | 		    "SA for %s exists", conn)); | 
    
    | 2147 |  |  | } | 
    
    | 2148 |  |  |  | 
    
    | 2149 |  |  | /* Handle a PF_KEY lifetime expiration message PMSG.  */ | 
    
    | 2150 |  |  | static void | 
    
    | 2151 |  |  | pf_key_v2_expire(struct pf_key_v2_msg *pmsg) | 
    
    | 2152 |  |  | { | 
    
    | 2153 |  |  | 	struct sadb_msg *msg; | 
    
    | 2154 |  |  | 	struct sadb_sa *ssa; | 
    
    | 2155 |  |  | 	struct sadb_address *dst; | 
    
    | 2156 |  |  | 	struct sockaddr *dstaddr; | 
    
    | 2157 |  |  | 	struct sadb_lifetime *life, *lifecurrent; | 
    
    | 2158 |  |  | 	struct sa      *sa; | 
    
    | 2159 |  |  | 	struct pf_key_v2_node *lifenode, *ext; | 
    
    | 2160 |  |  | 	char           *dst_str; | 
    
    | 2161 |  |  |  | 
    
    | 2162 |  |  | 	msg = (struct sadb_msg *)TAILQ_FIRST(pmsg)->seg; | 
    
    | 2163 |  |  | 	ext = pf_key_v2_find_ext(pmsg, SADB_EXT_SA); | 
    
    | 2164 |  |  | 	if (!ext) { | 
    
    | 2165 |  |  | 		log_print("pf_key_v2_expire: no SA extension found"); | 
    
    | 2166 |  |  | 		return; | 
    
    | 2167 |  |  | 	} | 
    
    | 2168 |  |  | 	ssa = ext->seg; | 
    
    | 2169 |  |  | 	ext = pf_key_v2_find_ext(pmsg, SADB_EXT_ADDRESS_DST); | 
    
    | 2170 |  |  | 	if (!ext) { | 
    
    | 2171 |  |  | 		log_print("pf_key_v2_expire: " | 
    
    | 2172 |  |  | 		    "no destination address extension found"); | 
    
    | 2173 |  |  | 		return; | 
    
    | 2174 |  |  | 	} | 
    
    | 2175 |  |  | 	dst = ext->seg; | 
    
    | 2176 |  |  | 	dstaddr = (struct sockaddr *) (dst + 1); | 
    
    | 2177 |  |  | 	lifenode = pf_key_v2_find_ext(pmsg, SADB_EXT_LIFETIME_HARD); | 
    
    | 2178 |  |  | 	if (!lifenode) | 
    
    | 2179 |  |  | 		lifenode = pf_key_v2_find_ext(pmsg, SADB_EXT_LIFETIME_SOFT); | 
    
    | 2180 |  |  | 	if (!lifenode) { | 
    
    | 2181 |  |  | 		log_print("pf_key_v2_expire: no lifetime extension found"); | 
    
    | 2182 |  |  | 		return; | 
    
    | 2183 |  |  | 	} | 
    
    | 2184 |  |  | 	life = lifenode->seg; | 
    
    | 2185 |  |  |  | 
    
    | 2186 |  |  | 	lifenode = pf_key_v2_find_ext(pmsg, SADB_EXT_LIFETIME_CURRENT); | 
    
    | 2187 |  |  | 	if (!lifenode) { | 
    
    | 2188 |  |  | 		log_print("pf_key_v2_expire: " | 
    
    | 2189 |  |  | 		    "no current lifetime extension found"); | 
    
    | 2190 |  |  | 		return; | 
    
    | 2191 |  |  | 	} | 
    
    | 2192 |  |  | 	lifecurrent = lifenode->seg; | 
    
    | 2193 |  |  |  | 
    
    | 2194 |  |  | 	if (sockaddr2text(dstaddr, &dst_str, 0)) | 
    
    | 2195 |  |  | 		dst_str = 0; | 
    
    | 2196 |  |  |  | 
    
    | 2197 |  |  | 	LOG_DBG((LOG_SYSDEP, 20, "pf_key_v2_expire: " | 
    
    | 2198 |  |  | 	    "%s dst %s SPI %x sproto %d", | 
    
    | 2199 |  |  | 	    life->sadb_lifetime_exttype == SADB_EXT_LIFETIME_SOFT ? "SOFT" | 
    
    | 2200 |  |  | 	    : "HARD", dst_str ? dst_str : "<unknown>", | 
    
    | 2201 |  |  | 	    ntohl(ssa->sadb_sa_spi), msg->sadb_msg_satype)); | 
    
    | 2202 |  |  |  | 
    
    | 2203 |  |  | 	free(dst_str); | 
    
    | 2204 |  |  |  | 
    
    | 2205 |  |  | 	/* | 
    
    | 2206 |  |  | 	 * Find the IPsec SA.  The IPsec stack has two SAs for every IKE SA, | 
    
    | 2207 |  |  | 	 * one outgoing and one incoming, we regard expirations for any of | 
    
    | 2208 |  |  | 	 * them as an expiration of the full IKE SA.  Likewise, in | 
    
    | 2209 |  |  | 	 * protection suites consisting of more than one protocol, any | 
    
    | 2210 |  |  | 	 * expired individual IPsec stack SA will be seen as an expiration | 
    
    | 2211 |  |  | 	 * of the full suite. | 
    
    | 2212 |  |  | 	 */ | 
    
    | 2213 |  |  | 	switch (msg->sadb_msg_satype) { | 
    
    | 2214 |  |  | 	case SADB_SATYPE_ESP: | 
    
    | 2215 |  |  | 		sa = ipsec_sa_lookup(dstaddr, ssa->sadb_sa_spi, | 
    
    | 2216 |  |  | 		    IPSEC_PROTO_IPSEC_ESP); | 
    
    | 2217 |  |  | 		break; | 
    
    | 2218 |  |  |  | 
    
    | 2219 |  |  | 	case SADB_SATYPE_AH: | 
    
    | 2220 |  |  | 		sa = ipsec_sa_lookup(dstaddr, ssa->sadb_sa_spi, | 
    
    | 2221 |  |  | 		    IPSEC_PROTO_IPSEC_AH); | 
    
    | 2222 |  |  | 		break; | 
    
    | 2223 |  |  |  | 
    
    | 2224 |  |  | 	case SADB_X_SATYPE_IPCOMP: | 
    
    | 2225 |  |  | 		sa = ipsec_sa_lookup(dstaddr, ssa->sadb_sa_spi, | 
    
    | 2226 |  |  | 		    IPSEC_PROTO_IPCOMP); | 
    
    | 2227 |  |  | 		break; | 
    
    | 2228 |  |  |  | 
    
    | 2229 |  |  | 	default: | 
    
    | 2230 |  |  | 		/* XXX Log? */ | 
    
    | 2231 |  |  | 		sa = 0; | 
    
    | 2232 |  |  | 		break; | 
    
    | 2233 |  |  | 	} | 
    
    | 2234 |  |  |  | 
    
    | 2235 |  |  | 	/* If the SA is already gone, don't do anything.  */ | 
    
    | 2236 |  |  | 	if (!sa) | 
    
    | 2237 |  |  | 		return; | 
    
    | 2238 |  |  |  | 
    
    | 2239 |  |  | 	/* | 
    
    | 2240 |  |  | 	 * If we got a notification, try to renegotiate the SA -- unless of | 
    
    | 2241 |  |  | 	 * course it has already been replaced by another. | 
    
    | 2242 |  |  | 	 * Also, ignore SAs that were not dynamically established, or that | 
    
    | 2243 |  |  | 	 * did not see any use. | 
    
    | 2244 |  |  | 	 */ | 
    
    | 2245 |  |  | 	if (!(sa->flags & SA_FLAG_REPLACED) && | 
    
    | 2246 |  |  | 	    (sa->flags & SA_FLAG_ONDEMAND) && | 
    
    | 2247 |  |  | 	    lifecurrent->sadb_lifetime_bytes) | 
    
    | 2248 |  |  | 		exchange_establish(sa->name, 0, 0, 0); | 
    
    | 2249 |  |  |  | 
    
    | 2250 |  |  | 	if (life->sadb_lifetime_exttype == SADB_EXT_LIFETIME_HARD) { | 
    
    | 2251 |  |  | 		/* Remove the old SA, it isn't useful anymore.  */ | 
    
    | 2252 |  |  | 		sa_free(sa); | 
    
    | 2253 |  |  | 	} | 
    
    | 2254 |  |  | } | 
    
    | 2255 |  |  |  | 
    
    | 2256 |  |  | static int | 
    
    | 2257 |  |  | mask4len(const struct sockaddr_in *mask) | 
    
    | 2258 |  |  | { | 
    
    | 2259 |  |  | 	int len; | 
    
    | 2260 |  |  | 	u_int32_t m; | 
    
    | 2261 |  |  |  | 
    
    | 2262 |  |  | 	len = 0; | 
    
    | 2263 |  |  | 	for (m = 0x80000000; m & ntohl(mask->sin_addr.s_addr); m >>= 1) | 
    
    | 2264 |  |  | 		len++; | 
    
    | 2265 |  |  | 	if (len == 32) | 
    
    | 2266 |  |  | 		len = -1; | 
    
    | 2267 |  |  | 	return len; | 
    
    | 2268 |  |  | } | 
    
    | 2269 |  |  |  | 
    
    | 2270 |  |  | #ifndef s6_addr8 | 
    
    | 2271 |  |  | #define s6_addr8 __u6_addr.__u6_addr8 | 
    
    | 2272 |  |  | #endif | 
    
    | 2273 |  |  |  | 
    
    | 2274 |  |  | static int | 
    
    | 2275 |  |  | mask6len(const struct sockaddr_in6 *mask) | 
    
    | 2276 |  |  | { | 
    
    | 2277 |  |  | 	int i, len; | 
    
    | 2278 |  |  | 	u_int8_t m; | 
    
    | 2279 |  |  |  | 
    
    | 2280 |  |  | 	len = 0; | 
    
    | 2281 |  |  | 	for (i = 0, m = 0; i < 16 && !m; i++) | 
    
    | 2282 |  |  | 		for (m = 0x80; m & mask->sin6_addr.s6_addr8[i]; m >>= 1) | 
    
    | 2283 |  |  | 			len++; | 
    
    | 2284 |  |  | 	if (len == 128) | 
    
    | 2285 |  |  | 		len = -1; | 
    
    | 2286 |  |  | 	return len; | 
    
    | 2287 |  |  | } | 
    
    | 2288 |  |  |  | 
    
    | 2289 |  |  | static int | 
    
    | 2290 |  |  | phase2id(char *str, size_t size, const char *side, const char *sflow, | 
    
    | 2291 |  |  |     int masklen, u_int8_t proto, u_int16_t port) | 
    
    | 2292 |  |  | { | 
    
    | 2293 |  |  | 	char smasklen[10], sproto[10], sport[10]; | 
    
    | 2294 |  |  |  | 
    
    | 2295 |  |  | 	smasklen[0] = sproto[0] = sport[0] = 0; | 
    
    | 2296 |  |  | 	if (masklen != -1) | 
    
    | 2297 |  |  | 		snprintf(smasklen, sizeof smasklen, "/%d", masklen); | 
    
    | 2298 |  |  | 	if (proto) | 
    
    | 2299 |  |  | 		snprintf(sproto, sizeof sproto, "=%u", proto); | 
    
    | 2300 |  |  | 	if (port) | 
    
    | 2301 |  |  | 		snprintf(sport, sizeof sport, ":%u", ntohs(port)); | 
    
    | 2302 |  |  |  | 
    
    | 2303 |  |  | 	return snprintf(str, size, "%s-%s%s%s%s", side, sflow, smasklen, | 
    
    | 2304 |  |  | 	    sproto, sport); | 
    
    | 2305 |  |  | } | 
    
    | 2306 |  |  |  | 
    
    | 2307 |  |  | /* Handle a PF_KEY SA ACQUIRE message PMSG.  */ | 
    
    | 2308 |  |  | static void | 
    
    | 2309 |  |  | pf_key_v2_acquire(struct pf_key_v2_msg *pmsg) | 
    
    | 2310 |  |  | { | 
    
    | 2311 |  |  | 	struct sadb_msg *msg, askpolicy_msg; | 
    
    | 2312 |  |  | 	struct pf_key_v2_msg *askpolicy = 0, *ret = 0; | 
    
    | 2313 |  |  | 	struct sadb_x_policy policy; | 
    
    | 2314 |  |  | 	struct sadb_address *dst = 0, *src = 0; | 
    
    | 2315 |  |  | 	struct sockaddr *dstaddr, *srcaddr = 0; | 
    
    | 2316 |  |  | 	struct sadb_comb *scmb = 0; | 
    
    | 2317 |  |  | 	struct sadb_prop *sprp = 0; | 
    
    | 2318 |  |  | 	struct sadb_ident *srcident = 0, *dstident = 0; | 
    
    | 2319 |  |  | 	char		dstbuf[ADDRESS_MAX], srcbuf[ADDRESS_MAX], *peer = 0; | 
    
    | 2320 |  |  | 	char		confname[120], *conn = 0; | 
    
    | 2321 |  |  | 	char           *srcid = 0, *dstid = 0, *prefstring = 0; | 
    
    | 2322 |  |  | 	int		slen, af, afamily, masklen; | 
    
    | 2323 |  |  | 	struct sockaddr *smask, *sflow, *dmask, *dflow; | 
    
    | 2324 |  |  | 	struct sadb_protocol *sproto; | 
    
    | 2325 |  |  | 	char		ssflow[ADDRESS_MAX], sdflow[ADDRESS_MAX]; | 
    
    | 2326 |  |  | 	char		sdmask[ADDRESS_MAX], ssmask[ADDRESS_MAX]; | 
    
    | 2327 |  |  | 	int		dmasklen, smasklen; | 
    
    | 2328 |  |  | 	char           *sidtype = 0, *didtype = 0; | 
    
    | 2329 |  |  | 	char		lname[100], dname[100], configname[200]; | 
    
    | 2330 |  |  | 	int		shostflag = 0, dhostflag = 0; | 
    
    | 2331 |  |  | 	struct pf_key_v2_node *ext; | 
    
    | 2332 |  |  | 	struct passwd  *pwd = 0; | 
    
    | 2333 |  |  | 	u_int16_t       sport = 0, dport = 0; | 
    
    | 2334 |  |  | 	u_int8_t	tproto = 0; | 
    
    | 2335 |  |  | 	char		tmbuf[sizeof sport * 3 + 1], *xform; | 
    
    | 2336 |  |  | 	int		connlen; | 
    
    | 2337 |  |  |  | 
    
    | 2338 |  |  | 	/* This needs to be dynamically allocated. */ | 
    
    | 2339 |  |  | 	connlen = 22; | 
    
    | 2340 |  |  | 	conn = malloc(connlen); | 
    
    | 2341 |  |  | 	if (!conn) { | 
    
    | 2342 |  |  | 		log_error("pf_key_v2_acquire: malloc (%d) failed", connlen); | 
    
    | 2343 |  |  | 		return; | 
    
    | 2344 |  |  | 	} | 
    
    | 2345 |  |  | 	msg = (struct sadb_msg *)TAILQ_FIRST(pmsg)->seg; | 
    
    | 2346 |  |  |  | 
    
    | 2347 |  |  | 	ext = pf_key_v2_find_ext(pmsg, SADB_EXT_ADDRESS_DST); | 
    
    | 2348 |  |  | 	if (!ext) { | 
    
    | 2349 |  |  | 		log_print("pf_key_v2_acquire: " | 
    
    | 2350 |  |  | 		    "no destination address specified"); | 
    
    | 2351 |  |  | 		free(conn); | 
    
    | 2352 |  |  | 		return; | 
    
    | 2353 |  |  | 	} | 
    
    | 2354 |  |  | 	dst = ext->seg; | 
    
    | 2355 |  |  |  | 
    
    | 2356 |  |  | 	ext = pf_key_v2_find_ext(pmsg, SADB_EXT_ADDRESS_SRC); | 
    
    | 2357 |  |  | 	if (ext) | 
    
    | 2358 |  |  | 		src = ext->seg; | 
    
    | 2359 |  |  |  | 
    
    | 2360 |  |  | 	ext = pf_key_v2_find_ext(pmsg, SADB_EXT_PROPOSAL); | 
    
    | 2361 |  |  | 	if (ext) { | 
    
    | 2362 |  |  | 		sprp = ext->seg; | 
    
    | 2363 |  |  | 		scmb = (struct sadb_comb *) (sprp + 1); | 
    
    | 2364 |  |  | 	} | 
    
    | 2365 |  |  | 	ext = pf_key_v2_find_ext(pmsg, SADB_EXT_IDENTITY_SRC); | 
    
    | 2366 |  |  | 	if (ext) | 
    
    | 2367 |  |  | 		srcident = ext->seg; | 
    
    | 2368 |  |  |  | 
    
    | 2369 |  |  | 	ext = pf_key_v2_find_ext(pmsg, SADB_EXT_IDENTITY_DST); | 
    
    | 2370 |  |  | 	if (ext) | 
    
    | 2371 |  |  | 		dstident = ext->seg; | 
    
    | 2372 |  |  |  | 
    
    | 2373 |  |  | 	/* Ask the kernel for the matching policy. */ | 
    
    | 2374 |  |  | 	bzero(&askpolicy_msg, sizeof askpolicy_msg); | 
    
    | 2375 |  |  | 	askpolicy_msg.sadb_msg_type = SADB_X_ASKPOLICY; | 
    
    | 2376 |  |  | 	askpolicy = pf_key_v2_msg_new(&askpolicy_msg, 0); | 
    
    | 2377 |  |  | 	if (!askpolicy) | 
    
    | 2378 |  |  | 		goto fail; | 
    
    | 2379 |  |  |  | 
    
    | 2380 |  |  | 	policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY; | 
    
    | 2381 |  |  | 	policy.sadb_x_policy_len = sizeof policy / PF_KEY_V2_CHUNK; | 
    
    | 2382 |  |  | 	policy.sadb_x_policy_seq = msg->sadb_msg_seq; | 
    
    | 2383 |  |  | 	if (pf_key_v2_msg_add(askpolicy, (struct sadb_ext *)&policy, 0) == -1) | 
    
    | 2384 |  |  | 		goto fail; | 
    
    | 2385 |  |  |  | 
    
    | 2386 |  |  | 	ret = pf_key_v2_call(askpolicy); | 
    
    | 2387 |  |  | 	if (!ret) | 
    
    | 2388 |  |  | 		goto fail; | 
    
    | 2389 |  |  |  | 
    
    | 2390 |  |  | 	/* Now we have all the information needed. */ | 
    
    | 2391 |  |  |  | 
    
    | 2392 |  |  | 	ext = pf_key_v2_find_ext(ret, SADB_X_EXT_SRC_FLOW); | 
    
    | 2393 |  |  | 	if (!ext) { | 
    
    | 2394 |  |  | 		log_print("pf_key_v2_acquire: no source flow extension found"); | 
    
    | 2395 |  |  | 		goto fail; | 
    
    | 2396 |  |  | 	} | 
    
    | 2397 |  |  | 	sflow = (struct sockaddr *) (((struct sadb_address *) ext->seg) + 1); | 
    
    | 2398 |  |  |  | 
    
    | 2399 |  |  | 	ext = pf_key_v2_find_ext(ret, SADB_X_EXT_DST_FLOW); | 
    
    | 2400 |  |  | 	if (!ext) { | 
    
    | 2401 |  |  | 		log_print("pf_key_v2_acquire: " | 
    
    | 2402 |  |  | 		    "no destination flow extension found"); | 
    
    | 2403 |  |  | 		goto fail; | 
    
    | 2404 |  |  | 	} | 
    
    | 2405 |  |  | 	dflow = (struct sockaddr *) (((struct sadb_address *) ext->seg) + 1); | 
    
    | 2406 |  |  | 	ext = pf_key_v2_find_ext(ret, SADB_X_EXT_SRC_MASK); | 
    
    | 2407 |  |  | 	if (!ext) { | 
    
    | 2408 |  |  | 		log_print("pf_key_v2_acquire: no source mask extension found"); | 
    
    | 2409 |  |  | 		goto fail; | 
    
    | 2410 |  |  | 	} | 
    
    | 2411 |  |  | 	smask = (struct sockaddr *) (((struct sadb_address *) ext->seg) + 1); | 
    
    | 2412 |  |  |  | 
    
    | 2413 |  |  | 	ext = pf_key_v2_find_ext(ret, SADB_X_EXT_DST_MASK); | 
    
    | 2414 |  |  | 	if (!ext) { | 
    
    | 2415 |  |  | 		log_print("pf_key_v2_acquire: " | 
    
    | 2416 |  |  | 		    "no destination mask extension found"); | 
    
    | 2417 |  |  | 		goto fail; | 
    
    | 2418 |  |  | 	} | 
    
    | 2419 |  |  | 	dmask = (struct sockaddr *) (((struct sadb_address *) ext->seg) + 1); | 
    
    | 2420 |  |  |  | 
    
    | 2421 |  |  | 	ext = pf_key_v2_find_ext(ret, SADB_X_EXT_FLOW_TYPE); | 
    
    | 2422 |  |  | 	if (!ext) { | 
    
    | 2423 |  |  | 		log_print("pf_key_v2_acquire: no flow type extension found"); | 
    
    | 2424 |  |  | 		goto fail; | 
    
    | 2425 |  |  | 	} | 
    
    | 2426 |  |  | 	sproto = ext->seg; | 
    
    | 2427 |  |  | 	tproto = sproto->sadb_protocol_proto; | 
    
    | 2428 |  |  |  | 
    
    | 2429 |  |  | 	bzero(ssflow, sizeof ssflow); | 
    
    | 2430 |  |  | 	bzero(sdflow, sizeof sdflow); | 
    
    | 2431 |  |  | 	bzero(ssmask, sizeof ssmask); | 
    
    | 2432 |  |  | 	bzero(sdmask, sizeof sdmask); | 
    
    | 2433 |  |  | 	smasklen = dmasklen = -1; | 
    
    | 2434 |  |  |  | 
    
    | 2435 |  |  | 	sidtype = didtype = "IPV4_ADDR_SUBNET";	/* default */ | 
    
    | 2436 |  |  |  | 
    
    | 2437 |  |  | 	switch (sflow->sa_family) { | 
    
    | 2438 |  |  | 	case AF_INET: | 
    
    | 2439 |  |  | 		if (inet_ntop(AF_INET, | 
    
    | 2440 |  |  | 		    &((struct sockaddr_in *) sflow)->sin_addr, ssflow, | 
    
    | 2441 |  |  | 		    ADDRESS_MAX) == NULL) { | 
    
    | 2442 |  |  | 			log_print("pf_key_v2_acquire: inet_ntop failed"); | 
    
    | 2443 |  |  | 			goto fail; | 
    
    | 2444 |  |  | 		} | 
    
    | 2445 |  |  | 		sport = ((struct sockaddr_in *) sflow)->sin_port; | 
    
    | 2446 |  |  | 		if (inet_ntop(AF_INET, | 
    
    | 2447 |  |  | 		    &((struct sockaddr_in *) dflow)->sin_addr, sdflow, | 
    
    | 2448 |  |  | 		    ADDRESS_MAX) == NULL) { | 
    
    | 2449 |  |  | 			log_print("pf_key_v2_acquire: inet_ntop failed"); | 
    
    | 2450 |  |  | 			goto fail; | 
    
    | 2451 |  |  | 		} | 
    
    | 2452 |  |  | 		dport = ((struct sockaddr_in *) dflow)->sin_port; | 
    
    | 2453 |  |  | 		if (inet_ntop(AF_INET, | 
    
    | 2454 |  |  | 		    &((struct sockaddr_in *) smask)->sin_addr, ssmask, | 
    
    | 2455 |  |  | 		    ADDRESS_MAX) == NULL) { | 
    
    | 2456 |  |  | 			log_print("pf_key_v2_acquire: inet_ntop failed"); | 
    
    | 2457 |  |  | 			goto fail; | 
    
    | 2458 |  |  | 		} | 
    
    | 2459 |  |  | 		if (inet_ntop(AF_INET, | 
    
    | 2460 |  |  | 		    &((struct sockaddr_in *) dmask)->sin_addr, sdmask, | 
    
    | 2461 |  |  | 		    ADDRESS_MAX) == NULL) { | 
    
    | 2462 |  |  | 			log_print("pf_key_v2_acquire: inet_ntop failed"); | 
    
    | 2463 |  |  | 			goto fail; | 
    
    | 2464 |  |  | 		} | 
    
    | 2465 |  |  | 		smasklen = mask4len((struct sockaddr_in *) smask); | 
    
    | 2466 |  |  | 		dmasklen = mask4len((struct sockaddr_in *) dmask); | 
    
    | 2467 |  |  | 		if (((struct sockaddr_in *) smask)->sin_addr.s_addr == | 
    
    | 2468 |  |  | 		    INADDR_BROADCAST) { | 
    
    | 2469 |  |  | 			shostflag = 1; | 
    
    | 2470 |  |  | 			sidtype = "IPV4_ADDR"; | 
    
    | 2471 |  |  | 		} | 
    
    | 2472 |  |  | 		if (((struct sockaddr_in *) dmask)->sin_addr.s_addr == | 
    
    | 2473 |  |  | 		    INADDR_BROADCAST) { | 
    
    | 2474 |  |  | 			dhostflag = 1; | 
    
    | 2475 |  |  | 			didtype = "IPV4_ADDR"; | 
    
    | 2476 |  |  | 		} | 
    
    | 2477 |  |  | 		break; | 
    
    | 2478 |  |  |  | 
    
    | 2479 |  |  | 	case AF_INET6: | 
    
    | 2480 |  |  | 		if (inet_ntop(AF_INET6, | 
    
    | 2481 |  |  | 		    &((struct sockaddr_in6 *) sflow)->sin6_addr, | 
    
    | 2482 |  |  | 		    ssflow, ADDRESS_MAX) == NULL) { | 
    
    | 2483 |  |  | 			log_print("pf_key_v2_acquire: inet_ntop failed"); | 
    
    | 2484 |  |  | 			goto fail; | 
    
    | 2485 |  |  | 		} | 
    
    | 2486 |  |  | 		sport = ((struct sockaddr_in6 *) sflow)->sin6_port; | 
    
    | 2487 |  |  | 		if (inet_ntop(AF_INET6, | 
    
    | 2488 |  |  | 		    &((struct sockaddr_in6 *) dflow)->sin6_addr, | 
    
    | 2489 |  |  | 		    sdflow, ADDRESS_MAX) == NULL) { | 
    
    | 2490 |  |  | 			log_print("pf_key_v2_acquire: inet_ntop failed"); | 
    
    | 2491 |  |  | 			goto fail; | 
    
    | 2492 |  |  | 		} | 
    
    | 2493 |  |  | 		dport = ((struct sockaddr_in6 *) dflow)->sin6_port; | 
    
    | 2494 |  |  | 		if (inet_ntop(AF_INET6, | 
    
    | 2495 |  |  | 		    &((struct sockaddr_in6 *) smask)->sin6_addr, | 
    
    | 2496 |  |  | 		    ssmask, ADDRESS_MAX) == NULL) { | 
    
    | 2497 |  |  | 			log_print("pf_key_v2_acquire: inet_ntop failed"); | 
    
    | 2498 |  |  | 			goto fail; | 
    
    | 2499 |  |  | 		} | 
    
    | 2500 |  |  | 		if (inet_ntop(AF_INET6, | 
    
    | 2501 |  |  | 		    &((struct sockaddr_in6 *) dmask)->sin6_addr, | 
    
    | 2502 |  |  | 		    sdmask, ADDRESS_MAX) == NULL) { | 
    
    | 2503 |  |  | 			log_print("pf_key_v2_acquire: inet_ntop failed"); | 
    
    | 2504 |  |  | 			goto fail; | 
    
    | 2505 |  |  | 		} | 
    
    | 2506 |  |  | 		smasklen = mask6len((struct sockaddr_in6 *) smask); | 
    
    | 2507 |  |  | 		dmasklen = mask6len((struct sockaddr_in6 *) dmask); | 
    
    | 2508 |  |  | 		sidtype = didtype = "IPV6_ADDR_SUBNET"; | 
    
    | 2509 |  |  | 		if (IN6_IS_ADDR_FULL(&((struct sockaddr_in6 *)smask)->sin6_addr)) { | 
    
    | 2510 |  |  | 			shostflag = 1; | 
    
    | 2511 |  |  | 			sidtype = "IPV6_ADDR"; | 
    
    | 2512 |  |  | 		} | 
    
    | 2513 |  |  | 		if (IN6_IS_ADDR_FULL(&((struct sockaddr_in6 *)dmask)->sin6_addr)) { | 
    
    | 2514 |  |  | 			dhostflag = 1; | 
    
    | 2515 |  |  | 			didtype = "IPV6_ADDR"; | 
    
    | 2516 |  |  | 		} | 
    
    | 2517 |  |  | 		break; | 
    
    | 2518 |  |  | 	} | 
    
    | 2519 |  |  |  | 
    
    | 2520 |  |  | 	dstaddr = (struct sockaddr *)(dst + 1); | 
    
    | 2521 |  |  | 	bzero(dstbuf, sizeof dstbuf); | 
    
    | 2522 |  |  | 	bzero(srcbuf, sizeof srcbuf); | 
    
    | 2523 |  |  |  | 
    
    | 2524 |  |  | 	if (dstaddr->sa_family == 0) { | 
    
    | 2525 |  |  | 		/* | 
    
    | 2526 |  |  | 		 * Destination was not specified in the flow -- can we derive | 
    
    | 2527 |  |  | 		 * it? | 
    
    | 2528 |  |  | 		 */ | 
    
    | 2529 |  |  | 		if (dhostflag == 0) { | 
    
    | 2530 |  |  | 			log_print("pf_key_v2_acquire: " | 
    
    | 2531 |  |  | 			    "Cannot determine precise destination"); | 
    
    | 2532 |  |  | 			goto fail; | 
    
    | 2533 |  |  | 		} | 
    
    | 2534 |  |  | 		dstaddr = dflow; | 
    
    | 2535 |  |  | 	} | 
    
    | 2536 |  |  | 	switch (dstaddr->sa_family) { | 
    
    | 2537 |  |  | 	case AF_INET: | 
    
    | 2538 |  |  | 		if (inet_ntop(AF_INET, | 
    
    | 2539 |  |  | 		    &((struct sockaddr_in *) dstaddr)->sin_addr, | 
    
    | 2540 |  |  | 		    dstbuf, ADDRESS_MAX) == NULL) { | 
    
    | 2541 |  |  | 			log_print("pf_key_v2_acquire: inet_ntop failed"); | 
    
    | 2542 |  |  | 			goto fail; | 
    
    | 2543 |  |  | 		} | 
    
    | 2544 |  |  | 		LOG_DBG((LOG_SYSDEP, 20, | 
    
    | 2545 |  |  | 		    "pf_key_v2_acquire: dst=%s sproto %d", dstbuf, | 
    
    | 2546 |  |  | 		    msg->sadb_msg_satype)); | 
    
    | 2547 |  |  | 		break; | 
    
    | 2548 |  |  |  | 
    
    | 2549 |  |  | 	case AF_INET6: | 
    
    | 2550 |  |  | 		if (inet_ntop(AF_INET6, | 
    
    | 2551 |  |  | 		    &((struct sockaddr_in6 *) dstaddr)->sin6_addr, | 
    
    | 2552 |  |  | 		    dstbuf, ADDRESS_MAX) == NULL) { | 
    
    | 2553 |  |  | 			log_print("pf_key_v2_acquire: inet_ntop failed"); | 
    
    | 2554 |  |  | 			goto fail; | 
    
    | 2555 |  |  | 		} | 
    
    | 2556 |  |  | 		LOG_DBG((LOG_SYSDEP, 20, | 
    
    | 2557 |  |  | 		    "pf_key_v2_acquire: dst=%s sproto %d", dstbuf, | 
    
    | 2558 |  |  | 		    msg->sadb_msg_satype)); | 
    
    | 2559 |  |  | 		break; | 
    
    | 2560 |  |  | 	} | 
    
    | 2561 |  |  |  | 
    
    | 2562 |  |  | 	if (src) { | 
    
    | 2563 |  |  | 		srcaddr = (struct sockaddr *) (src + 1); | 
    
    | 2564 |  |  |  | 
    
    | 2565 |  |  | 		switch (srcaddr->sa_family) { | 
    
    | 2566 |  |  | 		case AF_INET: | 
    
    | 2567 |  |  | 			if (inet_ntop(AF_INET, | 
    
    | 2568 |  |  | 			    &((struct sockaddr_in *) srcaddr)->sin_addr, | 
    
    | 2569 |  |  | 			    srcbuf, ADDRESS_MAX) == NULL) { | 
    
    | 2570 |  |  | 				log_print("pf_key_v2_acquire: " | 
    
    | 2571 |  |  | 				    "inet_ntop failed"); | 
    
    | 2572 |  |  | 				goto fail; | 
    
    | 2573 |  |  | 			} | 
    
    | 2574 |  |  | 			break; | 
    
    | 2575 |  |  |  | 
    
    | 2576 |  |  | 		case AF_INET6: | 
    
    | 2577 |  |  | 			if (inet_ntop(AF_INET6, | 
    
    | 2578 |  |  | 			    &((struct sockaddr_in6 *)srcaddr)->sin6_addr, | 
    
    | 2579 |  |  | 			    srcbuf, ADDRESS_MAX) == NULL) { | 
    
    | 2580 |  |  | 				log_print("pf_key_v2_acquire: " | 
    
    | 2581 |  |  | 				    "inet_ntop failed"); | 
    
    | 2582 |  |  | 				goto fail; | 
    
    | 2583 |  |  | 			} | 
    
    | 2584 |  |  | 			break; | 
    
    | 2585 |  |  |  | 
    
    | 2586 |  |  | 		default: | 
    
    | 2587 |  |  | 			/* | 
    
    | 2588 |  |  | 			 * The kernel will pass an all '0' EXT_ADDRESS_SRC if | 
    
    | 2589 |  |  | 			 * it wasn't specified for the flow. In that case, do | 
    
    | 2590 |  |  | 			 * NOT specify the srcaddr in the Peer-name below | 
    
    | 2591 |  |  | 			 */ | 
    
    | 2592 |  |  | 			srcbuf[0] = 0; | 
    
    | 2593 |  |  | 			srcaddr = NULL; | 
    
    | 2594 |  |  | 			break; | 
    
    | 2595 |  |  | 		} | 
    
    | 2596 |  |  | 	} | 
    
    | 2597 |  |  | 	/* Insert source ID. */ | 
    
    | 2598 |  |  | 	if (srcident) { | 
    
    | 2599 |  |  | 		slen = (srcident->sadb_ident_len * sizeof(u_int64_t)) | 
    
    | 2600 |  |  | 			- sizeof(struct sadb_ident); | 
    
    | 2601 |  |  | 		if (((unsigned char *) (srcident + 1))[slen - 1] != '\0') { | 
    
    | 2602 |  |  | 			log_print("pf_key_v2_acquire: " | 
    
    | 2603 |  |  | 			    "source identity not NUL-terminated"); | 
    
    | 2604 |  |  | 			goto fail; | 
    
    | 2605 |  |  | 		} | 
    
    | 2606 |  |  | 		/* Check for valid type. */ | 
    
    | 2607 |  |  | 		switch (srcident->sadb_ident_type) { | 
    
    | 2608 |  |  | 		case SADB_IDENTTYPE_PREFIX: | 
    
    | 2609 |  |  | 			/* Determine what the address family is. */ | 
    
    | 2610 |  |  | 			srcid = memchr(srcident + 1, ':', slen); | 
    
    | 2611 |  |  | 			if (srcid) | 
    
    | 2612 |  |  | 				afamily = AF_INET6; | 
    
    | 2613 |  |  | 			else | 
    
    | 2614 |  |  | 				afamily = AF_INET; | 
    
    | 2615 |  |  |  | 
    
    | 2616 |  |  | 			srcid = memchr(srcident + 1, '/', slen); | 
    
    | 2617 |  |  | 			if (!srcid) { | 
    
    | 2618 |  |  | 				log_print("pf_key_v2_acquire: " | 
    
    | 2619 |  |  | 				    "badly formatted PREFIX identity"); | 
    
    | 2620 |  |  | 				goto fail; | 
    
    | 2621 |  |  | 			} | 
    
    | 2622 |  |  | 			masklen = atoi(srcid + 1); | 
    
    | 2623 |  |  |  | 
    
    | 2624 |  |  | 			/* XXX We only support host addresses. */ | 
    
    | 2625 |  |  | 			if ((afamily == AF_INET6 && masklen != 128) || | 
    
    | 2626 |  |  | 			    (afamily == AF_INET && masklen != 32)) { | 
    
    | 2627 |  |  | 				log_print("pf_key_v2_acquire: " | 
    
    | 2628 |  |  | 				    "non-host address specified in source " | 
    
    | 2629 |  |  | 				    "identity (mask length %d), ignoring " | 
    
    | 2630 |  |  | 				    "request", masklen); | 
    
    | 2631 |  |  | 				goto fail; | 
    
    | 2632 |  |  | 			} | 
    
    | 2633 |  |  | 			/* | 
    
    | 2634 |  |  | 			 * NUL-terminate the PREFIX string at the separator, | 
    
    | 2635 |  |  | 			 * then dup. | 
    
    | 2636 |  |  | 			 */ | 
    
    | 2637 |  |  | 			*srcid = '\0'; | 
    
    | 2638 |  |  | 			if (asprintf(&srcid, "id-%s", | 
    
    | 2639 |  |  | 			    (char *) (srcident + 1)) == -1) { | 
    
    | 2640 |  |  | 				log_error("pf_key_v2_acquire: asprintf() failed"); | 
    
    | 2641 |  |  | 				goto fail; | 
    
    | 2642 |  |  | 			} | 
    
    | 2643 |  |  |  | 
    
    | 2644 |  |  | 			/* Set the section if it doesn't already exist. */ | 
    
    | 2645 |  |  | 			af = conf_begin(); | 
    
    | 2646 |  |  | 			if (!conf_get_str(srcid, "ID-type")) { | 
    
    | 2647 |  |  | 				if (conf_set(af, srcid, "ID-type", | 
    
    | 2648 |  |  | 				    afamily == AF_INET ? "IPV4_ADDR" : | 
    
    | 2649 |  |  | 				    "IPV6_ADDR", 1, 0) || | 
    
    | 2650 |  |  | 				    conf_set(af, srcid, "Refcount", "1", 1, 0) || | 
    
    | 2651 |  |  | 				    conf_set(af, srcid, "Address", | 
    
    | 2652 |  |  | 					(char *) (srcident + 1), 1, 0)) { | 
    
    | 2653 |  |  | 					conf_end(af, 0); | 
    
    | 2654 |  |  | 					goto fail; | 
    
    | 2655 |  |  | 				} | 
    
    | 2656 |  |  | 			} else | 
    
    | 2657 |  |  | 				pf_key_v2_conf_refinc(af, srcid); | 
    
    | 2658 |  |  | 			conf_end(af, 1); | 
    
    | 2659 |  |  | 			break; | 
    
    | 2660 |  |  |  | 
    
    | 2661 |  |  | 		case SADB_IDENTTYPE_FQDN: | 
    
    | 2662 |  |  | 			prefstring = "FQDN"; | 
    
    | 2663 |  |  | 			/*FALLTHROUGH*/ | 
    
    | 2664 |  |  | 		case SADB_IDENTTYPE_USERFQDN: | 
    
    | 2665 |  |  | 			if (!prefstring) { | 
    
    | 2666 |  |  | 				prefstring = "USER_FQDN"; | 
    
    | 2667 |  |  |  | 
    
    | 2668 |  |  | 				/* | 
    
    | 2669 |  |  | 				 * Check whether there is a string following | 
    
    | 2670 |  |  | 				 * the header; if no, that there is a user ID | 
    
    | 2671 |  |  | 				 * (and acquire the login name). If there is | 
    
    | 2672 |  |  | 				 * both a string and a user ID, check that | 
    
    | 2673 |  |  | 				 * they match. | 
    
    | 2674 |  |  | 				 */ | 
    
    | 2675 |  |  | 				if ((slen == 0) && | 
    
    | 2676 |  |  | 				    (srcident->sadb_ident_id == 0)) { | 
    
    | 2677 |  |  | 					log_print("pf_key_v2_acquire: " | 
    
    | 2678 |  |  | 					    "no user FQDN or ID provided"); | 
    
    | 2679 |  |  | 					goto fail; | 
    
    | 2680 |  |  | 				} | 
    
    | 2681 |  |  | 				if (srcident->sadb_ident_id) { | 
    
    | 2682 |  |  | 					pwd = | 
    
    | 2683 |  |  | 					    getpwuid(srcident->sadb_ident_id); | 
    
    | 2684 |  |  | 					if (!pwd) { | 
    
    | 2685 |  |  | 						log_error("pf_key_v2_acquire: " | 
    
    | 2686 |  |  | 						    "could not acquire " | 
    
    | 2687 |  |  | 						    "username from provided " | 
    
    | 2688 |  |  | 						    "ID %llu", | 
    
    | 2689 |  |  | 						    srcident->sadb_ident_id); | 
    
    | 2690 |  |  | 						goto fail; | 
    
    | 2691 |  |  | 					} | 
    
    | 2692 |  |  | 					if (slen != 0) | 
    
    | 2693 |  |  | 						if (strcmp(pwd->pw_name, | 
    
    | 2694 |  |  | 						    (char *) (srcident + 1)) | 
    
    | 2695 |  |  | 						    != 0) { | 
    
    | 2696 |  |  | 							log_print("pf_key_v2_acquire: " | 
    
    | 2697 |  |  | 							    "provided user " | 
    
    | 2698 |  |  | 							    "name and ID do " | 
    
    | 2699 |  |  | 							    "not match (%s != " | 
    
    | 2700 |  |  | 							    "%s)", | 
    
    | 2701 |  |  | 							    (char *) (srcident + 1), | 
    
    | 2702 |  |  | 							    pwd->pw_name); | 
    
    | 2703 |  |  | 							/* | 
    
    | 2704 |  |  | 							 * String has | 
    
    | 2705 |  |  | 							 * precedence, per | 
    
    | 2706 |  |  | 							 * RFC 2367. | 
    
    | 2707 |  |  | 							 */ | 
    
    | 2708 |  |  | 						} | 
    
    | 2709 |  |  | 				} | 
    
    | 2710 |  |  | 			} | 
    
    | 2711 |  |  | 			if (asprintf(&srcid, "id-%s", | 
    
    | 2712 |  |  | 			    slen ? (char *) (srcident + 1) : pwd->pw_name) == -1) { | 
    
    | 2713 |  |  | 				log_error("pf_key_v2_acquire: asprintf() failed"); | 
    
    | 2714 |  |  | 				goto fail; | 
    
    | 2715 |  |  | 			} | 
    
    | 2716 |  |  | 			pwd = 0; | 
    
    | 2717 |  |  |  | 
    
    | 2718 |  |  | 			/* Set the section if it doesn't already exist. */ | 
    
    | 2719 |  |  | 			af = conf_begin(); | 
    
    | 2720 |  |  | 			if (!conf_get_str(srcid, "ID-type")) { | 
    
    | 2721 |  |  | 				if (conf_set(af, srcid, "ID-type", prefstring, | 
    
    | 2722 |  |  | 				    1, 0) || | 
    
    | 2723 |  |  | 				    conf_set(af, srcid, "Refcount", "1", 1, 0) || | 
    
    | 2724 |  |  | 				    conf_set(af, srcid, "Name", | 
    
    | 2725 |  |  | 					srcid + 3, 1, 0)) { | 
    
    | 2726 |  |  | 					conf_end(af, 0); | 
    
    | 2727 |  |  | 					goto fail; | 
    
    | 2728 |  |  | 				} | 
    
    | 2729 |  |  | 			} else | 
    
    | 2730 |  |  | 				pf_key_v2_conf_refinc(af, srcid); | 
    
    | 2731 |  |  | 			conf_end(af, 1); | 
    
    | 2732 |  |  | 			break; | 
    
    | 2733 |  |  |  | 
    
    | 2734 |  |  | 		default: | 
    
    | 2735 |  |  | 			LOG_DBG((LOG_SYSDEP, 20, | 
    
    | 2736 |  |  | 			    "pf_key_v2_acquire: invalid source ID type %d", | 
    
    | 2737 |  |  | 			    srcident->sadb_ident_type)); | 
    
    | 2738 |  |  | 			goto fail; | 
    
    | 2739 |  |  | 		} | 
    
    | 2740 |  |  |  | 
    
    | 2741 |  |  | 		LOG_DBG((LOG_SYSDEP, 50, | 
    
    | 2742 |  |  | 		    "pf_key_v2_acquire: constructed source ID \"%s\"", srcid)); | 
    
    | 2743 |  |  | 		prefstring = 0; | 
    
    | 2744 |  |  | 	} | 
    
    | 2745 |  |  | 	/* Insert destination ID. */ | 
    
    | 2746 |  |  | 	if (dstident) { | 
    
    | 2747 |  |  | 		slen = (dstident->sadb_ident_len * sizeof(u_int64_t)) | 
    
    | 2748 |  |  | 			- sizeof(struct sadb_ident); | 
    
    | 2749 |  |  |  | 
    
    | 2750 |  |  | 		/* Check for valid type. */ | 
    
    | 2751 |  |  | 		switch (dstident->sadb_ident_type) { | 
    
    | 2752 |  |  | 		case SADB_IDENTTYPE_PREFIX: | 
    
    | 2753 |  |  | 			/* Determine what the address family is. */ | 
    
    | 2754 |  |  | 			dstid = memchr(dstident + 1, ':', slen); | 
    
    | 2755 |  |  | 			if (dstid) | 
    
    | 2756 |  |  | 				afamily = AF_INET6; | 
    
    | 2757 |  |  | 			else | 
    
    | 2758 |  |  | 				afamily = AF_INET; | 
    
    | 2759 |  |  |  | 
    
    | 2760 |  |  | 			dstid = memchr(dstident + 1, '/', slen); | 
    
    | 2761 |  |  | 			if (!dstid) { | 
    
    | 2762 |  |  | 				log_print("pf_key_v2_acquire: " | 
    
    | 2763 |  |  | 				    "badly formatted PREFIX identity"); | 
    
    | 2764 |  |  | 				goto fail; | 
    
    | 2765 |  |  | 			} | 
    
    | 2766 |  |  | 			masklen = atoi(dstid + 1); | 
    
    | 2767 |  |  |  | 
    
    | 2768 |  |  | 			/* XXX We only support host addresses. */ | 
    
    | 2769 |  |  | 			if ((afamily == AF_INET6 && masklen != 128) || | 
    
    | 2770 |  |  | 			    (afamily == AF_INET && masklen != 32)) { | 
    
    | 2771 |  |  | 				log_print("pf_key_v2_acquire: " | 
    
    | 2772 |  |  | 				    "non-host address specified in " | 
    
    | 2773 |  |  | 				    "destination identity (mask length %d), " | 
    
    | 2774 |  |  | 				    "ignoring request", masklen); | 
    
    | 2775 |  |  | 				goto fail; | 
    
    | 2776 |  |  | 			} | 
    
    | 2777 |  |  | 			/* | 
    
    | 2778 |  |  | 			 * NUL-terminate the PREFIX string at the separator, | 
    
    | 2779 |  |  | 			 * then dup. | 
    
    | 2780 |  |  | 			 */ | 
    
    | 2781 |  |  | 			*dstid = '\0'; | 
    
    | 2782 |  |  | 			if (asprintf(&dstid, "id-%s", | 
    
    | 2783 |  |  | 			    (char *) (dstident + 1)) == -1) { | 
    
    | 2784 |  |  | 				log_error("pf_key_v2_acquire: asprintf() failed"); | 
    
    | 2785 |  |  | 				goto fail; | 
    
    | 2786 |  |  | 			} | 
    
    | 2787 |  |  |  | 
    
    | 2788 |  |  | 			/* Set the section if it doesn't already exist. */ | 
    
    | 2789 |  |  | 			af = conf_begin(); | 
    
    | 2790 |  |  | 			if (!conf_get_str(dstid, "ID-type")) { | 
    
    | 2791 |  |  | 				if (conf_set(af, dstid, "ID-type", | 
    
    | 2792 |  |  | 				    afamily == AF_INET ? "IPV4_ADDR" : | 
    
    | 2793 |  |  | 				    "IPV6_ADDR", 1, 0) || | 
    
    | 2794 |  |  | 				    conf_set(af, dstid, "Refcount", "1", 1, 0) || | 
    
    | 2795 |  |  | 				    conf_set(af, dstid, "Address", | 
    
    | 2796 |  |  | 					(char *) (dstident + 1), 1, 0)) { | 
    
    | 2797 |  |  | 					conf_end(af, 0); | 
    
    | 2798 |  |  | 					goto fail; | 
    
    | 2799 |  |  | 				} | 
    
    | 2800 |  |  | 			} else | 
    
    | 2801 |  |  | 				pf_key_v2_conf_refinc(af, dstid); | 
    
    | 2802 |  |  | 			conf_end(af, 1); | 
    
    | 2803 |  |  | 			break; | 
    
    | 2804 |  |  |  | 
    
    | 2805 |  |  | 		case SADB_IDENTTYPE_FQDN: | 
    
    | 2806 |  |  | 			prefstring = "FQDN"; | 
    
    | 2807 |  |  | 			/*FALLTHROUGH*/ | 
    
    | 2808 |  |  | 		case SADB_IDENTTYPE_USERFQDN: | 
    
    | 2809 |  |  | 			if (!prefstring) { | 
    
    | 2810 |  |  | 				prefstring = "USER_FQDN"; | 
    
    | 2811 |  |  |  | 
    
    | 2812 |  |  | 				/* | 
    
    | 2813 |  |  | 				 * Check whether there is a string following | 
    
    | 2814 |  |  | 				 * the header; if no, that there is a user ID | 
    
    | 2815 |  |  | 				 * (and acquire the login name). If there is | 
    
    | 2816 |  |  | 				 * both a string and a user ID, check that | 
    
    | 2817 |  |  | 				 * they match. | 
    
    | 2818 |  |  | 				 */ | 
    
    | 2819 |  |  | 				if (slen == 0 && | 
    
    | 2820 |  |  | 				    dstident->sadb_ident_id == 0) { | 
    
    | 2821 |  |  | 					log_print("pf_key_v2_acquire: " | 
    
    | 2822 |  |  | 					    "no user FQDN or ID provided"); | 
    
    | 2823 |  |  | 					goto fail; | 
    
    | 2824 |  |  | 				} | 
    
    | 2825 |  |  | 				if (dstident->sadb_ident_id) { | 
    
    | 2826 |  |  | 					pwd = getpwuid(dstident->sadb_ident_id); | 
    
    | 2827 |  |  | 					if (!pwd) { | 
    
    | 2828 |  |  | 						log_error("pf_key_v2_acquire: " | 
    
    | 2829 |  |  | 						    "could not acquire " | 
    
    | 2830 |  |  | 						    "username from provided " | 
    
    | 2831 |  |  | 						    "ID %llu", | 
    
    | 2832 |  |  | 						    dstident->sadb_ident_id); | 
    
    | 2833 |  |  | 						goto fail; | 
    
    | 2834 |  |  | 					} | 
    
    | 2835 |  |  | 					if (slen != 0) | 
    
    | 2836 |  |  | 						if (strcmp(pwd->pw_name, | 
    
    | 2837 |  |  | 						    (char *) (dstident + 1)) | 
    
    | 2838 |  |  | 						    != 0) { | 
    
    | 2839 |  |  | 							log_print("pf_key_v2_acquire: " | 
    
    | 2840 |  |  | 							    "provided user " | 
    
    | 2841 |  |  | 							    "name and ID do " | 
    
    | 2842 |  |  | 							    "not match (%s != " | 
    
    | 2843 |  |  | 							    "%s)", | 
    
    | 2844 |  |  | 							    (char *) (dstident + 1), | 
    
    | 2845 |  |  | 							    pwd->pw_name); | 
    
    | 2846 |  |  | 							/* | 
    
    | 2847 |  |  | 							 * String has | 
    
    | 2848 |  |  | 							 * precedence, per RF | 
    
    | 2849 |  |  | 							 * 2367. | 
    
    | 2850 |  |  | 							 */ | 
    
    | 2851 |  |  | 						} | 
    
    | 2852 |  |  | 				} | 
    
    | 2853 |  |  | 			} | 
    
    | 2854 |  |  | 			if (asprintf(&dstid, "id-%s", | 
    
    | 2855 |  |  | 			    slen ? (char *) (dstident + 1) : pwd->pw_name) == -1) { | 
    
    | 2856 |  |  | 				log_error("pf_key_v2_acquire: asprintf() failed"); | 
    
    | 2857 |  |  | 				goto fail; | 
    
    | 2858 |  |  | 			} | 
    
    | 2859 |  |  | 			pwd = 0; | 
    
    | 2860 |  |  |  | 
    
    | 2861 |  |  | 			/* Set the section if it doesn't already exist. */ | 
    
    | 2862 |  |  | 			af = conf_begin(); | 
    
    | 2863 |  |  | 			if (!conf_get_str(dstid, "ID-type")) { | 
    
    | 2864 |  |  | 				if (conf_set(af, dstid, "ID-type", prefstring, | 
    
    | 2865 |  |  | 				    1, 0) || | 
    
    | 2866 |  |  | 				    conf_set(af, dstid, "Refcount", "1", 1, 0) || | 
    
    | 2867 |  |  | 				    conf_set(af, dstid, "Name", | 
    
    | 2868 |  |  | 					dstid + 3, 1, 0)) { | 
    
    | 2869 |  |  | 					conf_end(af, 0); | 
    
    | 2870 |  |  | 					goto fail; | 
    
    | 2871 |  |  | 				} | 
    
    | 2872 |  |  | 			} else | 
    
    | 2873 |  |  | 				pf_key_v2_conf_refinc(af, dstid); | 
    
    | 2874 |  |  | 			conf_end(af, 1); | 
    
    | 2875 |  |  | 			break; | 
    
    | 2876 |  |  |  | 
    
    | 2877 |  |  | 		default: | 
    
    | 2878 |  |  | 			LOG_DBG((LOG_SYSDEP, 20, "pf_key_v2_acquire: " | 
    
    | 2879 |  |  | 			    "invalid destination ID type %d", | 
    
    | 2880 |  |  | 			    dstident->sadb_ident_type)); | 
    
    | 2881 |  |  | 			goto fail; | 
    
    | 2882 |  |  | 		} | 
    
    | 2883 |  |  |  | 
    
    | 2884 |  |  | 		LOG_DBG((LOG_SYSDEP, 50, | 
    
    | 2885 |  |  | 		    "pf_key_v2_acquire: constructed destination ID \"%s\"", | 
    
    | 2886 |  |  | 		    dstid)); | 
    
    | 2887 |  |  | 	} | 
    
    | 2888 |  |  | 	/* Now we've placed the necessary IDs in the configuration space. */ | 
    
    | 2889 |  |  |  | 
    
    | 2890 |  |  | 	/* Get a new connection sequence number. */ | 
    
    | 2891 |  |  | 	for (;; connection_seq++) { | 
    
    | 2892 |  |  | 		snprintf(conn, connlen, "Connection-%u", connection_seq); | 
    
    | 2893 |  |  |  | 
    
    | 2894 |  |  | 		/* Does it exist ? */ | 
    
    | 2895 |  |  | 		if (!conf_get_str(conn, "Phase")) | 
    
    | 2896 |  |  | 			break; | 
    
    | 2897 |  |  | 	} | 
    
    | 2898 |  |  |  | 
    
    | 2899 |  |  | 	/* | 
    
    | 2900 |  |  | 	 * Set the IPsec connection entry. In particular, the following fields: | 
    
    | 2901 |  |  | 	 * - Phase | 
    
    | 2902 |  |  | 	 * - ISAKMP-peer | 
    
    | 2903 |  |  | 	 * - Local-ID/Remote-ID (if provided) | 
    
    | 2904 |  |  | 	 * - Acquire-ID (sequence number of kernel message, e.g., PF_KEYv2) | 
    
    | 2905 |  |  | 	 * - Configuration | 
    
    | 2906 |  |  | 	 * | 
    
    | 2907 |  |  | 	 * Also set the following section: | 
    
    | 2908 |  |  | 	 *    [peer-dstaddr(-local-srcaddr)] | 
    
    | 2909 |  |  | 	 * with these fields: | 
    
    | 2910 |  |  | 	 * - Phase | 
    
    | 2911 |  |  | 	 * - ID (if provided) | 
    
    | 2912 |  |  | 	 * - Remote-ID (if provided) | 
    
    | 2913 |  |  | 	 * - Local-address (if provided) | 
    
    | 2914 |  |  | 	 * - Address | 
    
    | 2915 |  |  | 	 * - Configuration (if an entry phase1-dstaddr-srcadd) | 
    
    | 2916 |  |  | 	 *                  exists -- otherwise use the defaults) | 
    
    | 2917 |  |  | 	 */ | 
    
    | 2918 |  |  |  | 
    
    | 2919 |  |  | 	/* | 
    
    | 2920 |  |  | 	 * The various cases: | 
    
    | 2921 |  |  | 	 * - peer-dstaddr | 
    
    | 2922 |  |  | 	 * - peer-dstaddr-local-srcaddr | 
    
    | 2923 |  |  | 	 */ | 
    
    | 2924 |  |  | 	if (asprintf(&peer, "peer-%s%s%s", dstbuf, srcaddr ? "-local-" : "", | 
    
    | 2925 |  |  | 	    srcaddr ? srcbuf : "") == -1) | 
    
    | 2926 |  |  | 		goto fail; | 
    
    | 2927 |  |  |  | 
    
    | 2928 |  |  | 	/* | 
    
    | 2929 |  |  | 	 * Set the IPsec connection section. Refcount is set to 2, because | 
    
    | 2930 |  |  | 	 * it will be linked both to the incoming and the outgoing SA. | 
    
    | 2931 |  |  | 	 */ | 
    
    | 2932 |  |  | 	af = conf_begin(); | 
    
    | 2933 |  |  | 	if (conf_set(af, conn, "Phase", "2", 0, 0) || | 
    
    | 2934 |  |  | 	    conf_set(af, conn, "Flags", "__ondemand", 0, 0) || | 
    
    | 2935 |  |  | 	    conf_set(af, conn, "Refcount", "2", 0, 0) || | 
    
    | 2936 |  |  | 	    conf_set(af, conn, "ISAKMP-peer", peer, 0, 0)) { | 
    
    | 2937 |  |  | 		conf_end(af, 0); | 
    
    | 2938 |  |  | 		goto fail; | 
    
    | 2939 |  |  | 	} | 
    
    | 2940 |  |  | 	/* Set the sequence number. */ | 
    
    | 2941 |  |  | 	snprintf(lname, sizeof lname, "%u", msg->sadb_msg_seq); | 
    
    | 2942 |  |  | 	if (conf_set(af, conn, "Acquire-ID", lname, 0, 0)) { | 
    
    | 2943 |  |  | 		conf_end(af, 0); | 
    
    | 2944 |  |  | 		goto fail; | 
    
    | 2945 |  |  | 	} | 
    
    | 2946 |  |  | 	/* | 
    
    | 2947 |  |  | 	 * Set Phase 2 IDs -- this is the Local-ID section. | 
    
    | 2948 |  |  | 	 * - from-address | 
    
    | 2949 |  |  | 	 * - from-address=proto | 
    
    | 2950 |  |  | 	 * - from-address=proto:port | 
    
    | 2951 |  |  | 	 * - from-network/masklen | 
    
    | 2952 |  |  | 	 * - from-network/masklen=proto | 
    
    | 2953 |  |  | 	 * - from-network/masklen=proto:port | 
    
    | 2954 |  |  | 	 */ | 
    
    | 2955 |  |  | 	phase2id(lname, sizeof lname, "from", ssflow, smasklen, tproto, sport); | 
    
    | 2956 |  |  | 	if (conf_set(af, conn, "Local-ID", lname, 0, 0)) { | 
    
    | 2957 |  |  | 		conf_end(af, 0); | 
    
    | 2958 |  |  | 		goto fail; | 
    
    | 2959 |  |  | 	} | 
    
    | 2960 |  |  | 	if (!conf_get_str(lname, "ID-type")) { | 
    
    | 2961 |  |  | 		if (conf_set(af, lname, "Refcount", "1", 0, 0)) { | 
    
    | 2962 |  |  | 			conf_end(af, 0); | 
    
    | 2963 |  |  | 			goto fail; | 
    
    | 2964 |  |  | 		} | 
    
    | 2965 |  |  | 		if (shostflag) { | 
    
    | 2966 |  |  | 			if (conf_set(af, lname, "ID-type", sidtype, 0, 0) || | 
    
    | 2967 |  |  | 			    conf_set(af, lname, "Address", ssflow, 0, 0)) { | 
    
    | 2968 |  |  | 				conf_end(af, 0); | 
    
    | 2969 |  |  | 				goto fail; | 
    
    | 2970 |  |  | 			} | 
    
    | 2971 |  |  | 		} else { | 
    
    | 2972 |  |  | 			if (conf_set(af, lname, "ID-type", sidtype, 0, 0) || | 
    
    | 2973 |  |  | 			    conf_set(af, lname, "Network", ssflow, 0, 0) || | 
    
    | 2974 |  |  | 			    conf_set(af, lname, "Netmask", ssmask, 0, 0)) { | 
    
    | 2975 |  |  | 				conf_end(af, 0); | 
    
    | 2976 |  |  | 				goto fail; | 
    
    | 2977 |  |  | 			} | 
    
    | 2978 |  |  | 		} | 
    
    | 2979 |  |  | 		if (tproto) { | 
    
    | 2980 |  |  | 			snprintf(tmbuf, sizeof sport * 3 + 1, "%u", tproto); | 
    
    | 2981 |  |  | 			if (conf_set(af, lname, "Protocol", tmbuf, 0, 0)) { | 
    
    | 2982 |  |  | 				conf_end(af, 0); | 
    
    | 2983 |  |  | 				goto fail; | 
    
    | 2984 |  |  | 			} | 
    
    | 2985 |  |  | 			if (sport) { | 
    
    | 2986 |  |  | 				snprintf(tmbuf, sizeof sport * 3 + 1, "%u", | 
    
    | 2987 |  |  | 				    ntohs(sport)); | 
    
    | 2988 |  |  | 				if (conf_set(af, lname, "Port", tmbuf, 0, 0)) { | 
    
    | 2989 |  |  | 					conf_end(af, 0); | 
    
    | 2990 |  |  | 					goto fail; | 
    
    | 2991 |  |  | 				} | 
    
    | 2992 |  |  | 			} | 
    
    | 2993 |  |  | 		} | 
    
    | 2994 |  |  | 	} else | 
    
    | 2995 |  |  | 		pf_key_v2_conf_refinc(af, lname); | 
    
    | 2996 |  |  |  | 
    
    | 2997 |  |  | 	/* | 
    
    | 2998 |  |  | 	 * Set Remote-ID section. | 
    
    | 2999 |  |  | 	 * to-address | 
    
    | 3000 |  |  | 	 * to-address=proto | 
    
    | 3001 |  |  | 	 * to-address=proto:port | 
    
    | 3002 |  |  | 	 * to-network/masklen | 
    
    | 3003 |  |  | 	 * to-network/masklen=proto | 
    
    | 3004 |  |  | 	 * to-network/masklen=proto:port | 
    
    | 3005 |  |  | 	 */ | 
    
    | 3006 |  |  | 	phase2id(dname, sizeof dname, "to", sdflow, dmasklen, tproto, dport); | 
    
    | 3007 |  |  | 	if (conf_set(af, conn, "Remote-ID", dname, 0, 0)) { | 
    
    | 3008 |  |  | 		conf_end(af, 0); | 
    
    | 3009 |  |  | 		goto fail; | 
    
    | 3010 |  |  | 	} | 
    
    | 3011 |  |  | 	if (!conf_get_str(dname, "ID-type")) { | 
    
    | 3012 |  |  | 		if (conf_set(af, dname, "Refcount", "1", 0, 0)) { | 
    
    | 3013 |  |  | 			conf_end(af, 0); | 
    
    | 3014 |  |  | 			goto fail; | 
    
    | 3015 |  |  | 		} | 
    
    | 3016 |  |  | 		if (dhostflag) { | 
    
    | 3017 |  |  | 			if (conf_set(af, dname, "ID-type", didtype, 0, 0) || | 
    
    | 3018 |  |  | 			    conf_set(af, dname, "Address", sdflow, 0, 0)) { | 
    
    | 3019 |  |  | 				conf_end(af, 0); | 
    
    | 3020 |  |  | 				goto fail; | 
    
    | 3021 |  |  | 			} | 
    
    | 3022 |  |  | 		} else { | 
    
    | 3023 |  |  | 			if (conf_set(af, dname, "ID-type", didtype, 0, 0) || | 
    
    | 3024 |  |  | 			    conf_set(af, dname, "Network", sdflow, 0, 0) || | 
    
    | 3025 |  |  | 			    conf_set(af, dname, "Netmask", sdmask, 0, 0)) { | 
    
    | 3026 |  |  | 				conf_end(af, 0); | 
    
    | 3027 |  |  | 				goto fail; | 
    
    | 3028 |  |  | 			} | 
    
    | 3029 |  |  | 		} | 
    
    | 3030 |  |  |  | 
    
    | 3031 |  |  | 		if (tproto) { | 
    
    | 3032 |  |  | 			snprintf(tmbuf, sizeof dport * 3 + 1, "%u", tproto); | 
    
    | 3033 |  |  | 			if (conf_set(af, dname, "Protocol", tmbuf, 0, 0)) { | 
    
    | 3034 |  |  | 				conf_end(af, 0); | 
    
    | 3035 |  |  | 				goto fail; | 
    
    | 3036 |  |  | 			} | 
    
    | 3037 |  |  | 			if (dport) { | 
    
    | 3038 |  |  | 				snprintf(tmbuf, sizeof dport * 3 + 1, "%u", | 
    
    | 3039 |  |  | 				    ntohs(dport)); | 
    
    | 3040 |  |  | 				if (conf_set(af, dname, "Port", tmbuf, 0, 0)) { | 
    
    | 3041 |  |  | 					conf_end(af, 0); | 
    
    | 3042 |  |  | 					goto fail; | 
    
    | 3043 |  |  | 				} | 
    
    | 3044 |  |  | 			} | 
    
    | 3045 |  |  | 		} | 
    
    | 3046 |  |  | 	} else | 
    
    | 3047 |  |  | 		pf_key_v2_conf_refinc(af, dname); | 
    
    | 3048 |  |  |  | 
    
    | 3049 |  |  | 	/* | 
    
    | 3050 |  |  | 	 * XXX | 
    
    | 3051 |  |  | 	 * We should be using information from the proposal to set this up. | 
    
    | 3052 |  |  | 	 * At least, we should make this selectable. | 
    
    | 3053 |  |  | 	 */ | 
    
    | 3054 |  |  |  | 
    
    | 3055 |  |  | 	/* | 
    
    | 3056 |  |  | 	 * Phase 2 configuration. | 
    
    | 3057 |  |  | 	 * - phase2-from-address-to-address | 
    
    | 3058 |  |  | 	 * - ... | 
    
    | 3059 |  |  | 	 * - phase2-from-net/len=proto:port-to-net/len=proto:port | 
    
    | 3060 |  |  | 	 */ | 
    
    | 3061 |  |  | 	snprintf(configname, sizeof configname, "phase2-%s-%s", lname, dname); | 
    
    | 3062 |  |  | 	if (conf_set(af, conn, "Configuration", configname, 0, 0)) { | 
    
    | 3063 |  |  | 		conf_end(af, 0); | 
    
    | 3064 |  |  | 		goto fail; | 
    
    | 3065 |  |  | 	} | 
    
    | 3066 |  |  | 	if (!conf_get_str(configname, "Exchange_type")) { | 
    
    | 3067 |  |  | 		if (conf_set(af, configname, "Exchange_type", "Quick_mode", | 
    
    | 3068 |  |  | 		    0, 0) || | 
    
    | 3069 |  |  | 		    conf_set(af, peer, "Refcount", "1", 0, 0) || | 
    
    | 3070 |  |  | 		    conf_set(af, configname, "DOI", "IPSEC", 0, 0)) { | 
    
    | 3071 |  |  | 			conf_end(af, 0); | 
    
    | 3072 |  |  | 			goto fail; | 
    
    | 3073 |  |  | 		} | 
    
    | 3074 |  |  | 		if (conf_get_str("General", "Default-phase-2-suites")) { | 
    
    | 3075 |  |  | 			if (conf_set(af, configname, "Suites", | 
    
    | 3076 |  |  | 			    conf_get_str("General", "Default-phase-2-suites"), | 
    
    | 3077 |  |  | 			    0, 0)) { | 
    
    | 3078 |  |  | 				conf_end(af, 0); | 
    
    | 3079 |  |  | 				goto fail; | 
    
    | 3080 |  |  | 			} | 
    
    | 3081 |  |  | 		} else { | 
    
    | 3082 |  |  | 			if (conf_set(af, configname, "Suites", | 
    
    | 3083 |  |  | 			    "QM-ESP-3DES-SHA-PFS-SUITE", 0, 0)) { | 
    
    | 3084 |  |  | 				conf_end(af, 0); | 
    
    | 3085 |  |  | 				goto fail; | 
    
    | 3086 |  |  | 			} | 
    
    | 3087 |  |  | 		} | 
    
    | 3088 |  |  | 	} else | 
    
    | 3089 |  |  | 		pf_key_v2_conf_refinc(af, configname); | 
    
    | 3090 |  |  |  | 
    
    | 3091 |  |  | 	/* Set the ISAKMP-peer section. */ | 
    
    | 3092 |  |  | 	if (!conf_get_str(peer, "Phase")) { | 
    
    | 3093 |  |  | 		if (conf_set(af, peer, "Phase", "1", 0, 0) || | 
    
    | 3094 |  |  | 		    conf_set(af, peer, "Refcount", "1", 0, 0) || | 
    
    | 3095 |  |  | 		    conf_set(af, peer, "Address", dstbuf, 0, 0)) { | 
    
    | 3096 |  |  | 			conf_end(af, 0); | 
    
    | 3097 |  |  | 			goto fail; | 
    
    | 3098 |  |  | 		} | 
    
    | 3099 |  |  | 		if (srcaddr && conf_set(af, peer, "Local-address", srcbuf, 0, | 
    
    | 3100 |  |  | 		    0)) { | 
    
    | 3101 |  |  | 			conf_end(af, 0); | 
    
    | 3102 |  |  | 			goto fail; | 
    
    | 3103 |  |  | 		} | 
    
    | 3104 |  |  | 		snprintf(confname, sizeof confname, "phase1-%s", peer); | 
    
    | 3105 |  |  | 		if (conf_set(af, peer, "Configuration", confname, 0, 0)) { | 
    
    | 3106 |  |  | 			conf_end(af, 0); | 
    
    | 3107 |  |  | 			goto fail; | 
    
    | 3108 |  |  | 		} | 
    
    | 3109 |  |  |  | 
    
    | 3110 |  |  | 		/* Phase 1 configuration. */ | 
    
    | 3111 |  |  | 		if (!conf_get_str(confname, "exchange_type")) { | 
    
    | 3112 |  |  | 			xform = conf_get_str("Default-phase-1-configuration", | 
    
    | 3113 |  |  | 			"Transforms"); | 
    
    | 3114 |  |  | 			if (conf_set(af, confname, "Transforms", xform ? xform : | 
    
    | 3115 |  |  | 			    "3DES-SHA-RSA_SIG", 0, 0)) { | 
    
    | 3116 |  |  | 				conf_end(af, 0); | 
    
    | 3117 |  |  | 				goto fail; | 
    
    | 3118 |  |  | 			} | 
    
    | 3119 |  |  |  | 
    
    | 3120 |  |  | 			if (conf_set(af, confname, "Exchange_Type", "ID_PROT", | 
    
    | 3121 |  |  | 			    0, 0) || | 
    
    | 3122 |  |  | 			    conf_set(af, confname, "DOI", "IPSEC", 0, 0) || | 
    
    | 3123 |  |  | 			    conf_set(af, confname, "Refcount", "1", 0, 0)) { | 
    
    | 3124 |  |  | 				conf_end(af, 0); | 
    
    | 3125 |  |  | 				goto fail; | 
    
    | 3126 |  |  | 			} | 
    
    | 3127 |  |  | 		} else | 
    
    | 3128 |  |  | 			pf_key_v2_conf_refinc(af, confname); | 
    
    | 3129 |  |  |  | 
    
    | 3130 |  |  | 		/* The ID we should use in Phase 1. */ | 
    
    | 3131 |  |  | 		if (srcid && conf_set(af, peer, "ID", srcid, 0, 0)) { | 
    
    | 3132 |  |  | 			conf_end(af, 0); | 
    
    | 3133 |  |  | 			goto fail; | 
    
    | 3134 |  |  | 		} | 
    
    | 3135 |  |  | 		/* The ID the other side should use in Phase 1. */ | 
    
    | 3136 |  |  | 		if (dstid && conf_set(af, peer, "Remote-ID", dstid, 0, 0)) { | 
    
    | 3137 |  |  | 			conf_end(af, 0); | 
    
    | 3138 |  |  | 			goto fail; | 
    
    | 3139 |  |  | 		} | 
    
    | 3140 |  |  | 	} else | 
    
    | 3141 |  |  | 		pf_key_v2_conf_refinc(af, peer); | 
    
    | 3142 |  |  |  | 
    
    | 3143 |  |  | 	/* All done. */ | 
    
    | 3144 |  |  | 	conf_end(af, 1); | 
    
    | 3145 |  |  |  | 
    
    | 3146 |  |  | 	/* Let's rock 'n roll. */ | 
    
    | 3147 |  |  | 	pf_key_v2_connection_check(conn); | 
    
    | 3148 |  |  | 	connection_record_passive(conn); | 
    
    | 3149 |  |  | 	conn = 0; | 
    
    | 3150 |  |  |  | 
    
    | 3151 |  |  | 	/* Fall-through to cleanup. */ | 
    
    | 3152 |  |  | fail: | 
    
    | 3153 |  |  | 	if (ret) | 
    
    | 3154 |  |  | 		pf_key_v2_msg_free(ret); | 
    
    | 3155 |  |  | 	if (askpolicy) | 
    
    | 3156 |  |  | 		pf_key_v2_msg_free(askpolicy); | 
    
    | 3157 |  |  | 	free(srcid); | 
    
    | 3158 |  |  | 	free(dstid); | 
    
    | 3159 |  |  | 	free(peer); | 
    
    | 3160 |  |  | 	free(conn); | 
    
    | 3161 |  |  | 	return; | 
    
    | 3162 |  |  | } | 
    
    | 3163 |  |  |  | 
    
    | 3164 |  |  | static void | 
    
    | 3165 |  |  | pf_key_v2_notify(struct pf_key_v2_msg *msg) | 
    
    | 3166 |  |  | { | 
    
    | 3167 |  |  | 	switch (((struct sadb_msg *)TAILQ_FIRST(msg)->seg)->sadb_msg_type) { | 
    
    | 3168 |  |  | 	case SADB_EXPIRE: | 
    
    | 3169 |  |  | 		pf_key_v2_expire(msg); | 
    
    | 3170 |  |  | 		break; | 
    
    | 3171 |  |  |  | 
    
    | 3172 |  |  | 	case SADB_ACQUIRE: | 
    
    | 3173 |  |  | 		if (!ui_daemon_passive) | 
    
    | 3174 |  |  | 			pf_key_v2_acquire(msg); | 
    
    | 3175 |  |  | 		break; | 
    
    | 3176 |  |  |  | 
    
    | 3177 |  |  | 	default: | 
    
    | 3178 |  |  | 		log_print("pf_key_v2_notify: unexpected message type (%d)", | 
    
    | 3179 |  |  | 		    ((struct sadb_msg *)TAILQ_FIRST(msg)->seg)->sadb_msg_type); | 
    
    | 3180 |  |  | 	} | 
    
    | 3181 |  |  | 	pf_key_v2_msg_free(msg); | 
    
    | 3182 |  |  | } | 
    
    | 3183 |  |  |  | 
    
    | 3184 |  |  | void | 
    
    | 3185 |  |  | pf_key_v2_handler(int fd) | 
    
    | 3186 |  |  | { | 
    
    | 3187 |  |  | 	struct pf_key_v2_msg *msg; | 
    
    | 3188 |  |  | 	int		n; | 
    
    | 3189 |  |  |  | 
    
    | 3190 |  |  | 	/* | 
    
    | 3191 |  |  | 	 * As synchronous read/writes to the socket can have taken place | 
    
    | 3192 |  |  | 	 * between the select(2) call of the main loop and this handler, we | 
    
    | 3193 |  |  | 	 * need to recheck the readability. | 
    
    | 3194 |  |  | 	 */ | 
    
    | 3195 |  |  | 	if (ioctl(pf_key_v2_socket, FIONREAD, &n) == -1) { | 
    
    | 3196 |  |  | 		log_error("pf_key_v2_handler: ioctl (%d, FIONREAD, &n) failed", | 
    
    | 3197 |  |  | 		    pf_key_v2_socket); | 
    
    | 3198 |  |  | 		return; | 
    
    | 3199 |  |  | 	} | 
    
    | 3200 |  |  | 	if (!n) | 
    
    | 3201 |  |  | 		return; | 
    
    | 3202 |  |  |  | 
    
    | 3203 |  |  | 	msg = pf_key_v2_read(0); | 
    
    | 3204 |  |  | 	if (msg) | 
    
    | 3205 |  |  | 		pf_key_v2_notify(msg); | 
    
    | 3206 |  |  | } | 
    
    | 3207 |  |  |  | 
    
    | 3208 |  |  | /* | 
    
    | 3209 |  |  |  * Group 2 IPsec SAs given by the PROTO1 and PROTO2 protocols of the SA IKE | 
    
    | 3210 |  |  |  * security association in a chain. | 
    
    | 3211 |  |  |  * XXX Assumes OpenBSD GRPSPIS extension. | 
    
    | 3212 |  |  |  */ | 
    
    | 3213 |  |  | int | 
    
    | 3214 |  |  | pf_key_v2_group_spis(struct sa *sa, struct proto *proto1, | 
    
    | 3215 |  |  |     struct proto *proto2, int incoming) | 
    
    | 3216 |  |  | { | 
    
    | 3217 |  |  | 	struct sadb_msg msg; | 
    
    | 3218 |  |  | 	struct sadb_sa  sa1, sa2; | 
    
    | 3219 |  |  | 	struct sadb_address *addr = 0; | 
    
    | 3220 |  |  | 	struct sadb_protocol protocol; | 
    
    | 3221 |  |  | 	struct pf_key_v2_msg *grpspis = 0, *ret = 0; | 
    
    | 3222 |  |  | 	struct sockaddr *saddr; | 
    
    | 3223 |  |  | 	int		err; | 
    
    | 3224 |  |  | 	size_t		len; | 
    
    | 3225 |  |  |  | 
    
    | 3226 |  |  | 	msg.sadb_msg_type = SADB_X_GRPSPIS; | 
    
    | 3227 |  |  | 	switch (proto1->proto) { | 
    
    | 3228 |  |  | 	case IPSEC_PROTO_IPSEC_ESP: | 
    
    | 3229 |  |  | 		msg.sadb_msg_satype = SADB_SATYPE_ESP; | 
    
    | 3230 |  |  | 		break; | 
    
    | 3231 |  |  | 	case IPSEC_PROTO_IPSEC_AH: | 
    
    | 3232 |  |  | 		msg.sadb_msg_satype = SADB_SATYPE_AH; | 
    
    | 3233 |  |  | 		break; | 
    
    | 3234 |  |  | 	case IPSEC_PROTO_IPCOMP: | 
    
    | 3235 |  |  | 		msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP; | 
    
    | 3236 |  |  | 		break; | 
    
    | 3237 |  |  | 	default: | 
    
    | 3238 |  |  | 		log_print("pf_key_v2_group_spis: invalid proto %d", | 
    
    | 3239 |  |  | 		    proto1->proto); | 
    
    | 3240 |  |  | 		goto cleanup; | 
    
    | 3241 |  |  | 	} | 
    
    | 3242 |  |  | 	msg.sadb_msg_seq = 0; | 
    
    | 3243 |  |  | 	grpspis = pf_key_v2_msg_new(&msg, 0); | 
    
    | 3244 |  |  | 	if (!grpspis) | 
    
    | 3245 |  |  | 		goto cleanup; | 
    
    | 3246 |  |  |  | 
    
    | 3247 |  |  | 	/* Setup the SA extensions.  */ | 
    
    | 3248 |  |  | 	sa1.sadb_sa_exttype = SADB_EXT_SA; | 
    
    | 3249 |  |  | 	sa1.sadb_sa_len = sizeof sa1 / PF_KEY_V2_CHUNK; | 
    
    | 3250 |  |  | 	memcpy(&sa1.sadb_sa_spi, proto1->spi[incoming], | 
    
    | 3251 |  |  | 	    sizeof sa1.sadb_sa_spi); | 
    
    | 3252 |  |  | 	sa1.sadb_sa_replay = 0; | 
    
    | 3253 |  |  | 	sa1.sadb_sa_state = 0; | 
    
    | 3254 |  |  | 	sa1.sadb_sa_auth = 0; | 
    
    | 3255 |  |  | 	sa1.sadb_sa_encrypt = 0; | 
    
    | 3256 |  |  | 	sa1.sadb_sa_flags = 0; | 
    
    | 3257 |  |  | 	if (pf_key_v2_msg_add(grpspis, (struct sadb_ext *)&sa1, 0) == -1) | 
    
    | 3258 |  |  | 		goto cleanup; | 
    
    | 3259 |  |  |  | 
    
    | 3260 |  |  | 	sa2.sadb_sa_exttype = SADB_X_EXT_SA2; | 
    
    | 3261 |  |  | 	sa2.sadb_sa_len = sizeof sa2 / PF_KEY_V2_CHUNK; | 
    
    | 3262 |  |  | 	memcpy(&sa2.sadb_sa_spi, proto2->spi[incoming], | 
    
    | 3263 |  |  | 	    sizeof sa2.sadb_sa_spi); | 
    
    | 3264 |  |  | 	sa2.sadb_sa_replay = 0; | 
    
    | 3265 |  |  | 	sa2.sadb_sa_state = 0; | 
    
    | 3266 |  |  | 	sa2.sadb_sa_auth = 0; | 
    
    | 3267 |  |  | 	sa2.sadb_sa_encrypt = 0; | 
    
    | 3268 |  |  | 	sa2.sadb_sa_flags = 0; | 
    
    | 3269 |  |  | 	if (pf_key_v2_msg_add(grpspis, (struct sadb_ext *)&sa2, 0) == -1) | 
    
    | 3270 |  |  | 		goto cleanup; | 
    
    | 3271 |  |  |  | 
    
    | 3272 |  |  | 	/* | 
    
    | 3273 |  |  | 	 * Setup the ADDRESS extensions. | 
    
    | 3274 |  |  | 	 */ | 
    
    | 3275 |  |  | 	if (incoming) | 
    
    | 3276 |  |  | 		sa->transport->vtbl->get_src(sa->transport, &saddr); | 
    
    | 3277 |  |  | 	else | 
    
    | 3278 |  |  | 		sa->transport->vtbl->get_dst(sa->transport, &saddr); | 
    
    | 3279 |  |  | 	len = sizeof *addr + PF_KEY_V2_ROUND(SA_LEN(saddr)); | 
    
    | 3280 |  |  | 	addr = calloc(1, len); | 
    
    | 3281 |  |  | 	if (!addr) | 
    
    | 3282 |  |  | 		goto cleanup; | 
    
    | 3283 |  |  | 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; | 
    
    | 3284 |  |  | 	addr->sadb_address_len = len / PF_KEY_V2_CHUNK; | 
    
    | 3285 |  |  | 	addr->sadb_address_reserved = 0; | 
    
    | 3286 |  |  | 	memcpy(addr + 1, saddr, SA_LEN(saddr)); | 
    
    | 3287 |  |  | 	((struct sockaddr_in *) (addr + 1))->sin_port = 0; | 
    
    | 3288 |  |  | 	if (pf_key_v2_msg_add(grpspis, (struct sadb_ext *) addr, | 
    
    | 3289 |  |  | 	    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 3290 |  |  | 		goto cleanup; | 
    
    | 3291 |  |  | 	addr = 0; | 
    
    | 3292 |  |  |  | 
    
    | 3293 |  |  | 	addr = calloc(1, len); | 
    
    | 3294 |  |  | 	if (!addr) | 
    
    | 3295 |  |  | 		goto cleanup; | 
    
    | 3296 |  |  | 	addr->sadb_address_exttype = SADB_X_EXT_DST2; | 
    
    | 3297 |  |  | 	addr->sadb_address_len = len / PF_KEY_V2_CHUNK; | 
    
    | 3298 |  |  | 	addr->sadb_address_reserved = 0; | 
    
    | 3299 |  |  | 	memcpy(addr + 1, saddr, SA_LEN(saddr)); | 
    
    | 3300 |  |  | 	((struct sockaddr_in *) (addr + 1))->sin_port = 0; | 
    
    | 3301 |  |  | 	if (pf_key_v2_msg_add(grpspis, (struct sadb_ext *) addr, | 
    
    | 3302 |  |  | 	    PF_KEY_V2_NODE_MALLOCED) == -1) | 
    
    | 3303 |  |  | 		goto cleanup; | 
    
    | 3304 |  |  | 	addr = 0; | 
    
    | 3305 |  |  |  | 
    
    | 3306 |  |  | 	/* Setup the PROTOCOL extension.  */ | 
    
    | 3307 |  |  | 	protocol.sadb_protocol_exttype = SADB_X_EXT_PROTOCOL; | 
    
    | 3308 |  |  | 	protocol.sadb_protocol_len = sizeof protocol / PF_KEY_V2_CHUNK; | 
    
    | 3309 |  |  | 	switch (proto2->proto) { | 
    
    | 3310 |  |  | 	case IPSEC_PROTO_IPSEC_ESP: | 
    
    | 3311 |  |  | 		protocol.sadb_protocol_proto = SADB_SATYPE_ESP; | 
    
    | 3312 |  |  | 		break; | 
    
    | 3313 |  |  | 	case IPSEC_PROTO_IPSEC_AH: | 
    
    | 3314 |  |  | 		protocol.sadb_protocol_proto = SADB_SATYPE_AH; | 
    
    | 3315 |  |  | 		break; | 
    
    | 3316 |  |  | 	case IPSEC_PROTO_IPCOMP: | 
    
    | 3317 |  |  | 		protocol.sadb_protocol_proto = SADB_X_SATYPE_IPCOMP; | 
    
    | 3318 |  |  | 		break; | 
    
    | 3319 |  |  | 	default: | 
    
    | 3320 |  |  | 		log_print("pf_key_v2_group_spis: invalid proto %d", | 
    
    | 3321 |  |  | 		    proto2->proto); | 
    
    | 3322 |  |  | 		goto cleanup; | 
    
    | 3323 |  |  | 	} | 
    
    | 3324 |  |  | 	protocol.sadb_protocol_reserved2 = 0; | 
    
    | 3325 |  |  | 	if (pf_key_v2_msg_add(grpspis, | 
    
    | 3326 |  |  | 	    (struct sadb_ext *)&protocol, 0) == -1) | 
    
    | 3327 |  |  | 		goto cleanup; | 
    
    | 3328 |  |  |  | 
    
    | 3329 |  |  | 	ret = pf_key_v2_call(grpspis); | 
    
    | 3330 |  |  | 	pf_key_v2_msg_free(grpspis); | 
    
    | 3331 |  |  | 	grpspis = 0; | 
    
    | 3332 |  |  | 	if (!ret) | 
    
    | 3333 |  |  | 		goto cleanup; | 
    
    | 3334 |  |  | 	err = ((struct sadb_msg *)TAILQ_FIRST(ret)->seg)->sadb_msg_errno; | 
    
    | 3335 |  |  | 	if (err) { | 
    
    | 3336 |  |  | 		log_print("pf_key_v2_group_spis: GRPSPIS: %s", strerror(err)); | 
    
    | 3337 |  |  | 		goto cleanup; | 
    
    | 3338 |  |  | 	} | 
    
    | 3339 |  |  | 	pf_key_v2_msg_free(ret); | 
    
    | 3340 |  |  |  | 
    
    | 3341 |  |  | 	LOG_DBG((LOG_SYSDEP, 50, "pf_key_v2_group_spis: done")); | 
    
    | 3342 |  |  |  | 
    
    | 3343 |  |  | 	return 0; | 
    
    | 3344 |  |  |  | 
    
    | 3345 |  |  | cleanup: | 
    
    | 3346 |  |  | 	free(addr); | 
    
    | 3347 |  |  | 	if (grpspis) | 
    
    | 3348 |  |  | 		pf_key_v2_msg_free(grpspis); | 
    
    | 3349 |  |  | 	if (ret) | 
    
    | 3350 |  |  | 		pf_key_v2_msg_free(ret); | 
    
    | 3351 |  |  | 	return -1; | 
    
    | 3352 |  |  | } |