XRootD
Loading...
Searching...
No Matches
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"
52
53#ifdef HAVE_SYSTEMD
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
72XrdLink *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
130int 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
185XrdLink *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
214int 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
#define XRDNET_UDPBUFFSZ
#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)
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)