-- Symmetric operation
function Image
- (Val : Inet_Addr_VN_Type;
- Hex : Boolean := False) return String;
+ (Val : Inet_Addr_Bytes;
+ Hex : Boolean := False) return String;
-- Output an array of inet address components in hex or decimal mode
function Is_IP_Address (Name : String) return Boolean;
-- Create_Selector has been called and Close_Selector has not been called,
-- or the null selector.
+ function Create_Address
+ (Family : Family_Type; Bytes : Inet_Addr_Bytes) return Inet_Addr_Type
+ with Inline;
+ -- Creates address from family and Inet_Addr_Bytes array.
+
+ function Get_Bytes (Addr : Inet_Addr_Type) return Inet_Addr_Bytes
+ with Inline;
+ -- Extract bytes from address
+
---------
-- "+" --
---------
-----------
function Image
- (Val : Inet_Addr_VN_Type;
+ (Val : Inet_Addr_Bytes;
Hex : Boolean := False) return String
is
-- The largest Inet_Addr_Comp_Type image occurs with IPv4. It
function Image (Value : Inet_Addr_Type) return String is
begin
if Value.Family = Family_Inet then
- return Image (Inet_Addr_VN_Type (Value.Sin_V4), Hex => False);
+ return Image (Inet_Addr_Bytes (Value.Sin_V4), Hex => False);
else
- return Image (Inet_Addr_VN_Type (Value.Sin_V6), Hex => True);
+ return Image (Inet_Addr_Bytes (Value.Sin_V6), Hex => True);
end if;
end Image;
-- The elaboration and finalization of this object perform the required
-- initialization and cleanup actions for the sockets library.
+ --------------------
+ -- Create_Address --
+ --------------------
+
+ function Create_Address
+ (Family : Family_Type; Bytes : Inet_Addr_Bytes) return Inet_Addr_Type
+ is
+ (case Family is
+ when Family_Inet => (Family_Inet, Bytes),
+ when Family_Inet6 => (Family_Inet6, Bytes));
+
+ ---------------
+ -- Get_Bytes --
+ ---------------
+
+ function Get_Bytes (Addr : Inet_Addr_Type) return Inet_Addr_Bytes is
+ (case Addr.Family is
+ when Family_Inet => Addr.Sin_V4,
+ when Family_Inet6 => Addr.Sin_V6);
+
+ ----------
+ -- Mask --
+ ----------
+
+ function Mask
+ (Family : Family_Type;
+ Length : Natural;
+ Host : Boolean := False) return Inet_Addr_Type
+ is
+ Addr_Len : constant Natural := Inet_Addr_Bytes_Length (Family);
+ begin
+ if Length > 8 * Addr_Len then
+ raise Constraint_Error with
+ "invalid mask length for address family " & Family'Img;
+ end if;
+
+ declare
+ B : Inet_Addr_Bytes (1 .. Addr_Len);
+ Part : Inet_Addr_Comp_Type;
+ begin
+ for J in 1 .. Length / 8 loop
+ B (J) := (if Host then 0 else 255);
+ end loop;
+
+ if Length < 8 * Addr_Len then
+ Part := 2 ** (8 - Length mod 8) - 1;
+ B (Length / 8 + 1) := (if Host then Part else not Part);
+
+ for J in Length / 8 + 2 .. B'Last loop
+ B (J) := (if Host then 255 else 0);
+ end loop;
+ end if;
+
+ return Create_Address (Family, B);
+ end;
+ end Mask;
+
+ -----------
+ -- "and" --
+ -----------
+
+ function "and" (Addr, Mask : Inet_Addr_Type) return Inet_Addr_Type is
+ begin
+ if Addr.Family /= Mask.Family then
+ raise Constraint_Error with "incompatible address families";
+ end if;
+
+ declare
+ A : constant Inet_Addr_Bytes := Get_Bytes (Addr);
+ M : constant Inet_Addr_Bytes := Get_Bytes (Mask);
+ R : Inet_Addr_Bytes (A'Range);
+
+ begin
+ for J in A'Range loop
+ R (J) := A (J) and M (J);
+ end loop;
+ return Create_Address (Addr.Family, R);
+ end;
+ end "and";
+
+ ----------
+ -- "or" --
+ ----------
+
+ function "or" (Net, Host : Inet_Addr_Type) return Inet_Addr_Type is
+ begin
+ if Net.Family /= Host.Family then
+ raise Constraint_Error with "incompatible address families";
+ end if;
+
+ declare
+ N : constant Inet_Addr_Bytes := Get_Bytes (Net);
+ H : constant Inet_Addr_Bytes := Get_Bytes (Host);
+ R : Inet_Addr_Bytes (N'Range);
+
+ begin
+ for J in N'Range loop
+ R (J) := N (J) or H (J);
+ end loop;
+ return Create_Address (Net.Family, R);
+ end;
+ end "or";
+
+ -----------
+ -- "not" --
+ -----------
+
+ function "not" (Mask : Inet_Addr_Type) return Inet_Addr_Type is
+ M : constant Inet_Addr_Bytes := Get_Bytes (Mask);
+ R : Inet_Addr_Bytes (M'Range);
+ begin
+ for J in R'Range loop
+ R (J) := not M (J);
+ end loop;
+ return Create_Address (Mask.Family, R);
+ end "not";
+
end GNAT.Sockets;
No_Port : constant Port_Type;
-- Uninitialized port number
- type Inet_Addr_Type (Family : Family_Type := Family_Inet) is private;
+ type Inet_Addr_Comp_Type is mod 2 ** 8;
+ -- Octet for Internet address
+
+ Inet_Addr_Bytes_Length : constant array (Family_Type) of Positive :=
+ (Family_Inet => 4, Family_Inet6 => 16);
+
+ type Inet_Addr_Bytes is array (Natural range <>) of Inet_Addr_Comp_Type;
+
+ subtype Inet_Addr_V4_Type is
+ Inet_Addr_Bytes (1 .. Inet_Addr_Bytes_Length (Family_Inet));
+ subtype Inet_Addr_V6_Type is
+ Inet_Addr_Bytes (1 .. Inet_Addr_Bytes_Length (Family_Inet6));
+
+ subtype Inet_Addr_VN_Type is Inet_Addr_Bytes;
+ -- For backwards compatibility
+
+ type Inet_Addr_Type (Family : Family_Type := Family_Inet) is record
+ case Family is
+ when Family_Inet =>
+ Sin_V4 : Inet_Addr_V4_Type := (others => 0);
+
+ when Family_Inet6 =>
+ Sin_V6 : Inet_Addr_V6_Type := (others => 0);
+ end case;
+ end record;
+
-- An Internet address depends on an address family (IPv4 contains 4 octets
-- and IPv6 contains 16 octets). Any_Inet_Addr is a special value treated
-- like a wildcard enabling all addresses. No_Inet_Addr provides a special
All_Hosts_Group_Inet_Addr : constant Inet_Addr_Type;
All_Routers_Group_Inet_Addr : constant Inet_Addr_Type;
+ -- Functions to handle masks and prefixes
+
+ function Mask
+ (Family : Family_Type;
+ Length : Natural;
+ Host : Boolean := False) return Inet_Addr_Type;
+ -- Return an address mask of the given family with the given prefix length.
+ -- If Host is False, this is a network mask (i.e. network bits are 1,
+ -- and host bits are 0); if Host is True, this is a host mask (i.e.
+ -- network bits are 0, and host bits are 1).
+
+ function "and" (Addr, Mask : Inet_Addr_Type) return Inet_Addr_Type;
+ function "or" (Net, Host : Inet_Addr_Type) return Inet_Addr_Type;
+ function "not" (Mask : Inet_Addr_Type) return Inet_Addr_Type;
+ -- Bit-wise operations on inet addresses (both operands must have the
+ -- same address family).
+
type Sock_Addr_Type (Family : Family_Type := Family_Inet) is record
Addr : Inet_Addr_Type (Family);
Port : Port_Type;
-- undefined if Last = No_Socket.
end record;
- subtype Inet_Addr_Comp_Type is Natural range 0 .. 255;
- -- Octet for Internet address
-
- type Inet_Addr_VN_Type is array (Natural range <>) of Inet_Addr_Comp_Type;
-
- subtype Inet_Addr_V4_Type is Inet_Addr_VN_Type (1 .. 4);
- subtype Inet_Addr_V6_Type is Inet_Addr_VN_Type (1 .. 16);
-
- type Inet_Addr_Type (Family : Family_Type := Family_Inet) is record
- case Family is
- when Family_Inet =>
- Sin_V4 : Inet_Addr_V4_Type := (others => 0);
-
- when Family_Inet6 =>
- Sin_V6 : Inet_Addr_V6_Type := (others => 0);
- end case;
- end record;
-
Any_Port : constant Port_Type := 0;
No_Port : constant Port_Type := 0;