device: renew dhcp leases on awake for software devices
[NetworkManager.git] / src / nm-iface-helper.c
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 (C) 2014 Red Hat, Inc.
19  */
20
21 #include "nm-default.h"
22
23 #include <glib-unix.h>
24 #include <getopt.h>
25 #include <locale.h>
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <string.h>
31 #include <sys/resource.h>
32 #include <sys/stat.h>
33 #include <signal.h>
34
35 /* Cannot include <net/if.h> due to conflict with <linux/if.h>.
36  * Forward declare if_nametoindex. */
37 extern unsigned int if_nametoindex (const char *__ifname);
38
39 #include "main-utils.h"
40 #include "NetworkManagerUtils.h"
41 #include "nm-linux-platform.h"
42 #include "nm-dhcp-manager.h"
43 #include "nm-rdisc.h"
44 #include "nm-lndp-rdisc.h"
45 #include "nm-utils.h"
46 #include "nm-setting-ip6-config.h"
47 #include "nm-sd.h"
48
49 #if !defined(NM_DIST_VERSION)
50 # define NM_DIST_VERSION VERSION
51 #endif
52
53 #define NMIH_PID_FILE_FMT NMRUNDIR "/nm-iface-helper-%d.pid"
54
55 static GMainLoop *main_loop = NULL;
56 static int ifindex = -1;
57
58 static struct {
59         gboolean slaac;
60         gboolean show_version;
61         gboolean become_daemon;
62         gboolean debug;
63         gboolean g_fatal_warnings;
64         gboolean slaac_required;
65         gboolean dhcp4_required;
66         int tempaddr;
67         char *ifname;
68         char *uuid;
69         char *dhcp4_address;
70         char *dhcp4_clientid;
71         char *dhcp4_hostname;
72         char *dhcp4_fqdn;
73         char *iid_str;
74         NMSettingIP6ConfigAddrGenMode addr_gen_mode;
75         char *logging_backend;
76         char *opt_log_level;
77         char *opt_log_domains;
78         guint32 priority_v4;
79         guint32 priority_v6;
80 } global_opt = {
81         .tempaddr = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
82         .priority_v4 = NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4,
83         .priority_v6 = NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6,
84 };
85
86 static void
87 dhcp4_state_changed (NMDhcpClient *client,
88                      NMDhcpState state,
89                      NMIP4Config *ip4_config,
90                      GHashTable *options,
91                      const char *event_id,
92                      gpointer user_data)
93 {
94         static NMIP4Config *last_config = NULL;
95         NMIP4Config *existing;
96
97         g_return_if_fail (!ip4_config || NM_IS_IP4_CONFIG (ip4_config));
98
99         nm_log_dbg (LOGD_DHCP4, "(%s): new DHCPv4 client state %d", global_opt.ifname, state);
100
101         switch (state) {
102         case NM_DHCP_STATE_BOUND:
103                 g_assert (ip4_config);
104                 existing = nm_ip4_config_capture (ifindex, FALSE);
105                 if (last_config)
106                         nm_ip4_config_subtract (existing, last_config);
107
108                 nm_ip4_config_merge (existing, ip4_config, NM_IP_CONFIG_MERGE_DEFAULT);
109                 if (!nm_ip4_config_commit (existing, ifindex, TRUE, global_opt.priority_v4))
110                         nm_log_warn (LOGD_DHCP4, "(%s): failed to apply DHCPv4 config", global_opt.ifname);
111
112                 if (last_config)
113                         g_object_unref (last_config);
114                 last_config = nm_ip4_config_new (nm_dhcp_client_get_ifindex (client));
115                 nm_ip4_config_replace (last_config, ip4_config, NULL);
116                 break;
117         case NM_DHCP_STATE_TIMEOUT:
118         case NM_DHCP_STATE_DONE:
119         case NM_DHCP_STATE_FAIL:
120                 if (global_opt.dhcp4_required) {
121                         nm_log_warn (LOGD_DHCP4, "(%s): DHCPv4 timed out or failed, quitting...", global_opt.ifname);
122                         g_main_loop_quit (main_loop);
123                 } else
124                         nm_log_warn (LOGD_DHCP4, "(%s): DHCPv4 timed out or failed", global_opt.ifname);
125                 break;
126         default:
127                 break;
128         }
129 }
130
131 static void
132 rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_data)
133 {
134         static NMIP6Config *rdisc_config = NULL;
135         NMIP6Config *existing;
136         static int system_support = -1;
137         guint32 ifa_flags = 0x00;
138         int i;
139
140         if (system_support == -1) {
141                 /*
142                  * Check, whether kernel is recent enough, to help user space handling RA.
143                  * If it's not supported, we have no ipv6-privacy and must add autoconf
144                  * addresses as /128.
145                  * The reason for the /128 is to prevent the kernel
146                  * from adding a prefix route for this address.
147                  **/
148                 system_support = nm_platform_check_support_kernel_extended_ifa_flags (NM_PLATFORM_GET);
149         }
150
151         if (system_support)
152                 ifa_flags = IFA_F_NOPREFIXROUTE;
153         if (global_opt.tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR
154             || global_opt.tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR)
155         {
156                 /* without system_support, this flag will be ignored. Still set it, doesn't seem to do any harm. */
157                 ifa_flags |= IFA_F_MANAGETEMPADDR;
158         }
159
160         existing = nm_ip6_config_capture (ifindex, FALSE, global_opt.tempaddr);
161         if (rdisc_config)
162                 nm_ip6_config_subtract (existing, rdisc_config);
163         else
164                 rdisc_config = nm_ip6_config_new (ifindex);
165
166         if (changed & NM_RDISC_CONFIG_GATEWAYS) {
167                 /* Use the first gateway as ordered in router discovery cache. */
168                 if (rdisc->gateways->len) {
169                         NMRDiscGateway *gateway = &g_array_index (rdisc->gateways, NMRDiscGateway, 0);
170
171                         nm_ip6_config_set_gateway (rdisc_config, &gateway->address);
172                 } else
173                         nm_ip6_config_set_gateway (rdisc_config, NULL);
174         }
175
176         if (changed & NM_RDISC_CONFIG_ADDRESSES) {
177                 /* Rebuild address list from router discovery cache. */
178                 nm_ip6_config_reset_addresses (rdisc_config);
179
180                 /* rdisc->addresses contains at most max_addresses entries.
181                  * This is different from what the kernel does, which
182                  * also counts static and temporary addresses when checking
183                  * max_addresses.
184                  **/
185                 for (i = 0; i < rdisc->addresses->len; i++) {
186                         NMRDiscAddress *discovered_address = &g_array_index (rdisc->addresses, NMRDiscAddress, i);
187                         NMPlatformIP6Address address;
188
189                         memset (&address, 0, sizeof (address));
190                         address.address = discovered_address->address;
191                         address.plen = system_support ? 64 : 128;
192                         address.timestamp = discovered_address->timestamp;
193                         address.lifetime = discovered_address->lifetime;
194                         address.preferred = discovered_address->preferred;
195                         if (address.preferred > address.lifetime)
196                                 address.preferred = address.lifetime;
197                         address.source = NM_IP_CONFIG_SOURCE_RDISC;
198                         address.n_ifa_flags = ifa_flags;
199
200                         nm_ip6_config_add_address (rdisc_config, &address);
201                 }
202         }
203
204         if (changed & NM_RDISC_CONFIG_ROUTES) {
205                 /* Rebuild route list from router discovery cache. */
206                 nm_ip6_config_reset_routes (rdisc_config);
207
208                 for (i = 0; i < rdisc->routes->len; i++) {
209                         NMRDiscRoute *discovered_route = &g_array_index (rdisc->routes, NMRDiscRoute, i);
210                         NMPlatformIP6Route route;
211
212                         /* Only accept non-default routes.  The router has no idea what the
213                          * local configuration or user preferences are, so sending routes
214                          * with a prefix length of 0 is quite rude and thus ignored.
215                          */
216                         if (discovered_route->plen > 0) {
217                                 memset (&route, 0, sizeof (route));
218                                 route.network = discovered_route->network;
219                                 route.plen = discovered_route->plen;
220                                 route.gateway = discovered_route->gateway;
221                                 route.source = NM_IP_CONFIG_SOURCE_RDISC;
222                                 route.metric = global_opt.priority_v6;
223
224                                 nm_ip6_config_add_route (rdisc_config, &route);
225                         }
226                 }
227         }
228
229         if (changed & NM_RDISC_CONFIG_DHCP_LEVEL) {
230                 /* Unsupported until systemd DHCPv6 is ready */
231         }
232
233         if (changed & NM_RDISC_CONFIG_HOP_LIMIT)
234                 nm_platform_sysctl_set_ip6_hop_limit_safe (NM_PLATFORM_GET, global_opt.ifname, rdisc->hop_limit);
235
236         if (changed & NM_RDISC_CONFIG_MTU) {
237                 char val[16];
238
239                 g_snprintf (val, sizeof (val), "%d", rdisc->mtu);
240                 nm_platform_sysctl_set (NM_PLATFORM_GET, nm_utils_ip6_property_path (global_opt.ifname, "mtu"), val);
241         }
242
243         nm_ip6_config_merge (existing, rdisc_config, NM_IP_CONFIG_MERGE_DEFAULT);
244         if (!nm_ip6_config_commit (existing, ifindex, TRUE))
245                 nm_log_warn (LOGD_IP6, "(%s): failed to apply IPv6 config", global_opt.ifname);
246 }
247
248 static void
249 rdisc_ra_timeout (NMRDisc *rdisc, gpointer user_data)
250 {
251         if (global_opt.slaac_required) {
252                 nm_log_warn (LOGD_IP6, "(%s): IPv6 timed out or failed, quitting...", global_opt.ifname);
253                 g_main_loop_quit (main_loop);
254         } else
255                 nm_log_warn (LOGD_IP6, "(%s): IPv6 timed out or failed", global_opt.ifname);
256 }
257
258 static gboolean
259 quit_handler (gpointer user_data)
260 {
261         g_main_loop_quit (main_loop);
262         return G_SOURCE_REMOVE;
263 }
264
265 static void
266 setup_signals (void)
267 {
268         signal (SIGPIPE, SIG_IGN);
269         g_unix_signal_add (SIGINT, quit_handler, NULL);
270         g_unix_signal_add (SIGTERM, quit_handler, NULL);
271 }
272
273 static void
274 do_early_setup (int *argc, char **argv[])
275 {
276         gint64 priority64_v4 = -1;
277         gint64 priority64_v6 = -1;
278         GOptionEntry options[] = {
279                 /* Interface/IP config */
280                 { "ifname", 'i', 0, G_OPTION_ARG_STRING, &global_opt.ifname, N_("The interface to manage"), N_("eth0") },
281                 { "uuid", 'u', 0, G_OPTION_ARG_STRING, &global_opt.uuid, N_("Connection UUID"), N_("661e8cd0-b618-46b8-9dc9-31a52baaa16b") },
282                 { "slaac", 's', 0, G_OPTION_ARG_NONE, &global_opt.slaac, N_("Whether to manage IPv6 SLAAC"), NULL },
283                 { "slaac-required", '6', 0, G_OPTION_ARG_NONE, &global_opt.slaac_required, N_("Whether SLAAC must be successful"), NULL },
284                 { "slaac-tempaddr", 't', 0, G_OPTION_ARG_INT, &global_opt.tempaddr, N_("Use an IPv6 temporary privacy address"), NULL },
285                 { "dhcp4", 'd', 0, G_OPTION_ARG_STRING, &global_opt.dhcp4_address, N_("Current DHCPv4 address"), NULL },
286                 { "dhcp4-required", '4', 0, G_OPTION_ARG_NONE, &global_opt.dhcp4_required, N_("Whether DHCPv4 must be successful"), NULL },
287                 { "dhcp4-clientid", 'c', 0, G_OPTION_ARG_STRING, &global_opt.dhcp4_clientid, N_("Hex-encoded DHCPv4 client ID"), NULL },
288                 { "dhcp4-hostname", 'h', 0, G_OPTION_ARG_STRING, &global_opt.dhcp4_hostname, N_("Hostname to send to DHCP server"), N_("barbar") },
289                 { "dhcp4-fqdn",     'F', 0, G_OPTION_ARG_STRING, &global_opt.dhcp4_fqdn, N_("FQDN to send to DHCP server"), N_("host.domain.org") },
290                 { "priority4", '\0', 0, G_OPTION_ARG_INT64, &priority64_v4, N_("Route priority for IPv4"), N_("0") },
291                 { "priority6", '\0', 0, G_OPTION_ARG_INT64, &priority64_v6, N_("Route priority for IPv6"), N_("1024") },
292                 { "iid", 'e', 0, G_OPTION_ARG_STRING, &global_opt.iid_str, N_("Hex-encoded Interface Identifier"), "" },
293                 { "addr-gen-mode", 'e', 0, G_OPTION_ARG_INT, &global_opt.addr_gen_mode, N_("IPv6 SLAAC address generation mode"), "eui64" },
294                 { "logging-backend", '\0', 0, G_OPTION_ARG_STRING, &global_opt.logging_backend, N_("The logging backend configuration value. See logging.backend in NetworkManager.conf"), NULL },
295
296                 /* Logging/debugging */
297                 { "version", 'V', 0, G_OPTION_ARG_NONE, &global_opt.show_version, N_("Print NetworkManager version and exit"), NULL },
298                 { "no-daemon", 'n', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &global_opt.become_daemon, N_("Don't become a daemon"), NULL },
299                 { "debug", 'b', 0, G_OPTION_ARG_NONE, &global_opt.debug, N_("Don't become a daemon, and log to stderr"), NULL },
300                 { "log-level", 0, 0, G_OPTION_ARG_STRING, &global_opt.opt_log_level, N_("Log level: one of [%s]"), "INFO" },
301                 { "log-domains", 0, 0, G_OPTION_ARG_STRING, &global_opt.opt_log_domains,
302                   N_("Log domains separated by ',': any combination of [%s]"),
303                   "PLATFORM,RFKILL,WIFI" },
304                 { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &global_opt.g_fatal_warnings, N_("Make all warnings fatal"), NULL },
305                 {NULL}
306         };
307
308         if (!nm_main_utils_early_setup ("nm-iface-helper",
309                                         argc,
310                                         argv,
311                                         options,
312                                         NULL,
313                                         NULL,
314                                         _("nm-iface-helper is a small, standalone process that manages a single network interface.")))
315                 exit (1);
316
317         if (priority64_v4 >= 0 && priority64_v4 <= G_MAXUINT32)
318                 global_opt.priority_v4 = (guint32) priority64_v4;
319         if (priority64_v6 >= 0 && priority64_v6 <= G_MAXUINT32)
320                 global_opt.priority_v6 = (guint32) priority64_v6;
321 }
322
323 static void
324 ip6_address_changed (NMPlatform *platform,
325                      NMPObjectType obj_type,
326                      int iface,
327                      NMPlatformIP6Address *addr,
328                      NMPlatformSignalChangeType change_type,
329                      NMRDisc *rdisc)
330 {
331         if (   (change_type == NM_PLATFORM_SIGNAL_CHANGED && addr->n_ifa_flags & IFA_F_DADFAILED)
332             || (change_type == NM_PLATFORM_SIGNAL_REMOVED && addr->n_ifa_flags & IFA_F_TENTATIVE))
333                 nm_rdisc_dad_failed (rdisc, &addr->address);
334 }
335
336 int
337 main (int argc, char *argv[])
338 {
339         char *bad_domains = NULL;
340         GError *error = NULL;
341         gboolean wrote_pidfile = FALSE;
342         gs_free char *pidfile = NULL;
343         gs_unref_object NMDhcpClient *dhcp4_client = NULL;
344         gs_unref_object NMRDisc *rdisc = NULL;
345         GByteArray *hwaddr = NULL;
346         size_t hwaddr_len = 0;
347         gconstpointer tmp;
348         gs_free NMUtilsIPv6IfaceId *iid = NULL;
349         guint sd_id;
350
351         nm_g_type_init ();
352
353         setpgid (getpid (), getpid ());
354
355         do_early_setup (&argc, &argv);
356
357         if (global_opt.g_fatal_warnings) {
358                 GLogLevelFlags fatal_mask;
359
360                 fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
361                 fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
362                 g_log_set_always_fatal (fatal_mask);
363         }
364
365         if (global_opt.show_version) {
366                 fprintf (stdout, NM_DIST_VERSION "\n");
367                 exit (0);
368         }
369
370         nm_main_utils_ensure_root ();
371
372         if (!global_opt.ifname || !global_opt.uuid) {
373                 fprintf (stderr, _("An interface name and UUID are required\n"));
374                 exit (1);
375         }
376
377         ifindex = if_nametoindex (global_opt.ifname);
378         if (ifindex <= 0) {
379                 fprintf (stderr, _("Failed to find interface index for %s (%s)\n"), global_opt.ifname, strerror (errno));
380                 exit (1);
381         }
382         pidfile = g_strdup_printf (NMIH_PID_FILE_FMT, ifindex);
383         nm_main_utils_ensure_not_running_pidfile (pidfile);
384
385         nm_main_utils_ensure_rundir ();
386
387         if (!nm_logging_setup (global_opt.opt_log_level,
388                                global_opt.opt_log_domains,
389                                &bad_domains,
390                                &error)) {
391                 fprintf (stderr,
392                          _("%s.  Please use --help to see a list of valid options.\n"),
393                          error->message);
394                 exit (1);
395         } else if (bad_domains) {
396                 fprintf (stderr,
397                          _("Ignoring unrecognized log domain(s) '%s' passed on command line.\n"),
398                          bad_domains);
399                 g_clear_pointer (&bad_domains, g_free);
400         }
401
402         if (global_opt.become_daemon && !global_opt.debug) {
403                 if (daemon (0, 0) < 0) {
404                         int saved_errno;
405
406                         saved_errno = errno;
407                         fprintf (stderr, _("Could not daemonize: %s [error %u]\n"),
408                                  g_strerror (saved_errno),
409                                  saved_errno);
410                         exit (1);
411                 }
412                 if (nm_main_utils_write_pidfile (pidfile))
413                         wrote_pidfile = TRUE;
414         }
415
416         /* Set up unix signal handling - before creating threads, but after daemonizing! */
417         main_loop = g_main_loop_new (NULL, FALSE);
418         setup_signals ();
419
420         nm_logging_syslog_openlog (global_opt.logging_backend
421                                    ? global_opt.logging_backend
422                                    : (global_opt.debug ? "debug" : NULL));
423
424         nm_log_info (LOGD_CORE, "nm-iface-helper (version " NM_DIST_VERSION ") is starting...");
425
426         /* Set up platform interaction layer */
427         nm_linux_platform_setup ();
428
429         tmp = nm_platform_link_get_address (NM_PLATFORM_GET, ifindex, &hwaddr_len);
430         if (tmp) {
431                 hwaddr = g_byte_array_sized_new (hwaddr_len);
432                 g_byte_array_append (hwaddr, tmp, hwaddr_len);
433         }
434
435         if (global_opt.iid_str) {
436                 GBytes *bytes;
437                 gsize ignored = 0;
438
439                 bytes = nm_utils_hexstr2bin (global_opt.iid_str);
440                 if (!bytes || g_bytes_get_size (bytes) != sizeof (*iid)) {
441                         fprintf (stderr, _("(%s): Invalid IID %s\n"), global_opt.ifname, global_opt.iid_str);
442                         exit (1);
443                 }
444                 iid = g_bytes_unref_to_data (bytes, &ignored);
445         }
446
447         if (global_opt.dhcp4_address) {
448                 nm_platform_sysctl_set (NM_PLATFORM_GET, nm_utils_ip4_property_path (global_opt.ifname, "promote_secondaries"), "1");
449
450                 dhcp4_client = nm_dhcp_manager_start_ip4 (nm_dhcp_manager_get (),
451                                                           global_opt.ifname,
452                                                           ifindex,
453                                                           hwaddr,
454                                                           global_opt.uuid,
455                                                           global_opt.priority_v4,
456                                                           !!global_opt.dhcp4_hostname,
457                                                           global_opt.dhcp4_hostname,
458                                                           global_opt.dhcp4_fqdn,
459                                                           global_opt.dhcp4_clientid,
460                                                           45,
461                                                           NULL,
462                                                           global_opt.dhcp4_address);
463                 g_assert (dhcp4_client);
464                 g_signal_connect (dhcp4_client,
465                                   NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED,
466                                   G_CALLBACK (dhcp4_state_changed),
467                                   NULL);
468         }
469
470         if (global_opt.slaac) {
471                 nm_platform_link_set_user_ipv6ll_enabled (NM_PLATFORM_GET, ifindex, TRUE);
472
473                 rdisc = nm_lndp_rdisc_new (NM_PLATFORM_GET, ifindex, global_opt.ifname, global_opt.uuid, global_opt.addr_gen_mode, NULL);
474                 g_assert (rdisc);
475
476                 if (iid)
477                         nm_rdisc_set_iid (rdisc, *iid);
478
479                 nm_platform_sysctl_set (NM_PLATFORM_GET, nm_utils_ip6_property_path (global_opt.ifname, "accept_ra"), "1");
480                 nm_platform_sysctl_set (NM_PLATFORM_GET, nm_utils_ip6_property_path (global_opt.ifname, "accept_ra_defrtr"), "0");
481                 nm_platform_sysctl_set (NM_PLATFORM_GET, nm_utils_ip6_property_path (global_opt.ifname, "accept_ra_pinfo"), "0");
482                 nm_platform_sysctl_set (NM_PLATFORM_GET, nm_utils_ip6_property_path (global_opt.ifname, "accept_ra_rtr_pref"), "0");
483
484                 g_signal_connect (NM_PLATFORM_GET,
485                                   NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
486                                   G_CALLBACK (ip6_address_changed),
487                                   rdisc);
488                 g_signal_connect (rdisc,
489                                   NM_RDISC_CONFIG_CHANGED,
490                                   G_CALLBACK (rdisc_config_changed),
491                                   NULL);
492                 g_signal_connect (rdisc,
493                                   NM_RDISC_RA_TIMEOUT,
494                                   G_CALLBACK (rdisc_ra_timeout),
495                                   NULL);
496                 nm_rdisc_start (rdisc);
497         }
498
499         sd_id = nm_sd_event_attach_default ();
500
501         g_main_loop_run (main_loop);
502
503         g_clear_pointer (&hwaddr, g_byte_array_unref);
504
505         if (pidfile && wrote_pidfile)
506                 unlink (pidfile);
507
508         nm_log_info (LOGD_CORE, "exiting");
509
510         nm_clear_g_source (&sd_id);
511         exit (0);
512 }
513
514 /*******************************************************/
515 /* Stub functions */
516
517 void
518 nm_main_config_reload (int signal)
519 {
520         nm_log_info (LOGD_CORE, "reloading configuration not supported");
521 }
522
523 gconstpointer nm_config_get (void);
524 const char *nm_config_get_dhcp_client (gpointer unused);
525 gboolean nm_config_get_configure_and_quit (gpointer unused);
526 gconstpointer nm_bus_manager_get (void);
527 void nm_bus_manager_register_object (gpointer unused, gpointer object);
528 void nm_bus_manager_unregister_object (gpointer unused, gpointer object);
529
530 gconstpointer
531 nm_config_get (void)
532 {
533         return GUINT_TO_POINTER (1);
534 }
535
536 const char *
537 nm_config_get_dhcp_client (gpointer unused)
538 {
539         return "internal";
540 }
541
542 gboolean
543 nm_config_get_configure_and_quit (gpointer unused)
544 {
545         return TRUE;
546 }
547
548 gconstpointer
549 nm_bus_manager_get (void)
550 {
551         return GUINT_TO_POINTER (1);
552 }
553
554 void
555 nm_bus_manager_register_object (gpointer unused, gpointer object)
556 {
557 }
558
559 void
560 nm_bus_manager_unregister_object (gpointer unused, gpointer object)
561 {
562 }
563