dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / krb5 / kdb / kdb_log.c
blobfcd32c8d04d53859bcb6f812a14e40742570688a
1 /*
2 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
6 #include <sys/stat.h>
7 #include <sys/types.h>
8 #include <unistd.h>
9 #include <fcntl.h>
10 #include <sys/mman.h>
11 #include <k5-int.h>
12 #include <stdlib.h>
13 #include <limits.h>
14 #include <syslog.h>
15 #include "kdb_log.h"
18 * This modules includes all the necessary functions that create and
19 * modify the Kerberos principal update and header logs.
22 #define getpagesize() sysconf(_SC_PAGESIZE)
24 static int pagesize = 0;
26 #define INIT_ULOG(ctx) log_ctx = ctx->kdblog_context; \
27 ulog = log_ctx->ulog
29 * Sync update entry to disk.
31 krb5_error_code
32 ulog_sync_update(kdb_hlog_t *ulog, kdb_ent_header_t *upd)
34 ulong_t start, end, size;
35 krb5_error_code retval;
37 if (ulog == NULL)
38 return (KRB5_LOG_ERROR);
40 if (!pagesize)
41 pagesize = getpagesize();
43 start = ((ulong_t)upd) & (~(pagesize-1));
45 end = (((ulong_t)upd) + ulog->kdb_block +
46 (pagesize-1)) & (~(pagesize-1));
48 size = end - start;
49 if (retval = msync((caddr_t)start, size, MS_SYNC)) {
50 return (retval);
53 return (0);
57 * Sync memory to disk for the update log header.
59 void
60 ulog_sync_header(kdb_hlog_t *ulog)
63 if (!pagesize)
64 pagesize = getpagesize();
66 if (msync((caddr_t)ulog, pagesize, MS_SYNC)) {
68 * Couldn't sync to disk, let's panic
70 syslog(LOG_ERR, "ulog_sync_header: could not sync to disk");
71 abort();
76 * Resizes the array elements. We reinitialize the update log rather than
77 * unrolling the the log and copying it over to a temporary log for obvious
78 * performance reasons. Slaves will subsequently do a full resync, but
79 * the need for resizing should be very small.
81 krb5_error_code
82 ulog_resize(kdb_hlog_t *ulog, uint32_t ulogentries, int ulogfd, uint_t recsize)
84 uint_t new_block, new_size;
86 if (ulog == NULL)
87 return (KRB5_LOG_ERROR);
89 new_size = sizeof (kdb_hlog_t);
91 new_block = (recsize / ULOG_BLOCK) + 1;
92 new_block *= ULOG_BLOCK;
94 new_size += ulogentries * new_block;
96 if (new_size <= MAXLOGLEN) {
98 * Reinit log with new block size
100 (void) memset(ulog, 0, sizeof (kdb_hlog_t));
102 ulog->kdb_hmagic = KDB_HMAGIC;
103 ulog->db_version_num = KDB_VERSION;
104 ulog->kdb_state = KDB_STABLE;
105 ulog->kdb_block = new_block;
107 ulog_sync_header(ulog);
110 * Time to expand log considering new block size
112 if (lseek(ulogfd, new_size, SEEK_SET) == -1) {
113 return (errno);
116 if (write(ulogfd, "+", 1) != 1) {
117 return (errno);
119 } else {
121 * Can't map into file larger than MAXLOGLEN
123 return (KRB5_LOG_ERROR);
126 return (0);
130 * Adds an entry to the update log.
131 * The layout of the update log looks like:
133 * header log -> [ update header -> xdr(kdb_incr_update_t) ], ...
135 krb5_error_code
136 ulog_add_update(krb5_context context, kdb_incr_update_t *upd)
138 XDR xdrs;
139 kdbe_time_t ktime;
140 struct timeval timestamp;
141 kdb_ent_header_t *indx_log;
142 uint_t i, recsize;
143 ulong_t upd_size;
144 krb5_error_code retval;
145 kdb_sno_t cur_sno;
146 kdb_log_context *log_ctx;
147 kdb_hlog_t *ulog = NULL;
148 uint32_t ulogentries;
149 int ulogfd;
151 INIT_ULOG(context);
152 ulogentries = log_ctx->ulogentries;
153 ulogfd = log_ctx->ulogfd;
155 if (upd == NULL)
156 return (KRB5_LOG_ERROR);
158 (void) gettimeofday(&timestamp, NULL);
159 ktime.seconds = timestamp.tv_sec;
160 ktime.useconds = timestamp.tv_usec;
162 upd_size = xdr_sizeof((xdrproc_t)xdr_kdb_incr_update_t, upd);
164 recsize = sizeof (kdb_ent_header_t) + upd_size;
166 if (recsize > ulog->kdb_block) {
167 if (retval = ulog_resize(ulog, ulogentries, ulogfd, recsize)) {
168 /* Resize element array failed */
169 return (retval);
173 cur_sno = ulog->kdb_last_sno;
176 * We need to overflow our sno, replicas will do full
177 * resyncs once they see their sno > than the masters.
179 if (cur_sno == ULONG_MAX)
180 cur_sno = 1;
181 else
182 cur_sno++;
185 * We squirrel this away for finish_update() to index
187 upd->kdb_entry_sno = cur_sno;
189 i = (cur_sno - 1) % ulogentries;
191 indx_log = (kdb_ent_header_t *)INDEX(ulog, i);
193 (void) memset(indx_log, 0, ulog->kdb_block);
195 indx_log->kdb_umagic = KDB_UMAGIC;
196 indx_log->kdb_entry_size = upd_size;
197 indx_log->kdb_entry_sno = cur_sno;
198 indx_log->kdb_time = upd->kdb_time = ktime;
199 indx_log->kdb_commit = upd->kdb_commit = FALSE;
201 ulog->kdb_state = KDB_UNSTABLE;
203 xdrmem_create(&xdrs, (char *)indx_log->entry_data,
204 indx_log->kdb_entry_size, XDR_ENCODE);
205 if (!xdr_kdb_incr_update_t(&xdrs, upd))
206 return (KRB5_LOG_CONV);
208 if (retval = ulog_sync_update(ulog, indx_log))
209 return (retval);
211 if (ulog->kdb_num < ulogentries)
212 ulog->kdb_num++;
214 ulog->kdb_last_sno = cur_sno;
215 ulog->kdb_last_time = ktime;
218 * Since this is a circular array, once we circled, kdb_first_sno is
219 * always kdb_entry_sno + 1.
221 if (cur_sno > ulogentries) {
222 i = upd->kdb_entry_sno % ulogentries;
223 indx_log = (kdb_ent_header_t *)INDEX(ulog, i);
224 ulog->kdb_first_sno = indx_log->kdb_entry_sno;
225 ulog->kdb_first_time = indx_log->kdb_time;
226 } else if (cur_sno == 1) {
227 ulog->kdb_first_sno = 1;
228 ulog->kdb_first_time = indx_log->kdb_time;
231 ulog_sync_header(ulog);
233 return (0);
237 * Mark the log entry as committed and sync the memory mapped log
238 * to file.
240 krb5_error_code
241 ulog_finish_update(krb5_context context, kdb_incr_update_t *upd)
243 krb5_error_code retval;
244 kdb_ent_header_t *indx_log;
245 uint_t i;
246 kdb_log_context *log_ctx;
247 kdb_hlog_t *ulog = NULL;
248 uint32_t ulogentries;
250 INIT_ULOG(context);
251 ulogentries = log_ctx->ulogentries;
253 i = (upd->kdb_entry_sno - 1) % ulogentries;
255 indx_log = (kdb_ent_header_t *)INDEX(ulog, i);
257 indx_log->kdb_commit = TRUE;
259 ulog->kdb_state = KDB_STABLE;
261 if (retval = ulog_sync_update(ulog, indx_log))
262 return (retval);
264 ulog_sync_header(ulog);
266 return (0);
270 * Set the header log details on the slave and sync it to file.
272 void
273 ulog_finish_update_slave(kdb_hlog_t *ulog, kdb_last_t lastentry)
276 ulog->kdb_last_sno = lastentry.last_sno;
277 ulog->kdb_last_time = lastentry.last_time;
279 ulog_sync_header(ulog);
283 * Delete an entry to the update log.
285 krb5_error_code
286 ulog_delete_update(krb5_context context, kdb_incr_update_t *upd)
289 upd->kdb_deleted = TRUE;
291 return (ulog_add_update(context, upd));
295 * Used by the slave or master (during ulog_check) to update it's hash db from
296 * the incr update log.
298 krb5_error_code
299 ulog_replay(krb5_context context, kdb_incr_result_t *incr_ret)
301 krb5_db_entry *entry = NULL;
302 kdb_incr_update_t *upd = NULL, *fupd;
303 int i, no_of_updates;
304 krb5_error_code retval;
305 krb5_principal dbprinc = NULL;
306 kdb_last_t errlast;
307 char *dbprincstr = NULL;
308 kdb_log_context *log_ctx;
309 kdb_hlog_t *ulog = NULL;
310 bool_t fini = FALSE;
312 INIT_ULOG(context);
314 no_of_updates = incr_ret->updates.kdb_ulog_t_len;
315 upd = incr_ret->updates.kdb_ulog_t_val;
316 fupd = upd;
319 * We reset last_sno and last_time to 0, if krb5_db_put_principal
320 * or krb5_db_delete_principal fail.
322 errlast.last_sno = (unsigned int)0;
323 errlast.last_time.seconds = (unsigned int)0;
324 errlast.last_time.useconds = (unsigned int)0;
326 if (krb5_db_inited(context)) {
327 retval = krb5_db_open(context, NULL,
328 KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN);
329 if (retval != 0)
330 goto cleanup;
331 fini = TRUE;
334 for (i = 0; i < no_of_updates; i++) {
335 int nentry = 1;
337 if (!upd->kdb_commit)
338 continue;
340 if (upd->kdb_deleted) {
341 dbprincstr = malloc((upd->kdb_princ_name.utf8str_t_len
342 + 1) * sizeof (char));
344 if (dbprincstr == NULL) {
345 retval = ENOMEM;
346 goto cleanup;
349 (void) strlcpy(dbprincstr,
350 (char *)upd->kdb_princ_name.utf8str_t_val,
351 (upd->kdb_princ_name.utf8str_t_len + 1));
353 if (retval = krb5_parse_name(context, dbprincstr,
354 &dbprinc)) {
355 goto cleanup;
358 free(dbprincstr);
360 retval = krb5_db_delete_principal(context,
361 dbprinc, &nentry);
363 if (dbprinc)
364 krb5_free_principal(context, dbprinc);
366 if (retval)
367 goto cleanup;
368 } else {
369 entry = (krb5_db_entry *)malloc(sizeof (krb5_db_entry));
371 if (!entry) {
372 retval = errno;
373 goto cleanup;
376 (void) memset(entry, 0, sizeof (krb5_db_entry));
378 if (retval = ulog_conv_2dbentry(context, entry, upd, 1))
379 goto cleanup;
381 retval = krb5_db_put_principal(context, entry,
382 &nentry);
384 if (entry) {
385 krb5_db_free_principal(context, entry, nentry);
386 free(entry);
387 entry = NULL;
389 if (retval)
390 goto cleanup;
393 upd++;
396 cleanup:
397 if (fupd)
398 ulog_free_entries(fupd, no_of_updates);
400 if (log_ctx && (log_ctx->iproprole == IPROP_SLAVE)) {
401 if (retval)
402 ulog_finish_update_slave(ulog, errlast);
403 else
404 ulog_finish_update_slave(ulog, incr_ret->lastentry);
407 if (fini == TRUE)
408 krb5_db_fini(context);
410 return (retval);
414 * Validate the log file and resync any uncommitted update entries
415 * to the principal database.
417 krb5_error_code
418 ulog_check(krb5_context context, kdb_hlog_t *ulog)
420 XDR xdrs;
421 krb5_error_code retval = 0;
422 int i;
423 kdb_ent_header_t *indx_log;
424 kdb_incr_update_t *upd = NULL;
425 kdb_incr_result_t *incr_ret = NULL;
427 ulog->kdb_state = KDB_STABLE;
429 for (i = 0; i < ulog->kdb_num; i++) {
430 indx_log = (kdb_ent_header_t *)INDEX(ulog, i);
432 if (indx_log->kdb_umagic != KDB_UMAGIC) {
434 * Update entry corrupted we should scream and die
436 ulog->kdb_state = KDB_CORRUPT;
437 retval = KRB5_LOG_CORRUPT;
438 break;
441 if (indx_log->kdb_commit == FALSE) {
442 ulog->kdb_state = KDB_UNSTABLE;
444 incr_ret = (kdb_incr_result_t *)
445 malloc(sizeof (kdb_incr_result_t));
446 if (incr_ret == NULL) {
447 retval = errno;
448 goto error;
451 upd = (kdb_incr_update_t *)
452 malloc(sizeof (kdb_incr_update_t));
453 if (upd == NULL) {
454 retval = errno;
455 goto error;
458 (void) memset(upd, 0, sizeof (kdb_incr_update_t));
459 xdrmem_create(&xdrs, (char *)indx_log->entry_data,
460 indx_log->kdb_entry_size, XDR_DECODE);
461 if (!xdr_kdb_incr_update_t(&xdrs, upd)) {
462 retval = KRB5_LOG_CONV;
463 goto error;
466 incr_ret->updates.kdb_ulog_t_len = 1;
467 incr_ret->updates.kdb_ulog_t_val = upd;
469 upd->kdb_commit = TRUE;
472 * We don't want to readd this update and just use the
473 * existing update to be propagated later on
475 ulog_set_role(context, IPROP_NULL);
476 retval = ulog_replay(context, incr_ret);
479 * upd was freed by ulog_replay, we NULL
480 * the pointer in case we subsequently break from loop.
482 upd = NULL;
483 if (incr_ret) {
484 free(incr_ret);
485 incr_ret = NULL;
487 ulog_set_role(context, IPROP_MASTER);
489 if (retval)
490 goto error;
493 * We flag this as committed since this was
494 * the last entry before kadmind crashed, ergo
495 * the slaves have not seen this update before
497 indx_log->kdb_commit = TRUE;
498 retval = ulog_sync_update(ulog, indx_log);
499 if (retval)
500 goto error;
502 ulog->kdb_state = KDB_STABLE;
506 error:
507 if (upd)
508 ulog_free_entries(upd, 1);
510 free(incr_ret);
512 ulog_sync_header(ulog);
514 return (retval);
518 * Map the log file to memory for performance and simplicity.
520 * Called by: if iprop_enabled then ulog_map();
521 * Assumes that the caller will terminate on ulog_map, hence munmap and
522 * closing of the fd are implicitly performed by the caller.
523 * Returns 0 on success else failure.
525 krb5_error_code
526 ulog_map(krb5_context context, kadm5_config_params *params, int caller)
528 struct stat st;
529 krb5_error_code retval;
530 uint32_t ulog_filesize;
531 char logname[MAX_FILENAME];
532 kdb_log_context *log_ctx;
533 kdb_hlog_t *ulog = NULL;
534 uint32_t ulogentries;
535 int ulogfd = -1;
537 if ((caller == FKADMIND) || (caller == FKCOMMAND))
538 ulogentries = params->iprop_ulogsize;
540 ulog_filesize = sizeof (kdb_hlog_t);
542 if (strlcpy(logname, params->dbname, MAX_FILENAME) >= MAX_FILENAME)
543 return (KRB5_LOG_ERROR);
544 if (strlcat(logname, ".ulog", MAX_FILENAME) >= MAX_FILENAME)
545 return (KRB5_LOG_ERROR);
547 if (stat(logname, &st) == -1) {
549 if (caller == FKPROPLOG) {
551 * File doesn't exist so we exit with kproplog
553 return (errno);
556 if ((ulogfd = open(logname, O_RDWR+O_CREAT, 0600)) == -1) {
557 return (errno);
560 if (lseek(ulogfd, 0L, SEEK_CUR) == -1) {
561 return (errno);
564 if ((caller == FKADMIND) || (caller == FKCOMMAND))
565 ulog_filesize += ulogentries * ULOG_BLOCK;
567 if (lseek(ulogfd, ulog_filesize, SEEK_SET) == -1) {
568 return (errno);
571 if (write(ulogfd, "+", 1) != 1) {
572 return (errno);
575 } else {
577 if ((ulogfd = open(logname, O_RDWR, 0600)) == -1) {
579 * Can't open existing log file
581 return (errno);
585 if (caller == FKPROPLOG) {
586 fstat(ulogfd, &st);
587 ulog_filesize = st.st_size;
589 ulog = mmap(NULL, ulog_filesize,
590 PROT_READ+PROT_WRITE, MAP_PRIVATE, ulogfd, 0);
591 } else {
593 * else kadmind, kpropd, & kcommands should udpate stores
595 ulog = mmap(NULL, MAXLOGLEN,
596 PROT_READ+PROT_WRITE, MAP_SHARED, ulogfd, 0);
599 if ((int)(ulog) == -1) {
601 * Can't map update log file to memory
603 return (errno);
606 if (!context->kdblog_context) {
607 if (!(log_ctx = malloc(sizeof (kdb_log_context))))
608 return (errno);
609 context->kdblog_context = (void *)log_ctx;
610 } else
611 log_ctx = context->kdblog_context;
612 log_ctx->ulog = ulog;
613 log_ctx->ulogentries = ulogentries;
614 log_ctx->ulogfd = ulogfd;
616 if (ulog->kdb_hmagic != KDB_HMAGIC) {
617 if (ulog->kdb_hmagic == 0) {
619 * New update log
621 (void) memset(ulog, 0, sizeof (kdb_hlog_t));
623 ulog->kdb_hmagic = KDB_HMAGIC;
624 ulog->db_version_num = KDB_VERSION;
625 ulog->kdb_state = KDB_STABLE;
626 ulog->kdb_block = ULOG_BLOCK;
627 if (!(caller == FKPROPLOG))
628 ulog_sync_header(ulog);
629 } else {
630 return (KRB5_LOG_CORRUPT);
634 if (caller == FKADMIND) {
635 switch (ulog->kdb_state) {
636 case KDB_STABLE:
637 case KDB_UNSTABLE:
639 * Log is currently un/stable, check anyway
641 retval = ulog_check(context, ulog);
642 if (retval == KRB5_LOG_CORRUPT) {
643 return (retval);
645 break;
646 case KDB_CORRUPT:
647 return (KRB5_LOG_CORRUPT);
648 default:
650 * Invalid db state
652 return (KRB5_LOG_ERROR);
654 } else if ((caller == FKPROPLOG) || (caller == FKPROPD)) {
656 * kproplog and kpropd don't need to do anything else
658 return (0);
662 * Reinit ulog if the log is being truncated or expanded after
663 * we have circled.
665 if (ulog->kdb_num != ulogentries) {
666 if ((ulog->kdb_num != 0) &&
667 ((ulog->kdb_last_sno > ulog->kdb_num) ||
668 (ulog->kdb_num > ulogentries))) {
669 (void) memset(ulog, 0, sizeof (kdb_hlog_t));
671 ulog->kdb_hmagic = KDB_HMAGIC;
672 ulog->db_version_num = KDB_VERSION;
673 ulog->kdb_state = KDB_STABLE;
674 ulog->kdb_block = ULOG_BLOCK;
676 ulog_sync_header(ulog);
680 * Expand ulog if we have specified a greater size
682 if (ulog->kdb_num < ulogentries) {
683 ulog_filesize += ulogentries * ulog->kdb_block;
685 if (lseek(ulogfd, ulog_filesize, SEEK_SET) == -1) {
686 return (errno);
689 if (write(ulogfd, "+", 1) != 1) {
690 return (errno);
695 return (0);
699 * Get the last set of updates seen, (last+1) to n is returned.
701 krb5_error_code
702 ulog_get_entries(
703 krb5_context context, /* input - krb5 lib config */
704 kdb_last_t last, /* input - slave's last sno */
705 kdb_incr_result_t *ulog_handle) /* output - incr result for slave */
707 XDR xdrs;
708 kdb_ent_header_t *indx_log;
709 kdb_incr_update_t *upd;
710 uint_t indx, count, tdiff;
711 uint32_t sno;
712 krb5_error_code retval;
713 struct timeval timestamp;
714 kdb_log_context *log_ctx;
715 kdb_hlog_t *ulog = NULL;
716 uint32_t ulogentries;
718 INIT_ULOG(context);
719 ulogentries = log_ctx->ulogentries;
722 * Check to make sure we don't have a corrupt ulog first.
724 if (ulog->kdb_state == KDB_CORRUPT) {
725 ulog_handle->ret = UPDATE_ERROR;
726 return (KRB5_LOG_CORRUPT);
729 gettimeofday(&timestamp, NULL);
731 tdiff = timestamp.tv_sec - ulog->kdb_last_time.seconds;
732 if (tdiff <= ULOG_IDLE_TIME) {
733 ulog_handle->ret = UPDATE_BUSY;
734 return (0);
738 * We need to lock out other processes here, such as kadmin.local,
739 * since we are looking at the last_sno and looking up updates. So
740 * we can share with other readers.
742 retval = krb5_db_lock(context, KRB5_LOCKMODE_SHARED);
743 if (retval)
744 return (retval);
747 * We may have overflowed the update log or we shrunk the log, or
748 * the client's ulog has just been created.
750 if ((last.last_sno > ulog->kdb_last_sno) ||
751 (last.last_sno < ulog->kdb_first_sno) ||
752 (last.last_sno == 0)) {
753 ulog_handle->lastentry.last_sno = ulog->kdb_last_sno;
754 (void) krb5_db_unlock(context);
755 ulog_handle->ret = UPDATE_FULL_RESYNC_NEEDED;
756 return (0);
757 } else if (last.last_sno <= ulog->kdb_last_sno) {
758 sno = last.last_sno;
760 indx = (sno - 1) % ulogentries;
762 indx_log = (kdb_ent_header_t *)INDEX(ulog, indx);
765 * Validate the time stamp just to make sure it was the same sno
767 if ((indx_log->kdb_time.seconds == last.last_time.seconds) &&
768 (indx_log->kdb_time.useconds == last.last_time.useconds)) {
771 * If we have the same sno we return success
773 if (last.last_sno == ulog->kdb_last_sno) {
774 (void) krb5_db_unlock(context);
775 ulog_handle->ret = UPDATE_NIL;
776 return (0);
779 count = ulog->kdb_last_sno - sno;
781 ulog_handle->updates.kdb_ulog_t_val =
782 (kdb_incr_update_t *)malloc(
783 sizeof (kdb_incr_update_t) * count);
785 upd = ulog_handle->updates.kdb_ulog_t_val;
787 if (upd == NULL) {
788 (void) krb5_db_unlock(context);
789 ulog_handle->ret = UPDATE_ERROR;
790 return (errno);
793 while (sno < ulog->kdb_last_sno) {
794 indx = sno % ulogentries;
796 indx_log = (kdb_ent_header_t *)
797 INDEX(ulog, indx);
799 (void) memset(upd, 0,
800 sizeof (kdb_incr_update_t));
801 xdrmem_create(&xdrs,
802 (char *)indx_log->entry_data,
803 indx_log->kdb_entry_size, XDR_DECODE);
804 if (!xdr_kdb_incr_update_t(&xdrs, upd)) {
805 (void) krb5_db_unlock(context);
806 ulog_handle->ret = UPDATE_ERROR;
807 return (KRB5_LOG_CONV);
810 * Mark commitment since we didn't
811 * want to decode and encode the
812 * incr update record the first time.
814 upd->kdb_commit = indx_log->kdb_commit;
816 upd++;
817 sno++;
818 } /* while */
820 ulog_handle->updates.kdb_ulog_t_len = count;
822 ulog_handle->lastentry.last_sno = ulog->kdb_last_sno;
823 ulog_handle->lastentry.last_time.seconds =
824 ulog->kdb_last_time.seconds;
825 ulog_handle->lastentry.last_time.useconds =
826 ulog->kdb_last_time.useconds;
827 ulog_handle->ret = UPDATE_OK;
829 (void) krb5_db_unlock(context);
831 return (0);
832 } else {
834 * We have time stamp mismatch or we no longer have
835 * the slave's last sno, so we brute force it
837 (void) krb5_db_unlock(context);
838 ulog_handle->ret = UPDATE_FULL_RESYNC_NEEDED;
840 return (0);
845 * Should never get here, return error
847 ulog_handle->ret = UPDATE_ERROR;
848 return (KRB5_LOG_ERROR);
851 krb5_error_code
852 ulog_set_role(krb5_context ctx, iprop_role role)
854 kdb_log_context *log_ctx;
856 if (!ctx->kdblog_context) {
857 if (!(log_ctx = malloc(sizeof (kdb_log_context))))
858 return (errno);
859 ctx->kdblog_context = (void *)log_ctx;
860 } else
861 log_ctx = ctx->kdblog_context;
863 log_ctx->iproprole = role;
865 return (0);