XRootD
XrdInet.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d I n e t . c c */
4 /* */
5 /* (c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* Produced by Andrew Hanushevsky for Stanford University under contract */
7 /* DE-AC02-76-SFO0515 with the Department of Energy */
8 /* */
9 /* This file is part of the XRootD software suite. */
10 /* */
11 /* XRootD is free software: you can redistribute it and/or modify it under */
12 /* the terms of the GNU Lesser General Public License as published by the */
13 /* Free Software Foundation, either version 3 of the License, or (at your */
14 /* option) any later version. */
15 /* */
16 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19 /* License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24 /* */
25 /* The copyright holder's institutional names and contributor's names may not */
26 /* be used to endorse or promote products derived from this software without */
27 /* specific prior written permission of the institution or contributor. */
28 /******************************************************************************/
29 
30 #include <cctype>
31 #include <cerrno>
32 #include <netdb.h>
33 #include <cstdio>
34 #include <unistd.h>
35 #include <sys/types.h>
36 
37 #ifdef HAVE_SYSTEMD
38 #include <sys/socket.h>
39 #include <systemd/sd-daemon.h>
40 #endif
41 
42 #include "XrdSys/XrdSysError.hh"
43 
44 #include "Xrd/XrdInet.hh"
45 #include "Xrd/XrdLinkCtl.hh"
46 
47 #include "Xrd/XrdTrace.hh"
48 
49 #include "XrdNet/XrdNetAddr.hh"
50 #include "XrdNet/XrdNetOpts.hh"
51 #include "XrdNet/XrdNetSecurity.hh"
52 
53 #ifdef HAVE_SYSTEMD
54 #include "XrdNet/XrdNetBuffer.hh"
55 #include "XrdNet/XrdNetSocket.hh"
56 #endif
57 
58 /******************************************************************************/
59 /* G l o b a l s */
60 /******************************************************************************/
61 
62  bool XrdInet::AssumeV4 = false;
63 
64  const char *XrdInet::TraceID = "Inet";
65 
67 
68 /******************************************************************************/
69 /* A c c e p t */
70 /******************************************************************************/
71 
72 XrdLink *XrdInet::Accept(int opts, int timeout, XrdSysSemaphore *theSem)
73 {
74  static const char *unk = "unkown.endpoint";
75  XrdNetAddr myAddr;
76  XrdLink *lp;
77  int anum=0, lnkopts = (opts & XRDNET_MULTREAD ? XRDLINK_RDLOCK : 0);
78 
79 // Perform regular accept. This will be a unique TCP socket. We loop here
80 // until the accept succeeds as it should never fail at this stage.
81 //
82  while(!XrdNet::Accept(myAddr, opts | XRDNET_NORLKUP, timeout))
83  {if (timeout >= 0)
84  {if (theSem) theSem->Post();
85  return (XrdLink *)0;
86  }
87  sleep(1); anum++;
88  if (!(anum%60)) eDest->Emsg("Accept", "Unable to accept connections!");
89  }
90 
91 // If authorization was deferred, tell call we accepted the connection but
92 // will be doing a background check on this connection.
93 //
94  if (theSem) theSem->Post();
95  if (!(netOpts & XRDNET_NORLKUP)) myAddr.Name();
96 
97 // Authorize by ip address or full (slow) hostname format. We defer the check
98 // so that the next accept can occur before we do any DNS resolution.
99 //
100  if (Patrol)
101  {if (!Patrol->Authorize(myAddr))
102  {char ipbuff[512];
103  myAddr.Format(ipbuff, sizeof(ipbuff), XrdNetAddr::fmtAuto,
105  eDest->Emsg("Accept",EACCES,"accept TCP connection from",ipbuff);
106  close(myAddr.SockFD());
107  return (XrdLink *)0;
108  }
109  }
110 
111 // Allocate a new network object
112 //
113  if (!(lp = XrdLinkCtl::Alloc(myAddr, lnkopts)))
114  {eDest->Emsg("Accept", ENOMEM, "allocate new link for", myAddr.Name(unk));
115  close(myAddr.SockFD());
116  } else {
117  TRACE(NET, "Accepted connection on port " <<Portnum <<" from "
118  <<myAddr.SockFD() <<'@' <<myAddr.Name(unk));
119  }
120 
121 // All done
122 //
123  return lp;
124 }
125 
126 /******************************************************************************/
127 /* B i n d S D */
128 /******************************************************************************/
129 
130 int XrdInet::BindSD(int port, const char *contype)
131 {
132 #ifdef HAVE_SYSTEMD
133  int nSD, opts = XRDNET_SERVER | netOpts;
134 
135 // If an arbitrary port is wanted, then systemd can't supply such a socket.
136 // Of course, do the same in the absencse of systemd sockets.
137 //
138  if (port == 0 || (nSD = sd_listen_fds(0)) <= 0) return Bind(port, contype);
139 
140 // Do some presets here
141 //
142  int v4Sock = AF_INET;
143  int v6Sock = (XrdNetAddr::IPV4Set() ? AF_INET : AF_INET6);
144  uint16_t sdPort = static_cast<uint16_t>(port);
145 
146 // Get correct socket type
147 //
148  if (*contype != 'u') PortType = SOCK_STREAM;
149  else {PortType = SOCK_DGRAM;
151  }
152 
153 // For each fd, check if it is a socket that we should have bound to. Make
154 // allowances for UDP sockets. Otherwise, make sure the socket is listening.
155 //
156  for (int i = 0; i < nSD; i++)
157  {int sdFD = SD_LISTEN_FDS_START + i;
158  if (sd_is_socket_inet(sdFD, v4Sock, PortType, -1, sdPort) > 0
159  || sd_is_socket_inet(sdFD, v6Sock, PortType, -1, sdPort) > 0)
160  {iofd = sdFD;
161  Portnum = port;
163  if (PortType == SOCK_DGRAM)
166  } else {
167  if (sd_is_socket(sdFD,v4Sock,PortType,0) > 0
168  || sd_is_socket(sdFD,v6Sock,PortType,0) > 0) return Listen();
169  }
170  return 0;
171  }
172  }
173 #endif
174 
175 // Either we have no systemd process or no acceptable FD available. Do an
176 // old-style bind() call to setup the socket.
177 //
178  return Bind(port, contype);
179 }
180 
181 /******************************************************************************/
182 /* C o n n e c t */
183 /******************************************************************************/
184 
185 XrdLink *XrdInet::Connect(const char *host, int port, int opts, int tmo)
186 {
187  static const char *unk = "unkown.endpoint";
188  XrdNetAddr myAddr;
189  XrdLink *lp;
190  int lnkopts = (opts & XRDNET_MULTREAD ? XRDLINK_RDLOCK : 0);
191 
192 // Try to do a connect. This will be a unique TCP socket.
193 //
194  if (!XrdNet::Connect(myAddr, host, port, opts, tmo)) return (XrdLink *)0;
195 
196 // Return a link object
197 //
198  if (!(lp = XrdLinkCtl::Alloc(myAddr, lnkopts)))
199  {eDest->Emsg("Connect", ENOMEM, "allocate new link to", myAddr.Name(unk));
200  close(myAddr.SockFD());
201  } else {
202  TRACE(NET, "Connected to " <<myAddr.Name(unk) <<':' <<port);
203  }
204 
205 // All done, return whatever object we have
206 //
207  return lp;
208 }
209 
210 /******************************************************************************/
211 /* Private: L i s t e n */
212 /******************************************************************************/
213 
214 int XrdInet::Listen()
215 {
216  int backlog, erc;
217 
218 // Determine backlog value
219 //
220  if (!(backlog = netOpts & XRDNET_BKLG)) backlog = XRDNET_BKLG;
221 
222 // Issue a listen
223 //
224  if (listen(iofd, backlog) == 0) return 0;
225  erc = errno;
226 
227 // We were unable to listen on this socket. Diagnose and return error.
228 //
229  if (!(netOpts & XRDNET_NOEMSG) && eDest)
230  {char eBuff[64];
231  sprintf(eBuff, "listen on port %d", Portnum);
232  eDest->Emsg("Bind", erc, eBuff);
233  }
234 
235 // Return an error
236 //
237  return -erc;
238 }
239 
240 /******************************************************************************/
241 /* S e c u r e */
242 /******************************************************************************/
243 
245 {
246 
247 // If we don't have a Patrol object then use the one supplied. Otherwise
248 // merge the supplied object into the existing object.
249 //
250  if (Patrol) Patrol->Merge(secp);
251  else Patrol = secp;
252 }
#define XRDLINK_RDLOCK
Definition: XrdLinkCtl.hh:58
#define XRDNET_NORLKUP
Definition: XrdNetOpts.hh:87
#define XRDNET_MULTREAD
Definition: XrdNetOpts.hh:47
#define XRDNET_SERVER
Definition: XrdNetOpts.hh:99
#define XRDNET_NOEMSG
Definition: XrdNetOpts.hh:71
#define XRDNET_UDPSOCKET
Definition: XrdNetOpts.hh:79
#define XRDNET_BKLG
Definition: XrdNetOpts.hh:104
#define XRDNET_UDPBUFFSZ
Definition: XrdNetOpts.hh:114
#define close(a)
Definition: XrdPosix.hh:43
struct myOpts opts
#define TRACE(act, x)
Definition: XrdTrace.hh:63
int BindSD(int port, const char *contype="tcp")
Definition: XrdInet.cc:130
XrdLink * Connect(const char *host, int port, int opts=0, int timeout=-1)
Definition: XrdInet.cc:185
void Secure(XrdNetSecurity *secp)
Definition: XrdInet.cc:244
XrdLink * Accept(int opts=0, int timeout=-1, XrdSysSemaphore *theSem=0)
Definition: XrdInet.cc:72
static XrdNetIF netIF
Definition: XrdInet.hh:68
static XrdLink * Alloc(XrdNetAddr &peer, int opts=0)
Definition: XrdLinkCtl.cc:109
static const int noPort
Do not add port number.
int Format(char *bAddr, int bLen, fmtUse fmtType=fmtAuto, int fmtOpts=0)
@ fmtAuto
Hostname if already resolved o/w use fmtAddr.
const char * Name(const char *eName=0, const char **eText=0)
static bool IPV4Set()
Definition: XrdNetAddr.hh:61
bool Authorize(const char *hSpec)
void Merge(XrdNetSecurity *srcp)
static int setOpts(int fd, int options, XrdSysError *eDest=0)
int Windowsz
Definition: XrdNet.hh:290
int Bind(int port, const char *contype="tcp")
Definition: XrdNet.cc:164
int iofd
Definition: XrdNet.hh:287
XrdSysError * eDest
Definition: XrdNet.hh:283
XrdNetBufferQ * BuffQ
Definition: XrdNet.hh:293
int netOpts
Definition: XrdNet.hh:291
int Connect(XrdNetAddr &myAddr, const char *dest, int port=-1, int opts=0, int timeout=-1)
Definition: XrdNet.cc:252
int Portnum
Definition: XrdNet.hh:288
int BuffSize
Definition: XrdNet.hh:292
int Accept(XrdNetAddr &myAddr, int opts=0, int timeout=-1)
Definition: XrdNet.cc:84
int PortType
Definition: XrdNet.hh:289
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95