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.40 2004/10/17 19:33:33 stefanf 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>
64 #include <rpcsvc/ypclnt.h>
68 #define BINDINGDIR "/var/yp/binding"
72 #define YPBINDLOCK "/var/run/ypbind.lock"
76 struct _dom_binding
*dom_pnext
;
77 char dom_domain
[YPMAXDOMAIN
+ 1];
78 struct sockaddr_in dom_server_addr
;
82 int dom_broadcast_pid
;
87 #define READFD ypdb->dom_pipe_fds[0]
88 #define WRITEFD ypdb->dom_pipe_fds[1]
89 #define BROADFD broad_domain->dom_pipe_fds[1]
91 extern bool_t
xdr_domainname(), xdr_ypbind_resp();
92 extern bool_t
xdr_ypreq_key(), xdr_ypresp_val();
93 extern bool_t
xdr_ypbind_setdom();
96 void *ypbindproc_null_2_yp(SVCXPRT
*, void *, CLIENT
*);
97 void *ypbindproc_setdom_2_yp(SVCXPRT
*, struct ypbind_setdom
*, CLIENT
*);
98 void rpc_received(char *, struct sockaddr_in
*, int);
99 void broadcast(struct _dom_binding
*);
100 int ping(struct _dom_binding
*);
101 int tell_parent(char *, struct sockaddr_in
*);
102 void handle_children(struct _dom_binding
*);
105 void yp_restricted_mode(char *);
106 int verify(struct in_addr
);
109 struct _dom_binding
*ypbindlist
;
110 static struct _dom_binding
*broad_domain
;
113 #define YPSET_LOCAL 1
115 int ypsetmode
= YPSET_NO
;
116 int ypsecuremode
= 0;
120 * Special restricted mode variables: when in restricted mode, only the
121 * specified restricted_domain will be bound, and only the servers listed
122 * in restricted_addrs will be used for binding.
124 #define RESTRICTED_SERVERS 10
125 int yp_restricted
= 0;
127 struct in_addr restricted_addrs
[RESTRICTED_SERVERS
];
129 /* No more than MAX_CHILDREN child broadcasters at a time. */
131 #define MAX_CHILDREN 5
133 /* No more than MAX_DOMAINS simultaneous domains */
135 #define MAX_DOMAINS 200
137 /* RPC timeout value */
138 #ifndef FAIL_THRESHOLD
139 #define FAIL_THRESHOLD 20
142 /* Number of times to fish for a response froma particular set of hosts */
144 #define MAX_RETRIES 30
153 SVCXPRT
*udptransp
, *tcptransp
;
156 ypbindproc_null_2_yp(SVCXPRT
*transp
, void *argp
, CLIENT
*clnt
)
160 bzero(&res
, sizeof(res
));
165 ypbindproc_domain_2_yp(SVCXPRT
*transp
, domainname
*argp
, CLIENT
*clnt
)
167 static struct ypbind_resp res
;
168 struct _dom_binding
*ypdb
;
169 char path
[MAXPATHLEN
];
171 bzero(&res
, sizeof res
);
172 res
.ypbind_status
= YPBIND_FAIL_VAL
;
173 res
.ypbind_resp_u
.ypbind_error
= YPBIND_ERR_NOSERV
;
175 if (strchr(*argp
, '/')) {
176 syslog(LOG_WARNING
, "Domain name '%s' has embedded slash -- \
181 for (ypdb
= ypbindlist
; ypdb
; ypdb
= ypdb
->dom_pnext
) {
182 if (strcmp(ypdb
->dom_domain
, *argp
) == 0)
188 syslog(LOG_NOTICE
, "Running in restricted mode -- request to bind domain \"%s\" rejected.\n", *argp
);
192 if (domains
>= MAX_DOMAINS
) {
193 syslog(LOG_WARNING
, "domain limit (%d) exceeded",
195 res
.ypbind_resp_u
.ypbind_error
= YPBIND_ERR_RESC
;
198 ypdb
= (struct _dom_binding
*)malloc(sizeof *ypdb
);
200 syslog(LOG_WARNING
, "malloc: %m");
201 res
.ypbind_resp_u
.ypbind_error
= YPBIND_ERR_RESC
;
204 bzero(ypdb
, sizeof *ypdb
);
205 strncpy(ypdb
->dom_domain
, *argp
, sizeof ypdb
->dom_domain
);
206 ypdb
->dom_vers
= YPVERS
;
208 ypdb
->dom_default
= 0;
209 ypdb
->dom_lockfd
= -1;
210 sprintf(path
, "%s/%s.%ld", BINDINGDIR
,
211 ypdb
->dom_domain
, ypdb
->dom_vers
);
213 ypdb
->dom_pnext
= ypbindlist
;
222 res
.ypbind_status
= YPBIND_SUCC_VAL
;
223 res
.ypbind_resp_u
.ypbind_error
= 0; /* Success */
224 *(u_int32_t
*)&res
.ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_addr
=
225 ypdb
->dom_server_addr
.sin_addr
.s_addr
;
226 *(u_short
*)&res
.ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_port
=
227 ypdb
->dom_server_addr
.sin_port
;
228 /*printf("domain %s at %s/%d\n", ypdb->dom_domain,
229 inet_ntoa(ypdb->dom_server_addr.sin_addr),
230 ntohs(ypdb->dom_server_addr.sin_port));*/
235 ypbindproc_setdom_2_yp(SVCXPRT
*transp
, ypbind_setdom
*argp
, CLIENT
*clnt
)
237 struct sockaddr_in
*fromsin
, bindsin
;
238 static char *result
= NULL
;
240 if (strchr(argp
->ypsetdom_domain
, '/')) {
241 syslog(LOG_WARNING
, "Domain name '%s' has embedded slash -- \
242 rejecting.", argp
->ypsetdom_domain
);
245 fromsin
= svc_getcaller(transp
);
249 if (fromsin
->sin_addr
.s_addr
!= htonl(INADDR_LOOPBACK
)) {
250 svcerr_noprog(transp
);
258 svcerr_noprog(transp
);
262 if (ntohs(fromsin
->sin_port
) >= IPPORT_RESERVED
) {
263 svcerr_noprog(transp
);
267 if (argp
->ypsetdom_vers
!= YPVERS
) {
268 svcerr_noprog(transp
);
272 bzero(&bindsin
, sizeof bindsin
);
273 bindsin
.sin_family
= AF_INET
;
274 bindsin
.sin_addr
.s_addr
= *(u_int32_t
*)argp
->ypsetdom_binding
.ypbind_binding_addr
;
275 bindsin
.sin_port
= *(u_short
*)argp
->ypsetdom_binding
.ypbind_binding_port
;
276 rpc_received(argp
->ypsetdom_domain
, &bindsin
, 1);
278 return((void *) &result
);
282 ypbindprog_2(struct svc_req
*rqstp
, SVCXPRT
*transp
)
285 domainname ypbindproc_domain_2_arg
;
286 struct ypbind_setdom ypbindproc_setdom_2_arg
;
288 struct authunix_parms
*creds
;
290 bool_t (*xdr_argument
)(), (*xdr_result
)();
293 switch (rqstp
->rq_proc
) {
294 case YPBINDPROC_NULL
:
295 xdr_argument
= xdr_void
;
296 xdr_result
= xdr_void
;
297 local
= (char *(*)()) ypbindproc_null_2_yp
;
300 case YPBINDPROC_DOMAIN
:
301 xdr_argument
= xdr_domainname
;
302 xdr_result
= xdr_ypbind_resp
;
303 local
= (char *(*)()) ypbindproc_domain_2_yp
;
306 case YPBINDPROC_SETDOM
:
307 switch (rqstp
->rq_cred
.oa_flavor
) {
309 creds
= (struct authunix_parms
*)rqstp
->rq_clntcred
;
310 if (creds
->aup_uid
!= 0) {
311 svcerr_auth(transp
, AUTH_BADCRED
);
316 svcerr_auth(transp
, AUTH_TOOWEAK
);
320 xdr_argument
= xdr_ypbind_setdom
;
321 xdr_result
= xdr_void
;
322 local
= (char *(*)()) ypbindproc_setdom_2_yp
;
326 svcerr_noproc(transp
);
329 bzero(&argument
, sizeof(argument
));
330 if (!svc_getargs(transp
, (xdrproc_t
)xdr_argument
, &argument
)) {
331 svcerr_decode(transp
);
334 result
= (*local
)(transp
, &argument
, rqstp
);
335 if (result
!= NULL
&&
336 !svc_sendreply(transp
, (xdrproc_t
)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
]);
405 else if (strcmp("-m", argv
[i
]) == 0)
408 errx(1, "unknown option: %s", argv
[i
]);
411 /* blow away everything in BINDINGDIR (if it exists) */
413 if ((dird
= opendir(BINDINGDIR
)) != NULL
) {
414 char path
[MAXPATHLEN
];
415 while ((dirp
= readdir(dird
)) != NULL
)
416 if (strcmp(dirp
->d_name
, ".") &&
417 strcmp(dirp
->d_name
, "..")) {
418 sprintf(path
,"%s/%s",BINDINGDIR
,dirp
->d_name
);
429 pmap_unset(YPBINDPROG
, YPBINDVERS
);
431 udptransp
= svcudp_create(RPC_ANYSOCK
);
432 if (udptransp
== NULL
)
433 errx(1, "cannot create udp service");
434 if (!svc_register(udptransp
, YPBINDPROG
, YPBINDVERS
, ypbindprog_2
,
436 errx(1, "unable to register (YPBINDPROG, YPBINDVERS, udp)");
438 tcptransp
= svctcp_create(RPC_ANYSOCK
, 0, 0);
439 if (tcptransp
== NULL
)
440 errx(1, "cannot create tcp service");
442 if (!svc_register(tcptransp
, YPBINDPROG
, YPBINDVERS
, ypbindprog_2
,
444 errx(1, "unable to register (YPBINDPROG, YPBINDVERS, tcp)");
446 /* build initial domain binding, make it "unsuccessful" */
447 ypbindlist
= (struct _dom_binding
*)malloc(sizeof *ypbindlist
);
448 if (ypbindlist
== NULL
)
450 bzero(ypbindlist
, sizeof *ypbindlist
);
451 strncpy(ypbindlist
->dom_domain
, domain_name
, sizeof ypbindlist
->dom_domain
);
452 ypbindlist
->dom_vers
= YPVERS
;
453 ypbindlist
->dom_alive
= 0;
454 ypbindlist
->dom_lockfd
= -1;
455 ypbindlist
->dom_default
= 1;
458 signal(SIGCHLD
, reaper
);
459 signal(SIGTERM
, terminate
);
461 ppid
= getpid(); /* Remember who we are. */
463 openlog(argv
[0], LOG_PID
, LOG_DAEMON
);
465 /* Kick off the default domain */
466 broadcast(ypbindlist
);
474 switch (select(_rpc_dtablesize(), &fdsr
, NULL
, NULL
, &tv
)) {
480 syslog(LOG_WARNING
, "select: %m");
483 for (ypdb
= ypbindlist
; ypdb
; ypdb
= next
) {
484 next
= ypdb
->dom_pnext
;
485 if (READFD
> 0 && FD_ISSET(READFD
, &fdsr
)) {
486 handle_children(ypdb
);
487 if (children
== (MAX_CHILDREN
- 1))
491 svc_getreqset(&fdsr
);
503 struct _dom_binding
*ypdb
;
505 for (ypdb
= ypbindlist
; ypdb
; ypdb
= ypdb
->dom_pnext
)
509 /* The clnt_broadcast() callback mechanism sucks. */
512 * Receive results from broadcaster. Don't worry about passing
513 * bogus info to rpc_received() -- it can handle it. Note that we
514 * must be sure to invalidate the dom_pipe_fds descriptors here:
515 * since descriptors can be re-used, we have to make sure we
516 * don't mistake one of the RPC descriptors for one of the pipes.
517 * What's weird is that forgetting to invalidate the pipe descriptors
518 * doesn't always result in an error (otherwise I would have caught
519 * the mistake much sooner), even though logically it should.
522 handle_children(struct _dom_binding
*ypdb
)
524 char buf
[YPMAXDOMAIN
+ 1];
525 struct sockaddr_in addr
;
527 struct _dom_binding
*y
, *prev
= NULL
;
528 char path
[MAXPATHLEN
];
530 if ((d
= read(READFD
, &buf
, sizeof(buf
))) <= 0)
531 syslog(LOG_WARNING
, "could not read from child: %m");
533 if ((a
= read(READFD
, &addr
, sizeof(struct sockaddr_in
))) < 0)
534 syslog(LOG_WARNING
, "could not read from child: %m");
537 FD_CLR(READFD
, &fdsr
);
538 FD_CLR(READFD
, &svc_fdset
);
539 READFD
= WRITEFD
= -1;
541 rpc_received(buf
, &addr
, 0);
543 for (y
= ypbindlist
; y
; y
= y
->dom_pnext
) {
548 switch (ypdb
->dom_default
) {
551 ypbindlist
= y
->dom_pnext
;
553 prev
->dom_pnext
= y
->dom_pnext
;
554 sprintf(path
, "%s/%s.%ld", BINDINGDIR
,
555 ypdb
->dom_domain
, YPVERS
);
556 close(ypdb
->dom_lockfd
);
562 ypdb
->dom_broadcast_pid
= 0;
575 * Send our dying words back to our parent before we perish.
578 tell_parent(char *dom
, struct sockaddr_in
*addr
)
580 char buf
[YPMAXDOMAIN
+ 1];
581 struct timeval timeout
;
587 sprintf(buf
, "%s", broad_domain
->dom_domain
);
588 if (write(BROADFD
, &buf
, sizeof(buf
)) < 0)
592 * Stay in sync with parent: wait for it to read our first
593 * message before sending the second.
597 FD_SET(BROADFD
, &fds
);
598 if (select(FD_SETSIZE
, NULL
, &fds
, NULL
, &timeout
) == -1)
600 if (FD_ISSET(BROADFD
, &fds
)) {
601 if (write(BROADFD
, addr
, sizeof(struct sockaddr_in
)) < 0)
612 broadcast_result(bool_t
*out
, struct sockaddr_in
*addr
)
614 if (retries
>= MAX_RETRIES
) {
615 bzero(addr
, sizeof(struct sockaddr_in
));
616 if (tell_parent(broad_domain
->dom_domain
, addr
))
617 syslog(LOG_WARNING
, "lost connection to parent");
621 if (yp_restricted
&& verify(addr
->sin_addr
)) {
623 syslog(LOG_NOTICE
, "NIS server at %s not in restricted mode access list -- rejecting.\n",inet_ntoa(addr
->sin_addr
));
626 if (tell_parent(broad_domain
->dom_domain
, addr
))
627 syslog(LOG_WARNING
, "lost connection to parent");
633 * The right way to send RPC broadcasts.
634 * Use the clnt_broadcast() RPC service. Unfortunately, clnt_broadcast()
635 * blocks while waiting for replies, so we have to fork off separate
636 * broadcaster processes that do the waiting and then transmit their
637 * results back to the parent for processing. We also have to remember
638 * to save the name of the domain we're trying to bind in a global
639 * variable since clnt_broadcast() provides no way to pass things to
640 * the 'eachresult' callback function.
643 broadcast(struct _dom_binding
*ypdb
)
648 if (children
>= MAX_CHILDREN
|| ypdb
->dom_broadcast_pid
)
651 if (pipe(ypdb
->dom_pipe_fds
) < 0) {
652 syslog(LOG_WARNING
, "pipe: %m");
656 if (ypdb
->dom_vers
== -1 && (long)ypdb
->dom_server_addr
.sin_addr
.s_addr
)
657 syslog(LOG_WARNING
, "NIS server [%s] for domain \"%s\" not responding",
658 inet_ntoa(ypdb
->dom_server_addr
.sin_addr
), ypdb
->dom_domain
);
661 flock(ypdb
->dom_lockfd
, LOCK_UN
);
663 switch ((ypdb
->dom_broadcast_pid
= fork())) {
666 signal(SIGCHLD
, SIG_DFL
);
667 signal(SIGTERM
, SIG_DFL
);
670 syslog(LOG_WARNING
, "fork: %m");
676 FD_SET(READFD
, &svc_fdset
);
681 /* Release all locks before doing anything else. */
683 close(ypbindlist
->dom_lockfd
);
684 ypbindlist
= ypbindlist
->dom_pnext
;
689 * Special 'many-cast' behavior. If we're in restricted mode,
690 * we have a list of possible server addresses to try. What
691 * we can do is transmit to each ypserv's YPPROC_DOMAIN_NONACK
692 * procedure and time the replies. Whoever replies fastest
693 * gets to be our server. Note that this is not a broadcast
694 * operation: we transmit uni-cast datagrams only.
696 if (yp_restricted
&& yp_manycast
) {
699 struct sockaddr_in sin
;
701 i
= __yp_ping(restricted_addrs
, yp_restricted
,
702 ypdb
->dom_domain
, &port
);
704 bzero(&ypdb
->dom_server_addr
,
705 sizeof(struct sockaddr_in
));
706 if (tell_parent(ypdb
->dom_domain
,
707 &ypdb
->dom_server_addr
)) {
709 "lost connection to parent");
712 bzero(&sin
, sizeof(struct sockaddr_in
));
713 bcopy(&restricted_addrs
[i
],
714 &sin
.sin_addr
, sizeof(struct in_addr
));
715 sin
.sin_family
= AF_INET
;
717 if (tell_parent(broad_domain
->dom_domain
, &sin
))
719 "lost connection to parent");
729 ptr
= ypdb
->dom_domain
;
730 stat
= clnt_broadcast(YPPROG
, YPVERS
, YPPROC_DOMAIN_NONACK
,
731 (xdrproc_t
)xdr_domainname
, &ptr
,
732 (xdrproc_t
)xdr_bool
, &out
,
733 (resultproc_t
)broadcast_result
);
736 if (stat
!= RPC_SUCCESS
) {
737 bzero(&ypdb
->dom_server_addr
, sizeof(struct sockaddr_in
));
738 if (tell_parent(ypdb
->dom_domain
, &ypdb
->dom_server_addr
))
739 syslog(LOG_WARNING
, "lost connection to parent");
746 * The right way to check if a server is alive.
747 * Attempt to get a client handle pointing to the server and send a
748 * YPPROC_DOMAIN. If we can't get a handle or we get a reply of FALSE,
749 * we invalidate this binding entry and send out a broadcast to try to
750 * establish a new binding. Note that we treat non-default domains
751 * specially: once bound, we keep tabs on our server, but if it
752 * goes away and fails to respond after one round of broadcasting, we
753 * abandon it until a client specifically references it again. We make
754 * every effort to keep our default domain bound, however, since we
755 * need it to keep the system on its feet.
758 ping(struct _dom_binding
*ypdb
)
761 struct timeval interval
, timeout
;
763 int rpcsock
= RPC_ANYSOCK
;
764 CLIENT
*client_handle
;
766 interval
.tv_sec
= FAIL_THRESHOLD
;
767 interval
.tv_usec
= 0;
768 timeout
.tv_sec
= FAIL_THRESHOLD
;
771 if (ypdb
->dom_broadcast_pid
)
774 if ((client_handle
= clntudp_bufcreate(&ypdb
->dom_server_addr
,
775 YPPROG
, YPVERS
, interval
, &rpcsock
, RPCSMALLMSGSIZE
,
776 RPCSMALLMSGSIZE
)) == NULL
) {
777 /* Can't get a handle: we're dead. */
787 ptr
= ypdb
->dom_domain
;
789 stat
= clnt_call(client_handle
, YPPROC_DOMAIN
,
790 (xdrproc_t
)xdr_domainname
, &ptr
,
791 (xdrproc_t
)xdr_bool
, &out
, timeout
);
792 if (stat
!= RPC_SUCCESS
|| out
== FALSE
) {
795 clnt_destroy(client_handle
);
801 clnt_destroy(client_handle
);
806 rpc_received(char *dom
, struct sockaddr_in
*raddrp
, int force
)
808 struct _dom_binding
*ypdb
, *prev
= NULL
;
810 struct ypbind_resp ybr
;
811 char path
[MAXPATHLEN
];
814 /*printf("returned from %s/%d about %s\n", inet_ntoa(raddrp->sin_addr),
815 ntohs(raddrp->sin_port), dom);*/
820 for (ypdb
= ypbindlist
; ypdb
; ypdb
= ypdb
->dom_pnext
) {
821 if (strcmp(ypdb
->dom_domain
, dom
) == 0)
827 if (ypdb
->dom_broadcast_pid
) {
828 kill(ypdb
->dom_broadcast_pid
, SIGINT
);
830 FD_CLR(READFD
, &fdsr
);
831 FD_CLR(READFD
, &svc_fdset
);
832 READFD
= WRITEFD
= -1;
836 /* if in secure mode, check originating port number */
837 if ((ypsecuremode
&& (ntohs(raddrp
->sin_port
) >= IPPORT_RESERVED
))) {
838 syslog(LOG_WARNING
, "Rejected NIS server on [%s/%d] for domain %s.",
839 inet_ntoa(raddrp
->sin_addr
), ntohs(raddrp
->sin_port
),
842 ypdb
->dom_broadcast_pid
= 0;
848 if (raddrp
->sin_addr
.s_addr
== (long)0) {
849 switch (ypdb
->dom_default
) {
852 ypbindlist
= ypdb
->dom_pnext
;
854 prev
->dom_pnext
= ypdb
->dom_pnext
;
855 sprintf(path
, "%s/%s.%ld", BINDINGDIR
,
856 ypdb
->dom_domain
, YPVERS
);
857 close(ypdb
->dom_lockfd
);
863 ypdb
->dom_broadcast_pid
= 0;
875 ypdb
= (struct _dom_binding
*)malloc(sizeof *ypdb
);
877 syslog(LOG_WARNING
, "malloc: %m");
880 bzero(ypdb
, sizeof *ypdb
);
881 strncpy(ypdb
->dom_domain
, dom
, sizeof ypdb
->dom_domain
);
882 ypdb
->dom_lockfd
= -1;
883 ypdb
->dom_default
= 0;
884 ypdb
->dom_pnext
= ypbindlist
;
888 /* We've recovered from a crash: inform the world. */
889 if (ypdb
->dom_vers
== -1 && ypdb
->dom_server_addr
.sin_addr
.s_addr
)
890 syslog(LOG_WARNING
, "NIS server [%s] for domain \"%s\" OK",
891 inet_ntoa(raddrp
->sin_addr
), ypdb
->dom_domain
);
893 bcopy(raddrp
, &ypdb
->dom_server_addr
, sizeof ypdb
->dom_server_addr
);
895 ypdb
->dom_vers
= YPVERS
;
897 ypdb
->dom_broadcast_pid
= 0;
899 if (ypdb
->dom_lockfd
!= -1)
900 close(ypdb
->dom_lockfd
);
902 sprintf(path
, "%s/%s.%ld", BINDINGDIR
,
903 ypdb
->dom_domain
, ypdb
->dom_vers
);
905 if ((fd
= open(path
, O_CREAT
|O_SHLOCK
|O_RDWR
|O_TRUNC
, 0644)) == -1) {
906 mkdir(BINDINGDIR
, 0755);
907 if ((fd
= open(path
, O_CREAT
|O_SHLOCK
|O_RDWR
|O_TRUNC
, 0644)) == -1)
911 if ((fd
= open(path
, O_CREAT
|O_RDWR
|O_TRUNC
, 0644)) == -1) {
912 mkdir(BINDINGDIR
, 0755);
913 if ((fd
= open(path
, O_CREAT
|O_RDWR
|O_TRUNC
, 0644)) == -1)
920 * ok, if BINDINGDIR exists, and we can create the binding file,
923 ypdb
->dom_lockfd
= fd
;
925 iov
[0].iov_base
= (char *)&(udptransp
->xp_port
);
926 iov
[0].iov_len
= sizeof udptransp
->xp_port
;
927 iov
[1].iov_base
= (char *)&ybr
;
928 iov
[1].iov_len
= sizeof ybr
;
930 bzero(&ybr
, sizeof ybr
);
931 ybr
.ypbind_status
= YPBIND_SUCC_VAL
;
932 *(u_int32_t
*)&ybr
.ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_addr
= raddrp
->sin_addr
.s_addr
;
933 *(u_short
*)&ybr
.ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_port
= raddrp
->sin_port
;
935 if (writev(ypdb
->dom_lockfd
, iov
, 2) != iov
[0].iov_len
+ iov
[1].iov_len
) {
936 syslog(LOG_WARNING
, "write: %m");
937 close(ypdb
->dom_lockfd
);
938 ypdb
->dom_lockfd
= -1;
944 * Check address against list of allowed servers. Return 0 if okay,
948 verify(struct in_addr addr
)
952 for (i
= 0; i
< RESTRICTED_SERVERS
; i
++)
953 if (!bcmp(&addr
, &restricted_addrs
[i
], sizeof(struct in_addr
)))
960 * Try to set restricted mode. We default to normal mode if we can't
961 * resolve the specified hostnames.
964 yp_restricted_mode(char *args
)
970 /* Find the restricted domain. */
971 if ((s
= strsep(&args
, ",")) == NULL
)
975 /* Get the addresses of the servers. */
976 while ((s
= strsep(&args
, ",")) != NULL
&& i
< RESTRICTED_SERVERS
) {
977 if ((h
= gethostbyname(s
)) == NULL
)
979 bcopy (h
->h_addr_list
[0], &restricted_addrs
[i
],
980 sizeof(struct in_addr
));
984 /* ypset and ypsetme not allowed with restricted mode */
985 ypsetmode
= YPSET_NO
;