Skip to content

Commit

Permalink
replace {:ip, addr} with {:bind_to_device, ifname} in connectivity ch…
Browse files Browse the repository at this point in the history
…ecks

Signed-off-by: Connor Rigby <[email protected]>
  • Loading branch information
ConnorRigby committed Jun 13, 2024
1 parent f38417e commit bed17af
Show file tree
Hide file tree
Showing 5 changed files with 13 additions and 52 deletions.
6 changes: 3 additions & 3 deletions lib/vintage_net/connectivity/http_client.ex
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ defmodule VintageNet.Connectivity.HTTPClient do
end

@doc "Create a request from the specified IP address"
@spec create_request(URI.t(), :inet.ip_address(), [{String.t(), String.t()}]) :: Request.t()
def create_request(uri, src_ip, headers \\ []) do
@spec create_request(URI.t(), VintageNet.ifname(), [{String.t(), String.t()}]) :: Request.t()
def create_request(uri, ifname, headers \\ []) do
headers =
[{"User-Agent", "VintageNet/#{version()}"}, {"Host", uri.host}, {"Connection", "close"}] ++
headers
Expand All @@ -41,7 +41,7 @@ defmodule VintageNet.Connectivity.HTTPClient do
headers,
[
:binary,
ip: src_ip,
bind_to_device: ifname,
packet: :raw,
active: false
]
Expand Down
37 changes: 1 addition & 36 deletions lib/vintage_net/connectivity/tcp_ping.ex
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,7 @@ defmodule VintageNet.Connectivity.TCPPing do
# interface. I.e., errors on other interfaces mess up DNS even if the
# one of interest is ok.
with {:ok, dest_ip} <- VintageNet.IP.ip_to_tuple(host),
{:ok, src_ip} <- get_interface_address(ifname, family(dest_ip)),
{:ok, tcp} <- :gen_tcp.connect(dest_ip, port, [ip: src_ip], @ping_timeout) do
{:ok, tcp} <- :gen_tcp.connect(dest_ip, port, [bind_to_device: ifname], @ping_timeout) do
_ = :gen_tcp.close(tcp)
{:ok, {evaluate_result(family(dest_ip), dest_ip), []}}
else
Expand All @@ -97,40 +96,6 @@ defmodule VintageNet.Connectivity.TCPPing do
end
end

@doc """
Helper function for getting an ip address attached to an interface for use with the
`ip` keyword argument for :gen_tcp.connect/3 and related functions.
"""
@spec get_interface_address(VintageNet.ifname(), :inet | :inet6) ::
{:ok, VintageNet.any_ip_address()}
| {:error, :inet.posix() | :if_not_found | :no_suitable_ip_address}
def get_interface_address(ifname, family) do
with {:ok, addresses} <- :inet.getifaddrs(),
{:ok, params} <- find_addresses_on_interface(addresses, ifname) do
find_ip_addr(params, family)
end
end

defp find_addresses_on_interface(addresses, ifname) do
ifname_cl = to_charlist(ifname)

case Enum.find(addresses, fn {k, _v} -> k == ifname_cl end) do
{^ifname_cl, params} -> {:ok, params}
_ -> {:error, :if_not_found}
end
end

defp find_ip_addr(params, family) do
case Enum.find(params, &ip_addr?(family, &1)) do
{:addr, addr} -> {:ok, addr}
_ -> {:error, :no_suitable_ip_address}
end
end

defp ip_addr?(:inet, {:addr, {_, _, _, _}}), do: true
defp ip_addr?(:inet6, {:addr, {_, _, _, _, _, _, _, _}}), do: true
defp ip_addr?(_family, _), do: false

defp family({_, _, _, _}), do: :inet
defp family({_, _, _, _, _, _, _, _}), do: :inet6

Expand Down
10 changes: 4 additions & 6 deletions lib/vintage_net/connectivity/web_request.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ defmodule VintageNet.Connectivity.WebRequest do
"""

@behaviour VintageNet.Connectivity.Check
import VintageNet.Connectivity.TCPPing, only: [get_interface_address: 2]
alias VintageNet.Connectivity.HTTPClient
require Logger

Expand Down Expand Up @@ -64,8 +63,7 @@ defmodule VintageNet.Connectivity.WebRequest do

@impl VintageNet.Connectivity.Check
def check(ifname, {__MODULE__, options}) do
with {:ok, src_ip} <- get_interface_address(ifname, :inet),
{:ok, body} <- make_request(src_ip, options) do
with {:ok, body} <- make_request(ifname, options) do
evaluate_match(body, options[:match])
else
{:error, :econnrefused} ->
Expand All @@ -81,9 +79,9 @@ defmodule VintageNet.Connectivity.WebRequest do
end
end

@spec make_request(:inet.ip_address(), Keyword.t()) :: {:ok, String.t()} | {:error, term()}
defp make_request(src_ip, options) do
request = HTTPClient.create_request(options[:url], src_ip)
@spec make_request(VintageNet.ifname(), Keyword.t()) :: {:ok, String.t()} | {:error, term()}
defp make_request(ifname, options) do
request = HTTPClient.create_request(options[:url], ifname)

case HTTPClient.make_request(request, options[:max_response_size], options[:timeout_millis]) do
{:ok, {{_version, _status, _status_message}, _headers, body}} -> {:ok, body}
Expand Down
10 changes: 4 additions & 6 deletions lib/vintage_net/connectivity/when_where.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ defmodule VintageNet.Connectivity.WhenWhere do
"""

@behaviour VintageNet.Connectivity.Check
import VintageNet.Connectivity.TCPPing, only: [get_interface_address: 2]
import VintageNet.Connectivity.WebRequest, only: [validate_url: 1]

alias VintageNet.Connectivity.HTTPClient
Expand Down Expand Up @@ -45,8 +44,7 @@ defmodule VintageNet.Connectivity.WhenWhere do
def check(ifname, {__MODULE__, options}) do
nonce = Base.encode16(:rand.bytes(4))

with {:ok, src_ip} <- get_interface_address(ifname, :inet),
{:ok, headers, reply} <- make_request(src_ip, nonce, options),
with {:ok, headers, reply} <- make_request(ifname, nonce, options),
:ok <- validate_nonce(headers, nonce),
properties <- build_props(Enum.to_list(reply), []) do
{:ok, {:internet, properties}}
Expand All @@ -62,12 +60,12 @@ defmodule VintageNet.Connectivity.WhenWhere do
end
end

@spec make_request(:inet.ip_address(), String.t(), Keyword.t()) ::
@spec make_request(VintageNet.ifname(), String.t(), Keyword.t()) ::
{:ok, [{String.t(), String.t()}], map()} | {:error, term()}
defp make_request(src_ip, nonce, options) do
defp make_request(ifname, nonce, options) do
url = %{options[:url] | query: "nonce=#{nonce}"}
request_headers = [{"Content-Type", "application/x-erlang-binary"}]
request = HTTPClient.create_request(url, src_ip, request_headers)
request = HTTPClient.create_request(url, ifname, request_headers)

case HTTPClient.make_request(request, options[:max_response_size], options[:timeout_millis]) do
{:ok, {{_version, 200, _status_message}, headers, body}} ->
Expand Down
2 changes: 1 addition & 1 deletion test/vintage_net/connectivity/tcp_ping_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ defmodule VintageNet.Connectivity.TCPPingTest do
test "ping IPv4 known hosts" do
ifname = Utils.get_ifname_for_tests()

assert TCPPing.check(ifname, {TCPPing, host: "127.0.0.1", port: 80}) == {:ok, {:lan, []}}
assert TCPPing.check("lo", {TCPPing, host: "127.0.0.1", port: 80}) == {:ok, {:lan, []}}
assert TCPPing.check(ifname, {TCPPing, host: "1.1.1.1", port: 53}) == {:ok, {:internet, []}}
end

Expand Down

0 comments on commit bed17af

Please sign in to comment.