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