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  */
36 uint32_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 
49 void 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  */
71 void 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 
108 int 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 
119 struct 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 
129 struct 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 
141 int 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 
155 int 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 
189 struct 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 
199  nl_cache_mngt_provide(cache);
200 
201  return cache;
202 }
203 
204 struct 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 
216  nl_cache_mngt_provide(cache);
217 
218  return cache;
219 }
220 
221 void 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