Skip to content

Commit

Permalink
Set broadcast IP address for static IPv4 config
Browse files Browse the repository at this point in the history
When running the `"ip addr"` command, the broadcast IP address wasn't
getting set properly:

```
4: uap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq qlen 1000
    link/ether b4:8c:9d:9c:2a:0b brd ff:ff:ff:ff:ff:ff
    inet 172.16.61.1/24 brd 172.16.61.1 scope global uap0
       valid_lft forever preferred_lft forever
```

I'm not sure when/how this started, but this commit fixes the issue by
always setting it to the all-ones host (RFC 922):

```
4: uap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq qlen 1000
    link/ether b4:8c:9d:9c:2a:0b brd ff:ff:ff:ff:ff:ff
    inet 172.16.61.1/24 brd 172.16.61.255 scope global uap0
       valid_lft forever preferred_lft forever
```

The code supports /31 and /32 subnets to avoid raising should this ever
be called for them.
  • Loading branch information
fhunleth committed May 15, 2023
1 parent c5808c6 commit c52dede
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 4 deletions.
21 changes: 21 additions & 0 deletions lib/vintage_net/ip.ex
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,25 @@ defmodule VintageNet.IP do

{new_a, new_b, new_c, new_d, new_e, new_f, new_g, new_h}
end

@doc """
Return the IPv4 broadcast address for the specified subnet and prefix
Examples:
iex> VintageNet.IP.ipv4_broadcast_address({192, 168, 1, 50}, 24)
{192, 168, 1, 255}
iex> VintageNet.IP.ipv4_broadcast_address({74, 125, 227, 0}, 29)
{74, 125, 227, 7}
"""
@spec ipv4_broadcast_address(:inet.ip4_address(), VintageNet.prefix_length()) ::
:inet.ip4_address()
def ipv4_broadcast_address({a, b, c, d}, subnet_bits)
when subnet_bits >= 0 and subnet_bits <= 32 do
not_subnet_bits = 32 - subnet_bits
<<subnet::size(subnet_bits), _::size(not_subnet_bits)>> = <<a, b, c, d>>
<<new_a, new_b, new_c, new_d>> = <<subnet::size(subnet_bits), -1::size(not_subnet_bits)>>
{new_a, new_b, new_c, new_d}
end
end
16 changes: 15 additions & 1 deletion lib/vintage_net/ip/ipv4_config.ex
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,9 @@ defmodule VintageNet.IP.IPv4Config do
) do
addr_subnet = IP.cidr_to_string(ipv4.address, ipv4.prefix_length)

broadcast_addr =
IP.ipv4_broadcast_address(ipv4.address, ipv4.prefix_length) |> IP.ip_to_string()

route_manager_up =
case ipv4[:gateway] do
nil ->
Expand All @@ -223,7 +226,18 @@ defmodule VintageNet.IP.IPv4Config do
up_cmds ++
[
{:run_ignore_errors, "ip", ["addr", "flush", "dev", ifname, "label", ifname]},
{:run, "ip", ["addr", "add", addr_subnet, "dev", ifname, "label", ifname]},
{:run, "ip",
[
"addr",
"add",
addr_subnet,
"dev",
ifname,
"broadcast",
broadcast_addr,
"label",
ifname
]},
{:run, "ip", ["link", "set", ifname, "up"]},
route_manager_up,
resolver_up
Expand Down
39 changes: 36 additions & 3 deletions test/vintage_net/ip/ipv4_config_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,18 @@ defmodule VintageNet.IP.IPv4ConfigTest do
],
up_cmds: [
{:run_ignore_errors, "ip", ["addr", "flush", "dev", "eth0", "label", "eth0"]},
{:run, "ip", ["addr", "add", "192.168.1.2/24", "dev", "eth0", "label", "eth0"]},
{:run, "ip",
[
"addr",
"add",
"192.168.1.2/24",
"dev",
"eth0",
"broadcast",
"192.168.1.255",
"label",
"eth0"
]},
{:run, "ip", ["link", "set", "eth0", "up"]},
{:fun, VintageNet.RouteManager, :set_route,
["eth0", [{{192, 168, 1, 2}, 24}], {192, 168, 1, 1}]},
Expand Down Expand Up @@ -182,7 +193,18 @@ defmodule VintageNet.IP.IPv4ConfigTest do
],
up_cmds: [
{:run_ignore_errors, "ip", ["addr", "flush", "dev", "eth0", "label", "eth0"]},
{:run, "ip", ["addr", "add", "192.168.1.2/24", "dev", "eth0", "label", "eth0"]},
{:run, "ip",
[
"addr",
"add",
"192.168.1.2/24",
"dev",
"eth0",
"broadcast",
"192.168.1.255",
"label",
"eth0"
]},
{:run, "ip", ["link", "set", "eth0", "up"]},
{:fun, VintageNet.RouteManager, :clear_route, ["eth0"]},
{:fun, VintageNet.NameResolver, :clear, ["eth0"]}
Expand Down Expand Up @@ -228,7 +250,18 @@ defmodule VintageNet.IP.IPv4ConfigTest do
],
up_cmds: [
{:run_ignore_errors, "ip", ["addr", "flush", "dev", "eth0", "label", "eth0"]},
{:run, "ip", ["addr", "add", "192.168.1.2/24", "dev", "eth0", "label", "eth0"]},
{:run, "ip",
[
"addr",
"add",
"192.168.1.2/24",
"dev",
"eth0",
"broadcast",
"192.168.1.255",
"label",
"eth0"
]},
{:run, "ip", ["link", "set", "eth0", "up"]},
{:fun, VintageNet.RouteManager, :clear_route, ["eth0"]},
{:fun, VintageNet.NameResolver, :setup, ["eth0", nil, [{1, 2, 3, 4}]]}
Expand Down

0 comments on commit c52dede

Please sign in to comment.