/** * @brief Describe a GPFS striping pattern * * At present, we support a files based layout only. The CRUSH * striping pattern is a-periodic * * @param[in] export_pub Public export handle * @param[out] da_addr_body Stream we write the result to * @param[in] type Type of layout that gave the device * @param[in] deviceid The device to look up * * @return Valid error codes in RFC 5661, p. 365. */ nfsstat4 getdeviceinfo(struct fsal_module *fsal_hdl, XDR *da_addr_body, const layouttype4 type, const struct pnfs_deviceid *deviceid) { struct deviceinfo_arg darg; /* The position before any bytes are sent to the stream */ size_t da_beginning; size_t ds_buffer; /* The total length of the XDR-encoded da_addr_body */ size_t da_length; int rc; int errsv; darg.mountdirfd = deviceid->device_id4; darg.type = LAYOUT4_NFSV4_1_FILES; darg.devid.devid = deviceid->devid; darg.devid.device_id1 = deviceid->device_id1; darg.devid.device_id2 = deviceid->device_id2; darg.devid.device_id4 = deviceid->device_id4; darg.devid.devid = deviceid->devid; da_beginning = xdr_getpos(da_addr_body); darg.xdr.p = xdr_inline(da_addr_body, 0); ds_buffer = da_addr_body->x_handy; /* xdr_size_inline(da_addr_body); */ darg.xdr.end = (int *)(darg.xdr.p + ((ds_buffer - da_beginning) / BYTES_PER_XDR_UNIT)); LogDebug(COMPONENT_PNFS, "getdeviceinfo p %p end %p da_length %zu ds_buffer %zu seq %d fd %d fsid 0x%" PRIx64, darg.xdr.p, darg.xdr.end, da_beginning, ds_buffer, deviceid->device_id2, deviceid->device_id4, deviceid->devid); rc = gpfs_ganesha(OPENHANDLE_GET_DEVICEINFO, &darg); errsv = errno; if (rc < 0) { LogDebug(COMPONENT_PNFS, "getdeviceinfo rc %d", rc); if (errsv == EUNATCH) LogFatal(COMPONENT_PNFS, "GPFS Returned EUNATCH"); return NFS4ERR_RESOURCE; } (void)xdr_inline(da_addr_body, rc); da_length = xdr_getpos(da_addr_body) - da_beginning; LogDebug(COMPONENT_PNFS, "getdeviceinfo rc %d da_length %zd", rc, da_length); return NFS4_OK; }
static bool_t apply_buf(bool_t (*fn)(), caddr_t in, u_int size) { bool_t result; char out[BUFSIZ]; XDR xin, xout; xdrbuf_create(&xin, 0, XDR_ENCODE); /* Inline to force grow. */ if (!fn(&xin, in) || !xdr_inline(&xin, 2 * BUFSIZ)) { xdr_destroy(&xin); return FALSE; } xdrmem_create(&xout, xin.x_base, xdr_getpos(&xin), XDR_DECODE); result = fn(&xout, out) && 0 == memcmp(in, out, size); xdr_destroy(&xin); return result; }
/* * 2. Marshal */ static bool_t authdes_marshal(AUTH *auth, XDR *xdrs) { /* LINTED pointer alignment */ struct ad_private *ad = AUTH_PRIVATE(auth); struct authdes_cred *cred = &ad->ad_cred; struct authdes_verf *verf = &ad->ad_verf; des_block cryptbuf[2]; des_block ivec; int status; int len; rpc_inline_t *ixdr; /* * Figure out the "time", accounting for any time difference * with the server if necessary. */ (void)gettimeofday(&ad->ad_timestamp, NULL); ad->ad_timestamp.tv_sec += ad->ad_timediff.tv_sec; ad->ad_timestamp.tv_usec += ad->ad_timediff.tv_usec; while (ad->ad_timestamp.tv_usec >= USEC_PER_SEC) { ad->ad_timestamp.tv_usec -= USEC_PER_SEC; ad->ad_timestamp.tv_sec++; } /* * XDR the timestamp and possibly some other things, then * encrypt them. */ ixdr = (rpc_inline_t *)cryptbuf; IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_sec); IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_usec); if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { IXDR_PUT_U_INT32(ixdr, ad->ad_window); IXDR_PUT_U_INT32(ixdr, ad->ad_window - 1); ivec.key.high = ivec.key.low = 0; status = cbc_crypt((char *)&auth->ah_key, (char *)cryptbuf, (u_int) 2 * sizeof (des_block), DES_ENCRYPT | DES_HW, (char *)&ivec); } else { status = ecb_crypt((char *)&auth->ah_key, (char *)cryptbuf, (u_int) sizeof (des_block), DES_ENCRYPT | DES_HW); } if (DES_FAILED(status)) { syslog(LOG_ERR, "authdes_marshal: DES encryption failure"); return (FALSE); } ad->ad_verf.adv_xtimestamp = cryptbuf[0]; if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high; ad->ad_verf.adv_winverf = cryptbuf[1].key.low; } else { ad->ad_cred.adc_nickname = ad->ad_nickname; ad->ad_verf.adv_winverf = 0; } /* * Serialize the credential and verifier into opaque * authentication data. */ if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { len = ((1 + 1 + 2 + 1)*BYTES_PER_XDR_UNIT + ad->ad_fullnamelen); } else { len = (1 + 1)*BYTES_PER_XDR_UNIT; } if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) { IXDR_PUT_INT32(ixdr, AUTH_DES); IXDR_PUT_INT32(ixdr, len); } else { ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_cred.oa_flavor)); ATTEMPT(xdr_putint32(xdrs, &len)); } ATTEMPT(xdr_authdes_cred(xdrs, cred)); len = (2 + 1)*BYTES_PER_XDR_UNIT; if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) { IXDR_PUT_INT32(ixdr, AUTH_DES); IXDR_PUT_INT32(ixdr, len); } else { ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_verf.oa_flavor)); ATTEMPT(xdr_putint32(xdrs, &len)); } ATTEMPT(xdr_authdes_verf(xdrs, verf)); return (TRUE); }
/* * 2. Marshal */ static bool_t authdes_marshal (AUTH *auth, XDR *xdrs) { struct ad_private *ad = AUTH_PRIVATE (auth); struct authdes_cred *cred = &ad->ad_cred; struct authdes_verf *verf = &ad->ad_verf; des_block cryptbuf[2]; des_block ivec; int status; int len; register int32_t *ixdr; struct timeval tval; /* * Figure out the "time", accounting for any time difference * with the server if necessary. */ __gettimeofday (&tval, (struct timezone *) NULL); ad->ad_timestamp.tv_sec = tval.tv_sec + ad->ad_timediff.tv_sec; ad->ad_timestamp.tv_usec = tval.tv_usec + ad->ad_timediff.tv_usec; if (ad->ad_timestamp.tv_usec >= MILLION) { ad->ad_timestamp.tv_usec -= MILLION; ad->ad_timestamp.tv_sec += 1; } /* * XDR the timestamp and possibly some other things, then * encrypt them. * XXX We have a real Year 2038 problem here. */ ixdr = (int32_t *) cryptbuf; IXDR_PUT_INT32 (ixdr, ad->ad_timestamp.tv_sec); IXDR_PUT_INT32 (ixdr, ad->ad_timestamp.tv_usec); if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { IXDR_PUT_U_INT32 (ixdr, ad->ad_window); IXDR_PUT_U_INT32 (ixdr, ad->ad_window - 1); ivec.key.high = ivec.key.low = 0; status = cbc_crypt ((char *) &auth->ah_key, (char *) cryptbuf, 2 * sizeof (des_block), DES_ENCRYPT | DES_HW, (char *) &ivec); } else status = ecb_crypt ((char *) &auth->ah_key, (char *) cryptbuf, sizeof (des_block), DES_ENCRYPT | DES_HW); if (DES_FAILED (status)) { debug ("authdes_marshal: DES encryption failure"); return FALSE; } ad->ad_verf.adv_xtimestamp = cryptbuf[0]; if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high; ad->ad_verf.adv_winverf = cryptbuf[1].key.low; } else { ad->ad_cred.adc_nickname = ad->ad_nickname; ad->ad_verf.adv_winverf = 0; } /* * Serialize the credential and verifier into opaque * authentication data. */ if (ad->ad_cred.adc_namekind == ADN_FULLNAME) len = ((1 + 1 + 2 + 1) * BYTES_PER_XDR_UNIT + ad->ad_fullnamelen); else len = (1 + 1) * BYTES_PER_XDR_UNIT; if ((ixdr = xdr_inline (xdrs, 2 * BYTES_PER_XDR_UNIT)) != NULL) { IXDR_PUT_INT32 (ixdr, AUTH_DES); IXDR_PUT_U_INT32 (ixdr, len); } else { ATTEMPT (xdr_putint32 (xdrs, &auth->ah_cred.oa_flavor)); ATTEMPT (xdr_putint32 (xdrs, &len)); } ATTEMPT (xdr_authdes_cred (xdrs, cred)); len = (2 + 1) * BYTES_PER_XDR_UNIT; if ((ixdr = xdr_inline (xdrs, 2 * BYTES_PER_XDR_UNIT)) != NULL) { IXDR_PUT_INT32 (ixdr, AUTH_DES); IXDR_PUT_U_INT32 (ixdr, len); } else { ATTEMPT (xdr_putint32 (xdrs, &auth->ah_verf.oa_flavor)); ATTEMPT (xdr_putint32 (xdrs, &len)); } ATTEMPT (xdr_authdes_verf (xdrs, verf)); return TRUE; }