GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ypserv/yppush/yppush.c Lines: 0 145 0.0 %
Date: 2017-11-13 Branches: 0 65 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: yppush.c,v 1.31 2015/01/16 06:40:23 deraadt Exp $ */
2
3
/*
4
 * Copyright (c) 1995 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/resource.h>
32
#include <sys/wait.h>
33
34
#include <stdio.h>
35
#include <unistd.h>
36
#include <stdlib.h>
37
#include <signal.h>
38
#include <ctype.h>
39
40
#include <rpc/rpc.h>
41
#include <rpc/xdr.h>
42
#include <rpcsvc/yp.h>
43
#include <rpcsvc/ypclnt.h>
44
45
#include <netdb.h>
46
#include <string.h>
47
#include <errno.h>
48
#include <fcntl.h>
49
50
#include "yplib_host.h"
51
#include "ypdef.h"
52
#include "ypdb.h"
53
54
int  Verbose = 0;
55
char Domain[HOST_NAME_MAX+1], Map[255];
56
u_int32_t OrderNum;
57
char *master;
58
59
extern void yppush_xfrrespprog_1(struct svc_req *request, SVCXPRT *xprt);
60
extern bool_t xdr_ypreq_xfr(XDR *, struct ypreq_xfr *);
61
62
static void
63
usage(void)
64
{
65
	fprintf(stderr,
66
	    "usage: yppush [-v] [-d domainname] [-h hostname] mapname\n");
67
	exit(1);
68
}
69
70
static void
71
my_svc_run(void)
72
{
73
	struct pollfd *pfd = NULL, *newp;
74
	int nready, saved_max_pollfd = 0;
75
76
	for (;;) {
77
		if (svc_max_pollfd > saved_max_pollfd) {
78
			newp = reallocarray(pfd, svc_max_pollfd, sizeof(*pfd));
79
			if (newp == NULL) {
80
				free(pfd);
81
				perror("svc_run: - realloc failed");
82
				return;
83
			}
84
			pfd = newp;
85
			saved_max_pollfd = svc_max_pollfd;
86
		}
87
		memcpy(pfd, svc_pollfd, sizeof(*pfd) * svc_max_pollfd);
88
89
		nready = poll(pfd, svc_max_pollfd, 60 * 1000);
90
		switch (nready) {
91
		case -1:
92
			if (errno == EINTR)
93
				continue;
94
			perror("yppush: my_svc_run: poll failed");
95
			free(pfd);
96
			return;
97
		case 0:
98
			fprintf(stderr, "yppush: Callback timed out.\n");
99
			exit(0);
100
		default:
101
			svc_getreq_poll(pfd, nready);
102
			break;
103
		}
104
	}
105
}
106
107
static void
108
req_xfr(pid_t pid, u_int prog, SVCXPRT *transp, char *host, CLIENT *client)
109
{
110
	struct ypreq_xfr request;
111
	struct timeval tv;
112
113
	tv.tv_sec = 0;
114
	tv.tv_usec = 0;
115
116
	request.map_parms.domain=(char *)&Domain;
117
	request.map_parms.map=(char *)&Map;
118
	request.map_parms.peer=master;
119
	request.map_parms.ordernum=OrderNum;
120
	request.transid=(u_int)pid;
121
	request.prog=prog;
122
	request.port=transp->xp_port;
123
124
	if (Verbose)
125
		printf("%d: %s(%u@%s) -> %s@%s\n",
126
		    request.transid, request.map_parms.map,
127
		    request.map_parms.ordernum, host,
128
		    request.map_parms.peer, request.map_parms.domain);
129
	switch (clnt_call(client, YPPROC_XFR, xdr_ypreq_xfr, &request,
130
	    xdr_void, NULL, tv)) {
131
	case RPC_SUCCESS:
132
	case RPC_TIMEDOUT:
133
		break;
134
	default:
135
		clnt_perror(client, "yppush: Cannot call YPPROC_XFR");
136
		kill(pid, SIGTERM);
137
		break;
138
	}
139
}
140
141
static void
142
push(int inlen, char *indata)
143
{
144
	char host[HOST_NAME_MAX+1];
145
	CLIENT *client;
146
	SVCXPRT *transp;
147
	int sock = RPC_ANYSOCK, status;
148
	u_int prog;
149
	bool_t sts = 0;
150
	pid_t pid;
151
	struct rusage res;
152
153
	snprintf(host, sizeof host, "%*.*s", inlen, inlen, indata);
154
155
	client = clnt_create(host, YPPROG, YPVERS, "tcp");
156
	if (client == NULL) {
157
		if (Verbose)
158
			fprintf(stderr, "Target Host: %s\n", host);
159
		clnt_pcreateerror("yppush: Cannot create client");
160
		return;
161
	}
162
163
	transp = svcudp_create(sock);
164
	if (transp == NULL) {
165
		fprintf(stderr, "yppush: Cannot create callback transport.\n");
166
		return;
167
	}
168
	if (transp->xp_port >= IPPORT_RESERVED) {
169
		SVC_DESTROY(transp);
170
		fprintf(stderr, "yppush: Cannot allocate reserved port.\n");
171
		return;
172
	}
173
174
	for (prog=0x40000000; prog<0x5fffffff; prog++) {
175
		if ((sts = svc_register(transp, prog, 1,
176
		    yppush_xfrrespprog_1, IPPROTO_UDP)))
177
			break;
178
	}
179
180
	if (!sts) {
181
		fprintf(stderr, "yppush: Cannot register callback.\n");
182
		return;
183
	}
184
185
	switch (pid=fork()) {
186
	case -1:
187
		fprintf(stderr, "yppush: Cannot fork.\n");
188
		exit(1);
189
	case 0:
190
		my_svc_run();
191
		exit(0);
192
	default:
193
		close(transp->xp_sock);
194
		transp->xp_sock = -1;
195
		req_xfr(pid, prog, transp, host, client);
196
		wait4(pid, &status, 0, &res);
197
		svc_unregister(prog, 1);
198
		if (client != NULL)
199
			clnt_destroy(client);
200
		/* XXX transp leak? */
201
	}
202
203
}
204
205
static int
206
pushit(u_long instatus, char *inkey, int inkeylen, char *inval, int invallen,
207
    void *indata)
208
{
209
	if (instatus != YP_TRUE)
210
		return instatus;
211
	push(invallen, inval);
212
	return 0;
213
}
214
215
int
216
main(int argc, char *argv[])
217
{
218
	struct ypall_callback ypcb;
219
	extern char *optarg;
220
	extern int optind;
221
	char	*domain, *map, *hostname;
222
	int c, r, i;
223
	char *ypmap = "ypservers";
224
	CLIENT *client;
225
	static char map_path[PATH_MAX];
226
	struct stat finfo;
227
	DBM *yp_databas;
228
	char order_key[YP_LAST_LEN] = YP_LAST_KEY;
229
	datum o;
230
231
	yp_get_default_domain(&domain);
232
	hostname = NULL;
233
	while ((c=getopt(argc, argv, "d:h:v")) != -1)
234
		switch (c) {
235
		case 'd':
236
			domain = optarg;
237
			break;
238
		case 'h':
239
			hostname = optarg;
240
			break;
241
		case 'v':
242
			Verbose = 1;
243
			break;
244
		default:
245
			usage();
246
			/*NOTREACHED*/
247
		}
248
249
	if (optind + 1 != argc )
250
		usage();
251
252
	map = argv[optind];
253
254
	strncpy(Domain, domain, sizeof(Domain)-1);
255
	Domain[sizeof(Domain)-1] = '\0';
256
	strncpy(Map, map, sizeof(Map)-1);
257
	Map[sizeof(Map)-1] = '\0';
258
259
	/* Check domain */
260
	snprintf(map_path, sizeof map_path, "%s/%s", YP_DB_PATH, domain);
261
	if (!((stat(map_path, &finfo) == 0) && S_ISDIR(finfo.st_mode))) {
262
		fprintf(stderr, "yppush: Map does not exist.\n");
263
		exit(1);
264
	}
265
266
	/* Check map */
267
	snprintf(map_path, sizeof map_path, "%s/%s/%s%s",
268
	    YP_DB_PATH, domain, Map, YPDB_SUFFIX);
269
	if (!(stat(map_path, &finfo) == 0)) {
270
		fprintf(stderr, "yppush: Map does not exist.\n");
271
		exit(1);
272
	}
273
274
	snprintf(map_path, sizeof map_path, "%s/%s/%s",
275
	    YP_DB_PATH, domain, Map);
276
	yp_databas = ypdb_open(map_path, 0, O_RDONLY);
277
	OrderNum=0xffffffff;
278
	if (yp_databas == 0) {
279
		fprintf(stderr, "yppush: %s%s: Cannot open database\n",
280
		    map_path, YPDB_SUFFIX);
281
	} else {
282
		o.dptr = (char *) &order_key;
283
		o.dsize = YP_LAST_LEN;
284
		o = ypdb_fetch(yp_databas, o);
285
		if (o.dptr == NULL) {
286
			fprintf(stderr,
287
			    "yppush: %s: Cannot determine order number\n",
288
			    Map);
289
		} else {
290
			OrderNum=0;
291
			for (i=0; i<o.dsize-1; i++) {
292
				if (!isdigit((unsigned char)o.dptr[i]))
293
					OrderNum=0xffffffff;
294
			}
295
			if (OrderNum != 0) {
296
				fprintf(stderr,
297
				    "yppush: %s: Invalid order number '%s'\n",
298
				    Map, o.dptr);
299
			} else {
300
				OrderNum = atoi(o.dptr);
301
			}
302
		}
303
	}
304
305
	yp_bind(Domain);
306
307
	r = yp_master(Domain, ypmap, &master);
308
	if (r != 0) {
309
		fprintf(stderr, "yppush: could not get ypservers map\n");
310
		exit(1);
311
	}
312
313
	if (hostname != NULL) {
314
		push(strlen(hostname), hostname);
315
	} else {
316
		if (Verbose) {
317
			printf("Contacting master for ypservers (%s).\n",
318
			    master);
319
		}
320
321
		client = yp_bind_host(master, YPPROG, YPVERS, 0, 1);
322
323
		ypcb.foreach = pushit;
324
		ypcb.data = NULL;
325
		r = yp_all_host(client, Domain, ypmap, &ypcb);
326
	}
327
328
	exit(0);
329
}