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
main(int argc,char ** argv)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
pid_open(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
init_files(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
net_open(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
queue(head,cp)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
pqueue(head,cp)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 *
dequeue(head)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
open_bind(name,qlen,clen,conp,adrp)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
bind(fd,name,qlen,clen,ap)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
catch_signals(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
rst_signals(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
sigterm()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
listen(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
check_sac_mesg()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
doevent(struct call_list * phead,int fd)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
send_dis(struct call_list * phead,int fd)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
trycon(struct call_list * phead,int fd)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
start_server(netfd,dbp)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
senviron(call)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 *
parse(s)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
clr_call(struct t_call * call)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
pitchcall(struct call_list * pending,struct t_discon * discon)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
add_prvaddr(dbp)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
mod_prvaddr(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
del_prvaddr(dbp)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 *
svc_code_match(new_code)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
rpc_register(dbp)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
rpc_unregister(dbp)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