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