Thomas Haller 2016-10-04 12:21:40 +02:00
commit 6e9abe3d88
44 changed files with 1922 additions and 75 deletions

59
TODO
View file

@ -245,65 +245,6 @@ because the user has no physical access to the router itself, but has been given
as passphrase/PSK instead.
* Proxies
HTTP and other proxies are per-connection configuration. It's highly unlikely
that the same proxy you need to use at work is used at home or in a coffee shop.
Thus, it makes sense that which proxy settings to use should be updated when
network connections change. NetworkManager is a perfect place to do this since
it tracks which network connections are active, and it already queries the
network for automatic proxy configuration via DHCP and WPAD.
However, proxy handling is complicated and may require use of Javascript to
parse PAC files provided by WPAD, and this is not something NetworkManager
should do itself. Instead, that should be left to "proxy handlers", or external
utilities like libproxy or pacrunner that take raw proxy information, parse it,
and tell applications what proxy server to use for a specific network resource.
NetworkManager should provide all the proxy information it can find to these
external proxy handlers via the D-Bus interface and dispatcher scripts.
We should add a new NMSetting subclass called NMSettingProxy that holds
necessary proxy configuration. The properties of this setting should be a
superset of what is provided in the Firefox proxy configuration screen and the
various desktop environment proxy configuration tools like the GNOME Network
Proxy control panel; this should include at a minimum:
method: "auto", "manual", "none"
default-proxy: string
default-proxy-port: uint
default-always: boolean (use default proxy for all protocols)
ssl-proxy: string
ssl-proxy-port: uint
ftp-proxy: string
ftp-proxy-port: uint
socks-proxy: string
socks-proxy-port: uint
socks-version: uint, either 4 or 5
no-proxy-for: array of strings (things not to use the proxy for, ie ".foobar.com",
"192.168.0.1/24", an IPv6 address, etc)
pac-url: string (URL of PAC file, overrides DHCP-provided WPAD value)
(FIXME: proxy authentication? do we need separate user/pass properties for
each protocol type? should NM handle proxy auth or should it be punted
to each application?)
After completing IP configuration but still during the NM_DEVICE_STATE_IP_CONFIG
activation stage, NetworkManager would merge the automatically supplied proxy
configuration (from DHCP's WPAD option) with user-provided overrides from the
NMSettingProxy export the resulting proxy configuration via D-Bus and dispatcher
scripts. The 'default' connection's proxy configuration would be preferred, so
we'd have to update proxy configuration from nm-policy.c the same time we update
DNS information and the default route.
Merged proxy information should be exposed in two places. First, it should be
exported over D-Bus as a property of the org.freedesktop.NetworkManager.Device
interface. This property should be named "ProxyInfo" and should have the
D-Bus signature "a{sv}" (eg, dictionary) and should mirror the properties from
the NMSettingProxy object.
Second, it should be exported via the dispatcher to dispatcher scripts when
with the "up" and "down" events.
* Better Tablet/Mobile Behavior
There are a few components to this:

View file

@ -100,6 +100,46 @@ add_domains (GSList *items,
return items;
}
static GSList *
construct_proxy_items (GSList *items, GVariant *proxy_config, const char *prefix)
{
GVariant *val;
if (proxy_config == NULL)
return items;
if (prefix == NULL)
prefix = "";
/* PAC Url */
val = g_variant_lookup_value (proxy_config, "pac-url", G_VARIANT_TYPE_STRING);
if (val) {
char *str;
str = g_strdup_printf ("%sPROXY_PAC_URL=%s",
prefix,
g_variant_get_string (val, NULL));
items = g_slist_prepend (items, str);
g_variant_unref (val);
}
/* PAC Script */
val = g_variant_lookup_value (proxy_config, "pac-script", G_VARIANT_TYPE_STRING);
if (val) {
char *str;
str = g_strdup_printf ("%sPROXY_PAC_SCRIPT=%s",
prefix,
g_variant_get_string (val, NULL));
items = g_slist_prepend (items, str);
g_variant_unref (val);
}
return items;
}
static GSList *
construct_ip4_items (GSList *items, GVariant *ip4_config, const char *prefix)
{
@ -323,12 +363,14 @@ nm_dispatcher_utils_construct_envp (const char *action,
GVariant *connection_dict,
GVariant *connection_props,
GVariant *device_props,
GVariant *device_proxy_props,
GVariant *device_ip4_props,
GVariant *device_ip6_props,
GVariant *device_dhcp4_props,
GVariant *device_dhcp6_props,
const char *connectivity_state,
const char *vpn_ip_iface,
GVariant *vpn_proxy_props,
GVariant *vpn_ip4_props,
GVariant *vpn_ip6_props,
char **out_iface,
@ -443,6 +485,7 @@ nm_dispatcher_utils_construct_envp (const char *action,
/* Device it's aren't valid if the device isn't activated */
if (iface && (dev_state == NM_DEVICE_STATE_ACTIVATED)) {
items = construct_proxy_items (items, device_proxy_props, NULL);
items = construct_ip4_items (items, device_ip4_props, NULL);
items = construct_ip6_items (items, device_ip6_props, NULL);
items = construct_device_dhcp4_items (items, device_dhcp4_props);
@ -451,6 +494,7 @@ nm_dispatcher_utils_construct_envp (const char *action,
if (vpn_ip_iface) {
items = g_slist_prepend (items, g_strdup_printf ("VPN_IP_IFACE=%s", vpn_ip_iface));
items = construct_proxy_items (items, vpn_proxy_props, "VPN_");
items = construct_ip4_items (items, vpn_ip4_props, "VPN_");
items = construct_ip6_items (items, vpn_ip6_props, "VPN_");
}

View file

@ -26,12 +26,14 @@ nm_dispatcher_utils_construct_envp (const char *action,
GVariant *connection_dict,
GVariant *connection_props,
GVariant *device_props,
GVariant *device_proxy_props,
GVariant *device_ip4_props,
GVariant *device_ip6_props,
GVariant *device_dhcp4_props,
GVariant *device_dhcp6_props,
const char *connectivity_state,
const char *vpn_ip_iface,
GVariant *vpn_proxy_props,
GVariant *vpn_ip4_props,
GVariant *vpn_ip6_props,
char **out_iface,

View file

@ -76,12 +76,14 @@ handle_action (NMDBusDispatcher *dbus_dispatcher,
GVariant *connection_dict,
GVariant *connection_props,
GVariant *device_props,
GVariant *device_proxy_props,
GVariant *device_ip4_props,
GVariant *device_ip6_props,
GVariant *device_dhcp4_props,
GVariant *device_dhcp6_props,
const char *connectivity_state,
const char *vpn_ip_iface,
GVariant *vpn_proxy_props,
GVariant *vpn_ip4_props,
GVariant *vpn_ip6_props,
gboolean request_debug,
@ -665,12 +667,14 @@ handle_action (NMDBusDispatcher *dbus_dispatcher,
GVariant *connection_dict,
GVariant *connection_props,
GVariant *device_props,
GVariant *device_proxy_props,
GVariant *device_ip4_props,
GVariant *device_ip6_props,
GVariant *device_dhcp4_props,
GVariant *device_dhcp6_props,
const char *connectivity_state,
const char *vpn_ip_iface,
GVariant *vpn_proxy_props,
GVariant *vpn_ip4_props,
GVariant *vpn_ip6_props,
gboolean request_debug,
@ -697,12 +701,14 @@ handle_action (NMDBusDispatcher *dbus_dispatcher,
connection_dict,
connection_props,
device_props,
device_proxy_props,
device_ip4_props,
device_ip6_props,
device_dhcp4_props,
device_dhcp6_props,
connectivity_state,
vpn_ip_iface,
vpn_proxy_props,
vpn_ip4_props,
vpn_ip6_props,
&request->iface,

View file

@ -12,6 +12,10 @@ type=13
interface=virbr0
path=/org/freedesktop/NetworkManager/Devices/0
[proxy]
pac-url=http://networkmanager.com/proxy.pac
pac-script="function FindProxyForURL (url, host) {}"
[ip4]
addresses=192.168.122.1/24 0.0.0.0
domains=
@ -26,6 +30,8 @@ CONNECTION_ID=virbr0
CONNECTION_EXTERNAL=1
DEVICE_IFACE=virbr0
DEVICE_IP_IFACE=virbr0
PROXY_PAC_URL=http://networkmanager.com/proxy.pac
PROXY_PAC_SCRIPT="function FindProxyForURL (url, host) {}"
IP4_NUM_ADDRESSES=1
IP4_ADDRESS_0=192.168.122.1/24 0.0.0.0
IP4_GATEWAY=0.0.0.0

View file

@ -25,6 +25,10 @@ broadcast_address=192.168.1.255
subnet_mask=255.255.255.0
expiry=1304300446
[proxy]
pac-url=http://networkmanager.com/proxy.pac
pac-script="function FindProxyForURL (url, host) {}"
[ip4]
addresses=192.168.1.119/24 192.168.1.1
nameservers=68.87.77.134 68.87.72.134 192.168.1.1
@ -38,6 +42,8 @@ CONNECTION_ID=Random Connection
CONNECTION_FILENAME=/callouts/tests/dispatcher-up
DEVICE_IFACE=wlan0
DEVICE_IP_IFACE=wlan0
PROXY_PAC_URL=http://networkmanager.com/proxy.pac
PROXY_PAC_SCRIPT="function FindProxyForURL (url, host) {}"
IP4_ADDRESS_0=192.168.1.119/24 192.168.1.1
IP4_NUM_ADDRESSES=1
IP4_NAMESERVERS=68.87.77.134 68.87.72.134 192.168.1.1

View file

@ -25,6 +25,10 @@ broadcast_address=192.168.1.255
subnet_mask=255.255.255.0
expiry=1304349405
[proxy]
pac-url=http://networkmanager.com/proxy.pac
pac-script="function FindProxyForURL (url, host) {}"
[ip4]
addresses=192.168.1.119/24 192.168.1.1
nameservers=68.87.77.134 68.87.72.134 192.168.1.1
@ -38,6 +42,8 @@ CONNECTION_ID=Random Connection
CONNECTION_FILENAME=/callouts/tests/dispatcher-vpn-down
DEVICE_IFACE=wlan0
DEVICE_IP_IFACE=tun0
PROXY_PAC_URL=http://networkmanager.com/proxy.pac
PROXY_PAC_SCRIPT="function FindProxyForURL (url, host) {}"
IP4_ADDRESS_0=192.168.1.119/24 192.168.1.1
IP4_NUM_ADDRESSES=1
IP4_NAMESERVERS=68.87.77.134 68.87.72.134 192.168.1.1

View file

@ -25,6 +25,10 @@ broadcast_address=192.168.1.255
subnet_mask=255.255.255.0
expiry=1304349405
[proxy]
pac-url=http://networkmanager.com/proxy.pac
pac-script="function FindProxyForURL (url, host) {}"
[ip4]
addresses=192.168.1.119/24 192.168.1.1
nameservers=68.87.77.134 68.87.72.134 192.168.1.1
@ -38,6 +42,8 @@ CONNECTION_ID=Random Connection
CONNECTION_FILENAME=/callouts/tests/dispatcher-vpn-up
DEVICE_IFACE=wlan0
DEVICE_IP_IFACE=tun0
PROXY_PAC_URL=http://networkmanager.com/proxy.pac
PROXY_PAC_SCRIPT="function FindProxyForURL (url, host) {}"
IP4_ADDRESS_0=192.168.1.119/24 192.168.1.1
IP4_NUM_ADDRESSES=1
IP4_NAMESERVERS=68.87.77.134 68.87.72.134 192.168.1.1

View file

@ -193,6 +193,33 @@ add_uint_array (GKeyFile *kf,
return TRUE;
}
static gboolean
parse_proxy (GKeyFile *kf, GVariant **out_props, const char *section, GError **error)
{
GVariantBuilder props;
char *tmp;
g_variant_builder_init (&props, G_VARIANT_TYPE ("a{sv}"));
tmp = g_key_file_get_string (kf, section, "pac-url", error);
if (tmp == NULL)
return FALSE;
g_variant_builder_add (&props, "{sv}",
"pac-url",
g_variant_new_string (tmp));
g_free (tmp);
tmp = g_key_file_get_string (kf, section, "pac-script", error);
if (tmp == NULL)
return FALSE;
g_variant_builder_add (&props, "{sv}",
"pac-script",
g_variant_new_string (tmp));
g_free (tmp);
*out_props = g_variant_builder_end (&props);
return TRUE;
}
static gboolean
parse_ip4 (GKeyFile *kf, GVariant **out_props, const char *section, GError **error)
{
@ -357,12 +384,14 @@ get_dispatcher_file (const char *file,
GVariant **out_con_dict,
GVariant **out_con_props,
GVariant **out_device_props,
GVariant **out_device_proxy_props,
GVariant **out_device_ip4_props,
GVariant **out_device_ip6_props,
GVariant **out_device_dhcp4_props,
GVariant **out_device_dhcp6_props,
char **out_connectivity_state,
char **out_vpn_ip_iface,
GVariant **out_vpn_proxy_props,
GVariant **out_vpn_ip4_props,
GVariant **out_vpn_ip6_props,
char **out_expected_iface,
@ -378,12 +407,14 @@ get_dispatcher_file (const char *file,
g_assert (out_con_dict && !*out_con_dict);
g_assert (out_con_props && !*out_con_props);
g_assert (out_device_props && !*out_device_props);
g_assert (out_device_proxy_props && !*out_device_proxy_props);
g_assert (out_device_ip4_props && !*out_device_ip4_props);
g_assert (out_device_ip6_props && !*out_device_ip6_props);
g_assert (out_device_dhcp4_props && !*out_device_dhcp4_props);
g_assert (out_device_dhcp6_props && !*out_device_dhcp6_props);
g_assert (out_connectivity_state && !*out_connectivity_state);
g_assert (out_vpn_ip_iface && !*out_vpn_ip_iface);
g_assert (out_vpn_proxy_props && !*out_vpn_proxy_props);
g_assert (out_vpn_ip4_props && !*out_vpn_ip4_props);
g_assert (out_vpn_ip6_props && !*out_vpn_ip6_props);
g_assert (out_expected_iface && !*out_expected_iface);
@ -408,6 +439,11 @@ get_dispatcher_file (const char *file,
if (!parse_device (kf, out_device_props, error))
goto out;
if (g_key_file_has_group (kf, "proxy")) {
if (!parse_proxy (kf, out_device_proxy_props, "proxy", error))
goto out;
}
if (g_key_file_has_group (kf, "ip4")) {
if (!parse_ip4 (kf, out_device_ip4_props, "ip4", error))
goto out;
@ -452,12 +488,14 @@ test_generic (const char *file, const char *override_vpn_ip_iface)
gs_unref_variant GVariant *con_dict = NULL;
gs_unref_variant GVariant *con_props = NULL;
gs_unref_variant GVariant *device_props = NULL;
gs_unref_variant GVariant *device_proxy_props = NULL;
gs_unref_variant GVariant *device_ip4_props = NULL;
gs_unref_variant GVariant *device_ip6_props = NULL;
gs_unref_variant GVariant *device_dhcp4_props = NULL;
gs_unref_variant GVariant *device_dhcp6_props = NULL;
gs_free char *connectivity_change = NULL;
gs_free char *vpn_ip_iface = NULL;
gs_unref_variant GVariant *vpn_proxy_props = NULL;
gs_unref_variant GVariant *vpn_ip4_props = NULL;
gs_unref_variant GVariant *vpn_ip6_props = NULL;
gs_free char *expected_iface = NULL;
@ -477,12 +515,14 @@ test_generic (const char *file, const char *override_vpn_ip_iface)
&con_dict,
&con_props,
&device_props,
&device_proxy_props,
&device_ip4_props,
&device_ip6_props,
&device_dhcp4_props,
&device_dhcp6_props,
&connectivity_change,
&vpn_ip_iface,
&vpn_proxy_props,
&vpn_ip4_props,
&vpn_ip6_props,
&expected_iface,
@ -498,12 +538,14 @@ test_generic (const char *file, const char *override_vpn_ip_iface)
con_dict,
con_props,
device_props,
device_proxy_props,
device_ip4_props,
device_ip6_props,
device_dhcp4_props,
device_dhcp6_props,
connectivity_change,
override_vpn_ip_iface ? override_vpn_ip_iface : vpn_ip_iface,
vpn_proxy_props,
vpn_ip4_props,
vpn_ip6_props,
&out_iface,

View file

@ -899,6 +899,82 @@ nmc_team_check_config (const char *config, char **out_config, GError **error)
return TRUE;
}
/*
* nmc_proxy_check_script:
* @script: file name with PAC script, or raw PAC Script data
* @out_script: raw PAC Script (with removed new-line characters)
* @error: location to store error, or %NULL
*
* Check PAC Script from @script parameter and return the checked/sanitized
* config in @out_script.
*
* Returns: %TRUE if the script is valid, %FALSE if it is invalid
*/
gboolean
nmc_proxy_check_script (const char *script, char **out_script, GError **error)
{
enum {
_PAC_SCRIPT_TYPE_GUESS,
_PAC_SCRIPT_TYPE_FILE,
_PAC_SCRIPT_TYPE_JSON,
} desired_type = _PAC_SCRIPT_TYPE_GUESS;
const char *filename = NULL;
size_t c_len = 0;
gs_free char *script_clone = NULL;
*out_script = NULL;
if (!script || !script[0])
return TRUE;
if (g_str_has_prefix (script, "file://")) {
script += NM_STRLEN ("file://");
desired_type = _PAC_SCRIPT_TYPE_FILE;
} else if (g_str_has_prefix (script, "js://")) {
script += NM_STRLEN ("js://");
desired_type = _PAC_SCRIPT_TYPE_JSON;
}
if (NM_IN_SET (desired_type, _PAC_SCRIPT_TYPE_FILE, _PAC_SCRIPT_TYPE_GUESS)) {
gs_free char *contents = NULL;
if (!g_file_get_contents (script, &contents, &c_len, NULL)) {
if (desired_type == _PAC_SCRIPT_TYPE_FILE) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("cannot read pac-script from file '%s'"),
script);
return FALSE;
}
} else {
if (c_len != strlen (contents)) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("file '%s' contains non-valid utf-8"),
script);
return FALSE;
}
filename = script;
script = script_clone = g_steal_pointer (&contents);
}
}
if ( !strstr (script, "FindProxyForURL")
|| !g_utf8_validate (script, -1, NULL)) {
if (filename) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("'%s' does not contain a valid PAC Script"), filename);
} else {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("Not a valid PAC Script"));
}
return FALSE;
}
*out_script = (script == script_clone)
? g_steal_pointer (&script_clone)
: g_strdup (script);
return TRUE;
}
/*
* nmc_find_connection:
* @connections: array of NMConnections to search in

View file

@ -44,6 +44,7 @@ nmc_vlan_parse_priority_maps (const char *priority_map,
const char *nmc_bond_validate_mode (const char *mode, GError **error);
gboolean nmc_team_check_config (const char *config, char **out_config, GError **error);
gboolean nmc_proxy_check_script (const char *script, char **out_script, GError **error);
NMConnection *nmc_find_connection (const GPtrArray *connections,
const char *filter_type,

View file

@ -170,6 +170,7 @@ NmcOutputField nmc_fields_settings_names[] = {
SETTING_FIELD (NM_SETTING_IP_TUNNEL_SETTING_NAME, nmc_fields_setting_ip_tunnel + 1), /* 26 */
SETTING_FIELD (NM_SETTING_MACVLAN_SETTING_NAME, nmc_fields_setting_macvlan + 1), /* 27 */
SETTING_FIELD (NM_SETTING_VXLAN_SETTING_NAME, nmc_fields_setting_vxlan + 1), /* 28 */
SETTING_FIELD (NM_SETTING_PROXY_SETTING_NAME, nmc_fields_setting_proxy + 1), /* 29 */
{NULL, NULL, 0, NULL, NULL, FALSE, FALSE, 0}
};
#define NMC_FIELDS_SETTINGS_NAMES_ALL_X NM_SETTING_CONNECTION_SETTING_NAME","\
@ -199,7 +200,8 @@ NmcOutputField nmc_fields_settings_names[] = {
NM_SETTING_TUN_SETTING_NAME"," \
NM_SETTING_IP_TUNNEL_SETTING_NAME"," \
NM_SETTING_MACVLAN_SETTING_NAME"," \
NM_SETTING_VXLAN_SETTING_NAME
NM_SETTING_VXLAN_SETTING_NAME"," \
NM_SETTING_PROXY_SETTING_NAME
#define NMC_FIELDS_SETTINGS_NAMES_ALL NMC_FIELDS_SETTINGS_NAMES_ALL_X
/* Active connection data */
@ -2995,6 +2997,7 @@ static const NameItem nmc_bridge_slave_settings [] = {
static const NameItem nmc_no_slave_settings [] = {
{ NM_SETTING_IP4_CONFIG_SETTING_NAME, NULL, NULL, FALSE },
{ NM_SETTING_IP6_CONFIG_SETTING_NAME, NULL, NULL, FALSE },
{ NM_SETTING_PROXY_SETTING_NAME, NULL, NULL, FALSE },
{ NULL, NULL, NULL, FALSE }
};
@ -4301,6 +4304,10 @@ static OptionInfo option_info[] = {
{ NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_ADDRESSES, "ip6", OPTION_MULTI, N_("IPv6 address (IP[/plen]) [none]"), NULL,
set_ip6_address, NULL },
{ NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_GATEWAY, "gw6", OPTION_NONE, N_("IPv6 gateway [none]"), NULL, NULL, NULL },
{ NM_SETTING_PROXY_SETTING_NAME, NM_SETTING_PROXY_METHOD, "method", OPTION_NONE, N_("Proxy method"), NULL, NULL, NULL },
{ NM_SETTING_PROXY_SETTING_NAME, NM_SETTING_PROXY_BROWSER_ONLY, "browser-only", OPTION_NONE, N_("Browser Only"), NULL, NULL, NULL },
{ NM_SETTING_PROXY_SETTING_NAME, NM_SETTING_PROXY_PAC_URL, "pac-url", OPTION_NONE, N_("PAC Url"), NULL, NULL, NULL },
{ NM_SETTING_PROXY_SETTING_NAME, NM_SETTING_PROXY_PAC_SCRIPT, "pac-script", OPTION_NONE, N_("PAC Script"), NULL, NULL, NULL },
{ NULL, NULL, NULL, OPTION_NONE, NULL, NULL, NULL, NULL },
};
@ -4803,6 +4810,8 @@ setting_name_to_name (const char *name)
return _("IPv4 protocol");
if (strcmp (name, NM_SETTING_IP6_CONFIG_SETTING_NAME) == 0)
return _("IPv6 protocol");
if (strcmp (name, NM_SETTING_PROXY_SETTING_NAME) == 0)
return _("Proxy");
/* Should not happen; but let's still try to be somewhat sensible. */
return name;
@ -7087,6 +7096,8 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
nmc_setting_ip4_connect_handlers (NM_SETTING_IP_CONFIG (setting));
else if (NM_IS_SETTING_IP6_CONFIG (setting))
nmc_setting_ip6_connect_handlers (NM_SETTING_IP_CONFIG (setting));
else if (NM_IS_SETTING_PROXY (setting))
nmc_setting_proxy_connect_handlers (NM_SETTING_PROXY (setting));
nm_connection_add_setting (connection, setting);
}
@ -7733,6 +7744,11 @@ editor_init_new_connection (NmCli *nmc, NMConnection *connection)
setting = nm_setting_ip6_config_new ();
nmc_setting_custom_init (setting);
nm_connection_add_setting (connection, setting);
/* Also Proxy Setting */
setting = nm_setting_proxy_new ();
nmc_setting_custom_init (setting);
nm_connection_add_setting (connection, setting);
}
}
@ -7740,11 +7756,13 @@ static void
editor_init_existing_connection (NMConnection *connection)
{
NMSettingIPConfig *s_ip4, *s_ip6;
NMSettingProxy *s_proxy;
NMSettingWireless *s_wireless;
NMSettingConnection *s_con;
s_ip4 = nm_connection_get_setting_ip4_config (connection);
s_ip6 = nm_connection_get_setting_ip6_config (connection);
s_proxy = nm_connection_get_setting_proxy (connection);
s_wireless = nm_connection_get_setting_wireless (connection);
s_con = nm_connection_get_setting_connection (connection);
@ -7752,6 +7770,8 @@ editor_init_existing_connection (NMConnection *connection)
nmc_setting_ip4_connect_handlers (s_ip4);
if (s_ip6)
nmc_setting_ip6_connect_handlers (s_ip6);
if (s_proxy)
nmc_setting_proxy_connect_handlers (s_proxy);
if (s_wireless)
nmc_setting_wireless_connect_handlers (s_wireless);
if (s_con)

View file

@ -3313,6 +3313,7 @@ do_device_wifi_hotspot (NmCli *nmc, int argc, char **argv)
NMSettingWireless *s_wifi;
NMSettingWirelessSecurity *s_wsec;
NMSettingIPConfig *s_ip4, *s_ip6;
NMSettingProxy *s_proxy;
GBytes *ssid_bytes;
GError *error = NULL;
@ -3479,6 +3480,10 @@ do_device_wifi_hotspot (NmCli *nmc, int argc, char **argv)
nm_connection_add_setting (connection, NM_SETTING (s_ip6));
g_object_set (s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
s_proxy = (NMSettingProxy *) nm_setting_proxy_new ();
nm_connection_add_setting (connection, NM_SETTING (s_proxy));
g_object_set (s_proxy, NM_SETTING_PROXY_METHOD, NM_SETTING_PROXY_METHOD_NONE, NULL);
/* Activate the connection now */
nmc->nowait_flag = (nmc->timeout == 0);
nmc->should_wait++;

View file

@ -795,6 +795,20 @@ NmcOutputField nmc_fields_setting_vxlan[] = {
NM_SETTING_VXLAN_L2_MISS","\
NM_SETTING_VXLAN_L3_MISS
/* Available fields for NM_SETTING_PROXY_SETTING_NAME */
NmcOutputField nmc_fields_setting_proxy[] = {
SETTING_FIELD ("name"), /* 0 */
SETTING_FIELD (NM_SETTING_PROXY_METHOD), /* 1 */
SETTING_FIELD (NM_SETTING_PROXY_BROWSER_ONLY), /* 2 */
SETTING_FIELD (NM_SETTING_PROXY_PAC_URL), /* 3 */
SETTING_FIELD (NM_SETTING_PROXY_PAC_SCRIPT), /* 4 */
{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
};
#define NMC_FIELDS_SETTING_PROXY_ALL "name"","\
NM_SETTING_PROXY_METHOD","\
NM_SETTING_PROXY_BROWSER_ONLY","\
NM_SETTING_PROXY_PAC_URL","\
NM_SETTING_PROXY_PAC_SCRIPT
/*----------------------------------------------------------------------------*/
static char *
wep_key_type_to_string (NMWepKeyType type)
@ -2100,6 +2114,65 @@ DEFINE_GETTER (nmc_property_vxlan_get_rsc, NM_SETTING_VXLAN_RSC)
DEFINE_GETTER (nmc_property_vxlan_get_l2_miss, NM_SETTING_VXLAN_L2_MISS)
DEFINE_GETTER (nmc_property_vxlan_get_l3_miss, NM_SETTING_VXLAN_L3_MISS)
/* --- NM_SETTING_PROXY_SETTING_NAME property get functions --- */
DEFINE_GETTER (nmc_property_proxy_get_browser_only, NM_SETTING_PROXY_BROWSER_ONLY)
DEFINE_GETTER (nmc_property_proxy_get_pac_url, NM_SETTING_PROXY_PAC_URL)
DEFINE_GETTER (nmc_property_proxy_get_pac_script, NM_SETTING_PROXY_PAC_SCRIPT)
static char *
nmc_property_proxy_get_method (NMSetting *setting, NmcPropertyGetType get_type)
{
NMSettingProxy *s_proxy = NM_SETTING_PROXY (setting);
NMSettingProxyMethod method;
method = nm_setting_proxy_get_method (s_proxy);
return nm_utils_enum_to_str (nm_setting_proxy_method_get_type (), method);
}
static gboolean
nmc_property_proxy_set_method (NMSetting *setting, const char *prop,
const char *val, GError **error)
{
NMSettingProxyMethod method;
gboolean ret;
ret = nm_utils_enum_from_str (nm_setting_proxy_method_get_type(), val,
(int *) &method, NULL);
if (!ret) {
gs_free const char **values = NULL;
gs_free char *values_str = NULL;
values = nm_utils_enum_get_values (nm_setting_proxy_method_get_type (),
NM_SETTING_PROXY_METHOD_AUTO,
G_MAXINT);
values_str = g_strjoinv (",", (char **) values);
g_set_error (error, 1, 0, _("invalid method '%s', use one of %s"),
val, values_str);
return FALSE;
}
g_object_set (setting, prop, method, NULL);
return TRUE;
}
static gboolean
nmc_property_proxy_set_pac_script (NMSetting *setting, const char *prop,
const char *val, GError **error)
{
char *script = NULL;
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (!nmc_proxy_check_script (val, &script, error)) {
return FALSE;
}
g_object_set (setting, prop, script, NULL);
g_free (script);
return TRUE;
}
/*----------------------------------------------------------------------------*/
static void
@ -2310,6 +2383,21 @@ ipv6_method_changed_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
g_signal_handlers_unblock_by_func (object, G_CALLBACK (ipv6_addresses_changed_cb), NULL);
}
static void
proxy_method_changed_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
{
NMSettingProxyMethod method;
method = nm_setting_proxy_get_method (NM_SETTING_PROXY (object));
if (method == NM_SETTING_PROXY_METHOD_NONE) {
g_object_set (object,
NM_SETTING_PROXY_PAC_URL, NULL,
NM_SETTING_PROXY_PAC_SCRIPT, NULL,
NULL);
}
}
static void
wireless_band_channel_changed_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
{
@ -2387,6 +2475,15 @@ nmc_setting_ip6_connect_handlers (NMSettingIPConfig *setting)
G_CALLBACK (ipv6_method_changed_cb), NULL);
}
void
nmc_setting_proxy_connect_handlers (NMSettingProxy *setting)
{
g_return_if_fail (NM_IS_SETTING_PROXY (setting));
g_signal_connect (setting, "notify::" NM_SETTING_PROXY_METHOD,
G_CALLBACK (proxy_method_changed_cb), NULL);
}
void
nmc_setting_wireless_connect_handlers (NMSettingWireless *setting)
{
@ -2460,6 +2557,10 @@ nmc_setting_custom_init (NMSetting *setting)
g_object_set (NM_SETTING_IP_CONFIG (setting),
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO,
NULL);
} else if (NM_IS_SETTING_PROXY (setting)) {
g_object_set (NM_SETTING_PROXY (setting),
NM_SETTING_PROXY_METHOD, NM_SETTING_PROXY_METHOD_NONE,
NULL);
} else if (NM_IS_SETTING_TUN (setting)) {
g_object_set (NM_SETTING_TUN (setting),
NM_SETTING_TUN_MODE, NM_SETTING_TUN_MODE_TUN,
@ -7787,6 +7888,36 @@ nmc_properties_init (void)
NULL,
NULL,
NULL);
/* Add editable properties for NM_SETTING_PROXY_SETTING_NAME */
nmc_add_prop_funcs (GLUE (PROXY, METHOD),
nmc_property_proxy_get_method,
nmc_property_proxy_set_method,
NULL,
NULL,
NULL,
NULL);
nmc_add_prop_funcs (GLUE (PROXY, BROWSER_ONLY),
nmc_property_proxy_get_browser_only,
nmc_property_set_bool,
NULL,
NULL,
NULL,
NULL);
nmc_add_prop_funcs (GLUE (PROXY, PAC_URL),
nmc_property_proxy_get_pac_url,
nmc_property_set_string,
NULL,
NULL,
NULL,
NULL);
nmc_add_prop_funcs (GLUE (PROXY, PAC_SCRIPT),
nmc_property_proxy_get_pac_script,
nmc_property_proxy_set_pac_script,
NULL,
NULL,
NULL,
NULL);
}
void
@ -9042,7 +9173,7 @@ setting_macvlan_details (NMSetting *setting, NmCli *nmc, const char *one_prop,
return TRUE;
}
static gboolean
static gboolean
setting_vxlan_details (NMSetting *setting, NmCli *nmc, const char *one_prop, gboolean secrets)
{
NMSettingVxlan *s_vxlan = NM_SETTING_VXLAN (setting);
@ -9083,6 +9214,35 @@ setting_vxlan_details (NMSetting *setting, NmCli *nmc, const char *one_prop, gb
return TRUE;
}
static gboolean
setting_proxy_details (NMSetting *setting, NmCli *nmc, const char *one_prop, gboolean secrets)
{
NMSettingProxy *s_proxy = NM_SETTING_PROXY (setting);
NmcOutputField *tmpl, *arr;
size_t tmpl_len;
g_return_val_if_fail (NM_IS_SETTING_PROXY (s_proxy), FALSE);
tmpl = nmc_fields_setting_proxy;
tmpl_len = sizeof (nmc_fields_setting_proxy);
nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_PROXY_ALL,
tmpl, FALSE, NULL, NULL);
arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
g_ptr_array_add (nmc->output_data, arr);
arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
set_val_str (arr, 1, nmc_property_proxy_get_method (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 2, nmc_property_proxy_get_browser_only (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 3, nmc_property_proxy_get_pac_url (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 4, nmc_property_proxy_get_pac_script (setting, NMC_PROPERTY_GET_PRETTY));
g_ptr_array_add (nmc->output_data, arr);
print_data (nmc); /* Print all data */
return TRUE;
}
typedef struct {
const char *sname;
gboolean (*func) (NMSetting *setting, NmCli *nmc, const char *one_prop, gboolean secrets);
@ -9118,6 +9278,7 @@ static const SettingDetails detail_printers[] = {
{ NM_SETTING_IP_TUNNEL_SETTING_NAME, setting_ip_tunnel_details },
{ NM_SETTING_MACVLAN_SETTING_NAME, setting_macvlan_details },
{ NM_SETTING_VXLAN_SETTING_NAME, setting_vxlan_details },
{ NM_SETTING_PROXY_SETTING_NAME, setting_proxy_details },
{ NULL },
};

View file

@ -32,6 +32,7 @@ NMSetting *nmc_setting_new_for_name (const char *name);
void nmc_setting_custom_init (NMSetting *setting);
void nmc_setting_ip4_connect_handlers (NMSettingIPConfig *setting);
void nmc_setting_ip6_connect_handlers (NMSettingIPConfig *setting);
void nmc_setting_proxy_connect_handlers (NMSettingProxy *setting);
void nmc_setting_wireless_connect_handlers (NMSettingWireless *setting);
void nmc_setting_connection_connect_handlers (NMSettingConnection *setting, NMConnection *connection);
@ -92,5 +93,6 @@ extern NmcOutputField nmc_fields_setting_tun[];
extern NmcOutputField nmc_fields_setting_ip_tunnel[];
extern NmcOutputField nmc_fields_setting_macvlan[];
extern NmcOutputField nmc_fields_setting_vxlan[];
extern NmcOutputField nmc_fields_setting_proxy[];
#endif /* NMC_SETTINGS_H */

View file

@ -32,6 +32,7 @@ libnm_core_headers = \
$(core)/nm-setting-olpc-mesh.h \
$(core)/nm-setting-ppp.h \
$(core)/nm-setting-pppoe.h \
$(core)/nm-setting-proxy.h \
$(core)/nm-setting-serial.h \
$(core)/nm-setting-team-port.h \
$(core)/nm-setting-team.h \
@ -94,6 +95,7 @@ libnm_core_sources = \
$(core)/nm-setting-olpc-mesh.c \
$(core)/nm-setting-ppp.c \
$(core)/nm-setting-pppoe.c \
$(core)/nm-setting-proxy.c \
$(core)/nm-setting-serial.c \
$(core)/nm-setting-team-port.c \
$(core)/nm-setting-team.c \

View file

@ -2180,6 +2180,24 @@ nm_connection_get_setting_pppoe (NMConnection *connection)
return (NMSettingPppoe *) nm_connection_get_setting (connection, NM_TYPE_SETTING_PPPOE);
}
/**
* nm_connection_get_setting_proxy:
* @connection: the #NMConnection
*
* A shortcut to return any #NMSettingProxy the connection might contain.
*
* Returns:an #NMSettingProxy if the connection contains one, otherwise %NULL
*
* Since: 1.6
**/
NMSettingProxy *
nm_connection_get_setting_proxy (NMConnection *connection)
{
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
return (NMSettingProxy *) nm_connection_get_setting (connection, NM_TYPE_SETTING_PROXY);
}
/**
* nm_connection_get_setting_serial:
* @connection: the #NMConnection

View file

@ -211,6 +211,8 @@ NMSettingMacvlan * nm_connection_get_setting_macvlan (NMConnec
NMSettingOlpcMesh * nm_connection_get_setting_olpc_mesh (NMConnection *connection);
NMSettingPpp * nm_connection_get_setting_ppp (NMConnection *connection);
NMSettingPppoe * nm_connection_get_setting_pppoe (NMConnection *connection);
NM_AVAILABLE_IN_1_6
NMSettingProxy * nm_connection_get_setting_proxy (NMConnection *connection);
NMSettingSerial * nm_connection_get_setting_serial (NMConnection *connection);
NMSettingTun * nm_connection_get_setting_tun (NMConnection *connection);
NMSettingVpn * nm_connection_get_setting_vpn (NMConnection *connection);

View file

@ -49,6 +49,7 @@
#include "nm-setting-gsm.h"
#include "nm-setting-infiniband.h"
#include "nm-setting-ip-tunnel.h"
#include "nm-setting-proxy.h"
#include "nm-setting-ip4-config.h"
#include "nm-setting-ip6-config.h"
#include "nm-setting-macvlan.h"

View file

@ -43,6 +43,7 @@ typedef struct _NMSettingGsm NMSettingGsm;
typedef struct _NMSettingInfiniband NMSettingInfiniband;
typedef struct _NMSettingIPConfig NMSettingIPConfig;
typedef struct _NMSettingIPTunnel NMSettingIPTunnel;
typedef struct _NMSettingProxy NMSettingProxy;
typedef struct _NMSettingIP4Config NMSettingIP4Config;
typedef struct _NMSettingIP6Config NMSettingIP6Config;
typedef struct _NMSettingMacvlan NMSettingMacvlan;

View file

@ -0,0 +1,330 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* (C) Copyright 2016 Atul Anand <atulhjp@gmail.com>.
*/
#include "nm-default.h"
#include "nm-setting-proxy.h"
#include "nm-utils.h"
#include "nm-setting-private.h"
/**
* SECTION:nm-setting-proxy
* @short_description: Describes Proxy Url, Script and other related properties
*
* The #NMSettingProxy object is a #NMSetting subclass that describes properties
* related to Proxy settings like Pac Url, Pac Script etc.
*
* NetworkManager support 2 values for the #NMSettingProxy:method property for
* proxy. If "auto" is specified then WPAD takes places and the appropriate details
* are pushed into PacRunner or user can override this URL with a new PAC url or a
* PAC Script. If "none" is selected then no proxy configuration is given to PacRunner
* to fulfill client queries.
**/
G_DEFINE_TYPE_WITH_CODE (NMSettingProxy, nm_setting_proxy, NM_TYPE_SETTING,
_nm_register_setting (PROXY, 4))
NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_PROXY)
#define NM_SETTING_PROXY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_PROXY, NMSettingProxyPrivate))
typedef struct {
NMSettingProxyMethod method;
gboolean browser_only;
char *pac_url;
char *pac_script;
} NMSettingProxyPrivate;
enum {
PROP_0,
PROP_METHOD,
PROP_BROWSER_ONLY,
PROP_PAC_URL,
PROP_PAC_SCRIPT,
LAST_PROP
};
/**
* nm_setting_proxy_new:
*
* Creates a new #NMSettingProxy object.
*
* Returns: the new empty #NMSettingProxy object
*
* Since: 1.6
**/
NMSetting *
nm_setting_proxy_new (void)
{
return (NMSetting *) g_object_new (NM_TYPE_SETTING_PROXY, NULL);
}
/**
* nm_setting_proxy_get_method:
* @setting: the #NMSettingProxy
*
* Returns the proxy configuration method. By default the value is "NONE".
* "NONE" should be selected for a connection intended for direct network
* access.
*
* Returns: the proxy configuration method
*
* Since: 1.6
**/
NMSettingProxyMethod
nm_setting_proxy_get_method (NMSettingProxy *setting)
{
g_return_val_if_fail (NM_IS_SETTING_PROXY (setting), NM_SETTING_PROXY_METHOD_NONE);
return NM_SETTING_PROXY_GET_PRIVATE (setting)->method;
}
/**
* nm_setting_proxy_get_browser_only:
* @setting: the #NMSettingProxy
*
* Returns: TRUE if this proxy configuration is only for Browser
* clients/schemes otherwise FALSE.
*
* Since: 1.6
**/
gboolean
nm_setting_proxy_get_browser_only (NMSettingProxy *setting)
{
g_return_val_if_fail (NM_IS_SETTING_PROXY (setting), FALSE);
return NM_SETTING_PROXY_GET_PRIVATE (setting)->browser_only;
}
/**
* nm_setting_proxy_get_pac_url:
* @setting: the #NMSettingProxy
*
* Returns: the PAC url for obtaining PAC file
*
* Since: 1.6
**/
const char *
nm_setting_proxy_get_pac_url (NMSettingProxy *setting)
{
g_return_val_if_fail (NM_IS_SETTING_PROXY (setting), NULL);
return NM_SETTING_PROXY_GET_PRIVATE (setting)->pac_url;
}
/**
* nm_setting_proxy_get_pac_script:
* @setting: the #NMSettingProxy
*
* Returns: the PAC Script
*
* Since: 1.6
**/
const char *
nm_setting_proxy_get_pac_script (NMSettingProxy *setting)
{
g_return_val_if_fail (NM_IS_SETTING_PROXY (setting), NULL);
return NM_SETTING_PROXY_GET_PRIVATE (setting)->pac_script;
}
static gboolean
verify (NMSetting *setting, NMConnection *connection, GError **error)
{
NMSettingProxyPrivate *priv = NM_SETTING_PROXY_GET_PRIVATE (setting);
NMSettingProxyMethod method;
method = priv->method;
if (method == NM_SETTING_PROXY_METHOD_NONE) {
if (priv->pac_url) {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("this property is not allowed for method none"));
g_prefix_error (error, "%s.%s: ", NM_SETTING_PROXY_SETTING_NAME, NM_SETTING_PROXY_PAC_URL);
return FALSE;
}
if (priv->pac_script) {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("this property is not allowed for method none"));
g_prefix_error (error, "%s.%s: ", NM_SETTING_PROXY_SETTING_NAME, NM_SETTING_PROXY_PAC_SCRIPT);
return FALSE;
}
}
if (priv->pac_script && strlen (priv->pac_script) > 1*1024*1024) {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("the script is too large"));
g_prefix_error (error, "%s.%s: ", NM_SETTING_PROXY_SETTING_NAME, NM_SETTING_PROXY_PAC_SCRIPT);
return FALSE;
}
return TRUE;
}
static void
nm_setting_proxy_init (NMSettingProxy *setting)
{
NMSettingProxyPrivate *priv = NM_SETTING_PROXY_GET_PRIVATE (setting);
priv->method = NM_SETTING_PROXY_METHOD_NONE;
}
static void
finalize (GObject *object)
{
NMSettingProxy *self = NM_SETTING_PROXY (object);
NMSettingProxyPrivate *priv = NM_SETTING_PROXY_GET_PRIVATE (self);
g_free (priv->pac_url);
g_free (priv->pac_script);
G_OBJECT_CLASS (nm_setting_proxy_parent_class)->finalize (object);
}
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMSettingProxy *setting = NM_SETTING_PROXY (object);
switch (prop_id) {
case PROP_METHOD:
g_value_set_int (value, nm_setting_proxy_get_method (setting));
break;
case PROP_BROWSER_ONLY:
g_value_set_boolean (value, nm_setting_proxy_get_browser_only (setting));
break;
case PROP_PAC_URL:
g_value_set_string (value, nm_setting_proxy_get_pac_url (setting));
break;
case PROP_PAC_SCRIPT:
g_value_set_string (value, nm_setting_proxy_get_pac_script (setting));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
NMSettingProxyPrivate *priv = NM_SETTING_PROXY_GET_PRIVATE (object);
switch (prop_id) {
case PROP_METHOD:
priv->method = g_value_get_int (value);
break;
case PROP_BROWSER_ONLY:
priv->browser_only = g_value_get_boolean (value);
break;
case PROP_PAC_URL:
g_free (priv->pac_url);
priv->pac_url = g_value_dup_string (value);
break;
case PROP_PAC_SCRIPT:
g_free (priv->pac_script);
priv->pac_script = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
nm_setting_proxy_class_init (NMSettingProxyClass *setting_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
g_type_class_add_private (setting_class, sizeof (NMSettingProxyPrivate));
/* virtual methods */
object_class->set_property = set_property;
object_class->get_property = get_property;
object_class->finalize = finalize;
parent_class->verify = verify;
/**
* NMSettingProxy:method:
*
* Method for proxy configuration, Default is "NONE"
*
* Since: 1.6
**/
g_object_class_install_property
(object_class, PROP_METHOD,
g_param_spec_int (NM_SETTING_PROXY_METHOD, "", "",
G_MININT32, G_MAXINT32, NM_SETTING_PROXY_METHOD_NONE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
/**
* NMSettingProxy:browser-only:
*
* TRUE if Proxy is for Browser Stuff.
*
* Since: 1.6
**/
g_object_class_install_property
(object_class, PROP_BROWSER_ONLY,
g_param_spec_boolean (NM_SETTING_PROXY_BROWSER_ONLY, "", "",
FALSE,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
/**
* NMSettingProxy:pac-url:
*
* PAC Url for obtaining PAC File.
*
* Since: 1.6
**/
g_object_class_install_property
(object_class, PROP_PAC_URL,
g_param_spec_string (NM_SETTING_PROXY_PAC_URL, "", "",
NULL,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
/**
* NMSettingProxy:pac-script:
*
* PAC Script For the connection.
*
* Since: 1.6
**/
g_object_class_install_property
(object_class, PROP_PAC_SCRIPT,
g_param_spec_string (NM_SETTING_PROXY_PAC_SCRIPT, "", "",
NULL,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
}

View file

@ -0,0 +1,88 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* (C) Copyright 2016 Atul Anand <atulhjp@gmail.com>.
*/
#ifndef __NM_SETTING_PROXY_H__
#define __NM_SETTING_PROXY_H__
#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
#error "Only <NetworkManager.h> can be included directly."
#endif
#include <nm-setting.h>
G_BEGIN_DECLS
/**
* NMSettingProxyMethod:
* @NM_SETTING_PROXY_METHOD_AUTO: DHCP obtained Proxy/ Manual override
* @NM_SETTING_PROXY_METHOD_NONE: No Proxy for the Connection
*
* The Proxy method.
*
* Since: 1.6
*/
typedef enum {
NM_SETTING_PROXY_METHOD_AUTO = 0,
NM_SETTING_PROXY_METHOD_NONE
} NMSettingProxyMethod;
#define NM_TYPE_SETTING_PROXY (nm_setting_proxy_get_type ())
#define NM_SETTING_PROXY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_PROXY, NMSettingProxy))
#define NM_SETTING_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_PROXY, NMSettingProxyClass))
#define NM_IS_SETTING_PROXY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_PROXY))
#define NM_IS_SETTING_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_PROXY))
#define NM_SETTING_PROXY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_PROXY, NMSettingProxyClass))
#define NM_SETTING_PROXY_SETTING_NAME "proxy"
#define NM_SETTING_PROXY_METHOD "method"
#define NM_SETTING_PROXY_BROWSER_ONLY "browser-only"
#define NM_SETTING_PROXY_PAC_URL "pac-url"
#define NM_SETTING_PROXY_PAC_SCRIPT "pac-script"
struct _NMSettingProxy {
NMSetting parent;
};
typedef struct {
NMSettingClass parent;
gpointer padding[4];
} NMSettingProxyClass;
NM_AVAILABLE_IN_1_6
GType nm_setting_proxy_get_type (void);
NM_AVAILABLE_IN_1_6
NMSetting *nm_setting_proxy_new (void);
NM_AVAILABLE_IN_1_6
NMSettingProxyMethod nm_setting_proxy_get_method (NMSettingProxy *setting);
NM_AVAILABLE_IN_1_6
gboolean nm_setting_proxy_get_browser_only (NMSettingProxy *setting);
NM_AVAILABLE_IN_1_6
const char *nm_setting_proxy_get_pac_url (NMSettingProxy *setting);
NM_AVAILABLE_IN_1_6
const char *nm_setting_proxy_get_pac_script (NMSettingProxy *setting);
G_END_DECLS
#endif /* __NM_SETTING_PROXY_H__ */

View file

@ -183,6 +183,9 @@ typedef enum {
/* string: VPN interface name (tun0, tap0, etc) */
#define NM_VPN_PLUGIN_CONFIG_TUNDEV "tundev"
/* string: Proxy PAC */
#define NM_VPN_PLUGIN_CONFIG_PROXY_PAC "pac"
/* string: Login message */
#define NM_VPN_PLUGIN_CONFIG_BANNER "banner"

View file

@ -62,6 +62,7 @@
#include <nm-setting-infiniband.h>
#include <nm-setting-ip-config.h>
#include <nm-setting-ip-tunnel.h>
#include <nm-setting-proxy.h>
#include <nm-setting-ip4-config.h>
#include <nm-setting-ip6-config.h>
#include <nm-setting-macvlan.h>

View file

@ -1087,5 +1087,13 @@ global:
libnm_1_6_0 {
global:
nm_capability_get_type;
nm_connection_get_setting_proxy;
nm_setting_proxy_get_type;
nm_setting_proxy_new;
nm_setting_proxy_get_method;
nm_setting_proxy_method_get_type;
nm_setting_proxy_get_browser_only;
nm_setting_proxy_get_pac_url;
nm_setting_proxy_get_pac_script;
nm_utils_is_json_object;
} libnm_1_4_0;

View file

@ -1983,6 +1983,19 @@ It's equivalent of using <literal>+ipv6.addresses</literal> syntax.</entry>
</tbody>
</tgroup></table>
<table><title>Proxy options</title><tgroup cols="3">
<thead>
<row><entry>Alias</entry><entry>Property</entry><entry>Note</entry></row>
</thead>
<tbody>
<row>
<entry align="left"></entry>
<entry align="left"><link linkend="nm-settings.property.proxy.pac-script">proxy.pac-script</link></entry>
<entry align="left" valign="top">Read the java script pac-script from file or pass it directly on the command line. Prefix the value with "file://" or "js://" to force one or the other.</entry>
</row>
</tbody>
</tgroup></table>
</refsect1>
<refsect1 id='environment_variables'><title>Environment Variables</title>

View file

@ -71,6 +71,7 @@ libnm-core/nm-setting-macvlan.c
libnm-core/nm-setting-olpc-mesh.c
libnm-core/nm-setting-ppp.c
libnm-core/nm-setting-pppoe.c
libnm-core/nm-setting-proxy.c
libnm-core/nm-setting-team.c
libnm-core/nm-setting-team-port.c
libnm-core/nm-setting-tun.c

View file

@ -442,6 +442,8 @@ libNetworkManager_la_SOURCES = \
nm-exported-object.h \
nm-firewall-manager.c \
nm-firewall-manager.h \
nm-proxy-config.c \
nm-proxy-config.h \
nm-ip4-config.c \
nm-ip4-config.h \
nm-ip6-config.c \
@ -456,6 +458,8 @@ libNetworkManager_la_SOURCES = \
nm-manager.h \
nm-multi-index.c \
nm-multi-index.h \
nm-pacrunner-manager.c \
nm-pacrunner-manager.h \
nm-policy.c \
nm-policy.h \
nm-rfkill-manager.c \
@ -556,6 +560,9 @@ nm_iface_helper_SOURCES = \
platform/wifi/wifi-utils.c \
platform/wifi/wifi-utils.h \
\
nm-pacrunner-manager.c \
nm-pacrunner-manager.h \
\
rdisc/nm-lndp-rdisc.c \
rdisc/nm-lndp-rdisc.h \
rdisc/nm-rdisc.c \
@ -566,6 +573,8 @@ nm_iface_helper_SOURCES = \
\
nm-exported-object.c \
nm-exported-object.h \
nm-proxy-config.c \
nm-proxy-config.h \
nm-ip4-config.c \
nm-ip4-config.h \
nm-ip6-config.c \

View file

@ -45,8 +45,10 @@
#include "nm-lndp-rdisc.h"
#include "nm-dhcp-manager.h"
#include "nm-act-request.h"
#include "nm-proxy-config.h"
#include "nm-ip4-config.h"
#include "nm-ip6-config.h"
#include "nm-pacrunner-manager.h"
#include "nm-dnsmasq-manager.h"
#include "nm-dhcp4-config.h"
#include "nm-dhcp6-config.h"
@ -294,6 +296,10 @@ typedef struct _NMDevicePrivate {
guint32 dhcp_timeout;
char * dhcp_anycast_address;
/* Proxy Configuration */
NMProxyConfig *proxy_config;
NMPacrunnerManager *pacrunner_manager;
/* IP4 configuration info */
NMIP4Config * ip4_config; /* Combined config from VPN, settings, and device */
union {
@ -416,6 +422,8 @@ typedef struct _NMDevicePrivate {
} NMDevicePrivate;
static void nm_device_set_proxy_config (NMDevice *self, GHashTable *options);
static gboolean nm_device_set_ip4_config (NMDevice *self,
NMIP4Config *config,
guint32 default_route_metric,
@ -5072,6 +5080,8 @@ dhcp4_state_changed (NMDhcpClient *client,
break;
}
nm_device_set_proxy_config (self, options);
nm_dhcp4_config_set_options (priv->dhcp4.config, options);
_notify (self, PROP_DHCP4_CONFIG);
priv->dhcp4.num_tries_left = DHCP_NUM_TRIES_MAX;
@ -6982,6 +6992,9 @@ activate_stage3_ip_config_start (NMDevice *self)
&& !nm_device_activate_stage3_ip6_start (self))
return;
/* Proxy */
nm_device_set_proxy_config (self, NULL);
check_ip_state (self, TRUE);
}
@ -8517,8 +8530,50 @@ nm_device_is_activating (NMDevice *self)
return priv->act_handle4.id ? TRUE : FALSE;
}
/* IP Configuration stuff */
NMProxyConfig *
nm_device_get_proxy_config (NMDevice *self)
{
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
return NM_DEVICE_GET_PRIVATE (self)->proxy_config;
}
static void
nm_device_set_proxy_config (NMDevice *self, GHashTable *options)
{
NMDevicePrivate *priv;
NMConnection *connection;
NMSettingProxy *s_proxy = NULL;
char *pac = NULL;
g_return_if_fail (NM_IS_DEVICE (self));
priv = NM_DEVICE_GET_PRIVATE (self);
g_clear_object (&priv->proxy_config);
priv->proxy_config = nm_proxy_config_new ();
if (options) {
pac = g_hash_table_lookup (options, "wpad");
if (pac) {
nm_proxy_config_set_method (priv->proxy_config, NM_PROXY_CONFIG_METHOD_AUTO);
nm_proxy_config_set_pac_url (priv->proxy_config, pac);
_LOGD (LOGD_PROXY, "proxy: PAC url \"%s\"", pac);
} else {
nm_proxy_config_set_method (priv->proxy_config, NM_PROXY_CONFIG_METHOD_NONE);
_LOGD (LOGD_PROXY, "proxy: PAC url not obtained from DHCP server");
}
}
connection = nm_device_get_applied_connection (self);
if (connection)
s_proxy = nm_connection_get_setting_proxy (connection);
if (s_proxy)
nm_proxy_config_merge_setting (priv->proxy_config, s_proxy);
}
/* IP Configuration stuff */
NMDhcp4Config *
nm_device_get_dhcp4_config (NMDevice *self)
{
@ -10735,6 +10790,7 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type)
*/
nm_device_set_ip4_config (self, NULL, 0, TRUE, TRUE, NULL);
nm_device_set_ip6_config (self, NULL, TRUE, TRUE, NULL);
g_clear_object (&priv->proxy_config);
g_clear_object (&priv->con_ip4_config);
g_clear_object (&priv->dev_ip4_config);
g_clear_object (&priv->ext_ip4_config);
@ -11325,6 +11381,9 @@ _set_state_full (NMDevice *self,
deactivate_dispatcher_complete (0, self);
}
}
/* Remove config from PacRunner */
nm_pacrunner_manager_remove (priv->pacrunner_manager, nm_device_get_ip_iface (self));
break;
case NM_DEVICE_STATE_DISCONNECTED:
if ( priv->queued_act_request
@ -11348,6 +11407,14 @@ _set_state_full (NMDevice *self,
nm_act_request_get_settings_connection (req),
nm_act_request_get_applied_connection (req),
self, NULL, NULL, NULL);
if (priv->proxy_config) {
nm_pacrunner_manager_send (priv->pacrunner_manager,
nm_device_get_ip_iface (self),
priv->proxy_config,
priv->ip4_config,
priv->ip6_config);
}
break;
case NM_DEVICE_STATE_FAILED:
/* Usually upon failure the activation chain is interrupted in
@ -12164,6 +12231,8 @@ nm_device_init (NMDevice *self)
priv->available_connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL);
priv->ip6_saved_properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
priv->pacrunner_manager = g_object_ref (nm_pacrunner_manager_get ());
priv->default_route.v4_is_assumed = TRUE;
priv->default_route.v6_is_assumed = TRUE;
@ -12275,6 +12344,8 @@ dispose (GObject *object)
dispatcher_cleanup (self);
g_clear_object (&priv->pacrunner_manager);
_cleanup_generic_pre (self, CLEANUP_TYPE_KEEP);
g_warn_if_fail (priv->slaves == NULL);

View file

@ -366,9 +366,10 @@ const char * nm_device_get_permanent_hw_address (NMDevice *dev,
gboolean fallback_fake);
const char * nm_device_get_initial_hw_address (NMDevice *dev);
NMProxyConfig * nm_device_get_proxy_config (NMDevice *dev);
NMDhcp4Config * nm_device_get_dhcp4_config (NMDevice *dev);
NMDhcp6Config * nm_device_get_dhcp6_config (NMDevice *dev);
NMIP4Config * nm_device_get_ip4_config (NMDevice *dev);
void nm_device_replace_vpn4_config (NMDevice *dev,
NMIP4Config *old,

View file

@ -32,6 +32,7 @@
#include "nm-device.h"
#include "nm-dhcp4-config.h"
#include "nm-dhcp6-config.h"
#include "nm-proxy-config.h"
#include "nm-ip4-config.h"
#include "nm-ip6-config.h"
#include "nm-manager.h"
@ -90,6 +91,29 @@ _get_monitor_by_action (DispatcherAction action)
}
}
static void
dump_proxy_to_props (NMProxyConfig *proxy, GVariantBuilder *builder)
{
const char *pac_url = NULL, *pac_script = NULL;
if (nm_proxy_config_get_method (proxy) == NM_PROXY_CONFIG_METHOD_NONE)
return;
pac_url = nm_proxy_config_get_pac_url (proxy);
if (pac_url) {
g_variant_builder_add (builder, "{sv}",
"pac-url",
g_variant_new_string (pac_url));
}
pac_script = nm_proxy_config_get_pac_script (proxy);
if (pac_script) {
g_variant_builder_add (builder, "{sv}",
"pac-script",
g_variant_new_string (pac_script));
}
}
static void
dump_ip4_to_props (NMIP4Config *ip4, GVariantBuilder *builder)
{
@ -231,11 +255,13 @@ dump_ip6_to_props (NMIP6Config *ip6, GVariantBuilder *builder)
static void
fill_device_props (NMDevice *device,
GVariantBuilder *dev_builder,
GVariantBuilder *proxy_builder,
GVariantBuilder *ip4_builder,
GVariantBuilder *ip6_builder,
GVariant **dhcp4_props,
GVariant **dhcp6_props)
{
NMProxyConfig *proxy_config;
NMIP4Config *ip4_config;
NMIP6Config *ip6_config;
NMDhcp4Config *dhcp4_config;
@ -254,6 +280,10 @@ fill_device_props (NMDevice *device,
g_variant_builder_add (dev_builder, "{sv}", NMD_DEVICE_PROPS_PATH,
g_variant_new_object_path (nm_exported_object_get_path (NM_EXPORTED_OBJECT (device))));
proxy_config = nm_device_get_proxy_config (device);
if (proxy_config)
dump_proxy_to_props (proxy_config, proxy_builder);
ip4_config = nm_device_get_ip4_config (device);
if (ip4_config)
dump_ip4_to_props (ip4_config, ip4_builder);
@ -272,11 +302,15 @@ fill_device_props (NMDevice *device,
}
static void
fill_vpn_props (NMIP4Config *ip4_config,
fill_vpn_props (NMProxyConfig *proxy_config,
NMIP4Config *ip4_config,
NMIP6Config *ip6_config,
GVariantBuilder *proxy_builder,
GVariantBuilder *ip4_builder,
GVariantBuilder *ip6_builder)
{
if (proxy_config)
dump_proxy_to_props (proxy_config, proxy_builder);
if (ip4_config)
dump_ip4_to_props (ip4_config, ip4_builder);
if (ip6_config)
@ -454,6 +488,7 @@ _dispatcher_call (DispatcherAction action,
NMDevice *device,
NMConnectivityState connectivity_state,
const char *vpn_iface,
NMProxyConfig *vpn_proxy_config,
NMIP4Config *vpn_ip4_config,
NMIP6Config *vpn_ip6_config,
DispatcherFunc callback,
@ -463,10 +498,12 @@ _dispatcher_call (DispatcherAction action,
GVariant *connection_dict;
GVariantBuilder connection_props;
GVariantBuilder device_props;
GVariantBuilder device_proxy_props;
GVariantBuilder device_ip4_props;
GVariantBuilder device_ip6_props;
GVariant *device_dhcp4_props = NULL;
GVariant *device_dhcp6_props = NULL;
GVariantBuilder vpn_proxy_props;
GVariantBuilder vpn_ip4_props;
GVariantBuilder vpn_ip6_props;
DispatchInfo *info = NULL;
@ -551,8 +588,10 @@ _dispatcher_call (DispatcherAction action,
}
g_variant_builder_init (&device_props, G_VARIANT_TYPE_VARDICT);
g_variant_builder_init (&device_proxy_props, G_VARIANT_TYPE_VARDICT);
g_variant_builder_init (&device_ip4_props, G_VARIANT_TYPE_VARDICT);
g_variant_builder_init (&device_ip6_props, G_VARIANT_TYPE_VARDICT);
g_variant_builder_init (&vpn_proxy_props, G_VARIANT_TYPE_VARDICT);
g_variant_builder_init (&vpn_ip4_props, G_VARIANT_TYPE_VARDICT);
g_variant_builder_init (&vpn_ip6_props, G_VARIANT_TYPE_VARDICT);
@ -561,13 +600,16 @@ _dispatcher_call (DispatcherAction action,
&& action != DISPATCHER_ACTION_CONNECTIVITY_CHANGE) {
fill_device_props (device,
&device_props,
&device_proxy_props,
&device_ip4_props,
&device_ip6_props,
&device_dhcp4_props,
&device_dhcp6_props);
if (vpn_ip4_config || vpn_ip6_config) {
fill_vpn_props (vpn_ip4_config,
fill_vpn_props (vpn_proxy_config,
vpn_ip4_config,
vpn_ip6_config,
&vpn_proxy_props,
&vpn_ip4_props,
&vpn_ip6_props);
}
@ -584,17 +626,19 @@ _dispatcher_call (DispatcherAction action,
GVariantIter *results;
ret = _nm_dbus_proxy_call_sync (dispatcher_proxy, "Action",
g_variant_new ("(s@a{sa{sv}}a{sv}a{sv}a{sv}a{sv}@a{sv}@a{sv}ssa{sv}a{sv}b)",
g_variant_new ("(s@a{sa{sv}}a{sv}a{sv}a{sv}a{sv}a{sv}@a{sv}@a{sv}ssa{sv}a{sv}a{sv}b)",
action_to_string (action),
connection_dict,
&connection_props,
&device_props,
&device_proxy_props,
&device_ip4_props,
&device_ip6_props,
device_dhcp4_props,
device_dhcp6_props,
nm_connectivity_state_to_string (connectivity_state),
vpn_iface ? vpn_iface : "",
&vpn_proxy_props,
&vpn_ip4_props,
&vpn_ip6_props,
nm_logging_enabled (LOGL_DEBUG, LOGD_DISPATCH)),
@ -620,17 +664,19 @@ _dispatcher_call (DispatcherAction action,
info->callback = callback;
info->user_data = user_data;
g_dbus_proxy_call (dispatcher_proxy, "Action",
g_variant_new ("(s@a{sa{sv}}a{sv}a{sv}a{sv}a{sv}@a{sv}@a{sv}ssa{sv}a{sv}b)",
g_variant_new ("(s@a{sa{sv}}a{sv}a{sv}a{sv}a{sv}a{sv}@a{sv}@a{sv}ssa{sv}a{sv}a{sv}b)",
action_to_string (action),
connection_dict,
&connection_props,
&device_props,
&device_proxy_props,
&device_ip4_props,
&device_ip6_props,
device_dhcp4_props,
device_dhcp6_props,
nm_connectivity_state_to_string (connectivity_state),
vpn_iface ? vpn_iface : "",
&vpn_proxy_props,
&vpn_ip4_props,
&vpn_ip6_props,
nm_logging_enabled (LOGL_DEBUG, LOGD_DISPATCH)),
@ -680,7 +726,7 @@ nm_dispatcher_call (DispatcherAction action,
guint *out_call_id)
{
return _dispatcher_call (action, FALSE, settings_connection, applied_connection, device,
NM_CONNECTIVITY_UNKNOWN, NULL, NULL, NULL,
NM_CONNECTIVITY_UNKNOWN, NULL, NULL, NULL, NULL,
callback, user_data, out_call_id);
}
@ -703,7 +749,7 @@ nm_dispatcher_call_sync (DispatcherAction action,
NMDevice *device)
{
return _dispatcher_call (action, TRUE, settings_connection, applied_connection, device,
NM_CONNECTIVITY_UNKNOWN, NULL, NULL, NULL, NULL, NULL, NULL);
NM_CONNECTIVITY_UNKNOWN, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
}
/**
@ -713,6 +759,7 @@ nm_dispatcher_call_sync (DispatcherAction action,
* @applied_connection: the currently applied connection
* @parent_device: the parent #NMDevice of the VPN connection
* @vpn_iface: the IP interface of the VPN tunnel, if any
* @vpn_proxy_config: the #NMProxyConfig of the VPN connection
* @vpn_ip4_config: the #NMIP4Config of the VPN connection
* @vpn_ip6_config: the #NMIP6Config of the VPN connection
* @callback: a caller-supplied callback to execute when done
@ -731,6 +778,7 @@ nm_dispatcher_call_vpn (DispatcherAction action,
NMConnection *applied_connection,
NMDevice *parent_device,
const char *vpn_iface,
NMProxyConfig *vpn_proxy_config,
NMIP4Config *vpn_ip4_config,
NMIP6Config *vpn_ip6_config,
DispatcherFunc callback,
@ -738,8 +786,8 @@ nm_dispatcher_call_vpn (DispatcherAction action,
guint *out_call_id)
{
return _dispatcher_call (action, FALSE, settings_connection, applied_connection,
parent_device, NM_CONNECTIVITY_UNKNOWN, vpn_iface, vpn_ip4_config,
vpn_ip6_config, callback, user_data, out_call_id);
parent_device, NM_CONNECTIVITY_UNKNOWN, vpn_iface, vpn_proxy_config,
vpn_ip4_config, vpn_ip6_config, callback, user_data, out_call_id);
}
/**
@ -749,6 +797,7 @@ nm_dispatcher_call_vpn (DispatcherAction action,
* @applied_connection: the currently applied connection
* @parent_device: the parent #NMDevice of the VPN connection
* @vpn_iface: the IP interface of the VPN tunnel, if any
* @vpn_proxy_config: the #NMProxyConfig of the VPN connection
* @vpn_ip4_config: the #NMIP4Config of the VPN connection
* @vpn_ip6_config: the #NMIP6Config of the VPN connection
*
@ -763,11 +812,12 @@ nm_dispatcher_call_vpn_sync (DispatcherAction action,
NMConnection *applied_connection,
NMDevice *parent_device,
const char *vpn_iface,
NMProxyConfig *vpn_proxy_config,
NMIP4Config *vpn_ip4_config,
NMIP6Config *vpn_ip6_config)
{
return _dispatcher_call (action, TRUE, settings_connection, applied_connection,
parent_device, NM_CONNECTIVITY_UNKNOWN, vpn_iface,
parent_device, NM_CONNECTIVITY_UNKNOWN, vpn_iface, vpn_proxy_config,
vpn_ip4_config, vpn_ip6_config, NULL, NULL, NULL);
}
@ -785,7 +835,7 @@ nm_dispatcher_call_connectivity (DispatcherAction action,
NMConnectivityState connectivity_state)
{
return _dispatcher_call (action, FALSE, NULL, NULL, NULL, connectivity_state,
NULL, NULL, NULL, NULL, NULL, NULL);
NULL, NULL, NULL, NULL, NULL, NULL, NULL);
}
void

View file

@ -61,6 +61,7 @@ gboolean nm_dispatcher_call_vpn (DispatcherAction action,
NMConnection *applied_connection,
NMDevice *parent_device,
const char *vpn_iface,
NMProxyConfig *vpn_proxy_config,
NMIP4Config *vpn_ip4_config,
NMIP6Config *vpn_ip6_config,
DispatcherFunc callback,
@ -72,6 +73,7 @@ gboolean nm_dispatcher_call_vpn_sync (DispatcherAction action,
NMConnection *applied_connection,
NMDevice *parent_device,
const char *vpn_iface,
NMProxyConfig *vpn_proxy_config,
NMIP4Config *vpn_ip4_config,
NMIP6Config *vpn_ip6_config);

View file

@ -90,7 +90,7 @@ static struct {
char *logging_domains_to_string;
const LogLevelDesc level_desc[_LOGL_N];
#define _DOMAIN_DESC_LEN 38
#define _DOMAIN_DESC_LEN 39
/* Would be nice to use C99 flexible array member here,
* but that feature doesn't seem well supported. */
const LogDesc domain_desc[_DOMAIN_DESC_LEN];
@ -145,6 +145,7 @@ static struct {
{ LOGD_AUDIT, "AUDIT" },
{ LOGD_SYSTEMD, "SYSTEMD" },
{ LOGD_VPN_PLUGIN,"VPN_PLUGIN" },
{ LOGD_PROXY, "PROXY" },
{ 0, NULL }
/* keep _DOMAIN_DESC_LEN in sync */
},

View file

@ -66,6 +66,7 @@ typedef enum { /*< skip >*/
LOGD_AUDIT = (1LL << 34),
LOGD_SYSTEMD = (1LL << 35),
LOGD_VPN_PLUGIN = (1LL << 36),
LOGD_PROXY = (1LL << 37),
__LOGD_MAX,
LOGD_ALL = (((__LOGD_MAX - 1LL) << 1) - 1LL),

474
src/nm-pacrunner-manager.c Normal file
View file

@ -0,0 +1,474 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* (C) Copyright 2016 Atul Anand <atulhjp@gmail.com>.
*/
#include "nm-default.h"
#include "nm-pacrunner-manager.h"
#include "nm-utils.h"
#include "nm-platform.h"
#include "nm-proxy-config.h"
#include "nm-ip4-config.h"
#include "nm-ip6-config.h"
#define PACRUNNER_DBUS_SERVICE "org.pacrunner"
#define PACRUNNER_DBUS_INTERFACE "org.pacrunner.Manager"
#define PACRUNNER_DBUS_PATH "/org/pacrunner/manager"
/*****************************************************************************/
struct remove_data {
char *iface;
char *path;
};
typedef struct {
char *iface;
GPtrArray *domains;
GDBusProxy *pacrunner;
GCancellable *pacrunner_cancellable;
GList *args;
GList *remove;
} NMPacrunnerManagerPrivate;
struct _NMPacrunnerManager {
GObject parent;
NMPacrunnerManagerPrivate _priv;
};
struct _NMPacrunnerManagerClass {
GObjectClass parent;
};
G_DEFINE_TYPE (NMPacrunnerManager, nm_pacrunner_manager, G_TYPE_OBJECT)
#define NM_PACRUNNER_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMPacrunnerManager, NM_IS_PACRUNNER_MANAGER)
/*****************************************************************************/
NM_DEFINE_SINGLETON_GETTER (NMPacrunnerManager, nm_pacrunner_manager_get, NM_TYPE_PACRUNNER_MANAGER);
/*****************************************************************************/
#define _NMLOG_DOMAIN LOGD_PROXY
#define _NMLOG_PREFIX_NAME "pacrunner"
#define _NMLOG(level, ...) \
G_STMT_START { \
nm_log ((level), _NMLOG_DOMAIN, \
"%s[%p]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
_NMLOG_PREFIX_NAME, \
(self) /* Beware: must not dereference @self (see pacrunner_remove_done) */\
_NM_UTILS_MACRO_REST(__VA_ARGS__)); \
} G_STMT_END
/*****************************************************************************/
static void
remove_data_destroy (struct remove_data *data)
{
g_return_if_fail (data != NULL);
g_free (data->iface);
g_free (data->path);
memset (data, 0, sizeof (struct remove_data));
g_free (data);
}
static void
add_proxy_config (NMPacrunnerManager *self, GVariantBuilder *proxy_data, const NMProxyConfig *proxy_config)
{
const char *pac_url, *pac_script;
NMProxyConfigMethod method;
method = nm_proxy_config_get_method (proxy_config);
if (method == NM_PROXY_CONFIG_METHOD_AUTO) {
pac_url = nm_proxy_config_get_pac_url (proxy_config);
if (pac_url) {
g_variant_builder_add (proxy_data, "{sv}",
"URL",
g_variant_new_string (pac_url));
}
pac_script = nm_proxy_config_get_pac_script (proxy_config);
if (pac_script) {
g_variant_builder_add (proxy_data, "{sv}",
"Script",
g_variant_new_string (pac_script));
}
}
g_variant_builder_add (proxy_data, "{sv}",
"BrowserOnly",
g_variant_new_boolean (nm_proxy_config_get_browser_only (proxy_config)));
}
static void
add_ip4_config (NMPacrunnerManager *self, GVariantBuilder *proxy_data, NMIP4Config *ip4)
{
NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
int i;
char *cidr = NULL;
/* Extract Searches */
for (i = 0; i < nm_ip4_config_get_num_searches (ip4); i++)
g_ptr_array_add (priv->domains, g_strdup (nm_ip4_config_get_search (ip4, i)));
/* Extract domains */
for (i = 0; i < nm_ip4_config_get_num_domains (ip4); i++)
g_ptr_array_add (priv->domains, g_strdup (nm_ip4_config_get_domain (ip4, i)));
/* Add Addresses and routes in CIDR form */
for (i = 0; i < nm_ip4_config_get_num_addresses (ip4); i++) {
const NMPlatformIP4Address *address = nm_ip4_config_get_address (ip4, i);
cidr = g_strdup_printf ("%s/%u",
nm_utils_inet4_ntop (address->address, NULL),
address->plen);
g_ptr_array_add (priv->domains, g_strdup (cidr));
g_free (cidr);
}
for (i = 0; i < nm_ip4_config_get_num_routes (ip4); i++) {
const NMPlatformIP4Route *routes = nm_ip4_config_get_route (ip4, i);
cidr = g_strdup_printf ("%s/%u",
nm_utils_inet4_ntop (routes->network, NULL),
routes->plen);
g_ptr_array_add (priv->domains, g_strdup (cidr));
g_free (cidr);
}
}
static void
add_ip6_config (NMPacrunnerManager *self, GVariantBuilder *proxy_data, NMIP6Config *ip6)
{
NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
int i;
char *cidr = NULL;
/* Extract searches */
for (i = 0; i < nm_ip6_config_get_num_searches (ip6); i++)
g_ptr_array_add (priv->domains, g_strdup (nm_ip6_config_get_search (ip6, i)));
/* Extract domains */
for (i = 0; i < nm_ip6_config_get_num_domains (ip6); i++)
g_ptr_array_add (priv->domains, g_strdup (nm_ip6_config_get_domain (ip6, i)));
/* Add Addresses and routes in CIDR form */
for (i = 0; i < nm_ip6_config_get_num_addresses (ip6); i++) {
const NMPlatformIP6Address *address = nm_ip6_config_get_address (ip6, i);
cidr = g_strdup_printf ("%s/%u",
nm_utils_inet6_ntop (&address->address, NULL),
address->plen);
g_ptr_array_add (priv->domains, g_strdup (cidr));
g_free (cidr);
}
for (i = 0; i < nm_ip6_config_get_num_routes (ip6); i++) {
const NMPlatformIP6Route *routes = nm_ip6_config_get_route (ip6, i);
cidr = g_strdup_printf ("%s/%u",
nm_utils_inet6_ntop (&routes->network, NULL),
routes->plen);
g_ptr_array_add (priv->domains, g_strdup (cidr));
g_free (cidr);
}
}
static void
pacrunner_send_done (GObject *source, GAsyncResult *res, gpointer user_data)
{
NMPacrunnerManager *self = NM_PACRUNNER_MANAGER (user_data);
NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
gs_free_error GError *error = NULL;
gs_unref_variant GVariant *variant = NULL;
const char *path = NULL;
GList *iter = NULL;
gboolean found = FALSE;
variant = g_dbus_proxy_call_finish (priv->pacrunner, res, &error);
if (!variant) {
_LOGD ("sending proxy config to pacrunner failed: %s", error->message);
} else {
struct remove_data *data;
g_variant_get (variant, "(&o)", &path);
/* Replace the old path (if any) of proxy config with the new one returned
* from CreateProxyConfiguration() DBus method on PacRunner.
*/
for (iter = g_list_first (priv->remove); iter; iter = g_list_next (iter)) {
struct remove_data *r = iter->data;
if (g_strcmp0 (priv->iface, r->iface) == 0) {
g_free (r->path);
r->path = g_strdup (path);
found = TRUE;
break;
}
}
if (!found) {
data = g_malloc0 (sizeof (struct remove_data));
data->iface = g_strdup (priv->iface);
data->path = g_strdup (path);
priv->remove = g_list_append (priv->remove, data);
_LOGD ("proxy config sent to pacrunner");
}
}
}
static void
send_pacrunner_proxy_data (NMPacrunnerManager *self, GVariant *pacrunner_manager_args)
{
NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
if (!pacrunner_manager_args)
return;
if (priv->pacrunner)
g_dbus_proxy_call (priv->pacrunner,
"CreateProxyConfiguration",
pacrunner_manager_args,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
(GAsyncReadyCallback) pacrunner_send_done,
self);
}
static void
name_owner_changed (GObject *object,
GParamSpec *pspec,
gpointer user_data)
{
NMPacrunnerManager *self = NM_PACRUNNER_MANAGER (user_data);
NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
gs_free char *owner = NULL;
GList *iter = NULL;
owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (object));
if (owner) {
_LOGD ("PacRunner appeared as %s", owner);
for (iter = g_list_first(priv->args); iter; iter = g_list_next(iter)) {
send_pacrunner_proxy_data (self, iter->data);
}
} else {
_LOGD ("PacRunner disappeared");
}
}
static void
pacrunner_proxy_cb (GObject *source, GAsyncResult *res, gpointer user_data)
{
NMPacrunnerManager *self = user_data;
NMPacrunnerManagerPrivate *priv;
GError *error = NULL;
GDBusProxy *proxy;
proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
if (!proxy) {
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
_LOGW ("failed to connect to pacrunner via DBus: %s", error->message);
g_error_free (error);
return;
}
priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
priv->pacrunner = proxy;
nm_clear_g_cancellable (&priv->pacrunner_cancellable);
g_signal_connect (priv->pacrunner, "notify::g-name-owner",
G_CALLBACK (name_owner_changed), self);
}
/**
* nm_pacrunner_manager_send():
* @self: the #NMPacrunnerManager
* @iface: the iface for the connection or %NULL
* @proxy_config: Proxy config of the connection
* @ip4_conifg: IP4 Cofig of the connection
* @ip6_config: IP6 Config of the connection
*/
void
nm_pacrunner_manager_send (NMPacrunnerManager *self,
const char *iface,
NMProxyConfig *proxy_config,
NMIP4Config *ip4_config,
NMIP6Config *ip6_config)
{
char **strv = NULL;
NMProxyConfigMethod method;
NMPacrunnerManagerPrivate *priv;
GVariantBuilder proxy_data;
GVariant *pacrunner_manager_args;
g_return_if_fail (NM_IS_PACRUNNER_MANAGER (self));
g_return_if_fail (proxy_config);
priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
g_free (priv->iface);
priv->iface = g_strdup (iface);
g_variant_builder_init (&proxy_data, G_VARIANT_TYPE_VARDICT);
g_variant_builder_add (&proxy_data, "{sv}",
"Interface",
g_variant_new_string (iface));
method = nm_proxy_config_get_method (proxy_config);
switch (method) {
case NM_PROXY_CONFIG_METHOD_AUTO:
g_variant_builder_add (&proxy_data, "{sv}",
"Method",
g_variant_new_string ("auto"));
break;
case NM_PROXY_CONFIG_METHOD_NONE:
g_variant_builder_add (&proxy_data, "{sv}",
"Method",
g_variant_new_string ("direct"));
}
priv->domains = g_ptr_array_new_with_free_func (g_free);
/* Extract stuff from Configs */
add_proxy_config (self, &proxy_data, proxy_config);
if (ip4_config)
add_ip4_config (self, &proxy_data, ip4_config);
if (ip6_config)
add_ip6_config (self, &proxy_data, ip6_config);
g_ptr_array_add (priv->domains, NULL);
strv = (char **) g_ptr_array_free (priv->domains, (priv->domains->len == 1));
if (strv) {
g_variant_builder_add (&proxy_data, "{sv}",
"Domains",
g_variant_new_strv ((const char *const *) strv, -1));
g_strfreev (strv);
}
pacrunner_manager_args = g_variant_ref_sink (g_variant_new ("(a{sv})", &proxy_data));
priv->args = g_list_append (priv->args, pacrunner_manager_args);
/* Send if PacRunner is available on Bus, otherwise
* argument has already been appended above to be
* sent when PacRunner appears.
*/
send_pacrunner_proxy_data (self, pacrunner_manager_args);
}
static void
pacrunner_remove_done (GObject *source, GAsyncResult *res, gpointer user_data)
{
/* @self may be a dangling pointer. However, we don't use it as the
* logging macro below does not dereference @self. */
NMPacrunnerManager *self = user_data;
gs_free_error GError *error = NULL;
gs_unref_variant GVariant *ret = NULL;
ret = g_dbus_proxy_call_finish ((GDBusProxy *) source, res, &error);
if (!ret)
_LOGD ("Couldn't remove proxy config from pacrunner: %s", error->message);
else
_LOGD ("Sucessfully removed proxy config from pacrunner");
}
/**
* nm_pacrunner_manager_remove():
* @self: the #NMPacrunnerManager
* @iface: the iface for the connection to be removed
* from PacRunner
*/
void
nm_pacrunner_manager_remove (NMPacrunnerManager *self, const char *iface)
{
NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
GList *list;
for (list = g_list_first(priv->remove); list; list = g_list_next(list)) {
struct remove_data *data = list->data;
if (g_strcmp0 (data->iface, iface) == 0) {
if (priv->pacrunner && data->path)
g_dbus_proxy_call (priv->pacrunner,
"DestroyProxyConfiguration",
g_variant_new ("(o)", data->path),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
(GAsyncReadyCallback) pacrunner_remove_done,
self);
break;
}
}
}
/*****************************************************************************/
static void
nm_pacrunner_manager_init (NMPacrunnerManager *self)
{
NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
priv->pacrunner_cancellable = g_cancellable_new ();
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
PACRUNNER_DBUS_SERVICE,
PACRUNNER_DBUS_PATH,
PACRUNNER_DBUS_INTERFACE,
priv->pacrunner_cancellable,
(GAsyncReadyCallback) pacrunner_proxy_cb,
self);
}
static void
dispose (GObject *object)
{
NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE ((NMPacrunnerManager *) object);
g_clear_pointer (&priv->iface, g_free);
nm_clear_g_cancellable (&priv->pacrunner_cancellable);
g_clear_object (&priv->pacrunner);
g_list_free_full (priv->args, (GDestroyNotify) g_variant_unref);
priv->args = NULL;
g_list_free_full (priv->remove, (GDestroyNotify) remove_data_destroy);
priv->remove = NULL;
G_OBJECT_CLASS (nm_pacrunner_manager_parent_class)->dispose (object);
}
static void
nm_pacrunner_manager_class_init (NMPacrunnerManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = dispose;
}

View file

@ -0,0 +1,45 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* (C) Copyright 2016 Atul Anand <atulhjp@gmail.com>.
*/
#ifndef __NETWORKMANAGER_PACRUNNER_MANAGER_H__
#define __NETWORKMANAGER_PACRUNNER_MANAGER_H__
#define NM_TYPE_PACRUNNER_MANAGER (nm_pacrunner_manager_get_type ())
#define NM_PACRUNNER_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_PACRUNNER_MANAGER, NMPacrunnerManager))
#define NM_PACRUNNER_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_PACRUNNER_MANAGER, NMPacrunnerManagerClass))
#define NM_IS_PACRUNNER_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_PACRUNNER_MANAGER))
#define NM_IS_PACRUNNER_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_PACRUNNER_MANAGER))
#define NM_PACRUNNER_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_PACRUNNER_MANAGER, NMPacrunnerManagerClass))
typedef struct _NMPacrunnerManagerClass NMPacrunnerManagerClass;
GType nm_pacrunner_manager_get_type (void);
NMPacrunnerManager *nm_pacrunner_manager_get (void);
void nm_pacrunner_manager_send (NMPacrunnerManager *self,
const char *iface,
NMProxyConfig *proxy_config,
NMIP4Config *ip4_config,
NMIP6Config *ip6_config);
void nm_pacrunner_manager_remove (NMPacrunnerManager *self, const char *iface);
#endif /* __NETWORKMANAGER_PACRUNNER_MANAGER_H__ */

187
src/nm-proxy-config.c Normal file
View file

@ -0,0 +1,187 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* (C) Copyright 2016 Atul Anand <atulhjp@gmail.com>.
*/
#include "nm-default.h"
#include "nm-proxy-config.h"
#include <stdlib.h>
#include "nm-core-internal.h"
/*****************************************************************************/
typedef struct {
NMProxyConfigMethod method;
gboolean browser_only;
char *pac_url;
char *pac_script;
} NMProxyConfigPrivate;
struct _NMProxyConfig {
GObject parent;
NMProxyConfigPrivate _priv;
};
struct _NMProxyConfigClass {
GObjectClass parent;
};
G_DEFINE_TYPE (NMProxyConfig, nm_proxy_config, G_TYPE_OBJECT)
#define NM_PROXY_CONFIG_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMProxyConfig, NM_IS_PROXY_CONFIG)
/*****************************************************************************/
void
nm_proxy_config_set_method (NMProxyConfig *config, NMProxyConfigMethod method)
{
NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE (config);
priv->method = method;
}
NMProxyConfigMethod
nm_proxy_config_get_method (const NMProxyConfig *config)
{
const NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE (config);
return priv->method;
}
void
nm_proxy_config_merge_setting (NMProxyConfig *config, NMSettingProxy *setting)
{
const char *tmp = NULL;
NMProxyConfigPrivate *priv;
NMSettingProxyMethod method;
if (!setting)
return;
g_return_if_fail (NM_IS_SETTING_PROXY (setting));
priv = NM_PROXY_CONFIG_GET_PRIVATE (config);
g_clear_pointer (&priv->pac_script, g_free);
method = nm_setting_proxy_get_method (setting);
switch (method) {
case NM_SETTING_PROXY_METHOD_AUTO:
priv->method = NM_PROXY_CONFIG_METHOD_AUTO;
/* Free DHCP Obtained PAC Url (i.e Option 252)
* only when libnm overrides it.
*/
tmp = nm_setting_proxy_get_pac_url (setting);
if (tmp) {
g_free (priv->pac_url);
priv->pac_url = g_strdup (tmp);
}
tmp = nm_setting_proxy_get_pac_script (setting);
priv->pac_script = g_strdup (tmp);
break;
case NM_SETTING_PROXY_METHOD_NONE:
priv->method = NM_PROXY_CONFIG_METHOD_NONE;
break;
}
priv->browser_only = nm_setting_proxy_get_browser_only (setting);
}
gboolean
nm_proxy_config_get_browser_only (const NMProxyConfig *config)
{
const NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE (config);
return priv->browser_only;
}
void
nm_proxy_config_set_pac_url (NMProxyConfig *config, const char *url)
{
NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE (config);
g_free (priv->pac_url);
priv->pac_url = g_strdup (url);
}
const char *
nm_proxy_config_get_pac_url (const NMProxyConfig *config)
{
const NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE (config);
return priv->pac_url;
}
void
nm_proxy_config_set_pac_script (NMProxyConfig *config, const char *script)
{
NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE (config);
g_free (priv->pac_script);
priv->pac_script = g_strdup (script);
}
const char *
nm_proxy_config_get_pac_script (const NMProxyConfig *config)
{
const NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE (config);
return priv->pac_script;
}
/*****************************************************************************/
static void
nm_proxy_config_init (NMProxyConfig *config)
{
NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE (config);
priv->method = NM_PROXY_CONFIG_METHOD_NONE;
}
NMProxyConfig *
nm_proxy_config_new (void)
{
return NM_PROXY_CONFIG (g_object_new (NM_TYPE_PROXY_CONFIG, NULL));
}
static void
finalize (GObject *object)
{
NMProxyConfig *self = NM_PROXY_CONFIG (object);
NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE (self);
g_free (priv->pac_url);
g_free (priv->pac_script);
G_OBJECT_CLASS (nm_proxy_config_parent_class)->finalize (object);
}
static void
nm_proxy_config_class_init (NMProxyConfigClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = finalize;
}

57
src/nm-proxy-config.h Normal file
View file

@ -0,0 +1,57 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* (C) Copyright 2016 Atul Anand <atulhjp@gmail.com>.
*/
#ifndef __NETWORKMANAGER_PROXY_CONFIG_H__
#define __NETWORKMANAGER_PROXY_CONFIG_H__
#include "nm-setting-proxy.h"
typedef enum {
NM_PROXY_CONFIG_METHOD_AUTO = 0,
NM_PROXY_CONFIG_METHOD_NONE
} NMProxyConfigMethod;
#define NM_TYPE_PROXY_CONFIG (nm_proxy_config_get_type ())
#define NM_PROXY_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_PROXY_CONFIG, NMProxyConfig))
#define NM_PROXY_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_PROXY_CONFIG, NMProxyConfigClass))
#define NM_IS_PROXY_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_PROXY_CONFIG))
#define NM_IS_PROXY_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_PROXY_CONFIG))
#define NM_PROXY_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_PROXY_CONFIG, NMProxyConfigClass))
typedef struct _NMProxyConfigClass NMProxyConfigClass;
GType nm_proxy_config_get_type (void);
NMProxyConfig * nm_proxy_config_new (void);
void nm_proxy_config_set_method (NMProxyConfig *config, NMProxyConfigMethod method);
NMProxyConfigMethod nm_proxy_config_get_method (const NMProxyConfig *config);
void nm_proxy_config_merge_setting (NMProxyConfig *config, NMSettingProxy *setting);
gboolean nm_proxy_config_get_browser_only (const NMProxyConfig *config);
void nm_proxy_config_set_pac_url (NMProxyConfig *config, const char *url);
const char * nm_proxy_config_get_pac_url (const NMProxyConfig *config);
void nm_proxy_config_set_pac_script (NMProxyConfig *config, const char *script);
const char * nm_proxy_config_get_pac_script (const NMProxyConfig *config);
#endif /* __NETWORKMANAGER_PROXY_CONFIG_H__ */

View file

@ -42,11 +42,13 @@ typedef struct _NMDefaultRouteManager NMDefaultRouteManager;
typedef struct _NMDevice NMDevice;
typedef struct _NMDhcp4Config NMDhcp4Config;
typedef struct _NMDhcp6Config NMDhcp6Config;
typedef struct _NMProxyConfig NMProxyConfig;
typedef struct _NMIP4Config NMIP4Config;
typedef struct _NMIP6Config NMIP6Config;
typedef struct _NMManager NMManager;
typedef struct _NMPolicy NMPolicy;
typedef struct _NMRfkillManager NMRfkillManager;
typedef struct _NMPacrunnerManager NMPacrunnerManager;
typedef struct _NMRouteManager NMRouteManager;
typedef struct _NMSessionMonitor NMSessionMonitor;
typedef struct _NMSleepMonitor NMSleepMonitor;

View file

@ -57,6 +57,7 @@
#include "nm-setting-adsl.h"
#include "nm-setting-wireless.h"
#include "nm-setting-wireless-security.h"
#include "nm-setting-proxy.h"
#include "nm-setting-bond.h"
#include "nm-utils.h"
#include "nm-core-internal.h"

View file

@ -48,6 +48,7 @@
#include "nm-setting-bridge.h"
#include "nm-setting-bridge-port.h"
#include "nm-setting-dcb.h"
#include "nm-setting-proxy.h"
#include "nm-setting-generic.h"
#include "nm-core-internal.h"
#include "nm-utils.h"
@ -899,6 +900,62 @@ error:
return success;
}
static NMSetting *
make_proxy_setting (shvarFile *ifcfg, GError **error)
{
NMSettingProxy *s_proxy = NULL;
char *value = NULL;
NMSettingProxyMethod method;
value = svGetValue (ifcfg, "PROXY_METHOD", FALSE);
if (!value)
return NULL;
if (!g_ascii_strcasecmp (value, "auto"))
method = NM_SETTING_PROXY_METHOD_AUTO;
else
method = NM_SETTING_PROXY_METHOD_NONE;
g_free (value);
s_proxy = (NMSettingProxy *) nm_setting_proxy_new ();
switch (method) {
case NM_SETTING_PROXY_METHOD_AUTO:
g_object_set (s_proxy,
NM_SETTING_PROXY_METHOD, NM_SETTING_PROXY_METHOD_AUTO,
NULL);
value = svGetValue (ifcfg, "PAC_URL", FALSE);
if (value) {
value = g_strstrip (value);
g_object_set (s_proxy, NM_SETTING_PROXY_PAC_URL, value, NULL);
g_free (value);
}
value = svGetValue (ifcfg, "PAC_SCRIPT", FALSE);
if (value) {
value = g_strstrip (value);
g_object_set (s_proxy, NM_SETTING_PROXY_PAC_SCRIPT, value, NULL);
g_free (value);
}
break;
case NM_SETTING_PROXY_METHOD_NONE:
g_object_set (s_proxy,
NM_SETTING_PROXY_METHOD, NM_SETTING_PROXY_METHOD_NONE,
NULL);
}
value = svGetValue (ifcfg, "BROWSER_ONLY", FALSE);
if (value) {
if (!g_ascii_strcasecmp (value, "yes")) {
g_object_set (s_proxy, NM_SETTING_PROXY_BROWSER_ONLY, TRUE, NULL);
g_free (value);
}
}
return NM_SETTING (s_proxy);
}
static NMSetting *
make_ip4_setting (shvarFile *ifcfg,
@ -4962,7 +5019,7 @@ connection_from_file_full (const char *filename,
shvarFile *parsed;
gs_free char *type = NULL;
char *devtype, *bootproto;
NMSetting *s_ip4, *s_ip6, *s_port, *s_dcb = NULL;
NMSetting *s_ip4, *s_ip6, *s_proxy, *s_port, *s_dcb = NULL;
const char *ifcfg_name = NULL;
g_return_val_if_fail (filename != NULL, NULL);
@ -5179,6 +5236,10 @@ connection_from_file_full (const char *filename,
*/
check_dns_search_domains (parsed, s_ip4, s_ip6);
s_proxy = make_proxy_setting (parsed, error);
if (s_proxy)
nm_connection_add_setting (connection, s_proxy);
/* Bridge port? */
s_port = make_bridge_port_setting (parsed);
if (s_port)

View file

@ -36,6 +36,7 @@
#include "nm-setting-wired.h"
#include "nm-setting-wireless.h"
#include "nm-setting-8021x.h"
#include "nm-setting-proxy.h"
#include "nm-setting-ip4-config.h"
#include "nm-setting-ip6-config.h"
#include "nm-setting-pppoe.h"
@ -1997,6 +1998,50 @@ error:
return success;
}
static gboolean
write_proxy_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
{
NMSettingProxy *s_proxy;
NMSettingProxyMethod method;
const char *pac_url, *pac_script;
gboolean browser_only;
s_proxy = nm_connection_get_setting_proxy (connection);
if (!s_proxy)
return TRUE;
svSetValue (ifcfg, "BROWSER_ONLY", NULL, FALSE);
svSetValue (ifcfg, "PAC_URL", NULL, FALSE);
svSetValue (ifcfg, "PAC_SCRIPT", NULL, FALSE);
method = nm_setting_proxy_get_method (s_proxy);
switch (method) {
case NM_SETTING_PROXY_METHOD_AUTO:
svSetValue (ifcfg, "PROXY_METHOD", "auto", FALSE);
pac_url = nm_setting_proxy_get_pac_url (s_proxy);
if (pac_url)
svSetValue (ifcfg, "PAC_URL", pac_url, FALSE);
pac_script = nm_setting_proxy_get_pac_script (s_proxy);
if (pac_script)
svSetValue (ifcfg, "PAC_SCRIPT", pac_script, FALSE);
break;
case NM_SETTING_PROXY_METHOD_NONE:
svSetValue (ifcfg, "PROXY_METHOD", "none", FALSE);
/* Write nothing more */
}
browser_only = nm_setting_proxy_get_browser_only (s_proxy);
if (browser_only)
svSetValue (ifcfg, "BROWSER_ONLY", "yes", FALSE);
else
svSetValue (ifcfg, "BROWSER_ONLY", "no", FALSE);
return TRUE;
}
static gboolean
write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
{
@ -2887,6 +2932,9 @@ write_connection (NMConnection *connection,
if (!write_dcb_setting (connection, ifcfg, error))
goto out;
if (!write_proxy_setting (connection, ifcfg, error))
goto out;
svSetValue (ifcfg, "DHCP_HOSTNAME", NULL, FALSE);
svSetValue (ifcfg, "DHCP_FQDN", NULL, FALSE);

View file

@ -32,6 +32,7 @@
#include <unistd.h>
#include <syslog.h>
#include "nm-proxy-config.h"
#include "nm-ip4-config.h"
#include "nm-ip6-config.h"
#include "nm-platform.h"
@ -41,6 +42,7 @@
#include "nm-dispatcher.h"
#include "nm-agent-manager.h"
#include "nm-core-internal.h"
#include "nm-pacrunner-manager.h"
#include "nm-default-route-manager.h"
#include "nm-route-manager.h"
#include "nm-firewall-manager.h"
@ -124,6 +126,7 @@ typedef struct {
GCancellable *cancellable;
GVariant *connect_hash;
guint connect_timeout;
NMProxyConfig *proxy_config;
gboolean has_ip4;
NMIP4Config *ip4_config;
guint32 ip4_internal_gw;
@ -537,6 +540,7 @@ _set_vpn_state (NMVpnConnection *self,
_get_applied_connection (self),
parent_dev,
priv->ip_iface,
priv->proxy_config,
priv->ip4_config,
priv->ip6_config,
dispatcher_pre_up_done,
@ -556,11 +560,20 @@ _set_vpn_state (NMVpnConnection *self,
_get_applied_connection (self),
parent_dev,
priv->ip_iface,
priv->proxy_config,
priv->ip4_config,
priv->ip6_config,
NULL,
NULL,
NULL);
if (priv->proxy_config) {
nm_pacrunner_manager_send (nm_pacrunner_manager_get (),
priv->ip_iface,
priv->proxy_config,
priv->ip4_config,
priv->ip6_config);
}
break;
case STATE_DEACTIVATING:
if (quitting) {
@ -569,6 +582,7 @@ _set_vpn_state (NMVpnConnection *self,
_get_applied_connection (self),
parent_dev,
priv->ip_iface,
priv->proxy_config,
priv->ip4_config,
priv->ip6_config);
} else {
@ -577,6 +591,7 @@ _set_vpn_state (NMVpnConnection *self,
_get_applied_connection (self),
parent_dev,
priv->ip_iface,
priv->proxy_config,
priv->ip4_config,
priv->ip6_config,
dispatcher_pre_down_done,
@ -586,6 +601,9 @@ _set_vpn_state (NMVpnConnection *self,
dispatcher_pre_down_done (0, self);
}
}
/* Remove config from PacRunner */
nm_pacrunner_manager_remove (nm_pacrunner_manager_get(), priv->ip_iface);
break;
case STATE_FAILED:
case STATE_DISCONNECTED:
@ -599,6 +617,7 @@ _set_vpn_state (NMVpnConnection *self,
parent_dev,
priv->ip_iface,
NULL,
NULL,
NULL);
} else {
nm_dispatcher_call_vpn (DISPATCHER_ACTION_VPN_DOWN,
@ -610,6 +629,7 @@ _set_vpn_state (NMVpnConnection *self,
NULL,
NULL,
NULL,
NULL,
NULL);
}
}
@ -1277,6 +1297,20 @@ process_generic_config (NMVpnConnection *self, GVariant *dict)
_notify (self, PROP_BANNER);
}
/* Proxy Config */
g_clear_object (&priv->proxy_config);
priv->proxy_config = nm_proxy_config_new ();
if (g_variant_lookup (dict, NM_VPN_PLUGIN_CONFIG_PROXY_PAC, "&s", &str)) {
nm_proxy_config_set_method (priv->proxy_config, NM_PROXY_CONFIG_METHOD_AUTO);
nm_proxy_config_set_pac_url (priv->proxy_config, str);
} else
nm_proxy_config_set_method (priv->proxy_config, NM_PROXY_CONFIG_METHOD_NONE);
/* User overrides if any from the NMConnection's Proxy settings */
nm_proxy_config_merge_setting (priv->proxy_config,
nm_connection_get_setting_proxy (_get_applied_connection (self)));
/* External world-visible address of the VPN server */
priv->ip4_external_gw = 0;
g_clear_pointer (&priv->ip6_external_gw, g_free);
@ -2199,6 +2233,14 @@ nm_vpn_connection_get_banner (NMVpnConnection *self)
return NM_VPN_CONNECTION_GET_PRIVATE (self)->banner;
}
NMProxyConfig *
nm_vpn_connection_get_proxy_config (NMVpnConnection *self)
{
g_return_val_if_fail (NM_IS_VPN_CONNECTION (self), NULL);
return NM_VPN_CONNECTION_GET_PRIVATE (self)->proxy_config;
}
NMIP4Config *
nm_vpn_connection_get_ip4_config (NMVpnConnection *self)
{
@ -2597,6 +2639,7 @@ dispose (GObject *object)
g_cancellable_cancel (priv->cancellable);
g_clear_object (&priv->cancellable);
}
g_clear_object (&priv->proxy_config);
nm_exported_object_clear_and_unexport (&priv->ip4_config);
nm_exported_object_clear_and_unexport (&priv->ip6_config);
g_clear_object (&priv->proxy);

View file

@ -68,6 +68,8 @@ void nm_vpn_connection_disconnect (NMVpnConnection *self,
NMVpnConnectionStateReason reason,
gboolean quitting);
NMProxyConfig * nm_vpn_connection_get_proxy_config (NMVpnConnection *self);
NMIP4Config * nm_vpn_connection_get_ip4_config (NMVpnConnection *self);
NMIP6Config * nm_vpn_connection_get_ip6_config (NMVpnConnection *self);
const char * nm_vpn_connection_get_ip_iface (NMVpnConnection *self, gboolean fallback_device);