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