Kyle Swenson | 7900a3c | 2021-08-12 14:34:44 -0600 | [diff] [blame] | 1 | /* cdu_nf_events.c |
| 2 | * |
| 3 | * This file handles client data usage netfilter conntrack events. |
| 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> |
| 23 | #include <linux/module.h> |
Kyle Swenson | 9e092e9 | 2024-01-15 11:57:45 -0700 | [diff] [blame^] | 24 | #include <linux/netfilter/x_tables.h> |
Kyle Swenson | 7900a3c | 2021-08-12 14:34:44 -0600 | [diff] [blame] | 25 | #include <net/netfilter/nf_conntrack.h> |
| 26 | #include <net/netfilter/nf_conntrack_core.h> |
| 27 | |
| 28 | #include "cdu_db.h" |
| 29 | #include "cdu_nf_events.h" |
| 30 | #include "cdu_xt_target.h" |
| 31 | #include "cdu_types.h" |
| 32 | |
| 33 | #ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS |
| 34 | #error Can not use this module without conntrack events |
| 35 | #endif |
| 36 | |
| 37 | static u_int8_t nf_registered; |
| 38 | |
| 39 | static int cdu_nf_event(struct notifier_block *this, unsigned long events, void *ptr) |
| 40 | { |
| 41 | struct nf_ct_event *item = (struct nf_ct_event *)ptr; |
| 42 | struct nf_conn *ct = item->ct; |
| 43 | |
| 44 | if (!ct) { |
| 45 | CDU_DEBUG("No ct available\n"); |
| 46 | return -EINVAL; |
| 47 | } |
| 48 | |
| 49 | if (ct->orig_direction == CDU_DIR_NOT_SET) { |
| 50 | /* This ct does not have a direction information because it didn't |
| 51 | * travel through the xt hook, which means that we don't care |
| 52 | * about this traffic |
| 53 | */ |
| 54 | return NOTIFY_DONE; |
| 55 | } |
| 56 | |
| 57 | /* Update data usage htable entry on end of flow trigger */ |
| 58 | if (events & (1 << IPCT_DESTROY)) { |
| 59 | CDU_DEBUG("Caught %s NF event. mac=%pM, dir %s, ct %p\n", |
| 60 | events & (1 << IPCT_NEW)?"NEW":"DESTROY", ct->mac, |
| 61 | (ct->orig_direction == CDU_DIR_SRC)?"DIR_SRC":"DIR_DEST", ct); |
| 62 | |
| 63 | cdu_db_update_entry(ct, CDU_DB_UPDATE_PERMA_SET, CDU_DB_CONNTR_NOCLEAR); |
| 64 | } |
| 65 | |
| 66 | return NOTIFY_DONE; |
| 67 | } |
| 68 | |
| 69 | static struct notifier_block cdu_nf_notifier = { |
| 70 | .notifier_call = cdu_nf_event, |
| 71 | }; |
| 72 | |
| 73 | int cdu_nf_events_register(void) |
| 74 | { |
| 75 | int result; |
| 76 | |
| 77 | if (!nf_registered) { |
| 78 | result = nf_conntrack_register_notifier(&init_net, &cdu_nf_notifier); |
| 79 | if (result < 0) { |
| 80 | CDU_INFO("Failed to register conntrack notifier %d\n", result); |
| 81 | return result; |
| 82 | } |
| 83 | nf_registered = 1; |
| 84 | } |
| 85 | |
| 86 | CDU_DEBUG("initialized\n"); |
| 87 | return 0; |
| 88 | } |
| 89 | |
| 90 | void cdu_nf_events_unregister(void) |
| 91 | { |
| 92 | if (nf_registered) { |
| 93 | nf_conntrack_unregister_notifier(&init_net, &cdu_nf_notifier); |
| 94 | CDU_DEBUG("uninitialized\n"); |
| 95 | } |
| 96 | } |
| 97 | |