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