1------------------------------------------------------------------------------ 2-- -- 3-- GNAT COMPILER COMPONENTS -- 4-- -- 5-- G N A T . S O C K E T S . T H I N _ C O M M O N -- 6-- -- 7-- S p e c -- 8-- -- 9-- Copyright (C) 2008-2019, AdaCore -- 10-- -- 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- -- 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- -- 15-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- 16-- or FITNESS FOR A PARTICULAR PURPOSE. -- 17-- -- 18-- As a special exception under Section 7 of GPL version 3, you are granted -- 19-- additional permissions described in the GCC Runtime Library Exception, -- 20-- version 3.1, as published by the Free Software Foundation. -- 21-- -- 22-- You should have received a copy of the GNU General Public License and -- 23-- a copy of the GCC Runtime Library Exception along with this program; -- 24-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- 25-- <http://www.gnu.org/licenses/>. -- 26-- -- 27-- GNAT was originally developed by the GNAT team at New York University. -- 28-- Extensive contributions were provided by Ada Core Technologies Inc. -- 29-- -- 30------------------------------------------------------------------------------ 31 32-- This is the target-independent part of the thin sockets mapping. 33-- This package should not be directly with'ed by an applications program. 34 35with Ada.Unchecked_Conversion; 36with Interfaces.C.Strings; 37 38package GNAT.Sockets.Thin_Common is 39 40 package C renames Interfaces.C; 41 package CS renames C.Strings; 42 43 Success : constant C.int := 0; 44 Failure : constant C.int := -1; 45 46 type time_t is 47 range -2 ** (8 * SOSC.SIZEOF_tv_sec - 1) 48 .. 2 ** (8 * SOSC.SIZEOF_tv_sec - 1) - 1; 49 for time_t'Size use 8 * SOSC.SIZEOF_tv_sec; 50 pragma Convention (C, time_t); 51 52 type suseconds_t is 53 range -2 ** (8 * SOSC.SIZEOF_tv_usec - 1) 54 .. 2 ** (8 * SOSC.SIZEOF_tv_usec - 1) - 1; 55 for suseconds_t'Size use 8 * SOSC.SIZEOF_tv_usec; 56 pragma Convention (C, suseconds_t); 57 58 type Timeval is record 59 Tv_Sec : time_t; 60 Tv_Usec : suseconds_t; 61 end record; 62 pragma Convention (C, Timeval); 63 64 type Timeval_Access is access all Timeval; 65 pragma Convention (C, Timeval_Access); 66 67 type socklen_t is mod 2 ** (8 * SOSC.SIZEOF_socklen_t); 68 for socklen_t'Size use (8 * SOSC.SIZEOF_socklen_t); 69 70 Immediat : constant Timeval := (0, 0); 71 72 ------------------------------------------- 73 -- Mapping tables to low level constants -- 74 ------------------------------------------- 75 76 Families : constant array (Family_Type) of C.int := 77 (Family_Unspec => SOSC.AF_UNSPEC, 78 Family_Inet => SOSC.AF_INET, 79 Family_Inet6 => SOSC.AF_INET6); 80 81 Lengths : constant array (Family_Type) of C.unsigned_char := 82 (Family_Unspec => 0, 83 Family_Inet => SOSC.SIZEOF_sockaddr_in, 84 Family_Inet6 => SOSC.SIZEOF_sockaddr_in6); 85 86 ---------------------------- 87 -- Generic socket address -- 88 ---------------------------- 89 90 -- Common header 91 92 -- All socket address types (struct sockaddr, struct sockaddr_storage, 93 -- and protocol specific address types) start with the same 2-byte header, 94 -- which is either a length and a family (one byte each) or just a two-byte 95 -- family. The following unchecked union describes the two possible layouts 96 -- and is meant to be constrained with SOSC.Have_Sockaddr_Len. 97 98 type Sockaddr_Length_And_Family 99 (Has_Sockaddr_Len : Boolean := False) 100 is record 101 case Has_Sockaddr_Len is 102 when True => 103 Length : C.unsigned_char; 104 Char_Family : C.unsigned_char; 105 106 when False => 107 Short_Family : C.unsigned_short; 108 end case; 109 end record; 110 pragma Unchecked_Union (Sockaddr_Length_And_Family); 111 pragma Convention (C, Sockaddr_Length_And_Family); 112 113 procedure Set_Family 114 (Length_And_Family : out Sockaddr_Length_And_Family; 115 Family : Family_Type); 116 -- Set the family component to the appropriate value for Family, and also 117 -- set Length accordingly if applicable on this platform. 118 119 ---------------------------- 120 -- AF_INET socket address -- 121 ---------------------------- 122 123 type In_Addr is record 124 S_B1, S_B2, S_B3, S_B4 : C.unsigned_char; 125 end record; 126 for In_Addr'Alignment use C.int'Alignment; 127 pragma Convention (C, In_Addr); 128 -- IPv4 address, represented as a network-order C.int. Note that the 129 -- underlying operating system may assume that values of this type have 130 -- C.int alignment, so we need to provide a suitable alignment clause here. 131 132 function To_In_Addr is new Ada.Unchecked_Conversion (C.int, In_Addr); 133 function To_Int is new Ada.Unchecked_Conversion (In_Addr, C.int); 134 135 function To_In_Addr (Addr : Inet_Addr_Type) return In_Addr; 136 procedure To_Inet_Addr 137 (Addr : In_Addr; 138 Result : out Inet_Addr_Type); 139 -- Conversion functions 140 141 type In6_Addr is array (1 .. 16) of C.unsigned_char; 142 for In6_Addr'Alignment use C.int'Alignment; 143 pragma Convention (C, In6_Addr); 144 145 function To_In6_Addr (Addr : Inet_Addr_Type) return In6_Addr; 146 procedure To_Inet_Addr 147 (Addr : In6_Addr; 148 Result : out Inet_Addr_Type); 149 -- Conversion functions 150 151 type Sockaddr (Family : Family_Type := Family_Inet) is record 152 Sin_Family : Sockaddr_Length_And_Family; 153 -- Address family (and address length on some platforms) 154 155 Sin_Port : C.unsigned_short; 156 -- Port in network byte order 157 158 case Family is 159 when Family_Inet => 160 Sin_Addr : In_Addr := (others => 0); 161 -- IPv4 address 162 163 Sin_Zero : C.char_array (1 .. 8) := (others => C.nul); 164 -- Padding 165 -- 166 -- Note that some platforms require that all unused (reserved) bytes 167 -- in addresses be initialized to 0 (e.g. VxWorks). 168 when Family_Inet6 => 169 Sin6_FlowInfo : Interfaces.Unsigned_32 := 0; 170 Sin6_Addr : In6_Addr := (others => 0); 171 Sin6_Scope_Id : Interfaces.Unsigned_32 := 0; 172 when Family_Unspec => 173 null; 174 end case; 175 end record; 176 pragma Unchecked_Union (Sockaddr); 177 pragma Convention (C, Sockaddr); 178 -- Internet socket address 179 180 type Sockaddr_Access is access all Sockaddr; 181 pragma Convention (C, Sockaddr_Access); 182 -- Access to internet socket address 183 184 procedure Set_Address 185 (Sin : Sockaddr_Access; 186 Address : Sock_Addr_Type); 187 -- Initialise all necessary fields in Sin from Address. 188 -- Set appropriate Family, Port, and either Sin.Sin_Addr or Sin.Sin6_Addr 189 -- depend on family. 190 191 function Get_Address (Sin : Sockaddr) return Sock_Addr_Type; 192 -- Get Sock_Addr_Type from Sockaddr 193 194 ------------------ 195 -- Host entries -- 196 ------------------ 197 198 type Hostent is new 199 System.Storage_Elements.Storage_Array (1 .. SOSC.SIZEOF_struct_hostent); 200 for Hostent'Alignment use 8; 201 -- Host entry. This is an opaque type used only via the following 202 -- accessor functions, because 'struct hostent' has different layouts on 203 -- different platforms. 204 205 type Hostent_Access is access all Hostent; 206 pragma Convention (C, Hostent_Access); 207 -- Access to host entry 208 209 function Hostent_H_Name 210 (E : Hostent_Access) return System.Address; 211 212 function Hostent_H_Alias 213 (E : Hostent_Access; I : C.int) return System.Address; 214 215 function Hostent_H_Addrtype 216 (E : Hostent_Access) return C.int; 217 218 function Hostent_H_Length 219 (E : Hostent_Access) return C.int; 220 221 function Hostent_H_Addr 222 (E : Hostent_Access; Index : C.int) return System.Address; 223 224 --------------------- 225 -- Service entries -- 226 --------------------- 227 228 type Servent is new 229 System.Storage_Elements.Storage_Array (1 .. SOSC.SIZEOF_struct_servent); 230 for Servent'Alignment use 8; 231 -- Service entry. This is an opaque type used only via the following 232 -- accessor functions, because 'struct servent' has different layouts on 233 -- different platforms. 234 235 type Servent_Access is access all Servent; 236 pragma Convention (C, Servent_Access); 237 -- Access to service entry 238 239 function Servent_S_Name 240 (E : Servent_Access) return System.Address; 241 242 function Servent_S_Alias 243 (E : Servent_Access; Index : C.int) return System.Address; 244 245 function Servent_S_Port 246 (E : Servent_Access) return C.unsigned_short; 247 248 function Servent_S_Proto 249 (E : Servent_Access) return System.Address; 250 251 ------------------ 252 -- NetDB access -- 253 ------------------ 254 255 -- There are three possible situations for the following NetDB access 256 -- functions: 257 -- - inherently thread safe (case of data returned in a thread specific 258 -- buffer); 259 -- - thread safe using user-provided buffer; 260 -- - thread unsafe. 261 -- 262 -- In the first and third cases, the Buf and Buflen are ignored. In the 263 -- second case, the caller must provide a buffer large enough to 264 -- accommodate the returned data. In the third case, the caller must ensure 265 -- that these functions are called within a critical section. 266 267 function C_Gethostbyname 268 (Name : C.char_array; 269 Ret : not null access Hostent; 270 Buf : System.Address; 271 Buflen : C.int; 272 H_Errnop : not null access C.int) return C.int; 273 274 function C_Gethostbyaddr 275 (Addr : System.Address; 276 Addr_Len : C.int; 277 Addr_Type : C.int; 278 Ret : not null access Hostent; 279 Buf : System.Address; 280 Buflen : C.int; 281 H_Errnop : not null access C.int) return C.int; 282 283 function C_Getservbyname 284 (Name : C.char_array; 285 Proto : C.char_array; 286 Ret : not null access Servent; 287 Buf : System.Address; 288 Buflen : C.int) return C.int; 289 290 function C_Getservbyport 291 (Port : C.int; 292 Proto : C.char_array; 293 Ret : not null access Servent; 294 Buf : System.Address; 295 Buflen : C.int) return C.int; 296 297 Address_Size : constant := Standard'Address_Size; 298 299 type Addrinfo; 300 type Addrinfo_Access is access all Addrinfo; 301 302 type Addrinfo is record 303 ai_flags : C.int; 304 ai_family : C.int; 305 ai_socktype : C.int; 306 ai_protocol : C.int; 307 ai_addrlen : socklen_t; 308 ai_addr : Sockaddr_Access; 309 ai_canonname : CS.char_array_access; 310 ai_next : Addrinfo_Access; 311 end record with Convention => C; 312 for Addrinfo use record 313 ai_flags at SOSC.AI_FLAGS_OFFSET range 0 .. C.int'Size - 1; 314 ai_family at SOSC.AI_FAMILY_OFFSET range 0 .. C.int'Size - 1; 315 ai_socktype at SOSC.AI_SOCKTYPE_OFFSET range 0 .. C.int'Size - 1; 316 ai_protocol at SOSC.AI_PROTOCOL_OFFSET range 0 .. C.int'Size - 1; 317 ai_addrlen at SOSC.AI_ADDRLEN_OFFSET range 0 .. socklen_t'Size - 1; 318 ai_canonname at SOSC.AI_CANONNAME_OFFSET range 0 .. Address_Size - 1; 319 ai_addr at SOSC.AI_ADDR_OFFSET range 0 .. Address_Size - 1; 320 ai_next at SOSC.AI_NEXT_OFFSET range 0 .. Address_Size - 1; 321 end record; 322 323 function C_Getaddrinfo 324 (Node : CS.char_array_access; 325 Service : CS.char_array_access; 326 Hints : access constant Addrinfo; 327 Res : not null access Addrinfo_Access) return C.int; 328 329 procedure C_Freeaddrinfo (res : Addrinfo_Access); 330 331 function C_Getnameinfo 332 (sa : Sockaddr_Access; 333 salen : socklen_t; 334 host : CS.char_array_access; 335 hostlen : C.size_t; 336 serv : CS.char_array_access; 337 servlen : C.size_t; 338 flags : C.int) return C.int; 339 340 function C_GAI_Strerror (ecode : C.int) return CS.chars_ptr; 341 342 ------------------------------------ 343 -- Scatter/gather vector handling -- 344 ------------------------------------ 345 346 type Msghdr is record 347 Msg_Name : System.Address; 348 Msg_Namelen : C.unsigned; 349 Msg_Iov : System.Address; 350 Msg_Iovlen : SOSC.Msg_Iovlen_T; 351 Msg_Control : System.Address; 352 Msg_Controllen : C.size_t; 353 Msg_Flags : C.int; 354 end record; 355 pragma Convention (C, Msghdr); 356 357 ---------------------------- 358 -- Socket sets management -- 359 ---------------------------- 360 361 procedure Get_Socket_From_Set 362 (Set : access Fd_Set; 363 Last : access C.int; 364 Socket : access C.int); 365 -- Get last socket in Socket and remove it from the socket set. The 366 -- parameter Last is a maximum value of the largest socket. This hint is 367 -- used to avoid scanning very large socket sets. After a call to 368 -- Get_Socket_From_Set, Last is set back to the real largest socket in the 369 -- socket set. 370 371 procedure Insert_Socket_In_Set 372 (Set : access Fd_Set; 373 Socket : C.int); 374 -- Insert socket in the socket set 375 376 function Is_Socket_In_Set 377 (Set : access constant Fd_Set; 378 Socket : C.int) return C.int; 379 -- Check whether Socket is in the socket set, return a non-zero 380 -- value if it is, zero if it is not. 381 382 procedure Last_Socket_In_Set 383 (Set : access Fd_Set; 384 Last : access C.int); 385 -- Find the largest socket in the socket set. This is needed for select(). 386 -- When Last_Socket_In_Set is called, parameter Last is a maximum value of 387 -- the largest socket. This hint is used to avoid scanning very large 388 -- socket sets. After the call, Last is set back to the real largest socket 389 -- in the socket set. 390 391 procedure Remove_Socket_From_Set (Set : access Fd_Set; Socket : C.int); 392 -- Remove socket from the socket set 393 394 procedure Reset_Socket_Set (Set : access Fd_Set); 395 -- Make Set empty 396 397 ------------------------------------------ 398 -- Pairs of signalling file descriptors -- 399 ------------------------------------------ 400 401 type Two_Ints is array (0 .. 1) of C.int; 402 pragma Convention (C, Two_Ints); 403 -- Container for two int values 404 405 subtype Fd_Pair is Two_Ints; 406 -- Two_Ints as used for Create_Signalling_Fds: a pair of connected file 407 -- descriptors, one of which (the "read end" of the connection) being used 408 -- for reading, the other one (the "write end") being used for writing. 409 410 Read_End : constant := 0; 411 Write_End : constant := 1; 412 -- Indexes into an Fd_Pair value providing access to each of the connected 413 -- file descriptors. 414 415 function Inet_Pton 416 (Af : C.int; 417 Cp : System.Address; 418 Inp : System.Address) return C.int; 419 420 function Inet_Ntop 421 (Af : C.int; 422 Src : System.Address; 423 Dst : CS.char_array_access; 424 Size : socklen_t) return CS.char_array_access; 425 426 function C_Ioctl 427 (Fd : C.int; 428 Req : SOSC.IOCTL_Req_T; 429 Arg : access C.int) return C.int; 430 431 function Short_To_Network 432 (S : C.unsigned_short) return C.unsigned_short; 433 pragma Inline (Short_To_Network); 434 -- Convert a port number into a network port number 435 436 function Network_To_Short 437 (S : C.unsigned_short) return C.unsigned_short 438 renames Short_To_Network; 439 -- Symmetric operation 440 441private 442 pragma Import (C, Get_Socket_From_Set, "__gnat_get_socket_from_set"); 443 pragma Import (C, Is_Socket_In_Set, "__gnat_is_socket_in_set"); 444 pragma Import (C, Last_Socket_In_Set, "__gnat_last_socket_in_set"); 445 pragma Import (C, Insert_Socket_In_Set, "__gnat_insert_socket_in_set"); 446 pragma Import (C, Remove_Socket_From_Set, "__gnat_remove_socket_from_set"); 447 pragma Import (C, Reset_Socket_Set, "__gnat_reset_socket_set"); 448 pragma Import (C, C_Ioctl, "__gnat_socket_ioctl"); 449 pragma Import (C, Inet_Pton, SOSC.Inet_Pton_Linkname); 450 pragma Import (C, Inet_Ntop, SOSC.Inet_Ntop_Linkname); 451 452 pragma Import (C, C_Gethostbyname, "__gnat_gethostbyname"); 453 pragma Import (C, C_Gethostbyaddr, "__gnat_gethostbyaddr"); 454 pragma Import (C, C_Getservbyname, "__gnat_getservbyname"); 455 pragma Import (C, C_Getservbyport, "__gnat_getservbyport"); 456 457 pragma Import (C, C_Getaddrinfo, "__gnat_getaddrinfo"); 458 pragma Import (C, C_Freeaddrinfo, "__gnat_freeaddrinfo"); 459 pragma Import (C, C_Getnameinfo, "__gnat_getnameinfo"); 460 pragma Import (C, C_GAI_Strerror, "__gnat_gai_strerror"); 461 462 pragma Import (C, Servent_S_Name, "__gnat_servent_s_name"); 463 pragma Import (C, Servent_S_Alias, "__gnat_servent_s_alias"); 464 pragma Import (C, Servent_S_Port, "__gnat_servent_s_port"); 465 pragma Import (C, Servent_S_Proto, "__gnat_servent_s_proto"); 466 467 pragma Import (C, Hostent_H_Name, "__gnat_hostent_h_name"); 468 pragma Import (C, Hostent_H_Alias, "__gnat_hostent_h_alias"); 469 pragma Import (C, Hostent_H_Addrtype, "__gnat_hostent_h_addrtype"); 470 pragma Import (C, Hostent_H_Length, "__gnat_hostent_h_length"); 471 pragma Import (C, Hostent_H_Addr, "__gnat_hostent_h_addr"); 472 473end GNAT.Sockets.Thin_Common; 474