]>
git.saurik.com Git - apple/network_cmds.git/blob - ypserv.tproj/ypserv_db.c
055b904605bc9d524912eb989a5b2236e1b62f75
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 /* $OpenBSD: ypserv_db.c,v 1.13 1997/08/09 23:10:12 maja Exp $ */
26 * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
27 * Copyright (c) 1996 Charles D. Cranor
28 * All rights reserved.
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by Mats O Jansson
41 * and Charles D. Cranor.
42 * 4. The name of the author may not be used to endorse or promote products
43 * derived from this software without specific prior written permission.
45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
46 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
47 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
49 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 static char rcsid
[] = "$OpenBSD: ypserv_db.c,v 1.13 1997/08/09 23:10:12 maja Exp $";
63 * major revision/cleanup of Mats' version
64 * done by Chuck Cranor <chuck@ccrc.wustl.edu>
70 #include <rpcsvc/yp.h>
71 #include <rpcsvc/ypclnt.h>
73 #include <sys/param.h>
79 #include <arpa/nameser.h>
81 #include <sys/types.h>
82 #include <sys/socket.h>
83 #include <sys/queue.h>
84 #include <netinet/in.h>
85 #include <arpa/inet.h>
87 #include <sys/errno.h>
92 LIST_HEAD(domainlist
, opt_domain
); /* LIST of domains */
93 LIST_HEAD(maplist
, opt_map
); /* LIST of maps (in a domain) */
94 CIRCLEQ_HEAD(mapq
, opt_map
); /* CIRCLEQ of maps (LRU) */
97 mapname map
; /* map name (malloc'd) */
98 DBM
*db
; /* database */
99 struct opt_domain
*dom
; /* back ptr to our domain */
100 int host_lookup
; /* host lookup */
101 int secure
; /* secure map? */
102 CIRCLEQ_ENTRY(opt_map
) mapsq
; /* map queue pointers */
103 LIST_ENTRY(opt_map
) mapsl
; /* map list pointers */
107 domainname domain
; /* domain name (malloc'd) */
108 struct maplist dmaps
; /* the domain's active maps */
109 LIST_ENTRY(opt_domain
) domsl
; /* global linked list of domains */
113 struct domainlist doms
; /* global list of domains */
114 struct mapq maps
; /* global queue of maps (LRU) */
119 * ypdb_init: init the queues and lists
133 * Check if key is a YP private key. Return TRUE if it is and
134 * ypprivate is FALSE.
138 yp_private(key
,ypprivate
)
147 if (key
.dsize
== 0 || key
.dptr
== NULL
)
150 if (key
.dsize
== YP_LAST_LEN
&&
151 strncmp(key
.dptr
,YP_LAST_KEY
,YP_LAST_LEN
) == 0)
153 if (key
.dsize
== YP_INPUT_LEN
&&
154 strncmp(key
.dptr
,YP_INPUT_KEY
,YP_INPUT_LEN
) == 0)
156 if (key
.dsize
== YP_OUTPUT_LEN
&&
157 strncmp(key
.dptr
,YP_OUTPUT_KEY
,YP_OUTPUT_LEN
) == 0)
159 if (key
.dsize
== YP_MASTER_LEN
&&
160 strncmp(key
.dptr
,YP_MASTER_KEY
,YP_MASTER_LEN
) == 0)
162 if (key
.dsize
== YP_DOMAIN_LEN
&&
163 strncmp(key
.dptr
,YP_DOMAIN_KEY
,YP_DOMAIN_LEN
) == 0)
165 if (key
.dsize
== YP_INTERDOMAIN_LEN
&&
166 strncmp(key
.dptr
,YP_INTERDOMAIN_KEY
,YP_INTERDOMAIN_LEN
) == 0)
168 if (key
.dsize
== YP_SECURE_LEN
&&
169 strncmp(key
.dptr
,YP_SECURE_KEY
,YP_SECURE_LEN
) == 0)
176 * Close least recent used map. This routine is called when we have
177 * no more file descripotors free, or we want to close all maps.
183 struct opt_map
*last
= maps
.cqh_last
;
185 if (last
== (void*)&maps
) {
186 yplog(" ypdb_close_last: LRU list is empty!");
190 CIRCLEQ_REMOVE(&maps
, last
, mapsq
); /* remove from LRU circleq */
191 LIST_REMOVE(last
, mapsl
); /* remove from domain list */
194 yplog(" ypdb_close_last: closing map %s in domain %s [db=0x%x]",
195 last
->map
, last
->dom
->domain
, last
->db
);
198 ypdb_close(last
->db
); /* close DB */
199 free(last
->map
); /* free map name */
200 free(last
); /* free map */
206 * Close all open maps.
214 yplog(" ypdb_close_all(): start");
216 while (maps
.cqh_first
!= (void *)&maps
) {
220 yplog(" ypdb_close_all(): done");
225 * Close Database if Open/Close Optimization isn't turned on.
233 yplog(" ypdb_close_db(0x%x)", db
);
245 ypdb_open_db(domain
, map
, status
, map_info
)
249 struct opt_map
**map_info
;
251 char map_path
[MAXPATHLEN
];
252 static char *domain_key
= YP_INTERDOMAIN_KEY
;
253 static char *secure_key
= YP_SECURE_KEY
;
254 /* struct stat finfo; */
257 struct opt_domain
*d
= NULL
;
258 struct opt_map
*m
= NULL
;
264 * check for preloaded domain, map
267 for (d
= doms
.lh_first
; d
!= NULL
; d
= d
->domsl
.le_next
) {
268 if (strcmp(domain
, d
->domain
) == 0) break;
272 for (m
= d
->dmaps
.lh_first
; m
!= NULL
; m
= m
->mapsl
.le_next
)
273 if (strcmp(map
, m
->map
) == 0) break;
282 yplog(" ypdb_open_db: cached open: domain=%s, map=%s, db=0x%x",
285 CIRCLEQ_REMOVE(&maps
, m
, mapsq
); /* adjust LRU queue */
286 CIRCLEQ_INSERT_HEAD(&maps
, m
, mapsq
);
291 /* Check for illegal charcaters */
293 if (strchr(domain
, '/')) {
297 if (strchr(map
, '/')) {
310 snprintf(map_path
, sizeof(map_path
), "%s/%s/%s", YP_DB_PATH
,
312 db
= ypdb_open(map_path
, O_RDONLY
, 0444);
316 yplog(" ypdb_open_db: errno %d (%s)",
317 errno
,sys_errlist
[errno
]);
319 if ((errno
== ENFILE
) || (errno
== EMFILE
)) {
329 *status
= YP_NOMAP
; /* see note below */
331 if (errno
== ENOENT
) {
333 yplog(" ypdb_open_db: no map %s (domain=%s)",
339 yplog(" ypdb_open_db: ypdb_open FAILED: map %s (domain=%s)",
346 * note: status now YP_NOMAP
349 if (d
== NULL
) { /* allocate new domain? */
350 d
= (struct opt_domain
*) malloc(sizeof(*d
));
351 if (d
) d
->domain
= strdup(domain
);
352 if (d
== NULL
|| d
->domain
== NULL
) {
353 yplog(" ypdb_open_db: MALLOC failed");
358 LIST_INIT(&d
->dmaps
);
359 LIST_INSERT_HEAD(&doms
, d
, domsl
);
361 yplog(" ypdb_open_db: NEW DOMAIN %s", domain
);
366 * m must be NULL since we couldn't find a map. allocate new one
369 m
= (struct opt_map
*) malloc(sizeof(*m
));
371 m
->map
= strdup(map
);
373 if (m
== NULL
|| m
->map
== NULL
) {
375 yplog(" ypdb_open_db: MALLOC failed");
381 m
->host_lookup
= FALSE
;
382 CIRCLEQ_INSERT_HEAD(&maps
, m
, mapsq
);
383 LIST_INSERT_HEAD(&d
->dmaps
, m
, mapsl
);
384 if (strcmp(map
, YP_HOSTNAME
) == 0 || strcmp(map
, YP_HOSTADDR
) == 0) {
387 k
.dsize
= YP_INTERDOMAIN_LEN
;
388 v
= ypdb_fetch(db
,k
);
389 if (v
.dptr
) m
->host_lookup
= TRUE
;
391 m
->host_lookup
= TRUE
;
396 k
.dsize
= YP_SECURE_LEN
;
397 v
= ypdb_fetch(db
,k
);
398 if (v
.dptr
) m
->secure
= TRUE
;
400 if (map_info
) *map_info
= m
;
402 yplog(" ypdb_open_db: NEW MAP domain=%s, map=%s, hl=%d, s=%d, db=0x%x",
403 domain
, map
, m
->host_lookup
, m
->secure
, m
->db
);
410 * lookup host. Not needed for Rhapsody, lookupd does this stuff.
414 lookup_host(nametable
, host_lookup
, db
, keystr
, result
)
421 struct hostent
*host
;
422 struct in_addr
*addr_name
;
423 struct in_addr addr_addr
;
424 static char val
[BUFSIZ
+1]; /* match libc */
425 static hostname
[MAXHOSTNAMELEN
];
426 char tmpbuf
[MAXHOSTNAMELEN
+ 20];
431 if (!host_lookup
) return(YP_NOKEY
);
433 if ((_res
.options
& RES_INIT
) == 0)
435 bcopy("b", _res
.lookups
, sizeof("b"));
438 host
= gethostbyname(keystr
);
439 if (host
== NULL
|| host
->h_addrtype
!= AF_INET
)
441 addr_name
= (struct in_addr
*) *host
->h_addr_list
;
443 for (; host
->h_addr_list
[0] != NULL
; host
->h_addr_list
++) {
444 addr_name
= (struct in_addr
*)host
->h_addr_list
[0];
445 snprintf(tmpbuf
,sizeof(tmpbuf
), "%s %s\n",
446 inet_ntoa(*addr_name
), host
->h_name
);
447 if (v
- val
+ strlen(tmpbuf
) + 1 > sizeof(val
))
450 v
= v
+ strlen(tmpbuf
);
452 result
->val
.valdat_val
= val
;
453 result
->val
.valdat_len
= v
- val
;
457 inet_aton(keystr
, &addr_addr
);
458 host
= gethostbyaddr((char *) &addr_addr
, sizeof(addr_addr
), AF_INET
);
459 if (host
== NULL
) return(YP_NOKEY
);
461 strncpy((char *)hostname
, host
->h_name
, sizeof(hostname
) - 1);
462 hostname
[sizeof(hostname
) - 1] = '\0';
463 host
= gethostbyname((char *)hostname
);
464 if (host
== NULL
) return(YP_NOKEY
);
467 for(; host
->h_addr_list
[0] != NULL
; host
->h_addr_list
++)
468 if (!bcmp(host
->h_addr_list
[0], &addr_addr
, sizeof(addr_addr
)))
471 yplog("lookup_host: address %s not listed for host %s\n",
472 inet_ntoa(addr_addr
), hostname
);
474 "ypserv: address %s not listed for host %s\n",
475 inet_ntoa(addr_addr
), hostname
);
479 snprintf(val
,sizeof(val
),"%s %s",keystr
,host
->h_name
);
482 while ((ptr
= *(host
->h_aliases
)) != NULL
) {
484 if ((v
- val
) + l
+ 1 > BUFSIZ
)
492 result
->val
.valdat_val
= val
;
493 result
->val
.valdat_len
= v
- val
;
500 ypdb_get_record(domain
, map
, key
, ypprivate
)
506 static ypresp_val res
;
507 /* static char keystr[YPMAXRECORD+1]; */
511 struct opt_map
*map_info
= NULL
;
513 bzero((char *)&res
, sizeof(res
));
515 db
= ypdb_open_db(domain
, map
, &res
.stat
, &map_info
);
516 if (!db
|| res
.stat
< 0)
519 host_lookup
= map_info
->host_lookup
;
521 k
.dptr
= key
.keydat_val
;
522 k
.dsize
= key
.keydat_len
;
524 if (yp_private(k
,ypprivate
)) {
529 v
= ypdb_fetch(db
, k
);
531 /* lookupd does DNS resolution, not ypserv. */
532 if (v
.dptr
== NULL
) {
534 res
.val
.valdat_val
= NULL
;
535 res
.val
.valdat_len
= 0;
537 res
.val
.valdat_val
= v
.dptr
;
538 res
.val
.valdat_len
= v
.dsize
;
548 ypdb_get_first(domain
, map
, ypprivate
)
553 static ypresp_key_val res
;
557 bzero((char *)&res
, sizeof(res
));
559 db
= ypdb_open_db(domain
, map
, &res
.stat
, NULL
);
563 k
= ypdb_firstkey(db
);
565 while (yp_private(k
,ypprivate
)) {
566 k
= ypdb_nextkey(db
);
569 if (k
.dptr
== NULL
) {
572 res
.key
.keydat_val
= k
.dptr
;
573 res
.key
.keydat_len
= k
.dsize
;
574 v
= ypdb_fetch(db
,k
);
575 if (v
.dptr
== NULL
) {
578 res
.val
.valdat_val
= v
.dptr
;
579 res
.val
.valdat_len
= v
.dsize
;
590 ypdb_get_next(domain
, map
, key
, ypprivate
)
596 static ypresp_key_val res
;
600 bzero((char *)&res
, sizeof(res
));
602 db
= ypdb_open_db(domain
, map
, &res
.stat
, NULL
);
606 n
.dptr
= key
.keydat_val
;
607 n
.dsize
= key
.keydat_len
;
613 n
= ypdb_setkey(db
,n
);
615 if (n
.dptr
!= NULL
) {
616 k
= ypdb_nextkey(db
);
621 if (k
.dptr
!= NULL
) {
622 while (yp_private(k
,ypprivate
)) {
623 k
= ypdb_nextkey(db
);
627 if (k
.dptr
== NULL
) {
628 res
.stat
= YP_NOMORE
;
630 res
.key
.keydat_val
= k
.dptr
;
631 res
.key
.keydat_len
= k
.dsize
;
632 v
= ypdb_fetch(db
,k
);
633 if (v
.dptr
== NULL
) {
634 res
.stat
= YP_NOMORE
;
636 res
.val
.valdat_val
= v
.dptr
;
637 res
.val
.valdat_len
= v
.dsize
;
648 ypdb_get_order(domain
, map
)
652 static ypresp_order res
;
653 static char *order_key
= YP_LAST_KEY
;
654 char order
[MAX_LAST_LEN
+1];
658 bzero((char *)&res
, sizeof(res
));
660 db
= ypdb_open_db(domain
, map
, &res
.stat
, NULL
);
665 k
.dsize
= YP_LAST_LEN
;
667 v
= ypdb_fetch(db
,k
);
668 if (v
.dptr
== NULL
) {
671 strncpy(order
, v
.dptr
, v
.dsize
);
672 order
[v
.dsize
] = '\0';
673 res
.ordernum
= (u_int32_t
)atol(order
);
683 ypdb_get_master(domain
, map
)
687 static ypresp_master res
;
688 static char *master_key
= YP_MASTER_KEY
;
689 static char master
[MAX_MASTER_LEN
+1];
693 bzero((char *)&res
, sizeof(res
));
695 db
= ypdb_open_db(domain
, map
, &res
.stat
, NULL
);
700 k
.dsize
= YP_MASTER_LEN
;
702 v
= ypdb_fetch(db
,k
);
703 if (v
.dptr
== NULL
) {
706 strncpy(master
, v
.dptr
, v
.dsize
);
707 master
[v
.dsize
] = '\0';
708 res
.peer
= (peername
) &master
;
718 ypdb_xdr_get_all(xdrs
, req
)
722 static ypresp_all resp
;
726 bzero((char *)&resp
, sizeof(resp
));
729 * open db, and advance past any private keys we may see
732 db
= ypdb_open_db(req
->domain
, req
->map
,
733 &resp
.ypresp_all_u
.val
.stat
, NULL
);
734 if (!db
|| resp
.ypresp_all_u
.val
.stat
< 0)
736 k
= ypdb_firstkey(db
);
737 while (yp_private(k
,FALSE
)) {
738 k
= ypdb_nextkey(db
);
746 v
= ypdb_fetch(db
,k
);
752 resp
.ypresp_all_u
.val
.stat
= YP_TRUE
;
753 resp
.ypresp_all_u
.val
.key
.keydat_val
= k
.dptr
;
754 resp
.ypresp_all_u
.val
.key
.keydat_len
= k
.dsize
;
755 resp
.ypresp_all_u
.val
.val
.valdat_val
= v
.dptr
;
756 resp
.ypresp_all_u
.val
.val
.valdat_len
= v
.dsize
;
758 if (!xdr_ypresp_all(xdrs
, &resp
)) {
760 yplog(" ypdb_xdr_get_all: xdr_ypresp_all failed");
765 /* advance past private keys */
766 k
= ypdb_nextkey(db
);
767 while (yp_private(k
,FALSE
)) {
768 k
= ypdb_nextkey(db
);
772 bzero((char *)&resp
, sizeof(resp
));
773 resp
.ypresp_all_u
.val
.stat
= YP_NOKEY
;
776 if (!xdr_ypresp_all(xdrs
, &resp
)) {
778 yplog(" ypdb_xdr_get_all: final xdr_ypresp_all failed");
789 ypdb_secure(domain
, map
)
793 static ypresp_val res
;
796 struct opt_map
*map_info
= NULL
;
798 bzero((char *)&res
, sizeof(res
));
801 db
= ypdb_open_db(domain
, map
, &res
.stat
, &map_info
);
802 if (!db
|| res
.stat
< 0)
803 return(secure
); /* ? */
805 secure
= map_info
->secure
;