1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /* NetworkManager system settings service - keyfile plugin
3 *
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.
8 *
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.
13 *
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.
17 *
18 * Copyright (C) 2009 - 2012 Red Hat, Inc.
19 */
20
21 #include <string.h>
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <arpa/inet.h>
25 #include <errno.h>
26 #include <stdlib.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #include <stdio.h>
30 #include <netinet/ether.h>
31
32 #include <nm-setting-connection.h>
33 #include <nm-setting-wired.h>
34 #include <nm-setting-wireless.h>
35 #include <nm-setting-8021x.h>
36 #include <nm-setting-ip4-config.h>
37 #include <nm-setting-ip6-config.h>
38 #include <nm-setting-pppoe.h>
39 #include <nm-setting-vlan.h>
40 #include <nm-setting-team.h>
41 #include <nm-setting-team-port.h>
42 #include <nm-utils.h>
43
44 #include "common.h"
45 #include "shvar.h"
46 #include "reader.h"
47 #include "writer.h"
48 #include "utils.h"
49 #include "crypto.h"
50
51 #define PLUGIN_WARN(pname, fmt, args...) \
52 { g_warning (" " pname ": " fmt, ##args); }
53
54 static void
55 save_secret_flags (shvarFile *ifcfg,
56 const char *key,
57 NMSettingSecretFlags flags)
58 {
59 GString *str;
60
61 g_return_if_fail (ifcfg != NULL);
62 g_return_if_fail (key != NULL);
63
64 if (flags == NM_SETTING_SECRET_FLAG_NONE) {
65 svSetValue (ifcfg, key, NULL, FALSE);
66 return;
67 }
68
69 /* Convert flags bitfield into string representation */
70 str = g_string_sized_new (20);
71 if (flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED)
72 g_string_append (str, SECRET_FLAG_AGENT);
73
74 if (flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) {
75 if (str->len)
76 g_string_append_c (str, ' ');
77 g_string_append (str, SECRET_FLAG_NOT_SAVED);
78 }
79
80 if (flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED) {
81 if (str->len)
82 g_string_append_c (str, ' ');
83 g_string_append (str, SECRET_FLAG_NOT_REQUIRED);
84 }
85
86 svSetValue (ifcfg, key, str->len ? str->str : NULL, FALSE);
87 g_string_free (str, TRUE);
88 }
89
90 static void
91 set_secret (shvarFile *ifcfg,
92 const char *key,
93 const char *value,
94 const char *flags_key,
95 NMSettingSecretFlags flags,
96 gboolean verbatim)
97 {
98 shvarFile *keyfile;
99
100 /* Clear the secret from the ifcfg and the associated "keys" file */
101 svSetValue (ifcfg, key, NULL, FALSE);
102
103 /* Save secret flags */
104 save_secret_flags (ifcfg, flags_key, flags);
105
106 keyfile = utils_get_keys_ifcfg (ifcfg->fileName, TRUE);
107 if (!keyfile) {
108 PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: could not create key file for '%s'",
109 ifcfg->fileName);
110 goto error;
111 }
112
113 /* Clear the secret from the associated "keys" file */
114 svSetValue (keyfile, key, NULL, FALSE);
115
116 /* Only write the secret if it's system owned and supposed to be saved */
117 if (flags == NM_SETTING_SECRET_FLAG_NONE)
118 svSetValue (keyfile, key, value, verbatim);
119
120 if (svWriteFile (keyfile, 0600)) {
121 PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: could not update key file '%s'",
122 keyfile->fileName);
123 svCloseFile (keyfile);
124 goto error;
125 }
126 svCloseFile (keyfile);
127 return;
128
129 error:
130 /* Try setting the secret in the actual ifcfg */
131 svSetValue (ifcfg, key, value, FALSE);
132 }
133
134 static gboolean
135 write_secret_file (const char *path,
136 const char *data,
137 gsize len,
138 GError **error)
139 {
140 char *tmppath;
141 int fd = -1, written;
142 gboolean success = FALSE;
143
144 tmppath = g_malloc0 (strlen (path) + 10);
145 memcpy (tmppath, path, strlen (path));
146 strcat (tmppath, ".XXXXXX");
147
148 errno = 0;
149 fd = mkstemp (tmppath);
150 if (fd < 0) {
151 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
152 "Could not create temporary file for '%s': %d",
153 path, errno);
154 goto out;
155 }
156
157 /* Only readable by root */
158 errno = 0;
159 if (fchmod (fd, S_IRUSR | S_IWUSR)) {
160 close (fd);
161 unlink (tmppath);
162 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
163 "Could not set permissions for temporary file '%s': %d",
164 path, errno);
165 goto out;
166 }
167
168 errno = 0;
169 written = write (fd, data, len);
170 if (written != len) {
171 close (fd);
172 unlink (tmppath);
173 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
174 "Could not write temporary file for '%s': %d",
175 path, errno);
176 goto out;
177 }
178 close (fd);
179
180 /* Try to rename */
181 errno = 0;
182 if (rename (tmppath, path)) {
183 unlink (tmppath);
184 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
185 "Could not rename temporary file to '%s': %d",
186 path, errno);
187 goto out;
188 }
189 success = TRUE;
190
191 out:
192 g_free (tmppath);
193 return success;
194 }
195
196 typedef struct ObjectType {
197 const char *setting_key;
198 NMSetting8021xCKScheme (*scheme_func)(NMSetting8021x *setting);
199 const char * (*path_func) (NMSetting8021x *setting);
200 const GByteArray * (*blob_func) (NMSetting8021x *setting);
201 const char *ifcfg_key;
202 const char *suffix;
203 } ObjectType;
204
205 static const ObjectType ca_type = {
206 NM_SETTING_802_1X_CA_CERT,
207 nm_setting_802_1x_get_ca_cert_scheme,
208 nm_setting_802_1x_get_ca_cert_path,
209 nm_setting_802_1x_get_ca_cert_blob,
210 "IEEE_8021X_CA_CERT",
211 "ca-cert.der"
212 };
213
214 static const ObjectType phase2_ca_type = {
215 NM_SETTING_802_1X_PHASE2_CA_CERT,
216 nm_setting_802_1x_get_phase2_ca_cert_scheme,
217 nm_setting_802_1x_get_phase2_ca_cert_path,
218 nm_setting_802_1x_get_phase2_ca_cert_blob,
219 "IEEE_8021X_INNER_CA_CERT",
220 "inner-ca-cert.der"
221 };
222
223 static const ObjectType client_type = {
224 NM_SETTING_802_1X_CLIENT_CERT,
225 nm_setting_802_1x_get_client_cert_scheme,
226 nm_setting_802_1x_get_client_cert_path,
227 nm_setting_802_1x_get_client_cert_blob,
228 "IEEE_8021X_CLIENT_CERT",
229 "client-cert.der"
230 };
231
232 static const ObjectType phase2_client_type = {
233 NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
234 nm_setting_802_1x_get_phase2_client_cert_scheme,
235 nm_setting_802_1x_get_phase2_client_cert_path,
236 nm_setting_802_1x_get_phase2_client_cert_blob,
237 "IEEE_8021X_INNER_CLIENT_CERT",
238 "inner-client-cert.der"
239 };
240
241 static const ObjectType pk_type = {
242 NM_SETTING_802_1X_PRIVATE_KEY,
243 nm_setting_802_1x_get_private_key_scheme,
244 nm_setting_802_1x_get_private_key_path,
245 nm_setting_802_1x_get_private_key_blob,
246 "IEEE_8021X_PRIVATE_KEY",
247 "private-key.pem"
248 };
249
250 static const ObjectType phase2_pk_type = {
251 NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
252 nm_setting_802_1x_get_phase2_private_key_scheme,
253 nm_setting_802_1x_get_phase2_private_key_path,
254 nm_setting_802_1x_get_phase2_private_key_blob,
255 "IEEE_8021X_INNER_PRIVATE_KEY",
256 "inner-private-key.pem"
257 };
258
259 static const ObjectType p12_type = {
260 NM_SETTING_802_1X_PRIVATE_KEY,
261 nm_setting_802_1x_get_private_key_scheme,
262 nm_setting_802_1x_get_private_key_path,
263 nm_setting_802_1x_get_private_key_blob,
264 "IEEE_8021X_PRIVATE_KEY",
265 "private-key.p12"
266 };
267
268 static const ObjectType phase2_p12_type = {
269 NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
270 nm_setting_802_1x_get_phase2_private_key_scheme,
271 nm_setting_802_1x_get_phase2_private_key_path,
272 nm_setting_802_1x_get_phase2_private_key_blob,
273 "IEEE_8021X_INNER_PRIVATE_KEY",
274 "inner-private-key.p12"
275 };
276
277 static gboolean
278 write_object (NMSetting8021x *s_8021x,
279 shvarFile *ifcfg,
280 const ObjectType *objtype,
281 GError **error)
282 {
283 NMSetting8021xCKScheme scheme;
284 const char *path = NULL;
285 const GByteArray *blob = NULL;
286
287 g_return_val_if_fail (ifcfg != NULL, FALSE);
288 g_return_val_if_fail (objtype != NULL, FALSE);
289
290 scheme = (*(objtype->scheme_func))(s_8021x);
291 switch (scheme) {
292 case NM_SETTING_802_1X_CK_SCHEME_BLOB:
293 blob = (*(objtype->blob_func))(s_8021x);
294 break;
295 case NM_SETTING_802_1X_CK_SCHEME_PATH:
296 path = (*(objtype->path_func))(s_8021x);
297 break;
298 default:
299 break;
300 }
301
302 /* If certificate/private key wasn't sent, the connection may no longer be
303 * 802.1x and thus we clear out the paths and certs.
304 */
305 if (!path && !blob) {
306 char *standard_file;
307 int ignored;
308
309 /* Since no cert/private key is now being used, delete any standard file
310 * that was created for this connection, but leave other files alone.
311 * Thus, for example,
312 * /etc/sysconfig/network-scripts/ca-cert-Test_Write_Wifi_WPA_EAP-TLS.der
313 * will be deleted, but /etc/pki/tls/cert.pem will not.
314 */
315 standard_file = utils_cert_path (ifcfg->fileName, objtype->suffix);
316 if (g_file_test (standard_file, G_FILE_TEST_EXISTS))
317 ignored = unlink (standard_file);
318 g_free (standard_file);
319
320 svSetValue (ifcfg, objtype->ifcfg_key, NULL, FALSE);
321 return TRUE;
322 }
323
324 /* If the object path was specified, prefer that over any raw cert data that
325 * may have been sent.
326 */
327 if (path) {
328 svSetValue (ifcfg, objtype->ifcfg_key, path, FALSE);
329 return TRUE;
330 }
331
332 /* If it's raw certificate data, write the data out to the standard file */
333 if (blob) {
334 gboolean success;
335 char *new_file;
336 GError *write_error = NULL;
337
338 new_file = utils_cert_path (ifcfg->fileName, objtype->suffix);
339 if (!new_file) {
340 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
341 "Could not create file path for %s / %s",
342 NM_SETTING_802_1X_SETTING_NAME, objtype->setting_key);
343 return FALSE;
344 }
345
346 /* Write the raw certificate data out to the standard file so that we
347 * can use paths from now on instead of pushing around the certificate
348 * data itself.
349 */
350 success = write_secret_file (new_file, (const char *) blob->data, blob->len, &write_error);
351 if (success) {
352 svSetValue (ifcfg, objtype->ifcfg_key, new_file, FALSE);
353 g_free (new_file);
354 return TRUE;
355 } else {
356 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
357 "Could not write certificate/key for %s / %s: %s",
358 NM_SETTING_802_1X_SETTING_NAME, objtype->setting_key,
359 (write_error && write_error->message) ? write_error->message : "(unknown)");
360 g_clear_error (&write_error);
361 }
362 g_free (new_file);
363 }
364
365 return FALSE;
366 }
367
368 static gboolean
369 write_8021x_certs (NMSetting8021x *s_8021x,
370 gboolean phase2,
371 shvarFile *ifcfg,
372 GError **error)
373 {
374 const char *password = NULL;
375 gboolean success = FALSE, is_pkcs12 = FALSE;
376 const ObjectType *otype = NULL;
377 NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
378
379 /* CA certificate */
380 if (!write_object (s_8021x, ifcfg, phase2 ? &phase2_ca_type : &ca_type, error))
381 return FALSE;
382
383 /* Private key */
384 if (phase2) {
385 otype = &phase2_pk_type;
386 if (nm_setting_802_1x_get_phase2_private_key_format (s_8021x) == NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
387 otype = &phase2_p12_type;
388 is_pkcs12 = TRUE;
389 }
390 password = nm_setting_802_1x_get_phase2_private_key_password (s_8021x);
391 flags = nm_setting_802_1x_get_phase2_private_key_password_flags (s_8021x);
392 } else {
393 otype = &pk_type;
394 if (nm_setting_802_1x_get_private_key_format (s_8021x) == NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
395 otype = &p12_type;
396 is_pkcs12 = TRUE;
397 }
398 password = nm_setting_802_1x_get_private_key_password (s_8021x);
399 flags = nm_setting_802_1x_get_private_key_password_flags (s_8021x);
400 }
401
402 /* Save the private key */
403 if (!write_object (s_8021x, ifcfg, otype, error))
404 goto out;
405
406 /* Private key password */
407 if (phase2) {
408 set_secret (ifcfg,
409 "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD",
410 password,
411 "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD_FLAGS",
412 flags,
413 FALSE);
414 } else {
415 set_secret (ifcfg,
416 "IEEE_8021X_PRIVATE_KEY_PASSWORD",
417 password,
418 "IEEE_8021X_PRIVATE_KEY_PASSWORD_FLAGS",
419 flags,
420 FALSE);
421 }
422
423 /* Client certificate */
424 if (is_pkcs12) {
425 /* Don't need a client certificate with PKCS#12 since the file is both
426 * the client certificate and the private key in one file.
427 */
428 svSetValue (ifcfg,
429 phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT",
430 NULL, FALSE);
431 } else {
432 /* Save the client certificate */
433 if (!write_object (s_8021x, ifcfg, phase2 ? &phase2_client_type : &client_type, error))
434 goto out;
435 }
436
437 success = TRUE;
438
439 out:
440 return success;
441 }
442
443 static gboolean
444 write_8021x_setting (NMConnection *connection,
445 shvarFile *ifcfg,
446 gboolean wired,
447 GError **error)
448 {
449 NMSetting8021x *s_8021x;
450 const char *value;
451 char *tmp = NULL;
452 gboolean success = FALSE;
453 GString *phase2_auth;
454
455 s_8021x = nm_connection_get_setting_802_1x (connection);
456 if (!s_8021x) {
457 /* If wired, clear KEY_MGMT */
458 if (wired)
459 svSetValue (ifcfg, "KEY_MGMT", NULL, FALSE);
460 return TRUE;
461 }
462
463 /* If wired, write KEY_MGMT */
464 if (wired)
465 svSetValue (ifcfg, "KEY_MGMT", "IEEE8021X", FALSE);
466
467 /* EAP method */
468 if (nm_setting_802_1x_get_num_eap_methods (s_8021x)) {
469 value = nm_setting_802_1x_get_eap_method (s_8021x, 0);
470 if (value)
471 tmp = g_ascii_strup (value, -1);
472 }
473 svSetValue (ifcfg, "IEEE_8021X_EAP_METHODS", tmp ? tmp : NULL, FALSE);
474 g_free (tmp);
475
476 svSetValue (ifcfg, "IEEE_8021X_IDENTITY",
477 nm_setting_802_1x_get_identity (s_8021x),
478 FALSE);
479
480 svSetValue (ifcfg, "IEEE_8021X_ANON_IDENTITY",
481 nm_setting_802_1x_get_anonymous_identity (s_8021x),
482 FALSE);
483
484 set_secret (ifcfg,
485 "IEEE_8021X_PASSWORD",
486 nm_setting_802_1x_get_password (s_8021x),
487 "IEEE_8021X_PASSWORD_FLAGS",
488 nm_setting_802_1x_get_password_flags (s_8021x),
489 FALSE);
490
491 /* PEAP version */
492 value = nm_setting_802_1x_get_phase1_peapver (s_8021x);
493 svSetValue (ifcfg, "IEEE_8021X_PEAP_VERSION", NULL, FALSE);
494 if (value && (!strcmp (value, "0") || !strcmp (value, "1")))
495 svSetValue (ifcfg, "IEEE_8021X_PEAP_VERSION", value, FALSE);
496
497 /* Force new PEAP label */
498 value = nm_setting_802_1x_get_phase1_peaplabel (s_8021x);
499 svSetValue (ifcfg, "IEEE_8021X_PEAP_FORCE_NEW_LABEL", NULL, FALSE);
500 if (value && !strcmp (value, "1"))
501 svSetValue (ifcfg, "IEEE_8021X_PEAP_FORCE_NEW_LABEL", "yes", FALSE);
502
503 /* PAC file */
504 value = nm_setting_802_1x_get_pac_file (s_8021x);
505 svSetValue (ifcfg, "IEEE_8021X_PAC_FILE", NULL, FALSE);
506 if (value)
507 svSetValue (ifcfg, "IEEE_8021X_PAC_FILE", value, FALSE);
508
509 /* FAST PAC provisioning */
510 value = nm_setting_802_1x_get_phase1_fast_provisioning (s_8021x);
511 svSetValue (ifcfg, "IEEE_8021X_FAST_PROVISIONING", NULL, FALSE);
512 if (value) {
513 if (strcmp (value, "1") == 0)
514 svSetValue (ifcfg, "IEEE_8021X_FAST_PROVISIONING", "allow-unauth", FALSE);
515 else if (strcmp (value, "2") == 0)
516 svSetValue (ifcfg, "IEEE_8021X_FAST_PROVISIONING", "allow-auth", FALSE);
517 else if (strcmp (value, "3") == 0)
518 svSetValue (ifcfg, "IEEE_8021X_FAST_PROVISIONING", "allow-unauth allow-auth", FALSE);
519 }
520
521 /* Phase2 auth methods */
522 svSetValue (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS", NULL, FALSE);
523 phase2_auth = g_string_new (NULL);
524
525 value = nm_setting_802_1x_get_phase2_auth (s_8021x);
526 if (value) {
527 tmp = g_ascii_strup (value, -1);
528 g_string_append (phase2_auth, tmp);
529 g_free (tmp);
530 }
531
532 value = nm_setting_802_1x_get_phase2_autheap (s_8021x);
533 if (value) {
534 if (phase2_auth->len)
535 g_string_append_c (phase2_auth, ' ');
536
537 tmp = g_ascii_strup (value, -1);
538 g_string_append_printf (phase2_auth, "EAP-%s", tmp);
539 g_free (tmp);
540 }
541
542 svSetValue (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS",
543 phase2_auth->len ? phase2_auth->str : NULL,
544 FALSE);
545
546 g_string_free (phase2_auth, TRUE);
547
548 success = write_8021x_certs (s_8021x, FALSE, ifcfg, error);
549 if (success) {
550 /* phase2/inner certs */
551 success = write_8021x_certs (s_8021x, TRUE, ifcfg, error);
552 }
553
554 return success;
555 }
556
557 static gboolean
558 write_wireless_security_setting (NMConnection *connection,
559 shvarFile *ifcfg,
560 gboolean adhoc,
561 gboolean *no_8021x,
562 GError **error)
563 {
564 NMSettingWirelessSecurity *s_wsec;
565 const char *key_mgmt, *auth_alg, *key, *proto, *cipher, *psk;
566 gboolean wep = FALSE, wpa = FALSE, dynamic_wep = FALSE;
567 char *tmp;
568 guint32 i, num;
569 GString *str;
570
571 s_wsec = nm_connection_get_setting_wireless_security (connection);
572 if (!s_wsec) {
573 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
574 "Missing '%s' setting", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
575 return FALSE;
576 }
577
578 key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec);
579 g_assert (key_mgmt);
580
581 auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec);
582
583 svSetValue (ifcfg, "DEFAULTKEY", NULL, FALSE);
584
585 if (!strcmp (key_mgmt, "none")) {
586 svSetValue (ifcfg, "KEY_MGMT", NULL, FALSE);
587 wep = TRUE;
588 *no_8021x = TRUE;
589 } else if (!strcmp (key_mgmt, "wpa-none") || !strcmp (key_mgmt, "wpa-psk")) {
590 svSetValue (ifcfg, "KEY_MGMT", "WPA-PSK", FALSE);
591 wpa = TRUE;
592 *no_8021x = TRUE;
593 } else if (!strcmp (key_mgmt, "ieee8021x")) {
594 svSetValue (ifcfg, "KEY_MGMT", "IEEE8021X", FALSE);
595 dynamic_wep = TRUE;
596 } else if (!strcmp (key_mgmt, "wpa-eap")) {
597 svSetValue (ifcfg, "KEY_MGMT", "WPA-EAP", FALSE);
598 wpa = TRUE;
599 }
600
601 svSetValue (ifcfg, "SECURITYMODE", NULL, FALSE);
602 if (auth_alg) {
603 if (!strcmp (auth_alg, "shared"))
604 svSetValue (ifcfg, "SECURITYMODE", "restricted", FALSE);
605 else if (!strcmp (auth_alg, "open"))
606 svSetValue (ifcfg, "SECURITYMODE", "open", FALSE);
607 else if (!strcmp (auth_alg, "leap")) {
608 svSetValue (ifcfg, "SECURITYMODE", "leap", FALSE);
609 svSetValue (ifcfg, "IEEE_8021X_IDENTITY",
610 nm_setting_wireless_security_get_leap_username (s_wsec),
611 FALSE);
612 set_secret (ifcfg,
613 "IEEE_8021X_PASSWORD",
614 nm_setting_wireless_security_get_leap_password (s_wsec),
615 "IEEE_8021X_PASSWORD_FLAGS",
616 nm_setting_wireless_security_get_leap_password_flags (s_wsec),
617 FALSE);
618 *no_8021x = TRUE;
619 }
620 }
621
622 /* WEP keys */
623
624 /* Clear any default key */
625 set_secret (ifcfg, "KEY", NULL, "WEP_KEY_FLAGS", NM_SETTING_SECRET_FLAG_NONE, FALSE);
626
627 /* Clear existing keys */
628 for (i = 0; i < 4; i++) {
629 tmp = g_strdup_printf ("KEY_PASSPHRASE%d", i + 1);
630 set_secret (ifcfg, tmp, NULL, "WEP_KEY_FLAGS", NM_SETTING_SECRET_FLAG_NONE, FALSE);
631 g_free (tmp);
632
633 tmp = g_strdup_printf ("KEY%d", i + 1);
634 set_secret (ifcfg, tmp, NULL, "WEP_KEY_FLAGS", NM_SETTING_SECRET_FLAG_NONE, FALSE);
635 g_free (tmp);
636 }
637
638 /* And write the new ones out */
639 if (wep) {
640 /* Default WEP TX key index */
641 tmp = g_strdup_printf ("%d", nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec) + 1);
642 svSetValue (ifcfg, "DEFAULTKEY", tmp, FALSE);
643 g_free (tmp);
644
645 for (i = 0; i < 4; i++) {
646 NMWepKeyType key_type;
647
648 key = nm_setting_wireless_security_get_wep_key (s_wsec, i);
649 if (key) {
650 char *ascii_key = NULL;
651
652 /* Passphrase needs a different ifcfg key since with WEP, there
653 * are some passphrases that are indistinguishable from WEP hex
654 * keys.
655 */
656 key_type = nm_setting_wireless_security_get_wep_key_type (s_wsec);
657 if (key_type == NM_WEP_KEY_TYPE_PASSPHRASE)
658 tmp = g_strdup_printf ("KEY_PASSPHRASE%d", i + 1);
659 else {
660 tmp = g_strdup_printf ("KEY%d", i + 1);
661
662 /* Add 's:' prefix for ASCII keys */
663 if (strlen (key) == 5 || strlen (key) == 13) {
664 ascii_key = g_strdup_printf ("s:%s", key);
665 key = ascii_key;
666 }
667 }
668
669 set_secret (ifcfg,
670 tmp,
671 key,
672 "WEP_KEY_FLAGS",
673 nm_setting_wireless_security_get_wep_key_flags (s_wsec),
674 FALSE);
675 g_free (tmp);
676 g_free (ascii_key);
677 }
678 }
679 }
680
681 /* WPA protos */
682 svSetValue (ifcfg, "WPA_ALLOW_WPA", NULL, FALSE);
683 svSetValue (ifcfg, "WPA_ALLOW_WPA2", NULL, FALSE);
684 num = nm_setting_wireless_security_get_num_protos (s_wsec);
685 for (i = 0; i < num; i++) {
686 proto = nm_setting_wireless_security_get_proto (s_wsec, i);
687 if (proto && !strcmp (proto, "wpa"))
688 svSetValue (ifcfg, "WPA_ALLOW_WPA", "yes", FALSE);
689 else if (proto && !strcmp (proto, "rsn"))
690 svSetValue (ifcfg, "WPA_ALLOW_WPA2", "yes", FALSE);
691 }
692
693 /* WPA Pairwise ciphers */
694 svSetValue (ifcfg, "CIPHER_PAIRWISE", NULL, FALSE);
695 str = g_string_new (NULL);
696 num = nm_setting_wireless_security_get_num_pairwise (s_wsec);
697 for (i = 0; i < num; i++) {
698 if (i > 0)
699 g_string_append_c (str, ' ');
700 cipher = nm_setting_wireless_security_get_pairwise (s_wsec, i);
701
702 /* Don't write out WEP40 or WEP104 if for some reason they are set; they
703 * are not valid pairwise ciphers.
704 */
705 if (strcmp (cipher, "wep40") && strcmp (cipher, "wep104")) {
706 tmp = g_ascii_strup (cipher, -1);
707 g_string_append (str, tmp);
708 g_free (tmp);
709 }
710 }
711 if (strlen (str->str) && (dynamic_wep == FALSE))
712 svSetValue (ifcfg, "CIPHER_PAIRWISE", str->str, FALSE);
713 g_string_free (str, TRUE);
714
715 /* WPA Group ciphers */
716 svSetValue (ifcfg, "CIPHER_GROUP", NULL, FALSE);
717 str = g_string_new (NULL);
718 num = nm_setting_wireless_security_get_num_groups (s_wsec);
719 for (i = 0; i < num; i++) {
720 if (i > 0)
721 g_string_append_c (str, ' ');
722 cipher = nm_setting_wireless_security_get_group (s_wsec, i);
723 tmp = g_ascii_strup (cipher, -1);
724 g_string_append (str, tmp);
725 g_free (tmp);
726 }
727 if (strlen (str->str) && (dynamic_wep == FALSE))
728 svSetValue (ifcfg, "CIPHER_GROUP", str->str, FALSE);
729 g_string_free (str, TRUE);
730
731 /* WPA Passphrase */
732 if (wpa) {
733 char *quoted = NULL;
734
735 psk = nm_setting_wireless_security_get_psk (s_wsec);
736 if (psk && (strlen (psk) != 64)) {
737 /* Quote the PSK since it's a passphrase */
738 quoted = utils_single_quote_string (psk);
739 }
740 set_secret (ifcfg,
741 "WPA_PSK",
742 quoted ? quoted : psk,
743 "WPA_PSK_FLAGS",
744 nm_setting_wireless_security_get_psk_flags (s_wsec),
745 TRUE);
746 g_free (quoted);
747 } else {
748 set_secret (ifcfg,
749 "WPA_PSK",
750 NULL,
751 "WPA_PSK_FLAGS",
752 NM_SETTING_SECRET_FLAG_NONE,
753 FALSE);
754 }
755
756 return TRUE;
757 }
758
759 static gboolean
760 write_wireless_setting (NMConnection *connection,
761 shvarFile *ifcfg,
762 gboolean *no_8021x,
763 GError **error)
764 {
765 NMSettingWireless *s_wireless;
766 char *tmp, *tmp2;
767 const GByteArray *ssid, *device_mac, *cloned_mac, *bssid;
768 const char *mode;
769 char buf[33];
770 guint32 mtu, chan, i;
771 gboolean adhoc = FALSE, hex_ssid = FALSE;
772 const GSList *macaddr_blacklist;
773
774 s_wireless = nm_connection_get_setting_wireless (connection);
775 if (!s_wireless) {
776 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
777 "Missing '%s' setting", NM_SETTING_WIRELESS_SETTING_NAME);
778 return FALSE;
779 }
780
781 svSetValue (ifcfg, "HWADDR", NULL, FALSE);
782 device_mac = nm_setting_wireless_get_mac_address (s_wireless);
783 if (device_mac) {
784 tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
785 device_mac->data[0], device_mac->data[1], device_mac->data[2],
786 device_mac->data[3], device_mac->data[4], device_mac->data[5]);
787 svSetValue (ifcfg, "HWADDR", tmp, FALSE);
788 g_free (tmp);
789 }
790
791 svSetValue (ifcfg, "MACADDR", NULL, FALSE);
792 cloned_mac = nm_setting_wireless_get_cloned_mac_address (s_wireless);
793 if (cloned_mac) {
794 tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
795 cloned_mac->data[0], cloned_mac->data[1], cloned_mac->data[2],
796 cloned_mac->data[3], cloned_mac->data[4], cloned_mac->data[5]);
797 svSetValue (ifcfg, "MACADDR", tmp, FALSE);
798 g_free (tmp);
799 }
800
801 svSetValue (ifcfg, "HWADDR_BLACKLIST", NULL, FALSE);
802 macaddr_blacklist = nm_setting_wireless_get_mac_address_blacklist (s_wireless);
803 if (macaddr_blacklist) {
804 const GSList *iter;
805 GString *blacklist_str = g_string_new (NULL);
806
807 for (iter = macaddr_blacklist; iter; iter = g_slist_next (iter)) {
808 g_string_append (blacklist_str, iter->data);
809 g_string_append_c (blacklist_str, ' ');
810
811 }
812 if (blacklist_str->len > 0)
813 g_string_truncate (blacklist_str, blacklist_str->len - 1);
814 svSetValue (ifcfg, "HWADDR_BLACKLIST", blacklist_str->str, FALSE);
815 g_string_free (blacklist_str, TRUE);
816 }
817
818 svSetValue (ifcfg, "MTU", NULL, FALSE);
819 mtu = nm_setting_wireless_get_mtu (s_wireless);
820 if (mtu) {
821 tmp = g_strdup_printf ("%u", mtu);
822 svSetValue (ifcfg, "MTU", tmp, FALSE);
823 g_free (tmp);
824 }
825
826 ssid = nm_setting_wireless_get_ssid (s_wireless);
827 if (!ssid) {
828 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
829 "Missing SSID in '%s' setting", NM_SETTING_WIRELESS_SETTING_NAME);
830 return FALSE;
831 }
832 if (!ssid->len || ssid->len > 32) {
833 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
834 "Invalid SSID in '%s' setting", NM_SETTING_WIRELESS_SETTING_NAME);
835 return FALSE;
836 }
837
838 /* If the SSID contains any non-printable characters, we need to use the
839 * hex notation of the SSID instead.
840 */
841 for (i = 0; i < ssid->len; i++) {
842 if (!g_ascii_isprint (ssid->data[i])) {
843 hex_ssid = TRUE;
844 break;
845 }
846 }
847
848 if (hex_ssid) {
849 GString *str;
850
851 /* Hex SSIDs don't get quoted */
852 str = g_string_sized_new (ssid->len * 2 + 3);
853 g_string_append (str, "0x");
854 for (i = 0; i < ssid->len; i++)
855 g_string_append_printf (str, "%02X", ssid->data[i]);
856 svSetValue (ifcfg, "ESSID", str->str, TRUE);
857 g_string_free (str, TRUE);
858 } else {
859 /* Printable SSIDs always get quoted */
860 memset (buf, 0, sizeof (buf));
861 memcpy (buf, ssid->data, ssid->len);
862 tmp = svEscape (buf);
863
864 /* svEscape will usually quote the string, but just for consistency,
865 * if svEscape doesn't quote the ESSID, we quote it ourselves.
866 */
867 if (tmp[0] != '"' && tmp[strlen (tmp) - 1] != '"') {
868 tmp2 = g_strdup_printf ("\"%s\"", tmp);
869 svSetValue (ifcfg, "ESSID", tmp2, TRUE);
870 g_free (tmp2);
871 } else
872 svSetValue (ifcfg, "ESSID", tmp, TRUE);
873 g_free (tmp);
874 }
875
876 mode = nm_setting_wireless_get_mode (s_wireless);
877 if (!mode || !strcmp (mode, "infrastructure")) {
878 svSetValue (ifcfg, "MODE", "Managed", FALSE);
879 } else if (!strcmp (mode, "adhoc")) {
880 svSetValue (ifcfg, "MODE", "Ad-Hoc", FALSE);
881 adhoc = TRUE;
882 } else {
883 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
884 "Invalid mode '%s' in '%s' setting",
885 mode, NM_SETTING_WIRELESS_SETTING_NAME);
886 return FALSE;
887 }
888
889 svSetValue (ifcfg, "CHANNEL", NULL, FALSE);
890 chan = nm_setting_wireless_get_channel (s_wireless);
891 if (chan) {
892 tmp = g_strdup_printf ("%u", chan);
893 svSetValue (ifcfg, "CHANNEL", tmp, FALSE);
894 g_free (tmp);
895 }
896
897 svSetValue (ifcfg, "BSSID", NULL, FALSE);
898 bssid = nm_setting_wireless_get_bssid (s_wireless);
899 if (bssid) {
900 tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
901 bssid->data[0], bssid->data[1], bssid->data[2],
902 bssid->data[3], bssid->data[4], bssid->data[5]);
903 svSetValue (ifcfg, "BSSID", tmp, FALSE);
904 g_free (tmp);
905 }
906
907 /* Ensure DEFAULTKEY and SECURITYMODE are cleared unless there's security;
908 * otherwise there's no way to detect WEP vs. open when WEP keys aren't
909 * saved.
910 */
911 svSetValue (ifcfg, "DEFAULTKEY", NULL, FALSE);
912 svSetValue (ifcfg, "SECURITYMODE", NULL, FALSE);
913
914 if (nm_connection_get_setting_wireless_security (connection)) {
915 if (!write_wireless_security_setting (connection, ifcfg, adhoc, no_8021x, error))
916 return FALSE;
917 } else {
918 char *keys_path;
919
920 /* Clear out wifi security keys */
921 svSetValue (ifcfg, "KEY_MGMT", NULL, FALSE);
922 svSetValue (ifcfg, "IEEE_8021X_IDENTITY", NULL, FALSE);
923 set_secret (ifcfg, "IEEE_8021X_PASSWORD", NULL, "IEEE_8021X_PASSWORD_FLAGS", NM_SETTING_SECRET_FLAG_NONE, FALSE);
924 svSetValue (ifcfg, "SECURITYMODE", NULL, FALSE);
925
926 /* Clear existing keys */
927 set_secret (ifcfg, "KEY", NULL, "WEP_KEY_FLAGS", NM_SETTING_SECRET_FLAG_NONE, FALSE);
928 for (i = 0; i < 4; i++) {
929 tmp = g_strdup_printf ("KEY_PASSPHRASE%d", i + 1);
930 set_secret (ifcfg, tmp, NULL, "WEP_KEY_FLAGS", NM_SETTING_SECRET_FLAG_NONE, FALSE);
931 g_free (tmp);
932
933 tmp = g_strdup_printf ("KEY%d", i + 1);
934 set_secret (ifcfg, tmp, NULL, "WEP_KEY_FLAGS", NM_SETTING_SECRET_FLAG_NONE, FALSE);
935 g_free (tmp);
936 }
937
938 svSetValue (ifcfg, "DEFAULTKEY", NULL, FALSE);
939 svSetValue (ifcfg, "WPA_ALLOW_WPA", NULL, FALSE);
940 svSetValue (ifcfg, "WPA_ALLOW_WPA2", NULL, FALSE);
941 svSetValue (ifcfg, "CIPHER_PAIRWISE", NULL, FALSE);
942 svSetValue (ifcfg, "CIPHER_GROUP", NULL, FALSE);
943 set_secret (ifcfg, "WPA_PSK", NULL, "WPA_PSK_FLAGS", NM_SETTING_SECRET_FLAG_NONE, FALSE);
944
945 /* Kill any old keys file */
946 keys_path = utils_get_keys_path (ifcfg->fileName);
947 (void) unlink (keys_path);
948 g_free (keys_path);
949 }
950
951 svSetValue (ifcfg, "TYPE", TYPE_WIRELESS, FALSE);
952
953 return TRUE;
954 }
955
956 static gboolean
957 write_infiniband_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
958 {
959 NMSettingInfiniband *s_infiniband;
960 const GByteArray *mac;
961 char *tmp;
962 const char *transport_mode, *parent;
963 guint32 mtu;
964 int p_key;
965
966 s_infiniband = nm_connection_get_setting_infiniband (connection);
967 if (!s_infiniband) {
968 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
969 "Missing '%s' setting", NM_SETTING_INFINIBAND_SETTING_NAME);
970 return FALSE;
971 }
972
973 svSetValue (ifcfg, "HWADDR", NULL, FALSE);
974 mac = nm_setting_infiniband_get_mac_address (s_infiniband);
975 if (mac) {
976 tmp = nm_utils_hwaddr_ntoa (mac->data, ARPHRD_INFINIBAND);
977 svSetValue (ifcfg, "HWADDR", tmp, FALSE);
978 g_free (tmp);
979 }
980
981 svSetValue (ifcfg, "MTU", NULL, FALSE);
982 mtu = nm_setting_infiniband_get_mtu (s_infiniband);
983 if (mtu) {
984 tmp = g_strdup_printf ("%u", mtu);
985 svSetValue (ifcfg, "MTU", tmp, FALSE);
986 g_free (tmp);
987 }
988
989 transport_mode = nm_setting_infiniband_get_transport_mode (s_infiniband);
990 svSetValue (ifcfg, "CONNECTED_MODE",
991 strcmp (transport_mode, "connected") == 0 ? "yes" : "no",
992 FALSE);
993
994 p_key = nm_setting_infiniband_get_p_key (s_infiniband);
995 if (p_key != -1) {
996 svSetValue (ifcfg, "PKEY", "yes", FALSE);
997 tmp = g_strdup_printf ("%u", p_key);
998 svSetValue (ifcfg, "PKEY_ID", tmp, FALSE);
999 g_free (tmp);
1000
1001 parent = nm_setting_infiniband_get_parent (s_infiniband);
1002 if (parent)
1003 svSetValue (ifcfg, "PHYSDEV", parent, FALSE);
1004 }
1005
1006 svSetValue (ifcfg, "TYPE", TYPE_INFINIBAND, FALSE);
1007
1008 return TRUE;
1009 }
1010
1011 static gboolean
1012 write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
1013 {
1014 NMSettingWired *s_wired;
1015 const GByteArray *device_mac, *cloned_mac;
1016 char *tmp;
1017 const char *nettype, *portname, *ctcprot, *s390_key, *s390_val;
1018 guint32 mtu, num_opts, i;
1019 const GPtrArray *s390_subchannels;
1020 GString *str;
1021 const GSList *macaddr_blacklist;
1022
1023 s_wired = nm_connection_get_setting_wired (connection);
1024 if (!s_wired) {
1025 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
1026 "Missing '%s' setting", NM_SETTING_WIRED_SETTING_NAME);
1027 return FALSE;
1028 }
1029
1030 svSetValue (ifcfg, "HWADDR", NULL, FALSE);
1031 device_mac = nm_setting_wired_get_mac_address (s_wired);
1032 if (device_mac) {
1033 tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
1034 device_mac->data[0], device_mac->data[1], device_mac->data[2],
1035 device_mac->data[3], device_mac->data[4], device_mac->data[5]);
1036 svSetValue (ifcfg, "HWADDR", tmp, FALSE);
1037 g_free (tmp);
1038 }
1039
1040 svSetValue (ifcfg, "MACADDR", NULL, FALSE);
1041 cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
1042 if (cloned_mac) {
1043 tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
1044 cloned_mac->data[0], cloned_mac->data[1], cloned_mac->data[2],
1045 cloned_mac->data[3], cloned_mac->data[4], cloned_mac->data[5]);
1046 svSetValue (ifcfg, "MACADDR", tmp, FALSE);
1047 g_free (tmp);
1048 }
1049
1050 svSetValue (ifcfg, "HWADDR_BLACKLIST", NULL, FALSE);
1051 macaddr_blacklist = nm_setting_wired_get_mac_address_blacklist (s_wired);
1052 if (macaddr_blacklist) {
1053 const GSList *iter;
1054 GString *blacklist_str = g_string_new (NULL);
1055
1056 for (iter = macaddr_blacklist; iter; iter = g_slist_next (iter)) {
1057 g_string_append (blacklist_str, iter->data);
1058 g_string_append_c (blacklist_str, ' ');
1059
1060 }
1061 if (blacklist_str->len > 0)
1062 g_string_truncate (blacklist_str, blacklist_str->len - 1);
1063 svSetValue (ifcfg, "HWADDR_BLACKLIST", blacklist_str->str, FALSE);
1064 g_string_free (blacklist_str, TRUE);
1065 }
1066
1067 svSetValue (ifcfg, "MTU", NULL, FALSE);
1068 mtu = nm_setting_wired_get_mtu (s_wired);
1069 if (mtu) {
1070 tmp = g_strdup_printf ("%u", mtu);
1071 svSetValue (ifcfg, "MTU", tmp, FALSE);
1072 g_free (tmp);
1073 }
1074
1075 svSetValue (ifcfg, "SUBCHANNELS", NULL, FALSE);
1076 s390_subchannels = nm_setting_wired_get_s390_subchannels (s_wired);
1077 if (s390_subchannels) {
1078 tmp = NULL;
1079 if (s390_subchannels->len == 2) {
1080 tmp = g_strdup_printf ("%s,%s",
1081 (const char *) g_ptr_array_index (s390_subchannels, 0),
1082 (const char *) g_ptr_array_index (s390_subchannels, 1));
1083 } else if (s390_subchannels->len == 3) {
1084 tmp = g_strdup_printf ("%s,%s,%s",
1085 (const char *) g_ptr_array_index (s390_subchannels, 0),
1086 (const char *) g_ptr_array_index (s390_subchannels, 1),
1087 (const char *) g_ptr_array_index (s390_subchannels, 2));
1088 }
1089 svSetValue (ifcfg, "SUBCHANNELS", tmp, FALSE);
1090 g_free (tmp);
1091 }
1092
1093 svSetValue (ifcfg, "NETTYPE", NULL, FALSE);
1094 nettype = nm_setting_wired_get_s390_nettype (s_wired);
1095 if (nettype)
1096 svSetValue (ifcfg, "NETTYPE", nettype, FALSE);
1097
1098 svSetValue (ifcfg, "PORTNAME", NULL, FALSE);
1099 portname = nm_setting_wired_get_s390_option_by_key (s_wired, "portname");
1100 if (portname)
1101 svSetValue (ifcfg, "PORTNAME", portname, FALSE);
1102
1103 svSetValue (ifcfg, "CTCPROT", NULL, FALSE);
1104 ctcprot = nm_setting_wired_get_s390_option_by_key (s_wired, "ctcprot");
1105 if (ctcprot)
1106 svSetValue (ifcfg, "CTCPROT", ctcprot, FALSE);
1107
1108 svSetValue (ifcfg, "OPTIONS", NULL, FALSE);
1109 num_opts = nm_setting_wired_get_num_s390_options (s_wired);
1110 if (s390_subchannels && num_opts) {
1111 str = g_string_sized_new (30);
1112 for (i = 0; i < num_opts; i++) {
1113 nm_setting_wired_get_s390_option (s_wired, i, &s390_key, &s390_val);
1114
1115 /* portname is handled separately */
1116 if (!strcmp (s390_key, "portname") || !strcmp (s390_key, "ctcprot"))
1117 continue;
1118
1119 if (str->len)
1120 g_string_append_c (str, ' ');
1121 g_string_append_printf (str, "%s=%s", s390_key, s390_val);
1122 }
1123 if (str->len)
1124 svSetValue (ifcfg, "OPTIONS", str->str, FALSE);
1125 g_string_free (str, TRUE);
1126 }
1127
1128 svSetValue (ifcfg, "TYPE", TYPE_ETHERNET, FALSE);
1129
1130 return TRUE;
1131 }
1132
1133 static GString *
1134 vlan_priority_maplist_to_stringlist (NMSettingVlan *s_vlan, NMVlanPriorityMap map)
1135 {
1136 GSList *strlist = NULL, *iter;
1137 GString *value = NULL;
1138
1139 if (map == NM_VLAN_INGRESS_MAP)
1140 g_object_get (G_OBJECT (s_vlan), NM_SETTING_VLAN_INGRESS_PRIORITY_MAP, &strlist, NULL);
1141 else if (map == NM_VLAN_EGRESS_MAP)
1142 g_object_get (G_OBJECT (s_vlan), NM_SETTING_VLAN_EGRESS_PRIORITY_MAP, &strlist, NULL);
1143 else
1144 return NULL;
1145
1146 value = g_string_new ("");
1147 for (iter = strlist; iter; iter = g_slist_next (iter))
1148 g_string_append_printf (value, "%s%s", value->len ? "," : "", (const char *) iter->data);
1149
1150 g_slist_free_full (strlist, g_free);
1151
1152 return value;
1153 }
1154
1155 static gboolean
1156 write_vlan_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wired, GError **error)
1157 {
1158 NMSettingVlan *s_vlan;
1159 NMSettingConnection *s_con;
1160 NMSettingWired *s_wired;
1161 char *tmp;
1162 guint32 vlan_flags = 0;
1163 GString *text = NULL;
1164
1165 s_con = nm_connection_get_setting_connection (connection);
1166 if (!s_con) {
1167 g_set_error_literal (error, IFCFG_PLUGIN_ERROR, 0, "Missing connection setting");
1168 return FALSE;
1169 }
1170
1171 s_vlan = nm_connection_get_setting_vlan (connection);
1172 if (!s_vlan) {
1173 g_set_error_literal (error, IFCFG_PLUGIN_ERROR, 0, "Missing VLAN setting");
1174 return FALSE;
1175 }
1176
1177 svSetValue (ifcfg, "VLAN", "yes", FALSE);
1178 svSetValue (ifcfg, "TYPE", TYPE_VLAN, FALSE);
1179 svSetValue (ifcfg, "DEVICE", nm_setting_vlan_get_interface_name (s_vlan), FALSE);
1180 svSetValue (ifcfg, "PHYSDEV", nm_setting_vlan_get_parent (s_vlan), FALSE);
1181 svSetValue (ifcfg, "MASTER", nm_setting_connection_get_master (s_con), FALSE);
1182
1183 tmp = g_strdup_printf ("%d", nm_setting_vlan_get_id (s_vlan));
1184 svSetValue (ifcfg, "VLAN_ID", tmp, FALSE);
1185 g_free (tmp);
1186
1187 vlan_flags = nm_setting_vlan_get_flags (s_vlan);
1188 if (vlan_flags & NM_VLAN_FLAG_REORDER_HEADERS)
1189 svSetValue (ifcfg, "REORDER_HDR", "1", FALSE);
1190 else
1191 svSetValue (ifcfg, "REORDER_HDR", "0", FALSE);
1192
1193 svSetValue (ifcfg, "VLAN_FLAGS", NULL, FALSE);
1194 if (vlan_flags & NM_VLAN_FLAG_GVRP) {
1195 if (vlan_flags & NM_VLAN_FLAG_LOOSE_BINDING)
1196 svSetValue (ifcfg, "VLAN_FLAGS", "GVRP,LOOSE_BINDING", FALSE);
1197 else
1198 svSetValue (ifcfg, "VLAN_FLAGS", "GVRP", FALSE);
1199 } else if (vlan_flags & NM_VLAN_FLAG_LOOSE_BINDING)
1200 svSetValue (ifcfg, "VLAN_FLAGS", "LOOSE_BINDING", FALSE);
1201
1202 text = vlan_priority_maplist_to_stringlist (s_vlan, NM_VLAN_INGRESS_MAP);
1203 svSetValue (ifcfg, "VLAN_INGRESS_PRIORITY_MAP", text ? text->str : NULL, FALSE);
1204 if (text)
1205 g_string_free (text, TRUE);
1206
1207 text = vlan_priority_maplist_to_stringlist (s_vlan, NM_VLAN_EGRESS_MAP);
1208 svSetValue (ifcfg, "VLAN_EGRESS_PRIORITY_MAP", text ? text->str : NULL, FALSE);
1209 if (text)
1210 g_string_free (text, TRUE);
1211
1212 svSetValue (ifcfg, "HWADDR", NULL, FALSE);
1213 svSetValue (ifcfg, "MACADDR", NULL, FALSE);
1214 svSetValue (ifcfg, "MTU", NULL, FALSE);
1215
1216 s_wired = nm_connection_get_setting_wired (connection);
1217 if (s_wired) {
1218 const GByteArray *device_mac, *cloned_mac;
1219 guint32 mtu;
1220
1221 *wired = TRUE;
1222
1223 device_mac = nm_setting_wired_get_mac_address (s_wired);
1224 if (device_mac) {
1225 tmp = nm_utils_hwaddr_ntoa (device_mac->data, ARPHRD_ETHER);
1226 svSetValue (ifcfg, "HWADDR", tmp, FALSE);
1227 g_free (tmp);
1228 }
1229
1230 cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
1231 if (cloned_mac) {
1232 tmp = nm_utils_hwaddr_ntoa (cloned_mac->data, ARPHRD_ETHER);
1233 svSetValue (ifcfg, "MACADDR", tmp, FALSE);
1234 g_free (tmp);
1235 }
1236
1237 mtu = nm_setting_wired_get_mtu (s_wired);
1238 if (mtu) {
1239 tmp = g_strdup_printf ("%u", mtu);
1240 svSetValue (ifcfg, "MTU", tmp, FALSE);
1241 g_free (tmp);
1242 }
1243 }
1244
1245 return TRUE;
1246 }
1247
1248 static gboolean
1249 write_bonding_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
1250 {
1251 NMSettingBond *s_bond;
1252 const char *iface;
1253 guint32 i, num_opts;
1254
1255 s_bond = nm_connection_get_setting_bond (connection);
1256 if (!s_bond) {
1257 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
1258 "Missing '%s' setting", NM_SETTING_BOND_SETTING_NAME);
1259 return FALSE;
1260 }
1261
1262 iface = nm_setting_bond_get_interface_name (s_bond);
1263 if (!iface) {
1264 g_set_error (error, IFCFG_PLUGIN_ERROR, 0, "Missing interface name");
1265 return FALSE;
1266 }
1267
1268 svSetValue (ifcfg, "DEVICE", iface, FALSE);
1269 svSetValue (ifcfg, "BONDING_OPTS", NULL, FALSE);
1270
1271 num_opts = nm_setting_bond_get_num_options (s_bond);
1272 if (num_opts > 0) {
1273 GString *str = g_string_sized_new (64);
1274
1275 for (i = 0; i < nm_setting_bond_get_num_options (s_bond); i++) {
1276 const char *key, *value;
1277
1278 if (!nm_setting_bond_get_option (s_bond, i, &key, &value))
1279 continue;
1280
1281 if (str->len)
1282 g_string_append_c (str, ' ');
1283
1284 g_string_append_printf (str, "%s=%s", key, value);
1285 }
1286
1287 if (str->len)
1288 svSetValue (ifcfg, "BONDING_OPTS", str->str, FALSE);
1289
1290 g_string_free (str, TRUE);
1291 }
1292
1293 svSetValue (ifcfg, "TYPE", TYPE_BOND, FALSE);
1294 svSetValue (ifcfg, "BONDING_MASTER", "yes", FALSE);
1295
1296 return TRUE;
1297 }
1298
1299 static gboolean
1300 write_team_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
1301 {
1302 NMSettingTeam *s_team;
1303 const char *iface;
1304 const char *config;
1305
1306 s_team = nm_connection_get_setting_team (connection);
1307 if (!s_team) {
1308 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
1309 "Missing '%s' setting", NM_SETTING_TEAM_SETTING_NAME);
1310 return FALSE;
1311 }
1312
1313 iface = nm_setting_team_get_interface_name (s_team);
1314 if (!iface) {
1315 g_set_error (error, IFCFG_PLUGIN_ERROR, 0, "Missing interface name");
1316 return FALSE;
1317 }
1318
1319 svSetValue (ifcfg, "DEVICE", iface, FALSE);
1320 config = nm_setting_team_get_config (s_team);
1321 svSetValue (ifcfg, "TEAM_CONFIG", config, FALSE);
1322 svSetValue (ifcfg, "DEVICETYPE", TYPE_TEAM, FALSE);
1323
1324 return TRUE;
1325 }
1326
1327 static guint32
1328 get_setting_default (NMSetting *setting, const char *prop)
1329 {
1330 GParamSpec *pspec;
1331 GValue val = G_VALUE_INIT;
1332 guint32 ret = 0;
1333
1334 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), prop);
1335 g_assert (pspec);
1336 g_value_init (&val, pspec->value_type);
1337 g_param_value_set_default (pspec, &val);
1338 g_assert (G_VALUE_HOLDS_UINT (&val));
1339 ret = g_value_get_uint (&val);
1340 g_value_unset (&val);
1341 return ret;
1342 }
1343
1344 static gboolean
1345 write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
1346 {
1347 NMSettingBridge *s_bridge;
1348 const char *iface;
1349 guint32 i;
1350 GString *opts;
1351 char *s;
1352
1353 s_bridge = nm_connection_get_setting_bridge (connection);
1354 if (!s_bridge) {
1355 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
1356 "Missing '%s' setting", NM_SETTING_BRIDGE_SETTING_NAME);
1357 return FALSE;
1358 }
1359
1360 iface = nm_setting_bridge_get_interface_name (s_bridge);
1361 if (!iface) {
1362 g_set_error (error, IFCFG_PLUGIN_ERROR, 0, "Missing interface name");
1363 return FALSE;
1364 }
1365
1366 svSetValue (ifcfg, "DEVICE", iface, FALSE);
1367 svSetValue (ifcfg, "BRIDGING_OPTS", NULL, FALSE);
1368 svSetValue (ifcfg, "STP", "no", FALSE);
1369 svSetValue (ifcfg, "DELAY", NULL, FALSE);
1370
1371 /* Bridge options */
1372 opts = g_string_sized_new (32);
1373
1374 if (nm_setting_bridge_get_stp (s_bridge)) {
1375 svSetValue (ifcfg, "STP", "yes", FALSE);
1376
1377 i = nm_setting_bridge_get_forward_delay (s_bridge);
1378 if (i && i != get_setting_default (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_FORWARD_DELAY)) {
1379 s = g_strdup_printf ("%u", i);
1380 svSetValue (ifcfg, "DELAY", s, FALSE);
1381 g_free (s);
1382 }
1383
1384 g_string_append_printf (opts, "priority=%u", nm_setting_bridge_get_priority (s_bridge));
1385
1386 i = nm_setting_bridge_get_hello_time (s_bridge);
1387 if (i && i != get_setting_default (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_HELLO_TIME)) {
1388 if (opts->len)
1389 g_string_append_c (opts, ' ');
1390 g_string_append_printf (opts, "hello_time=%u", i);
1391 }
1392
1393 i = nm_setting_bridge_get_max_age (s_bridge);
1394 if (i && i != get_setting_default (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_MAX_AGE)) {
1395 if (opts->len)
1396 g_string_append_c (opts, ' ');
1397 g_string_append_printf (opts, "max_age=%u", i);
1398 }
1399 }
1400
1401 i = nm_setting_bridge_get_ageing_time (s_bridge);
1402 if (i != get_setting_default (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_AGEING_TIME)) {
1403 if (opts->len)
1404 g_string_append_c (opts, ' ');
1405 g_string_append_printf (opts, "ageing_time=%u", i);
1406 }
1407
1408 if (opts->len)
1409 svSetValue (ifcfg, "BRIDGING_OPTS", opts->str, FALSE);
1410 g_string_free (opts, TRUE);
1411
1412 svSetValue (ifcfg, "TYPE", TYPE_BRIDGE, FALSE);
1413
1414 return TRUE;
1415 }
1416
1417 static gboolean
1418 write_bridge_port_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
1419 {
1420 NMSettingBridgePort *s_port;
1421 guint32 i;
1422 GString *opts;
1423
1424 s_port = nm_connection_get_setting_bridge_port (connection);
1425 if (!s_port)
1426 return TRUE;
1427
1428 svSetValue (ifcfg, "BRIDGING_OPTS", NULL, FALSE);
1429
1430 /* Bridge options */
1431 opts = g_string_sized_new (32);
1432
1433 i = nm_setting_bridge_port_get_priority (s_port);
1434 if (i && i != get_setting_default (NM_SETTING (s_port), NM_SETTING_BRIDGE_PORT_PRIORITY))
1435 g_string_append_printf (opts, "priority=%u", i);
1436
1437 i = nm_setting_bridge_port_get_path_cost (s_port);
1438 if (i && i != get_setting_default (NM_SETTING (s_port), NM_SETTING_BRIDGE_PORT_PATH_COST)) {
1439 if (opts->len)
1440 g_string_append_c (opts, ' ');
1441 g_string_append_printf (opts, "path_cost=%u", i);
1442 }
1443
1444 if (nm_setting_bridge_port_get_hairpin_mode (s_port)) {
1445 if (opts->len)
1446 g_string_append_c (opts, ' ');
1447 g_string_append_printf (opts, "hairpin_mode=1");
1448 }
1449
1450 if (opts->len)
1451 svSetValue (ifcfg, "BRIDGING_OPTS", opts->str, FALSE);
1452 g_string_free (opts, TRUE);
1453
1454 return TRUE;
1455 }
1456
1457 static gboolean
1458 write_team_port_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
1459 {
1460 NMSettingTeamPort *s_port;
1461 const char *config;
1462
1463 s_port = nm_connection_get_setting_team_port (connection);
1464 if (!s_port)
1465 return TRUE;
1466
1467 config = nm_setting_team_port_get_config (s_port);
1468 svSetValue (ifcfg, "TEAM_PORT_CONFIG", config, FALSE);
1469
1470 return TRUE;
1471 }
1472
1473 static void
1474 write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg)
1475 {
1476 guint32 n, i;
1477 GString *str;
1478 const char *master;
1479 char *tmp;
1480
1481 svSetValue (ifcfg, "NAME", nm_setting_connection_get_id (s_con), FALSE);
1482 svSetValue (ifcfg, "UUID", nm_setting_connection_get_uuid (s_con), FALSE);
1483 svSetValue (ifcfg, "DEVICE", nm_setting_connection_get_interface_name (s_con), FALSE);
1484 svSetValue (ifcfg, "ONBOOT",
1485 nm_setting_connection_get_autoconnect (s_con) ? "yes" : "no",
1486 FALSE);
1487
1488 /* Permissions */
1489 svSetValue (ifcfg, "USERS", NULL, FALSE);
1490 n = nm_setting_connection_get_num_permissions (s_con);
1491 if (n > 0) {
1492 str = g_string_sized_new (n * 20);
1493
1494 for (i = 0; i < n; i++) {
1495 const char *puser = NULL;
1496
1497 /* Items separated by space for consistency with eg
1498 * IPV6ADDR_SECONDARIES and DOMAIN.
1499 */
1500 if (str->len)
1501 g_string_append_c (str, ' ');
1502
1503 if (nm_setting_connection_get_permission (s_con, i, NULL, &puser, NULL))
1504 g_string_append (str, puser);
1505 }
1506 svSetValue (ifcfg, "USERS", str->str, FALSE);
1507 g_string_free (str, TRUE);
1508 }
1509
1510 svSetValue (ifcfg, "ZONE", nm_setting_connection_get_zone(s_con), FALSE);
1511
1512 master = nm_setting_connection_get_master (s_con);
1513 if (master) {
1514 if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_BOND_SETTING_NAME))
1515 svSetValue (ifcfg, "MASTER", master, FALSE);
1516 else if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_BRIDGE_SETTING_NAME))
1517 svSetValue (ifcfg, "BRIDGE", master, FALSE);
1518 else if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_TEAM_SETTING_NAME)) {
1519 svSetValue (ifcfg, "TEAM_MASTER", master, FALSE);
1520 svSetValue (ifcfg, "DEVICETYPE", TYPE_TEAM_PORT, FALSE);
1521 }
1522 }
1523
1524 /* secondary connection UUIDs */
1525 svSetValue (ifcfg, "SECONDARY_UUIDS", NULL, FALSE);
1526 n = nm_setting_connection_get_num_secondaries (s_con);
1527 if (n > 0) {
1528 str = g_string_sized_new (n * 37);
1529
1530 for (i = 0; i < n; i++) {
1531 const char *uuid;
1532
1533 /* Items separated by space for consistency with eg
1534 * IPV6ADDR_SECONDARIES and DOMAIN.
1535 */
1536 if (str->len)
1537 g_string_append_c (str, ' ');
1538
1539 if ((uuid = nm_setting_connection_get_secondary (s_con, i)) != NULL)
1540 g_string_append (str, uuid);
1541 }
1542 svSetValue (ifcfg, "SECONDARY_UUIDS", str->str, FALSE);
1543 g_string_free (str, TRUE);
1544 }
1545
1546 svSetValue (ifcfg, "GATEWAY_PING_TIMEOUT", NULL, FALSE);
1547 if (nm_setting_connection_get_gateway_ping_timeout (s_con)) {
1548 tmp = g_strdup_printf ("%" G_GUINT32_FORMAT, nm_setting_connection_get_gateway_ping_timeout (s_con));
1549 svSetValue (ifcfg, "GATEWAY_PING_TIMEOUT", tmp, FALSE);
1550 g_free (tmp);
1551 }
1552 }
1553
1554 static gboolean
1555 write_route_file_legacy (const char *filename, NMSettingIP4Config *s_ip4, GError **error)
1556 {
1557 char dest[INET_ADDRSTRLEN];
1558 char next_hop[INET_ADDRSTRLEN];
1559 char **route_items;
1560 char *route_contents;
1561 NMIP4Route *route;
1562 guint32 ip, prefix, metric;
1563 guint32 i, num;
1564 gboolean success = FALSE;
1565
1566 g_return_val_if_fail (filename != NULL, FALSE);
1567 g_return_val_if_fail (s_ip4 != NULL, FALSE);
1568 g_return_val_if_fail (error != NULL, FALSE);
1569 g_return_val_if_fail (*error == NULL, FALSE);
1570
1571 num = nm_setting_ip4_config_get_num_routes (s_ip4);
1572 if (num == 0) {
1573 unlink (filename);
1574 return TRUE;
1575 }
1576
1577 route_items = g_malloc0 (sizeof (char*) * (num + 1));
1578 for (i = 0; i < num; i++) {
1579 route = nm_setting_ip4_config_get_route (s_ip4, i);
1580
1581 memset (dest, 0, sizeof (dest));
1582 ip = nm_ip4_route_get_dest (route);
1583 inet_ntop (AF_INET, (const void *) &ip, &dest[0], sizeof (dest));
1584
1585 prefix = nm_ip4_route_get_prefix (route);
1586
1587 memset (next_hop, 0, sizeof (next_hop));
1588 ip = nm_ip4_route_get_next_hop (route);
1589 inet_ntop (AF_INET, (const void *) &ip, &next_hop[0], sizeof (next_hop));
1590
1591 metric = nm_ip4_route_get_metric (route);
1592
1593 route_items[i] = g_strdup_printf ("%s/%u via %s metric %u\n", dest, prefix, next_hop, metric);
1594 }
1595 route_items[num] = NULL;
1596 route_contents = g_strjoinv (NULL, route_items);
1597 g_strfreev (route_items);
1598
1599 if (!g_file_set_contents (filename, route_contents, -1, NULL)) {
1600 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
1601 "Writing route file '%s' failed", filename);
1602 goto error;
1603 }
1604
1605 success = TRUE;
1606
1607 error:
1608 g_free (route_contents);
1609
1610 return success;
1611 }
1612
1613 static gboolean
1614 write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
1615 {
1616 NMSettingIP4Config *s_ip4;
1617 const char *value;
1618 char *addr_key, *prefix_key, *netmask_key, *gw_key, *metric_key, *tmp;
1619 char *route_path = NULL;
1620 gint32 j;
1621 guint32 i, num;
1622 GString *searches;
1623 gboolean success = FALSE;
1624 gboolean fake_ip4 = FALSE;
1625 const char *method = NULL;
1626
1627 s_ip4 = nm_connection_get_setting_ip4_config (connection);
1628 if (s_ip4)
1629 method = nm_setting_ip4_config_get_method (s_ip4);
1630
1631 /* Missing IP4 setting is assumed to be DHCP */
1632 if (!method)
1633 method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
1634
1635 if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) {
1636 int result;
1637
1638 /* IPv4 disabled, clear IPv4 related parameters */
1639 svSetValue (ifcfg, "BOOTPROTO", NULL, FALSE);
1640 for (j = -1; j < 256; j++) {
1641 if (j == -1) {
1642 addr_key = g_strdup ("IPADDR");
1643 prefix_key = g_strdup ("PREFIX");
1644 netmask_key = g_strdup ("NETMASK");
1645 gw_key = g_strdup ("GATEWAY");
1646 } else {
1647 addr_key = g_strdup_printf ("IPADDR%d", j);
1648 prefix_key = g_strdup_printf ("PREFIX%d", j);
1649 netmask_key = g_strdup_printf ("NETMASK%d", j);
1650 gw_key = g_strdup_printf ("GATEWAY%d", j);
1651 }
1652
1653 svSetValue (ifcfg, addr_key, NULL, FALSE);
1654 svSetValue (ifcfg, prefix_key, NULL, FALSE);
1655 svSetValue (ifcfg, netmask_key, NULL, FALSE);
1656 svSetValue (ifcfg, gw_key, NULL, FALSE);
1657
1658 g_free (addr_key);
1659 g_free (prefix_key);
1660 g_free (netmask_key);
1661 g_free (gw_key);
1662 }
1663
1664 route_path = utils_get_route_path (ifcfg->fileName);
1665 result = unlink (route_path);
1666 g_free (route_path);
1667 return TRUE;
1668 }
1669
1670 /* Temporarily create fake IP4 setting if missing; method set to DHCP above */
1671 if (!s_ip4) {
1672 s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
1673 fake_ip4 = TRUE;
1674 }
1675
1676 if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO))
1677 svSetValue (ifcfg, "BOOTPROTO", "dhcp", FALSE);
1678 else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL))
1679 svSetValue (ifcfg, "BOOTPROTO", "none", FALSE);
1680 else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL))
1681 svSetValue (ifcfg, "BOOTPROTO", "autoip", FALSE);
1682 else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED))
1683 svSetValue (ifcfg, "BOOTPROTO", "shared", FALSE);
1684
1685 /* Write out IPADDR0 .. IPADDR255, PREFIX0 .. PREFIX255, GATEWAY0 .. GATEWAY255
1686 * Possible NETMASK<n> is removed only (it's obsolete) */
1687 num = nm_setting_ip4_config_get_num_addresses (s_ip4);
1688 svSetValue (ifcfg, "IPADDR", NULL, FALSE);
1689 svSetValue (ifcfg, "PREFIX", NULL, FALSE);
1690 svSetValue (ifcfg, "NETMASK", NULL, FALSE);
1691 svSetValue (ifcfg, "GATEWAY", NULL, FALSE);
1692 for (i = 0; i < 256; i++) {
1693 char buf[INET_ADDRSTRLEN];
1694 NMIP4Address *addr;
1695 guint32 ip;
1696
1697 addr_key = g_strdup_printf ("IPADDR%d", i);
1698 prefix_key = g_strdup_printf ("PREFIX%d", i);
1699 netmask_key = g_strdup_printf ("NETMASK%d", i);
1700 gw_key = g_strdup_printf ("GATEWAY%d", i);
1701
1702 if (i >= num) {
1703 svSetValue (ifcfg, addr_key, NULL, FALSE);
1704 svSetValue (ifcfg, prefix_key, NULL, FALSE);
1705 svSetValue (ifcfg, netmask_key, NULL, FALSE);
1706 svSetValue (ifcfg, gw_key, NULL, FALSE);
1707 } else {
1708 addr = nm_setting_ip4_config_get_address (s_ip4, i);
1709
1710 memset (buf, 0, sizeof (buf));
1711 ip = nm_ip4_address_get_address (addr);
1712 inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
1713 svSetValue (ifcfg, addr_key, &buf[0], FALSE);
1714
1715 tmp = g_strdup_printf ("%u", nm_ip4_address_get_prefix (addr));
1716 svSetValue (ifcfg, prefix_key, tmp, FALSE);
1717 g_free (tmp);
1718
1719 if (nm_ip4_address_get_gateway (addr)) {
1720 memset (buf, 0, sizeof (buf));
1721 ip = nm_ip4_address_get_gateway (addr);
1722 inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
1723 svSetValue (ifcfg, gw_key, &buf[0], FALSE);
1724 } else
1725 svSetValue (ifcfg, gw_key, NULL, FALSE);
1726 }
1727
1728 g_free (addr_key);
1729 g_free (prefix_key);
1730 g_free (netmask_key);
1731 g_free (gw_key);
1732 }
1733
1734 num = nm_setting_ip4_config_get_num_dns (s_ip4);
1735 for (i = 0; i < 254; i++) {
1736 char buf[INET_ADDRSTRLEN + 1];
1737 guint32 ip;
1738
1739 addr_key = g_strdup_printf ("DNS%d", i + 1);
1740
1741 if (i >= num)
1742 svSetValue (ifcfg, addr_key, NULL, FALSE);
1743 else {
1744 ip = nm_setting_ip4_config_get_dns (s_ip4, i);
1745
1746 memset (buf, 0, sizeof (buf));
1747 inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
1748 svSetValue (ifcfg, addr_key, &buf[0], FALSE);
1749 }
1750 g_free (addr_key);
1751 }
1752
1753 num = nm_setting_ip4_config_get_num_dns_searches (s_ip4);
1754 if (num > 0) {
1755 searches = g_string_new (NULL);
1756 for (i = 0; i < num; i++) {
1757 if (i > 0)
1758 g_string_append_c (searches, ' ');
1759 g_string_append (searches, nm_setting_ip4_config_get_dns_search (s_ip4, i));
1760 }
1761 svSetValue (ifcfg, "DOMAIN", searches->str, FALSE);
1762 g_string_free (searches, TRUE);
1763 } else
1764 svSetValue (ifcfg, "DOMAIN", NULL, FALSE);
1765
1766 /* DEFROUTE; remember that it has the opposite meaning from never-default */
1767 svSetValue (ifcfg, "DEFROUTE",
1768 nm_setting_ip4_config_get_never_default (s_ip4) ? "no" : "yes",
1769 FALSE);
1770
1771 svSetValue (ifcfg, "PEERDNS", NULL, FALSE);
1772 svSetValue (ifcfg, "PEERROUTES", NULL, FALSE);
1773 svSetValue (ifcfg, "DHCP_CLIENT_ID", NULL, FALSE);
1774 if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
1775 svSetValue (ifcfg, "PEERDNS",
1776 nm_setting_ip4_config_get_ignore_auto_dns (s_ip4) ? "no" : "yes",
1777 FALSE);
1778
1779 svSetValue (ifcfg, "PEERROUTES",
1780 nm_setting_ip4_config_get_ignore_auto_routes (s_ip4) ? "no" : "yes",
1781 FALSE);
1782
1783 value = nm_setting_ip4_config_get_dhcp_hostname (s_ip4);
1784 if (value)
1785 svSetValue (ifcfg, "DHCP_HOSTNAME", value, FALSE);
1786
1787 value = nm_setting_ip4_config_get_dhcp_client_id (s_ip4);
1788 if (value)
1789 svSetValue (ifcfg, "DHCP_CLIENT_ID", value, FALSE);
1790 }
1791
1792 svSetValue (ifcfg, "IPV4_FAILURE_FATAL",
1793 nm_setting_ip4_config_get_may_fail (s_ip4) ? "no" : "yes",
1794 FALSE);
1795
1796 /* Static routes - route-<name> file */
1797 route_path = utils_get_route_path (ifcfg->fileName);
1798 if (!route_path) {
1799 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
1800 "Could not get route file path for '%s'", ifcfg->fileName);
1801 goto out;
1802 }
1803
1804 if (utils_has_route_file_new_syntax (route_path)) {
1805 shvarFile *routefile;
1806
1807 routefile = utils_get_route_ifcfg (ifcfg->fileName, TRUE);
1808 if (!routefile) {
1809 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
1810 "Could not create route file '%s'", route_path);
1811 g_free (route_path);
1812 goto out;
1813 }
1814 g_free (route_path);
1815
1816 num = nm_setting_ip4_config_get_num_routes (s_ip4);
1817 for (i = 0; i < 256; i++) {
1818 char buf[INET_ADDRSTRLEN];
1819 NMIP4Route *route;
1820 guint32 ip, metric;
1821
1822 addr_key = g_strdup_printf ("ADDRESS%d", i);
1823 netmask_key = g_strdup_printf ("NETMASK%d", i);
1824 gw_key = g_strdup_printf ("GATEWAY%d", i);
1825 metric_key = g_strdup_printf ("METRIC%d", i);
1826
1827 if (i >= num) {
1828 svSetValue (routefile, addr_key, NULL, FALSE);
1829 svSetValue (routefile, netmask_key, NULL, FALSE);
1830 svSetValue (routefile, gw_key, NULL, FALSE);
1831 svSetValue (routefile, metric_key, NULL, FALSE);
1832 } else {
1833 route = nm_setting_ip4_config_get_route (s_ip4, i);
1834
1835 memset (buf, 0, sizeof (buf));
1836 ip = nm_ip4_route_get_dest (route);
1837 inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
1838 svSetValue (routefile, addr_key, &buf[0], FALSE);
1839
1840 memset (buf, 0, sizeof (buf));
1841 ip = nm_utils_ip4_prefix_to_netmask (nm_ip4_route_get_prefix (route));
1842 inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
1843 svSetValue (routefile, netmask_key, &buf[0], FALSE);
1844
1845 memset (buf, 0, sizeof (buf));
1846 ip = nm_ip4_route_get_next_hop (route);
1847 inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
1848 svSetValue (routefile, gw_key, &buf[0], FALSE);
1849
1850 memset (buf, 0, sizeof (buf));
1851 metric = nm_ip4_route_get_metric (route);
1852 if (metric == 0)
1853 svSetValue (routefile, metric_key, NULL, FALSE);
1854 else {
1855 tmp = g_strdup_printf ("%u", metric);
1856 svSetValue (routefile, metric_key, tmp, FALSE);
1857 g_free (tmp);
1858 }
1859 }
1860
1861 g_free (addr_key);
1862 g_free (netmask_key);
1863 g_free (gw_key);
1864 g_free (metric_key);
1865 }
1866 if (svWriteFile (routefile, 0644)) {
1867 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
1868 "Could not update route file '%s'", routefile->fileName);
1869 svCloseFile (routefile);
1870 goto out;
1871 }
1872 svCloseFile (routefile);
1873 } else {
1874 write_route_file_legacy (route_path, s_ip4, error);
1875 g_free (route_path);
1876 if (error && *error)
1877 goto out;
1878 }
1879
1880 success = TRUE;
1881
1882 out:
1883 if (fake_ip4)
1884 g_object_unref (s_ip4);
1885
1886 return success;
1887 }
1888
1889 static gboolean
1890 write_route6_file (const char *filename, NMSettingIP6Config *s_ip6, GError **error)
1891 {
1892 char dest[INET6_ADDRSTRLEN];
1893 char next_hop[INET6_ADDRSTRLEN];
1894 char **route_items;
1895 char *route_contents;
1896 NMIP6Route *route;
1897 const struct in6_addr *ip;
1898 guint32 prefix, metric;
1899 guint32 i, num;
1900 gboolean success = FALSE;
1901
1902 g_return_val_if_fail (filename != NULL, FALSE);
1903 g_return_val_if_fail (s_ip6 != NULL, FALSE);
1904 g_return_val_if_fail (error != NULL, FALSE);
1905 g_return_val_if_fail (*error == NULL, FALSE);
1906
1907 num = nm_setting_ip6_config_get_num_routes (s_ip6);
1908 if (num == 0) {
1909 unlink (filename);
1910 return TRUE;
1911 }
1912
1913 route_items = g_malloc0 (sizeof (char*) * (num + 1));
1914 for (i = 0; i < num; i++) {
1915 route = nm_setting_ip6_config_get_route (s_ip6, i);
1916
1917 memset (dest, 0, sizeof (dest));
1918 ip = nm_ip6_route_get_dest (route);
1919 inet_ntop (AF_INET6, (const void *) ip, &dest[0], sizeof (dest));
1920
1921 prefix = nm_ip6_route_get_prefix (route);
1922
1923 memset (next_hop, 0, sizeof (next_hop));
1924 ip = nm_ip6_route_get_next_hop (route);
1925 inet_ntop (AF_INET6, (const void *) ip, &next_hop[0], sizeof (next_hop));
1926
1927 metric = nm_ip6_route_get_metric (route);
1928
1929 route_items[i] = g_strdup_printf ("%s/%u via %s metric %u\n", dest, prefix, next_hop, metric);
1930 }
1931 route_items[num] = NULL;
1932 route_contents = g_strjoinv (NULL, route_items);
1933 g_strfreev (route_items);
1934
1935 if (!g_file_set_contents (filename, route_contents, -1, NULL)) {
1936 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
1937 "Writing route6 file '%s' failed", filename);
1938 goto error;
1939 }
1940
1941 success = TRUE;
1942
1943 error:
1944 g_free (route_contents);
1945 return success;
1946 }
1947
1948 static gboolean
1949 write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
1950 {
1951 NMSettingIP6Config *s_ip6;
1952 NMSettingIP4Config *s_ip4;
1953 const char *value;
1954 char *addr_key, *prefix;
1955 guint32 i, num, num4;
1956 GString *searches;
1957 char buf[INET6_ADDRSTRLEN];
1958 char ipv6_defaultgw[INET6_ADDRSTRLEN];
1959 NMIP6Address *addr;
1960 const struct in6_addr *ip;
1961 GString *ip_str1, *ip_str2, *ip_ptr;
1962 char *route6_path;
1963
1964 s_ip6 = nm_connection_get_setting_ip6_config (connection);
1965 if (!s_ip6) {
1966 /* Treat missing IPv6 setting as a setting with method "auto" */
1967 svSetValue (ifcfg, "IPV6INIT", "yes", FALSE);
1968 svSetValue (ifcfg, "IPV6_AUTOCONF", "yes", FALSE);
1969 svSetValue (ifcfg, "DHCPV6C", NULL, FALSE);
1970 svSetValue (ifcfg, "IPV6_DEFROUTE", "yes", FALSE);
1971 svSetValue (ifcfg, "IPV6_PEERDNS", "yes", FALSE);
1972 svSetValue (ifcfg, "IPV6_PEERROUTES", "yes", FALSE);
1973 svSetValue (ifcfg, "IPV6_FAILURE_FATAL", "no", FALSE);
1974 return TRUE;
1975 }
1976
1977 value = nm_setting_ip6_config_get_method (s_ip6);
1978 g_assert (value);
1979 if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) {
1980 svSetValue (ifcfg, "IPV6INIT", "no", FALSE);
1981 svSetValue (ifcfg, "DHCPV6C", NULL, FALSE);
1982 return TRUE;
1983 } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) {
1984 svSetValue (ifcfg, "IPV6INIT", "yes", FALSE);
1985 svSetValue (ifcfg, "IPV6_AUTOCONF", "yes", FALSE);
1986 svSetValue (ifcfg, "DHCPV6C", NULL, FALSE);
1987 } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) {
1988 const char *hostname;
1989 svSetValue (ifcfg, "IPV6INIT", "yes", FALSE);
1990 svSetValue (ifcfg, "IPV6_AUTOCONF", "no", FALSE);
1991 svSetValue (ifcfg, "DHCPV6C", "yes", FALSE);
1992 hostname = nm_setting_ip6_config_get_dhcp_hostname (s_ip6);
1993 if (hostname)
1994 svSetValue (ifcfg, "DHCP_HOSTNAME", hostname, FALSE);
1995 } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
1996 svSetValue (ifcfg, "IPV6INIT", "yes", FALSE);
1997 svSetValue (ifcfg, "IPV6_AUTOCONF", "no", FALSE);
1998 svSetValue (ifcfg, "DHCPV6C", NULL, FALSE);
1999 } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) {
2000 svSetValue (ifcfg, "IPV6INIT", "yes", FALSE);
2001 svSetValue (ifcfg, "IPV6_AUTOCONF", "no", FALSE);
2002 svSetValue (ifcfg, "DHCPV6C", NULL, FALSE);
2003 } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) {
2004 svSetValue (ifcfg, "IPV6INIT", "yes", FALSE);
2005 svSetValue (ifcfg, "DHCPV6C", NULL, FALSE);
2006 /* TODO */
2007 }
2008
2009 /* Write out IP addresses */
2010 num = nm_setting_ip6_config_get_num_addresses (s_ip6);
2011 ip_str1 = g_string_new (NULL);
2012 ip_str2 = g_string_new (NULL);
2013 ipv6_defaultgw[0] = 0;
2014 for (i = 0; i < num; i++) {
2015 if (i == 0)
2016 ip_ptr = ip_str1;
2017 else
2018 ip_ptr = ip_str2;
2019
2020 addr = nm_setting_ip6_config_get_address (s_ip6, i);
2021 ip = nm_ip6_address_get_address (addr);
2022 prefix = g_strdup_printf ("%u", nm_ip6_address_get_prefix (addr));
2023 memset (buf, 0, sizeof (buf));
2024 inet_ntop (AF_INET6, (const void *) ip, buf, sizeof (buf));
2025 if (i > 1)
2026 g_string_append_c (ip_ptr, ' '); /* separate addresses in IPV6ADDR_SECONDARIES */
2027 g_string_append (ip_ptr, buf);
2028 g_string_append_c (ip_ptr, '/');
2029 g_string_append (ip_ptr, prefix);
2030 g_free (prefix);
2031
2032 /* We only support gateway for the first IP address for now */
2033 if (i == 0) {
2034 ip = nm_ip6_address_get_gateway (addr);
2035 if (!IN6_IS_ADDR_UNSPECIFIED (ip))
2036 inet_ntop (AF_INET6, ip, ipv6_defaultgw, sizeof (ipv6_defaultgw));
2037 }
2038 }
2039 svSetValue (ifcfg, "IPV6ADDR", ip_str1->str, FALSE);
2040 svSetValue (ifcfg, "IPV6ADDR_SECONDARIES", ip_str2->str, FALSE);
2041 svSetValue (ifcfg, "IPV6_DEFAULTGW", ipv6_defaultgw, FALSE);
2042 g_string_free (ip_str1, TRUE);
2043 g_string_free (ip_str2, TRUE);
2044
2045 /* Write out DNS - 'DNS' key is used both for IPv4 and IPv6 */
2046 s_ip4 = nm_connection_get_setting_ip4_config (connection);
2047 num4 = s_ip4 ? nm_setting_ip4_config_get_num_dns (s_ip4) : 0; /* from where to start with IPv6 entries */
2048 num = nm_setting_ip6_config_get_num_dns (s_ip6);
2049 for (i = 0; i < 254; i++) {
2050 addr_key = g_strdup_printf ("DNS%d", i + num4 + 1);
2051
2052 if (i >= num)
2053 svSetValue (ifcfg, addr_key, NULL, FALSE);
2054 else {
2055 ip = nm_setting_ip6_config_get_dns (s_ip6, i);
2056
2057 memset (buf, 0, sizeof (buf));
2058 inet_ntop (AF_INET6, (const void *) ip, buf, sizeof (buf));
2059 svSetValue (ifcfg, addr_key, buf, FALSE);
2060 }
2061 g_free (addr_key);
2062 }
2063
2064 /* Write out DNS domains - 'DOMAIN' key is shared for both IPv4 and IPv6 domains */
2065 num = nm_setting_ip6_config_get_num_dns_searches (s_ip6);
2066 if (num > 0) {
2067 char *ip4_domains;
2068 ip4_domains = svGetValue (ifcfg, "DOMAIN", FALSE);
2069 searches = g_string_new (ip4_domains);
2070 for (i = 0; i < num; i++) {
2071 if (searches->len > 0)
2072 g_string_append_c (searches, ' ');
2073 g_string_append (searches, nm_setting_ip6_config_get_dns_search (s_ip6, i));
2074 }
2075 svSetValue (ifcfg, "DOMAIN", searches->str, FALSE);
2076 g_string_free (searches, TRUE);
2077 g_free (ip4_domains);
2078 }
2079
2080 /* handle IPV6_DEFROUTE */
2081 /* IPV6_DEFROUTE has the opposite meaning from 'never-default' */
2082 if (nm_setting_ip6_config_get_never_default(s_ip6))
2083 svSetValue (ifcfg, "IPV6_DEFROUTE", "no", FALSE);
2084 else
2085 svSetValue (ifcfg, "IPV6_DEFROUTE", "yes", FALSE);
2086
2087 svSetValue (ifcfg, "IPV6_PEERDNS", NULL, FALSE);
2088 svSetValue (ifcfg, "IPV6_PEERROUTES", NULL, FALSE);
2089 if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) {
2090 svSetValue (ifcfg, "IPV6_PEERDNS",
2091 nm_setting_ip6_config_get_ignore_auto_dns (s_ip6) ? "no" : "yes",
2092 FALSE);
2093
2094 svSetValue (ifcfg, "IPV6_PEERROUTES",
2095 nm_setting_ip6_config_get_ignore_auto_routes (s_ip6) ? "no" : "yes",
2096 FALSE);
2097 }
2098
2099 svSetValue (ifcfg, "IPV6_FAILURE_FATAL",
2100 nm_setting_ip6_config_get_may_fail (s_ip6) ? "no" : "yes",
2101 FALSE);
2102
2103 /* IPv6 Privacy Extensions */
2104 svSetValue (ifcfg, "IPV6_PRIVACY", NULL, FALSE);
2105 svSetValue (ifcfg, "IPV6_PRIVACY_PREFER_PUBLIC_IP", NULL, FALSE);
2106 switch (nm_setting_ip6_config_get_ip6_privacy (s_ip6)){
2107 case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED:
2108 svSetValue (ifcfg, "IPV6_PRIVACY", "no", FALSE);
2109 break;
2110 case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR:
2111 svSetValue (ifcfg, "IPV6_PRIVACY", "rfc3041", FALSE);
2112 svSetValue (ifcfg, "IPV6_PRIVACY_PREFER_PUBLIC_IP", "yes", FALSE);
2113 break;
2114 case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR:
2115 svSetValue (ifcfg, "IPV6_PRIVACY", "rfc3041", FALSE);
2116 break;
2117 default:
2118 break;
2119 }
2120
2121 /* Static routes go to route6-<dev> file */
2122 route6_path = utils_get_route6_path (ifcfg->fileName);
2123 if (!route6_path) {
2124 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
2125 "Could not get route6 file path for '%s'", ifcfg->fileName);
2126 goto error;
2127 }
2128 write_route6_file (route6_path, s_ip6, error);
2129 g_free (route6_path);
2130 if (error && *error)
2131 goto error;
2132
2133 return TRUE;
2134
2135 error:
2136 return FALSE;
2137 }
2138
2139 static char *
2140 escape_id (const char *id)
2141 {
2142 static const char const as_dash[] = "\\][|/=()!";
2143 char *escaped = g_strdup (id);
2144 char *p = escaped;
2145
2146 /* Escape random stuff */
2147 while (*p) {
2148 if (*p == ' ')
2149 *p = '_';
2150 else if (strchr (as_dash, *p))
2151 *p = '-';
2152 p++;
2153 }
2154
2155 return escaped;
2156 }
2157
2158 static gboolean
2159 write_connection (NMConnection *connection,
2160 const char *ifcfg_dir,
2161 const char *filename,
2162 const char *keyfile,
2163 char **out_filename,
2164 GError **error)
2165 {
2166 NMSettingConnection *s_con;
2167 gboolean success = FALSE;
2168 shvarFile *ifcfg = NULL;
2169 char *ifcfg_name = NULL;
2170 const char *type;
2171 gboolean no_8021x = FALSE;
2172 gboolean wired = FALSE;
2173
2174 if (!writer_can_write_connection (connection, error))
2175 return FALSE;
2176
2177 s_con = nm_connection_get_setting_connection (connection);
2178 g_assert (s_con);
2179
2180 if (filename) {
2181 /* For existing connections, 'filename' should be full path to ifcfg file */
2182 ifcfg = svNewFile (filename);
2183 ifcfg_name = g_strdup (filename);
2184 } else {
2185 char *escaped;
2186
2187 escaped = escape_id (nm_setting_connection_get_id (s_con));
2188 ifcfg_name = g_strdup_printf ("%s/ifcfg-%s", ifcfg_dir, escaped);
2189
2190 /* If a file with this path already exists then we need another name.
2191 * Multiple connections can have the same ID (ie if two connections with
2192 * the same ID are visible to different users) but of course can't have
2193 * the same path.
2194 */
2195 if (g_file_test (ifcfg_name, G_FILE_TEST_EXISTS)) {
2196 guint32 idx = 0;
2197
2198 g_free (ifcfg_name);
2199 while (idx++ < 500) {
2200 ifcfg_name = g_strdup_printf ("%s/ifcfg-%s-%u", ifcfg_dir, escaped, idx);
2201 if (g_file_test (ifcfg_name, G_FILE_TEST_EXISTS) == FALSE)
2202 break;
2203 g_free (ifcfg_name);
2204 ifcfg_name = NULL;
2205 }
2206 }
2207 g_free (escaped);
2208
2209 if (ifcfg_name == NULL) {
2210 g_set_error_literal (error, IFCFG_PLUGIN_ERROR, 0,
2211 "Failed to find usable ifcfg file name");
2212 return FALSE;
2213 }
2214
2215 ifcfg = svCreateFile (ifcfg_name);
2216 }
2217
2218 if (!ifcfg) {
2219 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
2220 "Failed to open/create ifcfg file '%s'", ifcfg_name);
2221 goto out;
2222 }
2223
2224 type = nm_setting_connection_get_connection_type (s_con);
2225 if (!type) {
2226 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
2227 "Missing connection type!");
2228 goto out;
2229 }
2230
2231 if (!strcmp (type, NM_SETTING_WIRED_SETTING_NAME)) {
2232 // FIXME: can't write PPPoE at this time
2233 if (nm_connection_get_setting_pppoe (connection)) {
2234 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
2235 "Can't write connection type '%s'",
2236 NM_SETTING_PPPOE_SETTING_NAME);
2237 goto out;
2238 }
2239
2240 if (!write_wired_setting (connection, ifcfg, error))
2241 goto out;
2242 wired = TRUE;
2243 } else if (!strcmp (type, NM_SETTING_VLAN_SETTING_NAME)) {
2244 if (!write_vlan_setting (connection, ifcfg, &wired, error))
2245 goto out;
2246 } else if (!strcmp (type, NM_SETTING_WIRELESS_SETTING_NAME)) {
2247 if (!write_wireless_setting (connection, ifcfg, &no_8021x, error))
2248 goto out;
2249 } else if (!strcmp (type, NM_SETTING_INFINIBAND_SETTING_NAME)) {
2250 if (!write_infiniband_setting (connection, ifcfg, error))
2251 goto out;
2252 } else if (!strcmp (type, NM_SETTING_BOND_SETTING_NAME)) {
2253 if (!write_bonding_setting (connection, ifcfg, error))
2254 goto out;
2255 } else if (!strcmp (type, NM_SETTING_TEAM_SETTING_NAME)) {
2256 if (!write_team_setting (connection, ifcfg, error))
2257 goto out;
2258 } else if (!strcmp (type, NM_SETTING_BRIDGE_SETTING_NAME)) {
2259 if (!write_bridge_setting (connection, ifcfg, error))
2260 goto out;
2261 } else {
2262 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
2263 "Can't write connection type '%s'", type);
2264 goto out;
2265 }
2266
2267 if (!no_8021x) {
2268 if (!write_8021x_setting (connection, ifcfg, wired, error))
2269 goto out;
2270 }
2271
2272 if (!write_bridge_port_setting (connection, ifcfg, error))
2273 goto out;
2274
2275 if (!write_team_port_setting (connection, ifcfg, error))
2276 goto out;
2277
2278 if (!utils_ignore_ip_config (connection)) {
2279 svSetValue (ifcfg, "DHCP_HOSTNAME", NULL, FALSE);
2280
2281 if (!write_ip4_setting (connection, ifcfg, error))
2282 goto out;
2283
2284 if (!write_ip6_setting (connection, ifcfg, error))
2285 goto out;
2286 }
2287
2288 write_connection_setting (s_con, ifcfg);
2289
2290 if (svWriteFile (ifcfg, 0644)) {
2291 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
2292 "Can't write connection '%s'", ifcfg->fileName);
2293 goto out;
2294 }
2295
2296 /* Only return the filename if this was a newly written ifcfg */
2297 if (out_filename && !filename)
2298 *out_filename = g_strdup (ifcfg_name);
2299
2300 success = TRUE;
2301
2302 out:
2303 if (ifcfg)
2304 svCloseFile (ifcfg);
2305 g_free (ifcfg_name);
2306 return success;
2307 }
2308
2309 gboolean
2310 writer_can_write_connection (NMConnection *connection, GError **error)
2311 {
2312 NMSettingConnection *s_con;
2313
2314 if ( ( nm_connection_is_type (connection, NM_SETTING_WIRED_SETTING_NAME)
2315 && !nm_connection_get_setting_pppoe (connection))
2316 || nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME)
2317 || nm_connection_is_type (connection, NM_SETTING_WIRELESS_SETTING_NAME)
2318 || nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME)
2319 || nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)
2320 || nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME)
2321 || nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME))
2322 return TRUE;
2323
2324 s_con = nm_connection_get_setting_connection (connection);
2325 g_assert (s_con);
2326 g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
2327 "The ifcfg-rh plugin cannot write the connection '%s' (type '%s' pppoe %d)",
2328 nm_connection_get_id (connection),
2329 nm_setting_connection_get_connection_type (s_con),
2330 !!nm_connection_get_setting_pppoe (connection));
2331 return FALSE;
2332 }
2333
2334 gboolean
2335 writer_new_connection (NMConnection *connection,
2336 const char *ifcfg_dir,
2337 char **out_filename,
2338 GError **error)
2339 {
2340 return write_connection (connection, ifcfg_dir, NULL, NULL, out_filename, error);
2341 }
2342
2343 gboolean
2344 writer_update_connection (NMConnection *connection,
2345 const char *ifcfg_dir,
2346 const char *filename,
2347 const char *keyfile,
2348 GError **error)
2349 {
2350 return write_connection (connection, ifcfg_dir, filename, keyfile, NULL, error);
2351 }
2352
2353