gboolean
nm_dnsmasq_manager_start (NMDnsMasqManager *manager,
                          NMIP4Config *ip4_config,
                          GError **error)
{
	NMDnsMasqManagerPrivate *priv;
	NMCmdLine *dm_cmd;
	char *cmd_str;

	g_return_val_if_fail (NM_IS_DNSMASQ_MANAGER (manager), FALSE);
	if (error)
		g_return_val_if_fail (*error == NULL, FALSE);

	priv = NM_DNSMASQ_MANAGER_GET_PRIVATE (manager);

	kill_existing_for_iface (priv->iface, priv->pidfile);

	dm_cmd = create_dm_cmd_line (priv->iface, ip4_config, priv->pidfile, error);
	if (!dm_cmd)
		return FALSE;

	g_ptr_array_add (dm_cmd->array, NULL);

	nm_info ("Starting dnsmasq...");

	cmd_str = nm_cmd_line_to_str (dm_cmd);
	nm_debug ("Command line: %s", cmd_str);
	g_free (cmd_str);

	priv->pid = 0;
	if (!g_spawn_async (NULL, (char **) dm_cmd->array->pdata, NULL,
					G_SPAWN_DO_NOT_REAP_CHILD,
					dm_child_setup,
					NULL, &priv->pid, error)) {
		goto out;
	}

	nm_debug ("dnsmasq started with pid %d", priv->pid);

	priv->dm_watch_id = g_child_watch_add (priv->pid, (GChildWatchFunc) dm_watch_cb, manager);

 out:
	if (dm_cmd)
		nm_cmd_line_destroy (dm_cmd);

	return priv->pid > 0;
}
Exemplo n.º 2
0
gboolean
nm_ppp_manager_start (NMPPPManager *manager,
                      NMActRequest *req,
                      const char *ppp_name,
                      guint32 timeout_secs,
                      GError **err)
{
	NMPPPManagerPrivate *priv;
	NMConnection *connection;
	NMSettingPpp *s_ppp;
	gboolean s_ppp_created = FALSE;
	NMSettingPppoe *pppoe_setting;
	NMSettingAdsl *adsl_setting;
	NMCmdLine *ppp_cmd;
	char *cmd_str;
	struct stat st;

	g_return_val_if_fail (NM_IS_PPP_MANAGER (manager), FALSE);
	g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE);

	priv = NM_PPP_MANAGER_GET_PRIVATE (manager);

#if !WITH_PPP
	/* PPP support disabled */
	g_set_error_literal (err,
	                     NM_MANAGER_ERROR,
	                     NM_MANAGER_ERROR_FAILED,
	                     "PPP support is not enabled.");
	return FALSE;
#endif

	priv->pid = 0;

	/* Make sure /dev/ppp exists (bgo #533064) */
	if (stat ("/dev/ppp", &st) || !S_ISCHR (st.st_mode))
		nm_utils_modprobe (NULL, FALSE, "ppp_generic", NULL);

	connection = nm_act_request_get_applied_connection (req);
	g_assert (connection);

	s_ppp = nm_connection_get_setting_ppp (connection);
	if (!s_ppp) {
		/* If the PPP settings are all default we may not have a PPP setting yet,
		 * so just make a default one here.
		 */
		s_ppp = NM_SETTING_PPP (nm_setting_ppp_new ());
		s_ppp_created = TRUE;
	}
	
	pppoe_setting = nm_connection_get_setting_pppoe (connection);
	if (pppoe_setting)
		pppoe_fill_defaults (s_ppp);

	adsl_setting = (NMSettingAdsl *) nm_connection_get_setting (connection, NM_TYPE_SETTING_ADSL);

	ppp_cmd = create_pppd_cmd_line (manager, s_ppp, pppoe_setting, adsl_setting, ppp_name, err);
	if (!ppp_cmd)
		goto out;

	g_ptr_array_add (ppp_cmd->array, NULL);

	_LOGI ("starting PPP connection");

	cmd_str = nm_cmd_line_to_str (ppp_cmd);
	_LOGD ("command line: %s", cmd_str);
	g_free (cmd_str);

	priv->pid = 0;
	if (!g_spawn_async (NULL, (char **) ppp_cmd->array->pdata, NULL,
	                    G_SPAWN_DO_NOT_REAP_CHILD,
	                    nm_utils_setpgid, NULL,
	                    &priv->pid, err)) {
		goto out;
	}

	_LOGI ("pppd started with pid %d", priv->pid);

	priv->ppp_watch_id = g_child_watch_add (priv->pid, (GChildWatchFunc) ppp_watch_cb, manager);
	priv->ppp_timeout_handler = g_timeout_add_seconds (timeout_secs, pppd_timed_out, manager);
	priv->act_req = g_object_ref (req);

out:
	if (s_ppp_created)
		g_object_unref (s_ppp);

	if (ppp_cmd)
		nm_cmd_line_destroy (ppp_cmd);

	return priv->pid > 0;
}
static NMCmdLine *
create_dm_cmd_line (const char *iface,
                    NMIP4Config *ip4_config,
                    const char *pidfile,
                    GError **error)
{
	const char *dm_binary;
	NMCmdLine *cmd;
	GString *s;
	NMIP4Address *tmp;
	struct in_addr addr;
	char buf[INET_ADDRSTRLEN + 1];
	char localaddr[INET_ADDRSTRLEN + 1];

	dm_binary = nm_find_dnsmasq ();
	if (!dm_binary) {
		g_set_error (error, NM_DNSMASQ_MANAGER_ERROR, NM_DNSMASQ_MANAGER_ERROR_NOT_FOUND,
		             "Could not find dnsmasq binary.");
		return NULL;
	}

	/* Find the IP4 address to use */
	tmp = nm_ip4_config_get_address (ip4_config, 0);

	/* Create dnsmasq command line */
	cmd = nm_cmd_line_new ();
	nm_cmd_line_add_string (cmd, dm_binary);

	nm_cmd_line_add_string (cmd, "--no-hosts");
	nm_cmd_line_add_string (cmd, "--keep-in-foreground");
	nm_cmd_line_add_string (cmd, "--bind-interfaces");
	nm_cmd_line_add_string (cmd, "--no-poll");
	nm_cmd_line_add_string (cmd, "--except-interface=lo");

	s = g_string_new ("--listen-address=");
	addr.s_addr = nm_ip4_address_get_address (tmp);
	if (!inet_ntop (AF_INET, &addr, &localaddr[0], INET_ADDRSTRLEN)) {
		nm_warning ("%s: error converting IP4 address 0x%X",
		            __func__, ntohl (addr.s_addr));
		goto error;
	}
	g_string_append (s, localaddr);
	nm_cmd_line_add_string (cmd, s->str);
	g_string_free (s, TRUE);

	s = g_string_new ("--dhcp-range=");

	/* Add start of address range */
	addr.s_addr = nm_ip4_address_get_address (tmp) + htonl (9);
	if (!inet_ntop (AF_INET, &addr, &buf[0], INET_ADDRSTRLEN)) {
		nm_warning ("%s: error converting IP4 address 0x%X",
		            __func__, ntohl (addr.s_addr));
		goto error;
	}
	g_string_append (s, buf);

	g_string_append_c (s, ',');

	/* Add end of address range */
	addr.s_addr = nm_ip4_address_get_address (tmp) + htonl (99);
	if (!inet_ntop (AF_INET, &addr, &buf[0], INET_ADDRSTRLEN)) {
		nm_warning ("%s: error converting IP4 address 0x%X",
		            __func__, ntohl (addr.s_addr));
		goto error;
	}
	g_string_append (s, buf);

	g_string_append (s, ",60m");
	nm_cmd_line_add_string (cmd, s->str);
	g_string_free (s, TRUE);

	s = g_string_new ("--dhcp-option=option:router,");
	g_string_append (s, localaddr);
	nm_cmd_line_add_string (cmd, s->str);
	g_string_free (s, TRUE);

	nm_cmd_line_add_string (cmd, "--dhcp-lease-max=50");

	s = g_string_new ("--pid-file=");
	g_string_append (s, pidfile);
	nm_cmd_line_add_string (cmd, s->str);
	g_string_free (s, TRUE);

	return cmd;

error:
	nm_cmd_line_destroy (cmd);
	return NULL;
}
static NMCmdLine *
create_dm_cmd_line (const char *iface,
                    NMIP4Config *ip4_config,
                    const char *pidfile,
                    GError **error)
{
	NMCmdLine *cmd;
	GString *s;
	const NMPlatformIP4Address *tmp;
	char first[INET_ADDRSTRLEN];
	char last[INET_ADDRSTRLEN];
	char localaddr[INET_ADDRSTRLEN];
	char *error_desc = NULL;
	const char *dm_binary;

	dm_binary = nm_utils_find_helper ("dnsmasq", DNSMASQ_PATH, error);
	if (!dm_binary)
		return NULL;

	/* Create dnsmasq command line */
	cmd = nm_cmd_line_new ();
	nm_cmd_line_add_string (cmd, dm_binary);

	if (getenv ("NM_DNSMASQ_DEBUG")) {
		nm_cmd_line_add_string (cmd, "--log-dhcp");
		nm_cmd_line_add_string (cmd, "--log-queries");
	}

	/* dnsmasq may read from it's default config file location, which if that
	 * location is a valid config file, it will combine with the options here
	 * and cause undesirable side-effects.  Like sending bogus IP addresses
	 * as the gateway or whatever.  So tell dnsmasq not to use any config file
	 * at all.
	 */
	nm_cmd_line_add_string (cmd, "--conf-file");

	nm_cmd_line_add_string (cmd, "--no-hosts");
	nm_cmd_line_add_string (cmd, "--keep-in-foreground");
	nm_cmd_line_add_string (cmd, "--bind-interfaces");
	nm_cmd_line_add_string (cmd, "--except-interface=lo");
	nm_cmd_line_add_string (cmd, "--clear-on-reload");

	/* Use strict order since in the case of VPN connections, the VPN's
	 * nameservers will be first in resolv.conf, and those need to be tried
	 * first by dnsmasq to successfully resolve names from the VPN.
	 */
	nm_cmd_line_add_string (cmd, "--strict-order");

	/* Find the IP4 address to use */
	tmp = nm_ip4_config_get_address (ip4_config, 0);

	s = g_string_new ("--listen-address=");
	nm_utils_inet4_ntop (tmp->address, localaddr);
	g_string_append (s, localaddr);
	nm_cmd_line_add_string (cmd, s->str);
	g_string_free (s, TRUE);

	if (!nm_dnsmasq_utils_get_range (tmp, first, last, &error_desc)) {
		g_set_error_literal (error,
		                     NM_MANAGER_ERROR,
		                     NM_MANAGER_ERROR_FAILED,
		                     error_desc);
		nm_log_warn (LOGD_SHARING, "Failed to find DHCP address ranges: %s", error_desc);
		g_free (error_desc);
		nm_cmd_line_destroy (cmd);
		return NULL;
	}

	s = g_string_new ("--dhcp-range=");
	g_string_append_printf (s, "%s,%s,60m", first, last);
	nm_cmd_line_add_string (cmd, s->str);
	g_string_free (s, TRUE);

	s = g_string_new ("--dhcp-option=option:router,");
	g_string_append (s, localaddr);
	nm_cmd_line_add_string (cmd, s->str);
	g_string_free (s, TRUE);

	nm_cmd_line_add_string (cmd, "--dhcp-lease-max=50");

	s = g_string_new ("--pid-file=");
	g_string_append (s, pidfile);
	nm_cmd_line_add_string (cmd, s->str);
	g_string_free (s, TRUE);

	return cmd;
}