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
dbm_deletefile(file)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
xdr_pages(xdrs)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
xdr_dirs(xdrs)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
xdr_myfyl(xdrs,objp)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
ypxfrd_getdbm(tempmap,master,domain,map)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