1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /* NetworkManager system settings service - keyfile plugin
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Copyright 2009 - 2014 Red Hat, Inc.
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <arpa/inet.h>
33 #include <nm-setting-connection.h>
34 #include <nm-setting-wired.h>
35 #include <nm-setting-wireless.h>
36 #include <nm-setting-8021x.h>
37 #include <nm-setting-ip4-config.h>
38 #include <nm-setting-ip6-config.h>
39 #include <nm-setting-pppoe.h>
40 #include <nm-setting-vlan.h>
41 #include <nm-setting-team.h>
42 #include <nm-setting-team-port.h>
43 #include "nm-core-internal.h"
46 #include "nm-logging.h"
56 save_secret_flags (shvarFile *ifcfg,
58 NMSettingSecretFlags flags)
62 g_return_if_fail (ifcfg != NULL);
63 g_return_if_fail (key != NULL);
65 if (flags == NM_SETTING_SECRET_FLAG_NONE) {
66 svSetValue (ifcfg, key, NULL, FALSE);
70 /* Convert flags bitfield into string representation */
71 str = g_string_sized_new (20);
72 if (flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED)
73 g_string_append (str, SECRET_FLAG_AGENT);
75 if (flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) {
77 g_string_append_c (str, ' ');
78 g_string_append (str, SECRET_FLAG_NOT_SAVED);
81 if (flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED) {
83 g_string_append_c (str, ' ');
84 g_string_append (str, SECRET_FLAG_NOT_REQUIRED);
87 svSetValue (ifcfg, key, str->len ? str->str : NULL, FALSE);
88 g_string_free (str, TRUE);
92 set_secret (shvarFile *ifcfg,
95 const char *flags_key,
96 NMSettingSecretFlags flags,
100 GError *error = NULL;
102 /* Clear the secret from the ifcfg and the associated "keys" file */
103 svSetValue (ifcfg, key, NULL, FALSE);
105 /* Save secret flags */
106 save_secret_flags (ifcfg, flags_key, flags);
108 keyfile = utils_get_keys_ifcfg (ifcfg->fileName, TRUE);
110 nm_log_warn (LOGD_SETTINGS, " could not create ifcfg file for '%s'", ifcfg->fileName);
114 /* Clear the secret from the associated "keys" file */
115 svSetValue (keyfile, key, NULL, FALSE);
117 /* Only write the secret if it's system owned and supposed to be saved */
118 if (flags == NM_SETTING_SECRET_FLAG_NONE)
119 svSetValue (keyfile, key, value, verbatim);
121 if (!svWriteFile (keyfile, 0600, &error)) {
122 nm_log_warn (LOGD_SETTINGS, " could not update ifcfg file '%s': %s",
123 keyfile->fileName, error->message);
124 g_clear_error (&error);
125 svCloseFile (keyfile);
128 svCloseFile (keyfile);
132 /* Try setting the secret in the actual ifcfg */
133 svSetValue (ifcfg, key, value, FALSE);
137 write_secret_file (const char *path,
143 int fd = -1, written;
144 gboolean success = FALSE;
146 tmppath = g_malloc0 (strlen (path) + 10);
147 memcpy (tmppath, path, strlen (path));
148 strcat (tmppath, ".XXXXXX");
151 fd = mkstemp (tmppath);
153 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
154 "Could not create temporary file for '%s': %d",
159 /* Only readable by root */
161 if (fchmod (fd, S_IRUSR | S_IWUSR)) {
164 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
165 "Could not set permissions for temporary file '%s': %d",
171 written = write (fd, data, len);
172 if (written != len) {
175 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
176 "Could not write temporary file for '%s': %d",
184 if (rename (tmppath, path)) {
186 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
187 "Could not rename temporary file to '%s': %d",
198 typedef struct ObjectType {
199 const char *setting_key;
200 NMSetting8021xCKScheme (*scheme_func)(NMSetting8021x *setting);
201 const char * (*path_func) (NMSetting8021x *setting);
202 GBytes * (*blob_func) (NMSetting8021x *setting);
203 const char *ifcfg_key;
207 static const ObjectType ca_type = {
208 NM_SETTING_802_1X_CA_CERT,
209 nm_setting_802_1x_get_ca_cert_scheme,
210 nm_setting_802_1x_get_ca_cert_path,
211 nm_setting_802_1x_get_ca_cert_blob,
212 "IEEE_8021X_CA_CERT",
216 static const ObjectType phase2_ca_type = {
217 NM_SETTING_802_1X_PHASE2_CA_CERT,
218 nm_setting_802_1x_get_phase2_ca_cert_scheme,
219 nm_setting_802_1x_get_phase2_ca_cert_path,
220 nm_setting_802_1x_get_phase2_ca_cert_blob,
221 "IEEE_8021X_INNER_CA_CERT",
225 static const ObjectType client_type = {
226 NM_SETTING_802_1X_CLIENT_CERT,
227 nm_setting_802_1x_get_client_cert_scheme,
228 nm_setting_802_1x_get_client_cert_path,
229 nm_setting_802_1x_get_client_cert_blob,
230 "IEEE_8021X_CLIENT_CERT",
234 static const ObjectType phase2_client_type = {
235 NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
236 nm_setting_802_1x_get_phase2_client_cert_scheme,
237 nm_setting_802_1x_get_phase2_client_cert_path,
238 nm_setting_802_1x_get_phase2_client_cert_blob,
239 "IEEE_8021X_INNER_CLIENT_CERT",
240 "inner-client-cert.der"
243 static const ObjectType pk_type = {
244 NM_SETTING_802_1X_PRIVATE_KEY,
245 nm_setting_802_1x_get_private_key_scheme,
246 nm_setting_802_1x_get_private_key_path,
247 nm_setting_802_1x_get_private_key_blob,
248 "IEEE_8021X_PRIVATE_KEY",
252 static const ObjectType phase2_pk_type = {
253 NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
254 nm_setting_802_1x_get_phase2_private_key_scheme,
255 nm_setting_802_1x_get_phase2_private_key_path,
256 nm_setting_802_1x_get_phase2_private_key_blob,
257 "IEEE_8021X_INNER_PRIVATE_KEY",
258 "inner-private-key.pem"
261 static const ObjectType p12_type = {
262 NM_SETTING_802_1X_PRIVATE_KEY,
263 nm_setting_802_1x_get_private_key_scheme,
264 nm_setting_802_1x_get_private_key_path,
265 nm_setting_802_1x_get_private_key_blob,
266 "IEEE_8021X_PRIVATE_KEY",
270 static const ObjectType phase2_p12_type = {
271 NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
272 nm_setting_802_1x_get_phase2_private_key_scheme,
273 nm_setting_802_1x_get_phase2_private_key_path,
274 nm_setting_802_1x_get_phase2_private_key_blob,
275 "IEEE_8021X_INNER_PRIVATE_KEY",
276 "inner-private-key.p12"
280 write_object (NMSetting8021x *s_8021x,
282 const ObjectType *objtype,
285 NMSetting8021xCKScheme scheme;
286 const char *path = NULL;
289 g_return_val_if_fail (ifcfg != NULL, FALSE);
290 g_return_val_if_fail (objtype != NULL, FALSE);
292 scheme = (*(objtype->scheme_func))(s_8021x);
294 case NM_SETTING_802_1X_CK_SCHEME_BLOB:
295 blob = (*(objtype->blob_func))(s_8021x);
297 case NM_SETTING_802_1X_CK_SCHEME_PATH:
298 path = (*(objtype->path_func))(s_8021x);
304 /* If certificate/private key wasn't sent, the connection may no longer be
305 * 802.1x and thus we clear out the paths and certs.
307 if (!path && !blob) {
311 /* Since no cert/private key is now being used, delete any standard file
312 * that was created for this connection, but leave other files alone.
314 * /etc/sysconfig/network-scripts/ca-cert-Test_Write_Wifi_WPA_EAP-TLS.der
315 * will be deleted, but /etc/pki/tls/cert.pem will not.
317 standard_file = utils_cert_path (ifcfg->fileName, objtype->suffix);
318 if (g_file_test (standard_file, G_FILE_TEST_EXISTS))
319 ignored = unlink (standard_file);
320 g_free (standard_file);
322 svSetValue (ifcfg, objtype->ifcfg_key, NULL, FALSE);
326 /* If the object path was specified, prefer that over any raw cert data that
327 * may have been sent.
330 svSetValue (ifcfg, objtype->ifcfg_key, path, FALSE);
334 /* If it's raw certificate data, write the data out to the standard file */
338 GError *write_error = NULL;
340 new_file = utils_cert_path (ifcfg->fileName, objtype->suffix);
342 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
343 "Could not create file path for %s / %s",
344 NM_SETTING_802_1X_SETTING_NAME, objtype->setting_key);
348 /* Write the raw certificate data out to the standard file so that we
349 * can use paths from now on instead of pushing around the certificate
352 success = write_secret_file (new_file,
353 (const char *) g_bytes_get_data (blob, NULL),
354 g_bytes_get_size (blob),
357 svSetValue (ifcfg, objtype->ifcfg_key, new_file, FALSE);
361 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
362 "Could not write certificate/key for %s / %s: %s",
363 NM_SETTING_802_1X_SETTING_NAME, objtype->setting_key,
364 (write_error && write_error->message) ? write_error->message : "(unknown)");
365 g_clear_error (&write_error);
374 write_8021x_certs (NMSetting8021x *s_8021x,
379 const char *password = NULL;
380 gboolean success = FALSE, is_pkcs12 = FALSE;
381 const ObjectType *otype = NULL;
382 NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
385 if (!write_object (s_8021x, ifcfg, phase2 ? &phase2_ca_type : &ca_type, error))
390 otype = &phase2_pk_type;
391 if (nm_setting_802_1x_get_phase2_private_key_format (s_8021x) == NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
392 otype = &phase2_p12_type;
395 password = nm_setting_802_1x_get_phase2_private_key_password (s_8021x);
396 flags = nm_setting_802_1x_get_phase2_private_key_password_flags (s_8021x);
399 if (nm_setting_802_1x_get_private_key_format (s_8021x) == NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
403 password = nm_setting_802_1x_get_private_key_password (s_8021x);
404 flags = nm_setting_802_1x_get_private_key_password_flags (s_8021x);
407 /* Save the private key */
408 if (!write_object (s_8021x, ifcfg, otype, error))
411 /* Private key password */
414 "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD",
416 "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD_FLAGS",
421 "IEEE_8021X_PRIVATE_KEY_PASSWORD",
423 "IEEE_8021X_PRIVATE_KEY_PASSWORD_FLAGS",
428 /* Client certificate */
430 /* Don't need a client certificate with PKCS#12 since the file is both
431 * the client certificate and the private key in one file.
434 phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT",
437 /* Save the client certificate */
438 if (!write_object (s_8021x, ifcfg, phase2 ? &phase2_client_type : &client_type, error))
449 write_8021x_setting (NMConnection *connection,
454 NMSetting8021x *s_8021x;
455 const char *value, *match;
457 gboolean success = FALSE;
458 GString *phase2_auth;
462 s_8021x = nm_connection_get_setting_802_1x (connection);
464 /* If wired, clear KEY_MGMT */
466 svSetValue (ifcfg, "KEY_MGMT", NULL, FALSE);
470 /* If wired, write KEY_MGMT */
472 svSetValue (ifcfg, "KEY_MGMT", "IEEE8021X", FALSE);
475 if (nm_setting_802_1x_get_num_eap_methods (s_8021x)) {
476 value = nm_setting_802_1x_get_eap_method (s_8021x, 0);
478 tmp = g_ascii_strup (value, -1);
480 svSetValue (ifcfg, "IEEE_8021X_EAP_METHODS", tmp ? tmp : NULL, FALSE);
483 svSetValue (ifcfg, "IEEE_8021X_IDENTITY",
484 nm_setting_802_1x_get_identity (s_8021x),
487 svSetValue (ifcfg, "IEEE_8021X_ANON_IDENTITY",
488 nm_setting_802_1x_get_anonymous_identity (s_8021x),
492 "IEEE_8021X_PASSWORD",
493 nm_setting_802_1x_get_password (s_8021x),
494 "IEEE_8021X_PASSWORD_FLAGS",
495 nm_setting_802_1x_get_password_flags (s_8021x),
499 value = nm_setting_802_1x_get_phase1_peapver (s_8021x);
500 svSetValue (ifcfg, "IEEE_8021X_PEAP_VERSION", NULL, FALSE);
501 if (value && (!strcmp (value, "0") || !strcmp (value, "1")))
502 svSetValue (ifcfg, "IEEE_8021X_PEAP_VERSION", value, FALSE);
504 /* Force new PEAP label */
505 value = nm_setting_802_1x_get_phase1_peaplabel (s_8021x);
506 svSetValue (ifcfg, "IEEE_8021X_PEAP_FORCE_NEW_LABEL", NULL, FALSE);
507 if (value && !strcmp (value, "1"))
508 svSetValue (ifcfg, "IEEE_8021X_PEAP_FORCE_NEW_LABEL", "yes", FALSE);
511 value = nm_setting_802_1x_get_pac_file (s_8021x);
512 svSetValue (ifcfg, "IEEE_8021X_PAC_FILE", NULL, FALSE);
514 svSetValue (ifcfg, "IEEE_8021X_PAC_FILE", value, FALSE);
516 /* FAST PAC provisioning */
517 value = nm_setting_802_1x_get_phase1_fast_provisioning (s_8021x);
518 svSetValue (ifcfg, "IEEE_8021X_FAST_PROVISIONING", NULL, FALSE);
520 if (strcmp (value, "1") == 0)
521 svSetValue (ifcfg, "IEEE_8021X_FAST_PROVISIONING", "allow-unauth", FALSE);
522 else if (strcmp (value, "2") == 0)
523 svSetValue (ifcfg, "IEEE_8021X_FAST_PROVISIONING", "allow-auth", FALSE);
524 else if (strcmp (value, "3") == 0)
525 svSetValue (ifcfg, "IEEE_8021X_FAST_PROVISIONING", "allow-unauth allow-auth", FALSE);
528 /* Phase2 auth methods */
529 svSetValue (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS", NULL, FALSE);
530 phase2_auth = g_string_new (NULL);
532 value = nm_setting_802_1x_get_phase2_auth (s_8021x);
534 tmp = g_ascii_strup (value, -1);
535 g_string_append (phase2_auth, tmp);
539 value = nm_setting_802_1x_get_phase2_autheap (s_8021x);
541 if (phase2_auth->len)
542 g_string_append_c (phase2_auth, ' ');
544 tmp = g_ascii_strup (value, -1);
545 g_string_append_printf (phase2_auth, "EAP-%s", tmp);
549 svSetValue (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS",
550 phase2_auth->len ? phase2_auth->str : NULL,
553 g_string_free (phase2_auth, TRUE);
555 svSetValue (ifcfg, "IEEE_8021X_SUBJECT_MATCH",
556 nm_setting_802_1x_get_subject_match (s_8021x),
559 svSetValue (ifcfg, "IEEE_8021X_PHASE2_SUBJECT_MATCH",
560 nm_setting_802_1x_get_phase2_subject_match (s_8021x),
563 svSetValue (ifcfg, "IEEE_8021X_ALTSUBJECT_MATCHES", NULL, FALSE);
564 str = g_string_new (NULL);
565 num = nm_setting_802_1x_get_num_altsubject_matches (s_8021x);
566 for (i = 0; i < num; i++) {
568 g_string_append_c (str, ' ');
569 match = nm_setting_802_1x_get_altsubject_match (s_8021x, i);
570 g_string_append (str, match);
573 svSetValue (ifcfg, "IEEE_8021X_ALTSUBJECT_MATCHES", str->str, FALSE);
574 g_string_free (str, TRUE);
576 svSetValue (ifcfg, "IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES", NULL, FALSE);
577 str = g_string_new (NULL);
578 num = nm_setting_802_1x_get_num_phase2_altsubject_matches (s_8021x);
579 for (i = 0; i < num; i++) {
581 g_string_append_c (str, ' ');
582 match = nm_setting_802_1x_get_phase2_altsubject_match (s_8021x, i);
583 g_string_append (str, match);
586 svSetValue (ifcfg, "IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES", str->str, FALSE);
587 g_string_free (str, TRUE);
589 success = write_8021x_certs (s_8021x, FALSE, ifcfg, error);
591 /* phase2/inner certs */
592 success = write_8021x_certs (s_8021x, TRUE, ifcfg, error);
599 write_wireless_security_setting (NMConnection *connection,
605 NMSettingWirelessSecurity *s_wsec;
606 const char *key_mgmt, *auth_alg, *key, *proto, *cipher, *psk;
607 gboolean wep = FALSE, wpa = FALSE, dynamic_wep = FALSE;
612 s_wsec = nm_connection_get_setting_wireless_security (connection);
614 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
615 "Missing '%s' setting", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
619 key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec);
622 auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec);
624 svSetValue (ifcfg, "DEFAULTKEY", NULL, FALSE);
626 if (!strcmp (key_mgmt, "none")) {
627 svSetValue (ifcfg, "KEY_MGMT", NULL, FALSE);
630 } else if (!strcmp (key_mgmt, "wpa-none") || !strcmp (key_mgmt, "wpa-psk")) {
631 svSetValue (ifcfg, "KEY_MGMT", "WPA-PSK", FALSE);
634 } else if (!strcmp (key_mgmt, "ieee8021x")) {
635 svSetValue (ifcfg, "KEY_MGMT", "IEEE8021X", FALSE);
637 } else if (!strcmp (key_mgmt, "wpa-eap")) {
638 svSetValue (ifcfg, "KEY_MGMT", "WPA-EAP", FALSE);
642 svSetValue (ifcfg, "SECURITYMODE", NULL, FALSE);
644 if (!strcmp (auth_alg, "shared"))
645 svSetValue (ifcfg, "SECURITYMODE", "restricted", FALSE);
646 else if (!strcmp (auth_alg, "open"))
647 svSetValue (ifcfg, "SECURITYMODE", "open", FALSE);
648 else if (!strcmp (auth_alg, "leap")) {
649 svSetValue (ifcfg, "SECURITYMODE", "leap", FALSE);
650 svSetValue (ifcfg, "IEEE_8021X_IDENTITY",
651 nm_setting_wireless_security_get_leap_username (s_wsec),
654 "IEEE_8021X_PASSWORD",
655 nm_setting_wireless_security_get_leap_password (s_wsec),
656 "IEEE_8021X_PASSWORD_FLAGS",
657 nm_setting_wireless_security_get_leap_password_flags (s_wsec),
665 /* Clear any default key */
666 set_secret (ifcfg, "KEY", NULL, "WEP_KEY_FLAGS", NM_SETTING_SECRET_FLAG_NONE, FALSE);
668 /* Clear existing keys */
669 for (i = 0; i < 4; i++) {
670 tmp = g_strdup_printf ("KEY_PASSPHRASE%d", i + 1);
671 set_secret (ifcfg, tmp, NULL, "WEP_KEY_FLAGS", NM_SETTING_SECRET_FLAG_NONE, FALSE);
674 tmp = g_strdup_printf ("KEY%d", i + 1);
675 set_secret (ifcfg, tmp, NULL, "WEP_KEY_FLAGS", NM_SETTING_SECRET_FLAG_NONE, FALSE);
679 /* And write the new ones out */
681 /* Default WEP TX key index */
682 tmp = g_strdup_printf ("%d", nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec) + 1);
683 svSetValue (ifcfg, "DEFAULTKEY", tmp, FALSE);
686 for (i = 0; i < 4; i++) {
687 NMWepKeyType key_type;
689 key = nm_setting_wireless_security_get_wep_key (s_wsec, i);
691 char *ascii_key = NULL;
693 /* Passphrase needs a different ifcfg key since with WEP, there
694 * are some passphrases that are indistinguishable from WEP hex
697 key_type = nm_setting_wireless_security_get_wep_key_type (s_wsec);
698 if (key_type == NM_WEP_KEY_TYPE_PASSPHRASE)
699 tmp = g_strdup_printf ("KEY_PASSPHRASE%d", i + 1);
701 tmp = g_strdup_printf ("KEY%d", i + 1);
703 /* Add 's:' prefix for ASCII keys */
704 if (strlen (key) == 5 || strlen (key) == 13) {
705 ascii_key = g_strdup_printf ("s:%s", key);
714 nm_setting_wireless_security_get_wep_key_flags (s_wsec),
723 svSetValue (ifcfg, "WPA_ALLOW_WPA", NULL, FALSE);
724 svSetValue (ifcfg, "WPA_ALLOW_WPA2", NULL, FALSE);
725 num = nm_setting_wireless_security_get_num_protos (s_wsec);
726 for (i = 0; i < num; i++) {
727 proto = nm_setting_wireless_security_get_proto (s_wsec, i);
728 if (proto && !strcmp (proto, "wpa"))
729 svSetValue (ifcfg, "WPA_ALLOW_WPA", "yes", FALSE);
730 else if (proto && !strcmp (proto, "rsn"))
731 svSetValue (ifcfg, "WPA_ALLOW_WPA2", "yes", FALSE);
734 /* WPA Pairwise ciphers */
735 svSetValue (ifcfg, "CIPHER_PAIRWISE", NULL, FALSE);
736 str = g_string_new (NULL);
737 num = nm_setting_wireless_security_get_num_pairwise (s_wsec);
738 for (i = 0; i < num; i++) {
740 g_string_append_c (str, ' ');
741 cipher = nm_setting_wireless_security_get_pairwise (s_wsec, i);
743 /* Don't write out WEP40 or WEP104 if for some reason they are set; they
744 * are not valid pairwise ciphers.
746 if (strcmp (cipher, "wep40") && strcmp (cipher, "wep104")) {
747 tmp = g_ascii_strup (cipher, -1);
748 g_string_append (str, tmp);
752 if (strlen (str->str) && (dynamic_wep == FALSE))
753 svSetValue (ifcfg, "CIPHER_PAIRWISE", str->str, FALSE);
754 g_string_free (str, TRUE);
756 /* WPA Group ciphers */
757 svSetValue (ifcfg, "CIPHER_GROUP", NULL, FALSE);
758 str = g_string_new (NULL);
759 num = nm_setting_wireless_security_get_num_groups (s_wsec);
760 for (i = 0; i < num; i++) {
762 g_string_append_c (str, ' ');
763 cipher = nm_setting_wireless_security_get_group (s_wsec, i);
764 tmp = g_ascii_strup (cipher, -1);
765 g_string_append (str, tmp);
768 if (strlen (str->str) && (dynamic_wep == FALSE))
769 svSetValue (ifcfg, "CIPHER_GROUP", str->str, FALSE);
770 g_string_free (str, TRUE);
776 psk = nm_setting_wireless_security_get_psk (s_wsec);
777 if (psk && (strlen (psk) != 64)) {
778 /* Quote the PSK since it's a passphrase */
779 quoted = utils_single_quote_string (psk);
783 quoted ? quoted : psk,
785 nm_setting_wireless_security_get_psk_flags (s_wsec),
793 NM_SETTING_SECRET_FLAG_NONE,
801 write_wireless_setting (NMConnection *connection,
806 NMSettingWireless *s_wireless;
809 const guint8 *ssid_data;
811 const char *mode, *bssid;
812 const char *device_mac, *cloned_mac;
814 guint32 mtu, chan, i;
815 gboolean adhoc = FALSE, hex_ssid = FALSE;
816 const char * const *macaddr_blacklist;
818 s_wireless = nm_connection_get_setting_wireless (connection);
820 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
821 "Missing '%s' setting", NM_SETTING_WIRELESS_SETTING_NAME);
825 device_mac = nm_setting_wireless_get_mac_address (s_wireless);
826 svSetValue (ifcfg, "HWADDR", device_mac, FALSE);
828 cloned_mac = nm_setting_wireless_get_cloned_mac_address (s_wireless);
829 svSetValue (ifcfg, "MACADDR", cloned_mac, FALSE);
831 svSetValue (ifcfg, "HWADDR_BLACKLIST", NULL, FALSE);
832 macaddr_blacklist = nm_setting_wireless_get_mac_address_blacklist (s_wireless);
833 if (macaddr_blacklist[0]) {
836 blacklist_str = g_strjoinv (" ", (char **) macaddr_blacklist);
837 svSetValue (ifcfg, "HWADDR_BLACKLIST", blacklist_str, FALSE);
838 g_free (blacklist_str);
841 svSetValue (ifcfg, "MTU", NULL, FALSE);
842 mtu = nm_setting_wireless_get_mtu (s_wireless);
844 tmp = g_strdup_printf ("%u", mtu);
845 svSetValue (ifcfg, "MTU", tmp, FALSE);
849 ssid = nm_setting_wireless_get_ssid (s_wireless);
851 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
852 "Missing SSID in '%s' setting", NM_SETTING_WIRELESS_SETTING_NAME);
855 ssid_data = g_bytes_get_data (ssid, &ssid_len);
856 if (!ssid_len || ssid_len > 32) {
857 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
858 "Invalid SSID in '%s' setting", NM_SETTING_WIRELESS_SETTING_NAME);
862 /* If the SSID contains any non-printable characters, we need to use the
863 * hex notation of the SSID instead.
865 for (i = 0; i < ssid_len; i++) {
866 if (!g_ascii_isprint (ssid_data[i])) {
875 /* Hex SSIDs don't get quoted */
876 str = g_string_sized_new (ssid_len * 2 + 3);
877 g_string_append (str, "0x");
878 for (i = 0; i < ssid_len; i++)
879 g_string_append_printf (str, "%02X", ssid_data[i]);
880 svSetValue (ifcfg, "ESSID", str->str, TRUE);
881 g_string_free (str, TRUE);
883 /* Printable SSIDs always get quoted */
884 memset (buf, 0, sizeof (buf));
885 memcpy (buf, ssid_data, ssid_len);
886 tmp = svEscape (buf);
888 /* svEscape will usually quote the string, but just for consistency,
889 * if svEscape doesn't quote the ESSID, we quote it ourselves.
891 if (tmp[0] != '"' && tmp[strlen (tmp) - 1] != '"') {
892 tmp2 = g_strdup_printf ("\"%s\"", tmp);
893 svSetValue (ifcfg, "ESSID", tmp2, TRUE);
896 svSetValue (ifcfg, "ESSID", tmp, TRUE);
900 mode = nm_setting_wireless_get_mode (s_wireless);
901 if (!mode || !strcmp (mode, "infrastructure")) {
902 svSetValue (ifcfg, "MODE", "Managed", FALSE);
903 } else if (!strcmp (mode, "adhoc")) {
904 svSetValue (ifcfg, "MODE", "Ad-Hoc", FALSE);
906 } else if (!strcmp (mode, "ap")) {
907 svSetValue (ifcfg, "MODE", "Ap", FALSE);
909 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
910 "Invalid mode '%s' in '%s' setting",
911 mode, NM_SETTING_WIRELESS_SETTING_NAME);
915 svSetValue (ifcfg, "CHANNEL", NULL, FALSE);
916 svSetValue (ifcfg, "BAND", NULL, FALSE);
917 chan = nm_setting_wireless_get_channel (s_wireless);
919 tmp = g_strdup_printf ("%u", chan);
920 svSetValue (ifcfg, "CHANNEL", tmp, FALSE);
923 /* Band only set if channel is not, since channel implies band */
924 svSetValue (ifcfg, "BAND", nm_setting_wireless_get_band (s_wireless), FALSE);
927 bssid = nm_setting_wireless_get_bssid (s_wireless);
928 svSetValue (ifcfg, "BSSID", bssid, FALSE);
930 /* Ensure DEFAULTKEY and SECURITYMODE are cleared unless there's security;
931 * otherwise there's no way to detect WEP vs. open when WEP keys aren't
934 svSetValue (ifcfg, "DEFAULTKEY", NULL, FALSE);
935 svSetValue (ifcfg, "SECURITYMODE", NULL, FALSE);
937 if (nm_connection_get_setting_wireless_security (connection)) {
938 if (!write_wireless_security_setting (connection, ifcfg, adhoc, no_8021x, error))
943 /* Clear out wifi security keys */
944 svSetValue (ifcfg, "KEY_MGMT", NULL, FALSE);
945 svSetValue (ifcfg, "IEEE_8021X_IDENTITY", NULL, FALSE);
946 set_secret (ifcfg, "IEEE_8021X_PASSWORD", NULL, "IEEE_8021X_PASSWORD_FLAGS", NM_SETTING_SECRET_FLAG_NONE, FALSE);
947 svSetValue (ifcfg, "SECURITYMODE", NULL, FALSE);
949 /* Clear existing keys */
950 set_secret (ifcfg, "KEY", NULL, "WEP_KEY_FLAGS", NM_SETTING_SECRET_FLAG_NONE, FALSE);
951 for (i = 0; i < 4; i++) {
952 tmp = g_strdup_printf ("KEY_PASSPHRASE%d", i + 1);
953 set_secret (ifcfg, tmp, NULL, "WEP_KEY_FLAGS", NM_SETTING_SECRET_FLAG_NONE, FALSE);
956 tmp = g_strdup_printf ("KEY%d", i + 1);
957 set_secret (ifcfg, tmp, NULL, "WEP_KEY_FLAGS", NM_SETTING_SECRET_FLAG_NONE, FALSE);
961 svSetValue (ifcfg, "DEFAULTKEY", NULL, FALSE);
962 svSetValue (ifcfg, "WPA_ALLOW_WPA", NULL, FALSE);
963 svSetValue (ifcfg, "WPA_ALLOW_WPA2", NULL, FALSE);
964 svSetValue (ifcfg, "CIPHER_PAIRWISE", NULL, FALSE);
965 svSetValue (ifcfg, "CIPHER_GROUP", NULL, FALSE);
966 set_secret (ifcfg, "WPA_PSK", NULL, "WPA_PSK_FLAGS", NM_SETTING_SECRET_FLAG_NONE, FALSE);
968 /* Kill any old keys file */
969 keys_path = utils_get_keys_path (ifcfg->fileName);
970 (void) unlink (keys_path);
974 svSetValue (ifcfg, "SSID_HIDDEN", nm_setting_wireless_get_hidden (s_wireless) ? "yes" : NULL, TRUE);
976 svSetValue (ifcfg, "TYPE", TYPE_WIRELESS, FALSE);
982 write_infiniband_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
984 NMSettingInfiniband *s_infiniband;
986 const char *mac, *transport_mode, *parent;
990 s_infiniband = nm_connection_get_setting_infiniband (connection);
992 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
993 "Missing '%s' setting", NM_SETTING_INFINIBAND_SETTING_NAME);
997 mac = nm_setting_infiniband_get_mac_address (s_infiniband);
998 svSetValue (ifcfg, "HWADDR", mac, FALSE);
1000 svSetValue (ifcfg, "MTU", NULL, FALSE);
1001 mtu = nm_setting_infiniband_get_mtu (s_infiniband);
1003 tmp = g_strdup_printf ("%u", mtu);
1004 svSetValue (ifcfg, "MTU", tmp, FALSE);
1008 transport_mode = nm_setting_infiniband_get_transport_mode (s_infiniband);
1009 svSetValue (ifcfg, "CONNECTED_MODE",
1010 strcmp (transport_mode, "connected") == 0 ? "yes" : "no",
1013 p_key = nm_setting_infiniband_get_p_key (s_infiniband);
1015 svSetValue (ifcfg, "PKEY", "yes", FALSE);
1016 tmp = g_strdup_printf ("%u", p_key);
1017 svSetValue (ifcfg, "PKEY_ID", tmp, FALSE);
1020 parent = nm_setting_infiniband_get_parent (s_infiniband);
1022 svSetValue (ifcfg, "PHYSDEV", parent, FALSE);
1025 svSetValue (ifcfg, "TYPE", TYPE_INFINIBAND, FALSE);
1031 write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
1033 NMSettingWired *s_wired;
1034 const char *device_mac, *cloned_mac;
1036 const char *nettype, *portname, *ctcprot, *s390_key, *s390_val;
1037 guint32 mtu, num_opts, i;
1038 const char *const *s390_subchannels;
1040 const char * const *macaddr_blacklist;
1042 s_wired = nm_connection_get_setting_wired (connection);
1044 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
1045 "Missing '%s' setting", NM_SETTING_WIRED_SETTING_NAME);
1049 device_mac = nm_setting_wired_get_mac_address (s_wired);
1050 svSetValue (ifcfg, "HWADDR", device_mac, FALSE);
1052 cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
1053 svSetValue (ifcfg, "MACADDR", cloned_mac, FALSE);
1055 svSetValue (ifcfg, "HWADDR_BLACKLIST", NULL, FALSE);
1056 macaddr_blacklist = nm_setting_wired_get_mac_address_blacklist (s_wired);
1057 if (macaddr_blacklist[0]) {
1058 char *blacklist_str;
1060 blacklist_str = g_strjoinv (" ", (char **) macaddr_blacklist);
1061 svSetValue (ifcfg, "HWADDR_BLACKLIST", blacklist_str, FALSE);
1062 g_free (blacklist_str);
1065 svSetValue (ifcfg, "MTU", NULL, FALSE);
1066 mtu = nm_setting_wired_get_mtu (s_wired);
1068 tmp = g_strdup_printf ("%u", mtu);
1069 svSetValue (ifcfg, "MTU", tmp, FALSE);
1073 svSetValue (ifcfg, "SUBCHANNELS", NULL, FALSE);
1074 s390_subchannels = nm_setting_wired_get_s390_subchannels (s_wired);
1075 if (s390_subchannels) {
1076 int len = g_strv_length ((char **)s390_subchannels);
1080 tmp = g_strdup_printf ("%s,%s", s390_subchannels[0], s390_subchannels[1]);
1081 } else if (len == 3) {
1082 tmp = g_strdup_printf ("%s,%s,%s", s390_subchannels[0], s390_subchannels[1],
1083 s390_subchannels[2]);
1085 svSetValue (ifcfg, "SUBCHANNELS", tmp, FALSE);
1089 svSetValue (ifcfg, "NETTYPE", NULL, FALSE);
1090 nettype = nm_setting_wired_get_s390_nettype (s_wired);
1092 svSetValue (ifcfg, "NETTYPE", nettype, FALSE);
1094 svSetValue (ifcfg, "PORTNAME", NULL, FALSE);
1095 portname = nm_setting_wired_get_s390_option_by_key (s_wired, "portname");
1097 svSetValue (ifcfg, "PORTNAME", portname, FALSE);
1099 svSetValue (ifcfg, "CTCPROT", NULL, FALSE);
1100 ctcprot = nm_setting_wired_get_s390_option_by_key (s_wired, "ctcprot");
1102 svSetValue (ifcfg, "CTCPROT", ctcprot, FALSE);
1104 svSetValue (ifcfg, "OPTIONS", NULL, FALSE);
1105 num_opts = nm_setting_wired_get_num_s390_options (s_wired);
1106 if (s390_subchannels && num_opts) {
1107 str = g_string_sized_new (30);
1108 for (i = 0; i < num_opts; i++) {
1109 nm_setting_wired_get_s390_option (s_wired, i, &s390_key, &s390_val);
1111 /* portname is handled separately */
1112 if (!strcmp (s390_key, "portname") || !strcmp (s390_key, "ctcprot"))
1116 g_string_append_c (str, ' ');
1117 g_string_append_printf (str, "%s=%s", s390_key, s390_val);
1120 svSetValue (ifcfg, "OPTIONS", str->str, FALSE);
1121 g_string_free (str, TRUE);
1124 svSetValue (ifcfg, "TYPE", TYPE_ETHERNET, FALSE);
1130 vlan_priority_maplist_to_stringlist (NMSettingVlan *s_vlan, NMVlanPriorityMap map)
1135 if (map == NM_VLAN_INGRESS_MAP)
1136 g_object_get (G_OBJECT (s_vlan), NM_SETTING_VLAN_INGRESS_PRIORITY_MAP, &strlist, NULL);
1137 else if (map == NM_VLAN_EGRESS_MAP)
1138 g_object_get (G_OBJECT (s_vlan), NM_SETTING_VLAN_EGRESS_PRIORITY_MAP, &strlist, NULL);
1143 value = g_strjoinv (",", strlist);
1146 g_strfreev (strlist);
1152 write_vlan_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wired, GError **error)
1154 NMSettingVlan *s_vlan;
1155 NMSettingConnection *s_con;
1156 NMSettingWired *s_wired;
1158 guint32 vlan_flags = 0;
1160 s_con = nm_connection_get_setting_connection (connection);
1162 g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
1163 "Missing connection setting");
1167 s_vlan = nm_connection_get_setting_vlan (connection);
1169 g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
1170 "Missing VLAN setting");
1174 svSetValue (ifcfg, "VLAN", "yes", FALSE);
1175 svSetValue (ifcfg, "TYPE", TYPE_VLAN, FALSE);
1176 svSetValue (ifcfg, "DEVICE", nm_setting_connection_get_interface_name (s_con), FALSE);
1177 svSetValue (ifcfg, "PHYSDEV", nm_setting_vlan_get_parent (s_vlan), FALSE);
1179 tmp = g_strdup_printf ("%d", nm_setting_vlan_get_id (s_vlan));
1180 svSetValue (ifcfg, "VLAN_ID", tmp, FALSE);
1183 vlan_flags = nm_setting_vlan_get_flags (s_vlan);
1184 if (vlan_flags & NM_VLAN_FLAG_REORDER_HEADERS)
1185 svSetValue (ifcfg, "REORDER_HDR", "1", FALSE);
1187 svSetValue (ifcfg, "REORDER_HDR", "0", FALSE);
1189 svSetValue (ifcfg, "VLAN_FLAGS", NULL, FALSE);
1190 if (vlan_flags & NM_VLAN_FLAG_GVRP) {
1191 if (vlan_flags & NM_VLAN_FLAG_LOOSE_BINDING)
1192 svSetValue (ifcfg, "VLAN_FLAGS", "GVRP,LOOSE_BINDING", FALSE);
1194 svSetValue (ifcfg, "VLAN_FLAGS", "GVRP", FALSE);
1195 } else if (vlan_flags & NM_VLAN_FLAG_LOOSE_BINDING)
1196 svSetValue (ifcfg, "VLAN_FLAGS", "LOOSE_BINDING", FALSE);
1198 tmp = vlan_priority_maplist_to_stringlist (s_vlan, NM_VLAN_INGRESS_MAP);
1199 svSetValue (ifcfg, "VLAN_INGRESS_PRIORITY_MAP", tmp, FALSE);
1202 tmp = vlan_priority_maplist_to_stringlist (s_vlan, NM_VLAN_EGRESS_MAP);
1203 svSetValue (ifcfg, "VLAN_EGRESS_PRIORITY_MAP", tmp, FALSE);
1206 svSetValue (ifcfg, "HWADDR", NULL, FALSE);
1207 svSetValue (ifcfg, "MACADDR", NULL, FALSE);
1208 svSetValue (ifcfg, "MTU", NULL, FALSE);
1210 s_wired = nm_connection_get_setting_wired (connection);
1212 const char *device_mac, *cloned_mac;
1217 device_mac = nm_setting_wired_get_mac_address (s_wired);
1219 svSetValue (ifcfg, "HWADDR", device_mac, FALSE);
1221 cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
1223 svSetValue (ifcfg, "MACADDR", cloned_mac, FALSE);
1225 mtu = nm_setting_wired_get_mtu (s_wired);
1227 tmp = g_strdup_printf ("%u", mtu);
1228 svSetValue (ifcfg, "MTU", tmp, FALSE);
1237 write_bonding_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
1239 NMSettingBond *s_bond;
1241 guint32 i, num_opts;
1243 s_bond = nm_connection_get_setting_bond (connection);
1245 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
1246 "Missing '%s' setting", NM_SETTING_BOND_SETTING_NAME);
1250 iface = nm_connection_get_interface_name (connection);
1252 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
1253 "Missing interface name");
1257 svSetValue (ifcfg, "DEVICE", iface, FALSE);
1258 svSetValue (ifcfg, "BONDING_OPTS", NULL, FALSE);
1260 num_opts = nm_setting_bond_get_num_options (s_bond);
1262 GString *str = g_string_sized_new (64);
1264 for (i = 0; i < nm_setting_bond_get_num_options (s_bond); i++) {
1265 const char *key, *value;
1267 if (!nm_setting_bond_get_option (s_bond, i, &key, &value))
1271 g_string_append_c (str, ' ');
1273 g_string_append_printf (str, "%s=%s", key, value);
1277 svSetValue (ifcfg, "BONDING_OPTS", str->str, FALSE);
1279 g_string_free (str, TRUE);
1282 svSetValue (ifcfg, "TYPE", TYPE_BOND, FALSE);
1283 svSetValue (ifcfg, "BONDING_MASTER", "yes", FALSE);
1289 write_team_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
1291 NMSettingTeam *s_team;
1295 s_team = nm_connection_get_setting_team (connection);
1297 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
1298 "Missing '%s' setting", NM_SETTING_TEAM_SETTING_NAME);
1302 iface = nm_connection_get_interface_name (connection);
1304 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
1305 "Missing interface name");
1309 svSetValue (ifcfg, "DEVICE", iface, FALSE);
1310 config = nm_setting_team_get_config (s_team);
1311 svSetValue (ifcfg, "TEAM_CONFIG", config, FALSE);
1312 svSetValue (ifcfg, "DEVICETYPE", TYPE_TEAM, FALSE);
1318 get_setting_default (NMSetting *setting, const char *prop)
1321 GValue val = G_VALUE_INIT;
1324 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), prop);
1326 g_value_init (&val, pspec->value_type);
1327 g_param_value_set_default (pspec, &val);
1328 g_assert (G_VALUE_HOLDS_UINT (&val));
1329 ret = g_value_get_uint (&val);
1330 g_value_unset (&val);
1335 write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
1337 NMSettingBridge *s_bridge;
1344 s_bridge = nm_connection_get_setting_bridge (connection);
1346 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
1347 "Missing '%s' setting", NM_SETTING_BRIDGE_SETTING_NAME);
1351 iface = nm_connection_get_interface_name (connection);
1353 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
1354 "Missing interface name");
1358 svSetValue (ifcfg, "DEVICE", iface, FALSE);
1359 svSetValue (ifcfg, "BRIDGING_OPTS", NULL, FALSE);
1360 svSetValue (ifcfg, "STP", "no", FALSE);
1361 svSetValue (ifcfg, "DELAY", NULL, FALSE);
1363 mac = nm_setting_bridge_get_mac_address (s_bridge);
1364 svSetValue (ifcfg, "MACADDR", mac, FALSE);
1366 /* Bridge options */
1367 opts = g_string_sized_new (32);
1369 if (nm_setting_bridge_get_stp (s_bridge)) {
1370 svSetValue (ifcfg, "STP", "yes", FALSE);
1372 i = nm_setting_bridge_get_forward_delay (s_bridge);
1373 if (i != get_setting_default (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_FORWARD_DELAY)) {
1374 s = g_strdup_printf ("%u", i);
1375 svSetValue (ifcfg, "DELAY", s, FALSE);
1379 g_string_append_printf (opts, "priority=%u", nm_setting_bridge_get_priority (s_bridge));
1381 i = nm_setting_bridge_get_hello_time (s_bridge);
1382 if (i != get_setting_default (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_HELLO_TIME)) {
1384 g_string_append_c (opts, ' ');
1385 g_string_append_printf (opts, "hello_time=%u", i);
1388 i = nm_setting_bridge_get_max_age (s_bridge);
1389 if (i != get_setting_default (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_MAX_AGE)) {
1391 g_string_append_c (opts, ' ');
1392 g_string_append_printf (opts, "max_age=%u", i);
1396 i = nm_setting_bridge_get_ageing_time (s_bridge);
1397 if (i != get_setting_default (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_AGEING_TIME)) {
1399 g_string_append_c (opts, ' ');
1400 g_string_append_printf (opts, "ageing_time=%u", i);
1404 svSetValue (ifcfg, "BRIDGING_OPTS", opts->str, FALSE);
1405 g_string_free (opts, TRUE);
1407 svSetValue (ifcfg, "TYPE", TYPE_BRIDGE, FALSE);
1413 write_bridge_port_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
1415 NMSettingBridgePort *s_port;
1419 s_port = nm_connection_get_setting_bridge_port (connection);
1423 svSetValue (ifcfg, "BRIDGING_OPTS", NULL, FALSE);
1425 /* Bridge options */
1426 opts = g_string_sized_new (32);
1428 i = nm_setting_bridge_port_get_priority (s_port);
1429 if (i != get_setting_default (NM_SETTING (s_port), NM_SETTING_BRIDGE_PORT_PRIORITY))
1430 g_string_append_printf (opts, "priority=%u", i);
1432 i = nm_setting_bridge_port_get_path_cost (s_port);
1433 if (i != get_setting_default (NM_SETTING (s_port), NM_SETTING_BRIDGE_PORT_PATH_COST)) {
1435 g_string_append_c (opts, ' ');
1436 g_string_append_printf (opts, "path_cost=%u", i);
1439 if (nm_setting_bridge_port_get_hairpin_mode (s_port)) {
1441 g_string_append_c (opts, ' ');
1442 g_string_append_printf (opts, "hairpin_mode=1");
1446 svSetValue (ifcfg, "BRIDGING_OPTS", opts->str, FALSE);
1447 g_string_free (opts, TRUE);
1453 write_team_port_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
1455 NMSettingTeamPort *s_port;
1458 s_port = nm_connection_get_setting_team_port (connection);
1462 config = nm_setting_team_port_get_config (s_port);
1463 svSetValue (ifcfg, "TEAM_PORT_CONFIG", config, FALSE);
1469 write_dcb_flags (shvarFile *ifcfg, const char *tag, NMSettingDcbFlags flags)
1473 prop = g_strdup_printf ("DCB_%s_ENABLE", tag);
1474 svSetValue (ifcfg, prop, (flags & NM_SETTING_DCB_FLAG_ENABLE) ? "yes" : NULL, FALSE);
1477 prop = g_strdup_printf ("DCB_%s_ADVERTISE", tag);
1478 svSetValue (ifcfg, prop, (flags & NM_SETTING_DCB_FLAG_ADVERTISE) ? "yes" : NULL, FALSE);
1481 prop = g_strdup_printf ("DCB_%s_WILLING", tag);
1482 svSetValue (ifcfg, prop, (flags & NM_SETTING_DCB_FLAG_WILLING) ? "yes" : NULL, FALSE);
1487 write_dcb_app (shvarFile *ifcfg,
1489 NMSettingDcbFlags flags,
1492 char *prop, *tmp = NULL;
1494 write_dcb_flags (ifcfg, tag, flags);
1496 if ((flags & NM_SETTING_DCB_FLAG_ENABLE) && (priority >= 0))
1497 tmp = g_strdup_printf ("%d", priority);
1498 prop = g_strdup_printf ("DCB_%s_PRIORITY", tag);
1499 svSetValue (ifcfg, prop, tmp, FALSE);
1504 typedef gboolean (*DcbGetBoolFunc) (NMSettingDcb *, guint);
1507 write_dcb_bool_array (shvarFile *ifcfg,
1509 NMSettingDcb *s_dcb,
1510 NMSettingDcbFlags flags,
1511 DcbGetBoolFunc get_func)
1516 if (!(flags & NM_SETTING_DCB_FLAG_ENABLE)) {
1517 svSetValue (ifcfg, key, NULL, FALSE);
1522 for (i = 0; i < 8; i++)
1523 str[i] = get_func (s_dcb, i) ? '1' : '0';
1524 svSetValue (ifcfg, key, str, FALSE);
1527 typedef guint (*DcbGetUintFunc) (NMSettingDcb *, guint);
1530 write_dcb_uint_array (shvarFile *ifcfg,
1532 NMSettingDcb *s_dcb,
1533 NMSettingDcbFlags flags,
1534 DcbGetUintFunc get_func)
1539 if (!(flags & NM_SETTING_DCB_FLAG_ENABLE)) {
1540 svSetValue (ifcfg, key, NULL, FALSE);
1545 for (i = 0; i < 8; i++) {
1546 num = get_func (s_dcb, i);
1552 g_assert_not_reached ();
1554 svSetValue (ifcfg, key, str, FALSE);
1558 write_dcb_percent_array (shvarFile *ifcfg,
1560 NMSettingDcb *s_dcb,
1561 NMSettingDcbFlags flags,
1562 DcbGetUintFunc get_func)
1567 if (!(flags & NM_SETTING_DCB_FLAG_ENABLE)) {
1568 svSetValue (ifcfg, key, NULL, FALSE);
1572 str = g_string_sized_new (30);
1573 for (i = 0; i < 8; i++) {
1575 g_string_append_c (str, ',');
1576 g_string_append_printf (str, "%d", get_func (s_dcb, i));
1578 svSetValue (ifcfg, key, str->str, FALSE);
1579 g_string_free (str, TRUE);
1583 write_dcb_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
1585 NMSettingDcb *s_dcb;
1586 NMSettingDcbFlags flags;
1588 s_dcb = nm_connection_get_setting_dcb (connection);
1590 static const char *clear_keys[] = {
1592 KEY_DCB_APP_FCOE_ENABLE,
1593 KEY_DCB_APP_FCOE_ADVERTISE,
1594 KEY_DCB_APP_FCOE_WILLING,
1595 KEY_DCB_APP_FCOE_MODE,
1596 KEY_DCB_APP_ISCSI_ENABLE,
1597 KEY_DCB_APP_ISCSI_ADVERTISE,
1598 KEY_DCB_APP_ISCSI_WILLING,
1599 KEY_DCB_APP_FIP_ENABLE,
1600 KEY_DCB_APP_FIP_ADVERTISE,
1601 KEY_DCB_APP_FIP_WILLING,
1603 KEY_DCB_PFC_ADVERTISE,
1604 KEY_DCB_PFC_WILLING,
1607 KEY_DCB_PG_ADVERTISE,
1617 for (iter = clear_keys; *iter; iter++)
1618 svSetValue (ifcfg, *iter, NULL, FALSE);
1622 svSetValue (ifcfg, "DCB", "yes", FALSE);
1624 write_dcb_app (ifcfg, "APP_FCOE",
1625 nm_setting_dcb_get_app_fcoe_flags (s_dcb),
1626 nm_setting_dcb_get_app_fcoe_priority (s_dcb));
1627 if (nm_setting_dcb_get_app_fcoe_flags (s_dcb) & NM_SETTING_DCB_FLAG_ENABLE)
1628 svSetValue (ifcfg, KEY_DCB_APP_FCOE_MODE, nm_setting_dcb_get_app_fcoe_mode (s_dcb), FALSE);
1630 svSetValue (ifcfg, KEY_DCB_APP_FCOE_MODE, NULL, FALSE);
1632 write_dcb_app (ifcfg, "APP_ISCSI",
1633 nm_setting_dcb_get_app_iscsi_flags (s_dcb),
1634 nm_setting_dcb_get_app_iscsi_priority (s_dcb));
1635 write_dcb_app (ifcfg, "APP_FIP",
1636 nm_setting_dcb_get_app_fip_flags (s_dcb),
1637 nm_setting_dcb_get_app_fip_priority (s_dcb));
1639 write_dcb_flags (ifcfg, "PFC", nm_setting_dcb_get_priority_flow_control_flags (s_dcb));
1640 write_dcb_bool_array (ifcfg, KEY_DCB_PFC_UP, s_dcb,
1641 nm_setting_dcb_get_priority_flow_control_flags (s_dcb),
1642 nm_setting_dcb_get_priority_flow_control);
1644 flags = nm_setting_dcb_get_priority_group_flags (s_dcb);
1645 write_dcb_flags (ifcfg, "PG", flags);
1646 write_dcb_uint_array (ifcfg, KEY_DCB_PG_ID, s_dcb, flags, nm_setting_dcb_get_priority_group_id);
1647 write_dcb_percent_array (ifcfg, KEY_DCB_PG_PCT, s_dcb, flags, nm_setting_dcb_get_priority_group_bandwidth);
1648 write_dcb_percent_array (ifcfg, KEY_DCB_PG_UPPCT, s_dcb, flags, nm_setting_dcb_get_priority_bandwidth);
1649 write_dcb_bool_array (ifcfg, KEY_DCB_PG_STRICT, s_dcb, flags, nm_setting_dcb_get_priority_strict_bandwidth);
1650 write_dcb_uint_array (ifcfg, KEY_DCB_PG_UP2TC, s_dcb, flags, nm_setting_dcb_get_priority_traffic_class);
1656 write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg)
1664 svSetValue (ifcfg, "NAME", nm_setting_connection_get_id (s_con), FALSE);
1665 svSetValue (ifcfg, "UUID", nm_setting_connection_get_uuid (s_con), FALSE);
1666 svSetValue (ifcfg, "DEVICE", nm_setting_connection_get_interface_name (s_con), FALSE);
1667 svSetValue (ifcfg, "ONBOOT",
1668 nm_setting_connection_get_autoconnect (s_con) ? "yes" : "no",
1671 i_int = nm_setting_connection_get_autoconnect_priority (s_con);
1672 tmp = i_int != NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_DEFAULT
1673 ? g_strdup_printf ("%d", i_int) : NULL;
1674 svSetValue (ifcfg, "AUTOCONNECT_PRIORITY", tmp, FALSE);
1678 svSetValue (ifcfg, "USERS", NULL, FALSE);
1679 n = nm_setting_connection_get_num_permissions (s_con);
1681 str = g_string_sized_new (n * 20);
1683 for (i = 0; i < n; i++) {
1684 const char *puser = NULL;
1686 /* Items separated by space for consistency with eg
1687 * IPV6ADDR_SECONDARIES and DOMAIN.
1690 g_string_append_c (str, ' ');
1692 if (nm_setting_connection_get_permission (s_con, i, NULL, &puser, NULL))
1693 g_string_append (str, puser);
1695 svSetValue (ifcfg, "USERS", str->str, FALSE);
1696 g_string_free (str, TRUE);
1699 svSetValue (ifcfg, "ZONE", nm_setting_connection_get_zone(s_con), FALSE);
1701 master = nm_setting_connection_get_master (s_con);
1703 if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_BOND_SETTING_NAME)) {
1704 svSetValue (ifcfg, "MASTER", master, FALSE);
1705 svSetValue (ifcfg, "SLAVE", "yes", FALSE);
1706 } else if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_BRIDGE_SETTING_NAME))
1707 svSetValue (ifcfg, "BRIDGE", master, FALSE);
1708 else if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_TEAM_SETTING_NAME)) {
1709 svSetValue (ifcfg, "TEAM_MASTER", master, FALSE);
1710 svSetValue (ifcfg, "DEVICETYPE", TYPE_TEAM_PORT, FALSE);
1711 svSetValue (ifcfg, "TYPE", NULL, FALSE);
1715 /* secondary connection UUIDs */
1716 svSetValue (ifcfg, "SECONDARY_UUIDS", NULL, FALSE);
1717 n = nm_setting_connection_get_num_secondaries (s_con);
1719 str = g_string_sized_new (n * 37);
1721 for (i = 0; i < n; i++) {
1724 /* Items separated by space for consistency with eg
1725 * IPV6ADDR_SECONDARIES and DOMAIN.
1728 g_string_append_c (str, ' ');
1730 if ((uuid = nm_setting_connection_get_secondary (s_con, i)) != NULL)
1731 g_string_append (str, uuid);
1733 svSetValue (ifcfg, "SECONDARY_UUIDS", str->str, FALSE);
1734 g_string_free (str, TRUE);
1737 svSetValue (ifcfg, "GATEWAY_PING_TIMEOUT", NULL, FALSE);
1738 if (nm_setting_connection_get_gateway_ping_timeout (s_con)) {
1739 tmp = g_strdup_printf ("%" G_GUINT32_FORMAT, nm_setting_connection_get_gateway_ping_timeout (s_con));
1740 svSetValue (ifcfg, "GATEWAY_PING_TIMEOUT", tmp, FALSE);
1746 write_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError **error)
1748 const char *dest, *next_hop;
1750 char *route_contents;
1755 gboolean success = FALSE;
1757 g_return_val_if_fail (filename != NULL, FALSE);
1758 g_return_val_if_fail (s_ip4 != NULL, FALSE);
1759 g_return_val_if_fail (error != NULL, FALSE);
1760 g_return_val_if_fail (*error == NULL, FALSE);
1762 num = nm_setting_ip_config_get_num_routes (s_ip4);
1768 route_items = g_malloc0 (sizeof (char*) * (num + 1));
1769 for (i = 0; i < num; i++) {
1770 route = nm_setting_ip_config_get_route (s_ip4, i);
1772 dest = nm_ip_route_get_dest (route);
1773 prefix = nm_ip_route_get_prefix (route);
1774 next_hop = nm_ip_route_get_next_hop (route);
1775 metric = nm_ip_route_get_metric (route);
1778 route_items[i] = g_strdup_printf ("%s/%u via %s\n", dest, prefix, next_hop);
1780 route_items[i] = g_strdup_printf ("%s/%u via %s metric %u\n", dest, prefix, next_hop, (guint32) metric);
1782 route_items[num] = NULL;
1783 route_contents = g_strjoinv (NULL, route_items);
1784 g_strfreev (route_items);
1786 if (!g_file_set_contents (filename, route_contents, -1, NULL)) {
1787 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
1788 "Writing route file '%s' failed", filename);
1795 g_free (route_contents);
1801 write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
1803 NMSettingIPConfig *s_ip4;
1805 char *addr_key, *prefix_key, *netmask_key, *gw_key, *metric_key, *tmp;
1806 char *route_path = NULL;
1809 gint64 route_metric;
1811 gboolean success = FALSE;
1812 gboolean fake_ip4 = FALSE;
1813 const char *method = NULL;
1815 s_ip4 = nm_connection_get_setting_ip4_config (connection);
1817 method = nm_setting_ip_config_get_method (s_ip4);
1819 /* Missing IP4 setting is assumed to be DHCP */
1821 method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
1823 if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) {
1826 /* IPv4 disabled, clear IPv4 related parameters */
1827 svSetValue (ifcfg, "BOOTPROTO", NULL, FALSE);
1828 for (j = -1; j < 256; j++) {
1830 addr_key = g_strdup ("IPADDR");
1831 prefix_key = g_strdup ("PREFIX");
1832 netmask_key = g_strdup ("NETMASK");
1833 gw_key = g_strdup ("GATEWAY");
1835 addr_key = g_strdup_printf ("IPADDR%d", j);
1836 prefix_key = g_strdup_printf ("PREFIX%d", j);
1837 netmask_key = g_strdup_printf ("NETMASK%d", j);
1838 gw_key = g_strdup_printf ("GATEWAY%d", j);
1841 svSetValue (ifcfg, addr_key, NULL, FALSE);
1842 svSetValue (ifcfg, prefix_key, NULL, FALSE);
1843 svSetValue (ifcfg, netmask_key, NULL, FALSE);
1844 svSetValue (ifcfg, gw_key, NULL, FALSE);
1847 g_free (prefix_key);
1848 g_free (netmask_key);
1852 route_path = utils_get_route_path (ifcfg->fileName);
1853 result = unlink (route_path);
1854 g_free (route_path);
1858 /* Temporarily create fake IP4 setting if missing; method set to DHCP above */
1860 s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
1864 if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO))
1865 svSetValue (ifcfg, "BOOTPROTO", "dhcp", FALSE);
1866 else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL))
1867 svSetValue (ifcfg, "BOOTPROTO", "none", FALSE);
1868 else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL))
1869 svSetValue (ifcfg, "BOOTPROTO", "autoip", FALSE);
1870 else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED))
1871 svSetValue (ifcfg, "BOOTPROTO", "shared", FALSE);
1873 /* Clear out un-numbered IP address fields */
1874 svSetValue (ifcfg, "IPADDR", NULL, FALSE);
1875 svSetValue (ifcfg, "PREFIX", NULL, FALSE);
1876 svSetValue (ifcfg, "NETMASK", NULL, FALSE);
1877 svSetValue (ifcfg, "GATEWAY", NULL, FALSE);
1878 /* Clear out zero-indexed IP address fields */
1879 svSetValue (ifcfg, "IPADDR0", NULL, FALSE);
1880 svSetValue (ifcfg, "PREFIX0", NULL, FALSE);
1881 svSetValue (ifcfg, "NETMASK0", NULL, FALSE);
1882 svSetValue (ifcfg, "GATEWAY0", NULL, FALSE);
1884 /* Write out IPADDR<n>, PREFIX<n>, GATEWAY<n> for current IP addresses
1885 * without labels. Unset obsolete NETMASK<n>.
1887 num = nm_setting_ip_config_get_num_addresses (s_ip4);
1888 for (i = n = 0; i < num; i++) {
1891 addr = nm_setting_ip_config_get_address (s_ip4, i);
1896 label = nm_ip_address_get_attribute (addr, "label");
1902 /* Instead of index 0 use un-numbered variables.
1903 * It's needed for compatibility with ifup that only recognizes 'GATEAWAY'
1904 * See https://bugzilla.redhat.com/show_bug.cgi?id=771673
1905 * and https://bugzilla.redhat.com/show_bug.cgi?id=1105770
1907 addr_key = g_strdup ("IPADDR");
1908 prefix_key = g_strdup ("PREFIX");
1909 netmask_key = g_strdup ("NETMASK");
1910 gw_key = g_strdup ("GATEWAY");
1912 addr_key = g_strdup_printf ("IPADDR%d", n);
1913 prefix_key = g_strdup_printf ("PREFIX%d", n);
1914 netmask_key = g_strdup_printf ("NETMASK%d", n);
1915 gw_key = g_strdup_printf ("GATEWAY%d", n);
1918 svSetValue (ifcfg, addr_key, nm_ip_address_get_address (addr), FALSE);
1920 tmp = g_strdup_printf ("%u", nm_ip_address_get_prefix (addr));
1921 svSetValue (ifcfg, prefix_key, tmp, FALSE);
1924 svSetValue (ifcfg, netmask_key, NULL, FALSE);
1925 svSetValue (ifcfg, gw_key, NULL, FALSE);
1928 g_free (prefix_key);
1929 g_free (netmask_key);
1934 /* Clear remaining IPADDR<n..255>, etc */
1935 for (; n < 256; n++) {
1936 addr_key = g_strdup_printf ("IPADDR%d", n);
1937 prefix_key = g_strdup_printf ("PREFIX%d", n);
1938 netmask_key = g_strdup_printf ("NETMASK%d", n);
1939 gw_key = g_strdup_printf ("GATEWAY%d", n);
1941 svSetValue (ifcfg, addr_key, NULL, FALSE);
1942 svSetValue (ifcfg, prefix_key, NULL, FALSE);
1943 svSetValue (ifcfg, netmask_key, NULL, FALSE);
1944 svSetValue (ifcfg, gw_key, NULL, FALSE);
1947 g_free (prefix_key);
1948 g_free (netmask_key);
1952 svSetValue (ifcfg, "GATEWAY", nm_setting_ip_config_get_gateway (s_ip4), FALSE);
1954 num = nm_setting_ip_config_get_num_dns (s_ip4);
1955 for (i = 0; i < 254; i++) {
1958 addr_key = g_strdup_printf ("DNS%d", i + 1);
1961 svSetValue (ifcfg, addr_key, NULL, FALSE);
1963 dns = nm_setting_ip_config_get_dns (s_ip4, i);
1964 svSetValue (ifcfg, addr_key, dns, FALSE);
1969 num = nm_setting_ip_config_get_num_dns_searches (s_ip4);
1971 searches = g_string_new (NULL);
1972 for (i = 0; i < num; i++) {
1974 g_string_append_c (searches, ' ');
1975 g_string_append (searches, nm_setting_ip_config_get_dns_search (s_ip4, i));
1977 svSetValue (ifcfg, "DOMAIN", searches->str, FALSE);
1978 g_string_free (searches, TRUE);
1980 svSetValue (ifcfg, "DOMAIN", NULL, FALSE);
1982 /* DEFROUTE; remember that it has the opposite meaning from never-default */
1983 svSetValue (ifcfg, "DEFROUTE",
1984 nm_setting_ip_config_get_never_default (s_ip4) ? "no" : "yes",
1987 svSetValue (ifcfg, "PEERDNS", NULL, FALSE);
1988 svSetValue (ifcfg, "PEERROUTES", NULL, FALSE);
1989 svSetValue (ifcfg, "DHCP_CLIENT_ID", NULL, FALSE);
1990 if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
1991 svSetValue (ifcfg, "PEERDNS",
1992 nm_setting_ip_config_get_ignore_auto_dns (s_ip4) ? "no" : "yes",
1995 svSetValue (ifcfg, "PEERROUTES",
1996 nm_setting_ip_config_get_ignore_auto_routes (s_ip4) ? "no" : "yes",
1999 value = nm_setting_ip_config_get_dhcp_hostname (s_ip4);
2001 svSetValue (ifcfg, "DHCP_HOSTNAME", value, FALSE);
2003 /* Missing DHCP_SEND_HOSTNAME means TRUE, and we prefer not write it explicitly
2004 * in that case, because it is NM-specific variable
2006 svSetValue (ifcfg, "DHCP_SEND_HOSTNAME",
2007 nm_setting_ip_config_get_dhcp_send_hostname (s_ip4) ? NULL : "no",
2010 value = nm_setting_ip4_config_get_dhcp_client_id (NM_SETTING_IP4_CONFIG (s_ip4));
2012 svSetValue (ifcfg, "DHCP_CLIENT_ID", value, FALSE);
2015 svSetValue (ifcfg, "IPV4_FAILURE_FATAL",
2016 nm_setting_ip_config_get_may_fail (s_ip4) ? "no" : "yes",
2019 route_metric = nm_setting_ip_config_get_route_metric (s_ip4);
2020 tmp = route_metric != -1 ? g_strdup_printf ("%"G_GINT64_FORMAT, route_metric) : NULL;
2021 svSetValue (ifcfg, "IPV4_ROUTE_METRIC", tmp, FALSE);
2024 /* Static routes - route-<name> file */
2025 route_path = utils_get_route_path (ifcfg->fileName);
2027 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
2028 "Could not get route file path for '%s'", ifcfg->fileName);
2032 if (utils_has_route_file_new_syntax (route_path)) {
2033 shvarFile *routefile;
2035 routefile = utils_get_route_ifcfg (ifcfg->fileName, TRUE);
2037 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
2038 "Could not create route file '%s'", route_path);
2039 g_free (route_path);
2042 g_free (route_path);
2044 num = nm_setting_ip_config_get_num_routes (s_ip4);
2045 for (i = 0; i < 256; i++) {
2046 char buf[INET_ADDRSTRLEN];
2051 addr_key = g_strdup_printf ("ADDRESS%d", i);
2052 netmask_key = g_strdup_printf ("NETMASK%d", i);
2053 gw_key = g_strdup_printf ("GATEWAY%d", i);
2054 metric_key = g_strdup_printf ("METRIC%d", i);
2057 svSetValue (routefile, addr_key, NULL, FALSE);
2058 svSetValue (routefile, netmask_key, NULL, FALSE);
2059 svSetValue (routefile, gw_key, NULL, FALSE);
2060 svSetValue (routefile, metric_key, NULL, FALSE);
2062 route = nm_setting_ip_config_get_route (s_ip4, i);
2064 svSetValue (routefile, addr_key, nm_ip_route_get_dest (route), FALSE);
2066 memset (buf, 0, sizeof (buf));
2067 netmask = nm_utils_ip4_prefix_to_netmask (nm_ip_route_get_prefix (route));
2068 inet_ntop (AF_INET, (const void *) &netmask, &buf[0], sizeof (buf));
2069 svSetValue (routefile, netmask_key, &buf[0], FALSE);
2071 svSetValue (routefile, gw_key, nm_ip_route_get_next_hop (route), FALSE);
2073 memset (buf, 0, sizeof (buf));
2074 metric = nm_ip_route_get_metric (route);
2076 svSetValue (routefile, metric_key, NULL, FALSE);
2078 tmp = g_strdup_printf ("%u", (guint32) metric);
2079 svSetValue (routefile, metric_key, tmp, FALSE);
2085 g_free (netmask_key);
2087 g_free (metric_key);
2089 if (!svWriteFile (routefile, 0644, error)) {
2090 svCloseFile (routefile);
2093 svCloseFile (routefile);
2095 write_route_file_legacy (route_path, s_ip4, error);
2096 g_free (route_path);
2097 if (error && *error)
2105 g_object_unref (s_ip4);
2111 write_ip4_aliases (NMConnection *connection, char *base_ifcfg_path)
2113 NMSettingIPConfig *s_ip4;
2114 char *base_ifcfg_dir, *base_ifcfg_name, *base_name;
2115 int i, num, base_ifcfg_name_len, base_name_len;
2118 base_ifcfg_dir = g_path_get_dirname (base_ifcfg_path);
2119 base_ifcfg_name = g_path_get_basename (base_ifcfg_path);
2120 base_ifcfg_name_len = strlen (base_ifcfg_name);
2121 base_name = base_ifcfg_name + strlen (IFCFG_TAG);
2122 base_name_len = strlen (base_name);
2124 /* Remove all existing aliases for this file first */
2125 dir = g_dir_open (base_ifcfg_dir, 0, NULL);
2129 while ((item = g_dir_read_name (dir))) {
2132 if ( strncmp (item, base_ifcfg_name, base_ifcfg_name_len) != 0
2133 || item[base_ifcfg_name_len] != ':')
2136 full_path = g_build_filename (base_ifcfg_dir, item, NULL);
2144 if (utils_ignore_ip_config (connection))
2147 s_ip4 = nm_connection_get_setting_ip4_config (connection);
2151 num = nm_setting_ip_config_get_num_addresses (s_ip4);
2152 for (i = 0; i < num; i++) {
2153 GVariant *label_var;
2154 const char *label, *p;
2159 addr = nm_setting_ip_config_get_address (s_ip4, i);
2161 label_var = nm_ip_address_get_attribute (addr, "label");
2164 label = g_variant_get_string (label_var, NULL);
2165 if ( strncmp (label, base_name, base_name_len) != 0
2166 || label[base_name_len] != ':')
2169 for (p = label; *p; p++) {
2170 if (!g_ascii_isalnum (*p) && *p != '_' && *p != ':')
2176 path = g_strdup_printf ("%s%s", base_ifcfg_path, label + base_name_len);
2177 ifcfg = svCreateFile (path);
2180 svSetValue (ifcfg, "DEVICE", label, FALSE);
2182 addr = nm_setting_ip_config_get_address (s_ip4, i);
2183 svSetValue (ifcfg, "IPADDR", nm_ip_address_get_address (addr), FALSE);
2185 tmp = g_strdup_printf ("%u", nm_ip_address_get_prefix (addr));
2186 svSetValue (ifcfg, "PREFIX", tmp, FALSE);
2189 svWriteFile (ifcfg, 0644, NULL);
2190 svCloseFile (ifcfg);
2193 g_free (base_ifcfg_name);
2194 g_free (base_ifcfg_dir);
2198 write_route6_file (const char *filename, NMSettingIPConfig *s_ip6, GError **error)
2201 char *route_contents;
2204 gboolean success = FALSE;
2206 g_return_val_if_fail (filename != NULL, FALSE);
2207 g_return_val_if_fail (s_ip6 != NULL, FALSE);
2208 g_return_val_if_fail (error != NULL, FALSE);
2209 g_return_val_if_fail (*error == NULL, FALSE);
2211 num = nm_setting_ip_config_get_num_routes (s_ip6);
2217 route_items = g_malloc0 (sizeof (char*) * (num + 1));
2218 for (i = 0; i < num; i++) {
2219 route = nm_setting_ip_config_get_route (s_ip6, i);
2221 if (nm_ip_route_get_metric (route) == -1) {
2222 route_items[i] = g_strdup_printf ("%s/%u via %s\n",
2223 nm_ip_route_get_dest (route),
2224 nm_ip_route_get_prefix (route),
2225 nm_ip_route_get_next_hop (route));
2227 route_items[i] = g_strdup_printf ("%s/%u via %s metric %u\n",
2228 nm_ip_route_get_dest (route),
2229 nm_ip_route_get_prefix (route),
2230 nm_ip_route_get_next_hop (route),
2231 (guint32) nm_ip_route_get_metric (route));
2234 route_items[num] = NULL;
2235 route_contents = g_strjoinv (NULL, route_items);
2236 g_strfreev (route_items);
2238 if (!g_file_set_contents (filename, route_contents, -1, NULL)) {
2239 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
2240 "Writing route6 file '%s' failed", filename);
2247 g_free (route_contents);
2252 write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
2254 NMSettingIPConfig *s_ip6;
2255 NMSettingIPConfig *s_ip4;
2259 guint32 i, num, num4;
2263 gint64 route_metric;
2264 GString *ip_str1, *ip_str2, *ip_ptr;
2267 s_ip6 = nm_connection_get_setting_ip6_config (connection);
2269 /* Treat missing IPv6 setting as a setting with method "auto" */
2270 svSetValue (ifcfg, "IPV6INIT", "yes", FALSE);
2271 svSetValue (ifcfg, "IPV6_AUTOCONF", "yes", FALSE);
2272 svSetValue (ifcfg, "DHCPV6C", NULL, FALSE);
2273 svSetValue (ifcfg, "IPV6_DEFROUTE", "yes", FALSE);
2274 svSetValue (ifcfg, "IPV6_PEERDNS", "yes", FALSE);
2275 svSetValue (ifcfg, "IPV6_PEERROUTES", "yes", FALSE);
2276 svSetValue (ifcfg, "IPV6_FAILURE_FATAL", "no", FALSE);
2277 svSetValue (ifcfg, "IPV6_ROUTE_METRIC", NULL, FALSE);
2281 value = nm_setting_ip_config_get_method (s_ip6);
2283 if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) {
2284 svSetValue (ifcfg, "IPV6INIT", "no", FALSE);
2285 svSetValue (ifcfg, "DHCPV6C", NULL, FALSE);
2287 } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) {
2288 svSetValue (ifcfg, "IPV6INIT", "yes", FALSE);
2289 svSetValue (ifcfg, "IPV6_AUTOCONF", "yes", FALSE);
2290 svSetValue (ifcfg, "DHCPV6C", NULL, FALSE);
2291 } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) {
2292 const char *hostname;
2293 svSetValue (ifcfg, "IPV6INIT", "yes", FALSE);
2294 svSetValue (ifcfg, "IPV6_AUTOCONF", "no", FALSE);
2295 svSetValue (ifcfg, "DHCPV6C", "yes", FALSE);
2296 hostname = nm_setting_ip_config_get_dhcp_hostname (s_ip6);
2298 svSetValue (ifcfg, "DHCP_HOSTNAME", hostname, FALSE);
2299 } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
2300 svSetValue (ifcfg, "IPV6INIT", "yes", FALSE);
2301 svSetValue (ifcfg, "IPV6_AUTOCONF", "no", FALSE);
2302 svSetValue (ifcfg, "DHCPV6C", NULL, FALSE);
2303 } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) {
2304 svSetValue (ifcfg, "IPV6INIT", "yes", FALSE);
2305 svSetValue (ifcfg, "IPV6_AUTOCONF", "no", FALSE);
2306 svSetValue (ifcfg, "DHCPV6C", NULL, FALSE);
2307 } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) {
2308 svSetValue (ifcfg, "IPV6INIT", "yes", FALSE);
2309 svSetValue (ifcfg, "DHCPV6C", NULL, FALSE);
2313 /* Write out IP addresses */
2314 num = nm_setting_ip_config_get_num_addresses (s_ip6);
2315 ip_str1 = g_string_new (NULL);
2316 ip_str2 = g_string_new (NULL);
2317 for (i = 0; i < num; i++) {
2323 addr = nm_setting_ip_config_get_address (s_ip6, i);
2326 g_string_append_c (ip_ptr, ' '); /* separate addresses in IPV6ADDR_SECONDARIES */
2327 g_string_append_printf (ip_ptr, "%s/%u",
2328 nm_ip_address_get_address (addr),
2329 nm_ip_address_get_prefix (addr));
2331 svSetValue (ifcfg, "IPV6ADDR", ip_str1->str, FALSE);
2332 svSetValue (ifcfg, "IPV6ADDR_SECONDARIES", ip_str2->str, FALSE);
2333 svSetValue (ifcfg, "IPV6_DEFAULTGW", nm_setting_ip_config_get_gateway (s_ip6), FALSE);
2334 g_string_free (ip_str1, TRUE);
2335 g_string_free (ip_str2, TRUE);
2337 /* Write out DNS - 'DNS' key is used both for IPv4 and IPv6 */
2338 s_ip4 = nm_connection_get_setting_ip4_config (connection);
2339 num4 = s_ip4 ? nm_setting_ip_config_get_num_dns (s_ip4) : 0; /* from where to start with IPv6 entries */
2340 num = nm_setting_ip_config_get_num_dns (s_ip6);
2341 for (i = 0; i < 254; i++) {
2342 addr_key = g_strdup_printf ("DNS%d", i + num4 + 1);
2345 svSetValue (ifcfg, addr_key, NULL, FALSE);
2347 dns = nm_setting_ip_config_get_dns (s_ip6, i);
2348 svSetValue (ifcfg, addr_key, dns, FALSE);
2353 /* Write out DNS domains - 'DOMAIN' key is shared for both IPv4 and IPv6 domains */
2354 num = nm_setting_ip_config_get_num_dns_searches (s_ip6);
2357 ip4_domains = svGetValue (ifcfg, "DOMAIN", FALSE);
2358 searches = g_string_new (ip4_domains);
2359 for (i = 0; i < num; i++) {
2360 if (searches->len > 0)
2361 g_string_append_c (searches, ' ');
2362 g_string_append (searches, nm_setting_ip_config_get_dns_search (s_ip6, i));
2364 svSetValue (ifcfg, "DOMAIN", searches->str, FALSE);
2365 g_string_free (searches, TRUE);
2366 g_free (ip4_domains);
2369 /* handle IPV6_DEFROUTE */
2370 /* IPV6_DEFROUTE has the opposite meaning from 'never-default' */
2371 if (nm_setting_ip_config_get_never_default(s_ip6))
2372 svSetValue (ifcfg, "IPV6_DEFROUTE", "no", FALSE);
2374 svSetValue (ifcfg, "IPV6_DEFROUTE", "yes", FALSE);
2376 svSetValue (ifcfg, "IPV6_PEERDNS", NULL, FALSE);
2377 svSetValue (ifcfg, "IPV6_PEERROUTES", NULL, FALSE);
2378 if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) {
2379 svSetValue (ifcfg, "IPV6_PEERDNS",
2380 nm_setting_ip_config_get_ignore_auto_dns (s_ip6) ? "no" : "yes",
2383 svSetValue (ifcfg, "IPV6_PEERROUTES",
2384 nm_setting_ip_config_get_ignore_auto_routes (s_ip6) ? "no" : "yes",
2388 svSetValue (ifcfg, "IPV6_FAILURE_FATAL",
2389 nm_setting_ip_config_get_may_fail (s_ip6) ? "no" : "yes",
2392 route_metric = nm_setting_ip_config_get_route_metric (s_ip6);
2393 tmp = route_metric != -1 ? g_strdup_printf ("%"G_GINT64_FORMAT, route_metric) : NULL;
2394 svSetValue (ifcfg, "IPV6_ROUTE_METRIC", tmp, FALSE);
2397 /* IPv6 Privacy Extensions */
2398 svSetValue (ifcfg, "IPV6_PRIVACY", NULL, FALSE);
2399 svSetValue (ifcfg, "IPV6_PRIVACY_PREFER_PUBLIC_IP", NULL, FALSE);
2400 switch (nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (s_ip6))){
2401 case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED:
2402 svSetValue (ifcfg, "IPV6_PRIVACY", "no", FALSE);
2404 case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR:
2405 svSetValue (ifcfg, "IPV6_PRIVACY", "rfc3041", FALSE);
2406 svSetValue (ifcfg, "IPV6_PRIVACY_PREFER_PUBLIC_IP", "yes", FALSE);
2408 case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR:
2409 svSetValue (ifcfg, "IPV6_PRIVACY", "rfc3041", FALSE);
2415 /* Static routes go to route6-<dev> file */
2416 route6_path = utils_get_route6_path (ifcfg->fileName);
2418 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
2419 "Could not get route6 file path for '%s'", ifcfg->fileName);
2422 write_route6_file (route6_path, s_ip6, error);
2423 g_free (route6_path);
2424 if (error && *error)
2434 escape_id (const char *id)
2436 char *escaped = g_strdup (id);
2439 /* Escape random stuff */
2443 else if (strchr ("\\][|/=()!", *p))
2452 write_connection (NMConnection *connection,
2453 const char *ifcfg_dir,
2454 const char *filename,
2455 const char *keyfile,
2456 char **out_filename,
2459 NMSettingConnection *s_con;
2460 gboolean success = FALSE;
2461 shvarFile *ifcfg = NULL;
2462 char *ifcfg_name = NULL;
2464 gboolean no_8021x = FALSE;
2465 gboolean wired = FALSE;
2467 if (!writer_can_write_connection (connection, error))
2470 s_con = nm_connection_get_setting_connection (connection);
2474 /* For existing connections, 'filename' should be full path to ifcfg file */
2475 ifcfg = svOpenFile (filename, error);
2479 ifcfg_name = g_strdup (filename);
2483 escaped = escape_id (nm_setting_connection_get_id (s_con));
2484 ifcfg_name = g_strdup_printf ("%s/ifcfg-%s", ifcfg_dir, escaped);
2486 /* If a file with this path already exists then we need another name.
2487 * Multiple connections can have the same ID (ie if two connections with
2488 * the same ID are visible to different users) but of course can't have
2491 if (g_file_test (ifcfg_name, G_FILE_TEST_EXISTS)) {
2494 g_free (ifcfg_name);
2495 while (idx++ < 500) {
2496 ifcfg_name = g_strdup_printf ("%s/ifcfg-%s-%u", ifcfg_dir, escaped, idx);
2497 if (g_file_test (ifcfg_name, G_FILE_TEST_EXISTS) == FALSE)
2499 g_free (ifcfg_name);
2505 if (ifcfg_name == NULL) {
2506 g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
2507 "Failed to find usable ifcfg file name");
2511 ifcfg = svCreateFile (ifcfg_name);
2514 type = nm_setting_connection_get_connection_type (s_con);
2516 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
2517 "Missing connection type!");
2521 if (!strcmp (type, NM_SETTING_WIRED_SETTING_NAME)) {
2522 // FIXME: can't write PPPoE at this time
2523 if (nm_connection_get_setting_pppoe (connection)) {
2524 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
2525 "Can't write connection type '%s'",
2526 NM_SETTING_PPPOE_SETTING_NAME);
2530 if (!write_wired_setting (connection, ifcfg, error))
2533 } else if (!strcmp (type, NM_SETTING_VLAN_SETTING_NAME)) {
2534 if (!write_vlan_setting (connection, ifcfg, &wired, error))
2536 } else if (!strcmp (type, NM_SETTING_WIRELESS_SETTING_NAME)) {
2537 if (!write_wireless_setting (connection, ifcfg, &no_8021x, error))
2539 } else if (!strcmp (type, NM_SETTING_INFINIBAND_SETTING_NAME)) {
2540 if (!write_infiniband_setting (connection, ifcfg, error))
2542 } else if (!strcmp (type, NM_SETTING_BOND_SETTING_NAME)) {
2543 if (!write_bonding_setting (connection, ifcfg, error))
2545 } else if (!strcmp (type, NM_SETTING_TEAM_SETTING_NAME)) {
2546 if (!write_team_setting (connection, ifcfg, error))
2548 } else if (!strcmp (type, NM_SETTING_BRIDGE_SETTING_NAME)) {
2549 if (!write_bridge_setting (connection, ifcfg, error))
2552 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
2553 "Can't write connection type '%s'", type);
2558 if (!write_8021x_setting (connection, ifcfg, wired, error))
2562 if (!write_bridge_port_setting (connection, ifcfg, error))
2565 if (!write_team_port_setting (connection, ifcfg, error))
2568 if (!write_dcb_setting (connection, ifcfg, error))
2571 if (!utils_ignore_ip_config (connection)) {
2572 svSetValue (ifcfg, "DHCP_HOSTNAME", NULL, FALSE);
2574 if (!write_ip4_setting (connection, ifcfg, error))
2576 write_ip4_aliases (connection, ifcfg_name);
2578 if (!write_ip6_setting (connection, ifcfg, error))
2582 write_connection_setting (s_con, ifcfg);
2584 if (!svWriteFile (ifcfg, 0644, error))
2587 /* Only return the filename if this was a newly written ifcfg */
2588 if (out_filename && !filename)
2589 *out_filename = g_strdup (ifcfg_name);
2595 svCloseFile (ifcfg);
2596 g_free (ifcfg_name);
2601 writer_can_write_connection (NMConnection *connection, GError **error)
2603 NMSettingConnection *s_con;
2605 if ( ( nm_connection_is_type (connection, NM_SETTING_WIRED_SETTING_NAME)
2606 && !nm_connection_get_setting_pppoe (connection))
2607 || nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME)
2608 || nm_connection_is_type (connection, NM_SETTING_WIRELESS_SETTING_NAME)
2609 || nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME)
2610 || nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)
2611 || nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME)
2612 || nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME))
2615 s_con = nm_connection_get_setting_connection (connection);
2617 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
2618 "The ifcfg-rh plugin cannot write the connection '%s' (type '%s' pppoe %d)",
2619 nm_connection_get_id (connection),
2620 nm_setting_connection_get_connection_type (s_con),
2621 !!nm_connection_get_setting_pppoe (connection));
2626 writer_new_connection (NMConnection *connection,
2627 const char *ifcfg_dir,
2628 char **out_filename,
2631 return write_connection (connection, ifcfg_dir, NULL, NULL, out_filename, error);
2635 writer_update_connection (NMConnection *connection,
2636 const char *ifcfg_dir,
2637 const char *filename,
2638 const char *keyfile,
2641 if (utils_has_complex_routes (filename)) {
2642 g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
2643 "Cannot modify a connection that has an associated 'rule-' or 'rule6-' file");
2647 return write_connection (connection, ifcfg_dir, filename, keyfile, NULL, error);