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 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdlib.h> 29 #include <alloca.h> 30 #include <signal.h> 31 #include <sys/stat.h> 32 #include <unistd.h> 33 #include <pthread.h> 34 #include <time.h> 35 #include <errno.h> 36 #include <door.h> 37 #include <zone.h> 38 #include <resolv.h> 39 #include <sys/socket.h> 40 #include <net/route.h> 41 #include <string.h> 42 #include <net/if.h> 43 #include <sys/stat.h> 44 #include <fcntl.h> 45 #include "nscd_common.h" 46 #include "nscd_door.h" 47 #include "nscd_config.h" 48 #include "nscd_switch.h" 49 #include "nscd_log.h" 50 #include "nscd_selfcred.h" 51 #include "nscd_frontend.h" 52 #include "nscd_admin.h" 53 54 static void rts_mon(void); 55 static void keep_open_dns_socket(void); 56 57 extern nsc_ctx_t *cache_ctx_p[]; 58 59 /* 60 * Current active Configuration data for the frontend component 61 */ 62 static nscd_cfg_global_frontend_t frontend_cfg_g; 63 static nscd_cfg_frontend_t *frontend_cfg; 64 65 static int max_servers = 0; 66 static int max_servers_set = 0; 67 static int per_user_is_on = 1; 68 69 static char *main_execname; 70 static char **main_argv; 71 extern int _whoami; 72 extern long activity; 73 extern mutex_t activity_lock; 74 75 static sema_t common_sema; 76 77 static thread_key_t lookup_state_key; 78 static mutex_t create_lock = DEFAULTMUTEX; 79 static int num_servers = 0; 80 static thread_key_t server_key; 81 82 /* 83 * Bind a TSD value to a server thread. This enables the destructor to 84 * be called if/when this thread exits. This would be a programming 85 * error, but better safe than sorry. 86 */ 87 /*ARGSUSED*/ 88 static void * 89 server_tsd_bind(void *arg) 90 { 91 static void *value = 0; 92 93 /* disable cancellation to avoid hangs if server threads disappear */ 94 (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 95 (void) thr_setspecific(server_key, value); 96 (void) door_return(NULL, 0, NULL, 0); 97 98 /* make lint happy */ 99 return (NULL); 100 } 101 102 /* 103 * Server threads are created here. 104 */ 105 /*ARGSUSED*/ 106 static void 107 server_create(door_info_t *dip) 108 { 109 (void) mutex_lock(&create_lock); 110 if (++num_servers > max_servers) { 111 num_servers--; 112 (void) mutex_unlock(&create_lock); 113 return; 114 } 115 (void) mutex_unlock(&create_lock); 116 (void) thr_create(NULL, 0, server_tsd_bind, NULL, 117 THR_BOUND|THR_DETACHED, NULL); 118 } 119 120 /* 121 * Server thread are destroyed here 122 */ 123 /*ARGSUSED*/ 124 static void 125 server_destroy(void *arg) 126 { 127 (void) mutex_lock(&create_lock); 128 num_servers--; 129 (void) mutex_unlock(&create_lock); 130 } 131 132 /* 133 * get clearance 134 */ 135 int 136 _nscd_get_clearance(sema_t *sema) { 137 if (sema_trywait(&common_sema) == 0) { 138 (void) thr_setspecific(lookup_state_key, NULL); 139 return (0); 140 } 141 142 if (sema_trywait(sema) == 0) { 143 (void) thr_setspecific(lookup_state_key, (void*)1); 144 return (0); 145 } 146 147 return (1); 148 } 149 150 151 /* 152 * release clearance 153 */ 154 int 155 _nscd_release_clearance(sema_t *sema) { 156 int which; 157 158 (void) thr_getspecific(lookup_state_key, (void**)&which); 159 if (which == 0) /* from common pool */ { 160 (void) sema_post(&common_sema); 161 return (0); 162 } 163 164 (void) sema_post(sema); 165 return (1); 166 } 167 168 static void 169 dozip(void) 170 { 171 /* not much here */ 172 } 173 174 static void 175 restart_if_cfgfile_changed() 176 { 177 178 static mutex_t nsswitch_lock = DEFAULTMUTEX; 179 static time_t last_nsswitch_check = 0; 180 static time_t last_nsswitch_modified = 0; 181 static time_t last_resolv_modified = 0; 182 time_t now = time(NULL); 183 char *me = "restart_if_cfgfile_changed"; 184 185 if (now - last_nsswitch_check <= _NSC_FILE_CHECK_TIME) 186 return; 187 188 (void) mutex_lock(&nsswitch_lock); 189 190 if (now - last_nsswitch_check > _NSC_FILE_CHECK_TIME) { 191 struct stat nss_buf; 192 struct stat res_buf; 193 194 last_nsswitch_check = now; 195 196 (void) mutex_unlock(&nsswitch_lock); /* let others continue */ 197 198 /* 199 * This code keeps us from statting resolv.conf 200 * if it doesn't exist, yet prevents us from ignoring 201 * it if it happens to disappear later on for a bit. 202 */ 203 204 if (last_resolv_modified >= 0) { 205 if (stat("/etc/resolv.conf", &res_buf) < 0) { 206 if (last_resolv_modified == 0) 207 last_resolv_modified = -1; 208 else 209 res_buf.st_mtime = last_resolv_modified; 210 } else if (last_resolv_modified == 0) { 211 last_resolv_modified = res_buf.st_mtime; 212 } 213 } 214 215 if (stat("/etc/nsswitch.conf", &nss_buf) < 0) { 216 217 /*EMPTY*/; 218 219 } else if (last_nsswitch_modified == 0) { 220 221 last_nsswitch_modified = nss_buf.st_mtime; 222 223 } else if ((last_nsswitch_modified < nss_buf.st_mtime) || 224 ((last_resolv_modified > 0) && 225 (last_resolv_modified < res_buf.st_mtime))) { 226 static mutex_t exit_lock = DEFAULTMUTEX; 227 char *fmri; 228 229 /* 230 * if in self cred mode, kill the forker and 231 * child nscds 232 */ 233 if (_nscd_is_self_cred_on(0, NULL)) { 234 _nscd_kill_forker(); 235 _nscd_kill_all_children(); 236 } 237 238 /* 239 * time for restart 240 */ 241 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_INFO) 242 (me, "nscd restart due to %s or %s change\n", 243 "/etc/nsswitch.conf", "resolv.conf"); 244 /* 245 * try to restart under smf 246 */ 247 if ((fmri = getenv("SMF_FMRI")) == NULL) { 248 /* not running under smf - reexec */ 249 (void) execv(main_execname, main_argv); 250 exit(1); /* just in case */ 251 } 252 253 /* prevent multiple restarts */ 254 (void) mutex_lock(&exit_lock); 255 256 if (smf_restart_instance(fmri) == 0) 257 (void) sleep(10); /* wait a bit */ 258 exit(1); /* give up waiting for resurrection */ 259 } 260 261 } else 262 (void) mutex_unlock(&nsswitch_lock); 263 } 264 265 uid_t 266 _nscd_get_client_euid() 267 { 268 ucred_t *uc = NULL; 269 uid_t id; 270 char *me = "get_client_euid"; 271 272 if (door_ucred(&uc) != 0) { 273 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 274 (me, "door_ucred: %s\n", strerror(errno)); 275 return ((uid_t)-1); 276 } 277 278 id = ucred_geteuid(uc); 279 ucred_free(uc); 280 return (id); 281 } 282 283 /* 284 * Check to see if the door client has PRIV_FILE_DAC_READ privilege. 285 * Return 0 if yes, -1 otherwise. 286 */ 287 int 288 _nscd_check_client_read_priv() 289 { 290 int rc = 0; 291 ucred_t *uc = NULL; 292 const priv_set_t *eset; 293 char *me = "_nscd_check_client_read_priv"; 294 295 if (door_ucred(&uc) != 0) { 296 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 297 (me, "door_ucred: %s\n", strerror(errno)); 298 return (-1); 299 } 300 eset = ucred_getprivset(uc, PRIV_EFFECTIVE); 301 if (!priv_ismember(eset, PRIV_FILE_DAC_READ)) 302 rc = -1; 303 ucred_free(uc); 304 return (rc); 305 } 306 307 static void 308 N2N_check_priv( 309 void *buf, 310 char *dc_str) 311 { 312 nss_pheader_t *phdr = (nss_pheader_t *)buf; 313 ucred_t *uc = NULL; 314 const priv_set_t *eset; 315 zoneid_t zoneid; 316 int errnum; 317 char *me = "N2N_check_priv"; 318 319 if (door_ucred(&uc) != 0) { 320 errnum = errno; 321 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 322 (me, "door_ucred: %s\n", strerror(errno)); 323 324 NSCD_RETURN_STATUS(phdr, NSS_ERROR, errnum); 325 } 326 327 eset = ucred_getprivset(uc, PRIV_EFFECTIVE); 328 zoneid = ucred_getzoneid(uc); 329 330 if ((zoneid != GLOBAL_ZONEID && zoneid != getzoneid()) || 331 eset != NULL ? !priv_ismember(eset, PRIV_SYS_ADMIN) : 332 ucred_geteuid(uc) != 0) { 333 334 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ALERT) 335 (me, "%s call failed(cred): caller pid %d, uid %d, " 336 "euid %d, zoneid %d\n", dc_str, ucred_getpid(uc), 337 ucred_getruid(uc), ucred_geteuid(uc), zoneid); 338 ucred_free(uc); 339 340 NSCD_RETURN_STATUS(phdr, NSS_ERROR, EACCES); 341 } 342 343 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 344 (me, "nscd received %s cmd from pid %d, uid %d, " 345 "euid %d, zoneid %d\n", dc_str, ucred_getpid(uc), 346 ucred_getruid(uc), ucred_geteuid(uc), zoneid); 347 348 ucred_free(uc); 349 350 NSCD_RETURN_STATUS_SUCCESS(phdr); 351 } 352 353 void 354 _nscd_APP_check_cred( 355 void *buf, 356 pid_t *pidp, 357 char *dc_str, 358 int log_comp, 359 int log_level) 360 { 361 nss_pheader_t *phdr = (nss_pheader_t *)buf; 362 ucred_t *uc = NULL; 363 uid_t ruid; 364 uid_t euid; 365 pid_t pid; 366 int errnum; 367 char *me = "_nscd_APP_check_cred"; 368 369 if (door_ucred(&uc) != 0) { 370 errnum = errno; 371 _NSCD_LOG(log_comp, NSCD_LOG_LEVEL_ERROR) 372 (me, "door_ucred: %s\n", strerror(errno)); 373 374 NSCD_RETURN_STATUS(phdr, NSS_ERROR, errnum); 375 } 376 377 NSCD_SET_STATUS_SUCCESS(phdr); 378 pid = ucred_getpid(uc); 379 if (NSS_PACKED_CRED_CHECK(buf, ruid = ucred_getruid(uc), 380 euid = ucred_geteuid(uc))) { 381 if (pidp != NULL) { 382 if (*pidp == (pid_t)-1) 383 *pidp = pid; 384 else if (*pidp != pid) { 385 NSCD_SET_STATUS(phdr, NSS_ERROR, EACCES); 386 } 387 } 388 } else { 389 NSCD_SET_STATUS(phdr, NSS_ERROR, EACCES); 390 } 391 392 ucred_free(uc); 393 394 if (NSCD_STATUS_IS_NOT_OK(phdr)) { 395 _NSCD_LOG(log_comp, log_level) 396 (me, "%s call failed: caller pid %d (input pid = %d), ruid %d, " 397 "euid %d, header ruid %d, header euid %d\n", dc_str, 398 pid, (pidp != NULL) ? *pidp : -1, ruid, euid, 399 ((nss_pheader_t *)(buf))->p_ruid, 400 ((nss_pheader_t *)(buf))->p_euid); 401 } 402 } 403 404 /* log error and return -1 when an invalid packed buffer header is found */ 405 static int 406 pheader_error(nss_pheader_t *phdr, uint32_t call_number) 407 { 408 char *call_num_str; 409 410 switch (call_number) { 411 case NSCD_SEARCH: 412 call_num_str = "NSCD_SEARCH"; 413 break; 414 case NSCD_SETENT: 415 call_num_str = "NSCD_SETENT"; 416 break; 417 case NSCD_GETENT: 418 call_num_str = "NSCD_GETENT"; 419 break; 420 case NSCD_ENDENT: 421 call_num_str = "NSCD_ENDENT"; 422 break; 423 case NSCD_PUT: 424 call_num_str = "NSCD_PUT"; 425 break; 426 case NSCD_GETHINTS: 427 call_num_str = "NSCD_GETHINTS"; 428 break; 429 default: 430 call_num_str = "UNKNOWN"; 431 break; 432 } 433 434 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ALERT) 435 ("pheader_error", "call number %s: invalid packed buffer header\n", 436 call_num_str); 437 438 NSCD_SET_STATUS(phdr, NSS_ERROR, EINVAL); 439 return (-1); 440 } 441 442 /* 443 * Validate the header of a getXbyY or setent/getent/endent request. 444 * Return 0 if good, -1 otherwise. 445 * 446 * A valid header looks like the following (size is arg_size, does 447 * not include the output area): 448 * +----------------------------------+ -- 449 * | nss_pheader_t (header fixed part)| ^ 450 * | | | 451 * | pbufsiz, dbd,off, key_off, | len = sizeof(nss_pheader_t) 452 * | data_off .... | | 453 * | | v 454 * +----------------------------------+ <----- dbd_off 455 * | dbd (database description) | ^ 456 * | nss_dbd_t + up to 3 strings | | 457 * | length = sizeof(nss_dbd_t) + | len = key_off - dbd_off 458 * | length of 3 strings + | | 459 * | length of padding | | 460 * | (total length in multiple of 4) | v 461 * +----------------------------------+ <----- key_off 462 * | lookup key | ^ 463 * | nss_XbyY_key_t, content varies, | | 464 * | based on database and lookup op | len = data_off - key_off 465 * | length = data_off - key_off | | 466 * | including padding, multiple of 4 | v 467 * +----------------------------------+ <----- data_off (= arg_size) 468 * | | ^ 469 * | area to hold results | | 470 * | | len = data_len (= pbufsiz - 471 * | | | data_off) 472 * | | v 473 * +----------------------------------+ <----- pbufsiz 474 */ 475 static int 476 validate_pheader( 477 void *argp, 478 size_t arg_size, 479 uint32_t call_number) 480 { 481 nss_pheader_t *phdr = (nss_pheader_t *)(void *)argp; 482 nssuint_t l1, l2; 483 484 /* 485 * current version is NSCD_HEADER_REV, length of the fixed part 486 * of the header must match the size of nss_pheader_t 487 */ 488 if (phdr->p_version != NSCD_HEADER_REV || 489 phdr->dbd_off != sizeof (nss_pheader_t)) 490 return (pheader_error(phdr, call_number)); 491 492 /* 493 * buffer size and offsets must be in multiple of 4 494 */ 495 if ((arg_size & 3) || (phdr->dbd_off & 3) || (phdr->key_off & 3) || 496 (phdr->data_off & 3)) 497 return (pheader_error(phdr, call_number)); 498 499 /* 500 * the input arg_size is the length of the request header 501 * and should be less than NSCD_PHDR_MAXLEN 502 */ 503 if (phdr->data_off != arg_size || arg_size > NSCD_PHDR_MAXLEN) 504 return (pheader_error(phdr, call_number)); 505 506 /* get length of the dbd area */ 507 l1 = phdr->key_off - phdr-> dbd_off; 508 509 /* 510 * dbd area may contain padding, so length of dbd should 511 * not be less than the length of the actual data 512 */ 513 if (l1 < phdr->dbd_len) 514 return (pheader_error(phdr, call_number)); 515 516 /* get length of the key area */ 517 l2 = phdr->data_off - phdr->key_off; 518 519 /* 520 * key area may contain padding, so length of key area should 521 * not be less than the length of the actual data 522 */ 523 if (l2 < phdr->key_len) 524 return (pheader_error(phdr, call_number)); 525 526 /* 527 * length of fixed part + lengths of dbd and key area = length of 528 * the request header 529 */ 530 if (sizeof (nss_pheader_t) + l1 + l2 != phdr->data_off) 531 return (pheader_error(phdr, call_number)); 532 533 /* header length + data length = buffer length */ 534 if (phdr->data_off + phdr->data_len != phdr->pbufsiz) 535 return (pheader_error(phdr, call_number)); 536 537 return (0); 538 } 539 540 /* log error and return -1 when an invalid nscd to nscd buffer is found */ 541 static int 542 N2Nbuf_error(nss_pheader_t *phdr, uint32_t call_number) 543 { 544 char *call_num_str; 545 546 switch (call_number) { 547 case NSCD_PING: 548 call_num_str = "NSCD_PING"; 549 break; 550 551 case NSCD_IMHERE: 552 call_num_str = "NSCD_IMHERE"; 553 break; 554 555 case NSCD_PULSE: 556 call_num_str = "NSCD_PULSE"; 557 break; 558 559 case NSCD_FORK: 560 call_num_str = "NSCD_FORK"; 561 break; 562 563 case NSCD_KILL: 564 call_num_str = "NSCD_KILL"; 565 break; 566 567 case NSCD_REFRESH: 568 call_num_str = "NSCD_REFRESH"; 569 break; 570 571 case NSCD_GETPUADMIN: 572 call_num_str = "NSCD_GETPUADMIN"; 573 break; 574 575 case NSCD_GETADMIN: 576 call_num_str = "NSCD_GETADMIN"; 577 break; 578 579 case NSCD_SETADMIN: 580 call_num_str = "NSCD_SETADMIN"; 581 break; 582 583 case NSCD_KILLSERVER: 584 call_num_str = "NSCD_KILLSERVER"; 585 break; 586 default: 587 call_num_str = "UNKNOWN"; 588 break; 589 } 590 591 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ALERT) 592 ("N2Nbuf_error", "call number %s: invalid N2N buffer\n", call_num_str); 593 594 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 595 NSCD_DOOR_BUFFER_CHECK_FAILED); 596 597 return (-1); 598 } 599 600 /* 601 * Validate the buffer of an nscd to nscd request. 602 * Return 0 if good, -1 otherwise. 603 * 604 * A valid buffer looks like the following (size is arg_size): 605 * +----------------------------------+ -- 606 * | nss_pheader_t (header fixed part)| ^ 607 * | | | 608 * | pbufsiz, dbd,off, key_off, | len = sizeof(nss_pheader_t) 609 * | data_off .... | | 610 * | | v 611 * +----------------------------------+ <---dbd_off = key_off = data_off 612 * | | ^ 613 * | input data/output data | | 614 * | OR no data | len = data_len (= pbufsiz - 615 * | | | data_off) 616 * | | | len could be zero 617 * | | v 618 * +----------------------------------+ <--- pbufsiz 619 */ 620 static int 621 validate_N2Nbuf( 622 void *argp, 623 size_t arg_size, 624 uint32_t call_number) 625 { 626 nss_pheader_t *phdr = (nss_pheader_t *)(void *)argp; 627 628 /* 629 * current version is NSCD_HEADER_REV, length of the fixed part 630 * of the header must match the size of nss_pheader_t 631 */ 632 if (phdr->p_version != NSCD_HEADER_REV || 633 phdr->dbd_off != sizeof (nss_pheader_t)) 634 return (N2Nbuf_error(phdr, call_number)); 635 636 /* 637 * There are no dbd and key data, so the dbd, key, data 638 * offsets should be equal 639 */ 640 if (phdr->dbd_off != phdr->key_off || 641 phdr->dbd_off != phdr->data_off) 642 return (N2Nbuf_error(phdr, call_number)); 643 644 /* 645 * the input arg_size is the buffer length and should 646 * be less or equal than NSCD_N2NBUF_MAXLEN 647 */ 648 if (phdr->pbufsiz != arg_size || arg_size > NSCD_N2NBUF_MAXLEN) 649 return (N2Nbuf_error(phdr, call_number)); 650 651 /* header length + data length = buffer length */ 652 if (phdr->data_off + phdr->data_len != phdr->pbufsiz) 653 return (N2Nbuf_error(phdr, call_number)); 654 655 return (0); 656 } 657 658 static void 659 lookup(char *argp, size_t arg_size) 660 { 661 nsc_lookup_args_t largs; 662 char space[NSCD_LOOKUP_BUFSIZE]; 663 nss_pheader_t *phdr = (nss_pheader_t *)(void *)argp; 664 665 NSCD_ALLOC_LOOKUP_BUFFER(argp, arg_size, phdr, space, 666 sizeof (space)); 667 668 /* 669 * make sure the first couple bytes of the data area is null, 670 * so that bad strings in the packed header stop here 671 */ 672 (void) memset((char *)phdr + phdr->data_off, 0, 16); 673 674 (void) memset(&largs, 0, sizeof (largs)); 675 largs.buffer = argp; 676 largs.bufsize = arg_size; 677 nsc_lookup(&largs, 0); 678 679 /* 680 * only the PUN needs to keep track of the 681 * activity count to determine when to 682 * terminate itself 683 */ 684 if (_whoami == NSCD_CHILD) { 685 (void) mutex_lock(&activity_lock); 686 ++activity; 687 (void) mutex_unlock(&activity_lock); 688 } 689 690 NSCD_SET_RETURN_ARG(phdr, arg_size); 691 (void) door_return(argp, arg_size, NULL, 0); 692 } 693 694 static void 695 getent(char *argp, size_t arg_size) 696 { 697 char space[NSCD_LOOKUP_BUFSIZE]; 698 nss_pheader_t *phdr = (nss_pheader_t *)(void *)argp; 699 700 NSCD_ALLOC_LOOKUP_BUFFER(argp, arg_size, phdr, space, sizeof (space)); 701 702 nss_pgetent(argp, arg_size); 703 704 NSCD_SET_RETURN_ARG(phdr, arg_size); 705 (void) door_return(argp, arg_size, NULL, 0); 706 } 707 708 static int 709 is_db_per_user(void *buf, char *dblist) 710 { 711 nss_pheader_t *phdr = (nss_pheader_t *)buf; 712 nss_dbd_t *pdbd; 713 char *dbname, *dbn; 714 int len; 715 716 /* copy db name into a temp buffer */ 717 pdbd = (nss_dbd_t *)((void *)((char *)buf + phdr->dbd_off)); 718 dbname = (char *)pdbd + pdbd->o_name; 719 len = strlen(dbname); 720 dbn = alloca(len + 2); 721 (void) memcpy(dbn, dbname, len); 722 723 /* check if <dbname> + ',' can be found in the dblist string */ 724 dbn[len] = ','; 725 dbn[len + 1] = '\0'; 726 if (strstr(dblist, dbn) != NULL) 727 return (1); 728 729 /* 730 * check if <dbname> can be found in the last part 731 * of the dblist string 732 */ 733 dbn[len] = '\0'; 734 if (strstr(dblist, dbn) != NULL) 735 return (1); 736 737 return (0); 738 } 739 740 /* 741 * Check to see if all conditions are met for processing per-user 742 * requests. Returns 1 if yes, -1 if backend is not configured, 743 * 0 otherwise. 744 */ 745 static int 746 need_per_user_door(void *buf, int whoami, uid_t uid, char **dblist) 747 { 748 nss_pheader_t *phdr = (nss_pheader_t *)buf; 749 750 NSCD_SET_STATUS_SUCCESS(phdr); 751 752 /* if already a per-user nscd, no need to get per-user door */ 753 if (whoami == NSCD_CHILD) 754 return (0); 755 756 /* forker shouldn't be asked */ 757 if (whoami == NSCD_FORKER) { 758 NSCD_SET_STATUS(phdr, NSS_ERROR, ENOTSUP); 759 return (0); 760 } 761 762 /* if door client is root, no need for a per-user door */ 763 if (uid == 0) 764 return (0); 765 766 /* 767 * if per-user lookup is not configured, no per-user 768 * door available 769 */ 770 if (_nscd_is_self_cred_on(0, dblist) == 0) 771 return (-1); 772 773 /* 774 * if per-user lookup is not configured for the db, 775 * don't bother 776 */ 777 if (is_db_per_user(phdr, *dblist) == 0) 778 return (0); 779 780 return (1); 781 } 782 783 static void 784 if_selfcred_return_per_user_door(char *argp, size_t arg_size, 785 door_desc_t *dp, int whoami) 786 { 787 nss_pheader_t *phdr = (nss_pheader_t *)((void *)argp); 788 char *dblist; 789 int door = -1; 790 int rc = 0; 791 door_desc_t desc; 792 char *space; 793 int len; 794 795 /* 796 * check to see if self-cred is configured and 797 * need to return an alternate PUN door 798 */ 799 if (per_user_is_on == 1) { 800 rc = need_per_user_door(argp, whoami, 801 _nscd_get_client_euid(), &dblist); 802 if (rc == -1) 803 per_user_is_on = 0; 804 } 805 if (rc <= 0) { 806 /* 807 * self-cred not configured, and no error detected, 808 * return to continue the door call processing 809 */ 810 if (NSCD_STATUS_IS_OK(phdr)) 811 return; 812 else 813 /* 814 * configured but error detected, 815 * stop the door call processing 816 */ 817 (void) door_return(argp, phdr->data_off, NULL, 0); 818 } 819 820 /* get the alternate PUN door */ 821 _nscd_proc_alt_get(argp, &door); 822 if (NSCD_GET_STATUS(phdr) != NSS_ALTRETRY) { 823 (void) door_return(argp, phdr->data_off, NULL, 0); 824 } 825 826 /* return the alternate door descriptor */ 827 len = strlen(dblist) + 1; 828 space = alloca(arg_size + len); 829 phdr->data_len = len; 830 (void) memcpy(space, phdr, arg_size); 831 (void) strncpy((char *)space + arg_size, dblist, len); 832 dp = &desc; 833 dp->d_attributes = DOOR_DESCRIPTOR; 834 dp->d_data.d_desc.d_descriptor = door; 835 arg_size += len; 836 (void) door_return(space, arg_size, dp, 1); 837 } 838 839 /*ARGSUSED*/ 840 static void 841 switcher(void *cookie, char *argp, size_t arg_size, 842 door_desc_t *dp, uint_t n_desc) 843 { 844 int iam; 845 pid_t ent_pid = -1; 846 nss_pheader_t *phdr = (nss_pheader_t *)((void *)argp); 847 void *uptr; 848 int len; 849 size_t buflen; 850 int callnum; 851 char *me = "switcher"; 852 853 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 854 (me, "switcher ...\n"); 855 856 if (argp == DOOR_UNREF_DATA) { 857 (void) printf("Door Slam... exiting\n"); 858 exit(0); 859 } 860 861 if (argp == NULL) { /* empty door call */ 862 (void) door_return(NULL, 0, 0, 0); /* return the favor */ 863 } 864 865 /* 866 * need to restart if main nscd and config file(s) changed 867 */ 868 if (_whoami == NSCD_MAIN) 869 restart_if_cfgfile_changed(); 870 871 if ((phdr->nsc_callnumber & NSCDV2CATMASK) == NSCD_CALLCAT_APP) { 872 873 /* make sure the packed buffer header is good */ 874 if (validate_pheader(argp, arg_size, 875 phdr->nsc_callnumber) == -1) 876 (void) door_return(argp, arg_size, NULL, 0); 877 878 switch (phdr->nsc_callnumber) { 879 880 case NSCD_SEARCH: 881 882 /* if a fallback to main nscd, skip per-user setup */ 883 if (phdr->p_status != NSS_ALTRETRY) 884 if_selfcred_return_per_user_door(argp, arg_size, 885 dp, _whoami); 886 lookup(argp, arg_size); 887 888 break; 889 890 case NSCD_SETENT: 891 892 _nscd_APP_check_cred(argp, &ent_pid, "NSCD_SETENT", 893 NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ALERT); 894 if (NSCD_STATUS_IS_OK(phdr)) { 895 if_selfcred_return_per_user_door(argp, arg_size, 896 dp, _whoami); 897 nss_psetent(argp, arg_size, ent_pid); 898 } 899 break; 900 901 case NSCD_GETENT: 902 903 getent(argp, arg_size); 904 break; 905 906 case NSCD_ENDENT: 907 908 nss_pendent(argp, arg_size); 909 break; 910 911 case NSCD_PUT: 912 913 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 914 (me, "door call NSCD_PUT not supported yet\n"); 915 916 NSCD_SET_STATUS(phdr, NSS_ERROR, ENOTSUP); 917 break; 918 919 case NSCD_GETHINTS: 920 921 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 922 (me, "door call NSCD_GETHINTS not supported yet\n"); 923 924 NSCD_SET_STATUS(phdr, NSS_ERROR, ENOTSUP); 925 break; 926 927 default: 928 929 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 930 (me, "Unknown name service door call op %x\n", 931 phdr->nsc_callnumber); 932 933 NSCD_SET_STATUS(phdr, NSS_ERROR, EINVAL); 934 break; 935 } 936 937 (void) door_return(argp, arg_size, NULL, 0); 938 } 939 940 iam = NSCD_MAIN; 941 callnum = phdr->nsc_callnumber & ~NSCD_WHOAMI; 942 if (callnum == NSCD_IMHERE || 943 callnum == NSCD_PULSE || callnum == NSCD_FORK) 944 iam = phdr->nsc_callnumber & NSCD_WHOAMI; 945 else 946 callnum = phdr->nsc_callnumber; 947 948 /* nscd -> nscd v2 calls */ 949 950 /* make sure the buffer is good */ 951 if (validate_N2Nbuf(argp, arg_size, callnum) == -1) 952 (void) door_return(argp, arg_size, NULL, 0); 953 954 switch (callnum) { 955 956 case NSCD_PING: 957 NSCD_SET_STATUS_SUCCESS(phdr); 958 break; 959 960 case NSCD_IMHERE: 961 _nscd_proc_iamhere(argp, dp, n_desc, iam); 962 break; 963 964 case NSCD_PULSE: 965 N2N_check_priv(argp, "NSCD_PULSE"); 966 if (NSCD_STATUS_IS_OK(phdr)) 967 _nscd_proc_pulse(argp, iam); 968 break; 969 970 case NSCD_FORK: 971 N2N_check_priv(argp, "NSCD_FORK"); 972 if (NSCD_STATUS_IS_OK(phdr)) 973 _nscd_proc_fork(argp, iam); 974 break; 975 976 case NSCD_KILL: 977 N2N_check_priv(argp, "NSCD_KILL"); 978 if (NSCD_STATUS_IS_OK(phdr)) 979 exit(0); 980 break; 981 982 case NSCD_REFRESH: 983 N2N_check_priv(argp, "NSCD_REFRESH"); 984 if (NSCD_STATUS_IS_OK(phdr)) { 985 if (_nscd_refresh() != NSCD_SUCCESS) 986 exit(1); 987 NSCD_SET_STATUS_SUCCESS(phdr); 988 } 989 break; 990 991 case NSCD_GETPUADMIN: 992 993 if (_nscd_is_self_cred_on(0, NULL)) { 994 _nscd_peruser_getadmin(argp, sizeof (nscd_admin_t)); 995 } else { 996 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 997 NSCD_SELF_CRED_NOT_CONFIGURED); 998 } 999 break; 1000 1001 case NSCD_GETADMIN: 1002 1003 len = _nscd_door_getadmin((void *)argp); 1004 if (len == 0) 1005 break; 1006 1007 /* size of door buffer not big enough, allocate one */ 1008 NSCD_ALLOC_DOORBUF(NSCD_GETADMIN, len, uptr, buflen); 1009 1010 /* copy packed header */ 1011 *(nss_pheader_t *)uptr = *(nss_pheader_t *)((void *)argp); 1012 1013 /* set new buffer size */ 1014 ((nss_pheader_t *)uptr)->pbufsiz = buflen; 1015 1016 /* try one more time */ 1017 (void) _nscd_door_getadmin((void *)uptr); 1018 (void) door_return(uptr, buflen, NULL, 0); 1019 break; 1020 1021 case NSCD_SETADMIN: 1022 N2N_check_priv(argp, "NSCD_SETADMIN"); 1023 if (NSCD_STATUS_IS_OK(phdr)) 1024 _nscd_door_setadmin(argp); 1025 break; 1026 1027 case NSCD_KILLSERVER: 1028 N2N_check_priv(argp, "NSCD_KILLSERVER"); 1029 if (NSCD_STATUS_IS_OK(phdr)) { 1030 /* also kill the forker nscd if one is running */ 1031 _nscd_kill_forker(); 1032 exit(0); 1033 } 1034 break; 1035 1036 default: 1037 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 1038 (me, "Unknown name service door call op %d\n", 1039 phdr->nsc_callnumber); 1040 1041 NSCD_SET_STATUS(phdr, NSS_ERROR, EINVAL); 1042 1043 (void) door_return(argp, arg_size, NULL, 0); 1044 break; 1045 1046 } 1047 (void) door_return(argp, arg_size, NULL, 0); 1048 } 1049 1050 int 1051 _nscd_setup_server(char *execname, char **argv) 1052 { 1053 1054 int fd; 1055 int errnum; 1056 int bind_failed = 0; 1057 struct stat buf; 1058 sigset_t myset; 1059 struct sigaction action; 1060 char *me = "_nscd_setup_server"; 1061 1062 main_execname = execname; 1063 main_argv = argv; 1064 1065 keep_open_dns_socket(); 1066 1067 /* 1068 * the max number of server threads should be fixed now, so 1069 * set flag to indicate that no in-flight change is allowed 1070 */ 1071 max_servers_set = 1; 1072 1073 (void) thr_keycreate(&lookup_state_key, NULL); 1074 (void) sema_init(&common_sema, frontend_cfg_g.common_worker_threads, 1075 USYNC_THREAD, 0); 1076 1077 /* Establish server thread pool */ 1078 (void) door_server_create(server_create); 1079 if (thr_keycreate(&server_key, server_destroy) != 0) { 1080 errnum = errno; 1081 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 1082 (me, "thr_keycreate (server thread): %s\n", 1083 strerror(errnum)); 1084 return (-1); 1085 } 1086 1087 /* Create a door */ 1088 if ((fd = door_create(switcher, NAME_SERVICE_DOOR_COOKIE, 1089 DOOR_UNREF | DOOR_NO_CANCEL)) < 0) { 1090 errnum = errno; 1091 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 1092 (me, "door_create: %s\n", strerror(errnum)); 1093 return (-1); 1094 } 1095 1096 /* if not main nscd, no more setup to do */ 1097 if (_whoami != NSCD_MAIN) 1098 return (fd); 1099 1100 /* bind to file system */ 1101 if (is_system_labeled() && (getzoneid() == GLOBAL_ZONEID)) { 1102 if (stat(TSOL_NAME_SERVICE_DOOR, &buf) < 0) { 1103 int newfd; 1104 if ((newfd = creat(TSOL_NAME_SERVICE_DOOR, 0444)) < 0) { 1105 errnum = errno; 1106 _NSCD_LOG(NSCD_LOG_FRONT_END, 1107 NSCD_LOG_LEVEL_ERROR) 1108 (me, "Cannot create %s: %s\n", 1109 TSOL_NAME_SERVICE_DOOR, 1110 strerror(errnum)); 1111 bind_failed = 1; 1112 } 1113 (void) close(newfd); 1114 } 1115 if (symlink(TSOL_NAME_SERVICE_DOOR, NAME_SERVICE_DOOR) != 0) { 1116 if (errno != EEXIST) { 1117 errnum = errno; 1118 _NSCD_LOG(NSCD_LOG_FRONT_END, 1119 NSCD_LOG_LEVEL_ERROR) 1120 (me, "Cannot symlink %s: %s\n", 1121 NAME_SERVICE_DOOR, strerror(errnum)); 1122 bind_failed = 1; 1123 } 1124 } 1125 } else if (stat(NAME_SERVICE_DOOR, &buf) < 0) { 1126 int newfd; 1127 if ((newfd = creat(NAME_SERVICE_DOOR, 0444)) < 0) { 1128 errnum = errno; 1129 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 1130 (me, "Cannot create %s: %s\n", NAME_SERVICE_DOOR, 1131 strerror(errnum)); 1132 bind_failed = 1; 1133 } 1134 (void) close(newfd); 1135 } 1136 1137 if (bind_failed == 1) { 1138 (void) door_revoke(fd); 1139 return (-1); 1140 } 1141 1142 if (fattach(fd, NAME_SERVICE_DOOR) < 0) { 1143 if ((errno != EBUSY) || 1144 (fdetach(NAME_SERVICE_DOOR) < 0) || 1145 (fattach(fd, NAME_SERVICE_DOOR) < 0)) { 1146 errnum = errno; 1147 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 1148 (me, "fattach: %s\n", strerror(errnum)); 1149 (void) door_revoke(fd); 1150 return (-1); 1151 } 1152 } 1153 1154 /* 1155 * kick off routing socket monitor thread 1156 */ 1157 if (thr_create(NULL, NULL, 1158 (void *(*)(void *))rts_mon, 0, 0, NULL) != 0) { 1159 errnum = errno; 1160 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 1161 (me, "thr_create (routing socket monitor): %s\n", 1162 strerror(errnum)); 1163 1164 (void) door_revoke(fd); 1165 return (-1); 1166 } 1167 1168 /* 1169 * set up signal handler for SIGHUP 1170 */ 1171 action.sa_handler = dozip; 1172 action.sa_flags = 0; 1173 (void) sigemptyset(&action.sa_mask); 1174 (void) sigemptyset(&myset); 1175 (void) sigaddset(&myset, SIGHUP); 1176 1177 if (sigaction(SIGHUP, &action, NULL) < 0) { 1178 errnum = errno; 1179 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 1180 (me, "sigaction (SIGHUP): %s\n", strerror(errnum)); 1181 1182 (void) door_revoke(fd); 1183 return (-1); 1184 } 1185 1186 return (fd); 1187 } 1188 1189 int 1190 _nscd_setup_child_server(int did) 1191 { 1192 1193 int errnum; 1194 int fd; 1195 nscd_rc_t rc; 1196 char *me = "_nscd_setup_child_server"; 1197 1198 /* Re-establish our own server thread pool */ 1199 (void) door_server_create(server_create); 1200 if (thr_keycreate(&server_key, server_destroy) != 0) { 1201 errnum = errno; 1202 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 1203 (me, "thr_keycreate failed: %s", strerror(errnum)); 1204 return (-1); 1205 } 1206 1207 /* 1208 * Create a new door. 1209 * Keep DOOR_REFUSE_DESC (self-cred nscds don't fork) 1210 */ 1211 (void) close(did); 1212 if ((fd = door_create(switcher, NAME_SERVICE_DOOR_COOKIE, 1213 DOOR_REFUSE_DESC|DOOR_UNREF|DOOR_NO_CANCEL)) < 0) { 1214 errnum = errno; 1215 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 1216 (me, "door_create failed: %s", strerror(errnum)); 1217 return (-1); 1218 } 1219 1220 /* 1221 * kick off routing socket monitor thread 1222 */ 1223 if (thr_create(NULL, NULL, 1224 (void *(*)(void *))rts_mon, 0, 0, NULL) != 0) { 1225 errnum = errno; 1226 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 1227 (me, "thr_create (routing socket monitor): %s\n", 1228 strerror(errnum)); 1229 (void) door_revoke(fd); 1230 return (-1); 1231 } 1232 1233 /* 1234 * start monitoring the states of the name service clients 1235 */ 1236 rc = _nscd_init_smf_monitor(); 1237 if (rc != NSCD_SUCCESS) { 1238 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 1239 (me, "unable to start the SMF monitor (rc = %d)\n", rc); 1240 1241 (void) door_revoke(fd); 1242 return (-1); 1243 } 1244 1245 return (fd); 1246 } 1247 1248 nscd_rc_t 1249 _nscd_alloc_frontend_cfg() 1250 { 1251 frontend_cfg = calloc(NSCD_NUM_DB, sizeof (nscd_cfg_frontend_t)); 1252 if (frontend_cfg == NULL) 1253 return (NSCD_NO_MEMORY); 1254 1255 return (NSCD_SUCCESS); 1256 } 1257 1258 1259 /* ARGSUSED */ 1260 nscd_rc_t 1261 _nscd_cfg_frontend_notify( 1262 void *data, 1263 struct nscd_cfg_param_desc *pdesc, 1264 nscd_cfg_id_t *nswdb, 1265 nscd_cfg_flag_t dflag, 1266 nscd_cfg_error_t **errorp, 1267 void *cookie) 1268 { 1269 void *dp; 1270 1271 /* 1272 * At init time, the whole group of config params are received. 1273 * At update time, group or individual parameter value could 1274 * be received. 1275 */ 1276 1277 if (_nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_INIT) || 1278 _nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_GROUP)) { 1279 /* 1280 * group data is received, copy in the 1281 * entire strcture 1282 */ 1283 if (_nscd_cfg_flag_is_set(pdesc->pflag, NSCD_CFG_PFLAG_GLOBAL)) 1284 frontend_cfg_g = *(nscd_cfg_global_frontend_t *)data; 1285 else 1286 frontend_cfg[nswdb->index] = 1287 *(nscd_cfg_frontend_t *)data; 1288 1289 } else { 1290 /* 1291 * individual paramater is received: copy in the 1292 * parameter value. 1293 */ 1294 if (_nscd_cfg_flag_is_set(pdesc->pflag, NSCD_CFG_PFLAG_GLOBAL)) 1295 dp = (char *)&frontend_cfg_g + pdesc->p_offset; 1296 else 1297 dp = (char *)&frontend_cfg[nswdb->index] + 1298 pdesc->p_offset; 1299 (void) memcpy(dp, data, pdesc->p_size); 1300 } 1301 1302 return (NSCD_SUCCESS); 1303 } 1304 1305 /* ARGSUSED */ 1306 nscd_rc_t 1307 _nscd_cfg_frontend_verify( 1308 void *data, 1309 struct nscd_cfg_param_desc *pdesc, 1310 nscd_cfg_id_t *nswdb, 1311 nscd_cfg_flag_t dflag, 1312 nscd_cfg_error_t **errorp, 1313 void **cookie) 1314 { 1315 1316 char *me = "_nscd_cfg_frontend_verify"; 1317 1318 /* 1319 * if max. number of server threads is set and in effect, 1320 * don't allow changing of the frontend configuration 1321 */ 1322 if (max_servers_set) { 1323 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_INFO) 1324 (me, "changing of the frontend configuration not allowed now"); 1325 1326 return (NSCD_CFG_CHANGE_NOT_ALLOWED); 1327 } 1328 1329 return (NSCD_SUCCESS); 1330 } 1331 1332 /* ARGSUSED */ 1333 nscd_rc_t 1334 _nscd_cfg_frontend_get_stat( 1335 void **stat, 1336 struct nscd_cfg_stat_desc *sdesc, 1337 nscd_cfg_id_t *nswdb, 1338 nscd_cfg_flag_t *dflag, 1339 void (**free_stat)(void *stat), 1340 nscd_cfg_error_t **errorp) 1341 { 1342 return (NSCD_SUCCESS); 1343 } 1344 1345 void 1346 _nscd_init_cache_sema(sema_t *sema, char *cache_name) 1347 { 1348 int i, j; 1349 char *dbn; 1350 1351 if (max_servers == 0) 1352 max_servers = frontend_cfg_g.common_worker_threads + 1353 frontend_cfg_g.cache_hit_threads; 1354 1355 for (i = 0; i < NSCD_NUM_DB; i++) { 1356 1357 dbn = NSCD_NSW_DB_NAME(i); 1358 if (strcasecmp(dbn, cache_name) == 0) { 1359 j = frontend_cfg[i].worker_thread_per_nsw_db; 1360 (void) sema_init(sema, j, USYNC_THREAD, 0); 1361 max_servers += j; 1362 break; 1363 } 1364 } 1365 } 1366 1367 /* 1368 * Monitor the routing socket. Address lists stored in the ipnodes 1369 * cache are sorted based on destination address selection rules, 1370 * so when things change that could affect that sorting (interfaces 1371 * go up or down, flags change, etc.), we clear that cache so the 1372 * list will be re-ordered the next time the hostname is resolved. 1373 */ 1374 static void 1375 rts_mon(void) 1376 { 1377 int rt_sock, rdlen, idx; 1378 union { 1379 struct { 1380 struct rt_msghdr rtm; 1381 struct sockaddr_storage addrs[RTA_NUMBITS]; 1382 } r; 1383 struct if_msghdr ifm; 1384 struct ifa_msghdr ifam; 1385 } mbuf; 1386 struct ifa_msghdr *ifam = &mbuf.ifam; 1387 char *me = "rts_mon"; 1388 1389 rt_sock = socket(PF_ROUTE, SOCK_RAW, 0); 1390 if (rt_sock < 0) { 1391 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 1392 (me, "Failed to open routing socket: %s\n", strerror(errno)); 1393 thr_exit(0); 1394 } 1395 1396 for (;;) { 1397 rdlen = read(rt_sock, &mbuf, sizeof (mbuf)); 1398 if (rdlen <= 0) { 1399 if (rdlen == 0 || (errno != EINTR && errno != EAGAIN)) { 1400 _NSCD_LOG(NSCD_LOG_FRONT_END, 1401 NSCD_LOG_LEVEL_ERROR) 1402 (me, "routing socket read: %s\n", 1403 strerror(errno)); 1404 thr_exit(0); 1405 } 1406 continue; 1407 } 1408 if (ifam->ifam_version != RTM_VERSION) { 1409 _NSCD_LOG(NSCD_LOG_FRONT_END, 1410 NSCD_LOG_LEVEL_ERROR) 1411 (me, "rx unknown version (%d) on " 1412 "routing socket.\n", 1413 ifam->ifam_version); 1414 continue; 1415 } 1416 switch (ifam->ifam_type) { 1417 case RTM_NEWADDR: 1418 case RTM_DELADDR: 1419 /* if no ipnodes cache, then nothing to do */ 1420 idx = get_cache_idx("ipnodes"); 1421 if (cache_ctx_p[idx] == NULL || 1422 cache_ctx_p[idx]->reaper_on != nscd_true) 1423 break; 1424 nsc_invalidate(cache_ctx_p[idx], NULL, NULL); 1425 break; 1426 case RTM_ADD: 1427 case RTM_DELETE: 1428 case RTM_CHANGE: 1429 case RTM_GET: 1430 case RTM_LOSING: 1431 case RTM_REDIRECT: 1432 case RTM_MISS: 1433 case RTM_LOCK: 1434 case RTM_OLDADD: 1435 case RTM_OLDDEL: 1436 case RTM_RESOLVE: 1437 case RTM_IFINFO: 1438 break; 1439 default: 1440 _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 1441 (me, "rx unknown msg type (%d) on routing socket.\n", 1442 ifam->ifam_type); 1443 break; 1444 } 1445 } 1446 } 1447 1448 static void 1449 keep_open_dns_socket(void) 1450 { 1451 _res.options |= RES_STAYOPEN; /* just keep this udp socket open */ 1452 } 1453