xref: /aosp_15_r20/external/libnl/src/lib/utils.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) 2003-2009 Thomas Graf <[email protected]>
4*4dc78e53SAndroid Build Coastguard Worker  */
5*4dc78e53SAndroid Build Coastguard Worker 
6*4dc78e53SAndroid Build Coastguard Worker /**
7*4dc78e53SAndroid Build Coastguard Worker  * @defgroup cli Command Line Interface API
8*4dc78e53SAndroid Build Coastguard Worker  *
9*4dc78e53SAndroid Build Coastguard Worker  * @{
10*4dc78e53SAndroid Build Coastguard Worker  *
11*4dc78e53SAndroid Build Coastguard Worker  * These modules provide an interface for text based applications. The
12*4dc78e53SAndroid Build Coastguard Worker  * functions provided are wrappers for their libnl equivalent with
13*4dc78e53SAndroid Build Coastguard Worker  * added error handling. The functions check for allocation failures,
14*4dc78e53SAndroid Build Coastguard Worker  * invalid input, and unknown types and will print error messages
15*4dc78e53SAndroid Build Coastguard Worker  * accordingly via nl_cli_fatal().
16*4dc78e53SAndroid Build Coastguard Worker  */
17*4dc78e53SAndroid Build Coastguard Worker 
18*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
19*4dc78e53SAndroid Build Coastguard Worker 
20*4dc78e53SAndroid Build Coastguard Worker #include <locale.h>
21*4dc78e53SAndroid Build Coastguard Worker #ifdef HAVE_DLFCN_H
22*4dc78e53SAndroid Build Coastguard Worker #include <dlfcn.h>
23*4dc78e53SAndroid Build Coastguard Worker #endif
24*4dc78e53SAndroid Build Coastguard Worker 
25*4dc78e53SAndroid Build Coastguard Worker #include <netlink/cli/utils.h>
26*4dc78e53SAndroid Build Coastguard Worker 
27*4dc78e53SAndroid Build Coastguard Worker /**
28*4dc78e53SAndroid Build Coastguard Worker  * Parse a text based 32 bit unsigned integer argument
29*4dc78e53SAndroid Build Coastguard Worker  * @arg arg		Integer in text form.
30*4dc78e53SAndroid Build Coastguard Worker  *
31*4dc78e53SAndroid Build Coastguard Worker  * Tries to convert the number provided in arg to a uint32_t. Will call
32*4dc78e53SAndroid Build Coastguard Worker  * nl_cli_fatal() if the conversion fails.
33*4dc78e53SAndroid Build Coastguard Worker  *
34*4dc78e53SAndroid Build Coastguard Worker  * @return 32bit unsigned integer.
35*4dc78e53SAndroid Build Coastguard Worker  */
nl_cli_parse_u32(const char * arg)36*4dc78e53SAndroid Build Coastguard Worker uint32_t nl_cli_parse_u32(const char *arg)
37*4dc78e53SAndroid Build Coastguard Worker {
38*4dc78e53SAndroid Build Coastguard Worker 	unsigned long lval;
39*4dc78e53SAndroid Build Coastguard Worker 	char *endptr;
40*4dc78e53SAndroid Build Coastguard Worker 
41*4dc78e53SAndroid Build Coastguard Worker 	lval = strtoul(arg, &endptr, 0);
42*4dc78e53SAndroid Build Coastguard Worker 	if (endptr == arg || lval == ULONG_MAX)
43*4dc78e53SAndroid Build Coastguard Worker 		nl_cli_fatal(EINVAL, "Unable to parse \"%s\", not a number.",
44*4dc78e53SAndroid Build Coastguard Worker 			     arg);
45*4dc78e53SAndroid Build Coastguard Worker 
46*4dc78e53SAndroid Build Coastguard Worker 	return (uint32_t) lval;
47*4dc78e53SAndroid Build Coastguard Worker }
48*4dc78e53SAndroid Build Coastguard Worker 
nl_cli_print_version(void)49*4dc78e53SAndroid Build Coastguard Worker void nl_cli_print_version(void)
50*4dc78e53SAndroid Build Coastguard Worker {
51*4dc78e53SAndroid Build Coastguard Worker 	printf("libnl tools version %s\n", LIBNL_VERSION);
52*4dc78e53SAndroid Build Coastguard Worker 	printf(
53*4dc78e53SAndroid Build Coastguard Worker 	"Copyright (C) 2003-2010 Thomas Graf <[email protected]>\n"
54*4dc78e53SAndroid Build Coastguard Worker 	"\n"
55*4dc78e53SAndroid Build Coastguard Worker 	"This program comes with ABSOLUTELY NO WARRANTY. This is free \n"
56*4dc78e53SAndroid Build Coastguard Worker 	"software, and you are welcome to redistribute it under certain\n"
57*4dc78e53SAndroid Build Coastguard Worker 	"conditions. See the GNU General Public License for details.\n"
58*4dc78e53SAndroid Build Coastguard Worker 	);
59*4dc78e53SAndroid Build Coastguard Worker 
60*4dc78e53SAndroid Build Coastguard Worker 	exit(0);
61*4dc78e53SAndroid Build Coastguard Worker }
62*4dc78e53SAndroid Build Coastguard Worker 
63*4dc78e53SAndroid Build Coastguard Worker /**
64*4dc78e53SAndroid Build Coastguard Worker  * Print error message and quit application
65*4dc78e53SAndroid Build Coastguard Worker  * @arg err		Error code.
66*4dc78e53SAndroid Build Coastguard Worker  * @arg fmt		Error message.
67*4dc78e53SAndroid Build Coastguard Worker  *
68*4dc78e53SAndroid Build Coastguard Worker  * Prints the formatted error message to stderr and quits the application
69*4dc78e53SAndroid Build Coastguard Worker  * using the provided error code.
70*4dc78e53SAndroid Build Coastguard Worker  */
nl_cli_fatal(int err,const char * fmt,...)71*4dc78e53SAndroid Build Coastguard Worker void nl_cli_fatal(int err, const char *fmt, ...)
72*4dc78e53SAndroid Build Coastguard Worker {
73*4dc78e53SAndroid Build Coastguard Worker 	va_list ap;
74*4dc78e53SAndroid Build Coastguard Worker 
75*4dc78e53SAndroid Build Coastguard Worker 	fprintf(stderr, "Error: ");
76*4dc78e53SAndroid Build Coastguard Worker 
77*4dc78e53SAndroid Build Coastguard Worker 	if (fmt) {
78*4dc78e53SAndroid Build Coastguard Worker 		va_start(ap, fmt);
79*4dc78e53SAndroid Build Coastguard Worker 		vfprintf(stderr, fmt, ap);
80*4dc78e53SAndroid Build Coastguard Worker 		va_end(ap);
81*4dc78e53SAndroid Build Coastguard Worker 		fprintf(stderr, "\n");
82*4dc78e53SAndroid Build Coastguard Worker 	} else {
83*4dc78e53SAndroid Build Coastguard Worker 		char *buf;
84*4dc78e53SAndroid Build Coastguard Worker #ifdef HAVE_STRERROR_L
85*4dc78e53SAndroid Build Coastguard Worker 		locale_t loc = newlocale(LC_MESSAGES_MASK, "", (locale_t)0);
86*4dc78e53SAndroid Build Coastguard Worker 		if (loc == (locale_t)0) {
87*4dc78e53SAndroid Build Coastguard Worker 			if (errno == ENOENT)
88*4dc78e53SAndroid Build Coastguard Worker 				loc = newlocale(LC_MESSAGES_MASK,
89*4dc78e53SAndroid Build Coastguard Worker 						"POSIX", (locale_t)0);
90*4dc78e53SAndroid Build Coastguard Worker 			if (loc == (locale_t)0)
91*4dc78e53SAndroid Build Coastguard Worker 				buf = "newlocale() failed";
92*4dc78e53SAndroid Build Coastguard Worker 		}
93*4dc78e53SAndroid Build Coastguard Worker 		if (loc != (locale_t)0)
94*4dc78e53SAndroid Build Coastguard Worker 			buf = strerror_l(err, loc);
95*4dc78e53SAndroid Build Coastguard Worker #else
96*4dc78e53SAndroid Build Coastguard Worker 		buf = strerror(err);
97*4dc78e53SAndroid Build Coastguard Worker #endif
98*4dc78e53SAndroid Build Coastguard Worker 		fprintf(stderr, "%s\n", buf);
99*4dc78e53SAndroid Build Coastguard Worker #ifdef HAVE_STRERROR_L
100*4dc78e53SAndroid Build Coastguard Worker 		if (loc != (locale_t)0)
101*4dc78e53SAndroid Build Coastguard Worker 			freelocale(loc);
102*4dc78e53SAndroid Build Coastguard Worker #endif
103*4dc78e53SAndroid Build Coastguard Worker 	}
104*4dc78e53SAndroid Build Coastguard Worker 
105*4dc78e53SAndroid Build Coastguard Worker 	exit(abs(err));
106*4dc78e53SAndroid Build Coastguard Worker }
107*4dc78e53SAndroid Build Coastguard Worker 
nl_cli_connect(struct nl_sock * sk,int protocol)108*4dc78e53SAndroid Build Coastguard Worker int nl_cli_connect(struct nl_sock *sk, int protocol)
109*4dc78e53SAndroid Build Coastguard Worker {
110*4dc78e53SAndroid Build Coastguard Worker 	int err;
111*4dc78e53SAndroid Build Coastguard Worker 
112*4dc78e53SAndroid Build Coastguard Worker 	if ((err = nl_connect(sk, protocol)) < 0)
113*4dc78e53SAndroid Build Coastguard Worker 		nl_cli_fatal(err, "Unable to connect netlink socket: %s",
114*4dc78e53SAndroid Build Coastguard Worker 			     nl_geterror(err));
115*4dc78e53SAndroid Build Coastguard Worker 
116*4dc78e53SAndroid Build Coastguard Worker 	return err;
117*4dc78e53SAndroid Build Coastguard Worker }
118*4dc78e53SAndroid Build Coastguard Worker 
nl_cli_alloc_socket(void)119*4dc78e53SAndroid Build Coastguard Worker struct nl_sock *nl_cli_alloc_socket(void)
120*4dc78e53SAndroid Build Coastguard Worker {
121*4dc78e53SAndroid Build Coastguard Worker 	struct nl_sock *sock;
122*4dc78e53SAndroid Build Coastguard Worker 
123*4dc78e53SAndroid Build Coastguard Worker 	if (!(sock = nl_socket_alloc()))
124*4dc78e53SAndroid Build Coastguard Worker 		nl_cli_fatal(ENOBUFS, "Unable to allocate netlink socket");
125*4dc78e53SAndroid Build Coastguard Worker 
126*4dc78e53SAndroid Build Coastguard Worker 	return sock;
127*4dc78e53SAndroid Build Coastguard Worker }
128*4dc78e53SAndroid Build Coastguard Worker 
nl_cli_addr_parse(const char * str,int family)129*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *nl_cli_addr_parse(const char *str, int family)
130*4dc78e53SAndroid Build Coastguard Worker {
131*4dc78e53SAndroid Build Coastguard Worker 	struct nl_addr *addr;
132*4dc78e53SAndroid Build Coastguard Worker 	int err;
133*4dc78e53SAndroid Build Coastguard Worker 
134*4dc78e53SAndroid Build Coastguard Worker 	if ((err = nl_addr_parse(str, family, &addr)) < 0)
135*4dc78e53SAndroid Build Coastguard Worker 		nl_cli_fatal(err, "Unable to parse address \"%s\": %s",
136*4dc78e53SAndroid Build Coastguard Worker 			     str, nl_geterror(err));
137*4dc78e53SAndroid Build Coastguard Worker 
138*4dc78e53SAndroid Build Coastguard Worker 	return addr;
139*4dc78e53SAndroid Build Coastguard Worker }
140*4dc78e53SAndroid Build Coastguard Worker 
nl_cli_parse_dumptype(const char * str)141*4dc78e53SAndroid Build Coastguard Worker int nl_cli_parse_dumptype(const char *str)
142*4dc78e53SAndroid Build Coastguard Worker {
143*4dc78e53SAndroid Build Coastguard Worker 	if (!strcasecmp(str, "brief"))
144*4dc78e53SAndroid Build Coastguard Worker 		return NL_DUMP_LINE;
145*4dc78e53SAndroid Build Coastguard Worker 	else if (!strcasecmp(str, "details") || !strcasecmp(str, "detailed"))
146*4dc78e53SAndroid Build Coastguard Worker 		return NL_DUMP_DETAILS;
147*4dc78e53SAndroid Build Coastguard Worker 	else if (!strcasecmp(str, "stats"))
148*4dc78e53SAndroid Build Coastguard Worker 		return NL_DUMP_STATS;
149*4dc78e53SAndroid Build Coastguard Worker 	else
150*4dc78e53SAndroid Build Coastguard Worker 		nl_cli_fatal(EINVAL, "Invalid dump type \"%s\".\n", str);
151*4dc78e53SAndroid Build Coastguard Worker 
152*4dc78e53SAndroid Build Coastguard Worker 	return 0;
153*4dc78e53SAndroid Build Coastguard Worker }
154*4dc78e53SAndroid Build Coastguard Worker 
nl_cli_confirm(struct nl_object * obj,struct nl_dump_params * params,int default_yes)155*4dc78e53SAndroid Build Coastguard Worker int nl_cli_confirm(struct nl_object *obj, struct nl_dump_params *params,
156*4dc78e53SAndroid Build Coastguard Worker 		   int default_yes)
157*4dc78e53SAndroid Build Coastguard Worker {
158*4dc78e53SAndroid Build Coastguard Worker 	nl_object_dump(obj, params);
159*4dc78e53SAndroid Build Coastguard Worker 
160*4dc78e53SAndroid Build Coastguard Worker 	for (;;) {
161*4dc78e53SAndroid Build Coastguard Worker 		char buf[32] = { 0 };
162*4dc78e53SAndroid Build Coastguard Worker 		int answer;
163*4dc78e53SAndroid Build Coastguard Worker 
164*4dc78e53SAndroid Build Coastguard Worker 		printf("Delete? (%c/%c) ",
165*4dc78e53SAndroid Build Coastguard Worker 			default_yes ? 'Y' : 'y',
166*4dc78e53SAndroid Build Coastguard Worker 			default_yes ? 'n' : 'N');
167*4dc78e53SAndroid Build Coastguard Worker 
168*4dc78e53SAndroid Build Coastguard Worker 		if (!fgets(buf, sizeof(buf), stdin)) {
169*4dc78e53SAndroid Build Coastguard Worker 			fprintf(stderr, "Error while reading\n.");
170*4dc78e53SAndroid Build Coastguard Worker 			continue;
171*4dc78e53SAndroid Build Coastguard Worker 		}
172*4dc78e53SAndroid Build Coastguard Worker 
173*4dc78e53SAndroid Build Coastguard Worker 		switch ((answer = tolower(buf[0]))) {
174*4dc78e53SAndroid Build Coastguard Worker 		case '\n':
175*4dc78e53SAndroid Build Coastguard Worker 			answer = default_yes ? 'y' : 'n';
176*4dc78e53SAndroid Build Coastguard Worker 			/* fall through */
177*4dc78e53SAndroid Build Coastguard Worker 		case 'y':
178*4dc78e53SAndroid Build Coastguard Worker 		case 'n':
179*4dc78e53SAndroid Build Coastguard Worker 			return answer == 'y';
180*4dc78e53SAndroid Build Coastguard Worker 		}
181*4dc78e53SAndroid Build Coastguard Worker 
182*4dc78e53SAndroid Build Coastguard Worker 		fprintf(stderr, "Invalid input, try again.\n");
183*4dc78e53SAndroid Build Coastguard Worker 	}
184*4dc78e53SAndroid Build Coastguard Worker 
185*4dc78e53SAndroid Build Coastguard Worker 	return 0;
186*4dc78e53SAndroid Build Coastguard Worker 
187*4dc78e53SAndroid Build Coastguard Worker }
188*4dc78e53SAndroid Build Coastguard Worker 
nl_cli_alloc_cache(struct nl_sock * sock,const char * name,int (* ac)(struct nl_sock *,struct nl_cache **))189*4dc78e53SAndroid Build Coastguard Worker struct nl_cache *nl_cli_alloc_cache(struct nl_sock *sock, const char *name,
190*4dc78e53SAndroid Build Coastguard Worker 			    int (*ac)(struct nl_sock *, struct nl_cache **))
191*4dc78e53SAndroid Build Coastguard Worker {
192*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache *cache;
193*4dc78e53SAndroid Build Coastguard Worker 	int err;
194*4dc78e53SAndroid Build Coastguard Worker 
195*4dc78e53SAndroid Build Coastguard Worker 	if ((err = ac(sock, &cache)) < 0)
196*4dc78e53SAndroid Build Coastguard Worker 		nl_cli_fatal(err, "Unable to allocate %s cache: %s",
197*4dc78e53SAndroid Build Coastguard Worker 			     name, nl_geterror(err));
198*4dc78e53SAndroid Build Coastguard Worker 
199*4dc78e53SAndroid Build Coastguard Worker 	nl_cache_mngt_provide(cache);
200*4dc78e53SAndroid Build Coastguard Worker 
201*4dc78e53SAndroid Build Coastguard Worker 	return cache;
202*4dc78e53SAndroid Build Coastguard Worker }
203*4dc78e53SAndroid Build Coastguard Worker 
nl_cli_alloc_cache_flags(struct nl_sock * sock,const char * name,unsigned int flags,int (* ac)(struct nl_sock *,struct nl_cache **,unsigned int))204*4dc78e53SAndroid Build Coastguard Worker struct nl_cache *nl_cli_alloc_cache_flags(struct nl_sock *sock,
205*4dc78e53SAndroid Build Coastguard Worker 			    const char *name, unsigned int flags,
206*4dc78e53SAndroid Build Coastguard Worker 			    int (*ac)(struct nl_sock *, struct nl_cache **,
207*4dc78e53SAndroid Build Coastguard Worker 				      unsigned int))
208*4dc78e53SAndroid Build Coastguard Worker {
209*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache *cache;
210*4dc78e53SAndroid Build Coastguard Worker 	int err;
211*4dc78e53SAndroid Build Coastguard Worker 
212*4dc78e53SAndroid Build Coastguard Worker 	if ((err = ac(sock, &cache, flags)) < 0)
213*4dc78e53SAndroid Build Coastguard Worker 		nl_cli_fatal(err, "Unable to allocate %s cache: %s",
214*4dc78e53SAndroid Build Coastguard Worker 			     name, nl_geterror(err));
215*4dc78e53SAndroid Build Coastguard Worker 
216*4dc78e53SAndroid Build Coastguard Worker 	nl_cache_mngt_provide(cache);
217*4dc78e53SAndroid Build Coastguard Worker 
218*4dc78e53SAndroid Build Coastguard Worker 	return cache;
219*4dc78e53SAndroid Build Coastguard Worker }
220*4dc78e53SAndroid Build Coastguard Worker 
nl_cli_load_module(const char * prefix,const char * name)221*4dc78e53SAndroid Build Coastguard Worker void nl_cli_load_module(const char *prefix, const char *name)
222*4dc78e53SAndroid Build Coastguard Worker {
223*4dc78e53SAndroid Build Coastguard Worker 	char path[FILENAME_MAX+1];
224*4dc78e53SAndroid Build Coastguard Worker 
225*4dc78e53SAndroid Build Coastguard Worker 	snprintf(path, sizeof(path), "%s/%s/%s.so",
226*4dc78e53SAndroid Build Coastguard Worker 		 _NL_PKGLIBDIR, prefix, name);
227*4dc78e53SAndroid Build Coastguard Worker 
228*4dc78e53SAndroid Build Coastguard Worker #ifdef HAVE_DLFCN_H
229*4dc78e53SAndroid Build Coastguard Worker 	{
230*4dc78e53SAndroid Build Coastguard Worker 		void *handle;
231*4dc78e53SAndroid Build Coastguard Worker 
232*4dc78e53SAndroid Build Coastguard Worker 		handle = dlopen(path, RTLD_NOW);
233*4dc78e53SAndroid Build Coastguard Worker 		if (!handle) {
234*4dc78e53SAndroid Build Coastguard Worker 			nl_cli_fatal(ENOENT, "Unable to load module \"%s\": %s\n",
235*4dc78e53SAndroid Build Coastguard Worker 			             path, dlerror());
236*4dc78e53SAndroid Build Coastguard Worker 		}
237*4dc78e53SAndroid Build Coastguard Worker 		/* We intentionally leak the dlopen handle. */
238*4dc78e53SAndroid Build Coastguard Worker 		/* coverity[RESOURCE_LEAK] */
239*4dc78e53SAndroid Build Coastguard Worker 	}
240*4dc78e53SAndroid Build Coastguard Worker #else
241*4dc78e53SAndroid Build Coastguard Worker 	nl_cli_fatal(ENOTSUP, "Unable to load module \"%s\": built without dynamic libraries support\n",
242*4dc78e53SAndroid Build Coastguard Worker 	             path);
243*4dc78e53SAndroid Build Coastguard Worker #endif
244*4dc78e53SAndroid Build Coastguard Worker }
245*4dc78e53SAndroid Build Coastguard Worker 
246*4dc78e53SAndroid Build Coastguard Worker /** @} */
247