e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * CDDL HEADER START
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * The contents of this file are subject to the terms of the
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Common Development and Distribution License (the "License").
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * You may not use this file except in compliance with the License.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * or http://www.opensolaris.org/os/licensing.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * See the License for the specific language governing permissions
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * and limitations under the License.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * When distributing Covered Code, include this CDDL HEADER in each
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * If applicable, add the following below this CDDL HEADER, with the
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * fields enclosed by brackets "[]" replaced with your own identifying
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * information: Portions Copyright [yyyy] [name of copyright owner]
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * CDDL HEADER END
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
b57459abfba36eb3068cfe44c6921168b4c4f774Julian Pullen * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Use is subject to license terms.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <strings.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <stdlib.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <syslog.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <errno.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <libintl.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <door.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <sys/types.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <sys/stat.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <fcntl.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <procfs.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include "cachemgr.h"
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethextern admin_t current_admin;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define CLEANUP_WAIT_TIME 60
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethtypedef enum cleanup_type {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth CLEANUP_ALL = 1,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth CLEANUP_BY_PID = 2
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth} cleanup_type_t;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethtypedef struct cleanup_op {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth pid_t pid;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cleanup_type_t type;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth} cleanup_op_t;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethtypedef struct main_nscd_struct {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth pid_t pid; /* main nscd pid */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth thread_t tid; /* main nscd tid */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int in_progress; /* A main nscd thread is */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* waiting for change or */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* copying data */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int is_waiting_cleanup; /* A main nscd thread is */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* waiting for another main */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* nscd thread to be cleaned */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* up */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth} main_nscd_t;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic chg_info_t chg = { DEFAULTMUTEX, DEFAULTCV, 0, NULL, NULL, NULL, 0 };
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic main_nscd_t chg_main_nscd = {0, 0, 0, 0};
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic mutex_t chg_main_nscd_lock = DEFAULTMUTEX;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic cond_t chg_main_nscd_cv = DEFAULTCV;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * The cookie of the configuration and its mutex
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic ldap_get_chg_cookie_t config_cookie = {0, 0};
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic mutex_t config_cookie_lock = DEFAULTMUTEX;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void cleanup_thread_by_pid(pid_t pid);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethldap_get_chg_cookie_t
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethchg_config_cookie_get(void)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ldap_get_chg_cookie_t cookie;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&config_cookie_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cookie = config_cookie;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&config_cookie_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (cookie);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethchg_config_cookie_increment_seq_num(void)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&config_cookie_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth config_cookie.seq_num++;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&config_cookie_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethvoid
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethchg_config_cookie_set(ldap_get_chg_cookie_t *cookie)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&config_cookie_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth config_cookie.mgr_pid = cookie->mgr_pid;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth config_cookie.seq_num = cookie->seq_num;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&config_cookie_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic boolean_t
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethchg_cookie_equal(ldap_get_chg_cookie_t *c1, ldap_get_chg_cookie_t *c2)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (c1->mgr_pid == c2->mgr_pid && c1->seq_num == c2->seq_num)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (B_TRUE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth else
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Create a node in the list and output the node. The caller can NOT free it.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic int
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethwaiting_list_add(chg_info_t *info, pid_t pid, thread_t tid,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth waiting_list_t **wlp)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth waiting_list_t *wl;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *wlp = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((wl = (waiting_list_t *)calloc(1, sizeof (waiting_list_t)))
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth logit("waiting_list_add: No memory. pid %ld tid %d\n",
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth pid, tid);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (CHG_NO_MEMORY);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth wl->pid = pid;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth wl->tid = tid;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (info->chg_w_first == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth info->chg_w_first = wl;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth info->chg_w_last = wl;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth info->chg_w_last->next = wl;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth wl->prev = info->chg_w_last;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth info->chg_w_last = wl;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *wlp = wl;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (CHG_SUCCESS);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Find a node with matching tid in the list and remove it from the list.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic int
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethwaiting_list_delete(chg_info_t *info, thread_t tid)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth waiting_list_t *wl;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth for (wl = info->chg_w_first; wl != NULL; wl = wl->next) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (wl->tid == tid) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (wl->next == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (wl->prev == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth info->chg_w_first = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth info->chg_w_last = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth wl->prev->next = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth info->chg_w_last = wl->prev;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (wl->prev == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth wl->next->prev = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth info->chg_w_first = wl->next;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth wl->prev->next = wl->next;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth wl->next->prev = wl->prev;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free(wl);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (CHG_SUCCESS);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (CHG_NOT_FOUND_IN_WAITING_LIST);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Delete the thread from the waiting list and remove data when the list
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * is empty.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethwaiting_list_cleanup(chg_info_t *chg, thread_t tid)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int rc;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = waiting_list_delete(chg, tid);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (rc == CHG_SUCCESS && chg->chg_w_first == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free(chg->chg_data);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg->chg_data = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg->chg_wakeup = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Set flag by pid so it can be cleaned up.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethwaiting_list_set_cleanup(chg_info_t *info, pid_t pid)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth waiting_list_t *wl;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth for (wl = info->chg_w_first; wl != NULL; wl = wl->next) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (wl->pid == pid) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth wl->cleanup = 1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth break;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Return: 1 - door client is dead, 0 - door client is alive
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic int
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethdoor_client_dead(void)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ucred_t *uc = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int rc;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (door_ucred(&uc) == -1 && errno == EINVAL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = 1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (uc)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ucred_free(uc);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (rc);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * This function handles GETSTATUSCHANGE call from main nscd.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * The call can be a START op or STOP op. A cookie is sent from main nscd too.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * The static global variable main_nscd keeps record of pid, tid and some flags.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * If the thread is door_return(), main_nscd.pid, main_nscd.tid are set to 0.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * When the call is START op, it checks if main_nscd.pid is 0. If it is, it
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * proceeds to wait for the change notification. If it's not, which means
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * another main nscd handling thread is still around. It sends broadcast to
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * clean up that thread and wait until the cleanup is done then proceeds to
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * wait for the change notification. If same main nscd sends START op
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * repeatedly, it'll be rejected.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * It also checks the cookie from main nscd. If it's not the same as
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * ldap_cachemgr's cookie, door returns config change.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * If the door call is STOP op, it creates a thread to clean up main nscd START
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * thread so it won't be blocking.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * In waiting for the change notification phase, the thread is waken up by
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * the notification threads or by the cleanup threads.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * If it's a notification, it copies data to the stack then door return.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * If it's a cleanup, door_client_dead() is called to verify it then
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * door return.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethint
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethchg_get_statusChange(LineBuf *info, ldap_call_t *in, pid_t nscd_pid)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int rc = CHG_SUCCESS, another_main_nscd_thread_alive = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int len, return_now;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth thread_t this_tid = thr_self();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth waiting_list_t *wl = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ldap_get_change_out_t *cout;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ldap_get_chg_cookie_t cookie;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth info->str = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth info->len = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (in->ldap_u.get_change.op == NS_STATUS_CHANGE_OP_START) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&chg_main_nscd_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (chg_main_nscd.pid != 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (nscd_pid != chg_main_nscd.pid) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * This is the case that nscd doesn't shut down
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * properly(e.g. core) and STOP op is not sent,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * the thread handling it is still around and
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * not cleaned up yet.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Test if the thread is still alive.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * If it is, clean it up.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * For thr_kill, if sig is 0, a validity check
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * is done for the existence of the target
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * thread; no signal is sent.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (thr_kill(chg_main_nscd.tid, 0) == 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth another_main_nscd_thread_alive = 1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cleanup_thread_by_pid(
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg_main_nscd.pid);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else if (chg_main_nscd.in_progress ||
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg_main_nscd.is_waiting_cleanup) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Same nscd pid can only send door call
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * one at a time and wait for ldap_cachemgr to
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * return change data. If it's the same pid
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * again, it's an nscd error.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&chg_main_nscd_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (CHG_NSCD_REPEATED_CALL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Wait for another thread to be cleaned up if it's alive.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * After that this cond var is waken up.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (another_main_nscd_thread_alive) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth while (chg_main_nscd.in_progress) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg_main_nscd.is_waiting_cleanup = 1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) cond_wait(&chg_main_nscd_cv,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth &chg_main_nscd_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Replace pid and tid and set the flag.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg_main_nscd.is_waiting_cleanup = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg_main_nscd.pid = nscd_pid;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg_main_nscd.tid = this_tid;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg_main_nscd.in_progress = 1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&chg_main_nscd_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cookie = chg_config_cookie_get();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (!chg_cookie_equal(&cookie, &in->ldap_u.get_change.cookie)) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * different cookie, set new cookie and
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * return door call right away
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth len = sizeof (ldap_get_change_out_t);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((cout = calloc(1, len)) == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = CHG_NO_MEMORY;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cout->type = NS_STATUS_CHANGE_TYPE_CONFIG;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cout->cookie = cookie;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth info->str = (char *)cout;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth info->len = len;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&chg.chg_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* wait for the change notification */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = waiting_list_add(&chg, nscd_pid, this_tid, &wl);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (rc == CHG_SUCCESS) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return_now = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth while (!chg.chg_wakeup) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (wl->cleanup ||
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth door_client_dead()) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return_now = 1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth break;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) cond_wait(&chg.chg_cv,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth &chg.chg_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* Check if door client is still alive again */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (!return_now && !wl->cleanup &&
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth !door_client_dead()) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* copy data to buffer */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((info->str = malloc(
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg.chg_data_size)) == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = CHG_NO_MEMORY;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) memcpy(info->str,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg.chg_data,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg.chg_data_size);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth info->len = chg.chg_data_size;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth waiting_list_cleanup(&chg, this_tid);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&chg.chg_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Reset pid, tid and flag, send wakeup signal.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&chg_main_nscd_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg_main_nscd.pid = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg_main_nscd.tid = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg_main_nscd.in_progress = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (chg_main_nscd.is_waiting_cleanup)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) cond_broadcast(&chg_main_nscd_cv);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&chg_main_nscd_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else if (in->ldap_u.get_change.op == NS_STATUS_CHANGE_OP_STOP) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cleanup_thread_by_pid(nscd_pid);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = CHG_SUCCESS;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = CHG_INVALID_PARAM;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (rc == CHG_EXCEED_MAX_THREADS)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cleanup_thread_by_pid(0);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (rc);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * This function copies the header and data stream to the buffer
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * then send broadcast to wake up the chg_get_statusChange() threads.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethint
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethchg_notify_statusChange(char *str)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ldap_get_change_out_t *cout = (ldap_get_change_out_t *)str;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cout->cookie = chg_config_cookie_get();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&chg.chg_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (chg.chg_w_first != NULL && chg.chg_wakeup == 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (chg.chg_data) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free(chg.chg_data);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg.chg_data = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg.chg_data = str;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cout->type == NS_STATUS_CHANGE_TYPE_CONFIG)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg.chg_data_size = sizeof (ldap_get_change_out_t);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth else
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* NS_STATUS_CHANGE_TYPE_SERVER */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg.chg_data_size = sizeof (ldap_get_change_out_t) -
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth sizeof (int) + cout->data_size;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg.chg_wakeup = 1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) cond_broadcast(&chg.chg_cv);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&chg.chg_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (CHG_SUCCESS);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * This is called when the configuration is refreshed.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * The new configuration is different from the current one, a notification
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * is sent tochg_get_statusChange() threads.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethvoid
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethchg_test_config_change(ns_config_t *new, int *change_status)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int changed = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth LineBuf new_cfg, cur_cfg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_ldap_error_t *errp = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ldap_config_out_t *new_out, *cur_out;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ldap_get_change_out_t *cout;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) memset(&new_cfg, 0, sizeof (LineBuf));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) memset(&cur_cfg, 0, sizeof (LineBuf));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Flatten the config data of the newly downloaded config and
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * current default config and compare both.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
b57459abfba36eb3068cfe44c6921168b4c4f774Julian Pullen if ((errp = __ns_ldap_LoadDoorInfo(&new_cfg, NULL, new, 0)) != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth __ns_ldap_freeError(&errp);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* error, assume the config is changed */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth changed = 1;
b57459abfba36eb3068cfe44c6921168b4c4f774Julian Pullen } else if ((errp = __ns_ldap_LoadDoorInfo(&cur_cfg, NULL, NULL, 0))
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth __ns_ldap_freeError(&errp);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* error, assume the config is changed */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth changed = 1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (changed == 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth new_out = (ldap_config_out_t *)new_cfg.str;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cur_out = (ldap_config_out_t *)cur_cfg.str;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (strcmp(new_out->config_str, cur_out->config_str) != 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth changed = 1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (current_admin.debug_level >= DBG_PROFILE_REFRESH) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth logit("config changed.\n");
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cur_cfg.str)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free(cur_cfg.str);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (new_cfg.str)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free(new_cfg.str);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (changed) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((cout = calloc(1, sizeof (ldap_get_change_out_t)))
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth logit("chg_test_config_change: No Memory\n");
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Replace the currentdefault config with the new
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * config
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth __s_api_init_config(new);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg_config_cookie_increment_seq_num();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cout->type = NS_STATUS_CHANGE_TYPE_CONFIG;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * cout->cookie is set by
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * chg_notify_statusChange
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) chg_notify_statusChange((char *)cout);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth __s_api_destroy_config(new);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *change_status = changed;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Wake up chg_get_statusChange() threads to clean up the threads
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * that main nscd doesn't exist on the other of door anymore or
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * the thread is marked as cleanup.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethcleanup_threads(chg_info_t *chg, pid_t pid, cleanup_type_t type)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&chg->chg_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (type == CLEANUP_BY_PID)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth waiting_list_set_cleanup(chg, pid);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * wake up threads without setting chg.chg_wakeup.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * It's for cleanup purpose, not for notifying changes.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) cond_broadcast(&chg->chg_cv);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&chg->chg_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * If arg is NULL, it loops forever,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * else it calls cleanup_threads once and exits.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethvoid *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethchg_cleanup_waiting_threads(void *arg)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cleanup_op_t *op = (cleanup_op_t *)arg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cleanup_type_t type = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth pid_t pid;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int always = 1, waiting;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (op == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth waiting = 1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth type = CLEANUP_ALL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth pid = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth waiting = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth type = op->type;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth pid = op->pid;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth while (always) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (waiting)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) sleep(CLEANUP_WAIT_TIME);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cleanup_threads(&chg, pid, type);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (!waiting)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth break;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (op)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free(op);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth thr_exit(NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * The door server thead which has the door client pid will be marked
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * as to be clean up. If pid is 0, no marking and just clean up all.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethcleanup_thread_by_pid(pid_t pid)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cleanup_op_t *op;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((op = malloc(sizeof (cleanup_op_t))) == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth op->pid = pid;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* clean up all if pid is 0 */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (pid == 0)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth op->type = CLEANUP_ALL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth else
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth op->type = CLEANUP_BY_PID;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (thr_create(NULL, 0, chg_cleanup_waiting_threads,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void *)op, THR_BOUND|THR_DETACHED, NULL) != 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free(op);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth logit("thr_create failed for cleanup_thread_by_pid(%ld)\n",
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth pid);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Output a psinfo of an nscd process with process id pid
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Return: 0 - Can't find the process or it's not nscd
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * 1 - psinfo found
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Note: If info is NULL, returns 0 or 1 only and no output from info.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic int
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethget_nscd_psinfo(pid_t pid, psinfo_t *info)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth psinfo_t pinfo;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth char fname[MAXPATHLEN];
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ssize_t ret;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int fd;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (snprintf(fname, MAXPATHLEN, "/proc/%d/psinfo", pid) > 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((fd = open(fname, O_RDONLY)) >= 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ret = read(fd, &pinfo, sizeof (psinfo_t));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) close(fd);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((ret == sizeof (psinfo_t)) &&
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (strcmp(pinfo.pr_fname, "nscd") == 0)) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (info)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *info = pinfo;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (1);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (0);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * If the parent process is nscd and euid is 0, it's a peruser nscd.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic int
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethis_peruser_nscd(pid_t pid)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth pid_t ppid;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth psinfo_t pinfo;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (get_nscd_psinfo(pid, &pinfo)) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ppid = pinfo.pr_ppid;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (get_nscd_psinfo(ppid, &pinfo) && pinfo.pr_euid == 0)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * get psinfo of parent forker nscd
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (1);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth else
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (0);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (0);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Check if the door client making door call is a nscd or peruser nscd and
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * output door client's pid.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethint
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethchg_is_called_from_nscd_or_peruser_nscd(char *dc_str, pid_t *pidp)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int rc;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth uid_t euid;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth pid_t pid;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ucred_t *uc = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (door_ucred(&uc) != 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = errno;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth logit("door_ucred() call failed %s\n", strerror(rc));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (0);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth euid = ucred_geteuid(uc);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth pid = *pidp = ucred_getpid(uc);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((euid == 0 && is_called_from_nscd(pid)) ||
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth is_peruser_nscd(pid)) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (current_admin.debug_level >= DBG_ALL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth logit("ldap_cachemgr received %s call from pid %ld, "
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth "uid %u, euid %u\n", dc_str, pid,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ucred_getruid(uc), euid);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = 1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (current_admin.debug_level >= DBG_CANT_FIND)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth logit("%s call failed(cred): caller pid %ld, uid %u, "
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth "euid %u\n", dc_str, pid,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ucred_getruid(uc), euid);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ucred_free(uc);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (rc);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}