bool_t zdr_nsm_my_id (ZDR *zdrs, nsm_my_id *objp) { register int32_t *buf; buf = NULL; if (!zdr_string (zdrs, &objp->my_name, NSM_MAXSTRLEN)) return FALSE; if (!zdr_int (zdrs, &objp->my_prog)) return FALSE; if (!zdr_int (zdrs, &objp->my_vers)) return FALSE; if (!zdr_int (zdrs, &objp->my_proc)) return FALSE; return TRUE; }
bool_t zdr_NSM1_UNMONres (ZDR *zdrs, NSM1_UNMONres *objp) { register int32_t *buf; buf = NULL; if (!zdr_int (zdrs, &objp->state)) return FALSE; return TRUE; }
bool_t zdr_NSM1_STATres (ZDR *zdrs, NSM1_STATres *objp) { register int32_t *buf; buf = NULL; if (!zdr_nsmstat1 (zdrs, &objp->res)) return FALSE; if (!zdr_int (zdrs, &objp->state)) return FALSE; return TRUE; }
bool_t zdr_NSM1_NOTIFYargs (ZDR *zdrs, NSM1_NOTIFYargs *objp) { register int32_t *buf; buf = NULL; if (!zdr_string (zdrs, &objp->mon_name, NSM_MAXSTRLEN)) return FALSE; if (!zdr_int (zdrs, &objp->state)) return FALSE; return TRUE; }
int rpc_queue_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu) { int size, recordmarker; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (rpc->timeout > 0) { pdu->timeout = rpc_current_time() + rpc->timeout; #ifndef HAVE_CLOCK_GETTIME /* If we do not have GETTIME we fallback to time() which * has 1s granularity for its timestamps. * We thus need to bump the timeout by 1000ms * so that the PDU will timeout within 1.0 - 2.0 seconds. * Otherwise setting a 1s timeout would trigger within * 0.001 - 1.0s. */ pdu->timeout += 1000; #endif } else { pdu->timeout = 0; } size = zdr_getpos(&pdu->zdr); /* for udp we dont queue, we just send it straight away */ if (rpc->is_udp != 0) { unsigned int hash; // XXX add a rpc->udp_dest_sock_size and get rid of sys/socket.h and netinet/in.h if (sendto(rpc->fd, pdu->zdr.buf, size, MSG_DONTWAIT, (struct sockaddr *)&rpc->udp_dest, sizeof(rpc->udp_dest)) < 0) { rpc_set_error(rpc, "Sendto failed with errno %s", strerror(errno)); rpc_free_pdu(rpc, pdu); return -1; } hash = rpc_hash_xid(pdu->xid); rpc_enqueue(&rpc->waitpdu[hash], pdu); rpc->waitpdu_len++; return 0; } /* write recordmarker */ zdr_setpos(&pdu->zdr, 0); recordmarker = (size - 4) | 0x80000000; zdr_int(&pdu->zdr, &recordmarker); pdu->outdata.size = size; rpc_enqueue(&rpc->outqueue, pdu); return 0; }
bool_t zdr_NLM4_LOCKargs (ZDR *zdrs, NLM4_LOCKargs *objp) { register int32_t *buf; buf = NULL; if (!zdr_nlm_cookie (zdrs, &objp->cookie)) return FALSE; if (!zdr_bool (zdrs, &objp->block)) return FALSE; if (!zdr_bool (zdrs, &objp->exclusive)) return FALSE; if (!zdr_nlm4_lock (zdrs, &objp->lock)) return FALSE; if (!zdr_bool (zdrs, &objp->reclaim)) return FALSE; if (!zdr_int (zdrs, &objp->state)) return FALSE; return TRUE; }
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; }