Line data Source code
1 : /*
2 : Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
3 :
4 : This file is part of libzmq, the ZeroMQ core engine in C++.
5 :
6 : libzmq is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU Lesser General Public License (LGPL) as published
8 : by the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : As a special exception, the Contributors give you permission to link
12 : this library with independent modules to produce an executable,
13 : regardless of the license terms of these independent modules, and to
14 : copy and distribute the resulting executable under terms of your choice,
15 : provided that you also meet, for each linked independent module, the
16 : terms and conditions of the license of that module. An independent
17 : module is a module which is not derived from or based on this library.
18 : If you modify this library, you must extend this exception to your
19 : version of the library.
20 :
21 : libzmq is distributed in the hope that it will be useful, but WITHOUT
22 : ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
24 : License for more details.
25 :
26 : You should have received a copy of the GNU Lesser General Public License
27 : along with this program. If not, see <http://www.gnu.org/licenses/>.
28 : */
29 :
30 : #include "precompiled.hpp"
31 : #include "ip.hpp"
32 : #include "err.hpp"
33 : #include "platform.hpp"
34 :
35 : #if defined ZMQ_HAVE_WINDOWS
36 : #include "windows.hpp"
37 : #else
38 : #include <fcntl.h>
39 : #include <sys/types.h>
40 : #include <sys/socket.h>
41 : #include <netdb.h>
42 : #include <netinet/in.h>
43 : #include <netinet/tcp.h>
44 : #endif
45 :
46 : #if defined ZMQ_HAVE_OPENVMS
47 : #include <ioctl.h>
48 : #endif
49 :
50 4182 : zmq::fd_t zmq::open_socket (int domain_, int type_, int protocol_)
51 : {
52 : // Setting this option result in sane behaviour when exec() functions
53 : // are used. Old sockets are closed and don't block TCP ports etc.
54 : #if defined ZMQ_HAVE_SOCK_CLOEXEC
55 4182 : type_ |= SOCK_CLOEXEC;
56 : #endif
57 :
58 4182 : fd_t s = socket (domain_, type_, protocol_);
59 : #ifdef ZMQ_HAVE_WINDOWS
60 : if (s == INVALID_SOCKET)
61 : return INVALID_SOCKET;
62 : #else
63 4182 : if (s == -1)
64 : return -1;
65 : #endif
66 :
67 : // If there's no SOCK_CLOEXEC, let's try the second best option. Note that
68 : // race condition can cause socket not to be closed (if fork happens
69 : // between socket creation and this point).
70 : #if !defined ZMQ_HAVE_SOCK_CLOEXEC && defined FD_CLOEXEC
71 : int rc = fcntl (s, F_SETFD, FD_CLOEXEC);
72 : errno_assert (rc != -1);
73 : #endif
74 :
75 : // On Windows, preventing sockets to be inherited by child processes.
76 : #if defined ZMQ_HAVE_WINDOWS && defined HANDLE_FLAG_INHERIT
77 : BOOL brc = SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0);
78 : win_assert (brc);
79 : #endif
80 :
81 4182 : return s;
82 : }
83 :
84 35783 : void zmq::unblock_socket (fd_t s_)
85 : {
86 : #if defined ZMQ_HAVE_WINDOWS
87 : u_long nonblock = 1;
88 : int rc = ioctlsocket (s_, FIONBIO, &nonblock);
89 : wsa_assert (rc != SOCKET_ERROR);
90 : #elif defined ZMQ_HAVE_OPENVMS
91 : int nonblock = 1;
92 : int rc = ioctl (s_, FIONBIO, &nonblock);
93 : errno_assert (rc != -1);
94 : #else
95 35783 : int flags = fcntl (s_, F_GETFL, 0);
96 35782 : if (flags == -1)
97 0 : flags = 0;
98 35782 : int rc = fcntl (s_, F_SETFL, flags | O_NONBLOCK);
99 35784 : errno_assert (rc != -1);
100 : #endif
101 35784 : }
102 :
103 30 : void zmq::enable_ipv4_mapping (fd_t s_)
104 : {
105 : (void) s_;
106 :
107 : #ifdef IPV6_V6ONLY
108 : #ifdef ZMQ_HAVE_WINDOWS
109 : DWORD flag = 0;
110 : #else
111 30 : int flag = 0;
112 : #endif
113 : int rc = setsockopt (s_, IPPROTO_IPV6, IPV6_V6ONLY, (const char*) &flag,
114 30 : sizeof (flag));
115 : #ifdef ZMQ_HAVE_WINDOWS
116 : wsa_assert (rc != SOCKET_ERROR);
117 : #else
118 30 : errno_assert (rc == 0);
119 : #endif
120 : #endif
121 30 : }
122 :
123 6761 : int zmq::get_peer_ip_address (fd_t sockfd_, std::string &ip_addr_)
124 : {
125 : int rc;
126 : struct sockaddr_storage ss;
127 :
128 : #if defined ZMQ_HAVE_HPUX || defined ZMQ_HAVE_WINDOWS
129 : int addrlen = static_cast <int> (sizeof ss);
130 : #else
131 6761 : socklen_t addrlen = sizeof ss;
132 : #endif
133 6761 : rc = getpeername (sockfd_, (struct sockaddr*) &ss, &addrlen);
134 : #ifdef ZMQ_HAVE_WINDOWS
135 : if (rc == SOCKET_ERROR) {
136 : const int last_error = WSAGetLastError();
137 : wsa_assert (last_error != WSANOTINITIALISED &&
138 : last_error != WSAEFAULT &&
139 : last_error != WSAEINPROGRESS &&
140 : last_error != WSAENOTSOCK);
141 : return 0;
142 : }
143 : #else
144 6762 : if (rc == -1) {
145 0 : errno_assert (errno != EBADF &&
146 : errno != EFAULT &&
147 : errno != ENOTSOCK);
148 : return 0;
149 : }
150 : #endif
151 :
152 : char host [NI_MAXHOST];
153 : rc = getnameinfo ((struct sockaddr*) &ss, addrlen, host, sizeof host,
154 6762 : NULL, 0, NI_NUMERICHOST);
155 6761 : if (rc != 0)
156 : return 0;
157 :
158 : ip_addr_ = host;
159 :
160 : union {
161 : struct sockaddr sa;
162 : struct sockaddr_storage sa_stor;
163 : } u;
164 :
165 6761 : u.sa_stor = ss;
166 6761 : return (int) u.sa.sa_family;
167 : }
168 :
169 12 : void zmq::set_ip_type_of_service (fd_t s_, int iptos)
170 : {
171 12 : int rc = setsockopt(s_, IPPROTO_IP, IP_TOS, reinterpret_cast<const char*>(&iptos), sizeof(iptos));
172 :
173 : #ifdef ZMQ_HAVE_WINDOWS
174 : wsa_assert (rc != SOCKET_ERROR);
175 : #else
176 12 : errno_assert (rc == 0);
177 : #endif
178 12 : }
|