summaryrefslogtreecommitdiff
path: root/gcc/ada/g-socket.adb
diff options
context:
space:
mode:
authorcharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2005-06-16 08:41:50 +0000
committercharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2005-06-16 08:41:50 +0000
commitad6d735e79dd7f48d0100bba36828e9d73735303 (patch)
tree9a3decf2d8760e995c4cab0cca0f7835b0284741 /gcc/ada/g-socket.adb
parent187e7e88fc94cdc8f22d2d794d7151a0e6e2a923 (diff)
downloadgcc-ad6d735e79dd7f48d0100bba36828e9d73735303.tar.gz
2005-06-14 Thomas Quinot <quinot@adacore.com>
PR ada/6717 * g-socket.ads, g-socket.adb (Inet_Addr): Special case the all-ones broadcast address. (Create_Selector): Bind listening socket used to create the signalling socket pair to 127.0.0.1 to limit the scope for 'theft' of connection. Set listen backlog to 1 to ensure that we detect socket theft by a failure of our own connect(2) call. (Check_Selector): Improve documentation of the selector mechanism. (Broadcast_Inet_Addr): New constant. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@101043 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ada/g-socket.adb')
-rw-r--r--gcc/ada/g-socket.adb52
1 files changed, 31 insertions, 21 deletions
diff --git a/gcc/ada/g-socket.adb b/gcc/ada/g-socket.adb
index ab2ed6e8ae1..0485abf9a0d 100644
--- a/gcc/ada/g-socket.adb
+++ b/gcc/ada/g-socket.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2001-2004 Ada Core Technologies, Inc. --
+-- Copyright (C) 2001-2005 Ada Core Technologies, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -37,7 +37,6 @@ with Ada.Unchecked_Conversion;
with Interfaces.C.Strings;
-with GNAT.OS_Lib; use GNAT.OS_Lib;
with GNAT.Sockets.Constants;
with GNAT.Sockets.Thin; use GNAT.Sockets.Thin;
with GNAT.Task_Lock;
@@ -651,11 +650,10 @@ package body GNAT.Sockets is
Err : Integer;
begin
- -- We open two signalling sockets. One of them is used to
- -- send data to the other, which is included in a C_Select
- -- socket set. The communication is used to force the call
- -- to C_Select to complete, and the waiting task to resume
- -- its execution.
+ -- We open two signalling sockets. One of them is used to send data to
+ -- send data to the other, which is included in a C_Select socket set.
+ -- The communication is used to force the call to C_Select to complete,
+ -- and the waiting task to resume its execution.
-- Create a listening socket
@@ -664,8 +662,13 @@ package body GNAT.Sockets is
Raise_Socket_Error (Socket_Errno);
end if;
- -- Sin is already correctly initialized. Bind the socket to any
- -- unused port.
+ -- Bind the socket to any unused port on localhost
+
+ Sin.Sin_Addr.S_B1 := 127;
+ Sin.Sin_Addr.S_B2 := 0;
+ Sin.Sin_Addr.S_B3 := 0;
+ Sin.Sin_Addr.S_B4 := 1;
+ Sin.Sin_Port := 0;
Res := C_Bind (S0, Sin'Address, Len);
if Res = Failure then
@@ -684,7 +687,10 @@ package body GNAT.Sockets is
Raise_Socket_Error (Err);
end if;
- Res := C_Listen (S0, 2);
+ -- Set backlog to 1 to guarantee that exactly one call to connect(2)
+ -- can succeed.
+
+ Res := C_Listen (S0, 1);
if Res = Failure then
Err := Socket_Errno;
@@ -700,13 +706,6 @@ package body GNAT.Sockets is
Raise_Socket_Error (Err);
end if;
- -- Use INADDR_LOOPBACK
-
- Sin.Sin_Addr.S_B1 := 127;
- Sin.Sin_Addr.S_B2 := 0;
- Sin.Sin_Addr.S_B3 := 0;
- Sin.Sin_Addr.S_B4 := 1;
-
-- Do a connect and accept the connection
Res := C_Connect (S1, Sin'Address, Len);
@@ -718,6 +717,10 @@ package body GNAT.Sockets is
Raise_Socket_Error (Err);
end if;
+ -- Since the call to connect(2) has suceeded and the backlog limit on
+ -- the listening socket is 1, we know that there is now exactly one
+ -- pending connection on S0, which is the one from S1.
+
S2 := C_Accept (S0, Sin'Address, Len'Access);
if S2 = Failure then
@@ -1232,17 +1235,24 @@ package body GNAT.Sockets is
function Inet_Addr (Image : String) return Inet_Addr_Type is
use Interfaces.C.Strings;
- Img : chars_ptr := New_String (Image);
+ Img : chars_ptr;
Res : C.int;
- Err : Integer;
begin
+ -- Special case for the all-ones broadcast address: this address
+ -- has the same in_addr_t value as Failure, and thus cannot be
+ -- properly returned by inet_addr(3).
+
+ if Image (Image'Range) = "255.255.255.255" then
+ return Broadcast_Inet_Addr;
+ end if;
+
+ Img := New_String (Image);
Res := C_Inet_Addr (Img);
- Err := Errno;
Free (Img);
if Res = Failure then
- Raise_Socket_Error (Err);
+ Raise_Socket_Error (Constants.EINVAL);
end if;
return To_Inet_Addr (To_In_Addr (Res));