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