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