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