1*4dc78e53SAndroid Build Coastguard Worker /* SPDX-License-Identifier: LGPL-2.1-only */
2*4dc78e53SAndroid Build Coastguard Worker /*
3*4dc78e53SAndroid Build Coastguard Worker * Copyright (c) 2018 Avast software
4*4dc78e53SAndroid Build Coastguard Worker */
5*4dc78e53SAndroid Build Coastguard Worker
6*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
7*4dc78e53SAndroid Build Coastguard Worker
8*4dc78e53SAndroid Build Coastguard Worker #include <linux/netlink.h>
9*4dc78e53SAndroid Build Coastguard Worker #include <linux/netfilter/nfnetlink.h>
10*4dc78e53SAndroid Build Coastguard Worker #include <linux/netfilter/nfnetlink_conntrack.h>
11*4dc78e53SAndroid Build Coastguard Worker
12*4dc78e53SAndroid Build Coastguard Worker #include <netlink/cli/utils.h>
13*4dc78e53SAndroid Build Coastguard Worker #include <netlink/cli/ct.h>
14*4dc78e53SAndroid Build Coastguard Worker
15*4dc78e53SAndroid Build Coastguard Worker struct private_nl_object
16*4dc78e53SAndroid Build Coastguard Worker {
17*4dc78e53SAndroid Build Coastguard Worker int ce_refcnt;
18*4dc78e53SAndroid Build Coastguard Worker struct nl_object_ops * ce_ops;
19*4dc78e53SAndroid Build Coastguard Worker struct nl_cache * ce_cache;
20*4dc78e53SAndroid Build Coastguard Worker struct nl_list_head ce_list;
21*4dc78e53SAndroid Build Coastguard Worker int ce_msgtype;
22*4dc78e53SAndroid Build Coastguard Worker int ce_flags;
23*4dc78e53SAndroid Build Coastguard Worker uint64_t ce_mask;
24*4dc78e53SAndroid Build Coastguard Worker };
25*4dc78e53SAndroid Build Coastguard Worker
nf_conntrack_parse_callback(struct nl_object * obj,void * opaque)26*4dc78e53SAndroid Build Coastguard Worker static void nf_conntrack_parse_callback(struct nl_object *obj, void *opaque)
27*4dc78e53SAndroid Build Coastguard Worker {
28*4dc78e53SAndroid Build Coastguard Worker struct nl_dump_params params = {
29*4dc78e53SAndroid Build Coastguard Worker .dp_fd = stdout,
30*4dc78e53SAndroid Build Coastguard Worker .dp_type = NL_DUMP_DETAILS,
31*4dc78e53SAndroid Build Coastguard Worker };
32*4dc78e53SAndroid Build Coastguard Worker
33*4dc78e53SAndroid Build Coastguard Worker nl_object_dump(obj, ¶ms);
34*4dc78e53SAndroid Build Coastguard Worker }
35*4dc78e53SAndroid Build Coastguard Worker
nf_conntrack_event_callback(struct nl_msg * msg,void * opaque)36*4dc78e53SAndroid Build Coastguard Worker static int nf_conntrack_event_callback(struct nl_msg *msg, void *opaque)
37*4dc78e53SAndroid Build Coastguard Worker {
38*4dc78e53SAndroid Build Coastguard Worker int err;
39*4dc78e53SAndroid Build Coastguard Worker struct nlmsghdr *hdr = nlmsg_hdr(msg);
40*4dc78e53SAndroid Build Coastguard Worker
41*4dc78e53SAndroid Build Coastguard Worker enum cntl_msg_types type = (enum cntl_msg_types) NFNL_MSG_TYPE(hdr->nlmsg_type);
42*4dc78e53SAndroid Build Coastguard Worker
43*4dc78e53SAndroid Build Coastguard Worker int flags = hdr->nlmsg_flags;
44*4dc78e53SAndroid Build Coastguard Worker
45*4dc78e53SAndroid Build Coastguard Worker if (type == IPCTNL_MSG_CT_DELETE) {
46*4dc78e53SAndroid Build Coastguard Worker printf("DELETE ");
47*4dc78e53SAndroid Build Coastguard Worker } else if (type == IPCTNL_MSG_CT_NEW) {
48*4dc78e53SAndroid Build Coastguard Worker if (flags & (NLM_F_CREATE|NLM_F_EXCL)) {
49*4dc78e53SAndroid Build Coastguard Worker printf("NEW ");
50*4dc78e53SAndroid Build Coastguard Worker } else {
51*4dc78e53SAndroid Build Coastguard Worker printf("UPDATE ");
52*4dc78e53SAndroid Build Coastguard Worker }
53*4dc78e53SAndroid Build Coastguard Worker } else {
54*4dc78e53SAndroid Build Coastguard Worker printf("UNKNOWN ");
55*4dc78e53SAndroid Build Coastguard Worker }
56*4dc78e53SAndroid Build Coastguard Worker
57*4dc78e53SAndroid Build Coastguard Worker if ((err = nl_msg_parse(msg, &nf_conntrack_parse_callback, opaque)) < 0) {
58*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(err, "nl_msg_parse: %s", nl_geterror(err));
59*4dc78e53SAndroid Build Coastguard Worker }
60*4dc78e53SAndroid Build Coastguard Worker /* Continue with next event */
61*4dc78e53SAndroid Build Coastguard Worker return NL_OK;
62*4dc78e53SAndroid Build Coastguard Worker }
63*4dc78e53SAndroid Build Coastguard Worker
main(int argc,char * argv[])64*4dc78e53SAndroid Build Coastguard Worker int main(int argc, char *argv[])
65*4dc78e53SAndroid Build Coastguard Worker {
66*4dc78e53SAndroid Build Coastguard Worker struct nl_sock *socket;
67*4dc78e53SAndroid Build Coastguard Worker int err;
68*4dc78e53SAndroid Build Coastguard Worker
69*4dc78e53SAndroid Build Coastguard Worker socket = nl_cli_alloc_socket();
70*4dc78e53SAndroid Build Coastguard Worker if (socket == NULL) {
71*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(ENOBUFS, "Unable to allocate netlink socket");
72*4dc78e53SAndroid Build Coastguard Worker }
73*4dc78e53SAndroid Build Coastguard Worker
74*4dc78e53SAndroid Build Coastguard Worker /*
75*4dc78e53SAndroid Build Coastguard Worker * Disable sequence number checking.
76*4dc78e53SAndroid Build Coastguard Worker * This is required to allow messages to be processed which were not requested by
77*4dc78e53SAndroid Build Coastguard Worker * a preceding request message, e.g. netlink events.
78*4dc78e53SAndroid Build Coastguard Worker */
79*4dc78e53SAndroid Build Coastguard Worker nl_socket_disable_seq_check(socket);
80*4dc78e53SAndroid Build Coastguard Worker
81*4dc78e53SAndroid Build Coastguard Worker /* subscribe conntrack events */
82*4dc78e53SAndroid Build Coastguard Worker nl_join_groups(socket, NF_NETLINK_CONNTRACK_NEW |
83*4dc78e53SAndroid Build Coastguard Worker NF_NETLINK_CONNTRACK_UPDATE |
84*4dc78e53SAndroid Build Coastguard Worker NF_NETLINK_CONNTRACK_DESTROY |
85*4dc78e53SAndroid Build Coastguard Worker NF_NETLINK_CONNTRACK_EXP_NEW |
86*4dc78e53SAndroid Build Coastguard Worker NF_NETLINK_CONNTRACK_EXP_UPDATE |
87*4dc78e53SAndroid Build Coastguard Worker NF_NETLINK_CONNTRACK_EXP_DESTROY);
88*4dc78e53SAndroid Build Coastguard Worker
89*4dc78e53SAndroid Build Coastguard Worker nl_cli_connect(socket, NETLINK_NETFILTER);
90*4dc78e53SAndroid Build Coastguard Worker
91*4dc78e53SAndroid Build Coastguard Worker nl_socket_modify_cb(socket, NL_CB_VALID, NL_CB_CUSTOM, &nf_conntrack_event_callback, 0);
92*4dc78e53SAndroid Build Coastguard Worker
93*4dc78e53SAndroid Build Coastguard Worker while (1) {
94*4dc78e53SAndroid Build Coastguard Worker
95*4dc78e53SAndroid Build Coastguard Worker errno = 0;
96*4dc78e53SAndroid Build Coastguard Worker if ((err = nl_recvmsgs_default(socket)) < 0) {
97*4dc78e53SAndroid Build Coastguard Worker switch (errno) {
98*4dc78e53SAndroid Build Coastguard Worker case ENOBUFS:
99*4dc78e53SAndroid Build Coastguard Worker // just print warning
100*4dc78e53SAndroid Build Coastguard Worker fprintf(stderr, "Lost events because of ENOBUFS\n");
101*4dc78e53SAndroid Build Coastguard Worker break;
102*4dc78e53SAndroid Build Coastguard Worker case EAGAIN:
103*4dc78e53SAndroid Build Coastguard Worker case EINTR:
104*4dc78e53SAndroid Build Coastguard Worker // continue reading
105*4dc78e53SAndroid Build Coastguard Worker break;
106*4dc78e53SAndroid Build Coastguard Worker default:
107*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(err, "Failed to receive: %s", nl_geterror(err));
108*4dc78e53SAndroid Build Coastguard Worker }
109*4dc78e53SAndroid Build Coastguard Worker }
110*4dc78e53SAndroid Build Coastguard Worker }
111*4dc78e53SAndroid Build Coastguard Worker }
112