xref: /aosp_15_r20/external/libnl/tests/test-cache-mngr.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 #include "nl-default.h"
4*4dc78e53SAndroid Build Coastguard Worker 
5*4dc78e53SAndroid Build Coastguard Worker #include <signal.h>
6*4dc78e53SAndroid Build Coastguard Worker #include <sys/time.h>
7*4dc78e53SAndroid Build Coastguard Worker #include <time.h>
8*4dc78e53SAndroid Build Coastguard Worker 
9*4dc78e53SAndroid Build Coastguard Worker #include <linux/netlink.h>
10*4dc78e53SAndroid Build Coastguard Worker 
11*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
12*4dc78e53SAndroid Build Coastguard Worker #include <netlink/cache.h>
13*4dc78e53SAndroid Build Coastguard Worker #include <netlink/cli/utils.h>
14*4dc78e53SAndroid Build Coastguard Worker 
15*4dc78e53SAndroid Build Coastguard Worker static int quit = 0;
16*4dc78e53SAndroid Build Coastguard Worker static int change = 1;
17*4dc78e53SAndroid Build Coastguard Worker static int print_ts = 0;
18*4dc78e53SAndroid Build Coastguard Worker 
19*4dc78e53SAndroid Build Coastguard Worker static struct nl_dump_params params = {
20*4dc78e53SAndroid Build Coastguard Worker 	.dp_type = NL_DUMP_LINE,
21*4dc78e53SAndroid Build Coastguard Worker };
22*4dc78e53SAndroid Build Coastguard Worker 
23*4dc78e53SAndroid Build Coastguard Worker 
print_timestamp(FILE * fp)24*4dc78e53SAndroid Build Coastguard Worker static void print_timestamp(FILE *fp)
25*4dc78e53SAndroid Build Coastguard Worker {
26*4dc78e53SAndroid Build Coastguard Worker 	struct timeval tv;
27*4dc78e53SAndroid Build Coastguard Worker 	char tshort[40];
28*4dc78e53SAndroid Build Coastguard Worker 	struct tm *tm;
29*4dc78e53SAndroid Build Coastguard Worker 	struct tm tm_buf;
30*4dc78e53SAndroid Build Coastguard Worker 
31*4dc78e53SAndroid Build Coastguard Worker 	gettimeofday(&tv, NULL);
32*4dc78e53SAndroid Build Coastguard Worker 	tm = localtime_r(&tv.tv_sec, &tm_buf);
33*4dc78e53SAndroid Build Coastguard Worker 
34*4dc78e53SAndroid Build Coastguard Worker 	strftime(tshort, sizeof(tshort), "%Y-%m-%dT%H:%M:%S", tm);
35*4dc78e53SAndroid Build Coastguard Worker 	fprintf(fp, "[%s.%06ld] ", tshort, tv.tv_usec);
36*4dc78e53SAndroid Build Coastguard Worker }
37*4dc78e53SAndroid Build Coastguard Worker 
change_cb(struct nl_cache * cache,struct nl_object * obj,int action,void * data)38*4dc78e53SAndroid Build Coastguard Worker static void change_cb(struct nl_cache *cache, struct nl_object *obj,
39*4dc78e53SAndroid Build Coastguard Worker 		      int action, void *data)
40*4dc78e53SAndroid Build Coastguard Worker {
41*4dc78e53SAndroid Build Coastguard Worker 	if (print_ts)
42*4dc78e53SAndroid Build Coastguard Worker 		print_timestamp(stdout);
43*4dc78e53SAndroid Build Coastguard Worker 
44*4dc78e53SAndroid Build Coastguard Worker 	if (action == NL_ACT_NEW)
45*4dc78e53SAndroid Build Coastguard Worker 		printf("NEW ");
46*4dc78e53SAndroid Build Coastguard Worker 	else if (action == NL_ACT_DEL)
47*4dc78e53SAndroid Build Coastguard Worker 		printf("DEL ");
48*4dc78e53SAndroid Build Coastguard Worker 	else if (action == NL_ACT_CHANGE)
49*4dc78e53SAndroid Build Coastguard Worker 		printf("CHANGE ");
50*4dc78e53SAndroid Build Coastguard Worker 
51*4dc78e53SAndroid Build Coastguard Worker 	nl_object_dump(obj, &params);
52*4dc78e53SAndroid Build Coastguard Worker 	fflush(stdout);
53*4dc78e53SAndroid Build Coastguard Worker 
54*4dc78e53SAndroid Build Coastguard Worker 	change = 1;
55*4dc78e53SAndroid Build Coastguard Worker }
56*4dc78e53SAndroid Build Coastguard Worker 
sigint(int arg)57*4dc78e53SAndroid Build Coastguard Worker static void sigint(int arg)
58*4dc78e53SAndroid Build Coastguard Worker {
59*4dc78e53SAndroid Build Coastguard Worker 	quit = 1;
60*4dc78e53SAndroid Build Coastguard Worker }
61*4dc78e53SAndroid Build Coastguard Worker 
print_usage(FILE * stream,const char * name)62*4dc78e53SAndroid Build Coastguard Worker static void print_usage(FILE* stream, const char *name)
63*4dc78e53SAndroid Build Coastguard Worker {
64*4dc78e53SAndroid Build Coastguard Worker 	fprintf(stream,
65*4dc78e53SAndroid Build Coastguard Worker 		"Usage: %s [OPTIONS]... <cache name>... \n"
66*4dc78e53SAndroid Build Coastguard Worker 		"\n"
67*4dc78e53SAndroid Build Coastguard Worker 		"OPTIONS\n"
68*4dc78e53SAndroid Build Coastguard Worker 		" -f, --format=TYPE      Output format { brief | details | stats }\n"
69*4dc78e53SAndroid Build Coastguard Worker 		"                        Default: brief\n"
70*4dc78e53SAndroid Build Coastguard Worker 		" -d, --dump             Dump cache content after a change.\n"
71*4dc78e53SAndroid Build Coastguard Worker 		" -i, --interval=TIME    Dump cache content after TIME seconds when there is no\n"
72*4dc78e53SAndroid Build Coastguard Worker 		"                        change; 0 to disable. Default: 1\n"
73*4dc78e53SAndroid Build Coastguard Worker 		" -I, --iter             Iterate over all address families when updating caches.\n"
74*4dc78e53SAndroid Build Coastguard Worker 		" -t, --tshort           Print a short timestamp before change messages.\n"
75*4dc78e53SAndroid Build Coastguard Worker 		" -h, --help             Show this help text.\n"
76*4dc78e53SAndroid Build Coastguard Worker 		, name);
77*4dc78e53SAndroid Build Coastguard Worker }
78*4dc78e53SAndroid Build Coastguard Worker 
main(int argc,char * argv[])79*4dc78e53SAndroid Build Coastguard Worker int main(int argc, char *argv[])
80*4dc78e53SAndroid Build Coastguard Worker {
81*4dc78e53SAndroid Build Coastguard Worker 	bool dump_on_change = false, dump_on_timeout = true, iter = false;
82*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache_mngr *mngr;
83*4dc78e53SAndroid Build Coastguard Worker 	int timeout = 1000, err;
84*4dc78e53SAndroid Build Coastguard Worker 
85*4dc78e53SAndroid Build Coastguard Worker 	for (;;) {
86*4dc78e53SAndroid Build Coastguard Worker 		static struct option long_opts[] = {
87*4dc78e53SAndroid Build Coastguard Worker 			{ "format", required_argument, 0, 'f' },
88*4dc78e53SAndroid Build Coastguard Worker 			{ "dump", no_argument, 0, 'd' },
89*4dc78e53SAndroid Build Coastguard Worker 			{ "interval", required_argument, 0, 'i' },
90*4dc78e53SAndroid Build Coastguard Worker 			{ "iter", no_argument, 0, 'I' },
91*4dc78e53SAndroid Build Coastguard Worker 			{ "tshort", no_argument, 0, 't' },
92*4dc78e53SAndroid Build Coastguard Worker 			{ "help", 0, 0, 'h' },
93*4dc78e53SAndroid Build Coastguard Worker 			{ 0, 0, 0, 0 }
94*4dc78e53SAndroid Build Coastguard Worker 		};
95*4dc78e53SAndroid Build Coastguard Worker 		int c;
96*4dc78e53SAndroid Build Coastguard Worker 
97*4dc78e53SAndroid Build Coastguard Worker 		c = getopt_long(argc, argv, "hf:di:It", long_opts, NULL);
98*4dc78e53SAndroid Build Coastguard Worker 		if (c == -1)
99*4dc78e53SAndroid Build Coastguard Worker 			break;
100*4dc78e53SAndroid Build Coastguard Worker 
101*4dc78e53SAndroid Build Coastguard Worker 		switch (c) {
102*4dc78e53SAndroid Build Coastguard Worker 			char *endptr;
103*4dc78e53SAndroid Build Coastguard Worker 			long interval;
104*4dc78e53SAndroid Build Coastguard Worker 
105*4dc78e53SAndroid Build Coastguard Worker 		case 'f':
106*4dc78e53SAndroid Build Coastguard Worker 			params.dp_type = nl_cli_parse_dumptype(optarg);
107*4dc78e53SAndroid Build Coastguard Worker 			break;
108*4dc78e53SAndroid Build Coastguard Worker 
109*4dc78e53SAndroid Build Coastguard Worker 		case 'd':
110*4dc78e53SAndroid Build Coastguard Worker 			dump_on_change = true;
111*4dc78e53SAndroid Build Coastguard Worker 			break;
112*4dc78e53SAndroid Build Coastguard Worker 
113*4dc78e53SAndroid Build Coastguard Worker 		case 'i':
114*4dc78e53SAndroid Build Coastguard Worker 			errno = 0;
115*4dc78e53SAndroid Build Coastguard Worker 			interval = strtol(optarg, &endptr, 0);
116*4dc78e53SAndroid Build Coastguard Worker 			if (interval < 0 || errno || *endptr) {
117*4dc78e53SAndroid Build Coastguard Worker 				nl_cli_fatal(EINVAL, "Invalid interval \"%s\".\n",
118*4dc78e53SAndroid Build Coastguard Worker 					     optarg);
119*4dc78e53SAndroid Build Coastguard Worker 				exit(1);
120*4dc78e53SAndroid Build Coastguard Worker 			}
121*4dc78e53SAndroid Build Coastguard Worker 			if (!interval) {
122*4dc78e53SAndroid Build Coastguard Worker 				dump_on_timeout = false;
123*4dc78e53SAndroid Build Coastguard Worker 			} else {
124*4dc78e53SAndroid Build Coastguard Worker 				timeout = interval * 1000;
125*4dc78e53SAndroid Build Coastguard Worker 			}
126*4dc78e53SAndroid Build Coastguard Worker 
127*4dc78e53SAndroid Build Coastguard Worker 			break;
128*4dc78e53SAndroid Build Coastguard Worker 
129*4dc78e53SAndroid Build Coastguard Worker 		case 'I':
130*4dc78e53SAndroid Build Coastguard Worker 			iter = true;
131*4dc78e53SAndroid Build Coastguard Worker 			break;
132*4dc78e53SAndroid Build Coastguard Worker 
133*4dc78e53SAndroid Build Coastguard Worker 		case 't':
134*4dc78e53SAndroid Build Coastguard Worker 			print_ts = true;
135*4dc78e53SAndroid Build Coastguard Worker 			break;
136*4dc78e53SAndroid Build Coastguard Worker 
137*4dc78e53SAndroid Build Coastguard Worker 		case 'h':
138*4dc78e53SAndroid Build Coastguard Worker 			print_usage(stdout, argv[0]);
139*4dc78e53SAndroid Build Coastguard Worker 			exit(0);
140*4dc78e53SAndroid Build Coastguard Worker 
141*4dc78e53SAndroid Build Coastguard Worker 		case '?':
142*4dc78e53SAndroid Build Coastguard Worker 			print_usage(stderr, argv[0]);
143*4dc78e53SAndroid Build Coastguard Worker 			exit(1);
144*4dc78e53SAndroid Build Coastguard Worker 		}
145*4dc78e53SAndroid Build Coastguard Worker 	}
146*4dc78e53SAndroid Build Coastguard Worker 
147*4dc78e53SAndroid Build Coastguard Worker 	err = nl_cache_mngr_alloc(NULL, NETLINK_ROUTE, NL_AUTO_PROVIDE, &mngr);
148*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
149*4dc78e53SAndroid Build Coastguard Worker 		nl_cli_fatal(err, "Unable to allocate cache manager: %s",
150*4dc78e53SAndroid Build Coastguard Worker 			     nl_geterror(err));
151*4dc78e53SAndroid Build Coastguard Worker 
152*4dc78e53SAndroid Build Coastguard Worker 	while (optind < argc) {
153*4dc78e53SAndroid Build Coastguard Worker 		struct nl_cache *cache;
154*4dc78e53SAndroid Build Coastguard Worker 
155*4dc78e53SAndroid Build Coastguard Worker 		err = nl_cache_alloc_name(argv[optind], &cache);
156*4dc78e53SAndroid Build Coastguard Worker 		if (err < 0)
157*4dc78e53SAndroid Build Coastguard Worker 			nl_cli_fatal(err, "Couldn't add cache %s: %s\n",
158*4dc78e53SAndroid Build Coastguard Worker 				     argv[optind], nl_geterror(err));
159*4dc78e53SAndroid Build Coastguard Worker 
160*4dc78e53SAndroid Build Coastguard Worker 		if (iter)
161*4dc78e53SAndroid Build Coastguard Worker 			nl_cache_set_flags(cache, NL_CACHE_AF_ITER);
162*4dc78e53SAndroid Build Coastguard Worker 
163*4dc78e53SAndroid Build Coastguard Worker 		err = nl_cache_mngr_add_cache(mngr, cache, &change_cb, NULL);
164*4dc78e53SAndroid Build Coastguard Worker 		if (err < 0)
165*4dc78e53SAndroid Build Coastguard Worker 			nl_cli_fatal(err, "Unable to add cache %s: %s",
166*4dc78e53SAndroid Build Coastguard Worker 				     argv[optind], nl_geterror(err));
167*4dc78e53SAndroid Build Coastguard Worker 
168*4dc78e53SAndroid Build Coastguard Worker 		optind++;
169*4dc78e53SAndroid Build Coastguard Worker 	}
170*4dc78e53SAndroid Build Coastguard Worker 
171*4dc78e53SAndroid Build Coastguard Worker 	params.dp_fd = stdout;
172*4dc78e53SAndroid Build Coastguard Worker 	signal(SIGINT, sigint);
173*4dc78e53SAndroid Build Coastguard Worker 
174*4dc78e53SAndroid Build Coastguard Worker 	while (!quit) {
175*4dc78e53SAndroid Build Coastguard Worker 		err = nl_cache_mngr_poll(mngr, timeout);
176*4dc78e53SAndroid Build Coastguard Worker 		if (err < 0 && err != -NLE_INTR)
177*4dc78e53SAndroid Build Coastguard Worker 			nl_cli_fatal(err, "Polling failed: %s", nl_geterror(err));
178*4dc78e53SAndroid Build Coastguard Worker 
179*4dc78e53SAndroid Build Coastguard Worker 		if (dump_on_timeout || (dump_on_change && change)) {
180*4dc78e53SAndroid Build Coastguard Worker 			nl_cache_mngr_info(mngr, &params);
181*4dc78e53SAndroid Build Coastguard Worker 			fflush(stdout);
182*4dc78e53SAndroid Build Coastguard Worker 			change = 0;
183*4dc78e53SAndroid Build Coastguard Worker 		}
184*4dc78e53SAndroid Build Coastguard Worker 	}
185*4dc78e53SAndroid Build Coastguard Worker 
186*4dc78e53SAndroid Build Coastguard Worker 	nl_cache_mngr_free(mngr);
187*4dc78e53SAndroid Build Coastguard Worker 
188*4dc78e53SAndroid Build Coastguard Worker 	return 0;
189*4dc78e53SAndroid Build Coastguard Worker }
190