1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * net/sched/em_nbyte.c N-Byte ematch 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 5*1da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License 6*1da177e4SLinus Torvalds * as published by the Free Software Foundation; either version 7*1da177e4SLinus Torvalds * 2 of the License, or (at your option) any later version. 8*1da177e4SLinus Torvalds * 9*1da177e4SLinus Torvalds * Authors: Thomas Graf <tgraf@suug.ch> 10*1da177e4SLinus Torvalds */ 11*1da177e4SLinus Torvalds 12*1da177e4SLinus Torvalds #include <linux/config.h> 13*1da177e4SLinus Torvalds #include <linux/module.h> 14*1da177e4SLinus Torvalds #include <linux/types.h> 15*1da177e4SLinus Torvalds #include <linux/kernel.h> 16*1da177e4SLinus Torvalds #include <linux/sched.h> 17*1da177e4SLinus Torvalds #include <linux/string.h> 18*1da177e4SLinus Torvalds #include <linux/skbuff.h> 19*1da177e4SLinus Torvalds #include <linux/tc_ematch/tc_em_nbyte.h> 20*1da177e4SLinus Torvalds #include <net/pkt_cls.h> 21*1da177e4SLinus Torvalds 22*1da177e4SLinus Torvalds struct nbyte_data 23*1da177e4SLinus Torvalds { 24*1da177e4SLinus Torvalds struct tcf_em_nbyte hdr; 25*1da177e4SLinus Torvalds char pattern[0]; 26*1da177e4SLinus Torvalds }; 27*1da177e4SLinus Torvalds 28*1da177e4SLinus Torvalds static int em_nbyte_change(struct tcf_proto *tp, void *data, int data_len, 29*1da177e4SLinus Torvalds struct tcf_ematch *em) 30*1da177e4SLinus Torvalds { 31*1da177e4SLinus Torvalds struct tcf_em_nbyte *nbyte = data; 32*1da177e4SLinus Torvalds 33*1da177e4SLinus Torvalds if (data_len < sizeof(*nbyte) || 34*1da177e4SLinus Torvalds data_len < (sizeof(*nbyte) + nbyte->len)) 35*1da177e4SLinus Torvalds return -EINVAL; 36*1da177e4SLinus Torvalds 37*1da177e4SLinus Torvalds em->datalen = sizeof(*nbyte) + nbyte->len; 38*1da177e4SLinus Torvalds em->data = (unsigned long) kmalloc(em->datalen, GFP_KERNEL); 39*1da177e4SLinus Torvalds if (em->data == 0UL) 40*1da177e4SLinus Torvalds return -ENOBUFS; 41*1da177e4SLinus Torvalds 42*1da177e4SLinus Torvalds memcpy((void *) em->data, data, em->datalen); 43*1da177e4SLinus Torvalds 44*1da177e4SLinus Torvalds return 0; 45*1da177e4SLinus Torvalds } 46*1da177e4SLinus Torvalds 47*1da177e4SLinus Torvalds static int em_nbyte_match(struct sk_buff *skb, struct tcf_ematch *em, 48*1da177e4SLinus Torvalds struct tcf_pkt_info *info) 49*1da177e4SLinus Torvalds { 50*1da177e4SLinus Torvalds struct nbyte_data *nbyte = (struct nbyte_data *) em->data; 51*1da177e4SLinus Torvalds unsigned char *ptr = tcf_get_base_ptr(skb, nbyte->hdr.layer); 52*1da177e4SLinus Torvalds 53*1da177e4SLinus Torvalds ptr += nbyte->hdr.off; 54*1da177e4SLinus Torvalds 55*1da177e4SLinus Torvalds if (!tcf_valid_offset(skb, ptr, nbyte->hdr.len)) 56*1da177e4SLinus Torvalds return 0; 57*1da177e4SLinus Torvalds 58*1da177e4SLinus Torvalds return !memcmp(ptr + nbyte->hdr.off, nbyte->pattern, nbyte->hdr.len); 59*1da177e4SLinus Torvalds } 60*1da177e4SLinus Torvalds 61*1da177e4SLinus Torvalds static struct tcf_ematch_ops em_nbyte_ops = { 62*1da177e4SLinus Torvalds .kind = TCF_EM_NBYTE, 63*1da177e4SLinus Torvalds .change = em_nbyte_change, 64*1da177e4SLinus Torvalds .match = em_nbyte_match, 65*1da177e4SLinus Torvalds .owner = THIS_MODULE, 66*1da177e4SLinus Torvalds .link = LIST_HEAD_INIT(em_nbyte_ops.link) 67*1da177e4SLinus Torvalds }; 68*1da177e4SLinus Torvalds 69*1da177e4SLinus Torvalds static int __init init_em_nbyte(void) 70*1da177e4SLinus Torvalds { 71*1da177e4SLinus Torvalds return tcf_em_register(&em_nbyte_ops); 72*1da177e4SLinus Torvalds } 73*1da177e4SLinus Torvalds 74*1da177e4SLinus Torvalds static void __exit exit_em_nbyte(void) 75*1da177e4SLinus Torvalds { 76*1da177e4SLinus Torvalds tcf_em_unregister(&em_nbyte_ops); 77*1da177e4SLinus Torvalds } 78*1da177e4SLinus Torvalds 79*1da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 80*1da177e4SLinus Torvalds 81*1da177e4SLinus Torvalds module_init(init_em_nbyte); 82*1da177e4SLinus Torvalds module_exit(exit_em_nbyte); 83