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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 /* 26 * Copyright (c) 1998 by Sun Microsystems, Inc. 27 * All rights reserved. 28 */ 29 30 #ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.19.9.1 */ 31 32 /* 33 * Network Listener Process 34 * 35 * command line: 36 * 37 * listen [ -m minor_prefix ] netspec 38 * 39 */ 40 41 /* system include files */ 42 43 #include <fcntl.h> 44 #include <signal.h> 45 #include <stdio.h> 46 #include <unistd.h> 47 #include <string.h> 48 #include <errno.h> 49 #include <memory.h> 50 #include <sys/utsname.h> 51 #include <sys/tiuser.h> 52 #include <sys/param.h> 53 #include <sys/types.h> 54 #include <sys/stat.h> 55 #include <sys/mkdev.h> 56 #include <values.h> 57 #include <ctype.h> 58 #include <pwd.h> 59 #include <grp.h> 60 #include <sys/ipc.h> 61 #include <sys/poll.h> 62 #include <sys/stropts.h> 63 #include <sac.h> 64 #include <utmpx.h> 65 66 /* listener include files */ 67 68 #include "lsparam.h" /* listener parameters */ 69 #include "lsfiles.h" /* listener files info */ 70 #include "lserror.h" /* listener error codes */ 71 #include "lsnlsmsg.h" /* NLPS listener protocol */ 72 #include "lssmbmsg.h" /* MS_NET identifier */ 73 #include "lsdbf.h" /* data base file stuff */ 74 #include "listen.h" 75 76 /* defines */ 77 78 #define NAMESIZE (NAMEBUFSZ-1) 79 80 #define SPLhi() Splflag = 1 81 #define SPLlo() Splflag = 0 82 83 #define GEN 1 84 #define LOGIN 0 85 86 /* global variables */ 87 88 int NLPS_proc = 0; /* set if process is a listener child */ 89 pid_t Pid; /* listener's process ID */ 90 char *Progname; /* listener's basename (from argv[0]) */ 91 static char Provbuf[PATHSIZE]; 92 char *Provider = Provbuf; /* name of transport provider */ 93 char *Netspec = NETSPEC; 94 char *Minor_prefix; /* prefix for minor device names */ 95 int Dbf_entries; /* number of private addresses in dbf file*/ 96 int Valid_addrs; /* number of addresses bound */ 97 struct pollfd *Pollfds; /* for polling fds */ 98 dbf_t *Dbfhead; /* Beginning of in-memory database */ 99 dbf_t *Newdbf; /* Beginning of in-memory database (reread) */ 100 char *Server_cmd_lines; /* database space */ 101 char *New_cmd_lines; /* database space (reread) */ 102 long Ndesc; /* Number of per-process file descriptors */ 103 int Readdb; /* set to TRUE by SAC_READDB message */ 104 struct netconfig *Netconf; /* netconfig structure for this network */ 105 106 struct call_list Free_call; 107 struct call_list *Free_call_p = &Free_call; /* call free list */ 108 struct call_list *Priv_call; /* call save pending list */ 109 110 /* FILE DESCRIPTOR MANAGEMENT: 111 * 112 * The listener uses 6 (sometimes 7) file descriptors: 113 * fd 0: Originally opened to /dev/null, used to accept incoming calls. 114 * fd 1: In the parent, a connection to _sacpipe. Closed in the child 115 * and dup'ed to 0. 116 * fd 2: In the parent, a connection to _pmpipe. Dup'ed in the child 117 * to 0. 118 * fd 3: Originally opened to /dev/null, this file descriptor is 119 * reserved to open the STREAMS pipe when passing the connection 120 * to a standing server. 121 * fd 4: Opened to the pid file. We have to keep it open to keep the 122 * lock active. 123 * fd 5: Opened to the log file. 124 * fd 6: Opened to the debug file ONLY when compiled with DEBUGMODE. 125 * 126 * The remaining file descriptors are available for binding private addresses. 127 */ 128 129 #ifndef DEBUGMODE 130 #define USEDFDS 6 131 #else 132 #define USEDFDS 7 133 FILE *Debugfp; /* for the debugging file */ 134 #endif 135 136 int Acceptfd; /* to accept connections (fd 0) */ 137 int Sacpipefd; /* pipe TO sac process (fd 1) */ 138 int Pmpipefd; /* pipe FROM sac process (fd 2) */ 139 int Passfd; /* pipe used to pass FD (fd 3) */ 140 int Pidfd; /* locked pid file (fd 4) */ 141 FILE *Logfp; /* for logging listener activity*/ 142 143 struct pmmsg Pmmsg; /* to respond to SAC */ 144 int State = PM_STARTING; /* current SAC state */ 145 char Mytag[15]; 146 147 char Lastmsg[BUFSIZ]; /* contains last msg logged (by stampbuf) */ 148 int Logmax = LOGMAX; /* number of entriet to allow in logfile */ 149 150 int Splflag; /* logfile critical region flag */ 151 152 static char *badnspmsg = "Bad netspec on command line ( Pathname too long )"; 153 static char *badstart = "Listener failed to start properly"; 154 static char *nologfile = "Unable to open listener log file during initialization"; 155 static char *usage = "Usage: listen [ -m minor_prefix ] network_device"; 156 static char *nopmtag = "Fatal error: Unable to get PMTAG from environment"; 157 static char tzenv[BUFSIZ]; 158 159 #define TIMEZONE "/etc/TIMEZONE" 160 #define TZSTR "TZ=" 161 162 void check_sac_mesg(); /* routine to process messages from sac */ 163 void rpc_register(); /* routine to register rpc services */ 164 void rpc_unregister(); /* routine to unregister rpc services */ 165 extern struct netconfig *getnetconfigent(); 166 extern char *t_alloc(); 167 extern void logexit(); 168 extern int t_errno; 169 extern int errno; 170 171 #ifndef TRUE 172 #define TRUE 1 173 #define FALSE 0 174 #endif 175 176 main(argc, argv) 177 int argc; 178 char **argv; 179 { 180 struct stat buf; 181 int ret; 182 char scratch[BUFSIZ]; 183 char log[BUFSIZ]; 184 char olog[BUFSIZ]; 185 char *scratch_p = scratch; 186 char *mytag_p; 187 FILE *fp; 188 extern char *getenv(); 189 char *parse(); 190 int c; 191 extern char *optarg; 192 extern int optind; 193 register int i; 194 char *Mytag_p = Mytag; 195 196 /* Get my port monitor tag out of the environment */ 197 if ((mytag_p = getenv("PMTAG")) == NULL) { 198 /* no place to write */ 199 exit(1); 200 } 201 strcpy(Mytag, mytag_p); 202 203 /* open log file */ 204 sprintf(log, "%s/%s/%s", ALTDIR, Mytag_p, LOGNAME); 205 sprintf(olog, "%s/%s/%s", ALTDIR, Mytag_p, OLOGNAME); 206 if (stat(log, &buf) == 0) { 207 /* file exists, try and save it but if we can't don't worry */ 208 unlink(olog); 209 rename(log, olog); 210 } 211 if ((i = open(log, O_WRONLY|O_CREAT|O_APPEND, 0444)) < 0) 212 logexit(1, nologfile); 213 /* as stated above, the log file should be file descriptor 5 */ 214 if ((ret = fcntl(i, F_DUPFD, 5)) != 5) 215 logexit(1, nologfile); 216 Logfp = fdopen(ret, "a+"); 217 218 /* Get my port monitor tag out of the environment */ 219 if ((mytag_p = getenv("PMTAG")) == NULL) { 220 logexit(1, nopmtag); 221 } 222 strcpy(Mytag, mytag_p); 223 224 (void) umask(022); 225 Readdb = FALSE; 226 227 if (geteuid() != (uid_t) 0) { 228 logmessage("Must be root to start listener"); 229 logexit(1, badstart); 230 } 231 232 while ((c = getopt(argc, argv, "m:")) != EOF) 233 switch (c) { 234 case 'm': 235 Minor_prefix = optarg; 236 break; 237 default: 238 logexit(1, usage); 239 break; 240 } 241 242 if ((Netspec = argv[optind]) == NULL) { 243 logexit(1, usage); 244 } 245 if ((Netconf = getnetconfigent(Netspec)) == NULL) { 246 sprintf(scratch, "no netconfig entry for <%s>", Netspec); 247 logmessage(scratch); 248 logexit(1, badstart); 249 } 250 if (!Minor_prefix) 251 Minor_prefix = argv[optind]; 252 253 if ((int) strlen(Netspec) > PATHSIZE) { 254 logmessage(badnspmsg); 255 logexit(1, badstart); 256 } 257 258 /* 259 * SAC will start the listener in the correct directory, so we 260 * don't need to chdir there, as we did in older versions 261 */ 262 263 strcpy(Provbuf, "/dev/"); 264 strcat(Provbuf, Netspec); 265 266 (void) umask(0); 267 268 init_files(); /* open Accept, Sac, Pm, Pass files */ 269 pid_open(); /* create pid file */ 270 271 #ifdef DEBUGMODE 272 sprintf(scratch, "%s/%s/%s", ALTDIR, Mytag, DBGNAME); 273 Debugfp = fopen(scratch, "w"); 274 #endif 275 276 277 #ifdef DEBUGMODE 278 if ((!Logfp) || (!Debugfp)) 279 #else 280 if (!Logfp) 281 #endif 282 logexit(1, badstart); 283 284 /* 285 * In case we started with no environment, find out what timezone we're 286 * in. This will get passed to children, so only need to do once. 287 */ 288 289 if (getenv("TZ") == NULL) { 290 fp = fopen(TIMEZONE, "r"); 291 if (fp) { 292 while (fgets(tzenv, BUFSIZ, fp)) { 293 if (tzenv[strlen(tzenv) - 1] == '\n') 294 tzenv[strlen(tzenv) - 1] = '\0'; 295 if (!strncmp(TZSTR, tzenv, strlen(TZSTR))) { 296 putenv(parse(tzenv)); 297 break; 298 } 299 } 300 fclose(fp); 301 } 302 else { 303 sprintf(scratch, "couldn't open %s, default to GMT", TIMEZONE); 304 logmessage(scratch); 305 } 306 } 307 308 logmessage("@(#)listen:listen.c 1.19.9.1"); 309 310 #ifdef DEBUGMODE 311 logmessage("Listener process with DEBUG capability"); 312 #endif 313 314 sprintf(scratch, "Listener port monitor tag: %s", Mytag_p); 315 logmessage(scratch); 316 DEBUG((9, "Minor prefix: %s Netspec %s", Minor_prefix, Netspec)); 317 318 /* fill in Pmmesg fields that always stay the same */ 319 320 Pmmsg.pm_maxclass = MAXCLASS; 321 strcpy(Pmmsg.pm_tag, Mytag_p); 322 Pmmsg.pm_size = 0; 323 324 /* Find out what state to start in. If not in env, exit */ 325 if ((scratch_p = getenv("ISTATE")) == NULL) 326 logexit(1, "ERROR: ISTATE variable not set in environment"); 327 328 if (!strcmp(scratch_p, "enabled")) { 329 State = PM_ENABLED; 330 logmessage("Starting state: ENABLED"); 331 } 332 else { 333 State = PM_DISABLED; 334 logmessage("Starting state: DISABLED"); 335 } 336 337 /* try to get my "basename" */ 338 Progname = strrchr(argv[0], '/'); 339 if (Progname && Progname[1]) 340 ++Progname; 341 else 342 Progname = argv[0]; 343 344 catch_signals(); 345 346 /* 347 * Allocate memory for private address and file descriptor table 348 * Here we are assuming that no matter how many private addresses 349 * exist in the system if the system limit is 20 then we will only 350 * get 20 file descriptors 351 */ 352 353 Ndesc = ulimit(4,0L); /* get num of file des on system */ 354 355 read_dbf(DB_INIT); 356 net_open(); /* init, open, bind names */ 357 358 for (i = 3; i < Ndesc; i++) { /* leave stdout, stderr open */ 359 fcntl(i, F_SETFD, 1); /* set close on exec flag*/ 360 } 361 362 logmessage("Initialization Complete"); 363 364 listen(); 365 exit(0); 366 } 367 368 369 /* 370 * pid_open: 371 * 372 * open pidfile with specified oflags and modes and lock it 373 * 374 */ 375 376 static char *pidopenmsg ="Can't create process ID file in home directory"; 377 static char *pidlockmsg ="Can't lock PID file: listener may already be running"; 378 379 pid_open() 380 { 381 int ret; 382 unsigned i; 383 char pidstring[20]; 384 385 if ((Pidfd = open(PIDNAME, PIDOFLAG, PIDMODE)) == -1) { 386 logmessage(pidopenmsg); 387 error(E_CREAT, EXIT | NOCORE | NO_MSG); 388 } 389 390 if (lockf(Pidfd, 2, 0L) == -1) { 391 logmessage(pidlockmsg); 392 logexit(1, badstart); 393 } 394 395 Pid = getpid(); 396 i = sprintf(pidstring, "%ld", Pid) + 1; 397 ftruncate(Pidfd, 0); 398 399 while ((ret = write(Pidfd, pidstring, i)) != i) { 400 if (errno == EINTR) 401 continue; 402 if (ret < 0) 403 sys_error(E_PIDWRITE, EXIT); 404 else 405 error(E_PIDWRITE, EXIT); 406 } 407 408 } 409 410 /* 411 * init_files: open initial files for the listener (see FILE DESC MGMT comment) 412 */ 413 414 static char *pmopenmsg = "Can't open pipe to read SAC messages"; 415 static char *sacopenmsg = "Can't open pipe to respond to SAC messages"; 416 417 init_files() 418 { 419 close(0); 420 if ((Acceptfd = open("/dev/null", O_RDWR)) != 0) { 421 logmessage("Trouble opening /dev/null"); 422 sys_error(E_SYS_ERROR, EXIT | NOCORE); 423 } 424 425 close(1); 426 if ((Sacpipefd = open(SACPIPE, O_RDWR|O_NDELAY)) != 1) { 427 logmessage(sacopenmsg); 428 error(E_CREAT, EXIT | NOCORE | NO_MSG); 429 } 430 431 close(2); 432 if ((Pmpipefd = open(PMPIPE, O_RDWR|O_NDELAY)) != 2) { 433 logmessage(pmopenmsg); 434 error(E_CREAT, EXIT | NOCORE | NO_MSG); 435 } 436 437 close(3); 438 if ((Passfd = dup(Acceptfd)) != 3) { 439 logmessage("Trouble duping /dev/null"); 440 sys_error(E_SYS_ERROR, EXIT | NOCORE); 441 } 442 443 } 444 445 446 /* 447 * net_open: open and bind communications channels 448 * The name generation code in net_open, open_bind and bind is, 449 * for the most part, specific to STARLAN NETWORK. 450 * This name generation code is included in the listener 451 * as a developer debugging aid. 452 */ 453 454 net_open() 455 { 456 #ifdef CHARADDR 457 char pbuf[NAMEBUFSZ + 1]; 458 #endif /* CHARADDR */ 459 register int i; 460 register dbf_t *dp; 461 char scratch[BUFSIZ]; 462 463 DEBUG((9,"in net_open")); 464 465 /* set up free call list and pending connection lists */ 466 467 Free_call_p->cl_head = (struct callsave *) NULL; 468 Free_call_p->cl_tail = (struct callsave *) NULL; 469 470 /* Pending calls are linked in a structure, one per fild descriptor */ 471 if ((Priv_call = (struct call_list *) malloc(Ndesc *(sizeof( 472 struct call_list)))) == NULL) 473 error(E_MALLOC,NOCORE | EXIT); 474 475 i = 0; 476 Valid_addrs = 0; 477 /* first do static addrs */ 478 while ( (i < Dbf_entries) ) { 479 dp = &Dbfhead[i]; 480 if (!(dp->dbf_sflags & DFLAG)) { 481 if (add_prvaddr(dp) == 0) 482 Valid_addrs++; 483 } 484 i++; 485 } 486 i = 0; 487 /* second pass for dynamic addrs */ 488 while ( (i < Dbf_entries) ) { 489 dp = &Dbfhead[i]; 490 if (dp->dbf_sflags & DFLAG) { 491 if (add_prvaddr(dp) == 0) 492 Valid_addrs++; 493 } 494 i++; 495 } 496 497 sprintf(scratch, "Net opened, %d %s bound, %d fds free", Valid_addrs, 498 (Valid_addrs == 1) ? "address" : "addresses", 499 Ndesc-Valid_addrs-USEDFDS); 500 logmessage(scratch); 501 } 502 503 504 /* 505 * Following are some general queueing routines. The call list head contains 506 * a pointer to the head of the queue and to the tail of the queue. Normally, 507 * calls are added to the tail and removed from the head to ensure they are 508 * processed in the order received, however, because of the possible interruption 509 * of an acceptance with the resulting requeueing, it is necessary to have a 510 * way to do a "priority queueing" which inserts at the head of the queue for 511 * immediate processing 512 */ 513 514 /* 515 * queue: 516 * 517 * add calls to tail of queue 518 */ 519 520 521 void 522 queue(head, cp) 523 register struct call_list *head; 524 register struct callsave *cp; 525 { 526 DEBUG((9,"in queue")); 527 if (head->cl_tail == (struct callsave *) NULL) { 528 cp->c_np = (struct callsave *) NULL; 529 head->cl_head = head->cl_tail = cp; 530 } 531 else { 532 cp->c_np = head->cl_tail->c_np; 533 head->cl_tail->c_np = cp; 534 head->cl_tail = cp; 535 } 536 } 537 538 539 /* 540 * pqueue: 541 * 542 * priority queuer, add calls to head of queue 543 */ 544 545 void 546 pqueue(head, cp) 547 register struct call_list *head; 548 register struct callsave *cp; 549 { 550 if (head->cl_head == (struct callsave *) NULL) { 551 cp->c_np = (struct callsave *) NULL; 552 head->cl_head = head->cl_tail = cp; 553 } 554 else { 555 cp->c_np = head->cl_head; 556 head->cl_head = cp; 557 } 558 } 559 560 561 /* 562 * dequeue: 563 * 564 * remove a call from the head of queue 565 */ 566 567 568 struct callsave * 569 dequeue(head) 570 register struct call_list *head; 571 { 572 register struct callsave *ret; 573 574 DEBUG((9,"in dequeue")); 575 if (head->cl_head == (struct callsave *) NULL) { 576 #ifdef OLD 577 DEBUG((9,"cl_head = null")); 578 error(E_CANT_HAPPEN, EXIT); 579 #endif 580 DEBUG((9, "NULL return")); 581 return((struct callsave *) NULL); 582 } 583 ret = head->cl_head; 584 head->cl_head = ret->c_np; 585 if (head->cl_head == (struct callsave *) NULL) 586 head->cl_tail = (struct callsave *) NULL; 587 return(ret); 588 } 589 590 591 /* 592 * open_bind: 593 * 594 * open the network and bind the endpoint to 'name' 595 * this routine is also used by listen(), so it can't exit 596 * under all error conditions: 597 * if there are no minor devices avaliable in the network driver, 598 * open_bind returns -1. (error message will be logged). 599 * if the open fails because all file descriptors are in use, 600 * open_bind returns -2. (no message logged). This should 601 * only happen when too many private addresses are specified. 602 * if the bind fails, open_bind returns -3 (no message logged). This 603 * happens when a duplicate address is bound, and the message 604 * should be logged by the routine that calls open_bind. 605 * All other errors cause an exit. 606 * 607 * If clen is zero, transport provider picks the name and these 608 * routines (open_bind and bind) ignore name and qlen -- 609 * this option is used when binding a name for accepting a connection 610 * (not for listening.) You MUST supply a name, qlen and clen when 611 * opening/binding a name for listening. 612 * 613 * Assumptions: driver returns ENXIO when all devices are allocated. 614 */ 615 616 int 617 open_bind(name, qlen, clen, conp, adrp) 618 char *name; 619 int qlen; 620 int clen; 621 unsigned int *conp; 622 char **adrp; 623 { 624 register fd; 625 int ret; 626 627 DEBUG((9,"in open_bind, qlen=%d clen=%d conp=%d",qlen,clen,conp)); 628 while ((fd = t_open(Provider, NETOFLAG, NULL)) < 0) { 629 if (t_errno == TSYSERR) { 630 switch (errno) { 631 case EINTR: 632 continue; 633 case EMFILE: 634 return(-2); 635 break; 636 case ENXIO: 637 case ENOSR: 638 case ENOSPC: 639 case EAGAIN: 640 tli_error(E_FD1OPEN, CONTINUE); 641 logmessage("No network minor devices (ENXIO/ENOSR)"); 642 return(-1); 643 break; 644 } 645 DEBUG((9,"problem in t_open")); 646 tli_error(E_FD1OPEN, EXIT); 647 } 648 } 649 650 ret = bind(fd, name, qlen, clen, adrp); 651 DEBUG((9, "bind returns %d", ret)); 652 653 if (ret < 0) { 654 t_close(fd); 655 return(-3); 656 } 657 if (conp) 658 *conp = ret; 659 return(fd); 660 } 661 662 663 int 664 bind(fd, name, qlen, clen, ap) 665 register fd; 666 char *name; 667 int qlen; 668 register int clen; 669 char **ap; 670 { 671 register struct t_bind *req = (struct t_bind *)0; 672 register struct t_bind *ret = (struct t_bind *)0; 673 register char *p, *q; 674 unsigned int retval; 675 extern void nlsaddr2c(); 676 extern int memcmp(); 677 extern int errno; 678 679 #ifdef CHARADDR 680 char pbuf[NAMEBUFSZ + 1]; 681 #endif 682 char scratch[BUFSIZ]; 683 684 DEBUG((9,"in bind, fd = %d, clen = %d", fd, clen)); 685 686 if (clen) { 687 errno = t_errno = 0; 688 while (!(req = (struct t_bind *)t_alloc(fd,T_BIND,T_ALL)) ) { 689 if ((t_errno != TSYSERR) || (errno != EAGAIN)) 690 tli_error( E_T_ALLOC, EXIT); 691 else 692 tli_error( E_T_ALLOC, CONTINUE); 693 } 694 695 errno = t_errno = 0; 696 while (!(ret = (struct t_bind *)t_alloc(fd,T_BIND,T_ALL)) ) { 697 if ((t_errno != TSYSERR) || (errno != EAGAIN)) 698 tli_error( E_T_ALLOC, EXIT); 699 else 700 tli_error( E_T_ALLOC, CONTINUE); 701 } 702 703 if (clen > (int) req->addr.maxlen) { 704 sprintf(scratch,"Truncating name size from %d to %d", 705 clen, req->addr.maxlen); 706 logmessage(scratch); 707 clen = req->addr.maxlen; 708 } 709 710 if (clen == -1) { 711 req->addr.len = 0; 712 } 713 else { 714 (void)memcpy(req->addr.buf, name, clen); 715 req->addr.len = clen; 716 } 717 req->qlen = qlen; 718 719 #if defined(CHARADDR) && defined(DEBUGMODE) 720 (void)memcpy(pbuf, req->addr.buf, req->addr.len); 721 pbuf[req->addr.len] = (char)0; 722 DEBUG((3,"bind: fd=%d, logical name=%c%s%c, len=%d", 723 fd, '\"',pbuf, '\"', req->addr.len)); 724 #endif /* CHARADDR && DEBUGMODE */ 725 726 727 #if defined(CHARADDR) && defined(DEBUGMODE) 728 (void)memcpy(pbuf, req->addr.buf, req->addr.len); 729 pbuf[req->addr.len] = (char)0; 730 DEBUG((3,"bind: fd=%d, address=%c%s%c, len=%d", 731 fd, '\"',pbuf, '\"', req->addr.len)); 732 #endif /* CHARADDR && DEBUGMODE */ 733 734 735 } 736 737 if (t_bind(fd, req, ret)) { 738 DEBUG((1,"t_bind failed; t_errno %d errno %d", t_errno, errno)); 739 if (qlen) /* starup only */ 740 tli_error(E_T_BIND, EXIT | NOCORE); 741 /* here during normal service */ 742 if ((t_errno == TNOADDR) || ((t_errno == TSYSERR) && (errno == EAGAIN))) { 743 /* our name space is all used up */ 744 tli_error(E_T_BIND, CONTINUE); 745 t_close(fd); 746 if (clen) { 747 if ( t_free((char *)req, T_BIND) ) 748 tli_error(E_T_FREE, EXIT); 749 if ( t_free((char *)ret, T_BIND) ) 750 tli_error(E_T_FREE, EXIT); 751 } 752 return(-1); 753 } 754 /* otherwise, irrecoverable error */ 755 tli_error(E_T_BIND, EXIT | NOCORE); 756 } 757 DEBUG((9, "t_bind succeeded")); 758 759 if (clen) { 760 retval = ret->qlen; 761 if (clen == -1) { 762 /* dynamic address */ 763 *ap = (char *) malloc(((ret->addr.len) << 1) + 3); 764 if (*ap) { 765 (*ap)[0] = '\\'; 766 (*ap)[1] = 'x'; 767 nlsaddr2c(*ap+2,ret->addr.buf,(int)ret->addr.len); 768 } 769 } 770 else if ( (ret->addr.len != req->addr.len) || 771 (memcmp( req->addr.buf, ret->addr.buf, (int) req->addr.len)) ) { 772 p = (char *) malloc(((ret->addr.len) << 1) + 1); 773 q = (char *) malloc(((req->addr.len) << 1) + 1); 774 if (p && q) { 775 nlsaddr2c(p, ret->addr.buf, (int)ret->addr.len); 776 nlsaddr2c(q, req->addr.buf, (int)req->addr.len); 777 sprintf(scratch, "Requested address \\x%s", q); 778 logmessage(scratch); 779 sprintf(scratch, "Actual address \\x%s", p); 780 logmessage(scratch); 781 free(p); 782 free(q); 783 } 784 DEBUG((9, "failed to bind requested address")); 785 t_unbind(fd); 786 t_close(fd); 787 if ( t_free((char *)req, T_BIND) ) 788 tli_error(E_T_FREE, EXIT); 789 if ( t_free((char *)ret, T_BIND) ) 790 tli_error(E_T_FREE, EXIT); 791 return(-1); 792 } 793 794 if ( t_free((char *)req, T_BIND) ) 795 tli_error(E_T_FREE, EXIT); 796 797 if ( t_free((char *)ret, T_BIND) ) 798 tli_error(E_T_FREE, EXIT); 799 return(retval); 800 } 801 return((unsigned int) 0); 802 } 803 804 805 /* 806 * catch_signals: 807 * Ignore some, catch the rest. Use SIGTERM to kill me. 808 */ 809 810 sigset_t Oset; 811 struct sigaction Sigterm; 812 struct sigaction Sigcld; 813 814 catch_signals() 815 { 816 sigset_t sset; 817 sigset_t eset; 818 struct sigaction sigact; 819 extern void sigterm(); 820 821 (void) sigfillset(&sset); 822 (void) sigdelset(&sset, SIGTERM); 823 (void) sigdelset(&sset, SIGCLD); 824 (void) sigprocmask(SIG_SETMASK, &sset, &Oset); 825 826 sigact.sa_flags = 0; 827 sigact.sa_handler = sigterm; 828 sigact.sa_mask = sset; 829 sigaction(SIGTERM, &sigact, &Sigterm); 830 sigact.sa_flags = SA_NOCLDWAIT; 831 sigact.sa_handler = SIG_IGN; 832 sigact.sa_mask = sset; 833 sigaction(SIGCLD, &sigact, &Sigcld); 834 } 835 836 837 /* 838 * rst_signals: 839 * After forking but before exec'ing a server, 840 * reset all signals to original setting. 841 */ 842 843 rst_signals() 844 { 845 struct sigaction sigact; 846 847 sigaction(SIGTERM, &Sigterm, NULL); 848 sigaction(SIGCLD, &Sigcld, NULL); 849 sigprocmask(SIG_SETMASK, &Oset, NULL); 850 } 851 852 853 /* 854 * sigterm: Clean up and exit. 855 */ 856 857 void 858 sigterm() 859 { 860 extern char *shaddr; 861 extern char *sh2addr; 862 863 error(E_SIGTERM, EXIT | NORMAL | NOCORE); /* calls cleanup */ 864 } 865 866 867 /* 868 * listen: listen for and process connection requests. 869 */ 870 871 static char *dbfnewdmsg = "Using new data base file"; 872 873 listen() 874 { 875 register i; 876 register dbf_t *dbp = Dbfhead; 877 register struct pollfd *sp; 878 struct call_list *phead; /* pending head */ 879 880 DEBUG((9,"in listen, tag %s", Pmmsg.pm_tag)); 881 882 if ((Pollfds = (struct pollfd *) malloc(Ndesc * sizeof(struct pollfd))) 883 == NULL) 884 error(E_MALLOC,NOCORE | EXIT); 885 886 /* setup poll structures for sac messages and private addresses */ 887 sp = Pollfds; 888 sp->fd = Pmpipefd; 889 sp->events = POLLIN; 890 sp->revents = 0; 891 sp++; 892 for (dbp = Dbfhead; dbp && dbp->dbf_svc_code; dbp++) { 893 if (dbp->dbf_fd >= 0) { 894 sp->fd = dbp->dbf_fd; 895 DEBUG((9, "adding %d to poll struct", dbp->dbf_fd)); 896 sp->events = POLLIN; 897 sp->revents = 0; 898 sp++; 899 } 900 } 901 errno = t_errno = 0; 902 903 for (;;) { 904 DEBUG((9,"listen(): TOP of loop")); 905 906 /* +1 for Pmpipefd */ 907 if (poll(Pollfds, Valid_addrs + 1, -1) < 0) { 908 if (errno == EINTR) 909 continue; 910 /* poll error */ 911 sys_error(E_POLL, EXIT); 912 } 913 else { 914 /* incoming request or message */ 915 for (i = 0, sp = Pollfds; i < Valid_addrs + 1; i++, sp++) { 916 switch (sp->revents) { 917 case POLLIN: 918 if (sp->fd == Pmpipefd) { 919 DEBUG((9,"sac message received")); 920 check_sac_mesg(); 921 } 922 else { 923 DEBUG((9,"Connection requested ")); 924 phead = ((sp->fd) + Priv_call); 925 doevent(phead, (sp->fd)); 926 if (State == PM_ENABLED) 927 trycon(phead, (sp->fd)); 928 else 929 send_dis(phead, (sp->fd)); 930 } 931 break; 932 case 0: 933 break; 934 /* distinguish the various errors for the user */ 935 case POLLERR: 936 logmessage("poll() returned POLLERR"); 937 error(E_SYS_ERROR, EXIT | NO_MSG); 938 case POLLHUP: 939 logmessage("poll() returned POLLHUP"); 940 error(E_SYS_ERROR, EXIT | NO_MSG); 941 case POLLNVAL: 942 logmessage("poll() returned POLLNVAL"); 943 error(E_SYS_ERROR, EXIT | NO_MSG); 944 case POLLPRI: 945 logmessage("poll() returned POLLPRI"); 946 error(E_SYS_ERROR, EXIT | NO_MSG); 947 case POLLOUT: 948 logmessage("poll() returned POLLOUT"); 949 error(E_SYS_ERROR, EXIT | NO_MSG); 950 default: 951 logmessage("poll() returned unrecognized event"); 952 error(E_SYS_ERROR, EXIT | NO_MSG); 953 } 954 sp->revents = 0; 955 } 956 } 957 958 if (Readdb) { 959 DEBUG((9,"dbf file has been modified")); 960 logmessage("Re-reading database"); 961 /* have to close an fd because read_dbf needs it */ 962 close(Acceptfd); 963 if (!read_dbf(DB_REREAD)) { 964 /* MUST re-open Acceptfd to insure it is free later */ 965 dup(Passfd); 966 mod_prvaddr(); 967 } 968 else { 969 dup(Passfd); 970 logmessage(dbfnewdmsg); 971 } 972 Readdb = FALSE; 973 } 974 } 975 } 976 977 978 /* 979 * check_sac_mesg: check the pipe to see if SAC has sent a message 980 */ 981 982 void 983 check_sac_mesg() 984 { 985 int length; 986 struct sacmsg sacmsg; 987 988 DEBUG((9, "in check_sac_mesg...")); 989 990 /* read all messages out of pipe */ 991 while ((length = read(Pmpipefd, &sacmsg, sizeof(sacmsg))) != 0) { 992 if (length < 0) { 993 if (errno == EINTR) 994 continue; 995 DEBUG((9, "read of _pmpipe failed")); 996 return; 997 } 998 999 switch (sacmsg.sc_type) { 1000 case SC_STATUS: 1001 DEBUG((9, "Got SC_STATUS message")); 1002 Pmmsg.pm_type = PM_STATUS; 1003 Pmmsg.pm_state = State; 1004 break; 1005 case SC_ENABLE: 1006 DEBUG((9, "Got SC_ENABLE message")); 1007 if (State != PM_ENABLED) 1008 logmessage("New state: ENABLED"); 1009 Pmmsg.pm_type = PM_STATUS; 1010 State = PM_ENABLED; 1011 Pmmsg.pm_state = PM_ENABLED; 1012 break; 1013 case SC_DISABLE: 1014 DEBUG((9, "Got SC_DISABLE message")); 1015 if (State != PM_DISABLED) 1016 logmessage("New state: DISABLED"); 1017 Pmmsg.pm_type = PM_STATUS; 1018 State = PM_DISABLED; 1019 Pmmsg.pm_state = PM_DISABLED; 1020 break; 1021 case SC_READDB: 1022 DEBUG((9, "Got SC_READDB message")); 1023 Readdb = TRUE; 1024 Pmmsg.pm_type = PM_STATUS; 1025 Pmmsg.pm_state = State; 1026 break; 1027 default: 1028 DEBUG((9, "Got UNKNOWN message")); 1029 Pmmsg.pm_type = PM_UNKNOWN; 1030 Pmmsg.pm_state = State; 1031 logmessage("Received unknown message from sac -- ignored"); 1032 break; 1033 } 1034 DEBUG((9, "Responding with state %d", Pmmsg.pm_state)); 1035 while (write(Sacpipefd, &Pmmsg, sizeof(Pmmsg)) != sizeof(Pmmsg)) { 1036 if (errno == EINTR) 1037 continue; 1038 DEBUG((9, "sanity response failed")); 1039 break; 1040 } 1041 } 1042 } 1043 1044 1045 /* 1046 * doevent: handle an asynchronous event 1047 */ 1048 1049 doevent(phead, fd) 1050 struct call_list *phead; 1051 int fd; 1052 { 1053 static struct t_discon *disc; 1054 register struct callsave *current; 1055 register struct t_call *call; 1056 char scratch[BUFSIZ]; 1057 1058 DEBUG((9, "in doevent")); 1059 switch (t_look(fd)) { 1060 case 0: 1061 sys_error(E_POLL, EXIT); 1062 /* no return */ 1063 case T_LISTEN: 1064 DEBUG((9, "case t_listen ")); 1065 current = dequeue(Free_call_p); 1066 call = current->c_cp; 1067 if (t_listen(fd, call) < 0) { 1068 tli_error(E_T_LISTEN, CONTINUE); 1069 clr_call(call); 1070 queue(Free_call_p, current); 1071 return; 1072 } 1073 queue(phead, current); 1074 DEBUG((9, "incoming call seq # %d", call->sequence)); 1075 break; 1076 case T_DISCONNECT: 1077 DEBUG((9, "case t_disconnect")); 1078 if (disc == NULL) { 1079 while (!(disc = (struct t_discon *)t_alloc(fd, T_DIS, T_ALL)) ) { 1080 if (t_errno == TBADF) 1081 DEBUG((9,"listen - fd not transport end point")); 1082 if ((t_errno != TSYSERR) || (errno != EAGAIN)) 1083 tli_error(E_T_ALLOC, EXIT); 1084 else 1085 tli_error(E_T_ALLOC, CONTINUE); 1086 } 1087 } 1088 if (t_rcvdis(fd, disc) < 0) { 1089 tli_error(E_T_RCVDIS, EXIT); 1090 /* no return */ 1091 } 1092 sprintf(scratch, "Disconnect on fd %d, seq # %d", fd, disc->sequence); 1093 logmessage(scratch); 1094 DEBUG((9, "incoming disconnect seq # %d", disc->sequence)); 1095 pitchcall(phead, disc); 1096 break; 1097 default: 1098 DEBUG((9, "case default")); 1099 tli_error(E_T_LOOK, CONTINUE); 1100 break; 1101 1102 } 1103 } 1104 1105 /* 1106 * send_dis: send a disconnect 1107 * called when we are in state PM_DISABLED 1108 */ 1109 1110 send_dis(phead, fd) 1111 struct call_list *phead; 1112 int fd; 1113 { 1114 register struct t_call *call; 1115 register struct callsave *current; 1116 char scratch[BUFSIZ]; 1117 1118 DEBUG((9, "sending disconnect")); 1119 while (!EMPTYLIST(phead)) { 1120 current = dequeue(phead); 1121 call = current->c_cp; 1122 if (t_snddis(fd, call) < 0) { 1123 if (t_errno == TLOOK) { 1124 DEBUG((9, "collision during snddis")); 1125 pqueue(phead, current); 1126 return; 1127 } 1128 else 1129 tli_error(E_T_SNDDIS, CONTINUE); 1130 } 1131 sprintf(scratch, "Incoming call while disabled: fd %d, seq %d", fd, call->sequence); 1132 logmessage(scratch); 1133 clr_call(call); 1134 queue(Free_call_p, current); 1135 } 1136 return; 1137 } 1138 1139 1140 /* 1141 * trycon: try to accept a connection 1142 */ 1143 1144 trycon(phead, fd) 1145 struct call_list *phead; 1146 int fd; 1147 { 1148 register struct callsave *current; 1149 register struct t_call *call; 1150 int i; 1151 pid_t pid; 1152 dbf_t *dbp; 1153 char scratch[BUFSIZ]; 1154 extern dbf_t *getentry(); 1155 1156 DEBUG((9, "in trycon")); 1157 while (!EMPTYLIST(phead)) { 1158 current = dequeue(phead); 1159 call = current->c_cp; 1160 1161 if ((dbp = getentry(fd)) == NULL) { 1162 sprintf(scratch, "No service bound to incoming fd %d: call disconnected", fd); 1163 logmessage(scratch); 1164 t_snddis(fd, call); 1165 clr_call(call); 1166 queue(Free_call_p, current); 1167 continue; 1168 } 1169 1170 if (dbp->dbf_flags & DBF_OFF) { 1171 sprintf(scratch, "Request for service on fd %d denied: disabled", fd); 1172 logmessage(scratch); 1173 t_snddis(fd, call); 1174 clr_call(call); 1175 queue(Free_call_p, current); 1176 continue; 1177 } 1178 1179 DEBUG((9, "try to accept #%d", call->sequence)); 1180 SPLhi(); 1181 close(Acceptfd); 1182 if ((Acceptfd = open_bind(NULL, 0, 0, (unsigned int *) 0, NULL)) != 0) { 1183 error(E_OPENBIND, CONTINUE); 1184 clr_call(call); 1185 queue(Free_call_p, current); 1186 continue; /* let transport provider generate disconnect */ 1187 } 1188 SPLlo(); 1189 if (t_accept(fd, Acceptfd, call) < 0) { 1190 if (t_errno == TLOOK) { 1191 t_close(Acceptfd); 1192 SPLhi(); 1193 if (dup(Passfd) != 0) 1194 logmessage("Trouble duping fd 0"); 1195 SPLlo(); 1196 logmessage("Incoming call during t_accept -- queueing current call"); 1197 DEBUG((9, "save call #%d", call->sequence)); 1198 pqueue(phead, current); 1199 return; 1200 } 1201 else { 1202 t_close(Acceptfd); 1203 SPLhi(); 1204 if (dup(Passfd) != 0) 1205 logmessage("Trouble duping fd 0"); 1206 SPLlo(); 1207 tli_error(E_T_ACCEPT, CONTINUE); 1208 clr_call(call); 1209 queue(Free_call_p, current); 1210 continue; 1211 } 1212 } 1213 1214 sprintf(scratch, "Connect: fd %d, svctag %s, seq %d, type %s", 1215 fd, dbp->dbf_svc_code, call->sequence, 1216 (dbp->dbf_sflags & PFLAG) ? "passfd" : "exec"); 1217 logmessage(scratch); 1218 1219 DEBUG((9, "Accepted call %d", call->sequence)); 1220 1221 if (dbp->dbf_sflags & PFLAG) { 1222 1223 close(Passfd); 1224 1225 if (pushmod(Acceptfd, dbp->dbf_modules)) { 1226 sprintf(scratch, "Could not push modules: %s", dbp->dbf_modules); 1227 logmessage(scratch); 1228 goto cleanup; 1229 } 1230 1231 /* doconfig needs a file descriptor, so use Passfd */ 1232 DEBUG((9, "Running doconfig on %s", dbp->dbf_svc_code)); 1233 if ((i = doconfig(Acceptfd, dbp->dbf_svc_code, NOASSIGN|NORUN)) != 0) { 1234 DEBUG((9, "doconfig exited with code %d", i)); 1235 sprintf(scratch, "doconfig failed on line %d of script %s", i, dbp->dbf_svc_code); 1236 logmessage(scratch); 1237 goto cleanup; 1238 } 1239 1240 /* open pipe to pass fd through */ 1241 if ((Passfd = open(dbp->dbf_cmd_line, O_WRONLY)) < 0) { 1242 /* bad pipe? */ 1243 sprintf(scratch,"Open failed: %s", dbp->dbf_cmd_line); 1244 logmessage(scratch); 1245 goto cleanup; 1246 } 1247 1248 if (ioctl(Passfd, I_SENDFD, Acceptfd) < 0) { 1249 /* clean up call, log error */ 1250 sprintf(scratch,"Passfd failed: %s", dbp->dbf_cmd_line); 1251 logmessage(scratch); 1252 } 1253 cleanup: 1254 /* clean up this call */ 1255 clr_call(call); 1256 t_close(Acceptfd); 1257 close(Passfd); 1258 Acceptfd = open("/dev/null", O_RDWR); 1259 Passfd = dup(Acceptfd); 1260 queue(Free_call_p, current); 1261 } 1262 else { 1263 if ((pid = fork()) < 0) 1264 log(E_FORK_SERVICE); 1265 else if (!pid) { 1266 setpgrp(); 1267 /* so log files are correct */ 1268 Pid = getpid(); 1269 1270 if (senviron(call)) { 1271 logmessage("Can't expand server's environment"); 1272 } 1273 1274 start_server(Acceptfd, dbp); 1275 #ifdef COREDUMP 1276 abort(); 1277 #endif 1278 exit(1); /* server failed, don't log */ 1279 /* no return */ 1280 } 1281 /* only parent gets here */ 1282 clr_call(call); 1283 t_close(Acceptfd); 1284 queue(Free_call_p, current); 1285 SPLhi(); 1286 if (dup(Passfd) != 0) 1287 logmessage("Trouble duping fd 0"); 1288 SPLlo(); 1289 } 1290 } 1291 } 1292 1293 /* 1294 * common code to start a server process (for any service) 1295 * The first argument in argv is the full pathname of server. 1296 * Before exec-ing the server, the caller's 1297 * logical address, opt and udata are addded to the environment. 1298 */ 1299 1300 static char homeenv[BUFSIZ]; 1301 static char pathenv[BUFSIZ]; 1302 1303 start_server(netfd, dbp) 1304 int netfd; 1305 register dbf_t *dbp; 1306 { 1307 char *path; 1308 char **argvp; 1309 extern char **environ; 1310 extern char **mkdbfargv(); 1311 register struct passwd *pwdp; 1312 struct group *grpp; 1313 char msgbuf[256]; 1314 int i; 1315 1316 1317 argvp = mkdbfargv(dbp); 1318 path = *argvp; 1319 1320 /* set up stdout and stderr before pushing optional modules */ 1321 /* this child doesn't need access to _sacpipe and _pmpipe */ 1322 1323 (void) close(Sacpipefd); 1324 (void) close(Pmpipefd); 1325 1326 if (dbp->dbf_flags & DBF_UTMP) { 1327 pid_t tmp; 1328 struct stat sbuf; 1329 char device[20]; 1330 char dummy[PMTAGSIZE + 1]; 1331 struct utmpx utline; 1332 1333 /* 1334 * create a utmpx entry -- 1335 * we do an extra fork here to make init this process's 1336 * parent. this lets init clean up the utmpx entry when 1337 * this proc dies. 1338 * 1339 * the utmpx routines need a file descriptor! 1340 */ 1341 1342 DEBUG((9, "Creating a utmpx entry for this service ")); 1343 if ((tmp = fork()) < 0) { 1344 logmessage("Can't fork to create utmpx entry"); 1345 exit(2); 1346 } 1347 if (tmp) 1348 exit(0); /* kill parent */ 1349 1350 /* 1351 * child continues processing, creating utmp and exec'ing 1352 * the service 1353 */ 1354 1355 setpgrp(); 1356 if (fstat(0, &sbuf) < 0) { 1357 logmessage("Stat failed on fd 0: no line field " 1358 "available for utmpx entry"); 1359 *device = '\0'; 1360 } 1361 else { 1362 if (minor(sbuf.st_rdev) < 100) 1363 sprintf(device, "%.9s%02d", Minor_prefix, 1364 minor(sbuf.st_rdev)); 1365 else 1366 sprintf(device, "%.8s%03d", Minor_prefix, 1367 minor(sbuf.st_rdev)); 1368 DEBUG((9, "Device: %s", device)); 1369 } 1370 /* 1371 * prepend a "." so this can be distinguished as a "funny" 1372 * utmpx entry that may never get a DEAD_PROCESS entry in 1373 * the wtmpx file. 1374 */ 1375 sprintf(dummy, ".%s", Mytag); 1376 /* XXX - utmp - fix login name length */ 1377 strncpy(utline.ut_user, dummy, sizeof (utline.ut_user) - 1); 1378 sprintf(utline.ut_id, "ls%c%c", SC_WILDC, SC_WILDC); 1379 strncpy(utline.ut_line, device, sizeof (utline.ut_line) - 1); 1380 utline.ut_pid = getpid(); 1381 utline.ut_type = USER_PROCESS; 1382 utline.ut_exit.e_termination = 0; 1383 utline.ut_exit.e_exit = 0; 1384 utline.ut_xtime = (time_t) time((time_t *)0); 1385 makeutx(&utline); 1386 } 1387 1388 if (dup(0) != 1 || dup(0) != 2) { 1389 logmessage("Dup of fd 0 failed"); 1390 exit(2); /* server, don't log */ 1391 } 1392 1393 1394 if (pushmod(netfd, dbp->dbf_modules)) { 1395 logmessage("Can't push server's modules: exit"); 1396 exit(2); /* server, don't log */ 1397 } 1398 1399 rst_signals(); 1400 1401 DEBUG((9, "Running doconfig on %s", dbp->dbf_svc_code)); 1402 if ((i = doconfig(Acceptfd, dbp->dbf_svc_code, 0)) != 0) { 1403 DEBUG((9, "doconfig exited with code %d", i)); 1404 sprintf(msgbuf, "doconfig failed on line %d of script %s", i, dbp->dbf_svc_code); 1405 logmessage(msgbuf); 1406 exit(2); 1407 } 1408 1409 if ((pwdp = getpwnam(dbp->dbf_id)) == NULL) { 1410 sprintf(msgbuf, "Missing or bad passwd entry for <%s>",dbp->dbf_id); 1411 logmessage(msgbuf); 1412 exit(2); /* server, don't log */ 1413 } 1414 1415 if (setgid(pwdp->pw_gid)) { 1416 if ((grpp = getgrgid(pwdp->pw_gid)) == NULL) { 1417 sprintf(msgbuf, "No group entry for %ld", pwdp->pw_gid); 1418 logmessage(msgbuf); 1419 exit(2); /* server, don't log */ 1420 } 1421 sprintf(msgbuf, "Cannot set group id to %s", grpp->gr_name); 1422 logmessage(msgbuf); 1423 exit(2); /* server, don't log */ 1424 } 1425 1426 if (setuid(pwdp->pw_uid)) { 1427 sprintf(msgbuf, "Cannot set user id to %s", dbp->dbf_id); 1428 logmessage(msgbuf); 1429 exit(2); /* server, don't log */ 1430 } 1431 1432 if (chdir(pwdp->pw_dir)) { 1433 sprintf(msgbuf, "Cannot chdir to %s", pwdp->pw_dir); 1434 logmessage(msgbuf); 1435 exit(2); /* server, don't log */ 1436 } 1437 1438 1439 DEBUG((9, "New uid %ld New gid %ld", getuid(), getgid())); 1440 1441 sprintf(homeenv, "HOME=%s", pwdp->pw_dir); 1442 putenv(homeenv); 1443 if (pwdp->pw_uid) 1444 sprintf(pathenv, "PATH=/usr/bin:"); 1445 else 1446 sprintf(pathenv, "PATH=/usr/sbin:/usr/bin"); 1447 putenv(pathenv); 1448 1449 endpwent(); 1450 1451 execve(path, argvp, environ); 1452 1453 /* exec returns only on failure! */ 1454 1455 logmessage("ERROR: could not exec server"); 1456 sys_error(E_SYS_ERROR, CONTINUE); 1457 return(-1); 1458 } 1459 1460 1461 /* 1462 * senviron: Update environment before exec-ing the server: 1463 * The callers logical address is placed in the 1464 * environment in hex/ascii character representation. 1465 * 1466 * Note: no need to free the malloc'ed buffers since this process 1467 * will either exec or exit. 1468 */ 1469 1470 static char provenv[2*PATHSIZE]; 1471 static char prefenv[2*PATHSIZE]; 1472 1473 int 1474 senviron(call) 1475 register struct t_call *call; 1476 { 1477 register char *p; 1478 extern void nlsaddr2c(); 1479 extern char *getenv(); 1480 1481 1482 /* 1483 * The following code handles the case where the listener was started with 1484 * no environment. If so, supply a reasonable default path. Parent already 1485 * set TZ on startup if it wasn't, so don't need to do it here. 1486 */ 1487 1488 if (getenv("PATH") == NULL) 1489 putenv("PATH=/usr/sbin:/usr/bin"); 1490 1491 if ((p = (char *)malloc(((call->addr.len)<<1) + 18)) == NULL) 1492 return(-1); 1493 strcpy(p, NLSADDR); 1494 strcat(p, "="); 1495 nlsaddr2c(p + strlen(p), call->addr.buf, (int)call->addr.len); 1496 DEBUG((7, "Adding %s to server's environment", p)); 1497 putenv(p); 1498 1499 if ((p = (char *)malloc(((call->opt.len)<<1) + 16)) == NULL) 1500 return(-1); 1501 strcpy(p, NLSOPT); 1502 strcat(p, "="); 1503 nlsaddr2c(p + strlen(p), call->opt.buf, (int)call->opt.len); 1504 DEBUG((7, "Adding %s to server's environment", p)); 1505 putenv(p); 1506 1507 p = provenv; 1508 strcpy(p, NLSPROVIDER); 1509 strcat(p, "="); 1510 strcat(p, Netspec); 1511 DEBUG((7, "Adding %s to environment", p)); 1512 putenv(p); 1513 1514 /* 1515 * MPREFIX is NEW for SVR4.0. It tells the nlps_server what to use 1516 * as a minor device prefix. THIS SHOULD BE DOCUMENTED! 1517 */ 1518 p = prefenv; 1519 strcpy(p, "MPREFIX"); 1520 strcat(p, "="); 1521 strcat(p, Minor_prefix); 1522 DEBUG((7, "Adding %s to environment", p)); 1523 putenv(p); 1524 1525 if ((p = (char *)malloc(((call->udata.len)<<1) + 20)) == NULL) 1526 return(-1); 1527 strcpy(p, NLSUDATA); 1528 strcat(p, "="); 1529 if ((int)call->udata.len >= 0) 1530 nlsaddr2c(p + strlen(p), call->udata.buf, (int)call->udata.len); 1531 putenv(p); 1532 return (0); 1533 } 1534 1535 1536 /* 1537 * parse: Parse TZ= string like init does for consistency 1538 * Work on string in place since result will 1539 * either be the same or shorter. 1540 */ 1541 1542 char * 1543 parse(s) 1544 char *s; 1545 { 1546 register char *p; 1547 register char *tp; 1548 char scratch[BUFSIZ]; 1549 int delim; 1550 1551 tp = p = s + strlen("TZ="); /* skip TZ= in parsing */ 1552 if ((*p == '"') || (*p == '\'')) { 1553 /* it is quoted */ 1554 delim = *p++; 1555 for (;;) { 1556 if (*p == '\0') { 1557 /* etc/TIMEZONE ill-formed, go without TZ */ 1558 sprintf(scratch, "%s ill-formed", TIMEZONE); 1559 logmessage(scratch); 1560 strcpy(s, "TZ="); 1561 return(s); 1562 } 1563 if (*p == delim) { 1564 *tp = '\0'; 1565 return(s); 1566 } 1567 else { 1568 *tp++ = *p++; 1569 } 1570 } 1571 } 1572 else { /* look for comment or trailing whitespace */ 1573 for ( ; *p && !isspace(*p) && *p != '#'; ++p) 1574 ; 1575 /* if a comment or trailing whitespace, trash it */ 1576 if (*p) { 1577 *p = '\0'; 1578 } 1579 return(s); 1580 } 1581 } 1582 1583 1584 /* 1585 * clr_call: clear out a call structure 1586 */ 1587 1588 clr_call(call) 1589 struct t_call *call; 1590 { 1591 call->sequence = 0; 1592 call->addr.len = 0; 1593 call->opt.len = 0; 1594 call->udata.len = 0; 1595 memset(call->addr.buf, 0, (int)call->addr.maxlen); 1596 memset(call->opt.buf, 0, (int)call->opt.maxlen); 1597 memset(call->udata.buf, 0, (int)call->udata.maxlen); 1598 } 1599 1600 1601 /* 1602 * pitchcall: remove call from pending list 1603 */ 1604 1605 pitchcall(pending, discon) 1606 struct call_list *pending; 1607 struct t_discon *discon; 1608 { 1609 register struct callsave *p, *oldp; 1610 1611 DEBUG((9, "pitching call, sequence # is %d", discon->sequence)); 1612 if (EMPTYLIST(pending)) { 1613 discon->sequence = -1; 1614 return; 1615 } 1616 p = pending->cl_head; 1617 oldp = (struct callsave *) NULL; 1618 while (p) { 1619 if (p->c_cp->sequence == discon->sequence) { 1620 if (oldp == (struct callsave *) NULL) { 1621 pending->cl_head = p->c_np; 1622 if (pending->cl_head == (struct callsave *) NULL) { 1623 pending->cl_tail = (struct callsave *) NULL; 1624 } 1625 } 1626 else if (p == pending->cl_tail) { 1627 oldp->c_np = p->c_np; 1628 pending->cl_tail = oldp; 1629 } 1630 else { 1631 oldp->c_np = p->c_np; 1632 } 1633 clr_call(p->c_cp); 1634 queue(Free_call_p, p); 1635 discon->sequence = -1; 1636 return; 1637 } 1638 oldp = p; 1639 p = p->c_np; 1640 } 1641 logmessage("received disconnect with no pending call"); 1642 discon->sequence = -1; 1643 return; 1644 } 1645 1646 /* 1647 * add_prvaddr: open and bind the private address specified in the database 1648 * entry passed into the routine. Update the maxcon and fd 1649 * entries in the database structure 1650 * 1651 * This routine is very sloppy with malloc'ed memory, but addresses 1652 * shouldn't ever change enough for this to matter. 1653 */ 1654 1655 add_prvaddr(dbp) 1656 dbf_t *dbp; 1657 { 1658 extern char *t_alloc(); 1659 register int j; 1660 struct call_list *temp_pend; 1661 register struct callsave *tmp; 1662 char scratch[BUFSIZ]; 1663 int bindfd; 1664 extern struct netbuf *stoa(); 1665 char str[NAMEBUFSZ]; 1666 char *lstr = str; 1667 struct netbuf netbuf; 1668 int maxcon; 1669 char *ap; 1670 int clen; 1671 1672 DEBUG((9,"in add_prvaddr, addr %s, svc %s", 1673 (dbp->dbf_sflags & DFLAG) ? "DYNAMIC" : dbp->dbf_prv_adr, 1674 dbp->dbf_svc_code)); 1675 netbuf.buf = NULL; 1676 netbuf.maxlen = 0; 1677 netbuf.len = 0; 1678 if (!(dbp->dbf_sflags & DFLAG)) { 1679 strcpy(lstr, dbp->dbf_prv_adr); 1680 1681 /* call stoa - convert from rfs address to netbuf */ 1682 1683 if (stoa(lstr, &netbuf) == (struct netbuf *)NULL) { 1684 DEBUG((9,"stoa returned null, errno = %d\n",errno)); 1685 error(1, E_MALLOC); 1686 return(-1); 1687 } 1688 clen = netbuf.len; 1689 } 1690 else { 1691 clen = -1; 1692 } 1693 if ((bindfd = open_bind(netbuf.buf, MAXCON, clen, &maxcon, &ap)) < 0) { 1694 switch (bindfd) { 1695 case -1: 1696 return(-1); 1697 break; 1698 case -2: 1699 sprintf(scratch, " Service %s ignored: out of file descriptors", dbp->dbf_svc_code); 1700 logmessage(scratch); 1701 return(-1); 1702 break; 1703 case -3: 1704 sprintf(scratch, " Service %s ignored: unable to bind requested address", dbp->dbf_svc_code); 1705 logmessage(scratch); 1706 return(-1); 1707 break; 1708 default: 1709 error(E_OPENBIND, EXIT); 1710 } 1711 } 1712 if (clen == -1) { 1713 sprintf(scratch,"Service %s: fd %d dynamic addr %s", dbp->dbf_svc_code, bindfd, ap); 1714 dbp->dbf_prv_adr = ap; 1715 } 1716 else { 1717 sprintf(scratch,"Service %s: fd %d addr %s", dbp->dbf_svc_code, bindfd, dbp->dbf_prv_adr); 1718 } 1719 logmessage(scratch); 1720 rpc_register(dbp); 1721 temp_pend = Priv_call + bindfd; 1722 dbp->dbf_fd = bindfd; 1723 dbp->dbf_maxcon = maxcon; 1724 temp_pend->cl_head = (struct callsave *) NULL; 1725 temp_pend->cl_tail = (struct callsave *) NULL; 1726 for (j=0; j < maxcon; ++j) { 1727 if ((tmp = (struct callsave *) malloc(sizeof(struct callsave))) == NULL) { 1728 error (E_MALLOC, NOCORE | EXIT); 1729 } 1730 if ((tmp->c_cp = (struct t_call *) t_alloc(bindfd, T_CALL, 1731 T_ALL)) == NULL) { 1732 tli_error(E_T_ALLOC,EXIT); 1733 } 1734 queue(Free_call_p, tmp); 1735 } 1736 return(0); 1737 } 1738 1739 /* 1740 * mod_prvaddr -- after re-reading the database, take appropriate action for 1741 * new, deleted, or changed addresses. 1742 */ 1743 mod_prvaddr() 1744 { 1745 dbf_t *entry_p; 1746 dbf_t *oldentry_p; 1747 char scratch[BUFSIZ]; 1748 dbf_t *svc_code_match(); 1749 int bound; 1750 struct pollfd *sp; 1751 1752 DEBUG((9, "in mod_prvaddr...")); 1753 /* 1754 * for each entry in the new table, check for a svc code match. 1755 * if there is a svc code match and the address matches, all we 1756 * need to do is update the new table. if the addresses are 1757 * different, we need to remove the old one and replace it. 1758 */ 1759 for (entry_p = Newdbf; entry_p && entry_p->dbf_svc_code; entry_p++) { 1760 if ((oldentry_p = svc_code_match(entry_p->dbf_svc_code)) != NULL) { 1761 /* matched svc code. see if address matches. */ 1762 DEBUG((9, "MATCHED service code")); 1763 if ((strcmp(oldentry_p->dbf_prv_adr, entry_p->dbf_prv_adr) == 0) || ((oldentry_p->dbf_sflags & DFLAG) && (entry_p->dbf_sflags & DFLAG))) { 1764 DEBUG((9, "SAME addresses, old %s, new %s", 1765 oldentry_p->dbf_prv_adr, entry_p->dbf_prv_adr)); 1766 /* update new table with fd, set old fd to -1 */ 1767 DEBUG((9, "Old fd %d", oldentry_p->dbf_fd)); 1768 entry_p->dbf_fd = oldentry_p->dbf_fd; 1769 entry_p->dbf_maxcon = oldentry_p->dbf_maxcon; 1770 oldentry_p->dbf_fd = -1; 1771 if ((oldentry_p->dbf_sflags & DFLAG) && (entry_p->dbf_sflags & DFLAG)) { 1772 entry_p->dbf_prv_adr = oldentry_p->dbf_prv_adr; 1773 } 1774 if (entry_p->dbf_fd != -1) { 1775 sprintf(scratch, "Service %s: fd %d addr %s", 1776 entry_p->dbf_svc_code, entry_p->dbf_fd, 1777 entry_p->dbf_prv_adr); 1778 logmessage(scratch); 1779 } 1780 if ((oldentry_p->dbf_version != entry_p->dbf_version) || (oldentry_p->dbf_prognum != entry_p->dbf_prognum)) { 1781 rpc_unregister(oldentry_p); 1782 rpc_register(entry_p); 1783 } 1784 } 1785 } 1786 } 1787 1788 /* now unbind the remaining addresses in the old table (fd != -1) */ 1789 1790 for (oldentry_p = Dbfhead; oldentry_p && oldentry_p->dbf_svc_code; oldentry_p++) { 1791 if (oldentry_p->dbf_fd != -1) { 1792 DEBUG((9, "deleting %s", oldentry_p->dbf_svc_code)); 1793 if (del_prvaddr(oldentry_p) == 0) 1794 Valid_addrs--; 1795 } 1796 } 1797 1798 /* now bind all of the new addresses (fd == -1) */ 1799 /* 1800 * this tries to bind any addresses that failed to bind successfully 1801 * when the address changed. This means that if a service is moved to 1802 * an address that is being deleted, the first attempt to bind it will 1803 * fail, the old address will be removed, and this bind will succeed 1804 */ 1805 1806 /* first the static addrs */ 1807 for (entry_p = Newdbf; entry_p && entry_p->dbf_svc_code; entry_p++) { 1808 if ((entry_p->dbf_fd == -1) && (!(entry_p->dbf_sflags & DFLAG))) { 1809 DEBUG((9, "adding %s", entry_p->dbf_svc_code)); 1810 if (add_prvaddr(entry_p) == 0) 1811 Valid_addrs++; 1812 } 1813 } 1814 /* then the dynamic addrs */ 1815 for (entry_p = Newdbf; entry_p && entry_p->dbf_svc_code; entry_p++) { 1816 if ((entry_p->dbf_fd == -1) && (entry_p->dbf_sflags & DFLAG)) { 1817 DEBUG((9, "adding %s", entry_p->dbf_svc_code)); 1818 if (add_prvaddr(entry_p) == 0) 1819 Valid_addrs++; 1820 } 1821 } 1822 1823 /* free old database, set up new pollfd table, and we're done */ 1824 1825 free(Dbfhead); 1826 free(Server_cmd_lines); 1827 Dbfhead = Newdbf; 1828 Newdbf = NULL; 1829 Server_cmd_lines = New_cmd_lines; 1830 sprintf(scratch, "Re-read complete, %d %s bound, %d fds free", Valid_addrs, 1831 (Valid_addrs == 1) ? "address" : "addresses", 1832 Ndesc-Valid_addrs-USEDFDS); 1833 logmessage(scratch); 1834 1835 /* Pollfds[0] is for _pmpipe */ 1836 sp = &Pollfds[1]; 1837 for (entry_p = Dbfhead; entry_p && entry_p->dbf_svc_code; entry_p++) { 1838 if (entry_p->dbf_fd >= 0) { 1839 sp->fd = entry_p->dbf_fd; 1840 DEBUG((9, "adding %d to poll struct", entry_p->dbf_fd)); 1841 sp->events = POLLIN; 1842 sp->revents = 0; 1843 sp++; 1844 } 1845 } 1846 } 1847 1848 /* 1849 * unbind the address, close the file descriptor, and free call structs 1850 */ 1851 1852 del_prvaddr(dbp) 1853 dbf_t *dbp; 1854 { 1855 struct callsave *tmp; 1856 struct call_list *q; 1857 struct t_call *call; 1858 int i; 1859 char scratch[BUFSIZ]; 1860 1861 DEBUG((9, "in del_prvaddr...")); 1862 rpc_unregister(dbp); 1863 if (dbp->dbf_fd < 0) 1864 return -1; 1865 1866 q = Priv_call + dbp->dbf_fd; 1867 i = 0; 1868 1869 /* delete pending calls */ 1870 while ((tmp = dequeue(q)) != NULL) { 1871 i++; 1872 call = tmp->c_cp; 1873 t_snddis(dbp->dbf_fd, call); 1874 t_free((char *)call, T_CALL); 1875 free(tmp); 1876 } 1877 1878 /* delete free call structs we don't need */ 1879 for ( ; i < dbp->dbf_maxcon; i++) { 1880 tmp = dequeue(Free_call_p); 1881 t_free((char *)tmp->c_cp, T_CALL); 1882 free(tmp); 1883 } 1884 1885 t_unbind(dbp->dbf_fd); 1886 t_close(dbp->dbf_fd); 1887 sprintf(scratch, "Unbind %s: fd %d addr %s", dbp->dbf_svc_code, 1888 dbp->dbf_fd, dbp->dbf_prv_adr); 1889 logmessage(scratch); 1890 dbp->dbf_fd = -1; 1891 return 0; 1892 } 1893 1894 1895 /* 1896 * look through the old database file to see if this service code matches 1897 * one already present 1898 */ 1899 1900 dbf_t * 1901 svc_code_match(new_code) 1902 char *new_code; 1903 { 1904 dbf_t *dbp; 1905 1906 for (dbp = Dbfhead; dbp && dbp->dbf_svc_code; dbp++) { 1907 if (strcmp(dbp->dbf_svc_code, new_code) == 0) 1908 return(dbp); 1909 } 1910 return((dbf_t *)NULL); 1911 } 1912 1913 1914 /* 1915 * register an rpc service with rpcbind 1916 */ 1917 1918 void 1919 rpc_register(dbp) 1920 register dbf_t *dbp; 1921 { 1922 char str[NAMEBUFSZ]; 1923 char scratch[BUFSIZ]; 1924 char *lstr = str; 1925 struct netbuf netbuf; 1926 extern struct netbuf *stoa(); 1927 extern int errno; 1928 1929 DEBUG((9, "in rpc_register")); 1930 if (dbp->dbf_prognum == -1 || dbp->dbf_version == -1) 1931 /* not an rpc service */ 1932 return; 1933 1934 rpc_unregister(dbp); 1935 netbuf.buf = NULL; 1936 netbuf.maxlen = 0; 1937 netbuf.len = 0; 1938 strcpy(lstr, dbp->dbf_prv_adr); 1939 if (stoa(lstr, &netbuf) == (struct netbuf *)NULL) { 1940 DEBUG((9,"stoa returned null, errno = %d\n",errno)); 1941 error(1, E_MALLOC); 1942 return; 1943 } 1944 if (rpcb_set(dbp->dbf_prognum, dbp->dbf_version, Netconf, &netbuf)) { 1945 sprintf(scratch," registered with rpcbind, prognum %d version %d", dbp->dbf_prognum, dbp->dbf_version); 1946 logmessage(scratch); 1947 } 1948 else { 1949 logmessage("rpcb_set failed, service not registered with rpcbind"); 1950 } 1951 return; 1952 } 1953 1954 1955 /* 1956 * unregister an rpc service with rpcbind 1957 */ 1958 1959 void 1960 rpc_unregister(dbp) 1961 register dbf_t *dbp; 1962 { 1963 DEBUG((9, "in rpc_unregister")); 1964 if (dbp->dbf_prognum == -1 || dbp->dbf_version == -1) 1965 /* not an rpc service */ 1966 return; 1967 (void) rpcb_unset(dbp->dbf_prognum, dbp->dbf_version, Netconf); 1968 } 1969