2 * Copyright (c) 1992/3 Theo de Raadt <deraadt@fsa.ca>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote
14 * products derived from this software without specific prior written
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * $FreeBSD: src/usr.sbin/ypbind/ypbind.c,v 1.30.2.2 2002/02/15 00:46:59 des Exp $
30 * $DragonFly: src/usr.sbin/ypbind/ypbind.c,v 1.6 2005/11/24 22:23:02 swildner Exp $
33 #include <sys/param.h>
34 #include <sys/types.h>
36 #include <sys/ioctl.h>
37 #include <sys/signal.h>
38 #include <sys/socket.h>
40 #include <sys/fcntl.h>
57 #include <netinet/in.h>
58 #include <arpa/inet.h>
59 #include <rpc/pmap_clnt.h>
60 #include <rpc/pmap_prot.h>
61 #include <rpc/pmap_rmt.h>
62 #include <rpc/rpc_com.h>
63 #include <rpcsvc/yp.h>
65 #include <rpcsvc/ypclnt.h>
69 #define BINDINGDIR "/var/yp/binding"
73 #define YPBINDLOCK "/var/run/ypbind.lock"
77 struct _dom_binding
*dom_pnext
;
78 char dom_domain
[YPMAXDOMAIN
+ 1];
79 struct sockaddr_in dom_server_addr
;
83 int dom_broadcast_pid
;
88 #define READFD ypdb->dom_pipe_fds[0]
89 #define WRITEFD ypdb->dom_pipe_fds[1]
90 #define BROADFD broad_domain->dom_pipe_fds[1]
92 extern bool_t
xdr_domainname(), xdr_ypbind_resp();
93 extern bool_t
xdr_ypreq_key(), xdr_ypresp_val();
94 extern bool_t
xdr_ypbind_setdom();
97 void *ypbindproc_null_2_yp(SVCXPRT
*, void *, CLIENT
*);
98 void *ypbindproc_setdom_2_yp(SVCXPRT
*, struct ypbind_setdom
*, CLIENT
*);
99 void rpc_received(char *, struct sockaddr_in
*, int);
100 void broadcast(struct _dom_binding
*);
101 int ping(struct _dom_binding
*);
102 int tell_parent(char *, struct sockaddr_in
*);
103 void handle_children(struct _dom_binding
*);
106 void yp_restricted_mode(char *);
107 int verify(struct in_addr
);
110 struct _dom_binding
*ypbindlist
;
111 static struct _dom_binding
*broad_domain
;
114 #define YPSET_LOCAL 1
116 int ypsetmode
= YPSET_NO
;
117 int ypsecuremode
= 0;
121 * Special restricted mode variables: when in restricted mode, only the
122 * specified restricted_domain will be bound, and only the servers listed
123 * in restricted_addrs will be used for binding.
125 #define RESTRICTED_SERVERS 10
126 int yp_restricted
= 0;
128 struct in_addr restricted_addrs
[RESTRICTED_SERVERS
];
130 /* No more than MAX_CHILDREN child broadcasters at a time. */
132 #define MAX_CHILDREN 5
134 /* No more than MAX_DOMAINS simultaneous domains */
136 #define MAX_DOMAINS 200
138 /* RPC timeout value */
139 #ifndef FAIL_THRESHOLD
140 #define FAIL_THRESHOLD 20
143 /* Number of times to fish for a response froma particular set of hosts */
145 #define MAX_RETRIES 30
154 SVCXPRT
*udptransp
, *tcptransp
;
157 ypbindproc_null_2_yp(SVCXPRT
*transp
, void *argp
, CLIENT
*clnt
)
161 bzero((char *)&res
, sizeof(res
));
166 ypbindproc_domain_2_yp(SVCXPRT
*transp
, domainname
*argp
, CLIENT
*clnt
)
168 static struct ypbind_resp res
;
169 struct _dom_binding
*ypdb
;
170 char path
[MAXPATHLEN
];
172 bzero((char *)&res
, sizeof res
);
173 res
.ypbind_status
= YPBIND_FAIL_VAL
;
174 res
.ypbind_resp_u
.ypbind_error
= YPBIND_ERR_NOSERV
;
176 if (strchr(*argp
, '/')) {
177 syslog(LOG_WARNING
, "Domain name '%s' has embedded slash -- \
182 for (ypdb
= ypbindlist
; ypdb
; ypdb
= ypdb
->dom_pnext
) {
183 if (strcmp(ypdb
->dom_domain
, *argp
) == 0)
189 syslog(LOG_NOTICE
, "Running in restricted mode -- request to bind domain \"%s\" rejected.\n", *argp
);
193 if (domains
>= MAX_DOMAINS
) {
194 syslog(LOG_WARNING
, "domain limit (%d) exceeded",
196 res
.ypbind_resp_u
.ypbind_error
= YPBIND_ERR_RESC
;
199 ypdb
= (struct _dom_binding
*)malloc(sizeof *ypdb
);
201 syslog(LOG_WARNING
, "malloc: %m");
202 res
.ypbind_resp_u
.ypbind_error
= YPBIND_ERR_RESC
;
205 bzero((char *)ypdb
, sizeof *ypdb
);
206 strncpy(ypdb
->dom_domain
, *argp
, sizeof ypdb
->dom_domain
);
207 ypdb
->dom_vers
= YPVERS
;
209 ypdb
->dom_default
= 0;
210 ypdb
->dom_lockfd
= -1;
211 sprintf(path
, "%s/%s.%ld", BINDINGDIR
,
212 ypdb
->dom_domain
, ypdb
->dom_vers
);
214 ypdb
->dom_pnext
= ypbindlist
;
223 res
.ypbind_status
= YPBIND_SUCC_VAL
;
224 res
.ypbind_resp_u
.ypbind_error
= 0; /* Success */
225 *(u_int32_t
*)&res
.ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_addr
=
226 ypdb
->dom_server_addr
.sin_addr
.s_addr
;
227 *(u_short
*)&res
.ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_port
=
228 ypdb
->dom_server_addr
.sin_port
;
229 /*printf("domain %s at %s/%d\n", ypdb->dom_domain,
230 inet_ntoa(ypdb->dom_server_addr.sin_addr),
231 ntohs(ypdb->dom_server_addr.sin_port));*/
236 ypbindproc_setdom_2_yp(SVCXPRT
*transp
, ypbind_setdom
*argp
, CLIENT
*clnt
)
238 struct sockaddr_in
*fromsin
, bindsin
;
239 static char *result
= NULL
;
241 if (strchr(argp
->ypsetdom_domain
, '/')) {
242 syslog(LOG_WARNING
, "Domain name '%s' has embedded slash -- \
243 rejecting.", argp
->ypsetdom_domain
);
246 fromsin
= svc_getcaller(transp
);
250 if (fromsin
->sin_addr
.s_addr
!= htonl(INADDR_LOOPBACK
)) {
251 svcerr_noprog(transp
);
259 svcerr_noprog(transp
);
263 if (ntohs(fromsin
->sin_port
) >= IPPORT_RESERVED
) {
264 svcerr_noprog(transp
);
268 if (argp
->ypsetdom_vers
!= YPVERS
) {
269 svcerr_noprog(transp
);
273 bzero((char *)&bindsin
, sizeof bindsin
);
274 bindsin
.sin_family
= AF_INET
;
275 bindsin
.sin_addr
.s_addr
= *(u_int32_t
*)argp
->ypsetdom_binding
.ypbind_binding_addr
;
276 bindsin
.sin_port
= *(u_short
*)argp
->ypsetdom_binding
.ypbind_binding_port
;
277 rpc_received(argp
->ypsetdom_domain
, &bindsin
, 1);
279 return((void *) &result
);
283 ypbindprog_2(struct svc_req
*rqstp
, SVCXPRT
*transp
)
286 domainname ypbindproc_domain_2_arg
;
287 struct ypbind_setdom ypbindproc_setdom_2_arg
;
289 struct authunix_parms
*creds
;
291 bool_t (*xdr_argument
)(), (*xdr_result
)();
294 switch (rqstp
->rq_proc
) {
295 case YPBINDPROC_NULL
:
296 xdr_argument
= xdr_void
;
297 xdr_result
= xdr_void
;
298 local
= (char *(*)()) ypbindproc_null_2_yp
;
301 case YPBINDPROC_DOMAIN
:
302 xdr_argument
= xdr_domainname
;
303 xdr_result
= xdr_ypbind_resp
;
304 local
= (char *(*)()) ypbindproc_domain_2_yp
;
307 case YPBINDPROC_SETDOM
:
308 switch (rqstp
->rq_cred
.oa_flavor
) {
310 creds
= (struct authunix_parms
*)rqstp
->rq_clntcred
;
311 if (creds
->aup_uid
!= 0) {
312 svcerr_auth(transp
, AUTH_BADCRED
);
317 svcerr_auth(transp
, AUTH_TOOWEAK
);
321 xdr_argument
= xdr_ypbind_setdom
;
322 xdr_result
= xdr_void
;
323 local
= (char *(*)()) ypbindproc_setdom_2_yp
;
327 svcerr_noproc(transp
);
330 bzero((char *)&argument
, sizeof(argument
));
331 if (!svc_getargs(transp
, xdr_argument
, (caddr_t
)&argument
)) {
332 svcerr_decode(transp
);
335 result
= (*local
)(transp
, &argument
, rqstp
);
336 if (result
!= NULL
&& !svc_sendreply(transp
, xdr_result
, result
)) {
337 svcerr_systemerr(transp
);
342 /* Jack the reaper */
348 while (wait3(&st
, WNOHANG
, NULL
) > 0)
355 struct _dom_binding
*ypdb
;
356 char path
[MAXPATHLEN
];
358 if (ppid
!= getpid())
361 for (ypdb
= ypbindlist
; ypdb
; ypdb
= ypdb
->dom_pnext
) {
362 close(ypdb
->dom_lockfd
);
363 if (ypdb
->dom_broadcast_pid
)
364 kill(ypdb
->dom_broadcast_pid
, SIGINT
);
365 sprintf(path
, "%s/%s.%ld", BINDINGDIR
,
366 ypdb
->dom_domain
, ypdb
->dom_vers
);
371 pmap_unset(YPBINDPROG
, YPBINDVERS
);
376 main(int argc
, char **argv
)
382 struct _dom_binding
*ypdb
, *next
;
384 /* Check that another ypbind isn't already running. */
385 if ((yplockfd
= (open(YPBINDLOCK
, O_RDONLY
|O_CREAT
, 0444))) == -1)
386 err(1, "%s", YPBINDLOCK
);
388 if (flock(yplockfd
, LOCK_EX
|LOCK_NB
) == -1 && errno
== EWOULDBLOCK
)
389 errx(1, "another ypbind is already running. Aborting");
391 /* XXX domainname will be overriden if we use restricted mode */
392 yp_get_default_domain(&domain_name
);
393 if (domain_name
[0] == '\0')
394 errx(1, "domainname not set. Aborting");
396 for (i
= 1; i
<argc
; i
++) {
397 if (strcmp("-ypset", argv
[i
]) == 0)
398 ypsetmode
= YPSET_ALL
;
399 else if (strcmp("-ypsetme", argv
[i
]) == 0)
400 ypsetmode
= YPSET_LOCAL
;
401 else if (strcmp("-s", argv
[i
]) == 0)
403 else if (strcmp("-S", argv
[i
]) == 0 && argc
> i
)
404 yp_restricted_mode(argv
[i
+1]);
405 else if (strcmp("-m", argv
[i
]) == 0)
409 /* blow away everything in BINDINGDIR (if it exists) */
411 if ((dird
= opendir(BINDINGDIR
)) != NULL
) {
412 char path
[MAXPATHLEN
];
413 while ((dirp
= readdir(dird
)) != NULL
)
414 if (strcmp(dirp
->d_name
, ".") &&
415 strcmp(dirp
->d_name
, "..")) {
416 sprintf(path
,"%s/%s",BINDINGDIR
,dirp
->d_name
);
427 pmap_unset(YPBINDPROG
, YPBINDVERS
);
429 udptransp
= svcudp_create(RPC_ANYSOCK
);
430 if (udptransp
== NULL
)
431 errx(1, "cannot create udp service");
432 if (!svc_register(udptransp
, YPBINDPROG
, YPBINDVERS
, ypbindprog_2
,
434 errx(1, "unable to register (YPBINDPROG, YPBINDVERS, udp)");
436 tcptransp
= svctcp_create(RPC_ANYSOCK
, 0, 0);
437 if (tcptransp
== NULL
)
438 errx(1, "cannot create tcp service");
440 if (!svc_register(tcptransp
, YPBINDPROG
, YPBINDVERS
, ypbindprog_2
,
442 errx(1, "unable to register (YPBINDPROG, YPBINDVERS, tcp)");
444 /* build initial domain binding, make it "unsuccessful" */
445 ypbindlist
= (struct _dom_binding
*)malloc(sizeof *ypbindlist
);
446 if (ypbindlist
== NULL
)
448 bzero((char *)ypbindlist
, sizeof *ypbindlist
);
449 strncpy(ypbindlist
->dom_domain
, domain_name
, sizeof ypbindlist
->dom_domain
);
450 ypbindlist
->dom_vers
= YPVERS
;
451 ypbindlist
->dom_alive
= 0;
452 ypbindlist
->dom_lockfd
= -1;
453 ypbindlist
->dom_default
= 1;
456 signal(SIGCHLD
, reaper
);
457 signal(SIGTERM
, terminate
);
459 ppid
= getpid(); /* Remember who we are. */
461 openlog(argv
[0], LOG_PID
, LOG_DAEMON
);
463 /* Kick off the default domain */
464 broadcast(ypbindlist
);
472 switch (select(_rpc_dtablesize(), &fdsr
, NULL
, NULL
, &tv
)) {
478 syslog(LOG_WARNING
, "select: %m");
481 for (ypdb
= ypbindlist
; ypdb
; ypdb
= next
) {
482 next
= ypdb
->dom_pnext
;
483 if (READFD
> 0 && FD_ISSET(READFD
, &fdsr
)) {
484 handle_children(ypdb
);
485 if (children
== (MAX_CHILDREN
- 1))
489 svc_getreqset(&fdsr
);
501 struct _dom_binding
*ypdb
;
503 for (ypdb
= ypbindlist
; ypdb
; ypdb
= ypdb
->dom_pnext
)
507 /* The clnt_broadcast() callback mechanism sucks. */
510 * Receive results from broadcaster. Don't worry about passing
511 * bogus info to rpc_received() -- it can handle it. Note that we
512 * must be sure to invalidate the dom_pipe_fds descriptors here:
513 * since descriptors can be re-used, we have to make sure we
514 * don't mistake one of the RPC descriptors for one of the pipes.
515 * What's weird is that forgetting to invalidate the pipe descriptors
516 * doesn't always result in an error (otherwise I would have caught
517 * the mistake much sooner), even though logically it should.
520 handle_children(struct _dom_binding
*ypdb
)
522 char buf
[YPMAXDOMAIN
+ 1];
523 struct sockaddr_in addr
;
525 struct _dom_binding
*y
, *prev
= NULL
;
526 char path
[MAXPATHLEN
];
528 if ((d
= read(READFD
, &buf
, sizeof(buf
))) <= 0)
529 syslog(LOG_WARNING
, "could not read from child: %m");
531 if ((a
= read(READFD
, &addr
, sizeof(struct sockaddr_in
))) < 0)
532 syslog(LOG_WARNING
, "could not read from child: %m");
535 FD_CLR(READFD
, &fdsr
);
536 FD_CLR(READFD
, &svc_fdset
);
537 READFD
= WRITEFD
= -1;
539 rpc_received((char *)&buf
, &addr
, 0);
541 for (y
= ypbindlist
; y
; y
= y
->dom_pnext
) {
546 switch (ypdb
->dom_default
) {
549 ypbindlist
= y
->dom_pnext
;
551 prev
->dom_pnext
= y
->dom_pnext
;
552 sprintf(path
, "%s/%s.%ld", BINDINGDIR
,
553 ypdb
->dom_domain
, YPVERS
);
554 close(ypdb
->dom_lockfd
);
560 ypdb
->dom_broadcast_pid
= 0;
573 * Send our dying words back to our parent before we perish.
576 tell_parent(char *dom
, struct sockaddr_in
*addr
)
578 char buf
[YPMAXDOMAIN
+ 1];
579 struct timeval timeout
;
585 sprintf(buf
, "%s", broad_domain
->dom_domain
);
586 if (write(BROADFD
, &buf
, sizeof(buf
)) < 0)
590 * Stay in sync with parent: wait for it to read our first
591 * message before sending the second.
595 FD_SET(BROADFD
, &fds
);
596 if (select(FD_SETSIZE
, NULL
, &fds
, NULL
, &timeout
) == -1)
598 if (FD_ISSET(BROADFD
, &fds
)) {
599 if (write(BROADFD
, addr
, sizeof(struct sockaddr_in
)) < 0)
610 broadcast_result(caddr_t out
, struct sockaddr_in
*addr
)
612 if (retries
>= MAX_RETRIES
) {
613 bzero((char *)addr
, sizeof(struct sockaddr_in
));
614 if (tell_parent(broad_domain
->dom_domain
, addr
))
615 syslog(LOG_WARNING
, "lost connection to parent");
619 if (yp_restricted
&& verify(addr
->sin_addr
)) {
621 syslog(LOG_NOTICE
, "NIS server at %s not in restricted mode access list -- rejecting.\n",inet_ntoa(addr
->sin_addr
));
624 if (tell_parent(broad_domain
->dom_domain
, addr
))
625 syslog(LOG_WARNING
, "lost connection to parent");
631 * The right way to send RPC broadcasts.
632 * Use the clnt_broadcast() RPC service. Unfortunately, clnt_broadcast()
633 * blocks while waiting for replies, so we have to fork off separate
634 * broadcaster processes that do the waiting and then transmit their
635 * results back to the parent for processing. We also have to remember
636 * to save the name of the domain we're trying to bind in a global
637 * variable since clnt_broadcast() provides no way to pass things to
638 * the 'eachresult' callback function.
641 broadcast(struct _dom_binding
*ypdb
)
646 if (children
>= MAX_CHILDREN
|| ypdb
->dom_broadcast_pid
)
649 if (pipe(ypdb
->dom_pipe_fds
) < 0) {
650 syslog(LOG_WARNING
, "pipe: %m");
654 if (ypdb
->dom_vers
== -1 && (long)ypdb
->dom_server_addr
.sin_addr
.s_addr
)
655 syslog(LOG_WARNING
, "NIS server [%s] for domain \"%s\" not responding",
656 inet_ntoa(ypdb
->dom_server_addr
.sin_addr
), ypdb
->dom_domain
);
659 flock(ypdb
->dom_lockfd
, LOCK_UN
);
661 switch ((ypdb
->dom_broadcast_pid
= fork())) {
664 signal(SIGCHLD
, SIG_DFL
);
665 signal(SIGTERM
, SIG_DFL
);
668 syslog(LOG_WARNING
, "fork: %m");
674 FD_SET(READFD
, &svc_fdset
);
679 /* Release all locks before doing anything else. */
681 close(ypbindlist
->dom_lockfd
);
682 ypbindlist
= ypbindlist
->dom_pnext
;
687 * Special 'many-cast' behavior. If we're in restricted mode,
688 * we have a list of possible server addresses to try. What
689 * we can do is transmit to each ypserv's YPPROC_DOMAIN_NONACK
690 * procedure and time the replies. Whoever replies fastest
691 * gets to be our server. Note that this is not a broadcast
692 * operation: we transmit uni-cast datagrams only.
694 if (yp_restricted
&& yp_manycast
) {
697 struct sockaddr_in sin
;
699 i
= __yp_ping(restricted_addrs
, yp_restricted
,
700 ypdb
->dom_domain
, &port
);
702 bzero((char *)&ypdb
->dom_server_addr
,
703 sizeof(struct sockaddr_in
));
704 if (tell_parent(ypdb
->dom_domain
,
705 &ypdb
->dom_server_addr
))
706 syslog(LOG_WARNING
, "lost connection to parent");
708 bzero((char *)&sin
, sizeof(struct sockaddr_in
));
709 bcopy((char *)&restricted_addrs
[i
],
710 (char *)&sin
.sin_addr
, sizeof(struct in_addr
));
711 sin
.sin_family
= AF_INET
;
713 if (tell_parent(broad_domain
->dom_domain
, &sin
))
715 "lost connection to parent");
725 ptr
= (char *)&ypdb
->dom_domain
;
726 stat
= clnt_broadcast(YPPROG
, YPVERS
, YPPROC_DOMAIN_NONACK
,
727 xdr_domainname
, (char *)&ptr
, xdr_bool
, (char *)&out
,
731 if (stat
!= RPC_SUCCESS
) {
732 bzero((char *)&ypdb
->dom_server_addr
,
733 sizeof(struct sockaddr_in
));
734 if (tell_parent(ypdb
->dom_domain
, &ypdb
->dom_server_addr
))
735 syslog(LOG_WARNING
, "lost connection to parent");
742 * The right way to check if a server is alive.
743 * Attempt to get a client handle pointing to the server and send a
744 * YPPROC_DOMAIN. If we can't get a handle or we get a reply of FALSE,
745 * we invalidate this binding entry and send out a broadcast to try to
746 * establish a new binding. Note that we treat non-default domains
747 * specially: once bound, we keep tabs on our server, but if it
748 * goes away and fails to respond after one round of broadcasting, we
749 * abandon it until a client specifically references it again. We make
750 * every effort to keep our default domain bound, however, since we
751 * need it to keep the system on its feet.
754 ping(struct _dom_binding
*ypdb
)
757 struct timeval interval
, timeout
;
759 int rpcsock
= RPC_ANYSOCK
;
760 CLIENT
*client_handle
;
762 interval
.tv_sec
= FAIL_THRESHOLD
;
763 interval
.tv_usec
= 0;
764 timeout
.tv_sec
= FAIL_THRESHOLD
;
767 if (ypdb
->dom_broadcast_pid
)
770 if ((client_handle
= clntudp_bufcreate(&ypdb
->dom_server_addr
,
771 YPPROG
, YPVERS
, interval
, &rpcsock
, RPCSMALLMSGSIZE
,
772 RPCSMALLMSGSIZE
)) == (CLIENT
*)NULL
) {
773 /* Can't get a handle: we're dead. */
783 ptr
= (char *)&ypdb
->dom_domain
;
785 if ((stat
= clnt_call(client_handle
, YPPROC_DOMAIN
,
786 xdr_domainname
, (char *)&ptr
, xdr_bool
, (char *)&out
,
787 timeout
)) != RPC_SUCCESS
|| out
== FALSE
) {
790 clnt_destroy(client_handle
);
796 clnt_destroy(client_handle
);
801 rpc_received(char *dom
, struct sockaddr_in
*raddrp
, int force
)
803 struct _dom_binding
*ypdb
, *prev
= NULL
;
805 struct ypbind_resp ybr
;
806 char path
[MAXPATHLEN
];
809 /*printf("returned from %s/%d about %s\n", inet_ntoa(raddrp->sin_addr),
810 ntohs(raddrp->sin_port), dom);*/
815 for (ypdb
= ypbindlist
; ypdb
; ypdb
= ypdb
->dom_pnext
) {
816 if (strcmp(ypdb
->dom_domain
, dom
) == 0)
822 if (ypdb
->dom_broadcast_pid
) {
823 kill(ypdb
->dom_broadcast_pid
, SIGINT
);
825 FD_CLR(READFD
, &fdsr
);
826 FD_CLR(READFD
, &svc_fdset
);
827 READFD
= WRITEFD
= -1;
831 /* if in secure mode, check originating port number */
832 if ((ypsecuremode
&& (ntohs(raddrp
->sin_port
) >= IPPORT_RESERVED
))) {
833 syslog(LOG_WARNING
, "Rejected NIS server on [%s/%d] for domain %s.",
834 inet_ntoa(raddrp
->sin_addr
), ntohs(raddrp
->sin_port
),
837 ypdb
->dom_broadcast_pid
= 0;
843 if (raddrp
->sin_addr
.s_addr
== (long)0) {
844 switch (ypdb
->dom_default
) {
847 ypbindlist
= ypdb
->dom_pnext
;
849 prev
->dom_pnext
= ypdb
->dom_pnext
;
850 sprintf(path
, "%s/%s.%ld", BINDINGDIR
,
851 ypdb
->dom_domain
, YPVERS
);
852 close(ypdb
->dom_lockfd
);
858 ypdb
->dom_broadcast_pid
= 0;
870 ypdb
= (struct _dom_binding
*)malloc(sizeof *ypdb
);
872 syslog(LOG_WARNING
, "malloc: %m");
875 bzero((char *)ypdb
, sizeof *ypdb
);
876 strncpy(ypdb
->dom_domain
, dom
, sizeof ypdb
->dom_domain
);
877 ypdb
->dom_lockfd
= -1;
878 ypdb
->dom_default
= 0;
879 ypdb
->dom_pnext
= ypbindlist
;
883 /* We've recovered from a crash: inform the world. */
884 if (ypdb
->dom_vers
== -1 && ypdb
->dom_server_addr
.sin_addr
.s_addr
)
885 syslog(LOG_WARNING
, "NIS server [%s] for domain \"%s\" OK",
886 inet_ntoa(raddrp
->sin_addr
), ypdb
->dom_domain
);
888 bcopy((char *)raddrp
, (char *)&ypdb
->dom_server_addr
,
889 sizeof ypdb
->dom_server_addr
);
891 ypdb
->dom_vers
= YPVERS
;
893 ypdb
->dom_broadcast_pid
= 0;
895 if (ypdb
->dom_lockfd
!= -1)
896 close(ypdb
->dom_lockfd
);
898 sprintf(path
, "%s/%s.%ld", BINDINGDIR
,
899 ypdb
->dom_domain
, ypdb
->dom_vers
);
901 if ((fd
= open(path
, O_CREAT
|O_SHLOCK
|O_RDWR
|O_TRUNC
, 0644)) == -1) {
902 mkdir(BINDINGDIR
, 0755);
903 if ((fd
= open(path
, O_CREAT
|O_SHLOCK
|O_RDWR
|O_TRUNC
, 0644)) == -1)
907 if ((fd
= open(path
, O_CREAT
|O_RDWR
|O_TRUNC
, 0644)) == -1) {
908 mkdir(BINDINGDIR
, 0755);
909 if ((fd
= open(path
, O_CREAT
|O_RDWR
|O_TRUNC
, 0644)) == -1)
916 * ok, if BINDINGDIR exists, and we can create the binding file,
919 ypdb
->dom_lockfd
= fd
;
921 iov
[0].iov_base
= (caddr_t
)&(udptransp
->xp_port
);
922 iov
[0].iov_len
= sizeof udptransp
->xp_port
;
923 iov
[1].iov_base
= (caddr_t
)&ybr
;
924 iov
[1].iov_len
= sizeof ybr
;
926 bzero(&ybr
, sizeof ybr
);
927 ybr
.ypbind_status
= YPBIND_SUCC_VAL
;
928 *(u_int32_t
*)&ybr
.ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_addr
= raddrp
->sin_addr
.s_addr
;
929 *(u_short
*)&ybr
.ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_port
= raddrp
->sin_port
;
931 if (writev(ypdb
->dom_lockfd
, iov
, 2) != iov
[0].iov_len
+ iov
[1].iov_len
) {
932 syslog(LOG_WARNING
, "write: %m");
933 close(ypdb
->dom_lockfd
);
934 ypdb
->dom_lockfd
= -1;
940 * Check address against list of allowed servers. Return 0 if okay,
944 verify(struct in_addr addr
)
948 for (i
= 0; i
< RESTRICTED_SERVERS
; i
++)
949 if (!bcmp((char *)&addr
, (char *)&restricted_addrs
[i
],
950 sizeof(struct in_addr
)))
957 * Try to set restricted mode. We default to normal mode if we can't
958 * resolve the specified hostnames.
961 yp_restricted_mode(char *args
)
967 /* Find the restricted domain. */
968 if ((s
= strsep(&args
, ",")) == NULL
)
972 /* Get the addresses of the servers. */
973 while ((s
= strsep(&args
, ",")) != NULL
&& i
< RESTRICTED_SERVERS
) {
974 if ((h
= gethostbyname(s
)) == NULL
)
976 bcopy ((char *)h
->h_addr_list
[0], (char *)&restricted_addrs
[i
],
977 sizeof(struct in_addr
));
981 /* ypset and ypsetme not allowed with restricted mode */
982 ypsetmode
= YPSET_NO
;