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