xref: /illumos-gate/usr/src/cmd/ypcmd/ypxfrd_client.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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 (c) 1986-1999 by Sun Microsystems, Inc.
24  * All rights reserved.
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
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 xdr_myfyl(xdrs, objp)
177 	XDR *xdrs;
178 	int *objp;
179 {
180 	if (!xdr_answer(xdrs, (answer *)objp))
181 		return (FALSE);
182 
183 	if (*objp != OK)
184 		return (TRUE);
185 
186 	if (!xdr_pages(xdrs, NULL))
187 		return (FALSE);
188 
189 	if (!xdr_dirs(xdrs, NULL))
190 		return (FALSE);
191 
192 	return (TRUE);
193 }
194 
195 ypxfrd_getdbm(tempmap, master, domain, map)
196 	char *tempmap;
197 	char *master;
198 	char *domain;
199 	char *map;
200 {
201 	hosereq	rmap;
202 	CLIENT	*clnt;
203 	int		res;
204 	int	recvsiz = 24 * 1024;
205 	struct netconfig *nconf;
206 	int fd;
207 	struct netbuf *svcaddr;
208 	struct t_bind *tbind;
209 	char *netid[] = { "tcp6", "tcp" };
210 	int i, lastnetid = (sizeof (netid)/sizeof (netid[0])) - 1;
211 
212 	for (i = 0; i <= lastnetid; i++) {
213 		if ((nconf = getnetconfigent(netid[i])) == NULL) {
214 			if (i != lastnetid)
215 				continue;
216 			logprintf("ypxfr: tcp transport not supported\n");
217 			return (-1);
218 		}
219 		if ((fd = t_open(nconf->nc_device, O_RDWR, NULL)) == -1) {
220 			freenetconfigent(nconf);
221 			if (i != lastnetid)
222 				continue;
223 			logprintf("ypxfr: TLI problems\n");
224 			return (-1);
225 		}
226 		if (secure_map == TRUE) {
227 			if (netdir_options(nconf, ND_SET_RESERVEDPORT, fd,
228 					NULL) == -1) {
229 				(void) close(fd);
230 				freenetconfigent(nconf);
231 				if (i != lastnetid)
232 					continue;
233 				logprintf(
234 			"ypxfr: cannot bind to reserved port for %s\n%s\n",
235 					netid[i], netdir_sperror(""));
236 				return (-1);
237 			}
238 		}
239 
240 		if ((tbind = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR)) ==
241 			NULL) {
242 			(void) close(fd);
243 			freenetconfigent(nconf);
244 			if (i != lastnetid)
245 				continue;
246 			logprintf("ypxfr: TLI problems\n");
247 			return (-1);
248 		}
249 		svcaddr = &(tbind->addr);
250 		if (rpcb_getaddr(YPXFRD, 1, nconf, svcaddr, master)
251 			== FALSE) {
252 			(void) t_free((char *)tbind, T_BIND);
253 			(void) close(fd);
254 			freenetconfigent(nconf);
255 			if (i != lastnetid)
256 				continue;
257 			logprintf("ypxfr: couldnot get %s address\n", master);
258 			return (-1);
259 		}
260 		if ((clnt = __nis_clnt_create(fd, nconf, 0, svcaddr, 0,
261 						YPXFRD, 1, recvsiz, 0)) == 0) {
262 			(void) t_free((char *)tbind, T_BIND);
263 			(void) close(fd);
264 			freenetconfigent(nconf);
265 			if (i != lastnetid)
266 				continue;
267 			clnt_pcreateerror(
268 				"ypxfr (get_map) - TCP channel create failure");
269 			return (-1);
270 		}
271 		(void) t_free((char *)tbind, T_BIND);
272 		break;
273 	}
274 	(void) CLNT_CONTROL(clnt, CLSET_FD_CLOSE, (char *)NULL);
275 
276 	rmap.map = map;
277 	rmap.domain = domain;
278 	memset((char *) &res, 0, sizeof (res));
279 	db = dbm_open(tempmap, O_RDWR + O_CREAT + O_TRUNC, 0777);
280 	if (db == NULL) {
281 		logprintf("dbm_open failed %s\n", tempmap);
282 		perror(tempmap);
283 		return (-2);
284 	}
285 
286 	if (clnt_call(clnt, getdbm, xdr_hosereq, (char *)&rmap, xdr_myfyl,
287 		(char *)&res, TIMEOUT) != RPC_SUCCESS) {
288 		logprintf("clnt call to ypxfrd getdbm failed.\n");
289 		clnt_perror(clnt, "getdbm");
290 		dbm_deletefile(tempmap);
291 		return (-3);
292 	}
293 	if (res != OK) {
294 		logprintf("clnt call %s ypxfrd getdbm NOTOK %s %s code=%d\n",
295 			master, domain, map, res);
296 		dbm_deletefile(tempmap);
297 		return (-4);
298 	}
299 	return (0);
300 
301 }
302