00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdNetCVSID = "$Id: XrdNet.cc 25932 2008-10-23 10:58:11Z ganis $";
00014
00015 #include <errno.h>
00016 #include <stdio.h>
00017 #include <string.h>
00018 #ifndef WIN32
00019 #include <poll.h>
00020 #include <unistd.h>
00021 #include <sys/types.h>
00022 #include <sys/socket.h>
00023 #else
00024 #include "XrdSys/XrdWin32.hh"
00025 #endif
00026
00027 #include "XrdNet/XrdNet.hh"
00028 #include "XrdNet/XrdNetDNS.hh"
00029 #include "XrdNet/XrdNetOpts.hh"
00030 #include "XrdNet/XrdNetPeer.hh"
00031 #include "XrdNet/XrdNetSecurity.hh"
00032 #include "XrdNet/XrdNetSocket.hh"
00033
00034 #include "XrdSys/XrdSysPlatform.hh"
00035 #include "XrdSys/XrdSysError.hh"
00036
00037
00038
00039
00040
00041 #define XRDNET_UDPBUFFSZ 32768
00042
00043
00044
00045
00046
00047 XrdNet::XrdNet(XrdSysError *erp, XrdNetSecurity *secp)
00048 {
00049 iofd = PortType = -1;
00050 eDest = erp;
00051 Police = secp;
00052 Domlen = Portnum = Windowsz = netOpts = 0;
00053 Domain = 0;
00054 BuffQ = 0;
00055 }
00056
00057
00058
00059
00060
00061 XrdNet::~XrdNet()
00062 {
00063 unBind();
00064 if (Domain) free(Domain);
00065 }
00066
00067
00068
00069
00070
00071 int XrdNet::Accept(XrdNetPeer &myPeer, int opts, int timeout)
00072 {
00073 int retc;
00074
00075
00076
00077 if (iofd < 0)
00078 {eDest->Emsg("Accept", "Network not bound to a port.");
00079 return 0;
00080 }
00081
00082
00083
00084 do {if (timeout >= 0)
00085 {struct pollfd sfd = {iofd,
00086 POLLIN|POLLRDNORM|POLLRDBAND|POLLPRI|POLLHUP,0};
00087 do {retc = poll(&sfd, 1, timeout*1000);}
00088 while(retc < 0 && (errno == EAGAIN || errno == EINTR));
00089 if (!retc)
00090 {if (!(opts & XRDNET_NOEMSG))
00091 eDest->Emsg("Accept", "Accept timed out.");
00092 return 0;
00093 }
00094 }
00095 } while(!(PortType == SOCK_STREAM ? do_Accept_TCP(myPeer, opts)
00096 : do_Accept_UDP(myPeer, opts)));
00097
00098
00099
00100 if (Domain && !(opts & XRDNET_NODNTRIM)) Trim(myPeer.InetName);
00101 return 1;
00102 }
00103
00104
00105
00106
00107
00108 int XrdNet::Bind(int bindport, const char *contype)
00109 {
00110 XrdNetSocket mySocket(eDest);
00111 int opts = XRDNET_SERVER | netOpts;
00112 int buffsz = Windowsz;
00113
00114
00115
00116 unBind();
00117
00118
00119
00120 if (*contype != 'u') PortType = SOCK_STREAM;
00121 else {PortType = SOCK_DGRAM;
00122 opts |= XRDNET_UDPSOCKET;
00123 if (!buffsz) buffsz = XRDNET_UDPBUFFSZ;
00124 }
00125
00126
00127
00128 if (mySocket.Open(0, bindport, opts, buffsz) < 0)
00129 return -mySocket.LastError();
00130
00131
00132
00133 iofd = mySocket.Detach();
00134
00135
00136
00137 Portnum = (bindport ? bindport : XrdNetDNS::getPort(iofd));
00138
00139
00140
00141 if (PortType == SOCK_DGRAM)
00142 {BuffSize = buffsz;
00143 BuffQ = new XrdNetBufferQ(buffsz);
00144 }
00145 return 0;
00146 }
00147
00148
00149
00150 int XrdNet::Bind(char *path, const char *contype)
00151 {
00152 XrdNetSocket mySocket(eDest);
00153 int opts = XRDNET_SERVER | netOpts;
00154 int buffsz = Windowsz;
00155
00156
00157
00158 if (*path != '/')
00159 {eDest->Emsg("Bind", "Invalid bind path -", path);
00160 return -EINVAL;
00161 }
00162
00163
00164
00165 unBind();
00166
00167
00168
00169 if (*contype != 'd') PortType = SOCK_STREAM;
00170 else {PortType = SOCK_DGRAM;
00171 opts |= XRDNET_UDPSOCKET;
00172 if (!buffsz) buffsz = XRDNET_UDPBUFFSZ;
00173 }
00174
00175
00176
00177 if (mySocket.Open(path, -1, opts, buffsz) < 0) return -mySocket.LastError();
00178
00179
00180
00181 iofd = mySocket.Detach();
00182
00183
00184
00185 if (PortType == SOCK_DGRAM)
00186 {BuffSize = buffsz;
00187 BuffQ = new XrdNetBufferQ(buffsz);
00188 }
00189 return 0;
00190 }
00191
00192
00193
00194
00195
00196 int XrdNet::Connect(XrdNetPeer &myPeer,
00197 const char *host, int port, int opts, int tmo)
00198 {
00199 XrdNetSocket mySocket(opts & XRDNET_NOEMSG ? 0 : eDest);
00200 struct sockaddr *sap;
00201 int buffsz = Windowsz;
00202
00203
00204
00205 if (!opts) opts = netOpts;
00206 if ((opts & XRDNET_UDPSOCKET) && !buffsz) buffsz = XRDNET_UDPBUFFSZ;
00207 if (tmo > 0) opts = (opts & ~XRDNET_TOUT) | (tmo > 255 ? 255 : tmo);
00208
00209
00210
00211 if (mySocket.Open(host, port, opts, buffsz) < 0) return 0;
00212 if (myPeer.InetName) free(myPeer.InetName);
00213 if ((opts & XRDNET_UDPSOCKET) || !host)
00214 {myPeer.InetName = strdup("n/a");
00215 memset((void *)&myPeer.InetAddr, 0, sizeof(myPeer.InetAddr));
00216 } else {
00217 const char *pn = mySocket.Peername(&sap);
00218 if (pn) {memcpy((void *)&myPeer.InetAddr, sap, sizeof(myPeer.InetAddr));
00219 myPeer.InetName = strdup(pn);
00220 if (Domain && !(opts & XRDNET_NODNTRIM)) Trim(myPeer.InetName);
00221 } else {
00222 memset((void *)&myPeer.InetAddr, 0, sizeof(myPeer.InetAddr));
00223 myPeer.InetName = strdup("unknown");
00224 }
00225 }
00226 myPeer.fd = mySocket.Detach();
00227 return 1;
00228 }
00229
00230
00231
00232
00233
00234 int XrdNet::Relay(XrdNetPeer &Peer, const char *dest, int opts)
00235 {
00236 return Connect(Peer, dest, -1, opts | XRDNET_UDPSOCKET);
00237 }
00238
00239
00240
00241
00242
00243 void XrdNet::Secure(XrdNetSecurity *secp)
00244 {
00245
00246
00247
00248
00249 if (Police) Police->Merge(secp);
00250 else Police = secp;
00251 }
00252
00253
00254
00255
00256
00257 void XrdNet::Trim(char *hname)
00258 {
00259 int k = strlen(hname);
00260 char *hnp;
00261
00262 if (Domlen && k > Domlen)
00263 {hnp = hname + (k - Domlen);
00264 if (!strcmp(Domain, hnp)) *hnp = '\0';
00265 }
00266 }
00267
00268
00269
00270
00271
00272 void XrdNet::unBind()
00273 {
00274 if (iofd >= 0) {close(iofd); iofd=-1; Portnum=0;}
00275 if (BuffQ) {delete BuffQ; BuffQ = 0;}
00276 }
00277
00278
00279
00280
00281
00282 int XrdNet::WSize()
00283 {
00284 int wsz;
00285
00286 if (iofd >= 0 && !XrdNetSocket::getWindow(iofd, wsz, eDest)) return wsz;
00287 return 0;
00288 }
00289
00290
00291
00292
00293
00294
00295
00296
00297 int XrdNet::do_Accept_TCP(XrdNetPeer &myPeer, int opts)
00298 {
00299 static int noAcpt = 0;
00300 int newfd;
00301 char *hname;
00302 struct sockaddr addr;
00303 SOCKLEN_t addrlen = sizeof(addr);
00304
00305
00306
00307 do {newfd = accept(iofd, &addr, &addrlen);}
00308 while(newfd < 0 && errno == EINTR);
00309
00310 if (newfd < 0)
00311 {if (errno != EMFILE || !(0x1ff & noAcpt++))
00312 eDest->Emsg("Accept", errno, "perform accept");
00313 return 0;
00314 }
00315
00316
00317
00318 if (Police)
00319 {if (!(hname = Police->Authorize(&addr)))
00320 {eDest->Emsg("Accept", EACCES, "accept TCP connection from",
00321 (hname = XrdNetDNS::getHostName(addr)));
00322 free(hname);
00323 close(newfd);
00324 return 0;
00325 }
00326 } else hname = (opts & XRDNET_NORLKUP ? XrdNetDNS::getHostID(addr)
00327 : XrdNetDNS::getHostName(addr));
00328
00329
00330
00331 XrdNetSocket::setOpts(newfd, (opts ? opts : netOpts));
00332
00333
00334
00335 myPeer.fd = newfd;
00336 memcpy(&(myPeer.InetAddr), &addr, sizeof(myPeer.InetAddr));
00337 if (myPeer.InetName) free(myPeer.InetName);
00338 myPeer.InetName = hname;
00339 return 1;
00340 }
00341
00342
00343
00344
00345
00346 int XrdNet::do_Accept_UDP(XrdNetPeer &myPeer, int opts)
00347 {
00348 char *hname = 0;
00349 int dlen;
00350 struct sockaddr addr;
00351 SOCKLEN_t addrlen = sizeof(addr);
00352 XrdNetBuffer *bp;
00353
00354
00355
00356
00357 if (!(bp = BuffQ->Alloc()))
00358 {eDest->Emsg("Accept", ENOMEM, "accept UDP message");
00359 return 0;
00360 }
00361
00362
00363
00364 do {dlen = recvfrom(iofd,(Sokdata_t)bp->data,BuffSize-1,0,&addr,&addrlen);
00365 } while(dlen < 0 && errno == EINTR);
00366
00367 if (dlen < 0)
00368 {eDest->Emsg("Receive", errno, "perform UDP recvfrom()");
00369 BuffQ->Recycle(bp);
00370 return 0;
00371 } else bp->data[dlen] = '\0';
00372
00373
00374
00375
00376 if (XrdNetDNS::isLoopback(addr)
00377 || (Police && !(hname = Police->Authorize(&addr))))
00378 {eDest->Emsg("Accept", -EACCES, "accept connection from",
00379 (hname = XrdNetDNS::getHostName(addr)));
00380 free(hname);
00381 BuffQ->Recycle(bp);
00382 return 0;
00383 } else {
00384 if (!hname) hname=(opts & XRDNET_NORLKUP ? XrdNetDNS::getHostID(addr)
00385 : XrdNetDNS::getHostName(addr));
00386 }
00387
00388
00389
00390
00391 myPeer.fd = (opts & XRDNET_NEWFD ? dup(iofd) : iofd);
00392 memcpy(&(myPeer.InetAddr), &addr, sizeof(myPeer.InetAddr));
00393 if (myPeer.InetName) free(myPeer.InetName);
00394 myPeer.InetName = hname;
00395 if (myPeer.InetBuff) myPeer.InetBuff->Recycle();
00396 myPeer.InetBuff = bp;
00397 return 1;
00398 }