1{ config, lib, pkgs, utils, ... }:
2
3with utils.systemdUtils.unitOptions;
4with utils.systemdUtils.lib;
5with lib;
6
7let
8
9 cfg = config.systemd.network;
10
11 check = {
12
13 global = {
14 sectionNetwork = checkUnitConfig "Network" [
15 (assertOnlyFields [
16 "SpeedMeter"
17 "SpeedMeterIntervalSec"
18 "ManageForeignRoutingPolicyRules"
19 "ManageForeignRoutes"
20 "RouteTable"
21 ])
22 (assertValueOneOf "SpeedMeter" boolValues)
23 (assertInt "SpeedMeterIntervalSec")
24 (assertValueOneOf "ManageForeignRoutingPolicyRules" boolValues)
25 (assertValueOneOf "ManageForeignRoutes" boolValues)
26 ];
27
28 sectionDHCPv4 = checkUnitConfig "DHCPv4" [
29 (assertOnlyFields [
30 "DUIDType"
31 "DUIDRawData"
32 ])
33 ];
34
35 sectionDHCPv6 = checkUnitConfig "DHCPv6" [
36 (assertOnlyFields [
37 "DUIDType"
38 "DUIDRawData"
39 ])
40 ];
41 };
42
43 link = {
44
45 sectionLink = checkUnitConfig "Link" [
46 (assertOnlyFields [
47 "Description"
48 "Alias"
49 "MACAddressPolicy"
50 "MACAddress"
51 "NamePolicy"
52 "Name"
53 "AlternativeNamesPolicy"
54 "AlternativeName"
55 "MTUBytes"
56 "BitsPerSecond"
57 "Duplex"
58 "AutoNegotiation"
59 "WakeOnLan"
60 "Port"
61 "Advertise"
62 "ReceiveChecksumOffload"
63 "TransmitChecksumOffload"
64 "TCPSegmentationOffload"
65 "TCP6SegmentationOffload"
66 "GenericSegmentationOffload"
67 "GenericReceiveOffload"
68 "LargeReceiveOffload"
69 "RxChannels"
70 "TxChannels"
71 "OtherChannels"
72 "CombinedChannels"
73 "RxBufferSize"
74 "TxBufferSize"
75 ])
76 (assertValueOneOf "MACAddressPolicy" ["persistent" "random" "none"])
77 (assertMacAddress "MACAddress")
78 (assertByteFormat "MTUBytes")
79 (assertByteFormat "BitsPerSecond")
80 (assertValueOneOf "Duplex" ["half" "full"])
81 (assertValueOneOf "AutoNegotiation" boolValues)
82 (assertValueOneOf "WakeOnLan" ["phy" "unicast" "multicast" "broadcast" "arp" "magic" "secureon" "off"])
83 (assertValueOneOf "Port" ["tp" "aui" "bnc" "mii" "fibre"])
84 (assertValueOneOf "ReceiveChecksumOffload" boolValues)
85 (assertValueOneOf "TransmitChecksumOffload" boolValues)
86 (assertValueOneOf "TCPSegmentationOffload" boolValues)
87 (assertValueOneOf "TCP6SegmentationOffload" boolValues)
88 (assertValueOneOf "GenericSegmentationOffload" boolValues)
89 (assertValueOneOf "GenericReceiveOffload" boolValues)
90 (assertValueOneOf "LargeReceiveOffload" boolValues)
91 (assertInt "RxChannels")
92 (assertRange "RxChannels" 1 4294967295)
93 (assertInt "TxChannels")
94 (assertRange "TxChannels" 1 4294967295)
95 (assertInt "OtherChannels")
96 (assertRange "OtherChannels" 1 4294967295)
97 (assertInt "CombinedChannels")
98 (assertRange "CombinedChannels" 1 4294967295)
99 (assertInt "RxBufferSize")
100 (assertInt "TxBufferSize")
101 ];
102 };
103
104 netdev = let
105
106 tunChecks = [
107 (assertOnlyFields [
108 "MultiQueue"
109 "PacketInfo"
110 "VNetHeader"
111 "User"
112 "Group"
113 ])
114 (assertValueOneOf "MultiQueue" boolValues)
115 (assertValueOneOf "PacketInfo" boolValues)
116 (assertValueOneOf "VNetHeader" boolValues)
117 ];
118 in {
119
120 sectionNetdev = checkUnitConfig "Netdev" [
121 (assertOnlyFields [
122 "Description"
123 "Name"
124 "Kind"
125 "MTUBytes"
126 "MACAddress"
127 ])
128 (assertHasField "Name")
129 (assertHasField "Kind")
130 (assertValueOneOf "Kind" [
131 "bond"
132 "bridge"
133 "dummy"
134 "gre"
135 "gretap"
136 "erspan"
137 "ip6gre"
138 "ip6tnl"
139 "ip6gretap"
140 "ipip"
141 "ipvlan"
142 "macvlan"
143 "macvtap"
144 "sit"
145 "tap"
146 "tun"
147 "veth"
148 "vlan"
149 "vti"
150 "vti6"
151 "vxlan"
152 "geneve"
153 "l2tp"
154 "macsec"
155 "vrf"
156 "vcan"
157 "vxcan"
158 "wireguard"
159 "netdevsim"
160 "nlmon"
161 "fou"
162 "xfrm"
163 "ifb"
164 "batadv"
165 ])
166 (assertByteFormat "MTUBytes")
167 (assertMacAddress "MACAddress")
168 ];
169
170 sectionVLAN = checkUnitConfig "VLAN" [
171 (assertOnlyFields [
172 "Id"
173 "GVRP"
174 "MVRP"
175 "LooseBinding"
176 "ReorderHeader"
177 ])
178 (assertInt "Id")
179 (assertRange "Id" 0 4094)
180 (assertValueOneOf "GVRP" boolValues)
181 (assertValueOneOf "MVRP" boolValues)
182 (assertValueOneOf "LooseBinding" boolValues)
183 (assertValueOneOf "ReorderHeader" boolValues)
184 ];
185
186 sectionMACVLAN = checkUnitConfig "MACVLAN" [
187 (assertOnlyFields [
188 "Mode"
189 ])
190 (assertValueOneOf "Mode" ["private" "vepa" "bridge" "passthru"])
191 ];
192
193 sectionVXLAN = checkUnitConfig "VXLAN" [
194 (assertOnlyFields [
195 "VNI"
196 "Remote"
197 "Local"
198 "Group"
199 "TOS"
200 "TTL"
201 "MacLearning"
202 "FDBAgeingSec"
203 "MaximumFDBEntries"
204 "ReduceARPProxy"
205 "L2MissNotification"
206 "L3MissNotification"
207 "RouteShortCircuit"
208 "UDPChecksum"
209 "UDP6ZeroChecksumTx"
210 "UDP6ZeroChecksumRx"
211 "RemoteChecksumTx"
212 "RemoteChecksumRx"
213 "GroupPolicyExtension"
214 "GenericProtocolExtension"
215 "DestinationPort"
216 "PortRange"
217 "FlowLabel"
218 "IPDoNotFragment"
219 ])
220 (assertInt "VNI")
221 (assertRange "VNI" 1 16777215)
222 (assertValueOneOf "MacLearning" boolValues)
223 (assertInt "MaximumFDBEntries")
224 (assertValueOneOf "ReduceARPProxy" boolValues)
225 (assertValueOneOf "L2MissNotification" boolValues)
226 (assertValueOneOf "L3MissNotification" boolValues)
227 (assertValueOneOf "RouteShortCircuit" boolValues)
228 (assertValueOneOf "UDPChecksum" boolValues)
229 (assertValueOneOf "UDP6ZeroChecksumTx" boolValues)
230 (assertValueOneOf "UDP6ZeroChecksumRx" boolValues)
231 (assertValueOneOf "RemoteChecksumTx" boolValues)
232 (assertValueOneOf "RemoteChecksumRx" boolValues)
233 (assertValueOneOf "GroupPolicyExtension" boolValues)
234 (assertValueOneOf "GenericProtocolExtension" boolValues)
235 (assertInt "FlowLabel")
236 (assertRange "FlowLabel" 0 1048575)
237 (assertValueOneOf "IPDoNotFragment" (boolValues + ["inherit"]))
238 ];
239
240 sectionTunnel = checkUnitConfig "Tunnel" [
241 (assertOnlyFields [
242 "Local"
243 "Remote"
244 "TOS"
245 "TTL"
246 "DiscoverPathMTU"
247 "IPv6FlowLabel"
248 "CopyDSCP"
249 "EncapsulationLimit"
250 "Key"
251 "InputKey"
252 "OutputKey"
253 "Mode"
254 "Independent"
255 "AssignToLoopback"
256 "AllowLocalRemote"
257 "FooOverUDP"
258 "FOUDestinationPort"
259 "FOUSourcePort"
260 "Encapsulation"
261 "IPv6RapidDeploymentPrefix"
262 "ISATAP"
263 "SerializeTunneledPackets"
264 "ERSPANIndex"
265 ])
266 (assertInt "TTL")
267 (assertRange "TTL" 0 255)
268 (assertValueOneOf "DiscoverPathMTU" boolValues)
269 (assertValueOneOf "CopyDSCP" boolValues)
270 (assertValueOneOf "Mode" ["ip6ip6" "ipip6" "any"])
271 (assertValueOneOf "Independent" boolValues)
272 (assertValueOneOf "AssignToLoopback" boolValues)
273 (assertValueOneOf "AllowLocalRemote" boolValues)
274 (assertValueOneOf "FooOverUDP" boolValues)
275 (assertPort "FOUDestinationPort")
276 (assertPort "FOUSourcePort")
277 (assertValueOneOf "Encapsulation" ["FooOverUDP" "GenericUDPEncapsulation"])
278 (assertValueOneOf "ISATAP" boolValues)
279 (assertValueOneOf "SerializeTunneledPackets" boolValues)
280 (assertInt "ERSPANIndex")
281 (assertRange "ERSPANIndex" 1 1048575)
282 ];
283
284 sectionFooOverUDP = checkUnitConfig "FooOverUDP" [
285 (assertOnlyFields [
286 "Port"
287 "Encapsulation"
288 "Protocol"
289 ])
290 (assertPort "Port")
291 (assertValueOneOf "Encapsulation" ["FooOverUDP" "GenericUDPEncapsulation"])
292 ];
293
294 sectionPeer = checkUnitConfig "Peer" [
295 (assertOnlyFields [
296 "Name"
297 "MACAddress"
298 ])
299 (assertMacAddress "MACAddress")
300 ];
301
302 sectionTun = checkUnitConfig "Tun" tunChecks;
303
304 sectionTap = checkUnitConfig "Tap" tunChecks;
305
306 # NOTE The PrivateKey directive is missing on purpose here, please
307 # do not add it to this list. The nix store is world-readable let's
308 # refrain ourselves from providing a footgun.
309 sectionWireGuard = checkUnitConfig "WireGuard" [
310 (assertOnlyFields [
311 "PrivateKeyFile"
312 "ListenPort"
313 "FirewallMark"
314 "RouteTable"
315 "RouteMetric"
316 ])
317 (assertInt "FirewallMark")
318 (assertRange "FirewallMark" 1 4294967295)
319 ];
320
321 # NOTE The PresharedKey directive is missing on purpose here, please
322 # do not add it to this list. The nix store is world-readable,let's
323 # refrain ourselves from providing a footgun.
324 sectionWireGuardPeer = checkUnitConfig "WireGuardPeer" [
325 (assertOnlyFields [
326 "PublicKey"
327 "PresharedKeyFile"
328 "AllowedIPs"
329 "Endpoint"
330 "PersistentKeepalive"
331 "RouteTable"
332 "RouteMetric"
333 ])
334 (assertInt "PersistentKeepalive")
335 (assertRange "PersistentKeepalive" 0 65535)
336 ];
337
338 sectionBond = checkUnitConfig "Bond" [
339 (assertOnlyFields [
340 "Mode"
341 "TransmitHashPolicy"
342 "LACPTransmitRate"
343 "MIIMonitorSec"
344 "UpDelaySec"
345 "DownDelaySec"
346 "LearnPacketIntervalSec"
347 "AdSelect"
348 "AdActorSystemPriority"
349 "AdUserPortKey"
350 "AdActorSystem"
351 "FailOverMACPolicy"
352 "ARPValidate"
353 "ARPIntervalSec"
354 "ARPIPTargets"
355 "ARPAllTargets"
356 "PrimaryReselectPolicy"
357 "ResendIGMP"
358 "PacketsPerSlave"
359 "GratuitousARP"
360 "AllSlavesActive"
361 "DynamicTransmitLoadBalancing"
362 "MinLinks"
363 ])
364 (assertValueOneOf "Mode" [
365 "balance-rr"
366 "active-backup"
367 "balance-xor"
368 "broadcast"
369 "802.3ad"
370 "balance-tlb"
371 "balance-alb"
372 ])
373 (assertValueOneOf "TransmitHashPolicy" [
374 "layer2"
375 "layer3+4"
376 "layer2+3"
377 "encap2+3"
378 "encap3+4"
379 ])
380 (assertValueOneOf "LACPTransmitRate" ["slow" "fast"])
381 (assertValueOneOf "AdSelect" ["stable" "bandwidth" "count"])
382 (assertInt "AdActorSystemPriority")
383 (assertRange "AdActorSystemPriority" 1 65535)
384 (assertInt "AdUserPortKey")
385 (assertRange "AdUserPortKey" 0 1023)
386 (assertValueOneOf "FailOverMACPolicy" ["none" "active" "follow"])
387 (assertValueOneOf "ARPValidate" ["none" "active" "backup" "all"])
388 (assertValueOneOf "ARPAllTargets" ["any" "all"])
389 (assertValueOneOf "PrimaryReselectPolicy" ["always" "better" "failure"])
390 (assertInt "ResendIGMP")
391 (assertRange "ResendIGMP" 0 255)
392 (assertInt "PacketsPerSlave")
393 (assertRange "PacketsPerSlave" 0 65535)
394 (assertInt "GratuitousARP")
395 (assertRange "GratuitousARP" 0 255)
396 (assertValueOneOf "AllSlavesActive" boolValues)
397 (assertValueOneOf "DynamicTransmitLoadBalancing" boolValues)
398 (assertInt "MinLinks")
399 (assertMinimum "MinLinks" 0)
400 ];
401
402 sectionXfrm = checkUnitConfig "Xfrm" [
403 (assertOnlyFields [
404 "InterfaceId"
405 "Independent"
406 ])
407 (assertInt "InterfaceId")
408 (assertRange "InterfaceId" 1 4294967295)
409 (assertValueOneOf "Independent" boolValues)
410 ];
411
412 sectionVRF = checkUnitConfig "VRF" [
413 (assertOnlyFields [
414 "Table"
415 ])
416 (assertInt "Table")
417 (assertMinimum "Table" 0)
418 ];
419
420 sectionBatmanAdvanced = checkUnitConfig "BatmanAdvanced" [
421 (assertOnlyFields [
422 "GatewayMode"
423 "Aggregation"
424 "BridgeLoopAvoidance"
425 "DistributedArpTable"
426 "Fragmentation"
427 "HopPenalty"
428 "OriginatorIntervalSec"
429 "GatewayBandwithDown"
430 "GatewayBandwithUp"
431 "RoutingAlgorithm"
432 ])
433 (assertValueOneOf "GatewayMode" ["off" "client" "server"])
434 (assertValueOneOf "Aggregation" boolValues)
435 (assertValueOneOf "BridgeLoopAvoidance" boolValues)
436 (assertValueOneOf "DistributedArpTable" boolValues)
437 (assertValueOneOf "Fragmentation" boolValues)
438 (assertInt "HopPenalty")
439 (assertRange "HopPenalty" 0 255)
440 (assertValueOneOf "RoutingAlgorithm" ["batman-v" "batman-iv"])
441 ];
442 };
443
444 network = {
445
446 sectionLink = checkUnitConfig "Link" [
447 (assertOnlyFields [
448 "MACAddress"
449 "MTUBytes"
450 "ARP"
451 "Multicast"
452 "AllMulticast"
453 "Unmanaged"
454 "Group"
455 "RequiredForOnline"
456 "RequiredFamilyForOnline"
457 "ActivationPolicy"
458 "Promiscuous"
459 ])
460 (assertMacAddress "MACAddress")
461 (assertByteFormat "MTUBytes")
462 (assertValueOneOf "ARP" boolValues)
463 (assertValueOneOf "Multicast" boolValues)
464 (assertValueOneOf "AllMulticast" boolValues)
465 (assertValueOneOf "Promiscuous" boolValues)
466 (assertValueOneOf "Unmanaged" boolValues)
467 (assertInt "Group")
468 (assertRange "Group" 0 2147483647)
469 (assertValueOneOf "RequiredForOnline" (boolValues ++ [
470 "missing"
471 "off"
472 "no-carrier"
473 "dormant"
474 "degraded-carrier"
475 "carrier"
476 "degraded"
477 "enslaved"
478 "routable"
479 ]))
480 (assertValueOneOf "RequiredFamilyForOnline" [
481 "ipv4"
482 "ipv6"
483 "both"
484 "any"
485 ])
486 (assertValueOneOf "ActivationPolicy" ([
487 "up"
488 "always-up"
489 "manual"
490 "always-down"
491 "down"
492 "bound"
493 ]))
494 ];
495
496 sectionNetwork = checkUnitConfig "Network" [
497 (assertOnlyFields [
498 "Description"
499 "DHCP"
500 "DHCPServer"
501 "LinkLocalAddressing"
502 "IPv4LLRoute"
503 "DefaultRouteOnDevice"
504 "LLMNR"
505 "MulticastDNS"
506 "DNSOverTLS"
507 "DNSSEC"
508 "DNSSECNegativeTrustAnchors"
509 "LLDP"
510 "EmitLLDP"
511 "BindCarrier"
512 "Address"
513 "Gateway"
514 "DNS"
515 "Domains"
516 "DNSDefaultRoute"
517 "NTP"
518 "IPForward"
519 "IPMasquerade"
520 "IPv6PrivacyExtensions"
521 "IPv6AcceptRA"
522 "IPv6DuplicateAddressDetection"
523 "IPv6HopLimit"
524 "IPv4ProxyARP"
525 "IPv6ProxyNDP"
526 "IPv6ProxyNDPAddress"
527 "IPv6SendRA"
528 "DHCPPrefixDelegation"
529 "IPv6MTUBytes"
530 "Bridge"
531 "Bond"
532 "VRF"
533 "VLAN"
534 "IPVLAN"
535 "MACVLAN"
536 "VXLAN"
537 "Tunnel"
538 "MACsec"
539 "ActiveSlave"
540 "PrimarySlave"
541 "ConfigureWithoutCarrier"
542 "IgnoreCarrierLoss"
543 "Xfrm"
544 "KeepConfiguration"
545 "BatmanAdvanced"
546 ])
547 # Note: For DHCP the values both, none, v4, v6 are deprecated
548 (assertValueOneOf "DHCP" ["yes" "no" "ipv4" "ipv6"])
549 (assertValueOneOf "DHCPServer" boolValues)
550 (assertValueOneOf "LinkLocalAddressing" ["yes" "no" "ipv4" "ipv6" "fallback" "ipv4-fallback"])
551 (assertValueOneOf "IPv4LLRoute" boolValues)
552 (assertValueOneOf "DefaultRouteOnDevice" boolValues)
553 (assertValueOneOf "LLMNR" (boolValues ++ ["resolve"]))
554 (assertValueOneOf "MulticastDNS" (boolValues ++ ["resolve"]))
555 (assertValueOneOf "DNSOverTLS" (boolValues ++ ["opportunistic"]))
556 (assertValueOneOf "DNSSEC" (boolValues ++ ["allow-downgrade"]))
557 (assertValueOneOf "LLDP" (boolValues ++ ["routers-only"]))
558 (assertValueOneOf "EmitLLDP" (boolValues ++ ["nearest-bridge" "non-tpmr-bridge" "customer-bridge"]))
559 (assertValueOneOf "DNSDefaultRoute" boolValues)
560 (assertValueOneOf "IPForward" (boolValues ++ ["ipv4" "ipv6"]))
561 (assertValueOneOf "IPMasquerade" (boolValues ++ ["ipv4" "ipv6" "both"]))
562 (assertValueOneOf "IPv6PrivacyExtensions" (boolValues ++ ["prefer-public" "kernel"]))
563 (assertValueOneOf "IPv6AcceptRA" boolValues)
564 (assertInt "IPv6DuplicateAddressDetection")
565 (assertMinimum "IPv6DuplicateAddressDetection" 0)
566 (assertInt "IPv6HopLimit")
567 (assertMinimum "IPv6HopLimit" 0)
568 (assertValueOneOf "IPv4ProxyARP" boolValues)
569 (assertValueOneOf "IPv6ProxyNDP" boolValues)
570 (assertValueOneOf "IPv6SendRA" boolValues)
571 (assertValueOneOf "DHCPPrefixDelegation" boolValues)
572 (assertByteFormat "IPv6MTUBytes")
573 (assertValueOneOf "ActiveSlave" boolValues)
574 (assertValueOneOf "PrimarySlave" boolValues)
575 (assertValueOneOf "ConfigureWithoutCarrier" boolValues)
576 (assertValueOneOf "KeepConfiguration" (boolValues ++ ["static" "dhcp-on-stop" "dhcp"]))
577 ];
578
579 sectionAddress = checkUnitConfig "Address" [
580 (assertOnlyFields [
581 "Address"
582 "Peer"
583 "Broadcast"
584 "Label"
585 "PreferredLifetime"
586 "Scope"
587 "RouteMetric"
588 "HomeAddress"
589 "DuplicateAddressDetection"
590 "ManageTemporaryAddress"
591 "AddPrefixRoute"
592 "AutoJoin"
593 ])
594 (assertHasField "Address")
595 (assertValueOneOf "PreferredLifetime" ["forever" "infinity" "0" 0])
596 (assertInt "RouteMetric")
597 (assertValueOneOf "HomeAddress" boolValues)
598 (assertValueOneOf "DuplicateAddressDetection" ["ipv4" "ipv6" "both" "none"])
599 (assertValueOneOf "ManageTemporaryAddress" boolValues)
600 (assertValueOneOf "AddPrefixRoute" boolValues)
601 (assertValueOneOf "AutoJoin" boolValues)
602 ];
603
604 sectionRoutingPolicyRule = checkUnitConfig "RoutingPolicyRule" [
605 (assertOnlyFields [
606 "TypeOfService"
607 "From"
608 "To"
609 "FirewallMark"
610 "Table"
611 "Priority"
612 "IncomingInterface"
613 "OutgoingInterface"
614 "SourcePort"
615 "DestinationPort"
616 "IPProtocol"
617 "InvertRule"
618 "Family"
619 "User"
620 "SuppressPrefixLength"
621 "Type"
622 "SuppressInterfaceGroup"
623 ])
624 (assertInt "TypeOfService")
625 (assertRange "TypeOfService" 0 255)
626 (assertInt "FirewallMark")
627 (assertRange "FirewallMark" 1 4294967295)
628 (assertInt "Priority")
629 (assertPort "SourcePort")
630 (assertPort "DestinationPort")
631 (assertValueOneOf "InvertRule" boolValues)
632 (assertValueOneOf "Family" ["ipv4" "ipv6" "both"])
633 (assertInt "SuppressPrefixLength")
634 (assertRange "SuppressPrefixLength" 0 128)
635 (assertValueOneOf "Type" ["blackhole" "unreachable" "prohibit"])
636 (assertRange "SuppressInterfaceGroup" 0 2147483647)
637 ];
638
639 sectionRoute = checkUnitConfig "Route" [
640 (assertOnlyFields [
641 "Gateway"
642 "GatewayOnLink"
643 "Destination"
644 "Source"
645 "Metric"
646 "IPv6Preference"
647 "Scope"
648 "PreferredSource"
649 "Table"
650 "Protocol"
651 "Type"
652 "InitialCongestionWindow"
653 "InitialAdvertisedReceiveWindow"
654 "QuickAck"
655 "FastOpenNoCookie"
656 "TTLPropagate"
657 "MTUBytes"
658 "IPServiceType"
659 "MultiPathRoute"
660 ])
661 (assertValueOneOf "GatewayOnLink" boolValues)
662 (assertInt "Metric")
663 (assertValueOneOf "IPv6Preference" ["low" "medium" "high"])
664 (assertValueOneOf "Scope" ["global" "site" "link" "host" "nowhere"])
665 (assertValueOneOf "Type" [
666 "unicast"
667 "local"
668 "broadcast"
669 "anycast"
670 "multicast"
671 "blackhole"
672 "unreachable"
673 "prohibit"
674 "throw"
675 "nat"
676 "xresolve"
677 ])
678 (assertValueOneOf "QuickAck" boolValues)
679 (assertValueOneOf "FastOpenNoCookie" boolValues)
680 (assertValueOneOf "TTLPropagate" boolValues)
681 (assertByteFormat "MTUBytes")
682 (assertValueOneOf "IPServiceType" ["CS6" "CS4"])
683 ];
684
685 sectionDHCPv4 = checkUnitConfig "DHCPv4" [
686 (assertOnlyFields [
687 "UseDNS"
688 "RoutesToDNS"
689 "UseNTP"
690 "UseSIP"
691 "UseMTU"
692 "Anonymize"
693 "SendHostname"
694 "UseHostname"
695 "Hostname"
696 "UseDomains"
697 "UseRoutes"
698 "UseTimezone"
699 "ClientIdentifier"
700 "VendorClassIdentifier"
701 "UserClass"
702 "MaxAttempts"
703 "DUIDType"
704 "DUIDRawData"
705 "IAID"
706 "RequestBroadcast"
707 "RouteMetric"
708 "RouteTable"
709 "RouteMTUBytes"
710 "ListenPort"
711 "SendRelease"
712 "SendDecline"
713 "BlackList"
714 "RequestOptions"
715 "SendOption"
716 "FallbackLeaseLifetimeSec"
717 "Label"
718 "Use6RD"
719 ])
720 (assertValueOneOf "UseDNS" boolValues)
721 (assertValueOneOf "RoutesToDNS" boolValues)
722 (assertValueOneOf "UseNTP" boolValues)
723 (assertValueOneOf "UseSIP" boolValues)
724 (assertValueOneOf "UseMTU" boolValues)
725 (assertValueOneOf "Anonymize" boolValues)
726 (assertValueOneOf "SendHostname" boolValues)
727 (assertValueOneOf "UseHostname" boolValues)
728 (assertValueOneOf "UseDomains" (boolValues ++ ["route"]))
729 (assertValueOneOf "UseRoutes" boolValues)
730 (assertValueOneOf "UseTimezone" boolValues)
731 (assertValueOneOf "ClientIdentifier" ["mac" "duid" "duid-only"])
732 (assertInt "IAID")
733 (assertValueOneOf "RequestBroadcast" boolValues)
734 (assertInt "RouteMetric")
735 (assertInt "RouteTable")
736 (assertRange "RouteTable" 0 4294967295)
737 (assertByteFormat "RouteMTUBytes")
738 (assertPort "ListenPort")
739 (assertValueOneOf "SendRelease" boolValues)
740 (assertValueOneOf "SendDecline" boolValues)
741 (assertValueOneOf "FallbackLeaseLifetimeSec" ["forever" "infinity"])
742 (assertValueOneOf "Use6RD" boolValues)
743 ];
744
745 sectionDHCPv6 = checkUnitConfig "DHCPv6" [
746 (assertOnlyFields [
747 "UseAddress"
748 "UseDNS"
749 "UseNTP"
750 "RouteMetric"
751 "RapidCommit"
752 "MUDURL"
753 "RequestOptions"
754 "SendVendorOption"
755 "PrefixDelegationHint"
756 "WithoutRA"
757 "SendOption"
758 "UserClass"
759 "VendorClass"
760 "DUIDType"
761 "DUIDRawData"
762 "IAID"
763 "UseDelegatedPrefix"
764 ])
765 (assertValueOneOf "UseAddress" boolValues)
766 (assertValueOneOf "UseDNS" boolValues)
767 (assertValueOneOf "UseNTP" boolValues)
768 (assertInt "RouteMetric")
769 (assertValueOneOf "RapidCommit" boolValues)
770 (assertValueOneOf "WithoutRA" ["no" "solicit" "information-request"])
771 (assertRange "SendOption" 1 65536)
772 (assertInt "IAID")
773 (assertValueOneOf "UseDelegatedPrefix" boolValues)
774 ];
775
776 sectionDHCPPrefixDelegation = checkUnitConfig "DHCPPrefixDelegation" [
777 (assertOnlyFields [
778 "UplinkInterface"
779 "SubnetId"
780 "Announce"
781 "Assign"
782 "Token"
783 "ManageTemporaryAddress"
784 "RouteMetric"
785 ])
786 (assertValueOneOf "Announce" boolValues)
787 (assertValueOneOf "Assign" boolValues)
788 (assertValueOneOf "ManageTemporaryAddress" boolValues)
789 (assertRange "RouteMetric" 0 4294967295)
790 ];
791
792 sectionIPv6AcceptRA = checkUnitConfig "IPv6AcceptRA" [
793 (assertOnlyFields [
794 "UseDNS"
795 "UseDomains"
796 "RouteTable"
797 "UseAutonomousPrefix"
798 "UseOnLinkPrefix"
799 "RouterDenyList"
800 "RouterAllowList"
801 "PrefixDenyList"
802 "PrefixAllowList"
803 "RouteDenyList"
804 "RouteAllowList"
805 "DHCPv6Client"
806 "RouteMetric"
807 "UseMTU"
808 "UseGateway"
809 "UseRoutePrefix"
810 "Token"
811 ])
812 (assertValueOneOf "UseDNS" boolValues)
813 (assertValueOneOf "UseDomains" (boolValues ++ ["route"]))
814 (assertRange "RouteTable" 0 4294967295)
815 (assertValueOneOf "UseAutonomousPrefix" boolValues)
816 (assertValueOneOf "UseOnLinkPrefix" boolValues)
817 (assertValueOneOf "DHCPv6Client" (boolValues ++ ["always"]))
818 (assertValueOneOf "UseMTU" boolValues)
819 (assertValueOneOf "UseGateway" boolValues)
820 (assertValueOneOf "UseRoutePrefix" boolValues)
821 ];
822
823 sectionDHCPServer = checkUnitConfig "DHCPServer" [
824 (assertOnlyFields [
825 "ServerAddress"
826 "PoolOffset"
827 "PoolSize"
828 "DefaultLeaseTimeSec"
829 "MaxLeaseTimeSec"
830 "UplinkInterface"
831 "EmitDNS"
832 "DNS"
833 "EmitNTP"
834 "NTP"
835 "EmitSIP"
836 "SIP"
837 "EmitPOP3"
838 "POP3"
839 "EmitSMTP"
840 "SMTP"
841 "EmitLPR"
842 "LPR"
843 "EmitRouter"
844 "Router"
845 "EmitTimezone"
846 "Timezone"
847 "SendOption"
848 "SendVendorOption"
849 "BindToInterface"
850 "RelayTarget"
851 "RelayAgentCircuitId"
852 "RelayAgentRemoteId"
853 ])
854 (assertInt "PoolOffset")
855 (assertMinimum "PoolOffset" 0)
856 (assertInt "PoolSize")
857 (assertMinimum "PoolSize" 0)
858 (assertValueOneOf "EmitDNS" boolValues)
859 (assertValueOneOf "EmitNTP" boolValues)
860 (assertValueOneOf "EmitSIP" boolValues)
861 (assertValueOneOf "EmitPOP3" boolValues)
862 (assertValueOneOf "EmitSMTP" boolValues)
863 (assertValueOneOf "EmitLPR" boolValues)
864 (assertValueOneOf "EmitRouter" boolValues)
865 (assertValueOneOf "EmitTimezone" boolValues)
866 (assertValueOneOf "BindToInterface" boolValues)
867 ];
868
869 sectionIPv6SendRA = checkUnitConfig "IPv6SendRA" [
870 (assertOnlyFields [
871 "Managed"
872 "OtherInformation"
873 "RouterLifetimeSec"
874 "RouterPreference"
875 "UplinkInterface"
876 "EmitDNS"
877 "DNS"
878 "EmitDomains"
879 "Domains"
880 "DNSLifetimeSec"
881 ])
882 (assertValueOneOf "Managed" boolValues)
883 (assertValueOneOf "OtherInformation" boolValues)
884 (assertValueOneOf "RouterPreference" ["high" "medium" "low" "normal" "default"])
885 (assertValueOneOf "EmitDNS" boolValues)
886 (assertValueOneOf "EmitDomains" boolValues)
887 ];
888
889 sectionIPv6Prefix = checkUnitConfig "IPv6Prefix" [
890 (assertOnlyFields [
891 "AddressAutoconfiguration"
892 "OnLink"
893 "Prefix"
894 "PreferredLifetimeSec"
895 "ValidLifetimeSec"
896 "Token"
897 ])
898 (assertValueOneOf "AddressAutoconfiguration" boolValues)
899 (assertValueOneOf "OnLink" boolValues)
900 ];
901
902 sectionIPv6RoutePrefix = checkUnitConfig "IPv6RoutePrefix" [
903 (assertOnlyFields [
904 "Route"
905 "LifetimeSec"
906 ])
907 (assertHasField "Route")
908 (assertInt "LifetimeSec")
909 ];
910
911 sectionDHCPServerStaticLease = checkUnitConfig "DHCPServerStaticLease" [
912 (assertOnlyFields [
913 "MACAddress"
914 "Address"
915 ])
916 (assertHasField "MACAddress")
917 (assertHasField "Address")
918 (assertMacAddress "MACAddress")
919 ];
920
921 };
922 };
923
924 commonNetworkOptions = {
925
926 enable = mkOption {
927 default = true;
928 type = types.bool;
929 description = lib.mdDoc ''
930 Whether to manage network configuration using {command}`systemd-network`.
931 '';
932 };
933
934 matchConfig = mkOption {
935 default = {};
936 example = { Name = "eth0"; };
937 type = types.attrsOf unitOption;
938 description = lib.mdDoc ''
939 Each attribute in this set specifies an option in the
940 `[Match]` section of the unit. See
941 {manpage}`systemd.link(5)`
942 {manpage}`systemd.netdev(5)`
943 {manpage}`systemd.network(5)`
944 for details.
945 '';
946 };
947
948 extraConfig = mkOption {
949 default = "";
950 type = types.lines;
951 description = lib.mdDoc "Extra configuration append to unit";
952 };
953 };
954
955 networkdOptions = {
956 networkConfig = mkOption {
957 default = {};
958 example = { SpeedMeter = true; ManageForeignRoutingPolicyRules = false; };
959 type = types.addCheck (types.attrsOf unitOption) check.global.sectionNetwork;
960 description = lib.mdDoc ''
961 Each attribute in this set specifies an option in the
962 `[Network]` section of the networkd config.
963 See {manpage}`networkd.conf(5)` for details.
964 '';
965 };
966
967 dhcpV4Config = mkOption {
968 default = {};
969 example = { DUIDType = "vendor"; };
970 type = types.addCheck (types.attrsOf unitOption) check.global.sectionDHCPv4;
971 description = lib.mdDoc ''
972 Each attribute in this set specifies an option in the
973 `[DHCPv4]` section of the networkd config.
974 See {manpage}`networkd.conf(5)` for details.
975 '';
976 };
977
978 dhcpV6Config = mkOption {
979 default = {};
980 example = { DUIDType = "vendor"; };
981 type = types.addCheck (types.attrsOf unitOption) check.global.sectionDHCPv6;
982 description = lib.mdDoc ''
983 Each attribute in this set specifies an option in the
984 `[DHCPv6]` section of the networkd config.
985 See {manpage}`networkd.conf(5)` for details.
986 '';
987 };
988 };
989
990 linkOptions = commonNetworkOptions // {
991 # overwrite enable option from above
992 enable = mkOption {
993 default = true;
994 type = types.bool;
995 description = lib.mdDoc ''
996 Whether to enable this .link unit. It's handled by udev no matter if {command}`systemd-networkd` is enabled or not
997 '';
998 };
999
1000 linkConfig = mkOption {
1001 default = {};
1002 example = { MACAddress = "00:ff:ee:aa:cc:dd"; };
1003 type = types.addCheck (types.attrsOf unitOption) check.link.sectionLink;
1004 description = lib.mdDoc ''
1005 Each attribute in this set specifies an option in the
1006 `[Link]` section of the unit. See
1007 {manpage}`systemd.link(5)` for details.
1008 '';
1009 };
1010
1011 };
1012
1013 wireguardPeerOptions = {
1014 options = {
1015 wireguardPeerConfig = mkOption {
1016 default = {};
1017 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionWireGuardPeer;
1018 description = lib.mdDoc ''
1019 Each attribute in this set specifies an option in the
1020 `[WireGuardPeer]` section of the unit. See
1021 {manpage}`systemd.network(5)` for details.
1022 '';
1023 };
1024 };
1025 };
1026
1027 netdevOptions = commonNetworkOptions // {
1028
1029 netdevConfig = mkOption {
1030 example = { Name = "mybridge"; Kind = "bridge"; };
1031 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionNetdev;
1032 description = lib.mdDoc ''
1033 Each attribute in this set specifies an option in the
1034 `[Netdev]` section of the unit. See
1035 {manpage}`systemd.netdev(5)` for details.
1036 '';
1037 };
1038
1039 vlanConfig = mkOption {
1040 default = {};
1041 example = { Id = 4; };
1042 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionVLAN;
1043 description = lib.mdDoc ''
1044 Each attribute in this set specifies an option in the
1045 `[VLAN]` section of the unit. See
1046 {manpage}`systemd.netdev(5)` for details.
1047 '';
1048 };
1049
1050 macvlanConfig = mkOption {
1051 default = {};
1052 example = { Mode = "private"; };
1053 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionMACVLAN;
1054 description = lib.mdDoc ''
1055 Each attribute in this set specifies an option in the
1056 `[MACVLAN]` section of the unit. See
1057 {manpage}`systemd.netdev(5)` for details.
1058 '';
1059 };
1060
1061 vxlanConfig = mkOption {
1062 default = {};
1063 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionVXLAN;
1064 description = lib.mdDoc ''
1065 Each attribute in this set specifies an option in the
1066 `[VXLAN]` section of the unit. See
1067 {manpage}`systemd.netdev(5)` for details.
1068 '';
1069 };
1070
1071 tunnelConfig = mkOption {
1072 default = {};
1073 example = { Remote = "192.168.1.1"; };
1074 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionTunnel;
1075 description = lib.mdDoc ''
1076 Each attribute in this set specifies an option in the
1077 `[Tunnel]` section of the unit. See
1078 {manpage}`systemd.netdev(5)` for details.
1079 '';
1080 };
1081
1082 fooOverUDPConfig = mkOption {
1083 default = { };
1084 example = { Port = 9001; };
1085 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionFooOverUDP;
1086 description = lib.mdDoc ''
1087 Each attribute in this set specifies an option in the
1088 `[FooOverUDP]` section of the unit. See
1089 {manpage}`systemd.netdev(5)` for details.
1090 '';
1091 };
1092
1093 peerConfig = mkOption {
1094 default = {};
1095 example = { Name = "veth2"; };
1096 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionPeer;
1097 description = lib.mdDoc ''
1098 Each attribute in this set specifies an option in the
1099 `[Peer]` section of the unit. See
1100 {manpage}`systemd.netdev(5)` for details.
1101 '';
1102 };
1103
1104 tunConfig = mkOption {
1105 default = {};
1106 example = { User = "openvpn"; };
1107 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionTun;
1108 description = lib.mdDoc ''
1109 Each attribute in this set specifies an option in the
1110 `[Tun]` section of the unit. See
1111 {manpage}`systemd.netdev(5)` for details.
1112 '';
1113 };
1114
1115 tapConfig = mkOption {
1116 default = {};
1117 example = { User = "openvpn"; };
1118 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionTap;
1119 description = lib.mdDoc ''
1120 Each attribute in this set specifies an option in the
1121 `[Tap]` section of the unit. See
1122 {manpage}`systemd.netdev(5)` for details.
1123 '';
1124 };
1125
1126 wireguardConfig = mkOption {
1127 default = {};
1128 example = {
1129 PrivateKeyFile = "/etc/wireguard/secret.key";
1130 ListenPort = 51820;
1131 FirewallMark = 42;
1132 };
1133 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionWireGuard;
1134 description = lib.mdDoc ''
1135 Each attribute in this set specifies an option in the
1136 `[WireGuard]` section of the unit. See
1137 {manpage}`systemd.netdev(5)` for details.
1138 Use `PrivateKeyFile` instead of
1139 `PrivateKey`: the nix store is
1140 world-readable.
1141 '';
1142 };
1143
1144 wireguardPeers = mkOption {
1145 default = [];
1146 example = [ { wireguardPeerConfig={
1147 Endpoint = "192.168.1.1:51820";
1148 PublicKey = "27s0OvaBBdHoJYkH9osZpjpgSOVNw+RaKfboT/Sfq0g=";
1149 PresharedKeyFile = "/etc/wireguard/psk.key";
1150 AllowedIPs = [ "10.0.0.1/32" ];
1151 PersistentKeepalive = 15;
1152 };}];
1153 type = with types; listOf (submodule wireguardPeerOptions);
1154 description = lib.mdDoc ''
1155 Each item in this array specifies an option in the
1156 `[WireGuardPeer]` section of the unit. See
1157 {manpage}`systemd.netdev(5)` for details.
1158 Use `PresharedKeyFile` instead of
1159 `PresharedKey`: the nix store is
1160 world-readable.
1161 '';
1162 };
1163
1164 bondConfig = mkOption {
1165 default = {};
1166 example = { Mode = "802.3ad"; };
1167 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionBond;
1168 description = lib.mdDoc ''
1169 Each attribute in this set specifies an option in the
1170 `[Bond]` section of the unit. See
1171 {manpage}`systemd.netdev(5)` for details.
1172 '';
1173 };
1174
1175 xfrmConfig = mkOption {
1176 default = {};
1177 example = { InterfaceId = 1; };
1178 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionXfrm;
1179 description = lib.mdDoc ''
1180 Each attribute in this set specifies an option in the
1181 `[Xfrm]` section of the unit. See
1182 {manpage}`systemd.netdev(5)` for details.
1183 '';
1184 };
1185
1186 vrfConfig = mkOption {
1187 default = {};
1188 example = { Table = 2342; };
1189 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionVRF;
1190 description = lib.mdDoc ''
1191 Each attribute in this set specifies an option in the
1192 `[VRF]` section of the unit. See
1193 {manpage}`systemd.netdev(5)` for details.
1194 A detailed explanation about how VRFs work can be found in the
1195 [kernel docs](https://www.kernel.org/doc/Documentation/networking/vrf.txt).
1196 '';
1197 };
1198
1199 batmanAdvancedConfig = mkOption {
1200 default = {};
1201 example = {
1202 GatewayMode = "server";
1203 RoutingAlgorithm = "batman-v";
1204 };
1205 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionBatmanAdvanced;
1206 description = lib.mdDoc ''
1207 Each attribute in this set specifies an option in the
1208 `[BatmanAdvanced]` section of the unit. See
1209 {manpage}`systemd.netdev(5)` for details.
1210 '';
1211 };
1212
1213 };
1214
1215 addressOptions = {
1216 options = {
1217 addressConfig = mkOption {
1218 example = { Address = "192.168.0.100/24"; };
1219 type = types.addCheck (types.attrsOf unitOption) check.network.sectionAddress;
1220 description = lib.mdDoc ''
1221 Each attribute in this set specifies an option in the
1222 `[Address]` section of the unit. See
1223 {manpage}`systemd.network(5)` for details.
1224 '';
1225 };
1226 };
1227 };
1228
1229 routingPolicyRulesOptions = {
1230 options = {
1231 routingPolicyRuleConfig = mkOption {
1232 default = { };
1233 example = { Table = 10; IncomingInterface = "eth1"; Family = "both"; };
1234 type = types.addCheck (types.attrsOf unitOption) check.network.sectionRoutingPolicyRule;
1235 description = lib.mdDoc ''
1236 Each attribute in this set specifies an option in the
1237 `[RoutingPolicyRule]` section of the unit. See
1238 {manpage}`systemd.network(5)` for details.
1239 '';
1240 };
1241 };
1242 };
1243
1244 routeOptions = {
1245 options = {
1246 routeConfig = mkOption {
1247 default = {};
1248 example = { Gateway = "192.168.0.1"; };
1249 type = types.addCheck (types.attrsOf unitOption) check.network.sectionRoute;
1250 description = lib.mdDoc ''
1251 Each attribute in this set specifies an option in the
1252 `[Route]` section of the unit. See
1253 {manpage}`systemd.network(5)` for details.
1254 '';
1255 };
1256 };
1257 };
1258
1259 ipv6PrefixOptions = {
1260 options = {
1261 ipv6PrefixConfig = mkOption {
1262 default = {};
1263 example = { Prefix = "fd00::/64"; };
1264 type = types.addCheck (types.attrsOf unitOption) check.network.sectionIPv6Prefix;
1265 description = lib.mdDoc ''
1266 Each attribute in this set specifies an option in the
1267 `[IPv6Prefix]` section of the unit. See
1268 {manpage}`systemd.network(5)` for details.
1269 '';
1270 };
1271 };
1272 };
1273
1274 ipv6RoutePrefixOptions = {
1275 options = {
1276 ipv6RoutePrefixConfig = mkOption {
1277 default = {};
1278 example = { Route = "fd00::/64"; };
1279 type = types.addCheck (types.attrsOf unitOption) check.network.sectionIPv6RoutePrefix;
1280 description = lib.mdDoc ''
1281 Each attribute in this set specifies an option in the
1282 `[IPv6RoutePrefix]` section of the unit. See
1283 {manpage}`systemd.network(5)` for details.
1284 '';
1285 };
1286 };
1287 };
1288
1289 dhcpServerStaticLeaseOptions = {
1290 options = {
1291 dhcpServerStaticLeaseConfig = mkOption {
1292 default = {};
1293 example = { MACAddress = "65:43:4a:5b:d8:5f"; Address = "192.168.1.42"; };
1294 type = types.addCheck (types.attrsOf unitOption) check.network.sectionDHCPServerStaticLease;
1295 description = lib.mdDoc ''
1296 Each attribute in this set specifies an option in the
1297 `[DHCPServerStaticLease]` section of the unit. See
1298 {manpage}`systemd.network(5)` for details.
1299
1300 Make sure to configure the corresponding client interface to use
1301 `ClientIdentifier=mac`.
1302 '';
1303 };
1304 };
1305 };
1306
1307 networkOptions = commonNetworkOptions // {
1308
1309 linkConfig = mkOption {
1310 default = {};
1311 example = { Unmanaged = true; };
1312 type = types.addCheck (types.attrsOf unitOption) check.network.sectionLink;
1313 description = lib.mdDoc ''
1314 Each attribute in this set specifies an option in the
1315 `[Link]` section of the unit. See
1316 {manpage}`systemd.network(5)` for details.
1317 '';
1318 };
1319
1320 networkConfig = mkOption {
1321 default = {};
1322 example = { Description = "My Network"; };
1323 type = types.addCheck (types.attrsOf unitOption) check.network.sectionNetwork;
1324 description = lib.mdDoc ''
1325 Each attribute in this set specifies an option in the
1326 `[Network]` section of the unit. See
1327 {manpage}`systemd.network(5)` for details.
1328 '';
1329 };
1330
1331 # systemd.network.networks.*.dhcpConfig has been deprecated in favor of ….dhcpV4Config
1332 # Produce a nice warning message so users know it is gone.
1333 dhcpConfig = mkOption {
1334 visible = false;
1335 apply = _: throw "The option `systemd.network.networks.*.dhcpConfig` can no longer be used since it's been removed. Please use `systemd.network.networks.*.dhcpV4Config` instead.";
1336 };
1337
1338 dhcpV4Config = mkOption {
1339 default = {};
1340 example = { UseDNS = true; UseRoutes = true; };
1341 type = types.addCheck (types.attrsOf unitOption) check.network.sectionDHCPv4;
1342 description = lib.mdDoc ''
1343 Each attribute in this set specifies an option in the
1344 `[DHCPv4]` section of the unit. See
1345 {manpage}`systemd.network(5)` for details.
1346 '';
1347 };
1348
1349 dhcpV6Config = mkOption {
1350 default = {};
1351 example = { UseDNS = true; };
1352 type = types.addCheck (types.attrsOf unitOption) check.network.sectionDHCPv6;
1353 description = lib.mdDoc ''
1354 Each attribute in this set specifies an option in the
1355 `[DHCPv6]` section of the unit. See
1356 {manpage}`systemd.network(5)` for details.
1357 '';
1358 };
1359
1360 dhcpV6PrefixDelegationConfig = mkOption {
1361 visible = false;
1362 apply = _: throw "The option `systemd.network.networks.<name>.dhcpV6PrefixDelegationConfig` has been renamed to `systemd.network.networks.<name>.dhcpPrefixDelegationConfig`.";
1363 };
1364
1365 dhcpPrefixDelegationConfig = mkOption {
1366 default = {};
1367 example = { SubnetId = "auto"; Announce = true; };
1368 type = types.addCheck (types.attrsOf unitOption) check.network.sectionDHCPPrefixDelegation;
1369 description = lib.mdDoc ''
1370 Each attribute in this set specifies an option in the
1371 `[DHCPPrefixDelegation]` section of the unit. See
1372 {manpage}`systemd.network(5)` for details.
1373 '';
1374 };
1375
1376 ipv6AcceptRAConfig = mkOption {
1377 default = {};
1378 example = { UseDNS = true; DHCPv6Client = "always"; };
1379 type = types.addCheck (types.attrsOf unitOption) check.network.sectionIPv6AcceptRA;
1380 description = lib.mdDoc ''
1381 Each attribute in this set specifies an option in the
1382 `[IPv6AcceptRA]` section of the unit. See
1383 {manpage}`systemd.network(5)` for details.
1384 '';
1385 };
1386
1387 dhcpServerConfig = mkOption {
1388 default = {};
1389 example = { PoolOffset = 50; EmitDNS = false; };
1390 type = types.addCheck (types.attrsOf unitOption) check.network.sectionDHCPServer;
1391 description = lib.mdDoc ''
1392 Each attribute in this set specifies an option in the
1393 `[DHCPServer]` section of the unit. See
1394 {manpage}`systemd.network(5)` for details.
1395 '';
1396 };
1397
1398 # systemd.network.networks.*.ipv6PrefixDelegationConfig has been deprecated
1399 # in 247 in favor of systemd.network.networks.*.ipv6SendRAConfig.
1400 ipv6PrefixDelegationConfig = mkOption {
1401 visible = false;
1402 apply = _: throw "The option `systemd.network.networks.*.ipv6PrefixDelegationConfig` has been replaced by `systemd.network.networks.*.ipv6SendRAConfig`.";
1403 };
1404
1405 ipv6SendRAConfig = mkOption {
1406 default = {};
1407 example = { EmitDNS = true; Managed = true; OtherInformation = true; };
1408 type = types.addCheck (types.attrsOf unitOption) check.network.sectionIPv6SendRA;
1409 description = lib.mdDoc ''
1410 Each attribute in this set specifies an option in the
1411 `[IPv6SendRA]` section of the unit. See
1412 {manpage}`systemd.network(5)` for details.
1413 '';
1414 };
1415
1416 dhcpServerStaticLeases = mkOption {
1417 default = [];
1418 example = [ { dhcpServerStaticLeaseConfig = { MACAddress = "65:43:4a:5b:d8:5f"; Address = "192.168.1.42"; }; } ];
1419 type = with types; listOf (submodule dhcpServerStaticLeaseOptions);
1420 description = lib.mdDoc ''
1421 A list of DHCPServerStaticLease sections to be added to the unit. See
1422 {manpage}`systemd.network(5)` for details.
1423 '';
1424 };
1425
1426 ipv6Prefixes = mkOption {
1427 default = [];
1428 example = [ { ipv6PrefixConfig = { AddressAutoconfiguration = true; OnLink = true; }; } ];
1429 type = with types; listOf (submodule ipv6PrefixOptions);
1430 description = lib.mdDoc ''
1431 A list of ipv6Prefix sections to be added to the unit. See
1432 {manpage}`systemd.network(5)` for details.
1433 '';
1434 };
1435
1436 ipv6RoutePrefixes = mkOption {
1437 default = [];
1438 example = [ { ipv6RoutePrefixConfig = { Route = "fd00::/64"; LifetimeSec = 3600; }; } ];
1439 type = with types; listOf (submodule ipv6RoutePrefixOptions);
1440 description = lib.mdDoc ''
1441 A list of ipv6RoutePrefix sections to be added to the unit. See
1442 {manpage}`systemd.network(5)` for details.
1443 '';
1444 };
1445
1446 name = mkOption {
1447 type = types.nullOr types.str;
1448 default = null;
1449 description = lib.mdDoc ''
1450 The name of the network interface to match against.
1451 '';
1452 };
1453
1454 DHCP = mkOption {
1455 type = types.nullOr types.str;
1456 default = null;
1457 description = lib.mdDoc ''
1458 Whether to enable DHCP on the interfaces matched.
1459 '';
1460 };
1461
1462 domains = mkOption {
1463 type = types.nullOr (types.listOf types.str);
1464 default = null;
1465 description = lib.mdDoc ''
1466 A list of domains to pass to the network config.
1467 '';
1468 };
1469
1470 address = mkOption {
1471 default = [ ];
1472 type = types.listOf types.str;
1473 description = lib.mdDoc ''
1474 A list of addresses to be added to the network section of the
1475 unit. See {manpage}`systemd.network(5)` for details.
1476 '';
1477 };
1478
1479 gateway = mkOption {
1480 default = [ ];
1481 type = types.listOf types.str;
1482 description = lib.mdDoc ''
1483 A list of gateways to be added to the network section of the
1484 unit. See {manpage}`systemd.network(5)` for details.
1485 '';
1486 };
1487
1488 dns = mkOption {
1489 default = [ ];
1490 type = types.listOf types.str;
1491 description = lib.mdDoc ''
1492 A list of dns servers to be added to the network section of the
1493 unit. See {manpage}`systemd.network(5)` for details.
1494 '';
1495 };
1496
1497 ntp = mkOption {
1498 default = [ ];
1499 type = types.listOf types.str;
1500 description = lib.mdDoc ''
1501 A list of ntp servers to be added to the network section of the
1502 unit. See {manpage}`systemd.network(5)` for details.
1503 '';
1504 };
1505
1506 bridge = mkOption {
1507 default = [ ];
1508 type = types.listOf types.str;
1509 description = lib.mdDoc ''
1510 A list of bridge interfaces to be added to the network section of the
1511 unit. See {manpage}`systemd.network(5)` for details.
1512 '';
1513 };
1514
1515 bond = mkOption {
1516 default = [ ];
1517 type = types.listOf types.str;
1518 description = lib.mdDoc ''
1519 A list of bond interfaces to be added to the network section of the
1520 unit. See {manpage}`systemd.network(5)` for details.
1521 '';
1522 };
1523
1524 vrf = mkOption {
1525 default = [ ];
1526 type = types.listOf types.str;
1527 description = lib.mdDoc ''
1528 A list of vrf interfaces to be added to the network section of the
1529 unit. See {manpage}`systemd.network(5)` for details.
1530 '';
1531 };
1532
1533 vlan = mkOption {
1534 default = [ ];
1535 type = types.listOf types.str;
1536 description = lib.mdDoc ''
1537 A list of vlan interfaces to be added to the network section of the
1538 unit. See {manpage}`systemd.network(5)` for details.
1539 '';
1540 };
1541
1542 macvlan = mkOption {
1543 default = [ ];
1544 type = types.listOf types.str;
1545 description = lib.mdDoc ''
1546 A list of macvlan interfaces to be added to the network section of the
1547 unit. See {manpage}`systemd.network(5)` for details.
1548 '';
1549 };
1550
1551 vxlan = mkOption {
1552 default = [ ];
1553 type = types.listOf types.str;
1554 description = lib.mdDoc ''
1555 A list of vxlan interfaces to be added to the network section of the
1556 unit. See {manpage}`systemd.network(5)` for details.
1557 '';
1558 };
1559
1560 tunnel = mkOption {
1561 default = [ ];
1562 type = types.listOf types.str;
1563 description = lib.mdDoc ''
1564 A list of tunnel interfaces to be added to the network section of the
1565 unit. See {manpage}`systemd.network(5)` for details.
1566 '';
1567 };
1568
1569 xfrm = mkOption {
1570 default = [ ];
1571 type = types.listOf types.str;
1572 description = lib.mdDoc ''
1573 A list of xfrm interfaces to be added to the network section of the
1574 unit. See {manpage}`systemd.network(5)` for details.
1575 '';
1576 };
1577
1578 addresses = mkOption {
1579 default = [ ];
1580 type = with types; listOf (submodule addressOptions);
1581 description = lib.mdDoc ''
1582 A list of address sections to be added to the unit. See
1583 {manpage}`systemd.network(5)` for details.
1584 '';
1585 };
1586
1587 routingPolicyRules = mkOption {
1588 default = [ ];
1589 type = with types; listOf (submodule routingPolicyRulesOptions);
1590 description = lib.mdDoc ''
1591 A list of routing policy rules sections to be added to the unit. See
1592 {manpage}`systemd.network(5)` for details.
1593 '';
1594 };
1595
1596 routes = mkOption {
1597 default = [ ];
1598 type = with types; listOf (submodule routeOptions);
1599 description = lib.mdDoc ''
1600 A list of route sections to be added to the unit. See
1601 {manpage}`systemd.network(5)` for details.
1602 '';
1603 };
1604
1605 };
1606
1607 networkConfig = { config, ... }: {
1608 config = {
1609 matchConfig = optionalAttrs (config.name != null) {
1610 Name = config.name;
1611 };
1612 networkConfig = optionalAttrs (config.DHCP != null) {
1613 DHCP = config.DHCP;
1614 } // optionalAttrs (config.domains != null) {
1615 Domains = concatStringsSep " " config.domains;
1616 };
1617 };
1618 };
1619
1620 networkdConfig = { config, ... }: {
1621 options = {
1622 routeTables = mkOption {
1623 default = {};
1624 example = { foo = 27; };
1625 type = with types; attrsOf int;
1626 description = lib.mdDoc ''
1627 Defines route table names as an attrset of name to number.
1628 See {manpage}`networkd.conf(5)` for details.
1629 '';
1630 };
1631
1632 addRouteTablesToIPRoute2 = mkOption {
1633 default = true;
1634 example = false;
1635 type = types.bool;
1636 description = lib.mdDoc ''
1637 If true and routeTables are set, then the specified route tables
1638 will also be installed into /etc/iproute2/rt_tables.
1639 '';
1640 };
1641 };
1642
1643 config = {
1644 networkConfig = optionalAttrs (config.routeTables != { }) {
1645 RouteTable = mapAttrsToList
1646 (name: number: "${name}:${toString number}")
1647 config.routeTables;
1648 };
1649 };
1650 };
1651
1652 commonMatchText = def: optionalString (def.matchConfig != { }) ''
1653 [Match]
1654 ${attrsToSection def.matchConfig}
1655 '';
1656
1657 linkToUnit = name: def:
1658 { inherit (def) enable;
1659 text = commonMatchText def
1660 + ''
1661 [Link]
1662 ${attrsToSection def.linkConfig}
1663 ''
1664 + def.extraConfig;
1665 };
1666
1667 netdevToUnit = name: def:
1668 { inherit (def) enable;
1669 text = commonMatchText def
1670 + ''
1671 [NetDev]
1672 ${attrsToSection def.netdevConfig}
1673 ''
1674 + optionalString (def.vlanConfig != { }) ''
1675 [VLAN]
1676 ${attrsToSection def.vlanConfig}
1677 ''
1678 + optionalString (def.macvlanConfig != { }) ''
1679 [MACVLAN]
1680 ${attrsToSection def.macvlanConfig}
1681 ''
1682 + optionalString (def.vxlanConfig != { }) ''
1683 [VXLAN]
1684 ${attrsToSection def.vxlanConfig}
1685 ''
1686 + optionalString (def.tunnelConfig != { }) ''
1687 [Tunnel]
1688 ${attrsToSection def.tunnelConfig}
1689 ''
1690 + optionalString (def.fooOverUDPConfig != { }) ''
1691 [FooOverUDP]
1692 ${attrsToSection def.fooOverUDPConfig}
1693 ''
1694 + optionalString (def.peerConfig != { }) ''
1695 [Peer]
1696 ${attrsToSection def.peerConfig}
1697 ''
1698 + optionalString (def.tunConfig != { }) ''
1699 [Tun]
1700 ${attrsToSection def.tunConfig}
1701 ''
1702 + optionalString (def.tapConfig != { }) ''
1703 [Tap]
1704 ${attrsToSection def.tapConfig}
1705 ''
1706 + optionalString (def.wireguardConfig != { }) ''
1707 [WireGuard]
1708 ${attrsToSection def.wireguardConfig}
1709 ''
1710 + flip concatMapStrings def.wireguardPeers (x: ''
1711 [WireGuardPeer]
1712 ${attrsToSection x.wireguardPeerConfig}
1713 '')
1714 + optionalString (def.bondConfig != { }) ''
1715 [Bond]
1716 ${attrsToSection def.bondConfig}
1717 ''
1718 + optionalString (def.xfrmConfig != { }) ''
1719 [Xfrm]
1720 ${attrsToSection def.xfrmConfig}
1721 ''
1722 + optionalString (def.vrfConfig != { }) ''
1723 [VRF]
1724 ${attrsToSection def.vrfConfig}
1725 ''
1726 + optionalString (def.batmanAdvancedConfig != { }) ''
1727 [BatmanAdvanced]
1728 ${attrsToSection def.batmanAdvancedConfig}
1729 ''
1730 + def.extraConfig;
1731 };
1732
1733 renderConfig = def:
1734 { text = ''
1735 [Network]
1736 ${attrsToSection def.networkConfig}
1737 ''
1738 + optionalString (def.dhcpV4Config != { }) ''
1739 [DHCPv4]
1740 ${attrsToSection def.dhcpV4Config}
1741 ''
1742 + optionalString (def.dhcpV6Config != { }) ''
1743 [DHCPv6]
1744 ${attrsToSection def.dhcpV6Config}
1745 ''; };
1746
1747 networkToUnit = name: def:
1748 { inherit (def) enable;
1749 text = commonMatchText def
1750 + optionalString (def.linkConfig != { }) ''
1751 [Link]
1752 ${attrsToSection def.linkConfig}
1753 ''
1754 + ''
1755 [Network]
1756 ''
1757 + attrsToSection def.networkConfig
1758 + optionalString (def.address != [ ]) ''
1759 ${concatStringsSep "\n" (map (s: "Address=${s}") def.address)}
1760 ''
1761 + optionalString (def.gateway != [ ]) ''
1762 ${concatStringsSep "\n" (map (s: "Gateway=${s}") def.gateway)}
1763 ''
1764 + optionalString (def.dns != [ ]) ''
1765 ${concatStringsSep "\n" (map (s: "DNS=${s}") def.dns)}
1766 ''
1767 + optionalString (def.ntp != [ ]) ''
1768 ${concatStringsSep "\n" (map (s: "NTP=${s}") def.ntp)}
1769 ''
1770 + optionalString (def.bridge != [ ]) ''
1771 ${concatStringsSep "\n" (map (s: "Bridge=${s}") def.bridge)}
1772 ''
1773 + optionalString (def.bond != [ ]) ''
1774 ${concatStringsSep "\n" (map (s: "Bond=${s}") def.bond)}
1775 ''
1776 + optionalString (def.vrf != [ ]) ''
1777 ${concatStringsSep "\n" (map (s: "VRF=${s}") def.vrf)}
1778 ''
1779 + optionalString (def.vlan != [ ]) ''
1780 ${concatStringsSep "\n" (map (s: "VLAN=${s}") def.vlan)}
1781 ''
1782 + optionalString (def.macvlan != [ ]) ''
1783 ${concatStringsSep "\n" (map (s: "MACVLAN=${s}") def.macvlan)}
1784 ''
1785 + optionalString (def.vxlan != [ ]) ''
1786 ${concatStringsSep "\n" (map (s: "VXLAN=${s}") def.vxlan)}
1787 ''
1788 + optionalString (def.tunnel != [ ]) ''
1789 ${concatStringsSep "\n" (map (s: "Tunnel=${s}") def.tunnel)}
1790 ''
1791 + optionalString (def.xfrm != [ ]) ''
1792 ${concatStringsSep "\n" (map (s: "Xfrm=${s}") def.xfrm)}
1793 ''
1794 + ''
1795
1796 ''
1797 + flip concatMapStrings def.addresses (x: ''
1798 [Address]
1799 ${attrsToSection x.addressConfig}
1800 '')
1801 + flip concatMapStrings def.routingPolicyRules (x: ''
1802 [RoutingPolicyRule]
1803 ${attrsToSection x.routingPolicyRuleConfig}
1804 '')
1805 + flip concatMapStrings def.routes (x: ''
1806 [Route]
1807 ${attrsToSection x.routeConfig}
1808 '')
1809 + optionalString (def.dhcpV4Config != { }) ''
1810 [DHCPv4]
1811 ${attrsToSection def.dhcpV4Config}
1812 ''
1813 + optionalString (def.dhcpV6Config != { }) ''
1814 [DHCPv6]
1815 ${attrsToSection def.dhcpV6Config}
1816 ''
1817 + optionalString (def.dhcpPrefixDelegationConfig != { }) ''
1818 [DHCPPrefixDelegation]
1819 ${attrsToSection def.dhcpPrefixDelegationConfig}
1820 ''
1821 + optionalString (def.ipv6AcceptRAConfig != { }) ''
1822 [IPv6AcceptRA]
1823 ${attrsToSection def.ipv6AcceptRAConfig}
1824 ''
1825 + optionalString (def.dhcpServerConfig != { }) ''
1826 [DHCPServer]
1827 ${attrsToSection def.dhcpServerConfig}
1828 ''
1829 + optionalString (def.ipv6SendRAConfig != { }) ''
1830 [IPv6SendRA]
1831 ${attrsToSection def.ipv6SendRAConfig}
1832 ''
1833 + flip concatMapStrings def.ipv6Prefixes (x: ''
1834 [IPv6Prefix]
1835 ${attrsToSection x.ipv6PrefixConfig}
1836 '')
1837 + flip concatMapStrings def.ipv6RoutePrefixes (x: ''
1838 [IPv6RoutePrefix]
1839 ${attrsToSection x.ipv6RoutePrefixConfig}
1840 '')
1841 + flip concatMapStrings def.dhcpServerStaticLeases (x: ''
1842 [DHCPServerStaticLease]
1843 ${attrsToSection x.dhcpServerStaticLeaseConfig}
1844 '')
1845 + def.extraConfig;
1846 };
1847
1848 unitFiles = listToAttrs (map (name: {
1849 name = "systemd/network/${name}";
1850 value.source = "${cfg.units.${name}.unit}/${name}";
1851 }) (attrNames cfg.units));
1852in
1853
1854{
1855 options = {
1856
1857 systemd.network.enable = mkOption {
1858 default = false;
1859 type = types.bool;
1860 description = lib.mdDoc ''
1861 Whether to enable networkd or not.
1862 '';
1863 };
1864
1865 systemd.network.links = mkOption {
1866 default = {};
1867 type = with types; attrsOf (submodule [ { options = linkOptions; } ]);
1868 description = lib.mdDoc "Definition of systemd network links.";
1869 };
1870
1871 systemd.network.netdevs = mkOption {
1872 default = {};
1873 type = with types; attrsOf (submodule [ { options = netdevOptions; } ]);
1874 description = lib.mdDoc "Definition of systemd network devices.";
1875 };
1876
1877 systemd.network.networks = mkOption {
1878 default = {};
1879 type = with types; attrsOf (submodule [ { options = networkOptions; } networkConfig ]);
1880 description = lib.mdDoc "Definition of systemd networks.";
1881 };
1882
1883 systemd.network.config = mkOption {
1884 default = {};
1885 type = with types; submodule [ { options = networkdOptions; } networkdConfig ];
1886 description = lib.mdDoc "Definition of global systemd network config.";
1887 };
1888
1889 systemd.network.units = mkOption {
1890 description = lib.mdDoc "Definition of networkd units.";
1891 default = {};
1892 internal = true;
1893 type = with types; attrsOf (submodule (
1894 { name, config, ... }:
1895 { options = mapAttrs (_: x: x // { internal = true; }) concreteUnitOptions;
1896 config = {
1897 unit = mkDefault (makeUnit name config);
1898 };
1899 }));
1900 };
1901
1902 systemd.network.wait-online = {
1903 anyInterface = mkOption {
1904 description = lib.mdDoc ''
1905 Whether to consider the network online when any interface is online, as opposed to all of them.
1906 This is useful on portable machines with a wired and a wireless interface, for example.
1907 '';
1908 type = types.bool;
1909 default = false;
1910 };
1911
1912 ignoredInterfaces = mkOption {
1913 description = lib.mdDoc ''
1914 Network interfaces to be ignored when deciding if the system is online.
1915 '';
1916 type = with types; listOf str;
1917 default = [];
1918 example = [ "wg0" ];
1919 };
1920
1921 timeout = mkOption {
1922 description = lib.mdDoc ''
1923 Time to wait for the network to come online, in seconds. Set to 0 to disable.
1924 '';
1925 type = types.ints.unsigned;
1926 default = 120;
1927 example = 0;
1928 };
1929
1930 extraArgs = mkOption {
1931 description = lib.mdDoc ''
1932 Extra command-line arguments to pass to systemd-networkd-wait-online.
1933 These also affect per-interface `systemd-network-wait-online@` services.
1934
1935 See [{manpage}`systemd-networkd-wait-online.service(8)`](https://www.freedesktop.org/software/systemd/man/systemd-networkd-wait-online.service.html) for all available options.
1936 '';
1937 type = with types; listOf str;
1938 default = [];
1939 };
1940 };
1941
1942 };
1943
1944 config = mkMerge [
1945
1946 # .link units are honored by udev, no matter if systemd-networkd is enabled or not.
1947 {
1948 systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.links;
1949 environment.etc = unitFiles;
1950
1951 systemd.network.wait-online.extraArgs =
1952 [ "--timeout=${toString cfg.wait-online.timeout}" ]
1953 ++ optional cfg.wait-online.anyInterface "--any"
1954 ++ map (i: "--ignore=${i}") cfg.wait-online.ignoredInterfaces;
1955 }
1956
1957 (mkIf config.systemd.network.enable {
1958
1959 users.users.systemd-network.group = "systemd-network";
1960
1961 systemd.additionalUpstreamSystemUnits = [
1962 "systemd-networkd-wait-online.service"
1963 "systemd-networkd.service"
1964 "systemd-networkd.socket"
1965 ];
1966
1967 systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.netdevs
1968 // mapAttrs' (n: v: nameValuePair "${n}.network" (networkToUnit n v)) cfg.networks;
1969
1970 # systemd-networkd is socket-activated by kernel netlink route change
1971 # messages. It is important to have systemd buffer those on behalf of
1972 # networkd.
1973 systemd.sockets.systemd-networkd.wantedBy = [ "sockets.target" ];
1974
1975 systemd.services.systemd-networkd = {
1976 wantedBy = [ "multi-user.target" ];
1977 aliases = [ "dbus-org.freedesktop.network1.service" ];
1978 restartTriggers = map (x: x.source) (attrValues unitFiles) ++ [
1979 config.environment.etc."systemd/networkd.conf".source
1980 ];
1981 };
1982
1983 systemd.services.systemd-networkd-wait-online = {
1984 wantedBy = [ "network-online.target" ];
1985 serviceConfig.ExecStart = [
1986 ""
1987 "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online ${utils.escapeSystemdExecArgs cfg.wait-online.extraArgs}"
1988 ];
1989 };
1990
1991 systemd.services."systemd-network-wait-online@" = {
1992 description = "Wait for Network Interface %I to be Configured";
1993 conflicts = [ "shutdown.target" ];
1994 requisite = [ "systemd-networkd.service" ];
1995 after = [ "systemd-networkd.service" ];
1996 serviceConfig = {
1997 Type = "oneshot";
1998 RemainAfterExit = true;
1999 ExecStart = "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online -i %I ${utils.escapeSystemdExecArgs cfg.wait-online.extraArgs}";
2000 };
2001 };
2002
2003 environment.etc."systemd/networkd.conf" = renderConfig cfg.config;
2004
2005 networking.iproute2 = mkIf (cfg.config.addRouteTablesToIPRoute2 && cfg.config.routeTables != { }) {
2006 enable = mkDefault true;
2007 rttablesExtraConfig = ''
2008
2009 # Extra tables defined in NixOS systemd.networkd.config.routeTables.
2010 ${concatStringsSep "\n" (mapAttrsToList (name: number: "${toString number} ${name}") cfg.config.routeTables)}
2011 '';
2012 };
2013
2014 services.resolved.enable = mkDefault true;
2015 })
2016 ];
2017}