Skip to content

Commit

Permalink
Merge pull request #887 from kernelkit/dhcp-server
Browse files Browse the repository at this point in the history
Add basic DHCP server support
  • Loading branch information
mattiaswal authored Jan 31, 2025
2 parents 0fbe225 + 028fc57 commit 5e89d8e
Show file tree
Hide file tree
Showing 89 changed files with 3,604 additions and 349 deletions.
15 changes: 9 additions & 6 deletions board/common/rootfs/etc/dnsmasq.conf
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@
# and similar events feed servers and configuration to dnsmasq.
domain-needed

# Only listen to loopback (local system)
interface=lo
bind-dynamic
#listen-address=127.0.0.1,::1

# Allow configuration and cache clear over D-Bus
enable-dbus

# Disable the following dnsmasq default DHCP options
#dhcp-option=option:netmask
#dhcp-option=28 # option:broadcast
#dhcp-option=option:domain-name
dhcp-option=option:router
dhcp-option=option:dns-server
dhcp-option=12 # option:hostname

# Generated by openresolv
resolv-file=/var/lib/misc/resolv.conf

# Include all files in a directory which end in .conf
conf-dir=/etc/dnsmasq.d/,*.conf

39 changes: 39 additions & 0 deletions board/common/rootfs/usr/bin/show
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ options:
-p Show plain output, no bells or whistles
commands:
dhcp Show DHCP server
port PORT Show port configuration and link information
ports Show ports available for bridging
vlans Show port groups in bridge
Expand All @@ -88,6 +89,41 @@ commands:
EOF
}

is_dhcp_running()
{
sysrepocfg -X -f json -m infix-dhcp-server | jq -r '
."infix-dhcp-server:dhcp-server".enabled as $global |
if ."infix-dhcp-server:dhcp-server".subnet? then
(."infix-dhcp-server:dhcp-server".subnet[] |
select(.enabled != false)) |
if $global != false and . then "true" else "false" end
else "false" end
' 2>/dev/null | grep -q true
}

dhcp()
{
if ! is_dhcp_running; then
echo "DHCP server not enabled."
exit 0
fi

case $1 in
detail)
sysrepocfg -f json -X -d operational -m infix-dhcp-server | \
jq -C .
;;
stat*)
sysrepocfg -f json -X -d operational -m infix-dhcp-server | \
/usr/libexec/statd/cli-pretty "show-dhcp-server" -s
;;
*)
sysrepocfg -f json -X -d operational -m infix-dhcp-server | \
/usr/libexec/statd/cli-pretty "show-dhcp-server"
;;
esac
}

# Usage 1: show port eth0
# Usage 2: show port
# Usage 3: show ports
Expand Down Expand Up @@ -295,6 +331,9 @@ case $cmd in
help)
usage
;;
dhcp | dhcp-server)
dhcp $*
;;
port*)
ports $*
;;
Expand Down
70 changes: 52 additions & 18 deletions doc/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,68 @@ Change Log

All notable changes to the project are documented in this file.

[v24.12.0][UNRELEASED]

[v25.01.0][] - 2025-01-31
-------------------------

> [!NOTE]
> This release contains breaking changes in the configuration file
> syntax for DHCP clients. Specifically DHCP options *with value*,
> i.e., the syntax for sending a hexadecimal value now require `hex`
> prefix before a string of colon-separated pairs of hex values.
### Changes

- NTP client status is now available in YANG
- Add support for more mDNS settings: allow/deny interfaces, acting
as "reflector" and filtering of reflected services. Issue #678
- Review of default `sysctl` settings, issue #829
- Upgrade Linux kernel to 6.12.11 (LTS)
- Upgrade Buildroot to 2024.02.10 (LTS)
- Add the possibility to change the boot order for the system with a
RPC and add boot order to operational datastore.
- SSH Server is now configurable, issue #441
SSH Server and NETCONF Server now uses the same SSH hostkey in factory-config
- Support for GRE/GRETAP tunnels
- Support for STP/RSTP on bridges
- Support for VXLAN tunnels
- Upgrade FRR from 9.1.2 to 9.1.3
- Add support for configuring SSH server, issue #441. As a result,
both SSH and NETCONF now use the same host key in `factory-config`
- Add operational support for reading DNS resolver info, issue #510
- Add operational support for NTP client, issue #510
- Add support for more mDNS settings: allow/deny interfaces, acting
as "reflector" and filtering of reflected services. Issue #678
- Add DHCPv4 server support, multiple subnets with static hosts and
DHCP options on global, subnet, or host level, issue #703.
Contributed by [MINEx Networks](https://minexn.com/)
- DHCP client options aligned with DHCP server, `startup-config`
files with old syntax are automatically migrated
- Breaking change in DHCP client options *with value*. Hexadecimal
values must now be formatted as `{ "hex": "c0:ff:ee" }` (JSON)
- Add documentation on management via SSH, Web (RESTCONF, Web
Console), and Console Port, issue #787
- Upgrade FRR from 9.1.2 to 9.1.3
- Add documentation of DNS client use and configuration, issue #798
- Add support for changing boot order for the system with an RPC,
including support for reading boot order from operational datastore
- Add support for GRE/GRETAP tunnels
- Add support for STP/RSTP on bridges
- Add support for VXLAN tunnels

### Fixes

- Fix #777: Authorized SSH key not applied to `startup-config`
- Fix #829: Avahi (mDNS responder) not starting properly on switches
with *many* ports (>10). This led to a review of `sysctl`:
- New for IPv4:
- Adjust IGMP max memberships: 20 -> 1000
- Use neighbor information on nexthop selection
- Use inbound interface address on ICMP errors
- Ignore routes with link down
- Disable `rp_filter`
- ARP settings have been changed to better fit routers, i.e.,
systems with multiple interfaces:
- Always use best local address when sending ARP
- Only reply to ARP if target IP is on the inbound interface
- Generate ARP requests when device is brought up or HW address changes
- New for IPv6:
- Keep static global addresses on link down
- Ignore routes with link down
- Fix #861: Fix error when running 251+ reconfigurations in test-mode
- Fix #777: Authorized SSH key not applied to startup config
- Minor cleanup of Networking Guide
- Fix memory leaks in confd
- Fix #869: Setup of bridges is now more robust
- Fix #899: DHCP client with client-id does not work
- Minor cleanup of Networking Guide
- Fix memory leaks in `confd`


[v24.11.1][] - 2024-11-29
-------------------------
Expand Down Expand Up @@ -81,6 +114,7 @@ All notable changes to the project are documented in this file.
forwarded, when the underlying ports are simultaneously attached to
a VLAN filtering bridge.


[v24.11.0][] - 2024-11-20
-------------------------

Expand Down Expand Up @@ -1437,8 +1471,8 @@ Supported YANG models in addition to those used by sysrepo and netopeer:
- N/A

[buildroot]: https://buildroot.org/
[UNRELEASED]: https://github.com/kernelkit/infix/compare/v24.11.0...HEAD
[v24.12.0]: https://github.com/kernelkit/infix/compare/v24.11.0...v24.12.0
[UNRELEASED]: https://github.com/kernelkit/infix/compare/v25.01.0...HEAD
[v25.01.0]: https://github.com/kernelkit/infix/compare/v24.11.0...v25.01.0
[v24.11.1]: https://github.com/kernelkit/infix/compare/v24.11.0...v24.11.1
[v24.11.0]: https://github.com/kernelkit/infix/compare/v24.10.0...v24.11.0
[v24.10.2]: https://github.com/kernelkit/infix/compare/v24.10.1...v24.10.2
Expand Down
171 changes: 171 additions & 0 deletions doc/dhcp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
DHCP Server
===========

The DHCPv4 server provides automatic IP address assignment and network
configuration for clients. It supports address pools, static host
assignments, and customizable DHCP options. It also serves as a DNS
proxy for local subnets and can even forward queries to upstream DNS
servers[^1].

> [!NOTE]
> When using the CLI, the system automatically enables essential options
> like DNS servers and default gateway based on the system's network
> configuration. These options can be disabled, changed or overridden,
> at any level: global, subnet, or per-host.

## Basic Configuration

The following example configures a DHCP server for subnet 192.168.2.0/24
with an address pool:

```
admin@example:/> configure
admin@example:/config/> edit dhcp-server
admin@example:/config/dhcp-server/> edit subnet 192.168.2.0/24
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/> set pool start-address 192.168.2.100 end-address 192.168.2.200
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/> leave
```

When setting up the server from the CLI, the system automatically adds a
few default DHCP options that will be sent to clients: both DNS server
and default gateway will use the system address on the matching
interface.

```
admin@example:/> show running-config
"infix-dhcp-server:dhcp-server": {
"subnet": [
{
"subnet": "192.168.2.0/24",
"option": [
{
"id": "dns-server",
"address": "auto"
},
{
"id": "router",
"address": "auto"
}
],
"pool": {
"start-address": "192.168.2.100",
"end-address": "192.168.2.200"
}
}
]
}
```

> [!IMPORTANT]
> Remember to set up an interface in this subnet, avoid using addresses
> in the DHCP pool, or reserved for static hosts. In Class C networks
> the router usually has address `.1`. Depending on the use-case, you
> may also want to set up routing.

## Static Host Assignment

To reserve specific IP addresses for clients based on their MAC address,
hostname, or client ID:

```
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/> edit host 192.168.2.10
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/host/192.168.2.10/> set match mac-address 00:11:22:33:44:55
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/host/192.168.2.10/> set hostname printer
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/host/192.168.2.10/> leave
```

Match hosts using a client identifier instead of MAC address:

```
admin@example:/config/dhcp-server/subnet/192.168.1.0/24/> edit host 192.168.1.50
admin@example:/config/dhcp-server/subnet/192.168.1.0/24/host/192.168.1.50/> edit match
admin@example:/config/dhcp-server/subnet/192.168.1.0/24/host/192.168.1.50/match/> set client-id hex c0:ff:ee
admin@example:/config/dhcp-server/subnet/192.168.1.0/24/host/192.168.1.50/match/> leave
admin@example:/config/dhcp-server/subnet/192.168.1.0/24/host/192.168.1.50/> set lease-time infinite
admin@example:/config/dhcp-server/subnet/192.168.1.0/24/host/192.168.1.50/> leave
```

The `hex` prefix here ensures matching of client ID is done using the
hexadecimal octets `c0:ff:ee`, three bytes. Without the prefix the
ASCII string "c0:ff:ee", eight bytes, is used.

> [!NOTE]
> The DHCP server is fully RFC conformant, in the case of option 61 this
> means that using the `hex` prefix will require the client to set the
> `htype` field of the option to `00`. See RFC 2132 for details.

## Custom DHCP Options

Configure additional DHCP options globally, per subnet, or per host:

```
admin@example:/config/dhcp-server/> edit subnet 192.168.2.0/24
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/> edit option dns-server
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/option/dns-server/> set address 8.8.8.8
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/option/dns-server/> leave
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/> edit option ntp-server
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/option/ntp-server/> set address 192.168.2.1
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/option/ntp-server/> leave
```

When configuring, e.g., `dns-server`, or `router` options with the value
`auto`, the system uses the IP address from the interface matching the
subnet. For example:

```
admin@example:/> show interfaces brief
Interface Status Address
eth0 UP 192.168.1.1/24
eth1 UP 192.168.2.1/24
admin@example:/config/dhcp-server/subnet/192.168.1.0/24/> edit option dns-server
admin@example:/config/dhcp-server/subnet/192.168.1.0/24/option/dns-server/> set address auto
admin@example:/config/dhcp-server/subnet/192.168.1.0/24/option/dns-server/> leave
```

In this case, clients in subnet 192.168.1.0/24 will receive 192.168.1.1
as their DNS server address.


## Multiple Subnets

Configure DHCP for multiple networks:

```
admin@example:/> configure
admin@example:/config/> edit dhcp-server
admin@example:/config/dhcp-server/> edit subnet 192.168.1.0/24
admin@example:/config/dhcp-server/subnet/192.168.1.0/24/> set pool start-address 192.168.1.100 end-address 192.168.1.200
admin@example:/config/dhcp-server/subnet/192.168.1.0/24/> leave
admin@example:/config/dhcp-server/> edit subnet 192.168.2.0/24
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/> set pool start-address 192.168.2.100 end-address 192.168.2.200
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/> leave
```


## Monitoring

View active leases and server statistics:

```
admin@example:/> show dhcp-server
IP ADDRESS MAC HOSTNAME CLIENT ID EXPIRES
192.168.2.22 00:a0:85:00:02:05 00:c0:ff:ee 3591s
192.168.1.11 00:a0:85:00:04:06 foo 01:00:a0:85:00:04:06 3591s
admin@example:/> show dhcp-server statistics
DHCP offers sent : 6
DHCP ACK messages sent : 5
DHCP NAK messages sent : 0
DHCP decline messages received : 0
DHCP discover messages received : 6
DHCP request messages received : 5
DHCP release messages received : 6
DHCP inform messages received : 6
```


[^1]: This requires the system DNS resolver to be configured.
Loading

0 comments on commit 5e89d8e

Please sign in to comment.