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]
23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright (c) 2016 by Delphix. All rights reserved.
28 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
32 * Portions of this source code were derived from Berkeley 4.3 BSD
33 * under license from the Regents of the University of California.
36 #pragma ident "%Z%%M% %I% %E% SMI"
40 * This contains YP server code which supplies the set of functions
41 * requested using rpc. The top level functions in this module
42 * are those which have symbols of the form YPPROC_xxxx defined in
43 * yp_prot.h, and symbols of the form YPOLDPROC_xxxx defined in ypsym.h.
44 * The latter exist to provide compatibility to the old version of the yp
45 * protocol/server, and may emulate the behavior of the previous software
46 * by invoking some other program.
48 * This module also contains functions which are used by (and only by) the
49 * top-level functions here.
52 #include <sys/types.h>
53 #include <sys/socket.h>
54 #include <netinet/in.h>
55 #include <arpa/inet.h>
58 #include <sys/systeminfo.h>
69 /* Use shim version of DBM calls */
71 #include "shim_hooks.h"
78 #define YPXFR_PROC "/usr/lib/netsvc/yp/ypxfr"
80 static char ypxfr_proc
[] = YPXFR_PROC
;
82 #define YPPUSH_PROC "/usr/lib/netsvc/yp/yppush"
84 static char yppush_proc
[] = YPPUSH_PROC
;
89 static char err_fork
[] = "ypserv: %s fork failure.\n";
90 #define FORK_ERR logprintf(err_fork, fun)
91 static char err_execl
[] = "ypserv: %s execl failure.\n";
92 #define EXEC_ERR logprintf(err_execl, fun)
93 static char err_respond
[] = "ypserv: %s can't respond to rpc request.\n";
94 #define RESPOND_ERR logprintf(err_respond, fun)
95 static char err_free
[] = "ypserv: %s can't free args.\n";
96 #define FREE_ERR logprintf(err_free, fun)
97 static char err_map
[] = "ypserv: %s no such map or access denied.\n";
98 #define MAP_ERR logprintf(err_map, fun)
99 static char err_vers
[] = "ypserv: %s version not supported.\n";
100 #define VERS_ERR logprintf(err_vers, fun)
102 static void ypfilter(DBM
*fdb
, datum
*inkey
, datum
*outkey
, datum
*val
,
103 uint_t
*status
, bool_t update
);
104 static bool isypsym(datum
*key
);
105 static bool xdrypserv_ypall(XDR
*xdrs
, struct ypreq_nokey
*req
);
106 static int multihomed(struct ypreq_key req
, struct ypresp_val
*resp
,
107 SVCXPRT
*xprt
, DBM
*fdb
);
108 static int omultihomed(struct yprequest req
, struct ypresponse
*resp
,
109 SVCXPRT
*xprt
, DBM
*fdb
);
112 /* For DNS forwarding */
113 extern bool dnsforward
;
114 extern bool client_setup_failure
;
115 extern int resolv_pid
;
116 extern CLIENT
*resolv_client
;
117 extern char *resolv_tp
;
120 * This determines whether or not a passed domain is served by this
121 * server, and returns a boolean. Used by both old and new protocol
125 ypdomain(SVCXPRT
*transp
, bool always_respond
)
127 char domain_name
[YPMAXDOMAIN
+ 1];
128 char *pdomain_name
= domain_name
;
130 char *fun
= "ypdomain";
134 memset(domain_name
, 0, sizeof (domain_name
));
136 if (!svc_getargs(transp
, (xdrproc_t
)xdr_ypdomain_wrap_string
,
137 (caddr_t
)&pdomain_name
)) {
138 svcerr_decode(transp
);
143 * If the file /var/yp/securenets is present on the server, and if
144 * the hostname is present in the file, then let the client bind to
147 nbuf
= svc_getrpccaller(transp
);
148 af
= ((struct sockaddr_storage
*)nbuf
->buf
)->ss_family
;
149 if (af
!= AF_INET
&& af
!= AF_INET6
) {
150 logprintf("Protocol incorrect\n");
154 if (!(check_secure_net_ti(nbuf
, fun
))) {
159 isserved
= ypcheck_domain(domain_name
);
161 if (isserved
|| always_respond
) {
163 if (!svc_sendreply(transp
, xdr_bool
, (char *)&isserved
)) {
167 logprintf("Domain %s not supported\n",
172 * This case is the one in which the domain is not
173 * supported, and in which we are not to respond in the
174 * unsupported case. We are going to make an error happen
175 * to allow the portmapper to end its wait without the
176 * normal timeout period. The assumption here is that
177 * the only process in the world which is using the function
178 * in its no-answer-if-nack form is the portmapper, which is
179 * doing the krock for pseudo-broadcast. If some poor fool
180 * calls this function as a single-cast message, the nack
181 * case will look like an incomprehensible error. Sigh...
182 * (The traditional Unix disclaimer)
185 svcerr_decode(transp
);
186 logprintf("Domain %s not supported (broadcast)\n",
192 * This implements the yp "match" function.
195 ypmatch(SVCXPRT
*transp
, struct svc_req
*rqstp
)
197 struct ypreq_key req
;
198 struct ypresp_val resp
;
199 char *fun
= "ypmatch";
202 memset(&req
, 0, sizeof (req
));
203 memset(&resp
, 0, sizeof (resp
));
204 resp
.status
= (unsigned)YP_NOKEY
;
206 if (!svc_getargs(transp
, (xdrproc_t
)xdr_ypreq_key
, (char *)&req
)) {
207 svcerr_decode(transp
);
212 * sanity check the map name and to a DBM lookup
213 * also perform an access check...
215 if ((fdb
= ypset_current_map(req
.map
, req
.domain
,
216 &resp
.status
)) != NULL
&&
217 yp_map_access(transp
, &resp
.status
, fdb
)) {
219 /* Check with the DBM database */
220 resp
.valdat
= dbm_fetch(fdb
, req
.keydat
);
221 if (resp
.valdat
.dptr
!= NULL
) {
222 resp
.status
= YP_TRUE
;
224 printf("%s: dbm: %40.40s\n",
225 fun
, resp
.valdat
.dptr
);
230 * If we're being asked to match YP_SECURE or YP_INTERDOMAIN
231 * and we haven't found it in the dbm file, then we don't
232 * really want to waste any more time. Specifically, we don't
235 if (req
.keydat
.dsize
== 0 ||
236 req
.keydat
.dptr
== NULL
||
237 req
.keydat
.dptr
[0] == '\0' ||
238 strncmp(req
.keydat
.dptr
, yp_secure
, req
.keydat
.dsize
) == 0 ||
239 strncmp(req
.keydat
.dptr
, yp_interdomain
, req
.keydat
.dsize
) == 0) {
243 /* Let's try the YP_MULTI_ hack... */
244 #ifdef MINUS_C_OPTION
245 if (multiflag
== TRUE
&& multihomed(req
, &resp
, transp
, fdb
))
248 if (multihomed(req
, &resp
, transp
, fdb
))
253 * Let's try DNS, but if client_setup_failure is set,
254 * we have tried DNS in the past and failed, there is
255 * no reason in forcing an infinite loop by turning
256 * off DNS in setup_resolv() only to turn it back on
259 if (!dnsforward
&& !client_setup_failure
) {
261 idkey
.dptr
= yp_interdomain
;
262 idkey
.dsize
= yp_interdomain_sz
;
263 idval
= dbm_fetch(fdb
, idkey
);
269 if (!resolv_pid
|| !resolv_client
) {
270 setup_resolv(&dnsforward
, &resolv_pid
,
271 &resolv_client
, resolv_tp
, 0);
272 if (resolv_client
== NULL
)
273 client_setup_failure
= TRUE
;
276 if (resolv_req(&dnsforward
, &resolv_client
,
277 &resolv_pid
, resolv_tp
,
278 rqstp
->rq_xprt
, &req
,
285 if (!svc_sendreply(transp
, (xdrproc_t
)xdr_ypresp_val
,
292 if (!svc_freeargs(transp
, (xdrproc_t
)xdr_ypreq_key
,
300 * This implements the yp "get first" function.
303 ypfirst(SVCXPRT
*transp
)
305 struct ypreq_nokey req
;
306 struct ypresp_key_val resp
;
307 char *fun
= "ypfirst";
310 memset(&req
, 0, sizeof (req
));
311 memset(&resp
, 0, sizeof (resp
));
313 if (!svc_getargs(transp
,
314 (xdrproc_t
)xdr_ypreq_nokey
,
316 svcerr_decode(transp
);
320 if ((fdb
= ypset_current_map(req
.map
, req
.domain
,
321 &resp
.status
)) != NULL
&&
322 yp_map_access(transp
, &resp
.status
, fdb
)) {
324 &resp
.keydat
, &resp
.valdat
, &resp
.status
, FALSE
);
327 if (!svc_sendreply(transp
,
328 (xdrproc_t
)xdr_ypresp_key_val
,
333 if (!svc_freeargs(transp
, (xdrproc_t
)xdr_ypreq_nokey
,
340 * This implements the yp "get next" function.
343 ypnext(SVCXPRT
*transp
)
345 struct ypreq_key req
;
346 struct ypresp_key_val resp
;
347 char *fun
= "ypnext";
350 memset(&req
, 0, sizeof (req
));
351 memset(&resp
, 0, sizeof (resp
));
353 if (!svc_getargs(transp
, (xdrproc_t
)xdr_ypreq_key
, (char *)&req
)) {
354 svcerr_decode(transp
);
358 if ((fdb
= ypset_current_map(req
.map
, req
.domain
,
359 &resp
.status
)) != NULL
&&
360 yp_map_access(transp
, &resp
.status
, fdb
)) {
361 ypfilter(fdb
, &req
.keydat
,
362 &resp
.keydat
, &resp
.valdat
, &resp
.status
, FALSE
);
365 if (!svc_sendreply(transp
,
366 (xdrproc_t
)xdr_ypresp_key_val
,
371 if (!svc_freeargs(transp
,
372 (xdrproc_t
)xdr_ypreq_key
,
379 * This implements the "transfer map" function. It takes the domain
380 * and map names and the callback information provided by the
381 * requester (yppush on some node), and execs a ypxfr process to do
382 * the actual transfer.
385 ypxfr(SVCXPRT
*transp
, int prog
)
387 struct ypreq_newxfr newreq
;
388 struct ypreq_xfr oldreq
;
389 struct ypresp_val resp
; /* not returned to the caller */
393 char *pdomain
, *pmap
;
398 if (prog
== YPPROC_NEWXFR
) {
399 memset(&newreq
, 0, sizeof (newreq
));
400 if (!svc_getargs(transp
, (xdrproc_t
)xdr_ypreq_newxfr
,
402 svcerr_decode(transp
);
407 fprintf(stderr
, "newreq:\n"
416 newreq
.map_parms
.domain
,
417 newreq
.map_parms
.map
,
418 newreq
.map_parms
.ordernum
,
419 newreq
.map_parms
.owner
,
424 sprintf(transid
, "%u", newreq
.transid
);
425 sprintf(proto
, "%u", newreq
.proto
);
426 sprintf(name
, "%s", newreq
.ypxfr_owner
);
427 pdomain
= newreq
.ypxfr_domain
;
428 pmap
= newreq
.ypxfr_map
;
429 } else if (prog
== YPPROC_XFR
) {
430 memset(&oldreq
, 0, sizeof (oldreq
));
431 if (!svc_getargs(transp
,
432 (xdrproc_t
)xdr_ypreq_xfr
,
434 svcerr_decode(transp
);
439 fprintf(stderr
, "oldreq:\n"
448 oldreq
.map_parms
.domain
,
449 oldreq
.map_parms
.map
,
450 oldreq
.map_parms
.ordernum
,
451 oldreq
.map_parms
.owner
,
457 sprintf(transid
, "%u", oldreq
.transid
);
458 sprintf(proto
, "%u", oldreq
.proto
);
459 sprintf(name
, "%s", oldreq
.ypxfr_owner
);
460 pdomain
= oldreq
.ypxfr_domain
;
461 pmap
= oldreq
.ypxfr_map
;
466 /* Check that the map exists and is accessible */
467 if ((fdb
= ypset_current_map(pmap
, pdomain
, &resp
.status
)) != NULL
&&
468 yp_map_access(transp
, &resp
.status
, fdb
)) {
473 } else if (pid
== 0) {
474 if (prog
== YPPROC_NEWXFR
|| prog
== YPPROC_XFR
) {
477 "EXECL: %s, -d, %s, -C, %s, %s, %s, %s\n",
479 transid
, proto
, name
, pmap
);
481 if (execl(ypxfr_proc
, "ypxfr", "-d",
482 pdomain
, "-C", transid
, proto
,
494 if (!svc_sendreply(transp
, xdr_void
, 0)) {
498 if (prog
== YPPROC_NEWXFR
) {
499 if (!svc_freeargs(transp
,
500 (xdrproc_t
)xdr_ypreq_newxfr
,
508 * This implements the "get all" function.
511 ypall(SVCXPRT
*transp
)
513 struct ypreq_nokey req
;
514 struct ypresp_val resp
; /* not returned to the caller */
519 req
.domain
= req
.map
= NULL
;
521 memset((char *)&req
, 0, sizeof (req
));
523 if (!svc_getargs(transp
,
524 (xdrproc_t
)xdr_ypreq_nokey
,
526 svcerr_decode(transp
);
538 if (!svc_freeargs(transp
,
539 (xdrproc_t
)xdr_ypreq_nokey
,
548 * access control hack: If denied then invalidate the map name.
551 if ((fdb
= ypset_current_map(req
.map
,
552 req
.domain
, &resp
.status
)) != NULL
&&
553 !yp_map_access(transp
, &resp
.status
, fdb
)) {
559 * This is the child process. The work gets done by xdrypserv_ypall/
560 * we must clear the "current map" first so that we do not
561 * share a seek pointer with the parent server.
564 if (!svc_sendreply(transp
,
565 (xdrproc_t
)xdrypserv_ypall
,
570 if (!svc_freeargs(transp
,
571 (xdrproc_t
)xdr_ypreq_nokey
,
577 * In yptol mode we may start a cache update thread within a child
578 * process. It is thus important that child processes do not exit,
579 * killing any such threads, before the thread has completed.
582 thr_join(0, NULL
, NULL
);
589 * This implements the "get master name" function.
592 ypmaster(SVCXPRT
*transp
)
594 struct ypreq_nokey req
;
595 struct ypresp_master resp
;
596 char *nullstring
= "";
597 char *fun
= "ypmaster";
600 memset((char *)&req
, 0, sizeof (req
));
601 resp
.master
= nullstring
;
602 resp
.status
= YP_TRUE
;
604 if (!svc_getargs(transp
,
605 (xdrproc_t
)xdr_ypreq_nokey
,
607 svcerr_decode(transp
);
611 if ((fdb
= ypset_current_map(req
.map
,
612 req
.domain
, &resp
.status
)) != NULL
&&
613 yp_map_access(transp
, &resp
.status
, fdb
)) {
615 if (!ypget_map_master(&resp
.master
, fdb
)) {
616 resp
.status
= (unsigned)YP_BADDB
;
620 if (!svc_sendreply(transp
,
621 (xdrproc_t
)xdr_ypresp_master
,
626 if (!svc_freeargs(transp
,
627 (xdrproc_t
)xdr_ypreq_nokey
,
634 * This implements the "get order number" function.
637 yporder(SVCXPRT
*transp
)
639 struct ypreq_nokey req
;
640 struct ypresp_order resp
;
641 char *fun
= "yporder";
644 req
.domain
= req
.map
= NULL
;
645 resp
.status
= YP_TRUE
;
648 memset((char *)&req
, 0, sizeof (req
));
650 if (!svc_getargs(transp
,
651 (xdrproc_t
)xdr_ypreq_nokey
,
653 svcerr_decode(transp
);
659 if ((fdb
= ypset_current_map(req
.map
,
661 &resp
.status
)) != NULL
&&
662 yp_map_access(transp
, &resp
.status
, fdb
)) {
664 if (!ypget_map_order(req
.map
, req
.domain
, &resp
.ordernum
)) {
665 resp
.status
= (unsigned)YP_BADDB
;
669 if (!svc_sendreply(transp
,
670 (xdrproc_t
)xdr_ypresp_order
,
675 if (!svc_freeargs(transp
,
676 (xdrproc_t
)xdr_ypreq_nokey
,
683 ypmaplist(SVCXPRT
*transp
)
685 char domain_name
[YPMAXDOMAIN
+ 1];
686 char *pdomain
= domain_name
;
687 char *fun
= "ypmaplist";
688 struct ypresp_maplist maplist
;
689 struct ypmaplist
*tmp
;
691 maplist
.list
= (struct ypmaplist
*)NULL
;
693 memset(domain_name
, 0, sizeof (domain_name
));
695 if (!svc_getargs(transp
,
696 (xdrproc_t
)xdr_ypdomain_wrap_string
,
697 (caddr_t
)&pdomain
)) {
698 svcerr_decode(transp
);
702 maplist
.status
= yplist_maps(domain_name
, &maplist
.list
);
704 if (!svc_sendreply(transp
,
705 (xdrproc_t
)xdr_ypresp_maplist
,
710 while (maplist
.list
) {
711 tmp
= maplist
.list
->ypml_next
;
712 free((char *)maplist
.list
);
718 * Ancillary functions used by the top-level functions within this
723 * This returns TRUE if a given key is a yp-private symbol, otherwise
729 if ((key
->dptr
== NULL
) ||
730 (key
->dsize
< yp_prefix_sz
) ||
731 memcmp(yp_prefix
, key
->dptr
, yp_prefix_sz
) ||
732 (!memcmp(key
->dptr
, "YP_MULTI_", 9))) {
739 * This provides private-symbol filtration for the enumeration functions.
742 ypfilter(DBM
*fdb
, datum
*inkey
, datum
*outkey
, datum
*val
, uint_t
*status
,
749 if (isypsym(inkey
)) {
750 *status
= (unsigned)YP_BADARGS
;
754 k
= dbm_do_nextkey(fdb
, *inkey
);
756 k
= dbm_firstkey(fdb
);
759 while (k
.dptr
&& isypsym(&k
)) {
760 k
= dbm_nextkey(fdb
);
763 if (k
.dptr
== NULL
) {
771 * In N2L mode we must call a version of dbm_fetch() that either does
772 * or does not check for entry updates. In non N2L mode both of these
773 * will end up doing a normal dbm_fetch().
776 *val
= shim_dbm_fetch(fdb
, k
);
778 *val
= shim_dbm_fetch_noupdate(fdb
, k
);
780 if (val
->dptr
!= NULL
) {
783 *status
= (unsigned)YP_BADDB
;
788 * Serializes a stream of struct ypresp_key_val's. This is used
789 * only by the ypserv side of the transaction.
792 xdrypserv_ypall(XDR
*xdrs
, struct ypreq_nokey
*req
)
795 struct ypresp_key_val resp
;
798 resp
.keydat
.dptr
= resp
.valdat
.dptr
= (char *)NULL
;
799 resp
.keydat
.dsize
= resp
.valdat
.dsize
= 0;
801 if ((fdb
= ypset_current_map(req
->map
, req
->domain
,
802 &resp
.status
)) != NULL
) {
803 ypfilter(fdb
, (datum
*) NULL
, &resp
.keydat
, &resp
.valdat
,
804 &resp
.status
, FALSE
);
806 while (resp
.status
== YP_TRUE
) {
807 if (!xdr_bool(xdrs
, &more
)) {
811 if (!xdr_ypresp_key_val(xdrs
, &resp
)) {
815 ypfilter(fdb
, &resp
.keydat
, &resp
.keydat
, &resp
.valdat
,
816 &resp
.status
, FALSE
);
820 if (!xdr_bool(xdrs
, &more
)) {
824 if (!xdr_ypresp_key_val(xdrs
, &resp
)) {
830 if (!xdr_bool(xdrs
, &more
)) {
838 * Additions for sparc cluster support
842 * Check for special multihomed host cookie in the key. If there,
843 * collect the addresses from the comma separated list and return
844 * the one that's nearest the client.
847 multihomed(struct ypreq_key req
, struct ypresp_val
*resp
,
848 SVCXPRT
*xprt
, DBM
*fdb
)
851 ulong_t bestaddr
, call_addr
;
854 static char localbuf
[_PBLKSIZ
]; /* buffer for multihomed IPv6 addr */
856 if (strcmp(req
.map
, "hosts.byname") &&
857 strcmp(req
.map
, "ipnodes.byname"))
858 /* default status is YP_NOKEY */
861 if (strncmp(req
.keydat
.dptr
, "YP_MULTI_", 9)) {
864 strncpy(name
, "YP_MULTI_", 9);
865 strncpy(name
+ 9, req
.keydat
.dptr
, req
.keydat
.dsize
);
866 tmpname
.dsize
= req
.keydat
.dsize
+ 9;
868 resp
->valdat
= dbm_fetch(fdb
, tmpname
);
871 * Return whole line (for debugging) if YP_MULTI_hostnam
874 resp
->valdat
= dbm_fetch(fdb
, req
.keydat
);
875 if (resp
->valdat
.dptr
!= NULL
)
879 if (resp
->valdat
.dptr
== NULL
)
882 strncpy(name
, req
.keydat
.dptr
, req
.keydat
.dsize
);
883 name
[req
.keydat
.dsize
] = NULL
;
885 if (strcmp(req
.map
, "ipnodes.byname") == 0) {
887 * This section handles multihomed IPv6 addresses.
888 * It returns all the IPv6 addresses one per line and only
889 * the requested hostname is returned. NO aliases will be
890 * returned. This is done exactly the same way DNS forwarding
891 * daemon handles multihomed hosts.
892 * New IPv6 enabled clients should be able to handle this
893 * information returned. The sorting is also the client's
899 if ((buf
= strdup(resp
->valdat
.dptr
)) == NULL
) /* no memory */
901 if ((bp
= strtok(buf
, " \t")) == NULL
) { /* no address field */
905 if ((cp
= strtok(NULL
, "")) == NULL
) { /* no host field */
909 if ((cp
= strtok(bp
, ",")) != NULL
) { /* multihomed host */
913 bsize
= sizeof (localbuf
);
917 if ((strlen(cp
) + strlen(name
)) >= bsize
) {
921 sprintf(endbuf
, "%s %s\n", cp
, name
);
922 cp
= strtok(NULL
, ",");
923 endbuf
= &endbuf
[strlen(endbuf
)];
924 bsize
= &localbuf
[sizeof (localbuf
)] - endbuf
;
926 resp
->valdat
.dptr
= localbuf
;
927 resp
->valdat
.dsize
= strlen(localbuf
);
931 /* remove trailing newline */
932 if (resp
->valdat
.dsize
&&
933 resp
->valdat
.dptr
[resp
->valdat
.dsize
-1] == '\n') {
934 resp
->valdat
.dptr
[resp
->valdat
.dsize
-1] = '\0';
935 resp
->valdat
.dsize
-= 1;
938 resp
->status
= YP_TRUE
;
941 nbuf
= svc_getrpccaller(xprt
);
943 * OK, now I have a netbuf structure which I'm supposed to
944 * treat as opaque... I hate transport independance!
945 * So, we're just gonna doit wrong... By wrong I mean that
946 * we assume that the buf part of the netbuf structure is going
947 * to be a sockaddr_in. We'll then check the assumed family
948 * member and hope that we find AF_INET in there... if not
949 * then we can't continue.
951 if (((struct sockaddr_in
*)(nbuf
->buf
))->sin_family
!= AF_INET
)
954 call_addr
= ((struct sockaddr_in
*)(nbuf
->buf
))->sin_addr
.s_addr
;
956 cp
= resp
->valdat
.dptr
;
957 if ((bp
= strtok(cp
, " \t")) == NULL
) /* no address field */
959 if ((cp
= strtok(NULL
, "")) == NULL
) /* no host field */
961 bp
= strtok(bp
, ",");
963 bestaddr
= inet_addr(bp
);
964 while (cp
= strtok(NULL
, ",")) {
967 taddr
= inet_addr(cp
);
968 if (ntohl(call_addr
^ taddr
) < ntohl(call_addr
^ bestaddr
))
971 cp
= resp
->valdat
.dptr
;
972 sprintf(cp
, "%s %s", inet_ntoa(*(struct in_addr
*)&bestaddr
), name
);
973 resp
->valdat
.dsize
= strlen(cp
);
975 resp
->status
= YP_TRUE
;
980 /* V1 dispatch routines */
982 ypoldmatch(SVCXPRT
*transp
, struct svc_req
*rqstp
)
984 bool dbmop_ok
= TRUE
;
985 struct yprequest req
;
986 struct ypreq_key nrq
;
987 struct ypresponse resp
;
988 char *fun
= "ypoldmatch";
991 memset((void *) &req
, 0, sizeof (req
));
992 memset((void *) &resp
, 0, sizeof (resp
));
994 if (!svc_getargs(transp
,
995 (xdrproc_t
)_xdr_yprequest
,
997 svcerr_decode(transp
);
1001 if (req
.yp_reqtype
!= YPMATCH_REQTYPE
) {
1002 resp
.ypmatch_resp_status
= (unsigned)YP_BADARGS
;
1007 (((fdb
= ypset_current_map(req
.ypmatch_req_map
,
1008 req
.ypmatch_req_domain
,
1009 &resp
.ypmatch_resp_status
))
1011 yp_map_access(transp
,
1012 &resp
.ypmatch_resp_status
,
1015 /* Check with the DBM database */
1016 resp
.ypmatch_resp_valdat
= dbm_fetch(fdb
,
1017 req
.ypmatch_req_keydat
);
1019 if (resp
.ypmatch_resp_valptr
!= NULL
) {
1020 resp
.ypmatch_resp_status
= YP_TRUE
;
1022 printf("%s: dbm: %s\n",
1023 fun
, resp
.ypmatch_resp_valptr
);
1028 * If we're being asked to match YP_SECURE or YP_INTERDOMAIN
1029 * and we haven't found it in the dbm file, then we don't
1030 * really want to waste any more time. Specifically, we don't
1033 if (req
.ypmatch_req_keysize
== 0 ||
1034 req
.ypmatch_req_keyptr
== NULL
||
1035 req
.ypmatch_req_keyptr
[0] == '\0' ||
1036 strncmp(req
.ypmatch_req_keyptr
, "YP_SECURE", 9) == 0 ||
1037 strncmp(req
.ypmatch_req_keyptr
, "YP_INTERDOMAIN", 14) == 0)
1041 /* Let's try the YP_MULTI_ hack... */
1042 #ifdef MINUS_C_OPTION
1043 if (multiflag
== TRUE
&& omultihomed(req
, &resp
, transp
, fdb
))
1046 if (omultihomed(req
, &resp
, transp
, fdb
))
1054 idkey
.dptr
= yp_interdomain
;
1055 idkey
.dsize
= yp_interdomain_sz
;
1056 idval
= dbm_fetch(fdb
, idkey
);
1063 setup_resolv(&dnsforward
, &resolv_pid
, &resolv_client
,
1066 if (req
.yp_reqtype
== YPREQ_KEY
) {
1067 nrq
= req
.yp_reqbody
.yp_req_keytype
;
1069 resolv_req(&dnsforward
, &resolv_client
, &resolv_pid
,
1070 resolv_tp
, rqstp
->rq_xprt
,
1079 if (!svc_sendreply(transp
,
1080 (xdrproc_t
)_xdr_ypresponse
,
1085 if (!svc_freeargs(transp
,
1086 (xdrproc_t
)_xdr_yprequest
,
1093 ypoldfirst(SVCXPRT
*transp
)
1095 bool dbmop_ok
= TRUE
;
1096 struct yprequest req
;
1097 struct ypresponse resp
;
1098 char *fun
= "ypoldfirst";
1101 memset((void *) &req
, 0, sizeof (req
));
1102 memset((void *) &resp
, 0, sizeof (resp
));
1104 if (!svc_getargs(transp
,
1105 (xdrproc_t
)_xdr_yprequest
,
1107 svcerr_decode(transp
);
1111 if (req
.yp_reqtype
!= YPFIRST_REQTYPE
) {
1112 resp
.ypfirst_resp_status
= (unsigned)YP_BADARGS
;
1117 ((fdb
= ypset_current_map(req
.ypfirst_req_map
,
1118 req
.ypfirst_req_domain
,
1119 &resp
.ypfirst_resp_status
))
1121 yp_map_access(transp
,
1122 &resp
.ypfirst_resp_status
,
1125 resp
.ypfirst_resp_keydat
= dbm_firstkey(fdb
);
1127 if (resp
.ypfirst_resp_keyptr
!= NULL
) {
1128 resp
.ypfirst_resp_valdat
=
1129 dbm_fetch(fdb
, resp
.ypfirst_resp_keydat
);
1131 if (resp
.ypfirst_resp_valptr
!= NULL
) {
1132 resp
.ypfirst_resp_status
= YP_TRUE
;
1134 resp
.ypfirst_resp_status
= (unsigned)YP_BADDB
;
1137 resp
.ypfirst_resp_status
= (unsigned)YP_NOKEY
;
1141 resp
.yp_resptype
= YPFIRST_RESPTYPE
;
1143 if (!svc_sendreply(transp
,
1144 (xdrproc_t
)_xdr_ypresponse
,
1149 if (!svc_freeargs(transp
,
1150 (xdrproc_t
)_xdr_yprequest
,
1157 ypoldnext(SVCXPRT
*transp
)
1159 bool dbmop_ok
= TRUE
;
1160 struct yprequest req
;
1161 struct ypresponse resp
;
1162 char *fun
= "ypoldnext";
1165 memset((void *) &req
, 0, sizeof (req
));
1166 memset((void *) &resp
, 0, sizeof (resp
));
1168 if (!svc_getargs(transp
,
1169 (xdrproc_t
)_xdr_yprequest
,
1171 svcerr_decode(transp
);
1175 if (req
.yp_reqtype
!= YPNEXT_REQTYPE
) {
1176 resp
.ypnext_resp_status
= (unsigned)YP_BADARGS
;
1181 ((fdb
= ypset_current_map(req
.ypnext_req_map
,
1182 req
.ypnext_req_domain
,
1183 &resp
.ypnext_resp_status
)) != NULL
&&
1184 yp_map_access(transp
, &resp
.ypnext_resp_status
, fdb
))) {
1186 resp
.ypnext_resp_keydat
= dbm_nextkey(fdb
);
1188 if (resp
.ypnext_resp_keyptr
!= NULL
) {
1189 resp
.ypnext_resp_valdat
=
1190 dbm_fetch(fdb
, resp
.ypnext_resp_keydat
);
1192 if (resp
.ypnext_resp_valptr
!= NULL
) {
1193 resp
.ypnext_resp_status
= YP_TRUE
;
1195 resp
.ypnext_resp_status
= (unsigned)YP_BADDB
;
1198 resp
.ypnext_resp_status
= (unsigned)YP_NOMORE
;
1202 resp
.yp_resptype
= YPNEXT_RESPTYPE
;
1204 if (!svc_sendreply(transp
,
1205 (xdrproc_t
)_xdr_ypresponse
,
1210 if (!svc_freeargs(transp
,
1211 (xdrproc_t
)_xdr_yprequest
,
1218 * This retrieves the order number and master peer name from the map.
1219 * The conditions for the various message fields are: domain is filled
1220 * in iff the domain exists. map is filled in iff the map exists.
1221 * order number is filled in iff it's in the map. owner is filled in
1222 * iff the master peer is in the map.
1225 ypoldpoll(SVCXPRT
*transp
)
1227 struct yprequest req
;
1228 struct ypresponse resp
;
1233 char *fun
= "ypoldpoll";
1236 memset((void *) &req
, 0, sizeof (req
));
1237 memset((void *) &resp
, 0, sizeof (resp
));
1239 if (!svc_getargs(transp
,
1240 (xdrproc_t
)_xdr_yprequest
,
1242 svcerr_decode(transp
);
1246 if (req
.yp_reqtype
== YPPOLL_REQTYPE
) {
1247 if (strcmp(req
.yppoll_req_domain
, "yp_private") == 0 ||
1248 strcmp(req
.yppoll_req_map
, "ypdomains") == 0 ||
1249 strcmp(req
.yppoll_req_map
, "ypmaps") == 0) {
1252 * Backward comatibility for 2.0 NIS servers
1254 domain
= req
.yppoll_req_domain
;
1255 map
= req
.yppoll_req_map
;
1256 } else if ((fdb
= ypset_current_map(req
.yppoll_req_map
,
1257 req
.yppoll_req_domain
,
1259 domain
= req
.yppoll_req_domain
;
1260 map
= req
.yppoll_req_map
;
1261 ypget_map_order(map
, domain
,
1262 &resp
.yppoll_resp_ordernum
);
1263 ypget_map_master(&owner
, fdb
);
1265 switch ((int)error
) {
1267 map
= req
.yppoll_req_map
;
1268 /* Fall through to set the domain too. */
1271 domain
= req
.yppoll_req_domain
;
1277 resp
.yp_resptype
= YPPOLL_RESPTYPE
;
1278 resp
.yppoll_resp_domain
= domain
;
1279 resp
.yppoll_resp_map
= map
;
1280 resp
.yppoll_resp_owner
= owner
;
1282 if (!svc_sendreply(transp
,
1283 (xdrproc_t
)_xdr_ypresponse
,
1288 if (!svc_freeargs(transp
,
1289 (xdrproc_t
)_xdr_yprequest
,
1296 ypoldpush(SVCXPRT
*transp
)
1298 struct yprequest req
;
1299 struct ypresp_val resp
;
1301 char *fun
= "ypoldpush";
1304 memset((void *) &req
, 0, sizeof (req
));
1306 if (!svc_getargs(transp
,
1307 (xdrproc_t
)_xdr_yprequest
,
1309 svcerr_decode(transp
);
1313 if (((fdb
= ypset_current_map(req
.yppush_req_map
,
1314 req
.yppush_req_domain
,
1315 &resp
.status
)) != NULL
) &&
1316 (yp_map_access(transp
, &resp
.status
, fdb
))) {
1323 } else if (pid
== 0) {
1324 ypclr_current_map();
1326 if (execl(yppush_proc
, "yppush", "-d", req
.yppush_req_domain
,
1327 req
.yppush_req_map
, NULL
)) {
1333 if (!svc_sendreply(transp
,
1334 (xdrproc_t
)xdr_void
,
1339 if (!svc_freeargs(transp
,
1340 (xdrproc_t
)_xdr_yprequest
,
1347 ypoldpull(SVCXPRT
*transp
)
1349 struct yprequest req
;
1350 struct ypresp_val resp
;
1352 char *fun
= "ypoldpull";
1355 memset((void *) &req
, 0, sizeof (req
));
1357 if (!svc_getargs(transp
,
1358 (xdrproc_t
)_xdr_yprequest
,
1360 svcerr_decode(transp
);
1364 if (req
.yp_reqtype
== YPPULL_REQTYPE
) {
1366 if (((fdb
= ypset_current_map(req
.yppull_req_map
,
1367 req
.yppull_req_domain
,
1368 &resp
.status
)) == NULL
) ||
1369 (yp_map_access(transp
, &resp
.status
, fdb
))) {
1375 } else if (pid
== 0) {
1376 ypclr_current_map();
1378 if (execl(ypxfr_proc
, "ypxfr", "-d",
1379 req
.yppull_req_domain
,
1380 req
.yppull_req_map
, NULL
)) {
1387 if (!svc_freeargs(transp
,
1388 (xdrproc_t
)_xdr_yprequest
,
1395 ypoldget(SVCXPRT
*transp
)
1397 struct yprequest req
;
1398 struct ypresp_val resp
;
1400 char *fun
= "ypoldget";
1403 memset((void *) &req
, 0, sizeof (req
));
1405 if (!svc_getargs(transp
,
1406 (xdrproc_t
)_xdr_yprequest
,
1408 svcerr_decode(transp
);
1412 if (!svc_sendreply(transp
, xdr_void
, 0)) {
1416 if (req
.yp_reqtype
== YPGET_REQTYPE
) {
1418 if (((fdb
= ypset_current_map(req
.ypget_req_map
,
1419 req
.ypget_req_domain
,
1420 &resp
.status
)) == NULL
) ||
1421 (yp_map_access(transp
, &resp
.status
, fdb
))) {
1428 } else if (pid
== 0) {
1430 ypclr_current_map();
1432 if (execl(ypxfr_proc
, "ypxfr", "-d",
1433 req
.ypget_req_domain
, "-h",
1434 req
.ypget_req_owner
,
1435 req
.ypget_req_map
, NULL
)) {
1443 if (!svc_freeargs(transp
,
1444 (xdrproc_t
)_xdr_yprequest
,
1451 omultihomed(struct yprequest req
,
1452 struct ypresponse
*resp
, SVCXPRT
*xprt
, DBM
*fdb
)
1455 char name
[PATH_MAX
];
1456 struct netbuf
*nbuf
;
1457 ulong_t bestaddr
, call_addr
;
1459 if (strcmp(req
.ypmatch_req_map
, "hosts.byname"))
1462 if (strncmp(req
.ypmatch_req_keyptr
, "YP_MULTI_", 9)) {
1465 strncpy(name
, "YP_MULTI_", 9);
1466 strncpy(name
+ 9, req
.ypmatch_req_keyptr
,
1467 req
.ypmatch_req_keysize
);
1468 tmpname
.dsize
= req
.ypmatch_req_keysize
+ 9;
1469 tmpname
.dptr
= name
;
1470 resp
->ypmatch_resp_valdat
= dbm_fetch(fdb
, tmpname
);
1472 resp
->ypmatch_resp_valdat
=
1473 dbm_fetch(fdb
, req
.ypmatch_req_keydat
);
1474 if (resp
->ypmatch_resp_valptr
!= NULL
)
1478 if (resp
->ypmatch_resp_valptr
== NULL
)
1481 strncpy(name
, req
.ypmatch_req_keyptr
, req
.ypmatch_req_keysize
);
1482 name
[req
.ypmatch_req_keysize
] = NULL
;
1484 nbuf
= svc_getrpccaller(xprt
);
1487 * OK, now I have a netbuf structure which I'm supposed to treat
1488 * as opaque... I hate transport independance! So, we're just
1489 * gonna doit wrong... By wrong I mean that we assume that the
1490 * buf part of the netbuf structure is going to be a sockaddr_in.
1491 * We'll then check the assumed family member and hope that we
1492 * find AF_INET in there... if not then we can't continue.
1494 if (((struct sockaddr_in
*)(nbuf
->buf
))->sin_family
!= AF_INET
)
1497 call_addr
= ((struct sockaddr_in
*)(nbuf
->buf
))->sin_addr
.s_addr
;
1499 cp
= resp
->ypmatch_resp_valptr
;
1500 if ((bp
= strtok(cp
, "\t")) == NULL
) /* No address field */
1502 if ((cp
= strtok(NULL
, "")) == NULL
) /* No host field */
1504 bp
= strtok(bp
, ",");
1506 bestaddr
= inet_addr(bp
);
1507 while (cp
= strtok(NULL
, ",")) {
1510 taddr
= inet_addr(cp
);
1511 if (ntohl(call_addr
^ taddr
) < ntohl(call_addr
^ bestaddr
))
1515 cp
= resp
->ypmatch_resp_valptr
;
1516 sprintf(cp
, "%s %s", inet_ntoa(*(struct in_addr
*)&bestaddr
), name
);
1517 resp
->ypmatch_resp_valsize
= strlen(cp
);
1519 resp
->ypmatch_resp_status
= YP_TRUE
;