comparison gcc/ada/libgnat/g-socket.adb @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
comparison
equal deleted inserted replaced
131:84e7813d76e9 145:1830386684a0
4 -- -- 4 -- --
5 -- G N A T . S O C K E T S -- 5 -- G N A T . S O C K E T S --
6 -- -- 6 -- --
7 -- B o d y -- 7 -- B o d y --
8 -- -- 8 -- --
9 -- Copyright (C) 2001-2018, AdaCore -- 9 -- Copyright (C) 2001-2019, AdaCore --
10 -- -- 10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under -- 11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- -- 12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- -- 13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- 14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
29 -- -- 29 -- --
30 ------------------------------------------------------------------------------ 30 ------------------------------------------------------------------------------
31 31
32 with Ada.Streams; use Ada.Streams; 32 with Ada.Streams; use Ada.Streams;
33 with Ada.Exceptions; use Ada.Exceptions; 33 with Ada.Exceptions; use Ada.Exceptions;
34 with Ada.Containers.Generic_Array_Sort;
34 with Ada.Finalization; 35 with Ada.Finalization;
35 with Ada.Unchecked_Conversion; 36 with Ada.Unchecked_Conversion;
36 37
37 with GNAT.Sockets.Thin_Common; use GNAT.Sockets.Thin_Common; 38 with GNAT.Sockets.Thin_Common; use GNAT.Sockets.Thin_Common;
38 with GNAT.Sockets.Thin; use GNAT.Sockets.Thin; 39 with GNAT.Sockets.Thin; use GNAT.Sockets.Thin;
47 with System.Task_Lock; 48 with System.Task_Lock;
48 49
49 package body GNAT.Sockets is 50 package body GNAT.Sockets is
50 51
51 package C renames Interfaces.C; 52 package C renames Interfaces.C;
53
54 type IPV6_Mreq is record
55 ipv6mr_multiaddr : In6_Addr;
56 ipv6mr_interface : C.unsigned;
57 end record with Convention => C;
58 -- Record to Add/Drop_Membership for multicast in IPv6
52 59
53 ENOERROR : constant := 0; 60 ENOERROR : constant := 0;
54 61
55 Netdb_Buffer_Size : constant := SOSC.Need_Netdb_Buffer * 1024; 62 Netdb_Buffer_Size : constant := SOSC.Need_Netdb_Buffer * 1024;
56 Need_Netdb_Lock : constant Boolean := SOSC.Need_Netdb_Lock /= 0; 63 Need_Netdb_Lock : constant Boolean := SOSC.Need_Netdb_Lock /= 0;
60 -- to ensure concurrent uses do not interfere. 67 -- to ensure concurrent uses do not interfere.
61 68
62 -- Correspondence tables 69 -- Correspondence tables
63 70
64 Levels : constant array (Level_Type) of C.int := 71 Levels : constant array (Level_Type) of C.int :=
65 (Socket_Level => SOSC.SOL_SOCKET, 72 (Socket_Level => SOSC.SOL_SOCKET,
66 IP_Protocol_For_IP_Level => SOSC.IPPROTO_IP, 73 IP_Protocol_For_IP_Level => SOSC.IPPROTO_IP,
67 IP_Protocol_For_UDP_Level => SOSC.IPPROTO_UDP, 74 IP_Protocol_For_IPv6_Level => SOSC.IPPROTO_IPV6,
68 IP_Protocol_For_TCP_Level => SOSC.IPPROTO_TCP); 75 IP_Protocol_For_UDP_Level => SOSC.IPPROTO_UDP,
76 IP_Protocol_For_TCP_Level => SOSC.IPPROTO_TCP,
77 IP_Protocol_For_ICMP_Level => SOSC.IPPROTO_ICMP,
78 IP_Protocol_For_IGMP_Level => SOSC.IPPROTO_IGMP,
79 IP_Protocol_For_RAW_Level => SOSC.IPPROTO_RAW);
69 80
70 Modes : constant array (Mode_Type) of C.int := 81 Modes : constant array (Mode_Type) of C.int :=
71 (Socket_Stream => SOSC.SOCK_STREAM, 82 (Socket_Stream => SOSC.SOCK_STREAM,
72 Socket_Datagram => SOSC.SOCK_DGRAM); 83 Socket_Datagram => SOSC.SOCK_DGRAM,
84 Socket_Raw => SOSC.SOCK_RAW);
73 85
74 Shutmodes : constant array (Shutmode_Type) of C.int := 86 Shutmodes : constant array (Shutmode_Type) of C.int :=
75 (Shut_Read => SOSC.SHUT_RD, 87 (Shut_Read => SOSC.SHUT_RD,
76 Shut_Write => SOSC.SHUT_WR, 88 Shut_Write => SOSC.SHUT_WR,
77 Shut_Read_Write => SOSC.SHUT_RDWR); 89 Shut_Read_Write => SOSC.SHUT_RDWR);
87 Send_Buffer => SOSC.SO_SNDBUF, 99 Send_Buffer => SOSC.SO_SNDBUF,
88 Receive_Buffer => SOSC.SO_RCVBUF, 100 Receive_Buffer => SOSC.SO_RCVBUF,
89 Linger => SOSC.SO_LINGER, 101 Linger => SOSC.SO_LINGER,
90 Error => SOSC.SO_ERROR, 102 Error => SOSC.SO_ERROR,
91 No_Delay => SOSC.TCP_NODELAY, 103 No_Delay => SOSC.TCP_NODELAY,
92 Add_Membership => SOSC.IP_ADD_MEMBERSHIP, 104 Add_Membership_V4 => SOSC.IP_ADD_MEMBERSHIP,
93 Drop_Membership => SOSC.IP_DROP_MEMBERSHIP, 105 Drop_Membership_V4 => SOSC.IP_DROP_MEMBERSHIP,
94 Multicast_If => SOSC.IP_MULTICAST_IF, 106 Multicast_If_V4 => SOSC.IP_MULTICAST_IF,
107 Multicast_Loop_V4 => SOSC.IP_MULTICAST_LOOP,
108 Receive_Packet_Info => SOSC.IP_PKTINFO,
95 Multicast_TTL => SOSC.IP_MULTICAST_TTL, 109 Multicast_TTL => SOSC.IP_MULTICAST_TTL,
96 Multicast_Loop => SOSC.IP_MULTICAST_LOOP, 110 Add_Membership_V6 => SOSC.IPV6_ADD_MEMBERSHIP,
97 Receive_Packet_Info => SOSC.IP_PKTINFO, 111 Drop_Membership_V6 => SOSC.IPV6_DROP_MEMBERSHIP,
112 Multicast_If_V6 => SOSC.IPV6_MULTICAST_IF,
113 Multicast_Loop_V6 => SOSC.IPV6_MULTICAST_LOOP,
114 Multicast_Hops => SOSC.IPV6_MULTICAST_HOPS,
115 IPv6_Only => SOSC.IPV6_V6ONLY,
98 Send_Timeout => SOSC.SO_SNDTIMEO, 116 Send_Timeout => SOSC.SO_SNDTIMEO,
99 Receive_Timeout => SOSC.SO_RCVTIMEO, 117 Receive_Timeout => SOSC.SO_RCVTIMEO,
100 Busy_Polling => SOSC.SO_BUSY_POLL); 118 Busy_Polling => SOSC.SO_BUSY_POLL);
101 -- ??? Note: for OpenSolaris, Receive_Packet_Info should be IP_RECVPKTINFO, 119 -- ??? Note: for OpenSolaris, Receive_Packet_Info should be IP_RECVPKTINFO,
102 -- but for Linux compatibility this constant is the same as IP_PKTINFO. 120 -- but for Linux compatibility this constant is the same as IP_PKTINFO.
108 3 => SOSC.MSG_EOR); -- Send_End_Of_Record 126 3 => SOSC.MSG_EOR); -- Send_End_Of_Record
109 127
110 Socket_Error_Id : constant Exception_Id := Socket_Error'Identity; 128 Socket_Error_Id : constant Exception_Id := Socket_Error'Identity;
111 Host_Error_Id : constant Exception_Id := Host_Error'Identity; 129 Host_Error_Id : constant Exception_Id := Host_Error'Identity;
112 130
113 Hex_To_Char : constant String (1 .. 16) := "0123456789ABCDEF"; 131 type In_Addr_Union (Family : Family_Inet_4_6) is record
114 -- Use to print in hexadecimal format 132 case Family is
133 when Family_Inet =>
134 In4 : In_Addr;
135 when Family_Inet6 =>
136 In6 : In6_Addr;
137 end case;
138 end record with Unchecked_Union;
115 139
116 ----------------------- 140 -----------------------
117 -- Local subprograms -- 141 -- Local subprograms --
118 ----------------------- 142 -----------------------
119 143
130 function To_Int (F : Request_Flag_Type) return C.int; 154 function To_Int (F : Request_Flag_Type) return C.int;
131 -- Return the int value corresponding to the specified flags combination 155 -- Return the int value corresponding to the specified flags combination
132 156
133 function Set_Forced_Flags (F : C.int) return C.int; 157 function Set_Forced_Flags (F : C.int) return C.int;
134 -- Return F with the bits from SOSC.MSG_Forced_Flags forced set 158 -- Return F with the bits from SOSC.MSG_Forced_Flags forced set
135
136 function Short_To_Network
137 (S : C.unsigned_short) return C.unsigned_short;
138 pragma Inline (Short_To_Network);
139 -- Convert a port number into a network port number
140
141 function Network_To_Short
142 (S : C.unsigned_short) return C.unsigned_short
143 renames Short_To_Network;
144 -- Symmetric operation
145
146 function Image
147 (Val : Inet_Addr_Bytes;
148 Hex : Boolean := False) return String;
149 -- Output an array of inet address components in hex or decimal mode
150
151 function Is_IP_Address (Name : String) return Boolean;
152 -- Return true when Name is an IPv4 address in dotted quad notation
153 159
154 procedure Netdb_Lock; 160 procedure Netdb_Lock;
155 pragma Inline (Netdb_Lock); 161 pragma Inline (Netdb_Lock);
156 procedure Netdb_Unlock; 162 procedure Netdb_Unlock;
157 pragma Inline (Netdb_Unlock); 163 pragma Inline (Netdb_Unlock);
158 -- Lock/unlock operation used to protect netdb access for platforms that 164 -- Lock/unlock operation used to protect netdb access for platforms that
159 -- require such protection. 165 -- require such protection.
160 166
161 function To_In_Addr (Addr : Inet_Addr_Type) return In_Addr;
162 procedure To_Inet_Addr
163 (Addr : In_Addr;
164 Result : out Inet_Addr_Type);
165 -- Conversion functions
166
167 function To_Host_Entry (E : Hostent_Access) return Host_Entry_Type; 167 function To_Host_Entry (E : Hostent_Access) return Host_Entry_Type;
168 -- Conversion function 168 -- Conversion function
169 169
170 function To_Service_Entry (E : Servent_Access) return Service_Entry_Type; 170 function To_Service_Entry (E : Servent_Access) return Service_Entry_Type;
171 -- Conversion function 171 -- Conversion function
177 -- Separate Val in seconds and microseconds 177 -- Separate Val in seconds and microseconds
178 178
179 function To_Duration (Val : Timeval) return Timeval_Duration; 179 function To_Duration (Val : Timeval) return Timeval_Duration;
180 -- Reconstruct a Duration value from a Timeval record (seconds and 180 -- Reconstruct a Duration value from a Timeval record (seconds and
181 -- microseconds). 181 -- microseconds).
182
183 function Dedot (Value : String) return String
184 is (if Value /= "" and then Value (Value'Last) = '.'
185 then Value (Value'First .. Value'Last - 1)
186 else Value);
187 -- Removes dot at the end of error message
182 188
183 procedure Raise_Socket_Error (Error : Integer); 189 procedure Raise_Socket_Error (Error : Integer);
184 -- Raise Socket_Error with an exception message describing the error code 190 -- Raise Socket_Error with an exception message describing the error code
185 -- from errno. 191 -- from errno.
186 192
187 procedure Raise_Host_Error (H_Error : Integer; Name : String); 193 procedure Raise_Host_Error (H_Error : Integer; Name : String);
188 -- Raise Host_Error exception with message describing error code (note 194 -- Raise Host_Error exception with message describing error code (note
189 -- hstrerror seems to be obsolete) from h_errno. Name is the name 195 -- hstrerror seems to be obsolete) from h_errno. Name is the name
190 -- or address that was being looked up. 196 -- or address that was being looked up.
197
198 procedure Raise_GAI_Error (RC : C.int; Name : String);
199 -- Raise Host_Error with exception message in case of errors in
200 -- getaddrinfo and getnameinfo.
201
202 function Is_Windows return Boolean with Inline;
203 -- Returns True on Windows platform
191 204
192 procedure Narrow (Item : in out Socket_Set_Type); 205 procedure Narrow (Item : in out Socket_Set_Type);
193 -- Update Last as it may be greater than the real last socket 206 -- Update Last as it may be greater than the real last socket
194 207
195 procedure Check_For_Fd_Set (Fd : Socket_Type); 208 procedure Check_For_Fd_Set (Fd : Socket_Type);
274 -- Return True for an "open" Selector_Type object, i.e. one for which 287 -- Return True for an "open" Selector_Type object, i.e. one for which
275 -- Create_Selector has been called and Close_Selector has not been called, 288 -- Create_Selector has been called and Close_Selector has not been called,
276 -- or the null selector. 289 -- or the null selector.
277 290
278 function Create_Address 291 function Create_Address
279 (Family : Family_Type; Bytes : Inet_Addr_Bytes) return Inet_Addr_Type 292 (Family : Family_Inet_4_6; Bytes : Inet_Addr_Bytes) return Inet_Addr_Type
280 with Inline; 293 with Inline;
281 -- Creates address from family and Inet_Addr_Bytes array. 294 -- Creates address from family and Inet_Addr_Bytes array.
282 295
283 function Get_Bytes (Addr : Inet_Addr_Type) return Inet_Addr_Bytes 296 function Get_Bytes (Addr : Inet_Addr_Type) return Inet_Addr_Bytes
284 with Inline; 297 with Inline;
326 (Server : Socket_Type; 339 (Server : Socket_Type;
327 Socket : out Socket_Type; 340 Socket : out Socket_Type;
328 Address : out Sock_Addr_Type) 341 Address : out Sock_Addr_Type)
329 is 342 is
330 Res : C.int; 343 Res : C.int;
331 Sin : aliased Sockaddr_In; 344 Sin : aliased Sockaddr;
332 Len : aliased C.int := Sin'Size / 8; 345 Len : aliased C.int := Sin'Size / 8;
333 346
334 begin 347 begin
335 Res := C_Accept (C.int (Server), Sin'Address, Len'Access); 348 Res := C_Accept (C.int (Server), Sin'Address, Len'Access);
336 349
337 if Res = Failure then 350 if Res = Failure then
338 Raise_Socket_Error (Socket_Errno); 351 Raise_Socket_Error (Socket_Errno);
339 end if; 352 end if;
340 353
341 Socket := Socket_Type (Res); 354 Socket := Socket_Type (Res);
342 355 Address := Get_Address (Sin, Len);
343 To_Inet_Addr (Sin.Sin_Addr, Address.Addr);
344 Address.Port := Port_Type (Network_To_Short (Sin.Sin_Port));
345 end Accept_Socket; 356 end Accept_Socket;
346 357
347 ------------------- 358 -------------------
348 -- Accept_Socket -- 359 -- Accept_Socket --
349 ------------------- 360 -------------------
449 procedure Bind_Socket 460 procedure Bind_Socket
450 (Socket : Socket_Type; 461 (Socket : Socket_Type;
451 Address : Sock_Addr_Type) 462 Address : Sock_Addr_Type)
452 is 463 is
453 Res : C.int; 464 Res : C.int;
454 Sin : aliased Sockaddr_In; 465 Sin : aliased Sockaddr;
455 Len : constant C.int := Sin'Size / 8; 466 Len : C.int;
456 -- This assumes that Address.Family = Family_Inet??? 467
457 468 begin
458 begin 469 Set_Address (Sin'Unchecked_Access, Address, Len);
459 if Address.Family = Family_Inet6 then
460 raise Socket_Error with "IPv6 not supported";
461 end if;
462
463 Set_Family (Sin.Sin_Family, Address.Family);
464 Set_Address (Sin'Unchecked_Access, To_In_Addr (Address.Addr));
465 Set_Port
466 (Sin'Unchecked_Access,
467 Short_To_Network (C.unsigned_short (Address.Port)));
468 470
469 Res := C_Bind (C.int (Socket), Sin'Address, Len); 471 Res := C_Bind (C.int (Socket), Sin'Address, Len);
470 472
471 if Res = Failure then 473 if Res = Failure then
472 Raise_Socket_Error (Socket_Errno); 474 Raise_Socket_Error (Socket_Errno);
476 ---------------------- 478 ----------------------
477 -- Check_For_Fd_Set -- 479 -- Check_For_Fd_Set --
478 ---------------------- 480 ----------------------
479 481
480 procedure Check_For_Fd_Set (Fd : Socket_Type) is 482 procedure Check_For_Fd_Set (Fd : Socket_Type) is
481 use SOSC;
482
483 begin 483 begin
484 -- On Windows, fd_set is a FD_SETSIZE array of socket ids: 484 -- On Windows, fd_set is a FD_SETSIZE array of socket ids:
485 -- no check required. Warnings suppressed because condition 485 -- no check required. Warnings suppressed because condition
486 -- is known at compile time. 486 -- is known at compile time.
487 487
488 if Target_OS = Windows then 488 if Is_Windows then
489 489
490 return; 490 return;
491 491
492 -- On other platforms, fd_set is an FD_SETSIZE bitmap: check 492 -- On other platforms, fd_set is an FD_SETSIZE bitmap: check
493 -- that Fd is within range (otherwise behavior is undefined). 493 -- that Fd is within range (otherwise behavior is undefined).
665 665
666 function Connect_Socket 666 function Connect_Socket
667 (Socket : Socket_Type; 667 (Socket : Socket_Type;
668 Server : Sock_Addr_Type) return C.int 668 Server : Sock_Addr_Type) return C.int
669 is 669 is
670 Sin : aliased Sockaddr_In; 670 Sin : aliased Sockaddr;
671 Len : constant C.int := Sin'Size / 8; 671 Len : C.int;
672 672 begin
673 begin 673 Set_Address (Sin'Unchecked_Access, Server, Len);
674 if Server.Family = Family_Inet6 then
675 raise Socket_Error with "IPv6 not supported";
676 end if;
677
678 Set_Family (Sin.Sin_Family, Server.Family);
679 Set_Address (Sin'Unchecked_Access, To_In_Addr (Server.Addr));
680 Set_Port
681 (Sin'Unchecked_Access,
682 Short_To_Network (C.unsigned_short (Server.Port)));
683 674
684 return C_Connect (C.int (Socket), Sin'Address, Len); 675 return C_Connect (C.int (Socket), Sin'Address, Len);
685 end Connect_Socket; 676 end Connect_Socket;
686 677
687 procedure Connect_Socket 678 procedure Connect_Socket
859 ------------------- 850 -------------------
860 851
861 procedure Create_Socket 852 procedure Create_Socket
862 (Socket : out Socket_Type; 853 (Socket : out Socket_Type;
863 Family : Family_Type := Family_Inet; 854 Family : Family_Type := Family_Inet;
864 Mode : Mode_Type := Socket_Stream) 855 Mode : Mode_Type := Socket_Stream;
856 Level : Level_Type := IP_Protocol_For_IP_Level)
865 is 857 is
866 Res : C.int; 858 Res : C.int;
867 859
868 begin 860 begin
869 Res := C_Socket (Families (Family), Modes (Mode), 0); 861 Res := C_Socket (Families (Family), Modes (Mode), Levels (Level));
870 862
871 if Res = Failure then 863 if Res = Failure then
872 Raise_Socket_Error (Socket_Errno); 864 Raise_Socket_Error (Socket_Errno);
873 end if; 865 end if;
874 866
875 Socket := Socket_Type (Res); 867 Socket := Socket_Type (Res);
876 end Create_Socket; 868 end Create_Socket;
869
870 ------------------------
871 -- Create_Socket_Pair --
872 ------------------------
873
874 procedure Create_Socket_Pair
875 (Left : out Socket_Type;
876 Right : out Socket_Type;
877 Family : Family_Type := Family_Unspec;
878 Mode : Mode_Type := Socket_Stream;
879 Level : Level_Type := IP_Protocol_For_IP_Level)
880 is
881 Res : C.int;
882 Pair : aliased Thin_Common.Fd_Pair;
883
884 begin
885 Res := C_Socketpair
886 ((if Family = Family_Unspec then Default_Socket_Pair_Family
887 else Families (Family)),
888 Modes (Mode), Levels (Level), Pair'Access);
889
890 if Res = Failure then
891 Raise_Socket_Error (Socket_Errno);
892 end if;
893
894 Left := Socket_Type (Pair (Pair'First));
895 Right := Socket_Type (Pair (Pair'Last));
896 end Create_Socket_Pair;
877 897
878 ----------- 898 -----------
879 -- Empty -- 899 -- Empty --
880 ----------- 900 -----------
881 901
957 else 977 else
958 return Get_Peer_Name (Stream_Socket_Stream_Type (Stream.all).Socket); 978 return Get_Peer_Name (Stream_Socket_Stream_Type (Stream.all).Socket);
959 end if; 979 end if;
960 end Get_Address; 980 end Get_Address;
961 981
982 ---------------------
983 -- Raise_GAI_Error --
984 ---------------------
985
986 procedure Raise_GAI_Error (RC : C.int; Name : String) is
987 begin
988 if RC = SOSC.EAI_SYSTEM then
989 declare
990 Errcode : constant Integer := Socket_Errno;
991 begin
992 raise Host_Error with Err_Code_Image (Errcode)
993 & Dedot (Socket_Error_Message (Errcode)) & ": " & Name;
994 end;
995 else
996 raise Host_Error with Err_Code_Image (Integer (RC))
997 & Dedot (CS.Value (C_GAI_Strerror (RC))) & ": " & Name;
998 end if;
999 end Raise_GAI_Error;
1000
1001 ----------------------
1002 -- Get_Address_Info --
1003 ----------------------
1004
1005 function Get_Address_Info
1006 (Host : String;
1007 Service : String;
1008 Family : Family_Type := Family_Unspec;
1009 Mode : Mode_Type := Socket_Stream;
1010 Level : Level_Type := IP_Protocol_For_IP_Level;
1011 Numeric_Host : Boolean := False;
1012 Passive : Boolean := False;
1013 Unknown : access procedure
1014 (Family, Mode, Level, Length : Integer) := null)
1015 return Address_Info_Array
1016 is
1017 A : aliased Addrinfo_Access;
1018 N : aliased C.char_array := C.To_C (Host);
1019 S : aliased C.char_array := C.To_C (if Service = "" then "0"
1020 else Service);
1021 Hints : aliased constant Addrinfo :=
1022 (ai_family => Families (Family),
1023 ai_socktype => Modes (Mode),
1024 ai_protocol => Levels (Level),
1025 ai_flags => (if Numeric_Host then SOSC.AI_NUMERICHOST else 0) +
1026 (if Passive then SOSC.AI_PASSIVE else 0),
1027 ai_addrlen => 0,
1028 others => <>);
1029
1030 R : C.int;
1031 Iter : Addrinfo_Access;
1032 Found : Boolean;
1033
1034 function To_Array return Address_Info_Array;
1035 -- Convert taken from OS addrinfo list A into Address_Info_Array
1036
1037 --------------
1038 -- To_Array --
1039 --------------
1040
1041 function To_Array return Address_Info_Array is
1042 Result : Address_Info_Array (1 .. 8);
1043
1044 procedure Unsupported;
1045 -- Calls Unknown callback if defiend
1046
1047 -----------------
1048 -- Unsupported --
1049 -----------------
1050
1051 procedure Unsupported is
1052 begin
1053 if Unknown /= null then
1054 Unknown
1055 (Integer (Iter.ai_family),
1056 Integer (Iter.ai_socktype),
1057 Integer (Iter.ai_protocol),
1058 Integer (Iter.ai_addrlen));
1059 end if;
1060 end Unsupported;
1061
1062 -- Start of processing for To_Array
1063
1064 begin
1065 for J in Result'Range loop
1066 Look_For_Supported : loop
1067 if Iter = null then
1068 pragma Warnings
1069 (Off, "may be referenced before it has a value");
1070
1071 return Result (1 .. J - 1);
1072
1073 pragma Warnings
1074 (On, "may be referenced before it has a value");
1075 end if;
1076
1077 Result (J).Addr :=
1078 Get_Address (Iter.ai_addr.all, C.int (Iter.ai_addrlen));
1079
1080 if Result (J).Addr.Family = Family_Unspec then
1081 Unsupported;
1082 else
1083 for M in Modes'Range loop
1084 Found := False;
1085 if Modes (M) = Iter.ai_socktype then
1086 Result (J).Mode := M;
1087 Found := True;
1088 exit;
1089 end if;
1090 end loop;
1091
1092 if Found then
1093 for L in Levels'Range loop
1094 if Levels (L) = Iter.ai_protocol then
1095 Result (J).Level := L;
1096 exit;
1097 end if;
1098 end loop;
1099
1100 exit Look_For_Supported;
1101 else
1102 Unsupported;
1103 end if;
1104 end if;
1105
1106 Iter := Iter.ai_next;
1107 end loop Look_For_Supported;
1108
1109 Iter := Iter.ai_next;
1110 end loop;
1111
1112 return Result & To_Array;
1113 end To_Array;
1114
1115 -- Start of processing for Get_Address_Info
1116
1117 begin
1118 R := C_Getaddrinfo
1119 (Node => (if Host = "" then null else N'Unchecked_Access),
1120 Service => S'Unchecked_Access,
1121 Hints => Hints'Unchecked_Access,
1122 Res => A'Access);
1123
1124 if R /= 0 then
1125 Raise_GAI_Error
1126 (R, Host & (if Service = "" then "" else ':' & Service));
1127 end if;
1128
1129 Iter := A;
1130
1131 return Result : constant Address_Info_Array := To_Array do
1132 C_Freeaddrinfo (A);
1133 end return;
1134 end Get_Address_Info;
1135
1136 ----------
1137 -- Sort --
1138 ----------
1139
1140 procedure Sort
1141 (Addr_Info : in out Address_Info_Array;
1142 Compare : access function (Left, Right : Address_Info) return Boolean)
1143 is
1144 function Comp (Left, Right : Address_Info) return Boolean is
1145 (Compare (Left, Right));
1146 procedure Sorter is new Ada.Containers.Generic_Array_Sort
1147 (Positive, Address_Info, Address_Info_Array, Comp);
1148 begin
1149 Sorter (Addr_Info);
1150 end Sort;
1151
1152 ------------------------
1153 -- IPv6_TCP_Preferred --
1154 ------------------------
1155
1156 function IPv6_TCP_Preferred (Left, Right : Address_Info) return Boolean is
1157 begin
1158 pragma Assert (Family_Inet < Family_Inet6);
1159 -- To be sure that Family_Type enumeration has appropriate elements
1160 -- order
1161
1162 if Left.Addr.Family /= Right.Addr.Family then
1163 return Left.Addr.Family > Right.Addr.Family;
1164 end if;
1165
1166 pragma Assert (Socket_Stream < Socket_Datagram);
1167 -- To be sure that Mode_Type enumeration has appropriate elements order
1168
1169 return Left.Mode < Right.Mode;
1170 end IPv6_TCP_Preferred;
1171
1172 -------------------
1173 -- Get_Name_Info --
1174 -------------------
1175
1176 function Get_Name_Info
1177 (Addr : Sock_Addr_Type;
1178 Numeric_Host : Boolean := False;
1179 Numeric_Serv : Boolean := False) return Host_Service
1180 is
1181 SA : aliased Sockaddr;
1182 H : aliased C.char_array := (1 .. SOSC.NI_MAXHOST => C.nul);
1183 S : aliased C.char_array := (1 .. SOSC.NI_MAXSERV => C.nul);
1184 RC : C.int;
1185 Len : C.int;
1186 begin
1187 Set_Address (SA'Unchecked_Access, Addr, Len);
1188
1189 RC := C_Getnameinfo
1190 (SA'Unchecked_Access, socklen_t (Len),
1191 H'Unchecked_Access, H'Length,
1192 S'Unchecked_Access, S'Length,
1193 (if Numeric_Host then SOSC.NI_NUMERICHOST else 0) +
1194 (if Numeric_Serv then SOSC.NI_NUMERICSERV else 0));
1195
1196 if RC /= 0 then
1197 Raise_GAI_Error (RC, Image (Addr));
1198 end if;
1199
1200 declare
1201 HR : constant String := C.To_Ada (H);
1202 SR : constant String := C.To_Ada (S);
1203 begin
1204 return (HR'Length, SR'Length, HR, SR);
1205 end;
1206 end Get_Name_Info;
1207
962 ------------------------- 1208 -------------------------
963 -- Get_Host_By_Address -- 1209 -- Get_Host_By_Address --
964 ------------------------- 1210 -------------------------
965 1211
966 function Get_Host_By_Address 1212 function Get_Host_By_Address
967 (Address : Inet_Addr_Type; 1213 (Address : Inet_Addr_Type;
968 Family : Family_Type := Family_Inet) return Host_Entry_Type 1214 Family : Family_Type := Family_Inet) return Host_Entry_Type
969 is 1215 is
970 pragma Unreferenced (Family); 1216 pragma Unreferenced (Family);
971 1217
972 HA : aliased In_Addr := To_In_Addr (Address); 1218 HA : aliased In_Addr_Union (Address.Family);
973 Buflen : constant C.int := Netdb_Buffer_Size; 1219 Buflen : constant C.int := Netdb_Buffer_Size;
974 Buf : aliased C.char_array (1 .. Netdb_Buffer_Size); 1220 Buf : aliased C.char_array (1 .. Netdb_Buffer_Size);
975 Res : aliased Hostent; 1221 Res : aliased Hostent;
976 Err : aliased C.int; 1222 Err : aliased C.int;
977 1223
978 begin 1224 begin
1225 case Address.Family is
1226 when Family_Inet =>
1227 HA.In4 := To_In_Addr (Address);
1228 when Family_Inet6 =>
1229 HA.In6 := To_In6_Addr (Address);
1230 end case;
1231
979 Netdb_Lock; 1232 Netdb_Lock;
980 1233
981 if C_Gethostbyaddr (HA'Address, HA'Size / 8, SOSC.AF_INET, 1234 if C_Gethostbyaddr
982 Res'Access, Buf'Address, Buflen, Err'Access) /= 0 1235 (HA'Address,
1236 (case Address.Family is
1237 when Family_Inet => HA.In4'Size,
1238 when Family_Inet6 => HA.In6'Size) / 8,
1239 Families (Address.Family),
1240 Res'Access, Buf'Address, Buflen, Err'Access) /= 0
983 then 1241 then
984 Netdb_Unlock; 1242 Netdb_Unlock;
985 Raise_Host_Error (Integer (Err), Image (Address)); 1243 Raise_Host_Error (Integer (Err), Image (Address));
986 end if; 1244 end if;
987 1245
1005 function Get_Host_By_Name (Name : String) return Host_Entry_Type is 1263 function Get_Host_By_Name (Name : String) return Host_Entry_Type is
1006 begin 1264 begin
1007 -- If the given name actually is the string representation of 1265 -- If the given name actually is the string representation of
1008 -- an IP address, use Get_Host_By_Address instead. 1266 -- an IP address, use Get_Host_By_Address instead.
1009 1267
1010 if Is_IP_Address (Name) then 1268 if Is_IPv4_Address (Name) or else Is_IPv6_Address (Name) then
1011 return Get_Host_By_Address (Inet_Addr (Name)); 1269 return Get_Host_By_Address (Inet_Addr (Name));
1012 end if; 1270 end if;
1013 1271
1014 declare 1272 declare
1015 HN : constant C.char_array := C.To_C (Name); 1273 HN : constant C.char_array := C.To_C (Name);
1039 ------------------- 1297 -------------------
1040 -- Get_Peer_Name -- 1298 -- Get_Peer_Name --
1041 ------------------- 1299 -------------------
1042 1300
1043 function Get_Peer_Name (Socket : Socket_Type) return Sock_Addr_Type is 1301 function Get_Peer_Name (Socket : Socket_Type) return Sock_Addr_Type is
1044 Sin : aliased Sockaddr_In; 1302 Sin : aliased Sockaddr;
1045 Len : aliased C.int := Sin'Size / 8; 1303 Len : aliased C.int := Sin'Size / 8;
1046 Res : Sock_Addr_Type (Family_Inet);
1047
1048 begin 1304 begin
1049 if C_Getpeername (C.int (Socket), Sin'Address, Len'Access) = Failure then 1305 if C_Getpeername (C.int (Socket), Sin'Address, Len'Access) = Failure then
1050 Raise_Socket_Error (Socket_Errno); 1306 Raise_Socket_Error (Socket_Errno);
1051 end if; 1307 end if;
1052 1308
1053 To_Inet_Addr (Sin.Sin_Addr, Res.Addr); 1309 return Get_Address (Sin, Len);
1054 Res.Port := Port_Type (Network_To_Short (Sin.Sin_Port));
1055
1056 return Res;
1057 end Get_Peer_Name; 1310 end Get_Peer_Name;
1058 1311
1059 ------------------------- 1312 -------------------------
1060 -- Get_Service_By_Name -- 1313 -- Get_Service_By_Name --
1061 ------------------------- 1314 -------------------------
1125 --------------------- 1378 ---------------------
1126 1379
1127 function Get_Socket_Name 1380 function Get_Socket_Name
1128 (Socket : Socket_Type) return Sock_Addr_Type 1381 (Socket : Socket_Type) return Sock_Addr_Type
1129 is 1382 is
1130 Sin : aliased Sockaddr_In; 1383 Sin : aliased Sockaddr;
1131 Len : aliased C.int := Sin'Size / 8; 1384 Len : aliased C.int := Sin'Size / 8;
1132 Res : C.int; 1385 Res : C.int;
1133 Addr : Sock_Addr_Type := No_Sock_Addr;
1134
1135 begin 1386 begin
1136 Res := C_Getsockname (C.int (Socket), Sin'Address, Len'Access); 1387 Res := C_Getsockname (C.int (Socket), Sin'Address, Len'Access);
1137 1388
1138 if Res /= Failure then 1389 if Res = Failure then
1139 To_Inet_Addr (Sin.Sin_Addr, Addr.Addr); 1390 return No_Sock_Addr;
1140 Addr.Port := Port_Type (Network_To_Short (Sin.Sin_Port)); 1391 end if;
1141 end if; 1392
1142 1393 return Get_Address (Sin, Len);
1143 return Addr;
1144 end Get_Socket_Name; 1394 end Get_Socket_Name;
1145 1395
1146 ----------------------- 1396 -----------------------
1147 -- Get_Socket_Option -- 1397 -- Get_Socket_Option --
1148 ----------------------- 1398 -----------------------
1149 1399
1150 function Get_Socket_Option 1400 function Get_Socket_Option
1151 (Socket : Socket_Type; 1401 (Socket : Socket_Type;
1152 Level : Level_Type := Socket_Level; 1402 Level : Level_Type;
1153 Name : Option_Name; 1403 Name : Option_Name;
1154 Optname : Interfaces.C.int := -1) return Option_Type 1404 Optname : Interfaces.C.int := -1) return Option_Type
1155 is 1405 is
1156 use SOSC; 1406 use type C.unsigned;
1157 use type C.unsigned_char; 1407 use type C.unsigned_char;
1158 1408
1159 V8 : aliased Two_Ints; 1409 V8 : aliased Two_Ints;
1160 V4 : aliased C.int; 1410 V4 : aliased C.int;
1411 U4 : aliased C.unsigned;
1161 V1 : aliased C.unsigned_char; 1412 V1 : aliased C.unsigned_char;
1162 VT : aliased Timeval; 1413 VT : aliased Timeval;
1163 Len : aliased C.int; 1414 Len : aliased C.int;
1164 Add : System.Address; 1415 Add : System.Address;
1165 Res : C.int; 1416 Res : C.int;
1176 else 1427 else
1177 Onm := Optname; 1428 Onm := Optname;
1178 end if; 1429 end if;
1179 1430
1180 case Name is 1431 case Name is
1181 when Multicast_Loop 1432 when Multicast_TTL
1182 | Multicast_TTL
1183 | Receive_Packet_Info 1433 | Receive_Packet_Info
1184 => 1434 =>
1185 Len := V1'Size / 8; 1435 Len := V1'Size / 8;
1186 Add := V1'Address; 1436 Add := V1'Address;
1187 1437
1188 when Broadcast 1438 when Broadcast
1189 | Busy_Polling 1439 | Busy_Polling
1190 | Error 1440 | Error
1191 | Generic_Option 1441 | Generic_Option
1192 | Keep_Alive 1442 | Keep_Alive
1193 | Multicast_If 1443 | Multicast_If_V4
1444 | Multicast_If_V6
1445 | Multicast_Loop_V4
1446 | Multicast_Loop_V6
1447 | Multicast_Hops
1194 | No_Delay 1448 | No_Delay
1195 | Receive_Buffer 1449 | Receive_Buffer
1196 | Reuse_Address 1450 | Reuse_Address
1197 | Send_Buffer 1451 | Send_Buffer
1452 | IPv6_Only
1198 => 1453 =>
1199 Len := V4'Size / 8; 1454 Len := V4'Size / 8;
1200 Add := V4'Address; 1455 Add := V4'Address;
1201 1456
1202 when Receive_Timeout 1457 when Receive_Timeout
1204 => 1459 =>
1205 -- The standard argument for SO_RCVTIMEO and SO_SNDTIMEO is a 1460 -- The standard argument for SO_RCVTIMEO and SO_SNDTIMEO is a
1206 -- struct timeval, but on Windows it is a milliseconds count in 1461 -- struct timeval, but on Windows it is a milliseconds count in
1207 -- a DWORD. 1462 -- a DWORD.
1208 1463
1209 if Target_OS = Windows then 1464 if Is_Windows then
1210 Len := V4'Size / 8; 1465 Len := U4'Size / 8;
1211 Add := V4'Address; 1466 Add := U4'Address;
1212
1213 else 1467 else
1214 Len := VT'Size / 8; 1468 Len := VT'Size / 8;
1215 Add := VT'Address; 1469 Add := VT'Address;
1216 end if; 1470 end if;
1217 1471
1218 when Add_Membership 1472 when Add_Membership_V4
1219 | Drop_Membership 1473 | Add_Membership_V6
1220 | Linger 1474 | Drop_Membership_V4
1475 | Drop_Membership_V6
1476 =>
1477 raise Socket_Error with
1478 "Add/Drop membership valid only for Set_Socket_Option";
1479
1480 when Linger
1221 => 1481 =>
1222 Len := V8'Size / 8; 1482 Len := V8'Size / 8;
1223 Add := V8'Address; 1483 Add := V8'Address;
1224 end case; 1484 end case;
1225 1485
1241 1501
1242 when Broadcast 1502 when Broadcast
1243 | Keep_Alive 1503 | Keep_Alive
1244 | No_Delay 1504 | No_Delay
1245 | Reuse_Address 1505 | Reuse_Address
1506 | Multicast_Loop_V4
1507 | Multicast_Loop_V6
1508 | IPv6_Only
1246 => 1509 =>
1247 Opt.Enabled := (V4 /= 0); 1510 Opt.Enabled := (V4 /= 0);
1248 1511
1249 when Busy_Polling => 1512 when Busy_Polling =>
1250 Opt.Microseconds := Natural (V4); 1513 Opt.Microseconds := Natural (V4);
1259 Opt.Size := Natural (V4); 1522 Opt.Size := Natural (V4);
1260 1523
1261 when Error => 1524 when Error =>
1262 Opt.Error := Resolve_Error (Integer (V4)); 1525 Opt.Error := Resolve_Error (Integer (V4));
1263 1526
1264 when Add_Membership 1527 when Add_Membership_V4
1265 | Drop_Membership 1528 | Add_Membership_V6
1529 | Drop_Membership_V4
1530 | Drop_Membership_V6
1266 => 1531 =>
1267 To_Inet_Addr (To_In_Addr (V8 (V8'First)), Opt.Multicast_Address); 1532 -- No way to be here. Exception raised in the first case Name
1268 To_Inet_Addr (To_In_Addr (V8 (V8'Last)), Opt.Local_Interface); 1533 -- expression.
1269 1534 null;
1270 when Multicast_If => 1535
1536 when Multicast_If_V4 =>
1271 To_Inet_Addr (To_In_Addr (V4), Opt.Outgoing_If); 1537 To_Inet_Addr (To_In_Addr (V4), Opt.Outgoing_If);
1538
1539 when Multicast_If_V6 =>
1540 Opt.Outgoing_If_Index := Natural (V4);
1272 1541
1273 when Multicast_TTL => 1542 when Multicast_TTL =>
1274 Opt.Time_To_Live := Integer (V1); 1543 Opt.Time_To_Live := Integer (V1);
1275 1544
1276 when Multicast_Loop 1545 when Multicast_Hops =>
1277 | Receive_Packet_Info 1546 Opt.Hop_Limit := Integer (V4);
1547
1548 when Receive_Packet_Info
1278 => 1549 =>
1279 Opt.Enabled := (V1 /= 0); 1550 Opt.Enabled := (V1 /= 0);
1280 1551
1281 when Receive_Timeout 1552 when Receive_Timeout
1282 | Send_Timeout 1553 | Send_Timeout
1283 => 1554 =>
1284 if Target_OS = Windows then 1555 if Is_Windows then
1285 1556
1286 -- Timeout is in milliseconds, actual value is 500 ms + 1557 -- Timeout is in milliseconds, actual value is 500 ms +
1287 -- returned value (unless it is 0). 1558 -- returned value (unless it is 0).
1288 1559
1289 if V4 = 0 then 1560 if U4 = 0 then
1290 Opt.Timeout := 0.0; 1561 Opt.Timeout := 0.0;
1291 else 1562 else
1292 Opt.Timeout := Natural (V4) * 0.001 + 0.500; 1563 Opt.Timeout := Duration (U4) / 1000 + 0.500;
1293 end if; 1564 end if;
1294 1565
1295 else 1566 else
1296 Opt.Timeout := To_Duration (VT); 1567 Opt.Timeout := To_Duration (VT);
1297 end if; 1568 end if;
1320 1591
1321 ----------- 1592 -----------
1322 -- Image -- 1593 -- Image --
1323 ----------- 1594 -----------
1324 1595
1325 function Image 1596 function Image (Value : Inet_Addr_Type) return String is
1326 (Val : Inet_Addr_Bytes; 1597 use type CS.char_array_access;
1327 Hex : Boolean := False) return String 1598 Size : constant socklen_t :=
1328 is 1599 (case Value.Family is
1329 -- The largest Inet_Addr_Comp_Type image occurs with IPv4. It 1600 when Family_Inet => 4 * Value.Sin_V4'Length,
1330 -- has at most a length of 3 plus one '.' character. 1601 when Family_Inet6 => 6 * 5 + 4 * 4);
1331 1602 -- 1234:1234:1234:1234:1234:1234:123.123.123.123
1332 Buffer : String (1 .. 4 * Val'Length); 1603 Dst : aliased C.char_array := (1 .. C.size_t (Size) => C.nul);
1333 Length : Natural := 1; 1604 Ia : aliased In_Addr_Union (Value.Family);
1334 Separator : Character; 1605 begin
1335 1606 case Value.Family is
1336 procedure Img10 (V : Inet_Addr_Comp_Type); 1607 when Family_Inet6 =>
1337 -- Append to Buffer image of V in decimal format 1608 Ia.In6 := To_In6_Addr (Value);
1338 1609 when Family_Inet =>
1339 procedure Img16 (V : Inet_Addr_Comp_Type); 1610 Ia.In4 := To_In_Addr (Value);
1340 -- Append to Buffer image of V in hexadecimal format 1611 end case;
1341 1612
1342 ----------- 1613 if Inet_Ntop
1343 -- Img10 -- 1614 (Families (Value.Family), Ia'Address,
1344 ----------- 1615 Dst'Unchecked_Access, Size) = null
1345 1616 then
1346 procedure Img10 (V : Inet_Addr_Comp_Type) is 1617 Raise_Socket_Error (Socket_Errno);
1347 Img : constant String := V'Img; 1618 end if;
1348 Len : constant Natural := Img'Length - 1; 1619
1349 begin 1620 return C.To_Ada (Dst);
1350 Buffer (Length .. Length + Len - 1) := Img (2 .. Img'Last);
1351 Length := Length + Len;
1352 end Img10;
1353
1354 -----------
1355 -- Img16 --
1356 -----------
1357
1358 procedure Img16 (V : Inet_Addr_Comp_Type) is
1359 begin
1360 Buffer (Length) := Hex_To_Char (Natural (V / 16) + 1);
1361 Buffer (Length + 1) := Hex_To_Char (Natural (V mod 16) + 1);
1362 Length := Length + 2;
1363 end Img16;
1364
1365 -- Start of processing for Image
1366
1367 begin
1368 Separator := (if Hex then ':' else '.');
1369
1370 for J in Val'Range loop
1371 if Hex then
1372 Img16 (Val (J));
1373 else
1374 Img10 (Val (J));
1375 end if;
1376
1377 if J /= Val'Last then
1378 Buffer (Length) := Separator;
1379 Length := Length + 1;
1380 end if;
1381 end loop;
1382
1383 return Buffer (1 .. Length - 1);
1384 end Image; 1621 end Image;
1385 1622
1386 ----------- 1623 -----------
1387 -- Image -- 1624 -- Image --
1388 ----------- 1625 -----------
1389 1626
1390 function Image (Value : Inet_Addr_Type) return String is
1391 begin
1392 if Value.Family = Family_Inet then
1393 return Image (Inet_Addr_Bytes (Value.Sin_V4), Hex => False);
1394 else
1395 return Image (Inet_Addr_Bytes (Value.Sin_V6), Hex => True);
1396 end if;
1397 end Image;
1398
1399 -----------
1400 -- Image --
1401 -----------
1402
1403 function Image (Value : Sock_Addr_Type) return String is 1627 function Image (Value : Sock_Addr_Type) return String is
1404 Port : constant String := Value.Port'Img; 1628 function Ipv6_Brackets (S : String) return String is
1405 begin 1629 (if Value.Family = Family_Inet6 then "[" & S & "]" else S);
1406 return Image (Value.Addr) & ':' & Port (2 .. Port'Last); 1630 begin
1631 case Value.Family is
1632 when Family_Unix =>
1633 if ASU.Length (Value.Name) > 0
1634 and then ASU.Element (Value.Name, 1) = ASCII.NUL
1635 then
1636 return '@' & ASU.Slice (Value.Name, 2, ASU.Length (Value.Name));
1637 else
1638 return ASU.To_String (Value.Name);
1639 end if;
1640
1641 when Family_Inet_4_6 =>
1642 declare
1643 Port : constant String := Value.Port'Img;
1644 begin
1645 return Ipv6_Brackets (Image (Value.Addr)) & ':'
1646 & Port (2 .. Port'Last);
1647 end;
1648
1649 when Family_Unspec =>
1650 return "";
1651 end case;
1407 end Image; 1652 end Image;
1408 1653
1409 ----------- 1654 -----------
1410 -- Image -- 1655 -- Image --
1411 ----------- 1656 -----------
1452 1697
1453 function Inet_Addr (Image : String) return Inet_Addr_Type is 1698 function Inet_Addr (Image : String) return Inet_Addr_Type is
1454 use Interfaces.C; 1699 use Interfaces.C;
1455 1700
1456 Img : aliased char_array := To_C (Image); 1701 Img : aliased char_array := To_C (Image);
1457 Addr : aliased C.int;
1458 Res : C.int; 1702 Res : C.int;
1459 Result : Inet_Addr_Type; 1703 Result : Inet_Addr_Type;
1460 1704 IPv6 : constant Boolean := Is_IPv6_Address (Image);
1705 Ia : aliased In_Addr_Union
1706 (if IPv6 then Family_Inet6 else Family_Inet);
1461 begin 1707 begin
1462 -- Special case for an empty Image as on some platforms (e.g. Windows) 1708 -- Special case for an empty Image as on some platforms (e.g. Windows)
1463 -- calling Inet_Addr("") will not return an error. 1709 -- calling Inet_Addr("") will not return an error.
1464 1710
1465 if Image = "" then 1711 if Image = "" then
1466 Raise_Socket_Error (SOSC.EINVAL); 1712 Raise_Socket_Error (SOSC.EINVAL);
1467 end if; 1713 end if;
1468 1714
1469 Res := Inet_Pton (SOSC.AF_INET, Img'Address, Addr'Address); 1715 Res := Inet_Pton
1716 ((if IPv6 then SOSC.AF_INET6 else SOSC.AF_INET), Img'Address,
1717 Ia'Address);
1470 1718
1471 if Res < 0 then 1719 if Res < 0 then
1472 Raise_Socket_Error (Socket_Errno); 1720 Raise_Socket_Error (Socket_Errno);
1473 1721
1474 elsif Res = 0 then 1722 elsif Res = 0 then
1475 Raise_Socket_Error (SOSC.EINVAL); 1723 Raise_Socket_Error (SOSC.EINVAL);
1476 end if; 1724 end if;
1477 1725
1478 To_Inet_Addr (To_In_Addr (Addr), Result); 1726 if IPv6 then
1727 To_Inet_Addr (Ia.In6, Result);
1728 else
1729 To_Inet_Addr (Ia.In4, Result);
1730 end if;
1731
1479 return Result; 1732 return Result;
1480 end Inet_Addr; 1733 end Inet_Addr;
1481 1734
1482 ---------------- 1735 ----------------
1483 -- Initialize -- 1736 -- Initialize --
1523 -- of Sockets_Library_Controller. 1776 -- of Sockets_Library_Controller.
1524 1777
1525 null; 1778 null;
1526 end Initialize; 1779 end Initialize;
1527 1780
1781 ----------------
1782 -- Is_Windows --
1783 ----------------
1784
1785 function Is_Windows return Boolean is
1786 use SOSC;
1787 begin
1788 return Target_OS = Windows;
1789 end Is_Windows;
1790
1528 -------------- 1791 --------------
1529 -- Is_Empty -- 1792 -- Is_Empty --
1530 -------------- 1793 --------------
1531 1794
1532 function Is_Empty (Item : Socket_Set_Type) return Boolean is 1795 function Is_Empty (Item : Socket_Set_Type) return Boolean is
1533 begin 1796 begin
1534 return Item.Last = No_Socket; 1797 return Item.Last = No_Socket;
1535 end Is_Empty; 1798 end Is_Empty;
1536 1799
1537 ------------------- 1800 ---------------------
1538 -- Is_IP_Address -- 1801 -- Is_IPv6_Address --
1539 ------------------- 1802 ---------------------
1540 1803
1541 function Is_IP_Address (Name : String) return Boolean is 1804 function Is_IPv6_Address (Name : String) return Boolean is
1805 Prev_Colon : Natural := 0;
1806 Double_Colon : Boolean := False;
1807 Colons : Natural := 0;
1808 begin
1809 for J in Name'Range loop
1810 if Name (J) = ':' then
1811 Colons := Colons + 1;
1812
1813 if Prev_Colon > 0 and then J = Prev_Colon + 1 then
1814 if Double_Colon then
1815 -- Only one double colon allowed
1816 return False;
1817 end if;
1818
1819 Double_Colon := True;
1820
1821 elsif J = Name'Last then
1822 -- Single colon at the end is not allowed
1823 return False;
1824 end if;
1825
1826 Prev_Colon := J;
1827
1828 elsif Prev_Colon = Name'First then
1829 -- Single colon at start is not allowed
1830 return False;
1831
1832 elsif Name (J) = '.' then
1833 return Prev_Colon > 0
1834 and then Is_IPv4_Address (Name (Prev_Colon + 1 .. Name'Last));
1835
1836 elsif Name (J) not in '0' .. '9' | 'A' .. 'F' | 'a' .. 'f' then
1837 return False;
1838
1839 end if;
1840 end loop;
1841
1842 return Colons in 2 .. 8;
1843 end Is_IPv6_Address;
1844
1845 ---------------------
1846 -- Is_IPv4_Address --
1847 ---------------------
1848
1849 function Is_IPv4_Address (Name : String) return Boolean is
1542 Dots : Natural := 0; 1850 Dots : Natural := 0;
1543 1851
1544 begin 1852 begin
1545 -- Perform a cursory check for a dotted quad: we must have 1 to 3 dots, 1853 -- Perform a cursory check for a dotted quad: we must have 1 to 3 dots,
1546 -- and there must be at least one digit around each. 1854 -- and there must be at least one digit around each.
1567 return False; 1875 return False;
1568 end if; 1876 end if;
1569 end loop; 1877 end loop;
1570 1878
1571 return Dots in 1 .. 3; 1879 return Dots in 1 .. 3;
1572 end Is_IP_Address; 1880 end Is_IPv4_Address;
1573 1881
1574 ------------- 1882 -------------
1575 -- Is_Open -- 1883 -- Is_Open --
1576 ------------- 1884 -------------
1577 1885
1655 begin 1963 begin
1656 if Need_Netdb_Lock then 1964 if Need_Netdb_Lock then
1657 System.Task_Lock.Unlock; 1965 System.Task_Lock.Unlock;
1658 end if; 1966 end if;
1659 end Netdb_Unlock; 1967 end Netdb_Unlock;
1968
1969 ----------------------------
1970 -- Network_Socket_Address --
1971 ----------------------------
1972
1973 function Network_Socket_Address
1974 (Addr : Inet_Addr_Type; Port : Port_Type) return Sock_Addr_Type is
1975 begin
1976 return Result : Sock_Addr_Type (Addr.Family) do
1977 Result.Addr := Addr;
1978 Result.Port := Port;
1979 end return;
1980 end Network_Socket_Address;
1660 1981
1661 -------------------------------- 1982 --------------------------------
1662 -- Normalize_Empty_Socket_Set -- 1983 -- Normalize_Empty_Socket_Set --
1663 -------------------------------- 1984 --------------------------------
1664 1985
1756 ---------------------- 2077 ----------------------
1757 -- Raise_Host_Error -- 2078 -- Raise_Host_Error --
1758 ---------------------- 2079 ----------------------
1759 2080
1760 procedure Raise_Host_Error (H_Error : Integer; Name : String) is 2081 procedure Raise_Host_Error (H_Error : Integer; Name : String) is
1761 function Dedot (Value : String) return String is
1762 (if Value /= "" and then Value (Value'Last) = '.' then
1763 Value (Value'First .. Value'Last - 1)
1764 else
1765 Value);
1766 -- Removes dot at the end of error message
1767
1768 begin 2082 begin
1769 raise Host_Error with 2083 raise Host_Error with
1770 Err_Code_Image (H_Error) 2084 Err_Code_Image (H_Error)
1771 & Dedot (Host_Error_Messages.Host_Error_Message (H_Error)) 2085 & Dedot (Host_Error_Messages.Host_Error_Message (H_Error))
1772 & ": " & Name; 2086 & ": " & Name;
1859 Last : out Ada.Streams.Stream_Element_Offset; 2173 Last : out Ada.Streams.Stream_Element_Offset;
1860 From : out Sock_Addr_Type; 2174 From : out Sock_Addr_Type;
1861 Flags : Request_Flag_Type := No_Request_Flag) 2175 Flags : Request_Flag_Type := No_Request_Flag)
1862 is 2176 is
1863 Res : C.int; 2177 Res : C.int;
1864 Sin : aliased Sockaddr_In; 2178 Sin : aliased Sockaddr;
1865 Len : aliased C.int := Sin'Size / 8; 2179 Len : aliased C.int := Sin'Size / 8;
1866 2180
1867 begin 2181 begin
1868 Res := 2182 Res :=
1869 C_Recvfrom 2183 C_Recvfrom
1878 Raise_Socket_Error (Socket_Errno); 2192 Raise_Socket_Error (Socket_Errno);
1879 end if; 2193 end if;
1880 2194
1881 Last := Last_Index (First => Item'First, Count => size_t (Res)); 2195 Last := Last_Index (First => Item'First, Count => size_t (Res));
1882 2196
1883 To_Inet_Addr (Sin.Sin_Addr, From.Addr); 2197 From := Get_Address (Sin, Len);
1884 From.Port := Port_Type (Network_To_Short (Sin.Sin_Port));
1885 end Receive_Socket; 2198 end Receive_Socket;
1886 2199
1887 -------------------- 2200 --------------------
1888 -- Receive_Vector -- 2201 -- Receive_Vector --
1889 -------------------- 2202 --------------------
2138 To : access Sock_Addr_Type; 2451 To : access Sock_Addr_Type;
2139 Flags : Request_Flag_Type := No_Request_Flag) 2452 Flags : Request_Flag_Type := No_Request_Flag)
2140 is 2453 is
2141 Res : C.int; 2454 Res : C.int;
2142 2455
2143 Sin : aliased Sockaddr_In; 2456 Sin : aliased Sockaddr;
2144 C_To : System.Address; 2457 C_To : System.Address;
2145 Len : C.int; 2458 Len : C.int;
2146 2459
2147 begin 2460 begin
2148 if To /= null then 2461 if To /= null then
2149 Set_Family (Sin.Sin_Family, To.Family); 2462 Set_Address (Sin'Unchecked_Access, To.all, Len);
2150 Set_Address (Sin'Unchecked_Access, To_In_Addr (To.Addr));
2151 Set_Port
2152 (Sin'Unchecked_Access,
2153 Short_To_Network (C.unsigned_short (To.Port)));
2154 C_To := Sin'Address; 2463 C_To := Sin'Address;
2155 Len := Sin'Size / 8;
2156 2464
2157 else 2465 else
2158 C_To := System.Null_Address; 2466 C_To := System.Null_Address;
2159 Len := 0; 2467 Len := 0;
2160 end if; 2468 end if;
2287 -- Set_Socket_Option -- 2595 -- Set_Socket_Option --
2288 ----------------------- 2596 -----------------------
2289 2597
2290 procedure Set_Socket_Option 2598 procedure Set_Socket_Option
2291 (Socket : Socket_Type; 2599 (Socket : Socket_Type;
2292 Level : Level_Type := Socket_Level; 2600 Level : Level_Type;
2293 Option : Option_Type) 2601 Option : Option_Type)
2294 is 2602 is
2295 use SOSC; 2603 use type C.unsigned;
2296 2604
2605 MR : aliased IPV6_Mreq;
2297 V8 : aliased Two_Ints; 2606 V8 : aliased Two_Ints;
2298 V4 : aliased C.int; 2607 V4 : aliased C.int;
2608 U4 : aliased C.unsigned;
2299 V1 : aliased C.unsigned_char; 2609 V1 : aliased C.unsigned_char;
2300 VT : aliased Timeval; 2610 VT : aliased Timeval;
2301 Len : C.int; 2611 Len : C.int;
2302 Add : System.Address := Null_Address; 2612 Add : System.Address := Null_Address;
2303 Res : C.int; 2613 Res : C.int;
2312 2622
2313 when Broadcast 2623 when Broadcast
2314 | Keep_Alive 2624 | Keep_Alive
2315 | No_Delay 2625 | No_Delay
2316 | Reuse_Address 2626 | Reuse_Address
2627 | Multicast_Loop_V4
2628 | Multicast_Loop_V6
2629 | IPv6_Only
2317 => 2630 =>
2318 V4 := C.int (Boolean'Pos (Option.Enabled)); 2631 V4 := C.int (Boolean'Pos (Option.Enabled));
2319 Len := V4'Size / 8; 2632 Len := V4'Size / 8;
2320 Add := V4'Address; 2633 Add := V4'Address;
2321 2634
2340 when Error => 2653 when Error =>
2341 V4 := C.int (Boolean'Pos (True)); 2654 V4 := C.int (Boolean'Pos (True));
2342 Len := V4'Size / 8; 2655 Len := V4'Size / 8;
2343 Add := V4'Address; 2656 Add := V4'Address;
2344 2657
2345 when Add_Membership 2658 when Add_Membership_V4
2346 | Drop_Membership 2659 | Drop_Membership_V4
2347 => 2660 =>
2348 V8 (V8'First) := To_Int (To_In_Addr (Option.Multicast_Address)); 2661 V8 (V8'First) := To_Int (To_In_Addr (Option.Multicast_Address));
2349 V8 (V8'Last) := To_Int (To_In_Addr (Option.Local_Interface)); 2662 V8 (V8'Last) := To_Int (To_In_Addr (Option.Local_Interface));
2350 Len := V8'Size / 8; 2663 Len := V8'Size / 8;
2351 Add := V8'Address; 2664 Add := V8'Address;
2352 2665
2353 when Multicast_If => 2666 when Add_Membership_V6
2667 | Drop_Membership_V6 =>
2668 MR.ipv6mr_multiaddr := To_In6_Addr (Option.Multicast_Address);
2669 MR.ipv6mr_interface := C.unsigned (Option.Interface_Index);
2670 Len := MR'Size / 8;
2671 Add := MR'Address;
2672
2673 when Multicast_If_V4 =>
2354 V4 := To_Int (To_In_Addr (Option.Outgoing_If)); 2674 V4 := To_Int (To_In_Addr (Option.Outgoing_If));
2675 Len := V4'Size / 8;
2676 Add := V4'Address;
2677
2678 when Multicast_If_V6 =>
2679 V4 := C.int (Option.Outgoing_If_Index);
2355 Len := V4'Size / 8; 2680 Len := V4'Size / 8;
2356 Add := V4'Address; 2681 Add := V4'Address;
2357 2682
2358 when Multicast_TTL => 2683 when Multicast_TTL =>
2359 V1 := C.unsigned_char (Option.Time_To_Live); 2684 V1 := C.unsigned_char (Option.Time_To_Live);
2360 Len := V1'Size / 8; 2685 Len := V1'Size / 8;
2361 Add := V1'Address; 2686 Add := V1'Address;
2362 2687
2363 when Multicast_Loop 2688 when Multicast_Hops =>
2364 | Receive_Packet_Info 2689 V4 := C.int (Option.Hop_Limit);
2690 Len := V4'Size / 8;
2691 Add := V4'Address;
2692
2693 when Receive_Packet_Info
2365 => 2694 =>
2366 V1 := C.unsigned_char (Boolean'Pos (Option.Enabled)); 2695 V1 := C.unsigned_char (Boolean'Pos (Option.Enabled));
2367 Len := V1'Size / 8; 2696 Len := V1'Size / 8;
2368 Add := V1'Address; 2697 Add := V1'Address;
2369 2698
2370 when Receive_Timeout 2699 when Receive_Timeout
2371 | Send_Timeout 2700 | Send_Timeout
2372 => 2701 =>
2373 if Target_OS = Windows then 2702 if Is_Windows then
2374 2703
2375 -- On Windows, the timeout is a DWORD in milliseconds, and 2704 -- On Windows, the timeout is a DWORD in milliseconds
2376 -- the actual timeout is 500 ms + the given value (unless it 2705
2377 -- is 0). 2706 Len := U4'Size / 8;
2378 2707 Add := U4'Address;
2379 V4 := C.int (Option.Timeout / 0.001); 2708
2380 2709 U4 := C.unsigned (Option.Timeout / 0.001);
2381 if V4 > 500 then 2710
2382 V4 := V4 - 500; 2711 if Option.Timeout > 0.0 and then U4 = 0 then
2383 2712 -- Avoid round to zero. Zero timeout mean unlimited.
2384 elsif V4 > 0 then 2713 U4 := 1;
2385 V4 := 1;
2386 end if; 2714 end if;
2387 2715
2388 Len := V4'Size / 8; 2716 -- Old windows versions actual timeout is 500 ms + the given
2389 Add := V4'Address; 2717 -- value (unless it is 0).
2718
2719 if Minus_500ms_Windows_Timeout /= 0 then
2720 if U4 > 500 then
2721 U4 := U4 - 500;
2722
2723 elsif U4 > 0 then
2724 U4 := 1;
2725 end if;
2726 end if;
2390 2727
2391 else 2728 else
2392 VT := To_Timeval (Option.Timeout); 2729 VT := To_Timeval (Option.Timeout);
2393 Len := VT'Size / 8; 2730 Len := VT'Size / 8;
2394 Add := VT'Address; 2731 Add := VT'Address;
2414 if Res = Failure then 2751 if Res = Failure then
2415 Raise_Socket_Error (Socket_Errno); 2752 Raise_Socket_Error (Socket_Errno);
2416 end if; 2753 end if;
2417 end Set_Socket_Option; 2754 end Set_Socket_Option;
2418 2755
2419 ----------------------
2420 -- Short_To_Network --
2421 ----------------------
2422
2423 function Short_To_Network (S : C.unsigned_short) return C.unsigned_short is
2424 use type C.unsigned_short;
2425
2426 begin
2427 -- Big-endian case. No conversion needed. On these platforms, htons()
2428 -- defaults to a null procedure.
2429
2430 if Default_Bit_Order = High_Order_First then
2431 return S;
2432
2433 -- Little-endian case. We must swap the high and low bytes of this
2434 -- short to make the port number network compliant.
2435
2436 else
2437 return (S / 256) + (S mod 256) * 256;
2438 end if;
2439 end Short_To_Network;
2440
2441 --------------------- 2756 ---------------------
2442 -- Shutdown_Socket -- 2757 -- Shutdown_Socket --
2443 --------------------- 2758 ---------------------
2444 2759
2445 procedure Shutdown_Socket 2760 procedure Shutdown_Socket
2507 ----------------- 2822 -----------------
2508 -- To_Duration -- 2823 -- To_Duration --
2509 ----------------- 2824 -----------------
2510 2825
2511 function To_Duration (Val : Timeval) return Timeval_Duration is 2826 function To_Duration (Val : Timeval) return Timeval_Duration is
2512 begin 2827 Max_D : constant Long_Long_Integer := Long_Long_Integer (Forever - 0.5);
2513 return Natural (Val.Tv_Sec) * 1.0 + Natural (Val.Tv_Usec) * 1.0E-6; 2828 Tv_sec_64 : constant Boolean := SOSC.SIZEOF_tv_sec = 8;
2829 -- Need to separate this condition into the constant declaration to
2830 -- avoid GNAT warning about "always true" or "always false".
2831 begin
2832 if Tv_sec_64 then
2833 -- Check for possible Duration overflow when Tv_Sec field is 64 bit
2834 -- integer.
2835
2836 if Val.Tv_Sec > time_t (Max_D) or else
2837 (Val.Tv_Sec = time_t (Max_D) and then
2838 Val.Tv_Usec > suseconds_t ((Forever - Duration (Max_D)) * 1E6))
2839 then
2840 return Forever;
2841 end if;
2842 end if;
2843
2844 return Duration (Val.Tv_Sec) + Duration (Val.Tv_Usec) * 1.0E-6;
2514 end To_Duration; 2845 end To_Duration;
2515 2846
2516 ------------------- 2847 -------------------
2517 -- To_Host_Entry -- 2848 -- To_Host_Entry --
2518 ------------------- 2849 -------------------
2519 2850
2520 function To_Host_Entry (E : Hostent_Access) return Host_Entry_Type is 2851 function To_Host_Entry (E : Hostent_Access) return Host_Entry_Type is
2521 use type C.size_t;
2522
2523 Aliases_Count, Addresses_Count : Natural; 2852 Aliases_Count, Addresses_Count : Natural;
2524 2853
2525 -- H_Length is not used because it is currently only ever set to 4, as 2854 Family : constant Family_Type :=
2526 -- we only handle the case of H_Addrtype being AF_INET. 2855 (case Hostent_H_Addrtype (E) is
2527 2856 when SOSC.AF_INET => Family_Inet,
2528 begin 2857 when SOSC.AF_INET6 => Family_Inet6,
2529 if Hostent_H_Addrtype (E) /= SOSC.AF_INET then 2858 when others => Family_Unspec);
2859
2860 Addr_Len : constant C.size_t := C.size_t (Hostent_H_Length (E));
2861
2862 begin
2863 if Family = Family_Unspec then
2530 Raise_Socket_Error (SOSC.EPFNOSUPPORT); 2864 Raise_Socket_Error (SOSC.EPFNOSUPPORT);
2531 end if; 2865 end if;
2532 2866
2533 Aliases_Count := 0; 2867 Aliases_Count := 0;
2534 while Hostent_H_Alias (E, C.int (Aliases_Count)) /= Null_Address loop 2868 while Hostent_H_Alias (E, C.int (Aliases_Count)) /= Null_Address loop
2552 (E, C.int (J - Result.Aliases'First)))); 2886 (E, C.int (J - Result.Aliases'First))));
2553 end loop; 2887 end loop;
2554 2888
2555 for J in Result.Addresses'Range loop 2889 for J in Result.Addresses'Range loop
2556 declare 2890 declare
2557 Addr : In_Addr; 2891 Ia : In_Addr_Union (Family);
2558 2892
2559 -- Hostent_H_Addr (E, <index>) may return an address that is 2893 -- Hostent_H_Addr (E, <index>) may return an address that is
2560 -- not correctly aligned for In_Addr, so we need to use 2894 -- not correctly aligned for In_Addr, so we need to use
2561 -- an intermediate copy operation on a type with an alignment 2895 -- an intermediate copy operation on a type with an alignment
2562 -- of 1 to recover the value. 2896 -- of 1 to recover the value.
2563 2897
2564 subtype Addr_Buf_T is C.char_array (1 .. Addr'Size / 8); 2898 subtype Addr_Buf_T is C.char_array (1 .. Addr_Len);
2565 Unaligned_Addr : Addr_Buf_T; 2899 Unaligned_Addr : Addr_Buf_T;
2566 for Unaligned_Addr'Address 2900 for Unaligned_Addr'Address
2567 use Hostent_H_Addr (E, C.int (J - Result.Addresses'First)); 2901 use Hostent_H_Addr (E, C.int (J - Result.Addresses'First));
2568 pragma Import (Ada, Unaligned_Addr); 2902 pragma Import (Ada, Unaligned_Addr);
2569 2903
2570 Aligned_Addr : Addr_Buf_T; 2904 Aligned_Addr : Addr_Buf_T;
2571 for Aligned_Addr'Address use Addr'Address; 2905 for Aligned_Addr'Address use Ia'Address;
2572 pragma Import (Ada, Aligned_Addr); 2906 pragma Import (Ada, Aligned_Addr);
2573 2907
2574 begin 2908 begin
2575 Aligned_Addr := Unaligned_Addr; 2909 Aligned_Addr := Unaligned_Addr;
2576 To_Inet_Addr (Addr, Result.Addresses (J)); 2910 if Family = Family_Inet6 then
2911 To_Inet_Addr (Ia.In6, Result.Addresses (J));
2912 else
2913 To_Inet_Addr (Ia.In4, Result.Addresses (J));
2914 end if;
2577 end; 2915 end;
2578 end loop; 2916 end loop;
2579 end return; 2917 end return;
2580 end To_Host_Entry; 2918 end To_Host_Entry;
2581
2582 ----------------
2583 -- To_In_Addr --
2584 ----------------
2585
2586 function To_In_Addr (Addr : Inet_Addr_Type) return In_Addr is
2587 begin
2588 if Addr.Family = Family_Inet then
2589 return (S_B1 => C.unsigned_char (Addr.Sin_V4 (1)),
2590 S_B2 => C.unsigned_char (Addr.Sin_V4 (2)),
2591 S_B3 => C.unsigned_char (Addr.Sin_V4 (3)),
2592 S_B4 => C.unsigned_char (Addr.Sin_V4 (4)));
2593 end if;
2594
2595 raise Socket_Error with "IPv6 not supported";
2596 end To_In_Addr;
2597
2598 ------------------
2599 -- To_Inet_Addr --
2600 ------------------
2601
2602 procedure To_Inet_Addr
2603 (Addr : In_Addr;
2604 Result : out Inet_Addr_Type) is
2605 begin
2606 Result.Sin_V4 (1) := Inet_Addr_Comp_Type (Addr.S_B1);
2607 Result.Sin_V4 (2) := Inet_Addr_Comp_Type (Addr.S_B2);
2608 Result.Sin_V4 (3) := Inet_Addr_Comp_Type (Addr.S_B3);
2609 Result.Sin_V4 (4) := Inet_Addr_Comp_Type (Addr.S_B4);
2610 end To_Inet_Addr;
2611 2919
2612 ------------ 2920 ------------
2613 -- To_Int -- 2921 -- To_Int --
2614 ------------ 2922 ------------
2615 2923
2699 3007
2700 -- Normal case where we do round down 3008 -- Normal case where we do round down
2701 3009
2702 else 3010 else
2703 S := time_t (Val - 0.5); 3011 S := time_t (Val - 0.5);
2704 uS := suseconds_t (1_000_000 * (Val - Selector_Duration (S))); 3012 uS := suseconds_t (1_000_000 * (Val - Selector_Duration (S)) - 0.5);
3013
3014 if uS = -1 then
3015 -- It happen on integer duration
3016 uS := 0;
3017 end if;
2705 end if; 3018 end if;
2706 3019
2707 return (S, uS); 3020 return (S, uS);
2708 end To_Timeval; 3021 end To_Timeval;
2709 3022
2794 -------------------- 3107 --------------------
2795 -- Create_Address -- 3108 -- Create_Address --
2796 -------------------- 3109 --------------------
2797 3110
2798 function Create_Address 3111 function Create_Address
2799 (Family : Family_Type; Bytes : Inet_Addr_Bytes) return Inet_Addr_Type 3112 (Family : Family_Inet_4_6; Bytes : Inet_Addr_Bytes) return Inet_Addr_Type
2800 is 3113 is
2801 (case Family is 3114 (case Family is
2802 when Family_Inet => (Family_Inet, Bytes), 3115 when Family_Inet => (Family_Inet, Bytes),
2803 when Family_Inet6 => (Family_Inet6, Bytes)); 3116 when Family_Inet6 => (Family_Inet6, Bytes));
2804 3117
2814 ---------- 3127 ----------
2815 -- Mask -- 3128 -- Mask --
2816 ---------- 3129 ----------
2817 3130
2818 function Mask 3131 function Mask
2819 (Family : Family_Type; 3132 (Family : Family_Inet_4_6;
2820 Length : Natural; 3133 Length : Natural;
2821 Host : Boolean := False) return Inet_Addr_Type 3134 Host : Boolean := False) return Inet_Addr_Type
2822 is 3135 is
2823 Addr_Len : constant Natural := Inet_Addr_Bytes_Length (Family); 3136 Addr_Len : constant Natural := Inet_Addr_Bytes_Length (Family);
2824 begin 3137 begin
2846 3159
2847 return Create_Address (Family, B); 3160 return Create_Address (Family, B);
2848 end; 3161 end;
2849 end Mask; 3162 end Mask;
2850 3163
3164 -------------------------
3165 -- Unix_Socket_Address --
3166 -------------------------
3167
3168 function Unix_Socket_Address (Addr : String) return Sock_Addr_Type is
3169 begin
3170 return Sock_Addr_Type'(Family_Unix, ASU.To_Unbounded_String (Addr));
3171 end Unix_Socket_Address;
3172
2851 ----------- 3173 -----------
2852 -- "and" -- 3174 -- "and" --
2853 ----------- 3175 -----------
2854 3176
2855 function "and" (Addr, Mask : Inet_Addr_Type) return Inet_Addr_Type is 3177 function "and" (Addr, Mask : Inet_Addr_Type) return Inet_Addr_Type is