diff options
| -rw-r--r-- | fs/lockd/svc.c | 3 | ||||
| -rw-r--r-- | fs/nfs/callback.c | 1 | ||||
| -rw-r--r-- | fs/nfsd/nfssvc.c | 2 | ||||
| -rw-r--r-- | include/linux/sunrpc/svc.h | 16 | ||||
| -rw-r--r-- | net/sunrpc/svc.c | 113 |
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 | ||
| 91 | static struct svc_stat nfsd_acl_svcstats = { | 92 | static 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 | ||
| 386 | struct 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 | ||
| 1164 | svc_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; | ||
| 1207 | err_bad_vers: | ||
| 1208 | ret->mismatch.lovers = progp->pg_lovers; | ||
| 1209 | ret->mismatch.hivers = progp->pg_hivers; | ||
| 1210 | return rpc_prog_mismatch; | ||
| 1211 | err_bad_proc: | ||
| 1212 | return rpc_proc_unavail; | ||
| 1213 | } | ||
| 1214 | EXPORT_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 | |||
| 1167 | svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) | 1220 | svc_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 | ||
| 1387 | err_bad_vers: | 1426 | err_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 | ||
| 1397 | err_bad_proc: | 1436 | err_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); |
