2fb5273d742f9ad43cd4b5792bae280dd8ee464a
[NetworkManager.git] / src / nm-core-utils.h
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /* NetworkManager -- Network link manager
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  *
18  * Copyright 2004 - 2016 Red Hat, Inc.
19  * Copyright 2005 - 2008 Novell, Inc.
20  */
21
22 #ifndef __NM_CORE_UTILS_H__
23 #define __NM_CORE_UTILS_H__
24
25 #include <stdio.h>
26 #include <arpa/inet.h>
27
28 #include "nm-default.h"
29 #include "nm-connection.h"
30
31 /*****************************************************************************/
32
33 #define NM_PLATFORM_LIFETIME_PERMANENT G_MAXUINT32
34
35 #define NM_DEFINE_SINGLETON_INSTANCE(TYPE) \
36 static TYPE *singleton_instance
37
38 #define NM_DEFINE_SINGLETON_REGISTER(TYPE) \
39 NM_DEFINE_SINGLETON_INSTANCE (TYPE); \
40 static void \
41 _singleton_instance_weak_ref_cb (gpointer data, \
42                                  GObject *where_the_object_was) \
43 { \
44         nm_log_dbg (LOGD_CORE, "disposing %s singleton (%p)", G_STRINGIFY (TYPE), singleton_instance); \
45         singleton_instance = NULL; \
46 } \
47 static inline void \
48 nm_singleton_instance_register (void) \
49 { \
50         g_object_weak_ref (G_OBJECT (singleton_instance), _singleton_instance_weak_ref_cb, NULL); \
51         _nm_singleton_instance_register_destruction (G_OBJECT (singleton_instance)); \
52 }
53
54 void _nm_singleton_instance_register_destruction (GObject *instance);
55
56 /* By default, the getter will assert that the singleton will be created only once. You can
57  * change this by redefining NM_DEFINE_SINGLETON_ALLOW_MULTIPLE. */
58 #ifndef NM_DEFINE_SINGLETON_ALLOW_MULTIPLE
59 #define NM_DEFINE_SINGLETON_ALLOW_MULTIPLE     FALSE
60 #endif
61
62 #define NM_DEFINE_SINGLETON_GETTER(TYPE, GETTER, GTYPE, ...) \
63 NM_DEFINE_SINGLETON_INSTANCE (TYPE); \
64 NM_DEFINE_SINGLETON_REGISTER (TYPE); \
65 TYPE * \
66 GETTER (void) \
67 { \
68         if (G_UNLIKELY (!singleton_instance)) { \
69                 static char _already_created = FALSE; \
70 \
71                 g_assert (!_already_created || (NM_DEFINE_SINGLETON_ALLOW_MULTIPLE)); \
72                 _already_created = TRUE;\
73                 singleton_instance = (g_object_new (GTYPE, ##__VA_ARGS__, NULL)); \
74                 g_assert (singleton_instance); \
75                 nm_singleton_instance_register (); \
76                 nm_log_dbg (LOGD_CORE, "create %s singleton (%p)", G_STRINGIFY (TYPE), singleton_instance); \
77         } \
78         return singleton_instance; \
79 }
80
81 /* attach @instance to the data or @owner. @owner owns a reference
82  * to @instance thus the lifetime of @instance is at least as long
83  * as that of @owner. Use this when @owner depends on @instance. */
84 #define NM_UTILS_KEEP_ALIVE(owner, instance, unique_token) \
85     G_STMT_START { \
86          g_object_set_data_full (G_OBJECT (owner), \
87                                  ".nm-utils-keep-alive-" unique_token "", \
88                                  g_object_ref (instance), \
89                                  g_object_unref); \
90     } G_STMT_END
91
92 /*****************************************************************************/
93
94 /**
95  * NMUtilsError:
96  * @NM_UTILS_ERROR_UNKNOWN: unknown or unclassified error
97  * @NM_UTILS_ERROR_CANCELLED_DISPOSING: when disposing an object that has
98  *   pending aynchronous operations, the operation is cancelled with this
99  *   error reason. Depending on the usage, this might indicate a bug because
100  *   usually the target object should stay alive as long as there are pending
101  *   operations.
102  */
103 typedef enum {
104         NM_UTILS_ERROR_UNKNOWN = 0,                 /*< nick=Unknown >*/
105         NM_UTILS_ERROR_CANCELLED_DISPOSING,         /*< nick=CancelledDisposing >*/
106 } NMUtilsError;
107
108 #define NM_UTILS_ERROR (nm_utils_error_quark ())
109 GQuark nm_utils_error_quark (void);
110
111 void nm_utils_error_set_cancelled (GError **error,
112                                    gboolean is_disposing,
113                                    const char *instance_name);
114 gboolean nm_utils_error_is_cancelled (GError *error,
115                                       gboolean consider_is_disposing);
116
117 /*****************************************************************************/
118
119 gint nm_utils_ascii_str_to_bool (const char *str,
120                                  gint default_value);
121
122 /*****************************************************************************/
123
124 gboolean nm_ethernet_address_is_valid (gconstpointer addr, gssize len);
125
126 in_addr_t nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen);
127 const struct in6_addr *nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen);
128
129 /**
130  * nm_utils_ip6_route_metric_normalize:
131  * @metric: the route metric
132  *
133  * For IPv6 route, kernel treats the value 0 as IP6_RT_PRIO_USER (1024).
134  * Thus, when comparing metric (values), we want to treat zero as NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6.
135  *
136  * Returns: @metric, if @metric is not zero, otherwise 1024.
137  */
138 static inline guint32
139 nm_utils_ip6_route_metric_normalize (guint32 metric)
140 {
141         return metric ? metric : 1024 /*NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6*/;
142 }
143
144 int nm_spawn_process (const char *args, GError **error);
145
146 int nm_utils_modprobe (GError **error, gboolean suppress_error_loggin, const char *arg1, ...) G_GNUC_NULL_TERMINATED;
147
148 guint64 nm_utils_get_start_time_for_pid (pid_t pid, char *out_state, pid_t *out_ppid);
149
150 void nm_utils_kill_process_sync (pid_t pid, guint64 start_time, int sig, guint64 log_domain,
151                                  const char *log_name, guint32 wait_before_kill_msec,
152                                  guint32 sleep_duration_msec, guint32 max_wait_msec);
153
154 typedef void (*NMUtilsKillChildAsyncCb) (pid_t pid, gboolean success, int child_status, void *user_data);
155 void nm_utils_kill_child_async (pid_t pid, int sig, guint64 log_domain, const char *log_name,
156                                 guint32 wait_before_kill_msec,
157                                 NMUtilsKillChildAsyncCb callback, void *user_data);
158 gboolean nm_utils_kill_child_sync (pid_t pid, int sig, guint64 log_domain, const char *log_name,
159                                    int *child_status, guint32 wait_before_kill_msec,
160                                    guint32 sleep_duration_msec);
161
162 const char *nm_utils_find_helper (const char *progname,
163                                   const char *try_first,
164                                   GError **error);
165
166 typedef enum {
167         NM_MATCH_SPEC_NO_MATCH  = 0,
168         NM_MATCH_SPEC_MATCH     = 1,
169         NM_MATCH_SPEC_NEG_MATCH = 2,
170 } NMMatchSpecMatchType;
171
172 NMMatchSpecMatchType nm_match_spec_device_type (const GSList *specs, const char *device_type);
173 NMMatchSpecMatchType nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr);
174 NMMatchSpecMatchType nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels);
175 NMMatchSpecMatchType nm_match_spec_interface_name (const GSList *specs, const char *interface_name);
176 NMMatchSpecMatchType nm_match_spec_match_config (const GSList *specs, guint nm_version, const char *env);
177 GSList *nm_match_spec_split (const char *value);
178 char *nm_match_spec_join (GSList *specs);
179
180 extern char _nm_utils_to_string_buffer[2096];
181
182 void     nm_utils_to_string_buffer_init (char **buf, gsize *len);
183 gboolean nm_utils_to_string_buffer_init_null (gconstpointer obj, char **buf, gsize *len);
184
185 /*****************************************************************************/
186
187 typedef struct {
188         unsigned flag;
189         const char *name;
190 } NMUtilsFlags2StrDesc;
191
192 #define NM_UTILS_FLAGS2STR(f, n) { .flag = f, .name = ""n, }
193
194 #define _NM_UTILS_FLAGS2STR_DEFINE(scope, fcn_name, flags_type, ...) \
195 scope const char * \
196 fcn_name (flags_type flags, char *buf, gsize len) \
197 { \
198         static const NMUtilsFlags2StrDesc descs[] = { \
199                 __VA_ARGS__ \
200         }; \
201         G_STATIC_ASSERT (sizeof (flags_type) <= sizeof (unsigned)); \
202         return nm_utils_flags2str (descs, G_N_ELEMENTS (descs), flags, buf, len); \
203 };
204
205 #define NM_UTILS_FLAGS2STR_DEFINE(fcn_name, flags_type, ...) \
206         _NM_UTILS_FLAGS2STR_DEFINE (, fcn_name, flags_type, __VA_ARGS__)
207 #define NM_UTILS_FLAGS2STR_DEFINE_STATIC(fcn_name, flags_type, ...) \
208         _NM_UTILS_FLAGS2STR_DEFINE (static, fcn_name, flags_type, __VA_ARGS__)
209
210 const char *nm_utils_flags2str (const NMUtilsFlags2StrDesc *descs,
211                                 gsize n_descs,
212                                 unsigned flags,
213                                 char *buf,
214                                 gsize len);
215
216 /*****************************************************************************/
217
218 #define NM_UTILS_ENUM2STR(v, n)     (void) 0; case v: s = ""n""; break; (void) 0
219 #define NM_UTILS_ENUM2STR_IGNORE(v) (void) 0; case v: break; (void) 0
220
221 #define _NM_UTILS_ENUM2STR_DEFINE(scope, fcn_name, lookup_type, int_fmt, ...) \
222 scope const char * \
223 fcn_name (lookup_type val, char *buf, gsize len) \
224 { \
225         nm_utils_to_string_buffer_init (&buf, &len); \
226         if (len) { \
227                 const char *s = NULL; \
228                 switch (val) { \
229                         (void) 0, \
230                         __VA_ARGS__ \
231                         (void) 0; \
232                 }; \
233                 if (s) \
234                         g_strlcpy (buf, s, len); \
235                 else \
236                         g_snprintf (buf, len, "(%"int_fmt")", val); \
237         } \
238         return buf; \
239 }
240
241 #define NM_UTILS_ENUM2STR_DEFINE(fcn_name, lookup_type, ...) \
242         _NM_UTILS_ENUM2STR_DEFINE (, fcn_name, lookup_type, "d", __VA_ARGS__)
243 #define NM_UTILS_ENUM2STR_DEFINE_STATIC(fcn_name, lookup_type, ...) \
244         _NM_UTILS_ENUM2STR_DEFINE (static, fcn_name, lookup_type, "d", __VA_ARGS__)
245
246 /*****************************************************************************/
247
248 #define NM_UTILS_LOOKUP_DEFAULT(v)      return (v)
249 #define NM_UTILS_LOOKUP_DEFAULT_WARN(v) g_return_val_if_reached (v)
250 #define NM_UTILS_LOOKUP_ITEM(v, n)     (void) 0; case v: return (n); (void) 0
251 #define NM_UTILS_LOOKUP_STR_ITEM(v, n) NM_UTILS_LOOKUP_ITEM(v, ""n"")
252 #define NM_UTILS_LOOKUP_ITEM_IGNORE(v) (void) 0; case v: break; (void) 0
253
254 #define _NM_UTILS_LOOKUP_DEFINE(scope, fcn_name, lookup_type, result_type, unknown_val, ...) \
255 scope result_type \
256 fcn_name (lookup_type val) \
257 { \
258         switch (val) { \
259                 (void) 0, \
260                 __VA_ARGS__ \
261                 (void) 0; \
262         }; \
263         { unknown_val; } \
264 }
265
266 #define NM_UTILS_LOOKUP_STR_DEFINE(fcn_name, lookup_type, unknown_val, ...) \
267         _NM_UTILS_LOOKUP_DEFINE (, fcn_name, lookup_type, const char *, unknown_val, __VA_ARGS__)
268 #define NM_UTILS_LOOKUP_STR_DEFINE_STATIC(fcn_name, lookup_type, unknown_val, ...) \
269         _NM_UTILS_LOOKUP_DEFINE (static, fcn_name, lookup_type, const char *, unknown_val, __VA_ARGS__)
270
271 /* Call the string-lookup-table function @fcn_name. If the function returns
272  * %NULL, the numeric index is converted to string using a alloca() buffer.
273  * Beware: this macro uses alloca(). */
274 #define NM_UTILS_LOOKUP_STR(fcn_name, idx) \
275         ({ \
276                 typeof (idx) _idx = (idx); \
277                 const char *_s; \
278                 \
279                 _s = fcn_name (_idx); \
280                 if (!_s) { \
281                         _s = g_alloca (30); \
282                         \
283                         g_snprintf ((char *) _s, 30, "(%lld)", (long long) _idx); \
284                 } \
285                 _s; \
286         })
287
288 /*****************************************************************************/
289
290 static inline void
291 _nm_utils_strbuf_init (char *buf, gsize len, char **p_buf_ptr, gsize *p_buf_len)
292 {
293         NM_SET_OUT (p_buf_len, len);
294         NM_SET_OUT (p_buf_ptr, buf);
295         buf[0] = '\0';
296 }
297
298 #define nm_utils_strbuf_init(buf, p_buf_ptr, p_buf_len) \
299         G_STMT_START { \
300                 G_STATIC_ASSERT (G_N_ELEMENTS (buf) == sizeof (buf) && sizeof (buf) > sizeof (char *)); \
301                 _nm_utils_strbuf_init ((buf), sizeof (buf), (p_buf_ptr), (p_buf_len)); \
302         } G_STMT_END
303 void nm_utils_strbuf_append (char **buf, gsize *len, const char *format, ...) __attribute__((__format__ (__printf__, 3, 4)));
304 void nm_utils_strbuf_append_c (char **buf, gsize *len, char c);
305 void nm_utils_strbuf_append_str (char **buf, gsize *len, const char *str);
306
307 const char *nm_utils_get_ip_config_method (NMConnection *connection,
308                                            GType         ip_setting_type);
309
310 char *nm_utils_new_vlan_name (const char *parent_iface, guint32 vlan_id);
311
312 GPtrArray *nm_utils_read_resolv_conf_nameservers (const char *rc_contents);
313 GPtrArray *nm_utils_read_resolv_conf_dns_options (const char *rc_contents);
314
315 int nm_utils_cmp_connection_by_autoconnect_priority (NMConnection **a, NMConnection **b);
316
317 void nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base, guint32 level, guint64 domain, const char *name, const char *prefix);
318
319 #define NM_UTILS_NS_PER_SECOND  ((gint64) 1000000000)
320 #define NM_UTILS_NS_PER_MSEC    ((gint64) 1000000)
321 #define NM_UTILS_NS_TO_MSEC_CEIL(nsec)      (((nsec) + (NM_UTILS_NS_PER_MSEC - 1)) / NM_UTILS_NS_PER_MSEC)
322
323 gint64 nm_utils_get_monotonic_timestamp_ns (void);
324 gint64 nm_utils_get_monotonic_timestamp_us (void);
325 gint64 nm_utils_get_monotonic_timestamp_ms (void);
326 gint32 nm_utils_get_monotonic_timestamp_s (void);
327 gint64 nm_utils_monotonic_timestamp_as_boottime (gint64 timestamp, gint64 timestamp_ticks_per_ns);
328
329 gboolean    nm_utils_is_valid_path_component (const char *name);
330 const char *NM_ASSERT_VALID_PATH_COMPONENT (const char *name);
331 const char *nm_utils_ip6_property_path (const char *ifname, const char *property);
332 const char *nm_utils_ip4_property_path (const char *ifname, const char *property);
333
334 gboolean nm_utils_is_specific_hostname (const char *name);
335
336 /* IPv6 Interface Identifer helpers */
337
338 /**
339  * NMUtilsIPv6IfaceId:
340  * @id: convenience member for validity checking; never use directly
341  * @id_u8: the 64-bit Interface Identifier
342  *
343  * Holds a 64-bit IPv6 Interface Identifier.  The IID is a sequence of bytes
344  * and should not normally be treated as a %guint64, but this is done for
345  * convenience of validity checking and initialization.
346  */
347 struct _NMUtilsIPv6IfaceId {
348         union {
349                 guint64 id;
350                 guint8  id_u8[8];
351         };
352 };
353
354 #define NM_UTILS_IPV6_IFACE_ID_INIT { { .id = 0 } }
355
356 gboolean nm_utils_get_ipv6_interface_identifier (NMLinkType link_type,
357                                                  const guint8 *hwaddr,
358                                                  guint len,
359                                                  guint dev_id,
360                                                  NMUtilsIPv6IfaceId *out_iid);
361
362 void nm_utils_ipv6_addr_set_interface_identfier (struct in6_addr *addr,
363                                                  const NMUtilsIPv6IfaceId iid);
364
365 gboolean nm_utils_ipv6_addr_set_stable_privacy (struct in6_addr *addr,
366                                                 const char *ifname,
367                                                 const char *uuid,
368                                                 guint dad_counter,
369                                                 GError **error);
370
371 void nm_utils_ipv6_interface_identfier_get_from_addr (NMUtilsIPv6IfaceId *iid,
372                                                       const struct in6_addr *addr);
373
374 void nm_utils_array_remove_at_indexes (GArray *array, const guint *indexes_to_delete, gsize len);
375
376 void nm_utils_setpgid (gpointer unused);
377
378 typedef enum {
379         NM_UTILS_TEST_NONE                              = 0,
380
381         /* Internal flag, marking that either nm_utils_get_testing() or _nm_utils_set_testing() was called. */
382         _NM_UTILS_TEST_INITIALIZED                      = (1LL << 0),
383
384         /* Indicate that test mode is enabled in general. Explicitly calling _nm_utils_set_testing() will always set this flag. */
385         _NM_UTILS_TEST_GENERAL                          = (1LL << 1),
386
387         /* Don't check the owner of keyfiles during testing. */
388         NM_UTILS_TEST_NO_KEYFILE_OWNER_CHECK            = (1LL << 2),
389
390         _NM_UTILS_TEST_LAST,
391         NM_UTILS_TEST_ALL                               = (((_NM_UTILS_TEST_LAST - 1) << 1) - 1) & ~(_NM_UTILS_TEST_INITIALIZED),
392 } NMUtilsTestFlags;
393
394 gboolean nm_utils_get_testing_initialized (void);
395 NMUtilsTestFlags nm_utils_get_testing (void);
396 void _nm_utils_set_testing (NMUtilsTestFlags flags);
397
398 void nm_utils_g_value_set_strv (GValue *value, GPtrArray *strings);
399
400 guint nm_utils_parse_debug_string (const char *string,
401                                    const GDebugKey *keys,
402                                    guint nkeys);
403
404 void nm_utils_ifname_cpy (char *dst, const char *name);
405
406 guint32 nm_utils_lifetime_rebase_relative_time_on_now (guint32 timestamp,
407                                                        guint32 duration,
408                                                        gint32 now);
409
410 gboolean nm_utils_lifetime_get (guint32 timestamp,
411                                 guint32 lifetime,
412                                 guint32 preferred,
413                                 gint32 now,
414                                 guint32 *out_lifetime,
415                                 guint32 *out_preferred);
416
417 gboolean nm_utils_ip4_address_is_link_local (in_addr_t addr);
418
419 #endif /* __NM_CORE_UTILS_H__ */