diff --git a/lib/vintage_net/ip.ex b/lib/vintage_net/ip.ex index bbe2548c..9bb7e3b7 100644 --- a/lib/vintage_net/ip.ex +++ b/lib/vintage_net/ip.ex @@ -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 + <> = <> + <> = <> + {new_a, new_b, new_c, new_d} + end end diff --git a/lib/vintage_net/ip/ipv4_config.ex b/lib/vintage_net/ip/ipv4_config.ex index 43e74fe8..d2e40906 100644 --- a/lib/vintage_net/ip/ipv4_config.ex +++ b/lib/vintage_net/ip/ipv4_config.ex @@ -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 -> @@ -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 diff --git a/test/vintage_net/ip/ipv4_config_test.exs b/test/vintage_net/ip/ipv4_config_test.exs index 376fdb5e..18adacbc 100644 --- a/test/vintage_net/ip/ipv4_config_test.exs +++ b/test/vintage_net/ip/ipv4_config_test.exs @@ -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}]}, @@ -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"]} @@ -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}]]}