Blame clients/tui/nm-editor-bindings.c

Packit Service a1bd4f
/* SPDX-License-Identifier: GPL-2.0+ */
Packit 5756e2
/*
Packit 5756e2
 * Copyright (C) 2013 Red Hat, Inc.
Packit 5756e2
 */
Packit 5756e2
Packit 5756e2
/**
Packit 5756e2
 * SECTION:nm-editor-bindings
Packit 5756e2
 * @short_description: #GBinding-based NM connection editor helpers
Packit 5756e2
 *
Packit 5756e2
 * nm-editor-bindings contains helper functions to bind NMSettings objects
Packit 5756e2
 * to connection editing widgets. The goal is that this should eventually be
Packit 5756e2
 * shared between nmtui, nm-connection-editor, and gnome-control-center.
Packit 5756e2
 */
Packit 5756e2
Packit 5756e2
#include "nm-default.h"
Packit 5756e2
Packit 5756e2
#include "nm-editor-bindings.h"
Packit 5756e2
Packit 5756e2
#include <arpa/inet.h>
Packit 5756e2
#include <netinet/in.h>
Packit 5756e2
#include <stdlib.h>
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
value_transform_string_int(const GValue *src_value, GValue *dest_value)
Packit 5756e2
{
Packit Service a1bd4f
    long  val;
Packit Service a1bd4f
    char *end;
Packit 5756e2
Packit Service a1bd4f
    val = strtol(g_value_get_string(src_value), &end, 10);
Packit Service a1bd4f
    if (val < G_MININT || val > G_MAXINT || *end)
Packit Service a1bd4f
        return;
Packit 5756e2
Packit Service a1bd4f
    g_value_set_int(dest_value, (int) val);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
value_transform_string_uint(const GValue *src_value, GValue *dest_value)
Packit 5756e2
{
Packit Service a1bd4f
    long  val;
Packit Service a1bd4f
    char *end;
Packit 5756e2
Packit Service a1bd4f
    val = strtol(g_value_get_string(src_value), &end, 10);
Packit Service a1bd4f
    if (val < 0 || val > G_MAXUINT || *end)
Packit Service a1bd4f
        return;
Packit 5756e2
Packit Service a1bd4f
    g_value_set_uint(dest_value, (int) val);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
void
Packit Service a1bd4f
nm_editor_bindings_init(void)
Packit 5756e2
{
Packit Service a1bd4f
    /* glib registers number -> string, but not string -> number */
Packit Service a1bd4f
    g_value_register_transform_func(G_TYPE_STRING, G_TYPE_INT, value_transform_string_int);
Packit Service a1bd4f
    g_value_register_transform_func(G_TYPE_STRING, G_TYPE_UINT, value_transform_string_uint);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
ip_addresses_with_prefix_to_strv(GBinding *    binding,
Packit Service a1bd4f
                                 const GValue *source_value,
Packit Service a1bd4f
                                 GValue *      target_value,
Packit Service a1bd4f
                                 gpointer      user_data)
Packit 5756e2
{
Packit Service a1bd4f
    GPtrArray *  addrs;
Packit Service a1bd4f
    NMIPAddress *addr;
Packit Service a1bd4f
    const char * addrstr;
Packit Service a1bd4f
    guint32      prefix;
Packit Service a1bd4f
    char **      strings;
Packit Service a1bd4f
    int          i;
Packit Service a1bd4f
Packit Service a1bd4f
    addrs   = g_value_get_boxed(source_value);
Packit Service a1bd4f
    strings = g_new0(char *, addrs->len + 1);
Packit Service a1bd4f
Packit Service a1bd4f
    for (i = 0; i < addrs->len; i++) {
Packit Service a1bd4f
        addr    = addrs->pdata[i];
Packit Service a1bd4f
        addrstr = nm_ip_address_get_address(addr);
Packit Service a1bd4f
        prefix  = nm_ip_address_get_prefix(addr);
Packit Service a1bd4f
Packit Service a1bd4f
        if (addrstr)
Packit Service a1bd4f
            strings[i] = g_strdup_printf("%s/%d", addrstr, (int) prefix);
Packit Service a1bd4f
        else
Packit Service a1bd4f
            strings[i] = g_strdup("");
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    g_value_take_boxed(target_value, strings);
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
ip_addresses_with_prefix_from_strv(GBinding *    binding,
Packit Service a1bd4f
                                   const GValue *source_value,
Packit Service a1bd4f
                                   GValue *      target_value,
Packit Service a1bd4f
                                   gpointer      user_data)
Packit 5756e2
{
Packit Service a1bd4f
    int          addr_family = GPOINTER_TO_INT(user_data);
Packit Service a1bd4f
    char **      strings;
Packit Service a1bd4f
    GPtrArray *  addrs;
Packit Service a1bd4f
    NMIPAddress *addr;
Packit Service a1bd4f
    char *       addrstr;
Packit Service a1bd4f
    int          prefix;
Packit Service a1bd4f
    int          i;
Packit Service a1bd4f
Packit Service a1bd4f
    strings = g_value_get_boxed(source_value);
Packit Service a1bd4f
    /* Fetch the original property value, so as to preserve their extra attributes */
Packit Service a1bd4f
    g_object_get(g_binding_get_source(binding),
Packit Service a1bd4f
                 g_binding_get_source_property(binding),
Packit Service a1bd4f
                 &addrs,
Packit Service a1bd4f
                 NULL);
Packit Service a1bd4f
Packit Service a1bd4f
    for (i = 0; strings[i]; i++) {
Packit Service a1bd4f
        if (i >= addrs->len) {
Packit Service a1bd4f
            if (addr_family == AF_INET)
Packit Service a1bd4f
                addr = nm_ip_address_new(AF_INET, "0.0.0.0", 32, NULL);
Packit Service a1bd4f
            else
Packit Service a1bd4f
                addr = nm_ip_address_new(AF_INET6, "::", 128, NULL);
Packit Service a1bd4f
            g_ptr_array_add(addrs, addr);
Packit Service a1bd4f
        } else
Packit Service a1bd4f
            addr = addrs->pdata[i];
Packit Service a1bd4f
Packit Service a1bd4f
        if (!nm_utils_parse_inaddr_prefix(addr_family, strings[i], &addrstr, &prefix)) {
Packit Service a1bd4f
            g_ptr_array_unref(addrs);
Packit Service a1bd4f
            return FALSE;
Packit Service a1bd4f
        }
Packit Service a1bd4f
Packit Service a1bd4f
        if (prefix == -1) {
Packit Service a1bd4f
            if (addr_family == AF_INET) {
Packit Service a1bd4f
                in_addr_t v4;
Packit Service a1bd4f
Packit Service a1bd4f
                inet_pton(addr_family, addrstr, &v4;;
Packit Service a1bd4f
                if (nm_utils_ip_is_site_local(AF_INET, &v4))
Packit Service a1bd4f
                    prefix = nm_utils_ip4_get_default_prefix(v4);
Packit Service a1bd4f
                else
Packit Service a1bd4f
                    prefix = 32;
Packit Service a1bd4f
            } else
Packit Service a1bd4f
                prefix = 64;
Packit Service a1bd4f
        }
Packit Service a1bd4f
Packit Service a1bd4f
        nm_ip_address_set_address(addr, addrstr);
Packit Service a1bd4f
        nm_ip_address_set_prefix(addr, prefix);
Packit Service a1bd4f
        g_free(addrstr);
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    g_ptr_array_set_size(addrs, i);
Packit Service a1bd4f
    g_value_take_boxed(target_value, addrs);
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
/**
Packit 5756e2
 * nm_editor_bind_ip_addresses_with_prefix_to_strv:
Packit 5756e2
 * @addr_family: the IP address family
Packit 5756e2
 * @source: the source object (eg, an #NMSettingIP4Config)
Packit 5756e2
 * @source_property: the property on @source to bind (eg,
Packit 5756e2
 *   %NM_SETTING_IP4_CONFIG_ADDRESSES)
Packit 5756e2
 * @target: the target object (eg, an #NmtAddressList)
Packit 5756e2
 * @target_property: the property on @target to bind
Packit 5756e2
 *   (eg, "strings")
Packit 5756e2
 * @flags: %GBindingFlags
Packit 5756e2
 *
Packit 5756e2
 * Binds the #GPtrArray-of-#NMIPAddress property @source_property on @source to
Packit 5756e2
 * the %G_TYPE_STRV property @target_property on @target.
Packit 5756e2
 *
Packit 5756e2
 * Each #NMIPAddress in @source_property will be converted to a string of the
Packit 5756e2
 * form "ip.ad.dr.ess/prefix" or "ip:ad:dr:ess/prefix" in @target_property (and
Packit 5756e2
 * vice versa if %G_BINDING_BIDIRECTIONAL) is specified.
Packit 5756e2
 */
Packit 5756e2
void
Packit Service a1bd4f
nm_editor_bind_ip_addresses_with_prefix_to_strv(int           addr_family,
Packit Service a1bd4f
                                                gpointer      source,
Packit Service a1bd4f
                                                const char *  source_property,
Packit Service a1bd4f
                                                gpointer      target,
Packit Service a1bd4f
                                                const char *  target_property,
Packit Service a1bd4f
                                                GBindingFlags flags)
Packit 5756e2
{
Packit Service a1bd4f
    g_object_bind_property_full(source,
Packit Service a1bd4f
                                source_property,
Packit Service a1bd4f
                                target,
Packit Service a1bd4f
                                target_property,
Packit Service a1bd4f
                                flags,
Packit Service a1bd4f
                                ip_addresses_with_prefix_to_strv,
Packit Service a1bd4f
                                ip_addresses_with_prefix_from_strv,
Packit Service a1bd4f
                                GINT_TO_POINTER(addr_family),
Packit Service a1bd4f
                                NULL);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
ip_addresses_check_and_copy(GBinding *    binding,
Packit Service a1bd4f
                            const GValue *source_value,
Packit Service a1bd4f
                            GValue *      target_value,
Packit Service a1bd4f
                            gpointer      user_data)
Packit 5756e2
{
Packit Service a1bd4f
    int    addr_family = GPOINTER_TO_INT(user_data);
Packit Service a1bd4f
    char **strings;
Packit Service a1bd4f
    int    i;
Packit 5756e2
Packit Service a1bd4f
    strings = g_value_get_boxed(source_value);
Packit 5756e2
Packit Service a1bd4f
    for (i = 0; strings[i]; i++) {
Packit Service a1bd4f
        if (!nm_utils_ipaddr_is_valid(addr_family, strings[i]))
Packit Service a1bd4f
            return FALSE;
Packit Service a1bd4f
    }
Packit 5756e2
Packit Service a1bd4f
    g_value_set_boxed(target_value, strings);
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
/**
Packit 5756e2
 * nm_editor_bind_ip_addresses_to_strv:
Packit 5756e2
 * @addr_family: the IP address family
Packit 5756e2
 * @source: the source object (eg, an #NMSettingIP4Config)
Packit 5756e2
 * @source_property: the property on @source to bind (eg,
Packit 5756e2
 *   %NM_SETTING_IP4_CONFIG_DNS)
Packit 5756e2
 * @target: the target object (eg, an #NmtAddressList)
Packit 5756e2
 * @target_property: the property on @target to bind
Packit 5756e2
 *   (eg, "strings")
Packit 5756e2
 * @flags: %GBindingFlags
Packit 5756e2
 *
Packit 5756e2
 * Binds the %G_TYPE_STRV property @source_property on @source to the
Packit 5756e2
 * %G_TYPE_STRV property @target_property on @target, verifying that
Packit 5756e2
 * each string is a valid address of type @addr_family when copying.
Packit 5756e2
 */
Packit 5756e2
void
Packit Service a1bd4f
nm_editor_bind_ip_addresses_to_strv(int           addr_family,
Packit Service a1bd4f
                                    gpointer      source,
Packit Service a1bd4f
                                    const char *  source_property,
Packit Service a1bd4f
                                    gpointer      target,
Packit Service a1bd4f
                                    const char *  target_property,
Packit Service a1bd4f
                                    GBindingFlags flags)
Packit 5756e2
{
Packit Service a1bd4f
    g_object_bind_property_full(source,
Packit Service a1bd4f
                                source_property,
Packit Service a1bd4f
                                target,
Packit Service a1bd4f
                                target_property,
Packit Service a1bd4f
                                flags,
Packit Service a1bd4f
                                ip_addresses_check_and_copy,
Packit Service a1bd4f
                                ip_addresses_check_and_copy,
Packit Service a1bd4f
                                GINT_TO_POINTER(addr_family),
Packit Service a1bd4f
                                NULL);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
ip_gateway_to_string(GBinding *    binding,
Packit Service a1bd4f
                     const GValue *source_value,
Packit Service a1bd4f
                     GValue *      target_value,
Packit Service a1bd4f
                     gpointer      user_data)
Packit 5756e2
{
Packit Service a1bd4f
    g_value_set_string(target_value, g_value_get_string(source_value));
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
ip_gateway_from_string(GBinding *    binding,
Packit Service a1bd4f
                       const GValue *source_value,
Packit Service a1bd4f
                       GValue *      target_value,
Packit Service a1bd4f
                       gpointer      user_data)
Packit 5756e2
{
Packit Service a1bd4f
    int         addr_family = GPOINTER_TO_INT(user_data);
Packit Service a1bd4f
    const char *gateway;
Packit 5756e2
Packit Service a1bd4f
    gateway = g_value_get_string(source_value);
Packit Service a1bd4f
    if (gateway && !nm_utils_ipaddr_is_valid(addr_family, gateway))
Packit Service a1bd4f
        gateway = NULL;
Packit 5756e2
Packit Service a1bd4f
    g_value_set_string(target_value, gateway);
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
ip_addresses_to_gateway(GBinding *    binding,
Packit Service a1bd4f
                        const GValue *source_value,
Packit Service a1bd4f
                        GValue *      target_value,
Packit Service a1bd4f
                        gpointer      user_data)
Packit 5756e2
{
Packit Service a1bd4f
    GPtrArray *addrs;
Packit Service a1bd4f
Packit Service a1bd4f
    addrs = g_value_get_boxed(source_value);
Packit Service a1bd4f
    if (addrs->len == 0) {
Packit Service a1bd4f
        g_value_set_string(target_value, NULL);
Packit Service a1bd4f
        return TRUE;
Packit Service a1bd4f
    } else
Packit Service a1bd4f
        return FALSE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
ip_addresses_to_sensitivity(GBinding *    binding,
Packit Service a1bd4f
                            const GValue *source_value,
Packit Service a1bd4f
                            GValue *      target_value,
Packit Service a1bd4f
                            gpointer      user_data)
Packit 5756e2
{
Packit Service a1bd4f
    GPtrArray *addrs;
Packit 5756e2
Packit Service a1bd4f
    addrs = g_value_get_boxed(source_value);
Packit Service a1bd4f
    g_value_set_boolean(target_value, addrs->len != 0);
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
/**
Packit 5756e2
 * nm_editor_bind_ip_gateway_to_string:
Packit 5756e2
 * @addr_family: the IP address family
Packit 5756e2
 * @source: the source #NMSettingIPConfig
Packit 5756e2
 * @target: the target object (eg, an #NmtIPEntry)
Packit 5756e2
 * @target_property: the property on @target to bind (eg, "text")
Packit 5756e2
 * @target_sensitive_property: the "sensitivity" property on @target to bind
Packit 5756e2
 * @flags: %GBindingFlags
Packit 5756e2
 *
Packit 5756e2
 * Binds the #NMSettingIPConfig:gateway property on @source to the
Packit 5756e2
 * %G_TYPE_STRING property @target_property and %G_TYPE_BOOLEAN property
Packit 5756e2
 * @target_sensitive_property on @target, also taking the
Packit 5756e2
 * #NMSettingIPConfig:addresses property on @source into account.
Packit 5756e2
 *
Packit 5756e2
 * In particular, if @source has no static IP addresses, then @target_property
Packit 5756e2
 * will be set to "" and @target_sensitive_property will be set to %FALSE.
Packit 5756e2
 *
Packit 5756e2
 * If @source has at least one static IP address, then
Packit 5756e2
 * @target_sensitive_property will be set to %TRUE, @target_property will be
Packit 5756e2
 * initialized from @source's #NMSettingIPConfig:gateway, and @source will be
Packit 5756e2
 * updated with the value of @target_property whenever it contains a valid IP
Packit 5756e2
 * address.
Packit 5756e2
 */
Packit 5756e2
void
Packit Service a1bd4f
nm_editor_bind_ip_gateway_to_string(int                addr_family,
Packit Service a1bd4f
                                    NMSettingIPConfig *source,
Packit Service a1bd4f
                                    gpointer           target,
Packit Service a1bd4f
                                    const char *       target_property,
Packit Service a1bd4f
                                    const char *       target_sensitive_property,
Packit Service a1bd4f
                                    GBindingFlags      flags)
Packit 5756e2
{
Packit Service a1bd4f
    g_object_bind_property_full(source,
Packit Service a1bd4f
                                "gateway",
Packit Service a1bd4f
                                target,
Packit Service a1bd4f
                                target_property,
Packit Service a1bd4f
                                flags,
Packit Service a1bd4f
                                ip_gateway_to_string,
Packit Service a1bd4f
                                ip_gateway_from_string,
Packit Service a1bd4f
                                GINT_TO_POINTER(addr_family),
Packit Service a1bd4f
                                NULL);
Packit Service a1bd4f
    g_object_bind_property_full(source,
Packit Service a1bd4f
                                "addresses",
Packit Service a1bd4f
                                source,
Packit Service a1bd4f
                                "gateway",
Packit Service a1bd4f
                                (flags & G_BINDING_SYNC_CREATE),
Packit Service a1bd4f
                                ip_addresses_to_gateway,
Packit Service a1bd4f
                                NULL,
Packit Service a1bd4f
                                NULL,
Packit Service a1bd4f
                                NULL);
Packit Service a1bd4f
    g_object_bind_property_full(source,
Packit Service a1bd4f
                                "addresses",
Packit Service a1bd4f
                                target,
Packit Service a1bd4f
                                target_sensitive_property,
Packit Service a1bd4f
                                (flags & G_BINDING_SYNC_CREATE),
Packit Service a1bd4f
                                ip_addresses_to_sensitivity,
Packit Service a1bd4f
                                NULL,
Packit Service a1bd4f
                                NULL,
Packit Service a1bd4f
                                NULL);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
ip_route_transform_to_dest_string(GBinding *    binding,
Packit Service a1bd4f
                                  const GValue *source_value,
Packit Service a1bd4f
                                  GValue *      target_value,
Packit Service a1bd4f
                                  gpointer      user_data)
Packit 5756e2
{
Packit Service a1bd4f
    NMIPRoute * route;
Packit Service a1bd4f
    const char *addrstr;
Packit Service a1bd4f
    char *      string;
Packit Service a1bd4f
Packit Service a1bd4f
    route = g_value_get_boxed(source_value);
Packit Service a1bd4f
    if (route)
Packit Service a1bd4f
        addrstr = nm_ip_route_get_dest(route);
Packit Service a1bd4f
    else
Packit Service a1bd4f
        addrstr = NULL;
Packit Service a1bd4f
Packit Service a1bd4f
    if (addrstr) {
Packit Service a1bd4f
        string = g_strdup_printf("%s/%d", addrstr, (int) nm_ip_route_get_prefix(route));
Packit Service a1bd4f
        g_value_take_string(target_value, string);
Packit Service a1bd4f
    } else
Packit Service a1bd4f
        g_value_set_string(target_value, "");
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
ip_route_transform_to_next_hop_string(GBinding *    binding,
Packit Service a1bd4f
                                      const GValue *source_value,
Packit Service a1bd4f
                                      GValue *      target_value,
Packit Service a1bd4f
                                      gpointer      user_data)
Packit 5756e2
{
Packit Service a1bd4f
    NMIPRoute * route;
Packit Service a1bd4f
    const char *addrstr;
Packit Service a1bd4f
Packit Service a1bd4f
    route = g_value_get_boxed(source_value);
Packit Service a1bd4f
    if (route) {
Packit Service a1bd4f
        addrstr = nm_ip_route_get_next_hop(route);
Packit Service a1bd4f
        if (!addrstr)
Packit Service a1bd4f
            addrstr = "";
Packit Service a1bd4f
    } else
Packit Service a1bd4f
        addrstr = "";
Packit Service a1bd4f
Packit Service a1bd4f
    g_value_set_string(target_value, addrstr);
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
ip_route_transform_to_metric_string(GBinding *    binding,
Packit Service a1bd4f
                                    const GValue *source_value,
Packit Service a1bd4f
                                    GValue *      target_value,
Packit Service a1bd4f
                                    gpointer      user_data)
Packit 5756e2
{
Packit Service a1bd4f
    NMIPRoute *route;
Packit Service a1bd4f
    char *     string;
Packit Service a1bd4f
Packit Service a1bd4f
    route = g_value_get_boxed(source_value);
Packit Service a1bd4f
    if (route && nm_ip_route_get_dest(route) && nm_ip_route_get_metric(route) != -1) {
Packit Service a1bd4f
        string = g_strdup_printf("%lu", (gulong) nm_ip_route_get_metric(route));
Packit Service a1bd4f
        g_value_take_string(target_value, string);
Packit Service a1bd4f
    } else
Packit Service a1bd4f
        g_value_set_string(target_value, "");
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
ip_route_transform_from_dest_string(GBinding *    binding,
Packit Service a1bd4f
                                    const GValue *source_value,
Packit Service a1bd4f
                                    GValue *      target_value,
Packit Service a1bd4f
                                    gpointer      user_data)
Packit 5756e2
{
Packit Service a1bd4f
    int         addr_family = GPOINTER_TO_INT(user_data);
Packit Service a1bd4f
    NMIPRoute * route;
Packit Service a1bd4f
    const char *text;
Packit Service a1bd4f
    char *      addrstr;
Packit Service a1bd4f
    int         prefix;
Packit Service a1bd4f
Packit Service a1bd4f
    text = g_value_get_string(source_value);
Packit Service a1bd4f
    if (!nm_utils_parse_inaddr_prefix(addr_family, text, &addrstr, &prefix))
Packit Service a1bd4f
        return FALSE;
Packit Service a1bd4f
Packit Service a1bd4f
    /* Fetch the original property value */
Packit Service a1bd4f
    g_object_get(g_binding_get_source(binding),
Packit Service a1bd4f
                 g_binding_get_source_property(binding),
Packit Service a1bd4f
                 &route,
Packit Service a1bd4f
                 NULL);
Packit Service a1bd4f
Packit Service a1bd4f
    if (prefix == -1) {
Packit Service a1bd4f
        if (addr_family == AF_INET) {
Packit Service a1bd4f
            in_addr_t v4;
Packit Service a1bd4f
Packit Service a1bd4f
            inet_pton(addr_family, addrstr, &v4;;
Packit Service a1bd4f
            if (nm_utils_ip_is_site_local(AF_INET, &v4)) {
Packit Service a1bd4f
                prefix = nm_utils_ip4_get_default_prefix(v4);
Packit Service a1bd4f
                if (v4 & (~nm_utils_ip4_prefix_to_netmask(prefix)))
Packit Service a1bd4f
                    prefix = 32;
Packit Service a1bd4f
            } else
Packit Service a1bd4f
                prefix = 32;
Packit Service a1bd4f
        } else
Packit Service a1bd4f
            prefix = 64;
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    nm_ip_route_set_dest(route, addrstr);
Packit Service a1bd4f
    nm_ip_route_set_prefix(route, prefix);
Packit Service a1bd4f
    g_free(addrstr);
Packit Service a1bd4f
Packit Service a1bd4f
    g_value_take_boxed(target_value, route);
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
ip_route_transform_from_next_hop_string(GBinding *    binding,
Packit Service a1bd4f
                                        const GValue *source_value,
Packit Service a1bd4f
                                        GValue *      target_value,
Packit Service a1bd4f
                                        gpointer      user_data)
Packit 5756e2
{
Packit Service a1bd4f
    int         addr_family = GPOINTER_TO_INT(user_data);
Packit Service a1bd4f
    NMIPRoute * route;
Packit Service a1bd4f
    const char *text;
Packit Service a1bd4f
Packit Service a1bd4f
    text = g_value_get_string(source_value);
Packit Service a1bd4f
    if (*text) {
Packit Service a1bd4f
        if (!nm_utils_ipaddr_is_valid(addr_family, text))
Packit Service a1bd4f
            return FALSE;
Packit Service a1bd4f
    } else
Packit Service a1bd4f
        text = NULL;
Packit Service a1bd4f
Packit Service a1bd4f
    /* Fetch the original property value */
Packit Service a1bd4f
    g_object_get(g_binding_get_source(binding),
Packit Service a1bd4f
                 g_binding_get_source_property(binding),
Packit Service a1bd4f
                 &route,
Packit Service a1bd4f
                 NULL);
Packit Service a1bd4f
Packit Service a1bd4f
    nm_ip_route_set_next_hop(route, text);
Packit Service a1bd4f
Packit Service a1bd4f
    g_value_take_boxed(target_value, route);
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
ip_route_transform_from_metric_string(GBinding *    binding,
Packit Service a1bd4f
                                      const GValue *source_value,
Packit Service a1bd4f
                                      GValue *      target_value,
Packit Service a1bd4f
                                      gpointer      user_data)
Packit 5756e2
{
Packit Service a1bd4f
    NMIPRoute * route;
Packit Service a1bd4f
    const char *text;
Packit Service a1bd4f
    gint64      metric;
Packit 5756e2
Packit Service a1bd4f
    text   = g_value_get_string(source_value);
Packit Service a1bd4f
    metric = _nm_utils_ascii_str_to_int64(text, 10, 0, G_MAXUINT32, -1);
Packit 5756e2
Packit Service a1bd4f
    /* Fetch the original property value */
Packit Service a1bd4f
    g_object_get(g_binding_get_source(binding),
Packit Service a1bd4f
                 g_binding_get_source_property(binding),
Packit Service a1bd4f
                 &route,
Packit Service a1bd4f
                 NULL);
Packit 5756e2
Packit Service a1bd4f
    nm_ip_route_set_metric(route, metric);
Packit 5756e2
Packit Service a1bd4f
    g_value_take_boxed(target_value, route);
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
/**
Packit 5756e2
 * nm_editor_bind_ip_route_to_strings:
Packit 5756e2
 * @addr_family: the IP address family
Packit 5756e2
 * @source: the source object
Packit 5756e2
 * @source_property: the source property
Packit 5756e2
 * @dest_target: the target object for the route's destination
Packit 5756e2
 * @dest_target_property: the property on @dest_target
Packit 5756e2
 * @next_hop_target: the target object for the route's next hop
Packit 5756e2
 * @next_hop_target_property: the property on @next_hop_target
Packit 5756e2
 * @metric_target: the target object for the route's metric
Packit 5756e2
 * @metric_target_property: the property on @metric_target
Packit 5756e2
 * @flags: %GBindingFlags
Packit 5756e2
 *
Packit 5756e2
 * Binds the #NMIPRoute-valued property @source_property on @source to the
Packit 5756e2
 * three indicated string-valued target properties (and vice versa if
Packit 5756e2
 * %G_BINDING_BIDIRECTIONAL is specified).
Packit 5756e2
 *
Packit 5756e2
 * @dest_target_property should be an "address/prefix" string, as with
Packit 5756e2
 * nm_editor_bind_ip4_addresses_with_prefix_to_strv(). @next_hop_target_property
Packit 5756e2
 * is a plain IP address, and @metric_target_property is a number.
Packit 5756e2
 */
Packit 5756e2
void
Packit Service a1bd4f
nm_editor_bind_ip_route_to_strings(int           addr_family,
Packit Service a1bd4f
                                   gpointer      source,
Packit Service a1bd4f
                                   const char *  source_property,
Packit Service a1bd4f
                                   gpointer      dest_target,
Packit Service a1bd4f
                                   const char *  dest_target_property,
Packit Service a1bd4f
                                   gpointer      next_hop_target,
Packit Service a1bd4f
                                   const char *  next_hop_target_property,
Packit Service a1bd4f
                                   gpointer      metric_target,
Packit Service a1bd4f
                                   const char *  metric_target_property,
Packit Service a1bd4f
                                   GBindingFlags flags)
Packit 5756e2
{
Packit Service a1bd4f
    g_object_bind_property_full(source,
Packit Service a1bd4f
                                source_property,
Packit Service a1bd4f
                                dest_target,
Packit Service a1bd4f
                                dest_target_property,
Packit Service a1bd4f
                                flags,
Packit Service a1bd4f
                                ip_route_transform_to_dest_string,
Packit Service a1bd4f
                                ip_route_transform_from_dest_string,
Packit Service a1bd4f
                                GINT_TO_POINTER(addr_family),
Packit Service a1bd4f
                                NULL);
Packit Service a1bd4f
    g_object_bind_property_full(source,
Packit Service a1bd4f
                                source_property,
Packit Service a1bd4f
                                next_hop_target,
Packit Service a1bd4f
                                next_hop_target_property,
Packit Service a1bd4f
                                flags,
Packit Service a1bd4f
                                ip_route_transform_to_next_hop_string,
Packit Service a1bd4f
                                ip_route_transform_from_next_hop_string,
Packit Service a1bd4f
                                GINT_TO_POINTER(addr_family),
Packit Service a1bd4f
                                NULL);
Packit Service a1bd4f
    g_object_bind_property_full(source,
Packit Service a1bd4f
                                source_property,
Packit Service a1bd4f
                                metric_target,
Packit Service a1bd4f
                                metric_target_property,
Packit Service a1bd4f
                                flags,
Packit Service a1bd4f
                                ip_route_transform_to_metric_string,
Packit Service a1bd4f
                                ip_route_transform_from_metric_string,
Packit Service a1bd4f
                                GINT_TO_POINTER(addr_family),
Packit Service a1bd4f
                                NULL);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
/* Wireless security method binding */
Packit 5756e2
typedef struct {
Packit Service a1bd4f
    NMConnection *             connection;
Packit Service a1bd4f
    NMSettingWirelessSecurity *s_wsec;
Packit Service a1bd4f
    gboolean                   s_wsec_in_use;
Packit 5756e2
Packit Service a1bd4f
    GObject *target;
Packit Service a1bd4f
    char *   target_property;
Packit 5756e2
Packit Service a1bd4f
    gboolean updating;
Packit 5756e2
} NMEditorWirelessSecurityMethodBinding;
Packit 5756e2
Packit 5756e2
static const char *
Packit Service a1bd4f
get_security_type(NMEditorWirelessSecurityMethodBinding *binding)
Packit 5756e2
{
Packit Service a1bd4f
    const char *key_mgmt, *auth_alg;
Packit 5756e2
Packit Service a1bd4f
    if (!binding->s_wsec_in_use)
Packit Service a1bd4f
        return "none";
Packit 5756e2
Packit Service a1bd4f
    key_mgmt = nm_setting_wireless_security_get_key_mgmt(binding->s_wsec);
Packit Service a1bd4f
    auth_alg = nm_setting_wireless_security_get_auth_alg(binding->s_wsec);
Packit 5756e2
Packit Service a1bd4f
    /* No IEEE 802.1x */
Packit Service a1bd4f
    if (!strcmp(key_mgmt, "none")) {
Packit Service a1bd4f
        NMWepKeyType wep_type = nm_setting_wireless_security_get_wep_key_type(binding->s_wsec);
Packit 5756e2
Packit Service a1bd4f
        if (wep_type == NM_WEP_KEY_TYPE_KEY)
Packit Service a1bd4f
            return "wep-key";
Packit Service a1bd4f
        else
Packit Service a1bd4f
            return "wep-passphrase";
Packit Service a1bd4f
    }
Packit 5756e2
Packit Service a1bd4f
    if (!strcmp(key_mgmt, "ieee8021x")) {
Packit Service a1bd4f
        if (auth_alg && !strcmp(auth_alg, "leap"))
Packit Service a1bd4f
            return "leap";
Packit Service a1bd4f
        return "dynamic-wep";
Packit Service a1bd4f
    }
Packit 5756e2
Packit Service a1bd4f
    if (!strcmp(key_mgmt, "wpa-psk"))
Packit Service a1bd4f
        return "wpa-personal";
Packit 5756e2
Packit Service a1bd4f
    if (!strcmp(key_mgmt, "sae"))
Packit Service a1bd4f
        return "wpa3-personal";
Packit 5756e2
Packit Service a1bd4f
    if (!strcmp(key_mgmt, "owe"))
Packit Service a1bd4f
        return "owe";
Packit 5756e2
Packit Service a1bd4f
    if (!strcmp(key_mgmt, "wpa-eap"))
Packit Service a1bd4f
        return "wpa-enterprise";
Packit 5756e2
Packit Service d0b836
    if (!strcmp(key_mgmt, "wpa-eap-suite-b-192"))
Packit Service d0b836
        return "wpa3-enterprise-suite-b-192";
Packit Service d0b836
Packit Service a1bd4f
    return NULL;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
wireless_security_changed(GObject *object, GParamSpec *pspec, gpointer user_data)
Packit 5756e2
{
Packit Service a1bd4f
    NMEditorWirelessSecurityMethodBinding *binding = user_data;
Packit 5756e2
Packit Service a1bd4f
    if (binding->updating)
Packit Service a1bd4f
        return;
Packit 5756e2
Packit Service a1bd4f
    binding->updating = TRUE;
Packit Service a1bd4f
    g_object_set(binding->target, binding->target_property, get_security_type(binding), NULL);
Packit Service a1bd4f
    binding->updating = FALSE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
wireless_connection_changed(NMConnection *connection, gpointer user_data)
Packit 5756e2
{
Packit Service a1bd4f
    NMEditorWirelessSecurityMethodBinding *binding = user_data;
Packit Service a1bd4f
    NMSettingWirelessSecurity *            s_wsec;
Packit 5756e2
Packit Service a1bd4f
    if (binding->updating)
Packit Service a1bd4f
        return;
Packit 5756e2
Packit Service a1bd4f
    s_wsec = nm_connection_get_setting_wireless_security(connection);
Packit Service a1bd4f
    if ((s_wsec && binding->s_wsec_in_use) || (!s_wsec && !binding->s_wsec_in_use))
Packit Service a1bd4f
        return;
Packit 5756e2
Packit Service a1bd4f
    binding->s_wsec_in_use = !binding->s_wsec_in_use;
Packit Service a1bd4f
    wireless_security_changed(NULL, NULL, binding);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
wireless_security_target_changed(GObject *object, GParamSpec *pspec, gpointer user_data)
Packit 5756e2
{
Packit Service a1bd4f
    NMEditorWirelessSecurityMethodBinding *binding = user_data;
Packit Service a1bd4f
    char *                                 method;
Packit Service a1bd4f
Packit Service a1bd4f
    if (binding->updating)
Packit Service a1bd4f
        return;
Packit Service a1bd4f
Packit Service a1bd4f
    g_object_get(binding->target, binding->target_property, &method, NULL);
Packit Service a1bd4f
Packit Service a1bd4f
    binding->updating = TRUE;
Packit Service a1bd4f
Packit Service a1bd4f
    if (!strcmp(method, "none")) {
Packit Service a1bd4f
        if (!binding->s_wsec_in_use)
Packit Service a1bd4f
            return;
Packit Service a1bd4f
        binding->s_wsec_in_use = FALSE;
Packit Service a1bd4f
        nm_connection_remove_setting(binding->connection, NM_TYPE_SETTING_WIRELESS_SECURITY);
Packit Service a1bd4f
Packit Service a1bd4f
        binding->updating = FALSE;
Packit Service a1bd4f
        return;
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    if (!binding->s_wsec_in_use) {
Packit Service a1bd4f
        binding->s_wsec_in_use = TRUE;
Packit Service a1bd4f
        nm_connection_add_setting(binding->connection, NM_SETTING(binding->s_wsec));
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    if (!strcmp(method, "wep-key")) {
Packit Service a1bd4f
        g_object_set(binding->s_wsec,
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
Packit Service a1bd4f
                     "none",
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_AUTH_ALG,
Packit Service a1bd4f
                     "open",
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE,
Packit Service a1bd4f
                     NM_WEP_KEY_TYPE_KEY,
Packit Service a1bd4f
                     NULL);
Packit Service a1bd4f
    } else if (!strcmp(method, "wep-passphrase")) {
Packit Service a1bd4f
        g_object_set(binding->s_wsec,
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
Packit Service a1bd4f
                     "none",
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_AUTH_ALG,
Packit Service a1bd4f
                     "open",
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE,
Packit Service a1bd4f
                     NM_WEP_KEY_TYPE_PASSPHRASE,
Packit Service a1bd4f
                     NULL);
Packit Service a1bd4f
    } else if (!strcmp(method, "leap")) {
Packit Service a1bd4f
        g_object_set(binding->s_wsec,
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
Packit Service a1bd4f
                     "ieee8021x",
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_AUTH_ALG,
Packit Service a1bd4f
                     "leap",
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE,
Packit Service a1bd4f
                     NM_WEP_KEY_TYPE_UNKNOWN,
Packit Service a1bd4f
                     NULL);
Packit Service a1bd4f
    } else if (!strcmp(method, "dynamic-wep")) {
Packit Service a1bd4f
        g_object_set(binding->s_wsec,
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
Packit Service a1bd4f
                     "ieee8021x",
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_AUTH_ALG,
Packit Service a1bd4f
                     "open",
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE,
Packit Service a1bd4f
                     NM_WEP_KEY_TYPE_UNKNOWN,
Packit Service a1bd4f
                     NULL);
Packit Service a1bd4f
    } else if (!strcmp(method, "wpa-personal")) {
Packit Service a1bd4f
        g_object_set(binding->s_wsec,
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
Packit Service a1bd4f
                     "wpa-psk",
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_AUTH_ALG,
Packit Service a1bd4f
                     NULL,
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE,
Packit Service a1bd4f
                     NM_WEP_KEY_TYPE_UNKNOWN,
Packit Service a1bd4f
                     NULL);
Packit Service a1bd4f
    } else if (!strcmp(method, "wpa3-personal")) {
Packit Service a1bd4f
        g_object_set(binding->s_wsec,
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
Packit Service a1bd4f
                     "sae",
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_AUTH_ALG,
Packit Service a1bd4f
                     NULL,
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE,
Packit Service a1bd4f
                     NM_WEP_KEY_TYPE_UNKNOWN,
Packit Service a1bd4f
                     NULL);
Packit Service a1bd4f
    } else if (!strcmp(method, "owe")) {
Packit Service a1bd4f
        g_object_set(binding->s_wsec,
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
Packit Service a1bd4f
                     "owe",
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_AUTH_ALG,
Packit Service a1bd4f
                     NULL,
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE,
Packit Service a1bd4f
                     NM_WEP_KEY_TYPE_UNKNOWN,
Packit Service a1bd4f
                     NULL);
Packit Service a1bd4f
    } else if (!strcmp(method, "wpa-enterprise")) {
Packit Service a1bd4f
        g_object_set(binding->s_wsec,
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
Packit Service a1bd4f
                     "wpa-eap",
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_AUTH_ALG,
Packit Service a1bd4f
                     NULL,
Packit Service a1bd4f
                     NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE,
Packit Service a1bd4f
                     NM_WEP_KEY_TYPE_UNKNOWN,
Packit Service a1bd4f
                     NULL);
Packit Service a1bd4f
    } else
Packit Service a1bd4f
        g_warn_if_reached();
Packit Service a1bd4f
Packit Service a1bd4f
    binding->updating = FALSE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
wireless_security_target_destroyed(gpointer user_data, GObject *ex_target)
Packit 5756e2
{
Packit Service a1bd4f
    NMEditorWirelessSecurityMethodBinding *binding = user_data;
Packit 5756e2
Packit Service a1bd4f
    g_signal_handlers_disconnect_by_func(binding->s_wsec,
Packit Service a1bd4f
                                         G_CALLBACK(wireless_security_changed),
Packit Service a1bd4f
                                         binding);
Packit Service a1bd4f
    g_object_unref(binding->s_wsec);
Packit Service a1bd4f
    g_object_unref(binding->connection);
Packit 5756e2
Packit Service a1bd4f
    g_free(binding->target_property);
Packit 5756e2
Packit Service a1bd4f
    g_slice_free(NMEditorWirelessSecurityMethodBinding, binding);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
/**
Packit 5756e2
 * nm_editor_bind_wireless_security_method:
Packit 5756e2
 * @connection: an #NMConnection
Packit 5756e2
 * @s_wsec: an #NMSettingWirelessSecurity
Packit 5756e2
 * @target: the target widget
Packit 5756e2
 * @target_property: the string-valued property on @target to bind
Packit 5756e2
 * @flags: %GBindingFlags
Packit 5756e2
 *
Packit 5756e2
 * Binds the wireless security method on @connection to
Packit 5756e2
 * @target_property on @target (and vice versa if
Packit 5756e2
 * %G_BINDING_BIDIRECTIONAL).
Packit 5756e2
 *
Packit 5756e2
 * @target_property will be of the values "none", "wpa-personal",
Packit 5756e2
 * "wpa-enterprise", "wep-key", "wep-passphrase", "dynamic-wep", or
Packit 5756e2
 * "leap".
Packit 5756e2
 *
Packit 5756e2
 * If binding bidirectionally, @s_wsec will be automatically added to
Packit 5756e2
 * or removed from @connection as needed when @target_property
Packit 5756e2
 * changes.
Packit 5756e2
 */
Packit 5756e2
void
Packit Service a1bd4f
nm_editor_bind_wireless_security_method(NMConnection *             connection,
Packit Service a1bd4f
                                        NMSettingWirelessSecurity *s_wsec,
Packit Service a1bd4f
                                        gpointer                   target,
Packit Service a1bd4f
                                        const char *               target_property,
Packit Service a1bd4f
                                        GBindingFlags              flags)
Packit 5756e2
{
Packit Service a1bd4f
    NMEditorWirelessSecurityMethodBinding *binding;
Packit Service a1bd4f
    char *                                 notify;
Packit Service a1bd4f
Packit Service a1bd4f
    binding = g_slice_new0(NMEditorWirelessSecurityMethodBinding);
Packit Service a1bd4f
Packit Service a1bd4f
    binding->target          = target;
Packit Service a1bd4f
    binding->target_property = g_strdup(target_property);
Packit Service a1bd4f
    if (flags & G_BINDING_BIDIRECTIONAL) {
Packit Service a1bd4f
        notify = g_strdup_printf("notify::%s", target_property);
Packit Service a1bd4f
        g_signal_connect(target, notify, G_CALLBACK(wireless_security_target_changed), binding);
Packit Service a1bd4f
        g_free(notify);
Packit Service a1bd4f
    }
Packit Service a1bd4f
    g_object_weak_ref(target, wireless_security_target_destroyed, binding);
Packit Service a1bd4f
Packit Service a1bd4f
    binding->connection = g_object_ref(connection);
Packit Service a1bd4f
    g_signal_connect(connection,
Packit Service a1bd4f
                     NM_CONNECTION_CHANGED,
Packit Service a1bd4f
                     G_CALLBACK(wireless_connection_changed),
Packit Service a1bd4f
                     binding);
Packit Service a1bd4f
    binding->s_wsec_in_use = (nm_connection_get_setting_wireless_security(connection) != NULL);
Packit Service a1bd4f
Packit Service a1bd4f
    binding->s_wsec = g_object_ref(s_wsec);
Packit Service a1bd4f
    g_signal_connect(s_wsec,
Packit Service a1bd4f
                     "notify::" NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
Packit Service a1bd4f
                     G_CALLBACK(wireless_security_changed),
Packit Service a1bd4f
                     binding);
Packit Service a1bd4f
    g_signal_connect(s_wsec,
Packit Service a1bd4f
                     "notify::" NM_SETTING_WIRELESS_SECURITY_AUTH_ALG,
Packit Service a1bd4f
                     G_CALLBACK(wireless_security_changed),
Packit Service a1bd4f
                     binding);
Packit Service a1bd4f
    g_signal_connect(s_wsec,
Packit Service a1bd4f
                     "notify::" NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE,
Packit Service a1bd4f
                     G_CALLBACK(wireless_security_changed),
Packit Service a1bd4f
                     binding);
Packit Service a1bd4f
Packit Service a1bd4f
    if (flags & G_BINDING_SYNC_CREATE)
Packit Service a1bd4f
        wireless_security_changed(NULL, NULL, binding);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
/* WEP key binding */
Packit 5756e2
Packit 5756e2
typedef struct {
Packit Service a1bd4f
    NMSettingWirelessSecurity *s_wsec;
Packit Service a1bd4f
    GObject *                  entry, *key_selector;
Packit Service a1bd4f
    char *                     entry_property, *key_selector_property;
Packit 5756e2
Packit Service a1bd4f
    gboolean updating;
Packit 5756e2
} NMEditorWepKeyBinding;
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
wep_key_setting_changed(GObject *object, GParamSpec *pspec, gpointer user_data)
Packit 5756e2
{
Packit Service a1bd4f
    NMEditorWepKeyBinding *binding = user_data;
Packit Service a1bd4f
    const char *           key;
Packit Service a1bd4f
    int                    index;
Packit Service a1bd4f
Packit Service a1bd4f
    if (binding->updating)
Packit Service a1bd4f
        return;
Packit Service a1bd4f
Packit Service a1bd4f
    index = nm_setting_wireless_security_get_wep_tx_keyidx(binding->s_wsec);
Packit Service a1bd4f
    key   = nm_setting_wireless_security_get_wep_key(binding->s_wsec, index);
Packit Service a1bd4f
Packit Service a1bd4f
    binding->updating = TRUE;
Packit Service a1bd4f
    g_object_set(binding->key_selector, binding->key_selector_property, index, NULL);
Packit Service a1bd4f
    g_object_set(binding->entry, binding->entry_property, key, NULL);
Packit Service a1bd4f
    binding->updating = FALSE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
wep_key_ui_changed(GObject *object, GParamSpec *pspec, gpointer user_data)
Packit 5756e2
{
Packit Service a1bd4f
    NMEditorWepKeyBinding *binding = user_data;
Packit Service a1bd4f
    char *                 key;
Packit Service a1bd4f
    int                    index;
Packit Service a1bd4f
Packit Service a1bd4f
    if (binding->updating)
Packit Service a1bd4f
        return;
Packit Service a1bd4f
Packit Service a1bd4f
    g_object_get(binding->key_selector, binding->key_selector_property, &index, NULL);
Packit Service a1bd4f
    g_object_get(binding->entry, binding->entry_property, &key, NULL);
Packit Service a1bd4f
Packit Service a1bd4f
    binding->updating = TRUE;
Packit Service a1bd4f
    g_object_set(binding->s_wsec,
Packit Service a1bd4f
                 NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX,
Packit Service a1bd4f
                 index,
Packit Service a1bd4f
                 NM_SETTING_WIRELESS_SECURITY_WEP_KEY0,
Packit Service a1bd4f
                 index == 0 ? key : NULL,
Packit Service a1bd4f
                 NM_SETTING_WIRELESS_SECURITY_WEP_KEY1,
Packit Service a1bd4f
                 index == 1 ? key : NULL,
Packit Service a1bd4f
                 NM_SETTING_WIRELESS_SECURITY_WEP_KEY2,
Packit Service a1bd4f
                 index == 2 ? key : NULL,
Packit Service a1bd4f
                 NM_SETTING_WIRELESS_SECURITY_WEP_KEY3,
Packit Service a1bd4f
                 index == 3 ? key : NULL,
Packit Service a1bd4f
                 NULL);
Packit Service a1bd4f
    binding->updating = FALSE;
Packit Service a1bd4f
Packit Service a1bd4f
    g_free(key);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
wep_key_target_destroyed(gpointer user_data, GObject *ex_target)
Packit 5756e2
{
Packit Service a1bd4f
    NMEditorWepKeyBinding *binding = user_data;
Packit Service a1bd4f
Packit Service a1bd4f
    g_signal_handlers_disconnect_by_func(binding->s_wsec,
Packit Service a1bd4f
                                         G_CALLBACK(wep_key_setting_changed),
Packit Service a1bd4f
                                         binding);
Packit Service a1bd4f
Packit Service a1bd4f
    if (ex_target != binding->entry) {
Packit Service a1bd4f
        g_signal_handlers_disconnect_by_func(binding->entry,
Packit Service a1bd4f
                                             G_CALLBACK(wep_key_ui_changed),
Packit Service a1bd4f
                                             binding);
Packit Service a1bd4f
        g_object_weak_unref(binding->entry, wep_key_target_destroyed, binding);
Packit Service a1bd4f
    } else {
Packit Service a1bd4f
        g_signal_handlers_disconnect_by_func(binding->key_selector,
Packit Service a1bd4f
                                             G_CALLBACK(wep_key_ui_changed),
Packit Service a1bd4f
                                             binding);
Packit Service a1bd4f
        g_object_weak_unref(binding->key_selector, wep_key_target_destroyed, binding);
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    g_object_unref(binding->s_wsec);
Packit Service a1bd4f
    g_free(binding->entry_property);
Packit Service a1bd4f
    g_free(binding->key_selector_property);
Packit Service a1bd4f
Packit Service a1bd4f
    g_slice_free(NMEditorWepKeyBinding, binding);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
/**
Packit 5756e2
 * nm_editor_bind_wireless_security_wep_key:
Packit 5756e2
 * @s_wsec: an #NMSettingWirelessSecurity
Packit 5756e2
 * @entry: an entry widget
Packit 5756e2
 * @entry_property: the string-valued property on @entry to bind
Packit 5756e2
 * @key_selector: a pop-up widget of some sort
Packit 5756e2
 * @key_selector_property: the integer-valued property on
Packit 5756e2
 *   @key_selector to bind
Packit 5756e2
 * @flags: %GBindingFlags
Packit 5756e2
 *
Packit 5756e2
 * Binds the "wep-tx-keyidx" property on @s_wsec to
Packit 5756e2
 * @key_selector_property on @key_selector, and the corresponding
Packit 5756e2
 * "wep-keyN" property to @entry_property on @entry (and vice versa if
Packit 5756e2
 * %G_BINDING_BIDIRECTIONAL).
Packit 5756e2
 */
Packit 5756e2
void
Packit Service a1bd4f
nm_editor_bind_wireless_security_wep_key(NMSettingWirelessSecurity *s_wsec,
Packit Service a1bd4f
                                         gpointer                   entry,
Packit Service a1bd4f
                                         const char *               entry_property,
Packit Service a1bd4f
                                         gpointer                   key_selector,
Packit Service a1bd4f
                                         const char *               key_selector_property,
Packit Service a1bd4f
                                         GBindingFlags              flags)
Packit 5756e2
{
Packit Service a1bd4f
    NMEditorWepKeyBinding *binding;
Packit Service a1bd4f
    char *                 notify;
Packit Service a1bd4f
Packit Service a1bd4f
    binding                        = g_slice_new0(NMEditorWepKeyBinding);
Packit Service a1bd4f
    binding->s_wsec                = g_object_ref(s_wsec);
Packit Service a1bd4f
    binding->entry                 = entry;
Packit Service a1bd4f
    binding->entry_property        = g_strdup(entry_property);
Packit Service a1bd4f
    binding->key_selector          = key_selector;
Packit Service a1bd4f
    binding->key_selector_property = g_strdup(key_selector_property);
Packit Service a1bd4f
Packit Service a1bd4f
    g_signal_connect(s_wsec,
Packit Service a1bd4f
                     "notify::" NM_SETTING_WIRELESS_SECURITY_WEP_KEY0,
Packit Service a1bd4f
                     G_CALLBACK(wep_key_setting_changed),
Packit Service a1bd4f
                     binding);
Packit Service a1bd4f
    g_signal_connect(s_wsec,
Packit Service a1bd4f
                     "notify::" NM_SETTING_WIRELESS_SECURITY_WEP_KEY1,
Packit Service a1bd4f
                     G_CALLBACK(wep_key_setting_changed),
Packit Service a1bd4f
                     binding);
Packit Service a1bd4f
    g_signal_connect(s_wsec,
Packit Service a1bd4f
                     "notify::" NM_SETTING_WIRELESS_SECURITY_WEP_KEY2,
Packit Service a1bd4f
                     G_CALLBACK(wep_key_setting_changed),
Packit Service a1bd4f
                     binding);
Packit Service a1bd4f
    g_signal_connect(s_wsec,
Packit Service a1bd4f
                     "notify::" NM_SETTING_WIRELESS_SECURITY_WEP_KEY3,
Packit Service a1bd4f
                     G_CALLBACK(wep_key_setting_changed),
Packit Service a1bd4f
                     binding);
Packit Service a1bd4f
Packit Service a1bd4f
    g_signal_connect(s_wsec,
Packit Service a1bd4f
                     "notify::" NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX,
Packit Service a1bd4f
                     G_CALLBACK(wep_key_setting_changed),
Packit Service a1bd4f
                     binding);
Packit Service a1bd4f
Packit Service a1bd4f
    if (flags & G_BINDING_BIDIRECTIONAL) {
Packit Service a1bd4f
        notify = g_strdup_printf("notify::%s", entry_property);
Packit Service a1bd4f
        g_signal_connect(entry, notify, G_CALLBACK(wep_key_ui_changed), binding);
Packit Service a1bd4f
        g_free(notify);
Packit Service a1bd4f
Packit Service a1bd4f
        notify = g_strdup_printf("notify::%s", key_selector_property);
Packit Service a1bd4f
        g_signal_connect(key_selector, notify, G_CALLBACK(wep_key_ui_changed), binding);
Packit Service a1bd4f
        g_free(notify);
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    g_object_weak_ref(entry, wep_key_target_destroyed, binding);
Packit Service a1bd4f
    g_object_weak_ref(key_selector, wep_key_target_destroyed, binding);
Packit Service a1bd4f
Packit Service a1bd4f
    if (flags & G_BINDING_SYNC_CREATE)
Packit Service a1bd4f
        wep_key_setting_changed(NULL, NULL, binding);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
/* VLAN binding */
Packit 5756e2
Packit 5756e2
typedef struct {
Packit Service a1bd4f
    NMSettingVlan *      s_vlan;
Packit Service a1bd4f
    NMSettingConnection *s_con;
Packit 5756e2
Packit Service a1bd4f
    char *last_ifname_parent;
Packit Service a1bd4f
    int   last_ifname_id;
Packit 5756e2
Packit Service a1bd4f
    gboolean updating;
Packit 5756e2
} NMEditorVlanWidgetBinding;
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
parse_interface_name(const char *ifname, char **parent_ifname, int *id)
Packit 5756e2
{
Packit Service a1bd4f
    const char *ifname_end;
Packit Service a1bd4f
    char *      end;
Packit Service a1bd4f
Packit Service a1bd4f
    if (!ifname || !*ifname)
Packit Service a1bd4f
        return FALSE;
Packit Service a1bd4f
Packit Service a1bd4f
    if (g_str_has_prefix(ifname, "vlan")) {
Packit Service a1bd4f
        ifname_end = ifname + 4;
Packit Service a1bd4f
        *id        = strtoul(ifname_end, &end, 10);
Packit Service a1bd4f
        if (*end || end == (char *) ifname_end || *id < 0)
Packit Service a1bd4f
            return FALSE;
Packit Service a1bd4f
        *parent_ifname = NULL;
Packit Service a1bd4f
        return TRUE;
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    ifname_end = strchr(ifname, '.');
Packit Service a1bd4f
    if (ifname_end) {
Packit Service a1bd4f
        *id = strtoul(ifname_end + 1, &end, 10);
Packit Service a1bd4f
        if (*end || end == (char *) ifname_end + 1 || *id < 0)
Packit Service a1bd4f
            return FALSE;
Packit Service a1bd4f
        *parent_ifname = g_strndup(ifname, ifname_end - ifname);
Packit Service a1bd4f
        return TRUE;
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    return FALSE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
vlan_settings_changed(GObject *object, GParamSpec *pspec, gpointer user_data)
Packit 5756e2
{
Packit Service a1bd4f
    NMEditorVlanWidgetBinding *binding = user_data;
Packit Service a1bd4f
    const char *               ifname, *parent;
Packit Service a1bd4f
    char *                     ifname_parent;
Packit Service a1bd4f
    int                        ifname_id, id;
Packit Service a1bd4f
Packit Service a1bd4f
    if (binding->updating)
Packit Service a1bd4f
        return;
Packit Service a1bd4f
Packit Service a1bd4f
    ifname = nm_setting_connection_get_interface_name(binding->s_con);
Packit Service a1bd4f
    parent = nm_setting_vlan_get_parent(binding->s_vlan);
Packit Service a1bd4f
    id     = nm_setting_vlan_get_id(binding->s_vlan);
Packit Service a1bd4f
Packit Service a1bd4f
    if (!parse_interface_name(ifname, &ifname_parent, &ifname_id))
Packit Service a1bd4f
        return;
Packit Service a1bd4f
Packit Service a1bd4f
    /* If the id in INTERFACE_NAME changed, and ID is either unset, or was previously
Packit Service a1bd4f
     * in sync with INTERFACE_NAME, then update ID.
Packit Service a1bd4f
     */
Packit Service a1bd4f
    if (id != ifname_id && (id == binding->last_ifname_id || id == 0)) {
Packit Service a1bd4f
        binding->updating = TRUE;
Packit Service a1bd4f
        g_object_set(G_OBJECT(binding->s_vlan), NM_SETTING_VLAN_ID, ifname_id, NULL);
Packit Service a1bd4f
        binding->updating = FALSE;
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    /* If the PARENT in INTERFACE_NAME changed, and PARENT is either unset, or was
Packit Service a1bd4f
     * previously in sync with INTERFACE_NAME, then update PARENT.
Packit Service a1bd4f
     */
Packit Service a1bd4f
    if (g_strcmp0(parent, ifname_parent) != 0
Packit Service a1bd4f
        && (g_strcmp0(parent, binding->last_ifname_parent) == 0 || !parent || !*parent)) {
Packit Service a1bd4f
        binding->updating = TRUE;
Packit Service a1bd4f
        g_object_set(G_OBJECT(binding->s_vlan), NM_SETTING_VLAN_PARENT, ifname_parent, NULL);
Packit Service a1bd4f
        binding->updating = FALSE;
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    g_free(binding->last_ifname_parent);
Packit Service a1bd4f
    binding->last_ifname_parent = ifname_parent;
Packit Service a1bd4f
    binding->last_ifname_id     = ifname_id;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
vlan_target_destroyed(gpointer user_data, GObject *ex_target)
Packit 5756e2
{
Packit Service a1bd4f
    NMEditorVlanWidgetBinding *binding = user_data;
Packit 5756e2
Packit Service a1bd4f
    g_free(binding->last_ifname_parent);
Packit Service a1bd4f
    g_slice_free(NMEditorVlanWidgetBinding, binding);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
/**
Packit 5756e2
 * nm_editor_bind_vlan_name:
Packit 5756e2
 * @s_vlan: an #NMSettingVlan
Packit 5756e2
 *
Packit 5756e2
 * Binds together several properties on @s_vlan, so that if the
Packit 5756e2
 * %NM_SETTING_VLAN_INTERFACE_NAME matches %NM_SETTING_VLAN_PARENT
Packit 5756e2
 * and %NM_SETTING_VLAN_ID in the obvious way, then changes to
Packit 5756e2
 * %NM_SETTING_VLAN_INTERFACE_NAME will propagate to the other
Packit 5756e2
 * two properties automatically.
Packit 5756e2
 */
Packit 5756e2
void
Packit Service a1bd4f
nm_editor_bind_vlan_name(NMSettingVlan *s_vlan, NMSettingConnection *s_con)
Packit 5756e2
{
Packit Service a1bd4f
    NMEditorVlanWidgetBinding *binding;
Packit Service a1bd4f
    const char *               ifname;
Packit 5756e2
Packit Service a1bd4f
    binding         = g_slice_new0(NMEditorVlanWidgetBinding);
Packit Service a1bd4f
    binding->s_vlan = s_vlan;
Packit Service a1bd4f
    binding->s_con  = s_con;
Packit 5756e2
Packit Service a1bd4f
    g_signal_connect(s_con,
Packit Service a1bd4f
                     "notify::" NM_SETTING_CONNECTION_INTERFACE_NAME,
Packit Service a1bd4f
                     G_CALLBACK(vlan_settings_changed),
Packit Service a1bd4f
                     binding);
Packit 5756e2
Packit Service a1bd4f
    g_object_weak_ref(G_OBJECT(s_vlan), vlan_target_destroyed, binding);
Packit 5756e2
Packit Service a1bd4f
    ifname = nm_setting_connection_get_interface_name(s_con);
Packit Service a1bd4f
    if (!parse_interface_name(ifname, &binding->last_ifname_parent, &binding->last_ifname_id)) {
Packit Service a1bd4f
        binding->last_ifname_parent = NULL;
Packit Service a1bd4f
        binding->last_ifname_id     = 0;
Packit Service a1bd4f
    }
Packit 5756e2
}