1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtNetwork module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #ifndef QNET_UNIX_P_H
41 #define QNET_UNIX_P_H
42 
43 //
44 //  W A R N I N G
45 //  -------------
46 //
47 // This file is not part of the Qt API.  It exists for the convenience
48 // of Qt code on Unix. This header file may change from version to
49 // version to version without notice, or even be removed.
50 //
51 // We mean it.
52 //
53 
54 #include <QtNetwork/private/qtnetworkglobal_p.h>
55 #include "private/qcore_unix_p.h"
56 
57 #include <sys/types.h>
58 #include <sys/socket.h>
59 #include <netinet/in.h>
60 
61 #if defined(Q_OS_VXWORKS)
62 #  include <sockLib.h>
63 #endif
64 
65 // for inet_addr
66 #include <netdb.h>
67 #include <arpa/inet.h>
68 #if defined(Q_OS_VXWORKS)
69 #  include <hostLib.h>
70 #else
71 #  include <resolv.h>
72 #endif
73 
74 QT_BEGIN_NAMESPACE
75 
76 // Almost always the same. If not, specify in qplatformdefs.h.
77 #if !defined(QT_SOCKOPTLEN_T)
78 # define QT_SOCKOPTLEN_T QT_SOCKLEN_T
79 #endif
80 
81 static inline int qt_safe_socket(int domain, int type, int protocol, int flags = 0)
82 {
83     Q_ASSERT((flags & ~O_NONBLOCK) == 0);
84 
85     int fd;
86 #ifdef QT_THREADSAFE_CLOEXEC
87     int newtype = type | SOCK_CLOEXEC;
88     if (flags & O_NONBLOCK)
89         newtype |= SOCK_NONBLOCK;
90     fd = ::socket(domain, newtype, protocol);
91     return fd;
92 #else
93     fd = ::socket(domain, type, protocol);
94     if (fd == -1)
95         return -1;
96 
97     ::fcntl(fd, F_SETFD, FD_CLOEXEC);
98 
99     // set non-block too?
100     if (flags & O_NONBLOCK)
101         ::fcntl(fd, F_SETFL, ::fcntl(fd, F_GETFL) | O_NONBLOCK);
102 
103     return fd;
104 #endif
105 }
106 
107 static inline int qt_safe_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *addrlen, int flags = 0)
108 {
109     Q_ASSERT((flags & ~O_NONBLOCK) == 0);
110 
111     int fd;
112 #ifdef QT_THREADSAFE_CLOEXEC
113     // use accept4
114     int sockflags = SOCK_CLOEXEC;
115     if (flags & O_NONBLOCK)
116         sockflags |= SOCK_NONBLOCK;
117 # if defined(Q_OS_NETBSD)
118     fd = ::paccept(s, addr, static_cast<QT_SOCKLEN_T *>(addrlen), NULL, sockflags);
119 # else
120     fd = ::accept4(s, addr, static_cast<QT_SOCKLEN_T *>(addrlen), sockflags);
121 # endif
122     return fd;
123 #else
124     fd = ::accept(s, addr, static_cast<QT_SOCKLEN_T *>(addrlen));
125     if (fd == -1)
126         return -1;
127 
128     ::fcntl(fd, F_SETFD, FD_CLOEXEC);
129 
130     // set non-block too?
131     if (flags & O_NONBLOCK)
132         ::fcntl(fd, F_SETFL, ::fcntl(fd, F_GETFL) | O_NONBLOCK);
133 
134     return fd;
135 #endif
136 }
137 
qt_safe_listen(int s,int backlog)138 static inline int qt_safe_listen(int s, int backlog)
139 {
140     return ::listen(s, backlog);
141 }
142 
qt_safe_connect(int sockfd,const struct sockaddr * addr,QT_SOCKLEN_T addrlen)143 static inline int qt_safe_connect(int sockfd, const struct sockaddr *addr, QT_SOCKLEN_T addrlen)
144 {
145     int ret;
146     // Solaris e.g. expects a non-const 2nd parameter
147     EINTR_LOOP(ret, QT_SOCKET_CONNECT(sockfd, const_cast<struct sockaddr *>(addr), addrlen));
148     return ret;
149 }
150 #undef QT_SOCKET_CONNECT
151 #define QT_SOCKET_CONNECT qt_safe_connect
152 
153 #if defined(socket)
154 # undef socket
155 #endif
156 #if defined(accept)
157 # undef accept
158 #endif
159 #if defined(listen)
160 # undef listen
161 #endif
162 
163 // VxWorks' headers specify 'int' instead of '...' for the 3rd ioctl() parameter.
164 template <typename T>
qt_safe_ioctl(int sockfd,unsigned long request,T arg)165 static inline int qt_safe_ioctl(int sockfd, unsigned long request, T arg)
166 {
167 #ifdef Q_OS_VXWORKS
168     return ::ioctl(sockfd, request, (int) arg);
169 #else
170     return ::ioctl(sockfd, request, arg);
171 #endif
172 }
173 
qt_safe_sendmsg(int sockfd,const struct msghdr * msg,int flags)174 static inline int qt_safe_sendmsg(int sockfd, const struct msghdr *msg, int flags)
175 {
176 #ifdef MSG_NOSIGNAL
177     flags |= MSG_NOSIGNAL;
178 #else
179     qt_ignore_sigpipe();
180 #endif
181 
182     int ret;
183     EINTR_LOOP(ret, ::sendmsg(sockfd, msg, flags));
184     return ret;
185 }
186 
qt_safe_recvmsg(int sockfd,struct msghdr * msg,int flags)187 static inline int qt_safe_recvmsg(int sockfd, struct msghdr *msg, int flags)
188 {
189     int ret;
190 
191     EINTR_LOOP(ret, ::recvmsg(sockfd, msg, flags));
192     return ret;
193 }
194 
195 QT_END_NAMESPACE
196 
197 #endif // QNET_UNIX_P_H
198