]> git.saurik.com Git - apple/network_cmds.git/blob - ypxfr.tproj/ypxfr.c
ee763f7391155bd48e5a9be100cab5bba2e638e2
[apple/network_cmds.git] / ypxfr.tproj / ypxfr.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
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
13 * file.
14 *
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.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /* $OpenBSD: ypxfr.c,v 1.22 1997/07/30 12:07:02 maja Exp $ */
26
27 /*
28 * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
29 * All rights reserved.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
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 * 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.
44 *
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
55 * SUCH DAMAGE.
56 */
57
58 #ifndef LINT
59 static char rcsid[] = "$OpenBSD: ypxfr.c,v 1.22 1997/07/30 12:07:02 maja Exp $";
60 #endif
61
62 #include <sys/types.h>
63 #include <sys/stat.h>
64 #include <sys/socket.h>
65
66 #include <netinet/in.h>
67 #include <arpa/inet.h>
68
69 #include <stdio.h>
70 #include <stdlib.h>
71 #include <unistd.h>
72 #include <fcntl.h>
73 #include <string.h>
74 #include <netdb.h>
75
76 #include <rpc/rpc.h>
77 #include <rpc/xdr.h>
78 #include <rpcsvc/yp.h>
79 #include <rpcsvc/ypclnt.h>
80
81 #include "yplib_host.h"
82 #include "yplog.h"
83 #include "ypdb.h"
84 #include "ypdef.h"
85
86 extern char *__progname; /* from crt0.o */
87 DBM *db;
88
89 extern bool_t xdr_ypresp_all_seq();
90
91 extern int (*ypresp_allfn)();
92 extern void *ypresp_data;
93
94 static int
95 ypxfr_foreach(status,keystr,keylen,valstr,vallen,data)
96 int status,keylen,vallen;
97 char *keystr,*valstr,*data;
98 {
99 datum key,val;
100
101 if (status == YP_NOMORE)
102 return(0);
103
104 keystr[keylen] = '\0';
105 valstr[vallen] = '\0';
106
107 key.dptr = keystr;
108 key.dsize = strlen(keystr);
109
110 val.dptr = valstr;
111 val.dsize = strlen(valstr);
112
113 ypdb_store(db, key, val, YPDB_INSERT);
114
115 return 0;
116 }
117
118 int
119 get_local_ordernum(domain, map, lordernum)
120 char *domain;
121 char *map;
122 u_int32_t *lordernum;
123 {
124 char map_path[MAXPATHLEN];
125 char order_key[] = YP_LAST_KEY;
126 char order[MAX_LAST_LEN+1];
127 struct stat finfo;
128 DBM *db;
129 datum k,v;
130 int status;
131
132 /* This routine returns YPPUSH_SUCC or YPPUSH_NODOM */
133
134 status = YPPUSH_SUCC;
135
136 snprintf(map_path, sizeof map_path, "%s/%s", YP_DB_PATH, domain);
137 if (!((stat(map_path, &finfo) == 0) &&
138 ((finfo.st_mode & S_IFMT) == S_IFDIR))) {
139 fprintf(stderr, "%s: domain %s not found locally\n",
140 __progname, domain);
141 status = YPPUSH_NODOM;
142 }
143
144 if(status > 0) {
145 snprintf(map_path, sizeof map_path, "%s/%s/%s%s",
146 YP_DB_PATH, domain, map, YPDB_SUFFIX);
147 if(!(stat(map_path, &finfo) == 0)) {
148 status = YPPUSH_NOMAP;
149 }
150 }
151
152 if(status > 0) {
153 snprintf(map_path, sizeof map_path, "%s/%s/%s",
154 YP_DB_PATH, domain, map);
155 db = ypdb_open(map_path, O_RDONLY, 0444);
156 if(db == NULL) {
157 status = YPPUSH_DBM;
158 }
159
160 }
161
162 if(status > 0) {
163 k.dptr = (char *)&order_key;
164 k.dsize = YP_LAST_LEN;
165
166 v = ypdb_fetch(db,k);
167 ypdb_close(db);
168
169 if (v.dptr == NULL) {
170 *lordernum = 0;
171 } else {
172 strncpy(order, v.dptr, sizeof order-1);
173 order[sizeof order-1] = '\0';
174 *lordernum = (u_int32_t)atol(order);
175 }
176 }
177
178 if((status == YPPUSH_NOMAP) || (status == YPPUSH_DBM)) {
179 *lordernum = 0;
180 status = YPPUSH_SUCC;
181 }
182
183 return(status);
184
185 }
186
187 int
188 get_remote_ordernum(client, domain, map, lordernum, rordernum)
189 CLIENT *client;
190 char *domain;
191 char *map;
192 u_int32_t lordernum;
193 u_int32_t *rordernum;
194 {
195 int status;
196
197 status = yp_order_host(client, domain, map, rordernum);
198
199 if (status == 0) {
200 if(*rordernum <= lordernum) {
201 status = YPPUSH_AGE;
202 } else {
203 status = YPPUSH_SUCC;
204 }
205 }
206
207 return status;
208 }
209
210 void
211 get_map(client,domain,map,incallback)
212 CLIENT *client;
213 char *domain;
214 char *map;
215 struct ypall_callback *incallback;
216 {
217 (void)yp_all_host(client, domain, map, incallback);
218
219 }
220
221 DBM *
222 create_db(domain,map,temp_map)
223 char *domain;
224 char *map;
225 char *temp_map;
226 {
227 return ypdb_open_suf(temp_map, O_RDWR, 0444);
228 }
229
230 int
231 install_db(domain,map,temp_map)
232 char *domain;
233 char *map;
234 char *temp_map;
235 {
236 char db_name[MAXPATHLEN];
237
238 snprintf(db_name, sizeof db_name, "%s/%s/%s%s",
239 YP_DB_PATH, domain, map, YPDB_SUFFIX);
240 rename(temp_map, db_name);
241
242 return YPPUSH_SUCC;
243 }
244
245 int
246 add_order(db, ordernum)
247 DBM *db;
248 u_int32_t ordernum;
249 {
250 char datestr[11];
251 datum key,val;
252 char keystr[] = YP_LAST_KEY;
253 int status;
254
255 sprintf(datestr, "%010u", ordernum);
256
257 key.dptr = keystr;
258 key.dsize = strlen(keystr);
259
260 val.dptr = datestr;
261 val.dsize = strlen(datestr);
262
263 status = ypdb_store(db, key, val, YPDB_INSERT);
264 if(status >= 0) {
265 status = YPPUSH_SUCC;
266 } else {
267 status = YPPUSH_DBM;
268 }
269 return(status);
270 }
271
272 int
273 add_master(client, domain, map, db)
274 CLIENT *client;
275 char *domain;
276 char *map;
277 DBM *db;
278 {
279 char keystr[] = YP_MASTER_KEY;
280 char *master;
281 int status;
282 datum key,val;
283
284 master = NULL;
285
286 /* Get MASTER */
287
288 status = yp_master_host(client, domain, map, &master);
289
290 if(master != NULL) {
291 key.dptr = keystr;
292 key.dsize = strlen(keystr);
293
294 val.dptr = master;
295 val.dsize = strlen(master);
296
297 status = ypdb_store(db, key, val, YPDB_INSERT);
298 if(status >= 0) {
299 status = YPPUSH_SUCC;
300 } else {
301 status = YPPUSH_DBM;
302 }
303 }
304
305 return status;
306 }
307
308 int
309 add_interdomain(client, domain, map, db)
310 CLIENT *client;
311 char *domain;
312 char *map;
313 DBM *db;
314 {
315 char keystr[] = YP_INTERDOMAIN_KEY;
316 char *value;
317 int vallen;
318 int status;
319 datum k,v;
320
321 /* Get INTERDOMAIN */
322
323 k.dptr = keystr;
324 k.dsize = strlen(keystr);
325
326 status = yp_match_host(client, domain, map,
327 k.dptr, k.dsize, &value, &vallen);
328
329 if(status == 0 && value) {
330 v.dptr = value;
331 v.dsize = vallen;
332
333 if(v.dptr != NULL) {
334 status = ypdb_store(db,k,v,YPDB_INSERT);
335 if(status >= 0) {
336 status = YPPUSH_SUCC;
337 } else {
338 status = YPPUSH_DBM;
339 }
340 }
341 }
342
343 return 1;
344 }
345
346 int
347 add_secure(client, domain, map, db)
348 CLIENT *client;
349 char *domain;
350 char *map;
351 DBM *db;
352 {
353 char keystr[] = YP_SECURE_KEY;
354 char *value;
355 int vallen;
356 int status;
357 datum k,v;
358
359 /* Get SECURE */
360
361 k.dptr = keystr;
362 k.dsize = strlen(keystr);
363
364 status = yp_match_host(client, domain, map,
365 k.dptr, k.dsize, &value, &vallen);
366
367 if(status > 0) {
368 v.dptr = value;
369 v.dsize = vallen;
370
371 if(v.dptr != NULL) {
372 status = ypdb_store(db,k,v,YPDB_INSERT);
373 if(status >= 0) {
374 status = YPPUSH_SUCC;
375 } else {
376 status = YPPUSH_DBM;
377 }
378 }
379 }
380
381 return status;
382
383 }
384
385 int
386 send_clear(client)
387 CLIENT *client;
388 {
389 struct timeval tv;
390 int r;
391 int status;
392
393 status = YPPUSH_SUCC;
394
395 tv.tv_sec = 10;
396 tv.tv_usec = 0;
397
398 /* Send CLEAR */
399
400 r = clnt_call(client, YPPROC_CLEAR,
401 xdr_void, 0, xdr_void, 0, tv);
402 if(r != RPC_SUCCESS) {
403 clnt_perror(client, "yp_clear: clnt_call");
404 }
405
406 return status;
407
408 }
409
410 int
411 send_reply(client,status,tid)
412 CLIENT *client;
413 u_long status;
414 u_long tid;
415 {
416 struct timeval tv;
417 struct ypresp_xfr resp;
418 int r;
419
420 tv.tv_sec = 10;
421 tv.tv_usec = 0;
422
423 resp.transid = tid;
424 resp.xfrstat = status;
425
426 /* Send CLEAR */
427
428 r = clnt_call(client, 1,
429 xdr_ypresp_xfr, &resp, xdr_void, 0, tv);
430 if(r != RPC_SUCCESS) {
431 clnt_perror(client, "yppushresp_xdr: clnt_call");
432 }
433
434 return status;
435
436 }
437
438 int
439 main (argc,argv)
440 int argc;
441 char *argv[];
442 {
443 int usage = 0;
444 int cflag = 0;
445 int fflag = 0;
446 int Cflag = 0;
447 int ch;
448 extern char *optarg;
449 char *domain;
450 char *host = NULL;
451 char *srcdomain = NULL;
452 char *tid = NULL;
453 char *prog = NULL;
454 char *ipadd = NULL;
455 char *port = NULL;
456 char *map = NULL;
457 u_int32_t ordernum, new_ordernum;
458 struct ypall_callback callback;
459 CLIENT *client;
460 int status,xfr_status;
461 int srvport;
462
463 status = YPPUSH_SUCC;
464 client = NULL;
465
466 yp_get_default_domain(&domain);
467
468 while ((ch = getopt(argc, argv, "cd:fh:s:C:")) != -1)
469 switch (ch) {
470 case 'c':
471 cflag++;
472 break;
473 case 'd':
474 if (strchr(optarg, '/')) /* Ha ha, we are not listening */
475 break;
476 domain = optarg;
477 break;
478 case 'f':
479 fflag++;
480 break;
481 case 'h':
482 host = optarg;
483 break;
484 case 's':
485 if (strchr(optarg, '/')) /* Ha ha, we are not listening */
486 break;
487 srcdomain = optarg;
488 break;
489 case 'C':
490 if (optind + 3 >= argc) {
491 usage++;
492 optind = argc;
493 break;
494 }
495 Cflag++;
496 tid = optarg;
497 prog = argv[optind++];
498 ipadd = argv[optind++];
499 port = argv[optind++];
500 break;
501 default:
502 usage++;
503 break;
504 }
505
506 if(optind + 1 != argc) {
507 usage++;
508 } else {
509 map = argv[optind];
510 }
511
512 if (usage) {
513 status = YPPUSH_BADARGS;
514 fprintf(stderr, "usage: %s %s %s\n",
515 "[-cf] [-d domain] [-h host] [-s domain]",
516 "[-C tid prog ipadd port] mapname\n",
517 __progname);
518 }
519
520 if (status > 0) {
521 ypopenlog();
522
523 yplog("ypxfr: Arguments:");
524 yplog("YP clear to local: %s", (cflag) ? "no" : "yes");
525 yplog(" Force transfer: %s", (fflag) ? "yes" : "no");
526 yplog(" domain: %s", domain);
527 yplog(" host: %s", host);
528 yplog(" source domain: %s", srcdomain);
529 yplog(" transid: %s", tid);
530 yplog(" prog: %s", prog);
531 yplog(" port: %s", port);
532 yplog(" ipadd: %s", ipadd);
533 yplog(" map: %s", map);
534
535 if(fflag != 0) {
536 ordernum = 0;
537 } else {
538 status = get_local_ordernum(domain, map, &ordernum);
539 }
540 }
541
542 if (status > 0) {
543
544 yplog("Get Master");
545
546 if (host == NULL) {
547 if (srcdomain == NULL) {
548 status = yp_master(domain,map,&host);
549 } else {
550 status = yp_master(srcdomain,map,&host);
551 }
552 if(status == 0) {
553 status = YPPUSH_SUCC;
554 } else {
555 status = -status;
556 }
557 }
558 };
559
560 /* XXX this is raceable if portmap has holes! */
561 if (status > 0) {
562
563 yplog("Check for reserved port on host: %s", host);
564
565 srvport = getrpcport(host,YPPROG,YPVERS,IPPROTO_TCP);
566 if (srvport >= IPPORT_RESERVED)
567 status = YPPUSH_REFUSED;
568
569 }
570
571 if (status > 0) {
572
573 yplog("Connect host: %s", host);
574
575 client = yp_bind_host(host,YPPROG,YPVERS,0,1);
576
577 status = get_remote_ordernum(client, domain, map,
578 ordernum, &new_ordernum);
579
580 }
581
582 if (status == YPPUSH_SUCC) {
583 char tmpmapname[MAXPATHLEN];
584 int fd;
585
586 /* Create temporary db */
587 snprintf(tmpmapname, sizeof tmpmapname,
588 "%s/%s/ypdbXXXXXXXXXX", YP_DB_PATH, domain);
589 fd = mkstemp(tmpmapname);
590 if (fd == -1)
591 status = YPPUSH_DBM;
592 else
593 close(fd);
594
595 if (status > 0) {
596 db = create_db(domain,map,tmpmapname);
597 if(db == NULL)
598 status = YPPUSH_DBM;
599 }
600
601 /* Add ORDER */
602 if(status > 0) {
603 status = add_order(db, new_ordernum);
604 }
605
606 /* Add MASTER */
607 if(status > 0) {
608 status = add_master(client,domain,map,db);
609 }
610
611 /* Add INTERDOMAIN */
612 if(status > 0) {
613 status = add_interdomain(client,domain,map,db);
614 }
615
616 /* Add SECURE */
617 if(status > 0) {
618 status = add_secure(client,domain,map,db);
619 }
620
621 if(status > 0) {
622 callback.foreach=ypxfr_foreach;
623 get_map(client,domain,map,&callback);
624 }
625
626 /* Close db */
627 if(db != NULL) {
628 ypdb_close(db);
629 }
630
631 /* Rename db */
632 if(status > 0) {
633 status = install_db(domain,map,tmpmapname);
634 } else {
635 unlink(tmpmapname);
636 status = YPPUSH_SUCC;
637 }
638
639 }
640
641 xfr_status = status;
642
643 if(client != NULL) {
644 clnt_destroy(client);
645 }
646
647 /* YP_CLEAR */
648
649 if(!cflag) {
650 client = yp_bind_local(YPPROG,YPVERS);
651 status = send_clear(client);
652 clnt_destroy(client);
653 }
654
655 if(Cflag > 0) {
656 /* Send Response */
657 client = yp_bind_host(ipadd,
658 atoi(prog),
659 1,
660 atoi(port),
661 0);
662 status = send_reply(client,xfr_status,atoi(tid));
663 clnt_destroy(client);
664 }
665
666 return(0);
667
668 }
669