xref: /aosp_15_r20/external/libnl/src/nf-ct-events.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
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, &params);
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