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