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