libzmq  master
ZeroMQ C++ Core Engine (LIBZMQ)
ip.cpp
Go to the documentation of this file.
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 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  type_ |= SOCK_CLOEXEC;
56 #endif
57 
58  fd_t s = socket (domain_, type_, protocol_);
59 #ifdef ZMQ_HAVE_WINDOWS
60  if (s == INVALID_SOCKET)
61  return INVALID_SOCKET;
62 #else
63  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  return s;
82 }
83 
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  int flags = fcntl (s_, F_GETFL, 0);
96  if (flags == -1)
97  flags = 0;
98  int rc = fcntl (s_, F_SETFL, flags | O_NONBLOCK);
99  errno_assert (rc != -1);
100 #endif
101 }
102 
104 {
105  (void) s_;
106 
107 #ifdef IPV6_V6ONLY
108 #ifdef ZMQ_HAVE_WINDOWS
109  DWORD flag = 0;
110 #else
111  int flag = 0;
112 #endif
113  int rc = setsockopt (s_, IPPROTO_IPV6, IPV6_V6ONLY, (const char*) &flag,
114  sizeof (flag));
115 #ifdef ZMQ_HAVE_WINDOWS
116  wsa_assert (rc != SOCKET_ERROR);
117 #else
118  errno_assert (rc == 0);
119 #endif
120 #endif
121 }
122 
123 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  socklen_t addrlen = sizeof ss;
132 #endif
133  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  if (rc == -1) {
145  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  NULL, 0, NI_NUMERICHOST);
155  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  u.sa_stor = ss;
166  return (int) u.sa.sa_family;
167 }
168 
169 void zmq::set_ip_type_of_service (fd_t s_, int iptos)
170 {
171  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  errno_assert (rc == 0);
177 #endif
178 }
int fd_t
Definition: fd.hpp:50
fd_t open_socket(int domain_, int type_, int protocol_)
Definition: ip.cpp:50
void unblock_socket(fd_t s_)
Definition: ip.cpp:84
#define ENOTSOCK
Definition: zmq.h:136
int get_peer_ip_address(fd_t sockfd_, std::string &ip_addr_)
Definition: ip.cpp:123
void enable_ipv4_mapping(fd_t s_)
Definition: ip.cpp:103
#define errno_assert(x)
Definition: err.hpp:129
void set_ip_type_of_service(fd_t s_, int iptos)
Definition: ip.cpp:169