From 38c4e50d8c738553de6f5e7a5fee3b55728ea457 Mon Sep 17 00:00:00 2001 From: Dmitriy Anisimkov Date: Tue, 17 Sep 2019 07:59:23 +0000 Subject: [PATCH] [Ada] Support for local unix sockets in GNAT.Sockets API Sock_Addr_Type has Family_Unix variant now. This variant can be created with function Unix_Local_Addr call. And this variant is working in GNAT.Socket routines where it is appropriate. 2019-09-17 Dmitriy Anisimkov gcc/ada/ * gsocket.h: Include sys/un.h. * s-oscons-tmplt.c (AF_UNIX): New constant generation. (SIZEOF_sockaddr_un): Idem. * libgnat/g-socket.ads (Family_Type): New value Family_Unix added. (Family_Inet_4_6): New subtype only for network families. (Sock_Addr_Type): Add Unbounded_String field for Family_Unix variant. (Unix_Socket_Address): Create Sock_Addr_Type from socket pathname. (Network_Socket_Address): Create Sock_Addr_Type from Inet_Addr_Type and Port_Type parameters. * libgnat/g-socket.adb: Support local unix address in socket routines. (Get_Address_Info): Disable warning about Result may be referenced before it has a value. Remove duplicated code to exit from Look_For_Supported. * libgnat/g-sothco.ads (Unix_Name_Length): New constant defining maximum number of characters in local socket address path. (Sockaddr): Add variant for Family_Unix address family. Move Sin_Port and Sin_Family to Family_Inet section. Add Sin6_Port and Sin6_Family to Family_Inet6 section. (Set_Address): Add out parameter Length to return valuable Sockaddr data length. (Get_Address): Add input parameter Length to set valuable Sockaddr data length. * libgnat/g-sothco.adb: Support local unix address in socket routines. From-SVN: r275770 --- gcc/ada/ChangeLog | 31 +++++++++ gcc/ada/gsocket.h | 1 + gcc/ada/libgnat/g-socket.adb | 121 ++++++++++++++++++++++------------- gcc/ada/libgnat/g-socket.ads | 45 ++++++++----- gcc/ada/libgnat/g-sothco.adb | 72 ++++++++++++++++++--- gcc/ada/libgnat/g-sothco.ads | 55 ++++++++++------ gcc/ada/s-oscons-tmplt.c | 18 ++++++ 7 files changed, 252 insertions(+), 91 deletions(-) diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index ee7945cff06..f5b72a08561 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,34 @@ +2019-09-17 Dmitriy Anisimkov + + * gsocket.h: Include sys/un.h. + * s-oscons-tmplt.c (AF_UNIX): New constant generation. + (SIZEOF_sockaddr_un): Idem. + * libgnat/g-socket.ads (Family_Type): New value Family_Unix + added. + (Family_Inet_4_6): New subtype only for network families. + (Sock_Addr_Type): Add Unbounded_String field for Family_Unix + variant. + (Unix_Socket_Address): Create Sock_Addr_Type from socket + pathname. + (Network_Socket_Address): Create Sock_Addr_Type from + Inet_Addr_Type and Port_Type parameters. + * libgnat/g-socket.adb: Support local unix address in socket + routines. + (Get_Address_Info): Disable warning about Result may be + referenced before it has a value. Remove duplicated code to exit + from Look_For_Supported. + * libgnat/g-sothco.ads (Unix_Name_Length): New constant defining + maximum number of characters in local socket address path. + (Sockaddr): Add variant for Family_Unix address family. Move + Sin_Port and Sin_Family to Family_Inet section. Add Sin6_Port + and Sin6_Family to Family_Inet6 section. + (Set_Address): Add out parameter Length to return valuable + Sockaddr data length. + (Get_Address): Add input parameter Length to set valuable + Sockaddr data length. + * libgnat/g-sothco.adb: Support local unix address in socket + routines. + 2019-09-17 Eric Botcazou * exp_attr.adb (Expand_Size_Attribute): Chain the special cases diff --git a/gcc/ada/gsocket.h b/gcc/ada/gsocket.h index c44e134165c..91a06b8197b 100644 --- a/gcc/ada/gsocket.h +++ b/gcc/ada/gsocket.h @@ -208,6 +208,7 @@ */ #if !(defined (VMS) || defined (__MINGW32__)) #include +#include #include #include #include diff --git a/gcc/ada/libgnat/g-socket.adb b/gcc/ada/libgnat/g-socket.adb index 51817ea94d5..8565ccff535 100644 --- a/gcc/ada/libgnat/g-socket.adb +++ b/gcc/ada/libgnat/g-socket.adb @@ -128,14 +128,12 @@ package body GNAT.Sockets is Socket_Error_Id : constant Exception_Id := Socket_Error'Identity; Host_Error_Id : constant Exception_Id := Host_Error'Identity; - type In_Addr_Union (Family : Family_Type) is record + type In_Addr_Union (Family : Family_Inet_4_6) is record case Family is when Family_Inet => In4 : In_Addr; when Family_Inet6 => In6 : In6_Addr; - when Family_Unspec => - null; end case; end record with Unchecked_Union; @@ -291,7 +289,7 @@ package body GNAT.Sockets is -- or the null selector. function Create_Address - (Family : Family_Type; Bytes : Inet_Addr_Bytes) return Inet_Addr_Type + (Family : Family_Inet_4_6; Bytes : Inet_Addr_Bytes) return Inet_Addr_Type with Inline; -- Creates address from family and Inet_Addr_Bytes array. @@ -354,7 +352,7 @@ package body GNAT.Sockets is end if; Socket := Socket_Type (Res); - Address := Get_Address (Sin); + Address := Get_Address (Sin, Len); end Accept_Socket; ------------------- @@ -465,12 +463,12 @@ package body GNAT.Sockets is is Res : C.int; Sin : aliased Sockaddr; + Len : C.int; begin - Set_Address (Sin'Unchecked_Access, Address); + Set_Address (Sin'Unchecked_Access, Address, Len); - Res := C_Bind - (C.int (Socket), Sin'Address, C.int (Lengths (Address.Family))); + Res := C_Bind (C.int (Socket), Sin'Address, Len); if Res = Failure then Raise_Socket_Error (Socket_Errno); @@ -670,11 +668,11 @@ package body GNAT.Sockets is Server : Sock_Addr_Type) return C.int is Sin : aliased Sockaddr; + Len : C.int; begin - Set_Address (Sin'Unchecked_Access, Server); + Set_Address (Sin'Unchecked_Access, Server, Len); - return C_Connect - (C.int (Socket), Sin'Address, C.int (Lengths (Server.Family))); + return C_Connect (C.int (Socket), Sin'Address, Len); end Connect_Socket; procedure Connect_Socket @@ -1039,10 +1037,17 @@ package body GNAT.Sockets is for J in Result'Range loop Look_For_Supported : loop if Iter = null then + pragma Warnings + (Off, "may be referenced before it has a value"); + return Result (1 .. J - 1); + + pragma Warnings + (On, "may be referenced before it has a value"); end if; - Result (J).Addr := Get_Address (Iter.ai_addr.all); + Result (J).Addr := + Get_Address (Iter.ai_addr.all, C.int (Iter.ai_addrlen)); if Result (J).Addr.Family = Family_Unspec then Unsupported; @@ -1071,10 +1076,6 @@ package body GNAT.Sockets is end if; Iter := Iter.ai_next; - - if Iter = null then - return Result (1 .. J - 1); - end if; end loop Look_For_Supported; Iter := Iter.ai_next; @@ -1149,15 +1150,16 @@ package body GNAT.Sockets is Numeric_Host : Boolean := False; Numeric_Serv : Boolean := False) return Host_Service is - SA : aliased Sockaddr; - H : aliased C.char_array := (1 .. SOSC.NI_MAXHOST => C.nul); - S : aliased C.char_array := (1 .. SOSC.NI_MAXSERV => C.nul); - RC : C.int; + SA : aliased Sockaddr; + H : aliased C.char_array := (1 .. SOSC.NI_MAXHOST => C.nul); + S : aliased C.char_array := (1 .. SOSC.NI_MAXSERV => C.nul); + RC : C.int; + Len : C.int; begin - Set_Address (SA'Unchecked_Access, Addr); + Set_Address (SA'Unchecked_Access, Addr, Len); RC := C_Getnameinfo - (SA'Unchecked_Access, socklen_t (Lengths (Addr.Family)), + (SA'Unchecked_Access, socklen_t (Len), H'Unchecked_Access, H'Length, S'Unchecked_Access, S'Length, (if Numeric_Host then SOSC.NI_NUMERICHOST else 0) + @@ -1197,9 +1199,6 @@ package body GNAT.Sockets is HA.In4 := To_In_Addr (Address); when Family_Inet6 => HA.In6 := To_In6_Addr (Address); - when Family_Unspec => - return (0, 0, (1, " "), (1 .. 0 => (1, " ")), - (1 .. 0 => No_Inet_Addr)); end case; Netdb_Lock; @@ -1208,8 +1207,7 @@ package body GNAT.Sockets is (HA'Address, (case Address.Family is when Family_Inet => HA.In4'Size, - when Family_Inet6 => HA.In6'Size, - when Family_Unspec => 0) / 8, + when Family_Inet6 => HA.In6'Size) / 8, Families (Address.Family), Res'Access, Buf'Address, Buflen, Err'Access) /= 0 then @@ -1280,7 +1278,7 @@ package body GNAT.Sockets is Raise_Socket_Error (Socket_Errno); end if; - return Get_Address (Sin); + return Get_Address (Sin, Len); end Get_Peer_Name; ------------------------- @@ -1364,7 +1362,7 @@ package body GNAT.Sockets is return No_Sock_Addr; end if; - return Get_Address (Sin); + return Get_Address (Sin, Len); end Get_Socket_Name; ----------------------- @@ -1572,9 +1570,8 @@ package body GNAT.Sockets is Size : constant socklen_t := (case Value.Family is when Family_Inet => 4 * Value.Sin_V4'Length, - when Family_Inet6 => 6 * 5 + 4 * 4, + when Family_Inet6 => 6 * 5 + 4 * 4); -- 1234:1234:1234:1234:1234:1234:123.123.123.123 - when Family_Unspec => 0); Dst : aliased C.char_array := (1 .. C.size_t (Size) => C.nul); Ia : aliased In_Addr_Union (Value.Family); begin @@ -1583,8 +1580,6 @@ package body GNAT.Sockets is Ia.In6 := To_In6_Addr (Value); when Family_Inet => Ia.In4 := To_In_Addr (Value); - when Family_Unspec => - return ""; end case; if Inet_Ntop @@ -1602,11 +1597,30 @@ package body GNAT.Sockets is ----------- function Image (Value : Sock_Addr_Type) return String is - Port : constant String := Value.Port'Img; function Ipv6_Brackets (S : String) return String is (if Value.Family = Family_Inet6 then "[" & S & "]" else S); begin - return Ipv6_Brackets (Image (Value.Addr)) & ':' & Port (2 .. Port'Last); + case Value.Family is + when Family_Unix => + if ASU.Length (Value.Name) > 0 + and then ASU.Element (Value.Name, 1) = ASCII.NUL + then + return '@' & ASU.Slice (Value.Name, 2, ASU.Length (Value.Name)); + else + return ASU.To_String (Value.Name); + end if; + + when Family_Inet_4_6 => + declare + Port : constant String := Value.Port'Img; + begin + return Ipv6_Brackets (Image (Value.Addr)) & ':' + & Port (2 .. Port'Last); + end; + + when Family_Unspec => + return ""; + end case; end Image; ----------- @@ -1924,6 +1938,19 @@ package body GNAT.Sockets is end if; end Netdb_Unlock; + ---------------------------- + -- Network_Socket_Address -- + ---------------------------- + + function Network_Socket_Address + (Addr : Inet_Addr_Type; Port : Port_Type) return Sock_Addr_Type is + begin + return Result : Sock_Addr_Type (Addr.Family) do + Result.Addr := Addr; + Result.Port := Port; + end return; + end Network_Socket_Address; + -------------------------------- -- Normalize_Empty_Socket_Set -- -------------------------------- @@ -2139,7 +2166,7 @@ package body GNAT.Sockets is Last := Last_Index (First => Item'First, Count => size_t (Res)); - From := Get_Address (Sin); + From := Get_Address (Sin, Len); end Receive_Socket; -------------------- @@ -2404,9 +2431,8 @@ package body GNAT.Sockets is begin if To /= null then - Set_Address (Sin'Unchecked_Access, To.all); + Set_Address (Sin'Unchecked_Access, To.all, Len); C_To := Sin'Address; - Len := C.int (Thin_Common.Lengths (To.Family)); else C_To := System.Null_Address; @@ -3055,12 +3081,11 @@ package body GNAT.Sockets is -------------------- function Create_Address - (Family : Family_Type; Bytes : Inet_Addr_Bytes) return Inet_Addr_Type + (Family : Family_Inet_4_6; Bytes : Inet_Addr_Bytes) return Inet_Addr_Type is (case Family is when Family_Inet => (Family_Inet, Bytes), - when Family_Inet6 => (Family_Inet6, Bytes), - when Family_Unspec => (Family => Family_Unspec)); + when Family_Inet6 => (Family_Inet6, Bytes)); --------------- -- Get_Bytes -- @@ -3069,15 +3094,14 @@ package body GNAT.Sockets is 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, - when Family_Unspec => (1 .. 0 => 0)); + when Family_Inet6 => Addr.Sin_V6); ---------- -- Mask -- ---------- function Mask - (Family : Family_Type; + (Family : Family_Inet_4_6; Length : Natural; Host : Boolean := False) return Inet_Addr_Type is @@ -3109,6 +3133,15 @@ package body GNAT.Sockets is end; end Mask; + ------------------------- + -- Unix_Socket_Address -- + ------------------------- + + function Unix_Socket_Address (Addr : String) return Sock_Addr_Type is + begin + return Sock_Addr_Type'(Family_Unix, ASU.To_Unbounded_String (Addr)); + end Unix_Socket_Address; + ----------- -- "and" -- ----------- diff --git a/gcc/ada/libgnat/g-socket.ads b/gcc/ada/libgnat/g-socket.ads index acd72f1e650..38d10784fc7 100644 --- a/gcc/ada/libgnat/g-socket.ads +++ b/gcc/ada/libgnat/g-socket.ads @@ -45,6 +45,7 @@ with Ada.Exceptions; with Ada.Streams; +with Ada.Strings.Unbounded; with Ada.Unchecked_Deallocation; with Interfaces.C; @@ -469,12 +470,14 @@ package GNAT.Sockets is -- Return a file descriptor to be used by external subprograms. This is -- useful for C functions that are not yet interfaced in this package. - type Family_Type is (Family_Inet, Family_Inet6, Family_Unspec); + type Family_Type is (Family_Inet, Family_Inet6, Family_Unix, Family_Unspec); -- Address family (or protocol family) identifies the communication domain -- and groups protocols with similar address formats. -- The order of the enumeration elements should not be changed unilaterally -- because the IPv6_TCP_Preferred routine rely on it. + subtype Family_Inet_4_6 is Family_Type range Family_Inet .. Family_Inet6; + type Mode_Type is (Socket_Stream, Socket_Datagram, Socket_Raw); -- Stream sockets provide connection-oriented byte streams. Datagram -- sockets support unreliable connectionless message-based communication. @@ -502,8 +505,8 @@ package GNAT.Sockets is type Inet_Addr_Comp_Type is mod 2 ** 8; -- Octet for Internet address - Inet_Addr_Bytes_Length : constant array (Family_Type) of Natural := - (Family_Inet => 4, Family_Inet6 => 16, Family_Unspec => 0); + Inet_Addr_Bytes_Length : constant array (Family_Inet_4_6) of Natural := + (Family_Inet => 4, Family_Inet6 => 16); type Inet_Addr_Bytes is array (Natural range <>) of Inet_Addr_Comp_Type; @@ -515,7 +518,7 @@ package GNAT.Sockets is subtype Inet_Addr_VN_Type is Inet_Addr_Bytes; -- For backwards compatibility - type Inet_Addr_Type (Family : Family_Type := Family_Inet) is record + type Inet_Addr_Type (Family : Family_Inet_4_6 := Family_Inet) is record case Family is when Family_Inet => Sin_V4 : Inet_Addr_V4_Type := (others => 0); @@ -523,9 +526,6 @@ package GNAT.Sockets is when Family_Inet6 => Sin_V6 : Inet_Addr_V6_Type := (others => 0); - when Family_Unspec => - null; - end case; end record; @@ -541,10 +541,6 @@ package GNAT.Sockets is No_Inet_Addr : constant Inet_Addr_Type; -- Uninitialized inet address - Unspecified_Addr : constant Inet_Addr_Type; - -- Unspecified address. Unlike of No_Inet_Addr the constraint is - -- Family_Unspec for this constant. - Broadcast_Inet_Addr : constant Inet_Addr_Type; -- Broadcast destination address in the current network @@ -581,7 +577,7 @@ package GNAT.Sockets is -- Functions to handle masks and prefixes function Mask - (Family : Family_Type; + (Family : Family_Inet_4_6; Length : Natural; Host : Boolean := False) return Inet_Addr_Type; -- Return an address mask of the given family with the given prefix length. @@ -596,8 +592,15 @@ package GNAT.Sockets is -- same address family). type Sock_Addr_Type (Family : Family_Type := Family_Inet) is record - Addr : Inet_Addr_Type (Family); - Port : Port_Type; + case Family is + when Family_Unix => + Name : Ada.Strings.Unbounded.Unbounded_String; + when Family_Inet_4_6 => + Addr : Inet_Addr_Type (Family); + Port : Port_Type; + when Family_Unspec => + null; + end case; end record; pragma No_Component_Reordering (Sock_Addr_Type); -- Socket addresses fully define a socket connection with protocol family, @@ -619,12 +622,20 @@ package GNAT.Sockets is -- 8 hextets in hexadecimal format separated by colons. function Image (Value : Sock_Addr_Type) return String; - -- Return inet address image and port image separated by a colon + -- Return socket address image. Network socket address image will be with + -- a port image separated by a colon. function Inet_Addr (Image : String) return Inet_Addr_Type; -- Convert address image from numbers-dots-and-colons notation into an -- inet address. + function Unix_Socket_Address (Addr : String) return Sock_Addr_Type; + -- Convert unix local socket name to Sock_Addr_Type + + function Network_Socket_Address + (Addr : Inet_Addr_Type; Port : Port_Type) return Sock_Addr_Type; + -- Create network socket address + -- Host entries provide complete information on a given host: the official -- name, an array of alternative names or aliases and array of network -- addresses. @@ -1439,6 +1450,8 @@ package GNAT.Sockets is private + package ASU renames Ada.Strings.Unbounded; + type Socket_Type is new Integer; No_Socket : constant Socket_Type := -1; @@ -1493,8 +1506,6 @@ private (Family_Inet6, (others => 0)); No_Inet_Addr : constant Inet_Addr_Type := (Family_Inet, (others => 0)); - Unspecified_Addr : constant Inet_Addr_Type := - (Family => Family_Unspec); Broadcast_Inet_Addr : constant Inet_Addr_Type := (Family_Inet, (others => 255)); Loopback_Inet_Addr : constant Inet_Addr_Type := diff --git a/gcc/ada/libgnat/g-sothco.adb b/gcc/ada/libgnat/g-sothco.adb index eb15ac2e842..9794d8b0ea1 100644 --- a/gcc/ada/libgnat/g-sothco.adb +++ b/gcc/ada/libgnat/g-sothco.adb @@ -37,18 +37,59 @@ package body GNAT.Sockets.Thin_Common is procedure Set_Address (Sin : Sockaddr_Access; - Address : Sock_Addr_Type) + Address : Sock_Addr_Type; + Length : out C.int) is + use type C.char; + + function Network_Port return C.unsigned_short is + (Short_To_Network (C.unsigned_short (Address.Port))) with Inline; + begin Set_Family (Sin.Sin_Family, Address.Family); - Sin.Sin_Port := Short_To_Network (C.unsigned_short (Address.Port)); + + Length := C.int (Lengths (Address.Family)); case Address.Family is when Family_Inet => + Sin.Sin_Port := Network_Port; Sin.Sin_Addr := To_In_Addr (Address.Addr); + when Family_Inet6 => + Sin.Sin6_Port := Network_Port; Sin.Sin6_Addr := To_In6_Addr (Address.Addr); Sin.Sin6_Scope_Id := 0; + + when Family_Unix => + declare + use type C.size_t; + Name_Len : constant C.size_t := + C.size_t (ASU.Length (Address.Name)); + begin + Length := Sockaddr_Length_And_Family'Size / System.Storage_Unit + + C.int (Name_Len); + + if Name_Len > Sin.Sun_Path'Length then + raise Constraint_Error with + "Too big address length for UNIX local communication"; + end if; + + if Name_Len = 0 then + Sin.Sun_Path (1) := C.nul; + + else + Sin.Sun_Path (1 .. Name_Len) := + C.To_C (ASU.To_String (Address.Name), Append_Nul => False); + + if Sin.Sun_Path (1) /= C.nul + and then Name_Len < Sin.Sun_Path'Length + then + Sin.Sun_Path (Name_Len + 1) := C.nul; + Length := Length + 1; + end if; + end if; + end; + when Family_Unspec => null; end case; @@ -58,26 +99,39 @@ package body GNAT.Sockets.Thin_Common is -- Get_Address -- ----------------- - function Get_Address (Sin : Sockaddr) return Sock_Addr_Type is - use type C.unsigned_short; + function Get_Address + (Sin : Sockaddr; Length : C.int) return Sock_Addr_Type + is + use type C.unsigned_short, C.size_t, C.char, SOSC.OS_Type; Family : constant C.unsigned_short := (if SOSC.Has_Sockaddr_Len = 0 then Sin.Sin_Family.Short_Family else C.unsigned_short (Sin.Sin_Family.Char_Family)); - AF_INET6_Defined : constant Boolean := SOSC.AF_INET6 > 0; Result : Sock_Addr_Type - (if AF_INET6_Defined and then SOSC.AF_INET6 = Family then Family_Inet6 + (if SOSC.AF_INET6 > 0 and then SOSC.AF_INET6 = Family then Family_Inet6 + elsif SOSC.AF_UNIX > 0 and then SOSC.AF_UNIX = Family then Family_Unix elsif SOSC.AF_INET = Family then Family_Inet else Family_Unspec); begin - Result.Port := Port_Type (Network_To_Short (Sin.Sin_Port)); - case Result.Family is when Family_Inet => + Result.Port := Port_Type (Network_To_Short (Sin.Sin_Port)); To_Inet_Addr (Sin.Sin_Addr, Result.Addr); when Family_Inet6 => + Result.Port := Port_Type (Network_To_Short (Sin.Sin6_Port)); To_Inet_Addr (Sin.Sin6_Addr, Result.Addr); + when Family_Unix => + if Length > Sin.Sin_Family'Size / System.Storage_Unit then + Result.Name := ASU.To_Unbounded_String + (C.To_Ada + (Sin.Sun_Path + (1 .. C.size_t (Length) + - Sin.Sin_Family'Size / System.Storage_Unit), + Trim_Nul => Sin.Sun_Path (1) /= C.nul + or else SOSC.Target_OS = SOSC.Windows)); + end if; + when Family_Unspec => - Result.Addr := (Family => Family_Unspec); + null; end case; return Result; diff --git a/gcc/ada/libgnat/g-sothco.ads b/gcc/ada/libgnat/g-sothco.ads index c62161d7857..a68019c5125 100644 --- a/gcc/ada/libgnat/g-sothco.ads +++ b/gcc/ada/libgnat/g-sothco.ads @@ -75,11 +75,13 @@ package GNAT.Sockets.Thin_Common is Families : constant array (Family_Type) of C.int := (Family_Unspec => SOSC.AF_UNSPEC, + Family_Unix => SOSC.AF_UNIX, Family_Inet => SOSC.AF_INET, Family_Inet6 => SOSC.AF_INET6); Lengths : constant array (Family_Type) of C.unsigned_char := (Family_Unspec => 0, + Family_Unix => SOSC.SIZEOF_sockaddr_un, Family_Inet => SOSC.SIZEOF_sockaddr_in, Family_Inet6 => SOSC.SIZEOF_sockaddr_in6); @@ -106,9 +108,7 @@ package GNAT.Sockets.Thin_Common is when False => Short_Family : C.unsigned_short; end case; - end record; - pragma Unchecked_Union (Sockaddr_Length_And_Family); - pragma Convention (C, Sockaddr_Length_And_Family); + end record with Unchecked_Union, Convention => C; procedure Set_Family (Length_And_Family : out Sockaddr_Length_And_Family; @@ -122,9 +122,7 @@ package GNAT.Sockets.Thin_Common is type In_Addr is record S_B1, S_B2, S_B3, S_B4 : C.unsigned_char; - end record; - for In_Addr'Alignment use C.int'Alignment; - pragma Convention (C, In_Addr); + end record with Convention => C, Alignment => C.int'Alignment; -- IPv4 address, represented as a network-order C.int. Note that the -- underlying operating system may assume that values of this type have -- C.int alignment, so we need to provide a suitable alignment clause here. @@ -138,9 +136,10 @@ package GNAT.Sockets.Thin_Common is Result : out Inet_Addr_Type); -- Conversion functions - type In6_Addr is array (1 .. 16) of C.unsigned_char; - for In6_Addr'Alignment use C.int'Alignment; - pragma Convention (C, In6_Addr); + type In6_Addr is array (1 .. 16) of C.unsigned_char with Convention => C; + + Unix_Name_Length : constant := 108; + -- Maximum length for local unix socket name function To_In6_Addr (Addr : Inet_Addr_Type) return In6_Addr; procedure To_Inet_Addr @@ -149,14 +148,14 @@ package GNAT.Sockets.Thin_Common is -- Conversion functions type Sockaddr (Family : Family_Type := Family_Inet) is record - Sin_Family : Sockaddr_Length_And_Family; - -- Address family (and address length on some platforms) - - Sin_Port : C.unsigned_short; - -- Port in network byte order - case Family is when Family_Inet => + Sin_Family : Sockaddr_Length_And_Family; + -- Address family (and address length on some platforms) + + Sin_Port : C.unsigned_short; + -- Port in network byte order + Sin_Addr : In_Addr := (others => 0); -- IPv4 address @@ -165,16 +164,28 @@ package GNAT.Sockets.Thin_Common is -- -- Note that some platforms require that all unused (reserved) bytes -- in addresses be initialized to 0 (e.g. VxWorks). + when Family_Inet6 => + Sin6_Family : Sockaddr_Length_And_Family; + -- Address family (and address length on some platforms) + + Sin6_Port : C.unsigned_short; + -- Port in network byte order + Sin6_FlowInfo : Interfaces.Unsigned_32 := 0; Sin6_Addr : In6_Addr := (others => 0); Sin6_Scope_Id : Interfaces.Unsigned_32 := 0; + + when Family_Unix => + Sun_Family : Sockaddr_Length_And_Family; + -- Address family (and address length on some platforms) + + Sun_Path : C.char_array (1 .. Unix_Name_Length); + when Family_Unspec => null; end case; - end record; - pragma Unchecked_Union (Sockaddr); - pragma Convention (C, Sockaddr); + end record with Convention => C, Unchecked_Union; -- Internet socket address type Sockaddr_Access is access all Sockaddr; @@ -183,13 +194,15 @@ package GNAT.Sockets.Thin_Common is procedure Set_Address (Sin : Sockaddr_Access; - Address : Sock_Addr_Type); + Address : Sock_Addr_Type; + Length : out C.int); -- Initialise all necessary fields in Sin from Address. -- Set appropriate Family, Port, and either Sin.Sin_Addr or Sin.Sin6_Addr -- depend on family. + -- Set the Length out parameter to the valuable Sockaddr data length. - function Get_Address (Sin : Sockaddr) return Sock_Addr_Type; - -- Get Sock_Addr_Type from Sockaddr + function Get_Address (Sin : Sockaddr; Length : C.int) return Sock_Addr_Type; + -- Get Sock_Addr_Type from Sockaddr and its valuable data Length ------------------ -- Host entries -- diff --git a/gcc/ada/s-oscons-tmplt.c b/gcc/ada/s-oscons-tmplt.c index 655d68a79f2..4c3ecc60572 100644 --- a/gcc/ada/s-oscons-tmplt.c +++ b/gcc/ada/s-oscons-tmplt.c @@ -1053,6 +1053,11 @@ CND(AF_INET, "IPv4 address family") #endif CND(AF_INET6, "IPv6 address family") +#ifndef AF_UNIX +# define AF_UNIX -1 +#endif +CND(AF_UNIX, "Local unix family") + #ifndef AF_UNSPEC # define AF_UNSPEC -1 #else @@ -1701,6 +1706,19 @@ CND(SIZEOF_sockaddr_in, "struct sockaddr_in") #endif CND(SIZEOF_sockaddr_in6, "struct sockaddr_in6") +/** + ** The sockaddr_un structure is not defined in MINGW C headers + ** but Windows supports it from build 17063. + **/ +#if defined(__MINGW32__) +struct sockaddr_un { + ADDRESS_FAMILY sun_family; /* AF_UNIX */ + char sun_path[108]; /* Pathname */ +}; +#endif +#define SIZEOF_sockaddr_un (sizeof (struct sockaddr_un)) +CND(SIZEOF_sockaddr_un, "struct sockaddr_un") + #define SIZEOF_fd_set (sizeof (fd_set)) CND(SIZEOF_fd_set, "fd_set") CND(FD_SETSIZE, "Max fd value") -- 2.30.2