xref: /illumos-gate/usr/src/cmd/ypcmd/ypxfrd_client.c (revision 2bbdd445a21f9d61f4a0ca0faf05d5ceb2bd91f3)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <unistd.h>
30 #include <netconfig.h>
31 #include <netdir.h>
32 #include <rpc/rpc.h>
33 #include <sys/file.h>
34 #include <sys/param.h>
35 #include "ypxfrd.h"
36 #include <ndbm.h>
37 #include <rpcsvc/yp_prot.h>
38 #include <rpcsvc/nis.h>
39 #include <strings.h>
40 
41 #include <sys/isa_defs.h>	/* for ENDIAN defines */
42 
43 #if defined(_LITTLE_ENDIAN)
44 #define	DOSWAB 1
45 #endif
46 
47 static struct timeval TIMEOUT = {25, 0};
48 static	DBM	*db;
49 
50 extern bool secure_map;
51 extern void logprintf(char *, ...);
52 
53 /* delete the dbm file with name file */
54 static int
55 dbm_deletefile(file)
56 char *file;
57 {
58 	char	pag1[MAXPATHLEN];
59 	char	dir1[MAXPATHLEN];
60 	int err;
61 	strcpy(pag1, file);
62 	strcat(pag1, ".pag");
63 	strcpy(dir1, file);
64 	strcat(dir1, ".dir");
65 	err = 0;
66 	if (unlink(pag1) < 0) {
67 		perror("unlinkpag");
68 		err = -1;
69 	}
70 
71 	if (unlink(dir1) < 0) {
72 		perror("unlinkdir");
73 		return (-1);
74 	}
75 	return (err);
76 }
77 
78 /* xdr just the .pag file of a dbm file */
79 static	bool_t
80 xdr_pages(xdrs)
81 	XDR	*xdrs;
82 {
83 	static struct pag res;
84 	struct pag	*PAG;
85 #ifdef DOSWAB
86 	short	*s;
87 	int		i;
88 #endif
89 	bool_t	more;
90 	bool_t	goteof;
91 	off64_t	where;
92 	int	true = 1;
93 
94 	goteof = FALSE;
95 	if (!xdr_pag(xdrs, &res))
96 		return (FALSE);
97 	PAG = &res;
98 	while (true) {
99 		if (PAG->status == OK) {
100 #ifdef DOSWAB
101 		s = (short *)PAG->pag_u.ok.blkdat;
102 		s[0] = ntohs(s[0]);
103 		for (i = 1; i <= s[0]; i++)
104 			s[i] = ntohs(s[i]);
105 #endif
106 			errno = 0;
107 			where = (((off64_t)PAG->pag_u.ok.blkno) * PBLKSIZ);
108 			(void) lseek64(db->dbm_pagf, where, L_SET);
109 			if (errno != 0) {
110 				perror("seek");
111 				exit(-1);
112 			}
113 			if (write(db->dbm_pagf,
114 				PAG->pag_u.ok.blkdat, PBLKSIZ) < 0) {
115 				perror("write");
116 				exit(-1);
117 			}
118 		} else if (PAG->status == GETDBM_ERROR) {
119 			(void) printf("clnt call getpag GETDBM_ERROR\n");
120 			exit(-1);
121 		} else if (PAG->status == GETDBM_EOF)
122 			goteof = TRUE;
123 		if (!xdr_bool(xdrs, &more))
124 			return (FALSE);
125 		if (more == FALSE)
126 			return (goteof);
127 		if (!xdr_pag(xdrs, &res))
128 			return (FALSE);
129 	}
130 	/*NOTREACHED*/
131 	return (TRUE);
132 }
133 /* xdr  just the .dir part of a dbm file */
134 static	bool_t
135 xdr_dirs(xdrs)
136 	XDR	*xdrs;
137 {
138 	static	struct dir res;
139 	struct	dir	*DIR;
140 	bool_t	more;
141 	bool_t	goteof;
142 	off64_t	where;
143 	int	true = 1;
144 
145 	goteof = FALSE;
146 	if (!xdr_dir(xdrs, &res))
147 		return (FALSE);
148 	DIR = &res;
149 	while (true) {
150 		if (DIR->status == OK) {
151 			errno = 0;
152 			where = (((off64_t)DIR->dir_u.ok.blkno) * DBLKSIZ);
153 			(void) lseek64(db->dbm_dirf, where, L_SET);
154 			if (errno != 0) {
155 				perror("seek");
156 				exit(-1);
157 			}
158 			if (write(db->dbm_dirf,
159 				DIR->dir_u.ok.blkdat, DBLKSIZ) < 0) {
160 				perror("write");
161 				exit(-1);
162 			}
163 		} else if (DIR->status == GETDBM_ERROR) {
164 			(void) printf("clnt call getdir GETDBM_ERROR\n");
165 			exit(-1);
166 		} else if (DIR->status == GETDBM_EOF)
167 			goteof = TRUE;
168 		if (!xdr_bool(xdrs, &more))
169 			return (FALSE);
170 		if (more == FALSE)
171 			return (goteof);
172 		if (!xdr_dir(xdrs, &res))
173 			return (FALSE);
174 	}
175 	/*NOTREACHED*/
176 	return (TRUE);
177 }
178 
179 /*
180  * xdr a dbm file from ypxfrd
181  * note that if the client or server do not support ndbm
182  * we may not use this optional protocol
183  */
184 
185 int
186 xdr_myfyl(xdrs, objp)
187 	XDR *xdrs;
188 	int *objp;
189 {
190 	if (!xdr_answer(xdrs, (answer *)objp))
191 		return (FALSE);
192 
193 	if (*objp != OK)
194 		return (TRUE);
195 
196 	if (!xdr_pages(xdrs))
197 		return (FALSE);
198 
199 	if (!xdr_dirs(xdrs))
200 		return (FALSE);
201 
202 	return (TRUE);
203 }
204 
205 int
206 ypxfrd_getdbm(tempmap, master, domain, map)
207 	char *tempmap;
208 	char *master;
209 	char *domain;
210 	char *map;
211 {
212 	hosereq	rmap;
213 	CLIENT	*clnt;
214 	int		res;
215 	int	recvsiz = 24 * 1024;
216 	struct netconfig *nconf;
217 	int fd;
218 	struct netbuf *svcaddr;
219 	struct t_bind *tbind;
220 	char *netid[] = { "tcp6", "tcp" };
221 	int i, lastnetid = (sizeof (netid)/sizeof (netid[0])) - 1;
222 
223 	for (i = 0; i <= lastnetid; i++) {
224 		if ((nconf = getnetconfigent(netid[i])) == NULL) {
225 			if (i != lastnetid)
226 				continue;
227 			logprintf("ypxfr: tcp transport not supported\n");
228 			return (-1);
229 		}
230 		if ((fd = t_open(nconf->nc_device, O_RDWR, NULL)) == -1) {
231 			freenetconfigent(nconf);
232 			if (i != lastnetid)
233 				continue;
234 			logprintf("ypxfr: TLI problems\n");
235 			return (-1);
236 		}
237 		if (secure_map == TRUE) {
238 			if (netdir_options(nconf, ND_SET_RESERVEDPORT, fd,
239 					NULL) == -1) {
240 				(void) close(fd);
241 				freenetconfigent(nconf);
242 				if (i != lastnetid)
243 					continue;
244 				logprintf(
245 			"ypxfr: cannot bind to reserved port for %s\n%s\n",
246 					netid[i], netdir_sperror());
247 				return (-1);
248 			}
249 		}
250 
251 		/* LINTED pointer alignment */
252 		if ((tbind = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR)) ==
253 			NULL) {
254 			(void) close(fd);
255 			freenetconfigent(nconf);
256 			if (i != lastnetid)
257 				continue;
258 			logprintf("ypxfr: TLI problems\n");
259 			return (-1);
260 		}
261 		svcaddr = &(tbind->addr);
262 		if (rpcb_getaddr(YPXFRD, 1, nconf, svcaddr, master)
263 			== FALSE) {
264 			(void) t_free((char *)tbind, T_BIND);
265 			(void) close(fd);
266 			freenetconfigent(nconf);
267 			if (i != lastnetid)
268 				continue;
269 			logprintf("ypxfr: couldnot get %s address\n", master);
270 			return (-1);
271 		}
272 		if ((clnt = __nis_clnt_create(fd, nconf, 0, svcaddr, 0,
273 						YPXFRD, 1, recvsiz, 0)) == 0) {
274 			(void) t_free((char *)tbind, T_BIND);
275 			(void) close(fd);
276 			freenetconfigent(nconf);
277 			if (i != lastnetid)
278 				continue;
279 			clnt_pcreateerror(
280 				"ypxfr (get_map) - TCP channel create failure");
281 			return (-1);
282 		}
283 		(void) t_free((char *)tbind, T_BIND);
284 		break;
285 	}
286 	(void) CLNT_CONTROL(clnt, CLSET_FD_CLOSE, (char *)NULL);
287 
288 	rmap.map = map;
289 	rmap.domain = domain;
290 	(void) memset((char *)&res, 0, sizeof (res));
291 	db = dbm_open(tempmap, O_RDWR + O_CREAT + O_TRUNC, 0777);
292 	if (db == NULL) {
293 		logprintf("dbm_open failed %s\n", tempmap);
294 		perror(tempmap);
295 		return (-2);
296 	}
297 
298 	if (clnt_call(clnt, getdbm, xdr_hosereq, (char *)&rmap, xdr_myfyl,
299 		(char *)&res, TIMEOUT) != RPC_SUCCESS) {
300 		logprintf("clnt call to ypxfrd getdbm failed.\n");
301 		clnt_perror(clnt, "getdbm");
302 		(void) dbm_deletefile(tempmap);
303 		return (-3);
304 	}
305 	if (res != OK) {
306 		logprintf("clnt call %s ypxfrd getdbm NOTOK %s %s code=%d\n",
307 			master, domain, map, res);
308 		(void) dbm_deletefile(tempmap);
309 		return (-4);
310 	}
311 	return (0);
312 
313 }
314