1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 *
26 * Copyright 2017 Jason King.
27 * Copyright (c) 2017, Joyent, Inc.
28 */
29
30 #include <sys/types.h>
31 #include <net/pfkeyv2.h>
32 #include <ipsec_util.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <locale.h>
36 #include <netdb.h>
37 #include <stdio.h>
38 #include <note.h>
39 #include <atomic.h>
40 #include <pthread.h>
41 #include <sys/stropts.h> /* For I_NREAD */
42 #include <libuutil.h>
43 #include <bunyan.h>
44
45 #include "defs.h"
46 #include "ikev2.h"
47 #include "ikev2_pkt.h"
48 #include "ikev2_sa.h"
49 #include "pkcs11.h"
50
51 struct pfreq;
52 typedef struct pfreq {
53 uu_list_node_t pr_node;
54 pfreq_cb_t *pr_cb;
55 void *pr_data;
56 uint32_t pr_msgid;
57 } pfreq_t;
58
59 static bunyan_logger_t *pflog;
60 static uu_list_pool_t *pfreq_pool;
61 static umem_cache_t *pfreq_cache;
62 static pthread_mutex_t pfreq_lock = PTHREAD_MUTEX_INITIALIZER;
63 static uu_list_t *pfreq_list;
64
65 /* PF_KEY socket. */
66 int pfkey;
67
68 /* our msgids */
69 static volatile uint32_t msgid = 0;
70
71 static int pfreq_ctor(void *, void *, int);
72 static pfreq_t *pfreq_new(pfreq_cb_t *, void *);
73 static void pfreq_free(pfreq_t *);
74
75 static void handle_reply(sadb_msg_t *);
76 static void handle_delete(sadb_msg_t *);
77 static void handle_flush(sadb_msg_t *);
78 static void handle_expire(sadb_msg_t *);
79 static void handle_acquire(sadb_msg_t *, boolean_t);
80 static void handle_register(sadb_msg_t *);
81
82 #if 0
83 static ikev2_pay_sa_t *convert_acquire(parsedmsg_t *);
84 static ikev2_pay_sa_t *convert_ext_acquire(parsedmsg_t *, ikev2_spi_proto_t);
85 static ikev2_xf_auth_t ikev2_pf_to_auth(int);
86 #endif
87
88 static const char *pfkey_opcodes[] = {
89 "RESERVED", "GETSPI", "UPDATE", "ADD", "DELETE", "GET",
90 "ACQUIRE", "REGISTER", "EXPIRE", "FLUSH", "DUMP", "X_PROMISC",
91 "X_INVERSE_ACQUIRE", "X_UPDATEPAIR", "X_DELPAIR"
92 };
93
94 static const char *
95 pfkey_type(unsigned int type)
96 {
97 if (type > SADB_MAX)
98 return ("ILLEGAL");
99 else
100 return (pfkey_opcodes[type]);
101 }
102
103 static const char *pfkey_satypes[] = {
104 "UNSPEC", "<undef>", "AH", "ESP", "<undef>", "RSVP", "OSPFV2",
105 "RIPV2", "MIP"
106 };
107
108 static const char *
109 pfkey_satype(unsigned int type)
110 {
111 if (type > SADB_SATYPE_MAX)
112 return ("ILLEGAL");
113 else
114 return (pfkey_satypes[type]);
115 }
116
117 /* Deal with algorithm name lookups */
118
119 static const char *
120 alg_to_string(int doi_number, const algindex_t *algindex)
121 {
122 int i;
123
124 for (i = 0; algindex[i].desc; i++)
125 if (doi_number == algindex[i].doi_num)
126 return (algindex[i].desc);
127 return ("unknown");
128 }
129
130 char *
131 kef_alg_to_string(int algnum, int protonum, char *algname)
132 {
133 struct ipsecalgent *testentry;
134 int error;
135
136 testentry = getipsecalgbynum(algnum, protonum, &error);
137 if (testentry == NULL || testentry->a_names[0] == NULL)
138 (void) snprintf(algname, 80, "unknown");
139 else
140 (void) snprintf(algname, 80, "%s", testentry->a_names[0]);
141
142 /* safe to use on a NULL pointer */
143 (void) freeipsecalgent(testentry);
144 return (algname);
145 }
146
147 /*
148 * The passed in parsedmsg_t looks like this (see defs.h):
149 *
150 * {
151 * *pmsg_next
152 * *pmsg_samsg
153 * *pmsg_exts[0][1][2][3].....[SADB_EXT_MAX + 2]
154 * *pmsg_sss (struct sockaddr_storage *)
155 * *pmsg_dss (struct sockaddr_storage *)
156 * *pmsg_isss (struct sockaddr_storage *)
157 * *pmsg_idss (struct sockaddr_storage *)
158 * *pmsg_nlss (struct sockaddr_storage *)
159 * *pmsg_nrss (struct sockaddr_storage *)
160 * } parsedmsg_t;
161 *
162 * This function parses through the whole samsg looking for valid PF_KEY
163 * extensions. Each extension type found is saved in the pmsg_exts array.
164 * As the parsedmsg_t is initialised as zero's when entering the function, it's
165 * easy to check later to see which extensions exist in the samsg by
166 * checking for NULL.
167 *
168 * Some extensions will have a sockaddr_storage associated with the type
169 * EG: SADB_EXT_ADDRESS_SRC, in these cases a pointer to the appropriate
170 * structure in samsg is set in the parsedmsg_t.
171 *
172 * After parsing the whole samsg, the optional arguments (which is a list
173 * of required extensions) are checked for in the parsedmsg_t. If all of the
174 * required extensions are valid then the function returns B_TRUE.
175 *
176 * Even if the required extensions are not in the samsg (and the function
177 * returns B_FALSE) the pmsg->pmsg_exts array will still contain the headers
178 * that were in the samsg.
179 *
180 * Assume the kernel knows what it's doing with messages that get passed up.
181 * The variable arguments are a list of ints with SADB_EXT_* values.
182 */
183 static boolean_t
184 extract_exts(sadb_msg_t *samsg, parsedmsg_t *pmsg, int numexts, ...)
185 {
186 sadb_ext_t *ext;
187 sadb_ext_t **exts = pmsg->pmsg_exts;
188 int current_ext;
189 va_list ap;
190 boolean_t rc = B_TRUE;
191
192 (void) memset(pmsg, 0, sizeof (parsedmsg_t));
193
194 ext = (sadb_ext_t *)(samsg + 1);
195 pmsg->pmsg_samsg = samsg;
196
197 do {
198 exts[ext->sadb_ext_type] = ext;
199 if (ext->sadb_ext_type == SADB_EXT_ADDRESS_SRC)
200 pmsg->pmsg_sss = (struct sockaddr_storage *)
201 (((sadb_address_t *)ext) + 1);
202 if (ext->sadb_ext_type == SADB_EXT_ADDRESS_DST)
203 pmsg->pmsg_dss = (struct sockaddr_storage *)
204 (((sadb_address_t *)ext) + 1);
205 if (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_SRC)
206 pmsg->pmsg_isss = (struct sockaddr_storage *)
207 (((sadb_address_t *)ext) + 1);
208 if (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_DST)
209 pmsg->pmsg_idss = (struct sockaddr_storage *)
210 (((sadb_address_t *)ext) + 1);
211 if (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_NATT_REM)
212 pmsg->pmsg_nrss = (struct sockaddr_storage *)
213 (((sadb_address_t *)ext) + 1);
214 if (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_NATT_LOC)
215 pmsg->pmsg_nlss = (struct sockaddr_storage *)
216 (((sadb_address_t *)ext) + 1);
217
218 ext = (sadb_ext_t *)(((uint64_t *)ext) + ext->sadb_ext_len);
219
220 } while (((uint8_t *)ext) - ((uint8_t *)samsg) <
221 SADB_64TO8(samsg->sadb_msg_len));
222
223 va_start(ap, numexts);
224 while (numexts-- > 0) {
225 current_ext = va_arg(ap, int);
226 if (exts[current_ext] == NULL) {
227 rc = B_FALSE;
228 break;
229 }
230 }
231 va_end(ap);
232
233 return (rc);
234 }
235
236 static void
237 pfkey_inbound(int s, void *arg)
238 {
239 _NOTE(ARGUNUSED(arg))
240
241 sadb_msg_t *samsg;
242 ssize_t rc;
243 int length;
244
245 if (ioctl(s, I_NREAD, &length) < 0) {
246 STDERR(error, log, "ioctl(I_NREAD) failed");
247
248 /* XXX KEBE ASKS - will we rapidly return at this point? */
249 schedule_socket(s, pfkey_inbound);
250 return;
251 }
252
253 if (length == 0) {
254 bunyan_info(log, "ioctl: zero length message",
255 BUNYAN_T_STRING, "func", __func__,
256 BUNYAN_T_STRING, "file", __FILE__,
257 BUNYAN_T_INT32, "line", __LINE__,
258 BUNYAN_T_END);
259 /* XXX KEBE ASKS - will we rapidly return at this point? */
260 schedule_socket(s, pfkey_inbound);
261 return;
262 }
263
264 samsg = malloc(length);
265 if (samsg == NULL) {
266 STDERR(error, log, "malloc failure");
267 schedule_socket(s, pfkey_inbound);
268 return;
269 }
270
271 rc = read(s, samsg, length);
272 if (rc <= 0) {
273 if (rc == -1) {
274 STDERR(error, log, "read failed");
275 /* Should I exit()? */
276 }
277 free(samsg);
278 /* XXX KEBE ASKS - will we rapidly return at this point? */
279 schedule_socket(s, pfkey_inbound);
280 return;
281 }
282
283 /* At this point, we can safely re-schedule the socket for reading. */
284 schedule_socket(s, pfkey_inbound);
285
286 bunyan_debug(log, "SADB message received",
287 BUNYAN_T_STRING, "msg_type", pfkey_type(samsg->sadb_msg_type),
288 BUNYAN_T_UINT32, "msg_type_val", (uint32_t)samsg->sadb_msg_type,
289 BUNYAN_T_STRING, "sa_type", pfkey_satype(samsg->sadb_msg_satype),
290 BUNYAN_T_UINT32, "sa_type_val", (uint32_t)samsg->sadb_msg_satype,
291 BUNYAN_T_UINT32, "msg_pid", samsg->sadb_msg_pid,
292 BUNYAN_T_UINT32, "msg_seq", samsg->sadb_msg_seq,
293 BUNYAN_T_UINT32, "msg_errno_val", (uint32_t)samsg->sadb_msg_errno,
294 BUNYAN_T_STRING, "msg_errno", strerror(samsg->sadb_msg_errno),
295 BUNYAN_T_UINT32, "msg_diagnostic_val",
296 (uint32_t)samsg->sadb_x_msg_diagnostic,
297 BUNYAN_T_UINT32, "msg_diagnostic",
298 keysock_diag(samsg->sadb_x_msg_diagnostic),
299 BUNYAN_T_UINT32, "length", (uint32_t)samsg->sadb_msg_len,
300 BUNYAN_T_END);
301
302 /*
303 * XXX KEBE SAYS for now don't print the full inbound message. An
304 * "ipseckey monitor" instance is useful here.
305 */
306
307 /*
308 * If it might be a reply to us, handle it.
309 */
310 if (samsg->sadb_msg_pid == getpid()) {
311 handle_reply(samsg);
312 return;
313 }
314
315 /*
316 * Silently pitch the message if it's an error reply to someone else.
317 */
318 if (samsg->sadb_msg_errno != 0) {
319 bunyan_debug(log, "reply not for us, dropped", BUNYAN_T_END);
320 free(samsg);
321 return;
322 }
323
324 /*
325 * At this point, we have a kernel-emitted message. Typically this
326 * will be an ACQUIRE, EXPIRE, or DELETE/DELPAIR. Other ones include
327 * FLUSH (which if we follow in.iked semantics, will nuke all IKE SA
328 * state) and REGISTER (indicating a change in kernel algorithm
329 * support).
330 */
331
332 switch (samsg->sadb_msg_type) {
333 case SADB_ACQUIRE:
334 handle_acquire(samsg, B_TRUE);
335 return;
336 case SADB_EXPIRE:
337 handle_expire(samsg);
338 return;
339 case SADB_DELETE:
340 case SADB_X_DELPAIR:
341 handle_delete(samsg);
342 return;
343 case SADB_FLUSH:
344 handle_flush(samsg);
345 return;
346 case SADB_REGISTER:
347 handle_register(samsg);
348 /*
349 * Explicitly free it here because handle_register() is also
350 * called from pf_key_init(), which has samsg on the stack
351 * instead.
352 */
353 free(samsg);
354 return;
355 }
356
357 bunyan_debug(log, "SADB message type unknown, ignored.",
358 BUNYAN_T_UINT32, "msg_type_val", (uint32_t)samsg->sadb_msg_type,
359 BUNYAN_T_END);
360 free(samsg);
361 }
362
363 /*
364 * Send a pfkey message 'msg'. The reply will invoke the callback
365 * function 'cb' with data as an argument.
366 * Returns B_TRUE if the request is successfully sent,
367 * B_FALSE if there was an error.
368 */
369 boolean_t
370 pfkey_send_msg(sadb_msg_t *msg, pfreq_cb_t *cb, void *data)
371 {
372 pfreq_t *req;
373 uu_list_index_t idx;
374 ssize_t n;
375
376 req = pfreq_new(cb, data);
377 if (req == NULL)
378 return (B_FALSE);
379
380 msg->sadb_msg_seq = req->pr_msgid;
381 msg->sadb_msg_pid = getpid();
382 n = write(pfkey, msg, msg->sadb_msg_len);
383 if (n != msg->sadb_msg_len) {
384 if (n < 0) {
385 STDERR(error, log, "pf_key write failed");
386 } else {
387 bunyan_error(log, "pf_key truncated write",
388 BUNYAN_T_UINT32, "n", (uint32_t)n,
389 BUNYAN_T_END);
390 }
391 pfreq_free(req);
392 return (B_FALSE);
393 }
394
395 (void) pthread_mutex_lock(&pfreq_lock);
396
397 (void) uu_list_find(pfreq_list, req, NULL, &idx);
398 uu_list_insert(pfreq_list, req, idx);
399 (void) pthread_mutex_unlock(&pfreq_lock);
400
401 return (B_TRUE);
402 }
403
404 /*
405 * Inform the kernel of an error.
406 * src is the pfkey message the error is a response to, reason is
407 * the reason for the error
408 */
409 void
410 pfkey_send_error(const sadb_msg_t *src, uint8_t reason)
411 {
412 sadb_msg_t msg = { 0 };
413 ssize_t n;
414
415 /* Errors consists of just the sadb header */
416 msg.sadb_msg_len = SADB_8TO64(sizeof (sadb_msg_t));
417 msg.sadb_msg_version = PF_KEY_V2;
418 msg.sadb_msg_type = src->sadb_msg_type;
419 msg.sadb_msg_errno = reason;
420 msg.sadb_msg_satype = src->sadb_msg_satype;
421 msg.sadb_x_msg_diagnostic = SADB_X_DIAGNOSTIC_NONE;
422 msg.sadb_msg_seq = src->sadb_msg_seq;
423 msg.sadb_msg_pid = src->sadb_msg_pid;
424
425 n = write(pfkey, &msg, sizeof (sadb_msg_t));
426 if (n != sizeof (sadb_msg_t))
427 STDERR(error, log, "Unable to send PFKEY error notification");
428 }
429
430 static void
431 handle_reply(sadb_msg_t *reply)
432 {
433 pfreq_t *req;
434 uu_list_index_t idx;
435
436 PTH(pthread_mutex_lock(&pfreq_lock));
437 req = uu_list_find(pfreq_list, NULL, reply, &idx);
438 if (req != NULL)
439 uu_list_remove(pfreq_list, req);
440 PTH(pthread_mutex_unlock(&pfreq_lock));
441
442 if (req == NULL) {
443 /* XXX: log more fields? */
444 bunyan_info(pflog, "Received a reply to an unknown request; "
445 "ignorning.",
446 BUNYAN_T_STRING, "msg_type",
447 pfkey_satype(reply->sadb_msg_type),
448 BUNYAN_T_UINT32, "msg_type_val",
449 (uint32_t)reply->sadb_msg_type,
450 BUNYAN_T_INT32, "pid", reply->sadb_msg_pid,
451 BUNYAN_T_UINT32, "seq", reply->sadb_msg_seq,
452 BUNYAN_T_END);
453 free(reply);
454 return;
455 }
456
457 #if 0
458 req->pr_cb(reply, req->pr_data);
459 pfreq_free(req);
460 #endif
461
462 switch (reply->sadb_msg_type) {
463 case SADB_ACQUIRE:
464 {
465 /* Should be a response to our inverse acquire */
466 parsedmsg_t pmsg = { 0 };
467
468 if (!extract_exts(reply, &pmsg, 1, SADB_X_EXT_EPROP)) {
469 bunyan_info(pflog, "No extended proposal found in "
470 "ACQUIRE reply.", BUNYAN_T_END);
471 free(reply);
472 return;
473 }
474
475 /*
476 * XXX: lookup what we queried based on msgid, extract
477 * SA type and pass to convert_ext_acquire
478 */
479
480 /* XXX: continue CHILD SA processing */
481 break;
482 }
483 default:
484 /* XXX: More to come */
485 ;
486 }
487
488 free(reply);
489 }
490
491 static void
492 handle_flush(sadb_msg_t *samsg)
493 {
494 bunyan_trace(pflog, "Handling SADB flush message", BUNYAN_T_END);
495
496 /* Return if just AH or ESP SAs are being freed. */
497 if (samsg->sadb_msg_satype != SADB_SATYPE_UNSPEC)
498 return;
499
500 /* XXX KEBE SAYS FILL ME IN! */
501
502 ikev2_sa_flush();
503
504 /*
505 * If we receive an SADB_FLUSH for all SA types, get rid of any IKE
506 * SAs.
507 */
508
509 free(samsg);
510 }
511
512 /*
513 * Handle the PF_KEY SADB_EXPIRE message for idle timeout.
514 *
515 * XXX KEBE SAYS this'll most likely kick off Dead Peer Detection if we can
516 * find an IKE SA.
517 */
518 static void
519 handle_idle_timeout(sadb_msg_t *samsg)
520 {
521 bunyan_trace(pflog, "Handling SADB idle expire message", BUNYAN_T_END);
522
523 /* XXX KEBE SAYS FILL ME IN! */
524 free(samsg);
525 }
526
527 static void
528 handle_expire(sadb_msg_t *samsg)
529 {
530 parsedmsg_t pmsg;
531
532 /*
533 * If SOFT expire, see if the SADB_X_SAFLAGS_KM1 (initiator) is set,
534 * if so, consider treating this expire as an ACQUIRE message.
535 *
536 * If HARD expire, treat this message like a DELETE.
537 *
538 * If IDLE expire, see if we need to do a little DPD or not.
539 */
540
541 if (extract_exts(samsg, &pmsg, 1, SADB_EXT_LIFETIME_HARD)) {
542 bunyan_debug(pflog, "Handling SADB hard expire message",
543 BUNYAN_T_END);
544 handle_delete(samsg);
545 return;
546 }
547
548 if (pmsg.pmsg_exts[SADB_X_EXT_LIFETIME_IDLE] != NULL) {
549 handle_idle_timeout(samsg);
550 return;
551 }
552
553 /*
554 * extract_exts() has already filled in pmsg with data from
555 * samsg. pmsg.pmsg_exts[foo] will be NULL if this was
556 * not set in samsg. Bail out if the message appears to be
557 * poorly formed. If everything looks good, create a new
558 * "ACQUIRE like" message and pass off to handle_acquire().
559 */
560
561 if (pmsg.pmsg_exts[SADB_EXT_LIFETIME_SOFT] == NULL) {
562 /* XXX: more fields */
563 bunyan_info(pflog, "SADB EXPIRE message is missing both "
564 "hard and soft lifetimes", BUNYAN_T_END);
565 /* XXX: ignore? */
566 }
567
568 bunyan_debug(pflog, "Handling SADB soft expire message", BUNYAN_T_END);
569 /* XXX KEBE SAYS FILL ME IN! */
570
571 free(samsg);
572 }
573
574 static void
575 handle_register(sadb_msg_t *samsg)
576 {
577 _NOTE(ARGUNUSED(samsg))
578 /* XXX KEBE SAYS FILL ME IN! */
579
580 /*
581 * XXX KEBE wonders if this is as necessary as 2367 first imagined?
582 *
583 * With inverse-ACQUIRE, you know better what algorithms are available
584 * and acceptable. This may go away or remain a mere stub.
585 */
586 }
587
588 static void
589 handle_delete(sadb_msg_t *samsg)
590 {
591 bunyan_trace(pflog, "Handling SADB delete", BUNYAN_T_END);
592
593 /* XXX KEBE SAYS FILL ME IN! */
594 free(samsg);
595 }
596
597 /*
598 * Handle a PF_KEY ACQUIRE message. This function, or something that it
599 * calls (either directly or via callbacks) must free samsg.
600 */
601 /* XXX KEBE wonders if create_child_sa will be needed here or not. */
602 static void
603 handle_acquire(sadb_msg_t *samsg, boolean_t create_child_sa)
604 {
605 /* XXX: for now */
606 _NOTE(ARGUNUSED(create_child_sa))
607
608 parsedmsg_t pmsg;
609
610 bunyan_debug(pflog, "Handling SADB acquire", BUNYAN_T_END);
611
612 if (!extract_exts(samsg, &pmsg, 1, SADB_EXT_PROPOSAL)) {
613 bunyan_info(pflog, "No proposal found in ACQUIRE message",
614 BUNYAN_T_END);
615 free(samsg);
616 return;
617 }
618
619 /* XXX KEBE SAYS FILL ME IN! */
620 free(samsg);
621 }
622
623 static int
624 pfreq_compare(const void *l_arg, const void *r_arg, void *msg_arg)
625 {
626 const pfreq_t *l = l_arg;
627 const pfreq_t *r = r_arg;
628 sadb_msg_t *msg = msg_arg;
629 uint32_t msgid;
630
631 ASSERT((r != NULL && msg == NULL) || (r == NULL && msg != NULL));
632
633 if (r != NULL)
634 msgid = r->pr_msgid;
635 else
636 msgid = msg->sadb_msg_seq;
637
638 if (l->pr_msgid < msgid)
639 return (-1);
640 if (l->pr_msgid > msgid)
641 return (1);
642 if (r == NULL)
643 return (0);
644
645 if (l->pr_data < r->pr_data)
646 return (-1);
647 if (l->pr_data > r->pr_data)
648 return (1);
649 return (0);
650 }
651
652 static int
653 pfreq_ctor(void *buf, void *ignore, int flags)
654 {
655 _NOTE(ARGUNUSED(ignore, flags))
656 (void) memset(buf, 0, sizeof (pfreq_t));
657 return (0);
658 }
659
660 static pfreq_t *
661 pfreq_new(pfreq_cb_t *cb, void *data)
662 {
663 pfreq_t *req = umem_cache_alloc(pfreq_cache, UMEM_DEFAULT);
664
665 if (req == NULL)
666 return (NULL);
667
668 req->pr_msgid = atomic_inc_32_nv(&msgid);
669 req->pr_cb = cb;
670 req->pr_data = data;
671 return (req);
672 }
673
674 static void
675 pfreq_free(pfreq_t *req)
676 {
677 (void) pfreq_ctor(req, NULL, 0);
678 umem_cache_free(pfreq_cache, req);
679 }
680
681 static void
682 pfkey_register(uint8_t satype)
683 {
684 uint64_t buffer[128] = { 0 };
685 sadb_msg_t *samsg = (sadb_msg_t *)buffer;
686 ssize_t n;
687 uint32_t msgid = atomic_inc_32_nv(&msgid);
688 pid_t pid = getpid();
689
690 CTASSERT(sizeof (buffer) >= sizeof (*samsg));
691
692 samsg->sadb_msg_version = PF_KEY_V2;
693 samsg->sadb_msg_type = SADB_REGISTER;
694 samsg->sadb_msg_errno = 0;
695 samsg->sadb_msg_satype = satype;
696 samsg->sadb_msg_reserved = 0;
697 samsg->sadb_msg_seq = msgid;
698 samsg->sadb_msg_pid = pid;
699 samsg->sadb_msg_len = SADB_8TO64(sizeof (*samsg));
700
701 n = write(pfkey, buffer, sizeof (*samsg));
702 if (n < 0)
703 err(EXIT_FAILURE, "pf_key write error");
704 if (n < sizeof (*samsg))
705 errx(EXIT_FAILURE, "Unable to write pf_key register message");
706
707 do {
708 (void) memset(buffer, 0, sizeof (buffer));
709 n = read(pfkey, buffer, sizeof (buffer));
710 if (n < 0)
711 err(EXIT_FAILURE, "pf_key read failure");
712 } while (samsg->sadb_msg_seq != msgid ||
713 samsg->sadb_msg_pid != pid ||
714 samsg->sadb_msg_type != SADB_REGISTER);
715
716 if (samsg->sadb_msg_errno != 0) {
717 if (samsg->sadb_msg_errno != EPROTONOSUPPORT)
718 errx(EXIT_FAILURE, "pf_key register returned %s (%d).",
719 strerror(samsg->sadb_msg_errno),
720 samsg->sadb_msg_errno);
721 bunyan_error(pflog, "Protocol not supported",
722 BUNYAN_T_UINT32, "msg_satype",
723 (uint32_t)samsg->sadb_msg_satype, BUNYAN_T_END);
724 }
725
726 bunyan_debug(pflog, "Initial REGISTER with SADB",
727 BUNYAN_T_STRING, "satype", pfkey_satype(samsg->sadb_msg_satype),
728 BUNYAN_T_END);
729
730 handle_register(samsg);
731 }
732
733 void
734 pfkey_init(void)
735 {
736 uint32_t flag = 0;
737 int rc;
738
739 #ifdef DEBUG
740 flag |= UU_LIST_POOL_DEBUG;
741 #endif
742
743 pfreq_pool = uu_list_pool_create("pfreq_list", sizeof (pfreq_t),
744 offsetof(pfreq_t, pr_node), pfreq_compare, flag);
745 if (pfreq_pool == NULL)
746 errx(EXIT_FAILURE, "Unable to create pfreq list pool: %s",
747 uu_strerror(uu_error()));
748
749 pfreq_cache = umem_cache_create("pfreq cache", sizeof (pfreq_t),
750 sizeof (uint64_t), pfreq_ctor, NULL, NULL, NULL, NULL, 0);
751 if (pfreq_cache == NULL)
752 err(EXIT_FAILURE, "Unable to create pfreq cache");
753
754 pfkey = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
755 if (pfkey == -1)
756 err(EXIT_FAILURE, "Unable to create pf_key socket");
757
758 rc = bunyan_child(log, &pflog,
759 BUNYAN_T_INT32, "socketfd", (int32_t)pfkey,
760 BUNYAN_T_END);
761 if (rc != 0)
762 errx(EXIT_FAILURE, "Unable to create child logger: %s",
763 strerror(rc));
764
765 pfkey_register(SADB_SATYPE_ESP);
766 pfkey_register(SADB_SATYPE_AH);
767
768 schedule_socket(pfkey, pfkey_inbound);
769 }