ReactOS 0.4.15-dev-7906-g1b85a5f
callback_server.c File Reference
#include <windows.h>
#include <strsafe.h>
#include "nfs41_ops.h"
#include "delegation.h"
#include "nfs41_callback.h"
#include "daemon_debug.h"
Include dependency graph for callback_server.c:

Go to the source code of this file.

Macros

#define CBSLVL   2 /* dprintf level for callback server logging */
 

Functions

static void replay_cache_write (IN nfs41_cb_session *session, IN struct cb_compound_args *args, IN struct cb_compound_res *res, IN bool_t cachethis)
 
void nfs41_callback_session_init (IN nfs41_session *session)
 
static enum_t handle_cb_layoutrecall (IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_layoutrecall_args *args, OUT struct cb_layoutrecall_res *res)
 
static enum_t handle_cb_recall_slot (IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_recall_slot_args *args, OUT struct cb_recall_slot_res *res)
 
static enum_t handle_cb_sequence (IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_sequence_args *args, OUT struct cb_sequence_res *res, OUT nfs41_cb_session **session_out, OUT bool_t *cachethis)
 
static enum_t handle_cb_getattr (IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_getattr_args *args, OUT struct cb_getattr_res *res)
 
static enum_t handle_cb_recall (IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_recall_args *args, OUT struct cb_recall_res *res)
 
static enum_t handle_cb_notify_deviceid (IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_notify_deviceid_args *args, OUT struct cb_notify_deviceid_res *res)
 
static void replay_cache_write (IN nfs41_cb_session *session, IN OPTIONAL struct cb_compound_args *args, IN struct cb_compound_res *res, IN bool_t cachethis)
 
static bool_t replay_validate_args (IN struct cb_compound_args *args, IN const struct replay_cache *cache)
 
static bool_t replay_validate_ops (IN const struct cb_compound_args *args, IN const struct cb_compound_res *res)
 
static int replay_cache_read (IN nfs41_cb_session *session, IN struct cb_compound_args *args, OUT struct cb_compound_res **res_out)
 
static void handle_cb_compound (nfs41_rpc_clnt *rpc_clnt, cb_req *req, struct cb_compound_res **reply)
 
int nfs41_handle_callback (void *rpc_clnt, void *cb, struct cb_compound_res **reply)
 

Variables

static const char g_server_tag [] = "ms-nfs41-callback"
 

Macro Definition Documentation

◆ CBSLVL

#define CBSLVL   2 /* dprintf level for callback server logging */

Definition at line 31 of file callback_server.c.

Function Documentation

◆ handle_cb_compound()

static void handle_cb_compound ( nfs41_rpc_clnt rpc_clnt,
cb_req req,
struct cb_compound_res **  reply 
)
static

Definition at line 354 of file callback_server.c.

355{
356 struct cb_compound_args args = { 0 };
357 struct cb_compound_res *res = NULL;
358 struct cb_argop *argop;
359 struct cb_resop *resop;
360 XDR *xdr = (XDR*)req->xdr;
362 bool_t cachethis = FALSE;
364
365 dprintf(CBSLVL, "--> handle_cb_compound()\n");
366
367 /* decode the arguments */
368 if (!proc_cb_compound_args(xdr, &args)) {
370 eprintf("failed to decode compound arguments\n");
371 }
372
373 /* allocate the compound results */
374 res = calloc(1, sizeof(struct cb_compound_res));
375 if (res == NULL) {
377 goto out;
378 }
379 res->status = status;
381 res->tag.str[CB_COMPOUND_MAX_TAG-1] = 0;
382 res->tag.len = (uint32_t)strlen(res->tag.str);
383 res->resarray = calloc(args.argarray_count, sizeof(struct cb_resop));
384 if (res->resarray == NULL) {
385 res->status = NFS4ERR_SERVERFAULT;
386 goto out;
387 }
388
389 dprintf(CBSLVL, "CB_COMPOUND('%s', %u)\n", args.tag.str, args.argarray_count);
390 if (args.minorversion != 1) {
391 res->status = NFS4ERR_MINOR_VERS_MISMATCH; //XXXXX
392 eprintf("args.minorversion %u != 1\n", args.minorversion);
393 goto out;
394 }
395
396 /* handle each operation in the compound */
397 for (i = 0; i < args.argarray_count && res->status == NFS4_OK; i++) {
398 argop = &args.argarray[i];
399 resop = &res->resarray[i];
400 resop->opnum = argop->opnum;
401 res->resarray_count++;
402
403 /* 20.9.3: The error NFS4ERR_SEQUENCE_POS MUST be returned
404 * when CB_SEQUENCE is found in any position in a CB_COMPOUND
405 * beyond the first. If any other operation is in the first
406 * position of CB_COMPOUND, NFS4ERR_OP_NOT_IN_SESSION MUST
407 * be returned.
408 */
409 if (i == 0 && argop->opnum != OP_CB_SEQUENCE) {
410 res->status = resop->res.status = NFS4ERR_OP_NOT_IN_SESSION;
411 break;
412 }
413 if (i != 0 && argop->opnum == OP_CB_SEQUENCE) {
414 res->status = resop->res.status = NFS4ERR_SEQUENCE_POS;
415 break;
416 }
418 res->status = resop->res.status = status;
419 break;
420 }
421
422 switch (argop->opnum) {
424 dprintf(1, "OP_CB_LAYOUTRECALL\n");
425 res->status = handle_cb_layoutrecall(rpc_clnt,
426 &argop->args.layoutrecall, &resop->res.layoutrecall);
427 break;
429 dprintf(1, "OP_CB_RECALL_SLOT\n");
430 res->status = handle_cb_recall_slot(rpc_clnt,
431 &argop->args.recall_slot, &resop->res.recall_slot);
432 break;
433 case OP_CB_SEQUENCE:
434 dprintf(1, "OP_CB_SEQUENCE\n");
435 status = handle_cb_sequence(rpc_clnt, &argop->args.sequence,
436 &resop->res.sequence, &session, &cachethis);
437
439 /* replace the current results with the cached response */
441 if (status) res->status = status;
442 goto out;
443 }
444
445 if (status == NFS4_OK)
446 res->status = resop->res.sequence.status;
447 break;
448 case OP_CB_GETATTR:
449 dprintf(1, "OP_CB_GETATTR\n");
450 res->status = handle_cb_getattr(rpc_clnt,
451 &argop->args.getattr, &resop->res.getattr);
452 break;
453 case OP_CB_RECALL:
454 dprintf(1, "OP_CB_RECALL\n");
455 res->status = handle_cb_recall(rpc_clnt,
456 &argop->args.recall, &resop->res.recall);
457 break;
458 case OP_CB_NOTIFY:
459 dprintf(1, "OP_CB_NOTIFY\n");
460 res->status = NFS4ERR_NOTSUPP;
461 break;
462 case OP_CB_PUSH_DELEG:
463 dprintf(1, "OP_CB_PUSH_DELEG\n");
464 res->status = NFS4ERR_NOTSUPP;
465 break;
466 case OP_CB_RECALL_ANY:
467 dprintf(1, "OP_CB_RECALL_ANY\n");
468 res->status = NFS4ERR_NOTSUPP;
469 break;
471 dprintf(1, "OP_CB_RECALLABLE_OBJ_AVAIL\n");
472 res->status = NFS4ERR_NOTSUPP;
473 break;
475 dprintf(1, "OP_CB_WANTS_CANCELLED\n");
476 res->status = NFS4ERR_NOTSUPP;
477 break;
479 dprintf(1, "OP_CB_NOTIFY_LOCK\n");
480 res->status = NFS4ERR_NOTSUPP;
481 break;
483 dprintf(1, "OP_CB_NOTIFY_DEVICEID\n");
484 res->status = NFS4_OK;
485 break;
486 case OP_CB_ILLEGAL:
487 dprintf(1, "OP_CB_ILLEGAL\n");
488 res->status = NFS4ERR_NOTSUPP;
489 break;
490 default:
491 eprintf("operation %u not supported\n", argop->opnum);
492 res->status = NFS4ERR_NOTSUPP;
493 break;
494 }
495 }
496
497 /* always attempt to cache the reply */
498 if (session)
499 replay_cache_write(session, &args, res, cachethis);
500out:
501 /* free the arguments */
502 xdr->x_op = XDR_FREE;
504
505 *reply = res;
506 dprintf(CBSLVL, "<-- handle_cb_compound() returning %s (%u results)\n",
507 nfs_error_string(res ? res->status : status),
508 res ? res->resarray_count : 0);
509}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
static int replay_cache_read(IN nfs41_cb_session *session, IN struct cb_compound_args *args, OUT struct cb_compound_res **res_out)
static enum_t handle_cb_recall_slot(IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_recall_slot_args *args, OUT struct cb_recall_slot_res *res)
static const char g_server_tag[]
static enum_t handle_cb_recall(IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_recall_args *args, OUT struct cb_recall_res *res)
static enum_t handle_cb_sequence(IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_sequence_args *args, OUT struct cb_sequence_res *res, OUT nfs41_cb_session **session_out, OUT bool_t *cachethis)
static void replay_cache_write(IN nfs41_cb_session *session, IN struct cb_compound_args *args, IN struct cb_compound_res *res, IN bool_t cachethis)
static enum_t handle_cb_getattr(IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_getattr_args *args, OUT struct cb_getattr_res *res)
#define CBSLVL
static enum_t handle_cb_layoutrecall(IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_layoutrecall_args *args, OUT struct cb_layoutrecall_res *res)
bool_t proc_cb_compound_args(XDR *xdr, struct cb_compound_args *args)
Definition: callback_xdr.c:590
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
const char * nfs_error_string(int status)
Definition: daemon_debug.c:370
#define NULL
Definition: types.h:112
int32_t bool_t
Definition: types.h:101
#define FALSE
Definition: types.h:117
UINT32 uint32_t
Definition: types.h:75
GLuint res
Definition: glext.h:9613
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define CB_COMPOUND_MAX_TAG
@ OP_CB_SEQUENCE
@ OP_CB_PUSH_DELEG
@ OP_CB_WANTS_CANCELLED
@ OP_CB_LAYOUTRECALL
@ OP_CB_NOTIFY_LOCK
@ OP_CB_ILLEGAL
@ OP_CB_RECALL_ANY
@ OP_CB_GETATTR
@ OP_CB_NOTIFY_DEVICEID
@ OP_CB_RECALL_SLOT
@ OP_CB_NOTIFY
@ OP_CB_RECALL
@ OP_CB_RECALLABLE_OBJ_AVAIL
@ NFS4ERR_OP_NOT_IN_SESSION
Definition: nfs41_const.h:180
@ NFS4ERR_SEQUENCE_POS
Definition: nfs41_const.h:173
@ NFS4ERR_RETRY_UNCACHED_REP
Definition: nfs41_const.h:177
@ NFS4ERR_MINOR_VERS_MISMATCH
Definition: nfs41_const.h:128
@ NFS4ERR_BADXDR
Definition: nfs41_const.h:143
@ NFS4ERR_NOTSUPP
Definition: nfs41_const.h:109
@ NFS4_OK
Definition: nfs41_const.h:87
@ NFS4ERR_SERVERFAULT
Definition: nfs41_const.h:111
@ NFS4ERR_SEQ_FALSE_RETRY
Definition: nfs41_const.h:185
#define uint32_t
Definition: nsiface.idl:61
#define dprintf
Definition: regdump.c:33
static FILE * out
Definition: regtests2xml.c:44
#define calloc
Definition: rosglue.h:14
STRSAFEAPI StringCchCopyA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc)
Definition: strsafe.h:145
void * xdr
Definition: clnt.h:156
Definition: xdr.h:103
enum xdr_op x_op
Definition: xdr.h:104
Definition: match.c:390
enum_t opnum
union cb_op_args args
union cb_op_res res
enum_t opnum
Definition: ps.c:97
struct cb_recall_args recall
struct cb_sequence_args sequence
struct cb_getattr_args getattr
struct cb_recall_slot_args recall_slot
struct cb_layoutrecall_args layoutrecall
struct cb_getattr_res getattr
struct cb_sequence_res sequence
enum_t status
struct cb_layoutrecall_res layoutrecall
struct cb_recall_slot_res recall_slot
struct cb_recall_res recall
@ XDR_FREE
Definition: xdr.h:87

Referenced by nfs41_handle_callback().

◆ handle_cb_getattr()

static enum_t handle_cb_getattr ( IN nfs41_rpc_clnt rpc_clnt,
IN struct cb_getattr_args args,
OUT struct cb_getattr_res res 
)
static

Definition at line 174 of file callback_server.c.

178{
179 /* look up cached attributes for the given filehandle */
180 res->status = nfs41_delegation_getattr(rpc_clnt->client,
181 &args->fh, &args->attr_request, &res->info);
182 return res->status;
183}
int nfs41_delegation_getattr(IN nfs41_client *client, IN const nfs41_fh *fh, IN const bitmap4 *attr_request, OUT nfs41_file_info *info)
Definition: delegation.c:783

Referenced by handle_cb_compound().

◆ handle_cb_layoutrecall()

static enum_t handle_cb_layoutrecall ( IN nfs41_rpc_clnt rpc_clnt,
IN struct cb_layoutrecall_args args,
OUT struct cb_layoutrecall_res res 
)
static

Definition at line 60 of file callback_server.c.

64{
66
67 status = pnfs_file_layout_recall(rpc_clnt->client, args);
68 switch (status) {
69 case PNFS_PENDING:
70 /* not enough information to process the recall yet */
71 res->status = NFS4ERR_DELAY;
72 break;
73 default:
74 /* forgetful model for layout recalls */
76 break;
77 }
78
79 dprintf(CBSLVL, " OP_CB_LAYOUTRECALL { %s, %s, recall %u } %s\n",
81 pnfs_iomode_string(args->iomode), args->recall.type,
82 nfs_error_string(res->status));
83 return res->status;
84}
const char * pnfs_iomode_string(enum pnfs_iomode iomode)
Definition: pnfs_debug.c:58
const char * pnfs_layout_type_string(enum pnfs_layout_type type)
Definition: pnfs_debug.c:48
@ NFS4ERR_DELAY
Definition: nfs41_const.h:113
@ NFS4ERR_NOMATCHING_LAYOUT
Definition: nfs41_const.h:169
enum pnfs_status pnfs_file_layout_recall(IN struct __nfs41_client *client, IN const struct cb_layoutrecall_args *recall)
pnfs_status
Definition: pnfs.h:58
@ PNFS_PENDING
Definition: pnfs.h:60

Referenced by handle_cb_compound().

◆ handle_cb_notify_deviceid()

static enum_t handle_cb_notify_deviceid ( IN nfs41_rpc_clnt rpc_clnt,
IN struct cb_notify_deviceid_args args,
OUT struct cb_notify_deviceid_res res 
)
static

Definition at line 198 of file callback_server.c.

202{
203 uint32_t i;
204 for (i = 0; i < args->change_count; i++) {
205 pnfs_file_device_notify(rpc_clnt->client->devices,
206 &args->change_list[i]);
207 }
208 res->status = NFS4_OK;
209 return res->status;
210}
enum pnfs_status pnfs_file_device_notify(IN struct pnfs_file_device_list *devices, IN const struct notify_deviceid4 *change)
Definition: pnfs_device.c:328

◆ handle_cb_recall()

static enum_t handle_cb_recall ( IN nfs41_rpc_clnt rpc_clnt,
IN struct cb_recall_args args,
OUT struct cb_recall_res res 
)
static

Definition at line 186 of file callback_server.c.

190{
191 /* return the delegation asynchronously */
192 res->status = nfs41_delegation_recall(rpc_clnt->client,
193 &args->fh, &args->stateid, args->truncate);
194 return res->status;
195}
int nfs41_delegation_recall(IN nfs41_client *client, IN nfs41_fh *fh, IN const stateid4 *stateid, IN bool_t truncate)
Definition: delegation.c:703

Referenced by handle_cb_compound().

◆ handle_cb_recall_slot()

static enum_t handle_cb_recall_slot ( IN nfs41_rpc_clnt rpc_clnt,
IN struct cb_recall_slot_args args,
OUT struct cb_recall_slot_res res 
)
static

Definition at line 87 of file callback_server.c.

91{
92 res->status = nfs41_session_recall_slot(rpc_clnt->client->session,
93 args->target_highest_slotid);
94
95 dprintf(CBSLVL, " OP_CB_RECALL_SLOT { %u } %s\n",
96 args->target_highest_slotid, nfs_error_string(res->status));
97 return res->status;
98}
int nfs41_session_recall_slot(IN nfs41_session *session, IN OUT uint32_t target_highest_slotid)

Referenced by handle_cb_compound().

◆ handle_cb_sequence()

static enum_t handle_cb_sequence ( IN nfs41_rpc_clnt rpc_clnt,
IN struct cb_sequence_args args,
OUT struct cb_sequence_res res,
OUT nfs41_cb_session **  session_out,
OUT bool_t cachethis 
)
static

Definition at line 101 of file callback_server.c.

107{
108 nfs41_cb_session *cb_session = &rpc_clnt->client->session->cb_session;
110 res->status = NFS4_OK;
111
112 *session_out = cb_session;
113
114 /* validate the sessionid */
115 if (memcmp(cb_session->cb_sessionid, args->sessionid,
117 eprintf("[cb] received sessionid doesn't match session\n");
118 res->status = NFS4ERR_BADSESSION;
119 goto out;
120 }
121
122 /* we only support 1 slot for the back channel so slotid MUST be 0 */
123 if (args->slotid != 0) {
124 eprintf("[cb] received unexpected slotid=%d\n", args->slotid);
125 res->status = NFS4ERR_BADSLOT;
126 goto out;
127 }
128 if (args->highest_slotid != 0) {
129 eprintf("[cb] received unexpected highest_slotid=%d\n",
130 args->highest_slotid);
131 res->status = NFS4ERR_BAD_HIGH_SLOT;
132 goto out;
133 }
134
135 /* check for a retry with the same seqid */
136 if (args->sequenceid == cb_session->cb_seqnum) {
137 if (!cb_session->replay.res.length) {
138 /* return success for sequence, but fail the next operation */
139 res->status = NFS4_OK;
141 } else {
142 /* return NFS4ERR_SEQ_FALSE_RETRY for all replays; if the retry
143 * turns out to be valid, this response will be replaced anyway */
145 }
146 goto out;
147 }
148
149 /* error on any unexpected seqids */
150 if (args->sequenceid != cb_session->cb_seqnum+1) {
151 eprintf("[cb] bad received seq#=%d, expected=%d\n",
152 args->sequenceid, cb_session->cb_seqnum+1);
153 res->status = NFS4ERR_SEQ_MISORDERED;
154 goto out;
155 }
156
157 cb_session->cb_seqnum = args->sequenceid;
158 *cachethis = args->cachethis;
159
160 memcpy(res->ok.sessionid, args->sessionid, NFS4_SESSIONID_SIZE);
161 res->ok.sequenceid = args->sequenceid;
162 res->ok.slotid = args->slotid;
163 res->ok.highest_slotid = args->highest_slotid;
164 res->ok.target_highest_slotid = args->highest_slotid;
165
166out:
167 dprintf(CBSLVL, " OP_CB_SEQUENCE { seqid %u, slot %u, cachethis %d } "
168 "%s\n", args->sequenceid, args->slotid, args->cachethis,
169 nfs_error_string(res->status));
170 return status;
171}
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define NFS4_SESSIONID_SIZE
Definition: nfs41_const.h:32
@ NFS4ERR_SEQ_MISORDERED
Definition: nfs41_const.h:172
@ NFS4ERR_BADSLOT
Definition: nfs41_const.h:162
@ NFS4ERR_BADSESSION
Definition: nfs41_const.h:161
@ NFS4ERR_BAD_HIGH_SLOT
Definition: nfs41_const.h:186
struct __nfs41_cb_session::@38 replay
uint32_t cb_seqnum
Definition: nfs41.h:251
const unsigned char * cb_sessionid
Definition: nfs41.h:250

Referenced by handle_cb_compound().

◆ nfs41_callback_session_init()

void nfs41_callback_session_init ( IN nfs41_session session)

Definition at line 44 of file callback_server.c.

46{
47 /* initialize the replay cache with status NFS4ERR_SEQ_MISORDERED */
48 struct cb_compound_res res = { 0 };
50 res.tag.len = sizeof(g_server_tag);
52
53 session->cb_session.cb_sessionid = session->session_id;
54
55 replay_cache_write(&session->cb_session, NULL, &res, FALSE);
56}

Referenced by session_alloc().

◆ nfs41_handle_callback()

int nfs41_handle_callback ( void rpc_clnt,
void cb,
struct cb_compound_res **  reply 
)

Definition at line 516 of file callback_server.c.

517{
518#endif
519 nfs41_rpc_clnt *rpc = (nfs41_rpc_clnt *)rpc_clnt;
520 cb_req *request = (cb_req *)cb;
521 uint32_t status = 0;
522
523 dprintf(1, "nfs41_handle_callback: received call\n");
524 if (request->rq_prog != NFS41_RPC_CBPROGRAM) {
525 eprintf("invalid rpc program %u\n", request->rq_prog);
526 status = 2;
527 goto out;
528 }
529
530 switch (request->rq_proc) {
531 case CB_NULL:
532 dprintf(1, "CB_NULL\n");
533 break;
534
535 case CB_COMPOUND:
536 dprintf(1, "CB_COMPOUND\n");
537 handle_cb_compound(rpc, request, reply);
538 break;
539
540 default:
541 dprintf(1, "invalid rpc procedure %u\n", request->rq_proc);
542 status = 3;
543 goto out;
544 }
545out:
546 return status;
547}
static void handle_cb_compound(nfs41_rpc_clnt *rpc_clnt, cb_req *req, struct cb_compound_res **reply)
static HMODULE MODULEINFO DWORD cb
Definition: module.c:33
@ CB_NULL
@ CB_COMPOUND
#define NFS41_RPC_CBPROGRAM
Definition: nfs41_const.h:80
Definition: clnt.h:152
Definition: tftpd.h:86

Referenced by get_client_for_netaddr().

◆ replay_cache_read()

static int replay_cache_read ( IN nfs41_cb_session session,
IN struct cb_compound_args args,
OUT struct cb_compound_res **  res_out 
)
static

Definition at line 296 of file callback_server.c.

300{
301 XDR xdr;
302 struct cb_compound_res *replay;
303 struct cb_compound_res *res = *res_out;
305
306 replay = calloc(1, sizeof(struct cb_compound_res));
307 if (replay == NULL) {
308 eprintf("[cb] failed to allocate replay buffer\n");
310 goto out;
311 }
312
313 /* decode the response from the replay cache */
314 xdrmem_create(&xdr, (char*)session->replay.res.buffer,
316 if (!proc_cb_compound_res(&xdr, replay)) {
317 eprintf("[cb] failed to decode replay buffer\n");
319 goto out_free_replay;
320 }
321
322 /* if we cached the arguments, use them to validate the retry */
323 if (session->replay.arg.length) {
324 if (!replay_validate_args(args, &session->replay.arg)) {
325 eprintf("[cb] retry attempt with different arguments\n");
327 goto out_free_replay;
328 }
329 } else { /* otherwise, comparing opnums is the best we can do */
330 if (!replay_validate_ops(args, replay)) {
331 eprintf("[cb] retry attempt with different operations\n");
333 goto out_free_replay;
334 }
335 }
336
337 /* free previous response and replace it with the replay */
338 xdr.x_op = XDR_FREE;
340
341 dprintf(2, "[cb] retry: returning cached response\n");
342
343 *res_out = replay;
344out:
345 return status;
346
347out_free_replay:
348 xdr.x_op = XDR_FREE;
349 proc_cb_compound_res(&xdr, replay);
350 goto out;
351}
static bool_t replay_validate_args(IN struct cb_compound_args *args, IN const struct replay_cache *cache)
static bool_t replay_validate_ops(IN const struct cb_compound_args *args, IN const struct cb_compound_res *res)
bool_t proc_cb_compound_res(XDR *xdr, struct cb_compound_res *res)
Definition: callback_xdr.c:638
#define NFS41_MAX_SERVER_CACHE
Definition: nfs41_const.h:39
@ XDR_DECODE
Definition: xdr.h:86
void xdrmem_create(XDR *xdrs, char *addr, u_int size, enum xdr_op op)
Definition: xdr_mem.c:94

Referenced by handle_cb_compound().

◆ replay_cache_write() [1/2]

static void replay_cache_write ( IN nfs41_cb_session session,
IN OPTIONAL struct cb_compound_args args,
IN struct cb_compound_res res,
IN bool_t  cachethis 
)
static

Definition at line 212 of file callback_server.c.

217{
218 XDR xdr;
219 uint32_t i;
220
221 session->replay.arg.length = 0;
222 session->replay.res.length = 0;
223
224 /* encode the reply directly into the replay cache */
225 xdrmem_create(&xdr, (char*)session->replay.res.buffer,
227
228 /* always try to cache the result */
229 if (proc_cb_compound_res(&xdr, res)) {
230 session->replay.res.length = XDR_GETPOS(&xdr);
231
232 if (args) {
233 /* encode the arguments into the request cache */
234 xdrmem_create(&xdr, (char*)session->replay.arg.buffer,
236
237 if (proc_cb_compound_args(&xdr, args))
238 session->replay.arg.length = XDR_GETPOS(&xdr);
239 }
240 } else if (cachethis) {
241 /* on failure, only return errors if caching was requested */
243
244 /* find the first operation that failed to encode */
245 for (i = 0; i < res->resarray_count; i++) {
246 if (!res->resarray[i].xdr_ok) {
247 res->resarray[i].res.status = NFS4ERR_REP_TOO_BIG_TO_CACHE;
248 res->resarray_count = i + 1;
249 break;
250 }
251 }
252 }
253}
@ NFS4ERR_REP_TOO_BIG_TO_CACHE
Definition: nfs41_const.h:176
@ XDR_ENCODE
Definition: xdr.h:85
#define XDR_GETPOS(xdrs)
Definition: xdr.h:199

◆ replay_cache_write() [2/2]

static void replay_cache_write ( IN nfs41_cb_session session,
IN struct cb_compound_args args,
IN struct cb_compound_res res,
IN bool_t  cachethis 
)
static

◆ replay_validate_args()

static bool_t replay_validate_args ( IN struct cb_compound_args args,
IN const struct replay_cache cache 
)
static

Definition at line 255 of file callback_server.c.

258{
260 XDR xdr;
261
262 /* encode the current arguments into a temporary buffer */
264
265 if (!proc_cb_compound_args(&xdr, args))
266 return FALSE;
267
268 /* must match the cached length */
269 if (XDR_GETPOS(&xdr) != cache->length)
270 return FALSE;
271
272 /* must match the cached buffer contents */
273 return memcmp(cache->buffer, buffer, cache->length) == 0;
274}
GLuint buffer
Definition: glext.h:5915
Definition: cache.c:49

Referenced by replay_cache_read().

◆ replay_validate_ops()

static bool_t replay_validate_ops ( IN const struct cb_compound_args args,
IN const struct cb_compound_res res 
)
static

Definition at line 276 of file callback_server.c.

279{
280 uint32_t i;
281 for (i = 0; i < res->resarray_count; i++) {
282 /* can't have more operations than the request */
283 if (i >= args->argarray_count)
284 return FALSE;
285
286 /* each opnum must match the request */
287 if (args->argarray[i].opnum != res->resarray[i].opnum)
288 return FALSE;
289
290 if (res->resarray[i].res.status)
291 break;
292 }
293 return TRUE;
294}
#define TRUE
Definition: types.h:120

Referenced by replay_cache_read().

Variable Documentation

◆ g_server_tag

const char g_server_tag[] = "ms-nfs41-callback"
static

Definition at line 34 of file callback_server.c.

Referenced by handle_cb_compound(), and nfs41_callback_session_init().