int rpc_nfs2_statfs_async(struct rpc_context *rpc, rpc_cb cb, struct STATFS2args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_STATFS, cb, private_data, (zdrproc_t)zdr_STATFS2res, sizeof(STATFS2res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/STATFS call"); return -1; } if (zdr_STATFS2args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode STATFS2args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/STATFS call"); rpc_free_pdu(rpc, pdu); return -3; } return 0; }
int rpc_nfs3_remove_async(struct rpc_context *rpc, rpc_cb cb, struct REMOVE3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_REMOVE, cb, private_data, (zdrproc_t)zdr_REMOVE3res, sizeof(REMOVE3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/REMOVE call"); return -1; } if (zdr_REMOVE3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode REMOVE3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/REMOVE call"); rpc_free_pdu(rpc, pdu); return -3; } return 0; }
int rpc_nfsacl_setacl_async(struct rpc_context *rpc, rpc_cb cb, struct SETACL3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFSACL_PROGRAM, NFSACL_V3, NFSACL3_SETACL, cb, private_data, (zdrproc_t)zdr_SETACL3res, sizeof(SETACL3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfsacl/setacl call"); return -1; } if (zdr_SETACL3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode SETACL3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfsacl/setacl call"); rpc_free_pdu(rpc, pdu); return -2; } return 0; }
int rpc_nfs2_write_async(struct rpc_context *rpc, rpc_cb cb, struct WRITE2args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu2(rpc, NFS_PROGRAM, NFS_V2, NFS2_WRITE, cb, private_data, (zdrproc_t)zdr_WRITE2res, sizeof(WRITE2res), args->totalcount); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/WRITE call"); return -1; } if (zdr_WRITE2args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode WRITE2args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/WRITE call"); rpc_free_pdu(rpc, pdu); return -3; } return 0; }
int rpc_nlm4_cancel_async(struct rpc_context *rpc, rpc_cb cb, struct NLM4_CANCargs *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NLM_PROGRAM, NLM_V4, NLM4_CANCEL, cb, private_data, (xdrproc_t)xdr_NLM4_CANCres, sizeof(NLM4_CANCres)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nlm/cancel call"); return -1; } if (xdr_NLM4_CANCargs(&pdu->xdr, args) == 0) { rpc_set_error(rpc, "XDR error: Failed to encode NLM4_CANCargs"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nlm/cancel call"); rpc_free_pdu(rpc, pdu); return -1; } return 0; }
int rpc_nlm4_unlock_async(struct rpc_context *rpc, rpc_cb cb, struct NLM4_UNLOCKargs *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NLM_PROGRAM, NLM_V4, NLM4_UNLOCK, cb, private_data, (zdrproc_t)zdr_NLM4_UNLOCKres, sizeof(NLM4_UNLOCKres)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nlm/unlock call"); return -1; } if (zdr_NLM4_UNLOCKargs(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode NLM4_UNLOCKargs"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nlm/unlock call"); rpc_free_pdu(rpc, pdu); return -1; } return 0; }
int rpc_rquota1_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, RQUOTA_PROGRAM, RQUOTA_V1, RQUOTA1_NULL, cb, private_data, (xdrproc_t)xdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for rquota1/null call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for rquota1/null call"); rpc_free_pdu(rpc, pdu); return -2; } return 0; }
int rpc_nfsacl_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFSACL_PROGRAM, NFSACL_V3, NFSACL3_NULL, cb, private_data, (xdrproc_t)xdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfsacl/null call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfsacl/null call"); rpc_free_pdu(rpc, pdu); return -2; } return 0; }
int rpc_pmap_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V2, PMAP_NULL, cb, private_data, (xdrproc_t)xdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for portmap/null call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for portmap/null call"); rpc_free_pdu(rpc, pdu); return -1; } return 0; }
int rpc_nlm4_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NLM_PROGRAM, NLM_V4, NLM4_NULL, cb, private_data, (zdrproc_t)zdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nlm/null call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nlm/null call"); rpc_free_pdu(rpc, pdu); return -1; } return 0; }
int rpc_process_pdu(struct rpc_context *rpc, char *buf, int size) { struct rpc_pdu *pdu, *prev_pdu; struct rpc_queue *q; ZDR zdr; int pos, recordmarker = 0; unsigned int hash; uint32_t xid; char *reasbuf = NULL; assert(rpc->magic == RPC_CONTEXT_MAGIC); memset(&zdr, 0, sizeof(ZDR)); zdrmem_create(&zdr, buf, size, ZDR_DECODE); if (rpc->is_udp == 0) { if (zdr_int(&zdr, &recordmarker) == 0) { rpc_set_error(rpc, "zdr_int reading recordmarker failed"); zdr_destroy(&zdr); return -1; } if (!(recordmarker&0x80000000)) { zdr_destroy(&zdr); if (rpc_add_fragment(rpc, buf+4, size-4) != 0) { rpc_set_error(rpc, "Failed to queue fragment for reassembly."); return -1; } return 0; } } /* reassembly */ if (recordmarker != 0 && rpc->fragments != NULL) { struct rpc_fragment *fragment; uint32_t total = size - 4; char *ptr; zdr_destroy(&zdr); for (fragment = rpc->fragments; fragment; fragment = fragment->next) { total += fragment->size; if (total < fragment->size) { rpc_set_error(rpc, "Fragments too large"); rpc_free_all_fragments(rpc); return -1; } } reasbuf = malloc(total); if (reasbuf == NULL) { rpc_set_error(rpc, "Failed to reassemble PDU"); rpc_free_all_fragments(rpc); return -1; } ptr = reasbuf; for (fragment = rpc->fragments; fragment; fragment = fragment->next) { memcpy(ptr, fragment->data, fragment->size); ptr += fragment->size; } memcpy(ptr, buf + 4, size - 4); zdrmem_create(&zdr, reasbuf, total, ZDR_DECODE); rpc_free_all_fragments(rpc); } if (rpc->is_server_context) { int ret; ret = rpc_process_call(rpc, &zdr); zdr_destroy(&zdr); if (reasbuf != NULL) { free(reasbuf); } return ret; } pos = zdr_getpos(&zdr); if (zdr_int(&zdr, (int *)&xid) == 0) { rpc_set_error(rpc, "zdr_int reading xid failed"); zdr_destroy(&zdr); if (reasbuf != NULL) { free(reasbuf); } return -1; } zdr_setpos(&zdr, pos); /* Look up the transaction in a hash table of our requests */ hash = rpc_hash_xid(xid); q = &rpc->waitpdu[hash]; /* Follow the hash chain. Linear traverse singly-linked list, * but track previous entry for optimised removal */ prev_pdu = NULL; for (pdu=q->head; pdu; pdu=pdu->next) { if (pdu->xid != xid) { prev_pdu = pdu; continue; } if (rpc->is_udp == 0 || rpc->is_broadcast == 0) { /* Singly-linked but we track head and tail */ if (pdu == q->head) q->head = pdu->next; if (pdu == q->tail) q->tail = prev_pdu; if (prev_pdu != NULL) prev_pdu->next = pdu->next; rpc->waitpdu_len--; } if (rpc_process_reply(rpc, pdu, &zdr) != 0) { rpc_set_error(rpc, "rpc_procdess_reply failed"); } zdr_destroy(&zdr); if (rpc->is_udp == 0 || rpc->is_broadcast == 0) { rpc_free_pdu(rpc, pdu); } if (reasbuf != NULL) { free(reasbuf); } return 0; } zdr_destroy(&zdr); if (reasbuf != NULL) { free(reasbuf); } return 0; }