]>
git.saurik.com Git - apple/network_cmds.git/blob - ypserv.tproj/ypserv_db.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
24 /* $OpenBSD: ypserv_db.c,v 1.13 1997/08/09 23:10:12 maja Exp $ */
27 * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
28 * Copyright (c) 1996 Charles D. Cranor
29 * All rights reserved.
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. All advertising materials mentioning features or use of this software
40 * must display the following acknowledgement:
41 * This product includes software developed by Mats O Jansson
42 * and Charles D. Cranor.
43 * 4. The name of the author may not be used to endorse or promote products
44 * derived from this software without specific prior written permission.
46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
47 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
48 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
50 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 static char rcsid
[] = "$OpenBSD: ypserv_db.c,v 1.13 1997/08/09 23:10:12 maja Exp $";
64 * major revision/cleanup of Mats' version
65 * done by Chuck Cranor <chuck@ccrc.wustl.edu>
71 #include <rpcsvc/yp.h>
72 #include <rpcsvc/ypclnt.h>
74 #include <sys/param.h>
80 #include <arpa/nameser.h>
82 #include <sys/types.h>
83 #include <sys/socket.h>
84 #include <sys/queue.h>
85 #include <netinet/in.h>
86 #include <arpa/inet.h>
88 #include <sys/errno.h>
93 LIST_HEAD(domainlist
, opt_domain
); /* LIST of domains */
94 LIST_HEAD(maplist
, opt_map
); /* LIST of maps (in a domain) */
95 CIRCLEQ_HEAD(mapq
, opt_map
); /* CIRCLEQ of maps (LRU) */
98 mapname map
; /* map name (malloc'd) */
99 DBM
*db
; /* database */
100 struct opt_domain
*dom
; /* back ptr to our domain */
101 int host_lookup
; /* host lookup */
102 int secure
; /* secure map? */
103 CIRCLEQ_ENTRY(opt_map
) mapsq
; /* map queue pointers */
104 LIST_ENTRY(opt_map
) mapsl
; /* map list pointers */
108 domainname domain
; /* domain name (malloc'd) */
109 struct maplist dmaps
; /* the domain's active maps */
110 LIST_ENTRY(opt_domain
) domsl
; /* global linked list of domains */
114 struct domainlist doms
; /* global list of domains */
115 struct mapq maps
; /* global queue of maps (LRU) */
120 * ypdb_init: init the queues and lists
134 * Check if key is a YP private key. Return TRUE if it is and
135 * ypprivate is FALSE.
139 yp_private(key
,ypprivate
)
148 if (key
.dsize
== 0 || key
.dptr
== NULL
)
151 if (key
.dsize
== YP_LAST_LEN
&&
152 strncmp(key
.dptr
,YP_LAST_KEY
,YP_LAST_LEN
) == 0)
154 if (key
.dsize
== YP_INPUT_LEN
&&
155 strncmp(key
.dptr
,YP_INPUT_KEY
,YP_INPUT_LEN
) == 0)
157 if (key
.dsize
== YP_OUTPUT_LEN
&&
158 strncmp(key
.dptr
,YP_OUTPUT_KEY
,YP_OUTPUT_LEN
) == 0)
160 if (key
.dsize
== YP_MASTER_LEN
&&
161 strncmp(key
.dptr
,YP_MASTER_KEY
,YP_MASTER_LEN
) == 0)
163 if (key
.dsize
== YP_DOMAIN_LEN
&&
164 strncmp(key
.dptr
,YP_DOMAIN_KEY
,YP_DOMAIN_LEN
) == 0)
166 if (key
.dsize
== YP_INTERDOMAIN_LEN
&&
167 strncmp(key
.dptr
,YP_INTERDOMAIN_KEY
,YP_INTERDOMAIN_LEN
) == 0)
169 if (key
.dsize
== YP_SECURE_LEN
&&
170 strncmp(key
.dptr
,YP_SECURE_KEY
,YP_SECURE_LEN
) == 0)
177 * Close least recent used map. This routine is called when we have
178 * no more file descripotors free, or we want to close all maps.
184 struct opt_map
*last
= maps
.cqh_last
;
186 if (last
== (void*)&maps
) {
187 yplog(" ypdb_close_last: LRU list is empty!");
191 CIRCLEQ_REMOVE(&maps
, last
, mapsq
); /* remove from LRU circleq */
192 LIST_REMOVE(last
, mapsl
); /* remove from domain list */
195 yplog(" ypdb_close_last: closing map %s in domain %s [db=0x%x]",
196 last
->map
, last
->dom
->domain
, last
->db
);
199 ypdb_close(last
->db
); /* close DB */
200 free(last
->map
); /* free map name */
201 free(last
); /* free map */
207 * Close all open maps.
215 yplog(" ypdb_close_all(): start");
217 while (maps
.cqh_first
!= (void *)&maps
) {
221 yplog(" ypdb_close_all(): done");
226 * Close Database if Open/Close Optimization isn't turned on.
234 yplog(" ypdb_close_db(0x%x)", db
);
246 ypdb_open_db(domain
, map
, status
, map_info
)
250 struct opt_map
**map_info
;
252 char map_path
[MAXPATHLEN
];
253 static char *domain_key
= YP_INTERDOMAIN_KEY
;
254 static char *secure_key
= YP_SECURE_KEY
;
255 /* struct stat finfo; */
258 struct opt_domain
*d
= NULL
;
259 struct opt_map
*m
= NULL
;
265 * check for preloaded domain, map
268 for (d
= doms
.lh_first
; d
!= NULL
; d
= d
->domsl
.le_next
) {
269 if (strcmp(domain
, d
->domain
) == 0) break;
273 for (m
= d
->dmaps
.lh_first
; m
!= NULL
; m
= m
->mapsl
.le_next
)
274 if (strcmp(map
, m
->map
) == 0) break;
283 yplog(" ypdb_open_db: cached open: domain=%s, map=%s, db=0x%x",
286 CIRCLEQ_REMOVE(&maps
, m
, mapsq
); /* adjust LRU queue */
287 CIRCLEQ_INSERT_HEAD(&maps
, m
, mapsq
);
292 /* Check for illegal charcaters */
294 if (strchr(domain
, '/')) {
298 if (strchr(map
, '/')) {
311 snprintf(map_path
, sizeof(map_path
), "%s/%s/%s", YP_DB_PATH
,
313 db
= ypdb_open(map_path
, O_RDONLY
, 0444);
317 yplog(" ypdb_open_db: errno %d (%s)",
318 errno
,sys_errlist
[errno
]);
320 if ((errno
== ENFILE
) || (errno
== EMFILE
)) {
330 *status
= YP_NOMAP
; /* see note below */
332 if (errno
== ENOENT
) {
334 yplog(" ypdb_open_db: no map %s (domain=%s)",
340 yplog(" ypdb_open_db: ypdb_open FAILED: map %s (domain=%s)",
347 * note: status now YP_NOMAP
350 if (d
== NULL
) { /* allocate new domain? */
351 d
= (struct opt_domain
*) malloc(sizeof(*d
));
352 if (d
) d
->domain
= strdup(domain
);
353 if (d
== NULL
|| d
->domain
== NULL
) {
354 yplog(" ypdb_open_db: MALLOC failed");
359 LIST_INIT(&d
->dmaps
);
360 LIST_INSERT_HEAD(&doms
, d
, domsl
);
362 yplog(" ypdb_open_db: NEW DOMAIN %s", domain
);
367 * m must be NULL since we couldn't find a map. allocate new one
370 m
= (struct opt_map
*) malloc(sizeof(*m
));
372 m
->map
= strdup(map
);
374 if (m
== NULL
|| m
->map
== NULL
) {
376 yplog(" ypdb_open_db: MALLOC failed");
382 m
->host_lookup
= FALSE
;
383 CIRCLEQ_INSERT_HEAD(&maps
, m
, mapsq
);
384 LIST_INSERT_HEAD(&d
->dmaps
, m
, mapsl
);
385 if (strcmp(map
, YP_HOSTNAME
) == 0 || strcmp(map
, YP_HOSTADDR
) == 0) {
388 k
.dsize
= YP_INTERDOMAIN_LEN
;
389 v
= ypdb_fetch(db
,k
);
390 if (v
.dptr
) m
->host_lookup
= TRUE
;
392 m
->host_lookup
= TRUE
;
397 k
.dsize
= YP_SECURE_LEN
;
398 v
= ypdb_fetch(db
,k
);
399 if (v
.dptr
) m
->secure
= TRUE
;
401 if (map_info
) *map_info
= m
;
403 yplog(" ypdb_open_db: NEW MAP domain=%s, map=%s, hl=%d, s=%d, db=0x%x",
404 domain
, map
, m
->host_lookup
, m
->secure
, m
->db
);
411 * lookup host. Not needed for Rhapsody, lookupd does this stuff.
415 lookup_host(nametable
, host_lookup
, db
, keystr
, result
)
422 struct hostent
*host
;
423 struct in_addr
*addr_name
;
424 struct in_addr addr_addr
;
425 static char val
[BUFSIZ
+1]; /* match libc */
426 static hostname
[MAXHOSTNAMELEN
];
427 char tmpbuf
[MAXHOSTNAMELEN
+ 20];
432 if (!host_lookup
) return(YP_NOKEY
);
434 if ((_res
.options
& RES_INIT
) == 0)
436 bcopy("b", _res
.lookups
, sizeof("b"));
439 host
= gethostbyname(keystr
);
440 if (host
== NULL
|| host
->h_addrtype
!= AF_INET
)
442 addr_name
= (struct in_addr
*) *host
->h_addr_list
;
444 for (; host
->h_addr_list
[0] != NULL
; host
->h_addr_list
++) {
445 addr_name
= (struct in_addr
*)host
->h_addr_list
[0];
446 snprintf(tmpbuf
,sizeof(tmpbuf
), "%s %s\n",
447 inet_ntoa(*addr_name
), host
->h_name
);
448 if (v
- val
+ strlen(tmpbuf
) + 1 > sizeof(val
))
451 v
= v
+ strlen(tmpbuf
);
453 result
->val
.valdat_val
= val
;
454 result
->val
.valdat_len
= v
- val
;
458 inet_aton(keystr
, &addr_addr
);
459 host
= gethostbyaddr((char *) &addr_addr
, sizeof(addr_addr
), AF_INET
);
460 if (host
== NULL
) return(YP_NOKEY
);
462 strncpy((char *)hostname
, host
->h_name
, sizeof(hostname
) - 1);
463 hostname
[sizeof(hostname
) - 1] = '\0';
464 host
= gethostbyname((char *)hostname
);
465 if (host
== NULL
) return(YP_NOKEY
);
468 for(; host
->h_addr_list
[0] != NULL
; host
->h_addr_list
++)
469 if (!bcmp(host
->h_addr_list
[0], &addr_addr
, sizeof(addr_addr
)))
472 yplog("lookup_host: address %s not listed for host %s\n",
473 inet_ntoa(addr_addr
), hostname
);
475 "ypserv: address %s not listed for host %s\n",
476 inet_ntoa(addr_addr
), hostname
);
480 snprintf(val
,sizeof(val
),"%s %s",keystr
,host
->h_name
);
483 while ((ptr
= *(host
->h_aliases
)) != NULL
) {
485 if ((v
- val
) + l
+ 1 > BUFSIZ
)
493 result
->val
.valdat_val
= val
;
494 result
->val
.valdat_len
= v
- val
;
501 ypdb_get_record(domain
, map
, key
, ypprivate
)
507 static ypresp_val res
;
508 /* static char keystr[YPMAXRECORD+1]; */
512 struct opt_map
*map_info
= NULL
;
514 bzero((char *)&res
, sizeof(res
));
516 db
= ypdb_open_db(domain
, map
, &res
.stat
, &map_info
);
517 if (!db
|| res
.stat
< 0)
520 host_lookup
= map_info
->host_lookup
;
522 k
.dptr
= key
.keydat_val
;
523 k
.dsize
= key
.keydat_len
;
525 if (yp_private(k
,ypprivate
)) {
530 v
= ypdb_fetch(db
, k
);
532 /* lookupd does DNS resolution, not ypserv. */
533 if (v
.dptr
== NULL
) {
535 res
.val
.valdat_val
= NULL
;
536 res
.val
.valdat_len
= 0;
538 res
.val
.valdat_val
= v
.dptr
;
539 res
.val
.valdat_len
= v
.dsize
;
549 ypdb_get_first(domain
, map
, ypprivate
)
554 static ypresp_key_val res
;
558 bzero((char *)&res
, sizeof(res
));
560 db
= ypdb_open_db(domain
, map
, &res
.stat
, NULL
);
564 k
= ypdb_firstkey(db
);
566 while (yp_private(k
,ypprivate
)) {
567 k
= ypdb_nextkey(db
);
570 if (k
.dptr
== NULL
) {
573 res
.key
.keydat_val
= k
.dptr
;
574 res
.key
.keydat_len
= k
.dsize
;
575 v
= ypdb_fetch(db
,k
);
576 if (v
.dptr
== NULL
) {
579 res
.val
.valdat_val
= v
.dptr
;
580 res
.val
.valdat_len
= v
.dsize
;
591 ypdb_get_next(domain
, map
, key
, ypprivate
)
597 static ypresp_key_val res
;
601 bzero((char *)&res
, sizeof(res
));
603 db
= ypdb_open_db(domain
, map
, &res
.stat
, NULL
);
607 n
.dptr
= key
.keydat_val
;
608 n
.dsize
= key
.keydat_len
;
614 n
= ypdb_setkey(db
,n
);
616 if (n
.dptr
!= NULL
) {
617 k
= ypdb_nextkey(db
);
622 if (k
.dptr
!= NULL
) {
623 while (yp_private(k
,ypprivate
)) {
624 k
= ypdb_nextkey(db
);
628 if (k
.dptr
== NULL
) {
629 res
.stat
= YP_NOMORE
;
631 res
.key
.keydat_val
= k
.dptr
;
632 res
.key
.keydat_len
= k
.dsize
;
633 v
= ypdb_fetch(db
,k
);
634 if (v
.dptr
== NULL
) {
635 res
.stat
= YP_NOMORE
;
637 res
.val
.valdat_val
= v
.dptr
;
638 res
.val
.valdat_len
= v
.dsize
;
649 ypdb_get_order(domain
, map
)
653 static ypresp_order res
;
654 static char *order_key
= YP_LAST_KEY
;
655 char order
[MAX_LAST_LEN
+1];
659 bzero((char *)&res
, sizeof(res
));
661 db
= ypdb_open_db(domain
, map
, &res
.stat
, NULL
);
666 k
.dsize
= YP_LAST_LEN
;
668 v
= ypdb_fetch(db
,k
);
669 if (v
.dptr
== NULL
) {
672 strncpy(order
, v
.dptr
, v
.dsize
);
673 order
[v
.dsize
] = '\0';
674 res
.ordernum
= (u_int32_t
)atol(order
);
684 ypdb_get_master(domain
, map
)
688 static ypresp_master res
;
689 static char *master_key
= YP_MASTER_KEY
;
690 static char master
[MAX_MASTER_LEN
+1];
694 bzero((char *)&res
, sizeof(res
));
696 db
= ypdb_open_db(domain
, map
, &res
.stat
, NULL
);
701 k
.dsize
= YP_MASTER_LEN
;
703 v
= ypdb_fetch(db
,k
);
704 if (v
.dptr
== NULL
) {
707 strncpy(master
, v
.dptr
, v
.dsize
);
708 master
[v
.dsize
] = '\0';
709 res
.peer
= (peername
) &master
;
719 ypdb_xdr_get_all(xdrs
, req
)
723 static ypresp_all resp
;
727 bzero((char *)&resp
, sizeof(resp
));
730 * open db, and advance past any private keys we may see
733 db
= ypdb_open_db(req
->domain
, req
->map
,
734 &resp
.ypresp_all_u
.val
.stat
, NULL
);
735 if (!db
|| resp
.ypresp_all_u
.val
.stat
< 0)
737 k
= ypdb_firstkey(db
);
738 while (yp_private(k
,FALSE
)) {
739 k
= ypdb_nextkey(db
);
747 v
= ypdb_fetch(db
,k
);
753 resp
.ypresp_all_u
.val
.stat
= YP_TRUE
;
754 resp
.ypresp_all_u
.val
.key
.keydat_val
= k
.dptr
;
755 resp
.ypresp_all_u
.val
.key
.keydat_len
= k
.dsize
;
756 resp
.ypresp_all_u
.val
.val
.valdat_val
= v
.dptr
;
757 resp
.ypresp_all_u
.val
.val
.valdat_len
= v
.dsize
;
759 if (!xdr_ypresp_all(xdrs
, &resp
)) {
761 yplog(" ypdb_xdr_get_all: xdr_ypresp_all failed");
766 /* advance past private keys */
767 k
= ypdb_nextkey(db
);
768 while (yp_private(k
,FALSE
)) {
769 k
= ypdb_nextkey(db
);
773 bzero((char *)&resp
, sizeof(resp
));
774 resp
.ypresp_all_u
.val
.stat
= YP_NOKEY
;
777 if (!xdr_ypresp_all(xdrs
, &resp
)) {
779 yplog(" ypdb_xdr_get_all: final xdr_ypresp_all failed");
790 ypdb_secure(domain
, map
)
794 static ypresp_val res
;
797 struct opt_map
*map_info
= NULL
;
799 bzero((char *)&res
, sizeof(res
));
802 db
= ypdb_open_db(domain
, map
, &res
.stat
, &map_info
);
803 if (!db
|| res
.stat
< 0)
804 return(secure
); /* ? */
806 secure
= map_info
->secure
;