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