File: | src/usr.sbin/ypserv/ypxfr/ypxfr.c |
Warning: | line 257, column 5 Value stored to 'status' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: ypxfr.c,v 1.39 2015/02/09 23:00:15 deraadt Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se> |
5 | * All rights reserved. |
6 | * |
7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions |
9 | * are met: |
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. |
15 | * |
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 |
26 | * SUCH DAMAGE. |
27 | */ |
28 | |
29 | #include <sys/types.h> |
30 | #include <sys/stat.h> |
31 | #include <sys/socket.h> |
32 | |
33 | #include <netinet/in.h> |
34 | #include <arpa/inet.h> |
35 | |
36 | #include <stdio.h> |
37 | #include <stdlib.h> |
38 | #include <unistd.h> |
39 | #include <fcntl.h> |
40 | #include <string.h> |
41 | #include <netdb.h> |
42 | |
43 | #include <rpc/rpc.h> |
44 | #include <rpc/xdr.h> |
45 | #include <rpcsvc/yp.h> |
46 | #include <rpcsvc/ypclnt.h> |
47 | |
48 | #include "yplib_host.h" |
49 | #include "yplog.h" |
50 | #include "ypdb.h" |
51 | #include "ypdef.h" |
52 | |
53 | DBM *db; |
54 | |
55 | static int |
56 | ypxfr_foreach(u_long status, char *keystr, int keylen, char *valstr, int vallen, |
57 | void *data) |
58 | { |
59 | datum key, val; |
60 | |
61 | if (status == YP_NOMORE) |
62 | return(0); |
63 | |
64 | keystr[keylen] = '\0'; |
65 | valstr[vallen] = '\0'; |
66 | |
67 | key.dptr = keystr; |
68 | key.dsize = strlen(keystr); |
69 | |
70 | val.dptr = valstr; |
71 | val.dsize = strlen(valstr); |
72 | |
73 | ypdb_store(db, key, val, YPDB_INSERT0); |
74 | return 0; |
75 | } |
76 | |
77 | static int |
78 | get_local_ordernum(char *domain, char *map, u_int32_t *lordernum) |
79 | { |
80 | char map_path[PATH_MAX1024], order[MAX_LAST_LEN10+1]; |
81 | char order_key[] = YP_LAST_KEY"YP_LAST_MODIFIED"; |
82 | struct stat finfo; |
83 | datum k, v; |
84 | int status; |
85 | DBM *db; |
86 | |
87 | /* This routine returns YPPUSH_SUCC or YPPUSH_NODOM */ |
88 | |
89 | status = YPPUSH_SUCC; |
90 | |
91 | snprintf(map_path, sizeof map_path, "%s/%s", YP_DB_PATH"/var/yp", domain); |
92 | if (!((stat(map_path, &finfo) == 0) && S_ISDIR(finfo.st_mode)((finfo.st_mode & 0170000) == 0040000))) { |
93 | fprintf(stderr(&__sF[2]), "ypxfr: domain %s not found locally\n", |
94 | domain); |
95 | status = YPPUSH_NODOM; |
96 | goto bail; |
97 | } |
98 | |
99 | snprintf(map_path, sizeof map_path, "%s/%s/%s%s", |
100 | YP_DB_PATH"/var/yp", domain, map, YPDB_SUFFIX".db"); |
101 | if (!(stat(map_path, &finfo) == 0)) { |
102 | status = YPPUSH_NOMAP; |
103 | goto bail; |
104 | } |
105 | |
106 | snprintf(map_path, sizeof map_path, "%s/%s/%s", |
107 | YP_DB_PATH"/var/yp", domain, map); |
108 | db = ypdb_open(map_path, O_RDONLY0x0000, 0444); |
109 | if (db == NULL((void *)0)) { |
110 | status = YPPUSH_DBM; |
111 | goto bail; |
112 | } |
113 | |
114 | k.dptr = (char *)&order_key; |
115 | k.dsize = YP_LAST_LEN(sizeof("YP_LAST_MODIFIED")-1); |
116 | |
117 | v = ypdb_fetch(db, k); |
118 | |
119 | if (v.dptr == NULL((void *)0)) { |
120 | *lordernum = 0; |
121 | } else { |
122 | strlcpy(order, v.dptr, sizeof order); |
123 | *lordernum = (u_int32_t)atol(order); |
124 | } |
125 | |
126 | ypdb_close(db); |
127 | bail: |
128 | if (status == YPPUSH_NOMAP || status == YPPUSH_DBM) { |
129 | *lordernum = 0; |
130 | status = YPPUSH_SUCC; |
131 | } |
132 | return (status); |
133 | |
134 | } |
135 | |
136 | static int |
137 | get_remote_ordernum(CLIENT *client, char *domain, char *map, |
138 | u_int32_t lordernum, u_int32_t *rordernum) |
139 | { |
140 | int status; |
141 | |
142 | status = yp_order_host(client, domain, map, rordernum); |
143 | |
144 | if (status == 0) { |
145 | if (*rordernum <= lordernum) |
146 | status = YPPUSH_AGE; |
147 | else |
148 | status = YPPUSH_SUCC; |
149 | } |
150 | return status; |
151 | } |
152 | |
153 | static int |
154 | get_map(CLIENT *client, char *domain, char *map, |
155 | struct ypall_callback *incallback) |
156 | { |
157 | int status; |
158 | |
159 | status = yp_all_host(client, domain, map, incallback); |
160 | if (status == 0 || status == YPERR_NOMORE8) |
161 | status = YPPUSH_SUCC; |
162 | else |
163 | status = YPPUSH_YPERR; |
164 | return (status); |
165 | } |
166 | |
167 | static DBM * |
168 | create_db(char *domain, char *map, char *temp_map) |
169 | { |
170 | return ypdb_open_suf(temp_map, O_RDWR0x0002, 0444); |
171 | } |
172 | |
173 | static int |
174 | install_db(char *domain, char *map, char *temp_map) |
175 | { |
176 | char db_name[PATH_MAX1024]; |
177 | |
178 | snprintf(db_name, sizeof db_name, "%s/%s/%s%s", |
179 | YP_DB_PATH"/var/yp", domain, map, YPDB_SUFFIX".db"); |
180 | rename(temp_map, db_name); |
181 | return YPPUSH_SUCC; |
182 | } |
183 | |
184 | static int |
185 | add_order(DBM *db, u_int32_t ordernum) |
186 | { |
187 | char datestr[11]; |
188 | datum key, val; |
189 | char keystr[] = YP_LAST_KEY"YP_LAST_MODIFIED"; |
190 | int status; |
191 | |
192 | snprintf(datestr, sizeof datestr, "%010u", ordernum); |
193 | |
194 | key.dptr = keystr; |
195 | key.dsize = strlen(keystr); |
196 | |
197 | val.dptr = datestr; |
198 | val.dsize = strlen(datestr); |
199 | |
200 | status = ypdb_store(db, key, val, YPDB_INSERT0); |
201 | if (status >= 0) |
202 | status = YPPUSH_SUCC; |
203 | else |
204 | status = YPPUSH_DBM; |
205 | return (status); |
206 | } |
207 | |
208 | static int |
209 | add_master(CLIENT *client, char *domain, char *map, DBM *db) |
210 | { |
211 | char keystr[] = YP_MASTER_KEY"YP_MASTER_NAME", *master = NULL((void *)0); |
212 | datum key, val; |
213 | int status; |
214 | |
215 | /* Get MASTER */ |
216 | status = yp_master_host(client, domain, map, &master); |
217 | |
218 | if (master != NULL((void *)0)) { |
219 | key.dptr = keystr; |
220 | key.dsize = strlen(keystr); |
221 | |
222 | val.dptr = master; |
223 | val.dsize = strlen(master); |
224 | |
225 | status = ypdb_store(db, key, val, YPDB_INSERT0); |
226 | if (status >= 0) |
227 | status = YPPUSH_SUCC; |
228 | else |
229 | status = YPPUSH_DBM; |
230 | } |
231 | return (status); |
232 | } |
233 | |
234 | static int |
235 | add_interdomain(CLIENT *client, char *domain, char *map, DBM *db) |
236 | { |
237 | char keystr[] = YP_INTERDOMAIN_KEY"YP_INTERDOMAIN", *value; |
238 | int vallen, status; |
239 | datum k, v; |
240 | |
241 | /* Get INTERDOMAIN */ |
242 | |
243 | k.dptr = keystr; |
244 | k.dsize = strlen(keystr); |
245 | |
246 | status = yp_match_host(client, domain, map, |
247 | k.dptr, k.dsize, &value, &vallen); |
248 | if (status == 0 && value) { |
249 | v.dptr = value; |
250 | v.dsize = vallen; |
251 | |
252 | if (v.dptr != NULL((void *)0)) { |
253 | status = ypdb_store(db, k, v, YPDB_INSERT0); |
254 | if (status >= 0) |
255 | status = YPPUSH_SUCC; |
256 | else |
257 | status = YPPUSH_DBM; |
Value stored to 'status' is never read | |
258 | } |
259 | } |
260 | return 1; |
261 | } |
262 | |
263 | static int |
264 | add_secure(CLIENT *client, char *domain, char *map, DBM *db) |
265 | { |
266 | char keystr[] = YP_SECURE_KEY"YP_SECURE", *value; |
267 | int vallen, status; |
268 | datum k, v; |
269 | |
270 | /* Get SECURE */ |
271 | |
272 | k.dptr = keystr; |
273 | k.dsize = strlen(keystr); |
274 | |
275 | status = yp_match_host(client, domain, map, |
276 | k.dptr, k.dsize, &value, &vallen); |
277 | if (status == 0 && value) { |
278 | v.dptr = value; |
279 | v.dsize = vallen; |
280 | |
281 | if (v.dptr != NULL((void *)0)) { |
282 | status = ypdb_store(db, k, v, YPDB_INSERT0); |
283 | if (status >= 0) |
284 | status = YPPUSH_SUCC; |
285 | else |
286 | status = YPPUSH_DBM; |
287 | } |
288 | } |
289 | return status; |
290 | } |
291 | |
292 | static int |
293 | send_clear(CLIENT *client) |
294 | { |
295 | struct timeval tv; |
296 | int status, r; |
297 | |
298 | status = YPPUSH_SUCC; |
299 | |
300 | tv.tv_sec = 10; |
301 | tv.tv_usec = 0; |
302 | |
303 | /* Send CLEAR */ |
304 | r = clnt_call(client, YPPROC_CLEAR, xdr_void, 0, xdr_void, 0, tv)((*(client)->cl_ops->cl_call)(client, ((u_long)7), xdr_void , (caddr_t)0, xdr_void, (caddr_t)0, tv)); |
305 | if (r != RPC_SUCCESS) |
306 | clnt_perror(client, "yp_clear: clnt_call"); |
307 | return status; |
308 | |
309 | } |
310 | |
311 | static int |
312 | send_reply(CLIENT *client, u_long status, u_long tid) |
313 | { |
314 | struct ypresp_xfr resp; |
315 | struct timeval tv; |
316 | int r; |
317 | |
318 | tv.tv_sec = 10; |
319 | tv.tv_usec = 0; |
320 | |
321 | resp.transid = tid; |
322 | resp.xfrstat = status; |
323 | |
324 | /* Send CLEAR */ |
325 | r = clnt_call(client, 1, xdr_ypresp_xfr, &resp, xdr_void, 0, tv)((*(client)->cl_ops->cl_call)(client, 1, xdr_ypresp_xfr , (caddr_t)&resp, xdr_void, (caddr_t)0, tv)); |
326 | if (r != RPC_SUCCESS) |
327 | clnt_perror(client, "yppushresp_xdr: clnt_call"); |
328 | return status; |
329 | |
330 | } |
331 | |
332 | static void |
333 | usage(void) |
334 | { |
335 | fprintf(stderr(&__sF[2]), |
336 | "usage: ypxfr [-cf] [-C tid prog ipadd port] [-d domain] " |
337 | "[-h host] [-s domain]\n" |
338 | " mapname\n"); |
339 | exit(1); |
340 | } |
341 | |
342 | int |
343 | main(int argc, char *argv[]) |
344 | { |
345 | int cflag = 0, fflag = 0, Cflag = 0; |
346 | char *domain, *host = NULL((void *)0), *srcdomain = NULL((void *)0); |
347 | char *tid = NULL((void *)0), *prog = NULL((void *)0), *ipadd = NULL((void *)0); |
348 | char *port = NULL((void *)0), *map = NULL((void *)0); |
349 | int status, xfr_status, ch, srvport; |
350 | u_int32_t ordernum, new_ordernum; |
351 | struct ypall_callback callback; |
352 | CLIENT *client = NULL((void *)0); |
353 | extern char *optarg; |
354 | |
355 | yp_get_default_domain(&domain); |
356 | |
357 | while ((ch = getopt(argc, argv, "cd:fh:s:C:")) != -1) |
358 | switch (ch) { |
359 | case 'c': |
360 | cflag = 1; |
361 | break; |
362 | case 'd': |
363 | if (strchr(optarg, '/')) /* Ha ha, we are not listening */ |
364 | break; |
365 | domain = optarg; |
366 | break; |
367 | case 'f': |
368 | fflag = 1; |
369 | break; |
370 | case 'h': |
371 | host = optarg; |
372 | break; |
373 | case 's': |
374 | if (strchr(optarg, '/')) /* Ha ha, we are not listening */ |
375 | break; |
376 | srcdomain = optarg; |
377 | break; |
378 | case 'C': |
379 | if (optind + 3 >= argc) |
380 | usage(); |
381 | Cflag = 1; |
382 | tid = optarg; |
383 | prog = argv[optind++]; |
384 | ipadd = argv[optind++]; |
385 | port = argv[optind++]; |
386 | break; |
387 | default: |
388 | usage(); |
389 | break; |
390 | } |
391 | |
392 | status = YPPUSH_SUCC; |
393 | |
394 | if (optind + 1 != argc) |
395 | usage(); |
396 | |
397 | map = argv[optind]; |
398 | |
399 | if (status > 0) { |
400 | ypopenlog(); |
401 | |
402 | yplog("ypxfr: Arguments:"); |
403 | yplog("YP clear to local: %s", (cflag) ? "no" : "yes"); |
404 | yplog(" Force transfer: %s", (fflag) ? "yes" : "no"); |
405 | yplog(" domain: %s", domain); |
406 | yplog(" host: %s", host); |
407 | yplog(" source domain: %s", srcdomain); |
408 | yplog(" transid: %s", tid); |
409 | yplog(" prog: %s", prog); |
410 | yplog(" port: %s", port); |
411 | yplog(" ipadd: %s", ipadd); |
412 | yplog(" map: %s", map); |
413 | |
414 | if (fflag != 0) { |
415 | ordernum = 0; |
416 | } else { |
417 | status = get_local_ordernum(domain, map, &ordernum); |
418 | } |
419 | } |
420 | |
421 | if (status > 0) { |
422 | yplog("Get Master"); |
423 | |
424 | if (host == NULL((void *)0)) { |
425 | if (srcdomain == NULL((void *)0)) { |
426 | status = yp_master(domain, map, &host); |
427 | } else { |
428 | status = yp_master(srcdomain, map, &host); |
429 | } |
430 | if (status == 0) { |
431 | status = YPPUSH_SUCC; |
432 | } else { |
433 | status = -status; |
434 | } |
435 | } |
436 | } |
437 | |
438 | /* XXX this is raceable if portmap has holes! */ |
439 | if (status > 0) { |
440 | yplog("Check for reserved port on host: %s", host); |
441 | |
442 | srvport = getrpcport(host, YPPROG((u_long)100004), YPVERS((u_long)2), IPPROTO_TCP6); |
443 | if (srvport >= IPPORT_RESERVED1024) |
444 | status = YPPUSH_REFUSED; |
445 | } |
446 | |
447 | if (status > 0) { |
448 | yplog("Connect host: %s", host); |
449 | |
450 | client = yp_bind_host(host, YPPROG((u_long)100004), YPVERS((u_long)2), 0, 1); |
451 | |
452 | status = get_remote_ordernum(client, domain, map, |
453 | ordernum, &new_ordernum); |
454 | } |
455 | |
456 | if (status == YPPUSH_SUCC) { |
457 | char tmpmapname[PATH_MAX1024]; |
458 | int fd; |
459 | |
460 | /* Create temporary db */ |
461 | snprintf(tmpmapname, sizeof tmpmapname, |
462 | "%s/%s/ypdbXXXXXXXXXX", YP_DB_PATH"/var/yp", domain); |
463 | fd = mkstemp(tmpmapname); |
464 | if (fd == -1) |
465 | status = YPPUSH_DBM; |
466 | else |
467 | close(fd); |
468 | |
469 | if (status > 0) { |
470 | db = create_db(domain, map, tmpmapname); |
471 | if (db == NULL((void *)0)) |
472 | status = YPPUSH_DBM; |
473 | } |
474 | |
475 | /* Add ORDER */ |
476 | if (status > 0) |
477 | status = add_order(db, new_ordernum); |
478 | |
479 | /* Add MASTER */ |
480 | if (status > 0) |
481 | status = add_master(client, domain, map, db); |
482 | |
483 | /* Add INTERDOMAIN */ |
484 | if (status > 0) |
485 | status = add_interdomain(client, domain, map, db); |
486 | |
487 | /* Add SECURE */ |
488 | if (status > 0) |
489 | status = add_secure(client, domain, map, db); |
490 | |
491 | if (status > 0) { |
492 | callback.foreach = ypxfr_foreach; |
493 | status = get_map(client, domain, map, &callback); |
494 | } |
495 | |
496 | /* Close db */ |
497 | if (db != NULL((void *)0)) |
498 | ypdb_close(db); |
499 | |
500 | /* Rename db */ |
501 | if (status > 0) { |
502 | status = install_db(domain, map, tmpmapname); |
503 | } else { |
504 | unlink(tmpmapname); |
505 | status = YPPUSH_SUCC; |
506 | } |
507 | } |
508 | |
509 | xfr_status = status; |
510 | |
511 | if (client != NULL((void *)0)) |
512 | clnt_destroy(client)((*(client)->cl_ops->cl_destroy)(client)); |
513 | |
514 | /* YP_CLEAR */ |
515 | |
516 | if (!cflag) { |
517 | client = yp_bind_local(YPPROG((u_long)100004), YPVERS((u_long)2)); |
518 | status = send_clear(client); |
519 | clnt_destroy(client)((*(client)->cl_ops->cl_destroy)(client)); |
520 | } |
521 | |
522 | if (Cflag > 0) { |
523 | /* Send Response */ |
524 | client = yp_bind_host(ipadd, atoi(prog), 1, atoi(port), 0); |
525 | status = send_reply(client, xfr_status, atoi(tid)); |
526 | clnt_destroy(client)((*(client)->cl_ops->cl_destroy)(client)); |
527 | } |
528 | return (0); |
529 | } |