blob: 5c62dcc23df106e427601af388f20d08e9b80e04 [file] [log] [blame]
Kyle Swenson7900a3c2021-08-12 14:34:44 -06001/* cdu_xt_target.c
2 *
3 * This file defines client data usage xtables target.
4 *
5 * Author: Cradlepoint Technology, Inc. <source@cradlepoint.com>
6 * Adrian Sitterle <asitterle@cradlepoint.com>
7 *
8 * Copyright (C) 2019 Cradlepoint Technology, Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19
20#include <linux/version.h>
21#include <linux/types.h>
22#include <linux/kernel.h>
Kyle Swenson7900a3c2021-08-12 14:34:44 -060023#include <linux/netfilter/x_tables.h>
24#include <net/netfilter/nf_conntrack.h>
25#include <net/netfilter/nf_conntrack_core.h>
26#include <linux/netfilter/nf_conntrack_common.h>
27#include <linux/etherdevice.h>
28
29
30#include "cdu_types.h"
31#include "cdu_xt_target.h"
32#include "cdu_nf_events.h"
33#include "cdu_seq_file.h"
34#include "cdu_db.h"
35
36static unsigned int usage_tg(struct sk_buff *skb, const struct xt_action_param *par)
37{
38 struct nf_conn *ct;
39 enum ip_conntrack_info ctinfo;
40 const struct xt_usage_tginfo *info = par->targinfo;
41 unsigned char direction = (info->src == 1);
42
43 ct = nf_ct_get(skb, &ctinfo);
44 if (unlikely(!ct))
45 return XT_CONTINUE;
46
47 if (likely(ct->orig_direction != CDU_DIR_NOT_SET))
48 return XT_CONTINUE;
49
50 if (direction) {
51
52 if (ctinfo == IP_CT_NEW)
53 ct->orig_direction = CDU_DIR_SRC;
54 else if (ctinfo == IP_CT_IS_REPLY)
55 ct->orig_direction = CDU_DIR_DEST;
56 else
57 return XT_CONTINUE;
58
59 ether_addr_copy(ct->mac, eth_hdr(skb)->h_source);
60
61 cdu_db_add_entry_ifmissing(ct);
62 }
63
64
65 return XT_CONTINUE;
66}
67
68static int xt_usage_check(const struct xt_tgchk_param *par)
69{
70 struct xt_usage_tginfo *info = par->targinfo;
71
72 if (!info->priv) {
73 info->priv = cdu_seq_file_create(info->name, info->readreset);
74 if (!info->priv)
75 return -ENOMEM;
76 cdu_nf_events_register();
77 }
78
79 (info->priv->usecount)++;
80
81 return 0;
82}
83
84static void xt_usage_destroy(const struct xt_tgdtor_param *par)
85{
86 struct xt_usage_tginfo *info = par->targinfo;
87
88 if (info->priv) {
89 CDU_DEBUG("usecount=%u\n", info->priv->usecount);
90 (info->priv->usecount)--;
91 if (info->priv->usecount <= 0) {
92 cdu_seq_file_destroy(info->priv);
93 info->priv = NULL;
94 cdu_nf_events_unregister();
95 }
96 }
97}
98
99static struct xt_target usage_tg_reg __read_mostly = {
100 .name = "USAGE",
101 .revision = 0,
102 .family = NFPROTO_UNSPEC,
103 .target = usage_tg,
104 .checkentry = xt_usage_check,
105 .destroy = xt_usage_destroy,
106 .targetsize = sizeof(struct xt_usage_tginfo),
107 .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_IN) |
108 (1 << NF_INET_FORWARD) | (1 << NF_INET_POST_ROUTING) |
109 (1 << NF_INET_LOCAL_OUT),
110 .me = THIS_MODULE,
111};
112
113int cdu_xt_target_register(void)
114{
115 int result = xt_register_target(&usage_tg_reg);
116
117 if (result < 0) {
118 CDU_INFO("Failed to register xt target notifier %d\n", result);
119 return result;
120 }
121 CDU_DEBUG("initialized\n");
122 return 0;
123}
124
125void cdu_xt_target_unregister(void)
126{
127 xt_unregister_target(&usage_tg_reg);
128 CDU_DEBUG("uninitialized\n");
129}