420 | 420 |
static void
|
421 | 421 |
write_network_file(net_definition* def, const char* rootdir, const char* path)
|
422 | 422 |
{
|
|
423 |
GString* network = NULL;
|
|
424 |
GString* link = NULL;
|
423 | 425 |
GString* s = NULL;
|
424 | 426 |
mode_t orig_umask;
|
425 | 427 |
|
426 | |
/* do we need to write a .network file? */
|
427 | |
if (!def->dhcp4 && !def->dhcp6 && !def->bridge && !def->bond &&
|
428 | |
!def->ip4_addresses && !def->ip6_addresses && !def->gateway4 && !def->gateway6 &&
|
429 | |
!def->ip4_nameservers && !def->ip6_nameservers && !def->has_vlans &&
|
430 | |
def->type < ND_VIRTUAL)
|
431 | |
return;
|
432 | |
|
433 | |
/* build file contents */
|
434 | |
s = g_string_sized_new(200);
|
435 | |
append_match_section(def, s, TRUE);
|
|
428 |
/* Prepare the [Link] section of the .network file. */
|
|
429 |
link = g_string_sized_new(200);
|
|
430 |
|
|
431 |
/* Prepare the [Network] section */
|
|
432 |
network = g_string_sized_new(200);
|
436 | 433 |
|
437 | 434 |
if (def->optional || def->optional_addresses) {
|
438 | |
g_string_append(s, "\n[Link]\n");
|
439 | 435 |
if (def->optional) {
|
440 | |
g_string_append(s, "RequiredForOnline=no\n");
|
|
436 |
g_string_append(link, "RequiredForOnline=no\n");
|
441 | 437 |
}
|
442 | 438 |
for (unsigned i = 0; optional_address_options[i].name != NULL; ++i) {
|
443 | 439 |
if (def->optional_addresses & optional_address_options[i].flag) {
|
444 | |
g_string_append_printf(s, "OptionalAddresses=%s\n", optional_address_options[i].name);
|
|
440 |
g_string_append_printf(link, "OptionalAddresses=%s\n", optional_address_options[i].name);
|
445 | 441 |
}
|
446 | 442 |
}
|
447 | 443 |
}
|
448 | 444 |
|
449 | |
g_string_append(s, "\n[Network]\n");
|
|
445 |
|
450 | 446 |
if (def->dhcp4 && def->dhcp6)
|
451 | |
g_string_append(s, "DHCP=yes\n");
|
|
447 |
g_string_append(network, "DHCP=yes\n");
|
452 | 448 |
else if (def->dhcp4)
|
453 | |
g_string_append(s, "DHCP=ipv4\n");
|
|
449 |
g_string_append(network, "DHCP=ipv4\n");
|
454 | 450 |
else if (def->dhcp6)
|
455 | |
g_string_append(s, "DHCP=ipv6\n");
|
|
451 |
g_string_append(network, "DHCP=ipv6\n");
|
456 | 452 |
|
457 | 453 |
/* Set link local addressing -- this does not apply to bond and bridge
|
458 | 454 |
* member interfaces, which always get it disabled.
|
459 | 455 |
*/
|
460 | 456 |
if (!def->bond && !def->bridge && (def->linklocal.ipv4 || def->linklocal.ipv6)) {
|
461 | 457 |
if (def->linklocal.ipv4 && def->linklocal.ipv6)
|
462 | |
g_string_append(s, "LinkLocalAddressing=yes\n");
|
|
458 |
g_string_append(network, "LinkLocalAddressing=yes\n");
|
463 | 459 |
else if (def->linklocal.ipv4)
|
464 | |
g_string_append(s, "LinkLocalAddressing=ipv4\n");
|
|
460 |
g_string_append(network, "LinkLocalAddressing=ipv4\n");
|
465 | 461 |
else if (def->linklocal.ipv6)
|
466 | |
g_string_append(s, "LinkLocalAddressing=ipv6\n");
|
|
462 |
g_string_append(network, "LinkLocalAddressing=ipv6\n");
|
467 | 463 |
} else {
|
468 | |
g_string_append(s, "LinkLocalAddressing=no\n");
|
|
464 |
g_string_append(network, "LinkLocalAddressing=no\n");
|
469 | 465 |
}
|
470 | 466 |
|
471 | 467 |
if (def->ip4_addresses)
|
472 | 468 |
for (unsigned i = 0; i < def->ip4_addresses->len; ++i)
|
473 | |
g_string_append_printf(s, "Address=%s\n", g_array_index(def->ip4_addresses, char*, i));
|
|
469 |
g_string_append_printf(network, "Address=%s\n", g_array_index(def->ip4_addresses, char*, i));
|
474 | 470 |
if (def->ip6_addresses)
|
475 | 471 |
for (unsigned i = 0; i < def->ip6_addresses->len; ++i)
|
476 | |
g_string_append_printf(s, "Address=%s\n", g_array_index(def->ip6_addresses, char*, i));
|
|
472 |
g_string_append_printf(network, "Address=%s\n", g_array_index(def->ip6_addresses, char*, i));
|
477 | 473 |
if (def->accept_ra == ACCEPT_RA_ENABLED)
|
478 | |
g_string_append_printf(s, "IPv6AcceptRA=yes\n");
|
|
474 |
g_string_append_printf(network, "IPv6AcceptRA=yes\n");
|
479 | 475 |
else if (def->accept_ra == ACCEPT_RA_DISABLED)
|
480 | |
g_string_append_printf(s, "IPv6AcceptRA=no\n");
|
|
476 |
g_string_append_printf(network, "IPv6AcceptRA=no\n");
|
481 | 477 |
if (def->ip6_privacy)
|
482 | |
g_string_append(s, "IPv6PrivacyExtensions=yes\n");
|
|
478 |
g_string_append(network, "IPv6PrivacyExtensions=yes\n");
|
483 | 479 |
if (def->gateway4)
|
484 | |
g_string_append_printf(s, "Gateway=%s\n", def->gateway4);
|
|
480 |
g_string_append_printf(network, "Gateway=%s\n", def->gateway4);
|
485 | 481 |
if (def->gateway6)
|
486 | |
g_string_append_printf(s, "Gateway=%s\n", def->gateway6);
|
|
482 |
g_string_append_printf(network, "Gateway=%s\n", def->gateway6);
|
487 | 483 |
if (def->ip4_nameservers)
|
488 | 484 |
for (unsigned i = 0; i < def->ip4_nameservers->len; ++i)
|
489 | |
g_string_append_printf(s, "DNS=%s\n", g_array_index(def->ip4_nameservers, char*, i));
|
|
485 |
g_string_append_printf(network, "DNS=%s\n", g_array_index(def->ip4_nameservers, char*, i));
|
490 | 486 |
if (def->ip6_nameservers)
|
491 | 487 |
for (unsigned i = 0; i < def->ip6_nameservers->len; ++i)
|
492 | |
g_string_append_printf(s, "DNS=%s\n", g_array_index(def->ip6_nameservers, char*, i));
|
|
488 |
g_string_append_printf(network, "DNS=%s\n", g_array_index(def->ip6_nameservers, char*, i));
|
493 | 489 |
if (def->search_domains) {
|
494 | |
g_string_append_printf(s, "Domains=%s", g_array_index(def->search_domains, char*, 0));
|
|
490 |
g_string_append_printf(network, "Domains=%s", g_array_index(def->search_domains, char*, 0));
|
495 | 491 |
for (unsigned i = 1; i < def->search_domains->len; ++i)
|
496 | |
g_string_append_printf(s, " %s", g_array_index(def->search_domains, char*, i));
|
497 | |
g_string_append(s, "\n");
|
|
492 |
g_string_append_printf(network, " %s", g_array_index(def->search_domains, char*, i));
|
|
493 |
g_string_append(network, "\n");
|
498 | 494 |
}
|
499 | 495 |
|
500 | 496 |
if (def->type >= ND_VIRTUAL)
|
501 | |
g_string_append(s, "ConfigureWithoutCarrier=yes\n");
|
|
497 |
g_string_append(network, "ConfigureWithoutCarrier=yes\n");
|
502 | 498 |
|
503 | 499 |
if (def->bridge) {
|
504 | |
g_string_append_printf(s, "Bridge=%s\n", def->bridge);
|
|
500 |
g_string_append_printf(network, "Bridge=%s\n", def->bridge);
|
505 | 501 |
|
506 | 502 |
if (def->bridge_params.path_cost || def->bridge_params.port_priority)
|
507 | |
g_string_append_printf(s, "\n[Bridge]\n");
|
|
503 |
g_string_append_printf(network, "\n[Bridge]\n");
|
508 | 504 |
if (def->bridge_params.path_cost)
|
509 | |
g_string_append_printf(s, "Cost=%u\n", def->bridge_params.path_cost);
|
|
505 |
g_string_append_printf(network, "Cost=%u\n", def->bridge_params.path_cost);
|
510 | 506 |
if (def->bridge_params.port_priority)
|
511 | |
g_string_append_printf(s, "Priority=%u\n", def->bridge_params.port_priority);
|
|
507 |
g_string_append_printf(network, "Priority=%u\n", def->bridge_params.port_priority);
|
512 | 508 |
}
|
513 | 509 |
if (def->bond) {
|
514 | |
g_string_append_printf(s, "Bond=%s\n", def->bond);
|
|
510 |
g_string_append_printf(network, "Bond=%s\n", def->bond);
|
515 | 511 |
|
516 | 512 |
if (def->bond_params.primary_slave)
|
517 | |
g_string_append_printf(s, "PrimarySlave=true\n");
|
|
513 |
g_string_append_printf(network, "PrimarySlave=true\n");
|
518 | 514 |
}
|
519 | 515 |
|
520 | 516 |
if (def->has_vlans) {
|
|
524 | 520 |
g_hash_table_iter_init(&i, netdefs);
|
525 | 521 |
while (g_hash_table_iter_next (&i, NULL, (gpointer*) &nd))
|
526 | 522 |
if (nd->vlan_link == def)
|
527 | |
g_string_append_printf(s, "VLAN=%s\n", nd->id);
|
|
523 |
g_string_append_printf(network, "VLAN=%s\n", nd->id);
|
528 | 524 |
}
|
529 | 525 |
|
530 | 526 |
if (def->routes != NULL) {
|
531 | 527 |
for (unsigned i = 0; i < def->routes->len; ++i) {
|
532 | 528 |
ip_route* cur_route = g_array_index (def->routes, ip_route*, i);
|
533 | |
write_route(cur_route, s);
|
|
529 |
write_route(cur_route, network);
|
534 | 530 |
}
|
535 | 531 |
}
|
536 | 532 |
if (def->ip_rules != NULL) {
|
537 | 533 |
for (unsigned i = 0; i < def->ip_rules->len; ++i) {
|
538 | 534 |
ip_rule* cur_rule = g_array_index (def->ip_rules, ip_rule*, i);
|
539 | |
write_ip_rule(cur_rule, s);
|
|
535 |
write_ip_rule(cur_rule, network);
|
540 | 536 |
}
|
541 | 537 |
}
|
542 | 538 |
|
543 | 539 |
if (def->dhcp4 || def->dhcp6) {
|
544 | 540 |
/* NetworkManager compatible route metrics */
|
545 | |
g_string_append(s, "\n[DHCP]\n");
|
|
541 |
g_string_append(network, "\n[DHCP]\n");
|
|
542 |
|
546 | 543 |
if (g_strcmp0(def->dhcp_identifier, "duid") != 0)
|
547 | |
g_string_append_printf(s, "ClientIdentifier=%s\n", def->dhcp_identifier);
|
|
544 |
g_string_append_printf(network, "ClientIdentifier=%s\n", def->dhcp_identifier);
|
548 | 545 |
if (def->critical)
|
549 | |
g_string_append_printf(s, "CriticalConnection=true\n");
|
|
546 |
g_string_append_printf(network, "CriticalConnection=true\n");
|
550 | 547 |
|
551 | 548 |
dhcp_overrides combined_dhcp_overrides;
|
552 | 549 |
combine_dhcp_overrides(def, &combined_dhcp_overrides);
|
553 | 550 |
|
554 | 551 |
if (combined_dhcp_overrides.metric == METRIC_UNSPEC) {
|
555 | |
g_string_append_printf(s, "RouteMetric=%i\n", (def->type == ND_WIFI ? 600 : 100));
|
|
552 |
g_string_append_printf(network, "RouteMetric=%i\n", (def->type == ND_WIFI ? 600 : 100));
|
556 | 553 |
} else {
|
557 | |
g_string_append_printf(s, "RouteMetric=%u\n",
|
|
554 |
g_string_append_printf(network, "RouteMetric=%u\n",
|
558 | 555 |
combined_dhcp_overrides.metric);
|
559 | 556 |
}
|
560 | 557 |
|
|
562 | 559 |
if (!combined_dhcp_overrides.use_mtu) {
|
563 | 560 |
/* isc-dhcp dhclient compatible UseMTU, networkd default is to
|
564 | 561 |
* not accept MTU, which breaks clouds */
|
565 | |
g_string_append_printf(s, "UseMTU=false\n");
|
|
562 |
g_string_append_printf(network, "UseMTU=false\n");
|
566 | 563 |
} else {
|
567 | |
g_string_append_printf(s, "UseMTU=true\n");
|
|
564 |
g_string_append_printf(network, "UseMTU=true\n");
|
568 | 565 |
}
|
569 | 566 |
|
570 | 567 |
/* Only write DHCP options that differ from the networkd default. */
|
571 | 568 |
if (!combined_dhcp_overrides.use_routes)
|
572 | |
g_string_append_printf(s, "UseRoutes=false\n");
|
|
569 |
g_string_append_printf(network, "UseRoutes=false\n");
|
573 | 570 |
if (!combined_dhcp_overrides.use_dns)
|
574 | |
g_string_append_printf(s, "UseDNS=false\n");
|
|
571 |
g_string_append_printf(network, "UseDNS=false\n");
|
575 | 572 |
if (!combined_dhcp_overrides.use_ntp)
|
576 | |
g_string_append_printf(s, "UseNTP=false\n");
|
|
573 |
g_string_append_printf(network, "UseNTP=false\n");
|
577 | 574 |
if (!combined_dhcp_overrides.send_hostname)
|
578 | |
g_string_append_printf(s, "SendHostname=false\n");
|
|
575 |
g_string_append_printf(network, "SendHostname=false\n");
|
579 | 576 |
if (!combined_dhcp_overrides.use_hostname)
|
580 | |
g_string_append_printf(s, "UseHostname=false\n");
|
|
577 |
g_string_append_printf(network, "UseHostname=false\n");
|
581 | 578 |
if (combined_dhcp_overrides.hostname)
|
582 | |
g_string_append_printf(s, "Hostname=%s\n", combined_dhcp_overrides.hostname);
|
583 | |
}
|
584 | |
|
585 | |
/* these do not contain secrets and need to be readable by
|
586 | |
* systemd-networkd - LP: #1736965 */
|
587 | |
orig_umask = umask(022);
|
588 | |
g_string_free_to_file(s, rootdir, path, ".network");
|
589 | |
umask(orig_umask);
|
|
579 |
g_string_append_printf(network, "Hostname=%s\n", combined_dhcp_overrides.hostname);
|
|
580 |
}
|
|
581 |
|
|
582 |
if (network->len > 0 || link->len > 0) {
|
|
583 |
s = g_string_sized_new(200);
|
|
584 |
append_match_section(def, s, TRUE);
|
|
585 |
|
|
586 |
if (link->len > 0)
|
|
587 |
g_string_append_printf(s, "\n[Link]\n%s", link->str);
|
|
588 |
if (network->len > 0)
|
|
589 |
g_string_append_printf(s, "\n[Network]\n%s", network->str);
|
|
590 |
|
|
591 |
g_string_free(link, TRUE);
|
|
592 |
g_string_free(network, TRUE);
|
|
593 |
|
|
594 |
/* these do not contain secrets and need to be readable by
|
|
595 |
* systemd-networkd - LP: #1736965 */
|
|
596 |
orig_umask = umask(022);
|
|
597 |
g_string_free_to_file(s, rootdir, path, ".network");
|
|
598 |
umask(orig_umask);
|
|
599 |
}
|
590 | 600 |
}
|
591 | 601 |
|
592 | 602 |
static void
|