1 /* $NetBSD: ypxfr.c,v 1.18 2009/11/05 15:23:55 chuck Exp $ */
4 * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
31 __RCSID("$NetBSD: ypxfr.c,v 1.18 2009/11/05 15:23:55 chuck Exp $");
34 #include <sys/param.h>
35 #include <sys/types.h>
37 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
52 #include <rpcsvc/yp_prot.h>
53 #include <rpcsvc/ypclnt.h>
55 #include "yplib_host.h"
61 static int yperr2yppush(int);
62 static int ypxfr_foreach(int, char *, int, char *, int, char *);
64 int main(int, char *[]);
65 int get_local_ordernum(char *, char *, u_int
*);
66 int get_remote_ordernum(CLIENT
*, char *, char *, u_int
, u_int
*);
67 void get_map(CLIENT
*, char *, char *, struct ypall_callback
*);
68 DBM
*create_db(char *, char *, char *, size_t);
69 int install_db(char *, char *, char *);
70 int unlink_db(char *, char *, char *);
71 int add_order(DBM
*, u_int
);
72 int add_master(CLIENT
*, char *, char *, DBM
*);
73 int add_interdomain(CLIENT
*, char *, char *, DBM
*);
74 int add_secure(CLIENT
*, char *, char *, DBM
*);
75 int send_clear(CLIENT
*);
76 int send_reply(CLIENT
*, int, int);
79 main(int argc
, char **argv
)
81 int need_usage
= 0, cflag
= 0, fflag
= 0, Cflag
= 0;
85 char *srcdomain
= NULL
;
91 u_int ordernum
, new_ordernum
;
92 struct ypall_callback callback
;
94 char temp_map
[MAXPATHLEN
];
95 int status
, xfr_status
;
100 if (yp_get_default_domain(&domain
))
101 errx(1, "can't get YP domain name");
103 while ((ch
= getopt(argc
, argv
, "cd:fh:s:C:")) != -1) {
126 if (optind
+ 3 >= argc
) {
133 prog
= argv
[optind
++];
134 ipadd
= argv
[optind
++];
135 port
= argv
[optind
++];
142 argc
-= optind
; argv
+= optind
;
150 status
= YPPUSH_BADARGS
;
151 fprintf(stderr
, "usage: %s [-cf] [-d domain] [-h host] %s\n",
153 "[-s domain] [-C tid prog ipadd port] mapname");
158 openlog("ypxfr", LOG_PID
, LOG_DAEMON
);
160 syslog(LOG_DEBUG
, "ypxfr: Arguments:");
161 syslog(LOG_DEBUG
, "YP clear to local: %s", (cflag
) ? "no" : "yes");
162 syslog(LOG_DEBUG
, " Force transfer: %s", (fflag
) ? "yes" : "no");
163 syslog(LOG_DEBUG
, " domain: %s", domain
);
164 syslog(LOG_DEBUG
, " host: %s", host
);
165 syslog(LOG_DEBUG
, " source domain: %s", srcdomain
);
166 syslog(LOG_DEBUG
, " transid: %s", tid
);
167 syslog(LOG_DEBUG
, " prog: %s", prog
);
168 syslog(LOG_DEBUG
, " port: %s", port
);
169 syslog(LOG_DEBUG
, " ipadd: %s", ipadd
);
170 syslog(LOG_DEBUG
, " map: %s", map
);
176 status
= get_local_ordernum(domain
, map
, &ordernum
);
182 syslog(LOG_DEBUG
, "Get Master");
186 if (srcdomain
== NULL
)
187 status
= yp_master(domain
, map
, &host
);
189 status
= yp_master(srcdomain
, map
, &host
);
192 status
= YPPUSH_SUCC
;
194 status
= YPPUSH_MADDR
;
200 syslog(LOG_DEBUG
, "Connect host: %s", host
);
203 client
= yp_bind_host(host
, YPPROG
, YPVERS
, 0, 1);
205 status
= get_remote_ordernum(client
, domain
, map
, ordernum
,
209 if (status
== YPPUSH_SUCC
) {
210 /* Create temporary db */
211 db
= create_db(domain
, map
, temp_map
, sizeof(temp_map
));
217 status
= add_order(db
, new_ordernum
);
221 status
= add_master(client
, domain
, map
, db
);
223 /* Add INTERDOMAIN */
225 status
= add_interdomain(client
, domain
, map
, db
);
229 status
= add_secure(client
, domain
, map
, db
);
232 callback
.foreach
= ypxfr_foreach
;
233 get_map(client
, domain
, map
, &callback
);
242 status
= install_db(domain
, map
, temp_map
);
244 (void) unlink_db(domain
, map
, temp_map
);
251 clnt_destroy(client
);
255 client
= yp_bind_local(YPPROG
, YPVERS
);
256 status
= send_clear(client
);
257 clnt_destroy(client
);
262 client
= yp_bind_host(ipadd
, atoi(prog
), 1, atoi(port
), 0);
263 status
= send_reply(client
, xfr_status
, atoi(tid
));
264 clnt_destroy(client
);
271 * yperr2yppush: convert error codes from functions like yp_order_host,
272 * yp_master_host, and yp_match_host into YPPUSH rpc status values.
275 yperr2yppush(int yperr
) {
278 return(YPPUSH_NODOM
);
280 return(YPPUSH_NOMAP
);
282 return(YPPUSH_YPERR
);
284 return(YPPUSH_YPERR
);
288 * generic error status for the rest (BADARGS, RPC, YPERR, RESRC,
289 * NOMORE, PMAP, YPBIND, YPSERV, NODOM, VERS, ACCESS, BUSY)
291 return(YPPUSH_XFRERR
); /* generic error status */
295 ypxfr_foreach(int status
, char *keystr
, int keylen
, char *valstr
,
296 int vallen
, char *data
)
300 if (status
== YP_NOMORE
)
303 keystr
[keylen
] = '\0';
304 valstr
[vallen
] = '\0';
307 key
.dsize
= strlen(keystr
);
310 val
.dsize
= strlen(valstr
);
312 /* XXX: suspect... ignoring return value here */
313 ypdb_store(db
, key
, val
, YPDB_INSERT
);
319 get_local_ordernum(char *domain
, char *map
, u_int
*lordernum
)
322 char order_key
[] = YP_LAST_KEY
;
323 char order
[MAX_LAST_LEN
+1];
329 status
= YPPUSH_SUCC
;
331 snprintf(map_path
, sizeof(map_path
), "%s/%s", YP_DB_PATH
, domain
);
333 /* Make sure we serve the domain. */
334 if ((stat(map_path
, &finfo
)) != 0 ||
335 (S_ISDIR(finfo
.st_mode
) == 0)) {
336 warnx("domain `%s' not found locally", domain
);
337 status
= YPPUSH_NODOM
;
341 /* Make sure we serve the map. */
342 snprintf(map_path
, sizeof(map_path
), "%s/%s/%s%s",
343 YP_DB_PATH
, domain
, map
, YPDB_SUFFIX
);
344 if (stat(map_path
, &finfo
) != 0) {
345 status
= YPPUSH_NOMAP
;
349 /* Open the map file. */
350 snprintf(map_path
, sizeof(map_path
), "%s/%s/%s",
351 YP_DB_PATH
, domain
, map
);
352 ldb
= ypdb_open(map_path
);
358 k
.dptr
= (char *)&order_key
;
359 k
.dsize
= YP_LAST_LEN
;
361 v
= ypdb_fetch(ldb
, k
);
366 strncpy(order
, v
.dptr
, v
.dsize
);
367 order
[v
.dsize
] = '\0';
368 *lordernum
= (u_int
)atoi((char *)&order
);
373 if ((status
== YPPUSH_NOMAP
) || (status
== YPPUSH_DBM
)) {
375 status
= YPPUSH_SUCC
;
382 get_remote_ordernum(CLIENT
*client
, char *domain
, char *map
,
383 u_int lordernum
, u_int
*rordernum
)
387 status
= yp_order_host(client
, domain
, map
, (int *)rordernum
);
390 if (*rordernum
<= lordernum
)
393 status
= YPPUSH_SUCC
;
395 status
= yperr2yppush(status
);
402 get_map(CLIENT
*client
, char *domain
, char *map
,
403 struct ypall_callback
*incallback
)
406 (void)yp_all_host(client
, domain
, map
, incallback
);
410 create_db(char *domain
, char *map
, char *db_temp
, size_t db_temp_len
)
412 static const char template[] = "ypdbXXXXXX";
415 snprintf(db_temp
, db_temp_len
, "%s/%s/%s",
416 YP_DB_PATH
, domain
, template);
418 ldb
= ypdb_mktemp(db_temp
);
424 install_db(char *domain
, char *map
, char *db_temp
)
426 char db_name
[MAXPATHLEN
];
428 snprintf(db_name
, sizeof(db_name
), "%s/%s/%s%s",
429 YP_DB_PATH
, domain
, map
, YPDB_SUFFIX
);
431 if (rename(db_temp
, db_name
)) {
432 warn("can't rename `%s' -> `%s'", db_temp
, db_name
);
440 unlink_db(char *domain
, char *map
, char *db_temp
)
443 if (unlink(db_temp
)) {
444 warn("can't unlink `%s'", db_temp
);
452 add_order(DBM
*ldb
, u_int ordernum
)
456 char keystr
[] = YP_LAST_KEY
;
459 snprintf(datestr
, sizeof(datestr
), "%010d", ordernum
);
462 key
.dsize
= strlen(keystr
);
465 val
.dsize
= strlen(datestr
);
467 status
= ypdb_store(ldb
, key
, val
, YPDB_INSERT
);
469 status
= YPPUSH_SUCC
;
477 add_master(CLIENT
*client
, char *domain
, char *map
, DBM
*ldb
)
479 char keystr
[] = YP_MASTER_KEY
;
487 status
= yp_master_host(client
, domain
, map
, &master
);
489 if (master
!= NULL
) {
491 key
.dsize
= strlen(keystr
);
494 val
.dsize
= strlen(master
);
496 status
= ypdb_store(ldb
, key
, val
, YPDB_INSERT
);
498 status
= YPPUSH_SUCC
;
502 status
= yperr2yppush(status
);
509 add_interdomain(CLIENT
*client
, char *domain
, char *map
, DBM
*ldb
)
511 char keystr
[] = YP_INTERDOMAIN_KEY
;
517 /* Get INTERDOMAIN */
519 k
.dsize
= strlen(keystr
);
521 status
= yp_match_host(client
, domain
, map
,
522 k
.dptr
, k
.dsize
, &value
, &vallen
);
524 if (status
== YPERR_KEY
) {
525 /* this is an optional key/val, so it may not be present */
526 status
= YPPUSH_SUCC
;
527 } else if (status
== 0 && value
) {
531 if (v
.dptr
!= NULL
) {
532 status
= ypdb_store(ldb
, k
, v
, YPDB_INSERT
);
534 status
= YPPUSH_SUCC
;
539 status
= yperr2yppush(status
);
546 add_secure(CLIENT
*client
, char *domain
, char *map
, DBM
*ldb
)
548 char keystr
[] = YP_SECURE_KEY
;
556 k
.dsize
= strlen(keystr
);
558 status
= yp_match_host(client
, domain
, map
,
559 k
.dptr
, k
.dsize
, &value
, &vallen
);
561 if (status
== YPERR_KEY
) {
562 /* this is an optional key/val, so it may not be present */
563 status
= YPPUSH_SUCC
;
564 } else if (status
== 0 && value
!= 0) {
568 if (v
.dptr
!= NULL
) {
569 status
= ypdb_store(ldb
, k
, v
, YPDB_INSERT
);
571 status
= YPPUSH_SUCC
;
576 status
= yperr2yppush(status
);
583 send_clear(CLIENT
*client
)
589 status
= YPPUSH_SUCC
;
595 r
= clnt_call(client
, YPPROC_CLEAR
, xdr_void
, 0, xdr_void
, 0, tv
);
596 if (r
!= RPC_SUCCESS
) {
597 clnt_perror(client
, "yp_clear: clnt_call");
605 send_reply(CLIENT
*client
, int status
, int tid
)
608 struct ypresp_xfr resp
;
615 resp
.xfrstat
= status
;
618 r
= clnt_call(client
, YPPUSHPROC_XFRRESP
, xdr_ypresp_xfr
, &resp
,
620 if (r
!= RPC_SUCCESS
) {
621 clnt_perror(client
, "yppushresp_xdr: clnt_call");