Blame src/core/settings/plugins/ifupdown/nms-ifupdown-parser.c

Packit Service 5ffa24
/* SPDX-License-Identifier: GPL-2.0-or-later */
Packit Service 5ffa24
/*
Packit Service 5ffa24
 * Alexander Sack <asac@ubuntu.com>
Packit Service 5ffa24
 * Copyright (C) 2008 Canonical Ltd.
Packit Service 5ffa24
 */
Packit Service 5ffa24
Packit Service 2bceb2
#include "src/core/nm-default-daemon.h"
Packit Service 5ffa24
Packit Service 5ffa24
#include "nms-ifupdown-parser.h"
Packit Service 5ffa24
Packit Service 5ffa24
#include <arpa/inet.h>
Packit Service 5ffa24
#include <stdlib.h>
Packit Service 5ffa24
#include <ctype.h>
Packit Service 5ffa24
Packit Service dff8e4
#include "libnm-core-intern/nm-core-internal.h"
Packit Service 5ffa24
#include "settings/nm-settings-plugin.h"
Packit Service 5ffa24
Packit Service 5ffa24
#include "nms-ifupdown-plugin.h"
Packit Service 5ffa24
#include "nms-ifupdown-parser.h"
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
#define _NMLOG_PREFIX_NAME "ifupdown"
Packit Service 5ffa24
#define _NMLOG_DOMAIN      LOGD_SETTINGS
Packit Service 5ffa24
#define _NMLOG(level, ...)                          \
Packit Service 5ffa24
    nm_log((level),                                 \
Packit Service 5ffa24
           _NMLOG_DOMAIN,                           \
Packit Service 5ffa24
           NULL,                                    \
Packit Service 5ffa24
           NULL,                                    \
Packit Service 5ffa24
           "%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
Packit Service 5ffa24
           _NMLOG_PREFIX_NAME ": " _NM_UTILS_MACRO_REST(__VA_ARGS__))
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
#define _str_has_prefix(val, prefix, require_suffix)                   \
Packit Service 5ffa24
    ({                                                                 \
Packit Service 5ffa24
        const char *_val = (val);                                      \
Packit Service 5ffa24
                                                                       \
Packit Service 5ffa24
        (strncmp(_val, "" prefix "", NM_STRLEN(prefix)) == 0)          \
Packit Service 5ffa24
            && (!(require_suffix) || _val[NM_STRLEN(prefix)] != '\0'); \
Packit Service 5ffa24
    })
Packit Service 5ffa24
Packit Service 5ffa24
static const char *
Packit Service 5ffa24
_ifupdownplugin_guess_connection_type(if_block *block)
Packit Service 5ffa24
{
Packit Service 5ffa24
    const char *ret_type = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    if (nm_streq0(ifparser_getkey(block, "inet"), "ppp"))
Packit Service 5ffa24
        ret_type = NM_SETTING_PPP_SETTING_NAME;
Packit Service 5ffa24
    else {
Packit Service 5ffa24
        if_data *ifb;
Packit Service 5ffa24
Packit Service 5ffa24
        c_list_for_each_entry (ifb, &block->data_lst_head, data_lst) {
Packit Service 5ffa24
            if (_str_has_prefix(ifb->key, "wireless-", FALSE)
Packit Service 5ffa24
                || _str_has_prefix(ifb->key, "wpa-", FALSE)) {
Packit Service 5ffa24
                ret_type = NM_SETTING_WIRELESS_SETTING_NAME;
Packit Service 5ffa24
                break;
Packit Service 5ffa24
            }
Packit Service 5ffa24
        }
Packit Service 5ffa24
        if (!ret_type)
Packit Service 5ffa24
            ret_type = NM_SETTING_WIRED_SETTING_NAME;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    _LOGI("guessed connection type (%s) = %s", block->name, ret_type);
Packit Service 5ffa24
    return ret_type;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
struct _Mapping {
Packit Service 5ffa24
    const char *   domain;
Packit Service 5ffa24
    const gpointer target;
Packit Service 5ffa24
};
Packit Service 5ffa24
Packit Service 5ffa24
static gpointer
Packit Service 5ffa24
map_by_mapping(struct _Mapping *mapping, const char *key)
Packit Service 5ffa24
{
Packit Service 5ffa24
    struct _Mapping *curr = mapping;
Packit Service 5ffa24
Packit Service 5ffa24
    while (curr->domain) {
Packit Service 5ffa24
        if (nm_streq(curr->domain, key))
Packit Service 5ffa24
            return curr->target;
Packit Service 5ffa24
        curr++;
Packit Service 5ffa24
    }
Packit Service 5ffa24
    return NULL;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
update_wireless_setting_from_if_block(NMConnection *connection, if_block *block)
Packit Service 5ffa24
{
Packit Service 5ffa24
    if_data *       curr;
Packit Service 5ffa24
    const char *    value     = ifparser_getkey(block, "inet");
Packit Service 5ffa24
    struct _Mapping mapping[] = {{"ssid", "ssid"},
Packit Service 5ffa24
                                 {"essid", "ssid"},
Packit Service 5ffa24
                                 {"mode", "mode"},
Packit Service 5ffa24
                                 {NULL, NULL}};
Packit Service 5ffa24
Packit Service 5ffa24
    NMSettingWireless *wireless_setting = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    if (nm_streq0(value, "ppp"))
Packit Service 5ffa24
        return;
Packit Service 5ffa24
Packit Service 5ffa24
    _LOGI("update wireless settings (%s).", block->name);
Packit Service 5ffa24
    wireless_setting = NM_SETTING_WIRELESS(nm_setting_wireless_new());
Packit Service 5ffa24
Packit Service 5ffa24
    c_list_for_each_entry (curr, &block->data_lst_head, data_lst) {
Packit Service 5ffa24
        if (_str_has_prefix(curr->key, "wireless-", TRUE)) {
Packit Service 5ffa24
            const char *newkey = map_by_mapping(mapping, curr->key + NM_STRLEN("wireless-"));
Packit Service 5ffa24
Packit Service 5ffa24
            _LOGI("wireless setting key: %s='%s'", newkey, curr->data);
Packit Service 5ffa24
            if (nm_streq0(newkey, "ssid")) {
Packit Service 5ffa24
                GBytes *ssid;
Packit Service 5ffa24
                int     len = strlen(curr->data);
Packit Service 5ffa24
Packit Service 5ffa24
                ssid = g_bytes_new(curr->data, len);
Packit Service 5ffa24
                g_object_set(wireless_setting, NM_SETTING_WIRELESS_SSID, ssid, NULL);
Packit Service 5ffa24
                g_bytes_unref(ssid);
Packit Service 5ffa24
                _LOGI("setting wireless ssid = %d", len);
Packit Service 5ffa24
            } else if (nm_streq0(newkey, "mode")) {
Packit Service 5ffa24
                if (!g_ascii_strcasecmp(curr->data, "Managed")
Packit Service 5ffa24
                    || !g_ascii_strcasecmp(curr->data, "Auto"))
Packit Service 5ffa24
                    g_object_set(wireless_setting,
Packit Service 5ffa24
                                 NM_SETTING_WIRELESS_MODE,
Packit Service 5ffa24
                                 NM_SETTING_WIRELESS_MODE_INFRA,
Packit Service 5ffa24
                                 NULL);
Packit Service 5ffa24
                else if (!g_ascii_strcasecmp(curr->data, "Ad-Hoc"))
Packit Service 5ffa24
                    g_object_set(wireless_setting,
Packit Service 5ffa24
                                 NM_SETTING_WIRELESS_MODE,
Packit Service 5ffa24
                                 NM_SETTING_WIRELESS_MODE_ADHOC,
Packit Service 5ffa24
                                 NULL);
Packit Service 5ffa24
                else if (!g_ascii_strcasecmp(curr->data, "Master"))
Packit Service 5ffa24
                    g_object_set(wireless_setting,
Packit Service 5ffa24
                                 NM_SETTING_WIRELESS_MODE,
Packit Service 5ffa24
                                 NM_SETTING_WIRELESS_MODE_AP,
Packit Service 5ffa24
                                 NULL);
Packit Service 5ffa24
                else
Packit Service 5ffa24
                    _LOGW("Invalid mode '%s' (not 'Ad-Hoc', 'Ap', 'Managed', or 'Auto')",
Packit Service 5ffa24
                          curr->data);
Packit Service 5ffa24
            } else {
Packit Service 5ffa24
                g_object_set(wireless_setting, newkey, curr->data, NULL);
Packit Service 5ffa24
            }
Packit Service 5ffa24
        } else if (_str_has_prefix(curr->key, "wpa-", TRUE)) {
Packit Service 5ffa24
            const char *newkey = map_by_mapping(mapping, curr->key + NM_STRLEN("wpa-"));
Packit Service 5ffa24
Packit Service 5ffa24
            if (nm_streq0(newkey, "ssid")) {
Packit Service 5ffa24
                GBytes *ssid;
Packit Service 5ffa24
                int     len = strlen(curr->data);
Packit Service 5ffa24
Packit Service 5ffa24
                ssid = g_bytes_new(curr->data, len);
Packit Service 5ffa24
                g_object_set(wireless_setting, NM_SETTING_WIRELESS_SSID, ssid, NULL);
Packit Service 5ffa24
                g_bytes_unref(ssid);
Packit Service 5ffa24
                _LOGI("setting wpa ssid = %d", len);
Packit Service 5ffa24
            } else if (newkey) {
Packit Service 5ffa24
                g_object_set(wireless_setting, newkey, curr->data, NULL);
Packit Service 5ffa24
                _LOGI("setting wpa newkey(%s)=data(%s)", newkey, curr->data);
Packit Service 5ffa24
            }
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
    nm_connection_add_setting(connection, (NMSetting *) wireless_setting);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
typedef char *(*IfupdownStrDupeFunc)(gconstpointer value, gpointer data);
Packit Service 5ffa24
typedef gpointer (*IfupdownStrToTypeFunc)(const char *value);
Packit Service 5ffa24
Packit Service 5ffa24
static char *
Packit Service 5ffa24
normalize_dupe_wireless_key(gpointer value, gpointer data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    char *valuec     = value;
Packit Service 5ffa24
    char *endc       = valuec + strlen(valuec);
Packit Service 5ffa24
    char *delim      = valuec;
Packit Service 5ffa24
    char *next       = delim;
Packit Service 5ffa24
    char *result     = malloc(strlen(valuec) + 1);
Packit Service 5ffa24
    char *result_cur = result;
Packit Service 5ffa24
Packit Service 5ffa24
    while (*delim && (next = strchr(delim, '-')) != NULL) {
Packit Service 5ffa24
        if (next == delim) {
Packit Service 5ffa24
            delim++;
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
        }
Packit Service 5ffa24
        strncpy(result_cur, delim, next - delim);
Packit Service 5ffa24
        result_cur += next - delim;
Packit Service 5ffa24
        delim = next + 1;
Packit Service 5ffa24
    }
Packit Service 5ffa24
    if (*delim && strlen(valuec) > GPOINTER_TO_UINT(delim - valuec)) {
Packit Service 5ffa24
        strncpy(result_cur, delim, endc - delim);
Packit Service 5ffa24
        result_cur += endc - delim;
Packit Service 5ffa24
    }
Packit Service 5ffa24
    *result_cur = '\0';
Packit Service 5ffa24
    return result;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static char *
Packit Service 5ffa24
normalize_dupe(gpointer value, gpointer data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    return g_strdup(value);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static char *
Packit Service 5ffa24
normalize_tolower(gpointer value, gpointer data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    return g_ascii_strdown(value, -1);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static char *
Packit Service 5ffa24
normalize_psk(gpointer value, gpointer data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    if (strlen(value) >= 8 && strlen(value) <= 64)
Packit Service 5ffa24
        return g_strdup(value);
Packit Service 5ffa24
    return NULL;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static gpointer
Packit Service 5ffa24
string_to_gpointerint(const char *data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    int result = (int) strtol(data, NULL, 10);
Packit Service 5ffa24
    return GINT_TO_POINTER(result);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static gpointer
Packit Service 5ffa24
string_to_glist_of_strings(const char *data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    GSList *ret    = NULL;
Packit Service 5ffa24
    char *  string = (char *) data;
Packit Service 5ffa24
    while (string) {
Packit Service 5ffa24
        char *next = NULL;
Packit Service 5ffa24
        if ((next = strchr(string, ' ')) || (next = strchr(string, '\t'))
Packit Service 5ffa24
            || (next = strchr(string, '\0'))) {
Packit Service 5ffa24
            char *part = g_strndup(string, (next - string));
Packit Service 5ffa24
            ret        = g_slist_append(ret, part);
Packit Service 5ffa24
            if (*next)
Packit Service 5ffa24
                string = next + 1;
Packit Service 5ffa24
            else
Packit Service 5ffa24
                string = NULL;
Packit Service 5ffa24
        } else {
Packit Service 5ffa24
            string = NULL;
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
    return ret;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
slist_free_all(gpointer slist)
Packit Service 5ffa24
{
Packit Service 5ffa24
    g_slist_free_full((GSList *) slist, g_free);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
update_wireless_security_setting_from_if_block(NMConnection *connection, if_block *block)
Packit Service 5ffa24
{
Packit Service 5ffa24
    if_data *       curr;
Packit Service 5ffa24
    const char *    value     = ifparser_getkey(block, "inet");
Packit Service 5ffa24
    struct _Mapping mapping[] = {{"psk", "psk"},
Packit Service 5ffa24
                                 {"identity", "leap-username"},
Packit Service 5ffa24
                                 {"password", "leap-password"},
Packit Service 5ffa24
                                 {"key", "wep-key0"},
Packit Service 5ffa24
                                 {"key-mgmt", "key-mgmt"},
Packit Service 5ffa24
                                 {"group", "group"},
Packit Service 5ffa24
                                 {"pairwise", "pairwise"},
Packit Service 5ffa24
                                 {"proto", "proto"},
Packit Service 5ffa24
                                 {"pin", "pin"},
Packit Service 5ffa24
                                 {"wep-key0", "wep-key0"},
Packit Service 5ffa24
                                 {"wep-key1", "wep-key1"},
Packit Service 5ffa24
                                 {"wep-key2", "wep-key2"},
Packit Service 5ffa24
                                 {"wep-key3", "wep-key3"},
Packit Service 5ffa24
                                 {"wep-tx-keyidx", "wep-tx-keyidx"},
Packit Service 5ffa24
                                 {NULL, NULL}};
Packit Service 5ffa24
Packit Service 5ffa24
    struct _Mapping dupe_mapping[] = {{"psk", normalize_psk},
Packit Service 5ffa24
                                      {"identity", normalize_dupe},
Packit Service 5ffa24
                                      {"password", normalize_dupe},
Packit Service 5ffa24
                                      {"key", normalize_dupe_wireless_key},
Packit Service 5ffa24
                                      {"key-mgmt", normalize_tolower},
Packit Service 5ffa24
                                      {"group", normalize_tolower},
Packit Service 5ffa24
                                      {"pairwise", normalize_tolower},
Packit Service 5ffa24
                                      {"proto", normalize_tolower},
Packit Service 5ffa24
                                      {"pin", normalize_dupe},
Packit Service 5ffa24
                                      {"wep-key0", normalize_dupe_wireless_key},
Packit Service 5ffa24
                                      {"wep-key1", normalize_dupe_wireless_key},
Packit Service 5ffa24
                                      {"wep-key2", normalize_dupe_wireless_key},
Packit Service 5ffa24
                                      {"wep-key3", normalize_dupe_wireless_key},
Packit Service 5ffa24
                                      {"wep-tx-keyidx", normalize_dupe},
Packit Service 5ffa24
                                      {NULL, NULL}};
Packit Service 5ffa24
Packit Service 5ffa24
    struct _Mapping type_mapping[] = {{"group", string_to_glist_of_strings},
Packit Service 5ffa24
                                      {"pairwise", string_to_glist_of_strings},
Packit Service 5ffa24
                                      {"proto", string_to_glist_of_strings},
Packit Service 5ffa24
                                      {"wep-tx-keyidx", string_to_gpointerint},
Packit Service 5ffa24
                                      {NULL, NULL}};
Packit Service 5ffa24
Packit Service 5ffa24
    struct _Mapping free_type_mapping[] = {{"group", slist_free_all},
Packit Service 5ffa24
                                           {"pairwise", slist_free_all},
Packit Service 5ffa24
                                           {"proto", slist_free_all},
Packit Service 5ffa24
                                           {NULL, NULL}};
Packit Service 5ffa24
Packit Service 5ffa24
    NMSettingWirelessSecurity *wireless_security_setting;
Packit Service 5ffa24
    NMSettingWireless *        s_wireless;
Packit Service 5ffa24
    gboolean                   security = FALSE;
Packit Service 5ffa24
Packit Service 5ffa24
    if (nm_streq0(value, "ppp"))
Packit Service 5ffa24
        return;
Packit Service 5ffa24
Packit Service 5ffa24
    s_wireless = nm_connection_get_setting_wireless(connection);
Packit Service 5ffa24
    g_return_if_fail(s_wireless);
Packit Service 5ffa24
Packit Service 5ffa24
    _LOGI("update wireless security settings (%s).", block->name);
Packit Service 5ffa24
    wireless_security_setting = NM_SETTING_WIRELESS_SECURITY(nm_setting_wireless_security_new());
Packit Service 5ffa24
Packit Service 5ffa24
    c_list_for_each_entry (curr, &block->data_lst_head, data_lst) {
Packit Service 5ffa24
        if (_str_has_prefix(curr->key, "wireless-", TRUE)) {
Packit Service 5ffa24
            const char *          key                  = curr->key + NM_STRLEN("wireless-");
Packit Service 5ffa24
            char *                property_value       = NULL;
Packit Service 5ffa24
            gpointer              typed_property_value = NULL;
Packit Service 5ffa24
            const char *          newkey               = map_by_mapping(mapping, key);
Packit Service 5ffa24
            IfupdownStrDupeFunc   dupe_func            = map_by_mapping(dupe_mapping, key);
Packit Service 5ffa24
            IfupdownStrToTypeFunc type_map_func        = map_by_mapping(type_mapping, key);
Packit Service 5ffa24
            GFreeFunc             free_func            = map_by_mapping(free_type_mapping, key);
Packit Service 5ffa24
            if (!newkey || !dupe_func)
Packit Service 5ffa24
                goto next;
Packit Service 5ffa24
Packit Service 5ffa24
            property_value = (*dupe_func)(curr->data, connection);
Packit Service 5ffa24
            _LOGI("setting wireless security key: %s=%s", newkey, property_value);
Packit Service 5ffa24
Packit Service 5ffa24
            if (type_map_func) {
Packit Service 5ffa24
                errno                = 0;
Packit Service 5ffa24
                typed_property_value = (*type_map_func)(property_value);
Packit Service 5ffa24
                if (errno)
Packit Service 5ffa24
                    goto wireless_next;
Packit Service 5ffa24
            }
Packit Service 5ffa24
Packit Service 5ffa24
            g_object_set(wireless_security_setting,
Packit Service 5ffa24
                         newkey,
Packit Service 5ffa24
                         typed_property_value ?: property_value,
Packit Service 5ffa24
                         NULL);
Packit Service 5ffa24
            security = TRUE;
Packit Service 5ffa24
Packit Service 5ffa24
wireless_next:
Packit Service 5ffa24
            g_free(property_value);
Packit Service 5ffa24
            if (typed_property_value && free_func)
Packit Service 5ffa24
                (*free_func)(typed_property_value);
Packit Service 5ffa24
Packit Service 5ffa24
        } else if (_str_has_prefix(curr->key, "wpa-", TRUE)) {
Packit Service 5ffa24
            const char *          key                  = curr->key + NM_STRLEN("wpa-");
Packit Service 5ffa24
            char *                property_value       = NULL;
Packit Service 5ffa24
            gpointer              typed_property_value = NULL;
Packit Service 5ffa24
            const char *          newkey               = map_by_mapping(mapping, key);
Packit Service 5ffa24
            IfupdownStrDupeFunc   dupe_func            = map_by_mapping(dupe_mapping, key);
Packit Service 5ffa24
            IfupdownStrToTypeFunc type_map_func        = map_by_mapping(type_mapping, key);
Packit Service 5ffa24
            GFreeFunc             free_func            = map_by_mapping(free_type_mapping, key);
Packit Service 5ffa24
            if (!newkey || !dupe_func)
Packit Service 5ffa24
                goto next;
Packit Service 5ffa24
Packit Service 5ffa24
            property_value = (*dupe_func)(curr->data, connection);
Packit Service 5ffa24
            _LOGI("setting wpa security key: %s=%s",
Packit Service 5ffa24
                  newkey,
Packit Service 5ffa24
                  NM_IN_STRSET(newkey,
Packit Service 5ffa24
                               "key",
Packit Service 5ffa24
                               "leap-password",
Packit Service 5ffa24
                               "pin",
Packit Service 5ffa24
                               "psk",
Packit Service 5ffa24
                               "wep-key0",
Packit Service 5ffa24
                               "wep-key1",
Packit Service 5ffa24
                               "wep-key2",
Packit Service 5ffa24
                               "wep-key3")
Packit Service 5ffa24
                      ? "<omitted>"
Packit Service 5ffa24
                      : property_value);
Packit Service 5ffa24
Packit Service 5ffa24
            if (type_map_func) {
Packit Service 5ffa24
                errno                = 0;
Packit Service 5ffa24
                typed_property_value = (*type_map_func)(property_value);
Packit Service 5ffa24
                if (errno)
Packit Service 5ffa24
                    goto wpa_next;
Packit Service 5ffa24
            }
Packit Service 5ffa24
Packit Service 5ffa24
            g_object_set(wireless_security_setting,
Packit Service 5ffa24
                         newkey,
Packit Service 5ffa24
                         typed_property_value ?: property_value,
Packit Service 5ffa24
                         NULL);
Packit Service 5ffa24
            security = TRUE;
Packit Service 5ffa24
Packit Service 5ffa24
wpa_next:
Packit Service 5ffa24
            g_free(property_value);
Packit Service 5ffa24
            if (free_func && typed_property_value)
Packit Service 5ffa24
                (*free_func)(typed_property_value);
Packit Service 5ffa24
        }
Packit Service 5ffa24
next:;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (security)
Packit Service 5ffa24
        nm_connection_add_setting(connection, NM_SETTING(wireless_security_setting));
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
update_wired_setting_from_if_block(NMConnection *connection, if_block *block)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMSettingWired *s_wired = NULL;
Packit Service 5ffa24
    s_wired                 = NM_SETTING_WIRED(nm_setting_wired_new());
Packit Service 5ffa24
    nm_connection_add_setting(connection, NM_SETTING(s_wired));
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
ifupdown_ip4_add_dns(NMSettingIPConfig *s_ip4, const char *dns)
Packit Service 5ffa24
{
Packit Service 5ffa24
    gs_free const char **list = NULL;
Packit Service 5ffa24
    const char **        iter;
Packit Service 5ffa24
    guint32              addr;
Packit Service 5ffa24
Packit Service 5ffa24
    if (dns == NULL)
Packit Service 5ffa24
        return;
Packit Service 5ffa24
Packit Service 5ffa24
    list = nm_utils_strsplit_set(dns, " \t");
Packit Service 5ffa24
    for (iter = list; iter && *iter; iter++) {
Packit Service 5ffa24
        if (!inet_pton(AF_INET, *iter, &addr)) {
Packit Service 5ffa24
            _LOGW("    ignoring invalid nameserver '%s'", *iter);
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        if (!nm_setting_ip_config_add_dns(s_ip4, *iter))
Packit Service 5ffa24
            _LOGW("    duplicate DNS domain '%s'", *iter);
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static gboolean
Packit Service 5ffa24
update_ip4_setting_from_if_block(NMConnection *connection, if_block *block, GError **error)
Packit Service 5ffa24
{
Packit Service 5ffa24
    gs_unref_object NMSettingIPConfig *s_ip4 = NM_SETTING_IP_CONFIG(nm_setting_ip4_config_new());
Packit Service 5ffa24
    const char *                       type  = ifparser_getkey(block, "inet");
Packit Service 5ffa24
Packit Service 5ffa24
    if (!nm_streq0(type, "static")) {
Packit Service 5ffa24
        g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
Packit Service 5ffa24
    } else {
Packit Service 5ffa24
        guint32      tmp_mask;
Packit Service 5ffa24
        NMIPAddress *addr;
Packit Service 5ffa24
        const char * address_v;
Packit Service 5ffa24
        const char * netmask_v;
Packit Service 5ffa24
        const char * gateway_v;
Packit Service 5ffa24
        const char * nameserver_v;
Packit Service 5ffa24
        const char * nameservers_v;
Packit Service 5ffa24
        const char * search_v;
Packit Service 5ffa24
        guint32      netmask_int = 32;
Packit Service 5ffa24
Packit Service 5ffa24
        /* Address */
Packit Service 5ffa24
        address_v = ifparser_getkey(block, "address");
Packit Service 5ffa24
        if (!address_v) {
Packit Service 5ffa24
            g_set_error(error,
Packit Service 5ffa24
                        NM_SETTINGS_ERROR,
Packit Service 5ffa24
                        NM_SETTINGS_ERROR_INVALID_CONNECTION,
Packit Service 5ffa24
                        "Missing IPv4 address");
Packit Service 5ffa24
            return FALSE;
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        /* mask/prefix */
Packit Service 5ffa24
        netmask_v = ifparser_getkey(block, "netmask");
Packit Service 5ffa24
        if (netmask_v) {
Packit Service 5ffa24
            if (strlen(netmask_v) < 7) {
Packit Service 5ffa24
                netmask_int = atoi(netmask_v);
Packit Service 5ffa24
            } else if (!inet_pton(AF_INET, netmask_v, &tmp_mask)) {
Packit Service 5ffa24
                g_set_error(error,
Packit Service 5ffa24
                            NM_SETTINGS_ERROR,
Packit Service 5ffa24
                            NM_SETTINGS_ERROR_INVALID_CONNECTION,
Packit Service 5ffa24
                            "Invalid IPv4 netmask '%s'",
Packit Service 5ffa24
                            netmask_v);
Packit Service 5ffa24
                return FALSE;
Packit Service 5ffa24
            } else {
Packit Service 5ffa24
                netmask_int = nm_utils_ip4_netmask_to_prefix(tmp_mask);
Packit Service 5ffa24
            }
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        /* Add the new address to the setting */
Packit Service 5ffa24
        addr = nm_ip_address_new(AF_INET, address_v, netmask_int, error);
Packit Service 5ffa24
        if (!addr)
Packit Service 5ffa24
            return FALSE;
Packit Service 5ffa24
Packit Service 5ffa24
        if (nm_setting_ip_config_add_address(s_ip4, addr)) {
Packit Service 5ffa24
            _LOGI("addresses count: %d", nm_setting_ip_config_get_num_addresses(s_ip4));
Packit Service 5ffa24
        } else {
Packit Service 5ffa24
            _LOGI("ignoring duplicate IP4 address");
Packit Service 5ffa24
        }
Packit Service 5ffa24
        nm_ip_address_unref(addr);
Packit Service 5ffa24
Packit Service 5ffa24
        /* gateway */
Packit Service 5ffa24
        gateway_v = ifparser_getkey(block, "gateway");
Packit Service 5ffa24
        if (gateway_v) {
Packit Service 5ffa24
            if (!nm_utils_ipaddr_is_valid(AF_INET, gateway_v)) {
Packit Service 5ffa24
                g_set_error(error,
Packit Service 5ffa24
                            NM_SETTINGS_ERROR,
Packit Service 5ffa24
                            NM_SETTINGS_ERROR_INVALID_CONNECTION,
Packit Service 5ffa24
                            "Invalid IPv4 gateway '%s'",
Packit Service 5ffa24
                            gateway_v);
Packit Service 5ffa24
                return FALSE;
Packit Service 5ffa24
            }
Packit Service 5ffa24
            if (!nm_setting_ip_config_get_gateway(s_ip4))
Packit Service 5ffa24
                g_object_set(s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway_v, NULL);
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        nameserver_v = ifparser_getkey(block, "dns-nameserver");
Packit Service 5ffa24
        ifupdown_ip4_add_dns(s_ip4, nameserver_v);
Packit Service 5ffa24
Packit Service 5ffa24
        nameservers_v = ifparser_getkey(block, "dns-nameservers");
Packit Service 5ffa24
        ifupdown_ip4_add_dns(s_ip4, nameservers_v);
Packit Service 5ffa24
Packit Service 5ffa24
        if (!nm_setting_ip_config_get_num_dns(s_ip4))
Packit Service 5ffa24
            _LOGI("No dns-nameserver configured in /etc/network/interfaces");
Packit Service 5ffa24
Packit Service 5ffa24
        /* DNS searches */
Packit Service 5ffa24
        search_v = ifparser_getkey(block, "dns-search");
Packit Service 5ffa24
        if (search_v) {
Packit Service 5ffa24
            gs_free const char **list = NULL;
Packit Service 5ffa24
            const char **        iter;
Packit Service 5ffa24
Packit Service 5ffa24
            list = nm_utils_strsplit_set(search_v, " \t");
Packit Service 5ffa24
            for (iter = list; iter && *iter; iter++) {
Packit Service 5ffa24
                if (!nm_setting_ip_config_add_dns_search(s_ip4, *iter))
Packit Service 5ffa24
                    _LOGW("    duplicate DNS domain '%s'", *iter);
Packit Service 5ffa24
            }
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    nm_connection_add_setting(connection, NM_SETTING(g_steal_pointer(&s_ip4)));
Packit Service 5ffa24
    return TRUE;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
ifupdown_ip6_add_dns(NMSettingIPConfig *s_ip6, const char *dns)
Packit Service 5ffa24
{
Packit Service 5ffa24
    gs_free const char **list = NULL;
Packit Service 5ffa24
    const char **        iter;
Packit Service 5ffa24
    struct in6_addr      addr;
Packit Service 5ffa24
Packit Service 5ffa24
    if (dns == NULL)
Packit Service 5ffa24
        return;
Packit Service 5ffa24
Packit Service 5ffa24
    list = nm_utils_strsplit_set(dns, " \t");
Packit Service 5ffa24
    for (iter = list; iter && *iter; iter++) {
Packit Service 5ffa24
        if (!inet_pton(AF_INET6, *iter, &addr)) {
Packit Service 5ffa24
            _LOGW("    ignoring invalid nameserver '%s'", *iter);
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        if (!nm_setting_ip_config_add_dns(s_ip6, *iter))
Packit Service 5ffa24
            _LOGW("    duplicate DNS domain '%s'", *iter);
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static gboolean
Packit Service 5ffa24
update_ip6_setting_from_if_block(NMConnection *connection, if_block *block, GError **error)
Packit Service 5ffa24
{
Packit Service 5ffa24
    gs_unref_object NMSettingIPConfig *s_ip6 = NM_SETTING_IP_CONFIG(nm_setting_ip6_config_new());
Packit Service 5ffa24
    const char *                       type  = ifparser_getkey(block, "inet6");
Packit Service 5ffa24
Packit Service 5ffa24
    if (!NM_IN_STRSET(type, "static", "v4tunnel")) {
Packit Service 5ffa24
        g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL);
Packit Service 5ffa24
    } else {
Packit Service 5ffa24
        NMIPAddress *addr;
Packit Service 5ffa24
        const char * address_v;
Packit Service 5ffa24
        const char * prefix_v;
Packit Service 5ffa24
        const char * gateway_v;
Packit Service 5ffa24
        const char * nameserver_v;
Packit Service 5ffa24
        const char * nameservers_v;
Packit Service 5ffa24
        const char * search_v;
Packit Service 5ffa24
        guint        prefix_int;
Packit Service 5ffa24
Packit Service 5ffa24
        address_v = ifparser_getkey(block, "address");
Packit Service 5ffa24
        if (!address_v) {
Packit Service 5ffa24
            g_set_error(error,
Packit Service 5ffa24
                        NM_SETTINGS_ERROR,
Packit Service 5ffa24
                        NM_SETTINGS_ERROR_INVALID_CONNECTION,
Packit Service 5ffa24
                        "Missing IPv6 address");
Packit Service 5ffa24
            return FALSE;
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        prefix_v = ifparser_getkey(block, "netmask");
Packit Service 5ffa24
        if (prefix_v)
Packit Service 5ffa24
            prefix_int = _nm_utils_ascii_str_to_int64(prefix_v, 10, 0, 128, G_MAXINT);
Packit Service 5ffa24
        else
Packit Service 5ffa24
            prefix_int = 128;
Packit Service 5ffa24
Packit Service 5ffa24
        addr = nm_ip_address_new(AF_INET6, address_v, prefix_int, error);
Packit Service 5ffa24
        if (!addr)
Packit Service 5ffa24
            return FALSE;
Packit Service 5ffa24
Packit Service 5ffa24
        if (nm_setting_ip_config_add_address(s_ip6, addr)) {
Packit Service 5ffa24
            _LOGI("addresses count: %d", nm_setting_ip_config_get_num_addresses(s_ip6));
Packit Service 5ffa24
        } else {
Packit Service 5ffa24
            _LOGI("ignoring duplicate IP6 address");
Packit Service 5ffa24
        }
Packit Service 5ffa24
        nm_ip_address_unref(addr);
Packit Service 5ffa24
Packit Service 5ffa24
        gateway_v = ifparser_getkey(block, "gateway");
Packit Service 5ffa24
        if (gateway_v) {
Packit Service 5ffa24
            if (!nm_utils_ipaddr_is_valid(AF_INET6, gateway_v)) {
Packit Service 5ffa24
                g_set_error(error,
Packit Service 5ffa24
                            NM_SETTINGS_ERROR,
Packit Service 5ffa24
                            NM_SETTINGS_ERROR_INVALID_CONNECTION,
Packit Service 5ffa24
                            "Invalid IPv6 gateway '%s'",
Packit Service 5ffa24
                            gateway_v);
Packit Service 5ffa24
                return FALSE;
Packit Service 5ffa24
            }
Packit Service 5ffa24
            if (!nm_setting_ip_config_get_gateway(s_ip6))
Packit Service 5ffa24
                g_object_set(s_ip6, NM_SETTING_IP_CONFIG_GATEWAY, gateway_v, NULL);
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        nameserver_v = ifparser_getkey(block, "dns-nameserver");
Packit Service 5ffa24
        ifupdown_ip6_add_dns(s_ip6, nameserver_v);
Packit Service 5ffa24
Packit Service 5ffa24
        nameservers_v = ifparser_getkey(block, "dns-nameservers");
Packit Service 5ffa24
        ifupdown_ip6_add_dns(s_ip6, nameservers_v);
Packit Service 5ffa24
Packit Service 5ffa24
        if (!nm_setting_ip_config_get_num_dns(s_ip6))
Packit Service 5ffa24
            _LOGI("No dns-nameserver configured in /etc/network/interfaces");
Packit Service 5ffa24
Packit Service 5ffa24
        search_v = ifparser_getkey(block, "dns-search");
Packit Service 5ffa24
        if (search_v) {
Packit Service 5ffa24
            gs_free const char **list = NULL;
Packit Service 5ffa24
            const char **        iter;
Packit Service 5ffa24
Packit Service 5ffa24
            list = nm_utils_strsplit_set(search_v, " \t");
Packit Service 5ffa24
            for (iter = list; iter && *iter; iter++) {
Packit Service 5ffa24
                if (!nm_setting_ip_config_add_dns_search(s_ip6, *iter))
Packit Service 5ffa24
                    _LOGW("    duplicate DNS domain '%s'", *iter);
Packit Service 5ffa24
            }
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL, NULL);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    nm_connection_add_setting(connection, NM_SETTING(g_steal_pointer(&s_ip6)));
Packit Service 5ffa24
    return TRUE;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
NMConnection *
Packit Service 5ffa24
ifupdown_new_connection_from_if_block(if_block *block, gboolean autoconnect, GError **error)
Packit Service 5ffa24
{
Packit Service 5ffa24
    gs_unref_object NMConnection *connection = NULL;
Packit Service 5ffa24
    const char *                  type;
Packit Service 5ffa24
    gs_free char *                idstr = NULL;
Packit Service 5ffa24
    gs_free char *                uuid  = NULL;
Packit Service 5ffa24
    NMSettingConnection *         s_con;
Packit Service 5ffa24
Packit Service 5ffa24
    connection = nm_simple_connection_new();
Packit Service 5ffa24
Packit Service 5ffa24
    s_con = NM_SETTING_CONNECTION(nm_setting_connection_new());
Packit Service 5ffa24
    nm_connection_add_setting(connection, NM_SETTING(s_con));
Packit Service 5ffa24
Packit Service 5ffa24
    type  = _ifupdownplugin_guess_connection_type(block);
Packit Service 5ffa24
    idstr = g_strconcat("Ifupdown (", block->name, ")", NULL);
Packit Service 5ffa24
Packit Service 5ffa24
    uuid = nm_utils_uuid_generate_from_string(idstr, -1, NM_UTILS_UUID_TYPE_LEGACY, NULL);
Packit Service 5ffa24
    g_object_set(s_con,
Packit Service 5ffa24
                 NM_SETTING_CONNECTION_TYPE,
Packit Service 5ffa24
                 type,
Packit Service 5ffa24
                 NM_SETTING_CONNECTION_INTERFACE_NAME,
Packit Service 5ffa24
                 block->name,
Packit Service 5ffa24
                 NM_SETTING_CONNECTION_ID,
Packit Service 5ffa24
                 idstr,
Packit Service 5ffa24
                 NM_SETTING_CONNECTION_UUID,
Packit Service 5ffa24
                 uuid,
Packit Service 5ffa24
                 NM_SETTING_CONNECTION_AUTOCONNECT,
Packit Service 5ffa24
                 (gboolean)(!!autoconnect),
Packit Service 5ffa24
                 NULL);
Packit Service 5ffa24
Packit Service 5ffa24
    _LOGD("update_connection_setting_from_if_block: name:%s, type:%s, id:%s, uuid: %s",
Packit Service 5ffa24
          block->name,
Packit Service 5ffa24
          type,
Packit Service 5ffa24
          idstr,
Packit Service 5ffa24
          nm_setting_connection_get_uuid(s_con));
Packit Service 5ffa24
Packit Service 5ffa24
    if (nm_streq(type, NM_SETTING_WIRED_SETTING_NAME))
Packit Service 5ffa24
        update_wired_setting_from_if_block(connection, block);
Packit Service 5ffa24
    else if (nm_streq(type, NM_SETTING_WIRELESS_SETTING_NAME)) {
Packit Service 5ffa24
        update_wireless_setting_from_if_block(connection, block);
Packit Service 5ffa24
        update_wireless_security_setting_from_if_block(connection, block);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (ifparser_haskey(block, "inet6")) {
Packit Service 5ffa24
        if (!update_ip6_setting_from_if_block(connection, block, error))
Packit Service 5ffa24
            return FALSE;
Packit Service 5ffa24
    } else {
Packit Service 5ffa24
        if (!update_ip4_setting_from_if_block(connection, block, error))
Packit Service 5ffa24
            return FALSE;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (!nm_connection_normalize(connection, NULL, NULL, error))
Packit Service 5ffa24
        return NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    return g_steal_pointer(&connection);
Packit Service 5ffa24
}