aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/lockd/svc.c3
-rw-r--r--fs/nfs/callback.c1
-rw-r--r--fs/nfsd/nfssvc.c2
-rw-r--r--include/linux/sunrpc/svc.h16
-rw-r--r--net/sunrpc/svc.c113
5 files changed, 97 insertions, 38 deletions
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 346ed161756d..75415b21efda 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -807,5 +807,6 @@ static struct svc_program nlmsvc_program = {
807 .pg_name = "lockd", /* service name */ 807 .pg_name = "lockd", /* service name */
808 .pg_class = "nfsd", /* share authentication with nfsd */ 808 .pg_class = "nfsd", /* share authentication with nfsd */
809 .pg_stats = &nlmsvc_stats, /* stats table */ 809 .pg_stats = &nlmsvc_stats, /* stats table */
810 .pg_authenticate = &lockd_authenticate /* export authentication */ 810 .pg_authenticate = &lockd_authenticate, /* export authentication */
811 .pg_init_request = svc_generic_init_request,
811}; 812};
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 0b602a39dd71..a9510374bad7 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -457,4 +457,5 @@ static struct svc_program nfs4_callback_program = {
457 .pg_class = "nfs", /* authentication class */ 457 .pg_class = "nfs", /* authentication class */
458 .pg_stats = &nfs4_callback_stats, 458 .pg_stats = &nfs4_callback_stats,
459 .pg_authenticate = nfs_callback_authenticate, 459 .pg_authenticate = nfs_callback_authenticate,
460 .pg_init_request = svc_generic_init_request,
460}; 461};
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 89cb484f1cfb..e26762e84798 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -86,6 +86,7 @@ static struct svc_program nfsd_acl_program = {
86 .pg_class = "nfsd", 86 .pg_class = "nfsd",
87 .pg_stats = &nfsd_acl_svcstats, 87 .pg_stats = &nfsd_acl_svcstats,
88 .pg_authenticate = &svc_set_client, 88 .pg_authenticate = &svc_set_client,
89 .pg_init_request = svc_generic_init_request,
89}; 90};
90 91
91static struct svc_stat nfsd_acl_svcstats = { 92static struct svc_stat nfsd_acl_svcstats = {
@@ -118,6 +119,7 @@ struct svc_program nfsd_program = {
118 .pg_class = "nfsd", /* authentication class */ 119 .pg_class = "nfsd", /* authentication class */
119 .pg_stats = &nfsd_svcstats, /* version table */ 120 .pg_stats = &nfsd_svcstats, /* version table */
120 .pg_authenticate = &svc_set_client, /* export authentication */ 121 .pg_authenticate = &svc_set_client, /* export authentication */
122 .pg_init_request = svc_generic_init_request,
121 123
122}; 124};
123 125
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 7ff12c9dbeaf..f43d5765acff 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -383,6 +383,16 @@ struct svc_deferred_req {
383 __be32 args[0]; 383 __be32 args[0];
384}; 384};
385 385
386struct svc_process_info {
387 union {
388 int (*dispatch)(struct svc_rqst *, __be32 *);
389 struct {
390 unsigned int lovers;
391 unsigned int hivers;
392 } mismatch;
393 };
394};
395
386/* 396/*
387 * List of RPC programs on the same transport endpoint 397 * List of RPC programs on the same transport endpoint
388 */ 398 */
@@ -397,6 +407,9 @@ struct svc_program {
397 char * pg_class; /* class name: services sharing authentication */ 407 char * pg_class; /* class name: services sharing authentication */
398 struct svc_stat * pg_stats; /* rpc statistics */ 408 struct svc_stat * pg_stats; /* rpc statistics */
399 int (*pg_authenticate)(struct svc_rqst *); 409 int (*pg_authenticate)(struct svc_rqst *);
410 __be32 (*pg_init_request)(struct svc_rqst *,
411 const struct svc_program *,
412 struct svc_process_info *);
400}; 413};
401 414
402/* 415/*
@@ -506,6 +519,9 @@ char *svc_fill_symlink_pathname(struct svc_rqst *rqstp,
506 struct kvec *first, void *p, 519 struct kvec *first, void *p,
507 size_t total); 520 size_t total);
508__be32 svc_return_autherr(struct svc_rqst *rqstp, __be32 auth_err); 521__be32 svc_return_autherr(struct svc_rqst *rqstp, __be32 auth_err);
522__be32 svc_generic_init_request(struct svc_rqst *rqstp,
523 const struct svc_program *progp,
524 struct svc_process_info *procinfo);
509 525
510#define RPC_MAX_ADDRBUFLEN (63U) 526#define RPC_MAX_ADDRBUFLEN (63U)
511 527
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 3d5dd6b86652..69f3b9e015ce 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -1160,6 +1160,59 @@ svc_get_autherr(struct svc_rqst *rqstp, __be32 *statp)
1160 return rpc_auth_ok; 1160 return rpc_auth_ok;
1161} 1161}
1162 1162
1163__be32
1164svc_generic_init_request(struct svc_rqst *rqstp,
1165 const struct svc_program *progp,
1166 struct svc_process_info *ret)
1167{
1168 const struct svc_version *versp = NULL; /* compiler food */
1169 const struct svc_procedure *procp = NULL;
1170
1171 if (rqstp->rq_vers >= progp->pg_nvers )
1172 goto err_bad_vers;
1173 versp = progp->pg_vers[rqstp->rq_vers];
1174 if (!versp)
1175 goto err_bad_vers;
1176
1177 /*
1178 * Some protocol versions (namely NFSv4) require some form of
1179 * congestion control. (See RFC 7530 section 3.1 paragraph 2)
1180 * In other words, UDP is not allowed. We mark those when setting
1181 * up the svc_xprt, and verify that here.
1182 *
1183 * The spec is not very clear about what error should be returned
1184 * when someone tries to access a server that is listening on UDP
1185 * for lower versions. RPC_PROG_MISMATCH seems to be the closest
1186 * fit.
1187 */
1188 if (versp->vs_need_cong_ctrl && rqstp->rq_xprt &&
1189 !test_bit(XPT_CONG_CTRL, &rqstp->rq_xprt->xpt_flags))
1190 goto err_bad_vers;
1191
1192 if (rqstp->rq_proc >= versp->vs_nproc)
1193 goto err_bad_proc;
1194 rqstp->rq_procinfo = procp = &versp->vs_proc[rqstp->rq_proc];
1195 if (!procp)
1196 goto err_bad_proc;
1197
1198 /* Initialize storage for argp and resp */
1199 memset(rqstp->rq_argp, 0, procp->pc_argsize);
1200 memset(rqstp->rq_resp, 0, procp->pc_ressize);
1201
1202 /* Bump per-procedure stats counter */
1203 versp->vs_count[rqstp->rq_proc]++;
1204
1205 ret->dispatch = versp->vs_dispatch;
1206 return rpc_success;
1207err_bad_vers:
1208 ret->mismatch.lovers = progp->pg_lovers;
1209 ret->mismatch.hivers = progp->pg_hivers;
1210 return rpc_prog_mismatch;
1211err_bad_proc:
1212 return rpc_proc_unavail;
1213}
1214EXPORT_SYMBOL_GPL(svc_generic_init_request);
1215
1163/* 1216/*
1164 * Common routine for processing the RPC request. 1217 * Common routine for processing the RPC request.
1165 */ 1218 */
@@ -1167,11 +1220,11 @@ static int
1167svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) 1220svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
1168{ 1221{
1169 struct svc_program *progp; 1222 struct svc_program *progp;
1170 const struct svc_version *versp = NULL; /* compiler food */
1171 const struct svc_procedure *procp = NULL; 1223 const struct svc_procedure *procp = NULL;
1172 struct svc_serv *serv = rqstp->rq_server; 1224 struct svc_serv *serv = rqstp->rq_server;
1225 struct svc_process_info process;
1173 __be32 *statp; 1226 __be32 *statp;
1174 u32 prog, vers, proc; 1227 u32 prog, vers;
1175 __be32 auth_stat, rpc_stat; 1228 __be32 auth_stat, rpc_stat;
1176 int auth_res; 1229 int auth_res;
1177 __be32 *reply_statp; 1230 __be32 *reply_statp;
@@ -1203,8 +1256,8 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
1203 svc_putnl(resv, 0); /* ACCEPT */ 1256 svc_putnl(resv, 0); /* ACCEPT */
1204 1257
1205 rqstp->rq_prog = prog = svc_getnl(argv); /* program number */ 1258 rqstp->rq_prog = prog = svc_getnl(argv); /* program number */
1206 rqstp->rq_vers = vers = svc_getnl(argv); /* version number */ 1259 rqstp->rq_vers = svc_getnl(argv); /* version number */
1207 rqstp->rq_proc = proc = svc_getnl(argv); /* procedure number */ 1260 rqstp->rq_proc = svc_getnl(argv); /* procedure number */
1208 1261
1209 for (progp = serv->sv_program; progp; progp = progp->pg_next) 1262 for (progp = serv->sv_program; progp; progp = progp->pg_next)
1210 if (prog == progp->pg_prog) 1263 if (prog == progp->pg_prog)
@@ -1242,29 +1295,22 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
1242 if (progp == NULL) 1295 if (progp == NULL)
1243 goto err_bad_prog; 1296 goto err_bad_prog;
1244 1297
1245 if (vers >= progp->pg_nvers || 1298 rpc_stat = progp->pg_init_request(rqstp, progp, &process);
1246 !(versp = progp->pg_vers[vers])) 1299 switch (rpc_stat) {
1247 goto err_bad_vers; 1300 case rpc_success:
1248 1301 break;
1249 /* 1302 case rpc_prog_unavail:
1250 * Some protocol versions (namely NFSv4) require some form of 1303 goto err_bad_prog;
1251 * congestion control. (See RFC 7530 section 3.1 paragraph 2) 1304 case rpc_prog_mismatch:
1252 * In other words, UDP is not allowed. We mark those when setting
1253 * up the svc_xprt, and verify that here.
1254 *
1255 * The spec is not very clear about what error should be returned
1256 * when someone tries to access a server that is listening on UDP
1257 * for lower versions. RPC_PROG_MISMATCH seems to be the closest
1258 * fit.
1259 */
1260 if (versp->vs_need_cong_ctrl && rqstp->rq_xprt &&
1261 !test_bit(XPT_CONG_CTRL, &rqstp->rq_xprt->xpt_flags))
1262 goto err_bad_vers; 1305 goto err_bad_vers;
1306 case rpc_proc_unavail:
1307 goto err_bad_proc;
1308 }
1263 1309
1264 procp = versp->vs_proc + proc; 1310 procp = rqstp->rq_procinfo;
1265 if (proc >= versp->vs_nproc || !procp->pc_func) 1311 /* Should this check go into the dispatcher? */
1312 if (!procp || !procp->pc_func)
1266 goto err_bad_proc; 1313 goto err_bad_proc;
1267 rqstp->rq_procinfo = procp;
1268 1314
1269 /* Syntactic check complete */ 1315 /* Syntactic check complete */
1270 serv->sv_stats->rpccnt++; 1316 serv->sv_stats->rpccnt++;
@@ -1274,13 +1320,6 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
1274 statp = resv->iov_base +resv->iov_len; 1320 statp = resv->iov_base +resv->iov_len;
1275 svc_putnl(resv, RPC_SUCCESS); 1321 svc_putnl(resv, RPC_SUCCESS);
1276 1322
1277 /* Bump per-procedure stats counter */
1278 versp->vs_count[proc]++;
1279
1280 /* Initialize storage for argp and resp */
1281 memset(rqstp->rq_argp, 0, procp->pc_argsize);
1282 memset(rqstp->rq_resp, 0, procp->pc_ressize);
1283
1284 /* un-reserve some of the out-queue now that we have a 1323 /* un-reserve some of the out-queue now that we have a
1285 * better idea of reply size 1324 * better idea of reply size
1286 */ 1325 */
@@ -1288,7 +1327,7 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
1288 svc_reserve_auth(rqstp, procp->pc_xdrressize<<2); 1327 svc_reserve_auth(rqstp, procp->pc_xdrressize<<2);
1289 1328
1290 /* Call the function that processes the request. */ 1329 /* Call the function that processes the request. */
1291 if (!versp->vs_dispatch) { 1330 if (!process.dispatch) {
1292 /* 1331 /*
1293 * Decode arguments 1332 * Decode arguments
1294 * XXX: why do we ignore the return value? 1333 * XXX: why do we ignore the return value?
@@ -1317,7 +1356,7 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
1317 } 1356 }
1318 } else { 1357 } else {
1319 dprintk("svc: calling dispatcher\n"); 1358 dprintk("svc: calling dispatcher\n");
1320 if (!versp->vs_dispatch(rqstp, statp)) { 1359 if (!process.dispatch(rqstp, statp)) {
1321 /* Release reply info */ 1360 /* Release reply info */
1322 if (procp->pc_release) 1361 if (procp->pc_release)
1323 procp->pc_release(rqstp); 1362 procp->pc_release(rqstp);
@@ -1386,16 +1425,16 @@ err_bad_prog:
1386 1425
1387err_bad_vers: 1426err_bad_vers:
1388 svc_printk(rqstp, "unknown version (%d for prog %d, %s)\n", 1427 svc_printk(rqstp, "unknown version (%d for prog %d, %s)\n",
1389 vers, prog, progp->pg_name); 1428 rqstp->rq_vers, rqstp->rq_prog, progp->pg_name);
1390 1429
1391 serv->sv_stats->rpcbadfmt++; 1430 serv->sv_stats->rpcbadfmt++;
1392 svc_putnl(resv, RPC_PROG_MISMATCH); 1431 svc_putnl(resv, RPC_PROG_MISMATCH);
1393 svc_putnl(resv, progp->pg_lovers); 1432 svc_putnl(resv, process.mismatch.lovers);
1394 svc_putnl(resv, progp->pg_hivers); 1433 svc_putnl(resv, process.mismatch.hivers);
1395 goto sendit; 1434 goto sendit;
1396 1435
1397err_bad_proc: 1436err_bad_proc:
1398 svc_printk(rqstp, "unknown procedure (%d)\n", proc); 1437 svc_printk(rqstp, "unknown procedure (%d)\n", rqstp->rq_proc);
1399 1438
1400 serv->sv_stats->rpcbadfmt++; 1439 serv->sv_stats->rpcbadfmt++;
1401 svc_putnl(resv, RPC_PROC_UNAVAIL); 1440 svc_putnl(resv, RPC_PROC_UNAVAIL);