]>
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 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 /* $OpenBSD: ypserv_db.c,v 1.13 1997/08/09 23:10:12 maja Exp $ */
28 * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
29 * Copyright (c) 1996 Charles D. Cranor
30 * All rights reserved.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by Mats O Jansson
43 * and Charles D. Cranor.
44 * 4. The name of the author may not be used to endorse or promote products
45 * derived from this software without specific prior written permission.
47 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
48 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
49 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
51 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 static char rcsid
[] = "$OpenBSD: ypserv_db.c,v 1.13 1997/08/09 23:10:12 maja Exp $";
65 * major revision/cleanup of Mats' version
66 * done by Chuck Cranor <chuck@ccrc.wustl.edu>
72 #include <rpcsvc/yp.h>
73 #include <rpcsvc/ypclnt.h>
75 #include <sys/param.h>
81 #include <arpa/nameser.h>
83 #include <sys/types.h>
84 #include <sys/socket.h>
85 #include <sys/queue.h>
86 #include <netinet/in.h>
87 #include <arpa/inet.h>
89 #include <sys/errno.h>
94 LIST_HEAD(domainlist
, opt_domain
); /* LIST of domains */
95 LIST_HEAD(maplist
, opt_map
); /* LIST of maps (in a domain) */
96 CIRCLEQ_HEAD(mapq
, opt_map
); /* CIRCLEQ of maps (LRU) */
99 mapname map
; /* map name (malloc'd) */
100 DBM
*db
; /* database */
101 struct opt_domain
*dom
; /* back ptr to our domain */
102 int host_lookup
; /* host lookup */
103 int secure
; /* secure map? */
104 CIRCLEQ_ENTRY(opt_map
) mapsq
; /* map queue pointers */
105 LIST_ENTRY(opt_map
) mapsl
; /* map list pointers */
109 domainname domain
; /* domain name (malloc'd) */
110 struct maplist dmaps
; /* the domain's active maps */
111 LIST_ENTRY(opt_domain
) domsl
; /* global linked list of domains */
115 struct domainlist doms
; /* global list of domains */
116 struct mapq maps
; /* global queue of maps (LRU) */
121 * ypdb_init: init the queues and lists
135 * Check if key is a YP private key. Return TRUE if it is and
136 * ypprivate is FALSE.
140 yp_private(key
,ypprivate
)
149 if (key
.dsize
== 0 || key
.dptr
== NULL
)
152 if (key
.dsize
== YP_LAST_LEN
&&
153 strncmp(key
.dptr
,YP_LAST_KEY
,YP_LAST_LEN
) == 0)
155 if (key
.dsize
== YP_INPUT_LEN
&&
156 strncmp(key
.dptr
,YP_INPUT_KEY
,YP_INPUT_LEN
) == 0)
158 if (key
.dsize
== YP_OUTPUT_LEN
&&
159 strncmp(key
.dptr
,YP_OUTPUT_KEY
,YP_OUTPUT_LEN
) == 0)
161 if (key
.dsize
== YP_MASTER_LEN
&&
162 strncmp(key
.dptr
,YP_MASTER_KEY
,YP_MASTER_LEN
) == 0)
164 if (key
.dsize
== YP_DOMAIN_LEN
&&
165 strncmp(key
.dptr
,YP_DOMAIN_KEY
,YP_DOMAIN_LEN
) == 0)
167 if (key
.dsize
== YP_INTERDOMAIN_LEN
&&
168 strncmp(key
.dptr
,YP_INTERDOMAIN_KEY
,YP_INTERDOMAIN_LEN
) == 0)
170 if (key
.dsize
== YP_SECURE_LEN
&&
171 strncmp(key
.dptr
,YP_SECURE_KEY
,YP_SECURE_LEN
) == 0)
178 * Close least recent used map. This routine is called when we have
179 * no more file descripotors free, or we want to close all maps.
185 struct opt_map
*last
= maps
.cqh_last
;
187 if (last
== (void*)&maps
) {
188 yplog(" ypdb_close_last: LRU list is empty!");
192 CIRCLEQ_REMOVE(&maps
, last
, mapsq
); /* remove from LRU circleq */
193 LIST_REMOVE(last
, mapsl
); /* remove from domain list */
196 yplog(" ypdb_close_last: closing map %s in domain %s [db=0x%x]",
197 last
->map
, last
->dom
->domain
, last
->db
);
200 ypdb_close(last
->db
); /* close DB */
201 free(last
->map
); /* free map name */
202 free(last
); /* free map */
208 * Close all open maps.
216 yplog(" ypdb_close_all(): start");
218 while (maps
.cqh_first
!= (void *)&maps
) {
222 yplog(" ypdb_close_all(): done");
227 * Close Database if Open/Close Optimization isn't turned on.
235 yplog(" ypdb_close_db(0x%x)", db
);
247 ypdb_open_db(domain
, map
, status
, map_info
)
251 struct opt_map
**map_info
;
253 char map_path
[MAXPATHLEN
];
254 static char *domain_key
= YP_INTERDOMAIN_KEY
;
255 static char *secure_key
= YP_SECURE_KEY
;
256 /* struct stat finfo; */
259 struct opt_domain
*d
= NULL
;
260 struct opt_map
*m
= NULL
;
266 * check for preloaded domain, map
269 for (d
= doms
.lh_first
; d
!= NULL
; d
= d
->domsl
.le_next
) {
270 if (strcmp(domain
, d
->domain
) == 0) break;
274 for (m
= d
->dmaps
.lh_first
; m
!= NULL
; m
= m
->mapsl
.le_next
)
275 if (strcmp(map
, m
->map
) == 0) break;
284 yplog(" ypdb_open_db: cached open: domain=%s, map=%s, db=0x%x",
287 CIRCLEQ_REMOVE(&maps
, m
, mapsq
); /* adjust LRU queue */
288 CIRCLEQ_INSERT_HEAD(&maps
, m
, mapsq
);
293 /* Check for illegal charcaters */
295 if (strchr(domain
, '/')) {
299 if (strchr(map
, '/')) {
312 snprintf(map_path
, sizeof(map_path
), "%s/%s/%s", YP_DB_PATH
,
314 db
= ypdb_open(map_path
, O_RDONLY
, 0444);
318 yplog(" ypdb_open_db: errno %d (%s)",
319 errno
,sys_errlist
[errno
]);
321 if ((errno
== ENFILE
) || (errno
== EMFILE
)) {
331 *status
= YP_NOMAP
; /* see note below */
333 if (errno
== ENOENT
) {
335 yplog(" ypdb_open_db: no map %s (domain=%s)",
341 yplog(" ypdb_open_db: ypdb_open FAILED: map %s (domain=%s)",
348 * note: status now YP_NOMAP
351 if (d
== NULL
) { /* allocate new domain? */
352 d
= (struct opt_domain
*) malloc(sizeof(*d
));
353 if (d
) d
->domain
= strdup(domain
);
354 if (d
== NULL
|| d
->domain
== NULL
) {
355 yplog(" ypdb_open_db: MALLOC failed");
360 LIST_INIT(&d
->dmaps
);
361 LIST_INSERT_HEAD(&doms
, d
, domsl
);
363 yplog(" ypdb_open_db: NEW DOMAIN %s", domain
);
368 * m must be NULL since we couldn't find a map. allocate new one
371 m
= (struct opt_map
*) malloc(sizeof(*m
));
373 m
->map
= strdup(map
);
375 if (m
== NULL
|| m
->map
== NULL
) {
377 yplog(" ypdb_open_db: MALLOC failed");
383 m
->host_lookup
= FALSE
;
384 CIRCLEQ_INSERT_HEAD(&maps
, m
, mapsq
);
385 LIST_INSERT_HEAD(&d
->dmaps
, m
, mapsl
);
386 if (strcmp(map
, YP_HOSTNAME
) == 0 || strcmp(map
, YP_HOSTADDR
) == 0) {
389 k
.dsize
= YP_INTERDOMAIN_LEN
;
390 v
= ypdb_fetch(db
,k
);
391 if (v
.dptr
) m
->host_lookup
= TRUE
;
393 m
->host_lookup
= TRUE
;
398 k
.dsize
= YP_SECURE_LEN
;
399 v
= ypdb_fetch(db
,k
);
400 if (v
.dptr
) m
->secure
= TRUE
;
402 if (map_info
) *map_info
= m
;
404 yplog(" ypdb_open_db: NEW MAP domain=%s, map=%s, hl=%d, s=%d, db=0x%x",
405 domain
, map
, m
->host_lookup
, m
->secure
, m
->db
);
412 * lookup host. Not needed for Rhapsody, lookupd does this stuff.
416 lookup_host(nametable
, host_lookup
, db
, keystr
, result
)
423 struct hostent
*host
;
424 struct in_addr
*addr_name
;
425 struct in_addr addr_addr
;
426 static char val
[BUFSIZ
+1]; /* match libc */
427 static hostname
[MAXHOSTNAMELEN
];
428 char tmpbuf
[MAXHOSTNAMELEN
+ 20];
433 if (!host_lookup
) return(YP_NOKEY
);
435 if ((_res
.options
& RES_INIT
) == 0)
437 bcopy("b", _res
.lookups
, sizeof("b"));
440 host
= gethostbyname(keystr
);
441 if (host
== NULL
|| host
->h_addrtype
!= AF_INET
)
443 addr_name
= (struct in_addr
*) *host
->h_addr_list
;
445 for (; host
->h_addr_list
[0] != NULL
; host
->h_addr_list
++) {
446 addr_name
= (struct in_addr
*)host
->h_addr_list
[0];
447 snprintf(tmpbuf
,sizeof(tmpbuf
), "%s %s\n",
448 inet_ntoa(*addr_name
), host
->h_name
);
449 if (v
- val
+ strlen(tmpbuf
) + 1 > sizeof(val
))
452 v
= v
+ strlen(tmpbuf
);
454 result
->val
.valdat_val
= val
;
455 result
->val
.valdat_len
= v
- val
;
459 inet_aton(keystr
, &addr_addr
);
460 host
= gethostbyaddr((char *) &addr_addr
, sizeof(addr_addr
), AF_INET
);
461 if (host
== NULL
) return(YP_NOKEY
);
463 strncpy((char *)hostname
, host
->h_name
, sizeof(hostname
) - 1);
464 hostname
[sizeof(hostname
) - 1] = '\0';
465 host
= gethostbyname((char *)hostname
);
466 if (host
== NULL
) return(YP_NOKEY
);
469 for(; host
->h_addr_list
[0] != NULL
; host
->h_addr_list
++)
470 if (!bcmp(host
->h_addr_list
[0], &addr_addr
, sizeof(addr_addr
)))
473 yplog("lookup_host: address %s not listed for host %s\n",
474 inet_ntoa(addr_addr
), hostname
);
476 "ypserv: address %s not listed for host %s\n",
477 inet_ntoa(addr_addr
), hostname
);
481 snprintf(val
,sizeof(val
),"%s %s",keystr
,host
->h_name
);
484 while ((ptr
= *(host
->h_aliases
)) != NULL
) {
486 if ((v
- val
) + l
+ 1 > BUFSIZ
)
494 result
->val
.valdat_val
= val
;
495 result
->val
.valdat_len
= v
- val
;
502 ypdb_get_record(domain
, map
, key
, ypprivate
)
508 static ypresp_val res
;
509 /* static char keystr[YPMAXRECORD+1]; */
513 struct opt_map
*map_info
= NULL
;
515 bzero((char *)&res
, sizeof(res
));
517 db
= ypdb_open_db(domain
, map
, &res
.stat
, &map_info
);
518 if (!db
|| res
.stat
< 0)
521 host_lookup
= map_info
->host_lookup
;
523 k
.dptr
= key
.keydat_val
;
524 k
.dsize
= key
.keydat_len
;
526 if (yp_private(k
,ypprivate
)) {
531 v
= ypdb_fetch(db
, k
);
533 /* lookupd does DNS resolution, not ypserv. */
534 if (v
.dptr
== NULL
) {
536 res
.val
.valdat_val
= NULL
;
537 res
.val
.valdat_len
= 0;
539 res
.val
.valdat_val
= v
.dptr
;
540 res
.val
.valdat_len
= v
.dsize
;
550 ypdb_get_first(domain
, map
, ypprivate
)
555 static ypresp_key_val res
;
559 bzero((char *)&res
, sizeof(res
));
561 db
= ypdb_open_db(domain
, map
, &res
.stat
, NULL
);
565 k
= ypdb_firstkey(db
);
567 while (yp_private(k
,ypprivate
)) {
568 k
= ypdb_nextkey(db
);
571 if (k
.dptr
== NULL
) {
574 res
.key
.keydat_val
= k
.dptr
;
575 res
.key
.keydat_len
= k
.dsize
;
576 v
= ypdb_fetch(db
,k
);
577 if (v
.dptr
== NULL
) {
580 res
.val
.valdat_val
= v
.dptr
;
581 res
.val
.valdat_len
= v
.dsize
;
592 ypdb_get_next(domain
, map
, key
, ypprivate
)
598 static ypresp_key_val res
;
602 bzero((char *)&res
, sizeof(res
));
604 db
= ypdb_open_db(domain
, map
, &res
.stat
, NULL
);
608 n
.dptr
= key
.keydat_val
;
609 n
.dsize
= key
.keydat_len
;
615 n
= ypdb_setkey(db
,n
);
617 if (n
.dptr
!= NULL
) {
618 k
= ypdb_nextkey(db
);
623 if (k
.dptr
!= NULL
) {
624 while (yp_private(k
,ypprivate
)) {
625 k
= ypdb_nextkey(db
);
629 if (k
.dptr
== NULL
) {
630 res
.stat
= YP_NOMORE
;
632 res
.key
.keydat_val
= k
.dptr
;
633 res
.key
.keydat_len
= k
.dsize
;
634 v
= ypdb_fetch(db
,k
);
635 if (v
.dptr
== NULL
) {
636 res
.stat
= YP_NOMORE
;
638 res
.val
.valdat_val
= v
.dptr
;
639 res
.val
.valdat_len
= v
.dsize
;
650 ypdb_get_order(domain
, map
)
654 static ypresp_order res
;
655 static char *order_key
= YP_LAST_KEY
;
656 char order
[MAX_LAST_LEN
+1];
660 bzero((char *)&res
, sizeof(res
));
662 db
= ypdb_open_db(domain
, map
, &res
.stat
, NULL
);
667 k
.dsize
= YP_LAST_LEN
;
669 v
= ypdb_fetch(db
,k
);
670 if (v
.dptr
== NULL
) {
673 strncpy(order
, v
.dptr
, v
.dsize
);
674 order
[v
.dsize
] = '\0';
675 res
.ordernum
= (u_int32_t
)atol(order
);
685 ypdb_get_master(domain
, map
)
689 static ypresp_master res
;
690 static char *master_key
= YP_MASTER_KEY
;
691 static char master
[MAX_MASTER_LEN
+1];
695 bzero((char *)&res
, sizeof(res
));
697 db
= ypdb_open_db(domain
, map
, &res
.stat
, NULL
);
702 k
.dsize
= YP_MASTER_LEN
;
704 v
= ypdb_fetch(db
,k
);
705 if (v
.dptr
== NULL
) {
708 strncpy(master
, v
.dptr
, v
.dsize
);
709 master
[v
.dsize
] = '\0';
710 res
.peer
= (peername
) &master
;
720 ypdb_xdr_get_all(xdrs
, req
)
724 static ypresp_all resp
;
728 bzero((char *)&resp
, sizeof(resp
));
731 * open db, and advance past any private keys we may see
734 db
= ypdb_open_db(req
->domain
, req
->map
,
735 &resp
.ypresp_all_u
.val
.stat
, NULL
);
736 if (!db
|| resp
.ypresp_all_u
.val
.stat
< 0)
738 k
= ypdb_firstkey(db
);
739 while (yp_private(k
,FALSE
)) {
740 k
= ypdb_nextkey(db
);
748 v
= ypdb_fetch(db
,k
);
754 resp
.ypresp_all_u
.val
.stat
= YP_TRUE
;
755 resp
.ypresp_all_u
.val
.key
.keydat_val
= k
.dptr
;
756 resp
.ypresp_all_u
.val
.key
.keydat_len
= k
.dsize
;
757 resp
.ypresp_all_u
.val
.val
.valdat_val
= v
.dptr
;
758 resp
.ypresp_all_u
.val
.val
.valdat_len
= v
.dsize
;
760 if (!xdr_ypresp_all(xdrs
, &resp
)) {
762 yplog(" ypdb_xdr_get_all: xdr_ypresp_all failed");
767 /* advance past private keys */
768 k
= ypdb_nextkey(db
);
769 while (yp_private(k
,FALSE
)) {
770 k
= ypdb_nextkey(db
);
774 bzero((char *)&resp
, sizeof(resp
));
775 resp
.ypresp_all_u
.val
.stat
= YP_NOKEY
;
778 if (!xdr_ypresp_all(xdrs
, &resp
)) {
780 yplog(" ypdb_xdr_get_all: final xdr_ypresp_all failed");
791 ypdb_secure(domain
, map
)
795 static ypresp_val res
;
798 struct opt_map
*map_info
= NULL
;
800 bzero((char *)&res
, sizeof(res
));
803 db
= ypdb_open_db(domain
, map
, &res
.stat
, &map_info
);
804 if (!db
|| res
.stat
< 0)
805 return(secure
); /* ? */
807 secure
= map_info
->secure
;