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
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.
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]
24 * Copyright 2014 Garrett D'Amore
27 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
31 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
32 /* All Rights Reserved */
35 * Network Listener Process
39 * listen [ -m minor_prefix ] netspec
43 /* system include files */
52 #include <sys/utsname.h>
53 #include <sys/tiuser.h>
54 #include <sys/param.h>
55 #include <sys/types.h>
57 #include <sys/mkdev.h>
64 #include <sys/stropts.h>
68 /* listener include files */
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 */
80 #define NAMESIZE (NAMEBUFSZ-1)
82 #define SPLhi() Splflag = 1
83 #define SPLlo() Splflag = 0
88 /* global variables */
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 */
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 */
112 /* FILE DESCRIPTOR MANAGEMENT:
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
118 * fd 2: In the parent, a connection to _pmpipe. Dup'ed in the child
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
125 * fd 5: Opened to the log file.
126 * fd 6: Opened to the debug file ONLY when compiled with DEBUGMODE.
128 * The remaining file descriptors are available for binding private addresses.
135 FILE *Debugfp
; /* for the debugging file */
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*/
145 struct pmmsg Pmmsg
; /* to respond to SAC */
146 int State
= PM_STARTING
; /* current SAC state */
149 char Lastmsg
[BUFSIZ
]; /* contains last msg logged (by stampbuf) */
150 int Logmax
= LOGMAX
; /* number of entriet to allow in logfile */
152 int Splflag
; /* logfile critical region flag */
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
];
161 #define TZFILE "/etc/default/init"
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();
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);
192 main(int argc
, char **argv
)
196 char scratch
[BUFSIZ
];
199 char *scratch_p
= scratch
;
202 extern char *getenv();
208 char *Mytag_p
= Mytag
;
210 /* Get my port monitor tag out of the environment */
211 if ((mytag_p
= getenv("PMTAG")) == NULL
) {
212 /* no place to write */
215 strcpy(Mytag
, mytag_p
);
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 */
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+");
232 /* Get my port monitor tag out of the environment */
233 if ((mytag_p
= getenv("PMTAG")) == NULL
) {
236 strcpy(Mytag
, mytag_p
);
241 if (geteuid() != (uid_t
) 0) {
242 logmessage("Must be root to start listener");
243 logexit(1, badstart
);
246 while ((c
= getopt(argc
, argv
, "m:")) != EOF
)
249 Minor_prefix
= optarg
;
256 if ((Netspec
= argv
[optind
]) == NULL
) {
259 if ((Netconf
= getnetconfigent(Netspec
)) == NULL
) {
260 sprintf(scratch
, "no netconfig entry for <%s>", Netspec
);
262 logexit(1, badstart
);
265 Minor_prefix
= argv
[optind
];
267 if ((int) strlen(Netspec
) > PATHSIZE
) {
268 logmessage(badnspmsg
);
269 logexit(1, badstart
);
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
277 strcpy(Provbuf
, "/dev/");
278 strcat(Provbuf
, Netspec
);
282 init_files(); /* open Accept, Sac, Pm, Pass files */
283 pid_open(); /* create pid file */
286 sprintf(scratch
, "%s/%s/%s", ALTDIR
, Mytag
, DBGNAME
);
287 Debugfp
= fopen(scratch
, "w");
292 if ((!Logfp
) || (!Debugfp
))
296 logexit(1, badstart
);
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.
303 if (getenv("TZ") == NULL
) {
304 fp
= fopen(TZFILE
, "r");
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
));
317 sprintf(scratch
, "couldn't open %s, default to GMT",
323 logmessage("@(#)listen:listen.c 1.19.9.1");
326 logmessage("Listener process with DEBUG capability");
329 sprintf(scratch
, "Listener port monitor tag: %s", Mytag_p
);
331 DEBUG((9, "Minor prefix: %s Netspec %s", Minor_prefix
, Netspec
));
333 /* fill in Pmmesg fields that always stay the same */
335 Pmmsg
.pm_maxclass
= MAXCLASS
;
336 strcpy(Pmmsg
.pm_tag
, Mytag_p
);
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");
343 if (!strcmp(scratch_p
, "enabled")) {
345 logmessage("Starting state: ENABLED");
349 logmessage("Starting state: DISABLED");
352 /* try to get my "basename" */
353 Progname
= strrchr(argv
[0], '/');
354 if (Progname
&& Progname
[1])
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
368 Ndesc
= ulimit(4,0L); /* get num of file des on system */
371 net_open(); /* init, open, bind names */
373 for (i
= 3; i
< Ndesc
; i
++) { /* leave stdout, stderr open */
374 fcntl(i
, F_SETFD
, 1); /* set close on exec flag*/
377 logmessage("Initialization Complete");
387 * open pidfile with specified oflags and modes and lock it
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";
401 if ((Pidfd
= open(PIDNAME
, PIDOFLAG
, PIDMODE
)) == -1) {
402 logmessage(pidopenmsg
);
403 error(E_CREAT
, EXIT
| NOCORE
| NO_MSG
);
406 if (lockf(Pidfd
, 2, 0L) == -1) {
407 logmessage(pidlockmsg
);
408 logexit(1, badstart
);
412 i
= sprintf(pidstring
, "%ld", Pid
) + 1;
415 while ((ret
= write(Pidfd
, pidstring
, i
)) != i
) {
419 sys_error(E_PIDWRITE
, EXIT
);
421 error(E_PIDWRITE
, EXIT
);
427 * init_files: open initial files for the listener (see FILE DESC MGMT comment)
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";
437 if ((Acceptfd
= open("/dev/null", O_RDWR
)) != 0) {
438 logmessage("Trouble opening /dev/null");
439 sys_error(E_SYS_ERROR
, EXIT
| NOCORE
);
443 if ((Sacpipefd
= open(SACPIPE
, O_RDWR
|O_NDELAY
)) != 1) {
444 logmessage(sacopenmsg
);
445 error(E_CREAT
, EXIT
| NOCORE
| NO_MSG
);
449 if ((Pmpipefd
= open(PMPIPE
, O_RDWR
|O_NDELAY
)) != 2) {
450 logmessage(pmopenmsg
);
451 error(E_CREAT
, EXIT
| NOCORE
| NO_MSG
);
455 if ((Passfd
= dup(Acceptfd
)) != 3) {
456 logmessage("Trouble duping /dev/null");
457 sys_error(E_SYS_ERROR
, EXIT
| NOCORE
);
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.
475 char pbuf
[NAMEBUFSZ
+ 1];
476 #endif /* CHARADDR */
479 char scratch
[BUFSIZ
];
481 DEBUG((9,"in net_open"));
483 /* set up free call list and pending connection lists */
485 Free_call_p
->cl_head
= NULL
;
486 Free_call_p
->cl_tail
= NULL
;
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
);
495 /* first do static addrs */
496 while ( (i
< Dbf_entries
) ) {
498 if (!(dp
->dbf_sflags
& DFLAG
)) {
499 if (add_prvaddr(dp
) == 0)
505 /* second pass for dynamic addrs */
506 while ( (i
< Dbf_entries
) ) {
508 if (dp
->dbf_sflags
& DFLAG
) {
509 if (add_prvaddr(dp
) == 0)
515 sprintf(scratch
, "Net opened, %d %s bound, %d fds free", Valid_addrs
,
516 (Valid_addrs
== 1) ? "address" : "addresses",
517 Ndesc
-Valid_addrs
-USEDFDS
);
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
535 * add calls to tail of queue
541 struct call_list
*head
;
544 DEBUG((9,"in queue"));
545 if (head
->cl_tail
== NULL
) {
547 head
->cl_head
= head
->cl_tail
= cp
;
550 cp
->c_np
= head
->cl_tail
->c_np
;
551 head
->cl_tail
->c_np
= cp
;
560 * priority queuer, add calls to head of queue
565 struct call_list
*head
;
568 if (head
->cl_head
== NULL
) {
570 head
->cl_head
= head
->cl_tail
= cp
;
573 cp
->c_np
= head
->cl_head
;
582 * remove a call from the head of queue
588 struct call_list
*head
;
590 struct callsave
*ret
;
592 DEBUG((9,"in dequeue"));
593 if (head
->cl_head
== NULL
) {
595 DEBUG((9,"cl_head = null"));
596 error(E_CANT_HAPPEN
, EXIT
);
598 DEBUG((9, "NULL return"));
602 head
->cl_head
= ret
->c_np
;
603 if (head
->cl_head
== NULL
)
604 head
->cl_tail
= NULL
;
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.
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.
631 * Assumptions: driver returns ENXIO when all devices are allocated.
635 open_bind(name
, qlen
, clen
, conp
, adrp
)
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
) {
658 tli_error(E_FD1OPEN
, CONTINUE
);
659 logmessage("No network minor devices (ENXIO/ENOSR)");
663 DEBUG((9,"problem in t_open"));
664 tli_error(E_FD1OPEN
, EXIT
);
668 ret
= bind(fd
, name
, qlen
, clen
, adrp
);
669 DEBUG((9, "bind returns %d", ret
));
682 bind(fd
, name
, qlen
, clen
, ap
)
689 struct t_bind
*req
= NULL
;
690 struct t_bind
*ret
= NULL
;
693 extern void nlsaddr2c();
698 char pbuf
[NAMEBUFSZ
+ 1];
700 char scratch
[BUFSIZ
];
702 DEBUG((9,"in bind, fd = %d, clen = %d", fd
, clen
));
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
);
710 tli_error( E_T_ALLOC
, CONTINUE
);
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
);
718 tli_error( E_T_ALLOC
, CONTINUE
);
721 if (clen
> (int) req
->addr
.maxlen
) {
722 sprintf(scratch
,"Truncating name size from %d to %d",
723 clen
, req
->addr
.maxlen
);
725 clen
= req
->addr
.maxlen
;
732 (void)memcpy(req
->addr
.buf
, name
, clen
);
733 req
->addr
.len
= clen
;
737 #if defined(CHARADDR) && defined(DEBUGMODE)
738 (void)memcpy(pbuf
, req
->addr
.buf
, req
->addr
.len
);
739 pbuf
[req
->addr
.len
] = '\0';
740 DEBUG((3,"bind: fd=%d, logical name=%c%s%c, len=%d",
741 fd
, '\"',pbuf
, '\"', req
->addr
.len
));
742 #endif /* CHARADDR && DEBUGMODE */
745 #if defined(CHARADDR) && defined(DEBUGMODE)
746 (void)memcpy(pbuf
, req
->addr
.buf
, req
->addr
.len
);
747 pbuf
[req
->addr
.len
] = '\0';
748 DEBUG((3,"bind: fd=%d, address=%c%s%c, len=%d",
749 fd
, '\"',pbuf
, '\"', req
->addr
.len
));
750 #endif /* CHARADDR && DEBUGMODE */
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
);
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
);
772 /* otherwise, irrecoverable error */
773 tli_error(E_T_BIND
, EXIT
| NOCORE
);
775 DEBUG((9, "t_bind succeeded"));
780 /* dynamic address */
781 *ap
= (char *) malloc(((ret
->addr
.len
) << 1) + 3);
785 nlsaddr2c(*ap
+2,ret
->addr
.buf
,(int)ret
->addr
.len
);
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);
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
);
797 sprintf(scratch
, "Actual address \\x%s", p
);
802 DEBUG((9, "failed to bind requested address"));
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
);
812 if ( t_free((char *)req
, T_BIND
) )
813 tli_error(E_T_FREE
, EXIT
);
815 if ( t_free((char *)ret
, T_BIND
) )
816 tli_error(E_T_FREE
, EXIT
);
819 return((unsigned int) 0);
825 * Ignore some, catch the rest. Use SIGTERM to kill me.
829 struct sigaction Sigterm
;
830 struct sigaction Sigcld
;
837 struct sigaction sigact
;
838 extern void sigterm();
840 (void) sigfillset(&sset
);
841 (void) sigdelset(&sset
, SIGTERM
);
842 (void) sigdelset(&sset
, SIGCLD
);
843 (void) sigprocmask(SIG_SETMASK
, &sset
, &Oset
);
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
);
858 * After forking but before exec'ing a server,
859 * reset all signals to original setting.
865 struct sigaction sigact
;
867 sigaction(SIGTERM
, &Sigterm
, NULL
);
868 sigaction(SIGCLD
, &Sigcld
, NULL
);
869 sigprocmask(SIG_SETMASK
, &Oset
, NULL
);
874 * sigterm: Clean up and exit.
881 extern char *sh2addr
;
883 error(E_SIGTERM
, EXIT
| NORMAL
| NOCORE
); /* calls cleanup */
888 * listen: listen for and process connection requests.
891 static char *dbfnewdmsg
= "Using new data base file";
897 dbf_t
*dbp
= Dbfhead
;
899 struct call_list
*phead
; /* pending head */
901 DEBUG((9,"in listen, tag %s", Pmmsg
.pm_tag
));
903 if ((Pollfds
= (struct pollfd
*) malloc(Ndesc
* sizeof(struct pollfd
)))
905 error(E_MALLOC
,NOCORE
| EXIT
);
907 /* setup poll structures for sac messages and private addresses */
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
));
925 DEBUG((9,"listen(): TOP of loop"));
927 /* +1 for Pmpipefd */
928 if (poll(Pollfds
, Valid_addrs
+ 1, -1) < 0) {
932 sys_error(E_POLL
, EXIT
);
935 /* incoming request or message */
936 for (i
= 0, sp
= Pollfds
; i
< Valid_addrs
+ 1; i
++, sp
++) {
937 switch (sp
->revents
) {
939 if (sp
->fd
== Pmpipefd
) {
940 DEBUG((9,"sac message received"));
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
));
950 send_dis(phead
, (sp
->fd
));
955 /* distinguish the various errors for the user */
957 logmessage("poll() returned POLLERR");
958 error(E_SYS_ERROR
, EXIT
| NO_MSG
);
961 logmessage("poll() returned POLLHUP");
962 error(E_SYS_ERROR
, EXIT
| NO_MSG
);
965 logmessage("poll() returned POLLNVAL");
966 error(E_SYS_ERROR
, EXIT
| NO_MSG
);
969 logmessage("poll() returned POLLPRI");
970 error(E_SYS_ERROR
, EXIT
| NO_MSG
);
973 logmessage("poll() returned POLLOUT");
974 error(E_SYS_ERROR
, EXIT
| NO_MSG
);
977 logmessage("poll() returned unrecognized event");
978 error(E_SYS_ERROR
, EXIT
| NO_MSG
);
985 DEBUG((9,"dbf file has been modified"));
986 logmessage("Re-reading database");
987 /* have to close an fd because read_dbf needs it */
989 if (!read_dbf(DB_REREAD
)) {
990 /* MUST re-open Acceptfd to insure it is free later */
996 logmessage(dbfnewdmsg
);
1005 * check_sac_mesg: check the pipe to see if SAC has sent a message
1012 struct sacmsg sacmsg
;
1014 DEBUG((9, "in check_sac_mesg..."));
1016 /* read all messages out of pipe */
1017 while ((length
= read(Pmpipefd
, &sacmsg
, sizeof(sacmsg
))) != 0) {
1021 DEBUG((9, "read of _pmpipe failed"));
1025 switch (sacmsg
.sc_type
) {
1027 DEBUG((9, "Got SC_STATUS message"));
1028 Pmmsg
.pm_type
= PM_STATUS
;
1029 Pmmsg
.pm_state
= State
;
1032 DEBUG((9, "Got SC_ENABLE message"));
1033 if (State
!= PM_ENABLED
)
1034 logmessage("New state: ENABLED");
1035 Pmmsg
.pm_type
= PM_STATUS
;
1037 Pmmsg
.pm_state
= PM_ENABLED
;
1040 DEBUG((9, "Got SC_DISABLE message"));
1041 if (State
!= PM_DISABLED
)
1042 logmessage("New state: DISABLED");
1043 Pmmsg
.pm_type
= PM_STATUS
;
1044 State
= PM_DISABLED
;
1045 Pmmsg
.pm_state
= PM_DISABLED
;
1048 DEBUG((9, "Got SC_READDB message"));
1050 Pmmsg
.pm_type
= PM_STATUS
;
1051 Pmmsg
.pm_state
= State
;
1054 DEBUG((9, "Got UNKNOWN message"));
1055 Pmmsg
.pm_type
= PM_UNKNOWN
;
1056 Pmmsg
.pm_state
= State
;
1057 logmessage("Received unknown message from sac -- ignored");
1060 DEBUG((9, "Responding with state %d", Pmmsg
.pm_state
));
1061 while (write(Sacpipefd
, &Pmmsg
, sizeof(Pmmsg
)) != sizeof(Pmmsg
)) {
1064 DEBUG((9, "sanity response failed"));
1072 * doevent: handle an asynchronous event
1076 doevent(struct call_list
*phead
, int fd
)
1078 static struct t_discon
*disc
;
1079 struct callsave
*current
;
1080 struct t_call
*call
;
1081 char scratch
[BUFSIZ
];
1083 DEBUG((9, "in doevent"));
1084 switch (t_look(fd
)) {
1086 sys_error(E_POLL
, EXIT
);
1090 DEBUG((9, "case t_listen "));
1091 current
= dequeue(Free_call_p
);
1092 call
= current
->c_cp
;
1093 if (t_listen(fd
, call
) < 0) {
1094 tli_error(E_T_LISTEN
, CONTINUE
);
1096 queue(Free_call_p
, current
);
1099 queue(phead
, current
);
1100 DEBUG((9, "incoming call seq # %d", call
->sequence
));
1103 DEBUG((9, "case t_disconnect"));
1105 while (!(disc
= (struct t_discon
*)t_alloc(fd
, T_DIS
, T_ALL
)) ) {
1106 if (t_errno
== TBADF
)
1107 DEBUG((9,"listen - fd not transport end point"));
1108 if ((t_errno
!= TSYSERR
) || (errno
!= EAGAIN
))
1109 tli_error(E_T_ALLOC
, EXIT
);
1111 tli_error(E_T_ALLOC
, CONTINUE
);
1114 if (t_rcvdis(fd
, disc
) < 0) {
1115 tli_error(E_T_RCVDIS
, EXIT
);
1118 sprintf(scratch
, "Disconnect on fd %d, seq # %d", fd
, disc
->sequence
);
1119 logmessage(scratch
);
1120 DEBUG((9, "incoming disconnect seq # %d", disc
->sequence
));
1121 pitchcall(phead
, disc
);
1124 DEBUG((9, "case default"));
1125 tli_error(E_T_LOOK
, CONTINUE
);
1132 * send_dis: send a disconnect
1133 * called when we are in state PM_DISABLED
1137 send_dis(struct call_list
*phead
, int fd
)
1139 struct t_call
*call
;
1140 struct callsave
*current
;
1141 char scratch
[BUFSIZ
];
1143 DEBUG((9, "sending disconnect"));
1144 while (!EMPTYLIST(phead
)) {
1145 current
= dequeue(phead
);
1146 call
= current
->c_cp
;
1147 if (t_snddis(fd
, call
) < 0) {
1148 if (t_errno
== TLOOK
) {
1149 DEBUG((9, "collision during snddis"));
1150 pqueue(phead
, current
);
1154 tli_error(E_T_SNDDIS
, CONTINUE
);
1156 sprintf(scratch
, "Incoming call while disabled: fd %d, seq %d", fd
, call
->sequence
);
1157 logmessage(scratch
);
1159 queue(Free_call_p
, current
);
1166 * trycon: try to accept a connection
1170 trycon(struct call_list
*phead
, int fd
)
1172 struct callsave
*current
;
1173 struct t_call
*call
;
1177 char scratch
[BUFSIZ
];
1178 extern dbf_t
*getentry();
1180 DEBUG((9, "in trycon"));
1181 while (!EMPTYLIST(phead
)) {
1182 current
= dequeue(phead
);
1183 call
= current
->c_cp
;
1185 if ((dbp
= getentry(fd
)) == NULL
) {
1186 sprintf(scratch
, "No service bound to incoming fd %d: call disconnected", fd
);
1187 logmessage(scratch
);
1190 queue(Free_call_p
, current
);
1194 if (dbp
->dbf_flags
& DBF_OFF
) {
1195 sprintf(scratch
, "Request for service on fd %d denied: disabled", fd
);
1196 logmessage(scratch
);
1199 queue(Free_call_p
, current
);
1203 DEBUG((9, "try to accept #%d", call
->sequence
));
1206 if ((Acceptfd
= open_bind(NULL
, 0, 0, (unsigned int *) 0, NULL
)) != 0) {
1207 error(E_OPENBIND
, CONTINUE
);
1209 queue(Free_call_p
, current
);
1210 continue; /* let transport provider generate disconnect */
1213 if (t_accept(fd
, Acceptfd
, call
) < 0) {
1214 if (t_errno
== TLOOK
) {
1217 if (dup(Passfd
) != 0)
1218 logmessage("Trouble duping fd 0");
1220 logmessage("Incoming call during t_accept -- queueing current call");
1221 DEBUG((9, "save call #%d", call
->sequence
));
1222 pqueue(phead
, current
);
1228 if (dup(Passfd
) != 0)
1229 logmessage("Trouble duping fd 0");
1231 tli_error(E_T_ACCEPT
, CONTINUE
);
1233 queue(Free_call_p
, current
);
1238 sprintf(scratch
, "Connect: fd %d, svctag %s, seq %d, type %s",
1239 fd
, dbp
->dbf_svc_code
, call
->sequence
,
1240 (dbp
->dbf_sflags
& PFLAG
) ? "passfd" : "exec");
1241 logmessage(scratch
);
1243 DEBUG((9, "Accepted call %d", call
->sequence
));
1245 if (dbp
->dbf_sflags
& PFLAG
) {
1249 if (pushmod(Acceptfd
, dbp
->dbf_modules
)) {
1250 sprintf(scratch
, "Could not push modules: %s", dbp
->dbf_modules
);
1251 logmessage(scratch
);
1255 /* doconfig needs a file descriptor, so use Passfd */
1256 DEBUG((9, "Running doconfig on %s", dbp
->dbf_svc_code
));
1257 if ((i
= doconfig(Acceptfd
, dbp
->dbf_svc_code
, NOASSIGN
|NORUN
)) != 0) {
1258 DEBUG((9, "doconfig exited with code %d", i
));
1259 sprintf(scratch
, "doconfig failed on line %d of script %s", i
, dbp
->dbf_svc_code
);
1260 logmessage(scratch
);
1264 /* open pipe to pass fd through */
1265 if ((Passfd
= open(dbp
->dbf_cmd_line
, O_WRONLY
)) < 0) {
1267 sprintf(scratch
,"Open failed: %s", dbp
->dbf_cmd_line
);
1268 logmessage(scratch
);
1272 if (ioctl(Passfd
, I_SENDFD
, Acceptfd
) < 0) {
1273 /* clean up call, log error */
1274 sprintf(scratch
,"Passfd failed: %s", dbp
->dbf_cmd_line
);
1275 logmessage(scratch
);
1278 /* clean up this call */
1282 Acceptfd
= open("/dev/null", O_RDWR
);
1283 Passfd
= dup(Acceptfd
);
1284 queue(Free_call_p
, current
);
1287 if ((pid
= fork()) < 0)
1288 log(E_FORK_SERVICE
);
1291 /* so log files are correct */
1294 if (senviron(call
)) {
1295 logmessage("Can't expand server's environment");
1298 start_server(Acceptfd
, dbp
);
1302 exit(1); /* server failed, don't log */
1305 /* only parent gets here */
1308 queue(Free_call_p
, current
);
1310 if (dup(Passfd
) != 0)
1311 logmessage("Trouble duping fd 0");
1318 * common code to start a server process (for any service)
1319 * The first argument in argv is the full pathname of server.
1320 * Before exec-ing the server, the caller's
1321 * logical address, opt and udata are addded to the environment.
1324 static char homeenv
[BUFSIZ
];
1325 static char pathenv
[BUFSIZ
];
1328 start_server(netfd
, dbp
)
1334 extern char **environ
;
1335 extern char **mkdbfargv();
1336 struct passwd
*pwdp
;
1342 argvp
= mkdbfargv(dbp
);
1345 /* set up stdout and stderr before pushing optional modules */
1346 /* this child doesn't need access to _sacpipe and _pmpipe */
1348 (void) close(Sacpipefd
);
1349 (void) close(Pmpipefd
);
1351 if (dbp
->dbf_flags
& DBF_UTMP
) {
1355 char dummy
[PMTAGSIZE
+ 1];
1356 struct utmpx utline
;
1359 * create a utmpx entry --
1360 * we do an extra fork here to make init this process's
1361 * parent. this lets init clean up the utmpx entry when
1364 * the utmpx routines need a file descriptor!
1367 DEBUG((9, "Creating a utmpx entry for this service "));
1368 if ((tmp
= fork()) < 0) {
1369 logmessage("Can't fork to create utmpx entry");
1373 exit(0); /* kill parent */
1376 * child continues processing, creating utmp and exec'ing
1381 if (fstat(0, &sbuf
) < 0) {
1382 logmessage("Stat failed on fd 0: no line field "
1383 "available for utmpx entry");
1387 if (minor(sbuf
.st_rdev
) < 100)
1388 sprintf(device
, "%.9s%02d", Minor_prefix
,
1389 minor(sbuf
.st_rdev
));
1391 sprintf(device
, "%.8s%03d", Minor_prefix
,
1392 minor(sbuf
.st_rdev
));
1393 DEBUG((9, "Device: %s", device
));
1396 * prepend a "." so this can be distinguished as a "funny"
1397 * utmpx entry that may never get a DEAD_PROCESS entry in
1400 sprintf(dummy
, ".%s", Mytag
);
1401 /* XXX - utmp - fix login name length */
1402 strncpy(utline
.ut_user
, dummy
, sizeof (utline
.ut_user
) - 1);
1403 sprintf(utline
.ut_id
, "ls%c%c", SC_WILDC
, SC_WILDC
);
1404 strncpy(utline
.ut_line
, device
, sizeof (utline
.ut_line
) - 1);
1405 utline
.ut_pid
= getpid();
1406 utline
.ut_type
= USER_PROCESS
;
1407 utline
.ut_exit
.e_termination
= 0;
1408 utline
.ut_exit
.e_exit
= 0;
1409 utline
.ut_xtime
= (time_t) time((time_t *)0);
1413 if (dup(0) != 1 || dup(0) != 2) {
1414 logmessage("Dup of fd 0 failed");
1415 exit(2); /* server, don't log */
1419 if (pushmod(netfd
, dbp
->dbf_modules
)) {
1420 logmessage("Can't push server's modules: exit");
1421 exit(2); /* server, don't log */
1426 DEBUG((9, "Running doconfig on %s", dbp
->dbf_svc_code
));
1427 if ((i
= doconfig(Acceptfd
, dbp
->dbf_svc_code
, 0)) != 0) {
1428 DEBUG((9, "doconfig exited with code %d", i
));
1429 sprintf(msgbuf
, "doconfig failed on line %d of script %s", i
, dbp
->dbf_svc_code
);
1434 if ((pwdp
= getpwnam(dbp
->dbf_id
)) == NULL
) {
1435 sprintf(msgbuf
, "Missing or bad passwd entry for <%s>",dbp
->dbf_id
);
1437 exit(2); /* server, don't log */
1440 if (setgid(pwdp
->pw_gid
)) {
1441 if ((grpp
= getgrgid(pwdp
->pw_gid
)) == NULL
) {
1442 sprintf(msgbuf
, "No group entry for %ld", pwdp
->pw_gid
);
1444 exit(2); /* server, don't log */
1446 sprintf(msgbuf
, "Cannot set group id to %s", grpp
->gr_name
);
1448 exit(2); /* server, don't log */
1451 if (setuid(pwdp
->pw_uid
)) {
1452 sprintf(msgbuf
, "Cannot set user id to %s", dbp
->dbf_id
);
1454 exit(2); /* server, don't log */
1457 if (chdir(pwdp
->pw_dir
)) {
1458 sprintf(msgbuf
, "Cannot chdir to %s", pwdp
->pw_dir
);
1460 exit(2); /* server, don't log */
1464 DEBUG((9, "New uid %ld New gid %ld", getuid(), getgid()));
1466 sprintf(homeenv
, "HOME=%s", pwdp
->pw_dir
);
1469 sprintf(pathenv
, "PATH=/usr/bin:");
1471 sprintf(pathenv
, "PATH=/usr/sbin:/usr/bin");
1476 execve(path
, argvp
, environ
);
1478 /* exec returns only on failure! */
1480 logmessage("ERROR: could not exec server");
1481 sys_error(E_SYS_ERROR
, CONTINUE
);
1487 * senviron: Update environment before exec-ing the server:
1488 * The callers logical address is placed in the
1489 * environment in hex/ascii character representation.
1491 * Note: no need to free the malloc'ed buffers since this process
1492 * will either exec or exit.
1495 static char provenv
[2*PATHSIZE
];
1496 static char prefenv
[2*PATHSIZE
];
1500 struct t_call
*call
;
1503 extern void nlsaddr2c();
1504 extern char *getenv();
1508 * The following code handles the case where the listener was started with
1509 * no environment. If so, supply a reasonable default path. Parent already
1510 * set TZ on startup if it wasn't, so don't need to do it here.
1513 if (getenv("PATH") == NULL
)
1514 putenv("PATH=/usr/sbin:/usr/bin");
1516 if ((p
= (char *)malloc(((call
->addr
.len
)<<1) + 18)) == NULL
)
1520 nlsaddr2c(p
+ strlen(p
), call
->addr
.buf
, (int)call
->addr
.len
);
1521 DEBUG((7, "Adding %s to server's environment", p
));
1524 if ((p
= (char *)malloc(((call
->opt
.len
)<<1) + 16)) == NULL
)
1528 nlsaddr2c(p
+ strlen(p
), call
->opt
.buf
, (int)call
->opt
.len
);
1529 DEBUG((7, "Adding %s to server's environment", p
));
1533 strcpy(p
, NLSPROVIDER
);
1536 DEBUG((7, "Adding %s to environment", p
));
1540 * MPREFIX is NEW for SVR4.0. It tells the nlps_server what to use
1541 * as a minor device prefix. THIS SHOULD BE DOCUMENTED!
1544 strcpy(p
, "MPREFIX");
1546 strcat(p
, Minor_prefix
);
1547 DEBUG((7, "Adding %s to environment", p
));
1550 if ((p
= (char *)malloc(((call
->udata
.len
)<<1) + 20)) == NULL
)
1552 strcpy(p
, NLSUDATA
);
1554 if ((int)call
->udata
.len
>= 0)
1555 nlsaddr2c(p
+ strlen(p
), call
->udata
.buf
, (int)call
->udata
.len
);
1562 * parse: Parse TZ= string like init does for consistency
1563 * Work on string in place since result will
1564 * either be the same or shorter.
1573 char scratch
[BUFSIZ
];
1576 tp
= p
= s
+ strlen("TZ="); /* skip TZ= in parsing */
1577 if ((*p
== '"') || (*p
== '\'')) {
1582 /* etc/default/init ill-formed, go without TZ */
1583 sprintf(scratch
, "%s ill-formed", TZFILE
);
1584 logmessage(scratch
);
1597 else { /* look for comment or trailing whitespace */
1598 for ( ; *p
&& !isspace(*p
) && *p
!= '#'; ++p
)
1600 /* if a comment or trailing whitespace, trash it */
1610 * clr_call: clear out a call structure
1614 clr_call(struct t_call
*call
)
1619 call
->udata
.len
= 0;
1620 memset(call
->addr
.buf
, 0, (int)call
->addr
.maxlen
);
1621 memset(call
->opt
.buf
, 0, (int)call
->opt
.maxlen
);
1622 memset(call
->udata
.buf
, 0, (int)call
->udata
.maxlen
);
1627 * pitchcall: remove call from pending list
1631 pitchcall(struct call_list
*pending
, struct t_discon
*discon
)
1633 struct callsave
*p
, *oldp
;
1635 DEBUG((9, "pitching call, sequence # is %d", discon
->sequence
));
1636 if (EMPTYLIST(pending
)) {
1637 discon
->sequence
= -1;
1640 p
= pending
->cl_head
;
1643 if (p
->c_cp
->sequence
== discon
->sequence
) {
1645 pending
->cl_head
= p
->c_np
;
1646 if (pending
->cl_head
== NULL
) {
1647 pending
->cl_tail
= NULL
;
1650 else if (p
== pending
->cl_tail
) {
1651 oldp
->c_np
= p
->c_np
;
1652 pending
->cl_tail
= oldp
;
1655 oldp
->c_np
= p
->c_np
;
1658 queue(Free_call_p
, p
);
1659 discon
->sequence
= -1;
1665 logmessage("received disconnect with no pending call");
1666 discon
->sequence
= -1;
1671 * add_prvaddr: open and bind the private address specified in the database
1672 * entry passed into the routine. Update the maxcon and fd
1673 * entries in the database structure
1675 * This routine is very sloppy with malloc'ed memory, but addresses
1676 * shouldn't ever change enough for this to matter.
1683 extern char *t_alloc();
1685 struct call_list
*temp_pend
;
1686 struct callsave
*tmp
;
1687 char scratch
[BUFSIZ
];
1689 extern struct netbuf
*stoa();
1690 char str
[NAMEBUFSZ
];
1692 struct netbuf netbuf
;
1697 DEBUG((9,"in add_prvaddr, addr %s, svc %s",
1698 (dbp
->dbf_sflags
& DFLAG
) ? "DYNAMIC" : dbp
->dbf_prv_adr
,
1699 dbp
->dbf_svc_code
));
1703 if (!(dbp
->dbf_sflags
& DFLAG
)) {
1704 strcpy(lstr
, dbp
->dbf_prv_adr
);
1706 /* call stoa - convert from rfs address to netbuf */
1708 if (stoa(lstr
, &netbuf
) == NULL
) {
1709 DEBUG((9,"stoa returned null, errno = %d\n",errno
));
1718 if ((bindfd
= open_bind(netbuf
.buf
, MAXCON
, clen
, &maxcon
, &ap
)) < 0) {
1724 sprintf(scratch
, " Service %s ignored: out of file descriptors", dbp
->dbf_svc_code
);
1725 logmessage(scratch
);
1729 sprintf(scratch
, " Service %s ignored: unable to bind requested address", dbp
->dbf_svc_code
);
1730 logmessage(scratch
);
1734 error(E_OPENBIND
, EXIT
);
1738 sprintf(scratch
,"Service %s: fd %d dynamic addr %s", dbp
->dbf_svc_code
, bindfd
, ap
);
1739 dbp
->dbf_prv_adr
= ap
;
1742 sprintf(scratch
,"Service %s: fd %d addr %s", dbp
->dbf_svc_code
, bindfd
, dbp
->dbf_prv_adr
);
1744 logmessage(scratch
);
1746 temp_pend
= Priv_call
+ bindfd
;
1747 dbp
->dbf_fd
= bindfd
;
1748 dbp
->dbf_maxcon
= maxcon
;
1749 temp_pend
->cl_head
= NULL
;
1750 temp_pend
->cl_tail
= NULL
;
1751 for (j
=0; j
< maxcon
; ++j
) {
1752 if ((tmp
= (struct callsave
*) malloc(sizeof(struct callsave
))) == NULL
) {
1753 error (E_MALLOC
, NOCORE
| EXIT
);
1755 if ((tmp
->c_cp
= (struct t_call
*) t_alloc(bindfd
, T_CALL
,
1757 tli_error(E_T_ALLOC
,EXIT
);
1759 queue(Free_call_p
, tmp
);
1765 * mod_prvaddr -- after re-reading the database, take appropriate action for
1766 * new, deleted, or changed addresses.
1773 char scratch
[BUFSIZ
];
1774 dbf_t
*svc_code_match();
1778 DEBUG((9, "in mod_prvaddr..."));
1780 * for each entry in the new table, check for a svc code match.
1781 * if there is a svc code match and the address matches, all we
1782 * need to do is update the new table. if the addresses are
1783 * different, we need to remove the old one and replace it.
1785 for (entry_p
= Newdbf
; entry_p
&& entry_p
->dbf_svc_code
; entry_p
++) {
1786 if ((oldentry_p
= svc_code_match(entry_p
->dbf_svc_code
)) != NULL
) {
1787 /* matched svc code. see if address matches. */
1788 DEBUG((9, "MATCHED service code"));
1789 if ((strcmp(oldentry_p
->dbf_prv_adr
, entry_p
->dbf_prv_adr
) == 0) || ((oldentry_p
->dbf_sflags
& DFLAG
) && (entry_p
->dbf_sflags
& DFLAG
))) {
1790 DEBUG((9, "SAME addresses, old %s, new %s",
1791 oldentry_p
->dbf_prv_adr
, entry_p
->dbf_prv_adr
));
1792 /* update new table with fd, set old fd to -1 */
1793 DEBUG((9, "Old fd %d", oldentry_p
->dbf_fd
));
1794 entry_p
->dbf_fd
= oldentry_p
->dbf_fd
;
1795 entry_p
->dbf_maxcon
= oldentry_p
->dbf_maxcon
;
1796 oldentry_p
->dbf_fd
= -1;
1797 if ((oldentry_p
->dbf_sflags
& DFLAG
) && (entry_p
->dbf_sflags
& DFLAG
)) {
1798 entry_p
->dbf_prv_adr
= oldentry_p
->dbf_prv_adr
;
1800 if (entry_p
->dbf_fd
!= -1) {
1801 sprintf(scratch
, "Service %s: fd %d addr %s",
1802 entry_p
->dbf_svc_code
, entry_p
->dbf_fd
,
1803 entry_p
->dbf_prv_adr
);
1804 logmessage(scratch
);
1806 if ((oldentry_p
->dbf_version
!= entry_p
->dbf_version
) || (oldentry_p
->dbf_prognum
!= entry_p
->dbf_prognum
)) {
1807 rpc_unregister(oldentry_p
);
1808 rpc_register(entry_p
);
1814 /* now unbind the remaining addresses in the old table (fd != -1) */
1816 for (oldentry_p
= Dbfhead
; oldentry_p
&& oldentry_p
->dbf_svc_code
; oldentry_p
++) {
1817 if (oldentry_p
->dbf_fd
!= -1) {
1818 DEBUG((9, "deleting %s", oldentry_p
->dbf_svc_code
));
1819 if (del_prvaddr(oldentry_p
) == 0)
1824 /* now bind all of the new addresses (fd == -1) */
1826 * this tries to bind any addresses that failed to bind successfully
1827 * when the address changed. This means that if a service is moved to
1828 * an address that is being deleted, the first attempt to bind it will
1829 * fail, the old address will be removed, and this bind will succeed
1832 /* first the static addrs */
1833 for (entry_p
= Newdbf
; entry_p
&& entry_p
->dbf_svc_code
; entry_p
++) {
1834 if ((entry_p
->dbf_fd
== -1) && (!(entry_p
->dbf_sflags
& DFLAG
))) {
1835 DEBUG((9, "adding %s", entry_p
->dbf_svc_code
));
1836 if (add_prvaddr(entry_p
) == 0)
1840 /* then the dynamic addrs */
1841 for (entry_p
= Newdbf
; entry_p
&& entry_p
->dbf_svc_code
; entry_p
++) {
1842 if ((entry_p
->dbf_fd
== -1) && (entry_p
->dbf_sflags
& DFLAG
)) {
1843 DEBUG((9, "adding %s", entry_p
->dbf_svc_code
));
1844 if (add_prvaddr(entry_p
) == 0)
1849 /* free old database, set up new pollfd table, and we're done */
1852 free(Server_cmd_lines
);
1855 Server_cmd_lines
= New_cmd_lines
;
1856 sprintf(scratch
, "Re-read complete, %d %s bound, %d fds free", Valid_addrs
,
1857 (Valid_addrs
== 1) ? "address" : "addresses",
1858 Ndesc
-Valid_addrs
-USEDFDS
);
1859 logmessage(scratch
);
1861 /* Pollfds[0] is for _pmpipe */
1863 for (entry_p
= Dbfhead
; entry_p
&& entry_p
->dbf_svc_code
; entry_p
++) {
1864 if (entry_p
->dbf_fd
>= 0) {
1865 sp
->fd
= entry_p
->dbf_fd
;
1866 DEBUG((9, "adding %d to poll struct", entry_p
->dbf_fd
));
1867 sp
->events
= POLLIN
;
1875 * unbind the address, close the file descriptor, and free call structs
1882 struct callsave
*tmp
;
1883 struct call_list
*q
;
1884 struct t_call
*call
;
1886 char scratch
[BUFSIZ
];
1888 DEBUG((9, "in del_prvaddr..."));
1889 rpc_unregister(dbp
);
1890 if (dbp
->dbf_fd
< 0)
1893 q
= Priv_call
+ dbp
->dbf_fd
;
1896 /* delete pending calls */
1897 while ((tmp
= dequeue(q
)) != NULL
) {
1900 t_snddis(dbp
->dbf_fd
, call
);
1901 t_free((char *)call
, T_CALL
);
1905 /* delete free call structs we don't need */
1906 for ( ; i
< dbp
->dbf_maxcon
; i
++) {
1907 tmp
= dequeue(Free_call_p
);
1908 t_free((char *)tmp
->c_cp
, T_CALL
);
1912 t_unbind(dbp
->dbf_fd
);
1913 t_close(dbp
->dbf_fd
);
1914 sprintf(scratch
, "Unbind %s: fd %d addr %s", dbp
->dbf_svc_code
,
1915 dbp
->dbf_fd
, dbp
->dbf_prv_adr
);
1916 logmessage(scratch
);
1923 * look through the old database file to see if this service code matches
1924 * one already present
1928 svc_code_match(new_code
)
1933 for (dbp
= Dbfhead
; dbp
&& dbp
->dbf_svc_code
; dbp
++) {
1934 if (strcmp(dbp
->dbf_svc_code
, new_code
) == 0)
1937 return((dbf_t
*)NULL
);
1942 * register an rpc service with rpcbind
1949 char str
[NAMEBUFSZ
];
1950 char scratch
[BUFSIZ
];
1952 struct netbuf netbuf
;
1953 extern struct netbuf
*stoa();
1956 DEBUG((9, "in rpc_register"));
1957 if (dbp
->dbf_prognum
== -1 || dbp
->dbf_version
== -1)
1958 /* not an rpc service */
1961 rpc_unregister(dbp
);
1965 strcpy(lstr
, dbp
->dbf_prv_adr
);
1966 if (stoa(lstr
, &netbuf
) == NULL
) {
1967 DEBUG((9,"stoa returned null, errno = %d\n",errno
));
1971 if (rpcb_set(dbp
->dbf_prognum
, dbp
->dbf_version
, Netconf
, &netbuf
)) {
1972 sprintf(scratch
," registered with rpcbind, prognum %d version %d", dbp
->dbf_prognum
, dbp
->dbf_version
);
1973 logmessage(scratch
);
1976 logmessage("rpcb_set failed, service not registered with rpcbind");
1983 * unregister an rpc service with rpcbind
1990 DEBUG((9, "in rpc_unregister"));
1991 if (dbp
->dbf_prognum
== -1 || dbp
->dbf_version
== -1)
1992 /* not an rpc service */
1994 (void) rpcb_unset(dbp
->dbf_prognum
, dbp
->dbf_version
, Netconf
);