.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * net/sched/cls_route.c ROUTE4 classifier. |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or |
---|
5 | | - * modify it under the terms of the GNU General Public License |
---|
6 | | - * as published by the Free Software Foundation; either version |
---|
7 | | - * 2 of the License, or (at your option) any later version. |
---|
8 | 4 | * |
---|
9 | 5 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
---|
10 | 6 | */ |
---|
.. | .. |
---|
276 | 272 | tcf_queue_work(&f->rwork, route4_delete_filter_work); |
---|
277 | 273 | } |
---|
278 | 274 | |
---|
279 | | -static void route4_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) |
---|
| 275 | +static void route4_destroy(struct tcf_proto *tp, bool rtnl_held, |
---|
| 276 | + struct netlink_ext_ack *extack) |
---|
280 | 277 | { |
---|
281 | 278 | struct route4_head *head = rtnl_dereference(tp->root); |
---|
282 | 279 | int h1, h2; |
---|
.. | .. |
---|
312 | 309 | } |
---|
313 | 310 | |
---|
314 | 311 | static int route4_delete(struct tcf_proto *tp, void *arg, bool *last, |
---|
315 | | - struct netlink_ext_ack *extack) |
---|
| 312 | + bool rtnl_held, struct netlink_ext_ack *extack) |
---|
316 | 313 | { |
---|
317 | 314 | struct route4_head *head = rtnl_dereference(tp->root); |
---|
318 | 315 | struct route4_filter *f = arg; |
---|
.. | .. |
---|
393 | 390 | struct route4_bucket *b; |
---|
394 | 391 | int err; |
---|
395 | 392 | |
---|
396 | | - err = tcf_exts_validate(net, tp, tb, est, &f->exts, ovr, extack); |
---|
| 393 | + err = tcf_exts_validate(net, tp, tb, est, &f->exts, ovr, true, extack); |
---|
397 | 394 | if (err < 0) |
---|
398 | 395 | return err; |
---|
399 | 396 | |
---|
.. | .. |
---|
425 | 422 | nhandle |= handle & 0x7F00; |
---|
426 | 423 | if (nhandle != handle) |
---|
427 | 424 | return -EINVAL; |
---|
| 425 | + } |
---|
| 426 | + |
---|
| 427 | + if (!nhandle) { |
---|
| 428 | + NL_SET_ERR_MSG(extack, "Replacing with handle of 0 is invalid"); |
---|
| 429 | + return -EINVAL; |
---|
428 | 430 | } |
---|
429 | 431 | |
---|
430 | 432 | h1 = to_hash(nhandle); |
---|
.. | .. |
---|
468 | 470 | static int route4_change(struct net *net, struct sk_buff *in_skb, |
---|
469 | 471 | struct tcf_proto *tp, unsigned long base, u32 handle, |
---|
470 | 472 | struct nlattr **tca, void **arg, bool ovr, |
---|
471 | | - struct netlink_ext_ack *extack) |
---|
| 473 | + bool rtnl_held, struct netlink_ext_ack *extack) |
---|
472 | 474 | { |
---|
473 | 475 | struct route4_head *head = rtnl_dereference(tp->root); |
---|
474 | 476 | struct route4_filter __rcu **fp; |
---|
.. | .. |
---|
480 | 482 | int err; |
---|
481 | 483 | bool new = true; |
---|
482 | 484 | |
---|
| 485 | + if (!handle) { |
---|
| 486 | + NL_SET_ERR_MSG(extack, "Creating with handle of 0 is invalid"); |
---|
| 487 | + return -EINVAL; |
---|
| 488 | + } |
---|
| 489 | + |
---|
483 | 490 | if (opt == NULL) |
---|
484 | 491 | return handle ? -EINVAL : 0; |
---|
485 | 492 | |
---|
486 | | - err = nla_parse_nested(tb, TCA_ROUTE4_MAX, opt, route4_policy, NULL); |
---|
| 493 | + err = nla_parse_nested_deprecated(tb, TCA_ROUTE4_MAX, opt, |
---|
| 494 | + route4_policy, NULL); |
---|
487 | 495 | if (err < 0) |
---|
488 | 496 | return err; |
---|
489 | 497 | |
---|
.. | .. |
---|
496 | 504 | if (!f) |
---|
497 | 505 | goto errout; |
---|
498 | 506 | |
---|
499 | | - err = tcf_exts_init(&f->exts, TCA_ROUTE4_ACT, TCA_ROUTE4_POLICE); |
---|
| 507 | + err = tcf_exts_init(&f->exts, net, TCA_ROUTE4_ACT, TCA_ROUTE4_POLICE); |
---|
500 | 508 | if (err < 0) |
---|
501 | 509 | goto errout; |
---|
502 | 510 | |
---|
503 | 511 | if (fold) { |
---|
504 | 512 | f->id = fold->id; |
---|
505 | 513 | f->iif = fold->iif; |
---|
506 | | - f->res = fold->res; |
---|
507 | 514 | f->handle = fold->handle; |
---|
508 | 515 | |
---|
509 | 516 | f->tp = fold->tp; |
---|
.. | .. |
---|
528 | 535 | rcu_assign_pointer(f->next, f1); |
---|
529 | 536 | rcu_assign_pointer(*fp, f); |
---|
530 | 537 | |
---|
531 | | - if (fold && fold->handle && f->handle != fold->handle) { |
---|
| 538 | + if (fold) { |
---|
532 | 539 | th = to_hash(fold->handle); |
---|
533 | 540 | h = from_hash(fold->handle >> 16); |
---|
534 | 541 | b = rtnl_dereference(head->table[th]); |
---|
.. | .. |
---|
560 | 567 | return err; |
---|
561 | 568 | } |
---|
562 | 569 | |
---|
563 | | -static void route4_walk(struct tcf_proto *tp, struct tcf_walker *arg) |
---|
| 570 | +static void route4_walk(struct tcf_proto *tp, struct tcf_walker *arg, |
---|
| 571 | + bool rtnl_held) |
---|
564 | 572 | { |
---|
565 | 573 | struct route4_head *head = rtnl_dereference(tp->root); |
---|
566 | 574 | unsigned int h, h1; |
---|
567 | 575 | |
---|
568 | | - if (head == NULL) |
---|
569 | | - arg->stop = 1; |
---|
570 | | - |
---|
571 | | - if (arg->stop) |
---|
| 576 | + if (head == NULL || arg->stop) |
---|
572 | 577 | return; |
---|
573 | 578 | |
---|
574 | 579 | for (h = 0; h <= 256; h++) { |
---|
.. | .. |
---|
597 | 602 | } |
---|
598 | 603 | |
---|
599 | 604 | static int route4_dump(struct net *net, struct tcf_proto *tp, void *fh, |
---|
600 | | - struct sk_buff *skb, struct tcmsg *t) |
---|
| 605 | + struct sk_buff *skb, struct tcmsg *t, bool rtnl_held) |
---|
601 | 606 | { |
---|
602 | 607 | struct route4_filter *f = fh; |
---|
603 | 608 | struct nlattr *nest; |
---|
.. | .. |
---|
608 | 613 | |
---|
609 | 614 | t->tcm_handle = f->handle; |
---|
610 | 615 | |
---|
611 | | - nest = nla_nest_start(skb, TCA_OPTIONS); |
---|
| 616 | + nest = nla_nest_start_noflag(skb, TCA_OPTIONS); |
---|
612 | 617 | if (nest == NULL) |
---|
613 | 618 | goto nla_put_failure; |
---|
614 | 619 | |
---|