1 /*******************************************************************************
2 * Copyright (C) 2004-2008 Intel Corp. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * - Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 *
10 * - Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * - Neither the name of Intel Corp. nor the names of its
15 * contributors may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 *******************************************************************************/
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include "ATNetworkTool.h"
36 #include <sstream>
37 #include <algorithm>
38 #include <cerrno>
39 #include <net/if.h>
40 #include <netdb.h>
41
42 #ifdef __sun
43 #include <arpa/inet.h>
44 #include <sys/sockio.h>
45 #include <stdio.h>
46 #include <stropts.h>
47 #else
48 #include <ifaddrs.h>
49 #endif // __sun
50
51 #include <unistd.h>
52 #include <fcntl.h>
53
GetHostNameDomain(const char * name,std::string & domain)54 bool ATNetworkTool::GetHostNameDomain(const char *name, std::string &domain)
55 {
56 const char *domp = strchr(name, '.');
57 if (domp) {
58 domp++;
59 if (*domp) {
60 #ifdef LMS_NET_DEBUG
61 printf("D: %s\n", domp);
62 #endif
63 domain = domp;
64 return true;
65 }
66 }
67 return false;
68 }
69
GetHentDomain(struct hostent * hent,std::string & domain)70 bool ATNetworkTool::GetHentDomain(struct hostent *hent, std::string &domain)
71 {
72 if (NULL == hent) {
73 return false;
74 }
75 if (NULL == hent->h_name) {
76 return false;
77 }
78
79 #ifdef LMS_NET_DEBUG
80 printf("N: %s\n", hent->h_name);
81 #endif
82 if (ATNetworkTool::GetHostNameDomain(hent->h_name, domain)) {
83 return true;
84 }
85
86 if (NULL != hent->h_aliases) {
87 for (char **ssx = hent->h_aliases; ssx && *ssx; ssx++) {
88 #ifdef LMS_NET_DEBUG
89 printf("A: %s\n", *ssx);
90 #endif
91 if (ATNetworkTool::GetHostNameDomain(*ssx, domain)) {
92 return true;
93 }
94 }
95 }
96 return false;
97 }
98
GetIPDomain(const ATAddress & ip,std::string & domain,int & error)99 bool ATNetworkTool::GetIPDomain(const ATAddress &ip, std::string &domain, int &error)
100 {
101 char hbuf[NI_MAXHOST];
102
103 if (0 != (error = getnameinfo(ip.addr(), ip.size(),
104 hbuf, sizeof(hbuf),
105 NULL, 0,
106 NI_NAMEREQD))) {
107 return false;
108 }
109
110 return ATNetworkTool::GetHostNameDomain(hbuf, domain);
111 }
112
GetLocalIPs(ATAddressList & addresses,int & error,int family,bool withloopback)113 int ATNetworkTool::GetLocalIPs(ATAddressList &addresses, int &error, int family, bool withloopback)
114 {
115 struct ifaddrs *ifap;
116
117 #ifdef __sun
118
119 char buf[1024];
120 struct ifconf ifc;
121 struct ifreq *ifr;
122 int sock;
123 int nInterfaces;
124 int i;
125
126 addresses.clear();
127
128 sock = socket(AF_INET, SOCK_DGRAM, 0);
129 if(sock < 0)
130 {
131 perror("socket");
132 return 1;
133 }
134
135 /* Query available interfaces. */
136 ifc.ifc_len = sizeof(buf);
137 ifc.ifc_buf = buf;
138 if(ioctl(sock, SIOCGIFCONF, &ifc) < 0)
139 {
140 perror("ioctl(SIOCGIFCONF)");
141 close(sock);
142 return 1;
143 }
144
145 /* Iterate through the list of interfaces. */
146 ifr = ifc.ifc_req;
147 nInterfaces = ifc.ifc_len / sizeof(struct ifreq);
148 for(i = 0; i < nInterfaces; i++)
149 {
150 struct ifreq *item = &ifr[i];
151
152 if (item->ifr_flags & IFF_LOOPBACK)
153 continue;
154
155 addresses.insert(&item->ifr_addr);
156 }
157
158 close(sock);
159
160 #else // ! __sun
161
162 if (0 != getifaddrs(&ifap)) {
163 error = errno;
164 return -1;
165 }
166
167 addresses.clear();
168 for (struct ifaddrs *ifa = ifap; ifa; ifa = ifa->ifa_next) {
169 if (NULL == ifa->ifa_addr) {
170 continue;
171 }
172 if ((ifa->ifa_flags & IFF_UP) == 0) {
173 continue;
174 }
175 if ((!withloopback) &&
176 (((ifa->ifa_flags & IFF_LOOPBACK) != 0) ||
177 ((ifa->ifa_flags & (IFF_BROADCAST | IFF_POINTOPOINT)) == 0))) {
178 continue;
179 }
180
181 if (AF_UNSPEC != family) {
182 if (ATNetworkTool::AF_XINETX == family) {
183 if (!ATAddress::saIsInet(ifa->ifa_addr)) {
184 continue;
185 }
186 } else {
187 if (ifa->ifa_addr->sa_family != family) {
188 continue;
189 }
190 }
191 }
192
193 addresses.insert(ifa->ifa_addr);
194 }
195 freeifaddrs(ifap);
196
197 #endif // __sun
198
199 return 0;
200 }
201
GetLocalNetDomains(ATDomainMap & domains,int & error,int family)202 int ATNetworkTool::GetLocalNetDomains(ATDomainMap &domains, int &error, int family)
203 {
204 int ret;
205 ATAddressList addresses;
206
207 if (0 != (ret = ATNetworkTool::GetLocalIPs(addresses, error, family))) {
208 return ret;
209 }
210
211 domains.clear();
212 ATAddressList::iterator aend = addresses.end();
213 for (ATAddressList::iterator ait = addresses.begin();
214 ait != aend;
215 ait++)
216 {
217 std::string domain;
218 if (ATNetworkTool::GetIPDomain(*ait, domain, error)) {
219 domains[*ait] = domain;
220 }
221 }
222 return 0;
223 }
224
GetSockDomain(int sock,std::string & domain,int & error)225 int ATNetworkTool::GetSockDomain(int sock, std::string &domain, int &error)
226 {
227 struct sockaddr_storage ss;
228 socklen_t salen = sizeof(ss);
229 struct sockaddr *sa;
230
231 sa = (struct sockaddr *)&ss;
232
233 if (getsockname(sock, sa, &salen) != 0) {
234 error = errno;
235 return -1;
236 }
237
238 if (ATNetworkTool::GetIPDomain(sa, domain, error)) {
239 return 1;
240 }
241 return 0;
242 }
243
GetSockPeerIPs(int sock,ATAddressList & addresses,int & error,int family,bool zeroport)244 int ATNetworkTool::GetSockPeerIPs(int sock, ATAddressList &addresses, int &error,
245 int family, bool zeroport)
246 {
247 struct sockaddr_storage ss;
248 socklen_t salen = sizeof(ss);
249 struct sockaddr *sa;
250 struct addrinfo hints, *paddr, *paddrp;
251
252 sa = (struct sockaddr *)&ss;
253
254 if (getpeername(sock, sa, &salen) != 0) {
255 error = errno;
256 return -1;
257 }
258
259 char hbuf[NI_MAXHOST];
260 char pbuf[NI_MAXSERV];
261 if (0 != (error = getnameinfo(sa, salen,
262 hbuf, sizeof(hbuf),
263 pbuf, sizeof(pbuf),
264 0))) {
265 return -1;
266 }
267
268 memset(&hints, 0, sizeof(hints));
269 if (ATNetworkTool::AF_XINETX == family) {
270 hints.ai_family = PF_UNSPEC;
271 } else {
272 hints.ai_family = family;
273 }
274 hints.ai_socktype = SOCK_STREAM;
275 if (0 != (error = getaddrinfo(hbuf, pbuf, &hints, &paddrp))) {
276 return -1;
277 }
278 addresses.clear();
279 for (paddr = paddrp; paddr; paddr = paddr->ai_next) {
280 if (ATNetworkTool::AF_XINETX == family) {
281 if (!ATAddress::saIsInet(paddr->ai_addr)) {
282 continue;
283 }
284 }
285 if (zeroport) {
286 addresses.insert(ATAddress(paddr->ai_addr, 0));
287 } else {
288 addresses.insert(paddr->ai_addr);
289 }
290 }
291 freeaddrinfo(paddrp);
292 return 0;
293 }
294
IsSockPeerLocal(int sock,int & error,int family)295 int ATNetworkTool::IsSockPeerLocal(int sock, int &error, int family)
296 {
297 ATAddressList localAddresses;
298 ATAddressList targAddresses;
299
300 if (0 != ATNetworkTool::GetSockPeerIPs(sock, targAddresses, error,
301 family, true)) {
302 return -1;
303 }
304 if (0 != ATNetworkTool::GetLocalIPs(localAddresses, error,
305 family, true)) {
306 return -1;
307 }
308 if (std::includes(localAddresses.begin(), localAddresses.end(),
309 targAddresses.begin(), targAddresses.end())) {
310 return 1;
311 }
312 return 0;
313 }
314
CloseSocket(int s)315 int ATNetworkTool::CloseSocket(int s)
316 {
317 shutdown(s, SHUT_RDWR);
318 return close(s);
319 }
320
CreateSocket(const struct addrinfo * addr,int & error)321 int ATNetworkTool::CreateSocket(const struct addrinfo *addr, int &error)
322 {
323 return ATNetworkTool::CreateSocket(addr->ai_addr, addr->ai_addrlen,
324 error,
325 addr->ai_family, addr->ai_socktype,
326 addr->ai_protocol);
327 }
328
CreateSocket(const struct sockaddr * addr,socklen_t addrlen,int & error,int family,int socktype,int protocol)329 int ATNetworkTool::CreateSocket(const struct sockaddr *addr, socklen_t addrlen,
330 int &error,
331 int family, int socktype, int protocol)
332 {
333 int s = socket(family, socktype, protocol);
334 if (s < 0) {
335 error = errno;
336 return -1;
337 }
338
339 if (socktype != SOCK_DGRAM) {
340 linger l;
341 l.l_onoff = 0;
342 l.l_linger = 0;
343 if (setsockopt(s, SOL_SOCKET, SO_LINGER,
344 (char *)&l, sizeof(l)) == -1) {
345 error = errno;
346 close(s);
347 return -1;
348 }
349 }
350
351 if (bind(s, addr, addrlen) == -1) {
352 error = errno;
353 close(s);
354 return -1;
355 }
356
357 return s;
358 }
359
ConnectSocket(struct addrinfo * addr,int & error,bool loopback)360 int ATNetworkTool::ConnectSocket(struct addrinfo *addr,
361 int &error, bool loopback)
362 {
363 return ATNetworkTool::ConnectSocket(addr->ai_addr, addr->ai_addrlen,
364 error, loopback,
365 addr->ai_family, addr->ai_socktype,
366 addr->ai_protocol);
367 }
368
ConnectSocket(const struct sockaddr * addr,socklen_t addrlen,int & error,bool loopback,int family,int socktype,int protocol)369 int ATNetworkTool::ConnectSocket(const struct sockaddr *addr, socklen_t addrlen,
370 int &error, bool loopback,
371 int family, int socktype, int protocol)
372 {
373 struct addrinfo hints, *paddr, *paddrp;
374 int oks = -1;
375
376 memset(&hints, 0, sizeof(hints));
377 if (ATNetworkTool::AF_XINETX == family) {
378 hints.ai_family = PF_UNSPEC;
379 } else {
380 hints.ai_family = family;
381 }
382 hints.ai_socktype = socktype;
383 hints.ai_protocol = protocol;
384 #ifdef AI_NUMERICSERV
385 hints.ai_flags |= AI_NUMERICSERV;
386 #endif
387 if (!loopback) {
388 hints.ai_flags |= AI_PASSIVE;
389 }
390 if ((error = getaddrinfo(NULL, "0", &hints, &paddrp)) != 0) {
391 return -1;
392 }
393 for (paddr = paddrp; paddr; paddr = paddr->ai_next) {
394 if (ATNetworkTool::AF_XINETX == family) {
395 if (!ATAddress::saIsInet(paddr->ai_addr)) {
396 continue;
397 }
398 }
399
400 int s = ATNetworkTool::CreateSocket(paddr, error);
401 if (s < 0) {
402 continue;
403 }
404
405 if (connect(s, addr, addrlen) != 0) {
406 error = errno;
407 ATNetworkTool::CloseSocket(s);
408 continue;
409 }
410
411 oks = s;
412 break;
413 }
414 freeaddrinfo(paddrp);
415 return oks;
416 }
417
CreateServerSocket(in_port_t port,int & error,bool loopback,bool nonblocking,int family,int socktype,int protocol,int backlog)418 int ATNetworkTool::CreateServerSocket(in_port_t port,
419 int &error,
420 bool loopback, bool nonblocking,
421 int family, int socktype, int protocol,
422 int backlog)
423 {
424 std::stringstream ssport;
425
426 ssport << port;
427 return ATNetworkTool::CreateServerSocket(ssport.str().c_str(),
428 error,
429 loopback, nonblocking,
430 family, socktype, protocol,
431 backlog);
432 }
433
CreateServerSocket(const char * port,int & error,bool loopback,bool nonblocking,int family,int socktype,int protocol,int backlog)434 int ATNetworkTool::CreateServerSocket(const char *port,
435 int &error,
436 bool loopback, bool nonblocking,
437 int family, int socktype, int protocol,
438 int backlog)
439 {
440 ATSocketList sockets;
441 int s = -1;
442
443 int num = ATNetworkTool::CreateServerSockets(sockets, port,
444 error,
445 loopback, nonblocking,
446 family, socktype, protocol,
447 backlog, true);
448 if ((num > 0) && (sockets.size() > 0)) {
449 s = sockets[0];
450 }
451 sockets.clear();
452 return s;
453 }
454
455
CreateServerSockets(ATSocketList & sockets,in_port_t port,int & error,bool loopback,bool nonblocking,int family,int socktype,int protocol,int backlog,bool one)456 int ATNetworkTool::CreateServerSockets(ATSocketList &sockets, in_port_t port,
457 int &error,
458 bool loopback, bool nonblocking,
459 int family, int socktype, int protocol,
460 int backlog, bool one)
461 {
462 std::stringstream ssport;
463
464 ssport << port;
465 return ATNetworkTool::CreateServerSockets(sockets, ssport.str().c_str(),
466 error,
467 loopback, nonblocking,
468 family, socktype, protocol,
469 backlog, one);
470 }
471
CreateServerSockets(ATSocketList & sockets,const char * port,int & error,bool loopback,bool nonblocking,int family,int socktype,int protocol,int backlog,bool one)472 int ATNetworkTool::CreateServerSockets(ATSocketList &sockets, const char *port,
473 int &error,
474 bool loopback, bool nonblocking,
475 int family, int socktype, int protocol,
476 int backlog, bool one)
477 {
478 struct addrinfo hints, *paddr, *paddrp;
479 int num = 0;
480
481 memset(&hints, 0, sizeof(hints));
482 if (ATNetworkTool::AF_XINETX == family) {
483 hints.ai_family = PF_UNSPEC;
484 } else {
485 hints.ai_family = family;
486 }
487 hints.ai_socktype = socktype;
488 hints.ai_protocol = protocol;
489 #ifdef AI_NUMERICSERV
490 hints.ai_flags |= AI_NUMERICSERV;
491 #endif
492 if (!loopback) {
493 hints.ai_flags |= AI_PASSIVE;
494 }
495 if ((error = getaddrinfo(NULL, port, &hints, &paddrp)) != 0) {
496 return -1;
497 }
498 for (paddr = paddrp; paddr; paddr = paddr->ai_next) {
499 if (ATNetworkTool::AF_XINETX == family) {
500 if (!ATAddress::saIsInet(paddr->ai_addr)) {
501 continue;
502 }
503 }
504
505 int s = ATNetworkTool::CreateServerSocket(paddr, error,
506 nonblocking,
507 backlog);
508 if (s < 0) {
509 continue;
510 }
511 sockets.push_back(s);
512 num++;
513 if (one) {
514 break;
515 }
516 }
517 freeaddrinfo(paddrp);
518 return num;
519 }
520
CreateServerSocket(const struct addrinfo * addr,int & error,bool nonblocking,int backlog)521 int ATNetworkTool::CreateServerSocket(const struct addrinfo *addr, int &error,
522 bool nonblocking, int backlog)
523 {
524 int s = ATNetworkTool::CreateSocket(addr, error);
525 if (s < 0) {
526 return -1;
527 }
528
529 if (nonblocking) {
530 ATNetworkTool::SetNonBlocking(s);
531 }
532
533 if (listen(s, backlog) == -1) {
534 error = errno;
535 ATNetworkTool::CloseSocket(s);
536 return -1;
537 }
538
539 return s;
540 }
541
SetNonBlocking(int s,bool block)542 int ATNetworkTool::SetNonBlocking(int s, bool block)
543 {
544 if (block) {
545 return fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK);
546 } else {
547 return fcntl(s, F_SETFL, fcntl(s, F_GETFL) & ~O_NONBLOCK);
548 }
549 }
550
ConnectToSocket(int sock,int & error,bool loopback,int socktype,int protocol)551 int ATNetworkTool::ConnectToSocket(int sock, int &error, bool loopback,
552 int socktype, int protocol)
553 {
554 struct sockaddr_storage ss;
555 socklen_t addrLen = sizeof(ss);
556 struct sockaddr *sa = (struct sockaddr *)&ss;
557
558 if (getsockname(sock, sa, &addrLen) != 0) {
559 error = errno;
560 return -1;
561 }
562 int s = ATNetworkTool::ConnectSocket(sa, addrLen,
563 error, loopback,
564 sa->sa_family,
565 socktype, protocol);
566 if (s < 0) {
567 return -1;
568 }
569 return s;
570 }
571
Connect(const char * host,in_port_t port,int & error,int family,int socktype,int protocol)572 int ATNetworkTool::Connect(const char *host, in_port_t port,
573 int &error,
574 int family, int socktype, int protocol)
575 {
576 std::stringstream ssport;
577
578 ssport << port;
579
580 return ATNetworkTool::Connect(host, ssport.str().c_str(), error,
581 family, socktype, protocol);
582 }
583
Connect(const char * host,const char * port,int & error,int family,int socktype,int protocol)584 int ATNetworkTool::Connect(const char *host, const char *port,
585 int &error,
586 int family, int socktype, int protocol)
587 {
588 struct addrinfo hints, *paddr, *paddrp;
589 int oks = -1;
590
591 if (socktype != SOCK_DGRAM) {
592 socktype = SOCK_STREAM;
593 }
594
595 memset(&hints, 0, sizeof(hints));
596 if (ATNetworkTool::AF_XINETX == family) {
597 hints.ai_family = PF_UNSPEC;
598 } else {
599 hints.ai_family = family;
600 }
601 hints.ai_socktype = socktype;
602 hints.ai_protocol = protocol;
603 hints.ai_flags = AI_NUMERICHOST;
604 #ifdef AI_NUMERICSERV
605 hints.ai_flags |= AI_NUMERICSERV;
606 #endif
607 if ((error = getaddrinfo(host, port, &hints, &paddrp)) != 0) {
608 memset(&hints, 0, sizeof(hints));
609 if (ATNetworkTool::AF_XINETX == family) {
610 hints.ai_family = PF_UNSPEC;
611 } else {
612 hints.ai_family = family;
613 }
614 hints.ai_socktype = socktype;
615 hints.ai_protocol = protocol;
616 #ifdef AI_NUMERICSERV
617 hints.ai_flags |= AI_NUMERICSERV;
618 #endif
619 if ((error = getaddrinfo(host, port, &hints, &paddrp)) != 0) {
620 return -1;
621 }
622 }
623 for (paddr = paddrp; paddr; paddr = paddr->ai_next) {
624 if (ATNetworkTool::AF_XINETX == family) {
625 if (!ATAddress::saIsInet(paddr->ai_addr)) {
626 continue;
627 }
628 }
629
630 int s = ATNetworkTool::ConnectSocket(paddr, error);
631 if (s < 0) {
632 continue;
633 }
634 oks = s;
635 break;
636 }
637 freeaddrinfo(paddrp);
638 return oks;
639 }
640
ConnectLoopback(in_port_t port,int & error,int family,int socktype,int protocol)641 int ATNetworkTool::ConnectLoopback(in_port_t port,
642 int &error,
643 int family, int socktype, int protocol)
644 {
645 std::stringstream ssport;
646
647 ssport << port;
648
649 return ATNetworkTool::ConnectLoopback(ssport.str().c_str(), error,
650 family, socktype, protocol);
651 }
652
ConnectLoopback(const char * port,int & error,int family,int socktype,int protocol)653 int ATNetworkTool::ConnectLoopback(const char *port,
654 int &error,
655 int family, int socktype, int protocol)
656 {
657 struct addrinfo hints, *paddr, *paddrp;
658 int oks = -1;
659
660 if (socktype != SOCK_DGRAM) {
661 socktype = SOCK_STREAM;
662 }
663
664 memset(&hints, 0, sizeof(hints));
665 if (ATNetworkTool::AF_XINETX == family) {
666 hints.ai_family = PF_UNSPEC;
667 } else {
668 hints.ai_family = family;
669 }
670 hints.ai_socktype = socktype;
671 hints.ai_protocol = protocol;
672 #ifdef AI_NUMERICSERV
673 hints.ai_flags |= AI_NUMERICSERV;
674 #endif
675 if ((error = getaddrinfo(NULL, port, &hints, &paddrp)) != 0) {
676 return -1;
677 }
678 for (paddr = paddrp; paddr; paddr = paddr->ai_next) {
679 if (ATNetworkTool::AF_XINETX == family) {
680 if (!ATAddress::saIsInet(paddr->ai_addr)) {
681 continue;
682 }
683 }
684
685 int s = ATNetworkTool::ConnectSocket(paddr, error, true);
686 if (s < 0) {
687 continue;
688 }
689 oks = s;
690 break;
691 }
692 freeaddrinfo(paddrp);
693 return oks;
694 }
695
GetLocalPort(int sock)696 unsigned int ATNetworkTool::GetLocalPort(int sock)
697 {
698 struct sockaddr_storage ss;
699 socklen_t addrLen = sizeof(ss);
700 struct sockaddr *sa = (struct sockaddr *)&ss;
701
702 if (getsockname(sock, sa, &addrLen) != 0) {
703 return 0;
704 }
705 switch (sa->sa_family) {
706 case AF_INET6:
707 return ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
708 break;
709 case AF_INET:
710 return ntohs(((struct sockaddr_in *)sa)->sin_port);
711 break;
712 }
713 return 0;
714 }
715
Accept(int s,ATAddress & address,int & error,bool nonblocking)716 int ATNetworkTool::Accept(int s, ATAddress &address,
717 int &error, bool nonblocking)
718 {
719 struct sockaddr_storage saddr;
720 socklen_t addrLen = sizeof(saddr);
721 struct sockaddr *addr = (struct sockaddr *)&saddr;
722
723 int s_new = accept(s, addr, &addrLen);
724 if (s_new == -1) {
725 error = errno;
726 return -1;
727 }
728
729 address = addr;
730
731 ATNetworkTool::SetNonBlocking(s_new, nonblocking);
732
733 return s_new;
734 }
735
736