/* * netfilter module to enforce network quotas * * Sam Johnston */ #include #include #include #include #include #include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Sam Johnston "); static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED; static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, int offset, int *hotdrop) { struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo; unsigned int datalen; if (skb->len < sizeof(struct iphdr)) return NF_ACCEPT; datalen = skb->len - skb->nh.iph->ihl*4; spin_lock_bh("a_lock); if (q->quota >= datalen) { /* we can afford this one */ q->quota -= datalen; spin_unlock_bh("a_lock); #ifdef DEBUG_IPT_QUOTA printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen); #endif return 1; } /* so we do not allow even small packets from now on */ q->quota = 0; #ifdef DEBUG_IPT_QUOTA printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen); #endif spin_unlock_bh("a_lock); return 0; } static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { /* TODO: spinlocks? sanity checks? */ if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info))) return 0; return 1; } static struct ipt_match quota_match = { .name = "quota", .match = match, .checkentry = checkentry, .me = THIS_MODULE }; static int __init init(void) { return ipt_register_match("a_match); } static void __exit fini(void) { ipt_unregister_match("a_match); } module_init(init); module_exit(fini);