1 /* 2 * net/sched/em_meta.c Metadata ematch 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 * 9 * Authors: Thomas Graf <tgraf@suug.ch> 10 * 11 * ========================================================================== 12 * 13 * The metadata ematch compares two meta objects where each object 14 * represents either a meta value stored in the kernel or a static 15 * value provided by userspace. The objects are not provided by 16 * userspace itself but rather a definition providing the information 17 * to build them. Every object is of a certain type which must be 18 * equal to the object it is being compared to. 19 * 20 * The definition of a objects conists of the type (meta type), a 21 * identifier (meta id) and additional type specific information. 22 * The meta id is either TCF_META_TYPE_VALUE for values provided by 23 * userspace or a index to the meta operations table consisting of 24 * function pointers to type specific meta data collectors returning 25 * the value of the requested meta value. 26 * 27 * lvalue rvalue 28 * +-----------+ +-----------+ 29 * | type: INT | | type: INT | 30 * def | id: DEV | | id: VALUE | 31 * | data: | | data: 3 | 32 * +-----------+ +-----------+ 33 * | | 34 * ---> meta_ops[INT][DEV](...) | 35 * | | 36 * ----------- | 37 * V V 38 * +-----------+ +-----------+ 39 * | type: INT | | type: INT | 40 * obj | id: DEV | | id: VALUE | 41 * | data: 2 |<--data got filled out | data: 3 | 42 * +-----------+ +-----------+ 43 * | | 44 * --------------> 2 equals 3 <-------------- 45 * 46 * This is a simplified schema, the complexity varies depending 47 * on the meta type. Obviously, the length of the data must also 48 * be provided for non-numeric types. 49 * 50 * Additionaly, type dependant modifiers such as shift operators 51 * or mask may be applied to extend the functionaliy. As of now, 52 * the variable length type supports shifting the byte string to 53 * the right, eating up any number of octets and thus supporting 54 * wildcard interface name comparisons such as "ppp%" matching 55 * ppp0..9. 56 * 57 * NOTE: Certain meta values depend on other subsystems and are 58 * only available if that subsystem is enabled in the kernel. 59 */ 60 61 #include <linux/slab.h> 62 #include <linux/module.h> 63 #include <linux/types.h> 64 #include <linux/kernel.h> 65 #include <linux/sched.h> 66 #include <linux/string.h> 67 #include <linux/skbuff.h> 68 #include <linux/random.h> 69 #include <linux/if_vlan.h> 70 #include <linux/tc_ematch/tc_em_meta.h> 71 #include <net/dst.h> 72 #include <net/route.h> 73 #include <net/pkt_cls.h> 74 #include <net/sock.h> 75 76 struct meta_obj 77 { 78 unsigned long value; 79 unsigned int len; 80 }; 81 82 struct meta_value 83 { 84 struct tcf_meta_val hdr; 85 unsigned long val; 86 unsigned int len; 87 }; 88 89 struct meta_match 90 { 91 struct meta_value lvalue; 92 struct meta_value rvalue; 93 }; 94 95 static inline int meta_id(struct meta_value *v) 96 { 97 return TCF_META_ID(v->hdr.kind); 98 } 99 100 static inline int meta_type(struct meta_value *v) 101 { 102 return TCF_META_TYPE(v->hdr.kind); 103 } 104 105 #define META_COLLECTOR(FUNC) static void meta_##FUNC(struct sk_buff *skb, \ 106 struct tcf_pkt_info *info, struct meta_value *v, \ 107 struct meta_obj *dst, int *err) 108 109 /************************************************************************** 110 * System status & misc 111 **************************************************************************/ 112 113 META_COLLECTOR(int_random) 114 { 115 get_random_bytes(&dst->value, sizeof(dst->value)); 116 } 117 118 static inline unsigned long fixed_loadavg(int load) 119 { 120 int rnd_load = load + (FIXED_1/200); 121 int rnd_frac = ((rnd_load & (FIXED_1-1)) * 100) >> FSHIFT; 122 123 return ((rnd_load >> FSHIFT) * 100) + rnd_frac; 124 } 125 126 META_COLLECTOR(int_loadavg_0) 127 { 128 dst->value = fixed_loadavg(avenrun[0]); 129 } 130 131 META_COLLECTOR(int_loadavg_1) 132 { 133 dst->value = fixed_loadavg(avenrun[1]); 134 } 135 136 META_COLLECTOR(int_loadavg_2) 137 { 138 dst->value = fixed_loadavg(avenrun[2]); 139 } 140 141 /************************************************************************** 142 * Device names & indices 143 **************************************************************************/ 144 145 static inline int int_dev(struct net_device *dev, struct meta_obj *dst) 146 { 147 if (unlikely(dev == NULL)) 148 return -1; 149 150 dst->value = dev->ifindex; 151 return 0; 152 } 153 154 static inline int var_dev(struct net_device *dev, struct meta_obj *dst) 155 { 156 if (unlikely(dev == NULL)) 157 return -1; 158 159 dst->value = (unsigned long) dev->name; 160 dst->len = strlen(dev->name); 161 return 0; 162 } 163 164 META_COLLECTOR(int_dev) 165 { 166 *err = int_dev(skb->dev, dst); 167 } 168 169 META_COLLECTOR(var_dev) 170 { 171 *err = var_dev(skb->dev, dst); 172 } 173 174 /************************************************************************** 175 * vlan tag 176 **************************************************************************/ 177 178 META_COLLECTOR(int_vlan_tag) 179 { 180 unsigned short tag; 181 182 tag = vlan_tx_tag_get(skb); 183 if (!tag && __vlan_get_tag(skb, &tag)) 184 *err = -1; 185 else 186 dst->value = tag; 187 } 188 189 190 191 /************************************************************************** 192 * skb attributes 193 **************************************************************************/ 194 195 META_COLLECTOR(int_priority) 196 { 197 dst->value = skb->priority; 198 } 199 200 META_COLLECTOR(int_protocol) 201 { 202 /* Let userspace take care of the byte ordering */ 203 dst->value = skb->protocol; 204 } 205 206 META_COLLECTOR(int_pkttype) 207 { 208 dst->value = skb->pkt_type; 209 } 210 211 META_COLLECTOR(int_pktlen) 212 { 213 dst->value = skb->len; 214 } 215 216 META_COLLECTOR(int_datalen) 217 { 218 dst->value = skb->data_len; 219 } 220 221 META_COLLECTOR(int_maclen) 222 { 223 dst->value = skb->mac_len; 224 } 225 226 META_COLLECTOR(int_rxhash) 227 { 228 dst->value = skb_get_rxhash(skb); 229 } 230 231 /************************************************************************** 232 * Netfilter 233 **************************************************************************/ 234 235 META_COLLECTOR(int_mark) 236 { 237 dst->value = skb->mark; 238 } 239 240 /************************************************************************** 241 * Traffic Control 242 **************************************************************************/ 243 244 META_COLLECTOR(int_tcindex) 245 { 246 dst->value = skb->tc_index; 247 } 248 249 /************************************************************************** 250 * Routing 251 **************************************************************************/ 252 253 META_COLLECTOR(int_rtclassid) 254 { 255 if (unlikely(skb_dst(skb) == NULL)) 256 *err = -1; 257 else 258 #ifdef CONFIG_NET_CLS_ROUTE 259 dst->value = skb_dst(skb)->tclassid; 260 #else 261 dst->value = 0; 262 #endif 263 } 264 265 META_COLLECTOR(int_rtiif) 266 { 267 if (unlikely(skb_rtable(skb) == NULL)) 268 *err = -1; 269 else 270 dst->value = skb_rtable(skb)->fl.iif; 271 } 272 273 /************************************************************************** 274 * Socket Attributes 275 **************************************************************************/ 276 277 #define SKIP_NONLOCAL(skb) \ 278 if (unlikely(skb->sk == NULL)) { \ 279 *err = -1; \ 280 return; \ 281 } 282 283 META_COLLECTOR(int_sk_family) 284 { 285 SKIP_NONLOCAL(skb); 286 dst->value = skb->sk->sk_family; 287 } 288 289 META_COLLECTOR(int_sk_state) 290 { 291 SKIP_NONLOCAL(skb); 292 dst->value = skb->sk->sk_state; 293 } 294 295 META_COLLECTOR(int_sk_reuse) 296 { 297 SKIP_NONLOCAL(skb); 298 dst->value = skb->sk->sk_reuse; 299 } 300 301 META_COLLECTOR(int_sk_bound_if) 302 { 303 SKIP_NONLOCAL(skb); 304 /* No error if bound_dev_if is 0, legal userspace check */ 305 dst->value = skb->sk->sk_bound_dev_if; 306 } 307 308 META_COLLECTOR(var_sk_bound_if) 309 { 310 SKIP_NONLOCAL(skb); 311 312 if (skb->sk->sk_bound_dev_if == 0) { 313 dst->value = (unsigned long) "any"; 314 dst->len = 3; 315 } else { 316 struct net_device *dev; 317 318 rcu_read_lock(); 319 dev = dev_get_by_index_rcu(sock_net(skb->sk), 320 skb->sk->sk_bound_dev_if); 321 *err = var_dev(dev, dst); 322 rcu_read_unlock(); 323 } 324 } 325 326 META_COLLECTOR(int_sk_refcnt) 327 { 328 SKIP_NONLOCAL(skb); 329 dst->value = atomic_read(&skb->sk->sk_refcnt); 330 } 331 332 META_COLLECTOR(int_sk_rcvbuf) 333 { 334 SKIP_NONLOCAL(skb); 335 dst->value = skb->sk->sk_rcvbuf; 336 } 337 338 META_COLLECTOR(int_sk_shutdown) 339 { 340 SKIP_NONLOCAL(skb); 341 dst->value = skb->sk->sk_shutdown; 342 } 343 344 META_COLLECTOR(int_sk_proto) 345 { 346 SKIP_NONLOCAL(skb); 347 dst->value = skb->sk->sk_protocol; 348 } 349 350 META_COLLECTOR(int_sk_type) 351 { 352 SKIP_NONLOCAL(skb); 353 dst->value = skb->sk->sk_type; 354 } 355 356 META_COLLECTOR(int_sk_rmem_alloc) 357 { 358 SKIP_NONLOCAL(skb); 359 dst->value = sk_rmem_alloc_get(skb->sk); 360 } 361 362 META_COLLECTOR(int_sk_wmem_alloc) 363 { 364 SKIP_NONLOCAL(skb); 365 dst->value = sk_wmem_alloc_get(skb->sk); 366 } 367 368 META_COLLECTOR(int_sk_omem_alloc) 369 { 370 SKIP_NONLOCAL(skb); 371 dst->value = atomic_read(&skb->sk->sk_omem_alloc); 372 } 373 374 META_COLLECTOR(int_sk_rcv_qlen) 375 { 376 SKIP_NONLOCAL(skb); 377 dst->value = skb->sk->sk_receive_queue.qlen; 378 } 379 380 META_COLLECTOR(int_sk_snd_qlen) 381 { 382 SKIP_NONLOCAL(skb); 383 dst->value = skb->sk->sk_write_queue.qlen; 384 } 385 386 META_COLLECTOR(int_sk_wmem_queued) 387 { 388 SKIP_NONLOCAL(skb); 389 dst->value = skb->sk->sk_wmem_queued; 390 } 391 392 META_COLLECTOR(int_sk_fwd_alloc) 393 { 394 SKIP_NONLOCAL(skb); 395 dst->value = skb->sk->sk_forward_alloc; 396 } 397 398 META_COLLECTOR(int_sk_sndbuf) 399 { 400 SKIP_NONLOCAL(skb); 401 dst->value = skb->sk->sk_sndbuf; 402 } 403 404 META_COLLECTOR(int_sk_alloc) 405 { 406 SKIP_NONLOCAL(skb); 407 dst->value = skb->sk->sk_allocation; 408 } 409 410 META_COLLECTOR(int_sk_route_caps) 411 { 412 SKIP_NONLOCAL(skb); 413 dst->value = skb->sk->sk_route_caps; 414 } 415 416 META_COLLECTOR(int_sk_hash) 417 { 418 SKIP_NONLOCAL(skb); 419 dst->value = skb->sk->sk_hash; 420 } 421 422 META_COLLECTOR(int_sk_lingertime) 423 { 424 SKIP_NONLOCAL(skb); 425 dst->value = skb->sk->sk_lingertime / HZ; 426 } 427 428 META_COLLECTOR(int_sk_err_qlen) 429 { 430 SKIP_NONLOCAL(skb); 431 dst->value = skb->sk->sk_error_queue.qlen; 432 } 433 434 META_COLLECTOR(int_sk_ack_bl) 435 { 436 SKIP_NONLOCAL(skb); 437 dst->value = skb->sk->sk_ack_backlog; 438 } 439 440 META_COLLECTOR(int_sk_max_ack_bl) 441 { 442 SKIP_NONLOCAL(skb); 443 dst->value = skb->sk->sk_max_ack_backlog; 444 } 445 446 META_COLLECTOR(int_sk_prio) 447 { 448 SKIP_NONLOCAL(skb); 449 dst->value = skb->sk->sk_priority; 450 } 451 452 META_COLLECTOR(int_sk_rcvlowat) 453 { 454 SKIP_NONLOCAL(skb); 455 dst->value = skb->sk->sk_rcvlowat; 456 } 457 458 META_COLLECTOR(int_sk_rcvtimeo) 459 { 460 SKIP_NONLOCAL(skb); 461 dst->value = skb->sk->sk_rcvtimeo / HZ; 462 } 463 464 META_COLLECTOR(int_sk_sndtimeo) 465 { 466 SKIP_NONLOCAL(skb); 467 dst->value = skb->sk->sk_sndtimeo / HZ; 468 } 469 470 META_COLLECTOR(int_sk_sendmsg_off) 471 { 472 SKIP_NONLOCAL(skb); 473 dst->value = skb->sk->sk_sndmsg_off; 474 } 475 476 META_COLLECTOR(int_sk_write_pend) 477 { 478 SKIP_NONLOCAL(skb); 479 dst->value = skb->sk->sk_write_pending; 480 } 481 482 /************************************************************************** 483 * Meta value collectors assignment table 484 **************************************************************************/ 485 486 struct meta_ops 487 { 488 void (*get)(struct sk_buff *, struct tcf_pkt_info *, 489 struct meta_value *, struct meta_obj *, int *); 490 }; 491 492 #define META_ID(name) TCF_META_ID_##name 493 #define META_FUNC(name) { .get = meta_##name } 494 495 /* Meta value operations table listing all meta value collectors and 496 * assigns them to a type and meta id. */ 497 static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = { 498 [TCF_META_TYPE_VAR] = { 499 [META_ID(DEV)] = META_FUNC(var_dev), 500 [META_ID(SK_BOUND_IF)] = META_FUNC(var_sk_bound_if), 501 }, 502 [TCF_META_TYPE_INT] = { 503 [META_ID(RANDOM)] = META_FUNC(int_random), 504 [META_ID(LOADAVG_0)] = META_FUNC(int_loadavg_0), 505 [META_ID(LOADAVG_1)] = META_FUNC(int_loadavg_1), 506 [META_ID(LOADAVG_2)] = META_FUNC(int_loadavg_2), 507 [META_ID(DEV)] = META_FUNC(int_dev), 508 [META_ID(PRIORITY)] = META_FUNC(int_priority), 509 [META_ID(PROTOCOL)] = META_FUNC(int_protocol), 510 [META_ID(PKTTYPE)] = META_FUNC(int_pkttype), 511 [META_ID(PKTLEN)] = META_FUNC(int_pktlen), 512 [META_ID(DATALEN)] = META_FUNC(int_datalen), 513 [META_ID(MACLEN)] = META_FUNC(int_maclen), 514 [META_ID(NFMARK)] = META_FUNC(int_mark), 515 [META_ID(TCINDEX)] = META_FUNC(int_tcindex), 516 [META_ID(RTCLASSID)] = META_FUNC(int_rtclassid), 517 [META_ID(RTIIF)] = META_FUNC(int_rtiif), 518 [META_ID(SK_FAMILY)] = META_FUNC(int_sk_family), 519 [META_ID(SK_STATE)] = META_FUNC(int_sk_state), 520 [META_ID(SK_REUSE)] = META_FUNC(int_sk_reuse), 521 [META_ID(SK_BOUND_IF)] = META_FUNC(int_sk_bound_if), 522 [META_ID(SK_REFCNT)] = META_FUNC(int_sk_refcnt), 523 [META_ID(SK_RCVBUF)] = META_FUNC(int_sk_rcvbuf), 524 [META_ID(SK_SNDBUF)] = META_FUNC(int_sk_sndbuf), 525 [META_ID(SK_SHUTDOWN)] = META_FUNC(int_sk_shutdown), 526 [META_ID(SK_PROTO)] = META_FUNC(int_sk_proto), 527 [META_ID(SK_TYPE)] = META_FUNC(int_sk_type), 528 [META_ID(SK_RMEM_ALLOC)] = META_FUNC(int_sk_rmem_alloc), 529 [META_ID(SK_WMEM_ALLOC)] = META_FUNC(int_sk_wmem_alloc), 530 [META_ID(SK_OMEM_ALLOC)] = META_FUNC(int_sk_omem_alloc), 531 [META_ID(SK_WMEM_QUEUED)] = META_FUNC(int_sk_wmem_queued), 532 [META_ID(SK_RCV_QLEN)] = META_FUNC(int_sk_rcv_qlen), 533 [META_ID(SK_SND_QLEN)] = META_FUNC(int_sk_snd_qlen), 534 [META_ID(SK_ERR_QLEN)] = META_FUNC(int_sk_err_qlen), 535 [META_ID(SK_FORWARD_ALLOCS)] = META_FUNC(int_sk_fwd_alloc), 536 [META_ID(SK_ALLOCS)] = META_FUNC(int_sk_alloc), 537 [META_ID(SK_ROUTE_CAPS)] = META_FUNC(int_sk_route_caps), 538 [META_ID(SK_HASH)] = META_FUNC(int_sk_hash), 539 [META_ID(SK_LINGERTIME)] = META_FUNC(int_sk_lingertime), 540 [META_ID(SK_ACK_BACKLOG)] = META_FUNC(int_sk_ack_bl), 541 [META_ID(SK_MAX_ACK_BACKLOG)] = META_FUNC(int_sk_max_ack_bl), 542 [META_ID(SK_PRIO)] = META_FUNC(int_sk_prio), 543 [META_ID(SK_RCVLOWAT)] = META_FUNC(int_sk_rcvlowat), 544 [META_ID(SK_RCVTIMEO)] = META_FUNC(int_sk_rcvtimeo), 545 [META_ID(SK_SNDTIMEO)] = META_FUNC(int_sk_sndtimeo), 546 [META_ID(SK_SENDMSG_OFF)] = META_FUNC(int_sk_sendmsg_off), 547 [META_ID(SK_WRITE_PENDING)] = META_FUNC(int_sk_write_pend), 548 [META_ID(VLAN_TAG)] = META_FUNC(int_vlan_tag), 549 [META_ID(RXHASH)] = META_FUNC(int_rxhash), 550 } 551 }; 552 553 static inline struct meta_ops * meta_ops(struct meta_value *val) 554 { 555 return &__meta_ops[meta_type(val)][meta_id(val)]; 556 } 557 558 /************************************************************************** 559 * Type specific operations for TCF_META_TYPE_VAR 560 **************************************************************************/ 561 562 static int meta_var_compare(struct meta_obj *a, struct meta_obj *b) 563 { 564 int r = a->len - b->len; 565 566 if (r == 0) 567 r = memcmp((void *) a->value, (void *) b->value, a->len); 568 569 return r; 570 } 571 572 static int meta_var_change(struct meta_value *dst, struct nlattr *nla) 573 { 574 int len = nla_len(nla); 575 576 dst->val = (unsigned long)kmemdup(nla_data(nla), len, GFP_KERNEL); 577 if (dst->val == 0UL) 578 return -ENOMEM; 579 dst->len = len; 580 return 0; 581 } 582 583 static void meta_var_destroy(struct meta_value *v) 584 { 585 kfree((void *) v->val); 586 } 587 588 static void meta_var_apply_extras(struct meta_value *v, 589 struct meta_obj *dst) 590 { 591 int shift = v->hdr.shift; 592 593 if (shift && shift < dst->len) 594 dst->len -= shift; 595 } 596 597 static int meta_var_dump(struct sk_buff *skb, struct meta_value *v, int tlv) 598 { 599 if (v->val && v->len) 600 NLA_PUT(skb, tlv, v->len, (void *) v->val); 601 return 0; 602 603 nla_put_failure: 604 return -1; 605 } 606 607 /************************************************************************** 608 * Type specific operations for TCF_META_TYPE_INT 609 **************************************************************************/ 610 611 static int meta_int_compare(struct meta_obj *a, struct meta_obj *b) 612 { 613 /* Let gcc optimize it, the unlikely is not really based on 614 * some numbers but jump free code for mismatches seems 615 * more logical. */ 616 if (unlikely(a->value == b->value)) 617 return 0; 618 else if (a->value < b->value) 619 return -1; 620 else 621 return 1; 622 } 623 624 static int meta_int_change(struct meta_value *dst, struct nlattr *nla) 625 { 626 if (nla_len(nla) >= sizeof(unsigned long)) { 627 dst->val = *(unsigned long *) nla_data(nla); 628 dst->len = sizeof(unsigned long); 629 } else if (nla_len(nla) == sizeof(u32)) { 630 dst->val = nla_get_u32(nla); 631 dst->len = sizeof(u32); 632 } else 633 return -EINVAL; 634 635 return 0; 636 } 637 638 static void meta_int_apply_extras(struct meta_value *v, 639 struct meta_obj *dst) 640 { 641 if (v->hdr.shift) 642 dst->value >>= v->hdr.shift; 643 644 if (v->val) 645 dst->value &= v->val; 646 } 647 648 static int meta_int_dump(struct sk_buff *skb, struct meta_value *v, int tlv) 649 { 650 if (v->len == sizeof(unsigned long)) 651 NLA_PUT(skb, tlv, sizeof(unsigned long), &v->val); 652 else if (v->len == sizeof(u32)) { 653 NLA_PUT_U32(skb, tlv, v->val); 654 } 655 656 return 0; 657 658 nla_put_failure: 659 return -1; 660 } 661 662 /************************************************************************** 663 * Type specific operations table 664 **************************************************************************/ 665 666 struct meta_type_ops 667 { 668 void (*destroy)(struct meta_value *); 669 int (*compare)(struct meta_obj *, struct meta_obj *); 670 int (*change)(struct meta_value *, struct nlattr *); 671 void (*apply_extras)(struct meta_value *, struct meta_obj *); 672 int (*dump)(struct sk_buff *, struct meta_value *, int); 673 }; 674 675 static struct meta_type_ops __meta_type_ops[TCF_META_TYPE_MAX+1] = { 676 [TCF_META_TYPE_VAR] = { 677 .destroy = meta_var_destroy, 678 .compare = meta_var_compare, 679 .change = meta_var_change, 680 .apply_extras = meta_var_apply_extras, 681 .dump = meta_var_dump 682 }, 683 [TCF_META_TYPE_INT] = { 684 .compare = meta_int_compare, 685 .change = meta_int_change, 686 .apply_extras = meta_int_apply_extras, 687 .dump = meta_int_dump 688 } 689 }; 690 691 static inline struct meta_type_ops * meta_type_ops(struct meta_value *v) 692 { 693 return &__meta_type_ops[meta_type(v)]; 694 } 695 696 /************************************************************************** 697 * Core 698 **************************************************************************/ 699 700 static int meta_get(struct sk_buff *skb, struct tcf_pkt_info *info, 701 struct meta_value *v, struct meta_obj *dst) 702 { 703 int err = 0; 704 705 if (meta_id(v) == TCF_META_ID_VALUE) { 706 dst->value = v->val; 707 dst->len = v->len; 708 return 0; 709 } 710 711 meta_ops(v)->get(skb, info, v, dst, &err); 712 if (err < 0) 713 return err; 714 715 if (meta_type_ops(v)->apply_extras) 716 meta_type_ops(v)->apply_extras(v, dst); 717 718 return 0; 719 } 720 721 static int em_meta_match(struct sk_buff *skb, struct tcf_ematch *m, 722 struct tcf_pkt_info *info) 723 { 724 int r; 725 struct meta_match *meta = (struct meta_match *) m->data; 726 struct meta_obj l_value, r_value; 727 728 if (meta_get(skb, info, &meta->lvalue, &l_value) < 0 || 729 meta_get(skb, info, &meta->rvalue, &r_value) < 0) 730 return 0; 731 732 r = meta_type_ops(&meta->lvalue)->compare(&l_value, &r_value); 733 734 switch (meta->lvalue.hdr.op) { 735 case TCF_EM_OPND_EQ: 736 return !r; 737 case TCF_EM_OPND_LT: 738 return r < 0; 739 case TCF_EM_OPND_GT: 740 return r > 0; 741 } 742 743 return 0; 744 } 745 746 static void meta_delete(struct meta_match *meta) 747 { 748 if (meta) { 749 struct meta_type_ops *ops = meta_type_ops(&meta->lvalue); 750 751 if (ops && ops->destroy) { 752 ops->destroy(&meta->lvalue); 753 ops->destroy(&meta->rvalue); 754 } 755 } 756 757 kfree(meta); 758 } 759 760 static inline int meta_change_data(struct meta_value *dst, struct nlattr *nla) 761 { 762 if (nla) { 763 if (nla_len(nla) == 0) 764 return -EINVAL; 765 766 return meta_type_ops(dst)->change(dst, nla); 767 } 768 769 return 0; 770 } 771 772 static inline int meta_is_supported(struct meta_value *val) 773 { 774 return (!meta_id(val) || meta_ops(val)->get); 775 } 776 777 static const struct nla_policy meta_policy[TCA_EM_META_MAX + 1] = { 778 [TCA_EM_META_HDR] = { .len = sizeof(struct tcf_meta_hdr) }, 779 }; 780 781 static int em_meta_change(struct tcf_proto *tp, void *data, int len, 782 struct tcf_ematch *m) 783 { 784 int err; 785 struct nlattr *tb[TCA_EM_META_MAX + 1]; 786 struct tcf_meta_hdr *hdr; 787 struct meta_match *meta = NULL; 788 789 err = nla_parse(tb, TCA_EM_META_MAX, data, len, meta_policy); 790 if (err < 0) 791 goto errout; 792 793 err = -EINVAL; 794 if (tb[TCA_EM_META_HDR] == NULL) 795 goto errout; 796 hdr = nla_data(tb[TCA_EM_META_HDR]); 797 798 if (TCF_META_TYPE(hdr->left.kind) != TCF_META_TYPE(hdr->right.kind) || 799 TCF_META_TYPE(hdr->left.kind) > TCF_META_TYPE_MAX || 800 TCF_META_ID(hdr->left.kind) > TCF_META_ID_MAX || 801 TCF_META_ID(hdr->right.kind) > TCF_META_ID_MAX) 802 goto errout; 803 804 meta = kzalloc(sizeof(*meta), GFP_KERNEL); 805 if (meta == NULL) 806 goto errout; 807 808 memcpy(&meta->lvalue.hdr, &hdr->left, sizeof(hdr->left)); 809 memcpy(&meta->rvalue.hdr, &hdr->right, sizeof(hdr->right)); 810 811 if (!meta_is_supported(&meta->lvalue) || 812 !meta_is_supported(&meta->rvalue)) { 813 err = -EOPNOTSUPP; 814 goto errout; 815 } 816 817 if (meta_change_data(&meta->lvalue, tb[TCA_EM_META_LVALUE]) < 0 || 818 meta_change_data(&meta->rvalue, tb[TCA_EM_META_RVALUE]) < 0) 819 goto errout; 820 821 m->datalen = sizeof(*meta); 822 m->data = (unsigned long) meta; 823 824 err = 0; 825 errout: 826 if (err && meta) 827 meta_delete(meta); 828 return err; 829 } 830 831 static void em_meta_destroy(struct tcf_proto *tp, struct tcf_ematch *m) 832 { 833 if (m) 834 meta_delete((struct meta_match *) m->data); 835 } 836 837 static int em_meta_dump(struct sk_buff *skb, struct tcf_ematch *em) 838 { 839 struct meta_match *meta = (struct meta_match *) em->data; 840 struct tcf_meta_hdr hdr; 841 struct meta_type_ops *ops; 842 843 memset(&hdr, 0, sizeof(hdr)); 844 memcpy(&hdr.left, &meta->lvalue.hdr, sizeof(hdr.left)); 845 memcpy(&hdr.right, &meta->rvalue.hdr, sizeof(hdr.right)); 846 847 NLA_PUT(skb, TCA_EM_META_HDR, sizeof(hdr), &hdr); 848 849 ops = meta_type_ops(&meta->lvalue); 850 if (ops->dump(skb, &meta->lvalue, TCA_EM_META_LVALUE) < 0 || 851 ops->dump(skb, &meta->rvalue, TCA_EM_META_RVALUE) < 0) 852 goto nla_put_failure; 853 854 return 0; 855 856 nla_put_failure: 857 return -1; 858 } 859 860 static struct tcf_ematch_ops em_meta_ops = { 861 .kind = TCF_EM_META, 862 .change = em_meta_change, 863 .match = em_meta_match, 864 .destroy = em_meta_destroy, 865 .dump = em_meta_dump, 866 .owner = THIS_MODULE, 867 .link = LIST_HEAD_INIT(em_meta_ops.link) 868 }; 869 870 static int __init init_em_meta(void) 871 { 872 return tcf_em_register(&em_meta_ops); 873 } 874 875 static void __exit exit_em_meta(void) 876 { 877 tcf_em_unregister(&em_meta_ops); 878 } 879 880 MODULE_LICENSE("GPL"); 881 882 module_init(init_em_meta); 883 module_exit(exit_em_meta); 884 885 MODULE_ALIAS_TCF_EMATCH(TCF_EM_META); 886