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 case POLLHUP: 960 logmessage("poll() returned POLLHUP"); 961 error(E_SYS_ERROR, EXIT | NO_MSG); 962 case POLLNVAL: 963 logmessage("poll() returned POLLNVAL"); 964 error(E_SYS_ERROR, EXIT | NO_MSG); 965 case POLLPRI: 966 logmessage("poll() returned POLLPRI"); 967 error(E_SYS_ERROR, EXIT | NO_MSG); 968 case POLLOUT: 969 logmessage("poll() returned POLLOUT"); 970 error(E_SYS_ERROR, EXIT | NO_MSG); 971 default: 972 logmessage("poll() returned unrecognized event"); 973 error(E_SYS_ERROR, EXIT | NO_MSG); 974 } 975 sp->revents = 0; 976 } 977 } 978 979 if (Readdb) { 980 DEBUG((9,"dbf file has been modified")); 981 logmessage("Re-reading database"); 982 /* have to close an fd because read_dbf needs it */ 983 close(Acceptfd); 984 if (!read_dbf(DB_REREAD)) { 985 /* MUST re-open Acceptfd to insure it is free later */ 986 dup(Passfd); 987 mod_prvaddr(); 988 } 989 else { 990 dup(Passfd); 991 logmessage(dbfnewdmsg); 992 } 993 Readdb = FALSE; 994 } 995 } 996 } 997 998 999 /* 1000 * check_sac_mesg: check the pipe to see if SAC has sent a message 1001 */ 1002 1003 void 1004 check_sac_mesg() 1005 { 1006 int length; 1007 struct sacmsg sacmsg; 1008 1009 DEBUG((9, "in check_sac_mesg...")); 1010 1011 /* read all messages out of pipe */ 1012 while ((length = read(Pmpipefd, &sacmsg, sizeof(sacmsg))) != 0) { 1013 if (length < 0) { 1014 if (errno == EINTR) 1015 continue; 1016 DEBUG((9, "read of _pmpipe failed")); 1017 return; 1018 } 1019 1020 switch (sacmsg.sc_type) { 1021 case SC_STATUS: 1022 DEBUG((9, "Got SC_STATUS message")); 1023 Pmmsg.pm_type = PM_STATUS; 1024 Pmmsg.pm_state = State; 1025 break; 1026 case SC_ENABLE: 1027 DEBUG((9, "Got SC_ENABLE message")); 1028 if (State != PM_ENABLED) 1029 logmessage("New state: ENABLED"); 1030 Pmmsg.pm_type = PM_STATUS; 1031 State = PM_ENABLED; 1032 Pmmsg.pm_state = PM_ENABLED; 1033 break; 1034 case SC_DISABLE: 1035 DEBUG((9, "Got SC_DISABLE message")); 1036 if (State != PM_DISABLED) 1037 logmessage("New state: DISABLED"); 1038 Pmmsg.pm_type = PM_STATUS; 1039 State = PM_DISABLED; 1040 Pmmsg.pm_state = PM_DISABLED; 1041 break; 1042 case SC_READDB: 1043 DEBUG((9, "Got SC_READDB message")); 1044 Readdb = TRUE; 1045 Pmmsg.pm_type = PM_STATUS; 1046 Pmmsg.pm_state = State; 1047 break; 1048 default: 1049 DEBUG((9, "Got UNKNOWN message")); 1050 Pmmsg.pm_type = PM_UNKNOWN; 1051 Pmmsg.pm_state = State; 1052 logmessage("Received unknown message from sac -- ignored"); 1053 break; 1054 } 1055 DEBUG((9, "Responding with state %d", Pmmsg.pm_state)); 1056 while (write(Sacpipefd, &Pmmsg, sizeof(Pmmsg)) != sizeof(Pmmsg)) { 1057 if (errno == EINTR) 1058 continue; 1059 DEBUG((9, "sanity response failed")); 1060 break; 1061 } 1062 } 1063 } 1064 1065 1066 /* 1067 * doevent: handle an asynchronous event 1068 */ 1069 1070 static void 1071 doevent(struct call_list *phead, int fd) 1072 { 1073 static struct t_discon *disc; 1074 struct callsave *current; 1075 struct t_call *call; 1076 char scratch[BUFSIZ]; 1077 1078 DEBUG((9, "in doevent")); 1079 switch (t_look(fd)) { 1080 case 0: 1081 sys_error(E_POLL, EXIT); 1082 /* no return */ 1083 case T_LISTEN: 1084 DEBUG((9, "case t_listen ")); 1085 current = dequeue(Free_call_p); 1086 call = current->c_cp; 1087 if (t_listen(fd, call) < 0) { 1088 tli_error(E_T_LISTEN, CONTINUE); 1089 clr_call(call); 1090 queue(Free_call_p, current); 1091 return; 1092 } 1093 queue(phead, current); 1094 DEBUG((9, "incoming call seq # %d", call->sequence)); 1095 break; 1096 case T_DISCONNECT: 1097 DEBUG((9, "case t_disconnect")); 1098 if (disc == NULL) { 1099 while (!(disc = (struct t_discon *)t_alloc(fd, T_DIS, T_ALL)) ) { 1100 if (t_errno == TBADF) 1101 DEBUG((9,"listen - fd not transport end point")); 1102 if ((t_errno != TSYSERR) || (errno != EAGAIN)) 1103 tli_error(E_T_ALLOC, EXIT); 1104 else 1105 tli_error(E_T_ALLOC, CONTINUE); 1106 } 1107 } 1108 if (t_rcvdis(fd, disc) < 0) { 1109 tli_error(E_T_RCVDIS, EXIT); 1110 /* no return */ 1111 } 1112 sprintf(scratch, "Disconnect on fd %d, seq # %d", fd, disc->sequence); 1113 logmessage(scratch); 1114 DEBUG((9, "incoming disconnect seq # %d", disc->sequence)); 1115 pitchcall(phead, disc); 1116 break; 1117 default: 1118 DEBUG((9, "case default")); 1119 tli_error(E_T_LOOK, CONTINUE); 1120 break; 1121 1122 } 1123 } 1124 1125 /* 1126 * send_dis: send a disconnect 1127 * called when we are in state PM_DISABLED 1128 */ 1129 1130 static void 1131 send_dis(struct call_list *phead, int fd) 1132 { 1133 struct t_call *call; 1134 struct callsave *current; 1135 char scratch[BUFSIZ]; 1136 1137 DEBUG((9, "sending disconnect")); 1138 while (!EMPTYLIST(phead)) { 1139 current = dequeue(phead); 1140 call = current->c_cp; 1141 if (t_snddis(fd, call) < 0) { 1142 if (t_errno == TLOOK) { 1143 DEBUG((9, "collision during snddis")); 1144 pqueue(phead, current); 1145 return; 1146 } 1147 else 1148 tli_error(E_T_SNDDIS, CONTINUE); 1149 } 1150 sprintf(scratch, "Incoming call while disabled: fd %d, seq %d", fd, call->sequence); 1151 logmessage(scratch); 1152 clr_call(call); 1153 queue(Free_call_p, current); 1154 } 1155 return; 1156 } 1157 1158 1159 /* 1160 * trycon: try to accept a connection 1161 */ 1162 1163 static void 1164 trycon(struct call_list *phead, int fd) 1165 { 1166 struct callsave *current; 1167 struct t_call *call; 1168 int i; 1169 pid_t pid; 1170 dbf_t *dbp; 1171 char scratch[BUFSIZ]; 1172 extern dbf_t *getentry(); 1173 1174 DEBUG((9, "in trycon")); 1175 while (!EMPTYLIST(phead)) { 1176 current = dequeue(phead); 1177 call = current->c_cp; 1178 1179 if ((dbp = getentry(fd)) == NULL) { 1180 sprintf(scratch, "No service bound to incoming fd %d: call disconnected", fd); 1181 logmessage(scratch); 1182 t_snddis(fd, call); 1183 clr_call(call); 1184 queue(Free_call_p, current); 1185 continue; 1186 } 1187 1188 if (dbp->dbf_flags & DBF_OFF) { 1189 sprintf(scratch, "Request for service on fd %d denied: disabled", fd); 1190 logmessage(scratch); 1191 t_snddis(fd, call); 1192 clr_call(call); 1193 queue(Free_call_p, current); 1194 continue; 1195 } 1196 1197 DEBUG((9, "try to accept #%d", call->sequence)); 1198 SPLhi(); 1199 close(Acceptfd); 1200 if ((Acceptfd = open_bind(NULL, 0, 0, (unsigned int *) 0, NULL)) != 0) { 1201 error(E_OPENBIND, CONTINUE); 1202 clr_call(call); 1203 queue(Free_call_p, current); 1204 continue; /* let transport provider generate disconnect */ 1205 } 1206 SPLlo(); 1207 if (t_accept(fd, Acceptfd, call) < 0) { 1208 if (t_errno == TLOOK) { 1209 t_close(Acceptfd); 1210 SPLhi(); 1211 if (dup(Passfd) != 0) 1212 logmessage("Trouble duping fd 0"); 1213 SPLlo(); 1214 logmessage("Incoming call during t_accept -- queueing current call"); 1215 DEBUG((9, "save call #%d", call->sequence)); 1216 pqueue(phead, current); 1217 return; 1218 } 1219 else { 1220 t_close(Acceptfd); 1221 SPLhi(); 1222 if (dup(Passfd) != 0) 1223 logmessage("Trouble duping fd 0"); 1224 SPLlo(); 1225 tli_error(E_T_ACCEPT, CONTINUE); 1226 clr_call(call); 1227 queue(Free_call_p, current); 1228 continue; 1229 } 1230 } 1231 1232 sprintf(scratch, "Connect: fd %d, svctag %s, seq %d, type %s", 1233 fd, dbp->dbf_svc_code, call->sequence, 1234 (dbp->dbf_sflags & PFLAG) ? "passfd" : "exec"); 1235 logmessage(scratch); 1236 1237 DEBUG((9, "Accepted call %d", call->sequence)); 1238 1239 if (dbp->dbf_sflags & PFLAG) { 1240 1241 close(Passfd); 1242 1243 if (pushmod(Acceptfd, dbp->dbf_modules)) { 1244 sprintf(scratch, "Could not push modules: %s", dbp->dbf_modules); 1245 logmessage(scratch); 1246 goto cleanup; 1247 } 1248 1249 /* doconfig needs a file descriptor, so use Passfd */ 1250 DEBUG((9, "Running doconfig on %s", dbp->dbf_svc_code)); 1251 if ((i = doconfig(Acceptfd, dbp->dbf_svc_code, NOASSIGN|NORUN)) != 0) { 1252 DEBUG((9, "doconfig exited with code %d", i)); 1253 sprintf(scratch, "doconfig failed on line %d of script %s", i, dbp->dbf_svc_code); 1254 logmessage(scratch); 1255 goto cleanup; 1256 } 1257 1258 /* open pipe to pass fd through */ 1259 if ((Passfd = open(dbp->dbf_cmd_line, O_WRONLY)) < 0) { 1260 /* bad pipe? */ 1261 sprintf(scratch,"Open failed: %s", dbp->dbf_cmd_line); 1262 logmessage(scratch); 1263 goto cleanup; 1264 } 1265 1266 if (ioctl(Passfd, I_SENDFD, Acceptfd) < 0) { 1267 /* clean up call, log error */ 1268 sprintf(scratch,"Passfd failed: %s", dbp->dbf_cmd_line); 1269 logmessage(scratch); 1270 } 1271 cleanup: 1272 /* clean up this call */ 1273 clr_call(call); 1274 t_close(Acceptfd); 1275 close(Passfd); 1276 Acceptfd = open("/dev/null", O_RDWR); 1277 Passfd = dup(Acceptfd); 1278 queue(Free_call_p, current); 1279 } 1280 else { 1281 if ((pid = fork()) < 0) 1282 log(E_FORK_SERVICE); 1283 else if (!pid) { 1284 setpgrp(); 1285 /* so log files are correct */ 1286 Pid = getpid(); 1287 1288 if (senviron(call)) { 1289 logmessage("Can't expand server's environment"); 1290 } 1291 1292 start_server(Acceptfd, dbp); 1293 #ifdef COREDUMP 1294 abort(); 1295 #endif 1296 exit(1); /* server failed, don't log */ 1297 /* no return */ 1298 } 1299 /* only parent gets here */ 1300 clr_call(call); 1301 t_close(Acceptfd); 1302 queue(Free_call_p, current); 1303 SPLhi(); 1304 if (dup(Passfd) != 0) 1305 logmessage("Trouble duping fd 0"); 1306 SPLlo(); 1307 } 1308 } 1309 } 1310 1311 /* 1312 * common code to start a server process (for any service) 1313 * The first argument in argv is the full pathname of server. 1314 * Before exec-ing the server, the caller's 1315 * logical address, opt and udata are addded to the environment. 1316 */ 1317 1318 static char homeenv[BUFSIZ]; 1319 static char pathenv[BUFSIZ]; 1320 1321 int 1322 start_server(netfd, dbp) 1323 int netfd; 1324 dbf_t *dbp; 1325 { 1326 char *path; 1327 char **argvp; 1328 extern char **environ; 1329 extern char **mkdbfargv(); 1330 struct passwd *pwdp; 1331 struct group *grpp; 1332 char msgbuf[256]; 1333 int i; 1334 1335 1336 argvp = mkdbfargv(dbp); 1337 path = *argvp; 1338 1339 /* set up stdout and stderr before pushing optional modules */ 1340 /* this child doesn't need access to _sacpipe and _pmpipe */ 1341 1342 (void) close(Sacpipefd); 1343 (void) close(Pmpipefd); 1344 1345 if (dbp->dbf_flags & DBF_UTMP) { 1346 pid_t tmp; 1347 struct stat sbuf; 1348 char device[20]; 1349 char dummy[PMTAGSIZE + 1]; 1350 struct utmpx utline; 1351 1352 /* 1353 * create a utmpx entry -- 1354 * we do an extra fork here to make init this process's 1355 * parent. this lets init clean up the utmpx entry when 1356 * this proc dies. 1357 * 1358 * the utmpx routines need a file descriptor! 1359 */ 1360 1361 DEBUG((9, "Creating a utmpx entry for this service ")); 1362 if ((tmp = fork()) < 0) { 1363 logmessage("Can't fork to create utmpx entry"); 1364 exit(2); 1365 } 1366 if (tmp) 1367 exit(0); /* kill parent */ 1368 1369 /* 1370 * child continues processing, creating utmp and exec'ing 1371 * the service 1372 */ 1373 1374 setpgrp(); 1375 if (fstat(0, &sbuf) < 0) { 1376 logmessage("Stat failed on fd 0: no line field " 1377 "available for utmpx entry"); 1378 *device = '\0'; 1379 } 1380 else { 1381 if (minor(sbuf.st_rdev) < 100) 1382 sprintf(device, "%.9s%02d", Minor_prefix, 1383 minor(sbuf.st_rdev)); 1384 else 1385 sprintf(device, "%.8s%03d", Minor_prefix, 1386 minor(sbuf.st_rdev)); 1387 DEBUG((9, "Device: %s", device)); 1388 } 1389 /* 1390 * prepend a "." so this can be distinguished as a "funny" 1391 * utmpx entry that may never get a DEAD_PROCESS entry in 1392 * the wtmpx file. 1393 */ 1394 sprintf(dummy, ".%s", Mytag); 1395 /* XXX - utmp - fix login name length */ 1396 strncpy(utline.ut_user, dummy, sizeof (utline.ut_user) - 1); 1397 sprintf(utline.ut_id, "ls%c%c", SC_WILDC, SC_WILDC); 1398 strncpy(utline.ut_line, device, sizeof (utline.ut_line) - 1); 1399 utline.ut_pid = getpid(); 1400 utline.ut_type = USER_PROCESS; 1401 utline.ut_exit.e_termination = 0; 1402 utline.ut_exit.e_exit = 0; 1403 utline.ut_xtime = (time_t) time((time_t *)0); 1404 makeutx(&utline); 1405 } 1406 1407 if (dup(0) != 1 || dup(0) != 2) { 1408 logmessage("Dup of fd 0 failed"); 1409 exit(2); /* server, don't log */ 1410 } 1411 1412 1413 if (pushmod(netfd, dbp->dbf_modules)) { 1414 logmessage("Can't push server's modules: exit"); 1415 exit(2); /* server, don't log */ 1416 } 1417 1418 rst_signals(); 1419 1420 DEBUG((9, "Running doconfig on %s", dbp->dbf_svc_code)); 1421 if ((i = doconfig(Acceptfd, dbp->dbf_svc_code, 0)) != 0) { 1422 DEBUG((9, "doconfig exited with code %d", i)); 1423 sprintf(msgbuf, "doconfig failed on line %d of script %s", i, dbp->dbf_svc_code); 1424 logmessage(msgbuf); 1425 exit(2); 1426 } 1427 1428 if ((pwdp = getpwnam(dbp->dbf_id)) == NULL) { 1429 sprintf(msgbuf, "Missing or bad passwd entry for <%s>",dbp->dbf_id); 1430 logmessage(msgbuf); 1431 exit(2); /* server, don't log */ 1432 } 1433 1434 if (setgid(pwdp->pw_gid)) { 1435 if ((grpp = getgrgid(pwdp->pw_gid)) == NULL) { 1436 sprintf(msgbuf, "No group entry for %ld", pwdp->pw_gid); 1437 logmessage(msgbuf); 1438 exit(2); /* server, don't log */ 1439 } 1440 sprintf(msgbuf, "Cannot set group id to %s", grpp->gr_name); 1441 logmessage(msgbuf); 1442 exit(2); /* server, don't log */ 1443 } 1444 1445 if (setuid(pwdp->pw_uid)) { 1446 sprintf(msgbuf, "Cannot set user id to %s", dbp->dbf_id); 1447 logmessage(msgbuf); 1448 exit(2); /* server, don't log */ 1449 } 1450 1451 if (chdir(pwdp->pw_dir)) { 1452 sprintf(msgbuf, "Cannot chdir to %s", pwdp->pw_dir); 1453 logmessage(msgbuf); 1454 exit(2); /* server, don't log */ 1455 } 1456 1457 1458 DEBUG((9, "New uid %ld New gid %ld", getuid(), getgid())); 1459 1460 sprintf(homeenv, "HOME=%s", pwdp->pw_dir); 1461 putenv(homeenv); 1462 if (pwdp->pw_uid) 1463 sprintf(pathenv, "PATH=/usr/bin:"); 1464 else 1465 sprintf(pathenv, "PATH=/usr/sbin:/usr/bin"); 1466 putenv(pathenv); 1467 1468 endpwent(); 1469 1470 execve(path, argvp, environ); 1471 1472 /* exec returns only on failure! */ 1473 1474 logmessage("ERROR: could not exec server"); 1475 sys_error(E_SYS_ERROR, CONTINUE); 1476 return(-1); 1477 } 1478 1479 1480 /* 1481 * senviron: Update environment before exec-ing the server: 1482 * The callers logical address is placed in the 1483 * environment in hex/ascii character representation. 1484 * 1485 * Note: no need to free the malloc'ed buffers since this process 1486 * will either exec or exit. 1487 */ 1488 1489 static char provenv[2*PATHSIZE]; 1490 static char prefenv[2*PATHSIZE]; 1491 1492 int 1493 senviron(call) 1494 struct t_call *call; 1495 { 1496 char *p; 1497 extern void nlsaddr2c(); 1498 extern char *getenv(); 1499 1500 1501 /* 1502 * The following code handles the case where the listener was started with 1503 * no environment. If so, supply a reasonable default path. Parent already 1504 * set TZ on startup if it wasn't, so don't need to do it here. 1505 */ 1506 1507 if (getenv("PATH") == NULL) 1508 putenv("PATH=/usr/sbin:/usr/bin"); 1509 1510 if ((p = (char *)malloc(((call->addr.len)<<1) + 18)) == NULL) 1511 return(-1); 1512 strcpy(p, NLSADDR); 1513 strcat(p, "="); 1514 nlsaddr2c(p + strlen(p), call->addr.buf, (int)call->addr.len); 1515 DEBUG((7, "Adding %s to server's environment", p)); 1516 putenv(p); 1517 1518 if ((p = (char *)malloc(((call->opt.len)<<1) + 16)) == NULL) 1519 return(-1); 1520 strcpy(p, NLSOPT); 1521 strcat(p, "="); 1522 nlsaddr2c(p + strlen(p), call->opt.buf, (int)call->opt.len); 1523 DEBUG((7, "Adding %s to server's environment", p)); 1524 putenv(p); 1525 1526 p = provenv; 1527 strcpy(p, NLSPROVIDER); 1528 strcat(p, "="); 1529 strcat(p, Netspec); 1530 DEBUG((7, "Adding %s to environment", p)); 1531 putenv(p); 1532 1533 /* 1534 * MPREFIX is NEW for SVR4.0. It tells the nlps_server what to use 1535 * as a minor device prefix. THIS SHOULD BE DOCUMENTED! 1536 */ 1537 p = prefenv; 1538 strcpy(p, "MPREFIX"); 1539 strcat(p, "="); 1540 strcat(p, Minor_prefix); 1541 DEBUG((7, "Adding %s to environment", p)); 1542 putenv(p); 1543 1544 if ((p = (char *)malloc(((call->udata.len)<<1) + 20)) == NULL) 1545 return(-1); 1546 strcpy(p, NLSUDATA); 1547 strcat(p, "="); 1548 if ((int)call->udata.len >= 0) 1549 nlsaddr2c(p + strlen(p), call->udata.buf, (int)call->udata.len); 1550 putenv(p); 1551 return (0); 1552 } 1553 1554 1555 /* 1556 * parse: Parse TZ= string like init does for consistency 1557 * Work on string in place since result will 1558 * either be the same or shorter. 1559 */ 1560 1561 char * 1562 parse(s) 1563 char *s; 1564 { 1565 char *p; 1566 char *tp; 1567 char scratch[BUFSIZ]; 1568 int delim; 1569 1570 tp = p = s + strlen("TZ="); /* skip TZ= in parsing */ 1571 if ((*p == '"') || (*p == '\'')) { 1572 /* it is quoted */ 1573 delim = *p++; 1574 for (;;) { 1575 if (*p == '\0') { 1576 /* etc/default/init ill-formed, go without TZ */ 1577 sprintf(scratch, "%s ill-formed", TZFILE); 1578 logmessage(scratch); 1579 strcpy(s, "TZ="); 1580 return(s); 1581 } 1582 if (*p == delim) { 1583 *tp = '\0'; 1584 return(s); 1585 } 1586 else { 1587 *tp++ = *p++; 1588 } 1589 } 1590 } 1591 else { /* look for comment or trailing whitespace */ 1592 for ( ; *p && !isspace(*p) && *p != '#'; ++p) 1593 ; 1594 /* if a comment or trailing whitespace, trash it */ 1595 if (*p) { 1596 *p = '\0'; 1597 } 1598 return(s); 1599 } 1600 } 1601 1602 1603 /* 1604 * clr_call: clear out a call structure 1605 */ 1606 1607 static void 1608 clr_call(struct t_call *call) 1609 { 1610 call->sequence = 0; 1611 call->addr.len = 0; 1612 call->opt.len = 0; 1613 call->udata.len = 0; 1614 memset(call->addr.buf, 0, (int)call->addr.maxlen); 1615 memset(call->opt.buf, 0, (int)call->opt.maxlen); 1616 memset(call->udata.buf, 0, (int)call->udata.maxlen); 1617 } 1618 1619 1620 /* 1621 * pitchcall: remove call from pending list 1622 */ 1623 1624 static void 1625 pitchcall(struct call_list *pending, struct t_discon *discon) 1626 { 1627 struct callsave *p, *oldp; 1628 1629 DEBUG((9, "pitching call, sequence # is %d", discon->sequence)); 1630 if (EMPTYLIST(pending)) { 1631 discon->sequence = -1; 1632 return; 1633 } 1634 p = pending->cl_head; 1635 oldp = (struct callsave *) NULL; 1636 while (p) { 1637 if (p->c_cp->sequence == discon->sequence) { 1638 if (oldp == (struct callsave *) NULL) { 1639 pending->cl_head = p->c_np; 1640 if (pending->cl_head == (struct callsave *) NULL) { 1641 pending->cl_tail = (struct callsave *) NULL; 1642 } 1643 } 1644 else if (p == pending->cl_tail) { 1645 oldp->c_np = p->c_np; 1646 pending->cl_tail = oldp; 1647 } 1648 else { 1649 oldp->c_np = p->c_np; 1650 } 1651 clr_call(p->c_cp); 1652 queue(Free_call_p, p); 1653 discon->sequence = -1; 1654 return; 1655 } 1656 oldp = p; 1657 p = p->c_np; 1658 } 1659 logmessage("received disconnect with no pending call"); 1660 discon->sequence = -1; 1661 return; 1662 } 1663 1664 /* 1665 * add_prvaddr: open and bind the private address specified in the database 1666 * entry passed into the routine. Update the maxcon and fd 1667 * entries in the database structure 1668 * 1669 * This routine is very sloppy with malloc'ed memory, but addresses 1670 * shouldn't ever change enough for this to matter. 1671 */ 1672 1673 int 1674 add_prvaddr(dbp) 1675 dbf_t *dbp; 1676 { 1677 extern char *t_alloc(); 1678 int j; 1679 struct call_list *temp_pend; 1680 struct callsave *tmp; 1681 char scratch[BUFSIZ]; 1682 int bindfd; 1683 extern struct netbuf *stoa(); 1684 char str[NAMEBUFSZ]; 1685 char *lstr = str; 1686 struct netbuf netbuf; 1687 int maxcon; 1688 char *ap; 1689 int clen; 1690 1691 DEBUG((9,"in add_prvaddr, addr %s, svc %s", 1692 (dbp->dbf_sflags & DFLAG) ? "DYNAMIC" : dbp->dbf_prv_adr, 1693 dbp->dbf_svc_code)); 1694 netbuf.buf = NULL; 1695 netbuf.maxlen = 0; 1696 netbuf.len = 0; 1697 if (!(dbp->dbf_sflags & DFLAG)) { 1698 strcpy(lstr, dbp->dbf_prv_adr); 1699 1700 /* call stoa - convert from rfs address to netbuf */ 1701 1702 if (stoa(lstr, &netbuf) == (struct netbuf *)NULL) { 1703 DEBUG((9,"stoa returned null, errno = %d\n",errno)); 1704 error(1, E_MALLOC); 1705 return(-1); 1706 } 1707 clen = netbuf.len; 1708 } 1709 else { 1710 clen = -1; 1711 } 1712 if ((bindfd = open_bind(netbuf.buf, MAXCON, clen, &maxcon, &ap)) < 0) { 1713 switch (bindfd) { 1714 case -1: 1715 return(-1); 1716 break; 1717 case -2: 1718 sprintf(scratch, " Service %s ignored: out of file descriptors", dbp->dbf_svc_code); 1719 logmessage(scratch); 1720 return(-1); 1721 break; 1722 case -3: 1723 sprintf(scratch, " Service %s ignored: unable to bind requested address", dbp->dbf_svc_code); 1724 logmessage(scratch); 1725 return(-1); 1726 break; 1727 default: 1728 error(E_OPENBIND, EXIT); 1729 } 1730 } 1731 if (clen == -1) { 1732 sprintf(scratch,"Service %s: fd %d dynamic addr %s", dbp->dbf_svc_code, bindfd, ap); 1733 dbp->dbf_prv_adr = ap; 1734 } 1735 else { 1736 sprintf(scratch,"Service %s: fd %d addr %s", dbp->dbf_svc_code, bindfd, dbp->dbf_prv_adr); 1737 } 1738 logmessage(scratch); 1739 rpc_register(dbp); 1740 temp_pend = Priv_call + bindfd; 1741 dbp->dbf_fd = bindfd; 1742 dbp->dbf_maxcon = maxcon; 1743 temp_pend->cl_head = (struct callsave *) NULL; 1744 temp_pend->cl_tail = (struct callsave *) NULL; 1745 for (j=0; j < maxcon; ++j) { 1746 if ((tmp = (struct callsave *) malloc(sizeof(struct callsave))) == NULL) { 1747 error (E_MALLOC, NOCORE | EXIT); 1748 } 1749 if ((tmp->c_cp = (struct t_call *) t_alloc(bindfd, T_CALL, 1750 T_ALL)) == NULL) { 1751 tli_error(E_T_ALLOC,EXIT); 1752 } 1753 queue(Free_call_p, tmp); 1754 } 1755 return(0); 1756 } 1757 1758 /* 1759 * mod_prvaddr -- after re-reading the database, take appropriate action for 1760 * new, deleted, or changed addresses. 1761 */ 1762 static void 1763 mod_prvaddr(void) 1764 { 1765 dbf_t *entry_p; 1766 dbf_t *oldentry_p; 1767 char scratch[BUFSIZ]; 1768 dbf_t *svc_code_match(); 1769 int bound; 1770 struct pollfd *sp; 1771 1772 DEBUG((9, "in mod_prvaddr...")); 1773 /* 1774 * for each entry in the new table, check for a svc code match. 1775 * if there is a svc code match and the address matches, all we 1776 * need to do is update the new table. if the addresses are 1777 * different, we need to remove the old one and replace it. 1778 */ 1779 for (entry_p = Newdbf; entry_p && entry_p->dbf_svc_code; entry_p++) { 1780 if ((oldentry_p = svc_code_match(entry_p->dbf_svc_code)) != NULL) { 1781 /* matched svc code. see if address matches. */ 1782 DEBUG((9, "MATCHED service code")); 1783 if ((strcmp(oldentry_p->dbf_prv_adr, entry_p->dbf_prv_adr) == 0) || ((oldentry_p->dbf_sflags & DFLAG) && (entry_p->dbf_sflags & DFLAG))) { 1784 DEBUG((9, "SAME addresses, old %s, new %s", 1785 oldentry_p->dbf_prv_adr, entry_p->dbf_prv_adr)); 1786 /* update new table with fd, set old fd to -1 */ 1787 DEBUG((9, "Old fd %d", oldentry_p->dbf_fd)); 1788 entry_p->dbf_fd = oldentry_p->dbf_fd; 1789 entry_p->dbf_maxcon = oldentry_p->dbf_maxcon; 1790 oldentry_p->dbf_fd = -1; 1791 if ((oldentry_p->dbf_sflags & DFLAG) && (entry_p->dbf_sflags & DFLAG)) { 1792 entry_p->dbf_prv_adr = oldentry_p->dbf_prv_adr; 1793 } 1794 if (entry_p->dbf_fd != -1) { 1795 sprintf(scratch, "Service %s: fd %d addr %s", 1796 entry_p->dbf_svc_code, entry_p->dbf_fd, 1797 entry_p->dbf_prv_adr); 1798 logmessage(scratch); 1799 } 1800 if ((oldentry_p->dbf_version != entry_p->dbf_version) || (oldentry_p->dbf_prognum != entry_p->dbf_prognum)) { 1801 rpc_unregister(oldentry_p); 1802 rpc_register(entry_p); 1803 } 1804 } 1805 } 1806 } 1807 1808 /* now unbind the remaining addresses in the old table (fd != -1) */ 1809 1810 for (oldentry_p = Dbfhead; oldentry_p && oldentry_p->dbf_svc_code; oldentry_p++) { 1811 if (oldentry_p->dbf_fd != -1) { 1812 DEBUG((9, "deleting %s", oldentry_p->dbf_svc_code)); 1813 if (del_prvaddr(oldentry_p) == 0) 1814 Valid_addrs--; 1815 } 1816 } 1817 1818 /* now bind all of the new addresses (fd == -1) */ 1819 /* 1820 * this tries to bind any addresses that failed to bind successfully 1821 * when the address changed. This means that if a service is moved to 1822 * an address that is being deleted, the first attempt to bind it will 1823 * fail, the old address will be removed, and this bind will succeed 1824 */ 1825 1826 /* first the static addrs */ 1827 for (entry_p = Newdbf; entry_p && entry_p->dbf_svc_code; entry_p++) { 1828 if ((entry_p->dbf_fd == -1) && (!(entry_p->dbf_sflags & DFLAG))) { 1829 DEBUG((9, "adding %s", entry_p->dbf_svc_code)); 1830 if (add_prvaddr(entry_p) == 0) 1831 Valid_addrs++; 1832 } 1833 } 1834 /* then the dynamic addrs */ 1835 for (entry_p = Newdbf; entry_p && entry_p->dbf_svc_code; entry_p++) { 1836 if ((entry_p->dbf_fd == -1) && (entry_p->dbf_sflags & DFLAG)) { 1837 DEBUG((9, "adding %s", entry_p->dbf_svc_code)); 1838 if (add_prvaddr(entry_p) == 0) 1839 Valid_addrs++; 1840 } 1841 } 1842 1843 /* free old database, set up new pollfd table, and we're done */ 1844 1845 free(Dbfhead); 1846 free(Server_cmd_lines); 1847 Dbfhead = Newdbf; 1848 Newdbf = NULL; 1849 Server_cmd_lines = New_cmd_lines; 1850 sprintf(scratch, "Re-read complete, %d %s bound, %d fds free", Valid_addrs, 1851 (Valid_addrs == 1) ? "address" : "addresses", 1852 Ndesc-Valid_addrs-USEDFDS); 1853 logmessage(scratch); 1854 1855 /* Pollfds[0] is for _pmpipe */ 1856 sp = &Pollfds[1]; 1857 for (entry_p = Dbfhead; entry_p && entry_p->dbf_svc_code; entry_p++) { 1858 if (entry_p->dbf_fd >= 0) { 1859 sp->fd = entry_p->dbf_fd; 1860 DEBUG((9, "adding %d to poll struct", entry_p->dbf_fd)); 1861 sp->events = POLLIN; 1862 sp->revents = 0; 1863 sp++; 1864 } 1865 } 1866 } 1867 1868 /* 1869 * unbind the address, close the file descriptor, and free call structs 1870 */ 1871 1872 int 1873 del_prvaddr(dbp) 1874 dbf_t *dbp; 1875 { 1876 struct callsave *tmp; 1877 struct call_list *q; 1878 struct t_call *call; 1879 int i; 1880 char scratch[BUFSIZ]; 1881 1882 DEBUG((9, "in del_prvaddr...")); 1883 rpc_unregister(dbp); 1884 if (dbp->dbf_fd < 0) 1885 return -1; 1886 1887 q = Priv_call + dbp->dbf_fd; 1888 i = 0; 1889 1890 /* delete pending calls */ 1891 while ((tmp = dequeue(q)) != NULL) { 1892 i++; 1893 call = tmp->c_cp; 1894 t_snddis(dbp->dbf_fd, call); 1895 t_free((char *)call, T_CALL); 1896 free(tmp); 1897 } 1898 1899 /* delete free call structs we don't need */ 1900 for ( ; i < dbp->dbf_maxcon; i++) { 1901 tmp = dequeue(Free_call_p); 1902 t_free((char *)tmp->c_cp, T_CALL); 1903 free(tmp); 1904 } 1905 1906 t_unbind(dbp->dbf_fd); 1907 t_close(dbp->dbf_fd); 1908 sprintf(scratch, "Unbind %s: fd %d addr %s", dbp->dbf_svc_code, 1909 dbp->dbf_fd, dbp->dbf_prv_adr); 1910 logmessage(scratch); 1911 dbp->dbf_fd = -1; 1912 return 0; 1913 } 1914 1915 1916 /* 1917 * look through the old database file to see if this service code matches 1918 * one already present 1919 */ 1920 1921 dbf_t * 1922 svc_code_match(new_code) 1923 char *new_code; 1924 { 1925 dbf_t *dbp; 1926 1927 for (dbp = Dbfhead; dbp && dbp->dbf_svc_code; dbp++) { 1928 if (strcmp(dbp->dbf_svc_code, new_code) == 0) 1929 return(dbp); 1930 } 1931 return((dbf_t *)NULL); 1932 } 1933 1934 1935 /* 1936 * register an rpc service with rpcbind 1937 */ 1938 1939 void 1940 rpc_register(dbp) 1941 dbf_t *dbp; 1942 { 1943 char str[NAMEBUFSZ]; 1944 char scratch[BUFSIZ]; 1945 char *lstr = str; 1946 struct netbuf netbuf; 1947 extern struct netbuf *stoa(); 1948 extern int errno; 1949 1950 DEBUG((9, "in rpc_register")); 1951 if (dbp->dbf_prognum == -1 || dbp->dbf_version == -1) 1952 /* not an rpc service */ 1953 return; 1954 1955 rpc_unregister(dbp); 1956 netbuf.buf = NULL; 1957 netbuf.maxlen = 0; 1958 netbuf.len = 0; 1959 strcpy(lstr, dbp->dbf_prv_adr); 1960 if (stoa(lstr, &netbuf) == (struct netbuf *)NULL) { 1961 DEBUG((9,"stoa returned null, errno = %d\n",errno)); 1962 error(1, E_MALLOC); 1963 return; 1964 } 1965 if (rpcb_set(dbp->dbf_prognum, dbp->dbf_version, Netconf, &netbuf)) { 1966 sprintf(scratch," registered with rpcbind, prognum %d version %d", dbp->dbf_prognum, dbp->dbf_version); 1967 logmessage(scratch); 1968 } 1969 else { 1970 logmessage("rpcb_set failed, service not registered with rpcbind"); 1971 } 1972 return; 1973 } 1974 1975 1976 /* 1977 * unregister an rpc service with rpcbind 1978 */ 1979 1980 void 1981 rpc_unregister(dbp) 1982 dbf_t *dbp; 1983 { 1984 DEBUG((9, "in rpc_unregister")); 1985 if (dbp->dbf_prognum == -1 || dbp->dbf_version == -1) 1986 /* not an rpc service */ 1987 return; 1988 (void) rpcb_unset(dbp->dbf_prognum, dbp->dbf_version, Netconf); 1989 } 1990